industrial-model 1.2.1__py3-none-any.whl → 1.2.3__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.
- industrial_model-1.2.3.dist-info/METADATA +1118 -0
- {industrial_model-1.2.1.dist-info → industrial_model-1.2.3.dist-info}/RECORD +4 -4
- {industrial_model-1.2.1.dist-info → industrial_model-1.2.3.dist-info}/WHEEL +1 -1
- industrial_model-1.2.1.dist-info/METADATA +0 -334
- {industrial_model-1.2.1.dist-info → industrial_model-1.2.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -30,7 +30,7 @@ industrial_model/queries/params.py,sha256=50qY5BO5onLsXorhcv-7qCKhJaMO94UzhKLCmZ
|
|
|
30
30
|
industrial_model/queries/utils.py,sha256=uP6PLh9IVHDK6J8x444zHWPmyV4PkxdLO-PMc6qWItc,1505
|
|
31
31
|
industrial_model/statements/__init__.py,sha256=xazAVHvN8HKsWcXR2Hp1aGxd59stg13JXO6tgpJnsC4,5660
|
|
32
32
|
industrial_model/statements/expressions.py,sha256=4ZZOcZroI5-4xRw4PXIRlufi0ARndE5zSbbxLDpR2Ec,4816
|
|
33
|
-
industrial_model-1.2.
|
|
34
|
-
industrial_model-1.2.
|
|
35
|
-
industrial_model-1.2.
|
|
36
|
-
industrial_model-1.2.
|
|
33
|
+
industrial_model-1.2.3.dist-info/METADATA,sha256=sVnK17Ksz5sXFP-e9o9IAMFN87fYmIAaZyBWOyb0_qM,28872
|
|
34
|
+
industrial_model-1.2.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
35
|
+
industrial_model-1.2.3.dist-info/licenses/LICENSE,sha256=BCHCZ1Qo7m4YvAEIQqtVBI3NebFJdZ8_7m_cxInIlN0,4934
|
|
36
|
+
industrial_model-1.2.3.dist-info/RECORD,,
|
|
@@ -1,334 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: industrial-model
|
|
3
|
-
Version: 1.2.1
|
|
4
|
-
Summary: Industrial Model ORM
|
|
5
|
-
Project-URL: Homepage, https://github.com/lucasrosaalves/industrial-model
|
|
6
|
-
Project-URL: Source, https://github.com/lucasrosaalves/industrial-model
|
|
7
|
-
Author-email: Lucas Alves <lucasrosaalves@gmail.com>
|
|
8
|
-
License-File: LICENSE
|
|
9
|
-
Classifier: Programming Language :: Python
|
|
10
|
-
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
-
Classifier: Topic :: Database
|
|
16
|
-
Classifier: Topic :: Database :: Database Engines/Servers
|
|
17
|
-
Classifier: Typing :: Typed
|
|
18
|
-
Requires-Python: >=3.11
|
|
19
|
-
Requires-Dist: anyio>=4.9.0
|
|
20
|
-
Requires-Dist: cognite-sdk>=7.87.0
|
|
21
|
-
Requires-Dist: pydantic>=2.11.4
|
|
22
|
-
Requires-Dist: pyyaml>=6.0.2
|
|
23
|
-
Description-Content-Type: text/markdown
|
|
24
|
-
|
|
25
|
-
# 📦 industrial-model
|
|
26
|
-
|
|
27
|
-
`industrial-model` is a Python ORM-style abstraction for querying views in Cognite Data Fusion (CDF). It provides a declarative and type-safe way to model CDF views using `pydantic`, build queries, and interact with the CDF API in a Pythonic fashion.
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## ✨ Features
|
|
32
|
-
|
|
33
|
-
- Define CDF views using Pydantic-style classes.
|
|
34
|
-
- Build complex queries using fluent and composable filters.
|
|
35
|
-
- Easily fetch data using standard or paginated query execution.
|
|
36
|
-
- Automatic alias and field transformation support.
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
|
-
## 📦 Installation
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
pip install industrial-model
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
---
|
|
47
|
-
|
|
48
|
-
# Usage Example
|
|
49
|
-
|
|
50
|
-
This section shows how to interact with **Cognite Data Fusion (CDF)** using the `industrial_model` package.
|
|
51
|
-
We use the simplified version of the `CogniteAsset`view in the `CogniteCore` data model (version `v1`) as a sample for all the examples below.
|
|
52
|
-
|
|
53
|
-
---
|
|
54
|
-
|
|
55
|
-
```graphql
|
|
56
|
-
type CogniteAsset {
|
|
57
|
-
name: String
|
|
58
|
-
description: String
|
|
59
|
-
tags: [String]
|
|
60
|
-
parent: CogniteAsset
|
|
61
|
-
root: CogniteAsset
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
---
|
|
66
|
-
|
|
67
|
-
## 🚀 Getting Started
|
|
68
|
-
|
|
69
|
-
### 1. Define Your Model (You only need to add the properties that you want to retrieve)
|
|
70
|
-
|
|
71
|
-
```python
|
|
72
|
-
from industrial_model import ViewInstance
|
|
73
|
-
|
|
74
|
-
class CogniteAsset(ViewInstance):
|
|
75
|
-
name: str
|
|
76
|
-
description: str
|
|
77
|
-
aliases: list[str]
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### 2. Create the Engine
|
|
81
|
-
|
|
82
|
-
#### Option A: From Configuration File
|
|
83
|
-
|
|
84
|
-
Create a `cognite-sdk-config.yaml` file with your credentials and model configuration:
|
|
85
|
-
|
|
86
|
-
```yaml
|
|
87
|
-
cognite:
|
|
88
|
-
project: "${CDF_PROJECT}"
|
|
89
|
-
client_name: "${CDF_CLIENT_NAME}"
|
|
90
|
-
base_url: "https://${CDF_CLUSTER}.cognitedata.com"
|
|
91
|
-
credentials:
|
|
92
|
-
client_credentials:
|
|
93
|
-
token_url: "${CDF_TOKEN_URL}"
|
|
94
|
-
client_id: "${CDF_CLIENT_ID}"
|
|
95
|
-
client_secret: "${CDF_CLIENT_SECRET}"
|
|
96
|
-
scopes: ["https://${CDF_CLUSTER}.cognitedata.com/.default"]
|
|
97
|
-
|
|
98
|
-
data_model:
|
|
99
|
-
external_id: "CogniteCore"
|
|
100
|
-
space: "cdf_cdm"
|
|
101
|
-
version: "v1"
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
```python
|
|
105
|
-
from industrial_model import Engine
|
|
106
|
-
from pathlib import Path
|
|
107
|
-
|
|
108
|
-
engine = Engine.from_config_file(Path("cognite-sdk-config.yaml"))
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
#### Option B: Manually
|
|
112
|
-
|
|
113
|
-
```python
|
|
114
|
-
from cognite.client import CogniteClient
|
|
115
|
-
from industrial_model import Engine, DataModelId
|
|
116
|
-
|
|
117
|
-
engine = Engine(
|
|
118
|
-
cognite_client=CogniteClient(), # you need to create a valid cognite client
|
|
119
|
-
data_model_id=DataModelId(external_id="CogniteCore", space="cdf_cdm", version="v1")
|
|
120
|
-
)
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
---
|
|
124
|
-
|
|
125
|
-
## 🔎 Querying Assets by Alias
|
|
126
|
-
|
|
127
|
-
```python
|
|
128
|
-
from industrial_model import select, col
|
|
129
|
-
|
|
130
|
-
statement = (
|
|
131
|
-
select(CogniteAsset)
|
|
132
|
-
.where(col(CogniteAsset.aliases).contains_any_(["my_alias"]))
|
|
133
|
-
.limit(1000)
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
results = engine.query_all_pages(statement)
|
|
137
|
-
```
|
|
138
|
-
|
|
139
|
-
---
|
|
140
|
-
|
|
141
|
-
## 🔗 Filtering by Parent Name
|
|
142
|
-
|
|
143
|
-
```python
|
|
144
|
-
class CogniteAsset(ViewInstance):
|
|
145
|
-
name: str
|
|
146
|
-
description: str
|
|
147
|
-
aliases: list[str]
|
|
148
|
-
parent: CogniteAsset | None = None
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
```python
|
|
152
|
-
statement = (
|
|
153
|
-
select(CogniteAsset)
|
|
154
|
-
.where(
|
|
155
|
-
col(CogniteAsset.aliases).contains_any_(["my_alias"]) &
|
|
156
|
-
col(CogniteAsset.parent).nested_(col(CogniteAsset.name) == "Parent Asset Name")
|
|
157
|
-
)
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
results = engine.query(statement)
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
---
|
|
164
|
-
|
|
165
|
-
## 🔗 Filtering by Parent Name with bool operators
|
|
166
|
-
|
|
167
|
-
```python
|
|
168
|
-
from industrial_model import select, col, or_, and_
|
|
169
|
-
|
|
170
|
-
statement = select(CogniteAsset).where(
|
|
171
|
-
and_(
|
|
172
|
-
col(CogniteAsset.aliases).contains_any_(["my_alias"]),
|
|
173
|
-
or_(
|
|
174
|
-
col(CogniteAsset.parent).nested_(
|
|
175
|
-
col(CogniteAsset.name) == "Parent Asset Name 1"
|
|
176
|
-
),
|
|
177
|
-
col(CogniteAsset.parent).nested_(
|
|
178
|
-
col(CogniteAsset.name) == "Parent Asset Name 2"
|
|
179
|
-
),
|
|
180
|
-
),
|
|
181
|
-
)
|
|
182
|
-
)
|
|
183
|
-
|
|
184
|
-
results = engine.query(statement)
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
---
|
|
188
|
-
|
|
189
|
-
## 🔗 Paginating with cursor and sort by name
|
|
190
|
-
|
|
191
|
-
```python
|
|
192
|
-
class CogniteAsset(ViewInstance):
|
|
193
|
-
name: str
|
|
194
|
-
description: str
|
|
195
|
-
aliases: list[str]
|
|
196
|
-
parent: CogniteAsset | None = None
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
```python
|
|
200
|
-
statement = select(CogniteAsset).asc(CogniteAsset.name).cursor("NEXT_CURSOR")
|
|
201
|
-
|
|
202
|
-
results = engine.query(statement)
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
## 🔗 Proving an alias for a property
|
|
208
|
-
|
|
209
|
-
```python
|
|
210
|
-
from pydantic import Field
|
|
211
|
-
|
|
212
|
-
class CogniteAsset(ViewInstance):
|
|
213
|
-
another_name: str = Field(alias="name")
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
---
|
|
217
|
-
|
|
218
|
-
## 🎯 Optimize Query with View Config - The spaces will be appended in every query
|
|
219
|
-
|
|
220
|
-
```python
|
|
221
|
-
from industrial_model import ViewInstanceConfig
|
|
222
|
-
|
|
223
|
-
class CogniteAsset(ViewInstance):
|
|
224
|
-
view_config = ViewInstanceConfig(
|
|
225
|
-
view_external_id="CogniteAsset", # Maps this class to the 'CogniteAsset' view
|
|
226
|
-
instance_spaces_prefix="Industr-", # Filters queries to spaces with this prefix
|
|
227
|
-
instance_spaces=[
|
|
228
|
-
"Industrial-Data"
|
|
229
|
-
], # Alternatively, explicitly filter by these spaces
|
|
230
|
-
)
|
|
231
|
-
name: str
|
|
232
|
-
description: str
|
|
233
|
-
aliases: list[str]
|
|
234
|
-
parent: CogniteAsset | None = None
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
---
|
|
238
|
-
|
|
239
|
-
## 🔍 Search by Fuzzy Name
|
|
240
|
-
|
|
241
|
-
```python
|
|
242
|
-
from industrial_model import search
|
|
243
|
-
|
|
244
|
-
search_statement = (
|
|
245
|
-
search(CogniteAsset)
|
|
246
|
-
.where(col(CogniteAsset.aliases).contains_any_(["my_alias"]))
|
|
247
|
-
.query_by(
|
|
248
|
-
query="my fuzzy name",
|
|
249
|
-
query_properties=[CogniteAsset.name],
|
|
250
|
-
operator="AND",
|
|
251
|
-
)
|
|
252
|
-
)
|
|
253
|
-
|
|
254
|
-
search_result = engine.search(search_statement)
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
---
|
|
258
|
-
|
|
259
|
-
## 📊 Aggregating Data
|
|
260
|
-
|
|
261
|
-
```python
|
|
262
|
-
from industrial_model import aggregate, AggregatedViewInstance
|
|
263
|
-
|
|
264
|
-
class CogniteAssetByName(AggregatedViewInstance):
|
|
265
|
-
view_config = ViewInstanceConfig(view_external_id="CogniteAsset")
|
|
266
|
-
name: str
|
|
267
|
-
|
|
268
|
-
aggregate_statement = aggregate(CogniteAssetByName, "count").group_by(
|
|
269
|
-
col(CogniteAssetByName.name)
|
|
270
|
-
)
|
|
271
|
-
|
|
272
|
-
aggregate_result = engine.aggregate(aggregate_statement)
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
---
|
|
276
|
-
|
|
277
|
-
## 🗑️ Deleting Instances
|
|
278
|
-
|
|
279
|
-
```python
|
|
280
|
-
instances_to_delete = engine.search(
|
|
281
|
-
search(CogniteAsset)
|
|
282
|
-
.where(col(CogniteAsset.aliases).contains_any_(["my_alias"]))
|
|
283
|
-
.query_by("my fuzzy name", [CogniteAsset.name])
|
|
284
|
-
)
|
|
285
|
-
|
|
286
|
-
engine.delete(instances_to_delete)
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
---
|
|
290
|
-
|
|
291
|
-
## ✏️ Upserting Instances
|
|
292
|
-
|
|
293
|
-
```python
|
|
294
|
-
from industrial_model import WritableViewInstance, InstanceId
|
|
295
|
-
|
|
296
|
-
class CogniteAsset(WritableViewInstance):
|
|
297
|
-
view_config = ViewInstanceConfig(view_external_id="CogniteAsset")
|
|
298
|
-
name: str
|
|
299
|
-
aliases: list[str]
|
|
300
|
-
|
|
301
|
-
def edge_id_factory(self, target_node: InstanceId, edge_type: InstanceId) -> InstanceId:
|
|
302
|
-
return InstanceId(
|
|
303
|
-
external_id=f"{self.external_id}-{target_node.external_id}-{edge_type.external_id}",
|
|
304
|
-
space=self.space,
|
|
305
|
-
)
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
```python
|
|
309
|
-
instances = engine.query_all_pages(
|
|
310
|
-
select(CogniteAsset).where(col(CogniteAsset.aliases).contains_any_(["my_alias"]))
|
|
311
|
-
)
|
|
312
|
-
|
|
313
|
-
for instance in instances:
|
|
314
|
-
instance.aliases.append("new_alias")
|
|
315
|
-
|
|
316
|
-
engine.upsert(instances, replace=False, remove_unset=False)
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
---
|
|
320
|
-
|
|
321
|
-
## ✏️ Async version
|
|
322
|
-
|
|
323
|
-
All methods have a async equivalent version
|
|
324
|
-
|
|
325
|
-
```python
|
|
326
|
-
await engine.query_async(...)
|
|
327
|
-
await engine.query_all_pages_async(...)
|
|
328
|
-
await engine.search_async(...)
|
|
329
|
-
await engine.aggregate_async(...)
|
|
330
|
-
await engine.delete_async(...)
|
|
331
|
-
await engine.upsert_async(...)
|
|
332
|
-
```
|
|
333
|
-
|
|
334
|
-
---
|
|
File without changes
|