cognite-neat 0.97.2__py3-none-any.whl → 0.97.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

@@ -42,6 +42,27 @@ class Queries:
42
42
  for res in list(self.graph.query(query_statement))
43
43
  ]
44
44
 
45
+ @property
46
+ def types(self) -> dict[URIRef, str]:
47
+ """Types and their short form in the graph"""
48
+ query = """SELECT DISTINCT ?type
49
+ WHERE {?s a ?type .}"""
50
+ return {type_: remove_namespace_from_uri(cast(URIRef, type_)) for (type_,) in list(self.graph.query(query))} # type: ignore[misc, index, arg-type]
51
+
52
+ def type_uri(self, type_: str) -> list[URIRef]:
53
+ """Get the URIRef of a type"""
54
+ return [k for k, v in self.types.items() if v == type_]
55
+
56
+ @property
57
+ def properties(self) -> dict[URIRef, str]:
58
+ query = """SELECT DISTINCT ?property
59
+ WHERE {?s ?property ?o . FILTER(?property != rdf:type)}"""
60
+ return {type_: remove_namespace_from_uri(cast(URIRef, type_)) for (type_,) in list(self.graph.query(query))} # type: ignore[misc, index, arg-type]
61
+
62
+ def property_uri(self, property_: str) -> list[URIRef]:
63
+ """Get the URIRef of a type"""
64
+ return [k for k, v in self.properties.items() if v == property_]
65
+
45
66
  def list_instances_ids_of_class(self, class_uri: URIRef, limit: int = -1) -> list[URIRef]:
46
67
  """Get instances ids for a given class
47
68
 
@@ -101,7 +122,7 @@ class Queries:
101
122
  # We cannot include the RDF.type in case there is a neat:type property
102
123
  return [remove_namespace_from_uri(list(triple)) for triple in result if triple[1] != RDF.type] # type: ignore[misc, index, arg-type]
103
124
 
104
- def types_with_property(self, property_uri: URIRef) -> list[URIRef]:
125
+ def type_with_property(self, type_: URIRef, property_uri: URIRef) -> bool:
105
126
  """Check if a property exists in the graph store
106
127
 
107
128
  Args:
@@ -110,8 +131,8 @@ class Queries:
110
131
  Returns:
111
132
  True if property exists, False otherwise
112
133
  """
113
- query = f"SELECT DISTINCT ?t WHERE {{ ?s <{property_uri}> ?o ; a ?t}} Limit 1"
114
- return cast(list[URIRef], [t[0] for t in self.graph.query(query)]) # type: ignore[index]
134
+ query = f"SELECT ?o WHERE {{ ?s a <{type_}> ; <{property_uri}> ?o .}} Limit 1"
135
+ return bool(list(self.graph.query(query)))
115
136
 
116
137
  def has_namespace(self, namespace: Namespace) -> bool:
117
138
  """Check if a namespace exists in the graph store
@@ -250,7 +271,7 @@ class Queries:
250
271
  result = self.graph.query(query)
251
272
 
252
273
  # We cannot include the RDF.type in case there is a neat:type property
253
- return [remove_namespace_from_uri(cast(ResultRow, triple)) for triple in result if triple[1] != RDF.type] # type: ignore[misc, index]
274
+ return [remove_namespace_from_uri(cast(ResultRow, triple)) for triple in result if triple[1] != RDF.type] # type: ignore[misc, index, arg-type]
254
275
  else:
255
276
  warnings.warn(
256
277
  "No rules found for the graph store, returning empty list.",
@@ -157,21 +157,6 @@ class DMSPostValidation:
157
157
  )
158
158
  )
159
159
 
160
- # This sets the container definition for all the properties where it is not defined.
161
- # This allows the user to define the container only once.
162
- value_type = next(iter(value_types))
163
- list_definition = next(iter(list_definitions)) if list_definitions else None
164
- nullable_definition = next(iter(nullable_definitions)) if nullable_definitions else None
165
- default_definition = next(iter(default_definitions)) if default_definitions else None
166
- index_definition = next(iter(index_definitions)).split(",") if index_definitions else None
167
- constraint_definition = next(iter(constraint_definitions)).split(",") if constraint_definitions else None
168
- for _, prop in properties:
169
- prop.value_type = value_type
170
- prop.is_list = prop.is_list or list_definition
171
- prop.nullable = prop.nullable or nullable_definition
172
- prop.default = prop.default or default_definition
173
- prop.index = prop.index or index_definition
174
- prop.constraint = prop.constraint or constraint_definition
175
160
  self.issue_list.extend(errors)
176
161
 
177
162
  def _referenced_views_and_containers_are_existing_and_proper_size(self) -> None:
@@ -21,6 +21,7 @@ from cognite.neat._store._provenance import (
21
21
  INSTANCES_ENTITY,
22
22
  Change,
23
23
  )
24
+ from cognite.neat._utils.auth import _CLIENT_NAME
24
25
 
25
26
  from ._inspect import InspectAPI
26
27
  from ._prepare import PrepareAPI
@@ -51,6 +52,8 @@ class NeatSession:
51
52
  self.show = ShowAPI(self._state)
52
53
  self.set = SetAPI(self._state, verbose)
53
54
  self.inspect = InspectAPI(self._state)
55
+ if self._client is not None and self._client._config is not None:
56
+ self._client._config.client_name = _CLIENT_NAME
54
57
  if load_engine != "skip" and (engine_version := load_neat_engine(client, load_engine)):
55
58
  print(f"Neat Engine {engine_version} loaded.")
56
59
 
@@ -12,7 +12,7 @@ from cognite.neat._rules.transformers import ReduceCogniteModel, ToCompliantEnti
12
12
  from cognite.neat._store._provenance import Change
13
13
 
14
14
  from ._state import SessionState
15
- from .exceptions import intercept_session_exceptions
15
+ from .exceptions import NeatSessionError, intercept_session_exceptions
16
16
 
17
17
 
18
18
  @intercept_session_exceptions
@@ -32,18 +32,18 @@ class InstancePrepareAPI:
32
32
 
33
33
  def make_connection_on_exact_match(
34
34
  self,
35
- source: tuple[URIRef, URIRef],
36
- target: tuple[URIRef, URIRef],
37
- connection: URIRef | None = None,
35
+ source: tuple[str, str],
36
+ target: tuple[str, str],
37
+ connection: str | None = None,
38
38
  limit: int | None = 100,
39
39
  ) -> None:
40
40
  """Make connection on exact match.
41
41
 
42
42
  Args:
43
- source: The source of the connection. A tuple of (rdf type, property) where
43
+ source: The source of the connection. A tuple of (type, property) where
44
44
  where property is the property that should be matched on the source
45
45
  to make the connection with the target.
46
- target: The target of the connection. A tuple of (rdf type, property) where
46
+ target: The target of the connection. A tuple of (type, property) where
47
47
  where property is the property that should be matched on the target
48
48
  to make the connection with the source.
49
49
 
@@ -51,11 +51,19 @@ class InstancePrepareAPI:
51
51
  will be made by lowercasing the target type.
52
52
  limit: The maximum number of connections to make. If None, all connections
53
53
 
54
+ !!! note "Make Connection on Exact Match"
55
+ This method will make a connection between the source and target based on the exact match:
56
+ (SourceType)-[sourceProperty]->(sourceValue) == (TargetType)-[targetProperty]->(targetValue)
57
+
58
+ The connection will be made by creating a new property on the source type that will contain the
59
+ target value, as follows:
60
+ (SourceType)-[connection]->(TargetType)
61
+
54
62
 
55
63
  """
56
64
 
57
- subject_type, subject_predicate = source
58
- object_type, object_predicate = target
65
+ subject_type, subject_predicate = self._get_type_and_property_uris(*source)
66
+ object_type, object_predicate = self._get_type_and_property_uris(*target)
59
67
 
