entitysdk 0.6.1__tar.gz → 0.6.2__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 (124) hide show
  1. {entitysdk-0.6.1/src/entitysdk.egg-info → entitysdk-0.6.2}/PKG-INFO +1 -1
  2. {entitysdk-0.6.1 → entitysdk-0.6.2}/examples/02_morphology.ipynb +18 -2
  3. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/client.py +4 -0
  4. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/core.py +20 -7
  5. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/asset.py +1 -0
  6. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/util.py +3 -0
  7. {entitysdk-0.6.1 → entitysdk-0.6.2/src/entitysdk.egg-info}/PKG-INFO +1 -1
  8. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/test_asset.py +1 -0
  9. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/test_client.py +52 -1
  10. {entitysdk-0.6.1 → entitysdk-0.6.2}/.github/workflows/sdist.yml +0 -0
  11. {entitysdk-0.6.1 → entitysdk-0.6.2}/.github/workflows/tox.yml +0 -0
  12. {entitysdk-0.6.1 → entitysdk-0.6.2}/.gitignore +0 -0
  13. {entitysdk-0.6.1 → entitysdk-0.6.2}/CHANGELOG.rst +0 -0
  14. {entitysdk-0.6.1 → entitysdk-0.6.2}/CONTRIBUTING.md +0 -0
  15. {entitysdk-0.6.1 → entitysdk-0.6.2}/LICENSE.txt +0 -0
  16. {entitysdk-0.6.1 → entitysdk-0.6.2}/README.md +0 -0
  17. {entitysdk-0.6.1 → entitysdk-0.6.2}/examples/01_searching.ipynb +0 -0
  18. {entitysdk-0.6.1 → entitysdk-0.6.2}/examples/03_circuit.ipynb +0 -0
  19. {entitysdk-0.6.1 → entitysdk-0.6.2}/examples/04_simulation_campaign.ipynb +0 -0
  20. {entitysdk-0.6.1 → entitysdk-0.6.2}/examples/utils.py +0 -0
  21. {entitysdk-0.6.1 → entitysdk-0.6.2}/pyproject.toml +0 -0
  22. {entitysdk-0.6.1 → entitysdk-0.6.2}/setup.cfg +0 -0
  23. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/__init__.py +0 -0
  24. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/common.py +0 -0
  25. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/config.py +0 -0
  26. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/downloaders/__init__.py +0 -0
  27. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/downloaders/emodel.py +0 -0
  28. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/downloaders/ion_channel_model.py +0 -0
  29. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/downloaders/memodel.py +0 -0
  30. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/downloaders/morphology.py +0 -0
  31. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/exception.py +0 -0
  32. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/mixin.py +0 -0
  33. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/__init__.py +0 -0
  34. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/activity.py +0 -0
  35. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/agent.py +0 -0
  36. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/base.py +0 -0
  37. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/brain_location.py +0 -0
  38. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/brain_region.py +0 -0
  39. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/brain_region_hierarchy.py +0 -0
  40. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/circuit.py +0 -0
  41. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/classification.py +0 -0
  42. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/contribution.py +0 -0
  43. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/core.py +0 -0
  44. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/electrical_cell_recording.py +0 -0
  45. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/emodel.py +0 -0
  46. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/entity.py +0 -0
  47. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/etype.py +0 -0
  48. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/ion_channel_model.py +0 -0
  49. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/license.py +0 -0
  50. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/memodel.py +0 -0
  51. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/memodelcalibrationresult.py +0 -0
  52. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/morphology.py +0 -0
  53. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/mtype.py +0 -0
  54. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/response.py +0 -0
  55. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/scientific_artifact.py +0 -0
  56. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/simulation.py +0 -0
  57. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/simulation_campaign.py +0 -0
  58. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/simulation_execution.py +0 -0
  59. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/simulation_generation.py +0 -0
  60. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/simulation_result.py +0 -0
  61. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/single_neuron_simulation.py +0 -0
  62. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/single_neuron_synaptome_simulation.py +0 -0
  63. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/subject.py +0 -0
  64. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/synaptome.py +0 -0
  65. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/taxonomy.py +0 -0
  66. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/models/validation_result.py +0 -0
  67. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/result.py +0 -0
  68. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/route.py +0 -0
  69. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/schemas/__init__.py +0 -0
  70. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/schemas/asset.py +0 -0
  71. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/schemas/base.py +0 -0
  72. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/schemas/memodel.py +0 -0
  73. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/serdes.py +0 -0
  74. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/token_manager.py +0 -0
  75. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/types.py +0 -0
  76. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/utils/__init__.py +0 -0
  77. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/utils/asset.py +0 -0
  78. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk/utils/filesystem.py +0 -0
  79. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk.egg-info/SOURCES.txt +0 -0
  80. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk.egg-info/dependency_links.txt +0 -0
  81. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk.egg-info/requires.txt +0 -0
  82. {entitysdk-0.6.1 → entitysdk-0.6.2}/src/entitysdk.egg-info/top_level.txt +0 -0
  83. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/__init__.py +0 -0
  84. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/integration/__init__.py +0 -0
  85. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/integration/conftest.py +0 -0
  86. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/integration/test_searching.py +0 -0
  87. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/__init__.py +0 -0
  88. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/conftest.py +0 -0
  89. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/downloaders/test_emodel.py +0 -0
  90. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/downloaders/test_ion_channel_model.py +0 -0
  91. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/downloaders/test_memodel.py +0 -0
  92. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/downloaders/test_morphology.py +0 -0
  93. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/__init__.py +0 -0
  94. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/data/.gitignore +0 -0
  95. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/data/circuit.json +0 -0
  96. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/data/electrical_cell_recording.json +0 -0
  97. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/data/ion_channel_model.json +0 -0
  98. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/data/memodel_calibration_result.json +0 -0
  99. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/data/reconstruction_morphology.json +0 -0
  100. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/data/simulation_campaign.json +0 -0
  101. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/data/validation_result.json +0 -0
  102. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/test_agent.py +0 -0
  103. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/test_brain_region.py +0 -0
  104. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/test_circuit.py +0 -0
  105. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/test_contribution.py +0 -0
  106. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/test_electrical_cell_recording.py +0 -0
  107. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/test_init.py +0 -0
  108. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/test_ion_channel_model.py +0 -0
  109. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/test_memodel_calibration_result.py +0 -0
  110. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/test_morphology.py +0 -0
  111. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/test_simulation_campaign.py +0 -0
  112. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/models/test_validation_result.py +0 -0
  113. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/test_base.py +0 -0
  114. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/test_common.py +0 -0
  115. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/test_config.py +0 -0
  116. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/test_result.py +0 -0
  117. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/test_route.py +0 -0
  118. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/test_serdes.py +0 -0
  119. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/test_token_manager.py +0 -0
  120. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/test_util.py +0 -0
  121. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/util.py +0 -0
  122. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/utils/test_asset.py +0 -0
  123. {entitysdk-0.6.1 → entitysdk-0.6.2}/tests/unit/utils/test_filesystem.py +0 -0
  124. {entitysdk-0.6.1 → entitysdk-0.6.2}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: entitysdk
