cognite-neat 0.107.0__tar.gz → 0.109.0__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.
Files changed (192) hide show
  1. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/PKG-INFO +1 -1
  2. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_constants.py +35 -1
  3. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/_shared.py +4 -0
  4. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/extractors/_classic_cdf/_base.py +115 -14
  5. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/extractors/_classic_cdf/_classic.py +87 -6
  6. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/extractors/_classic_cdf/_relationships.py +48 -12
  7. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/extractors/_classic_cdf/_sequences.py +19 -1
  8. cognite_neat-0.109.0/cognite/neat/_graph/extractors/_dms.py +307 -0
  9. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/extractors/_dms_graph.py +54 -4
  10. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/extractors/_mock_graph_generator.py +1 -1
  11. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/extractors/_rdf_file.py +3 -2
  12. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/loaders/__init__.py +1 -3
  13. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/loaders/_rdf2dms.py +20 -10
  14. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/queries/_base.py +144 -84
  15. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/queries/_construct.py +1 -1
  16. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/transformers/__init__.py +3 -1
  17. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/transformers/_base.py +4 -4
  18. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/transformers/_classic_cdf.py +13 -13
  19. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/transformers/_prune_graph.py +3 -3
  20. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/transformers/_rdfpath.py +3 -4
  21. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/transformers/_value_type.py +71 -13
  22. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_issues/errors/__init__.py +2 -0
  23. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_issues/errors/_external.py +8 -0
  24. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_issues/errors/_resources.py +1 -1
  25. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_issues/warnings/__init__.py +0 -2
  26. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_issues/warnings/_models.py +1 -1
  27. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_issues/warnings/_properties.py +0 -8
  28. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_issues/warnings/_resources.py +1 -1
  29. cognite_neat-0.109.0/cognite/neat/_rules/catalog/classic_model.xlsx +0 -0
  30. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/exporters/_rules2instance_template.py +3 -3
  31. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/exporters/_rules2yaml.py +1 -1
  32. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/importers/__init__.py +3 -1
  33. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/importers/_dtdl2rules/spec.py +1 -2
  34. cognite_neat-0.109.0/cognite/neat/_rules/importers/_rdf/__init__.py +5 -0
  35. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/importers/_rdf/_base.py +2 -2
  36. cognite_neat-0.109.0/cognite/neat/_rules/importers/_rdf/_inference2rules.py +578 -0
  37. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/_base_rules.py +22 -11
  38. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/dms/_exporter.py +5 -4
  39. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/dms/_rules.py +1 -8
  40. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/dms/_rules_input.py +4 -0
  41. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/information/_rules_input.py +5 -0
  42. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/transformers/__init__.py +10 -3
  43. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/transformers/_base.py +6 -1
  44. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/transformers/_converters.py +530 -364
  45. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/transformers/_mapping.py +4 -4
  46. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_session/_base.py +100 -47
  47. cognite_neat-0.109.0/cognite/neat/_session/_create.py +133 -0
  48. cognite_neat-0.109.0/cognite/neat/_session/_drop.py +103 -0
  49. cognite_neat-0.109.0/cognite/neat/_session/_fix.py +28 -0
  50. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_session/_inspect.py +22 -7
  51. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_session/_mapping.py +8 -8
  52. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_session/_prepare.py +3 -247
  53. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_session/_read.py +138 -17
  54. cognite_neat-0.109.0/cognite/neat/_session/_set.py +95 -0
  55. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_session/_show.py +16 -43
  56. cognite_neat-0.109.0/cognite/neat/_session/_state.py +100 -0
  57. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_session/_to.py +11 -4
  58. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_session/_wizard.py +1 -1
  59. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_session/exceptions.py +8 -1
  60. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_store/_graph_store.py +301 -146
  61. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_store/_provenance.py +36 -20
  62. cognite_neat-0.109.0/cognite/neat/_store/_rules_store.py +386 -0
  63. cognite_neat-0.109.0/cognite/neat/_store/exceptions.py +59 -0
  64. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_utils/auth.py +5 -3
  65. cognite_neat-0.109.0/cognite/neat/_version.py +2 -0
  66. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/pyproject.toml +1 -1
  67. cognite_neat-0.107.0/cognite/neat/_graph/extractors/_dms.py +0 -192
  68. cognite_neat-0.107.0/cognite/neat/_rules/catalog/classic_model.xlsx +0 -0
  69. cognite_neat-0.107.0/cognite/neat/_rules/importers/_rdf/__init__.py +0 -5
  70. cognite_neat-0.107.0/cognite/neat/_rules/importers/_rdf/_inference2rules.py +0 -294
  71. cognite_neat-0.107.0/cognite/neat/_session/_drop.py +0 -45
  72. cognite_neat-0.107.0/cognite/neat/_session/_set.py +0 -46
  73. cognite_neat-0.107.0/cognite/neat/_session/_state.py +0 -99
  74. cognite_neat-0.107.0/cognite/neat/_store/_rules_store.py +0 -400
  75. cognite_neat-0.107.0/cognite/neat/_store/exceptions.py +0 -23
  76. cognite_neat-0.107.0/cognite/neat/_version.py +0 -2
  77. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/LICENSE +0 -0
  78. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/README.md +0 -0
  79. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/__init__.py +0 -0
  80. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_client/__init__.py +0 -0
  81. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_client/_api/__init__.py +0 -0
  82. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_client/_api/data_modeling_loaders.py +0 -0
  83. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_client/_api/schema.py +0 -0
  84. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_client/_api_client.py +0 -0
  85. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_client/data_classes/__init__.py +0 -0
  86. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_client/data_classes/data_modeling.py +0 -0
  87. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_client/data_classes/neat_sequence.py +0 -0
  88. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_client/data_classes/schema.py +0 -0
  89. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_client/testing.py +0 -0
  90. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_config.py +0 -0
  91. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/__init__.py +0 -0
  92. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/_tracking/__init__.py +0 -0
  93. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/_tracking/base.py +0 -0
  94. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/_tracking/log.py +0 -0
  95. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/examples/Knowledge-Graph-Nordic44-dirty.xml +0 -0
  96. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/examples/Knowledge-Graph-Nordic44.xml +0 -0
  97. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/examples/__init__.py +0 -0
  98. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/examples/skos-capturing-sheet-wind-topics.xlsx +0 -0
  99. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/extractors/__init__.py +0 -0
  100. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/extractors/_base.py +0 -0
  101. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/extractors/_classic_cdf/__init__.py +0 -0
  102. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/extractors/_classic_cdf/_assets.py +0 -0
  103. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/extractors/_classic_cdf/_data_sets.py +0 -0
  104. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/extractors/_classic_cdf/_events.py +0 -0
  105. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/extractors/_classic_cdf/_files.py +0 -0
  106. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/extractors/_classic_cdf/_labels.py +0 -0
  107. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/extractors/_classic_cdf/_timeseries.py +0 -0
  108. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/extractors/_dexpi.py +0 -0
  109. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/extractors/_iodd.py +0 -0
  110. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/loaders/_base.py +0 -0
  111. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/queries/__init__.py +0 -0
  112. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/queries/_shared.py +0 -0
  113. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_graph/transformers/_iodd.py +0 -0
  114. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_issues/__init__.py +0 -0
  115. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_issues/_base.py +0 -0
  116. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_issues/errors/_general.py +0 -0
  117. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_issues/errors/_properties.py +0 -0
  118. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_issues/errors/_workflow.py +0 -0
  119. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_issues/formatters.py +0 -0
  120. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_issues/warnings/_external.py +0 -0
  121. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_issues/warnings/_general.py +0 -0
  122. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_issues/warnings/user_modeling.py +0 -0
  123. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/__init__.py +0 -0
  124. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/_constants.py +0 -0
  125. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/_shared.py +0 -0
  126. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/analysis/__init__.py +0 -0
  127. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/analysis/_base.py +0 -0
  128. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/analysis/_dms.py +0 -0
  129. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/analysis/_information.py +0 -0
  130. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/catalog/__init__.py +0 -0
  131. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/catalog/hello_world_pump.xlsx +0 -0
  132. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/catalog/info-rules-imf.xlsx +0 -0
  133. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/exporters/__init__.py +0 -0
  134. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/exporters/_base.py +0 -0
  135. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/exporters/_rules2dms.py +0 -0
  136. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/exporters/_rules2excel.py +0 -0
  137. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/exporters/_rules2ontology.py +0 -0
  138. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/exporters/_validation.py +0 -0
  139. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/importers/_base.py +0 -0
  140. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/importers/_dms2rules.py +0 -0
  141. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/importers/_dtdl2rules/__init__.py +0 -0
  142. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/importers/_dtdl2rules/_unit_lookup.py +0 -0
  143. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/importers/_dtdl2rules/dtdl_converter.py +0 -0
  144. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/importers/_dtdl2rules/dtdl_importer.py +0 -0
  145. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/importers/_rdf/_imf2rules.py +0 -0
  146. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/importers/_rdf/_owl2rules.py +0 -0
  147. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/importers/_rdf/_shared.py +0 -0
  148. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/importers/_spreadsheet2rules.py +0 -0
  149. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/importers/_yaml2rules.py +0 -0
  150. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/__init__.py +0 -0
  151. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/_base_input.py +0 -0
  152. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/_rdfpath.py +0 -0
  153. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/_types.py +0 -0
  154. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/data_types.py +0 -0
  155. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/dms/__init__.py +0 -0
  156. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/dms/_validation.py +0 -0
  157. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/entities/__init__.py +0 -0
  158. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/entities/_constants.py +0 -0
  159. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/entities/_loaders.py +0 -0
  160. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/entities/_multi_value.py +0 -0
  161. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/entities/_single_value.py +0 -0
  162. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/entities/_types.py +0 -0
  163. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/entities/_wrapped.py +0 -0
  164. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/information/__init__.py +0 -0
  165. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/information/_rules.py +0 -0
  166. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/information/_validation.py +0 -0
  167. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/mapping/__init__.py +0 -0
  168. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/mapping/_classic2core.py +0 -0
  169. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/models/mapping/_classic2core.yaml +0 -0
  170. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_rules/transformers/_verification.py +0 -0
  171. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_session/__init__.py +0 -0
  172. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_session/_collector.py +0 -0
  173. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_session/engine/__init__.py +0 -0
  174. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_session/engine/_import.py +0 -0
  175. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_session/engine/_interface.py +0 -0
  176. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_session/engine/_load.py +0 -0
  177. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_shared.py +0 -0
  178. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_store/__init__.py +0 -0
  179. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_utils/__init__.py +0 -0
  180. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_utils/auxiliary.py +0 -0
  181. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_utils/collection_.py +0 -0
  182. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_utils/graph_transformations_report.py +0 -0
  183. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_utils/io_.py +0 -0
  184. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_utils/rdf_.py +0 -0
  185. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_utils/reader/__init__.py +0 -0
  186. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_utils/reader/_base.py +0 -0
  187. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_utils/spreadsheet.py +0 -0
  188. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_utils/text.py +0 -0
  189. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_utils/time_.py +0 -0
  190. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_utils/upload.py +0 -0
  191. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/_utils/xml_.py +0 -0
  192. {cognite_neat-0.107.0 → cognite_neat-0.109.0}/cognite/neat/py.typed +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: cognite-neat
