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,1187 @@
|
|
|
1
|
+
"""Generate XML Schema Definition (XSD) corresponding to the meta-model."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
import xml.etree.ElementTree as ET
|
|
5
|
+
|
|
6
|
+
# noinspection PyUnresolvedReferences
|
|
7
|
+
import xml.dom.minidom
|
|
8
|
+
from typing import TextIO, MutableMapping, Optional, Tuple, List, Sequence, Any
|
|
9
|
+
|
|
10
|
+
from icontract import ensure, require
|
|
11
|
+
import greenery
|
|
12
|
+
|
|
13
|
+
import aas_core_codegen.xsd
|
|
14
|
+
from aas_core_codegen import (
|
|
15
|
+
naming,
|
|
16
|
+
specific_implementations,
|
|
17
|
+
intermediate,
|
|
18
|
+
run,
|
|
19
|
+
infer_for_schema,
|
|
20
|
+
)
|
|
21
|
+
from aas_core_codegen.common import Error, assert_never, Identifier
|
|
22
|
+
from aas_core_codegen.xsd import naming as xsd_naming
|
|
23
|
+
from aas_core_codegen.parse import retree as parse_retree
|
|
24
|
+
|
|
25
|
+
assert aas_core_codegen.xsd.__doc__ == __doc__
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _define_for_enumeration(enumeration: intermediate.Enumeration) -> List[ET.Element]:
|
|
29
|
+
"""
|
|
30
|
+
Generate the definitions for an ``enumeration``.
|
|
31
|
+
The root element is to be *extended* with the resulting list.
|
|
32
|
+
"""
|
|
33
|
+
restriction = ET.Element("xs:restriction", {"base": "xs:string"})
|
|
34
|
+
for literal in enumeration.literals:
|
|
35
|
+
restriction.append(ET.Element("xs:enumeration", {"value": literal.value}))
|
|
36
|
+
|
|
37
|
+
element = ET.Element(
|
|
38
|
+
"xs:simpleType", {"name": xsd_naming.type_name(enumeration.name)}
|
|
39
|
+
)
|
|
40
|
+
element.append(restriction)
|
|
41
|
+
|
|
42
|
+
return [element]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
_PRIMITIVE_MAP = {
|
|
46
|
+
intermediate.PrimitiveType.BOOL: "xs:boolean",
|
|
47
|
+
intermediate.PrimitiveType.INT: "xs:long",
|
|
48
|
+
intermediate.PrimitiveType.FLOAT: "xs:double",
|
|
49
|
+
intermediate.PrimitiveType.STR: "xs:string",
|
|
50
|
+
intermediate.PrimitiveType.BYTEARRAY: "xs:base64Binary",
|
|
51
|
+
}
|
|
52
|
+
assert all(literal in _PRIMITIVE_MAP for literal in intermediate.PrimitiveType)
|
|
53
|
+
|
|
54
|
+
# noinspection RegExpSimplifiable
|
|
55
|
+
_ESCAPE_BACKSLASH_X_RE = re.compile(r"\\x([a-fA-f0-9]{2})")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _undo_escaping_backslash_x_in_pattern(pattern: str) -> str:
|
|
59
|
+
"""
|
|
60
|
+
Undo the escaping of `\\x??` in the ``pattern``.
|
|
61
|
+
|
|
62
|
+
This is necessary since XML Schema Validators do not know how to handle such escape
|
|
63
|
+
sequences in the patterns and need the verbatim characters.
|
|
64
|
+
"""
|
|
65
|
+
parts = [] # type: List[str]
|
|
66
|
+
cursor = None # type: Optional[int]
|
|
67
|
+
for mtch in re.finditer(_ESCAPE_BACKSLASH_X_RE, pattern):
|
|
68
|
+
if cursor is None:
|
|
69
|
+
parts.append(pattern[: mtch.start()])
|
|
70
|
+
else:
|
|
71
|
+
parts.append(pattern[cursor : mtch.start()])
|
|
72
|
+
|
|
73
|
+
ascii_code = int(mtch.group(1), base=16)
|
|
74
|
+
character = chr(ascii_code)
|
|
75
|
+
parts.append(character)
|
|
76
|
+
cursor = mtch.end()
|
|
77
|
+
|
|
78
|
+
if cursor is None:
|
|
79
|
+
parts.append(pattern)
|
|
80
|
+
else:
|
|
81
|
+
if cursor < len(pattern):
|
|
82
|
+
parts.append(pattern[cursor:])
|
|
83
|
+
|
|
84
|
+
return "".join(parts)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# noinspection RegExpSimplifiable
|
|
88
|
+
_ESCAPE_BACKSLASH_X_U_U_RE = re.compile(
|
|
89
|
+
r"(\\x([a-fA-f0-9]{2})|\\u([a-fA-f0-9]{4})|\\U([a-fA-f0-9]{8}))"
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _undo_escaping_backslash_x_u_and_U_in_pattern(pattern: str) -> str:
|
|
94
|
+
"""
|
|
95
|
+
Undo the escaping of ``\\x??``, ``\\u????`` and ``\\U????????`` in the ``pattern``.
|
|
96
|
+
|
|
97
|
+
This is necessary since Greenery does not know how to handle such escape
|
|
98
|
+
sequences in the patterns and need the verbatim characters.
|
|
99
|
+
"""
|
|
100
|
+
parts = [] # type: List[str]
|
|
101
|
+
cursor = None # type: Optional[int]
|
|
102
|
+
for mtch in re.finditer(_ESCAPE_BACKSLASH_X_U_U_RE, pattern):
|
|
103
|
+
if cursor is None:
|
|
104
|
+
parts.append(pattern[: mtch.start()])
|
|
105
|
+
else:
|
|
106
|
+
parts.append(pattern[cursor : mtch.start()])
|
|
107
|
+
|
|
108
|
+
substring = mtch.group(0)
|
|
109
|
+
assert len(substring) > 2
|
|
110
|
+
assert substring[0] == "\\"
|
|
111
|
+
|
|
112
|
+
hex_code = substring[2:]
|
|
113
|
+
code_point = int(hex_code, base=16)
|
|
114
|
+
character = chr(code_point)
|
|
115
|
+
parts.append(character)
|
|
116
|
+
cursor = mtch.end()
|
|
117
|
+
|
|
118
|
+
if cursor is None:
|
|
119
|
+
parts.append(pattern)
|
|
120
|
+
else:
|
|
121
|
+
if cursor < len(pattern):
|
|
122
|
+
parts.append(pattern[cursor:])
|
|
123
|
+
|
|
124
|
+
return "".join(parts)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class _AnchorRemover(parse_retree.PassThroughVisitor):
|
|
128
|
+
"""
|
|
129
|
+
Remove anchors from a regex in-place.
|
|
130
|
+
|
|
131
|
+
We need to remove the anchors (``^``, ``$``) since patterns in the XSD are always
|
|
132
|
+
anchored.
|
|
133
|
+
|
|
134
|
+
This is necessary since otherwise the schema validation fails.
|
|
135
|
+
See: https://stackoverflow.com/questions/4367914/regular-expression-in-xml-schema-definition-fails
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
def visit_concatenation(self, node: parse_retree.Concatenation) -> None:
|
|
139
|
+
"""Visit the ``concatenation``."""
|
|
140
|
+
new_concatenants = [] # type: List[parse_retree.Term]
|
|
141
|
+
for concatenant in node.concatenants:
|
|
142
|
+
if not (
|
|
143
|
+
isinstance(concatenant.value, parse_retree.Symbol)
|
|
144
|
+
and concatenant.value.kind
|
|
145
|
+
in (parse_retree.SymbolKind.START, parse_retree.SymbolKind.END)
|
|
146
|
+
):
|
|
147
|
+
new_concatenants.append(concatenant)
|
|
148
|
+
|
|
149
|
+
node.concatenants = new_concatenants
|
|
150
|
+
for concatenant in new_concatenants:
|
|
151
|
+
self.visit(concatenant)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
155
|
+
def _translate_pattern(pattern: str) -> Tuple[Optional[str], Optional[str]]:
|
|
156
|
+
"""Translate the pattern to obtain the equivalent in XSD."""
|
|
157
|
+
pattern = _undo_escaping_backslash_x_in_pattern(pattern)
|
|
158
|
+
|
|
159
|
+
parsed, error = parse_retree.parse(values=[pattern])
|
|
160
|
+
if error is not None:
|
|
161
|
+
regex_line, pointer_line = parse_retree.render_pointer(error.cursor)
|
|
162
|
+
return None, f"{error.message}\n{regex_line}\n{pointer_line}"
|
|
163
|
+
assert parsed is not None
|
|
164
|
+
|
|
165
|
+
remover = _AnchorRemover()
|
|
166
|
+
remover.visit(parsed)
|
|
167
|
+
|
|
168
|
+
values = parse_retree.render(regex=parsed)
|
|
169
|
+
parts = [] # type: List[str]
|
|
170
|
+
for value in values:
|
|
171
|
+
assert isinstance(value, str), (
|
|
172
|
+
"Only strings expected when rendering a pattern "
|
|
173
|
+
"supplied originally as a string"
|
|
174
|
+
)
|
|
175
|
+
parts.append(value)
|
|
176
|
+
|
|
177
|
+
return "".join(parts), None
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def _generate_xs_restriction(
|
|
181
|
+
base_type: intermediate.PrimitiveType,
|
|
182
|
+
len_constraint: Optional[infer_for_schema.LenConstraint],
|
|
183
|
+
pattern_constraints: Optional[Sequence[infer_for_schema.PatternConstraint]],
|
|
184
|
+
) -> Tuple[Optional[ET.Element], Optional[str]]:
|
|
185
|
+
"""
|
|
186
|
+
Generate the ``xs:restriction`` for the given primitive.
|
|
187
|
+
|
|
188
|
+
Return the restriction element (if any length or pattern constraints), or
|
|
189
|
+
an error.
|
|
190
|
+
"""
|
|
191
|
+
if len_constraint is None and (
|
|
192
|
+
pattern_constraints is None or (len(pattern_constraints) == 0)
|
|
193
|
+
):
|
|
194
|
+
return None, None
|
|
195
|
+
|
|
196
|
+
restriction = ET.Element("xs:restriction", {"base": _PRIMITIVE_MAP[base_type]})
|
|
197
|
+
|
|
198
|
+
# NOTE (mristin, 2023-02-27):
|
|
199
|
+
# We skip the general XML character pattern. It makes greenery
|
|
200
|
+
# unbearably slow since it instantiates *each* character in
|
|
201
|
+
# the character range. Since XML engines can not deal with the special
|
|
202
|
+
# characters any ways, there is no need to include this constraint in
|
|
203
|
+
# the XSD pattern restrictions.
|
|
204
|
+
patterns_relevant_for_xsd: Optional[List[infer_for_schema.PatternConstraint]] = None
|
|
205
|
+
|
|
206
|
+
if pattern_constraints is not None:
|
|
207
|
+
patterns_relevant_for_xsd = [
|
|
208
|
+
pattern_constraint
|
|
209
|
+
for pattern_constraint in pattern_constraints
|
|
210
|
+
if pattern_constraint.pattern
|
|
211
|
+
!= (
|
|
212
|
+
"^[\\x09\\x0A\\x0D\\x20-\\uD7FF\\uE000-\\uFFFD"
|
|
213
|
+
"\\U00010000-\\U0010FFFF]*$"
|
|
214
|
+
)
|
|
215
|
+
]
|
|
216
|
+
|
|
217
|
+
if patterns_relevant_for_xsd is not None and len(patterns_relevant_for_xsd) > 0:
|
|
218
|
+
translated_pattern: Optional[str]
|
|
219
|
+
|
|
220
|
+
if len(patterns_relevant_for_xsd) == 1:
|
|
221
|
+
translated_pattern, error = _translate_pattern(
|
|
222
|
+
patterns_relevant_for_xsd[0].pattern
|
|
223
|
+
)
|
|
224
|
+
if error is not None:
|
|
225
|
+
return None, error
|
|
226
|
+
else:
|
|
227
|
+
# NOTE (mristin, 2023-02-27):
|
|
228
|
+
# The module ``greenery`` is not annotated with types at the moment.
|
|
229
|
+
merger = None # type: Optional[Any]
|
|
230
|
+
for pattern_constraint in patterns_relevant_for_xsd:
|
|
231
|
+
# NOTE (mristin, 2023-02-27):
|
|
232
|
+
# Greenery expects the characters to be in unicode and not escaped.
|
|
233
|
+
translated_for_greenery = _undo_escaping_backslash_x_u_and_U_in_pattern(
|
|
234
|
+
pattern_constraint.pattern
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
try:
|
|
238
|
+
parsed = greenery.parse(translated_for_greenery)
|
|
239
|
+
except Exception as exception:
|
|
240
|
+
if translated_for_greenery == pattern_constraint.pattern:
|
|
241
|
+
return None, (
|
|
242
|
+
f"The greenery failed to parse "
|
|
243
|
+
f"the pattern {translated_for_greenery!r}: {exception}"
|
|
244
|
+
)
|
|
245
|
+
else:
|
|
246
|
+
return None, (
|
|
247
|
+
f"The greenery failed to parse "
|
|
248
|
+
f"the pattern {translated_for_greenery!r} "
|
|
249
|
+
f"(which was originally {pattern_constraint.pattern!r}): "
|
|
250
|
+
f"{exception}"
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
if merger is None:
|
|
254
|
+
merger = parsed
|
|
255
|
+
else:
|
|
256
|
+
merger = merger & parsed
|
|
257
|
+
|
|
258
|
+
assert merger is not None
|
|
259
|
+
|
|
260
|
+
translated_pattern, error = _translate_pattern(str(merger))
|
|
261
|
+
if error is not None:
|
|
262
|
+
return None, error
|
|
263
|
+
|
|
264
|
+
assert translated_pattern is not None
|
|
265
|
+
|
|
266
|
+
pattern = ET.Element(
|
|
267
|
+
"xs:pattern",
|
|
268
|
+
{"value": translated_pattern},
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
restriction.append(pattern)
|
|
272
|
+
|
|
273
|
+
if len_constraint is not None:
|
|
274
|
+
if len_constraint.min_value is not None:
|
|
275
|
+
min_length = ET.Element(
|
|
276
|
+
"xs:minLength", {"value": str(len_constraint.min_value)}
|
|
277
|
+
)
|
|
278
|
+
restriction.append(min_length)
|
|
279
|
+
|
|
280
|
+
if len_constraint.max_value is not None:
|
|
281
|
+
max_length = ET.Element(
|
|
282
|
+
"xs:maxLength", {"value": str(len_constraint.max_value)}
|
|
283
|
+
)
|
|
284
|
+
restriction.append(max_length)
|
|
285
|
+
|
|
286
|
+
return restriction, None
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
290
|
+
def _generate_xs_element_for_a_primitive_property(
|
|
291
|
+
prop: intermediate.Property,
|
|
292
|
+
len_constraint: Optional[infer_for_schema.LenConstraint],
|
|
293
|
+
pattern_constraints: Optional[Sequence[infer_for_schema.PatternConstraint]],
|
|
294
|
+
) -> Tuple[Optional[ET.Element], Optional[Error]]:
|
|
295
|
+
"""
|
|
296
|
+
Generate the ``xs:element`` for a primitive property.
|
|
297
|
+
|
|
298
|
+
A primitive property is a property whose type is either a primitive or
|
|
299
|
+
a constrained primitive. The reason why we take these two together is that we
|
|
300
|
+
in-line the constraints for the constrained primitives.
|
|
301
|
+
|
|
302
|
+
We do not define the constrained primitives separately in the schema in order to
|
|
303
|
+
avoid the confusion during comparisons between the XSD and the meta-model in
|
|
304
|
+
the book.
|
|
305
|
+
"""
|
|
306
|
+
type_anno = intermediate.beneath_optional(prop.type_annotation)
|
|
307
|
+
|
|
308
|
+
if (
|
|
309
|
+
isinstance(type_anno, intermediate.OurTypeAnnotation)
|
|
310
|
+
and type_anno.our_type.name == "Value_data_type"
|
|
311
|
+
):
|
|
312
|
+
# NOTE (mristin, 2022-11-10):
|
|
313
|
+
# Please see :py:const:`_EXPLANATION_ABOUT_WHY_WE_EXPECT_VALUE_DATA_TYPE`
|
|
314
|
+
# for the explanation why we hard-wire the ``Value_data_type`` here
|
|
315
|
+
return (
|
|
316
|
+
ET.Element(
|
|
317
|
+
"xs:element",
|
|
318
|
+
{
|
|
319
|
+
"name": naming.xml_property(prop.name),
|
|
320
|
+
"type": "valueDataType",
|
|
321
|
+
},
|
|
322
|
+
),
|
|
323
|
+
None,
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
# NOTE (mristin, 2022-03-30):
|
|
327
|
+
# Specify the type of the ``type_anno`` here with assert instead of specifying it
|
|
328
|
+
# in the pre-condition to help mypy a bit.
|
|
329
|
+
|
|
330
|
+
base_type = intermediate.try_primitive_type(type_anno)
|
|
331
|
+
|
|
332
|
+
assert (
|
|
333
|
+
base_type is not None
|
|
334
|
+
), f"Expected a primitive or a constrained primitive, but got: {type_anno}"
|
|
335
|
+
|
|
336
|
+
xs_restriction, error = _generate_xs_restriction(
|
|
337
|
+
base_type=base_type,
|
|
338
|
+
len_constraint=len_constraint,
|
|
339
|
+
pattern_constraints=pattern_constraints,
|
|
340
|
+
)
|
|
341
|
+
if error is not None:
|
|
342
|
+
return None, Error(
|
|
343
|
+
prop.parsed.node,
|
|
344
|
+
f"Failed to generate the restriction for property {prop.name}: {error}",
|
|
345
|
+
)
|
|
346
|
+
# NOTE (mristin, 2022-06-18):
|
|
347
|
+
# xs_restriction may be None here if there are no constraints.
|
|
348
|
+
|
|
349
|
+
xs_element: ET.Element
|
|
350
|
+
|
|
351
|
+
if xs_restriction is None:
|
|
352
|
+
xs_element = ET.Element(
|
|
353
|
+
"xs:element",
|
|
354
|
+
{
|
|
355
|
+
"name": naming.xml_property(prop.name),
|
|
356
|
+
"type": _PRIMITIVE_MAP[base_type],
|
|
357
|
+
},
|
|
358
|
+
)
|
|
359
|
+
else:
|
|
360
|
+
xs_simple_type = ET.Element("xs:simpleType")
|
|
361
|
+
xs_simple_type.append(xs_restriction)
|
|
362
|
+
|
|
363
|
+
xs_element = ET.Element("xs:element", {"name": naming.xml_property(prop.name)})
|
|
364
|
+
xs_element.append(xs_simple_type)
|
|
365
|
+
|
|
366
|
+
return xs_element, None
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
370
|
+
def _generate_xs_element_for_a_list_property(
|
|
371
|
+
prop: intermediate.Property,
|
|
372
|
+
len_constraint: Optional[infer_for_schema.LenConstraint],
|
|
373
|
+
) -> Tuple[Optional[ET.Element], Optional[Error]]:
|
|
374
|
+
"""Generate the ``xs:element`` for a list property."""
|
|
375
|
+
type_anno = intermediate.beneath_optional(prop.type_annotation)
|
|
376
|
+
|
|
377
|
+
# NOTE (mristin, 2022-03-30):
|
|
378
|
+
# Specify the ``type_anno`` here with assert instead of specifying it
|
|
379
|
+
# in the pre-condition to help mypy a bit
|
|
380
|
+
assert isinstance(type_anno, intermediate.ListTypeAnnotation)
|
|
381
|
+
|
|
382
|
+
min_occurs = "0"
|
|
383
|
+
max_occurs = "unbounded"
|
|
384
|
+
if len_constraint is not None:
|
|
385
|
+
if len_constraint.min_value is not None:
|
|
386
|
+
min_occurs = str(len_constraint.min_value)
|
|
387
|
+
|
|
388
|
+
if len_constraint.max_value is not None:
|
|
389
|
+
max_occurs = str(len_constraint.max_value)
|
|
390
|
+
|
|
391
|
+
xs_element: ET.Element
|
|
392
|
+
|
|
393
|
+
if isinstance(type_anno.items, intermediate.OurTypeAnnotation):
|
|
394
|
+
# NOTE (mristin, 2021-11-13):
|
|
395
|
+
# We need to nest the elements in the tag element to separate them in the
|
|
396
|
+
# sequence.
|
|
397
|
+
|
|
398
|
+
our_type = type_anno.items.our_type
|
|
399
|
+
|
|
400
|
+
if isinstance(our_type, intermediate.Enumeration):
|
|
401
|
+
return None, Error(
|
|
402
|
+
prop.parsed.node,
|
|
403
|
+
f"We do not know how to specify the list of enumerations "
|
|
404
|
+
f"for the property {prop.name!r} of {prop.specified_for.name!r} "
|
|
405
|
+
f"in the XSD with the type: {type_anno}",
|
|
406
|
+
)
|
|
407
|
+
|
|
408
|
+
elif isinstance(our_type, intermediate.ConstrainedPrimitive):
|
|
409
|
+
return None, Error(
|
|
410
|
+
prop.parsed.node,
|
|
411
|
+
f"We do not know how to specify the list of constrained primitives "
|
|
412
|
+
f"for the property {prop.name!r} of {prop.specified_for.name!r} "
|
|
413
|
+
f"in the XSD with the type: {type_anno}",
|
|
414
|
+
)
|
|
415
|
+
|
|
416
|
+
elif isinstance(
|
|
417
|
+
our_type, (intermediate.AbstractClass, intermediate.ConcreteClass)
|
|
418
|
+
):
|
|
419
|
+
# NOTE (mristin, 2022-05-26):
|
|
420
|
+
# We need to check for the concrete descendants. If there are no concrete
|
|
421
|
+
# descendants, there is no choice group either. Notably, this not only
|
|
422
|
+
# applies to concrete classes, but there is no choice group for the abstract
|
|
423
|
+
# classes without descendants either.
|
|
424
|
+
if len(our_type.concrete_descendants) > 0:
|
|
425
|
+
choice_group_name = xsd_naming.choice_group_name(our_type.name)
|
|
426
|
+
xs_group = ET.Element(
|
|
427
|
+
"xs:group",
|
|
428
|
+
{
|
|
429
|
+
"ref": choice_group_name,
|
|
430
|
+
"minOccurs": min_occurs,
|
|
431
|
+
"maxOccurs": max_occurs,
|
|
432
|
+
},
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
xs_sequence = ET.Element("xs:sequence")
|
|
436
|
+
xs_sequence.append(xs_group)
|
|
437
|
+
|
|
438
|
+
xs_complex_type = ET.Element("xs:complexType")
|
|
439
|
+
xs_complex_type.append(xs_sequence)
|
|
440
|
+
|
|
441
|
+
xs_element = ET.Element(
|
|
442
|
+
"xs:element", {"name": naming.xml_property(prop.name)}
|
|
443
|
+
)
|
|
444
|
+
xs_element.append(xs_complex_type)
|
|
445
|
+
else:
|
|
446
|
+
xs_element_inner = ET.Element(
|
|
447
|
+
"xs:element",
|
|
448
|
+
{
|
|
449
|
+
"name": naming.xml_class_name(our_type.name),
|
|
450
|
+
"type": xsd_naming.type_name(our_type.name),
|
|
451
|
+
"minOccurs": min_occurs,
|
|
452
|
+
"maxOccurs": max_occurs,
|
|
453
|
+
},
|
|
454
|
+
)
|
|
455
|
+
xs_sequence = ET.Element("xs:sequence")
|
|
456
|
+
xs_sequence.append(xs_element_inner)
|
|
457
|
+
|
|
458
|
+
xs_complex_type = ET.Element("xs:complexType")
|
|
459
|
+
xs_complex_type.append(xs_sequence)
|
|
460
|
+
|
|
461
|
+
xs_element = ET.Element(
|
|
462
|
+
"xs:element", {"name": naming.xml_property(prop.name)}
|
|
463
|
+
)
|
|
464
|
+
xs_element.append(xs_complex_type)
|
|
465
|
+
|
|
466
|
+
elif isinstance(our_type, intermediate.ConstrainedPrimitive):
|
|
467
|
+
return None, Error(
|
|
468
|
+
prop.parsed.node,
|
|
469
|
+
f"We do not know how to specify the list of constrained primitives "
|
|
470
|
+
f"for the property {prop.name!r} of {prop.specified_for.name!r} "
|
|
471
|
+
f"in the XSD with the type: {type_anno}",
|
|
472
|
+
)
|
|
473
|
+
else:
|
|
474
|
+
assert_never(our_type)
|
|
475
|
+
else:
|
|
476
|
+
return None, Error(
|
|
477
|
+
prop.parsed.node,
|
|
478
|
+
f"We do not know how to specify the list "
|
|
479
|
+
f"for the property {prop.name!r} of {prop.specified_for.name!r} "
|
|
480
|
+
f"in the XSD with the type: {type_anno}",
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
return xs_element, None
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
487
|
+
def _generate_xs_element_for_a_property(
|
|
488
|
+
prop: intermediate.Property,
|
|
489
|
+
len_constraint: Optional[infer_for_schema.LenConstraint],
|
|
490
|
+
pattern_constraints: Optional[Sequence[infer_for_schema.PatternConstraint]],
|
|
491
|
+
) -> Tuple[Optional[ET.Element], Optional[Error]]:
|
|
492
|
+
"""Generate the definition of an ``xs:element`` for a property."""
|
|
493
|
+
type_anno = intermediate.beneath_optional(prop.type_annotation)
|
|
494
|
+
|
|
495
|
+
xs_element: Optional[ET.Element]
|
|
496
|
+
|
|
497
|
+
if isinstance(type_anno, intermediate.PrimitiveTypeAnnotation):
|
|
498
|
+
xs_element, error = _generate_xs_element_for_a_primitive_property(
|
|
499
|
+
prop=prop,
|
|
500
|
+
len_constraint=len_constraint,
|
|
501
|
+
pattern_constraints=pattern_constraints,
|
|
502
|
+
)
|
|
503
|
+
if error is not None:
|
|
504
|
+
return None, error
|
|
505
|
+
assert xs_element is not None
|
|
506
|
+
|
|
507
|
+
elif isinstance(type_anno, intermediate.OurTypeAnnotation):
|
|
508
|
+
our_type = type_anno.our_type
|
|
509
|
+
|
|
510
|
+
if isinstance(our_type, intermediate.Enumeration):
|
|
511
|
+
xs_element = ET.Element(
|
|
512
|
+
"xs:element",
|
|
513
|
+
{
|
|
514
|
+
"name": naming.xml_property(prop.name),
|
|
515
|
+
"type": xsd_naming.type_name(our_type.name),
|
|
516
|
+
},
|
|
517
|
+
)
|
|
518
|
+
|
|
519
|
+
elif isinstance(our_type, intermediate.ConstrainedPrimitive):
|
|
520
|
+
xs_element, error = _generate_xs_element_for_a_primitive_property(
|
|
521
|
+
prop=prop,
|
|
522
|
+
len_constraint=len_constraint,
|
|
523
|
+
pattern_constraints=pattern_constraints,
|
|
524
|
+
)
|
|
525
|
+
if error is not None:
|
|
526
|
+
return None, error
|
|
527
|
+
assert xs_element is not None
|
|
528
|
+
|
|
529
|
+
elif isinstance(
|
|
530
|
+
our_type, (intermediate.AbstractClass, intermediate.ConcreteClass)
|
|
531
|
+
):
|
|
532
|
+
# NOTE (mristin, 2022-05-26):
|
|
533
|
+
# We generate choices only if there are at least one concrete descendant.
|
|
534
|
+
# Otherwise, the choice is not generated. Hence, we need to reference
|
|
535
|
+
# a choice only if there is actually one.
|
|
536
|
+
#
|
|
537
|
+
# This is especially necessary for abstract classes with no descendants
|
|
538
|
+
# which we still want to include in the schema. We simply generate an empty
|
|
539
|
+
# element in the schema for such abstract classes without descendants.
|
|
540
|
+
if len(our_type.concrete_descendants) > 0:
|
|
541
|
+
xs_sequence = ET.Element("xs:sequence")
|
|
542
|
+
xs_sequence.append(
|
|
543
|
+
ET.Element(
|
|
544
|
+
"xs:group", {"ref": xsd_naming.choice_group_name(our_type.name)}
|
|
545
|
+
)
|
|
546
|
+
)
|
|
547
|
+
|
|
548
|
+
xs_complex_type = ET.Element("xs:complexType")
|
|
549
|
+
xs_complex_type.append(xs_sequence)
|
|
550
|
+
|
|
551
|
+
xs_element = ET.Element(
|
|
552
|
+
"xs:element", {"name": naming.xml_property(prop.name)}
|
|
553
|
+
)
|
|
554
|
+
xs_element.append(xs_complex_type)
|
|
555
|
+
else:
|
|
556
|
+
xs_element = ET.Element(
|
|
557
|
+
"xs:element",
|
|
558
|
+
{
|
|
559
|
+
"name": naming.xml_property(prop.name),
|
|
560
|
+
"type": xsd_naming.type_name(our_type.name),
|
|
561
|
+
},
|
|
562
|
+
)
|
|
563
|
+
else:
|
|
564
|
+
assert_never(type_anno.our_type)
|
|
565
|
+
|
|
566
|
+
elif isinstance(type_anno, intermediate.ListTypeAnnotation):
|
|
567
|
+
xs_element, error = _generate_xs_element_for_a_list_property(
|
|
568
|
+
prop=prop, len_constraint=len_constraint
|
|
569
|
+
)
|
|
570
|
+
if error is not None:
|
|
571
|
+
return None, error
|
|
572
|
+
|
|
573
|
+
assert xs_element is not None
|
|
574
|
+
else:
|
|
575
|
+
assert_never(type_anno)
|
|
576
|
+
|
|
577
|
+
assert xs_element is not None
|
|
578
|
+
|
|
579
|
+
if isinstance(prop.type_annotation, intermediate.OptionalTypeAnnotation):
|
|
580
|
+
xs_element.attrib["minOccurs"] = "0"
|
|
581
|
+
xs_element.attrib["maxOccurs"] = "1"
|
|
582
|
+
|
|
583
|
+
return xs_element, None
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
587
|
+
def _define_properties(
|
|
588
|
+
cls: intermediate.ClassUnion,
|
|
589
|
+
constraints_by_property: infer_for_schema.ConstraintsByProperty,
|
|
590
|
+
) -> Tuple[Optional[List[ET.Element]], Optional[List[Error]]]:
|
|
591
|
+
"""Define the properties of the ``cls`` as a sequence of tags."""
|
|
592
|
+
sequence = [] # type: List[ET.Element]
|
|
593
|
+
errors = [] # type: List[Error]
|
|
594
|
+
|
|
595
|
+
for prop in cls.properties:
|
|
596
|
+
if prop.specified_for is not cls:
|
|
597
|
+
continue
|
|
598
|
+
|
|
599
|
+
len_constraint = constraints_by_property.len_constraints_by_property.get(
|
|
600
|
+
prop, None
|
|
601
|
+
)
|
|
602
|
+
|
|
603
|
+
pattern_constraints = constraints_by_property.patterns_by_property.get(
|
|
604
|
+
prop, None
|
|
605
|
+
)
|
|
606
|
+
|
|
607
|
+
xs_element, error = _generate_xs_element_for_a_property(
|
|
608
|
+
prop=prop,
|
|
609
|
+
len_constraint=len_constraint,
|
|
610
|
+
pattern_constraints=pattern_constraints,
|
|
611
|
+
)
|
|
612
|
+
if error is not None:
|
|
613
|
+
errors.append(error)
|
|
614
|
+
else:
|
|
615
|
+
assert xs_element is not None
|
|
616
|
+
sequence.append(xs_element)
|
|
617
|
+
|
|
618
|
+
if len(errors) > 0:
|
|
619
|
+
return None, errors
|
|
620
|
+
|
|
621
|
+
return sequence, None
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
def _generate_xs_group_for_class(
|
|
625
|
+
cls: intermediate.ClassUnion,
|
|
626
|
+
constraints_by_property: infer_for_schema.ConstraintsByProperty,
|
|
627
|
+
) -> Tuple[Optional[ET.Element], Optional[Error]]:
|
|
628
|
+
"""Generate the ``xs:group`` representation of the class properties."""
|
|
629
|
+
properties, properties_errors = _define_properties(
|
|
630
|
+
cls=cls, constraints_by_property=constraints_by_property
|
|
631
|
+
)
|
|
632
|
+
|
|
633
|
+
if properties_errors is not None:
|
|
634
|
+
return None, Error(
|
|
635
|
+
cls.parsed.node,
|
|
636
|
+
f"Failed to generate xs:group for the class {cls.name!r}",
|
|
637
|
+
properties_errors,
|
|
638
|
+
)
|
|
639
|
+
|
|
640
|
+
assert properties is not None
|
|
641
|
+
|
|
642
|
+
xs_sequence = ET.Element("xs:sequence")
|
|
643
|
+
for inheritance in cls.inheritances:
|
|
644
|
+
inheritance_xs_group = ET.Element(
|
|
645
|
+
"xs:group", {"ref": xsd_naming.group_name(inheritance.name)}
|
|
646
|
+
)
|
|
647
|
+
xs_sequence.append(inheritance_xs_group)
|
|
648
|
+
|
|
649
|
+
xs_sequence.extend(properties)
|
|
650
|
+
|
|
651
|
+
xs_group = ET.Element("xs:group", {"name": xsd_naming.group_name(cls.name)})
|
|
652
|
+
xs_group.append(xs_sequence)
|
|
653
|
+
|
|
654
|
+
return xs_group, None
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
658
|
+
def _define_for_class(
|
|
659
|
+
cls: intermediate.ClassUnion,
|
|
660
|
+
constraints_by_property: infer_for_schema.ConstraintsByProperty,
|
|
661
|
+
) -> Tuple[Optional[List[ET.Element]], Optional[Error]]:
|
|
662
|
+
"""
|
|
663
|
+
Generate the definitions for the class ``cls``.
|
|
664
|
+
|
|
665
|
+
The root element is to be *extended* with the resulting list.
|
|
666
|
+
"""
|
|
667
|
+
# NOTE (mristin, 2022-03-30):
|
|
668
|
+
# We define each set of properties in a group. Then we reference these groups
|
|
669
|
+
# among the complex types.
|
|
670
|
+
# See: https://stackoverflow.com/questions/1198755/xml-schemas-with-multiple-inheritance
|
|
671
|
+
|
|
672
|
+
xs_group, xs_group_error = _generate_xs_group_for_class(
|
|
673
|
+
cls=cls, constraints_by_property=constraints_by_property
|
|
674
|
+
)
|
|
675
|
+
if xs_group_error is not None:
|
|
676
|
+
return None, xs_group_error
|
|
677
|
+
|
|
678
|
+
assert xs_group is not None
|
|
679
|
+
|
|
680
|
+
xs_group_ref = ET.Element("xs:group", {"ref": xsd_naming.group_name(cls.name)})
|
|
681
|
+
|
|
682
|
+
xs_sequence = ET.Element("xs:sequence")
|
|
683
|
+
xs_sequence.append(xs_group_ref)
|
|
684
|
+
|
|
685
|
+
complex_type = ET.Element(
|
|
686
|
+
"xs:complexType", {"name": xsd_naming.type_name(cls.name)}
|
|
687
|
+
)
|
|
688
|
+
complex_type.append(xs_sequence)
|
|
689
|
+
|
|
690
|
+
return [xs_group, complex_type], None
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
@require(lambda cls: len(cls.concrete_descendants) > 0)
|
|
694
|
+
def _generate_choice_group(cls: intermediate.ClassUnion) -> ET.Element:
|
|
695
|
+
"""Generate a group that defines a choice of concrete descendants."""
|
|
696
|
+
xs_choice = ET.Element("xs:choice")
|
|
697
|
+
|
|
698
|
+
if isinstance(cls, intermediate.ConcreteClass):
|
|
699
|
+
xs_choice.append(
|
|
700
|
+
ET.Element(
|
|
701
|
+
"xs:element",
|
|
702
|
+
{
|
|
703
|
+
"name": naming.xml_class_name(cls.name),
|
|
704
|
+
"type": xsd_naming.type_name(cls.name),
|
|
705
|
+
},
|
|
706
|
+
)
|
|
707
|
+
)
|
|
708
|
+
|
|
709
|
+
for descendant in cls.concrete_descendants:
|
|
710
|
+
xs_choice.append(
|
|
711
|
+
ET.Element(
|
|
712
|
+
"xs:element",
|
|
713
|
+
{
|
|
714
|
+
"name": naming.xml_class_name(descendant.name),
|
|
715
|
+
"type": xsd_naming.type_name(descendant.name),
|
|
716
|
+
},
|
|
717
|
+
)
|
|
718
|
+
)
|
|
719
|
+
|
|
720
|
+
xs_group = ET.Element("xs:group", {"name": xsd_naming.choice_group_name(cls.name)})
|
|
721
|
+
xs_group.append(xs_choice)
|
|
722
|
+
return xs_group
|
|
723
|
+
|
|
724
|
+
|
|
725
|
+
_WHITESPACE_RE = re.compile(r"\s+")
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
729
|
+
def _retrieve_implementation_specific_elements(
|
|
730
|
+
cls: intermediate.ClassUnion,
|
|
731
|
+
spec_impls: specific_implementations.SpecificImplementations,
|
|
732
|
+
) -> Tuple[Optional[List[ET.Element]], Optional[List[Error]]]:
|
|
733
|
+
"""Parse the elements from the implementation-specific snippet."""
|
|
734
|
+
implementation_key = specific_implementations.ImplementationKey(f"{cls.name}.xml")
|
|
735
|
+
|
|
736
|
+
text = spec_impls.get(implementation_key, None)
|
|
737
|
+
if text is None:
|
|
738
|
+
return None, [
|
|
739
|
+
Error(
|
|
740
|
+
cls.parsed.node,
|
|
741
|
+
f"The implementation is missing "
|
|
742
|
+
f"for the implementation-specific class: {implementation_key}",
|
|
743
|
+
)
|
|
744
|
+
]
|
|
745
|
+
|
|
746
|
+
implementation_root: ET.Element
|
|
747
|
+
|
|
748
|
+
try:
|
|
749
|
+
implementation_root = ET.fromstring(text)
|
|
750
|
+
except Exception as err:
|
|
751
|
+
return None, [
|
|
752
|
+
Error(
|
|
753
|
+
cls.parsed.node,
|
|
754
|
+
f"Failed to parse the XML out of "
|
|
755
|
+
f"the specific implementation {implementation_key}: {err}",
|
|
756
|
+
)
|
|
757
|
+
]
|
|
758
|
+
|
|
759
|
+
errors = [] # type: List[Error]
|
|
760
|
+
for descendant in implementation_root.iter():
|
|
761
|
+
if descendant.text is not None and not _WHITESPACE_RE.fullmatch(
|
|
762
|
+
descendant.text
|
|
763
|
+
):
|
|
764
|
+
errors.append(
|
|
765
|
+
Error(
|
|
766
|
+
cls.parsed.node,
|
|
767
|
+
f"Unexpected text "
|
|
768
|
+
f"in the specific implementation {implementation_key} "
|
|
769
|
+
f"in an element with tag {descendant.tag!r}: {descendant.text!r}",
|
|
770
|
+
)
|
|
771
|
+
)
|
|
772
|
+
continue
|
|
773
|
+
|
|
774
|
+
if descendant.tail is not None and not _WHITESPACE_RE.fullmatch(
|
|
775
|
+
descendant.tail
|
|
776
|
+
):
|
|
777
|
+
errors.append(
|
|
778
|
+
Error(
|
|
779
|
+
cls.parsed.node,
|
|
780
|
+
f"Unexpected tail text "
|
|
781
|
+
f"in the specific implementation {implementation_key} "
|
|
782
|
+
f"in an element with tag {descendant.tag!r}: {descendant.tail!r}",
|
|
783
|
+
)
|
|
784
|
+
)
|
|
785
|
+
continue
|
|
786
|
+
|
|
787
|
+
if len(errors) > 0:
|
|
788
|
+
return None, errors
|
|
789
|
+
|
|
790
|
+
# Ignore the implementation root since it defines a partial schema
|
|
791
|
+
elements = [] # type: List[ET.Element]
|
|
792
|
+
for child in implementation_root:
|
|
793
|
+
elements.append(child)
|
|
794
|
+
|
|
795
|
+
return elements, None
|
|
796
|
+
|
|
797
|
+
|
|
798
|
+
def _sort_by_tags_and_names_in_place(root: ET.Element) -> None:
|
|
799
|
+
"""
|
|
800
|
+
Sort the children elements by tag and name attribute in place.
|
|
801
|
+
|
|
802
|
+
This makes diffing and searching in the schema a bit easier.
|
|
803
|
+
"""
|
|
804
|
+
groups = [] # type: List[ET.Element]
|
|
805
|
+
simple_types = [] # type: List[ET.Element]
|
|
806
|
+
complex_types = [] # type: List[ET.Element]
|
|
807
|
+
miscellaneous = [] # type: List[ET.Element]
|
|
808
|
+
elements = [] # type: List[ET.Element]
|
|
809
|
+
|
|
810
|
+
for child in root:
|
|
811
|
+
if child.tag == "xs:group":
|
|
812
|
+
groups.append(child)
|
|
813
|
+
elif child.tag == "xs:simpleType":
|
|
814
|
+
simple_types.append(child)
|
|
815
|
+
elif child.tag == "xs:complexType":
|
|
816
|
+
complex_types.append(child)
|
|
817
|
+
elif child.tag == "xs:element":
|
|
818
|
+
elements.append(child)
|
|
819
|
+
else:
|
|
820
|
+
miscellaneous.append(child)
|
|
821
|
+
|
|
822
|
+
for element_list in [groups, simple_types, complex_types, miscellaneous, elements]:
|
|
823
|
+
element_list.sort(key=lambda elt: elt.attrib.get("name", ""))
|
|
824
|
+
|
|
825
|
+
children = groups + simple_types + complex_types + elements + miscellaneous
|
|
826
|
+
|
|
827
|
+
assert len(children) == len(root)
|
|
828
|
+
root[:] = children
|
|
829
|
+
|
|
830
|
+
|
|
831
|
+
_EXPLANATION_ABOUT_WHY_WE_EXPECT_VALUE_DATA_TYPE = (
|
|
832
|
+
"(mristin, 2022-09-02) "
|
|
833
|
+
'We provide an internal data type ``valueDataType`` to correspond to "any XSD '
|
|
834
|
+
'atomic type as specified via DataTypeDefXsd". We need this type since we '
|
|
835
|
+
"hard-wire ``Value_data_type`` to it. We could have made "
|
|
836
|
+
"the class ``Value_data_type``implementation-specific and defined its "
|
|
837
|
+
"representation manually as a snippet, including ``valueDataType``.\n\n"
|
|
838
|
+
"However, we decided against that. This would be a major hurdle for "
|
|
839
|
+
"other code and test data generators (which can treat ``Value_data_type`` "
|
|
840
|
+
"simply as string). Therefore, we make the XSD generator "
|
|
841
|
+
"a bit more hacky instead of complicating the other generators.\n\n"
|
|
842
|
+
"If in the future, for whatever reason, the semantic of ``Value_data_type`` "
|
|
843
|
+
"changes (or the type is renamed), be careful to maintain backwards "
|
|
844
|
+
"compatibility here! You probably want to distinguish different versions "
|
|
845
|
+
"of the meta-model and act accordingly. At that point, it might also make "
|
|
846
|
+
"sense to refactor this schema generator to a separate repository, and "
|
|
847
|
+
"fix it to a particular range of meta-model versions."
|
|
848
|
+
)
|
|
849
|
+
|
|
850
|
+
|
|
851
|
+
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
|
|
852
|
+
def _generate(
|
|
853
|
+
symbol_table: intermediate.SymbolTable,
|
|
854
|
+
spec_impls: specific_implementations.SpecificImplementations,
|
|
855
|
+
) -> Tuple[Optional[str], Optional[List[Error]]]:
|
|
856
|
+
"""Generate the XML Schema Definition (XSD) based on the ``symbol_table."""
|
|
857
|
+
root_element_key = specific_implementations.ImplementationKey("root_element.xml")
|
|
858
|
+
|
|
859
|
+
root_element_as_text = spec_impls.get(root_element_key, None)
|
|
860
|
+
if root_element_as_text is None:
|
|
861
|
+
return None, [
|
|
862
|
+
Error(
|
|
863
|
+
None,
|
|
864
|
+
f"The implementation snippet for the root element "
|
|
865
|
+
f"is missing: {root_element_key}",
|
|
866
|
+
)
|
|
867
|
+
]
|
|
868
|
+
|
|
869
|
+
root: ET.Element
|
|
870
|
+
try:
|
|
871
|
+
root = ET.fromstring(root_element_as_text)
|
|
872
|
+
except ET.ParseError as err:
|
|
873
|
+
return None, [
|
|
874
|
+
Error(
|
|
875
|
+
None, f"Failed to parse the root element from {root_element_key}: {err}"
|
|
876
|
+
)
|
|
877
|
+
]
|
|
878
|
+
|
|
879
|
+
# NOTE (mristin, 2022-03-30):
|
|
880
|
+
# We need to use minidom to extract the ``xmlns`` property as ElementTree removes
|
|
881
|
+
# it.
|
|
882
|
+
# noinspection PyUnresolvedReferences
|
|
883
|
+
minidom_doc = xml.dom.minidom.parseString(root_element_as_text)
|
|
884
|
+
|
|
885
|
+
if not minidom_doc.documentElement.hasAttribute("xmlns"):
|
|
886
|
+
return None, [
|
|
887
|
+
Error(
|
|
888
|
+
None,
|
|
889
|
+
f"The implementation snippet for the root element "
|
|
890
|
+
f"is missing the 'xmlns' attribute: {root_element_key}",
|
|
891
|
+
)
|
|
892
|
+
]
|
|
893
|
+
|
|
894
|
+
xmlns = minidom_doc.documentElement.getAttribute("xmlns")
|
|
895
|
+
|
|
896
|
+
if xmlns != symbol_table.meta_model.xml_namespace:
|
|
897
|
+
return None, [
|
|
898
|
+
Error(
|
|
899
|
+
None,
|
|
900
|
+
f"The 'xmlns' attribute of the implementation snippet "
|
|
901
|
+
f"{root_element_key} for the root element "
|
|
902
|
+
f"and the '__xml_namespace__' of the meta-model "
|
|
903
|
+
f"do not coincide: "
|
|
904
|
+
f"{xmlns!r} != {symbol_table.meta_model.xml_namespace!r}",
|
|
905
|
+
)
|
|
906
|
+
]
|
|
907
|
+
|
|
908
|
+
if not minidom_doc.documentElement.hasAttribute("targetNamespace"):
|
|
909
|
+
return None, [
|
|
910
|
+
Error(
|
|
911
|
+
None,
|
|
912
|
+
f"The implementation snippet for the root element "
|
|
913
|
+
f"is missing the 'targetNamespace' attribute: {root_element_key}",
|
|
914
|
+
)
|
|
915
|
+
]
|
|
916
|
+
|
|
917
|
+
target_namespace = minidom_doc.documentElement.getAttribute("targetNamespace")
|
|
918
|
+
if target_namespace != symbol_table.meta_model.xml_namespace:
|
|
919
|
+
return None, [
|
|
920
|
+
Error(
|
|
921
|
+
None,
|
|
922
|
+
f"The 'targetNamespace' attribute of the implementation snippet "
|
|
923
|
+
f"{root_element_key} for the root element "
|
|
924
|
+
f"and the '__xml_namespace__' of the meta-model "
|
|
925
|
+
f"do not coincide: "
|
|
926
|
+
f"{target_namespace!r} != {symbol_table.meta_model.xml_namespace!r}",
|
|
927
|
+
)
|
|
928
|
+
]
|
|
929
|
+
|
|
930
|
+
assert root is not None
|
|
931
|
+
|
|
932
|
+
errors = [] # type: List[Error]
|
|
933
|
+
|
|
934
|
+
# NOTE (mristin, 2022-04-09):
|
|
935
|
+
# We remove any whitespace tail and text in all the tags, and make sure there is no
|
|
936
|
+
# unexpected text anywhere.
|
|
937
|
+
for element in root.iter():
|
|
938
|
+
if element.text is not None:
|
|
939
|
+
if _WHITESPACE_RE.fullmatch(element.text):
|
|
940
|
+
element.text = None
|
|
941
|
+
else:
|
|
942
|
+
errors.append(
|
|
943
|
+
Error(
|
|
944
|
+
None,
|
|
945
|
+
f"Unexpected text in an element with tag {element.tag!r} "
|
|
946
|
+
f"from the snippet {root_element_key!r}: {element.text!r}",
|
|
947
|
+
)
|
|
948
|
+
)
|
|
949
|
+
|
|
950
|
+
if element.tail is not None:
|
|
951
|
+
if _WHITESPACE_RE.fullmatch(element.tail):
|
|
952
|
+
element.tail = None
|
|
953
|
+
else:
|
|
954
|
+
errors.append(
|
|
955
|
+
Error(
|
|
956
|
+
None,
|
|
957
|
+
f"Unexpected tail in an element with tag {element.tag!r} "
|
|
958
|
+
f"from the snippet {root_element_key!r}: {element.tail!r}",
|
|
959
|
+
)
|
|
960
|
+
)
|
|
961
|
+
|
|
962
|
+
if len(errors) > 0:
|
|
963
|
+
return None, errors
|
|
964
|
+
|
|
965
|
+
constraints_by_class, some_errors = infer_for_schema.infer_constraints_by_class(
|
|
966
|
+
symbol_table=symbol_table
|
|
967
|
+
)
|
|
968
|
+
|
|
969
|
+
if some_errors is not None:
|
|
970
|
+
errors.extend(some_errors)
|
|
971
|
+
|
|
972
|
+
# NOTE (mristin, 2022-11-10):
|
|
973
|
+
# Please see :py:const:`_EXPLANATION_ABOUT_WHY_WE_EXPECT_VALUE_DATA_TYPE` for
|
|
974
|
+
# the explanation why we retrieve the ``Value_data_type`` here
|
|
975
|
+
value_data_type_cls = symbol_table.find_our_type(Identifier("Value_data_type"))
|
|
976
|
+
|
|
977
|
+
if value_data_type_cls is None:
|
|
978
|
+
errors.append(
|
|
979
|
+
Error(
|
|
980
|
+
None,
|
|
981
|
+
"XSD generator expected to find our type ``Value_data_type``, but it "
|
|
982
|
+
"was not present in the meta-model.\n\n"
|
|
983
|
+
+ _EXPLANATION_ABOUT_WHY_WE_EXPECT_VALUE_DATA_TYPE,
|
|
984
|
+
)
|
|
985
|
+
)
|
|
986
|
+
elif not isinstance(value_data_type_cls, intermediate.ConstrainedPrimitive):
|
|
987
|
+
errors.append(
|
|
988
|
+
Error(
|
|
989
|
+
None,
|
|
990
|
+
"XSD generator expected ``Value_data_type`` to be "
|
|
991
|
+
"a constrained primitive, but got: {type(value_data_type_cls)}.\n\n"
|
|
992
|
+
+ _EXPLANATION_ABOUT_WHY_WE_EXPECT_VALUE_DATA_TYPE,
|
|
993
|
+
)
|
|
994
|
+
)
|
|
995
|
+
elif value_data_type_cls.constrainee != intermediate.PrimitiveType.STR:
|
|
996
|
+
errors.append(
|
|
997
|
+
Error(
|
|
998
|
+
None,
|
|
999
|
+
f"XSD generator expected ``Value_data_type`` to be a constrained "
|
|
1000
|
+
f"primitive of strings, "
|
|
1001
|
+
f"but got: {value_data_type_cls.constrainee}.\n\n"
|
|
1002
|
+
+ _EXPLANATION_ABOUT_WHY_WE_EXPECT_VALUE_DATA_TYPE,
|
|
1003
|
+
)
|
|
1004
|
+
)
|
|
1005
|
+
else:
|
|
1006
|
+
# Our type ``Value_data_type`` is as expected.
|
|
1007
|
+
pass
|
|
1008
|
+
|
|
1009
|
+
if len(errors) > 0:
|
|
1010
|
+
return None, errors
|
|
1011
|
+
|
|
1012
|
+
assert constraints_by_class is not None
|
|
1013
|
+
|
|
1014
|
+
ids_of_our_types_in_properties = (
|
|
1015
|
+
intermediate.collect_ids_of_our_types_in_properties(symbol_table=symbol_table)
|
|
1016
|
+
)
|
|
1017
|
+
|
|
1018
|
+
# region Specify ``valueDataType``
|
|
1019
|
+
|
|
1020
|
+
assert value_data_type_cls is not None
|
|
1021
|
+
|
|
1022
|
+
value_data_type_element = ET.Element(
|
|
1023
|
+
"xs:simpleType", attrib={"name": "valueDataType"}
|
|
1024
|
+
)
|
|
1025
|
+
|
|
1026
|
+
value_data_type_element.append(
|
|
1027
|
+
ET.Element(
|
|
1028
|
+
"xs:restriction",
|
|
1029
|
+
attrib={"base": "xs:string"},
|
|
1030
|
+
)
|
|
1031
|
+
)
|
|
1032
|
+
|
|
1033
|
+
root.append(value_data_type_element)
|
|
1034
|
+
|
|
1035
|
+
# endregion
|
|
1036
|
+
|
|
1037
|
+
for our_type in symbol_table.our_types:
|
|
1038
|
+
if our_type.name == "Value_data_type":
|
|
1039
|
+
# NOTE (mristin, 2022-11-10):
|
|
1040
|
+
# Please see :py:const:`_EXPLANATION_ABOUT_WHY_WE_EXPECT_VALUE_DATA_TYPE`
|
|
1041
|
+
# for the explanation why we hard-wire the ``Value_data_type`` here
|
|
1042
|
+
continue
|
|
1043
|
+
|
|
1044
|
+
elements: Optional[List[ET.Element]]
|
|
1045
|
+
|
|
1046
|
+
if (
|
|
1047
|
+
isinstance(
|
|
1048
|
+
our_type, (intermediate.AbstractClass, intermediate.ConcreteClass)
|
|
1049
|
+
)
|
|
1050
|
+
and our_type.is_implementation_specific
|
|
1051
|
+
):
|
|
1052
|
+
elements, impl_spec_errors = _retrieve_implementation_specific_elements(
|
|
1053
|
+
cls=our_type, spec_impls=spec_impls
|
|
1054
|
+
)
|
|
1055
|
+
if impl_spec_errors is not None:
|
|
1056
|
+
errors.extend(impl_spec_errors)
|
|
1057
|
+
continue
|
|
1058
|
+
|
|
1059
|
+
assert elements is not None
|
|
1060
|
+
else:
|
|
1061
|
+
if isinstance(our_type, intermediate.Enumeration):
|
|
1062
|
+
if id(our_type) not in ids_of_our_types_in_properties:
|
|
1063
|
+
continue
|
|
1064
|
+
|
|
1065
|
+
elements = _define_for_enumeration(enumeration=our_type)
|
|
1066
|
+
|
|
1067
|
+
elif isinstance(our_type, intermediate.ConstrainedPrimitive):
|
|
1068
|
+
# NOTE (mristin, 2022-03-30):
|
|
1069
|
+
# We in-line the constraints from the constrained primitives directly
|
|
1070
|
+
# in the properties. We do not want to introduce separate definitions
|
|
1071
|
+
# for them as that would make it more difficult for downstream code
|
|
1072
|
+
# generators to generate meaningful code.
|
|
1073
|
+
|
|
1074
|
+
continue
|
|
1075
|
+
|
|
1076
|
+
elif isinstance(
|
|
1077
|
+
our_type, (intermediate.AbstractClass, intermediate.ConcreteClass)
|
|
1078
|
+
):
|
|
1079
|
+
elements, definition_error = _define_for_class(
|
|
1080
|
+
cls=our_type, constraints_by_property=constraints_by_class[our_type]
|
|
1081
|
+
)
|
|
1082
|
+
|
|
1083
|
+
if definition_error is not None:
|
|
1084
|
+
errors.append(definition_error)
|
|
1085
|
+
continue
|
|
1086
|
+
|
|
1087
|
+
assert elements is not None
|
|
1088
|
+
|
|
1089
|
+
if len(our_type.concrete_descendants) > 0:
|
|
1090
|
+
choice_group = _generate_choice_group(cls=our_type)
|
|
1091
|
+
elements.append(choice_group)
|
|
1092
|
+
else:
|
|
1093
|
+
assert_never(our_type)
|
|
1094
|
+
|
|
1095
|
+
assert elements is not None
|
|
1096
|
+
root.extend(elements)
|
|
1097
|
+
|
|
1098
|
+
if len(errors) > 0:
|
|
1099
|
+
return None, errors
|
|
1100
|
+
|
|
1101
|
+
# Tag name 🠒 (name 🠒 element)
|
|
1102
|
+
observed_definitions = dict(
|
|
1103
|
+
dict()
|
|
1104
|
+
) # type: MutableMapping[str, MutableMapping[str, ET.Element]]
|
|
1105
|
+
|
|
1106
|
+
for element in root:
|
|
1107
|
+
name = element.attrib.get("name", None)
|
|
1108
|
+
if name is None:
|
|
1109
|
+
continue
|
|
1110
|
+
|
|
1111
|
+
observed_for_tag = observed_definitions.get(element.tag, None)
|
|
1112
|
+
if observed_for_tag is None:
|
|
1113
|
+
observed_for_tag = dict()
|
|
1114
|
+
observed_definitions[element.tag] = observed_for_tag
|
|
1115
|
+
|
|
1116
|
+
observed_element = observed_for_tag.get(name, None)
|
|
1117
|
+
if observed_element is not None:
|
|
1118
|
+
ours = ET.tostring(element, encoding="unicode", method="xml")
|
|
1119
|
+
theirs = ET.tostring(observed_element, encoding="unicode", method="xml")
|
|
1120
|
+
|
|
1121
|
+
errors.append(
|
|
1122
|
+
Error(
|
|
1123
|
+
None,
|
|
1124
|
+
f"There are conflicting definitions in the schema "
|
|
1125
|
+
f"with the name {name!r}:\n"
|
|
1126
|
+
f"\n"
|
|
1127
|
+
f"{ours}\n"
|
|
1128
|
+
f"\n"
|
|
1129
|
+
f"and\n"
|
|
1130
|
+
f"\n"
|
|
1131
|
+
f"{theirs}",
|
|
1132
|
+
)
|
|
1133
|
+
)
|
|
1134
|
+
else:
|
|
1135
|
+
observed_for_tag[name] = element
|
|
1136
|
+
|
|
1137
|
+
if len(errors) > 0:
|
|
1138
|
+
return None, errors
|
|
1139
|
+
|
|
1140
|
+
_sort_by_tags_and_names_in_place(root)
|
|
1141
|
+
|
|
1142
|
+
# NOTE (mristin, 2022-03-30):
|
|
1143
|
+
# For some unknown reason, ElementTree erases the xmlns property of the root
|
|
1144
|
+
# element. Therefore, we need to add it here manually.
|
|
1145
|
+
root.attrib["xmlns"] = xmlns
|
|
1146
|
+
|
|
1147
|
+
text = ET.tostring(root, encoding="unicode", method="xml")
|
|
1148
|
+
|
|
1149
|
+
# NOTE (mristin, 2021-11-23):
|
|
1150
|
+
# This approach is slow, but effective. As long as the meta-model is not too big,
|
|
1151
|
+
# this should work.
|
|
1152
|
+
# noinspection PyUnresolvedReferences
|
|
1153
|
+
pretty_text = xml.dom.minidom.parseString(text).toprettyxml(indent=" ")
|
|
1154
|
+
|
|
1155
|
+
return pretty_text, None
|
|
1156
|
+
|
|
1157
|
+
|
|
1158
|
+
def execute(context: run.Context, stdout: TextIO, stderr: TextIO) -> int:
|
|
1159
|
+
"""Generate the code."""
|
|
1160
|
+
code, errors = _generate(
|
|
1161
|
+
symbol_table=context.symbol_table, spec_impls=context.spec_impls
|
|
1162
|
+
)
|
|
1163
|
+
|
|
1164
|
+
if errors is not None:
|
|
1165
|
+
run.write_error_report(
|
|
1166
|
+
message=f"Failed to generate the XML Schema Definition "
|
|
1167
|
+
f"based on {context.model_path}",
|
|
1168
|
+
errors=[context.lineno_columner.error_message(error) for error in errors],
|
|
1169
|
+
stderr=stderr,
|
|
1170
|
+
)
|
|
1171
|
+
return 1
|
|
1172
|
+
|
|
1173
|
+
assert code is not None
|
|
1174
|
+
|
|
1175
|
+
pth = context.output_dir / "schema.xsd"
|
|
1176
|
+
try:
|
|
1177
|
+
pth.write_text(code, encoding="utf-8")
|
|
1178
|
+
except Exception as exception:
|
|
1179
|
+
run.write_error_report(
|
|
1180
|
+
message=f"Failed to write the XML Schema Definition to {pth}",
|
|
1181
|
+
errors=[str(exception)],
|
|
1182
|
+
stderr=stderr,
|
|
1183
|
+
)
|
|
1184
|
+
return 1
|
|
1185
|
+
|
|
1186
|
+
stdout.write(f"Code generated to: {context.output_dir}\n")
|
|
1187
|
+
return 0
|