industrial-model 0.1.31__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.
Files changed (34) hide show
  1. {industrial_model-0.1.31 → industrial_model-0.1.32}/PKG-INFO +1 -1
  2. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/cognite_adapters/filter_mapper.py +32 -5
  3. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/cognite_adapters/query_mapper.py +16 -2
  4. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/models/entities.py +2 -2
  5. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/statements/__init__.py +22 -0
  6. {industrial_model-0.1.31 → industrial_model-0.1.32}/pyproject.toml +1 -1
  7. {industrial_model-0.1.31 → industrial_model-0.1.32}/.gitignore +0 -0
  8. {industrial_model-0.1.31 → industrial_model-0.1.32}/README.md +0 -0
  9. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/__init__.py +0 -0
  10. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/cognite_adapters/__init__.py +0 -0
  11. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/cognite_adapters/aggregation_mapper.py +0 -0
  12. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/cognite_adapters/models.py +0 -0
  13. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/cognite_adapters/optimizer.py +0 -0
  14. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/cognite_adapters/query_result_mapper.py +0 -0
  15. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/cognite_adapters/search_mapper.py +0 -0
  16. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/cognite_adapters/sort_mapper.py +0 -0
  17. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/cognite_adapters/upsert_mapper.py +0 -0
  18. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/cognite_adapters/utils.py +0 -0
  19. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/cognite_adapters/view_mapper.py +0 -0
  20. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/config.py +0 -0
  21. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/constants.py +0 -0
  22. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/engines/__init__.py +0 -0
  23. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/engines/async_engine.py +0 -0
  24. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/engines/engine.py +0 -0
  25. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/models/__init__.py +0 -0
  26. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/models/base.py +0 -0
  27. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/models/schemas.py +0 -0
  28. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/py.typed +0 -0
  29. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/queries/__init__.py +0 -0
  30. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/queries/models.py +0 -0
  31. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/queries/params.py +0 -0
  32. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/queries/utils.py +0 -0
  33. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/statements/expressions.py +0 -0
  34. {industrial_model-0.1.31 → industrial_model-0.1.32}/industrial_model/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: industrial-model
3
- Version: 0.1.31
3
+ Version: 0.1.32
4
4
  Summary: Industrial Model ORM
5
5
  Author-email: Lucas Alves <lucasrosaalves@gmail.com>
6
6
  Classifier: Programming Language :: Python
@@ -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 MappedProperty, View
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.to_cdf_filter_bool(expression, root_view))
34
+ result.append(self._to_cdf_filter_bool(expression, root_view))
30
35
  elif isinstance(expression, LeafExpression):
31
- result.append(self.to_cdf_filter_leaf(expression, root_view))
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 to_cdf_filter_bool(
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 to_cdf_filter_leaf(
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(["edge", "type"], property.type.dump()),
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
  )
@@ -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, metaclass=DBModelMetaclass):
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]):
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "industrial-model"
3
- version = "0.1.31"
3
+ version = "0.1.32"
4
4
  description = "Industrial Model ORM"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"