From 37cbfb0224e21c52c442f5617c4ff9d9f75efd11 Mon Sep 17 00:00:00 2001 From: Dan Bungert Date: Tue, 25 Jan 2022 13:54:36 -0700 Subject: [PATCH] serializer: fix and test for KeyError '$type' --- subiquity/common/serialize.py | 7 +++++++ subiquity/common/tests/test_serialization.py | 13 +++++++++++++ 2 files changed, 20 insertions(+) diff --git a/subiquity/common/serialize.py b/subiquity/common/serialize.py index 5036fcde..fc019585 100644 --- a/subiquity/common/serialize.py +++ b/subiquity/common/serialize.py @@ -194,6 +194,13 @@ class Serializer: args = {} fields = {field.name: field for field in attr.fields(annotation)} for key in value.keys(): + if key not in fields and key == '$type': + # Union types can contain a '$type' field that is not + # actually one of the keys. This happens if a object is + # serialized as part of a Union, sent to an API caller, + # then received back on a different endpoint that isn't a + # Union. + continue args.update(self._deserialize_field( fields[key], value[key], path)) return annotation(**args) diff --git a/subiquity/common/tests/test_serialization.py b/subiquity/common/tests/test_serialization.py index e518bca1..418f7ad2 100644 --- a/subiquity/common/tests/test_serialization.py +++ b/subiquity/common/tests/test_serialization.py @@ -156,6 +156,19 @@ class TestSerializer(CommonSerializerTests, unittest.TestCase): } self.assertSerialization(typing.Union[Data, Container], data, expected) + def test_arbitrary_types_may_have_type_field(self): + # The serializer will add a $type field to data elements in a Union. + # If we then take that serialized value and fling it back to another + # API entrypoint, one that isn't taking a Union, it must be cool with + # the excess $type field. + data = { + '$type': 'Data', + 'field1': '1', + 'field2': 2, + } + expected = Data(field1='1', field2=2) + self.assertDeserializesTo(Data, data, expected) + class TestCompactSerializer(CommonSerializerTests, unittest.TestCase):