3
- Version: 0.6.1
3
+ Version: 0.6.2
4
4
  Summary: Python library for interacting with the entitycore service
5
5
  Author-email: Open Brain Institute <info@openbraininstitute.org>
6
6
  Maintainer-email: Open Brain Institute <info@openbraininstitute.org>
@@ -276,7 +276,8 @@
276
276
  " entity_id=registered.id,\n",
277
277
  " entity_type=ReconstructionMorphology,\n",
278
278
  " file_path=file1,\n",
279
- " file_content_type=\"application/h5\",\n",
279
+ " file_content_type=\"application/x-hdf5\",\n",
280
+ " asset_label=\"hdf5\",\n",
280
281
  " )\n",
281
282
  " rprint(asset1)\n",
282
283
  "\n",
@@ -289,6 +290,7 @@
289
290
  " file_content=buffer,\n",
290
291
  " file_name=\"buffer.h5\",\n",
291
292
  " file_content_type=\"application/swc\",\n",
293
+ " asset_label=\"swc\",\n",
292
294
  " )\n",
293
295
  " rprint(asset2)"
294
296
  ]
@@ -408,8 +410,22 @@
408
410
  }
409
411
  ],
410
412
  "metadata": {
413
+ "kernelspec": {
414
+ "display_name": "Python 3 (ipykernel)",
415
+ "language": "python",
416
+ "name": "python3"
417
+ },
411
418
  "language_info": {
412
- "name": "python"
419
+ "codemirror_mode": {
420
+ "name": "ipython",
421
+ "version": 3
422
+ },
423
+ "file_extension": ".py",
424
+ "mimetype": "text/x-python",
425
+ "name": "python",
426
+ "nbconvert_exporter": "python",
427
+ "pygments_lexer": "ipython3",
428
+ "version": "3.12.10"
413
429
  }
414
430
  },
415
431
  "nbformat": 4,
@@ -214,6 +214,7 @@ class Client:
214
214
  file_content_type: str,
215
215
  file_name: str | None = None,
216
216
  file_metadata: dict | None = None,
217
+ asset_label: str | None = None,
217
218
  project_context: ProjectContext | None = None,
218
219
  ) -> Asset:
219
220
  """Upload asset to an existing entity's endpoint from a file path."""
@@ -229,6 +230,7 @@ class Client:
229
230
  file_name=file_name or path.name,
230
231
  content_type=file_content_type,
231
232
  metadata=file_metadata,
233
+ label=asset_label,
232
234
  )
233
235
  return core.upload_asset_file(
234
236
  url=url,
@@ -248,6 +250,7 @@ class Client:
248
250
  file_name: str,
249
251
  file_content_type: str,
250
252
  file_metadata: dict | None = None,
253
+ asset_label: str | None = None,
251
254
  project_context: ProjectContext | None = None,
252
255
  ) -> Asset:
253
256
  """Upload asset to an existing entity's endpoint from a file-like object."""
@@ -261,6 +264,7 @@ class Client:
261
264
  file_name=file_name,
262
265
  content_type=file_content_type,
263
266
  metadata=file_metadata or {},
267
+ label=asset_label,
264
268
  )
265
269
  context = self._required_user_context(override_context=project_context)
266
270
  return core.upload_asset_content(
@@ -1,6 +1,7 @@
1
1
  """Core SDK operations."""
2
2
 
3
3
  import io
4
+ import logging
4
5
  import os
5
6
  from collections.abc import Iterator
6
7
  from pathlib import Path
@@ -10,11 +11,13 @@ import httpx
10
11
 
11
12
  from entitysdk import serdes
12
13
  from entitysdk.common import ProjectContext
14
+ from entitysdk.exception import EntitySDKError
13
15
  from entitysdk.models.asset import Asset, DetailedFileList, LocalAssetMetadata
14
16
  from entitysdk.models.core import Identifiable
15
17
  from entitysdk.result import IteratorResult
16
18
  from entitysdk.util import make_db_api_request, stream_paginated_request
17
19
 
20
+ L = logging.getLogger(__name__)
18
21
  TIdentifiable = TypeVar("TIdentifiable", bound=Identifiable)
19
22
 
20
23
 
@@ -170,6 +173,7 @@ def upload_asset_content(
170
173
  url=url,
171
174
  method="POST",
172
175
  files=files,
176
+ data={"label": asset_metadata.label} if asset_metadata.label else None,
173
177
  project_context=project_context,
174
178
  token=token,
175
179
  http_client=http_client,
@@ -192,7 +196,7 @@ def upload_asset_directory(
192
196
  for concrete_path in paths.values():
193
197
  if not concrete_path.exists():
194
198
  msg = f"Path {concrete_path} does not exist"
195
- raise Exception(msg)
199
+ raise EntitySDKError(msg)
196
200
 
197
201
  response = make_db_api_request(
198
202
  url=url,
@@ -214,11 +218,20 @@ def upload_asset_directory(
214
218
  failed = {}
215
219
  for path, url in to_upload.items():
216
220
  with open(paths[Path(path)], "rb") as fd:
217
- response = http_client.request(
218
- method="PUT", url=url, content=fd, follow_redirects=True
219
- )
220
- if response.status_code != 200:
221
- failed[path] = url
221
+ try:
222
+ response = http_client.request(
223
+ method="PUT",
224
+ url=url,
225
+ content=fd,
226
+ follow_redirects=True,
227
+ timeout=20,
228
+ )
229
+ except httpx.HTTPError:
230
+ L.exception("Upload failed, will retry again")
231
+ failed[path] = url
232
+ else:
233
+ if response.status_code != 200:
234
+ failed[path] = url
222
235
  return failed
223
236
 
224
237
  to_upload = js["files"]
@@ -228,7 +241,7 @@ def upload_asset_directory(
228
241
  break
229
242
 
230
243
  if to_upload:
231
- raise Exception(f"Uploading these files failed: {to_upload}")
244
+ raise EntitySDKError(f"Uploading these files failed: {to_upload}")
232
245
 
233
246
  return serdes.deserialize_model(js["asset"], Asset)
234
247
 
@@ -93,6 +93,7 @@ class LocalAssetMetadata(BaseModel):
93
93
  description="The metadata of the asset.",
94
94
  ),
95
95
  ] = None
96
+ label: Annotated[str | None, Field(description="Optional asset label.")] = None
96
97
 
97
98
 
98
99
  class DetailedFile(BaseModel):
@@ -19,6 +19,7 @@ def make_db_api_request(
19
19
  *,
20
20
  method: str,
21
21
  json: dict | None = None,
22
+ data: dict | None = None,
22
23
  parameters: dict | None = None,
23
24
  files: dict | None = None,
24
25
  project_context: ProjectContext | None = None,
@@ -42,6 +43,7 @@ def make_db_api_request(
42
43
  headers=headers,
43
44
  json=json,
44
45
  files=files,
46
+ data=data,
45
47
  params=parameters,
46
48
  follow_redirects=True,
47
49
  )
@@ -53,6 +55,7 @@ def make_db_api_request(
53
55
  except httpx.HTTPStatusError as e:
54
56
  message = (
55
57
  f"HTTP error {response.status_code} for {method} {url}\n"
58
+ f"data : {data}\n"
56
59
  f"json : {dumps(json, indent=2)}\n"
57
60
  f"params : {parameters}\n"
58
61
  f"response : {response.text}"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: entitysdk
3
- Version: 0.6.1
3
+ Version: 0.6.2
4
4
  Summary: Python library for interacting with the entitycore service
5
5
  Author-email: Open Brain Institute <info@openbraininstitute.org>
6
6
  Maintainer-email: Open Brain Institute <info@openbraininstitute.org>
@@ -39,4 +39,5 @@ def test_local_asset_metadata():
39
39
  "file_name": "file_name",
40
40
  "content_type": "text/plain",
41
41
  "metadata": {"key": "value"},
42
+ "label": None,
42
43
  }
@@ -4,6 +4,7 @@ import uuid
4
4
  from pathlib import Path
5
5
  from unittest.mock import patch
6
6
 
7
+ import httpx
7
8
  import pytest
8
9
 
9
10
  from entitysdk.client import Client
@@ -145,6 +146,14 @@ def test_client_upload_file(
145
146
  method="POST",
146
147
  url=f"{api_url}/entity/{entity_id}/assets",
147
148
  match_headers=request_headers,
149
+ match_files={
150
+ "file": (
151
+ "foo",
152
+ b"foo",
153
+ "text/plain",
154
+ )
155
+ },
156
+ match_data={"label": "swc"},
148
157
  json=_mock_asset_response(asset_id),
149
158
  )
150
159
 
@@ -158,6 +167,7 @@ def test_client_upload_file(
158
167
  file_path=path,
159
168
  file_content_type="text/plain",
160
169
  file_metadata={"key": "value"},
170
+ asset_label="swc",
161
171
  )
162
172
 
163
173
  assert res.id == asset_id
@@ -179,6 +189,7 @@ def test_client_upload_content(client, httpx_mock, api_url, request_headers):
179
189
  "text/plain",
180
190
  )
181
191
  },
192
+ match_data={"label": "swc"},
182
193
  json=_mock_asset_response(asset_id),
183
194
  )
184
195
  res = client.upload_content(
@@ -188,6 +199,7 @@ def test_client_upload_content(client, httpx_mock, api_url, request_headers):
188
199
  file_content=buffer,
189
200
  file_content_type="text/plain",
190
201
  file_metadata={"key": "value"},
202
+ asset_label="swc",
191
203
  )
192
204
 
193
205
  assert res.id == asset_id
@@ -767,6 +779,45 @@ def test_upload_directory_by_paths(
767
779
  )
768
780
  assert res == Asset.model_validate(asset)
769
781
 
782
+ httpx_mock.add_response(
783
+ method="POST",
784
+ url=f"{api_url}/entity/{entity_id}/assets/directory/upload",
785
+ match_headers=request_headers,
786
+ json={
787
+ "asset": asset,
788
+ "files": {
789
+ "foo/bar/baz/subdir0/file1.txt": "http://upload_url0",
790
+ },
791
+ },
792
+ )
793
+
794
+ # have read error / exception
795
+ httpx_mock.add_exception(
796
+ httpx.ReadTimeout("Unable to read within timeout"),
797
+ method="PUT",
798
+ url="http://upload_url0",
799
+ )
800
+ httpx_mock.add_exception(
801
+ httpx.ReadTimeout("Unable to read within timeout"),
802
+ method="PUT",
803
+ url="http://upload_url0",
804
+ )
805
+ httpx_mock.add_exception(
806
+ httpx.ReadTimeout("Unable to read within timeout"),
807
+ method="PUT",
808
+ url="http://upload_url0",
809
+ )
810
+
811
+ with pytest.raises(EntitySDKError, match="Uploading these files failed"):
812
+ client.upload_directory(
813
+ entity_id=entity_id,
814
+ entity_type=Entity,
815
+ name="test-directory",
816
+ paths=paths,
817
+ label=None,
818
+ metadata=None,
819
+ )
820
+
770
821
  # have s3 upload fail:
771
822
  httpx_mock.add_response(
772
823
  method="POST",
@@ -784,7 +835,7 @@ def test_upload_directory_by_paths(
784
835
  httpx_mock.add_response(method="PUT", url="http://upload_url0", status_code=404)
785
836
  httpx_mock.add_response(method="PUT", url="http://upload_url0", status_code=404)
786
837
 
787
- with pytest.raises(Exception, match="Uploading these files failed"):
838
+ with pytest.raises(EntitySDKError, match="Uploading these files failed"):
788
839
  client.upload_directory(
789
840
  entity_id=entity_id,
790
841
  entity_type=Entity,
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