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,571 @@
1
+ from collections import defaultdict
2
+ from itertools import chain
3
+ from typing import Literal, TypeAlias, TypeVar
4
+
5
+ import networkx as nx
6
+ from pyparsing import cached_property
7
+
8
+ from cognite.neat._data_model._snapshot import SchemaSnapshot
9
+ from cognite.neat._data_model.models.dms._constraints import RequiresConstraintDefinition
10
+ from cognite.neat._data_model.models.dms._container import ContainerRequest
11
+ from cognite.neat._data_model.models.dms._data_types import DirectNodeRelation
12
+ from cognite.neat._data_model.models.dms._limits import SchemaLimits
13
+ from cognite.neat._data_model.models.dms._references import (
14
+ ContainerDirectReference,
15
+ ContainerReference,
16
+ ViewDirectReference,
17
+ ViewReference,
18
+ )
19
+ from cognite.neat._data_model.models.dms._view_property import (
20
+ EdgeProperty,
21
+ ReverseDirectRelationProperty,
22
+ ViewCorePropertyRequest,
23
+ ViewRequestProperty,
24
+ )
25
+ from cognite.neat._data_model.models.dms._views import ViewRequest
26
+ from cognite.neat._utils.useful_types import ModusOperandi, T_Reference
27
+
28
+ # Type aliases for better readability
29
+ ViewsByReference: TypeAlias = dict[ViewReference, ViewRequest]
30
+ ContainersByReference: TypeAlias = dict[ContainerReference, ContainerRequest]
31
+ AncestorsByReference: TypeAlias = dict[ViewReference, set[ViewReference]]
32
+
33
+ ReverseToDirectMapping: TypeAlias = dict[
34
+ tuple[ViewReference, str], tuple[ViewReference, ContainerDirectReference | ViewDirectReference]
35
+ ]
36
+ ConnectionEndNodeTypes: TypeAlias = dict[tuple[ViewReference, str], ViewReference | None]
37
+
38
+
39
+ ResourceSource = Literal["auto", "merged", "cdf", "both"]
40
+
41
+ _NodeT = TypeVar("_NodeT", ContainerReference, ViewReference)
42
+
43
+
44
+ class ValidationResources:
45
+ def __init__(
46
+ self, modus_operandi: ModusOperandi, local: SchemaSnapshot, cdf: SchemaSnapshot, limits: SchemaLimits
47
+ ) -> None:
48
+ self._modus_operandi = modus_operandi
49
+ self.limits = limits
50
+
51
+ self.local = local
52
+ self.cdf = cdf
53
+
54
+ if self._modus_operandi == "additive":
55
+ self.merged = self.local.merge(self.cdf)
56
+ elif self._modus_operandi == "rebuild":
57
+ self.merged = local.model_copy(deep=True)
58
+ else:
59
+ raise RuntimeError(f"ValidationResources: Unknown modus_operandi: {self._modus_operandi}. This is a bug!")
60
+
61
+ # need this shortcut for easier access and also to avoid mypy to complains
62
+ self.merged_data_model = self.merged.data_model[next(iter(self.merged.data_model.keys()))]
63
+
64
+ # For caching of expanded views
65
+ self._expanded_views_cache: dict[ViewReference, ViewRequest] = {}
66
+
67
+ def select_view(
68
+ self, view_ref: ViewReference, property_: str | None = None, source: ResourceSource = "auto"
69
+ ) -> ViewRequest | None:
70
+ """Select view definition based on source strategy and optionally filter by property.
71
+
72
+ Selection prioritize merged view over CDF if both are available, as merged view represents the effective
73
+ definition which will be a result when the local schema is deployed to CDF.
74
+
75
+
76
+ Args:
77
+ view_ref: The view to select
78
+ property_: Optional property name to filter views that contain this property
79
+ source: The source strategy to use, options are: "auto", "local", "cdf", "both", where "auto" means
80
+ that the selection is driven by the modus_operandi of the validation resources.
81
+
82
+ Returns:
83
+ The selected ViewRequest or None if not found.
84
+ """
85
+
86
+ check_merged, check_cdf = self._resolve_resource_sources(view_ref, source)
87
+
88
+ merged_view = self.merged.views.get(view_ref) if check_merged else None
89
+ cdf_view = self.cdf.views.get(view_ref) if check_cdf else None
90
+
91
+ if property_ is None:
92
+ return merged_view or cdf_view
93
+
94
+ # Filtering based on the property presence
95
+ # Try views with the property first, then any available view where merged view is prioritized
96
+ candidates = chain(
97
+ (v for v in (merged_view, cdf_view) if v and v.properties and property_ in v.properties),
98
+ (v for v in (merged_view, cdf_view) if v),
99
+ )
100
+
101
+ return next(candidates, None)
102
+
103
+ def select_container(
104
+ self, container_ref: ContainerReference, property_: str | None = None, source: ResourceSource = "auto"
105
+ ) -> ContainerRequest | None:
106
+ """Select container definition based on source strategy and optionally filter by property.
107
+
108
+ Selection prioritize merged container over CDF if both are available, as merged container represents
109
+ the effective definition which will be a result when the local schema is deployed to CDF.
110
+
111
+ Args:
112
+ container_ref: The container to select
113
+ property_: Optional property name to filter containers that contain this property
114
+ source: The source strategy to use, options are: "auto", "local", "cdf", "both", where "auto" means
115
+ that the selection is driven by the modus_operandi of the validation resources.
116
+
117
+ Returns:
118
+ The selected ContainerRequest or None if not found.
119
+ """
120
+
121
+ check_merged, check_cdf = self._resolve_resource_sources(container_ref, source)
122
+
123
+ merged_container = self.merged.containers.get(container_ref) if check_merged else None
124
+ cdf_container = self.cdf.containers.get(container_ref) if check_cdf else None
125
+
126
+ if property_ is None:
127
+ return merged_container or cdf_container
128
+
129
+ # Try containers with the property first, then any available container
130
+ candidates = chain(
131
+ (c for c in (merged_container, cdf_container) if c and c.properties and property_ in c.properties),
132
+ (c for c in (merged_container, cdf_container) if c),
133
+ )
134
+
135
+ return next(candidates, None)
136
+
137
+ def _resolve_resource_sources(
138
+ self, resource_ref: ViewReference | ContainerReference, source: ResourceSource
139
+ ) -> tuple[bool, bool]:
140
+ """
141
+ Determine which resource sources (merged and/or CDF) to check based on the source parameter.
142
+
143
+ Args:
144
+ resource_ref: The resource reference to check (ViewReference or ContainerReference)
145
+ source: The source strategy to use
146
+
147
+ Returns:
148
+ Tuple of (check_merged, check_cdf) booleans indicating which sources to check
149
+ """
150
+ if source == "auto":
151
+ # Auto mode: driven by data modeling modus (approach)
152
+ # If elements is in the schema space, we check merged, else we check CDF
153
+
154
+ in_schema_space = resource_ref.space == self.merged_data_model.space
155
+
156
+ if self._modus_operandi == "additive":
157
+ # In additive modus, schema space means local additions on top of CDF
158
+ # always check CDF, while do not check merged if resource is not in schema space
159
+ check_merged = in_schema_space
160
+ check_cdf = True
161
+ elif self._modus_operandi == "rebuild":
162
+ # In rebuild modus, schema space means the full desired state is in local schema (i.e., merged)
163
+ # you are not adding to CDF, but replacing it, so never check CDF for schema space resources
164
+ check_merged = in_schema_space
165
+ check_cdf = not in_schema_space
166
+ else:
167
+ raise RuntimeError(
168
+ f"_resolve_resource_sources: Unknown modus_operandi: {self._modus_operandi}. This is a bug!"
169
+ )
170
+
171
+ elif source == "merged":
172
+ check_merged = True
173
+ check_cdf = False
174
+ elif source == "cdf":
175
+ check_merged = False
176
+ check_cdf = True
177
+ elif source == "both":
178
+ check_merged = True
179
+ check_cdf = True
180
+ else:
181
+ raise RuntimeError(f"_resolve_resource_sources: Unknown source: {source}. This is a bug!")
182
+
183
+ return check_merged, check_cdf
184
+
185
+ @cached_property
186
+ def ancestors_by_view(self) -> dict[ViewReference, list[ViewReference]]:
187
+ """
188
+ Create a mapping of each view to its list of ancestors.
189
+
190
+ Returns:
191
+ Dictionary mapping each ViewReference to its list of ancestor ViewReferences
192
+ """
193
+ ancestors_mapping: dict[ViewReference, list[ViewReference]] = {}
194
+
195
+ if not self.merged_data_model.views:
196
+ return ancestors_mapping
197
+
198
+ for view in self.merged_data_model.views:
199
+ ancestors_mapping[view] = self.view_ancestors(view)
200
+ return ancestors_mapping
201
+
202
+ def view_ancestors(
203
+ self, offspring: ViewReference, ancestors: list[ViewReference] | None = None, source: ResourceSource = "auto"
204
+ ) -> list[ViewReference]:
205
+ """
206
+ Recursively find all ancestors of a given view by traversing the implements hierarchy.
207
+ Handles branching to explore all possible ancestor paths.
208
+
209
+ Args:
210
+ offspring: The view to find ancestors for
211
+ ancestors: Accumulated list of ancestors (used internally for recursion)
212
+
213
+ Returns:
214
+ List of all ancestor ViewReferences
215
+ """
216
+ if ancestors is None:
217
+ ancestors = []
218
+
219
+ # Determine which view definition to use based on space and modus operandi
220
+ view_definition = self.select_view(view_ref=offspring, source=source)
221
+
222
+ # Base case: no view definition or no implements
223
+ if not view_definition or not view_definition.implements:
224
+ return ancestors
225
+
226
+ # Explore all parent branches
227
+ for parent in view_definition.implements:
228
+ if parent not in ancestors:
229
+ ancestors.append(parent)
230
+ # Recursively explore this branch
231
+ self.view_ancestors(parent, ancestors)
232
+
233
+ return ancestors
234
+
235
+ def is_ancestor(self, offspring: ViewReference, ancestor: ViewReference) -> bool:
236
+ return ancestor in self.view_ancestors(offspring)
237
+
238
+ def _expand_view(self, view_ref: ViewReference) -> ViewRequest | None:
239
+ """Expand a view by including properties from its ancestors.
240
+
241
+ Args:
242
+ view_ref: The view to expand.
243
+
244
+ Returns:
245
+ ViewRequest with expanded properties, or None if view not found.
246
+ """
247
+ view = self.select_view(view_ref)
248
+
249
+ if not view:
250
+ return None
251
+
252
+ # Create a deep copy to avoid mutating the original
253
+ expanded_view = view.model_copy(deep=True)
254
+
255
+ # Get all ancestor properties (oldest to newest)
256
+ ancestor_refs = self.view_ancestors(view_ref)
257
+ ancestor_properties: dict[str, ViewRequestProperty] = {}
258
+
259
+ # Collect properties from ancestors, overriding with newer ancestors properties
260
+ for ancestor_ref in reversed(ancestor_refs):
261
+ ancestor = self.select_view(ancestor_ref)
262
+ if ancestor and ancestor.properties:
263
+ ancestor_properties.update(ancestor.properties)
264
+
265
+ # Merge: ancestor properties first, then override with view's own properties
266
+ if ancestor_properties:
267
+ if not expanded_view.properties:
268
+ expanded_view.properties = {}
269
+
270
+ # Ancestor properties are base, view properties override
271
+ expanded_view.properties = {**ancestor_properties, **expanded_view.properties}
272
+
273
+ return expanded_view
274
+
275
+ def expand_view_properties(self, view_ref: ViewReference) -> ViewRequest | None:
276
+ """Get a mapping of view references to their corresponding properties, both directly defined and inherited
277
+ from ancestor views through implements."""
278
+
279
+ if view_ref not in self._expanded_views_cache:
280
+ expanded_view = self._expand_view(view_ref)
281
+ if expanded_view:
282
+ self._expanded_views_cache[view_ref] = expanded_view
283
+
284
+ return self._expanded_views_cache.get(view_ref)
285
+
286
+ @cached_property
287
+ def referenced_containers(self) -> set[ContainerReference]:
288
+ """Get a set of all container references used by the views in the local data model."""
289
+
290
+ referenced_containers: set[ContainerReference] = set()
291
+
292
+ if not self.merged_data_model.views:
293
+ return referenced_containers
294
+
295
+ for view_ref in self.merged_data_model.views:
296
+ view = self.select_view(view_ref)
297
+ # This should never happen, if it happens, it's a bug
298
+ if not view:
299
+ raise RuntimeError(f"referenced_containers: View {view_ref!s} not found. This is a bug!")
300
+
301
+ if not view.properties:
302
+ continue
303
+ for property_ in view.properties.values():
304
+ if isinstance(property_, ViewCorePropertyRequest):
305
+ referenced_containers.add(property_.container)
306
+
307
+ return referenced_containers
308
+
309
+ @cached_property
310
+ def reverse_to_direct_mapping(
311
+ self,
312
+ ) -> dict[tuple[ViewReference, str], tuple[ViewReference, ContainerDirectReference | ViewDirectReference]]:
313
+ """Get a mapping of reverse direct relations to their corresponding source view and 'through' property."""
314
+
315
+ bidirectional_connections: dict[
316
+ tuple[ViewReference, str], tuple[ViewReference, ContainerDirectReference | ViewDirectReference]
317
+ ] = {}
318
+
319
+ if self.merged_data_model.views:
320
+ for view_ref in self.merged_data_model.views:
321
+ view = self.select_view(view_ref)
322
+
323
+ # This should never happen, if it happens, it's a bug
324
+ if not view:
325
+ raise RuntimeError(f"reverse_to_direct_mapping: View {view_ref!s} not found. This is a bug!")
326
+
327
+ if not view.properties:
328
+ continue
329
+ for prop_ref, property_ in view.properties.items():
330
+ # reverse direct relation
331
+ if isinstance(property_, ReverseDirectRelationProperty):
332
+ bidirectional_connections[(view_ref, prop_ref)] = (
333
+ property_.source,
334
+ property_.through,
335
+ )
336
+
337
+ return bidirectional_connections
338
+
339
+ @property
340
+ def connection_end_node_types(self) -> dict[tuple[ViewReference, str], ViewReference | None]:
341
+ """Get a mapping of view references to their corresponding ViewRequest objects."""
342
+
343
+ connection_end_node_types: dict[tuple[ViewReference, str], ViewReference | None] = {}
344
+
345
+ if self.merged_data_model.views:
346
+ for view_ref in self.merged_data_model.views:
347
+ view = self.select_view(view_ref)
348
+ if not view:
349
+ raise RuntimeError(f"View {view_ref!s} not found. This is a bug!")
350
+
351
+ if not view.properties:
352
+ continue
353
+
354
+ for prop_ref, property_ in view.properties.items():
355
+ # direct relation
356
+ if isinstance(property_, ViewCorePropertyRequest):
357
+ # explicit set of end node type via 'source' which is View reference
358
+ if property_.source:
359
+ connection_end_node_types[(view_ref, prop_ref)] = property_.source
360
+
361
+ # implicit end node type via container property, without actual knowledge of end node type
362
+ elif (
363
+ (
364
+ container := self.select_container(
365
+ property_.container, property_.container_property_identifier
366
+ )
367
+ )
368
+ and (property_.container_property_identifier in container.properties)
369
+ and (
370
+ isinstance(
371
+ container.properties[property_.container_property_identifier].type,
372
+ DirectNodeRelation,
373
+ )
374
+ )
375
+ ):
376
+ connection_end_node_types[(view_ref, prop_ref)] = None
377
+
378
+ # reverse direct relation
379
+ elif isinstance(property_, ReverseDirectRelationProperty) and property_.source:
380
+ connection_end_node_types[(view_ref, prop_ref)] = property_.source
381
+
382
+ # edge property
383
+ elif isinstance(property_, EdgeProperty) and property_.source:
384
+ connection_end_node_types[(view_ref, prop_ref)] = property_.source
385
+
386
+ return connection_end_node_types
387
+
388
+ @cached_property
389
+ def views_by_container(self) -> dict[ContainerReference, set[ViewReference]]:
390
+ """Get a mapping from containers to the views that use them.
391
+
392
+ Includes views from both the merged schema and all CDF views to capture
393
+ container-view relationships across the entire CDF environment.
394
+ Uses expanded views to include inherited properties.
395
+ """
396
+
397
+ # Include all unique views from merged and CDF
398
+ views_by_container: dict[ContainerReference, set[ViewReference]] = defaultdict(set)
399
+
400
+ # Include all unique views from merged and CDF
401
+ all_view_refs = set(self.merged.views.keys()) | set(self.cdf.views.keys())
402
+
403
+ for view_ref in all_view_refs:
404
+ # Use expanded view to include inherited properties
405
+ view = self.expand_view_properties(view_ref)
406
+ if not view:
407
+ continue
408
+
409
+ for container in view.used_containers:
410
+ views_by_container[container].add(view_ref)
411
+
412
+ return dict(views_by_container)
413
+
414
+ @cached_property
415
+ def containers_by_view(self) -> dict[ViewReference, set[ContainerReference]]:
416
+ """Get a mapping from views to the containers they use.
417
+
418
+ Includes views from both the merged schema and all CDF views.
419
+ Uses expanded views to include inherited properties.
420
+ """
421
+ containers_by_view: dict[ViewReference, set[ContainerReference]] = {}
422
+
423
+ # Include all unique views from merged and CDF
424
+ all_view_refs = set(self.merged.views.keys()) | set(self.cdf.views.keys())
425
+
426
+ for view_ref in all_view_refs:
427
+ # Use expanded view to include inherited properties
428
+ view = self.expand_view_properties(view_ref)
429
+ if view is not None:
430
+ containers_by_view[view_ref] = view.used_containers
431
+
432
+ return containers_by_view
433
+
434
+ def find_views_mapping_to_containers(self, containers: list[ContainerReference]) -> set[ViewReference]:
435
+ """Find views that map to all specified containers.
436
+
437
+ That is, the intersection of views that use each of the specified containers.
438
+
439
+ Args:
440
+ containers: List of containers to check
441
+
442
+ Returns:
443
+ Set of views that contain all the specified containers
444
+
445
+ Example:
446
+ Given views V1, V2, V3 and containers C1, C2:
447
+ - V1 uses containers {C1, C2}
448
+ - V2 uses containers {C1}
449
+ - V3 uses containers {C2}
450
+
451
+ find_views_mapping_to_containers([C1, C2]) returns {V1}
452
+ find_views_mapping_to_containers([C1]) returns {V1, V2}
453
+ find_views_mapping_to_containers([C2]) returns {V1, V3}
454
+ """
455
+ if not containers:
456
+ return set()
457
+
458
+ view_sets = [self.views_by_container.get(c, set()) for c in containers]
459
+ return set.intersection(*view_sets)
460
+
461
+ @cached_property
462
+ def implements_graph(self) -> nx.DiGraph:
463
+ """Build a weighted directed graph of view implements.
464
+
465
+ Nodes are ViewReferences, edges represent implements.
466
+ An edge A → B means view A implements view B. Order of views in implements is used to set weight of an edge.
467
+
468
+ Includes views from both merged schema and CDF
469
+ """
470
+ graph: nx.DiGraph = nx.DiGraph()
471
+
472
+ for view_ref in self.cdf.views:
473
+ graph.add_node(view_ref)
474
+ for view_ref in self.merged.views:
475
+ graph.add_node(view_ref)
476
+
477
+ # Add edges for implements
478
+ for view_ref in graph.nodes():
479
+ view = self.select_view(view_ref)
480
+ if not view or not view.implements:
481
+ continue
482
+
483
+ # Adding weight to preserve order of implements
484
+ for i, implement in enumerate(view.implements):
485
+ graph.add_edge(view_ref, implement, weight=i + 1)
486
+
487
+ return graph
488
+
489
+ @cached_property
490
+ def implements_cycles(self) -> list[list[ViewReference]]:
491
+ """Find all cycles in the implements graph.
492
+ Returns:
493
+ List of lists, where each list contains the ordered Views involved in forming the implements cycle.
494
+ """
495
+
496
+ return self.graph_cycles(self.implements_graph)
497
+
498
+ @cached_property
499
+ def requires_constraint_graph(self) -> nx.DiGraph:
500
+ """Build a directed graph of container requires constraints.
501
+
502
+ Nodes are ContainerReferences, edges represent requires constraints.
503
+ An edge A → B means container A requires container B.
504
+
505
+ Includes containers from both merged schema and CDF
506
+ """
507
+ graph: nx.DiGraph = nx.DiGraph()
508
+
509
+ for container_ref in self.cdf.containers:
510
+ graph.add_node(container_ref)
511
+ for container_ref in self.merged.containers:
512
+ graph.add_node(container_ref)
513
+
514
+ # Add edges for requires constraints from all known containers
515
+ for container_ref in graph.nodes():
516
+ container = self.select_container(container_ref)
517
+ if not container or not container.constraints:
518
+ continue
519
+ for constraint in container.constraints.values():
520
+ if not isinstance(constraint, RequiresConstraintDefinition):
521
+ continue
522
+ graph.add_edge(container_ref, constraint.require)
523
+
524
+ return graph
525
+
526
+ @staticmethod
527
+ def forms_directed_path(nodes: set[_NodeT], graph: nx.DiGraph) -> bool:
528
+ """Check if nodes form an uninterrupted directed path in the graph.
529
+
530
+ Returns True if there exists a node that can reach all other nodes via
531
+ directed edges in the graph.
532
+
533
+ Args:
534
+ nodes: Set of nodes to check
535
+ graph: Directed graph containing the nodes
536
+
537
+ Returns:
538
+ True if nodes form a directed path (one node reaches all others)
539
+
540
+ Example:
541
+ Given nodes N1, N2, N3 with edges:
542
+ - N1 -> N2
543
+ - N2 -> N3
544
+
545
+ forms_directed_path({N1, N2, N3}) returns True (N1 reaches all others)
546
+ forms_directed_path({N2, N3}) returns True (N2 reaches N3)
547
+ forms_directed_path({N1, N3}) returns False (N1 can't reach N3 without N2)
548
+ """
549
+ if len(nodes) <= 1:
550
+ return True
551
+
552
+ for candidate in nodes:
553
+ others = nodes - {candidate}
554
+ if others.issubset(nx.descendants(graph, candidate)):
555
+ return True
556
+
557
+ return False
558
+
559
+ @cached_property
560
+ def requires_constraint_cycles(self) -> list[list[ContainerReference]]:
561
+ """Find all cycles in the requires constraint graph.
562
+ Returns:
563
+ List of lists, where each list contains the ordered containers involved in forming the requires cycle.
564
+ """
565
+
566
+ return self.graph_cycles(self.requires_constraint_graph)
567
+
568
+ @staticmethod
569
+ def graph_cycles(graph: nx.DiGraph) -> list[list[T_Reference]]:
570
+ """Returns cycles in the graph otherwise empty list"""
571
+ return [candidate for candidate in nx.simple_cycles(graph) if len(candidate) > 1]
@@ -0,0 +1,74 @@
1
+ from ._identifiers import NameSpace
2
+
3
+ XML_SCHEMA_NAMESPACE = NameSpace("http://www.w3.org/2001/XMLSchema#")
4
+
5
+ CDF_CDM_SPACE = "cdf_cdm"
6
+ CDF_CDM_VERSION = "v1"
7
+
8
+ COGNITE_CONCEPTS_MAIN = (
9
+ "CogniteAsset",
10
+ "CogniteEquipment",
11
+ "CogniteActivity",
12
+ "CogniteTimeSeries",
13
+ "CogniteFile",
14
+ )
15
+
16
+ COGNITE_CONCEPTS_INTERFACES = (
17
+ "CogniteDescribable",
18
+ "CogniteSourceable",
19
+ "CogniteSchedulable",
20
+ "CogniteVisualizable",
21
+ )
22
+
23
+ COGNITE_CONCEPTS_CONFIGURATIONS = (
24
+ "CogniteSourceSystem",
25
+ "CogniteUnit",
26
+ "CogniteAssetClass",
27
+ "CogniteAssetType",
28
+ "CogniteEquipmentType",
29
+ "CogniteFileCategory",
30
+ )
31
+ COGNITE_CONCEPTS_ANNOTATIONS = (
32
+ "CogniteAnnotation",
33
+ "CogniteDiagramAnnotation",
34
+ )
35
+ COGNITE_CONCEPTS_3D = (
36
+ "CogniteCubeMap",
37
+ "CogniteCADRevision",
38
+ "CognitePointCloudVolume",
39
+ "Cognite360ImageAnnotation",
40
+ "Cognite3DObject",
41
+ "Cognite3DRevision",
42
+ "Cognite360Image",
43
+ "Cognite360ImageCollection",
44
+ "Cognite360ImageStation",
45
+ "CognitePointCloudModel",
46
+ "Cognite3DTransformation",
47
+ "Cognite360ImageModel",
48
+ "Cognite3DModel",
49
+ "CogniteCADModel",
50
+ "CognitePointCloudRevision",
51
+ "CogniteCADNode",
52
+ )
53
+
54
+ COGNITE_CONCEPTS: tuple[str, ...] = (
55
+ *COGNITE_CONCEPTS_MAIN,
56
+ *COGNITE_CONCEPTS_INTERFACES,
57
+ *COGNITE_CONCEPTS_CONFIGURATIONS,
58
+ *COGNITE_CONCEPTS_ANNOTATIONS,
59
+ *COGNITE_CONCEPTS_3D,
60
+ )
61
+
62
+ COGNITE_SPACES = (
63
+ CDF_CDM_SPACE,
64
+ "cdf_360_image_schema",
65
+ "cdf_3d_schema",
66
+ "cdf_apm",
67
+ "cdf_apps_shared",
68
+ "cdf_cdm_3d",
69
+ )
70
+
71
+ # Defaults from https://docs.cognite.com/cdf/dm/dm_reference/dm_limits_and_restrictions#list-size-limits
72
+
73
+ DEFAULT_MAX_LIST_SIZE = 1000
74
+ DEFAULT_MAX_LIST_SIZE_DIRECT_RELATIONS = 100