cognite-neat 0.88.2__tar.gz → 0.88.3__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 (242) hide show
  1. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/PKG-INFO +1 -1
  2. cognite_neat-0.88.3/cognite/neat/_version.py +1 -0
  3. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/loaders/_base.py +3 -3
  4. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/loaders/_rdf2asset.py +24 -25
  5. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/loaders/_rdf2dms.py +20 -15
  6. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/issues/__init__.py +1 -3
  7. cognite_neat-0.88.3/cognite/neat/issues/_base.py +415 -0
  8. cognite_neat-0.88.3/cognite/neat/issues/errors/__init__.py +72 -0
  9. cognite_neat-0.88.3/cognite/neat/issues/errors/_external.py +67 -0
  10. cognite_neat-0.88.3/cognite/neat/issues/errors/_general.py +28 -0
  11. cognite_neat-0.88.3/cognite/neat/issues/errors/_properties.py +62 -0
  12. cognite_neat-0.88.3/cognite/neat/issues/errors/_resources.py +111 -0
  13. cognite_neat-0.88.3/cognite/neat/issues/errors/_workflow.py +36 -0
  14. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/issues/formatters.py +1 -1
  15. cognite_neat-0.88.3/cognite/neat/issues/warnings/__init__.py +66 -0
  16. cognite_neat-0.88.3/cognite/neat/issues/warnings/_external.py +40 -0
  17. cognite_neat-0.88.3/cognite/neat/issues/warnings/_general.py +29 -0
  18. cognite_neat-0.88.3/cognite/neat/issues/warnings/_models.py +92 -0
  19. cognite_neat-0.88.3/cognite/neat/issues/warnings/_properties.py +44 -0
  20. cognite_neat-0.88.3/cognite/neat/issues/warnings/_resources.py +55 -0
  21. cognite_neat-0.88.3/cognite/neat/issues/warnings/user_modeling.py +113 -0
  22. cognite_neat-0.88.3/cognite/neat/rules/_shared.py +18 -0
  23. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/exporters/_base.py +6 -6
  24. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/exporters/_rules2dms.py +18 -11
  25. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/exporters/_rules2excel.py +4 -4
  26. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/exporters/_rules2ontology.py +74 -51
  27. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/exporters/_rules2yaml.py +3 -3
  28. cognite_neat-0.88.3/cognite/neat/rules/exporters/_validation.py +14 -0
  29. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_base.py +8 -12
  30. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_dms2rules.py +21 -24
  31. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_dtdl2rules/dtdl_converter.py +22 -17
  32. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_dtdl2rules/dtdl_importer.py +26 -19
  33. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_dtdl2rules/spec.py +7 -0
  34. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_imf2rules/_imf2classes.py +1 -1
  35. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_imf2rules/_imf2rules.py +9 -7
  36. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_inference2rules.py +8 -8
  37. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_owl2rules/_owl2classes.py +1 -0
  38. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_owl2rules/_owl2properties.py +1 -0
  39. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_owl2rules/_owl2rules.py +4 -4
  40. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_shared.py +3 -3
  41. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_spreadsheet2rules.py +35 -22
  42. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_yaml2rules.py +23 -22
  43. cognite_neat-0.88.3/cognite/neat/rules/models/_constants.py +2 -0
  44. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/_rdfpath.py +4 -4
  45. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/_types/_field.py +5 -10
  46. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/asset/_rules.py +1 -3
  47. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/asset/_validation.py +13 -9
  48. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/dms/_converter.py +2 -4
  49. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/dms/_exporter.py +30 -8
  50. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/dms/_rules.py +23 -7
  51. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/dms/_schema.py +87 -78
  52. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/dms/_validation.py +104 -65
  53. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/information/_converter.py +2 -2
  54. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/information/_rules.py +7 -8
  55. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/information/_validation.py +47 -24
  56. cognite_neat-0.88.3/cognite/neat/rules/transformers/_base.py +15 -0
  57. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/auxiliary.py +2 -35
  58. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/text.py +17 -0
  59. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/base.py +4 -4
  60. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/cdf_store.py +3 -3
  61. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/data_contracts.py +1 -1
  62. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/lib/current/graph_extractor.py +3 -3
  63. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/lib/current/graph_loader.py +2 -2
  64. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/lib/current/graph_store.py +1 -1
  65. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/lib/current/rules_exporter.py +10 -10
  66. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/lib/current/rules_importer.py +6 -6
  67. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/lib/current/rules_validator.py +5 -6
  68. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/lib/io/io_steps.py +5 -5
  69. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps_registry.py +4 -5
  70. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/pyproject.toml +1 -1
  71. cognite_neat-0.88.2/cognite/neat/_version.py +0 -1
  72. cognite_neat-0.88.2/cognite/neat/exceptions.py +0 -145
  73. cognite_neat-0.88.2/cognite/neat/graph/__init__.py +0 -3
  74. cognite_neat-0.88.2/cognite/neat/graph/exceptions.py +0 -90
  75. cognite_neat-0.88.2/cognite/neat/issues/_base.py +0 -226
  76. cognite_neat-0.88.2/cognite/neat/issues/errors/external.py +0 -21
  77. cognite_neat-0.88.2/cognite/neat/issues/errors/properties.py +0 -75
  78. cognite_neat-0.88.2/cognite/neat/issues/errors/resources.py +0 -123
  79. cognite_neat-0.88.2/cognite/neat/issues/neat_warnings/__init__.py +0 -2
  80. cognite_neat-0.88.2/cognite/neat/issues/neat_warnings/identifier.py +0 -27
  81. cognite_neat-0.88.2/cognite/neat/issues/neat_warnings/models.py +0 -22
  82. cognite_neat-0.88.2/cognite/neat/issues/neat_warnings/properties.py +0 -77
  83. cognite_neat-0.88.2/cognite/neat/issues/neat_warnings/resources.py +0 -125
  84. cognite_neat-0.88.2/cognite/neat/rules/_shared.py +0 -10
  85. cognite_neat-0.88.2/cognite/neat/rules/exporters/_validation.py +0 -99
  86. cognite_neat-0.88.2/cognite/neat/rules/issues/__init__.py +0 -22
  87. cognite_neat-0.88.2/cognite/neat/rules/issues/base.py +0 -63
  88. cognite_neat-0.88.2/cognite/neat/rules/issues/dms.py +0 -549
  89. cognite_neat-0.88.2/cognite/neat/rules/issues/fileread.py +0 -197
  90. cognite_neat-0.88.2/cognite/neat/rules/issues/ontology.py +0 -298
  91. cognite_neat-0.88.2/cognite/neat/rules/issues/spreadsheet.py +0 -563
  92. cognite_neat-0.88.2/cognite/neat/rules/issues/spreadsheet_file.py +0 -151
  93. cognite_neat-0.88.2/cognite/neat/rules/issues/tables.py +0 -72
  94. cognite_neat-0.88.2/cognite/neat/rules/models/_constants.py +0 -1
  95. cognite_neat-0.88.2/cognite/neat/workflows/_exceptions.py +0 -41
  96. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/LICENSE +0 -0
  97. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/README.md +0 -0
  98. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/__init__.py +0 -0
  99. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/_shared.py +0 -0
  100. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/__init__.py +0 -0
  101. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/asgi/metrics.py +0 -0
  102. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/configuration.py +0 -0
  103. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/context_manager/__init__.py +0 -0
  104. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/context_manager/manager.py +0 -0
  105. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/data_classes/__init__.py +0 -0
  106. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/data_classes/rest.py +0 -0
  107. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/explorer.py +0 -0
  108. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/routers/configuration.py +0 -0
  109. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/routers/crud.py +0 -0
  110. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/routers/metrics.py +0 -0
  111. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/routers/workflows.py +0 -0
  112. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/utils/__init__.py +0 -0
  113. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/utils/data_mapping.py +0 -0
  114. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/utils/logging.py +0 -0
  115. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/api/utils/query_templates.py +0 -0
  116. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/main.py +0 -0
  117. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/monitoring/__init__.py +0 -0
  118. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/monitoring/metrics.py +0 -0
  119. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/index.html +0 -0
  120. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/.gitignore +0 -0
  121. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/README.md +0 -0
  122. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/asset-manifest.json +0 -0
  123. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/favicon.ico +0 -0
  124. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/img/architect-icon.svg +0 -0
  125. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/img/developer-icon.svg +0 -0
  126. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/img/sme-icon.svg +0 -0
  127. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/index.html +0 -0
  128. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/logo192.png +0 -0
  129. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/manifest.json +0 -0
  130. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/robots.txt +0 -0
  131. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/static/css/main.72e3d92e.css +0 -0
  132. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/static/css/main.72e3d92e.css.map +0 -0
  133. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/static/js/main.5a52cf09.js +0 -0
  134. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/static/js/main.5a52cf09.js.LICENSE.txt +0 -0
  135. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/static/js/main.5a52cf09.js.map +0 -0
  136. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/app/ui/neat-app/build/static/media/logo.8093b84df9ed36a174c629d6fe0b730d.svg +0 -0
  137. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/config.py +0 -0
  138. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/constants.py +0 -0
  139. {cognite_neat-0.88.2/cognite/neat/graph/extractors/_classic_cdf → cognite_neat-0.88.3/cognite/neat/graph}/__init__.py +0 -0
  140. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/_shared.py +0 -0
  141. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/_tracking/__init__.py +0 -0
  142. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/_tracking/base.py +0 -0
  143. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/_tracking/log.py +0 -0
  144. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/examples/Knowledge-Graph-Nordic44-dirty.xml +0 -0
  145. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/examples/Knowledge-Graph-Nordic44.xml +0 -0
  146. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/examples/__init__.py +0 -0
  147. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/examples/skos-capturing-sheet-wind-topics.xlsx +0 -0
  148. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/__init__.py +0 -0
  149. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_base.py +0 -0
  150. {cognite_neat-0.88.2/cognite/neat/issues/errors → cognite_neat-0.88.3/cognite/neat/graph/extractors/_classic_cdf}/__init__.py +0 -0
  151. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_classic_cdf/_assets.py +0 -0
  152. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_classic_cdf/_base.py +0 -0
  153. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_classic_cdf/_events.py +0 -0
  154. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_classic_cdf/_files.py +0 -0
  155. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_classic_cdf/_labels.py +0 -0
  156. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_classic_cdf/_relationships.py +0 -0
  157. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_classic_cdf/_sequences.py +0 -0
  158. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_classic_cdf/_timeseries.py +0 -0
  159. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_dexpi.py +0 -0
  160. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_mock_graph_generator.py +0 -0
  161. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/extractors/_rdf_file.py +0 -0
  162. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/loaders/__init__.py +0 -0
  163. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/models.py +0 -0
  164. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/queries/__init__.py +0 -0
  165. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/queries/_base.py +0 -0
  166. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/queries/_construct.py +0 -0
  167. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/queries/_shared.py +0 -0
  168. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/transformers/__init__.py +0 -0
  169. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/transformers/_base.py +0 -0
  170. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/transformers/_classic_cdf.py +0 -0
  171. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/graph/transformers/_rdfpath.py +0 -0
  172. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/py.typed +0 -0
  173. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/__init__.py +0 -0
  174. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/analysis/__init__.py +0 -0
  175. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/analysis/_asset.py +0 -0
  176. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/analysis/_base.py +0 -0
  177. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/analysis/_information.py +0 -0
  178. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/examples/__init__.py +0 -0
  179. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/examples/wind-energy.owl +0 -0
  180. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/exporters/__init__.py +0 -0
  181. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/__init__.py +0 -0
  182. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_dtdl2rules/__init__.py +0 -0
  183. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_dtdl2rules/_unit_lookup.py +0 -0
  184. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/__init__.py +0 -0
  185. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_imf2rules/__init__.py +0 -0
  186. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_imf2rules/_imf2metadata.py +0 -0
  187. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_imf2rules/_imf2properties.py +0 -0
  188. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_owl2rules/__init__.py +0 -0
  189. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/importers/_rdf/_owl2rules/_owl2metadata.py +0 -0
  190. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/__init__.py +0 -0
  191. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/_base.py +0 -0
  192. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/_types/__init__.py +0 -0
  193. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/asset/__init__.py +0 -0
  194. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/asset/_converter.py +0 -0
  195. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/asset/_rules_input.py +0 -0
  196. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/asset/_serializer.py +0 -0
  197. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/data_types.py +0 -0
  198. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/dms/__init__.py +0 -0
  199. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/dms/_rules_input.py +0 -0
  200. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/dms/_serializer.py +0 -0
  201. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/domain.py +0 -0
  202. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/entities.py +0 -0
  203. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/information/__init__.py +0 -0
  204. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/information/_rules_input.py +0 -0
  205. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/information/_serializer.py +0 -0
  206. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/rules/models/wrapped_entities.py +0 -0
  207. {cognite_neat-0.88.2/cognite/neat/utils → cognite_neat-0.88.3/cognite/neat/rules/transformers}/__init__.py +0 -0
  208. {cognite_neat-0.88.2/cognite/neat/graph/stores → cognite_neat-0.88.3/cognite/neat/store}/__init__.py +0 -0
  209. {cognite_neat-0.88.2/cognite/neat/graph/stores → cognite_neat-0.88.3/cognite/neat/store}/_base.py +0 -0
  210. {cognite_neat-0.88.2/cognite/neat/graph/stores → cognite_neat-0.88.3/cognite/neat/store}/_provenance.py +0 -0
  211. {cognite_neat-0.88.2/cognite/neat/utils/cdf → cognite_neat-0.88.3/cognite/neat/utils}/__init__.py +0 -0
  212. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/auth.py +0 -0
  213. {cognite_neat-0.88.2/cognite/neat/workflows/steps → cognite_neat-0.88.3/cognite/neat/utils/cdf}/__init__.py +0 -0
  214. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/cdf/data_classes.py +0 -0
  215. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/cdf/loaders/__init__.py +0 -0
  216. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/cdf/loaders/_base.py +0 -0
  217. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/cdf/loaders/_data_modeling.py +0 -0
  218. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/cdf/loaders/_ingestion.py +0 -0
  219. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/collection_.py +0 -0
  220. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/rdf_.py +0 -0
  221. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/regex_patterns.py +0 -0
  222. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/spreadsheet.py +0 -0
  223. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/time_.py +0 -0
  224. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/upload.py +0 -0
  225. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/utils/xml_.py +0 -0
  226. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/__init__.py +0 -0
  227. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/examples/Export_DMS/workflow.yaml +0 -0
  228. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/examples/Import_DMS/workflow.yaml +0 -0
  229. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/examples/Validate_Rules/workflow.yaml +0 -0
  230. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/examples/Validate_Solution_Model/workflow.yaml +0 -0
  231. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/examples/Visualize_Data_Model_Using_Mock_Graph/workflow.yaml +0 -0
  232. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/examples/Visualize_Semantic_Data_Model/workflow.yaml +0 -0
  233. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/manager.py +0 -0
  234. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/model.py +0 -0
  235. {cognite_neat-0.88.2/cognite/neat/workflows/steps/lib → cognite_neat-0.88.3/cognite/neat/workflows/steps}/__init__.py +0 -0
  236. /cognite_neat-0.88.2/cognite/neat/issues/errors/schema.py → /cognite_neat-0.88.3/cognite/neat/workflows/steps/lib/__init__.py +0 -0
  237. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/lib/current/__init__.py +0 -0
  238. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/lib/io/__init__.py +0 -0
  239. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/steps/step_model.py +0 -0
  240. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/tasks.py +0 -0
  241. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/cognite/neat/workflows/triggers.py +0 -0
  242. {cognite_neat-0.88.2 → cognite_neat-0.88.3}/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.88.2
