cvat-cli 2.66.0__tar.gz → 2.68.0__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.
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/PKG-INFO +2 -2
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/pyproject.toml +1 -1
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/_internal/agent.py +36 -59
- cvat_cli-2.68.0/src/cvat_cli/version.py +1 -0
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli.egg-info/PKG-INFO +2 -2
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli.egg-info/requires.txt +1 -1
- cvat_cli-2.66.0/src/cvat_cli/version.py +0 -1
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/README.md +0 -0
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/setup.cfg +0 -0
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/__init__.py +0 -0
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/__main__.py +0 -0
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/_internal/__init__.py +0 -0
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/_internal/command_base.py +0 -0
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/_internal/commands_all.py +0 -0
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/_internal/commands_functions.py +0 -0
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/_internal/commands_projects.py +0 -0
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/_internal/commands_tasks.py +0 -0
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/_internal/common.py +0 -0
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/_internal/parsers.py +0 -0
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/_internal/utils.py +0 -0
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli.egg-info/SOURCES.txt +0 -0
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli.egg-info/dependency_links.txt +0 -0
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli.egg-info/entry_points.txt +0 -0
- {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cvat-cli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.68.0
|
|
4
4
|
Summary: Command-line client for CVAT
|
|
5
5
|
Author-email: "CVAT.ai Corporation" <support@cvat.ai>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -9,7 +9,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
9
9
|
Classifier: Operating System :: OS Independent
|
|
10
10
|
Requires-Python: >=3.10
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
|
-
Requires-Dist: cvat-sdk==2.
|
|
12
|
+
Requires-Dist: cvat-sdk==2.68.0
|
|
13
13
|
Requires-Dist: attrs>=24.2.0
|
|
14
14
|
Requires-Dist: Pillow>=10.3.0
|
|
15
15
|
|
|
@@ -157,7 +157,7 @@ class _TrackingStateContainer:
|
|
|
157
157
|
raise _BadArError(f"Tracking state {state_id!r} is not for task #{task_id}")
|
|
158
158
|
|
|
159
159
|
if image_dims != ext_state.original_image_dims:
|
|
160
|
-
raise _BadArError(
|
|
160
|
+
raise _BadArError("Image sizes of the start frame and the current frame are different")
|
|
161
161
|
|
|
162
162
|
ext_state.last_accessed_at = datetime.now(tz=timezone.utc)
|
|
163
163
|
self._id_to_ext_state.move_to_end(state_id)
|
|
@@ -263,64 +263,41 @@ class _NewReconnectionDelay:
|
|
|
263
263
|
class _TaskCacheLimiter:
|
|
264
264
|
"""
|
|
265
265
|
This class deletes least-recently used tasks from the dataset cache,
|
|
266
|
-
so that at any time the cache contains at most
|
|
267
|
-
tasks with downloaded chunks, and at most _MAX_TASKS_WITHOUT_CHUNKS without.
|
|
266
|
+
so that at any time the cache contains at most _MAX_CACHED_TASKS tasks.
|
|
268
267
|
|
|
269
268
|
This helps manage disk usage, since agents may run indefinitely, and
|
|
270
269
|
we don't want the dataset cache to keep growing.
|
|
271
270
|
"""
|
|
272
271
|
|
|
273
|
-
|
|
274
|
-
_MAX_TASKS_WITHOUT_CHUNKS = 10
|
|
272
|
+
_MAX_CACHED_TASKS = 10
|
|
275
273
|
|
|
276
274
|
def __init__(self, client: Client) -> None:
|
|
277
275
|
self._client = client
|
|
278
276
|
self._cache_manager = make_cache_manager(client, cvatds.UpdatePolicy.IF_MISSING_OR_STALE)
|
|
279
277
|
|
|
280
|
-
self.
|
|
281
|
-
self._cached_without_chunks_task_ids = []
|
|
278
|
+
self._cached_task_ids = []
|
|
282
279
|
|
|
283
280
|
self._task_ids_in_use = set()
|
|
284
281
|
|
|
285
282
|
@contextlib.contextmanager
|
|
286
|
-
def using_cache_for_task(
|
|
287
|
-
self, task_id: int, *, with_chunks: bool
|
|
288
|
-
) -> Generator[None, None, None]:
|
|
283
|
+
def using_cache_for_task(self, task_id: int) -> Generator[None, None, None]:
|
|
289
284
|
if task_id in self._task_ids_in_use:
|
|
290
|
-
# If with_chunks is True, we would have to ensure that task_id is returned to the
|
|
291
|
-
# "with chunks" list after it leaves _task_ids_in_use, regardless of the value of
|
|
292
|
-
# with_chunks in the call that initially put it in. That would be tricky to implement,
|
|
293
|
-
# and we don't have a use case for it, so just ban it.
|
|
294
|
-
assert not with_chunks
|
|
295
285
|
yield
|
|
296
286
|
return
|
|
297
287
|
|
|
298
|
-
if task_id in self.
|
|
299
|
-
|
|
300
|
-
# _cached_with_chunks_task_ids in the end.
|
|
301
|
-
with_chunks = True
|
|
302
|
-
|
|
303
|
-
self._cached_with_chunks_task_ids.remove(task_id)
|
|
304
|
-
elif task_id in self._cached_without_chunks_task_ids:
|
|
305
|
-
self._cached_without_chunks_task_ids.remove(task_id)
|
|
288
|
+
if task_id in self._cached_task_ids:
|
|
289
|
+
self._cached_task_ids.remove(task_id)
|
|
306
290
|
|
|
307
291
|
self._task_ids_in_use.add(task_id)
|
|
308
292
|
|
|
309
|
-
if
|
|
310
|
-
|
|
311
|
-
max_cached_tasks = self._MAX_TASKS_WITH_CHUNKS
|
|
312
|
-
else:
|
|
313
|
-
cached_task_ids = self._cached_without_chunks_task_ids
|
|
314
|
-
max_cached_tasks = self._MAX_TASKS_WITHOUT_CHUNKS
|
|
315
|
-
|
|
316
|
-
if len(cached_task_ids) + len(self._task_ids_in_use) > max_cached_tasks:
|
|
317
|
-
self._delete_task_cache(cached_task_ids.pop(0))
|
|
293
|
+
if len(self._cached_task_ids) + len(self._task_ids_in_use) > self._MAX_CACHED_TASKS:
|
|
294
|
+
self._delete_task_cache(self._cached_task_ids.pop(0))
|
|
318
295
|
|
|
319
296
|
try:
|
|
320
297
|
yield
|
|
321
298
|
finally:
|
|
322
299
|
self._task_ids_in_use.remove(task_id)
|
|
323
|
-
|
|
300
|
+
self._cached_task_ids.append(task_id)
|
|
324
301
|
|
|
325
302
|
def _delete_task_cache(self, task_id: int) -> None:
|
|
326
303
|
self._client.logger.info("Deleting task %d from the cache to make room...", task_id)
|
|
@@ -809,12 +786,10 @@ class _Agent:
|
|
|
809
786
|
|
|
810
787
|
def _calculate_result_for_detection_ar(self, ar_id: str, ar_params) -> dict[str, Any]:
|
|
811
788
|
if ar_params["type"] == "annotate_task":
|
|
812
|
-
with self._task_cache_limiter.using_cache_for_task(ar_params["task"]
|
|
789
|
+
with self._task_cache_limiter.using_cache_for_task(ar_params["task"]):
|
|
813
790
|
return self._calculate_result_for_annotate_task_ar(ar_id, ar_params)
|
|
814
791
|
elif ar_params["type"] == "annotate_frame":
|
|
815
|
-
with self._task_cache_limiter.using_cache_for_task(
|
|
816
|
-
ar_params["task"], with_chunks=False
|
|
817
|
-
):
|
|
792
|
+
with self._task_cache_limiter.using_cache_for_task(ar_params["task"]):
|
|
818
793
|
return self._calculate_result_for_annotate_frame_ar(ar_id, ar_params)
|
|
819
794
|
else:
|
|
820
795
|
raise _BadArError(f"unsupported type: {ar_params['type']!r}")
|
|
@@ -848,7 +823,12 @@ class _Agent:
|
|
|
848
823
|
)
|
|
849
824
|
|
|
850
825
|
def _calculate_result_for_annotate_task_ar(self, ar_id: str, ar_params) -> dict[str, Any]:
|
|
851
|
-
ds = cvatds.TaskDataset(
|
|
826
|
+
ds = cvatds.TaskDataset(
|
|
827
|
+
self._client,
|
|
828
|
+
ar_params["task"],
|
|
829
|
+
load_annotations=False,
|
|
830
|
+
media_download_policy=cvatds.MediaDownloadPolicy.FETCH_CHUNKS_ON_DEMAND,
|
|
831
|
+
)
|
|
852
832
|
|
|
853
833
|
# Fetching the dataset might take a while, so do a progress update to let the server
|
|
854
834
|
# know we're still alive.
|
|
@@ -859,25 +839,26 @@ class _Agent:
|
|
|
859
839
|
|
|
860
840
|
all_annotations = models.PatchedLabeledDataRequest(tags=[], shapes=[])
|
|
861
841
|
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
self._executor.
|
|
866
|
-
|
|
842
|
+
with ds.iter_samples(temporary_chunks=True) as samples:
|
|
843
|
+
for sample_index, sample in enumerate(samples):
|
|
844
|
+
context = self._create_detection_function_context(ar_params, sample.frame_name)
|
|
845
|
+
annotations = self._executor.result(
|
|
846
|
+
self._executor.submit(_worker_job_detect, context, sample.media.load_image())
|
|
847
|
+
)
|
|
867
848
|
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
849
|
+
tags, shapes = mapper.validate_and_remap(annotations, sample.frame_index)
|
|
850
|
+
all_annotations.tags.extend(tags)
|
|
851
|
+
all_annotations.shapes.extend(shapes)
|
|
871
852
|
|
|
872
|
-
|
|
853
|
+
current_timestamp = datetime.now(tz=timezone.utc)
|
|
873
854
|
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
855
|
+
if current_timestamp >= last_update_timestamp + _UPDATE_INTERVAL:
|
|
856
|
+
self._update_ar(ar_id, (sample_index + 1) / len(ds.samples))
|
|
857
|
+
last_update_timestamp = current_timestamp
|
|
877
858
|
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
859
|
+
# Interactive requests are time sensitive, so if there are any,
|
|
860
|
+
# we have to put the current AR on hold and process them ASAP.
|
|
861
|
+
self._process_available_ars(REQUEST_CATEGORY_INTERACTIVE)
|
|
881
862
|
|
|
882
863
|
return {"annotations": all_annotations}
|
|
883
864
|
|
|
@@ -897,14 +878,10 @@ class _Agent:
|
|
|
897
878
|
|
|
898
879
|
def _calculate_result_for_tracking_ar(self, ar_id: str, ar_params) -> dict[str, Any]:
|
|
899
880
|
if ar_params["type"] == "init_tracking":
|
|
900
|
-
with self._task_cache_limiter.using_cache_for_task(
|
|
901
|
-
ar_params["task"], with_chunks=False
|
|
902
|
-
):
|
|
881
|
+
with self._task_cache_limiter.using_cache_for_task(ar_params["task"]):
|
|
903
882
|
return self._calculate_result_for_init_tracking_ar(ar_id, ar_params)
|
|
904
883
|
elif ar_params["type"] == "track":
|
|
905
|
-
with self._task_cache_limiter.using_cache_for_task(
|
|
906
|
-
ar_params["task"], with_chunks=False
|
|
907
|
-
):
|
|
884
|
+
with self._task_cache_limiter.using_cache_for_task(ar_params["task"]):
|
|
908
885
|
return self._calculate_result_for_track_ar(ar_id, ar_params)
|
|
909
886
|
else:
|
|
910
887
|
raise _BadArError(f"unsupported type: {ar_params['type']!r}")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VERSION = "2.68.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cvat-cli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.68.0
|
|
4
4
|
Summary: Command-line client for CVAT
|
|
5
5
|
Author-email: "CVAT.ai Corporation" <support@cvat.ai>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -9,7 +9,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
9
9
|
Classifier: Operating System :: OS Independent
|
|
10
10
|
Requires-Python: >=3.10
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
|
-
Requires-Dist: cvat-sdk==2.
|
|
12
|
+
Requires-Dist: cvat-sdk==2.68.0
|
|
13
13
|
Requires-Dist: attrs>=24.2.0
|
|
14
14
|
Requires-Dist: Pillow>=10.3.0
|
|
15
15
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
VERSION = "2.66.0"
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|