cognite-neat 0.99.0__py3-none-any.whl → 0.100.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 (84) hide show
  1. cognite/neat/_client/_api/data_modeling_loaders.py +390 -116
  2. cognite/neat/_client/_api/schema.py +63 -2
  3. cognite/neat/_client/data_classes/data_modeling.py +4 -0
  4. cognite/neat/_client/data_classes/schema.py +2 -348
  5. cognite/neat/_constants.py +27 -4
  6. cognite/neat/_graph/extractors/_base.py +7 -0
  7. cognite/neat/_graph/extractors/_classic_cdf/_classic.py +28 -18
  8. cognite/neat/_graph/loaders/_rdf2dms.py +52 -13
  9. cognite/neat/_graph/transformers/__init__.py +3 -3
  10. cognite/neat/_graph/transformers/_classic_cdf.py +135 -56
  11. cognite/neat/_issues/_base.py +26 -17
  12. cognite/neat/_issues/errors/__init__.py +4 -2
  13. cognite/neat/_issues/errors/_external.py +7 -0
  14. cognite/neat/_issues/errors/_properties.py +2 -7
  15. cognite/neat/_issues/errors/_resources.py +1 -1
  16. cognite/neat/_issues/warnings/__init__.py +6 -2
  17. cognite/neat/_issues/warnings/_external.py +9 -1
  18. cognite/neat/_issues/warnings/_resources.py +41 -2
  19. cognite/neat/_issues/warnings/user_modeling.py +4 -4
  20. cognite/neat/_rules/_constants.py +2 -6
  21. cognite/neat/_rules/analysis/_base.py +15 -5
  22. cognite/neat/_rules/analysis/_dms.py +20 -0
  23. cognite/neat/_rules/analysis/_information.py +22 -0
  24. cognite/neat/_rules/exporters/_base.py +3 -5
  25. cognite/neat/_rules/exporters/_rules2dms.py +190 -200
  26. cognite/neat/_rules/importers/__init__.py +1 -3
  27. cognite/neat/_rules/importers/_base.py +1 -1
  28. cognite/neat/_rules/importers/_dms2rules.py +3 -25
  29. cognite/neat/_rules/importers/_rdf/__init__.py +5 -0
  30. cognite/neat/_rules/importers/_rdf/_base.py +34 -11
  31. cognite/neat/_rules/importers/_rdf/_imf2rules.py +91 -0
  32. cognite/neat/_rules/importers/_rdf/_inference2rules.py +40 -7
  33. cognite/neat/_rules/importers/_rdf/_owl2rules.py +80 -0
  34. cognite/neat/_rules/importers/_rdf/_shared.py +138 -441
  35. cognite/neat/_rules/models/_base_rules.py +19 -0
  36. cognite/neat/_rules/models/_types.py +5 -0
  37. cognite/neat/_rules/models/dms/__init__.py +2 -0
  38. cognite/neat/_rules/models/dms/_exporter.py +247 -123
  39. cognite/neat/_rules/models/dms/_rules.py +7 -49
  40. cognite/neat/_rules/models/dms/_rules_input.py +8 -3
  41. cognite/neat/_rules/models/dms/_validation.py +421 -123
  42. cognite/neat/_rules/models/entities/_multi_value.py +3 -0
  43. cognite/neat/_rules/models/information/__init__.py +2 -0
  44. cognite/neat/_rules/models/information/_rules.py +17 -61
  45. cognite/neat/_rules/models/information/_rules_input.py +11 -2
  46. cognite/neat/_rules/models/information/_validation.py +107 -11
  47. cognite/neat/_rules/models/mapping/_classic2core.py +1 -1
  48. cognite/neat/_rules/models/mapping/_classic2core.yaml +8 -4
  49. cognite/neat/_rules/transformers/__init__.py +2 -1
  50. cognite/neat/_rules/transformers/_converters.py +163 -61
  51. cognite/neat/_rules/transformers/_mapping.py +132 -2
  52. cognite/neat/_rules/transformers/_pipelines.py +1 -1
  53. cognite/neat/_rules/transformers/_verification.py +29 -4
  54. cognite/neat/_session/_base.py +46 -60
  55. cognite/neat/_session/_mapping.py +105 -5
  56. cognite/neat/_session/_prepare.py +49 -14
  57. cognite/neat/_session/_read.py +50 -4
  58. cognite/neat/_session/_set.py +1 -0
  59. cognite/neat/_session/_to.py +38 -12
  60. cognite/neat/_session/_wizard.py +5 -0
  61. cognite/neat/_session/engine/_interface.py +3 -2
  62. cognite/neat/_session/exceptions.py +4 -0
  63. cognite/neat/_store/_base.py +79 -19
  64. cognite/neat/_utils/collection_.py +22 -0
  65. cognite/neat/_utils/rdf_.py +30 -4
  66. cognite/neat/_version.py +2 -2
  67. cognite/neat/_workflows/steps/lib/current/rules_exporter.py +3 -91
  68. cognite/neat/_workflows/steps/lib/current/rules_importer.py +2 -16
  69. cognite/neat/_workflows/steps/lib/current/rules_validator.py +3 -5
  70. {cognite_neat-0.99.0.dist-info → cognite_neat-0.100.0.dist-info}/METADATA +1 -1
  71. {cognite_neat-0.99.0.dist-info → cognite_neat-0.100.0.dist-info}/RECORD +74 -82
  72. cognite/neat/_rules/importers/_rdf/_imf2rules/__init__.py +0 -3
  73. cognite/neat/_rules/importers/_rdf/_imf2rules/_imf2classes.py +0 -86
  74. cognite/neat/_rules/importers/_rdf/_imf2rules/_imf2metadata.py +0 -29
  75. cognite/neat/_rules/importers/_rdf/_imf2rules/_imf2properties.py +0 -130
  76. cognite/neat/_rules/importers/_rdf/_imf2rules/_imf2rules.py +0 -154
  77. cognite/neat/_rules/importers/_rdf/_owl2rules/__init__.py +0 -3
  78. cognite/neat/_rules/importers/_rdf/_owl2rules/_owl2classes.py +0 -58
  79. cognite/neat/_rules/importers/_rdf/_owl2rules/_owl2metadata.py +0 -65
  80. cognite/neat/_rules/importers/_rdf/_owl2rules/_owl2properties.py +0 -59
  81. cognite/neat/_rules/importers/_rdf/_owl2rules/_owl2rules.py +0 -39
  82. {cognite_neat-0.99.0.dist-info → cognite_neat-0.100.0.dist-info}/LICENSE +0 -0
  83. {cognite_neat-0.99.0.dist-info → cognite_neat-0.100.0.dist-info}/WHEEL +0 -0
  84. {cognite_neat-0.99.0.dist-info → cognite_neat-0.100.0.dist-info}/entry_points.txt +0 -0
