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.
Files changed (604) hide show
  1. aas_core_codegen/__init__.py +6 -0
  2. aas_core_codegen/__main__.py +8 -0
  3. aas_core_codegen/common.py +500 -0
  4. aas_core_codegen/cpp/__init__.py +1 -0
  5. aas_core_codegen/cpp/aas_common/__init__.py +6 -0
  6. aas_core_codegen/cpp/aas_common/_generate.py +713 -0
  7. aas_core_codegen/cpp/common.py +681 -0
  8. aas_core_codegen/cpp/constants/__init__.py +6 -0
  9. aas_core_codegen/cpp/constants/_generate.py +568 -0
  10. aas_core_codegen/cpp/description.py +654 -0
  11. aas_core_codegen/cpp/enhancing/__init__.py +4 -0
  12. aas_core_codegen/cpp/enhancing/_generate.py +993 -0
  13. aas_core_codegen/cpp/iteration/__init__.py +6 -0
  14. aas_core_codegen/cpp/iteration/_generate.py +2332 -0
  15. aas_core_codegen/cpp/jsonization/__init__.py +6 -0
  16. aas_core_codegen/cpp/jsonization/_generate.py +2619 -0
  17. aas_core_codegen/cpp/main.py +694 -0
  18. aas_core_codegen/cpp/naming.py +170 -0
  19. aas_core_codegen/cpp/optionaling.py +557 -0
  20. aas_core_codegen/cpp/pattern/__init__.py +6 -0
  21. aas_core_codegen/cpp/pattern/_generate.py +508 -0
  22. aas_core_codegen/cpp/revm/__init__.py +6 -0
  23. aas_core_codegen/cpp/revm/_generate.py +1149 -0
  24. aas_core_codegen/cpp/stringification/__init__.py +5 -0
  25. aas_core_codegen/cpp/stringification/_generate.py +955 -0
  26. aas_core_codegen/cpp/structure/__init__.py +7 -0
  27. aas_core_codegen/cpp/structure/_generate.py +1503 -0
  28. aas_core_codegen/cpp/transpilation.py +1383 -0
  29. aas_core_codegen/cpp/unrolling.py +159 -0
  30. aas_core_codegen/cpp/verification/__init__.py +6 -0
  31. aas_core_codegen/cpp/verification/_generate.py +3073 -0
  32. aas_core_codegen/cpp/visitation/__init__.py +6 -0
  33. aas_core_codegen/cpp/visitation/_generate.py +521 -0
  34. aas_core_codegen/cpp/wstringification/__init__.py +5 -0
  35. aas_core_codegen/cpp/wstringification/_generate.py +586 -0
  36. aas_core_codegen/cpp/xmlization/__init__.py +6 -0
  37. aas_core_codegen/cpp/xmlization/_generate.py +5373 -0
  38. aas_core_codegen/cpp/yielding.py +201 -0
  39. aas_core_codegen/csharp/__init__.py +1 -0
  40. aas_core_codegen/csharp/common.py +224 -0
  41. aas_core_codegen/csharp/constants/__init__.py +5 -0
  42. aas_core_codegen/csharp/constants/_generate.py +409 -0
  43. aas_core_codegen/csharp/copying/__init__.py +4 -0
  44. aas_core_codegen/csharp/copying/_generate.py +498 -0
  45. aas_core_codegen/csharp/description.py +1103 -0
  46. aas_core_codegen/csharp/enhancing/__init__.py +4 -0
  47. aas_core_codegen/csharp/enhancing/_generate.py +667 -0
  48. aas_core_codegen/csharp/jsonization/__init__.py +4 -0
  49. aas_core_codegen/csharp/jsonization/_generate.py +1630 -0
  50. aas_core_codegen/csharp/main.py +421 -0
  51. aas_core_codegen/csharp/naming.py +157 -0
  52. aas_core_codegen/csharp/reporting/__init__.py +4 -0
  53. aas_core_codegen/csharp/reporting/_generate.py +266 -0
  54. aas_core_codegen/csharp/stringification/__init__.py +4 -0
  55. aas_core_codegen/csharp/stringification/_generate.py +243 -0
  56. aas_core_codegen/csharp/structure/__init__.py +6 -0
  57. aas_core_codegen/csharp/structure/_generate.py +1341 -0
  58. aas_core_codegen/csharp/transpilation.py +990 -0
  59. aas_core_codegen/csharp/unrolling.py +211 -0
  60. aas_core_codegen/csharp/verification/__init__.py +6 -0
  61. aas_core_codegen/csharp/verification/_generate.py +1457 -0
  62. aas_core_codegen/csharp/visitation/__init__.py +5 -0
  63. aas_core_codegen/csharp/visitation/_generate.py +579 -0
  64. aas_core_codegen/csharp/xmlization/__init__.py +4 -0
  65. aas_core_codegen/csharp/xmlization/_generate.py +1980 -0
  66. aas_core_codegen/golang/__init__.py +1 -0
  67. aas_core_codegen/golang/aas_common/__init__.py +4 -0
  68. aas_core_codegen/golang/aas_common/_generate.py +152 -0
  69. aas_core_codegen/golang/common.py +303 -0
  70. aas_core_codegen/golang/constants/__init__.py +5 -0
  71. aas_core_codegen/golang/constants/_generate.py +339 -0
  72. aas_core_codegen/golang/description.py +501 -0
  73. aas_core_codegen/golang/enhancing/__init__.py +4 -0
  74. aas_core_codegen/golang/enhancing/_generate.py +527 -0
  75. aas_core_codegen/golang/jsonization/__init__.py +4 -0
  76. aas_core_codegen/golang/jsonization/_generate.py +1740 -0
  77. aas_core_codegen/golang/main.py +368 -0
  78. aas_core_codegen/golang/naming.py +412 -0
  79. aas_core_codegen/golang/pointering.py +631 -0
  80. aas_core_codegen/golang/reporting/__init__.py +4 -0
  81. aas_core_codegen/golang/reporting/_generate.py +218 -0
  82. aas_core_codegen/golang/stringification/__init__.py +4 -0
  83. aas_core_codegen/golang/stringification/_generate.py +394 -0
  84. aas_core_codegen/golang/structure/__init__.py +6 -0
  85. aas_core_codegen/golang/structure/_generate.py +1493 -0
  86. aas_core_codegen/golang/transpilation.py +1191 -0
  87. aas_core_codegen/golang/unrolling.py +159 -0
  88. aas_core_codegen/golang/verification/__init__.py +6 -0
  89. aas_core_codegen/golang/verification/_generate.py +1513 -0
  90. aas_core_codegen/golang/xmlization/__init__.py +4 -0
  91. aas_core_codegen/golang/xmlization/_generate.py +2507 -0
  92. aas_core_codegen/infer_for_schema/__init__.py +21 -0
  93. aas_core_codegen/infer_for_schema/_inline.py +693 -0
  94. aas_core_codegen/infer_for_schema/_len.py +527 -0
  95. aas_core_codegen/infer_for_schema/_pattern.py +311 -0
  96. aas_core_codegen/infer_for_schema/_set.py +394 -0
  97. aas_core_codegen/infer_for_schema/_stringify.py +201 -0
  98. aas_core_codegen/infer_for_schema/_types.py +135 -0
  99. aas_core_codegen/infer_for_schema/match.py +122 -0
  100. aas_core_codegen/intermediate/__init__.py +78 -0
  101. aas_core_codegen/intermediate/_hierarchy.py +397 -0
  102. aas_core_codegen/intermediate/_stringify.py +989 -0
  103. aas_core_codegen/intermediate/_translate.py +5128 -0
  104. aas_core_codegen/intermediate/_types.py +2901 -0
  105. aas_core_codegen/intermediate/construction.py +750 -0
  106. aas_core_codegen/intermediate/doc.py +344 -0
  107. aas_core_codegen/intermediate/pattern_verification.py +428 -0
  108. aas_core_codegen/intermediate/revm.py +985 -0
  109. aas_core_codegen/intermediate/type_inference.py +2266 -0
  110. aas_core_codegen/java/__init__.py +1 -0
  111. aas_core_codegen/java/common.py +197 -0
  112. aas_core_codegen/java/constants/__init__.py +5 -0
  113. aas_core_codegen/java/constants/_generate.py +334 -0
  114. aas_core_codegen/java/copying/__init__.py +4 -0
  115. aas_core_codegen/java/copying/_generate.py +502 -0
  116. aas_core_codegen/java/description.py +774 -0
  117. aas_core_codegen/java/enhancing/__init__.py +4 -0
  118. aas_core_codegen/java/enhancing/_generate.py +820 -0
  119. aas_core_codegen/java/generation/__init__.py +5 -0
  120. aas_core_codegen/java/generation/_generate.py +285 -0
  121. aas_core_codegen/java/jsonization/__init__.py +4 -0
  122. aas_core_codegen/java/jsonization/_generate.py +1472 -0
  123. aas_core_codegen/java/main.py +438 -0
  124. aas_core_codegen/java/naming.py +187 -0
  125. aas_core_codegen/java/optional.py +514 -0
  126. aas_core_codegen/java/reporting/__init__.py +4 -0
  127. aas_core_codegen/java/reporting/_generate.py +248 -0
  128. aas_core_codegen/java/stringification/__init__.py +4 -0
  129. aas_core_codegen/java/stringification/_generate.py +212 -0
  130. aas_core_codegen/java/structure/__init__.py +6 -0
  131. aas_core_codegen/java/structure/_generate.py +1767 -0
  132. aas_core_codegen/java/transpilation.py +1111 -0
  133. aas_core_codegen/java/verification/__init__.py +6 -0
  134. aas_core_codegen/java/verification/_generate.py +1536 -0
  135. aas_core_codegen/java/visitation/__init__.py +5 -0
  136. aas_core_codegen/java/visitation/_generate.py +689 -0
  137. aas_core_codegen/java/xmlization/__init__.py +4 -0
  138. aas_core_codegen/java/xmlization/_generate.py +2274 -0
  139. aas_core_codegen/jsonld/__init__.py +1 -0
  140. aas_core_codegen/jsonld/main.py +455 -0
  141. aas_core_codegen/jsonschema/__init__.py +1 -0
  142. aas_core_codegen/jsonschema/main.py +982 -0
  143. aas_core_codegen/main.py +245 -0
  144. aas_core_codegen/naming.py +133 -0
  145. aas_core_codegen/opcua/__init__.py +1 -0
  146. aas_core_codegen/opcua/main.py +1525 -0
  147. aas_core_codegen/opcua/naming.py +126 -0
  148. aas_core_codegen/parse/__init__.py +46 -0
  149. aas_core_codegen/parse/_rules.py +796 -0
  150. aas_core_codegen/parse/_stringify.py +532 -0
  151. aas_core_codegen/parse/_translate.py +3940 -0
  152. aas_core_codegen/parse/_types.py +973 -0
  153. aas_core_codegen/parse/retree/__init__.py +46 -0
  154. aas_core_codegen/parse/retree/_fix.py +434 -0
  155. aas_core_codegen/parse/retree/_parse.py +1143 -0
  156. aas_core_codegen/parse/retree/_render.py +298 -0
  157. aas_core_codegen/parse/retree/_stringify.py +199 -0
  158. aas_core_codegen/parse/retree/_types.py +362 -0
  159. aas_core_codegen/parse/retree/_visitor.py +70 -0
  160. aas_core_codegen/parse/tree.py +1303 -0
  161. aas_core_codegen/protobuf/__init__.py +1 -0
  162. aas_core_codegen/protobuf/common.py +225 -0
  163. aas_core_codegen/protobuf/description.py +1102 -0
  164. aas_core_codegen/protobuf/main.py +115 -0
  165. aas_core_codegen/protobuf/naming.py +143 -0
  166. aas_core_codegen/protobuf/structure/__init__.py +6 -0
  167. aas_core_codegen/protobuf/structure/_generate.py +502 -0
  168. aas_core_codegen/py.typed +1 -0
  169. aas_core_codegen/python/__init__.py +1 -0
  170. aas_core_codegen/python/aas_common/__init__.py +4 -0
  171. aas_core_codegen/python/aas_common/_generate.py +63 -0
  172. aas_core_codegen/python/common.py +406 -0
  173. aas_core_codegen/python/constants/__init__.py +5 -0
  174. aas_core_codegen/python/constants/_generate.py +377 -0
  175. aas_core_codegen/python/description.py +508 -0
  176. aas_core_codegen/python/jsonization/__init__.py +4 -0
  177. aas_core_codegen/python/jsonization/_generate.py +1391 -0
  178. aas_core_codegen/python/main.py +323 -0
  179. aas_core_codegen/python/naming.py +255 -0
  180. aas_core_codegen/python/stringification/__init__.py +4 -0
  181. aas_core_codegen/python/stringification/_generate.py +129 -0
  182. aas_core_codegen/python/structure/__init__.py +6 -0
  183. aas_core_codegen/python/structure/_generate.py +1801 -0
  184. aas_core_codegen/python/transpilation.py +958 -0
  185. aas_core_codegen/python/unrolling.py +156 -0
  186. aas_core_codegen/python/verification/__init__.py +6 -0
  187. aas_core_codegen/python/verification/_generate.py +1471 -0
  188. aas_core_codegen/python/xmlization/__init__.py +4 -0
  189. aas_core_codegen/python/xmlization/_generate.py +3003 -0
  190. aas_core_codegen/python_protobuf/__init__.py +1 -0
  191. aas_core_codegen/python_protobuf/main.py +1424 -0
  192. aas_core_codegen/python_protobuf/naming.py +85 -0
  193. aas_core_codegen/rdf_shacl/__init__.py +1 -0
  194. aas_core_codegen/rdf_shacl/_description.py +351 -0
  195. aas_core_codegen/rdf_shacl/common.py +206 -0
  196. aas_core_codegen/rdf_shacl/main.py +114 -0
  197. aas_core_codegen/rdf_shacl/naming.py +145 -0
  198. aas_core_codegen/rdf_shacl/rdf.py +435 -0
  199. aas_core_codegen/rdf_shacl/shacl.py +453 -0
  200. aas_core_codegen/run.py +124 -0
  201. aas_core_codegen/smoke/__init__.py +1 -0
  202. aas_core_codegen/smoke/main.py +219 -0
  203. aas_core_codegen/specific_implementations.py +72 -0
  204. aas_core_codegen/stringify.py +333 -0
  205. aas_core_codegen/typescript/__init__.py +1 -0
  206. aas_core_codegen/typescript/aas_common/__init__.py +4 -0
  207. aas_core_codegen/typescript/aas_common/_generate.py +472 -0
  208. aas_core_codegen/typescript/common.py +340 -0
  209. aas_core_codegen/typescript/constants/__init__.py +5 -0
  210. aas_core_codegen/typescript/constants/_generate.py +347 -0
  211. aas_core_codegen/typescript/description.py +530 -0
  212. aas_core_codegen/typescript/jsonization/__init__.py +4 -0
  213. aas_core_codegen/typescript/jsonization/_generate.py +1510 -0
  214. aas_core_codegen/typescript/main.py +258 -0
  215. aas_core_codegen/typescript/naming.py +189 -0
  216. aas_core_codegen/typescript/stringification/__init__.py +4 -0
  217. aas_core_codegen/typescript/stringification/_generate.py +367 -0
  218. aas_core_codegen/typescript/structure/__init__.py +6 -0
  219. aas_core_codegen/typescript/structure/_generate.py +2500 -0
  220. aas_core_codegen/typescript/transpilation.py +1051 -0
  221. aas_core_codegen/typescript/unrolling.py +159 -0
  222. aas_core_codegen/typescript/verification/__init__.py +6 -0
  223. aas_core_codegen/typescript/verification/_generate.py +1578 -0
  224. aas_core_codegen/xsd/__init__.py +1 -0
  225. aas_core_codegen/xsd/main.py +1187 -0
  226. aas_core_codegen/xsd/naming.py +83 -0
  227. aas_core_codegen/yielding/__init__.py +1 -0
  228. aas_core_codegen/yielding/flow.py +139 -0
  229. aas_core_codegen/yielding/linear.py +754 -0
  230. aas_core_codegen-0.0.16.dist-info/METADATA +211 -0
  231. aas_core_codegen-0.0.16.dist-info/RECORD +604 -0
  232. aas_core_codegen-0.0.16.dist-info/WHEEL +5 -0
  233. aas_core_codegen-0.0.16.dist-info/entry_points.txt +3 -0
  234. aas_core_codegen-0.0.16.dist-info/licenses/AUTHORS +9 -0
  235. aas_core_codegen-0.0.16.dist-info/licenses/LICENSE +23 -0
  236. aas_core_codegen-0.0.16.dist-info/top_level.txt +2 -0
  237. dev/continuous_integration/__init__.py +1 -0
  238. dev/continuous_integration/check_help_in_readme.py +208 -0
  239. dev/continuous_integration/check_init_and_pyproject_consistent.py +154 -0
  240. dev/continuous_integration/precommit.py +400 -0
  241. dev/dev_scripts/__init__.py +1 -0
  242. dev/dev_scripts/compare_rendered_regexes_against_source_py.py +42 -0
  243. dev/dev_scripts/copy_to_aas_core3_cpp.py +100 -0
  244. dev/dev_scripts/copy_to_aas_core3_java.py +90 -0
  245. dev/dev_scripts/download_latest_aas_core_meta_v3.py +114 -0
  246. dev/dev_scripts/draw_bipartite_graph_based_on_lines.py +37 -0
  247. dev/dev_scripts/run_tests_with_rerecord.py +69 -0
  248. dev/dev_scripts/update_to_aas_core_meta.py +174 -0
  249. dev/integration_tests/input/jsonschema/boilerplate/main.py +55 -0
  250. dev/integration_tests/input/meta_model.py +38 -0
  251. dev/integration_tests/input/python/boilerplate/main.py +153 -0
  252. dev/integration_tests/main.py +258 -0
  253. dev/test_data/csharp/test_structure/concrete_class_with_descendants/meta_model.py +15 -0
  254. dev/test_data/csharp/test_structure/constructor_without_arguments/all_properties_optional/meta_model.py +9 -0
  255. dev/test_data/csharp/test_structure/constructor_without_arguments/no_properties/meta_model.py +6 -0
  256. dev/test_data/csharp/test_verification/builtin_functions/len/on_list/meta_model.py +20 -0
  257. dev/test_data/csharp/test_verification/builtin_functions/len/on_str/meta_model.py +16 -0
  258. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/as_prefix/meta_model.py +8 -0
  259. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/as_suffix/meta_model.py +8 -0
  260. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_group_with_quantifier/meta_model.py +8 -0
  261. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_the_middle/meta_model.py +8 -0
  262. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/in_union/meta_model.py +8 -0
  263. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/single_utf32_literal/meta_model.py +8 -0
  264. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/with_quantifier_within_group/meta_model.py +8 -0
  265. dev/test_data/csharp/test_verification/pattern_verification/utf32_as_literal/with_quantifier_without_group/meta_model.py +8 -0
  266. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/at_the_beginning/meta_model.py +8 -0
  267. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/at_the_end/meta_model.py +8 -0
  268. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/in_the_middle/meta_model.py +8 -0
  269. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/multiple/meta_model.py +8 -0
  270. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/single/meta_model.py +8 -0
  271. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/literal/single_with_quantifier/meta_model.py +8 -0
  272. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/mixed_with_non_utf32/meta_model.py +8 -0
  273. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/more_than_two_high_surrogates/meta_model.py +8 -0
  274. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/multiple_utf32_ranges/meta_model.py +8 -0
  275. 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
  276. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/same_high_surrogate/meta_model.py +8 -0
  277. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/same_high_surrogate_with_quantifier/meta_model.py +8 -0
  278. dev/test_data/csharp/test_verification/pattern_verification/utf32_in_character_set/range/two_high_surrogates/meta_model.py +8 -0
  279. dev/test_data/intermediate/expected/class/empty/meta_model.py +6 -0
  280. dev/test_data/intermediate/expected/class/implementation_specific_method/meta_model.py +8 -0
  281. dev/test_data/intermediate/expected/class/inheritance/meta_model.py +41 -0
  282. dev/test_data/intermediate/expected/class/methods_with_contracts/meta_model.py +15 -0
  283. dev/test_data/intermediate/expected/class/only_method_no_property/meta_model.py +7 -0
  284. dev/test_data/intermediate/expected/class/only_property_no_method/meta_model.py +9 -0
  285. dev/test_data/intermediate/expected/constant/constant_set/of_enum/meta_model.py +12 -0
  286. dev/test_data/intermediate/expected/constant/constant_set/of_str/meta_model.py +4 -0
  287. dev/test_data/intermediate/expected/constant/constant_set/with_description/meta_model.py +6 -0
  288. dev/test_data/intermediate/expected/constant/constant_set/with_superset_of/meta_model.py +14 -0
  289. dev/test_data/intermediate/expected/constant/constant_str/only_value/meta_model.py +7 -0
  290. dev/test_data/intermediate/expected/constant/constant_str/with_description/meta_model.py +5 -0
  291. dev/test_data/intermediate/expected/documentation/docstring_with_special_characters_in_literal/meta_model.py +20 -0
  292. dev/test_data/intermediate/expected/documentation/docstring_with_special_characters_outside_literal/meta_model.py +20 -0
  293. dev/test_data/intermediate/expected/empty/meta_model.py +2 -0
  294. dev/test_data/intermediate/expected/enumeration/meta_model.py +9 -0
  295. dev/test_data/intermediate/expected/interface/basic/meta_model.py +14 -0
  296. dev/test_data/intermediate/expected/interface/empty/meta_model.py +7 -0
  297. dev/test_data/intermediate/expected/interface/inheritance/meta_model.py +27 -0
  298. dev/test_data/intermediate/expected/interface/method_signature/meta_model.py +10 -0
  299. dev/test_data/intermediate/expected/interface/only_constructor/meta_model.py +11 -0
  300. dev/test_data/intermediate/expected/method/non_mutating/implementation_specific/meta_model.py +12 -0
  301. dev/test_data/intermediate/expected/method/non_mutating/understood/meta_model.py +11 -0
  302. dev/test_data/intermediate/expected/type_annotation/atomic/meta_model.py +9 -0
  303. dev/test_data/intermediate/expected/type_annotation/subscripted/class/meta_model.py +13 -0
  304. dev/test_data/intermediate/expected/type_annotation/subscripted/primitive/meta_model.py +9 -0
  305. dev/test_data/intermediate/unexpected/constant_set/of_enum/enumeration_literals_in_subset_outside_of_superset/meta_model.py +20 -0
  306. dev/test_data/intermediate/unexpected/constant_set/of_enum/invalid_literal/meta_model.py +11 -0
  307. dev/test_data/intermediate/unexpected/constant_set/of_enum/mismatch_between_enumeration_and_literal/meta_model.py +30 -0
  308. dev/test_data/intermediate/unexpected/constant_set/of_enum/mismatch_in_enumerations_between_subset_and_superset/meta_model.py +21 -0
  309. dev/test_data/intermediate/unexpected/constant_set/of_str/literals_in_subset_outside_of_superset/meta_model.py +18 -0
  310. dev/test_data/intermediate/unexpected/constant_set/of_str/mismatch_between_type_annotation_and_literals/meta_model.py +10 -0
  311. dev/test_data/intermediate/unexpected/constant_set/of_str/superset_and_subset_mismatch_in_type/meta_model.py +12 -0
  312. dev/test_data/intermediate/unexpected/constraints/dangling_constraintref/meta_model.py +18 -0
  313. dev/test_data/intermediate/unexpected/constraints/duplicate_constraints/meta_model.py +20 -0
  314. dev/test_data/intermediate/unexpected/documentation/unexpected_documentation_elements/meta_model.py +34 -0
  315. dev/test_data/intermediate/unexpected/invariant/class_invariant_uses_re/meta_model.py +10 -0
  316. dev/test_data/intermediate/unexpected/invariant/invariant_of_constrained_primitive_uses_re/meta_model.py +7 -0
  317. dev/test_data/intermediate/unexpected/invariant/unexpected_argument_count_to_len/meta_model.py +20 -0
  318. dev/test_data/intermediate/unexpected/invariant/unhandled_built_in_function/meta_model.py +16 -0
  319. dev/test_data/intermediate/unexpected/method_definitions/non_constant_default/meta_model.py +7 -0
  320. dev/test_data/intermediate/unexpected/optional_constructor_arguments_wo_default/default_non_none/meta_model.py +16 -0
  321. dev/test_data/intermediate/unexpected/optional_constructor_arguments_wo_default/no_default/meta_model.py +16 -0
  322. dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/after_inheritance/meta_model.py +58 -0
  323. dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/type_missmatch/meta_model.py +9 -0
  324. dev/test_data/intermediate/unexpected/properties_and_constructor_arguments_do_not_match/within_class/meta_model.py +22 -0
  325. dev/test_data/jsonschema/test_main/regression_when_len_constraints_on_inherited_property/meta_model.py +28 -0
  326. dev/test_data/opcua/test_main/abstract_and_concrete_classes/meta_model.py +37 -0
  327. dev/test_data/opcua/test_main/classes_with_invariants/meta_model.py +21 -0
  328. dev/test_data/opcua/test_main/concrete_class_with_descendant/meta_model.py +27 -0
  329. dev/test_data/opcua/test_main/concrete_class_with_enum/meta_model.py +21 -0
  330. dev/test_data/opcua/test_main/concrete_class_with_list_of_instances/meta_model.py +21 -0
  331. dev/test_data/opcua/test_main/concrete_class_with_primitive_attributes/meta_model.py +41 -0
  332. dev/test_data/opcua/test_main/concrete_class_with_string/meta_model.py +13 -0
  333. dev/test_data/opcua/test_main/constrained_primitive/meta_model.py +20 -0
  334. dev/test_data/opcua/test_main/multiple_inheritance/meta_model.py +25 -0
  335. dev/test_data/parse/expected/constant/constant_set/of_enum/meta_model.py +12 -0
  336. dev/test_data/parse/expected/constant/constant_set/of_str/meta_model.py +4 -0
  337. dev/test_data/parse/expected/constant/constant_set/with_description/meta_model.py +6 -0
  338. dev/test_data/parse/expected/constant/constant_set/with_superset_of/meta_model.py +14 -0
  339. dev/test_data/parse/expected/constant/constant_str/only_value/meta_model.py +7 -0
  340. dev/test_data/parse/expected/constant/constant_str/with_description/meta_model.py +5 -0
  341. dev/test_data/parse/expected/enum/ok/meta_model.py +15 -0
  342. dev/test_data/parse/expected/implementation_specific_class/properties_and_methods_in_implementation_specific_class/meta_model.py +17 -0
  343. dev/test_data/parse/expected/inheritance/basic/meta_model.py +11 -0
  344. dev/test_data/parse/expected/inheritance/diamond/meta_model.py +26 -0
  345. dev/test_data/parse/expected/inheritance/inheritance_from_concrete_class/meta_model.py +10 -0
  346. dev/test_data/parse/expected/invariants/in_relation/meta_model.py +16 -0
  347. dev/test_data/parse/expected/method/arguments/meta_model.py +7 -0
  348. dev/test_data/parse/expected/method/basic/meta_model.py +7 -0
  349. dev/test_data/parse/expected/method/contracts/condition_as_keyword_argument/meta_model.py +8 -0
  350. dev/test_data/parse/expected/method/contracts/condition_as_positional_argument/meta_model.py +8 -0
  351. dev/test_data/parse/expected/method/contracts/description_as_keyword_argument/meta_model.py +8 -0
  352. dev/test_data/parse/expected/method/contracts/description_as_positional_argument/meta_model.py +8 -0
  353. dev/test_data/parse/expected/method/contracts/multiple_contracts_in_order/meta_model.py +17 -0
  354. dev/test_data/parse/expected/method/contracts/postcondition/basic/meta_model.py +10 -0
  355. dev/test_data/parse/expected/method/contracts/postcondition/snapshot/with_keyword_arguments/meta_model.py +9 -0
  356. dev/test_data/parse/expected/method/contracts/postcondition/snapshot/with_positional_arguments/meta_model.py +9 -0
  357. dev/test_data/parse/expected/method/default/meta_model.py +9 -0
  358. dev/test_data/parse/expected/method/description/meta_model.py +8 -0
  359. dev/test_data/parse/expected/method/is_implementation_specific/meta_model.py +8 -0
  360. dev/test_data/parse/expected/method/non_mutating/meta_model.py +11 -0
  361. dev/test_data/parse/expected/method/returns_none/meta_model.py +7 -0
  362. dev/test_data/parse/expected/method/returns_something/meta_model.py +7 -0
  363. dev/test_data/parse/expected/single_class/description/meta_model.py +12 -0
  364. dev/test_data/parse/expected/single_class/empty/meta_model.py +6 -0
  365. dev/test_data/parse/expected/single_class/property/description/meta_model.py +14 -0
  366. dev/test_data/parse/expected/single_class/property/mandatory/meta_model.py +6 -0
  367. dev/test_data/parse/expected/single_class/property/optional/meta_model.py +6 -0
  368. dev/test_data/parse/expected/single_class/property/recursion_to_entity/meta_model.py +6 -0
  369. dev/test_data/parse/unexpected/class_decorators/non_name_decorator/meta_model.py +7 -0
  370. dev/test_data/parse/unexpected/class_decorators/unknown_decorator/meta_model.py +7 -0
  371. dev/test_data/parse/unexpected/class_definitions/is_abstract_and_implementation_specific/meta_model.py +8 -0
  372. dev/test_data/parse/unexpected/class_definitions/unexpected_docstring_before_a_method/meta_model.py +11 -0
  373. dev/test_data/parse/unexpected/class_definitions/unexpected_docstring_for_a_pass/meta_model.py +9 -0
  374. dev/test_data/parse/unexpected/class_definitions/unexpected_double_description_for_a_property/meta_model.py +10 -0
  375. dev/test_data/parse/unexpected/class_inheritances/inheriting_from_implementation_specific_parent/meta_model.py +20 -0
  376. dev/test_data/parse/unexpected/class_inheritances/non_name_super_class/meta_model.py +6 -0
  377. dev/test_data/parse/unexpected/enum/expression_as_assignment_value/meta_model.py +6 -0
  378. dev/test_data/parse/unexpected/enum/non_assignment/meta_model.py +8 -0
  379. dev/test_data/parse/unexpected/enum/non_string_literal/meta_model.py +6 -0
  380. dev/test_data/parse/unexpected/enum/unexpected_inheritance/meta_model.py +6 -0
  381. dev/test_data/parse/unexpected/method_contracts/contract/non_lambda_condition/meta_model.py +8 -0
  382. dev/test_data/parse/unexpected/method_contracts/contract/non_string_literal_description/meta_model.py +8 -0
  383. dev/test_data/parse/unexpected/method_contracts/contract/without_any_arguments/meta_model.py +8 -0
  384. dev/test_data/parse/unexpected/method_contracts/contract/without_condition/meta_model.py +8 -0
  385. dev/test_data/parse/unexpected/method_contracts/postcondition/OLD_in_postcondition_without_snapshot/meta_model.py +8 -0
  386. dev/test_data/parse/unexpected/method_contracts/postcondition/argument_missing_in_function/meta_model.py +8 -0
  387. dev/test_data/parse/unexpected/method_contracts/precondition/argument_missing_in_function/meta_model.py +8 -0
  388. dev/test_data/parse/unexpected/method_contracts/snapshot/argument_missing_in_function/meta_model.py +8 -0
  389. dev/test_data/parse/unexpected/method_contracts/snapshot/capture_not_a_lambda/meta_model.py +8 -0
  390. dev/test_data/parse/unexpected/method_contracts/snapshot/invalid_name/meta_model.py +8 -0
  391. dev/test_data/parse/unexpected/method_contracts/snapshot/name_not_a_string_literal/meta_model.py +8 -0
  392. dev/test_data/parse/unexpected/method_contracts/snapshot/without_a_capture/meta_model.py +8 -0
  393. dev/test_data/parse/unexpected/method_contracts/snapshot/without_a_name/meta_model.py +8 -0
  394. dev/test_data/parse/unexpected/method_decorators/non_mutating/non_mutating_constructor/meta_model.py +8 -0
  395. dev/test_data/parse/unexpected/method_decorators/non_mutating/non_mutating_verification_function/meta_model.py +8 -0
  396. dev/test_data/parse/unexpected/method_decorators/non_name_decorator/meta_model.py +8 -0
  397. dev/test_data/parse/unexpected/method_decorators/unknown_call_decorator/meta_model.py +8 -0
  398. dev/test_data/parse/unexpected/method_decorators/unknown_name_decorator/meta_model.py +8 -0
  399. dev/test_data/parse/unexpected/method_definitions/argument_with_final/meta_model.py +7 -0
  400. dev/test_data/parse/unexpected/method_definitions/argument_without_a_type_annotation/meta_model.py +7 -0
  401. dev/test_data/parse/unexpected/method_definitions/default_for_self/meta_model.py +7 -0
  402. dev/test_data/parse/unexpected/method_definitions/dunder/meta_model.py +7 -0
  403. dev/test_data/parse/unexpected/method_definitions/init_with_return_type/meta_model.py +7 -0
  404. dev/test_data/parse/unexpected/method_definitions/with_keyword_only_arguments/meta_model.py +7 -0
  405. dev/test_data/parse/unexpected/method_definitions/with_positional_arguments/meta_model.py +7 -0
  406. dev/test_data/parse/unexpected/method_definitions/with_type_annotation_for_self/meta_model.py +7 -0
  407. dev/test_data/parse/unexpected/method_definitions/with_variable_arguments/meta_model.py +7 -0
  408. dev/test_data/parse/unexpected/method_definitions/with_variable_keyword_arguments/meta_model.py +7 -0
  409. dev/test_data/parse/unexpected/method_definitions/without_arguments/meta_model.py +7 -0
  410. dev/test_data/parse/unexpected/method_definitions/without_self/meta_model.py +7 -0
  411. dev/test_data/parse/unexpected/method_definitions/without_type_annotation_for_result/meta_model.py +7 -0
  412. dev/test_data/parse/unexpected/property_definitions/final_without_subscript/meta_model.py +6 -0
  413. dev/test_data/parse/unexpected/property_definitions/nested_final/meta_model.py +6 -0
  414. dev/test_data/parse/unexpected/property_definitions/non_simple/meta_model.py +6 -0
  415. dev/test_data/parse/unexpected/property_definitions/unexpected_assignment/meta_model.py +6 -0
  416. dev/test_data/parse/unexpected/property_definitions/unexpected_non_name_property/meta_model.py +6 -0
  417. dev/test_data/parse/unexpected/property_definitions/without_type_annotation/meta_model.py +6 -0
  418. dev/test_data/parse/unexpected/symbol_table/constant_set_with_a_non_set_subset/meta_model.py +6 -0
  419. dev/test_data/parse/unexpected/symbol_table/dangling_inheritance/meta_model.py +6 -0
  420. dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_a_property/meta_model.py +6 -0
  421. dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_an_argument/meta_model.py +7 -0
  422. dev/test_data/parse/unexpected/symbol_table/dangling_reference_in_type_annotation_of_constant_set/meta_model.py +6 -0
  423. dev/test_data/parse/unexpected/symbol_table/dangling_subset_in_constant_set/meta_model.py +4 -0
  424. dev/test_data/parse/unexpected/symbol_table/inheritance_from_non_class/meta_model.py +10 -0
  425. dev/test_data/parse_retree/expected/character_set/common_escaping/source.py +1 -0
  426. dev/test_data/parse_retree/expected/character_set/complementing/double_caret/source.py +1 -0
  427. dev/test_data/parse_retree/expected/character_set/complementing/multiple_ranges/source.py +1 -0
  428. dev/test_data/parse_retree/expected/character_set/complementing/suffix_dash/source.py +1 -0
  429. dev/test_data/parse_retree/expected/character_set/escape_first_caret/source.py +1 -0
  430. dev/test_data/parse_retree/expected/character_set/literals_which_need_no_escaping_in_characters_set_but_need_escaping_outside/source.py +1 -0
  431. dev/test_data/parse_retree/expected/character_set/multiple_ranges/source.py +1 -0
  432. dev/test_data/parse_retree/expected/character_set/single_literal/source.py +1 -0
  433. dev/test_data/parse_retree/expected/character_set/single_range/source.py +1 -0
  434. dev/test_data/parse_retree/expected/character_set/unescaped_dash/only_dash/source.py +1 -0
  435. dev/test_data/parse_retree/expected/character_set/unescaped_dash/prefix_dash/source.py +1 -0
  436. dev/test_data/parse_retree/expected/character_set/unescaped_dash/suffix_dash/source.py +1 -0
  437. dev/test_data/parse_retree/expected/dot/source.py +1 -0
  438. dev/test_data/parse_retree/expected/empty/group/source.py +1 -0
  439. dev/test_data/parse_retree/expected/empty/group_in_a_group/source.py +1 -0
  440. dev/test_data/parse_retree/expected/empty/group_of_union_of_empty_concatenations/source.py +1 -0
  441. dev/test_data/parse_retree/expected/empty/regex/source.py +1 -0
  442. dev/test_data/parse_retree/expected/empty/union_of_empty_concatenations/source.py +1 -0
  443. dev/test_data/parse_retree/expected/escaped_literals/source.py +1 -0
  444. dev/test_data/parse_retree/expected/formatted_value/at_the_beginning/source.py +1 -0
  445. dev/test_data/parse_retree/expected/formatted_value/at_the_end/source.py +1 -0
  446. dev/test_data/parse_retree/expected/formatted_value/in_the_middle/source.py +1 -0
  447. dev/test_data/parse_retree/expected/formatted_value/single_formatted_value/source.py +1 -0
  448. dev/test_data/parse_retree/expected/literal/source.py +1 -0
  449. dev/test_data/parse_retree/expected/quantifier/greedy/at_least_3/source.py +1 -0
  450. dev/test_data/parse_retree/expected/quantifier/greedy/at_least_one/source.py +1 -0
  451. dev/test_data/parse_retree/expected/quantifier/greedy/at_most_3/source.py +1 -0
  452. dev/test_data/parse_retree/expected/quantifier/greedy/exactly_3/source.py +1 -0
  453. dev/test_data/parse_retree/expected/quantifier/greedy/maybe/source.py +1 -0
  454. dev/test_data/parse_retree/expected/quantifier/greedy/zero_or_more/source.py +1 -0
  455. dev/test_data/parse_retree/expected/quantifier/non_greedy/at_least_3/source.py +1 -0
  456. dev/test_data/parse_retree/expected/quantifier/non_greedy/at_least_one/source.py +1 -0
  457. dev/test_data/parse_retree/expected/quantifier/non_greedy/at_most_3/source.py +1 -0
  458. dev/test_data/parse_retree/expected/quantifier/non_greedy/exactly_3/source.py +1 -0
  459. dev/test_data/parse_retree/expected/quantifier/non_greedy/maybe/source.py +1 -0
  460. dev/test_data/parse_retree/expected/quantifier/non_greedy/zero_or_more/source.py +1 -0
  461. dev/test_data/parse_retree/expected/quantifier/on_a_character_set/source.py +1 -0
  462. dev/test_data/parse_retree/expected/quantifier/on_a_formatted_value/source.py +1 -0
  463. dev/test_data/parse_retree/expected/quantifier/on_a_group/source.py +1 -0
  464. dev/test_data/parse_retree/expected/quantifier/on_a_literal/source.py +1 -0
  465. dev/test_data/parse_retree/expected/start_and_stop_symbols/double_end_symbol/source.py +1 -0
  466. dev/test_data/parse_retree/expected/start_and_stop_symbols/double_start_symbol/source.py +1 -0
  467. dev/test_data/parse_retree/expected/start_and_stop_symbols/end_symbol_in_the_middle/source.py +1 -0
  468. dev/test_data/parse_retree/expected/start_and_stop_symbols/only_start_symbol/source.py +1 -0
  469. dev/test_data/parse_retree/expected/start_and_stop_symbols/only_stop_symbol/source.py +1 -0
  470. dev/test_data/parse_retree/expected/start_and_stop_symbols/start_symbol_at_the_beginning/source.py +1 -0
  471. dev/test_data/parse_retree/expected/start_and_stop_symbols/start_symbol_in_the_middle/source.py +1 -0
  472. dev/test_data/parse_retree/expected/start_and_stop_symbols/stop_symbol_at_the_end/source.py +1 -0
  473. dev/test_data/parse_retree/expected/union/of_character_sets/source.py +1 -0
  474. dev/test_data/parse_retree/expected/union/of_groups/source.py +1 -0
  475. dev/test_data/parse_retree/expected/union/of_string_literals/source.py +1 -0
  476. dev/test_data/parse_retree/expected/union/within_group/source.py +1 -0
  477. dev/test_data/parse_retree/expected/whitespace/source.py +1 -0
  478. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/Uxxxxxxxx_out_of_range/source.py +1 -0
  479. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/only_backslash/source.py +1 -0
  480. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_Uxxxxxxxx/source.py +1 -0
  481. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_uxxxx/source.py +1 -0
  482. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/short_x/source.py +1 -0
  483. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unexpected_escaping/source.py +1 -0
  484. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/digit/source.py +1 -0
  485. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_digit/source.py +1 -0
  486. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_whitespace/source.py +1 -0
  487. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/not_word/source.py +1 -0
  488. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/whitespace/source.py +1 -0
  489. dev/test_data/parse_retree/unexpected/improper_escaping/character_literal/unhandled/word/source.py +1 -0
  490. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/Uxxxxxxxx_out_of_range/source.py +1 -0
  491. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/only_backslash/source.py +1 -0
  492. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_Uxxxxxxxx/source.py +1 -0
  493. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_uxxxx/source.py +1 -0
  494. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/short_x/source.py +1 -0
  495. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unexpected_escaping/source.py +1 -0
  496. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/digit/source.py +1 -0
  497. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_digit/source.py +1 -0
  498. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_whitespace/source.py +1 -0
  499. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/not_word/source.py +1 -0
  500. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/whitespace/source.py +1 -0
  501. dev/test_data/parse_retree/unexpected/improper_escaping/range_character/unhandled/word/source.py +1 -0
  502. dev/test_data/parse_retree/unexpected/invalid_character_range/source.py +1 -0
  503. dev/test_data/parse_retree/unexpected/invalid_quantifier/at_least_x/source.py +1 -0
  504. dev/test_data/parse_retree/unexpected/invalid_quantifier/between_3_and_x/source.py +1 -0
  505. dev/test_data/parse_retree/unexpected/invalid_quantifier/exactly_x/source.py +1 -0
  506. dev/test_data/parse_retree/unexpected/unhandled_group_directives/source.py +1 -0
  507. dev/test_data/parse_retree/unexpected/unterminated/character_set/source.py +1 -0
  508. dev/test_data/parse_retree/unexpected/unterminated/group/source.py +1 -0
  509. dev/test_data/parse_retree/unexpected/unterminated/group_of_union_of_empty_concatenations/source.py +1 -0
  510. dev/test_data/parse_retree/unexpected/unterminated/quantifier/source.py +1 -0
  511. dev/test_data/parse_retree/unexpected/unterminated/quantifier_with_comma/source.py +1 -0
  512. dev/test_data/parse_retree/unexpected/unterminated/quantifier_with_number_and_comma/source.py +1 -0
  513. dev/test_data/proto/test_main/expected/abstract_and_concrete_classes/meta_model.py +37 -0
  514. dev/test_data/proto/test_main/expected/concrete_class_with_descendants/meta_model.py +30 -0
  515. dev/test_data/proto/test_main/expected/concrete_class_with_enum/meta_model.py +21 -0
  516. dev/test_data/proto/test_main/expected/concrete_class_with_list_of_instances/meta_model.py +21 -0
  517. dev/test_data/proto/test_main/expected/concrete_class_with_primitive_attributes/meta_model.py +41 -0
  518. dev/test_data/python_protobuf/test_main/abstract_and_concrete_classes/expected_output/pbization.py +532 -0
  519. dev/test_data/python_protobuf/test_main/abstract_and_concrete_classes/meta_model.py +37 -0
  520. dev/test_data/python_protobuf/test_main/concrete_class_with_descendant/expected_output/pbization.py +527 -0
  521. dev/test_data/python_protobuf/test_main/concrete_class_with_descendant/meta_model.py +27 -0
  522. dev/test_data/python_protobuf/test_main/concrete_class_with_enum/expected_output/pbization.py +290 -0
  523. dev/test_data/python_protobuf/test_main/concrete_class_with_enum/meta_model.py +21 -0
  524. dev/test_data/python_protobuf/test_main/concrete_class_with_list_of_instances/expected_output/pbization.py +328 -0
  525. dev/test_data/python_protobuf/test_main/concrete_class_with_list_of_instances/meta_model.py +23 -0
  526. dev/test_data/python_protobuf/test_main/concrete_class_with_primitive_attributes/expected_output/pbization.py +274 -0
  527. dev/test_data/python_protobuf/test_main/concrete_class_with_primitive_attributes/meta_model.py +41 -0
  528. dev/test_data/rdf_shacl/test_main/expected/regression_when_lang_string_class_is_missing/meta_model.py +29 -0
  529. dev/test_data/rdf_shacl/test_main/expected/regression_when_len_constraints_on_inherited_property/meta_model.py +27 -0
  530. dev/test_data/rdf_shacl/test_main/unexpected/regression_len_constraint_on_class_property/meta_model.py +61 -0
  531. dev/test_data/real_meta_models/aas_core_meta.v3.py +5721 -0
  532. dev/test_data/smoke/test_main/unexpected/infer_for_schema_error/meta_model.py +12 -0
  533. dev/test_data/smoke/test_main/unexpected/intermediate_error/meta_model.py +18 -0
  534. dev/test_data/smoke/test_main/unexpected/parse_error/meta_model.py +5 -0
  535. dev/test_data/smoke/test_main/unexpected/pattern_verification_unparsable_regex/direct_match/meta_model.py +8 -0
  536. dev/test_data/smoke/test_main/unexpected/type_error/meta_model.py +18 -0
  537. dev/tests/__init__.py +1 -0
  538. dev/tests/common.py +197 -0
  539. dev/tests/cpp/__init__.py +0 -0
  540. dev/tests/cpp/test_common.py +32 -0
  541. dev/tests/cpp/test_main.py +144 -0
  542. dev/tests/cpp/test_pattern.py +188 -0
  543. dev/tests/cpp/test_verification.py +189 -0
  544. dev/tests/cpp/test_yielding.py +225 -0
  545. dev/tests/csharp/__init__.py +0 -0
  546. dev/tests/csharp/live_test_main.py +109 -0
  547. dev/tests/csharp/test_common.py +28 -0
  548. dev/tests/csharp/test_description.py +684 -0
  549. dev/tests/csharp/test_main.py +129 -0
  550. dev/tests/csharp/test_structure.py +93 -0
  551. dev/tests/csharp/test_verification.py +82 -0
  552. dev/tests/description.py +29 -0
  553. dev/tests/golang/__init__.py +0 -0
  554. dev/tests/golang/test_common.py +78 -0
  555. dev/tests/golang/test_main.py +128 -0
  556. dev/tests/infer_for_schema/__init__.py +0 -0
  557. dev/tests/infer_for_schema/common.py +47 -0
  558. dev/tests/infer_for_schema/test_len_on_properties.py +955 -0
  559. dev/tests/infer_for_schema/test_len_on_self.py +580 -0
  560. dev/tests/infer_for_schema/test_patterns_on_properties.py +686 -0
  561. dev/tests/infer_for_schema/test_patterns_on_self.py +258 -0
  562. dev/tests/infer_for_schema/test_property_in_set_of_enumeration_literals.py +600 -0
  563. dev/tests/infer_for_schema/test_property_in_set_of_primitives.py +549 -0
  564. dev/tests/intermediate/__init__.py +0 -0
  565. dev/tests/intermediate/test_constructor.py +719 -0
  566. dev/tests/intermediate/test_hierarchy.py +221 -0
  567. dev/tests/intermediate/test_revm.py +134 -0
  568. dev/tests/intermediate/test_translate.py +337 -0
  569. dev/tests/intermediate/test_type_inference.py +333 -0
  570. dev/tests/intermediate/test_types.py +169 -0
  571. dev/tests/java/__init__.py +0 -0
  572. dev/tests/java/test_common.py +20 -0
  573. dev/tests/java/test_description.py +128 -0
  574. dev/tests/java/test_main.py +234 -0
  575. dev/tests/jsonld_context/test_main.py +79 -0
  576. dev/tests/opcua/__init__.py +3 -0
  577. dev/tests/opcua/test_main.py +110 -0
  578. dev/tests/our_jsonschema/__init__.py +3 -0
  579. dev/tests/our_jsonschema/test_main.py +232 -0
  580. dev/tests/parse/__init__.py +0 -0
  581. dev/tests/parse/test_parse.py +503 -0
  582. dev/tests/parse/test_retree.py +272 -0
  583. dev/tests/proto/__init__.py +0 -0
  584. dev/tests/proto/test_main.py +112 -0
  585. dev/tests/python/__init__.py +0 -0
  586. dev/tests/python/test_common.py +124 -0
  587. dev/tests/python/test_main.py +126 -0
  588. dev/tests/python/test_xml_playground.py +254 -0
  589. dev/tests/python_protobuf/__init__.py +0 -0
  590. dev/tests/python_protobuf/test_main.py +111 -0
  591. dev/tests/rdf_shacl/__init__.py +0 -0
  592. dev/tests/rdf_shacl/test_common.py +32 -0
  593. dev/tests/rdf_shacl/test_description.py +223 -0
  594. dev/tests/rdf_shacl/test_main.py +194 -0
  595. dev/tests/smoke/__init__.py +0 -0
  596. dev/tests/smoke/test_main.py +83 -0
  597. dev/tests/test_common.py +94 -0
  598. dev/tests/typescript/__init__.py +0 -0
  599. dev/tests/typescript/test_common.py +108 -0
  600. dev/tests/typescript/test_main.py +125 -0
  601. dev/tests/xsd/__init__.py +0 -0
  602. dev/tests/xsd/test_main.py +227 -0
  603. dev/tests/yielding/__init__.py +0 -0
  604. 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