cognite-neat 0.121.1__py3-none-any.whl → 0.121.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/_version.py +1 -1
- cognite/neat/core/_client/_api/statistics.py +91 -0
- cognite/neat/core/_client/_api_client.py +2 -0
- cognite/neat/core/_client/data_classes/statistics.py +125 -0
- cognite/neat/core/_client/testing.py +4 -0
- cognite/neat/core/_constants.py +6 -7
- cognite/neat/core/_data_model/_constants.py +23 -16
- cognite/neat/core/_data_model/_shared.py +33 -17
- cognite/neat/core/_data_model/analysis/__init__.py +2 -2
- cognite/neat/core/_data_model/analysis/_base.py +186 -183
- cognite/neat/core/_data_model/catalog/__init__.py +1 -1
- cognite/neat/core/_data_model/exporters/__init__.py +5 -5
- cognite/neat/core/_data_model/exporters/_base.py +10 -8
- cognite/neat/core/_data_model/exporters/{_rules2dms.py → _data_model2dms.py} +22 -18
- cognite/neat/core/_data_model/exporters/{_rules2excel.py → _data_model2excel.py} +51 -51
- cognite/neat/core/_data_model/exporters/{_rules2instance_template.py → _data_model2instance_template.py} +4 -4
- cognite/neat/core/_data_model/exporters/{_rules2ontology.py → _data_model2ontology.py} +50 -50
- cognite/neat/core/_data_model/exporters/{_rules2yaml.py → _data_model2yaml.py} +21 -18
- cognite/neat/core/_data_model/importers/__init__.py +6 -6
- cognite/neat/core/_data_model/importers/_base.py +8 -6
- cognite/neat/core/_data_model/importers/_base_file_reader.py +56 -0
- cognite/neat/core/_data_model/importers/{_yaml2rules.py → _dict2data_model.py} +40 -20
- cognite/neat/core/_data_model/importers/{_dms2rules.py → _dms2data_model.py} +58 -49
- cognite/neat/core/_data_model/importers/{_dtdl2rules → _dtdl2data_model}/dtdl_converter.py +22 -22
- cognite/neat/core/_data_model/importers/{_dtdl2rules → _dtdl2data_model}/dtdl_importer.py +7 -7
- cognite/neat/core/_data_model/importers/{_dtdl2rules → _dtdl2data_model}/spec.py +3 -3
- cognite/neat/core/_data_model/importers/_rdf/_base.py +9 -9
- cognite/neat/core/_data_model/importers/_rdf/_imf2rules.py +15 -15
- cognite/neat/core/_data_model/importers/_rdf/_inference2rules.py +36 -36
- cognite/neat/core/_data_model/importers/_rdf/_owl2rules.py +12 -12
- cognite/neat/core/_data_model/importers/_rdf/_shared.py +25 -25
- cognite/neat/core/_data_model/importers/{_spreadsheet2rules.py → _spreadsheet2data_model.py} +72 -12
- cognite/neat/core/_data_model/models/__init__.py +8 -8
- cognite/neat/core/_data_model/models/_base_unverified.py +1 -1
- cognite/neat/core/_data_model/models/_base_verified.py +3 -3
- cognite/neat/core/_data_model/models/_types.py +6 -6
- cognite/neat/core/_data_model/models/conceptual/__init__.py +6 -6
- cognite/neat/core/_data_model/models/conceptual/_unverified.py +20 -20
- cognite/neat/core/_data_model/models/conceptual/_validation.py +87 -77
- cognite/neat/core/_data_model/models/conceptual/_verified.py +53 -51
- cognite/neat/core/_data_model/models/data_types.py +2 -2
- cognite/neat/core/_data_model/models/entities/__init__.py +8 -8
- cognite/neat/core/_data_model/models/entities/_loaders.py +11 -10
- cognite/neat/core/_data_model/models/entities/_multi_value.py +5 -5
- cognite/neat/core/_data_model/models/entities/_single_value.py +44 -38
- cognite/neat/core/_data_model/models/entities/_types.py +9 -3
- cognite/neat/core/_data_model/models/entities/_wrapped.py +3 -3
- cognite/neat/core/_data_model/models/mapping/_classic2core.py +12 -9
- cognite/neat/core/_data_model/models/physical/__init__.py +40 -0
- cognite/neat/core/_data_model/models/{dms → physical}/_exporter.py +71 -52
- cognite/neat/core/_data_model/models/{dms/_rules_input.py → physical/_unverified.py} +48 -39
- cognite/neat/core/_data_model/models/{dms → physical}/_validation.py +13 -11
- cognite/neat/core/_data_model/models/{dms/_rules.py → physical/_verified.py} +68 -60
- cognite/neat/core/_data_model/transformers/__init__.py +27 -23
- cognite/neat/core/_data_model/transformers/_base.py +26 -19
- cognite/neat/core/_data_model/transformers/_converters.py +703 -618
- cognite/neat/core/_data_model/transformers/_mapping.py +74 -55
- cognite/neat/core/_data_model/transformers/_verification.py +63 -54
- cognite/neat/core/_instances/extractors/_base.py +1 -1
- cognite/neat/core/_instances/extractors/_classic_cdf/_classic.py +8 -8
- cognite/neat/core/_instances/extractors/_dms_graph.py +42 -34
- cognite/neat/core/_instances/extractors/_mock_graph_generator.py +98 -95
- cognite/neat/core/_instances/loaders/_base.py +2 -2
- cognite/neat/core/_instances/loaders/_rdf2dms.py +6 -6
- cognite/neat/core/_instances/transformers/_base.py +7 -4
- cognite/neat/core/_instances/transformers/_value_type.py +2 -6
- cognite/neat/core/_issues/_base.py +4 -4
- cognite/neat/core/_issues/errors/__init__.py +2 -2
- cognite/neat/core/_issues/errors/_wrapper.py +2 -2
- cognite/neat/core/_issues/warnings/_models.py +4 -4
- cognite/neat/core/_store/__init__.py +3 -3
- cognite/neat/core/_store/{_rules_store.py → _data_model.py} +119 -112
- cognite/neat/core/_store/{_graph_store.py → _instance.py} +3 -4
- cognite/neat/core/_store/_provenance.py +2 -2
- cognite/neat/core/_store/exceptions.py +2 -2
- cognite/neat/core/_utils/rdf_.py +14 -0
- cognite/neat/core/_utils/text.py +1 -1
- cognite/neat/session/_base.py +22 -20
- cognite/neat/session/_drop.py +2 -2
- cognite/neat/session/_inspect.py +5 -5
- cognite/neat/session/_mapping.py +8 -6
- cognite/neat/session/_read.py +2 -2
- cognite/neat/session/_set.py +3 -3
- cognite/neat/session/_show.py +11 -11
- cognite/neat/session/_state.py +13 -13
- cognite/neat/session/_subset.py +12 -9
- cognite/neat/session/_template.py +13 -13
- cognite/neat/session/_to.py +17 -17
- {cognite_neat-0.121.1.dist-info → cognite_neat-0.121.2.dist-info}/METADATA +1 -1
- {cognite_neat-0.121.1.dist-info → cognite_neat-0.121.2.dist-info}/RECORD +95 -93
- cognite/neat/core/_data_model/exporters/_validation.py +0 -14
- cognite/neat/core/_data_model/models/dms/__init__.py +0 -32
- /cognite/neat/core/_data_model/catalog/{info-rules-imf.xlsx → conceptual-imf-data-model.xlsx} +0 -0
- /cognite/neat/core/_data_model/importers/{_dtdl2rules → _dtdl2data_model}/__init__.py +0 -0
- /cognite/neat/core/_data_model/importers/{_dtdl2rules → _dtdl2data_model}/_unit_lookup.py +0 -0
- {cognite_neat-0.121.1.dist-info → cognite_neat-0.121.2.dist-info}/WHEEL +0 -0
- {cognite_neat-0.121.1.dist-info → cognite_neat-0.121.2.dist-info}/licenses/LICENSE +0 -0
cognite/neat/_version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
__version__ = "0.121.
|
|
1
|
+
__version__ = "0.121.2"
|
|
2
2
|
__engine__ = "^2.0.4"
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import itertools
|
|
2
|
+
from typing import overload
|
|
3
|
+
|
|
4
|
+
from cognite.client._api_client import APIClient
|
|
5
|
+
from cognite.client._cognite_client import CogniteClient
|
|
6
|
+
from cognite.client.config import ClientConfig
|
|
7
|
+
from cognite.client.data_classes.data_modeling.ids import _load_space_identifier
|
|
8
|
+
from cognite.client.utils.useful_types import SequenceNotStr
|
|
9
|
+
|
|
10
|
+
from cognite.neat.core._client.data_classes.statistics import (
|
|
11
|
+
ProjectStatsAndLimits,
|
|
12
|
+
SpaceInstanceCounts,
|
|
13
|
+
SpaceInstanceCountsList,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class StatisticsAPI(APIClient):
|
|
18
|
+
_RESOURCE_PATH = "/models/statistics"
|
|
19
|
+
|
|
20
|
+
def __init__(self, config: ClientConfig, api_version: str | None, cognite_client: CogniteClient) -> None:
|
|
21
|
+
# This is an alpha API, which requires a specific version.
|
|
22
|
+
super().__init__(config, "v1", cognite_client)
|
|
23
|
+
self._RETRIEVE_LIMIT = 100
|
|
24
|
+
|
|
25
|
+
def project(self) -> ProjectStatsAndLimits:
|
|
26
|
+
"""`Retrieve project-wide usage data and limits
|
|
27
|
+
|
|
28
|
+
Returns the usage data and limits for a project's data modelling usage, including data model schemas
|
|
29
|
+
and graph instances
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
ProjectStatsAndLimits: The requested statistics and limits
|
|
33
|
+
|
|
34
|
+
Examples:
|
|
35
|
+
Fetch project statistics (and limits) and check the current number of data models vs.
|
|
36
|
+
and how many more can be created:
|
|
37
|
+
>>> from cognite.neat.core._client import NeatClient
|
|
38
|
+
>>> client = NeatClient()
|
|
39
|
+
>>> stats = client.instance_statistics.project()
|
|
40
|
+
>>> num_dm = stats.data_models.current
|
|
41
|
+
>>> num_dm_left = stats.data_models.limit - num_dm
|
|
42
|
+
"""
|
|
43
|
+
response_data = self._get(self._RESOURCE_PATH).json()
|
|
44
|
+
if "project" not in response_data:
|
|
45
|
+
response_data["project"] = self._cognite_client._config.project
|
|
46
|
+
return ProjectStatsAndLimits._load(response_data)
|
|
47
|
+
|
|
48
|
+
@overload
|
|
49
|
+
def list(self, space: str) -> SpaceInstanceCounts: ...
|
|
50
|
+
|
|
51
|
+
@overload
|
|
52
|
+
def list(self, space: SequenceNotStr[str] | None = None) -> SpaceInstanceCountsList: ...
|
|
53
|
+
|
|
54
|
+
def list(self, space: str | SequenceNotStr[str] | None = None) -> SpaceInstanceCounts | SpaceInstanceCountsList:
|
|
55
|
+
"""`Retrieve usage data and limits per space
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
space (str | SequenceNotStr[str] | None): The space or spaces to retrieve statistics for.
|
|
59
|
+
If None, all spaces will be retrieved.
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
SpaceInstanceCounts | SpaceInstanceCountsList: InstanceStatsPerSpace if a single space is given, else
|
|
63
|
+
InstanceStatsList (which is a list of InstanceStatsPerSpace)
|
|
64
|
+
|
|
65
|
+
Examples:
|
|
66
|
+
Fetch statistics for a single space:
|
|
67
|
+
>>> from cognite.neat.core._client import NeatClient
|
|
68
|
+
>>> client = NeatClient()
|
|
69
|
+
>>> res = client.instance_statistics.list("my-space")
|
|
70
|
+
Fetch statistics for multiple spaces:
|
|
71
|
+
>>> res = client.instance_statistics.list(
|
|
72
|
+
... ["my-space1", "my-space2"]
|
|
73
|
+
... )
|
|
74
|
+
Fetch statistics for all spaces (ignores the 'space' argument):
|
|
75
|
+
>>> res = client.instance_statistics.list(return_all=True)
|
|
76
|
+
"""
|
|
77
|
+
if space is None:
|
|
78
|
+
return SpaceInstanceCountsList._load(self._get(self._RESOURCE_PATH + "/spaces").json()["items"])
|
|
79
|
+
|
|
80
|
+
is_single = isinstance(space, str)
|
|
81
|
+
|
|
82
|
+
ids = _load_space_identifier(space)
|
|
83
|
+
result = SpaceInstanceCountsList._load(
|
|
84
|
+
itertools.chain.from_iterable(
|
|
85
|
+
self._post(self._RESOURCE_PATH + "/spaces/byids", json={"items": chunk.as_dicts()}).json()["items"]
|
|
86
|
+
for chunk in ids.chunked(self._RETRIEVE_LIMIT)
|
|
87
|
+
)
|
|
88
|
+
)
|
|
89
|
+
if is_single:
|
|
90
|
+
return result[0]
|
|
91
|
+
return result
|
|
@@ -5,6 +5,7 @@ from cognite.neat.core._utils.auth import _CLIENT_NAME
|
|
|
5
5
|
from ._api.data_modeling_loaders import DataModelLoaderAPI
|
|
6
6
|
from ._api.neat_instances import NeatInstancesAPI
|
|
7
7
|
from ._api.schema import SchemaAPI
|
|
8
|
+
from ._api.statistics import StatisticsAPI
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class NeatClient(CogniteClient):
|
|
@@ -17,3 +18,4 @@ class NeatClient(CogniteClient):
|
|
|
17
18
|
self.loaders = DataModelLoaderAPI(self)
|
|
18
19
|
self.schema = SchemaAPI(self)
|
|
19
20
|
self.instances = NeatInstancesAPI(self)
|
|
21
|
+
self.instance_statistics = StatisticsAPI(self._config, self._config.api_subversion, self)
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from cognite.client import CogniteClient
|
|
5
|
+
from cognite.client.data_classes._base import CogniteObject, CogniteResource, CogniteResourceList
|
|
6
|
+
from typing_extensions import Self
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass
|
|
10
|
+
class InstanceCounts(CogniteResource):
|
|
11
|
+
nodes: int
|
|
12
|
+
edges: int
|
|
13
|
+
soft_deleted_nodes: int
|
|
14
|
+
soft_deleted_edges: int
|
|
15
|
+
|
|
16
|
+
@classmethod
|
|
17
|
+
def _load(cls, resource: dict[str, Any], cognite_client: CogniteClient | None = None) -> Self:
|
|
18
|
+
return cls(
|
|
19
|
+
nodes=resource["nodes"],
|
|
20
|
+
edges=resource["edges"],
|
|
21
|
+
soft_deleted_nodes=resource["softDeletedNodes"],
|
|
22
|
+
soft_deleted_edges=resource["softDeletedEdges"],
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass
|
|
27
|
+
class SpaceInstanceCounts(InstanceCounts):
|
|
28
|
+
space: str
|
|
29
|
+
|
|
30
|
+
@classmethod
|
|
31
|
+
def _load(cls, resource: dict[str, Any], cognite_client: CogniteClient | None = None) -> Self:
|
|
32
|
+
return cls(
|
|
33
|
+
space=resource["space"],
|
|
34
|
+
nodes=resource["nodes"],
|
|
35
|
+
edges=resource["edges"],
|
|
36
|
+
soft_deleted_nodes=resource["softDeletedNodes"],
|
|
37
|
+
soft_deleted_edges=resource["softDeletedEdges"],
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class SpaceInstanceCountsList(CogniteResourceList):
|
|
42
|
+
_RESOURCE = SpaceInstanceCounts
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass
|
|
46
|
+
class CountLimitPair(CogniteObject):
|
|
47
|
+
count: int
|
|
48
|
+
limit: int
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def _load(cls, resource: dict[str, Any], cognite_client: CogniteClient | None = None) -> Self:
|
|
52
|
+
return cls(
|
|
53
|
+
count=resource["count"],
|
|
54
|
+
limit=resource["limit"],
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass
|
|
59
|
+
class InstanceCountsLimits(InstanceCounts):
|
|
60
|
+
instances_limit: int
|
|
61
|
+
soft_deleted_instances_limit: int
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def instances(self) -> int:
|
|
65
|
+
return self.nodes + self.edges
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def soft_deleted_instances(self) -> int:
|
|
69
|
+
return self.soft_deleted_nodes + self.soft_deleted_edges
|
|
70
|
+
|
|
71
|
+
@classmethod
|
|
72
|
+
def _load(cls, resource: dict[str, Any], cognite_client: CogniteClient | None = None) -> Self:
|
|
73
|
+
return cls(
|
|
74
|
+
nodes=resource["nodes"],
|
|
75
|
+
edges=resource["edges"],
|
|
76
|
+
soft_deleted_nodes=resource["softDeletedNodes"],
|
|
77
|
+
soft_deleted_edges=resource["softDeletedEdges"],
|
|
78
|
+
instances_limit=resource["instancesLimit"],
|
|
79
|
+
soft_deleted_instances_limit=resource["softDeletedInstancesLimit"],
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@dataclass
|
|
84
|
+
class ProjectStatsAndLimits(CogniteResource):
|
|
85
|
+
project: str
|
|
86
|
+
spaces: CountLimitPair
|
|
87
|
+
containers: CountLimitPair
|
|
88
|
+
views: CountLimitPair
|
|
89
|
+
data_models: CountLimitPair
|
|
90
|
+
container_properties: CountLimitPair
|
|
91
|
+
instances: InstanceCountsLimits
|
|
92
|
+
concurrent_read_limit: int
|
|
93
|
+
concurrent_write_limit: int
|
|
94
|
+
concurrent_delete_limit: int
|
|
95
|
+
|
|
96
|
+
@classmethod
|
|
97
|
+
def _load(cls, data: dict[str, Any], cognite_client: CogniteClient | None = None) -> Self:
|
|
98
|
+
return cls(
|
|
99
|
+
project=data["project"],
|
|
100
|
+
spaces=CountLimitPair._load(data["spaces"]),
|
|
101
|
+
containers=CountLimitPair._load(data["containers"]),
|
|
102
|
+
views=CountLimitPair._load(data["views"]),
|
|
103
|
+
data_models=CountLimitPair._load(data["dataModels"]),
|
|
104
|
+
container_properties=CountLimitPair._load(data["containerProperties"]),
|
|
105
|
+
instances=InstanceCountsLimits._load(data["instances"]),
|
|
106
|
+
concurrent_read_limit=data["concurrentReadLimit"],
|
|
107
|
+
concurrent_write_limit=data["concurrentWriteLimit"],
|
|
108
|
+
concurrent_delete_limit=data["concurrentDeleteLimit"],
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
def dump(self, camel_case: bool = True) -> dict[str, Any]:
|
|
112
|
+
return {
|
|
113
|
+
"project": self.project,
|
|
114
|
+
"spaces": self.spaces.dump(camel_case=camel_case),
|
|
115
|
+
"containers": self.containers.dump(camel_case=camel_case),
|
|
116
|
+
"views": self.views.dump(camel_case=camel_case),
|
|
117
|
+
"dataModels" if camel_case else "data_models": self.data_models.dump(camel_case=camel_case),
|
|
118
|
+
"containerProperties" if camel_case else "container_properties": self.container_properties.dump(
|
|
119
|
+
camel_case=camel_case
|
|
120
|
+
),
|
|
121
|
+
"instances": self.instances.dump(camel_case=camel_case),
|
|
122
|
+
"concurrentReadLimit" if camel_case else "concurrent_read_limit": self.concurrent_read_limit,
|
|
123
|
+
"concurrentWriteLimit" if camel_case else "concurrent_write_limit": self.concurrent_write_limit,
|
|
124
|
+
"concurrentDeleteLimit" if camel_case else "concurrent_delete_limit": self.concurrent_delete_limit,
|
|
125
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from collections.abc import Iterator
|
|
2
2
|
from contextlib import contextmanager
|
|
3
3
|
from typing import Any
|
|
4
|
+
from unittest.mock import MagicMock
|
|
4
5
|
|
|
5
6
|
from cognite.client.testing import CogniteClientMock
|
|
6
7
|
|
|
@@ -9,6 +10,7 @@ from cognite.neat.core._client._api_client import NeatClient
|
|
|
9
10
|
from ._api.data_modeling_loaders import DataModelLoaderAPI
|
|
10
11
|
from ._api.neat_instances import NeatInstancesAPI
|
|
11
12
|
from ._api.schema import SchemaAPI
|
|
13
|
+
from ._api.statistics import StatisticsAPI
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
class NeatClientMock(CogniteClientMock):
|
|
@@ -22,6 +24,8 @@ class NeatClientMock(CogniteClientMock):
|
|
|
22
24
|
super().__init__(*args, **kwargs)
|
|
23
25
|
return
|
|
24
26
|
super().__init__(*args, **kwargs)
|
|
27
|
+
self.instance_statistics = MagicMock(spec_set=StatisticsAPI)
|
|
28
|
+
|
|
25
29
|
self.schema = SchemaAPI(self)
|
|
26
30
|
self.loaders = DataModelLoaderAPI(self)
|
|
27
31
|
self.instances = NeatInstancesAPI(self)
|
cognite/neat/core/_constants.py
CHANGED
|
@@ -12,7 +12,7 @@ from cognite import neat
|
|
|
12
12
|
from cognite.neat.core._issues.errors._general import NeatValueError
|
|
13
13
|
|
|
14
14
|
if TYPE_CHECKING:
|
|
15
|
-
from cognite.neat.core._data_model.models.
|
|
15
|
+
from cognite.neat.core._data_model.models.physical import PhysicalProperty
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
def _is_in_notebook() -> bool:
|
|
@@ -104,9 +104,8 @@ COGNITE_CONCEPTS = (
|
|
|
104
104
|
|
|
105
105
|
DMS_LISTABLE_PROPERTY_LIMIT = 1000
|
|
106
106
|
|
|
107
|
-
EXAMPLE_RULES = PACKAGE_DIRECTORY / "
|
|
108
|
-
EXAMPLE_GRAPHS = PACKAGE_DIRECTORY / "
|
|
109
|
-
EXAMPLE_WORKFLOWS = PACKAGE_DIRECTORY / "_workflows" / "examples"
|
|
107
|
+
EXAMPLE_RULES = PACKAGE_DIRECTORY / "core" / "_data_model" / "examples"
|
|
108
|
+
EXAMPLE_GRAPHS = PACKAGE_DIRECTORY / "core" / "_instances" / "examples"
|
|
110
109
|
|
|
111
110
|
DEFAULT_SPACE_URI = "http://purl.org/cognite/space/{space}#"
|
|
112
111
|
SPACE_URI_PATTERN = re.compile(r"http://purl.org/cognite/space/(?P<space>[^#]+)#$")
|
|
@@ -196,11 +195,11 @@ _ASSET_PATH_PROPERTY = {
|
|
|
196
195
|
BASE_MODEL = Literal["CogniteCore"]
|
|
197
196
|
|
|
198
197
|
|
|
199
|
-
def get_asset_read_only_properties_with_connection() -> "list[
|
|
198
|
+
def get_asset_read_only_properties_with_connection() -> "list[PhysicalProperty]":
|
|
200
199
|
"""Gets the asset read-only properties with connection, i.e. Root and Path."""
|
|
201
|
-
from cognite.neat.core._data_model.models.
|
|
200
|
+
from cognite.neat.core._data_model.models.physical import PhysicalProperty
|
|
202
201
|
|
|
203
|
-
return [
|
|
202
|
+
return [PhysicalProperty.model_validate(item) for item in (_ASSET_ROOT_PROPERTY, _ASSET_PATH_PROPERTY)]
|
|
204
203
|
|
|
205
204
|
|
|
206
205
|
def get_base_concepts(
|
|
@@ -15,9 +15,10 @@ class EntityTypes(StrEnum):
|
|
|
15
15
|
predicate = "predicate"
|
|
16
16
|
object = "object"
|
|
17
17
|
class_ = "class"
|
|
18
|
+
concept = "concept"
|
|
18
19
|
parent_class = "parent_class"
|
|
19
20
|
property_ = "property"
|
|
20
|
-
|
|
21
|
+
physical_property = "physical_property"
|
|
21
22
|
conceptual_property = "conceptual_property"
|
|
22
23
|
object_property = "ObjectProperty"
|
|
23
24
|
data_property = "DatatypeProperty"
|
|
@@ -43,9 +44,11 @@ class EntityTypes(StrEnum):
|
|
|
43
44
|
space = "space"
|
|
44
45
|
|
|
45
46
|
|
|
46
|
-
def get_reserved_words(
|
|
47
|
+
def get_reserved_words(
|
|
48
|
+
key: Literal["concept", "view", "property", "space"],
|
|
49
|
+
) -> list[str]:
|
|
47
50
|
return {
|
|
48
|
-
"
|
|
51
|
+
"concept": ["Concept", "concept"],
|
|
49
52
|
"view": [
|
|
50
53
|
"Query",
|
|
51
54
|
"Mutation",
|
|
@@ -103,10 +106,14 @@ DATA_MODEL_COMPLIANCE_REGEX = r"^[a-zA-Z]([a-zA-Z0-9_]{0,253}[a-zA-Z0-9])?$"
|
|
|
103
106
|
VIEW_ID_COMPLIANCE_REGEX = (
|
|
104
107
|
rf"(?!^({'|'.join(get_reserved_words('view'))})$)" r"(^[a-zA-Z][a-zA-Z0-9_]{0,253}[a-zA-Z0-9]?$)"
|
|
105
108
|
)
|
|
106
|
-
|
|
107
|
-
rf"(?!^({'|'.join(get_reserved_words('property'))})$)"
|
|
109
|
+
PHYSICAL_PROPERTY_ID_COMPLIANCE_REGEX = (
|
|
110
|
+
rf"(?!^({'|'.join(get_reserved_words('property'))})$)"
|
|
111
|
+
r"(^[a-zA-Z][a-zA-Z0-9_]{0,253}[a-zA-Z0-9]?$)"
|
|
112
|
+
)
|
|
113
|
+
CONCEPT_ID_COMPLIANCE_REGEX = (
|
|
114
|
+
rf"(?!^({'|'.join(get_reserved_words('concept'))})$)"
|
|
115
|
+
r"(^[a-zA-Z0-9._-]{0,253}[a-zA-Z0-9]?$)"
|
|
108
116
|
)
|
|
109
|
-
CLASS_ID_COMPLIANCE_REGEX = rf"(?!^({'|'.join(get_reserved_words('class'))})$)" r"(^[a-zA-Z0-9._-]{0,253}[a-zA-Z0-9]?$)"
|
|
110
117
|
|
|
111
118
|
INFORMATION_PROPERTY_ID_COMPLIANCE_REGEX = r"^(\*)|(?!^(Property|property)$)(^[a-zA-Z0-9._-]{0,253}[a-zA-Z0-9]?$)"
|
|
112
119
|
VERSION_COMPLIANCE_REGEX = r"^[a-zA-Z0-9]([.a-zA-Z0-9_-]{0,41}[a-zA-Z0-9])?$"
|
|
@@ -139,15 +146,15 @@ class _Patterns:
|
|
|
139
146
|
return re.compile(VIEW_ID_COMPLIANCE_REGEX)
|
|
140
147
|
|
|
141
148
|
@cached_property
|
|
142
|
-
def
|
|
143
|
-
return re.compile(
|
|
149
|
+
def physical_property_id_compliance(self) -> re.Pattern[str]:
|
|
150
|
+
return re.compile(PHYSICAL_PROPERTY_ID_COMPLIANCE_REGEX)
|
|
144
151
|
|
|
145
152
|
@cached_property
|
|
146
|
-
def
|
|
147
|
-
return re.compile(
|
|
153
|
+
def concept_id_compliance(self) -> re.Pattern[str]:
|
|
154
|
+
return re.compile(CONCEPT_ID_COMPLIANCE_REGEX)
|
|
148
155
|
|
|
149
156
|
@cached_property
|
|
150
|
-
def
|
|
157
|
+
def conceptual_property_id_compliance(self) -> re.Pattern[str]:
|
|
151
158
|
return re.compile(INFORMATION_PROPERTY_ID_COMPLIANCE_REGEX)
|
|
152
159
|
|
|
153
160
|
@cached_property
|
|
@@ -158,11 +165,11 @@ class _Patterns:
|
|
|
158
165
|
self,
|
|
159
166
|
entity: EntityTypes,
|
|
160
167
|
) -> re.Pattern:
|
|
161
|
-
if entity == EntityTypes.
|
|
162
|
-
return self.
|
|
168
|
+
if entity == EntityTypes.concept:
|
|
169
|
+
return self.concept_id_compliance
|
|
163
170
|
|
|
164
171
|
elif entity == EntityTypes.conceptual_property:
|
|
165
|
-
return self.
|
|
172
|
+
return self.conceptual_property_id_compliance
|
|
166
173
|
|
|
167
174
|
elif entity == EntityTypes.view:
|
|
168
175
|
return self.view_id_compliance
|
|
@@ -171,8 +178,8 @@ class _Patterns:
|
|
|
171
178
|
elif entity == EntityTypes.container:
|
|
172
179
|
return self.view_id_compliance
|
|
173
180
|
|
|
174
|
-
elif entity == EntityTypes.
|
|
175
|
-
return self.
|
|
181
|
+
elif entity == EntityTypes.physical_property:
|
|
182
|
+
return self.physical_property_id_compliance
|
|
176
183
|
|
|
177
184
|
elif entity == EntityTypes.version:
|
|
178
185
|
return self.version_compliance
|
|
@@ -3,27 +3,36 @@ from typing import Generic, TypeAlias, TypeVar
|
|
|
3
3
|
|
|
4
4
|
from cognite.neat.core._data_model.models import (
|
|
5
5
|
ConceptualDataModel,
|
|
6
|
-
|
|
6
|
+
PhysicalDataModel,
|
|
7
7
|
)
|
|
8
8
|
from cognite.neat.core._data_model.models.conceptual._unverified import (
|
|
9
9
|
UnverifiedConceptualDataModel,
|
|
10
10
|
)
|
|
11
|
-
from cognite.neat.core._data_model.models.
|
|
11
|
+
from cognite.neat.core._data_model.models.physical._unverified import (
|
|
12
|
+
UnverifiedPhysicalDataModel,
|
|
13
|
+
)
|
|
12
14
|
from cognite.neat.core._utils.spreadsheet import SpreadsheetRead
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
VerifiedDataModel: TypeAlias = ConceptualDataModel | PhysicalDataModel
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
T_VerifiedDataModel = TypeVar("T_VerifiedDataModel", bound=VerifiedDataModel)
|
|
19
|
+
UnverifiedDataModel: TypeAlias = UnverifiedPhysicalDataModel | UnverifiedConceptualDataModel
|
|
20
|
+
T_UnverifiedDataModel = TypeVar("T_UnverifiedDataModel", bound=UnverifiedDataModel)
|
|
19
21
|
|
|
20
22
|
|
|
21
23
|
@dataclass
|
|
22
|
-
class
|
|
23
|
-
"""This
|
|
24
|
+
class ImportedDataModel(Generic[T_UnverifiedDataModel]):
|
|
25
|
+
"""This class is used to store results of data model import from a source prior to
|
|
26
|
+
verification and validation.
|
|
27
|
+
|
|
28
|
+
Attributes:
|
|
29
|
+
unverified_data_model: The unverified data model.
|
|
30
|
+
context: The context of the import, including warnings, errors and any other
|
|
31
|
+
relevant information.
|
|
32
|
+
"""
|
|
24
33
|
|
|
25
|
-
|
|
26
|
-
|
|
34
|
+
unverified_data_model: T_UnverifiedDataModel | None
|
|
35
|
+
context: dict[str, SpreadsheetRead]
|
|
27
36
|
|
|
28
37
|
@classmethod
|
|
29
38
|
def display_type_name(cls) -> str:
|
|
@@ -31,13 +40,20 @@ class ReadRules(Generic[T_InputRules]):
|
|
|
31
40
|
|
|
32
41
|
@property
|
|
33
42
|
def display_name(self) -> str:
|
|
34
|
-
if self.
|
|
35
|
-
return "
|
|
36
|
-
return self.
|
|
43
|
+
if self.unverified_data_model is None:
|
|
44
|
+
return "Failed to load data model"
|
|
45
|
+
return self.unverified_data_model.display_name
|
|
37
46
|
|
|
38
47
|
|
|
39
|
-
|
|
40
|
-
|
|
48
|
+
ImportedUnverifiedDataModel: TypeAlias = (
|
|
49
|
+
ImportedDataModel[UnverifiedPhysicalDataModel] | ImportedDataModel[UnverifiedConceptualDataModel]
|
|
50
|
+
)
|
|
51
|
+
T_ImportedUnverifiedDataModel = TypeVar("T_ImportedUnverifiedDataModel", bound=ImportedUnverifiedDataModel)
|
|
41
52
|
|
|
42
|
-
|
|
43
|
-
|
|
53
|
+
DataModel: TypeAlias = (
|
|
54
|
+
ConceptualDataModel
|
|
55
|
+
| PhysicalDataModel
|
|
56
|
+
| ImportedDataModel[UnverifiedPhysicalDataModel]
|
|
57
|
+
| ImportedDataModel[UnverifiedConceptualDataModel]
|
|
58
|
+
)
|
|
59
|
+
T_DataModel = TypeVar("T_DataModel", bound=DataModel)
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
from ._base import
|
|
1
|
+
from ._base import DataModelAnalysis
|
|
2
2
|
|
|
3
|
-
__all__ = ["
|
|
3
|
+
__all__ = ["DataModelAnalysis"]
|