"""Base transport interface for instrument communication.""" from abc import ABC, abstractmethod class Transport(ABC): """Abstract transport interface for instrument communication. This abstract base class defines the interface that all transport implementations (TCP, VISA, etc.) must implement. It provides basic connection management and communication primitives for SCPI-based instruments. Implementations must inherit from this class and implement all abstract methods. """ @abstractmethod def connect(self) -> None: """Establish connection to instrument. Raises: ConnectionError: If connection fails. """ pass @abstractmethod def disconnect(self) -> None: """Close connection to instrument. Should be idempotent - safe to call multiple times. """ pass @abstractmethod def write(self, command: str) -> None: """Send command to instrument. Args: command: SCPI command string to send (without terminator). Raises: ConnectionError: If not connected. IOError: If write fails. """ pass @abstractmethod def read(self, timeout: float | None = None) -> str: """Read response from instrument. Args: timeout: Read timeout in seconds. None uses default. Returns: Response string from instrument (without terminator). Raises: ConnectionError: If not connected. TimeoutError: If read times out. IOError: If read fails. """ pass @abstractmethod def query(self, command: str, timeout: float | None = None) -> str: """Send command and read response. Convenience method combining write() and read(). Args: command: SCPI command string to send. timeout: Read timeout in seconds. None uses default. Returns: Response string from instrument. Raises: ConnectionError: If not connected. TimeoutError: If read times out. IOError: If communication fails. """ pass @property @abstractmethod def is_connected(self) -> bool: """Check if connection is active. Returns: True if connected, False otherwise. """ pass