3
+ Version: 0.88.3
4
4
  Summary: Knowledge graph transformation
5
5
  Home-page: https://cognite-neat.readthedocs-hosted.com/
6
6
  License: Apache-2.0
@@ -0,0 +1 @@
1
+ __version__ = "0.88.3"
@@ -6,9 +6,9 @@ from typing import ClassVar, Generic, TypeVar
6
6
  from cognite.client import CogniteClient
7
7
  from cognite.client.data_classes.capabilities import Capability
8
8
 
9
- from cognite.neat.graph import NeatGraphStore
10
9
  from cognite.neat.issues import IssueList, NeatIssue, NeatIssueList
11
- from cognite.neat.issues.errors.external import FailedAuthorizationError
10
+ from cognite.neat.issues.errors import AuthorizationError
11
+ from cognite.neat.store import NeatGraphStore
12
12
  from cognite.neat.utils.auxiliary import class_html_doc
13
13
  from cognite.neat.utils.upload import UploadResult, UploadResultList
14
14
 
@@ -61,7 +61,7 @@ class CDFLoader(BaseLoader[T_Output]):
61
61
  if missing_capabilities:
62
62
  upload_result = UploadResult[Hashable](name=type(self).__name__)
63
63
  upload_result.issues.append(
64
- FailedAuthorizationError(action="Upload to CDF", reason=str(missing_capabilities))
64
+ AuthorizationError(action="Upload to CDF", reason=str(missing_capabilities))
65
65
  )
