entitysdk 0.2.0__tar.gz → 0.2.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.2.0/src/entitysdk.egg-info → entitysdk-0.2.2}/PKG-INFO +17 -2
- {entitysdk-0.2.0 → entitysdk-0.2.2}/README.md +16 -1
- entitysdk-0.2.0/examples/searching.ipynb → entitysdk-0.2.2/examples/01_searching.ipynb +9 -3
- entitysdk-0.2.0/examples/morphology.ipynb → entitysdk-0.2.2/examples/02_morphology.ipynb +51 -14
- entitysdk-0.2.0/examples/contribution.ipynb → entitysdk-0.2.2/examples/03_contribution.ipynb +12 -3
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/models/asset.py +0 -6
- entitysdk-0.2.2/src/entitysdk/models/brain_region.py +36 -0
- entitysdk-0.2.2/src/entitysdk/models/ion_channel_model.py +158 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/models/morphology.py +1 -34
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/route.py +2 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2/src/entitysdk.egg-info}/PKG-INFO +17 -2
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk.egg-info/SOURCES.txt +8 -3
- entitysdk-0.2.2/tests/unit/models/data/ion_channel_model.json +114 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/unit/models/data/reconstruction_morphology.json +8 -12
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/unit/models/test_asset.py +0 -2
- entitysdk-0.2.2/tests/unit/models/test_brain_region.py +22 -0
- entitysdk-0.2.2/tests/unit/models/test_ion_channel_model.py +60 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/unit/test_client.py +0 -2
- {entitysdk-0.2.0 → entitysdk-0.2.2}/.github/workflows/sdist.yml +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/.github/workflows/tox.yml +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/.gitignore +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/CHANGELOG.rst +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/CONTRIBUTING.md +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/LICENSE.txt +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/pyproject.toml +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/setup.cfg +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/__init__.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/client.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/common.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/config.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/core.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/exception.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/mixin.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/models/__init__.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/models/agent.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/models/base.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/models/contribution.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/models/core.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/models/entity.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/models/mtype.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/models/response.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/result.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/serdes.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/token_manager.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/typedef.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk/util.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk.egg-info/dependency_links.txt +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk.egg-info/requires.txt +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/src/entitysdk.egg-info/top_level.txt +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/__init__.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/integration/__init__.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/integration/conftest.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/integration/test_searching.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/unit/__init__.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/unit/conftest.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/unit/models/__init__.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/unit/models/data/.gitignore +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/unit/models/test_agent.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/unit/models/test_contribution.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/unit/models/test_morphology.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/unit/test_base.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/unit/test_common.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/unit/test_config.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/unit/test_result.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/unit/test_route.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/unit/test_serdes.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/unit/test_token_manager.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/unit/test_util.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tests/unit/util.py +0 -0
- {entitysdk-0.2.0 → entitysdk-0.2.2}/tox.ini +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: entitysdk
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.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,6 +39,21 @@ entitysdk is a Python library for interacting with the [entitycore service][enti
|
|
39
39
|
```bash
|
40
40
|
pip install entitysdk
|
41
41
|
```
|
42
|
+
|
43
|
+
## Obtaining a valid access token
|
44
|
+
|
45
|
+
An access token can be retrieved easily using the obi-auth helper library.
|
46
|
+
|
47
|
+
```bash
|
48
|
+
pip install obi-auth
|
49
|
+
```
|
50
|
+
|
51
|
+
```python
|
52
|
+
from obi_auth import get_token
|
53
|
+
|
54
|
+
access_token = get_token(environment="staging")
|
55
|
+
```
|
56
|
+
|
42
57
|
## Quick Start
|
43
58
|
|
44
59
|
```python
|
@@ -49,11 +64,11 @@ from entitysdk.models.morphology import ReconstructionMorphology
|
|
49
64
|
|
50
65
|
# Initialize client
|
51
66
|
client = Client(
|
52
|
-
api_url="http://api.example.com",
|
53
67
|
project_context=ProjectContext(
|
54
68
|
project_id=UUID("your-project-id"),
|
55
69
|
virtual_lab_id=UUID("your-lab-id")
|
56
70
|
)
|
71
|
+
environment="staging"
|
57
72
|
)
|
58
73
|
|
59
74
|
# Search for morphologies
|
@@ -18,6 +18,21 @@ entitysdk is a Python library for interacting with the [entitycore service][enti
|
|
18
18
|
```bash
|
19
19
|
pip install entitysdk
|
20
20
|
```
|
21
|
+
|
22
|
+
## Obtaining a valid access token
|
23
|
+
|
24
|
+
An access token can be retrieved easily using the obi-auth helper library.
|
25
|
+
|
26
|
+
```bash
|
27
|
+
pip install obi-auth
|
28
|
+
```
|
29
|
+
|
30
|
+
```python
|
31
|
+
from obi_auth import get_token
|
32
|
+
|
33
|
+
access_token = get_token(environment="staging")
|
34
|
+
```
|
35
|
+
|
21
36
|
## Quick Start
|
22
37
|
|
23
38
|
```python
|
@@ -28,11 +43,11 @@ from entitysdk.models.morphology import ReconstructionMorphology
|
|
28
43
|
|
29
44
|
# Initialize client
|
30
45
|
client = Client(
|
31
|
-
api_url="http://api.example.com",
|
32
46
|
project_context=ProjectContext(
|
33
47
|
project_id=UUID("your-project-id"),
|
34
48
|
virtual_lab_id=UUID("your-lab-id")
|
35
49
|
)
|
50
|
+
environment="staging"
|
36
51
|
)
|
37
52
|
|
38
53
|
# Search for morphologies
|
@@ -28,7 +28,13 @@
|
|
28
28
|
" project_id=\"0dbced5f-cc3d-488a-8c7f-cfb8ea039dc6\",\n",
|
29
29
|
")\n",
|
30
30
|
"client = Client(api_url=entitycore_api_url, project_context=project_context)\n",
|
31
|
-
"token = os.getenv(\"ACCESS_TOKEN\", \"XXX\")"
|
31
|
+
"token = os.getenv(\"ACCESS_TOKEN\", \"XXX\")\n",
|
32
|
+
"\n",
|
33
|
+
"# uncomment for staging\n",
|
34
|
+
"# from obi_auth import get_token\n",
|
35
|
+
"\n",
|
36
|
+
"# token = get_token(environment=\"staging\")\n",
|
37
|
+
"# client = Client(environment=\"staging\")"
|
32
38
|
]
|
33
39
|
},
|
34
40
|
{
|
@@ -239,7 +245,7 @@
|
|
239
245
|
"id": "fae8506b-9cbc-433b-a17d-6ce3d84bcf4c",
|
240
246
|
"metadata": {},
|
241
247
|
"source": [
|
242
|
-
"## Find morphologies
|
248
|
+
"## Find morphologies by mtype"
|
243
249
|
]
|
244
250
|
},
|
245
251
|
{
|
@@ -282,7 +288,7 @@
|
|
282
288
|
"name": "python",
|
283
289
|
"nbconvert_exporter": "python",
|
284
290
|
"pygments_lexer": "ipython3",
|
285
|
-
"version": "3.12.
|
291
|
+
"version": "3.12.10"
|
286
292
|
}
|
287
293
|
},
|
288
294
|
"nbformat": 4,
|
@@ -46,7 +46,14 @@
|
|
46
46
|
" project_id=\"0dbced5f-cc3d-488a-8c7f-cfb8ea039dc6\",\n",
|
47
47
|
")\n",
|
48
48
|
"client = Client(api_url=entitycore_api_url, project_context=project_context)\n",
|
49
|
-
"token = os.getenv(\"ACCESS_TOKEN\", \"XXX\")"
|
49
|
+
"token = os.getenv(\"ACCESS_TOKEN\", \"XXX\")\n",
|
50
|
+
"\n",
|
51
|
+
"# uncomment for staging\n",
|
52
|
+
"# from obi_auth import get_token\n",
|
53
|
+
"# token = get_token(environment=\"staging\")\n",
|
54
|
+
"# Replace this with your vlab project url in staging\n",
|
55
|
+
"# project_context = ProjectContext.from_vlab_url(\"https://staging.openbraininstitute.org/app/virtual-lab/lab/594fd60d-7a38-436f-939d-500feaa13bba/project/ff89ca07-6613-4922-9ab0-2637221db8b5/home\")\n",
|
56
|
+
"# client = Client(environment=\"staging\", project_context=project_context)"
|
50
57
|
]
|
51
58
|
},
|
52
59
|
{
|
@@ -92,13 +99,35 @@
|
|
92
99
|
{
|
93
100
|
"cell_type": "code",
|
94
101
|
"execution_count": null,
|
95
|
-
"id": "
|
102
|
+
"id": "e5dde536-0c58-4d42-a834-1b1a0ec17e9d",
|
96
103
|
"metadata": {},
|
97
104
|
"outputs": [],
|
98
105
|
"source": [
|
99
106
|
"rprint(strain)"
|
100
107
|
]
|
101
108
|
},
|
109
|
+
{
|
110
|
+
"cell_type": "code",
|
111
|
+
"execution_count": null,
|
112
|
+
"id": "5d42a174-9737-4477-830a-3dc908dea925",
|
113
|
+
"metadata": {},
|
114
|
+
"outputs": [],
|
115
|
+
"source": [
|
116
|
+
"brain_region = client.search_entity(\n",
|
117
|
+
" entity_type=BrainRegion, query={\"annotation_value\": 68}, token=token\n",
|
118
|
+
").one()"
|
119
|
+
]
|
120
|
+
},
|
121
|
+
{
|
122
|
+
"cell_type": "code",
|
123
|
+
"execution_count": null,
|
124
|
+
"id": "282200cd-ad0c-4bb3-bc21-88de85289179",
|
125
|
+
"metadata": {},
|
126
|
+
"outputs": [],
|
127
|
+
"source": [
|
128
|
+
"rprint(brain_region)"
|
129
|
+
]
|
130
|
+
},
|
102
131
|
{
|
103
132
|
"cell_type": "markdown",
|
104
133
|
"id": "a0193055-3448-4d1c-99cc-4d953727ef4e",
|
@@ -114,19 +143,11 @@
|
|
114
143
|
"metadata": {},
|
115
144
|
"outputs": [],
|
116
145
|
"source": [
|
117
|
-
"# No GET endpoint yet for brain-region\n",
|
118
|
-
"\n",
|
119
146
|
"brain_location = BrainLocation(\n",
|
120
147
|
" x=4101.52490234375,\n",
|
121
148
|
" y=1173.8499755859375,\n",
|
122
149
|
" z=4744.60009765625,\n",
|
123
150
|
")\n",
|
124
|
-
"brain_region = BrainRegion(\n",
|
125
|
-
" id=68,\n",
|
126
|
-
" name=\"Frontal pole, layer 1\",\n",
|
127
|
-
" acronym=\"FRP1\",\n",
|
128
|
-
" children=[],\n",
|
129
|
-
")\n",
|
130
151
|
"morphology = ReconstructionMorphology(\n",
|
131
152
|
" name=\"my-morph\",\n",
|
132
153
|
" description=\"A morphology\",\n",
|
@@ -153,7 +174,25 @@
|
|
153
174
|
"id": "83fb7e5e-73b5-4227-aa22-90bb789b0907",
|
154
175
|
"metadata": {},
|
155
176
|
"source": [
|
156
|
-
"## Register morphology
|
177
|
+
"## Register morphology"
|
178
|
+
]
|
179
|
+
},
|
180
|
+
{
|
181
|
+
"cell_type": "code",
|
182
|
+
"execution_count": null,
|
183
|
+
"id": "2e32a168",
|
184
|
+
"metadata": {},
|
185
|
+
"outputs": [],
|
186
|
+
"source": [
|
187
|
+
"registered = client.register_entity(entity=morphology, token=token)"
|
188
|
+
]
|
189
|
+
},
|
190
|
+
{
|
191
|
+
"cell_type": "markdown",
|
192
|
+
"id": "c0d500bd",
|
193
|
+
"metadata": {},
|
194
|
+
"source": [
|
195
|
+
"## Upload assets"
|
157
196
|
]
|
158
197
|
},
|
159
198
|
{
|
@@ -163,8 +202,6 @@
|
|
163
202
|
"metadata": {},
|
164
203
|
"outputs": [],
|
165
204
|
"source": [
|
166
|
-
"registered = client.register_entity(entity=morphology, token=token)\n",
|
167
|
-
"\n",
|
168
205
|
"with tempfile.TemporaryDirectory() as tdir:\n",
|
169
206
|
" file1 = Path(tdir, \"morph.h5\")\n",
|
170
207
|
" file1.write_text(\"h5\")\n",
|
@@ -428,7 +465,7 @@
|
|
428
465
|
"name": "python",
|
429
466
|
"nbconvert_exporter": "python",
|
430
467
|
"pygments_lexer": "ipython3",
|
431
|
-
"version": "3.12.
|
468
|
+
"version": "3.12.10"
|
432
469
|
}
|
433
470
|
},
|
434
471
|
"nbformat": 4,
|
entitysdk-0.2.0/examples/contribution.ipynb → entitysdk-0.2.2/examples/03_contribution.ipynb
RENAMED
@@ -23,7 +23,14 @@
|
|
23
23
|
" project_id=\"0dbced5f-cc3d-488a-8c7f-cfb8ea039dc6\",\n",
|
24
24
|
")\n",
|
25
25
|
"client = Client(api_url=entitycore_api_url, project_context=project_context)\n",
|
26
|
-
"token = os.getenv(\"ACCESS_TOKEN\", \"XXX\")"
|
26
|
+
"token = os.getenv(\"ACCESS_TOKEN\", \"XXX\")\n",
|
27
|
+
"\n",
|
28
|
+
"# uncomment for staging\n",
|
29
|
+
"# from obi_auth import get_token\n",
|
30
|
+
"# token = get_token(environment=\"staging\")\n",
|
31
|
+
"# Replace this with your vlab project url in staging\n",
|
32
|
+
"# project_context = ProjectContext.from_vlab_url(\"https://staging.openbraininstitute.org/app/virtual-lab/lab/594fd60d-7a38-436f-939d-500feaa13bba/project/ff89ca07-6613-4922-9ab0-2637221db8b5/home\")\n",
|
33
|
+
"# client = Client(environment=\"staging\", project_context=project_context)"
|
27
34
|
]
|
28
35
|
},
|
29
36
|
{
|
@@ -82,7 +89,7 @@
|
|
82
89
|
"outputs": [],
|
83
90
|
"source": [
|
84
91
|
"morphology = client.search_entity(\n",
|
85
|
-
" entity_type=ReconstructionMorphology, token=token, limit=1\n",
|
92
|
+
" entity_type=ReconstructionMorphology, token=token, limit=1, query={\"name__ilike\": \"my-morph\"}\n",
|
86
93
|
").first()"
|
87
94
|
]
|
88
95
|
},
|
@@ -135,6 +142,8 @@
|
|
135
142
|
"metadata": {},
|
136
143
|
"outputs": [],
|
137
144
|
"source": [
|
145
|
+
"# Note: It will fail if registered twice\n",
|
146
|
+
"# because there is a uniqueness constraint on (agent, morphology_id)\n",
|
138
147
|
"registered = client.register_entity(entity=contribution, token=token)"
|
139
148
|
]
|
140
149
|
},
|
@@ -193,7 +202,7 @@
|
|
193
202
|
"name": "python",
|
194
203
|
"nbconvert_exporter": "python",
|
195
204
|
"pygments_lexer": "ipython3",
|
196
|
-
"version": "3.12.
|
205
|
+
"version": "3.12.10"
|
197
206
|
}
|
198
207
|
},
|
199
208
|
"nbformat": 4,
|
@@ -0,0 +1,36 @@
|
|
1
|
+
"""BrainRegion model."""
|
2
|
+
|
3
|
+
from typing import Annotated
|
4
|
+
|
5
|
+
from pydantic import Field
|
6
|
+
|
7
|
+
from entitysdk.models.core import Identifiable
|
8
|
+
from entitysdk.typedef import ID
|
9
|
+
|
10
|
+
|
11
|
+
class BrainRegion(Identifiable):
|
12
|
+
"""BrainRegion model."""
|
13
|
+
|
14
|
+
name: Annotated[
|
15
|
+
str,
|
16
|
+
Field(
|
17
|
+
examples=["Thalamus"],
|
18
|
+
description="The name of the brain region.",
|
19
|
+
),
|
20
|
+
]
|
21
|
+
annotation_value: Annotated[
|
22
|
+
int, Field(examples=[997], description="The annotation voxel value.")
|
23
|
+
]
|
24
|
+
acronym: Annotated[
|
25
|
+
str,
|
26
|
+
Field(
|
27
|
+
examples=["TH"],
|
28
|
+
description="The acronym of the brain region.",
|
29
|
+
),
|
30
|
+
]
|
31
|
+
parent_structure_id: Annotated[
|
32
|
+
ID, Field(examples=[], description="The parent region structure UUID.")
|
33
|
+
]
|
34
|
+
hierarchy_id: Annotated[
|
35
|
+
ID, Field(examples=[], description="The brain hierarchy that includes this brain region.")
|
36
|
+
]
|
@@ -0,0 +1,158 @@
|
|
1
|
+
"""Ion channel model."""
|
2
|
+
|
3
|
+
from typing import Annotated
|
4
|
+
|
5
|
+
from pydantic import Field
|
6
|
+
|
7
|
+
from entitysdk.mixin import HasAssets
|
8
|
+
from entitysdk.models.base import BaseModel
|
9
|
+
from entitysdk.models.contribution import Contribution
|
10
|
+
from entitysdk.models.entity import Entity
|
11
|
+
from entitysdk.models.morphology import BrainRegion, License, Species, Strain
|
12
|
+
|
13
|
+
|
14
|
+
class UseIon(BaseModel):
|
15
|
+
"""Specifies how an ion is used in the mod file (USEION behavior)."""
|
16
|
+
|
17
|
+
ion_name: Annotated[
|
18
|
+
str,
|
19
|
+
Field(
|
20
|
+
description="The name of the ion involved.",
|
21
|
+
examples="Ca",
|
22
|
+
),
|
23
|
+
]
|
24
|
+
read: Annotated[
|
25
|
+
list[str] | None,
|
26
|
+
Field(
|
27
|
+
description="Variables listed in the READ statement for this ion.",
|
28
|
+
examples=["eca", "ica"],
|
29
|
+
),
|
30
|
+
]
|
31
|
+
write: Annotated[
|
32
|
+
list[str] | None,
|
33
|
+
Field(
|
34
|
+
description="Variables listed in the WRITE statement for this ion.",
|
35
|
+
examples=["ica"],
|
36
|
+
),
|
37
|
+
]
|
38
|
+
valence: Annotated[
|
39
|
+
int | None,
|
40
|
+
Field(
|
41
|
+
description="VALENCE of the ion, if specified.",
|
42
|
+
examples=2,
|
43
|
+
),
|
44
|
+
]
|
45
|
+
main_ion: Annotated[
|
46
|
+
bool | None,
|
47
|
+
Field(
|
48
|
+
description="Whether this ion is the main ion for the mechanism.",
|
49
|
+
examples=True,
|
50
|
+
),
|
51
|
+
] = None
|
52
|
+
|
53
|
+
|
54
|
+
class NeuronBlock(BaseModel):
|
55
|
+
"""Variables declared in the NEURON block of the mod file."""
|
56
|
+
|
57
|
+
global_: Annotated[
|
58
|
+
list[dict[str, str | None]] | None,
|
59
|
+
Field(
|
60
|
+
description="Variables listed in the GLOBAL statement, with associated units.",
|
61
|
+
examples=[{"celsius": "degree C"}],
|
62
|
+
),
|
63
|
+
] = None
|
64
|
+
range: Annotated[
|
65
|
+
list[dict[str, str | None]] | None,
|
66
|
+
Field(
|
67
|
+
description="Variables listed in the RANGE statement, with associated units.",
|
68
|
+
examples=[{"gCa_HVAbar": "S/cm2"}, {"ica": "mA/cm2"}],
|
69
|
+
),
|
70
|
+
] = None
|
71
|
+
useion: Annotated[
|
72
|
+
list[UseIon] | None,
|
73
|
+
Field(
|
74
|
+
description="Ion-specific READ/WRITE/VALENCE declarations from USEION.",
|
75
|
+
),
|
76
|
+
] = None
|
77
|
+
nonspecific: Annotated[
|
78
|
+
list[dict[str, str | None]] | None,
|
79
|
+
Field(
|
80
|
+
description="Variables listed in NONSPECIFIC_CURRENT statements.",
|
81
|
+
examples=[{"ihcn": "mA/cm2"}],
|
82
|
+
),
|
83
|
+
] = None
|
84
|
+
|
85
|
+
|
86
|
+
class IonChannelModel(HasAssets, Entity):
|
87
|
+
"""Ion channel mechanism model."""
|
88
|
+
|
89
|
+
name: Annotated[
|
90
|
+
str,
|
91
|
+
Field(
|
92
|
+
description="The name of the ion channel model "
|
93
|
+
"(e.g., the SUFFIX or POINT_PROCESS name).",
|
94
|
+
examples="Ca_HVA",
|
95
|
+
),
|
96
|
+
]
|
97
|
+
nmodl_suffix: Annotated[
|
98
|
+
str,
|
99
|
+
Field(
|
100
|
+
description="The SUFFIX of the ion channel model as defined in the NMODL file ",
|
101
|
+
examples="Ca_HVA",
|
102
|
+
),
|
103
|
+
]
|
104
|
+
description: Annotated[
|
105
|
+
str,
|
106
|
+
Field(
|
107
|
+
description="A description of the ion channel mechanism.",
|
108
|
+
examples="High-voltage activated calcium channel",
|
109
|
+
),
|
110
|
+
]
|
111
|
+
species: Annotated[
|
112
|
+
Species,
|
113
|
+
Field(description="The species for which the mechanism applies."),
|
114
|
+
]
|
115
|
+
strain: Annotated[
|
116
|
+
Strain | None,
|
117
|
+
Field(description="The specific strain of the species, if applicable."),
|
118
|
+
] = None
|
119
|
+
brain_region: Annotated[
|
120
|
+
BrainRegion,
|
121
|
+
Field(description="The brain region where the mechanism is used or applies."),
|
122
|
+
]
|
123
|
+
license: Annotated[
|
124
|
+
License | None,
|
125
|
+
Field(description="License under which the mechanism is distributed."),
|
126
|
+
] = None
|
127
|
+
contributions: Annotated[
|
128
|
+
list[Contribution] | None,
|
129
|
+
Field(description="List of contributions related to this mechanism."),
|
130
|
+
] = None
|
131
|
+
is_ljp_corrected: Annotated[
|
132
|
+
bool,
|
133
|
+
Field(
|
134
|
+
description="Whether the mechanism is corrected for liquid junction potential.",
|
135
|
+
),
|
136
|
+
] = False
|
137
|
+
is_temperature_dependent: Annotated[
|
138
|
+
bool,
|
139
|
+
Field(
|
140
|
+
description="Whether the mechanism includes temperature dependence "
|
141
|
+
"(e.g. via q10 factor).",
|
142
|
+
),
|
143
|
+
]
|
144
|
+
temperature_celsius: Annotated[
|
145
|
+
int,
|
146
|
+
Field(description="The temperature at which the mechanism has been built to work on."),
|
147
|
+
]
|
148
|
+
is_stochastic: Annotated[
|
149
|
+
bool | None,
|
150
|
+
Field(
|
151
|
+
description="Whether the mechanism has stochastic behavior.",
|
152
|
+
),
|
153
|
+
] = False
|
154
|
+
neuron_block: Annotated[
|
155
|
+
NeuronBlock,
|
156
|
+
Field(description="Variables declared in the NEURON block of the mod file."),
|
157
|
+
]
|
158
|
+
legacy_id: list[str] | None = None
|
@@ -5,6 +5,7 @@ from typing import Annotated
|
|
5
5
|
from pydantic import Field
|
6
6
|
|
7
7
|
from entitysdk.mixin import HasAssets
|
8
|
+
from entitysdk.models.brain_region import BrainRegion
|
8
9
|
from entitysdk.models.contribution import Contribution
|
9
10
|
from entitysdk.models.core import Struct
|
10
11
|
from entitysdk.models.entity import Entity
|
@@ -38,40 +39,6 @@ class License(Entity):
|
|
38
39
|
]
|
39
40
|
|
40
41
|
|
41
|
-
class BrainRegion(Entity):
|
42
|
-
"""BrainRegion model."""
|
43
|
-
|
44
|
-
id: Annotated[
|
45
|
-
int,
|
46
|
-
Field(
|
47
|
-
examples=[1, 2],
|
48
|
-
description="The region's id.",
|
49
|
-
),
|
50
|
-
] # type: ignore
|
51
|
-
|
52
|
-
name: Annotated[
|
53
|
-
str,
|
54
|
-
Field(
|
55
|
-
examples=["Prefrontal Cortex"],
|
56
|
-
description="The name of the brain region.",
|
57
|
-
),
|
58
|
-
]
|
59
|
-
acronym: Annotated[
|
60
|
-
str,
|
61
|
-
Field(
|
62
|
-
examples=["PFC"],
|
63
|
-
description="The acronym of the brain region.",
|
64
|
-
),
|
65
|
-
]
|
66
|
-
children: Annotated[
|
67
|
-
list[int],
|
68
|
-
Field(
|
69
|
-
examples=[1, 2],
|
70
|
-
description="The children of the brain region hierarchy.",
|
71
|
-
),
|
72
|
-
]
|
73
|
-
|
74
|
-
|
75
42
|
class BrainLocation(Struct):
|
76
43
|
"""BrainLocation model."""
|
77
44
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: entitysdk
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.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,6 +39,21 @@ entitysdk is a Python library for interacting with the [entitycore service][enti
|
|
39
39
|
```bash
|
40
40
|
pip install entitysdk
|
41
41
|
```
|
42
|
+
|
43
|
+
## Obtaining a valid access token
|
44
|
+
|
45
|
+
An access token can be retrieved easily using the obi-auth helper library.
|
46
|
+
|
47
|
+
```bash
|
48
|
+
pip install obi-auth
|
49
|
+
```
|
50
|
+
|
51
|
+
```python
|
52
|
+
from obi_auth import get_token
|
53
|
+
|
54
|
+
access_token = get_token(environment="staging")
|
55
|
+
```
|
56
|
+
|
42
57
|
## Quick Start
|
43
58
|
|
44
59
|
```python
|
@@ -49,11 +64,11 @@ from entitysdk.models.morphology import ReconstructionMorphology
|
|
49
64
|
|
50
65
|
# Initialize client
|
51
66
|
client = Client(
|
52
|
-
api_url="http://api.example.com",
|
53
67
|
project_context=ProjectContext(
|
54
68
|
project_id=UUID("your-project-id"),
|
55
69
|
virtual_lab_id=UUID("your-lab-id")
|
56
70
|
)
|
71
|
+
environment="staging"
|
57
72
|
)
|
58
73
|
|
59
74
|
# Search for morphologies
|
@@ -7,9 +7,9 @@ pyproject.toml
|
|
7
7
|
tox.ini
|
8
8
|
.github/workflows/sdist.yml
|
9
9
|
.github/workflows/tox.yml
|
10
|
-
examples/
|
11
|
-
examples/
|
12
|
-
examples/
|
10
|
+
examples/01_searching.ipynb
|
11
|
+
examples/02_morphology.ipynb
|
12
|
+
examples/03_contribution.ipynb
|
13
13
|
src/entitysdk/__init__.py
|
14
14
|
src/entitysdk/client.py
|
15
15
|
src/entitysdk/common.py
|
@@ -32,9 +32,11 @@ src/entitysdk/models/__init__.py
|
|
32
32
|
src/entitysdk/models/agent.py
|
33
33
|
src/entitysdk/models/asset.py
|
34
34
|
src/entitysdk/models/base.py
|
35
|
+
src/entitysdk/models/brain_region.py
|
35
36
|
src/entitysdk/models/contribution.py
|
36
37
|
src/entitysdk/models/core.py
|
37
38
|
src/entitysdk/models/entity.py
|
39
|
+
src/entitysdk/models/ion_channel_model.py
|
38
40
|
src/entitysdk/models/morphology.py
|
39
41
|
src/entitysdk/models/mtype.py
|
40
42
|
src/entitysdk/models/response.py
|
@@ -57,7 +59,10 @@ tests/unit/util.py
|
|
57
59
|
tests/unit/models/__init__.py
|
58
60
|
tests/unit/models/test_agent.py
|
59
61
|
tests/unit/models/test_asset.py
|
62
|
+
tests/unit/models/test_brain_region.py
|
60
63
|
tests/unit/models/test_contribution.py
|
64
|
+
tests/unit/models/test_ion_channel_model.py
|
61
65
|
tests/unit/models/test_morphology.py
|
62
66
|
tests/unit/models/data/.gitignore
|
67
|
+
tests/unit/models/data/ion_channel_model.json
|
63
68
|
tests/unit/models/data/reconstruction_morphology.json
|
@@ -0,0 +1,114 @@
|
|
1
|
+
{
|
2
|
+
"id": "b8f38c7f-2675-4c6a-a394-f3a60a9a3e6f",
|
3
|
+
"update_date": "2024-10-29T13:36:30.827776Z",
|
4
|
+
"creation_date": "2024-09-10T14:25:03.707956Z",
|
5
|
+
"createdBy": null,
|
6
|
+
"updatedBy": null,
|
7
|
+
"authorized_public": true,
|
8
|
+
"authorized_project_id": "c73ac3a5-3b7d-41bc-92e7-9f9309a49300",
|
9
|
+
"name": "Ca_HVA",
|
10
|
+
"nmodl_suffix": "Ca_HVA",
|
11
|
+
"brain_region": {
|
12
|
+
"id": "38553ac8-7d71-4591-bfee-2fc72e2dffdf",
|
13
|
+
"update_date": "2025-05-09T13:32:18.034672Z",
|
14
|
+
"creation_date": "2025-05-09T13:32:18.034672Z",
|
15
|
+
"name": "Accessory abducens nucleus",
|
16
|
+
"annotation_value": 568,
|
17
|
+
"acronym": "ACVI",
|
18
|
+
"parent_structure_id": "596305b3-71b2-41e4-afd3-b9f2e90f79f8",
|
19
|
+
"hierarchy_id": "e3e70682-c209-4cac-a29f-6fbed82c07cd"
|
20
|
+
},
|
21
|
+
"description": "High-voltage activated calcium channel",
|
22
|
+
"species": {
|
23
|
+
"id": "0895fa61-fa6d-4674-9014-7300f9edf8da",
|
24
|
+
"update_date": "2025-03-29T16:48:36.175090Z",
|
25
|
+
"creation_date": "2025-03-29T16:48:36.175090Z",
|
26
|
+
"createdBy": null,
|
27
|
+
"updatedBy": null,
|
28
|
+
"authorized_public": null,
|
29
|
+
"authorized_project_id": null,
|
30
|
+
"name": "Rattus norvegicus",
|
31
|
+
"taxonomy_id": "NCBITaxon:10116"
|
32
|
+
},
|
33
|
+
"strain": null,
|
34
|
+
"license": null,
|
35
|
+
"contributions": [
|
36
|
+
{
|
37
|
+
"id": "7f43ce20-e63d-48c1-bc73-dabb38ee181b",
|
38
|
+
"update_date": "2025-03-29T16:49:12.449364Z",
|
39
|
+
"creation_date": "2025-03-29T16:49:12.449364Z",
|
40
|
+
"agent": {
|
41
|
+
"id": "f27cfa11-d1bc-4a14-b651-174bb53674ff",
|
42
|
+
"update_date": "2021-04-14T09:51:14.062000Z",
|
43
|
+
"creation_date": "2021-04-14T09:51:14.062000Z",
|
44
|
+
"type": "organization",
|
45
|
+
"pref_label": "École Polytechnique Fédérale de Lausanne",
|
46
|
+
"alternative_name": ""
|
47
|
+
},
|
48
|
+
"role": {
|
49
|
+
"id": "8b06e557-277b-4b0c-a439-bfb02d41927c",
|
50
|
+
"update_date": "2025-03-29T16:48:36.192831Z",
|
51
|
+
"creation_date": "2025-03-29T16:48:36.192831Z",
|
52
|
+
"name": "unspecified",
|
53
|
+
"role_id": "unspecified"
|
54
|
+
},
|
55
|
+
"entity": null
|
56
|
+
}
|
57
|
+
],
|
58
|
+
"is_ljp_corrected": false,
|
59
|
+
"is_temperature_dependent": true,
|
60
|
+
"temperature_celsius": 36,
|
61
|
+
"is_stochastic": true,
|
62
|
+
"neuron_block": {
|
63
|
+
"global_": [
|
64
|
+
{"gna": "S/cm2"},
|
65
|
+
{"gk": "S/cm2"}
|
66
|
+
],
|
67
|
+
"range": [
|
68
|
+
{"gCa_HVAbar": "S/cm2"},
|
69
|
+
{"ica": "mA/cm2"}
|
70
|
+
],
|
71
|
+
"useion": [
|
72
|
+
{
|
73
|
+
"ion_name": "Ca",
|
74
|
+
"read": ["eca"],
|
75
|
+
"write": ["ica"],
|
76
|
+
"valence": 2,
|
77
|
+
"main_ion": true
|
78
|
+
}
|
79
|
+
],
|
80
|
+
"nonspecific": [{"ihcn": "mA/cm2"}]
|
81
|
+
},
|
82
|
+
"assets": [
|
83
|
+
{
|
84
|
+
"id": "a90bab5c-8529-4829-99fc-e90a270e8b30",
|
85
|
+
"path": "Ca_HVA.mod",
|
86
|
+
"full_path": "public/a98b7abc-fc46-4700-9e3d-37137812c730/0dbced5f-cc3d-488a-8c7f-cfb8ea039dc6/assets/ion_channel_model/9720aa4a-0cd1-4f10-b6ad-04deb8f997b6/Ca_HVA.mod",
|
87
|
+
"is_directory": false,
|
88
|
+
"content_type": "application/swc",
|
89
|
+
"size": 561221,
|
90
|
+
"sha256_digest": "8b850eface3e7b881db62c361dc5da62be008ca81501c406a59646bf7075c95b",
|
91
|
+
"status": "created",
|
92
|
+
"creation_date": null,
|
93
|
+
"update_date": null,
|
94
|
+
"meta": {
|
95
|
+
"legacy": {
|
96
|
+
"@id": "https://bbp.epfl.ch/data/public/morphologies/42315b31-081f-4d40-8b94-b72dbd16c99e",
|
97
|
+
"name": "Ca_HVA.mod",
|
98
|
+
"@type": "DataDownload",
|
99
|
+
"digest": {
|
100
|
+
"value": "8b850eface3e7b881db62c361dc5da62be008ca81501c406a59646bf7075c95b",
|
101
|
+
"algorithm": "SHA-256"
|
102
|
+
},
|
103
|
+
"atLocation": {
|
104
|
+
"@type": "Location",
|
105
|
+
"store": {"@id": "nxv:diskStorageDefault", "_rev": 1, "@type": "DiskStorage"}
|
106
|
+
},
|
107
|
+
"contentUrl": "https://bbp.epfl.ch/nexus/v1/files/public/morphologies/https:%2F%2Fbbp.epfl.ch%2Fdata%2Fpublic%2Fmorphologies%2F42315b31-081f-4d40-8b94-b72dbd16c99e",
|
108
|
+
"contentSize": {"value": 561221, "unitCode": "bytes"},
|
109
|
+
"encodingFormat": "application/mod"
|
110
|
+
}
|
111
|
+
}
|
112
|
+
}
|
113
|
+
]
|
114
|
+
}
|
@@ -13,7 +13,6 @@
|
|
13
13
|
"creation_date": null,
|
14
14
|
"path": "mpg150211_A_idA.swc",
|
15
15
|
"full_path": "public/a98b7abc-fc46-4700-9e3d-37137812c730/0dbced5f-cc3d-488a-8c7f-cfb8ea039dc6/assets/reconstruction_morphology/9720aa4a-0cd1-4f10-b6ad-04deb8f997b6/mpg150211_A_idA.swc",
|
16
|
-
"bucket_name": "entitycore-data-dev",
|
17
16
|
"is_directory": false,
|
18
17
|
"content_type": "application/swc",
|
19
18
|
"size": 561221,
|
@@ -51,7 +50,6 @@
|
|
51
50
|
"creation_date": null,
|
52
51
|
"path": "mpg150211_A_idA.ASC",
|
53
52
|
"full_path": "public/a98b7abc-fc46-4700-9e3d-37137812c730/0dbced5f-cc3d-488a-8c7f-cfb8ea039dc6/assets/reconstruction_morphology/9720aa4a-0cd1-4f10-b6ad-04deb8f997b6/mpg150211_A_idA.ASC",
|
54
|
-
"bucket_name": "entitycore-data-dev",
|
55
53
|
"is_directory": false,
|
56
54
|
"content_type": "application/asc",
|
57
55
|
"size": 525332,
|
@@ -87,16 +85,14 @@
|
|
87
85
|
"name": "mpg150211_A_idA",
|
88
86
|
"location": null,
|
89
87
|
"brain_region": {
|
90
|
-
"id":
|
91
|
-
"update_date": "2025-
|
92
|
-
"creation_date": "2025-
|
93
|
-
"
|
94
|
-
"
|
95
|
-
"
|
96
|
-
"
|
97
|
-
"
|
98
|
-
"acronym": "CA1sp",
|
99
|
-
"children": []
|
88
|
+
"id": "38553ac8-7d71-4591-bfee-2fc72e2dffdf",
|
89
|
+
"update_date": "2025-05-09T13:32:18.034672Z",
|
90
|
+
"creation_date": "2025-05-09T13:32:18.034672Z",
|
91
|
+
"name": "Accessory abducens nucleus",
|
92
|
+
"annotation_value": 568,
|
93
|
+
"acronym": "ACVI",
|
94
|
+
"parent_structure_id": "596305b3-71b2-41e4-afd3-b9f2e90f79f8",
|
95
|
+
"hierarchy_id": "e3e70682-c209-4cac-a29f-6fbed82c07cd"
|
100
96
|
},
|
101
97
|
"description": "Neuronal morphology of excitatory neuron cell 'mpg150211_A_idA' in Field CA1, pyramidal layer of cell type SR_PC. A neuron that releases excitatory neurotransmitters. This neuron doesn't have axon, has a basal dendrite and apical dendrite.",
|
102
98
|
"species": {
|
@@ -8,7 +8,6 @@ def test_asset():
|
|
8
8
|
id=MOCK_UUID,
|
9
9
|
path="path/to/asset",
|
10
10
|
full_path="full/path/to/asset",
|
11
|
-
bucket_name="bucket_name",
|
12
11
|
is_directory=False,
|
13
12
|
content_type="text/plain",
|
14
13
|
size=100,
|
@@ -20,7 +19,6 @@ def test_asset():
|
|
20
19
|
"id": MOCK_UUID,
|
21
20
|
"path": "path/to/asset",
|
22
21
|
"full_path": "full/path/to/asset",
|
23
|
-
"bucket_name": "bucket_name",
|
24
22
|
"is_directory": False,
|
25
23
|
"content_type": "text/plain",
|
26
24
|
"size": 100,
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import pytest
|
2
|
+
|
3
|
+
from entitysdk.models.brain_region import BrainRegion
|
4
|
+
|
5
|
+
|
6
|
+
@pytest.fixture
|
7
|
+
def json_data():
|
8
|
+
return {
|
9
|
+
"id": "38553ac8-7d71-4591-bfee-2fc72e2dffdf",
|
10
|
+
"update_date": "2025-05-09T13:32:18.034672Z",
|
11
|
+
"creation_date": "2025-05-09T13:32:18.034672Z",
|
12
|
+
"name": "Accessory abducens nucleus",
|
13
|
+
"annotation_value": 568,
|
14
|
+
"acronym": "ACVI",
|
15
|
+
"parent_structure_id": "596305b3-71b2-41e4-afd3-b9f2e90f79f8",
|
16
|
+
"hierarchy_id": "e3e70682-c209-4cac-a29f-6fbed82c07cd",
|
17
|
+
}
|
18
|
+
|
19
|
+
|
20
|
+
def test_model(json_data):
|
21
|
+
res = BrainRegion.model_validate(json_data)
|
22
|
+
assert res.model_dump(mode="json") == json_data
|
@@ -0,0 +1,60 @@
|
|
1
|
+
import json
|
2
|
+
from pathlib import Path
|
3
|
+
|
4
|
+
import pytest
|
5
|
+
|
6
|
+
from entitysdk.models.ion_channel_model import IonChannelModel
|
7
|
+
|
8
|
+
from ..util import MOCK_UUID
|
9
|
+
|
10
|
+
DATA_DIR = Path(__file__).parent / "data"
|
11
|
+
|
12
|
+
|
13
|
+
@pytest.fixture
|
14
|
+
def json_ion_channel_expanded():
|
15
|
+
return json.loads(Path(DATA_DIR / "ion_channel_model.json").read_bytes())
|
16
|
+
|
17
|
+
|
18
|
+
@pytest.fixture
|
19
|
+
def ion_channel_model(json_ion_channel_expanded):
|
20
|
+
return IonChannelModel.model_validate(json_ion_channel_expanded)
|
21
|
+
|
22
|
+
|
23
|
+
def test_read_ion_channel_model(client, httpx_mock, auth_token, json_ion_channel_expanded):
|
24
|
+
httpx_mock.add_response(method="GET", json=json_ion_channel_expanded)
|
25
|
+
entity = client.get_entity(
|
26
|
+
entity_id=MOCK_UUID,
|
27
|
+
entity_type=IonChannelModel,
|
28
|
+
token=auth_token,
|
29
|
+
with_assets=False,
|
30
|
+
)
|
31
|
+
assert entity.model_dump(mode="json") == json_ion_channel_expanded | {"legacy_id": None}
|
32
|
+
|
33
|
+
|
34
|
+
def test_register_ion_channel_model(
|
35
|
+
client, httpx_mock, auth_token, ion_channel_model, json_ion_channel_expanded
|
36
|
+
):
|
37
|
+
httpx_mock.add_response(
|
38
|
+
method="POST", json=ion_channel_model.model_dump(mode="json") | {"id": str(MOCK_UUID)}
|
39
|
+
)
|
40
|
+
registered = client.register_entity(entity=ion_channel_model, token=auth_token)
|
41
|
+
expected_json = json_ion_channel_expanded.copy() | {"id": str(MOCK_UUID)}
|
42
|
+
assert registered.model_dump(mode="json") == expected_json | {"legacy_id": None}
|
43
|
+
|
44
|
+
|
45
|
+
def test_update_ion_channel_model(
|
46
|
+
client, httpx_mock, auth_token, ion_channel_model, json_ion_channel_expanded
|
47
|
+
):
|
48
|
+
httpx_mock.add_response(
|
49
|
+
method="PATCH",
|
50
|
+
json=ion_channel_model.model_dump(mode="json") | {"name": "foo"},
|
51
|
+
)
|
52
|
+
updated = client.update_entity(
|
53
|
+
entity_id=ion_channel_model.id,
|
54
|
+
entity_type=IonChannelModel,
|
55
|
+
attrs_or_entity={"name": "foo"},
|
56
|
+
token=auth_token,
|
57
|
+
)
|
58
|
+
|
59
|
+
expected_json = json_ion_channel_expanded.copy() | {"name": "foo"}
|
60
|
+
assert updated.model_dump(mode="json") == expected_json | {"legacy_id": None}
|
@@ -133,7 +133,6 @@ def _mock_asset_response(asset_id):
|
|
133
133
|
"id": str(asset_id),
|
134
134
|
"path": "path/to/asset",
|
135
135
|
"full_path": "full/path/to/asset",
|
136
|
-
"bucket_name": "bucket_name",
|
137
136
|
"is_directory": False,
|
138
137
|
"content_type": "text/plain",
|
139
138
|
"size": 100,
|
@@ -315,7 +314,6 @@ def _mock_asset_delete_response(asset_id):
|
|
315
314
|
return {
|
316
315
|
"path": "buffer.h5",
|
317
316
|
"full_path": "private/103d7868/103d7868/assets/reconstruction_morphology/8703/buffer.h5",
|
318
|
-
"bucket_name": "obi-private",
|
319
317
|
"is_directory": False,
|
320
318
|
"content_type": "application/swc",
|
321
319
|
"size": 18,
|
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
|