Skip to content

Commit 7834093

Browse files
author
Roman Donchenko
committed
cvat-sdk: Fix creating tasks with non-local files
Forcing the `Content-Type` for the `upload_data` API call to `multipart/form-data` does not work, because the current logic for converting Python values to parts (`ApiClient._convert_body_to_post_params`) does not encode them in a way that Django REST Framework can understand (it JSON-encodes each part). Fortunately, we don't actually need to do that, since when we create a task with non-local files, we don't need to upload any files, and so we can just post the original JSON, so do just that. I couldn't add a test for the remote image case, because CVAT rejects all URLs with non-public IP addressses. However, I did test this case manually.
1 parent 7ecd742 commit 7834093

File tree

4 files changed

+22
-3
lines changed

4 files changed

+22
-3
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ non-ascii paths while adding files from "Connected file share" (issue #4428)
3434
- Invisible label item in label constructor when label color background is white,
3535
or close to it (<https://github.com/opencv/cvat/pull/5041>)
3636
- Fixed cvat-core ESlint problems (<https://github.com/opencv/cvat/pull/5027>)
37+
- Fixed task creation with non-local files via the SDK/CLI
38+
(<https://github.com/opencv/cvat/issues/4962>)
3739

3840
### Security
3941
- TDB

cvat-sdk/cvat_sdk/core/proxies/tasks.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,9 @@ def upload_data(
7777
if resource_type is ResourceType.LOCAL:
7878
pass # handled later
7979
elif resource_type is ResourceType.REMOTE:
80-
data = {f"remote_files[{i}]": f for i, f in enumerate(resources)}
80+
data["remote_files"] = resources
8181
elif resource_type is ResourceType.SHARE:
82-
data = {f"server_files[{i}]": f for i, f in enumerate(resources)}
82+
data["server_files"] = resources
8383

8484
data["image_quality"] = 70
8585
data.update(
@@ -104,7 +104,6 @@ def upload_data(
104104
self.api.create_data(
105105
self.id,
106106
data_request=models.DataRequest(**data),
107-
_content_type="multipart/form-data",
108107
)
109108
elif resource_type == ResourceType.LOCAL:
110109
url = self._client.api_map.make_endpoint_url(

tests/python/sdk/test_tasks.py

+17
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,23 @@ def test_can_create_task_with_local_data(self):
126126
assert "100%" in pbar_out.getvalue().strip("\r").split("\r")[-1]
127127
assert self.stdout.getvalue() == ""
128128

129+
def test_can_create_task_with_remote_data(self):
130+
task = self.client.tasks.create_from_data(
131+
spec={
132+
"name": "test_task",
133+
"labels": [{"name": "car"}, {"name": "person"}],
134+
},
135+
resource_type=ResourceType.SHARE,
136+
resources=["image_case_107_2.png", "image_case_107_1.png"],
137+
# make sure string fields are transferred correctly;
138+
# see https://github.com/opencv/cvat/issues/4962
139+
data_params={"sorting_method": "lexicographical"},
140+
)
141+
142+
assert task.size == 2
143+
assert task.get_frames_info()[0].name == "image_case_107_1.png"
144+
assert self.stdout.getvalue() == ""
145+
129146
def test_cant_create_task_with_no_data(self):
130147
pbar_out = io.StringIO()
131148
pbar = make_pbar(file=pbar_out)

tests/python/shared/fixtures/init.py

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
osp.join(CVAT_ROOT_DIR, dc_file)
3131
for dc_file in (
3232
"docker-compose.dev.yml",
33+
"tests/docker-compose.file_share.yml",
3334
"tests/docker-compose.minio.yml",
3435
"tests/docker-compose.webhook.yml",
3536
)

0 commit comments

Comments
 (0)