industrial-model 0.1.3__tar.gz → 0.1.5__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 (39) hide show
  1. industrial_model-0.1.5/.vscode/settings.json +8 -0
  2. {industrial_model-0.1.3 → industrial_model-0.1.5}/PKG-INFO +24 -4
  3. {industrial_model-0.1.3 → industrial_model-0.1.5}/README.md +23 -3
  4. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/cognite_adapters/optimizer.py +5 -2
  5. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/cognite_adapters/query_mapper.py +16 -14
  6. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/models/__init__.py +2 -0
  7. {industrial_model-0.1.3/industrial_model/cognite_adapters → industrial_model-0.1.5/industrial_model/models}/schemas.py +1 -3
  8. {industrial_model-0.1.3 → industrial_model-0.1.5}/pyproject.toml +2 -1
  9. {industrial_model-0.1.3 → industrial_model-0.1.5}/uv.lock +45 -1
  10. {industrial_model-0.1.3 → industrial_model-0.1.5}/.gitignore +0 -0
  11. {industrial_model-0.1.3 → industrial_model-0.1.5}/.python-version +0 -0
  12. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/__init__.py +0 -0
  13. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/cognite_adapters/__init__.py +0 -0
  14. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/cognite_adapters/filter_mapper.py +0 -0
  15. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/cognite_adapters/query_result_mapper.py +0 -0
  16. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/cognite_adapters/sort_mapper.py +0 -0
  17. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/cognite_adapters/utils.py +0 -0
  18. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/cognite_adapters/view_mapper.py +0 -0
  19. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/config.py +0 -0
  20. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/constants.py +0 -0
  21. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/engines/__init__.py +0 -0
  22. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/engines/async_engine.py +0 -0
  23. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/engines/engine.py +0 -0
  24. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/models/base.py +0 -0
  25. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/models/entities.py +0 -0
  26. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/py.typed +0 -0
  27. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/queries/__init__.py +0 -0
  28. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/queries/models.py +0 -0
  29. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/queries/params.py +0 -0
  30. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/statements/__init__.py +0 -0
  31. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/statements/expressions.py +0 -0
  32. {industrial_model-0.1.3 → industrial_model-0.1.5}/industrial_model/utils.py +0 -0
  33. {industrial_model-0.1.3 → industrial_model-0.1.5}/scripts/build.sh +0 -0
  34. {industrial_model-0.1.3 → industrial_model-0.1.5}/scripts/format.sh +0 -0
  35. {industrial_model-0.1.3 → industrial_model-0.1.5}/scripts/lint.sh +0 -0
  36. {industrial_model-0.1.3 → industrial_model-0.1.5}/tests/__init__.py +0 -0
  37. {industrial_model-0.1.3 → industrial_model-0.1.5}/tests/cognite-sdk-config.yaml +0 -0
  38. {industrial_model-0.1.3 → industrial_model-0.1.5}/tests/hubs.py +0 -0
  39. {industrial_model-0.1.3 → industrial_model-0.1.5}/tests/tests_adapter.py +0 -0
