aas-core-codegen 0.0.16__py3-none-any.whl
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.
- aas_core_codegen/__init__.py +6 -0
- aas_core_codegen/__main__.py +8 -0
- aas_core_codegen/common.py +500 -0
- aas_core_codegen/cpp/__init__.py +1 -0
- aas_core_codegen/cpp/aas_common/__init__.py +6 -0
- aas_core_codegen/cpp/aas_common/_generate.py +713 -0
- aas_core_codegen/cpp/common.py +681 -0
- aas_core_codegen/cpp/constants/__init__.py +6 -0
- aas_core_codegen/cpp/constants/_generate.py +568 -0
- aas_core_codegen/cpp/description.py +654 -0
- aas_core_codegen/cpp/enhancing/__init__.py +4 -0
- aas_core_codegen/cpp/enhancing/_generate.py +993 -0
- aas_core_codegen/cpp/iteration/__init__.py +6 -0
- aas_core_codegen/cpp/iteration/_generate.py +2332 -0
- aas_core_codegen/cpp/jsonization/__init__.py +6 -0
- aas_core_codegen/cpp/jsonization/_generate.py +2619 -0
- aas_core_codegen/cpp/main.py +694 -0
- aas_core_codegen/cpp/naming.py +170 -0
- aas_core_codegen/cpp/optionaling.py +557 -0
- aas_core_codegen/cpp/pattern/__init__.py +6 -0
- aas_core_codegen/cpp/pattern/_generate.py +508 -0
- aas_core_codegen/cpp/revm/__init__.py +6 -0
- aas_core_codegen/cpp/revm/_generate.py +1149 -0
- aas_core_codegen/cpp/stringification/__init__.py +5 -0
- aas_core_codegen/cpp/stringification/_generate.py +955 -0
- aas_core_codegen/cpp/structure/__init__.py +7 -0
- aas_core_codegen/cpp/structure/_generate.py +1503 -0
- aas_core_codegen/cpp/transpilation.py +1383 -0
- aas_core_codegen/cpp/unrolling.py +159 -0
- aas_core_codegen/cpp/verification/__init__.py +6 -0
- aas_core_codegen/cpp/verification/_generate.py +3073 -0
- aas_core_codegen/cpp/visitation/__init__.py +6 -0
- aas_core_codegen/cpp/visitation/_generate.py +521 -0
- aas_core_codegen/cpp/wstringification/__init__.py +5 -0
- aas_core_codegen/cpp/wstringification/_generate.py +586 -0
- aas_core_codegen/cpp/xmlization/__init__.py +6 -0
- aas_core_codegen/cpp/xmlization/_generate.py +5373 -0
- aas_core_codegen/cpp/yielding.py +201 -0
- aas_core_codegen/csharp/__init__.py +1 -0
- aas_core_codegen/csharp/common.py +224 -0
- aas_core_codegen/csharp/constants/__init__.py +5 -0
- aas_core_codegen/csharp/constants/_generate.py +409 -0
- aas_core_codegen/csharp/copying/__init__.py +4 -0
- aas_core_codegen/csharp/copying/_generate.py +498 -0
- aas_core_codegen/csharp/description.py +1103 -0
- aas_core_codegen/csharp/enhancing/__init__.py +4 -0
- aas_core_codegen/csharp/enhancing/_generate.py +667 -0
- aas_core_codegen/csharp/jsonization/__init__.py +4 -0
- aas_core_codegen/csharp/jsonization/_generate.py +1630 -0
- aas_core_codegen/csharp/main.py +421 -0
- aas_core_codegen/csharp/naming.py +157 -0
- aas_core_codegen/csharp/reporting/__init__.py +4 -0
- aas_core_codegen/csharp/reporting/_generate.py +266 -0
- aas_core_codegen/csharp/stringification/__init__.py +4 -0
- aas_core_codegen/csharp/stringification/_generate.py +243 -0
- aas_core_codegen/csharp/structure/__init__.py +6 -0
- aas_core_codegen/csharp/structure/_generate.py +1341 -0
- aas_core_codegen/csharp/transpilation.py +990 -0
- aas_core_codegen/csharp/unrolling.py +211 -0
- aas_core_codegen/csharp/verification/__init__.py +6 -0
- aas_core_codegen/csharp/verification/_generate.py +1457 -0
- aas_core_codegen/csharp/visitation/__init__.py +5 -0
- aas_core_codegen/csharp/visitation/_generate.py +579 -0
- aas_core_codegen/csharp/xmlization/__init__.py +4 -0
- aas_core_codegen/csharp/xmlization/_generate.py +1980 -0
- aas_core_codegen/golang/__init__.py +1 -0
- aas_core_codegen/golang/aas_common/__init__.py +4 -0
- aas_core_codegen/golang/aas_common/_generate.py +152 -0
- aas_core_codegen/golang/common.py +303 -0
- aas_core_codegen/golang/constants/__init__.py +5 -0
- aas_core_codegen/golang/constants/_generate.py +339 -0
- aas_core_codegen/golang/description.py +501 -0
- aas_core_codegen/golang/enhancing/__init__.py +4 -0
- aas_core_codegen/golang/enhancing/_generate.py +527 -0
- aas_core_codegen/golang/jsonization/__init__.py +4 -0
- aas_core_codegen/golang/jsonization/_generate.py +1740 -0
- aas_core_codegen/golang/main.py +368 -0
- aas_core_codegen/golang/naming.py +412 -0
- aas_core_codegen/golang/pointering.py +631 -0
- aas_core_codegen/golang/reporting/__init__.py +4 -0
- aas_core_codegen/golang/reporting/_generate.py +218 -0
- aas_core_codegen/golang/stringification/__init__.py +4 -0
- aas_core_codegen/golang/stringification/_generate.py +394 -0
- aas_core_codegen/golang/structure/__init__.py +6 -0
- aas_core_codegen/golang/structure/_generate.py +1493 -0
- aas_core_codegen/golang/transpilation.py +1191 -0
- aas_core_codegen/golang/unrolling.py +159 -0
- aas_core_codegen/golang/verification/__init__.py +6 -0
- aas_core_codegen/golang/verification/_generate.py +1513 -0
- aas_core_codegen/golang/xmlization/__init__.py +4 -0
- aas_core_codegen/golang/xmlization/_generate.py +2507 -0
- aas_core_codegen/infer_for_schema/__init__.py +21 -0
- aas_core_codegen/infer_for_schema/_inline.py +693 -0
- aas_core_codegen/infer_for_schema/_len.py +527 -0
- aas_core_codegen/infer_for_schema/_pattern.py +311 -0
- aas_core_codegen/infer_for_schema/_set.py +394 -0
- aas_core_codegen/infer_for_schema/_stringify.py +201 -0
- aas_core_codegen/infer_for_schema/_types.py +135 -0
- aas_core_codegen/infer_for_schema/match.py +122 -0
- aas_core_codegen/intermediate/__init__.py +78 -0
- aas_core_codegen/intermediate/_hierarchy.py +397 -0
- aas_core_codegen/intermediate/_stringify.py +989 -0
- aas_core_codegen/intermediate/_translate.py +5128 -0
- aas_core_codegen/intermediate/_types.py +2901 -0
- aas_core_codegen/intermediate/construction.py +750 -0
- aas_core_codegen/intermediate/doc.py +344 -0
- aas_core_codegen/intermediate/pattern_verification.py +428 -0
- aas_core_codegen/intermediate/revm.py +985 -0
- aas_core_codegen/intermediate/type_inference.py +2266 -0
- aas_core_codegen/java/__init__.py +1 -0
- aas_core_codegen/java/common.py +197 -0
- aas_core_codegen/java/constants/__init__.py +5 -0
- aas_core_codegen/java/constants/_generate.py +334 -0
- aas_core_codegen/java/copying/__init__.py +4 -0
- aas_core_codegen/java/copying/_generate.py +502 -0
- aas_core_codegen/java/description.py +774 -0
- aas_core_codegen/java/enhancing/__init__.py +4 -0
- aas_core_codegen/java/enhancing/_generate.py +820 -0
- aas_core_codegen/java/generation/__init__.py +5 -0
- aas_core_codegen/java/generation/_generate.py +285 -0
- aas_core_codegen/java/jsonization/__init__.py +4 -0
- aas_core_codegen/java/jsonization/_generate.py +1472 -0
- aas_core_codegen/java/main.py +438 -0
- aas_core_codegen/java/naming.py +187 -0
- aas_core_codegen/java/optional.py +514 -0
- aas_core_codegen/java/reporting/__init__.py +4 -0
- aas_core_codegen/java/reporting/_generate.py +248 -0
- aas_core_codegen/java/stringification/__init__.py +4 -0
- aas_core_codegen/java/stringification/_generate.py +212 -0
- aas_core_codegen/java/structure/__init__.py +6 -0
- aas_core_codegen/java/structure/_generate.py +1767 -0
- aas_core_codegen/java/transpilation.py +1111 -0
- aas_core_codegen/java/verification/__init__.py +6 -0
- aas_core_codegen/java/verification/_generate.py +1536 -0
- aas_core_codegen/java/visitation/__init__.py +5 -0
- aas_core_codegen/java/visitation/_generate.py +689 -0
- aas_core_codegen/java/xmlization/__init__.py +4 -0
- aas_core_codegen/java/xmlization/_generate.py +2274 -0
- aas_core_codegen/jsonld/__init__.py +1 -0
- aas_core_codegen/jsonld/main.py +455 -0
- aas_core_codegen/jsonschema/__init__.py +1 -0
- aas_core_codegen/jsonschema/main.py +982 -0
- aas_core_codegen/main.py +245 -0
- aas_core_codegen/naming.py +133 -0
- aas_core_codegen/opcua/__init__.py +1 -0
- aas_core_codegen/opcua/main.py +1525 -0
- aas_core_codegen/opcua/naming.py +126 -0
- aas_core_codegen/parse/__init__.py +46 -0
- aas_core_codegen/parse/_rules.py +796 -0
- aas_core_codegen/parse/_stringify.py +532 -0
- aas_core_codegen/parse/_translate.py +3940 -0
- aas_core_codegen/parse/_types.py +973 -0
- aas_core_codegen/parse/retree/__init__.py +46 -0
- aas_core_codegen/parse/retree/_fix.py +434 -0
- aas_core_codegen/parse/retree/_parse.py +1143 -0
- aas_core_codegen/parse/retree/_render.py +298 -0
- aas_core_codegen/parse/retree/_stringify.py +199 -0
- aas_core_codegen/parse/retree/_types.py +362 -0
- aas_core_codegen/parse/retree/_visitor.py +70 -0
- aas_core_codegen/parse/tree.py +1303 -0
- aas_core_codegen/protobuf/__init__.py +1 -0
- aas_core_codegen/protobuf/common.py +225 -0
- aas_core_codegen/protobuf/description.py +1102 -0
- aas_core_codegen/protobuf/main.py +115 -0
- aas_core_codegen/protobuf/naming.py +143 -0
- aas_core_codegen/protobuf/structure/__init__.py +6 -0
- aas_core_codegen/protobuf/structure/_generate.py +502 -0
- aas_core_codegen/py.typed +1 -0
- aas_core_codegen/python/__init__.py +1 -0
- aas_core_codegen/python/aas_common/__init__.py +4 -0
- aas_core_codegen/python/aas_common/_generate.py +63 -0
- aas_core_codegen/python/common.py +406 -0
- aas_core_codegen/python/constants/__init__.py +5 -0
- aas_core_codegen/python/constants/_generate.py +377 -0
- aas_core_codegen/python/description.py +508 -0
- aas_core_codegen/python/jsonization/__init__.py +4 -0
- aas_core_codegen/python/jsonization/_generate.py +1391 -0
- aas_core_codegen/python/main.py +323 -0
- aas_core_codegen/python/naming.py +255 -0
- aas_core_codegen/python/stringification/__init__.py +4 -0
- aas_core_codegen/python/stringification/_generate.py +129 -0
- aas_core_codegen/python/structure/__init__.py +6 -0
- aas_core_codegen/python/structure/_generate.py +1801 -0
- aas_core_codegen/python/transpilation.py +958 -0
- aas_core_codegen/python/unrolling.py +156 -0
- aas_core_codegen/python/verification/__init__.py +6 -0
- aas_core_codegen/python/verification/_generate.py +1471 -0
- aas_core_codegen/python/xmlization/__init__.py +4 -0
- aas_core_codegen/python/xmlization/_generate.py +3003 -0
- aas_core_codegen/python_protobuf/__init__.py +1 -0
- aas_core_codegen/python_protobuf/main.py +1424 -0
- aas_core_codegen/python_protobuf/naming.py +85 -0
- aas_core_codegen/rdf_shacl/__init__.py +1 -0
- aas_core_codegen/rdf_shacl/_description.py +351 -0
- aas_core_codegen/rdf_shacl/common.py +206 -0
- aas_core_codegen/rdf_shacl/main.py +114 -0
- aas_core_codegen/rdf_shacl/naming.py +145 -0
- aas_core_codegen/rdf_shacl/rdf.py +435 -0
- aas_core_codegen/rdf_shacl/shacl.py +453 -0
- aas_core_codegen/run.py +124 -0
- aas_core_codegen/smoke/__init__.py +1 -0
- aas_core_codegen/smoke/main.py +219 -0
- aas_core_codegen/specific_implementations.py +72 -0
- aas_core_codegen/stringify.py +333 -0
- aas_core_codegen/typescript/__init__.py +1 -0
- aas_core_codegen/typescript/aas_common/__init__.py +4 -0
- aas_core_codegen/typescript/aas_common/_generate.py +472 -0
- aas_core_codegen/typescript/common.py +340 -0
- aas_core_codegen/typescript/constants/__init__.py +5 -0
- aas_core_codegen/typescript/constants/_generate.py +347 -0
- aas_core_codegen/typescript/description.py +530 -0
- aas_core_codegen/typescript/jsonization/__init__.py +4 -0
- aas_core_codegen/typescript/jsonization/_generate.py +1510 -0
- aas_core_codegen/typescript/main.py +258 -0
- aas_core_codegen/typescript/naming.py +189 -0
- aas_core_codegen/typescript/stringification/__init__.py +4 -0
- aas_core_codegen/typescript/stringification/_generate.py +367 -0
- aas_core_codegen/typescript/structure/__init__.py +6 -0
- aas_core_codegen/typescript/structure/_generate.py +2500 -0
- aas_core_codegen/typescript/transpilation.py +1051 -0
- aas_core_codegen/typescript/unrolling.py +159 -0
- aas_core_codegen/typescript/verification/__init__.py +6 -0
- aas_core_codegen/typescript/verification/_generate.py +1578 -0
- aas_core_codegen/xsd/__init__.py +1 -0
- aas_core_codegen/xsd/main.py +1187 -0
- aas_core_codegen/xsd/naming.py +83 -0
- aas_core_codegen/yielding/__init__.py +1 -0
- aas_core_codegen/yielding/flow.py +139 -0
- aas_core_codegen/yielding/linear.py +754 -0
- aas_core_codegen-0.0.16.dist-info/METADATA +211 -0
- aas_core_codegen-0.0.16.dist-info/RECORD +604 -0
- aas_core_codegen-0.0.16.dist-info/WHEEL +5 -0
- aas_core_codegen-0.0.16.dist-info/entry_points.txt +3 -0
- aas_core_codegen-0.0.16.dist-info/licenses/AUTHORS +9 -0
- aas_core_codegen-0.0.16.dist-info/licenses/LICENSE +23 -0
- aas_core_codegen-0.0.16.dist-info/top_level.txt +2 -0
- dev/continuous_integration/__init__.py +1 -0
- dev/continuous_integration/check_help_in_readme.py +208 -0
- dev/continuous_integration/check_init_and_pyproject_consistent.py +154 -0
- dev/continuous_integration/precommit.py +400 -0
- dev/dev_scripts/__init__.py +1 -0
- dev/dev_scripts/compare_rendered_regexes_against_source_py.py +42 -0
- dev/dev_scripts/copy_to_aas_core3_cpp.py +100 -0
- dev/dev_scripts/copy_to_aas_core3_java.py +90 -0
- dev/dev_scripts/download_latest_aas_core_meta_v3.py +114 -0
- dev/dev_scripts/draw_bipartite_graph_based_on_lines.py +37 -0
- dev/dev_scripts/run_tests_with_rerecord.py +69 -0
- dev/dev_scripts/update_to_aas_core_meta.py +174 -0
- dev/integration_tests/input/jsonschema/boilerplate/main.py +55 -0
- dev/integration_tests/input/meta_model.py +38 -0
- dev/integration_tests/input/python/boilerplate/main.py +153 -0
- dev/integration_tests/main.py +258 -0
- dev/test_data/csharp/test_structure/concrete_class_with_descendants/meta_model.py +15 -0
- dev/test_data/csharp/test_structure/constructor_without_arguments/all_properties_optional/meta_model.py +9 -0
- dev/test_data/csharp/test_structure/constructor_without_arguments/no_properties/meta_model.py +6 -0
- dev/test_data/csharp/test_verification/builtin_functions/len/on_list/meta_model.py +20 -0
- dev/test_data/csharp/test_verification/builtin_functions/len/on_str/meta_model.py +16 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/as_prefix/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/as_suffix/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_group_with_quantifier/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_the_middle/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_union/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/single_utf32_literal/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/with_quantifier_within_group/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/with_quantifier_without_group/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/at_the_beginning/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/at_the_end/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/in_the_middle/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/multiple/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/single/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/single_with_quantifier/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/mixed_with_non_utf32/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/more_than_two_high_surrogates/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/multiple_utf32_ranges/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/multiple_utf32_ranges_mixed_with_non_utf32/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/same_high_surrogate/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/same_high_surrogate_with_quantifier/meta_model.py +8 -0
- dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/two_high_surrogates/meta_model.py +8 -0
- dev/test_data/intermediate/expected/class/empty/meta_model.py +6 -0
- dev/test_data/intermediate/expected/class/implementation_specific_method/meta_model.py +8 -0
- dev/test_data/intermediate/expected/class/inheritance/meta_model.py +41 -0
- dev/test_data/intermediate/expected/class/methods_with_contracts/meta_model.py +15 -0
- dev/test_data/intermediate/expected/class/only_method_no_property/meta_model.py +7 -0
- dev/test_data/intermediate/expected/class/only_property_no_method/meta_model.py +9 -0
- dev/test_data/intermediate/expected/constant/constant_set/of_enum/meta_model.py +12 -0
- dev/test_data/intermediate/expected/constant/constant_set/of_str/meta_model.py +4 -0
- dev/test_data/intermediate/expected/constant/constant_set/with_description/meta_model.py +6 -0
- dev/test_data/intermediate/expected/constant/constant_set/with_superset_of/meta_model.py +14 -0
- dev/test_data/intermediate/expected/constant/constant_str/only_value/meta_model.py +7 -0
- dev/test_data/intermediate/expected/constant/constant_str/with_description/meta_model.py +5 -0
- dev/test_data/intermediate/expected/documentation/docstring_with_special_characters_in_literal/meta_model.py +20 -0
- dev/test_data/intermediate/expected/documentation/docstring_with_special_characters_outside_literal/meta_model.py +20 -0
- dev/test_data/intermediate/expected/empty/meta_model.py +2 -0
- dev/test_data/intermediate/expected/enumeration/meta_model.py +9 -0
- dev/test_data/intermediate/expected/interface/basic/meta_model.py +14 -0
- dev/test_data/intermediate/expected/interface/empty/meta_model.py +7 -0
- dev/test_data/intermediate/expected/interface/inheritance/meta_model.py +27 -0
- dev/test_data/intermediate/expected/interface/method_signature/meta_model.py +10 -0
- dev/test_data/intermediate/expected/interface/only_constructor/meta_model.py +11 -0
- dev/test_data/intermediate/expected/method/non_mutating/implementation_specific/meta_model.py +12 -0
- dev/test_data/intermediate/expected/method/non_mutating/understood/meta_model.py +11 -0
- dev/test_data/intermediate/expected/type_annotation/atomic/meta_model.py +9 -0
- dev/test_data/intermediate/expected/type_annotation/subscripted/class/meta_model.py +13 -0
- dev/test_data/intermediate/expected/type_annotation/subscripted/primitive/meta_model.py +9 -0
- dev/test_data/intermediate/unexpected/constant_set/of_enum/enumeration_literals_in_subset_outside_of_superset/meta_model.py +20 -0
- dev/test_data/intermediate/unexpected/constant_set/of_enum/invalid_literal/meta_model.py +11 -0
- dev/test_data/intermediate/unexpected/constant_set/of_enum/mismatch_between_enumeration_and_literal/meta_model.py +30 -0
- dev/test_data/intermediate/unexpected/constant_set/of_enum/mismatch_in_enumerations_between_subset_and_superset/meta_model.py +21 -0
- dev/test_data/intermediate/unexpected/constant_set/of_str/literals_in_subset_outside_of_superset/meta_model.py +18 -0
- dev/test_data/intermediate/unexpected/constant_set/of_str/mismatch_between_type_annotation_and_literals/meta_model.py +10 -0
- dev/test_data/intermediate/unexpected/constant_set/of_str/superset_and_subset_mismatch_in_type/meta_model.py +12 -0
- dev/test_data/intermediate/unexpected/constraints/dangling_constraintref/meta_model.py +18 -0
- dev/test_data/intermediate/unexpected/constraints/duplicate_constraints/meta_model.py +20 -0
- dev/test_data/intermediate/unexpected/documentation/unexpected_documentation_elements/meta_model.py +34 -0
- dev/test_data/intermediate/unexpected/invariant/class_invariant_uses_re/meta_model.py +10 -0
- dev/test_data/intermediate/unexpected/invariant/invariant_of_constrained_primitive_uses_re/meta_model.py +7 -0
- dev/test_data/intermediate/unexpected/invariant/unexpected_argument_count_to_len/meta_model.py +20 -0
- dev/test_data/intermediate/unexpected/invariant/unhandled_built_in_function/meta_model.py +16 -0
- dev/test_data/intermediate/unexpected/method_definitions/non_constant_default/meta_model.py +7 -0
- dev/test_data/intermediate/unexpected/optional_constructor_arguments_wo_default/default_non_none/meta_model.py +16 -0
- dev/test_data/intermediate/unexpected/optional_constructor_arguments_wo_default/no_default/meta_model.py +16 -0
- dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/after_inheritance/meta_model.py +58 -0
- dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/type_missmatch/meta_model.py +9 -0
- dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/within_class/meta_model.py +22 -0
- dev/test_data/jsonschema/test_main/regression_when_len_constraints_on_inherited_property/meta_model.py +28 -0
- dev/test_data/opcua/test_main/abstract_and_concrete_classes/meta_model.py +37 -0
- dev/test_data/opcua/test_main/classes_with_invariants/meta_model.py +21 -0
- dev/test_data/opcua/test_main/concrete_class_with_descendant/meta_model.py +27 -0
- dev/test_data/opcua/test_main/concrete_class_with_enum/meta_model.py +21 -0
- dev/test_data/opcua/test_main/concrete_class_with_list_of_instances/meta_model.py +21 -0
- dev/test_data/opcua/test_main/concrete_class_with_primitive_attributes/meta_model.py +41 -0
- dev/test_data/opcua/test_main/concrete_class_with_string/meta_model.py +13 -0
- dev/test_data/opcua/test_main/constrained_primitive/meta_model.py +20 -0
- dev/test_data/opcua/test_main/multiple_inheritance/meta_model.py +25 -0
- dev/test_data/parse/expected/constant/constant_set/of_enum/meta_model.py +12 -0
- dev/test_data/parse/expected/constant/constant_set/of_str/meta_model.py +4 -0
- dev/test_data/parse/expected/constant/constant_set/with_description/meta_model.py +6 -0
- dev/test_data/parse/expected/constant/constant_set/with_superset_of/meta_model.py +14 -0
- dev/test_data/parse/expected/constant/constant_str/only_value/meta_model.py +7 -0
- dev/test_data/parse/expected/constant/constant_str/with_description/meta_model.py +5 -0
- dev/test_data/parse/expected/enum/ok/meta_model.py +15 -0
- dev/test_data/parse/expected/implementation_specific_class/properties_and_methods_in_implementation_specific_class/meta_model.py +17 -0
- dev/test_data/parse/expected/inheritance/basic/meta_model.py +11 -0
- dev/test_data/parse/expected/inheritance/diamond/meta_model.py +26 -0
- dev/test_data/parse/expected/inheritance/inheritance_from_concrete_class/meta_model.py +10 -0
- dev/test_data/parse/expected/invariants/in_relation/meta_model.py +16 -0
- dev/test_data/parse/expected/method/arguments/meta_model.py +7 -0
- dev/test_data/parse/expected/method/basic/meta_model.py +7 -0
- dev/test_data/parse/expected/method/contracts/condition_as_keyword_argument/meta_model.py +8 -0
- dev/test_data/parse/expected/method/contracts/condition_as_positional_argument/meta_model.py +8 -0
- dev/test_data/parse/expected/method/contracts/description_as_keyword_argument/meta_model.py +8 -0
- dev/test_data/parse/expected/method/contracts/description_as_positional_argument/meta_model.py +8 -0
- dev/test_data/parse/expected/method/contracts/multiple_contracts_in_order/meta_model.py +17 -0
- dev/test_data/parse/expected/method/contracts/postcondition/basic/meta_model.py +10 -0
- dev/test_data/parse/expected/method/contracts/postcondition/snapshot/with_keyword_arguments/meta_model.py +9 -0
- dev/test_data/parse/expected/method/contracts/postcondition/snapshot/with_positional_arguments/meta_model.py +9 -0
- dev/test_data/parse/expected/method/default/meta_model.py +9 -0
- dev/test_data/parse/expected/method/description/meta_model.py +8 -0
- dev/test_data/parse/expected/method/is_implementation_specific/meta_model.py +8 -0
- dev/test_data/parse/expected/method/non_mutating/meta_model.py +11 -0
- dev/test_data/parse/expected/method/returns_none/meta_model.py +7 -0
- dev/test_data/parse/expected/method/returns_something/meta_model.py +7 -0
- dev/test_data/parse/expected/single_class/description/meta_model.py +12 -0
- dev/test_data/parse/expected/single_class/empty/meta_model.py +6 -0
- dev/test_data/parse/expected/single_class/property/description/meta_model.py +14 -0
- dev/test_data/parse/expected/single_class/property/mandatory/meta_model.py +6 -0
- dev/test_data/parse/expected/single_class/property/optional/meta_model.py +6 -0
- dev/test_data/parse/expected/single_class/property/recursion_to_entity/meta_model.py +6 -0
- dev/test_data/parse/unexpected/class_decorators/non_name_decorator/meta_model.py +7 -0
- dev/test_data/parse/unexpected/class_decorators/unknown_decorator/meta_model.py +7 -0
- dev/test_data/parse/unexpected/class_definitions/is_abstract_and_implementation_specific/meta_model.py +8 -0
- dev/test_data/parse/unexpected/class_definitions/unexpected_docstring_before_a_method/meta_model.py +11 -0
- dev/test_data/parse/unexpected/class_definitions/unexpected_docstring_for_a_pass/meta_model.py +9 -0
- dev/test_data/parse/unexpected/class_definitions/unexpected_double_description_for_a_property/meta_model.py +10 -0
- dev/test_data/parse/unexpected/class_inheritances/inheriting_from_implementation_specific_parent/meta_model.py +20 -0
- dev/test_data/parse/unexpected/class_inheritances/non_name_super_class/meta_model.py +6 -0
- dev/test_data/parse/unexpected/enum/expression_as_assignment_value/meta_model.py +6 -0
- dev/test_data/parse/unexpected/enum/non_assignment/meta_model.py +8 -0
- dev/test_data/parse/unexpected/enum/non_string_literal/meta_model.py +6 -0
- dev/test_data/parse/unexpected/enum/unexpected_inheritance/meta_model.py +6 -0
- dev/test_data/parse/unexpected/method_contracts/contract/non_lambda_condition/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/contract/non_string_literal_description/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/contract/without_any_arguments/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/contract/without_condition/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/postcondition/OLD_in_postcondition_without_snapshot/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/postcondition/argument_missing_in_function/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/precondition/argument_missing_in_function/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/argument_missing_in_function/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/capture_not_a_lambda/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/invalid_name/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/name_not_a_string_literal/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/without_a_capture/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_contracts/snapshot/without_a_name/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_decorators/non_mutating/non_mutating_constructor/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_decorators/non_mutating/non_mutating_verification_function/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_decorators/non_name_decorator/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_decorators/unknown_call_decorator/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_decorators/unknown_name_decorator/meta_model.py +8 -0
- dev/test_data/parse/unexpected/method_definitions/argument_with_final/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/argument_without_a_type_annotation/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/default_for_self/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/dunder/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/init_with_return_type/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/with_keyword_only_arguments/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/with_positional_arguments/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/with_type_annotation_for_self/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/with_variable_arguments/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/with_variable_keyword_arguments/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/without_arguments/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/without_self/meta_model.py +7 -0
- dev/test_data/parse/unexpected/method_definitions/without_type_annotation_for_result/meta_model.py +7 -0
- dev/test_data/parse/unexpected/property_definitions/final_without_subscript/meta_model.py +6 -0
- dev/test_data/parse/unexpected/property_definitions/nested_final/meta_model.py +6 -0
- dev/test_data/parse/unexpected/property_definitions/non_simple/meta_model.py +6 -0
- dev/test_data/parse/unexpected/property_definitions/unexpected_assignment/meta_model.py +6 -0
- dev/test_data/parse/unexpected/property_definitions/unexpected_non_name_property/meta_model.py +6 -0
- dev/test_data/parse/unexpected/property_definitions/without_type_annotation/meta_model.py +6 -0
- dev/test_data/parse/unexpected/symbol_table/constant_set_with_a_non_set_subset/meta_model.py +6 -0
- dev/test_data/parse/unexpected/symbol_table/dangling_inheritance/meta_model.py +6 -0
- dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_a_property/meta_model.py +6 -0
- dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_an_argument/meta_model.py +7 -0
- dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_constant_set/meta_model.py +6 -0
- dev/test_data/parse/unexpected/symbol_table/dangling_subset_in_constant_set/meta_model.py +4 -0
- dev/test_data/parse/unexpected/symbol_table/inheritance_from_non_class/meta_model.py +10 -0
- dev/test_data/parse_retree/expected/character_set/common_escaping/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/complementing/double_caret/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/complementing/multiple_ranges/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/complementing/suffix_dash/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/escape_first_caret/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/literals_which_need_no_escaping_in_characters_set_but_need_escaping_outside/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/multiple_ranges/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/single_literal/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/single_range/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/unescaped_dash/only_dash/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/unescaped_dash/prefix_dash/source.py +1 -0
- dev/test_data/parse_retree/expected/character_set/unescaped_dash/suffix_dash/source.py +1 -0
- dev/test_data/parse_retree/expected/dot/source.py +1 -0
- dev/test_data/parse_retree/expected/empty/group/source.py +1 -0
- dev/test_data/parse_retree/expected/empty/group_in_a_group/source.py +1 -0
- dev/test_data/parse_retree/expected/empty/group_of_union_of_empty_concatenations/source.py +1 -0
- dev/test_data/parse_retree/expected/empty/regex/source.py +1 -0
- dev/test_data/parse_retree/expected/empty/union_of_empty_concatenations/source.py +1 -0
- dev/test_data/parse_retree/expected/escaped_literals/source.py +1 -0
- dev/test_data/parse_retree/expected/formatted_value/at_the_beginning/source.py +1 -0
- dev/test_data/parse_retree/expected/formatted_value/at_the_end/source.py +1 -0
- dev/test_data/parse_retree/expected/formatted_value/in_the_middle/source.py +1 -0
- dev/test_data/parse_retree/expected/formatted_value/single_formatted_value/source.py +1 -0
- dev/test_data/parse_retree/expected/literal/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/at_least_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/at_least_one/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/at_most_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/exactly_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/maybe/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/greedy/zero_or_more/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/at_least_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/at_least_one/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/at_most_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/exactly_3/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/maybe/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/non_greedy/zero_or_more/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/on_a_character_set/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/on_a_formatted_value/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/on_a_group/source.py +1 -0
- dev/test_data/parse_retree/expected/quantifier/on_a_literal/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/double_end_symbol/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/double_start_symbol/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/end_symbol_in_the_middle/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/only_start_symbol/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/only_stop_symbol/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/start_symbol_at_the_beginning/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/start_symbol_in_the_middle/source.py +1 -0
- dev/test_data/parse_retree/expected/start_and_stop_symbols/stop_symbol_at_the_end/source.py +1 -0
- dev/test_data/parse_retree/expected/union/of_character_sets/source.py +1 -0
- dev/test_data/parse_retree/expected/union/of_groups/source.py +1 -0
- dev/test_data/parse_retree/expected/union/of_string_literals/source.py +1 -0
- dev/test_data/parse_retree/expected/union/within_group/source.py +1 -0
- dev/test_data/parse_retree/expected/whitespace/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/Uxxxxxxxx_out_of_range/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/only_backslash/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_Uxxxxxxxx/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_uxxxx/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_x/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unexpected_escaping/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/digit/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_digit/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_whitespace/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_word/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/whitespace/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/word/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/Uxxxxxxxx_out_of_range/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/only_backslash/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_Uxxxxxxxx/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_uxxxx/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_x/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unexpected_escaping/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/digit/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_digit/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_whitespace/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_word/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/whitespace/source.py +1 -0
- dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/word/source.py +1 -0
- dev/test_data/parse_retree/unexpected/invalid_character_range/source.py +1 -0
- dev/test_data/parse_retree/unexpected/invalid_quantifier/at_least_x/source.py +1 -0
- dev/test_data/parse_retree/unexpected/invalid_quantifier/between_3_and_x/source.py +1 -0
- dev/test_data/parse_retree/unexpected/invalid_quantifier/exactly_x/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unhandled_group_directives/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/character_set/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/group/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/group_of_union_of_empty_concatenations/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/quantifier/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/quantifier_with_comma/source.py +1 -0
- dev/test_data/parse_retree/unexpected/unterminated/quantifier_with_number_and_comma/source.py +1 -0
- dev/test_data/proto/test_main/expected/abstract_and_concrete_classes/meta_model.py +37 -0
- dev/test_data/proto/test_main/expected/concrete_class_with_descendants/meta_model.py +30 -0
- dev/test_data/proto/test_main/expected/concrete_class_with_enum/meta_model.py +21 -0
- dev/test_data/proto/test_main/expected/concrete_class_with_list_of_instances/meta_model.py +21 -0
- dev/test_data/proto/test_main/expected/concrete_class_with_primitive_attributes/meta_model.py +41 -0
- dev/test_data/python_protobuf/test_main/abstract_and_concrete_classes/expected_output/pbization.py +532 -0
- dev/test_data/python_protobuf/test_main/abstract_and_concrete_classes/meta_model.py +37 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_descendant/expected_output/pbization.py +527 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_descendant/meta_model.py +27 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_enum/expected_output/pbization.py +290 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_enum/meta_model.py +21 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_list_of_instances/expected_output/pbization.py +328 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_list_of_instances/meta_model.py +23 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_primitive_attributes/expected_output/pbization.py +274 -0
- dev/test_data/python_protobuf/test_main/concrete_class_with_primitive_attributes/meta_model.py +41 -0
- dev/test_data/rdf_shacl/test_main/expected/regression_when_lang_string_class_is_missing/meta_model.py +29 -0
- dev/test_data/rdf_shacl/test_main/expected/regression_when_len_constraints_on_inherited_property/meta_model.py +27 -0
- dev/test_data/rdf_shacl/test_main/unexpected/regression_len_constraint_on_class_property/meta_model.py +61 -0
- dev/test_data/real_meta_models/aas_core_meta.v3.py +5721 -0
- dev/test_data/smoke/test_main/unexpected/infer_for_schema_error/meta_model.py +12 -0
- dev/test_data/smoke/test_main/unexpected/intermediate_error/meta_model.py +18 -0
- dev/test_data/smoke/test_main/unexpected/parse_error/meta_model.py +5 -0
- dev/test_data/smoke/test_main/unexpected/pattern_verification_unparsable_regex/direct_match/meta_model.py +8 -0
- dev/test_data/smoke/test_main/unexpected/type_error/meta_model.py +18 -0
- dev/tests/__init__.py +1 -0
- dev/tests/common.py +197 -0
- dev/tests/cpp/__init__.py +0 -0
- dev/tests/cpp/test_common.py +32 -0
- dev/tests/cpp/test_main.py +144 -0
- dev/tests/cpp/test_pattern.py +188 -0
- dev/tests/cpp/test_verification.py +189 -0
- dev/tests/cpp/test_yielding.py +225 -0
- dev/tests/csharp/__init__.py +0 -0
- dev/tests/csharp/live_test_main.py +109 -0
- dev/tests/csharp/test_common.py +28 -0
- dev/tests/csharp/test_description.py +684 -0
- dev/tests/csharp/test_main.py +129 -0
- dev/tests/csharp/test_structure.py +93 -0
- dev/tests/csharp/test_verification.py +82 -0
- dev/tests/description.py +29 -0
- dev/tests/golang/__init__.py +0 -0
- dev/tests/golang/test_common.py +78 -0
- dev/tests/golang/test_main.py +128 -0
- dev/tests/infer_for_schema/__init__.py +0 -0
- dev/tests/infer_for_schema/common.py +47 -0
- dev/tests/infer_for_schema/test_len_on_properties.py +955 -0
- dev/tests/infer_for_schema/test_len_on_self.py +580 -0
- dev/tests/infer_for_schema/test_patterns_on_properties.py +686 -0
- dev/tests/infer_for_schema/test_patterns_on_self.py +258 -0
- dev/tests/infer_for_schema/test_property_in_set_of_enumeration_literals.py +600 -0
- dev/tests/infer_for_schema/test_property_in_set_of_primitives.py +549 -0
- dev/tests/intermediate/__init__.py +0 -0
- dev/tests/intermediate/test_constructor.py +719 -0
- dev/tests/intermediate/test_hierarchy.py +221 -0
- dev/tests/intermediate/test_revm.py +134 -0
- dev/tests/intermediate/test_translate.py +337 -0
- dev/tests/intermediate/test_type_inference.py +333 -0
- dev/tests/intermediate/test_types.py +169 -0
- dev/tests/java/__init__.py +0 -0
- dev/tests/java/test_common.py +20 -0
- dev/tests/java/test_description.py +128 -0
- dev/tests/java/test_main.py +234 -0
- dev/tests/jsonld_context/test_main.py +79 -0
- dev/tests/opcua/__init__.py +3 -0
- dev/tests/opcua/test_main.py +110 -0
- dev/tests/our_jsonschema/__init__.py +3 -0
- dev/tests/our_jsonschema/test_main.py +232 -0
- dev/tests/parse/__init__.py +0 -0
- dev/tests/parse/test_parse.py +503 -0
- dev/tests/parse/test_retree.py +272 -0
- dev/tests/proto/__init__.py +0 -0
- dev/tests/proto/test_main.py +112 -0
- dev/tests/python/__init__.py +0 -0
- dev/tests/python/test_common.py +124 -0
- dev/tests/python/test_main.py +126 -0
- dev/tests/python/test_xml_playground.py +254 -0
- dev/tests/python_protobuf/__init__.py +0 -0
- dev/tests/python_protobuf/test_main.py +111 -0
- dev/tests/rdf_shacl/__init__.py +0 -0
- dev/tests/rdf_shacl/test_common.py +32 -0
- dev/tests/rdf_shacl/test_description.py +223 -0
- dev/tests/rdf_shacl/test_main.py +194 -0
- dev/tests/smoke/__init__.py +0 -0
- dev/tests/smoke/test_main.py +83 -0
- dev/tests/test_common.py +94 -0
- dev/tests/typescript/__init__.py +0 -0
- dev/tests/typescript/test_common.py +108 -0
- dev/tests/typescript/test_main.py +125 -0
- dev/tests/xsd/__init__.py +0 -0
- dev/tests/xsd/test_main.py +227 -0
- dev/tests/yielding/__init__.py +0 -0
- dev/tests/yielding/test_linear.py +558 -0
|
@@ -0,0 +1,1801 @@
|
|
|
1
|
+
"""Generate the Python data structures from the intermediate representation."""
|
|
2
|
+
import io
|
|
3
|
+
import itertools
|
|
4
|
+
import textwrap
|
|
5
|
+
from typing import (
|
|
6
|
+
Optional,
|
|
7
|
+
Dict,
|
|
8
|
+
List,
|
|
9
|
+
Tuple,
|
|
10
|
+
cast,
|
|
11
|
+
Union,
|
|
12
|
+
Mapping,
|
|
13
|
+
Final,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
from icontract import ensure, require
|
|
17
|
+
|
|
18
|
+
from aas_core_codegen import intermediate
|
|
19
|
+
from aas_core_codegen import specific_implementations
|
|
20
|
+
from aas_core_codegen.common import (
|
|
21
|
+
Error,
|
|
22
|
+
Identifier,
|
|
23
|
+
assert_never,
|
|
24
|
+
Stripped,
|
|
25
|
+
indent_but_first_line,
|
|
26
|
+
)
|
|
27
|
+
from aas_core_codegen.intermediate import (
|
|
28
|
+
construction as intermediate_construction,
|
|
29
|
+
)
|
|
30
|
+
from aas_core_codegen.python import (
|
|
31
|
+
common as python_common,
|
|
32
|
+
naming as python_naming,
|
|
33
|
+
description as python_description,
|
|
34
|
+
unrolling as python_unrolling,
|
|
35
|
+
)
|
|
36
|
+
from aas_core_codegen.python.common import (
|
|
37
|
+
INDENT as I,
|
|
38
|
+
INDENT2 as II,
|
|
39
|
+
INDENT3 as III,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# region Checks
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _human_readable_identifier(
|
|
47
|
+
something: Union[
|
|
48
|
+
intermediate.Enumeration, intermediate.AbstractClass, intermediate.ConcreteClass
|
|
49
|
+
]
|
|
50
|
+
) -> str:
|
|
51
|
+
"""
|
|
52
|
+
Represent ``something`` in a human-readable text.
|
|
53
|
+
|
|
54
|
+
The reader should be able to trace ``something`` back to the meta-model.
|
|
55
|
+
"""
|
|
56
|
+
result: str
|
|
57
|
+
|
|
58
|
+
if isinstance(something, intermediate.Enumeration):
|
|
59
|
+
result = f"meta-model enumeration {something.name!r}"
|
|
60
|
+
elif isinstance(something, intermediate.AbstractClass):
|
|
61
|
+
result = f"meta-model abstract class {something.name!r}"
|
|
62
|
+
elif isinstance(something, intermediate.ConcreteClass):
|
|
63
|
+
result = f"meta-model concrete class {something.name!r}"
|
|
64
|
+
else:
|
|
65
|
+
assert_never(something)
|
|
66
|
+
|
|
67
|
+
return result
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _verify_intra_structure_collisions(
|
|
71
|
+
our_type: intermediate.OurType,
|
|
72
|
+
) -> Optional[Error]:
|
|
73
|
+
"""Verify that no member names collide in the Python structure of our type."""
|
|
74
|
+
errors = [] # type: List[Error]
|
|
75
|
+
|
|
76
|
+
if isinstance(our_type, intermediate.Enumeration):
|
|
77
|
+
enum_literal_map = (
|
|
78
|
+
dict()
|
|
79
|
+
) # type: Dict[Identifier, intermediate.EnumerationLiteral]
|
|
80
|
+
|
|
81
|
+
for literal in our_type.literals:
|
|
82
|
+
literal_name = python_naming.enum_literal_name(literal.name)
|
|
83
|
+
colliding_literal = enum_literal_map.get(literal_name, None)
|
|
84
|
+
if colliding_literal is not None:
|
|
85
|
+
errors.append(
|
|
86
|
+
Error(
|
|
87
|
+
literal.parsed.node,
|
|
88
|
+
f"The Python name, {literal_name!r}, "
|
|
89
|
+
f"for the literal {literal.name!r} collides with "
|
|
90
|
+
f"the Python name of another "
|
|
91
|
+
f"literal {colliding_literal.name!r}",
|
|
92
|
+
)
|
|
93
|
+
)
|
|
94
|
+
else:
|
|
95
|
+
enum_literal_map[literal_name] = literal
|
|
96
|
+
|
|
97
|
+
elif isinstance(our_type, intermediate.ConstrainedPrimitive):
|
|
98
|
+
pass
|
|
99
|
+
|
|
100
|
+
elif isinstance(our_type, intermediate.Class):
|
|
101
|
+
observed_member_names = {} # type: Dict[Identifier, str]
|
|
102
|
+
|
|
103
|
+
for prop in our_type.properties:
|
|
104
|
+
prop_name = python_naming.property_name(prop.name)
|
|
105
|
+
if prop_name in observed_member_names:
|
|
106
|
+
errors.append(
|
|
107
|
+
Error(
|
|
108
|
+
prop.parsed.node,
|
|
109
|
+
f"Python property {prop_name!r} corresponding "
|
|
110
|
+
f"to the meta-model property {prop.name!r} collides with "
|
|
111
|
+
f"the {observed_member_names[prop_name]}",
|
|
112
|
+
)
|
|
113
|
+
)
|
|
114
|
+
else:
|
|
115
|
+
observed_member_names[prop_name] = (
|
|
116
|
+
f"Python property {prop_name!r} corresponding to "
|
|
117
|
+
f"the meta-model property {prop.name!r}"
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
for method in our_type.methods:
|
|
121
|
+
method_name = python_naming.method_name(method.name)
|
|
122
|
+
|
|
123
|
+
if method_name in observed_member_names:
|
|
124
|
+
errors.append(
|
|
125
|
+
Error(
|
|
126
|
+
method.parsed.node,
|
|
127
|
+
f"Python method {method_name!r} corresponding "
|
|
128
|
+
f"to the meta-model method {method.name!r} collides with "
|
|
129
|
+
f"the {observed_member_names[method_name]}",
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
else:
|
|
133
|
+
observed_member_names[method_name] = (
|
|
134
|
+
f"Python method {method_name!r} corresponding to "
|
|
135
|
+
f"the meta-model method {method.name!r}"
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
else:
|
|
139
|
+
assert_never(our_type)
|
|
140
|
+
|
|
141
|
+
if len(errors) > 0:
|
|
142
|
+
errors.append(
|
|
143
|
+
Error(
|
|
144
|
+
our_type.parsed.node,
|
|
145
|
+
f"Naming collision(s) in Python code for our type {our_type.name!r}",
|
|
146
|
+
underlying=errors,
|
|
147
|
+
)
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
return None
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def _verify_structure_name_collisions(
|
|
154
|
+
symbol_table: intermediate.SymbolTable,
|
|
155
|
+
) -> List[Error]:
|
|
156
|
+
"""Verify that the Python names of the structures do not collide."""
|
|
157
|
+
observed_structure_names: Dict[
|
|
158
|
+
Identifier,
|
|
159
|
+
Union[
|
|
160
|
+
intermediate.Enumeration,
|
|
161
|
+
intermediate.AbstractClass,
|
|
162
|
+
intermediate.ConcreteClass,
|
|
163
|
+
],
|
|
164
|
+
] = dict()
|
|
165
|
+
|
|
166
|
+
errors = [] # type: List[Error]
|
|
167
|
+
|
|
168
|
+
# region Inter-structure collisions
|
|
169
|
+
|
|
170
|
+
for enum_or_cls in itertools.chain(symbol_table.enumerations, symbol_table.classes):
|
|
171
|
+
name = python_naming.name_of(enum_or_cls)
|
|
172
|
+
|
|
173
|
+
other = observed_structure_names.get(name, None)
|
|
174
|
+
|
|
175
|
+
if other is not None:
|
|
176
|
+
errors.append(
|
|
177
|
+
Error(
|
|
178
|
+
enum_or_cls.parsed.node,
|
|
179
|
+
f"The Python name {name!r} "
|
|
180
|
+
f"of the {_human_readable_identifier(enum_or_cls)} "
|
|
181
|
+
f"collides with the Python name "
|
|
182
|
+
f"of the {_human_readable_identifier(other)}",
|
|
183
|
+
)
|
|
184
|
+
)
|
|
185
|
+
else:
|
|
186
|
+
observed_structure_names[name] = enum_or_cls
|
|
187
|
+
|
|
188
|
+
# endregion
|
|
189
|
+
|
|
190
|
+
# region Intra-structure collisions
|
|
191
|
+
|
|
192
|
+
for our_type in symbol_table.our_types:
|
|
193
|
+
collision_error = _verify_intra_structure_collisions(our_type=our_type)
|
|
194
|
+
|
|
195
|
+
if collision_error is not None:
|
|
196
|
+
errors.append(collision_error)
|
|
197
|
+
|
|
198
|
+
# endregion
|
|
199
|
+
|
|
200
|
+
return errors
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
class VerifiedIntermediateSymbolTable(intermediate.SymbolTable):
|
|
204
|
+
"""Represent a verified symbol table which can be used for code generation."""
|
|
205
|
+
|
|
206
|
+
# noinspection PyInitNewSignature
|
|
207
|
+
def __new__(
|
|
208
|
+
cls, symbol_table: intermediate.SymbolTable
|
|
209
|
+
) -> "VerifiedIntermediateSymbolTable":
|
|
210
|
+
raise AssertionError("Only for type annotation")
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
@ensure(lambda result: (result[0] is None) ^ (result[1] is None))
|
|
214
|
+
def verify(
|
|
215
|
+
symbol_table: intermediate.SymbolTable,
|
|
216
|
+
) -> Tuple[Optional[VerifiedIntermediateSymbolTable], Optional[List[Error]]]:
|
|
217
|
+
"""Verify that Python code can be generated from the ``symbol_table``."""
|
|
218
|
+
errors = [] # type: List[Error]
|
|
219
|
+
|
|
220
|
+
structure_name_collisions = _verify_structure_name_collisions(
|
|
221
|
+
symbol_table=symbol_table
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
errors.extend(structure_name_collisions)
|
|
225
|
+
|
|
226
|
+
if len(errors) > 0:
|
|
227
|
+
return None, errors
|
|
228
|
+
|
|
229
|
+
return cast(VerifiedIntermediateSymbolTable, symbol_table), None
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
# endregion
|
|
233
|
+
|
|
234
|
+
# region Generation
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
@require(lambda enumeration, literal: id(literal) in enumeration.literal_id_set)
|
|
238
|
+
@require(lambda literal: literal.description is not None)
|
|
239
|
+
def _generate_comment_for_enumeration_literal(
|
|
240
|
+
enumeration: intermediate.Enumeration,
|
|
241
|
+
literal: intermediate.EnumerationLiteral,
|
|
242
|
+
aas_module: python_common.QualifiedModuleName,
|
|
243
|
+
) -> Tuple[Optional[Stripped], Optional[List[Error]]]:
|
|
244
|
+
"""Generate the documentation comment for the given enumeration literal."""
|
|
245
|
+
# NOTE (mristin, 2022-10-29):
|
|
246
|
+
# We need to state the pre-condition for the second time for mypy.
|
|
247
|
+
assert literal.description is not None
|
|
248
|
+
|
|
249
|
+
text, errors = python_description.generate_summary_remarks(
|
|
250
|
+
description=literal.description,
|
|
251
|
+
context=python_description.Context(
|
|
252
|
+
aas_module=aas_module, module=Identifier("types"), cls_or_enum=enumeration
|
|
253
|
+
),
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
if errors is not None:
|
|
257
|
+
return None, errors
|
|
258
|
+
|
|
259
|
+
assert text is not None
|
|
260
|
+
|
|
261
|
+
return python_description.documentation_comment(text), None
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
@require(lambda cls_or_enum: cls_or_enum.description is not None)
|
|
265
|
+
def _generate_docstring_for_cls_or_enum(
|
|
266
|
+
cls_or_enum: Union[intermediate.Enumeration, intermediate.ClassUnion],
|
|
267
|
+
aas_module: python_common.QualifiedModuleName,
|
|
268
|
+
) -> Tuple[Optional[Stripped], Optional[List[Error]]]:
|
|
269
|
+
"""Generate the docstring for our type."""
|
|
270
|
+
# NOTE (mristin, 2022-10-29):
|
|
271
|
+
# We need to state the pre-condition for the second time for mypy.
|
|
272
|
+
assert cls_or_enum.description is not None
|
|
273
|
+
|
|
274
|
+
text, errors = python_description.generate_summary_remarks_constraints(
|
|
275
|
+
description=cls_or_enum.description,
|
|
276
|
+
context=python_description.Context(
|
|
277
|
+
aas_module=aas_module, module=Identifier("types"), cls_or_enum=cls_or_enum
|
|
278
|
+
),
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
if errors is not None:
|
|
282
|
+
return None, errors
|
|
283
|
+
|
|
284
|
+
assert text is not None
|
|
285
|
+
|
|
286
|
+
return python_description.docstring(text), None
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
@ensure(lambda result: (result[0] is None) ^ (result[1] is None))
|
|
290
|
+
def _generate_enum(
|
|
291
|
+
enum: intermediate.Enumeration, aas_module: python_common.QualifiedModuleName
|
|
292
|
+
) -> Tuple[Optional[Stripped], Optional[Error]]:
|
|
293
|
+
"""Generate the Python code for the enum."""
|
|
294
|
+
writer = io.StringIO()
|
|
295
|
+
|
|
296
|
+
errors = [] # type: List[Error]
|
|
297
|
+
|
|
298
|
+
docstring = None # type: Optional[Stripped]
|
|
299
|
+
if enum.description is not None:
|
|
300
|
+
# fmt: off
|
|
301
|
+
docstring, docstring_errors = (
|
|
302
|
+
_generate_docstring_for_cls_or_enum(
|
|
303
|
+
cls_or_enum=enum,
|
|
304
|
+
aas_module=aas_module
|
|
305
|
+
)
|
|
306
|
+
)
|
|
307
|
+
# fmt: on
|
|
308
|
+
|
|
309
|
+
if docstring_errors:
|
|
310
|
+
errors.append(
|
|
311
|
+
Error(
|
|
312
|
+
enum.description.parsed.node,
|
|
313
|
+
f"Failed to generate the docstring "
|
|
314
|
+
f"for the enumeration {enum.name!r}",
|
|
315
|
+
docstring_errors,
|
|
316
|
+
)
|
|
317
|
+
)
|
|
318
|
+
else:
|
|
319
|
+
assert docstring is not None
|
|
320
|
+
|
|
321
|
+
name = python_naming.enum_name(enum.name)
|
|
322
|
+
|
|
323
|
+
writer.write(f"class {name}(enum.Enum):\n")
|
|
324
|
+
if len(enum.literals) == 0:
|
|
325
|
+
if docstring is not None:
|
|
326
|
+
writer.write(textwrap.indent(docstring, I))
|
|
327
|
+
else:
|
|
328
|
+
writer.write(
|
|
329
|
+
f"""\
|
|
330
|
+
{I}# pylint: disable=missing-class-docstring
|
|
331
|
+
{I}pass
|
|
332
|
+
"""
|
|
333
|
+
)
|
|
334
|
+
else:
|
|
335
|
+
if docstring is not None:
|
|
336
|
+
writer.write(textwrap.indent(docstring, I))
|
|
337
|
+
else:
|
|
338
|
+
writer.write(f"{I}# pylint: disable=missing-class-docstring")
|
|
339
|
+
|
|
340
|
+
for literal in enum.literals:
|
|
341
|
+
writer.write("\n\n")
|
|
342
|
+
|
|
343
|
+
if literal.description is not None:
|
|
344
|
+
comment, comment_errors = _generate_comment_for_enumeration_literal(
|
|
345
|
+
enumeration=enum, literal=literal, aas_module=aas_module
|
|
346
|
+
)
|
|
347
|
+
if comment_errors is not None:
|
|
348
|
+
errors.append(
|
|
349
|
+
Error(
|
|
350
|
+
literal.description.parsed.node,
|
|
351
|
+
f"Failed to generate the documentation comment "
|
|
352
|
+
f"for enumeration literal {literal.name!r}",
|
|
353
|
+
comment_errors,
|
|
354
|
+
)
|
|
355
|
+
)
|
|
356
|
+
else:
|
|
357
|
+
assert comment is not None
|
|
358
|
+
|
|
359
|
+
writer.write(textwrap.indent(comment, I))
|
|
360
|
+
writer.write("\n")
|
|
361
|
+
|
|
362
|
+
literal_name = python_naming.enum_literal_name(literal.name)
|
|
363
|
+
writer.write(textwrap.indent(f"{literal_name} = {repr(literal.value)}", I))
|
|
364
|
+
|
|
365
|
+
if len(errors) > 0:
|
|
366
|
+
return None, Error(
|
|
367
|
+
enum.parsed.node,
|
|
368
|
+
f"Failed to generate the Python code for the enumeration {enum.name!r}",
|
|
369
|
+
errors,
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
return Stripped(writer.getvalue()), None
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
class _DescendBodyUnroller(python_unrolling.AbstractUnroller):
|
|
376
|
+
"""Generate the code that unrolls descent into an element."""
|
|
377
|
+
|
|
378
|
+
#: If set, generates the code with unrolled yields.
|
|
379
|
+
#: Otherwise, we do not unroll recursively.
|
|
380
|
+
_recurse: Final[bool]
|
|
381
|
+
|
|
382
|
+
#: Pre-computed descendability map. A type is descendable if we should unroll it
|
|
383
|
+
#: further.
|
|
384
|
+
_descendability: Final[Mapping[intermediate.TypeAnnotationUnion, bool]]
|
|
385
|
+
|
|
386
|
+
#: Generator of loop variable names.
|
|
387
|
+
#:
|
|
388
|
+
#: We generate for each list iteration a new variable since Python tracks
|
|
389
|
+
#: variables in the function scope, not block scope.
|
|
390
|
+
_generator_for_loop_variables: Final[python_common.GeneratorForLoopVariables]
|
|
391
|
+
|
|
392
|
+
def __init__(
|
|
393
|
+
self,
|
|
394
|
+
recurse: bool,
|
|
395
|
+
descendability: Mapping[intermediate.TypeAnnotationUnion, bool],
|
|
396
|
+
generator_for_loop_variables: python_common.GeneratorForLoopVariables,
|
|
397
|
+
) -> None:
|
|
398
|
+
"""Initialize with the given values."""
|
|
399
|
+
self._recurse = recurse
|
|
400
|
+
self._descendability = descendability
|
|
401
|
+
self._generator_for_loop_variables = generator_for_loop_variables
|
|
402
|
+
|
|
403
|
+
def _unroll_primitive_type_annotation(
|
|
404
|
+
self,
|
|
405
|
+
unrollee_expr: str,
|
|
406
|
+
type_annotation: intermediate.PrimitiveTypeAnnotation,
|
|
407
|
+
path: List[str],
|
|
408
|
+
list_loop_level: int,
|
|
409
|
+
) -> List[python_unrolling.Node]:
|
|
410
|
+
"""Generate code for the given specific ``type_annotation``."""
|
|
411
|
+
# We can not descend into a primitive type.
|
|
412
|
+
return []
|
|
413
|
+
|
|
414
|
+
def _unroll_our_type_annotation(
|
|
415
|
+
self,
|
|
416
|
+
unrollee_expr: str,
|
|
417
|
+
type_annotation: intermediate.OurTypeAnnotation,
|
|
418
|
+
path: List[str],
|
|
419
|
+
list_loop_level: int,
|
|
420
|
+
) -> List[python_unrolling.Node]:
|
|
421
|
+
"""Generate code for the given specific ``type_annotation``."""
|
|
422
|
+
our_type = type_annotation.our_type
|
|
423
|
+
|
|
424
|
+
if isinstance(our_type, intermediate.Enumeration):
|
|
425
|
+
# We can not descend into an enumeration.
|
|
426
|
+
return []
|
|
427
|
+
|
|
428
|
+
elif isinstance(our_type, intermediate.ConstrainedPrimitive):
|
|
429
|
+
# We can not descend into a primitive type.
|
|
430
|
+
return []
|
|
431
|
+
|
|
432
|
+
assert isinstance(our_type, intermediate.Class) # Exhaustively match
|
|
433
|
+
|
|
434
|
+
result = [python_unrolling.Node(f"yield {unrollee_expr}", children=[])]
|
|
435
|
+
|
|
436
|
+
if self._recurse:
|
|
437
|
+
if self._descendability[type_annotation]:
|
|
438
|
+
result.append(
|
|
439
|
+
python_unrolling.Node(
|
|
440
|
+
text=f"yield from {unrollee_expr}.descend()",
|
|
441
|
+
children=[],
|
|
442
|
+
)
|
|
443
|
+
)
|
|
444
|
+
|
|
445
|
+
return result
|
|
446
|
+
|
|
447
|
+
def _unroll_list_type_annotation(
|
|
448
|
+
self,
|
|
449
|
+
unrollee_expr: str,
|
|
450
|
+
type_annotation: intermediate.ListTypeAnnotation,
|
|
451
|
+
path: List[str],
|
|
452
|
+
list_loop_level: int,
|
|
453
|
+
) -> List[python_unrolling.Node]:
|
|
454
|
+
"""Generate code for the given specific ``type_annotation``."""
|
|
455
|
+
if (
|
|
456
|
+
not self._recurse
|
|
457
|
+
and isinstance(type_annotation.items, intermediate.OurTypeAnnotation)
|
|
458
|
+
and isinstance(
|
|
459
|
+
type_annotation.items.our_type,
|
|
460
|
+
(intermediate.AbstractClass, intermediate.ConcreteClass),
|
|
461
|
+
)
|
|
462
|
+
):
|
|
463
|
+
return [python_unrolling.Node(f"yield from {unrollee_expr}", children=[])]
|
|
464
|
+
|
|
465
|
+
loop_var = next(self._generator_for_loop_variables)
|
|
466
|
+
children = self.unroll(
|
|
467
|
+
unrollee_expr=loop_var,
|
|
468
|
+
type_annotation=type_annotation.items,
|
|
469
|
+
path=[], # Path is unused in this context
|
|
470
|
+
list_loop_level=list_loop_level + 1,
|
|
471
|
+
)
|
|
472
|
+
|
|
473
|
+
if len(children) == 0:
|
|
474
|
+
return []
|
|
475
|
+
|
|
476
|
+
node = python_unrolling.Node(
|
|
477
|
+
text=f"for {loop_var} in {unrollee_expr}:",
|
|
478
|
+
children=children,
|
|
479
|
+
)
|
|
480
|
+
|
|
481
|
+
return [node]
|
|
482
|
+
|
|
483
|
+
def _unroll_optional_type_annotation(
|
|
484
|
+
self,
|
|
485
|
+
unrollee_expr: str,
|
|
486
|
+
type_annotation: intermediate.OptionalTypeAnnotation,
|
|
487
|
+
path: List[str],
|
|
488
|
+
list_loop_level: int,
|
|
489
|
+
) -> List[python_unrolling.Node]:
|
|
490
|
+
"""Generate code for the given specific ``type_annotation``."""
|
|
491
|
+
children = self.unroll(
|
|
492
|
+
unrollee_expr=unrollee_expr,
|
|
493
|
+
type_annotation=type_annotation.value,
|
|
494
|
+
path=path,
|
|
495
|
+
list_loop_level=list_loop_level,
|
|
496
|
+
)
|
|
497
|
+
|
|
498
|
+
if len(children) == 0:
|
|
499
|
+
return []
|
|
500
|
+
|
|
501
|
+
return [
|
|
502
|
+
python_unrolling.Node(
|
|
503
|
+
text=f"if {unrollee_expr} is not None:", children=children
|
|
504
|
+
)
|
|
505
|
+
]
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
def _generate_descend_body(cls: intermediate.ConcreteClass, recurse: bool) -> Stripped:
|
|
509
|
+
"""
|
|
510
|
+
Generate the body of the ``descend`` and ``descend_once`` methods.
|
|
511
|
+
|
|
512
|
+
With this function, we unroll the recursion as a simple optimization
|
|
513
|
+
in the recursive case.
|
|
514
|
+
"""
|
|
515
|
+
blocks = [] # type: List[Stripped]
|
|
516
|
+
|
|
517
|
+
generator_for_loop_variables = python_common.GeneratorForLoopVariables()
|
|
518
|
+
|
|
519
|
+
for prop in cls.properties:
|
|
520
|
+
descendability = intermediate.map_descendability(
|
|
521
|
+
type_annotation=prop.type_annotation
|
|
522
|
+
)
|
|
523
|
+
|
|
524
|
+
if not descendability[prop.type_annotation]:
|
|
525
|
+
continue
|
|
526
|
+
|
|
527
|
+
# region Unroll
|
|
528
|
+
|
|
529
|
+
unroller = _DescendBodyUnroller(
|
|
530
|
+
recurse=recurse,
|
|
531
|
+
descendability=descendability,
|
|
532
|
+
generator_for_loop_variables=generator_for_loop_variables,
|
|
533
|
+
)
|
|
534
|
+
|
|
535
|
+
roots = unroller.unroll(
|
|
536
|
+
unrollee_expr=f"self.{python_naming.property_name(prop.name)}",
|
|
537
|
+
type_annotation=prop.type_annotation,
|
|
538
|
+
path=[], # We do not use path in this context
|
|
539
|
+
list_loop_level=0,
|
|
540
|
+
)
|
|
541
|
+
|
|
542
|
+
assert len(roots) > 0, (
|
|
543
|
+
"Since the type annotation was descendable, we must have obtained "
|
|
544
|
+
"at least one unrolling node"
|
|
545
|
+
)
|
|
546
|
+
|
|
547
|
+
blocks.extend(Stripped(python_unrolling.render(root)) for root in roots)
|
|
548
|
+
|
|
549
|
+
# endregion
|
|
550
|
+
|
|
551
|
+
if len(blocks) == 0:
|
|
552
|
+
blocks.append(
|
|
553
|
+
Stripped(
|
|
554
|
+
"""\
|
|
555
|
+
# No descendable properties
|
|
556
|
+
return
|
|
557
|
+
# For this uncommon return-yield construction, see:
|
|
558
|
+
# https://stackoverflow.com/questions/13243766/how-to-define-an-empty-generator-function
|
|
559
|
+
# noinspection PyUnreachableCode
|
|
560
|
+
yield"""
|
|
561
|
+
)
|
|
562
|
+
)
|
|
563
|
+
|
|
564
|
+
return Stripped("\n\n".join(blocks))
|
|
565
|
+
|
|
566
|
+
|
|
567
|
+
def _generate_descend_once_method(cls: intermediate.ConcreteClass) -> Stripped:
|
|
568
|
+
"""Generate the ``descend_once`` method for the concrete class ``cls``."""
|
|
569
|
+
|
|
570
|
+
body = _generate_descend_body(cls=cls, recurse=False)
|
|
571
|
+
|
|
572
|
+
return Stripped(
|
|
573
|
+
f"""\
|
|
574
|
+
def descend_once(self) -> Iterator[Class]:
|
|
575
|
+
{I}\"\"\"
|
|
576
|
+
{I}Iterate over the instances referenced from this instance.
|
|
577
|
+
|
|
578
|
+
{I}We do not recurse into the referenced instance.
|
|
579
|
+
|
|
580
|
+
{I}:yield: instances directly referenced from this instance
|
|
581
|
+
{I}\"\"\"
|
|
582
|
+
{I}{indent_but_first_line(body, I)}"""
|
|
583
|
+
)
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
def _generate_descend_method(cls: intermediate.ConcreteClass) -> Stripped:
|
|
587
|
+
"""Generate the recursive ``descend`` method for the concrete class ``cls``."""
|
|
588
|
+
|
|
589
|
+
body = _generate_descend_body(cls=cls, recurse=True)
|
|
590
|
+
|
|
591
|
+
return Stripped(
|
|
592
|
+
f"""\
|
|
593
|
+
def descend(self) -> Iterator[Class]:
|
|
594
|
+
{I}\"\"\"
|
|
595
|
+
{I}Iterate recursively over the instances referenced from this one.
|
|
596
|
+
|
|
597
|
+
{I}:yield: instances recursively referenced from this instance
|
|
598
|
+
{I}\"\"\"
|
|
599
|
+
{I}{indent_but_first_line(body, I)}"""
|
|
600
|
+
)
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
def _generate_default_value(default: intermediate.Default) -> Stripped:
|
|
604
|
+
"""Generate the Python code representing the default value of an argument."""
|
|
605
|
+
code: str
|
|
606
|
+
|
|
607
|
+
if isinstance(default, intermediate.DefaultPrimitive):
|
|
608
|
+
if default.value is None:
|
|
609
|
+
code = "None"
|
|
610
|
+
elif isinstance(default.value, bool):
|
|
611
|
+
code = "True" if default.value else "False"
|
|
612
|
+
elif isinstance(default.value, str):
|
|
613
|
+
code = python_common.string_literal(default.value)
|
|
614
|
+
elif isinstance(default.value, int):
|
|
615
|
+
code = str(default.value)
|
|
616
|
+
elif isinstance(default.value, float):
|
|
617
|
+
code = f"{default}"
|
|
618
|
+
else:
|
|
619
|
+
assert_never(default.value)
|
|
620
|
+
elif isinstance(default, intermediate.DefaultEnumerationLiteral):
|
|
621
|
+
code = ".".join(
|
|
622
|
+
[
|
|
623
|
+
python_naming.enum_name(default.enumeration.name),
|
|
624
|
+
python_naming.enum_literal_name(default.literal.name),
|
|
625
|
+
]
|
|
626
|
+
)
|
|
627
|
+
else:
|
|
628
|
+
assert_never(default)
|
|
629
|
+
|
|
630
|
+
return Stripped(code)
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
@require(lambda cls: not cls.is_implementation_specific)
|
|
634
|
+
@require(lambda cls: not cls.constructor.is_implementation_specific)
|
|
635
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
636
|
+
def _generate_constructor(
|
|
637
|
+
cls: intermediate.ClassUnion,
|
|
638
|
+
symbol_table: intermediate.SymbolTable,
|
|
639
|
+
) -> Tuple[Optional[Stripped], Optional[Error]]:
|
|
640
|
+
"""
|
|
641
|
+
Generate the constructor function for the given class ``cls``.
|
|
642
|
+
|
|
643
|
+
Return empty string if there is an empty constructor.
|
|
644
|
+
"""
|
|
645
|
+
if len(cls.constructor.arguments) == 0 and len(cls.constructor.statements) == 0:
|
|
646
|
+
return Stripped(""), None
|
|
647
|
+
|
|
648
|
+
# region Construct the body
|
|
649
|
+
|
|
650
|
+
body = [] # type: List[Stripped]
|
|
651
|
+
for stmt in cls.constructor.statements:
|
|
652
|
+
if isinstance(stmt, intermediate_construction.CallSuperConstructor):
|
|
653
|
+
super_class = symbol_table.must_find_class(stmt.super_name)
|
|
654
|
+
|
|
655
|
+
writer = io.StringIO()
|
|
656
|
+
|
|
657
|
+
if len(super_class.constructor.arguments) == 0:
|
|
658
|
+
writer.write(
|
|
659
|
+
f"""\
|
|
660
|
+
{python_naming.class_name(super_class.name)}.__init__(
|
|
661
|
+
{I}self
|
|
662
|
+
)"""
|
|
663
|
+
)
|
|
664
|
+
else:
|
|
665
|
+
writer.write(
|
|
666
|
+
f"""\
|
|
667
|
+
{python_naming.class_name(super_class.name)}.__init__(
|
|
668
|
+
{I}self,
|
|
669
|
+
"""
|
|
670
|
+
)
|
|
671
|
+
for i, arg in enumerate(super_class.constructor.arguments):
|
|
672
|
+
writer.write(f"{I}{python_naming.argument_name(arg.name)}")
|
|
673
|
+
if i < len(super_class.constructor.arguments) - 1:
|
|
674
|
+
writer.write(",\n")
|
|
675
|
+
else:
|
|
676
|
+
writer.write("\n")
|
|
677
|
+
writer.write(")")
|
|
678
|
+
|
|
679
|
+
body.append(Stripped(writer.getvalue()))
|
|
680
|
+
|
|
681
|
+
elif isinstance(stmt, intermediate_construction.AssignArgument):
|
|
682
|
+
if stmt.default is None:
|
|
683
|
+
body.append(
|
|
684
|
+
Stripped(
|
|
685
|
+
f"self.{python_naming.property_name(stmt.name)} = "
|
|
686
|
+
f"{python_naming.argument_name(stmt.argument)}"
|
|
687
|
+
)
|
|
688
|
+
)
|
|
689
|
+
else:
|
|
690
|
+
if isinstance(stmt.default, intermediate_construction.EmptyList):
|
|
691
|
+
arg_name = python_naming.argument_name(stmt.argument)
|
|
692
|
+
|
|
693
|
+
# Write the assignment as a ternary operator
|
|
694
|
+
writer = io.StringIO()
|
|
695
|
+
writer.write(
|
|
696
|
+
f"""\
|
|
697
|
+
self.{python_naming.property_name(stmt.name)} = (
|
|
698
|
+
{I}{arg_name}
|
|
699
|
+
{I}if {arg_name} is not None
|
|
700
|
+
{I}else []
|
|
701
|
+
)"""
|
|
702
|
+
)
|
|
703
|
+
|
|
704
|
+
body.append(Stripped(writer.getvalue()))
|
|
705
|
+
elif isinstance(
|
|
706
|
+
stmt.default, intermediate_construction.DefaultEnumLiteral
|
|
707
|
+
):
|
|
708
|
+
literal_code = ".".join(
|
|
709
|
+
[
|
|
710
|
+
python_naming.enum_name(stmt.default.enum.name),
|
|
711
|
+
python_naming.enum_literal_name(stmt.default.literal.name),
|
|
712
|
+
]
|
|
713
|
+
)
|
|
714
|
+
|
|
715
|
+
arg_name = python_naming.argument_name(stmt.argument)
|
|
716
|
+
|
|
717
|
+
body.append(
|
|
718
|
+
Stripped(
|
|
719
|
+
f"""\
|
|
720
|
+
self.{python_naming.property_name(stmt.name)} = (
|
|
721
|
+
{I}{arg_name}
|
|
722
|
+
{I}if {arg_name} is not None
|
|
723
|
+
{I}else {literal_code}
|
|
724
|
+
)"""
|
|
725
|
+
)
|
|
726
|
+
)
|
|
727
|
+
else:
|
|
728
|
+
assert_never(stmt.default)
|
|
729
|
+
|
|
730
|
+
else:
|
|
731
|
+
assert_never(stmt)
|
|
732
|
+
|
|
733
|
+
# endregion
|
|
734
|
+
|
|
735
|
+
# region Assemble the constructor with the definition and the body
|
|
736
|
+
|
|
737
|
+
arg_codes = [] # type: List[str]
|
|
738
|
+
for arg in cls.constructor.arguments:
|
|
739
|
+
arg_type = python_common.generate_type(type_annotation=arg.type_annotation)
|
|
740
|
+
arg_name = python_naming.argument_name(arg.name)
|
|
741
|
+
|
|
742
|
+
if arg.default is None:
|
|
743
|
+
arg_codes.append(Stripped(f"{arg_name}: {arg_type}"))
|
|
744
|
+
else:
|
|
745
|
+
arg_codes.append(
|
|
746
|
+
Stripped(
|
|
747
|
+
f"{arg_name}: {arg_type} = {_generate_default_value(arg.default)}"
|
|
748
|
+
)
|
|
749
|
+
)
|
|
750
|
+
|
|
751
|
+
writer = io.StringIO()
|
|
752
|
+
|
|
753
|
+
if len(arg_codes) == 0:
|
|
754
|
+
writer.write("def __init__(self) -> None:\n")
|
|
755
|
+
if len(arg_codes) == 1:
|
|
756
|
+
writer.write(f"def __init__(self, {arg_codes[0]}) -> None:\n")
|
|
757
|
+
else:
|
|
758
|
+
arg_block = ",\n".join(["self"] + arg_codes)
|
|
759
|
+
arg_block_indented = textwrap.indent(arg_block, II)
|
|
760
|
+
writer.write(f"def __init__(\n{arg_block_indented}\n) -> None:\n")
|
|
761
|
+
|
|
762
|
+
writer.write(f'{I}"""Initialize with the given values."""')
|
|
763
|
+
|
|
764
|
+
if len(body) > 0:
|
|
765
|
+
for body_stmt in body:
|
|
766
|
+
writer.write(f"\n{I}{indent_but_first_line(body_stmt, I)}")
|
|
767
|
+
|
|
768
|
+
# endregion
|
|
769
|
+
|
|
770
|
+
return Stripped(writer.getvalue()), None
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
@require(lambda cls, prop: id(prop) in cls.property_id_set)
|
|
774
|
+
@require(lambda prop: prop.description is not None)
|
|
775
|
+
def _generate_comment_for_property(
|
|
776
|
+
cls: intermediate.ClassUnion,
|
|
777
|
+
prop: intermediate.Property,
|
|
778
|
+
aas_module: python_common.QualifiedModuleName,
|
|
779
|
+
) -> Tuple[Optional[Stripped], Optional[List[Error]]]:
|
|
780
|
+
"""Generate the documentation comment for the given property."""
|
|
781
|
+
# NOTE (mristin, 2022-10-29):
|
|
782
|
+
# We need to write a double assertion for mypy.
|
|
783
|
+
assert prop.description is not None
|
|
784
|
+
|
|
785
|
+
text, errors = python_description.generate_summary_remarks_constraints(
|
|
786
|
+
description=prop.description,
|
|
787
|
+
context=python_description.Context(
|
|
788
|
+
aas_module=aas_module, module=Identifier("types"), cls_or_enum=cls
|
|
789
|
+
),
|
|
790
|
+
)
|
|
791
|
+
|
|
792
|
+
if errors is not None:
|
|
793
|
+
return None, errors
|
|
794
|
+
|
|
795
|
+
assert text is not None
|
|
796
|
+
|
|
797
|
+
return python_description.documentation_comment(text), None
|
|
798
|
+
|
|
799
|
+
|
|
800
|
+
@require(lambda cls: not cls.is_implementation_specific)
|
|
801
|
+
@ensure(lambda result: (result[0] is None) ^ (result[1] is None))
|
|
802
|
+
def _generate_class(
|
|
803
|
+
cls: intermediate.ClassUnion,
|
|
804
|
+
spec_impls: specific_implementations.SpecificImplementations,
|
|
805
|
+
aas_module: python_common.QualifiedModuleName,
|
|
806
|
+
symbol_table: intermediate.SymbolTable,
|
|
807
|
+
) -> Tuple[Optional[Stripped], Optional[Error]]:
|
|
808
|
+
"""Generate Python code for the given concrete class ``cls``."""
|
|
809
|
+
# region Collect blocks of the class body
|
|
810
|
+
|
|
811
|
+
# Code blocks of the class body separated by double newlines and indented once
|
|
812
|
+
blocks = [] # type: List[Stripped]
|
|
813
|
+
|
|
814
|
+
# region Property definitions
|
|
815
|
+
|
|
816
|
+
for prop in cls.properties:
|
|
817
|
+
if prop.specified_for is not cls:
|
|
818
|
+
continue
|
|
819
|
+
|
|
820
|
+
prop_comment = None # type: Optional[Stripped]
|
|
821
|
+
if prop.description is not None:
|
|
822
|
+
prop_comment, prop_comment_errors = _generate_comment_for_property(
|
|
823
|
+
cls=cls, prop=prop, aas_module=aas_module
|
|
824
|
+
)
|
|
825
|
+
if prop_comment_errors is not None:
|
|
826
|
+
return None, Error(
|
|
827
|
+
prop.description.parsed.node,
|
|
828
|
+
"Failed to generate the property comment",
|
|
829
|
+
prop_comment_errors,
|
|
830
|
+
)
|
|
831
|
+
|
|
832
|
+
prop_type = python_common.generate_type(type_annotation=prop.type_annotation)
|
|
833
|
+
prop_name = python_naming.property_name(prop.name)
|
|
834
|
+
|
|
835
|
+
writer = io.StringIO()
|
|
836
|
+
if prop_comment is not None:
|
|
837
|
+
writer.write(prop_comment)
|
|
838
|
+
writer.write("\n")
|
|
839
|
+
writer.write(f"{prop_name}: {prop_type}")
|
|
840
|
+
blocks.append(Stripped(writer.getvalue()))
|
|
841
|
+
|
|
842
|
+
# endregion
|
|
843
|
+
|
|
844
|
+
# region over_X_or_empty getter
|
|
845
|
+
|
|
846
|
+
for prop in cls.properties:
|
|
847
|
+
if prop.specified_for is not cls:
|
|
848
|
+
continue
|
|
849
|
+
|
|
850
|
+
if isinstance(
|
|
851
|
+
prop.type_annotation, intermediate.OptionalTypeAnnotation
|
|
852
|
+
) and isinstance(prop.type_annotation.value, intermediate.ListTypeAnnotation):
|
|
853
|
+
prop_name = python_naming.property_name(prop.name)
|
|
854
|
+
items_type = python_common.generate_type(prop.type_annotation.value.items)
|
|
855
|
+
|
|
856
|
+
blocks.append(
|
|
857
|
+
Stripped(
|
|
858
|
+
f"""\
|
|
859
|
+
def over_{prop_name}_or_empty(
|
|
860
|
+
{II}self
|
|
861
|
+
) -> Iterator[{items_type}]:
|
|
862
|
+
{I}\"\"\"Yield from :py:attr:`.{prop_name}` if set.\"\"\"
|
|
863
|
+
{I}if self.{prop_name} is not None:
|
|
864
|
+
{II}yield from self.{prop_name}"""
|
|
865
|
+
)
|
|
866
|
+
)
|
|
867
|
+
|
|
868
|
+
# endregion
|
|
869
|
+
|
|
870
|
+
# region Methods
|
|
871
|
+
|
|
872
|
+
errors = [] # type: List[Error]
|
|
873
|
+
|
|
874
|
+
for method in cls.methods:
|
|
875
|
+
if method.specified_for is not cls:
|
|
876
|
+
continue
|
|
877
|
+
|
|
878
|
+
if isinstance(method, intermediate.ImplementationSpecificMethod):
|
|
879
|
+
implementation_key = specific_implementations.ImplementationKey(
|
|
880
|
+
f"Types/{method.specified_for.name}/{method.name}.py"
|
|
881
|
+
)
|
|
882
|
+
|
|
883
|
+
implementation = spec_impls.get(implementation_key, None)
|
|
884
|
+
|
|
885
|
+
if implementation is None:
|
|
886
|
+
errors.append(
|
|
887
|
+
Error(
|
|
888
|
+
method.parsed.node,
|
|
889
|
+
f"The implementation is missing for "
|
|
890
|
+
f"the implementation-specific method: {implementation_key}",
|
|
891
|
+
)
|
|
892
|
+
)
|
|
893
|
+
continue
|
|
894
|
+
|
|
895
|
+
blocks.append(implementation)
|
|
896
|
+
else:
|
|
897
|
+
# NOTE (mristin, 2022-09-28):
|
|
898
|
+
# At the moment, we do not transpile the method body and its contracts.
|
|
899
|
+
# We want to finish the meta-model for the V3, fix de/serialization and
|
|
900
|
+
# generate SDKs for a couple of languages before taking on this rather hard
|
|
901
|
+
# task.
|
|
902
|
+
|
|
903
|
+
errors.append(
|
|
904
|
+
Error(
|
|
905
|
+
cls.parsed.node,
|
|
906
|
+
"At the moment, we do not transpile the method body and "
|
|
907
|
+
"its contracts. We want to finish the meta-model for the V3, "
|
|
908
|
+
"fix de/serialization and generate SDKs for a couple of languages "
|
|
909
|
+
"before taking on this rather hard task.",
|
|
910
|
+
)
|
|
911
|
+
)
|
|
912
|
+
|
|
913
|
+
if isinstance(cls, intermediate.ConcreteClass):
|
|
914
|
+
blocks.append(_generate_descend_once_method(cls=cls))
|
|
915
|
+
|
|
916
|
+
blocks.append(_generate_descend_method(cls=cls))
|
|
917
|
+
|
|
918
|
+
visit_name = python_naming.method_name(Identifier(f"visit_{cls.name}"))
|
|
919
|
+
|
|
920
|
+
blocks.append(
|
|
921
|
+
Stripped(
|
|
922
|
+
f"""\
|
|
923
|
+
def accept(self, visitor: "AbstractVisitor") -> None:
|
|
924
|
+
{I}\"\"\"Dispatch the :paramref:`visitor` on this instance.\"\"\"
|
|
925
|
+
{I}visitor.{visit_name}(self)"""
|
|
926
|
+
)
|
|
927
|
+
)
|
|
928
|
+
|
|
929
|
+
visit_with_context_name = python_naming.method_name(
|
|
930
|
+
Identifier(f"visit_{cls.name}_with_context")
|
|
931
|
+
)
|
|
932
|
+
|
|
933
|
+
blocks.append(
|
|
934
|
+
Stripped(
|
|
935
|
+
f"""\
|
|
936
|
+
def accept_with_context(
|
|
937
|
+
{II}self,
|
|
938
|
+
{II}visitor: "AbstractVisitorWithContext[ContextT]",
|
|
939
|
+
{II}context: ContextT
|
|
940
|
+
) -> None:
|
|
941
|
+
{I}\"\"\"Dispatch the :paramref:`visitor` on this instance in :paramref:`context`.\"\"\"
|
|
942
|
+
{I}visitor.{visit_with_context_name}(self, context)"""
|
|
943
|
+
)
|
|
944
|
+
)
|
|
945
|
+
|
|
946
|
+
transform_name = python_naming.method_name(Identifier(f"transform_{cls.name}"))
|
|
947
|
+
|
|
948
|
+
blocks.append(
|
|
949
|
+
Stripped(
|
|
950
|
+
f"""\
|
|
951
|
+
def transform(
|
|
952
|
+
{II}self,
|
|
953
|
+
{II}transformer: "AbstractTransformer[T]"
|
|
954
|
+
) -> T:
|
|
955
|
+
{I}\"\"\"Dispatch the :paramref:`transformer` on this instance.\"\"\"
|
|
956
|
+
{I}return transformer.{transform_name}(self)"""
|
|
957
|
+
)
|
|
958
|
+
)
|
|
959
|
+
|
|
960
|
+
transform_with_context_name = python_naming.method_name(
|
|
961
|
+
Identifier(f"transform_{cls.name}_with_context")
|
|
962
|
+
)
|
|
963
|
+
|
|
964
|
+
blocks.append(
|
|
965
|
+
Stripped(
|
|
966
|
+
f"""\
|
|
967
|
+
def transform_with_context(
|
|
968
|
+
{II}self,
|
|
969
|
+
{II}transformer: "AbstractTransformerWithContext[ContextT, T]",
|
|
970
|
+
{II}context: ContextT
|
|
971
|
+
) -> T:
|
|
972
|
+
{I}\"\"\"
|
|
973
|
+
{I}Dispatch the :paramref:`transformer` on this instance in :paramref:`context`.
|
|
974
|
+
{I}\"\"\"
|
|
975
|
+
{I}return transformer.{transform_with_context_name}(
|
|
976
|
+
{II}self, context)"""
|
|
977
|
+
)
|
|
978
|
+
)
|
|
979
|
+
|
|
980
|
+
# endregion
|
|
981
|
+
|
|
982
|
+
# region Constructor
|
|
983
|
+
|
|
984
|
+
if cls.constructor.is_implementation_specific:
|
|
985
|
+
implementation_key = specific_implementations.ImplementationKey(
|
|
986
|
+
f"Types/{cls.name}/{cls.name}.py"
|
|
987
|
+
)
|
|
988
|
+
implementation = spec_impls.get(implementation_key, None)
|
|
989
|
+
|
|
990
|
+
if implementation is None:
|
|
991
|
+
errors.append(
|
|
992
|
+
Error(
|
|
993
|
+
cls.parsed.node,
|
|
994
|
+
f"The implementation of the implementation-specific constructor "
|
|
995
|
+
f"is missing: {implementation_key}",
|
|
996
|
+
)
|
|
997
|
+
)
|
|
998
|
+
else:
|
|
999
|
+
blocks.append(implementation)
|
|
1000
|
+
else:
|
|
1001
|
+
constructor_block, error = _generate_constructor(
|
|
1002
|
+
cls=cls, symbol_table=symbol_table
|
|
1003
|
+
)
|
|
1004
|
+
|
|
1005
|
+
if error is not None:
|
|
1006
|
+
errors.append(error)
|
|
1007
|
+
else:
|
|
1008
|
+
assert constructor_block is not None
|
|
1009
|
+
|
|
1010
|
+
# NOTE (mristin, 2022-06-21):
|
|
1011
|
+
# Empty constructor will be automatically generated by the interpreter.
|
|
1012
|
+
if constructor_block != "":
|
|
1013
|
+
blocks.append(constructor_block)
|
|
1014
|
+
|
|
1015
|
+
# endregion
|
|
1016
|
+
|
|
1017
|
+
if len(errors) > 0:
|
|
1018
|
+
return None, Error(
|
|
1019
|
+
cls.parsed.node,
|
|
1020
|
+
f"Failed to generate the code for the class {cls.name}",
|
|
1021
|
+
errors,
|
|
1022
|
+
)
|
|
1023
|
+
|
|
1024
|
+
docstring = None # type: Optional[Stripped]
|
|
1025
|
+
if cls.description is not None:
|
|
1026
|
+
docstring, docstring_errors = _generate_docstring_for_cls_or_enum(
|
|
1027
|
+
cls_or_enum=cls, aas_module=aas_module
|
|
1028
|
+
)
|
|
1029
|
+
if docstring_errors is not None:
|
|
1030
|
+
return None, Error(
|
|
1031
|
+
cls.description.parsed.node,
|
|
1032
|
+
"Failed to generate the docstring",
|
|
1033
|
+
docstring_errors,
|
|
1034
|
+
)
|
|
1035
|
+
|
|
1036
|
+
assert docstring is not None
|
|
1037
|
+
|
|
1038
|
+
# endregion
|
|
1039
|
+
|
|
1040
|
+
# region Assemble the class definition with its body
|
|
1041
|
+
|
|
1042
|
+
name = python_naming.class_name(cls.name)
|
|
1043
|
+
|
|
1044
|
+
# NOTE (mristin, 2022-09-17):
|
|
1045
|
+
# Every class in the meta-model inherits from the most general abstract class
|
|
1046
|
+
# ``Class`.
|
|
1047
|
+
|
|
1048
|
+
super_names = [] # type: List[str]
|
|
1049
|
+
|
|
1050
|
+
if len(cls.inheritances) == 0:
|
|
1051
|
+
# NOTE (mristin, 2022-09-17):
|
|
1052
|
+
# We only have to include the most general ancestor ``Class`` if there are no
|
|
1053
|
+
# ancestors. Otherwise, one of the ancestors will have already inherited from
|
|
1054
|
+
# it.
|
|
1055
|
+
super_names.append("Class")
|
|
1056
|
+
else:
|
|
1057
|
+
super_names = [
|
|
1058
|
+
python_naming.class_name(inheritance.name)
|
|
1059
|
+
for inheritance in cls.inheritances
|
|
1060
|
+
]
|
|
1061
|
+
|
|
1062
|
+
assert len(super_names) > 0, "Assumption for the code generation below"
|
|
1063
|
+
|
|
1064
|
+
writer = io.StringIO()
|
|
1065
|
+
if sum(len(super_name) + 2 for super_name in super_names) + len(name) < 70:
|
|
1066
|
+
# NOTE (mristin, 2022-09-17):
|
|
1067
|
+
# Put the class definition on the single line as it fit by the heuristic.
|
|
1068
|
+
super_names_joined = ", ".join(super_names)
|
|
1069
|
+
writer.write(f"class {name}({super_names_joined}):\n")
|
|
1070
|
+
else:
|
|
1071
|
+
writer.write(f"class {name}(\n")
|
|
1072
|
+
for i, super_name in enumerate(super_names):
|
|
1073
|
+
if i < len(super_names) - 1:
|
|
1074
|
+
writer.write(f"{II}{super_name},\n")
|
|
1075
|
+
else:
|
|
1076
|
+
writer.write(f"{II}{super_name}")
|
|
1077
|
+
writer.write("):\n")
|
|
1078
|
+
|
|
1079
|
+
if docstring is not None:
|
|
1080
|
+
writer.write(textwrap.indent(docstring, I))
|
|
1081
|
+
else:
|
|
1082
|
+
writer.write(f"{I}# pylint: disable=missing-class-docstring")
|
|
1083
|
+
|
|
1084
|
+
if len(blocks) == 0:
|
|
1085
|
+
# NOTE (mristin, 2022-09-28):
|
|
1086
|
+
# We have to add a ``pass`` statement if there was no description. Otherwise,
|
|
1087
|
+
# the generated code would be invalid. In cases where description is defined,
|
|
1088
|
+
# a ``pass`` statement is redundant.
|
|
1089
|
+
if docstring is None:
|
|
1090
|
+
writer.write(f"\n{I}pass")
|
|
1091
|
+
else:
|
|
1092
|
+
for i, code in enumerate(blocks):
|
|
1093
|
+
writer.write("\n\n")
|
|
1094
|
+
writer.write(textwrap.indent(code, I))
|
|
1095
|
+
|
|
1096
|
+
# endregion
|
|
1097
|
+
|
|
1098
|
+
return Stripped(writer.getvalue()), None
|
|
1099
|
+
|
|
1100
|
+
|
|
1101
|
+
def _generate_abstract_visitor(symbol_table: intermediate.SymbolTable) -> Stripped:
|
|
1102
|
+
"""Generate the code for the abstract visitor."""
|
|
1103
|
+
blocks = [
|
|
1104
|
+
Stripped(
|
|
1105
|
+
f"""\
|
|
1106
|
+
def visit(
|
|
1107
|
+
{II}self,
|
|
1108
|
+
{II}that: Class
|
|
1109
|
+
) -> None:
|
|
1110
|
+
{I}\"\"\"Double-dispatch on :paramref:`that`.\"\"\"
|
|
1111
|
+
{I}that.accept(self)"""
|
|
1112
|
+
)
|
|
1113
|
+
] # type: List[Stripped]
|
|
1114
|
+
|
|
1115
|
+
for cls in symbol_table.concrete_classes:
|
|
1116
|
+
visit_name = python_naming.method_name(Identifier(f"visit_{cls.name}"))
|
|
1117
|
+
cls_name = python_naming.class_name(cls.name)
|
|
1118
|
+
|
|
1119
|
+
blocks.append(
|
|
1120
|
+
Stripped(
|
|
1121
|
+
f"""\
|
|
1122
|
+
@abc.abstractmethod
|
|
1123
|
+
def {visit_name}(
|
|
1124
|
+
{II}self,
|
|
1125
|
+
{II}that: {cls_name}
|
|
1126
|
+
) -> None:
|
|
1127
|
+
{I}\"\"\"Visit :paramref:`that`.\"\"\"
|
|
1128
|
+
{I}raise NotImplementedError()"""
|
|
1129
|
+
)
|
|
1130
|
+
)
|
|
1131
|
+
|
|
1132
|
+
writer = io.StringIO()
|
|
1133
|
+
writer.write(
|
|
1134
|
+
f"""\
|
|
1135
|
+
class AbstractVisitor:
|
|
1136
|
+
{I}\"\"\"Visit the instances of the model.\"\"\"
|
|
1137
|
+
"""
|
|
1138
|
+
)
|
|
1139
|
+
|
|
1140
|
+
for i, block in enumerate(blocks):
|
|
1141
|
+
if i > 0:
|
|
1142
|
+
writer.write("\n\n")
|
|
1143
|
+
|
|
1144
|
+
writer.write(textwrap.indent(block, I))
|
|
1145
|
+
|
|
1146
|
+
return Stripped(writer.getvalue())
|
|
1147
|
+
|
|
1148
|
+
|
|
1149
|
+
def _generate_abstract_visitor_with_context(
|
|
1150
|
+
symbol_table: intermediate.SymbolTable,
|
|
1151
|
+
) -> Stripped:
|
|
1152
|
+
"""Generate the code for the abstract visitor with context."""
|
|
1153
|
+
blocks = [
|
|
1154
|
+
Stripped(
|
|
1155
|
+
f"""\
|
|
1156
|
+
def visit_with_context(
|
|
1157
|
+
{II}self,
|
|
1158
|
+
{II}that: Class,
|
|
1159
|
+
{II}context: ContextT
|
|
1160
|
+
) -> None:
|
|
1161
|
+
{I}\"\"\"Double-dispatch on :paramref:`that`.\"\"\"
|
|
1162
|
+
{I}that.accept_with_context(self, context)"""
|
|
1163
|
+
)
|
|
1164
|
+
] # type: List[Stripped]
|
|
1165
|
+
|
|
1166
|
+
for cls in symbol_table.concrete_classes:
|
|
1167
|
+
visit_with_context_name = python_naming.method_name(
|
|
1168
|
+
Identifier(f"visit_{cls.name}_with_context")
|
|
1169
|
+
)
|
|
1170
|
+
cls_name = python_naming.class_name(cls.name)
|
|
1171
|
+
|
|
1172
|
+
blocks.append(
|
|
1173
|
+
Stripped(
|
|
1174
|
+
f"""\
|
|
1175
|
+
@abc.abstractmethod
|
|
1176
|
+
def {visit_with_context_name}(
|
|
1177
|
+
{II}self,
|
|
1178
|
+
{II}that: {cls_name},
|
|
1179
|
+
{II}context: ContextT
|
|
1180
|
+
) -> None:
|
|
1181
|
+
{I}\"\"\"Visit :paramref:`that` in :paramref:`context`.\"\"\"
|
|
1182
|
+
{I}raise NotImplementedError()"""
|
|
1183
|
+
)
|
|
1184
|
+
)
|
|
1185
|
+
|
|
1186
|
+
writer = io.StringIO()
|
|
1187
|
+
writer.write(
|
|
1188
|
+
f"""\
|
|
1189
|
+
class AbstractVisitorWithContext(Generic[ContextT]):
|
|
1190
|
+
{I}\"\"\"Visit the instances of the model with context.\"\"\"
|
|
1191
|
+
"""
|
|
1192
|
+
)
|
|
1193
|
+
|
|
1194
|
+
for i, block in enumerate(blocks):
|
|
1195
|
+
if i > 0:
|
|
1196
|
+
writer.write("\n\n")
|
|
1197
|
+
|
|
1198
|
+
writer.write(textwrap.indent(block, I))
|
|
1199
|
+
|
|
1200
|
+
return Stripped(writer.getvalue())
|
|
1201
|
+
|
|
1202
|
+
|
|
1203
|
+
def _generate_pass_through_visitor(symbol_table: intermediate.SymbolTable) -> Stripped:
|
|
1204
|
+
"""Generate the code for the pass-through visitor."""
|
|
1205
|
+
blocks = [
|
|
1206
|
+
Stripped(
|
|
1207
|
+
f"""\
|
|
1208
|
+
def visit(
|
|
1209
|
+
{II}self,
|
|
1210
|
+
{II}that: Class
|
|
1211
|
+
) -> None:
|
|
1212
|
+
{I}\"\"\"Double-dispatch on :paramref:`that`.\"\"\"
|
|
1213
|
+
{I}that.accept(self)"""
|
|
1214
|
+
)
|
|
1215
|
+
] # type: List[Stripped]
|
|
1216
|
+
|
|
1217
|
+
for cls in symbol_table.concrete_classes:
|
|
1218
|
+
visit_name = python_naming.method_name(Identifier(f"visit_{cls.name}"))
|
|
1219
|
+
cls_name = python_naming.class_name(cls.name)
|
|
1220
|
+
|
|
1221
|
+
blocks.append(
|
|
1222
|
+
Stripped(
|
|
1223
|
+
f"""\
|
|
1224
|
+
def {visit_name}(
|
|
1225
|
+
{II}self,
|
|
1226
|
+
{II}that: {cls_name}
|
|
1227
|
+
) -> None:
|
|
1228
|
+
{I}\"\"\"Visit :paramref:`that`.\"\"\"
|
|
1229
|
+
{I}for another in that.descend_once():
|
|
1230
|
+
{II}self.visit(another)"""
|
|
1231
|
+
)
|
|
1232
|
+
)
|
|
1233
|
+
|
|
1234
|
+
writer = io.StringIO()
|
|
1235
|
+
writer.write(
|
|
1236
|
+
f"""\
|
|
1237
|
+
class PassThroughVisitor(AbstractVisitor):
|
|
1238
|
+
{I}\"\"\"
|
|
1239
|
+
{I}Visit the instances of the model without action.
|
|
1240
|
+
|
|
1241
|
+
{I}This visitor is not meant to be directly used. Instead, you usually
|
|
1242
|
+
{I}inherit from it, and implement only the relevant visit methods.
|
|
1243
|
+
{I}\"\"\"
|
|
1244
|
+
"""
|
|
1245
|
+
)
|
|
1246
|
+
|
|
1247
|
+
for i, block in enumerate(blocks):
|
|
1248
|
+
if i > 0:
|
|
1249
|
+
writer.write("\n\n")
|
|
1250
|
+
|
|
1251
|
+
writer.write(textwrap.indent(block, I))
|
|
1252
|
+
|
|
1253
|
+
return Stripped(writer.getvalue())
|
|
1254
|
+
|
|
1255
|
+
|
|
1256
|
+
def _generate_pass_through_visitor_with_context(
|
|
1257
|
+
symbol_table: intermediate.SymbolTable,
|
|
1258
|
+
) -> Stripped:
|
|
1259
|
+
"""Generate the code for the pass-through visitor with context."""
|
|
1260
|
+
blocks = [
|
|
1261
|
+
Stripped(
|
|
1262
|
+
f"""\
|
|
1263
|
+
def visit_with_context(
|
|
1264
|
+
{II}self,
|
|
1265
|
+
{II}that: Class,
|
|
1266
|
+
{II}context: ContextT
|
|
1267
|
+
) -> None:
|
|
1268
|
+
{I}\"\"\"Double-dispatch on :paramref:`that`.\"\"\"
|
|
1269
|
+
{I}that.accept_with_context(self, context)"""
|
|
1270
|
+
)
|
|
1271
|
+
] # type: List[Stripped]
|
|
1272
|
+
|
|
1273
|
+
for cls in symbol_table.concrete_classes:
|
|
1274
|
+
visit_with_context_name = python_naming.method_name(
|
|
1275
|
+
Identifier(f"visit_{cls.name}_with_context")
|
|
1276
|
+
)
|
|
1277
|
+
cls_name = python_naming.class_name(cls.name)
|
|
1278
|
+
|
|
1279
|
+
blocks.append(
|
|
1280
|
+
Stripped(
|
|
1281
|
+
f"""\
|
|
1282
|
+
def {visit_with_context_name}(
|
|
1283
|
+
{II}self,
|
|
1284
|
+
{II}that: {cls_name},
|
|
1285
|
+
{II}context: ContextT
|
|
1286
|
+
) -> None:
|
|
1287
|
+
{I}\"\"\"Visit :paramref:`that` in :paramref:`context`.\"\"\"
|
|
1288
|
+
{I}for another in that.descend_once():
|
|
1289
|
+
{II}self.visit_with_context(another, context)"""
|
|
1290
|
+
)
|
|
1291
|
+
)
|
|
1292
|
+
|
|
1293
|
+
writer = io.StringIO()
|
|
1294
|
+
writer.write(
|
|
1295
|
+
f"""\
|
|
1296
|
+
class PassThroughVisitorWithContext(
|
|
1297
|
+
{II}AbstractVisitorWithContext[ContextT]
|
|
1298
|
+
):
|
|
1299
|
+
{I}\"\"\"
|
|
1300
|
+
{I}Visit the instances of the model without action and in context.
|
|
1301
|
+
|
|
1302
|
+
{I}This visitor is not meant to be directly used. Instead, you usually
|
|
1303
|
+
{I}inherit from it, and implement only the relevant visit methods.
|
|
1304
|
+
{I}\"\"\"
|
|
1305
|
+
"""
|
|
1306
|
+
)
|
|
1307
|
+
|
|
1308
|
+
for i, block in enumerate(blocks):
|
|
1309
|
+
if i > 0:
|
|
1310
|
+
writer.write("\n\n")
|
|
1311
|
+
|
|
1312
|
+
writer.write(textwrap.indent(block, I))
|
|
1313
|
+
|
|
1314
|
+
return Stripped(writer.getvalue())
|
|
1315
|
+
|
|
1316
|
+
|
|
1317
|
+
def _generate_abstract_transformer(symbol_table: intermediate.SymbolTable) -> Stripped:
|
|
1318
|
+
"""Generate the code for the abstract transformer."""
|
|
1319
|
+
blocks = [
|
|
1320
|
+
Stripped(
|
|
1321
|
+
f"""\
|
|
1322
|
+
def transform(
|
|
1323
|
+
{II}self,
|
|
1324
|
+
{II}that: Class
|
|
1325
|
+
) -> T:
|
|
1326
|
+
{I}\"\"\"Double-dispatch on :paramref:`that`.\"\"\"
|
|
1327
|
+
{I}return that.transform(self)"""
|
|
1328
|
+
)
|
|
1329
|
+
] # type: List[Stripped]
|
|
1330
|
+
|
|
1331
|
+
for cls in symbol_table.concrete_classes:
|
|
1332
|
+
transform_name = python_naming.method_name(Identifier(f"transform_{cls.name}"))
|
|
1333
|
+
|
|
1334
|
+
cls_name = python_naming.class_name(cls.name)
|
|
1335
|
+
|
|
1336
|
+
blocks.append(
|
|
1337
|
+
Stripped(
|
|
1338
|
+
f"""\
|
|
1339
|
+
@abc.abstractmethod
|
|
1340
|
+
def {transform_name}(
|
|
1341
|
+
{II}self,
|
|
1342
|
+
{II}that: {cls_name}
|
|
1343
|
+
) -> T:
|
|
1344
|
+
{I}\"\"\"Transform :paramref:`that`.\"\"\"
|
|
1345
|
+
{I}raise NotImplementedError()"""
|
|
1346
|
+
)
|
|
1347
|
+
)
|
|
1348
|
+
|
|
1349
|
+
writer = io.StringIO()
|
|
1350
|
+
writer.write(
|
|
1351
|
+
f"""\
|
|
1352
|
+
class AbstractTransformer(Generic[T]):
|
|
1353
|
+
{I}\"\"\"Transform the instances of the model.\"\"\"
|
|
1354
|
+
"""
|
|
1355
|
+
)
|
|
1356
|
+
|
|
1357
|
+
for i, block in enumerate(blocks):
|
|
1358
|
+
if i > 0:
|
|
1359
|
+
writer.write("\n\n")
|
|
1360
|
+
|
|
1361
|
+
writer.write(textwrap.indent(block, I))
|
|
1362
|
+
|
|
1363
|
+
return Stripped(writer.getvalue())
|
|
1364
|
+
|
|
1365
|
+
|
|
1366
|
+
def _generate_abstract_transformer_with_context(
|
|
1367
|
+
symbol_table: intermediate.SymbolTable,
|
|
1368
|
+
) -> Stripped:
|
|
1369
|
+
"""Generate the code for the abstract transformer with context."""
|
|
1370
|
+
blocks = [
|
|
1371
|
+
Stripped(
|
|
1372
|
+
f"""\
|
|
1373
|
+
def transform_with_context(
|
|
1374
|
+
{II}self,
|
|
1375
|
+
{II}that: Class,
|
|
1376
|
+
{II}context: ContextT
|
|
1377
|
+
) -> T:
|
|
1378
|
+
{I}\"\"\"Double-dispatch on :paramref:`that`.\"\"\"
|
|
1379
|
+
{I}return that.transform_with_context(self, context)"""
|
|
1380
|
+
)
|
|
1381
|
+
] # type: List[Stripped]
|
|
1382
|
+
|
|
1383
|
+
for cls in symbol_table.concrete_classes:
|
|
1384
|
+
transform_with_context_name = python_naming.method_name(
|
|
1385
|
+
Identifier(f"transform_{cls.name}_with_context")
|
|
1386
|
+
)
|
|
1387
|
+
|
|
1388
|
+
cls_name = python_naming.class_name(cls.name)
|
|
1389
|
+
|
|
1390
|
+
blocks.append(
|
|
1391
|
+
Stripped(
|
|
1392
|
+
f"""\
|
|
1393
|
+
@abc.abstractmethod
|
|
1394
|
+
def {transform_with_context_name}(
|
|
1395
|
+
{II}self,
|
|
1396
|
+
{II}that: {cls_name},
|
|
1397
|
+
{II}context: ContextT
|
|
1398
|
+
) -> T:
|
|
1399
|
+
{I}\"\"\"Transform :paramref:`that` in :paramref:`context`.\"\"\"
|
|
1400
|
+
{I}raise NotImplementedError()"""
|
|
1401
|
+
)
|
|
1402
|
+
)
|
|
1403
|
+
|
|
1404
|
+
writer = io.StringIO()
|
|
1405
|
+
writer.write(
|
|
1406
|
+
f"""\
|
|
1407
|
+
class AbstractTransformerWithContext(
|
|
1408
|
+
{II}Generic[ContextT, T]
|
|
1409
|
+
):
|
|
1410
|
+
{I}\"\"\"Transform the instances of the model in context.\"\"\"
|
|
1411
|
+
"""
|
|
1412
|
+
)
|
|
1413
|
+
|
|
1414
|
+
for i, block in enumerate(blocks):
|
|
1415
|
+
if i > 0:
|
|
1416
|
+
writer.write("\n\n")
|
|
1417
|
+
|
|
1418
|
+
writer.write(textwrap.indent(block, I))
|
|
1419
|
+
|
|
1420
|
+
return Stripped(writer.getvalue())
|
|
1421
|
+
|
|
1422
|
+
|
|
1423
|
+
def _generate_transformer_with_default(
|
|
1424
|
+
symbol_table: intermediate.SymbolTable,
|
|
1425
|
+
) -> Stripped:
|
|
1426
|
+
"""Generate the code for the transformer with default transformation."""
|
|
1427
|
+
blocks = [
|
|
1428
|
+
Stripped(
|
|
1429
|
+
"""\
|
|
1430
|
+
#: Default value which is returned if no override of the transformation
|
|
1431
|
+
default: T"""
|
|
1432
|
+
),
|
|
1433
|
+
Stripped(
|
|
1434
|
+
f"""\
|
|
1435
|
+
def __init__(self, default: T) -> None:
|
|
1436
|
+
{I}\"\"\"Initialize with the given :paramref:`default` value.\"\"\"
|
|
1437
|
+
{I}self.default = default"""
|
|
1438
|
+
),
|
|
1439
|
+
Stripped(
|
|
1440
|
+
f"""\
|
|
1441
|
+
def transform(
|
|
1442
|
+
{II}self,
|
|
1443
|
+
{II}that: Class
|
|
1444
|
+
) -> T:
|
|
1445
|
+
{I}\"\"\"Double-dispatch on :paramref:`that`.\"\"\"
|
|
1446
|
+
{I}return that.transform(self)"""
|
|
1447
|
+
),
|
|
1448
|
+
] # type: List[Stripped]
|
|
1449
|
+
|
|
1450
|
+
for cls in symbol_table.concrete_classes:
|
|
1451
|
+
transform_name = python_naming.method_name(Identifier(f"transform_{cls.name}"))
|
|
1452
|
+
|
|
1453
|
+
cls_name = python_naming.class_name(cls.name)
|
|
1454
|
+
|
|
1455
|
+
blocks.append(
|
|
1456
|
+
Stripped(
|
|
1457
|
+
f"""\
|
|
1458
|
+
def {transform_name}(
|
|
1459
|
+
{II}self,
|
|
1460
|
+
{II}that: {cls_name}
|
|
1461
|
+
) -> T:
|
|
1462
|
+
{I}\"\"\"Transform :paramref:`that`.\"\"\"
|
|
1463
|
+
{I}return self.default"""
|
|
1464
|
+
)
|
|
1465
|
+
)
|
|
1466
|
+
|
|
1467
|
+
writer = io.StringIO()
|
|
1468
|
+
writer.write(
|
|
1469
|
+
f"""\
|
|
1470
|
+
class TransformerWithDefault(AbstractTransformer[T]):
|
|
1471
|
+
{I}\"\"\"
|
|
1472
|
+
{I}Transform the instances of the model.
|
|
1473
|
+
|
|
1474
|
+
{I}If you do not override the transformation methods, they simply
|
|
1475
|
+
{I}return :py:attr:`.default`.
|
|
1476
|
+
{I}\"\"\"
|
|
1477
|
+
"""
|
|
1478
|
+
)
|
|
1479
|
+
|
|
1480
|
+
for i, block in enumerate(blocks):
|
|
1481
|
+
if i > 0:
|
|
1482
|
+
writer.write("\n\n")
|
|
1483
|
+
|
|
1484
|
+
writer.write(textwrap.indent(block, I))
|
|
1485
|
+
|
|
1486
|
+
return Stripped(writer.getvalue())
|
|
1487
|
+
|
|
1488
|
+
|
|
1489
|
+
def _generate_transformer_with_default_and_context(
|
|
1490
|
+
symbol_table: intermediate.SymbolTable,
|
|
1491
|
+
) -> Stripped:
|
|
1492
|
+
"""Generate the code for the transformer with default transformation and context."""
|
|
1493
|
+
blocks = [
|
|
1494
|
+
Stripped(
|
|
1495
|
+
"""\
|
|
1496
|
+
#: Default value which is returned if no override of the transformation
|
|
1497
|
+
default: T"""
|
|
1498
|
+
),
|
|
1499
|
+
Stripped(
|
|
1500
|
+
f"""\
|
|
1501
|
+
def __init__(self, default: T) -> None:
|
|
1502
|
+
{I}\"\"\"Initialize with the given :paramref:`default` value.\"\"\"
|
|
1503
|
+
{I}self.default = default"""
|
|
1504
|
+
),
|
|
1505
|
+
Stripped(
|
|
1506
|
+
f"""\
|
|
1507
|
+
def transform_with_context(
|
|
1508
|
+
{II}self,
|
|
1509
|
+
{II}that: Class,
|
|
1510
|
+
{II}context: ContextT
|
|
1511
|
+
) -> T:
|
|
1512
|
+
{I}\"\"\"Double-dispatch on :paramref:`that`.\"\"\"
|
|
1513
|
+
{I}return that.transform_with_context(self, context)"""
|
|
1514
|
+
),
|
|
1515
|
+
] # type: List[Stripped]
|
|
1516
|
+
|
|
1517
|
+
for cls in symbol_table.concrete_classes:
|
|
1518
|
+
transform_with_context_name = python_naming.method_name(
|
|
1519
|
+
Identifier(f"transform_{cls.name}_with_context")
|
|
1520
|
+
)
|
|
1521
|
+
|
|
1522
|
+
cls_name = python_naming.class_name(cls.name)
|
|
1523
|
+
|
|
1524
|
+
blocks.append(
|
|
1525
|
+
Stripped(
|
|
1526
|
+
f"""\
|
|
1527
|
+
def {transform_with_context_name}(
|
|
1528
|
+
{II}self,
|
|
1529
|
+
{II}that: {cls_name},
|
|
1530
|
+
{II}context: ContextT
|
|
1531
|
+
) -> T:
|
|
1532
|
+
{I}\"\"\"Transform :paramref:`that` in :paramref:`context`.\"\"\"
|
|
1533
|
+
{I}return self.default"""
|
|
1534
|
+
)
|
|
1535
|
+
)
|
|
1536
|
+
|
|
1537
|
+
writer = io.StringIO()
|
|
1538
|
+
writer.write(
|
|
1539
|
+
f"""\
|
|
1540
|
+
class TransformerWithDefaultAndContext(
|
|
1541
|
+
{II}AbstractTransformerWithContext[ContextT, T]
|
|
1542
|
+
):
|
|
1543
|
+
{I}\"\"\"
|
|
1544
|
+
{I}Transform the instances of the model in context.
|
|
1545
|
+
|
|
1546
|
+
{I}If you do not override the transformation methods, they simply
|
|
1547
|
+
{I}return :py:attr:`.default`.
|
|
1548
|
+
{I}\"\"\"
|
|
1549
|
+
"""
|
|
1550
|
+
)
|
|
1551
|
+
|
|
1552
|
+
for i, block in enumerate(blocks):
|
|
1553
|
+
if i > 0:
|
|
1554
|
+
writer.write("\n\n")
|
|
1555
|
+
|
|
1556
|
+
writer.write(textwrap.indent(block, I))
|
|
1557
|
+
|
|
1558
|
+
return Stripped(writer.getvalue())
|
|
1559
|
+
|
|
1560
|
+
|
|
1561
|
+
def _generate_docstring_for_meta_model(
|
|
1562
|
+
description: intermediate.DescriptionOfMetaModel,
|
|
1563
|
+
aas_module: python_common.QualifiedModuleName,
|
|
1564
|
+
) -> Tuple[Optional[Stripped], Optional[List[Error]]]:
|
|
1565
|
+
"""Generate the docstring for the given meta-model."""
|
|
1566
|
+
text, errors = python_description.generate_summary_remarks_constraints(
|
|
1567
|
+
description=description,
|
|
1568
|
+
context=python_description.Context(
|
|
1569
|
+
aas_module=aas_module, module=Identifier("types"), cls_or_enum=None
|
|
1570
|
+
),
|
|
1571
|
+
)
|
|
1572
|
+
|
|
1573
|
+
if errors is not None:
|
|
1574
|
+
return None, errors
|
|
1575
|
+
|
|
1576
|
+
assert text is not None
|
|
1577
|
+
|
|
1578
|
+
return python_description.docstring(text), None
|
|
1579
|
+
|
|
1580
|
+
|
|
1581
|
+
# fmt: off
|
|
1582
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
1583
|
+
@ensure(
|
|
1584
|
+
lambda result:
|
|
1585
|
+
not (result[0] is not None) or result[0].endswith('\n'),
|
|
1586
|
+
"Trailing newline mandatory for valid end-of-files"
|
|
1587
|
+
)
|
|
1588
|
+
# fmt: on
|
|
1589
|
+
def generate(
|
|
1590
|
+
symbol_table: VerifiedIntermediateSymbolTable,
|
|
1591
|
+
aas_module: python_common.QualifiedModuleName,
|
|
1592
|
+
spec_impls: specific_implementations.SpecificImplementations,
|
|
1593
|
+
) -> Tuple[Optional[str], Optional[List[Error]]]:
|
|
1594
|
+
"""
|
|
1595
|
+
Generate the Python code of the structures based on the symbol table.
|
|
1596
|
+
|
|
1597
|
+
The ``aas_module`` indicates the fully-qualified name of the base module.
|
|
1598
|
+
"""
|
|
1599
|
+
errors = [] # type: List[Error]
|
|
1600
|
+
|
|
1601
|
+
blocks = [] # type: List[Stripped]
|
|
1602
|
+
|
|
1603
|
+
if symbol_table.meta_model.description is not None:
|
|
1604
|
+
# fmt: off
|
|
1605
|
+
docstring, docstring_errors = (
|
|
1606
|
+
_generate_docstring_for_meta_model(
|
|
1607
|
+
description=symbol_table.meta_model.description,
|
|
1608
|
+
aas_module=aas_module
|
|
1609
|
+
)
|
|
1610
|
+
)
|
|
1611
|
+
# fmt: on
|
|
1612
|
+
|
|
1613
|
+
if docstring_errors is not None:
|
|
1614
|
+
errors.extend(docstring_errors)
|
|
1615
|
+
else:
|
|
1616
|
+
assert docstring is not None
|
|
1617
|
+
blocks.append(docstring)
|
|
1618
|
+
|
|
1619
|
+
blocks.extend(
|
|
1620
|
+
[
|
|
1621
|
+
python_common.WARNING,
|
|
1622
|
+
Stripped(
|
|
1623
|
+
f"""\
|
|
1624
|
+
import abc
|
|
1625
|
+
import enum
|
|
1626
|
+
from typing import (
|
|
1627
|
+
{I}Generic,
|
|
1628
|
+
{I}Iterator,
|
|
1629
|
+
{I}Optional,
|
|
1630
|
+
{I}TypeVar,
|
|
1631
|
+
{I}List
|
|
1632
|
+
)"""
|
|
1633
|
+
),
|
|
1634
|
+
Stripped(
|
|
1635
|
+
"""\
|
|
1636
|
+
T = TypeVar("T")
|
|
1637
|
+
ContextT = TypeVar("ContextT")"""
|
|
1638
|
+
),
|
|
1639
|
+
Stripped(
|
|
1640
|
+
f"""\
|
|
1641
|
+
class Class(abc.ABC):
|
|
1642
|
+
{I}\"\"\"Represent the most general class of an AAS model.\"\"\"
|
|
1643
|
+
{I}@abc.abstractmethod
|
|
1644
|
+
{I}def descend_once(self) -> Iterator["Class"]:
|
|
1645
|
+
{II}\"\"\"Iterate over all the instances referenced from this one.\"\"\"
|
|
1646
|
+
{II}raise NotImplementedError()
|
|
1647
|
+
|
|
1648
|
+
{I}@abc.abstractmethod
|
|
1649
|
+
{I}def descend(self) -> Iterator["Class"]:
|
|
1650
|
+
{II}\"\"\"Iterate recursively over all the instances referenced from this one.\"\"\"
|
|
1651
|
+
{II}raise NotImplementedError()
|
|
1652
|
+
|
|
1653
|
+
{I}@abc.abstractmethod
|
|
1654
|
+
{I}def accept(
|
|
1655
|
+
{III}self,
|
|
1656
|
+
{III}visitor: "AbstractVisitor"
|
|
1657
|
+
{I}) -> None:
|
|
1658
|
+
{II}\"\"\"
|
|
1659
|
+
{II}Dispatch the :paramref:`visitor` on this instance.
|
|
1660
|
+
|
|
1661
|
+
{II}:param visitor: to be dispatched
|
|
1662
|
+
{II}\"\"\"
|
|
1663
|
+
{II}raise NotImplementedError()
|
|
1664
|
+
|
|
1665
|
+
{I}@abc.abstractmethod
|
|
1666
|
+
{I}def accept_with_context(
|
|
1667
|
+
{III}self,
|
|
1668
|
+
{III}visitor: "AbstractVisitorWithContext[ContextT]",
|
|
1669
|
+
{III}context: ContextT
|
|
1670
|
+
{I}) -> None:
|
|
1671
|
+
{II}\"\"\"
|
|
1672
|
+
{II}Dispatch the :paramref:`visitor` on this instance with :paramref:`context`.
|
|
1673
|
+
|
|
1674
|
+
{II}:param visitor: to be dispatched
|
|
1675
|
+
{II}:param context: of the visitation
|
|
1676
|
+
{II}\"\"\"
|
|
1677
|
+
{II}raise NotImplementedError()
|
|
1678
|
+
|
|
1679
|
+
{I}@abc.abstractmethod
|
|
1680
|
+
{I}def transform(
|
|
1681
|
+
{III}self,
|
|
1682
|
+
{III}transformer: "AbstractTransformer[T]"
|
|
1683
|
+
{I}) -> T:
|
|
1684
|
+
{II}\"\"\"
|
|
1685
|
+
{II}Dispatch the :paramref:`transformer` on this instance.
|
|
1686
|
+
|
|
1687
|
+
{II}:param transformer: to be dispatched
|
|
1688
|
+
{II}:return: transformed self
|
|
1689
|
+
{II}\"\"\"
|
|
1690
|
+
{II}raise NotImplementedError()
|
|
1691
|
+
|
|
1692
|
+
{I}@abc.abstractmethod
|
|
1693
|
+
{I}def transform_with_context(
|
|
1694
|
+
{III}self,
|
|
1695
|
+
{III}transformer: "AbstractTransformerWithContext[ContextT, T]",
|
|
1696
|
+
{III}context: ContextT
|
|
1697
|
+
{I}) -> T:
|
|
1698
|
+
{II}\"\"\"
|
|
1699
|
+
{II}Dispatch the :paramref:`transformer` on this instance with :paramref:`context`.
|
|
1700
|
+
|
|
1701
|
+
{II}:param transformer: to be dispatched
|
|
1702
|
+
{II}:return: transformed self
|
|
1703
|
+
{II}\"\"\"
|
|
1704
|
+
{II}raise NotImplementedError()"""
|
|
1705
|
+
),
|
|
1706
|
+
Stripped(
|
|
1707
|
+
"""\
|
|
1708
|
+
# pylint: disable=redefined-builtin"""
|
|
1709
|
+
),
|
|
1710
|
+
]
|
|
1711
|
+
)
|
|
1712
|
+
|
|
1713
|
+
for our_type in symbol_table.our_types:
|
|
1714
|
+
error: Optional[Error]
|
|
1715
|
+
|
|
1716
|
+
if isinstance(our_type, intermediate.Enumeration):
|
|
1717
|
+
block, error = _generate_enum(enum=our_type, aas_module=aas_module)
|
|
1718
|
+
if error is None:
|
|
1719
|
+
assert block is not None
|
|
1720
|
+
blocks.append(block)
|
|
1721
|
+
continue
|
|
1722
|
+
|
|
1723
|
+
elif isinstance(our_type, intermediate.ConstrainedPrimitive):
|
|
1724
|
+
# NOTE (mristin, 2022-09-28):
|
|
1725
|
+
# We do not generate the constrained primitives as types. We only
|
|
1726
|
+
# consider them in the verification.
|
|
1727
|
+
continue
|
|
1728
|
+
|
|
1729
|
+
elif isinstance(
|
|
1730
|
+
our_type, (intermediate.AbstractClass, intermediate.ConcreteClass)
|
|
1731
|
+
):
|
|
1732
|
+
if our_type.is_implementation_specific:
|
|
1733
|
+
implementation_key = specific_implementations.ImplementationKey(
|
|
1734
|
+
f"Types/{our_type.name}.py"
|
|
1735
|
+
)
|
|
1736
|
+
|
|
1737
|
+
block = spec_impls.get(implementation_key, None)
|
|
1738
|
+
if block is None:
|
|
1739
|
+
error = Error(
|
|
1740
|
+
our_type.parsed.node,
|
|
1741
|
+
f"The implementation is missing "
|
|
1742
|
+
f"for the implementation-specific "
|
|
1743
|
+
f"class: {implementation_key}",
|
|
1744
|
+
)
|
|
1745
|
+
else:
|
|
1746
|
+
blocks.append(block)
|
|
1747
|
+
continue
|
|
1748
|
+
else:
|
|
1749
|
+
block, error = _generate_class(
|
|
1750
|
+
cls=our_type,
|
|
1751
|
+
spec_impls=spec_impls,
|
|
1752
|
+
aas_module=aas_module,
|
|
1753
|
+
symbol_table=symbol_table,
|
|
1754
|
+
)
|
|
1755
|
+
if error is None:
|
|
1756
|
+
assert block is not None
|
|
1757
|
+
blocks.append(block)
|
|
1758
|
+
continue
|
|
1759
|
+
else:
|
|
1760
|
+
assert_never(our_type)
|
|
1761
|
+
|
|
1762
|
+
assert error is not None
|
|
1763
|
+
errors.append(
|
|
1764
|
+
Error(
|
|
1765
|
+
our_type.parsed.node,
|
|
1766
|
+
f"Failed to generate the code for {our_type.name!r}",
|
|
1767
|
+
[error],
|
|
1768
|
+
)
|
|
1769
|
+
)
|
|
1770
|
+
|
|
1771
|
+
if len(errors) > 0:
|
|
1772
|
+
return None, errors
|
|
1773
|
+
|
|
1774
|
+
blocks.extend(
|
|
1775
|
+
[
|
|
1776
|
+
_generate_abstract_visitor(symbol_table=symbol_table),
|
|
1777
|
+
_generate_abstract_visitor_with_context(symbol_table=symbol_table),
|
|
1778
|
+
_generate_pass_through_visitor(symbol_table=symbol_table),
|
|
1779
|
+
_generate_pass_through_visitor_with_context(symbol_table=symbol_table),
|
|
1780
|
+
_generate_abstract_transformer(symbol_table=symbol_table),
|
|
1781
|
+
_generate_abstract_transformer_with_context(symbol_table=symbol_table),
|
|
1782
|
+
_generate_transformer_with_default(symbol_table=symbol_table),
|
|
1783
|
+
_generate_transformer_with_default_and_context(symbol_table=symbol_table),
|
|
1784
|
+
]
|
|
1785
|
+
)
|
|
1786
|
+
|
|
1787
|
+
blocks.append(python_common.WARNING)
|
|
1788
|
+
|
|
1789
|
+
out = io.StringIO()
|
|
1790
|
+
for i, block in enumerate(blocks):
|
|
1791
|
+
if i > 0:
|
|
1792
|
+
out.write("\n\n\n")
|
|
1793
|
+
|
|
1794
|
+
out.write(block)
|
|
1795
|
+
|
|
1796
|
+
out.write("\n")
|
|
1797
|
+
|
|
1798
|
+
return out.getvalue(), None
|
|
1799
|
+
|
|
1800
|
+
|
|
1801
|
+
# endregion
|