@@ -13,6 +13,21 @@ class ResourceNeatWarning(NeatWarning, Generic[T_Identifier]):
13
13
  resource_type: ResourceType
14
14
 
15
15
 
16
+ @dataclass(unsafe_hash=True)
17
+ class ResourceRegexViolationWarning(ResourceNeatWarning):
18
+ """The {resource_type} with identifier {identifier} in the {location} is violating
19
+ the CDF regex {regex}. This will lead to errors when converting to DMS data model.
20
+ """
21
+
22
+ fix = (
23
+ "Either export the data model and make the necessary changes manually"
24
+ " or run prepare.cdf_compliant_external_ids."
25
+ )
26
+
27
+ location: str
28
+ regex: str
29
+
30
+
16
31
  @dataclass(unsafe_hash=True)
17
32
  class ResourceNotFoundWarning(ResourceNeatWarning, Generic[T_Identifier, T_ReferenceIdentifier]):
18
33
  """The {resource_type} with identifier {identifier} referred by {referred_type} {referred_by} does not exist.
@@ -24,6 +39,30 @@ class ResourceNotFoundWarning(ResourceNeatWarning, Generic[T_Identifier, T_Refer
24
39
  referred_type: str
25
40
 
26
41
 
42
+ @dataclass(unsafe_hash=True)
43
+ class ResourceNotDefinedWarning(ResourceNeatWarning, Generic[T_Identifier, T_ReferenceIdentifier]):
44
+ """The {resource_type} {identifier} is not defined in the {location}"""
45
+
46
+ extra = "{column_name} {row_number} in {sheet_name}"
47
+ fix = "Define the {resource_type} {identifier} in {location}."
48
+
49
+ location: str
50
+ column_name: str | None = None
51
+ row_number: int | None = None
52
+ sheet_name: str | None = None
53
+
54
+
55
+ @dataclass(unsafe_hash=True)
56
+ class ResourceRedefinedWarning(ResourceNeatWarning, Generic[T_Identifier, T_ReferenceIdentifier]):
57
+ """The {resource_type} {identifier} feature {feature} is being redefine from {current_value} to {new_value}.
58
+ This will be ignored."""
59
+
60
+ fix = "Avoid redefinition {resource_type} features"
61
+ feature: str
62
+ current_value: str
63
+ new_value: str
64
+
65
+
27
66
  @dataclass(unsafe_hash=True)
28
67
  class ResourcesDuplicatedWarning(NeatWarning, Generic[T_Identifier]):
29
68
  """Duplicated {resource_type} with identifiers {resources} were found. {default_action}"""
@@ -37,12 +76,12 @@ class ResourcesDuplicatedWarning(NeatWarning, Generic[T_Identifier]):
37
76
 
38
77
  @dataclass(unsafe_hash=True)
39
78
  class ResourceRetrievalWarning(NeatWarning, Generic[T_Identifier]):
40
- """Failed to retrieve {resource_type} with identifiers {resources}. Continuing without
79
+ """Failed to retrieve {resource_type} with identifier(s) {resources}. Continuing without
41
80
  these resources."""