@@ -0,0 +1,8 @@
1
+ {
2
+ "editor.defaultFormatter": "charliermarsh.ruff",
3
+ "editor.formatOnSave": true,
4
+ "editor.codeActionsOnSave": {
5
+ "source.fixAll": "always",
6
+ "source.organizeImports": "always"
7
+ }
8
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: industrial-model
3
- Version: 0.1.3
3
+ Version: 0.1.5
4
4
  Summary: Industrial Model ORM
5
5
  Author-email: Lucas Alves <lucasrosaalves@gmail.com>
6
6
  Classifier: Programming Language :: Python
@@ -81,7 +81,27 @@ class Country(ViewInstance):
81
81
  class Person(ViewInstance):
82
82
  name: str
83
83
  birthday: datetime.date
84
- livesIn: Country
84
+ lives_in: Country
85
+ cars: list[Car]
86
+
87
+
88
+ # By default, the ORM maps the class name to the view in the data model.
89
+ # You can override this behavior using the `view_config` field.
90
+
91
+ # For improved query performance, you can configure `instance_spaces` or `instance_spaces_prefix`
92
+ # in the `view_config`. These options include space filters in the generated queries,
93
+ # which can significantly reduce response times when working with large datasets.
94
+
95
+ class AnotherPerson(ViewInstance):
96
+ view_config = ViewInstanceConfig(
97
+ view_external_id="Person", # Maps this class to the 'Person' view
98
+ instance_spaces_prefix="Industr-", # Filters queries to spaces with this prefix
99
+ instance_spaces=["Industrial-Data"] # Alternatively, explicitly filter by these spaces
100
+ )
101
+
102
+ name: str
103
+ birthday: datetime.date
104
+ lives_in: Country
85
105
  cars: list[Car]
86
106
 
87
107
 
@@ -128,9 +148,9 @@ result = engine.query(statement)
128
148
  # 4. Nested filtering using relationships
129
149
  statement = select(Person).where(
130
150
  or_(
131
- col(Person.livesIn).nested_(Country.name == "usa"),
151
+ col(Person.lives_in).nested_(Country.name == "usa"),
132
152
  and_(
133
- col(Person.livesIn).nested_(col(Country.name).equals_("bra")),
153
+ col(Person.lives_in).nested_(col(Country.name).equals_("bra")),
134
154
  col(Person.birthday).equals_("2023-01-01")
135
155
  )
136
156
  )
@@ -61,7 +61,27 @@ class Country(ViewInstance):
61
61
  class Person(ViewInstance):
62
62
  name: str
63
63
  birthday: datetime.date
64
- livesIn: Country
64
+ lives_in: Country
65
+ cars: list[Car]
66
+
67
+
68
+ # By default, the ORM maps the class name to the view in the data model.
69
+ # You can override this behavior using the `view_config` field.
70
+
71
+ # For improved query performance, you can configure `instance_spaces` or `instance_spaces_prefix`
72
+ # in the `view_config`. These options include space filters in the generated queries,
73
+ # which can significantly reduce response times when working with large datasets.
74
+
75
+ class AnotherPerson(ViewInstance):
76
+ view_config = ViewInstanceConfig(
77
+ view_external_id="Person", # Maps this class to the 'Person' view
78
+ instance_spaces_prefix="Industr-", # Filters queries to spaces with this prefix
79
+ instance_spaces=["Industrial-Data"] # Alternatively, explicitly filter by these spaces
80
+ )
81
+
82
+ name: str
83
+ birthday: datetime.date
84
+ lives_in: Country
65
85
  cars: list[Car]
66
86
 
67
87
 
@@ -108,9 +128,9 @@ result = engine.query(statement)
108
128
  # 4. Nested filtering using relationships
109
129
  statement = select(Person).where(
110
130
  or_(
111
- col(Person.livesIn).nested_(Country.name == "usa"),
131
+ col(Person.lives_in).nested_(Country.name == "usa"),
112
132
  and_(
113
- col(Person.livesIn).nested_(col(Country.name).equals_("bra")),
133
+ col(Person.lives_in).nested_(col(Country.name).equals_("bra")),
114
134
  col(Person.birthday).equals_("2023-01-01")
115
135
  )
116
136
  )
@@ -49,8 +49,11 @@ class QueryOptimizer:
49
49
  where_clause, BoolExpression
50
50
  ) and self._has_space_filter(where_clause.filters):
51
51
  return True
52
- elif isinstance(where_clause, LeafExpression):
53
- return where_clause.property == SPACE_PROPERTY
52
+ elif (
53
+ isinstance(where_clause, LeafExpression)
54
+ and where_clause.property == SPACE_PROPERTY
55
+ ):
56
+ return True
54
57
 
55
58
  return False
56
59
 
@@ -21,13 +21,12 @@ from cognite.client.data_classes.data_modeling.views import (
21
21
  )
22
22
 
23
23
  from industrial_model.constants import EDGE_MARKER, MAX_LIMIT, NESTED_SEP
24
- from industrial_model.models import TViewInstance
24
+ from industrial_model.models import TViewInstance, get_schema_properties
25
25
  from industrial_model.statements import Statement
26
26
 
27
27
  from .filter_mapper import (
28
28
  FilterMapper,
29
29
  )
30
- from .schemas import get_schema_properties
31
30
  from .sort_mapper import SortMapper
32
31
  from .view_mapper import ViewMapper
33
32
 
@@ -135,19 +134,22 @@ class QueryMapper:
135
134
  with_,
136
135
  select_,
137
136
  )
138
- if not props:
139
- with_[property_key] = NodeResultSetExpression(
140
- from_=key,
141
- direction="inwards",
142
- through=property.source.as_property_ref(
143
- property.through.property
144
- ),
145
- limit=MAX_LIMIT,
146
- )
147
137
 
148
- select_[property_key] = self._get_select(
149
- property.source, props
150
- )
138
+ with_[property_key] = NodeResultSetExpression(
139
+ from_=key,
140
+ direction="inwards",
141
+ through=property.source.as_property_ref(
142
+ property.through.property
143
+ ),
144
+ limit=MAX_LIMIT,
145
+ )
146
+
147
+ if property.through.property not in props:
148
+ props.append(property.through.property)
149
+
150
+ select_[property_key] = self._get_select(
151
+ property.source, props
152
+ )
151
153
  elif isinstance(property, EdgeConnection) and property.source:
152
154
  edge_property_key = f"{property_key}{NESTED_SEP}{EDGE_MARKER}"
153
155
 
@@ -7,6 +7,7 @@ from .entities import (
7
7
  ViewInstance,
8
8
  ViewInstanceConfig,
9
9
  )
10
+ from .schemas import get_schema_properties
10
11
 
11
12
  __all__ = [
12
13
  "RootModel",
@@ -16,4 +17,5 @@ __all__ = [
16
17
  "ValidationMode",
17
18
  "PaginatedResult",
18
19
  "ViewInstanceConfig",
20
+ "get_schema_properties",
19
21
  ]
@@ -12,14 +12,12 @@ from typing import (
12
12
 
13
13
  from pydantic import BaseModel
14
14
 
15
- from industrial_model.constants import NESTED_SEP
16
-
17
15
  TBaseModel = TypeVar("TBaseModel", bound=BaseModel)
18
16
 
19
17
 
20
18
  def get_schema_properties(
21
19
  cls: type[TBaseModel],
22
- nested_separator: str = NESTED_SEP,
20
+ nested_separator: str,
23
21
  prefix: str | None = None,
24
22
  ) -> list[str]:
25
23
  data = _get_type_properties(cls) or {}
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "industrial-model"
3
- version = "0.1.3"
3
+ version = "0.1.5"
4
4
  description = "Industrial Model ORM"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -26,6 +26,7 @@ build-backend = "hatchling.build"
26
26
  dev-dependencies = [
27
27
  "dotenv>=0.9.9",
28
28
  "mypy>=1.15.0",
29
+ "pytest>=8.3.5",
29
30
  "pyyaml>=6.0.2",
30
31
  "ruff>=0.11.8",
31
32
  "types-pyyaml>=6.0.12.20250402",
@@ -143,6 +143,15 @@ wheels = [
143
143
  { url = "https://files.pythonhosted.org/packages/85/08/38477bff9eaa7a153847718d50faea698ef68a998a3c69fdba09ad4b919a/cognite_sdk-7.75.0-py3-none-any.whl", hash = "sha256:0696ff265e11ae3a2351760def6f2bd04df1e2524bf855c5d7920a76b123d5e0", size = 623162 },
144
144
  ]
145
145
 
146
+ [[package]]
147
+ name = "colorama"
148
+ version = "0.4.6"
149
+ source = { registry = "https://pypi.org/simple" }
150
+ sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 }
151
+ wheels = [
152
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
153
+ ]
154
+
146
155
  [[package]]
147
156
  name = "cryptography"
148
157
  version = "44.0.3"
@@ -206,7 +215,7 @@ wheels = [
206
215
 
207
216
  [[package]]
208
217
  name = "industrial-model"
209
- version = "0.1.0"
218
+ version = "0.1.5"
210
219
  source = { editable = "." }
211
220
  dependencies = [
212
221
  { name = "anyio" },
@@ -218,6 +227,7 @@ dependencies = [
218
227
  dev = [
219
228
  { name = "dotenv" },
220
229
  { name = "mypy" },
230
+ { name = "pytest" },
221
231
  { name = "pyyaml" },
222
232
  { name = "ruff" },
223
233
  { name = "types-pyyaml" },
@@ -234,11 +244,21 @@ requires-dist = [
234
244
  dev = [
235
245
  { name = "dotenv", specifier = ">=0.9.9" },
236
246
  { name = "mypy", specifier = ">=1.15.0" },
247
+ { name = "pytest", specifier = ">=8.3.5" },
237
248
  { name = "pyyaml", specifier = ">=6.0.2" },
238
249
  { name = "ruff", specifier = ">=0.11.8" },
239
250
  { name = "types-pyyaml", specifier = ">=6.0.12.20250402" },
240
251
  ]
241
252
 
253
+ [[package]]
254
+ name = "iniconfig"
255
+ version = "2.1.0"
256
+ source = { registry = "https://pypi.org/simple" }
257
+ sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793 }
258
+ wheels = [
259
+ { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050 },
260
+ ]
261
+
242
262
  [[package]]
243
263
  name = "msal"
244
264
  version = "1.32.3"
@@ -311,6 +331,15 @@ wheels = [
311
331
  { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469 },
312
332
  ]
313
333
 
334
+ [[package]]
335
+ name = "pluggy"
336
+ version = "1.6.0"
337
+ source = { registry = "https://pypi.org/simple" }
338
+ sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412 }
339
+ wheels = [
340
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538 },
341
+ ]
342
+
314
343
  [[package]]
315
344
  name = "protobuf"
316
345
  version = "6.31.0"
@@ -428,6 +457,21 @@ crypto = [
428
457
  { name = "cryptography" },
429
458
  ]
430
459
 
460
+ [[package]]
461
+ name = "pytest"
462
+ version = "8.3.5"
463
+ source = { registry = "https://pypi.org/simple" }
464
+ dependencies = [
465
+ { name = "colorama", marker = "sys_platform == 'win32'" },
466
+ { name = "iniconfig" },
467
+ { name = "packaging" },
468
+ { name = "pluggy" },
469
+ ]
470
+ sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891 }
471
+ wheels = [
472
+ { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634 },
473
+ ]
474
+
431
475
  [[package]]
432
476
  name = "python-dotenv"
433
477
  version = "1.1.0"