cognite-neat 0.92.3__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 +12 -8
  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 +7 -7
  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 +15 -6
  130. cognite/neat/{rules → _rules}/models/_base_rules.py +14 -2
  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 +26 -23
  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 +7 -4
  148. cognite/neat/{rules → _rules}/models/information/_rules.py +34 -22
  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.3.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.3.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.3.dist-info/RECORD +0 -224
  212. cognite_neat-0.92.3.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.3.dist-info → cognite_neat-0.93.0.dist-info}/LICENSE +0 -0
@@ -0,0 +1,61 @@
1
+ from collections.abc import Collection
2
+ from typing import Literal, cast
3
+
4
+ from cognite.client.data_classes.data_modeling import DataModelIdentifier
5
+
6
+ from cognite.neat._issues._base import IssueList
7
+ from cognite.neat._rules._shared import ReadRules
8
+ from cognite.neat._rules.models.information._rules_input import InformationInputRules
9
+ from cognite.neat._rules.transformers import ReduceCogniteModel, ToCompliantEntities, ToExtension
10
+
11
+ from ._state import SessionState
12
+
13
+
14
+ class PrepareAPI:
15
+ def __init__(self, state: SessionState, verbose: bool) -> None:
16
+ self._state = state
17
+ self._verbose = verbose
18
+ self.data_model = DataModelPrepareAPI(state, verbose)
19
+
20
+
21
+ class DataModelPrepareAPI:
22
+ def __init__(self, state: SessionState, verbose: bool) -> None:
23
+ self._state = state
24
+ self._verbose = verbose
25
+
26
+ def cdf_compliant_external_ids(self) -> None:
27
+ """Convert data model component external ids to CDF compliant entities."""
28
+ if input := self._state.information_input_rule:
29
+ output = ToCompliantEntities().transform(input)
30
+ self._state.input_rules.append(
31
+ ReadRules(
32
+ rules=cast(InformationInputRules, output.get_rules()),
33
+ issues=IssueList(),
34
+ read_context={},
35
+ )
36
+ )
37
+
38
+ def to_extension(self, new_data_model_id: DataModelIdentifier, org_name: str | None = None) -> None:
39
+ """Uses the current data model as a basis to extend from.
40
+
41
+ Args:
42
+ new_data_model_id: The new data model that is extending the current data model.
43
+ org_name: Organization name to use for the views in the new data model. This is required if you are
44
+ creating an extension from a Cognite Data Model.
45
+
46
+ """
47
+ if dms := self._state.last_verified_dms_rules:
48
+ output = ToExtension(new_data_model_id, org_name).transform(dms)
49
+ self._state.verified_rules.append(output.rules)
50
+
51
+ def reduce(self, drop: Collection[Literal["3D", "Annotation", "BaseViews"]]) -> None:
52
+ """This is a special method that allow you to drop parts of the data model.
53
+ This only applies to Cognite Data Models.
54
+
55
+ Args:
56
+ drop: Which parts of the data model to drop.
57
+
58
+ """
59
+ if dms := self._state.last_verified_dms_rules:
60
+ output = ReduceCogniteModel(drop).transform(dms)
61
+ self._state.verified_rules.append(output.rules)
@@ -0,0 +1,118 @@
1
+ from pathlib import Path
2
+ from typing import Any
3
+
4
+ from cognite.client import CogniteClient
5
+ from cognite.client.data_classes.data_modeling import DataModelIdentifier
6
+
7
+ from cognite.neat._graph import examples as instances_examples
8
+ from cognite.neat._graph import extractors
9
+ from cognite.neat._issues import IssueList
10
+ from cognite.neat._rules import importers
11
+ from cognite.neat._rules._shared import ReadRules
12
+
13
+ from ._state import SessionState
14
+ from ._wizard import NeatObjectType, RDFFileType, object_wizard, rdf_dm_wizard
15
+
16
+
17
+ class ReadAPI:
18
+ def __init__(self, state: SessionState, client: CogniteClient | None, verbose: bool) -> None:
19
+ self._state = state
20
+ self._verbose = verbose
21
+ self.cdf = CDFReadAPI(state, client, verbose)
22
+ self.rdf = RDFReadAPI(state, client, verbose)
23
+ self.excel = ExcelReadAPI(state, client, verbose)
24
+
25
+
26
+ class BaseReadAPI:
27
+ def __init__(self, state: SessionState, client: CogniteClient | None, verbose: bool) -> None:
28
+ self._state = state
29
+ self._verbose = verbose
30
+ self._client = client
31
+
32
+ def _store_rules(self, io: Any, input_rules: ReadRules, source: str) -> None:
33
+ if input_rules.rules:
34
+ self._state.input_rules.append(input_rules)
35
+ if self._verbose:
36
+ if input_rules.issues.has_errors:
37
+ print(f"{source} {type(io)} {io} read failed")
38
+ else:
39
+ print(f"{source} {type(io)} {io} read successfully")
40
+
41
+ def _return_filepath(self, io: Any) -> Path:
42
+ if isinstance(io, str):
43
+ return Path(io)
44
+ elif isinstance(io, Path):
45
+ return io
46
+ else:
47
+ raise ValueError(f"Expected str or Path, got {type(io)}")
48
+
49
+
50
+ class CDFReadAPI(BaseReadAPI):
51
+ def data_model(self, data_model_id: DataModelIdentifier) -> IssueList:
52
+ if self._client is None:
53
+ raise ValueError("No client provided. Please provide a client to read a data model.")
54
+
55
+ importer = importers.DMSImporter.from_data_model_id(self._client, data_model_id)
56
+ input_rules = importer.to_rules()
57
+ self._store_rules(data_model_id, input_rules, "CDF")
58
+ return input_rules.issues
59
+
60
+
61
+ class ExcelReadAPI(BaseReadAPI):
62
+ def __call__(self, io: Any) -> IssueList:
63
+ filepath = self._return_filepath(io)
64
+ input_rules: ReadRules = importers.ExcelImporter(filepath).to_rules()
65
+ self._store_rules(io, input_rules, "Excel")
66
+ return input_rules.issues
67
+
68
+
69
+ class RDFReadAPI(BaseReadAPI):
70
+ def __init__(self, state: SessionState, client: CogniteClient | None, verbose: bool) -> None:
71
+ super().__init__(state, client, verbose)
72
+ self.examples = RDFExamples(state)
73
+
74
+ def _ontology(self, io: Any) -> IssueList:
75
+ filepath = self._return_filepath(io)
76
+ input_rules: ReadRules = importers.OWLImporter.from_file(filepath).to_rules()
77
+ self._store_rules(io, input_rules, "Ontology")
78
+ return input_rules.issues
79
+
80
+ def _imf(self, io: Any) -> IssueList:
81
+ filepath = self._return_filepath(io)
82
+ input_rules: ReadRules = importers.IMFImporter.from_file(filepath).to_rules()
83
+ self._store_rules(io, input_rules, "IMF Types")
84
+ return input_rules.issues
85
+
86
+ def __call__(
87
+ self,
88
+ io: Any,
89
+ type: NeatObjectType | None = None,
90
+ source: RDFFileType | None = None,
91
+ ) -> IssueList:
92
+ if type is None:
93
+ type = object_wizard()
94
+
95
+ if type.lower() == "Data Model".lower():
96
+ source = source or rdf_dm_wizard("What type of data model is the RDF?")
97
+ if source == "Ontology":
98
+ return self._ontology(io)
99
+ elif source == "IMF":
100
+ return self._imf(io)
101
+ else:
102
+ raise ValueError(f"Expected ontology, imf or instances, got {source}")
103
+
104
+ elif type.lower() == "Instances".lower():
105
+ self._state.store.write(extractors.RdfFileExtractor(self._return_filepath(io)))
106
+ return IssueList()
107
+ else:
108
+ raise ValueError(f"Expected data model or instances, got {type}")
109
+
110
+
111
+ class RDFExamples:
112
+ def __init__(self, state: SessionState) -> None:
113
+ self._state = state
114
+
115
+ @property
116
+ def nordic44(self) -> IssueList:
117
+ self._state.store.write(extractors.RdfFileExtractor(instances_examples.nordic44_knowledge_graph))
118
+ return IssueList()
@@ -0,0 +1,96 @@
1
+ from typing import Any, cast
2
+
3
+ import networkx as nx
4
+ from ipycytoscape import CytoscapeWidget # type: ignore
5
+ from IPython.display import display
6
+
7
+ from cognite.neat._rules.models.dms._rules import DMSRules
8
+ from cognite.neat._rules.models.entities._single_value import ViewEntity
9
+
10
+ from ._state import SessionState
11
+
12
+
13
+ class ShowAPI:
14
+ def __init__(self, state: SessionState) -> None:
15
+ self._state = state
16
+ self.data_model = ShowDataModelAPI(self._state)
17
+
18
+
19
+ class ShowDataModelAPI:
20
+ def __init__(self, state: SessionState) -> None:
21
+ self._state = state
22
+
23
+ def __call__(self) -> Any:
24
+ if self._state.last_verified_dms_rules:
25
+ digraph = self._generate_dms_di_graph()
26
+ widget = self._generate_widget()
27
+ widget.graph.add_graph_from_networkx(digraph)
28
+ return display(widget)
29
+
30
+ def _generate_dms_di_graph(self) -> nx.DiGraph:
31
+ """Generate a DiGraph from the last verified DMS rules."""
32
+ G = nx.DiGraph()
33
+
34
+ nodes, edges = self._generate_dms_rules_nodes_and_edges()
35
+ G.add_nodes_from(nodes)
36
+ G.add_edges_from(edges)
37
+ for node in G.nodes:
38
+ G.nodes[node]["label"] = node
39
+
40
+ return G
41
+
42
+ def _generate_dms_rules_nodes_and_edges(self) -> tuple[list[str], list[tuple[str, str, dict]]]:
43
+ """Generate nodes and edges for the last verified DMS rules for DiGraph."""
44
+
45
+ nodes = []
46
+ edges = []
47
+
48
+ for prop_ in cast(DMSRules, self._state.last_verified_dms_rules).properties:
49
+ nodes.append(prop_.view.suffix)
50
+
51
+ if prop_.connection and isinstance(prop_.value_type, ViewEntity):
52
+ label = f"{prop_.property_} [{0 if prop_.nullable else 1}..{ '' if prop_.is_list else 1}]"
53
+ edges.append((prop_.view.suffix, prop_.value_type.suffix, {"label": label}))
54
+
55
+ for view in cast(DMSRules, self._state.last_verified_dms_rules).views:
56
+ nodes.append(view.view.suffix)
57
+
58
+ if view.implements:
59
+ for implement in view.implements:
60
+ edges.append((view.view.suffix, implement.suffix, {"label": "implements"}))
61
+
62
+ return nodes, edges
63
+
64
+ def _generate_widget(self):
65
+ """Generates an empty a CytoscapeWidget."""
66
+ widget = CytoscapeWidget()
67
+ widget.layout.height = "500px"
68
+
69
+ widget.set_style(
70
+ [
71
+ {
72
+ "selector": "node",
73
+ "css": {
74
+ "content": "data(label)",
75
+ "text-valign": "center",
76
+ "color": "black",
77
+ "background-color": "#33C4FF",
78
+ "font-size": "10px",
79
+ "width": "mapData(score, 0, 1, 10, 50)",
80
+ "height": "mapData(score, 0, 1, 10, 50)",
81
+ },
82
+ },
83
+ {
84
+ "selector": "edge",
85
+ "style": {
86
+ "width": 1,
87
+ "target-arrow-shape": "triangle",
88
+ "curve-style": "bezier",
89
+ "label": "data(label)",
90
+ "font-size": "8px",
91
+ },
92
+ },
93
+ ]
94
+ )
95
+
96
+ return widget
@@ -0,0 +1,69 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import Literal, cast
3
+
4
+ from cognite.neat._rules._shared import ReadRules, VerifiedRules
5
+ from cognite.neat._rules.models.dms._rules import DMSRules
6
+ from cognite.neat._rules.models.information._rules import InformationRules
7
+ from cognite.neat._rules.models.information._rules_input import InformationInputRules
8
+ from cognite.neat._store import NeatGraphStore
9
+
10
+ from .exceptions import NeatSessionError
11
+
12
+
13
+ @dataclass
14
+ class SessionState:
15
+ store_type: Literal["memory", "oxigraph"]
16
+ input_rules: list[ReadRules] = field(default_factory=list)
17
+ verified_rules: list[VerifiedRules] = field(default_factory=list)
18
+ _store: NeatGraphStore | None = field(init=False, default=None)
19
+
20
+ @property
21
+ def store(self) -> NeatGraphStore:
22
+ if not self.has_store:
23
+ if self.store_type == "oxigraph":
24
+ self._store = NeatGraphStore.from_oxi_store()
25
+ else:
26
+ self._store = NeatGraphStore.from_memory_store()
27
+ return cast(NeatGraphStore, self._store)
28
+
29
+ @property
30
+ def input_rule(self) -> ReadRules:
31
+ if not self.input_rules:
32
+ raise NeatSessionError("No input data model available. Try using [bold].read[/bold] to load a data model.")
33
+ return self.input_rules[-1]
34
+
35
+ @property
36
+ def information_input_rule(self) -> ReadRules | None:
37
+ if self.input_rules:
38
+ for rule in self.input_rules[::-1]:
39
+ if isinstance(rule.rules, InformationInputRules):
40
+ return rule
41
+ return None
42
+
43
+ @property
44
+ def last_verified_rule(self) -> VerifiedRules:
45
+ if not self.verified_rules:
46
+ raise NeatSessionError(
47
+ "No data model available to verify. Try using [bold].read[/bold] to load a data model."
48
+ )
49
+ return self.verified_rules[-1]
50
+
51
+ @property
52
+ def last_verified_dms_rules(self) -> DMSRules | None:
53
+ if self.verified_rules:
54
+ for rules in self.verified_rules[::-1]:
55
+ if isinstance(rules, DMSRules):
56
+ return rules
57
+ return None
58
+
59
+ @property
60
+ def last_verified_information_rules(self) -> InformationRules | None:
61
+ if self.verified_rules:
62
+ for rules in self.verified_rules[::-1]:
63
+ if isinstance(rules, InformationRules):
64
+ return rules
65
+ return None
66
+
67
+ @property
68
+ def has_store(self) -> bool:
69
+ return self._store is not None
@@ -0,0 +1,70 @@
1
+ from pathlib import Path
2
+ from typing import Any, overload
3
+
4
+ from cognite.client import CogniteClient
5
+
6
+ from cognite.neat._graph import loaders
7
+ from cognite.neat._rules import exporters
8
+ from cognite.neat._session._wizard import space_wizard
9
+
10
+ from ._state import SessionState
11
+
12
+
13
+ class ToAPI:
14
+ def __init__(self, state: SessionState, client: CogniteClient | None, verbose: bool) -> None:
15
+ self._state = state
16
+ self._verbose = verbose
17
+ self.cdf = CDFToAPI(state, client, verbose)
18
+
19
+ def excel(
20
+ self,
21
+ io: Any,
22
+ ) -> None:
23
+ exporter = exporters.ExcelExporter()
24
+ exporter.export_to_file(self._state.last_verified_rule, Path(io))
25
+ return None
26
+
27
+ @overload
28
+ def yaml(self, io: None) -> str: ...
29
+
30
+ @overload
31
+ def yaml(self, io: Any) -> None: ...
32
+
33
+ def yaml(self, io: Any | None = None) -> str | None:
34
+ exporter = exporters.YAMLExporter()
35
+ if io is None:
36
+ return exporter.export(self._state.last_verified_rule)
37
+
38
+ exporter.export_to_file(self._state.last_verified_rule, Path(io))
39
+ return None
40
+
41
+
42
+ class CDFToAPI:
43
+ def __init__(self, state: SessionState, client: CogniteClient | None, verbose: bool) -> None:
44
+ self._client = client
45
+ self._state = state
46
+ self._verbose = verbose
47
+
48
+ def instances(self, space: str | None = None):
49
+ if not self._state.last_verified_dms_rules:
50
+ raise ValueError("No verified DMS data model available")
51
+
52
+ loader = loaders.DMSLoader.from_rules(
53
+ self._state.last_verified_dms_rules, self._state.store, space_wizard(space=space)
54
+ )
55
+
56
+ if not self._client:
57
+ raise ValueError("No client provided!")
58
+
59
+ return loader.load_into_cdf(self._client)
60
+
61
+ def data_model(self):
62
+ if not self._state.last_verified_dms_rules:
63
+ raise ValueError("No verified DMS data model available")
64
+
65
+ exporter = exporters.DMSExporter()
66
+
67
+ if not self._client:
68
+ raise ValueError("No client provided!")
69
+
70
+ return exporter.export_to_cdf(self._state.last_verified_dms_rules, self._client)
@@ -0,0 +1,39 @@
1
+ from collections.abc import Sequence
2
+ from typing import Literal, TypeVar, get_args
3
+
4
+ from rich.prompt import IntPrompt, Prompt
5
+
6
+ from cognite.neat._rules._constants import PATTERNS
7
+
8
+ RDFFileType = Literal["Ontology", "IMF Types", "Inference"]
9
+ NeatObjectType = Literal["Data Model", "Instances"]
10
+
11
+
12
+ def object_wizard(message: str = "Select object") -> NeatObjectType:
13
+ return _selection(message, get_args(NeatObjectType))
14
+
15
+
16
+ def rdf_dm_wizard(message: str = "Select source:") -> RDFFileType:
17
+ return _selection(message, get_args(RDFFileType))
18
+
19
+
20
+ _T_Option = TypeVar("_T_Option")
21
+
22
+
23
+ def _selection(message: str, options: Sequence[_T_Option]) -> _T_Option:
24
+ option_text = "\n ".join([f"{i+1}) {option}" for i, option in enumerate(options)])
25
+ selected_index = (
26
+ IntPrompt().ask(f"{message}\n {option_text}\n", choices=list(map(str, range(1, len(options) + 1)))) - 1
27
+ )
28
+ return options[selected_index]
29
+
30
+
31
+ def space_wizard(message: str = "Set space", space: str | None = None) -> str:
32
+ while True:
33
+ user_input = space or Prompt().ask(f"{message}:")
34
+ if PATTERNS.space_compliance.match(str(user_input)):
35
+ return user_input
36
+ else:
37
+ print(f"Invalid input. Please provide a valid space name. {PATTERNS.space_compliance.pattern}")
38
+
39
+ space = ""
@@ -0,0 +1,42 @@
1
+ import functools
2
+ from collections.abc import Callable
3
+ from typing import Any
4
+
5
+ try:
6
+ from rich import print
7
+
8
+ _PREFIX = "[bold red][ERROR][/bold red]"
9
+ except ImportError:
10
+ _PREFIX = "[ERROR]"
11
+
12
+
13
+ class NeatSessionError(Exception):
14
+ """Base class for all exceptions raised by the NeatSession class."""
15
+
16
+ ...
17
+
18
+
19
+ def _intercept_session_exceptions(func: Callable):
20
+ @functools.wraps(func)
21
+ def wrapper(*args: Any, **kwargs: Any):
22
+ try:
23
+ return func(*args, **kwargs)
24
+ except NeatSessionError as e:
25
+ action = func.__name__
26
+ print(f"{_PREFIX} Cannot {action}: {e}")
27
+
28
+ return wrapper
29
+
30
+
31
+ def intercept_session_exceptions(cls: type):
32
+ to_check = [cls]
33
+ while to_check:
34
+ cls = to_check.pop()
35
+ for attr_name in dir(cls):
36
+ if not attr_name.startswith("_"):
37
+ attr = getattr(cls, attr_name)
38
+ if callable(attr):
39
+ setattr(cls, attr_name, _intercept_session_exceptions(attr))
40
+ elif isinstance(attr, type):
41
+ to_check.append(attr)
42
+ return cls
@@ -3,22 +3,22 @@ import warnings
3
3
  from collections.abc import Iterable
