benchling-sdk 1.9.0a5__py3-none-any.whl → 1.10.0__py3-none-any.whl
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.
- benchling_sdk/apps/canvas/__init__.py +0 -0
- benchling_sdk/apps/canvas/errors.py +14 -0
- benchling_sdk/apps/{helpers/canvas_helpers.py → canvas/framework.py} +129 -188
- benchling_sdk/apps/canvas/types.py +125 -0
- benchling_sdk/apps/config/__init__.py +0 -3
- benchling_sdk/apps/config/decryption_provider.py +1 -1
- benchling_sdk/apps/config/errors.py +38 -0
- benchling_sdk/apps/config/framework.py +343 -0
- benchling_sdk/apps/config/helpers.py +157 -0
- benchling_sdk/apps/config/{mock_dependencies.py → mock_config.py} +78 -99
- benchling_sdk/apps/config/types.py +36 -0
- benchling_sdk/apps/framework.py +49 -338
- benchling_sdk/apps/helpers/webhook_helpers.py +2 -2
- benchling_sdk/apps/status/__init__.py +0 -0
- benchling_sdk/apps/status/errors.py +85 -0
- benchling_sdk/apps/{helpers/session_helpers.py → status/framework.py} +58 -167
- benchling_sdk/apps/status/helpers.py +20 -0
- benchling_sdk/apps/status/types.py +45 -0
- benchling_sdk/apps/types.py +3 -0
- benchling_sdk/errors.py +4 -4
- benchling_sdk/models/__init__.py +44 -0
- benchling_sdk/services/v2/beta/{v2_beta_dataset_service.py → v2_beta_data_frame_service.py} +126 -116
- benchling_sdk/services/v2/stable/assay_result_service.py +18 -0
- benchling_sdk/services/v2/v2_beta_service.py +11 -11
- {benchling_sdk-1.9.0a5.dist-info → benchling_sdk-1.10.0.dist-info}/METADATA +4 -4
- {benchling_sdk-1.9.0a5.dist-info → benchling_sdk-1.10.0.dist-info}/RECORD +29 -20
- benchling_sdk/apps/config/dependencies.py +0 -1085
- benchling_sdk/apps/config/scalars.py +0 -226
- benchling_sdk/apps/helpers/config_helpers.py +0 -409
- /benchling_sdk/apps/{helpers → config}/cryptography_helpers.py +0 -0
- {benchling_sdk-1.9.0a5.dist-info → benchling_sdk-1.10.0.dist-info}/LICENSE +0 -0
- {benchling_sdk-1.9.0a5.dist-info → benchling_sdk-1.10.0.dist-info}/WHEEL +0 -0
@@ -4,77 +4,79 @@ from pathlib import Path
|
|
4
4
|
import tempfile
|
5
5
|
from typing import Dict, List, Optional, Union
|
6
6
|
|
7
|
-
from benchling_api_client.v2.beta.api.
|
8
|
-
from benchling_api_client.v2.beta.models.
|
9
|
-
from benchling_api_client.v2.beta.models.
|
10
|
-
from benchling_api_client.v2.beta.models.
|
11
|
-
|
7
|
+
from benchling_api_client.v2.beta.api.data_frames import create_data_frame, get_data_frame, patch_data_frame
|
8
|
+
from benchling_api_client.v2.beta.models.data_frame import DataFrame
|
9
|
+
from benchling_api_client.v2.beta.models.data_frame_create import DataFrameCreate
|
10
|
+
from benchling_api_client.v2.beta.models.data_frame_create_manifest_manifest_item import (
|
11
|
+
DataFrameCreateManifestManifestItem,
|
12
12
|
)
|
13
|
-
from benchling_api_client.v2.beta.models.
|
14
|
-
from benchling_api_client.v2.beta.models.
|
13
|
+
from benchling_api_client.v2.beta.models.data_frame_update import DataFrameUpdate
|
14
|
+
from benchling_api_client.v2.beta.models.data_frame_update_upload_status import DataFrameUpdateUploadStatus
|
15
15
|
from benchling_api_client.v2.beta.models.file_status_upload_status import FileStatusUploadStatus
|
16
16
|
from benchling_api_client.v2.types import Response
|
17
17
|
import httpx
|
18
18
|
|
19
|
-
from benchling_sdk.errors import
|
19
|
+
from benchling_sdk.errors import DataFrameInProgressError, InvalidDataFrameError, raise_for_status
|
20
20
|
from benchling_sdk.helpers.decorators import api_method
|
21
21
|
from benchling_sdk.helpers.response_helpers import model_from_detailed
|
22
22
|
from benchling_sdk.models import AsyncTaskLink
|
23
23
|
from benchling_sdk.services.v2.base_service import BaseService
|
24
24
|
|
25
|
-
|
25
|
+
_DEFAULT_HTTP_TIMEOUT_UPLOAD_DATA_FRAME: float = 60.0
|
26
26
|
|
27
27
|
|
28
|
-
class
|
28
|
+
class V2BetaDataFrameService(BaseService):
|
29
29
|
"""
|
30
|
-
V2-Beta
|
30
|
+
V2-Beta Data Frames.
|
31
31
|
|
32
|
-
|
32
|
+
Data Frames are Benchling objects that represent tabular data with typed columns and rows of data.
|
33
33
|
|
34
|
-
See https://benchling.com/api/v2-beta/reference#/
|
34
|
+
See https://benchling.com/api/v2-beta/reference#/Data%20Frames
|
35
35
|
"""
|
36
36
|
|
37
37
|
@api_method
|
38
|
-
def get_by_id(self,
|
38
|
+
def get_by_id(self, data_frame_id: str) -> DataFrame:
|
39
39
|
"""
|
40
|
-
Get a
|
40
|
+
Get a data frame and URLs to download its data.
|
41
41
|
|
42
|
-
See https://benchling.com/api/v2-beta/reference#/
|
42
|
+
See https://benchling.com/api/v2-beta/reference#/Data%20Frames/getDataFrame
|
43
43
|
"""
|
44
|
-
response =
|
44
|
+
response = get_data_frame.sync_detailed(client=self.client, data_frame_id=data_frame_id)
|
45
45
|
return model_from_detailed(response)
|
46
46
|
|
47
47
|
@api_method
|
48
|
-
def create(self,
|
48
|
+
def create(self, data_frame: DataFrameCreate) -> DataFrame:
|
49
49
|
"""
|
50
|
-
Create a
|
50
|
+
Create a data frame.
|
51
51
|
|
52
|
-
See https://benchling.com/api/v2-beta/reference#/
|
52
|
+
See https://benchling.com/api/v2-beta/reference#/Data%20Frames/createDataFrame
|
53
53
|
"""
|
54
|
-
response =
|
54
|
+
response = create_data_frame.sync_detailed(client=self.client, json_body=data_frame)
|
55
55
|
return model_from_detailed(response)
|
56
56
|
|
57
57
|
@api_method
|
58
|
-
def update(self,
|
58
|
+
def update(self, data_frame_id: str, data_frame: DataFrameUpdate) -> AsyncTaskLink:
|
59
59
|
"""
|
60
|
-
Update a
|
60
|
+
Update a data frame.
|
61
61
|
|
62
|
-
See https://benchling.com/api/v2-beta/reference#/
|
62
|
+
See https://benchling.com/api/v2-beta/reference#/Data%20Frames/patchDataFrame
|
63
63
|
"""
|
64
|
-
response =
|
64
|
+
response = patch_data_frame.sync_detailed(
|
65
|
+
client=self.client, data_frame_id=data_frame_id, json_body=data_frame
|
66
|
+
)
|
65
67
|
return model_from_detailed(response)
|
66
68
|
|
67
69
|
def upload_bytes(
|
68
70
|
self,
|
69
71
|
url: str,
|
70
72
|
input_bytes: Union[BytesIO, bytes],
|
71
|
-
timeout_seconds: float =
|
73
|
+
timeout_seconds: float = _DEFAULT_HTTP_TIMEOUT_UPLOAD_DATA_FRAME,
|
72
74
|
) -> None:
|
73
|
-
"""Upload bytes to an existing
|
75
|
+
"""Upload bytes to an existing data frame.
|
74
76
|
|
75
|
-
:param url: The url provided by Benchling for uploading to the
|
77
|
+
:param url: The url provided by Benchling for uploading to the data frame
|
76
78
|
:param input_bytes: Data to upload as bytes or BytesIO
|
77
|
-
:param timeout_seconds: Extends the normal HTTP timeout settings since
|
79
|
+
:param timeout_seconds: Extends the normal HTTP timeout settings since DataFrame uploads can be large
|
78
80
|
Use this to extend even further if streams are very large
|
79
81
|
"""
|
80
82
|
# Use a completely different client instead of our configured self.client.httpx_client
|
@@ -86,17 +88,19 @@ class V2BetaDatasetService(BaseService):
|
|
86
88
|
raise_for_status(response)
|
87
89
|
|
88
90
|
def upload_file(
|
89
|
-
self, url: str, file: Path, timeout_seconds: float =
|
91
|
+
self, url: str, file: Path, timeout_seconds: float = _DEFAULT_HTTP_TIMEOUT_UPLOAD_DATA_FRAME
|
90
92
|
) -> None:
|
91
|
-
"""Upload a file to an existing
|
93
|
+
"""Upload a file to an existing data frame.
|
92
94
|
|
93
|
-
:param url: The url provided by Benchling for uploading to the
|
95
|
+
:param url: The url provided by Benchling for uploading to the data frame
|
94
96
|
:param file: A valid Path to an existing file containing the data to upload
|
95
|
-
:param timeout_seconds: Extends the normal HTTP timeout settings since
|
97
|
+
:param timeout_seconds: Extends the normal HTTP timeout settings since DataFrame uploads can be large
|
96
98
|
Use this to extend even further if streams are very large
|
97
99
|
"""
|
98
100
|
if file.is_dir():
|
99
|
-
raise IsADirectoryError(
|
101
|
+
raise IsADirectoryError(
|
102
|
+
f"Cannot write data frame from directory '{file}', specify a file instead"
|
103
|
+
)
|
100
104
|
# Use a completely different client instead of our configured self.client.httpx_client
|
101
105
|
# Amazon will reject clients sending other headers besides the ones it expects
|
102
106
|
files = {"file": open(file, "rb")}
|
@@ -107,113 +111,117 @@ class V2BetaDatasetService(BaseService):
|
|
107
111
|
@api_method
|
108
112
|
def create_from_bytes(
|
109
113
|
self,
|
110
|
-
|
114
|
+
data_frame: DataFrameCreate,
|
111
115
|
input_bytes: Union[BytesIO, bytes],
|
112
|
-
timeout_seconds: float =
|
116
|
+
timeout_seconds: float = _DEFAULT_HTTP_TIMEOUT_UPLOAD_DATA_FRAME,
|
113
117
|
) -> AsyncTaskLink:
|
114
|
-
"""Create a
|
118
|
+
"""Create a data frame from bytes or BytesIO data.
|
115
119
|
|
116
|
-
:param
|
120
|
+
:param data_frame: The DataFrameCreate specification for the data. This must be provided, as it cannot be inferred from file names.
|
117
121
|
:param input_bytes: Data to upload as bytes or BytesIO
|
118
|
-
:param timeout_seconds: Extends the normal HTTP timeout settings since
|
122
|
+
:param timeout_seconds: Extends the normal HTTP timeout settings since DataFrame uploads can be large
|
119
123
|
Use this to extend even further if streams are very large
|
120
|
-
:return: An AsyncTaskLink that can be polled to know when the
|
124
|
+
:return: An AsyncTaskLink that can be polled to know when the data frame has completed processing
|
121
125
|
:rtype: AsyncTaskLink
|
122
126
|
"""
|
123
|
-
# This is a current limit of the
|
127
|
+
# This is a current limit of the DataFrame API. We may need additional methods in the future
|
124
128
|
# to allow multi upload
|
125
|
-
if not
|
126
|
-
raise
|
127
|
-
elif len(
|
128
|
-
raise
|
129
|
-
f"The
|
129
|
+
if not data_frame.manifest:
|
130
|
+
raise InvalidDataFrameError("The data frame manifest must contain exactly 1 item")
|
131
|
+
elif len(data_frame.manifest) != 1:
|
132
|
+
raise InvalidDataFrameError(
|
133
|
+
f"The data frame manifest contains {len(data_frame.manifest)} items. It must contain exactly 1"
|
130
134
|
)
|
131
|
-
|
132
|
-
manifest_item =
|
135
|
+
created_data_frame = self.create(data_frame)
|
136
|
+
manifest_item = created_data_frame.manifest[0]
|
133
137
|
|
134
138
|
# This would be unexpected and probably an error from the API return. Likely not a user error. This check appeases MyPy.
|
135
139
|
if manifest_item.url is None:
|
136
|
-
raise
|
137
|
-
f"The
|
140
|
+
raise InvalidDataFrameError(
|
141
|
+
f"The data frame manifest URL is None. The data frame {created_data_frame.id} is not available for data upload."
|
138
142
|
)
|
139
143
|
self.upload_bytes(url=manifest_item.url, input_bytes=input_bytes, timeout_seconds=timeout_seconds)
|
140
|
-
|
141
|
-
return self.update(
|
144
|
+
data_frame_update = DataFrameUpdate(upload_status=DataFrameUpdateUploadStatus.IN_PROGRESS)
|
145
|
+
return self.update(data_frame_id=created_data_frame.id, data_frame=data_frame_update)
|
142
146
|
|
143
147
|
@api_method
|
144
148
|
def create_from_file(
|
145
149
|
self,
|
146
150
|
file: Path,
|
147
|
-
|
148
|
-
timeout_seconds: float =
|
151
|
+
data_frame: Optional[DataFrameCreate] = None,
|
152
|
+
timeout_seconds: float = _DEFAULT_HTTP_TIMEOUT_UPLOAD_DATA_FRAME,
|
149
153
|
) -> AsyncTaskLink:
|
150
|
-
"""Create a
|
154
|
+
"""Create a data frame from file data.
|
151
155
|
|
152
156
|
:param file: A valid Path to an existing file containing the data to upload
|
153
|
-
:param
|
154
|
-
:param timeout_seconds: Extends the normal HTTP timeout settings since
|
157
|
+
:param data_frame: The DataFrameCreate specification for the data. If not provided, it will be inferred from the file name
|
158
|
+
:param timeout_seconds: Extends the normal HTTP timeout settings since DataFrame uploads can be large
|
155
159
|
Use this to extend even further if streams are very large
|
156
|
-
:return: An AsyncTaskLink that can be polled to know when the
|
160
|
+
:return: An AsyncTaskLink that can be polled to know when the data frame has completed processing
|
157
161
|
:rtype: AsyncTaskLink
|
158
162
|
"""
|
159
163
|
if file.is_dir():
|
160
|
-
raise IsADirectoryError(
|
164
|
+
raise IsADirectoryError(
|
165
|
+
f"Cannot write data frame from directory '{file}', specify a file instead"
|
166
|
+
)
|
161
167
|
with open(file, "rb") as file_handle:
|
162
168
|
input_bytes = file_handle.read()
|
163
|
-
if not
|
164
|
-
|
169
|
+
if not data_frame:
|
170
|
+
data_frame = DataFrameCreate(
|
165
171
|
name=f"{datetime.now()} {file.name}",
|
166
|
-
manifest=[
|
172
|
+
manifest=[DataFrameCreateManifestManifestItem(file_name=file.name)],
|
167
173
|
)
|
168
174
|
return self.create_from_bytes(
|
169
|
-
|
175
|
+
data_frame=data_frame, input_bytes=input_bytes, timeout_seconds=timeout_seconds
|
170
176
|
)
|
171
177
|
|
172
|
-
def
|
173
|
-
self,
|
178
|
+
def download_data_frame_bytes(
|
179
|
+
self, data_frame: DataFrame, timeout_seconds: float = _DEFAULT_HTTP_TIMEOUT_UPLOAD_DATA_FRAME
|
174
180
|
) -> List[BytesIO]:
|
175
|
-
"""Download
|
181
|
+
"""Download data frame data to bytes.
|
176
182
|
|
177
|
-
:param
|
178
|
-
:param timeout_seconds: Extends the normal HTTP timeout settings since
|
183
|
+
:param data_frame: The data frame to download
|
184
|
+
:param timeout_seconds: Extends the normal HTTP timeout settings since DataFrame uploads can be large
|
179
185
|
Use this to extend even further if streams are very large
|
180
|
-
:return: An ordered list of BytesIO streams corresponding to a manifest item in the
|
186
|
+
:return: An ordered list of BytesIO streams corresponding to a manifest item in the data frame
|
181
187
|
:rtype: List[BytesIO]
|
182
188
|
"""
|
183
|
-
if
|
184
|
-
raise
|
185
|
-
f"The
|
186
|
-
f"The status of
|
189
|
+
if data_frame.upload_status != FileStatusUploadStatus.SUCCEEDED:
|
190
|
+
raise DataFrameInProgressError(
|
191
|
+
f"The data frame data cannot be downloaded until the status is {FileStatusUploadStatus.SUCCEEDED}. "
|
192
|
+
f"The status of data frame {data_frame.id} is {data_frame.upload_status}"
|
187
193
|
)
|
188
|
-
|
189
|
-
for manifest_item in
|
194
|
+
data_frame_bytes = []
|
195
|
+
for manifest_item in data_frame.manifest:
|
190
196
|
# This should be present based on the status check above. Assertion satisfies MyPy
|
191
|
-
assert
|
197
|
+
assert (
|
198
|
+
manifest_item.url is not None
|
199
|
+
), f"Unable to download data frame {data_frame.id}, URL was empty"
|
192
200
|
with httpx.stream("GET", manifest_item.url, timeout=timeout_seconds) as download_stream:
|
193
201
|
target_bytes = BytesIO()
|
194
202
|
for chunk in download_stream.iter_bytes():
|
195
203
|
target_bytes.write(chunk)
|
196
204
|
target_bytes.seek(0)
|
197
|
-
|
198
|
-
return
|
205
|
+
data_frame_bytes.append(target_bytes)
|
206
|
+
return data_frame_bytes
|
199
207
|
|
200
|
-
def
|
208
|
+
def download_data_frame_files(
|
201
209
|
self,
|
202
|
-
|
210
|
+
data_frame: DataFrame,
|
203
211
|
destination_path: Optional[Path] = None,
|
204
|
-
timeout_seconds: float =
|
212
|
+
timeout_seconds: float = _DEFAULT_HTTP_TIMEOUT_UPLOAD_DATA_FRAME,
|
205
213
|
) -> List[Path]:
|
206
|
-
"""Download
|
214
|
+
"""Download data frame data to files.
|
207
215
|
|
208
|
-
:param
|
216
|
+
:param data_frame: The data frame to download
|
209
217
|
:param destination_path: A target directory to place the files. File names will be created based on the manifest item file names.
|
210
218
|
If not specified, a temp directory will be created. The caller is responsible for deleting this directory.
|
211
|
-
:param timeout_seconds: Extends the normal HTTP timeout settings since
|
219
|
+
:param timeout_seconds: Extends the normal HTTP timeout settings since DataFrame uploads can be large
|
212
220
|
Use this to extend even further if streams are very large
|
213
|
-
:return: An ordered list of downloaded file paths corresponding to a manifest item in the
|
221
|
+
:return: An ordered list of downloaded file paths corresponding to a manifest item in the data frame
|
214
222
|
:rtype: List[Path]
|
215
223
|
"""
|
216
|
-
|
224
|
+
data_frame_files = []
|
217
225
|
if not destination_path:
|
218
226
|
destination_path = Path(tempfile.mkdtemp())
|
219
227
|
elif destination_path.is_file():
|
@@ -222,61 +230,63 @@ class V2BetaDatasetService(BaseService):
|
|
222
230
|
)
|
223
231
|
elif not destination_path.exists():
|
224
232
|
raise NotADirectoryError(f"The destination path '{destination_path}' does not exist")
|
225
|
-
if
|
226
|
-
raise
|
227
|
-
f"The
|
228
|
-
f"The status of
|
233
|
+
if data_frame.upload_status != FileStatusUploadStatus.SUCCEEDED:
|
234
|
+
raise DataFrameInProgressError(
|
235
|
+
f"The data frame data cannot be downloaded until the status is {FileStatusUploadStatus.SUCCEEDED}. "
|
236
|
+
f"The status of data frame {data_frame.id} is {data_frame.upload_status}"
|
229
237
|
)
|
230
|
-
for manifest_item in
|
238
|
+
for manifest_item in data_frame.manifest:
|
231
239
|
target_path = destination_path / manifest_item.file_name
|
232
|
-
|
240
|
+
data_frame_files.append(target_path)
|
233
241
|
# This should be present based on the status check above. Assertion satisfies MyPy
|
234
|
-
assert
|
235
|
-
|
242
|
+
assert (
|
243
|
+
manifest_item.url is not None
|
244
|
+
), f"Unable to download data frame {data_frame.id}, URL was empty"
|
245
|
+
with open(target_path, "wb") as data_frame_handle:
|
236
246
|
with httpx.stream("GET", manifest_item.url, timeout=timeout_seconds) as download_stream:
|
237
247
|
for chunk in download_stream.iter_bytes():
|
238
|
-
|
239
|
-
return
|
248
|
+
data_frame_handle.write(chunk)
|
249
|
+
return data_frame_files
|
240
250
|
|
241
251
|
@api_method
|
242
|
-
def
|
243
|
-
self,
|
252
|
+
def download_data_frame_bytes_by_id(
|
253
|
+
self, data_frame_id: str, timeout_seconds: float = _DEFAULT_HTTP_TIMEOUT_UPLOAD_DATA_FRAME
|
244
254
|
) -> List[BytesIO]:
|
245
|
-
"""Download
|
255
|
+
"""Download data frame data to files by data_frame_id.
|
246
256
|
|
247
|
-
Fetches the
|
257
|
+
Fetches the data frame first, then downloads the files.
|
248
258
|
|
249
|
-
:param
|
250
|
-
:param timeout_seconds: Extends the normal HTTP timeout settings since
|
259
|
+
:param data_frame_id: The id of the data frame to download
|
260
|
+
:param timeout_seconds: Extends the normal HTTP timeout settings since DataFrame uploads can be large
|
251
261
|
Use this to extend even further if streams are very large
|
252
|
-
:return: An ordered list of BytesIO streams corresponding to a manifest item in the
|
262
|
+
:return: An ordered list of BytesIO streams corresponding to a manifest item in the data frame
|
253
263
|
:rtype: List[BytesIO]
|
254
264
|
"""
|
255
|
-
|
256
|
-
return self.
|
265
|
+
data_frame = self.get_by_id(data_frame_id=data_frame_id)
|
266
|
+
return self.download_data_frame_bytes(data_frame=data_frame, timeout_seconds=timeout_seconds)
|
257
267
|
|
258
268
|
@api_method
|
259
|
-
def
|
269
|
+
def download_data_frame_files_by_id(
|
260
270
|
self,
|
261
|
-
|
271
|
+
data_frame_id: str,
|
262
272
|
destination_path: Optional[Path] = None,
|
263
|
-
timeout_seconds: float =
|
273
|
+
timeout_seconds: float = _DEFAULT_HTTP_TIMEOUT_UPLOAD_DATA_FRAME,
|
264
274
|
) -> List[Path]:
|
265
|
-
"""Download
|
275
|
+
"""Download data frame data to files by data_frame_id.
|
266
276
|
|
267
|
-
Fetches the
|
277
|
+
Fetches the data frame first, then downloads the files.
|
268
278
|
|
269
|
-
:param
|
279
|
+
:param data_frame_id: The id of the data frame to download
|
270
280
|
:param destination_path: A target directory to place the files. File names will be created based on the manifest item file names.
|
271
281
|
If not specified, a temp directory will be created. The caller is responsible for deleting this directory.
|
272
|
-
:param timeout_seconds: Extends the normal HTTP timeout settings since
|
282
|
+
:param timeout_seconds: Extends the normal HTTP timeout settings since DataFrame uploads can be large
|
273
283
|
Use this to extend even further if streams are very large
|
274
|
-
:return: An ordered list of downloaded file paths corresponding to a manifest item in the
|
284
|
+
:return: An ordered list of downloaded file paths corresponding to a manifest item in the data frame
|
275
285
|
:rtype: List[Path]
|
276
286
|
"""
|
277
|
-
|
278
|
-
return self.
|
279
|
-
|
287
|
+
data_frame = self.get_by_id(data_frame_id=data_frame_id)
|
288
|
+
return self.download_data_frame_files(
|
289
|
+
data_frame=data_frame, destination_path=destination_path, timeout_seconds=timeout_seconds
|
280
290
|
)
|
281
291
|
|
282
292
|
|
@@ -3,6 +3,7 @@ from typing import Iterable, List, Optional, Union
|
|
3
3
|
from benchling_api_client.v2.stable.api.assay_results import (
|
4
4
|
abort_assay_results_transaction,
|
5
5
|
archive_assay_results,
|
6
|
+
bulk_create_assay_results,
|
6
7
|
bulk_get_assay_results,
|
7
8
|
commit_assay_results_transaction,
|
8
9
|
create_assay_results,
|
@@ -31,10 +32,12 @@ from benchling_sdk.models import (
|
|
31
32
|
AssayResultIdsRequest,
|
32
33
|
AssayResultIdsResponse,
|
33
34
|
AssayResultsArchive,
|
35
|
+
AssayResultsBulkCreateInTableRequest,
|
34
36
|
AssayResultsBulkCreateRequest,
|
35
37
|
AssayResultsCreateResponse,
|
36
38
|
AssayResultsPaginatedList,
|
37
39
|
AssayResultTransactionCreateResponse,
|
40
|
+
AsyncTaskLink,
|
38
41
|
ListAssayResultsSort,
|
39
42
|
)
|
40
43
|
from benchling_sdk.services.v2.base_service import BaseService
|
@@ -196,6 +199,21 @@ class AssayResultService(BaseService):
|
|
196
199
|
response = create_assay_results.sync_detailed(client=self.client, json_body=create_results)
|
197
200
|
return model_from_detailed(response)
|
198
201
|
|
202
|
+
@api_method
|
203
|
+
def bulk_create(
|
204
|
+
self, assay_results: Iterable[AssayResultCreate], table_id: Optional[str] = None
|
205
|
+
) -> AsyncTaskLink:
|
206
|
+
"""
|
207
|
+
Create 1 or more results.
|
208
|
+
|
209
|
+
See https://benchling.com/api/reference#/Assay%20Results/bulkCreateAssayResults
|
210
|
+
"""
|
211
|
+
request_body = AssayResultsBulkCreateInTableRequest(
|
212
|
+
assay_results=list(assay_results), **({"table_id": table_id} if table_id else {})
|
213
|
+
)
|
214
|
+
response = bulk_create_assay_results.sync_detailed(client=self.client, json_body=request_body)
|
215
|
+
return model_from_detailed(response)
|
216
|
+
|
199
217
|
@api_method
|
200
218
|
def archive(self, assay_result_ids: Iterable[str]) -> AssayResultIdsResponse:
|
201
219
|
"""
|
@@ -7,7 +7,7 @@ from benchling_api_client.v2.stable.client import Client
|
|
7
7
|
from benchling_sdk.helpers.client_helpers import v2_beta_client
|
8
8
|
from benchling_sdk.helpers.retry_helpers import RetryStrategy
|
9
9
|
from benchling_sdk.services.v2.base_service import BaseService
|
10
|
-
from benchling_sdk.services.v2.beta.
|
10
|
+
from benchling_sdk.services.v2.beta.v2_beta_data_frame_service import V2BetaDataFrameService
|
11
11
|
|
12
12
|
if TYPE_CHECKING:
|
13
13
|
from benchling_sdk.services.v2.beta.v2_beta_aa_sequence_service import V2BetaAaSequenceService
|
@@ -37,7 +37,7 @@ class V2BetaService(BaseService):
|
|
37
37
|
_app_service: Optional[V2BetaAppService]
|
38
38
|
_collaboration_service: Optional[V2BetaCollaborationService]
|
39
39
|
_custom_entity_service: Optional[V2BetaCustomEntityService]
|
40
|
-
|
40
|
+
_data_frame_service: Optional[V2BetaDataFrameService]
|
41
41
|
_dna_oligo_service: Optional[V2BetaDnaOligoService]
|
42
42
|
_dna_sequence_service: Optional[V2BetaDnaSequenceService]
|
43
43
|
_entity_service: Optional[V2BetaEntityService]
|
@@ -61,7 +61,7 @@ class V2BetaService(BaseService):
|
|
61
61
|
self._app_service = None
|
62
62
|
self._collaboration_service = None
|
63
63
|
self._custom_entity_service = None
|
64
|
-
self.
|
64
|
+
self._data_frame_service = None
|
65
65
|
self._dna_sequence_service = None
|
66
66
|
self._dna_oligo_service = None
|
67
67
|
self._entity_service = None
|
@@ -137,19 +137,19 @@ class V2BetaService(BaseService):
|
|
137
137
|
return self._custom_entity_service
|
138
138
|
|
139
139
|
@property
|
140
|
-
def
|
140
|
+
def data_frames(self) -> V2BetaDataFrameService:
|
141
141
|
"""
|
142
|
-
V2-Beta
|
142
|
+
V2-Beta DataFrames.
|
143
143
|
|
144
|
-
|
144
|
+
DataFrames are Benchling objects that represent tabular data with typed columns and rows of data.
|
145
145
|
|
146
|
-
See https://benchling.com/api/v2-beta/reference#/
|
146
|
+
See https://benchling.com/api/v2-beta/reference#/Data%20Frames
|
147
147
|
"""
|
148
|
-
if self.
|
149
|
-
from benchling_sdk.services.v2.beta.
|
148
|
+
if self._data_frame_service is None:
|
149
|
+
from benchling_sdk.services.v2.beta.v2_beta_data_frame_service import V2BetaDataFrameService
|
150
150
|
|
151
|
-
self.
|
152
|
-
return self.
|
151
|
+
self._data_frame_service = V2BetaDataFrameService(self._beta_client, self.retry_strategy)
|
152
|
+
return self._data_frame_service
|
153
153
|
|
154
154
|
@property
|
155
155
|
def dna_oligos(self) -> V2BetaDnaOligoService:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: benchling-sdk
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.10.0
|
4
4
|
Summary: SDK for interacting with the Benchling Platform.
|
5
5
|
License: Apache-2.0
|
6
6
|
Author: Benchling Support
|
@@ -17,12 +17,12 @@ Provides-Extra: python-jose
|
|
17
17
|
Requires-Dist: PyYAML (>=6.0,<7.0)
|
18
18
|
Requires-Dist: attrs (>=20.1.0,<23)
|
19
19
|
Requires-Dist: backoff (>=1.10.0,<2.0.0)
|
20
|
-
Requires-Dist: benchling-api-client (==2.0.
|
20
|
+
Requires-Dist: benchling-api-client (==2.0.254)
|
21
21
|
Requires-Dist: certifi (>=2022.12.7)
|
22
|
-
Requires-Dist: cryptography (>=41.0.
|
22
|
+
Requires-Dist: cryptography (>=41.0.7,<42.0.0) ; extra == "cryptography"
|
23
23
|
Requires-Dist: dataclasses-json (>=0.5.2,<0.6.0)
|
24
24
|
Requires-Dist: httpx (>=0.23.0)
|
25
|
-
Requires-Dist: jwcrypto (>=1.
|
25
|
+
Requires-Dist: jwcrypto (>=1.5.1,<2.0.0)
|
26
26
|
Requires-Dist: ordered-set (>=4.1.0,<5.0.0)
|
27
27
|
Requires-Dist: psutil (>=5.9.4,<6.0.0) ; python_version >= "3.11" and python_version < "4.0"
|
28
28
|
Requires-Dist: python-dateutil (>=2.8.0,<3.0.0)
|
@@ -1,19 +1,28 @@
|
|
1
1
|
LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
2
2
|
benchling_sdk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
3
|
benchling_sdk/apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
|
-
benchling_sdk/apps/
|
5
|
-
benchling_sdk/apps/
|
6
|
-
benchling_sdk/apps/
|
7
|
-
benchling_sdk/apps/
|
8
|
-
benchling_sdk/apps/config/
|
9
|
-
benchling_sdk/apps/
|
4
|
+
benchling_sdk/apps/canvas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
+
benchling_sdk/apps/canvas/errors.py,sha256=5YTZOhSV-O0WqURjB1a676BIO429drCKfz5aQjsezms,358
|
6
|
+
benchling_sdk/apps/canvas/framework.py,sha256=IfgQP8Nut_TYB3ZNiWwuKdEG0uSDMn-r4xoogECStvk,24505
|
7
|
+
benchling_sdk/apps/canvas/types.py,sha256=tmuU0kpzd1pXqxs3X6x5kjWpCZJrJMb6hnfN1CbtFG4,3613
|
8
|
+
benchling_sdk/apps/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
+
benchling_sdk/apps/config/cryptography_helpers.py,sha256=VCzgQURLAitYjcjdwFzMPSKZ7MOD6ghxFdbPGA_6RbY,1778
|
10
|
+
benchling_sdk/apps/config/decryption_provider.py,sha256=-HgjkBto8mYlooV0LXFenfaiP7PDhHRnKEHkK1P6gh4,2184
|
11
|
+
benchling_sdk/apps/config/errors.py,sha256=-qkfLdcUTuuRD-V4L2l7nzQWnWTRuifDtkNDv8tfHoo,800
|
12
|
+
benchling_sdk/apps/config/framework.py,sha256=a2cIkPugEVUfBNtHm2cbE3Qu326xb-SpMuM0Gi6U-3Q,13337
|
13
|
+
benchling_sdk/apps/config/helpers.py,sha256=LTLDR0GCDoo_8Sx4kepQnMmgVEQT7MHfKAxIoAvV9TM,7077
|
14
|
+
benchling_sdk/apps/config/mock_config.py,sha256=EPUCxWiUSsWxWilnHAJIq-_f1q6ckZkXoIFv1S25hnM,26967
|
15
|
+
benchling_sdk/apps/config/types.py,sha256=XKfSGv-75CU-j1XwfXBGq8zbtnkF-PQnuY6Z2U47-Tg,953
|
16
|
+
benchling_sdk/apps/framework.py,sha256=G15mv20FH7FLHJrnXMPcuFdUsP3Va-grvb5A4eq0Qlk,3175
|
10
17
|
benchling_sdk/apps/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
|
-
benchling_sdk/apps/helpers/canvas_helpers.py,sha256=9z3fGE4wtm37NkcWC9U5mpMYtfk0rbExZK4iw21rQ4s,25324
|
12
|
-
benchling_sdk/apps/helpers/config_helpers.py,sha256=Q-UPqGCh7Rs5TkzAr3g6dPgR4AYS1hNw7g1N3H4Q0Eg,16627
|
13
|
-
benchling_sdk/apps/helpers/cryptography_helpers.py,sha256=VCzgQURLAitYjcjdwFzMPSKZ7MOD6ghxFdbPGA_6RbY,1778
|
14
18
|
benchling_sdk/apps/helpers/manifest_helpers.py,sha256=yidiKA5mwWdAFR1ZSUu40QoG0Us-bc6V8tYHYqheEtM,945
|
15
|
-
benchling_sdk/apps/helpers/
|
16
|
-
benchling_sdk/apps/
|
19
|
+
benchling_sdk/apps/helpers/webhook_helpers.py,sha256=R5bk480BbvomQ0kK9RXsnsrMBn-qp1Vy7zPyW_5d2hw,7108
|
20
|
+
benchling_sdk/apps/status/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
|
+
benchling_sdk/apps/status/errors.py,sha256=BezqnaHkCG1QBscD4301NjSYBHu7BzdYEUKF90psuz0,2377
|
22
|
+
benchling_sdk/apps/status/framework.py,sha256=go0pyU5qgMCvsrTDXWk3V9FZwbaRHgfhEWtjIZ-JLEE,27418
|
23
|
+
benchling_sdk/apps/status/helpers.py,sha256=o8jdgdxUYdGh2j0Gb3AYoeXI9Bu-ubyIkgWBuCGLKgE,705
|
24
|
+
benchling_sdk/apps/status/types.py,sha256=vE7-_7ns3mvPRJoVv-GQxc3389dIIH4mcG0VDNWpVhQ,746
|
25
|
+
benchling_sdk/apps/types.py,sha256=TBTfAB3IOoZjZqzTOK25kN3b6RTU9Z7tOMdBbq6u8lA,110
|
17
26
|
benchling_sdk/auth/__init__.py,sha256=N4pJYVUnTLzg5HO9ZldHaI-Am97i6AOCdQS0M5QcVpA,120
|
18
27
|
benchling_sdk/auth/api_key_auth.py,sha256=Ui-cnvGMjcwVPV_b2GdBaoTjEyHJIu9CjtZScVBEUvU,641
|
19
28
|
benchling_sdk/auth/bearer_token_auth.py,sha256=nymI8V91evcnK-TWKkBXZwck8U1qSh4WaseyQbvF-Cg,1268
|
@@ -21,7 +30,7 @@ benchling_sdk/auth/client_credentials_oauth2.py,sha256=LTcwtivobyhVRPJs7O2QpHW1N
|
|
21
30
|
benchling_sdk/benchling.py,sha256=eED0ge5hWspr1kFFZ1fOovPvw-JdVKhylAGT-n_GUSA,25943
|
22
31
|
benchling_sdk/docs/__init__.py,sha256=ySHo76PzLndmXOVWrF80VjB5Pi48G82CCQNdzUEzbCY,38
|
23
32
|
benchling_sdk/docs/__main__.py,sha256=1ZlGXdn2gHGC0fAuan5i54mh35VkDf5mhY9VeKNyCRA,244
|
24
|
-
benchling_sdk/errors.py,sha256=
|
33
|
+
benchling_sdk/errors.py,sha256=9JCjkY7wQ-K-_GStgYZrSns35FNExZSx-t5Xdlh-U0I,8239
|
25
34
|
benchling_sdk/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
26
35
|
benchling_sdk/helpers/client_helpers.py,sha256=o8pEyZlBq0eX2bhzRY7IwmGy2wIsI-L20YxSEL5q9m8,833
|
27
36
|
benchling_sdk/helpers/constants.py,sha256=dIJ83Qa4grP0n1NixmGNXsh-lK2VG-ioPpBd_AYBmlw,1094
|
@@ -34,7 +43,7 @@ benchling_sdk/helpers/response_helpers.py,sha256=vtmb9lEEKy3dRFre3Q0R4XaLBEaS_rr
|
|
34
43
|
benchling_sdk/helpers/retry_helpers.py,sha256=SeKOPjnJIes6UsD7kVqlYKBYmwH_DCHdllnG3jys3N8,2740
|
35
44
|
benchling_sdk/helpers/serialization_helpers.py,sha256=IUS0uGU_EiZvb8O-bTViUaROmxKcvdX3JeR9iKsWAG8,3662
|
36
45
|
benchling_sdk/helpers/transaction_manager.py,sha256=HcSDsgGK7Rb93bgv6fpb4HvQUT-tqP0lXgVa_bWCDh4,3663
|
37
|
-
benchling_sdk/models/__init__.py,sha256=
|
46
|
+
benchling_sdk/models/__init__.py,sha256=8gcaBsR_w-2-0jfpj75sl4UPgXrghiO5e1zNAywQkWY,335509
|
38
47
|
benchling_sdk/models/webhooks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
39
48
|
benchling_sdk/models/webhooks/v0/__init__.py,sha256=4n1NDjsKwvdQTGTpNjvzCBq4ZMwv4wtImkETMCX-TdM,6836
|
40
49
|
benchling_sdk/py.typed,sha256=8ZJUsxZiuOy1oJeVhsTWQhTG_6pTVHVXk5hJL79ebTk,25
|
@@ -49,7 +58,7 @@ benchling_sdk/services/v2/beta/v2_beta_aa_sequence_service.py,sha256=Y7E56Z8Piuu
|
|
49
58
|
benchling_sdk/services/v2/beta/v2_beta_app_service.py,sha256=nVOEQ3ESkUo2e4p_MYMq-VUpEx2wNpJIY7ZZ8UuHnuQ,1385
|
50
59
|
benchling_sdk/services/v2/beta/v2_beta_collaboration_service.py,sha256=epLHLdDRfj8ni2-45WWFSpOgQG-kTmbxTffRP1mnim0,5753
|
51
60
|
benchling_sdk/services/v2/beta/v2_beta_custom_entity_service.py,sha256=qpKQ8X_oiyDv_KIEeD9eTo6kGU9hkNlUqqjAdMZQPiM,1840
|
52
|
-
benchling_sdk/services/v2/beta/
|
61
|
+
benchling_sdk/services/v2/beta/v2_beta_data_frame_service.py,sha256=oqCVyYBK7YECXYIDWJ5VIaiAO-W7GXC7xd0Wy1swTmU,14853
|
53
62
|
benchling_sdk/services/v2/beta/v2_beta_dna_oligo_service.py,sha256=s2XZMItVJjJp3lZZ7YLh1GbV_cdIKLPOVqglKcAWMNg,1704
|
54
63
|
benchling_sdk/services/v2/beta/v2_beta_dna_sequence_service.py,sha256=wLN9lTF-faBrofQHlw3uKilaQvdOgSDI2oFa1GeuViY,1843
|
55
64
|
benchling_sdk/services/v2/beta/v2_beta_entity_service.py,sha256=NKYYdqZz6umnbGHb2syWr5E2ECwrPfoeWp5O--dhpaA,1970
|
@@ -62,7 +71,7 @@ benchling_sdk/services/v2/stable/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRk
|
|
62
71
|
benchling_sdk/services/v2/stable/aa_sequence_service.py,sha256=3RCNwyFBrryQowC9fbLoQHSSqKyGA6TQ0VQYBUyeg1U,11782
|
63
72
|
benchling_sdk/services/v2/stable/api_service.py,sha256=e0RNp4Jne9UTaHOYMOxxXJpsyUO3WMSFPzN7hB8iliU,12371
|
64
73
|
benchling_sdk/services/v2/stable/app_service.py,sha256=dy9FMVvMiJrkYbxZswKuB37EB9K_jCqQr9FfAa0BMgE,23126
|
65
|
-
benchling_sdk/services/v2/stable/assay_result_service.py,sha256=
|
74
|
+
benchling_sdk/services/v2/stable/assay_result_service.py,sha256=_qtSpMznVrGHlB2VnHI87IPjVQHCX1pZbLPJ_LYuW7U,13362
|
66
75
|
benchling_sdk/services/v2/stable/assay_run_service.py,sha256=tLpG1pAztEoaDatqlgYlRZ_LgwDly1_UeWt4G4UXvd4,9023
|
67
76
|
benchling_sdk/services/v2/stable/blob_service.py,sha256=KwchH3FGzPLfZx85GEG3voQp_ZxyVL_dds_9awRWa0Q,17115
|
68
77
|
benchling_sdk/services/v2/stable/box_service.py,sha256=M40smqG-jQlioyRfLBu9Cr9aQmdh06crsYbH1fiZ0BM,12359
|
@@ -103,10 +112,10 @@ benchling_sdk/services/v2/stable/workflow_output_service.py,sha256=VD0RvOBCkgX_Y
|
|
103
112
|
benchling_sdk/services/v2/stable/workflow_task_group_service.py,sha256=SSfHDH-Eniz09HG_qSPSfSVHU3BpvTbgGhOQS4iWcAw,8848
|
104
113
|
benchling_sdk/services/v2/stable/workflow_task_service.py,sha256=pOhwFmWVk1jh3A9C70LpLhYjlgk2DcGCfjO8Uup9ScQ,12819
|
105
114
|
benchling_sdk/services/v2/v2_alpha_service.py,sha256=vNfYK0Dheml9ozR_0tzTlA3blPDTdfTQR8ppaQ6xuu4,2609
|
106
|
-
benchling_sdk/services/v2/v2_beta_service.py,sha256=
|
115
|
+
benchling_sdk/services/v2/v2_beta_service.py,sha256=0vbjFFfPQNUGUhckR_cnzGjypRMBpBP6c5c49zrA3mk,11564
|
107
116
|
benchling_sdk/services/v2/v2_stable_service.py,sha256=YIc-_0p6x1NQqj7awnWgCTHxbxYO7ZOolePZyW90whc,35246
|
108
117
|
benchling_sdk/services/v2_service.py,sha256=3eoIjYEmGLPdWCpBN0pl7q7_HNWCsUvfvTn3Hcz0wSM,2860
|
109
|
-
benchling_sdk-1.
|
110
|
-
benchling_sdk-1.
|
111
|
-
benchling_sdk-1.
|
112
|
-
benchling_sdk-1.
|
118
|
+
benchling_sdk-1.10.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
119
|
+
benchling_sdk-1.10.0.dist-info/METADATA,sha256=96nD7POAvcaO-ZwLdG5VsGMEO7wqVS6rl-2qLIZNCvk,2124
|
120
|
+
benchling_sdk-1.10.0.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
|
121
|
+
benchling_sdk-1.10.0.dist-info/RECORD,,
|