From 2150f863e992159ef719fa6c7c3ee11b2f30cfda Mon Sep 17 00:00:00 2001 From: gaoflow Date: Thu, 4 Jun 2026 17:45:35 +0200 Subject: [PATCH] Fix XSD type name mapping for UnsignedInt and UnsignedByte XSD_TYPE_NAMES mapped UnsignedInt to "unsignedByte" and had no entry for UnsignedByte. Since XSD_TYPE_CLASSES is the inverse, deserializing a value with valueType "xs:unsignedInt" raised KeyError, and "xs:unsignedByte" resolved to UnsignedInt instead of UnsignedByte. Map each type to its own XSD name. Fixes #560. Signed-off-by: gaoflow --- sdk/basyx/aas/model/datatypes.py | 3 ++- sdk/test/model/test_datatypes.py | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/sdk/basyx/aas/model/datatypes.py b/sdk/basyx/aas/model/datatypes.py index d5acc6d45..398877d5a 100644 --- a/sdk/basyx/aas/model/datatypes.py +++ b/sdk/basyx/aas/model/datatypes.py @@ -397,8 +397,9 @@ def from_string(cls, value: str) -> "NormalizedString": NonNegativeInteger: "nonNegativeInteger", PositiveInteger: "positiveInteger", UnsignedLong: "unsignedLong", + UnsignedInt: "unsignedInt", UnsignedShort: "unsignedShort", - UnsignedInt: "unsignedByte", + UnsignedByte: "unsignedByte", AnyURI: "anyURI", String: "string", NormalizedString: "normalizedString", diff --git a/sdk/test/model/test_datatypes.py b/sdk/test/model/test_datatypes.py index b83c5e5fb..5c4f0827c 100644 --- a/sdk/test/model/test_datatypes.py +++ b/sdk/test/model/test_datatypes.py @@ -79,6 +79,21 @@ def test_trivial_cast(self) -> None: model.datatypes.trivial_cast("17", model.datatypes.Int) self.assertEqual("'17' cannot be trivially casted into Int", str(cm_2.exception)) + def test_xsd_type_name_mapping(self) -> None: + # UnsignedInt was mapped to "xs:unsignedByte" and UnsignedByte was + # missing entirely, so deserializing valueType "xs:unsignedInt" raised + # KeyError and "xs:unsignedByte" resolved to the wrong class (#560). + self.assertEqual("xs:unsignedInt", model.datatypes.XSD_TYPE_NAMES[model.datatypes.UnsignedInt]) + self.assertEqual("xs:unsignedByte", model.datatypes.XSD_TYPE_NAMES[model.datatypes.UnsignedByte]) + self.assertIs(model.datatypes.UnsignedInt, model.datatypes.XSD_TYPE_CLASSES["xs:unsignedInt"]) + self.assertIs(model.datatypes.UnsignedByte, model.datatypes.XSD_TYPE_CLASSES["xs:unsignedByte"]) + + # XSD_TYPE_CLASSES is the inverse of XSD_TYPE_NAMES; every type must + # round-trip, which also guarantees the names are unique. + for type_, name in model.datatypes.XSD_TYPE_NAMES.items(): + self.assertIs(type_, model.datatypes.XSD_TYPE_CLASSES[name]) + self.assertEqual(len(model.datatypes.XSD_TYPE_NAMES), len(model.datatypes.XSD_TYPE_CLASSES)) + class TestStringTypes(unittest.TestCase): def test_normalized_string(self) -> None: