evo-objects 0.6.5__tar.gz → 0.6.6__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.
- {evo_objects-0.6.5 → evo_objects-0.6.6}/PKG-INFO +2 -2
- {evo_objects-0.6.5 → evo_objects-0.6.6}/pyproject.toml +2 -2
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/exceptions.py +25 -1
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/typed/base.py +21 -7
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/utils/data.py +29 -25
- {evo_objects-0.6.5 → evo_objects-0.6.6}/.gitignore +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/LICENSE.md +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/__init__.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/_model_config.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/client/__init__.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/client/api_client.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/client/object_client.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/client/parse.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/data.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/endpoints/__init__.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/endpoints/api/__init__.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/endpoints/api/data_api.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/endpoints/api/metadata_api.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/endpoints/api/objects_api.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/endpoints/api/stages_api.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/endpoints/models.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/io.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/parquet/__init__.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/parquet/loader.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/py.typed +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/typed/__init__.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/typed/_data.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/typed/_downhole.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/typed/_grid.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/typed/_model.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/typed/_prefetch.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/typed/_utils.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/typed/attributes.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/typed/block_model_ref.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/typed/downhole_collection.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/typed/downhole_intervals.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/typed/exceptions.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/typed/pointset.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/typed/regular_grid.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/typed/regular_masked_grid.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/typed/spatial.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/typed/tensor_grid.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/typed/types.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/typed/variogram.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/utils/__init__.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/utils/downhole.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/utils/table_formats.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/utils/tables.py +0 -0
- {evo_objects-0.6.5 → evo_objects-0.6.6}/src/evo/objects/utils/types.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: evo-objects
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.6
|
|
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,7 +9,7 @@ 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[jmespath]>=0.5.
|
|
12
|
+
Requires-Dist: evo-sdk-common[jmespath]>=0.5.31
|
|
13
13
|
Requires-Dist: pydantic<3,>=2
|
|
14
14
|
Provides-Extra: aiohttp
|
|
15
15
|
Requires-Dist: evo-sdk-common[aiohttp]; extra == 'aiohttp'
|
|
@@ -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.6.
|
|
4
|
+
version = "0.6.6"
|
|
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[jmespath]>=0.5.
|
|
13
|
+
"evo-sdk-common[jmespath]>=0.5.31",
|
|
14
14
|
"pydantic>=2,<3",
|
|
15
15
|
]
|
|
16
16
|
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
from uuid import UUID
|
|
13
13
|
|
|
14
|
-
from evo.common.exceptions import CustomTypedError, EvoClientException
|
|
14
|
+
from evo.common.exceptions import BadRequestException, CustomTypedError, EvoClientException
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class SchemaIDFormatError(EvoClientException):
|
|
@@ -41,6 +41,30 @@ class SchemaValidationError(EvoClientException):
|
|
|
41
41
|
"""Failed to validate data against a geoscience object schema"""
|
|
42
42
|
|
|
43
43
|
|
|
44
|
+
class InvalidGeoscienceObjectError(CustomTypedError, BadRequestException):
|
|
45
|
+
"""The service rejected an object that does not match its geoscience object schema."""
|
|
46
|
+
|
|
47
|
+
TYPE_ID = "/geoscienceobject/schemas/invalid-object"
|
|
48
|
+
|
|
49
|
+
def __str__(self) -> str:
|
|
50
|
+
error_message = super().__str__()
|
|
51
|
+
detail = self.detail
|
|
52
|
+
if detail:
|
|
53
|
+
error_message = error_message.removesuffix(f"\nDetail: {detail}")
|
|
54
|
+
if json_path := self.content.get("json_path"):
|
|
55
|
+
error_message += f"\nInvalid value at: {json_path}"
|
|
56
|
+
if schema_path := self.content.get("schema_path"):
|
|
57
|
+
error_message += f"\nFailed schema rule: {schema_path}"
|
|
58
|
+
if detail:
|
|
59
|
+
if len(detail) > 500:
|
|
60
|
+
detail = (
|
|
61
|
+
f"{detail[:250]} ... [omitted] ... {detail[-250:]}\n"
|
|
62
|
+
"(For the full detail, catch this exception as exc and run print(exc.detail).)"
|
|
63
|
+
)
|
|
64
|
+
error_message += f"\nDetail: {detail}"
|
|
65
|
+
return error_message
|
|
66
|
+
|
|
67
|
+
|
|
44
68
|
class ObjectAlreadyExistsError(CustomTypedError):
|
|
45
69
|
TYPE_ID = "/geoscienceobject/objects/already-exists"
|
|
46
70
|
|
|
@@ -19,8 +19,9 @@ from dataclasses import dataclass
|
|
|
19
19
|
from typing import Annotated, Any, ClassVar
|
|
20
20
|
from uuid import UUID
|
|
21
21
|
|
|
22
|
-
from evo import jmespath
|
|
22
|
+
from evo import jmespath, logging
|
|
23
23
|
from evo.common import IContext, IFeedback, StaticContext
|
|
24
|
+
from evo.common.exceptions import error_context
|
|
24
25
|
from evo.common.utils import NoFeedback
|
|
25
26
|
from evo.objects import DownloadedObject, ObjectMetadata, ObjectReference, ObjectSchema, SchemaVersion
|
|
26
27
|
|
|
@@ -36,6 +37,8 @@ if sys.version_info >= (3, 11):
|
|
|
36
37
|
else:
|
|
37
38
|
from typing_extensions import Self
|
|
38
39
|
|
|
40
|
+
logger = logging.getLogger("object")
|
|
41
|
+
|
|
39
42
|
__all__ = [
|
|
40
43
|
"BaseObject",
|
|
41
44
|
"BaseObjectData",
|
|
@@ -254,9 +257,15 @@ class _BaseObject(SchemaModel):
|
|
|
254
257
|
|
|
255
258
|
# Take a copy to avoid the context changes affecting the object
|
|
256
259
|
context = StaticContext.create_copy(context)
|
|
257
|
-
|
|
260
|
+
description = f"{cls.__name__} '{data.name}'"
|
|
261
|
+
with error_context(f"While preparing data for {description}", logger=logger):
|
|
262
|
+
object_dict = await cls._data_to_schema(data, context)
|
|
258
263
|
object_dict["uuid"] = None # New UUID is generated by the service
|
|
259
|
-
|
|
264
|
+
target = f"path '{path}'" if path is not None else f"parent path '{parent or ''}'"
|
|
265
|
+
with error_context(
|
|
266
|
+
f"While creating {description} at {target} (schema: {object_dict['schema']})", logger=logger
|
|
267
|
+
):
|
|
268
|
+
obj = await create_geoscience_object(context, object_dict, parent, path)
|
|
260
269
|
return cls(obj)
|
|
261
270
|
|
|
262
271
|
@classmethod
|
|
@@ -285,10 +294,15 @@ class _BaseObject(SchemaModel):
|
|
|
285
294
|
workspace_id=reference.workspace_id,
|
|
286
295
|
)
|
|
287
296
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
297
|
+
description = f"{cls.__name__} '{data.name}'"
|
|
298
|
+
with error_context(f"While preparing replacement data for {description}", logger=logger):
|
|
299
|
+
object_dict = await cls._data_to_schema(data, reference_context)
|
|
300
|
+
with error_context(
|
|
301
|
+
f"While replacing {description} at '{reference}' (schema: {object_dict['schema']})", logger=logger
|
|
302
|
+
):
|
|
303
|
+
obj = await replace_geoscience_object(
|
|
304
|
+
reference_context, reference, object_dict, create_if_missing=create_if_missing
|
|
305
|
+
)
|
|
292
306
|
return cls(obj)
|
|
293
307
|
|
|
294
308
|
@classmethod
|
|
@@ -19,7 +19,7 @@ import numpy as np
|
|
|
19
19
|
|
|
20
20
|
from evo import logging
|
|
21
21
|
from evo.common import APIConnector, Environment, ICache, IFeedback, StaticContext
|
|
22
|
-
from evo.common.exceptions import StorageFileNotFoundError
|
|
22
|
+
from evo.common.exceptions import StorageFileNotFoundError, error_context
|
|
23
23
|
from evo.common.io.exceptions import DataExistsError
|
|
24
24
|
from evo.common.utils import NoFeedback, PartialFeedback, split_feedback
|
|
25
25
|
|
|
@@ -143,22 +143,24 @@ class ObjectDataClient:
|
|
|
143
143
|
n_names = len(names)
|
|
144
144
|
logger.debug(f"Found {n_names} data reference{'' if n_names == 1 else 's'}")
|
|
145
145
|
n_uploaded = 0
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
146
|
+
with error_context("While uploading referenced data", logger=logger):
|
|
147
|
+
async for ctx in ObjectDataUpload._create_multiple(
|
|
148
|
+
connector=self._connector,
|
|
149
|
+
environment=self._environment,
|
|
150
|
+
names=names,
|
|
151
|
+
):
|
|
152
|
+
if fb is not NoFeedback:
|
|
153
|
+
fb_part = PartialFeedback(parent=fb, start=n_uploaded / n_names, end=(n_uploaded + 1) / n_names)
|
|
154
|
+
else:
|
|
155
|
+
fb_part = NoFeedback
|
|
156
|
+
|
|
157
|
+
with error_context(f"While uploading referenced data '{ctx.name}'", logger=logger):
|
|
158
|
+
data_file = self.cache_location / ctx.name
|
|
159
|
+
logger.debug(f"Uploading data: {ctx.name}")
|
|
160
|
+
if not data_file.exists():
|
|
161
|
+
raise StorageFileNotFoundError(f"Object data file not found in cache: {data_file}")
|
|
162
|
+
await ctx.upload_from_path(filename=data_file, transport=self._connector.transport, fb=fb_part)
|
|
163
|
+
n_uploaded += 1
|
|
162
164
|
|
|
163
165
|
logger.debug(
|
|
164
166
|
f"Uploaded {n_uploaded} data reference{'' if n_uploaded == 1 else 's'}, skipped {n_names - n_uploaded}"
|
|
@@ -183,9 +185,10 @@ class ObjectDataClient:
|
|
|
183
185
|
"""
|
|
184
186
|
from .table_formats import get_known_format
|
|
185
187
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
188
|
+
with error_context("While preparing an Arrow table for Evo Parquet storage", logger=logger):
|
|
189
|
+
if not isinstance(table_format, KnownTableFormat):
|
|
190
|
+
table_format = get_known_format(table, table_formats=table_format)
|
|
191
|
+
table_info = table_format.save_table(table=table, destination=self.cache_location)
|
|
189
192
|
return table_info
|
|
190
193
|
|
|
191
194
|
async def upload_table(
|
|
@@ -210,11 +213,12 @@ class ObjectDataClient:
|
|
|
210
213
|
"""
|
|
211
214
|
table_info = self.save_table(table, table_format)
|
|
212
215
|
upload = ObjectDataUpload(connector=self._connector, environment=self._environment, name=table_info["data"])
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
216
|
+
with error_context(f"While uploading table data '{table_info['data']}'", logger=logger):
|
|
217
|
+
try:
|
|
218
|
+
await upload.upload_from_cache(cache=self._cache, transport=self._connector.transport, fb=fb)
|
|
219
|
+
except DataExistsError:
|
|
220
|
+
logger.debug(f"Data not uploaded because data already exists (label: {table_info['data']})")
|
|
221
|
+
fb.progress(1)
|
|
218
222
|
return table_info
|
|
219
223
|
|
|
220
224
|
async def upload_category_table(self, table: pa.Table, fb: IFeedback = NoFeedback) -> CategoryInfo:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|