cognite-neat 0.92.2__py3-none-any.whl → 0.93.0__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.

Potentially problematic release.


This version of cognite-neat might be problematic. Click here for more details.

Files changed (289) hide show
  1. cognite/neat/__init__.py +3 -2
  2. cognite/neat/{app → _app}/api/configuration.py +9 -7
  3. cognite/neat/_app/api/context_manager/__init__.py +3 -0
  4. cognite/neat/{app → _app}/api/context_manager/manager.py +1 -1
  5. cognite/neat/{app → _app}/api/explorer.py +5 -5
  6. cognite/neat/{app → _app}/api/routers/configuration.py +2 -2
  7. cognite/neat/{app → _app}/api/routers/crud.py +4 -4
  8. cognite/neat/{app → _app}/api/routers/workflows.py +7 -7
  9. cognite/neat/{app → _app}/main.py +1 -1
  10. cognite/neat/_app/ui/neat-app/package-lock.json +18306 -0
  11. cognite/neat/_app/ui/neat-app/package.json +62 -0
  12. cognite/neat/_app/ui/neat-app/public/favicon.ico +0 -0
  13. cognite/neat/_app/ui/neat-app/public/img/architect-icon.svg +116 -0
  14. cognite/neat/_app/ui/neat-app/public/img/developer-icon.svg +112 -0
  15. cognite/neat/_app/ui/neat-app/public/img/sme-icon.svg +34 -0
  16. cognite/neat/_app/ui/neat-app/public/index.html +43 -0
  17. cognite/neat/_app/ui/neat-app/public/logo192.png +0 -0
  18. cognite/neat/_app/ui/neat-app/public/manifest.json +25 -0
  19. cognite/neat/_app/ui/neat-app/public/robots.txt +3 -0
  20. cognite/neat/_app/ui/neat-app/src/App.css +38 -0
  21. cognite/neat/_app/ui/neat-app/src/App.js +17 -0
  22. cognite/neat/_app/ui/neat-app/src/App.test.js +8 -0
  23. cognite/neat/_app/ui/neat-app/src/MainContainer.tsx +70 -0
  24. cognite/neat/_app/ui/neat-app/src/components/JsonViewer.tsx +43 -0
  25. cognite/neat/_app/ui/neat-app/src/components/LocalUploader.tsx +124 -0
  26. cognite/neat/_app/ui/neat-app/src/components/OverviewComponentEditorDialog.tsx +63 -0
  27. cognite/neat/_app/ui/neat-app/src/components/StepEditorDialog.tsx +511 -0
  28. cognite/neat/_app/ui/neat-app/src/components/TabPanel.tsx +36 -0
  29. cognite/neat/_app/ui/neat-app/src/components/Utils.tsx +56 -0
  30. cognite/neat/_app/ui/neat-app/src/components/WorkflowDeleteDialog.tsx +60 -0
  31. cognite/neat/_app/ui/neat-app/src/components/WorkflowExecutionReport.tsx +112 -0
  32. cognite/neat/_app/ui/neat-app/src/components/WorkflowImportExportDialog.tsx +67 -0
  33. cognite/neat/_app/ui/neat-app/src/components/WorkflowMetadataDialog.tsx +79 -0
  34. cognite/neat/_app/ui/neat-app/src/index.css +13 -0
  35. cognite/neat/_app/ui/neat-app/src/index.js +13 -0
  36. cognite/neat/_app/ui/neat-app/src/logo.svg +1 -0
  37. cognite/neat/_app/ui/neat-app/src/reportWebVitals.js +13 -0
  38. cognite/neat/_app/ui/neat-app/src/setupTests.js +5 -0
  39. cognite/neat/_app/ui/neat-app/src/types/WorkflowTypes.ts +388 -0
  40. cognite/neat/_app/ui/neat-app/src/views/AboutView.tsx +61 -0
  41. cognite/neat/_app/ui/neat-app/src/views/ConfigView.tsx +184 -0
  42. cognite/neat/_app/ui/neat-app/src/views/GlobalConfigView.tsx +180 -0
  43. cognite/neat/_app/ui/neat-app/src/views/WorkflowView.tsx +570 -0
  44. cognite/neat/_app/ui/neat-app/tsconfig.json +27 -0
  45. cognite/neat/{config.py → _config.py} +3 -3
  46. cognite/neat/{constants.py → _constants.py} +13 -5
  47. cognite/neat/_graph/_shared.py +34 -0
  48. cognite/neat/{graph → _graph}/_tracking/base.py +1 -1
  49. cognite/neat/{graph → _graph}/_tracking/log.py +1 -1
  50. cognite/neat/{graph → _graph}/extractors/__init__.py +5 -0
  51. cognite/neat/{graph → _graph}/extractors/_base.py +2 -2
  52. cognite/neat/{graph → _graph}/extractors/_classic_cdf/_assets.py +1 -1
  53. cognite/neat/{graph → _graph}/extractors/_classic_cdf/_base.py +4 -4
  54. cognite/neat/{graph → _graph}/extractors/_classic_cdf/_classic.py +5 -5
  55. cognite/neat/{graph → _graph}/extractors/_classic_cdf/_data_sets.py +1 -1
  56. cognite/neat/{graph → _graph}/extractors/_classic_cdf/_events.py +1 -1
  57. cognite/neat/{graph → _graph}/extractors/_classic_cdf/_files.py +1 -1
  58. cognite/neat/{graph → _graph}/extractors/_classic_cdf/_labels.py +1 -1
  59. cognite/neat/{graph → _graph}/extractors/_classic_cdf/_relationships.py +2 -2
  60. cognite/neat/{graph → _graph}/extractors/_classic_cdf/_sequences.py +1 -1
  61. cognite/neat/{graph → _graph}/extractors/_classic_cdf/_timeseries.py +1 -1
  62. cognite/neat/{graph → _graph}/extractors/_dexpi.py +5 -5
  63. cognite/neat/{graph → _graph}/extractors/_dms.py +3 -3
  64. cognite/neat/_graph/extractors/_iodd.py +402 -0
  65. cognite/neat/{graph → _graph}/extractors/_mock_graph_generator.py +9 -8
  66. cognite/neat/_graph/extractors/_rdf_file.py +49 -0
  67. cognite/neat/{graph → _graph}/loaders/_base.py +5 -5
  68. cognite/neat/{graph → _graph}/loaders/_rdf2asset.py +11 -10
  69. cognite/neat/{graph → _graph}/loaders/_rdf2dms.py +10 -10
  70. cognite/neat/{graph → _graph}/queries/_base.py +91 -19
  71. cognite/neat/{graph → _graph}/queries/_construct.py +5 -5
  72. cognite/neat/{graph → _graph}/queries/_shared.py +3 -3
  73. cognite/neat/{graph → _graph}/transformers/__init__.py +6 -0
  74. cognite/neat/{graph → _graph}/transformers/_classic_cdf.py +135 -3
  75. cognite/neat/_graph/transformers/_iodd.py +25 -0
  76. cognite/neat/_graph/transformers/_prune_graph.py +126 -0
  77. cognite/neat/{graph → _graph}/transformers/_rdfpath.py +3 -3
  78. cognite/neat/_graph/transformers/_value_type.py +66 -0
  79. cognite/neat/{issues → _issues}/_base.py +32 -17
  80. cognite/neat/{issues → _issues}/errors/__init__.py +1 -1
  81. cognite/neat/{issues → _issues}/errors/_external.py +8 -8
  82. cognite/neat/{issues → _issues}/errors/_general.py +5 -5
  83. cognite/neat/{issues → _issues}/errors/_properties.py +7 -7
  84. cognite/neat/{issues → _issues}/errors/_resources.py +11 -11
  85. cognite/neat/{issues → _issues}/errors/_workflow.py +5 -5
  86. cognite/neat/{issues → _issues}/warnings/__init__.py +1 -1
  87. cognite/neat/{issues → _issues}/warnings/_external.py +5 -5
  88. cognite/neat/{issues → _issues}/warnings/_general.py +4 -4
  89. cognite/neat/{issues → _issues}/warnings/_models.py +10 -10
  90. cognite/neat/{issues → _issues}/warnings/_properties.py +6 -6
  91. cognite/neat/{issues → _issues}/warnings/_resources.py +5 -5
  92. cognite/neat/{issues → _issues}/warnings/user_modeling.py +9 -9
  93. cognite/neat/_rules/_constants.py +190 -0
  94. cognite/neat/{rules → _rules}/_shared.py +5 -5
  95. cognite/neat/_rules/analysis/__init__.py +5 -0
  96. cognite/neat/{rules → _rules}/analysis/_asset.py +5 -5
  97. cognite/neat/{rules → _rules}/analysis/_base.py +5 -5
  98. cognite/neat/_rules/analysis/_dms.py +43 -0
  99. cognite/neat/{rules → _rules}/analysis/_information.py +12 -6
  100. cognite/neat/_rules/catalog/__init__.py +6 -0
  101. cognite/neat/_rules/catalog/info-rules-imf.xlsx +0 -0
  102. cognite/neat/{rules → _rules}/exporters/__init__.py +2 -0
  103. cognite/neat/{rules → _rules}/exporters/_base.py +3 -3
  104. cognite/neat/{rules → _rules}/exporters/_rules2dms.py +5 -5
  105. cognite/neat/{rules → _rules}/exporters/_rules2excel.py +26 -7
  106. cognite/neat/_rules/exporters/_rules2instance_template.py +152 -0
  107. cognite/neat/{rules → _rules}/exporters/_rules2ontology.py +10 -9
  108. cognite/neat/{rules → _rules}/exporters/_rules2yaml.py +1 -3
  109. cognite/neat/{rules → _rules}/exporters/_validation.py +2 -2
  110. cognite/neat/{rules → _rules}/importers/_base.py +3 -3
  111. cognite/neat/{rules → _rules}/importers/_dms2rules.py +9 -9
  112. cognite/neat/{rules → _rules}/importers/_dtdl2rules/dtdl_converter.py +7 -7
  113. cognite/neat/{rules → _rules}/importers/_dtdl2rules/dtdl_importer.py +9 -9
  114. cognite/neat/{rules → _rules}/importers/_dtdl2rules/spec.py +1 -1
  115. cognite/neat/_rules/importers/_rdf/_base.py +144 -0
  116. cognite/neat/{rules → _rules}/importers/_rdf/_imf2rules/_imf2classes.py +1 -1
  117. cognite/neat/{rules → _rules}/importers/_rdf/_imf2rules/_imf2metadata.py +4 -4
  118. cognite/neat/{rules → _rules}/importers/_rdf/_imf2rules/_imf2properties.py +2 -1
  119. cognite/neat/{rules → _rules}/importers/_rdf/_imf2rules/_imf2rules.py +8 -39
  120. cognite/neat/{rules → _rules}/importers/_rdf/_inference2rules.py +33 -106
  121. cognite/neat/{rules → _rules}/importers/_rdf/_owl2rules/_owl2classes.py +1 -1
  122. cognite/neat/{rules → _rules}/importers/_rdf/_owl2rules/_owl2metadata.py +5 -5
  123. cognite/neat/{rules → _rules}/importers/_rdf/_owl2rules/_owl2properties.py +1 -1
  124. cognite/neat/_rules/importers/_rdf/_owl2rules/_owl2rules.py +39 -0
  125. cognite/neat/{rules → _rules}/importers/_rdf/_shared.py +4 -4
  126. cognite/neat/{rules → _rules}/importers/_spreadsheet2rules.py +40 -6
  127. cognite/neat/{rules → _rules}/importers/_yaml2rules.py +5 -5
  128. cognite/neat/{rules → _rules}/models/__init__.py +5 -5
  129. cognite/neat/{rules → _rules}/models/_base_input.py +30 -11
  130. cognite/neat/{rules → _rules}/models/_base_rules.py +22 -8
  131. cognite/neat/{rules → _rules}/models/_rdfpath.py +1 -1
  132. cognite/neat/_rules/models/_types.py +151 -0
  133. cognite/neat/{rules → _rules}/models/asset/_rules.py +4 -4
  134. cognite/neat/{rules → _rules}/models/asset/_rules_input.py +4 -4
  135. cognite/neat/{rules → _rules}/models/asset/_validation.py +7 -7
  136. cognite/neat/{rules → _rules}/models/data_types.py +15 -12
  137. cognite/neat/{rules → _rules}/models/dms/_exporter.py +60 -12
  138. cognite/neat/{rules → _rules}/models/dms/_rules.py +29 -26
  139. cognite/neat/{rules → _rules}/models/dms/_rules_input.py +4 -4
  140. cognite/neat/{rules → _rules}/models/dms/_schema.py +15 -14
  141. cognite/neat/{rules → _rules}/models/dms/_validation.py +8 -8
  142. cognite/neat/{rules → _rules}/models/domain.py +6 -6
  143. cognite/neat/{rules → _rules}/models/entities/__init__.py +1 -2
  144. cognite/neat/_rules/models/entities/_constants.py +15 -0
  145. cognite/neat/{rules → _rules}/models/entities/_loaders.py +2 -2
  146. cognite/neat/{rules → _rules}/models/entities/_multi_value.py +15 -2
  147. cognite/neat/{rules → _rules}/models/entities/_single_value.py +16 -4
  148. cognite/neat/{rules → _rules}/models/information/_rules.py +37 -25
  149. cognite/neat/{rules → _rules}/models/information/_rules_input.py +3 -3
  150. cognite/neat/{rules → _rules}/models/information/_validation.py +6 -5
  151. cognite/neat/_rules/models/mapping/__init__.py +4 -0
  152. cognite/neat/_rules/models/mapping/_base.py +131 -0
  153. cognite/neat/_rules/models/mapping/_classic2core.py +150 -0
  154. cognite/neat/{rules → _rules}/transformers/__init__.py +15 -2
  155. cognite/neat/{rules → _rules}/transformers/_base.py +3 -3
  156. cognite/neat/{rules → _rules}/transformers/_converters.py +289 -20
  157. cognite/neat/{rules/transformers/_map_onto.py → _rules/transformers/_mapping.py} +46 -4
  158. cognite/neat/{rules → _rules}/transformers/_pipelines.py +4 -4
  159. cognite/neat/{rules → _rules}/transformers/_verification.py +10 -4
  160. cognite/neat/_session/__init__.py +3 -0
  161. cognite/neat/_session/_base.py +86 -0
  162. cognite/neat/_session/_prepare.py +61 -0
  163. cognite/neat/_session/_read.py +118 -0
  164. cognite/neat/_session/_show.py +96 -0
  165. cognite/neat/_session/_state.py +69 -0
  166. cognite/neat/_session/_to.py +70 -0
  167. cognite/neat/_session/_wizard.py +39 -0
  168. cognite/neat/_session/exceptions.py +42 -0
  169. cognite/neat/{store → _store}/_base.py +63 -32
  170. cognite/neat/{store → _store}/_provenance.py +11 -1
  171. cognite/neat/{utils → _utils}/auth.py +14 -3
  172. cognite/neat/{utils → _utils}/auxiliary.py +1 -1
  173. cognite/neat/{utils → _utils}/cdf/loaders/_data_modeling.py +8 -2
  174. cognite/neat/{utils → _utils}/cdf/loaders/_ingestion.py +1 -1
  175. cognite/neat/{utils → _utils}/upload.py +1 -1
  176. cognite/neat/_version.py +1 -1
  177. cognite/neat/_workflows/__init__.py +17 -0
  178. cognite/neat/{workflows → _workflows}/base.py +10 -10
  179. cognite/neat/{workflows → _workflows}/cdf_store.py +3 -3
  180. cognite/neat/{workflows → _workflows}/examples/Export_DMS/workflow.yaml +89 -89
  181. cognite/neat/{workflows → _workflows}/manager.py +6 -6
  182. cognite/neat/{workflows → _workflows}/steps/data_contracts.py +3 -3
  183. cognite/neat/{workflows → _workflows}/steps/lib/current/graph_extractor.py +8 -31
  184. cognite/neat/{workflows → _workflows}/steps/lib/current/graph_loader.py +4 -4
  185. cognite/neat/{workflows → _workflows}/steps/lib/current/graph_store.py +4 -4
  186. cognite/neat/{workflows → _workflows}/steps/lib/current/rules_exporter.py +8 -8
  187. cognite/neat/{workflows → _workflows}/steps/lib/current/rules_importer.py +13 -13
  188. cognite/neat/{workflows → _workflows}/steps/lib/current/rules_validator.py +8 -8
  189. cognite/neat/{workflows → _workflows}/steps/lib/io/io_steps.py +3 -3
  190. cognite/neat/{workflows → _workflows}/steps/step_model.py +3 -3
  191. cognite/neat/{workflows → _workflows}/steps_registry.py +9 -9
  192. cognite/neat/{workflows → _workflows}/tasks.py +1 -1
  193. cognite/neat/{workflows → _workflows}/triggers.py +2 -2
  194. {cognite_neat-0.92.2.dist-info → cognite_neat-0.93.0.dist-info}/METADATA +6 -2
  195. cognite_neat-0.93.0.dist-info/RECORD +276 -0
  196. {cognite_neat-0.92.2.dist-info → cognite_neat-0.93.0.dist-info}/WHEEL +1 -1
  197. cognite_neat-0.93.0.dist-info/entry_points.txt +3 -0
  198. cognite/neat/app/api/context_manager/__init__.py +0 -3
  199. cognite/neat/graph/_shared.py +0 -5
  200. cognite/neat/graph/extractors/_iodd.py +0 -160
  201. cognite/neat/graph/extractors/_rdf_file.py +0 -26
  202. cognite/neat/rules/analysis/__init__.py +0 -6
  203. cognite/neat/rules/examples/__init__.py +0 -10
  204. cognite/neat/rules/examples/info-rules-imf.xlsx +0 -0
  205. cognite/neat/rules/examples/wind-energy.owl +0 -1511
  206. cognite/neat/rules/importers/_rdf/_owl2rules/_owl2rules.py +0 -65
  207. cognite/neat/rules/models/_types.py +0 -96
  208. cognite/neat/rules/models/entities/_constants.py +0 -73
  209. cognite/neat/utils/regex_patterns.py +0 -58
  210. cognite/neat/workflows/__init__.py +0 -12
  211. cognite_neat-0.92.2.dist-info/RECORD +0 -224
  212. cognite_neat-0.92.2.dist-info/entry_points.txt +0 -3
  213. /cognite/neat/{app → _app}/api/__init__.py +0 -0
  214. /cognite/neat/{app → _app}/api/asgi/metrics.py +0 -0
  215. /cognite/neat/{app → _app}/api/data_classes/__init__.py +0 -0
  216. /cognite/neat/{app → _app}/api/data_classes/rest.py +0 -0
  217. /cognite/neat/{app → _app}/api/routers/metrics.py +0 -0
  218. /cognite/neat/{app → _app}/api/utils/__init__.py +0 -0
  219. /cognite/neat/{app → _app}/api/utils/data_mapping.py +0 -0
  220. /cognite/neat/{app → _app}/api/utils/logging.py +0 -0
  221. /cognite/neat/{app → _app}/api/utils/query_templates.py +0 -0
  222. /cognite/neat/{app → _app}/monitoring/__init__.py +0 -0
  223. /cognite/neat/{app → _app}/monitoring/metrics.py +0 -0
  224. /cognite/neat/{app → _app}/ui/index.html +0 -0
  225. /cognite/neat/{app → _app}/ui/neat-app/.gitignore +0 -0
  226. /cognite/neat/{app → _app}/ui/neat-app/README.md +0 -0
  227. /cognite/neat/{app → _app}/ui/neat-app/build/asset-manifest.json +0 -0
  228. /cognite/neat/{app → _app}/ui/neat-app/build/favicon.ico +0 -0
  229. /cognite/neat/{app → _app}/ui/neat-app/build/img/architect-icon.svg +0 -0
  230. /cognite/neat/{app → _app}/ui/neat-app/build/img/developer-icon.svg +0 -0
  231. /cognite/neat/{app → _app}/ui/neat-app/build/img/sme-icon.svg +0 -0
  232. /cognite/neat/{app → _app}/ui/neat-app/build/index.html +0 -0
  233. /cognite/neat/{app → _app}/ui/neat-app/build/logo192.png +0 -0
  234. /cognite/neat/{app → _app}/ui/neat-app/build/manifest.json +0 -0
  235. /cognite/neat/{app → _app}/ui/neat-app/build/robots.txt +0 -0
  236. /cognite/neat/{app → _app}/ui/neat-app/build/static/css/main.72e3d92e.css +0 -0
  237. /cognite/neat/{app → _app}/ui/neat-app/build/static/css/main.72e3d92e.css.map +0 -0
  238. /cognite/neat/{app → _app}/ui/neat-app/build/static/js/main.5a52cf09.js +0 -0
  239. /cognite/neat/{app → _app}/ui/neat-app/build/static/js/main.5a52cf09.js.LICENSE.txt +0 -0
  240. /cognite/neat/{app → _app}/ui/neat-app/build/static/js/main.5a52cf09.js.map +0 -0
  241. /cognite/neat/{app → _app}/ui/neat-app/build/static/media/logo.8093b84df9ed36a174c629d6fe0b730d.svg +0 -0
  242. /cognite/neat/{graph → _graph}/__init__.py +0 -0
  243. /cognite/neat/{graph → _graph}/_tracking/__init__.py +0 -0
  244. /cognite/neat/{graph → _graph}/examples/Knowledge-Graph-Nordic44-dirty.xml +0 -0
  245. /cognite/neat/{graph → _graph}/examples/Knowledge-Graph-Nordic44.xml +0 -0
  246. /cognite/neat/{graph → _graph}/examples/__init__.py +0 -0
  247. /cognite/neat/{graph → _graph}/examples/skos-capturing-sheet-wind-topics.xlsx +0 -0
  248. /cognite/neat/{graph → _graph}/extractors/_classic_cdf/__init__.py +0 -0
  249. /cognite/neat/{graph → _graph}/loaders/__init__.py +0 -0
  250. /cognite/neat/{graph → _graph}/models.py +0 -0
  251. /cognite/neat/{graph → _graph}/queries/__init__.py +0 -0
  252. /cognite/neat/{graph → _graph}/transformers/_base.py +0 -0
  253. /cognite/neat/{issues → _issues}/__init__.py +0 -0
  254. /cognite/neat/{issues → _issues}/formatters.py +0 -0
  255. /cognite/neat/{rules → _rules}/__init__.py +0 -0
  256. /cognite/neat/{rules → _rules}/importers/__init__.py +0 -0
  257. /cognite/neat/{rules → _rules}/importers/_dtdl2rules/__init__.py +0 -0
  258. /cognite/neat/{rules → _rules}/importers/_dtdl2rules/_unit_lookup.py +0 -0
  259. /cognite/neat/{rules → _rules}/importers/_rdf/__init__.py +0 -0
  260. /cognite/neat/{rules → _rules}/importers/_rdf/_imf2rules/__init__.py +0 -0
  261. /cognite/neat/{rules → _rules}/importers/_rdf/_owl2rules/__init__.py +0 -0
  262. /cognite/neat/{rules → _rules}/models/asset/__init__.py +0 -0
  263. /cognite/neat/{rules → _rules}/models/dms/__init__.py +0 -0
  264. /cognite/neat/{rules → _rules}/models/entities/_types.py +0 -0
  265. /cognite/neat/{rules → _rules}/models/entities/_wrapped.py +0 -0
  266. /cognite/neat/{rules → _rules}/models/information/__init__.py +0 -0
  267. /cognite/neat/{store → _store}/__init__.py +0 -0
  268. /cognite/neat/{utils → _utils}/__init__.py +0 -0
  269. /cognite/neat/{utils → _utils}/cdf/__init__.py +0 -0
  270. /cognite/neat/{utils → _utils}/cdf/data_classes.py +0 -0
  271. /cognite/neat/{utils → _utils}/cdf/loaders/__init__.py +0 -0
  272. /cognite/neat/{utils → _utils}/cdf/loaders/_base.py +0 -0
  273. /cognite/neat/{utils → _utils}/collection_.py +0 -0
  274. /cognite/neat/{utils → _utils}/rdf_.py +0 -0
  275. /cognite/neat/{utils → _utils}/spreadsheet.py +0 -0
  276. /cognite/neat/{utils → _utils}/text.py +0 -0
  277. /cognite/neat/{utils → _utils}/time_.py +0 -0
  278. /cognite/neat/{utils → _utils}/xml_.py +0 -0
  279. /cognite/neat/{workflows → _workflows}/examples/Export_Semantic_Data_Model/workflow.yaml +0 -0
  280. /cognite/neat/{workflows → _workflows}/examples/Import_DMS/workflow.yaml +0 -0
  281. /cognite/neat/{workflows → _workflows}/examples/Validate_Rules/workflow.yaml +0 -0
  282. /cognite/neat/{workflows → _workflows}/examples/Validate_Solution_Model/workflow.yaml +0 -0
  283. /cognite/neat/{workflows → _workflows}/model.py +0 -0
  284. /cognite/neat/{workflows → _workflows}/steps/__init__.py +0 -0
  285. /cognite/neat/{workflows → _workflows}/steps/lib/__init__.py +0 -0
  286. /cognite/neat/{workflows → _workflows}/steps/lib/current/__init__.py +0 -0
  287. /cognite/neat/{workflows → _workflows}/steps/lib/io/__init__.py +0 -0
  288. /cognite/neat/{workflows → _workflows}/utils.py +0 -0
  289. {cognite_neat-0.92.2.dist-info → cognite_neat-0.93.0.dist-info}/LICENSE +0 -0
