diff --git a/examples/check_chassis_battery.py b/examples/check_chassis_battery.py index 5ea26c8..d89a8f6 100644 --- a/examples/check_chassis_battery.py +++ b/examples/check_chassis_battery.py @@ -22,30 +22,25 @@ def main(chassis_name: str) -> None: """ # noqa: D301 try: physical_channel_names = f"{chassis_name}/BatteryVoltageSensor" - connection_timeout = 10.0 reservation_access = ReservationAccess.READ_ONLY reservation_group = "admin" - reservation_timeout = 10.0 with Session.initialize_session_with_physical_channels( - None, physical_channel_names=physical_channel_names, - connection_timeout=connection_timeout, reservation_access=reservation_access, reservation_group=reservation_group, - reservation_timeout=reservation_timeout, ) as session: sensor_lower_critical = session.get_physical_channel_property_double( - physical_channel_names=physical_channel_names, property_name="SensorLowerCritical", + physical_channel_names=physical_channel_names, ) sensor_reading = session.get_physical_channel_property_double( - physical_channel_names=physical_channel_names, property_name="SensorReading", + physical_channel_names=physical_channel_names, ) health_state = session.get_physical_channel_property_string( - physical_channel_names=physical_channel_names, property_name="HealthState", + physical_channel_names=physical_channel_names, ) needs_replacement = sensor_reading < sensor_lower_critical diff --git a/examples/reset_device.py b/examples/reset_device.py index f62180f..cdc46f1 100644 --- a/examples/reset_device.py +++ b/examples/reset_device.py @@ -22,18 +22,13 @@ def main(device_names: str) -> None: reset_device SLSC-12001-XXXXXXXX-Mod1,SLSC-12001-XXXXXXXX-Mod2 """ # noqa: D301 try: - connection_timeout = 10.0 reservation_access = ReservationAccess.READ_ONLY reservation_group = "admin" - reservation_timeout = 10.0 with Session.initialize_session_with_devices( - None, device_names=device_names, - connection_timeout=connection_timeout, reservation_access=reservation_access, reservation_group=reservation_group, - reservation_timeout=reservation_timeout, ) as session: session.reset_devices(device_names) print(f"Reset command sent to device(s) {device_names}") diff --git a/examples/show_command_and_property_tree.py b/examples/show_command_and_property_tree.py index 63b86a6..2750c9a 100644 --- a/examples/show_command_and_property_tree.py +++ b/examples/show_command_and_property_tree.py @@ -49,18 +49,13 @@ def get_command_and_property_tree(device_name: str) -> dict: Returns: Dictionary containing the command and property tree of the device. """ - connection_timeout = 10.0 reservation_access = ReservationAccess.READ_ONLY reservation_group = "admin" - reservation_timeout = 10.0 with Session.initialize_session_with_devices( - None, - device_name, - connection_timeout, - reservation_access, - reservation_group, - reservation_timeout, + device_names=device_name, + reservation_access=reservation_access, + reservation_group=reservation_group, ) as session: data = { diff --git a/generated/nislsc/constants.py b/generated/nislsc/constants.py index b2875c3..a76c0ae 100644 --- a/generated/nislsc/constants.py +++ b/generated/nislsc/constants.py @@ -15,6 +15,26 @@ class StrEnum(str, Enum): """StrEnum fallback for Python versions < 3.11.""" +CONNECTED_DEVICES_ALIAS = "$ConnectedDevices" +"""A resource alias representing the session's connected devices.""" + +DEFAULT_DEVICES_ALIAS = "$DefaultDevices" +"""A resource alias representing the session's default devices.""" + +DEFAULT_NVMEM_AREAS_ALIAS = "$DefaultNVMEMAreas" +"""A resource alias representing the session's default NVMEM areas.""" + +DEFAULT_PHYS_CHANS_ALIAS = "$DefaultPhysChans" +"""A resource alias representing the session's default physical channels.""" + +RESERVED_DEVICES_ALIAS = "$ReservedDevices" +"""A resource alias representing the session's reserved devices.""" + +SESSION_ALIAS = "$Session" +"""A resource alias for accessing session properties.""" + +SYSTEM_ALIAS = "$System" +"""A resource alias for accessing system properties.""" class ReservationAccess(Enum): """Define SLSC reservation access modes.""" diff --git a/generated/nislsc/session.py b/generated/nislsc/session.py index c6b153b..88ef578 100644 --- a/generated/nislsc/session.py +++ b/generated/nislsc/session.py @@ -67,7 +67,7 @@ def close(self) -> None: self._owns_library = False @classmethod - def initialize_session_with_devices(cls, library: Library | None, device_names: str, connection_timeout: float, reservation_access: ReservationAccess, reservation_group: str, reservation_timeout: float) -> Self: + def initialize_session_with_devices(cls, device_names: str, library: Library | None = None, connection_timeout: float = -1.0, reservation_access: ReservationAccess = ReservationAccess.READ_WRITE, reservation_group: str = '', reservation_timeout: float = -1.0) -> Self: """Initialize an SLSC session with one or multiple devices. The session opens network connections for devices. If reservationAccess @@ -110,7 +110,7 @@ def initialize_session_with_devices(cls, library: Library | None, device_names: return cls(library, session_handle, owns_library) @classmethod - def initialize_session_with_nvmem_areas(cls, library: Library | None, nvmem_area_names: str, connection_timeout: float, reservation_access: ReservationAccess, reservation_group: str, reservation_timeout: float) -> Self: + def initialize_session_with_nvmem_areas(cls, nvmem_area_names: str, library: Library | None = None, connection_timeout: float = -1.0, reservation_access: ReservationAccess = ReservationAccess.READ_WRITE, reservation_group: str = '', reservation_timeout: float = -1.0) -> Self: """Initialize an SLSC session with one or multiple NVMEM areas. The session opens network connections for NVMEM areas. If @@ -155,7 +155,7 @@ def initialize_session_with_nvmem_areas(cls, library: Library | None, nvmem_area return cls(library, session_handle, owns_library) @classmethod - def initialize_session_with_physical_channels(cls, library: Library | None, physical_channel_names: str, connection_timeout: float, reservation_access: ReservationAccess, reservation_group: str, reservation_timeout: float) -> Self: + def initialize_session_with_physical_channels(cls, physical_channel_names: str, library: Library | None = None, connection_timeout: float = -1.0, reservation_access: ReservationAccess = ReservationAccess.READ_WRITE, reservation_group: str = '', reservation_timeout: float = -1.0) -> Self: """Initialize an SLSC session with one or multiple physical channels. The session opens network connections for devices that correspond to the @@ -203,7 +203,7 @@ def initialize_session_with_physical_channels(cls, library: Library | None, phys return cls(library, session_handle, owns_library) @classmethod - def initialize_session_without_resources(cls, library: Library | None) -> Self: + def initialize_session_without_resources(cls, library: Library | None = None) -> Self: """Initialize an SLSC session without specifying any resources or opening any network connections. @@ -239,7 +239,7 @@ def abort_session(self) -> None: """ self._interpreter.abort_session(self._session_handle) - def log_in(self, chassis_name: str, username: str, password: str, connection_timeout: float, save_credentials_to_disk: bool) -> None: + def log_in(self, chassis_name: str, username: str, password: str, save_credentials_to_disk: bool, connection_timeout: float = -1.0) -> None: """Attempt to connect and log in to the specified SLSC chassis. If successful, the username and password are cached on the local system @@ -297,7 +297,7 @@ def log_out(self, chassis_name: str) -> None: """ self._interpreter.log_out(self._session_handle, chassis_name) - def connect_to_devices(self, device_names: str, connection_timeout: float) -> None: + def connect_to_devices(self, device_names: str = '$DefaultDevices', connection_timeout: float = -1.0) -> None: """Open network connections for the specified device(s), sharing connections to the same SLSC chassis. @@ -318,7 +318,7 @@ def connect_to_devices(self, device_names: str, connection_timeout: float) -> No """ self._interpreter.connect_to_devices(self._session_handle, device_names, connection_timeout) - def disconnect_from_devices(self, device_names: str) -> None: + def disconnect_from_devices(self, device_names: str = '$DefaultDevices') -> None: """Close network connections for the specified devices. When multiple devices share a network connection because they are in the @@ -332,7 +332,7 @@ def disconnect_from_devices(self, device_names: str) -> None: """ self._interpreter.disconnect_from_devices(self._session_handle, device_names) - def connect_to_chassis_by_address(self, address: str, username: str, password: str, connection_timeout: float) -> str: + def connect_to_chassis_by_address(self, address: str, username: str, password: str, connection_timeout: float = -1.0) -> str: """Open a network connection for a chassis by the specified IP address or hostname. @@ -353,7 +353,7 @@ def connect_to_chassis_by_address(self, address: str, username: str, password: s chassis_name = self._interpreter.connect_to_chassis_by_address(self._session_handle, address, username, password, connection_timeout) return chassis_name - def reserve_devices(self, device_names: str, reservation_access: ReservationAccess, reservation_group: str, reservation_timeout: float) -> None: + def reserve_devices(self, device_names: str = '$DefaultDevices', reservation_access: ReservationAccess = ReservationAccess.READ_WRITE, reservation_group: str = '', reservation_timeout: float = -1.0) -> None: """Reserve the specified device(s), which prevents other sessions from accessing them. @@ -379,7 +379,7 @@ def reserve_devices(self, device_names: str, reservation_access: ReservationAcce """ self._interpreter.reserve_devices(self._session_handle, device_names, reservation_access, reservation_group, reservation_timeout) - def unreserve_devices(self, device_names: str) -> None: + def unreserve_devices(self, device_names: str = '$DefaultDevices') -> None: """Unreserve the specified device(s), allowing other sessions to access them. @@ -390,7 +390,7 @@ def unreserve_devices(self, device_names: str) -> None: """ self._interpreter.unreserve_devices(self._session_handle, device_names) - def reset_devices(self, device_names: str) -> None: + def reset_devices(self, device_names: str = '$DefaultDevices') -> None: """Reset the specified device(s) to the default state. This function sends the specified devices a hardware reset signal, @@ -425,7 +425,7 @@ def rename_device(self, device_name: str, new_device_name: str) -> None: """ self._interpreter.rename_device(self._session_handle, device_name, new_device_name) - def update_system_configuration_file(self, chassis_name: str, connection_timeout: float) -> None: + def update_system_configuration_file(self, chassis_name: str, connection_timeout: float = -1.0) -> None: """Update the information of the specified chassis and its modules in the local configuration file. @@ -442,7 +442,7 @@ def update_system_configuration_file(self, chassis_name: str, connection_timeout """ self._interpreter.update_system_configuration_file(self._session_handle, chassis_name, connection_timeout) - def add_network_chassis(self, address: str, username: str, password: str, connection_timeout: float) -> str: + def add_network_chassis(self, address: str, username: str, password: str, connection_timeout: float = -1.0) -> str: """Connect to the specified network chassis, adds the chassis and its modules to the system, and saves them to the local configuration file. @@ -1668,7 +1668,7 @@ def set_physical_channel_property_uint64_array(self, physical_channel_names: str """ self._interpreter.set_physical_channel_property_uint64_array(self._session_handle, physical_channel_names, property_name, property_value) - def commit_properties_for_devices(self, device_names: str) -> None: + def commit_properties_for_devices(self, device_names: str = '$DefaultDevices') -> None: """Commit all device or physical channels properties with pending changes to hardware for the specified device(s) and the physical channels that they contain. @@ -1683,7 +1683,7 @@ def commit_properties_for_devices(self, device_names: str) -> None: """ self._interpreter.commit_properties_for_devices(self._session_handle, device_names) - def commit_properties_for_physical_channels(self, physical_channel_names: str) -> None: + def commit_properties_for_physical_channels(self, physical_channel_names: str = '$DefaultPhysChans') -> None: """Commit all physical channel properties with pending changes to hardware for the specified physical channel(s). @@ -2514,7 +2514,7 @@ def set_generic_property_uint64_array(self, resources: str, property_name: str, """ self._interpreter.set_generic_property_uint64_array(self._session_handle, resources, property_name, property_value) - def execute_device_command(self, device_names: str, command_name: str, timeout: float) -> None: + def execute_device_command(self, command_name: str, timeout: float, device_names: str = '$DefaultDevices') -> None: """Execute the specified device command on one or more devices. Commands define how user applications initiate actions or coordinated @@ -2538,7 +2538,7 @@ def execute_device_command(self, device_names: str, command_name: str, timeout: """ self._interpreter.execute_device_command(self._session_handle, device_names, command_name, timeout) - def execute_physical_channel_command(self, physical_channel_names: str, command_name: str, timeout: float) -> None: + def execute_physical_channel_command(self, command_name: str, timeout: float, physical_channel_names: str = '$DefaultPhysChans') -> None: """Execute the specified physical channel command on one or more physical channels. @@ -2588,7 +2588,7 @@ def execute_generic_command(self, resources: str, command_name: str, timeout: fl """ self._interpreter.execute_generic_command(self._session_handle, resources, command_name, timeout) - def read_register_uint8(self, device_name: str, register_address: int) -> int: + def read_register_uint8(self, register_address: int, device_name: str = '$DefaultDevices') -> int: """Read the specified register. To read a single bitfield, consider using properties instead. @@ -2607,7 +2607,7 @@ def read_register_uint8(self, device_name: str, register_address: int) -> int: data = self._interpreter.read_register_uint8(self._session_handle, device_name, register_address) return data - def read_register_uint16(self, device_name: str, register_address: int) -> int: + def read_register_uint16(self, register_address: int, device_name: str = '$DefaultDevices') -> int: """Read the specified register. To read a single bitfield, consider using properties instead. @@ -2626,7 +2626,7 @@ def read_register_uint16(self, device_name: str, register_address: int) -> int: data = self._interpreter.read_register_uint16(self._session_handle, device_name, register_address) return data - def read_register_uint32(self, device_name: str, register_address: int) -> int: + def read_register_uint32(self, register_address: int, device_name: str = '$DefaultDevices') -> int: """Read the specified register. To read a single bitfield, consider using properties instead. @@ -2645,7 +2645,7 @@ def read_register_uint32(self, device_name: str, register_address: int) -> int: data = self._interpreter.read_register_uint32(self._session_handle, device_name, register_address) return data - def read_register_uint64(self, device_name: str, register_address: int) -> int: + def read_register_uint64(self, register_address: int, device_name: str = '$DefaultDevices') -> int: """Read the specified register. To read a single bitfield, consider using properties instead. @@ -2664,7 +2664,7 @@ def read_register_uint64(self, device_name: str, register_address: int) -> int: data = self._interpreter.read_register_uint64(self._session_handle, device_name, register_address) return data - def write_register_uint8(self, device_name: str, register_address: int, data: int) -> None: + def write_register_uint8(self, register_address: int, data: int, device_name: str = '$DefaultDevices') -> None: """Write data to the specified register. To write a single bitfield, consider using properties instead. @@ -2680,7 +2680,7 @@ def write_register_uint8(self, device_name: str, register_address: int, data: in """ self._interpreter.write_register_uint8(self._session_handle, device_name, register_address, data) - def write_register_uint16(self, device_name: str, register_address: int, data: int) -> None: + def write_register_uint16(self, register_address: int, data: int, device_name: str = '$DefaultDevices') -> None: """Write data to the specified register. To write a single bitfield, consider using properties instead. @@ -2696,7 +2696,7 @@ def write_register_uint16(self, device_name: str, register_address: int, data: i """ self._interpreter.write_register_uint16(self._session_handle, device_name, register_address, data) - def write_register_uint32(self, device_name: str, register_address: int, data: int) -> None: + def write_register_uint32(self, register_address: int, data: int, device_name: str = '$DefaultDevices') -> None: """Write data to the specified register. To write a single bitfield, consider using properties instead. @@ -2712,7 +2712,7 @@ def write_register_uint32(self, device_name: str, register_address: int, data: i """ self._interpreter.write_register_uint32(self._session_handle, device_name, register_address, data) - def write_register_uint64(self, device_name: str, register_address: int, data: int) -> None: + def write_register_uint64(self, register_address: int, data: int, device_name: str = '$DefaultDevices') -> None: """Write data to the specified register. To write a single bitfield, consider using properties instead. @@ -2764,7 +2764,7 @@ def set_nvmem_bytes(self, nvmem_area: str, nvmem_address: int, bytes_data: bytes """ self._interpreter.set_nvmem_bytes(self._session_handle, nvmem_area, nvmem_address, bytes_data, serial_number, password) - def commit_nvmem_areas(self, nvmem_area_names: str) -> None: + def commit_nvmem_areas(self, nvmem_area_names: str = '$DefaultNVMEMAreas') -> None: """Commit pending changes to hardware for the specified NVMEM area(s). Args: @@ -2774,7 +2774,7 @@ def commit_nvmem_areas(self, nvmem_area_names: str) -> None: """ self._interpreter.commit_nvmem_areas(self._session_handle, nvmem_area_names) - def commit_nvmem_for_devices(self, device_names: str) -> None: + def commit_nvmem_for_devices(self, device_names: str = '$DefaultDevices') -> None: """Commit pending changes to hardware for all NVMEM areas on the specified device(s). diff --git a/src/codegen/metadata/nislscapi_full.json b/src/codegen/metadata/nislscapi_full.json index 7727275..b71e0ff 100644 --- a/src/codegen/metadata/nislscapi_full.json +++ b/src/codegen/metadata/nislscapi_full.json @@ -1214,6 +1214,7 @@ }, { "dataType": "TimeoutSeconds", + "default": -1.0, "dir": [ "in" ], @@ -1222,6 +1223,7 @@ }, { "dataType": "enum", + "default": "read/write", "dir": [ "in" ], @@ -1231,6 +1233,7 @@ }, { "dataType": "string", + "default": "", "dir": [ "in" ], @@ -1239,6 +1242,7 @@ }, { "dataType": "TimeoutSeconds", + "default": -1.0, "dir": [ "in" ], @@ -1313,6 +1317,7 @@ }, { "dataType": "TimeoutSeconds", + "default": -1.0, "dir": [ "in" ], @@ -1321,6 +1326,7 @@ }, { "dataType": "enum", + "default": "read/write", "dir": [ "in" ], @@ -1330,6 +1336,7 @@ }, { "dataType": "string", + "default": "", "dir": [ "in" ], @@ -1338,6 +1345,7 @@ }, { "dataType": "TimeoutSeconds", + "default": -1.0, "dir": [ "in" ], @@ -1413,6 +1421,7 @@ }, { "dataType": "TimeoutSeconds", + "default": -1.0, "dir": [ "in" ], @@ -1421,6 +1430,7 @@ }, { "dataType": "enum", + "default": "read/write", "dir": [ "in" ], @@ -1430,6 +1440,7 @@ }, { "dataType": "string", + "default": "", "dir": [ "in" ], @@ -1438,6 +1449,7 @@ }, { "dataType": "TimeoutSeconds", + "default": -1.0, "dir": [ "in" ], @@ -1723,6 +1735,7 @@ }, { "dataType": "TimeoutSeconds", + "default": -1.0, "dir": [ "in" ], @@ -1787,6 +1800,7 @@ }, { "dataType": "Device", + "default": "$DefaultDevices", "dir": [ "in" ], @@ -1795,6 +1809,7 @@ }, { "dataType": "TimeoutSeconds", + "default": -1.0, "dir": [ "in" ], @@ -1823,6 +1838,7 @@ }, { "dataType": "Device", + "default": "$DefaultDevices", "dir": [ "in" ], @@ -1875,6 +1891,7 @@ }, { "dataType": "TimeoutSeconds", + "default": -1.0, "dir": [ "in" ], @@ -1911,6 +1928,7 @@ }, { "dataType": "Device", + "default": "$DefaultDevices", "dir": [ "in" ], @@ -1919,6 +1937,7 @@ }, { "dataType": "enum", + "default": "read/write", "dir": [ "in" ], @@ -1928,6 +1947,7 @@ }, { "dataType": "string", + "default": "", "dir": [ "in" ], @@ -1936,6 +1956,7 @@ }, { "dataType": "TimeoutSeconds", + "default": -1.0, "dir": [ "in" ], @@ -1964,6 +1985,7 @@ }, { "dataType": "Device", + "default": "$DefaultDevices", "dir": [ "in" ], @@ -1992,6 +2014,7 @@ }, { "dataType": "Device", + "default": "$DefaultDevices", "dir": [ "in" ], @@ -2065,6 +2088,7 @@ }, { "dataType": "TimeoutSeconds", + "default": -1.0, "dir": [ "in" ], @@ -2116,6 +2140,7 @@ }, { "dataType": "TimeoutSeconds", + "default": -1.0, "dir": [ "in" ], @@ -4871,6 +4896,7 @@ }, { "dataType": "string", + "default": "$DefaultDevices", "dir": [ "in" ], @@ -4900,6 +4926,7 @@ }, { "dataType": "string", + "default": "$DefaultPhysChans", "dir": [ "in" ], @@ -6987,6 +7014,7 @@ }, { "dataType": "Device", + "default": "$DefaultDevices", "dir": [ "in" ], @@ -7032,6 +7060,7 @@ }, { "dataType": "PhysChan", + "default": "$DefaultPhysChans", "dir": [ "in" ], @@ -7120,6 +7149,7 @@ }, { "dataType": "Device", + "default": "$DefaultDevices", "dir": [ "in" ], @@ -7165,6 +7195,7 @@ }, { "dataType": "Device", + "default": "$DefaultDevices", "dir": [ "in" ], @@ -7210,6 +7241,7 @@ }, { "dataType": "Device", + "default": "$DefaultDevices", "dir": [ "in" ], @@ -7255,6 +7287,7 @@ }, { "dataType": "Device", + "default": "$DefaultDevices", "dir": [ "in" ], @@ -7300,6 +7333,7 @@ }, { "dataType": "Device", + "default": "$DefaultDevices", "dir": [ "in" ], @@ -7345,6 +7379,7 @@ }, { "dataType": "Device", + "default": "$DefaultDevices", "dir": [ "in" ], @@ -7390,6 +7425,7 @@ }, { "dataType": "Device", + "default": "$DefaultDevices", "dir": [ "in" ], @@ -7435,6 +7471,7 @@ }, { "dataType": "Device", + "default": "$DefaultDevices", "dir": [ "in" ], @@ -7656,6 +7693,7 @@ }, { "dataType": "NvmemArea", + "default": "$DefaultNVMEMAreas", "dir": [ "in" ], @@ -7685,6 +7723,7 @@ }, { "dataType": "Device", + "default": "$DefaultDevices", "dir": [ "in" ], diff --git a/src/codegen/templates/command.py.mako b/src/codegen/templates/command.py.mako index ee30b11..db95a77 100644 --- a/src/codegen/templates/command.py.mako +++ b/src/codegen/templates/command.py.mako @@ -70,9 +70,9 @@ class Command: % if is_class_func(function, "CommandReference") and function["name"] != "CloseProperty": % if is_classmethod(function, "CommandReference"): @classmethod - def ${get_python_function_name(function)}(${", ".join([param for param in get_classmethod_parameter_list(function)])})${get_function_return_type(function, True)}: + def ${get_python_function_name(function)}(${", ".join([param for param in get_classmethod_parameter_list(function, include_defaults=True)])})${get_function_return_type(function, True)}: % else: - def ${get_python_function_name(function)}(${", ".join([param for param in get_function_parameter_list(function, "CommandReference")])})${get_function_return_type(function, True)}: + def ${get_python_function_name(function)}(${", ".join([param for param in get_function_parameter_list(function, "CommandReference", include_defaults=True)])})${get_function_return_type(function, True)}: % endif: % if is_classmethod(function, "CommandReference"): % for docstrings in generate_docstrings(function, "CommandReference", True): diff --git a/src/codegen/templates/constants.py.mako b/src/codegen/templates/constants.py.mako index 2d0ce9c..2851cd4 100644 --- a/src/codegen/templates/constants.py.mako +++ b/src/codegen/templates/constants.py.mako @@ -59,6 +59,26 @@ except ImportError: class StrEnum(str, Enum): """StrEnum fallback for Python versions < 3.11.""" +CONNECTED_DEVICES_ALIAS = "$ConnectedDevices" +"""A resource alias representing the session's connected devices.""" + +DEFAULT_DEVICES_ALIAS = "$DefaultDevices" +"""A resource alias representing the session's default devices.""" + +DEFAULT_NVMEM_AREAS_ALIAS = "$DefaultNVMEMAreas" +"""A resource alias representing the session's default NVMEM areas.""" + +DEFAULT_PHYS_CHANS_ALIAS = "$DefaultPhysChans" +"""A resource alias representing the session's default physical channels.""" + +RESERVED_DEVICES_ALIAS = "$ReservedDevices" +"""A resource alias representing the session's reserved devices.""" + +SESSION_ALIAS = "$Session" +"""A resource alias for accessing session properties.""" + +SYSTEM_ALIAS = "$System" +"""A resource alias for accessing system properties.""" % for enum in enums: % if "capi" in enum["targets"]: diff --git a/src/codegen/templates/library.py.mako b/src/codegen/templates/library.py.mako index a1278c1..5146a66 100644 --- a/src/codegen/templates/library.py.mako +++ b/src/codegen/templates/library.py.mako @@ -85,7 +85,7 @@ class Library: % for function in functions: % if 'capi' in function['targets']: % if is_class_func(function, "Library") and function["name"] != "FinalizeLibrary" and function["name"] != "GetExtendedErrorInfo": - def ${get_python_function_name(function, True)}(${", ".join([param for param in get_function_parameter_list(function, "Library", True, True)])})${get_function_return_type(function)}: + def ${get_python_function_name(function, True)}(${", ".join([param for param in get_function_parameter_list(function, "Library", is_language=True, include_defaults=True)])})${get_function_return_type(function)}: % for docstrings in generate_docstrings(function, "Library"): ${docstrings} % endfor diff --git a/src/codegen/templates/property.py.mako b/src/codegen/templates/property.py.mako index 6d27f25..c28fe57 100644 --- a/src/codegen/templates/property.py.mako +++ b/src/codegen/templates/property.py.mako @@ -71,9 +71,9 @@ class Property: % if is_class_func(function, "PropertyReference") and function["name"] != "CloseProperty": % if is_classmethod(function, "PropertyReference"): @classmethod - def ${get_python_function_name(function)}(${", ".join([param for param in get_classmethod_parameter_list(function)])})${get_function_return_type(function, True)}: + def ${get_python_function_name(function)}(${", ".join([param for param in get_classmethod_parameter_list(function, include_defaults=True)])})${get_function_return_type(function, True)}: % else: - def ${get_python_function_name(function)}(${", ".join([param for param in get_function_parameter_list(function, "PropertyReference")])})${get_function_return_type(function, True)}: + def ${get_python_function_name(function)}(${", ".join([param for param in get_function_parameter_list(function, "PropertyReference", include_defaults=True)])})${get_function_return_type(function, True)}: % endif: % if is_classmethod(function, "PropertyReference"): % for docstrings in generate_docstrings(function, "PropertyReference", True): diff --git a/src/codegen/templates/session.py.mako b/src/codegen/templates/session.py.mako index a321001..c100f80 100644 --- a/src/codegen/templates/session.py.mako +++ b/src/codegen/templates/session.py.mako @@ -76,9 +76,9 @@ class Session: % if is_class_func(function, "Session") and function["name"] != "CloseSession": % if is_classmethod(function, "Session"): @classmethod - def ${get_python_function_name(function)}(${", ".join([param for param in get_classmethod_parameter_list(function)])})${get_function_return_type(function, True)}: + def ${get_python_function_name(function)}(${", ".join([param for param in get_classmethod_parameter_list(function, include_defaults=True)])})${get_function_return_type(function, True)}: % else: - def ${get_python_function_name(function)}(${", ".join([param for param in get_function_parameter_list(function, "Session")])})${get_function_return_type(function, True)}: + def ${get_python_function_name(function)}(${", ".join([param for param in get_function_parameter_list(function, "Session", include_defaults=True)])})${get_function_return_type(function, True)}: % endif: % if is_classmethod(function, "Session"): % for docstrings in generate_docstrings(function, "Session", True): diff --git a/src/codegen/templates/utils.py.mako b/src/codegen/templates/utils.py.mako index e816413..ae0f323 100644 --- a/src/codegen/templates/utils.py.mako +++ b/src/codegen/templates/utils.py.mako @@ -31,12 +31,12 @@ def _select_interpreter() -> BaseInterpreter: % for function in functions: % if 'capi' in function['targets']: % if remove_all_class_functions(function): -def ${get_python_function_name(function)}(${", ".join([param for param in get_function_parameter_list(function, None, True, False, False)])})${get_function_return_type(function)}: +def ${get_python_function_name(function)}(${", ".join([param for param in get_function_parameter_list(function, None, class_func=False, include_defaults=True)])})${get_function_return_type(function)}: % for docstrings in generate_docstrings(function): ${docstrings} % endfor _interpreter = _select_interpreter() - return _interpreter.${get_python_function_name(function)}(${", ".join([param for param in get_function_parameter_list(function, "", False)])}) + return _interpreter.${get_python_function_name(function)}(${", ".join([param for param in get_function_parameter_list(function, "", typing=False)])}) % endif % endif diff --git a/src/codegen/utilities/function_helpers.py b/src/codegen/utilities/function_helpers.py index c7e47da..0922b43 100644 --- a/src/codegen/utilities/function_helpers.py +++ b/src/codegen/utilities/function_helpers.py @@ -6,6 +6,7 @@ """ from utilities.interpreter_helpers import ( + convert_to_screaming_snake_case, get_param_datatype_in_ctypes, get_python_function_name, get_standardized_param_name, @@ -133,42 +134,104 @@ def get_ctypes_argtypes(function: dict) -> list[str]: return arg_list -def get_classmethod_parameter_list(function: dict) -> list[str]: +def get_classmethod_parameter_list(function: dict, include_defaults: bool = False) -> list[str]: """Generate the parameters for class methods.""" param_list = [] param_list.append("cls") + signature_params: list[tuple[str, bool]] = [] if "capi" in function["targets"]: for parameter in function["params"]: if is_capi(parameter) and is_param_input(parameter) and "Size" not in parameter["name"]: + default_value = _format_default_value(parameter) if include_defaults else None + has_none_default = _is_none_default(parameter) if include_defaults else False if parameter["dataType"] == "uint8[]": - param_list.append(f"{get_standardized_param_name(parameter)}s_data: bytes") + param_type = _type_with_none_default("bytes", has_none_default) + param = f"{get_standardized_param_name(parameter)}s_data: {param_type}" + if default_value is not None: + param = f"{param} = {default_value}" + signature_params.append((param, default_value is not None)) elif parameter["dataType"] == "enum": - param_list.append( - f"{get_standardized_param_name(parameter)}: {parameter['enumType']}" - ) + param_type = _type_with_none_default(parameter["enumType"], has_none_default) + param = f"{get_standardized_param_name(parameter)}: {param_type}" + if default_value is not None: + param = f"{param} = {default_value}" + signature_params.append((param, default_value is not None)) elif parameter["dataType"] == "Library": - param_list.append("library: Library | None") + param_type = _type_with_none_default("Library | None", has_none_default) + param = f"library: {param_type} = None" + signature_params.append((param, True)) elif parameter["dataType"] == "Session": - param_list.append("session: Session") + param_type = _type_with_none_default("Session", has_none_default) + param = f"session: {param_type}" + if default_value is not None: + param = f"{param} = {default_value}" + signature_params.append((param, default_value is not None)) else: - param_list.append( - f"{get_standardized_param_name(parameter)}: {PYTHON_DATATYPE_MAP.get(parameter['dataType'])}" + param_type = _type_with_none_default( + f"{PYTHON_DATATYPE_MAP.get(parameter['dataType'])}", + has_none_default, ) + param = f"{get_standardized_param_name(parameter)}: {param_type}" + if default_value is not None: + param = f"{param} = {default_value}" + signature_params.append((param, default_value is not None)) elif ( is_capi(parameter) and is_param_output(parameter) and parameter["dataType"] == "uint8[]" ): - param_list.append(f"num_{get_standardized_param_name(parameter)}: int") + signature_params.append( + ( + f"num_{get_standardized_param_name(parameter)}: int", + False, + ) + ) + param_list.extend(_reorder_signature_parameters(signature_params)) return param_list +def _format_default_value(parameter: dict) -> str | None: + """Convert metadata defaults to Python literals for generated signatures.""" + if "default" not in parameter: + return None + default = parameter["default"] + + if parameter.get("dataType") == "enum" and isinstance(default, str): + return f"{parameter['enumType']}.{convert_to_screaming_snake_case(default)}" + if isinstance(default, int) and parameter.get("dataType") in {"double", "TimeoutSeconds"}: + default = float(default) + return repr(default) + + +def _is_none_default(parameter: dict) -> bool: + """Check whether metadata explicitly sets a parameter default to None.""" + return "default" in parameter and parameter["default"] is None + + +def _type_with_none_default(type_hint: str, is_none_default: bool) -> str: + """Widen type hints for None defaults without duplicating optional markers.""" + if not is_none_default: + return type_hint + if "None" in type_hint: + return type_hint + return f"{type_hint} | None" + + +def _reorder_signature_parameters(parameters: list[tuple[str, bool]]) -> list[str]: + """Move all required parameters before defaulted ones while preserving relative order.""" + required = [parameter for parameter, has_default in parameters if not has_default] + defaulted = [parameter for parameter, has_default in parameters if has_default] + return required + defaulted + + def get_function_parameter_list( function: dict, class_name: str = None, + *, typing: bool = True, is_language: bool = False, class_func: bool = True, + include_defaults: bool = False, ) -> list[str]: """Generate a list of function parameters for a Python API function. @@ -183,6 +246,9 @@ def get_function_parameter_list( with a default value of Language.UNDEFINED. class_func: If True, indicates that the function is a class function. + include_defaults: If True, include parameter defaults + from metadata and reorder parameters so required + parameters appear before defaulted parameters. Returns: param_list: A list of parameter strings for the function definition. @@ -190,6 +256,7 @@ def get_function_parameter_list( param_list = [] if "capi" in function["targets"]: if typing: + signature_params: list[tuple[str, bool]] = [] if class_func: param_list.append("self") for parameter in function["params"]: @@ -199,24 +266,45 @@ def get_function_parameter_list( and "Size" not in parameter["name"] and parameter["dataType"] != class_name ): + default_value = _format_default_value(parameter) if include_defaults else None + has_none_default = _is_none_default(parameter) if include_defaults else False if parameter["dataType"] == "uint8[]": - param_list.append(f"{get_standardized_param_name(parameter)}s_data: bytes") + param_type = _type_with_none_default("bytes", has_none_default) + param = f"{get_standardized_param_name(parameter)}s_data: {param_type}" + if default_value is not None: + param = f"{param} = {default_value}" + signature_params.append((param, default_value is not None)) elif parameter["name"] == "language" and is_language: - param_list.append("language: Language = Language.UNDEFINED") + signature_params.append(("language: Language = Language.UNDEFINED", True)) elif parameter["dataType"] == "enum": - param_list.append( - f"{get_standardized_param_name(parameter)}: {parameter['enumType']}" + param_type = _type_with_none_default( + parameter["enumType"], has_none_default ) + param = f"{get_standardized_param_name(parameter)}: {param_type}" + if default_value is not None: + param = f"{param} = {default_value}" + signature_params.append((param, default_value is not None)) else: - param_list.append( - f"{get_standardized_param_name(parameter)}: {PYTHON_DATATYPE_MAP.get(parameter['dataType'])}" + param_type = _type_with_none_default( + f"{PYTHON_DATATYPE_MAP.get(parameter['dataType'])}", + has_none_default, ) + param = f"{get_standardized_param_name(parameter)}: {param_type}" + if default_value is not None: + param = f"{param} = {default_value}" + signature_params.append((param, default_value is not None)) elif ( is_capi(parameter) and is_param_output(parameter) and parameter["dataType"] == "uint8[]" ): - param_list.append(f"num_{get_standardized_param_name(parameter)}: int") + signature_params.append( + ( + f"num_{get_standardized_param_name(parameter)}: int", + False, + ) + ) + param_list.extend(_reorder_signature_parameters(signature_params)) else: for parameter in function["params"]: if ( @@ -285,27 +373,27 @@ def generate_function_call_in_class(function: dict, class_name: str) -> str: return_list.append("interpreter = library._interpreter") return_list.append("library_handle = library._interpreter._library_handle") return_list.append( - f"{return_var} = interpreter.{get_python_function_name(function)}({', '.join([param for param in (get_function_parameter_list(function, class_name, False) or [])])})" + f"{return_var} = interpreter.{get_python_function_name(function)}({', '.join([param for param in (get_function_parameter_list(function, class_name, typing=False) or [])])})" ) elif return_datatype == "CommandReference": return_list.append("session_handle = session._session_handle") return_list.append("interpreter = session._interpreter") return_list.append( - f"{return_var} = interpreter.{get_python_function_name(function)}({', '.join([param for param in (get_function_parameter_list(function, class_name, False) or [])])})" + f"{return_var} = interpreter.{get_python_function_name(function)}({', '.join([param for param in (get_function_parameter_list(function, class_name, typing=False) or [])])})" ) elif return_datatype == "PropertyReference": return_list.append("session_handle = session._session_handle") return_list.append("interpreter = session._interpreter") return_list.append( - f"{return_var} = interpreter.{get_python_function_name(function)}({', '.join([param for param in (get_function_parameter_list(function, class_name, False) or [])])})" + f"{return_var} = interpreter.{get_python_function_name(function)}({', '.join([param for param in (get_function_parameter_list(function, class_name, typing=False) or [])])})" ) elif return_datatype: return_list.append( - f"{return_var} = self._interpreter.{get_python_function_name(function)}({', '.join([param for param in (get_function_parameter_list(function, class_name, False) or [])])})" + f"{return_var} = self._interpreter.{get_python_function_name(function)}({', '.join([param for param in (get_function_parameter_list(function, class_name, typing=False) or [])])})" ) else: return_list.append( - f"self._interpreter.{get_python_function_name(function)}({', '.join([param for param in (get_function_parameter_list(function, class_name, False) or [])])})" + f"self._interpreter.{get_python_function_name(function)}({', '.join([param for param in (get_function_parameter_list(function, class_name, typing=False) or [])])})" ) return return_list diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py index 8c27214..7440980 100644 --- a/tests/unit/conftest.py +++ b/tests/unit/conftest.py @@ -10,7 +10,7 @@ from nislsc import Library, Session from nislsc._base_interpreter import BaseInterpreter -from nislsc.constants import Language, ReservationAccess +from nislsc.constants import Language from tests.unit._session_utils import ( expect_initialize_library, expect_initialize_session_with_devices, @@ -57,6 +57,6 @@ def session(library: Library, interpreter: Mock) -> Generator[Session, None, Non """ expect_initialize_session_with_devices(interpreter) with Session.initialize_session_with_devices( - library, "Dev1", -1.0, ReservationAccess.NONE, "", -1.0 + "Dev1", ) as sess: yield sess diff --git a/tests/unit/test_session.py b/tests/unit/test_session.py index 59bff71..3a42386 100644 --- a/tests/unit/test_session.py +++ b/tests/unit/test_session.py @@ -24,7 +24,9 @@ def test___library_provided___initialize_session_with_devices___session_handle_i expect_initialize_session_with_devices(interpreter, 100) with Session.initialize_session_with_devices( - library, "Dev1", -1.0, ReservationAccess.NONE, "", -1.0 + "Dev1", + library=library, + reservation_access=ReservationAccess.NONE, ) as session: assert session._session_handle == 100 interpreter.initialize_session_with_devices.assert_called_once() @@ -36,7 +38,9 @@ def test___library_provided___initialize_session_with_devices___owns_library_is_ expect_initialize_session_with_devices(interpreter) with Session.initialize_session_with_devices( - library, "Dev1", -1.0, ReservationAccess.NONE, "", -1.0 + "Dev1", + library=library, + reservation_access=ReservationAccess.NONE, ) as session: assert not session._owns_library @@ -48,7 +52,8 @@ def test___no_library___initialize_session_with_devices___library_created_and_ow expect_initialize_session_with_devices(interpreter) with Session.initialize_session_with_devices( - None, "Dev1", -1.0, ReservationAccess.NONE, "", -1.0 + "Dev1", + reservation_access=ReservationAccess.NONE, ) as session: assert session._owns_library assert session._library is not None @@ -61,7 +66,11 @@ def test___library_provided___initialize_session_with_devices___interpreter_call library_handle = library._interpreter._library_handle with Session.initialize_session_with_devices( - library, "Dev1,Dev2", 5.0, ReservationAccess.READ_WRITE, "MyGroup", 10.0 + "Dev1,Dev2", + library=library, + connection_timeout=5.0, + reservation_group="MyGroup", + reservation_timeout=10.0, ): interpreter.initialize_session_with_devices.assert_called_once_with( library_handle, @@ -82,7 +91,9 @@ def test___interpreter_raises_error___initialize_session_with_devices___slsc_err with pytest.raises(SLSCError) as exc_info: Session.initialize_session_with_devices( - library, "Dev1", -1.0, ReservationAccess.NONE, "", -1.0 + "Dev1", + library=library, + reservation_access=ReservationAccess.NONE, ) assert exc_info.value.error_code == -250806 @@ -153,7 +164,9 @@ def test___library_provided___initialize_session_with_nvmem_areas___session_hand expect_initialize_session_with_nvmem_areas(interpreter, 200) with Session.initialize_session_with_nvmem_areas( - library, "Area1", -1.0, ReservationAccess.NONE, "", -1.0 + "Area1", + library=library, + reservation_access=ReservationAccess.NONE, ) as session: assert session._session_handle == 200 interpreter.initialize_session_with_nvmem_areas.assert_called_once() @@ -166,7 +179,8 @@ def test___no_library___initialize_session_with_nvmem_areas___library_created_an expect_initialize_session_with_nvmem_areas(interpreter) with Session.initialize_session_with_nvmem_areas( - None, "Area1", -1.0, ReservationAccess.NONE, "", -1.0 + "Area1", + reservation_access=ReservationAccess.NONE, ) as session: assert session._owns_library @@ -177,7 +191,9 @@ def test___library_provided___initialize_session_with_physical_channels___sessio expect_initialize_session_with_physical_channels(interpreter, 300) with Session.initialize_session_with_physical_channels( - library, "Dev1/phys0", -1.0, ReservationAccess.NONE, "", -1.0 + "Dev1/phys0", + library=library, + reservation_access=ReservationAccess.NONE, ) as session: assert session._session_handle == 300 interpreter.initialize_session_with_physical_channels.assert_called_once() @@ -190,7 +206,8 @@ def test___no_library___initialize_session_with_physical_channels___library_crea expect_initialize_session_with_physical_channels(interpreter) with Session.initialize_session_with_physical_channels( - None, "Dev1/phys0", -1.0, ReservationAccess.NONE, "", -1.0 + "Dev1/phys0", + reservation_access=ReservationAccess.NONE, ) as session: assert session._owns_library @@ -200,7 +217,7 @@ def test___library_provided___initialize_session_without_resources___session_han ) -> None: expect_initialize_session_without_resources(interpreter, 400) - with Session.initialize_session_without_resources(library) as session: + with Session.initialize_session_without_resources(library=library) as session: assert session._session_handle == 400 interpreter.initialize_session_without_resources.assert_called_once() @@ -211,7 +228,7 @@ def test___no_library___initialize_session_without_resources___library_created_a expect_initialize_library(interpreter) expect_initialize_session_without_resources(interpreter) - with Session.initialize_session_without_resources(None) as session: + with Session.initialize_session_without_resources() as session: assert session._owns_library @@ -243,7 +260,9 @@ def test___context_manager___close___close_session_called_on_exit( expect_initialize_session_with_devices(interpreter, 100) with Session.initialize_session_with_devices( - library, "Dev1", -1.0, ReservationAccess.NONE, "", -1.0 + "Dev1", + library=library, + reservation_access=ReservationAccess.NONE, ): interpreter.close_session.assert_not_called() @@ -257,7 +276,8 @@ def test___close_owns_library___close___finalize_library_also_called( expect_initialize_session_with_devices(interpreter, 100) session = Session.initialize_session_with_devices( - None, "Dev1", -1.0, ReservationAccess.NONE, "", -1.0 + "Dev1", + reservation_access=ReservationAccess.NONE, ) session.close() @@ -270,7 +290,9 @@ def test___close_does_not_own_library___close___finalize_library_not_called( ) -> None: expect_initialize_session_with_devices(interpreter, 100) session = Session.initialize_session_with_devices( - library, "Dev1", -1.0, ReservationAccess.NONE, "", -1.0 + "Dev1", + library=library, + reservation_access=ReservationAccess.NONE, ) session.close() @@ -293,7 +315,7 @@ def test___session_opened___log_in___interpreter_called_with_args( ) -> None: session_handle = session._session_handle - session.log_in("Chassis1", "admin", "secret", 10.0, False) + session.log_in("Chassis1", "admin", "secret", False, 10.0) interpreter.log_in.assert_called_once_with( session_handle, "Chassis1", "admin", "secret", 10.0, False @@ -349,7 +371,7 @@ def test___session_opened___reserve_devices___interpreter_called_with_args( ) -> None: session_handle = session._session_handle - session.reserve_devices("Dev1", ReservationAccess.READ_WRITE, "MyGroup", 30.0) + session.reserve_devices("Dev1", reservation_group="MyGroup", reservation_timeout=30.0) interpreter.reserve_devices.assert_called_once_with( session_handle, "Dev1", ReservationAccess.READ_WRITE, "MyGroup", 30.0 @@ -873,7 +895,7 @@ def test___session_opened___execute_device_command___interpreter_called_with_arg ) -> None: session_handle = session._session_handle - session.execute_device_command("Dev1", "Reset", 10.0) + session.execute_device_command("Reset", 10.0, "Dev1") interpreter.execute_device_command.assert_called_once_with( session_handle, "Dev1", "Reset", 10.0 @@ -885,7 +907,7 @@ def test___session_opened___execute_physical_channel_command___interpreter_calle ) -> None: session_handle = session._session_handle - session.execute_physical_channel_command("Dev1/phys0", "Calibrate", 5.0) + session.execute_physical_channel_command("Calibrate", 5.0, "Dev1/phys0") interpreter.execute_physical_channel_command.assert_called_once_with( session_handle, "Dev1/phys0", "Calibrate", 5.0 @@ -919,7 +941,7 @@ def test___session_opened___read_register___returns_value( getattr(interpreter, method).return_value = value session_handle = session._session_handle - result = getattr(session, method)("Dev1", address) + result = getattr(session, method)(address, "Dev1") getattr(interpreter, method).assert_called_once_with(session_handle, "Dev1", address) assert result == value @@ -939,7 +961,7 @@ def test___session_opened___write_register___interpreter_called_with_args( ) -> None: session_handle = session._session_handle - getattr(session, method)("Dev1", address, value) + getattr(session, method)(address, value, "Dev1") getattr(interpreter, method).assert_called_once_with(session_handle, "Dev1", address, value)