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,58 @@
1
+ """Validators checking for consistency issues in data model."""
2
+
3
+ from cognite.neat._data_model._constants import COGNITE_SPACES
4
+ from cognite.neat._data_model.validation.dms._base import DataModelValidator
5
+ from cognite.neat._issues import Recommendation
6
+
7
+ BASE_CODE = "NEAT-DMS-CONSISTENCY"
8
+
9
+
10
+ class ViewSpaceVersionInconsistentWithDataModel(DataModelValidator):
11
+ """Validates that views have consistent space and version with the data model.
12
+
13
+ ## What it does
14
+ Validates that all views in the data model have the same space and version as the data model.
15
+
16
+ ## Why is this bad?
17
+ If views have different space or version than the data model, it may lead to more demanding development and
18
+ maintenance efforts. The industry best practice is to keep views in the same space and version as the data model.
19
+
20
+ ## Example
21
+ If the data model is defined in space "my_space" version "v1", but a view is defined in the same spave but with
22
+ version "v2", this requires additional attention during deployment and maintenance of the data model.
23
+ """
24
+
25
+ code = f"{BASE_CODE}-001"
26
+ issue_type = Recommendation
27
+
28
+ def run(self) -> list[Recommendation]:
29
+ recommendations: list[Recommendation] = []
30
+
31
+ if not self.validation_resources.merged_data_model.views:
32
+ return recommendations
33
+
34
+ space = self.validation_resources.merged_data_model.space
35
+ version = self.validation_resources.merged_data_model.version
36
+
37
+ for view_ref in self.validation_resources.merged_data_model.views:
38
+ issue_description = ""
39
+
40
+ if view_ref.space not in COGNITE_SPACES:
41
+ # notify about inconsistent space
42
+ if view_ref.space != space:
43
+ issue_description = f"space (view: {view_ref.space}, data model: {space})"
44
+
45
+ # or version if spaces are same
46
+ elif view_ref.version != version:
47
+ issue_description = f"version (view: {view_ref.version}, data model: {version})"
48
+
49
+ if issue_description:
50
+ recommendations.append(
51
+ Recommendation(
52
+ message=(f"View {view_ref!s} has inconsistent {issue_description} with the data model."),
53
+ fix="Update view version and/or space to match data model",
54
+ code=self.code,
55
+ )
56
+ )
57
+
58
+ return recommendations
@@ -0,0 +1,199 @@
1
+ """Validators for checking containers in the data model."""
2
+
3
+ from pyparsing import cast
4
+
5
+ from cognite.neat._data_model.models.dms._constraints import Constraint, RequiresConstraintDefinition
6
+ from cognite.neat._data_model.models.dms._view_property import ViewCorePropertyRequest
7
+ from cognite.neat._data_model.validation.dms._base import DataModelValidator
8
+ from cognite.neat._issues import ConsistencyError
9
+
10
+ BASE_CODE = "NEAT-DMS-CONTAINER"
11
+
12
+
13
+ class ExternalContainerDoesNotExist(DataModelValidator):
14
+ """
15
+ Validates that any container referenced by a view property, when the
16
+ referenced container does not belong to the data model's space, exists in CDF.
17
+
18
+ ## What it does
19
+ For each view property that maps to a container in a different space than the data model,
20
+ this validator checks that the referenced external container exists in CDF.
21
+
22
+ ## Why is this bad?
23
+ If a view property references a container that does not exist in CDF,
24
+ the data model cannot be deployed. The affected view property will not function, and the
25
+ deployment of the entire data model will fail.
26
+
27
+ ## Example
28
+ View `my_space:WindTurbine` has a property `location` that maps to container
29
+ `other_space:WindTurbineContainer`, where `other_space` differs from `my_space`. If that
30
+ container does not exist in CDF, the model cannot be deployed.
31
+ """
32
+
33
+ code = f"{BASE_CODE}-001"
34
+ issue_type = ConsistencyError
35
+
36
+ def run(self) -> list[ConsistencyError]:
37
+ errors: list[ConsistencyError] = []
38
+
39
+ if not self.validation_resources.merged_data_model.views:
40
+ return errors
41
+
42
+ for view_ref in self.validation_resources.merged_data_model.views:
43
+ view = self.validation_resources.select_view(view_ref)
44
+
45
+ if not view:
46
+ raise RuntimeError(
47
+ f"{type(self).__name__}: View {view_ref!s} not found in local resources. This is a bug in NEAT."
48
+ )
49
+
50
+ if view.properties is None:
51
+ continue
52
+
53
+ for property_ref, property_ in view.properties.items():
54
+ if not isinstance(property_, ViewCorePropertyRequest):
55
+ continue
56
+
57
+ if property_.container.space == self.validation_resources.merged_data_model.space:
58
+ continue
59
+
60
+ # Check existence of container in CDF
61
+ if property_.container not in self.validation_resources.cdf.containers:
62
+ errors.append(
63
+ ConsistencyError(
64
+ message=(
65
+ f"View {view_ref!s} property {property_ref!s} maps to "
66
+ f"external container {property_.container!s} which does not exist in CDF."
67
+ ),
68
+ fix="Define necessary container in CDF",
69
+ code=self.code,
70
+ )
71
+ )
72
+
73
+ return errors
74
+
75
+
76
+ class ExternalContainerPropertyDoesNotExist(DataModelValidator):
77
+ """
78
+ Validates that any container property referenced by a view property, when the
79
+ referenced container does not belong to the data model's space, exists in CDF.
80
+
81
+ ## What it does
82
+ For each view property that maps to a container in a different space than the data model,
83
+ this validator checks that the referenced container property exists in that external container in CDF.
84
+ This validator only runs if the external container exists in CDF.
85
+
86
+ ## Why is this bad?
87
+ If a view property references a container property that does not exist in CDF,
88
+ the data model cannot be deployed. The affected view property will not function, and the
89
+ deployment of the entire data model will fail.
90
+
91
+ ## Example
92
+ View `my_space:WindTurbine` has a property `location` that maps to container property
93
+ `gpsCoordinates` in `other_space:WindTurbineContainer`. If `gpsCoordinates` does not exist
94
+ in that container in CDF, deployment will fail.
95
+ """
96
+
97
+ code = f"{BASE_CODE}-002"
98
+ issue_type = ConsistencyError
99
+
100
+ def run(self) -> list[ConsistencyError]:
101
+ errors: list[ConsistencyError] = []
102
+
103
+ if self.validation_resources.merged_data_model.views:
104
+ for view_ref in self.validation_resources.merged_data_model.views:
105
+ view = self.validation_resources.select_view(view_ref)
106
+
107
+ if not view:
108
+ raise RuntimeError(
109
+ f"{type(self).__name__}: View {view_ref!s} not found in local resources. This is a bug in NEAT."
110
+ )
111
+
112
+ if view.properties is None:
113
+ continue
114
+
115
+ for property_ref, property_ in view.properties.items():
116
+ if not isinstance(property_, ViewCorePropertyRequest):
117
+ continue
118
+
119
+ if property_.container.space == self.validation_resources.merged_data_model.space:
120
+ continue
121
+
122
+ # Only check property if container exists in CDF
123
+ # this check is done in ExternalContainerDoesNotExist
124
+ if property_.container not in self.validation_resources.cdf.containers:
125
+ continue
126
+
127
+ # Check existence of container property in CDF
128
+ if (
129
+ property_.container_property_identifier
130
+ not in self.validation_resources.cdf.containers[property_.container].properties
131
+ ):
132
+ errors.append(
133
+ ConsistencyError(
134
+ message=(
135
+ f"View {view_ref!s} property {property_ref!s} maps to "
136
+ f"external container {property_.container!s} which does not have "
137
+ f"property '{property_.container_property_identifier}' in CDF."
138
+ ),
139
+ fix="Define necessary container property in CDF",
140
+ code=self.code,
141
+ )
142
+ )
143
+
144
+ return errors
145
+
146
+
147
+ class RequiredContainerDoesNotExist(DataModelValidator):
148
+ """
149
+ Validates that any container required by another container exists in the data model.
150
+
151
+ ## What it does
152
+ For each container in the data model, this validator checks that any container it
153
+ requires (via requires constraints) exists either in the data model or in CDF.
154
+
155
+ ## Why is this bad?
156
+ If a container requires another container that does not exist in the data model or in CDF,
157
+ the data model cannot be deployed. The affected container will not function, and
158
+ the deployment of the entire data model will fail.
159
+
160
+ ## Example
161
+ Container `windy_space:WindTurbineContainer` has a constraint requiring `windy_space:LocationContainer`.
162
+ If `windy_space:LocationContainer` does not exist in the data model or in CDF, deployment will fail.
163
+ """
164
+
165
+ code = f"{BASE_CODE}-003"
166
+ issue_type = ConsistencyError
167
+
168
+ def run(self) -> list[ConsistencyError]:
169
+ errors: list[ConsistencyError] = []
170
+
171
+ for container_ref in self.validation_resources.merged.containers:
172
+ container = self.validation_resources.select_container(container_ref)
173
+
174
+ if not container:
175
+ raise RuntimeError(
176
+ f"{type(self).__name__}: Container {container_ref!s} "
177
+ "not found in local resources. This is a bug in NEAT."
178
+ )
179
+
180
+ if not container.constraints:
181
+ continue
182
+
183
+ for constraint_ref, constraint in cast(dict[str, Constraint], container.constraints).items():
184
+ if not isinstance(constraint, RequiresConstraintDefinition):
185
+ continue
186
+
187
+ if not self.validation_resources.select_container(constraint.require):
188
+ errors.append(
189
+ ConsistencyError(
190
+ message=(
191
+ f"Container '{container_ref!s}' constraint '{constraint_ref}' requires container "
192
+ f"'{constraint.require!s}' which does not exist."
193
+ ),
194
+ fix="Define necessary container in the data model",
195
+ code=self.code,
196
+ )
197
+ )
198
+
199
+ return errors
@@ -0,0 +1,368 @@
1
+ """Validators for checking if defined data model is within CDF DMS schema limits."""
2
+
3
+ from typing import Literal
4
+
5
+ from cognite.neat._data_model.models.dms._container import ContainerRequest
6
+ from cognite.neat._data_model.models.dms._data_types import EnumProperty, ListablePropertyTypeDefinition
7
+ from cognite.neat._data_model.models.dms._indexes import BtreeIndex, InvertedIndex
8
+ from cognite.neat._data_model.models.dms._view_property import (
9
+ ViewCorePropertyRequest,
10
+ )
11
+ from cognite.neat._data_model.validation.dms._base import (
12
+ DataModelValidator,
13
+ )
14
+ from cognite.neat._issues import ConsistencyError
15
+
16
+ BASE_CODE = "NEAT-DMS-LIMITS"
17
+
18
+
19
+ class DataModelViewCountIsOutOfLimits(DataModelValidator):
20
+ """Validates that the data model does not exceed the maximum number of views.
21
+
22
+ ## What it does
23
+ This validator checks that the total number of views referenced by the data model
24
+ does not exceed the limit defined in the CDF project.
25
+
26
+ ## Why is this bad?
27
+ CDF enforces limits on the number of views per data model to ensure optimal performance
28
+ and resource utilization.
29
+
30
+ ## Example
31
+ If the CDF project has a limit of 100 views per data model, and the data model
32
+ references 120 views, this validator will raise a ConsistencyError issue.
33
+
34
+ """
35
+
36
+ code = f"{BASE_CODE}-DATA-MODEL-001"
37
+ issue_type = ConsistencyError
38
+
39
+ def run(self) -> list[ConsistencyError]:
40
+ errors: list[ConsistencyError] = []
41
+
42
+ if self.validation_resources.merged_data_model.views is None:
43
+ errors.append(
44
+ ConsistencyError(
45
+ message="The data model does not have any views. This means it is not a data model.",
46
+ code=self.code,
47
+ )
48
+ )
49
+
50
+ elif (
51
+ len(self.validation_resources.merged_data_model.views) > self.validation_resources.limits.data_models.views
52
+ ):
53
+ errors.append(
54
+ ConsistencyError(
55
+ message=(
56
+ f"The data model references {len(self.validation_resources.merged_data_model.views)} views, "
57
+ "which exceeds the limit of "
58
+ f"{self.validation_resources.limits.data_models.views} views per data model."
59
+ ),
60
+ code=self.code,
61
+ )
62
+ )
63
+ return errors
64
+
65
+
66
+ ### View level limits
67
+
68
+
69
+ class ViewPropertyCountIsOutOfLimits(DataModelValidator):
70
+ """Validates that a view does not exceed the maximum number of properties.
71
+
72
+ ## What it does
73
+ Checks that the view has no more properties than the CDF limit allows.
74
+
75
+ ## Why is this bad?
76
+ CDF enforces limits on the number of properties per view to ensure optimal performance.
77
+
78
+ ## Example
79
+ If a view has 150 properties and the CDF limit is 100 properties per view,
80
+ this validator will raise a ConsistencyError issue.
81
+ """
82
+
83
+ code = f"{BASE_CODE}-VIEW-001"
84
+ issue_type = ConsistencyError
85
+
86
+ def run(self) -> list[ConsistencyError]:
87
+ errors: list[ConsistencyError] = []
88
+
89
+ for view_ref in self.validation_resources.merged_data_model.views or []:
90
+ if not (view := self.validation_resources.expand_view_properties(view_ref)):
91
+ raise RuntimeError(f"{type(self).__name__}: View {view_ref!s} not found. This is a bug in NEAT.")
92
+
93
+ if view.properties and len(view.properties) > self.validation_resources.limits.views.properties:
94
+ errors.append(
95
+ ConsistencyError(
96
+ message=(
97
+ f"View {view_ref!s} has {len(view.properties)} properties,"
98
+ " which exceeds the limit of "
99
+ f"{self.validation_resources.limits.views.properties} properties per view."
100
+ ),
101
+ code=self.code,
102
+ )
103
+ )
104
+
105
+ elif not view.properties:
106
+ errors.append(
107
+ ConsistencyError(
108
+ message=(
109
+ f"View {view_ref!s} does "
110
+ "not have any properties defined, either directly or through implements."
111
+ ),
112
+ fix="Define at least one property for view",
113
+ code=self.code,
114
+ )
115
+ )
116
+
117
+ return errors
118
+
119
+
120
+ class ViewContainerCountIsOutOfLimits(DataModelValidator):
121
+ """Validates that a view does not reference too many containers.
122
+
123
+ ## What it does
124
+ Checks that the view references no more containers than the CDF limit allows.
125
+
126
+ ## Why is this bad?
127
+ CDF enforces limits on the number of containers per view to prevent overly complex view definitions, leading
128
+ to too many joins and performance degradation.
129
+
130
+ ## Example
131
+ If a view references 20 containers and the CDF limit is 10 containers per view,
132
+ this validator will raise a ConsistencyError issue.
133
+ """
134
+
135
+ code = f"{BASE_CODE}-VIEW-002"
136
+ issue_type = ConsistencyError
137
+
138
+ def run(self) -> list[ConsistencyError]:
139
+ errors: list[ConsistencyError] = []
140
+
141
+ # Single loop over all views
142
+ for view_ref in self.validation_resources.merged_data_model.views or []:
143
+ if not (view := self.validation_resources.expand_view_properties(view_ref)):
144
+ raise RuntimeError(f"{type(self).__name__}: View {view_ref!s} not found. This is a bug in NEAT.")
145
+
146
+ if view.properties:
147
+ count = len(
148
+ {
149
+ prop.container
150
+ for prop in view.properties.values()
151
+ if (isinstance(prop, ViewCorePropertyRequest) and prop.container)
152
+ }
153
+ )
154
+ if count > self.validation_resources.limits.views.containers:
155
+ errors.append(
156
+ ConsistencyError(
157
+ message=(
158
+ f"View {view_ref!s} references "
159
+ f"{count} containers, which exceeds the limit of "
160
+ f"{self.validation_resources.limits.views.containers} containers per view."
161
+ ),
162
+ code=self.code,
163
+ )
164
+ )
165
+
166
+ return errors
167
+
168
+
169
+ class ViewImplementsCountIsOutOfLimits(DataModelValidator):
170
+ """Validates that a view does not implement too many other views.
171
+
172
+ ## What it does
173
+ Checks that the view implements no more views than the CDF limit allows.
174
+
175
+ ## Why is this bad?
176
+ CDF enforces limits on the number of implemented views to prevent overly deep inheritance hierarchies.
177
+
178
+ ## Example
179
+ If a view implements 15 other views and the CDF limit is 10 implemented views per view,
180
+ this validator will raise a ConsistencyError issue.
181
+ """
182
+
183
+ code = f"{BASE_CODE}-VIEW-003"
184
+ issue_type = ConsistencyError
185
+
186
+ def run(self) -> list[ConsistencyError]:
187
+ errors: list[ConsistencyError] = []
188
+
189
+ # Single loop over all views
190
+ for view_ref in self.validation_resources.merged_data_model.views or []:
191
+ ancestors = self.validation_resources.view_ancestors(view_ref)
192
+ if ancestors and len(ancestors) > self.validation_resources.limits.views.implements:
193
+ errors.append(
194
+ ConsistencyError(
195
+ message=(
196
+ f"View {view_ref!s} implements {len(ancestors)} views,"
197
+ " which exceeds the limit of"
198
+ f" {self.validation_resources.limits.views.implements} implemented views per view."
199
+ ),
200
+ code=self.code,
201
+ )
202
+ )
203
+ return errors
204
+
205
+
206
+ ### Container level limits
207
+
208
+
209
+ class ContainerPropertyCountIsOutOfLimits(DataModelValidator):
210
+ """Validates that a container does not exceed the maximum number of properties.
211
+
212
+ ## What it does
213
+ Checks that the container has no more properties than the CDF limit allows.
214
+
215
+ ## Why is this bad?
216
+ CDF enforces limits on the number of properties per container to ensure optimal performance
217
+ and prevent PostGres tables that have too many columns.
218
+
219
+ ## Example
220
+ If a container has 150 properties and the CDF limit is 100 properties per container,
221
+ this validator will raise a ConsistencyError issue.
222
+ """
223
+
224
+ code = f"{BASE_CODE}-CONTAINER-001"
225
+ issue_type = ConsistencyError
226
+
227
+ def run(self) -> list[ConsistencyError]:
228
+ errors: list[ConsistencyError] = []
229
+ # Single loop over all containers
230
+ for container_ref in self.validation_resources.merged.containers:
231
+ container = self.validation_resources.select_container(container_ref)
232
+
233
+ if not container:
234
+ raise RuntimeError(
235
+ f"{type(self).__name__}: Container {container_ref!s} "
236
+ "not found in local resources. This is a bug in NEAT."
237
+ )
238
+
239
+ if (
240
+ container.properties
241
+ and len(container.properties) > self.validation_resources.limits.containers.properties()
242
+ ):
243
+ errors.append(
244
+ ConsistencyError(
245
+ message=(
246
+ f"Container {container_ref!s} has {len(container.properties)} properties, "
247
+ "which exceeds the limit of "
248
+ f"{self.validation_resources.limits.containers.properties()} properties per container."
249
+ ),
250
+ fix="Define at least one property for container",
251
+ code=self.code,
252
+ )
253
+ )
254
+ elif not container.properties:
255
+ errors.append(
256
+ ConsistencyError(
257
+ message=(f"Container {container_ref!s} does not have any properties defined."),
258
+ fix="Define at least one property for container",
259
+ code=self.code,
260
+ )
261
+ )
262
+
263
+ return errors
264
+
265
+
266
+ class ContainerPropertyListSizeIsOutOfLimits(DataModelValidator):
267
+ """Validates that container property list sizes do not exceed CDF limits.
268
+
269
+ ## What it does
270
+ Checks that list-type properties (max_list_size) do not exceed the appropriate limit based on:
271
+ - Data type (Int32, Int64, DirectRelation, etc.)
272
+ - Presence of btree index
273
+ - Default vs maximum limits
274
+
275
+ ## Why is this bad?
276
+ CDF enforces different list size limits for different data types and indexing configurations
277
+ to ensure optimal performance and prevent resource exhaustion.
278
+
279
+ ## Example
280
+ If a DirectRelation property has max_list_size=2000 with a btree index, but the limit
281
+ is 1000 for indexed DirectRelations, this validator will raise a ConsistencyError issue.
282
+
283
+ ## Note
284
+ Enum properties are skipped as they have a separate 32-value limit checked during read time of data model to neat
285
+ as a SyntaxError check.
286
+ """
287
+
288
+ code = f"{BASE_CODE}-CONTAINER-002"
289
+ issue_type = ConsistencyError
290
+
291
+ def run(self) -> list[ConsistencyError]:
292
+ errors: list[ConsistencyError] = []
293
+
294
+ # Single loop over all containers
295
+ for container_ref in self.validation_resources.merged.containers:
296
+ container = self.validation_resources.select_container(container_ref)
297
+
298
+ if not container:
299
+ raise RuntimeError(
300
+ f"{type(self).__name__}: Container {container_ref!s} "
301
+ "not found in local resources. This is a bug in NEAT."
302
+ )
303
+
304
+ properties_by_index_type = self.container_property_by_index_type(container)
305
+
306
+ for property_id, property_ in container.properties.items():
307
+ type_ = property_.type
308
+
309
+ # Skip enum properties (have separate 32-value limit)
310
+ if isinstance(type_, EnumProperty):
311
+ continue
312
+
313
+ # Only check listable properties with max_list_size set
314
+ if not isinstance(type_, ListablePropertyTypeDefinition) or type_.max_list_size is None:
315
+ continue
316
+
317
+ has_btree_index = property_id in properties_by_index_type[BtreeIndex.model_fields["index_type"].default]
318
+ limit = self.validation_resources.limits.containers.properties.listable(type_, has_btree_index)
319
+
320
+ if type_.max_list_size > limit:
321
+ errors.append(
322
+ ConsistencyError(
323
+ message=(
324
+ f"Container {container_ref!s} has property {property_id} with list size "
325
+ f"{type_.max_list_size}, which exceeds the limit of {limit} "
326
+ f"for data type {type_.__class__.__name__}."
327
+ ),
328
+ code=self.code,
329
+ )
330
+ )
331
+
332
+ return errors
333
+
334
+ @staticmethod
335
+ def container_property_by_index_type(container: ContainerRequest) -> dict[Literal["btree", "inverted"], list]:
336
+ """Map container properties to their index types for limit validation.
337
+
338
+ Categorizes container properties by their index configuration:
339
+ - "btree": Properties with btree indexes (have stricter list size limits)
340
+ - "inverted": Properties with inverted indexes
341
+
342
+ This mapping is used to determine the appropriate list size limit for
343
+ each property based on whether it has a btree index.
344
+
345
+ Args:
346
+ container: The container to analyze.
347
+
348
+ Returns:
349
+ Dictionary with index type strings as keys and lists of property identifiers
350
+ as values. Returns empty lists for both index types if container has no indexes.
351
+ """
352
+
353
+ container_property_by_index_type: dict[Literal["btree", "inverted"], list] = {
354
+ BtreeIndex.model_fields["index_type"].default: [],
355
+ InvertedIndex.model_fields["index_type"].default: [],
356
+ }
357
+ if not container.indexes:
358
+ return container_property_by_index_type
359
+
360
+ for index in container.indexes.values():
361
+ if isinstance(index, BtreeIndex):
362
+ container_property_by_index_type[BtreeIndex.model_fields["index_type"].default].extend(index.properties)
363
+ elif isinstance(index, InvertedIndex):
364
+ container_property_by_index_type[InvertedIndex.model_fields["index_type"].default].extend(
365
+ index.properties
366
+ )
367
+
368
+ return container_property_by_index_type