cognite-neat 0.75.7__py3-none-any.whl → 0.75.8__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/graph/extractors/_mock_graph_generator.py +6 -5
- cognite/neat/rules/analysis/_base.py +1 -1
- cognite/neat/rules/analysis/_information_rules.py +4 -4
- cognite/neat/rules/exporters/_rules2ontology.py +20 -17
- cognite/neat/rules/exporters/_validation.py +2 -2
- cognite/neat/rules/importers/_dms2rules.py +14 -15
- cognite/neat/rules/importers/_dtdl2rules/dtdl_converter.py +21 -19
- cognite/neat/rules/importers/_dtdl2rules/spec.py +1 -1
- cognite/neat/rules/importers/_owl2rules/_owl2rules.py +2 -2
- cognite/neat/rules/importers/_spreadsheet2rules.py +6 -1
- cognite/neat/rules/importers/_yaml2rules.py +8 -2
- cognite/neat/rules/issues/dms.py +1 -1
- cognite/neat/rules/models/data_types.py +54 -31
- cognite/neat/rules/models/entities.py +184 -41
- cognite/neat/rules/models/rdfpath.py +111 -11
- cognite/neat/rules/models/rules/_base.py +2 -2
- cognite/neat/rules/models/rules/_dms_architect_rules.py +117 -188
- cognite/neat/rules/models/rules/_dms_rules_write.py +355 -0
- cognite/neat/rules/models/rules/_dms_schema.py +3 -3
- cognite/neat/rules/models/rules/_domain_rules.py +6 -3
- cognite/neat/rules/models/rules/_information_rules.py +68 -61
- cognite/neat/rules/models/rules/_types/__init__.py +0 -47
- cognite/neat/rules/models/rules/_types/_base.py +1 -309
- cognite/neat/rules/models/rules/_types/_field.py +0 -225
- cognite/neat/workflows/steps/lib/rules_importer.py +3 -3
- {cognite_neat-0.75.7.dist-info → cognite_neat-0.75.8.dist-info}/METADATA +1 -1
- {cognite_neat-0.75.7.dist-info → cognite_neat-0.75.8.dist-info}/RECORD +31 -32
- cognite/neat/rules/models/_entity.py +0 -142
- cognite/neat/rules/models/rules/_types/_value.py +0 -159
- {cognite_neat-0.75.7.dist-info → cognite_neat-0.75.8.dist-info}/LICENSE +0 -0
- {cognite_neat-0.75.7.dist-info → cognite_neat-0.75.8.dist-info}/WHEEL +0 -0
- {cognite_neat-0.75.7.dist-info → cognite_neat-0.75.8.dist-info}/entry_points.txt +0 -0
|
@@ -4,22 +4,13 @@
|
|
|
4
4
|
import re
|
|
5
5
|
import sys
|
|
6
6
|
from collections import Counter
|
|
7
|
-
from
|
|
7
|
+
from functools import total_ordering
|
|
8
|
+
from typing import ClassVar, Literal
|
|
8
9
|
|
|
9
10
|
from pydantic import BaseModel, field_validator
|
|
10
11
|
|
|
11
12
|
from cognite.neat.rules import exceptions
|
|
12
13
|
|
|
13
|
-
from ._entity import (
|
|
14
|
-
CLASS_ID_REGEX,
|
|
15
|
-
CLASS_ID_REGEX_COMPILED,
|
|
16
|
-
ENTITY_ID_REGEX,
|
|
17
|
-
PROPERTY_ID_REGEX,
|
|
18
|
-
SUFFIX_REGEX,
|
|
19
|
-
Entity,
|
|
20
|
-
EntityTypes,
|
|
21
|
-
)
|
|
22
|
-
|
|
23
14
|
if sys.version_info >= (3, 11):
|
|
24
15
|
from enum import StrEnum
|
|
25
16
|
from typing import Self
|
|
@@ -40,6 +31,26 @@ class Lookup(StrEnum):
|
|
|
40
31
|
value = "value" # type: ignore
|
|
41
32
|
|
|
42
33
|
|
|
34
|
+
class EntityTypes(StrEnum):
|
|
35
|
+
class_ = "class"
|
|
36
|
+
property_ = "property"
|
|
37
|
+
undefined = "undefined"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# FOR PARSING STRINGS:
|
|
41
|
+
PREFIX_REGEX = r"[a-zA-Z]+[a-zA-Z0-9-_.]*[a-zA-Z0-9]+"
|
|
42
|
+
SUFFIX_REGEX = r"[a-zA-Z0-9-_.]+[a-zA-Z0-9]|[-_.]*[a-zA-Z0-9]+"
|
|
43
|
+
VERSION_REGEX = r"[a-zA-Z0-9]([.a-zA-Z0-9_-]{0,41}[a-zA-Z0-9])?"
|
|
44
|
+
|
|
45
|
+
ENTITY_ID_REGEX = rf"{PREFIX_REGEX}:({SUFFIX_REGEX})"
|
|
46
|
+
ENTITY_ID_REGEX_COMPILED = re.compile(rf"^(?P<prefix>{PREFIX_REGEX}):(?P<suffix>{SUFFIX_REGEX})$")
|
|
47
|
+
VERSIONED_ENTITY_REGEX_COMPILED = re.compile(
|
|
48
|
+
rf"^(?P<prefix>{PREFIX_REGEX}):(?P<suffix>{SUFFIX_REGEX})\(version=(?P<version>{VERSION_REGEX})\)$"
|
|
49
|
+
)
|
|
50
|
+
CLASS_ID_REGEX = rf"(?P<{EntityTypes.class_}>{ENTITY_ID_REGEX})"
|
|
51
|
+
CLASS_ID_REGEX_COMPILED = re.compile(rf"^{CLASS_ID_REGEX}$")
|
|
52
|
+
PROPERTY_ID_REGEX = rf"\((?P<{EntityTypes.property_}>{ENTITY_ID_REGEX})\)"
|
|
53
|
+
|
|
43
54
|
# traversal direction
|
|
44
55
|
DIRECTION_REGEX = r"(?P<direction>(->|<-))"
|
|
45
56
|
|
|
@@ -73,6 +84,95 @@ TABLE_REGEX_COMPILED = re.compile(
|
|
|
73
84
|
StepDirection = Literal["source", "target", "origin"]
|
|
74
85
|
_direction_by_symbol: dict[str, StepDirection] = {"->": "target", "<-": "source"}
|
|
75
86
|
|
|
87
|
+
Undefined = type(object())
|
|
88
|
+
Unknown = type(object())
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
# mypy does not like the sentinel value, and it is not possible to ignore only the line with it below.
|
|
92
|
+
# so we ignore all errors beyond this point.
|
|
93
|
+
# mypy: ignore-errors
|
|
94
|
+
@total_ordering
|
|
95
|
+
class Entity(BaseModel, arbitrary_types_allowed=True):
|
|
96
|
+
"""Entity is a class or property in OWL/RDF sense."""
|
|
97
|
+
|
|
98
|
+
type_: ClassVar[EntityTypes] = EntityTypes.undefined
|
|
99
|
+
prefix: str | Undefined = Undefined
|
|
100
|
+
suffix: str | Unknown
|
|
101
|
+
version: str | None = None
|
|
102
|
+
name: str | None = None
|
|
103
|
+
description: str | None = None
|
|
104
|
+
|
|
105
|
+
def __lt__(self, other: object) -> bool:
|
|
106
|
+
if type(self) is not type(other) or not isinstance(other, Entity):
|
|
107
|
+
return NotImplemented
|
|
108
|
+
return self.versioned_id < other.versioned_id
|
|
109
|
+
|
|
110
|
+
def __eq__(self, other: object) -> bool:
|
|
111
|
+
if type(self) is not type(other) or not isinstance(other, Entity):
|
|
112
|
+
return NotImplemented
|
|
113
|
+
return self.versioned_id == other.versioned_id
|
|
114
|
+
|
|
115
|
+
def __hash__(self) -> int:
|
|
116
|
+
return hash(self.versioned_id)
|
|
117
|
+
|
|
118
|
+
def as_non_versioned_entity(self) -> Self:
|
|
119
|
+
return self.from_string(f"{self.prefix}:{self.suffix}")
|
|
120
|
+
|
|
121
|
+
@property
|
|
122
|
+
def id(self) -> str:
|
|
123
|
+
if self.suffix is Unknown:
|
|
124
|
+
return "#N/A"
|
|
125
|
+
elif self.prefix is Undefined:
|
|
126
|
+
return self.suffix
|
|
127
|
+
else:
|
|
128
|
+
return f"{self.prefix}:{self.suffix}"
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def versioned_id(self) -> str:
|
|
132
|
+
if self.version is None:
|
|
133
|
+
return self.id
|
|
134
|
+
else:
|
|
135
|
+
return f"{self.id}(version={self.version})"
|
|
136
|
+
|
|
137
|
+
@property
|
|
138
|
+
def space(self) -> str:
|
|
139
|
+
"""Returns entity space in CDF."""
|
|
140
|
+
return self.prefix
|
|
141
|
+
|
|
142
|
+
@property
|
|
143
|
+
def external_id(self) -> str:
|
|
144
|
+
"""Returns entity external id in CDF."""
|
|
145
|
+
return self.suffix
|
|
146
|
+
|
|
147
|
+
def __repr__(self):
|
|
148
|
+
return self.versioned_id
|
|
149
|
+
|
|
150
|
+
def __str__(self):
|
|
151
|
+
return self.versioned_id
|
|
152
|
+
|
|
153
|
+
@classmethod
|
|
154
|
+
def from_string(cls, entity_string: str, base_prefix: str | None = None) -> Self:
|
|
155
|
+
if entity_string == "#N/A":
|
|
156
|
+
return cls(prefix=Undefined, suffix=Unknown)
|
|
157
|
+
elif result := VERSIONED_ENTITY_REGEX_COMPILED.match(entity_string):
|
|
158
|
+
return cls(
|
|
159
|
+
prefix=result.group("prefix"),
|
|
160
|
+
suffix=result.group("suffix"),
|
|
161
|
+
version=result.group("version"),
|
|
162
|
+
)
|
|
163
|
+
elif result := ENTITY_ID_REGEX_COMPILED.match(entity_string):
|
|
164
|
+
return cls(prefix=result.group("prefix"), suffix=result.group("suffix"))
|
|
165
|
+
elif base_prefix and re.match(SUFFIX_REGEX, entity_string) and re.match(PREFIX_REGEX, base_prefix):
|
|
166
|
+
return cls(prefix=base_prefix, suffix=entity_string)
|
|
167
|
+
else:
|
|
168
|
+
raise ValueError(f"{cls.__name__} is expected to be prefix:suffix, got {entity_string}")
|
|
169
|
+
|
|
170
|
+
@classmethod
|
|
171
|
+
def from_list(cls, entity_strings: list[str], base_prefix: str | None = None) -> list[Self]:
|
|
172
|
+
return [
|
|
173
|
+
cls.from_string(entity_string=entity_string, base_prefix=base_prefix) for entity_string in entity_strings
|
|
174
|
+
]
|
|
175
|
+
|
|
76
176
|
|
|
77
177
|
class Step(BaseModel):
|
|
78
178
|
class_: Entity
|
|
@@ -27,7 +27,7 @@ from pydantic import (
|
|
|
27
27
|
)
|
|
28
28
|
from pydantic.fields import FieldInfo
|
|
29
29
|
|
|
30
|
-
from cognite.neat.rules.models.
|
|
30
|
+
from cognite.neat.rules.models.entities import ClassEntity
|
|
31
31
|
|
|
32
32
|
if sys.version_info >= (3, 11):
|
|
33
33
|
from enum import StrEnum
|
|
@@ -274,7 +274,7 @@ class BaseRules(RuleModel):
|
|
|
274
274
|
|
|
275
275
|
# An sheet entity is either a class or a property.
|
|
276
276
|
class SheetEntity(RuleModel):
|
|
277
|
-
class_:
|
|
277
|
+
class_: ClassEntity = Field(alias="Class")
|
|
278
278
|
name: str | None = Field(alias="Name", default=None)
|
|
279
279
|
description: str | None = Field(alias="Description", default=None)
|
|
280
280
|
|