evo-objects 0.2.3__tar.gz → 0.3.1__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 (29) hide show
  1. {evo_objects-0.2.3 → evo_objects-0.3.1}/PKG-INFO +6 -4
  2. {evo_objects-0.2.3 → evo_objects-0.3.1}/pyproject.toml +8 -5
  3. {evo_objects-0.2.3 → evo_objects-0.3.1}/src/evo/objects/__init__.py +2 -1
  4. evo_objects-0.3.1/src/evo/objects/client/__init__.py +15 -0
  5. evo_objects-0.2.3/src/evo/objects/client.py → evo_objects-0.3.1/src/evo/objects/client/api_client.py +56 -220
  6. evo_objects-0.3.1/src/evo/objects/client/object_client.py +247 -0
  7. evo_objects-0.3.1/src/evo/objects/client/parse.py +199 -0
  8. {evo_objects-0.2.3 → evo_objects-0.3.1}/src/evo/objects/data.py +118 -10
  9. {evo_objects-0.2.3/src/evo/objects/utils → evo_objects-0.3.1/src/evo/objects/parquet}/__init__.py +11 -20
  10. evo_objects-0.3.1/src/evo/objects/parquet/loader.py +233 -0
  11. evo_objects-0.3.1/src/evo/objects/parquet/types.py +42 -0
  12. evo_objects-0.3.1/src/evo/objects/utils/__init__.py +41 -0
  13. {evo_objects-0.2.3 → evo_objects-0.3.1}/src/evo/objects/utils/data.py +92 -94
  14. {evo_objects-0.2.3 → evo_objects-0.3.1}/src/evo/objects/utils/table_formats.py +1 -2
  15. {evo_objects-0.2.3 → evo_objects-0.3.1}/src/evo/objects/utils/tables.py +12 -11
  16. evo_objects-0.2.3/src/evo/objects/utils/_types.py +0 -82
  17. {evo_objects-0.2.3 → evo_objects-0.3.1}/.gitignore +0 -0
  18. {evo_objects-0.2.3 → evo_objects-0.3.1}/LICENSE.md +0 -0
  19. {evo_objects-0.2.3 → evo_objects-0.3.1}/src/evo/objects/_model_config.py +0 -0
  20. {evo_objects-0.2.3 → evo_objects-0.3.1}/src/evo/objects/endpoints/__init__.py +0 -0
  21. {evo_objects-0.2.3 → evo_objects-0.3.1}/src/evo/objects/endpoints/api/__init__.py +0 -0
  22. {evo_objects-0.2.3 → evo_objects-0.3.1}/src/evo/objects/endpoints/api/data_api.py +0 -0
  23. {evo_objects-0.2.3 → evo_objects-0.3.1}/src/evo/objects/endpoints/api/metadata_api.py +0 -0
  24. {evo_objects-0.2.3 → evo_objects-0.3.1}/src/evo/objects/endpoints/api/objects_api.py +0 -0
  25. {evo_objects-0.2.3 → evo_objects-0.3.1}/src/evo/objects/endpoints/api/stages_api.py +0 -0
  26. {evo_objects-0.2.3 → evo_objects-0.3.1}/src/evo/objects/endpoints/models.py +0 -0
  27. {evo_objects-0.2.3 → evo_objects-0.3.1}/src/evo/objects/exceptions.py +0 -0
  28. {evo_objects-0.2.3 → evo_objects-0.3.1}/src/evo/objects/io.py +0 -0
  29. {evo_objects-0.2.3 → evo_objects-0.3.1}/src/evo/objects/py.typed +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: evo-objects
3
- Version: 0.2.3
3
+ Version: 0.3.1
4
4
  Summary: Python SDK for using the Seequent Evo Geoscience Object API
5
5
  Project-URL: Source, https://github.com/SeequentEvo/evo-python-sdk
6
6
  Project-URL: Tracker, https://github.com/SeequentEvo/evo-python-sdk/issues
