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