industrial-model 0.1.10__tar.gz → 0.1.12__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 (47) hide show
  1. {industrial_model-0.1.10 → industrial_model-0.1.12}/PKG-INFO +1 -1
  2. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/__init__.py +4 -1
  3. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/cognite_adapters/__init__.py +33 -8
  4. industrial_model-0.1.12/industrial_model/cognite_adapters/aggregation_mapper.py +64 -0
  5. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/cognite_adapters/optimizer.py +17 -8
  6. industrial_model-0.1.12/industrial_model/cognite_adapters/view_mapper.py +50 -0
  7. industrial_model-0.1.12/industrial_model/config.py +19 -0
  8. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/engines/async_engine.py +8 -2
  9. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/engines/engine.py +9 -5
  10. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/models/__init__.py +2 -0
  11. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/models/entities.py +6 -0
  12. industrial_model-0.1.12/industrial_model/statements/__init__.py +122 -0
  13. {industrial_model-0.1.10 → industrial_model-0.1.12}/pyproject.toml +1 -1
  14. {industrial_model-0.1.10 → industrial_model-0.1.12}/tests/tests_adapter.py +6 -2
  15. {industrial_model-0.1.10 → industrial_model-0.1.12}/uv.lock +1 -1
  16. industrial_model-0.1.10/.vscode/settings.json +0 -8
  17. industrial_model-0.1.10/industrial_model/cognite_adapters/view_mapper.py +0 -16
  18. industrial_model-0.1.10/industrial_model/config.py +0 -10
  19. industrial_model-0.1.10/industrial_model/statements/__init__.py +0 -72
  20. {industrial_model-0.1.10 → industrial_model-0.1.12}/.gitignore +0 -0
  21. {industrial_model-0.1.10 → industrial_model-0.1.12}/.python-version +0 -0
  22. {industrial_model-0.1.10 → industrial_model-0.1.12}/README.md +0 -0
  23. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/cognite_adapters/filter_mapper.py +0 -0
  24. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/cognite_adapters/models.py +0 -0
  25. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/cognite_adapters/query_mapper.py +0 -0
  26. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/cognite_adapters/query_result_mapper.py +0 -0
  27. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/cognite_adapters/sort_mapper.py +0 -0
  28. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/cognite_adapters/upsert_mapper.py +0 -0
  29. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/cognite_adapters/utils.py +0 -0
  30. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/constants.py +0 -0
  31. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/engines/__init__.py +0 -0
  32. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/models/base.py +0 -0
  33. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/models/schemas.py +0 -0
  34. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/py.typed +0 -0
  35. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/queries/__init__.py +0 -0
  36. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/queries/models.py +0 -0
  37. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/queries/params.py +0 -0
  38. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/statements/expressions.py +0 -0
  39. {industrial_model-0.1.10 → industrial_model-0.1.12}/industrial_model/utils.py +0 -0
  40. {industrial_model-0.1.10 → industrial_model-0.1.12}/scripts/build.sh +0 -0
  41. {industrial_model-0.1.10 → industrial_model-0.1.12}/scripts/format.sh +0 -0
  42. {industrial_model-0.1.10 → industrial_model-0.1.12}/scripts/lint.sh +0 -0
  43. {industrial_model-0.1.10 → industrial_model-0.1.12}/tests/__init__.py +0 -0
  44. {industrial_model-0.1.10 → industrial_model-0.1.12}/tests/cognite-sdk-config.yaml +0 -0
  45. {industrial_model-0.1.10 → industrial_model-0.1.12}/tests/hubs.py +0 -0
  46. {industrial_model-0.1.10 → industrial_model-0.1.12}/tests/models.py +0 -0
  47. {industrial_model-0.1.10 → industrial_model-0.1.12}/tests/test_upsert_mapper.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: industrial-model
3
- Version: 0.1.10
3
+ Version: 0.1.12
4
4
  Summary: Industrial Model ORM
5
5
  Author-email: Lucas Alves <lucasrosaalves@gmail.com>
6
6
  Classifier: Programming Language :: Python
@@ -1,6 +1,7 @@
1
1
  from .config import DataModelId
2
2
  from .engines import AsyncEngine, Engine
