cognite-neat 0.72.3__tar.gz → 0.73.1__tar.gz

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 (234) hide show
  1. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/PKG-INFO +2 -2
  2. cognite_neat-0.73.1/cognite/neat/_version.py +1 -0
  3. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/extractor/_dexpi.py +12 -4
  4. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/extractor/_graph_capturing_sheet.py +14 -12
  5. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/examples/power-grid-containers.yaml +3 -0
  6. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/examples/power-grid-model.yaml +3 -0
  7. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exporter/_rules2dms.py +3 -10
  8. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exporter/_rules2excel.py +3 -2
  9. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exporters/_rules2excel.py +94 -4
  10. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importer/_dms2rules.py +1 -4
  11. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importers/_dms2rules.py +40 -11
  12. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/issues/base.py +9 -1
  13. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/issues/dms.py +74 -0
  14. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/models/_rules/base.py +24 -2
  15. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/models/_rules/dms_architect_rules.py +123 -15
  16. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/models/_rules/dms_schema.py +5 -1
  17. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/models/_rules/domain_rules.py +14 -1
  18. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/models/_rules/information_rules.py +16 -2
  19. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/utils/spreadsheet.py +2 -2
  20. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/pyproject.toml +2 -2
  21. cognite_neat-0.72.3/cognite/neat/_version.py +0 -1
  22. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/LICENSE +0 -0
  23. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/README.md +0 -0
  24. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/__init__.py +0 -0
  25. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/api/__init__.py +0 -0
  26. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/api/asgi/metrics.py +0 -0
  27. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/api/configuration.py +0 -0
  28. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/api/context_manager/__init__.py +0 -0
  29. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/api/context_manager/manager.py +0 -0
  30. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/api/data_classes/__init__.py +0 -0
  31. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/api/data_classes/configuration.py +0 -0
  32. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/api/data_classes/rest.py +0 -0
  33. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/api/explorer.py +0 -0
  34. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/api/routers/configuration.py +0 -0
  35. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/api/routers/core.py +0 -0
  36. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/api/routers/crud.py +0 -0
  37. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/api/routers/data_exploration.py +0 -0
  38. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/api/routers/metrics.py +0 -0
  39. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/api/routers/rules.py +0 -0
  40. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/api/routers/workflows.py +0 -0
  41. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/api/utils/__init__.py +0 -0
  42. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/api/utils/data_mapping.py +0 -0
  43. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/api/utils/logging.py +0 -0
  44. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/api/utils/query_templates.py +0 -0
  45. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/main.py +0 -0
  46. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/monitoring/__init__.py +0 -0
  47. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/monitoring/metrics.py +0 -0
  48. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/ui/index.html +0 -0
  49. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/ui/neat-app/.gitignore +0 -0
  50. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/ui/neat-app/README.md +0 -0
  51. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/ui/neat-app/build/asset-manifest.json +0 -0
  52. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/ui/neat-app/build/favicon.ico +0 -0
  53. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/ui/neat-app/build/index.html +0 -0
  54. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/ui/neat-app/build/logo192.png +0 -0
  55. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/ui/neat-app/build/manifest.json +0 -0
  56. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/ui/neat-app/build/robots.txt +0 -0
  57. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/ui/neat-app/build/static/css/main.38a62222.css +0 -0
  58. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/ui/neat-app/build/static/css/main.38a62222.css.map +0 -0
  59. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/ui/neat-app/build/static/js/main.2efd96b2.js +0 -0
  60. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/ui/neat-app/build/static/js/main.2efd96b2.js.LICENSE.txt +0 -0
  61. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/ui/neat-app/build/static/js/main.2efd96b2.js.map +0 -0
  62. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/app/ui/neat-app/build/static/media/logo.8093b84df9ed36a174c629d6fe0b730d.svg +0 -0
  63. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/config.py +0 -0
  64. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/constants.py +0 -0
  65. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/exceptions.py +0 -0
  66. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/__init__.py +0 -0
  67. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/examples/Knowledge-Graph-Nordic44-dirty.xml +0 -0
  68. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/examples/Knowledge-Graph-Nordic44.xml +0 -0
  69. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/examples/__init__.py +0 -0
  70. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/examples/skos-capturing-sheet-wind-topics.xlsx +0 -0
  71. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/exceptions.py +0 -0
  72. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/extractor/__init__.py +0 -0
  73. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/extractor/_base.py +0 -0
  74. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/extractor/_mock_graph_generator.py +0 -0
  75. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/extractors/__init__.py +0 -0
  76. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/extractors/_base.py +0 -0
  77. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/extractors/_mock_graph_generator.py +0 -0
  78. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/loader/__init__.py +0 -0
  79. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/loader/_asset_loader.py +0 -0
  80. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/loader/_base.py +0 -0
  81. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/loader/_exceptions.py +0 -0
  82. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/loader/core/__init__.py +0 -0
  83. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/loader/core/labels.py +0 -0
  84. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/loader/core/models.py +0 -0
  85. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/loader/core/rdf_to_assets.py +0 -0
  86. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/loader/core/rdf_to_relationships.py +0 -0
  87. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/loader/rdf_to_dms.py +0 -0
  88. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/loader/validator.py +0 -0
  89. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/models.py +0 -0
  90. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/stores/__init__.py +0 -0
  91. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/stores/_base.py +0 -0
  92. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/stores/_graphdb_store.py +0 -0
  93. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/stores/_memory_store.py +0 -0
  94. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/stores/_oxigraph_store.py +0 -0
  95. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/stores/_oxrdflib.py +0 -0
  96. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/stores/_rdf_to_graph.py +0 -0
  97. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/transformation/__init__.py +0 -0
  98. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/transformation/entity_matcher.py +0 -0
  99. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/transformation/query_generator/__init__.py +0 -0
  100. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/transformation/query_generator/sparql.py +0 -0
  101. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/graph/transformation/transformer.py +0 -0
  102. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/py.typed +0 -0
  103. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/__init__.py +0 -0
  104. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/_analysis/__init__.py +0 -0
  105. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/_analysis/_base.py +0 -0
  106. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/_analysis/_information_rules.py +0 -0
  107. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/_shared.py +0 -0
  108. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/analysis.py +0 -0
  109. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/examples/Rules-Nordic44-to-TNT.xlsx +0 -0
  110. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/examples/Rules-Nordic44-to-graphql.xlsx +0 -0
  111. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/examples/__init__.py +0 -0
  112. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/examples/power-grid-example.xlsx +0 -0
  113. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/examples/rules-template.xlsx +0 -0
  114. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/examples/sheet2cdf-transformation-rules.xlsx +0 -0
  115. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/examples/skos-rules.xlsx +0 -0
  116. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/examples/source-to-solution-mapping-rules.xlsx +0 -0
  117. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/examples/wind-energy.owl +0 -0
  118. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exceptions.py +0 -0
  119. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exporter/__init__.py +0 -0
  120. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exporter/_base.py +0 -0
  121. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exporter/_core/__init__.py +0 -0
  122. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exporter/_core/rules2labels.py +0 -0
  123. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exporter/_rules2graphql.py +0 -0
  124. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exporter/_rules2ontology.py +0 -0
  125. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exporter/_rules2pydantic_models.py +0 -0
  126. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exporter/_rules2rules.py +0 -0
  127. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exporter/_rules2triples.py +0 -0
  128. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exporter/_validation.py +0 -0
  129. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exporters/__init__.py +0 -0
  130. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exporters/_base.py +0 -0
  131. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exporters/_models.py +0 -0
  132. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exporters/_rules2dms.py +0 -0
  133. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exporters/_rules2ontology.py +0 -0
  134. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exporters/_rules2yaml.py +0 -0
  135. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/exporters/_validation.py +0 -0
  136. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importer/__init__.py +0 -0
  137. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importer/_base.py +0 -0
  138. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importer/_dict2rules.py +0 -0
  139. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importer/_graph2rules.py +0 -0
  140. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importer/_json2rules.py +0 -0
  141. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importer/_owl2rules/__init__.py +0 -0
  142. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importer/_owl2rules/_owl2classes.py +0 -0
  143. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importer/_owl2rules/_owl2metadata.py +0 -0
  144. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importer/_owl2rules/_owl2properties.py +0 -0
  145. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importer/_owl2rules/_owl2rules.py +0 -0
  146. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importer/_spreadsheet2rules.py +0 -0
  147. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importer/_xsd2rules.py +0 -0
  148. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importer/_yaml2rules.py +0 -0
  149. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importers/__init__.py +0 -0
  150. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importers/_base.py +0 -0
  151. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importers/_dtdl2rules/__init__.py +0 -0
  152. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importers/_dtdl2rules/_unit_lookup.py +0 -0
  153. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importers/_dtdl2rules/dtdl_converter.py +0 -0
  154. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importers/_dtdl2rules/dtdl_importer.py +0 -0
  155. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importers/_dtdl2rules/spec.py +0 -0
  156. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importers/_owl2rules/__init__.py +0 -0
  157. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importers/_owl2rules/_owl2classes.py +0 -0
  158. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importers/_owl2rules/_owl2metadata.py +0 -0
  159. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importers/_owl2rules/_owl2properties.py +0 -0
  160. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importers/_owl2rules/_owl2rules.py +0 -0
  161. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importers/_spreadsheet2rules.py +0 -0
  162. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/importers/_yaml2rules.py +0 -0
  163. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/issues/__init__.py +0 -0
  164. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/issues/fileread.py +0 -0
  165. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/issues/formatters.py +0 -0
  166. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/issues/importing.py +0 -0
  167. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/issues/spreadsheet.py +0 -0
  168. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/issues/spreadsheet_file.py +0 -0
  169. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/models/__init__.py +0 -0
  170. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/models/_base.py +0 -0
  171. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/models/_rules/__init__.py +0 -0
  172. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/models/_rules/_types/__init__.py +0 -0
  173. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/models/_rules/_types/_base.py +0 -0
  174. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/models/_rules/_types/_field.py +0 -0
  175. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/models/_rules/_types/_value.py +0 -0
  176. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/models/raw_rules.py +0 -0
  177. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/models/rdfpath.py +0 -0
  178. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/models/rules.py +0 -0
  179. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/models/tables.py +0 -0
  180. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/rules/models/value_types.py +0 -0
  181. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/utils/__init__.py +0 -0
  182. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/utils/auxiliary.py +0 -0
  183. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/utils/cdf.py +0 -0
  184. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/utils/cdf_loaders/__init__.py +0 -0
  185. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/utils/cdf_loaders/_base.py +0 -0
  186. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/utils/cdf_loaders/_data_modeling.py +0 -0
  187. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/utils/cdf_loaders/_ingestion.py +0 -0
  188. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/utils/cdf_loaders/data_classes.py +0 -0
  189. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/utils/exceptions.py +0 -0
  190. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/utils/text.py +0 -0
  191. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/utils/utils.py +0 -0
  192. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/utils/xml.py +0 -0
  193. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/__init__.py +0 -0
  194. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/_exceptions.py +0 -0
  195. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/base.py +0 -0
  196. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/cdf_store.py +0 -0
  197. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/examples/Export DMS/workflow.yaml +0 -0
  198. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/examples/Export Rules to Ontology/workflow.yaml +0 -0
  199. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/examples/Extract DEXPI Graph and Export Rules/workflow.yaml +0 -0
  200. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/examples/Extract RDF Graph and Generate Assets/workflow.yaml +0 -0
  201. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/examples/Import DMS/workflow.yaml +0 -0
  202. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/examples/Ontology to Data Model/workflow.yaml +0 -0
  203. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/examples/Validate Rules/workflow.yaml +0 -0
  204. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/examples/Validate Solution Model/workflow.yaml +0 -0
  205. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/examples/Visualize Data Model Using Mock Graph/workflow.yaml +0 -0
  206. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/examples/Visualize Semantic Data Model/workflow.yaml +0 -0
  207. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/manager.py +0 -0
  208. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/migration/__init__.py +0 -0
  209. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/migration/steps.py +0 -0
  210. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/migration/wf_manifests.py +0 -0
  211. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/model.py +0 -0
  212. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/steps/__init__.py +0 -0
  213. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/steps/data_contracts.py +0 -0
  214. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/steps/lib/__init__.py +0 -0
  215. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/steps/lib/graph_extractor.py +0 -0
  216. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/steps/lib/graph_loader.py +0 -0
  217. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/steps/lib/graph_store.py +0 -0
  218. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/steps/lib/io_steps.py +0 -0
  219. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/steps/lib/rules_exporter.py +0 -0
  220. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/steps/lib/rules_importer.py +0 -0
  221. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/steps/lib/rules_validator.py +0 -0
  222. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/steps/lib/v1/__init__.py +0 -0
  223. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/steps/lib/v1/graph_contextualization.py +0 -0
  224. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/steps/lib/v1/graph_extractor.py +0 -0
  225. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/steps/lib/v1/graph_loader.py +0 -0
  226. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/steps/lib/v1/graph_store.py +0 -0
  227. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/steps/lib/v1/graph_transformer.py +0 -0
  228. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/steps/lib/v1/rules_exporter.py +0 -0
  229. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/steps/lib/v1/rules_importer.py +0 -0
  230. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/steps/step_model.py +0 -0
  231. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/steps_registry.py +0 -0
  232. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/tasks.py +0 -0
  233. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/triggers.py +0 -0
  234. {cognite_neat-0.72.3 → cognite_neat-0.73.1}/cognite/neat/workflows/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cognite-neat
