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,1525 @@
|
|
|
1
|
+
"""Generate the OPC UA Schema node set corresponding to the meta-model."""
|
|
2
|
+
import collections
|
|
3
|
+
import dataclasses
|
|
4
|
+
import enum
|
|
5
|
+
import io
|
|
6
|
+
import itertools
|
|
7
|
+
import re
|
|
8
|
+
import xml.dom.minidom
|
|
9
|
+
import xml.etree.ElementTree as ET
|
|
10
|
+
import xml.sax.saxutils
|
|
11
|
+
from typing import (
|
|
12
|
+
TextIO,
|
|
13
|
+
Tuple,
|
|
14
|
+
Optional,
|
|
15
|
+
List,
|
|
16
|
+
MutableMapping,
|
|
17
|
+
Mapping,
|
|
18
|
+
Union,
|
|
19
|
+
OrderedDict,
|
|
20
|
+
Iterable,
|
|
21
|
+
Set,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
from icontract import ensure, require
|
|
25
|
+
|
|
26
|
+
import aas_core_codegen.opcua
|
|
27
|
+
import aas_core_codegen.opcua.naming as opcua_naming
|
|
28
|
+
from aas_core_codegen import (
|
|
29
|
+
run,
|
|
30
|
+
intermediate,
|
|
31
|
+
specific_implementations,
|
|
32
|
+
)
|
|
33
|
+
from aas_core_codegen.common import (
|
|
34
|
+
Error,
|
|
35
|
+
assert_never,
|
|
36
|
+
Identifier,
|
|
37
|
+
IDENTIFIER_RE,
|
|
38
|
+
Stripped,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
assert aas_core_codegen.opcua.__doc__ == __doc__
|
|
42
|
+
|
|
43
|
+
_PRIMITIVE_MAP = {
|
|
44
|
+
intermediate.PrimitiveType.BOOL: "Boolean",
|
|
45
|
+
intermediate.PrimitiveType.INT: "Int64",
|
|
46
|
+
intermediate.PrimitiveType.FLOAT: "Double",
|
|
47
|
+
intermediate.PrimitiveType.STR: "String",
|
|
48
|
+
intermediate.PrimitiveType.BYTEARRAY: "ByteString",
|
|
49
|
+
}
|
|
50
|
+
assert all(literal in _PRIMITIVE_MAP for literal in intermediate.PrimitiveType)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class _IdentifierMachine:
|
|
54
|
+
"""
|
|
55
|
+
Produce stable identifiers for different nodes.
|
|
56
|
+
|
|
57
|
+
The Identifier Machine knows nothing about your scheme, so you have to come up
|
|
58
|
+
with your own.
|
|
59
|
+
|
|
60
|
+
It will try to be as stable as possible, *i.e.*, the identifiers for the names
|
|
61
|
+
should not change even if the order of :py:func:`obtain` is changed.
|
|
62
|
+
|
|
63
|
+
>>> machine = _IdentifierMachine()
|
|
64
|
+
>>> machine.obtain("something")
|
|
65
|
+
207137056
|
|
66
|
+
|
|
67
|
+
Obtaining an identifier is idem-potent:
|
|
68
|
+
|
|
69
|
+
>>> machine.obtain("something")
|
|
70
|
+
207137056
|
|
71
|
+
|
|
72
|
+
Another text gives you another identifier:
|
|
73
|
+
|
|
74
|
+
>>> machine.obtain("something_else")
|
|
75
|
+
165180381
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
def __init__(self) -> None:
|
|
79
|
+
self._identifier_map = dict() # type: MutableMapping[str, int]
|
|
80
|
+
self._taken_identifiers = set() # type: Set[int]
|
|
81
|
+
|
|
82
|
+
@staticmethod
|
|
83
|
+
def _hash(text: str) -> int:
|
|
84
|
+
"""
|
|
85
|
+
Compute the non-cryptographic hash of the given string.
|
|
86
|
+
|
|
87
|
+
We implement our own hash so that the implementation need not change across
|
|
88
|
+
different Python versions, in case they change the hash function.
|
|
89
|
+
|
|
90
|
+
>>> _IdentifierMachine._hash("something")
|
|
91
|
+
207137056
|
|
92
|
+
|
|
93
|
+
>>> _IdentifierMachine._hash("something_else")
|
|
94
|
+
165180381
|
|
95
|
+
|
|
96
|
+
>>> _IdentifierMachine._hash("")
|
|
97
|
+
7
|
|
98
|
+
"""
|
|
99
|
+
result = 7
|
|
100
|
+
for character in text:
|
|
101
|
+
result = (result * 31 + ord(character)) % 0x7FFFFFFF
|
|
102
|
+
|
|
103
|
+
return result
|
|
104
|
+
|
|
105
|
+
def obtain(self, text: str) -> int:
|
|
106
|
+
"""
|
|
107
|
+
Assign a slot for the text using hashing.
|
|
108
|
+
|
|
109
|
+
In most cases, we do not expect the resulting ID to change.
|
|
110
|
+
"""
|
|
111
|
+
identifier = self._identifier_map.get(text, None)
|
|
112
|
+
if identifier is not None:
|
|
113
|
+
return identifier
|
|
114
|
+
|
|
115
|
+
identifier = _IdentifierMachine._hash(text)
|
|
116
|
+
|
|
117
|
+
while identifier in self._taken_identifiers:
|
|
118
|
+
identifier += 1
|
|
119
|
+
|
|
120
|
+
self._taken_identifiers.add(identifier)
|
|
121
|
+
self._identifier_map[text] = identifier
|
|
122
|
+
|
|
123
|
+
return identifier
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _generate_aliases() -> ET.Element:
|
|
127
|
+
"""Generate the aliases including the primitive values."""
|
|
128
|
+
aliases = ET.Element("Aliases")
|
|
129
|
+
|
|
130
|
+
for name, i in (
|
|
131
|
+
("Boolean", 1),
|
|
132
|
+
("Int64", 8),
|
|
133
|
+
("Double", 11),
|
|
134
|
+
("String", 12),
|
|
135
|
+
("ByteString", 15),
|
|
136
|
+
("HasModellingRule", 37),
|
|
137
|
+
("HasTypeDefinition", 40),
|
|
138
|
+
("HasSubtype", 45),
|
|
139
|
+
("HasProperty", 46),
|
|
140
|
+
("HasComponent", 47),
|
|
141
|
+
("HasInterface", 17603),
|
|
142
|
+
):
|
|
143
|
+
alias = ET.Element("Alias", {"Alias": name})
|
|
144
|
+
alias.text = f"i={i}"
|
|
145
|
+
aliases.append(alias)
|
|
146
|
+
|
|
147
|
+
return aliases
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
@dataclasses.dataclass
|
|
151
|
+
class _IdentifiersForConstraints:
|
|
152
|
+
"""Map the references and object types for constraints to identifiers."""
|
|
153
|
+
|
|
154
|
+
constraint_id: int
|
|
155
|
+
constraint_identifier_id: int
|
|
156
|
+
constraint_text_id: int
|
|
157
|
+
has_constraint_id: int
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _generate_for_constraints_and_patterns(
|
|
161
|
+
identifiers_for_constraints: _IdentifiersForConstraints,
|
|
162
|
+
) -> List[ET.Element]:
|
|
163
|
+
"""Generate the object types and the references to represent constraints."""
|
|
164
|
+
return [
|
|
165
|
+
ET.fromstring(
|
|
166
|
+
f"""\
|
|
167
|
+
<UAObjectType
|
|
168
|
+
NodeId="ns=1;i={identifiers_for_constraints.constraint_id}"
|
|
169
|
+
BrowseName="1:Constraint"
|
|
170
|
+
>
|
|
171
|
+
<DisplayName>Constraint</DisplayName>
|
|
172
|
+
<References>
|
|
173
|
+
<Reference ReferenceType="HasSubtype" IsForward="false">i=58</Reference>
|
|
174
|
+
<Reference
|
|
175
|
+
ReferenceType="HasProperty"
|
|
176
|
+
>ns=1;i={identifiers_for_constraints.constraint_identifier_id}</Reference>
|
|
177
|
+
<Reference
|
|
178
|
+
ReferenceType="HasProperty"
|
|
179
|
+
>ns=1;i={identifiers_for_constraints.constraint_text_id}</Reference>
|
|
180
|
+
</References>
|
|
181
|
+
</UAObjectType>"""
|
|
182
|
+
),
|
|
183
|
+
ET.fromstring(
|
|
184
|
+
f"""\
|
|
185
|
+
<UAVariable
|
|
186
|
+
NodeId="ns=1;i={identifiers_for_constraints.constraint_identifier_id}"
|
|
187
|
+
BrowseName="1:identifier"
|
|
188
|
+
ParentNodeId="ns=1;i={identifiers_for_constraints.constraint_id}"
|
|
189
|
+
DataType="String"
|
|
190
|
+
>
|
|
191
|
+
<DisplayName>identifier</DisplayName>
|
|
192
|
+
<References>
|
|
193
|
+
<Reference ReferenceType="HasTypeDefinition">i=68</Reference>
|
|
194
|
+
<Reference ReferenceType="HasModellingRule">i=80</Reference>
|
|
195
|
+
</References>
|
|
196
|
+
</UAVariable>"""
|
|
197
|
+
),
|
|
198
|
+
ET.fromstring(
|
|
199
|
+
f"""\
|
|
200
|
+
<UAVariable
|
|
201
|
+
NodeId="ns=1;i={identifiers_for_constraints.constraint_text_id}"
|
|
202
|
+
BrowseName="1:text"
|
|
203
|
+
ParentNodeId="ns=1;i={identifiers_for_constraints.constraint_id}"
|
|
204
|
+
DataType="String"
|
|
205
|
+
>
|
|
206
|
+
<DisplayName>text</DisplayName>
|
|
207
|
+
<References>
|
|
208
|
+
<Reference ReferenceType="HasTypeDefinition">i=68</Reference>
|
|
209
|
+
<Reference ReferenceType="HasModellingRule">i=78</Reference>
|
|
210
|
+
</References>
|
|
211
|
+
</UAVariable>"""
|
|
212
|
+
),
|
|
213
|
+
ET.fromstring(
|
|
214
|
+
f"""\
|
|
215
|
+
<UAReferenceType
|
|
216
|
+
NodeId="ns=1;i={identifiers_for_constraints.has_constraint_id}"
|
|
217
|
+
BrowseName="1:HasConstraint"
|
|
218
|
+
>
|
|
219
|
+
<DisplayName>HasConstraint</DisplayName>
|
|
220
|
+
<References>
|
|
221
|
+
<Reference ReferenceType="HasSubtype" IsForward="false">i=32</Reference>
|
|
222
|
+
</References>
|
|
223
|
+
<InverseName>Constrains</InverseName>
|
|
224
|
+
</UAReferenceType>"""
|
|
225
|
+
),
|
|
226
|
+
]
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
#: All the classes whose instances have an ``i=...`` in the node set.
|
|
230
|
+
_OpcUaIdentifiable = Union[
|
|
231
|
+
intermediate.Enumeration,
|
|
232
|
+
intermediate.ConstrainedPrimitive,
|
|
233
|
+
intermediate.Class,
|
|
234
|
+
intermediate.Interface,
|
|
235
|
+
intermediate.Property,
|
|
236
|
+
intermediate.Invariant,
|
|
237
|
+
]
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def _reference(
|
|
241
|
+
reference_type: str, target: str, is_forward: Optional[bool] = None
|
|
242
|
+
) -> ET.Element:
|
|
243
|
+
"""Create a ``<Reference>`` element."""
|
|
244
|
+
attrib = collections.OrderedDict([("ReferenceType", reference_type)])
|
|
245
|
+
if is_forward is not None:
|
|
246
|
+
attrib["IsForward"] = "true" if is_forward else "false"
|
|
247
|
+
|
|
248
|
+
reference_el = ET.Element("Reference", attrib)
|
|
249
|
+
reference_el.text = target
|
|
250
|
+
|
|
251
|
+
return reference_el
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def _localized_text(text: str) -> ET.Element:
|
|
255
|
+
"""Create a nested ``<uax:LocalizedText>``."""
|
|
256
|
+
localized_text_el = ET.Element("uax:LocalizedText")
|
|
257
|
+
|
|
258
|
+
text_el = ET.Element("uax:Text")
|
|
259
|
+
localized_text_el.append(text_el)
|
|
260
|
+
|
|
261
|
+
text_el.text = text
|
|
262
|
+
|
|
263
|
+
return localized_text_el
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def _generate_for_enum(
|
|
267
|
+
enumeration: intermediate.Enumeration,
|
|
268
|
+
identifier_map: Mapping[_OpcUaIdentifiable, int],
|
|
269
|
+
identifier_machine: _IdentifierMachine,
|
|
270
|
+
name_prefix: Identifier,
|
|
271
|
+
) -> List[ET.Element]:
|
|
272
|
+
"""Define the enumeration as OPC UA EnumStrings."""
|
|
273
|
+
enum_name = opcua_naming.enum_name(enumeration.name, name_prefix)
|
|
274
|
+
|
|
275
|
+
result = [] # type: List[ET.Element]
|
|
276
|
+
|
|
277
|
+
comment_starts = ET.Comment(f"{enum_name} starts.")
|
|
278
|
+
comment_starts.tail = "\n"
|
|
279
|
+
result.append(comment_starts)
|
|
280
|
+
|
|
281
|
+
enum_id = identifier_map[enumeration]
|
|
282
|
+
|
|
283
|
+
def generate_data_type() -> ET.Element:
|
|
284
|
+
"""Generate the element defining the data type."""
|
|
285
|
+
data_type_el = ET.Element(
|
|
286
|
+
"UADataType",
|
|
287
|
+
collections.OrderedDict(
|
|
288
|
+
[("NodeId", f"ns=1;i={enum_id}"), ("BrowseName", f"1:{enum_name}")]
|
|
289
|
+
),
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
display_name_el = ET.Element("DisplayName")
|
|
293
|
+
data_type_el.append(display_name_el)
|
|
294
|
+
display_name_el.text = enum_name
|
|
295
|
+
|
|
296
|
+
references_el = ET.Element("References")
|
|
297
|
+
data_type_el.append(references_el)
|
|
298
|
+
references_el.append(
|
|
299
|
+
_reference(reference_type="HasSubtype", target="i=29", is_forward=False)
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
definition_el = ET.Element("Definition", {"Name": f"1:{enum_name}"})
|
|
303
|
+
data_type_el.append(definition_el)
|
|
304
|
+
|
|
305
|
+
for i, literal in enumerate(enumeration.literals):
|
|
306
|
+
field = ET.Element(
|
|
307
|
+
"Field",
|
|
308
|
+
collections.OrderedDict(
|
|
309
|
+
[
|
|
310
|
+
("Name", opcua_naming.enum_literal_name(literal.name)),
|
|
311
|
+
("Value", str(i)),
|
|
312
|
+
]
|
|
313
|
+
),
|
|
314
|
+
)
|
|
315
|
+
definition_el.append(field)
|
|
316
|
+
|
|
317
|
+
return data_type_el
|
|
318
|
+
|
|
319
|
+
result.append(generate_data_type())
|
|
320
|
+
|
|
321
|
+
def generate_enum_strings() -> ET.Element:
|
|
322
|
+
"""Generate the EnumString for the enumeration."""
|
|
323
|
+
variable_id = identifier_machine.obtain(f"{enumeration.name}:variable")
|
|
324
|
+
|
|
325
|
+
variable_el = ET.Element(
|
|
326
|
+
"UAVariable",
|
|
327
|
+
collections.OrderedDict(
|
|
328
|
+
[
|
|
329
|
+
("DataType", "LocalizedText"),
|
|
330
|
+
("ValueRank", "1"),
|
|
331
|
+
("NodeId", f"ns=1;i={variable_id}"),
|
|
332
|
+
("ArrayDimensions", str(len(enumeration.literals))),
|
|
333
|
+
("BrowseName", "EnumStrings"),
|
|
334
|
+
("ParentNodeId", f"ns=1;i={enum_id}"),
|
|
335
|
+
]
|
|
336
|
+
),
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
display_name_el = ET.Element("DisplayName")
|
|
340
|
+
variable_el.append(display_name_el)
|
|
341
|
+
display_name_el.text = "EnumStrings"
|
|
342
|
+
|
|
343
|
+
references_el = ET.Element("References")
|
|
344
|
+
variable_el.append(references_el)
|
|
345
|
+
references_el.append(
|
|
346
|
+
_reference("HasProperty", target=f"ns=1;i={enum_id}", is_forward=False)
|
|
347
|
+
)
|
|
348
|
+
references_el.append(_reference("HasTypeDefinition", target="i=68"))
|
|
349
|
+
references_el.append(_reference("HasModellingRule", target="i=78"))
|
|
350
|
+
|
|
351
|
+
value_el = ET.Element("Value")
|
|
352
|
+
variable_el.append(value_el)
|
|
353
|
+
|
|
354
|
+
list_of_localized_text_el = ET.Element("uax:ListOfLocalizedText")
|
|
355
|
+
value_el.append(list_of_localized_text_el)
|
|
356
|
+
|
|
357
|
+
for literal in enumeration.literals:
|
|
358
|
+
list_of_localized_text_el.append(_localized_text(literal.value))
|
|
359
|
+
|
|
360
|
+
return variable_el
|
|
361
|
+
|
|
362
|
+
result.append(generate_enum_strings())
|
|
363
|
+
|
|
364
|
+
comment_ends = ET.Comment(f"{enum_name} ends.")
|
|
365
|
+
comment_ends.tail = "\n"
|
|
366
|
+
result.append(comment_ends)
|
|
367
|
+
|
|
368
|
+
return result
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
_CONSTRAINT_ID_PREFIX_RE = re.compile(r"Constraint \s*(?P<identifier>[^:]+)\s*:")
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
def _extract_constraint_identifier(description: str) -> Optional[str]:
|
|
375
|
+
"""
|
|
376
|
+
Try to extract the constraint identifier from the invariant description.
|
|
377
|
+
|
|
378
|
+
>>> _extract_constraint_identifier("Constraint 1: bla bla bla")
|
|
379
|
+
'1'
|
|
380
|
+
|
|
381
|
+
>>> _extract_constraint_identifier("Constraint 1 : bla bla bla")
|
|
382
|
+
'1'
|
|
383
|
+
|
|
384
|
+
>>> _extract_constraint_identifier("Bla bla bla")
|
|
385
|
+
|
|
386
|
+
>>> _extract_constraint_identifier("Constraint 2: Name with at most 9 characters.")
|
|
387
|
+
'2'
|
|
388
|
+
"""
|
|
389
|
+
match = _CONSTRAINT_ID_PREFIX_RE.match(description)
|
|
390
|
+
|
|
391
|
+
if match is None:
|
|
392
|
+
return None
|
|
393
|
+
|
|
394
|
+
return match.group("identifier").strip()
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
def _value_string(text: str) -> ET.Element:
|
|
398
|
+
"""Generate an ``<Value>`` element with the embedded string element."""
|
|
399
|
+
value_el = ET.Element("Value")
|
|
400
|
+
|
|
401
|
+
uax_string_el = ET.Element("uax:String")
|
|
402
|
+
value_el.append(uax_string_el)
|
|
403
|
+
uax_string_el.text = text
|
|
404
|
+
|
|
405
|
+
return value_el
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
def _generate_for_invariant(
|
|
409
|
+
invariant: intermediate.Invariant,
|
|
410
|
+
identifier_map: Mapping[_OpcUaIdentifiable, int],
|
|
411
|
+
identifiers_for_constraints: _IdentifiersForConstraints,
|
|
412
|
+
identifier_machine: _IdentifierMachine,
|
|
413
|
+
) -> List[ET.Element]:
|
|
414
|
+
"""Generate the constraint object for the invariant."""
|
|
415
|
+
assert (
|
|
416
|
+
invariant in identifier_map
|
|
417
|
+
), f"Invariant {invariant.description!r} missing in identifier map"
|
|
418
|
+
|
|
419
|
+
invariant_id = identifier_map[invariant]
|
|
420
|
+
|
|
421
|
+
constraint_identifier = _extract_constraint_identifier(invariant.description)
|
|
422
|
+
|
|
423
|
+
if constraint_identifier is None:
|
|
424
|
+
browse_name = f"ConstraintUnlabeled{invariant_id}"
|
|
425
|
+
else:
|
|
426
|
+
browse_name = opcua_naming.constraint_browser_name(
|
|
427
|
+
Stripped(constraint_identifier)
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
object_el = ET.fromstring(
|
|
431
|
+
f"""\
|
|
432
|
+
<UAObject
|
|
433
|
+
NodeId="ns=1;i={invariant_id}"
|
|
434
|
+
BrowseName="1:{browse_name}"
|
|
435
|
+
ParentNodeId="i=85"
|
|
436
|
+
>
|
|
437
|
+
<DisplayName>{browse_name}</DisplayName>
|
|
438
|
+
<References>
|
|
439
|
+
<Reference ReferenceType="Organizes" IsForward="false">i=85</Reference>
|
|
440
|
+
<Reference
|
|
441
|
+
ReferenceType="HasTypeDefinition"
|
|
442
|
+
>ns=1;i={identifiers_for_constraints.constraint_id}</Reference>
|
|
443
|
+
</References>
|
|
444
|
+
</UAObject>"""
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
text_id = identifier_machine.obtain(f"{invariant_id}:text")
|
|
448
|
+
|
|
449
|
+
text_variable_el = ET.fromstring(
|
|
450
|
+
f"""\
|
|
451
|
+
<UAVariable
|
|
452
|
+
DataType="String"
|
|
453
|
+
NodeId="ns=1;i={text_id}"
|
|
454
|
+
BrowseName="1:text"
|
|
455
|
+
ParentNodeId="ns=1;i={invariant_id}"
|
|
456
|
+
>
|
|
457
|
+
<DisplayName>text</DisplayName>
|
|
458
|
+
<References>
|
|
459
|
+
<Reference
|
|
460
|
+
ReferenceType="HasProperty"
|
|
461
|
+
IsForward="false"
|
|
462
|
+
>ns=1;i={invariant_id}</Reference>
|
|
463
|
+
<Reference ReferenceType="HasTypeDefinition">i=63</Reference>
|
|
464
|
+
</References>
|
|
465
|
+
</UAVariable>"""
|
|
466
|
+
)
|
|
467
|
+
|
|
468
|
+
# NOTE (mristin):
|
|
469
|
+
# We have to create the ``<Value>`` ourselves as we use a namespace alias and
|
|
470
|
+
# the ElementTree can not parse the namespace aliases from string.
|
|
471
|
+
text_variable_el.append(_value_string(invariant.description))
|
|
472
|
+
|
|
473
|
+
result = [object_el, text_variable_el]
|
|
474
|
+
|
|
475
|
+
if constraint_identifier is not None:
|
|
476
|
+
identifier_id = identifier_machine.obtain(f"{invariant_id}:identifier")
|
|
477
|
+
identifier_variable_el = ET.fromstring(
|
|
478
|
+
f"""\
|
|
479
|
+
<UAVariable
|
|
480
|
+
DataType="String"
|
|
481
|
+
NodeId="ns=1;i={identifier_id}"
|
|
482
|
+
BrowseName="1:identifier"
|
|
483
|
+
ParentNodeId="ns=1;i={invariant_id}"
|
|
484
|
+
>
|
|
485
|
+
<DisplayName>identifier</DisplayName>
|
|
486
|
+
<References>
|
|
487
|
+
<Reference
|
|
488
|
+
ReferenceType="HasProperty"
|
|
489
|
+
IsForward="false"
|
|
490
|
+
>ns=1;i={invariant_id}</Reference>
|
|
491
|
+
<Reference ReferenceType="HasTypeDefinition">i=63</Reference>
|
|
492
|
+
</References>
|
|
493
|
+
</UAVariable>"""
|
|
494
|
+
)
|
|
495
|
+
|
|
496
|
+
# NOTE (mristin):
|
|
497
|
+
# We have to create the ``<Value>`` ourselves as we use a namespace alias and
|
|
498
|
+
# the ElementTree can not parse the namespace aliases from string.
|
|
499
|
+
identifier_variable_el.append(_value_string(constraint_identifier))
|
|
500
|
+
|
|
501
|
+
result.append(identifier_variable_el)
|
|
502
|
+
|
|
503
|
+
return result
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
def _generate_for_constrained_primitive(
|
|
507
|
+
constrained_primitive: intermediate.ConstrainedPrimitive,
|
|
508
|
+
identifier_map: Mapping[_OpcUaIdentifiable, int],
|
|
509
|
+
identifiers_for_constraints: _IdentifiersForConstraints,
|
|
510
|
+
name_prefix: Identifier,
|
|
511
|
+
) -> ET.Element:
|
|
512
|
+
"""Define the constrained primitive and link it with constraints."""
|
|
513
|
+
constrained_primitive_name = opcua_naming.constrained_primitive_name(
|
|
514
|
+
constrained_primitive.name, prefix=name_prefix
|
|
515
|
+
)
|
|
516
|
+
constrained_primitive_id = identifier_map[constrained_primitive]
|
|
517
|
+
|
|
518
|
+
root = ET.fromstring(
|
|
519
|
+
f"""\
|
|
520
|
+
<UADataType
|
|
521
|
+
NodeId="ns=1;i={constrained_primitive_id}"
|
|
522
|
+
BrowseName="1:{constrained_primitive_name}"
|
|
523
|
+
>
|
|
524
|
+
<DisplayName>{constrained_primitive_name}</DisplayName>
|
|
525
|
+
<References>
|
|
526
|
+
<Reference
|
|
527
|
+
ReferenceType="HasSubtype"
|
|
528
|
+
IsForward="false"
|
|
529
|
+
>{_PRIMITIVE_MAP[constrained_primitive.constrainee]}</Reference>
|
|
530
|
+
</References>
|
|
531
|
+
</UADataType>"""
|
|
532
|
+
)
|
|
533
|
+
|
|
534
|
+
references_el = root.find("References")
|
|
535
|
+
assert references_el is not None, "Expected <References> in the node"
|
|
536
|
+
|
|
537
|
+
for invariant in constrained_primitive.invariants:
|
|
538
|
+
# NOTE (mristin):
|
|
539
|
+
# We do not model inheritance between the constrained primitives as this
|
|
540
|
+
# is not possible in OPC UA. Hence, we define all the constraints for each
|
|
541
|
+
# constrained primitive. This causes a lot of repetition, but we found no other
|
|
542
|
+
# way around it.
|
|
543
|
+
|
|
544
|
+
invariant_id = identifier_map[invariant]
|
|
545
|
+
|
|
546
|
+
references_el.append(
|
|
547
|
+
ET.fromstring(
|
|
548
|
+
f"""\
|
|
549
|
+
<Reference
|
|
550
|
+
ReferenceType="ns=1;i={identifiers_for_constraints.has_constraint_id}"
|
|
551
|
+
>ns=1;i={invariant_id}</Reference>"""
|
|
552
|
+
)
|
|
553
|
+
)
|
|
554
|
+
|
|
555
|
+
return root
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
class _PropertyReferenceType(enum.Enum):
|
|
559
|
+
PROPERTY = 0
|
|
560
|
+
COMPONENT = 1
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
def _determine_property_reference_type(
|
|
564
|
+
prop: intermediate.Property,
|
|
565
|
+
) -> _PropertyReferenceType:
|
|
566
|
+
"""
|
|
567
|
+
Determine how to map the given property.
|
|
568
|
+
|
|
569
|
+
In OPC UA, we distinguish between properties — attributes with simple data types or
|
|
570
|
+
arrays of simple data types — and components — references to instances
|
|
571
|
+
or aggregations of instances.
|
|
572
|
+
"""
|
|
573
|
+
type_anno = intermediate.beneath_optional(prop.type_annotation)
|
|
574
|
+
|
|
575
|
+
if (intermediate.try_primitive_type(type_anno) is not None) or (
|
|
576
|
+
isinstance(type_anno, intermediate.ListTypeAnnotation)
|
|
577
|
+
and intermediate.try_primitive_type(type_anno.items) is not None
|
|
578
|
+
):
|
|
579
|
+
return _PropertyReferenceType.PROPERTY
|
|
580
|
+
|
|
581
|
+
return _PropertyReferenceType.COMPONENT
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
def _try_primitive_type(
|
|
585
|
+
type_annotation: intermediate.TypeAnnotationUnion,
|
|
586
|
+
) -> Optional[intermediate.PrimitiveType]:
|
|
587
|
+
"""
|
|
588
|
+
Inspect the type annotation and determine the underlying primitive type, if any.
|
|
589
|
+
|
|
590
|
+
The primitive type can either be in the annotation itself, beneath an optional
|
|
591
|
+
or beneath a list.
|
|
592
|
+
|
|
593
|
+
This is different to :py:func:`intermediate.try_primitive_typ` since this function
|
|
594
|
+
considers lists as well. This is because OPC UA does not distinguish between
|
|
595
|
+
scalars and arrays when it comes to primitive types.
|
|
596
|
+
"""
|
|
597
|
+
type_anno = intermediate.beneath_optional(type_annotation)
|
|
598
|
+
|
|
599
|
+
# NOTE (mristin):
|
|
600
|
+
# We make sure that we do not use the variable unintentionally.
|
|
601
|
+
del type_annotation
|
|
602
|
+
|
|
603
|
+
if isinstance(type_anno, intermediate.PrimitiveTypeAnnotation):
|
|
604
|
+
return type_anno.a_type
|
|
605
|
+
|
|
606
|
+
elif isinstance(type_anno, intermediate.OurTypeAnnotation) and isinstance(
|
|
607
|
+
type_anno.our_type, intermediate.ConstrainedPrimitive
|
|
608
|
+
):
|
|
609
|
+
return type_anno.our_type.constrainee
|
|
610
|
+
|
|
611
|
+
elif isinstance(type_anno, intermediate.ListTypeAnnotation) and isinstance(
|
|
612
|
+
type_anno.items, intermediate.PrimitiveTypeAnnotation
|
|
613
|
+
):
|
|
614
|
+
return type_anno.items.a_type
|
|
615
|
+
|
|
616
|
+
else:
|
|
617
|
+
return None
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
def _generate_references_for_properties(
|
|
621
|
+
properties: Iterable[intermediate.Property],
|
|
622
|
+
identifier_map: Mapping[_OpcUaIdentifiable, int],
|
|
623
|
+
) -> List[ET.Element]:
|
|
624
|
+
"""
|
|
625
|
+
Generate the ``<Reference>`` entries for the given properties.
|
|
626
|
+
|
|
627
|
+
``prop_to_id`` maps each property to an OPC UA identifier.
|
|
628
|
+
"""
|
|
629
|
+
result = [] # type: List[ET.Element]
|
|
630
|
+
|
|
631
|
+
for prop in properties:
|
|
632
|
+
prop_id = identifier_map[prop]
|
|
633
|
+
|
|
634
|
+
property_reference_type = _determine_property_reference_type(prop)
|
|
635
|
+
if property_reference_type is _PropertyReferenceType.PROPERTY:
|
|
636
|
+
result.append(_reference("HasProperty", f"ns=1;i={prop_id}"))
|
|
637
|
+
elif property_reference_type is _PropertyReferenceType.COMPONENT:
|
|
638
|
+
result.append(_reference("HasComponent", f"ns=1;i={prop_id}"))
|
|
639
|
+
else:
|
|
640
|
+
assert_never(property_reference_type)
|
|
641
|
+
|
|
642
|
+
return result
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
@ensure(lambda result: result.tag in ("UAVariable", "UAObject"))
|
|
646
|
+
def _generate_for_property(
|
|
647
|
+
prop: intermediate.Property,
|
|
648
|
+
prop_id: int,
|
|
649
|
+
parent_id: int,
|
|
650
|
+
identifier_map: Mapping[_OpcUaIdentifiable, int],
|
|
651
|
+
) -> ET.Element:
|
|
652
|
+
"""Generate the variable element corresponding to the property."""
|
|
653
|
+
prop_name = opcua_naming.property_name(prop.name)
|
|
654
|
+
|
|
655
|
+
root = ET.Element(
|
|
656
|
+
"",
|
|
657
|
+
attrib=collections.OrderedDict(
|
|
658
|
+
[
|
|
659
|
+
("NodeId", f"ns=1;i={prop_id}"),
|
|
660
|
+
("BrowseName", f"1:{prop_name}"),
|
|
661
|
+
("ParentNodeId", f"ns=1;i={parent_id}"),
|
|
662
|
+
]
|
|
663
|
+
),
|
|
664
|
+
)
|
|
665
|
+
|
|
666
|
+
display_name_el = ET.Element("DisplayName")
|
|
667
|
+
root.append(display_name_el)
|
|
668
|
+
display_name_el.text = prop_name
|
|
669
|
+
|
|
670
|
+
if isinstance(prop.type_annotation, intermediate.OptionalTypeAnnotation):
|
|
671
|
+
type_anno = prop.type_annotation.value
|
|
672
|
+
else:
|
|
673
|
+
type_anno = prop.type_annotation
|
|
674
|
+
|
|
675
|
+
if isinstance(type_anno, intermediate.OptionalTypeAnnotation):
|
|
676
|
+
raise AssertionError(
|
|
677
|
+
"NOTE (mristin): We do not handle optional optionals, but you "
|
|
678
|
+
f"specified type annotation {prop.type_annotation} for the property "
|
|
679
|
+
f"{prop.name!r}."
|
|
680
|
+
)
|
|
681
|
+
|
|
682
|
+
if isinstance(type_anno, intermediate.ListTypeAnnotation):
|
|
683
|
+
type_anno = type_anno.items
|
|
684
|
+
|
|
685
|
+
elif isinstance(
|
|
686
|
+
type_anno,
|
|
687
|
+
(intermediate.PrimitiveTypeAnnotation, intermediate.OurTypeAnnotation),
|
|
688
|
+
):
|
|
689
|
+
pass
|
|
690
|
+
|
|
691
|
+
else:
|
|
692
|
+
assert_never(prop.type_annotation)
|
|
693
|
+
|
|
694
|
+
if not isinstance(
|
|
695
|
+
type_anno,
|
|
696
|
+
(intermediate.PrimitiveTypeAnnotation, intermediate.OurTypeAnnotation),
|
|
697
|
+
):
|
|
698
|
+
raise AssertionError(
|
|
699
|
+
f"NOTE (mristin): We only implemented optional and mandatory lists of "
|
|
700
|
+
f"primitives and lists of model instances, but you have "
|
|
701
|
+
f"a property {prop.name} with type: {prop.type_annotation}. "
|
|
702
|
+
f"Please contact the developers if you need this feature."
|
|
703
|
+
)
|
|
704
|
+
|
|
705
|
+
primitive_type = _try_primitive_type(type_anno)
|
|
706
|
+
|
|
707
|
+
is_list = isinstance(
|
|
708
|
+
intermediate.beneath_optional(prop.type_annotation),
|
|
709
|
+
intermediate.ListTypeAnnotation,
|
|
710
|
+
)
|
|
711
|
+
is_optional = isinstance(prop.type_annotation, intermediate.OptionalTypeAnnotation)
|
|
712
|
+
|
|
713
|
+
references_el = ET.Element("References")
|
|
714
|
+
if primitive_type is not None:
|
|
715
|
+
if is_optional:
|
|
716
|
+
# NOTE (mristin):
|
|
717
|
+
# This corresponds to ``Optional``.
|
|
718
|
+
references_el.append(_reference("HasModellingRule", target="i=80"))
|
|
719
|
+
else:
|
|
720
|
+
# NOTE (mristin):
|
|
721
|
+
# This corresponds to ``Mandatory``.
|
|
722
|
+
references_el.append(_reference("HasModellingRule", target="i=78"))
|
|
723
|
+
else:
|
|
724
|
+
if is_list:
|
|
725
|
+
if is_optional:
|
|
726
|
+
# NOTE (mristin):
|
|
727
|
+
# This corresponds to ``OptionalPlaceholder``.
|
|
728
|
+
references_el.append(_reference("HasModellingRule", target="i=11508"))
|
|
729
|
+
else:
|
|
730
|
+
# NOTE (mristin):
|
|
731
|
+
# This corresponds to ``MandatoryPlaceholder``.
|
|
732
|
+
references_el.append(_reference("HasModellingRule", target="i=11510"))
|
|
733
|
+
else:
|
|
734
|
+
if is_optional:
|
|
735
|
+
# NOTE (mristin):
|
|
736
|
+
# This corresponds to ``Optional``.
|
|
737
|
+
references_el.append(_reference("HasModellingRule", target="i=80"))
|
|
738
|
+
else:
|
|
739
|
+
# NOTE (mristin):
|
|
740
|
+
# This corresponds to ``Mandatory``.
|
|
741
|
+
references_el.append(_reference("HasModellingRule", target="i=78"))
|
|
742
|
+
|
|
743
|
+
if primitive_type is not None:
|
|
744
|
+
if isinstance(type_anno, intermediate.PrimitiveTypeAnnotation):
|
|
745
|
+
root.attrib["DataType"] = _PRIMITIVE_MAP[primitive_type]
|
|
746
|
+
|
|
747
|
+
elif isinstance(type_anno, intermediate.OurTypeAnnotation) and isinstance(
|
|
748
|
+
type_anno.our_type, intermediate.ConstrainedPrimitive
|
|
749
|
+
):
|
|
750
|
+
root.attrib["DataType"] = f"ns=1;i={identifier_map[type_anno.our_type]}"
|
|
751
|
+
|
|
752
|
+
else:
|
|
753
|
+
raise AssertionError(
|
|
754
|
+
f"Unexpected primitive type in the property {prop.name!r} with "
|
|
755
|
+
f"type annotation {prop.type_annotation} where the type annotation "
|
|
756
|
+
f"beneath any Optional or List was: {type_anno}"
|
|
757
|
+
)
|
|
758
|
+
|
|
759
|
+
references_el.append(_reference("HasTypeDefinition", target="i=68"))
|
|
760
|
+
|
|
761
|
+
if is_list:
|
|
762
|
+
root.attrib["ValueRank"] = "1"
|
|
763
|
+
|
|
764
|
+
root.tag = "UAVariable"
|
|
765
|
+
else:
|
|
766
|
+
if isinstance(type_anno, intermediate.PrimitiveTypeAnnotation):
|
|
767
|
+
raise AssertionError(
|
|
768
|
+
"The case of the primitive type should have been handled before."
|
|
769
|
+
)
|
|
770
|
+
elif isinstance(type_anno, intermediate.OurTypeAnnotation):
|
|
771
|
+
if isinstance(type_anno.our_type, intermediate.Enumeration):
|
|
772
|
+
root.tag = "UAVariable"
|
|
773
|
+
|
|
774
|
+
enum_id = identifier_map[type_anno.our_type]
|
|
775
|
+
|
|
776
|
+
root.attrib["DataType"] = f"ns=1;i={enum_id}"
|
|
777
|
+
|
|
778
|
+
references_el.append(_reference("HasTypeDefinition", target="i=62"))
|
|
779
|
+
|
|
780
|
+
elif isinstance(type_anno.our_type, intermediate.ConstrainedPrimitive):
|
|
781
|
+
raise AssertionError(
|
|
782
|
+
"The case of the primitive type should have been handled before."
|
|
783
|
+
)
|
|
784
|
+
|
|
785
|
+
elif isinstance(
|
|
786
|
+
type_anno.our_type,
|
|
787
|
+
(intermediate.AbstractClass, intermediate.ConcreteClass),
|
|
788
|
+
):
|
|
789
|
+
root.tag = "UAObject"
|
|
790
|
+
|
|
791
|
+
if type_anno.our_type.interface is not None:
|
|
792
|
+
# NOTE (mristin):
|
|
793
|
+
# We specify the type as ``BaseObjectType`` since multiple
|
|
794
|
+
# inheritance is not possible.
|
|
795
|
+
references_el.append(_reference("HasTypeDefinition", target="i=58"))
|
|
796
|
+
|
|
797
|
+
interface_id = identifier_map[type_anno.our_type.interface]
|
|
798
|
+
references_el.append(
|
|
799
|
+
_reference("HasInterface", target=f"ns=1;i={interface_id}")
|
|
800
|
+
)
|
|
801
|
+
|
|
802
|
+
for ancestor_cls in type_anno.our_type.ancestors:
|
|
803
|
+
assert ancestor_cls.interface is not None
|
|
804
|
+
|
|
805
|
+
ancestor_id = identifier_map[ancestor_cls.interface]
|
|
806
|
+
references_el.append(
|
|
807
|
+
_reference("HasInterface", target=f"ns=1;i={ancestor_id}")
|
|
808
|
+
)
|
|
809
|
+
|
|
810
|
+
references_el.extend(
|
|
811
|
+
_generate_references_for_properties(
|
|
812
|
+
# NOTE (mristin):
|
|
813
|
+
# We reference *all* the properties of the object since
|
|
814
|
+
# the type definition is set to ``BaseObjectType``, but
|
|
815
|
+
# needs to satisfy all the interfaces.
|
|
816
|
+
properties=type_anno.our_type.properties,
|
|
817
|
+
identifier_map=identifier_map,
|
|
818
|
+
)
|
|
819
|
+
)
|
|
820
|
+
|
|
821
|
+
else:
|
|
822
|
+
references_el.append(
|
|
823
|
+
_reference(
|
|
824
|
+
"HasTypeDefinition",
|
|
825
|
+
target=f"ns=1;i={identifier_map[type_anno.our_type]}",
|
|
826
|
+
)
|
|
827
|
+
)
|
|
828
|
+
else:
|
|
829
|
+
assert_never(type_anno.our_type)
|
|
830
|
+
else:
|
|
831
|
+
assert_never(type_anno)
|
|
832
|
+
|
|
833
|
+
root.append(references_el)
|
|
834
|
+
|
|
835
|
+
return root
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
def _generate_definitions_for_properties(
|
|
839
|
+
parent_id: int,
|
|
840
|
+
properties: Iterable[intermediate.Property],
|
|
841
|
+
identifier_map: Mapping[_OpcUaIdentifiable, int],
|
|
842
|
+
) -> List[ET.Element]:
|
|
843
|
+
"""
|
|
844
|
+
Generate the definition elements for all the properties.
|
|
845
|
+
|
|
846
|
+
``prop_to_id`` maps the properties to OPC UA identifiers.
|
|
847
|
+
"""
|
|
848
|
+
result = [] # type: List[ET.Element]
|
|
849
|
+
|
|
850
|
+
for prop in properties:
|
|
851
|
+
prop_id = identifier_map[prop]
|
|
852
|
+
|
|
853
|
+
property_el = _generate_for_property(
|
|
854
|
+
prop=prop,
|
|
855
|
+
prop_id=prop_id,
|
|
856
|
+
parent_id=parent_id,
|
|
857
|
+
identifier_map=identifier_map,
|
|
858
|
+
)
|
|
859
|
+
|
|
860
|
+
result.append(property_el)
|
|
861
|
+
|
|
862
|
+
return result
|
|
863
|
+
|
|
864
|
+
|
|
865
|
+
def _generate_for_interface(
|
|
866
|
+
interface: intermediate.Interface,
|
|
867
|
+
identifier_map: Mapping[_OpcUaIdentifiable, int],
|
|
868
|
+
identifiers_for_constraints: _IdentifiersForConstraints,
|
|
869
|
+
name_prefix: Identifier,
|
|
870
|
+
) -> List[ET.Element]:
|
|
871
|
+
"""Generate the definition for the given interface."""
|
|
872
|
+
interface_name = opcua_naming.interface_name(interface.name, name_prefix)
|
|
873
|
+
|
|
874
|
+
comment_starts = ET.Comment(f"{interface_name} starts.")
|
|
875
|
+
comment_starts.tail = "\n"
|
|
876
|
+
|
|
877
|
+
result = [comment_starts] # type: List[ET.Element]
|
|
878
|
+
|
|
879
|
+
interface_id = identifier_map[interface]
|
|
880
|
+
|
|
881
|
+
object_type_el = ET.Element(
|
|
882
|
+
"UAObjectType",
|
|
883
|
+
collections.OrderedDict(
|
|
884
|
+
[
|
|
885
|
+
("NodeId", f"ns=1;i={interface_id}"),
|
|
886
|
+
("BrowseName", f"1:{interface_name}"),
|
|
887
|
+
("IsAbstract", "true"),
|
|
888
|
+
]
|
|
889
|
+
),
|
|
890
|
+
)
|
|
891
|
+
result.append(object_type_el)
|
|
892
|
+
|
|
893
|
+
display_name_el = ET.Element("DisplayName")
|
|
894
|
+
display_name_el.text = interface_name
|
|
895
|
+
object_type_el.append(display_name_el)
|
|
896
|
+
|
|
897
|
+
strictly_interface_properties = [
|
|
898
|
+
prop for prop in interface.properties if prop.specified_for is interface.base
|
|
899
|
+
]
|
|
900
|
+
|
|
901
|
+
references_el = ET.Element("References")
|
|
902
|
+
object_type_el.append(references_el)
|
|
903
|
+
|
|
904
|
+
references_el.append(_reference("HasSubtype", target="i=17602", is_forward=False))
|
|
905
|
+
|
|
906
|
+
for invariant in interface.base.invariants:
|
|
907
|
+
if invariant.specified_for is not interface.base:
|
|
908
|
+
continue
|
|
909
|
+
|
|
910
|
+
invariant_id = identifier_map[invariant]
|
|
911
|
+
|
|
912
|
+
references_el.append(
|
|
913
|
+
_reference(
|
|
914
|
+
reference_type=f"ns=1;i={identifiers_for_constraints.has_constraint_id}",
|
|
915
|
+
target=f"ns=1;i={invariant_id}",
|
|
916
|
+
)
|
|
917
|
+
)
|
|
918
|
+
|
|
919
|
+
references_el.extend(
|
|
920
|
+
_generate_references_for_properties(
|
|
921
|
+
properties=strictly_interface_properties, identifier_map=identifier_map
|
|
922
|
+
)
|
|
923
|
+
)
|
|
924
|
+
|
|
925
|
+
result.extend(
|
|
926
|
+
_generate_definitions_for_properties(
|
|
927
|
+
parent_id=interface_id,
|
|
928
|
+
properties=strictly_interface_properties,
|
|
929
|
+
identifier_map=identifier_map,
|
|
930
|
+
)
|
|
931
|
+
)
|
|
932
|
+
|
|
933
|
+
comment_ends = ET.Comment(f"{interface_name} ends.")
|
|
934
|
+
comment_ends.tail = "\n"
|
|
935
|
+
result.append(comment_ends)
|
|
936
|
+
|
|
937
|
+
return result
|
|
938
|
+
|
|
939
|
+
|
|
940
|
+
def _generate_for_concrete_class(
|
|
941
|
+
cls: intermediate.ConcreteClass,
|
|
942
|
+
identifier_map: Mapping[_OpcUaIdentifiable, int],
|
|
943
|
+
identifiers_for_constraints: _IdentifiersForConstraints,
|
|
944
|
+
name_prefix: Identifier,
|
|
945
|
+
) -> List[ET.Element]:
|
|
946
|
+
"""Generate the definition for the given concrete class."""
|
|
947
|
+
cls_name = opcua_naming.class_name(cls.name, name_prefix)
|
|
948
|
+
cls_id = identifier_map[cls]
|
|
949
|
+
|
|
950
|
+
result = [ET.Comment(f"{cls_name} starts.")] # type: List[ET.Element]
|
|
951
|
+
|
|
952
|
+
object_type_el = ET.Element(
|
|
953
|
+
"UAObjectType",
|
|
954
|
+
attrib=collections.OrderedDict(
|
|
955
|
+
[("NodeId", f"ns=1;i={cls_id}"), ("BrowseName", f"1:{cls_name}")]
|
|
956
|
+
),
|
|
957
|
+
)
|
|
958
|
+
|
|
959
|
+
display_name_el = ET.Element("DisplayName")
|
|
960
|
+
display_name_el.text = cls_name
|
|
961
|
+
object_type_el.append(display_name_el)
|
|
962
|
+
|
|
963
|
+
references_el = ET.Element("References")
|
|
964
|
+
references_el.append(_reference("HasSubtype", target="i=58", is_forward=False))
|
|
965
|
+
|
|
966
|
+
if cls.interface is not None:
|
|
967
|
+
interface_id = identifier_map[cls.interface]
|
|
968
|
+
references_el.append(_reference("HasInterface", f"ns=1;i={interface_id}"))
|
|
969
|
+
|
|
970
|
+
for ancestor_cls in cls.ancestors:
|
|
971
|
+
assert ancestor_cls.interface is not None
|
|
972
|
+
|
|
973
|
+
assert ancestor_cls.interface in identifier_map, (
|
|
974
|
+
f"The OPC UA identifier is missing for the interface corresponding to "
|
|
975
|
+
f"the ancestor class {ancestor_cls.name!r} of the class {cls.name!r}"
|
|
976
|
+
)
|
|
977
|
+
|
|
978
|
+
ancestor_id = identifier_map[ancestor_cls.interface]
|
|
979
|
+
references_el.append(_reference("HasInterface", f"ns=1;i={ancestor_id}"))
|
|
980
|
+
|
|
981
|
+
if cls.interface is None:
|
|
982
|
+
# NOTE (mristin):
|
|
983
|
+
# We have to reference the constraints here since this concrete class has no
|
|
984
|
+
# interface, so no constraints have been referenced thus far. That is, we define
|
|
985
|
+
# the constraints in interfaces, but this class has none, so we have to
|
|
986
|
+
# reference them in the ``ObjectType`` corresponding to the class.
|
|
987
|
+
for invariant in cls.invariants:
|
|
988
|
+
if invariant.specified_for is not cls:
|
|
989
|
+
continue
|
|
990
|
+
|
|
991
|
+
invariant_id = identifier_map[invariant]
|
|
992
|
+
|
|
993
|
+
references_el.append(
|
|
994
|
+
_reference(
|
|
995
|
+
reference_type=f"ns=1;i={identifiers_for_constraints.has_constraint_id}",
|
|
996
|
+
target=f"ns=1;i={invariant_id}",
|
|
997
|
+
)
|
|
998
|
+
)
|
|
999
|
+
|
|
1000
|
+
else:
|
|
1001
|
+
# NOTE (mristin):
|
|
1002
|
+
# We assume that the object type needs to implement all the constraints imposed
|
|
1003
|
+
# on its interfaces. Since we define an interface for any concrete class with
|
|
1004
|
+
# descendants, we do not have to reference the constraints here.
|
|
1005
|
+
pass
|
|
1006
|
+
|
|
1007
|
+
strictly_cls_properties = [
|
|
1008
|
+
prop for prop in cls.properties if prop.specified_for is cls
|
|
1009
|
+
]
|
|
1010
|
+
|
|
1011
|
+
references_el.extend(
|
|
1012
|
+
_generate_references_for_properties(
|
|
1013
|
+
properties=strictly_cls_properties, identifier_map=identifier_map
|
|
1014
|
+
)
|
|
1015
|
+
)
|
|
1016
|
+
|
|
1017
|
+
object_type_el.append(references_el)
|
|
1018
|
+
result.append(object_type_el)
|
|
1019
|
+
|
|
1020
|
+
# NOTE (mristin):
|
|
1021
|
+
# We define the properties only if they have not been already defined
|
|
1022
|
+
# for an interface.
|
|
1023
|
+
# Otherwise, we refer to the properties of the interfaces through
|
|
1024
|
+
# ``HasComponent``/``HasProperty`` reference.
|
|
1025
|
+
if cls.interface is None:
|
|
1026
|
+
result.extend(
|
|
1027
|
+
_generate_definitions_for_properties(
|
|
1028
|
+
parent_id=cls_id,
|
|
1029
|
+
properties=strictly_cls_properties,
|
|
1030
|
+
identifier_map=identifier_map,
|
|
1031
|
+
)
|
|
1032
|
+
)
|
|
1033
|
+
|
|
1034
|
+
result.append(ET.Comment(f"{cls_name} ends."))
|
|
1035
|
+
|
|
1036
|
+
return result
|
|
1037
|
+
|
|
1038
|
+
|
|
1039
|
+
class _NamespaceDeclarations:
|
|
1040
|
+
#: URL of the main namespace
|
|
1041
|
+
main: str
|
|
1042
|
+
|
|
1043
|
+
#: URL to namespace alias
|
|
1044
|
+
url_to_alias: Mapping[str, str]
|
|
1045
|
+
|
|
1046
|
+
#: Namespace alias to URL
|
|
1047
|
+
alias_to_url: OrderedDict[str, str]
|
|
1048
|
+
|
|
1049
|
+
# fmt: off
|
|
1050
|
+
@require(
|
|
1051
|
+
lambda url_to_alias, alias_to_url:
|
|
1052
|
+
all(
|
|
1053
|
+
alias_to_url[alias] == url
|
|
1054
|
+
for url, alias in url_to_alias.items()
|
|
1055
|
+
)
|
|
1056
|
+
)
|
|
1057
|
+
@require(
|
|
1058
|
+
lambda url_to_alias, alias_to_url:
|
|
1059
|
+
all(
|
|
1060
|
+
url_to_alias[url] == alias
|
|
1061
|
+
for alias, url in alias_to_url.items()
|
|
1062
|
+
)
|
|
1063
|
+
)
|
|
1064
|
+
# fmt: on
|
|
1065
|
+
def __init__(
|
|
1066
|
+
self,
|
|
1067
|
+
main: str,
|
|
1068
|
+
url_to_alias: Mapping[str, str],
|
|
1069
|
+
alias_to_url: OrderedDict[str, str],
|
|
1070
|
+
) -> None:
|
|
1071
|
+
"""Initialize with the given values."""
|
|
1072
|
+
self.main = main
|
|
1073
|
+
self.url_to_alias = url_to_alias
|
|
1074
|
+
self.alias_to_url = alias_to_url
|
|
1075
|
+
|
|
1076
|
+
|
|
1077
|
+
def _extractNamespaceDeclarationsFromXML(
|
|
1078
|
+
text: str,
|
|
1079
|
+
) -> Tuple[Optional[_NamespaceDeclarations], Optional[str]]:
|
|
1080
|
+
"""
|
|
1081
|
+
Extract the namespace declarations from the given XML document.
|
|
1082
|
+
|
|
1083
|
+
Return the parsed declarations, or error, if any.
|
|
1084
|
+
"""
|
|
1085
|
+
minidom_doc = xml.dom.minidom.parseString(text)
|
|
1086
|
+
|
|
1087
|
+
main = None # type: Optional[str]
|
|
1088
|
+
url_to_alias = dict() # type: MutableMapping[str, str]
|
|
1089
|
+
alias_to_url = collections.OrderedDict() # type: OrderedDict[str, str]
|
|
1090
|
+
|
|
1091
|
+
for attribute, value in minidom_doc.documentElement.attributes.items():
|
|
1092
|
+
if attribute == "xmlns":
|
|
1093
|
+
main = value
|
|
1094
|
+
elif attribute.startswith("xmlns:"):
|
|
1095
|
+
alias = attribute[len("xmlns:") :]
|
|
1096
|
+
url_to_alias[value] = alias
|
|
1097
|
+
alias_to_url[alias] = value
|
|
1098
|
+
else:
|
|
1099
|
+
# NOTE (mristin):
|
|
1100
|
+
# This attribute is otherwise irrelevant.
|
|
1101
|
+
pass
|
|
1102
|
+
|
|
1103
|
+
if main is None:
|
|
1104
|
+
return None, "The main namespace is missing"
|
|
1105
|
+
|
|
1106
|
+
return (
|
|
1107
|
+
_NamespaceDeclarations(
|
|
1108
|
+
main=main, url_to_alias=url_to_alias, alias_to_url=alias_to_url
|
|
1109
|
+
),
|
|
1110
|
+
None,
|
|
1111
|
+
)
|
|
1112
|
+
|
|
1113
|
+
|
|
1114
|
+
INDENT = " "
|
|
1115
|
+
|
|
1116
|
+
# NOTE (mristin):
|
|
1117
|
+
# The ElementTree library is very peculiar when it comes to namespaces. The namespace
|
|
1118
|
+
# URLs are directly inserted as prefixes to tag names, even when the user specifies
|
|
1119
|
+
# an alias.
|
|
1120
|
+
_ET_NAMESPACE_PREFIX_RE = re.compile(r"^\{(?P<namespace>[^}]*)}")
|
|
1121
|
+
|
|
1122
|
+
|
|
1123
|
+
def _render(
|
|
1124
|
+
element: ET.Element,
|
|
1125
|
+
writer: TextIO,
|
|
1126
|
+
namespace_declarations: _NamespaceDeclarations,
|
|
1127
|
+
level: int = 0,
|
|
1128
|
+
) -> None:
|
|
1129
|
+
"""
|
|
1130
|
+
Render the given XML tree starting with the ``element`` at the root.
|
|
1131
|
+
|
|
1132
|
+
We designed the rendering such that the XMLs are easy to read and diff.
|
|
1133
|
+
"""
|
|
1134
|
+
indention = INDENT * level
|
|
1135
|
+
|
|
1136
|
+
if element.tag is ET.Comment: # type: ignore
|
|
1137
|
+
writer.write(f"{indention}<!-- {element.text} -->\n")
|
|
1138
|
+
else:
|
|
1139
|
+
if len(element) > 0:
|
|
1140
|
+
if element.text is not None and not element.text.isspace():
|
|
1141
|
+
raise ValueError(
|
|
1142
|
+
f"Unexpected element with children "
|
|
1143
|
+
f"and non-whitespace text: {element}; "
|
|
1144
|
+
f"the text was: {element.text!r}"
|
|
1145
|
+
)
|
|
1146
|
+
|
|
1147
|
+
if element.tail is not None and not element.tail.isspace():
|
|
1148
|
+
raise ValueError(
|
|
1149
|
+
f"Unexpected element with children "
|
|
1150
|
+
f"and non-whitespace tail: {element}; "
|
|
1151
|
+
f"the tail was: {element.tail!r}"
|
|
1152
|
+
)
|
|
1153
|
+
|
|
1154
|
+
ns_match = _ET_NAMESPACE_PREFIX_RE.match(element.tag)
|
|
1155
|
+
if ns_match is not None:
|
|
1156
|
+
ns_url = ns_match.group("namespace")
|
|
1157
|
+
|
|
1158
|
+
if ns_url == namespace_declarations.main:
|
|
1159
|
+
# NOTE (mristin):
|
|
1160
|
+
# We add 2 for the enclosing ``{`` and ``}``.
|
|
1161
|
+
name = element.tag[len(ns_url) + 2 :]
|
|
1162
|
+
else:
|
|
1163
|
+
ns_alias = namespace_declarations.url_to_alias.get(ns_url, None)
|
|
1164
|
+
if ns_alias is None:
|
|
1165
|
+
raise ValueError(
|
|
1166
|
+
f"Unexpected namespace URL in the ET element {element}. "
|
|
1167
|
+
f"The declared namespaces aliases "
|
|
1168
|
+
f"were: {namespace_declarations.url_to_alias}"
|
|
1169
|
+
)
|
|
1170
|
+
|
|
1171
|
+
# NOTE (mristin):
|
|
1172
|
+
# We add 2 for the enclosing ``{`` and ``}``.
|
|
1173
|
+
local_name = element.tag[len(ns_url) + 2 :]
|
|
1174
|
+
name = f"{ns_alias}:{local_name}"
|
|
1175
|
+
else:
|
|
1176
|
+
name = element.tag
|
|
1177
|
+
|
|
1178
|
+
text = None # type: Optional[str]
|
|
1179
|
+
if element.text is not None and not element.text.isspace():
|
|
1180
|
+
text = element.text
|
|
1181
|
+
|
|
1182
|
+
if text is None and len(element) == 0:
|
|
1183
|
+
if len(element.attrib) == 0:
|
|
1184
|
+
writer.write(f"{indention}<{name} />\n")
|
|
1185
|
+
else:
|
|
1186
|
+
writer.write(f"{indention}<{name}\n")
|
|
1187
|
+
for attrib, value in element.attrib.items():
|
|
1188
|
+
quoted_value = xml.sax.saxutils.quoteattr(value)
|
|
1189
|
+
writer.write(f"{indention}{INDENT}{attrib}={quoted_value}\n")
|
|
1190
|
+
|
|
1191
|
+
writer.write(f"{indention}/>\n")
|
|
1192
|
+
|
|
1193
|
+
elif text is not None and len(element) == 0:
|
|
1194
|
+
escaped_text = xml.sax.saxutils.escape(text)
|
|
1195
|
+
|
|
1196
|
+
if len(element.attrib) == 0:
|
|
1197
|
+
writer.write(f"{indention}<{name}>{escaped_text}</{name}>\n")
|
|
1198
|
+
else:
|
|
1199
|
+
writer.write(f"{indention}<{name}\n")
|
|
1200
|
+
|
|
1201
|
+
for attrib, value in element.attrib.items():
|
|
1202
|
+
quoted_value = xml.sax.saxutils.quoteattr(value)
|
|
1203
|
+
writer.write(f"{indention}{INDENT}{attrib}={quoted_value}\n")
|
|
1204
|
+
|
|
1205
|
+
writer.write(f"{indention}>{escaped_text}</{name}>\n")
|
|
1206
|
+
|
|
1207
|
+
elif text is None and len(element) > 0:
|
|
1208
|
+
if len(element.attrib) == 0:
|
|
1209
|
+
writer.write(f"{indention}<{name}>\n")
|
|
1210
|
+
|
|
1211
|
+
for child in element:
|
|
1212
|
+
_render(
|
|
1213
|
+
element=child,
|
|
1214
|
+
writer=writer,
|
|
1215
|
+
namespace_declarations=namespace_declarations,
|
|
1216
|
+
level=level + 1,
|
|
1217
|
+
)
|
|
1218
|
+
|
|
1219
|
+
writer.write(f"{indention}</{name}>\n")
|
|
1220
|
+
else:
|
|
1221
|
+
writer.write(f"{indention}<{name}\n")
|
|
1222
|
+
|
|
1223
|
+
for attrib, value in element.attrib.items():
|
|
1224
|
+
quoted_value = xml.sax.saxutils.quoteattr(value)
|
|
1225
|
+
writer.write(f"{indention}{INDENT}{attrib}={quoted_value}\n")
|
|
1226
|
+
|
|
1227
|
+
writer.write(f"{indention}>\n")
|
|
1228
|
+
|
|
1229
|
+
for child in element:
|
|
1230
|
+
_render(
|
|
1231
|
+
element=child,
|
|
1232
|
+
writer=writer,
|
|
1233
|
+
namespace_declarations=namespace_declarations,
|
|
1234
|
+
level=level + 1,
|
|
1235
|
+
)
|
|
1236
|
+
|
|
1237
|
+
writer.write(f"{indention}</{name}>\n")
|
|
1238
|
+
|
|
1239
|
+
else:
|
|
1240
|
+
raise AssertionError("Unexpected execution path")
|
|
1241
|
+
|
|
1242
|
+
|
|
1243
|
+
@ensure(lambda result: not (result[1] is not None) or (len(result[1]) >= 1))
|
|
1244
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
1245
|
+
@ensure(lambda result: not (result[0] is not None) or (result[0].endswith("\n")))
|
|
1246
|
+
def _generate(
|
|
1247
|
+
symbol_table: intermediate.SymbolTable,
|
|
1248
|
+
spec_impls: specific_implementations.SpecificImplementations,
|
|
1249
|
+
) -> Tuple[Optional[str], Optional[List[Error]]]:
|
|
1250
|
+
"""Generate tne node set according to the symbol table."""
|
|
1251
|
+
base_nodeset_key = specific_implementations.ImplementationKey("base_nodeset.xml")
|
|
1252
|
+
|
|
1253
|
+
base_nodeset_text = spec_impls.get(base_nodeset_key, None)
|
|
1254
|
+
if base_nodeset_text is None:
|
|
1255
|
+
return None, [
|
|
1256
|
+
Error(
|
|
1257
|
+
None,
|
|
1258
|
+
f"The implementation snippet for the base OPC UA nodeset "
|
|
1259
|
+
f"is missing: {base_nodeset_key}",
|
|
1260
|
+
)
|
|
1261
|
+
]
|
|
1262
|
+
|
|
1263
|
+
name_prefix_key = specific_implementations.ImplementationKey("name_prefix.txt")
|
|
1264
|
+
|
|
1265
|
+
name_prefix_text = spec_impls.get(name_prefix_key, None)
|
|
1266
|
+
if name_prefix_text is None:
|
|
1267
|
+
return None, [
|
|
1268
|
+
Error(
|
|
1269
|
+
None,
|
|
1270
|
+
f"The implementation snippet for the type name prefix "
|
|
1271
|
+
f"is missing: {name_prefix_key}",
|
|
1272
|
+
)
|
|
1273
|
+
]
|
|
1274
|
+
|
|
1275
|
+
if not IDENTIFIER_RE.match(name_prefix_text):
|
|
1276
|
+
return None, [
|
|
1277
|
+
Error(
|
|
1278
|
+
None,
|
|
1279
|
+
f"The implementation snippet for the type name prefix "
|
|
1280
|
+
f"at {name_prefix_key} is invalid: {name_prefix_text}",
|
|
1281
|
+
)
|
|
1282
|
+
]
|
|
1283
|
+
|
|
1284
|
+
name_prefix = Identifier(name_prefix_text)
|
|
1285
|
+
|
|
1286
|
+
namespace_declarations, error = _extractNamespaceDeclarationsFromXML(
|
|
1287
|
+
base_nodeset_text
|
|
1288
|
+
)
|
|
1289
|
+
if error is not None:
|
|
1290
|
+
return None, [
|
|
1291
|
+
Error(
|
|
1292
|
+
None,
|
|
1293
|
+
f"The namespaces could not be extracted from the implementation snippet "
|
|
1294
|
+
f"for the base OPC UA nodeset {base_nodeset_key}: {error}",
|
|
1295
|
+
)
|
|
1296
|
+
]
|
|
1297
|
+
|
|
1298
|
+
assert namespace_declarations is not None
|
|
1299
|
+
|
|
1300
|
+
if "uax" not in namespace_declarations.alias_to_url:
|
|
1301
|
+
return None, [
|
|
1302
|
+
Error(
|
|
1303
|
+
None,
|
|
1304
|
+
f"The namespace alias for 'uax' is missing in "
|
|
1305
|
+
f"the implementation snippet for the base OPC UA "
|
|
1306
|
+
f"nodeset: {base_nodeset_key}",
|
|
1307
|
+
)
|
|
1308
|
+
]
|
|
1309
|
+
|
|
1310
|
+
try:
|
|
1311
|
+
root = ET.fromstring(base_nodeset_text)
|
|
1312
|
+
except Exception as err:
|
|
1313
|
+
return None, [
|
|
1314
|
+
Error(
|
|
1315
|
+
None,
|
|
1316
|
+
f"Failed to parse the base nodeset XML out of "
|
|
1317
|
+
f"the snippet {base_nodeset_key}: {err}",
|
|
1318
|
+
)
|
|
1319
|
+
]
|
|
1320
|
+
|
|
1321
|
+
identifier_machine = _IdentifierMachine()
|
|
1322
|
+
|
|
1323
|
+
identifier_map = (
|
|
1324
|
+
collections.OrderedDict()
|
|
1325
|
+
) # type: MutableMapping[_OpcUaIdentifiable, int]
|
|
1326
|
+
|
|
1327
|
+
root.append(_generate_aliases())
|
|
1328
|
+
|
|
1329
|
+
# region Generate identifiers
|
|
1330
|
+
|
|
1331
|
+
identifiers_for_constraints = _IdentifiersForConstraints(
|
|
1332
|
+
# NOTE (mristin):
|
|
1333
|
+
# We prefix here with ``_`` in order to avoid conflicts with AAS class names.
|
|
1334
|
+
constraint_id=identifier_machine.obtain("_Constraint"),
|
|
1335
|
+
constraint_identifier_id=identifier_machine.obtain("_Constraint.identifier"),
|
|
1336
|
+
constraint_text_id=identifier_machine.obtain("_Constraint.text"),
|
|
1337
|
+
has_constraint_id=identifier_machine.obtain("_HasConstraint"),
|
|
1338
|
+
)
|
|
1339
|
+
|
|
1340
|
+
# noinspection SpellCheckingInspection
|
|
1341
|
+
invariants = [
|
|
1342
|
+
invariant
|
|
1343
|
+
for invariantable in itertools.chain(
|
|
1344
|
+
symbol_table.classes, symbol_table.constrained_primitives
|
|
1345
|
+
)
|
|
1346
|
+
for invariant in invariantable.invariants
|
|
1347
|
+
if invariant.specified_for is invariantable
|
|
1348
|
+
]
|
|
1349
|
+
|
|
1350
|
+
observed_invariant_uid_set = set() # type: Set[str]
|
|
1351
|
+
|
|
1352
|
+
for invariant in invariants:
|
|
1353
|
+
# NOTE (mristin):
|
|
1354
|
+
# We rely on
|
|
1355
|
+
# :py:func:`intermediate._translate._verify_invariant_descriptions_unique`
|
|
1356
|
+
# that the invariant descriptions are unique.
|
|
1357
|
+
|
|
1358
|
+
invariant_uid = (
|
|
1359
|
+
f"{invariant.specified_for.name}" f":invariant:{invariant.description}"
|
|
1360
|
+
)
|
|
1361
|
+
|
|
1362
|
+
assert (
|
|
1363
|
+
invariant_uid not in observed_invariant_uid_set
|
|
1364
|
+
), f"Unexpected duplicate invariant ID for: {invariant_uid}"
|
|
1365
|
+
observed_invariant_uid_set.add(invariant_uid)
|
|
1366
|
+
|
|
1367
|
+
identifier_map[invariant] = identifier_machine.obtain(invariant_uid)
|
|
1368
|
+
|
|
1369
|
+
for enumeration in symbol_table.enumerations:
|
|
1370
|
+
identifier_map[enumeration] = identifier_machine.obtain(enumeration.name)
|
|
1371
|
+
|
|
1372
|
+
for constrained_primitive in symbol_table.constrained_primitives:
|
|
1373
|
+
identifier_map[constrained_primitive] = identifier_machine.obtain(
|
|
1374
|
+
constrained_primitive.name
|
|
1375
|
+
)
|
|
1376
|
+
|
|
1377
|
+
for cls in symbol_table.classes:
|
|
1378
|
+
if cls.interface is not None:
|
|
1379
|
+
identifier_map[cls.interface] = identifier_machine.obtain(
|
|
1380
|
+
# NOTE (mristin):
|
|
1381
|
+
# We prefix with ``interface:`` to avoid conflicts with
|
|
1382
|
+
# concrete classes.
|
|
1383
|
+
f"interface:{cls.name}"
|
|
1384
|
+
)
|
|
1385
|
+
|
|
1386
|
+
for concrete_cls in symbol_table.concrete_classes:
|
|
1387
|
+
identifier_map[concrete_cls] = identifier_machine.obtain(concrete_cls.name)
|
|
1388
|
+
|
|
1389
|
+
for cls in symbol_table.classes:
|
|
1390
|
+
for prop in cls.properties:
|
|
1391
|
+
if prop.specified_for is not cls:
|
|
1392
|
+
continue
|
|
1393
|
+
|
|
1394
|
+
identifier_map[prop] = identifier_machine.obtain(f"{cls.name}.{prop.name}")
|
|
1395
|
+
|
|
1396
|
+
# endregion
|
|
1397
|
+
|
|
1398
|
+
root.extend(
|
|
1399
|
+
_generate_for_constraints_and_patterns(
|
|
1400
|
+
identifiers_for_constraints=identifiers_for_constraints
|
|
1401
|
+
)
|
|
1402
|
+
)
|
|
1403
|
+
|
|
1404
|
+
if len(symbol_table.enumerations) > 0:
|
|
1405
|
+
root.append(ET.Comment("Enumerations start here."))
|
|
1406
|
+
|
|
1407
|
+
for enumeration in symbol_table.enumerations:
|
|
1408
|
+
root.extend(
|
|
1409
|
+
_generate_for_enum(
|
|
1410
|
+
enumeration=enumeration,
|
|
1411
|
+
identifier_map=identifier_map,
|
|
1412
|
+
identifier_machine=identifier_machine,
|
|
1413
|
+
name_prefix=name_prefix,
|
|
1414
|
+
)
|
|
1415
|
+
)
|
|
1416
|
+
|
|
1417
|
+
if len(symbol_table.enumerations) > 0:
|
|
1418
|
+
root.append(ET.Comment("Enumerations end here."))
|
|
1419
|
+
|
|
1420
|
+
if len(invariants) > 0:
|
|
1421
|
+
root.append(ET.Comment("Constraints start here."))
|
|
1422
|
+
|
|
1423
|
+
for invariant in invariants:
|
|
1424
|
+
root.extend(
|
|
1425
|
+
_generate_for_invariant(
|
|
1426
|
+
invariant=invariant,
|
|
1427
|
+
identifier_map=identifier_map,
|
|
1428
|
+
identifiers_for_constraints=identifiers_for_constraints,
|
|
1429
|
+
identifier_machine=identifier_machine,
|
|
1430
|
+
)
|
|
1431
|
+
)
|
|
1432
|
+
|
|
1433
|
+
if len(invariants) > 0:
|
|
1434
|
+
root.append(ET.Comment("Constraints end here."))
|
|
1435
|
+
|
|
1436
|
+
if len(symbol_table.constrained_primitives) > 0:
|
|
1437
|
+
root.append(ET.Comment("Constrained primitives start here."))
|
|
1438
|
+
|
|
1439
|
+
for constrained_primitive in symbol_table.constrained_primitives:
|
|
1440
|
+
root.append(
|
|
1441
|
+
_generate_for_constrained_primitive(
|
|
1442
|
+
constrained_primitive=constrained_primitive,
|
|
1443
|
+
identifier_map=identifier_map,
|
|
1444
|
+
identifiers_for_constraints=identifiers_for_constraints,
|
|
1445
|
+
name_prefix=name_prefix,
|
|
1446
|
+
)
|
|
1447
|
+
)
|
|
1448
|
+
|
|
1449
|
+
if len(symbol_table.constrained_primitives) > 0:
|
|
1450
|
+
root.append(ET.Comment("Constrained primitives end here."))
|
|
1451
|
+
|
|
1452
|
+
for cls in symbol_table.classes:
|
|
1453
|
+
if cls.interface is not None:
|
|
1454
|
+
root.extend(
|
|
1455
|
+
_generate_for_interface(
|
|
1456
|
+
interface=cls.interface,
|
|
1457
|
+
identifier_map=identifier_map,
|
|
1458
|
+
identifiers_for_constraints=identifiers_for_constraints,
|
|
1459
|
+
name_prefix=name_prefix,
|
|
1460
|
+
)
|
|
1461
|
+
)
|
|
1462
|
+
|
|
1463
|
+
for concrete_cls in symbol_table.concrete_classes:
|
|
1464
|
+
root.extend(
|
|
1465
|
+
_generate_for_concrete_class(
|
|
1466
|
+
cls=concrete_cls,
|
|
1467
|
+
identifier_map=identifier_map,
|
|
1468
|
+
identifiers_for_constraints=identifiers_for_constraints,
|
|
1469
|
+
name_prefix=name_prefix,
|
|
1470
|
+
)
|
|
1471
|
+
)
|
|
1472
|
+
|
|
1473
|
+
writer = io.StringIO()
|
|
1474
|
+
|
|
1475
|
+
# NOTE (mristin):
|
|
1476
|
+
# ElementTree removes the namespaces in the root, so we have to add them back
|
|
1477
|
+
# manually.
|
|
1478
|
+
root.attrib["xmlns"] = namespace_declarations.main
|
|
1479
|
+
for alias, url in namespace_declarations.alias_to_url.items():
|
|
1480
|
+
root.attrib[f"xmlns:{alias}"] = url
|
|
1481
|
+
|
|
1482
|
+
_render(element=root, writer=writer, namespace_declarations=namespace_declarations)
|
|
1483
|
+
|
|
1484
|
+
return writer.getvalue(), None
|
|
1485
|
+
|
|
1486
|
+
|
|
1487
|
+
def execute(
|
|
1488
|
+
context: run.Context,
|
|
1489
|
+
stdout: TextIO,
|
|
1490
|
+
stderr: TextIO,
|
|
1491
|
+
) -> int:
|
|
1492
|
+
"""
|
|
1493
|
+
Execute the generation with the given parameters.
|
|
1494
|
+
|
|
1495
|
+
Return the error code, or 0 if no errors.
|
|
1496
|
+
"""
|
|
1497
|
+
code, errors = _generate(
|
|
1498
|
+
symbol_table=context.symbol_table, spec_impls=context.spec_impls
|
|
1499
|
+
)
|
|
1500
|
+
if errors is not None:
|
|
1501
|
+
run.write_error_report(
|
|
1502
|
+
message=f"Failed to generate the OPC UA node set "
|
|
1503
|
+
f"based on {context.model_path}",
|
|
1504
|
+
errors=[context.lineno_columner.error_message(error) for error in errors],
|
|
1505
|
+
stderr=stderr,
|
|
1506
|
+
)
|
|
1507
|
+
return 1
|
|
1508
|
+
|
|
1509
|
+
assert code is not None
|
|
1510
|
+
|
|
1511
|
+
# noinspection SpellCheckingInspection
|
|
1512
|
+
pth = context.output_dir / "nodeset.xml"
|
|
1513
|
+
try:
|
|
1514
|
+
pth.write_text(code, encoding="utf-8")
|
|
1515
|
+
except Exception as exception:
|
|
1516
|
+
run.write_error_report(
|
|
1517
|
+
message=f"Failed to write the OPC UA node set to {pth}",
|
|
1518
|
+
errors=[str(exception)],
|
|
1519
|
+
stderr=stderr,
|
|
1520
|
+
)
|
|
1521
|
+
return 1
|
|
1522
|
+
|
|
1523
|
+
stdout.write(f"Code generated to: {context.output_dir}\n")
|
|
1524
|
+
|
|
1525
|
+
return 0
|