datalab-api 0.2.0__tar.gz → 0.2.3__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.0/src/datalab_api.egg-info → datalab_api-0.2.3}/PKG-INFO +19 -5
- {datalab_api-0.2.0 → datalab_api-0.2.3}/README.md +8 -4
- {datalab_api-0.2.0 → datalab_api-0.2.3}/pyproject.toml +12 -4
- {datalab_api-0.2.0 → datalab_api-0.2.3}/src/datalab_api/__init__.py +21 -0
- {datalab_api-0.2.0 → datalab_api-0.2.3}/src/datalab_api/_base.py +72 -9
- {datalab_api-0.2.0 → datalab_api-0.2.3/src/datalab_api.egg-info}/PKG-INFO +19 -5
- {datalab_api-0.2.0 → datalab_api-0.2.3}/src/datalab_api.egg-info/SOURCES.txt +2 -1
- {datalab_api-0.2.0 → datalab_api-0.2.3}/src/datalab_api.egg-info/requires.txt +6 -0
- datalab_api-0.2.3/tests/test_client.py +22 -0
- {datalab_api-0.2.0 → datalab_api-0.2.3}/LICENSE +0 -0
- {datalab_api-0.2.0 → datalab_api-0.2.3}/setup.cfg +0 -0
- {datalab_api-0.2.0 → datalab_api-0.2.3}/src/datalab_api/cli.py +0 -0
- {datalab_api-0.2.0 → datalab_api-0.2.3}/src/datalab_api.egg-info/dependency_links.txt +0 -0
- {datalab_api-0.2.0 → datalab_api-0.2.3}/src/datalab_api.egg-info/entry_points.txt +0 -0
- {datalab_api-0.2.0 → datalab_api-0.2.3}/src/datalab_api.egg-info/top_level.txt +0 -0
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: datalab-api
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
|
+
Summary: A Python API for instances of the datalab data management platform (https://github.com/the-grey-group/datalab).
|
|
4
5
|
Author-email: Matthew Evans <matthew@ml-evs.science>
|
|
5
6
|
License: MIT
|
|
7
|
+
Project-URL: homepage, https://github.com/datalab-org/datalab-api
|
|
8
|
+
Project-URL: repository, https://github.com/datalab-org/datalab-api
|
|
9
|
+
Project-URL: documentation, https://datalab-python-api.readthedocs.io
|
|
10
|
+
Project-URL: changelog, https://github.com/datalab-org/datalab-api/releases
|
|
6
11
|
Classifier: Programming Language :: Python :: 3
|
|
7
12
|
Classifier: Programming Language :: Python :: 3.9
|
|
8
13
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -21,6 +26,9 @@ Requires-Dist: bokeh~=2.4
|
|
|
21
26
|
Requires-Dist: rich~=13.0
|
|
22
27
|
Provides-Extra: dev
|
|
23
28
|
Requires-Dist: pre-commit~=3.0; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest~=8.0; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-cov~=5.0; extra == "dev"
|
|
31
|
+
Requires-Dist: respx~=0.21; extra == "dev"
|
|
24
32
|
Provides-Extra: docs
|
|
25
33
|
Requires-Dist: mkdocs; extra == "docs"
|
|
26
34
|
Requires-Dist: mkdocs-material; extra == "docs"
|
|
@@ -30,13 +38,19 @@ Requires-Dist: mkdocs-jupyter; extra == "docs"
|
|
|
30
38
|
Provides-Extra: cli
|
|
31
39
|
Requires-Dist: typer~=0.9; extra == "cli"
|
|
32
40
|
Requires-Dist: click-shell~=2.1; extra == "cli"
|
|
41
|
+
Provides-Extra: all
|
|
42
|
+
Requires-Dist: datalab-api[cli,dev,docs]; extra == "all"
|
|
33
43
|
|
|
34
44
|
# <div align="center"><i>datalab</i> Python API</div>
|
|
35
45
|
|
|
36
46
|
<div align="center">
|
|
37
|
-
<a href="https://datalab-
|
|
38
|
-
<img src="https://
|
|
39
|
-
</
|
|
47
|
+
<a href="https://pypi.org/datalab-api"><img src="https://img.shields.io/pypi/v/datalab-api?logo=pypi&label=PyPI" /></a>
|
|
48
|
+
<a href="https://github.com/datalab-org/datalab-api?tab=MIT-1-ov-file#MIT-1-ov-file"><img src="https://img.shields.io/github/license/datalab-org/datalab-api" /></a>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<div align="center">
|
|
52
|
+
<a href="https://datalab-python-api.readthedocs.io/en/stable/?badge=stable"><img src="https://img.shields.io/readthedocs/datalab-python-api?logo=readthedocs" /></a>
|
|
53
|
+
<a href="https://pypi.org/datalab-api"><img src="https://img.shields.io/pypi/pyversions/datalab-api?logo=python&label=Python%20versions" /></a>
|
|
40
54
|
</div>
|
|
41
55
|
|
|
42
56
|
A simple Python API that can interact with [*datalab*](https://github.com/the-grey-group/datalab) instances.
|
|
@@ -91,7 +105,7 @@ This package implements basic functionality for displaying and manipulating entr
|
|
|
91
105
|
```python
|
|
92
106
|
from datalab_api import DatalabClient
|
|
93
107
|
|
|
94
|
-
with DatalabClient("https://api.
|
|
108
|
+
with DatalabClient("https://public.api.odbx.science") as client:
|
|
95
109
|
|
|
96
110
|
# List all items of a given type
|
|
97
111
|
items = client.get_items()
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
# <div align="center"><i>datalab</i> Python API</div>
|
|
2
2
|
|
|
3
3
|
<div align="center">
|
|
4
|
-
<a href="https://datalab-
|
|
5
|
-
<img src="https://
|
|
6
|
-
</
|
|
4
|
+
<a href="https://pypi.org/datalab-api"><img src="https://img.shields.io/pypi/v/datalab-api?logo=pypi&label=PyPI" /></a>
|
|
5
|
+
<a href="https://github.com/datalab-org/datalab-api?tab=MIT-1-ov-file#MIT-1-ov-file"><img src="https://img.shields.io/github/license/datalab-org/datalab-api" /></a>
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
<div align="center">
|
|
9
|
+
<a href="https://datalab-python-api.readthedocs.io/en/stable/?badge=stable"><img src="https://img.shields.io/readthedocs/datalab-python-api?logo=readthedocs" /></a>
|
|
10
|
+
<a href="https://pypi.org/datalab-api"><img src="https://img.shields.io/pypi/pyversions/datalab-api?logo=python&label=Python%20versions" /></a>
|
|
7
11
|
</div>
|
|
8
12
|
|
|
9
13
|
A simple Python API that can interact with [*datalab*](https://github.com/the-grey-group/datalab) instances.
|
|
@@ -58,7 +62,7 @@ This package implements basic functionality for displaying and manipulating entr
|
|
|
58
62
|
```python
|
|
59
63
|
from datalab_api import DatalabClient
|
|
60
64
|
|
|
61
|
-
with DatalabClient("https://api.
|
|
65
|
+
with DatalabClient("https://public.api.odbx.science") as client:
|
|
62
66
|
|
|
63
67
|
# List all items of a given type
|
|
64
68
|
items = client.get_items()
|
|
@@ -5,6 +5,7 @@ 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
9
|
keywords = []
|
|
9
10
|
license = { text = "MIT" }
|
|
10
11
|
authors = [{ name = "Matthew Evans", email = "matthew@ml-evs.science" }]
|
|
@@ -31,6 +32,9 @@ dependencies =[
|
|
|
31
32
|
[project.optional-dependencies]
|
|
32
33
|
dev = [
|
|
33
34
|
"pre-commit ~= 3.0",
|
|
35
|
+
"pytest ~= 8.0",
|
|
36
|
+
"pytest-cov ~= 5.0",
|
|
37
|
+
"respx ~= 0.21",
|
|
34
38
|
]
|
|
35
39
|
|
|
36
40
|
docs = [
|
|
@@ -46,14 +50,18 @@ cli = [
|
|
|
46
50
|
"click-shell ~= 2.1", # REPL-like interface
|
|
47
51
|
]
|
|
48
52
|
|
|
53
|
+
all = [
|
|
54
|
+
"datalab-api[dev,docs,cli]"
|
|
55
|
+
]
|
|
56
|
+
|
|
49
57
|
[project.scripts]
|
|
50
58
|
datalab = "datalab_api.cli:app"
|
|
51
59
|
|
|
52
60
|
[project.urls]
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
homepage = "https://github.com/datalab-org/datalab-api"
|
|
62
|
+
repository = "https://github.com/datalab-org/datalab-api"
|
|
63
|
+
documentation = "https://datalab-python-api.readthedocs.io"
|
|
64
|
+
changelog = "https://github.com/datalab-org/datalab-api/releases"
|
|
57
65
|
|
|
58
66
|
[tool.versioningit.vcs]
|
|
59
67
|
method = "git"
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import warnings
|
|
1
2
|
from pathlib import Path
|
|
2
3
|
from typing import Any, Optional, Union
|
|
3
4
|
|
|
@@ -214,6 +215,26 @@ class DatalabClient(BaseDatalabClient):
|
|
|
214
215
|
|
|
215
216
|
return item["item_data"]
|
|
216
217
|
|
|
218
|
+
def get_item_files(self, item_id: str) -> None:
|
|
219
|
+
"""Download all the files for a given item and save them locally
|
|
220
|
+
in the current working directory.
|
|
221
|
+
|
|
222
|
+
Parameters:
|
|
223
|
+
item_id: The ID of the item to search for.
|
|
224
|
+
|
|
225
|
+
"""
|
|
226
|
+
|
|
227
|
+
item_data = self.get_item(item_id)
|
|
228
|
+
for f in item_data.get("files", []):
|
|
229
|
+
file_location = f["location"]
|
|
230
|
+
url = file_location.replace("/app", self.datalab_api_url)
|
|
231
|
+
if Path(f["name"]).exists():
|
|
232
|
+
warnings.warn(f"Will not overwrite existing file {f['name']}")
|
|
233
|
+
continue
|
|
234
|
+
with open(f["name"], "wb") as file:
|
|
235
|
+
response = self.session.get(url, follow_redirects=True)
|
|
236
|
+
file.write(response.content)
|
|
237
|
+
|
|
217
238
|
def get_block(self, item_id: str, block_id: str, block_data: dict[str, Any]) -> dict[str, Any]:
|
|
218
239
|
"""Get a block with a given ID and block data.
|
|
219
240
|
Should be used in conjunction with `get_item` to load an existing block.
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import functools
|
|
2
2
|
import logging
|
|
3
3
|
import os
|
|
4
|
+
import re
|
|
5
|
+
import warnings
|
|
4
6
|
from importlib.metadata import version
|
|
5
7
|
from typing import Any, Optional
|
|
6
8
|
|
|
7
9
|
import httpx
|
|
10
|
+
from rich.console import Console
|
|
8
11
|
from rich.logging import RichHandler
|
|
9
12
|
from rich.pretty import pprint
|
|
13
|
+
from rich.table import Table
|
|
10
14
|
|
|
11
15
|
__version__ = version("datalab-api")
|
|
12
16
|
|
|
@@ -14,17 +18,46 @@ __all__ = ("__version__", "BaseDatalabClient")
|
|
|
14
18
|
|
|
15
19
|
|
|
16
20
|
def pretty_displayer(method):
|
|
21
|
+
"""A decorator which wraps a method with a 'display' kwarg, which will
|
|
22
|
+
either pretty print a JSON response, or display a Rich table.
|
|
23
|
+
|
|
24
|
+
"""
|
|
25
|
+
|
|
17
26
|
@functools.wraps(method)
|
|
18
27
|
def rich_wrapper(self, *args, **kwargs):
|
|
19
28
|
display = kwargs.pop("display", False)
|
|
29
|
+
page_limit = kwargs.pop("page_limit", 10)
|
|
20
30
|
result = method(self, *args, **kwargs)
|
|
21
31
|
if display:
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
blocks = None
|
|
33
|
+
if isinstance(result, dict):
|
|
34
|
+
if "blocks_obj" in result:
|
|
35
|
+
blocks = result["blocks_obj"]
|
|
36
|
+
elif "blocktype" in result:
|
|
37
|
+
blocks = {result["block_id"]: result}
|
|
38
|
+
result = None
|
|
39
|
+
if blocks:
|
|
40
|
+
for block in blocks.values():
|
|
41
|
+
if "bokeh_plot_data" in block:
|
|
42
|
+
bokeh_from_json(block)
|
|
43
|
+
if result:
|
|
44
|
+
pprint(result, max_length=None, max_string=100, max_depth=3)
|
|
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)
|
|
28
61
|
|
|
29
62
|
return result
|
|
30
63
|
|
|
@@ -39,16 +72,19 @@ class AutoPrettyPrint(type):
|
|
|
39
72
|
return super().__new__(cls, name, bases, dct)
|
|
40
73
|
|
|
41
74
|
|
|
42
|
-
def bokeh_from_json(block_data):
|
|
75
|
+
def bokeh_from_json(block_data, show=True):
|
|
43
76
|
from bokeh.io import curdoc
|
|
44
|
-
from bokeh.plotting import show
|
|
77
|
+
from bokeh.plotting import show as bokeh_show
|
|
45
78
|
|
|
46
79
|
if "bokeh_plot_data" in block_data:
|
|
47
80
|
bokeh_plot_data = block_data["bokeh_plot_data"]
|
|
48
81
|
else:
|
|
49
82
|
bokeh_plot_data = block_data
|
|
50
83
|
curdoc().replace_with_json(bokeh_plot_data["doc"])
|
|
51
|
-
show
|
|
84
|
+
if show:
|
|
85
|
+
bokeh_show(curdoc().roots[0])
|
|
86
|
+
|
|
87
|
+
return curdoc()
|
|
52
88
|
|
|
53
89
|
|
|
54
90
|
class BaseDatalabClient(metaclass=AutoPrettyPrint):
|
|
@@ -98,6 +134,8 @@ class BaseDatalabClient(metaclass=AutoPrettyPrint):
|
|
|
98
134
|
self._http_client = httpx.Client
|
|
99
135
|
self._headers["User-Agent"] = f"Datalab Python API/{__version__}"
|
|
100
136
|
|
|
137
|
+
self._detect_api_url()
|
|
138
|
+
|
|
101
139
|
info_json = self.get_info()
|
|
102
140
|
|
|
103
141
|
self._datalab_api_versions: list[str] = info_json["data"]["attributes"][
|
|
@@ -110,6 +148,27 @@ class BaseDatalabClient(metaclass=AutoPrettyPrint):
|
|
|
110
148
|
|
|
111
149
|
self._find_api_key()
|
|
112
150
|
|
|
151
|
+
def _detect_api_url(self) -> None:
|
|
152
|
+
"""Perform a handshake with the chosen URL to ascertain the correct API URL.
|
|
153
|
+
|
|
154
|
+
If a datalab UI URL is passed, the client will attempt to resolve the API URL by
|
|
155
|
+
inspecting the HTML meta tags.
|
|
156
|
+
|
|
157
|
+
Do not use the session for this, so we are not passing the API key to arbitrary URLs.
|
|
158
|
+
|
|
159
|
+
"""
|
|
160
|
+
response = httpx.get(self.datalab_api_url)
|
|
161
|
+
match = re.search(
|
|
162
|
+
r'<meta name="x_datalab_api_url" content="(.*?)">',
|
|
163
|
+
response.text,
|
|
164
|
+
re.IGNORECASE,
|
|
165
|
+
)
|
|
166
|
+
if match:
|
|
167
|
+
self.datalab_api_url = match.group(1)
|
|
168
|
+
warnings.warn(
|
|
169
|
+
f"Found API URL {self.datalab_api_url} in HTML meta tag. Creating client with this URL instead."
|
|
170
|
+
)
|
|
171
|
+
|
|
113
172
|
def get_info(self) -> dict[str, Any]:
|
|
114
173
|
raise NotImplementedError
|
|
115
174
|
|
|
@@ -173,6 +232,10 @@ class BaseDatalabClient(metaclass=AutoPrettyPrint):
|
|
|
173
232
|
if api_key is None:
|
|
174
233
|
api_key = os.getenv("DATALAB_API_KEY")
|
|
175
234
|
|
|
235
|
+
# Remove single and double quotes around API key if present
|
|
236
|
+
if api_key is not None:
|
|
237
|
+
api_key = api_key.strip("'").strip('"')
|
|
238
|
+
|
|
176
239
|
if api_key is None:
|
|
177
240
|
raise ValueError(
|
|
178
241
|
f"No API key found in environment variables {key_env_var}/<prefix>_{key_env_var}."
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: datalab-api
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
|
+
Summary: A Python API for instances of the datalab data management platform (https://github.com/the-grey-group/datalab).
|
|
4
5
|
Author-email: Matthew Evans <matthew@ml-evs.science>
|
|
5
6
|
License: MIT
|
|
7
|
+
Project-URL: homepage, https://github.com/datalab-org/datalab-api
|
|
8
|
+
Project-URL: repository, https://github.com/datalab-org/datalab-api
|
|
9
|
+
Project-URL: documentation, https://datalab-python-api.readthedocs.io
|
|
10
|
+
Project-URL: changelog, https://github.com/datalab-org/datalab-api/releases
|
|
6
11
|
Classifier: Programming Language :: Python :: 3
|
|
7
12
|
Classifier: Programming Language :: Python :: 3.9
|
|
8
13
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -21,6 +26,9 @@ Requires-Dist: bokeh~=2.4
|
|
|
21
26
|
Requires-Dist: rich~=13.0
|
|
22
27
|
Provides-Extra: dev
|
|
23
28
|
Requires-Dist: pre-commit~=3.0; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest~=8.0; extra == "dev"
|
|
30
|
+
Requires-Dist: pytest-cov~=5.0; extra == "dev"
|
|
31
|
+
Requires-Dist: respx~=0.21; extra == "dev"
|
|
24
32
|
Provides-Extra: docs
|
|
25
33
|
Requires-Dist: mkdocs; extra == "docs"
|
|
26
34
|
Requires-Dist: mkdocs-material; extra == "docs"
|
|
@@ -30,13 +38,19 @@ Requires-Dist: mkdocs-jupyter; extra == "docs"
|
|
|
30
38
|
Provides-Extra: cli
|
|
31
39
|
Requires-Dist: typer~=0.9; extra == "cli"
|
|
32
40
|
Requires-Dist: click-shell~=2.1; extra == "cli"
|
|
41
|
+
Provides-Extra: all
|
|
42
|
+
Requires-Dist: datalab-api[cli,dev,docs]; extra == "all"
|
|
33
43
|
|
|
34
44
|
# <div align="center"><i>datalab</i> Python API</div>
|
|
35
45
|
|
|
36
46
|
<div align="center">
|
|
37
|
-
<a href="https://datalab-
|
|
38
|
-
<img src="https://
|
|
39
|
-
</
|
|
47
|
+
<a href="https://pypi.org/datalab-api"><img src="https://img.shields.io/pypi/v/datalab-api?logo=pypi&label=PyPI" /></a>
|
|
48
|
+
<a href="https://github.com/datalab-org/datalab-api?tab=MIT-1-ov-file#MIT-1-ov-file"><img src="https://img.shields.io/github/license/datalab-org/datalab-api" /></a>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<div align="center">
|
|
52
|
+
<a href="https://datalab-python-api.readthedocs.io/en/stable/?badge=stable"><img src="https://img.shields.io/readthedocs/datalab-python-api?logo=readthedocs" /></a>
|
|
53
|
+
<a href="https://pypi.org/datalab-api"><img src="https://img.shields.io/pypi/pyversions/datalab-api?logo=python&label=Python%20versions" /></a>
|
|
40
54
|
</div>
|
|
41
55
|
|
|
42
56
|
A simple Python API that can interact with [*datalab*](https://github.com/the-grey-group/datalab) instances.
|
|
@@ -91,7 +105,7 @@ This package implements basic functionality for displaying and manipulating entr
|
|
|
91
105
|
```python
|
|
92
106
|
from datalab_api import DatalabClient
|
|
93
107
|
|
|
94
|
-
with DatalabClient("https://api.
|
|
108
|
+
with DatalabClient("https://public.api.odbx.science") as client:
|
|
95
109
|
|
|
96
110
|
# List all items of a given type
|
|
97
111
|
items = client.get_items()
|
|
@@ -9,4 +9,5 @@ src/datalab_api.egg-info/SOURCES.txt
|
|
|
9
9
|
src/datalab_api.egg-info/dependency_links.txt
|
|
10
10
|
src/datalab_api.egg-info/entry_points.txt
|
|
11
11
|
src/datalab_api.egg-info/requires.txt
|
|
12
|
-
src/datalab_api.egg-info/top_level.txt
|
|
12
|
+
src/datalab_api.egg-info/top_level.txt
|
|
13
|
+
tests/test_client.py
|
|
@@ -0,0 +1,22 @@
|
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|