entitysdk 0.6.0__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.
- {entitysdk-0.6.0/src/entitysdk.egg-info → entitysdk-0.6.2}/PKG-INFO +1 -1
- {entitysdk-0.6.0 → entitysdk-0.6.2}/examples/02_morphology.ipynb +18 -2
- {entitysdk-0.6.0 → entitysdk-0.6.2}/examples/03_circuit.ipynb +103 -9
- entitysdk-0.6.2/examples/utils.py +13 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/client.py +4 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/core.py +20 -7
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/downloaders/ion_channel_model.py +1 -1
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/__init__.py +2 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/asset.py +1 -0
- entitysdk-0.6.2/src/entitysdk/models/brain_region_hierarchy.py +19 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/route.py +1 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/util.py +3 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2/src/entitysdk.egg-info}/PKG-INFO +1 -1
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk.egg-info/SOURCES.txt +2 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/downloaders/test_ion_channel_model.py +1 -1
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/downloaders/test_memodel.py +1 -1
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/test_asset.py +1 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/test_client.py +53 -2
- {entitysdk-0.6.0 → entitysdk-0.6.2}/.github/workflows/sdist.yml +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/.github/workflows/tox.yml +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/.gitignore +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/CHANGELOG.rst +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/CONTRIBUTING.md +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/LICENSE.txt +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/README.md +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/examples/01_searching.ipynb +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/examples/04_simulation_campaign.ipynb +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/pyproject.toml +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/setup.cfg +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/__init__.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/common.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/config.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/downloaders/__init__.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/downloaders/emodel.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/downloaders/memodel.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/downloaders/morphology.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/exception.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/mixin.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/activity.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/agent.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/base.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/brain_location.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/brain_region.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/circuit.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/classification.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/contribution.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/core.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/electrical_cell_recording.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/emodel.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/entity.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/etype.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/ion_channel_model.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/license.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/memodel.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/memodelcalibrationresult.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/morphology.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/mtype.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/response.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/scientific_artifact.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/simulation.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/simulation_campaign.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/simulation_execution.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/simulation_generation.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/simulation_result.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/single_neuron_simulation.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/single_neuron_synaptome_simulation.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/subject.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/synaptome.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/taxonomy.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/validation_result.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/result.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/schemas/__init__.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/schemas/asset.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/schemas/base.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/schemas/memodel.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/serdes.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/token_manager.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/types.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/utils/__init__.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/utils/asset.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/utils/filesystem.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk.egg-info/dependency_links.txt +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk.egg-info/requires.txt +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk.egg-info/top_level.txt +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/__init__.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/integration/__init__.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/integration/conftest.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/integration/test_searching.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/__init__.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/conftest.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/downloaders/test_emodel.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/downloaders/test_morphology.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/__init__.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/data/.gitignore +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/data/circuit.json +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/data/electrical_cell_recording.json +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/data/ion_channel_model.json +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/data/memodel_calibration_result.json +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/data/reconstruction_morphology.json +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/data/simulation_campaign.json +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/data/validation_result.json +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/test_agent.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/test_brain_region.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/test_circuit.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/test_contribution.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/test_electrical_cell_recording.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/test_init.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/test_ion_channel_model.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/test_memodel_calibration_result.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/test_morphology.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/test_simulation_campaign.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/models/test_validation_result.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/test_base.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/test_common.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/test_config.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/test_result.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/test_route.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/test_serdes.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/test_token_manager.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/test_util.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/util.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/utils/test_asset.py +0 -0
- {entitysdk-0.6.0 → entitysdk-0.6.2}/tests/unit/utils/test_filesystem.py +0 -0
- {entitysdk-0.6.0 → 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.
|
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/
|
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
|
-
"
|
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,
|
@@ -8,8 +8,11 @@
|
|
8
8
|
"outputs": [],
|
9
9
|
"source": [
|
10
10
|
"import os\n",
|
11
|
+
"import tempfile\n",
|
12
|
+
"from pathlib import Path\n",
|
11
13
|
"\n",
|
12
14
|
"from rich import print as rprint\n",
|
15
|
+
"from utils import create_mock_circuit_dir\n",
|
13
16
|
"\n",
|
14
17
|
"from entitysdk import Client, ProjectContext, models\n",
|
15
18
|
"\n",
|
@@ -109,44 +112,135 @@
|
|
109
112
|
},
|
110
113
|
{
|
111
114
|
"cell_type": "markdown",
|
112
|
-
"id": "
|
115
|
+
"id": "c3ff25a9-fc61-4c19-8949-140c1dd33af7",
|
113
116
|
"metadata": {},
|
114
117
|
"source": [
|
115
|
-
"##
|
118
|
+
"## Upload directory"
|
116
119
|
]
|
117
120
|
},
|
118
121
|
{
|
119
122
|
"cell_type": "code",
|
120
123
|
"execution_count": null,
|
121
|
-
"id": "
|
124
|
+
"id": "3dccd413-f91b-42b1-8efe-56d01f68ddd0",
|
122
125
|
"metadata": {},
|
123
126
|
"outputs": [],
|
124
127
|
"source": [
|
125
|
-
"
|
128
|
+
"with tempfile.TemporaryDirectory() as tdir:\n",
|
129
|
+
" # create a hierarchy of files to upload\n",
|
130
|
+
" create_mock_circuit_dir(tdir)\n",
|
131
|
+
"\n",
|
132
|
+
" files = {str(path.relative_to(tdir)): path for path in Path(tdir).rglob(\"*\") if path.is_file()}\n",
|
133
|
+
"\n",
|
134
|
+
" directory_asset = client.upload_directory(\n",
|
135
|
+
" entity_id=registered_circuit.id,\n",
|
136
|
+
" entity_type=models.Circuit,\n",
|
137
|
+
" name=\"circuit\",\n",
|
138
|
+
" paths=files,\n",
|
139
|
+
" )"
|
140
|
+
]
|
141
|
+
},
|
142
|
+
{
|
143
|
+
"cell_type": "markdown",
|
144
|
+
"id": "6ad6ce94-ad74-4710-b274-1883fdeb41f5",
|
145
|
+
"metadata": {},
|
146
|
+
"source": [
|
147
|
+
"## List directory"
|
126
148
|
]
|
127
149
|
},
|
128
150
|
{
|
129
151
|
"cell_type": "code",
|
130
152
|
"execution_count": null,
|
131
|
-
"id": "
|
153
|
+
"id": "3b0d302e-46fe-4d97-b221-99833975eede",
|
132
154
|
"metadata": {},
|
133
155
|
"outputs": [],
|
134
156
|
"source": [
|
135
|
-
"
|
157
|
+
"files = client.list_directory(\n",
|
158
|
+
" entity_id=registered_circuit.id, entity_type=models.Circuit, asset_id=directory_asset.id\n",
|
159
|
+
")"
|
160
|
+
]
|
161
|
+
},
|
162
|
+
{
|
163
|
+
"cell_type": "code",
|
164
|
+
"execution_count": null,
|
165
|
+
"id": "749b85d2-dbce-455b-9ade-fec7e17f7208",
|
166
|
+
"metadata": {},
|
167
|
+
"outputs": [],
|
168
|
+
"source": [
|
169
|
+
"rprint(files)"
|
170
|
+
]
|
171
|
+
},
|
172
|
+
{
|
173
|
+
"cell_type": "markdown",
|
174
|
+
"id": "aad97379-3010-42c9-9fc5-f30101163f1c",
|
175
|
+
"metadata": {},
|
176
|
+
"source": [
|
177
|
+
"## Download directory"
|
178
|
+
]
|
179
|
+
},
|
180
|
+
{
|
181
|
+
"cell_type": "code",
|
182
|
+
"execution_count": null,
|
183
|
+
"id": "ace27230-6dfa-4bc6-8b2c-33998a22a111",
|
184
|
+
"metadata": {},
|
185
|
+
"outputs": [],
|
186
|
+
"source": [
|
187
|
+
"with tempfile.TemporaryDirectory() as tdir:\n",
|
188
|
+
" client.download_directory(\n",
|
189
|
+
" entity_id=registered_circuit.id,\n",
|
190
|
+
" entity_type=models.Circuit,\n",
|
191
|
+
" asset_id=directory_asset.id,\n",
|
192
|
+
" output_path=Path(tdir),\n",
|
193
|
+
" )\n",
|
194
|
+
" files = {str(path.relative_to(tdir)): path for path in Path(tdir).rglob(\"*\") if path.is_file()}\n",
|
195
|
+
" rprint(files)"
|
196
|
+
]
|
197
|
+
},
|
198
|
+
{
|
199
|
+
"cell_type": "markdown",
|
200
|
+
"id": "8bf620b4-fafc-4476-a719-bbe6e7a821bf",
|
201
|
+
"metadata": {},
|
202
|
+
"source": [
|
203
|
+
"## Fetch Circuit"
|
136
204
|
]
|
137
205
|
},
|
138
206
|
{
|
139
207
|
"cell_type": "code",
|
140
208
|
"execution_count": null,
|
141
|
-
"id": "
|
209
|
+
"id": "bed0af2c-ae46-41b0-ba77-485daef0a87b",
|
142
210
|
"metadata": {},
|
143
211
|
"outputs": [],
|
144
|
-
"source": [
|
212
|
+
"source": [
|
213
|
+
"fetched = client.get_entity(entity_id=registered_circuit.id, entity_type=models.Circuit)"
|
214
|
+
]
|
215
|
+
},
|
216
|
+
{
|
217
|
+
"cell_type": "code",
|
218
|
+
"execution_count": null,
|
219
|
+
"id": "ee27c8b5-dfa5-4fa5-ac2f-6cf158057bcf",
|
220
|
+
"metadata": {},
|
221
|
+
"outputs": [],
|
222
|
+
"source": [
|
223
|
+
"rprint(fetched)"
|
224
|
+
]
|
145
225
|
}
|
146
226
|
],
|
147
227
|
"metadata": {
|
228
|
+
"kernelspec": {
|
229
|
+
"display_name": "Python 3 (ipykernel)",
|
230
|
+
"language": "python",
|
231
|
+
"name": "python3"
|
232
|
+
},
|
148
233
|
"language_info": {
|
149
|
-
"
|
234
|
+
"codemirror_mode": {
|
235
|
+
"name": "ipython",
|
236
|
+
"version": 3
|
237
|
+
},
|
238
|
+
"file_extension": ".py",
|
239
|
+
"mimetype": "text/x-python",
|
240
|
+
"name": "python",
|
241
|
+
"nbconvert_exporter": "python",
|
242
|
+
"pygments_lexer": "ipython3",
|
243
|
+
"version": "3.12.10"
|
150
244
|
}
|
151
245
|
},
|
152
246
|
"nbformat": 4,
|
@@ -0,0 +1,13 @@
|
|
1
|
+
"""Helpers."""
|
2
|
+
|
3
|
+
from pathlib import Path
|
4
|
+
|
5
|
+
|
6
|
+
def create_mock_circuit_dir(output_dir: Path):
|
7
|
+
"""Create a mock hierarchy that looks like a circuit."""
|
8
|
+
output_dir = Path(output_dir)
|
9
|
+
output_dir.mkdir(exist_ok=True)
|
10
|
+
(output_dir / "circuit_config.json").touch()
|
11
|
+
(output_dir / "sonata").mkdir()
|
12
|
+
(output_dir / "sonata" / "nodes.h5").touch()
|
13
|
+
(output_dir / "sonata" / "edges.h5").touch()
|
@@ -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
|
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
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
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
|
244
|
+
raise EntitySDKError(f"Uploading these files failed: {to_upload}")
|
232
245
|
|
233
246
|
return serdes.deserialize_model(js["asset"], Asset)
|
234
247
|
|
@@ -22,7 +22,7 @@ def download_ion_channel_mechanism(
|
|
22
22
|
output_dir = create_dir(output_dir)
|
23
23
|
asset = client.download_assets(
|
24
24
|
ion_channel_model,
|
25
|
-
selection={"content_type": "application/
|
25
|
+
selection={"content_type": "application/mod"},
|
26
26
|
output_path=output_dir,
|
27
27
|
).one()
|
28
28
|
|
@@ -4,6 +4,7 @@ from entitysdk.models.agent import Organization, Person
|
|
4
4
|
from entitysdk.models.asset import Asset
|
5
5
|
from entitysdk.models.brain_location import BrainLocation
|
6
6
|
from entitysdk.models.brain_region import BrainRegion
|
7
|
+
from entitysdk.models.brain_region_hierarchy import BrainRegionHierarchy
|
7
8
|
from entitysdk.models.circuit import Circuit
|
8
9
|
from entitysdk.models.classification import ETypeClassification, MTypeClassification
|
9
10
|
from entitysdk.models.contribution import Contribution, Role
|
@@ -31,6 +32,7 @@ __all__ = [
|
|
31
32
|
"Asset",
|
32
33
|
"BrainLocation",
|
33
34
|
"BrainRegion",
|
35
|
+
"BrainRegionHierarchy",
|
34
36
|
"Circuit",
|
35
37
|
"Contribution",
|
36
38
|
"ElectricalCellRecording",
|
@@ -0,0 +1,19 @@
|
|
1
|
+
"""BrainRegionHierarchy model."""
|
2
|
+
|
3
|
+
from typing import Annotated
|
4
|
+
|
5
|
+
from pydantic import Field
|
6
|
+
|
7
|
+
from entitysdk.models.core import Identifiable
|
8
|
+
|
9
|
+
|
10
|
+
class BrainRegionHierarchy(Identifiable):
|
11
|
+
"""BrainRegionHierarchy model."""
|
12
|
+
|
13
|
+
name: Annotated[
|
14
|
+
str,
|
15
|
+
Field(
|
16
|
+
examples=["Thalamus"],
|
17
|
+
description="The name of the brain region.",
|
18
|
+
),
|
19
|
+
]
|
@@ -9,6 +9,7 @@ _ROUTES = {
|
|
9
9
|
"Activity": "activity",
|
10
10
|
"BrainLocation": "brain-location",
|
11
11
|
"BrainRegion": "brain-region",
|
12
|
+
"BrainRegionHierarchy": "brain-region-hierarchy",
|
12
13
|
"Circuit": "circuit",
|
13
14
|
"Contribution": "contribution",
|
14
15
|
"ElectricalCellRecording": "electrical-cell-recording",
|
@@ -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.
|
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>
|
@@ -11,6 +11,7 @@ examples/01_searching.ipynb
|
|
11
11
|
examples/02_morphology.ipynb
|
12
12
|
examples/03_circuit.ipynb
|
13
13
|
examples/04_simulation_campaign.ipynb
|
14
|
+
examples/utils.py
|
14
15
|
src/entitysdk/__init__.py
|
15
16
|
src/entitysdk/client.py
|
16
17
|
src/entitysdk/common.py
|
@@ -41,6 +42,7 @@ src/entitysdk/models/asset.py
|
|
41
42
|
src/entitysdk/models/base.py
|
42
43
|
src/entitysdk/models/brain_location.py
|
43
44
|
src/entitysdk/models/brain_region.py
|
45
|
+
src/entitysdk/models/brain_region_hierarchy.py
|
44
46
|
src/entitysdk/models/circuit.py
|
45
47
|
src/entitysdk/models/classification.py
|
46
48
|
src/entitysdk/models/contribution.py
|
@@ -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
|
@@ -555,7 +567,7 @@ def test_client_download_assets(
|
|
555
567
|
| {
|
556
568
|
"assets": [
|
557
569
|
_mock_asset_response(asset1_id)
|
558
|
-
| {"path": "foo/bar/bar.h5", "content_type": "application/hdf5"},
|
570
|
+
| {"path": "foo/bar/bar.h5", "content_type": "application/x-hdf5"},
|
559
571
|
_mock_asset_response(asset2_id)
|
560
572
|
| {"path": "foo/bar/bar.swc", "content_type": "application/swc"},
|
561
573
|
]
|
@@ -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(
|
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
|
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
|
{entitysdk-0.6.0 → entitysdk-0.6.2}/src/entitysdk/models/single_neuron_synaptome_simulation.py
RENAMED
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
|
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
|