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,1391 @@
1
+ """Generate Python code for JSON-ization based on the intermediate representation."""
2
+
3
+ import io
4
+ import textwrap
5
+ from typing import Tuple, Optional, List
6
+
7
+ from icontract import ensure, require
8
+
9
+ from aas_core_codegen import intermediate, naming, specific_implementations
10
+ from aas_core_codegen.common import (
11
+ Error,
12
+ Stripped,
13
+ Identifier,
14
+ assert_never,
15
+ indent_but_first_line,
16
+ )
17
+ from aas_core_codegen.python import (
18
+ common as python_common,
19
+ naming as python_naming,
20
+ )
21
+ from aas_core_codegen.python.common import (
22
+ INDENT as I,
23
+ INDENT2 as II,
24
+ INDENT3 as III,
25
+ INDENT4 as IIII,
26
+ )
27
+
28
+
29
+ # region De-serialization
30
+
31
+
32
+ def _generate_bool_from_jsonable() -> Stripped:
33
+ """Generate the function to decode a ``bool`` from a JSON-able."""
34
+ return Stripped(
35
+ f"""\
36
+ def _bool_from_jsonable(
37
+ {I}jsonable: Jsonable
38
+ ) -> bool:
39
+ {I}\"\"\"
40
+ {I}Parse :paramref:`jsonable` as a boolean.
41
+
42
+ {I}:param jsonable: JSON-able structure to be parsed
43
+ {I}:return: parsed boolean
44
+ {I}:raise: :py:class:`DeserializationException` if unexpected :paramref:`jsonable`
45
+ {I}\"\"\"
46
+ {I}if not isinstance(jsonable, bool):
47
+ {II}raise DeserializationException(
48
+ {III}f"Expected a bool, but got: {{type(jsonable)}}"
49
+ {II})
50
+ {I}return jsonable"""
51
+ )
52
+
53
+
54
+ def _generate_int_from_jsonable() -> Stripped:
55
+ """Generate the function to decode an ``int`` from a JSON-able."""
56
+ return Stripped(
57
+ f"""\
58
+ def _int_from_jsonable(
59
+ {I}jsonable: Jsonable
60
+ ) -> int:
61
+ {I}\"\"\"
62
+ {I}Parse :paramref:`jsonable` as an integer.
63
+
64
+ {I}:param jsonable: JSON-able structure to be parsed
65
+ {I}:return: parsed integer
66
+ {I}:raise: :py:class:`DeserializationException` if unexpected :paramref:`jsonable`
67
+ {I}\"\"\"
68
+ {I}if not isinstance(jsonable, int):
69
+ {II}raise DeserializationException(
70
+ {III}f"Expected an int, but got: {{type(jsonable)}}"
71
+ {II})
72
+ {I}return jsonable"""
73
+ )
74
+
75
+
76
+ def _generate_float_from_jsonable() -> Stripped:
77
+ """Generate the function to decode a ``float`` from a JSON-able."""
78
+ return Stripped(
79
+ f"""\
80
+ def _float_from_jsonable(
81
+ {I}jsonable: Jsonable
82
+ ) -> float:
83
+ {I}\"\"\"
84
+ {I}Parse :paramref:`jsonable` as a floating-point number.
85
+
86
+ {I}:param jsonable: JSON-able structure to be parsed
87
+ {I}:return: parsed floating-point number
88
+ {I}:raise: :py:class:`DeserializationException` if unexpected :paramref:`jsonable`
89
+ {I}\"\"\"
90
+ {I}if not isinstance(jsonable, float):
91
+ {II}raise DeserializationException(
92
+ {III}f"Expected a float, but got: {{type(jsonable)}}"
93
+ {II})
94
+ {I}return jsonable"""
95
+ )
96
+
97
+
98
+ def _generate_str_from_jsonable() -> Stripped:
99
+ """Generate the function to decode a ``str`` from a JSON-able."""
100
+ return Stripped(
101
+ f"""\
102
+ def _str_from_jsonable(
103
+ {I}jsonable: Jsonable
104
+ ) -> str:
105
+ {I}\"\"\"
106
+ {I}Parse :paramref:`jsonable` as a string.
107
+
108
+ {I}:param jsonable: JSON-able structure to be parsed
109
+ {I}:return: parsed string
110
+ {I}:raise: :py:class:`DeserializationException` if unexpected :paramref:`jsonable`
111
+ {I}\"\"\"
112
+ {I}if not isinstance(jsonable, str):
113
+ {II}raise DeserializationException(
114
+ {III}f"Expected a str, but got: {{type(jsonable)}}"
115
+ {II})
116
+ {I}return jsonable"""
117
+ )
118
+
119
+
120
+ def _generate_bytes_from_jsonable() -> Stripped:
121
+ """Generate the function to decode ``bytes`` from a JSON-able."""
122
+ return Stripped(
123
+ f"""\
124
+ def _bytes_from_jsonable(
125
+ {I}jsonable: Jsonable
126
+ ) -> bytes:
127
+ {I}\"\"\"
128
+ {I}Decode :paramref:`jsonable` as base64 string to a ``bytearray``.
129
+
130
+ {I}:param jsonable: JSON-able structure to be decoded
131
+ {I}:return: decoded bytearray
132
+ {I}:raise: :py:class:`DeserializationException` if unexpected :paramref:`jsonable`
133
+ {I}\"\"\"
134
+ {I}if not isinstance(jsonable, str):
135
+ {II}raise DeserializationException(
136
+ {III}f"Expected a str, but got: {{type(jsonable)}}"
137
+ {II})
138
+
139
+ {I}return base64.b64decode(
140
+ {II}jsonable.encode('ascii')
141
+ {I})"""
142
+ )
143
+
144
+
145
+ def _generate_enumeration_from_jsonable(
146
+ enumeration: intermediate.Enumeration,
147
+ ) -> Stripped:
148
+ """Generate the deserialization method for an enumeration."""
149
+ enum_name = python_naming.enum_name(identifier=enumeration.name)
150
+
151
+ function_name = python_naming.function_name(
152
+ Identifier(f"{enumeration.name}_from_jsonable")
153
+ )
154
+
155
+ enum_from_str = python_naming.function_name(
156
+ Identifier(f"{enumeration.name}_from_str")
157
+ )
158
+
159
+ return Stripped(
160
+ f"""\
161
+ def {function_name}(
162
+ {I}jsonable: Jsonable
163
+ ) -> aas_types.{enum_name}:
164
+ {I}\"\"\"
165
+ {I}Convert the JSON-able structure :paramref:`jsonable` to a literal of
166
+ {I}:py:class:`.types.{enum_name}`.
167
+
168
+ {I}:param jsonable: JSON-able structure to be parsed
169
+ {I}:return: parsed literal
170
+ {I}:raise: :py:class:`.DeserializationException` if unexpected :paramref:`jsonable`
171
+ {I}\"\"\"
172
+ {I}if not isinstance(jsonable, str):
173
+ {II}raise DeserializationException(
174
+ {III}"Expected a str, but got: {{type(jsonable)}}"
175
+ {II})
176
+
177
+ {I}literal = aas_stringification.{enum_from_str}(jsonable)
178
+ {I}if literal is None:
179
+ {II}raise DeserializationException(
180
+ {III}f"Not a valid string representation of "
181
+ {III}f"a literal of {enum_name}: {{jsonable}}"
182
+ {II})
183
+
184
+ {I}return literal"""
185
+ )
186
+
187
+
188
+ def _generate_is_array_like() -> Stripped:
189
+ """Generate the function to check that the jsonable is an array-like object."""
190
+ return Stripped(
191
+ f'''\
192
+ def _try_to_cast_to_array_like(
193
+ {I}jsonable: Jsonable
194
+ ) -> Optional[Iterable[Any]]:
195
+ {I}"""
196
+ {I}Try to cast the ``jsonable`` to something like a JSON array.
197
+
198
+ {I}In particular, we explicitly check that the ``jsonable`` is not a mapping, as we
199
+ {I}do not want to mistake dictionaries (*i.e.* de-serialized JSON objects) for lists.
200
+
201
+ {I}>>> assert _try_to_cast_to_array_like(True) is None
202
+
203
+ {I}>>> assert _try_to_cast_to_array_like(0) is None
204
+
205
+ {I}>>> assert _try_to_cast_to_array_like(2.2) is None
206
+
207
+ {I}>>> assert _try_to_cast_to_array_like("hello") is None
208
+
209
+ {I}>>> assert _try_to_cast_to_array_like(b"hello") is None
210
+
211
+ {I}>>> _try_to_cast_to_array_like([1, 2])
212
+ {I}[1, 2]
213
+
214
+ {I}>>> assert _try_to_cast_to_array_like({{"a": 3}}) is None
215
+
216
+ {I}>>> assert _try_to_cast_to_array_like(collections.OrderedDict()) is None
217
+
218
+ {I}>>> _try_to_cast_to_array_like(range(1, 2))
219
+ {I}range(1, 2)
220
+
221
+ {I}>>> _try_to_cast_to_array_like((1, 2))
222
+ {I}(1, 2)
223
+
224
+ {I}>>> assert _try_to_cast_to_array_like({{1, 2, 3}}) is None
225
+ {I}"""
226
+ {I}if (
227
+ {II}
228
+ {II}not isinstance(jsonable, (str, bytearray, bytes))
229
+ {II}and hasattr(jsonable, "__iter__")
230
+ {II}and not hasattr(jsonable, "keys")
231
+ {II}# NOTE (mristin):
232
+ {II}# There is no easy way to check for sets as opposed to sequence except
233
+ {II}# for checking for direct inheritance. A sequence also inherits from
234
+ {II}# a collection, so both sequences and sets provide ``__contains__`` method.
235
+ {II}#
236
+ {II}# See: https://docs.python.org/3/library/collections.abc.html
237
+ {II}and not isinstance(jsonable, collections.abc.Set)
238
+ {I}):
239
+ {II}return cast(Iterable[Any], jsonable)
240
+
241
+ {I}return None'''
242
+ )
243
+
244
+
245
+ def _generate_dispatch_map_for_abstract_class(
246
+ cls: intermediate.AbstractClass,
247
+ ) -> Stripped:
248
+ """Generate a mapping model type 🠒 de-serialization function."""
249
+ assert len(cls.concrete_descendants) > 0, (
250
+ "Expected an abstract class to have concrete descendants. "
251
+ "Otherwise we do not know how to de-serialize it."
252
+ )
253
+
254
+ mapping_name = python_naming.private_constant_name(
255
+ Identifier(f"{cls.name}_from_jsonable_dispatch")
256
+ )
257
+
258
+ cls_name = python_naming.class_name(cls.name)
259
+
260
+ mapping_writer = io.StringIO()
261
+ mapping_writer.write(
262
+ f"""\
263
+ {mapping_name}: Mapping[
264
+ {I}str,
265
+ {I}Callable[[Jsonable], aas_types.{cls_name}]
266
+ ] = {{
267
+ """
268
+ )
269
+
270
+ for descendant in cls.concrete_descendants:
271
+ function_name_for_descendant = python_naming.function_name(
272
+ Identifier(f"{descendant.name}_from_jsonable")
273
+ )
274
+
275
+ descendant_literal = python_common.string_literal(
276
+ naming.json_model_type(descendant.name)
277
+ )
278
+
279
+ mapping_writer.write(
280
+ f"""\
281
+ {I}{descendant_literal}: {function_name_for_descendant},
282
+ """
283
+ )
284
+
285
+ mapping_writer.write("}")
286
+
287
+ return Stripped(mapping_writer.getvalue())
288
+
289
+
290
+ @require(lambda cls: len(cls.concrete_descendants) > 0)
291
+ def _generate_dispatch_map_for_concrete_class(
292
+ cls: intermediate.ConcreteClass,
293
+ ) -> Stripped:
294
+ """
295
+ Generate a mapping model type 🠒 de-serialization function.
296
+
297
+ The ``jsonable`` can not be parsed straight-away as we don't know which class
298
+ (the actual one or one of the descendants) needs to be parsed.
299
+ """
300
+ mapping_name = python_naming.private_constant_name(
301
+ Identifier(f"{cls.name}_from_jsonable_dispatch")
302
+ )
303
+
304
+ cls_name = python_naming.class_name(cls.name)
305
+
306
+ mapping_writer = io.StringIO()
307
+ mapping_writer.write(
308
+ f"""\
309
+ {mapping_name}: Mapping[
310
+ {I}str,
311
+ {I}Callable[[Jsonable], aas_types.{cls_name}]
312
+ ] = {{
313
+ """
314
+ )
315
+
316
+ function_name_for_cls = python_naming.function_name(
317
+ Identifier(f"_{cls.name}_from_jsonable_without_dispatch")
318
+ )
319
+
320
+ cls_literal = python_common.string_literal(naming.json_model_type(cls.name))
321
+
322
+ mapping_writer.write(
323
+ f"""\
324
+ {I}{cls_literal}: {function_name_for_cls},
325
+ """
326
+ )
327
+
328
+ for descendant in cls.concrete_descendants:
329
+ function_name_for_descendant = python_naming.function_name(
330
+ Identifier(f"{descendant.name}_from_jsonable")
331
+ )
332
+
333
+ descendant_literal = python_common.string_literal(
334
+ naming.json_model_type(descendant.name)
335
+ )
336
+
337
+ mapping_writer.write(
338
+ f"""\
339
+ {I}{descendant_literal}: {function_name_for_descendant},
340
+ """
341
+ )
342
+
343
+ mapping_writer.write("}")
344
+
345
+ return Stripped(mapping_writer.getvalue())
346
+
347
+
348
+ # fmt: off
349
+ @require(
350
+ lambda cls: len(cls.concrete_descendants) > 0,
351
+ "Dispatch is only possible if there are one or more concrete descendants"
352
+ )
353
+ # fmt: on
354
+ def _generate_dispatch_from_jsonable(cls: intermediate.ClassUnion) -> Stripped:
355
+ """Generate the de-serialization dispatch for an abstract class."""
356
+ function_name = python_naming.function_name(Identifier(f"{cls.name}_from_jsonable"))
357
+
358
+ cls_name = python_naming.class_name(cls.name)
359
+
360
+ mapping_name = python_naming.private_constant_name(
361
+ Identifier(f"{cls.name}_from_jsonable_dispatch")
362
+ )
363
+
364
+ return Stripped(
365
+ f"""\
366
+ def {function_name}(
367
+ {II}jsonable: Jsonable
368
+ ) -> aas_types.{cls_name}:
369
+ {I}\"\"\"
370
+ {I}Parse an instance of :py:class:`.types.{cls_name}` from the JSON-able
371
+ {I}structure :paramref:`jsonable`.
372
+
373
+ {I}:param jsonable: structure to be parsed
374
+ {I}:return: Concrete instance of :py:class:`.types.{cls_name}`
375
+ {I}:raise: :py:class:`DeserializationException` if unexpected :paramref:`jsonable`
376
+ {I}\"\"\"
377
+ {I}if not isinstance(jsonable, collections.abc.Mapping):
378
+ {II}raise DeserializationException(
379
+ {III}f"Expected a mapping, but got: {{type(jsonable)}}"
380
+ {II})
381
+
382
+ {I}model_type = jsonable.get("modelType", None)
383
+ {I}if model_type is None:
384
+ {II}raise DeserializationException(
385
+ {III}"Expected the property modelType, but found none"
386
+ {II})
387
+
388
+ {I}if not isinstance(model_type, str):
389
+ {II}raise DeserializationException(
390
+ {III}"Expected the property modelType to be a str, but got: {{type(model_type)}}"
391
+ {II})
392
+
393
+ {I}dispatch = {mapping_name}.get(model_type, None)
394
+ {I}if dispatch is None:
395
+ {II}raise DeserializationException(
396
+ {III}f"Unexpected model type for {cls_name}: {{model_type}}"
397
+ {II})
398
+
399
+ {I}return dispatch(jsonable)"""
400
+ )
401
+
402
+
403
+ _PARSE_FUNCTION_BY_PRIMITIVE_TYPE = {
404
+ intermediate.PrimitiveType.BOOL: "_bool_from_jsonable",
405
+ intermediate.PrimitiveType.INT: "_int_from_jsonable",
406
+ intermediate.PrimitiveType.FLOAT: "_float_from_jsonable",
407
+ intermediate.PrimitiveType.STR: "_str_from_jsonable",
408
+ intermediate.PrimitiveType.BYTEARRAY: "_bytes_from_jsonable",
409
+ }
410
+ assert all(
411
+ literal in _PARSE_FUNCTION_BY_PRIMITIVE_TYPE
412
+ for literal in intermediate.PrimitiveType
413
+ )
414
+
415
+
416
+ def _parse_function_for_atomic_value(
417
+ type_annotation: intermediate.AtomicTypeAnnotation,
418
+ ) -> Stripped:
419
+ """Determine the parse function for deserializing an atomic non-optional value."""
420
+ function_name: str
421
+
422
+ if isinstance(type_annotation, intermediate.PrimitiveTypeAnnotation):
423
+ function_name = _PARSE_FUNCTION_BY_PRIMITIVE_TYPE[type_annotation.a_type]
424
+
425
+ elif isinstance(type_annotation, intermediate.OurTypeAnnotation):
426
+ our_type = type_annotation.our_type
427
+
428
+ if isinstance(
429
+ our_type,
430
+ (
431
+ intermediate.Enumeration,
432
+ intermediate.AbstractClass,
433
+ intermediate.ConcreteClass,
434
+ ),
435
+ ):
436
+ function_name = python_naming.function_name(
437
+ Identifier(f"{our_type.name}_from_jsonable")
438
+ )
439
+
440
+ elif isinstance(our_type, intermediate.ConstrainedPrimitive):
441
+ function_name = _PARSE_FUNCTION_BY_PRIMITIVE_TYPE[our_type.constrainee]
442
+
443
+ else:
444
+ assert_never(our_type)
445
+ else:
446
+ assert_never(type_annotation)
447
+
448
+ return Stripped(function_name)
449
+
450
+
451
+ def _generate_setter(cls: intermediate.ConcreteClass) -> Stripped:
452
+ """Generate a class which allows us to dispatch de-serialization for properties."""
453
+ methods = [] # type: List[Stripped]
454
+
455
+ init_writer = io.StringIO()
456
+ for i, prop in enumerate(cls.properties):
457
+ prop_name = python_naming.property_name(prop.name)
458
+ prop_type = python_common.generate_type(
459
+ prop.type_annotation, types_module=Identifier("aas_types")
460
+ )
461
+
462
+ # NOTE (mristin, 2022-07-22):
463
+ # We make all the properties optional since we switch over the properties
464
+ # during the de-serialization.
465
+ if not isinstance(prop.type_annotation, intermediate.OptionalTypeAnnotation):
466
+ prop_type = Stripped(f"Optional[{prop_type}]")
467
+
468
+ if i > 0:
469
+ init_writer.write("\n")
470
+ init_writer.write(f"self.{prop_name}: {prop_type} = None")
471
+
472
+ methods.append(
473
+ Stripped(
474
+ f"""\
475
+ def __init__(self) -> None:
476
+ {I}\"\"\"Initialize with all the properties unset.\"\"\"
477
+ {I}{indent_but_first_line(init_writer.getvalue(), I)}"""
478
+ )
479
+ )
480
+
481
+ methods.append(
482
+ Stripped(
483
+ f"""\
484
+ def ignore(self, jsonable: Jsonable) -> None:
485
+ {I}\"\"\"Ignore :paramref:`jsonable` and do not set anything.\"\"\"
486
+ {I}pass"""
487
+ )
488
+ )
489
+
490
+ for i, prop in enumerate(cls.properties):
491
+ prop_name = python_naming.property_name(prop.name)
492
+
493
+ method_name = python_naming.method_name(
494
+ Identifier(f"set_{prop.name}_from_jsonable")
495
+ )
496
+
497
+ type_anno = intermediate.beneath_optional(prop.type_annotation)
498
+ if isinstance(
499
+ type_anno,
500
+ (intermediate.PrimitiveTypeAnnotation, intermediate.OurTypeAnnotation),
501
+ ):
502
+ function_name = _parse_function_for_atomic_value(type_anno)
503
+ body = Stripped(
504
+ f"""\
505
+ self.{prop_name} = {function_name}(
506
+ {I}jsonable
507
+ )"""
508
+ )
509
+
510
+ elif isinstance(type_anno, intermediate.ListTypeAnnotation):
511
+ assert not isinstance(
512
+ type_anno.items,
513
+ (intermediate.OptionalTypeAnnotation, intermediate.ListTypeAnnotation),
514
+ ), (
515
+ "We chose to implement only a very limited pattern matching; "
516
+ "see intermediate._translate_._verify_only_simple_type_patterns"
517
+ )
518
+
519
+ items_type = python_common.generate_type(
520
+ type_anno.items, types_module=Identifier("aas_types")
521
+ )
522
+ parse_function = _parse_function_for_atomic_value(type_anno.items)
523
+
524
+ body = Stripped(
525
+ f"""\
526
+ array_like = _try_to_cast_to_array_like(jsonable)
527
+ if array_like is None:
528
+ {I}raise DeserializationException(
529
+ {II}f"Expected something array-like, but got: {{type(jsonable)}}"
530
+ {I})
531
+
532
+ items: List[
533
+ {I}{items_type}
534
+ ] = []
535
+ for i, jsonable_item in enumerate(array_like):
536
+ {I}try:
537
+ {II}item = {parse_function}(
538
+ {III}jsonable_item
539
+ {II})
540
+ {I}except DeserializationException as exception:
541
+ {II}exception.path._prepend(
542
+ {III}IndexSegment(
543
+ {IIII}array_like,
544
+ {IIII}i
545
+ {III})
546
+ {II})
547
+ {II}raise
548
+
549
+ {I}items.append(item)
550
+
551
+ self.{prop_name} = items"""
552
+ )
553
+
554
+ else:
555
+ assert_never(type_anno)
556
+
557
+ method_writer = io.StringIO()
558
+ method_writer.write(
559
+ f"""\
560
+ def {method_name}(
561
+ {II}self,
562
+ {II}jsonable: Jsonable
563
+ ) -> None:
564
+ {I}\"\"\"
565
+ {I}Parse :paramref:`jsonable` as the value of :py:attr:`~{prop_name}`.
566
+
567
+ {I}:param jsonable: input to be parsed
568
+ {I}\"\"\"
569
+ {I}{indent_but_first_line(body, I)}"""
570
+ )
571
+
572
+ methods.append(Stripped(method_writer.getvalue()))
573
+
574
+ cls_name = python_naming.private_class_name(Identifier(f"Setter_for_{cls.name}"))
575
+
576
+ writer = io.StringIO()
577
+ writer.write(
578
+ f"""\
579
+ class {cls_name}:
580
+ {I}\"\"\"Provide de-serialization-setters for properties.\"\"\"
581
+
582
+ """
583
+ )
584
+
585
+ assert len(methods) > 0, (
586
+ "Expected at least one method, otherwise the newlines are invalid and "
587
+ "have to be fixed"
588
+ )
589
+
590
+ for i, method in enumerate(methods):
591
+ if i > 0:
592
+ writer.write("\n\n")
593
+ writer.write(textwrap.indent(method, I))
594
+
595
+ return Stripped(writer.getvalue())
596
+
597
+
598
+ def _generate_setter_map(cls: intermediate.ConcreteClass) -> Stripped:
599
+ """Generate a mapping ``JSON property name`` -> deserialization on a setter."""
600
+ # fmt: off
601
+ assert (
602
+ sorted(
603
+ (arg.name, str(arg.type_annotation))
604
+ for arg in cls.constructor.arguments
605
+ ) == sorted(
606
+ (prop.name, str(prop.type_annotation))
607
+ for prop in cls.properties
608
+ )
609
+ ), (
610
+ "(mristin, 2022-10-03) We assume that the properties and constructor arguments "
611
+ "are identical at this point. If this is not the case, we have to re-write the "
612
+ "logic substantially! Please contact the developers if you see this."
613
+ )
614
+ # fmt: on
615
+
616
+ identifiers_expressions = [] # type: List[Tuple[Identifier, Stripped]]
617
+
618
+ setter_cls_name = python_naming.private_class_name(
619
+ Identifier(f"Setter_for_{cls.name}")
620
+ )
621
+
622
+ for prop in cls.properties:
623
+ json_identifier = naming.json_property(prop.name)
624
+ method_name = python_naming.method_name(
625
+ Identifier(f"set_{prop.name}_from_jsonable")
626
+ )
627
+
628
+ identifiers_expressions.append(
629
+ (json_identifier, Stripped(f"{setter_cls_name}.{method_name}"))
630
+ )
631
+
632
+ map_name = python_naming.private_constant_name(
633
+ Identifier(f"setter_map_for_{cls.name}")
634
+ )
635
+
636
+ writer = io.StringIO()
637
+ writer.write(
638
+ f"""\
639
+ {map_name}: Mapping[
640
+ {I}str,
641
+ {I}Callable[
642
+ {II}[{setter_cls_name}, Jsonable],
643
+ {II}None
644
+ {I}]
645
+ ] = {{
646
+ """
647
+ )
648
+ for identifier, expression in identifiers_expressions:
649
+ writer.write(
650
+ f"""\
651
+ {I}{python_common.string_literal(identifier)}:
652
+ {II}{indent_but_first_line(expression, II)},
653
+ """
654
+ )
655
+
656
+ writer.write(
657
+ f"""\
658
+ {I}'modelType':
659
+ {II}{setter_cls_name}.ignore
660
+ """
661
+ )
662
+
663
+ writer.write("}")
664
+ return Stripped(writer.getvalue())
665
+
666
+
667
+ def _generate_concrete_class_from_jsonable(
668
+ cls: intermediate.ConcreteClass,
669
+ ) -> Stripped:
670
+ """
671
+ Generate the deserialization function for a concrete class.
672
+
673
+ This function performs no dispatch. If it de-serializes a concrete class with
674
+ concrete descendants, we have to provide a different name. Otherwise, it would
675
+ shadow the name for the dispatch function.
676
+ """
677
+ # fmt: off
678
+ assert (
679
+ sorted(
680
+ (arg.name, str(arg.type_annotation))
681
+ for arg in cls.constructor.arguments
682
+ ) == sorted(
683
+ (prop.name, str(prop.type_annotation))
684
+ for prop in cls.properties
685
+ )
686
+ ), (
687
+ "(mristin, 2022-10-03) We assume that the properties and constructor arguments "
688
+ "are identical at this point. If this is not the case, we have to re-write the "
689
+ "logic substantially! Please contact the developers if you see this."
690
+ )
691
+ # fmt: on
692
+
693
+ setter_cls_name = python_naming.private_class_name(
694
+ Identifier(f"Setter_for_{cls.name}")
695
+ )
696
+
697
+ blocks = [
698
+ Stripped(
699
+ f"""\
700
+ if not isinstance(jsonable, collections.abc.Mapping):
701
+ {I}raise DeserializationException(
702
+ {II}f"Expected a mapping, but got: {{type(jsonable)}}"
703
+ {I})"""
704
+ ),
705
+ Stripped(f"setter = {setter_cls_name}()"),
706
+ ] # type: List[Stripped]
707
+
708
+ # NOTE (mristin):
709
+ # If the class has no concrete descendants, this function will be the sole entry
710
+ # point for the de-serialization. In that case, we have to explicitly check if
711
+ # the ``modelType`` is present — for cases where the serialization rules impose
712
+ # a model type for backwards compatibility even though it is redundant.
713
+ #
714
+ # If the class has concrete descendants, we can only publicly de-serialize it
715
+ # through a dispatching function, which will innately check for model type, so we
716
+ # do not have to repeat the check here.
717
+ if len(cls.concrete_descendants) == 0 and cls.serialization.with_model_type:
718
+ expected_model_type = naming.json_model_type(cls.name)
719
+ blocks.append(
720
+ Stripped(
721
+ f"""\
722
+ model_type = jsonable.get("modelType", None)
723
+ if model_type is None:
724
+ {I}raise DeserializationException(
725
+ {II}"Expected the property modelType, but found none"
726
+ {I})
727
+
728
+ if model_type != {python_common.string_literal(expected_model_type)}:
729
+ {I}raise DeserializationException(
730
+ {II}f"Invalid modelType, expected '{expected_model_type}', "
731
+ {II}f"but got: {{model_type!r}}"
732
+ {I})"""
733
+ )
734
+ )
735
+
736
+ # region Switch on property name
737
+
738
+ map_name = python_naming.private_constant_name(
739
+ Identifier(f"setter_map_for_{cls.name}")
740
+ )
741
+
742
+ blocks.append(
743
+ Stripped(
744
+ f"""\
745
+ for key, jsonable_value in jsonable.items():
746
+ {I}setter_method = (
747
+ {II}{map_name}.get(key)
748
+ {I})
749
+ {I}if setter_method is None:
750
+ {II}raise DeserializationException(
751
+ {III}f"Unexpected property: {{key}}"
752
+ {II})
753
+
754
+ {I}try:
755
+ {II}setter_method(setter, jsonable_value)
756
+ {I}except DeserializationException as exception:
757
+ {II}exception.path._prepend(
758
+ {III}PropertySegment(
759
+ {IIII}jsonable_value,
760
+ {IIII}key
761
+ {III})
762
+ {II})
763
+ {II}raise exception"""
764
+ )
765
+ )
766
+
767
+ # region Check required properties
768
+
769
+ required_checks = [] # type: List[Stripped]
770
+ for i, prop in enumerate(cls.properties):
771
+ if isinstance(prop.type_annotation, intermediate.OptionalTypeAnnotation):
772
+ continue
773
+
774
+ prop_name = python_naming.property_name(prop.name)
775
+
776
+ cause_literal = python_common.string_literal(
777
+ f"The required property {naming.json_property(prop.name)!r} is missing"
778
+ )
779
+ required_checks.append(
780
+ Stripped(
781
+ f"""\
782
+ if setter.{prop_name} is None:
783
+ {I}raise DeserializationException(
784
+ {II}{cause_literal}
785
+ {I})"""
786
+ )
787
+ )
788
+
789
+ if len(required_checks) > 0:
790
+ blocks.append(Stripped("\n\n".join(required_checks)))
791
+
792
+ # endregion
793
+
794
+ # region Pass in arguments to the constructor
795
+
796
+ cls_name = python_naming.class_name(cls.name)
797
+
798
+ if len(cls.constructor.arguments) == 0:
799
+ blocks.append(Stripped(f"return aas_types.{cls_name}()"))
800
+ else:
801
+ init_writer = io.StringIO()
802
+ init_writer.write(f"return aas_types.{cls_name}(\n")
803
+
804
+ for i, arg in enumerate(cls.constructor.arguments):
805
+ prop = cls.properties_by_name[arg.name]
806
+
807
+ prop_name = python_naming.property_name(prop.name)
808
+
809
+ init_writer.write(f"{I}setter.{prop_name}")
810
+
811
+ if i < len(cls.constructor.arguments) - 1:
812
+ init_writer.write(",\n")
813
+ else:
814
+ init_writer.write("\n")
815
+
816
+ init_writer.write(")")
817
+
818
+ blocks.append(Stripped(init_writer.getvalue()))
819
+ # endregion
820
+
821
+ writer = io.StringIO()
822
+
823
+ if len(cls.concrete_descendants) == 0:
824
+ function_name = python_naming.function_name(
825
+ Identifier(f"{cls.name}_from_jsonable")
826
+ )
827
+ else:
828
+ function_name = python_naming.function_name(
829
+ Identifier(f"_{cls.name}_from_jsonable_without_dispatch")
830
+ )
831
+
832
+ docstring_blocks = [
833
+ Stripped(
834
+ f"""\
835
+ Parse an instance of :py:class:`.types.{cls_name}` from the JSON-able
836
+ structure :paramref:`jsonable`."""
837
+ )
838
+ ] # type: List[Stripped]
839
+
840
+ if len(cls.concrete_descendants) > 0:
841
+ function_name_with_dispatch = python_naming.function_name(
842
+ Identifier(f"{cls.name}_from_jsonable")
843
+ )
844
+
845
+ docstring_blocks.append(
846
+ Stripped(
847
+ f"""\
848
+ This function performs no dispatch! It is used to parse the properties
849
+ as-are, and already assumes the exact model type. Usually, this function
850
+ is called from within a dispatching function, and you never call it
851
+ directly. If you want to de-serialize an instance of
852
+ :py:class:`.types.{cls_name}`, call
853
+ :py:func:`{function_name_with_dispatch}`."""
854
+ )
855
+ )
856
+
857
+ docstring_blocks.append(
858
+ Stripped(
859
+ f"""\
860
+ :param jsonable: structure to be parsed
861
+ :return: Parsed instance of :py:class:`.types.{cls_name}`
862
+ :raise: :py:class:`DeserializationException` if unexpected :paramref:`jsonable`"""
863
+ )
864
+ )
865
+
866
+ docstring = "\n\n".join(docstring_blocks)
867
+
868
+ writer.write(
869
+ f"""\
870
+ def {function_name}(
871
+ {II}jsonable: Jsonable
872
+ ) -> aas_types.{cls_name}:
873
+ {I}\"\"\"
874
+ {I}{indent_but_first_line(docstring, I)}
875
+ {I}\"\"\"
876
+ """
877
+ )
878
+
879
+ for i, block in enumerate(blocks):
880
+ if i > 0:
881
+ writer.write("\n\n")
882
+ writer.write(textwrap.indent(block, I))
883
+
884
+ return Stripped(writer.getvalue())
885
+
886
+
887
+ # endregion
888
+
889
+ # region Serialization
890
+
891
+
892
+ def _generate_bytes_to_base64_str() -> Stripped:
893
+ """Generate the function to encode bytes as base64-encoded string."""
894
+ return Stripped(
895
+ f"""\
896
+ def _bytes_to_base64_str(
897
+ {I}value: bytes
898
+ ) -> str:
899
+ {I}\"\"\"
900
+ {I}Encode :paramref:`value` as a base64 string.
901
+
902
+ {I}:param value: to be encoded
903
+ {I}:return: encoded :paramref:`value` in base64
904
+ {I}\"\"\"
905
+ {I}# We need to decode as ascii as ``base64.b64encode`` returns bytes,
906
+ {I}# not a string!
907
+ {I}return base64.b64encode(value).decode('ascii')"""
908
+ )
909
+
910
+
911
+ def _generate_transform_atomic_value(
912
+ access_expression: str, type_anno: intermediate.AtomicTypeAnnotation
913
+ ) -> Stripped:
914
+ """
915
+ Generate the snippet to transform the ``access_expression``.
916
+
917
+ The ``access_expression`` should either be a name or a member access.
918
+ """
919
+ if isinstance(type_anno, intermediate.PrimitiveTypeAnnotation) or (
920
+ isinstance(type_anno, intermediate.OurTypeAnnotation)
921
+ and isinstance(type_anno.our_type, intermediate.ConstrainedPrimitive)
922
+ ):
923
+ a_type = intermediate.try_primitive_type(type_anno)
924
+ assert a_type is not None
925
+
926
+ if (
927
+ a_type is intermediate.PrimitiveType.BOOL
928
+ or a_type is intermediate.PrimitiveType.INT
929
+ or a_type is intermediate.PrimitiveType.FLOAT
930
+ or a_type is intermediate.PrimitiveType.STR
931
+ ):
932
+ return Stripped(f"{access_expression}")
933
+
934
+ elif a_type is intermediate.PrimitiveType.BYTEARRAY:
935
+ return Stripped(f"_bytes_to_base64_str({access_expression})")
936
+
937
+ else:
938
+ assert_never(a_type)
939
+
940
+ elif isinstance(type_anno, intermediate.OurTypeAnnotation):
941
+ if isinstance(type_anno.our_type, intermediate.Enumeration):
942
+ return Stripped(f"{access_expression}.value")
943
+
944
+ elif isinstance(type_anno.our_type, intermediate.ConstrainedPrimitive):
945
+ raise AssertionError("This case should have been handled before.")
946
+
947
+ elif isinstance(
948
+ type_anno.our_type, (intermediate.AbstractClass, intermediate.ConcreteClass)
949
+ ):
950
+ return Stripped(f"self.transform({access_expression})")
951
+
952
+ else:
953
+ assert_never(type_anno.our_type)
954
+
955
+ else:
956
+ assert_never(type_anno.our_type)
957
+
958
+
959
+ def _generate_transform(cls: intermediate.ConcreteClass) -> Stripped:
960
+ """Generate the ``transform_X`` method to serialize an instance into a JSON-able."""
961
+ blocks = [
962
+ Stripped("jsonable: MutableMapping[str, MutableJsonable] = dict()")
963
+ ] # type: List[Stripped]
964
+
965
+ for prop in cls.properties:
966
+ key_literal = python_common.string_literal(naming.json_property(prop.name))
967
+ prop_name = python_naming.property_name(prop.name)
968
+
969
+ type_anno = intermediate.beneath_optional(prop.type_annotation)
970
+
971
+ block: Stripped
972
+
973
+ if isinstance(
974
+ type_anno,
975
+ (intermediate.PrimitiveTypeAnnotation, intermediate.OurTypeAnnotation),
976
+ ):
977
+ transformation_expression = _generate_transform_atomic_value(
978
+ access_expression=Stripped(f"that.{prop_name}"), type_anno=type_anno
979
+ )
980
+
981
+ block = Stripped(f"jsonable[{key_literal}] = {transformation_expression}")
982
+
983
+ # Rudimentary formatting heuristics
984
+ if len(block) > 70:
985
+ block = Stripped(
986
+ f"""\
987
+ jsonable[{key_literal}] = (
988
+ {I}{transformation_expression}
989
+ )"""
990
+ )
991
+
992
+ elif isinstance(type_anno, intermediate.ListTypeAnnotation):
993
+ assert isinstance(
994
+ type_anno.items,
995
+ (intermediate.PrimitiveTypeAnnotation, intermediate.OurTypeAnnotation),
996
+ ), (
997
+ "We expect only lists of primitive and our types. Lists of optionals "
998
+ "and nested lists are not handled yet. Please contact the developers."
999
+ )
1000
+
1001
+ transformation_expression = _generate_transform_atomic_value(
1002
+ access_expression=Stripped("item"), type_anno=type_anno.items
1003
+ )
1004
+
1005
+ block = Stripped(
1006
+ f"""\
1007
+ jsonable[{key_literal}] = [
1008
+ {I}{transformation_expression}
1009
+ {I}for item in that.{prop_name}
1010
+ ]"""
1011
+ )
1012
+
1013
+ else:
1014
+ assert_never(type_anno)
1015
+
1016
+ if isinstance(prop.type_annotation, intermediate.OptionalTypeAnnotation):
1017
+ block = Stripped(
1018
+ f"""\
1019
+ if that.{prop_name} is not None:
1020
+ {I}{indent_but_first_line(block, I)}"""
1021
+ )
1022
+
1023
+ blocks.append(block)
1024
+
1025
+ if cls.serialization.with_model_type:
1026
+ model_type_literal = python_common.string_literal(
1027
+ naming.json_model_type(cls.name)
1028
+ )
1029
+ blocks.append(Stripped(f"""jsonable["modelType"] = {model_type_literal}"""))
1030
+
1031
+ blocks.append(Stripped("return jsonable"))
1032
+
1033
+ method_name = python_naming.method_name(Identifier(f"transform_{cls.name}"))
1034
+
1035
+ cls_name = python_naming.class_name(cls.name)
1036
+
1037
+ writer = io.StringIO()
1038
+
1039
+ no_self_use = all(
1040
+ (
1041
+ some_type_anno := intermediate.beneath_optional(prop.type_annotation),
1042
+ intermediate.try_primitive_type(some_type_anno) is not None
1043
+ or (
1044
+ isinstance(some_type_anno, intermediate.OurTypeAnnotation)
1045
+ and isinstance(some_type_anno.our_type, intermediate.Enumeration)
1046
+ ),
1047
+ )[1]
1048
+ for prop in cls.properties
1049
+ )
1050
+
1051
+ if no_self_use:
1052
+ writer.write("# noinspection PyMethodMayBeStatic\n")
1053
+
1054
+ writer.write(
1055
+ f"""\
1056
+ def {method_name}(
1057
+ {I}self,
1058
+ {I}that: aas_types.{cls_name}
1059
+ ) -> MutableJsonable:
1060
+ {I}\"\"\"Serialize :paramref:`that` to a JSON-able representation.\"\"\""""
1061
+ )
1062
+
1063
+ if len(blocks) > 0:
1064
+ writer.write("\n")
1065
+
1066
+ for i, block in enumerate(blocks):
1067
+ if i > 0:
1068
+ writer.write("\n\n")
1069
+ writer.write(textwrap.indent(block, I))
1070
+
1071
+ return Stripped(writer.getvalue())
1072
+
1073
+
1074
+ def _generate_transformer(symbol_table: intermediate.SymbolTable) -> Stripped:
1075
+ methods = [] # type: List[Stripped]
1076
+
1077
+ for our_type in symbol_table.our_types:
1078
+ if isinstance(our_type, intermediate.ConcreteClass):
1079
+ methods.append(_generate_transform(our_type))
1080
+
1081
+ writer = io.StringIO()
1082
+ writer.write(
1083
+ f"""\
1084
+ class _Serializer(
1085
+ {II}aas_types.AbstractTransformer[MutableJsonable]
1086
+ ):
1087
+ {I}\"\"\"Transform the instance to its JSON-able representation.\"\"\""""
1088
+ )
1089
+
1090
+ for method in methods:
1091
+ writer.write("\n\n")
1092
+ writer.write(textwrap.indent(method, I))
1093
+
1094
+ return Stripped(writer.getvalue())
1095
+
1096
+
1097
+ # endregion
1098
+
1099
+ # fmt: off
1100
+ @ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
1101
+ @ensure(
1102
+ lambda result:
1103
+ not (result[0] is not None) or result[0].endswith('\n'),
1104
+ "Trailing newline mandatory for valid end-of-files"
1105
+ )
1106
+ # fmt: on
1107
+ def generate(
1108
+ symbol_table: intermediate.SymbolTable,
1109
+ aas_module: python_common.QualifiedModuleName,
1110
+ spec_impls: specific_implementations.SpecificImplementations,
1111
+ ) -> Tuple[Optional[str], Optional[List[Error]]]:
1112
+ """
1113
+ Generate the Python code for the general serialization.
1114
+
1115
+ The ``aas_module`` indicates the fully-qualified name of the base module.
1116
+ """
1117
+ blocks = [
1118
+ Stripped(
1119
+ """\
1120
+ \"\"\"
1121
+ Provide de/serialization of AAS classes to/from JSON.
1122
+
1123
+ We can not use one-pass deserialization for JSON since the object
1124
+ properties do not have fixed order, and hence we can not read
1125
+ ``modelType`` property ahead of the remaining properties.
1126
+ \"\"\""""
1127
+ ),
1128
+ python_common.WARNING,
1129
+ Stripped(
1130
+ f"""\
1131
+ import base64
1132
+ import collections.abc
1133
+ import sys
1134
+ from typing import (
1135
+ {I}cast,
1136
+ {I}Any,
1137
+ {I}Callable,
1138
+ {I}Iterable,
1139
+ {I}List,
1140
+ {I}Mapping,
1141
+ {I}MutableMapping,
1142
+ {I}Optional,
1143
+ {I}Sequence,
1144
+ {I}Union,
1145
+ )
1146
+
1147
+ if sys.version_info >= (3, 8):
1148
+ {I}from typing import Final
1149
+ else:
1150
+ {I}from typing_extensions import Final
1151
+
1152
+ import {aas_module}.common as aas_common
1153
+ import {aas_module}.stringification as aas_stringification
1154
+ import {aas_module}.types as aas_types"""
1155
+ ),
1156
+ Stripped(
1157
+ f"""\
1158
+ class PropertySegment:
1159
+ {I}\"\"\"Represent a property on a path to the erroneous value.\"\"\"
1160
+
1161
+ {I}#: Instance that contains the property
1162
+ {I}instance: Final[Mapping[str, Any]]
1163
+
1164
+ {I}#: Name of the property
1165
+ {I}name: Final[str]
1166
+
1167
+ {I}def __init__(
1168
+ {III}self,
1169
+ {III}instance: Mapping[str, Any],
1170
+ {III}name: str
1171
+ {I}) -> None:
1172
+ {II}\"\"\"Initialize with the given values.\"\"\"
1173
+ {II}self.instance = instance
1174
+ {II}self.name = name"""
1175
+ ),
1176
+ Stripped(
1177
+ f"""\
1178
+ class IndexSegment:
1179
+ {I}\"\"\"Represent an index access on a path to the erroneous value.\"\"\"
1180
+
1181
+ {I}#: Container that contains the item
1182
+ {I}container: Final[Iterable[Any]]
1183
+
1184
+ {I}#: Index of the item
1185
+ {I}index: Final[int]
1186
+
1187
+ {I}def __init__(
1188
+ {III}self,
1189
+ {III}container: Iterable[Any],
1190
+ {III}index: int
1191
+ {I}) -> None:
1192
+ {II}\"\"\"Initialize with the given values.\"\"\"
1193
+ {II}self.container = container
1194
+ {II}self.index = index"""
1195
+ ),
1196
+ Stripped(
1197
+ """\
1198
+ Segment = Union[PropertySegment, IndexSegment]"""
1199
+ ),
1200
+ Stripped(
1201
+ f"""\
1202
+ class Path:
1203
+ {I}\"\"\"Represent the relative path to the erroneous value.\"\"\"
1204
+
1205
+ {I}def __init__(self) -> None:
1206
+ {II}\"\"\"Initialize as an empty path.\"\"\"
1207
+ {II}self._segments = [] # type: List[Segment]
1208
+
1209
+ {I}@property
1210
+ {I}def segments(self) -> Sequence[Segment]:
1211
+ {II}\"\"\"Get the segments of the path.\"\"\"
1212
+ {II}return self._segments
1213
+
1214
+ {I}def _prepend(self, segment: Segment) -> None:
1215
+ {II}\"\"\"Insert the :paramref:`segment` in front of other segments.\"\"\"
1216
+ {II}self._segments.insert(0, segment)
1217
+
1218
+ {I}def __str__(self) -> str:
1219
+ {II}if len(self._segments) == 0:
1220
+ {III}return ""
1221
+
1222
+ {II}parts = [] # type: List[str]
1223
+
1224
+ {II}iterator = iter(self._segments)
1225
+ {II}first = next(iterator)
1226
+ {II}if isinstance(first, PropertySegment):
1227
+ {III}parts.append(f"{{first.name}}")
1228
+ {II}elif isinstance(first, IndexSegment):
1229
+ {III}parts.append(f"[{{first.index}}]")
1230
+ {II}else:
1231
+ {III}aas_common.assert_never(first)
1232
+
1233
+ {II}for segment in iterator:
1234
+ {III}if isinstance(segment, PropertySegment):
1235
+ {IIII}parts.append(f".{{segment.name}}")
1236
+ {III}elif isinstance(segment, IndexSegment):
1237
+ {IIII}parts.append(f"[{{segment.index}}]")
1238
+ {III}else:
1239
+ {IIII}aas_common.assert_never(segment)
1240
+
1241
+ {II}return "".join(parts)"""
1242
+ ),
1243
+ Stripped(
1244
+ f"""\
1245
+ class DeserializationException(Exception):
1246
+ {I}\"\"\"Signal that the JSON de-serialization could not be performed.\"\"\"
1247
+
1248
+ {I}#: Human-readable explanation of the exception's cause
1249
+ {I}cause: Final[str]
1250
+
1251
+ {I}#: Relative path to the erroneous value
1252
+ {I}path: Final[Path]
1253
+
1254
+ {I}def __init__(
1255
+ {III}self,
1256
+ {III}cause: str
1257
+ {I}) -> None:
1258
+ {II}\"\"\"Initialize with the given :paramref:`cause` and an empty path.\"\"\"
1259
+ {II}self.cause = cause
1260
+ {II}self.path = Path()"""
1261
+ ),
1262
+ Stripped(
1263
+ f"""\
1264
+ # NOTE (mristin, 2022-10-03):
1265
+ # Recursive definitions are not yet available in mypy
1266
+ # (see https://github.com/python/mypy/issues/731). We have to use ``Any``
1267
+ # here, instead of recursive type annotations.
1268
+ Jsonable = Union[
1269
+ {I}bool,
1270
+ {I}int,
1271
+ {I}float,
1272
+ {I}str,
1273
+ {I}Sequence[Any],
1274
+ {I}Mapping[str, Any]
1275
+ ]"""
1276
+ ),
1277
+ Stripped(
1278
+ f"""\
1279
+ MutableJsonable = Union[
1280
+ {I}bool,
1281
+ {I}int,
1282
+ {I}float,
1283
+ {I}str,
1284
+ {I}List[Any],
1285
+ {I}MutableMapping[str, Any]
1286
+ ]"""
1287
+ ),
1288
+ Stripped("# region De-serialization"),
1289
+ _generate_bool_from_jsonable(),
1290
+ _generate_int_from_jsonable(),
1291
+ _generate_float_from_jsonable(),
1292
+ _generate_str_from_jsonable(),
1293
+ _generate_bytes_from_jsonable(),
1294
+ _generate_is_array_like(),
1295
+ ] # type: List[Stripped]
1296
+
1297
+ errors = [] # type: List[Error]
1298
+
1299
+ for our_type in symbol_table.our_types:
1300
+ if isinstance(our_type, intermediate.Enumeration):
1301
+ blocks.append(_generate_enumeration_from_jsonable(enumeration=our_type))
1302
+ elif isinstance(our_type, intermediate.ConstrainedPrimitive):
1303
+ pass
1304
+ elif isinstance(our_type, intermediate.AbstractClass):
1305
+ blocks.append(_generate_dispatch_from_jsonable(cls=our_type))
1306
+ elif isinstance(our_type, intermediate.ConcreteClass):
1307
+ if len(our_type.concrete_descendants) > 0:
1308
+ blocks.append(_generate_dispatch_from_jsonable(cls=our_type))
1309
+
1310
+ if our_type.is_implementation_specific:
1311
+ implementation_key = specific_implementations.ImplementationKey(
1312
+ f"Jsonization/{our_type.name}_from_jsonable.py"
1313
+ )
1314
+
1315
+ implementation = spec_impls.get(implementation_key, None)
1316
+ if implementation is None:
1317
+ errors.append(
1318
+ Error(
1319
+ our_type.parsed.node,
1320
+ f"The jsonization snippet is missing "
1321
+ f"for the implementation-specific "
1322
+ f"class {our_type.name}: {implementation_key}",
1323
+ )
1324
+ )
1325
+ continue
1326
+ else:
1327
+ blocks.append(_generate_setter(cls=our_type))
1328
+
1329
+ blocks.append(_generate_concrete_class_from_jsonable(cls=our_type))
1330
+ else:
1331
+ assert_never(our_type)
1332
+
1333
+ # NOTE (mristin, 2022-10-03):
1334
+ # We add all the dispatch mappings at the end as the functions might not have been
1335
+ # defined yet otherwise.
1336
+ for our_type in symbol_table.our_types:
1337
+ if isinstance(our_type, intermediate.AbstractClass):
1338
+ blocks.append(_generate_dispatch_map_for_abstract_class(cls=our_type))
1339
+ elif isinstance(our_type, intermediate.ConcreteClass):
1340
+ if len(our_type.concrete_descendants) > 0:
1341
+ blocks.append(_generate_dispatch_map_for_concrete_class(cls=our_type))
1342
+
1343
+ if not our_type.is_implementation_specific:
1344
+ blocks.append(_generate_setter_map(cls=our_type))
1345
+
1346
+ else:
1347
+ pass
1348
+
1349
+ blocks.append(Stripped("# endregion"))
1350
+
1351
+ blocks.append(Stripped("# region Serialization"))
1352
+
1353
+ blocks.append(_generate_bytes_to_base64_str())
1354
+
1355
+ blocks.append(_generate_transformer(symbol_table=symbol_table))
1356
+
1357
+ blocks.append(Stripped("_SERIALIZER = _Serializer()"))
1358
+
1359
+ blocks.append(
1360
+ Stripped(
1361
+ f"""\
1362
+ def to_jsonable(that: aas_types.Class) -> MutableJsonable:
1363
+ {I}\"\"\"
1364
+ {I}Convert :paramref:`that` to a JSON-able structure.
1365
+
1366
+ {I}:param that:
1367
+ {II}AAS data to be recursively converted to a JSON-able structure
1368
+ {I}:return:
1369
+ {II}JSON-able structure which can be further encoded with, *e.g.*, :py:mod:`json`
1370
+ {I}\"\"\"
1371
+ {I}return _SERIALIZER.transform(that)"""
1372
+ )
1373
+ )
1374
+
1375
+ blocks.append(Stripped("# endregion"))
1376
+
1377
+ if len(errors) > 0:
1378
+ return None, errors
1379
+
1380
+ blocks.append(python_common.WARNING)
1381
+
1382
+ writer = io.StringIO()
1383
+ for i, block in enumerate(blocks):
1384
+ if i > 0:
1385
+ writer.write("\n\n\n")
1386
+
1387
+ writer.write(block)
1388
+
1389
+ writer.write("\n")
1390
+
1391
+ return writer.getvalue(), None