3
- Version: 0.107.0
3
+ Version: 0.109.0
4
4
  Summary: Knowledge graph transformation
5
5
  License: Apache-2.0
6
6
  Author: Nikola Vasiljevic
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING
5
5
  from cognite.client import data_modeling as dm
6
6
  from cognite.client.data_classes.data_modeling.ids import DataModelId
7
7
  from rdflib import DC, DCTERMS, FOAF, OWL, RDF, RDFS, SH, SKOS, XSD, Namespace, URIRef
8
+ from rdflib.namespace import DefinedNamespace
8
9
 
9
10
  from cognite import neat
10
11
 
@@ -73,10 +74,22 @@ DEFAULT_NAMESPACE = Namespace("http://purl.org/cognite/neat/")
73
74
  CDF_NAMESPACE = Namespace("https://cognitedata.com/")
74
75
  DEFAULT_BASE_URI = URIRef(DEFAULT_NAMESPACE)
75
76
  CLASSIC_CDF_NAMESPACE = Namespace("http://purl.org/cognite/cdf-classic#")
76
- UNKNOWN_TYPE = DEFAULT_NAMESPACE.UnknownType
77
77
  XML_SCHEMA_NAMESPACE = Namespace("http://www.w3.org/2001/XMLSchema#")
78
78
 
