Skip to content

model.base: Protect NamespaceSet attributes from being replaced - #619

Open
zrgt wants to merge 2 commits into
eclipse-basyx:developfrom
rwth-iat:fix/65-namespaceset-attribute-assignment
Open

model.base: Protect NamespaceSet attributes from being replaced#619
zrgt wants to merge 2 commits into
eclipse-basyx:developfrom
rwth-iat:fix/65-namespaceset-attribute-assignment

Conversation

@zrgt

@zrgt zrgt commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Attributes like Submodel.submodel_element, Qualifiable.qualifier or
HasExtension.extension hold a NamespaceSet, while the corresponding
__init__ parameters accept any Iterable. Assigning an iterable to
such an attribute after initialization silently replaced the
NamespaceSet with that plain object. The old NamespaceSet remained
registered in namespace_element_sets, so its objects stayed reachable
via get_referable() and friends while being invisible in the
attribute, uniqueness constraints were no longer checked and the
parent of the new objects was never set. The resulting errors, such as
AttributeError: 'list' object has no attribute 'update_nss_from' when
iterating over an ObjectStore, gave no hint about the actual cause.

Namespace.__setattr__ now redirects such assignments to the content of
the existing NamespaceSet, which is the behavior a user would expect
from the type of the __init__ parameters:

submodel.submodel_element = [my_property]  # replaces the content of the set
aas.extension = []                         # clears the set

As discussed in the issue, this is done centrally in Namespace instead
of via a property per attribute. That way it needs no repetition for
every current and future NamespaceSet attribute and also covers
NamespaceSet attributes of classes defined outside of this repository.
The existing SubmodelElementList.value setter keeps working unchanged.

The replacement is atomic: if one of the new objects violates a
constraint, the previous content of the set is restored, so a failed
assignment leaves the object untouched.

Fixes #65

Attributes like `Submodel.submodel_element`, `Qualifiable.qualifier` or
`HasExtension.extension` hold a `NamespaceSet`, while the corresponding
`__init__` parameters accept any `Iterable`. Assigning an iterable to
such an attribute after initialization silently replaced the
`NamespaceSet` with that plain object. The old `NamespaceSet` remained
registered in `namespace_element_sets`, so its objects stayed reachable
via `get_referable()` and friends while being invisible in the
attribute, uniqueness constraints were no longer checked and the
`parent` of the new objects was never set. The resulting errors, such as
`AttributeError: 'list' object has no attribute 'update_nss_from'` when
iterating over an `ObjectStore`, gave no hint about the actual cause.

`Namespace.__setattr__` now redirects such assignments to the content of
the existing `NamespaceSet`, which is the behavior a user would expect
from the type of the `__init__` parameters. This is done centrally in
`Namespace` instead of via a property per attribute, so that it also
applies to the `NamespaceSet` attributes of classes outside of this
repository. The replacement is atomic: if one of the new objects
violates a constraint, the previous content of the set is restored.

Fixes #65
@zrgt
zrgt requested a review from s-heppner August 28, 2026 16:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant