diff --git a/src/sdc11073/definitions_base.py b/src/sdc11073/definitions_base.py index 8fd02f5c..f0435a53 100644 --- a/src/sdc11073/definitions_base.py +++ b/src/sdc11073/definitions_base.py @@ -1,7 +1,7 @@ from __future__ import annotations from abc import ABC, abstractmethod -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, ClassVar if TYPE_CHECKING: from types import ModuleType @@ -16,11 +16,12 @@ class ProtocolsRegistry(type): """base class that has the only purpose to register classes that use this as metaclass.""" - protocols = [] + protocols: ClassVar[list[type[BaseDefinitions]]] = [] def __new__(cls, name: str, *arg, **kwarg): - new_cls = super().__new__(cls, name, *arg, **kwarg) + new_cls: ProtocolsRegistry = super().__new__(cls, name, *arg, **kwarg) if name != 'BaseDefinitions': # ignore the base class itself + new_cls: type[BaseDefinitions] cls.protocols.append(new_cls) return new_cls @@ -100,7 +101,7 @@ class BaseDefinitions(metaclass=ProtocolsRegistry): MedicalDeviceType: QName = None # a QName, needed for types_match method ActionsNamespace: str = None # needed for wsdl generation PortTypeNamespace: str = None # needed for wsdl generation - MedicalDeviceTypesFilter: list[QName] = None # list of QNames that are used / expected in "types" of wsdiscovery + MedicalDeviceTypesFilter: tuple[QName] | None = None # QNames that are used / expected in "types" of wsdiscovery Actions = None data_model: AbstractDataModel = None diff --git a/src/sdc11073/definitions_sdc.py b/src/sdc11073/definitions_sdc.py index 5b109336..7bc4b67b 100644 --- a/src/sdc11073/definitions_sdc.py +++ b/src/sdc11073/definitions_sdc.py @@ -64,6 +64,6 @@ class SDC_v1_Definitions(BaseDefinitions): # pylint: disable=invalid-name MedicalDeviceType = ns_hlp.MDPWS.tag('MedicalDevice') ActionsNamespace = ns_hlp.SDC.namespace PortTypeNamespace = ns_hlp.SDC.namespace - MedicalDeviceTypesFilter = [DpwsDeviceType, MedicalDeviceType] + MedicalDeviceTypesFilter = (DpwsDeviceType, MedicalDeviceType) Actions = actions.Actions data_model = V1Model() diff --git a/src/sdc11073/httpserver/compression.py b/src/sdc11073/httpserver/compression.py index c873b653..58d13114 100644 --- a/src/sdc11073/httpserver/compression.py +++ b/src/sdc11073/httpserver/compression.py @@ -1,8 +1,9 @@ -"""Compression module for http. """ +"""Compression module for http.""" +import contextlib import zlib from abc import ABC, abstractmethod from collections import OrderedDict -from typing import Type +from typing import ClassVar try: import lz4.frame @@ -30,13 +31,14 @@ def decompress_payload(payload): class CompressionHandler: """Compression handler. - Should be used by servers and clients that are supposed to handle compression + Should be used by servers and clients that are supposed to handle compression. """ - available_encodings = [] # initial default - handlers = {} + + available_encodings: ClassVar[list[str]] = [] # initial default + handlers: ClassVar[dict[str, type[AbstractDataCompressor]]] = {} @classmethod - def register_handler(cls, handler: Type[AbstractDataCompressor]): + def register_handler(cls, handler: type[AbstractDataCompressor]): for alg in handler.algorithms: if alg.lower() in cls.available_encodings: raise ValueError(f'Algorithm {alg} already registered, class = {cls.__name__} ') @@ -56,7 +58,7 @@ def compress_payload(cls, algorithm: str, payload: bytes): return cls.get_handler(algorithm).compress_payload(payload) @classmethod - def decompress_payload(cls, algorithm: str, payload:bytes): + def decompress_payload(cls, algorithm: str, payload: bytes): """Decompresses payload based on required algorithm. Raises CompressionException if algorithm is not supported. @@ -68,12 +70,9 @@ def decompress_payload(cls, algorithm: str, payload:bytes): @classmethod def get_handler(cls, algorithm: str): - """ - - :param algorithm: one of strings provided by registered compression handlers + """:param algorithm: one of strings provided by registered compression handlers :return: AbstractDataCompressor implementation """ - handler = cls.handlers.get(algorithm.lower()) if not handler: txt = f"{algorithm} compression is not supported. Only {cls.available_encodings} are supported." @@ -82,14 +81,13 @@ def get_handler(cls, algorithm: str): @staticmethod def parse_header(header): - """ - Examples of headers are: Examples of its use are: + """Examples of headers are: Examples of its use are: - Accept-Encoding: compress, gzip - Accept-Encoding: - Accept-Encoding: * - Accept-Encoding: compress;q=0.5, gzip;q=1.0 - Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0 + Accept-Encoding: compress, gzip + Accept-Encoding: + Accept-Encoding: * + Accept-Encoding: compress;q=0.5, gzip;q=1.0 + Accept-Encoding: gzip;q=1.0, identity; q=0.5, *;q=0 returns sorted list of compression algorithms by priority """ @@ -100,10 +98,9 @@ def parse_header(header): for alg in (x.split(";") for x in header.split(",")): alg_name = alg[0].strip() parsed_headers[alg_name] = 1 # default - try: + with contextlib.suppress(ValueError, IndexError): parsed_headers[alg_name] = float(alg[1].split("=")[1]) - except (ValueError, IndexError): - pass + return [pair[0] for pair in sorted(parsed_headers.items(), key=lambda kv: kv[1], reverse=True)] @@ -111,15 +108,14 @@ class GzipCompressionHandler(AbstractDataCompressor): algorithms = ('gzip',) @staticmethod - def compress_payload(payload:bytes): + def compress_payload(payload: bytes): if not isinstance(payload, bytes): raise TypeError(f'a bytes-like object is required, not "{payload.__class__.__name__}", payload={payload}') gzip_compress = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION, zlib.DEFLATED, 16 + zlib.MAX_WBITS) - data = gzip_compress.compress(payload) + gzip_compress.flush() - return data + return gzip_compress.compress(payload) + gzip_compress.flush() @staticmethod - def decompress_payload(payload:bytes): + def decompress_payload(payload: bytes): return zlib.decompress(payload, 16 + zlib.MAX_WBITS) @@ -130,11 +126,11 @@ class Lz4CompressionHandler(AbstractDataCompressor): algorithms = ('x-lz4', 'lz4') @staticmethod - def compress_payload(payload:bytes): + def compress_payload(payload: bytes): return lz4.frame.compress(payload) @staticmethod - def decompress_payload(payload:bytes): + def decompress_payload(payload: bytes): return lz4.frame.decompress(payload) diff --git a/src/sdc11073/mdib/consumermdibxtra.py b/src/sdc11073/mdib/consumermdibxtra.py index 766949d6..6e5b403e 100644 --- a/src/sdc11073/mdib/consumermdibxtra.py +++ b/src/sdc11073/mdib/consumermdibxtra.py @@ -7,7 +7,7 @@ from enum import IntEnum from statistics import mean, stdev from threading import Lock -from typing import TYPE_CHECKING, Callable +from typing import TYPE_CHECKING, Callable, ClassVar from sdc11073 import observableproperties as properties from sdc11073.exceptions import ApiUsageError @@ -43,7 +43,7 @@ class DeterminationTimeWarner: ST_IN_RANGE = 0 ST_OUT_OF_RANGE = 1 - result_lookup = { + result_lookup: ClassVar[dict[tuple[int, int], tuple[_WarningState, bool]]] = { (ST_IN_RANGE, ST_IN_RANGE): (_WarningState.A_NO_LOG, False), (ST_IN_RANGE, ST_OUT_OF_RANGE): (_WarningState.A_OUT_OF_RANGE, False), (ST_OUT_OF_RANGE, ST_OUT_OF_RANGE): (_WarningState.A_STILL_OUT_OF_RANGE, True), diff --git a/src/sdc11073/mdib/descriptorcontainers.py b/src/sdc11073/mdib/descriptorcontainers.py index 4f4398f9..8fb8fb36 100644 --- a/src/sdc11073/mdib/descriptorcontainers.py +++ b/src/sdc11073/mdib/descriptorcontainers.py @@ -3,7 +3,7 @@ import inspect import sys from dataclasses import dataclass -from typing import TYPE_CHECKING, Any, Protocol +from typing import TYPE_CHECKING, Any, Protocol, ClassVar from sdc11073 import observableproperties as properties from sdc11073.xml_types import ext_qnames as ext @@ -124,7 +124,9 @@ class AbstractDescriptorContainer(ContainerBase): _props = ('Handle', 'DescriptorVersion', 'SafetyClassification', 'Extension', 'Type') _child_elements_order = (ext.Extension, pm_qnames.Type) # child elements in BICEPS order STATE_QNAME = None - extension_class_lookup = {msg.Retrievability: pm_types.Retrievability} + extension_class_lookup: ClassVar[dict[etree_.QName, type[pm_types.PropertyBasedPMType]]] = { + msg.Retrievability: pm_types.Retrievability + } def __init__(self, handle: str | None, parent_handle: str | None): """Parent Handle can only be None for a Mds Descriptor. every other descriptor has a parent.""" diff --git a/src/sdc11073/mdib/statecontainers.py b/src/sdc11073/mdib/statecontainers.py index 21ea214b..f0a06b28 100644 --- a/src/sdc11073/mdib/statecontainers.py +++ b/src/sdc11073/mdib/statecontainers.py @@ -154,7 +154,7 @@ class AllowedValuesType(pm_types.PropertyBasedPMType): # pylint: disable=invali """Represents a list of values, in xml it is a list of pm.Value elements with one value as text.""" Value: list[str] = x_struct.SubElementStringListProperty(pm.Value) - _props = ['Value'] + _props = ('Value',) def is_empty(self) -> bool: """Return True if Value is empty.""" diff --git a/src/sdc11073/provider/porttypes/porttypebase.py b/src/sdc11073/provider/porttypes/porttypebase.py index 8d7ce331..d11288ec 100644 --- a/src/sdc11073/provider/porttypes/porttypebase.py +++ b/src/sdc11073/provider/porttypes/porttypebase.py @@ -1,7 +1,7 @@ from __future__ import annotations from collections import namedtuple -from typing import TYPE_CHECKING, List, Optional +from typing import TYPE_CHECKING, Optional, ClassVar from lxml import etree as etree_ @@ -37,7 +37,7 @@ class DPWSPortTypeBase: port_type_name: Optional[etree_.QName] = None WSDLOperationBindings = () # overwrite in derived classes WSDLMessageDescriptions = () # overwrite in derived classes - additional_namespaces: List[PrefixNamespace] = [] # for special namespaces + additional_namespaces: ClassVar[list[PrefixNamespace]] = [] # for special namespaces def __init__(self, sdc_device, log_prefix: Optional[str] = None): """ diff --git a/src/sdc11073/provider/providerimpl.py b/src/sdc11073/provider/providerimpl.py index 5a853969..f4f5bfe2 100644 --- a/src/sdc11073/provider/providerimpl.py +++ b/src/sdc11073/provider/providerimpl.py @@ -329,7 +329,7 @@ def publish(self): scopes = self._components.scopes_factory(self._mdib) x_addrs = self.get_xaddrs() self._wsdiscovery.publish_service(self.epr_urn, - self._mdib.sdc_definitions.MedicalDeviceTypesFilter, + list(self._mdib.sdc_definitions.MedicalDeviceTypesFilter), scopes, x_addrs) diff --git a/src/sdc11073/pysoap/soapenvelope.py b/src/sdc11073/pysoap/soapenvelope.py index 370f429d..2ae0ba7c 100644 --- a/src/sdc11073/pysoap/soapenvelope.py +++ b/src/sdc11073/pysoap/soapenvelope.py @@ -109,14 +109,14 @@ class reasontext(ElementWithText): # noqa: N801 """Text with language attribute.""" lang: str = struct.StringAttributeProperty(ns_hlp.XML.tag('lang'), default_py_value='en-US') - _props = ['lang'] + _props = ('lang',) class faultreason(XMLTypeBase): # noqa: N801 """List of reasontext.""" Text: list[reasontext] = struct.SubElementListProperty(ns_hlp.S12.tag('Text'), value_class=reasontext) - _props = ['Text'] + _props = ('Text',) class subcode(XMLTypeBase): # noqa: N801 @@ -124,7 +124,7 @@ class subcode(XMLTypeBase): # noqa: N801 Value: etree_.QName = struct.NodeTextQNameProperty(ns_hlp.S12.tag('Value')) # optional Subcode Element intentionally omitted, it is of type subcode => recursion, bad idea! - _props = ['Value'] + _props = ('Value',) class faultcode(XMLTypeBase): # noqa: N801 @@ -132,7 +132,7 @@ class faultcode(XMLTypeBase): # noqa: N801 Value = struct.NodeEnumQNameProperty(ns_hlp.S12.tag('Value'), faultcodeEnum) Subcode = struct.SubElementProperty(ns_hlp.S12.tag('Subcode'), value_class=subcode, is_optional=True) - _props = ['Value', 'Subcode'] + _props = ('Value', 'Subcode') class Fault(MessageType): @@ -147,8 +147,8 @@ class Fault(MessageType): Role = struct.AnyUriTextElement(ns_hlp.S12.tag('Role'), is_optional=True) # Schema says Detail is an "any" type. Here it is modelled as a string that becomes the text of the Detail node Detail = struct.NodeStringProperty(ns_hlp.S12.tag('Detail'), is_optional=True) - _props = ['Code', 'Reason', 'Node', 'Role', 'Detail'] - additional_namespaces = [ns_hlp.XML, ns_hlp.WSE] + _props = ('Code', 'Reason', 'Node', 'Role', 'Detail') + additional_namespaces = (ns_hlp.XML, ns_hlp.WSE) def add_reason_text(self, text: str, lang: str = 'en-US'): """Add reason text to list.""" diff --git a/src/sdc11073/wsdiscovery/wsdimpl.py b/src/sdc11073/wsdiscovery/wsdimpl.py index deb4e04c..16971d35 100644 --- a/src/sdc11073/wsdiscovery/wsdimpl.py +++ b/src/sdc11073/wsdiscovery/wsdimpl.py @@ -102,10 +102,10 @@ def _is_scope_in_list(uri: str, match_by: str, srv_sc: wsd_types.ScopesType) -> def matches_filter(service: Service, - types: list[QName] | None, + types: Iterable[QName] | None, scopes: wsd_types.ScopesType | None) -> bool: """Check if service matches the types and scopes.""" - if types is not None and len(types) > 0: + if types is not None: for ttype in types: if not _is_type_in_list(ttype, service.types): return False @@ -117,7 +117,7 @@ def matches_filter(service: Service, def filter_services(services: Iterable[Service], - types: list[QName] | None, + types: Iterable[QName] | None, scopes: wsd_types.ScopesType | None) -> list[Service]: """Filter services that match types and scopes.""" return [service for service in services if matches_filter(service, types, scopes)] @@ -183,7 +183,7 @@ def stop(self): self._server_started = False def search_services(self, - types: list[QName] | None = None, + types: Iterable[QName] | None = None, scopes: wsd_types.ScopesType | None = None, timeout: int | float | None = 5, repeat_probe_interval: int | None = 3) -> list[Service]: @@ -198,6 +198,7 @@ def search_services(self, if not self._server_started: raise RuntimeError("Server not started") + types = list(types) if types is not None else None start = time.monotonic() end = start + timeout now = time.monotonic() @@ -545,7 +546,8 @@ def _send_probe_match(self, services: list[Service], relates_to: str, addr: str) ns_map=nsh.partial_map(nsh.WSD))) self._networking_thread.add_unicast_message(created_message, addr[0], addr[1]) - def _send_probe(self, types: list[QName] | None = None, scopes: wsd_types.ScopesType | None = None): + def _send_probe(self, types: Iterable[QName] | None = None, scopes: wsd_types.ScopesType | None = None): + types = list(types) if types is not None else None # enforce iteration self._logger.debug('sending probe types=%r scopes=%r', types_info(types), scopes) payload = wsd_types.ProbeType() payload.Types = types diff --git a/src/sdc11073/xml_types/addressing_types.py b/src/sdc11073/xml_types/addressing_types.py index f0004f92..14fcee14 100644 --- a/src/sdc11073/xml_types/addressing_types.py +++ b/src/sdc11073/xml_types/addressing_types.py @@ -22,21 +22,21 @@ class EndpointReferenceType(XMLTypeBase): Address = struct.NodeStringProperty(nsh.WSA.tag('Address')) ReferenceParameters = struct.AnyEtreeNodeListProperty(nsh.WSA.tag('ReferenceParameters'), is_optional=True) PortType = struct.NodeTextQNameProperty(nsh.WSA.tag('PortType'), is_optional=True) - _props = ['Address', 'ReferenceParameters', 'PortType'] + _props = ('Address', 'ReferenceParameters', 'PortType') class Relationship(ElementWithText): """Relationship type of ws-addressing.""" RelationshipType = struct.QNameAttributeProperty('RelationshipType') - _props = ['RelationshipType'] + _props = ('RelationshipType',) class MustUnderStandTextElement(ElementWithText): """XML Element with text and mustUnderstand attribute.""" _must_understand = struct.BooleanAttributeProperty(nsh.S12.tag('mustUnderstand'), default_py_value=True) - _props = ['_must_understand'] + _props = ('_must_understand',) def __init__(self, text: str | None = None): super().__init__() @@ -59,7 +59,7 @@ class HeaderInformationBlock(XMLTypeBase): From = struct.SubElementProperty(nsh.WSA.tag('From'), value_class=EndpointReferenceType, is_optional=True) - _props = ['MessageID', 'RelatesTo', 'To', 'Action', 'From'] + _props = ('MessageID', 'RelatesTo', 'To', 'Action', 'From') def __init__(self, action: str | None = None, message_id: str | None = None, diff --git a/src/sdc11073/xml_types/basetypes.py b/src/sdc11073/xml_types/basetypes.py index e6db58f0..d3500016 100644 --- a/src/sdc11073/xml_types/basetypes.py +++ b/src/sdc11073/xml_types/basetypes.py @@ -4,7 +4,7 @@ import inspect import traceback from math import isclose -from typing import List, TYPE_CHECKING +from typing import TYPE_CHECKING from lxml import etree as etree_ @@ -111,7 +111,7 @@ class ElementWithText(XMLTypeBase): """ NODETYPE = None text: str = NodeStringProperty() # this is the text of the node. Here attribute is lower case! - _props = ['text'] + _props = ('text',) def __init__(self, text=None): super().__init__() @@ -122,9 +122,9 @@ class ElementWithTextList(XMLTypeBase): """An Element with text, which is alist of words(string without whitespace). """ # this is the text list of the node. Here attribute is lower case! - text: List[str] = NodeTextListProperty(sub_element_name=None, + text: list[str] = NodeTextListProperty(sub_element_name=None, value_class=str) - _props = ['text'] + _props = ('text',) class MessageType(XMLTypeBase): @@ -134,4 +134,4 @@ class MessageType(XMLTypeBase): in the soap header.""" NODETYPE = None action = None - additional_namespaces = [] # derived class list namespaces other than PM and MSG + additional_namespaces = () # derived class list namespaces other than PM and MSG diff --git a/src/sdc11073/xml_types/dataconverters.py b/src/sdc11073/xml_types/dataconverters.py index c4c8dd24..4ae2898d 100644 --- a/src/sdc11073/xml_types/dataconverters.py +++ b/src/sdc11073/xml_types/dataconverters.py @@ -101,8 +101,8 @@ def __init__(self, element_converter): def check_valid(self, py_value) -> bool: if STRICT_VALUE_CHECK and py_value is not None: - if not isinstance(py_value, (list, tuple)): - raise ValueError(f'Value must be list or a tuple, got {type(py_value)}') + if not isinstance(py_value, list): + raise ValueError(f'Value must be an instance of {type(list)}, got {type(py_value)}') for elem in py_value: self._element_converter.check_valid(elem) diff --git a/src/sdc11073/xml_types/dpws_types.py b/src/sdc11073/xml_types/dpws_types.py index 6501263e..2a90c918 100644 --- a/src/sdc11073/xml_types/dpws_types.py +++ b/src/sdc11073/xml_types/dpws_types.py @@ -49,7 +49,7 @@ class HostServiceType(XMLTypeBase): EndpointReference = cp.SubElementProperty(default_ns_helper.WSA.tag('EndpointReference'), value_class=EndpointReferenceType) Types = cp.NodeTextQNameListProperty(default_ns_helper.DPWS.tag('Types')) - _props = ['EndpointReference', 'Types'] + _props = ('EndpointReference', 'Types') class HostedServiceType(XMLTypeBase): @@ -57,12 +57,12 @@ class HostedServiceType(XMLTypeBase): value_class=EndpointReferenceType) Types = cp.NodeTextQNameListProperty(default_ns_helper.DPWS.tag('Types')) ServiceId = cp.AnyUriTextElement(default_ns_helper.DPWS.tag('ServiceId')) - _props = ['EndpointReference', 'Types', 'ServiceId'] + _props = ('EndpointReference', 'Types', 'ServiceId') class LocalizedStringType(ElementWithText): lang = cp.StringAttributeProperty(default_ns_helper.XML.tag('lang')) - _props = ['lang'] + _props = ('lang',) @classmethod def init(cls, text: str, lang: Optional[str] = None): @@ -86,7 +86,7 @@ class ThisDeviceType(XMLTypeBase): value_class=LocalizedStringType) FirmwareVersion = cp.NodeStringProperty(default_ns_helper.DPWS.tag('FirmwareVersion'), is_optional=True) SerialNumber = cp.NodeStringProperty(default_ns_helper.DPWS.tag('SerialNumber'), is_optional=True) - _props = ['FriendlyName', 'FirmwareVersion', 'SerialNumber'] + _props = ('FriendlyName', 'FirmwareVersion', 'SerialNumber') def __init__(self, friendly_name: Union[str, LocalizedStringTypeDict, None] = None, firmware_version: Optional[str] = None, @@ -118,7 +118,7 @@ class ThisModelType(XMLTypeBase): ModelNumber = cp.NodeStringProperty(default_ns_helper.DPWS.tag('ModelNumber'), is_optional=True) ModelUrl = cp.NodeStringProperty(default_ns_helper.DPWS.tag('ModelUrl'), is_optional=True) PresentationUrl = cp.NodeStringProperty(default_ns_helper.DPWS.tag('PresentationUrl'), is_optional=True) - _props = ['Manufacturer', 'ManufacturerUrl', 'ModelName', 'ModelNumber', 'ModelUrl', 'PresentationUrl'] + _props = ('Manufacturer', 'ManufacturerUrl', 'ModelName', 'ModelNumber', 'ModelUrl', 'PresentationUrl') def __init__(self, manufacturer: Union[str, LocalizedStringTypeDict, None] = None, diff --git a/src/sdc11073/xml_types/eventing_types.py b/src/sdc11073/xml_types/eventing_types.py index c58e3b91..b93e7237 100644 --- a/src/sdc11073/xml_types/eventing_types.py +++ b/src/sdc11073/xml_types/eventing_types.py @@ -18,13 +18,13 @@ class DeliveryType(XMLTypeBase): NotifyTo = cp.SubElementProperty(wse_tag('NotifyTo'), value_class=EndpointReferenceType, default_py_value=EndpointReferenceType()) - _props = ['Mode', 'NotifyTo'] + _props = ('Mode', 'NotifyTo') class FilterType(ElementWithText): Dialect = cp.AnyURIAttributeProperty('Dialect') any = xml_structure.AnyEtreeNodeListProperty(None, is_optional=True) - _props = ['Dialect', 'any'] + _props = ('Dialect', 'any') class Subscribe(MessageType): @@ -40,8 +40,8 @@ class Subscribe(MessageType): Filter = cp.SubElementProperty(wse_tag('Filter'), value_class=FilterType, is_optional=True) - _props = ['EndTo', 'Delivery', 'Expires', 'Filter'] - additional_namespaces = [default_ns_helper.WSE] + _props = ('EndTo', 'Delivery', 'Expires', 'Filter') + additional_namespaces = (default_ns_helper.WSE,) def init_end_to(self): self.EndTo = EndpointReferenceType() @@ -59,20 +59,20 @@ class SubscribeResponse(MessageType): value_class=EndpointReferenceType, default_py_value=EndpointReferenceType()) Expires = cp.NodeTextProperty(wse_tag('Expires'), value_converter=DurationConverter) - _props = ['SubscriptionManager', 'Expires'] - additional_namespaces = [default_ns_helper.WSE] + _props = ('SubscriptionManager', 'Expires') + additional_namespaces = (default_ns_helper.WSE,) class Unsubscribe(MessageType): NODETYPE = wse_tag('Unsubscribe') action = EventingActions.Unsubscribe - additional_namespaces = [default_ns_helper.WSE] + additional_namespaces = (default_ns_helper.WSE,) class UnsubscribeResponse(MessageType): NODETYPE = wse_tag('UnsubscribeResponse') action = EventingActions.UnsubscribeResponse - additional_namespaces = [default_ns_helper.WSE] + additional_namespaces = (default_ns_helper.WSE,) def as_etree_node(self, *args, **kwargs): # Unsubscribe has empty body @@ -81,7 +81,7 @@ def as_etree_node(self, *args, **kwargs): class LanguageSpecificStringType(ElementWithText): lang = cp.StringAttributeProperty(attribute_name=xml_tag('lang')) - _props = ['lang'] + _props = ('lang',) class SubscriptionEnd(MessageType): @@ -93,8 +93,8 @@ class SubscriptionEnd(MessageType): Status = cp.NodeStringProperty(wse_tag('Status')) Reason = cp.SubElementListProperty(wse_tag('Reason'), value_class=LanguageSpecificStringType) - _props = ['SubscriptionManager', 'Status', 'Reason'] - additional_namespaces = [default_ns_helper.WSE] + _props = ('SubscriptionManager', 'Status', 'Reason') + additional_namespaces = (default_ns_helper.WSE,) def add_reason(self, text, lang=None): tmp = LanguageSpecificStringType() @@ -107,27 +107,27 @@ class Renew(MessageType): NODETYPE = wse_tag('Renew') action = EventingActions.Renew Expires = cp.NodeTextProperty(wse_tag('Expires'), value_converter=DurationConverter) - _props = ['Expires'] - additional_namespaces = [default_ns_helper.WSE] + _props = ('Expires',) + additional_namespaces = (default_ns_helper.WSE,) class RenewResponse(MessageType): NODETYPE = wse_tag('RenewResponse') action = EventingActions.RenewResponse Expires = cp.NodeTextProperty(wse_tag('Expires'), value_converter=DurationConverter) - _props = ['Expires'] - additional_namespaces = [default_ns_helper.WSE] + _props = ('Expires',) + additional_namespaces = (default_ns_helper.WSE,) class GetStatus(MessageType): NODETYPE = wse_tag('GetStatus') action = EventingActions.GetStatus - additional_namespaces = [default_ns_helper.WSE] + additional_namespaces = (default_ns_helper.WSE,) class GetStatusResponse(MessageType): NODETYPE = wse_tag('GetStatusResponse') action = EventingActions.GetStatusResponse Expires = cp.NodeTextProperty(wse_tag('Expires'), value_converter=DurationConverter) - _props = ['Expires'] - additional_namespaces = [default_ns_helper.WSE] + _props = ('Expires',) + additional_namespaces = (default_ns_helper.WSE,) diff --git a/src/sdc11073/xml_types/mex_types.py b/src/sdc11073/xml_types/mex_types.py index 6a4e8df8..0f9ec2b7 100644 --- a/src/sdc11073/xml_types/mex_types.py +++ b/src/sdc11073/xml_types/mex_types.py @@ -16,7 +16,7 @@ class GetMetadata(MessageType): action = 'http://schemas.xmlsoap.org/ws/2004/09/mex/GetMetadata/Request' Dialect = cp.AnyUriTextElement(wsx_tag('Dialect'), is_optional=True) Identifier = cp.AnyUriTextElement(wsx_tag('Identifier'), is_optional=True) - _props = ['Dialect', 'Identifier'] + _props = ('Dialect', 'Identifier') class ThisModelMetadataSection(PropertyBasedPMType): @@ -27,7 +27,7 @@ class ThisModelMetadataSection(PropertyBasedPMType): default_py_value=DeviceMetadataDialectURI.THIS_MODEL, is_optional=False) Identifier = cp.AnyURIAttributeProperty('Identifier') - _props = ['MetadataReference', 'Location', 'Dialect', 'Identifier'] + _props = ('MetadataReference', 'Location', 'Dialect', 'Identifier') class ThisDeviceMetadataSection(PropertyBasedPMType): @@ -38,14 +38,14 @@ class ThisDeviceMetadataSection(PropertyBasedPMType): default_py_value=DeviceMetadataDialectURI.THIS_DEVICE, is_optional=False) Identifier = cp.AnyURIAttributeProperty('Identifier') - _props = ['MetadataReference', 'Location', 'Dialect', 'Identifier'] + _props = ('MetadataReference', 'Location', 'Dialect', 'Identifier') class MetaDataRelationship(PropertyBasedPMType): Type = cp.AnyURIAttributeProperty(attribute_name='Type', default_py_value=DeviceRelationshipTypeURI.HOST) Host = cp.SubElementProperty(dpws_tag('Host'), value_class=HostServiceType) Hosted = cp.SubElementListProperty(dpws_tag('Hosted'), value_class=HostedServiceType) - _props = ['Type', 'Host', 'Hosted'] + _props = ('Type', 'Host', 'Hosted') class RelationshipMetadataSection(PropertyBasedPMType): @@ -57,7 +57,7 @@ class RelationshipMetadataSection(PropertyBasedPMType): default_py_value=DeviceMetadataDialectURI.RELATIONSHIP, is_optional=False) Identifier = cp.AnyURIAttributeProperty('Identifier') - _props = ['MetadataReference', 'Location', 'Dialect', 'Identifier'] + _props = ('MetadataReference', 'Location', 'Dialect', 'Identifier') class LocationMetadataSection(PropertyBasedPMType): @@ -66,7 +66,7 @@ class LocationMetadataSection(PropertyBasedPMType): default_py_value=default_ns_helper.WSDL.namespace, is_optional=False) Identifier = cp.AnyURIAttributeProperty('Identifier') - _props = ['Location', 'Dialect', 'Identifier'] + _props = ('Location', 'Dialect', 'Identifier') dialect_lookup = {DeviceMetadataDialectURI.THIS_MODEL: (ThisModelMetadataSection, @@ -89,7 +89,7 @@ class Metadata(MessageType): action = f'{default_ns_helper.WXF.namespace}/GetResponse' MetadataSection = cp.SubElementListProperty(wsx_tag('MetadataSection'), value_class=PropertyBasedPMType) - _props = ['MetadataSection'] + _props = ('MetadataSection',) def __init__(self): super().__init__() diff --git a/src/sdc11073/xml_types/msg_types.py b/src/sdc11073/xml_types/msg_types.py index 2f28e5a4..59b07365 100644 --- a/src/sdc11073/xml_types/msg_types.py +++ b/src/sdc11073/xml_types/msg_types.py @@ -56,15 +56,15 @@ class InvocationError(StringEnum): ### Reports ### class AbstractReportPart(PropertyBasedPMType): SourceMds = cp.NodeStringProperty(msg.SourceMds, is_optional=True) - _props = ['SourceMds'] + _props = ('SourceMds',) class AbstractReport(MessageType): MdibVersion = cp.IntegerAttributeProperty('MdibVersion', implied_py_value=0) SequenceId = cp.StringAttributeProperty('SequenceId') InstanceId = cp.IntegerAttributeProperty('InstanceId') - _props = ['MdibVersion', 'SequenceId', 'InstanceId'] - additional_namespaces = [default_ns_helper.XSI] + _props = ('MdibVersion', 'SequenceId', 'InstanceId') + additional_namespaces = (default_ns_helper.XSI,) def set_mdib_version_group(self, mdib_version_group): self.MdibVersion = mdib_version_group.mdib_version @@ -85,7 +85,7 @@ class MetricReportPart(ReportPartValuesList): value_class=AbstractContextStateContainer, cls_getter=get_state_container_class, ns_helper=default_ns_helper) - _props = ['MetricState'] + _props = ('MetricState',) @property def values_list(self): @@ -94,7 +94,7 @@ def values_list(self): class AbstractMetricReport(AbstractReport): ReportPart = cp.SubElementListProperty(msg.ReportPart, value_class=MetricReportPart) - _props = ['ReportPart'] + _props = ('ReportPart',) def add_report_part(self) -> MetricReportPart: self.ReportPart.append(MetricReportPart()) @@ -117,7 +117,7 @@ class ContextReportPart(ReportPartValuesList): value_class=AbstractContextStateContainer, cls_getter=get_state_container_class, ns_helper=default_ns_helper) - _props = ['ContextState'] + _props = ('ContextState',) @property def values_list(self): @@ -126,7 +126,7 @@ def values_list(self): class AbstractContextReport(AbstractReport): ReportPart = cp.SubElementListProperty(msg.ReportPart, value_class=ContextReportPart) - _props = ['ReportPart'] + _props = ('ReportPart',) def add_report_part(self) -> ContextReportPart: self.ReportPart.append(ContextReportPart()) @@ -149,7 +149,7 @@ class OperationalStateReportPart(ReportPartValuesList): value_class=AbstractOperationStateContainer, cls_getter=get_state_container_class, ns_helper=default_ns_helper) - _props = ['OperationState'] + _props = ('OperationState',) @property def values_list(self): @@ -158,7 +158,7 @@ def values_list(self): class AbstractOperationalStateReport(AbstractReport): ReportPart = cp.SubElementListProperty(msg.ReportPart, value_class=OperationalStateReportPart) - _props = ['ReportPart'] + _props = ('ReportPart',) def add_report_part(self) -> OperationalStateReportPart: self.ReportPart.append(OperationalStateReportPart()) @@ -181,7 +181,7 @@ class AlertReportPart(ReportPartValuesList): value_class=AbstractAlertStateContainer, cls_getter=get_state_container_class, ns_helper=default_ns_helper) - _props = ['AlertState'] + _props = ('AlertState',) @property def values_list(self): @@ -190,7 +190,7 @@ def values_list(self): class AbstractAlertReport(AbstractReport): ReportPart = cp.SubElementListProperty(msg.ReportPart, value_class=AlertReportPart) - _props = ['ReportPart'] + _props = ('ReportPart',) def add_report_part(self) -> AlertReportPart: self.ReportPart.append(AlertReportPart()) @@ -213,7 +213,7 @@ class ComponentReportPart(ReportPartValuesList): value_class=AbstractDeviceComponentStateContainer, cls_getter=get_state_container_class, ns_helper=default_ns_helper) - _props = ['ComponentState'] + _props = ('ComponentState',) @property def values_list(self): @@ -222,7 +222,7 @@ def values_list(self): class AbstractComponentReport(AbstractReport): ReportPart = cp.SubElementListProperty(msg.ReportPart, value_class=ComponentReportPart) - _props = ['ReportPart'] + _props = ('ReportPart',) def add_report_part(self) -> ComponentReportPart: self.ReportPart.append(ComponentReportPart()) @@ -245,7 +245,7 @@ class InvocationInfo(PropertyBasedPMType): InvocationState = cp.NodeEnumTextProperty(msg.InvocationState, InvocationState) InvocationError = cp.NodeEnumTextProperty(msg.InvocationError, InvocationError, is_optional=True) InvocationErrorMessage = cp.SubElementListProperty(msg.InvocationErrorMessage, value_class=LocalizedText) - _props = ['TransactionId', 'InvocationState', 'InvocationError', 'InvocationErrorMessage'] + _props = ('TransactionId', 'InvocationState', 'InvocationError', 'InvocationErrorMessage') def __repr__(self): if self.InvocationError: @@ -267,14 +267,14 @@ class OperationInvokedReportPart(AbstractReportPart): InvocationSource = cp.SubElementProperty(msg.InvocationSource, value_class=InstanceIdentifier) OperationHandleRef = cp.HandleRefAttributeProperty('OperationHandleRef', is_optional=False) OperationTarget = cp.HandleRefAttributeProperty('OperationTarget') - _props = ['InvocationInfo', 'InvocationSource', 'OperationHandleRef', 'OperationTarget'] + _props = ('InvocationInfo', 'InvocationSource', 'OperationHandleRef', 'OperationTarget') class OperationInvokedReport(AbstractReport): NODETYPE = msg.OperationInvokedReport action = Actions.OperationInvokedReport ReportPart = cp.SubElementListProperty(msg.ReportPart, value_class=OperationInvokedReportPart) - _props = ['ReportPart'] + _props = ('ReportPart',) def add_report_part(self) -> OperationInvokedReportPart: self.ReportPart.append(OperationInvokedReportPart()) @@ -289,7 +289,7 @@ class AbstractSetResponse(MessageType): MdibVersion = cp.VersionCounterAttributeProperty('MdibVersion', implied_py_value=0) SequenceId = cp.AnyURIAttributeProperty('SequenceId', is_optional=False) InstanceId = cp.UnsignedIntAttributeProperty('InstanceId') - _props = ['Extension', 'InvocationInfo', 'MdibVersion', 'SequenceId', 'InstanceId'] + _props = ('Extension', 'InvocationInfo', 'MdibVersion', 'SequenceId', 'InstanceId') class SetContextStateResponse(AbstractSetResponse): @@ -336,7 +336,7 @@ class WaveformStream(AbstractReport): value_class=RealTimeSampleArrayMetricStateContainer, cls_getter=get_state_container_class, ns_helper=default_ns_helper) - _props = ['State'] + _props = ('State',) ### DescriptionModificationReport ### @@ -353,14 +353,14 @@ class DescriptionModificationReportPart(AbstractReportPart): ModificationType = cp.EnumAttributeProperty('ModificationType', enum_cls=DescriptionModificationType, implied_py_value=DescriptionModificationType.UPDATE) - _props = ['Descriptor', 'State', 'ParentDescriptor', 'ModificationType'] + _props = ('Descriptor', 'State', 'ParentDescriptor', 'ModificationType') class DescriptionModificationReport(AbstractReport): NODETYPE = msg.DescriptionModificationReport action = Actions.DescriptionModificationReport ReportPart = cp.SubElementListProperty(msg.ReportPart, value_class=DescriptionModificationReportPart) - _props = ['ReportPart'] + _props = ('ReportPart',) def add_report_part(self) -> DescriptionModificationReportPart: self.ReportPart.append(DescriptionModificationReportPart()) @@ -382,14 +382,14 @@ class AbstractGet(MessageType): class AbstractSet(MessageType): OperationHandleRef = cp.NodeStringProperty(msg.OperationHandleRef) - _props = ['OperationHandleRef'] + _props = ('OperationHandleRef',) class AbstractGetResponse(MessageType): MdibVersion = cp.IntegerAttributeProperty('MdibVersion', implied_py_value=0) SequenceId = cp.StringAttributeProperty('SequenceId') InstanceId = cp.IntegerAttributeProperty('InstanceId') - _props = ['MdibVersion', 'SequenceId', 'InstanceId'] + _props = ('MdibVersion', 'SequenceId', 'InstanceId') def set_mdib_version_group(self, mdib_version_group): self.MdibVersion = mdib_version_group.mdib_version @@ -406,7 +406,7 @@ class Channel(PropertyBasedPMType): value_class=AbstractMetricDescriptorContainer, cls_getter=get_descriptor_container_class, ns_helper=default_ns_helper) - _props = ['container', 'Metric'] + _props = ('container', 'Metric') class Vmd(PropertyBasedPMType): @@ -415,7 +415,7 @@ class Vmd(PropertyBasedPMType): cls_getter=get_descriptor_container_class, ns_helper=default_ns_helper) Channel = cp.SubElementListProperty(pm.Channel, value_class=Channel) - _props = ['container', 'Channel'] + _props = ('container', 'Channel') class Mds(PropertyBasedPMType): @@ -424,12 +424,12 @@ class Mds(PropertyBasedPMType): cls_getter=get_descriptor_container_class, ns_helper=default_ns_helper) Vmd = cp.SubElementListProperty(pm.Vmd, value_class=Vmd) - _props = ['container', 'Vmd'] + _props = ('container', 'Vmd') class MdDescription(PropertyBasedPMType): Mds = cp.SubElementListProperty(pm.Mds, value_class=Mds) - _props = ['Mds'] + _props = ('Mds',) class MdState(PropertyBasedPMType): @@ -438,7 +438,7 @@ class MdState(PropertyBasedPMType): cls_getter=get_state_container_class, ns_helper=default_ns_helper ) - _props = ['State'] + _props = ('State',) # class Mdib(PropertyBasedPMType): @@ -457,14 +457,14 @@ class GetMdibResponse(AbstractGetResponse): NODETYPE = msg.GetMdibResponse action = Actions.GetMdibResponse Mdib = cp.AnyEtreeNodeProperty(None) - _props = ['Mdib'] + _props = ('Mdib',) class GetMdDescription(AbstractGet): NODETYPE = msg.GetMdDescription action = Actions.GetMdDescription HandleRef = cp.SubElementHandleRefListProperty(msg.HandleRef) - _props = ['HandleRef'] + _props = ('HandleRef',) class GetMdDescriptionResponse(AbstractGetResponse): @@ -473,28 +473,28 @@ class GetMdDescriptionResponse(AbstractGetResponse): MdDescription = cp.SubElementProperty(msg.MdDescription, value_class=MdDescription, default_py_value=MdDescription()) - _props = ['MdDescription'] + _props = ('MdDescription',) class GetMdState(AbstractGet): NODETYPE = msg.GetMdState action = Actions.GetMdState HandleRef = cp.SubElementHandleRefListProperty(msg.HandleRef) - _props = ['HandleRef'] + _props = ('HandleRef',) class GetMdStateResponse(AbstractGetResponse): NODETYPE = msg.GetMdStateResponse action = Actions.GetMdStateResponse MdState = cp.SubElementProperty(msg.MdState, value_class=MdState, default_py_value=MdState()) - _props = ['MdState'] + _props = ('MdState',) class GetDescriptor(AbstractGet): NODETYPE = msg.GetDescriptor action = Actions.GetDescriptor HandleRef = cp.SubElementHandleRefListProperty(msg.HandleRef) - _props = ['HandleRef'] + _props = ('HandleRef',) class GetDescriptorResponse(AbstractGetResponse): @@ -505,28 +505,28 @@ class GetDescriptorResponse(AbstractGetResponse): cls_getter=get_state_container_class, ns_helper=default_ns_helper ) - _props = ['Descriptor'] + _props = ('Descriptor',) class GetContainmentTree(AbstractGet): NODETYPE = msg.GetContainmentTree action = Actions.GetContainmentTree HandleRef = cp.SubElementHandleRefListProperty(msg.HandleRef) - _props = ['HandleRef'] + _props = ('HandleRef',) class GetContainmentTreeResponse(AbstractGetResponse): NODETYPE = msg.GetContainmentTreeResponse action = Actions.GetContainmentTreeResponse ContainmentTree = cp.SubElementListProperty(msg.ContainmentTree, value_class=ContainmentTree) - _props = ['ContainmentTree'] + _props = ('ContainmentTree',) class GetContextStates(AbstractGet): NODETYPE = msg.GetContextStates action = Actions.GetContextStates HandleRef = cp.SubElementHandleRefListProperty(msg.HandleRef) - _props = ['HandleRef'] + _props = ('HandleRef',) class GetContextStatesResponse(AbstractGetResponse): @@ -537,7 +537,7 @@ class GetContextStatesResponse(AbstractGetResponse): cls_getter=get_state_container_class, ns_helper=default_ns_helper ) - _props = ['ContextState'] + _props = ('ContextState',) class GetContextStatesByIdentification(AbstractGet): @@ -545,7 +545,7 @@ class GetContextStatesByIdentification(AbstractGet): action = Actions.GetContextStatesByIdentification Identification = cp.SubElementListProperty(msg.Identification, value_class=InstanceIdentifier) ContextType = cp.QNameAttributeProperty('ContextType') - _props = ['HandleRef'] + _props = ('HandleRef',) class GetContextStatesByIdentificationResponse(AbstractGetResponse): @@ -556,14 +556,14 @@ class GetContextStatesByIdentificationResponse(AbstractGetResponse): cls_getter=get_state_container_class, ns_helper=default_ns_helper ) - _props = ['ContextState'] + _props = ('ContextState',) class GetContextStatesByFilter(AbstractGet): NODETYPE = msg.GetContextStatesByFilter action = Actions.GetContextStatesByFilter Filter = cp.SubElementStringListProperty(msg.Filter) - _props = ['HandleRef'] + _props = ('HandleRef',) class GetContextStatesByFilterResponse(AbstractGetResponse): @@ -574,7 +574,7 @@ class GetContextStatesByFilterResponse(AbstractGetResponse): cls_getter=get_state_container_class, ns_helper=default_ns_helper ) - _props = ['ContextState'] + _props = ('ContextState',) class GetSupportedLanguages(AbstractGet): @@ -586,7 +586,7 @@ class GetSupportedLanguagesResponse(AbstractGetResponse): NODETYPE = msg.GetSupportedLanguagesResponse action = Actions.GetSupportedLanguagesResponse Lang = cp.SubElementStringListProperty(msg.Lang) - _props = ['Lang'] + _props = ('Lang',) class GetLocalizedText(AbstractGet): @@ -597,14 +597,14 @@ class GetLocalizedText(AbstractGet): Lang = cp.SubElementStringListProperty(msg.Lang) TextWidth = cp.SubElementTextListProperty(msg.TextWidth, value_class=LocalizedTextWidth) NumberOfLines = cp.SubElementTextListProperty(msg.NumberOfLines, value_class=int) - _props = ['Ref', 'Version', 'Lang', 'TextWidth', 'NumberOfLines'] + _props = ('Ref', 'Version', 'Lang', 'TextWidth', 'NumberOfLines') class GetLocalizedTextResponse(AbstractGetResponse): NODETYPE = msg.GetLocalizedTextResponse action = Actions.GetLocalizedTextResponse Text = cp.SubElementListProperty(msg.Text, value_class=LocalizedText) - _props = ['Text'] + _props = ('Text',) class SetContextState(AbstractSet): @@ -614,7 +614,7 @@ class SetContextState(AbstractSet): value_class=AbstractContextStateContainer, cls_getter=get_state_container_class, ns_helper=default_ns_helper) - _props = ['ProposedContextState'] + _props = ('ProposedContextState',) @property def argument(self): @@ -625,7 +625,7 @@ class SetValue(AbstractSet): NODETYPE = msg.SetValue action = Actions.SetValue RequestedNumericValue = cp.NodeTextProperty(msg.RequestedNumericValue, value_converter=DecimalConverter) - _props = ['RequestedNumericValue'] + _props = ('RequestedNumericValue',) @property def argument(self): @@ -636,7 +636,7 @@ class SetString(AbstractSet): NODETYPE = msg.SetString action = Actions.SetString RequestedStringValue = cp.NodeStringProperty(msg.RequestedStringValue) - _props = ['RequestedStringValue'] + _props = ('RequestedStringValue',) @property def argument(self): @@ -650,7 +650,7 @@ class SetAlertState(AbstractSet): value_class=AbstractAlertStateContainer, cls_getter=get_state_container_class, ns_helper=default_ns_helper) - _props = ['ProposedAlertState'] + _props = ('ProposedAlertState',) @property def argument(self): @@ -664,7 +664,7 @@ class SetMetricState(AbstractSet): value_class=AbstractMetricStateContainer, cls_getter=get_state_container_class, ns_helper=default_ns_helper) - _props = ['ProposedMetricState'] + _props = ('ProposedMetricState',) @property def argument(self): @@ -673,14 +673,14 @@ def argument(self): class Argument(PropertyBasedPMType): ArgValue = cp.NodeStringProperty(msg.ArgValue) - _props = ['ArgValue'] + _props = ('ArgValue',) class Activate(AbstractSet): NODETYPE = msg.Activate action = Actions.Activate Argument = cp.SubElementListProperty(msg.Argument, value_class=Argument) - _props = ['Argument'] + _props = ('Argument',) def add_argument(self, arg_value): arg = Argument() @@ -699,7 +699,7 @@ class SetComponentState(AbstractSet): value_class=AbstractDeviceComponentStateContainer, cls_getter=get_state_container_class, ns_helper=default_ns_helper) - _props = ['ProposedComponentState'] + _props = ('ProposedComponentState',) @property def argument(self): diff --git a/src/sdc11073/xml_types/wsd_types.py b/src/sdc11073/xml_types/wsd_types.py index e511c99a..0f7e46d0 100644 --- a/src/sdc11073/xml_types/wsd_types.py +++ b/src/sdc11073/xml_types/wsd_types.py @@ -14,7 +14,7 @@ class QNameListType(struct.NodeTextQNameListProperty): class ScopesType(ElementWithTextList): # text is a URI list MatchBy = struct.AnyURIAttributeProperty('MatchBy') - _props = ['MatchBy'] + _props = ('MatchBy',) def __init__(self, value: Optional[str] = None, match_by: Optional[str] = None): super().__init__() @@ -37,7 +37,7 @@ class HelloType(MessageType): value_class=str, is_optional=True) MetadataVersion = struct.NodeIntProperty(wsd_tag('MetadataVersion'), default_py_value=1) - _props = ['EndpointReference', 'Types', 'Scopes', 'XAddrs', 'MetadataVersion'] + _props = ('EndpointReference', 'Types', 'Scopes', 'XAddrs', 'MetadataVersion') class ByeType(MessageType): @@ -54,7 +54,7 @@ class ByeType(MessageType): value_class=str, is_optional=True) MetadataVersion = struct.NodeIntProperty(wsd_tag('MetadataVersion'), is_optional=True) - _props = ['EndpointReference', 'Types', 'Scopes', 'XAddrs', 'MetadataVersion'] + _props = ('EndpointReference', 'Types', 'Scopes', 'XAddrs', 'MetadataVersion') class ProbeType(MessageType): @@ -64,7 +64,7 @@ class ProbeType(MessageType): Scopes = struct.SubElementProperty(wsd_tag('Scopes'), value_class=ScopesType, is_optional=True) - _props = ['Types', 'Scopes'] + _props = ('Types', 'Scopes') class ProbeMatchType(XMLTypeBase): @@ -79,7 +79,7 @@ class ProbeMatchType(XMLTypeBase): value_class=str, is_optional=True) MetadataVersion = struct.NodeIntProperty(wsd_tag('MetadataVersion'), default_py_value=1) - _props = ['EndpointReference', 'Types', 'Scopes', 'XAddrs', 'MetadataVersion'] + _props = ('EndpointReference', 'Types', 'Scopes', 'XAddrs', 'MetadataVersion') class ProbeMatchesType(MessageType): @@ -87,8 +87,8 @@ class ProbeMatchesType(MessageType): action = f'{default_ns_helper.WSD.namespace}/ProbeMatches' ProbeMatch = struct.SubElementListProperty(wsd_tag('ProbeMatch'), value_class=ProbeMatchType) - _props = ['ProbeMatch'] - additional_namespaces = [default_ns_helper.WSD, default_ns_helper.WSA] + _props = ('ProbeMatch',) + additional_namespaces = (default_ns_helper.WSD, default_ns_helper.WSA) class ResolveType(MessageType): @@ -97,7 +97,7 @@ class ResolveType(MessageType): EndpointReference = struct.SubElementProperty(wsa_tag('EndpointReference'), value_class=EndpointReferenceType, default_py_value=EndpointReferenceType()) - _props = ['EndpointReference'] + _props = ('EndpointReference',) class ResolveMatchType(XMLTypeBase): @@ -112,7 +112,7 @@ class ResolveMatchType(XMLTypeBase): value_class=str, is_optional=True) MetadataVersion = struct.NodeIntProperty(wsd_tag('MetadataVersion'), default_py_value=1) - _props = ['EndpointReference', 'Types', 'Scopes', 'XAddrs', 'MetadataVersion'] + _props = ('EndpointReference', 'Types', 'Scopes', 'XAddrs', 'MetadataVersion') class ResolveMatchesType(MessageType): @@ -121,7 +121,7 @@ class ResolveMatchesType(MessageType): ResolveMatch = struct.SubElementProperty(wsd_tag('ResolveMatch'), value_class=ResolveMatchType, is_optional=True) - _props = ['ResolveMatch'] + _props = ('ResolveMatch',) class AppSequenceType(XMLTypeBase): @@ -130,4 +130,4 @@ class AppSequenceType(XMLTypeBase): InstanceId = struct.IntegerAttributeProperty('InstanceId', is_optional=False) SequenceId = struct.AnyURIAttributeProperty('SequenceId') MessageNumber = struct.IntegerAttributeProperty('MessageNumber', is_optional=False) - _props = ['InstanceId', 'SequenceId', 'MessageNumber'] + _props = ('InstanceId', 'SequenceId', 'MessageNumber') diff --git a/src/sdc11073/xml_types/xml_structure.py b/src/sdc11073/xml_types/xml_structure.py index 6c81583d..f4ee613f 100644 --- a/src/sdc11073/xml_types/xml_structure.py +++ b/src/sdc11073/xml_types/xml_structure.py @@ -1040,6 +1040,11 @@ def __get__(self, instance, owner): # noqa: ANN001 setattr(instance, self._local_var_name, []) return getattr(instance, self._local_var_name) + def __set__(self, instance, py_value): + if isinstance(py_value, tuple): + py_value = list(py_value) + super().__set__(instance, py_value) + def init_instance_data(self, instance: Any): setattr(instance, self._local_var_name, []) diff --git a/tests/test_mdib.py b/tests/test_mdib.py index f56585f9..e47f1fff 100644 --- a/tests/test_mdib.py +++ b/tests/test_mdib.py @@ -5,6 +5,7 @@ from sdc11073.exceptions import ApiUsageError from sdc11073.mdib import ProviderMdib from sdc11073.xml_types.pm_types import Coding +from sdc11073 import definitions_sdc mdib_folder = os.path.dirname(__file__) @@ -16,7 +17,8 @@ class TestMdib(unittest.TestCase): def test_select_descriptors(self): - device_mdib_container = ProviderMdib.from_mdib_file(mdib_70041_path) + device_mdib_container = ProviderMdib.from_mdib_file(mdib_70041_path, + protocol_definition=definitions_sdc.SDC_v1_Definitions) # from looking at the mdib file I know how many elements the tested paths shall return for path, expectedCount in [(('70041',), 1), (('70041', '69650'), 1), # VMDs @@ -33,11 +35,13 @@ def test_mdib_tns(self): # verify that a mdib with participant model as default namespace can be handled. # if creation does not raise any exception, all should be fine. device_mdib_container = ProviderMdib.from_mdib_file( - os.path.join(os.path.dirname(__file__), 'mdib_tns.xml')) + os.path.join(os.path.dirname(__file__), 'mdib_tns.xml'), + protocol_definition=definitions_sdc.SDC_v1_Definitions) self.assertTrue(device_mdib_container is not None) def test_get_metric_descriptor_by_code(self): - device_mdib_container = ProviderMdib.from_mdib_file(mdib_tns_path) + device_mdib_container = ProviderMdib.from_mdib_file(mdib_tns_path, + protocol_definition=definitions_sdc.SDC_v1_Definitions) metric_container = device_mdib_container.get_metric_descriptor_by_code(vmd_code=Coding("130536"), channel_code=Coding("130637"), metric_code=Coding("196174")) @@ -55,7 +59,8 @@ def test_get_metric_descriptor_by_code(self): class TestMdibTransaction(unittest.TestCase): def setUp(self): - self.mdib = ProviderMdib.from_mdib_file(mdib_tns_path) + self.mdib = ProviderMdib.from_mdib_file(mdib_tns_path, + protocol_definition=definitions_sdc.SDC_v1_Definitions) def test_create_delete_descriptor(self): with self.mdib.transaction_manager() as mgr: