Repository: voxel51/fiftyone

Issue:
Response format of CVAT job endpoint changed.
When I try to upload my dataset to the CVAT cloud instance, I get an error on the following line:

https://github.com/voxel51/fiftyone/blob/a49fd03ef9d5c98cbdf32f2ee8ac4f62d53c42a5/fiftyone/utils/cvat.py#L4141

The issue is reasonable, as the jobs may be created some time after the import happens (post request). It seems that if you want to request for the job IDs you must wait some time.
I don't know the best solution to fix that, but if you have an idea, I can create a pull request.

Furthermore, the response JSON format in my case is:
```
{'count': 1, 'next': None, 'previous': None, 'results': [{'url': 'https://app.cvat.ai/api/jobs/71332', 'id': 71332, 'task_id': 72946, 'project_id': 12856, ...}]}
```

The top layer keys are `['count', 'next', 'previous', 'results']` but in the line `[j["id"] for j in job_resp.json()]` the `id` is required to be in first layer. This causes the exception `string indices must be integer` as `j["id"]` is actually `"count"["id"]`.

I recommend changing it to `job_ids = [j["id"] for j in job_resp.json()["results"]]` as this resolves the second issue.

The results still might be empty right after the post request. There is still another fix required.



Discussion:
I haven't seen that the while loop prevents the synchronization issue. That means we actually just need to change the line `job_ids = [j["id"] for j in job_resp.json()]` to `job_ids = [j["id"] for j in job_resp.json()["results"]]`.

Sorry for the confusion.
Have encountered the same thing :+1: 
I have had the same issue and the proposed solution of @tjaeuth seems to be working for me. 

This is thus changing the line:
`job_ids = [j["id"] for j in job_resp.json()]` to `job_ids = [j["id"] for j in job_resp.json()["results"]]`


Resolving patch:
diff --git a/fiftyone/utils/cvat.py b/fiftyone/utils/cvat.py
--- a/fiftyone/utils/cvat.py
+++ b/fiftyone/utils/cvat.py
@@ -4139,7 +4139,11 @@ def upload_data(
         job_ids = []
         while not job_ids:
             job_resp = self.get(self.jobs_url(task_id))
-            job_ids = [j["id"] for j in job_resp.json()]
+            job_resp_json = job_resp.json()
+            if "results" in job_resp_json:
+                job_resp_json = job_resp_json["results"]
+
+            job_ids = [j["id"] for j in job_resp_json]
 
         if job_assignees is not None:
             num_assignees = len(job_assignees)


Test patch:
diff --git a/tests/intensive/cvat_tests.py b/tests/intensive/cvat_tests.py
--- a/tests/intensive/cvat_tests.py
+++ b/tests/intensive/cvat_tests.py
@@ -441,7 +441,10 @@ def test_task_creation_arguments(self):
                 self.assertEqual(task_json["name"], f"{task_name}_{idx + 1}")
                 if user is not None:
                     self.assertEqual(task_json["assignee"]["username"], user)
-                for job in api.get(api.jobs_url(task_id)).json():
+                jobs_json = api.get(api.jobs_url(task_id)).json()
+                if "results" in jobs_json:
+                    jobs_json = jobs_json["results"]
+                for job in jobs_json:
                     job_json = api.get(job["url"]).json()
                     if user is not None:
                         self.assertEqual(