4
4
  from datetime import datetime, timezone
5
5
  from pathlib import Path
6
- from typing import cast
6
+ from typing import Any, cast
7
7
 
8
8
  import pandas as pd
9
+ from pandas import Index
9
10
  from rdflib import Graph, Namespace, URIRef
10
11
  from rdflib.plugins.stores.sparqlstore import SPARQLUpdateStore
11
12
 
12
- from cognite.neat.constants import DEFAULT_NAMESPACE
13
- from cognite.neat.graph._shared import MIMETypes
14
- from cognite.neat.graph.extractors import RdfFileExtractor, TripleExtractors
15
- from cognite.neat.graph.models import InstanceType, Triple
16
- from cognite.neat.graph.queries import Queries
17
- from cognite.neat.graph.transformers import Transformers
18
- from cognite.neat.rules.analysis import InformationAnalysis
19
- from cognite.neat.rules.models import InformationRules
20
- from cognite.neat.rules.models.entities import ClassEntity
21
- from cognite.neat.utils.auxiliary import local_import
13
+ from cognite.neat._constants import DEFAULT_NAMESPACE
14
+ from cognite.neat._graph.extractors import RdfFileExtractor, TripleExtractors
15
+ from cognite.neat._graph.models import InstanceType, Triple
16
+ from cognite.neat._graph.queries import Queries
17
+ from cognite.neat._graph.transformers import Transformers
18
+ from cognite.neat._rules.analysis import InformationAnalysis
19
+ from cognite.neat._rules.models import InformationRules
20
+ from cognite.neat._rules.models.entities import ClassEntity
21
+ from cognite.neat._utils.auxiliary import local_import
22
22
 
