datalab-api 0.5.1__tar.gz → 0.5.2__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.5.1/src/datalab_api.egg-info → datalab_api-0.5.2}/PKG-INFO +1 -1
- {datalab_api-0.5.1 → datalab_api-0.5.2}/src/datalab_api/__init__.py +21 -3
- {datalab_api-0.5.1 → datalab_api-0.5.2}/src/datalab_api/_base.py +6 -0
- {datalab_api-0.5.1 → datalab_api-0.5.2/src/datalab_api.egg-info}/PKG-INFO +1 -1
- {datalab_api-0.5.1 → datalab_api-0.5.2}/tests/test_client.py +52 -0
- {datalab_api-0.5.1 → datalab_api-0.5.2}/LICENSE +0 -0
- {datalab_api-0.5.1 → datalab_api-0.5.2}/README.md +0 -0
- {datalab_api-0.5.1 → datalab_api-0.5.2}/pyproject.toml +0 -0
- {datalab_api-0.5.1 → datalab_api-0.5.2}/setup.cfg +0 -0
- {datalab_api-0.5.1 → datalab_api-0.5.2}/src/datalab_api/cli.py +0 -0
- {datalab_api-0.5.1 → datalab_api-0.5.2}/src/datalab_api/utils.py +0 -0
- {datalab_api-0.5.1 → datalab_api-0.5.2}/src/datalab_api.egg-info/SOURCES.txt +0 -0
- {datalab_api-0.5.1 → datalab_api-0.5.2}/src/datalab_api.egg-info/dependency_links.txt +0 -0
- {datalab_api-0.5.1 → datalab_api-0.5.2}/src/datalab_api.egg-info/entry_points.txt +0 -0
- {datalab_api-0.5.1 → datalab_api-0.5.2}/src/datalab_api.egg-info/requires.txt +0 -0
- {datalab_api-0.5.1 → datalab_api-0.5.2}/src/datalab_api.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: datalab-api
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.2
|
|
4
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-Expression: MIT
|
|
@@ -322,7 +322,12 @@ class DatalabClient(BaseDatalabClient):
|
|
|
322
322
|
If provided, the new file will take the place of the old file in any blocks it was attached to.
|
|
323
323
|
|
|
324
324
|
Returns:
|
|
325
|
-
A dictionary of the uploaded file data
|
|
325
|
+
A dictionary of the uploaded file data, with an additional
|
|
326
|
+
`not_modified` key. If `replace_file_id` was provided and the
|
|
327
|
+
server already holds identical content (compared by hash), the
|
|
328
|
+
update is a no-op: the server replies `304 Not Modified` and
|
|
329
|
+
`not_modified` is `True`. Servers older than datalab#1744 never
|
|
330
|
+
report this, so `not_modified` is always `False` against them.
|
|
326
331
|
|
|
327
332
|
"""
|
|
328
333
|
if isinstance(file_path, str):
|
|
@@ -341,10 +346,23 @@ class DatalabClient(BaseDatalabClient):
|
|
|
341
346
|
upload_url,
|
|
342
347
|
files=files,
|
|
343
348
|
data={"item_id": item_id, "replace_file": replace_file_id},
|
|
344
|
-
expected_status=201,
|
|
349
|
+
expected_status=[201, 304],
|
|
345
350
|
timeout=upload_timeout,
|
|
346
351
|
)
|
|
347
|
-
|
|
352
|
+
|
|
353
|
+
# A 201 always carries a body describing the stored file, so an
|
|
354
|
+
# empty dict here can only be the 304: the server compared hashes,
|
|
355
|
+
# found it already holds this content, and made no update. That is
|
|
356
|
+
# a success, so report it rather than raising.
|
|
357
|
+
if not upload:
|
|
358
|
+
return {
|
|
359
|
+
"status": "success",
|
|
360
|
+
"file_id": replace_file_id,
|
|
361
|
+
"is_update": True,
|
|
362
|
+
"not_modified": True,
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return {**upload, "not_modified": False}
|
|
348
366
|
|
|
349
367
|
def create_data_block(
|
|
350
368
|
self,
|
|
@@ -317,6 +317,12 @@ This is likely a server-side bug. Please report this issue to the datalab develo
|
|
|
317
317
|
f"HTTP {response.status_code} error at {url}: {error_message}"
|
|
318
318
|
)
|
|
319
319
|
|
|
320
|
+
# 204 and 304 carry no entity body by definition
|
|
321
|
+
# Where such a status is expected, an empty body
|
|
322
|
+
# is the success case rather than a parse failure.
|
|
323
|
+
if response.status_code in (204, 304):
|
|
324
|
+
return {}
|
|
325
|
+
|
|
320
326
|
# Parse JSON response
|
|
321
327
|
try:
|
|
322
328
|
data = response.json()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: datalab-api
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.2
|
|
4
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-Expression: MIT
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
import respx
|
|
3
|
+
from httpx import Response
|
|
3
4
|
|
|
4
5
|
from datalab_api import DatalabClient
|
|
5
6
|
from datalab_api._base import DatalabAPIError
|
|
@@ -71,3 +72,54 @@ def test_group_get(fake_api_url, mocked_api):
|
|
|
71
72
|
assert mocked_api["search-groups"].called
|
|
72
73
|
assert group["immutable_id"] == "67d0b01e03000cdc75134dbd"
|
|
73
74
|
assert group["group_id"] == "test_group"
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@respx.mock
|
|
78
|
+
def test_upload_file(fake_api_url, mocked_api, tmp_path):
|
|
79
|
+
"""A new upload is stored by the server and reported as modified."""
|
|
80
|
+
fake_upload = mocked_api.post("/upload-file/", name="upload")
|
|
81
|
+
fake_upload.return_value = Response(
|
|
82
|
+
201,
|
|
83
|
+
json={
|
|
84
|
+
"status": "success",
|
|
85
|
+
"file_id": "6810ab6bb2b13a2be6c1e37f",
|
|
86
|
+
"file_information": {"name": "data.csv"},
|
|
87
|
+
"is_update": False,
|
|
88
|
+
},
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
test_file = tmp_path / "data.csv"
|
|
92
|
+
test_file.write_text("a,b\n1,2\n")
|
|
93
|
+
|
|
94
|
+
with DatalabClient(fake_api_url) as client:
|
|
95
|
+
result = client.upload_file(item_id="KUVEKJ", file_path=test_file)
|
|
96
|
+
|
|
97
|
+
assert mocked_api["upload"].called
|
|
98
|
+
assert result["file_id"] == "6810ab6bb2b13a2be6c1e37f"
|
|
99
|
+
assert result["not_modified"] is False
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@respx.mock
|
|
103
|
+
def test_upload_file_not_modified(fake_api_url, mocked_api, tmp_path):
|
|
104
|
+
"""When replacing a file whose content the server already holds, it
|
|
105
|
+
replies 304 with an empty body. That is a successful no-op, so the
|
|
106
|
+
existing file ID is returned with `not_modified` set, rather than
|
|
107
|
+
the empty body being treated as an error."""
|
|
108
|
+
fake_upload = mocked_api.post("/upload-file/", name="upload")
|
|
109
|
+
fake_upload.return_value = Response(304, content=b"")
|
|
110
|
+
|
|
111
|
+
test_file = tmp_path / "data.csv"
|
|
112
|
+
test_file.write_text("a,b\n1,2\n")
|
|
113
|
+
|
|
114
|
+
with DatalabClient(fake_api_url) as client:
|
|
115
|
+
result = client.upload_file(
|
|
116
|
+
item_id="KUVEKJ",
|
|
117
|
+
file_path=test_file,
|
|
118
|
+
replace_file_id="6810ab6bb2b13a2be6c1e37f",
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
assert mocked_api["upload"].called
|
|
122
|
+
assert result["status"] == "success"
|
|
123
|
+
assert result["file_id"] == "6810ab6bb2b13a2be6c1e37f"
|
|
124
|
+
assert result["is_update"] is True
|
|
125
|
+
assert result["not_modified"] is True
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|