cognite-neat 0.70.1__py3-none-any.whl → 0.127.19__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 (530) hide show
  1. cognite/neat/__init__.py +4 -1
  2. cognite/neat/_client/__init__.py +4 -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 +125 -0
  7. cognite/neat/_client/data_classes.py +44 -0
  8. cognite/neat/_client/data_model_api.py +115 -0
  9. cognite/neat/_client/spaces_api.py +115 -0
  10. cognite/neat/_client/statistics_api.py +24 -0
  11. cognite/neat/_client/views_api.py +129 -0
  12. cognite/neat/_data_model/_analysis.py +186 -0
  13. cognite/neat/_data_model/_constants.py +67 -0
  14. cognite/neat/_data_model/_identifiers.py +61 -0
  15. cognite/neat/_data_model/_shared.py +41 -0
  16. cognite/neat/_data_model/deployer/_differ.py +140 -0
  17. cognite/neat/_data_model/deployer/_differ_container.py +360 -0
  18. cognite/neat/_data_model/deployer/_differ_data_model.py +54 -0
  19. cognite/neat/_data_model/deployer/_differ_space.py +9 -0
  20. cognite/neat/_data_model/deployer/_differ_view.py +299 -0
  21. cognite/neat/_data_model/deployer/data_classes.py +529 -0
  22. cognite/neat/_data_model/deployer/deployer.py +401 -0
  23. cognite/neat/_data_model/exporters/__init__.py +15 -0
  24. cognite/neat/_data_model/exporters/_api_exporter.py +37 -0
  25. cognite/neat/_data_model/exporters/_base.py +24 -0
  26. cognite/neat/_data_model/exporters/_table_exporter/exporter.py +128 -0
  27. cognite/neat/_data_model/exporters/_table_exporter/workbook.py +409 -0
  28. cognite/neat/_data_model/exporters/_table_exporter/writer.py +399 -0
  29. cognite/neat/_data_model/importers/__init__.py +5 -0
  30. cognite/neat/_data_model/importers/_api_importer.py +166 -0
  31. cognite/neat/_data_model/importers/_base.py +16 -0
  32. cognite/neat/_data_model/importers/_table_importer/data_classes.py +291 -0
  33. cognite/neat/_data_model/importers/_table_importer/importer.py +192 -0
  34. cognite/neat/_data_model/importers/_table_importer/reader.py +875 -0
  35. cognite/neat/_data_model/importers/_table_importer/source.py +94 -0
  36. cognite/neat/_data_model/models/conceptual/_base.py +18 -0
  37. cognite/neat/_data_model/models/conceptual/_concept.py +67 -0
  38. cognite/neat/_data_model/models/conceptual/_data_model.py +51 -0
  39. cognite/neat/_data_model/models/conceptual/_properties.py +104 -0
  40. cognite/neat/_data_model/models/conceptual/_property.py +105 -0
  41. cognite/neat/_data_model/models/dms/__init__.py +206 -0
  42. cognite/neat/_data_model/models/dms/_base.py +31 -0
  43. cognite/neat/_data_model/models/dms/_constants.py +47 -0
  44. cognite/neat/_data_model/models/dms/_constraints.py +42 -0
  45. cognite/neat/_data_model/models/dms/_container.py +159 -0
  46. cognite/neat/_data_model/models/dms/_data_model.py +94 -0
  47. cognite/neat/_data_model/models/dms/_data_types.py +195 -0
  48. cognite/neat/_data_model/models/dms/_http.py +28 -0
  49. cognite/neat/_data_model/models/dms/_indexes.py +30 -0
  50. cognite/neat/_data_model/models/dms/_limits.py +96 -0
  51. cognite/neat/_data_model/models/dms/_references.py +135 -0
  52. cognite/neat/_data_model/models/dms/_schema.py +18 -0
  53. cognite/neat/_data_model/models/dms/_space.py +48 -0
  54. cognite/neat/_data_model/models/dms/_types.py +17 -0
  55. cognite/neat/_data_model/models/dms/_view_filter.py +282 -0
  56. cognite/neat/_data_model/models/dms/_view_property.py +235 -0
  57. cognite/neat/_data_model/models/dms/_views.py +210 -0
  58. cognite/neat/_data_model/models/entities/__init__.py +50 -0
  59. cognite/neat/_data_model/models/entities/_base.py +101 -0
  60. cognite/neat/_data_model/models/entities/_constants.py +22 -0
  61. cognite/neat/_data_model/models/entities/_data_types.py +144 -0
  62. cognite/neat/_data_model/models/entities/_identifiers.py +61 -0
  63. cognite/neat/_data_model/models/entities/_parser.py +226 -0
  64. cognite/neat/_data_model/validation/dms/__init__.py +57 -0
  65. cognite/neat/_data_model/validation/dms/_ai_readiness.py +167 -0
  66. cognite/neat/_data_model/validation/dms/_base.py +304 -0
  67. cognite/neat/_data_model/validation/dms/_connections.py +627 -0
  68. cognite/neat/_data_model/validation/dms/_consistency.py +56 -0
  69. cognite/neat/_data_model/validation/dms/_containers.py +135 -0
  70. cognite/neat/_data_model/validation/dms/_limits.py +414 -0
  71. cognite/neat/_data_model/validation/dms/_orchestrator.py +202 -0
  72. cognite/neat/_data_model/validation/dms/_views.py +101 -0
  73. cognite/neat/_exceptions.py +56 -0
  74. cognite/neat/_issues.py +68 -0
  75. cognite/neat/_session/__init__.py +3 -0
  76. cognite/neat/_session/_html/_render.py +30 -0
  77. cognite/neat/_session/_html/static/__init__.py +8 -0
  78. cognite/neat/_session/_html/static/deployment.css +303 -0
  79. cognite/neat/_session/_html/static/deployment.js +149 -0
  80. cognite/neat/_session/_html/static/issues.css +211 -0
  81. cognite/neat/_session/_html/static/issues.js +167 -0
  82. cognite/neat/_session/_html/static/shared.css +186 -0
  83. cognite/neat/_session/_html/templates/__init__.py +4 -0
  84. cognite/neat/_session/_html/templates/deployment.html +74 -0
  85. cognite/neat/_session/_html/templates/issues.html +44 -0
  86. cognite/neat/_session/_issues.py +76 -0
  87. cognite/neat/_session/_opt.py +35 -0
  88. cognite/neat/_session/_physical.py +240 -0
  89. cognite/neat/_session/_result.py +231 -0
  90. cognite/neat/_session/_session.py +69 -0
  91. cognite/neat/_session/_usage_analytics/_collector.py +131 -0
  92. cognite/neat/_session/_usage_analytics/_constants.py +23 -0
  93. cognite/neat/_session/_usage_analytics/_storage.py +240 -0
  94. cognite/neat/_session/_wrappers.py +82 -0
  95. cognite/neat/_state_machine/__init__.py +10 -0
  96. cognite/neat/_state_machine/_base.py +37 -0
  97. cognite/neat/_state_machine/_states.py +52 -0
  98. cognite/neat/_store/__init__.py +3 -0
  99. cognite/neat/_store/_provenance.py +71 -0
  100. cognite/neat/_store/_store.py +144 -0
  101. cognite/neat/_utils/_reader.py +194 -0
  102. cognite/neat/_utils/auxiliary.py +39 -0
  103. cognite/neat/_utils/collection.py +11 -0
  104. cognite/neat/_utils/http_client/__init__.py +39 -0
  105. cognite/neat/_utils/http_client/_client.py +245 -0
  106. cognite/neat/_utils/http_client/_config.py +19 -0
  107. cognite/neat/_utils/http_client/_data_classes.py +294 -0
  108. cognite/neat/_utils/http_client/_tracker.py +31 -0
  109. cognite/neat/_utils/text.py +71 -0
  110. cognite/neat/_utils/useful_types.py +37 -0
  111. cognite/neat/_utils/validation.py +149 -0
  112. cognite/neat/_version.py +2 -1
  113. cognite/neat/v0/core/__init__.py +0 -0
  114. cognite/neat/v0/core/_client/__init__.py +4 -0
  115. cognite/neat/v0/core/_client/_api/__init__.py +0 -0
  116. cognite/neat/v0/core/_client/_api/data_modeling_loaders.py +1032 -0
  117. cognite/neat/v0/core/_client/_api/neat_instances.py +101 -0
  118. cognite/neat/v0/core/_client/_api/schema.py +158 -0
  119. cognite/neat/v0/core/_client/_api/statistics.py +91 -0
  120. cognite/neat/v0/core/_client/_api_client.py +21 -0
  121. cognite/neat/v0/core/_client/data_classes/__init__.py +0 -0
  122. cognite/neat/v0/core/_client/data_classes/data_modeling.py +198 -0
  123. cognite/neat/v0/core/_client/data_classes/neat_sequence.py +261 -0
  124. cognite/neat/v0/core/_client/data_classes/schema.py +540 -0
  125. cognite/neat/v0/core/_client/data_classes/statistics.py +125 -0
  126. cognite/neat/v0/core/_client/testing.py +39 -0
  127. cognite/neat/v0/core/_config.py +11 -0
  128. cognite/neat/v0/core/_constants.py +278 -0
  129. cognite/neat/v0/core/_data_model/__init__.py +0 -0
  130. cognite/neat/v0/core/_data_model/_constants.py +210 -0
  131. cognite/neat/v0/core/_data_model/_shared.py +59 -0
  132. cognite/neat/v0/core/_data_model/analysis/__init__.py +3 -0
  133. cognite/neat/v0/core/_data_model/analysis/_base.py +578 -0
  134. cognite/neat/v0/core/_data_model/catalog/__init__.py +8 -0
  135. cognite/neat/v0/core/_data_model/catalog/classic_model.xlsx +0 -0
  136. cognite/neat/v0/core/_data_model/catalog/conceptual-imf-data-model.xlsx +0 -0
  137. cognite/neat/v0/core/_data_model/catalog/hello_world_pump.xlsx +0 -0
  138. cognite/neat/v0/core/_data_model/exporters/__init__.py +38 -0
  139. cognite/neat/v0/core/_data_model/exporters/_base.py +67 -0
  140. cognite/neat/v0/core/_data_model/exporters/_data_model2dms.py +428 -0
  141. cognite/neat/v0/core/_data_model/exporters/_data_model2excel.py +612 -0
  142. cognite/neat/v0/core/_data_model/exporters/_data_model2instance_template.py +158 -0
  143. cognite/neat/v0/core/_data_model/exporters/_data_model2semantic_model.py +646 -0
  144. cognite/neat/v0/core/_data_model/exporters/_data_model2yaml.py +84 -0
  145. cognite/neat/v0/core/_data_model/importers/__init__.py +49 -0
  146. cognite/neat/v0/core/_data_model/importers/_base.py +64 -0
  147. cognite/neat/v0/core/_data_model/importers/_base_file_reader.py +56 -0
  148. cognite/neat/v0/core/_data_model/importers/_dict2data_model.py +131 -0
  149. cognite/neat/v0/core/_data_model/importers/_dms2data_model.py +705 -0
  150. cognite/neat/v0/core/_data_model/importers/_graph2data_model.py +299 -0
  151. cognite/neat/v0/core/_data_model/importers/_rdf/__init__.py +4 -0
  152. cognite/neat/v0/core/_data_model/importers/_rdf/_base.py +161 -0
  153. cognite/neat/v0/core/_data_model/importers/_rdf/_inference2rdata_model.py +618 -0
  154. cognite/neat/v0/core/_data_model/importers/_rdf/_owl2data_model.py +124 -0
  155. cognite/neat/v0/core/_data_model/importers/_rdf/_shared.py +255 -0
  156. cognite/neat/v0/core/_data_model/importers/_spreadsheet2data_model.py +424 -0
  157. cognite/neat/v0/core/_data_model/models/__init__.py +38 -0
  158. cognite/neat/v0/core/_data_model/models/_base_unverified.py +181 -0
  159. cognite/neat/v0/core/_data_model/models/_base_verified.py +449 -0
  160. cognite/neat/v0/core/_data_model/models/_import_contexts.py +82 -0
  161. cognite/neat/v0/core/_data_model/models/_types.py +171 -0
  162. cognite/neat/v0/core/_data_model/models/conceptual/__init__.py +25 -0
  163. cognite/neat/v0/core/_data_model/models/conceptual/_unverified.py +193 -0
  164. cognite/neat/v0/core/_data_model/models/conceptual/_validation.py +308 -0
  165. cognite/neat/v0/core/_data_model/models/conceptual/_verified.py +327 -0
  166. cognite/neat/v0/core/_data_model/models/data_types.py +422 -0
  167. cognite/neat/v0/core/_data_model/models/entities/__init__.py +70 -0
  168. cognite/neat/v0/core/_data_model/models/entities/_constants.py +18 -0
  169. cognite/neat/v0/core/_data_model/models/entities/_loaders.py +155 -0
  170. cognite/neat/v0/core/_data_model/models/entities/_multi_value.py +83 -0
  171. cognite/neat/v0/core/_data_model/models/entities/_restrictions.py +230 -0
  172. cognite/neat/v0/core/_data_model/models/entities/_single_value.py +676 -0
  173. cognite/neat/v0/core/_data_model/models/entities/_types.py +103 -0
  174. cognite/neat/v0/core/_data_model/models/entities/_wrapped.py +217 -0
  175. cognite/neat/v0/core/_data_model/models/mapping/__init__.py +3 -0
  176. cognite/neat/v0/core/_data_model/models/mapping/_classic2core.py +39 -0
  177. cognite/neat/v0/core/_data_model/models/mapping/_classic2core.yaml +608 -0
  178. cognite/neat/v0/core/_data_model/models/physical/__init__.py +40 -0
  179. cognite/neat/v0/core/_data_model/models/physical/_exporter.py +658 -0
  180. cognite/neat/v0/core/_data_model/models/physical/_unverified.py +557 -0
  181. cognite/neat/v0/core/_data_model/models/physical/_validation.py +887 -0
  182. cognite/neat/v0/core/_data_model/models/physical/_verified.py +667 -0
  183. cognite/neat/v0/core/_data_model/transformers/__init__.py +70 -0
  184. cognite/neat/v0/core/_data_model/transformers/_base.py +79 -0
  185. cognite/neat/v0/core/_data_model/transformers/_converters.py +2485 -0
  186. cognite/neat/v0/core/_data_model/transformers/_mapping.py +390 -0
  187. cognite/neat/v0/core/_data_model/transformers/_union_conceptual.py +208 -0
  188. cognite/neat/v0/core/_data_model/transformers/_verification.py +120 -0
  189. cognite/neat/v0/core/_instances/__init__.py +0 -0
  190. cognite/neat/v0/core/_instances/_shared.py +37 -0
  191. cognite/neat/v0/core/_instances/_tracking/__init__.py +4 -0
  192. cognite/neat/v0/core/_instances/_tracking/base.py +30 -0
  193. cognite/neat/v0/core/_instances/_tracking/log.py +27 -0
  194. cognite/neat/v0/core/_instances/extractors/__init__.py +76 -0
  195. cognite/neat/v0/core/_instances/extractors/_base.py +58 -0
  196. cognite/neat/v0/core/_instances/extractors/_classic_cdf/__init__.py +0 -0
  197. cognite/neat/v0/core/_instances/extractors/_classic_cdf/_assets.py +37 -0
  198. cognite/neat/v0/core/_instances/extractors/_classic_cdf/_base.py +443 -0
  199. cognite/neat/v0/core/_instances/extractors/_classic_cdf/_classic.py +479 -0
  200. cognite/neat/v0/core/_instances/extractors/_classic_cdf/_data_sets.py +35 -0
  201. cognite/neat/v0/core/_instances/extractors/_classic_cdf/_events.py +33 -0
  202. cognite/neat/v0/core/_instances/extractors/_classic_cdf/_files.py +45 -0
  203. cognite/neat/v0/core/_instances/extractors/_classic_cdf/_labels.py +54 -0
  204. cognite/neat/v0/core/_instances/extractors/_classic_cdf/_relationships.py +122 -0
  205. cognite/neat/v0/core/_instances/extractors/_classic_cdf/_sequences.py +280 -0
  206. cognite/neat/v0/core/_instances/extractors/_classic_cdf/_timeseries.py +48 -0
  207. cognite/neat/v0/core/_instances/extractors/_dict.py +105 -0
  208. cognite/neat/v0/core/_instances/extractors/_dms.py +315 -0
  209. cognite/neat/v0/core/_instances/extractors/_dms_graph.py +238 -0
  210. cognite/neat/v0/core/_instances/extractors/_mock_graph_generator.py +404 -0
  211. cognite/neat/v0/core/_instances/extractors/_raw.py +67 -0
  212. cognite/neat/v0/core/_instances/extractors/_rdf_file.py +80 -0
  213. cognite/neat/v0/core/_instances/loaders/__init__.py +24 -0
  214. cognite/neat/v0/core/_instances/loaders/_base.py +116 -0
  215. cognite/neat/v0/core/_instances/loaders/_rdf2dms.py +649 -0
  216. cognite/neat/v0/core/_instances/loaders/_rdf_to_instance_space.py +249 -0
  217. cognite/neat/v0/core/_instances/queries/__init__.py +3 -0
  218. cognite/neat/v0/core/_instances/queries/_base.py +16 -0
  219. cognite/neat/v0/core/_instances/queries/_queries.py +16 -0
  220. cognite/neat/v0/core/_instances/queries/_select.py +478 -0
  221. cognite/neat/v0/core/_instances/queries/_update.py +37 -0
  222. cognite/neat/v0/core/_instances/transformers/__init__.py +65 -0
  223. cognite/neat/v0/core/_instances/transformers/_base.py +133 -0
  224. cognite/neat/v0/core/_instances/transformers/_classic_cdf.py +589 -0
  225. cognite/neat/v0/core/_instances/transformers/_prune_graph.py +315 -0
  226. cognite/neat/v0/core/_instances/transformers/_rdfpath.py +84 -0
  227. cognite/neat/v0/core/_instances/transformers/_value_type.py +366 -0
  228. cognite/neat/v0/core/_issues/__init__.py +21 -0
  229. cognite/neat/v0/core/_issues/_base.py +348 -0
  230. cognite/neat/v0/core/_issues/_contextmanagers.py +50 -0
  231. cognite/neat/v0/core/_issues/_factory.py +69 -0
  232. cognite/neat/v0/core/_issues/errors/__init__.py +90 -0
  233. cognite/neat/v0/core/_issues/errors/_external.py +91 -0
  234. cognite/neat/v0/core/_issues/errors/_general.py +51 -0
  235. cognite/neat/v0/core/_issues/errors/_properties.py +80 -0
  236. cognite/neat/v0/core/_issues/errors/_resources.py +116 -0
  237. cognite/neat/v0/core/_issues/errors/_wrapper.py +93 -0
  238. cognite/neat/{rules/issues → v0/core/_issues}/formatters.py +12 -10
  239. cognite/neat/v0/core/_issues/warnings/__init__.py +99 -0
  240. cognite/neat/v0/core/_issues/warnings/_external.py +56 -0
  241. cognite/neat/v0/core/_issues/warnings/_general.py +46 -0
  242. cognite/neat/v0/core/_issues/warnings/_models.py +165 -0
  243. cognite/neat/v0/core/_issues/warnings/_properties.py +108 -0
  244. cognite/neat/v0/core/_issues/warnings/_resources.py +110 -0
  245. cognite/neat/v0/core/_issues/warnings/user_modeling.py +125 -0
  246. cognite/neat/v0/core/_shared.py +77 -0
  247. cognite/neat/v0/core/_store/__init__.py +4 -0
  248. cognite/neat/v0/core/_store/_data_model.py +487 -0
  249. cognite/neat/v0/core/_store/_instance.py +485 -0
  250. cognite/neat/v0/core/_store/_provenance.py +217 -0
  251. cognite/neat/v0/core/_store/exceptions.py +59 -0
  252. cognite/neat/v0/core/_utils/__init__.py +0 -0
  253. cognite/neat/v0/core/_utils/auth.py +364 -0
  254. cognite/neat/v0/core/_utils/auxiliary.py +169 -0
  255. cognite/neat/v0/core/_utils/collection_.py +66 -0
  256. cognite/neat/v0/core/_utils/graph_transformations_report.py +36 -0
  257. cognite/neat/v0/core/_utils/io_.py +11 -0
  258. cognite/neat/v0/core/_utils/rdf_.py +336 -0
  259. cognite/neat/v0/core/_utils/reader/__init__.py +3 -0
  260. cognite/neat/v0/core/_utils/reader/_base.py +194 -0
  261. cognite/neat/v0/core/_utils/spreadsheet.py +182 -0
  262. cognite/neat/v0/core/_utils/tarjan.py +44 -0
  263. cognite/neat/v0/core/_utils/text.py +277 -0
  264. cognite/neat/v0/core/_utils/time_.py +17 -0
  265. cognite/neat/v0/core/_utils/upload.py +134 -0
  266. cognite/neat/v0/core/_utils/xml_.py +52 -0
  267. cognite/neat/v0/plugins/__init__.py +4 -0
  268. cognite/neat/v0/plugins/_base.py +9 -0
  269. cognite/neat/v0/plugins/_data_model.py +48 -0
  270. cognite/neat/v0/plugins/_issues.py +35 -0
  271. cognite/neat/v0/plugins/_manager.py +94 -0
  272. cognite/neat/v0/session/__init__.py +3 -0
  273. cognite/neat/v0/session/_base.py +332 -0
  274. cognite/neat/v0/session/_collector.py +131 -0
  275. cognite/neat/v0/session/_diff.py +51 -0
  276. cognite/neat/v0/session/_drop.py +103 -0
  277. cognite/neat/v0/session/_experimental.py +26 -0
  278. cognite/neat/v0/session/_explore.py +39 -0
  279. cognite/neat/v0/session/_fix.py +28 -0
  280. cognite/neat/v0/session/_inspect.py +285 -0
  281. cognite/neat/v0/session/_mapping.py +71 -0
  282. cognite/neat/v0/session/_plugin.py +66 -0
  283. cognite/neat/v0/session/_prepare.py +286 -0
  284. cognite/neat/v0/session/_read.py +923 -0
  285. cognite/neat/v0/session/_set.py +101 -0
  286. cognite/neat/v0/session/_show.py +298 -0
  287. cognite/neat/v0/session/_state/README.md +23 -0
  288. cognite/neat/v0/session/_state.py +161 -0
  289. cognite/neat/v0/session/_subset.py +88 -0
  290. cognite/neat/v0/session/_template.py +208 -0
  291. cognite/neat/v0/session/_to.py +454 -0
  292. cognite/neat/v0/session/_wizard.py +44 -0
  293. cognite/neat/v0/session/engine/__init__.py +4 -0
  294. cognite/neat/v0/session/engine/_import.py +7 -0
  295. cognite/neat/v0/session/engine/_interface.py +25 -0
  296. cognite/neat/v0/session/engine/_load.py +131 -0
  297. cognite/neat/v0/session/exceptions.py +103 -0
  298. cognite/neat/v1.py +3 -0
  299. cognite_neat-0.127.19.dist-info/METADATA +145 -0
  300. cognite_neat-0.127.19.dist-info/RECORD +318 -0
  301. {cognite_neat-0.70.1.dist-info → cognite_neat-0.127.19.dist-info}/WHEEL +1 -1
  302. cognite/neat/app/api/asgi/metrics.py +0 -4
  303. cognite/neat/app/api/configuration.py +0 -110
  304. cognite/neat/app/api/context_manager/__init__.py +0 -3
  305. cognite/neat/app/api/context_manager/manager.py +0 -16
  306. cognite/neat/app/api/data_classes/configuration.py +0 -121
  307. cognite/neat/app/api/data_classes/rest.py +0 -78
  308. cognite/neat/app/api/explorer.py +0 -64
  309. cognite/neat/app/api/routers/configuration.py +0 -24
  310. cognite/neat/app/api/routers/core.py +0 -51
  311. cognite/neat/app/api/routers/crud.py +0 -112
  312. cognite/neat/app/api/routers/data_exploration.py +0 -334
  313. cognite/neat/app/api/routers/metrics.py +0 -10
  314. cognite/neat/app/api/routers/rules.py +0 -169
  315. cognite/neat/app/api/routers/workflows.py +0 -274
  316. cognite/neat/app/api/utils/data_mapping.py +0 -17
  317. cognite/neat/app/api/utils/logging.py +0 -26
  318. cognite/neat/app/api/utils/query_templates.py +0 -92
  319. cognite/neat/app/main.py +0 -17
  320. cognite/neat/app/monitoring/metrics.py +0 -69
  321. cognite/neat/app/ui/index.html +0 -1
  322. cognite/neat/app/ui/neat-app/.gitignore +0 -23
  323. cognite/neat/app/ui/neat-app/README.md +0 -70
  324. cognite/neat/app/ui/neat-app/build/asset-manifest.json +0 -14
  325. cognite/neat/app/ui/neat-app/build/favicon.ico +0 -0
  326. cognite/neat/app/ui/neat-app/build/index.html +0 -1
  327. cognite/neat/app/ui/neat-app/build/logo192.png +0 -0
  328. cognite/neat/app/ui/neat-app/build/manifest.json +0 -25
  329. cognite/neat/app/ui/neat-app/build/robots.txt +0 -3
  330. cognite/neat/app/ui/neat-app/build/static/css/main.38a62222.css +0 -2
  331. cognite/neat/app/ui/neat-app/build/static/css/main.38a62222.css.map +0 -1
  332. cognite/neat/app/ui/neat-app/build/static/js/main.ed960141.js +0 -3
  333. cognite/neat/app/ui/neat-app/build/static/js/main.ed960141.js.LICENSE.txt +0 -97
  334. cognite/neat/app/ui/neat-app/build/static/js/main.ed960141.js.map +0 -1
  335. cognite/neat/app/ui/neat-app/build/static/media/logo.8093b84df9ed36a174c629d6fe0b730d.svg +0 -1
  336. cognite/neat/config.py +0 -46
  337. cognite/neat/constants.py +0 -36
  338. cognite/neat/exceptions.py +0 -139
  339. cognite/neat/graph/__init__.py +0 -3
  340. cognite/neat/graph/exceptions.py +0 -91
  341. cognite/neat/graph/extractor/__init__.py +0 -6
  342. cognite/neat/graph/extractor/_base.py +0 -14
  343. cognite/neat/graph/extractor/_dexpi.py +0 -306
  344. cognite/neat/graph/extractor/_graph_capturing_sheet.py +0 -401
  345. cognite/neat/graph/extractor/_mock_graph_generator.py +0 -359
  346. cognite/neat/graph/extractors/_base.py +0 -14
  347. cognite/neat/graph/extractors/_mock_graph_generator.py +0 -359
  348. cognite/neat/graph/loader/__init__.py +0 -23
  349. cognite/neat/graph/loader/_asset_loader.py +0 -516
  350. cognite/neat/graph/loader/_base.py +0 -69
  351. cognite/neat/graph/loader/_exceptions.py +0 -87
  352. cognite/neat/graph/loader/core/labels.py +0 -58
  353. cognite/neat/graph/loader/core/models.py +0 -136
  354. cognite/neat/graph/loader/core/rdf_to_assets.py +0 -1047
  355. cognite/neat/graph/loader/core/rdf_to_relationships.py +0 -558
  356. cognite/neat/graph/loader/rdf_to_dms.py +0 -309
  357. cognite/neat/graph/loader/validator.py +0 -87
  358. cognite/neat/graph/models.py +0 -6
  359. cognite/neat/graph/stores/__init__.py +0 -13
  360. cognite/neat/graph/stores/_base.py +0 -384
  361. cognite/neat/graph/stores/_graphdb_store.py +0 -51
  362. cognite/neat/graph/stores/_memory_store.py +0 -43
  363. cognite/neat/graph/stores/_oxigraph_store.py +0 -145
  364. cognite/neat/graph/stores/_oxrdflib.py +0 -247
  365. cognite/neat/graph/stores/_rdf_to_graph.py +0 -40
  366. cognite/neat/graph/transformation/entity_matcher.py +0 -101
  367. cognite/neat/graph/transformation/query_generator/__init__.py +0 -3
  368. cognite/neat/graph/transformation/query_generator/sparql.py +0 -540
  369. cognite/neat/graph/transformation/transformer.py +0 -316
  370. cognite/neat/rules/_analysis/_base.py +0 -25
  371. cognite/neat/rules/_analysis/_information_rules.py +0 -414
  372. cognite/neat/rules/_shared.py +0 -5
  373. cognite/neat/rules/analysis.py +0 -231
  374. cognite/neat/rules/examples/Rules-Nordic44-to-TNT.xlsx +0 -0
  375. cognite/neat/rules/examples/Rules-Nordic44-to-graphql.xlsx +0 -0
  376. cognite/neat/rules/examples/__init__.py +0 -18
  377. cognite/neat/rules/examples/power-grid-containers.yaml +0 -113
  378. cognite/neat/rules/examples/power-grid-example.xlsx +0 -0
  379. cognite/neat/rules/examples/power-grid-model.yaml +0 -213
  380. cognite/neat/rules/examples/rules-template.xlsx +0 -0
  381. cognite/neat/rules/examples/sheet2cdf-transformation-rules.xlsx +0 -0
  382. cognite/neat/rules/examples/skos-rules.xlsx +0 -0
  383. cognite/neat/rules/examples/source-to-solution-mapping-rules.xlsx +0 -0
  384. cognite/neat/rules/examples/wind-energy.owl +0 -1511
  385. cognite/neat/rules/exceptions.py +0 -2972
  386. cognite/neat/rules/exporter/__init__.py +0 -20
  387. cognite/neat/rules/exporter/_base.py +0 -45
  388. cognite/neat/rules/exporter/_core/__init__.py +0 -5
  389. cognite/neat/rules/exporter/_core/rules2labels.py +0 -24
  390. cognite/neat/rules/exporter/_rules2dms.py +0 -888
  391. cognite/neat/rules/exporter/_rules2excel.py +0 -212
  392. cognite/neat/rules/exporter/_rules2graphql.py +0 -183
  393. cognite/neat/rules/exporter/_rules2ontology.py +0 -523
  394. cognite/neat/rules/exporter/_rules2pydantic_models.py +0 -748
  395. cognite/neat/rules/exporter/_rules2rules.py +0 -104
  396. cognite/neat/rules/exporter/_rules2triples.py +0 -37
  397. cognite/neat/rules/exporter/_validation.py +0 -150
  398. cognite/neat/rules/exporters/__init__.py +0 -15
  399. cognite/neat/rules/exporters/_base.py +0 -42
  400. cognite/neat/rules/exporters/_models.py +0 -58
  401. cognite/neat/rules/exporters/_rules2dms.py +0 -259
  402. cognite/neat/rules/exporters/_rules2excel.py +0 -196
  403. cognite/neat/rules/exporters/_rules2ontology.py +0 -561
  404. cognite/neat/rules/exporters/_rules2yaml.py +0 -78
  405. cognite/neat/rules/exporters/_validation.py +0 -107
  406. cognite/neat/rules/importer/__init__.py +0 -22
  407. cognite/neat/rules/importer/_base.py +0 -70
  408. cognite/neat/rules/importer/_dict2rules.py +0 -158
  409. cognite/neat/rules/importer/_dms2rules.py +0 -196
  410. cognite/neat/rules/importer/_graph2rules.py +0 -304
  411. cognite/neat/rules/importer/_json2rules.py +0 -39
  412. cognite/neat/rules/importer/_owl2rules/__init__.py +0 -3
  413. cognite/neat/rules/importer/_owl2rules/_owl2classes.py +0 -239
  414. cognite/neat/rules/importer/_owl2rules/_owl2metadata.py +0 -255
  415. cognite/neat/rules/importer/_owl2rules/_owl2properties.py +0 -217
  416. cognite/neat/rules/importer/_owl2rules/_owl2rules.py +0 -290
  417. cognite/neat/rules/importer/_spreadsheet2rules.py +0 -45
  418. cognite/neat/rules/importer/_xsd2rules.py +0 -20
  419. cognite/neat/rules/importer/_yaml2rules.py +0 -39
  420. cognite/neat/rules/importers/__init__.py +0 -16
  421. cognite/neat/rules/importers/_base.py +0 -124
  422. cognite/neat/rules/importers/_dms2rules.py +0 -191
  423. cognite/neat/rules/importers/_dtdl2rules/__init__.py +0 -3
  424. cognite/neat/rules/importers/_dtdl2rules/_unit_lookup.py +0 -224
  425. cognite/neat/rules/importers/_dtdl2rules/dtdl_converter.py +0 -318
  426. cognite/neat/rules/importers/_dtdl2rules/dtdl_importer.py +0 -164
  427. cognite/neat/rules/importers/_dtdl2rules/spec.py +0 -359
  428. cognite/neat/rules/importers/_owl2rules/__init__.py +0 -3
  429. cognite/neat/rules/importers/_owl2rules/_owl2classes.py +0 -219
  430. cognite/neat/rules/importers/_owl2rules/_owl2metadata.py +0 -217
  431. cognite/neat/rules/importers/_owl2rules/_owl2properties.py +0 -203
  432. cognite/neat/rules/importers/_owl2rules/_owl2rules.py +0 -148
  433. cognite/neat/rules/importers/_spreadsheet2rules.py +0 -266
  434. cognite/neat/rules/importers/_yaml2rules.py +0 -110
  435. cognite/neat/rules/issues/__init__.py +0 -27
  436. cognite/neat/rules/issues/base.py +0 -190
  437. cognite/neat/rules/issues/dms.py +0 -331
  438. cognite/neat/rules/issues/fileread.py +0 -156
  439. cognite/neat/rules/issues/importing.py +0 -220
  440. cognite/neat/rules/issues/spreadsheet.py +0 -381
  441. cognite/neat/rules/issues/spreadsheet_file.py +0 -151
  442. cognite/neat/rules/models/__init__.py +0 -5
  443. cognite/neat/rules/models/_base.py +0 -151
  444. cognite/neat/rules/models/_rules/__init__.py +0 -14
  445. cognite/neat/rules/models/_rules/_types/__init__.py +0 -66
  446. cognite/neat/rules/models/_rules/_types/_base.py +0 -450
  447. cognite/neat/rules/models/_rules/_types/_field.py +0 -339
  448. cognite/neat/rules/models/_rules/_types/_value.py +0 -156
  449. cognite/neat/rules/models/_rules/base.py +0 -320
  450. cognite/neat/rules/models/_rules/dms_architect_rules.py +0 -1034
  451. cognite/neat/rules/models/_rules/dms_schema.py +0 -641
  452. cognite/neat/rules/models/_rules/domain_rules.py +0 -55
  453. cognite/neat/rules/models/_rules/information_rules.py +0 -525
  454. cognite/neat/rules/models/raw_rules.py +0 -304
  455. cognite/neat/rules/models/rdfpath.py +0 -238
  456. cognite/neat/rules/models/rules.py +0 -1269
  457. cognite/neat/rules/models/tables.py +0 -9
  458. cognite/neat/rules/models/value_types.py +0 -117
  459. cognite/neat/utils/__init__.py +0 -3
  460. cognite/neat/utils/auxiliary.py +0 -11
  461. cognite/neat/utils/cdf.py +0 -24
  462. cognite/neat/utils/cdf_loaders/__init__.py +0 -25
  463. cognite/neat/utils/cdf_loaders/_base.py +0 -62
  464. cognite/neat/utils/cdf_loaders/_data_modeling.py +0 -275
  465. cognite/neat/utils/cdf_loaders/_ingestion.py +0 -152
  466. cognite/neat/utils/cdf_loaders/data_classes.py +0 -121
  467. cognite/neat/utils/exceptions.py +0 -41
  468. cognite/neat/utils/spreadsheet.py +0 -84
  469. cognite/neat/utils/text.py +0 -104
  470. cognite/neat/utils/utils.py +0 -354
  471. cognite/neat/utils/xml.py +0 -37
  472. cognite/neat/workflows/__init__.py +0 -12
  473. cognite/neat/workflows/_exceptions.py +0 -41
  474. cognite/neat/workflows/base.py +0 -574
  475. cognite/neat/workflows/cdf_store.py +0 -393
  476. cognite/neat/workflows/examples/Export DMS/workflow.yaml +0 -89
  477. cognite/neat/workflows/examples/Export Rules to Ontology/workflow.yaml +0 -152
  478. cognite/neat/workflows/examples/Extract DEXPI Graph and Export Rules/workflow.yaml +0 -139
  479. cognite/neat/workflows/examples/Extract RDF Graph and Generate Assets/workflow.yaml +0 -270
  480. cognite/neat/workflows/examples/Import DMS/workflow.yaml +0 -65
  481. cognite/neat/workflows/examples/Ontology to Data Model/workflow.yaml +0 -116
  482. cognite/neat/workflows/examples/Validate Rules/workflow.yaml +0 -67
  483. cognite/neat/workflows/examples/Validate Solution Model/workflow.yaml +0 -64
  484. cognite/neat/workflows/examples/Visualize Data Model Using Mock Graph/workflow.yaml +0 -95
  485. cognite/neat/workflows/examples/Visualize Semantic Data Model/workflow.yaml +0 -111
  486. cognite/neat/workflows/manager.py +0 -309
  487. cognite/neat/workflows/migration/steps.py +0 -93
  488. cognite/neat/workflows/migration/wf_manifests.py +0 -33
  489. cognite/neat/workflows/model.py +0 -202
  490. cognite/neat/workflows/steps/data_contracts.py +0 -140
  491. cognite/neat/workflows/steps/lib/__init__.py +0 -7
  492. cognite/neat/workflows/steps/lib/graph_extractor.py +0 -123
  493. cognite/neat/workflows/steps/lib/graph_loader.py +0 -68
  494. cognite/neat/workflows/steps/lib/graph_store.py +0 -139
  495. cognite/neat/workflows/steps/lib/io_steps.py +0 -393
  496. cognite/neat/workflows/steps/lib/rules_exporter.py +0 -453
  497. cognite/neat/workflows/steps/lib/rules_importer.py +0 -171
  498. cognite/neat/workflows/steps/lib/rules_validator.py +0 -102
  499. cognite/neat/workflows/steps/lib/v1/__init__.py +0 -7
  500. cognite/neat/workflows/steps/lib/v1/graph_contextualization.py +0 -82
  501. cognite/neat/workflows/steps/lib/v1/graph_extractor.py +0 -644
  502. cognite/neat/workflows/steps/lib/v1/graph_loader.py +0 -606
  503. cognite/neat/workflows/steps/lib/v1/graph_store.py +0 -278
  504. cognite/neat/workflows/steps/lib/v1/graph_transformer.py +0 -58
  505. cognite/neat/workflows/steps/lib/v1/rules_exporter.py +0 -513
  506. cognite/neat/workflows/steps/lib/v1/rules_importer.py +0 -612
  507. cognite/neat/workflows/steps/step_model.py +0 -83
  508. cognite/neat/workflows/steps_registry.py +0 -212
  509. cognite/neat/workflows/tasks.py +0 -18
  510. cognite/neat/workflows/triggers.py +0 -169
  511. cognite/neat/workflows/utils.py +0 -19
  512. cognite_neat-0.70.1.dist-info/METADATA +0 -212
  513. cognite_neat-0.70.1.dist-info/RECORD +0 -234
  514. cognite_neat-0.70.1.dist-info/entry_points.txt +0 -3
  515. /cognite/neat/{app/api → _data_model}/__init__.py +0 -0
  516. /cognite/neat/{app/api/data_classes → _data_model/deployer}/__init__.py +0 -0
  517. /cognite/neat/{app/api/utils → _data_model/exporters/_table_exporter}/__init__.py +0 -0
  518. /cognite/neat/{app/monitoring → _data_model/importers/_table_importer}/__init__.py +0 -0
  519. /cognite/neat/{graph/extractors → _data_model/models}/__init__.py +0 -0
  520. /cognite/neat/{graph/loader/core → _data_model/models/conceptual}/__init__.py +0 -0
  521. /cognite/neat/{graph/transformation → _data_model/validation}/__init__.py +0 -0
  522. /cognite/neat/{rules → _session/_html}/__init__.py +0 -0
  523. /cognite/neat/{rules/_analysis → _session/_usage_analytics}/__init__.py +0 -0
  524. /cognite/neat/{workflows/migration → _utils}/__init__.py +0 -0
  525. /cognite/neat/{workflows/steps → v0}/__init__.py +0 -0
  526. /cognite/neat/{graph → v0/core/_instances}/examples/Knowledge-Graph-Nordic44-dirty.xml +0 -0
  527. /cognite/neat/{graph → v0/core/_instances}/examples/Knowledge-Graph-Nordic44.xml +0 -0
  528. /cognite/neat/{graph → v0/core/_instances}/examples/__init__.py +0 -0
  529. /cognite/neat/{graph → v0/core/_instances}/examples/skos-capturing-sheet-wind-topics.xlsx +0 -0
  530. {cognite_neat-0.70.1.dist-info → cognite_neat-0.127.19.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,540 @@
1
+ import sys
2
+ import warnings
3
+ import zipfile
4
+ from collections import ChainMap
5
+ from collections.abc import Iterable, MutableMapping
6
+ from dataclasses import Field, dataclass, field, fields
7
+ from pathlib import Path
8
+ from typing import Any, ClassVar, Literal, cast
9
+
10
+ import yaml
11
+ from cognite.client import data_modeling as dm
12
+ from cognite.client.data_classes import DatabaseWrite, TransformationWrite
13
+ from cognite.client.data_classes.data_modeling.views import (
14
+ ReverseDirectRelationApply,
15
+ SingleEdgeConnection,
16
+ SingleEdgeConnectionApply,
17
+ SingleReverseDirectRelation,
18
+ SingleReverseDirectRelationApply,
19
+ ViewProperty,
20
+ ViewPropertyApply,
21
+ )
22
+
23
+ from cognite.neat.v0.core._client.data_classes.data_modeling import (
24
+ CogniteResourceDict,
25
+ ContainerApplyDict,
26
+ NodeApplyDict,
27
+ SpaceApplyDict,
28
+ ViewApplyDict,
29
+ )
30
+ from cognite.neat.v0.core._issues.errors import (
31
+ NeatYamlError,
32
+ )
33
+ from cognite.neat.v0.core._issues.warnings import (
34
+ FileTypeUnexpectedWarning,
35
+ ResourcesDuplicatedWarning,
36
+ )
37
+ from cognite.neat.v0.core._utils.text import to_camel_case
38
+
39
+ if sys.version_info >= (3, 11):
40
+ from typing import Self
41
+ else:
42
+ from typing_extensions import Self
43
+
44
+
45
+ @dataclass
46
+ class DMSSchema:
47
+ data_model: dm.DataModelApply | None = None
48
+ spaces: SpaceApplyDict = field(default_factory=SpaceApplyDict)
49
+ views: ViewApplyDict = field(default_factory=ViewApplyDict)
50
+ containers: ContainerApplyDict = field(default_factory=ContainerApplyDict)
51
+ node_types: NodeApplyDict = field(default_factory=NodeApplyDict)
52
+
53
+ _FIELD_NAME_BY_RESOURCE_TYPE: ClassVar[dict[str, str]] = {
54
+ "container": "containers",
55
+ "view": "views",
56
+ "datamodel": "data_model",
57
+ "space": "spaces",
58
+ "node": "node_types",
59
+ }
60
+
61
+ @classmethod
62
+ def from_directory(cls, directory: str | Path) -> Self:
63
+ """Load a schema from a directory containing YAML files.
64
+
65
+ The directory is expected to follow the Cognite-Toolkit convention
66
+ where each file is named as `resource_type.resource_name.yaml`.
67
+ """
68
+ data, context = cls._read_directory(Path(directory))
69
+ return cls.load(data, context)
70
+
71
+ @classmethod
72
+ def _read_directory(cls, directory: Path) -> tuple[dict[str, list[Any]], dict[str, list[Path]]]:
73
+ data: dict[str, Any] = {}
74
+ context: dict[str, list[Path]] = {}
75
+ for yaml_file in directory.rglob("*.yaml"):
76
+ if "." in yaml_file.stem:
77
+ resource_type = yaml_file.stem.rsplit(".", 1)[-1]
78
+ if attr_name := cls._FIELD_NAME_BY_RESOURCE_TYPE.get(resource_type):
79
+ data.setdefault(attr_name, [])
80
+ context.setdefault(attr_name, [])
81
+ try:
82
+ loaded = yaml.safe_load(yaml_file.read_text())
83
+ except Exception as e:
84
+ warnings.warn(
85
+ FileTypeUnexpectedWarning(yaml_file, frozenset([".yaml", ".yml"]), str(e)), stacklevel=2
86
+ )
87
+ continue
88
+
89
+ if isinstance(loaded, list):
90
+ data[attr_name].extend(loaded)
91
+ context[attr_name].extend([yaml_file] * len(loaded))
92
+ else:
93
+ data[attr_name].append(loaded)
94
+ context[attr_name].append(yaml_file)
95
+ return data, context
96
+
97
+ def to_directory(
98
+ self,
99
+ directory: str | Path,
100
+ exclude: set[str] | None = None,
101
+ new_line: str | None = "\n",
102
+ encoding: str | None = "utf-8",
103
+ ) -> None:
104
+ """Save the schema to a directory as YAML files. This is compatible with the Cognite-Toolkit convention.
105
+
106
+ Args:
107
+ directory (str | Path): The directory to save the schema to.
108
+ exclude (set[str]): A set of attributes to exclude from the output.
109
+ new_line (str): The line endings to use in the output files. Defaults to "\n".
110
+ encoding (str): The encoding to use in the output files. Defaults to "utf-8".
111
+ """
112
+ path_dir = Path(directory)
113
+ exclude_set = exclude or set()
114
+ data_models = path_dir / "data_models"
115
+ data_models.mkdir(parents=True, exist_ok=True)
116
+ if "spaces" not in exclude_set:
117
+ for space in self.spaces.values():
118
+ (data_models / f"{space.space}.space.yaml").write_text(
119
+ space.dump_yaml(), newline=new_line, encoding=encoding
120
+ )
121
+ if "data_models" not in exclude_set and self.data_model:
122
+ (data_models / f"{self.data_model.external_id}.datamodel.yaml").write_text(
123
+ self.data_model.dump_yaml(), newline=new_line, encoding=encoding
124
+ )
125
+ if "views" not in exclude_set and self.views:
126
+ view_dir = data_models / "views"
127
+ view_dir.mkdir(parents=True, exist_ok=True)
128
+ for view in self.views.values():
129
+ (view_dir / f"{view.external_id}.view.yaml").write_text(
130
+ view.dump_yaml(), newline=new_line, encoding=encoding
131
+ )
132
+ if "containers" not in exclude_set and self.containers:
133
+ container_dir = data_models / "containers"
134
+ container_dir.mkdir(parents=True, exist_ok=True)
135
+ for container in self.containers.values():
136
+ (container_dir / f"{container.external_id}.container.yaml").write_text(
137
+ container.dump_yaml(), newline=new_line, encoding=encoding
138
+ )
139
+ if "node_types" not in exclude_set and self.node_types:
140
+ node_dir = data_models / "nodes"
141
+ node_dir.mkdir(parents=True, exist_ok=True)
142
+ for node in self.node_types.values():
143
+ (node_dir / f"{node.external_id}.node.yaml").write_text(
144
+ node.dump_yaml(), newline=new_line, encoding=encoding
145
+ )
146
+
147
+ @classmethod
148
+ def from_zip(cls, zip_file: str | Path) -> Self:
149
+ """Load a schema from a ZIP file containing YAML files.
150
+
151
+ The ZIP file is expected to follow the Cognite-Toolkit convention
152
+ where each file is named as `resource_type.resource_name.yaml`.
153
+ """
154
+ data, context = cls._read_zip(Path(zip_file))
155
+ return cls.load(data, context)
156
+
157
+ @classmethod
158
+ def _read_zip(cls, zip_file: Path) -> tuple[dict[str, list[Any]], dict[str, list[Path]]]:
159
+ data: dict[str, list[Any]] = {}
160
+ context: dict[str, list[Path]] = {}
161
+ with zipfile.ZipFile(zip_file, "r") as zip_ref:
162
+ for file_info in zip_ref.infolist():
163
+ if file_info.filename.endswith(".yaml"):
164
+ if "/" not in file_info.filename:
165
+ continue
166
+ filename = Path(file_info.filename.split("/")[-1])
167
+ if "." not in filename.stem:
168
+ continue
169
+ resource_type = filename.stem.rsplit(".", 1)[-1]
170
+ if attr_name := cls._FIELD_NAME_BY_RESOURCE_TYPE.get(resource_type.casefold()):
171
+ data.setdefault(attr_name, [])
172
+ context.setdefault(attr_name, [])
173
+ try:
174
+ loaded = yaml.safe_load(zip_ref.read(file_info).decode())
175
+ except Exception as e:
176
+ warnings.warn(
177
+ FileTypeUnexpectedWarning(filename, frozenset([".yaml", ".yml"]), str(e)), stacklevel=2
178
+ )
179
+ continue
180
+ if isinstance(loaded, list):
181
+ data[attr_name].extend(loaded)
182
+ context[attr_name].extend([filename] * len(loaded))
183
+ else:
184
+ data[attr_name].append(loaded)
185
+ context[attr_name].append(filename)
186
+ return data, context
187
+
188
+ def to_zip(self, zip_file: str | Path, exclude: set[str] | None = None) -> None:
189
+ """Save the schema to a ZIP file as YAML files. This is compatible with the Cognite-Toolkit convention.
190
+
191
+ Args:
192
+ zip_file (str | Path): The ZIP file to save the schema to.
193
+ exclude (set[str]): A set of attributes to exclude from the output.
194
+ """
195
+ exclude_set = exclude or set()
196
+ with zipfile.ZipFile(zip_file, "w") as zip_ref:
197
+ if "spaces" not in exclude_set:
198
+ for space in self.spaces.values():
199
+ zip_ref.writestr(f"data_models/{space.space}.space.yaml", space.dump_yaml())
200
+ if "data_models" not in exclude_set and self.data_model:
201
+ zip_ref.writestr(
202
+ f"data_models/{self.data_model.external_id}.datamodel.yaml", self.data_model.dump_yaml()
203
+ )
204
+ if "views" not in exclude_set:
205
+ for view in self.views.values():
206
+ zip_ref.writestr(f"data_models/views/{view.external_id}.view.yaml", view.dump_yaml())
207
+ if "containers" not in exclude_set:
208
+ for container in self.containers.values():
209
+ zip_ref.writestr(
210
+ f"data_models/containers/{container.external_id}.container.yaml", container.dump_yaml()
211
+ )
212
+ if "node_types" not in exclude_set:
213
+ for node in self.node_types.values():
214
+ zip_ref.writestr(f"data_models/nodes/{node.external_id}.node.yaml", node.dump_yaml())
215
+
216
+ @classmethod
217
+ def load(cls, data: str | dict[str, list[Any]], context: dict[str, list[Path]] | None = None) -> Self:
218
+ """Loads a schema from a dictionary or a YAML or JSON formatted string.
219
+
220
+ Args:
221
+ data: The data to load the schema from. This can be a dictionary, a YAML or JSON formatted string.
222
+ context: This provides linage for where the data was loaded from. This is used in Warnings
223
+ if a single item fails to load.
224
+
225
+ Returns:
226
+ DMSSchema: The loaded schema.
227
+ """
228
+ context = context or {}
229
+ if isinstance(data, str):
230
+ # YAML is a superset of JSON, so we can use the same parser
231
+ try:
232
+ data_dict = yaml.safe_load(data)
233
+ except Exception as e:
234
+ raise NeatYamlError(str(e)) from None
235
+ if not isinstance(data_dict, dict) and all(isinstance(v, list) for v in data_dict.values()):
236
+ raise NeatYamlError(f"Invalid data structure: {type(data)}", "dict[str, list[Any]]") from None
237
+ else:
238
+ data_dict = data
239
+ loaded: dict[str, Any] = {}
240
+ for attr in fields(cls):
241
+ if items := data_dict.get(attr.name) or data_dict.get(to_camel_case(attr.name)):
242
+ if attr.name == "data_model":
243
+ if isinstance(items, list) and len(items) > 1:
244
+ try:
245
+ data_model_ids = [dm.DataModelId.load(item) for item in items]
246
+ except Exception as e:
247
+ data_model_file = context.get(attr.name, [Path("UNKNOWN")])[0]
248
+ warnings.warn(
249
+ FileTypeUnexpectedWarning(
250
+ data_model_file, frozenset([dm.DataModelApply.__name__]), str(e)
251
+ ),
252
+ stacklevel=2,
253
+ )
254
+ else:
255
+ warnings.warn(
256
+ ResourcesDuplicatedWarning(
257
+ frozenset(data_model_ids),
258
+ "data model",
259
+ "Will use the first DataModel.",
260
+ ),
261
+ stacklevel=2,
262
+ )
263
+ item = items[0] if isinstance(items, list) else items
264
+ try:
265
+ loaded[attr.name] = dm.DataModelApply.load(item)
266
+ except Exception as e:
267
+ data_model_file = context.get(attr.name, [Path("UNKNOWN")])[0]
268
+ warnings.warn(
269
+ FileTypeUnexpectedWarning(data_model_file, frozenset([dm.DataModelApply.__name__]), str(e)),
270
+ stacklevel=2,
271
+ )
272
+ else:
273
+ try:
274
+ loaded[attr.name] = attr.type.load(items) # type: ignore[union-attr]
275
+ except Exception as e:
276
+ loaded[attr.name] = cls._load_individual_resources(
277
+ items, attr, str(e), context.get(attr.name, [])
278
+ )
279
+ return cls(**loaded)
280
+
281
+ @classmethod
282
+ def _load_individual_resources(
283
+ cls: Any, items: list, attr: Field, trigger_error: str, resource_context: list[Path]
284
+ ) -> list[Any]:
285
+ type_ = cast(type, attr.type)
286
+ resources = type_([])
287
+ if not hasattr(type_, "_RESOURCE"):
288
+ warnings.warn(
289
+ FileTypeUnexpectedWarning(Path("UNKNOWN"), frozenset([type_.__name__]), trigger_error), stacklevel=2
290
+ )
291
+ return resources
292
+ # Fallback to load individual resources.
293
+ single_cls = type_._RESOURCE
294
+ for no, item in enumerate(items):
295
+ try:
296
+ loaded_instance = single_cls.load(item)
297
+ except Exception as e:
298
+ try:
299
+ filepath = resource_context[no]
300
+ except IndexError:
301
+ filepath = Path("UNKNOWN")
302
+ # We use repr(e) instead of str(e) to include the exception type in the warning message
303
+ warnings.warn(
304
+ FileTypeUnexpectedWarning(filepath, frozenset([single_cls.__name__]), repr(e)), stacklevel=2
305
+ )
306
+ else:
307
+ resources.append(loaded_instance)
308
+ return resources
309
+
310
+ @classmethod
311
+ def from_read_model(cls, model: dm.DataModel[dm.View]) -> Self:
312
+ """Load schema from a read model.
313
+
314
+ CAVEAT: This method infers the containers and spaces from the views. This means that
315
+ for example indexes and constraints will not be captured in the containers.
316
+
317
+ Args:
318
+ model (dm.DataModel): The read model to load the schema from.
319
+ """
320
+ write_model = model.as_write()
321
+ write_model.views = [view.as_id() for view in model.views or []]
322
+ views = ViewApplyDict([view.as_write() for view in model.views])
323
+ containers = ContainerApplyDict()
324
+ for view in model.views:
325
+ for prop in view.properties.values():
326
+ if not isinstance(prop, dm.MappedProperty):
327
+ continue
328
+ if prop.container not in containers:
329
+ containers[prop.container] = dm.ContainerApply(
330
+ space=prop.container.space,
331
+ external_id=prop.container.external_id,
332
+ properties={},
333
+ used_for=view.used_for,
334
+ )
335
+ containers[prop.container].properties[prop.container_property_identifier] = dm.ContainerProperty(
336
+ type=prop.type,
337
+ nullable=prop.nullable,
338
+ auto_increment=prop.auto_increment,
339
+ immutable=prop.immutable,
340
+ default_value=prop.default_value,
341
+ name=prop.name,
342
+ description=prop.description,
343
+ )
344
+
345
+ schema = cls(data_model=write_model, views=views, containers=containers)
346
+ schema.spaces = SpaceApplyDict(dm.SpaceApply(space) for space in schema.referenced_spaces())
347
+ return schema
348
+
349
+ def dump(self, camel_case: bool = True, sort: bool = True) -> dict[str, Any]:
350
+ """Dump the schema to a dictionary that can be serialized to JSON.
351
+
352
+ Args:
353
+ camel_case (bool): If True, the keys in the output dictionary will be in camel case.
354
+ sort (bool): If True, the items in the output dictionary will be sorted by their ID.
355
+ This is useful for deterministic output which is useful for comparing schemas.
356
+
357
+ Returns:
358
+ dict: The schema as a dictionary.
359
+ """
360
+ output: dict[str, Any] = {}
361
+ cls_fields = sorted(fields(self), key=lambda f: f.name) if sort else fields(self)
362
+ for attr in cls_fields:
363
+ if items := getattr(self, attr.name):
364
+ key = to_camel_case(attr.name) if camel_case else attr.name
365
+ if isinstance(items, CogniteResourceDict):
366
+ if sort:
367
+ output[key] = [
368
+ item.dump(camel_case) for item in sorted(items.values(), key=self._to_sortable_identifier)
369
+ ]
370
+ else:
371
+ output[key] = items.dump(camel_case)
372
+ else:
373
+ output[key] = items.dump(camel_case=camel_case)
374
+ return output
375
+
376
+ @classmethod
377
+ def _to_sortable_identifier(cls, item: Any) -> str | tuple[str, str] | tuple[str, str, str]:
378
+ if isinstance(item, dm.ContainerApply | dm.ViewApply | dm.DataModelApply | dm.NodeApply):
379
+ identifier = item.as_id().as_tuple()
380
+ if len(identifier) == 3 and identifier[2] is None:
381
+ return identifier[:2] # type: ignore[misc]
382
+ return cast(tuple[str, str] | tuple[str, str, str], identifier)
383
+ elif isinstance(item, dm.SpaceApply):
384
+ return item.space
385
+ elif isinstance(item, TransformationWrite):
386
+ return item.external_id or ""
387
+ elif isinstance(item, DatabaseWrite):
388
+ return item.name or ""
389
+ else:
390
+ raise ValueError(f"Cannot sort item of type {type(item)}")
391
+
392
+ def referenced_spaces(self, include_indirect_references: bool = True) -> set[str]:
393
+ """Get the spaces referenced by the schema.
394
+
395
+ Args:
396
+ include_indirect_references (bool): If True, the spaces referenced by as view.implements, and
397
+ view.referenced_containers will be included in the output.
398
+ Returns:
399
+ set[str]: The spaces referenced by the schema.
400
+ """
401
+ referenced_spaces = {view.space for view in self.views.values()}
402
+ referenced_spaces |= {container.space for container in self.containers.values()}
403
+ if include_indirect_references:
404
+ referenced_spaces |= {
405
+ container.space for view in self.views.values() for container in view.referenced_containers()
406
+ }
407
+ referenced_spaces |= {parent.space for view in self.views.values() for parent in view.implements or []}
408
+ referenced_spaces |= {node.space for node in self.node_types.values()}
409
+ if self.data_model:
410
+ referenced_spaces |= {self.data_model.space}
411
+ referenced_spaces |= {view.space for view in self.data_model.views or []}
412
+ referenced_spaces |= {s.space for s in self.spaces.values()}
413
+ return referenced_spaces
414
+
415
+ def referenced_container(self) -> set[dm.ContainerId]:
416
+ referenced_containers = {
417
+ container for view in self.views.values() for container in view.referenced_containers()
418
+ }
419
+ referenced_containers |= set(self.containers.keys())
420
+ return referenced_containers
421
+
422
+ def externally_referenced_containers(self) -> set[dm.ContainerId]:
423
+ """Get the containers referenced by the schema that are not defined in the schema."""
424
+ return {container for container in self.referenced_container() if container not in self.containers}
425
+
426
+ def as_read_model(self) -> dm.DataModel[dm.View]:
427
+ if self.data_model is None:
428
+ raise ValueError("Data model is not defined")
429
+ all_containers = self.containers.copy()
430
+ all_views = self.views.copy()
431
+ views: list[dm.View] = []
432
+ for view in self.views.values():
433
+ referenced_containers = ContainerApplyDict()
434
+ properties: dict[str, ViewProperty] = {}
435
+ # ChainMap is used to merge properties from the view and its parents
436
+ # Note that the order of the ChainMap is important, as the first dictionary has the highest priority
437
+ # So if a child and parent have the same property, the child property will be used.
438
+ write_properties = ChainMap(view.properties, *(all_views[v].properties for v in view.implements or [])) # type: ignore[arg-type]
439
+ for prop_name, prop in write_properties.items():
440
+ read_prop = self._as_read_properties(prop, all_containers)
441
+ if isinstance(read_prop, dm.MappedProperty) and read_prop.container not in referenced_containers:
442
+ referenced_containers[read_prop.container] = all_containers[read_prop.container]
443
+ properties[prop_name] = read_prop
444
+
445
+ read_view = dm.View(
446
+ space=view.space,
447
+ external_id=view.external_id,
448
+ version=view.version,
449
+ description=view.description,
450
+ name=view.name,
451
+ filter=view.filter,
452
+ implements=view.implements.copy(),
453
+ used_for=self._used_for(referenced_containers.values()),
454
+ writable=self._writable(properties.values(), referenced_containers.values()),
455
+ properties=properties,
456
+ is_global=False,
457
+ last_updated_time=0,
458
+ created_time=0,
459
+ )
460
+ views.append(read_view)
461
+
462
+ return dm.DataModel(
463
+ space=self.data_model.space,
464
+ external_id=self.data_model.external_id,
465
+ version=self.data_model.version,
466
+ name=self.data_model.name,
467
+ description=self.data_model.description,
468
+ views=views,
469
+ is_global=False,
470
+ last_updated_time=0,
471
+ created_time=0,
472
+ )
473
+
474
+ @staticmethod
475
+ def _as_read_properties(
476
+ write: ViewPropertyApply, all_containers: MutableMapping[dm.ContainerId, dm.ContainerApply]
477
+ ) -> ViewProperty:
478
+ if isinstance(write, dm.MappedPropertyApply):
479
+ container_prop = all_containers[write.container].properties[write.container_property_identifier]
480
+ return dm.MappedProperty(
481
+ container=write.container,
482
+ container_property_identifier=write.container_property_identifier,
483
+ name=write.name,
484
+ description=write.description,
485
+ source=write.source,
486
+ type=container_prop.type,
487
+ nullable=container_prop.nullable,
488
+ auto_increment=container_prop.auto_increment,
489
+ immutable=container_prop.immutable,
490
+ # Likely bug in SDK.
491
+ default_value=container_prop.default_value, # type: ignore[arg-type]
492
+ )
493
+ if isinstance(write, dm.EdgeConnectionApply):
494
+ edge_cls = SingleEdgeConnection if isinstance(write, SingleEdgeConnectionApply) else dm.MultiEdgeConnection
495
+ return edge_cls(
496
+ type=write.type,
497
+ source=write.source,
498
+ name=write.name,
499
+ description=write.description,
500
+ edge_source=write.edge_source,
501
+ direction=write.direction,
502
+ )
503
+ if isinstance(write, ReverseDirectRelationApply):
504
+ relation_cls = (
505
+ SingleReverseDirectRelation
506
+ if isinstance(write, SingleReverseDirectRelationApply)
507
+ else dm.MultiReverseDirectRelation
508
+ )
509
+ return relation_cls(
510
+ source=write.source,
511
+ through=write.through,
512
+ name=write.name,
513
+ description=write.description,
514
+ )
515
+ raise ValueError(f"Cannot convert {write} to read format")
516
+
517
+ @staticmethod
518
+ def _used_for(containers: Iterable[dm.ContainerApply]) -> Literal["node", "edge", "all"]:
519
+ used_for = {container.used_for for container in containers}
520
+ if used_for == {"node"}:
521
+ return "node"
522
+ if used_for == {"edge"}:
523
+ return "edge"
524
+ return "all"
525
+
526
+ @staticmethod
527
+ def _writable(properties: Iterable[ViewProperty], containers: Iterable[dm.ContainerApply]) -> bool:
528
+ used_properties = {
529
+ (prop.container, prop.container_property_identifier)
530
+ for prop in properties
531
+ if isinstance(prop, dm.MappedProperty)
532
+ }
533
+ required_properties = {
534
+ (container.as_id(), prop_id)
535
+ for container in containers
536
+ for prop_id, prop in container.properties.items()
537
+ if not prop.nullable
538
+ }
539
+ # If a container has a required property that is not used by the view, the view is not writable
540
+ return not bool(required_properties - used_properties)
@@ -0,0 +1,125 @@
1
+ from dataclasses import dataclass
2
+ from typing import Any
3
+
4
+ from cognite.client import CogniteClient
5
+ from cognite.client.data_classes._base import CogniteObject, CogniteResource, CogniteResourceList
6
+ from typing_extensions import Self
7
+
8
+
9
+ @dataclass
10
+ class InstanceCounts(CogniteResource):
11
+ nodes: int
12
+ edges: int
13
+ soft_deleted_nodes: int
14
+ soft_deleted_edges: int
15
+
16
+ @classmethod
17
+ def _load(cls, resource: dict[str, Any], cognite_client: CogniteClient | None = None) -> Self:
18
+ return cls(
19
+ nodes=resource["nodes"],
20
+ edges=resource["edges"],
21
+ soft_deleted_nodes=resource["softDeletedNodes"],
22
+ soft_deleted_edges=resource["softDeletedEdges"],
23
+ )
24
+
25
+
26
+ @dataclass
27
+ class SpaceInstanceCounts(InstanceCounts):
28
+ space: str
29
+
30
+ @classmethod
31
+ def _load(cls, resource: dict[str, Any], cognite_client: CogniteClient | None = None) -> Self:
32
+ return cls(
33
+ space=resource["space"],
34
+ nodes=resource["nodes"],
35
+ edges=resource["edges"],
36
+ soft_deleted_nodes=resource["softDeletedNodes"],
37
+ soft_deleted_edges=resource["softDeletedEdges"],
38
+ )
39
+
40
+
41
+ class SpaceInstanceCountsList(CogniteResourceList):
42
+ _RESOURCE = SpaceInstanceCounts
43
+
44
+
45
+ @dataclass
46
+ class CountLimitPair(CogniteObject):
47
+ count: int
48
+ limit: int
49
+
50
+ @classmethod
51
+ def _load(cls, resource: dict[str, Any], cognite_client: CogniteClient | None = None) -> Self:
52
+ return cls(
53
+ count=resource["count"],
54
+ limit=resource["limit"],
55
+ )
56
+
57
+
58
+ @dataclass
59
+ class InstanceCountsLimits(InstanceCounts):
60
+ instances_limit: int
61
+ soft_deleted_instances_limit: int
62
+
63
+ @property
64
+ def instances(self) -> int:
65
+ return self.nodes + self.edges
66
+
67
+ @property
68
+ def soft_deleted_instances(self) -> int:
69
+ return self.soft_deleted_nodes + self.soft_deleted_edges
70
+
71
+ @classmethod
72
+ def _load(cls, resource: dict[str, Any], cognite_client: CogniteClient | None = None) -> Self:
73
+ return cls(
74
+ nodes=resource["nodes"],
75
+ edges=resource["edges"],
76
+ soft_deleted_nodes=resource["softDeletedNodes"],
77
+ soft_deleted_edges=resource["softDeletedEdges"],
78
+ instances_limit=resource["instancesLimit"],
79
+ soft_deleted_instances_limit=resource["softDeletedInstancesLimit"],
80
+ )
81
+
82
+
83
+ @dataclass
84
+ class ProjectStatsAndLimits(CogniteResource):
85
+ project: str
86
+ spaces: CountLimitPair
87
+ containers: CountLimitPair
88
+ views: CountLimitPair
89
+ data_models: CountLimitPair
90
+ container_properties: CountLimitPair
91
+ instances: InstanceCountsLimits
92
+ concurrent_read_limit: int
93
+ concurrent_write_limit: int
94
+ concurrent_delete_limit: int
95
+
96
+ @classmethod
97
+ def _load(cls, data: dict[str, Any], cognite_client: CogniteClient | None = None) -> Self:
98
+ return cls(
99
+ project=data["project"],
100
+ spaces=CountLimitPair._load(data["spaces"]),
101
+ containers=CountLimitPair._load(data["containers"]),
102
+ views=CountLimitPair._load(data["views"]),
103
+ data_models=CountLimitPair._load(data["dataModels"]),
104
+ container_properties=CountLimitPair._load(data["containerProperties"]),
105
+ instances=InstanceCountsLimits._load(data["instances"]),
106
+ concurrent_read_limit=data["concurrentReadLimit"],
107
+ concurrent_write_limit=data["concurrentWriteLimit"],
108
+ concurrent_delete_limit=data["concurrentDeleteLimit"],
109
+ )
110
+
111
+ def dump(self, camel_case: bool = True) -> dict[str, Any]:
112
+ return {
113
+ "project": self.project,
114
+ "spaces": self.spaces.dump(camel_case=camel_case),
115
+ "containers": self.containers.dump(camel_case=camel_case),
116
+ "views": self.views.dump(camel_case=camel_case),
117
+ "dataModels" if camel_case else "data_models": self.data_models.dump(camel_case=camel_case),
118
+ "containerProperties" if camel_case else "container_properties": self.container_properties.dump(
119
+ camel_case=camel_case
120
+ ),
121
+ "instances": self.instances.dump(camel_case=camel_case),
122
+ "concurrentReadLimit" if camel_case else "concurrent_read_limit": self.concurrent_read_limit,
123
+ "concurrentWriteLimit" if camel_case else "concurrent_write_limit": self.concurrent_write_limit,
124
+ "concurrentDeleteLimit" if camel_case else "concurrent_delete_limit": self.concurrent_delete_limit,
125
+ }