@@ -3,23 +3,21 @@ from datetime import datetime
3
3
  from pathlib import Path
4
4
  from typing import cast
5
5
 
6
- from rdflib import RDF, Graph, Namespace, URIRef
6
+ from rdflib import RDF
7
7
  from rdflib import Literal as RdfLiteral
8
8
 
9
- from cognite.neat.constants import DEFAULT_NAMESPACE, get_default_prefixes
10
- from cognite.neat.issues import IssueList
11
- from cognite.neat.issues.errors import FileReadError
12
- from cognite.neat.issues.warnings import PropertyValueTypeUndefinedWarning
13
- from cognite.neat.rules._shared import ReadRules
14
- from cognite.neat.rules.importers._base import BaseImporter
15
- from cognite.neat.rules.models._base_rules import MatchType
16
- from cognite.neat.rules.models.entities._single_value import UnknownEntity
17
- from cognite.neat.rules.models.information import (
18
- InformationInputRules,
9
+ from cognite.neat._constants import DEFAULT_NAMESPACE
10
+ from cognite.neat._issues.warnings import PropertyValueTypeUndefinedWarning
11
+ from cognite.neat._rules.models._base_rules import MatchType
12
+ from cognite.neat._rules.models.data_types import AnyURI
13
+ from cognite.neat._rules.models.entities._single_value import UnknownEntity
14
+ from cognite.neat._rules.models.information import (
19
15
  InformationMetadata,
20
16
  )
21
- from cognite.neat.store import NeatGraphStore
22
- from cognite.neat.utils.rdf_ import get_namespace, remove_namespace_from_uri, uri_to_short_form
17
+ from cognite.neat._store import NeatGraphStore
18
+ from cognite.neat._utils.rdf_ import remove_namespace_from_uri
19
+
20
+ from ._base import DEFAULT_NON_EXISTING_NODE_TYPE, BaseRDFImporter
23
21
 
24
22
  ORDERED_CLASSES_QUERY = """SELECT ?class (count(?s) as ?instances )
25
23
  WHERE { ?s a ?class . }
@@ -36,7 +34,7 @@ INSTANCE_PROPERTIES_DEFINITION = """SELECT ?property (count(?property) as ?occur
36
34
  GROUP BY ?property ?dataType ?objectType"""
37
35
 
38
36
 
39
- class InferenceImporter(BaseImporter[InformationInputRules]):
37
+ class InferenceImporter(BaseRDFImporter):
40
38
  """Infers rules from a triple store.
41
39
 
42
40
  Rules inference through analysis of knowledge graph provided in various formats.
@@ -50,62 +48,32 @@ class InferenceImporter(BaseImporter[InformationInputRules]):
50
48
  prefix: Prefix to be used for the inferred model
51
49
  """
52
50
 
53
- def __init__(
54
- self,
55
- issue_list: IssueList,
56
- graph: Graph,
57
- max_number_of_instance: int = -1,
58
- prefix: str = "inferred",
59
- ) -> None:
60
- self.issue_list = issue_list
61
- self.graph = graph
62
- self.max_number_of_instance = max_number_of_instance
63
- self.prefix = prefix
64
-
65
51
  @classmethod
66
52
  def from_graph_store(
67
53
  cls,
68
54
  store: NeatGraphStore,
69
- max_number_of_instance: int = -1,
70
55
  prefix: str = "inferred",
56
+ max_number_of_instance: int = -1,
57
+ non_existing_node_type: UnknownEntity | AnyURI = DEFAULT_NON_EXISTING_NODE_TYPE,
71
58
  ) -> "InferenceImporter":
72
- issue_list = IssueList(title="Inferred from graph store")
73
-
74
- return cls(
75
- issue_list,
76
- store.graph,
77
- max_number_of_instance=max_number_of_instance,
78
- prefix=prefix,
79
- )
59
+ return super().from_graph_store(store, prefix, max_number_of_instance, non_existing_node_type)
80
60
 
81
61
  @classmethod
82
- def from_rdf_file(
62
+ def from_file(
83
63
  cls,
84
64
  filepath: Path,
85
- max_number_of_instance: int = -1,
86
65
  prefix: str = "inferred",
66
+ max_number_of_instance: int = -1,
67
+ non_existing_node_type: UnknownEntity | AnyURI = DEFAULT_NON_EXISTING_NODE_TYPE,
87
68
  ) -> "InferenceImporter":
88
- issue_list = IssueList(title=f"'{filepath.name}'")
89
-
90
- graph = Graph()
91
- try:
92
- graph.parse(filepath)
93
- except Exception as e:
94
- issue_list.append(FileReadError(filepath, str(e)))
95
-
96
- return cls(
97
- issue_list,
98
- graph,
99
- max_number_of_instance=max_number_of_instance,
100
- prefix=prefix,
101
- )
69
+ return super().from_file(filepath, prefix, max_number_of_instance, non_existing_node_type)
102
70
 
103
71
  @classmethod
104
72
  def from_json_file(
105
73
  cls,
106
74
  filepath: Path,
107
- max_number_of_instance: int = -1,
108
75
  prefix: str = "inferred",
76
+ max_number_of_instance: int = -1,
109
77
  ) -> "InferenceImporter":
110
78
  raise NotImplementedError("JSON file format is not supported yet.")
111
79
 
@@ -113,8 +81,8 @@ class InferenceImporter(BaseImporter[InformationInputRules]):
113
81
  def from_yaml_file(
114
82
  cls,
115
83
  filepath: Path,
116
- max_number_of_instance: int = -1,
117
84
  prefix: str = "inferred",
85
+ max_number_of_instance: int = -1,
118
86
  ) -> "InferenceImporter":
119
87
  raise NotImplementedError("YAML file format is not supported yet.")
120
88
 
@@ -122,27 +90,11 @@ class InferenceImporter(BaseImporter[InformationInputRules]):
122
90
  def from_xml_file(
123
91
  cls,
124
92
  filepath: Path,
125
- max_number_of_instance: int = -1,
126
93
  prefix: str = "inferred",
94
+ max_number_of_instance: int = -1,
127
95
  ) -> "InferenceImporter":
128
96
  raise NotImplementedError("JSON file format is not supported yet.")
129
97
 
130
- def to_rules(
131
- self,
132
- ) -> ReadRules[InformationInputRules]:
133
- """
134
- Creates `Rules` object from the data for target role.
135
- """
136
-
137
- if self.issue_list.has_errors:
138
- # In case there were errors during the import, the to_rules method will return None
139
- return ReadRules(None, self.issue_list, {})
140
-
141
- rules_dict = self._to_rules_components()
142
-
143
- rules = InformationInputRules.load(rules_dict)
144
- return ReadRules(rules, self.issue_list, {})
145
-
146
98
  def _to_rules_components(
147
99
  self,
148
100
  ) -> dict:
@@ -157,16 +109,10 @@ class InferenceImporter(BaseImporter[InformationInputRules]):
157
109
  """
158
110
  classes: dict[str, dict] = {}
159
111
  properties: dict[str, dict] = {}
160
- prefixes: dict[str, Namespace] = get_default_prefixes()
161
112
  count_by_value_type_by_property: dict[str, dict[str, int]] = defaultdict(Counter)
162
113
 
163
- # Adds default namespace to prefixes
164
- prefixes[self._default_metadata().prefix] = self._default_metadata().namespace
165
-
166
114
  # Infers all the classes in the graph
167
115
  for class_uri, no_instances in self.graph.query(ORDERED_CLASSES_QUERY): # type: ignore[misc]
168
- self._add_uri_namespace_to_prefixes(cast(URIRef, class_uri), prefixes)
169
-
170
116
  if (class_id := remove_namespace_from_uri(class_uri)) in classes:
171
117
  # handles cases when class id is already present in classes
172
118
  class_id = f"{class_id}_{len(classes)+1}"
@@ -195,27 +141,24 @@ class InferenceImporter(BaseImporter[InformationInputRules]):
195
141
 
196
142
  property_id = remove_namespace_from_uri(property_uri)
197
143
 
198
- self._add_uri_namespace_to_prefixes(cast(URIRef, property_uri), prefixes)
199
-
200
144
  if value_type_uri := (data_type_uri or object_type_uri):
201
- self._add_uri_namespace_to_prefixes(cast(URIRef, value_type_uri), prefixes)
202
-
203
145
  value_type_id = remove_namespace_from_uri(value_type_uri)
204
146
 
205
147
  # this handles situations when property points to node that is not present in graph
206
148
  else:
207
- value_type_id = str(UnknownEntity())
208
-
209
- self.issue_list.append(
210
- PropertyValueTypeUndefinedWarning(
211
- resource_type="Property",
212
- identifier=f"{class_id}{property_id}",
213
- property_name=property_id,
214
- default_action="Remove the property from the rules",
215
- recommended_action="Make sure that graph is complete",
216
- )
149
+ value_type_id = str(self.non_existing_node_type)
150
+
151
+ issue = PropertyValueTypeUndefinedWarning(
152
+ resource_type="Property",
153
+ identifier=f"{class_id}:{property_id}",
154
+ property_name=property_id,
155
+ default_action="Remove the property from the rules",
156
+ recommended_action="Make sure that graph is complete",
217
157
  )
218
158
 
159
+ if issue not in self.issue_list:
160
+ self.issue_list.append(issue)
161
+
219
162
  id_ = f"{class_id}:{property_id}"
220
163
 
221
164
  definition = {
@@ -224,10 +167,6 @@ class InferenceImporter(BaseImporter[InformationInputRules]):
224
167
  "max_count": cast(RdfLiteral, occurrence).value,
225
168
  "value_type": value_type_id,
226
169
  "reference": property_uri,
227
- "transformation": (
228
- f"{uri_to_short_form(class_definition['reference'], prefixes)}"
229
- f"({uri_to_short_form(cast(URIRef, property_uri), prefixes)})"
230
- ),
231
170
  }
232
171
 
233
172
  count_by_value_type_by_property[id_][value_type_id] += 1
@@ -279,20 +218,8 @@ class InferenceImporter(BaseImporter[InformationInputRules]):
279
218
  "metadata": self._default_metadata().model_dump(),
280
219
  "classes": list(classes.values()),
281
220
  "properties": list(properties.values()),
282
- "prefixes": prefixes,
283
221
  }
284
222
 
285
- @classmethod
286
- def _add_uri_namespace_to_prefixes(cls, URI: URIRef, prefixes: dict[str, Namespace]):
287
- """Add URI to prefixes dict if not already present
288
-
289
- Args:
290
- URI: URI from which namespace is being extracted
291
- prefixes: Dict of prefixes and namespaces
292
- """
293
- if Namespace(get_namespace(URI)) not in prefixes.values():
294
- prefixes[f"prefix-{len(prefixes)+1}"] = Namespace(get_namespace(URI))
295
-
296
223
  def _default_metadata(self):
297
224
  return InformationMetadata(
298
225
  name="Inferred Model",
@@ -2,7 +2,7 @@ from typing import cast
2
2
 
3
3
  from rdflib import Graph
4
4
 
5
- from cognite.neat.rules.importers._rdf._shared import (
5
+ from cognite.neat._rules.importers._rdf._shared import (
6
6
  clean_up_classes,
7
7
  make_classes_compliant,
8
8
  parse_raw_classes_dataframe,
@@ -1,10 +1,10 @@
1
1
  from rdflib import Graph, Namespace
2
2
 
3
- from cognite.neat.constants import DEFAULT_NAMESPACE
4
- from cognite.neat.rules.importers._rdf._shared import make_metadata_compliant
5
- from cognite.neat.rules.models import RoleTypes, SchemaCompleteness
6
- from cognite.neat.utils.collection_ import remove_none_elements_from_set
7
- from cognite.neat.utils.rdf_ import convert_rdflib_content
3
+ from cognite.neat._constants import DEFAULT_NAMESPACE
4
+ from cognite.neat._rules.importers._rdf._shared import make_metadata_compliant
5
+ from cognite.neat._rules.models import RoleTypes, SchemaCompleteness
6
+ from cognite.neat._utils.collection_ import remove_none_elements_from_set
7
+ from cognite.neat._utils.rdf_ import convert_rdflib_content
8
8
 
9
9
 
10
10
  def parse_owl_metadata(graph: Graph) -> dict:
@@ -2,7 +2,7 @@ from typing import cast
2
2
 
3
3
  from rdflib import Graph
4
4
 
5
- from cognite.neat.rules.importers._rdf._shared import (
5
+ from cognite.neat._rules.importers._rdf._shared import (
6
6
  clean_up_properties,
7
7
  make_properties_compliant,
8
8
  parse_raw_properties_dataframe,
@@ -0,0 +1,39 @@
1
+ """This module performs importing of various formats to one of serializations for which
2
+ there are loaders to TransformationRules pydantic class."""
3
+
4
+ from cognite.neat._rules.importers._rdf._base import BaseRDFImporter
5
+ from cognite.neat._rules.importers._rdf._shared import make_components_compliant
6
+
7
+ from ._owl2classes import parse_owl_classes
8
+ from ._owl2metadata import parse_owl_metadata
9
+ from ._owl2properties import parse_owl_properties
10
+
11
+
12
+ class OWLImporter(BaseRDFImporter):
13
+ """Convert OWL ontology to tables/ transformation rules / Excel file.
14
+
15
+ Args:
16
+ filepath: Path to OWL ontology
17
+
18
+ !!! Note
19
+ OWL Ontologies are information models which completeness varies. As such, constructing functional
20
+ data model directly will often be impossible, therefore the produced Rules object will be ill formed.
21
+ To avoid this, neat will automatically attempt to make the imported rules compliant by adding default
22
+ values for missing information, attaching dangling properties to default containers based on the
23
+ property type, etc.
24
+
25
+ One has to be aware that NEAT will be opinionated about how to make the ontology
26
+ compliant, and that the resulting rules may not be what you expect.
27
+
28
+ """
29
+
30
+ def _to_rules_components(
31
+ self,
32
+ ) -> dict:
33
+ components = {
34
+ "Metadata": parse_owl_metadata(self.graph),
35
+ "Classes": parse_owl_classes(self.graph),
36
+ "Properties": parse_owl_properties(self.graph),
37
+ }
38
+
39
+ return make_components_compliant(components)
@@ -4,10 +4,10 @@ import numpy as np
4
4
  import pandas as pd
5
5
  from rdflib import OWL, Literal, Namespace
6
6
 
7
- from cognite.neat.rules.models._base_rules import MatchType
8
- from cognite.neat.rules.models.data_types import _XSD_TYPES
9
- from cognite.neat.utils.rdf_ import remove_namespace_from_uri
10
- from cognite.neat.utils.regex_patterns import PATTERNS
7
+ from cognite.neat._rules._constants import PATTERNS
8
+ from cognite.neat._rules.models._base_rules import MatchType
9
+ from cognite.neat._rules.models.data_types import _XSD_TYPES
10
+ from cognite.neat._utils.rdf_ import remove_namespace_from_uri
11
11
 
12
12
 
13
13
  def parse_raw_classes_dataframe(query_results: list[tuple]) -> pd.DataFrame:
@@ -11,23 +11,25 @@ from typing import Literal, cast
11
11
  import pandas as pd
12
12
  from cognite.client.utils._importing import local_import
13
13
  from pandas import ExcelFile
14
+ from rdflib import Namespace
14
15
 
15
- from cognite.neat.issues import IssueList
16
- from cognite.neat.issues.errors import (
16
+ from cognite.neat._issues import IssueList
17
+ from cognite.neat._issues.errors import (
17
18
  FileMissingRequiredFieldError,
18
19
  FileNotFoundNeatError,
19
20
  FileReadError,
20
21
  PropertyDefinitionDuplicatedError,
21
22
  )
22
- from cognite.neat.rules._shared import ReadRules, T_InputRules
23
- from cognite.neat.rules.models import (
23
+ from cognite.neat._issues.warnings import FileMissingRequiredFieldWarning
24
+ from cognite.neat._rules._shared import ReadRules, T_InputRules
25
+ from cognite.neat._rules.models import (
24
26
  INPUT_RULES_BY_ROLE,
25
27
  VERIFIED_RULES_BY_ROLE,
26
28
  RoleTypes,
27
29
  SchemaCompleteness,
28
30
  )
29
- from cognite.neat.utils.spreadsheet import SpreadsheetRead, read_individual_sheet
30
- from cognite.neat.utils.text import humanize_collection
31
+ from cognite.neat._utils.spreadsheet import SpreadsheetRead, read_individual_sheet
32
+ from cognite.neat._utils.text import humanize_collection
31
33
 
32
34
  from ._base import BaseImporter
33
35
 
@@ -93,6 +95,7 @@ class ReadResult:
93
95
  sheets: dict[str, dict | list]
94
96
  read_info_by_sheet: dict[str, SpreadsheetRead]
95
97
  metadata: MetadataRaw
98
+ prefixes: dict[str, Namespace] | None = None
96
99
 
97
100
  @property
98
101
  def role(self) -> RoleTypes:
@@ -122,6 +125,10 @@ class SpreadsheetReader:
122
125
  def metadata_sheet_name(self) -> str:
123
126
  return f"{self._sheet_prefix}Metadata"
124
127
 
128
+ @property
129
+ def prefixes_sheet_name(self) -> str:
130
+ return "Prefixes"
131
+
125
132
  @property
126
133
  def seen_sheets(self) -> set[str]:
127
134
  if not self._seen_files:
@@ -149,6 +156,14 @@ class SpreadsheetReader:
149
156
  return None
150
157
  sheets["Metadata"] = dict(metadata)
151
158
 
159
+ # Special case for reading prefixes as they are suppose to be read only once
160
+ if (
161
+ self.prefixes_sheet_name in excel_file.sheet_names
162
+ and not self._sheet_prefix
163
+ and (prefixes := self._read_prefixes(excel_file, filepath))
164
+ ):
165
+ sheets["Prefixes"] = prefixes
166
+
152
167
  return ReadResult(sheets, read_info_by_sheet, metadata)
153
168
 
154
169
  def _read_metadata(self, excel_file: ExcelFile, filepath: Path) -> MetadataRaw | None:
@@ -163,6 +178,25 @@ class SpreadsheetReader:
163
178
  return None
164
179
  return metadata
165
180
 
181
+ def _read_prefixes(self, excel_file: ExcelFile, filepath: Path) -> dict[str, Namespace] | None:
182
+ if self.prefixes_sheet_name not in excel_file.sheet_names:
183
+ return None
184
+
185
+ else:
186
+ prefixes = {}
187
+
188
+ for row in read_individual_sheet(excel_file, "Prefixes", expected_headers=["Prefix", "Namespace"]):
189
+ if "Prefix" in row and "Namespace" in row:
190
+ prefixes[row["Prefix"]] = row["Namespace"]
191
+ else:
192
+ if "Prefix" not in row:
193
+ self.issue_list.append(FileMissingRequiredFieldWarning(filepath, "prefixes", "prefix"))
194
+ if "Namespace" not in row:
195
+ self.issue_list.append(FileMissingRequiredFieldWarning(filepath, "prefixes", "namespace"))
196
+ return None
197
+
198
+ return prefixes
199
+
166
200
  def _read_sheets(
167
201
  self, excel_file: ExcelFile, read_role: RoleTypes
168
202
  ) -> tuple[dict[str, dict | list] | None, dict[str, SpreadsheetRead]]:
@@ -3,16 +3,16 @@ from typing import Any, cast
3
3
 
4
4
  import yaml
5
5
 
6
- from cognite.neat.issues import IssueList, NeatIssue
7
- from cognite.neat.issues.errors import (
6
+ from cognite.neat._issues import IssueList, NeatIssue
7
+ from cognite.neat._issues.errors import (
8
8
  FileMissingRequiredFieldError,
9
9
  FileNotAFileError,
10
10
  FileNotFoundNeatError,
11
11
  FileTypeUnexpectedError,
12
12
  )
13
- from cognite.neat.issues.warnings import NeatValueWarning
14
- from cognite.neat.rules._shared import ReadRules, T_InputRules
15
- from cognite.neat.rules.models import INPUT_RULES_BY_ROLE, RoleTypes
13
+ from cognite.neat._issues.warnings import NeatValueWarning
14
+ from cognite.neat._rules._shared import ReadRules, T_InputRules
15
+ from cognite.neat._rules.models import INPUT_RULES_BY_ROLE, RoleTypes
16
16
 
17
17
  from ._base import BaseImporter
18
18
 
@@ -1,8 +1,8 @@
1
- from cognite.neat.rules.models.asset._rules import AssetRules
2
- from cognite.neat.rules.models.asset._rules_input import AssetInputRules
3
- from cognite.neat.rules.models.domain import DomainInputRules, DomainRules
4
- from cognite.neat.rules.models.information._rules import InformationRules
5
- from cognite.neat.rules.models.information._rules_input import InformationInputRules
1
+ from cognite.neat._rules.models.asset._rules import AssetRules
2
+ from cognite.neat._rules.models.asset._rules_input import AssetInputRules
3
+ from cognite.neat._rules.models.domain import DomainInputRules, DomainRules
4
+ from cognite.neat._rules.models.information._rules import InformationRules
5
+ from cognite.neat._rules.models.information._rules_input import InformationInputRules
6
6
 
7
7
  from ._base_rules import DataModelType, ExtensionCategory, RoleTypes, SchemaCompleteness, SheetList, SheetRow
8
8
  from .dms._rules import DMSRules
@@ -18,6 +18,8 @@ from dataclasses import Field, dataclass, fields, is_dataclass
18
18
  from types import GenericAlias, UnionType
19
19
  from typing import Any, Generic, TypeVar, Union, cast, get_args, get_origin, overload
20
20
 
21
+ import pandas as pd
22
+
21
23
  from ._base_rules import BaseRules, SchemaModel
22
24
 
23
25
  if sys.version_info >= (3, 11):
@@ -40,14 +42,14 @@ class InputRules(Generic[T_BaseRules], ABC):
40
42
 
41
43
  @classmethod
42
44
  @overload
43
- def load(cls, data: dict[str, Any]) -> Self: ...
45
+ def load(cls: "type[T_InputRules]", data: dict[str, Any]) -> "T_InputRules": ...
44
46
 
45
47
  @classmethod
46
48
  @overload
47
- def load(cls, data: None) -> None: ...
49
+ def load(cls: "type[T_InputRules]", data: None) -> None: ...
48
50
 
49
51
  @classmethod
50
- def load(cls, data: dict | None) -> Self | None:
52
+ def load(cls: "type[T_InputRules]", data: dict | None) -> "T_InputRules | None":
51
53
  if data is None:
52
54
  return None
53
55
  return cls._load(data)
@@ -62,15 +64,20 @@ class InputRules(Generic[T_BaseRules], ABC):
62
64
  if isinstance(type_, str) and type_.startswith(cls.__name__):
63
65
  type_ = cls
64
66
 
67
+ candidate: type
65
68
  if is_dataclass(type_):
66
- candidate = type_
69
+ candidate = type_ # type: ignore[assignment]
67
70
  elif isinstance(type_, GenericAlias) and type_.__origin__ is list and is_dataclass(type_.__args__[0]):
68
- candidate = type_.__args__[0]
71
+ candidate = type_.__args__[0] # type: ignore[assignment]
72
+
73
+ # this handles prefixes
74
+ elif isinstance(type_, GenericAlias) and type_.__origin__ is dict:
75
+ candidate = type_ # type: ignore[assignment]
69
76
  else:
70
77
  continue
71
78
 
72
- if hasattr(candidate, "_load"):
73
- output[field_.name] = candidate
79
+ output[field_.name] = candidate
80
+
74
81
  return output
75
82
 
76
83
  @classmethod
@@ -88,10 +95,16 @@ class InputRules(Generic[T_BaseRules], ABC):
88
95
  else:
89
96
  continue
90
97
 
91
- if isinstance(value, dict):
92
- args[field_name] = field_type._load(value) # type: ignore[attr-defined]
93
- elif isinstance(value, list) and value and isinstance(value[0], dict):
94
- args[field_name] = [field_type._load(item) for item in value] # type: ignore[attr-defined]
98
+ # Handles the case where the field is a dataclass
99
+ if hasattr(field_type, "_load"):
100
+ if isinstance(value, dict):
101
+ args[field_name] = field_type._load(value) # type: ignore[attr-defined]
102
+ elif isinstance(value, list) and value and isinstance(value[0], dict):
103
+ args[field_name] = [field_type._load(item) for item in value] # type: ignore[attr-defined]
104
+ # Handles the case where the field holds non-dataclass values, e.g. a prefixes dict
105
+ else:
106
+ args[field_name] = value
107
+
95
108
  return cls(**args)
96
109
 
97
110
  def _dataclass_fields(self) -> list[Field]:
@@ -114,6 +127,9 @@ class InputRules(Generic[T_BaseRules], ABC):
114
127
  return output
115
128
 
116
129
 
130
+ T_InputRules = TypeVar("T_InputRules", bound=InputRules)
131
+
132
+
117
133
  @dataclass
118
134
  class InputComponent(ABC, Generic[T_RuleModel]):
119
135
  @classmethod
@@ -160,3 +176,6 @@ class InputComponent(ABC, Generic[T_RuleModel]):
160
176
  for name, field_ in self._get_verified_cls().model_fields.items()
161
177
  if not field_.exclude
162
178
  }
179
+
180
+ def _repr_html_(self) -> str:
181
+ return pd.DataFrame([self.dump()])._repr_html_() # type: ignore[operator]
@@ -24,6 +24,8 @@ from pydantic import (
24
24
  from pydantic.main import IncEx
25
25
  from pydantic_core import core_schema
26
26
 
27
+ from cognite.neat._rules.models._types import ClassEntityType, InformationPropertyType
28
+
27
29
  if sys.version_info >= (3, 11):
28
30
  from enum import StrEnum
29
31
  from typing import Self
@@ -108,6 +110,14 @@ class SchemaModel(BaseModel):
108
110
  """Returns a set of mandatory fields for the model."""
109
111
  return _get_required_fields(cls, use_alias)
110
112
 
113
+ @field_validator("*", mode="before")
114
+ def strip_string(cls, value: Any) -> Any:
115
+ if isinstance(value, str):
116
+ return value.strip()
117
+ elif isinstance(value, list):
118
+ return [entry.strip() if isinstance(entry, str) else entry for entry in value]
119
+ return value
120
+
111
121
 
112
122
  class BaseMetadata(SchemaModel):
113
123
  """
@@ -200,7 +210,7 @@ class BaseRules(SchemaModel, ABC):
200
210
  as_reference: bool = False,
201
211
  mode: Literal["python", "json"] = "python",
202
212
  by_alias: bool = False,
203
- exclude: IncEx = None,
213
+ exclude: IncEx | None = None,
204
214
  exclude_none: bool = False,
205
215
  exclude_unset: bool = False,
206
216
  exclude_defaults: bool = False,
@@ -236,7 +246,7 @@ class BaseRules(SchemaModel, ABC):
236
246
  if entities_exclude_defaults:
237
247
  context["metadata"] = self.metadata
238
248
 
239
- exclude_input: IncEx
249
+ exclude_input: IncEx | None
240
250
  if self.reference is None:
241
251
  exclude_input = exclude
242
252
  else:
@@ -279,12 +289,6 @@ class BaseRules(SchemaModel, ABC):
279
289
 
280
290
 
281
291
  class SheetRow(SchemaModel):
282
- @field_validator("*", mode="before")
283
- def strip_string(cls, value: Any) -> Any:
284
- if isinstance(value, str):
285
- return value.strip()
286
- return value
287
-
288
292
  @abstractmethod
289
293
  def _identifier(self) -> tuple[Hashable, ...]:
290
294
  raise NotImplementedError()
@@ -346,3 +350,13 @@ ExtensionCategoryType = Annotated[
346
350
  ),
347
351
  BeforeValidator(lambda v: ExtensionCategory(v) if isinstance(v, str) else v),
348
352
  ]
353
+
354
+
355
+ # Immutable such that this can be used as a key in a dictionary
356
+ class PropertyRef(BaseModel, frozen=True):
357
+ class_: ClassEntityType = Field(alias="Class")
358
+ property_: InformationPropertyType = Field(alias="Property")
359
+
360
+
361
+ class ClassRef(BaseModel, frozen=True):
362
+ class_: ClassEntityType = Field(alias="Class")
@@ -8,7 +8,7 @@ from typing import ClassVar, Literal
8
8
 
9
9
  from pydantic import BaseModel, field_validator, model_serializer
10
10
 
11
- from cognite.neat.issues.errors import NeatValueError
11
+ from cognite.neat._issues.errors import NeatValueError
12
12
 
13
13
  if sys.version_info >= (3, 11):
14
14
  from enum import StrEnum