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.
- cognite/neat/_version.py +1 -1
- cognite/neat/constants.py +3 -0
- cognite/neat/graph/__init__.py +0 -3
- cognite/neat/graph/extractors/_mock_graph_generator.py +2 -1
- cognite/neat/graph/loaders/_base.py +3 -3
- cognite/neat/graph/loaders/_rdf2asset.py +24 -25
- cognite/neat/graph/loaders/_rdf2dms.py +20 -15
- cognite/neat/issues/__init__.py +1 -3
- cognite/neat/issues/_base.py +261 -71
- cognite/neat/issues/errors/__init__.py +73 -0
- cognite/neat/issues/errors/_external.py +67 -0
- cognite/neat/issues/errors/_general.py +35 -0
- cognite/neat/issues/errors/_properties.py +62 -0
- cognite/neat/issues/errors/_resources.py +111 -0
- cognite/neat/issues/errors/_workflow.py +36 -0
- cognite/neat/issues/formatters.py +1 -1
- cognite/neat/issues/warnings/__init__.py +66 -0
- cognite/neat/issues/warnings/_external.py +40 -0
- cognite/neat/issues/warnings/_general.py +29 -0
- cognite/neat/issues/warnings/_models.py +92 -0
- cognite/neat/issues/warnings/_properties.py +44 -0
- cognite/neat/issues/warnings/_resources.py +55 -0
- cognite/neat/issues/warnings/user_modeling.py +113 -0
- cognite/neat/rules/_shared.py +53 -2
- cognite/neat/rules/analysis/_base.py +1 -1
- cognite/neat/rules/exporters/_base.py +7 -18
- cognite/neat/rules/exporters/_rules2dms.py +17 -20
- cognite/neat/rules/exporters/_rules2excel.py +9 -16
- cognite/neat/rules/exporters/_rules2ontology.py +77 -64
- cognite/neat/rules/exporters/_rules2yaml.py +6 -9
- cognite/neat/rules/exporters/_validation.py +11 -96
- cognite/neat/rules/importers/_base.py +9 -58
- cognite/neat/rules/importers/_dms2rules.py +188 -135
- cognite/neat/rules/importers/_dtdl2rules/dtdl_converter.py +48 -35
- cognite/neat/rules/importers/_dtdl2rules/dtdl_importer.py +36 -45
- cognite/neat/rules/importers/_dtdl2rules/spec.py +7 -0
- cognite/neat/rules/importers/_rdf/_imf2rules/_imf2classes.py +8 -4
- cognite/neat/rules/importers/_rdf/_imf2rules/_imf2metadata.py +3 -3
- cognite/neat/rules/importers/_rdf/_imf2rules/_imf2properties.py +18 -11
- cognite/neat/rules/importers/_rdf/_imf2rules/_imf2rules.py +12 -19
- cognite/neat/rules/importers/_rdf/_inference2rules.py +14 -37
- cognite/neat/rules/importers/_rdf/_owl2rules/_owl2classes.py +1 -0
- cognite/neat/rules/importers/_rdf/_owl2rules/_owl2properties.py +1 -0
- cognite/neat/rules/importers/_rdf/_owl2rules/_owl2rules.py +9 -20
- cognite/neat/rules/importers/_rdf/_shared.py +4 -4
- cognite/neat/rules/importers/_spreadsheet2rules.py +46 -97
- cognite/neat/rules/importers/_yaml2rules.py +32 -58
- cognite/neat/rules/models/__init__.py +21 -5
- cognite/neat/rules/models/_base_input.py +162 -0
- cognite/neat/rules/models/{_base.py → _base_rules.py} +1 -12
- cognite/neat/rules/models/_rdfpath.py +4 -4
- cognite/neat/rules/models/{_types/_field.py → _types.py} +5 -10
- cognite/neat/rules/models/asset/__init__.py +5 -2
- cognite/neat/rules/models/asset/_rules.py +3 -23
- cognite/neat/rules/models/asset/_rules_input.py +40 -115
- cognite/neat/rules/models/asset/_validation.py +14 -10
- cognite/neat/rules/models/data_types.py +150 -44
- cognite/neat/rules/models/dms/__init__.py +19 -7
- cognite/neat/rules/models/dms/_exporter.py +102 -34
- cognite/neat/rules/models/dms/_rules.py +65 -162
- cognite/neat/rules/models/dms/_rules_input.py +186 -254
- cognite/neat/rules/models/dms/_schema.py +87 -78
- cognite/neat/rules/models/dms/_serializer.py +44 -3
- cognite/neat/rules/models/dms/_validation.py +106 -68
- cognite/neat/rules/models/domain.py +52 -1
- cognite/neat/rules/models/entities/__init__.py +63 -0
- cognite/neat/rules/models/entities/_constants.py +73 -0
- cognite/neat/rules/models/entities/_loaders.py +76 -0
- cognite/neat/rules/models/entities/_multi_value.py +67 -0
- cognite/neat/rules/models/{entities.py → entities/_single_value.py} +74 -232
- cognite/neat/rules/models/entities/_types.py +86 -0
- cognite/neat/rules/models/{wrapped_entities.py → entities/_wrapped.py} +1 -1
- cognite/neat/rules/models/information/__init__.py +10 -2
- cognite/neat/rules/models/information/_rules.py +10 -22
- cognite/neat/rules/models/information/_rules_input.py +57 -204
- cognite/neat/rules/models/information/_validation.py +48 -25
- cognite/neat/rules/transformers/__init__.py +21 -0
- cognite/neat/rules/transformers/_base.py +81 -0
- cognite/neat/rules/{models/information/_converter.py → transformers/_converters.py} +217 -21
- cognite/neat/rules/transformers/_map_onto.py +97 -0
- cognite/neat/rules/transformers/_pipelines.py +61 -0
- cognite/neat/rules/transformers/_verification.py +136 -0
- cognite/neat/{graph/stores → store}/_provenance.py +10 -1
- cognite/neat/utils/auxiliary.py +2 -35
- cognite/neat/utils/cdf/data_classes.py +20 -0
- cognite/neat/utils/regex_patterns.py +6 -0
- cognite/neat/utils/text.py +17 -0
- cognite/neat/workflows/base.py +4 -4
- cognite/neat/workflows/cdf_store.py +3 -3
- cognite/neat/workflows/steps/data_contracts.py +1 -1
- cognite/neat/workflows/steps/lib/current/graph_extractor.py +3 -3
- cognite/neat/workflows/steps/lib/current/graph_loader.py +2 -2
- cognite/neat/workflows/steps/lib/current/graph_store.py +1 -1
- cognite/neat/workflows/steps/lib/current/rules_exporter.py +116 -47
- cognite/neat/workflows/steps/lib/current/rules_importer.py +30 -28
- cognite/neat/workflows/steps/lib/current/rules_validator.py +5 -6
- cognite/neat/workflows/steps/lib/io/io_steps.py +5 -5
- cognite/neat/workflows/steps_registry.py +4 -5
- {cognite_neat-0.88.2.dist-info → cognite_neat-0.89.0.dist-info}/METADATA +1 -1
- {cognite_neat-0.88.2.dist-info → cognite_neat-0.89.0.dist-info}/RECORD +105 -106
- cognite/neat/exceptions.py +0 -145
- cognite/neat/graph/exceptions.py +0 -90
- cognite/neat/issues/errors/external.py +0 -21
- cognite/neat/issues/errors/properties.py +0 -75
- cognite/neat/issues/errors/resources.py +0 -123
- cognite/neat/issues/errors/schema.py +0 -0
- cognite/neat/issues/neat_warnings/__init__.py +0 -2
- cognite/neat/issues/neat_warnings/identifier.py +0 -27
- cognite/neat/issues/neat_warnings/models.py +0 -22
- cognite/neat/issues/neat_warnings/properties.py +0 -77
- cognite/neat/issues/neat_warnings/resources.py +0 -125
- cognite/neat/rules/issues/__init__.py +0 -22
- cognite/neat/rules/issues/base.py +0 -63
- cognite/neat/rules/issues/dms.py +0 -549
- cognite/neat/rules/issues/fileread.py +0 -197
- cognite/neat/rules/issues/ontology.py +0 -298
- cognite/neat/rules/issues/spreadsheet.py +0 -563
- cognite/neat/rules/issues/spreadsheet_file.py +0 -151
- cognite/neat/rules/issues/tables.py +0 -72
- cognite/neat/rules/models/_constants.py +0 -1
- cognite/neat/rules/models/_types/__init__.py +0 -19
- cognite/neat/rules/models/asset/_converter.py +0 -4
- cognite/neat/rules/models/dms/_converter.py +0 -145
- cognite/neat/workflows/_exceptions.py +0 -41
- /cognite/neat/{graph/stores → store}/__init__.py +0 -0
- /cognite/neat/{graph/stores → store}/_base.py +0 -0
- {cognite_neat-0.88.2.dist-info → cognite_neat-0.89.0.dist-info}/LICENSE +0 -0
- {cognite_neat-0.88.2.dist-info → cognite_neat-0.89.0.dist-info}/WHEEL +0 -0
- {cognite_neat-0.88.2.dist-info → cognite_neat-0.89.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Generic
|
|
3
|
+
|
|
4
|
+
from cognite.neat.issues._base import ResourceType
|
|
5
|
+
|
|
6
|
+
from ._resources import ResourceError, T_Identifier, T_ReferenceIdentifier
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass(frozen=True)
|
|
10
|
+
class PropertyError(ResourceError[T_Identifier]):
|
|
11
|
+
"""Base class for property errors {resource_type} with identifier {identifier}.{property_name}"""
|
|
12
|
+
|
|
13
|
+
property_name: str
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True)
|
|
17
|
+
class PropertyNotFoundError(PropertyError, Generic[T_Identifier, T_ReferenceIdentifier]):
|
|
18
|
+
"""The {resource_type} with identifier {identifier} does not have a property {property_name}"""
|
|
19
|
+
|
|
20
|
+
extra = "referred to by {referred_type} {referred_by} does not exist"
|
|
21
|
+
fix = "Ensure the {resource_type} {identifier} has a {property_name} property"
|
|
22
|
+
|
|
23
|
+
referred_by: T_ReferenceIdentifier | None = None
|
|
24
|
+
referred_type: ResourceType | None = None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass(frozen=True)
|
|
28
|
+
class PropertyTypeNotSupportedError(PropertyError[T_Identifier]):
|
|
29
|
+
"""The {resource_type} with identifier {identifier} has a property {property_name}
|
|
30
|
+
of unsupported type {property_type}"""
|
|
31
|
+
|
|
32
|
+
property_type: str
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# This is a generic error that should be used sparingly
|
|
36
|
+
@dataclass(frozen=True)
|
|
37
|
+
class PropertyDefinitionError(PropertyError[T_Identifier]):
|
|
38
|
+
"""Invalid property definition for {resource_type} {identifier}.{property_name}: {reason}"""
|
|
39
|
+
|
|
40
|
+
reason: str
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass(frozen=True)
|
|
44
|
+
class PropertyDefinitionDuplicatedError(PropertyError[T_Identifier]):
|
|
45
|
+
"""The {resource_type} with identifier {identifier} has multiple definitions for the property {property_name}
|
|
46
|
+
with values {property_values}
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
extra = "in locations {locations} with name {location_name}"
|
|
50
|
+
|
|
51
|
+
property_values: frozenset[str | int | float | bool | None | tuple[str | int | float | bool | None, ...]]
|
|
52
|
+
locations: tuple[str | int, ...] | None = None
|
|
53
|
+
location_name: str | None = None
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass(frozen=True)
|
|
57
|
+
class PropertyMappingDuplicatedError(PropertyError[T_Identifier], Generic[T_Identifier, T_ReferenceIdentifier]):
|
|
58
|
+
"""The {resource_type} with identifier {identifier}.{property_name} is mapped to by: {mappings}. Ensure
|
|
59
|
+
that only one {mapping_type} maps to {resource_type} {identifier}.{property_name}"""
|
|
60
|
+
|
|
61
|
+
mappings: frozenset[T_ReferenceIdentifier]
|
|
62
|
+
mapping_type: ResourceType
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Generic
|
|
3
|
+
|
|
4
|
+
from cognite.neat.issues._base import NeatError, ResourceType, T_Identifier, T_ReferenceIdentifier
|
|
5
|
+
from cognite.neat.utils.text import humanize_collection
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass(frozen=True)
|
|
9
|
+
class ResourceError(NeatError, Generic[T_Identifier], RuntimeError):
|
|
10
|
+
"""Base class for resource errors {resource_type} with identifier {identifier}"""
|
|
11
|
+
|
|
12
|
+
identifier: T_Identifier
|
|
13
|
+
resource_type: ResourceType
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True)
|
|
17
|
+
class ResourceDuplicatedError(ResourceError[T_Identifier]):
|
|
18
|
+
"""The {resource_type} with identifier {identifier} is duplicated in {location}"""
|
|
19
|
+
|
|
20
|
+
fix = "Remove the duplicate {resource_type} {identifier}."
|
|
21
|
+
location: str
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True)
|
|
25
|
+
class ResourceRetrievalError(ResourceError[T_Identifier]):
|
|
26
|
+
"""Failed to retrieve {resource_type} with identifier {identifier}. The error was: {error}"""
|
|
27
|
+
|
|
28
|
+
error: str
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass(frozen=True)
|
|
32
|
+
class ResourceNotFoundError(ResourceError, Generic[T_Identifier, T_ReferenceIdentifier]):
|
|
33
|
+
"""The {resource_type} with identifier {identifier} does not exist"""
|
|
34
|
+
|
|
35
|
+
extra = " This is expected by {referred_type} {referred_by}."
|
|
36
|
+
|
|
37
|
+
fix = "Create the {resource_type} {identifier}"
|
|
38
|
+
|
|
39
|
+
referred_by: T_ReferenceIdentifier | None = None
|
|
40
|
+
referred_type: ResourceType | None = None
|
|
41
|
+
more: str | None = None
|
|
42
|
+
|
|
43
|
+
def as_message(self) -> str:
|
|
44
|
+
msg = (self.__doc__ or "").format(resource_type=self.resource_type, identifier=self.identifier)
|
|
45
|
+
if self.referred_by and self.referred_type:
|
|
46
|
+
msg += self.extra.format(referred_type=self.referred_type, referred_by=self.referred_by)
|
|
47
|
+
if self.more:
|
|
48
|
+
msg += f" {self.more}"
|
|
49
|
+
msg += f" Fix {self.fix.format(resource_type=self.resource_type, identifier=self.identifier)}"
|
|
50
|
+
return msg
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass(frozen=True)
|
|
54
|
+
class ResourceNotDefinedError(ResourceError[T_Identifier]):
|
|
55
|
+
"""The {resource_type} {identifier} is not defined in the {location}"""
|
|
56
|
+
|
|
57
|
+
extra = "{column_name} {row_number} in {sheet_name}"
|
|
58
|
+
fix = "Define the {resource_type} {identifier} in {location}."
|
|
59
|
+
|
|
60
|
+
location: str
|
|
61
|
+
column_name: str | None = None
|
|
62
|
+
row_number: int | None = None
|
|
63
|
+
sheet_name: str | None = None
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@dataclass(frozen=True)
|
|
67
|
+
class ResourceConvertionError(ResourceError, ValueError):
|
|
68
|
+
"""Failed to convert the {resource_type} {identifier} to {target_format}: {reason}"""
|
|
69
|
+
|
|
70
|
+
fix = "Check the error message and correct the rules."
|
|
71
|
+
target_format: str
|
|
72
|
+
reason: str
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@dataclass(frozen=True)
|
|
76
|
+
class ResourceCreationError(ResourceError[T_Identifier], ValueError):
|
|
77
|
+
"""Failed to create {resource_type} with identifier {identifier}. The error was: {error}"""
|
|
78
|
+
|
|
79
|
+
error: str
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@dataclass(frozen=True)
|
|
83
|
+
class ResourceMissingIdentifierError(NeatError, ValueError):
|
|
84
|
+
"""The {resource_type} with name {name} is missing an identifier."""
|
|
85
|
+
|
|
86
|
+
resource_type: ResourceType
|
|
87
|
+
name: str | None = None
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@dataclass(frozen=True)
|
|
91
|
+
class ResourceChangedError(ResourceError[T_Identifier]):
|
|
92
|
+
"""The {resource_type} with identifier {identifier} has changed{changed}"""
|
|
93
|
+
|
|
94
|
+
fix = (
|
|
95
|
+
"When extending model with extension set to addition or reshape, "
|
|
96
|
+
"the {resource_type} properties must remain the same"
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
changed_properties: frozenset[str]
|
|
100
|
+
changed_attributes: frozenset[str]
|
|
101
|
+
|
|
102
|
+
def as_message(self) -> str:
|
|
103
|
+
if self.changed_properties:
|
|
104
|
+
changed = f" properties {humanize_collection(self.changed_properties)}."
|
|
105
|
+
elif self.changed_attributes:
|
|
106
|
+
changed = f" attributes {humanize_collection(self.changed_attributes)}."
|
|
107
|
+
else:
|
|
108
|
+
changed = "."
|
|
109
|
+
msg = (self.__doc__ or "").format(resource_type=self.resource_type, identifier=self.identifier, changed=changed)
|
|
110
|
+
msg += f"Fix {self.fix.format(resource_type=self.resource_type)}"
|
|
111
|
+
return msg
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from cognite.neat.issues import NeatError
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@dataclass(frozen=True)
|
|
7
|
+
class WorkFlowMissingDataError(NeatError, ValueError):
|
|
8
|
+
"""In the workflow step {step_name} the following data is missing: {missing_data}."""
|
|
9
|
+
|
|
10
|
+
step_name: str
|
|
11
|
+
missing_data: frozenset[str]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class WorkflowStepNotInitializedError(NeatError, RuntimeError):
|
|
16
|
+
"""Step {step_name} has not been initialized."""
|
|
17
|
+
|
|
18
|
+
step_name: str
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass(frozen=True)
|
|
22
|
+
class WorkflowConfigurationNotSetError(NeatError, RuntimeError):
|
|
23
|
+
"""The configuration variable '{config_variable}' is not set. Please set the configuration
|
|
24
|
+
before running the workflow."""
|
|
25
|
+
|
|
26
|
+
config_variable: str
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass(frozen=True)
|
|
30
|
+
class WorkflowStepOutputError(NeatError, RuntimeError):
|
|
31
|
+
"""Object type {step_type} is not supported as step output.
|
|
32
|
+
|
|
33
|
+
Step output must be of type DataContract or a FlowMessage.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
step_type: str
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""All warnings raised by the neat package are defined here. Note this module is called 'warnings' which
|
|
2
|
+
conflicts with the built-in Python warnings module. However, it is expected to always be used in an absolute
|
|
3
|
+
import, and should thus not cause a naming conflict."""
|
|
4
|
+
|
|
5
|
+
from cognite.neat.issues._base import DefaultWarning, NeatWarning, _get_subclasses
|
|
6
|
+
|
|
7
|
+
from . import user_modeling
|
|
8
|
+
from ._external import (
|
|
9
|
+
FileItemNotSupportedWarning,
|
|
10
|
+
FileMissingRequiredFieldWarning,
|
|
11
|
+
FileReadWarning,
|
|
12
|
+
FileTypeUnexpectedWarning,
|
|
13
|
+
)
|
|
14
|
+
from ._general import NeatValueWarning, NotSupportedWarning, RegexViolationWarning
|
|
15
|
+
from ._models import (
|
|
16
|
+
BreakingModelingPrincipleWarning,
|
|
17
|
+
CDFNotSupportedWarning,
|
|
18
|
+
NotSupportedHasDataFilterLimitWarning,
|
|
19
|
+
NotSupportedViewContainerLimitWarning,
|
|
20
|
+
PrincipleMatchingSpaceAndVersionWarning,
|
|
21
|
+
PrincipleOneModelOneSpaceWarning,
|
|
22
|
+
PrincipleSolutionBuildsOnEnterpriseWarning,
|
|
23
|
+
UserModelingWarning,
|
|
24
|
+
)
|
|
25
|
+
from ._properties import (
|
|
26
|
+
PropertyDefinitionDuplicatedWarning,
|
|
27
|
+
PropertyNotFoundWarning,
|
|
28
|
+
PropertyTypeNotSupportedWarning,
|
|
29
|
+
)
|
|
30
|
+
from ._resources import (
|
|
31
|
+
ResourceNeatWarning,
|
|
32
|
+
ResourceNotFoundWarning,
|
|
33
|
+
ResourceRetrievalWarning,
|
|
34
|
+
ResourcesDuplicatedWarning,
|
|
35
|
+
ResourceTypeNotSupportedWarning,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
__all__ = [
|
|
39
|
+
"DefaultWarning",
|
|
40
|
+
"FileReadWarning",
|
|
41
|
+
"FileMissingRequiredFieldWarning",
|
|
42
|
+
"FileItemNotSupportedWarning",
|
|
43
|
+
"FileTypeUnexpectedWarning",
|
|
44
|
+
"NeatValueWarning",
|
|
45
|
+
"NotSupportedWarning",
|
|
46
|
+
"UserModelingWarning",
|
|
47
|
+
"CDFNotSupportedWarning",
|
|
48
|
+
"BreakingModelingPrincipleWarning",
|
|
49
|
+
"PropertyDefinitionDuplicatedWarning",
|
|
50
|
+
"PropertyTypeNotSupportedWarning",
|
|
51
|
+
"PropertyNotFoundWarning",
|
|
52
|
+
"ResourceNeatWarning",
|
|
53
|
+
"ResourcesDuplicatedWarning",
|
|
54
|
+
"RegexViolationWarning",
|
|
55
|
+
"ResourceNotFoundWarning",
|
|
56
|
+
"ResourceTypeNotSupportedWarning",
|
|
57
|
+
"ResourceRetrievalWarning",
|
|
58
|
+
"PrincipleOneModelOneSpaceWarning",
|
|
59
|
+
"PrincipleMatchingSpaceAndVersionWarning",
|
|
60
|
+
"PrincipleSolutionBuildsOnEnterpriseWarning",
|
|
61
|
+
"NotSupportedViewContainerLimitWarning",
|
|
62
|
+
"NotSupportedHasDataFilterLimitWarning",
|
|
63
|
+
"user_modeling",
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
_NEAT_WARNINGS_BY_NAME = {warning.__name__: warning for warning in _get_subclasses(NeatWarning, include_base=True)}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from cognite.neat.issues import NeatWarning
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass(frozen=True)
|
|
8
|
+
class FileReadWarning(NeatWarning):
|
|
9
|
+
"""Error when reading file, {filepath}: {reason}"""
|
|
10
|
+
|
|
11
|
+
filepath: Path
|
|
12
|
+
reason: str
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass(frozen=True)
|
|
16
|
+
class FileMissingRequiredFieldWarning(NeatWarning):
|
|
17
|
+
"""Missing required {field_name} in {filepath}: {field}. The file will be skipped"""
|
|
18
|
+
|
|
19
|
+
filepath: Path
|
|
20
|
+
field_name: str
|
|
21
|
+
field: str
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True)
|
|
25
|
+
class FileTypeUnexpectedWarning(NeatWarning):
|
|
26
|
+
"""Unexpected file type: {filepath}. Expected format: {expected_format}"""
|
|
27
|
+
|
|
28
|
+
extra = "Error: {error_message}"
|
|
29
|
+
|
|
30
|
+
filepath: Path
|
|
31
|
+
expected_format: frozenset[str]
|
|
32
|
+
error_message: str | None = None
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass(frozen=True)
|
|
36
|
+
class FileItemNotSupportedWarning(NeatWarning):
|
|
37
|
+
"""The item {item} in {filepath} is not supported. The item will be skipped"""
|
|
38
|
+
|
|
39
|
+
item: str
|
|
40
|
+
filepath: Path
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from cognite.neat.issues import NeatWarning
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@dataclass(frozen=True)
|
|
7
|
+
class NeatValueWarning(NeatWarning):
|
|
8
|
+
"""{value}"""
|
|
9
|
+
|
|
10
|
+
value: str
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True)
|
|
14
|
+
class NotSupportedWarning(NeatWarning):
|
|
15
|
+
"""{feature} is not supported"""
|
|
16
|
+
|
|
17
|
+
feature: str
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass(frozen=True)
|
|
21
|
+
class RegexViolationWarning(NeatWarning):
|
|
22
|
+
"""The value '{value}' of {identifier} does not match the {pattern_name} pattern '{pattern}'"""
|
|
23
|
+
|
|
24
|
+
extra = "{motivation}"
|
|
25
|
+
value: str
|
|
26
|
+
pattern: str
|
|
27
|
+
identifier: str
|
|
28
|
+
pattern_name: str
|
|
29
|
+
motivation: str | None = None
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
from abc import ABC
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from typing import ClassVar
|
|
4
|
+
|
|
5
|
+
from cognite.client.data_classes.data_modeling import ViewId
|
|
6
|
+
|
|
7
|
+
from cognite.neat.constants import DMS_VIEW_CONTAINER_SIZE_LIMIT
|
|
8
|
+
from cognite.neat.issues import NeatWarning
|
|
9
|
+
|
|
10
|
+
_BASE_URL = "https://cognite-neat.readthedocs-hosted.com/en/latest/data-modeling-principles.html"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True)
|
|
14
|
+
class BreakingModelingPrincipleWarning(NeatWarning, ABC):
|
|
15
|
+
"""{warning_class}: {specific} violates the {principle} principle.
|
|
16
|
+
See {url} for more information."""
|
|
17
|
+
|
|
18
|
+
url: ClassVar[str]
|
|
19
|
+
specific: str
|
|
20
|
+
|
|
21
|
+
def as_message(self) -> str:
|
|
22
|
+
principle = type(self).__name__.removesuffix("Warning")
|
|
23
|
+
url = f"{_BASE_URL}#{self.url}"
|
|
24
|
+
return (self.__doc__ or "").format(
|
|
25
|
+
warning_class=BreakingModelingPrincipleWarning.__name__,
|
|
26
|
+
specific=self.specific,
|
|
27
|
+
principle=principle,
|
|
28
|
+
url=url,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass(frozen=True)
|
|
33
|
+
class PrincipleOneModelOneSpaceWarning(BreakingModelingPrincipleWarning):
|
|
34
|
+
"""{warning_class}: {specific} violates the {principle} principle.
|
|
35
|
+
See {url} for more information."""
|
|
36
|
+
|
|
37
|
+
url = "all-data-models-are-kept-in-its-own-space"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass(frozen=True)
|
|
41
|
+
class PrincipleMatchingSpaceAndVersionWarning(BreakingModelingPrincipleWarning):
|
|
42
|
+
"""{warning_class}: {specific} violates the {principle} principle.
|
|
43
|
+
See {url} for more information."""
|
|
44
|
+
|
|
45
|
+
url = "all-views-of-a-data-models-have-the-same-version-and-space-as-the-data-model"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass(frozen=True)
|
|
49
|
+
class PrincipleSolutionBuildsOnEnterpriseWarning(BreakingModelingPrincipleWarning):
|
|
50
|
+
"""{warning_class}: {specific} violates the {principle} principle.
|
|
51
|
+
See {url} for more information."""
|
|
52
|
+
|
|
53
|
+
url = "solution-data-models-should-always-be-referencing-the-enterprise-data-model"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass(frozen=True)
|
|
57
|
+
class UserModelingWarning(NeatWarning, ABC):
|
|
58
|
+
"""This is a generic warning for user modeling issues.
|
|
59
|
+
These warnings will not cause the resulting model to be invalid, but
|
|
60
|
+
will likely lead to suboptimal performance, unnecessary complexity, or other issues."""
|
|
61
|
+
|
|
62
|
+
...
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@dataclass(frozen=True)
|
|
66
|
+
class CDFNotSupportedWarning(NeatWarning, ABC):
|
|
67
|
+
"""This is a base class for warnings for modeling issues that will
|
|
68
|
+
likely lead to the CDF API rejecting the model."""
|
|
69
|
+
|
|
70
|
+
...
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@dataclass(frozen=True)
|
|
74
|
+
class NotSupportedViewContainerLimitWarning(CDFNotSupportedWarning):
|
|
75
|
+
"""The view {view_id} maps, {count} containers, which is more than the limit {limit}."""
|
|
76
|
+
|
|
77
|
+
fix = "Reduce the number of containers the view maps to." ""
|
|
78
|
+
|
|
79
|
+
view_id: ViewId
|
|
80
|
+
count: int
|
|
81
|
+
limit: int = DMS_VIEW_CONTAINER_SIZE_LIMIT
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@dataclass(frozen=True)
|
|
85
|
+
class NotSupportedHasDataFilterLimitWarning(CDFNotSupportedWarning):
|
|
86
|
+
"""The view {view_id} uses a hasData filter applied to {count} containers, which is more than the limit {limit}."""
|
|
87
|
+
|
|
88
|
+
fix = "Do not map to more than {limit} containers."
|
|
89
|
+
|
|
90
|
+
view_id: ViewId
|
|
91
|
+
count: int
|
|
92
|
+
limit: int = DMS_VIEW_CONTAINER_SIZE_LIMIT
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Generic
|
|
3
|
+
|
|
4
|
+
from cognite.neat.issues._base import ResourceType
|
|
5
|
+
|
|
6
|
+
from ._resources import ResourceNeatWarning, T_Identifier, T_ReferenceIdentifier
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass(frozen=True)
|
|
10
|
+
class PropertyWarning(ResourceNeatWarning[T_Identifier]):
|
|
11
|
+
"""Base class for property warnings {resource_type} with identifier {identifier}.{property_name}"""
|
|
12
|
+
|
|
13
|
+
property_name: str
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True)
|
|
17
|
+
class PropertyTypeNotSupportedWarning(PropertyWarning[T_Identifier]):
|
|
18
|
+
"""The {resource_type} with identifier {identifier} has a property {property_name}
|
|
19
|
+
of unsupported type {property_type}. This will be ignored."""
|
|
20
|
+
|
|
21
|
+
property_type: str
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True)
|
|
25
|
+
class PropertyNotFoundWarning(PropertyWarning, Generic[T_Identifier, T_ReferenceIdentifier]):
|
|
26
|
+
"""The {resource_type} with identifier {identifier} does not have a property {property_name} referred
|
|
27
|
+
to by {referred_type} {referred_by} does not exist. This will be ignored.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
fix = "Ensure the {resource_type} {identifier} has a {property_name} property"
|
|
31
|
+
referred_by: T_ReferenceIdentifier
|
|
32
|
+
referred_type: ResourceType
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass(frozen=True)
|
|
36
|
+
class PropertyDefinitionDuplicatedWarning(PropertyWarning[T_Identifier]):
|
|
37
|
+
"""Got multiple values for the {resource_type} {identifier}.{property_name} {values}.
|
|
38
|
+
{default_action}"""
|
|
39
|
+
|
|
40
|
+
extra = "Recommended action: {recommended_action}"
|
|
41
|
+
|
|
42
|
+
values: frozenset[str]
|
|
43
|
+
default_action: str
|
|
44
|
+
recommended_action: str | None = None
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Generic
|
|
3
|
+
|
|
4
|
+
from cognite.neat.issues._base import NeatWarning, ResourceType, T_Identifier, T_ReferenceIdentifier
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# Name ResourceNeatWarning to avoid conflicts with the built-in ResourceWarning
|
|
8
|
+
@dataclass(frozen=True)
|
|
9
|
+
class ResourceNeatWarning(NeatWarning, Generic[T_Identifier]):
|
|
10
|
+
"""Base class for resource warnings {resource_type} with identifier {identifier}"""
|
|
11
|
+
|
|
12
|
+
identifier: T_Identifier
|
|
13
|
+
resource_type: ResourceType
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True)
|
|
17
|
+
class ResourceNotFoundWarning(ResourceNeatWarning, Generic[T_Identifier, T_ReferenceIdentifier]):
|
|
18
|
+
"""The {resource_type} with identifier {identifier} referred by {referred_type} {referred_by} does not exist.
|
|
19
|
+
This will be ignored."""
|
|
20
|
+
|
|
21
|
+
fix = "Create the {resource_type}"
|
|
22
|
+
|
|
23
|
+
referred_by: T_ReferenceIdentifier
|
|
24
|
+
referred_type: str
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass(frozen=True)
|
|
28
|
+
class ResourcesDuplicatedWarning(NeatWarning, Generic[T_Identifier]):
|
|
29
|
+
"""Duplicated {resource_type} with identifiers {resources} were found. {default_action}"""
|
|
30
|
+
|
|
31
|
+
fix = "Remove the duplicate resources"
|
|
32
|
+
|
|
33
|
+
resources: frozenset[T_Identifier]
|
|
34
|
+
resource_type: ResourceType
|
|
35
|
+
default_action: str
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass(frozen=True)
|
|
39
|
+
class ResourceRetrievalWarning(NeatWarning, Generic[T_Identifier]):
|
|
40
|
+
"""Failed to retrieve {resource_type} with identifiers {resources}. Continuing without
|
|
41
|
+
these resources."""
|
|
42
|
+
|
|
43
|
+
extra = "The error was: {error}"
|
|
44
|
+
|
|
45
|
+
fix = "Check the error."
|
|
46
|
+
|
|
47
|
+
resources: frozenset[T_Identifier]
|
|
48
|
+
resource_type: ResourceType
|
|
49
|
+
error: str | None = None
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class ResourceTypeNotSupportedWarning(ResourceNeatWarning[T_Identifier]):
|
|
53
|
+
"""The {resource_type} with identifier {identifier} is not supported. This will be ignored."""
|
|
54
|
+
|
|
55
|
+
resource_type: str # type: ignore[assignment]
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""These are user modeling warnings. These warnings will not cause the resulting model
|
|
2
|
+
to be invalid, but will likely lead to suboptimal performance, unnecessary complexity,
|
|
3
|
+
or other issues."""
|
|
4
|
+
# These warnings are usually only used once in the code base.
|
|
5
|
+
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
|
|
8
|
+
from cognite.client.data_classes.data_modeling import ContainerId, ViewId
|
|
9
|
+
|
|
10
|
+
from cognite.neat.constants import DMS_CONTAINER_PROPERTY_SIZE_LIMIT
|
|
11
|
+
|
|
12
|
+
from ._models import UserModelingWarning
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"DirectRelationMissingSourceWarning",
|
|
16
|
+
"EmptyContainerWarning",
|
|
17
|
+
"HasDataFilterOnNoPropertiesViewWarning",
|
|
18
|
+
"NodeTypeFilterOnParentViewWarning",
|
|
19
|
+
"HasDataFilterOnViewWithReferencesWarning",
|
|
20
|
+
"ViewPropertyLimitWarning",
|
|
21
|
+
"NotNeatSupportedFilterWarning",
|
|
22
|
+
"ParentInDifferentSpaceWarning",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass(frozen=True)
|
|
27
|
+
class DirectRelationMissingSourceWarning(UserModelingWarning):
|
|
28
|
+
"""The view {view_id}.{prop_name} is a direct relation without a source.
|
|
29
|
+
Direct relations in views should point to a single other view, if not, you end up
|
|
30
|
+
with a more complex model than necessary."""
|
|
31
|
+
|
|
32
|
+
fix = "Create the source view"
|
|
33
|
+
|
|
34
|
+
view_id: ViewId
|
|
35
|
+
prop_name: str
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass(frozen=True)
|
|
39
|
+
class ParentInDifferentSpaceWarning(UserModelingWarning):
|
|
40
|
+
"""The view {view_id} has multiple parents in different spaces.
|
|
41
|
+
Neat recommends maximum one implementation of a view from another space."""
|
|
42
|
+
|
|
43
|
+
fix = "Ensure all parents of the view are in the same space"
|
|
44
|
+
|
|
45
|
+
view_id: ViewId
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass(frozen=True)
|
|
49
|
+
class EmptyContainerWarning(UserModelingWarning):
|
|
50
|
+
"""Container {container_id} is empty and will be skipped.
|
|
51
|
+
The container does not have any properties."""
|
|
52
|
+
|
|
53
|
+
fix = "Add properties to the container or remove the container"
|
|
54
|
+
|
|
55
|
+
container_id: ContainerId
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass(frozen=True)
|
|
59
|
+
class HasDataFilterOnNoPropertiesViewWarning(UserModelingWarning):
|
|
60
|
+
"""Cannot set hasData filter on view {view_id}.
|
|
61
|
+
The view does not have properties in any containers.
|
|
62
|
+
Use a node type filter instead."""
|
|
63
|
+
|
|
64
|
+
fix = "Use a node type filter instead"
|
|
65
|
+
|
|
66
|
+
view_id: ViewId
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@dataclass(frozen=True)
|
|
70
|
+
class NodeTypeFilterOnParentViewWarning(UserModelingWarning):
|
|
71
|
+
"""Setting a node type filter on parent view {view_id}.
|
|
72
|
+
This is not recommended as parent views are typically used for multiple types of nodes."""
|
|
73
|
+
|
|
74
|
+
fix = "Use a HasData filter instead"
|
|
75
|
+
|
|
76
|
+
view_id: ViewId
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@dataclass(frozen=True)
|
|
80
|
+
class HasDataFilterOnViewWithReferencesWarning(UserModelingWarning):
|
|
81
|
+
"""Setting a hasData filter on view {view_id} which references other views {references}.
|
|
82
|
+
This is not recommended as it will lead to no nodes being returned when querying the solution view.
|
|
83
|
+
Use a NodeType filter instead."""
|
|
84
|
+
|
|
85
|
+
fix = "Use a NodeType filter instead"
|
|
86
|
+
|
|
87
|
+
view_id: ViewId
|
|
88
|
+
references: frozenset[ViewId]
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@dataclass(frozen=True)
|
|
92
|
+
class ViewPropertyLimitWarning(UserModelingWarning):
|
|
93
|
+
"""The number of properties in the {view_id} view is {count} which
|
|
94
|
+
is more than the API limit {limit} properties.
|
|
95
|
+
This can lead to performance issues.
|
|
96
|
+
Reduce the number of properties in the view."""
|
|
97
|
+
|
|
98
|
+
fix = "Reduce the number of properties in the view"
|
|
99
|
+
|
|
100
|
+
view_id: ViewId
|
|
101
|
+
count: int
|
|
102
|
+
limit: int = DMS_CONTAINER_PROPERTY_SIZE_LIMIT
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@dataclass(frozen=True)
|
|
106
|
+
class NotNeatSupportedFilterWarning(UserModelingWarning):
|
|
107
|
+
"""The view {view_id} uses a non-standard filter.
|
|
108
|
+
This will not be validated by Neat, and is thus not recommended.
|
|
109
|
+
If you can use a HasData or NoteType filter."""
|
|
110
|
+
|
|
111
|
+
fix = "Use a HasData or NoteType filter instead"
|
|
112
|
+
|
|
113
|
+
view_id: ViewId
|