79
79
 
80
+ class NEAT(DefinedNamespace):
81
+ """
82
+ NEAT internal data model used for internal purposes of the NEAT library
83
+
84
+ """
85
+
86
+ _fail = True
87
+ _NS = Namespace("http://thisisneat.io/internal/")
88
+
89
+ UnknownType: URIRef # Unknown type used to express that the type of a subject is unknown
90
+ EmptyType: URIRef # Empty type used to express that the type of a subject is empty
91
+
92
+
80
93
  def get_default_prefixes_and_namespaces() -> dict[str, Namespace]:
81
94
  return {
82
95
  "owl": OWL._NS,
@@ -154,3 +167,24 @@ READONLY_PROPERTIES_BY_CONTAINER: Mapping[dm.ContainerId, frozenset[str]] = {
154
167
 
155
168
  def is_readonly_property(container: dm.ContainerId, property_: str) -> bool:
156
169
  return container in READONLY_PROPERTIES_BY_CONTAINER and property_ in READONLY_PROPERTIES_BY_CONTAINER[container]
170
+
171
+
172
+ DMS_RESERVED_PROPERTIES = frozenset(
173
+ {
174
+ "createdTime",
175
+ "deletedTime",
176
+ "edge_id",
177
+ "extensions",
178
+ "externalId",
179
+ "lastUpdatedTime",
180
+ "node_id",
181
+ "project_id",
182
+ "property_group",
183
+ "seq",
184
+ "space",
185
+ "version",
186
+ "tg_table_name",
187
+ "startNode",
188
+ "endNode",
189
+ }
190
+ )
@@ -7,6 +7,10 @@ MIMETypes: TypeAlias = Literal[
7
7
  RDFTypes: TypeAlias = Literal["xml", "rdf", "owl", "n3", "ttl", "turtle", "nt", "nq", "nquads", "trig"]
8
8
 
9
9
 
10
+ def quad_formats() -> list[str]:
11
+ return ["trig", "nquads", "nq", "nt"]
12
+
13
+
10
14
  def rdflib_to_oxi_type(rdflib_format: str) -> str | None:
11
15
  """Convert an RDFlib format to a MIME type.
12
16
 
@@ -1,6 +1,8 @@
1
1
  import json
2
2
  import re
3
3
  import sys
4
+ import typing
5
+ import urllib.parse
4
6
  import warnings
5
7
  from abc import ABC, abstractmethod
6
8
  from collections.abc import Callable, Iterable, Sequence, Set
@@ -16,7 +18,8 @@ from rdflib import RDF, XSD, Literal, Namespace, URIRef
16
18
 
17
19
  from cognite.neat._constants import DEFAULT_NAMESPACE
18
20
  from cognite.neat._graph.extractors._base import BaseExtractor
19
- from cognite.neat._issues.warnings import CDFAuthWarning
21
+ from cognite.neat._issues.errors import NeatValueError
22
+ from cognite.neat._issues.warnings import CDFAuthWarning, NeatValueWarning
20
23
  from cognite.neat._shared import Triple
21
24
  from cognite.neat._utils.auxiliary import string_to_ideal_type
22
25
  from cognite.neat._utils.collection_ import iterate_progress_bar_if_above_config_threshold
@@ -72,6 +75,8 @@ class ClassicCDFBaseExtractor(BaseExtractor, ABC, Generic[T_CogniteResource]):
72
75
  camel_case (bool, optional): Whether to use camelCase instead of snake_case for property names.
73
76
  Defaults to True.
74
77
  as_write (bool, optional): Whether to use the write/request format of the items. Defaults to False.
78
+ prefix (str, optional): A prefix to add to the rdf type. Defaults to None.
79
+ identifier (Literal["id", "externalId"], optional): The identifier to use. Defaults to "id".
75
80
  """
76
81
 
77
82
  _default_rdf_type: str
@@ -90,6 +95,7 @@ class ClassicCDFBaseExtractor(BaseExtractor, ABC, Generic[T_CogniteResource]):
90
95
  camel_case: bool = True,
91
96
  as_write: bool = False,
92
97
  prefix: str | None = None,
98
+ identifier: typing.Literal["id", "externalId"] = "id",
93
99
  ):
94
100
  self.namespace = namespace or DEFAULT_NAMESPACE
95
101
  self.items = items
@@ -101,9 +107,18 @@ class ClassicCDFBaseExtractor(BaseExtractor, ABC, Generic[T_CogniteResource]):
101
107
  self.camel_case = camel_case
102
108
  self.as_write = as_write
103
109
  self.prefix = prefix
110
+ self.identifier = identifier
111
+ # If identifier=externalId, we need to keep track of the external ids
112
+ # and use them in linking of Files, Sequences, TimeSeries, and Events.
113
+ self.asset_external_ids_by_id: dict[int, str] = {}
114
+ self.lookup_dataset_external_id: Callable[[int], str] | None = None
115
+ # Used by the ClassicGraphExtractor to log URIRefs
116
+ self._log_urirefs = False
117
+ self._uriref_by_external_id: dict[str, URIRef] = {}
104
118
 
105
119
  def extract(self) -> Iterable[Triple]:
106
120
  """Extracts an asset with the given asset_id."""
121
+ from ._assets import AssetsExtractor
107
122
 
108
123
  if self.total is not None and self.total > 0:
109
124
  to_iterate = iterate_progress_bar_if_above_config_threshold(
@@ -111,21 +126,40 @@ class ClassicCDFBaseExtractor(BaseExtractor, ABC, Generic[T_CogniteResource]):
111
126
  )
112
127
  else:
113
128
  to_iterate = self.items
129
+ if self.identifier == "externalId" and isinstance(self, AssetsExtractor):
130
+ to_iterate = self._store_asset_external_ids(to_iterate) # type: ignore[attr-defined]
131
+
114
132
  for no, asset in enumerate(to_iterate):
115
133
  yield from self._item2triples(asset)
116
134
  if self.limit and no >= self.limit:
117
135
  break
118
136
 
137
+ def _store_asset_external_ids(self, items: Iterable[T_CogniteResource]) -> Iterable[T_CogniteResource]:
138
+ for item in items:
139
+ if hasattr(item, "id") and hasattr(item, "external_id"):
140
+ self.asset_external_ids_by_id[item.id] = item.external_id
141
+ yield item
142
+
119
143
  def _item2triples(self, item: T_CogniteResource) -> list[Triple]:
120
- id_value: str | None
121
- if hasattr(item, "id"):
122
- id_value = str(item.id)
144
+ if self.identifier == "id":
145
+ id_value: str | None
146
+ if hasattr(item, "id"):
147
+ id_value = str(item.id)
148
+ else:
149
+ id_value = self._fallback_id(item)
150
+ if id_value is None:
151
+ return []
152
+ id_suffix = id_value
153
+ elif self.identifier == "externalId":
154
+ if not hasattr(item, "external_id"):
155
+ return []
156
+ id_suffix = self._external_id_as_uri_suffix(item.external_id)
123
157
  else:
124
- id_value = self._fallback_id(item)
125
- if id_value is None:
126
- return []
158
+ raise NeatValueError(f"Unknown identifier {self.identifier}")
127
159
 
128
- id_ = self.namespace[f"{self._instance_id_prefix}{id_value}"]
160
+ id_ = self.namespace[f"{self._instance_id_prefix}{id_suffix}"]
161
+ if self._log_urirefs and hasattr(item, "external_id"):
162
+ self._uriref_by_external_id[item.external_id] = id_
129
163
 
130
164
  type_ = self._get_rdf_type(item)
131
165
 
@@ -154,10 +188,25 @@ class ClassicCDFBaseExtractor(BaseExtractor, ABC, Generic[T_CogniteResource]):
154
188
  """This can be overridden to handle special cases for the item."""
155
189
  return []
156
190
 
191
+ @classmethod
192
+ def _external_id_as_uri_suffix(cls, external_id: str | None) -> str:
193
+ if external_id == "":
194
+ warnings.warn(NeatValueWarning(f"Empty external id in {cls._default_rdf_type}"), stacklevel=2)
195
+ return "empty"
196
+ elif external_id == "\x00":
197
+ warnings.warn(NeatValueWarning(f"Null external id in {cls._default_rdf_type}"), stacklevel=2)
198
+ return "null"
199
+ elif external_id is None:
200
+ warnings.warn(NeatValueWarning(f"None external id in {cls._default_rdf_type}"), stacklevel=2)
201
+ return "None"
202
+ # The external ID needs to pass the ^[^\\x00]{1,256}$ regex for the DMS API.
203
+ # In addition, neat internals requires the external ID to be a valid URI.
204
+ return urllib.parse.quote(external_id)
205
+
157
206
  def _fallback_id(self, item: T_CogniteResource) -> str | None:
158
207
  raise AttributeError(
159
208
  f"Item of type {type(item)} does not have an id attribute. "
160
- f"Please implement the _fallback_id method in the extractor."
209
+ "Please implement the _fallback_id method in the extractor."
161
210
  )
162
211
 
163
212
  def _metadata_to_triples(self, id_: URIRef, metadata: dict[str, str]) -> Iterable[Triple]:
@@ -181,10 +230,29 @@ class ClassicCDFBaseExtractor(BaseExtractor, ABC, Generic[T_CogniteResource]):
181
230
  return self._SPACE_PATTERN.sub("_", type_)
182
231
 
183
232
  def _as_object(self, raw: Any, key: str) -> Literal | URIRef:
233
+ """Return properly formatted object part of s-p-o triple"""
184
234
  if key in {"data_set_id", "dataSetId"}:
185
- return self.namespace[f"{InstanceIdPrefix.data_set}{raw}"]
235
+ if self.identifier == "externalId" and self.lookup_dataset_external_id:
236
+ try:
237
+ data_set_external_id = self.lookup_dataset_external_id(raw)
238
+ except KeyError:
239
+ return Literal("Unknown data set")
240
+ else:
241
+ return self.namespace[
242
+ f"{InstanceIdPrefix.data_set}{self._external_id_as_uri_suffix(data_set_external_id)}"
243
+ ]
244
+ else:
245
+ return self.namespace[f"{InstanceIdPrefix.data_set}{raw}"]
186
246
  elif key in {"assetId", "asset_id", "assetIds", "asset_ids", "parentId", "rootId", "parent_id", "root_id"}:
187
- return self.namespace[f"{InstanceIdPrefix.asset}{raw}"]
247
+ if self.identifier == "id":
248
+ return self.namespace[f"{InstanceIdPrefix.asset}{raw}"]
249
+ else:
250
+ try:
251
+ asset_external_id = self._external_id_as_uri_suffix(self.asset_external_ids_by_id[raw])
252
+ except KeyError:
253
+ return Literal("Unknown asset", datatype=XSD.string)
254
+ else:
255
+ return self.namespace[f"{InstanceIdPrefix.asset}{asset_external_id}"]
188
256
  elif key in {
189
257
  "startTime",
190
258
  "endTime",
@@ -223,10 +291,21 @@ class ClassicCDFBaseExtractor(BaseExtractor, ABC, Generic[T_CogniteResource]):
223
291
  camel_case: bool = True,
224
292
  as_write: bool = False,
225
293
  prefix: str | None = None,
294
+ identifier: typing.Literal["id", "externalId"] = "id",
226
295
  ):
227
296
  total, items = cls._handle_no_access(lambda: cls._from_dataset(client, data_set_external_id))
228
297
  return cls(
229
- items, namespace, to_type, total, limit, unpack_metadata, skip_metadata_values, camel_case, as_write, prefix
298
+ items,
299
+ namespace,
300
+ to_type,
301
+ total,
302
+ limit,
303
+ unpack_metadata,
304
+ skip_metadata_values,
305
+ camel_case,
306
+ as_write,
307
+ prefix,
308
+ identifier,
230
309
  )
231
310
 
232
311
  @classmethod
@@ -249,10 +328,21 @@ class ClassicCDFBaseExtractor(BaseExtractor, ABC, Generic[T_CogniteResource]):
249
328
  camel_case: bool = True,
250
329
  as_write: bool = False,
251
330
  prefix: str | None = None,
331
+ identifier: typing.Literal["id", "externalId"] = "id",
252
332
  ):
253
333
  total, items = cls._handle_no_access(lambda: cls._from_hierarchy(client, root_asset_external_id))
254
334
  return cls(
255
- items, namespace, to_type, total, limit, unpack_metadata, skip_metadata_values, camel_case, as_write, prefix
335
+ items,
336
+ namespace,
337
+ to_type,
338
+ total,
339
+ limit,
340
+ unpack_metadata,
341
+ skip_metadata_values,
342
+ camel_case,
343
+ as_write,
344
+ prefix,
345
+ identifier,
256
346
  )
257
347
 
258
348
  @classmethod
@@ -274,10 +364,21 @@ class ClassicCDFBaseExtractor(BaseExtractor, ABC, Generic[T_CogniteResource]):
274
364
  camel_case: bool = True,
275
365
  as_write: bool = False,
276
366
  prefix: str | None = None,
367
+ identifier: typing.Literal["id", "externalId"] = "id",
277
368
  ):
