From e626e4ec4003c5d58428afacb8c1aad99934b1c7 Mon Sep 17 00:00:00 2001 From: Chris Talkington Date: Sat, 18 May 2024 17:27:30 -0500 Subject: [PATCH] Parse more enums to python enums (#573) --- src/pyipp/enums.py | 22 +++++--- src/pyipp/parser.py | 29 ++++++----- tests/__snapshots__/test_parser.ambr | 78 ++++++++++++++-------------- 3 files changed, 71 insertions(+), 58 deletions(-) diff --git a/src/pyipp/enums.py b/src/pyipp/enums.py index e77cf569..64a05bbe 100644 --- a/src/pyipp/enums.py +++ b/src/pyipp/enums.py @@ -312,11 +312,19 @@ class IppOrientationRequested(IntEnum): ATTRIBUTE_ENUM_MAP = { - "document-state": IppDocumentState, - "finishings": IppFinishing, - "job-state": IppJobState, - "orientation-requested": IppOrientationRequested, - "printer-state": IppPrinterState, - "print-quality": IppPrintQuality, - "status-code": IppStatus, + "document-state": IppDocumentState, # PWG5100.5 + "finishings": IppFinishing, # RFC8011 + "finishings-default": IppFinishing, # RFC8011 + "finishings-supported": IppFinishing, # RFC8011 + "job-state": IppJobState, # RFC8011 + "media-source-feed-orientation": IppOrientationRequested, # PWG5100.7 + "operations-supported": IppOperation, # RFC8011 + "orientation-requested": IppOrientationRequested, # RFC8011 + "orientation-requested-default": IppOrientationRequested, # RFC8011 + "orientation-requested-supported": IppOrientationRequested, # RFC8011 + "printer-state": IppPrinterState, # RFC8011 + "print-quality": IppPrintQuality, # RFC8011 + "print-quality-default": IppPrintQuality, # RFC8011 + "print-quality-supported": IppPrintQuality, # RFC8011 + "status-code": IppStatus, # RFC8011 } diff --git a/src/pyipp/parser.py b/src/pyipp/parser.py index 42d6e164..7beecfb9 100644 --- a/src/pyipp/parser.py +++ b/src/pyipp/parser.py @@ -39,32 +39,33 @@ def parse_ieee1284_device_id(device_id: str) -> dict[str, str]: def parse_collection(data: bytes, offset: int) -> tuple[dict[str, Any], int]: """Parse member attributes from IPP collection.""" collection_data: dict[str, Any] = {} - member_name: str = "unknown" + member_name: str = "" _LOGGER.debug("#BeginCollectionOffset: %s", offset) + while struct.unpack_from("b", data, offset)[0] != IppTag.END_COLLECTION.value: - attribute, new_offset = parse_attribute(data, offset) + attribute, next_attr_offset = parse_attribute(data, offset, member_name) if attribute["tag"] == IppTag.MEMBER_NAME.value: member_name = attribute["value"] - else: + elif member_name: collection_data[member_name] = attribute["value"] - offset = new_offset - - next_attribute, next_attr_offset = parse_attribute(data, offset) - if next_attribute["tag"] == IppTag.END_COLLECTION.value: offset = next_attr_offset - _LOGGER.debug("#EndCollectionOffset: %s", new_offset) + _LOGGER.debug("#EndCollectionOffset: %s", offset) - return collection_data, offset + # skip over end of collection marker + _, next_attr_offset = parse_attribute(data, offset) + + return collection_data, next_attr_offset # pylint: disable=R0912,R0915 def parse_attribute( # noqa: PLR0912, PLR0915 data: bytes, offset: int, + prev_attr_name: str = "", ) -> tuple[dict[str, Any], int]: """Parse attribute from IPP data. @@ -86,6 +87,8 @@ def parse_attribute( # noqa: PLR0912, PLR0915 attribute["name"] = data[offset:offset_length].decode("utf-8") offset += attribute["name-length"] + resolved_attr_name = attribute["name"] or prev_attr_name + if attribute["name"]: _LOGGER.debug( "Attribute Name: %s (%s)", attribute["name"], hex(attribute["tag"]), @@ -104,9 +107,9 @@ def parse_attribute( # noqa: PLR0912, PLR0915 if ( attribute["tag"] == IppTag.ENUM.value - and attribute["name"] in ATTRIBUTE_ENUM_MAP + and resolved_attr_name in ATTRIBUTE_ENUM_MAP ): - enum_class = ATTRIBUTE_ENUM_MAP[attribute["name"]] + enum_class = ATTRIBUTE_ENUM_MAP[resolved_attr_name] attribute["value"] = enum_class(attribute["value"]) offset += 4 @@ -287,7 +290,9 @@ def parse( # noqa: PLR0912, PLR0915 attribute_key = "unsupported-attributes" offset += 1 - attribute, new_offset = parse_attribute(raw_data, offset) + attribute, new_offset = parse_attribute( + raw_data, offset, previous_attribute_name, + ) # if attribute has a name -> add it # if attribute doesn't have a name -> it is part of an array diff --git a/tests/__snapshots__/test_parser.ambr b/tests/__snapshots__/test_parser.ambr index a8b238d5..79141e0a 100644 --- a/tests/__snapshots__/test_parser.ambr +++ b/tests/__snapshots__/test_parser.ambr @@ -27,8 +27,8 @@ 'image/urf', 'image/jpeg', ]), - 'finishings-default': 3, - 'finishings-supported': 3, + 'finishings-default': , + 'finishings-supported': , 'generated-natural-language-supported': 'de', 'identify-actions-default': list([ 'flash', @@ -135,7 +135,7 @@ 'media-source': 'main', 'media-source-properties': dict({ 'media-source-feed-direction': 'long-edge-first', - 'media-source-feed-orientation': 5, + 'media-source-feed-orientation': , }), 'media-top-margin': 300, 'media-type': 'stationery', @@ -152,7 +152,7 @@ 'media-source': 'main', 'media-source-properties': dict({ 'media-source-feed-direction': 'long-edge-first', - 'media-source-feed-orientation': 5, + 'media-source-feed-orientation': , }), 'media-top-margin': 300, 'media-type': 'stationery', @@ -168,7 +168,7 @@ 'media-source': 'main', 'media-source-properties': dict({ 'media-source-feed-direction': 'long-edge-first', - 'media-source-feed-orientation': 5, + 'media-source-feed-orientation': , }), 'media-top-margin': 0, 'media-type': 'stationery', @@ -320,20 +320,20 @@ 'multiple-operation-time-out': 150, 'natural-language-configured': 'de', 'operations-supported': list([ - 2, - 4, - 5, - 6, - 8, - 9, - 10, - 11, - 60, - ]), - 'orientation-requested-default': 3, + , + , + , + , + , + , + , + , + , + ]), + 'orientation-requested-default': , 'orientation-requested-supported': list([ - 3, - 4, + , + , ]), 'output-bin-default': 'face-up', 'output-bin-supported': 'face-up', @@ -355,10 +355,10 @@ ]), 'print-content-optimize-default': 'auto', 'print-content-optimize-supported': 'auto', - 'print-quality-default': 4, + 'print-quality-default': , 'print-quality-supported': list([ - 4, - 5, + , + , ]), 'print-scaling-default': 'auto', 'print-scaling-supported': list([ @@ -481,8 +481,8 @@ 'copies', 'sides', ]), - 'finishings-default': 3, - 'finishings-supported': 3, + 'finishings-default': , + 'finishings-supported': , 'generated-natural-language-supported': 'en', 'identify-actions-default': 'flash', 'identify-actions-supported': 'flash', @@ -766,19 +766,19 @@ 'multiple-operation-time-out-action': 'abort-job', 'natural-language-configured': 'en', 'operations-supported': list([ - 2, - 4, - 5, - 6, - 8, - 9, - 10, - 11, - 59, - 60, - ]), - 'orientation-requested-default': 3, - 'orientation-requested-supported': 3, + , + , + , + , + , + , + , + , + , + , + ]), + 'orientation-requested-default': , + 'orientation-requested-supported': , 'output-bin-default': 'face-up', 'output-bin-supported': 'face-up', 'pages-per-minute': 9, @@ -795,10 +795,10 @@ ]), 'print-content-optimize-default': 'auto', 'print-content-optimize-supported': 'auto', - 'print-quality-default': 4, + 'print-quality-default': , 'print-quality-supported': list([ - 4, - 5, + , + , ]), 'print-scaling-default': 'auto', 'print-scaling-supported': list([