From 4fa4ad1dcb816acd692b1a6c795dd15d557c8c52 Mon Sep 17 00:00:00 2001 From: Marko Ristin-Kaufmann Date: Thu, 29 Oct 2026 23:10:45 +0100 Subject: [PATCH] Update to aas-core-meta c5f6c49 We update the meta-model to aas-core-meta c5f6c49 and re-generate the code. Notably, the literals of ``Level`` and ``Extent`` now follow the spelling of the Part 2 OpenAPI schema (``deep``, ``core``, ``withoutBlobValue`` and ``withBlobValue``) instead of the spelling in the book prose (``Deep``, ``Core``, ``WithoutBLOBValue`` and ``WithBLOBValue``), since the servers, such as BaSyx, accept only the former. Moreover, the created-at of the administrative information can now be equal to its updated-at. Previously, created-at had to be strictly before updated-at, which was against the book. --- aas_core3_2/stringification.py | 8 +-- aas_core3_2/types.py | 23 ++++++-- aas_core3_2/verification.py | 27 +++++---- dev/dev_scripts/codegen/meta_model.py | 55 +++++++++++++------ .../revision.json.errors | 1 - .../templateId.json.errors | 1 - .../version.json.errors | 1 - .../embeddedDataSpecifications.json.errors | 1 - .../revision.json.errors | 1 - .../templateId.json.errors | 1 - .../version.json.errors | 1 - dev/tests/test_jsonization_of_enums.py | 4 +- 12 files changed, 77 insertions(+), 47 deletions(-) diff --git a/aas_core3_2/stringification.py b/aas_core3_2/stringification.py index 15c4d9e..2962944 100644 --- a/aas_core3_2/stringification.py +++ b/aas_core3_2/stringification.py @@ -572,8 +572,8 @@ def execution_state_from_str(text: str) -> Optional[our_types.ExecutionState]: _LEVEL_FROM_STR: Mapping[str, our_types.Level] = { - "Deep": our_types.Level.DEEP, - "Core": our_types.Level.CORE, + "deep": our_types.Level.DEEP, + "core": our_types.Level.CORE, } @@ -619,8 +619,8 @@ def content_from_str(text: str) -> Optional[our_types.Content]: _EXTENT_FROM_STR: Mapping[str, our_types.Extent] = { - "WithoutBLOBValue": our_types.Extent.WITHOUT_BLOB_VALUE, - "WithBLOBValue": our_types.Extent.WITH_BLOB_VALUE, + "withoutBlobValue": our_types.Extent.WITHOUT_BLOB_VALUE, + "withBlobValue": our_types.Extent.WITH_BLOB_VALUE, } diff --git a/aas_core3_2/types.py b/aas_core3_2/types.py index 1e3054b..79f8940 100644 --- a/aas_core3_2/types.py +++ b/aas_core3_2/types.py @@ -8922,6 +8922,13 @@ class Level(enum.Enum): See: https://industrialdigitaltwin.io/aas-specifications/IDTA-01002/v3.2/specification/interfaces-operation-parameters.html#SerializationModifier + + .. note:: + + We follow the spelling of the literals in the Part 2 OpenAPI schema + (Part2-API-Schemas/openapi.yaml), ``deep`` and ``core``, rather than + the spelling in the book prose, since the servers, such as BaSyx, accept + only the former. """ #: All elements of a requested hierarchy level and all children on all @@ -8932,11 +8939,11 @@ class Level(enum.Enum): #: SubmodelElementCollections or SubmodelElementLists, the 'statements' #: field of Entities, or the 'annotations' field of #: AnnotatedRelationshipElements. - DEEP = "Deep" + DEEP = "deep" #: Only elements of a requested hierarchy level as well as direct children #: are returned. By this, a client can iterate the hierarchy step by step. - CORE = "Core" + CORE = "core" class Content(enum.Enum): @@ -8976,16 +8983,24 @@ class Extent(enum.Enum): See: https://industrialdigitaltwin.io/aas-specifications/IDTA-01002/v3.2/specification/interfaces-operation-parameters.html#SerializationModifier + + .. note:: + + We follow the spelling of the literals in the Part 2 OpenAPI schema + (Part2-API-Schemas/openapi.yaml), ``withoutBlobValue`` and + ``withBlobValue``, rather than the spelling in the book prose, such as + ``WithBLOBValue``, since the servers, such as BaSyx, accept only + the former. """ #: Only applicable to BLOB-elements; the BLOB content is not returned. #: #: This is the default value. - WITHOUT_BLOB_VALUE = "WithoutBLOBValue" + WITHOUT_BLOB_VALUE = "withoutBlobValue" #: Only applicable to BLOB-elements; the BLOB content is returned as #: base64-encoded string. - WITH_BLOB_VALUE = "WithBLOBValue" + WITH_BLOB_VALUE = "withBlobValue" class PagedResult(Class): diff --git a/aas_core3_2/verification.py b/aas_core3_2/verification.py index 8cf1b79..5aed5d9 100644 --- a/aas_core3_2/verification.py +++ b/aas_core3_2/verification.py @@ -744,25 +744,28 @@ def date_time_utc_less(that: str, other: str) -> Optional[bool]: return less -def date_time_utc_less_or_invalid(that: str, other: str) -> bool: +def date_time_utc_less_or_equal_or_invalid(that: str, other: str) -> bool: """ - Check that the date-time :paramref:`that` is before :paramref:`other`, unless - either of them is invalid. + Check that the date-time :paramref:`that` is before or at the same instant as + :paramref:`other`, unless either of them is invalid. The invalid date-times are reported by the invariants of ``DateTimeUTC``, so that we do not report them twice. See :py:func:`date_time_utc_less`. - :param that: Date-time which is expected to come first - :param other: Date-time which is expected to come later + :param that: + Date-time which is expected to come first or at the same instant + :param other: + Date-time which is expected to come later or at the same instant :return: - True if :paramref:`that` is before :paramref:`other`, or if either of - them is not a valid ``xs:dateTime`` in UTC + True if :paramref:`that` is before or at the same instant as + :paramref:`other`, or if either of them is not a valid ``xs:dateTime`` + in UTC """ - less = date_time_utc_less(that, other) - if less is None: + other_less = date_time_utc_less(other, that) + if other_less is None: return True - return less + return not other_less # noinspection SpellCheckingInspection @@ -2692,9 +2695,9 @@ def transform_administrative_information( if not ( not (((that.created_at is not None) and (that.updated_at is not None))) - or date_time_utc_less_or_invalid(that.created_at, that.updated_at) + or date_time_utc_less_or_equal_or_invalid(that.created_at, that.updated_at) ): - yield Error("Created-at must be before updated-at.") + yield Error("Created-at must be before or equal to updated-at.") if not (not (that.revision is not None) or (that.version is not None)): yield Error( diff --git a/dev/dev_scripts/codegen/meta_model.py b/dev/dev_scripts/codegen/meta_model.py index a25885c..224938a 100644 --- a/dev/dev_scripts/codegen/meta_model.py +++ b/dev/dev_scripts/codegen/meta_model.py @@ -1,4 +1,4 @@ -# Downloaded from: https://raw.githubusercontent.com/eclipse-aascw/aas-core-meta/63cbfd368a915a6696c6dec5b455dd5430ba652a/aas_core_meta/v3_2.py +# Downloaded from: https://raw.githubusercontent.com/eclipse-aascw/aas-core-meta/c5f6c49c227bc199980924e6a5c42d3632ea7051/aas_core_meta/v3_2.py """ --- WORK IN PROGRESS --- Provide an implementation of the Asset Administration Shell (AAS) V3.2. @@ -814,26 +814,30 @@ def date_time_UTC_less(that: str, other: str) -> Optional[bool]: @verification -def date_time_UTC_less_or_invalid(that: str, other: str) -> bool: +def date_time_UTC_less_or_equal_or_invalid(that: str, other: str) -> bool: """ - Check that the date-time :paramref:`that` is before :paramref:`other`, unless - either of them is invalid. + Check that the date-time :paramref:`that` is before or at the same instant as + :paramref:`other`, unless either of them is invalid. The invalid date-times are reported by the invariants of :class:`Date_time_UTC`, so that we do not report them twice. See :func:`date_time_UTC_less`. - :param that: Date-time which is expected to come first - :param other: Date-time which is expected to come later + :param that: Date-time which is expected to come first or at the same instant + :param other: Date-time which is expected to come later or at the same instant :returns: - True if :paramref:`that` is before :paramref:`other`, or if either of - them is not a valid ``xs:dateTime`` in UTC + True if :paramref:`that` is before or at the same instant as + :paramref:`other`, or if either of them is not a valid ``xs:dateTime`` + in UTC """ - less = date_time_UTC_less(that, other) - if less is None: + # NOTE (mristin): + # The date-time :paramref:`that` is before or at the same instant as + # :paramref:`other` if and only if :paramref:`other` is not before it. + other_less = date_time_UTC_less(other, that) + if other_less is None: return True - return less + return not other_less # noinspection SpellCheckingInspection @@ -2715,8 +2719,8 @@ def __init__( @invariant( lambda self: not (self.created_at is not None and self.updated_at is not None) - or date_time_UTC_less_or_invalid(self.created_at, self.updated_at), - "Created-at must be before updated-at." + or date_time_UTC_less_or_equal_or_invalid(self.created_at, self.updated_at), + "Created-at must be before or equal to updated-at." ) # fmt: on class Administrative_information(Has_data_specification): @@ -8899,9 +8903,16 @@ class Level(Enum): See: https://industrialdigitaltwin.io/aas-specifications/IDTA-01002/v3.2/specification/interfaces-operation-parameters.html#SerializationModifier + + .. note:: + + We follow the spelling of the literals in the Part 2 OpenAPI schema + (Part2-API-Schemas/openapi.yaml), ``deep`` and ``core``, rather than + the spelling in the book prose, since the servers, such as BaSyx, accept + only the former. """ - Deep = "Deep" + Deep = "deep" """ All elements of a requested hierarchy level and all children on all sublevels are returned. @@ -8913,7 +8924,7 @@ class Level(Enum): AnnotatedRelationshipElements. """ - Core = "Core" + Core = "core" """ Only elements of a requested hierarchy level as well as direct children are returned. By this, a client can iterate the hierarchy step by step. @@ -8965,16 +8976,24 @@ class Extent(Enum): See: https://industrialdigitaltwin.io/aas-specifications/IDTA-01002/v3.2/specification/interfaces-operation-parameters.html#SerializationModifier + + .. note:: + + We follow the spelling of the literals in the Part 2 OpenAPI schema + (Part2-API-Schemas/openapi.yaml), ``withoutBlobValue`` and + ``withBlobValue``, rather than the spelling in the book prose, such as + ``WithBLOBValue``, since the servers, such as BaSyx, accept only + the former. """ - Without_blob_value = "WithoutBLOBValue" + Without_blob_value = "withoutBlobValue" """ Only applicable to BLOB-elements; the BLOB content is not returned. This is the default value. """ - With_blob_value = "WithBLOBValue" + With_blob_value = "withBlobValue" """ Only applicable to BLOB-elements; the BLOB content is returned as base64-encoded string. @@ -12291,4 +12310,4 @@ def __init__( # endregion Part 2 -# Downloaded from: https://raw.githubusercontent.com/eclipse-aascw/aas-core-meta/63cbfd368a915a6696c6dec5b455dd5430ba652a/aas_core_meta/v3_2.py +# Downloaded from: https://raw.githubusercontent.com/eclipse-aascw/aas-core-meta/c5f6c49c227bc199980924e6a5c42d3632ea7051/aas_core_meta/v3_2.py diff --git a/dev/test_data/VerificationError/Json/Unexpected/Invalid/MaxLengthViolation/AdministrativeInformation/revision.json.errors b/dev/test_data/VerificationError/Json/Unexpected/Invalid/MaxLengthViolation/AdministrativeInformation/revision.json.errors index 50f4be9..b7768ed 100644 --- a/dev/test_data/VerificationError/Json/Unexpected/Invalid/MaxLengthViolation/AdministrativeInformation/revision.json.errors +++ b/dev/test_data/VerificationError/Json/Unexpected/Invalid/MaxLengthViolation/AdministrativeInformation/revision.json.errors @@ -1,2 +1 @@ -: Created-at must be before updated-at. .revision: Revision type shall have a maximum length of 4 characters. diff --git a/dev/test_data/VerificationError/Json/Unexpected/Invalid/MaxLengthViolation/AdministrativeInformation/templateId.json.errors b/dev/test_data/VerificationError/Json/Unexpected/Invalid/MaxLengthViolation/AdministrativeInformation/templateId.json.errors index d1e6a5a..d7c85ff 100644 --- a/dev/test_data/VerificationError/Json/Unexpected/Invalid/MaxLengthViolation/AdministrativeInformation/templateId.json.errors +++ b/dev/test_data/VerificationError/Json/Unexpected/Invalid/MaxLengthViolation/AdministrativeInformation/templateId.json.errors @@ -1,2 +1 @@ -: Created-at must be before updated-at. .template_id: Identifier shall have a maximum length of 2048 characters. diff --git a/dev/test_data/VerificationError/Json/Unexpected/Invalid/MaxLengthViolation/AdministrativeInformation/version.json.errors b/dev/test_data/VerificationError/Json/Unexpected/Invalid/MaxLengthViolation/AdministrativeInformation/version.json.errors index 56824fb..9a3bd11 100644 --- a/dev/test_data/VerificationError/Json/Unexpected/Invalid/MaxLengthViolation/AdministrativeInformation/version.json.errors +++ b/dev/test_data/VerificationError/Json/Unexpected/Invalid/MaxLengthViolation/AdministrativeInformation/version.json.errors @@ -1,2 +1 @@ -: Created-at must be before updated-at. .version: Version type shall have a maximum length of 4 characters. diff --git a/dev/test_data/VerificationError/Json/Unexpected/Invalid/MinLengthViolation/AdministrativeInformation/embeddedDataSpecifications.json.errors b/dev/test_data/VerificationError/Json/Unexpected/Invalid/MinLengthViolation/AdministrativeInformation/embeddedDataSpecifications.json.errors index c866464..aab23e3 100644 --- a/dev/test_data/VerificationError/Json/Unexpected/Invalid/MinLengthViolation/AdministrativeInformation/embeddedDataSpecifications.json.errors +++ b/dev/test_data/VerificationError/Json/Unexpected/Invalid/MinLengthViolation/AdministrativeInformation/embeddedDataSpecifications.json.errors @@ -1,2 +1 @@ : Embedded data specifications must be either not set or have at least one item. -: Created-at must be before updated-at. diff --git a/dev/test_data/VerificationError/Json/Unexpected/Invalid/MinLengthViolation/AdministrativeInformation/revision.json.errors b/dev/test_data/VerificationError/Json/Unexpected/Invalid/MinLengthViolation/AdministrativeInformation/revision.json.errors index 513b5bf..74893f7 100644 --- a/dev/test_data/VerificationError/Json/Unexpected/Invalid/MinLengthViolation/AdministrativeInformation/revision.json.errors +++ b/dev/test_data/VerificationError/Json/Unexpected/Invalid/MinLengthViolation/AdministrativeInformation/revision.json.errors @@ -1,3 +1,2 @@ -: Created-at must be before updated-at. .revision: The value must not be empty. .revision: Revision type shall match the revision pattern. diff --git a/dev/test_data/VerificationError/Json/Unexpected/Invalid/MinLengthViolation/AdministrativeInformation/templateId.json.errors b/dev/test_data/VerificationError/Json/Unexpected/Invalid/MinLengthViolation/AdministrativeInformation/templateId.json.errors index 383c9f7..8da610d 100644 --- a/dev/test_data/VerificationError/Json/Unexpected/Invalid/MinLengthViolation/AdministrativeInformation/templateId.json.errors +++ b/dev/test_data/VerificationError/Json/Unexpected/Invalid/MinLengthViolation/AdministrativeInformation/templateId.json.errors @@ -1,2 +1 @@ -: Created-at must be before updated-at. .template_id: The value must not be empty. diff --git a/dev/test_data/VerificationError/Json/Unexpected/Invalid/MinLengthViolation/AdministrativeInformation/version.json.errors b/dev/test_data/VerificationError/Json/Unexpected/Invalid/MinLengthViolation/AdministrativeInformation/version.json.errors index a449414..e838f09 100644 --- a/dev/test_data/VerificationError/Json/Unexpected/Invalid/MinLengthViolation/AdministrativeInformation/version.json.errors +++ b/dev/test_data/VerificationError/Json/Unexpected/Invalid/MinLengthViolation/AdministrativeInformation/version.json.errors @@ -1,3 +1,2 @@ -: Created-at must be before updated-at. .version: The value must not be empty. .version: Version type shall match the version pattern. diff --git a/dev/tests/test_jsonization_of_enums.py b/dev/tests/test_jsonization_of_enums.py index 3245d5b..d15e4b8 100644 --- a/dev/tests/test_jsonization_of_enums.py +++ b/dev/tests/test_jsonization_of_enums.py @@ -310,7 +310,7 @@ def test_execution_state(self) -> None: self.assertEqual(enum_literal.value, jsonable) def test_level(self) -> None: - for jsonable in ["Deep", "Core"]: + for jsonable in ["deep", "core"]: enum_literal = our_jsonization.level_from_jsonable(jsonable) self.assertEqual(enum_literal.value, jsonable) @@ -322,7 +322,7 @@ def test_content(self) -> None: self.assertEqual(enum_literal.value, jsonable) def test_extent(self) -> None: - for jsonable in ["WithoutBLOBValue", "WithBLOBValue"]: + for jsonable in ["withoutBlobValue", "withBlobValue"]: enum_literal = our_jsonization.extent_from_jsonable(jsonable) self.assertEqual(enum_literal.value, jsonable)