cognite-neat 0.117.1__py3-none-any.whl → 0.117.2__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.
- cognite/neat/_client/_api/neat_instances.py +71 -0
- cognite/neat/_client/_api_client.py +2 -0
- cognite/neat/_client/testing.py +2 -0
- cognite/neat/_graph/extractors/_dms.py +11 -21
- cognite/neat/_rules/catalog/hello_world_pump.xlsx +0 -0
- cognite/neat/_version.py +1 -1
- {cognite_neat-0.117.1.dist-info → cognite_neat-0.117.2.dist-info}/METADATA +1 -1
- {cognite_neat-0.117.1.dist-info → cognite_neat-0.117.2.dist-info}/RECORD +11 -10
- {cognite_neat-0.117.1.dist-info → cognite_neat-0.117.2.dist-info}/LICENSE +0 -0
- {cognite_neat-0.117.1.dist-info → cognite_neat-0.117.2.dist-info}/WHEEL +0 -0
- {cognite_neat-0.117.1.dist-info → cognite_neat-0.117.2.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import time
|
|
2
|
+
from collections.abc import Iterator
|
|
3
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
4
|
+
|
|
5
|
+
from cognite.client.data_classes.data_modeling import Edge, Node, ViewId
|
|
6
|
+
from cognite.client.data_classes.filters import Filter
|
|
7
|
+
from cognite.client.exceptions import CogniteAPIError
|
|
8
|
+
from cognite.client.utils.useful_types import SequenceNotStr
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from cognite.neat._client._api_client import NeatClient
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class NeatInstancesAPI:
|
|
15
|
+
def __init__(self, client: "NeatClient") -> None:
|
|
16
|
+
self._client = client
|
|
17
|
+
|
|
18
|
+
def iterate(
|
|
19
|
+
self,
|
|
20
|
+
instance_type: Literal["node", "edge"] = "node",
|
|
21
|
+
space: str | SequenceNotStr[str] | None = None,
|
|
22
|
+
filter_: Filter | None = None,
|
|
23
|
+
source: ViewId | None = None,
|
|
24
|
+
) -> Iterator[Node] | Iterator[Edge]:
|
|
25
|
+
"""Neat specific implementation of the client.data_modeling.instances(...) method to account for 408.
|
|
26
|
+
|
|
27
|
+
In addition, we enforce sort based on the argument below (provided by Alex B.).
|
|
28
|
+
"""
|
|
29
|
+
body: dict[str, Any] = {"limit": 1_000, "cursor": None, "instanceType": instance_type}
|
|
30
|
+
# Without a sort, the sort is implicitly by the internal id, as cursoring needs a stable sort.
|
|
31
|
+
# By making the sort be on external_id, Postgres should pick the index that's on
|
|
32
|
+
# (project_id, space, external_id) WHERE deleted_at IS NULL. In other words,
|
|
33
|
+
# avoiding soft deleted instances.
|
|
34
|
+
body["sort"] = [
|
|
35
|
+
{
|
|
36
|
+
"property": [instance_type, "externalId"],
|
|
37
|
+
"direction": "ascending",
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
url = f"/api/{self._client._API_VERSION}/projects/{self._client.config.project}/models/instances/list"
|
|
41
|
+
filter_ = self._client.data_modeling.instances._merge_space_into_filter(instance_type, space, filter_)
|
|
42
|
+
if filter_:
|
|
43
|
+
body["filter"] = filter_.dump() if isinstance(filter_, Filter) else filter_
|
|
44
|
+
if source:
|
|
45
|
+
body["sources"] = [{"source": source.dump(include_type=True, camel_case=True)}]
|
|
46
|
+
last_limit_change: float = 0.0
|
|
47
|
+
while True:
|
|
48
|
+
try:
|
|
49
|
+
response = self._client.post(url=url, json=body)
|
|
50
|
+
except CogniteAPIError as e:
|
|
51
|
+
if e.code == 408 and body["limit"] > 1:
|
|
52
|
+
body["limit"] = body["limit"] // 2
|
|
53
|
+
last_limit_change = time.perf_counter()
|
|
54
|
+
continue
|
|
55
|
+
raise e
|
|
56
|
+
response_body = response.json()
|
|
57
|
+
yield from (
|
|
58
|
+
Node.load(item) if item.get("instanceType") == "node" else Edge.load(item)
|
|
59
|
+
for item in response_body["items"]
|
|
60
|
+
)
|
|
61
|
+
next_cursor = response_body.get("nextCursor")
|
|
62
|
+
if next_cursor is None:
|
|
63
|
+
break
|
|
64
|
+
body["cursor"] = next_cursor
|
|
65
|
+
# Increase the limit every 30 seconds to avoid fetching reduced
|
|
66
|
+
# instances for a long time after a 408. This limit is somewhat arbitrary,
|
|
67
|
+
# but it should be large enough to avoid many requests, but small enough
|
|
68
|
+
# to avoid fetching very slowly for a long time after a 408.
|
|
69
|
+
if (time.perf_counter() - last_limit_change) > 30.0 and body["limit"] < 1_000:
|
|
70
|
+
body["limit"] = min(int(body["limit"] * 1.5), 1_000)
|
|
71
|
+
last_limit_change = time.perf_counter()
|
|
@@ -3,6 +3,7 @@ from cognite.client import ClientConfig, CogniteClient
|
|
|
3
3
|
from cognite.neat._utils.auth import _CLIENT_NAME
|
|
4
4
|
|
|
5
5
|
from ._api.data_modeling_loaders import DataModelLoaderAPI
|
|
6
|
+
from ._api.neat_instances import NeatInstancesAPI
|
|
6
7
|
from ._api.schema import SchemaAPI
|
|
7
8
|
|
|
8
9
|
|
|
@@ -15,3 +16,4 @@ class NeatClient(CogniteClient):
|
|
|
15
16
|
self._config.client_name = _CLIENT_NAME
|
|
16
17
|
self.loaders = DataModelLoaderAPI(self)
|
|
17
18
|
self.schema = SchemaAPI(self)
|
|
19
|
+
self.instances = NeatInstancesAPI(self)
|
cognite/neat/_client/testing.py
CHANGED
|
@@ -7,6 +7,7 @@ from cognite.client.testing import CogniteClientMock
|
|
|
7
7
|
from cognite.neat._client._api_client import NeatClient
|
|
8
8
|
|
|
9
9
|
from ._api.data_modeling_loaders import DataModelLoaderAPI
|
|
10
|
+
from ._api.neat_instances import NeatInstancesAPI
|
|
10
11
|
from ._api.schema import SchemaAPI
|
|
11
12
|
|
|
12
13
|
|
|
@@ -23,6 +24,7 @@ class NeatClientMock(CogniteClientMock):
|
|
|
23
24
|
super().__init__(*args, **kwargs)
|
|
24
25
|
self.schema = SchemaAPI(self)
|
|
25
26
|
self.loaders = DataModelLoaderAPI(self)
|
|
27
|
+
self.instances = NeatInstancesAPI(self)
|
|
26
28
|
|
|
27
29
|
|
|
28
30
|
@contextmanager
|
|
@@ -3,13 +3,13 @@ import urllib.parse
|
|
|
3
3
|
from collections.abc import Callable, Iterable, Iterator, Set
|
|
4
4
|
from functools import cached_property
|
|
5
5
|
|
|
6
|
-
from cognite.client import CogniteClient
|
|
7
6
|
from cognite.client import data_modeling as dm
|
|
8
7
|
from cognite.client.data_classes.data_modeling import DataModelIdentifier
|
|
9
|
-
from cognite.client.data_classes.data_modeling.instances import Edge, Instance,
|
|
8
|
+
from cognite.client.data_classes.data_modeling.instances import Edge, Instance, Node
|
|
10
9
|
from cognite.client.utils.useful_types import SequenceNotStr
|
|
11
10
|
from rdflib import RDF, Literal, Namespace, URIRef
|
|
12
11
|
|
|
12
|
+
from cognite.neat._client import NeatClient
|
|
13
13
|
from cognite.neat._config import GLOBAL_CONFIG
|
|
14
14
|
from cognite.neat._constants import DEFAULT_SPACE_URI, is_readonly_property
|
|
15
15
|
from cognite.neat._issues.errors import ResourceRetrievalError
|
|
@@ -62,7 +62,7 @@ class DMSExtractor(BaseExtractor):
|
|
|
62
62
|
@classmethod
|
|
63
63
|
def from_data_model(
|
|
64
64
|
cls,
|
|
65
|
-
client:
|
|
65
|
+
client: NeatClient,
|
|
66
66
|
data_model: DataModelIdentifier,
|
|
67
67
|
limit: int | None = None,
|
|
68
68
|
overwrite_namespace: Namespace | None = None,
|
|
@@ -96,7 +96,7 @@ class DMSExtractor(BaseExtractor):
|
|
|
96
96
|
@classmethod
|
|
97
97
|
def from_views(
|
|
98
98
|
cls,
|
|
99
|
-
client:
|
|
99
|
+
client: NeatClient,
|
|
100
100
|
views: Iterable[dm.View],
|
|
101
101
|
limit: int | None = None,
|
|
102
102
|
overwrite_namespace: Namespace | None = None,
|
|
@@ -237,7 +237,7 @@ class DMSExtractor(BaseExtractor):
|
|
|
237
237
|
|
|
238
238
|
|
|
239
239
|
class _ViewInstanceIterator(Iterable[Instance]):
|
|
240
|
-
def __init__(self, client:
|
|
240
|
+
def __init__(self, client: NeatClient, view: dm.View, instance_space: str | SequenceNotStr[str] | None = None):
|
|
241
241
|
self.client = client
|
|
242
242
|
self.view = view
|
|
243
243
|
self.instance_space = instance_space
|
|
@@ -275,28 +275,20 @@ class _ViewInstanceIterator(Iterable[Instance]):
|
|
|
275
275
|
}
|
|
276
276
|
# All nodes and edges with properties
|
|
277
277
|
if self.view.used_for in ("node", "all"):
|
|
278
|
-
|
|
279
|
-
# By making the sort be on external_id, Postgres should pick the index
|
|
280
|
-
# that's on (project_id, space, external_id)
|
|
281
|
-
# WHERE deleted_at IS NULL. In other words, avoiding soft deleted instances.
|
|
282
|
-
node_iterable: Iterable[Instance] = self.client.data_modeling.instances(
|
|
283
|
-
chunk_size=None,
|
|
278
|
+
node_iterable: Iterable[Instance] = self.client.instances.iterate(
|
|
284
279
|
instance_type="node",
|
|
285
|
-
|
|
280
|
+
source=view_id,
|
|
286
281
|
space=self.instance_space,
|
|
287
|
-
sort=InstanceSort(["node", "externalId"]),
|
|
288
282
|
)
|
|
289
283
|
if read_only_properties:
|
|
290
284
|
node_iterable = self._remove_read_only_properties(node_iterable, read_only_properties, view_id)
|
|
291
285
|
yield from node_iterable
|
|
292
286
|
|
|
293
287
|
if self.view.used_for in ("edge", "all"):
|
|
294
|
-
yield from self.client.
|
|
295
|
-
chunk_size=None,
|
|
288
|
+
yield from self.client.instances.iterate(
|
|
296
289
|
instance_type="edge",
|
|
297
|
-
|
|
290
|
+
source=view_id,
|
|
298
291
|
space=self.instance_space,
|
|
299
|
-
sort=InstanceSort(["edge", "externalId"]),
|
|
300
292
|
)
|
|
301
293
|
|
|
302
294
|
for prop in self.view.properties.values():
|
|
@@ -304,14 +296,12 @@ class _ViewInstanceIterator(Iterable[Instance]):
|
|
|
304
296
|
if prop.edge_source:
|
|
305
297
|
# All edges with properties are extracted from the edge source
|
|
306
298
|
continue
|
|
307
|
-
yield from self.client.
|
|
308
|
-
chunk_size=None,
|
|
299
|
+
yield from self.client.instances.iterate(
|
|
309
300
|
instance_type="edge",
|
|
310
|
-
|
|
301
|
+
filter_=dm.filters.Equals(
|
|
311
302
|
["edge", "type"], {"space": prop.type.space, "externalId": prop.type.external_id}
|
|
312
303
|
),
|
|
313
304
|
space=self.instance_space,
|
|
314
|
-
sort=InstanceSort(["edge", "externalId"]),
|
|
315
305
|
)
|
|
316
306
|
|
|
317
307
|
@staticmethod
|
|
Binary file
|
cognite/neat/_version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
__version__ = "0.117.
|
|
1
|
+
__version__ = "0.117.2"
|
|
2
2
|
__engine__ = "^2.0.4"
|
|
@@ -3,13 +3,14 @@ cognite/neat/_alpha.py,sha256=AVw3YiSwpOiV3fSoTbwTxd-p7WGlS-zgf4TPZCT_9vE,1163
|
|
|
3
3
|
cognite/neat/_client/__init__.py,sha256=RQ7MwL8mwGqGHokRzsPqO3XStDzmI4-c12_gz1UPJ74,177
|
|
4
4
|
cognite/neat/_client/_api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
cognite/neat/_client/_api/data_modeling_loaders.py,sha256=LsB8k2erMZ3BJ_wLMIBhav7ykimLkV2QJjnbeC2xikE,39790
|
|
6
|
+
cognite/neat/_client/_api/neat_instances.py,sha256=BxFmErL5FX1FVupHWsZRBsMMMT0BtExpnioiM5XOSHo,3349
|
|
6
7
|
cognite/neat/_client/_api/schema.py,sha256=K8iNuTKHayHGVldMWfY8N6KWG71hOpNIklWGsAkCPMY,6925
|
|
7
|
-
cognite/neat/_client/_api_client.py,sha256=
|
|
8
|
+
cognite/neat/_client/_api_client.py,sha256=wsNK3abwoIppleWzVZmoXe9Ia_wrU4QqOxnxxls3ipY,714
|
|
8
9
|
cognite/neat/_client/data_classes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
10
|
cognite/neat/_client/data_classes/data_modeling.py,sha256=RvpUp9ygd-yffQFJ7O2mQqMLDPIa-dmip5zPb8QVIiw,6672
|
|
10
11
|
cognite/neat/_client/data_classes/neat_sequence.py,sha256=QZWSfWnwk6KlYJvsInco4Wdwc1U8DnOQKWmHebArbQY,10830
|
|
11
12
|
cognite/neat/_client/data_classes/schema.py,sha256=jPFTIKrZI0qZtwu1Bc1m3aLu_VbxIEkhZCneHpIbNkc,23205
|
|
12
|
-
cognite/neat/_client/testing.py,sha256=
|
|
13
|
+
cognite/neat/_client/testing.py,sha256=JnzLQegw2f6SATWRNDQ8Fui6qBYyz7vFgA5myjioohY,1175
|
|
13
14
|
cognite/neat/_config.py,sha256=WT1BS8uADcFvGoUYOOfwFOVq_VBl472TisdoA3wLick,280
|
|
14
15
|
cognite/neat/_constants.py,sha256=WcrInu37p56BP7gPRIvTVScu6D9Di4RQG-OiYg5NAek,8250
|
|
15
16
|
cognite/neat/_graph/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -36,7 +37,7 @@ cognite/neat/_graph/extractors/_classic_cdf/_sequences.py,sha256=HxN0mnm5GrPAfcN
|
|
|
36
37
|
cognite/neat/_graph/extractors/_classic_cdf/_timeseries.py,sha256=6CmmxWWG2IErfNKOPhsjQ5wSOTUZZMjulpaRbHj0Q-g,1560
|
|
37
38
|
cognite/neat/_graph/extractors/_dexpi.py,sha256=SFWnKXYpQToWag9aoX8fxISNa9b8KlqjZnkwI18BzNY,9431
|
|
38
39
|
cognite/neat/_graph/extractors/_dict.py,sha256=CmXvYkzhRjWDPEaXZAb_YyWCwJDeNzdWBkmFyc2K90s,4321
|
|
39
|
-
cognite/neat/_graph/extractors/_dms.py,sha256=
|
|
40
|
+
cognite/neat/_graph/extractors/_dms.py,sha256=fpr9jmJlnB9IS9sdDA7RV50e_RedF7AEVE25qLlgtp4,13810
|
|
40
41
|
cognite/neat/_graph/extractors/_dms_graph.py,sha256=b_OpXsLZ1xCGEWAqsF5Qk6EknZzxDbcfaZ5NOZGaYrE,9441
|
|
41
42
|
cognite/neat/_graph/extractors/_iodd.py,sha256=sV5xKZi2ZT7MQsUQTVji9vxH34pD5yAvUjtT-gb8mts,18473
|
|
42
43
|
cognite/neat/_graph/extractors/_mock_graph_generator.py,sha256=k6qVslbxwE2WpU1L5NLgHJExk8Sho96Ag6-_bcCiLwA,15436
|
|
@@ -79,7 +80,7 @@ cognite/neat/_rules/analysis/__init__.py,sha256=0Y7KiXpzrwOIU7GVlC3zlizj1TXe6sod
|
|
|
79
80
|
cognite/neat/_rules/analysis/_base.py,sha256=t9NBxZoM95_7UqOa9coWzsH0Kv6neKcb0dtebTV2KnI,23434
|
|
80
81
|
cognite/neat/_rules/catalog/__init__.py,sha256=dwDB8b-5GKZuwVyPuiwsH0EaK2FY9-wJrkTjKoL8KE4,250
|
|
81
82
|
cognite/neat/_rules/catalog/classic_model.xlsx,sha256=YkocpkKypizjsWYwOdn5yzIz_BSl8T8SQLxgm4GIjLQ,15014
|
|
82
|
-
cognite/neat/_rules/catalog/hello_world_pump.xlsx,sha256=
|
|
83
|
+
cognite/neat/_rules/catalog/hello_world_pump.xlsx,sha256=E63t5U1PQLIoUfXp1mEuhuq8I2TGKovZlEfIhO5bevw,23322
|
|
83
84
|
cognite/neat/_rules/catalog/info-rules-imf.xlsx,sha256=vrE5g8vBtsGpwJqygxG3t9I3x4SUAyQsi1vtWfZ8QW4,53682
|
|
84
85
|
cognite/neat/_rules/exporters/__init__.py,sha256=IYBa0DIYlx8cFItgYRw9W4FY_LmVEjuaqMz3JORZZX0,1204
|
|
85
86
|
cognite/neat/_rules/exporters/_base.py,sha256=VkNMy8wsH-x4tAjS44cXgzzNH0CM2k_4RhkMwK50J7g,2284
|
|
@@ -176,10 +177,10 @@ cognite/neat/_utils/text.py,sha256=BFJoEOQBFgpelysL92FdF0OVRVFl0q9tRNoz-oRanNc,7
|
|
|
176
177
|
cognite/neat/_utils/time_.py,sha256=O30LUiDH9TdOYz8_a9pFqTtJdg8vEjC3qHCk8xZblG8,345
|
|
177
178
|
cognite/neat/_utils/upload.py,sha256=xWtM6mFuD2QYQHaZ7zCAuGptbEpPIxcH-raWQu93-Ug,5845
|
|
178
179
|
cognite/neat/_utils/xml_.py,sha256=FQkq84u35MUsnKcL6nTMJ9ajtG9D5i1u4VBnhGqP2DQ,1710
|
|
179
|
-
cognite/neat/_version.py,sha256=
|
|
180
|
+
cognite/neat/_version.py,sha256=QPLtZ3sS71bmoKNu3TyTYKy7lRyMCDh2l6Ur8ITOlz8,46
|
|
180
181
|
cognite/neat/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
181
|
-
cognite_neat-0.117.
|
|
182
|
-
cognite_neat-0.117.
|
|
183
|
-
cognite_neat-0.117.
|
|
184
|
-
cognite_neat-0.117.
|
|
185
|
-
cognite_neat-0.117.
|
|
182
|
+
cognite_neat-0.117.2.dist-info/LICENSE,sha256=W8VmvFia4WHa3Gqxq1Ygrq85McUNqIGDVgtdvzT-XqA,11351
|
|
183
|
+
cognite_neat-0.117.2.dist-info/METADATA,sha256=ekCAFZpHqHGP0JjfiP9NOa7ETMffALadml3HTGnfWvQ,5361
|
|
184
|
+
cognite_neat-0.117.2.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
|
185
|
+
cognite_neat-0.117.2.dist-info/entry_points.txt,sha256=SsQlnl8SNMSSjE3acBI835JYFtsIinLSbVmHmMEXv6E,51
|
|
186
|
+
cognite_neat-0.117.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|