3
- Version: 0.72.3
3
+ Version: 0.73.1
4
4
  Summary: Knowledge graph transformation
5
5
  Home-page: https://cognite-neat.readthedocs-hosted.com/
6
6
  License: Apache-2.0
@@ -19,7 +19,7 @@ Provides-Extra: graphql
19
19
  Provides-Extra: oxi
20
20
  Requires-Dist: PyYAML
21
21
  Requires-Dist: backports.strenum (>=1.2,<2.0) ; python_version < "3.11"
22
- Requires-Dist: cognite-sdk (>=7.28.2,<8.0.0)
22
+ Requires-Dist: cognite-sdk (>=7.37.0,<8.0.0)
23
23
  Requires-Dist: deepdiff
24
24
  Requires-Dist: exceptiongroup (>=1.1.3,<2.0.0) ; python_version < "3.11"
25
25
  Requires-Dist: fastapi (>=0.100,<0.101)
@@ -0,0 +1 @@
1
+ __version__ = "0.73.1"
@@ -103,6 +103,10 @@ def _add_node_label(id_: str, nodes: dict, element: Element) -> dict:
103
103
  if grandchildren := get_children(children[0], "Text", 1):
104
104
  if "String" in grandchildren[0].attrib:
105
105
  nodes[id_]["header"]["label"] = grandchildren[0].attrib["String"]