278
369
  total, items = cls._from_file(file_path)
279
370
  return cls(
280
- items, namespace, to_type, total, limit, unpack_metadata, skip_metadata_values, camel_case, as_write, prefix
371
+ items,
372
+ namespace,
373
+ to_type,
374
+ total,
375
+ limit,
376
+ unpack_metadata,
377
+ skip_metadata_values,
378
+ camel_case,
379
+ as_write,
380
+ prefix,
381
+ identifier,
281
382
  )
282
383
 
283
384
  @classmethod
@@ -1,3 +1,5 @@
1
+ import typing
2
+ import urllib.parse
1
3
  import warnings
2
4
  from collections import defaultdict
3
5
  from collections.abc import Iterable, Sequence
@@ -9,8 +11,8 @@ from rdflib import Namespace, URIRef
9
11
 
10
12
  from cognite.neat._constants import CLASSIC_CDF_NAMESPACE, DEFAULT_NAMESPACE, get_default_prefixes_and_namespaces
11
13
  from cognite.neat._graph.extractors._base import KnowledgeGraphExtractor
12
- from cognite.neat._issues.errors import NeatValueError
13
- from cognite.neat._issues.warnings import CDFAuthWarning
14
+ from cognite.neat._issues.errors import NeatValueError, ResourceNotFoundError
15
+ from cognite.neat._issues.warnings import CDFAuthWarning, NeatValueWarning
14
16
  from cognite.neat._rules._shared import ReadRules
