aas-submodel-to-py - AAS Submodel Python Code Generator
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).
Examples
Example of generated classes
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],
):
...
Usage Example of the generated class
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.
Installation
Using PyPI:
pip install aas-submodel-to-py
Or from the repository root:
pip install -e ./aas-submodel-to-py
Supported Input
| 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.
Usage
Command Line
# 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
Python API
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"
)
Running Tests
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.
Support and Contribution
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!
License
This project is licensed under the MIT License. See the LICENSE file for details.
Metadata
Release files for aas-submodel-to-py 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| aas_submodel_to_py-0.2.0.tar.gz | 52.0 kB | With provenance | Details for aas_submodel_to_py-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| aas_submodel_to_py-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for aas_submodel_to_py-0.2.0-py3-none-any.whl |
Total release size: 79.0 kB
Release files / aas_submodel_to_py-0.2.0.tar.gz
| Download URL | aas_submodel_to_py-0.2.0.tar.gz |
|---|---|
| Size | 52.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e0720ae04376fb4e5d7941fc48e8c7a05e7e0c7618c48bbb89a5d3c436cc74ab
|
|
BLAKE2b-256 checksum How to use checksums |
b8f62a16a2207431898c0589091332ca4ccbebb86432af22a6d8c534fb6bf1c1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.
Transparency logRelease files / aas_submodel_to_py-0.2.0-py3-none-any.whl
| Download URL | aas_submodel_to_py-0.2.0-py3-none-any.whl |
|---|---|
| Size | 27.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
16a739ebd51007c75eaed3717361e9e6b6e45d44202c90618f933746357baa34
|
|
BLAKE2b-256 checksum How to use checksums |
ddaed7e5d632aa8d2724fd7a29f273cc5114222d0d3afc0f877d6cd2af03024a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.
Transparency logSecurity for aas-submodel-to-py 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for aas_submodel_to_py-0.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.