aas-standard-parser 0.1.9__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (20) hide show
  1. {aas_standard_parser-0.1.9 → aas_standard_parser-0.2.1}/PKG-INFO +1 -1
  2. {aas_standard_parser-0.1.9 → aas_standard_parser-0.2.1}/aas_standard_parser/aimc_parser.py +39 -36
  3. {aas_standard_parser-0.1.9 → aas_standard_parser-0.2.1}/aas_standard_parser.egg-info/PKG-INFO +1 -1
  4. {aas_standard_parser-0.1.9 → aas_standard_parser-0.2.1}/pyproject.toml +1 -1
  5. {aas_standard_parser-0.1.9 → aas_standard_parser-0.2.1}/tests/test_aimc_parser.py +36 -22
  6. {aas_standard_parser-0.1.9 → aas_standard_parser-0.2.1}/LICENSE +0 -0
  7. {aas_standard_parser-0.1.9 → aas_standard_parser-0.2.1}/README.md +0 -0
  8. {aas_standard_parser-0.1.9 → aas_standard_parser-0.2.1}/aas_standard_parser/__init__.py +0 -0
  9. {aas_standard_parser-0.1.9 → aas_standard_parser-0.2.1}/aas_standard_parser/aid_parser.py +0 -0
  10. {aas_standard_parser-0.1.9 → aas_standard_parser-0.2.1}/aas_standard_parser/collection_helpers.py +0 -0
  11. {aas_standard_parser-0.1.9 → aas_standard_parser-0.2.1}/aas_standard_parser/demo/demo_process.py +0 -0
  12. {aas_standard_parser-0.1.9 → aas_standard_parser-0.2.1}/aas_standard_parser/demo/logging_handler.py +0 -0
  13. {aas_standard_parser-0.1.9 → aas_standard_parser-0.2.1}/aas_standard_parser/reference_helpers.py +0 -0
  14. {aas_standard_parser-0.1.9 → aas_standard_parser-0.2.1}/aas_standard_parser/submodel_parser.py +0 -0
  15. {aas_standard_parser-0.1.9 → aas_standard_parser-0.2.1}/aas_standard_parser/utils.py +0 -0
  16. {aas_standard_parser-0.1.9 → aas_standard_parser-0.2.1}/aas_standard_parser.egg-info/SOURCES.txt +0 -0
  17. {aas_standard_parser-0.1.9 → aas_standard_parser-0.2.1}/aas_standard_parser.egg-info/dependency_links.txt +0 -0
  18. {aas_standard_parser-0.1.9 → aas_standard_parser-0.2.1}/aas_standard_parser.egg-info/requires.txt +0 -0
  19. {aas_standard_parser-0.1.9 → aas_standard_parser-0.2.1}/aas_standard_parser.egg-info/top_level.txt +0 -0
  20. {aas_standard_parser-0.1.9 → aas_standard_parser-0.2.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aas-standard-parser
3
- Version: 0.1.9
3
+ Version: 0.2.1
4
4
  Summary: Some auxiliary functions for parsing standard submodels
5
5
  Author-email: Daniel Klein <daniel.klein@em.ag>
6
6
  License: MIT License
@@ -2,7 +2,7 @@
2
2
 
3
3
  import json
4
4
  import logging
5
- from dataclasses import dataclass, field
5
+ from dataclasses import field
6
6
 
7
7
  import basyx.aas.adapter.json
8
8
  from basyx.aas import model
@@ -12,21 +12,27 @@ import aas_standard_parser.collection_helpers as ch
12
12
  logger = logging.getLogger(__name__)
13
13
 
14
14
 
15
+ class ReferenceProperties:
16
+ """Class representing properties of a reference in the mapping configuration."""
17
+
18
+ reference: model.ExternalReference = field(metadata={"description": "Reference to the property in the submodel."})
19
+ submodel_id: str = field(metadata={"description": "Identifier of the submodel used by the reference."})
20
+ property_name: str = field(metadata={"description": "Name of the mapped property."})
21
+ parent_path: list[str] = field(metadata={"description": "List of idShorts representing the parent path of the reference."})
22
+
23
+
15
24
  class SourceSinkRelation:
16
25
  """Class representing a source-sink relation in the mapping configuration."""
17
26
 
18
- aid_submodel_id: str = field(metadata={"description": "Identifier of the AID submodel used by the source reference."})
19
- source: model.ExternalReference = field(metadata={"description": "Reference to the source property in the AID submodel."})
20
- sink: model.ExternalReference = field(metadata={"description": "Reference to the sink property in the target submodel."})
21
- property_name: str = field(metadata={"description": "Name of the mapped property."})
22
- source_parent_path: list[str] = field(metadata={"description": "List of idShorts representing the parent path of the reference."})
27
+ source_properties: ReferenceProperties = field(metadata={"description": "Properties of the source reference."})
28
+ sink_properties: ReferenceProperties = field(metadata={"description": "Properties of the sink reference."})
23
29
 
24
30
  def source_as_dict(self) -> dict:
25
31
  """Convert the source reference to a dictionary.
26
32
 
27
33
  :return: The source reference as a dictionary.
28
34
  """
29
- dict_string = json.dumps(self.source, cls=basyx.aas.adapter.json.AASToJsonEncoder)
35
+ dict_string = json.dumps(self.source_properties.reference, cls=basyx.aas.adapter.json.AASToJsonEncoder)
30
36
  dict_string = dict_string.replace("GlobalReference", "Submodel").replace("FragmentReference", "SubmodelElementCollection")
31
37
  return json.loads(dict_string)
32
38
 
@@ -35,14 +41,7 @@ class SourceSinkRelation:
35
41
 
36
42
  :return: The sink reference as a dictionary.
37
43
  """
38
- return json.loads(json.dumps(self.sink, cls=basyx.aas.adapter.json.AASToJsonEncoder))
39
-
40
- def get_source_parent_property_group_name(self) -> str:
41
- """Get the name of the parent property group from the source. Ignore 'properties' entries from the path."""
42
- if len(self.source_parent_path) == 0:
43
- return ""
44
-
45
- return next((n for n in reversed(self.source_parent_path) if n != "properties"), "")
44
+ return json.dumps(self.sink_properties.reference, cls=basyx.aas.adapter.json.AASToJsonEncoder)
46
45
 
47
46
 
48
47
  class MappingConfiguration:
@@ -164,7 +163,7 @@ def parse_mapping_configuration_element(
164
163
  return None
165
164
 
166
165
  # check if all relations have the same AID submodel
167
- aid_submodel_ids = list({source_sink_relation.aid_submodel_id for source_sink_relation in source_sink_relations})
166
+ aid_submodel_ids = list({source_sink_relation.source_properties.submodel_id for source_sink_relation in source_sink_relations})
168
167
 
169
168
  if len(aid_submodel_ids) != 1:
170
169
  logger.error(
@@ -233,33 +232,37 @@ def _generate_source_sink_relations(mapping_configuration_element: model.Submode
233
232
  logger.warning(f"'second' reference is missing in RelationshipElement '{source_sink_relation.id_short}'")
234
233
  continue
235
234
 
236
- source_ref = source_sink_relation.first
235
+ relation = SourceSinkRelation()
236
+ relation.source_properties = _get_reference_properties(source_sink_relation.first)
237
+ relation.sink_properties = _get_reference_properties(source_sink_relation.second)
237
238
 
238
- global_ref = next((key for key in source_ref.key if key.type == model.KeyTypes.GLOBAL_REFERENCE), None)
239
+ source_sink_relations.append(relation)
239
240
 
240
- if global_ref is None:
241
- logger.warning(f"No GLOBAL_REFERENCE key found in 'first' reference of RelationshipElement '{source_sink_relation.id_short}'")
242
- continue
241
+ return source_sink_relations
243
242
 
244
- last_fragment_ref = next(
245
- (key for key in reversed(source_ref.key) if key.type == model.KeyTypes.FRAGMENT_REFERENCE),
246
- None,
247
- )
248
243
 
249
- if last_fragment_ref is None:
250
- logger.warning(f"No FRAGMENT_REFERENCE key found in 'first' reference of RelationshipElement '{source_sink_relation.id_short}'")
251
- continue
244
+ def _get_reference_properties(reference: model.ExternalReference) -> ReferenceProperties | None:
245
+ global_ref = next((key for key in reference.key if key.type == model.KeyTypes.GLOBAL_REFERENCE), None)
252
246
 
253
- relation = SourceSinkRelation()
254
- relation.source = source_sink_relation.first
255
- relation.sink = source_sink_relation.second
256
- relation.aid_submodel_id = global_ref.value
257
- relation.property_name = last_fragment_ref.value
258
- relation.source_parent_path = _get_reference_parent_path(source_ref)
247
+ if global_ref is None:
248
+ logger.warning(f"No GLOBAL_REFERENCE key found in 'first' reference of RelationshipElement '{reference}'")
249
+ return None
259
250
 
260
- source_sink_relations.append(relation)
251
+ last_fragment_ref = next((key for key in reversed(reference.key) if key.type == model.KeyTypes.FRAGMENT_REFERENCE), None)
261
252
 
262
- return source_sink_relations
253
+ if last_fragment_ref is None:
254
+ logger.warning(f"No FRAGMENT_REFERENCE key found in 'first' reference of RelationshipElement '{reference.id_short}'")
255
+ return None
256
+
257
+ parent_path = _get_reference_parent_path(reference)
258
+
259
+ ref_properties = ReferenceProperties()
260
+ ref_properties.submodel_id = global_ref.value
261
+ ref_properties.property_name = last_fragment_ref.value
262
+ ref_properties.parent_path = parent_path
263
+ ref_properties.reference = reference
264
+
265
+ return ref_properties
263
266
 
264
267
 
265
268
  def _get_reference_parent_path(reference: model.ExternalReference) -> list[str]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aas-standard-parser
3
- Version: 0.1.9
3
+ Version: 0.2.1
4
4
  Summary: Some auxiliary functions for parsing standard submodels
5
5
  Author-email: Daniel Klein <daniel.klein@em.ag>
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "aas-standard-parser"
7
- version = "0.1.9"
7
+ version = "0.2.1"
8
8
  description = "Some auxiliary functions for parsing standard submodels"
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
@@ -1,7 +1,7 @@
1
1
  import pytest
2
2
  from basyx.aas import model
3
3
 
4
- from aas_standard_parser.aimc_parser import MappingConfiguration, SourceSinkRelation
4
+ from aas_standard_parser.aimc_parser import MappingConfiguration, SourceSinkRelation, ReferenceProperties
5
5
  import aas_standard_parser.aimc_parser as aimc_parser
6
6
  from aas_standard_parser.utils import create_submodel_from_file
7
7
 
@@ -40,7 +40,6 @@ def test_003_parse_mapping_configuration_element(aimc_submodel: model.submodel):
40
40
 
41
41
  assert configuration is not None
42
42
  _check_interface_ref(configuration)
43
- _check_relations_aid(configuration)
44
43
  _check_relations(configuration)
45
44
 
46
45
  def test_004_parse_mapping_configurations(aimc_submodel: model.submodel):
@@ -56,7 +55,6 @@ def test_004_parse_mapping_configurations(aimc_submodel: model.submodel):
56
55
  assert configuration.aid_submodel_id == "https://fluid40.de/ids/sm/4757_4856_8464_1441"
57
56
 
58
57
  _check_interface_ref(configuration)
59
- _check_relations_aid(configuration)
60
58
  _check_relations(configuration)
61
59
 
62
60
  def _check_interface_ref(configuration: MappingConfiguration):
@@ -74,32 +72,51 @@ def _check_interface_ref(configuration: MappingConfiguration):
74
72
  assert key is not None
75
73
  assert key.value == "https://fluid40.de/ids/sm/4757_4856_8464_1442/Interface_MQTT"
76
74
 
77
- def _check_relations_aid(configuration: MappingConfiguration):
75
+
76
+ def _check_relations(configuration: MappingConfiguration):
78
77
  assert len(configuration.source_sink_relations) > 0
79
78
 
80
79
  relation = configuration.source_sink_relations[0]
81
80
  assert relation is not None
82
- assert relation.aid_submodel_id == configuration.aid_submodel_id
83
81
 
84
- assert relation.property_name is not None
85
- assert relation.property_name == "HandlingC"
82
+ assert relation.source_properties is not None
83
+ assert relation.source_properties.submodel_id == configuration.aid_submodel_id
86
84
 
85
+ assert relation.sink_properties is not None
87
86
 
88
- def _check_relations(configuration: MappingConfiguration):
89
- assert len(configuration.source_sink_relations) > 0
87
+ _check_relations_source(relation.source_properties)
88
+ _check_relations_sink(relation.sink_properties)
89
+ _check_relation_methods(relation)
90
90
 
91
- relation = configuration.source_sink_relations[0]
92
- assert relation is not None
93
- assert relation.source is not None
94
- assert relation.sink is not None
95
- assert relation.source_parent_path is not None
96
- assert len(relation.source_parent_path) == 5
97
- assert relation.source_parent_path[3] == "axes_position"
91
+ def _check_relations_source(reference_properties: ReferenceProperties):
92
+ assert reference_properties is not None
98
93
 
99
- assert isinstance(relation.source, model.ExternalReference)
100
- assert isinstance(relation.sink, model.ExternalReference)
94
+ assert isinstance(reference_properties.reference, model.ExternalReference)
101
95
 
102
- _check_relation_methods(relation)
96
+ assert reference_properties.property_name is not None
97
+ assert reference_properties.property_name == "HandlingC"
98
+
99
+ assert reference_properties.parent_path is not None
100
+ assert len(reference_properties.parent_path) == 5
101
+ assert reference_properties.parent_path[3] == "axes_position"
102
+
103
+ assert reference_properties.submodel_id is not None
104
+ assert reference_properties.submodel_id == reference_properties.reference.key[0].value
105
+
106
+ def _check_relations_sink(reference_properties: ReferenceProperties):
107
+ assert reference_properties is not None
108
+
109
+ assert isinstance(reference_properties.reference, model.ExternalReference)
110
+
111
+ assert reference_properties.property_name is not None
112
+ assert reference_properties.property_name == "HandlingC"
113
+
114
+ assert reference_properties.parent_path is not None
115
+ assert len(reference_properties.parent_path) == 2
116
+ assert reference_properties.parent_path[1] == "AxesPosition"
117
+
118
+ assert reference_properties.submodel_id is not None
119
+ assert reference_properties.submodel_id == reference_properties.reference.key[0].value
103
120
 
104
121
  def _check_relation_methods(relation: SourceSinkRelation):
105
122
  # test to_json methods
@@ -110,6 +127,3 @@ def _check_relation_methods(relation: SourceSinkRelation):
110
127
  sink_json = relation.sink_as_dict()
111
128
  assert sink_json is not None
112
129
  assert "type" in sink_json
113
-
114
- parent_name = relation.get_source_parent_property_group_name()
115
- assert parent_name == "axes_position"