15
17
  from cognite.neat._rules.catalog import classic_model
16
18
  from cognite.neat._rules.models import InformationInputRules, InformationRules
@@ -101,6 +103,7 @@ class ClassicGraphExtractor(KnowledgeGraphExtractor):
101
103
  namespace: Namespace | None = None,
102
104
  limit_per_type: int | None = None,
103
105
  prefix: str | None = None,
106
+ identifier: typing.Literal["id", "externalId"] = "id",
104
107
  ):
105
108
  self._client = client
106
109
  if sum([bool(data_set_external_id), bool(root_asset_external_id)]) != 1:
@@ -115,16 +118,23 @@ class ClassicGraphExtractor(KnowledgeGraphExtractor):
115
118
  camel_case=True,
116
119
  limit=limit_per_type,
117
120
  prefix=prefix,
121
+ identifier=identifier,
118
122
  )
123
+ self._identifier = identifier
119
124
  self._prefix = prefix
120
125
  self._limit_per_type = limit_per_type
121
126
 
127
+ self._uris_by_external_id_by_type: dict[InstanceIdPrefix, dict[str, URIRef]] = defaultdict(dict)
122
128
  self._source_external_ids_by_type: dict[InstanceIdPrefix, set[str]] = defaultdict(set)
123
129
  self._target_external_ids_by_type: dict[InstanceIdPrefix, set[str]] = defaultdict(set)
130
+ self._relationship_subject_predicate_type_external_id: list[tuple[URIRef, URIRef, str, str]] = []
124
131
  self._labels: set[str] = set()
125
132
  self._data_set_ids: set[int] = set()
