diff --git a/hl7/containers.py b/hl7/containers.py index 1b1626b..73ace74 100644 --- a/hl7/containers.py +++ b/hl7/containers.py @@ -742,12 +742,26 @@ def assign_field( while len(field) < repeat_num: field.append(self.create_repetition([])) repetition = field(repeat_num) + if not isinstance(repetition, Repetition): + # A non-repeating field stores its value as a bare string. Promote + # it to a Repetition so it can be addressed at the component or + # subcomponent level instead of raising a TypeError. + repetition = self.create_repetition( + [repetition] if repetition != "" else [] + ) + field(repeat_num, repetition) if component_num is None: repetition[:] = [value] return while len(repetition) < component_num: repetition.append(self.create_component([])) component = repetition(component_num) + if not isinstance(component, Component): + # Likewise, a single-component repetition stores a bare string. + component = self.create_component( + [component] if component != "" else [] + ) + repetition(component_num, component) if subcomponent_num is None: component[:] = [value] return diff --git a/tests/test_parse.py b/tests/test_parse.py index 39cc786..faa0a25 100644 --- a/tests/test_parse.py +++ b/tests/test_parse.py @@ -356,6 +356,27 @@ def test_assign(self): self.assertEqual(msg2["MSH.21.1.1"], "COMPONENT 21.1.1") self.assertEqual(msg2["MSH.21.1.2.4"], "SUBCOMPONENT 21.1.2.4") + def test_assign_deeper_into_simple_field(self): + # Regression for #55: assigning into a field/repetition that was parsed + # as a bare string must promote it to a container rather than raising + # "TypeError: 'str' object does not support item assignment". + sample = "MSH|^~\\&|field|rep1~rep2|" + + # repetition level (the reported case) + seg = hl7.parse(sample).segments("MSH")[0] + seg.assign_field("NewRep", 3, 1) + self.assertEqual(str(seg(3)), "NewRep") + + # component level keeps the existing value as the first component + seg = hl7.parse(sample).segments("MSH")[0] + seg.assign_field("X", 3, 1, 2) + self.assertEqual(str(seg(3)), "field^X") + + # subcomponent level into a single-component repetition + seg = hl7.parse(sample).segments("MSH")[0] + seg.assign_field("Y", 4, 1, 1, 2) + self.assertEqual(str(seg(4)), "rep1&Y~rep2") + def test_unescape(self): msg = hl7.parse(rep_sample_hl7)