106
+ # extension for schema version 3.3, where text is used to "label" without a <label> parent
107
+ elif children := get_children(element, "Text", 1):
108
+ if "String" in children[0].attrib:
109
+ nodes[id_]["header"]["label"] = children[0].attrib["String"]
106
110
 
107
111
  return nodes
108
112
 
@@ -111,10 +115,14 @@ def _add_node_generic_attributes(id_: str, nodes: dict, element: Element) -> dic
111
115
  if children := get_children(element, "GenericAttributes", 1):
112
116
  if grandchildren := get_children(children[0], "GenericAttribute"):
113
117
  for generic_attribute in grandchildren:
114
- if generic_attribute.attrib["AttributeURI"] not in nodes[id_]:
115
- nodes[id_]["attributes"][generic_attribute.attrib["AttributeURI"]] = [generic_attribute.attrib]
116
- else:
117
- nodes[id_]["attributes"][generic_attribute.attrib["AttributeURI"]].append(generic_attribute.attrib)
118
+ # extension for schema version 3.3, where "AttributeURI" is not included
119
+ if "AttributeURI" in generic_attribute.attrib:
120
+ if generic_attribute.attrib["AttributeURI"] not in nodes[id_]:
121
+ nodes[id_]["attributes"][generic_attribute.attrib["AttributeURI"]] = [generic_attribute.attrib]
122
+ else:
123
+ nodes[id_]["attributes"][generic_attribute.attrib["AttributeURI"]].append(
124
+ generic_attribute.attrib
125
+ )
118
126
 
119
127
  return nodes
120
128
 
@@ -11,6 +11,7 @@ from openpyxl.cell import Cell
11
11
  from openpyxl.styles import Alignment, Border, Font, NamedStyle, PatternFill, Side
12
12
  from openpyxl.utils import get_column_letter
13
13
  from openpyxl.worksheet.datavalidation import DataValidation
14
+ from openpyxl.worksheet.worksheet import Worksheet
14
15
  from rdflib import RDF, XSD, Literal, Namespace, URIRef
15
16
 
16
17
  from cognite.neat.graph import exceptions
