Skip to content
Snippets Groups Projects
Commit 72077565 authored by Torben Miny's avatar Torben Miny
Browse files

Merge branch feature/namespace_add_objects with refs/heads/improve/V30RC01...

Merge branch feature/namespace_add_objects with refs/heads/improve/V30RC01 into refs/merge-requests/81/train
parents 800f93f2 c85c3ace
No related branches found
No related tags found
No related merge requests found
Pipeline #542913 passed
......@@ -420,7 +420,7 @@ class Identifier:
return "Identifier({}={})".format(self.id_type.name, self.id)
_NSO = TypeVar('_NSO', bound=Union["Referable", "Constraint", "HasSemantics", "HasExtension"])
_NSO = TypeVar('_NSO', bound=Union["Referable", "Constraint", "HasSemantics", "Extension"])
class Namespace(metaclass=abc.ABCMeta):
......@@ -442,23 +442,31 @@ class Namespace(metaclass=abc.ABCMeta):
:raises KeyError: If no such :class:`~._NSO` can be found
"""
object_ = None
for ns_set in self.namespace_element_sets:
try:
object_ = ns_set.get_object_by_attribute(attribute_name, attribute)
break
return ns_set.get_object_by_attribute(attribute_name, attribute)
except KeyError:
continue
if object_:
return object_
raise KeyError(f"{object_type.__name__} with {attribute_name} {attribute} not found in this "
f"namespace")
raise KeyError(f"{object_type.__name__} with {attribute_name} {attribute} not found in this namespace")
def _add_object(self, attribute_name: str, obj: _NSO) -> None:
"""
Add an :class:`~._NSO` to this namespace by its attribute
:raises KeyError: If no such :class:`~._NSO` can be found
"""
for ns_set in self.namespace_element_sets:
if attribute_name not in ns_set.get_attribute_name_list():
continue
ns_set.add(obj)
return
raise ValueError(f"{obj!r} can't be added to this namespace")
def _remove_object(self, object_type: type, attribute_name: str, attribute) -> None:
"""
Remove an :class:`~.Extension` from this namespace by its name
Remove an :class:`~.NSO` from this namespace by its attribute
:raises KeyError: If no such :class:`~.Extension` can be found
:raises KeyError: If no such :class:`~.NSO` can be found
"""
for ns_set in self.namespace_element_sets:
if attribute_name in ns_set.get_attribute_name_list():
......@@ -467,8 +475,7 @@ class Namespace(metaclass=abc.ABCMeta):
return
except KeyError:
continue
raise KeyError(f"{object_type.__name__} with {attribute_name} {attribute} not found in this "
f"namespace")
raise KeyError(f"{object_type.__name__} with {attribute_name} {attribute} not found in this namespace")
class HasExtension(Namespace, metaclass=abc.ABCMeta):
......@@ -500,6 +507,16 @@ class HasExtension(Namespace, metaclass=abc.ABCMeta):
"""
return super()._get_object(HasExtension, "name", name)
def add_extension(self, extension: "Extension") -> None:
"""
Add a :class:`~.Extension` to this Namespace
:param extension: The :class:`~.Extension` to add
:raises KeyError: If a :class:`~.Extension` with the same name is already present in this namespace
:raises ValueError: If the given :class:`~.Extension` already has a parent namespace
"""
return super()._add_object("name", extension)
def remove_extension_by_name(self, name: str) -> None:
"""
Remove an :class:`~.Extension` from this namespace by its name
......@@ -979,6 +996,8 @@ class HasSemantics(metaclass=abc.ABCMeta):
@abc.abstractmethod
def __init__(self):
super().__init__()
# TODO: parent can be any `Namespace`, unfortunately this definition would be incompatible with the definition
# of Referable.parent as `UniqueIdShortNamespace`
self.parent: Optional[Any] = None
self._semantic_id: Optional[Reference] = None
......@@ -989,6 +1008,7 @@ class HasSemantics(metaclass=abc.ABCMeta):
@semantic_id.setter
def semantic_id(self, semantic_id: Optional[Reference]) -> None:
if self.parent is not None:
if semantic_id is not None:
for set_ in self.parent.namespace_element_sets:
if set_.contains_id("semantic_id", semantic_id):
raise KeyError("Object with semantic_id '{}' is already present in the parent Namespace"
......@@ -1128,12 +1148,22 @@ class Qualifiable(Namespace, metaclass=abc.ABCMeta):
def get_qualifier_by_type(self, qualifier_type: QualifierType) -> "Qualifier":
"""
Find a :class:`~.Qualifier` in this Namespaces by its type
Find a :class:`~.Qualifier` in this Namespace by its type
:raises KeyError: If no such :class:`~.Qualifier` can be found
"""
return super()._get_object(Qualifiable, "type", qualifier_type)
def add_qualifier(self, qualifier: "Qualifier") -> None:
"""
Add a :class:`~.Qualifier` to this Namespace
:param qualifier: The :class:`~.Qualifier` to add
:raises KeyError: If a qualifier with the same type is already present in this namespace
:raises ValueError: If the passed object already has a parent namespace
"""
return super()._add_object("type", qualifier)
def remove_qualifier_by_type(self, qualifier_type: QualifierType) -> None:
"""
Remove a :class:`~.Qualifier` from this Namespace by its type
......@@ -1167,7 +1197,7 @@ class Qualifier(Constraint, HasSemantics):
TODO: Add instruction what to do after construction
"""
super().__init__()
self.parent: Optional[Qualifiable] = None # type: ignore
self.parent: Optional[Qualifiable] = None
self._type: QualifierType
self.type: QualifierType = type_
self.value_type: Type[datatypes.AnyXSDType] = value_type
......@@ -1274,7 +1304,7 @@ class UniqueIdShortNamespace(Namespace, metaclass=abc.ABCMeta):
def get_referable(self, id_short: str) -> Referable:
"""
Find a :class:`~.Referable` in this Namespaces by its id_short
Find a :class:`~.Referable` in this Namespace by its id_short
:param id_short: id_short
:returns: :class:`~.Referable`
......@@ -1282,6 +1312,16 @@ class UniqueIdShortNamespace(Namespace, metaclass=abc.ABCMeta):
"""
return super()._get_object(Referable, "id_short", id_short)
def add_referable(self, referable: Referable) -> None:
"""
Add a :class:`~.Referable` to this Namespace
:param referable: The :class:`~.Referable` to add
:raises KeyError: If a :class:`~.Referable` with the same name is already present in this namespace
:raises ValueError: If the given :class:`~.Referable` already has a parent namespace
"""
return super()._add_object("id_short", referable)
def remove_referable(self, id_short: str) -> None:
"""
Remove a Referable from this Namespace by its id_short
......
......@@ -768,6 +768,8 @@ class SubmodelElementCollectionOrderedUniqueSemanticId(SubmodelElementCollection
super().__init__(id_short, (), display_name, category, description, parent, semantic_id, qualifier, kind,
extension)
# super().__init__() adds an unused NamespaceSet
self.namespace_element_sets.pop()
self.value = base.OrderedNamespaceSet(self, [("id_short", False), ("semantic_id", True)], value)
@property
......@@ -873,6 +875,8 @@ class SubmodelElementCollectionUnorderedUniqueSemanticId(SubmodelElementCollecti
"""
super().__init__(id_short, (), display_name, category, description, parent, semantic_id, qualifier, kind,
extension)
# super().__init__() adds an unused NamespaceSet
self.namespace_element_sets.pop()
self.value = base.NamespaceSet(self, [("id_short", False), ("semantic_id", True)], value)
@property
......
......@@ -303,17 +303,46 @@ class ReferableTest(unittest.TestCase):
# Sources of embedded objects should always be updated
self.assertEqual("scheme:NewRelElSource", example_relel.source)
def test_update_commit_qualifier(self):
def test_update_commit_qualifier_extension_semantic_id(self):
submodel = model.Submodel(model.Identifier("https://acplt.org/Test_Submodel", model.IdentifierType.IRI))
submodel.update()
qualifier = model.Qualifier("test", model.datatypes.String)
submodel.qualifier.add(qualifier)
extension = model.Extension("test")
collection = model.SubmodelElementCollection.create("test")
semantic_id = model.Reference((model.Key(model.KeyElements.GLOBAL_REFERENCE, "test", model.KeyType.IRI),))
property = model.MultiLanguageProperty("test", semantic_id=semantic_id)
collection.add_referable(property)
submodel.add_qualifier(qualifier)
submodel.add_extension(extension)
submodel.add_referable(collection)
submodel.commit()
self.assertEqual(next(iter(submodel.qualifier)), qualifier)
self.assertEqual(next(iter(submodel.extension)), extension)
self.assertEqual(next(iter(submodel.submodel_element)), collection)
self.assertEqual(next(iter(collection.value)), property)
submodel.get_qualifier_by_type("test")
submodel.get_extension_by_name("test")
collection_ = submodel.get_referable("test")
self.assertIsInstance(collection_, model.SubmodelElementCollectionUnorderedUniqueSemanticId)
assert isinstance(collection_, model.SubmodelElementCollectionUnorderedUniqueSemanticId)
collection_.get_object_by_semantic_id(semantic_id)
submodel.remove_qualifier_by_type("test")
submodel.remove_extension_by_name("test")
submodel.remove_referable("test")
collection_.remove_object_by_semantic_id(semantic_id)
with self.assertRaises(StopIteration):
next(iter(submodel.qualifier))
with self.assertRaises(StopIteration):
next(iter(submodel.extension))
with self.assertRaises(StopIteration):
next(iter(submodel.submodel_element))
with self.assertRaises(StopIteration):
next(iter(collection_.value))
submodel.commit()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment