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,235 @@
1
+ from abc import ABC
2
+ from typing import Annotated, Any, Literal
3
+
4
+ from pydantic import Field, Json, TypeAdapter, field_serializer
5
+ from pydantic_core.core_schema import FieldSerializationInfo
6
+
7
+ from cognite.neat._utils.useful_types import BaseModelObject
8
+
9
+ from ._base import Resource, WriteableResource
10
+ from ._constants import CONTAINER_AND_VIEW_PROPERTIES_IDENTIFIER_PATTERN
11
+ from ._data_types import DataType
12
+ from ._references import ContainerDirectReference, ContainerReference, NodeReference, ViewDirectReference, ViewReference
13
+
14
+
15
+ class ViewPropertyDefinition(Resource, ABC):
16
+ connection_type: str
17
+
18
+
19
+ class ViewCoreProperty(ViewPropertyDefinition, ABC):
20
+ # Core properties do not have connection type in the API, but we add it here such that
21
+ # we can use it as a discriminator in unions. The exclude=True ensures that it is not
22
+ # sent to the API.
23
+ connection_type: Literal["primary_property"] = Field(default="primary_property", exclude=True)
24
+ name: str | None = Field(
25
+ default=None,
26
+ description="Readable property name.",
27
+ max_length=255,
28
+ )
29
+ description: str | None = Field(
30
+ default=None,
31
+ description="Description of the content and suggested use for this property..",
32
+ max_length=1024,
33
+ )
34
+ container: ContainerReference = Field(
35
+ description="Reference to the container where this property is defined.",
36
+ )
37
+ container_property_identifier: str = Field(
38
+ description="Identifier of the property in the container.",
39
+ min_length=1,
40
+ max_length=255,
41
+ pattern=CONTAINER_AND_VIEW_PROPERTIES_IDENTIFIER_PATTERN,
42
+ )
43
+
44
+ @field_serializer("container", mode="plain")
45
+ @classmethod
46
+ def serialize_container(cls, container: ContainerReference, info: FieldSerializationInfo) -> dict[str, Any]:
47
+ output = container.model_dump(**vars(info))
48
+ output["type"] = "container"
49
+ return output
50
+
51
+
52
+ class ViewCorePropertyRequest(ViewCoreProperty):
53
+ source: ViewReference | None = Field(
54
+ default=None,
55
+ description="Indicates on what type a referenced direct relation is expected to be. "
56
+ "Only applicable for direct relation properties.",
57
+ )
58
+
59
+ @field_serializer("source", mode="plain")
60
+ @classmethod
61
+ def serialize_source(cls, source: ViewReference | None, info: FieldSerializationInfo) -> dict[str, Any] | None:
62
+ if source is None:
63
+ return None
64
+ output = source.model_dump(**vars(info))
65
+ output["type"] = "view"
66
+ return output
67
+
68
+
69
+ class ConstraintOrIndexState(BaseModelObject):
70
+ nullability: Literal["current", "pending", "failed"] | None = Field(
71
+ None,
72
+ description="""For properties that have isNullable set to false, this field describes the validity of the
73
+ not-null constraint. It is not specified for nullable properties.
74
+
75
+ Possible values are:
76
+
77
+ "failed": The property contains null values, violating the constraint. This can occur if a property with
78
+ existing nulls was made non-nullable. New null values will still be rejected.
79
+ "current": The constraint is satisfied; all values in the property are not null.
80
+ "pending": The constraint validity has not yet been computed.
81
+ """,
82
+ )
83
+
84
+
85
+ class ViewCorePropertyResponse(ViewCoreProperty, WriteableResource[ViewCorePropertyRequest]):
86
+ immutable: bool | None = Field(
87
+ default=None,
88
+ description="Should updates to this property be rejected after the initial population?",
89
+ )
90
+ nullable: bool | None = Field(
91
+ default=None,
92
+ description="Does this property need to be set to a value, or not?",
93
+ )
94
+ auto_increment: bool | None = Field(
95
+ default=None,
96
+ description="Increment the property based on its highest current value (max value).",
97
+ )
98
+ default_value: str | int | bool | dict[str, Json] | None = Field(
99
+ default=None,
100
+ description="Default value to use when you do not specify a value for the property.",
101
+ )
102
+ constraint_state: ConstraintOrIndexState = Field(
103
+ description="Describes the validity of constraints defined on this property"
104
+ )
105
+ type: DataType = Field(description="The type of data you can store in this property.")
106
+
107
+ def as_request(self) -> ViewCorePropertyRequest:
108
+ return ViewCorePropertyRequest.model_validate(self.model_dump(by_alias=True))
109
+
110
+
111
+ class ConnectionPropertyDefinition(ViewPropertyDefinition, ABC):
112
+ name: str | None = Field(
113
+ default=None,
114
+ description="Readable property name.",
115
+ max_length=255,
116
+ )
117
+ description: str | None = Field(
118
+ default=None,
119
+ description="Description of the content and suggested use for this property..",
120
+ max_length=1024,
121
+ )
122
+
123
+
124
+ class EdgeProperty(ConnectionPropertyDefinition, ABC):
125
+ source: ViewReference = Field(
126
+ description="The target node(s) of this connection can be read through the view specified in 'source'."
127
+ )
128
+ type: NodeReference = Field(
129
+ description="Reference to the node pointed to by the direct relation. The reference consists of a "
130
+ "space and an external-id."
131
+ )
132
+ edge_source: ViewReference | None = Field(
133
+ None, description="The edge(s) of this connection can be read through the view specified in 'edgeSource'."
134
+ )
135
+ direction: Literal["outwards", "inwards"] = Field(
136
+ "outwards", description="The direction of the edge(s) of this connection."
137
+ )
138
+
139
+ @field_serializer("source", "edge_source", mode="plain")
140
+ @classmethod
141
+ def serialize_source(cls, source: ViewReference | None, info: FieldSerializationInfo) -> dict[str, Any] | None:
142
+ if source is None:
143
+ return None
144
+ output = source.model_dump(**vars(info))
145
+ output["type"] = "view"
146
+ return output
147
+
148
+
149
+ class SingleEdgeProperty(EdgeProperty):
150
+ connection_type: Literal["single_edge_connection"] = "single_edge_connection"
151
+
152
+
153
+ class MultiEdgeProperty(EdgeProperty):
154
+ connection_type: Literal["multi_edge_connection"] = "multi_edge_connection"
155
+
156
+
157
+ class ReverseDirectRelationProperty(ConnectionPropertyDefinition, ABC):
158
+ source: ViewReference = Field(
159
+ description="The node(s) containing the direct relation property can be read "
160
+ "through the view specified in 'source'."
161
+ )
162
+ through: ContainerDirectReference | ViewDirectReference = Field(
163
+ description="The view of the node containing the direct relation property."
164
+ )
165
+
166
+ @field_serializer("source", mode="plain")
167
+ @classmethod
168
+ def serialize_source(cls, source: ViewReference, info: FieldSerializationInfo) -> dict[str, Any] | None:
169
+ output = source.model_dump(**vars(info))
170
+ output["type"] = "view"
171
+ return output
172
+
173
+ @field_serializer("through", mode="plain")
174
+ @classmethod
175
+ def serialize_through(
176
+ cls, through: ContainerDirectReference | ViewDirectReference, info: FieldSerializationInfo
177
+ ) -> dict[str, Any]:
178
+ output = through.model_dump(**vars(info))
179
+ if isinstance(through, ContainerDirectReference):
180
+ output["source"]["type"] = "container"
181
+ else:
182
+ output["source"]["type"] = "view"
183
+ return output
184
+
185
+
186
+ class SingleReverseDirectRelationPropertyRequest(ReverseDirectRelationProperty):
187
+ connection_type: Literal["single_reverse_direct_relation"] = "single_reverse_direct_relation"
188
+
189
+
190
+ class MultiReverseDirectRelationPropertyRequest(ReverseDirectRelationProperty):
191
+ connection_type: Literal["multi_reverse_direct_relation"] = "multi_reverse_direct_relation"
192
+
193
+
194
+ class SingleReverseDirectRelationPropertyResponse(
195
+ ReverseDirectRelationProperty, WriteableResource[SingleReverseDirectRelationPropertyRequest]
196
+ ):
197
+ connection_type: Literal["single_reverse_direct_relation"] = "single_reverse_direct_relation"
198
+ targets_list: bool = Field(
199
+ description="Whether or not this reverse direct relation targets a list of direct relations.",
200
+ )
201
+
202
+ def as_request(self) -> SingleReverseDirectRelationPropertyRequest:
203
+ return SingleReverseDirectRelationPropertyRequest.model_validate(self.model_dump(by_alias=True))
204
+
205
+
206
+ class MultiReverseDirectRelationPropertyResponse(
207
+ ReverseDirectRelationProperty, WriteableResource[MultiReverseDirectRelationPropertyRequest]
208
+ ):
209
+ connection_type: Literal["multi_reverse_direct_relation"] = "multi_reverse_direct_relation"
210
+ targets_list: bool = Field(
211
+ description="Whether or not this reverse direct relation targets a list of direct relations.",
212
+ )
213
+
214
+ def as_request(self) -> MultiReverseDirectRelationPropertyRequest:
215
+ return MultiReverseDirectRelationPropertyRequest.model_validate(self.model_dump(by_alias=True))
216
+
217
+
218
+ ViewRequestProperty = Annotated[
219
+ SingleEdgeProperty
220
+ | MultiEdgeProperty
221
+ | SingleReverseDirectRelationPropertyRequest
222
+ | MultiReverseDirectRelationPropertyRequest
223
+ | ViewCorePropertyRequest,
224
+ Field(discriminator="connection_type"),
225
+ ]
226
+ ViewResponseProperty = Annotated[
227
+ SingleEdgeProperty
228
+ | MultiEdgeProperty
229
+ | SingleReverseDirectRelationPropertyResponse
230
+ | MultiReverseDirectRelationPropertyResponse
231
+ | ViewCorePropertyResponse,
232
+ Field(discriminator="connection_type"),
233
+ ]
234
+
235
+ ViewRequestPropertyAdapter: TypeAdapter[ViewRequestProperty] = TypeAdapter(ViewRequestProperty)
@@ -0,0 +1,216 @@
1
+ import re
2
+ from abc import ABC
3
+ from typing import Any, Literal, TypeVar
4
+
5
+ from pydantic import Field, field_serializer, field_validator, model_validator
6
+ from pydantic_core.core_schema import FieldSerializationInfo
7
+
8
+ from cognite.neat._utils.text import humanize_collection
9
+
10
+ from . import DirectNodeRelation
11
+ from ._base import APIResource, Resource, WriteableResource
12
+ from ._constants import (
13
+ CONTAINER_AND_VIEW_PROPERTIES_IDENTIFIER_PATTERN,
14
+ DM_EXTERNAL_ID_PATTERN,
15
+ DM_VERSION_PATTERN,
16
+ FORBIDDEN_CONTAINER_AND_VIEW_EXTERNAL_IDS,
17
+ FORBIDDEN_CONTAINER_AND_VIEW_PROPERTIES_IDENTIFIER,
18
+ SPACE_FORMAT_PATTERN,
19
+ )
20
+ from ._references import ContainerReference, NodeReference, ViewReference
21
+ from ._view_filter import Filter
22
+ from ._view_property import (
23
+ EdgeProperty,
24
+ ViewCorePropertyRequest,
25
+ ViewCorePropertyResponse,
26
+ ViewRequestProperty,
27
+ ViewResponseProperty,
28
+ )
29
+
30
+ KEY_PATTERN = re.compile(CONTAINER_AND_VIEW_PROPERTIES_IDENTIFIER_PATTERN)
31
+
32
+
33
+ class View(Resource, APIResource[ViewReference], ABC):
34
+ space: str = Field(
35
+ description="Id of the space that the view belongs to.",
36
+ min_length=1,
37
+ max_length=43,
38
+ pattern=SPACE_FORMAT_PATTERN,
39
+ )
40
+ external_id: str = Field(
41
+ description="External-id of the view.",
42
+ min_length=1,
43
+ max_length=255,
44
+ pattern=DM_EXTERNAL_ID_PATTERN,
45
+ )
46
+ version: str = Field(
47
+ description="Version of the view.",
48
+ max_length=43,
49
+ pattern=DM_VERSION_PATTERN,
50
+ )
51
+ name: str | None = Field(
52
+ default=None,
53
+ description="name for the view.",
54
+ max_length=255,
55
+ )
56
+ description: str | None = Field(
57
+ default=None,
58
+ description="Description of the view.",
59
+ max_length=1024,
60
+ )
61
+ filter: Filter | None = Field(
62
+ default=None,
63
+ description="A filter Domain Specific Language (DSL) used to select which instances the view should include.",
64
+ )
65
+ implements: list[ViewReference] | None = Field(
66
+ default=None,
67
+ description="References to the views from where this view will inherit properties.",
68
+ )
69
+
70
+ def as_reference(self) -> ViewReference:
71
+ return ViewReference(space=self.space, external_id=self.external_id, version=self.version)
72
+
73
+ @model_validator(mode="before")
74
+ def set_connection_type_on_primary_properties(cls, data: dict) -> dict:
75
+ if "properties" not in data:
76
+ return data
77
+ properties = data["properties"]
78
+ if not isinstance(properties, dict):
79
+ return data
80
+ # We assume all properties without connectionType are core properties.
81
+ # The reason we set connectionType it easy for pydantic to discriminate the union.
82
+ # This also leads to better error messages, as if there is a union and pydantic do not know which
83
+ # type to pick it will give errors from all type in the union.
84
+ new_properties: dict[str, Any] = {}
85
+ for prop_id, prop in properties.items():
86
+ if isinstance(prop, dict) and "connectionType" not in prop:
87
+ prop_copy = prop.copy()
88
+ prop_copy["connectionType"] = "primary_property"
89
+ new_properties[prop_id] = prop_copy
90
+ else:
91
+ new_properties[prop_id] = prop
92
+ if new_properties:
93
+ new_data = data.copy()
94
+ new_data["properties"] = new_properties
95
+ return new_data
96
+
97
+ return data
98
+
99
+ @field_validator("external_id", mode="after")
100
+ def check_forbidden_external_id_value(cls, val: str) -> str:
101
+ """Check the external_id not present in forbidden set"""
102
+ if val in FORBIDDEN_CONTAINER_AND_VIEW_EXTERNAL_IDS:
103
+ raise ValueError(
104
+ f"'{val}' is a reserved view External ID. Reserved External IDs are: "
105
+ f"{humanize_collection(FORBIDDEN_CONTAINER_AND_VIEW_EXTERNAL_IDS)}"
106
+ )
107
+ return val
108
+
109
+ @field_serializer("implements", mode="plain")
110
+ @classmethod
111
+ def serialize_implements(
112
+ cls, implements: list[ViewReference] | None, info: FieldSerializationInfo
113
+ ) -> list[dict[str, Any]] | None:
114
+ if implements is None:
115
+ return None
116
+ output: list[dict[str, Any]] = []
117
+ for view in implements:
118
+ dumped = view.model_dump(**vars(info))
119
+ dumped["type"] = "view"
120
+ output.append(dumped)
121
+ return output
122
+
123
+
124
+ class ViewRequest(View):
125
+ properties: dict[str, ViewRequestProperty] = Field(
126
+ description="View with included properties and expected edges, indexed by a unique space-local identifier."
127
+ )
128
+
129
+ @field_validator("properties", mode="after")
130
+ def validate_properties_identifier(cls, val: dict[str, ViewRequestProperty]) -> dict[str, ViewRequestProperty]:
131
+ """Validate properties Identifier"""
132
+ return _validate_properties_keys(val)
133
+
134
+ @property
135
+ def used_containers(self) -> set[ContainerReference]:
136
+ """Get all containers referenced by this view."""
137
+ return {prop.container for prop in self.properties.values() if isinstance(prop, ViewCorePropertyRequest)}
138
+
139
+
140
+ class ViewResponse(View, WriteableResource[ViewRequest]):
141
+ properties: dict[str, ViewResponseProperty] = Field(
142
+ description="List of properties and connections included in this view."
143
+ )
144
+
145
+ created_time: int = Field(
146
+ description="When the view was created. The number of milliseconds since 00:00:00 Thursday, 1 January 1970, "
147
+ "Coordinated Universal Time (UTC), minus leap seconds."
148
+ )
149
+ last_updated_time: int = Field(
150
+ description="When the view was last updated. The number of milliseconds since 00:00:00 Thursday, "
151
+ "1 January 1970, Coordinated Universal Time (UTC), minus leap seconds."
152
+ )
153
+ writable: bool = Field(
154
+ description="oes the view support write operations, i.e. is it writable? "
155
+ "You can write to a view if the view maps all non-nullable properties."
156
+ )
157
+ queryable: bool = Field(
158
+ description="Does the view support queries, i.e. is it queryable? You can query a view if "
159
+ "it either has a filter or at least one property mapped to a container."
160
+ )
161
+ used_for: Literal["node", "edge", "all"] = Field(description="Should this operation apply to nodes, edges or both.")
162
+ is_global: bool = Field(description="Is this a global view.")
163
+ mapped_containers: list[ContainerReference] = Field(
164
+ description="List of containers with properties mapped by this view."
165
+ )
166
+
167
+ @field_validator("properties", mode="after")
168
+ def validate_properties_identifier(cls, val: dict[str, ViewResponseProperty]) -> dict[str, ViewResponseProperty]:
169
+ """Validate properties Identifier"""
170
+ return _validate_properties_keys(val)
171
+
172
+ @property
173
+ def node_types(self) -> list[NodeReference]:
174
+ """Get all node types referenced by this view."""
175
+ nodes_refs: set[NodeReference] = set()
176
+ for prop in self.properties.values():
177
+ if isinstance(prop, EdgeProperty):
178
+ nodes_refs.add(prop.type)
179
+ return list(nodes_refs)
180
+
181
+ def as_request(self) -> ViewRequest:
182
+ dumped = self.model_dump(by_alias=True, exclude={"properties"})
183
+ properties: dict[str, Any] = {}
184
+ for key, value in self.properties.items():
185
+ if isinstance(value, ViewCorePropertyResponse) and isinstance(value.type, DirectNodeRelation):
186
+ # Special case. In the request the source of DirectNodeRelation is set on the Property object,
187
+ # while in the response it is set on the DirectNodeRelation object.
188
+ request_object = value.as_request().model_dump(by_alias=True)
189
+ request_object["source"] = value.type.source.model_dump(by_alias=True) if value.type.source else None
190
+ properties[key] = request_object
191
+ elif isinstance(value, WriteableResource):
192
+ properties[key] = value.as_request().model_dump(by_alias=True)
193
+ else:
194
+ properties[key] = value.model_dump(by_alias=True)
195
+
196
+ dumped["properties"] = properties
197
+ return ViewRequest.model_validate(dumped)
198
+
199
+
200
+ T_Property = TypeVar("T_Property")
201
+
202
+
203
+ def _validate_properties_keys(properties: dict[str, T_Property]) -> dict[str, T_Property]:
204
+ """Validate keys of a properties dictionary."""
205
+ errors: list[str] = []
206
+ for key in properties:
207
+ if not KEY_PATTERN.match(key):
208
+ errors.append(f"Property '{key}' does not match the required pattern: {KEY_PATTERN.pattern}")
209
+ if key in FORBIDDEN_CONTAINER_AND_VIEW_PROPERTIES_IDENTIFIER:
210
+ errors.append(
211
+ f"'{key}' is a reserved property identifier. Reserved identifiers are: "
212
+ f"{humanize_collection(FORBIDDEN_CONTAINER_AND_VIEW_PROPERTIES_IDENTIFIER)}"
213
+ )
214
+ if errors:
215
+ raise ValueError("; ".join(errors))
216
+ return properties
@@ -0,0 +1,50 @@
1
+ from ._base import ConceptEntity, UnknownEntity
2
+ from ._constants import Undefined, Unknown
3
+ from ._data_types import (
4
+ AnyURI,
5
+ Boolean,
6
+ DataType,
7
+ Date,
8
+ DateTime,
9
+ DateTimeStamp,
10
+ Double,
11
+ Enum,
12
+ File,
13
+ Float,
14
+ Integer,
15
+ Json,
16
+ Long,
17
+ Sequence,
18
+ String,
19
+ Timeseries,
20
+ )
21
+ from ._identifiers import URI, NameSpace
22
+ from ._parser import ParsedEntity, parse_entities, parse_entity
23
+
24
+ __all__ = [
25
+ "URI",
26
+ "AnyURI",
27
+ "Boolean",
28
+ "ConceptEntity",
29
+ "DataType",
30
+ "Date",
31
+ "DateTime",
32
+ "DateTimeStamp",
33
+ "Double",
34
+ "Enum",
35
+ "File",
36
+ "Float",
37
+ "Integer",
38
+ "Json",
39
+ "Long",
40
+ "NameSpace",
41
+ "ParsedEntity",
42
+ "Sequence",
43
+ "String",
44
+ "Timeseries",
45
+ "Undefined",
46
+ "Unknown",
47
+ "UnknownEntity",
48
+ "parse_entities",
49
+ "parse_entity",
50
+ ]
@@ -0,0 +1,101 @@
1
+ from functools import total_ordering
2
+ from typing import Any
3
+
4
+ from pydantic import BaseModel, Field, field_validator, model_serializer
5
+
6
+ from ._constants import (
7
+ PREFIX_PATTERN,
8
+ SUFFIX_PATTERN,
9
+ VERSION_PATTERN,
10
+ Undefined,
11
+ Unknown,
12
+ _UndefinedType,
13
+ _UnknownType,
14
+ )
15
+
16
+
17
+ @total_ordering
18
+ class Entity(BaseModel, extra="ignore", populate_by_name=True):
19
+ """Entity is a concept, class, property, datatype in semantics sense."""
20
+
21
+ prefix: str | _UndefinedType = Field(default=Undefined, pattern=PREFIX_PATTERN, min_length=1, max_length=43)
22
+ suffix: str = Field(min_length=1, max_length=255, pattern=SUFFIX_PATTERN)
23
+
24
+ @model_serializer(when_used="unless-none", return_type=str)
25
+ def as_str(self) -> str:
26
+ return str(self)
27
+
28
+ @field_validator("*", mode="before")
29
+ def strip_string(cls, value: Any) -> Any:
30
+ if isinstance(value, str):
31
+ return value.strip()
32
+ elif isinstance(value, list):
33
+ return [entry.strip() if isinstance(entry, str) else entry for entry in value]
34
+ return value
35
+
36
+ def as_tuple(self) -> tuple[str, ...]:
37
+ # We haver overwritten the serialization to str, so we need to do it manually
38
+ extra: tuple[str, ...] = tuple(
39
+ [
40
+ str(v or "")
41
+ for field_name in self.model_fields.keys()
42
+ if (v := getattr(self, field_name)) and field_name not in {"prefix", "suffix"}
43
+ ]
44
+ )
45
+ if isinstance(self.prefix, _UndefinedType):
46
+ return str(self.suffix), *extra
47
+ else:
48
+ return self.prefix, str(self.suffix), *extra
49
+
50
+ def __lt__(self, other: object) -> bool:
51
+ if type(other) is not type(self):
52
+ return NotImplemented
53
+ return self.as_tuple() < other.as_tuple() # type: ignore[attr-defined]
54
+
55
+ def __eq__(self, other: object) -> bool:
56
+ # We need to be explicit that we are not allowing comparison between different types
57
+ if type(other) is not type(self):
58
+ # requires explicit raising as NotImplemented would lead to running comparison
59
+ raise TypeError(f"'==' not supported between instances of {type(self).__name__} and {type(other).__name__}")
60
+ return self.as_tuple() == other.as_tuple() # type: ignore[attr-defined]
61
+
62
+ def __hash__(self) -> int:
63
+ return hash(f"{type(self).__name__}({self})")
64
+
65
+ def __str__(self) -> str:
66
+ # there are three cases for string representation:
67
+ # 1. only suffix is present -> return str(suffix)
68
+ # 2. prefix and suffix are present -> return "prefix:suffix"
69
+ # 3. prefix, suffix and other fields are present -> return "prefix:suffix(field1=value1,field2=value2)"
70
+
71
+ model_dump = {k: v for k in self.model_fields if (v := getattr(self, k)) is not None}
72
+
73
+ base_str = f"{self.prefix}:{self.suffix}" if not isinstance(self.prefix, _UndefinedType) else str(self.suffix)
74
+
75
+ extra_fields = {
76
+ (self.model_fields[k].alias or k): v for k, v in model_dump.items() if k not in {"prefix", "suffix"}
77
+ }
78
+ if extra_fields:
79
+ extra_str = ",".join([f"{k}={v}" for k, v in extra_fields.items()])
80
+ return f"{base_str}({extra_str})"
81
+ else:
82
+ return base_str
83
+
84
+ def __repr__(self) -> str:
85
+ # We have overwritten the serialization to str, so we need to do it manually
86
+ model_dump = {k: v for k in self.model_fields if (v := getattr(self, k)) is not None}
87
+ args = ",".join([f"{k}={v!r}" for k, v in model_dump.items()])
88
+ return f"{type(self).__name__}({args})"
89
+
90
+
91
+ class ConceptEntity(Entity):
92
+ version: str | None = Field(default=None, pattern=VERSION_PATTERN, max_length=43)
93
+
94
+
95
+ class UnknownEntity(ConceptEntity):
96
+ prefix: _UndefinedType = Undefined
97
+ suffix: _UnknownType = Unknown # type: ignore[assignment]
98
+
99
+ @property
100
+ def id(self) -> str:
101
+ return str(Unknown)
@@ -0,0 +1,22 @@
1
+ from pydantic import BaseModel
2
+
3
+
4
+ class _UndefinedType(BaseModel): ...
5
+
6
+
7
+ class _UnknownType(BaseModel):
8
+ def __str__(self) -> str:
9
+ return "#N/A"
10
+
11
+ def __hash__(self) -> int:
12
+ return hash(str(self))
13
+
14
+
15
+ # This is a trick to make Undefined and Unknown singletons
16
+ Undefined = _UndefinedType()
17
+ Unknown = _UnknownType()
18
+
19
+
20
+ PREFIX_PATTERN = r"^[a-zA-Z][a-zA-Z0-9_-]{0,41}[a-zA-Z0-9]?$"
21
+ SUFFIX_PATTERN = r"^[a-zA-Z0-9._~?@!$&'*+,;=%-]+$"
22
+ VERSION_PATTERN = r"^[a-zA-Z0-9]([.a-zA-Z0-9_-]{0,41}[a-zA-Z0-9])?$"