Skip to content

Commit 79fc8b4

Browse files
Copilotmedley56
andcommitted
Address code review comments: improve error handling and documentation
Co-authored-by: medley56 <7018964+medley56@users.noreply.github.com>
1 parent 8280b91 commit 79fc8b4

File tree

2 files changed

+42
-17
lines changed

2 files changed

+42
-17
lines changed

space_packet_parser/xtce/containers.py

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ def parse(self, packet: spp.SpacePacket, parameter_lookup: dict[str, parameters.
4343
The packet being parsed
4444
parameter_lookup : dict[str, parameters.Parameter]
4545
Dictionary to look up parameter objects by name
46+
47+
Raises
48+
------
49+
NotImplementedError
50+
If RepeatEntry is specified
51+
KeyError
52+
If the referenced parameter is not found in parameter_lookup
4653
"""
4754
# Check if repeat_entry is specified
4855
if self.repeat_entry is not None:
@@ -55,7 +62,13 @@ def parse(self, packet: spp.SpacePacket, parameter_lookup: dict[str, parameters.
5562
return
5663

5764
# Parse the parameter
58-
parameter = parameter_lookup[self.parameter_ref]
65+
try:
66+
parameter = parameter_lookup[self.parameter_ref]
67+
except KeyError as err:
68+
raise KeyError(
69+
f"Parameter '{self.parameter_ref}' referenced in ParameterRefEntry not found in parameter lookup. "
70+
f"Available parameters: {list(parameter_lookup.keys())}"
71+
) from err
5972
parameter.parse(packet)
6073

6174
@classmethod
@@ -94,29 +107,27 @@ def from_xml(
94107
if (include_cond_elem := element.find("IncludeCondition")) is not None:
95108
# IncludeCondition contains a single MatchCriteria element (Comparison, ComparisonList, or BooleanExpression)
96109
if (comparison_list_elem := include_cond_elem.find("ComparisonList")) is not None:
97-
# Multiple comparisons - create a list of Comparison objects
98-
# All comparisons in a ComparisonList must be true (AND logic)
99-
# We'll store them as individual Comparison objects that will be evaluated separately
100-
# The parse method will need to evaluate all of them
110+
# ComparisonList contains multiple Comparison elements with AND semantics per XTCE spec
111+
# Note: The existing restriction_criteria uses the same pattern (iterfind("*"))
112+
# to iterate over Comparison elements in a ComparisonList
101113
comparisons_list = [
102114
comparisons.Comparison.from_xml(comp) for comp in comparison_list_elem.iterfind("*")
103115
]
104-
# For now, we'll use the first comparison. A proper implementation would need
105-
# a way to represent multiple conditions that all must be true.
106-
# Since the MatchCriteria interface expects a single object, we need a different approach.
107-
# Let's create a simple wrapper that can handle multiple comparisons.
108-
# Actually, looking at the restriction_criteria handling in SequenceContainer,
109-
# they store a list of MatchCriteria. Let's do the same approach here
110-
# by storing just the first one for now, and handle multiple in a future enhancement.
116+
# LIMITATION: MatchCriteria interface expects a single object, but ComparisonList
117+
# requires AND logic across multiple comparisons. For now, we only support single
118+
# comparisons in ComparisonList. Full AND logic would require a new MatchCriteria
119+
# subclass or modifying include_condition to accept a list of MatchCriteria.
120+
# This follows the same limitation pattern used in restriction_criteria where
121+
# multiple MatchCriteria are stored in a list on the SequenceContainer itself.
111122
if len(comparisons_list) == 1:
112123
include_condition = comparisons_list[0]
113124
else:
114-
# For multiple comparisons, we need to create a structure that can evaluate all
115-
# For now, we'll just use the first and warn
125+
# For multiple comparisons, warn and use only the first one
116126
warnings.warn(
117-
f"ComparisonList with {len(comparisons_list)} comparisons in IncludeCondition. "
118-
f"Only the first comparison will be evaluated. Full support for ComparisonList "
119-
f"in IncludeCondition is not yet implemented.",
127+
f"ComparisonList with {len(comparisons_list)} comparisons in IncludeCondition "
128+
f"for parameter '{parameter_ref}'. Only the first comparison will be evaluated. "
129+
f"Full AND logic for ComparisonList in IncludeCondition requires architectural "
130+
f"changes to support multiple MatchCriteria conditions.",
120131
UserWarning,
121132
)
122133
include_condition = comparisons_list[0] if comparisons_list else None

tests/unit/test_xtce/test_include_condition.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,3 +398,17 @@ def test_parameter_ref_entry_from_xml_without_condition():
398398
assert param_ref_entry.parameter_ref == "TestParam"
399399
assert param_ref_entry.include_condition is None
400400
assert param_ref_entry.repeat_entry is None
401+
402+
403+
def test_parameter_ref_entry_undefined_parameter_error():
404+
"""Test that ParameterRefEntry raises informative KeyError for undefined parameter"""
405+
# Create ParameterRefEntry referencing a non-existent parameter
406+
param_ref_entry = containers.ParameterRefEntry(parameter_ref="NonExistentParam")
407+
408+
# Create packet
409+
test_data = struct.pack(">B", 42)
410+
packet = SpacePacket(binary_data=test_data)
411+
412+
# Parse should raise KeyError with helpful message
413+
with pytest.raises(KeyError, match="NonExistentParam.*not found in parameter lookup"):
414+
param_ref_entry.parse(packet, parameter_lookup={})

0 commit comments

Comments
 (0)