Commit 7c90fb8a authored by Torben Miny's avatar Torben Miny
Browse files

Merge branch fix/annotatedRelationshipElement_annotation with...

Merge branch fix/annotatedRelationshipElement_annotation with refs/heads/master into refs/merge-requests/38/train
parents 6b2d997b b903020a
Pipeline #286099 passed with stage
in 3 minutes and 6 seconds
......@@ -562,17 +562,9 @@ class AASFromJsonDecoder(json.JSONDecoder):
kind=cls._get_kind(dct))
cls._amend_abstract_attributes(ret, dct)
if 'annotation' in dct:
for annotation_data in _get_ts(dct, 'annotation', list):
try:
ret.annotation.add(cls._construct_aas_reference(annotation_data, model.DataElement))
except (KeyError, TypeError) as e:
error_message = \
"Error while trying to convert JSON object into annotation Reference for {}: {} >>> {}".format(
ret, e, pprint.pformat(dct, depth=2, width=2 ** 14, compact=True))
if cls.failsafe:
logger.error(error_message, exc_info=e)
else:
raise type(e)(error_message) from e
for element in _get_ts(dct, "annotation", list):
if _expect_type(element, model.DataElement, str(ret), cls.failsafe):
ret.annotation.add(element)
return ret
@classmethod
......
......@@ -588,11 +588,11 @@ def _construct_submodel_element(element: etree.Element, failsafe: bool, **kwargs
"submodelElementCollection": _construct_submodel_element_collection
}.items()}
if element.tag not in submodel_elements:
return _construct_data_element(element, failsafe, abstract_element="submodel element", **kwargs)
return _construct_data_element(element, failsafe, abstract_class_name="submodel element", **kwargs)
return submodel_elements[element.tag](element, failsafe, **kwargs)
def _construct_data_element(element: etree.Element, failsafe: bool, abstract_element: str = "data element",
def _construct_data_element(element: etree.Element, failsafe: bool, abstract_class_name: str = "data element",
**kwargs: Any) -> model.DataElement:
data_elements: Dict[str, Callable[..., model.DataElement]] = {NS_AAS + k: v for k, v in {
"blob": _construct_blob,
......@@ -603,7 +603,7 @@ def _construct_data_element(element: etree.Element, failsafe: bool, abstract_ele
"referenceElement": _construct_reference_element,
}.items()}
if element.tag not in data_elements:
raise KeyError(_element_pretty_identifier(element) + f" is not a valid {abstract_element}!")
raise KeyError(_element_pretty_identifier(element) + f" is not a valid {abstract_class_name}!")
return data_elements[element.tag](element, failsafe, **kwargs)
......@@ -631,17 +631,13 @@ def _construct_operation_variable(element: etree.Element, _failsafe: bool, **_kw
def _construct_annotated_relationship_element(element: etree.Element, failsafe: bool, **_kwargs: Any) \
-> model.AnnotatedRelationshipElement:
annotated_relationship_element = model.AnnotatedRelationshipElement(
_child_text_mandatory(element, NS_AAS + "idShort"),
_child_construct_mandatory(element, NS_AAS + "first", _construct_referable_reference),
_child_construct_mandatory(element, NS_AAS + "second", _construct_referable_reference),
kind=_get_modeling_kind(element)
annotated_relationship_element = _construct_relationship_element_internal(
element, failsafe, object_class=model.AnnotatedRelationshipElement
)
annotations = _get_child_mandatory(element, NS_AAS + "annotations")
for data_element_ref in _failsafe_construct_multiple(annotations.findall(NS_AAS + "reference"),
_construct_data_element_reference, failsafe):
annotated_relationship_element.annotation.add(data_element_ref)
_amend_abstract_attributes(annotated_relationship_element, element, failsafe)
for data_element in _get_child_mandatory(element, NS_AAS + "annotations"):
constructed = _failsafe_construct(data_element, _construct_data_element, failsafe)
if constructed is not None:
annotated_relationship_element.annotation.add(constructed)
return annotated_relationship_element
......@@ -793,7 +789,15 @@ def _construct_reference_element(element: etree.Element, failsafe: bool, **_kwar
def _construct_relationship_element(element: etree.Element, failsafe: bool, **_kwargs: Any) \
-> model.RelationshipElement:
relationship_element = model.RelationshipElement(
return _construct_relationship_element_internal(element, failsafe, model.RelationshipElement, **_kwargs)
RE = TypeVar("RE", bound=model.RelationshipElement)
def _construct_relationship_element_internal(element: etree.Element, failsafe: bool,
object_class: Type[RE], **_kwargs: Any) -> RE:
relationship_element = object_class(
_child_text_mandatory(element, NS_AAS + "idShort"),
_child_construct_mandatory(element, NS_AAS + "first", _construct_referable_reference),
_child_construct_mandatory(element, NS_AAS + "second", _construct_referable_reference),
......
......@@ -746,8 +746,8 @@ def annotated_relationship_element_to_xml(obj: model.AnnotatedRelationshipElemen
et_annotated_relationship_element = relationship_element_to_xml(obj, tag)
et_annotations = _generate_element(name=NS_AAS+"annotations")
if obj.annotation:
for reference in obj.annotation:
et_annotations.append(reference_to_xml(reference))
for data_element in obj.annotation:
et_annotations.append(data_element_to_xml(data_element))
et_annotated_relationship_element.append(et_annotations)
return et_annotated_relationship_element
......
......@@ -360,14 +360,15 @@ class AASDataChecker(DataChecker):
:return:
"""
self.check_relationship_element_equal(object_, expected_value)
self.check_contained_element_length(object_, 'annotation', model.AASReference,
self.check_contained_element_length(object_, 'annotation', model.DataElement,
len(expected_value.annotation))
for expected_ref in expected_value.annotation:
ref = self._find_reference(expected_ref, object_.annotation)
if self.check(ref is not None, 'Annotated Reference {} must exist'.format(repr(expected_ref))):
self._check_reference_equal(ref, expected_ref) # type: ignore
for expected_data_element in expected_value.annotation:
self.check(
object_.annotation.get(expected_data_element.id_short) is not None,
'Annotation {} must exist'.format(repr(expected_data_element))
)
found_elements = self._find_extra_reference(object_.annotation, expected_value.annotation)
found_elements = self._find_extra_elements_by_id_short(object_.annotation, expected_value.annotation)
self.check(found_elements == set(), 'Annotated Reference {} must not have extra '
'references'.format(repr(object_)),
value=found_elements)
......
......@@ -433,11 +433,16 @@ def create_example_submodel() -> model.Submodel:
value='ExampleProperty2',
id_type=model.KeyType.IDSHORT),),
model.Property),
annotation={model.AASReference((model.Key(type_=model.KeyElements.PROPERTY,
local=True,
value='ExampleProperty3',
id_type=model.KeyType.IDSHORT),),
model.Property)},
annotation={model.Property(id_short="ExampleAnnotatedProperty",
value_type=model.datatypes.String,
value='exampleValue',
parent=None),
model.Range(id_short="ExampleAnnotatedRange",
value_type=model.datatypes.Integer,
min_=1,
max_=5,
parent=None)
},
category='PARAMETER',
description={'en-us': 'Example AnnotatedRelationshipElement object',
'de': 'Beispiel AnnotatedRelationshipElement Element'},
......
......@@ -199,11 +199,16 @@ def create_example_submodel() -> model.Submodel:
value='ExampleProperty',
id_type=model.KeyType.IDSHORT),),
model.Property),
annotation={model.AASReference((model.Key(type_=model.KeyElements.PROPERTY,
local=True,
value='ExampleProperty',
id_type=model.KeyType.IDSHORT),),
model.Property)},
annotation={model.Property(id_short="ExampleAnnotatedProperty",
value_type=model.datatypes.String,
value='exampleValue',
parent=None),
model.Range(id_short="ExampleAnnotatedRange",
value_type=model.datatypes.Integer,
min_=1,
max_=5,
parent=None)
},
category='PARAMETER',
description={'en-us': 'Example AnnotatedRelationshipElement object',
'de': 'Beispiel AnnotatedRelationshipElement Element'},
......
......@@ -681,7 +681,7 @@ class RelationshipElement(SubmodelElement):
self.second: base.AASReference = second
class AnnotatedRelationshipElement(RelationshipElement):
class AnnotatedRelationshipElement(RelationshipElement, base.Namespace):
"""
An annotated relationship element is a relationship element that can be annotated with additional data elements.
......@@ -692,7 +692,7 @@ class AnnotatedRelationshipElement(RelationshipElement):
id_short: str,
first: base.AASReference,
second: base.AASReference,
annotation: Optional[Set[base.AASReference[DataElement]]] = None,
annotation: Optional[Iterable[DataElement]] = None,
category: Optional[str] = None,
description: Optional[base.LangStringSet] = None,
parent: Optional[base.Namespace] = None,
......@@ -703,7 +703,7 @@ class AnnotatedRelationshipElement(RelationshipElement):
Initializer of AnnotatedRelationshipElement
:param id_short: Identifying string of the element within its name space. (from base.Referable)
:param annotation: Unordered list of annotations that hold for the relationship between to elements
:param annotation: Unordered list of annotations that hold for the relationship between two elements
:param category: The category is a value that gives further meta information w.r.t. to the class of the element.
It affects the expected existence of attributes and the applicability of constraints.
(from base.Referable)
......@@ -721,7 +721,10 @@ class AnnotatedRelationshipElement(RelationshipElement):
"""
super().__init__(id_short, first, second, category, description, parent, semantic_id, qualifier, kind)
self.annotation: Set[base.AASReference[DataElement]] = set() if annotation is None else annotation
if annotation is None:
self.annotation: base.NamespaceSet[DataElement] = base.NamespaceSet(self)
else:
self.annotation = base.NamespaceSet(self, annotation)
class OperationVariable:
......
......@@ -141,7 +141,6 @@ class ComplianceToolTest(unittest.TestCase):
def test_json_create_example(self) -> None:
file_path = os.path.join(os.path.dirname(aas.compliance_tool.__file__), 'cli.py')
test_file_path = os.path.join(os.path.dirname(__file__), 'files')
file, filename = tempfile.mkstemp(suffix=".json")
os.close(file)
......@@ -202,7 +201,6 @@ class ComplianceToolTest(unittest.TestCase):
def test_xml_create_example(self) -> None:
file_path = os.path.join(os.path.dirname(aas.compliance_tool.__file__), 'cli.py')
test_file_path = os.path.join(os.path.dirname(__file__), 'files')
file, filename = tempfile.mkstemp(suffix=".xml")
os.close(file)
......
......@@ -197,21 +197,19 @@ class AASDataCheckerTest(unittest.TestCase):
id_type=model.KeyType.IDSHORT),),
model.Property),
annotation={
model.AASReference((model.Key(type_=model.KeyElements.PROPERTY,
local=True,
value='ExampleProperty',
id_type=model.KeyType.IDSHORT),),
model.Property)
model.Property(id_short="ExampleAnnotatedProperty",
value_type=model.datatypes.String,
value='exampleValue',
parent=None)
})
checker = AASDataChecker(raise_immediately=False)
checker.check_annotated_relationship_element_equal(rel1, rel2)
self.assertEqual(2, sum(1 for _ in checker.failed_checks))
checker_iterator = iter(checker.failed_checks)
self.assertEqual("FAIL: AnnotatedRelationshipElement[test] must contain 1 AASReferences "
self.assertEqual("FAIL: AnnotatedRelationshipElement[test] must contain 1 DataElements "
"(count=0)",
repr(next(checker_iterator)))
self.assertEqual("FAIL: Annotated Reference AASReference(type=Property, key=(Key(local=True, id_type=IDSHORT, "
"value=ExampleProperty),)) must exist ()",
self.assertEqual("FAIL: Annotation Property[test / ExampleAnnotatedProperty] must exist ()",
repr(next(checker_iterator)))
def test_submodel_checker(self):
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment