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
@@ -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
@@ -75,7 +75,7 @@ class BasicHTML(Formatter):
75
75
  ul = ET.SubElement(self._body, "ul")
76
76
  for issue in issues_in_category:
77
77
  li = ET.SubElement(ul, "li")
78
- li.text = issue.message()
78
+ li.text = issue.as_message()
79
79
 
80
80
 
81
81
  FORMATTER_BY_NAME: dict[str, type[Formatter]] = {
@@ -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