@@ -9,15 +9,17 @@ Project-URL: Documentation, https://developer.seequent.com/
9
9
  Author-email: Seequent <support@seequent.com>
10
10
  License-File: LICENSE.md
11
11
  Requires-Python: >=3.10
12
- Requires-Dist: evo-sdk-common>=0.1.0
12
+ Requires-Dist: evo-sdk-common[jmespath]>=0.5.4
13
13
  Requires-Dist: pydantic<3,>=2
14
14
  Provides-Extra: aiohttp
15
- Requires-Dist: evo-sdk-common[aiohttp]>=0.1.0; extra == 'aiohttp'
15
+ Requires-Dist: evo-sdk-common[aiohttp]; extra == 'aiohttp'
16
16
  Provides-Extra: notebooks
17
- Requires-Dist: evo-sdk-common[notebooks]>=0.1.0; extra == 'notebooks'
17
+ Requires-Dist: evo-sdk-common[notebooks]; extra == 'notebooks'
18
18
  Provides-Extra: utils
19
+ Requires-Dist: numpy; extra == 'utils'
19
20
  Requires-Dist: pandas; extra == 'utils'
20
21
  Requires-Dist: pyarrow; extra == 'utils'
22
+ Requires-Dist: pyarrow-stubs; extra == 'utils'
21
23
  Description-Content-Type: text/markdown
22
24
 
23
25
  <p align="center"><a href="https://seequent.com" target="_blank"><picture><source media="(prefers-color-scheme: dark)" srcset="https://developer.seequent.com/img/seequent-logo-dark.svg" alt="Seequent logo" width="400" /><img src="https://developer.seequent.com/img/seequent-logo.svg" alt="Seequent logo" width="400" /></picture></a></p>
@@ -1,7 +1,7 @@
1
1
  [project]
2
2
  name = "evo-objects"
3
3
  description = "Python SDK for using the Seequent Evo Geoscience Object API"
4
- version = "0.2.3"
4
+ version = "0.3.1"
5
5
  requires-python = ">=3.10"
6
6
  license-files = ["LICENSE.md"]
7
7
  dynamic = ["readme"]
@@ -10,7 +10,7 @@ authors = [
10
10
  ]
11
11
 
12
12
  dependencies = [
13
- "evo-sdk-common>=0.1.0",
13
+ "evo-sdk-common[jmespath]>=0.5.4",
14
14
  "pydantic>=2,<3",
15
15
  ]
16
16
 
@@ -21,9 +21,9 @@ Homepage = "https://www.seequent.com/"
21
21
  Documentation = "https://developer.seequent.com/"
22
22
 
23
23
  [project.optional-dependencies]
24
- aiohttp = ["evo-sdk-common[aiohttp]>=0.1.0"]
25
- notebooks = ["evo-sdk-common[notebooks]>=0.1.0"]
26
- utils = ["pyarrow", "pandas"]
24
+ aiohttp = ["evo-sdk-common[aiohttp]"]
25
+ notebooks = ["evo-sdk-common[notebooks]"]
26
+ utils = ["pyarrow", "pyarrow-stubs", "pandas", "numpy"]
27
27
 
28
28
  [dependency-groups]
29
29
  # Dev dependencies. The version is left unspecified so the latest is installed.
@@ -52,6 +52,9 @@ line-length = 120
52
52
  [tool.ruff.lint]
53
53
  extend-select = ["I", "RUF022"]
54
54
 
55
+ [tool.ruff.lint.isort]
56
+ known-first-party = ["evo"]
57
+
55
58
  [build-system]
56
59
  requires = ["hatchling", "hatch-fancy-pypi-readme"]
57
60
  build-backend = "hatchling.build"
@@ -10,7 +10,7 @@
10
10
  # limitations under the License.
11
11
 
12
12
  from .client import DownloadedObject, ObjectAPIClient
13
- from .data import ObjectMetadata, ObjectSchema, ObjectVersion, SchemaVersion, Stage
13
+ from .data import ObjectMetadata, ObjectReference, ObjectSchema, ObjectVersion, SchemaVersion, Stage
14
14
  from .io import ObjectDataDownload, ObjectDataUpload
