cognite-neat 0.88.2__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.

Files changed (129) hide show
  1. cognite/neat/_version.py +1 -1
  2. cognite/neat/constants.py +3 -0
  3. cognite/neat/graph/__init__.py +0 -3
  4. cognite/neat/graph/extractors/_mock_graph_generator.py +2 -1
  5. cognite/neat/graph/loaders/_base.py +3 -3
  6. cognite/neat/graph/loaders/_rdf2asset.py +24 -25
  7. cognite/neat/graph/loaders/_rdf2dms.py +20 -15
  8. cognite/neat/issues/__init__.py +1 -3
  9. cognite/neat/issues/_base.py +261 -71
  10. cognite/neat/issues/errors/__init__.py +73 -0
  11. cognite/neat/issues/errors/_external.py +67 -0
  12. cognite/neat/issues/errors/_general.py +35 -0
  13. cognite/neat/issues/errors/_properties.py +62 -0
  14. cognite/neat/issues/errors/_resources.py +111 -0
  15. cognite/neat/issues/errors/_workflow.py +36 -0
  16. cognite/neat/issues/formatters.py +1 -1
  17. cognite/neat/issues/warnings/__init__.py +66 -0
  18. cognite/neat/issues/warnings/_external.py +40 -0
  19. cognite/neat/issues/warnings/_general.py +29 -0
  20. cognite/neat/issues/warnings/_models.py +92 -0
  21. cognite/neat/issues/warnings/_properties.py +44 -0
  22. cognite/neat/issues/warnings/_resources.py +55 -0
  23. cognite/neat/issues/warnings/user_modeling.py +113 -0
  24. cognite/neat/rules/_shared.py +53 -2
  25. cognite/neat/rules/analysis/_base.py +1 -1
  26. cognite/neat/rules/exporters/_base.py +7 -18
  27. cognite/neat/rules/exporters/_rules2dms.py +17 -20
  28. cognite/neat/rules/exporters/_rules2excel.py +9 -16
  29. cognite/neat/rules/exporters/_rules2ontology.py +77 -64
  30. cognite/neat/rules/exporters/_rules2yaml.py +6 -9
  31. cognite/neat/rules/exporters/_validation.py +11 -96
  32. cognite/neat/rules/importers/_base.py +9 -58
  33. cognite/neat/rules/importers/_dms2rules.py +188 -135
  34. cognite/neat/rules/importers/_dtdl2rules/dtdl_converter.py +48 -35
  35. cognite/neat/rules/importers/_dtdl2rules/dtdl_importer.py +36 -45
  36. cognite/neat/rules/importers/_dtdl2rules/spec.py +7 -0
  37. cognite/neat/rules/importers/_rdf/_imf2rules/_imf2classes.py +8 -4
  38. cognite/neat/rules/importers/_rdf/_imf2rules/_imf2metadata.py +3 -3
  39. cognite/neat/rules/importers/_rdf/_imf2rules/_imf2properties.py +18 -11
  40. cognite/neat/rules/importers/_rdf/_imf2rules/_imf2rules.py +12 -19
  41. cognite/neat/rules/importers/_rdf/_inference2rules.py +14 -37
  42. cognite/neat/rules/importers/_rdf/_owl2rules/_owl2classes.py +1 -0
  43. cognite/neat/rules/importers/_rdf/_owl2rules/_owl2properties.py +1 -0
  44. cognite/neat/rules/importers/_rdf/_owl2rules/_owl2rules.py +9 -20
  45. cognite/neat/rules/importers/_rdf/_shared.py +4 -4
  46. cognite/neat/rules/importers/_spreadsheet2rules.py +46 -97
  47. cognite/neat/rules/importers/_yaml2rules.py +32 -58
  48. cognite/neat/rules/models/__init__.py +21 -5
  49. cognite/neat/rules/models/_base_input.py +162 -0
  50. cognite/neat/rules/models/{_base.py → _base_rules.py} +1 -12
  51. cognite/neat/rules/models/_rdfpath.py +4 -4
  52. cognite/neat/rules/models/{_types/_field.py → _types.py} +5 -10
  53. cognite/neat/rules/models/asset/__init__.py +5 -2
  54. cognite/neat/rules/models/asset/_rules.py +3 -23
  55. cognite/neat/rules/models/asset/_rules_input.py +40 -115
  56. cognite/neat/rules/models/asset/_validation.py +14 -10
  57. cognite/neat/rules/models/data_types.py +150 -44
  58. cognite/neat/rules/models/dms/__init__.py +19 -7
  59. cognite/neat/rules/models/dms/_exporter.py +102 -34
  60. cognite/neat/rules/models/dms/_rules.py +65 -162
  61. cognite/neat/rules/models/dms/_rules_input.py +186 -254
  62. cognite/neat/rules/models/dms/_schema.py +87 -78
  63. cognite/neat/rules/models/dms/_serializer.py +44 -3
  64. cognite/neat/rules/models/dms/_validation.py +106 -68
  65. cognite/neat/rules/models/domain.py +52 -1
  66. cognite/neat/rules/models/entities/__init__.py +63 -0
  67. cognite/neat/rules/models/entities/_constants.py +73 -0
  68. cognite/neat/rules/models/entities/_loaders.py +76 -0
  69. cognite/neat/rules/models/entities/_multi_value.py +67 -0
  70. cognite/neat/rules/models/{entities.py → entities/_single_value.py} +74 -232
  71. cognite/neat/rules/models/entities/_types.py +86 -0
  72. cognite/neat/rules/models/{wrapped_entities.py → entities/_wrapped.py} +1 -1
  73. cognite/neat/rules/models/information/__init__.py +10 -2
  74. cognite/neat/rules/models/information/_rules.py +10 -22
  75. cognite/neat/rules/models/information/_rules_input.py +57 -204
  76. cognite/neat/rules/models/information/_validation.py +48 -25
  77. cognite/neat/rules/transformers/__init__.py +21 -0
  78. cognite/neat/rules/transformers/_base.py +81 -0
  79. cognite/neat/rules/{models/information/_converter.py → transformers/_converters.py} +217 -21
  80. cognite/neat/rules/transformers/_map_onto.py +97 -0
  81. cognite/neat/rules/transformers/_pipelines.py +61 -0
  82. cognite/neat/rules/transformers/_verification.py +136 -0
  83. cognite/neat/{graph/stores → store}/_provenance.py +10 -1
  84. cognite/neat/utils/auxiliary.py +2 -35
  85. cognite/neat/utils/cdf/data_classes.py +20 -0
  86. cognite/neat/utils/regex_patterns.py +6 -0
  87. cognite/neat/utils/text.py +17 -0
  88. cognite/neat/workflows/base.py +4 -4
  89. cognite/neat/workflows/cdf_store.py +3 -3
  90. cognite/neat/workflows/steps/data_contracts.py +1 -1
  91. cognite/neat/workflows/steps/lib/current/graph_extractor.py +3 -3
  92. cognite/neat/workflows/steps/lib/current/graph_loader.py +2 -2
  93. cognite/neat/workflows/steps/lib/current/graph_store.py +1 -1
  94. cognite/neat/workflows/steps/lib/current/rules_exporter.py +116 -47
  95. cognite/neat/workflows/steps/lib/current/rules_importer.py +30 -28
  96. cognite/neat/workflows/steps/lib/current/rules_validator.py +5 -6
  97. cognite/neat/workflows/steps/lib/io/io_steps.py +5 -5
  98. cognite/neat/workflows/steps_registry.py +4 -5
  99. {cognite_neat-0.88.2.dist-info → cognite_neat-0.89.0.dist-info}/METADATA +1 -1
  100. {cognite_neat-0.88.2.dist-info → cognite_neat-0.89.0.dist-info}/RECORD +105 -106
  101. cognite/neat/exceptions.py +0 -145
  102. cognite/neat/graph/exceptions.py +0 -90
  103. cognite/neat/issues/errors/external.py +0 -21
  104. cognite/neat/issues/errors/properties.py +0 -75
  105. cognite/neat/issues/errors/resources.py +0 -123
  106. cognite/neat/issues/errors/schema.py +0 -0
  107. cognite/neat/issues/neat_warnings/__init__.py +0 -2
  108. cognite/neat/issues/neat_warnings/identifier.py +0 -27
  109. cognite/neat/issues/neat_warnings/models.py +0 -22
  110. cognite/neat/issues/neat_warnings/properties.py +0 -77
  111. cognite/neat/issues/neat_warnings/resources.py +0 -125
  112. cognite/neat/rules/issues/__init__.py +0 -22
  113. cognite/neat/rules/issues/base.py +0 -63
  114. cognite/neat/rules/issues/dms.py +0 -549
  115. cognite/neat/rules/issues/fileread.py +0 -197
  116. cognite/neat/rules/issues/ontology.py +0 -298
  117. cognite/neat/rules/issues/spreadsheet.py +0 -563
  118. cognite/neat/rules/issues/spreadsheet_file.py +0 -151
  119. cognite/neat/rules/issues/tables.py +0 -72
  120. cognite/neat/rules/models/_constants.py +0 -1
  121. cognite/neat/rules/models/_types/__init__.py +0 -19
  122. cognite/neat/rules/models/asset/_converter.py +0 -4
  123. cognite/neat/rules/models/dms/_converter.py +0 -145
  124. cognite/neat/workflows/_exceptions.py +0 -41
  125. /cognite/neat/{graph/stores → store}/__init__.py +0 -0
  126. /cognite/neat/{graph/stores → store}/_base.py +0 -0
  127. {cognite_neat-0.88.2.dist-info → cognite_neat-0.89.0.dist-info}/LICENSE +0 -0
  128. {cognite_neat-0.88.2.dist-info → cognite_neat-0.89.0.dist-info}/WHEEL +0 -0
  129. {cognite_neat-0.88.2.dist-info → cognite_neat-0.89.0.dist-info}/entry_points.txt +0 -0