133
+ self._data_set_external_ids: set[str] = set()
126
134
  self._extracted_labels = False
127
135
  self._extracted_data_sets = False
136
+ self._asset_external_ids_by_id: dict[int, str] = {}
137
+ self._dataset_external_ids_by_id: dict[int, str] = {}
128
138
 
129
139
  def _get_activity_names(self) -> list[str]:
130
140
  activities = [data_access_object.extractor_cls.__name__ for data_access_object in self._classic_node_types] + [
@@ -138,12 +148,17 @@ class ClassicGraphExtractor(KnowledgeGraphExtractor):
138
148
 
139
149
  def extract(self) -> Iterable[Triple]:
140
150
  """Extracts all classic CDF Resources."""
151
+ self._validate_exists()
152
+
141
153
  yield from self._extract_core_start_nodes()
142
154
 
143
155
  yield from self._extract_start_node_relationships()
144
156
 
145
157
  yield from self._extract_core_end_nodes()
146
158
 
159
+ if self._identifier == "id":
160
+ yield from self._extract_relationship_target_triples()
161
+
147
162
  try:
148
163
  yield from self._extract_labels()
149
164
  except CogniteAPIError as e:
@@ -209,7 +224,17 @@ class ClassicGraphExtractor(KnowledgeGraphExtractor):
209
224
  else:
210
225
  resource = "unknown"
211
226
  external_id = "unknown"
212
- return DEFAULT_NAMESPACE[f"{self._client.config.project}/{resource}/{external_id}"]
227
+ return DEFAULT_NAMESPACE[f"{self._client.config.project}/{resource}/{urllib.parse.quote(external_id)}"]
228
+
229
+ def _validate_exists(self) -> None:
230
+ if self._data_set_external_id:
231
+ if self._client.data_sets.retrieve(external_id=self._data_set_external_id) is None:
232
+ raise ResourceNotFoundError(self._data_set_external_id, "data set")
233
+ elif self._root_asset_external_id:
234
+ if self._client.assets.retrieve(external_id=self._root_asset_external_id) is None:
235
+ raise ResourceNotFoundError(self._root_asset_external_id, "root asset")
236
+ else:
237
+ raise ValueError("Exactly one of data_set_external_id or root_asset_external_id must be set.")
213
238
 
214
239
  def _extract_core_start_nodes(self):
215
240
  for core_node in self._classic_node_types:
@@ -224,8 +249,20 @@ class ClassicGraphExtractor(KnowledgeGraphExtractor):
224
249
  else:
225
250
  raise ValueError("Exactly one of data_set_external_id or root_asset_external_id must be set.")
226
251
 
252
+ if self._identifier == "externalId":
253
+ if isinstance(extractor, AssetsExtractor):
254
+ self._asset_external_ids_by_id = extractor.asset_external_ids_by_id
255
+ else:
256
+ extractor.asset_external_ids_by_id = self._asset_external_ids_by_id
257
+ extractor.lookup_dataset_external_id = self._lookup_dataset
258
+ elif self._identifier == "id":
259
+ extractor._log_urirefs = True
260
+
227
261
  yield from self._extract_with_logging_label_dataset(extractor, core_node.resource_type)
228
262
 
263
+ if self._identifier == "id":
264
+ self._uris_by_external_id_by_type[core_node.resource_type].update(extractor._uriref_by_external_id)
265
+
229
266
  def _extract_start_node_relationships(self):
230
267
  for start_resource_type, source_external_ids in self._source_external_ids_by_type.items():
231
268
  start_type = start_resource_type.removesuffix("_")
@@ -236,6 +273,8 @@ class ClassicGraphExtractor(KnowledgeGraphExtractor):
236
273
  extractor = RelationshipsExtractor(relationship_iterator, **self._extractor_args)
237
274
  # This is a private attribute, but we need to set it to log the target nodes.
238
275
  extractor._log_target_nodes = True
276
+ if self._identifier == "id":
277
+ extractor._uri_by_external_id_by_by_type = self._uris_by_external_id_by_type
239
278
 
240
279
  yield from extractor.extract()
241
280
 
@@ -254,6 +293,11 @@ class ClassicGraphExtractor(KnowledgeGraphExtractor):
254
293
  ):
255
294
  self._target_external_ids_by_type[end_type].add(external_id)
256
295
 
296
+ if self._identifier == "id":
297
+ # We need to store all future target triples which we will lookup after fetching
298
+ # the target nodes.
299
+ self._relationship_subject_predicate_type_external_id.extend(extractor._target_triples)
300
+
257
301
  def _extract_core_end_nodes(self):
258
302
  for core_node in self._classic_node_types:
259
303
  target_external_ids = self._target_external_ids_by_type[core_node.resource_type]
@@ -264,8 +308,26 @@ class ClassicGraphExtractor(KnowledgeGraphExtractor):
264
308
  ):
265
309
  resource_iterator = api.retrieve_multiple(external_ids=list(chunk), ignore_unknown_ids=True)
266
310
  extractor = core_node.extractor_cls(resource_iterator, **self._extractor_args)
311
+
312
+ extractor.asset_external_ids_by_id = self._asset_external_ids_by_id
313
+ extractor.lookup_dataset_external_id = self._lookup_dataset
314
+ if self._identifier == "id":
315
+ extractor._log_urirefs = True
316
+
267
317
  yield from self._extract_with_logging_label_dataset(extractor)
268
318
 
319
+ if self._identifier == "id":
320
+ self._uris_by_external_id_by_type[core_node.resource_type].update(extractor._uriref_by_external_id)
321
+
322
+ def _extract_relationship_target_triples(self):
323
+ for id_, predicate, type_, external_id in self._relationship_subject_predicate_type_external_id:
324
+ try:
325
+ object_uri = self._uris_by_external_id_by_type[InstanceIdPrefix.from_str(type_)][external_id]
326
+ except KeyError:
327
+ warnings.warn(NeatValueWarning(f"Missing externalId {external_id} for {type_}"), stacklevel=2)
328
+ else:
329
+ yield id_, predicate, object_uri
330
+
269
331
  def _extract_labels(self):