42
81
 
43
82
  extra = "The error was: {error}"
44
83
 
45
- fix = "Check the error."
84
+ fix = "Check the error and fix accordingly."
46
85
 
47
86
  resources: frozenset[T_Identifier]
48
87
  resource_type: ResourceType
@@ -17,7 +17,7 @@ __all__ = [
17
17
  "HasDataFilterOnNoPropertiesViewWarning",
18
18
  "NodeTypeFilterOnParentViewWarning",
19
19
  "HasDataFilterOnViewWithReferencesWarning",
20
- "ViewPropertyLimitWarning",
20
+ "ContainerPropertyLimitWarning",
21
21
  "NotNeatSupportedFilterWarning",
22
22
  "ParentInDifferentSpaceWarning",
23
23
  ]
@@ -89,15 +89,15 @@ class HasDataFilterOnViewWithReferencesWarning(UserModelingWarning):
89
89
 
90
90
 
91
91
  @dataclass(unsafe_hash=True)
92
- class ViewPropertyLimitWarning(UserModelingWarning):
93
- """The number of properties in the {view_id} view is {count} which
92
+ class ContainerPropertyLimitWarning(UserModelingWarning):
93
+ """The number of properties in the {container_id} view is {count} which
94
94
  is more than the API limit {limit} properties.
95
95
  This can lead to performance issues.
