industrial-model 0.1.30__tar.gz → 0.1.32__tar.gz
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.
- {industrial_model-0.1.30 → industrial_model-0.1.32}/PKG-INFO +1 -1
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/cognite_adapters/filter_mapper.py +32 -5
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/cognite_adapters/query_mapper.py +16 -2
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/cognite_adapters/query_result_mapper.py +34 -8
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/models/entities.py +2 -2
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/statements/__init__.py +22 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/pyproject.toml +1 -1
- {industrial_model-0.1.30 → industrial_model-0.1.32}/.gitignore +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/README.md +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/__init__.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/cognite_adapters/__init__.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/cognite_adapters/aggregation_mapper.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/cognite_adapters/models.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/cognite_adapters/optimizer.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/cognite_adapters/search_mapper.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/cognite_adapters/sort_mapper.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/cognite_adapters/upsert_mapper.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/cognite_adapters/utils.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/cognite_adapters/view_mapper.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/config.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/constants.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/engines/__init__.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/engines/async_engine.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/engines/engine.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/models/__init__.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/models/base.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/models/schemas.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/py.typed +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/queries/__init__.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/queries/models.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/queries/params.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/queries/utils.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/statements/expressions.py +0 -0
- {industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/utils.py +0 -0
|
@@ -2,7 +2,11 @@ from datetime import date, datetime
|
|
|
2
2
|
from typing import Any
|
|
3
3
|
|
|
4
4
|
import cognite.client.data_classes.filters as cdf_filters
|
|
5
|
-
from cognite.client.data_classes.data_modeling import
|
|
5
|
+
from cognite.client.data_classes.data_modeling import (
|
|
6
|
+
EdgeConnection,
|
|
7
|
+
MappedProperty,
|
|
8
|
+
View,
|
|
9
|
+
)
|
|
6
10
|
|
|
7
11
|
from industrial_model.cognite_adapters.utils import get_property_ref
|
|
8
12
|
from industrial_model.models.entities import InstanceId
|
|
@@ -11,6 +15,7 @@ from industrial_model.statements import (
|
|
|
11
15
|
Expression,
|
|
12
16
|
LeafExpression,
|
|
13
17
|
)
|
|
18
|
+
from industrial_model.statements.expressions import Column
|
|
14
19
|
from industrial_model.utils import datetime_to_ms_iso_timestamp
|
|
15
20
|
|
|
16
21
|
from .view_mapper import ViewMapper
|
|
@@ -26,15 +31,37 @@ class FilterMapper:
|
|
|
26
31
|
result: list[cdf_filters.Filter] = []
|
|
27
32
|
for expression in expressions:
|
|
28
33
|
if isinstance(expression, BoolExpression):
|
|
29
|
-
result.append(self.
|
|
34
|
+
result.append(self._to_cdf_filter_bool(expression, root_view))
|
|
30
35
|
elif isinstance(expression, LeafExpression):
|
|
31
|
-
result.append(self.
|
|
36
|
+
result.append(self._to_cdf_filter_leaf(expression, root_view))
|
|
32
37
|
else:
|
|
33
38
|
cls_name = expression.__class__.__name__
|
|
34
39
|
raise ValueError(f"Expression not implemented {cls_name}")
|
|
35
40
|
return result
|
|
36
41
|
|
|
37
|
-
def
|
|
42
|
+
def map_edges(
|
|
43
|
+
self,
|
|
44
|
+
edges_expressions: list[tuple[Column, list[Expression]]],
|
|
45
|
+
root_view: View,
|
|
46
|
+
nested_separator: str,
|
|
47
|
+
) -> dict[str, list[cdf_filters.Filter]]:
|
|
48
|
+
result_dict: dict[str, list[cdf_filters.Filter]] = {}
|
|
49
|
+
|
|
50
|
+
for column, expressions in edges_expressions:
|
|
51
|
+
view_property = root_view.properties.get(column.property)
|
|
52
|
+
if not isinstance(view_property, EdgeConnection):
|
|
53
|
+
raise ValueError(f"Property {column.property} is not an edge")
|
|
54
|
+
|
|
55
|
+
filters = self.map(
|
|
56
|
+
expressions,
|
|
57
|
+
self._view_mapper.get_view(view_property.source.external_id),
|
|
58
|
+
)
|
|
59
|
+
result_key = root_view.external_id + nested_separator + column.property
|
|
60
|
+
result_dict.setdefault(result_key, []).extend(filters)
|
|
61
|
+
|
|
62
|
+
return result_dict
|
|
63
|
+
|
|
64
|
+
def _to_cdf_filter_bool(
|
|
38
65
|
self, expression: BoolExpression, root_view: View
|
|
39
66
|
) -> cdf_filters.Filter:
|
|
40
67
|
arguments = self.map(expression.filters, root_view)
|
|
@@ -48,7 +75,7 @@ class FilterMapper:
|
|
|
48
75
|
|
|
49
76
|
raise NotImplementedError(f"Operator {self.operator} not implemented")
|
|
50
77
|
|
|
51
|
-
def
|
|
78
|
+
def _to_cdf_filter_leaf(
|
|
52
79
|
self,
|
|
53
80
|
expression: LeafExpression,
|
|
54
81
|
root_view: View,
|
|
@@ -58,8 +58,12 @@ class QueryMapper:
|
|
|
58
58
|
|
|
59
59
|
relations = get_schema_properties(statement.entity, NESTED_SEP, root_node)
|
|
60
60
|
|
|
61
|
+
edge_filters = self._filter_mapper.map_edges(
|
|
62
|
+
statement.where_edge_clauses, root_view, NESTED_SEP
|
|
63
|
+
)
|
|
64
|
+
|
|
61
65
|
properties = self._include_statements(
|
|
62
|
-
root_node, root_view, relations, with_, select_
|
|
66
|
+
root_node, root_view, relations, edge_filters, with_, select_
|
|
63
67
|
)
|
|
64
68
|
|
|
65
69
|
select_[root_node] = self._get_select(root_view_id, properties)
|
|
@@ -80,6 +84,7 @@ class QueryMapper:
|
|
|
80
84
|
key: str,
|
|
81
85
|
view: View,
|
|
82
86
|
relations_to_include: list[str] | None,
|
|
87
|
+
edge_filters: dict[str, list[filters.Filter]],
|
|
83
88
|
with_: dict[str, ResultSetExpression],
|
|
84
89
|
select_: dict[str, Select],
|
|
85
90
|
) -> list[str]:
|
|
@@ -101,6 +106,7 @@ class QueryMapper:
|
|
|
101
106
|
property_key,
|
|
102
107
|
self._view_mapper.get_view(property.source.external_id),
|
|
103
108
|
relations_to_include,
|
|
109
|
+
edge_filters,
|
|
104
110
|
with_,
|
|
105
111
|
select_,
|
|
106
112
|
)
|
|
@@ -121,6 +127,7 @@ class QueryMapper:
|
|
|
121
127
|
property_key,
|
|
122
128
|
self._view_mapper.get_view(property.source.external_id),
|
|
123
129
|
relations_to_include,
|
|
130
|
+
edge_filters,
|
|
124
131
|
with_,
|
|
125
132
|
select_,
|
|
126
133
|
)
|
|
@@ -139,10 +146,16 @@ class QueryMapper:
|
|
|
139
146
|
elif isinstance(property, EdgeConnection) and property.source:
|
|
140
147
|
edge_property_key = f"{property_key}{NESTED_SEP}{EDGE_MARKER}"
|
|
141
148
|
|
|
149
|
+
edge_filter = edge_filters.get(property_key)
|
|
150
|
+
|
|
142
151
|
with_[edge_property_key] = EdgeResultSetExpression(
|
|
143
152
|
from_=key,
|
|
144
153
|
max_distance=1,
|
|
145
|
-
filter=filters.Equals(
|
|
154
|
+
filter=filters.Equals(
|
|
155
|
+
["edge", "type"],
|
|
156
|
+
property.type.dump(),
|
|
157
|
+
),
|
|
158
|
+
node_filter=filters.And(*edge_filter) if edge_filter else None,
|
|
146
159
|
direction=property.direction,
|
|
147
160
|
limit=MAX_LIMIT,
|
|
148
161
|
)
|
|
@@ -157,6 +170,7 @@ class QueryMapper:
|
|
|
157
170
|
property_key,
|
|
158
171
|
self._view_mapper.get_view(property.source.external_id),
|
|
159
172
|
relations_to_include,
|
|
173
|
+
edge_filters,
|
|
160
174
|
with_,
|
|
161
175
|
select_,
|
|
162
176
|
)
|
|
@@ -10,6 +10,10 @@ from cognite.client.data_classes.data_modeling import (
|
|
|
10
10
|
NodeList,
|
|
11
11
|
View,
|
|
12
12
|
)
|
|
13
|
+
from cognite.client.data_classes.data_modeling.data_types import (
|
|
14
|
+
ListablePropertyType,
|
|
15
|
+
)
|
|
16
|
+
from cognite.client.data_classes.data_modeling.instances import PropertyValue
|
|
13
17
|
from cognite.client.data_classes.data_modeling.views import (
|
|
14
18
|
MultiReverseDirectRelation,
|
|
15
19
|
SingleReverseDirectRelation,
|
|
@@ -112,13 +116,13 @@ class QueryResultMapper:
|
|
|
112
116
|
):
|
|
113
117
|
continue
|
|
114
118
|
|
|
115
|
-
|
|
116
|
-
(element.get("space", ""), element.get("externalId", ""))
|
|
117
|
-
if isinstance(element, dict)
|
|
118
|
-
else (node.space, node.external_id)
|
|
119
|
-
)
|
|
119
|
+
element_keys = self._get_element_keys(node, element)
|
|
120
120
|
|
|
121
|
-
node_entries =
|
|
121
|
+
node_entries = [
|
|
122
|
+
item
|
|
123
|
+
for element_key in element_keys
|
|
124
|
+
for item in mapping_nodes.get(element_key, [])
|
|
125
|
+
]
|
|
122
126
|
if not node_entries:
|
|
123
127
|
if mapping_key in properties:
|
|
124
128
|
properties.pop(mapping_key)
|
|
@@ -126,7 +130,11 @@ class QueryResultMapper:
|
|
|
126
130
|
|
|
127
131
|
entry_data = self.nodes_to_dict(node_entries)
|
|
128
132
|
properties[mapping_key] = entry_data if is_list else entry_data[0]
|
|
129
|
-
edge_entries =
|
|
133
|
+
edge_entries = [
|
|
134
|
+
item
|
|
135
|
+
for element_key in element_keys
|
|
136
|
+
for item in mapping_edges.get(element_key, [])
|
|
137
|
+
]
|
|
130
138
|
if edge_entries:
|
|
131
139
|
edges_mapping[mapping_key] = self._edges_to_model(edge_entries)
|
|
132
140
|
properties["_edges"] = edges_mapping
|
|
@@ -137,6 +145,21 @@ class QueryResultMapper:
|
|
|
137
145
|
|
|
138
146
|
return dict(result)
|
|
139
147
|
|
|
148
|
+
def _get_element_keys(
|
|
149
|
+
self, node: Node, element: PropertyValue | None
|
|
150
|
+
) -> list[tuple[str, str]]:
|
|
151
|
+
if isinstance(element, dict):
|
|
152
|
+
return [(element.get("space", ""), element.get("externalId", ""))]
|
|
153
|
+
|
|
154
|
+
if isinstance(element, list):
|
|
155
|
+
return [
|
|
156
|
+
(item.get("space", ""), item.get("externalId", ""))
|
|
157
|
+
for item in element
|
|
158
|
+
if isinstance(item, dict)
|
|
159
|
+
]
|
|
160
|
+
|
|
161
|
+
return [(node.space, node.external_id)]
|
|
162
|
+
|
|
140
163
|
def _get_property_mappings(
|
|
141
164
|
self,
|
|
142
165
|
key: str,
|
|
@@ -159,7 +182,10 @@ class QueryResultMapper:
|
|
|
159
182
|
self._view_mapper.get_view(property.source.external_id),
|
|
160
183
|
query_result,
|
|
161
184
|
)
|
|
162
|
-
is_list =
|
|
185
|
+
is_list = (
|
|
186
|
+
isinstance(property.type, ListablePropertyType)
|
|
187
|
+
and property.type.is_list
|
|
188
|
+
)
|
|
163
189
|
connection_type = ConnectionTypeEnum.DIRECT_RELATION
|
|
164
190
|
elif isinstance(property, SingleReverseDirectRelation) and property.source:
|
|
165
191
|
nodes = self._map_node_property(
|
|
@@ -16,7 +16,7 @@ from industrial_model.statements import Column
|
|
|
16
16
|
from .base import DBModelMetaclass, RootModel
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
class InstanceId(RootModel):
|
|
19
|
+
class InstanceId(RootModel, metaclass=DBModelMetaclass):
|
|
20
20
|
external_id: str
|
|
21
21
|
space: str
|
|
22
22
|
|
|
@@ -51,7 +51,7 @@ class ViewInstanceConfig(TypedDict, total=False):
|
|
|
51
51
|
view_code: str | None
|
|
52
52
|
|
|
53
53
|
|
|
54
|
-
class ViewInstance(InstanceId
|
|
54
|
+
class ViewInstance(InstanceId):
|
|
55
55
|
view_config: ClassVar[ViewInstanceConfig] = ViewInstanceConfig()
|
|
56
56
|
|
|
57
57
|
_edges: dict[str, list[EdgeContainer]] = PrivateAttr(default_factory=dict)
|
|
@@ -60,11 +60,33 @@ class BaseStatement(Generic[T]):
|
|
|
60
60
|
@dataclass
|
|
61
61
|
class Statement(BaseStatement[T]):
|
|
62
62
|
cursor_: str | None = field(init=False, default=None)
|
|
63
|
+
where_edge_clauses: list[tuple[Column, list[Expression]]] = field(
|
|
64
|
+
init=False, default_factory=list
|
|
65
|
+
)
|
|
63
66
|
|
|
64
67
|
def cursor(self, cursor: str | None) -> Self:
|
|
65
68
|
self.cursor_ = cursor
|
|
66
69
|
return self
|
|
67
70
|
|
|
71
|
+
def where_edge(
|
|
72
|
+
self, property: str | Column | Any, *expressions: bool | Expression
|
|
73
|
+
) -> Self:
|
|
74
|
+
if not expressions:
|
|
75
|
+
return self
|
|
76
|
+
|
|
77
|
+
expressions_: list[Expression] = []
|
|
78
|
+
for expression in expressions:
|
|
79
|
+
assert isinstance(expression, Expression)
|
|
80
|
+
expressions_.append(expression)
|
|
81
|
+
|
|
82
|
+
self.where_edge_clauses.append(
|
|
83
|
+
(
|
|
84
|
+
_create_column(property),
|
|
85
|
+
expressions_,
|
|
86
|
+
)
|
|
87
|
+
)
|
|
88
|
+
return self
|
|
89
|
+
|
|
68
90
|
|
|
69
91
|
@dataclass
|
|
70
92
|
class SearchStatement(BaseStatement[T]):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/cognite_adapters/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/cognite_adapters/models.py
RENAMED
|
File without changes
|
{industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/cognite_adapters/optimizer.py
RENAMED
|
File without changes
|
|
File without changes
|
{industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/cognite_adapters/sort_mapper.py
RENAMED
|
File without changes
|
|
File without changes
|
{industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/cognite_adapters/utils.py
RENAMED
|
File without changes
|
{industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/cognite_adapters/view_mapper.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/engines/async_engine.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{industrial_model-0.1.30 → industrial_model-0.1.32}/industrial_model/statements/expressions.py
RENAMED
|
File without changes
|
|
File without changes
|