3
3
  from .models import (
4
+ AggregationResult,
4
5
  InstanceId,
5
6
  PaginatedResult,
6
7
  TViewInstance,
@@ -10,9 +11,11 @@ from .models import (
10
11
  ViewInstanceConfig,
11
12
  WritableViewInstance,
12
13
  )
13
- from .statements import and_, col, not_, or_, select
14
+ from .statements import aggregate, and_, col, not_, or_, select
14
15
 
15
16
  __all__ = [
17
+ "aggregate",
18
+ "AggregationResult",
16
19
  "and_",
17
20
  "or_",
18
21
  "col",
@@ -11,9 +11,14 @@ from cognite.client.data_classes.data_modeling.query import (
11
11
  )
12
12
 
13
13
  from industrial_model.config import DataModelId
14
- from industrial_model.models import TViewInstance, TWritableViewInstance
15
- from industrial_model.statements import Statement
14
+ from industrial_model.models import (
15
+ AggregationResult,
16
+ TViewInstance,
17
+ TWritableViewInstance,
18
+ )
19
+ from industrial_model.statements import AggregationStatement, Statement
16
20
 
21
+ from .aggregation_mapper import AggregationMapper
17
22
  from .optimizer import QueryOptimizer
18
23
  from .query_mapper import QueryMapper
19
24
  from .query_result_mapper import (
@@ -34,15 +39,12 @@ class CogniteAdapter:
34
39
  ):
35
40
  self._cognite_client = cognite_client
36
41
 
37
- dm = cognite_client.data_modeling.data_models.retrieve(
38
- ids=data_model_id.as_tuple(),
39
- inline_views=True,
40
- ).latest_version()
41
- view_mapper = ViewMapper(dm.views)
42
+ view_mapper = ViewMapper(cognite_client, data_model_id)
43
+ self._optmizer = QueryOptimizer(cognite_client, data_model_id)
42
44
  self._query_mapper = QueryMapper(view_mapper)
43
45
  self._result_mapper = QueryResultMapper(view_mapper)
44
46
  self._upsert_mapper = UpsertMapper(view_mapper)
45
- self._optmizer = QueryOptimizer(cognite_client)
47
+ self._aggregation_mapper = AggregationMapper(view_mapper)
46
48
 
47
49
  def query(
48
50
  self, statement: Statement[TViewInstance], all_pages: bool
@@ -80,6 +82,29 @@ class CogniteAdapter:
80
82
  if not all_pages or last_page:
81
83
  return data, next_cursor_
82
84
 
85
+ def aggregate(
86
+ self, statement: AggregationStatement[TViewInstance]
87
+ ) -> list[AggregationResult]:
88
+ query = self._aggregation_mapper.map(statement)
89
+
90
+ result = self._cognite_client.data_modeling.instances.aggregate(
91
+ view=query.view.as_id(),
92
+ aggregates=query.metric_aggregation,
93
+ filter=query.filters,
94
+ group_by=query.group_by_columns,
95
+ limit=query.limit,
96
+ )
97
+
98
+ return [
99
+ AggregationResult(
100
+ group=item.group,
101
+ value=item.aggregates[0].value,
102
+ aggregate=statement.aggregate_,
103
+ )
104
+ for item in result
105
+ if item.aggregates and item.aggregates[0].value is not None
106
+ ]
107
+
83
108
  def upsert(
84
109
  self, entries: list[TWritableViewInstance], replace: bool = False
85
110
  ) -> None:
@@ -0,0 +1,64 @@
1
+ from dataclasses import dataclass
2
+
3
+ import cognite.client.data_classes.filters as filters
4
+ from cognite.client.data_classes.aggregations import Count, MetricAggregation
5
+ from cognite.client.data_classes.data_modeling import (
6
+ View,
7
+ )
8
+
9
+ from industrial_model.models import TViewInstance
10
+ from industrial_model.statements import AggregationStatement
11
+
12
+ from .filter_mapper import (
13
+ FilterMapper,
14
+ )
15
+ from .view_mapper import ViewMapper
16
+
17
+
18
+ @dataclass
19
+ class AggregationQuery:
20
+ view: View
21
+ metric_aggregation: MetricAggregation
22
+ filters: filters.Filter | None
23
+ group_by_columns: list[str]
24
+ limit: int
25
+
26
+
27
+ class AggregationMapper:
28
+ def __init__(self, view_mapper: ViewMapper):
29
+ self._view_mapper = view_mapper
30
+ self._filter_mapper = FilterMapper(view_mapper)
31
+
32
+ def map(
33
+ self, statement: AggregationStatement[TViewInstance]
34
+ ) -> AggregationQuery:
35
+ root_node = statement.entity.get_view_external_id()
36
+
37
+ root_view = self._view_mapper.get_view(root_node)
38
+
39
+ filters_ = (
40
+ filters.And(
41
+ *self._filter_mapper.map(statement.where_clauses, root_view)
42
+ )
43
+ if statement.where_clauses
44
+ else None
45
+ )
46
+
47
+ metric_aggregation = (
48
+ Count(statement.aggregation_property.property)
49
+ if statement.aggregate_ == "count"
50
+ else None
51
+ )
52
+ if metric_aggregation is None:
53
+ raise ValueError(
54
+ f"Unsupported aggregate function: {statement.aggregate_}"
55
+ )
56
+ return AggregationQuery(
57
+ view=root_view,
58
+ metric_aggregation=metric_aggregation,
59
+ filters=filters_,
60
+ group_by_columns=[
61
+ column.property for column in statement.group_by_columns
62
+ ],
63
+ limit=statement.limit_,
64
+ )
@@ -1,5 +1,8 @@
1
+ from threading import Lock
2
+
1
3
  from cognite.client import CogniteClient
2
4
 
5
+ from industrial_model.config import DataModelId
3
6
  from industrial_model.models import TViewInstance
4
7
  from industrial_model.statements import (
5
8
  BoolExpression,
@@ -14,11 +17,11 @@ SPACE_PROPERTY = "space"
14
17
 
15
18
  class QueryOptimizer:
16
19
  def __init__(
17
- self,
18
- cognite_client: CogniteClient,
20
+ self, cognite_client: CogniteClient, data_model_id: DataModelId
19
21
  ):
20
- self._all_spaces: list[str] | None = None
22
+ self._all_spaces = data_model_id.instance_spaces
21
23
  self._cognite_client = cognite_client
24
+ self._lock = Lock()
22
25
 
23
26
  def optimize(self, statement: Statement[TViewInstance]) -> None:
24
27
  instance_spaces = statement.entity.view_config.get("instance_spaces")
@@ -58,7 +61,7 @@ class QueryOptimizer:
58
61
  return False
59
62
 
60
63
  def _find_spaces(self, instance_spaces_prefix: str) -> list[str]:
61
- all_spaces = self._get_all_spaces()
64
+ all_spaces = self._load_spaces()
62
65
 
63
66
  return [
64
67
  space
@@ -66,12 +69,18 @@ class QueryOptimizer:
66
69
  if space.startswith(instance_spaces_prefix)
67
70
  ]
68
71
 
69
- def _get_all_spaces(self) -> list[str]:
72
+ def _load_spaces(self) -> list[str]:
70
73
  all_spaces = self._all_spaces
71
- if all_spaces is None:
74
+ if all_spaces:
75
+ return all_spaces
76
+
77
+ with self._lock:
78
+ if self._all_spaces:
79
+ return self._all_spaces
80
+
72
81
  all_spaces = self._cognite_client.data_modeling.spaces.list(
73
82
  limit=-1
74
83
  ).as_ids()
75
84
 
76
- self._all_spaces = all_spaces
77
- return all_spaces
85
+ self._all_spaces = all_spaces
86
+ return all_spaces
@@ -0,0 +1,50 @@
1
+ from threading import Lock
2
+
3
+ from cognite.client import CogniteClient
4
+ from cognite.client.data_classes.data_modeling import (
5
+ View,
6
+ )
7
+
8
+ from industrial_model.config import DataModelId
9
+
10
+
11
+ class ViewMapper:
12
+ def __init__(
13
+ self, cognite_client: CogniteClient, data_model_id: DataModelId
14
+ ):
15
+ self._cognite_client = cognite_client
16
+ self._data_model_id = data_model_id
17
+ self._views_as_dict: dict[str, View] | None = None
18
+
19
+ if data_model_id.views:
20
+ self._views_as_dict = {
21
+ view.external_id: view for view in data_model_id.views
22
+ }
23
+
24
+ self._lock = Lock()
25
+
26
+ def get_view(self, view_external_id: str) -> View:
27
+ views = self._load_views()
28
+ if view_external_id not in views:
29
+ raise ValueError(
30
+ f"View {view_external_id} is not available in data model"
31
+ )
32
+
33
+ return views[view_external_id]
34
+
35
+ def _load_views(self) -> dict[str, View]:
36
+ if self._views_as_dict:
37
+ return self._views_as_dict
38
+
39
+ with self._lock:
40
+ if self._views_as_dict:
41
+ return self._views_as_dict
42
+
43
+ dm = self._cognite_client.data_modeling.data_models.retrieve(
44
+ ids=self._data_model_id.as_tuple(),
45
+ inline_views=True,
46
+ ).latest_version()
47
+
48
+ views = {view.external_id: view for view in dm.views}
49
+ self._views_as_dict = views
50
+ return views
@@ -0,0 +1,19 @@
1
+ from dataclasses import dataclass, field
2
+
3
+ from cognite.client.data_classes.data_modeling import View
4
+ from pydantic import BaseModel, ConfigDict
5
+
6
+
7
+ @dataclass
8
+ class DataModelId(BaseModel):
9
+ model_config = ConfigDict(arbitrary_types_allowed=True)
10
+
11
+ external_id: str
12
+ space: str
13
+ version: str
14
+
15
+ views: list[View] | None = field(default=None)
16
+ instance_spaces: list[str] | None = field(default=None)
17
+
18
+ def as_tuple(self) -> tuple[str, str, str]:
19
+ return self.space, self.external_id, self.version
@@ -2,12 +2,13 @@ from cognite.client import CogniteClient
2
2
 
3
3
  from industrial_model.config import DataModelId
4
4
  from industrial_model.models import (
5
+ AggregationResult,
5
6
  PaginatedResult,
6
7
  TViewInstance,
8
+ TWritableViewInstance,
7
9
  ValidationMode,
8
10
  )
9
- from industrial_model.models.entities import TWritableViewInstance
10
- from industrial_model.statements import Statement
11
+ from industrial_model.statements import AggregationStatement, Statement
11
12
  from industrial_model.utils import run_async
12
13
 
13
14
  from .engine import Engine
@@ -37,6 +38,11 @@ class AsyncEngine:
37
38
  self._engine.query_all_pages, statement, validation_mode
38
39
  )
39
40
 
41
+ async def aggregate_async(
42
+ self, statement: AggregationStatement[TViewInstance]
43
+ ) -> list[AggregationResult]:
44
+ return await run_async(self._engine.aggregate, statement)
45
+
40
46
  async def upsert_async(
41
47
  self, entries: list[TWritableViewInstance], replace: bool = False
42
48
  ) -> None:
@@ -5,15 +5,14 @@ from cognite.client import CogniteClient
5
5
  from industrial_model.cognite_adapters import CogniteAdapter
6
6
  from industrial_model.config import DataModelId
7
7
  from industrial_model.models import (
8
+ AggregationResult,
9
+ EdgeContainer,
8
10
  PaginatedResult,
9
11
  TViewInstance,
10
- ValidationMode,
11
- )
12
- from industrial_model.models.entities import (
13
- EdgeContainer,
14
12
  TWritableViewInstance,
13
+ ValidationMode,
15
14
  )
16
- from industrial_model.statements import Statement
15
+ from industrial_model.statements import AggregationStatement, Statement
17
16
 
18
17
 
19
18
  class Engine:
@@ -49,6 +48,11 @@ class Engine:
49
48
 
50
49
  return self._validate_data(statement.entity, data, validation_mode)
51
50
 
51
+ def aggregate(
52
+ self, statement: AggregationStatement[TViewInstance]
53
+ ) -> list[AggregationResult]:
54
+ return self._cognite_adapter.aggregate(statement)
55
+
52
56
  def upsert(
53
57
  self, entries: list[TWritableViewInstance], replace: bool = False
54
58
  ) -> None:
@@ -1,5 +1,6 @@
1
1
  from .base import RootModel
2
2
  from .entities import (
3
+ AggregationResult,
3
4
  EdgeContainer,
4
5
  InstanceId,
5
6
  PaginatedResult,
@@ -13,6 +14,7 @@ from .entities import (
13
14
  from .schemas import get_parent_and_children_nodes, get_schema_properties
14
15
 
15
16
  __all__ = [
17
+ "AggregationResult",
16
18
  "RootModel",
17
19
  "EdgeContainer",
18
20
  "InstanceId",
@@ -90,4 +90,10 @@ class PaginatedResult(RootModel, Generic[TViewInstance]):
90
90
  next_cursor: str | None
91
91
 
92
92
 
93
+ class AggregationResult(RootModel):
94
+ group: dict[str, str | int | float | bool | InstanceId] | None
95
+ value: float
96
+ aggregate: str
97
+
98
+
93
99
  ValidationMode = Literal["raiseOnError", "ignoreOnError"]
@@ -0,0 +1,122 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import Any, Generic, Literal, Self, TypeVar
3
+
4
+ from industrial_model.constants import DEFAULT_LIMIT, SORT_DIRECTION
5
+
6
+ from .expressions import (
7
+ BoolExpression,
8
+ Column,
9
+ Expression,
10
+ LeafExpression,
11
+ and_,
12
+ col,
13
+ not_,
14
+ or_,
15
+ )
16
+
17
+ T = TypeVar("T")
18
+
19
+
20
+ def _create_column(property: str | Column | Any) -> Column:
21
+ return property if isinstance(property, Column) else Column(property)
22
+
23
+
24
+ @dataclass
25
+ class Statement(Generic[T]):
26
+ entity: type[T] = field(init=True)
27
+ where_clauses: list[Expression] = field(init=False, default_factory=list)
28
+ sort_clauses: list[tuple[Column, SORT_DIRECTION]] = field(
29
+ init=False, default_factory=list
30
+ )
31
+ limit_: int = field(init=False, default=DEFAULT_LIMIT)
32
+ cursor_: str | None = field(init=False, default=None)
33
+
34
+ def where(self, *expressions: bool | Expression) -> Self:
35
+ for expression in expressions:
36
+ assert isinstance(expression, Expression)
37
+ self.where_clauses.append(expression)
38
+ return self
39
+
40
+ def asc(self, property: str | Column | Any) -> Self:
41
+ return self.sort(property, "ascending")
42
+
43
+ def desc(self, property: str | Column | Any) -> Self:
44
+ return self.sort(property, "descending")
45
+
46
+ def sort(
47
+ self, property: str | Column | Any, direction: SORT_DIRECTION
48
+ ) -> Self:
49
+ self.sort_clauses.append(
50
+ (
51
+ _create_column(property),
52
+ direction,
53
+ )
54
+ )
55
+ return self
56
+
57
+ def limit(self, limit: int) -> Self:
58
+ self.limit_ = limit
59
+ return self
60
+
61
+ def cursor(self, cursor: str | None) -> Self:
62
+ self.cursor_ = cursor
63
+ return self
64
+
65
+
66
+ @dataclass
67
+ class AggregationStatement(Generic[T]):
68
+ aggregate_: Literal["count"] = field(init=False, default="count")
69
+ aggregation_property: Column = field(
70
+ init=False, default=Column("externalId")
71
+ )
72
+
73
+ entity: type[T] = field(init=True)
74
+ group_by_columns: list[Column] = field(init=False, default_factory=list)
75
+ where_clauses: list[Expression] = field(init=False, default_factory=list)
76
+ limit_: int = field(init=False, default=-1)
77
+
78
+ def aggregate(self, aggregates: Literal["count"]) -> Self:
79
+ self.aggregate_ = aggregates
80
+ return self
81
+
82
+ def aggregate_by(self, property: str | Column | Any) -> Self:
83
+ self.aggregation_property = _create_column(property)
84
+ return self
85
+
86
+ def group_by(self, *property: str | Column | Any) -> Self:
87
+ self.group_by_columns.extend(_create_column(p) for p in property)
88
+ return self
89
+
90
+ def where(self, *expressions: bool | Expression) -> Self:
91
+ for expression in expressions:
92
+ assert isinstance(expression, Expression)
93
+ self.where_clauses.append(expression)
94
+ return self
95
+
96
+ def limit(self, limit: int) -> Self:
97
+ self.limit_ = limit
98
+ return self
99
+
100
+
101
+ def select(entity: type[T]) -> Statement[T]:
102
+ return Statement(entity)
103
+
104
+
105
+ def aggregate(entity: type[T]) -> AggregationStatement[T]:
106
+ return AggregationStatement(entity)
107
+
108
+
109
+ __all__ = [
110
+ "aggregate",
111
+ "AggregationStatement",
112
+ "Statement",
113
+ "select",
114
+ "Column",
115
+ "col",
116
+ "Expression",
117
+ "LeafExpression",
118
+ "BoolExpression",
119
+ "and_",
120
+ "not_",
121
+ "or_",
122
+ ]
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "industrial-model"
3
- version = "0.1.10"
3
+ version = "0.1.12"
4
4
  description = "Industrial Model ORM"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -1,7 +1,7 @@
1
1
  import datetime
2
2
  import json
3
3
 
4
- from industrial_model import col, select
4
+ from industrial_model import aggregate, col, select
5
5
 
6
6
  from .hubs import generate_engine
7
7
  from .models import DescribableEntity, Event
@@ -17,7 +17,9 @@ if __name__ == "__main__":
17
17
  & (col(Event.start_date_time) < datetime.datetime(2025, 6, 1))
18
18
  )
19
19
 
20
- statement = select(Event).limit(50).where(filter)
20
+ statement = (
21
+ select(Event).limit(2500).where(filter).asc(Event.start_date_time)
22
+ )
21
23
 
22
24
  result = [
23
25
  item.model_dump(mode="json")
@@ -25,3 +27,5 @@ if __name__ == "__main__":
25
27
  ]
26
28
  print(len(result))
27
29
  json.dump(result, open("entities.json", "w"), indent=2)
30
+
31
+ print(adapter.aggregate(aggregate(Event).group_by(Event.space)))
@@ -215,7 +215,7 @@ wheels = [
215
215
 
216
216
  [[package]]
217
217
  name = "industrial-model"
218
- version = "0.1.10"
218
+ version = "0.1.12"
219
219
  source = { editable = "." }
220
220
  dependencies = [
221
221
  { name = "anyio" },
@@ -1,8 +0,0 @@
1
- {
2
- "editor.defaultFormatter": "charliermarsh.ruff",
3
- "editor.formatOnSave": true,
4
- "editor.codeActionsOnSave": {
5
- "source.fixAll": "always",
6
- "source.organizeImports": "always"
7
- }
8
- }
@@ -1,16 +0,0 @@
1
- from cognite.client.data_classes.data_modeling import (
2
- View,
3
- )
4
-
5
-
6
- class ViewMapper:
7
- def __init__(self, views: list[View]):
8
- self._views_as_dict = {view.external_id: view for view in views}
9
-
10
- def get_view(self, view_external_id: str) -> View:
11
- if view_external_id not in self._views_as_dict:
12
- raise ValueError(
13
- f"View {view_external_id} is not available in data model"
14
- )
15
-
16
- return self._views_as_dict[view_external_id]
@@ -1,10 +0,0 @@
1
- from industrial_model.models import RootModel
2
-
3
-
4
- class DataModelId(RootModel):
5
- external_id: str
6
- space: str
7
- version: str
8
-
9
- def as_tuple(self) -> tuple[str, str, str]:
10
- return self.space, self.external_id, self.version
@@ -1,72 +0,0 @@
1
- from dataclasses import dataclass, field
2
- from typing import Any, Generic, Self, TypeVar
3
-
4
- from industrial_model.constants import DEFAULT_LIMIT, SORT_DIRECTION
5
-
6
- from .expressions import (
7
- BoolExpression,
8
- Column,
9
- Expression,
10
- LeafExpression,
11
- and_,
12
- col,
13
- not_,
14
- or_,
15
- )
16
-
17
- T = TypeVar("T")
18
-
19
-
20
- @dataclass
21
- class Statement(Generic[T]):
22
- entity: type[T] = field(init=True)
23
- where_clauses: list[Expression] = field(init=False, default_factory=list)
24
- sort_clauses: list[tuple[Column, SORT_DIRECTION]] = field(
25
- init=False, default_factory=list
26
- )
27
- limit_: int = field(init=False, default=DEFAULT_LIMIT)
28
- cursor_: str | None = field(init=False, default=None)
29
-
30
- def where(self, *expressions: bool | Expression) -> Self:
31
- for expression in expressions:
32
- assert isinstance(expression, Expression)
33
- self.where_clauses.append(expression)
34
- return self
35
-
36
- def asc(self, property: Any) -> Self:
37
- self.sort_clauses.append((Column(property), "ascending"))
38
- return self
39
-
40
- def desc(self, property: Any) -> Self:
41
- self.sort_clauses.append((Column(property), "descending"))
42
- return self
43
-
44
- def sort(self, property: Any, direction: SORT_DIRECTION) -> Self:
45
- self.sort_clauses.append((Column(property), direction))
46
- return self
47
-
48
- def limit(self, limit: int) -> Self:
49
- self.limit_ = limit
50
- return self
51
-
52
- def cursor(self, cursor: str | None) -> Self:
53
- self.cursor_ = cursor
54
- return self
55
-
56
-
57
- def select(entity: type[T]) -> Statement[T]:
58
- return Statement(entity)
59
-
60
-
61
- __all__ = [
62
- "Statement",
63
- "select",
64
- "Column",
65
- "col",
66
- "Expression",
67
- "LeafExpression",
68
- "BoolExpression",
69
- "and_",
70
- "not_",
71
- "or_",
72
- ]