cognite-neat 0.88.3__py3-none-any.whl → 0.89.0__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/constants.py +3 -0
- cognite/neat/graph/extractors/_mock_graph_generator.py +2 -1
- cognite/neat/issues/_base.py +2 -1
- cognite/neat/issues/errors/__init__.py +2 -1
- cognite/neat/issues/errors/_general.py +7 -0
- cognite/neat/issues/warnings/_models.py +1 -1
- cognite/neat/issues/warnings/user_modeling.py +1 -1
- cognite/neat/rules/_shared.py +49 -6
- cognite/neat/rules/analysis/_base.py +1 -1
- cognite/neat/rules/exporters/_base.py +7 -18
- cognite/neat/rules/exporters/_rules2dms.py +8 -18
- cognite/neat/rules/exporters/_rules2excel.py +5 -12
- cognite/neat/rules/exporters/_rules2ontology.py +9 -19
- cognite/neat/rules/exporters/_rules2yaml.py +3 -6
- cognite/neat/rules/importers/_base.py +7 -52
- cognite/neat/rules/importers/_dms2rules.py +171 -115
- cognite/neat/rules/importers/_dtdl2rules/dtdl_converter.py +26 -18
- cognite/neat/rules/importers/_dtdl2rules/dtdl_importer.py +14 -30
- cognite/neat/rules/importers/_rdf/_imf2rules/_imf2classes.py +7 -3
- cognite/neat/rules/importers/_rdf/_imf2rules/_imf2metadata.py +3 -3
- cognite/neat/rules/importers/_rdf/_imf2rules/_imf2properties.py +18 -11
- cognite/neat/rules/importers/_rdf/_imf2rules/_imf2rules.py +9 -18
- cognite/neat/rules/importers/_rdf/_inference2rules.py +10 -33
- cognite/neat/rules/importers/_rdf/_owl2rules/_owl2rules.py +9 -20
- cognite/neat/rules/importers/_rdf/_shared.py +1 -1
- cognite/neat/rules/importers/_spreadsheet2rules.py +22 -86
- cognite/neat/rules/importers/_yaml2rules.py +14 -41
- cognite/neat/rules/models/__init__.py +21 -5
- cognite/neat/rules/models/_base_input.py +162 -0
- cognite/neat/rules/models/{_base.py → _base_rules.py} +1 -12
- cognite/neat/rules/models/asset/__init__.py +5 -2
- cognite/neat/rules/models/asset/_rules.py +2 -20
- cognite/neat/rules/models/asset/_rules_input.py +40 -115
- cognite/neat/rules/models/asset/_validation.py +1 -1
- cognite/neat/rules/models/data_types.py +150 -44
- cognite/neat/rules/models/dms/__init__.py +19 -7
- cognite/neat/rules/models/dms/_exporter.py +72 -26
- cognite/neat/rules/models/dms/_rules.py +42 -155
- cognite/neat/rules/models/dms/_rules_input.py +186 -254
- cognite/neat/rules/models/dms/_serializer.py +44 -3
- cognite/neat/rules/models/dms/_validation.py +3 -4
- cognite/neat/rules/models/domain.py +52 -1
- cognite/neat/rules/models/entities/__init__.py +63 -0
- cognite/neat/rules/models/entities/_constants.py +73 -0
- cognite/neat/rules/models/entities/_loaders.py +76 -0
- cognite/neat/rules/models/entities/_multi_value.py +67 -0
- cognite/neat/rules/models/{entities.py → entities/_single_value.py} +74 -232
- cognite/neat/rules/models/entities/_types.py +86 -0
- cognite/neat/rules/models/{wrapped_entities.py → entities/_wrapped.py} +1 -1
- cognite/neat/rules/models/information/__init__.py +10 -2
- cognite/neat/rules/models/information/_rules.py +3 -14
- cognite/neat/rules/models/information/_rules_input.py +57 -204
- cognite/neat/rules/models/information/_validation.py +1 -1
- cognite/neat/rules/transformers/__init__.py +21 -0
- cognite/neat/rules/transformers/_base.py +69 -3
- cognite/neat/rules/{models/information/_converter.py → transformers/_converters.py} +216 -20
- cognite/neat/rules/transformers/_map_onto.py +97 -0
- cognite/neat/rules/transformers/_pipelines.py +61 -0
- cognite/neat/rules/transformers/_verification.py +136 -0
- cognite/neat/store/_provenance.py +10 -1
- cognite/neat/utils/cdf/data_classes.py +20 -0
- cognite/neat/utils/regex_patterns.py +6 -0
- cognite/neat/workflows/steps/lib/current/rules_exporter.py +106 -37
- cognite/neat/workflows/steps/lib/current/rules_importer.py +24 -22
- {cognite_neat-0.88.3.dist-info → cognite_neat-0.89.0.dist-info}/METADATA +1 -1
- {cognite_neat-0.88.3.dist-info → cognite_neat-0.89.0.dist-info}/RECORD +71 -66
- cognite/neat/rules/models/_constants.py +0 -2
- cognite/neat/rules/models/_types/__init__.py +0 -19
- cognite/neat/rules/models/asset/_converter.py +0 -4
- cognite/neat/rules/models/dms/_converter.py +0 -143
- /cognite/neat/rules/models/{_types/_field.py → _types.py} +0 -0
- {cognite_neat-0.88.3.dist-info → cognite_neat-0.89.0.dist-info}/LICENSE +0 -0
- {cognite_neat-0.88.3.dist-info → cognite_neat-0.89.0.dist-info}/WHEEL +0 -0
- {cognite_neat-0.88.3.dist-info → cognite_neat-0.89.0.dist-info}/entry_points.txt +0 -0
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import inspect
|
|
2
2
|
import sys
|
|
3
3
|
from abc import ABC, abstractmethod
|
|
4
4
|
from functools import total_ordering
|
|
5
|
-
from
|
|
5
|
+
from types import UnionType
|
|
6
|
+
from typing import Any, ClassVar, Generic, Literal, TypeVar, Union, cast, get_args, get_origin
|
|
6
7
|
|
|
8
|
+
from cognite.client.data_classes.data_modeling import DirectRelationReference
|
|
9
|
+
from cognite.client.data_classes.data_modeling.data_types import UnitReference
|
|
7
10
|
from cognite.client.data_classes.data_modeling.ids import (
|
|
8
11
|
ContainerId,
|
|
9
12
|
DataModelId,
|
|
@@ -12,16 +15,12 @@ from cognite.client.data_classes.data_modeling.ids import (
|
|
|
12
15
|
ViewId,
|
|
13
16
|
)
|
|
14
17
|
from pydantic import (
|
|
15
|
-
AnyHttpUrl,
|
|
16
18
|
BaseModel,
|
|
17
|
-
BeforeValidator,
|
|
18
19
|
Field,
|
|
19
|
-
PlainSerializer,
|
|
20
20
|
model_serializer,
|
|
21
21
|
model_validator,
|
|
22
22
|
)
|
|
23
23
|
|
|
24
|
-
from cognite.neat.rules.models.data_types import DataType
|
|
25
24
|
from cognite.neat.utils.text import replace_non_alphanumeric_with_underscore
|
|
26
25
|
|
|
27
26
|
if sys.version_info >= (3, 11):
|
|
@@ -31,66 +30,17 @@ else:
|
|
|
31
30
|
from backports.strenum import StrEnum
|
|
32
31
|
from typing_extensions import Self
|
|
33
32
|
|
|
33
|
+
from cognite.neat.utils.regex_patterns import SPLIT_ON_COMMA_PATTERN, SPLIT_ON_EQUAL_PATTERN
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
object_property = "ObjectProperty"
|
|
44
|
-
data_property = "DatatypeProperty"
|
|
45
|
-
annotation_property = "AnnotationProperty"
|
|
46
|
-
object_value_type = "object_value_type"
|
|
47
|
-
data_value_type = "data_value_type" # these are strings, floats, ...
|
|
48
|
-
xsd_value_type = "xsd_value_type"
|
|
49
|
-
dms_value_type = "dms_value_type"
|
|
50
|
-
dms_node = "dms_node"
|
|
51
|
-
view = "view"
|
|
52
|
-
reference_entity = "reference_entity"
|
|
53
|
-
container = "container"
|
|
54
|
-
datamodel = "datamodel"
|
|
55
|
-
undefined = "undefined"
|
|
56
|
-
multi_value_type = "multi_value_type"
|
|
57
|
-
asset = "asset"
|
|
58
|
-
relationship = "relationship"
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
# ALLOWED
|
|
62
|
-
_ALLOWED_PATTERN = r"[^a-zA-Z0-9-_.]"
|
|
63
|
-
|
|
64
|
-
# FOR PARSING STRINGS:
|
|
65
|
-
_PREFIX_REGEX = r"[a-zA-Z]+[a-zA-Z0-9-_.]*[a-zA-Z0-9]+"
|
|
66
|
-
_SUFFIX_REGEX = r"[a-zA-Z0-9-_.]+[a-zA-Z0-9]|[-_.]*[a-zA-Z0-9]+"
|
|
67
|
-
_VERSION_REGEX = r"[a-zA-Z0-9]([.a-zA-Z0-9_-]{0,41}[a-zA-Z0-9])?"
|
|
68
|
-
_PROPERTY_REGEX = r"[a-zA-Z0-9][a-zA-Z0-9_-]*[a-zA-Z0-9]?"
|
|
69
|
-
_ENTITY_ID_REGEX = rf"{_PREFIX_REGEX}:({_SUFFIX_REGEX})"
|
|
70
|
-
_ENTITY_ID_REGEX_COMPILED = re.compile(rf"^(?P<prefix>{_PREFIX_REGEX}):(?P<suffix>{_SUFFIX_REGEX})$")
|
|
71
|
-
_VERSIONED_ENTITY_REGEX_COMPILED = re.compile(
|
|
72
|
-
rf"^(?P<prefix>{_PREFIX_REGEX}):(?P<suffix>{_SUFFIX_REGEX})\(version=(?P<version>{_VERSION_REGEX})\)$"
|
|
35
|
+
from ._constants import (
|
|
36
|
+
_PARSE,
|
|
37
|
+
ENTITY_PATTERN,
|
|
38
|
+
EntityTypes,
|
|
39
|
+
Undefined,
|
|
40
|
+
Unknown,
|
|
41
|
+
_UndefinedType,
|
|
42
|
+
_UnknownType,
|
|
73
43
|
)
|
|
74
|
-
_CLASS_ID_REGEX = rf"(?P<{EntityTypes.class_}>{_ENTITY_ID_REGEX})"
|
|
75
|
-
_CLASS_ID_REGEX_COMPILED = re.compile(rf"^{_CLASS_ID_REGEX}$")
|
|
76
|
-
_PROPERTY_ID_REGEX = rf"\((?P<{EntityTypes.property_}>{_ENTITY_ID_REGEX})\)"
|
|
77
|
-
|
|
78
|
-
_ENTITY_PATTERN = re.compile(r"^(?P<prefix>.*?):?(?P<suffix>[^(:]*)(\((?P<content>[^)]+)\))?$")
|
|
79
|
-
_MULTI_VALUE_TYPE_PATTERN = re.compile(r"^(?P<types>.*?)(\((?P<content>[^)]+)\))?$")
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
class _UndefinedType(BaseModel): ...
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
class _UnknownType(BaseModel):
|
|
86
|
-
def __str__(self) -> str:
|
|
87
|
-
return "#N/A"
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
# This is a trick to make Undefined and Unknown singletons
|
|
91
|
-
Undefined = _UndefinedType()
|
|
92
|
-
Unknown = _UnknownType()
|
|
93
|
-
_PARSE = object()
|
|
94
44
|
|
|
95
45
|
|
|
96
46
|
@total_ordering
|
|
@@ -108,7 +58,7 @@ class Entity(BaseModel, extra="ignore"):
|
|
|
108
58
|
elif isinstance(data, str) and data == str(Unknown):
|
|
109
59
|
return UnknownEntity(prefix=Undefined, suffix=Unknown)
|
|
110
60
|
if defaults and isinstance(defaults, dict):
|
|
111
|
-
# This is trick to pass in default values
|
|
61
|
+
# This is is a trick to pass in default values
|
|
112
62
|
return cls.model_validate({_PARSE: data, "defaults": defaults})
|
|
113
63
|
else:
|
|
114
64
|
return cls.model_validate(data)
|
|
@@ -132,7 +82,7 @@ class Entity(BaseModel, extra="ignore"):
|
|
|
132
82
|
elif data == str(Unknown):
|
|
133
83
|
raise ValueError(f"Unknown is not allowed for {cls.type_} entity")
|
|
134
84
|
|
|
135
|
-
result = cls._parse(data)
|
|
85
|
+
result = cls._parse(data, defaults)
|
|
136
86
|
output = defaults.copy()
|
|
137
87
|
# Populate by alias
|
|
138
88
|
for field_name, field_ in cls.model_fields.items():
|
|
@@ -148,20 +98,29 @@ class Entity(BaseModel, extra="ignore"):
|
|
|
148
98
|
return str(self)
|
|
149
99
|
|
|
150
100
|
@classmethod
|
|
151
|
-
def _parse(cls, raw: str) -> dict:
|
|
152
|
-
if not (result :=
|
|
101
|
+
def _parse(cls, raw: str, defaults: dict) -> dict:
|
|
102
|
+
if not (result := ENTITY_PATTERN.match(raw)):
|
|
153
103
|
return dict(prefix=Undefined, suffix=Unknown)
|
|
154
104
|
prefix = result.group("prefix") or Undefined
|
|
155
105
|
suffix = result.group("suffix")
|
|
156
106
|
content = result.group("content")
|
|
157
107
|
if content is None:
|
|
158
108
|
return dict(prefix=prefix, suffix=suffix)
|
|
159
|
-
extra_args = dict(pair.strip()
|
|
160
|
-
expected_args = {
|
|
109
|
+
extra_args = dict(SPLIT_ON_EQUAL_PATTERN.split(pair.strip()) for pair in SPLIT_ON_COMMA_PATTERN.split(content))
|
|
110
|
+
expected_args = {
|
|
111
|
+
field_.alias or field_name: field_.annotation for field_name, field_ in cls.model_fields.items()
|
|
112
|
+
}
|
|
161
113
|
for key in list(extra_args):
|
|
162
114
|
if key not in expected_args:
|
|
163
115
|
# Todo Warning about unknown key
|
|
164
116
|
del extra_args[key]
|
|
117
|
+
continue
|
|
118
|
+
annotation = expected_args[key]
|
|
119
|
+
if isinstance(annotation, UnionType) or get_origin(annotation) is Union:
|
|
120
|
+
annotation = get_args(annotation)[0]
|
|
121
|
+
|
|
122
|
+
if inspect.isclass(annotation) and issubclass(annotation, Entity): # type: ignore[arg-type]
|
|
123
|
+
extra_args[key] = annotation.load(extra_args[key], **defaults) # type: ignore[union-attr, assignment]
|
|
165
124
|
return dict(prefix=prefix, suffix=suffix, **extra_args)
|
|
166
125
|
|
|
167
126
|
def dump(self) -> str:
|
|
@@ -206,12 +165,15 @@ class Entity(BaseModel, extra="ignore"):
|
|
|
206
165
|
@property
|
|
207
166
|
def id(self) -> str:
|
|
208
167
|
# We have overwritten the serialization to str, so we need to do it manually
|
|
209
|
-
model_dump =
|
|
168
|
+
model_dump = [
|
|
210
169
|
(field.alias or field_name, v)
|
|
211
170
|
for field_name, field in self.model_fields.items()
|
|
212
171
|
if (v := getattr(self, field_name)) is not None and field_name not in {"prefix", "suffix"}
|
|
213
|
-
|
|
214
|
-
|
|
172
|
+
]
|
|
173
|
+
if len(model_dump) == 1:
|
|
174
|
+
args = f"{model_dump[0][0]}={model_dump[0][1]}"
|
|
175
|
+
else:
|
|
176
|
+
args = ",".join([f"{k}={v}" for k, v in model_dump])
|
|
215
177
|
if self.prefix == Undefined:
|
|
216
178
|
base_id = str(self.suffix)
|
|
217
179
|
else:
|
|
@@ -268,6 +230,15 @@ class UnknownEntity(ClassEntity):
|
|
|
268
230
|
return str(Unknown)
|
|
269
231
|
|
|
270
232
|
|
|
233
|
+
class UnitEntity(Entity):
|
|
234
|
+
type_: ClassVar[EntityTypes] = EntityTypes.unit
|
|
235
|
+
prefix: str
|
|
236
|
+
suffix: str
|
|
237
|
+
|
|
238
|
+
def as_reference(self) -> UnitReference:
|
|
239
|
+
return UnitReference(external_id=f"{self.prefix}:{self.suffix}")
|
|
240
|
+
|
|
241
|
+
|
|
271
242
|
class AssetFields(StrEnum):
|
|
272
243
|
externalId = "externalId"
|
|
273
244
|
name = "name"
|
|
@@ -293,61 +264,6 @@ class RelationshipEntity(Entity):
|
|
|
293
264
|
T_ID = TypeVar("T_ID", bound=ContainerId | ViewId | DataModelId | PropertyId | NodeId | None)
|
|
294
265
|
|
|
295
266
|
|
|
296
|
-
class MultiValueTypeInfo(BaseModel):
|
|
297
|
-
type_: ClassVar[EntityTypes] = EntityTypes.multi_value_type
|
|
298
|
-
types: list[DataType | ClassEntity]
|
|
299
|
-
|
|
300
|
-
def __str__(self) -> str:
|
|
301
|
-
return " | ".join([str(t) for t in self.types])
|
|
302
|
-
|
|
303
|
-
@model_serializer(when_used="unless-none", return_type=str)
|
|
304
|
-
def as_str(self) -> str:
|
|
305
|
-
return str(self)
|
|
306
|
-
|
|
307
|
-
@classmethod
|
|
308
|
-
def load(cls, data: Any) -> "MultiValueTypeInfo":
|
|
309
|
-
# already instance of MultiValueTypeInfo
|
|
310
|
-
if isinstance(data, cls):
|
|
311
|
-
return data
|
|
312
|
-
|
|
313
|
-
# it is a raw string that needs to be parsed
|
|
314
|
-
elif isinstance(data, str):
|
|
315
|
-
return cls.model_validate({_PARSE: data})
|
|
316
|
-
|
|
317
|
-
# it is dict that needs to be parsed
|
|
318
|
-
else:
|
|
319
|
-
return cls.model_validate(data)
|
|
320
|
-
|
|
321
|
-
@model_validator(mode="before")
|
|
322
|
-
def _load(cls, data: Any) -> "dict | MultiValueTypeInfo":
|
|
323
|
-
if isinstance(data, dict) and _PARSE in data:
|
|
324
|
-
data = data[_PARSE]
|
|
325
|
-
elif isinstance(data, dict):
|
|
326
|
-
return data
|
|
327
|
-
else:
|
|
328
|
-
raise ValueError(f"Cannot load {cls.__name__} from {data}")
|
|
329
|
-
|
|
330
|
-
result = cls._parse(data)
|
|
331
|
-
return result
|
|
332
|
-
|
|
333
|
-
@classmethod
|
|
334
|
-
def _parse(cls, raw: str) -> dict:
|
|
335
|
-
if not (types := [type_.strip() for type_ in raw.split("|")]):
|
|
336
|
-
return {"types": [UnknownEntity()]}
|
|
337
|
-
else:
|
|
338
|
-
return {
|
|
339
|
-
"types": [
|
|
340
|
-
(DataType.load(type_) if DataType.is_data_type(type_) else ClassEntity.load(type_))
|
|
341
|
-
for type_ in types
|
|
342
|
-
]
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
def set_default_prefix(self, prefix: str):
|
|
346
|
-
for type_ in self.types:
|
|
347
|
-
if isinstance(type_, ClassEntity) and type_.prefix is Undefined:
|
|
348
|
-
type_.prefix = prefix
|
|
349
|
-
|
|
350
|
-
|
|
351
267
|
class DMSEntity(Entity, Generic[T_ID], ABC):
|
|
352
268
|
type_: ClassVar[EntityTypes] = EntityTypes.undefined
|
|
353
269
|
prefix: str = Field(alias="space")
|
|
@@ -452,33 +368,6 @@ class DMSUnknownEntity(DMSEntity[None]):
|
|
|
452
368
|
return str(Unknown)
|
|
453
369
|
|
|
454
370
|
|
|
455
|
-
class ViewPropertyEntity(DMSVersionedEntity[PropertyId]):
|
|
456
|
-
type_: ClassVar[EntityTypes] = EntityTypes.property_
|
|
457
|
-
property_: str = Field(alias="property")
|
|
458
|
-
|
|
459
|
-
def as_id(self) -> PropertyId:
|
|
460
|
-
return PropertyId(
|
|
461
|
-
source=ViewId(self.space, self.external_id, self.version),
|
|
462
|
-
property=self.property_,
|
|
463
|
-
)
|
|
464
|
-
|
|
465
|
-
def as_view_id(self) -> ViewId:
|
|
466
|
-
return ViewId(space=self.space, external_id=self.external_id, version=self.version)
|
|
467
|
-
|
|
468
|
-
@classmethod
|
|
469
|
-
def from_id(cls, id: PropertyId) -> "ViewPropertyEntity":
|
|
470
|
-
if isinstance(id.source, ContainerId):
|
|
471
|
-
raise ValueError("Only view source are supported")
|
|
472
|
-
if id.source.version is None:
|
|
473
|
-
raise ValueError("Version must be specified")
|
|
474
|
-
return cls(
|
|
475
|
-
space=id.source.space,
|
|
476
|
-
externalId=id.source.external_id,
|
|
477
|
-
version=id.source.version,
|
|
478
|
-
property=id.property,
|
|
479
|
-
)
|
|
480
|
-
|
|
481
|
-
|
|
482
371
|
class DataModelEntity(DMSVersionedEntity[DataModelId]):
|
|
483
372
|
type_: ClassVar[EntityTypes] = EntityTypes.datamodel
|
|
484
373
|
|
|
@@ -498,10 +387,40 @@ class DMSNodeEntity(DMSEntity[NodeId]):
|
|
|
498
387
|
def as_id(self) -> NodeId:
|
|
499
388
|
return NodeId(space=self.space, external_id=self.external_id)
|
|
500
389
|
|
|
390
|
+
def as_reference(self) -> DirectRelationReference:
|
|
391
|
+
return DirectRelationReference(space=self.space, external_id=self.external_id)
|
|
392
|
+
|
|
501
393
|
@classmethod
|
|
502
394
|
def from_id(cls, id: NodeId) -> "DMSNodeEntity":
|
|
503
395
|
return cls(space=id.space, externalId=id.external_id)
|
|
504
396
|
|
|
397
|
+
@classmethod
|
|
398
|
+
def from_reference(cls, ref: DirectRelationReference) -> "DMSNodeEntity":
|
|
399
|
+
return cls(space=ref.space, externalId=ref.external_id)
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
class EdgeEntity(DMSEntity[None]):
|
|
403
|
+
type_: ClassVar[EntityTypes] = EntityTypes.edge
|
|
404
|
+
prefix: _UndefinedType = Undefined # type: ignore[assignment]
|
|
405
|
+
suffix: Literal["edge"] = "edge"
|
|
406
|
+
edge_type: DMSNodeEntity | None = Field(None, alias="type")
|
|
407
|
+
properties: ViewEntity | None = None
|
|
408
|
+
direction: Literal["outwards", "inwards"] = "outwards"
|
|
409
|
+
|
|
410
|
+
def as_id(self) -> None:
|
|
411
|
+
return None
|
|
412
|
+
|
|
413
|
+
@classmethod
|
|
414
|
+
def from_id(cls, id: None) -> Self:
|
|
415
|
+
return cls()
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
class ReverseConnectionEntity(Entity):
|
|
419
|
+
type_: ClassVar[EntityTypes] = EntityTypes.reverse
|
|
420
|
+
prefix: _UndefinedType = Undefined
|
|
421
|
+
suffix: Literal["reverse"] = "reverse"
|
|
422
|
+
property_: str = Field(alias="property")
|
|
423
|
+
|
|
505
424
|
|
|
506
425
|
class ReferenceEntity(ClassEntity):
|
|
507
426
|
type_: ClassVar[EntityTypes] = EntityTypes.reference_entity
|
|
@@ -538,80 +457,3 @@ class ReferenceEntity(ClassEntity):
|
|
|
538
457
|
|
|
539
458
|
def as_class_entity(self) -> ClassEntity:
|
|
540
459
|
return ClassEntity(prefix=self.prefix, suffix=self.suffix, version=self.version)
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
def _split_str(v: Any) -> list[str]:
|
|
544
|
-
if isinstance(v, str):
|
|
545
|
-
return v.replace(", ", ",").split(",")
|
|
546
|
-
return v
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
def _join_str(v: list[ClassEntity]) -> str | None:
|
|
550
|
-
return ",".join([entry.id for entry in v]) if v else None
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
def _generate_cdf_resource_list(v: Any) -> list[AssetEntity | RelationshipEntity]:
|
|
554
|
-
results = []
|
|
555
|
-
for item in _split_str(v):
|
|
556
|
-
if isinstance(item, str):
|
|
557
|
-
if "relationship" in item.lower():
|
|
558
|
-
results.append(RelationshipEntity.load(item))
|
|
559
|
-
elif "asset" in item.lower():
|
|
560
|
-
results.append(AssetEntity.load(item)) # type: ignore
|
|
561
|
-
else:
|
|
562
|
-
raise ValueError(f"Unsupported implementation definition: {item}")
|
|
563
|
-
|
|
564
|
-
elif isinstance(item, AssetEntity | RelationshipEntity):
|
|
565
|
-
results.append(item)
|
|
566
|
-
else:
|
|
567
|
-
raise ValueError(f"Unsupported implementation definition: {item}")
|
|
568
|
-
|
|
569
|
-
return results # type: ignore
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
ClassEntityList = Annotated[
|
|
573
|
-
list[ClassEntity],
|
|
574
|
-
BeforeValidator(_split_str),
|
|
575
|
-
PlainSerializer(
|
|
576
|
-
_join_str,
|
|
577
|
-
return_type=str,
|
|
578
|
-
when_used="unless-none",
|
|
579
|
-
),
|
|
580
|
-
]
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
CdfResourceEntityList = Annotated[
|
|
584
|
-
list[AssetEntity | RelationshipEntity],
|
|
585
|
-
BeforeValidator(_generate_cdf_resource_list),
|
|
586
|
-
PlainSerializer(
|
|
587
|
-
_join_str,
|
|
588
|
-
return_type=str,
|
|
589
|
-
when_used="unless-none",
|
|
590
|
-
),
|
|
591
|
-
]
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
ContainerEntityList = Annotated[
|
|
595
|
-
list[ContainerEntity],
|
|
596
|
-
BeforeValidator(_split_str),
|
|
597
|
-
PlainSerializer(
|
|
598
|
-
_join_str,
|
|
599
|
-
return_type=str,
|
|
600
|
-
when_used="unless-none",
|
|
601
|
-
),
|
|
602
|
-
]
|
|
603
|
-
|
|
604
|
-
ViewEntityList = Annotated[
|
|
605
|
-
list[ViewEntity],
|
|
606
|
-
BeforeValidator(_split_str),
|
|
607
|
-
PlainSerializer(
|
|
608
|
-
_join_str,
|
|
609
|
-
return_type=str,
|
|
610
|
-
when_used="unless-none",
|
|
611
|
-
),
|
|
612
|
-
]
|
|
613
|
-
|
|
614
|
-
URLEntity = Annotated[
|
|
615
|
-
AnyHttpUrl,
|
|
616
|
-
PlainSerializer(lambda v: str(v), return_type=str, when_used="unless-none"),
|
|
617
|
-
]
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
from typing import Annotated, Any
|
|
2
|
+
|
|
3
|
+
from pydantic import (
|
|
4
|
+
AnyHttpUrl,
|
|
5
|
+
BeforeValidator,
|
|
6
|
+
PlainSerializer,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
from ._single_value import AssetEntity, ClassEntity, ContainerEntity, RelationshipEntity, ViewEntity
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _split_str(v: Any) -> list[str]:
|
|
13
|
+
if isinstance(v, str):
|
|
14
|
+
return v.replace(", ", ",").split(",")
|
|
15
|
+
return v
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _join_str(v: list[ClassEntity]) -> str | None:
|
|
19
|
+
return ",".join([entry.id for entry in v]) if v else None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _generate_cdf_resource_list(v: Any) -> list[AssetEntity | RelationshipEntity]:
|
|
23
|
+
results = []
|
|
24
|
+
for item in _split_str(v):
|
|
25
|
+
if isinstance(item, str):
|
|
26
|
+
if "relationship" in item.lower():
|
|
27
|
+
results.append(RelationshipEntity.load(item))
|
|
28
|
+
elif "asset" in item.lower():
|
|
29
|
+
results.append(AssetEntity.load(item)) # type: ignore
|
|
30
|
+
else:
|
|
31
|
+
raise ValueError(f"Unsupported implementation definition: {item}")
|
|
32
|
+
|
|
33
|
+
elif isinstance(item, AssetEntity | RelationshipEntity):
|
|
34
|
+
results.append(item)
|
|
35
|
+
else:
|
|
36
|
+
raise ValueError(f"Unsupported implementation definition: {item}")
|
|
37
|
+
|
|
38
|
+
return results # type: ignore
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
ClassEntityList = Annotated[
|
|
42
|
+
list[ClassEntity],
|
|
43
|
+
BeforeValidator(_split_str),
|
|
44
|
+
PlainSerializer(
|
|
45
|
+
_join_str,
|
|
46
|
+
return_type=str,
|
|
47
|
+
when_used="unless-none",
|
|
48
|
+
),
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
CdfResourceEntityList = Annotated[
|
|
53
|
+
list[AssetEntity | RelationshipEntity],
|
|
54
|
+
BeforeValidator(_generate_cdf_resource_list),
|
|
55
|
+
PlainSerializer(
|
|
56
|
+
_join_str,
|
|
57
|
+
return_type=str,
|
|
58
|
+
when_used="unless-none",
|
|
59
|
+
),
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
ContainerEntityList = Annotated[
|
|
64
|
+
list[ContainerEntity],
|
|
65
|
+
BeforeValidator(_split_str),
|
|
66
|
+
PlainSerializer(
|
|
67
|
+
_join_str,
|
|
68
|
+
return_type=str,
|
|
69
|
+
when_used="unless-none",
|
|
70
|
+
),
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
ViewEntityList = Annotated[
|
|
74
|
+
list[ViewEntity],
|
|
75
|
+
BeforeValidator(_split_str),
|
|
76
|
+
PlainSerializer(
|
|
77
|
+
_join_str,
|
|
78
|
+
return_type=str,
|
|
79
|
+
when_used="unless-none",
|
|
80
|
+
),
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
URLEntity = Annotated[
|
|
84
|
+
AnyHttpUrl,
|
|
85
|
+
PlainSerializer(lambda v: str(v), return_type=str, when_used="unless-none"),
|
|
86
|
+
]
|
|
@@ -9,7 +9,7 @@ from cognite.client import data_modeling as dm
|
|
|
9
9
|
from cognite.client.data_classes.data_modeling import ContainerId, NodeId
|
|
10
10
|
from pydantic import BaseModel, model_serializer, model_validator
|
|
11
11
|
|
|
12
|
-
from
|
|
12
|
+
from ._single_value import ContainerEntity, DMSNodeEntity, Entity
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
@total_ordering
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
from ._rules import InformationClass, InformationMetadata, InformationProperty, InformationRules
|
|
2
|
-
from ._rules_input import
|
|
2
|
+
from ._rules_input import (
|
|
3
|
+
InformationInputClass,
|
|
4
|
+
InformationInputMetadata,
|
|
5
|
+
InformationInputProperty,
|
|
6
|
+
InformationInputRules,
|
|
7
|
+
)
|
|
3
8
|
|
|
4
9
|
__all__ = [
|
|
5
10
|
"InformationRules",
|
|
6
11
|
"InformationMetadata",
|
|
7
12
|
"InformationClass",
|
|
8
13
|
"InformationProperty",
|
|
9
|
-
"
|
|
14
|
+
"InformationInputRules",
|
|
15
|
+
"InformationInputMetadata",
|
|
16
|
+
"InformationInputClass",
|
|
17
|
+
"InformationInputProperty",
|
|
10
18
|
]
|
|
@@ -9,7 +9,7 @@ from rdflib import Namespace
|
|
|
9
9
|
|
|
10
10
|
from cognite.neat.constants import get_default_prefixes
|
|
11
11
|
from cognite.neat.issues.errors import PropertyDefinitionError
|
|
12
|
-
from cognite.neat.rules.models.
|
|
12
|
+
from cognite.neat.rules.models._base_rules import (
|
|
13
13
|
BaseMetadata,
|
|
14
14
|
BaseRules,
|
|
15
15
|
DataModelType,
|
|
@@ -34,7 +34,6 @@ from cognite.neat.rules.models._types import (
|
|
|
34
34
|
VersionType,
|
|
35
35
|
)
|
|
36
36
|
from cognite.neat.rules.models.data_types import DataType
|
|
37
|
-
from cognite.neat.rules.models.domain import DomainRules
|
|
38
37
|
from cognite.neat.rules.models.entities import (
|
|
39
38
|
ClassEntity,
|
|
40
39
|
ClassEntityList,
|
|
@@ -47,7 +46,7 @@ from cognite.neat.rules.models.entities import (
|
|
|
47
46
|
)
|
|
48
47
|
|
|
49
48
|
if TYPE_CHECKING:
|
|
50
|
-
from cognite.neat.rules.models import
|
|
49
|
+
from cognite.neat.rules.models import DMSRules
|
|
51
50
|
|
|
52
51
|
|
|
53
52
|
if sys.version_info >= (3, 11):
|
|
@@ -340,17 +339,7 @@ class InformationRules(BaseRules):
|
|
|
340
339
|
cleaned[reference] = _InformationRulesSerializer(by_alias, prefix).clean(ref_dump, True)
|
|
341
340
|
return cleaned
|
|
342
341
|
|
|
343
|
-
def as_domain_rules(self) -> DomainRules:
|
|
344
|
-
from ._converter import _InformationRulesConverter
|
|
345
|
-
|
|
346
|
-
return _InformationRulesConverter(self).as_domain_rules()
|
|
347
|
-
|
|
348
|
-
def as_asset_architect_rules(self) -> "AssetRules":
|
|
349
|
-
from ._converter import _InformationRulesConverter
|
|
350
|
-
|
|
351
|
-
return _InformationRulesConverter(self).as_asset_architect_rules()
|
|
352
|
-
|
|
353
342
|
def as_dms_rules(self) -> "DMSRules":
|
|
354
|
-
from .
|
|
343
|
+
from cognite.neat.rules.transformers._converters import _InformationRulesConverter
|
|
355
344
|
|
|
356
345
|
return _InformationRulesConverter(self).as_dms_rules()
|