|
3 | 3 | import json
|
4 | 4 | import pandas
|
5 | 5 | from getpass import getpass
|
6 |
| -from typing import Any, Dict, List, Union, Optional |
| 6 | +from typing import ( |
| 7 | + Any, |
| 8 | + Dict, |
| 9 | + List, |
| 10 | + TypeVar, |
| 11 | + Union, |
| 12 | + Optional, |
| 13 | +) |
7 | 14 | from functools import lru_cache
|
8 | 15 | from requests_toolbelt.multipart.encoder import MultipartEncoder
|
9 | 16 |
|
|
20 | 27 | from ...resources.scaleset import ScaleSet
|
21 | 28 |
|
22 | 29 |
|
| 30 | +CE = TypeVar("CE", bound=Union[Attachment, Compensation, Experiment, FcsFile, Gate, Plot, Population, ScaleSet]) |
| 31 | + |
23 | 32 | class APIClient(BaseAPIClient, metaclass=Singleton):
|
24 | 33 | _API_NAME = "CellEngine Python Toolkit"
|
25 | 34 |
|
@@ -119,6 +128,53 @@ def update_entity(self, experiment_id, _id, entity_type, body) -> dict:
|
119 | 128 | json=body,
|
120 | 129 | )
|
121 | 130 |
|
| 131 | + def _get_path(self, entity: CE) -> str: |
| 132 | + fullpath = f"{self.base_url}/{entity.path}" |
| 133 | + return fullpath |
| 134 | + |
| 135 | + def create(self, entity: CE, **kwargs) -> CE: |
| 136 | + """Create a local entity on CellEngine.""" |
| 137 | + if type(entity) is list: |
| 138 | + return self.create_multiple(entity, **kwargs) # type: ignore |
| 139 | + path = self._get_path(entity) |
| 140 | + structure_class = entity.__class__ |
| 141 | + if structure_class.__bases__[0] is not object: |
| 142 | + structure_class = structure_class.__bases__[0] |
| 143 | + body = converter.unstructure(entity) |
| 144 | + |
| 145 | + if body["_id"] == "None" or body["_id"] is None: |
| 146 | + del body["_id"] # https://github.com/primitybio/cellengine/issues/5800 |
| 147 | + |
| 148 | + res = self._post(path, json=body, params=kwargs) |
| 149 | + return converter.structure(res, structure_class) # type: ignore |
| 150 | + |
| 151 | + # TODO: add type annotation for entities |
| 152 | + def create_multiple(self, entities: List[CE], **kwargs) -> List[CE]: |
| 153 | + path = self._get_path(entities[0]) |
| 154 | + structure_class = entities[0].__class__ |
| 155 | + if structure_class.__bases__[0] is not object: |
| 156 | + structure_class = structure_class.__bases__[0] |
| 157 | + structure_class = List[structure_class] |
| 158 | + |
| 159 | + body = converter.unstructure(entities) |
| 160 | + |
| 161 | + for item in body: |
| 162 | + if item["_id"] == "None" or item["_id"] is None: |
| 163 | + del item["_id"] |
| 164 | + res = self._post(path, json=body, params=kwargs) |
| 165 | + return converter.structure(res, structure_class) |
| 166 | + |
| 167 | + def update(self, entity): |
| 168 | + # TODO: entity.path property |
| 169 | + path = self._get_path(entity) |
| 170 | + data = converter.unstructure(entity) |
| 171 | + res = self._patch(path, json=data,) |
| 172 | + return converter.structure(res, entity.__class__) |
| 173 | + |
| 174 | + def delete(self, entity) -> None: |
| 175 | + path = self._get_path(entity) |
| 176 | + self._delete(path) |
| 177 | + |
122 | 178 | def delete_entity(self, experiment_id, entity_type, _id):
|
123 | 179 | url = f"{self.base_url}/experiments/{experiment_id}/{entity_type}/{_id}"
|
124 | 180 | self._delete(url)
|
|
0 commit comments