cognite-neat 0.123.26__py3-none-any.whl → 1.0.22__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 (341) hide show
  1. cognite/neat/__init__.py +4 -3
  2. cognite/neat/_client/__init__.py +5 -0
  3. cognite/neat/_client/api.py +8 -0
  4. cognite/neat/_client/client.py +21 -0
  5. cognite/neat/_client/config.py +40 -0
  6. cognite/neat/_client/containers_api.py +138 -0
  7. cognite/neat/_client/data_classes.py +44 -0
  8. cognite/neat/_client/data_model_api.py +115 -0
  9. cognite/neat/_client/init/credentials.py +70 -0
  10. cognite/neat/_client/init/env_vars.py +131 -0
  11. cognite/neat/_client/init/main.py +51 -0
  12. cognite/neat/_client/spaces_api.py +115 -0
  13. cognite/neat/_client/statistics_api.py +24 -0
  14. cognite/neat/_client/views_api.py +144 -0
  15. cognite/neat/_config.py +266 -0
  16. cognite/neat/_data_model/_analysis.py +571 -0
  17. cognite/neat/_data_model/_constants.py +74 -0
  18. cognite/neat/_data_model/_identifiers.py +61 -0
  19. cognite/neat/_data_model/_shared.py +41 -0
  20. cognite/neat/_data_model/_snapshot.py +134 -0
  21. cognite/neat/_data_model/deployer/_differ.py +140 -0
  22. cognite/neat/_data_model/deployer/_differ_container.py +360 -0
  23. cognite/neat/_data_model/deployer/_differ_data_model.py +54 -0
  24. cognite/neat/_data_model/deployer/_differ_space.py +9 -0
  25. cognite/neat/_data_model/deployer/_differ_view.py +299 -0
  26. cognite/neat/_data_model/deployer/data_classes.py +644 -0
  27. cognite/neat/_data_model/deployer/deployer.py +431 -0
  28. cognite/neat/_data_model/exporters/__init__.py +15 -0
  29. cognite/neat/_data_model/exporters/_api_exporter.py +37 -0
  30. cognite/neat/_data_model/exporters/_base.py +24 -0
  31. cognite/neat/_data_model/exporters/_table_exporter/exporter.py +128 -0
  32. cognite/neat/_data_model/exporters/_table_exporter/workbook.py +409 -0
  33. cognite/neat/_data_model/exporters/_table_exporter/writer.py +480 -0
  34. cognite/neat/_data_model/importers/__init__.py +5 -0
  35. cognite/neat/_data_model/importers/_api_importer.py +166 -0
  36. cognite/neat/_data_model/importers/_base.py +16 -0
  37. cognite/neat/_data_model/importers/_table_importer/data_classes.py +344 -0
  38. cognite/neat/_data_model/importers/_table_importer/importer.py +192 -0
  39. cognite/neat/_data_model/importers/_table_importer/reader.py +1102 -0
  40. cognite/neat/_data_model/importers/_table_importer/source.py +94 -0
  41. cognite/neat/_data_model/models/conceptual/_base.py +18 -0
  42. cognite/neat/_data_model/models/conceptual/_concept.py +67 -0
  43. cognite/neat/_data_model/models/conceptual/_data_model.py +51 -0
  44. cognite/neat/_data_model/models/conceptual/_properties.py +104 -0
  45. cognite/neat/_data_model/models/conceptual/_property.py +105 -0
  46. cognite/neat/_data_model/models/dms/__init__.py +206 -0
  47. cognite/neat/_data_model/models/dms/_base.py +31 -0
  48. cognite/neat/_data_model/models/dms/_constants.py +48 -0
  49. cognite/neat/_data_model/models/dms/_constraints.py +42 -0
  50. cognite/neat/_data_model/models/dms/_container.py +159 -0
  51. cognite/neat/_data_model/models/dms/_data_model.py +95 -0
  52. cognite/neat/_data_model/models/dms/_data_types.py +195 -0
  53. cognite/neat/_data_model/models/dms/_http.py +28 -0
  54. cognite/neat/_data_model/models/dms/_indexes.py +30 -0
  55. cognite/neat/_data_model/models/dms/_limits.py +96 -0
  56. cognite/neat/_data_model/models/dms/_references.py +141 -0
  57. cognite/neat/_data_model/models/dms/_schema.py +18 -0
  58. cognite/neat/_data_model/models/dms/_space.py +48 -0
  59. cognite/neat/_data_model/models/dms/_types.py +17 -0
  60. cognite/neat/_data_model/models/dms/_view_filter.py +310 -0
  61. cognite/neat/_data_model/models/dms/_view_property.py +235 -0
  62. cognite/neat/_data_model/models/dms/_views.py +216 -0
  63. cognite/neat/_data_model/models/entities/__init__.py +50 -0
  64. cognite/neat/_data_model/models/entities/_base.py +101 -0
  65. cognite/neat/_data_model/models/entities/_constants.py +22 -0
  66. cognite/neat/_data_model/models/entities/_data_types.py +144 -0
  67. cognite/neat/_data_model/models/entities/_identifiers.py +61 -0
  68. cognite/neat/_data_model/models/entities/_parser.py +226 -0
  69. cognite/neat/_data_model/validation/dms/__init__.py +75 -0
  70. cognite/neat/_data_model/validation/dms/_ai_readiness.py +381 -0
  71. cognite/neat/_data_model/validation/dms/_base.py +25 -0
  72. cognite/neat/_data_model/validation/dms/_connections.py +681 -0
  73. cognite/neat/_data_model/validation/dms/_consistency.py +58 -0
  74. cognite/neat/_data_model/validation/dms/_containers.py +199 -0
  75. cognite/neat/_data_model/validation/dms/_limits.py +368 -0
  76. cognite/neat/_data_model/validation/dms/_orchestrator.py +70 -0
  77. cognite/neat/_data_model/validation/dms/_views.py +164 -0
  78. cognite/neat/_exceptions.py +68 -0
  79. cognite/neat/_issues.py +68 -0
  80. cognite/neat/_session/__init__.py +3 -0
  81. cognite/neat/_session/_html/_render.py +30 -0
  82. cognite/neat/_session/_html/static/__init__.py +8 -0
  83. cognite/neat/_session/_html/static/deployment.css +476 -0
  84. cognite/neat/_session/_html/static/deployment.js +181 -0
  85. cognite/neat/_session/_html/static/issues.css +211 -0
  86. cognite/neat/_session/_html/static/issues.js +168 -0
  87. cognite/neat/_session/_html/static/shared.css +186 -0
  88. cognite/neat/_session/_html/templates/__init__.py +4 -0
  89. cognite/neat/_session/_html/templates/deployment.html +80 -0
  90. cognite/neat/_session/_html/templates/issues.html +45 -0
  91. cognite/neat/_session/_issues.py +81 -0
  92. cognite/neat/_session/_physical.py +294 -0
  93. cognite/neat/_session/_result/__init__.py +3 -0
  94. cognite/neat/_session/_result/_deployment/__init__.py +0 -0
  95. cognite/neat/_session/_result/_deployment/_physical/__init__.py +0 -0
  96. cognite/neat/_session/_result/_deployment/_physical/_changes.py +196 -0
  97. cognite/neat/_session/_result/_deployment/_physical/_statistics.py +180 -0
  98. cognite/neat/_session/_result/_deployment/_physical/serializer.py +35 -0
  99. cognite/neat/_session/_result/_result.py +31 -0
  100. cognite/neat/_session/_session.py +81 -0
  101. cognite/neat/_session/_usage_analytics/__init__.py +0 -0
  102. cognite/neat/_session/_usage_analytics/_collector.py +131 -0
  103. cognite/neat/_session/_usage_analytics/_constants.py +23 -0
  104. cognite/neat/_session/_usage_analytics/_storage.py +240 -0
  105. cognite/neat/_session/_wrappers.py +101 -0
  106. cognite/neat/_state_machine/__init__.py +10 -0
  107. cognite/neat/_state_machine/_base.py +37 -0
  108. cognite/neat/_state_machine/_states.py +52 -0
  109. cognite/neat/_store/__init__.py +3 -0
  110. cognite/neat/_store/_provenance.py +88 -0
  111. cognite/neat/_store/_store.py +220 -0
  112. cognite/neat/_utils/__init__.py +0 -0
  113. cognite/neat/_utils/_reader.py +194 -0
  114. cognite/neat/_utils/auxiliary.py +49 -0
  115. cognite/neat/_utils/collection.py +11 -0
  116. cognite/neat/_utils/http_client/__init__.py +39 -0
  117. cognite/neat/_utils/http_client/_client.py +245 -0
  118. cognite/neat/_utils/http_client/_config.py +19 -0
  119. cognite/neat/_utils/http_client/_data_classes.py +294 -0
  120. cognite/neat/_utils/http_client/_tracker.py +31 -0
  121. cognite/neat/_utils/repo.py +19 -0
  122. cognite/neat/_utils/text.py +71 -0
  123. cognite/neat/_utils/useful_types.py +37 -0
  124. cognite/neat/_utils/validation.py +154 -0
  125. cognite/neat/_v0/__init__.py +0 -0
  126. cognite/neat/_v0/core/__init__.py +0 -0
  127. cognite/neat/_v0/core/_client/_api/__init__.py +0 -0
  128. cognite/neat/{core → _v0/core}/_client/_api/data_modeling_loaders.py +8 -7
  129. cognite/neat/{core → _v0/core}/_client/_api/neat_instances.py +5 -5
  130. cognite/neat/{core → _v0/core}/_client/_api/schema.py +5 -5
  131. cognite/neat/{core → _v0/core}/_client/_api/statistics.py +3 -3
  132. cognite/neat/{core → _v0/core}/_client/_api_client.py +1 -1
  133. cognite/neat/_v0/core/_client/data_classes/__init__.py +0 -0
  134. cognite/neat/{core → _v0/core}/_client/data_classes/schema.py +4 -4
  135. cognite/neat/{core → _v0/core}/_client/testing.py +1 -1
  136. cognite/neat/{core → _v0/core}/_constants.py +5 -3
  137. cognite/neat/_v0/core/_data_model/__init__.py +0 -0
  138. cognite/neat/{core → _v0/core}/_data_model/_constants.py +7 -0
  139. cognite/neat/{core → _v0/core}/_data_model/_shared.py +4 -4
  140. cognite/neat/{core → _v0/core}/_data_model/analysis/_base.py +8 -8
  141. cognite/neat/{core → _v0/core}/_data_model/exporters/__init__.py +1 -2
  142. cognite/neat/{core → _v0/core}/_data_model/exporters/_base.py +7 -7
  143. cognite/neat/{core → _v0/core}/_data_model/exporters/_data_model2dms.py +9 -9
  144. cognite/neat/{core → _v0/core}/_data_model/exporters/_data_model2excel.py +12 -12
  145. cognite/neat/{core → _v0/core}/_data_model/exporters/_data_model2instance_template.py +4 -4
  146. cognite/neat/{core/_data_model/exporters/_data_model2ontology.py → _v0/core/_data_model/exporters/_data_model2semantic_model.py} +126 -116
  147. cognite/neat/{core → _v0/core}/_data_model/exporters/_data_model2yaml.py +1 -1
  148. cognite/neat/{core → _v0/core}/_data_model/importers/_base.py +5 -5
  149. cognite/neat/{core → _v0/core}/_data_model/importers/_base_file_reader.py +2 -2
  150. cognite/neat/{core → _v0/core}/_data_model/importers/_dict2data_model.py +5 -5
  151. cognite/neat/{core → _v0/core}/_data_model/importers/_dms2data_model.py +18 -15
  152. cognite/neat/{core → _v0/core}/_data_model/importers/_graph2data_model.py +12 -12
  153. cognite/neat/{core → _v0/core}/_data_model/importers/_rdf/_base.py +12 -12
  154. cognite/neat/{core → _v0/core}/_data_model/importers/_rdf/_inference2rdata_model.py +14 -14
  155. cognite/neat/{core → _v0/core}/_data_model/importers/_rdf/_owl2data_model.py +41 -21
  156. cognite/neat/{core → _v0/core}/_data_model/importers/_rdf/_shared.py +9 -9
  157. cognite/neat/{core → _v0/core}/_data_model/importers/_spreadsheet2data_model.py +92 -12
  158. cognite/neat/{core → _v0/core}/_data_model/models/__init__.py +3 -3
  159. cognite/neat/{core → _v0/core}/_data_model/models/_base_verified.py +5 -5
  160. cognite/neat/{core → _v0/core}/_data_model/models/_import_contexts.py +1 -1
  161. cognite/neat/{core → _v0/core}/_data_model/models/_types.py +5 -5
  162. cognite/neat/{core → _v0/core}/_data_model/models/conceptual/_unverified.py +16 -10
  163. cognite/neat/{core → _v0/core}/_data_model/models/conceptual/_validation.py +12 -12
  164. cognite/neat/{core → _v0/core}/_data_model/models/conceptual/_verified.py +9 -9
  165. cognite/neat/{core → _v0/core}/_data_model/models/data_types.py +14 -4
  166. cognite/neat/{core → _v0/core}/_data_model/models/entities/__init__.py +6 -0
  167. cognite/neat/_v0/core/_data_model/models/entities/_loaders.py +155 -0
  168. cognite/neat/{core → _v0/core}/_data_model/models/entities/_multi_value.py +2 -2
  169. cognite/neat/_v0/core/_data_model/models/entities/_restrictions.py +230 -0
  170. cognite/neat/{core → _v0/core}/_data_model/models/entities/_single_value.py +121 -16
  171. cognite/neat/{core → _v0/core}/_data_model/models/entities/_types.py +10 -0
  172. cognite/neat/{core → _v0/core}/_data_model/models/mapping/_classic2core.py +5 -5
  173. cognite/neat/{core → _v0/core}/_data_model/models/physical/__init__.py +1 -1
  174. cognite/neat/{core → _v0/core}/_data_model/models/physical/_exporter.py +26 -19
  175. cognite/neat/{core → _v0/core}/_data_model/models/physical/_unverified.py +133 -37
  176. cognite/neat/{core → _v0/core}/_data_model/models/physical/_validation.py +24 -20
  177. cognite/neat/{core → _v0/core}/_data_model/models/physical/_verified.py +95 -24
  178. cognite/neat/{core → _v0/core}/_data_model/transformers/_base.py +4 -4
  179. cognite/neat/{core → _v0/core}/_data_model/transformers/_converters.py +35 -28
  180. cognite/neat/{core → _v0/core}/_data_model/transformers/_mapping.py +7 -7
  181. cognite/neat/{core → _v0/core}/_data_model/transformers/_union_conceptual.py +5 -5
  182. cognite/neat/{core → _v0/core}/_data_model/transformers/_verification.py +7 -7
  183. cognite/neat/_v0/core/_instances/__init__.py +0 -0
  184. cognite/neat/{core → _v0/core}/_instances/_tracking/base.py +1 -1
  185. cognite/neat/{core → _v0/core}/_instances/_tracking/log.py +1 -1
  186. cognite/neat/{core → _v0/core}/_instances/extractors/__init__.py +3 -2
  187. cognite/neat/{core → _v0/core}/_instances/extractors/_base.py +6 -6
  188. cognite/neat/_v0/core/_instances/extractors/_classic_cdf/__init__.py +0 -0
  189. cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_base.py +7 -7
  190. cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_classic.py +12 -12
  191. cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_relationships.py +3 -3
  192. cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_sequences.py +2 -2
  193. cognite/neat/{core → _v0/core}/_instances/extractors/_dict.py +6 -3
  194. cognite/neat/{core → _v0/core}/_instances/extractors/_dms.py +6 -6
  195. cognite/neat/{core → _v0/core}/_instances/extractors/_dms_graph.py +11 -11
  196. cognite/neat/{core → _v0/core}/_instances/extractors/_mock_graph_generator.py +10 -10
  197. cognite/neat/{core → _v0/core}/_instances/extractors/_raw.py +3 -3
  198. cognite/neat/{core → _v0/core}/_instances/extractors/_rdf_file.py +7 -7
  199. cognite/neat/{core → _v0/core}/_instances/loaders/_base.py +5 -5
  200. cognite/neat/{core → _v0/core}/_instances/loaders/_rdf2dms.py +17 -17
  201. cognite/neat/{core → _v0/core}/_instances/loaders/_rdf_to_instance_space.py +11 -11
  202. cognite/neat/{core → _v0/core}/_instances/queries/_select.py +29 -3
  203. cognite/neat/{core → _v0/core}/_instances/queries/_update.py +1 -1
  204. cognite/neat/{core → _v0/core}/_instances/transformers/_base.py +4 -4
  205. cognite/neat/{core → _v0/core}/_instances/transformers/_classic_cdf.py +6 -6
  206. cognite/neat/{core → _v0/core}/_instances/transformers/_prune_graph.py +4 -4
  207. cognite/neat/{core → _v0/core}/_instances/transformers/_rdfpath.py +1 -1
  208. cognite/neat/{core → _v0/core}/_instances/transformers/_value_type.py +4 -4
  209. cognite/neat/{core → _v0/core}/_issues/_base.py +5 -5
  210. cognite/neat/{core → _v0/core}/_issues/_contextmanagers.py +1 -1
  211. cognite/neat/{core → _v0/core}/_issues/_factory.py +3 -3
  212. cognite/neat/{core → _v0/core}/_issues/errors/__init__.py +1 -1
  213. cognite/neat/{core → _v0/core}/_issues/errors/_external.py +1 -1
  214. cognite/neat/{core → _v0/core}/_issues/errors/_general.py +1 -1
  215. cognite/neat/{core → _v0/core}/_issues/errors/_properties.py +1 -1
  216. cognite/neat/{core → _v0/core}/_issues/errors/_resources.py +2 -2
  217. cognite/neat/{core → _v0/core}/_issues/errors/_wrapper.py +7 -3
  218. cognite/neat/{core → _v0/core}/_issues/warnings/__init__.py +1 -1
  219. cognite/neat/{core → _v0/core}/_issues/warnings/_external.py +1 -1
  220. cognite/neat/{core → _v0/core}/_issues/warnings/_general.py +1 -1
  221. cognite/neat/{core → _v0/core}/_issues/warnings/_models.py +2 -2
  222. cognite/neat/{core → _v0/core}/_issues/warnings/_properties.py +2 -2
  223. cognite/neat/{core → _v0/core}/_issues/warnings/_resources.py +1 -1
  224. cognite/neat/{core → _v0/core}/_issues/warnings/user_modeling.py +1 -1
  225. cognite/neat/{core → _v0/core}/_store/_data_model.py +12 -12
  226. cognite/neat/{core → _v0/core}/_store/_instance.py +43 -10
  227. cognite/neat/{core → _v0/core}/_store/_provenance.py +3 -3
  228. cognite/neat/{core → _v0/core}/_store/exceptions.py +4 -4
  229. cognite/neat/_v0/core/_utils/__init__.py +0 -0
  230. cognite/neat/{core → _v0/core}/_utils/auth.py +22 -12
  231. cognite/neat/{core → _v0/core}/_utils/auxiliary.py +1 -1
  232. cognite/neat/{core → _v0/core}/_utils/collection_.py +2 -2
  233. cognite/neat/{core → _v0/core}/_utils/graph_transformations_report.py +1 -1
  234. cognite/neat/{core → _v0/core}/_utils/rdf_.py +1 -1
  235. cognite/neat/{core → _v0/core}/_utils/reader/_base.py +1 -1
  236. cognite/neat/{core → _v0/core}/_utils/spreadsheet.py +18 -4
  237. cognite/neat/{core → _v0/core}/_utils/text.py +1 -1
  238. cognite/neat/{core → _v0/core}/_utils/upload.py +3 -3
  239. cognite/neat/{session → _v0}/engine/_load.py +1 -1
  240. cognite/neat/_v0/plugins/__init__.py +4 -0
  241. cognite/neat/_v0/plugins/_base.py +9 -0
  242. cognite/neat/_v0/plugins/_data_model.py +48 -0
  243. cognite/neat/{plugins → _v0/plugins}/_issues.py +1 -1
  244. cognite/neat/{plugins → _v0/plugins}/_manager.py +7 -16
  245. cognite/neat/{session → _v0/session}/_base.py +13 -15
  246. cognite/neat/{session → _v0/session}/_collector.py +1 -1
  247. cognite/neat/_v0/session/_diff.py +51 -0
  248. cognite/neat/{session → _v0/session}/_drop.py +3 -3
  249. cognite/neat/{session → _v0/session}/_explore.py +2 -2
  250. cognite/neat/{session → _v0/session}/_fix.py +2 -2
  251. cognite/neat/{session → _v0/session}/_inspect.py +3 -3
  252. cognite/neat/{session → _v0/session}/_mapping.py +3 -3
  253. cognite/neat/{session → _v0/session}/_plugin.py +4 -5
  254. cognite/neat/{session → _v0/session}/_prepare.py +8 -8
  255. cognite/neat/{session → _v0/session}/_read.py +34 -21
  256. cognite/neat/{session → _v0/session}/_set.py +8 -8
  257. cognite/neat/{session → _v0/session}/_show.py +5 -5
  258. cognite/neat/{session → _v0/session}/_state.py +10 -10
  259. cognite/neat/{session → _v0/session}/_subset.py +4 -4
  260. cognite/neat/{session → _v0/session}/_template.py +11 -11
  261. cognite/neat/{session → _v0/session}/_to.py +12 -12
  262. cognite/neat/{session → _v0/session}/_wizard.py +1 -1
  263. cognite/neat/{session → _v0/session}/exceptions.py +5 -5
  264. cognite/neat/_version.py +1 -1
  265. cognite/neat/legacy.py +6 -0
  266. cognite_neat-1.0.22.dist-info/METADATA +123 -0
  267. cognite_neat-1.0.22.dist-info/RECORD +329 -0
  268. cognite_neat-1.0.22.dist-info/WHEEL +4 -0
  269. cognite/neat/core/_data_model/models/entities/_loaders.py +0 -75
  270. cognite/neat/plugins/__init__.py +0 -3
  271. cognite/neat/plugins/data_model/importers/__init__.py +0 -5
  272. cognite/neat/plugins/data_model/importers/_base.py +0 -28
  273. cognite/neat/session/_session/_data_model/__init__.py +0 -3
  274. cognite/neat/session/_session/_data_model/_read.py +0 -193
  275. cognite/neat/session/_session/_data_model/_routes.py +0 -45
  276. cognite/neat/session/_session/_data_model/_show.py +0 -147
  277. cognite/neat/session/_session/_data_model/_write.py +0 -335
  278. cognite_neat-0.123.26.dist-info/METADATA +0 -144
  279. cognite_neat-0.123.26.dist-info/RECORD +0 -201
  280. cognite_neat-0.123.26.dist-info/WHEEL +0 -4
  281. cognite_neat-0.123.26.dist-info/licenses/LICENSE +0 -201
  282. /cognite/neat/{core → _client/init}/__init__.py +0 -0
  283. /cognite/neat/{core/_client/_api → _data_model}/__init__.py +0 -0
  284. /cognite/neat/{core/_client/data_classes → _data_model/deployer}/__init__.py +0 -0
  285. /cognite/neat/{core/_data_model → _data_model/exporters/_table_exporter}/__init__.py +0 -0
  286. /cognite/neat/{core/_instances → _data_model/importers/_table_importer}/__init__.py +0 -0
  287. /cognite/neat/{core/_instances/extractors/_classic_cdf → _data_model/models}/__init__.py +0 -0
  288. /cognite/neat/{core/_utils → _data_model/models/conceptual}/__init__.py +0 -0
  289. /cognite/neat/{plugins/data_model → _data_model/validation}/__init__.py +0 -0
  290. /cognite/neat/{session/_session → _session/_html}/__init__.py +0 -0
  291. /cognite/neat/{core → _v0/core}/_client/__init__.py +0 -0
  292. /cognite/neat/{core → _v0/core}/_client/data_classes/data_modeling.py +0 -0
  293. /cognite/neat/{core → _v0/core}/_client/data_classes/neat_sequence.py +0 -0
  294. /cognite/neat/{core → _v0/core}/_client/data_classes/statistics.py +0 -0
  295. /cognite/neat/{core → _v0/core}/_config.py +0 -0
  296. /cognite/neat/{core → _v0/core}/_data_model/analysis/__init__.py +0 -0
  297. /cognite/neat/{core → _v0/core}/_data_model/catalog/__init__.py +0 -0
  298. /cognite/neat/{core → _v0/core}/_data_model/catalog/classic_model.xlsx +0 -0
  299. /cognite/neat/{core → _v0/core}/_data_model/catalog/conceptual-imf-data-model.xlsx +0 -0
  300. /cognite/neat/{core → _v0/core}/_data_model/catalog/hello_world_pump.xlsx +0 -0
  301. /cognite/neat/{core → _v0/core}/_data_model/importers/__init__.py +0 -0
  302. /cognite/neat/{core → _v0/core}/_data_model/importers/_rdf/__init__.py +0 -0
  303. /cognite/neat/{core → _v0/core}/_data_model/models/_base_unverified.py +0 -0
  304. /cognite/neat/{core → _v0/core}/_data_model/models/conceptual/__init__.py +0 -0
  305. /cognite/neat/{core → _v0/core}/_data_model/models/entities/_constants.py +0 -0
  306. /cognite/neat/{core → _v0/core}/_data_model/models/entities/_wrapped.py +0 -0
  307. /cognite/neat/{core → _v0/core}/_data_model/models/mapping/__init__.py +0 -0
  308. /cognite/neat/{core → _v0/core}/_data_model/models/mapping/_classic2core.yaml +0 -0
  309. /cognite/neat/{core → _v0/core}/_data_model/transformers/__init__.py +0 -0
  310. /cognite/neat/{core → _v0/core}/_instances/_shared.py +0 -0
  311. /cognite/neat/{core → _v0/core}/_instances/_tracking/__init__.py +0 -0
  312. /cognite/neat/{core → _v0/core}/_instances/examples/Knowledge-Graph-Nordic44-dirty.xml +0 -0
  313. /cognite/neat/{core → _v0/core}/_instances/examples/Knowledge-Graph-Nordic44.xml +0 -0
  314. /cognite/neat/{core → _v0/core}/_instances/examples/__init__.py +0 -0
  315. /cognite/neat/{core → _v0/core}/_instances/examples/skos-capturing-sheet-wind-topics.xlsx +0 -0
  316. /cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_assets.py +0 -0
  317. /cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_data_sets.py +0 -0
  318. /cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_events.py +0 -0
  319. /cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_files.py +0 -0
  320. /cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_labels.py +0 -0
  321. /cognite/neat/{core → _v0/core}/_instances/extractors/_classic_cdf/_timeseries.py +0 -0
  322. /cognite/neat/{core → _v0/core}/_instances/loaders/__init__.py +0 -0
  323. /cognite/neat/{core → _v0/core}/_instances/queries/__init__.py +0 -0
  324. /cognite/neat/{core → _v0/core}/_instances/queries/_base.py +0 -0
  325. /cognite/neat/{core → _v0/core}/_instances/queries/_queries.py +0 -0
  326. /cognite/neat/{core → _v0/core}/_instances/transformers/__init__.py +0 -0
  327. /cognite/neat/{core → _v0/core}/_issues/__init__.py +0 -0
  328. /cognite/neat/{core → _v0/core}/_issues/formatters.py +0 -0
  329. /cognite/neat/{core → _v0/core}/_shared.py +0 -0
  330. /cognite/neat/{core → _v0/core}/_store/__init__.py +0 -0
  331. /cognite/neat/{core → _v0/core}/_utils/io_.py +0 -0
  332. /cognite/neat/{core → _v0/core}/_utils/reader/__init__.py +0 -0
  333. /cognite/neat/{core → _v0/core}/_utils/tarjan.py +0 -0
  334. /cognite/neat/{core → _v0/core}/_utils/time_.py +0 -0
  335. /cognite/neat/{core → _v0/core}/_utils/xml_.py +0 -0
  336. /cognite/neat/{session → _v0}/engine/__init__.py +0 -0
  337. /cognite/neat/{session → _v0}/engine/_import.py +0 -0
  338. /cognite/neat/{session → _v0}/engine/_interface.py +0 -0
  339. /cognite/neat/{session → _v0/session}/__init__.py +0 -0
  340. /cognite/neat/{session → _v0/session}/_experimental.py +0 -0
  341. /cognite/neat/{session → _v0/session}/_state/README.md +0 -0
