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,2901 @@
1
+ """Provide types of the intermediate representation."""
2
+ import abc
3
+ import enum
4
+ import pathlib
5
+ from typing import (
6
+ Sequence,
7
+ Optional,
8
+ Union,
9
+ TypeVar,
10
+ Mapping,
11
+ MutableMapping,
12
+ Final,
13
+ FrozenSet,
14
+ Set,
15
+ OrderedDict,
16
+ Type,
17
+ get_args,
18
+ )
19
+
20
+ import docutils.nodes
21
+ from icontract import require, invariant, ensure, DBC
22
+
23
+ from aas_core_codegen import parse
24
+ from aas_core_codegen.common import (
25
+ Identifier,
26
+ assert_never,
27
+ assert_union_of_descendants_exhaustive,
28
+ assert_union_without_excluded,
29
+ Stripped,
30
+ )
31
+ from aas_core_codegen.intermediate import construction
32
+ from aas_core_codegen.parse import tree as parse_tree
33
+
34
+ _MODULE_NAME = pathlib.Path(__file__).parent.name
35
+
36
+
37
+ class PrimitiveType(enum.Enum):
38
+ """List primitive types."""
39
+
40
+ BOOL = "bool"
41
+ INT = "int"
42
+ FLOAT = "float"
43
+ STR = "str"
44
+ BYTEARRAY = "bytearray"
45
+
46
+
47
+ assert sorted(literal.value for literal in PrimitiveType) == sorted(
48
+ parse.PRIMITIVE_TYPES
49
+ ), "All primitive types specified in the intermediate layer"
50
+
51
+ STR_TO_PRIMITIVE_TYPE = {
52
+ literal.value: literal for literal in PrimitiveType
53
+ } # type: Mapping[str, PrimitiveType]
54
+
55
+ # fmt: off
56
+ PRIMITIVE_TYPE_TO_PYTHON_TYPE: Mapping[
57
+ PrimitiveType,
58
+ Union[Type[bool], Type[int], Type[float], Type[str], Type[bytearray]]
59
+ ] = {
60
+ PrimitiveType.BOOL: bool,
61
+ PrimitiveType.INT : int,
62
+ PrimitiveType.FLOAT: float,
63
+ PrimitiveType.STR: str,
64
+ PrimitiveType.BYTEARRAY: bytearray,
65
+ }
66
+ assert all(
67
+ primitive_type in PRIMITIVE_TYPE_TO_PYTHON_TYPE
68
+ for primitive_type in PrimitiveType
69
+ )
70
+ # fmt: on
71
+
72
+ # fmt: off
73
+ PYTHON_TYPE_TO_PRIMITIVE_TYPE: Mapping[
74
+ Union[Type[bool], Type[int], Type[float], Type[str], Type[bytearray]],
75
+ PrimitiveType
76
+ ] = {
77
+ bool: PrimitiveType.BOOL,
78
+ int: PrimitiveType.INT,
79
+ float: PrimitiveType.FLOAT,
80
+ str: PrimitiveType.STR,
81
+ bytearray: PrimitiveType.BYTEARRAY,
82
+ }
83
+ assert (
84
+ sorted(key.__name__ for key in PYTHON_TYPE_TO_PRIMITIVE_TYPE) ==
85
+ sorted(value.__name__ for value in PRIMITIVE_TYPE_TO_PYTHON_TYPE.values())
86
+ )
87
+ # fmt: on
88
+
89
+
90
+ class TypeAnnotation(DBC):
91
+ """Represent a general type annotation."""
92
+
93
+ #: Relation to the parse stage
94
+ parsed: Final[parse.TypeAnnotation]
95
+
96
+ def __init__(self, parsed: parse.TypeAnnotation) -> None:
97
+ """Initialize with the given values."""
98
+ self.parsed = parsed
99
+
100
+ @abc.abstractmethod
101
+ def __str__(self) -> str:
102
+ # Signal that this class is a purely abstract one
103
+ raise NotImplementedError()
104
+
105
+
106
+ class PrimitiveTypeAnnotation(TypeAnnotation):
107
+ """Represent a primitive type such as ``int``."""
108
+
109
+ def __init__(self, a_type: PrimitiveType, parsed: parse.TypeAnnotation) -> None:
110
+ """Initialize with the given values."""
111
+ TypeAnnotation.__init__(self, parsed=parsed)
112
+ self.a_type = a_type
113
+
114
+ def __str__(self) -> str:
115
+ return str(self.a_type.value)
116
+
117
+
118
+ class OurTypeAnnotation(TypeAnnotation):
119
+ """
120
+ Represent an atomic annotation defined by our type in the meta-model.
121
+
122
+ For example, ``Asset``.
123
+ """
124
+
125
+ def __init__(self, our_type: "OurType", parsed: parse.TypeAnnotation) -> None:
126
+ """Initialize with the given values."""
127
+ TypeAnnotation.__init__(self, parsed=parsed)
128
+ self.our_type = our_type
129
+
130
+ def __str__(self) -> str:
131
+ return self.our_type.name
132
+
133
+
134
+ class ListTypeAnnotation(TypeAnnotation):
135
+ """Represent a type annotation involving a ``List[...]``."""
136
+
137
+ def __init__(self, items: "TypeAnnotationUnion", parsed: parse.TypeAnnotation):
138
+ TypeAnnotation.__init__(self, parsed=parsed)
139
+
140
+ self.items = items
141
+
142
+ def __str__(self) -> str:
143
+ return f"List[{self.items}]"
144
+
145
+
146
+ # NOTE (mristin, 2021-11-19):
147
+ # We do not support other generic types except for ``List``. In the future we might
148
+ # add support for ``Set``, ``MutableMapping`` *etc.*
149
+
150
+
151
+ class OptionalTypeAnnotation(TypeAnnotation):
152
+ """Represent a type annotation involving an ``Optional[...]``."""
153
+
154
+ def __init__(self, value: "TypeAnnotationUnion", parsed: parse.TypeAnnotation):
155
+ TypeAnnotation.__init__(self, parsed=parsed)
156
+
157
+ self.value = value
158
+
159
+ def __str__(self) -> str:
160
+ return f"Optional[{self.value}]"
161
+
162
+
163
+ TypeAnnotationUnion = Union[
164
+ PrimitiveTypeAnnotation,
165
+ OurTypeAnnotation,
166
+ ListTypeAnnotation,
167
+ OptionalTypeAnnotation,
168
+ ]
169
+
170
+ assert_union_of_descendants_exhaustive(
171
+ union=TypeAnnotationUnion, base_class=TypeAnnotation
172
+ )
173
+
174
+ TypeAnnotationUnionAsTuple = (
175
+ PrimitiveTypeAnnotation,
176
+ OurTypeAnnotation,
177
+ ListTypeAnnotation,
178
+ OptionalTypeAnnotation,
179
+ )
180
+
181
+ assert TypeAnnotationUnionAsTuple == get_args(TypeAnnotationUnion)
182
+
183
+ TypeAnnotationExceptOptional = Union[
184
+ PrimitiveTypeAnnotation,
185
+ OurTypeAnnotation,
186
+ ListTypeAnnotation,
187
+ ]
188
+
189
+ assert_union_without_excluded(
190
+ original_union=TypeAnnotationUnion,
191
+ subset_union=TypeAnnotationExceptOptional,
192
+ excluded=[OptionalTypeAnnotation],
193
+ )
194
+
195
+ TypeAnnotationExceptOptionalAsTuple = (
196
+ PrimitiveTypeAnnotation,
197
+ OurTypeAnnotation,
198
+ ListTypeAnnotation,
199
+ )
200
+ assert TypeAnnotationExceptOptionalAsTuple == get_args(TypeAnnotationExceptOptional)
201
+
202
+ AtomicTypeAnnotation = Union[PrimitiveTypeAnnotation, OurTypeAnnotation]
203
+
204
+ assert_union_without_excluded(
205
+ original_union=TypeAnnotationUnion,
206
+ subset_union=AtomicTypeAnnotation,
207
+ excluded=[ListTypeAnnotation, OptionalTypeAnnotation],
208
+ )
209
+
210
+
211
+ def type_annotations_equal(
212
+ that: TypeAnnotationUnion, other: TypeAnnotationUnion
213
+ ) -> bool:
214
+ """
215
+ Compare two type annotations for equality.
216
+
217
+ Two type annotations are equal if they describe the same type.
218
+ """
219
+ if type(that) is not type(other):
220
+ return False
221
+
222
+ if isinstance(that, PrimitiveTypeAnnotation):
223
+ assert isinstance(other, PrimitiveTypeAnnotation)
224
+ return that.a_type == other.a_type
225
+
226
+ elif isinstance(that, OurTypeAnnotation):
227
+ assert isinstance(other, OurTypeAnnotation)
228
+ return that.our_type == other.our_type
229
+
230
+ elif isinstance(that, ListTypeAnnotation):
231
+ assert isinstance(other, ListTypeAnnotation)
232
+ return type_annotations_equal(that.items, other.items)
233
+
234
+ elif isinstance(that, OptionalTypeAnnotation):
235
+ assert isinstance(other, OptionalTypeAnnotation)
236
+ return type_annotations_equal(that.value, other.value)
237
+
238
+ else:
239
+ assert_never(that)
240
+
241
+ raise AssertionError("Should not have gotten here")
242
+
243
+
244
+ def beneath_optional(
245
+ type_annotation: TypeAnnotationUnion,
246
+ ) -> TypeAnnotationExceptOptional:
247
+ """Descend below ``Optional[...]`` to the underlying type."""
248
+ type_anno = type_annotation
249
+ while isinstance(type_anno, OptionalTypeAnnotation):
250
+ type_anno = type_anno.value
251
+
252
+ assert not isinstance(type_anno, OptionalTypeAnnotation)
253
+
254
+ return type_anno
255
+
256
+
257
+ # region Descriptions
258
+
259
+ # NOTE (mristin, 2022-03-18):
260
+ # We take C# documentation comments as an orientation for the structure of the
261
+ # descriptions.
262
+
263
+
264
+ def find_first_field_list(
265
+ element: docutils.nodes.Element,
266
+ ) -> Optional[docutils.nodes.field_list]:
267
+ """Find the first field list beneath the element or return None."""
268
+ return next(element.findall(condition=docutils.nodes.field_list), None)
269
+
270
+
271
+ class SummaryRemarksDescription(DBC):
272
+ """Represent a description with a summary and remarks."""
273
+
274
+ #: Summary as the first line of the docstring
275
+ summary: Final[docutils.nodes.paragraph]
276
+
277
+ #: List of remarks following the summary in the docstring
278
+ remarks: Final[Sequence[docutils.nodes.Element]]
279
+
280
+ #: Original parsed description
281
+ parsed: Final[parse.Description]
282
+
283
+ # fmt: off
284
+ @require(
285
+ lambda summary:
286
+ find_first_field_list(summary) is None,
287
+ "Summary expected without field lists"
288
+ )
289
+ @require(
290
+ lambda remarks:
291
+ all(
292
+ find_first_field_list(remark) is None
293
+ for remark in remarks
294
+ ),
295
+ "Remarks expected without field lists"
296
+ )
297
+ # fmt: on
298
+ def __init__(
299
+ self,
300
+ summary: docutils.nodes.paragraph,
301
+ remarks: Sequence[docutils.nodes.Element],
302
+ parsed: parse.Description,
303
+ ) -> None:
304
+ """Initialize with the given values."""
305
+ self.summary = summary
306
+ self.remarks = remarks
307
+ self.parsed = parsed
308
+
309
+ @abc.abstractmethod
310
+ def __repr__(self) -> str:
311
+ """Represent the instance as a string for easier debugging."""
312
+ raise NotImplementedError()
313
+
314
+
315
+ # noinspection PyAbstractClass
316
+ class SummaryRemarksConstraintsDescription(SummaryRemarksDescription):
317
+ """Represent a description with summary, remarks and constraints blocks."""
318
+
319
+ #: Map constraint documentation elements by their identifiers
320
+ constraints_by_identifier: Final[OrderedDict[str, docutils.nodes.field_body]]
321
+
322
+ # fmt: off
323
+ @require(
324
+ lambda constraints_by_identifier:
325
+ all(
326
+ find_first_field_list(body) is None
327
+ for body in constraints_by_identifier.values()
328
+ ),
329
+ "Constraint bodies expected without field lists"
330
+ )
331
+ # fmt: on
332
+ def __init__(
333
+ self,
334
+ summary: docutils.nodes.paragraph,
335
+ remarks: Sequence[docutils.nodes.Element],
336
+ constraints_by_identifier: OrderedDict[str, docutils.nodes.field_body],
337
+ parsed: parse.Description,
338
+ ) -> None:
339
+ """Initialize with the given values."""
340
+ SummaryRemarksDescription.__init__(
341
+ self, summary=summary, remarks=remarks, parsed=parsed
342
+ )
343
+ self.constraints_by_identifier = constraints_by_identifier
344
+
345
+
346
+ class DescriptionOfMetaModel(SummaryRemarksConstraintsDescription):
347
+ """Represent a description of a meta-model."""
348
+
349
+ def __repr__(self) -> str:
350
+ """Represent the instance as a string for easier debugging."""
351
+ return f"<{_MODULE_NAME}.{self.__class__.__name__} at 0x{id(self):x}>"
352
+
353
+
354
+ class DescriptionOfOurType(SummaryRemarksConstraintsDescription):
355
+ """Represent a description of our type."""
356
+
357
+ def __repr__(self) -> str:
358
+ """Represent the instance as a string for easier debugging."""
359
+ return f"<{_MODULE_NAME}.{self.__class__.__name__} at 0x{id(self):x}>"
360
+
361
+
362
+ class DescriptionOfProperty(SummaryRemarksConstraintsDescription):
363
+ """Represent a documentation of a property."""
364
+
365
+ def __repr__(self) -> str:
366
+ """Represent the instance as a string for easier debugging."""
367
+ return f"<{_MODULE_NAME}.{self.__class__.__name__} at 0x{id(self):x}>"
368
+
369
+
370
+ class DescriptionOfEnumerationLiteral(SummaryRemarksDescription):
371
+ """Represent a documentation of an enumeration literal."""
372
+
373
+ def __repr__(self) -> str:
374
+ """Represent the instance as a string for easier debugging."""
375
+ return f"<{_MODULE_NAME}.{self.__class__.__name__} at 0x{id(self):x}>"
376
+
377
+
378
+ class DescriptionOfSignature(SummaryRemarksDescription):
379
+ """Represent a documentation of a method or a function signature."""
380
+
381
+ #: Map argument documentation by the argument names
382
+ arguments_by_name: Final[OrderedDict[Identifier, docutils.nodes.field_body]]
383
+
384
+ #: Documentation of the return value, if written
385
+ returns: Final[Optional[docutils.nodes.field_body]]
386
+
387
+ # fmt: off
388
+ @require(
389
+ lambda arguments_by_name:
390
+ all(
391
+ find_first_field_list(body) is None
392
+ for body in arguments_by_name.values()
393
+ ),
394
+ "Argument descriptions expected without field lists"
395
+ )
396
+ @require(
397
+ lambda returns:
398
+ not (returns is not None)
399
+ or find_first_field_list(returns) is None,
400
+ "Return value description expected without field lists"
401
+ )
402
+ # fmt: on
403
+ def __init__(
404
+ self,
405
+ summary: docutils.nodes.paragraph,
406
+ remarks: Sequence[docutils.nodes.Element],
407
+ arguments_by_name: OrderedDict[Identifier, docutils.nodes.field_body],
408
+ returns: Optional[docutils.nodes.field_body],
409
+ parsed: parse.Description,
410
+ ) -> None:
411
+ """Initialize with the given values."""
412
+ SummaryRemarksDescription.__init__(
413
+ self, summary=summary, remarks=remarks, parsed=parsed
414
+ )
415
+ self.arguments_by_name = arguments_by_name
416
+ self.returns = returns
417
+
418
+ def __repr__(self) -> str:
419
+ """Represent the instance as a string for easier debugging."""
420
+ return f"<{_MODULE_NAME}.{self.__class__.__name__} at 0x{id(self):x}>"
421
+
422
+
423
+ class DescriptionOfConstant(SummaryRemarksDescription):
424
+ """Represent a documentation of a constant in the meta-model."""
425
+
426
+ def __repr__(self) -> str:
427
+ """Represent the instance as a string for easier debugging."""
428
+ return f"<{_MODULE_NAME}.{self.__class__.__name__} at 0x{id(self):x}>"
429
+
430
+
431
+ # endregion
432
+
433
+ # region Our types
434
+
435
+
436
+ class Property:
437
+ """Represent a property of a class."""
438
+
439
+ #: Name of the property
440
+ name: Final[Identifier]
441
+
442
+ #: Type annotation of the property
443
+ type_annotation: Final[TypeAnnotationUnion]
444
+
445
+ #: Description of the property, if any
446
+ description: Final[Optional[DescriptionOfProperty]]
447
+
448
+ #: The original class where this property is specified.
449
+ #: We stack all the properties over the ancestors, so using ``specified_for``
450
+ #: you can distinguish between inherited properties and genuine properties of
451
+ #: a class.
452
+ specified_for: Final["Class"]
453
+
454
+ #: Relation to the property from the parse stage
455
+ parsed: Final[parse.Property]
456
+
457
+ def __init__(
458
+ self,
459
+ name: Identifier,
460
+ type_annotation: TypeAnnotationUnion,
461
+ description: Optional[DescriptionOfProperty],
462
+ specified_for: "Class",
463
+ parsed: parse.Property,
464
+ ) -> None:
465
+ """Initialize with the given values."""
466
+ self.name = name
467
+ self.type_annotation = type_annotation
468
+ self.description = description
469
+ self.specified_for = specified_for
470
+ self.parsed = parsed
471
+
472
+ def __repr__(self) -> str:
473
+ """Represent the instance as a string for easier debugging."""
474
+ return (
475
+ f"<{_MODULE_NAME}.{self.__class__.__name__} {self.name} at 0x{id(self):x}>"
476
+ )
477
+
478
+
479
+ class DefaultPrimitive:
480
+ """Represent a primitive value as a default for an argument."""
481
+
482
+ #: The default value
483
+ value: Final[Union[bool, int, float, str, None]]
484
+
485
+ #: Relation to the parsed stage
486
+ parsed: Final[parse.Default]
487
+
488
+ def __init__(
489
+ self, value: Union[bool, int, float, str, None], parsed: parse.Default
490
+ ) -> None:
491
+ """Initialize with the given values."""
492
+ self.value = value
493
+ self.parsed = parsed
494
+
495
+
496
+ class DefaultEnumerationLiteral:
497
+ """Represent an enumeration literal as a default for an argument."""
498
+
499
+ #: Related enumeration
500
+ enumeration: Final["Enumeration"]
501
+
502
+ #: Related enumeration literal
503
+ literal: Final["EnumerationLiteral"]
504
+
505
+ #: Relation to the parse stage
506
+ parsed: Final[parse.Default]
507
+
508
+ # fmt: off
509
+ @require(
510
+ lambda enumeration, literal:
511
+ literal.name in enumeration.literals_by_name
512
+ and enumeration.literals_by_name[literal.name] == literal
513
+ )
514
+ # fmt: on
515
+ def __init__(
516
+ self,
517
+ enumeration: "Enumeration",
518
+ literal: "EnumerationLiteral",
519
+ parsed: parse.Default,
520
+ ) -> None:
521
+ """Initialize with the given values."""
522
+ self.parsed = parsed
523
+ self.enumeration = enumeration
524
+ self.literal = literal
525
+
526
+
527
+ Default = Union[DefaultPrimitive, DefaultEnumerationLiteral]
528
+
529
+
530
+ class Argument:
531
+ """Represent an argument of a method (both of an interface and of class)."""
532
+
533
+ #: Name of the argument
534
+ name: Final[Identifier]
535
+
536
+ #: Type annotation of the argument
537
+ type_annotation: Final[TypeAnnotationUnion]
538
+
539
+ #: Default value of the argument, if any
540
+ default: Final[Optional[Default]]
541
+
542
+ #: Relation to the parse stage
543
+ parsed: Final[parse.Argument]
544
+
545
+ def __init__(
546
+ self,
547
+ name: Identifier,
548
+ type_annotation: TypeAnnotationUnion,
549
+ default: Optional[Default],
550
+ parsed: parse.Argument,
551
+ ) -> None:
552
+ """Initialize with the given values."""
553
+ self.name = name
554
+ self.type_annotation = type_annotation
555
+ self.default = default
556
+ self.parsed = parsed
557
+
558
+
559
+ class Serialization:
560
+ """Specify the general settings for serialization of an interface or a class."""
561
+
562
+ def __init__(self, with_model_type: bool) -> None:
563
+ """
564
+ Initialize with the given values.
565
+
566
+ :param with_model_type:
567
+ if set, the serialization needs to include a discriminator.
568
+ """
569
+ self.with_model_type = with_model_type
570
+
571
+
572
+ class Invariant:
573
+ """Represent an invariant of a class."""
574
+
575
+ #: Human-readable description of the invariant
576
+ description: Final[str]
577
+
578
+ #: Understood body of the invariant
579
+ body: Final[parse_tree.Expression]
580
+
581
+ #: The original our type where this invariant is specified.
582
+ #: We stack all the invariants over the ancestors, so using ``specified_for``
583
+ #: you can distinguish between inherited invariants and genuine invariants of
584
+ #: a class or a constrained primitive.
585
+ specified_for: Final[Union["ConstrainedPrimitive", "Class"]]
586
+
587
+ #: Relation to the parse stage
588
+ parsed: Final[parse.Invariant]
589
+
590
+ def __init__(
591
+ self,
592
+ description: str,
593
+ body: parse_tree.Expression,
594
+ specified_for: Union["ConstrainedPrimitive", "Class"],
595
+ parsed: parse.Invariant,
596
+ ) -> None:
597
+ self.description = description
598
+ self.body = body
599
+ self.specified_for = specified_for
600
+ self.parsed = parsed
601
+
602
+
603
+ class Contract:
604
+ """Represent a contract of a method."""
605
+
606
+ #: Argument names of the contract
607
+ args: Final[Sequence[Identifier]]
608
+
609
+ #: Human-readable description of the contract, if any
610
+ description: Final[Optional[str]]
611
+
612
+ #: Understood body of the contract
613
+ body: Final[parse_tree.Node]
614
+
615
+ #: Relation to the parse stage
616
+ parsed: Final[parse.Contract]
617
+
618
+ def __init__(
619
+ self,
620
+ args: Sequence[Identifier],
621
+ description: Optional[str],
622
+ body: parse_tree.Node,
623
+ parsed: parse.Contract,
624
+ ) -> None:
625
+ """Initialize with the given values."""
626
+ self.args = args
627
+ self.description = description
628
+ self.body = body
629
+ self.parsed = parsed
630
+
631
+
632
+ class Snapshot:
633
+ """Represent a snapshot of an OLD value capture before the method execution."""
634
+
635
+ #: Argument names of the snapshot
636
+ args: Final[Sequence[Identifier]]
637
+
638
+ #: Understood body of the snapshot
639
+ body: Final[parse_tree.Node]
640
+
641
+ #: Name of the snapshot variable
642
+ name: Final[Identifier]
643
+
644
+ #: Relation to parse stage
645
+ parsed: Final[parse.Snapshot]
646
+
647
+ def __init__(
648
+ self,
649
+ args: Sequence[Identifier],
650
+ body: parse_tree.Node,
651
+ name: Identifier,
652
+ parsed: parse.Snapshot,
653
+ ) -> None:
654
+ """Initialize with the given values."""
655
+ self.args = args
656
+ self.body = body
657
+ self.name = name
658
+ self.parsed = parsed
659
+
660
+
661
+ class Contracts:
662
+ """Represent the set of contracts for a method or a function."""
663
+
664
+ # NOTE (mristin, 2022-04-07):
665
+ # Common programming languages which work with contracts usually implement
666
+ # pre-conditions in a disjunctive normal form, *i.e.* as a disjunction of
667
+ # conjunctions, where at least one conjunction needs to hold. The individual
668
+ # conjunctions correspond to the levels of the inheritance hierarchy.
669
+ #
670
+ # However, we have not touched methods at the moment nor their proper inheritance.
671
+ # Therefore, we leave the pre-conditions in the intermediate representation as they
672
+ # would appear in the code, without inheritance and hence without disjunctions.
673
+ # In the future, once we want to tackle the methods as a feature, we need to change
674
+ # the way how we model and resolve the pre-conditions through
675
+ # the inheritance hierarchy.
676
+
677
+ #: Pre-conditions that need to hold *before* the call
678
+ preconditions: Final[Sequence[Contract]]
679
+
680
+ #: Snapshots which are captured *before* the call
681
+ snapshots: Final[Sequence[Snapshot]]
682
+
683
+ #: Post-conditions that need to hold *after* the call
684
+ postconditions: Final[Sequence[Contract]]
685
+
686
+ def __init__(
687
+ self,
688
+ preconditions: Sequence[Contract],
689
+ snapshots: Sequence[Snapshot],
690
+ postconditions: Sequence[Contract],
691
+ ) -> None:
692
+ """Initialize with the given values."""
693
+ self.preconditions = preconditions
694
+ self.snapshots = snapshots
695
+ self.postconditions = postconditions
696
+
697
+
698
+ class SignatureLike(DBC):
699
+ """
700
+ Represent a signature-like "something".
701
+
702
+ This can be either a signature of a method, a method or a function.
703
+ """
704
+
705
+ #: Name of the signature-like
706
+ name: Final[Identifier]
707
+
708
+ #: Arguments of the signature-like
709
+ arguments: Final[Sequence[Argument]]
710
+
711
+ #: Return type of the signature-like
712
+ returns: Final[Optional[TypeAnnotationUnion]]
713
+
714
+ #: Description of the signature-like, if any
715
+ description: Final[Optional[DescriptionOfSignature]]
716
+
717
+ #: List of contracts of the signature-like. The contracts are stacked from the
718
+ #: ancestors.
719
+ contracts: Final[Contracts]
720
+
721
+ # NOTE (mristin, 2021-12-26):
722
+ # The ``parsed`` must be optional since constructors can be synthesized without
723
+ # being defined in the original meta-model.
724
+
725
+ #: Relation to the parse stage
726
+ parsed: Optional[parse.Method]
727
+
728
+ #: Map arguments by their names
729
+ arguments_by_name: Final[Mapping[Identifier, Argument]]
730
+
731
+ # fmt: off
732
+ @require(
733
+ lambda arguments:
734
+ all(
735
+ arg.name != 'self'
736
+ for arg in arguments
737
+ ),
738
+ "No explicit ``self`` argument in the arguments"
739
+ )
740
+ @require(
741
+ lambda arguments: (
742
+ arg_names := [arg.name for arg in arguments],
743
+ len(arg_names) == len(set(arg_names))
744
+ )[1],
745
+ "Unique arguments"
746
+ )
747
+ @ensure(
748
+ lambda self:
749
+ len(self.arguments) == len(self.arguments_by_name)
750
+ and all(
751
+ (
752
+ found_argument := self.arguments_by_name.get(argument.name, None),
753
+ found_argument is not None and found_argument is argument
754
+ )[1]
755
+ for argument in self.arguments
756
+ ),
757
+ "Arguments and arguments-by-name consistent"
758
+ )
759
+ # fmt: on
760
+ def __init__(
761
+ self,
762
+ name: Identifier,
763
+ arguments: Sequence[Argument],
764
+ returns: Optional[TypeAnnotationUnion],
765
+ description: Optional[DescriptionOfSignature],
766
+ contracts: Contracts,
767
+ parsed: Optional[parse.Method],
768
+ ) -> None:
769
+ """Initialize with the given values."""
770
+ self.name = name
771
+ self.arguments = arguments
772
+ self.returns = returns
773
+ self.description = description
774
+ self.contracts = contracts
775
+ self.parsed = parsed
776
+
777
+ self.arguments_by_name = {
778
+ argument.name: argument for argument in self.arguments
779
+ }
780
+
781
+ @abc.abstractmethod
782
+ def __repr__(self) -> str:
783
+ # Signal that this is a pure abstract class
784
+ raise NotImplementedError()
785
+
786
+
787
+ class Method(SignatureLike):
788
+ """Represent a method of a class."""
789
+
790
+ # NOTE (mristin, 2021-12-26):
791
+ # The ``parsed`` must be optional in the parent class, ``SignatureLike``, since
792
+ # constructors can be synthesized without being defined in the original meta-model.
793
+ #
794
+ # However, methods are never synthesized, so we always have a clear link to
795
+ # the parse stage.
796
+
797
+ parsed: parse.Method
798
+
799
+ #: The original class where this method is specified.
800
+ #: We stack all the methods over the ancestors, so using ``specified_for``
801
+ #: you can distinguish between inherited methods and genuine methods of
802
+ #: a class.
803
+ specified_for: Final["Class"]
804
+
805
+ #: If set, the method does not mutate the instance data.
806
+ #:
807
+ #: We do not check for non-mutating methods in any way as this is very complex,
808
+ #: so we leave it out-of-scope for the moment (2023-07-06).
809
+ non_mutating: Final[bool]
810
+
811
+ # fmt: off
812
+ @require(
813
+ lambda name:
814
+ name != "__init__",
815
+ "Expected constructors to be handled in a special way and not as a method"
816
+ )
817
+ @require(
818
+ lambda arguments, contracts:
819
+ (
820
+ arg_set := {arg.name for arg in arguments},
821
+ all(
822
+ arg in arg_set # pylint: disable=used-before-assignment
823
+ for precondition in contracts.preconditions
824
+ for arg in precondition.args
825
+ if arg != 'self'
826
+ )
827
+ and all(
828
+ arg in arg_set
829
+ for postcondition in contracts.postconditions
830
+ for arg in postcondition.args
831
+ if arg not in ('OLD', 'result', 'self')
832
+ )
833
+ and all(
834
+ arg in arg_set
835
+ for snapshot in contracts.snapshots
836
+ for arg in snapshot.args
837
+ if arg.name != 'self'
838
+ )
839
+ )[1],
840
+ "All arguments of contracts defined in method arguments except ``self``"
841
+ )
842
+ # fmt: on
843
+ def __init__(
844
+ self,
845
+ name: Identifier,
846
+ arguments: Sequence[Argument],
847
+ returns: Optional[TypeAnnotationUnion],
848
+ description: Optional[DescriptionOfSignature],
849
+ specified_for: "Class",
850
+ contracts: Contracts,
851
+ non_mutating: bool,
852
+ parsed: parse.Method,
853
+ ) -> None:
854
+ """Initialize with the given values."""
855
+ SignatureLike.__init__(
856
+ self,
857
+ name=name,
858
+ arguments=arguments,
859
+ returns=returns,
860
+ description=description,
861
+ contracts=contracts,
862
+ parsed=parsed,
863
+ )
864
+
865
+ self.non_mutating = non_mutating
866
+ self.specified_for = specified_for
867
+
868
+ @abc.abstractmethod
869
+ def __repr__(self) -> str:
870
+ # Signal that this is a pure abstract class.
871
+ raise NotImplementedError()
872
+
873
+
874
+ # NOTE (mristin, 2021-12-19):
875
+ # At the moment, we support only implementation-specific methods. However, we anticipate
876
+ # that we will try to understand the methods in the very near future, so we already
877
+ # prepare the class hierarchy for it.
878
+
879
+
880
+ class ImplementationSpecificMethod(Method):
881
+ """Represent an implementation-specific method of a class."""
882
+
883
+ # NOTE (mristin, 2021-12-26):
884
+ # The ``parsed`` must be optional in the parent class, ``SignatureLike``, since
885
+ # constructors can be synthesized without being defined in the original meta-model.
886
+ #
887
+ # However, methods are never synthesized, so we always have a clear link to
888
+ # the parse stage here.
889
+
890
+ #: Relation to parse stage
891
+ parsed: parse.Method
892
+
893
+ def __repr__(self) -> str:
894
+ """Represent the instance as a string for easier debugging."""
895
+ return (
896
+ f"<{_MODULE_NAME}.{self.__class__.__name__} {self.name} at 0x{id(self):x}>"
897
+ )
898
+
899
+
900
+ class UnderstoodMethod(Method):
901
+ """Represent a method of a class which we could understand."""
902
+
903
+ #: Understood syntax tree of the method's body
904
+ body: Final[Sequence[parse_tree.Node]]
905
+
906
+ # NOTE (mristin, 2021-12-26):
907
+ # The ``parsed`` must be optional in the parent class, ``SignatureLike``, since
908
+ # constructors can be synthesized without being defined in the original meta-model.
909
+ #
910
+ # However, methods are never synthesized, so we always have a clear link to
911
+ # the parse stage here.
912
+
913
+ #: Relation to parse stage
914
+ parsed: parse.Method
915
+
916
+ def __init__(
917
+ self,
918
+ name: Identifier,
919
+ arguments: Sequence[Argument],
920
+ returns: Optional[TypeAnnotationUnion],
921
+ description: Optional[DescriptionOfSignature],
922
+ specified_for: "Class",
923
+ contracts: Contracts,
924
+ non_mutating: bool,
925
+ body: Sequence[parse_tree.Node],
926
+ parsed: parse.Method,
927
+ ) -> None:
928
+ """Initialize with the given values."""
929
+ Method.__init__(
930
+ self,
931
+ name=name,
932
+ arguments=arguments,
933
+ returns=returns,
934
+ description=description,
935
+ specified_for=specified_for,
936
+ contracts=contracts,
937
+ non_mutating=non_mutating,
938
+ parsed=parsed,
939
+ )
940
+
941
+ self.body = body
942
+
943
+ def __repr__(self) -> str:
944
+ """Represent the instance as a string for easier debugging."""
945
+ return (
946
+ f"<{_MODULE_NAME}.{self.__class__.__name__} {self.name} at 0x{id(self):x}>"
947
+ )
948
+
949
+
950
+ class Constructor(SignatureLike):
951
+ """
952
+ Represent an understood constructor of a class stacked.
953
+
954
+ The constructor is expected to be stacked from the class and all the ancestors.
955
+ """
956
+
957
+ #: Interpreted statements of the constructor, including calls to super constructors
958
+ statements: Final[Sequence[construction.Statement]]
959
+
960
+ #: Interpreted statements of the constructor stacked over all the ancestors
961
+ #:
962
+ #: ``inlined_statements`` are semantically equivalent to ``statements``. Usually
963
+ #: you want to use them instead of ``statements`` when you deal with languages
964
+ #: which do not support multiple inheritance, so that calls to multiple super
965
+ #: constructors are not possible.
966
+ inlined_statements: Final[Sequence[construction.AssignArgument]]
967
+
968
+ #: If set, the constructor is implementation-specific, and we need to provide
969
+ #: a snippet for it.
970
+ is_implementation_specific: Final[bool]
971
+
972
+ def __init__(
973
+ self,
974
+ is_implementation_specific: bool,
975
+ arguments: Sequence[Argument],
976
+ contracts: Contracts,
977
+ description: Optional[DescriptionOfSignature],
978
+ statements: Sequence[construction.Statement],
979
+ inlined_statements: Sequence[construction.AssignArgument],
980
+ parsed: Optional[parse.Method],
981
+ ) -> None:
982
+ SignatureLike.__init__(
983
+ self,
984
+ name=Identifier("__init__"),
985
+ arguments=arguments,
986
+ returns=None,
987
+ description=description,
988
+ contracts=contracts,
989
+ parsed=parsed,
990
+ )
991
+
992
+ self.is_implementation_specific = is_implementation_specific
993
+
994
+ self.statements = statements
995
+ self.inlined_statements = inlined_statements
996
+
997
+ def __repr__(self) -> str:
998
+ """Represent the instance as a string for easier debugging."""
999
+ return f"<{_MODULE_NAME}.{self.__class__.__name__} at 0x{id(self):x}>"
1000
+
1001
+
1002
+ class EnumerationLiteral:
1003
+ """Represent a single enumeration literal."""
1004
+
1005
+ def __init__(
1006
+ self,
1007
+ name: Identifier,
1008
+ value: str,
1009
+ description: Optional[DescriptionOfEnumerationLiteral],
1010
+ parsed: parse.EnumerationLiteral,
1011
+ ) -> None:
1012
+ self.name = name
1013
+ self.value = value
1014
+ self.description = description
1015
+ self.parsed = parsed
1016
+
1017
+
1018
+ # fmt: off
1019
+ @invariant(
1020
+ lambda self:
1021
+ all(
1022
+ literal == self.literals_by_value[literal.value]
1023
+ for literal in self.literals
1024
+ ),
1025
+ "Literal map by value consistent on value"
1026
+ )
1027
+ @invariant(
1028
+ lambda self:
1029
+ sorted(map(id, self.literals_by_value.values())) == sorted(map(id, self.literals)),
1030
+ "Literal map by value complete"
1031
+ )
1032
+ @invariant(
1033
+ lambda self:
1034
+ all(
1035
+ literal == self.literals_by_name[literal.name]
1036
+ for literal in self.literals
1037
+ ),
1038
+ "Literal map by name consistent on name"
1039
+ )
1040
+ @invariant(
1041
+ lambda self:
1042
+ sorted(map(id, self.literals_by_name.values())) == sorted(map(id, self.literals)),
1043
+ "Literal map by name complete"
1044
+ )
1045
+ # fmt: on
1046
+ class Enumeration:
1047
+ """Represent an enumeration."""
1048
+
1049
+ #: Name of the enumeration
1050
+ name: Final[Identifier]
1051
+
1052
+ #: Literals associated with the enumeration
1053
+ literals: Final[Sequence[EnumerationLiteral]]
1054
+
1055
+ #: Description of the enumeration, if any
1056
+ description: Final[Optional[DescriptionOfOurType]]
1057
+
1058
+ #: Map literals by their identifiers
1059
+ literals_by_name: Final[Mapping[str, EnumerationLiteral]]
1060
+
1061
+ # NOTE (mristin, 2022-09-01):
1062
+ # This map is used by the downstream code, *e.g.*, aas-core3.0rc02-testgen.
1063
+ #: Map literals by their values
1064
+ literals_by_value: Final[Mapping[str, EnumerationLiteral]]
1065
+
1066
+ #: Collect IDs (with :py:func:`id`) of the literal objects in a set
1067
+ literal_id_set: Final[FrozenSet[int]]
1068
+
1069
+ def __init__(
1070
+ self,
1071
+ name: Identifier,
1072
+ literals: Sequence[EnumerationLiteral],
1073
+ description: Optional[DescriptionOfOurType],
1074
+ parsed: parse.Enumeration,
1075
+ ) -> None:
1076
+ self.name = name
1077
+ self.literals = literals
1078
+ self.description = description
1079
+ self.parsed = parsed
1080
+
1081
+ self.literals_by_name: Mapping[str, EnumerationLiteral] = {
1082
+ literal.name: literal for literal in self.literals
1083
+ }
1084
+
1085
+ self.literals_by_value: Mapping[str, EnumerationLiteral] = {
1086
+ literal.value: literal for literal in self.literals
1087
+ }
1088
+
1089
+ self.literal_id_set = frozenset(id(literal) for literal in literals)
1090
+
1091
+ def __repr__(self) -> str:
1092
+ """Represent the instance as a string for easier debugging."""
1093
+ return (
1094
+ f"<{_MODULE_NAME}.{self.__class__.__name__} {self.name} at 0x{id(self):x}>"
1095
+ )
1096
+
1097
+
1098
+ class ConstrainedPrimitive:
1099
+ """Represent a primitive type constrained by one or more invariants."""
1100
+
1101
+ #: Name of the class
1102
+ name: Final[Identifier]
1103
+
1104
+ # region Inheritances
1105
+
1106
+ # NOTE (mristin, 2021-12-24):
1107
+ # We have to decorate inheritances with ``@property`` so that the client code is
1108
+ # forced to use ``_set_inheritances``.
1109
+
1110
+ _inheritances: Sequence["ConstrainedPrimitive"]
1111
+
1112
+ _inheritance_id_set: FrozenSet[int]
1113
+
1114
+ # endregion
1115
+
1116
+ # region Ancestors
1117
+
1118
+ # NOTE (mristin, 2023-03-17):
1119
+ # We have to decorate ancestors with ``@property`` so that the translation code
1120
+ # is forced to use ``_set_ancestors``.
1121
+
1122
+ _ancestors: Sequence["ConstrainedPrimitive"]
1123
+
1124
+ _ancestor_id_set: FrozenSet[int]
1125
+
1126
+ # endregion
1127
+
1128
+ # region Descendants
1129
+
1130
+ # NOTE (mristin, 2021-12-24):
1131
+ # We have to decorate ``descendant_id_set`` with
1132
+ # ``@property`` so that the translation code is forced to use
1133
+ # ``_set_descendants``.
1134
+
1135
+ _descendant_id_set: FrozenSet[int]
1136
+
1137
+ # endregion
1138
+
1139
+ #: Which primitive type is constrained
1140
+ constrainee: PrimitiveType
1141
+
1142
+ #: If set, this class is implementation-specific, and we need to provide a snippet
1143
+ #: for each implementation target
1144
+ is_implementation_specific: Final[bool]
1145
+
1146
+ # region Invariants
1147
+
1148
+ # NOTE (mristin, 2022-03-19):
1149
+ # We have to decorate invariants with ``@property`` so that the translation code
1150
+ # is forced to use ``_set_invariants``.
1151
+
1152
+ _invariants: Sequence[Invariant]
1153
+
1154
+ _invariant_id_set: FrozenSet[int]
1155
+
1156
+ # endregion
1157
+
1158
+ #: Description of the class
1159
+ description: Final[Optional[DescriptionOfOurType]]
1160
+
1161
+ #: Relation to the class from the parse stage
1162
+ parsed: parse.Class
1163
+
1164
+ @require(lambda self, ancestors: self not in ancestors)
1165
+ def _set_ancestors(self, ancestors: Sequence["ConstrainedPrimitive"]) -> None:
1166
+ """
1167
+ Set the ancestors in the constrained primitive.
1168
+
1169
+ This method is expected to be called only during the translation phase.
1170
+ """
1171
+ self._ancestors = ancestors
1172
+
1173
+ self._ancestor_id_set = frozenset(id(ancestor) for ancestor in ancestors)
1174
+
1175
+ @require(lambda self, descendants: self not in descendants)
1176
+ def _set_descendants(self, descendants: Sequence["ConstrainedPrimitive"]) -> None:
1177
+ """
1178
+ Set the descendants in the constrained primitive.
1179
+
1180
+ This method is expected to be called only during the translation phase.
1181
+ """
1182
+ self._descendant_id_set = frozenset(
1183
+ id(descendant) for descendant in descendants
1184
+ )
1185
+
1186
+ def _set_invariants(self, invariants: Sequence[Invariant]) -> None:
1187
+ """
1188
+ Set the invariants in the class.
1189
+
1190
+ This method is expected to be called only during the translation phase.
1191
+ """
1192
+ self._invariants = invariants
1193
+ self._invariant_id_set = frozenset(id(inv) for inv in invariants)
1194
+
1195
+ # fmt: off
1196
+ @require(
1197
+ lambda inheritances:
1198
+ len(inheritances) == len(set(inheritance.name for inheritance in inheritances)),
1199
+ "No duplicate inheritances"
1200
+ )
1201
+ # fmt: on
1202
+ def _set_inheritances(self, inheritances: Sequence["ConstrainedPrimitive"]) -> None:
1203
+ """
1204
+ Set the inheritances in the class.
1205
+
1206
+ This method is expected to be called only during the translation phase.
1207
+ """
1208
+ self._inheritances = inheritances
1209
+
1210
+ self._inheritance_id_set = frozenset(
1211
+ id(inheritance) for inheritance in self._inheritances
1212
+ )
1213
+
1214
+ # fmt: off
1215
+ @require(
1216
+ lambda parsed: len(parsed.methods) == 0,
1217
+ "No methods expected in the constrained primitive type"
1218
+ )
1219
+ @require(
1220
+ lambda parsed: len(parsed.properties) == 0,
1221
+ "No properties expected in the constrained primitive type"
1222
+ )
1223
+ @require(
1224
+ lambda constrainee, inheritances:
1225
+ all(
1226
+ inheritance.constrainee == constrainee
1227
+ for inheritance in inheritances
1228
+ ),
1229
+ "Constrainee consistent with ancestors"
1230
+ )
1231
+ @require(
1232
+ lambda constrainee, descendants:
1233
+ all(
1234
+ descendant.constrainee == constrainee
1235
+ for descendant in descendants
1236
+ ),
1237
+ "Constrainee consistent with descendants"
1238
+ )
1239
+ @require(
1240
+ lambda ancestors, inheritances:
1241
+ (
1242
+ ancestor_id_set := set(id(ancestor) for ancestor in ancestors),
1243
+ all(
1244
+ id(inheritance) in ancestor_id_set # pylint: disable=used-before-assignment
1245
+ for inheritance in inheritances
1246
+ )
1247
+ )[1],
1248
+ "Inheritances is a subset of ancestors"
1249
+ )
1250
+ @require(lambda self, inheritances: self not in inheritances)
1251
+ @require(lambda self, ancestors: self not in ancestors)
1252
+ @require(lambda self, descendants: self not in descendants)
1253
+ # fmt: on
1254
+ def __init__(
1255
+ self,
1256
+ name: Identifier,
1257
+ inheritances: Sequence["ConstrainedPrimitive"],
1258
+ ancestors: Sequence["ConstrainedPrimitive"],
1259
+ descendants: Sequence["ConstrainedPrimitive"],
1260
+ constrainee: PrimitiveType,
1261
+ is_implementation_specific: bool,
1262
+ invariants: Sequence[Invariant],
1263
+ description: Optional[DescriptionOfOurType],
1264
+ parsed: parse.Class,
1265
+ ) -> None:
1266
+ self.name = name
1267
+ self._set_inheritances(inheritances)
1268
+ self._set_ancestors(ancestors)
1269
+ self._set_descendants(descendants)
1270
+ self.constrainee = constrainee
1271
+ self.is_implementation_specific = is_implementation_specific
1272
+ self._set_invariants(invariants)
1273
+ self.description = description
1274
+ self.parsed = parsed
1275
+
1276
+ @property
1277
+ def inheritances(self) -> Sequence["ConstrainedPrimitive"]:
1278
+ """Return direct parents that this class inherits from."""
1279
+ return self._inheritances
1280
+
1281
+ @property
1282
+ def inheritance_id_set(self) -> FrozenSet[int]:
1283
+ """Collect IDs (with :py:func:`id`) of the inheritance objects in a set."""
1284
+ return self._inheritance_id_set
1285
+
1286
+ @property
1287
+ def ancestors(self) -> Sequence["ConstrainedPrimitive"]:
1288
+ """
1289
+ Return the ancestor constrained primitives.
1290
+
1291
+ These are the constrained primitives that this one directly or indirectly
1292
+ inherits from.
1293
+ """
1294
+ return self._ancestors
1295
+
1296
+ @property
1297
+ def ancestor_id_set(self) -> FrozenSet[int]:
1298
+ """Collect IDs (with :py:func:`id`) of the ancestors in a set."""
1299
+ return self._ancestor_id_set
1300
+
1301
+ def is_subclass_of(self, constrained_primitive: "ConstrainedPrimitive") -> bool:
1302
+ """
1303
+ Check whether this one is a subclass of ``constrained_primitive``.
1304
+
1305
+ Every constrained primitive is a subclass of itself.
1306
+ """
1307
+ # NOTE (mristin, 2022-05-13):
1308
+ # This function is not used by the aas-core-codegen, but by downstream clients
1309
+ # such as aas-core3.0rc02-testgen.
1310
+
1311
+ if id(constrained_primitive) == id(self):
1312
+ return True
1313
+
1314
+ return id(constrained_primitive) in self._ancestor_id_set
1315
+
1316
+ @property
1317
+ def descendant_id_set(self) -> FrozenSet[int]:
1318
+ """List the IDs (as in Python's ``id`` built-in) of the descendants."""
1319
+ return self._descendant_id_set
1320
+
1321
+ @property
1322
+ def invariants(self) -> Sequence[Invariant]:
1323
+ """List invariants of the class."""
1324
+ return self._invariants
1325
+
1326
+ @property
1327
+ def invariant_id_set(self) -> FrozenSet[int]:
1328
+ """Collect IDs (with :py:func:`id`) of the invariant objects in a set."""
1329
+ return self._invariant_id_set
1330
+
1331
+ def __repr__(self) -> str:
1332
+ """Represent the instance as a string for easier debugging."""
1333
+ return (
1334
+ f"<{_MODULE_NAME}.{self.__class__.__name__} {self.name} at 0x{id(self):x}>"
1335
+ )
1336
+
1337
+
1338
+ class Class(DBC):
1339
+ """Represent an abstract or a concrete class."""
1340
+
1341
+ #: Name of the class
1342
+ name: Final[Identifier]
1343
+
1344
+ # region Inheritances
1345
+
1346
+ # NOTE (mristin, 2021-12-24):
1347
+ # We have to decorate inheritances with ``@property`` so that the translation code
1348
+ # is forced to use ``_set_inheritances``.
1349
+
1350
+ _inheritances: Sequence["ClassUnion"]
1351
+
1352
+ _inheritance_id_set: FrozenSet[int]
1353
+
1354
+ # endregion
1355
+
1356
+ # region Ancestors
1357
+
1358
+ # NOTE (mristin, 2023-03-17):
1359
+ # We have to decorate ancestors with ``@property`` so that the translation code
1360
+ # is forced to use ``_set_ancestors``.
1361
+
1362
+ _ancestors: Sequence["ClassUnion"]
1363
+
1364
+ _ancestor_id_set: FrozenSet[int]
1365
+
1366
+ # endregion
1367
+
1368
+ #: If set, this class is implementation-specific, and we need to provide a snippet
1369
+ #: for each implementation target
1370
+ is_implementation_specific: Final[bool]
1371
+
1372
+ #: Interface of the class. If it is a concrete class with no descendants, there is
1373
+ #: no interface available.
1374
+ interface: Optional["Interface"]
1375
+
1376
+ # region Descendants
1377
+
1378
+ # NOTE (mristin, 2023-03-24):
1379
+ # We have to decorate ``descendant_id_set``, ``descendants``,
1380
+ # ``concrete_descendant_id_set`` and ``concrete_descendants`` with
1381
+ # ``@property`` so that the translation code is forced to use
1382
+ # ``_set_descendants``.
1383
+
1384
+ _descendant_id_set: FrozenSet[int]
1385
+
1386
+ _descendants: Sequence["ClassUnion"]
1387
+
1388
+ _concrete_descendant_id_set: FrozenSet[int]
1389
+
1390
+ _concrete_descendants: Sequence["ConcreteClass"]
1391
+
1392
+ # endregion
1393
+
1394
+ # region Properties
1395
+
1396
+ # NOTE (mristin, 2022-03-19):
1397
+ # We have to decorate properties with ``@property`` so that the translation code
1398
+ # is forced to use ``_set_properties``.
1399
+
1400
+ _properties: Sequence[Property]
1401
+
1402
+ _properties_by_name: Mapping[Identifier, Property]
1403
+
1404
+ _property_id_set: FrozenSet[int]
1405
+
1406
+ # endregion
1407
+
1408
+ # region Methods
1409
+
1410
+ # NOTE (mristin, 2022-03-19):
1411
+ # We have to decorate methods with ``@property`` so that the translation code
1412
+ # is forced to use ``_set_methods``.
1413
+
1414
+ _methods: Sequence["MethodUnion"]
1415
+
1416
+ _methods_by_name: Mapping[Identifier, "MethodUnion"]
1417
+
1418
+ _method_id_set: FrozenSet[int]
1419
+
1420
+ # endregion
1421
+
1422
+ #: Constructor specification of the class
1423
+ constructor: Final[Constructor]
1424
+
1425
+ # region Invariants
1426
+
1427
+ # NOTE (mristin, 2022-03-19):
1428
+ # We have to decorate invariants with ``@property`` so that the translation code
1429
+ # is forced to use ``_set_invariants``.
1430
+
1431
+ _invariants: Sequence[Invariant]
1432
+
1433
+ _invariant_id_set: FrozenSet[int]
1434
+
1435
+ # endregion
1436
+
1437
+ #: Particular serialization settings for this class
1438
+ serialization: Final[Serialization]
1439
+
1440
+ #: Description of the class
1441
+ description: Final[Optional[DescriptionOfOurType]]
1442
+
1443
+ #: Relation to the class from the parse stage
1444
+ parsed: Final[parse.Class]
1445
+
1446
+ # fmt: off
1447
+ @require(
1448
+ lambda inheritances:
1449
+ len(inheritances) == len(set(inheritance.name for inheritance in inheritances)),
1450
+ "No duplicate inheritances"
1451
+ )
1452
+ # fmt: on
1453
+ def _set_inheritances(self, inheritances: Sequence["ClassUnion"]) -> None:
1454
+ """
1455
+ Set the inheritances in the class.
1456
+
1457
+ This method is expected to be called only during the translation phase.
1458
+ """
1459
+ self._inheritances = inheritances
1460
+
1461
+ self._inheritance_id_set = frozenset(
1462
+ id(inheritance) for inheritance in self._inheritances
1463
+ )
1464
+
1465
+ @require(lambda self, ancestors: self not in ancestors)
1466
+ def _set_ancestors(self, ancestors: Sequence["ClassUnion"]) -> None:
1467
+ """
1468
+ Set the ancestors in the class.
1469
+
1470
+ This method is expected to be called only during the translation phase.
1471
+ """
1472
+ self._ancestor_id_set = frozenset(id(ancestor) for ancestor in ancestors)
1473
+
1474
+ self._ancestors = ancestors
1475
+
1476
+ @require(lambda self, descendants: self not in descendants)
1477
+ def _set_descendants(self, descendants: Sequence["ClassUnion"]) -> None:
1478
+ """
1479
+ Set the descendants and the concrete descendants in the class.
1480
+
1481
+ This method is expected to be called only during the translation phase.
1482
+ """
1483
+ self._descendant_id_set = frozenset(
1484
+ id(descendant) for descendant in descendants
1485
+ )
1486
+
1487
+ self._descendants = descendants
1488
+
1489
+ self._concrete_descendants = [
1490
+ descendant
1491
+ for descendant in descendants
1492
+ if isinstance(descendant, ConcreteClass)
1493
+ ]
1494
+
1495
+ self._concrete_descendant_id_set = frozenset(
1496
+ id(descendant) for descendant in self._concrete_descendants
1497
+ )
1498
+
1499
+ # fmt: off
1500
+ @require(
1501
+ lambda properties:
1502
+ len(properties) == len(set(prop.name for prop in properties)),
1503
+ "No duplicate properties"
1504
+ )
1505
+ # fmt: on
1506
+ def _set_properties(self, properties: Sequence[Property]) -> None:
1507
+ """
1508
+ Set the properties in the class.
1509
+
1510
+ This method is expected to be called only during the translation phase.
1511
+ """
1512
+ self._properties = properties
1513
+ self._properties_by_name = {prop.name: prop for prop in properties}
1514
+ self._property_id_set = frozenset(id(prop) for prop in properties)
1515
+
1516
+ # fmt: off
1517
+ @require(
1518
+ lambda methods:
1519
+ len(methods) == len(set(method.name for method in methods)),
1520
+ "No duplicate methods"
1521
+ )
1522
+ # fmt: on
1523
+ def _set_methods(self, methods: Sequence["MethodUnion"]) -> None:
1524
+ """
1525
+ Set the methods in the class.
1526
+
1527
+ This method is expected to be called only during the translation phase.
1528
+ """
1529
+ self._methods = methods
1530
+ self._methods_by_name = {method.name: method for method in methods}
1531
+ self._method_id_set = frozenset(id(method) for method in methods)
1532
+
1533
+ def _set_invariants(self, invariants: Sequence[Invariant]) -> None:
1534
+ """
1535
+ Set the invariants in the class.
1536
+
1537
+ This method is expected to be called only during the translation phase.
1538
+ """
1539
+ self._invariants = invariants
1540
+ self._invariant_id_set = frozenset(id(inv) for inv in invariants)
1541
+
1542
+ # fmt: off
1543
+ @require(
1544
+ lambda ancestors, inheritances:
1545
+ (
1546
+ ancestor_id_set := set(id(ancestor) for ancestor in ancestors),
1547
+ all(
1548
+ id(inheritance) in ancestor_id_set # pylint: disable=used-before-assignment
1549
+ for inheritance in inheritances
1550
+ )
1551
+ )[1],
1552
+ "Inheritances is a subset of ancestors"
1553
+ )
1554
+ @require(
1555
+ lambda ancestors, descendants:
1556
+ len(
1557
+ set(id(ancestor) for ancestor in ancestors).difference(
1558
+ id(descendant) for descendant in descendants
1559
+ )
1560
+ ) == 0,
1561
+ "No ancestor is also a descendant"
1562
+ )
1563
+ @require(lambda self, inheritances: self not in inheritances)
1564
+ @require(lambda self, ancestors: self not in ancestors)
1565
+ @require(lambda self, descendants: self not in descendants)
1566
+ @ensure(
1567
+ lambda self:
1568
+ all(
1569
+ isinstance(descendant, ConcreteClass)
1570
+ for descendant in self.concrete_descendants
1571
+ ),
1572
+ "All concrete descendants must match in type"
1573
+ )
1574
+ @ensure(
1575
+ lambda descendants, self:
1576
+ all(
1577
+ (
1578
+ id(descendant) in self.concrete_descendant_id_set
1579
+ and descendant in self.descendants
1580
+ )
1581
+ for descendant in descendants
1582
+ ),
1583
+ "Descendants are propagated to properties"
1584
+ )
1585
+ @ensure(
1586
+ lambda self:
1587
+ (
1588
+ len(
1589
+ self.concrete_descendant_id_set.intersection(self.descendant_id_set)
1590
+ ) == len(self.concrete_descendant_id_set)
1591
+ ),
1592
+ "Concrete descendants are a subset of descendants"
1593
+ )
1594
+ @ensure(
1595
+ lambda self:
1596
+ (
1597
+ id(descendant) in self.concrete_descendant_id_set
1598
+ for descendant in self.descendants
1599
+ if isinstance(descendant, ConcreteClass)
1600
+ ),
1601
+ "All concrete descendants are in concrete descendant set"
1602
+ )
1603
+ # fmt: on
1604
+ def __init__(
1605
+ self,
1606
+ name: Identifier,
1607
+ inheritances: Sequence["ClassUnion"],
1608
+ ancestors: Sequence["ClassUnion"],
1609
+ interface: Optional["Interface"],
1610
+ descendants: Sequence["ClassUnion"],
1611
+ is_implementation_specific: bool,
1612
+ properties: Sequence[Property],
1613
+ methods: Sequence["MethodUnion"],
1614
+ constructor: Constructor,
1615
+ invariants: Sequence[Invariant],
1616
+ serialization: Serialization,
1617
+ description: Optional[DescriptionOfOurType],
1618
+ parsed: parse.Class,
1619
+ ) -> None:
1620
+ """Initialize with the given values."""
1621
+ self.name = name
1622
+ self._set_inheritances(inheritances)
1623
+ self._set_ancestors(ancestors)
1624
+ self.interface = interface
1625
+ self._set_descendants(descendants)
1626
+ self.is_implementation_specific = is_implementation_specific
1627
+ self._set_properties(properties)
1628
+ self._set_methods(methods)
1629
+ self.constructor = constructor
1630
+ self._set_invariants(invariants)
1631
+ self.serialization = serialization
1632
+ self.description = description
1633
+ self.parsed = parsed
1634
+
1635
+ @property
1636
+ def inheritances(self) -> Sequence["ClassUnion"]:
1637
+ """Return direct parents that this class inherits from."""
1638
+ return self._inheritances
1639
+
1640
+ @property
1641
+ def inheritance_id_set(self) -> FrozenSet[int]:
1642
+ """Collect IDs (with :py:func:`id`) of the inheritance objects in a set."""
1643
+ return self._inheritance_id_set
1644
+
1645
+ @property
1646
+ def ancestors(self) -> Sequence["ClassUnion"]:
1647
+ """Return classes that this class directly or indirectly inherits from."""
1648
+ return self._ancestors
1649
+
1650
+ @property
1651
+ def ancestor_id_set(self) -> FrozenSet[int]:
1652
+ """Collect IDs (with :py:func:`id`) of the ancestor classes in a set."""
1653
+ return self._ancestor_id_set
1654
+
1655
+ def is_subclass_of(self, cls: "ClassUnion") -> bool:
1656
+ """
1657
+ Check whether this class is a subclass of ``cls``.
1658
+
1659
+ Every class is a subclass of itself.
1660
+ """
1661
+ # NOTE (mristin, 2022-05-13):
1662
+ # This function is not used by the aas-core-codegen, but by downstream clients
1663
+ # such as aas-core3.0rc02-testgen.
1664
+
1665
+ if id(cls) == id(self):
1666
+ return True
1667
+
1668
+ return id(cls) in self._ancestor_id_set
1669
+
1670
+ @property
1671
+ def descendant_id_set(self) -> FrozenSet[int]:
1672
+ """List the IDs (as in Python's ``id`` built-in) of the descendants."""
1673
+ return self._descendant_id_set
1674
+
1675
+ @property
1676
+ def descendants(self) -> Sequence["ClassUnion"]:
1677
+ """List all descendants of this class."""
1678
+ return self._descendants
1679
+
1680
+ @property
1681
+ def concrete_descendant_id_set(self) -> FrozenSet[int]:
1682
+ """List the IDs (as in Python's ``id`` built-in) of the concrete descendants."""
1683
+ return self._concrete_descendant_id_set
1684
+
1685
+ @property
1686
+ def concrete_descendants(self) -> Sequence["ConcreteClass"]:
1687
+ """List descendants of this class which are concrete classes."""
1688
+ return self._concrete_descendants
1689
+
1690
+ @property
1691
+ def properties(self) -> Sequence[Property]:
1692
+ """Return list of properties of the class."""
1693
+ return self._properties
1694
+
1695
+ @property
1696
+ def properties_by_name(self) -> Mapping[Identifier, Property]:
1697
+ """Map all properties by their names."""
1698
+ return self._properties_by_name
1699
+
1700
+ @property
1701
+ def property_id_set(self) -> FrozenSet[int]:
1702
+ """Collect IDs (with :py:func:`id`) of the property objects in a set."""
1703
+ return self._property_id_set
1704
+
1705
+ @property
1706
+ def methods(self) -> Sequence["MethodUnion"]:
1707
+ """
1708
+ List methods of the class.
1709
+
1710
+ The methods are strictly non-static and non-class (in the Python sense of
1711
+ the terms).
1712
+ """
1713
+ return self._methods
1714
+
1715
+ @property
1716
+ def methods_by_name(self) -> Mapping[Identifier, "MethodUnion"]:
1717
+ """Map all methods by their names."""
1718
+ return self._methods_by_name
1719
+
1720
+ @property
1721
+ def method_id_set(self) -> FrozenSet[int]:
1722
+ """Collect IDs (with :py:func:`id`) of the method objects in a set."""
1723
+ return self._method_id_set
1724
+
1725
+ @property
1726
+ def invariants(self) -> Sequence[Invariant]:
1727
+ """List invariants of the class."""
1728
+ return self._invariants
1729
+
1730
+ @property
1731
+ def invariant_id_set(self) -> FrozenSet[int]:
1732
+ """Collect IDs (with :py:func:`id`) of the invariant objects in a set."""
1733
+ return self._invariant_id_set
1734
+
1735
+ @abc.abstractmethod
1736
+ def __repr__(self) -> str:
1737
+ # Signal that this is a purely abstract class.
1738
+ raise NotImplementedError()
1739
+
1740
+
1741
+ class ConcreteClass(Class):
1742
+ """Represent a class that can be instantiated."""
1743
+
1744
+ def __repr__(self) -> str:
1745
+ """Represent the instance as a string for easier debugging."""
1746
+ return (
1747
+ f"<{_MODULE_NAME}.{self.__class__.__name__} {self.name} at 0x{id(self):x}>"
1748
+ )
1749
+
1750
+
1751
+ class AbstractClass(Class):
1752
+ """Represent a class that is purely abstract and can not be instantiated."""
1753
+
1754
+ #: Interface of the class. All abstract classes have an interface as opposed to
1755
+ #: concrete classes, which only have an interface if there are descendants.
1756
+ interface: "Interface"
1757
+
1758
+ # We need to override the constructor because the ``interface`` is required.
1759
+ def __init__(
1760
+ self,
1761
+ name: Identifier,
1762
+ inheritances: Sequence["ClassUnion"],
1763
+ ancestors: Sequence["ClassUnion"],
1764
+ interface: "Interface",
1765
+ descendants: Sequence["ClassUnion"],
1766
+ is_implementation_specific: bool,
1767
+ properties: Sequence[Property],
1768
+ methods: Sequence["MethodUnion"],
1769
+ constructor: Constructor,
1770
+ invariants: Sequence[Invariant],
1771
+ serialization: Serialization,
1772
+ description: Optional[DescriptionOfOurType],
1773
+ parsed: parse.Class,
1774
+ ) -> None:
1775
+ """Initialize with the given values."""
1776
+ Class.__init__(
1777
+ self,
1778
+ name=name,
1779
+ inheritances=inheritances,
1780
+ ancestors=ancestors,
1781
+ interface=interface,
1782
+ descendants=descendants,
1783
+ is_implementation_specific=is_implementation_specific,
1784
+ properties=properties,
1785
+ methods=methods,
1786
+ constructor=constructor,
1787
+ invariants=invariants,
1788
+ serialization=serialization,
1789
+ description=description,
1790
+ parsed=parsed,
1791
+ )
1792
+
1793
+ def __repr__(self) -> str:
1794
+ """Represent the instance as a string for easier debugging."""
1795
+ return (
1796
+ f"<{_MODULE_NAME}.{self.__class__.__name__} {self.name} at 0x{id(self):x}>"
1797
+ )
1798
+
1799
+
1800
+ # endregion
1801
+
1802
+
1803
+ # region Constants
1804
+
1805
+
1806
+ class Constant(DBC):
1807
+ """Represent a constant of the meta-model."""
1808
+
1809
+ #: Name of the constant
1810
+ name: Final[Identifier]
1811
+
1812
+ #: Description of the constant, if any given in the meta-model
1813
+ description: Final[Optional[DescriptionOfConstant]]
1814
+
1815
+ def __init__(
1816
+ self,
1817
+ name: Identifier,
1818
+ description: Optional[DescriptionOfConstant],
1819
+ ) -> None:
1820
+ """Initialize with the given values."""
1821
+ self.name = name
1822
+ self.description = description
1823
+
1824
+ @abc.abstractmethod
1825
+ def __repr__(self) -> str:
1826
+ """Represent the instance as a string for easier debugging."""
1827
+ raise NotImplementedError()
1828
+
1829
+
1830
+ class ConstantPrimitive(Constant):
1831
+ """Represent a constant primitive value in the meta-model."""
1832
+
1833
+ #: Value of the constant
1834
+ value: Union[bool, int, float, str, bytearray]
1835
+
1836
+ #: Type of the constant
1837
+ a_type: Final[PrimitiveType]
1838
+
1839
+ #: Relation to the parse stage
1840
+ parsed: Final[parse.ConstantPrimitive]
1841
+
1842
+ # fmt: off
1843
+ # noinspection PyTypeHints
1844
+ @require(
1845
+ lambda value, a_type:
1846
+ isinstance(value, PRIMITIVE_TYPE_TO_PYTHON_TYPE[a_type])
1847
+ )
1848
+ # fmt: on
1849
+ def __init__(
1850
+ self,
1851
+ name: Identifier,
1852
+ value: Union[bool, int, float, str, bytearray],
1853
+ a_type: PrimitiveType,
1854
+ description: Optional[DescriptionOfConstant],
1855
+ parsed: parse.ConstantPrimitive,
1856
+ ) -> None:
1857
+ """Initialize with the given values."""
1858
+ Constant.__init__(
1859
+ self,
1860
+ name=name,
1861
+ description=description,
1862
+ )
1863
+
1864
+ self.value = value
1865
+ self.a_type = a_type
1866
+ self.parsed = parsed
1867
+
1868
+ def __repr__(self) -> str:
1869
+ """Represent the instance as a string for easier debugging."""
1870
+ return (
1871
+ f"<{_MODULE_NAME}.{self.__class__.__name__} {self.name} at 0x{id(self):x}>"
1872
+ )
1873
+
1874
+
1875
+ class PrimitiveSetLiteral:
1876
+ """Represent an item of a set of primitive literals."""
1877
+
1878
+ #: Value of the literal
1879
+ value: Union[bool, int, float, str, bytearray]
1880
+
1881
+ #: Type of the literal
1882
+ a_type: Final[PrimitiveType]
1883
+
1884
+ #: Relation to the parse stage
1885
+ parsed: Final[parse.SetLiteral]
1886
+
1887
+ # fmt: off
1888
+ # noinspection PyTypeHints
1889
+ @require(
1890
+ lambda value, a_type:
1891
+ isinstance(value, PRIMITIVE_TYPE_TO_PYTHON_TYPE[a_type])
1892
+ )
1893
+ # fmt: on
1894
+ def __init__(
1895
+ self,
1896
+ value: Union[bool, int, float, str, bytearray],
1897
+ a_type: PrimitiveType,
1898
+ parsed: parse.SetLiteral,
1899
+ ) -> None:
1900
+ """Initialize with the given values."""
1901
+ self.value = value
1902
+ self.a_type = a_type
1903
+ self.parsed = parsed
1904
+
1905
+ def __repr__(self) -> str:
1906
+ """Represent as a string for easier debugging."""
1907
+ return (
1908
+ f"<{_MODULE_NAME}.{self.__class__.__name__} "
1909
+ f"{self.a_type.name} {self.value!r} at 0x{id(self):x}>"
1910
+ )
1911
+
1912
+
1913
+ class ConstantSetOfPrimitives(Constant):
1914
+ """Represent a set of primitive literals."""
1915
+
1916
+ #: Type of the literals
1917
+ a_type: Final[PrimitiveType]
1918
+
1919
+ #: Members of this subset
1920
+ literals: Final[Sequence[PrimitiveSetLiteral]]
1921
+
1922
+ #: All other subsets which are contained in this enumeration subset
1923
+ subsets: Final[Sequence["ConstantSetOfPrimitives"]]
1924
+
1925
+ #: Relation to the parse stage
1926
+ parsed: Final[parse.ConstantSet]
1927
+
1928
+ #: Set of all the literal values
1929
+ literal_value_set: Final[Set[Union[bool, int, float, str, bytearray]]]
1930
+
1931
+ # fmt: off
1932
+ # noinspection PyTypeHints
1933
+ @require(
1934
+ lambda a_type, literals:
1935
+ all(
1936
+ literal.a_type is a_type
1937
+ for literal in literals
1938
+ ),
1939
+ "All literals share the same primitive type"
1940
+ )
1941
+ @ensure(
1942
+ lambda self:
1943
+ not (len(self.literal_value_set) > 1)
1944
+ or (
1945
+ python_type := PRIMITIVE_TYPE_TO_PYTHON_TYPE[self.a_type],
1946
+ all(
1947
+ isinstance(value, python_type) # pylint: disable=used-before-assignment
1948
+ for value in self.literal_value_set
1949
+ )
1950
+ )[1],
1951
+ "Types in the literal value set match ``a_type``"
1952
+ )
1953
+ # fmt: on
1954
+ def __init__(
1955
+ self,
1956
+ name: Identifier,
1957
+ a_type: PrimitiveType,
1958
+ literals: Sequence[PrimitiveSetLiteral],
1959
+ subsets: Sequence["ConstantSetOfPrimitives"],
1960
+ description: Optional[DescriptionOfConstant],
1961
+ parsed: parse.ConstantSet,
1962
+ ) -> None:
1963
+ """Initialize with the given values."""
1964
+ Constant.__init__(
1965
+ self,
1966
+ name=name,
1967
+ description=description,
1968
+ )
1969
+
1970
+ self.a_type = a_type
1971
+ self.literals = literals
1972
+ self.subsets = subsets
1973
+ self.parsed = parsed
1974
+
1975
+ self.literal_value_set = {literal.value for literal in literals}
1976
+
1977
+ def __repr__(self) -> str:
1978
+ """Represent the instance as a string for easier debugging."""
1979
+ return (
1980
+ f"<{_MODULE_NAME}.{self.__class__.__name__} {self.name} at 0x{id(self):x}>"
1981
+ )
1982
+
1983
+
1984
+ class ConstantSetOfEnumerationLiterals(Constant):
1985
+ """Represent a set of enumeration literals."""
1986
+
1987
+ #: Enumeration that this is a subset of
1988
+ enumeration: Final[Enumeration]
1989
+
1990
+ #: Members of this subset
1991
+ literals: Final[Sequence[EnumerationLiteral]]
1992
+
1993
+ #: All other subsets which are contained in this enumeration subset
1994
+ subsets: Final[Sequence["ConstantSetOfEnumerationLiterals"]]
1995
+
1996
+ #: Relation to the parse stage
1997
+ parsed: Final[parse.ConstantSet]
1998
+
1999
+ #: Set of all the IDs (as in Python objects) of the literals
2000
+ literal_id_set: Final[Set[int]]
2001
+
2002
+ # fmt: off
2003
+ @require(
2004
+ lambda literals, enumeration:
2005
+ all(
2006
+ id(literal) in enumeration.literal_id_set
2007
+ for literal in literals
2008
+ ),
2009
+ "All literals are members of the same enumeration"
2010
+ )
2011
+ @ensure(
2012
+ lambda literals, self:
2013
+ all(
2014
+ id(literal) in self.literal_id_set
2015
+ for literal in self.literals
2016
+ ) and len(self.literals) == len(self.literal_id_set),
2017
+ "Literal set corresponds to literals"
2018
+ )
2019
+ # fmt: on
2020
+ def __init__(
2021
+ self,
2022
+ name: Identifier,
2023
+ enumeration: Enumeration,
2024
+ literals: Sequence[EnumerationLiteral],
2025
+ subsets: Sequence["ConstantSetOfEnumerationLiterals"],
2026
+ description: Optional[DescriptionOfConstant],
2027
+ parsed: parse.ConstantSet,
2028
+ ) -> None:
2029
+ """Initialize with the given values."""
2030
+ Constant.__init__(
2031
+ self,
2032
+ name=name,
2033
+ description=description,
2034
+ )
2035
+
2036
+ self.enumeration = enumeration
2037
+ self.literals = literals
2038
+ self.subsets = subsets
2039
+ self.parsed = parsed
2040
+
2041
+ self.literal_id_set = {id(literal) for literal in self.literals}
2042
+
2043
+ def __repr__(self) -> str:
2044
+ """Represent the instance as a string for easier debugging."""
2045
+ return (
2046
+ f"<{_MODULE_NAME}.{self.__class__.__name__} {self.name} at 0x{id(self):x}>"
2047
+ )
2048
+
2049
+
2050
+ # endregion
2051
+
2052
+ # region Verification functions
2053
+
2054
+
2055
+ class Verification(SignatureLike):
2056
+ """Represent a verification function defined in the meta-model."""
2057
+
2058
+ parsed: parse.Method
2059
+
2060
+ # fmt: off
2061
+ @require(
2062
+ lambda arguments, contracts:
2063
+ (
2064
+ arg_set := {arg.name for arg in arguments},
2065
+ all(
2066
+ arg in arg_set # pylint: disable=used-before-assignment
2067
+ for precondition in contracts.preconditions
2068
+ for arg in precondition.args
2069
+ )
2070
+ and all(
2071
+ arg in arg_set
2072
+ for postcondition in contracts.postconditions
2073
+ for arg in postcondition.args
2074
+ if arg not in ('OLD', 'result')
2075
+ )
2076
+ and all(
2077
+ arg in arg_set
2078
+ for snapshot in contracts.snapshots
2079
+ for arg in snapshot.args
2080
+ )
2081
+ )[1],
2082
+ "All arguments of contracts defined in function arguments"
2083
+ )
2084
+ # fmt: on
2085
+ def __init__(
2086
+ self,
2087
+ name: Identifier,
2088
+ arguments: Sequence[Argument],
2089
+ returns: Optional[TypeAnnotationUnion],
2090
+ description: Optional[DescriptionOfSignature],
2091
+ contracts: Contracts,
2092
+ parsed: parse.Method,
2093
+ ) -> None:
2094
+ """Initialize with the given values."""
2095
+ SignatureLike.__init__(
2096
+ self,
2097
+ name=name,
2098
+ arguments=arguments,
2099
+ returns=returns,
2100
+ description=description,
2101
+ contracts=contracts,
2102
+ parsed=parsed,
2103
+ )
2104
+
2105
+ @abc.abstractmethod
2106
+ def __repr__(self) -> str:
2107
+ # Signal that this is a pure abstract class.
2108
+ raise NotImplementedError()
2109
+
2110
+
2111
+ class ImplementationSpecificVerification(Verification):
2112
+ """Represent an implementation-specific verification function."""
2113
+
2114
+ def __init__(
2115
+ self,
2116
+ name: Identifier,
2117
+ arguments: Sequence[Argument],
2118
+ returns: Optional[TypeAnnotationUnion],
2119
+ description: Optional[DescriptionOfSignature],
2120
+ contracts: Contracts,
2121
+ parsed: parse.Method,
2122
+ ) -> None:
2123
+ """Initialize with the given values."""
2124
+ Verification.__init__(
2125
+ self,
2126
+ name=name,
2127
+ arguments=arguments,
2128
+ returns=returns,
2129
+ description=description,
2130
+ contracts=contracts,
2131
+ parsed=parsed,
2132
+ )
2133
+
2134
+ def __repr__(self) -> str:
2135
+ """Represent the instance as a string for easier debugging."""
2136
+ return (
2137
+ f"<{_MODULE_NAME}.{self.__class__.__name__} {self.name} at 0x{id(self):x}>"
2138
+ )
2139
+
2140
+
2141
+ class PatternVerification(Verification):
2142
+ """
2143
+ Represent a function that checks a string against a regular expression.
2144
+
2145
+ There is expected to be a single string argument (the text to be matched).
2146
+ The function is expected to return a boolean.
2147
+ """
2148
+
2149
+ #: Method as we understood it in the parse stage
2150
+ parsed: parse.UnderstoodMethod
2151
+
2152
+ #: Pattern, *i.e.* the regular expression, that the function checks against
2153
+ pattern: Final[str]
2154
+
2155
+ #: Expression extracted from the function body to be checked at the end
2156
+ pattern_expr: Final[parse_tree.Expression]
2157
+
2158
+ # fmt: off
2159
+ @require(
2160
+ lambda arguments:
2161
+ len(arguments) == 1
2162
+ and isinstance(arguments[0].type_annotation, PrimitiveTypeAnnotation)
2163
+ and arguments[0].type_annotation.a_type == PrimitiveType.STR,
2164
+ "There is a single string argument"
2165
+ )
2166
+ @require(
2167
+ lambda returns:
2168
+ (returns is not None)
2169
+ and isinstance(returns, PrimitiveTypeAnnotation)
2170
+ and returns.a_type == PrimitiveType.BOOL
2171
+ )
2172
+ # fmt: on
2173
+ def __init__(
2174
+ self,
2175
+ name: Identifier,
2176
+ arguments: Sequence[Argument],
2177
+ returns: Optional[TypeAnnotationUnion],
2178
+ description: Optional[DescriptionOfSignature],
2179
+ contracts: Contracts,
2180
+ pattern: str,
2181
+ parsed: parse.UnderstoodMethod,
2182
+ ) -> None:
2183
+ """Initialize with the given values."""
2184
+ Verification.__init__(
2185
+ self,
2186
+ name=name,
2187
+ arguments=arguments,
2188
+ returns=returns,
2189
+ description=description,
2190
+ contracts=contracts,
2191
+ parsed=parsed,
2192
+ )
2193
+
2194
+ self.pattern = pattern
2195
+ self.pattern_expr = PatternVerification._extract_pattern_expr(parsed.body)
2196
+
2197
+ @staticmethod
2198
+ def _extract_pattern_expr(body: Sequence[parse_tree.Node]) -> parse_tree.Expression:
2199
+ """Extract the pattern expression from the body of the pattern verification."""
2200
+ assert len(body) >= 1
2201
+
2202
+ assert isinstance(body[-1], parse_tree.Return)
2203
+ # noinspection PyUnresolvedReferences
2204
+ assert isinstance(body[-1].value, parse_tree.IsNotNone)
2205
+ # noinspection PyUnresolvedReferences
2206
+ assert isinstance(body[-1].value.value, parse_tree.FunctionCall)
2207
+ # noinspection PyUnresolvedReferences
2208
+ assert body[-1].value.value.name.identifier == "match"
2209
+
2210
+ # noinspection PyUnresolvedReferences
2211
+ match_call = body[-1].value.value
2212
+
2213
+ assert isinstance(
2214
+ match_call, parse_tree.FunctionCall
2215
+ ), f"{parse_tree.dump(match_call)}"
2216
+ assert match_call.name.identifier == "match"
2217
+
2218
+ assert isinstance(match_call.args[0], parse_tree.Expression)
2219
+ return match_call.args[0]
2220
+
2221
+ def __repr__(self) -> str:
2222
+ """Represent the instance as a string for easier debugging."""
2223
+ return (
2224
+ f"<{_MODULE_NAME}.{self.__class__.__name__} {self.name} at 0x{id(self):x}>"
2225
+ )
2226
+
2227
+
2228
+ class TranspilableVerification(Verification):
2229
+ """
2230
+ Represent a function that needs to be transpiled into the native code.
2231
+
2232
+ Unlike :class:`.PatternVerification`, we do not understand this verification
2233
+ function at the higher level, and can not use it further in the inference.
2234
+ Nevertheless, we can still transpile it into different target implementations.
2235
+ """
2236
+
2237
+ #: Method as we understood it in the parse stage
2238
+ parsed: parse.UnderstoodMethod
2239
+
2240
+ def __init__(
2241
+ self,
2242
+ name: Identifier,
2243
+ arguments: Sequence[Argument],
2244
+ returns: Optional[TypeAnnotationUnion],
2245
+ description: Optional[DescriptionOfSignature],
2246
+ contracts: Contracts,
2247
+ parsed: parse.UnderstoodMethod,
2248
+ ) -> None:
2249
+ """Initialize with the given values."""
2250
+ Verification.__init__(
2251
+ self,
2252
+ name=name,
2253
+ arguments=arguments,
2254
+ returns=returns,
2255
+ description=description,
2256
+ contracts=contracts,
2257
+ parsed=parsed,
2258
+ )
2259
+
2260
+ def __repr__(self) -> str:
2261
+ """Represent the instance as a string for easier debugging."""
2262
+ return (
2263
+ f"<{_MODULE_NAME}.{self.__class__.__name__} {self.name} at 0x{id(self):x}>"
2264
+ )
2265
+
2266
+
2267
+ # endregion
2268
+
2269
+
2270
+ class Signature(SignatureLike):
2271
+ """Represent a signature of a method in an interface."""
2272
+
2273
+ def __init__(
2274
+ self,
2275
+ name: Identifier,
2276
+ arguments: Sequence[Argument],
2277
+ returns: Optional[TypeAnnotationUnion],
2278
+ description: Optional[DescriptionOfSignature],
2279
+ contracts: Contracts,
2280
+ parsed: parse.Method,
2281
+ ) -> None:
2282
+ """
2283
+ Initialize with the given values.
2284
+
2285
+ The ``parsed`` refers to the method of the abstract or concrete class that
2286
+ defines the interface. Mind that we do not introduce interfaces as a concept
2287
+ in the meta-model.
2288
+ """
2289
+ SignatureLike.__init__(
2290
+ self,
2291
+ name=name,
2292
+ arguments=arguments,
2293
+ returns=returns,
2294
+ description=description,
2295
+ contracts=contracts,
2296
+ parsed=parsed,
2297
+ )
2298
+
2299
+ def __repr__(self) -> str:
2300
+ """Represent the instance as a string for easier debugging."""
2301
+ return (
2302
+ f"<{_MODULE_NAME}.{self.__class__.__name__} {self.name} at 0x{id(self):x}>"
2303
+ )
2304
+
2305
+
2306
+ class Interface:
2307
+ """
2308
+ Represent an interface of some abstract and/or concrete classes.
2309
+
2310
+ Mind that the concept of interfaces is *not* used in the meta-model. We introduce
2311
+ it at the intermediate stage to facilitate generation of the code, especially for
2312
+ targets where multiple inheritance is not supported.
2313
+ """
2314
+
2315
+ #: Class which this interface is based on
2316
+ base: Final["ClassUnion"]
2317
+
2318
+ #: Name of the interface
2319
+ name: Final[Identifier]
2320
+
2321
+ inheritances: Final[Sequence["Interface"]]
2322
+
2323
+ #: List of concrete classes that implement this interface
2324
+ implementers: Sequence["ConcreteClass"]
2325
+
2326
+ #: List of properties assumed by the interface
2327
+ properties: Final[Sequence[Property]]
2328
+
2329
+ #: List of method signatures assumed by the interface
2330
+ signatures: Final[Sequence[Signature]]
2331
+
2332
+ #: Description of the interface, taken from class
2333
+ description: Final[Optional[DescriptionOfOurType]]
2334
+
2335
+ #: Relation to the class from the parse stage
2336
+ parsed: Final[parse.Class]
2337
+
2338
+ #: Map all properties by their identifiers to the corresponding objects
2339
+ properties_by_name: Final[Mapping[Identifier, Property]]
2340
+
2341
+ #: Collect IDs (with :py:func:`id`) of the property objects in a set
2342
+ property_id_set: Final[FrozenSet[int]]
2343
+
2344
+ def __init__(
2345
+ self,
2346
+ base: "ClassUnion",
2347
+ inheritances: Sequence["Interface"],
2348
+ ) -> None:
2349
+ """Initialize with the given values."""
2350
+ self.base = base
2351
+
2352
+ self.name = base.name
2353
+ self.inheritances = inheritances
2354
+
2355
+ implementers = list(base.concrete_descendants)
2356
+
2357
+ if isinstance(base, ConcreteClass):
2358
+ implementers.append(base)
2359
+
2360
+ self.implementers = implementers
2361
+
2362
+ self.properties = [
2363
+ prop for prop in base.properties if prop.specified_for is base
2364
+ ]
2365
+
2366
+ self.signatures = [
2367
+ Signature(
2368
+ name=method.name,
2369
+ arguments=method.arguments,
2370
+ returns=method.returns,
2371
+ description=method.description,
2372
+ contracts=method.contracts,
2373
+ parsed=method.parsed,
2374
+ )
2375
+ for method in base.methods
2376
+ if method.specified_for is base
2377
+ ]
2378
+
2379
+ self.description = base.description
2380
+ self.parsed = base.parsed
2381
+
2382
+ self.properties_by_name: Mapping[Identifier, Property] = {
2383
+ prop.name: prop for prop in self.properties
2384
+ }
2385
+
2386
+ self.property_id_set = frozenset(id(prop) for prop in self.properties)
2387
+
2388
+ def __repr__(self) -> str:
2389
+ """Represent the instance as a string for easier debugging."""
2390
+ return (
2391
+ f"<{_MODULE_NAME}.{self.__class__.__name__} {self.name} at 0x{id(self):x}>"
2392
+ )
2393
+
2394
+
2395
+ T = TypeVar("T")
2396
+
2397
+
2398
+ class MetaModel:
2399
+ """Collect information about the underlying meta-model."""
2400
+
2401
+ #: Description of the meta-model extracted from the docstring
2402
+ description: Final[Optional[DescriptionOfMetaModel]]
2403
+
2404
+ #: Specify the version of the meta-model
2405
+ version: Final[str]
2406
+
2407
+ #: Specify the XML namespace that is used both for de/serialization and for schema
2408
+ #: definitions
2409
+ xml_namespace: Final[Stripped]
2410
+
2411
+ @require(lambda xml_namespace: not xml_namespace.endswith("/"))
2412
+ @require(lambda xml_namespace: '"' not in xml_namespace)
2413
+ @require(lambda xml_namespace: "'" not in xml_namespace)
2414
+ def __init__(
2415
+ self,
2416
+ version: str,
2417
+ xml_namespace: Stripped,
2418
+ description: Optional[DescriptionOfMetaModel],
2419
+ ) -> None:
2420
+ self.version = version
2421
+ self.xml_namespace = xml_namespace
2422
+ self.description = description
2423
+
2424
+
2425
+ ClassUnion = Union[AbstractClass, ConcreteClass]
2426
+
2427
+
2428
+ class SymbolTable:
2429
+ """Represent all the symbols of the intermediate representation."""
2430
+
2431
+ #: List of all our types that we need for the code generation
2432
+ our_types: Final[Sequence["OurType"]]
2433
+
2434
+ #: List of all our types, topologically sorted by inheritance
2435
+ our_types_topologically_sorted: Final[Sequence["OurType"]]
2436
+
2437
+ #: List all constants defined in the meta-model
2438
+ constants: Final[Sequence["ConstantUnion"]]
2439
+
2440
+ #: Map constants by their name
2441
+ constants_by_name: Final[Mapping[Identifier, "ConstantUnion"]]
2442
+
2443
+ #: List of all functions used in the verification
2444
+ verification_functions: Final[Sequence["VerificationUnion"]]
2445
+
2446
+ #: Map verification functions by their name
2447
+ verification_functions_by_name: Final[Mapping[Identifier, "VerificationUnion"]]
2448
+
2449
+ #: Additional information about the source meta-model
2450
+ meta_model: Final[MetaModel]
2451
+
2452
+ _name_to_our_type: Final[Mapping[Identifier, "OurType"]]
2453
+
2454
+ #: List all the enumerations in the symbol table
2455
+ enumerations: Final[Sequence["Enumeration"]]
2456
+
2457
+ #: List all the constrained primitives in the symbol table
2458
+ constrained_primitives: Final[Sequence["ConstrainedPrimitive"]]
2459
+
2460
+ #: List all the classes (abstract and concrete alike) in the symbol table
2461
+ classes: Final[Sequence["ClassUnion"]]
2462
+
2463
+ #: List all the concrete classes in the symbol table
2464
+ concrete_classes: Final[Sequence["ConcreteClass"]]
2465
+
2466
+ # fmt: off
2467
+ @require(
2468
+ lambda our_types: (
2469
+ names := [our_type.name for our_type in our_types],
2470
+ len(names) == len(set(names)),
2471
+ )[1],
2472
+ "Names of our types unique",
2473
+ )
2474
+ @require(
2475
+ lambda our_types, our_types_topologically_sorted:
2476
+ set(
2477
+ id(our_type)
2478
+ for our_type in our_types
2479
+ if not isinstance(our_type, Enumeration)
2480
+ )
2481
+ == set(id(our_type) for our_type in our_types_topologically_sorted),
2482
+ "Only maybe the order differs between our_types and "
2483
+ "our_types_topologically_sorted"
2484
+ )
2485
+ @require(
2486
+ lambda constants: (
2487
+ names := [constant.name for constant in constants],
2488
+ len(names) == len(set(names)),
2489
+ )[1],
2490
+ "Names of the constants unique",
2491
+ )
2492
+ @ensure(
2493
+ lambda self:
2494
+ all(
2495
+ self.must_find_enumeration(enumeration.name)
2496
+ for enumeration in self.enumerations
2497
+ )
2498
+ )
2499
+ @ensure(
2500
+ lambda self:
2501
+ all(
2502
+ self.must_find_constrained_primitive(constrained_primitive.name)
2503
+ for constrained_primitive in self.constrained_primitives
2504
+ )
2505
+ )
2506
+ @ensure(
2507
+ lambda self:
2508
+ all(
2509
+ self.must_find_concrete_class(cls.name)
2510
+ for cls in self.concrete_classes
2511
+ )
2512
+ )
2513
+ @ensure(
2514
+ lambda self:
2515
+ all(
2516
+ self.must_find_class(cls.name)
2517
+ for cls in self.classes
2518
+ )
2519
+ )
2520
+ @ensure(
2521
+ lambda self:
2522
+ all(
2523
+ self.verification_functions_by_name[func.name] is func
2524
+ for func in self.verification_functions
2525
+ )
2526
+ and len(self.verification_functions_by_name) == len(
2527
+ self.verification_functions),
2528
+ "The verification functions and their mapping by name are consistent"
2529
+ )
2530
+ @ensure(
2531
+ lambda self:
2532
+ all(
2533
+ self.constants_by_name[constant.name] is constant
2534
+ for constant in self.constants
2535
+ ) and len(self.constants_by_name) == len(self.constants),
2536
+ "The constants and their mapping by name are consistent"
2537
+ )
2538
+ @ensure(
2539
+ lambda self:
2540
+ all(
2541
+ (
2542
+ found_our_type := self.find_our_type(our_type.name),
2543
+ found_our_type is not None and found_our_type is our_type
2544
+ )[1]
2545
+ for our_type in self.our_types
2546
+ ),
2547
+ "Finding our types is consistent with ``our_types``"
2548
+ )
2549
+ # fmt: on
2550
+ def __init__(
2551
+ self,
2552
+ our_types: Sequence["OurType"],
2553
+ our_types_topologically_sorted: Sequence["OurTypeExceptEnumeration"],
2554
+ constants: Sequence["ConstantUnion"],
2555
+ verification_functions: Sequence["VerificationUnion"],
2556
+ meta_model: MetaModel,
2557
+ ) -> None:
2558
+ """Initialize with the given values and map by name."""
2559
+ self.our_types = our_types
2560
+ self.our_types_topologically_sorted = our_types_topologically_sorted
2561
+ self.constants = constants
2562
+ self.verification_functions = verification_functions
2563
+ self.meta_model = meta_model
2564
+
2565
+ self.constants_by_name = {constant.name: constant for constant in constants}
2566
+
2567
+ self.verification_functions_by_name = {
2568
+ func.name: func for func in self.verification_functions
2569
+ }
2570
+
2571
+ self.enumerations = [
2572
+ our_type for our_type in our_types if isinstance(our_type, Enumeration)
2573
+ ]
2574
+
2575
+ self.classes = [
2576
+ our_type
2577
+ for our_type in our_types
2578
+ if isinstance(our_type, (AbstractClass, ConcreteClass))
2579
+ ]
2580
+
2581
+ self.concrete_classes = [
2582
+ our_type for our_type in our_types if isinstance(our_type, ConcreteClass)
2583
+ ]
2584
+
2585
+ self.constrained_primitives = [
2586
+ our_type
2587
+ for our_type in our_types
2588
+ if isinstance(our_type, ConstrainedPrimitive)
2589
+ ]
2590
+
2591
+ self._name_to_our_type = {our_type.name: our_type for our_type in our_types}
2592
+
2593
+ def find_our_type(self, name: Identifier) -> Optional["OurType"]:
2594
+ """Find our type with the given ``name``."""
2595
+ return self._name_to_our_type.get(name, None)
2596
+
2597
+ def must_find_our_type(self, name: Identifier) -> "OurType":
2598
+ """
2599
+ Find our type with the given ``name``.
2600
+
2601
+ :raise: :py:class:`KeyError` if the ``name`` is not in our types.
2602
+ """
2603
+ result = self.find_our_type(name)
2604
+ if result is None:
2605
+ raise KeyError(name)
2606
+
2607
+ return result
2608
+
2609
+ def must_find_enumeration(self, name: Identifier) -> "Enumeration":
2610
+ """
2611
+ Find the enumeration with the given ``name``.
2612
+
2613
+ :raise: :py:class:`KeyError` if the ``name`` is not in our types.
2614
+ :raise:
2615
+ :py:class:`TypeError` if the ``name`` is our type,
2616
+ but is not an enumeration.
2617
+ """
2618
+ result = self.find_our_type(name)
2619
+ if result is None:
2620
+ raise KeyError(name)
2621
+
2622
+ if not isinstance(result, Enumeration):
2623
+ raise TypeError(
2624
+ f"Found {name} in our types; "
2625
+ f"expected an instance of {Enumeration.__name__}, "
2626
+ f"but got {type(result)}: {result}"
2627
+ )
2628
+
2629
+ return result
2630
+
2631
+ def must_find_constrained_primitive(
2632
+ self, name: Identifier
2633
+ ) -> "ConstrainedPrimitive":
2634
+ """
2635
+ Find the constrained primitive with the given ``name``.
2636
+
2637
+ :raise: :py:class:`KeyError` if the ``name`` is not in our types.
2638
+ :raise:
2639
+ :py:class:`TypeError` if the ``name`` is our type,
2640
+ but is not a constrained primitive.
2641
+ """
2642
+ result = self.find_our_type(name)
2643
+ if result is None:
2644
+ raise KeyError(name)
2645
+
2646
+ if not isinstance(result, ConstrainedPrimitive):
2647
+ raise TypeError(
2648
+ f"Found {name} in our types; "
2649
+ f"expected an instance of {ConstrainedPrimitive.__name__}, "
2650
+ f"but got {type(result)}: {result}"
2651
+ )
2652
+
2653
+ return result
2654
+
2655
+ def must_find_class(self, name: Identifier) -> "ClassUnion":
2656
+ """
2657
+ Find the class with the given ``name``.
2658
+
2659
+ :raise: :py:class:`KeyError` if the ``name`` is not in our types.
2660
+ :raise: :py:class:`TypeError` if the ``name`` is our type, but is not a class.
2661
+ """
2662
+ result = self.find_our_type(name)
2663
+ if result is None:
2664
+ raise KeyError(name)
2665
+
2666
+ if not isinstance(result, (AbstractClass, ConcreteClass)):
2667
+ raise TypeError(
2668
+ f"Found {name} in our types; "
2669
+ f"expected an instance of {ClassUnion}, "
2670
+ f"but got {type(result)}: {result}"
2671
+ )
2672
+
2673
+ return result
2674
+
2675
+ def must_find_abstract_class(self, name: Identifier) -> "AbstractClass":
2676
+ """
2677
+ Find the abstract class with the given ``name``.
2678
+
2679
+ :raise: :py:class:`KeyError` if the ``name`` is not in our types.
2680
+ :raise:
2681
+ :py:class:`TypeError` if the ``name`` is our type,
2682
+ but is not an abstract class.
2683
+ """
2684
+ result = self.find_our_type(name)
2685
+ if result is None:
2686
+ raise KeyError(name)
2687
+
2688
+ if not isinstance(result, AbstractClass):
2689
+ raise TypeError(
2690
+ f"Found {name} in our types; "
2691
+ f"expected an instance of {AbstractClass.__name__}, "
2692
+ f"but got {type(result)}: {result}"
2693
+ )
2694
+
2695
+ return result
2696
+
2697
+ def must_find_concrete_class(self, name: Identifier) -> "ConcreteClass":
2698
+ """
2699
+ Find the concrete class with the given ``name``.
2700
+
2701
+ :raise: :py:class:`KeyError` if the ``name`` is not in our types.
2702
+ :raise:
2703
+ :py:class:`TypeError` if the ``name`` is our type,
2704
+ but is not a concrete class.
2705
+ """
2706
+ result = self.find_our_type(name)
2707
+ if result is None:
2708
+ raise KeyError(name)
2709
+
2710
+ if not isinstance(result, ConcreteClass):
2711
+ raise TypeError(
2712
+ f"Found {name} in our types; "
2713
+ f"expected an instance of {ConcreteClass.__name__}, "
2714
+ f"but got {type(result)}: {result}"
2715
+ )
2716
+
2717
+ return result
2718
+
2719
+ def must_find_class_or_constrained_primitive(
2720
+ self, name: Identifier
2721
+ ) -> Union["ClassUnion", ConstrainedPrimitive]:
2722
+ """
2723
+ Find the class with the given ``name``.
2724
+
2725
+ :raise: :py:class:`KeyError` if the ``name`` is not in our types.
2726
+ :raise:
2727
+ :py:class:`TypeError` if the ``name`` is our type, but is neither a class
2728
+ nor a constrained primitive
2729
+ """
2730
+ result = self.find_our_type(name)
2731
+ if result is None:
2732
+ raise KeyError(name)
2733
+
2734
+ if not isinstance(result, (AbstractClass, ConcreteClass, ConstrainedPrimitive)):
2735
+ raise TypeError(
2736
+ f"Found {name} in our types; "
2737
+ f"expected an instance of either {AbstractClass.__name__}, "
2738
+ f"{ConcreteClass.__name__} or {ConstrainedPrimitive.__name__},"
2739
+ f"but got {type(result)}: {result}"
2740
+ )
2741
+
2742
+ return result
2743
+
2744
+
2745
+ def try_primitive_type(type_annotation: TypeAnnotationUnion) -> Optional[PrimitiveType]:
2746
+ """
2747
+ Try to get the underlying primitive type of the type annotation.
2748
+
2749
+ If it is neither a primitive type annotation nor a constrained primitive,
2750
+ return None.
2751
+ """
2752
+ if isinstance(type_annotation, PrimitiveTypeAnnotation):
2753
+ return type_annotation.a_type
2754
+
2755
+ elif isinstance(type_annotation, OurTypeAnnotation) and isinstance(
2756
+ type_annotation.our_type, ConstrainedPrimitive
2757
+ ):
2758
+ return type_annotation.our_type.constrainee
2759
+ else:
2760
+ return None
2761
+
2762
+
2763
+ def map_descendability(
2764
+ type_annotation: TypeAnnotationUnion,
2765
+ ) -> MutableMapping[TypeAnnotationUnion, bool]:
2766
+ """
2767
+ Map the type annotation recursively by the descendability.
2768
+
2769
+ The descendability means that the type annotation references an interface
2770
+ or a class *or* that it is a subscripted type annotation which subscribes one or
2771
+ more classes of the meta-model.
2772
+
2773
+ Constrained primitives are considered primitives and thus non-descendable.
2774
+
2775
+ The mapping is a form of caching. Otherwise, the time complexity would be quadratic
2776
+ if we queried at each type annotation subscript.
2777
+ """
2778
+ mapping = dict() # type: MutableMapping[TypeAnnotationUnion, bool]
2779
+
2780
+ def recurse(a_type_annotation: TypeAnnotationUnion) -> bool:
2781
+ """Recursively iterate over subscripted type annotations."""
2782
+ if isinstance(a_type_annotation, PrimitiveTypeAnnotation):
2783
+ mapping[a_type_annotation] = False
2784
+ return False
2785
+
2786
+ elif isinstance(a_type_annotation, OurTypeAnnotation):
2787
+ result: bool
2788
+ if isinstance(a_type_annotation.our_type, Enumeration):
2789
+ result = False
2790
+ elif isinstance(a_type_annotation.our_type, ConstrainedPrimitive):
2791
+ result = False
2792
+ elif isinstance(a_type_annotation.our_type, Class):
2793
+ result = True
2794
+ else:
2795
+ assert_never(a_type_annotation.our_type)
2796
+
2797
+ mapping[a_type_annotation] = result
2798
+ return result
2799
+
2800
+ elif isinstance(a_type_annotation, ListTypeAnnotation):
2801
+ result = recurse(a_type_annotation=a_type_annotation.items)
2802
+ mapping[a_type_annotation] = result
2803
+ return result
2804
+
2805
+ elif isinstance(a_type_annotation, OptionalTypeAnnotation):
2806
+ result = recurse(a_type_annotation=a_type_annotation.value)
2807
+ mapping[a_type_annotation] = result
2808
+ return result
2809
+
2810
+ else:
2811
+ assert_never(a_type_annotation)
2812
+
2813
+ raise AssertionError("Should not have gotten here")
2814
+
2815
+ _ = recurse(a_type_annotation=type_annotation)
2816
+
2817
+ return mapping
2818
+
2819
+
2820
+ class _ConstructorArgumentOfClass:
2821
+ """Represent a constructor argument with its corresponding class."""
2822
+
2823
+ def __init__(self, arg: Argument, cls: Class) -> None:
2824
+ """Initialize with the given values."""
2825
+ self.arg = arg
2826
+ self.cls = cls
2827
+
2828
+
2829
+ def collect_ids_of_our_types_in_properties(symbol_table: SymbolTable) -> Set[int]:
2830
+ """
2831
+ Collect the IDs of our types occurring in type annotations of the properties.
2832
+
2833
+ The IDs refer to IDs of the Python objects in this context.
2834
+ """
2835
+ result = set() # type: Set[int]
2836
+ for cls in symbol_table.classes:
2837
+ for prop in cls.properties:
2838
+ type_anno = prop.type_annotation
2839
+
2840
+ old_type_anno = None # type: Optional[TypeAnnotation]
2841
+ while True:
2842
+ if isinstance(type_anno, OptionalTypeAnnotation):
2843
+ # noinspection PyUnresolvedReferences
2844
+ type_anno = type_anno.value
2845
+ elif isinstance(type_anno, ListTypeAnnotation):
2846
+ type_anno = type_anno.items
2847
+ elif isinstance(type_anno, PrimitiveTypeAnnotation):
2848
+ break
2849
+ elif isinstance(type_anno, OurTypeAnnotation):
2850
+ result.add(id(type_anno.our_type))
2851
+ break
2852
+ else:
2853
+ assert_never(type_anno)
2854
+
2855
+ assert old_type_anno is not type_anno, "Loop invariant"
2856
+ old_type_anno = type_anno
2857
+
2858
+ return result
2859
+
2860
+
2861
+ DescriptionUnion = Union[
2862
+ DescriptionOfMetaModel,
2863
+ DescriptionOfOurType,
2864
+ DescriptionOfProperty,
2865
+ DescriptionOfEnumerationLiteral,
2866
+ DescriptionOfSignature,
2867
+ DescriptionOfConstant,
2868
+ ]
2869
+ assert_union_of_descendants_exhaustive(
2870
+ union=DescriptionUnion, base_class=SummaryRemarksDescription
2871
+ )
2872
+ assert_union_of_descendants_exhaustive(union=ClassUnion, base_class=Class)
2873
+
2874
+ ClassUnionAsTuple = (AbstractClass, ConcreteClass)
2875
+ assert ClassUnionAsTuple == get_args(ClassUnion)
2876
+
2877
+ MethodUnion = Union[UnderstoodMethod, ImplementationSpecificMethod]
2878
+ assert_union_of_descendants_exhaustive(union=MethodUnion, base_class=Method)
2879
+
2880
+ OurType = Union[Enumeration, ConstrainedPrimitive, ClassUnion]
2881
+
2882
+ OurTypeExceptEnumeration = Union[ConstrainedPrimitive, ClassUnion]
2883
+ assert_union_without_excluded(
2884
+ original_union=OurType,
2885
+ subset_union=OurTypeExceptEnumeration,
2886
+ excluded=[Enumeration],
2887
+ )
2888
+
2889
+ ConstantSetUnion = Union[ConstantSetOfPrimitives, ConstantSetOfEnumerationLiterals]
2890
+
2891
+ ConstantUnion = Union[
2892
+ ConstantPrimitive, ConstantSetOfPrimitives, ConstantSetOfEnumerationLiterals
2893
+ ]
2894
+ assert_union_of_descendants_exhaustive(union=ConstantUnion, base_class=Constant)
2895
+
2896
+ VerificationUnion = Union[
2897
+ ImplementationSpecificVerification,
2898
+ PatternVerification,
2899
+ TranspilableVerification,
2900
+ ]
2901
+ assert_union_of_descendants_exhaustive(union=VerificationUnion, base_class=Verification)