industrial-model 0.1.11__tar.gz → 0.1.13__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.11 → industrial_model-0.1.13}/PKG-INFO +27 -13
- {industrial_model-0.1.11 → industrial_model-0.1.13}/README.md +26 -12
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/__init__.py +4 -2
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/cognite_adapters/__init__.py +12 -13
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/cognite_adapters/aggregation_mapper.py +22 -11
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/cognite_adapters/filter_mapper.py +4 -1
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/engines/async_engine.py +3 -3
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/engines/engine.py +6 -4
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/models/__init__.py +4 -2
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/models/base.py +11 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/models/entities.py +23 -17
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/statements/__init__.py +11 -14
- {industrial_model-0.1.11 → industrial_model-0.1.13}/pyproject.toml +1 -1
- {industrial_model-0.1.11 → industrial_model-0.1.13}/tests/models.py +9 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/tests/tests_adapter.py +15 -4
- industrial_model-0.1.13/tests/tests_aggregate.py +19 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/uv.lock +1 -1
- {industrial_model-0.1.11 → industrial_model-0.1.13}/.gitignore +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/.python-version +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/cognite_adapters/models.py +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/cognite_adapters/optimizer.py +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/cognite_adapters/query_mapper.py +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/cognite_adapters/query_result_mapper.py +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/cognite_adapters/sort_mapper.py +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/cognite_adapters/upsert_mapper.py +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/cognite_adapters/utils.py +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/cognite_adapters/view_mapper.py +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/config.py +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/constants.py +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/engines/__init__.py +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/models/schemas.py +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/py.typed +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/queries/__init__.py +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/queries/models.py +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/queries/params.py +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/statements/expressions.py +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/utils.py +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/scripts/build.sh +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/scripts/format.sh +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/scripts/lint.sh +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/tests/__init__.py +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/tests/cognite-sdk-config.yaml +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/tests/hubs.py +0 -0
- {industrial_model-0.1.11 → industrial_model-0.1.13}/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.
|
|
3
|
+
Version: 0.1.13
|
|
4
4
|
Summary: Industrial Model ORM
|
|
5
5
|
Author-email: Lucas Alves <lucasrosaalves@gmail.com>
|
|
6
6
|
Classifier: Programming Language :: Python
|
|
@@ -50,14 +50,19 @@ from cognite.client import CogniteClient
|
|
|
50
50
|
from pydantic import Field
|
|
51
51
|
|
|
52
52
|
from industrial_model import (
|
|
53
|
+
aggregate,
|
|
54
|
+
AggregatedViewInstance,
|
|
53
55
|
AsyncEngine,
|
|
54
56
|
DataModelId,
|
|
55
57
|
Engine,
|
|
58
|
+
InstanceId,
|
|
56
59
|
ViewInstance,
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
ViewInstanceConfig,
|
|
61
|
+
WritableViewInstance,
|
|
59
62
|
and_,
|
|
63
|
+
col,
|
|
60
64
|
or_,
|
|
65
|
+
select,
|
|
61
66
|
)
|
|
62
67
|
|
|
63
68
|
# Define entities (view instances)
|
|
@@ -184,12 +189,10 @@ all_results = engine.query_all_pages(statement)
|
|
|
184
189
|
|
|
185
190
|
# 7. Data Ingestion
|
|
186
191
|
|
|
187
|
-
from industrial_model import (
|
|
188
|
-
WritableViewInstance # necessary for data ingestion
|
|
189
|
-
)
|
|
190
|
-
|
|
191
|
-
|
|
192
192
|
class WritablePerson(WritableViewInstance):
|
|
193
|
+
view_config = ViewInstanceConfig(
|
|
194
|
+
view_external_id="Person" # Maps this class to the 'Person' view
|
|
195
|
+
)
|
|
193
196
|
name: str
|
|
194
197
|
lives_in: InstanceId
|
|
195
198
|
cars: list[InstanceId]
|
|
@@ -203,10 +206,7 @@ class WritablePerson(WritableViewInstance):
|
|
|
203
206
|
space=self.space,
|
|
204
207
|
)
|
|
205
208
|
|
|
206
|
-
statement = select(WritablePerson).where(
|
|
207
|
-
(WritablePerson.external_id == "Lucas")
|
|
208
|
-
)
|
|
209
|
-
|
|
209
|
+
statement = select(WritablePerson).where(WritablePerson.external_id == "Lucas")
|
|
210
210
|
person = engine.query_all_pages(statement)[0]
|
|
211
211
|
|
|
212
212
|
person.lives_in = InstanceId(external_id="br", space="data-space")
|
|
@@ -214,7 +214,21 @@ person.cars.clear() # Gonna remove all car edges from the person
|
|
|
214
214
|
|
|
215
215
|
engine.upsert([person])
|
|
216
216
|
|
|
217
|
-
```
|
|
218
217
|
|
|
219
218
|
|
|
219
|
+
# 8. Aggregate
|
|
220
|
+
|
|
221
|
+
class AggregateByNamePerson(AggregatedViewInstance):
|
|
222
|
+
view_config = ViewInstanceConfig(
|
|
223
|
+
view_external_id="Person" # Maps this class to the 'Person' view
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
name: str # group by name
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
aggregate_result = engine.aggregate(aggregate(AggregateByNamePerson, "count"))
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
|
|
220
234
|
---
|
|
@@ -30,14 +30,19 @@ from cognite.client import CogniteClient
|
|
|
30
30
|
from pydantic import Field
|
|
31
31
|
|
|
32
32
|
from industrial_model import (
|
|
33
|
+
aggregate,
|
|
34
|
+
AggregatedViewInstance,
|
|
33
35
|
AsyncEngine,
|
|
34
36
|
DataModelId,
|
|
35
37
|
Engine,
|
|
38
|
+
InstanceId,
|
|
36
39
|
ViewInstance,
|
|
37
|
-
|
|
38
|
-
|
|
40
|
+
ViewInstanceConfig,
|
|
41
|
+
WritableViewInstance,
|
|
39
42
|
and_,
|
|
43
|
+
col,
|
|
40
44
|
or_,
|
|
45
|
+
select,
|
|
41
46
|
)
|
|
42
47
|
|
|
43
48
|
# Define entities (view instances)
|
|
@@ -164,12 +169,10 @@ all_results = engine.query_all_pages(statement)
|
|
|
164
169
|
|
|
165
170
|
# 7. Data Ingestion
|
|
166
171
|
|
|
167
|
-
from industrial_model import (
|
|
168
|
-
WritableViewInstance # necessary for data ingestion
|
|
169
|
-
)
|
|
170
|
-
|
|
171
|
-
|
|
172
172
|
class WritablePerson(WritableViewInstance):
|
|
173
|
+
view_config = ViewInstanceConfig(
|
|
174
|
+
view_external_id="Person" # Maps this class to the 'Person' view
|
|
175
|
+
)
|
|
173
176
|
name: str
|
|
174
177
|
lives_in: InstanceId
|
|
175
178
|
cars: list[InstanceId]
|
|
@@ -183,10 +186,7 @@ class WritablePerson(WritableViewInstance):
|
|
|
183
186
|
space=self.space,
|
|
184
187
|
)
|
|
185
188
|
|
|
186
|
-
statement = select(WritablePerson).where(
|
|
187
|
-
(WritablePerson.external_id == "Lucas")
|
|
188
|
-
)
|
|
189
|
-
|
|
189
|
+
statement = select(WritablePerson).where(WritablePerson.external_id == "Lucas")
|
|
190
190
|
person = engine.query_all_pages(statement)[0]
|
|
191
191
|
|
|
192
192
|
person.lives_in = InstanceId(external_id="br", space="data-space")
|
|
@@ -194,7 +194,21 @@ person.cars.clear() # Gonna remove all car edges from the person
|
|
|
194
194
|
|
|
195
195
|
engine.upsert([person])
|
|
196
196
|
|
|
197
|
-
```
|
|
198
197
|
|
|
199
198
|
|
|
199
|
+
# 8. Aggregate
|
|
200
|
+
|
|
201
|
+
class AggregateByNamePerson(AggregatedViewInstance):
|
|
202
|
+
view_config = ViewInstanceConfig(
|
|
203
|
+
view_external_id="Person" # Maps this class to the 'Person' view
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
name: str # group by name
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
aggregate_result = engine.aggregate(aggregate(AggregateByNamePerson, "count"))
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
|
|
200
214
|
---
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
from .config import DataModelId
|
|
2
2
|
from .engines import AsyncEngine, Engine
|
|
3
3
|
from .models import (
|
|
4
|
-
|
|
4
|
+
AggregatedViewInstance,
|
|
5
5
|
InstanceId,
|
|
6
6
|
PaginatedResult,
|
|
7
|
+
TAggregatedViewInstance,
|
|
7
8
|
TViewInstance,
|
|
8
9
|
TWritableViewInstance,
|
|
9
10
|
ValidationMode,
|
|
@@ -15,7 +16,7 @@ from .statements import aggregate, and_, col, not_, or_, select
|
|
|
15
16
|
|
|
16
17
|
__all__ = [
|
|
17
18
|
"aggregate",
|
|
18
|
-
"
|
|
19
|
+
"AggregatedViewInstance",
|
|
19
20
|
"and_",
|
|
20
21
|
"or_",
|
|
21
22
|
"col",
|
|
@@ -25,6 +26,7 @@ __all__ = [
|
|
|
25
26
|
"InstanceId",
|
|
26
27
|
"TViewInstance",
|
|
27
28
|
"DataModelId",
|
|
29
|
+
"TAggregatedViewInstance",
|
|
28
30
|
"TWritableViewInstance",
|
|
29
31
|
"ValidationMode",
|
|
30
32
|
"Engine",
|
{industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/cognite_adapters/__init__.py
RENAMED
|
@@ -12,7 +12,7 @@ from cognite.client.data_classes.data_modeling.query import (
|
|
|
12
12
|
|
|
13
13
|
from industrial_model.config import DataModelId
|
|
14
14
|
from industrial_model.models import (
|
|
15
|
-
|
|
15
|
+
TAggregatedViewInstance,
|
|
16
16
|
TViewInstance,
|
|
17
17
|
TWritableViewInstance,
|
|
18
18
|
)
|
|
@@ -83,8 +83,8 @@ class CogniteAdapter:
|
|
|
83
83
|
return data, next_cursor_
|
|
84
84
|
|
|
85
85
|
def aggregate(
|
|
86
|
-
self, statement: AggregationStatement[
|
|
87
|
-
) -> list[
|
|
86
|
+
self, statement: AggregationStatement[TAggregatedViewInstance]
|
|
87
|
+
) -> list[dict[str, Any]]:
|
|
88
88
|
query = self._aggregation_mapper.map(statement)
|
|
89
89
|
|
|
90
90
|
result = self._cognite_client.data_modeling.instances.aggregate(
|
|
@@ -94,16 +94,15 @@ class CogniteAdapter:
|
|
|
94
94
|
group_by=query.group_by_columns,
|
|
95
95
|
limit=query.limit,
|
|
96
96
|
)
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
]
|
|
97
|
+
data: list[dict[str, Any]] = []
|
|
98
|
+
for item in result:
|
|
99
|
+
if not item.aggregates or item.aggregates[0].value is None:
|
|
100
|
+
continue
|
|
101
|
+
|
|
102
|
+
entry = item.group if item.group else {}
|
|
103
|
+
entry["value"] = item.aggregates[0].value
|
|
104
|
+
data.append(entry)
|
|
105
|
+
return data
|
|
107
106
|
|
|
108
107
|
def upsert(
|
|
109
108
|
self, entries: list[TWritableViewInstance], replace: bool = False
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
|
|
3
3
|
import cognite.client.data_classes.filters as filters
|
|
4
|
-
from cognite.client.data_classes.aggregations import
|
|
4
|
+
from cognite.client.data_classes.aggregations import (
|
|
5
|
+
Avg,
|
|
6
|
+
Count,
|
|
7
|
+
Max,
|
|
8
|
+
MetricAggregation,
|
|
9
|
+
Min,
|
|
10
|
+
Sum,
|
|
11
|
+
)
|
|
5
12
|
from cognite.client.data_classes.data_modeling import (
|
|
6
13
|
View,
|
|
7
14
|
)
|
|
8
15
|
|
|
9
|
-
from industrial_model.models import
|
|
16
|
+
from industrial_model.models import TAggregatedViewInstance
|
|
10
17
|
from industrial_model.statements import AggregationStatement
|
|
11
18
|
|
|
12
19
|
from .filter_mapper import (
|
|
@@ -30,7 +37,7 @@ class AggregationMapper:
|
|
|
30
37
|
self._filter_mapper = FilterMapper(view_mapper)
|
|
31
38
|
|
|
32
39
|
def map(
|
|
33
|
-
self, statement: AggregationStatement[
|
|
40
|
+
self, statement: AggregationStatement[TAggregatedViewInstance]
|
|
34
41
|
) -> AggregationQuery:
|
|
35
42
|
root_node = statement.entity.get_view_external_id()
|
|
36
43
|
|
|
@@ -43,12 +50,18 @@ class AggregationMapper:
|
|
|
43
50
|
if statement.where_clauses
|
|
44
51
|
else None
|
|
45
52
|
)
|
|
53
|
+
metric_aggregation: MetricAggregation | None = None
|
|
54
|
+
if statement.aggregate == "avg":
|
|
55
|
+
metric_aggregation = Avg(statement.aggregation_property.property)
|
|
56
|
+
elif statement.aggregate == "min":
|
|
57
|
+
metric_aggregation = Min(statement.aggregation_property.property)
|
|
58
|
+
elif statement.aggregate == "max":
|
|
59
|
+
metric_aggregation = Max(statement.aggregation_property.property)
|
|
60
|
+
elif statement.aggregate == "sum":
|
|
61
|
+
metric_aggregation = Sum(statement.aggregation_property.property)
|
|
62
|
+
elif statement.aggregate == "count":
|
|
63
|
+
metric_aggregation = Count(statement.aggregation_property.property)
|
|
46
64
|
|
|
47
|
-
metric_aggregation = (
|
|
48
|
-
Count(statement.aggregation_property.property)
|
|
49
|
-
if statement.aggregate_ == "count"
|
|
50
|
-
else None
|
|
51
|
-
)
|
|
52
65
|
if metric_aggregation is None:
|
|
53
66
|
raise ValueError(
|
|
54
67
|
f"Unsupported aggregate function: {statement.aggregate_}"
|
|
@@ -57,8 +70,6 @@ class AggregationMapper:
|
|
|
57
70
|
view=root_view,
|
|
58
71
|
metric_aggregation=metric_aggregation,
|
|
59
72
|
filters=filters_,
|
|
60
|
-
group_by_columns=
|
|
61
|
-
column.property for column in statement.group_by_columns
|
|
62
|
-
],
|
|
73
|
+
group_by_columns=statement.entity.get_group_by_fields(),
|
|
63
74
|
limit=statement.limit_,
|
|
64
75
|
)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from datetime import datetime
|
|
1
|
+
from datetime import date, datetime
|
|
2
2
|
|
|
3
3
|
import cognite.client.data_classes.filters as cdf_filters
|
|
4
4
|
from cognite.client.data_classes.data_modeling import MappedProperty, View
|
|
@@ -57,6 +57,9 @@ class FilterMapper:
|
|
|
57
57
|
if isinstance(value_, datetime):
|
|
58
58
|
value_ = datetime_to_ms_iso_timestamp(value_)
|
|
59
59
|
|
|
60
|
+
if isinstance(value_, date):
|
|
61
|
+
value_ = value_.strftime("%Y-%m-%d")
|
|
62
|
+
|
|
60
63
|
if expression.operator == "==":
|
|
61
64
|
return cdf_filters.Equals(property_ref, value_)
|
|
62
65
|
elif expression.operator == "in":
|
{industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/engines/async_engine.py
RENAMED
|
@@ -2,8 +2,8 @@ from cognite.client import CogniteClient
|
|
|
2
2
|
|
|
3
3
|
from industrial_model.config import DataModelId
|
|
4
4
|
from industrial_model.models import (
|
|
5
|
-
AggregationResult,
|
|
6
5
|
PaginatedResult,
|
|
6
|
+
TAggregatedViewInstance,
|
|
7
7
|
TViewInstance,
|
|
8
8
|
TWritableViewInstance,
|
|
9
9
|
ValidationMode,
|
|
@@ -39,8 +39,8 @@ class AsyncEngine:
|
|
|
39
39
|
)
|
|
40
40
|
|
|
41
41
|
async def aggregate_async(
|
|
42
|
-
self, statement: AggregationStatement[
|
|
43
|
-
) -> list[
|
|
42
|
+
self, statement: AggregationStatement[TAggregatedViewInstance]
|
|
43
|
+
) -> list[TAggregatedViewInstance]:
|
|
44
44
|
return await run_async(self._engine.aggregate, statement)
|
|
45
45
|
|
|
46
46
|
async def upsert_async(
|
|
@@ -5,9 +5,9 @@ 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
8
|
EdgeContainer,
|
|
10
9
|
PaginatedResult,
|
|
10
|
+
TAggregatedViewInstance,
|
|
11
11
|
TViewInstance,
|
|
12
12
|
TWritableViewInstance,
|
|
13
13
|
ValidationMode,
|
|
@@ -49,9 +49,11 @@ class Engine:
|
|
|
49
49
|
return self._validate_data(statement.entity, data, validation_mode)
|
|
50
50
|
|
|
51
51
|
def aggregate(
|
|
52
|
-
self, statement: AggregationStatement[
|
|
53
|
-
) -> list[
|
|
54
|
-
|
|
52
|
+
self, statement: AggregationStatement[TAggregatedViewInstance]
|
|
53
|
+
) -> list[TAggregatedViewInstance]:
|
|
54
|
+
data = self._cognite_adapter.aggregate(statement)
|
|
55
|
+
|
|
56
|
+
return [statement.entity.model_validate(item) for item in data]
|
|
55
57
|
|
|
56
58
|
def upsert(
|
|
57
59
|
self, entries: list[TWritableViewInstance], replace: bool = False
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
from .base import RootModel
|
|
2
2
|
from .entities import (
|
|
3
|
-
|
|
3
|
+
AggregatedViewInstance,
|
|
4
4
|
EdgeContainer,
|
|
5
5
|
InstanceId,
|
|
6
6
|
PaginatedResult,
|
|
7
|
+
TAggregatedViewInstance,
|
|
7
8
|
TViewInstance,
|
|
8
9
|
TWritableViewInstance,
|
|
9
10
|
ValidationMode,
|
|
@@ -14,10 +15,11 @@ from .entities import (
|
|
|
14
15
|
from .schemas import get_parent_and_children_nodes, get_schema_properties
|
|
15
16
|
|
|
16
17
|
__all__ = [
|
|
17
|
-
"
|
|
18
|
+
"AggregatedViewInstance",
|
|
18
19
|
"RootModel",
|
|
19
20
|
"EdgeContainer",
|
|
20
21
|
"InstanceId",
|
|
22
|
+
"TAggregatedViewInstance",
|
|
21
23
|
"TViewInstance",
|
|
22
24
|
"TWritableViewInstance",
|
|
23
25
|
"ViewInstance",
|
|
@@ -44,3 +44,14 @@ class RootModel(BaseModel):
|
|
|
44
44
|
populate_by_name=True,
|
|
45
45
|
from_attributes=True,
|
|
46
46
|
)
|
|
47
|
+
|
|
48
|
+
def get_field_name(self, field_name_or_alias: str) -> str | None:
|
|
49
|
+
entry = self.__class__.model_fields.get(field_name_or_alias)
|
|
50
|
+
if entry:
|
|
51
|
+
return field_name_or_alias
|
|
52
|
+
|
|
53
|
+
for key, field_info in self.__class__.model_fields.items():
|
|
54
|
+
if field_info.alias == field_name_or_alias:
|
|
55
|
+
return key
|
|
56
|
+
|
|
57
|
+
return None
|
|
@@ -56,17 +56,6 @@ class ViewInstance(InstanceId, metaclass=DBModelMetaclass):
|
|
|
56
56
|
def get_view_external_id(cls) -> str:
|
|
57
57
|
return cls.view_config.get("view_external_id") or cls.__name__
|
|
58
58
|
|
|
59
|
-
def get_field_name(self, field_name_or_alias: str) -> str | None:
|
|
60
|
-
entry = self.__class__.model_fields.get(field_name_or_alias)
|
|
61
|
-
if entry:
|
|
62
|
-
return field_name_or_alias
|
|
63
|
-
|
|
64
|
-
for key, field_info in self.__class__.model_fields.items():
|
|
65
|
-
if field_info.alias == field_name_or_alias:
|
|
66
|
-
return key
|
|
67
|
-
|
|
68
|
-
return None
|
|
69
|
-
|
|
70
59
|
|
|
71
60
|
class WritableViewInstance(ViewInstance):
|
|
72
61
|
@abstractmethod
|
|
@@ -78,10 +67,33 @@ class WritableViewInstance(ViewInstance):
|
|
|
78
67
|
)
|
|
79
68
|
|
|
80
69
|
|
|
70
|
+
class AggregatedViewInstance(RootModel, metaclass=DBModelMetaclass):
|
|
71
|
+
view_config: ClassVar[ViewInstanceConfig] = ViewInstanceConfig()
|
|
72
|
+
|
|
73
|
+
value: float
|
|
74
|
+
|
|
75
|
+
@classmethod
|
|
76
|
+
def get_view_external_id(cls) -> str:
|
|
77
|
+
return cls.view_config.get("view_external_id") or cls.__name__
|
|
78
|
+
|
|
79
|
+
@classmethod
|
|
80
|
+
def get_group_by_fields(cls) -> list[str]:
|
|
81
|
+
group_by_fields: set[str] = set()
|
|
82
|
+
for key, field_info in cls.model_fields.items():
|
|
83
|
+
if key == "value":
|
|
84
|
+
continue
|
|
85
|
+
group_by_fields.add(field_info.alias or key)
|
|
86
|
+
|
|
87
|
+
return list(group_by_fields)
|
|
88
|
+
|
|
89
|
+
|
|
81
90
|
TViewInstance = TypeVar("TViewInstance", bound=ViewInstance)
|
|
82
91
|
TWritableViewInstance = TypeVar(
|
|
83
92
|
"TWritableViewInstance", bound=WritableViewInstance
|
|
84
93
|
)
|
|
94
|
+
TAggregatedViewInstance = TypeVar(
|
|
95
|
+
"TAggregatedViewInstance", bound=AggregatedViewInstance
|
|
96
|
+
)
|
|
85
97
|
|
|
86
98
|
|
|
87
99
|
class PaginatedResult(RootModel, Generic[TViewInstance]):
|
|
@@ -90,10 +102,4 @@ class PaginatedResult(RootModel, Generic[TViewInstance]):
|
|
|
90
102
|
next_cursor: str | None
|
|
91
103
|
|
|
92
104
|
|
|
93
|
-
class AggregationResult(RootModel):
|
|
94
|
-
group: dict[str, str | int | float | bool] | None
|
|
95
|
-
value: float
|
|
96
|
-
aggregate: str
|
|
97
|
-
|
|
98
|
-
|
|
99
105
|
ValidationMode = Literal["raiseOnError", "ignoreOnError"]
|
|
@@ -63,30 +63,24 @@ class Statement(Generic[T]):
|
|
|
63
63
|
return self
|
|
64
64
|
|
|
65
65
|
|
|
66
|
+
AggregateTypes = Literal["count", "avg", "min", "max", "sum"]
|
|
67
|
+
|
|
68
|
+
|
|
66
69
|
@dataclass
|
|
67
70
|
class AggregationStatement(Generic[T]):
|
|
68
|
-
|
|
71
|
+
entity: type[T] = field(init=True)
|
|
72
|
+
aggregate: AggregateTypes = field(init=True)
|
|
73
|
+
|
|
69
74
|
aggregation_property: Column = field(
|
|
70
75
|
init=False, default=Column("externalId")
|
|
71
76
|
)
|
|
72
|
-
|
|
73
|
-
entity: type[T] = field(init=True)
|
|
74
|
-
group_by_columns: list[Column] = field(init=False, default_factory=list)
|
|
75
77
|
where_clauses: list[Expression] = field(init=False, default_factory=list)
|
|
76
78
|
limit_: int = field(init=False, default=-1)
|
|
77
79
|
|
|
78
|
-
def aggregate(self, aggregates: Literal["count"]) -> Self:
|
|
79
|
-
self.aggregate_ = aggregates
|
|
80
|
-
return self
|
|
81
|
-
|
|
82
80
|
def aggregate_by(self, property: str | Column | Any) -> Self:
|
|
83
81
|
self.aggregation_property = _create_column(property)
|
|
84
82
|
return self
|
|
85
83
|
|
|
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
84
|
def where(self, *expressions: bool | Expression) -> Self:
|
|
91
85
|
for expression in expressions:
|
|
92
86
|
assert isinstance(expression, Expression)
|
|
@@ -102,8 +96,11 @@ def select(entity: type[T]) -> Statement[T]:
|
|
|
102
96
|
return Statement(entity)
|
|
103
97
|
|
|
104
98
|
|
|
105
|
-
def aggregate(
|
|
106
|
-
|
|
99
|
+
def aggregate(
|
|
100
|
+
entity: type[T],
|
|
101
|
+
aggregate: AggregateTypes = "count",
|
|
102
|
+
) -> AggregationStatement[T]:
|
|
103
|
+
return AggregationStatement(entity=entity, aggregate=aggregate)
|
|
107
104
|
|
|
108
105
|
|
|
109
106
|
__all__ = [
|
|
@@ -52,6 +52,15 @@ class Event(ViewInstance):
|
|
|
52
52
|
]
|
|
53
53
|
|
|
54
54
|
|
|
55
|
+
class Msdp(ViewInstance):
|
|
56
|
+
view_config = ViewInstanceConfig(
|
|
57
|
+
view_external_id="OEEMSDP",
|
|
58
|
+
instance_spaces_prefix="OEE-",
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
effective_date: datetime.date
|
|
62
|
+
|
|
63
|
+
|
|
55
64
|
class WritableEvent(WritableViewInstance):
|
|
56
65
|
view_config = ViewInstanceConfig(
|
|
57
66
|
view_external_id="OEEEvent",
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import datetime
|
|
2
2
|
import json
|
|
3
3
|
|
|
4
|
-
from industrial_model import
|
|
4
|
+
from industrial_model import col, select
|
|
5
5
|
|
|
6
6
|
from .hubs import generate_engine
|
|
7
|
-
from .models import DescribableEntity, Event
|
|
7
|
+
from .models import DescribableEntity, Event, Msdp
|
|
8
8
|
|
|
9
9
|
if __name__ == "__main__":
|
|
10
10
|
adapter = generate_engine()
|
|
@@ -26,6 +26,17 @@ if __name__ == "__main__":
|
|
|
26
26
|
for item in adapter.query_all_pages(statement)
|
|
27
27
|
]
|
|
28
28
|
print(len(result))
|
|
29
|
-
json.dump(result, open("
|
|
29
|
+
json.dump(result, open("events.json", "w"), indent=2)
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
statement_msdp = (
|
|
32
|
+
select(Msdp)
|
|
33
|
+
.limit(2500)
|
|
34
|
+
.where(Msdp.effective_date >= datetime.date(2022, 5, 1))
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
result_msdp = [
|
|
38
|
+
item.model_dump(mode="json")
|
|
39
|
+
for item in adapter.query_all_pages(statement_msdp)
|
|
40
|
+
]
|
|
41
|
+
print(len(result_msdp))
|
|
42
|
+
json.dump(result_msdp, open("msdp.json", "w"), indent=2)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from industrial_model import (
|
|
2
|
+
AggregatedViewInstance,
|
|
3
|
+
ViewInstanceConfig,
|
|
4
|
+
aggregate,
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
from .hubs import generate_engine
|
|
8
|
+
|
|
9
|
+
if __name__ == "__main__":
|
|
10
|
+
adapter = generate_engine()
|
|
11
|
+
|
|
12
|
+
default_config = ViewInstanceConfig(view_external_id="OEEEvent")
|
|
13
|
+
|
|
14
|
+
class AggregatedEvent(AggregatedViewInstance):
|
|
15
|
+
view_config = default_config
|
|
16
|
+
event_definition: str
|
|
17
|
+
|
|
18
|
+
aggregate_result = adapter.aggregate(aggregate(AggregatedEvent, "count"))
|
|
19
|
+
print(aggregate_result)
|
|
File without changes
|
|
File without changes
|
{industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/cognite_adapters/models.py
RENAMED
|
File without changes
|
{industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/cognite_adapters/optimizer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/cognite_adapters/sort_mapper.py
RENAMED
|
File without changes
|
|
File without changes
|
{industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/cognite_adapters/utils.py
RENAMED
|
File without changes
|
{industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/cognite_adapters/view_mapper.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
|
{industrial_model-0.1.11 → industrial_model-0.1.13}/industrial_model/statements/expressions.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
|