@@ -0,0 +1,81 @@
1
+ import json
2
+ import uuid
3
+ from collections import defaultdict
4
+ from typing import Any
5
+
6
+ from cognite.neat._issues import ConsistencyError, IssueList, ModelSyntaxError, Recommendation
7
+ from cognite.neat._session._html._render import render
8
+ from cognite.neat._store import NeatStore
9
+
10
+
11
+ class Issues:
12
+ """Class to handle issues in the NeatSession."""
13
+
14
+ def __init__(self, store: NeatStore) -> None:
15
+ self._store = store
16
+
17
+ @property
18
+ def _issues(self) -> IssueList:
19
+ """Get all issues from the last change in the store."""
20
+ issues = IssueList()
21
+ if change := self._store.provenance.last_change:
22
+ issues += change.errors or IssueList()
23
+ issues += change.issues or IssueList()
24
+ return issues
25
+
26
+ @property
27
+ def _stats(self) -> dict[str, Any]:
28
+ """Compute statistics about issues."""
29
+ by_type: defaultdict[str, int] = defaultdict(int)
30
+ by_code: defaultdict[str, int] = defaultdict(int)
31
+
32
+ stats: dict[str, Any] = {
33
+ "total": len(self._issues),
34
+ "by_type": by_type,
35
+ "by_code": by_code,
36
+ "severity_order": [ModelSyntaxError.__name__, ConsistencyError.__name__, Recommendation.__name__],
37
+ }
38
+
39
+ for issue in self._issues:
40
+ stats["by_type"][issue.issue_type()] += 1
41
+
42
+ if issue.code:
43
+ stats["by_code"][f"{issue.issue_type()}:{issue.code}"] += 1
44
+
45
+ return stats
46
+
47
+ @property
48
+ def _serialized_issues(self) -> list[dict[str, Any]]:
49
+ """Convert issues to JSON-serializable format."""
50
+ serialized = []
51
+ for idx, issue in enumerate(self._issues):
52
+ serialized.append(
53
+ {
54
+ "id": idx,
55
+ "type": issue.issue_type(),
56
+ "code": issue.code or "",
57
+ "message": issue.message,
58
+ "fix": issue.fix or "",
59
+ }
60
+ )
61
+ return serialized
62
+
63
+ def _repr_html_(self) -> str:
64
+ """Generate interactive HTML representation."""
65
+ if not self._issues:
66
+ return "<b>No issues found.</b>"
67
+ stats = self._stats
68
+
69
+ # Generate unique ID for this render to avoid conflicts in Jupyter
70
+ unique_id = uuid.uuid4().hex[:8]
71
+
72
+ template_vars = {
73
+ "JSON": json.dumps(self._serialized_issues),
74
+ "total": stats["total"],
75
+ "syntax_errors": stats["by_type"].get("ModelSyntaxError", 0),
76
+ "consistency_errors": stats["by_type"].get("ConsistencyError", 0),
77
+ "recommendations": stats["by_type"].get("Recommendation", 0),
78
+ "unique_id": unique_id,
79
+ }
80
+
81
+ return render("issues", template_vars)
@@ -0,0 +1,294 @@
1
+ from typing import Any, Literal
2
+
3
+ from cognite.neat._client import NeatClient
4
+ from cognite.neat._config import NeatConfig
5
+ from cognite.neat._data_model.deployer.deployer import DeploymentOptions, SchemaDeployer
6
+ from cognite.neat._data_model.exporters import (
7
+ DMSAPIExporter,
8
+ DMSAPIJSONExporter,
9
+ DMSAPIYAMLExporter,
10
+ DMSExcelExporter,
11
+ DMSExporter,
12
+ DMSTableJSONExporter,
13
+ DMSTableYamlExporter,
14
+ )
15
+ from cognite.neat._data_model.exporters._table_exporter.workbook import WorkbookOptions
16
+ from cognite.neat._data_model.importers import DMSAPIImporter, DMSImporter, DMSTableImporter
17
+ from cognite.neat._data_model.models.dms import DataModelReference
18
+ from cognite.neat._data_model.validation.dms import DmsDataModelValidation
19
+ from cognite.neat._exceptions import UserInputError
20
+ from cognite.neat._state_machine import PhysicalState
21
+ from cognite.neat._store._store import NeatStore
22
+ from cognite.neat._utils._reader import NeatReader
23
+
24
+ from ._wrappers import session_wrapper
25
+
26
+
27
+ class PhysicalDataModel:
28
+ """Read from a data source into NeatSession graph store."""
29
+
30
+ def __init__(self, store: NeatStore, client: NeatClient, config: NeatConfig) -> None:
31
+ self._store = store
32
+ self._client = client
33
+ self._config = config
34
+ self.read = ReadPhysicalDataModel(self._store, self._client, self._config)
35
+ self.write = WritePhysicalDataModel(self._store, self._client, self._config)
36
+
37
+ def _repr_html_(self) -> str:
38
+ if not isinstance(self._store.state, PhysicalState):
39
+ return "No physical data model. Get started by reading physical data model <em>.physica_data_mode.read</em>"
40
+
41
+ dm = self._store.physical_data_model[-1]
42
+
43
+ html = ["<div>"]
44
+ html.append(
45
+ f"<h3>Data Model: {dm.data_model.space}:{dm.data_model.external_id}(version={dm.data_model.version})</h3>"
46
+ )
47
+ html.append("<table style='border-collapse: collapse;'>")
48
+ html.append("<tr><th style='text-align: left; padding: 4px; border: 1px solid #ddd;'>Component</th>")
49
+ html.append("<th style='text-align: left; padding: 4px; border: 1px solid #ddd;'>Count</th></tr>")
50
+
51
+ html.append("<tr><td style='padding: 4px; border: 1px solid #ddd;'>Views</td>")
52
+ html.append(f"<td style='padding: 4px; border: 1px solid #ddd;'>{len(dm.views)}</td></tr>")
53
+
54
+ html.append("<tr><td style='padding: 4px; border: 1px solid #ddd;'>Containers</td>")
55
+ html.append(f"<td style='padding: 4px; border: 1px solid #ddd;'>{len(dm.containers)}</td></tr>")
56
+
57
+ html.append("<tr><td style='padding: 4px; border: 1px solid #ddd;'>Spaces</td>")
58
+ html.append(f"<td style='padding: 4px; border: 1px solid #ddd;'>{len(dm.spaces)}</td></tr>")
59
+
60
+ html.append("<tr><td style='padding: 4px; border: 1px solid #ddd;'>Node Types</td>")
61
+ html.append(f"<td style='padding: 4px; border: 1px solid #ddd;'>{len(dm.node_types)}</td></tr>")
62
+
63
+ html.append("</table>")
64
+ html.append("</div>")
65
+
66
+ return "".join(html)
67
+
68
+
69
+ @session_wrapper
70
+ class ReadPhysicalDataModel:
71
+ """Read physical data model from various sources into NeatSession store.
72
+
73
+ Available methods:
74
+
75
+ - `neat.physical_data_model.read.yaml`
76
+ - `neat.physical_data_model.read.json`
77
+ - `neat.physical_data_model.read.excel`
78
+ - `neat.physical_data_model.read.cdf`
79
+ """
80
+
81
+ def __init__(self, store: NeatStore, client: NeatClient, config: NeatConfig) -> None:
82
+ self._store = store
83
+ self._client = client
84
+ self._config = config
85
+
86
+ def yaml(self, io: Any, format: Literal["neat", "toolkit"] = "neat") -> None:
87
+ """Read physical data model from YAML file(s)
88
+
89
+ Args:
90
+ io (Any): The file or directory path or buffer to read from.
91
+ format (Literal["neat", "toolkit"]): The format of the input file(s).
92
+ - "neat": Neat's DMS table format.
93
+ - "toolkit": Cognite DMS API format which is the format used by Cognite Toolkit.
94
+ """
95
+
96
+ path = NeatReader.create(io).materialize_path()
97
+
98
+ reader: DMSImporter
99
+ if format == "neat":
100
+ reader = DMSTableImporter.from_yaml(path)
101
+ elif format == "toolkit":
102
+ reader = DMSAPIImporter.from_yaml(path)
103
+ else:
104
+ raise UserInputError(f"Unsupported format: {format}. Supported formats are 'neat' and 'toolkit'.")
105
+
106
+ on_success = DmsDataModelValidation(
107
+ modus_operandi=self._config.modeling.mode,
108
+ cdf_snapshot=self._store.cdf_snapshot,
109
+ limits=self._store.cdf_limits,
110
+ can_run_validator=self._config.validation.can_run_validator,
111
+ enable_alpha_validators=self._config.alpha.enable_experimental_validators,
112
+ )
113
+ return self._store.read_physical(reader, on_success)
114
+
115
+ def json(self, io: Any, format: Literal["neat", "toolkit"] = "neat") -> None:
116
+ """Read physical data model from JSON file(s)
117
+
118
+ Args:
119
+ io (Any): The file or directory path or buffer to read from.
120
+ format (Literal["neat", "toolkit"]): The format of the input file(s).
121
+ - "neat": Neat's DMS table format.
122
+ - "toolkit": Cognite DMS API format which is the format used by Cognite Toolkit.
123
+ """
124
+
125
+ path = NeatReader.create(io).materialize_path()
126
+
127
+ reader: DMSImporter
128
+ if format == "neat":
129
+ reader = DMSTableImporter.from_json(path)
130
+ elif format == "toolkit":
131
+ reader = DMSAPIImporter.from_json(path)
132
+ else:
133
+ raise UserInputError(f"Unsupported format: {format}. Supported formats are 'neat' and 'toolkit'.")
134
+
135
+ on_success = DmsDataModelValidation(
136
+ modus_operandi=self._config.modeling.mode,
137
+ cdf_snapshot=self._store.cdf_snapshot,
138
+ limits=self._store.cdf_limits,
139
+ can_run_validator=self._config.validation.can_run_validator,
140
+ enable_alpha_validators=self._config.alpha.enable_experimental_validators,
141
+ )
142
+ return self._store.read_physical(reader, on_success)
143
+
144
+ def excel(self, io: Any) -> None:
145
+ """Read physical data model from Excel file
146
+
147
+ Args:
148
+ io (Any): The file path or buffer to read from.
149
+
150
+ """
151
+
152
+ path = NeatReader.create(io).materialize_path()
153
+ reader = DMSTableImporter.from_excel(path)
154
+
155
+ on_success = DmsDataModelValidation(
156
+ modus_operandi=self._config.modeling.mode,
157
+ cdf_snapshot=self._store.cdf_snapshot,
158
+ limits=self._store.cdf_limits,
159
+ can_run_validator=self._config.validation.can_run_validator,
160
+ enable_alpha_validators=self._config.alpha.enable_experimental_validators,
161
+ )
162
+
163
+ return self._store.read_physical(reader, on_success)
164
+
165
+ def cdf(self, space: str, external_id: str, version: str) -> None:
166
+ """Read physical data model from CDF
167
+
168
+ Args:
169
+ space (str): The schema space of the data model.
170
+ external_id (str): The external id of the data model.
171
+ version (str): The version of the data model.
172
+
173
+ """
174
+ reader = DMSAPIImporter.from_cdf(
175
+ DataModelReference(space=space, external_id=external_id, version=version), self._client
176
+ )
177
+
178
+ on_success = DmsDataModelValidation(
179
+ modus_operandi=self._config.modeling.mode,
180
+ cdf_snapshot=self._store.cdf_snapshot,
181
+ limits=self._store.cdf_limits,
182
+ can_run_validator=self._config.validation.can_run_validator,
183
+ enable_alpha_validators=self._config.alpha.enable_experimental_validators,
184
+ )
185
+
186
+ return self._store.read_physical(reader, on_success)
187
+
188
+
189
+ @session_wrapper
190
+ class WritePhysicalDataModel:
191
+ """Write physical data model to various sources from NeatSession store.
192
+
193
+ Available methods:
194
+
195
+ - `neat.physical_data_model.write.yaml`
196
+ - `neat.physical_data_model.write.json`
197
+ - `neat.physical_data_model.write.excel`
198
+ - `neat.physical_data_model.write.cdf`
199
+ """
200
+
201
+ def __init__(self, store: NeatStore, client: NeatClient, config: NeatConfig) -> None:
202
+ self._store = store
203
+ self._client = client
204
+ self._config = config
205
+
206
+ def yaml(self, io: Any, format: Literal["neat", "toolkit"] = "neat") -> None:
207
+ """Write physical data model to YAML file
208
+
209
+ Args:
210
+ io (Any): The file path or buffer to write to.
211
+ format (Literal["neat", "toolkit"]): The format of the output file
212
+ - "neat": Neat's DMS table format.
213
+ - "toolkit": Cognite DMS API format which is the format used by Cognite Toolkit.
214
+ """
215
+
216
+ file_path = NeatReader.create(io).materialize_path()
217
+ writer: DMSExporter
218
+ if format == "neat":
219
+ writer = DMSTableYamlExporter()
220
+ elif format == "toolkit":
221
+ writer = DMSAPIYAMLExporter()
222
+ else:
223
+ raise UserInputError(f"Unsupported format: {format}. Supported formats are 'neat' and 'toolkit'.")
224
+
225
+ return self._store.write_physical(writer, file_path=file_path)
226
+
227
+ def json(self, io: Any, format: Literal["neat", "toolkit"] = "neat") -> None:
228
+ """Write physical data model to JSON file
229
+
230
+ Args:
231
+ io (Any): The file path or buffer to write to.
232
+ format (Literal["neat", "toolkit"]): The format of the output file
233
+ - "neat": Neat's DMS table format.
234
+ - "toolkit": Cognite DMS API format which is the format used by Cognite Toolkit.
235
+ """
236
+
237
+ file_path = NeatReader.create(io).materialize_path()
238
+ writer: DMSExporter
239
+ if format == "neat":
240
+ writer = DMSTableJSONExporter()
241
+ elif format == "toolkit":
242
+ writer = DMSAPIJSONExporter()
243
+ else:
244
+ raise UserInputError(f"Unsupported format: {format}. Supported formats are 'neat' and 'toolkit'.")
245
+
246
+ return self._store.write_physical(writer, file_path=file_path)
247
+
248
+ def excel(self, io: Any, skip_other_spaces: bool = True) -> None:
249
+ """Write physical data model to Excel file
250
+
251
+ Args:
252
+ io (Any): The file path or buffer to write to.
253
+ skip_other_spaces (bool): If true, only properties in the same space as the data model will be written.
254
+
255
+ """
256
+
257
+ file_path = NeatReader.create(io).materialize_path()
258
+ options = WorkbookOptions(skip_properties_in_other_spaces=skip_other_spaces)
259
+ writer = DMSExcelExporter(options=options)
260
+
261
+ return self._store.write_physical(writer, file_path=file_path)
262
+
263
+ def cdf(self, dry_run: bool = True, rollback: bool = False, drop_data: bool = False) -> None:
264
+ """Write physical data model with views, containers, and spaces that are in the same space as the data model
265
+ to CDF.
266
+
267
+ Args:
268
+ dry_run (bool): If true, the changes will not be applied to CDF. Instead, Neat will
269
+ report what changes would have been made.
270
+ rollback (bool): If true, all changes will be rolled back if any error occurs.
271
+ drop_data (bool): Only applicable if the session mode is 'rebuild'. If
272
+
273
+ !!! note "Impact of governance profile"
274
+ This method depends on the session governance profile for data modeling set when creating the NeatSession:
275
+
276
+ - In `additive` mode, only new or updates to data models/views/containers will be applied.
277
+ You cannot remove views from data models, properties from views or containers, or
278
+ indexes or constraints from containers.
279
+
280
+ - In `rebuild` mode, the data model in CDF will be made to exactly match the data model in Neat.
281
+ If there are any breaking changes, Neat will delete and recreate the relevant
282
+ data model/view/container. However, if drop_data is set to False, Neat will treat
283
+ containers as `additive` and will not delete any containers or remove properties,
284
+ indexes, or constraints. To fully rebuild the data model, including containers, set drop_data to True.
285
+ """
286
+ writer = DMSAPIExporter()
287
+ options = DeploymentOptions(
288
+ dry_run=dry_run,
289
+ auto_rollback=rollback,
290
+ drop_data=drop_data,
291
+ modus_operandi=self._config.modeling.mode,
292
+ )
293
+ on_success = SchemaDeployer(self._client, options)
294
+ return self._store.write_physical(writer, on_success)
@@ -0,0 +1,3 @@
1
+ from ._result import Result
2
+
3
+ __all__ = ["Result"]
File without changes
@@ -0,0 +1,196 @@
1
+ import itertools
2
+ from typing import Any
3
+
4
+ from pydantic import BaseModel, Field
5
+
6
+ from cognite.neat._data_model.deployer.data_classes import (
7
+ AddedField,
8
+ AppliedChanges,
9
+ ChangedField,
10
+ ChangeResult,
11
+ DeploymentResult,
12
+ FieldChange,
13
+ FieldChanges,
14
+ RemovedField,
15
+ ResourceChange,
16
+ )
17
+
18
+
19
+ class SerializedFieldChange(BaseModel):
20
+ """Serialized field change for JSON output."""
21
+
22
+ field_path: str
23
+ severity: str
24
+ description: str
25
+
26
+ @classmethod
27
+ def from_field_change(cls, field_change: FieldChange) -> list["SerializedFieldChange"]:
28
+ """Serialize a field change, handling nested FieldChanges recursively.
29
+
30
+ Args:
31
+ field_change: The field change to serialize.
32
+
33
+ Returns:
34
+ List of serialized field changes (may be multiple if nested).
35
+ """
36
+ serialized_changes: list[SerializedFieldChange] = []
37
+
38
+ if isinstance(field_change, FieldChanges):
39
+ # Recursively handle nested changes
40
+ for change in field_change.changes:
41
+ serialized_changes.extend(cls.from_field_change(change))
42
+ else:
43
+ # Base case: single field change
44
+ serialized_changes.append(cls._from_single_field_change(field_change))
45
+
46
+ return serialized_changes
47
+
48
+ @classmethod
49
+ def _from_single_field_change(cls, field_change: FieldChange) -> "SerializedFieldChange":
50
+ """Serialize a single non-nested field change.
51
+
52
+ Args:
53
+ field_change: The single field change to serialize.
54
+
55
+ Returns:
56
+ Serialized field change.
57
+ """
58
+ return cls(
59
+ field_path=field_change.field_path,
60
+ severity=field_change.severity.name,
61
+ description=field_change.description
62
+ if isinstance(field_change, AddedField | RemovedField | ChangedField)
63
+ else "Field changed",
64
+ )
65
+
66
+
67
+ class SerializedResourceChange(BaseModel):
68
+ """Serialized resource change for JSON output."""
69
+
70
+ id: int
71
+ endpoint: str
72
+ change_type: str
73
+ severity: str
74
+ resource_id: str
75
+ message: str | None = None
76
+ changes: list[SerializedFieldChange] = Field(default_factory=list)
77
+
78
+ @classmethod
79
+ def from_resource_change(
80
+ cls, resource: ResourceChange, endpoint: str, change_id: int
81
+ ) -> "SerializedResourceChange":
82
+ """Serialize a single resource change.
83
+
84
+ Args:
85
+ resource: The resource change to serialize.
86
+ endpoint: The endpoint type.
87
+ change_id: Unique ID for this change.
88
+
89
+ Returns:
90
+ Serialized resource change.
91
+ """
92
+ changes: list[SerializedFieldChange] = []
93
+
94
+ for change in resource.changes:
95
+ changes.extend(SerializedFieldChange.from_field_change(change))
96
+
97
+ return cls(
98
+ id=change_id,
99
+ endpoint=endpoint,
100
+ change_type=resource.change_type,
101
+ severity=resource.severity.name,
102
+ resource_id=str(resource.resource_id),
103
+ changes=changes,
104
+ message=resource.message,
105
+ )
106
+
107
+ @classmethod
108
+ def from_change_result(cls, change_id: int, response: ChangeResult) -> "SerializedResourceChange":
109
+ """Serialize from a change result (actual deployment).
110
+
111
+ Args:
112
+ change_id: Unique ID for this change.
113
+ response: The change result from deployment.
114
+
115
+ Returns:
116
+ Serialized resource change with deployment status.
117
+ """
118
+ serialized_resource_change = cls.from_resource_change(
119
+ resource=response.change,
120
+ endpoint=response.endpoint,
121
+ change_id=change_id,
122
+ )
123
+
124
+ serialized_resource_change.message = response.message
125
+ if not response.is_success:
126
+ serialized_resource_change.change_type = "failed"
127
+
128
+ return serialized_resource_change
129
+
130
+
131
+ class SerializedChanges(BaseModel):
132
+ """Container for all serialized changes."""
133
+
134
+ changes: list[SerializedResourceChange] = Field(default_factory=list)
135
+
136
+ @classmethod
137
+ def from_deployment_result(cls, result: DeploymentResult) -> "SerializedChanges":
138
+ """Create SerializedChanges from a DeploymentResult.
139
+
140
+ Args:
141
+ result: The deployment result to serialize changes from.
142
+
143
+ Returns:
144
+ SerializedChanges instance with all changes.
145
+ """
146
+ serialized = cls()
147
+
148
+ if not result.responses:
149
+ serialized._add_from_dry_run(result)
150
+ else:
151
+ serialized._add_from_applied_changes(result.responses)
152
+
153
+ return serialized
154
+
155
+ def _add_from_dry_run(self, result: DeploymentResult) -> None:
156
+ """Add changes from dry run deployment.
157
+
158
+ Args:
159
+ result: The deployment result in dry run mode.
160
+ """
161
+ # Iterate over each endpoint plan
162
+ for endpoint_plan in result.plan:
163
+ # Then per resource in the endpoint
164
+ for resource in endpoint_plan.resources:
165
+ # Then serialize individual resource change
166
+ serialized_resource_change = SerializedResourceChange.from_resource_change(
167
+ resource=resource,
168
+ endpoint=endpoint_plan.endpoint,
169
+ change_id=len(self.changes),
170
+ )
171
+ self.changes.append(serialized_resource_change)
172
+
173
+ def _add_from_applied_changes(self, applied_changes: AppliedChanges) -> None:
174
+ """Add changes from actual deployment.
175
+ Args:
176
+ result: The deployment result from actual deployment.
177
+ """
178
+ for response in itertools.chain(
179
+ applied_changes.created,
180
+ applied_changes.merged_updated,
181
+ applied_changes.deletions,
182
+ applied_changes.unchanged,
183
+ applied_changes.skipped,
184
+ ):
185
+ self.changes.append(SerializedResourceChange.from_change_result(len(self.changes), response))
186
+
187
+ def model_dump_json_flat(self, **kwargs: Any) -> str:
188
+ """Dump changes as JSON array without the wrapper key.
189
+ Returns:
190
+ JSON string of the changes array.
191
+ """
192
+ if not self.changes:
193
+ return "[]"
194
+
195
+ iterator = (change.model_dump_json(**kwargs) for change in self.changes)
196
+ return f"[{','.join(iterator)}]"