space_packet_parser.common ========================== .. py:module:: space_packet_parser.common .. autoapi-nested-parse:: Common mixins Attributes ---------- .. autoapisummary:: space_packet_parser.common.logger space_packet_parser.common.BuiltinDataTypes space_packet_parser.common.ParameterDataTypes Classes ------- .. autoapisummary:: space_packet_parser.common.NamespaceAwareElement space_packet_parser.common.AttrComparable space_packet_parser.common.XmlObject space_packet_parser.common.Parseable space_packet_parser.common._Parameter space_packet_parser.common.BinaryParameter space_packet_parser.common.BoolParameter space_packet_parser.common.FloatParameter space_packet_parser.common.IntParameter space_packet_parser.common.StrParameter space_packet_parser.common.SpacePacket Functions --------- .. autoapisummary:: space_packet_parser.common._extract_bits Module Contents --------------- .. py:data:: logger .. py:class:: NamespaceAwareElement Bases: :py:obj:`lxml.etree.ElementBase` Custom element that automatically applies namespace mappings. .. py:attribute:: _nsmap :type: dict[str, str] .. py:attribute:: _ns_prefix :type: str | None :value: None .. py:method:: element_prefix() :classmethod: Create the XPath element prefix .. rubric:: Notes If the prefix is None, it indicates either an implicit namespace such as ``, where `nsmap` is `{None: "http://xtce-example-ns-uri", ...}` or no namespace awareness, such as ``, where `nsmap` does not contain any reference to a URI or prefix for the XTCE namespace (but may contain other namespace mappings). If the prefix is anything other than None, it must be a string and must be present in the namespace mapping dict and represents a prefixed namespace, such as `` where `nsmap` would be `{"xtce": "http://xtce-example-ns-uri", ...}` and `ns_prefix` would be `xtce`. .. py:method:: add_namespace_to_xpath(xpath: str) -> str :classmethod: Adds a namespace prefix to each element in an XPath expression. :param xpath: The original XPath expression without namespace prefixes. :type xpath: str :returns: The updated XPath expression with namespace prefixes. :rtype: str .. py:method:: find(path, namespaces=None) Override find() to automatically use the stored namespace map. .. py:method:: findall(path, namespaces=None) Override findall() to automatically use the stored namespace map. .. py:method:: iterfind(path, namespaces=None) Override iterfind() to automatically use the stored namespace map. .. py:method:: set_nsmap(nsmap: dict) :classmethod: Store the namespace map for all elements of this type. .. py:method:: get_nsmap() Retrieve the stored namespace map. .. py:method:: set_ns_prefix(ns_prefix: str | None) :classmethod: Store the namespace map for all elements of this type. .. py:method:: get_ns_prefix() Retrieve the stored namespace map. .. py:class:: AttrComparable Generic class that provides a notion of equality based on all non-callable, non-dunder attributes .. py:method:: __eq__(other) .. py:class:: XmlObject ABC that requires `to_xml_element` and `from_xml_element` methods for parsing and serializing a library object from an XML element object. .. py:method:: from_xml(element: lxml.etree.Element, *, tree: lxml.etree.ElementTree | None, parameter_lookup: dict[str, any] | None, parameter_type_lookup: dict[str, any] | None, container_lookup: dict[str, any] | None) -> XmlObject :classmethod: :abstractmethod: Create an object from an XML element .. rubric:: Notes This abstract implementation has a signature that includes all possible parameters to this function across our XML object classes in order to satisfy Liskov Substitution. It also makes it clear that you _can_ pass this information in to from_xml but depending on the subtype implementation, it may be ignored. :param element: XML element from which to parse the object :type element: ElementTree.Element :param tree: Full XML tree for parsing that requires access to other elements :type tree: Optional[ElementTree.ElementTree] :param parameter_lookup: Parameters dict for parsing that requires knowledge of existing parameters :type parameter_lookup: Optional[dict[str, parameters.ParameterType]] :param parameter_type_lookup: Parameter type dict for parsing that requires knowledge of existing parameter types :type parameter_type_lookup: Optional[dict[str, parameters.ParameterType]] :param container_lookup: Container type dict for parsing that requires knowledge of existing containers :type container_lookup: Optional[dict[str, parameters.ContainerType]] :rtype: cls .. py:method:: to_xml(*, elmaker: lxml.builder.ElementMaker) -> lxml.etree.Element :abstractmethod: Create an XML element from the object self :param elmaker: ElementMaker for creating new XML elements with predefined namespace :type elmaker: ElementMaker :returns: XML Element object :rtype: ElementTree.Element .. py:class:: Parseable Bases: :py:obj:`Protocol` Defines an object that can be parsed from packet data. .. py:method:: parse(packet: SpacePacket) -> None Parse this entry from the packet data and add the necessary items to the packet. .. py:data:: BuiltinDataTypes .. py:class:: _Parameter Mixin class for storing access to the raw value of a parsed data item. The raw value is the closest representation of the data item as it appears in the packet. e.g. bytes for binary data, int for integer data, etc. It has not been calibrated or adjusted in any way and is an easy way for user's to debug the transformations that happened after the fact. .. rubric:: Notes We need to override the __new__ method to store the raw value of the data item on immutable built-in types. So this is just a way of allowing us to inject our own attribute into the built-in types. .. py:class:: BinaryParameter Bases: :py:obj:`_Parameter`, :py:obj:`bytes` A class to represent a binary data item. .. py:class:: BoolParameter Bases: :py:obj:`_Parameter`, :py:obj:`int` A class to represent a parsed boolean data item. .. py:method:: __repr__() -> str Return repr(self). .. py:class:: FloatParameter Bases: :py:obj:`_Parameter`, :py:obj:`float` A class to represent a float data item. .. py:class:: IntParameter Bases: :py:obj:`_Parameter`, :py:obj:`int` A class to represent a integer data item. .. py:class:: StrParameter Bases: :py:obj:`_Parameter`, :py:obj:`str` A class to represent a string data item. .. py:data:: ParameterDataTypes .. py:class:: SpacePacket(*args, binary_data: bytes = b'', **kwargs) Bases: :py:obj:`dict` Packet representing parsed data items. Container that stores the binary packet data (bytes) as an instance attribute and the parsed data items in a dictionary interface. A ``SpacePacket`` generally begins as an empty dictionary that gets filled as the packet is parsed. To access the raw bytes of the packet, use the ``SpacePacket.binary_data`` attribute. :param \*args: Initial items to store in the packet, passed to the dict() constructor. :type \*args: Mapping or Iterable :param binary_data: The binary data for a single packet as a bytes object / subclass. This binary data is stored and used for parsing the data items. Internally we are tracking the parsing position within this binary_data object and trying to read specific bit ranges from it. :type binary_data: bytes, optional :param \*\*kwargs: Additional packet items to store, passed to the dict() constructor. :type \*\*kwargs: dict .. py:attribute:: binary_data :value: b'' .. py:attribute:: _parsing_pos :value: 0 .. py:property:: header :type: dict The header content of the packet. .. py:property:: user_data :type: dict The user data content of the packet. .. py:property:: raw_data :type: bytes The raw binary data of the packet. .. py:method:: _read_from_binary_as_bytes(nbits: int) -> bytes Read a number of bits from the binary packet data as bytes. Reads the minimum number of complete bytes required to capture `nbits`. Moves `_parsing_pos` cursor `nbits` forward, even if `nbits` is not an integer number of bytes. :param nbits: Number of bits to read :type nbits: int :returns: Raw bytes from the packet data :rtype: bytes .. py:method:: _read_from_binary_as_int(nbits: int) -> int Read a number of bits from the binary packet data as an integer. :param nbits: Number of bits to read :type nbits: int :returns: Integer representation of the bits read from the packet :rtype: int .. py:function:: _extract_bits(data: bytes, start_bit: int, nbits: int) Extract nbits from the data starting from the least significant end. If data = 00110101 11001010, start_bit = 2, nbits = 9, then the bits extracted are "110101110". Those bits are turned into a Python integer and returned. :param data: Data to extract bits from :type data: bytes :param start_bit: Starting bit location within the data :type start_bit: int :param nbits: Number of bits to extract :type nbits: int :returns: Extracted bits as an integer :rtype: int