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.
@@ -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.1.dist-info/METADATA,sha256=Ic7qCi1S_QRM_6tonlKbj4UYFGxqW0NHcaT3iQuDmrU,7770
34
- industrial_model-1.2.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
35
- industrial_model-1.2.1.dist-info/licenses/LICENSE,sha256=BCHCZ1Qo7m4YvAEIQqtVBI3NebFJdZ8_7m_cxInIlN0,4934
36
- industrial_model-1.2.1.dist-info/RECORD,,
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,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.27.0
2
+ Generator: hatchling 1.28.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -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
- ---