Observed since 20 Oct, 17:04 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Generate Submodel-Specific classes with filled metainformation derived from submodel templates
aas-submodel-to-py is a code generator tool built on top of the
BaSyx-Python-SDK.
It is designed to generate Submodel-specific classes and classes for its
submodel elements with filled meta-information derived from submodel templates.
These generated classes act as child classes of the BaSyx-Python-SDK classes and
represent classes of the Asset Administration Shell Metamodel.
The hierarchical structure of the generated submodel-specific class includes
all the required submodel element-specific classes. Input files can be .aasx,
.json, or .xml format (see Supported Input).
Here's a snippet of the classes generated from the
Digital Nameplate 3.0.1
submodel template (... marks omitted lines). Each submodel element gets a class nested in the class of
its submodel or collection. Its init takes the values of the element (e.g. value) and its submodel elements;
metadata like semantic_id or description are keyword arguments, typed by a TypedDict per BaSyx class
(e.g. PropertyMetadata), and default to the template's values, which template_defaults() returns.
The classes build instances (kind=Instance), so template qualifiers like SMT/Cardinality, which are only
allowed in templates, aren't taken over. Each module starts with a few helpers its classes share:
from typing import Any, Iterable, Optional, Tuple, TypedDict, Union, Unpack, cast
from basyx.aas import model as aas
from basyx.aas.model import datatypes as xsd
def global_ref(value: str) -> aas.ExternalReference:
"""External reference to the global identifier `value`, e.g. a semantic ID"""
return aas.ExternalReference((aas.Key(aas.KeyTypes.GLOBAL_REFERENCE, value),))
def collect_submodel_elements(*elements: Any, number_repeated: bool = True) -> list[aas.SubmodelElement]:
"""Collect the submodel elements passed to an init in one list: single elements, unless None,
and the elements of iterables, whose idShorts get an index if `number_repeated` (e.g. Keyword00)"""
...
class GeneratedSubmodelElementList(aas.SubmodelElementList):
"""SubmodelElementList, whose items may be instances of subclasses of type_value_list_element,
such as the generated classes of its items"""
...
class MultiLanguagePropertyMetadata(TypedDict, total=False):
"""Metadata of aas.MultiLanguageProperty, passed as keyword arguments to its generated classes"""
id_short: Optional[str]
...
semantic_id: Optional[aas.Reference]
...
class Nameplate(aas.Submodel):
class URIOfTheProduct(aas.Property):
...
class ManufacturerName(aas.MultiLanguageProperty):
@staticmethod
def template_defaults() -> MultiLanguagePropertyMetadata:
return {
"id_short": r"ManufacturerName",
"semantic_id": global_ref(r"0112/2///61987#ABA565#009"),
"supplemental_semantic_id": (global_ref(r"0173-1#02-AAO677#004"),),
}
def __init__(self, value: aas.MultiLanguageTextType, **kwargs: Unpack[MultiLanguagePropertyMetadata]):
super().__init__(value=value, **(self.template_defaults() | kwargs))
...
class Markings(GeneratedSubmodelElementList):
...
...
@staticmethod
def template_defaults() -> SubmodelMetadata:
return {
"id_short": r"Nameplate",
"description": aas.MultiLanguageTextType(
dict_={r"en": r"Contains the nameplate information attached to the product"}
),
"administration": aas.AdministrativeInformation(
version=r"3",
revision=r"0",
...
template_id=r"https://admin-shell.io/idta-02006-3-0",
...
),
"semantic_id": global_ref(r"https://admin-shell.io/idta/nameplate/3/0/Nameplate"),
}
def __init__(
self,
id_: str,
uRIOfTheProduct: Union[xsd.AnyURI, URIOfTheProduct],
manufacturerName: Union[aas.MultiLanguageTextType, ManufacturerName],
...
yearOfConstruction: Optional[Union[str, YearOfConstruction]] = None,
...
markings: Optional[Union[Iterable[Markings.Markings_item], Markings]] = None,
...
**kwargs: Unpack[SubmodelMetadata],
):
...
Here's an example of instantiating the generated Nameplate submodel. The classes generated from
Digital Nameplate 3.0.1 are part of py-aas-submodels:
from basyx.aas.model import MultiLanguageTextType
from py_aas_submodels.digital_nameplate_3_0_1 import Nameplate
nameplate = Nameplate(
id_="https://example.com/ids/sm/nameplate-001",
uRIOfTheProduct="https://www.domain-abc.com/Model-Nr-1234",
manufacturerName=MultiLanguageTextType({"de": "Muster AG"}),
manufacturerProductDesignation=MultiLanguageTextType({"en": "ABC-123"}),
addressInformation=Nameplate.AddressInformation(),
orderCodeOfManufacturer="ABC-123-XYZ",
yearOfConstruction="2022",
serialNumber=Nameplate.SerialNumber("12345678"),
)
All required submodel elements are positional arguments; optional elements default to None.
Metadata is passed as keyword arguments, e.g. Nameplate(..., id_short="Nameplate01"), and replaces the
template's value (None removes it); type checkers like mypy report unknown or wrongly typed metadata.
Instead of submodel elements (e.g. Nameplate.SerialNumber("12345678")), raw values can be passed
(e.g. yearOfConstruction="2022"); multi-language values are passed as MultiLanguageTextType.
Properties with a default value in the template (SMT/DefaultValue, else SMT/InitialValue) can be
created without value, e.g. PAMSpecificationSheet.GeneralInformation.SafetyMeasure().
Of elements marked as alternatives (SMT/EitherOr), only one may be given; passing more raises a ValueError.
Values restricted by the template (SMT/AllowedValue, SMT/AllowedRange, FormChoices, enumeration) are
checked as well and available as class attributes, e.g. SafetyMeasure.ALLOWED_VALUES == ("True", "False").
Lists (SubmodelElementList) take an iterable of their items or raw values, e.g. phases=["A1", "B2"].
List items have no idShort by default, as it is optional since AAS metamodel 3.1.
The output is auto-formatted with Black and passes the type checker mypy.
Using PyPI:
pip install aas-submodel-to-py
Or from the repository root:
pip install -e ./aas-submodel-to-py
| Format | AAS metamodel 3.1 | AAS metamodel 3.0 |
|---|---|---|
.json | ✅ | ✅ |
.aasx | ✅ | ❌ |
.xml | ✅ | ❌ |
Files are read with the BaSyx Python SDK (≥ 2.1.0), which implements AAS metamodel 3.1 and can't
read AASX and XML files of metamodel 3.0. Many templates on the IDTA website are still such files.
For those, use the JSON version of the template, or its _forAASMetamodelV3.1 variant; both are
published in admin-shell-io/submodel-templates.
For such files, as for any file without a submodel, the generator raises a NoSubmodelError
(submodel_to_code exits with an error message) instead of writing a module.
# Minimal: output .py is generated next to the input file
# e.g. IDTA-02006-2-0_Submodel_Digital Nameplate.aasx → IDTA_02006_2_0_Submodel_Digital_Nameplate.py
submodel_to_code -i /some/path/DigitalNameplate.aasx
# Write to a specific output directory (filename still auto-derived)
submodel_to_code -i /some/path/DigitalNameplate.aasx -d /some/other/path/
# Write to an explicit output file path
submodel_to_code -i /some/path/DigitalNameplate.aasx -o /some/path/output.py
# Overwrite an existing output file
submodel_to_code -i /some/path/DigitalNameplate.aasx --force
| Flag | Long form | Description | Required |
|---|---|---|---|
-i | --aas_path | Input AAS file (.aasx, .json, or .xml) | Yes |
-o | --outpath | Output .py file path (mutually exclusive with -d) | No |
-d | --outdir | Output directory; filename is derived from the input filename (mutually exclusive with -o) | No |
-f | --force | Overwrite the output file if it already exists | No |
If neither -o nor -d is given, the output file is written next to the input file with hyphens and spaces in the name replaced by underscores.
If the entry-point is not on PATH, use the module invocation:
python -m aas_submodel_to_py.submodel_to_code \
-i /some/path/DigitalNameplate.aasx \
-o /some/path/output.py
from aas_submodel_to_py import SubmodelCodegen
codegen = SubmodelCodegen()
# Generate from an AAS file (.aasx, .json, or .xml)
codegen.generate_from(
input_file="/some/path/DigitalNameplate.aasx",
output_file="nameplate.py"
)
# If you already have an AAS object store loaded in memory
codegen.generate_from_obj_store(
obj_store=my_existing_store,
output_file="output.py"
)
From the repository root:
pip install -e "./aas-submodel-to-py[test]"
python -m pytest aas-submodel-to-py/tests
The Tests workflow runs these tests, and the import checks of all
modules in py-aas-submodels, on Python 3.11 and 3.14
for every push to master/develop and every pull request.
If you encounter any issues, or want to contribute to the project, feel free to open an issue or a pull request. Your contributions are always welcome!
This project is licensed under the MIT License. See the LICENSE file for details.
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.2.0 | 12 Oct 2026 | 5 |
This describes our collected data; it is not a security assessment.
Shared repository data · GitHub
Observed since 20 Oct, 17:04 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:b4d6583baf1600f0d1ca1f00311bedbbf38e9c6bcb1bc8a7b31ac20ae6466c14