Commit 766aa5c7 authored by Torben Miny's avatar Torben Miny
Browse files

Merge branch 'improve/model' into 'master'

Improve/model

Closes #98, #95, #97, #110, and #113

See merge request !65
parents af73a4b0 402f4c39
Pipeline #366501 passed with stages
in 1 minute and 3 seconds
......@@ -3,6 +3,6 @@ The package consists of the python implementation of the AssetAdministrationShel
'Details of the Asset Administration Shell' specification of Plattform Industrie 4.0.
The subpackage 'model' is an implementation of the meta-model of the AAS,
in 'adapter', you can find JSON and XML adapters to translate between the pyaas and JSON/XML schemas;
in 'adapter', you can find JSON and XML adapters to translate between PyI40AAS objects and JSON/XML schemas;
and in 'util', some helpful functionality to actually use the AAS meta-model you created with 'model' is located.
"""
......@@ -2,7 +2,7 @@
This package contains different kinds of adapters.
json
This package offers an adapter for serialization and deserialization of PyAAS objects to/from JSON.
This package offers an adapter for serialization and deserialization of PyI40AAS objects to/from JSON.
xml
This package offers an adapter for serialization and deserialization of PyAAS objects to/from XML.
This package offers an adapter for serialization and deserialization of PyI40AAS objects to/from XML.
"""
......@@ -29,7 +29,7 @@ import itertools
import logging
import os
import re
from typing import Dict, Tuple, IO, Union, List, Set, Optional, Iterable
from typing import Dict, Tuple, IO, Union, List, Set, Optional, Iterable, Iterator
from .xml import read_aas_xml_file, write_aas_xml_file
from .. import model
......@@ -674,6 +674,13 @@ class AbstractSupplementaryFileContainer(metaclass=abc.ABCMeta):
"""
pass # pragma: no cover
@abc.abstractmethod
def __iter__(self) -> Iterator[str]:
"""
Return an iterator over all file names stored in this SupplementaryFileContainer.
"""
pass # pragma: no cover
class DictSupplementaryFileContainer(AbstractSupplementaryFileContainer):
"""
......@@ -723,3 +730,6 @@ class DictSupplementaryFileContainer(AbstractSupplementaryFileContainer):
def __contains__(self, item: object) -> bool:
return item in self._name_map
def __iter__(self) -> Iterator[str]:
return iter(self._name_map)
......@@ -299,7 +299,9 @@ class AASFromJsonDecoder(json.JSONDecoder):
@classmethod
def _construct_operation_variable(
cls, dct: Dict[str, object], object_class=model.OperationVariable) -> model.OperationVariable:
ret = object_class(value=_get_ts(dct, 'value', model.SubmodelElement))
# TODO: remove the following type: ignore comments when mypy supports abstract types for Type[T]
# see https://github.com/python/mypy/issues/5374
ret = object_class(value=_get_ts(dct, 'value', model.SubmodelElement)) # type: ignore
return ret
@classmethod
......@@ -390,7 +392,9 @@ class AASFromJsonDecoder(json.JSONDecoder):
cls._amend_abstract_attributes(ret, dct)
if 'containedElements' in dct:
for element_data in _get_ts(dct, 'containedElements', list):
ret.contained_element.add(cls._construct_aas_reference(element_data, model.Referable))
# TODO: remove the following type: ignore comments when mypy supports abstract types for Type[T]
# see https://github.com/python/mypy/issues/5374
ret.contained_element.add(cls._construct_aas_reference(element_data, model.Referable)) # type: ignore
return ret
@classmethod
......@@ -519,8 +523,11 @@ class AASFromJsonDecoder(json.JSONDecoder):
@classmethod
def _construct_basic_event(cls, dct: Dict[str, object], object_class=model.BasicEvent) -> model.BasicEvent:
# TODO: remove the following type: ignore comments when mypy supports abstract types for Type[T]
# see https://github.com/python/mypy/issues/5374
ret = object_class(id_short=_get_ts(dct, "idShort", str),
observed=cls._construct_aas_reference(_get_ts(dct, 'observed', dict), model.Referable),
observed=cls._construct_aas_reference(_get_ts(dct, 'observed', dict),
model.Referable), # type: ignore
kind=cls._get_kind(dct))
cls._amend_abstract_attributes(ret, dct)
return ret
......@@ -550,9 +557,13 @@ class AASFromJsonDecoder(json.JSONDecoder):
@classmethod
def _construct_relationship_element(
cls, dct: Dict[str, object], object_class=model.RelationshipElement) -> model.RelationshipElement:
# TODO: remove the following type: ignore comments when mypy supports abstract types for Type[T]
# see https://github.com/python/mypy/issues/5374
ret = object_class(id_short=_get_ts(dct, "idShort", str),
first=cls._construct_aas_reference(_get_ts(dct, 'first', dict), model.Referable),
second=cls._construct_aas_reference(_get_ts(dct, 'second', dict), model.Referable),
first=cls._construct_aas_reference(_get_ts(dct, 'first', dict),
model.Referable), # type: ignore
second=cls._construct_aas_reference(_get_ts(dct, 'second', dict),
model.Referable), # type: ignore
kind=cls._get_kind(dct))
cls._amend_abstract_attributes(ret, dct)
return ret
......@@ -561,10 +572,12 @@ class AASFromJsonDecoder(json.JSONDecoder):
def _construct_annotated_relationship_element(
cls, dct: Dict[str, object], object_class=model.AnnotatedRelationshipElement)\
-> model.AnnotatedRelationshipElement:
# TODO: remove the following type: ignore comments when mypy supports abstract types for Type[T]
# see https://github.com/python/mypy/issues/5374
ret = object_class(
id_short=_get_ts(dct, "idShort", str),
first=cls._construct_aas_reference(_get_ts(dct, 'first', dict), model.Referable),
second=cls._construct_aas_reference(_get_ts(dct, 'second', dict), model.Referable),
first=cls._construct_aas_reference(_get_ts(dct, 'first', dict), model.Referable), # type: ignore
second=cls._construct_aas_reference(_get_ts(dct, 'second', dict), model.Referable), # type: ignore
kind=cls._get_kind(dct))
cls._amend_abstract_attributes(ret, dct)
if not cls.stripped and 'annotation' in dct:
......
......@@ -501,7 +501,9 @@ class AASFromXmlDecoder:
"""
Helper function. Doesn't support the object_class parameter. Overwrite construct_aas_reference instead.
"""
return cls.construct_aas_reference_expect_type(element, model.Referable, **kwargs)
# TODO: remove the following type: ignore comments when mypy supports abstract types for Type[T]
# see https://github.com/python/mypy/issues/5374
return cls.construct_aas_reference_expect_type(element, model.Referable, **kwargs) # type: ignore
@classmethod
def _construct_concept_description_reference(cls, element: etree.Element, **kwargs: Any) \
......@@ -534,9 +536,11 @@ class AASFromXmlDecoder:
it will default to the type Referable. This behaviour is wanted in read_aas_xml_element().
"""
keys = cls._construct_key_tuple(element)
type_: Type[model.Referable] = model.Referable
# TODO: remove the following type: ignore comments when mypy supports abstract types for Type[T]
# see https://github.com/python/mypy/issues/5374
type_: Type[model.Referable] = model.Referable # type: ignore
if len(keys) > 0:
type_ = KEY_ELEMENTS_CLASSES_INVERSE.get(keys[-1].type, model.Referable)
type_ = KEY_ELEMENTS_CLASSES_INVERSE.get(keys[-1].type, model.Referable) # type: ignore
return object_class(keys, type_)
@classmethod
......
......@@ -583,7 +583,7 @@ def submodel_to_xml(obj: model.Submodel,
if obj.submodel_element:
for submodel_element in obj.submodel_element:
# TODO: simplify this should our suggestion regarding the XML schema get accepted
# https://git.rwth-aachen.de/acplt/pyaas/-/issues/57
# https://git.rwth-aachen.de/acplt/pyi40aas/-/issues/57
et_submodel_element = _generate_element(NS_AAS+"submodelElement")
et_submodel_element.append(submodel_element_to_xml(submodel_element))
et_submodel_elements.append(et_submodel_element)
......
......@@ -233,6 +233,7 @@ class CouchDBObjectStore(model.AbstractObjectStore):
:param url: URL to the CouchDB
:param database: Name of the Database inside the CouchDB
"""
super().__init__()
self.url: str = url
self.database_name: str = database
......
......@@ -336,8 +336,8 @@ def create_example_submodel() -> model.Submodel:
submodel_element_range = model.Range(
id_short='ExampleRange',
value_type=model.datatypes.Int,
min_=0,
max_=100,
min=0,
max=100,
category='PARAMETER',
description={'en-us': 'Example Range object',
'de': 'Beispiel Range Element'},
......@@ -455,8 +455,8 @@ def create_example_submodel() -> model.Submodel:
parent=None),
model.Range(id_short="ExampleAnnotatedRange",
value_type=model.datatypes.Integer,
min_=1,
max_=5,
min=1,
max=5,
parent=None)
},
category='PARAMETER',
......@@ -659,23 +659,23 @@ def create_example_asset_administration_shell(concept_dictionary: model.ConceptD
parent=None,
administration=model.AdministrativeInformation(version='0.9',
revision='0'),
security_=None,
submodel_={model.AASReference((model.Key(type_=model.KeyElements.SUBMODEL,
local=False,
value='https://acplt.org/Test_Submodel',
id_type=model.KeyType.IRI),),
model.Submodel),
model.AASReference((model.Key(type_=model.KeyElements.SUBMODEL,
local=False,
value='http://acplt.org/Submodels/Assets/TestAsset/Identification',
id_type=model.KeyType.IRI),),
model.Submodel),
model.AASReference((model.Key(type_=model.KeyElements.SUBMODEL,
local=False,
value='http://acplt.org/Submodels/Assets/TestAsset/BillOfMaterial',
id_type=model.KeyType.IRI),),
model.Submodel),
},
security=None,
submodel={model.AASReference((model.Key(type_=model.KeyElements.SUBMODEL,
local=False,
value='https://acplt.org/Test_Submodel',
id_type=model.KeyType.IRI),),
model.Submodel),
model.AASReference((model.Key(type_=model.KeyElements.SUBMODEL,
local=False,
value='http://acplt.org/Submodels/Assets/TestAsset/Identification',
id_type=model.KeyType.IRI),),
model.Submodel),
model.AASReference((model.Key(type_=model.KeyElements.SUBMODEL,
local=False,
value='http://acplt.org/Submodels/Assets/TestAsset/BillOfMaterial',
id_type=model.KeyType.IRI),),
model.Submodel),
},
concept_dictionary=[concept_dictionary],
view=[],
derived_from=model.AASReference((model.Key(type_=model.KeyElements.ASSET_ADMINISTRATION_SHELL,
......
......@@ -202,16 +202,16 @@ def create_example_asset_administration_shell(concept_dictionary: model.ConceptD
model.Asset),
identification=model.Identifier(id_='https://acplt.org/Test_AssetAdministrationShell_Mandatory',
id_type=model.IdentifierType.IRI),
submodel_={model.AASReference((model.Key(type_=model.KeyElements.SUBMODEL,
local=False,
value='https://acplt.org/Test_Submodel_Mandatory',
id_type=model.KeyType.IRI),),
model.Submodel),
model.AASReference((model.Key(type_=model.KeyElements.SUBMODEL,
local=False,
value='https://acplt.org/Test_Submodel2_Mandatory',
id_type=model.KeyType.IRI),),
model.Submodel)},
submodel={model.AASReference((model.Key(type_=model.KeyElements.SUBMODEL,
local=False,
value='https://acplt.org/Test_Submodel_Mandatory',
id_type=model.KeyType.IRI),),
model.Submodel),
model.AASReference((model.Key(type_=model.KeyElements.SUBMODEL,
local=False,
value='https://acplt.org/Test_Submodel2_Mandatory',
id_type=model.KeyType.IRI),),
model.Submodel)},
concept_dictionary=[concept_dictionary])
return asset_administration_shell
......
......@@ -102,8 +102,8 @@ def create_example_submodel() -> model.Submodel:
submodel_element_range = model.Range(
id_short='ExampleRange',
value_type=model.datatypes.Int,
min_=0,
max_=100,
min=0,
max=100,
category='PARAMETER',
description={'en-us': 'Example Range object',
'de': 'Beispiel Range Element'},
......@@ -204,8 +204,8 @@ def create_example_submodel() -> model.Submodel:
parent=None),
model.Range(id_short="ExampleAnnotatedRange",
value_type=model.datatypes.Integer,
min_=1,
max_=5,
min=1,
max=5,
parent=None)
},
category='PARAMETER',
......@@ -412,12 +412,12 @@ def create_example_asset_administration_shell(concept_dictionary: model.ConceptD
parent=None,
administration=model.AdministrativeInformation(version='0.9',
revision='0'),
security_=None,
submodel_={model.AASReference((model.Key(type_=model.KeyElements.SUBMODEL,
local=False,
value='https://acplt.org/Test_Submodel_Missing',
id_type=model.KeyType.IRI),),
model.Submodel)},
security=None,
submodel={model.AASReference((model.Key(type_=model.KeyElements.SUBMODEL,
local=False,
value='https://acplt.org/Test_Submodel_Missing',
id_type=model.KeyType.IRI),),
model.Submodel)},
concept_dictionary=[concept_dictionary],
view=[view, view_2],
derived_from=None)
......
......@@ -63,8 +63,8 @@ def create_example_submodel_template() -> model.Submodel:
submodel_element_range = model.Range(
id_short='ExampleRange',
value_type=model.datatypes.Int,
min_=None,
max_=100,
min=None,
max=100,
category='PARAMETER',
description={'en-us': 'Example Range object',
'de': 'Beispiel Range Element'},
......@@ -79,8 +79,8 @@ def create_example_submodel_template() -> model.Submodel:
submodel_element_range_2 = model.Range(
id_short='ExampleRange2',
value_type=model.datatypes.Int,
min_=0,
max_=None,
min=0,
max=None,
category='PARAMETER',
description={'en-us': 'Example Range object',
'de': 'Beispiel Range Element'},
......
......@@ -72,7 +72,7 @@ submodel = model.Submodel(
aas = model.AssetAdministrationShell(
identification=model.Identifier('https://acplt.org/Simple_AAS', model.IdentifierType.IRI),
asset=model.AASReference.from_referable(asset),
submodel_={model.AASReference.from_referable(submodel)}
submodel={model.AASReference.from_referable(submodel)}
)
......
......@@ -55,7 +55,7 @@ submodel = model.Submodel(
aashell = model.AssetAdministrationShell(
identification=model.Identifier('https://acplt.org/Simple_AAS', model.IdentifierType.IRI),
asset=model.AASReference.from_referable(asset),
submodel_={model.AASReference.from_referable(submodel)}
submodel={model.AASReference.from_referable(submodel)}
)
......
......@@ -53,7 +53,7 @@ submodel = Submodel(
aas = AssetAdministrationShell(
identification=model.Identifier('https://acplt.org/Simple_AAS', model.IdentifierType.IRI),
asset=model.AASReference.from_referable(asset),
submodel_={model.AASReference.from_referable(submodel)}
submodel={model.AASReference.from_referable(submodel)}
)
......@@ -115,7 +115,7 @@ property_reference = model.AASReference(
value='ExampleProperty',
id_type=model.KeyType.IDSHORT),
),
type_=model.Property
target_type=model.Property
)
# Now, we can resolve this new reference.
......
......@@ -20,9 +20,9 @@ This module contains the following classes from an up-to-down-level:
from typing import Optional, Set, Iterable, TYPE_CHECKING
from . import base, security, concept
if TYPE_CHECKING:
from . import submodel
from . import base, concept
from .security import Security
from .submodel import Submodel
class View(base.Referable, base.HasSemantics):
......@@ -89,8 +89,8 @@ class Asset(base.Identifiable):
description: Optional[base.LangStringSet] = None,
parent: Optional[base.Namespace] = None,
administration: Optional[base.AdministrativeInformation] = None,
asset_identification_model: Optional[base.AASReference["submodel.Submodel"]] = None,
bill_of_material: Optional[base.AASReference["submodel.Submodel"]] = None):
asset_identification_model: Optional[base.AASReference[Submodel]] = None,
bill_of_material: Optional[base.AASReference[Submodel]] = None):
"""
Initializer of Asset
......@@ -117,8 +117,8 @@ class Asset(base.Identifiable):
self.description: Optional[base.LangStringSet] = dict() if description is None else description
self.parent: Optional[base.Namespace] = parent
self.administration: Optional[base.AdministrativeInformation] = administration
self.asset_identification_model: Optional[base.AASReference["submodel.Submodel"]] = asset_identification_model
self.bill_of_material: Optional[base.AASReference["submodel.Submodel"]] = bill_of_material
self.asset_identification_model: Optional[base.AASReference[Submodel]] = asset_identification_model
self.bill_of_material: Optional[base.AASReference[Submodel]] = bill_of_material
class AssetAdministrationShell(base.Identifiable, base.Namespace):
......@@ -141,8 +141,8 @@ class AssetAdministrationShell(base.Identifiable, base.Namespace):
description: Optional[base.LangStringSet] = None,
parent: Optional[base.Namespace] = None,
administration: Optional[base.AdministrativeInformation] = None,
security_: Optional[security.Security] = None,
submodel_: Optional[Set[base.AASReference["submodel.Submodel"]]] = None,
security: Optional[Security] = None,
submodel: Optional[Set[base.AASReference[Submodel]]] = None,
concept_dictionary: Iterable[concept.ConceptDictionary] = (),
view: Iterable[View] = (),
derived_from: Optional[base.AASReference["AssetAdministrationShell"]] = None):
......@@ -157,8 +157,8 @@ class AssetAdministrationShell(base.Identifiable, base.Namespace):
:param description: Description or comments on the element. (from base.Referable)
:param parent: Reference to the next referable parent element of the element. (from base.Referable)
:param administration: Administrative information of an identifiable element. (from base.Identifiable)
:param security_: Definition of the security relevant aspects of the AAS.
:param submodel_: Unordered list of submodels to describe typically the asset of an AAS.
:param security: Definition of the security relevant aspects of the AAS.
:param submodel: Unordered list of submodels to describe typically the asset of an AAS.
:param concept_dictionary: Unordered list of concept dictionaries. The concept dictionaries typically contain
only descriptions for elements that are also used within the AAS
:param view: Unordered list of stakeholder specific views that can group the elements of the AAS.
......@@ -172,10 +172,10 @@ class AssetAdministrationShell(base.Identifiable, base.Namespace):
self.description: Optional[base.LangStringSet] = dict() if description is None else description
self.parent: Optional[base.Namespace] = parent
self.administration: Optional[base.AdministrativeInformation] = administration
self.derived_from: Optional[base.AASReference["AssetAdministrationShell"]] = derived_from
self.security: Optional[security.Security] = security_
self.derived_from: Optional[base.AASReference[AssetAdministrationShell]] = derived_from
self.security: Optional[Security] = security
self.asset: base.AASReference[Asset] = asset
self.submodel: Set[base.AASReference["submodel.Submodel"]] = set() if submodel_ is None else submodel_
self.submodel: Set[base.AASReference[Submodel]] = set() if submodel is None else submodel
self.concept_dictionary: base.NamespaceSet[concept.ConceptDictionary] = \
base.NamespaceSet(self, concept_dictionary)
self.view: base.NamespaceSet[View] = base.NamespaceSet(self, view)
......@@ -345,7 +345,7 @@ class AdministrativeInformation:
return self.version == other.version and self._revision == other._revision
def __repr__(self) -> str:
return "AdminstrativeInformation(version={}, revision={})".format(self.version, self.revision)
return "AdministrativeInformation(version={}, revision={})".format(self.version, self.revision)
revision = property(_get_revision, _set_revision)
......@@ -414,7 +414,7 @@ class Referable(metaclass=abc.ABCMeta):
This is used to specify where the Referable should be updated from and committed to.
Default is an empty string, making it use the source of its ancestor, if possible.
"""
@abc.abstractmethod
def __init__(self):
super().__init__()
self._id_short: Optional[str] = ""
......@@ -666,7 +666,7 @@ class AASReference(Reference, Generic[_RT]):
"""
def __init__(self,
key: Tuple[Key, ...],
type_: Type[_RT]):
target_type: Type[_RT]):
"""
Initializer of AASReference
......@@ -680,7 +680,7 @@ class AASReference(Reference, Generic[_RT]):
# TODO check keys for validity. GlobalReference and Fragment-Type keys are not allowed here
super().__init__(key)
self.type: Type[_RT]
object.__setattr__(self, 'type', type_)
object.__setattr__(self, 'type', target_type)
def resolve(self, provider_: "provider.AbstractObjectProvider") -> _RT:
"""
......@@ -788,7 +788,7 @@ class Identifiable(Referable, metaclass=abc.ABCMeta):
:ivar administration: Administrative information of an identifiable element.
:ivar identification: The globally unique identification of the element.
"""
@abc.abstractmethod
def __init__(self):
super().__init__()
self.administration: Optional[AdministrativeInformation] = None
......@@ -808,7 +808,7 @@ class HasSemantics(metaclass=abc.ABCMeta):
The semantic id may either reference an external global id or it may reference a referable model
element of kind=Type that defines the semantics of the element.
"""
@abc.abstractmethod
def __init__(self):
super().__init__()
self.semantic_id: Optional[Reference] = None
......@@ -823,7 +823,7 @@ class HasKind(metaclass=abc.ABCMeta):
:ivar kind: Kind of the element: either type or instance. Default = Instance.
"""
@abc.abstractmethod
def __init__(self):
super().__init__()
self._kind: ModelingKind = ModelingKind.INSTANCE
......@@ -839,7 +839,7 @@ class Constraint(metaclass=abc.ABCMeta):
<< abstract >>
"""
@abc.abstractmethod
def __init__(self):
pass
......@@ -852,7 +852,7 @@ class Qualifiable(metaclass=abc.ABCMeta):
:ivar qualifier: Unordered list of Constraints that gives additional qualification of a qualifiable element.
"""
@abc.abstractmethod
def __init__(self):
super().__init__()
self.qualifier: Set[Constraint] = set()
......@@ -993,6 +993,7 @@ class Namespace(metaclass=abc.ABCMeta):
:ivar namespace_element_sets: A list of all NamespaceSets of this Namespace
"""
@abc.abstractmethod
def __init__(self) -> None:
super().__init__()
self.namespace_element_sets: List[NamespaceSet] = []
......@@ -1008,6 +1009,20 @@ class Namespace(metaclass=abc.ABCMeta):
return dict_.get_referable(id_short)
raise KeyError("Referable with id_short {} not found in this namespace".format(id_short))
def remove_referable(self, id_short: str) -> None:
"""
Remove a Referable from this Namespace by its id_short
:raises KeyError: If no such Referable can be found
"""
for dict_ in self.namespace_element_sets:
if id_short in dict_:
return dict_.remove(id_short)
raise KeyError("Referable with id_short {} not found in this namespace".format(id_short))
def __iter__(self) -> Iterator[_RT]:
return itertools.chain.from_iterable(self.namespace_element_sets)
class NamespaceSet(MutableSet[_RT], Generic[_RT]):
"""
......@@ -1244,12 +1259,3 @@ class OrderedNamespaceSet(NamespaceSet[_RT], MutableSequence[_RT], Generic[_RT])
for o in self._order[i]:
super().remove(o)
del self._order[i]
class DataSpecificationContent(metaclass=abc.ABCMeta):
"""
Content of a DataSpecification.
<<abstract>>
"""
pass
......@@ -28,7 +28,7 @@ import base64
import datetime
import decimal
import re
from typing import NamedTuple, Type, Union, Dict, Optional
from typing import Type, Union, Dict, Optional
import dateutil.relativedelta
......
......@@ -34,7 +34,7 @@ class AbstractObjectProvider(metaclass=abc.ABCMeta):
This may include looking up the object's endpoint in a registry and fetching it from an HTTP server or a
database.
:param identifier:
:param identifier: The identifier of the object to return
:return: The Identifiable object (or a proxy object for a remote Identifiable object)
:raises KeyError: If no such Referable can be found
"""
......@@ -44,6 +44,7 @@ class AbstractObjectProvider(metaclass=abc.ABCMeta):
"""
Find an object in this set by its identification, with fallback parameter
:param identifier: The identifier of the object to return
:param default: An object to be returned, if no object with the given identification is found
:return: The Identifiable object with the given identification in the provider. Otherwise the `default` object
or None, if none is given.
......@@ -65,7 +66,9 @@ class AbstractObjectStore(AbstractObjectProvider, MutableSet[_IT], Generic[_IT],
delete objects (i.e. behave like a Python set). This includes local object stores (like `DictObjectStore`) and
database clients.
"""
pass
@abc.abstractmethod
def __init__(self):
pass
def update(self, other: Iterable[_IT]) -> None:
for x in other:
......@@ -77,6 +80,7 @@ class DictObjectStore(AbstractObjectStore[_IT], Generic[_IT]):
A local in-memory object store for Identifiable Objects, backed by a dict, mapping Identifier → Identifiable
"""
def __init__(self, objects: Iterable[_IT] = ()) -> None:
super().__init__()
self._backend: Dict[Identifier, _IT] = {}
for x in objects:
self.add(x)
......
......@@ -30,7 +30,7 @@ class SubmodelElement(base.Referable, base.Qualifiable, base.HasSemantics, base.
The property instances (kind=Instance) typically have a value. A property instance is also called
property-value pair in certain standards.
"""
@abc.abstractmethod
def __init__(self,
id_short: str,
category: Optional[str] = None,
......@@ -133,7 +133,7 @@ class DataElement(SubmodelElement, metaclass=abc.ABCMeta):