cognite-neat 1.0.32__py3-none-any.whl → 1.0.33__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.
- cognite/neat/_data_model/deployer/_differ_container.py +1 -1
- cognite/neat/_data_model/deployer/data_classes.py +15 -16
- cognite/neat/_data_model/deployer/deployer.py +40 -13
- cognite/neat/_data_model/models/dms/_http.py +10 -1
- cognite/neat/_data_model/models/dms/_references.py +38 -4
- cognite/neat/_version.py +1 -1
- {cognite_neat-1.0.32.dist-info → cognite_neat-1.0.33.dist-info}/METADATA +1 -1
- {cognite_neat-1.0.32.dist-info → cognite_neat-1.0.33.dist-info}/RECORD +9 -9
- {cognite_neat-1.0.32.dist-info → cognite_neat-1.0.33.dist-info}/WHEEL +0 -0
|
@@ -55,7 +55,7 @@ class ContainerDiffer(ItemDiffer[ContainerRequest]):
|
|
|
55
55
|
"constraints",
|
|
56
56
|
current.constraints,
|
|
57
57
|
new.constraints,
|
|
58
|
-
add_severity=SeverityType.
|
|
58
|
+
add_severity=SeverityType.WARNING,
|
|
59
59
|
remove_severity=SeverityType.WARNING,
|
|
60
60
|
differ=ConstraintDiffer("constraints"),
|
|
61
61
|
)
|
|
@@ -12,7 +12,6 @@ from pydantic.alias_generators import to_camel
|
|
|
12
12
|
from cognite.neat._data_model._snapshot import SchemaSnapshot
|
|
13
13
|
from cognite.neat._data_model.models.dms import (
|
|
14
14
|
BaseModelObject,
|
|
15
|
-
Constraint,
|
|
16
15
|
ContainerConstraintReference,
|
|
17
16
|
ContainerIndexReference,
|
|
18
17
|
ContainerPropertyDefinition,
|
|
@@ -20,7 +19,6 @@ from cognite.neat._data_model.models.dms import (
|
|
|
20
19
|
ContainerRequest,
|
|
21
20
|
DataModelRequest,
|
|
22
21
|
DataModelResource,
|
|
23
|
-
Index,
|
|
24
22
|
T_DataModelResource,
|
|
25
23
|
T_ResourceId,
|
|
26
24
|
ViewRequest,
|
|
@@ -193,7 +191,9 @@ class ContainerDeploymentPlan(ResourceDeploymentPlan[ContainerReference, Contain
|
|
|
193
191
|
def constraints_to_remove(self) -> dict[ContainerConstraintReference, RemovedField]:
|
|
194
192
|
return self._get_fields_to_remove("constraints.", ContainerConstraintReference)
|
|
195
193
|
|
|
196
|
-
def _get_fields_to_remove(
|
|
194
|
+
def _get_fields_to_remove(
|
|
195
|
+
self, field_prefix: str, ref_cls: type[ContainerIndexReference] | type[ContainerConstraintReference]
|
|
196
|
+
) -> dict:
|
|
197
197
|
items: dict = {}
|
|
198
198
|
for resource_change in self.resources:
|
|
199
199
|
for change in resource_change.changes:
|
|
@@ -202,7 +202,7 @@ class ContainerDeploymentPlan(ResourceDeploymentPlan[ContainerReference, Contain
|
|
|
202
202
|
items[
|
|
203
203
|
ref_cls(
|
|
204
204
|
space=resource_change.resource_id.space,
|
|
205
|
-
|
|
205
|
+
container_external_id=resource_change.resource_id.external_id,
|
|
206
206
|
identifier=identifier,
|
|
207
207
|
)
|
|
208
208
|
] = change
|
|
@@ -254,7 +254,7 @@ class ResourceDeploymentPlanList(UserList[ResourceDeploymentPlan]):
|
|
|
254
254
|
updated_resource = resource.model_copy(update={"new_value": resource.current_value})
|
|
255
255
|
elif resource.changes and resource.new_value is not None:
|
|
256
256
|
# Find all field removals and update new_value accordingly.
|
|
257
|
-
removals = [change for change in resource.changes if isinstance(change, RemovedField)]
|
|
257
|
+
removals: list[RemovedField] = [change for change in resource.changes if isinstance(change, RemovedField)]
|
|
258
258
|
addition_paths = {change.field_path for change in resource.changes if isinstance(change, AddedField)}
|
|
259
259
|
if removals:
|
|
260
260
|
if resource.current_value is None:
|
|
@@ -271,6 +271,13 @@ class ResourceDeploymentPlanList(UserList[ResourceDeploymentPlan]):
|
|
|
271
271
|
for change in resource.changes
|
|
272
272
|
if not isinstance(change, RemovedField)
|
|
273
273
|
or (isinstance(change, RemovedField) and change.field_path in addition_paths)
|
|
274
|
+
or (
|
|
275
|
+
isinstance(change, RemovedField)
|
|
276
|
+
and (
|
|
277
|
+
change.field_path.startswith("constraints.")
|
|
278
|
+
or change.field_path.startswith("indexes.")
|
|
279
|
+
)
|
|
280
|
+
)
|
|
274
281
|
],
|
|
275
282
|
}
|
|
276
283
|
)
|
|
@@ -320,22 +327,14 @@ class ResourceDeploymentPlanList(UserList[ResourceDeploymentPlan]):
|
|
|
320
327
|
resource: ContainerRequest, removals: list[RemovedField], addition_paths: set[str]
|
|
321
328
|
) -> DataModelResource:
|
|
322
329
|
container_properties = resource.properties.copy()
|
|
323
|
-
indexes = (resource.indexes or {}).copy()
|
|
324
|
-
constraints = (resource.constraints or {}).copy()
|
|
325
330
|
for removal in removals:
|
|
326
331
|
if removal.field_path.startswith("properties."):
|
|
327
332
|
prop_key = removal.field_path.removeprefix("properties.")
|
|
328
333
|
container_properties[prop_key] = cast(ContainerPropertyDefinition, removal.current_value)
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
index_key = removal.field_path.removeprefix("indexes.")
|
|
332
|
-
indexes[index_key] = cast(Index, removal.current_value)
|
|
333
|
-
elif removal.field_path.startswith("constraints.") and removal.field_path not in addition_paths:
|
|
334
|
-
# Constraint was removed and not re-added, so we need to restore it.
|
|
335
|
-
constraint_key = removal.field_path.removeprefix("constraints.")
|
|
336
|
-
constraints[constraint_key] = cast(Constraint, removal.current_value)
|
|
334
|
+
# Note: indexes and constraints are allowed to be removed in additive mode,
|
|
335
|
+
# so we don't restore them here unlike properties.
|
|
337
336
|
return resource.model_copy(
|
|
338
|
-
update={"properties": container_properties
|
|
337
|
+
update={"properties": container_properties},
|
|
339
338
|
deep=True,
|
|
340
339
|
)
|
|
341
340
|
|
|
@@ -185,16 +185,20 @@ class SchemaDeployer(OnSuccessResultProducer):
|
|
|
185
185
|
continue
|
|
186
186
|
current_resource = current_resources[ref]
|
|
187
187
|
diffs = differ.diff(current_resource, new_resource)
|
|
188
|
-
if (
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
and self.options.modus_operandi == "additive"
|
|
192
|
-
):
|
|
193
|
-
# In additive mode, changes to constraints and indexes require removal and re-adding
|
|
194
|
-
# In rebuild mode, all changes are forced via deletion and re-adding
|
|
188
|
+
if isinstance(current_resource, ContainerRequest) and isinstance(new_resource, ContainerRequest):
|
|
189
|
+
# CDF doesn't support in-place modification of constraints/indexes,
|
|
190
|
+
# so we transform changes to remove + add operations in both modes
|
|
195
191
|
diffs = self.remove_readd_modified_indexes_and_constraints(diffs, current_resource, new_resource)
|
|
192
|
+
|
|
193
|
+
warnings = self._generate_warnings_for_constraint_and_index_changes(diffs)
|
|
196
194
|
resources.append(
|
|
197
|
-
ResourceChange(
|
|
195
|
+
ResourceChange(
|
|
196
|
+
resource_id=ref,
|
|
197
|
+
new_value=new_resource,
|
|
198
|
+
current_value=current_resource,
|
|
199
|
+
changes=diffs,
|
|
200
|
+
message=" ".join(warnings) if warnings else None,
|
|
201
|
+
)
|
|
198
202
|
)
|
|
199
203
|
|
|
200
204
|
return plan_type(endpoint=endpoint, resources=resources)
|
|
@@ -222,19 +226,19 @@ class SchemaDeployer(OnSuccessResultProducer):
|
|
|
222
226
|
raise RuntimeError("Bug in Neat. Malformed field path for constraint/index change.")
|
|
223
227
|
# Field type is either "constraints" or "indexes"
|
|
224
228
|
field_type, identifier, *_ = diff.field_path.split(".", maxsplit=2)
|
|
225
|
-
|
|
229
|
+
field_path = f"{field_type}.{identifier}"
|
|
226
230
|
modified_diffs.append(
|
|
227
231
|
RemovedField(
|
|
228
|
-
field_path=
|
|
232
|
+
field_path=field_path,
|
|
229
233
|
item_severity=SeverityType.WARNING,
|
|
230
234
|
current_value=getattr(current_resource, field_type)[identifier],
|
|
231
235
|
)
|
|
232
236
|
)
|
|
233
|
-
|
|
237
|
+
add_severity = SeverityType.WARNING if field_type == "constraints" else SeverityType.SAFE
|
|
234
238
|
modified_diffs.append(
|
|
235
239
|
AddedField(
|
|
236
|
-
field_path=
|
|
237
|
-
item_severity=
|
|
240
|
+
field_path=field_path,
|
|
241
|
+
item_severity=add_severity,
|
|
238
242
|
new_value=getattr(new_resource, field_type)[identifier],
|
|
239
243
|
)
|
|
240
244
|
)
|
|
@@ -262,6 +266,29 @@ class SchemaDeployer(OnSuccessResultProducer):
|
|
|
262
266
|
)
|
|
263
267
|
return None
|
|
264
268
|
|
|
269
|
+
@classmethod
|
|
270
|
+
def _generate_warnings_for_constraint_and_index_changes(cls, diffs: list[FieldChange]) -> list[str]:
|
|
271
|
+
"""Generate warning messages for constraint and index changes.
|
|
272
|
+
|
|
273
|
+
Args:
|
|
274
|
+
diffs: The list of field changes.
|
|
275
|
+
|
|
276
|
+
Returns:
|
|
277
|
+
A list of warning messages for field changes involving constraint and index changes.
|
|
278
|
+
"""
|
|
279
|
+
warnings: list[str] = []
|
|
280
|
+
if any(isinstance(diff, AddedField) and diff.field_path.startswith("constraints.") for diff in diffs):
|
|
281
|
+
warnings.append(
|
|
282
|
+
"Adding constraints could cause ingestion failures if the data being ingested violates the constraint."
|
|
283
|
+
)
|
|
284
|
+
if any(
|
|
285
|
+
isinstance(diff, RemovedField)
|
|
286
|
+
and (diff.field_path.startswith("constraints.") or diff.field_path.startswith("indexes."))
|
|
287
|
+
for diff in diffs
|
|
288
|
+
):
|
|
289
|
+
warnings.append("Removing constraints or indexes may affect query performance.")
|
|
290
|
+
return warnings
|
|
291
|
+
|
|
265
292
|
def should_proceed_to_deploy(self, plan: Sequence[ResourceDeploymentPlan]) -> bool:
|
|
266
293
|
max_severity_in_plan = SeverityType.max_severity(
|
|
267
294
|
[change.severity for resource_plan in plan for change in resource_plan.resources],
|
|
@@ -6,6 +6,8 @@ from cognite.neat._utils.useful_types import ReferenceObject
|
|
|
6
6
|
from ._container import ContainerRequest
|
|
7
7
|
from ._data_model import DataModelRequest
|
|
8
8
|
from ._references import (
|
|
9
|
+
ContainerConstraintReference,
|
|
10
|
+
ContainerIndexReference,
|
|
9
11
|
ContainerReference,
|
|
10
12
|
DataModelReference,
|
|
11
13
|
SpaceReference,
|
|
@@ -18,7 +20,14 @@ DataModelResource: TypeAlias = SpaceRequest | DataModelRequest | ViewRequest | C
|
|
|
18
20
|
|
|
19
21
|
T_DataModelResource = TypeVar("T_DataModelResource", bound=DataModelResource)
|
|
20
22
|
|
|
21
|
-
ResourceId: TypeAlias =
|
|
23
|
+
ResourceId: TypeAlias = (
|
|
24
|
+
SpaceReference
|
|
25
|
+
| DataModelReference
|
|
26
|
+
| ViewReference
|
|
27
|
+
| ContainerReference
|
|
28
|
+
| ContainerIndexReference
|
|
29
|
+
| ContainerConstraintReference
|
|
30
|
+
)
|
|
22
31
|
|
|
23
32
|
T_ResourceId = TypeVar("T_ResourceId", bound=ResourceId)
|
|
24
33
|
|
|
@@ -133,9 +133,43 @@ class ViewDirectReference(ReferenceObject):
|
|
|
133
133
|
return f"{self.source!s}.{self.identifier}"
|
|
134
134
|
|
|
135
135
|
|
|
136
|
-
class ContainerIndexReference(
|
|
137
|
-
|
|
136
|
+
class ContainerIndexReference(ReferenceObject):
|
|
137
|
+
"""Reference to a container index for deletion API."""
|
|
138
|
+
|
|
139
|
+
space: str = Field(
|
|
140
|
+
description="Id of the space hosting the container.",
|
|
141
|
+
min_length=1,
|
|
142
|
+
max_length=43,
|
|
143
|
+
pattern=SPACE_FORMAT_PATTERN,
|
|
144
|
+
)
|
|
145
|
+
container_external_id: str = Field(
|
|
146
|
+
description="External-id of the container.",
|
|
147
|
+
min_length=1,
|
|
148
|
+
max_length=255,
|
|
149
|
+
pattern=DM_EXTERNAL_ID_PATTERN,
|
|
150
|
+
alias="containerExternalId",
|
|
151
|
+
)
|
|
152
|
+
identifier: str = Field(
|
|
153
|
+
description="Identifier of the index.",
|
|
154
|
+
)
|
|
138
155
|
|
|
139
156
|
|
|
140
|
-
class ContainerConstraintReference(
|
|
141
|
-
|
|
157
|
+
class ContainerConstraintReference(ReferenceObject):
|
|
158
|
+
"""Reference to a container constraint for deletion API."""
|
|
159
|
+
|
|
160
|
+
space: str = Field(
|
|
161
|
+
description="Id of the space hosting the container.",
|
|
162
|
+
min_length=1,
|
|
163
|
+
max_length=43,
|
|
164
|
+
pattern=SPACE_FORMAT_PATTERN,
|
|
165
|
+
)
|
|
166
|
+
container_external_id: str = Field(
|
|
167
|
+
description="External-id of the container.",
|
|
168
|
+
min_length=1,
|
|
169
|
+
max_length=255,
|
|
170
|
+
pattern=DM_EXTERNAL_ID_PATTERN,
|
|
171
|
+
alias="containerExternalId",
|
|
172
|
+
)
|
|
173
|
+
identifier: str = Field(
|
|
174
|
+
description="Identifier of the constraint.",
|
|
175
|
+
)
|
cognite/neat/_version.py
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
__version__ = "1.0.
|
|
1
|
+
__version__ = "1.0.33"
|
|
2
2
|
__engine__ = "^2.0.4"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cognite-neat
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.33
|
|
4
4
|
Summary: Knowledge graph transformation
|
|
5
5
|
Author: Nikola Vasiljevic, Anders Albert
|
|
6
6
|
Author-email: Nikola Vasiljevic <nikola.vasiljevic@cognite.com>, Anders Albert <anders.albert@cognite.com>
|
|
@@ -24,12 +24,12 @@ cognite/neat/_data_model/_shared.py,sha256=H0gFqa8tKFNWuvdat5jL6OwySjCw3aQkLPY3w
|
|
|
24
24
|
cognite/neat/_data_model/_snapshot.py,sha256=JBaKmL0Tmprz59SZ1JeB49BPMB8Hqa-OAOt0Bai8cw4,6305
|
|
25
25
|
cognite/neat/_data_model/deployer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
26
|
cognite/neat/_data_model/deployer/_differ.py,sha256=1ircRBCoaFooSzMTmTZBTORHeAhDa8YtDEnVwBo6TUI,4742
|
|
27
|
-
cognite/neat/_data_model/deployer/_differ_container.py,sha256=
|
|
27
|
+
cognite/neat/_data_model/deployer/_differ_container.py,sha256=AGD4emPRCEdFGFN4rJzLn8JhOjbTrHtYVtXr8q9vSPY,14668
|
|
28
28
|
cognite/neat/_data_model/deployer/_differ_data_model.py,sha256=iA7Xp-7NRvzZJXLLpJaLebkKKpv_VCBKPX6f-RU9wBk,1864
|
|
29
29
|
cognite/neat/_data_model/deployer/_differ_space.py,sha256=J_AaqiseLpwQsOkKc7gmho4U2oSWAGVeEdQNepZiWw0,343
|
|
30
30
|
cognite/neat/_data_model/deployer/_differ_view.py,sha256=g1xHwsoxFUaTOTtQa19nntKF3rxFzc2FxpKKFAUN_NE,11412
|
|
31
|
-
cognite/neat/_data_model/deployer/data_classes.py,sha256=
|
|
32
|
-
cognite/neat/_data_model/deployer/deployer.py,sha256=
|
|
31
|
+
cognite/neat/_data_model/deployer/data_classes.py,sha256=HhByk8m7SbEPAKkUNDF7koRtQPHhILpVXN3f83icfKs,27028
|
|
32
|
+
cognite/neat/_data_model/deployer/deployer.py,sha256=CaD_N6fy2wk6TfrAyRssC65vf_FRvl3yfLQXtGUFdCo,20870
|
|
33
33
|
cognite/neat/_data_model/exporters/__init__.py,sha256=AskjmB_0Vqib4kN84bWt8-M8nO42QypFf-l-E8oA5W8,482
|
|
34
34
|
cognite/neat/_data_model/exporters/_api_exporter.py,sha256=nBDHx9dGbaje0T4IEQv0Kulk2Yu7FkPXgXK_MgLbE50,4948
|
|
35
35
|
cognite/neat/_data_model/exporters/_base.py,sha256=rG_qAU5i5Hh5hUMep2UmDFFZID4x3LEenL6Z5C6N8GQ,646
|
|
@@ -59,10 +59,10 @@ cognite/neat/_data_model/models/dms/_constraints.py,sha256=cyGgDlByXAuSMWJg7Oc25
|
|
|
59
59
|
cognite/neat/_data_model/models/dms/_container.py,sha256=wtQbNUwtpymltT1jav8wD4kIfjaIYnvhhz1KS0ffAbo,6044
|
|
60
60
|
cognite/neat/_data_model/models/dms/_data_model.py,sha256=tq_JGNN-1JxG46bhBhunZiLedklYbDXFEfINB0x3a3Q,3219
|
|
61
61
|
cognite/neat/_data_model/models/dms/_data_types.py,sha256=FMt_d5aJD-o3s9VQWyyCVlHk7D_p3RlSNXBP1OACPs4,6424
|
|
62
|
-
cognite/neat/_data_model/models/dms/_http.py,sha256=
|
|
62
|
+
cognite/neat/_data_model/models/dms/_http.py,sha256=FxOWb0qDKOc7urVXp8J0xl8gRV_psHWwfQLyAS8sLeM,1074
|
|
63
63
|
cognite/neat/_data_model/models/dms/_indexes.py,sha256=ZtXe8ABuRcsAwRIZ9FCanS3uwZHpkOAhvDvjSXtx_Fs,900
|
|
64
64
|
cognite/neat/_data_model/models/dms/_limits.py,sha256=-vwRutprJ7rPXLleSxCh_satR9AqRAvEMig5wSVBEXg,3596
|
|
65
|
-
cognite/neat/_data_model/models/dms/_references.py,sha256=
|
|
65
|
+
cognite/neat/_data_model/models/dms/_references.py,sha256=2l9ZD4ZCj-gzc0QB-rV4iVm8-fsnczziEOn2mZTaEfE,4934
|
|
66
66
|
cognite/neat/_data_model/models/dms/_schema.py,sha256=2JFLcm52smzPdtZ69Lf02UbYAD8I_hpRbI7ZAzdxJJs,641
|
|
67
67
|
cognite/neat/_data_model/models/dms/_space.py,sha256=mj6gID4vcAGsHNtgfXm4_4FMOQbUOkMd3HaYEdy07XM,1895
|
|
68
68
|
cognite/neat/_data_model/models/dms/_types.py,sha256=5-cgC53AG186OZUqkltv7pMjcGNLuH7Etbn8IUcgk1c,447
|
|
@@ -333,9 +333,9 @@ cognite/neat/_v0/session/_template.py,sha256=BNcvrW5y7LWzRM1XFxZkfR1Nc7e8UgjBClH
|
|
|
333
333
|
cognite/neat/_v0/session/_to.py,sha256=AnsRSDDdfFyYwSgi0Z-904X7WdLtPfLlR0x1xsu_jAo,19447
|
|
334
334
|
cognite/neat/_v0/session/_wizard.py,sha256=baPJgXAAF3d1bn4nbIzon1gWfJOeS5T43UXRDJEnD3c,1490
|
|
335
335
|
cognite/neat/_v0/session/exceptions.py,sha256=jv52D-SjxGfgqaHR8vnpzo0SOJETIuwbyffSWAxSDJw,3495
|
|
336
|
-
cognite/neat/_version.py,sha256=
|
|
336
|
+
cognite/neat/_version.py,sha256=1SKg9QyerZ0e2dpVZc97ky2WseNfvIsmQKsSm-Ot5NM,45
|
|
337
337
|
cognite/neat/legacy.py,sha256=DMFeLCSBLT2enk-nm1KfX1rKR2DQDpxY-w6ThY0y9c8,421
|
|
338
338
|
cognite/neat/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
339
|
-
cognite_neat-1.0.
|
|
340
|
-
cognite_neat-1.0.
|
|
341
|
-
cognite_neat-1.0.
|
|
339
|
+
cognite_neat-1.0.33.dist-info/WHEEL,sha256=e_m4S054HL0hyR3CpOk-b7Q7fDX6BuFkgL5OjAExXas,80
|
|
340
|
+
cognite_neat-1.0.33.dist-info/METADATA,sha256=2xWjKg7ErSy3X3GJbvybZB952bXdMJPT5ETumyMEahw,6872
|
|
341
|
+
cognite_neat-1.0.33.dist-info/RECORD,,
|
|
File without changes
|