Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make model.Entity.specific_asset_id a Set of model.SpecificAssetIds #149

Merged
merged 25 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
77e0f86
Fix Entity.specificAssetIds in schemas
zrgt Oct 27, 2023
e1fffec
- Set `Entity.specific_asset_id` as `Iterable[SpecificAssetId]`, beca…
zrgt Oct 27, 2023
92e8618
Refactor `check_entity_equal()`&`check_asset_information_equal()`
zrgt Oct 27, 2023
0ed5d4f
Update test files
zrgt Oct 27, 2023
bc66b2a
Update tutorial_serialization_deserialization.py
zrgt Oct 27, 2023
91bfe92
Use getter/setter decorators for global_asset_id
zrgt Oct 29, 2023
0386628
Fix errors from MyPy
zrgt Oct 29, 2023
2f8a731
Fix pycodestyle errors
zrgt Oct 29, 2023
f537658
Fix typehint of specific_asset_id
zrgt Nov 3, 2023
046ee15
Fix wrong example value
zrgt Nov 3, 2023
7a2e341
model.base: fix `ConstrainedList.clear()` atomicity
jkhsjdhjs Nov 4, 2023
ff31f45
model.submodel: remove `_string_constraints` decorator from `Entity`
jkhsjdhjs Nov 4, 2023
7ac9aa6
model.submodel: move `Entity.global_asset_id` string constraint check…
jkhsjdhjs Nov 4, 2023
4b8a7ae
model.submodel: remove duplicate code in `Entity`
jkhsjdhjs Nov 4, 2023
3dcf9ff
model.ass: add `_validate_asset_ids()` function to `AssetInformation`
jkhsjdhjs Nov 4, 2023
b853160
model.{aas, submodel}: add set hook to `{AssetInformation, Entity}.sp…
jkhsjdhjs Nov 4, 2023
39a8c48
model.submodel: assign values correctly in `Entity.__init__`
jkhsjdhjs Nov 4, 2023
6b3de29
model.{aas, submodel}: add getter/setter for `{AssetInformation, Enti…
jkhsjdhjs Nov 4, 2023
47b2e47
model.submodel: verify constraints when `SpecificAssetIds` are added …
jkhsjdhjs Nov 4, 2023
5e0f160
model.{aas, submodel}: improve `{AssetInformation, Entity}.global_ass…
jkhsjdhjs Nov 4, 2023
6fb375d
test.model: add `AssetInformation` tests and improve `Entity` tests
jkhsjdhjs Nov 4, 2023
f11c7f5
Merge branch 'fix/constrained_list_clear_atomicity' into entityfix
jkhsjdhjs Nov 4, 2023
f8a2bf6
Merge pull request #1 from rwth-iat/entityfix
zrgt Nov 7, 2023
9ed5704
Refactor `Entity` and `AssetInformation`
zrgt Nov 7, 2023
0222237
Refactor `Entity` and `AssetInformation`
zrgt Nov 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 17 additions & 15 deletions basyx/aas/model/aas.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,24 +60,26 @@ def __init__(self,

super().__init__()
self.asset_kind: base.AssetKind = asset_kind
self._specific_asset_id: base.ConstrainedList[base.SpecificAssetId] = \
base.ConstrainedList(specific_asset_id, item_set_hook=self._check_constraint_set_spec_asset_id,
item_del_hook=self._check_constraint_del_spec_asset_id)
self._global_asset_id: Optional[base.Identifier]
# AASd-131 is validated via the global_asset_id setter
self.global_asset_id = global_asset_id
self.asset_type: Optional[base.Identifier] = asset_type
self.default_thumbnail: Optional[base.Resource] = default_thumbnail

def _check_constraint_set_spec_asset_id(self, old: List[base.SpecificAssetId], new: List[base.SpecificAssetId],
list_: List[base.SpecificAssetId]) -> None:
# assign private attributes, bypassing setters, as constraints will be checked below
self._specific_asset_id: base.ConstrainedList[base.SpecificAssetId] = base.ConstrainedList(
specific_asset_id,
item_set_hook=self._check_constraint_set_spec_asset_id,
item_del_hook=self._check_constraint_del_spec_asset_id
)
self._global_asset_id: Optional[base.Identifier] = global_asset_id
self._validate_asset_ids(global_asset_id, bool(specific_asset_id))

def _check_constraint_set_spec_asset_id(self, items_to_replace: List[base.SpecificAssetId],
new_items: List[base.SpecificAssetId],
old_list: List[base.SpecificAssetId]) -> None:
self._validate_asset_ids(self.global_asset_id,
# whether the list is nonempty after the set operation
len(old) < len(list_) or len(new) > 0)
len(old_list) - len(items_to_replace) + len(new_items) > 0)

def _check_constraint_del_spec_asset_id(self, _item_to_del: base.SpecificAssetId,
list_: List[base.SpecificAssetId]) -> None:
self._validate_asset_ids(self.global_asset_id, len(list_) > 1)
old_list: List[base.SpecificAssetId]) -> None:
self._validate_asset_ids(self.global_asset_id, len(old_list) > 1)

@property
def global_asset_id(self) -> Optional[base.Identifier]:
Expand All @@ -86,8 +88,6 @@ def global_asset_id(self) -> Optional[base.Identifier]:
@global_asset_id.setter
def global_asset_id(self, global_asset_id: Optional[base.Identifier]) -> None:
self._validate_asset_ids(global_asset_id, bool(self.specific_asset_id))
if global_asset_id is not None:
_string_constraints.check_identifier(global_asset_id)
self._global_asset_id = global_asset_id

@property
Expand All @@ -104,6 +104,8 @@ def _validate_asset_ids(global_asset_id: Optional[base.Identifier], specific_ass
if global_asset_id is None and not specific_asset_id_nonempty:
raise base.AASConstraintViolation(131,
"An AssetInformation has to have a globalAssetId or a specificAssetId")
if global_asset_id is not None:
_string_constraints.check_identifier(global_asset_id)

def __repr__(self) -> str:
return "AssetInformation(assetKind={}, globalAssetId={}, specificAssetId={}, assetType={}, " \
Expand Down
58 changes: 28 additions & 30 deletions basyx/aas/model/submodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -1106,41 +1106,38 @@ def __init__(self,
super().__init__(id_short, display_name, category, description, parent, semantic_id, qualifier, extension,
supplemental_semantic_id, embedded_data_specifications)
self.statement = base.NamespaceSet(self, [("id_short", True)], statement)
self._specific_asset_id: base.ConstrainedList[base.SpecificAssetId] = \
base.ConstrainedList(specific_asset_id, item_set_hook=self._check_constraint_set_spec_asset_id,
item_del_hook=self._check_constraint_del_spec_asset_id)
# assign private attributes, bypassing setters, as constraints will be checked below
self._entity_type: base.EntityType = entity_type
# add item_add_hook after items have been added, because checking the constraints requires the global_asset_id
# to be set
self._specific_asset_id._item_add_hook = self._check_constraint_add_spec_asset_id
# use setter for global_asset_id, as it also checks the string constraint,
# which hasn't been checked at this point
# furthermore, the setter also validates AASd-014
self._global_asset_id: Optional[base.Identifier]
self.global_asset_id = global_asset_id

def _check_constraint_add_spec_asset_id(self, _new: base.SpecificAssetId, _list: List[base.SpecificAssetId]) \
-> None:
self._validate_asset_ids_for_entity_type(self.entity_type, self.global_asset_id, True)

def _check_constraint_set_spec_asset_id(self, old: List[base.SpecificAssetId], new: List[base.SpecificAssetId],
list_: List[base.SpecificAssetId]) -> None:
self._validate_asset_ids_for_entity_type(self.entity_type, self.global_asset_id,
# whether the list is nonempty after the set operation
len(old) < len(list_) or len(new) > 0)
self._global_asset_id: Optional[base.Identifier] = global_asset_id
self._specific_asset_id: base.ConstrainedList[base.SpecificAssetId] = base.ConstrainedList(
specific_asset_id,
item_add_hook=self._check_constraint_add_spec_asset_id,
item_set_hook=self._check_constraint_set_spec_asset_id,
item_del_hook=self._check_constraint_del_spec_asset_id
)
self._validate_asset_ids(entity_type, global_asset_id, bool(specific_asset_id))

def _check_constraint_add_spec_asset_id(self, _new_item: base.SpecificAssetId,
_old_list: List[base.SpecificAssetId]) -> None:
self._validate_asset_ids(self.entity_type, self.global_asset_id, True)

def _check_constraint_set_spec_asset_id(self, items_to_replace: List[base.SpecificAssetId],
new_items: List[base.SpecificAssetId],
old_list: List[base.SpecificAssetId]) -> None:
self._validate_asset_ids(self.entity_type, self.global_asset_id,
len(old_list) - len(items_to_replace) + len(new_items) > 0)

def _check_constraint_del_spec_asset_id(self, _item_to_del: base.SpecificAssetId,
list_: List[base.SpecificAssetId]) -> None:
self._validate_asset_ids_for_entity_type(self.entity_type, self.global_asset_id, len(list_) > 1)
old_list: List[base.SpecificAssetId]) -> None:
self._validate_asset_ids(self.entity_type, self.global_asset_id, len(old_list) > 1)

@property
def entity_type(self) -> base.EntityType:
return self._entity_type

@entity_type.setter
def entity_type(self, entity_type: base.EntityType) -> None:
self._validate_asset_ids_for_entity_type(entity_type, self.global_asset_id, bool(self.specific_asset_id))
self._validate_asset_ids(entity_type, self.global_asset_id, bool(self.specific_asset_id))
self._entity_type = entity_type

@property
Expand All @@ -1149,9 +1146,7 @@ def global_asset_id(self) -> Optional[base.Identifier]:

@global_asset_id.setter
def global_asset_id(self, global_asset_id: Optional[base.Identifier]) -> None:
self._validate_asset_ids_for_entity_type(self.entity_type, global_asset_id, bool(self.specific_asset_id))
if global_asset_id is not None:
_string_constraints.check_identifier(global_asset_id)
self._validate_asset_ids(self.entity_type, global_asset_id, bool(self.specific_asset_id))
self._global_asset_id = global_asset_id

@property
Expand All @@ -1164,9 +1159,9 @@ def specific_asset_id(self, specific_asset_id: Iterable[base.SpecificAssetId]) -
self._specific_asset_id[:] = specific_asset_id

@staticmethod
def _validate_asset_ids_for_entity_type(entity_type: base.EntityType,
global_asset_id: Optional[base.Identifier],
specific_asset_id_nonempty: bool) -> None:
def _validate_asset_ids(entity_type: base.EntityType,
global_asset_id: Optional[base.Identifier],
specific_asset_id_nonempty: bool) -> None:
if entity_type == base.EntityType.SELF_MANAGED_ENTITY and global_asset_id is None \
and not specific_asset_id_nonempty:
raise base.AASConstraintViolation(
Expand All @@ -1176,6 +1171,9 @@ def _validate_asset_ids_for_entity_type(entity_type: base.EntityType,
raise base.AASConstraintViolation(
14, "A co-managed entity has to have neither a globalAssetId nor a specificAssetId")

if global_asset_id is not None:
_string_constraints.check_identifier(global_asset_id)
zrgt marked this conversation as resolved.
Show resolved Hide resolved


class EventElement(SubmodelElement, metaclass=abc.ABCMeta):
"""
Expand Down
Loading