60
68
  transformer = MakeConnectionOnExactMatch(
61
69
  subject_type,
@@ -68,6 +76,24 @@ class InstancePrepareAPI:
68
76
 
69
77
  self._state.instances.store.transform(transformer)
70
78
 
79
+ def _get_type_and_property_uris(self, type_: str, property_: str) -> tuple[URIRef, URIRef]:
80
+ type_uri = self._state.instances.store.queries.type_uri(type_)
81
+ property_uri = self._state.instances.store.queries.property_uri(property_)
82
+
83
+ if not type_uri:
84
+ raise NeatSessionError(f"Type {type_} does not exist in the graph.")
85
+ elif len(type_uri) > 1:
86
+ raise NeatSessionError(f"{type_} has multiple ids found in the graph: {','.join(type_uri)}.")
87
+
88
+ if not property_uri:
89
+ raise NeatSessionError(f"Property {property_} does not exist in the graph.")
90
+ elif len(type_uri) > 1:
91
+ raise NeatSessionError(f"{property_} has multiple ids found in the graph: {','.join(property_uri)}.")
92
+
93
+ if not self._state.instances.store.queries.type_with_property(type_uri[0], property_uri[0]):
94
+ raise NeatSessionError(f"Property {property_} is not defined for type {type_}. Cannot make connection")
95
+ return type_uri[0], property_uri[0]
96
+
71
97
 
72
98
  @intercept_session_exceptions
73
99
  class DataModelPrepareAPI:
cognite/neat/_version.py CHANGED
@@ -1,2 +1,2 @@
1
- __version__ = "0.97.2"
1
+ __version__ = "0.97.3"
2
2
  __engine__ = "^1.0.3"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cognite-neat
3
- Version: 0.97.2
3
+ Version: 0.97.3
4
4
  Summary: Knowledge graph transformation
5
5
  Home-page: https://cognite-neat.readthedocs-hosted.com/
6
6
  License: Apache-2.0
@@ -105,7 +105,7 @@ cognite/neat/_graph/loaders/_base.py,sha256=tjplRd-vbWhWyys0Ll3KgHR3F3ETlP_dXJ3e
105
105
  cognite/neat/_graph/loaders/_rdf2asset.py,sha256=OMfTVbVEx6yAUlds7c2mVcgnBV0Cq5DiQ7joW3-yy0Y,17525
106
106
  cognite/neat/_graph/loaders/_rdf2dms.py,sha256=kR5yjXS5VDHMUFff5WSTrZRqKSzX53SlEbcwHMVh8J8,15951
107
107
  cognite/neat/_graph/queries/__init__.py,sha256=BgDd-037kvtWwAoGAy8eORVNMiZ5-E9sIV0txIpeaN4,50
108
- cognite/neat/_graph/queries/_base.py,sha256=NuDG8H4wC7R4Py8kpgiWEbfAVZajV3L2ivaHDyYa8Iw,12714
108
+ cognite/neat/_graph/queries/_base.py,sha256=FhRCUQ-jpVdtC6qdBWqTlh6JP29BigQJoyACkrr5bBM,13700
109
109
  cognite/neat/_graph/queries/_construct.py,sha256=CW8uHtXXACUXDj1AcEjROXtvoiuyx0CTgZ0bURY5Neo,7213
110
110
  cognite/neat/_graph/queries/_shared.py,sha256=K3svLkvw-DWPZUwIwpJRjPKg5UIRKFCn5jBLpuJjiHc,5330
111
111
  cognite/neat/_graph/transformers/__init__.py,sha256=CdlG9Bk--bLyO5S8jJOkOriZQwJtukXj7oRPXfKKJSY,984
@@ -188,7 +188,7 @@ cognite/neat/_rules/models/dms/_exporter.py,sha256=gCATniEtjhCOpofnY4jjTRnkm1s84
188
188
  cognite/neat/_rules/models/dms/_rules.py,sha256=3_cn4wIzQDwfSmIwCFRKDJLhvuXxUrz4ompDLtT3Fx0,21445
189
189
  cognite/neat/_rules/models/dms/_rules_input.py,sha256=8tOJ9XNX9qBW-PEKAyCJ1mvG1BgrEbJBk7VYTTKG_D0,11813
190
190
  cognite/neat/_rules/models/dms/_schema.py,sha256=HSmSDvOm5S0x4Vb9tH9Jvd5i9tXiiM08E_Sdu6q_iA8,50783
191
- cognite/neat/_rules/models/dms/_validation.py,sha256=LxufRBRUCqvO1yztbk01O5dcX4N4Elf75JHqxt6p8WM,18398
191
+ cognite/neat/_rules/models/dms/_validation.py,sha256=63cS1troy3CBpfeIst0AtpKGYS1-IiZEbh_6Y8Pv3bQ,17256
192
192
  cognite/neat/_rules/models/domain.py,sha256=zzmurr1caPZaz6hoUwveCHlSM-bDf9Rt-S1m5HWOfRk,4295
193
193
  cognite/neat/_rules/models/entities/__init__.py,sha256=QD-h79HhjqCsgscNU5kuf1ieRCE94dOfpujLuzYbtHk,1469
194
194
  cognite/neat/_rules/models/entities/_constants.py,sha256=ToiLaaF-hGLPfn3AsKIIrfB4ZdTk4cY1RjM9gA1Qjkg,288
@@ -211,9 +211,9 @@ cognite/neat/_rules/transformers/_mapping.py,sha256=RWHKPMaP3JdeCNvoDGu9ZGHxfyeI
211
211
  cognite/neat/_rules/transformers/_pipelines.py,sha256=-E5Hgitnr6ee8R9_3sqtjmWIPJ0w1xaLErG6Fo6ExVU,2603
212
212
  cognite/neat/_rules/transformers/_verification.py,sha256=8p3cpVTfBkEeRLZSFJh_tby8ScRJodjSvrt2-_JBwQ4,2885
213
213
  cognite/neat/_session/__init__.py,sha256=fxQ5URVlUnmEGYyB8Baw7IDq-uYacqkigbc4b-Pr9Fw,58
214
- cognite/neat/_session/_base.py,sha256=eSMjfptLG43UFctdm7uXjAXkVjN3pwqB7NICplj8U2k,8356
214
+ cognite/neat/_session/_base.py,sha256=NHyESFlD3N1aUW6oJ3emuUSklopQUXeXblUk9-eje8U,8540
215
215
  cognite/neat/_session/_inspect.py,sha256=42mWP2GbQPxsM8-Xt-jY3_LHH0VNikkX8I2t1D_tj5I,7058
216
- cognite/neat/_session/_prepare.py,sha256=AIJj28wCbZizbiCeE5wfB4RYZbyoc3bu6ESYgfb9AaY,9673
216
+ cognite/neat/_session/_prepare.py,sha256=RnKetAX305PwdHQwOag1NHxmU1UTyAQMTAzQAw7MxLw,11219
217
217
  cognite/neat/_session/_read.py,sha256=d6O-ymlVx4o0mjKDIlrHOXiTOZxrdxhEX6mieLLETEI,9461
218
218
  cognite/neat/_session/_set.py,sha256=zNhHI-7WON3NUXCc1Ajo2ti8l5kPYmHeJ8MxJ_QLIJk,1927
219
219
  cognite/neat/_session/_show.py,sha256=-f1-f6vJKdpZODYuFv6TFmO1BuELUldfCqZqeLvr0NE,14161
@@ -247,7 +247,7 @@ cognite/neat/_utils/text.py,sha256=PvTEsEjaTu8SE8yYaKUrce4msboMj933dK7-0Eey_rE,3
247
247
  cognite/neat/_utils/time_.py,sha256=O30LUiDH9TdOYz8_a9pFqTtJdg8vEjC3qHCk8xZblG8,345
248
248
  cognite/neat/_utils/upload.py,sha256=iWKmsQgw4EHLv-11NjYu7zAj5LtqTAfNa87a1kWeuaU,5727
249
249
  cognite/neat/_utils/xml_.py,sha256=FQkq84u35MUsnKcL6nTMJ9ajtG9D5i1u4VBnhGqP2DQ,1710
250
- cognite/neat/_version.py,sha256=i1XG3bCI016w9QBXpZK2V7_H3qAxKFiPgn1XbWWNSmk,45
250
+ cognite/neat/_version.py,sha256=x_rAP_QXrbMfEieOF7mnEF3qFbN1SzK4mMGniMYJCAo,45
251
251
  cognite/neat/_workflows/__init__.py,sha256=S0fZq7kvoqDKodHu1UIPsqcpdvXoefUWRPt1lqeQkQs,420
252
252
  cognite/neat/_workflows/base.py,sha256=O1pcmfbme2gIVF2eOGrKZSUDmhZc8L9rI8UfvLN2YAM,26839
253
253
  cognite/neat/_workflows/cdf_store.py,sha256=3pebnATPo6In4-1srpa3wzstynTOi3T6hwFX5uaie4c,18050
@@ -276,8 +276,8 @@ cognite/neat/_workflows/tasks.py,sha256=dr2xuIb8P5e5e9p_fjzRlvDbKsre2xGYrkc3wnRx
276
276
  cognite/neat/_workflows/triggers.py,sha256=u69xOsaTtM8_WD6ZeIIBB-XKwvlZmPHAsZQh_TnyHcM,7073
277
277
  cognite/neat/_workflows/utils.py,sha256=gKdy3RLG7ctRhbCRwaDIWpL9Mi98zm56-d4jfHDqP1E,453
278
278
  cognite/neat/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
279
- cognite_neat-0.97.2.dist-info/LICENSE,sha256=W8VmvFia4WHa3Gqxq1Ygrq85McUNqIGDVgtdvzT-XqA,11351
280
- cognite_neat-0.97.2.dist-info/METADATA,sha256=6njFfu62z3vsTJ8fymHG1K7IYRqx8Lh-fvVxVDeV4Eo,9657
281
- cognite_neat-0.97.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
282
- cognite_neat-0.97.2.dist-info/entry_points.txt,sha256=SsQlnl8SNMSSjE3acBI835JYFtsIinLSbVmHmMEXv6E,51
283
- cognite_neat-0.97.2.dist-info/RECORD,,
279
+ cognite_neat-0.97.3.dist-info/LICENSE,sha256=W8VmvFia4WHa3Gqxq1Ygrq85McUNqIGDVgtdvzT-XqA,11351
280
+ cognite_neat-0.97.3.dist-info/METADATA,sha256=ohCmVgNuYqPUXNKeJk9sFrE9yRuxwjbroUmNoUhLj-k,9657
281
+ cognite_neat-0.97.3.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
282
+ cognite_neat-0.97.3.dist-info/entry_points.txt,sha256=SsQlnl8SNMSSjE3acBI835JYFtsIinLSbVmHmMEXv6E,51
283
+ cognite_neat-0.97.3.dist-info/RECORD,,