cognite-neat 0.75.6__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/_models.py +6 -1
- cognite/neat/rules/exporters/_rules2dms.py +67 -14
- 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 +282 -0
- cognite/neat/rules/models/entities.py +442 -0
- 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/utils/cdf_loaders/_data_modeling.py +4 -2
- cognite/neat/workflows/steps/lib/rules_exporter.py +97 -0
- cognite/neat/workflows/steps/lib/rules_importer.py +3 -3
- {cognite_neat-0.75.6.dist-info → cognite_neat-0.75.8.dist-info}/METADATA +1 -1
- {cognite_neat-0.75.6.dist-info → cognite_neat-0.75.8.dist-info}/RECORD +35 -34
- cognite/neat/rules/models/_entity.py +0 -142
- cognite/neat/rules/models/rules/_types/_value.py +0 -159
- {cognite_neat-0.75.6.dist-info → cognite_neat-0.75.8.dist-info}/LICENSE +0 -0
- {cognite_neat-0.75.6.dist-info → cognite_neat-0.75.8.dist-info}/WHEEL +0 -0
- {cognite_neat-0.75.6.dist-info → cognite_neat-0.75.8.dist-info}/entry_points.txt +0 -0
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
import sys
|
|
3
|
-
from functools import total_ordering
|
|
4
|
-
from typing import ClassVar
|
|
5
|
-
|
|
6
|
-
from pydantic import BaseModel
|
|
7
|
-
|
|
8
|
-
if sys.version_info >= (3, 11):
|
|
9
|
-
from enum import StrEnum
|
|
10
|
-
from typing import Self
|
|
11
|
-
else:
|
|
12
|
-
from backports.strenum import StrEnum
|
|
13
|
-
from typing_extensions import Self
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class EntityTypes(StrEnum):
|
|
17
|
-
subject = "subject"
|
|
18
|
-
predicate = "predicate"
|
|
19
|
-
object = "object"
|
|
20
|
-
class_ = "class"
|
|
21
|
-
parent_class = "parent_class"
|
|
22
|
-
property_ = "property"
|
|
23
|
-
object_property = "ObjectProperty"
|
|
24
|
-
data_property = "DatatypeProperty"
|
|
25
|
-
annotation_property = "AnnotationProperty"
|
|
26
|
-
object_value_type = "object_value_type"
|
|
27
|
-
data_value_type = "data_value_type" # these are strings, floats, ...
|
|
28
|
-
xsd_value_type = "xsd_value_type"
|
|
29
|
-
dms_value_type = "dms_value_type"
|
|
30
|
-
view = "view"
|
|
31
|
-
view_prop = "view_prop"
|
|
32
|
-
reference_entity = "reference_entity"
|
|
33
|
-
container = "container"
|
|
34
|
-
datamodel = "datamodel"
|
|
35
|
-
undefined = "undefined"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
# ALLOWED
|
|
39
|
-
ALLOWED_PATTERN = r"[^a-zA-Z0-9-_.]"
|
|
40
|
-
|
|
41
|
-
# FOR PARSING STRINGS:
|
|
42
|
-
PREFIX_REGEX = r"[a-zA-Z]+[a-zA-Z0-9-_.]*[a-zA-Z0-9]+"
|
|
43
|
-
SUFFIX_REGEX = r"[a-zA-Z0-9-_.]+[a-zA-Z0-9]|[-_.]*[a-zA-Z0-9]+"
|
|
44
|
-
VERSION_REGEX = r"[a-zA-Z0-9]([.a-zA-Z0-9_-]{0,41}[a-zA-Z0-9])?"
|
|
45
|
-
PROPERTY_REGEX = r"[a-zA-Z0-9][a-zA-Z0-9_-]*[a-zA-Z0-9]?"
|
|
46
|
-
ENTITY_ID_REGEX = rf"{PREFIX_REGEX}:({SUFFIX_REGEX})"
|
|
47
|
-
ENTITY_ID_REGEX_COMPILED = re.compile(rf"^(?P<prefix>{PREFIX_REGEX}):(?P<suffix>{SUFFIX_REGEX})$")
|
|
48
|
-
VERSIONED_ENTITY_REGEX_COMPILED = re.compile(
|
|
49
|
-
rf"^(?P<prefix>{PREFIX_REGEX}):(?P<suffix>{SUFFIX_REGEX})\(version=(?P<version>{VERSION_REGEX})\)$"
|
|
50
|
-
)
|
|
51
|
-
CLASS_ID_REGEX = rf"(?P<{EntityTypes.class_}>{ENTITY_ID_REGEX})"
|
|
52
|
-
CLASS_ID_REGEX_COMPILED = re.compile(rf"^{CLASS_ID_REGEX}$")
|
|
53
|
-
PROPERTY_ID_REGEX = rf"\((?P<{EntityTypes.property_}>{ENTITY_ID_REGEX})\)"
|
|
54
|
-
|
|
55
|
-
Undefined = type(object())
|
|
56
|
-
Unknown = type(object())
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
# mypy does not like the sentinel value, and it is not possible to ignore only the line with it below.
|
|
60
|
-
# so we ignore all errors beyond this point.
|
|
61
|
-
# mypy: ignore-errors
|
|
62
|
-
@total_ordering
|
|
63
|
-
class Entity(BaseModel, arbitrary_types_allowed=True):
|
|
64
|
-
"""Entity is a class or property in OWL/RDF sense."""
|
|
65
|
-
|
|
66
|
-
type_: ClassVar[EntityTypes] = EntityTypes.undefined
|
|
67
|
-
prefix: str | Undefined = Undefined
|
|
68
|
-
suffix: str | Unknown
|
|
69
|
-
version: str | None = None
|
|
70
|
-
name: str | None = None
|
|
71
|
-
description: str | None = None
|
|
72
|
-
|
|
73
|
-
def __lt__(self, other: object) -> bool:
|
|
74
|
-
if type(self) is not type(other) or not isinstance(other, Entity):
|
|
75
|
-
return NotImplemented
|
|
76
|
-
return self.versioned_id < other.versioned_id
|
|
77
|
-
|
|
78
|
-
def __eq__(self, other: object) -> bool:
|
|
79
|
-
if type(self) is not type(other) or not isinstance(other, Entity):
|
|
80
|
-
return NotImplemented
|
|
81
|
-
return self.versioned_id == other.versioned_id
|
|
82
|
-
|
|
83
|
-
def __hash__(self) -> int:
|
|
84
|
-
return hash(self.versioned_id)
|
|
85
|
-
|
|
86
|
-
def as_non_versioned_entity(self) -> Self:
|
|
87
|
-
return self.from_string(f"{self.prefix}:{self.suffix}")
|
|
88
|
-
|
|
89
|
-
@property
|
|
90
|
-
def id(self) -> str:
|
|
91
|
-
if self.suffix is Unknown:
|
|
92
|
-
return "#N/A"
|
|
93
|
-
elif self.prefix is Undefined:
|
|
94
|
-
return self.suffix
|
|
95
|
-
else:
|
|
96
|
-
return f"{self.prefix}:{self.suffix}"
|
|
97
|
-
|
|
98
|
-
@property
|
|
99
|
-
def versioned_id(self) -> str:
|
|
100
|
-
if self.version is None:
|
|
101
|
-
return self.id
|
|
102
|
-
else:
|
|
103
|
-
return f"{self.id}(version={self.version})"
|
|
104
|
-
|
|
105
|
-
@property
|
|
106
|
-
def space(self) -> str:
|
|
107
|
-
"""Returns entity space in CDF."""
|
|
108
|
-
return self.prefix
|
|
109
|
-
|
|
110
|
-
@property
|
|
111
|
-
def external_id(self) -> str:
|
|
112
|
-
"""Returns entity external id in CDF."""
|
|
113
|
-
return self.suffix
|
|
114
|
-
|
|
115
|
-
def __repr__(self):
|
|
116
|
-
return self.versioned_id
|
|
117
|
-
|
|
118
|
-
def __str__(self):
|
|
119
|
-
return self.versioned_id
|
|
120
|
-
|
|
121
|
-
@classmethod
|
|
122
|
-
def from_string(cls, entity_string: str, base_prefix: str | None = None) -> Self:
|
|
123
|
-
if entity_string == "#N/A":
|
|
124
|
-
return cls(prefix=Undefined, suffix=Unknown)
|
|
125
|
-
elif result := VERSIONED_ENTITY_REGEX_COMPILED.match(entity_string):
|
|
126
|
-
return cls(
|
|
127
|
-
prefix=result.group("prefix"),
|
|
128
|
-
suffix=result.group("suffix"),
|
|
129
|
-
version=result.group("version"),
|
|
130
|
-
)
|
|
131
|
-
elif result := ENTITY_ID_REGEX_COMPILED.match(entity_string):
|
|
132
|
-
return cls(prefix=result.group("prefix"), suffix=result.group("suffix"))
|
|
133
|
-
elif base_prefix and re.match(SUFFIX_REGEX, entity_string) and re.match(PREFIX_REGEX, base_prefix):
|
|
134
|
-
return cls(prefix=base_prefix, suffix=entity_string)
|
|
135
|
-
else:
|
|
136
|
-
raise ValueError(f"{cls.__name__} is expected to be prefix:suffix, got {entity_string}")
|
|
137
|
-
|
|
138
|
-
@classmethod
|
|
139
|
-
def from_list(cls, entity_strings: list[str], base_prefix: str | None = None) -> list[Self]:
|
|
140
|
-
return [
|
|
141
|
-
cls.from_string(entity_string=entity_string, base_prefix=base_prefix) for entity_string in entity_strings
|
|
142
|
-
]
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from datetime import date, datetime
|
|
4
|
-
from typing import ClassVar, cast
|
|
5
|
-
|
|
6
|
-
from cognite.client.data_classes.data_modeling import (
|
|
7
|
-
Boolean,
|
|
8
|
-
Date,
|
|
9
|
-
FileReference,
|
|
10
|
-
Float32,
|
|
11
|
-
Float64,
|
|
12
|
-
Int32,
|
|
13
|
-
Int64,
|
|
14
|
-
Json,
|
|
15
|
-
SequenceReference,
|
|
16
|
-
Text,
|
|
17
|
-
TimeSeriesReference,
|
|
18
|
-
Timestamp,
|
|
19
|
-
)
|
|
20
|
-
from pydantic import BaseModel
|
|
21
|
-
|
|
22
|
-
from ._base import Entity, EntityTypes
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class ValueTypeMapping(BaseModel):
|
|
26
|
-
"""Mapping between XSD, Python, DMS and Graphql types."""
|
|
27
|
-
|
|
28
|
-
xsd: str
|
|
29
|
-
python: type
|
|
30
|
-
dms: type
|
|
31
|
-
graphql: str
|
|
32
|
-
sql: str
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
# mypy: ignore-errors
|
|
36
|
-
class XSDValueType(Entity):
|
|
37
|
-
"""Value type is a data/object type defined as a child of Entity model."""
|
|
38
|
-
|
|
39
|
-
type_: ClassVar[EntityTypes] = EntityTypes.xsd_value_type
|
|
40
|
-
mapping: ValueTypeMapping
|
|
41
|
-
|
|
42
|
-
@property
|
|
43
|
-
def python(self) -> type:
|
|
44
|
-
"""Returns the Python type for a given value type."""
|
|
45
|
-
return cast(ValueTypeMapping, self.mapping).python
|
|
46
|
-
|
|
47
|
-
@property
|
|
48
|
-
def xsd(self) -> str:
|
|
49
|
-
"""Returns the XSD type for a given value type."""
|
|
50
|
-
return cast(ValueTypeMapping, self.mapping).xsd
|
|
51
|
-
|
|
52
|
-
@property
|
|
53
|
-
def dms(self) -> type:
|
|
54
|
-
"""Returns the DMS type for a given value type."""
|
|
55
|
-
return cast(ValueTypeMapping, self.mapping).dms
|
|
56
|
-
|
|
57
|
-
@property
|
|
58
|
-
def graphql(self) -> str:
|
|
59
|
-
"""Returns the Graphql type for a given value type."""
|
|
60
|
-
return cast(ValueTypeMapping, self.mapping).graphql
|
|
61
|
-
|
|
62
|
-
@property
|
|
63
|
-
def sql(self) -> str:
|
|
64
|
-
"""Returns the SQL type for a given value type."""
|
|
65
|
-
return cast(ValueTypeMapping, self.mapping).sql
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
class DMSValueType(XSDValueType):
|
|
69
|
-
type_: ClassVar[EntityTypes] = EntityTypes.dms_value_type
|
|
70
|
-
|
|
71
|
-
def __str__(self) -> str:
|
|
72
|
-
return self.dms._type
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
_DATA_TYPES: list[dict] = [
|
|
76
|
-
{"name": "boolean", "python": bool, "GraphQL": "Boolean", "dms": Boolean, "SQL": "BOOLEAN"},
|
|
77
|
-
{"name": "float", "python": float, "GraphQL": "Float", "dms": Float64, "SQL": "FLOAT"},
|
|
78
|
-
{"name": "double", "python": float, "GraphQL": "Float", "dms": Float64, "SQL": "DOUBLE"},
|
|
79
|
-
{"name": "integer", "python": int, "GraphQL": "Int", "dms": Int32, "SQL": "INTEGER"},
|
|
80
|
-
{"name": "nonPositiveInteger", "python": int, "GraphQL": "Int", "dms": Int32, "SQL": "INTEGER"},
|
|
81
|
-
{"name": "nonNegativeInteger", "python": int, "GraphQL": "Int", "dms": Int32, "SQL": "INTEGER"},
|
|
82
|
-
{"name": "negativeInteger", "python": int, "GraphQL": "Int", "dms": Int32, "SQL": "INTEGER"},
|
|
83
|
-
{"name": "long", "python": int, "GraphQL": "Int", "dms": Int64, "SQL": "INTEGER"},
|
|
84
|
-
{"name": "string", "python": str, "GraphQL": "String", "dms": Text, "SQL": "STRING"},
|
|
85
|
-
{"name": "langString", "python": str, "GraphQL": "String", "dms": Text, "SQL": "STRING"},
|
|
86
|
-
{"name": "anyURI", "python": str, "GraphQL": "String", "dms": Text, "SQL": "STRING"},
|
|
87
|
-
{"name": "normalizedString", "python": str, "GraphQL": "String", "dms": Text, "SQL": "STRING"},
|
|
88
|
-
{"name": "token", "python": str, "GraphQL": "String", "dms": Text, "SQL": "STRING"},
|
|
89
|
-
# Graphql does not have a datetime/date type this is CDF specific
|
|
90
|
-
{"name": "dateTime", "python": datetime, "GraphQL": "Timestamp", "dms": Timestamp, "SQL": "TIMESTAMP"},
|
|
91
|
-
{"name": "dateTimeStamp", "python": datetime, "GraphQL": "Timestamp", "dms": Timestamp, "SQL": "TIMESTAMP"},
|
|
92
|
-
{"name": "date", "python": date, "GraphQL": "String", "dms": Date, "SQL": "DATE"},
|
|
93
|
-
# Some RDF types which are not in XSD
|
|
94
|
-
{"name": "PlainLiteral", "python": str, "GraphQL": "String", "dms": Text, "SQL": "STRING"},
|
|
95
|
-
{"name": "Literal", "python": str, "GraphQL": "String", "dms": Text, "SQL": "STRING"},
|
|
96
|
-
# CDF specific types, not in XSD
|
|
97
|
-
{
|
|
98
|
-
"name": "timeseries",
|
|
99
|
-
"python": TimeSeriesReference,
|
|
100
|
-
"GraphQL": "TimeSeries",
|
|
101
|
-
"dms": TimeSeriesReference,
|
|
102
|
-
"SQL": "STRING",
|
|
103
|
-
},
|
|
104
|
-
{"name": "file", "python": FileReference, "GraphQL": "File", "dms": FileReference, "SQL": "STRING"},
|
|
105
|
-
{"name": "sequence", "python": SequenceReference, "GraphQL": "Sequence", "dms": SequenceReference, "SQL": "STRING"},
|
|
106
|
-
{"name": "json", "python": Json, "GraphQL": "Json", "dms": Json, "SQL": "STRING"},
|
|
107
|
-
]
|
|
108
|
-
|
|
109
|
-
_DMS_TYPES: list[dict] = [
|
|
110
|
-
{"name": "boolean", "python": bool, "GraphQL": "Boolean", "dms": Boolean, "SQL": "BOOLEAN"},
|
|
111
|
-
{"name": "float", "python": float, "GraphQL": "Float", "dms": Float32, "SQL": "FLOAT"},
|
|
112
|
-
{"name": "double", "python": float, "GraphQL": "Float", "dms": Float64, "SQL": "DOUBLE"},
|
|
113
|
-
{"name": "integer", "python": int, "GraphQL": "Int", "dms": Int32, "SQL": "INTEGER"},
|
|
114
|
-
{"name": "long", "python": int, "GraphQL": "Int", "dms": Int64, "SQL": "INTEGER"},
|
|
115
|
-
{"name": "string", "python": str, "GraphQL": "String", "dms": Text, "SQL": "STRING"},
|
|
116
|
-
{"name": "dateTimeStamp", "python": datetime, "GraphQL": "Timestamp", "dms": Timestamp, "SQL": "TIMESTAMP"},
|
|
117
|
-
{
|
|
118
|
-
"name": "timeseries",
|
|
119
|
-
"python": TimeSeriesReference,
|
|
120
|
-
"GraphQL": "TimeSeries",
|
|
121
|
-
"dms": TimeSeriesReference,
|
|
122
|
-
"SQL": "STRING",
|
|
123
|
-
},
|
|
124
|
-
{"name": "file", "python": FileReference, "GraphQL": "File", "dms": FileReference, "SQL": "STRING"},
|
|
125
|
-
{"name": "sequence", "python": SequenceReference, "GraphQL": "Sequence", "dms": SequenceReference, "SQL": "STRING"},
|
|
126
|
-
{"name": "json", "python": Json, "GraphQL": "Json", "dms": Json, "SQL": "STRING"},
|
|
127
|
-
]
|
|
128
|
-
|
|
129
|
-
XSD_VALUE_TYPE_MAPPINGS: dict[str, XSDValueType] = {
|
|
130
|
-
data_type["name"]: XSDValueType(
|
|
131
|
-
prefix="xsd",
|
|
132
|
-
suffix=cast(str, data_type["name"]),
|
|
133
|
-
name=cast(str, data_type["name"]),
|
|
134
|
-
mapping=ValueTypeMapping(
|
|
135
|
-
xsd=data_type["name"],
|
|
136
|
-
python=data_type["python"],
|
|
137
|
-
dms=data_type["dms"],
|
|
138
|
-
graphql=data_type["GraphQL"],
|
|
139
|
-
sql=data_type["SQL"],
|
|
140
|
-
),
|
|
141
|
-
)
|
|
142
|
-
for data_type in _DATA_TYPES
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
DMS_VALUE_TYPE_MAPPINGS: dict[str, DMSValueType] = {
|
|
146
|
-
data_type["dms"]._type.casefold(): DMSValueType(
|
|
147
|
-
prefix="dms",
|
|
148
|
-
suffix=data_type["dms"]._type.casefold(),
|
|
149
|
-
name=data_type["dms"]._type.casefold(),
|
|
150
|
-
mapping=ValueTypeMapping(
|
|
151
|
-
xsd=data_type["name"],
|
|
152
|
-
python=data_type["python"],
|
|
153
|
-
dms=data_type["dms"],
|
|
154
|
-
graphql=data_type["GraphQL"],
|
|
155
|
-
sql=data_type["SQL"],
|
|
156
|
-
),
|
|
157
|
-
)
|
|
158
|
-
for data_type in _DMS_TYPES
|
|
159
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|