270
332
  for chunk in self._chunk(list(self._labels), description="Extracting labels"):
271
333
  label_iterator = self._client.labels.retrieve(external_id=list(chunk), ignore_unknown_ids=True)
@@ -275,6 +337,11 @@ class ClassicGraphExtractor(KnowledgeGraphExtractor):
275
337
  for chunk in self._chunk(list(self._data_set_ids), description="Extracting data sets"):
276
338
  data_set_iterator = self._client.data_sets.retrieve_multiple(ids=list(chunk), ignore_unknown_ids=True)
277
339
  yield from DataSetExtractor(data_set_iterator, **self._extractor_args).extract()
340
+ for chunk in self._chunk(list(self._data_set_external_ids), description="Extracting data sets"):
341
+ data_set_iterator = self._client.data_sets.retrieve_multiple(
342
+ external_ids=list(chunk), ignore_unknown_ids=True
343
+ )
344
+ yield from DataSetExtractor(data_set_iterator, **self._extractor_args).extract()
278
345
 
279
346
  def _extract_with_logging_label_dataset(
280
347
  self, extractor: ClassicCDFBaseExtractor, resource_type: InstanceIdPrefix | None = None
@@ -285,9 +352,11 @@ class ClassicGraphExtractor(KnowledgeGraphExtractor):
285
352
  elif triple[1] == self._namespace.labels:
286
353
  self._labels.add(remove_namespace_from_uri(triple[2]).removeprefix(InstanceIdPrefix.label))
287
354
  elif triple[1] == self._namespace.dataSetId:
288
- self._data_set_ids.add(
289
- int(remove_namespace_from_uri(triple[2]).removeprefix(InstanceIdPrefix.data_set))
290
- )
355
+ identifier = remove_namespace_from_uri(triple[2]).removeprefix(InstanceIdPrefix.data_set)
356
+ try:
357
+ self._data_set_ids.add(int(identifier))
358
+ except ValueError:
359
+ self._data_set_external_ids.add(identifier)
291
360
  yield triple
292
361
 
293
362
  @staticmethod
@@ -297,3 +366,15 @@ class ClassicGraphExtractor(KnowledgeGraphExtractor):
297
366
  return iterate_progress_bar(to_iterate, (len(items) // 1_000) + 1, description)
298
367
  else:
299
368
  return to_iterate
369
+
370
+ def _lookup_dataset(self, dataset_id: int) -> str:
371
+ if dataset_id not in self._dataset_external_ids_by_id:
372
+ try:
373
+ if (dataset := self._client.data_sets.retrieve(id=dataset_id)) and dataset.external_id:
374
+ self._dataset_external_ids_by_id[dataset_id] = dataset.external_id
375
+ else:
376
+ raise KeyError(f"Could not find dataset with id {dataset_id}.")
377
+ except CogniteAPIError as e:
378
+ warnings.warn(CDFAuthWarning("lookup dataset", str(e)), stacklevel=2)
379
+ return f"{InstanceIdPrefix.data_set}{dataset_id}"
380
+ return self._dataset_external_ids_by_id[dataset_id]
@@ -1,11 +1,16 @@
1
+ import typing
2
+ import warnings
1
3
  from collections import defaultdict
2
4
  from collections.abc import Callable, Iterable, Set
3
5
  from pathlib import Path
6
+ from typing import Any
4
7
 
5
8
  from cognite.client import CogniteClient
6
9
  from cognite.client.data_classes import Relationship, RelationshipList
7
- from rdflib import Namespace
10
+ from rdflib import Namespace, URIRef
8
11
 
12
+ from cognite.neat._issues.warnings import NeatValueWarning
13
+ from cognite.neat._shared import Triple
9
14
  from cognite.neat._utils.auxiliary import create_sha256_hash
10
15
 
11
16
  from ._base import DEFAULT_SKIP_METADATA_VALUES, ClassicCDFBaseExtractor, InstanceIdPrefix, T_CogniteResource
@@ -29,9 +34,17 @@ class RelationshipsExtractor(ClassicCDFBaseExtractor[Relationship]):
29
34
  camel_case: bool = True,
30
35
  as_write: bool = False,
31
36
  prefix: str | None = None,
37
+ identifier: typing.Literal["id", "externalId"] = "id",
32
38
  ):
39
+ # This is used by the ClassicExtractor to log the target nodes, such
40
+ # that it can extract them.
41
+ # It is private to avoid exposing it to the user.
42
+ self._target_external_ids_by_type: dict[InstanceIdPrefix, set[str]] = defaultdict(set)
43
+ self._log_target_nodes = False
44
+ # Ensure that this becomes an iterator, even if it is a list.
45
+ to_iterate = (self._log_target_nodes_if_set(item) for item in items)
33
46
  super().__init__(
34
- items,
47
+ to_iterate,
35
48
  namespace=namespace,
36
49
  to_type=to_type,
37
50
  total=total,
@@ -41,12 +54,39 @@ class RelationshipsExtractor(ClassicCDFBaseExtractor[Relationship]):
41
54
  camel_case=camel_case,
42
55
  as_write=as_write,
43
56
  prefix=prefix,
57
+ identifier=identifier,
44
58
  )
45
- # This is used by the ClassicExtractor to log the target nodes, such
46
- # that it can extract them.
47
- # It is private to avoid exposing it to the user.
48
- self._log_target_nodes = False
49
- self._target_external_ids_by_type: dict[InstanceIdPrefix, set[str]] = defaultdict(set)
59
+ self._uri_by_external_id_by_by_type: dict[InstanceIdPrefix, dict[str, URIRef]] = defaultdict(dict)
60
+ self._target_triples: list[tuple[URIRef, URIRef, str, str]] = []
61
+
62
+ def _log_target_nodes_if_set(self, item: Relationship) -> Relationship:
63
+ if not self._log_target_nodes:
64
+ return item
65
+ if item.target_type and item.target_external_id:
66
+ self._target_external_ids_by_type[InstanceIdPrefix.from_str(item.target_type)].add(item.target_external_id)
67
+ return item
68
+
69
+ def _item2triples_special_cases(self, id_: URIRef, dumped: dict[str, Any]) -> list[Triple]:
70
+ if self.identifier == "externalId":
71
+ return []
72
+ triples: list[Triple] = []
73
+ if (source_external_id := dumped.pop("sourceExternalId")) and "sourceType" in dumped:
74
+ source_type = dumped["sourceType"]
75
+ try:
76
+ source_uri = self._uri_by_external_id_by_by_type[InstanceIdPrefix.from_str(source_type)][
77
+ source_external_id
78
+ ]
79
+ except KeyError:
80
+ warnings.warn(
81
+ NeatValueWarning(f"Missing externalId {source_external_id} for {source_type}"), stacklevel=2
82
+ )
83
+ else:
84
+ triples.append((id_, self.namespace["sourceExternalId"], source_uri))
85
+ if (target_external_id := dumped.pop("targetExternalId")) and "targetType" in dumped:
86
+ target_type = dumped["targetType"]
87
+ # We do not yet have the target nodes, so we log them for later extraction.
88
+ self._target_triples.append((id_, self.namespace["targetExternalId"], target_type, target_external_id))
89
+ return triples
50
90
 
51
91
  @classmethod
52
92
  def _from_dataset(
@@ -69,10 +109,6 @@ class RelationshipsExtractor(ClassicCDFBaseExtractor[Relationship]):
69
109
  return len(relationships), relationships
70
110
 
71
111
  def _fallback_id(self, item: Relationship) -> str | None:
72
- if item.external_id and item.source_external_id and item.target_external_id:
73
- if self._log_target_nodes and item.target_type and item.target_external_id:
74
- self._target_external_ids_by_type[InstanceIdPrefix.from_str(item.target_type)].add(
75
- item.target_external_id
76
- )
112
+ if item.external_id:
77
113
  return create_sha256_hash(item.external_id)
78
114
  return None
@@ -1,5 +1,6 @@
1
1
  import itertools
2
2
  import json
3
+ import typing
3
4
  from collections.abc import Callable, Iterable, Set
4
5
  from pathlib import Path
5
6
  from typing import Any
@@ -53,10 +54,21 @@ class SequencesExtractor(ClassicCDFBaseExtractor[NeatSequence]):
53
54
  camel_case: bool = True,
54
55
  as_write: bool = False,
55
56
  prefix: str | None = None,
57
+ identifier: typing.Literal["id", "externalId"] = "id",
56
58
  unpack_columns: bool = False,
57
59
  ):
58
60
  super().__init__(
59
- items, namespace, to_type, total, limit, unpack_metadata, skip_metadata_values, camel_case, as_write, prefix
61
+ items,
62
+ namespace,
63
+ to_type,
64
+ total,
65
+ limit,
66
+ unpack_metadata,
67
+ skip_metadata_values,
68
+ camel_case,
69
+ as_write,
70
+ prefix,
71
+ identifier,
60
72
  )
61
73
  self.unpack_columns = unpack_columns
62
74
 
@@ -73,6 +85,7 @@ class SequencesExtractor(ClassicCDFBaseExtractor[NeatSequence]):
73
85
  camel_case: bool = True,
74
86
  as_write: bool = False,
75
87
  prefix: str | None = None,
88
+ identifier: typing.Literal["id", "externalId"] = "id",
76
89
  unpack_columns: bool = False,
77
90
  ):
78
91
  total, items = cls._handle_no_access(lambda: cls._from_dataset(client, data_set_external_id))
@@ -87,6 +100,7 @@ class SequencesExtractor(ClassicCDFBaseExtractor[NeatSequence]):
87
100
  camel_case,
88
101
  as_write,
89
102
  prefix,
103
+ identifier,
90
104
  unpack_columns,
91
105
  )