66
66
  yield upload_result
67
67
  return
@@ -19,12 +19,12 @@ from cognite.client.exceptions import CogniteAPIError, CogniteDuplicatedError
19
19
 
20
20
  from cognite.neat.graph._tracking.base import Tracker
21
21
  from cognite.neat.graph._tracking.log import LogTracker
22
- from cognite.neat.graph.stores import NeatGraphStore
23
- from cognite.neat.issues import IssueList, NeatIssue, NeatIssueList
24
- from cognite.neat.issues.errors.resources import InvalidResourceError
22
+ from cognite.neat.issues import IssueList, NeatError, NeatIssue, NeatIssueList
23
+ from cognite.neat.issues.errors import ResourceCreationError, ResourceNotFoundError
25
24
  from cognite.neat.rules.analysis._asset import AssetAnalysis
26
25
  from cognite.neat.rules.models import AssetRules
27
26
  from cognite.neat.rules.models.entities import ClassEntity, EntityTypes
27
+ from cognite.neat.store import NeatGraphStore
28
28
  from cognite.neat.utils.auxiliary import create_sha256_hash
29
29
  from cognite.neat.utils.upload import UploadResult
30
30
 
@@ -122,6 +122,7 @@ class AssetLoader(CDFLoader[AssetWrite]):
122
122
  tracker: Tracker,
