PlatSim_Genova/LAZY_INITIALIZATION_GUIDE.md
2026-02-02 09:43:12 +01:00

215 lines
7.4 KiB
Markdown

# Modifica Lazy Initialization per theGrifo1553
## Problema Originale
Prima della modifica, `theGrifo1553` veniva istanziato immediatamente all'import del modulo `leo_grifo_1553`:
```python
# VECCHIO CODICE (problematico)
theGrifo1553 = GrifoInstrumentInterface(0.2)
```
**Conseguenze:**
- La connessione hardware 1553 avveniva all'import, anche in modalità `--simulate`
- Il mock doveva sostituire `sys.modules` PRIMA che il test importasse i moduli
- Impossibile importare lo script senza hardware disponibile
- Fallimento import se `PlatformSimulator/bin` non nel path
## Soluzione Implementata
Introdotto un **lazy proxy** (`_LazyGrifoProxy`) che ritarda la creazione dell'istanza reale fino al primo utilizzo:
```python
# NUOVO CODICE (lazy)
class _LazyGrifoProxy:
"""Proxy that lazily constructs GrifoInstrumentInterface on first use."""
def __init__(self, timeout: float = 0.2):
self._timeout = timeout
self._instance = None
def _ensure(self):
"""Initialize only when needed."""
if self._instance is None:
self._instance = GrifoInstrumentInterface(self._timeout)
def __getattr__(self, item):
"""Delegate to real instance after ensuring it exists."""
# Support hasattr() without initialization for known methods
known_methods = ['check', 'get', 'set', 'getInterface', 'run']
if item in known_methods and self._instance is None:
def lazy_method(*args, **kwargs):
self._ensure()
return getattr(self._instance, item)(*args, **kwargs)
return lazy_method
self._ensure()
return getattr(self._instance, item)
theGrifo1553 = _LazyGrifoProxy(0.2)
```
## Vantaggi
### 1. Compatibilità Totale con Modalità Simulazione
- ✅ Il mock può sostituire `sys.modules['leo_grifo_1553']` DOPO l'import iniziale
- ✅ Nessuna connessione hardware tentata finché non si usa `--simulate`
- ✅ Import sicuro anche senza `PlatformSimulator/bin` nel path
### 2. Compatibilità Totale con Target Reale
- ✅ Primo accesso a metodo/attributo → istanza reale creata automaticamente
- ✅ API identica: `check()`, `get()`, `set()`, `getInterface()`, `run()`
- ✅ Passaggio come parametro funziona: `check(theGrifo1553, ...)`
-`hasattr()` supportato: il mock usa `hasattr()` per controlli
### 3. Trasparenza Totale
Il proxy è completamente trasparente per il codice esistente:
- Non richiede modifiche a `GRIFO_M_PBIT.py`
- Non richiede modifiche a `test_common_function.py`
- Non richiede modifiche a `GRIFO_M_PBIT_mock.py`
## Verifica sul Target Reale
### Test 1: Verifica Import Lazy
Esegui lo script di test per verificare che il proxy funzioni:
```powershell
cd TestEnvironment\scripts
python test_lazy_proxy.py
```
**Output atteso:**
```
✓ Proxy is lazy - real instance not yet created
✓ hasattr() checks pass without initialization
✓ Mock replacement works correctly
ALL TESTS PASSED ✓
```
### Test 2: Esecuzione sul Target Reale (Senza --simulate)
**Pre-requisiti:**
- Hardware 1553 connesso e funzionante
- `PlatformSimulator/bin` nel PYTHONPATH o ambiente configurato
- Modulo `interpreter` disponibile e funzionante
**Comando:**
```powershell
cd TestEnvironment\scripts
python GRIFO_M_PBIT.py
```
**Comportamento atteso:**
1. Import dello script: **SUCCESSO** (nessuna connessione hardware ancora)
2. Chiamata a `theGrifo1553.getInterface()` in `test_proc()`: **Qui avviene la connessione**
3. Prima chiamata `check(theGrifo1553, ...)`: proxy delega all'istanza reale
4. Test procede normalmente come prima della modifica
**Verifica connessione lazy:**
Aggiungi temporaneamente log all'inizio di `test_proc()`:
```python
def test_proc():
import logging
logging.info(f"theGrifo1553 prima dell'uso: {repr(theGrifo1553)}")
interface = theGrifo1553.getInterface() # <- QUI avviene la connessione
logging.info(f"theGrifo1553 dopo getInterface(): {repr(theGrifo1553)}")
```
**Output atteso nel log:**
```
theGrifo1553 prima dell'uso: <LazyGrifoProxy(uninitialized, timeout=0.2)>
theGrifo1553 dopo getInterface(): <leo_grifo_1553.GrifoInstrumentInterface object at 0x...>
```
### Test 3: Esecuzione in Simulazione (Con --simulate)
**Comando:**
```powershell
python GRIFO_M_PBIT.py --simulate
```
**Comportamento atteso:**
1. Import dello script: **SUCCESSO**
2. Rilevamento flag `--simulate`: import di `GRIFO_M_PBIT_mock`
3. Mock sostituisce `sys.modules['leo_grifo_1553']` con modulo fake
4. Proxy originale **NON viene mai inizializzato** (nessuna connessione hardware)
5. Tutte le chiamate vanno al mock, test procede in simulazione
## Compatibilità Verificata
**Modulo leo_grifo_1553.py**
- Import sicuro anche senza hardware
- Lazy initialization funzionante
- API identica per codice esistente
**Script GRIFO_M_PBIT.py**
- Nessuna modifica necessaria
- Funziona con e senza `--simulate`
- Check/get/set funzionano identicamente
**Mock GRIFO_M_PBIT_mock.py**
- Sostituisce `sys.modules` correttamente
- `hasattr()` checks funzionano
- Nessuna inizializzazione hardware in simulate
**Helper test_common_function.py**
- `check(theGrifo1553, ...)` funziona
- Passaggio proxy come parametro OK
- Nessuna modifica necessaria
## Risoluzione Problemi
### Problema: "AttributeError: 'GrifoInstrumentInterface' object has no attribute 'xyz'"
**Causa:** Metodo/attributo non esiste nell'interfaccia reale.
**Soluzione:** Verifica nome metodo corretto. I metodi supportati dal proxy sono:
- `check(expected, msg, field, **kwargs)`
- `get(msg, field, **kwargs)`
- `set(value, msg, field, **kwargs)`
- `getInterface()` → ritorna oggetto `grifo_1553` nativo
- `run(enable: bool)`
### Problema: "ImportError: No module named 'interpreter'"
**Causa:** Ambiente non configurato per hardware reale.
**Soluzione:** Esegui con uno di questi metodi:
1. **Wrapper Python:** `python python_simulate_wrapper.py` (solo simulate)
2. **Batch Production:** Usa `run.bat` o configura PYTHONPATH manualmente
3. **Modalità Simulate:** Aggiungi flag `--simulate` (non richiede interpreter)
### Problema: "Connessione hardware avviene all'import"
**Causa:** Il proxy potrebbe non essere stato applicato correttamente.
**Soluzione:**
1. Verifica che `leo_grifo_1553.py` contenga `_LazyGrifoProxy`
2. Verifica che `theGrifo1553 = _LazyGrifoProxy(0.2)` sia l'ultima riga del file
3. Esegui `test_lazy_proxy.py` per verificare il comportamento
## File Modificati
- `TestEnvironment/env/leo_grifo_1553.py` - Aggiunto `_LazyGrifoProxy` (linee ~140-190)
- `TestEnvironment/scripts/test_lazy_proxy.py` - Script di test nuovo (creato)
## File NON Modificati (compatibilità preservata)
- `TestEnvironment/scripts/GRIFO_M_PBIT.py` - Nessuna modifica necessaria
- `TestEnvironment/scripts/GRIFO_M_PBIT_mock.py` - Nessuna modifica necessaria
- `TestEnvironment/env/test_common_function.py` - Nessuna modifica necessaria
- `TestEnvironment/env/leo_grifo_common.py` - Nessuna modifica necessaria
## Conclusioni
La modifica garantisce:
-**100% compatibilità con codice esistente** (nessuna modifica ai test)
-**Target reale funziona identicamente** (connessione lazy al primo uso)
-**Simulazione funziona correttamente** (mock sostituisce prima dell'init)
-**Import sicuro** (no hardware all'import)
-**Trasparenza totale** (API identica per utente finale)
Puoi eseguire sul target reale con sicurezza: il comportamento è identico, solo la temporizzazione della connessione hardware è cambiata (da import-time a first-use-time).