96
96
  Reduce the number of properties in the view."""
97
97
 
98
98
  fix = "Reduce the number of properties in the view"
99
99
 
100
- view_id: ViewId
100
+ container_id: ContainerId
101
101
  count: int
102
102
  limit: int = DMS_CONTAINER_PROPERTY_SIZE_LIMIT
103
103
 
@@ -106,13 +106,9 @@ VIEW_ID_COMPLIANCE_REGEX = (
106
106
  DMS_PROPERTY_ID_COMPLIANCE_REGEX = (
107
107
  rf"(?!^({'|'.join(get_reserved_words('property'))})$)" r"(^[a-zA-Z][a-zA-Z0-9_]{0,253}[a-zA-Z0-9]?$)"
108
108
  )
109
- CLASS_ID_COMPLIANCE_REGEX = (
110
- rf"(?!^({'|'.join(get_reserved_words('class'))})$)" r"(^[a-zA-Z][a-zA-Z0-9._-]{0,253}[a-zA-Z0-9]?$)"
111
- )
109
+ CLASS_ID_COMPLIANCE_REGEX = rf"(?!^({'|'.join(get_reserved_words('class'))})$)" r"(^[a-zA-Z0-9._-]{0,253}[a-zA-Z0-9]?$)"
112
110
 
113
- INFORMATION_PROPERTY_ID_COMPLIANCE_REGEX = (
114
- r"^(\*)|(?!^(Property|property)$)(^[a-zA-Z][a-zA-Z0-9._-]{0,253}[a-zA-Z0-9]?$)"
115
- )
111
+ INFORMATION_PROPERTY_ID_COMPLIANCE_REGEX = r"^(\*)|(?!^(Property|property)$)(^[a-zA-Z0-9._-]{0,253}[a-zA-Z0-9]?$)"
116
112
  VERSION_COMPLIANCE_REGEX = r"^[a-zA-Z0-9]([.a-zA-Z0-9_-]{0,41}[a-zA-Z0-9])?$"
117
113
 
118
114
 
@@ -4,23 +4,25 @@ from abc import ABC, abstractmethod
4
4
  from collections import defaultdict
5
5
  from collections.abc import Set
6
6
  from dataclasses import dataclass
7
- from typing import Generic, TypeVar
7
+ from typing import Generic, TypeVar, cast
8
8
 
9
9
  import pandas as pd
10
- from pydantic import BaseModel
10
+ from rdflib import URIRef
11
11
 
12
12
  from cognite.neat._rules.models._base_rules import BaseRules
13
13
  from cognite.neat._rules.models._rdfpath import RDFPath
14
+ from cognite.neat._rules.models.dms._rules import DMSProperty, DMSView
14
15
  from cognite.neat._rules.models.entities import (
15
16
  ClassEntity,
16
17
  Entity,
17
18
  )
18
19
  from cognite.neat._rules.models.information import InformationProperty
20
+ from cognite.neat._rules.models.information._rules import InformationClass
19
21
  from cognite.neat._utils.rdf_ import get_inheritance_path
20
22
 
21
23
  T_Rules = TypeVar("T_Rules", bound=BaseRules)
22
- T_Property = TypeVar("T_Property", bound=BaseModel)
23
- T_Class = TypeVar("T_Class", bound=BaseModel)
24
+ T_Property = TypeVar("T_Property", bound=InformationProperty | DMSProperty)
25
+ T_Class = TypeVar("T_Class", bound=InformationClass | DMSView)
24
26
  T_ClassEntity = TypeVar("T_ClassEntity", bound=Entity)
25
27
  T_PropertyEntity = TypeVar("T_PropertyEntity", bound=Entity | str)
26
28
 
@@ -108,6 +110,14 @@ class BaseAnalysis(ABC, Generic[T_Rules, T_Class, T_Property, T_ClassEntity, T_P
108
110
  def inherited_referred_classes(self) -> set[ClassEntity]:
109
111
  raise NotImplementedError
110
112
 
113
+ @property
114
+ def properties_by_neat_id(self) -> dict[URIRef, T_Property]:
115
+ return {cast(URIRef, prop.neatId): prop for prop in self._get_properties()}
116
+
117
+ @property
118
+ def classes_by_neat_id(self) -> dict[URIRef, T_Class]:
119
+ return {cast(URIRef, class_.neatId): class_ for class_ in self._get_classes()}
120
+
111
121
  # Todo Lru cache this method.
112
122
  def class_parent_pairs(self, allow_different_space: bool = False) -> dict[T_ClassEntity, list[T_ClassEntity]]:
113
123
  """This only returns class - parent pairs only if parent is in the same data model"""
@@ -176,7 +186,7 @@ class BaseAnalysis(ABC, Generic[T_Rules, T_Class, T_Property, T_ClassEntity, T_P
176
186
  # ParentClassEntity -> ClassEntity to match the type of class_property_pairs
177
187
  if parent in class_property_pairs:
178
188
  for property_ in class_property_pairs[parent]:
179
- property_ = property_.model_copy()
189
+ property_ = property_.model_copy() # type: ignore
180
190
 
181
191
  # This corresponds to importing properties from parent class
182
192
  # making sure that the property is attached to desired child class
@@ -1,3 +1,7 @@
1
+ from collections import defaultdict
2
+
3
+ from rdflib import URIRef
4
+
1
5
  from cognite.neat._constants import DMS_LISTABLE_PROPERTY_LIMIT
2
6
  from cognite.neat._rules.models.dms import DMSProperty, DMSRules, DMSView
3
7
  from cognite.neat._rules.models.entities import ViewEntity
@@ -35,3 +39,19 @@ class DMSAnalysis(BaseAnalysis[DMSRules, DMSView, DMSProperty, ViewEntity, str])
35
39
 
36
40
  def _get_prop_entity(self, property_: DMSProperty) -> str:
37
41
  return property_.view_property
42
+
43
+ def views_with_properties_linked_to_classes(
44
+ self,
45
+ consider_inheritance: bool = False,
46
+ allow_different_namespace: bool = False,
47
+ ) -> dict[ViewEntity, dict[str, URIRef]]:
48
+ view_property_pairs = self.classes_with_properties(consider_inheritance, allow_different_namespace)
49
+
50
+ view_and_properties_with_links: dict[ViewEntity, dict[str, URIRef]] = defaultdict(dict)
51
+
52
+ for view, properties in view_property_pairs.items():
53
+ view_and_properties_with_links[view] = {
54
+ prop.view_property: prop.logical for prop in properties if prop.logical
55
+ }
56
+
57
+ return view_and_properties_with_links
@@ -101,6 +101,28 @@ class InformationAnalysis(BaseAnalysis[InformationRules, InformationClass, Infor
101
101
 
102
102
  return property_renaming_configuration
103
103
 
104
+ def neat_id_to_transformation_property_uri(self, property_neat_id: URIRef) -> URIRef | None:
105
+ if (
106
+ (property_ := self.properties_by_neat_id.get(property_neat_id))
107
+ and property_.transformation
108
+ and isinstance(
109
+ property_.transformation.traversal,
110
+ SingleProperty,
111
+ )
112
+ and (
113
+ property_.transformation.traversal.property.prefix in self.rules.prefixes
114
+ or property_.transformation.traversal.property.prefix == self.rules.metadata.prefix
115
+ )
116
+ ):
117
+ namespace = (
118
+ self.rules.metadata.namespace
119
+ if property_.transformation.traversal.property.prefix == self.rules.metadata.prefix
120
+ else self.rules.prefixes[property_.transformation.traversal.property.prefix]
121
+ )
122
+
123
+ return namespace[property_.transformation.traversal.property.suffix]
124
+ return None
125
+
104
126
  def property_types(self, class_: ClassEntity) -> dict[str, EntityTypes]:
105
127
  property_types = {}
106
128
  if definitions := self.class_property_pairs(consider_inheritance=True).get(class_, None):
@@ -31,11 +31,9 @@ class BaseExporter(ABC, Generic[T_VerifiedRules, T_Export]):
31
31
  class CDFExporter(BaseExporter[T_VerifiedRules, T_Export]):
32
32
  @abstractmethod
33
33
  def export_to_cdf_iterable(
34
- self, rules: T_VerifiedRules, client: NeatClient, dry_run: bool = False, fallback_one_by_one: bool = False
34
+ self, rules: T_VerifiedRules, client: NeatClient, dry_run: bool = False
35
35
  ) -> Iterable[UploadResult]:
36
36
  raise NotImplementedError
37
37
 
38
- def export_to_cdf(
39
- self, rules: T_VerifiedRules, client: NeatClient, dry_run: bool = False, fallback_one_by_one: bool = False
40
- ) -> UploadResultList:
41
- return UploadResultList(self.export_to_cdf_iterable(rules, client, dry_run, fallback_one_by_one))
38
+ def export_to_cdf(self, rules: T_VerifiedRules, client: NeatClient, dry_run: bool = False) -> UploadResultList:
39
+ return UploadResultList(self.export_to_cdf_iterable(rules, client, dry_run))