92
106
 
@@ -103,6 +117,7 @@ class SequencesExtractor(ClassicCDFBaseExtractor[NeatSequence]):
103
117
  camel_case: bool = True,
104
118
  as_write: bool = False,
105
119
  prefix: str | None = None,
120
+ identifier: typing.Literal["id", "externalId"] = "id",
106
121
  unpack_columns: bool = False,
107
122
  ):
108
123
  total, items = cls._handle_no_access(lambda: cls._from_hierarchy(client, root_asset_external_id))
@@ -117,6 +132,7 @@ class SequencesExtractor(ClassicCDFBaseExtractor[NeatSequence]):
117
132
  camel_case,
118
133
  as_write,
119
134
  prefix,
135
+ identifier,
120
136
  unpack_columns,
121
137
  )
122
138
 
@@ -132,6 +148,7 @@ class SequencesExtractor(ClassicCDFBaseExtractor[NeatSequence]):
132
148
  camel_case: bool = True,
133
149
  as_write: bool = False,
134
150
  prefix: str | None = None,
151
+ identifier: typing.Literal["id", "externalId"] = "id",
135
152
  unpack_columns: bool = False,
136
153
  ):
137
154
  total, items = cls._from_file(file_path)
@@ -146,6 +163,7 @@ class SequencesExtractor(ClassicCDFBaseExtractor[NeatSequence]):
146
163
  camel_case,
147
164
  as_write,
148
165
  prefix,
166
+ identifier,
149
167
  unpack_columns,
150
168
  )
151
169