123
123
  stop_on_exception: bool,
124
124
  ) -> Iterable[Any]:
125
+ error: NeatError
125
126
  for class_ in ordered_classes:
126
127
  tracker.start(repr(class_.id))
127
128
 
@@ -143,20 +144,18 @@ class AssetLoader(CDFLoader[AssetWrite]):
143
144
 
144
145
  # check on parent
145
146
  if "parentExternalId" in fields and fields["parentExternalId"] not in self.processed_assets:
146
- error = InvalidResourceError(
147
- resource_type=EntityTypes.asset,
148
- identifier=identifier,
149
- reason=(
150
- f"Parent asset {fields['parentExternalId']} does not exist or failed creation"
151
- f""" {
152
- f', moving the asset {identifier} under orphanage {self.orphanage.external_id}'
153
- if self.orphanage
154
- else ''}"""
155
- ),
147
+ error = ResourceNotFoundError(
148
+ fields["parentExternalId"],
149
+ EntityTypes.asset,
150
+ identifier,
151
+ EntityTypes.asset,
152
+ f"Moving the asset {identifier} under orphanage {self.orphanage.external_id}"
153
+ if self.orphanage
154
+ else "",
156
155
  )
157
156
  tracker.issue(error)
158
157
  if stop_on_exception:
159
- raise error.as_exception()
158
+ raise error
160
159
  yield error
161
160
 
162
161
  # if orphanage is set asset will use orphanage as parent
@@ -171,10 +170,10 @@ class AssetLoader(CDFLoader[AssetWrite]):
171
170
  yield AssetWrite.load(fields)
172
171
  self.processed_assets.add(identifier)
173
172
  except KeyError as e:
174
- error = InvalidResourceError(resource_type=EntityTypes.asset, identifier=identifier, reason=str(e))
173
+ error = ResourceCreationError(identifier, EntityTypes.asset, error=str(e))
175
174
  tracker.issue(error)
176
175
  if stop_on_exception:
177
- raise error.as_exception() from e
176
+ raise error from e
178
177
  yield error
179
178
 
180
179
  yield _END_OF_CLASS
@@ -201,17 +200,17 @@ class AssetLoader(CDFLoader[AssetWrite]):
201
200
 
202
201
  # check if source asset exists
203
202
  if source_external_id not in self.processed_assets:
204
- error = InvalidResourceError(
203
+ error = ResourceCreationError(
205
204
  resource_type=EntityTypes.relationship,
206
205
  identifier=source_external_id,
207
- reason=(
206
+ error=(
208
207
  f"Asset {source_external_id} does not exist! "
209
208
  "Aborting creation of relationships which use this asset as the source."
210
209
  ),
211
210
  )
212
211
  tracker.issue(error)
213
212
  if stop_on_exception:
214
- raise error.as_exception()
213
+ raise error
215
214
  yield error
216
215
  continue
217
216
 
@@ -221,10 +220,10 @@ class AssetLoader(CDFLoader[AssetWrite]):
221
220
  target_external_id = f"{self.external_id_prefix or ''}{target_external_id}"
222
221
  # check if source asset exists
223
222
  if target_external_id not in self.processed_assets:
224
- error = InvalidResourceError(
223
+ error = ResourceCreationError(
225
224
  resource_type=EntityTypes.relationship,
226
225
  identifier=target_external_id,
227
- reason=(
226
+ error=(
228
227
  f"Asset {target_external_id} does not exist! "
229
228
  f"Cannot create relationship between {source_external_id}"
230
229
  f" and {target_external_id}. "
@@ -232,7 +231,7 @@ class AssetLoader(CDFLoader[AssetWrite]):
232
231
  )
233
232
  tracker.issue(error)
234
233
  if stop_on_exception:
235
- raise error.as_exception()
234
+ raise error
236
235
  yield error
237
236
  continue
238
237
 
@@ -248,14 +247,14 @@ class AssetLoader(CDFLoader[AssetWrite]):
248
247
  labels=[label] if self.use_labels else None,
249
248
  )
250
249
  except KeyError as e:
251
- error = InvalidResourceError(
250
+ error = ResourceCreationError(
252
251
  resource_type=EntityTypes.relationship,
253
252
  identifier=external_id,
254
- reason=str(e),
253
+ error=str(e),
255
254
  )
256
255
  tracker.issue(error)
257
256
  if stop_on_exception:
258
- raise error.as_exception() from e
257
+ raise error from e
259
258
  yield error
260
259
 
261
260
  yield _END_OF_CLASS
@@ -14,14 +14,18 @@ from cognite.client.data_classes.data_modeling.views import SingleEdgeConnection
14
14
  from cognite.client.exceptions import CogniteAPIError
15
15
  from pydantic import BaseModel, ValidationInfo, create_model, field_validator
16
16
 
17
- import cognite.neat.issues.errors.resources
18
17
  from cognite.neat.graph._tracking import LogTracker, Tracker
19
- from cognite.neat.graph.stores import NeatGraphStore
20
18
  from cognite.neat.issues import IssueList, NeatIssue, NeatIssueList
21
- from cognite.neat.issues.errors.resources import FailedConvertError, InvalidResourceError, ResourceNotFoundError
22
- from cognite.neat.issues.neat_warnings.models import InvalidClassWarning
19
+ from cognite.neat.issues.errors import (
20
+ ResourceConvertionError,
21
+ ResourceCreationError,
22
+ ResourceDuplicatedError,
23
+ ResourceRetrievalError,
24
+ )
25
+ from cognite.neat.issues.warnings import PropertyTypeNotSupportedWarning
23
26
  from cognite.neat.rules.models import DMSRules
24
27
  from cognite.neat.rules.models.data_types import _DATA_TYPE_BY_DMS_TYPE, Json
28
+ from cognite.neat.store import NeatGraphStore
25
29
  from cognite.neat.utils.auxiliary import create_sha256_hash
26
30
  from cognite.neat.utils.upload import UploadResult
27
31
 
@@ -69,9 +73,7 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
69
73
  try:
70
74
  data_model = client.data_modeling.data_models.retrieve(data_model_id, inline_views=True).latest_version()
71
75
  except Exception as e:
72
- issues.append(
73
- ResourceNotFoundError(identifier=repr(data_model_id), resource_type="Data Model", reason=str(e))
74
- )
76
+ issues.append(ResourceRetrievalError(data_model_id, "data model", str(e)))
75
77
 
76
78
  return cls(graph_store, data_model, instance_space, {}, issues)
77
79
 
@@ -83,8 +85,9 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
83
85
  data_model = rules.as_schema().as_read_model()
84
86
  except Exception as e:
85
87
  issues.append(
86
- FailedConvertError(
88
+ ResourceConvertionError(
87
89
  identifier=rules.metadata.as_identifier(),
90
+ resource_type="DMS Rules",
88
91
  target_format="read DMS model",
89
92
  reason=str(e),
90
93
  )
@@ -114,10 +117,10 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
114
117
  try:
115
118
  yield self._create_node(identifier, properties, pydantic_cls, view_id)
116
119
  except ValueError as e:
117
- error = InvalidResourceError(resource_type="node", identifier=identifier, reason=str(e))
120
+ error = ResourceCreationError(identifier, "node", error=str(e))
118
121
  tracker.issue(error)
119
122
  if stop_on_exception:
120
- raise error.as_exception() from e
123
+ raise error from e
121
124
  yield error
122
125
  yield from self._create_edges(identifier, properties, edge_by_properties, tracker)
123
126
  tracker.finish(repr(view_id))
@@ -162,9 +165,11 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
162
165
  data_type = _DATA_TYPE_BY_DMS_TYPE.get(prop.type._type)
163
166
  if not data_type:
164
167
  issues.append(
165
- InvalidClassWarning(
166
- class_name=repr(view.as_id()),
167
- reason=f"Unknown data type for property {prop_name}: {prop.type._type}",
168
+ PropertyTypeNotSupportedWarning(
169
+ view.as_id(),
170
+ "view",
171
+ prop_name,
172
+ prop.type._type,
168
173
  )
169
174
  )
170
175
  continue
@@ -251,10 +256,10 @@ class DMSLoader(CDFLoader[dm.InstanceApply]):
251
256
  continue
252
257
  edge = edge_by_properties[prop]
253
258
  if isinstance(edge, SingleEdgeConnection) and len(values) > 1:
254
- error = cognite.neat.issues.errors.resources.InvalidResourceError(
259
+ error = ResourceDuplicatedError(
255
260
  resource_type="edge",
256
261
  identifier=identifier,
257
- reason=f"Multiple values for single edge {edge}. Expected only one.",
262
+ location=f"Multiple values for single edge {edge}. Expected only one.",
258
263
  )
259
264
  tracker.issue(error)
260
265
  yield error
@@ -1,7 +1,5 @@
1
1
  """This is module contains all the Neat Exceptions (Errors) and Warnings as well
2
- as
3
-
4
- """
2
+ as some helper classes to handle them like NeatIssueList"""
5
3
 
6
4
  from ._base import DefaultWarning, IssueList, MultiValueError, NeatError, NeatIssue, NeatIssueList, NeatWarning
7
5
 
@@ -0,0 +1,415 @@
1
+ import sys
2
+ import warnings
3
+ from abc import ABC
4
+ from collections import UserList
5
+ from collections.abc import Collection, Hashable, Iterable, Sequence
6
+ from dataclasses import dataclass, fields
7
+ from functools import total_ordering
8
+ from pathlib import Path
9
+ from types import UnionType
10
+ from typing import Any, ClassVar, Literal, TypeAlias, TypeVar, get_args, get_origin
11
+ from warnings import WarningMessage
12
+
13
+ import pandas as pd
14
+ from cognite.client.data_classes.data_modeling import ContainerId, ViewId
15
+ from pydantic_core import ErrorDetails
16
+
17
+ from cognite.neat.utils.spreadsheet import SpreadsheetRead
18
+ from cognite.neat.utils.text import humanize_collection, to_camel, to_snake
19
+
20
+ if sys.version_info < (3, 11):
21
+ from exceptiongroup import ExceptionGroup
22
+ from typing_extensions import Self
23
+ else:
24
+ from typing import Self
25
+
26
+
27
+ __all__ = [
28
+ "NeatIssue",
29
+ "NeatError",
30
+ "NeatWarning",
31
+ "DefaultWarning",
32
+ "NeatIssueList",
33
+ "MultiValueError",
34
+ ]
35
+
36
+ T_Identifier = TypeVar("T_Identifier", bound=Hashable)
37
+
38
+ T_ReferenceIdentifier = TypeVar("T_ReferenceIdentifier", bound=Hashable)
39
+
40
+ ResourceType: TypeAlias = (
41
+ Literal[
42
+ "view",
43
+ "container",
44
+ "view property",
45
+ "container property",
46
+ "space",
47
+ "class",
48
+ "asset",
49
+ "relationship",
50
+ "data model",
51
+ "edge",
52
+ "node",
53
+ "unknown",
54
+ ]
55
+ # String to handle all unknown types in different importers.
56
+ | str
57
+ )
58
+
59
+
60
+ @total_ordering
61
+ @dataclass(frozen=True)
62
+ class NeatIssue:
63
+ """This is the base class for all exceptions and warnings (issues) used in Neat."""
64
+
65
+ extra: ClassVar[str | None] = None
66
+ fix: ClassVar[str | None] = None
67
+
68
+ def as_message(self) -> str:
69
+ """Return a human-readable message for the issue."""
70
+ template = self.__doc__
71
+ if not template:
72
+ return "Missing"
73
+ variables, has_all_optional = self._get_variables()
74
+
75
+ msg = template.format(**variables)
76
+ if self.extra and has_all_optional:
77
+ msg += "\n" + self.extra.format(**variables)
78
+ if self.fix:
79
+ msg += f"\nFix: {self.fix.format(**variables)}"
80
+ name = type(self).__name__
81
+ return f"{name}: {msg}"
82
+
83
+ def _get_variables(self) -> tuple[dict[str, str], bool]:
84
+ variables: dict[str, str] = {}
85
+ has_all_optional = True
86
+ for name, var_ in vars(self).items():
87
+ if var_ is None:
88
+ has_all_optional = False
89
+ elif isinstance(var_, str):
90
+ variables[name] = var_
91
+ elif isinstance(var_, Path):
92
+ variables[name] = var_.as_posix()
93
+ elif isinstance(var_, Collection):
94
+ variables[name] = humanize_collection(var_)
95
+ else:
96
+ variables[name] = repr(var_)
97
+ return variables, has_all_optional
98
+
99
+ def dump(self) -> dict[str, Any]:
100
+ """Return a dictionary representation of the issue."""
101
+ variables = vars(self)
102
+ output = {to_camel(key): self._dump_value(value) for key, value in variables.items() if value is not None}
103
+ output["NeatIssue"] = type(self).__name__
104
+ return output
105
+
106
+ @classmethod
107
+ def _dump_value(cls, value: Any) -> list | int | bool | float | str | dict:
108
+ if isinstance(value, str | int | bool | float):
109
+ return value
110
+ elif isinstance(value, frozenset):
111
+ return [cls._dump_value(item) for item in value]
112
+ elif isinstance(value, Path):
113
+ return value.as_posix()
114
+ elif isinstance(value, tuple):
115
+ return [cls._dump_value(item) for item in value]
116
+ elif isinstance(value, ViewId | ContainerId):
117
+ return value.dump(camel_case=True, include_type=True)
118
+ raise ValueError(f"Unsupported type: {type(value)}")
119
+
120
+ @classmethod
121
+ def load(cls, data: dict[str, Any]) -> "NeatIssue":
122
+ """Create an instance of the issue from a dictionary."""
123
+ from cognite.neat.issues.errors import _NEAT_ERRORS_BY_NAME, NeatValueError
124
+ from cognite.neat.issues.warnings import _NEAT_WARNINGS_BY_NAME
125
+
126
+ if "NeatIssue" not in data:
127
+ raise NeatValueError("The data does not contain a NeatIssue key.")
128
+ issue_type = data.pop("NeatIssue")
129
+ args = {to_snake(key): value for key, value in data.items()}
130
+ if issue_type in _NEAT_ERRORS_BY_NAME:
131
+ return cls._load_values(_NEAT_ERRORS_BY_NAME[issue_type], args)
132
+ elif issue_type in _NEAT_WARNINGS_BY_NAME:
133
+ return cls._load_values(_NEAT_WARNINGS_BY_NAME[issue_type], args)
134
+ else:
135
+ raise NeatValueError(f"Unknown issue type: {issue_type}")
136
+
137
+ @classmethod
138
+ def _load_values(cls, neat_issue_cls: "type[NeatIssue]", data: dict[str, Any]) -> "NeatIssue":
139
+ args: dict[str, Any] = {}
140
+ for f in fields(neat_issue_cls):
141
+ if f.name not in data:
142
+ continue
143
+ value = data[f.name]
144
+ args[f.name] = cls._load_value(f.type, value)
145
+ return neat_issue_cls(**args)
146
+
147
+ @classmethod
148
+ def _load_value(cls, type_: type, value: Any) -> Any:
149
+ if isinstance(type_, UnionType) or get_origin(type_) is UnionType:
150
+ args = get_args(type_)
151
+ return cls._load_value(args[0], value)
152
+ elif type_ is frozenset or get_origin(type_) is frozenset:
153
+ subtype = get_args(type_)[0]
154
+ return frozenset(cls._load_value(subtype, item) for item in value)
155
+ elif type_ is Path:
156
+ return Path(value)
157
+ elif type_ is tuple or get_origin(type_) is tuple:
158
+ subtype = get_args(type_)[0]
159
+ return tuple(cls._load_value(subtype, item) for item in value)
160
+ elif type_ is ViewId:
161
+ return ViewId.load(value)
162
+ elif type_ is ContainerId:
163
+ return ContainerId.load(value)
164
+ return value
165
+
166
+ def __lt__(self, other: "NeatIssue") -> bool:
167
+ if not isinstance(other, NeatIssue):
168
+ return NotImplemented
169
+ return (type(self).__name__, self.as_message()) < (type(other).__name__, other.as_message())
170
+
171
+ def __eq__(self, other: object) -> bool:
172
+ if not isinstance(other, NeatIssue):
173
+ return NotImplemented
174
+ return (type(self).__name__, self.as_message()) == (type(other).__name__, other.as_message())
175
+
176
+
177
+ @dataclass(frozen=True)
178
+ class NeatError(NeatIssue, Exception):
179
+ """This is the base class for all exceptions (errors) used in Neat."""
180
+
181
+ @classmethod
182
+ def from_pydantic_errors(cls, errors: list[ErrorDetails], **kwargs) -> "list[NeatError]":
183
+ """Convert a list of pydantic errors to a list of Error instances.
184
+
185
+ This is intended to be overridden in subclasses to handle specific error types.
186
+ """
187
+ all_errors: list[NeatError] = []
188
+ read_info_by_sheet = kwargs.get("read_info_by_sheet")
189
+
190
+ for error in errors:
191
+ ctx = error.get("ctx")
192
+ if isinstance(ctx, dict) and isinstance(multi_error := ctx.get("error"), MultiValueError):
193
+ if read_info_by_sheet:
194
+ for caught_error in multi_error.errors:
195
+ cls._adjust_row_numbers(caught_error, read_info_by_sheet) # type: ignore[arg-type]
196
+ all_errors.extend(multi_error.errors) # type: ignore[arg-type]
197
+ elif isinstance(ctx, dict) and isinstance(single_error := ctx.get("error"), NeatError):
198
+ if read_info_by_sheet:
199
+ cls._adjust_row_numbers(single_error, read_info_by_sheet)
200
+ all_errors.append(single_error)
201
+ elif len(error["loc"]) >= 4 and read_info_by_sheet:
202
+ all_errors.append(RowError.from_pydantic_error(error, read_info_by_sheet))
203
+ else:
204
+ all_errors.append(DefaultPydanticError.from_pydantic_error(error))
205
+ return all_errors
206
+
207
+ @staticmethod
208
+ def _adjust_row_numbers(caught_error: "NeatError", read_info_by_sheet: dict[str, SpreadsheetRead]) -> None:
209
+ from cognite.neat.issues.errors._properties import PropertyDefinitionDuplicatedError
210
+ from cognite.neat.issues.errors._resources import ResourceNotDefinedError
211
+
212
+ reader = read_info_by_sheet.get("Properties", SpreadsheetRead())
213
+
214
+ if isinstance(caught_error, PropertyDefinitionDuplicatedError) and caught_error.location_name == "rows":
215
+ adjusted_row_number = (
216
+ tuple(
217
+ reader.adjusted_row_number(row_no) if isinstance(row_no, int) else row_no
218
+ for row_no in caught_error.locations or []
219
+ )
220
+ or None
221
+ )
222
+ # The error is frozen, so we have to use __setattr__ to change the row number
223
+ object.__setattr__(caught_error, "locations", adjusted_row_number)
224
+ elif isinstance(caught_error, RowError):
225
+ # Adjusting the row number to the actual row number in the spreadsheet
226
+ new_row = reader.adjusted_row_number(caught_error.row)
227
+ # The error is frozen, so we have to use __setattr__ to change the row number
228
+ object.__setattr__(caught_error, "row", new_row)
229
+ elif isinstance(caught_error, ResourceNotDefinedError):
230
+ if isinstance(caught_error.row_number, int) and caught_error.sheet_name == "Properties":
231
+ new_row = reader.adjusted_row_number(caught_error.row_number)
232
+ object.__setattr__(caught_error, "row_number", new_row)
233
+
234
+
235
+ @dataclass(frozen=True)
236
+ class DefaultPydanticError(NeatError, ValueError):
237
+ """{type}: {msg} [loc={loc}]"""
238
+
239
+ type: str
240
+ loc: tuple[int | str, ...]
241
+ msg: str
242
+
243
+ @classmethod
244
+ def from_pydantic_error(cls, error: ErrorDetails) -> "DefaultPydanticError":
245
+ return cls(
246
+ type=error["type"],
247
+ loc=error["loc"],
248
+ msg=error["msg"],
249
+ )
250
+
251
+ def as_message(self) -> str:
252
+ if self.loc and len(self.loc) == 1:
253
+ return f"{self.loc[0]} sheet: {self.msg}"
254
+ elif self.loc and len(self.loc) == 2:
255
+ return f"{self.loc[0]} sheet field/column <{self.loc[1]}>: {self.msg}"
256
+ else:
257
+ return self.msg
258
+
259
+
260
+ @dataclass(frozen=True)
261
+ class RowError(NeatError, ValueError):
262
+ """In {sheet_name}, row={row}, column={column}: {msg}. [type={type}, input_value={input}]"""
263
+
264
+ extra = "For further information visit {url}"
265
+
266
+ sheet_name: str
267
+ column: str
268
+ row: int
269
+ type: str
270
+ msg: str
271
+ input: Any
272
+ url: str | None = None
273
+
274
+ @classmethod
275
+ def from_pydantic_error(
276
+ cls,
277
+ error: ErrorDetails,
278
+ read_info_by_sheet: dict[str, SpreadsheetRead] | None = None,
279
+ ) -> Self:
280
+ sheet_name, _, row, column, *__ = error["loc"]
281
+ reader = (read_info_by_sheet or {}).get(str(sheet_name), SpreadsheetRead())
282
+ return cls(
283
+ sheet_name=str(sheet_name),
284
+ column=str(column),
285
+ row=reader.adjusted_row_number(int(row)),
286
+ type=error["type"],
287
+ msg=error["msg"],
288
+ input=error.get("input"),
289
+ url=str(url) if (url := error.get("url")) else None,
290
+ )
291
+
292
+ def as_message(self) -> str:
293
+ input_str = str(self.input) if self.input is not None else ""
294
+ input_str = input_str[:50] + "..." if len(input_str) > 50 else input_str
295
+ output = (
296
+ f"In {self.sheet_name}, row={self.row}, column={self.column}: {self.msg}. "
297
+ f"[type={self.type}, input_value={input_str}]"
298
+ )
299
+ if self.url:
300
+ output += f" For further information visit {self.url}"
301
+ return output
302
+
303
+
304
+ @dataclass(frozen=True)
305
+ class NeatWarning(NeatIssue, UserWarning):
306
+ """This is the base class for all warnings used in Neat."""
307
+
308
+ @classmethod
309
+ def from_warning(cls, warning: WarningMessage) -> "NeatWarning":
310
+ """Create a NeatWarning from a WarningMessage."""
311
+ return DefaultWarning.from_warning_message(warning)
312
+
313
+
314
+ @dataclass(frozen=True)
315
+ class DefaultWarning(NeatWarning):
316
+ """{category}: {warning}"""
317
+
318
+ extra = "Source: {source}"
319
+
320
+ warning: str
321
+ category: str
322
+ source: str | None = None
323
+
324
+ @classmethod
325
+ def from_warning_message(cls, warning: WarningMessage) -> NeatWarning:
326
+ if isinstance(warning.message, NeatWarning):
327
+ return warning.message
328
+
329
+ return cls(
330
+ warning=str(warning.message),
331
+ category=warning.category.__name__,
332
+ source=warning.source,
333
+ )
334
+
335
+ def as_message(self) -> str:
336
+ return str(self.warning)
337
+
338
+
339
+ T_NeatIssue = TypeVar("T_NeatIssue", bound=NeatIssue)
340
+
341
+
342
+ class NeatIssueList(UserList[T_NeatIssue], ABC):
343
+ """This is a generic list of NeatIssues."""
344
+
345
+ def __init__(self, issues: Sequence[T_NeatIssue] | None = None, title: str | None = None):
346
+ super().__init__(issues or [])
347
+ self.title = title
348
+
349
+ @property
350
+ def errors(self) -> Self:
351
+ """Return all the errors in this list."""
352
+ return type(self)([issue for issue in self if isinstance(issue, NeatError)]) # type: ignore[misc]
353
+
354
+ @property
355
+ def has_errors(self) -> bool:
356
+ """Return True if this list contains any errors."""
357
+ return any(isinstance(issue, NeatError) for issue in self)
358
+
359
+ @property
360
+ def warnings(self) -> Self:
361
+ """Return all the warnings in this list."""
362
+ return type(self)([issue for issue in self if isinstance(issue, NeatWarning)]) # type: ignore[misc]
363
+
364
+ def as_errors(self) -> ExceptionGroup:
365
+ """Return an ExceptionGroup with all the errors in this list."""
366
+ return ExceptionGroup(
367
+ "Operation failed",
368
+ [issue for issue in self if isinstance(issue, NeatError)],
369
+ )
370
+
371
+ def trigger_warnings(self) -> None:
372
+ """Trigger all warnings in this list."""
373
+ for warning in [issue for issue in self if isinstance(issue, NeatWarning)]:
374
+ warnings.warn(warning, stacklevel=2)
375
+
376
+ def to_pandas(self) -> pd.DataFrame:
377
+ """Return a pandas DataFrame representation of this list."""
378
+ return pd.DataFrame([issue.dump() for issue in self])
379
+
380
+ def _repr_html_(self) -> str | None:
381
+ return self.to_pandas()._repr_html_() # type: ignore[operator]
382
+
383
+ def as_exception(self) -> "MultiValueError":
384
+ """Return a MultiValueError with all the errors in this list."""
385
+ return MultiValueError(self.errors)
386
+
387
+
388
+ class MultiValueError(ValueError):
389
+ """This is a container for multiple errors.
390
+
391
+ It is used in the pydantic field_validator/model_validator to collect multiple errors, which
392
+ can then be caught in a try-except block and returned as an IssueList.
393
+
394
+ """
395
+
396
+ def __init__(self, errors: Sequence[NeatIssue]):
397
+ self.errors = list(errors)
398
+
399
+
400
+ class IssueList(NeatIssueList[NeatIssue]):
401
+ """This is a list of NeatIssues."""
402
+
403
+ ...
404
+
405
+
406
+ T_Cls = TypeVar("T_Cls")
407
+
408
+
409
+ def _get_subclasses(cls_: type[T_Cls], include_base: bool = False) -> Iterable[type[T_Cls]]:
410
+ """Get all subclasses of a class."""
411
+ if include_base:
412
+ yield cls_
413
+ for s in cls_.__subclasses__():
414
+ yield s
415
+ yield from _get_subclasses(s, False)