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
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
from collections.abc import Sequence
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from typing import Any, Literal, cast, overload
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
|
|
8
|
+
from cognite.neat.rules.models.data_types import DataType
|
|
9
|
+
from cognite.neat.rules.models.entities import (
|
|
10
|
+
ClassEntity,
|
|
11
|
+
ContainerEntity,
|
|
12
|
+
DMSUnknownEntity,
|
|
13
|
+
Unknown,
|
|
14
|
+
ViewEntity,
|
|
15
|
+
ViewPropertyEntity,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
from ._base import ExtensionCategory, SchemaCompleteness
|
|
19
|
+
from ._dms_architect_rules import DMSContainer, DMSMetadata, DMSProperty, DMSRules, DMSView
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class DMSMetadataWrite:
|
|
24
|
+
schema_: Literal["complete", "partial", "extended"]
|
|
25
|
+
space: str
|
|
26
|
+
external_id: str
|
|
27
|
+
creator: str
|
|
28
|
+
version: str
|
|
29
|
+
extension: Literal["addition", "reshape", "rebuild"] = "addition"
|
|
30
|
+
name: str | None = None
|
|
31
|
+
description: str | None = None
|
|
32
|
+
created: datetime | str | None = None
|
|
33
|
+
updated: datetime | str | None = None
|
|
34
|
+
default_view_version: str | None = None
|
|
35
|
+
|
|
36
|
+
@classmethod
|
|
37
|
+
def load(cls, data: dict[str, Any] | None) -> "DMSMetadataWrite | None":
|
|
38
|
+
if data is None:
|
|
39
|
+
return None
|
|
40
|
+
_add_alias(data, DMSMetadata)
|
|
41
|
+
return cls(
|
|
42
|
+
schema_=data.get("schema_"), # type: ignore[arg-type]
|
|
43
|
+
space=data.get("space"), # type: ignore[arg-type]
|
|
44
|
+
external_id=data.get("external_id"), # type: ignore[arg-type]
|
|
45
|
+
creator=data.get("creator"), # type: ignore[arg-type]
|
|
46
|
+
version=data.get("version"), # type: ignore[arg-type]
|
|
47
|
+
extension=data.get("extension", "addition"),
|
|
48
|
+
name=data.get("name"),
|
|
49
|
+
description=data.get("description"),
|
|
50
|
+
created=data.get("created"),
|
|
51
|
+
updated=data.get("updated"),
|
|
52
|
+
default_view_version=data.get("default_view_version"),
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
def dump(self) -> dict[str, Any]:
|
|
56
|
+
return dict(
|
|
57
|
+
schema=SchemaCompleteness(self.schema_),
|
|
58
|
+
extension=ExtensionCategory(self.extension),
|
|
59
|
+
space=self.space,
|
|
60
|
+
externalId=self.external_id,
|
|
61
|
+
creator=self.creator,
|
|
62
|
+
version=self.version,
|
|
63
|
+
name=self.name,
|
|
64
|
+
description=self.description,
|
|
65
|
+
created=self.created or datetime.now(),
|
|
66
|
+
updated=self.updated or datetime.now(),
|
|
67
|
+
default_view_version=self.default_view_version or self.version,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass
|
|
72
|
+
class DMSPropertyWrite:
|
|
73
|
+
view: str
|
|
74
|
+
view_property: str | None
|
|
75
|
+
value_type: str
|
|
76
|
+
property_: str | None
|
|
77
|
+
class_: str | None = None
|
|
78
|
+
name: str | None = None
|
|
79
|
+
description: str | None = None
|
|
80
|
+
relation: Literal["direct", "reversedirect", "multiedge"] | None = None
|
|
81
|
+
nullable: bool | None = None
|
|
82
|
+
is_list: bool | None = None
|
|
83
|
+
default: str | int | dict | None = None
|
|
84
|
+
reference: str | None = None
|
|
85
|
+
container: str | None = None
|
|
86
|
+
container_property: str | None = None
|
|
87
|
+
index: str | list[str] | None = None
|
|
88
|
+
constraint: str | list[str] | None = None
|
|
89
|
+
|
|
90
|
+
@classmethod
|
|
91
|
+
@overload
|
|
92
|
+
def load(cls, data: None) -> None:
|
|
93
|
+
...
|
|
94
|
+
|
|
95
|
+
@classmethod
|
|
96
|
+
@overload
|
|
97
|
+
def load(cls, data: dict[str, Any]) -> "DMSPropertyWrite":
|
|
98
|
+
...
|
|
99
|
+
|
|
100
|
+
@classmethod
|
|
101
|
+
@overload
|
|
102
|
+
def load(cls, data: list[dict[str, Any]]) -> list["DMSPropertyWrite"]:
|
|
103
|
+
...
|
|
104
|
+
|
|
105
|
+
@classmethod
|
|
106
|
+
def load(
|
|
107
|
+
cls, data: dict[str, Any] | list[dict[str, Any]] | None
|
|
108
|
+
) -> "DMSPropertyWrite | list[DMSPropertyWrite] | None":
|
|
109
|
+
if data is None:
|
|
110
|
+
return None
|
|
111
|
+
if isinstance(data, list) or (isinstance(data, dict) and isinstance(data.get("data"), list)):
|
|
112
|
+
items = cast(list[dict[str, Any]], data.get("data") if isinstance(data, dict) else data)
|
|
113
|
+
return [loaded for item in items if (loaded := cls.load(item)) is not None]
|
|
114
|
+
|
|
115
|
+
_add_alias(data, DMSProperty)
|
|
116
|
+
return cls(
|
|
117
|
+
view=data.get("view"), # type: ignore[arg-type]
|
|
118
|
+
view_property=data.get("view_property"), # type: ignore[arg-type]
|
|
119
|
+
value_type=data.get("value_type"), # type: ignore[arg-type]
|
|
120
|
+
property_=data.get("property_"),
|
|
121
|
+
class_=data.get("class_"),
|
|
122
|
+
name=data.get("name"),
|
|
123
|
+
description=data.get("description"),
|
|
124
|
+
relation=data.get("relation"),
|
|
125
|
+
nullable=data.get("nullable"),
|
|
126
|
+
is_list=data.get("is_list"),
|
|
127
|
+
default=data.get("default"),
|
|
128
|
+
reference=data.get("reference"),
|
|
129
|
+
container=data.get("container"),
|
|
130
|
+
container_property=data.get("container_property"),
|
|
131
|
+
index=data.get("index"),
|
|
132
|
+
constraint=data.get("constraint"),
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
def dump(self, default_space: str, default_version: str) -> dict[str, Any]:
|
|
136
|
+
value_type: DataType | ViewPropertyEntity | ViewEntity | DMSUnknownEntity
|
|
137
|
+
if DataType.is_data_type(self.value_type):
|
|
138
|
+
value_type = DataType.load(self.value_type)
|
|
139
|
+
elif self.value_type == str(Unknown):
|
|
140
|
+
value_type = DMSUnknownEntity()
|
|
141
|
+
else:
|
|
142
|
+
try:
|
|
143
|
+
value_type = ViewPropertyEntity.load(self.value_type, space=default_space, version=default_version)
|
|
144
|
+
except ValueError:
|
|
145
|
+
value_type = ViewEntity.load(self.value_type, space=default_space, version=default_version)
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
"View": ViewEntity.load(self.view, space=default_space, version=default_version),
|
|
149
|
+
"ViewProperty": self.view_property,
|
|
150
|
+
"Value Type": value_type,
|
|
151
|
+
"Property": self.property_ or self.view_property,
|
|
152
|
+
"Class": ClassEntity.load(self.class_, prefix=default_space, version=default_version)
|
|
153
|
+
if self.class_
|
|
154
|
+
else None,
|
|
155
|
+
"Name": self.name,
|
|
156
|
+
"Description": self.description,
|
|
157
|
+
"Relation": self.relation,
|
|
158
|
+
"Nullable": self.nullable,
|
|
159
|
+
"IsList": self.is_list,
|
|
160
|
+
"Default": self.default,
|
|
161
|
+
"Reference": self.reference,
|
|
162
|
+
"Container": ContainerEntity.load(self.container, space=default_space, version=default_version)
|
|
163
|
+
if self.container
|
|
164
|
+
else None,
|
|
165
|
+
"ContainerProperty": self.container_property,
|
|
166
|
+
"Index": self.index,
|
|
167
|
+
"Constraint": self.constraint,
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
@dataclass
|
|
172
|
+
class DMSContainerWrite:
|
|
173
|
+
container: str
|
|
174
|
+
class_: str | None = None
|
|
175
|
+
name: str | None = None
|
|
176
|
+
description: str | None = None
|
|
177
|
+
reference: str | None = None
|
|
178
|
+
constraint: str | None = None
|
|
179
|
+
|
|
180
|
+
@classmethod
|
|
181
|
+
@overload
|
|
182
|
+
def load(cls, data: None) -> None:
|
|
183
|
+
...
|
|
184
|
+
|
|
185
|
+
@classmethod
|
|
186
|
+
@overload
|
|
187
|
+
def load(cls, data: dict[str, Any]) -> "DMSContainerWrite":
|
|
188
|
+
...
|
|
189
|
+
|
|
190
|
+
@classmethod
|
|
191
|
+
@overload
|
|
192
|
+
def load(cls, data: list[dict[str, Any]]) -> list["DMSContainerWrite"]:
|
|
193
|
+
...
|
|
194
|
+
|
|
195
|
+
@classmethod
|
|
196
|
+
def load(
|
|
197
|
+
cls, data: dict[str, Any] | list[dict[str, Any]] | None
|
|
198
|
+
) -> "DMSContainerWrite | list[DMSContainerWrite] | None":
|
|
199
|
+
if data is None:
|
|
200
|
+
return None
|
|
201
|
+
if isinstance(data, list) or (isinstance(data, dict) and isinstance(data.get("data"), list)):
|
|
202
|
+
items = cast(list[dict[str, Any]], data.get("data") if isinstance(data, dict) else data)
|
|
203
|
+
return [loaded for item in items if (loaded := cls.load(item)) is not None]
|
|
204
|
+
|
|
205
|
+
_add_alias(data, DMSContainer)
|
|
206
|
+
return cls(
|
|
207
|
+
container=data.get("container"), # type: ignore[arg-type]
|
|
208
|
+
class_=data.get("class_"),
|
|
209
|
+
name=data.get("name"),
|
|
210
|
+
description=data.get("description"),
|
|
211
|
+
reference=data.get("reference"),
|
|
212
|
+
constraint=data.get("constraint"),
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
def dump(self, default_space: str) -> dict[str, Any]:
|
|
216
|
+
container = ContainerEntity.load(self.container, space=default_space)
|
|
217
|
+
return dict(
|
|
218
|
+
Container=container,
|
|
219
|
+
Class=ClassEntity.load(self.class_, prefix=default_space) if self.class_ else container.as_class(),
|
|
220
|
+
Name=self.name,
|
|
221
|
+
Description=self.description,
|
|
222
|
+
Reference=self.reference,
|
|
223
|
+
Constraint=[
|
|
224
|
+
ContainerEntity.load(constraint.strip(), space=default_space)
|
|
225
|
+
for constraint in self.constraint.split(",")
|
|
226
|
+
]
|
|
227
|
+
if self.constraint
|
|
228
|
+
else None,
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
@dataclass
|
|
233
|
+
class DMSViewWrite:
|
|
234
|
+
view: str
|
|
235
|
+
class_: str | None = None
|
|
236
|
+
name: str | None = None
|
|
237
|
+
description: str | None = None
|
|
238
|
+
implements: str | None = None
|
|
239
|
+
reference: str | None = None
|
|
240
|
+
filter_: Literal["hasData", "nodeType"] | None = None
|
|
241
|
+
in_model: bool = True
|
|
242
|
+
|
|
243
|
+
@classmethod
|
|
244
|
+
@overload
|
|
245
|
+
def load(cls, data: None) -> None:
|
|
246
|
+
...
|
|
247
|
+
|
|
248
|
+
@classmethod
|
|
249
|
+
@overload
|
|
250
|
+
def load(cls, data: dict[str, Any]) -> "DMSViewWrite":
|
|
251
|
+
...
|
|
252
|
+
|
|
253
|
+
@classmethod
|
|
254
|
+
@overload
|
|
255
|
+
def load(cls, data: list[dict[str, Any]]) -> list["DMSViewWrite"]:
|
|
256
|
+
...
|
|
257
|
+
|
|
258
|
+
@classmethod
|
|
259
|
+
def load(cls, data: dict[str, Any] | list[dict[str, Any]] | None) -> "DMSViewWrite | list[DMSViewWrite] | None":
|
|
260
|
+
if data is None:
|
|
261
|
+
return None
|
|
262
|
+
if isinstance(data, list) or (isinstance(data, dict) and isinstance(data.get("data"), list)):
|
|
263
|
+
items = cast(list[dict[str, Any]], data.get("data") if isinstance(data, dict) else data)
|
|
264
|
+
return [loaded for item in items if (loaded := cls.load(item)) is not None]
|
|
265
|
+
_add_alias(data, DMSView)
|
|
266
|
+
|
|
267
|
+
return cls(
|
|
268
|
+
view=data.get("view"), # type: ignore[arg-type]
|
|
269
|
+
class_=data.get("class"),
|
|
270
|
+
name=data.get("name"),
|
|
271
|
+
description=data.get("description"),
|
|
272
|
+
implements=data.get("implements"),
|
|
273
|
+
reference=data.get("reference"),
|
|
274
|
+
filter_=data.get("filter_"),
|
|
275
|
+
in_model=data.get("in_model", True),
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
def dump(self, default_space: str, default_version: str) -> dict[str, Any]:
|
|
279
|
+
view = ViewEntity.load(self.view, space=default_space, version=default_version)
|
|
280
|
+
return dict(
|
|
281
|
+
View=view,
|
|
282
|
+
Class=ClassEntity.load(self.class_, prefix=default_space, version=default_version)
|
|
283
|
+
if self.class_
|
|
284
|
+
else view.as_class(),
|
|
285
|
+
Name=self.name,
|
|
286
|
+
Description=self.description,
|
|
287
|
+
Implements=[
|
|
288
|
+
ViewEntity.load(implement, space=default_space, version=default_version)
|
|
289
|
+
for implement in self.implements.split(",")
|
|
290
|
+
]
|
|
291
|
+
if self.implements
|
|
292
|
+
else None,
|
|
293
|
+
Reference=self.reference,
|
|
294
|
+
Filter=self.filter_,
|
|
295
|
+
InModel=self.in_model,
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
@dataclass
|
|
300
|
+
class DMSRulesWrite:
|
|
301
|
+
metadata: DMSMetadataWrite
|
|
302
|
+
properties: Sequence[DMSPropertyWrite]
|
|
303
|
+
views: Sequence[DMSViewWrite]
|
|
304
|
+
containers: Sequence[DMSContainerWrite] | None = None
|
|
305
|
+
reference: "DMSRulesWrite | DMSRules | None" = None
|
|
306
|
+
|
|
307
|
+
@classmethod
|
|
308
|
+
@overload
|
|
309
|
+
def load(cls, data: dict[str, Any]) -> "DMSRulesWrite":
|
|
310
|
+
...
|
|
311
|
+
|
|
312
|
+
@classmethod
|
|
313
|
+
@overload
|
|
314
|
+
def load(cls, data: None) -> None:
|
|
315
|
+
...
|
|
316
|
+
|
|
317
|
+
@classmethod
|
|
318
|
+
def load(cls, data: dict | None) -> "DMSRulesWrite | None":
|
|
319
|
+
if data is None:
|
|
320
|
+
return None
|
|
321
|
+
_add_alias(data, DMSRules)
|
|
322
|
+
return cls(
|
|
323
|
+
metadata=DMSMetadataWrite.load(data.get("metadata")), # type: ignore[arg-type]
|
|
324
|
+
properties=DMSPropertyWrite.load(data.get("properties")), # type: ignore[arg-type]
|
|
325
|
+
views=DMSViewWrite.load(data.get("views")), # type: ignore[arg-type]
|
|
326
|
+
containers=DMSContainerWrite.load(data.get("containers")) or [],
|
|
327
|
+
reference=DMSRulesWrite.load(data.get("reference")),
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
def as_read(self) -> DMSRules:
|
|
331
|
+
return DMSRules.model_validate(self.dump())
|
|
332
|
+
|
|
333
|
+
def dump(self) -> dict[str, Any]:
|
|
334
|
+
default_space = self.metadata.space
|
|
335
|
+
default_version = self.metadata.version
|
|
336
|
+
reference: dict[str, Any] | None = None
|
|
337
|
+
if isinstance(self.reference, DMSRulesWrite):
|
|
338
|
+
reference = self.reference.dump()
|
|
339
|
+
elif isinstance(self.reference, DMSRules):
|
|
340
|
+
# We need to load through the DMSRulesWrite to set the correct default space and version
|
|
341
|
+
reference = DMSRulesWrite.load(self.reference.model_dump()).dump()
|
|
342
|
+
|
|
343
|
+
return dict(
|
|
344
|
+
Metadata=self.metadata.dump(),
|
|
345
|
+
Properties=[prop.dump(default_space, default_version) for prop in self.properties],
|
|
346
|
+
Views=[view.dump(default_space, default_version) for view in self.views],
|
|
347
|
+
Containers=[container.dump(default_space) for container in self.containers or []] or None,
|
|
348
|
+
Reference=reference,
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
def _add_alias(data: dict[str, Any], base_model: type[BaseModel]) -> None:
|
|
353
|
+
for field_name, field_ in base_model.model_fields.items():
|
|
354
|
+
if field_name not in data and field_.alias in data:
|
|
355
|
+
data[field_name] = data[field_.alias]
|
|
@@ -27,7 +27,7 @@ from cognite.neat.rules.issues.dms import (
|
|
|
27
27
|
MissingSpaceError,
|
|
28
28
|
MissingViewError,
|
|
29
29
|
)
|
|
30
|
-
from cognite.neat.rules.models.
|
|
30
|
+
from cognite.neat.rules.models.data_types import _DATA_TYPE_BY_DMS_TYPE
|
|
31
31
|
from cognite.neat.utils.cdf_loaders import ViewLoader
|
|
32
32
|
from cognite.neat.utils.cdf_loaders.data_classes import RawTableWrite, RawTableWriteList
|
|
33
33
|
from cognite.neat.utils.text import to_camel
|
|
@@ -577,8 +577,8 @@ class PipelineSchema(DMSSchema):
|
|
|
577
577
|
container = container_by_id.get(prop.container)
|
|
578
578
|
if container is not None:
|
|
579
579
|
dms_type = container.properties[prop.container_property_identifier].type._type
|
|
580
|
-
if dms_type in
|
|
581
|
-
sql_type =
|
|
580
|
+
if dms_type in _DATA_TYPE_BY_DMS_TYPE:
|
|
581
|
+
sql_type = _DATA_TYPE_BY_DMS_TYPE[dms_type].sql
|
|
582
582
|
else:
|
|
583
583
|
warnings.warn(
|
|
584
584
|
f"Unknown DMS type '{dms_type}' for property '{prop_name}'", RuntimeWarning, stacklevel=2
|
|
@@ -4,6 +4,9 @@ from typing import Any, ClassVar
|
|
|
4
4
|
from pydantic import Field, field_serializer, field_validator, model_serializer
|
|
5
5
|
from pydantic_core.core_schema import SerializationInfo
|
|
6
6
|
|
|
7
|
+
from cognite.neat.rules.models.data_types import DataType
|
|
8
|
+
from cognite.neat.rules.models.entities import ClassEntity, ParentEntityList
|
|
9
|
+
|
|
7
10
|
from ._base import (
|
|
8
11
|
BaseMetadata,
|
|
9
12
|
RoleTypes,
|
|
@@ -11,7 +14,7 @@ from ._base import (
|
|
|
11
14
|
SheetEntity,
|
|
12
15
|
SheetList,
|
|
13
16
|
)
|
|
14
|
-
from ._types import
|
|
17
|
+
from ._types import PropertyType, StrOrListType
|
|
15
18
|
|
|
16
19
|
|
|
17
20
|
class DomainMetadata(BaseMetadata):
|
|
@@ -21,7 +24,7 @@ class DomainMetadata(BaseMetadata):
|
|
|
21
24
|
|
|
22
25
|
class DomainProperty(SheetEntity):
|
|
23
26
|
property_: PropertyType = Field(alias="Property")
|
|
24
|
-
value_type:
|
|
27
|
+
value_type: DataType | ClassEntity = Field(alias="Value Type")
|
|
25
28
|
min_count: int | None = Field(alias="Min Count", default=None)
|
|
26
29
|
max_count: int | float | None = Field(alias="Max Count", default=None)
|
|
27
30
|
|
|
@@ -40,7 +43,7 @@ class DomainProperty(SheetEntity):
|
|
|
40
43
|
|
|
41
44
|
class DomainClass(SheetEntity):
|
|
42
45
|
description: str | None = Field(None, alias="Description")
|
|
43
|
-
parent:
|
|
46
|
+
parent: ParentEntityList | None = Field(alias="Parent Class")
|
|
44
47
|
|
|
45
48
|
|
|
46
49
|
class DomainRules(RuleModel):
|