23
23
  from ._provenance import Change, Provenance
24
24
 
@@ -158,20 +158,29 @@ class NeatGraphStore:
158
158
 
159
159
  def write(self, extractor: TripleExtractors) -> None:
160
160
  _start = datetime.now(timezone.utc)
161
+ success = True
161
162
 
162
- if isinstance(extractor, RdfFileExtractor):
163
- self._parse_file(extractor.filepath, extractor.mime_type, extractor.base_uri)
163
+ if isinstance(extractor, RdfFileExtractor) and not extractor.issue_list.has_errors:
164
+ self._parse_file(extractor.filepath, cast(str, extractor.mime_type), extractor.base_uri)
165
+ elif isinstance(extractor, RdfFileExtractor):
166
+ success = False
167
+ issue_text = "\n".join([issue.as_message() for issue in extractor.issue_list])
168
+ warnings.warn(
169
+ f"Cannot write to graph store with {type(extractor).__name__}, errors found in file:\n{issue_text}",
170
+ stacklevel=2,
171
+ )
164
172
  else:
165
173
  self._add_triples(extractor.extract())
166
174
 
167
- self.provenance.append(
168
- Change.record(
169
- activity=f"{type(extractor).__name__}",
170
- start=_start,
171
- end=datetime.now(timezone.utc),
172
- description=f"Extracted triples to graph store using {type(extractor).__name__}",
175
+ if success:
176
+ self.provenance.append(
177
+ Change.record(
178
+ activity=f"{type(extractor).__name__}",
179
+ start=_start,
180
+ end=datetime.now(timezone.utc),
181
+ description=f"Extracted triples to graph store using {type(extractor).__name__}",
182
+ )
173
183
  )
174
- )
175
184
 
176
185
  def read(self, class_: str) -> Iterable[tuple[str, dict[str | InstanceType, list[str]]]]:
177
186
  """Read instances for given view from the graph store."""
@@ -234,7 +243,7 @@ class NeatGraphStore:
234
243
  def _parse_file(
235
244
  self,
236
245
  filepath: Path,
237
- mime_type: MIMETypes = "application/rdf+xml",
246
+ mime_type: str = "application/rdf+xml",
238
247
  base_uri: URIRef | None = None,
239
248
  ) -> None:
240
249
  """Imports graph data from file.
@@ -342,16 +351,38 @@ class NeatGraphStore:
342
351
  def _repr_html_(self) -> str:
343
352
  provenance = self.provenance._repr_html_()
344
353
  summary: pd.DataFrame = self.summary
345
- summary_text = (
346
- "<br /><strong>Graph is empty</strong><br />"
347
- if summary.empty
348
- else f"<br /><strong>Graph content</strong><br />{cast(pd.DataFrame, summary)._repr_html_()}" # type: ignore[operator]
349
- )
350
354
 
351
- return (
352
- f"<strong>{type(self).__name__}</strong> A graph store is a container for storing triples. "
353
- "It can be queried and transformed to extract information.<br />"
354
- "<strong>Provenance</strong> Provenance is a record of changes that have occurred in the graph store.<br />"
355
- f"{provenance}"
356
- f"{summary_text}"
355
+ if summary.empty:
356
+ summary_text = "<br /><strong>Graph is empty</strong><br />"
357
+ else:
358
+ summary_text = (
359
+ "<br /><strong>Overview</strong>:" # type: ignore
360
+ f"<ul><li>{len(summary)} types</strong></li>"
361
+ f"<li>{sum(summary['Occurrence'])} instances</strong></li></ul>"
362
+ f"{cast(pd.DataFrame, self._shorten_summary(summary))._repr_html_()}" # type: ignore[operator]
363
+ )
364
+
365
+ return f"{summary_text}" f"{provenance}"
366
+
367
+ def _shorten_summary(self, summary: pd.DataFrame) -> pd.DataFrame:
368
+ """Shorten summary to top 5 types by occurrence."""
369
+ top_5_rows = summary.head(5)
370
+ last_row = summary.tail(1)
371
+
372
+ indexes = [
373
+ *top_5_rows.index.tolist(),
374
+ "...",
375
+ *last_row.index.tolist(),
376
+ ]
377
+
378
+ shorter_summary = pd.concat(
379
+ [
380
+ top_5_rows,
381
+ pd.DataFrame([["..."] * summary.shape[1]], columns=summary.columns),
382
+ last_row,
383
+ ],
384
+ ignore_index=True,
357
385
  )
386
+ shorter_summary.index = cast(Index[Any], indexes)
387
+
388
+ return shorter_summary
@@ -15,8 +15,8 @@ from typing import TypeVar
15
15
 
16
16
  from rdflib import PROV, RDF, Literal, URIRef
17
17
 
18
+ from cognite.neat._constants import DEFAULT_NAMESPACE
18
19
  from cognite.neat._shared import FrozenNeatObject, NeatList
19
- from cognite.neat.constants import DEFAULT_NAMESPACE
20
20
 
21
21
 
22
22
  @dataclass(frozen=True)
@@ -114,3 +114,13 @@ class Provenance(NeatList[Change]):
114
114
 
115
115
  def __setitem__(self, *args, **kwargs):
116
116
  raise TypeError("Cannot modify change from provenance")
117
+
118
+ def _repr_html_(self) -> str:
119
+ text = "<br /><strong>Provenance</strong>:<ul>"
120
+
121
+ for change in self:
122
+ text += f"<li>{change.description}</li>"
123
+
124
+ text += "</ul>"
125
+
126
+ return text