Files
py-dvt-ate/src/py_dvt_ate/instruments/scpi.py
Kai Chappell 5d15dfd7d0 Add SCPI parser tests
Comprehensive test suite for SCPI command parsing:
- SCPICommand dataclass tests (creation, keyword property)
- Parser tests for queries, commands, arguments
- IEEE 488.2 common command tests (*IDN?, *RST, etc.)
- Edge cases (whitespace, empty strings)
- Instrument-specific command tests

Also fixed bug where is_query was determined from command string
ending rather than header ending (handles queries with arguments).
2025-04-21 13:10:50 +00:00

88 lines
2.6 KiB
Python

"""SCPI command parsing.
This module provides SCPI (Standard Commands for Programmable Instruments)
command parsing for instrument communication. It handles IEEE 488.2 common
commands (*IDN?, *RST, etc.) and instrument-specific commands.
"""
from dataclasses import dataclass
@dataclass
class SCPICommand:
"""Parsed SCPI command.
Attributes:
header: The command header (e.g., "TEMP:SETPOINT" or "*IDN").
arguments: List of command arguments (e.g., ["85.0"]).
is_query: True if the command ends with '?' (query command).
"""
header: str
arguments: list[str]
is_query: bool
@property
def keyword(self) -> str:
"""Return the command keyword without '?'.
For query commands like "TEMP:SETPOINT?", returns "TEMP:SETPOINT".
For regular commands like "VOLT", returns "VOLT".
"""
return self.header.rstrip("?")
class SCPIParser:
"""Parse SCPI command strings.
Handles both IEEE 488.2 common commands (e.g., *IDN?, *RST) and
instrument-specific commands (e.g., VOLT 3.3, TEMP:SETPOINT?).
Examples:
>>> parser = SCPIParser()
>>> cmd = parser.parse("*IDN?")
>>> cmd.header, cmd.is_query
('*IDN?', True)
>>> cmd = parser.parse("VOLT 3.3")
>>> cmd.header, cmd.arguments
('VOLT', ['3.3'])
"""
def parse(self, command_string: str) -> SCPICommand:
"""Parse a SCPI command string.
Args:
command_string: The raw SCPI command string to parse.
Returns:
SCPICommand with parsed header, arguments, and query flag.
Examples:
"*IDN?" -> SCPICommand("*IDN?", [], True)
"VOLT 3.3" -> SCPICommand("VOLT", ["3.3"], False)
"TEMP:SETPOINT?" -> SCPICommand("TEMP:SETPOINT?", [], True)
"CONF:VOLT:DC 10,0.001" -> SCPICommand("CONF:VOLT:DC", ["10", "0.001"], False)
"""
command_string = command_string.strip()
if not command_string:
return SCPICommand(header="", arguments=[], is_query=False)
# Split into header and arguments on first whitespace
parts = command_string.split(None, 1)
header = parts[0]
arguments: list[str] = []
if len(parts) > 1:
# Parse comma-separated arguments
arg_string = parts[1]
arguments = [arg.strip() for arg in arg_string.split(",")]
# Query is determined by whether the header ends with '?'
is_query = header.endswith("?")
return SCPICommand(
header=header,
arguments=arguments,
is_query=is_query,
)