@@ -1,549 +0,0 @@
1
- from abc import ABC
2
- from dataclasses import dataclass
3
- from typing import Any, ClassVar
4
-
5
- from cognite.client.data_classes import data_modeling as dm
6
-
7
- from .base import NeatValidationError, ValidationWarning
8
-
9
- __all__ = [
10
- "DMSSchemaError",
11
- "DMSSchemaWarning",
12
- "IncompleteSchemaError",
13
- "DirectRelationMissingSourceWarning",
14
- "ViewModelVersionNotMatchingWarning",
15
- "ViewModelSpaceNotMatchingWarning",
16
- "ViewMapsToTooManyContainersWarning",
17
- "DuplicatedViewInDataModelError",
18
- "ContainerPropertyUsedMultipleTimesError",
19
- "EmptyContainerWarning",
20
- "UnsupportedConnectionWarning",
21
- "MultipleReferenceWarning",
22
- "HasDataFilterOnNoPropertiesViewWarning",
23
- "HasDataFilterAppliedToTooManyContainersWarning",
24
- "ReverseRelationMissingOtherSideWarning",
25
- "NodeTypeFilterOnParentViewWarning",
26
- "MissingViewInModelWarning",
27
- "ViewSizeWarning",
28
- "ChangingContainerError",
29
- "ChangingViewError",
30
- ]
31
-
32
-
33
- @dataclass(frozen=True)
34
- class DMSSchemaError(NeatValidationError, ABC): ...
35
-
36
-
37
- @dataclass(frozen=True)
38
- class DMSSchemaWarning(ValidationWarning, ABC): ...
39
-
40
-
41
- @dataclass(frozen=True)
42
- class ViewSizeWarning(DMSSchemaWarning):
43
- description = (
44
- "The number of properties in the {view} view is {count} which is more than "
45
- "the recommended limit of {limit} properties. This can lead to performance issues."
46
- )
47
- fix = "Reduce the size of the view"
48
- error_name: ClassVar[str] = "ViewSizeWarning"
49
-
50
- view_id: dm.ViewId
51
- limit: int
52
- count: int
53
-
54
- def message(self) -> str:
55
- return self.description.format(view=repr(self.view_id), count=self.count, limit=self.limit)
56
-
57
- def dump(self) -> dict[str, Any]:
58
- output = super().dump()
59
- output["view_id"] = self.view_id.dump()
60
- output["limit"] = self.limit
61
- output["count"] = self.count
62
- return output
63
-
64
-
65
- @dataclass(frozen=True)
66
- class IncompleteSchemaError(DMSSchemaError):
67
- description = "This error is raised when the schema is claimed to be complete but missing some components"
68
- fix = "Either provide the missing components or change the schema to partial"
69
- missing_component: dm.ContainerId | dm.ViewId
70
-
71
- def message(self) -> str:
72
- return (
73
- "The data model schema is set to be complete, however, "
74
- f"the referred component {self.missing_component} is not preset."
75
- )
76
-
77
- def dump(self) -> dict[str, Any]:
78
- output = super().dump()
79
- output["missing_component"] = self.missing_component
80
- return output
81
-
82
-
83
- @dataclass(frozen=True)
84
- class DuplicatedViewInDataModelError(DMSSchemaError):
85
- description = "The view is duplicated in the DataModel"
86
- fix = "Remove the duplicated view"
87
- error_name: ClassVar[str] = "DuplicatedViewInDataModel"
88
- referred_by: dm.DataModelId
89
- view: dm.ViewId
90
-
91
- def message(self) -> str:
92
- return f"The view {self.view} is duplicated in the DataModel {self.referred_by}"
93
-
94
- def dump(self) -> dict[str, Any]:
95
- output = super().dump()
96
- output["referred_by"] = self.referred_by
97
- output["view"] = self.view
98
- return output
99
-
100
-
101
- @dataclass(frozen=True)
102
- class DirectRelationMissingSourceWarning(DMSSchemaWarning):
103
- description = "The source view referred to by the DirectRelation does not exist"
104
- fix = "Create the source view"
105
- error_name: ClassVar[str] = "DirectRelationMissingSource"
106
- view_id: dm.ViewId
107
- property: str
108
-
109
- def message(self) -> str:
110
- return f"The source view referred to by '{self.view_id.external_id}.{self.property}' does not exist."
111
-
112
- def dump(self) -> dict[str, Any]:
113
- output = super().dump()
114
- output["view_id"] = self.view_id
115
- output["property"] = self.property
116
- return output
117
-
118
-
119
- @dataclass(frozen=True)
120
- class ViewModelVersionNotMatchingWarning(DMSSchemaWarning):
121
- description = "The view model version does not match the data model version"
122
- fix = "Update the view model version to match the data model version"
123
- error_name: ClassVar[str] = "ViewModelVersionNotMatching"
124
- view_ids: list[dm.ViewId]
125
- data_model_version: str
126
-
127
- def message(self) -> str:
128
- return (
129
- f"The version in the views {self.view_ids} does not match the version in the data model "
130
- f"{self.data_model_version}. This is not recommended as it easily leads to confusion and errors. "
131
- f"Views are very cheap and we recommend you update the version of the views to match the data"
132
- f" model version, irrespective of whether the views have changed or not."
133
- " The approach of having same version of model components as the model itself "
134
- " is a globally recognized data modeling practice."
135
- )
136
-
137
- def dump(self) -> dict[str, Any]:
138
- output = super().dump()
139
- output["view_id"] = [view_id.dump() for view_id in self.view_ids]
140
- output["data_model_version"] = self.data_model_version
141
- return output
142
-
143
-
144
- @dataclass(frozen=True)
145
- class ViewModelSpaceNotMatchingWarning(DMSSchemaWarning):
146
- description = "The view model space does not match the data model space"
147
- fix = "Update the view model space to match the data model space"
148
- error_name: ClassVar[str] = "ViewModelSpaceNotMatching"
149
- view_ids: list[dm.ViewId]
150
- data_model_space: str
151
-
152
- def message(self) -> str:
153
- return (
154
- f"The space in the views {self.view_ids} does not match the space in the data model "
155
- f"{self.data_model_space}. This is not recommended as it easily leads to confusion and errors. "
156
- f"Views are very cheap and we recommend you always have views in the same space as the data model."
157
- )
158
-
159
- def dump(self) -> dict[str, Any]:
160
- output = super().dump()
161
- output["view_id"] = [view_id.dump() for view_id in self.view_ids]
162
- output["data_model_space"] = self.data_model_space
163
- return output
164
-
165
-
166
- @dataclass(frozen=True)
167
- class ViewMapsToTooManyContainersWarning(DMSSchemaWarning):
168
- description = "The view maps to more than 10 containers which impacts read/write performance of data model"
169
- fix = "Try to have as few containers as possible to which the view maps to"
170
- error_name: ClassVar[str] = "ViewMapsToTooManyContainers"
171
- view_id: dm.ViewId
172
- container_ids: set[dm.ContainerId]
173
-
174
- def message(self) -> str:
175
- return (
176
- f"The view {self.view_id} maps to total of {len(self.container_ids)},."
177
- "Mapping to more than 10 containers is not recommended and can lead to poor performances."
178
- "Re-iterate the data model design to reduce the number of containers to which the view maps to."
179
- )
180
-
181
- def dump(self) -> dict[str, Any]:
182
- output = super().dump()
183
- output["view_id"] = self.view_id.dump()
184
- output["container_ids"] = [container_id.dump() for container_id in self.container_ids]
185
- return output
186
-
187
-
188
- @dataclass(frozen=True)
189
- class MissingViewInModelWarning(DMSSchemaWarning):
190
- description = "The data model contains view pointing to views not present in the data model"
191
- fix = "Add the view(s) to the data model"
192
- error_name: ClassVar[str] = "MissingViewInModel"
193
- data_model_id: dm.DataModelId
194
- view_ids: set[dm.ViewId]
195
-
196
- def message(self) -> str:
197
- return f"The view(s) {self.view_ids} are missing in the data model {self.data_model_id}"
198
-
199
- def dump(self) -> dict[str, Any]:
200
- output = super().dump()
201
- output["data_model_id"] = self.data_model_id.dump()
202
- output["view_id"] = [view_id.dump() for view_id in self.view_ids]
203
- return output
204
-
205
-
206
- @dataclass(frozen=True)
207
- class ContainerPropertyUsedMultipleTimesError(DMSSchemaError):
208
- description = "The container property is used multiple times by the same view property"
209
- fix = "Use unique container properties for when mapping to the same container"
210
- error_name: ClassVar[str] = "ContainerPropertyUsedMultipleTimes"
211
- container: dm.ContainerId
212
- property: str
213
- referred_by: frozenset[tuple[dm.ViewId, str]]
214
-
215
- def message(self) -> str:
216
- return (
217
- f"The container property {self.property} of {self.container} is used multiple times "
218
- f"by the same view {self.referred_by}"
219
- )
220
-
221
- def dump(self) -> dict[str, Any]:
222
- output = super().dump()
223
- output["container"] = self.container
224
- output["property"] = self.property
225
- output["referred_by"] = sorted(self.referred_by)
226
- return output
227
-
228
-
229
- @dataclass(frozen=True)
230
- class ChangingContainerError(DMSSchemaError):
231
- description = "You are adding to an existing model. "
232
- fix = "Keep the container the same"
233
- error_name: ClassVar[str] = "ChangingContainerError"
234
- container_id: dm.ContainerId
235
- changed_properties: list[str] | None = None
236
- changed_attributes: list[str] | None = None
237
-
238
- def __post_init__(self):
239
- # Sorting for deterministic output
240
- if self.changed_properties:
241
- self.changed_properties.sort()
242
- if self.changed_attributes:
243
- self.changed_attributes.sort()
244
-
245
- def message(self) -> str:
246
- if self.changed_properties:
247
- changed = f" properties {self.changed_properties}."
248
- elif self.changed_attributes:
249
- changed = f" attributes {self.changed_attributes}."
250
- else:
251
- changed = "."
252
- return (
253
- f"The container {self.container_id} has changed{changed}"
254
- "When extending model with extension set to addition or reshape, the container "
255
- "properties must remain the same"
256
- )
257
-
258
- def dump(self) -> dict[str, Any]:
259
- output = super().dump()
260
- output["container_id"] = self.container_id.dump()
261
- output["changed_properties"] = self.changed_properties
262
- return output
263
-
264
-
265
- @dataclass(frozen=True)
266
- class ChangingViewError(DMSSchemaError):
267
- description = "You are adding to an existing model. "
268
- fix = "Keep the view the same"
269
- error_name: ClassVar[str] = "ChangingViewError"
270
- view_id: dm.ViewId
271
- changed_properties: list[str] | None = None
272
- changed_attributes: list[str] | None = None
273
-
274
- def __post_init__(self):
275
- # Sorting for deterministic output
276
- if self.changed_properties:
277
- self.changed_properties.sort()
278
- if self.changed_attributes:
279
- self.changed_attributes.sort()
280
-
281
- def message(self) -> str:
282
- if self.changed_properties:
283
- changed = f" properties {self.changed_properties}."
284
- elif self.changed_attributes:
285
- changed = f" attributes {self.changed_attributes}."
286
- else:
287
- changed = "."
288
-
289
- return (
290
- f"The view {self.view_id} has changed{changed}"
291
- "When extending model with extension set to addition, the view properties must remain the same"
292
- )
293
-
294
- def dump(self) -> dict[str, Any]:
295
- output = super().dump()
296
- output["view_id"] = self.view_id.dump()
297
- output["difference"] = self.changed_properties
298
- return output
299
-
300
-
301
- @dataclass(frozen=True)
302
- class EntityIDNotDMSCompliantWarning(DMSSchemaWarning):
303
- description = "The entity ID, {entity_id} of type {entity_type}, is not DMS compliant. Violating regex {regex}"
304
- fix = "Change the entity ID to be DMS compliant"
305
- error_name: ClassVar[str] = "EntityIDNotDMSCompliantWarning"
306
- entity_id: str
307
- entity_type: str
308
- regex: str
309
-
310
- def message(self) -> str:
311
- return self.description.format(entity_id=self.entity_id, entity_type=self.entity_type, regex=self.regex)
312
-
313
- def dump(self) -> dict[str, Any]:
314
- output = super().dump()
315
- output["entity_id"] = self.entity_id
316
- output["dms_type"] = self.entity_type
317
- output["regex"] = self.regex
318
- return output
319
-
320
-
321
- @dataclass(frozen=True)
322
- class EmptyContainerWarning(DMSSchemaWarning):
323
- description = "The container is empty"
324
- fix = "Add data to the container"
325
- error_name: ClassVar[str] = "EmptyContainerWarning"
326
- container_id: dm.ContainerId
327
-
328
- def message(self) -> str:
329
- return (
330
- f"The container {self.container_id} is empty. Is this intended? Skipping this container "
331
- "in the data model."
332
- )
333
-
334
- def dump(self) -> dict[str, Any]:
335
- output = super().dump()
336
- output["container_id"] = self.container_id.dump()
337
- return output
338
-
339
-
340
- @dataclass(frozen=True)
341
- class UnsupportedConnectionWarning(DMSSchemaWarning):
342
- description = "The connection type is not supported by neat"
343
- fix = "Change the connection to a supported type"
344
- error_name: ClassVar[str] = "UnsupportedConnectionWarning"
345
- view_id: dm.ViewId
346
- property: str
347
- connection: str
348
-
349
- def message(self) -> str:
350
- return (
351
- f"The connection {self.connection} in {self.view_id}.{self.property} is not supported."
352
- "This property will be ignored."
353
- )
354
-
355
- def dump(self) -> dict[str, Any]:
356
- output = super().dump()
357
- output["view_id"] = self.view_id.dump()
358
- output["property"] = self.property
359
- output["connection"] = self.connection
360
- return output
361
-
362
-
363
- @dataclass(frozen=True)
364
- class ReverseRelationMissingOtherSideWarning(DMSSchemaWarning):
365
- description = "The relation is missing the other side"
366
- fix = "Add the other side of the relation"
367
- error_name: ClassVar[str] = "ReverseRelationMissingOtherSideWarning"
368
- view_id: dm.ViewId
369
- property: str
370
-
371
- def message(self) -> str:
372
- return f"The reverse relation specified in {self.view_id}.{self.property} is missing the other side."
373
-
374
- def dump(self) -> dict[str, Any]:
375
- output = super().dump()
376
- output["view_id"] = self.view_id.dump()
377
- output["property"] = self.property
378
- return output
379
-
380
-
381
- @dataclass(frozen=True)
382
- class MultipleReferenceWarning(DMSSchemaWarning):
383
- description = "The view is implements multiple views from other spaces"
384
- fix = "Neat expects maximum one implementation of a view from another space"
385
- error_name: ClassVar[str] = "MultipleReferenceWarning"
386
- view_id: dm.ViewId
387
- implements: list[dm.ViewId]
388
-
389
- def message(self) -> str:
390
- return f"The view {self.view_id} implements multiple views from other spaces: {self.implements}. " + self.fix
391
-
392
- def dump(self) -> dict[str, Any]:
393
- output = super().dump()
394
- output["view_id"] = self.view_id.dump()
395
- output["implements"] = [view.dump() for view in self.implements]
396
- return output
397
-
398
-
399
- @dataclass(frozen=True)
400
- class HasDataFilterOnNoPropertiesViewWarning(DMSSchemaWarning):
401
- description = "Attempting to set a HasData filter on a view without properties."
402
- fix = "Add properties to the view or use a node type filter"
403
- error_name: ClassVar[str] = "HasDataFilterOnNoPropertiesViewWarning"
404
- view_id: dm.ViewId
405
-
406
- def message(self) -> str:
407
- return (
408
- f"Cannot set hasData filter on view {self.view_id} as it does not have properties in any containers. "
409
- "Using a node type filter instead."
410
- )
411
-
412
- def dump(self) -> dict[str, Any]:
413
- output = super().dump()
414
- output["view_id"] = self.view_id.dump()
415
- return output
416
-
417
-
418
- @dataclass(frozen=True)
419
- class HasDataFilterAppliedToTooManyContainersWarning(DMSSchemaWarning):
420
- description = "The view filter hasData applied to more than 10 containers this will cause DMS API Error"
421
- fix = "Do not map to more than 10 containers, alternatively override the filter by using rawFilter"
422
- error_name: ClassVar[str] = "HasDataFilterAppliedToTooManyContainers"
423
- view_id: dm.ViewId
424
- container_ids: set[dm.ContainerId]
425
-
426
- def message(self) -> str:
427
- return (
428
- f"The view {self.view_id} HasData filter applied to total of {len(self.container_ids)},."
429
- "Applying HasData filter to more than 10 containers is not recommended and can lead to DMS API error."
430
- "Re-iterate the data model design to reduce the number of containers to which the view maps to."
431
- )
432
-
433
- def dump(self) -> dict[str, Any]:
434
- output = super().dump()
435
- output["view_id"] = self.view_id.dump()
436
- output["container_ids"] = [container_id.dump() for container_id in self.container_ids]
437
- return output
438
-
439
-
440
- @dataclass(frozen=True)
441
- class RawFilterAppliedToViewWarning(DMSSchemaWarning):
442
- description = "Raw filter is applied to a view, which is against the neat data modeling lifecycle."
443
- fix = "Do not use raw filter, instead use HasData filter or nodeType filter or change the data model design."
444
- error_name: ClassVar[str] = "RawFilterAppliedToView"
445
- view_id: dm.ViewId
446
-
447
- def message(self) -> str:
448
- return (
449
- f"RawFilter applied to the view {self.view_id}."
450
- " The usage of RawFilter is against the neat team recommendations and the neat data modeling lifecycle."
451
- " When opting for raw filter, the user is responsible for any errors that arise in neat."
452
- )
453
-
454
- def dump(self) -> dict[str, Any]:
455
- output = super().dump()
456
- output["view_id"] = self.view_id.dump()
457
- return output
458
-
459
-
460
- @dataclass(frozen=True)
461
- class NodeTypeFilterOnParentViewWarning(DMSSchemaWarning):
462
- description = (
463
- "Setting a node type filter on a parent view. This is not "
464
- "recommended as parent views are typically used for multiple type of nodes."
465
- )
466
- fix = "Use a HasData filter instead"
467
- error_name: ClassVar[str] = "NodeTypeFilterOnParentViewWarning"
468
- view_id: dm.ViewId
469
-
470
- def message(self) -> str:
471
- return (
472
- f"Setting a node type filter on parent view {self.view_id}. This is not recommended as "
473
- "parent views are typically used for multiple types of nodes."
474
- )
475
-
476
- def dump(self) -> dict[str, Any]:
477
- output = super().dump()
478
- output["view_id"] = self.view_id.dump()
479
- return output
480
-
481
-
482
- @dataclass(frozen=True)
483
- class HasDataFilterOnViewWithReferencesWarning(DMSSchemaWarning):
484
- description = (
485
- "Setting a hasData filter on a solution view which reference other containers is not recommended."
486
- "This will lead to no nodes being returned when querying the solution view."
487
- )
488
- fix = "Use a node type filter instead"
489
- error_name: ClassVar[str] = "HasDataFilterOnReferencedViewWarning"
490
-
491
- view_id: dm.ViewId
492
- references: list[dm.ViewId]
493
-
494
- def message(self) -> str:
495
- return (
496
- f"Setting a hasData filter on view {self.view_id} which references other views {self.references}. "
497
- "This is not recommended as it will lead to no nodes being returned when querying the solution view."
498
- )
499
-
500
- def dump(self) -> dict[str, Any]:
501
- output = super().dump()
502
- output["view_id"] = self.view_id.dump()
503
- output["references"] = [view.dump() for view in sorted(self.references, key=lambda x: x.as_tuple())]
504
- return output
505
-
506
-
507
- @dataclass(frozen=True)
508
- class OtherDataModelsInSpaceWarning(DMSSchemaWarning):
509
- description = "The space contains other data models"
510
- fix = "Move the data models to their respective spaces."
511
- error_name: ClassVar[str] = "OtherDataModelsInSpaceWarning"
512
- space: str
513
- data_models: list[dm.DataModelId]
514
-
515
- def message(self) -> str:
516
- return (
517
- f"The space {self.space} contains data models from other spaces: {self.data_models}. {self.fix}"
518
- " It is recommended to only have one data model per space. This avoid potential conflicts and "
519
- "makes it easier to manage the data models."
520
- )
521
-
522
- def dump(self) -> dict[str, Any]:
523
- output = super().dump()
524
- output["space"] = self.space
525
- output["data_models"] = [data_model.dump() for data_model in self.data_models]
526
- return output
527
-
528
-
529
- @dataclass(frozen=True)
530
- class SolutionOnTopOfSolutionModelWarning(DMSSchemaWarning):
531
- description = "The data model is a solution on top of another solution"
532
- fix = "Use the base solution as the data model"
533
- error_name: ClassVar[str] = "SolutionOnTopOfSolutionModelWarning"
534
- data_model: dm.DataModelId
535
- base_data_model: dm.DataModelId
536
-
537
- def message(self) -> str:
538
- return (
539
- f"The data model {self.data_model} is a solution model on top of another solution {self.base_data_model} "
540
- "model. This is not recommended as it can lead to confusion and errors. It is very hard to "
541
- "maintain a nested structure of solution models. Instead, only build solution models on "
542
- "top of enterprise models."
543
- )
544
-
545
- def dump(self) -> dict[str, Any]:
546
- output = super().dump()
547
- output["data_model"] = self.data_model.dump()
548
- output["base_data_model"] = self.base_data_model.dump()
549
- return output