datalab-api 0.2.7__tar.gz → 0.2.9__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.
@@ -1,7 +1,7 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: datalab-api
3
- Version: 0.2.7
4
- Summary: A Python API for instances of the datalab data management platform (https://github.com/the-grey-group/datalab).
3
+ Version: 0.2.9
4
+ Summary: A Python API for instances of the datalab data management platform (https://github.com/datalab-org/datalab).
5
5
  Author-email: Matthew Evans <matthew@ml-evs.science>
6
6
  License: MIT
7
7
  Project-URL: homepage, https://github.com/datalab-org/datalab-api
@@ -10,7 +10,6 @@ Project-URL: documentation, https://datalab-python-api.readthedocs.io
10
10
  Project-URL: changelog, https://github.com/datalab-org/datalab-api/releases
11
11
  Classifier: Programming Language :: Python :: 3
12
12
  Classifier: Programming Language :: Python :: 3.9
13
- Classifier: Programming Language :: Python :: 3
14
13
  Classifier: Programming Language :: Python :: 3.10
15
14
  Classifier: Programming Language :: Python :: 3.11
16
15
  Classifier: Programming Language :: Python :: 3.12
@@ -22,12 +21,13 @@ Requires-Python: >=3.9
22
21
  Description-Content-Type: text/markdown
23
22
  License-File: LICENSE
24
23
  Requires-Dist: httpx~=0.27
25
- Requires-Dist: bokeh~=2.4
24
+ Requires-Dist: bokeh~=2.4; platform_system != "Emscripten"
26
25
  Requires-Dist: rich~=13.0
26
+ Requires-Dist: numpy<2
27
27
  Provides-Extra: dev
28
- Requires-Dist: pre-commit~=3.0; extra == "dev"
28
+ Requires-Dist: pre-commit<5,>=3; extra == "dev"
29
29
  Requires-Dist: pytest~=8.0; extra == "dev"
30
- Requires-Dist: pytest-cov~=5.0; extra == "dev"
30
+ Requires-Dist: pytest-cov<7,>=5; extra == "dev"
31
31
  Requires-Dist: respx~=0.21; extra == "dev"
32
32
  Provides-Extra: docs
33
33
  Requires-Dist: mkdocs; extra == "docs"
@@ -56,11 +56,11 @@ Requires-Dist: datalab-api[cli,dev,docs]; extra == "all"
56
56
  <a href="https://pypi.org/datalab-api"><img src="https://img.shields.io/pypi/pyversions/datalab-api?logo=python&label=Python%20versions" /></a>
57
57
  </div>
58
58
 
59
- A simple Python API that can interact with [*datalab*](https://github.com/the-grey-group/datalab) instances.
59
+ A simple Python API that can interact with [*datalab*](https://github.com/datalab-org/datalab) instances.
60
60
 
61
61
  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
62
 
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://the-datalab.readthedocs.io/en/latest/rest_api/).
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://docs.datalab-org.io/en/stable/rest_api/).
64
64
  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
65
  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
66
 
@@ -88,9 +88,9 @@ pip install .
88
88
  ## Usage
89
89
 
90
90
  Example usage as a Jupyter notebook can be found in the `examples` directory or
91
- in the [online documentation](https://datalab-api.readthedocs.io/), as
91
+ in the [online documentation](https://api-docs.datalab-org.io), as
92
92
  well as the full [API
93
- documentation](https://datalab-api.readthedocs.io/en/latest/reference/).
93
+ documentation](https://api-docs.datalab-org.io/en/stable/reference/).
94
94
 
95
95
  ### Authentication
96
96
 
@@ -98,7 +98,7 @@ Currently the only supported authentication method is via an API key.
98
98
  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
99
 
100
100
  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://the-datalab.readthedocs.io/en/latest/config/#mandatory-settings), e.g., `GREY_DATALAB_API_KEY` or `PUBLIC_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://docs.datalab-org.io/en/stable/config/#mandatory-settings), e.g., `GREY_DATALAB_API_KEY` or `PUBLIC_DATALAB_API_KEY`.
102
102
  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
103
 
104
104
  ### 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/the-grey-group/datalab) instances.
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://the-datalab.readthedocs.io/en/latest/rest_api/).
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-api.readthedocs.io/), as
45
+ in the [online documentation](https://api-docs.datalab-org.io), as
46
46
  well as the full [API
47
- documentation](https://datalab-api.readthedocs.io/en/latest/reference/).
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://the-datalab.readthedocs.io/en/latest/config/#mandatory-settings), e.g., `GREY_DATALAB_API_KEY` or `PUBLIC_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://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
@@ -5,14 +5,15 @@ build-backend = "setuptools.build_meta"
5
5
  [project]
6
6
  name = "datalab-api"
7
7
  readme = "README.md"
8
- description = "A Python API for instances of the datalab data management platform (https://github.com/the-grey-group/datalab)."
8
+ description = "A Python API for instances of the datalab data management platform (https://github.com/datalab-org/datalab)."
9
9
  keywords = []
10
10
  license = { text = "MIT" }
11
11
  authors = [{ name = "Matthew Evans", email = "matthew@ml-evs.science" }]
12
12
  dynamic = ["version"]
13
13
  classifiers = [
14
- "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.9",
15
- "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10",
14
+ "Programming Language :: Python :: 3",
15
+ "Programming Language :: Python :: 3.9",
16
+ "Programming Language :: Python :: 3.10",
16
17
  "Programming Language :: Python :: 3.11",
17
18
  "Programming Language :: Python :: 3.12",
18
19
  "Intended Audience :: Science/Research",
@@ -22,18 +23,19 @@ classifiers = [
22
23
  ]
23
24
 
24
25
  requires-python = ">=3.9"
25
- dependencies =[
26
- "httpx ~= 0.27", # better HTTP requests
27
- "bokeh ~= 2.4", # interactive plots from datalab directly
28
- "rich ~= 13.0", # nicer terminal output
26
+ dependencies = [
27
+ "httpx ~= 0.27", # better HTTP requests
28
+ 'bokeh ~= 2.4; platform_system != "Emscripten"', # interactive plots from datalab directly
29
+ "rich ~= 13.0", # nicer terminal output
30
+ "numpy < 2", # upper pin for numpy due to bad pins in bokeh
29
31
  ]
30
32
 
31
33
 
32
34
  [project.optional-dependencies]
33
35
  dev = [
34
- "pre-commit ~= 3.0",
36
+ "pre-commit >= 3,< 5",
35
37
  "pytest ~= 8.0",
36
- "pytest-cov ~= 5.0",
38
+ "pytest-cov >= 5,< 7",
37
39
  "respx ~= 0.21",
38
40
  ]
39
41
 
@@ -46,18 +48,13 @@ docs = [
46
48
  ]
47
49
 
48
50
  cli = [
49
- "typer ~= 0.9", # command line interface
51
+ "typer ~= 0.9", # command line interface
50
52
  "click-shell ~= 2.1", # REPL-like interface
51
53
  ]
52
54
 
53
- cheminventory-helper = [
54
- "pandas ~= 2.2",
55
- "openpyxl ~= 3.0"
56
- ]
55
+ cheminventory-helper = ["pandas ~= 2.2", "openpyxl ~= 3.0"]
57
56
 
58
- all = [
59
- "datalab-api[dev,docs,cli]"
60
- ]
57
+ all = ["datalab-api[dev,docs,cli]"]
61
58
 
62
59
  [project.scripts]
63
60
  datalab = "datalab_api.cli:app"
@@ -68,11 +65,13 @@ repository = "https://github.com/datalab-org/datalab-api"
68
65
  documentation = "https://datalab-python-api.readthedocs.io"
69
66
  changelog = "https://github.com/datalab-org/datalab-api/releases"
70
67
 
68
+ [tool.uv]
69
+ cache-keys = [{ git = true }]
70
+
71
71
  [tool.versioningit.vcs]
72
72
  method = "git"
73
73
  default-tag = "0.0.1"
74
74
 
75
-
76
75
  [tool.mypy]
77
76
  # plugins = "pydantic.mypy"
78
77
  ignore_missing_imports = true
@@ -127,7 +126,6 @@ ignore = [
127
126
  "PLW0603",
128
127
  "PLW2901",
129
128
  "PT003",
130
- "PT004", # pytest-missing-fixture-name-underscore
131
129
  "PT006", # pytest-parametrize-names-wrong-type
132
130
  "PT013", # pytest-incorrect-pytest-import
133
131
  "PTH", # prefer Pathlib to os.path
@@ -162,7 +160,7 @@ ignore = [
162
160
  pydocstyle.convention = "numpy"
163
161
  isort.known-first-party = ["jobflow_remote"]
164
162
  isort.split-on-trailing-comma = false
165
- fixable = ["A", "B", "C", "D", "E", "F", "I"]
163
+ fixable = ["A", "B", "C", "D", "E", "F", "I", "PT", "RUF"]
166
164
  unfixable = []
167
165
  # Allow unused variables when underscore-prefixed.
168
166
  dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
@@ -7,7 +7,7 @@ from typing import Any, Optional, Union
7
7
 
8
8
  from ._base import BaseDatalabClient, __version__
9
9
 
10
- __all__ = ("__version__", "DatalabClient")
10
+ __all__ = ("DatalabClient", "__version__")
11
11
 
12
12
 
13
13
  class DuplicateItemError(ValueError):
@@ -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
- return info_resp.json()
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
 
@@ -253,8 +277,7 @@ class DatalabClient(BaseDatalabClient):
253
277
 
254
278
  item_data = self.get_item(item_id)
255
279
  for f in item_data.get("files", []):
256
- file_location = f["location"]
257
- url = file_location.replace("/app", self.datalab_api_url)
280
+ url = f"{self.datalab_api_url}/files/{f['immutable_id']}/{f['name']}"
258
281
  if Path(f["name"]).exists():
259
282
  warnings.warn(f"Will not overwrite existing file {f['name']}")
260
283
  continue
@@ -14,7 +14,7 @@ from rich.table import Table
14
14
 
15
15
  __version__ = version("datalab-api")
16
16
 
17
- __all__ = ("__version__", "BaseDatalabClient")
17
+ __all__ = ("BaseDatalabClient", "__version__")
18
18
 
19
19
 
20
20
  def pretty_displayer(method):
@@ -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
- table = Table(show_lines=True)
47
- table.add_column("type", overflow="crop", justify="center")
48
- table.add_column("ID", style="cyan", no_wrap=True)
49
- table.add_column("refcode", style="magenta", no_wrap=True)
50
- table.add_column("name", width=30, overflow="ellipsis", no_wrap=True)
51
- for item in result[:page_limit]:
52
- table.add_row(
53
- item["type"][0].upper(),
54
- item["item_id"],
55
- item["refcode"],
56
- item["name"],
57
- end_section=True,
58
- )
59
- console = Console()
60
- console.print(table)
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
 
@@ -97,6 +100,12 @@ class BaseDatalabClient(metaclass=AutoPrettyPrint):
97
100
  _headers: dict[str, str] = {}
98
101
  _timeout: httpx.Timeout = httpx.Timeout(10.0, read=60.0)
99
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."""
108
+
100
109
  bad_server_versions: Optional[tuple[tuple[int, int, int]]] = ((0, 2, 0),)
101
110
  """Any known server versions that are not supported by this client."""
102
111
 
@@ -134,13 +143,12 @@ class BaseDatalabClient(metaclass=AutoPrettyPrint):
134
143
 
135
144
  self._detect_api_url()
136
145
 
137
- info_json = self.get_info()
146
+ self.get_info()
147
+ self.get_block_info()
138
148
 
139
- self._datalab_api_versions: list[str] = info_json["data"]["attributes"][
140
- "available_api_versions"
141
- ]
142
- self._datalab_server_version: str = info_json["data"]["attributes"]["server_version"]
143
- 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(
144
152
  "identifier_prefix"
145
153
  )
146
154
 
@@ -170,6 +178,9 @@ class BaseDatalabClient(metaclass=AutoPrettyPrint):
170
178
  def get_info(self) -> dict[str, Any]:
171
179
  raise NotImplementedError
172
180
 
181
+ def get_block_info(self) -> list[dict[str, Any]]:
182
+ raise NotImplementedError
183
+
173
184
  @property
174
185
  def session(self) -> httpx.Client:
175
186
  if self._session is None:
@@ -1,7 +1,7 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: datalab-api
3
- Version: 0.2.7
4
- Summary: A Python API for instances of the datalab data management platform (https://github.com/the-grey-group/datalab).
3
+ Version: 0.2.9
4
+ Summary: A Python API for instances of the datalab data management platform (https://github.com/datalab-org/datalab).
5
5
  Author-email: Matthew Evans <matthew@ml-evs.science>
6
6
  License: MIT
7
7
  Project-URL: homepage, https://github.com/datalab-org/datalab-api
@@ -10,7 +10,6 @@ Project-URL: documentation, https://datalab-python-api.readthedocs.io
10
10
  Project-URL: changelog, https://github.com/datalab-org/datalab-api/releases
11
11
  Classifier: Programming Language :: Python :: 3
12
12
  Classifier: Programming Language :: Python :: 3.9
13
- Classifier: Programming Language :: Python :: 3
14
13
  Classifier: Programming Language :: Python :: 3.10
15
14
  Classifier: Programming Language :: Python :: 3.11
16
15
  Classifier: Programming Language :: Python :: 3.12
@@ -22,12 +21,13 @@ Requires-Python: >=3.9
22
21
  Description-Content-Type: text/markdown
23
22
  License-File: LICENSE
24
23
  Requires-Dist: httpx~=0.27
25
- Requires-Dist: bokeh~=2.4
24
+ Requires-Dist: bokeh~=2.4; platform_system != "Emscripten"
26
25
  Requires-Dist: rich~=13.0
26
+ Requires-Dist: numpy<2
27
27
  Provides-Extra: dev
28
- Requires-Dist: pre-commit~=3.0; extra == "dev"
28
+ Requires-Dist: pre-commit<5,>=3; extra == "dev"
29
29
  Requires-Dist: pytest~=8.0; extra == "dev"
30
- Requires-Dist: pytest-cov~=5.0; extra == "dev"
30
+ Requires-Dist: pytest-cov<7,>=5; extra == "dev"
31
31
  Requires-Dist: respx~=0.21; extra == "dev"
32
32
  Provides-Extra: docs
33
33
  Requires-Dist: mkdocs; extra == "docs"
@@ -56,11 +56,11 @@ Requires-Dist: datalab-api[cli,dev,docs]; extra == "all"
56
56
  <a href="https://pypi.org/datalab-api"><img src="https://img.shields.io/pypi/pyversions/datalab-api?logo=python&label=Python%20versions" /></a>
57
57
  </div>
58
58
 
59
- A simple Python API that can interact with [*datalab*](https://github.com/the-grey-group/datalab) instances.
59
+ A simple Python API that can interact with [*datalab*](https://github.com/datalab-org/datalab) instances.
60
60
 
61
61
  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
62
 
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://the-datalab.readthedocs.io/en/latest/rest_api/).
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://docs.datalab-org.io/en/stable/rest_api/).
64
64
  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
65
  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
66
 
@@ -88,9 +88,9 @@ pip install .
88
88
  ## Usage
89
89
 
90
90
  Example usage as a Jupyter notebook can be found in the `examples` directory or
91
- in the [online documentation](https://datalab-api.readthedocs.io/), as
91
+ in the [online documentation](https://api-docs.datalab-org.io), as
92
92
  well as the full [API
93
- documentation](https://datalab-api.readthedocs.io/en/latest/reference/).
93
+ documentation](https://api-docs.datalab-org.io/en/stable/reference/).
94
94
 
95
95
  ### Authentication
96
96
 
@@ -98,7 +98,7 @@ Currently the only supported authentication method is via an API key.
98
98
  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
99
 
100
100
  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://the-datalab.readthedocs.io/en/latest/config/#mandatory-settings), e.g., `GREY_DATALAB_API_KEY` or `PUBLIC_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://docs.datalab-org.io/en/stable/config/#mandatory-settings), e.g., `GREY_DATALAB_API_KEY` or `PUBLIC_DATALAB_API_KEY`.
102
102
  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
103
 
104
104
  ### Python API
@@ -1,6 +1,9 @@
1
1
  httpx~=0.27
2
- bokeh~=2.4
3
2
  rich~=13.0
3
+ numpy<2
4
+
5
+ [:platform_system != "Emscripten"]
6
+ bokeh~=2.4
4
7
 
5
8
  [all]
6
9
  datalab-api[cli,dev,docs]
@@ -14,9 +17,9 @@ typer~=0.9
14
17
  click-shell~=2.1
15
18
 
16
19
  [dev]
17
- pre-commit~=3.0
20
+ pre-commit<5,>=3
18
21
  pytest~=8.0
19
- pytest-cov~=5.0
22
+ pytest-cov<7,>=5
20
23
  respx~=0.21
21
24
 
22
25
  [docs]
@@ -0,0 +1,51 @@
1
+ import pytest
2
+ import respx
3
+ from httpx import Response
4
+
5
+ from datalab_api import DatalabClient
6
+
7
+
8
+ @respx.mock
9
+ def test_redirect_url(fake_ui_html, fake_info_json, fake_block_info_json):
10
+ fake_ui = respx.get("https://ui.datalab.industries").mock(
11
+ return_value=Response(200, content=fake_ui_html)
12
+ )
13
+ fake_info_api = respx.get("https://api.datalab.industries/info").mock(
14
+ return_value=Response(200, json=fake_info_json)
15
+ )
16
+ fake_block_info_api = respx.get("https://api.datalab.industries/info/blocks").mock(
17
+ return_value=Response(200, json=fake_block_info_json)
18
+ )
19
+ with pytest.warns(
20
+ UserWarning,
21
+ match="^Found API URL https://api.datalab.industries in HTML meta tag. Creating client with this URL instead.$",
22
+ ):
23
+ client = DatalabClient("https://ui.datalab.industries")
24
+ assert fake_ui.called
25
+ assert fake_info_api.called
26
+ assert fake_block_info_api.called
27
+ assert client.datalab_api_url == "https://api.datalab.industries"
28
+
29
+
30
+ @respx.mock
31
+ def test_sample_list(fake_samples_json, fake_info_json, fake_block_info_json):
32
+ fake_api = respx.get("https://api.datalab.industries/").mock(
33
+ return_value=Response(200, content="<!doctype html></html>")
34
+ )
35
+ fake_samples_api = respx.get("https://api.datalab.industries/samples").mock(
36
+ return_value=Response(200, json=fake_samples_json)
37
+ )
38
+ fake_info_api = respx.get("https://api.datalab.industries/info").mock(
39
+ return_value=Response(200, json=fake_info_json)
40
+ )
41
+ fake_block_info_api = respx.get("https://api.datalab.industries/info/blocks").mock(
42
+ return_value=Response(200, json=fake_block_info_json)
43
+ )
44
+ with DatalabClient("https://api.datalab.industries") as client:
45
+ samples = client.get_items(display=True)
46
+ assert fake_samples_api.called
47
+ assert fake_api.called
48
+ assert fake_info_api.called
49
+ assert fake_block_info_api.called
50
+ assert len(samples)
51
+ assert samples[0]["item_id"] == "test"
@@ -1,22 +0,0 @@
1
- import pytest
2
- import respx
3
- from datalab_api import DatalabClient
4
- from httpx import Response
5
-
6
-
7
- @respx.mock
8
- def test_redirect_url(fake_ui_html, fake_info_json):
9
- fake_ui = respx.get("https://ui.datalab.industries").mock(
10
- return_value=Response(200, content=fake_ui_html)
11
- )
12
- fake_api = respx.get("https://api.datalab.industries/info").mock(
13
- return_value=Response(200, json=fake_info_json)
14
- )
15
- with pytest.warns(
16
- UserWarning,
17
- match="^Found API URL https://api.datalab.industries in HTML meta tag. Creating client with this URL instead.$",
18
- ):
19
- client = DatalabClient("https://ui.datalab.industries")
20
- assert fake_ui.called
21
- assert fake_api.called
22
- assert client.datalab_api_url == "https://api.datalab.industries"
File without changes
File without changes