datalab-api 0.2.6__tar.gz → 0.2.8__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.
- {datalab_api-0.2.6/src/datalab_api.egg-info → datalab_api-0.2.8}/PKG-INFO +10 -9
- {datalab_api-0.2.6 → datalab_api-0.2.8}/README.md +5 -5
- {datalab_api-0.2.6 → datalab_api-0.2.8}/pyproject.toml +6 -3
- {datalab_api-0.2.6 → datalab_api-0.2.8}/src/datalab_api/__init__.py +55 -5
- {datalab_api-0.2.6 → datalab_api-0.2.8}/src/datalab_api/_base.py +41 -23
- {datalab_api-0.2.6 → datalab_api-0.2.8/src/datalab_api.egg-info}/PKG-INFO +10 -9
- {datalab_api-0.2.6 → datalab_api-0.2.8}/src/datalab_api.egg-info/requires.txt +3 -2
- {datalab_api-0.2.6 → datalab_api-0.2.8}/tests/test_client.py +7 -3
- {datalab_api-0.2.6 → datalab_api-0.2.8}/LICENSE +0 -0
- {datalab_api-0.2.6 → datalab_api-0.2.8}/setup.cfg +0 -0
- {datalab_api-0.2.6 → datalab_api-0.2.8}/src/datalab_api/cli.py +0 -0
- {datalab_api-0.2.6 → datalab_api-0.2.8}/src/datalab_api/helpers.py +0 -0
- {datalab_api-0.2.6 → datalab_api-0.2.8}/src/datalab_api.egg-info/SOURCES.txt +0 -0
- {datalab_api-0.2.6 → datalab_api-0.2.8}/src/datalab_api.egg-info/dependency_links.txt +0 -0
- {datalab_api-0.2.6 → datalab_api-0.2.8}/src/datalab_api.egg-info/entry_points.txt +0 -0
- {datalab_api-0.2.6 → datalab_api-0.2.8}/src/datalab_api.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: datalab-api
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Summary: A Python API for instances of the datalab data management platform (https://github.com/the-grey-group/datalab).
|
|
5
5
|
Author-email: Matthew Evans <matthew@ml-evs.science>
|
|
6
6
|
License: MIT
|
|
@@ -24,10 +24,11 @@ License-File: LICENSE
|
|
|
24
24
|
Requires-Dist: httpx~=0.27
|
|
25
25
|
Requires-Dist: bokeh~=2.4
|
|
26
26
|
Requires-Dist: rich~=13.0
|
|
27
|
+
Requires-Dist: numpy<2
|
|
27
28
|
Provides-Extra: dev
|
|
28
|
-
Requires-Dist: pre-commit
|
|
29
|
+
Requires-Dist: pre-commit<5,>=3; extra == "dev"
|
|
29
30
|
Requires-Dist: pytest~=8.0; extra == "dev"
|
|
30
|
-
Requires-Dist: pytest-cov
|
|
31
|
+
Requires-Dist: pytest-cov<7,>=5; extra == "dev"
|
|
31
32
|
Requires-Dist: respx~=0.21; extra == "dev"
|
|
32
33
|
Provides-Extra: docs
|
|
33
34
|
Requires-Dist: mkdocs; extra == "docs"
|
|
@@ -56,11 +57,11 @@ Requires-Dist: datalab-api[cli,dev,docs]; extra == "all"
|
|
|
56
57
|
<a href="https://pypi.org/datalab-api"><img src="https://img.shields.io/pypi/pyversions/datalab-api?logo=python&label=Python%20versions" /></a>
|
|
57
58
|
</div>
|
|
58
59
|
|
|
59
|
-
A simple Python API that can interact with [*datalab*](https://github.com/
|
|
60
|
+
A simple Python API that can interact with [*datalab*](https://github.com/datalab-org/datalab) instances.
|
|
60
61
|
|
|
61
62
|
The idea here is to provide a set of utility functions and models for manipulating samples, cells, inventory, files, users and metadata associated with *datalab* entries in an automated way.
|
|
62
63
|
|
|
63
|
-
This API may not expose all the functionality available in a given *datalab* instance, and the idea would be that this package can support multiple versions of the underlying [*datalab* REST API](https://
|
|
64
|
+
This API may not expose all the functionality available in a given *datalab* instance, and the idea would be that this package can support multiple versions of the underlying [*datalab* REST API](https://docs.datalab-org.io/en/stable/rest_api/).
|
|
64
65
|
This means that the API is primarily *functional* in nature, as opposed to object-oriented, since *datalab* instances are free to use their own custom data models.
|
|
65
66
|
The available schemas are reported as instance metadata and in the future object-oriented models may be able to be genereated directly in the client (so e.g., the returned data would be Python objects like `Sample` rather than JSON data).
|
|
66
67
|
|
|
@@ -88,9 +89,9 @@ pip install .
|
|
|
88
89
|
## Usage
|
|
89
90
|
|
|
90
91
|
Example usage as a Jupyter notebook can be found in the `examples` directory or
|
|
91
|
-
in the [online documentation](https://datalab-
|
|
92
|
+
in the [online documentation](https://api-docs.datalab-org.io), as
|
|
92
93
|
well as the full [API
|
|
93
|
-
documentation](https://datalab-
|
|
94
|
+
documentation](https://api-docs.datalab-org.io/en/stable/reference/).
|
|
94
95
|
|
|
95
96
|
### Authentication
|
|
96
97
|
|
|
@@ -98,7 +99,7 @@ Currently the only supported authentication method is via an API key.
|
|
|
98
99
|
You can generate one for your account for a given *datalab* instance by visiting the `/get-api-key` endpoint of your chosen instance, or, if using a recent version of *datalab*, by visiting your account settings in the browser.
|
|
99
100
|
|
|
100
101
|
This API key can be set via the environment variable `DATALAB_API_KEY`.
|
|
101
|
-
To suport the use case of needing to interact with multiple datalab instances, the client will also check prefixed environment variables that use the [`IDENTIFIER_PREFIX` of the chosen datalab instance](https://
|
|
102
|
+
To suport the use case of needing to interact with multiple datalab instances, the client will also check prefixed environment variables that use the [`IDENTIFIER_PREFIX` of the chosen datalab instance](https://docs.datalab-org.io/en/stable/config/#mandatory-settings), e.g., `GREY_DATALAB_API_KEY` or `PUBLIC_DATALAB_API_KEY`.
|
|
102
103
|
Only keys that match will be read (e.g., other environment variables starting with `PUBLIC_` will be ignored, when connecting to the [public demo datalab](https://demo.datalab-org.io)).
|
|
103
104
|
|
|
104
105
|
### Python API
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
<a href="https://pypi.org/datalab-api"><img src="https://img.shields.io/pypi/pyversions/datalab-api?logo=python&label=Python%20versions" /></a>
|
|
11
11
|
</div>
|
|
12
12
|
|
|
13
|
-
A simple Python API that can interact with [*datalab*](https://github.com/
|
|
13
|
+
A simple Python API that can interact with [*datalab*](https://github.com/datalab-org/datalab) instances.
|
|
14
14
|
|
|
15
15
|
The idea here is to provide a set of utility functions and models for manipulating samples, cells, inventory, files, users and metadata associated with *datalab* entries in an automated way.
|
|
16
16
|
|
|
17
|
-
This API may not expose all the functionality available in a given *datalab* instance, and the idea would be that this package can support multiple versions of the underlying [*datalab* REST API](https://
|
|
17
|
+
This API may not expose all the functionality available in a given *datalab* instance, and the idea would be that this package can support multiple versions of the underlying [*datalab* REST API](https://docs.datalab-org.io/en/stable/rest_api/).
|
|
18
18
|
This means that the API is primarily *functional* in nature, as opposed to object-oriented, since *datalab* instances are free to use their own custom data models.
|
|
19
19
|
The available schemas are reported as instance metadata and in the future object-oriented models may be able to be genereated directly in the client (so e.g., the returned data would be Python objects like `Sample` rather than JSON data).
|
|
20
20
|
|
|
@@ -42,9 +42,9 @@ pip install .
|
|
|
42
42
|
## Usage
|
|
43
43
|
|
|
44
44
|
Example usage as a Jupyter notebook can be found in the `examples` directory or
|
|
45
|
-
in the [online documentation](https://datalab-
|
|
45
|
+
in the [online documentation](https://api-docs.datalab-org.io), as
|
|
46
46
|
well as the full [API
|
|
47
|
-
documentation](https://datalab-
|
|
47
|
+
documentation](https://api-docs.datalab-org.io/en/stable/reference/).
|
|
48
48
|
|
|
49
49
|
### Authentication
|
|
50
50
|
|
|
@@ -52,7 +52,7 @@ Currently the only supported authentication method is via an API key.
|
|
|
52
52
|
You can generate one for your account for a given *datalab* instance by visiting the `/get-api-key` endpoint of your chosen instance, or, if using a recent version of *datalab*, by visiting your account settings in the browser.
|
|
53
53
|
|
|
54
54
|
This API key can be set via the environment variable `DATALAB_API_KEY`.
|
|
55
|
-
To suport the use case of needing to interact with multiple datalab instances, the client will also check prefixed environment variables that use the [`IDENTIFIER_PREFIX` of the chosen datalab instance](https://
|
|
55
|
+
To suport the use case of needing to interact with multiple datalab instances, the client will also check prefixed environment variables that use the [`IDENTIFIER_PREFIX` of the chosen datalab instance](https://docs.datalab-org.io/en/stable/config/#mandatory-settings), e.g., `GREY_DATALAB_API_KEY` or `PUBLIC_DATALAB_API_KEY`.
|
|
56
56
|
Only keys that match will be read (e.g., other environment variables starting with `PUBLIC_` will be ignored, when connecting to the [public demo datalab](https://demo.datalab-org.io)).
|
|
57
57
|
|
|
58
58
|
### Python API
|
|
@@ -26,14 +26,15 @@ dependencies =[
|
|
|
26
26
|
"httpx ~= 0.27", # better HTTP requests
|
|
27
27
|
"bokeh ~= 2.4", # interactive plots from datalab directly
|
|
28
28
|
"rich ~= 13.0", # nicer terminal output
|
|
29
|
+
"numpy < 2", # upper pin for numpy due to bad pins in bokeh
|
|
29
30
|
]
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
[project.optional-dependencies]
|
|
33
34
|
dev = [
|
|
34
|
-
"pre-commit
|
|
35
|
+
"pre-commit >= 3,< 5",
|
|
35
36
|
"pytest ~= 8.0",
|
|
36
|
-
"pytest-cov
|
|
37
|
+
"pytest-cov >= 5,< 7",
|
|
37
38
|
"respx ~= 0.21",
|
|
38
39
|
]
|
|
39
40
|
|
|
@@ -68,11 +69,13 @@ repository = "https://github.com/datalab-org/datalab-api"
|
|
|
68
69
|
documentation = "https://datalab-python-api.readthedocs.io"
|
|
69
70
|
changelog = "https://github.com/datalab-org/datalab-api/releases"
|
|
70
71
|
|
|
72
|
+
[tool.uv]
|
|
73
|
+
cache-keys = [{ git = true }]
|
|
74
|
+
|
|
71
75
|
[tool.versioningit.vcs]
|
|
72
76
|
method = "git"
|
|
73
77
|
default-tag = "0.0.1"
|
|
74
78
|
|
|
75
|
-
|
|
76
79
|
[tool.mypy]
|
|
77
80
|
# plugins = "pydantic.mypy"
|
|
78
81
|
ignore_missing_imports = true
|
|
@@ -30,13 +30,17 @@ class DatalabClient(BaseDatalabClient):
|
|
|
30
30
|
def get_info(self) -> dict[str, Any]:
|
|
31
31
|
"""Fetch metadata associated with this datalab instance.
|
|
32
32
|
|
|
33
|
+
The server information is stored on the client and can be accessed
|
|
34
|
+
by the `info` attribute.
|
|
35
|
+
|
|
33
36
|
Returns:
|
|
34
37
|
dict: The JSON response from the `/info` endpoint of the Datalab API.
|
|
35
38
|
|
|
36
39
|
"""
|
|
37
40
|
info_url = f"{self.datalab_api_url}/info"
|
|
38
41
|
info_resp = self.session.get(info_url, follow_redirects=True)
|
|
39
|
-
|
|
42
|
+
self.info = info_resp.json()["data"]
|
|
43
|
+
return self.info
|
|
40
44
|
|
|
41
45
|
def authenticate(self):
|
|
42
46
|
"""Tests authentication of the client with the Datalab API."""
|
|
@@ -48,6 +52,26 @@ class DatalabClient(BaseDatalabClient):
|
|
|
48
52
|
)
|
|
49
53
|
return user_resp.json()
|
|
50
54
|
|
|
55
|
+
def get_block_info(self) -> list[dict[str, Any]]:
|
|
56
|
+
"""Return the list of available data blocks types for this instance,
|
|
57
|
+
including some details and descriptions of their usage.
|
|
58
|
+
|
|
59
|
+
The block information is stored on the client and can be accessed
|
|
60
|
+
by the `block_info` attribute.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
A list of dictionary of block types.
|
|
64
|
+
|
|
65
|
+
"""
|
|
66
|
+
block_info_url = f"{self.datalab_api_url}/info/blocks"
|
|
67
|
+
block_info_resp = self.session.get(block_info_url, follow_redirects=True)
|
|
68
|
+
if block_info_resp.status_code != 200:
|
|
69
|
+
raise RuntimeError(
|
|
70
|
+
f"Failed to list block information at {block_info_url}: {block_info_resp.status_code=}."
|
|
71
|
+
)
|
|
72
|
+
self.block_info = block_info_resp.json()["data"]
|
|
73
|
+
return self.block_info
|
|
74
|
+
|
|
51
75
|
def get_items(self, item_type: str | None = "samples") -> list[dict[str, Any]]:
|
|
52
76
|
"""List items of the given type available to the authenticated user.
|
|
53
77
|
|
|
@@ -131,7 +155,8 @@ class DatalabClient(BaseDatalabClient):
|
|
|
131
155
|
try:
|
|
132
156
|
collection_immutable_id = self.get_collection(collection_id)["immutable_id"]
|
|
133
157
|
except RuntimeError:
|
|
134
|
-
|
|
158
|
+
self.create_collection(collection_id)
|
|
159
|
+
collection_immutable_id = self.get_collection(collection_id)["immutable_id"]
|
|
135
160
|
new_item["collections"] = new_item.get("collections", [])
|
|
136
161
|
new_item["collections"].append({"immutable_id": collection_immutable_id})
|
|
137
162
|
|
|
@@ -252,8 +277,7 @@ class DatalabClient(BaseDatalabClient):
|
|
|
252
277
|
|
|
253
278
|
item_data = self.get_item(item_id)
|
|
254
279
|
for f in item_data.get("files", []):
|
|
255
|
-
|
|
256
|
-
url = file_location.replace("/app", self.datalab_api_url)
|
|
280
|
+
url = f"{self.datalab_api_url}/files/{f['immutable_id']}/{f['name']}"
|
|
257
281
|
if Path(f["name"]).exists():
|
|
258
282
|
warnings.warn(f"Will not overwrite existing file {f['name']}")
|
|
259
283
|
continue
|
|
@@ -389,6 +413,33 @@ class DatalabClient(BaseDatalabClient):
|
|
|
389
413
|
|
|
390
414
|
return block_data
|
|
391
415
|
|
|
416
|
+
def update_data_block(
|
|
417
|
+
self, item_id: str, block_id: str, block_type: str, block_data: dict
|
|
418
|
+
) -> dict[str, Any]:
|
|
419
|
+
"""Attempts to update a block with the given payload of data,
|
|
420
|
+
returning the updated block.
|
|
421
|
+
|
|
422
|
+
Parameters:
|
|
423
|
+
item_id: The ID of the item that the block is attached to.
|
|
424
|
+
block_id: The ID of existing block.
|
|
425
|
+
block_type: The type of block to update.
|
|
426
|
+
block_data: The payload of block data to update; will be used to selectively update
|
|
427
|
+
any fields present, with validation performed by the remote block code itself.
|
|
428
|
+
|
|
429
|
+
Returns:
|
|
430
|
+
If successful, the updated block data.
|
|
431
|
+
|
|
432
|
+
Raises:
|
|
433
|
+
RuntimeError: If the block update fails.
|
|
434
|
+
|
|
435
|
+
"""
|
|
436
|
+
payload = {k: v for k, v in block_data.items()}
|
|
437
|
+
payload["block_id"] = block_id
|
|
438
|
+
payload["blocktype"] = block_type
|
|
439
|
+
payload["item_id"] = item_id
|
|
440
|
+
|
|
441
|
+
return self._update_data_block(block_type=block_type, block_data=payload)
|
|
442
|
+
|
|
392
443
|
def _update_data_block(
|
|
393
444
|
self, block_type: str, block_data: dict, file_ids: str | list[str] | None = None
|
|
394
445
|
) -> dict[str, Any]:
|
|
@@ -401,7 +452,6 @@ class DatalabClient(BaseDatalabClient):
|
|
|
401
452
|
raise RuntimeError(
|
|
402
453
|
"API does not currently support attaching multiple files in a block."
|
|
403
454
|
)
|
|
404
|
-
|
|
405
455
|
block_data["file_id"] = file_ids[0]
|
|
406
456
|
|
|
407
457
|
blocks_url = f"{self.datalab_api_url}/update-block/"
|
|
@@ -43,21 +43,24 @@ def pretty_displayer(method):
|
|
|
43
43
|
if result:
|
|
44
44
|
pprint(result, max_length=None, max_string=100, max_depth=3)
|
|
45
45
|
elif isinstance(result, list):
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
46
|
+
try:
|
|
47
|
+
table = Table(show_lines=True)
|
|
48
|
+
table.add_column("type", overflow="crop", justify="center")
|
|
49
|
+
table.add_column("ID", style="cyan", no_wrap=True)
|
|
50
|
+
table.add_column("refcode", style="magenta", no_wrap=True)
|
|
51
|
+
table.add_column("name", width=30, overflow="ellipsis", no_wrap=True)
|
|
52
|
+
for item in result[:page_limit]:
|
|
53
|
+
table.add_row(
|
|
54
|
+
item["type"][0].upper(),
|
|
55
|
+
item["item_id"],
|
|
56
|
+
item["refcode"],
|
|
57
|
+
item["name"],
|
|
58
|
+
end_section=True,
|
|
59
|
+
)
|
|
60
|
+
console = Console()
|
|
61
|
+
console.print(table)
|
|
62
|
+
except Exception:
|
|
63
|
+
pprint(result, max_length=None, max_string=100, max_depth=3)
|
|
61
64
|
|
|
62
65
|
return result
|
|
63
66
|
|
|
@@ -95,6 +98,13 @@ class BaseDatalabClient(metaclass=AutoPrettyPrint):
|
|
|
95
98
|
_api_key: Optional[str] = None
|
|
96
99
|
_session: Optional[httpx.Client] = None
|
|
97
100
|
_headers: dict[str, str] = {}
|
|
101
|
+
_timeout: httpx.Timeout = httpx.Timeout(10.0, read=60.0)
|
|
102
|
+
|
|
103
|
+
info: dict[str, Any] = {}
|
|
104
|
+
"""The `data` response from the `/info` endpoint of the Datalab API."""
|
|
105
|
+
|
|
106
|
+
block_info: list[dict[str, Any]] = []
|
|
107
|
+
"""The `data` response from the `/info/blocks` endpoint of the Datalab API."""
|
|
98
108
|
|
|
99
109
|
bad_server_versions: Optional[tuple[tuple[int, int, int]]] = ((0, 2, 0),)
|
|
100
110
|
"""Any known server versions that are not supported by this client."""
|
|
@@ -133,13 +143,12 @@ class BaseDatalabClient(metaclass=AutoPrettyPrint):
|
|
|
133
143
|
|
|
134
144
|
self._detect_api_url()
|
|
135
145
|
|
|
136
|
-
|
|
146
|
+
self.get_info()
|
|
147
|
+
self.get_block_info()
|
|
137
148
|
|
|
138
|
-
self._datalab_api_versions: list[str] =
|
|
139
|
-
|
|
140
|
-
]
|
|
141
|
-
self._datalab_server_version: str = info_json["data"]["attributes"]["server_version"]
|
|
142
|
-
self._datalab_instance_prefix: Optional[str] = info_json["data"]["attributes"].get(
|
|
149
|
+
self._datalab_api_versions: list[str] = self.info["attributes"]["available_api_versions"]
|
|
150
|
+
self._datalab_server_version: str = self.info["attributes"]["server_version"]
|
|
151
|
+
self._datalab_instance_prefix: Optional[str] = self.info["attributes"].get(
|
|
143
152
|
"identifier_prefix"
|
|
144
153
|
)
|
|
145
154
|
|
|
@@ -169,16 +178,25 @@ class BaseDatalabClient(metaclass=AutoPrettyPrint):
|
|
|
169
178
|
def get_info(self) -> dict[str, Any]:
|
|
170
179
|
raise NotImplementedError
|
|
171
180
|
|
|
181
|
+
def get_block_info(self) -> list[dict[str, Any]]:
|
|
182
|
+
raise NotImplementedError
|
|
183
|
+
|
|
172
184
|
@property
|
|
173
185
|
def session(self) -> httpx.Client:
|
|
174
186
|
if self._session is None:
|
|
175
|
-
return self._http_client(headers=self.headers)
|
|
187
|
+
return self._http_client(headers=self.headers, timeout=self.timeout)
|
|
176
188
|
return self._session
|
|
177
189
|
|
|
178
190
|
@property
|
|
179
|
-
def headers(self):
|
|
191
|
+
def headers(self) -> dict[str, str]:
|
|
192
|
+
"""Any headers to send with each request to the datalab API."""
|
|
180
193
|
return self._headers
|
|
181
194
|
|
|
195
|
+
@property
|
|
196
|
+
def timeout(self) -> httpx.Timeout:
|
|
197
|
+
"""A timeout object to use for the datalab API session."""
|
|
198
|
+
return self._timeout
|
|
199
|
+
|
|
182
200
|
def _version_negotiation(self):
|
|
183
201
|
"""Check whether this client is expected to work with this instance.
|
|
184
202
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: datalab-api
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Summary: A Python API for instances of the datalab data management platform (https://github.com/the-grey-group/datalab).
|
|
5
5
|
Author-email: Matthew Evans <matthew@ml-evs.science>
|
|
6
6
|
License: MIT
|
|
@@ -24,10 +24,11 @@ License-File: LICENSE
|
|
|
24
24
|
Requires-Dist: httpx~=0.27
|
|
25
25
|
Requires-Dist: bokeh~=2.4
|
|
26
26
|
Requires-Dist: rich~=13.0
|
|
27
|
+
Requires-Dist: numpy<2
|
|
27
28
|
Provides-Extra: dev
|
|
28
|
-
Requires-Dist: pre-commit
|
|
29
|
+
Requires-Dist: pre-commit<5,>=3; extra == "dev"
|
|
29
30
|
Requires-Dist: pytest~=8.0; extra == "dev"
|
|
30
|
-
Requires-Dist: pytest-cov
|
|
31
|
+
Requires-Dist: pytest-cov<7,>=5; extra == "dev"
|
|
31
32
|
Requires-Dist: respx~=0.21; extra == "dev"
|
|
32
33
|
Provides-Extra: docs
|
|
33
34
|
Requires-Dist: mkdocs; extra == "docs"
|
|
@@ -56,11 +57,11 @@ Requires-Dist: datalab-api[cli,dev,docs]; extra == "all"
|
|
|
56
57
|
<a href="https://pypi.org/datalab-api"><img src="https://img.shields.io/pypi/pyversions/datalab-api?logo=python&label=Python%20versions" /></a>
|
|
57
58
|
</div>
|
|
58
59
|
|
|
59
|
-
A simple Python API that can interact with [*datalab*](https://github.com/
|
|
60
|
+
A simple Python API that can interact with [*datalab*](https://github.com/datalab-org/datalab) instances.
|
|
60
61
|
|
|
61
62
|
The idea here is to provide a set of utility functions and models for manipulating samples, cells, inventory, files, users and metadata associated with *datalab* entries in an automated way.
|
|
62
63
|
|
|
63
|
-
This API may not expose all the functionality available in a given *datalab* instance, and the idea would be that this package can support multiple versions of the underlying [*datalab* REST API](https://
|
|
64
|
+
This API may not expose all the functionality available in a given *datalab* instance, and the idea would be that this package can support multiple versions of the underlying [*datalab* REST API](https://docs.datalab-org.io/en/stable/rest_api/).
|
|
64
65
|
This means that the API is primarily *functional* in nature, as opposed to object-oriented, since *datalab* instances are free to use their own custom data models.
|
|
65
66
|
The available schemas are reported as instance metadata and in the future object-oriented models may be able to be genereated directly in the client (so e.g., the returned data would be Python objects like `Sample` rather than JSON data).
|
|
66
67
|
|
|
@@ -88,9 +89,9 @@ pip install .
|
|
|
88
89
|
## Usage
|
|
89
90
|
|
|
90
91
|
Example usage as a Jupyter notebook can be found in the `examples` directory or
|
|
91
|
-
in the [online documentation](https://datalab-
|
|
92
|
+
in the [online documentation](https://api-docs.datalab-org.io), as
|
|
92
93
|
well as the full [API
|
|
93
|
-
documentation](https://datalab-
|
|
94
|
+
documentation](https://api-docs.datalab-org.io/en/stable/reference/).
|
|
94
95
|
|
|
95
96
|
### Authentication
|
|
96
97
|
|
|
@@ -98,7 +99,7 @@ Currently the only supported authentication method is via an API key.
|
|
|
98
99
|
You can generate one for your account for a given *datalab* instance by visiting the `/get-api-key` endpoint of your chosen instance, or, if using a recent version of *datalab*, by visiting your account settings in the browser.
|
|
99
100
|
|
|
100
101
|
This API key can be set via the environment variable `DATALAB_API_KEY`.
|
|
101
|
-
To suport the use case of needing to interact with multiple datalab instances, the client will also check prefixed environment variables that use the [`IDENTIFIER_PREFIX` of the chosen datalab instance](https://
|
|
102
|
+
To suport the use case of needing to interact with multiple datalab instances, the client will also check prefixed environment variables that use the [`IDENTIFIER_PREFIX` of the chosen datalab instance](https://docs.datalab-org.io/en/stable/config/#mandatory-settings), e.g., `GREY_DATALAB_API_KEY` or `PUBLIC_DATALAB_API_KEY`.
|
|
102
103
|
Only keys that match will be read (e.g., other environment variables starting with `PUBLIC_` will be ignored, when connecting to the [public demo datalab](https://demo.datalab-org.io)).
|
|
103
104
|
|
|
104
105
|
### Python API
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
httpx~=0.27
|
|
2
2
|
bokeh~=2.4
|
|
3
3
|
rich~=13.0
|
|
4
|
+
numpy<2
|
|
4
5
|
|
|
5
6
|
[all]
|
|
6
7
|
datalab-api[cli,dev,docs]
|
|
@@ -14,9 +15,9 @@ typer~=0.9
|
|
|
14
15
|
click-shell~=2.1
|
|
15
16
|
|
|
16
17
|
[dev]
|
|
17
|
-
pre-commit
|
|
18
|
+
pre-commit<5,>=3
|
|
18
19
|
pytest~=8.0
|
|
19
|
-
pytest-cov
|
|
20
|
+
pytest-cov<7,>=5
|
|
20
21
|
respx~=0.21
|
|
21
22
|
|
|
22
23
|
[docs]
|
|
@@ -5,18 +5,22 @@ from httpx import Response
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
@respx.mock
|
|
8
|
-
def test_redirect_url(fake_ui_html, fake_info_json):
|
|
8
|
+
def test_redirect_url(fake_ui_html, fake_info_json, fake_block_info_json):
|
|
9
9
|
fake_ui = respx.get("https://ui.datalab.industries").mock(
|
|
10
10
|
return_value=Response(200, content=fake_ui_html)
|
|
11
11
|
)
|
|
12
|
-
|
|
12
|
+
fake_info_api = respx.get("https://api.datalab.industries/info").mock(
|
|
13
13
|
return_value=Response(200, json=fake_info_json)
|
|
14
14
|
)
|
|
15
|
+
fake_block_info_api = respx.get("https://api.datalab.industries/info/blocks").mock(
|
|
16
|
+
return_value=Response(200, json=fake_block_info_json)
|
|
17
|
+
)
|
|
15
18
|
with pytest.warns(
|
|
16
19
|
UserWarning,
|
|
17
20
|
match="^Found API URL https://api.datalab.industries in HTML meta tag. Creating client with this URL instead.$",
|
|
18
21
|
):
|
|
19
22
|
client = DatalabClient("https://ui.datalab.industries")
|
|
20
23
|
assert fake_ui.called
|
|
21
|
-
assert
|
|
24
|
+
assert fake_info_api.called
|
|
25
|
+
assert fake_block_info_api.called
|
|
22
26
|
assert client.datalab_api_url == "https://api.datalab.industries"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|