15
15
 
16
16
  __all__ = [
@@ -19,6 +19,7 @@ __all__ = [
19
19
  "ObjectDataDownload",
20
20
  "ObjectDataUpload",
21
21
  "ObjectMetadata",
22
+ "ObjectReference",
22
23
  "ObjectSchema",
23
24
  "ObjectVersion",
24
25
  "SchemaVersion",
@@ -0,0 +1,15 @@
1
+ # Copyright © 2025 Bentley Systems, Incorporated
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ # http://www.apache.org/licenses/LICENSE-2.0
6
+ # Unless required by applicable law or agreed to in writing, software
7
+ # distributed under the License is distributed on an "AS IS" BASIS,
8
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9
+ # See the License for the specific language governing permissions and
10
+ # limitations under the License.
11
+
12
+ from .api_client import ObjectAPIClient
13
+ from .object_client import DownloadedObject
14
+
15
+ __all__ = ["DownloadedObject", "ObjectAPIClient"]
@@ -11,110 +11,46 @@
11
11
 
12
12
  from __future__ import annotations
13
13
 
14
- from collections.abc import AsyncIterator, Iterator, Sequence
15
- from pathlib import PurePosixPath
14
+ from collections.abc import AsyncIterator, Sequence
16
15
  from uuid import UUID
17
16
 
18
17
  from evo import logging
19
18
  from evo.common import APIConnector, BaseAPIClient, HealthCheckType, ICache, Page, ServiceHealth
20
19
  from evo.common.data import EmptyResponse, Environment, OrderByOperatorEnum
21
- from evo.common.io.exceptions import DataNotFoundError
22
20
  from evo.common.utils import get_service_health, parse_order_by
23
- from evo.workspaces import ServiceUser
24
-
25
- from .data import ObjectMetadata, ObjectOrderByEnum, ObjectSchema, ObjectVersion, OrgObjectMetadata, Stage
26
- from .endpoints import MetadataApi, ObjectsApi, StagesApi
27
- from .endpoints.models import (
28
- GeoscienceObject,
29
- GeoscienceObjectVersion,
30
- GetObjectResponse,
31
- ListedObject,
32
- MetadataUpdateBody,
33
- OrgListedObject,
34
- PostObjectResponse,
35
- UpdateGeoscienceObject,
36
- )
37
- from .exceptions import ObjectUUIDError
38
- from .io import ObjectDataDownload, ObjectDataUpload
39
- from .utils import ObjectDataClient
40
21
 
41
- logger = logging.getLogger("object.client")
42
-
43
- __all__ = [
44
- "DownloadedObject",
45
- "ObjectAPIClient",
46
- ]
47
-
48
-
49
- def _version_from_listed_version(model: GeoscienceObjectVersion) -> ObjectVersion:
50
- """Create an ObjectVersion instance from a generated ListedObject model.
51
-
52
- :param model: The model to create the ObjectVersion instance from.
53
-
54
- :return: An ObjectVersion instance.
55
- """
56
- created_by = None if model.created_by is None else ServiceUser.from_model(model.created_by) # type: ignore
57
- stage = None if model.stage is None else Stage.from_model(model.stage)
58
- return ObjectVersion(
59
- version_id=model.version_id,
60
- created_at=model.created_at,
61
- created_by=created_by,
62
- stage=stage,
63
- )
64
-
65
-
66
- class DownloadedObject:
67
- """A downloaded geoscience object."""
68
-
69
- def __init__(
70
- self, object_: GeoscienceObject, metadata: ObjectMetadata, urls_by_name: dict[str, str], connector: APIConnector
71
- ) -> None:
72
- self._object = object_
73
- self._metadata = metadata
74
- self._urls_by_name = urls_by_name
75
- self._connector = connector
76
-
77
- @property
78
- def schema(self) -> ObjectSchema:
79
- """The schema of the object."""
80
- return self._metadata.schema_id
81
-
82
- @property
83
- def metadata(self) -> ObjectMetadata:
84
- """The metadata of the object."""
85
- return self._metadata
86
-
87
- def as_dict(self) -> dict:
88
- """Get this object as a dictionary."""
89
- return self._object.model_dump(mode="python", by_alias=True)
90
-
91
- def prepare_data_download(self, data_identifiers: Sequence[str | UUID]) -> Iterator[ObjectDataDownload]:
92
- """Prepare to download multiple data files from the geoscience object service, for this object.
93
-
94
- Any data IDs that are not associated with the requested object will raise a DataNotFoundError.
95
-
96
- :param data_identifiers: A list of sha256 digests or UUIDs for the data to be downloaded.
22
+ from ..data import ObjectMetadata, ObjectOrderByEnum, ObjectReference, ObjectVersion, OrgObjectMetadata, Stage
23
+ from ..endpoints import MetadataApi, ObjectsApi, StagesApi
24
+ from ..endpoints.models import GeoscienceObject, MetadataUpdateBody, UpdateGeoscienceObject
25
+ from ..exceptions import ObjectUUIDError
26
+ from ..io import ObjectDataDownload, ObjectDataUpload
27
+ from . import parse
28
+ from .object_client import DownloadedObject
29
+
30
+ try:
31
+ from ..utils import ObjectDataClient
32
+ except ImportError:
33
+ _DATA_CLIENT_AVAILABLE = False
34
+ else:
35
+ _DATA_CLIENT_AVAILABLE = True
97
36
 
98
- :return: An iterator of data download contexts that can be used to download the data.
37
+ logger = logging.getLogger("object.client")
99
38
 
100
- :raises DataNotFoundError: If any requested data ID is not associated with this object.
101
- """
102
- try:
103
- filtered_urls_by_name = {str(name): self._urls_by_name[str(name)] for name in data_identifiers}
104
- except KeyError as exc:
105
- raise DataNotFoundError(f"Unable to find the requested data: {exc.args[0]}") from exc
106
- for ctx in ObjectDataDownload._create_multiple(
107
- connector=self._connector, metadata=self._metadata, urls_by_name=filtered_urls_by_name
108
- ):
109
- yield ctx
39
+ __all__ = ["ObjectAPIClient"]
110
40
 
111
41
 
112
42
  class ObjectAPIClient(BaseAPIClient):
113
- def __init__(self, environment: Environment, connector: APIConnector) -> None:
43
+ def __init__(self, environment: Environment, connector: APIConnector, cache: ICache | None = None) -> None:
44
+ """
45
+ :param environment: The target Evo environment, providing org and workspace IDs.
46
+ :param connector: The API connector to use for making API calls.
47
+ :param cache: An optional cache to use for data downloads.
48
+ """
114
49
  super().__init__(environment, connector)
115
50
  self._stages_api = StagesApi(connector=connector)
116
51
  self._objects_api = ObjectsApi(connector=connector)
117
52
  self._metadata_api = MetadataApi(connector=connector)
53
+ self._cache = cache
118
54
 
119
55
  async def get_service_health(self, check_type: HealthCheckType = HealthCheckType.FULL) -> ServiceHealth:
120
56
  """Get the health of the geoscience object service.
@@ -128,79 +64,6 @@ class ObjectAPIClient(BaseAPIClient):
128
64
  """
129
65
  return await get_service_health(self._connector, "geoscience-object", check_type=check_type)
130
66
 
131
- def _metadata_from_listed_object(self, model: ListedObject) -> ObjectMetadata:
132
- """Create an ObjectMetadata instance from a generated ListedObject model.
133
-
134
- :param model: The model to create the ObjectMetadata instance from.
135
-
136
- :return: An ObjectMetadata instance.
137
- """
138
- created_by = None if model.created_by is None else ServiceUser.from_model(model.created_by)
139
- modified_by = None if model.modified_by is None else ServiceUser.from_model(model.modified_by)
140
- stage = None if model.stage is None else Stage.from_model(model.stage)
141
- return ObjectMetadata(
142
- environment=self._environment,
143
- id=model.object_id,
144
- name=model.name,
145
- created_at=model.created_at,
146
- created_by=created_by,
147
- modified_at=model.modified_at,
148
- modified_by=modified_by,
149
- parent=model.path.rstrip("/"),
150
- schema_id=ObjectSchema.from_id(model.schema_),
151
- version_id=model.version_id,
152
- stage=stage,
153
- )
154
-
155
- def _metadata_from_org_listed_object(self, model: OrgListedObject) -> OrgObjectMetadata:
156
- """Create an OrgObjectMetadata instance from a generated OrgListedObject model.
157
-
158
- :param model: The model to create the OrgObjectMetadata instance from.
159
-
160
- :return: An OrgObjectMetadata instance.
161
- """
162
- created_by = None if model.created_by is None else ServiceUser.from_model(model.created_by)
163
- modified_by = None if model.modified_by is None else ServiceUser.from_model(model.modified_by)
164
- stage = None if model.stage is None else Stage.from_model(model.stage)
165
- return OrgObjectMetadata(
166
- environment=self._environment,
167
- workspace_id=model.workspace_id,
168
- workspace_name=model.workspace_name,
169
- id=model.object_id,
170
- name=model.name,
171
- created_at=model.created_at,
172
- created_by=created_by,
173
- modified_at=model.modified_at,
174
- modified_by=modified_by,
175
- schema_id=ObjectSchema.from_id(model.schema_),
176
- stage=stage,
177
- )
178
-
179
- def _metadata_from_endpoint_model(self, model: GetObjectResponse | PostObjectResponse) -> ObjectMetadata:
180
- """Create an ObjectMetadata instance from a generated GetObjectResponse or PostObjectResponse model.
181
-
182
- :param model: The model to create the ObjectMetadata instance from.
183
-
184
- :return: An ObjectMetadata instance.
185
- """
186
- object_path = PurePosixPath(model.object_path)
187
- created_by = None if model.created_by is None else ServiceUser.from_model(model.created_by)
188
- modified_by = None if model.modified_by is None else ServiceUser.from_model(model.modified_by)
189
- stage = None if model.stage is None else Stage.from_model(model.stage)
190
- return ObjectMetadata(
191
- environment=self._environment,
192
- id=model.object_id,
193
- name=object_path.name,
194
- created_at=model.created_at,
195
- created_by=created_by,
196
- modified_at=model.modified_at,
197
- modified_by=modified_by,
198
- parent=str(object_path.parent),
199
- schema_id=ObjectSchema.from_id(model.object.schema_),
200
- version_id=model.version_id,
201
- stage=stage,
202
- )
203
-
204
67
  async def list_objects(
205
68
  self,
206
69
  offset: int = 0,
@@ -238,12 +101,7 @@ class ObjectAPIClient(BaseAPIClient):
238
101
  request_timeout=request_timeout,
239
102
  deleted=deleted,
240
103
  )
241
- return Page(
242
- offset=offset,
243
- limit=limit,
244
- total=response.total,
245
- items=[self._metadata_from_listed_object(model) for model in response.objects],
246
- )
104
+ return parse.page_of_metadata(response, self._environment)
247
105
 
248
106
  async def list_all_objects(
249
107
  self,
@@ -320,17 +178,7 @@ class ObjectAPIClient(BaseAPIClient):
320
178
  permitted_workspaces_only=True,
321
179
  deleted=deleted,
322
180
  )
323
- return Page(
324
- offset=offset,
325
- limit=limit,
326
- total=response.total,
327
- items=[self._metadata_from_org_listed_object(model) for model in response.objects],
328
- )
329
-
330
- @staticmethod
331
- def _get_object_versions(response: GetObjectResponse) -> list[ObjectVersion]:
332
- object_versions = [_version_from_listed_version(model) for model in response.versions]
333
- return sorted(object_versions, key=lambda v: v.created_at, reverse=True)
181
+ return parse.page_of_metadata(response, self._environment)
334
182
 
335
183
  async def list_versions_by_path(
336
184
  self, path: str, request_timeout: int | float | tuple[int | float, int | float] | None = None
@@ -350,7 +198,7 @@ class ObjectAPIClient(BaseAPIClient):
350
198
  include_versions=True,
351
199
  request_timeout=request_timeout,
352
200
  )
353
- return self._get_object_versions(response)
201
+ return parse.versions(response)
354
202
 
355
203
  async def list_versions_by_id(
356
204
  self, object_id: UUID, request_timeout: int | float | tuple[int | float, int | float] | None = None
@@ -370,7 +218,7 @@ class ObjectAPIClient(BaseAPIClient):
370
218
  include_versions=True,
371
219
  request_timeout=request_timeout,
372
220
  )
373
- return self._get_object_versions(response)
221
+ return parse.versions(response)
374
222
 
375
223
  async def prepare_data_upload(self, data_identifiers: Sequence[str | UUID]) -> AsyncIterator[ObjectDataUpload]:
376
224
  """Prepare to upload multiple data files to the geoscience object service.
@@ -416,20 +264,23 @@ class ObjectAPIClient(BaseAPIClient):
416
264
  for ctx in downloaded_object.prepare_data_download(data_identifiers):
417
265
  yield ctx
418
266
 
419
- def get_data_client(self, cache: ICache) -> ObjectDataClient:
420
- """Get a data client for the geoscience object service.
267
+ if _DATA_CLIENT_AVAILABLE:
268
+ # Optional data client functionality, enabled if the data client dependencies are installed.
421
269
 
422
- The data client provides a high-level interface for uploading and downloading data that is referenced in
423
- geoscience objects, and caching the data locally. It depends on the optional dependency `pyarrow`, which is
424
- not installed by default. This dependency can be installed with `pip install evo-objects[utils]`.
270
+ def get_data_client(self, cache: ICache) -> ObjectDataClient:
271
+ """Get a data client for the geoscience object service.
425
272
 
426
- :param cache: The cache to use for data downloads.
273
+ The data client provides a high-level interface for uploading and downloading data that is referenced in
274
+ geoscience objects, and caching the data locally. It depends on the optional dependency `pyarrow`, which is
275
+ not installed by default. This dependency can be installed with `pip install evo-objects[utils]`.
427
276
 
428
- :return: An ObjectDataClient instance.
277
+ :param cache: The cache to use for data downloads.
429
278
 
430
- :raises RuntimeError: If the `pyarrow` package is not installed.
431
- """
432
- return ObjectDataClient(environment=self._environment, connector=self._connector, cache=cache)
279
+ :return: An ObjectDataClient instance.
280
+
281
+ :raises RuntimeError: If the `pyarrow` package is not installed.
282
+ """
283
+ return ObjectDataClient(environment=self._environment, connector=self._connector, cache=cache)
433
284
 
434
285
  async def create_geoscience_object(
435
286
  self, path: str, object_dict: dict, request_timeout: int | float | tuple[int | float, int | float] | None = None
@@ -461,7 +312,7 @@ class ObjectAPIClient(BaseAPIClient):
461
312
  request_timeout=request_timeout,
462
313
  )
463
314
  object_dict["uuid"] = result.object_id
464
- return self._metadata_from_endpoint_model(result)
315
+ return parse.object_metadata(result, self._environment)
465
316
 
466
317
  async def move_geoscience_object(
467
318
  self, path: str, object_dict: dict, request_timeout: int | float | tuple[int | float, int | float] | None = None
@@ -488,7 +339,7 @@ class ObjectAPIClient(BaseAPIClient):
488
339
  geoscience_object=object_for_upload,
489
340
  request_timeout=request_timeout,
490
341
  )
491
- return self._metadata_from_endpoint_model(result)
342
+ return parse.object_metadata(result, self._environment)
492
343
 
493
344
  async def update_geoscience_object(
494
345
  self, object_dict: dict, request_timeout: int | float | tuple[int | float, int | float] | None = None
@@ -514,18 +365,7 @@ class ObjectAPIClient(BaseAPIClient):
514
365
  update_geoscience_object=object_for_upload,
515
366
  request_timeout=request_timeout,
516
367
  )
517
- return self._metadata_from_endpoint_model(result)
518
-
519
- def _downloaded_object_from_response(self, response: GetObjectResponse) -> DownloadedObject:
520
- """Parse object metadata and a geoscience object model instance from a get object response
521
-
522
- :param response: The response from one of the get object endpoints.
523
-
524
- :return: A tuple containing the object metadata and a data model of the requested geoscience object.
525
- """
526
- metadata = self._metadata_from_endpoint_model(response)
527
- urls_by_name = {getattr(link, "name", link.id): link.download_url for link in response.links.data}
528
- return DownloadedObject(response.object, metadata, urls_by_name, self._connector)
368
+ return parse.object_metadata(result, self._environment)
529
369
 
530
370
  async def download_object_by_path(
531
371
  self,
@@ -543,15 +383,13 @@ class ObjectAPIClient(BaseAPIClient):
543
383
 
544
384
  :return: A tuple containing the object metadata and a data model of the requested geoscience object.
545
385
  """
546
- response = await self._objects_api.get_object(
547
- org_id=str(self._environment.org_id),
548
- workspace_id=str(self._environment.workspace_id),
549
- objects_path=path,
550
- version=version,
551
- additional_headers={"Accept-Encoding": "gzip"},
386
+ reference = ObjectReference.new(environment=self._environment, object_path=path, version_id=version)
387
+ return await DownloadedObject.from_reference(
388
+ connector=self._connector,
389
+ reference=reference,
390
+ cache=self._cache,
552
391
  request_timeout=request_timeout,
553
392
  )
554
- return self._downloaded_object_from_response(response)
555
393
 
556
394
  async def download_object_by_id(
557
395
  self,
@@ -569,15 +407,13 @@ class ObjectAPIClient(BaseAPIClient):
569
407
 
570
408
  :return: A tuple containing the object metadata and a data model of the requested geoscience object.
571
409
  """
572
- response = await self._objects_api.get_object_by_id(
573
- org_id=str(self._environment.org_id),
574
- workspace_id=str(self._environment.workspace_id),
575
- object_id=str(object_id),
576
- version=version,
577
- additional_headers={"Accept-Encoding": "gzip"},
410
+ reference = ObjectReference.new(environment=self._environment, object_id=object_id, version_id=version)
411
+ return await DownloadedObject.from_reference(
412
+ connector=self._connector,
413
+ reference=reference,
414
+ cache=self._cache,
578
415
  request_timeout=request_timeout,
579
416
  )
580
- return self._downloaded_object_from_response(response)
581
417
 
582
418
  async def get_latest_object_versions(
583
419
  self,
@@ -668,14 +504,14 @@ class ObjectAPIClient(BaseAPIClient):
668
504
  # If the restore happened with a rename, the response will be the metadata of the restored object
669
505
  if isinstance(result, EmptyResponse):
670
506
  return None
671
- return self._metadata_from_endpoint_model(result)
507
+ return parse.object_metadata(result, self._environment)
672
508
 
673
509
  async def list_stages(self) -> list[Stage]:
674
510
  """List all available stages in the organisation.
675
511
 
676
512
  :return: A list of all available stages."""
677
513
  response = await self._stages_api.list_stages(org_id=str(self._environment.org_id))
678
- return [Stage.from_model(model) for model in response.stages]
514
+ return [parse.stage(model) for model in response.stages]
679
515
 
680
516
  async def set_stage(self, object_id: UUID, version_id: int, stage_id: UUID) -> None:
681
517
  """Set the stage of a specific version of a geoscience object.