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.
Files changed (24) hide show
  1. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/PKG-INFO +2 -2
  2. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/pyproject.toml +1 -1
  3. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/_internal/agent.py +36 -59
  4. cvat_cli-2.68.0/src/cvat_cli/version.py +1 -0
  5. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli.egg-info/PKG-INFO +2 -2
  6. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli.egg-info/requires.txt +1 -1
  7. cvat_cli-2.66.0/src/cvat_cli/version.py +0 -1
  8. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/README.md +0 -0
  9. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/setup.cfg +0 -0
  10. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/__init__.py +0 -0
  11. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/__main__.py +0 -0
  12. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/_internal/__init__.py +0 -0
  13. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/_internal/command_base.py +0 -0
  14. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/_internal/commands_all.py +0 -0
  15. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/_internal/commands_functions.py +0 -0
  16. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/_internal/commands_projects.py +0 -0
  17. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/_internal/commands_tasks.py +0 -0
  18. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/_internal/common.py +0 -0
  19. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/_internal/parsers.py +0 -0
  20. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli/_internal/utils.py +0 -0
  21. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli.egg-info/SOURCES.txt +0 -0
  22. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli.egg-info/dependency_links.txt +0 -0
  23. {cvat_cli-2.66.0 → cvat_cli-2.68.0}/src/cvat_cli.egg-info/entry_points.txt +0 -0
  24. {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.66.0
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.66.0
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
 
@@ -16,7 +16,7 @@ classifiers = [
16
16
  ]
17
17
  requires-python = ">=3.10"
18
18
  dependencies = [
19
- "cvat-sdk==2.66.0",
19
+ "cvat-sdk==2.68.0",
20
20
 
21
21
  "attrs>=24.2.0",
22
22
  "Pillow>=10.3.0",
@@ -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(f"Image sizes of the start frame and the current frame are different")
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 _MAX_TASKS_WITH_CHUNKS
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
- _MAX_TASKS_WITH_CHUNKS = 1
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._cached_with_chunks_task_ids = []
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._cached_with_chunks_task_ids:
299
- # If the task already had cached chunks, we have to return it back to
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 with_chunks:
310
- cached_task_ids = self._cached_with_chunks_task_ids
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
- cached_task_ids.append(task_id)
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"], with_chunks=True):
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(self._client, ar_params["task"], load_annotations=False)
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
- for sample_index, sample in enumerate(ds.samples):
863
- context = self._create_detection_function_context(ar_params, sample.frame_name)
864
- annotations = self._executor.result(
865
- self._executor.submit(_worker_job_detect, context, sample.media.load_image())
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
- tags, shapes = mapper.validate_and_remap(annotations, sample.frame_index)
869
- all_annotations.tags.extend(tags)
870
- all_annotations.shapes.extend(shapes)
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
- current_timestamp = datetime.now(tz=timezone.utc)
853
+ current_timestamp = datetime.now(tz=timezone.utc)
873
854
 
874
- if current_timestamp >= last_update_timestamp + _UPDATE_INTERVAL:
875
- self._update_ar(ar_id, (sample_index + 1) / len(ds.samples))
876
- last_update_timestamp = current_timestamp
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
- # Interactive requests are time sensitive, so if there are any,
879
- # we have to put the current AR on hold and process them ASAP.
880
- self._process_available_ars(REQUEST_CATEGORY_INTERACTIVE)
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.66.0
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.66.0
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,3 +1,3 @@
1
- cvat-sdk==2.66.0
1
+ cvat-sdk==2.68.0
2
2
  attrs>=24.2.0
3
3
  Pillow>=10.3.0
@@ -1 +0,0 @@
1
- VERSION = "2.66.0"
File without changes
File without changes