@@ -321,7 +322,7 @@ def rules2graph_capturing_sheet(
321
322
  workbook.create_sheet(title=class_)
322
323
 
323
324
  # Add header rows
324
- workbook[class_].append(["identifier", *list(properties.keys())])
325
+ cast(Worksheet, workbook[class_]).append(["identifier", *list(properties.keys())])
325
326
 
326
327
  if auto_identifier_type and auto_identifier_type == "index-based": # default, easy to read
327
328
  logging.debug(f"Configuring index-based automatic identifiers for sheet {class_}")
@@ -350,35 +351,35 @@ def _add_index_identifiers(workbook: Workbook, sheet: str, no_rows: int):
350
351
  """Adds index-based auto identifier to a sheet identifier column"""
351
352
  for i in range(no_rows):
352
353
  prefix = to_dms_name(sheet, "class", True)
353
- workbook[sheet][f"A{i+2}"] = f'=IF(ISBLANK(B{i+2}), "","{prefix}-{i+1}")'
354
+ workbook[sheet][f"A{i+2}"] = f'=IF(ISBLANK(B{i+2}), "","{prefix}-{i+1}")' # type: ignore[index]
354
355
 
355
356
 
356
357
  def _add_uuid_identifiers(workbook: Workbook, sheet: str, no_rows: int):
357
358
  """Adds UUID-based auto identifier to a sheet identifier column"""
358
359
  for i in range(no_rows):
359
360
  prefix = to_dms_name(sheet, "class", True)
360
- workbook[sheet][f"A{i+2}"] = f'=IF(ISBLANK(B{i+2}), "","{prefix}-{uuid.uuid4()}")'
361
+ workbook[sheet][f"A{i+2}"] = f'=IF(ISBLANK(B{i+2}), "","{prefix}-{uuid.uuid4()}")' # type: ignore[index]
361
362
 
362
363
 
363
364
  def _add_drop_down_list(workbook: Workbook, sheet: str, column: str, no_rows: int, value_sheet: str, value_column: str):
364
365
  """Adds a drop down list to a column"""
365
366
  drop_down_list = DataValidation(type="list", formula1=f"={value_sheet}!{value_column}$2:{value_column}${no_rows}")
366
367
 
367
- workbook[sheet].add_data_validation(drop_down_list)
368
+ cast(Worksheet, workbook[sheet]).add_data_validation(drop_down_list)
368
369
 
369
370
  for i in range(no_rows):
370
- drop_down_list.add(workbook[sheet][f"{column}{i+2}"])
371
+ drop_down_list.add(workbook[sheet][f"{column}{i+2}"]) # type: ignore[index, misc]
371
372
 
372
373
 
373
374
  def _adjust_column_width(workbook: Workbook):
374
375
  """Adjusts the column width based on the content"""
375
376
  for sheet in workbook.sheetnames:
376
- for cell_tuple in workbook[sheet].columns:
377
+ for cell_tuple in cast(Worksheet, workbook[sheet]).columns:
377
378
  # Wrong type annotation in openpyxl
378
379
  cell = cast(Cell, cell_tuple[0]) # type: ignore[index]
379
380
  if cell.value:
380
381
  adjusted_width = (len(str(cell.value)) + 5) * 1.2
381
- workbook[sheet].column_dimensions[cell.column_letter].width = adjusted_width
382
+ cast(Worksheet, workbook[sheet]).column_dimensions[cell.column_letter].width = adjusted_width
382
383
 
383
384
 
384
385
  def _set_header_style(workbook: Workbook):
@@ -390,12 +391,13 @@ def _set_header_style(workbook: Workbook):
390
391
  workbook.add_named_style(style)
391
392
 
392
393
  for sheet in workbook.sheetnames:
393
- for cell_tuple in workbook[sheet].columns:
394
+ for cell_tuple in cast(Worksheet, workbook[sheet]).columns:
394
395
  # Wrong type annotation in openpyxl
395
396
  cell = cast(Cell, cell_tuple[0]) # type: ignore[index]
396
- workbook[sheet][f"{cell.column_letter}1"].style = style
397
+ worksheet = cast(Worksheet, workbook[sheet])
398
+ worksheet[f"{cell.column_letter}1"].style = style
397
399
  if f"{cell.column_letter}1" == "A1":
398
- workbook[sheet][f"{cell.column_letter}1"].fill = PatternFill("solid", start_color="2FB5F2")
400
+ worksheet[f"{cell.column_letter}1"].fill = PatternFill("solid", start_color="2FB5F2")
399
401
  else:
400
- workbook[sheet][f"{cell.column_letter}1"].fill = PatternFill("solid", start_color="FFB202")
401
- workbook[sheet][f"{cell.column_letter}1"].alignment = Alignment(horizontal="center", vertical="center")
402
+ worksheet[f"{cell.column_letter}1"].fill = PatternFill("solid", start_color="FFB202")
403
+ worksheet[f"{cell.column_letter}1"].alignment = Alignment(horizontal="center", vertical="center")
@@ -53,6 +53,7 @@
53
53
  type:
54
54
  container: null
55
55
  type: direct
56
+ list: false
56
57
  space: workshop
57
58
  usedFor: node
58
59
  - externalId: SubGeographicalRegion
@@ -81,6 +82,7 @@
81
82
  type:
82
83
  container: null
83
84
  type: direct
85
+ list: false
84
86
  space: workshop
85
87
  usedFor: node
86
88
  - externalId: Substation
@@ -109,5 +111,6 @@
109
111
  type:
110
112
  container: null
111
113
  type: direct
114
+ list: false
112
115
  space: workshop
113
116
  usedFor: node
@@ -81,6 +81,7 @@ views:
81
81
  type:
82
82
  container: null
83
83
  type: direct
84
+ list: false
84
85
  source:
85
86
  space: workshop
86
87
  externalId: GeographicalRegion
@@ -132,6 +133,7 @@ views:
132
133
  type:
133
134
  container: null
134
135
  type: direct
136
+ list: false
135
137
  source:
136
138
  space: workshop
137
139
  externalId: SubGeographicalRegion
@@ -195,6 +197,7 @@ views:
195
197
  type:
196
198
  container: null
197
199
  type: direct
200
+ list: false
198
201
  source:
199
202
  space: workshop
200
203
  externalId: Substation
@@ -34,7 +34,6 @@ from cognite.client.data_classes.data_modeling import (
34
34
  ViewApply,
35
35
  ViewId,
36
36
  )
37
- from cognite.client.data_classes.data_modeling.data_types import ListablePropertyType
38
37
  from cognite.client.data_classes.data_modeling.views import (
39
38
  ConnectionDefinitionApply,
40
39
  SingleHopConnectionDefinitionApply,
@@ -284,12 +283,9 @@ class DMSSchemaComponents(BaseModel):
284
283
  if (
285
284
  not isinstance(existing_property.type, DirectRelation)
286
285
  and not isinstance(api_container_property.type, DirectRelation)
287
- and cast(ListablePropertyType, existing_property.type).is_list
288
- != cast(ListablePropertyType, api_container_property.type).is_list
286
+ and existing_property.type.is_list != api_container_property.type.is_list
289
287
  ):
290
- cast(
291
- ListablePropertyType, containers[container_id].properties[container_property_id].type
292
- ).is_list = True
288
+ containers[container_id].properties[container_property_id].type.is_list = True
293
289
 
294
290
  if errors:
295
291
  raise ExceptionGroup("Properties value types have been redefined! This is prohibited! Aborting!", errors)
@@ -302,10 +298,7 @@ class DMSSchemaComponents(BaseModel):
302
298
 
303
299
  # Literal, i.e. Node attribute
304
300
  if property_.property_type is EntityTypes.data_property:
305
- property_type = cast(
306
- type[ListablePropertyType],
307
- cast(ValueTypeMapping, property_.expected_value_type.mapping).dms,
308
- )
301
+ property_type = cast(ValueTypeMapping, property_.expected_value_type.mapping).dms
309
302
  return ContainerProperty(
310
303
  type=property_type(is_list=is_one_to_many),
311
304
  nullable=property_.min_count == 0,
@@ -4,6 +4,7 @@ from typing import cast
4
4
  from openpyxl import Workbook
5
5
  from openpyxl.cell import Cell
6
6
  from openpyxl.styles import Alignment, Border, Font, NamedStyle, PatternFill, Side
7
+ from openpyxl.worksheet.worksheet import Worksheet
7
8
 
8
9
  from cognite.neat.rules.models._base import EntityTypes
9
10
 
@@ -190,7 +191,7 @@ class ExcelExporter(BaseExporter[Workbook]):
190
191
  if sheet == "Metadata":
191
192
  continue
192
193
  if sheet == "Classes" or sheet == "Properties":
193
- sheet_obj = data[sheet]
194
+ sheet_obj = cast(Worksheet, data[sheet])
194
195
  if sheet == "Classes":
195
196
  sheet_obj.freeze_panes = "A3"
196
197
  else:
@@ -207,6 +208,6 @@ class ExcelExporter(BaseExporter[Workbook]):
207
208
  cell.fill = PatternFill("solid", start_color="D5DBD5")
208
209
  cell.alignment = Alignment(horizontal="center", vertical="center")
209
210
  adjusted_width = (len(str(cell.value)) + 5) * 1.2
210
- data[sheet].column_dimensions[cell.column_letter].width = adjusted_width
211
+ cast(Worksheet, data[sheet]).column_dimensions[cell.column_letter].width = adjusted_width
211
212
 
212
213
  return data
@@ -1,16 +1,19 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import itertools
4
+ from datetime import datetime
4
5
  from pathlib import Path
5
6
  from types import GenericAlias
6
- from typing import Any, ClassVar, Literal, get_args
7
+ from typing import Any, ClassVar, Literal, cast, get_args
7
8
 
8
9
  from openpyxl import Workbook
9
10
  from openpyxl.cell import MergedCell
10
11
  from openpyxl.styles import Alignment, Border, Font, PatternFill, Side
12
+ from openpyxl.worksheet.worksheet import Worksheet
11
13
 
12
14
  from cognite.neat.rules._shared import Rules
13
- from cognite.neat.rules.models._rules.base import RoleTypes, SheetEntity
15
+ from cognite.neat.rules.models._rules import DMSRules, DomainRules, InformationRules
16
+ from cognite.neat.rules.models._rules.base import RoleTypes, SchemaCompleteness, SheetEntity
14
17
 
15
18
  from ._base import BaseExporter
16
19
 
@@ -23,6 +26,9 @@ class ExcelExporter(BaseExporter[Workbook]):
23
26
  on the different styles.
24
27
  output_role: The role to use for the exported spreadsheet. If provided, the rules will be converted to
25
28
  this role formate before being written to excel. If not provided, the role from the rules will be used.
29
+ new_model_id: The new model ID to use for the exported spreadsheet. This is only applicable if the input
30
+ rules have 'is_reference' set. If provided, the model ID will be used to automatically create the
31
+ new metadata sheet in the Excel file.
26
32
 
27
33
  The following styles are available:
28
34
 
@@ -43,12 +49,18 @@ class ExcelExporter(BaseExporter[Workbook]):
43
49
  }
44
50
  style_options = get_args(Style)
45
51
 
46
- def __init__(self, styling: Style = "default", output_role: RoleTypes | None = None):
52
+ def __init__(
53
+ self,
54
+ styling: Style = "default",
55
+ output_role: RoleTypes | None = None,
56
+ new_model_id: tuple[str, str, str] | None = None,
57
+ ):
47
58
  if styling not in self.style_options:
48
59
  raise ValueError(f"Invalid styling: {styling}. Valid options are {self.style_options}")
49
60
  self.styling = styling
50
61
  self._styling_level = self.style_options.index(styling)
51
62
  self.output_role = output_role
63
+ self.new_model_id = new_model_id
52
64
 
53
65
  def export_to_file(self, rules: Rules, filepath: Path) -> None:
54
66
  """Exports transformation rules to excel file."""
@@ -70,7 +82,7 @@ class ExcelExporter(BaseExporter[Workbook]):
70
82
  if rules.is_reference:
71
83
  # Writes empty reference sheets
72
84
  dumped_rules = {
73
- "Metadata": {field_alias: None for field_alias in rules.metadata.model_dump(by_alias=True).keys()},
85
+ "Metadata": self._create_metadata_sheet_user_rules(rules),
74
86
  }
75
87
  dumped_rules["Metadata"]["role"] = (
76
88
  self.output_role and self.output_role.value
@@ -155,6 +167,12 @@ class ExcelExporter(BaseExporter[Workbook]):
155
167
  cell.font = Font(bold=True, size=14)
156
168
 
157
169
  def _write_metadata_sheet(self, workbook: Workbook, metadata: dict[str, Any], is_reference: bool = False) -> None:
170
+ # Excel does not support timezone in datetime strings
171
+ if isinstance(metadata.get("created"), datetime):
172
+ metadata["created"] = metadata["created"].replace(tzinfo=None)
173
+ if isinstance(metadata.get("updated"), datetime):
174
+ metadata["updated"] = metadata["updated"].replace(tzinfo=None)
175
+
158
176
  if is_reference:
159
177
  metadata_sheet = workbook.create_sheet("RefMetadata")
160
178
  else:
@@ -181,6 +199,7 @@ class ExcelExporter(BaseExporter[Workbook]):
181
199
  @classmethod
182
200
  def _adjust_column_widths(cls, workbook: Workbook) -> None:
183
201
  for sheet in workbook:
202
+ sheet = cast(Worksheet, sheet)
184
203
  for column_cells in sheet.columns:
185
204
  try:
186
205
  max_length = max(len(str(cell.value)) for cell in column_cells if cell.value is not None)
@@ -194,3 +213,74 @@ class ExcelExporter(BaseExporter[Workbook]):
194
213
  current = sheet.column_dimensions[selected_column.column_letter].width or (max_length + 0.5)
195
214
  sheet.column_dimensions[selected_column.column_letter].width = max(current, max_length + 0.5)
196
215
  return None
216
+
217
+ def _create_metadata_sheet_user_rules(self, rules: Rules) -> dict[str, Any]:
218
+ metadata: dict[str, Any] = {
219
+ field_alias: None for field_alias in rules.metadata.model_dump(by_alias=True).keys()
220
+ }
221
+ if "creator" in metadata:
222
+ metadata["creator"] = "YOUR NAME"
223
+
224
+ if isinstance(rules, DomainRules):
225
+ return metadata
226
+ elif isinstance(rules, DMSRules):
227
+ existing_model_id = (rules.metadata.space, rules.metadata.external_id, rules.metadata.version)
228
+ elif isinstance(rules, InformationRules):
229
+ existing_model_id = (rules.metadata.prefix, rules.metadata.name, rules.metadata.version)
230
+ else:
231
+ raise ValueError(f"Unsupported rules type: {type(rules)}")
232
+ existing_metadata = rules.metadata.model_dump(by_alias=True)
233
+ if isinstance(existing_metadata["created"], datetime):
234
+ metadata["created"] = existing_metadata["created"].replace(tzinfo=None)
235
+ if isinstance(existing_metadata["updated"], datetime):
236
+ metadata["updated"] = existing_metadata["updated"].replace(tzinfo=None)
237
+ # Excel does not support timezone in datetime strings
238
+ now_iso = datetime.now().replace(tzinfo=None).isoformat()
239
+ is_info = isinstance(rules, InformationRules)
240
+ is_dms = not is_info
241
+ is_extension = self.new_model_id is not None
242
+ is_solution = is_extension and self.new_model_id != existing_model_id
243
+
244
+ if is_solution:
245
+ metadata["prefix" if is_info else "space"] = self.new_model_id[0] # type: ignore[index]
246
+ metadata["title" if is_info else "externalId"] = self.new_model_id[1] # type: ignore[index]
247
+ metadata["version"] = self.new_model_id[2] # type: ignore[index]
248
+ else:
249
+ metadata["prefix" if is_info else "space"] = existing_model_id[0]
250
+ metadata["title" if is_info else "externalId"] = existing_model_id[1]
251
+ metadata["version"] = existing_model_id[2]
252
+
253
+ if is_solution and is_info:
254
+ metadata["namespace"] = f"http://purl.org/{self.new_model_id[0]}/" # type: ignore[index]
255
+ elif is_info:
256
+ metadata["namespace"] = existing_metadata["namespace"]
257
+
258
+ if is_solution and is_dms:
259
+ metadata["name"] = self.new_model_id[1] # type: ignore[index]
260
+
261
+ if is_solution:
262
+ metadata["created"] = now_iso
263
+ else:
264
+ metadata["created"] = existing_metadata["created"]
265
+
266
+ if is_solution or is_extension:
267
+ metadata["updated"] = now_iso
268
+ else:
269
+ metadata["updated"] = existing_metadata["updated"]
270
+
271
+ if is_solution:
272
+ metadata["creator"] = "YOUR NAME"
273
+ else:
274
+ metadata["creator"] = existing_metadata["creator"]
275
+
276
+ if not is_solution:
277
+ metadata["description"] = existing_metadata["description"]
278
+
279
+ if is_extension:
280
+ metadata["schema"] = SchemaCompleteness.extended.value
281
+ else:
282
+ metadata["schema"] = SchemaCompleteness.complete.value
283
+
284
+ metadata["extension"] = "addition"
285
+
286
+ return metadata
@@ -13,7 +13,6 @@ from cognite.client.data_classes.data_modeling import (
13
13
  SingleHopConnectionDefinition,
14
14
  View,
15
15
  )
16
- from cognite.client.data_classes.data_modeling.data_types import ListablePropertyType
17
16
  from cognite.client.data_classes.data_modeling.ids import DataModelIdentifier, ViewId
18
17
 
19
18
  from cognite.neat.rules.models.tables import Tables
@@ -132,9 +131,7 @@ class DMSImporter(BaseImporter):
132
131
 
133
132
  max_count: str | float = "1"
134
133
  if isinstance(prop, SingleHopConnectionDefinition) or (
135
- isinstance(prop, MappedProperty)
136
- and isinstance(prop.type, ListablePropertyType)
137
- and prop.type.is_list
134
+ isinstance(prop, MappedProperty) and prop.type.is_list
138
135
  ):
139
136
  max_count = float("nan")
140
137
 
@@ -5,9 +5,10 @@ from cognite.client import CogniteClient
5
5
  from cognite.client import data_modeling as dm
6
6
  from cognite.client.data_classes.data_modeling import DataModelIdentifier
7
7
  from cognite.client.data_classes.data_modeling.containers import BTreeIndex, InvertedIndex
8
- from cognite.client.data_classes.data_modeling.data_types import ListablePropertyType
8
+ from cognite.client.utils import ms_to_datetime
9
9
 
10
10
  from cognite.neat.rules import issues
11
+ from cognite.neat.rules.importers._base import BaseImporter, Rules
11
12
  from cognite.neat.rules.issues import IssueList
12
13
  from cognite.neat.rules.models._rules import DMSRules, DMSSchema, RoleTypes
13
14
  from cognite.neat.rules.models._rules._types import (
@@ -19,6 +20,7 @@ from cognite.neat.rules.models._rules._types import (
19
20
  ViewEntity,
20
21
  ViewPropEntity,
21
22
  )
23
+ from cognite.neat.rules.models._rules.base import ExtensionCategory, SchemaCompleteness
22
24
  from cognite.neat.rules.models._rules.dms_architect_rules import (
23
25
  DMSContainer,
24
26
  DMSMetadata,
@@ -27,16 +29,47 @@ from cognite.neat.rules.models._rules.dms_architect_rules import (
27
29
  SheetList,
28
30
  )
29
31
 
30
- from ._base import BaseImporter, Rules
31
-
32
32
 
33
33
  class DMSImporter(BaseImporter):
34
- def __init__(self, schema: DMSSchema):
34
+ def __init__(self, schema: DMSSchema, metadata: DMSMetadata | None = None):
35
35
  self.schema = schema
36
+ self.metadata = metadata
36
37
 
37
38
  @classmethod
38
39
  def from_data_model_id(cls, client: CogniteClient, data_model_id: DataModelIdentifier) -> "DMSImporter":
39
- return cls(DMSSchema.from_model_id(client, data_model_id))
40
+ """Create a DMSImporter ready to convert the given data model to rules.
41
+
42
+ Args:
43
+ client: Instantiated CogniteClient to retrieve data model.
44
+ data_model_id: Data Model to retrieve.
45
+
46
+ Returns:
47
+ DMSImporter: DMSImporter instance
48
+ """
49
+ data_models = client.data_modeling.data_models.retrieve(data_model_id, inline_views=True)
50
+ if len(data_models) == 0:
51
+ raise ValueError(f"Data model {data_model_id} not found")
52
+ data_model = data_models.latest_version()
53
+ schema = DMSSchema.from_data_model(client, data_model)
54
+ description, creator = DMSMetadata._get_description_and_creator(data_model.description)
55
+
56
+ created = ms_to_datetime(data_model.created_time)
57
+ updated = ms_to_datetime(data_model.last_updated_time)
58
+
59
+ metadata = DMSMetadata(
60
+ schema_=SchemaCompleteness.complete,
61
+ extension=ExtensionCategory.addition,
62
+ space=data_model.space,
63
+ external_id=data_model.external_id,
64
+ name=data_model.name or data_model.external_id,
65
+ version=data_model.version or "0.1.0",
66
+ updated=updated,
67
+ created=created,
68
+ creator=creator,
69
+ description=description,
70
+ default_view_version=data_model.version or "0.1.0",
71
+ )
72
+ return cls(schema, metadata)
40
73
 
41
74
  @classmethod
42
75
  def from_directory(cls, directory: str | Path) -> "DMSImporter":
@@ -138,11 +171,7 @@ class DMSImporter(BaseImporter):
138
171
  description=prop.description,
139
172
  value_type=cast(ViewPropEntity | DMSValueType, container_prop.type._type),
140
173
  nullable=container_prop.nullable,
141
- is_list=(
142
- container_prop.type.is_list
143
- if isinstance(container_prop.type, ListablePropertyType)
144
- else False
145
- ),
174
+ is_list=container_prop.type.is_list,
146
175
  default=container_prop.default_value,
147
176
  container=ContainerEntity.from_id(container.as_id()),
148
177
  container_property=prop.container_property_identifier,
@@ -172,7 +201,7 @@ class DMSImporter(BaseImporter):
172
201
  }
173
202
 
174
203
  dms_rules = DMSRules(
175
- metadata=DMSMetadata.from_data_model(data_model),
204
+ metadata=self.metadata or DMSMetadata.from_data_model(data_model),
176
205
  properties=properties,
177
206
  containers=SheetList[DMSContainer](
178
207
  data=[DMSContainer.from_container(container) for container in self.schema.containers]
@@ -68,7 +68,15 @@ class NeatValidationError(ValidationIssue, ABC):
68
68
 
69
69
  This is intended to be overridden in subclasses to handle specific error types.
70
70
  """
71
- return [DefaultPydanticError.from_pydantic_error(error) for error in errors]
71
+ all_errors = []
72
+ for error in errors:
73
+ if isinstance(ctx := error.get("ctx"), dict) and isinstance(
74
+ multi_error := ctx.get("error"), MultiValueError
75
+ ):
76
+ all_errors.extend(multi_error.errors)
77
+ else:
78
+ all_errors.append(DefaultPydanticError.from_pydantic_error(error))
79
+ return all_errors
72
80
 
73
81
 
74
82
  @dataclass(frozen=True)
@@ -26,6 +26,8 @@ __all__ = [
26
26
  "MultipleReferenceWarning",
27
27
  "HasDataFilterOnNoPropertiesViewWarning",
28
28
  "NodeTypeFilterOnParentViewWarning",
29
+ "ChangingContainerError",
30
+ "ChangingViewError",
29
31
  ]
30
32
 
31
33
 
@@ -225,6 +227,78 @@ class ContainerPropertyUsedMultipleTimesError(DMSSchemaError):
225
227
  return output
226
228
 
227
229
 
230
+ @dataclass(frozen=True)
231
+ class ChangingContainerError(DMSSchemaError):
232
+ description = "You are adding to an existing model. "
233
+ fix = "Keep the container the same"
234
+ error_name: ClassVar[str] = "ChangingContainerError"
235
+ container_id: dm.ContainerId
236
+ changed_properties: list[str] | None = None
237
+ changed_attributes: list[str] | None = None
238
+
239
+ def __post_init__(self):
240
+ # Sorting for deterministic output
241
+ if self.changed_properties:
242
+ self.changed_properties.sort()
243
+ if self.changed_attributes:
244
+ self.changed_attributes.sort()
245
+
246
+ def message(self) -> str:
247
+ if self.changed_properties:
248
+ changed = f" properties {self.changed_properties}."
249
+ elif self.changed_attributes:
250
+ changed = f" attributes {self.changed_attributes}."
251
+ else:
252
+ changed = "."
253
+ return (
254
+ f"The container {self.container_id} has changed{changed}"
255
+ "When extending model with extension set to addition or reshape, the container "
256
+ "properties must remain the same"
257
+ )
258
+
259
+ def dump(self) -> dict[str, Any]:
260
+ output = super().dump()
261
+ output["container_id"] = self.container_id.dump()
262
+ output["changed_properties"] = self.changed_properties
263
+ return output
264
+
265
+
266
+ @dataclass(frozen=True)
267
+ class ChangingViewError(DMSSchemaError):
268
+ description = "You are adding to an existing model. "
269
+ fix = "Keep the view the same"
270
+ error_name: ClassVar[str] = "ChangingViewError"
271
+ view_id: dm.ViewId
272
+ changed_properties: list[str] | None = None
273
+ changed_attributes: list[str] | None = None
274
+
275
+ def __post_init__(self):
276
+ # Sorting for deterministic output
277
+ if self.changed_properties:
278
+ self.changed_properties.sort()
279
+ if self.changed_attributes:
280
+ self.changed_attributes.sort()
281
+
282
+ def message(self) -> str:
283
+ if self.changed_properties:
284
+ changed = f" properties {self.changed_properties}."
285
+ elif self.changed_attributes:
286
+ changed = f" attributes {self.changed_attributes}."
287
+ else:
288
+ changed = "."
289
+
290
+ return (
291
+ f"The view {self.view_id} has changed{changed}"
292
+ "When extending model with extension set to addition, the view properties must remain the same"
293
+ )
294
+
295
+ def dump(self) -> dict[str, Any]:
296
+ output = super().dump()
297
+ output["view_id"] = self.view_id.dump()
298
+ output["difference"] = self.changed_properties
299
+ return output
300
+
301
+
228
302
  @dataclass(frozen=True)
229
303
  class DirectRelationListWarning(DMSSchemaWarning):
230
304
  description = "The container property is set to a direct relation list, which is not supported by the CDF API"
@@ -10,10 +10,21 @@ import types
10
10
  from abc import abstractmethod
11
11
  from collections.abc import Callable, Iterator
12
12
  from functools import wraps
13
- from typing import Any, ClassVar, Generic, TypeAlias, TypeVar
13
+ from typing import Annotated, Any, ClassVar, Generic, TypeAlias, TypeVar
14
14
 
15
15
  import pandas as pd
16
- from pydantic import BaseModel, ConfigDict, Field, HttpUrl, constr, field_validator, model_serializer, model_validator
16
+ from pydantic import (
17
+ BaseModel,
18
+ BeforeValidator,
19
+ ConfigDict,
20
+ Field,
21
+ HttpUrl,
22
+ PlainSerializer,
23
+ constr,
24
+ field_validator,
25
+ model_serializer,
26
+ model_validator,
27
+ )
17
28
  from pydantic.fields import FieldInfo
18
29
 
19
30
  from cognite.neat.rules.models._rules._types import ClassType
@@ -318,3 +329,14 @@ class SheetList(BaseModel, Generic[T_Entity]):
318
329
  def mandatory_fields(cls, use_alias=False) -> set[str]:
319
330
  """Returns a set of mandatory fields for the model."""
320
331
  return _get_required_fields(cls, use_alias)
332
+
333
+
334
+ ExtensionCategoryType = Annotated[
335
+ ExtensionCategory,
336
+ PlainSerializer(
337
+ lambda v: v.value if isinstance(v, ExtensionCategory) else v,
338
+ return_type=str,
339
+ when_used="unless-none",
340
+ ),
341
+ BeforeValidator(lambda v: ExtensionCategory(v) if isinstance(v, str) else v),
342
+ ]