supervisely 6.73.228__py3-none-any.whl → 6.73.230__py3-none-any.whl

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.
@@ -1388,7 +1388,7 @@ class AnnotationApi(ModuleApi):
1388
1388
  ann_info = loop.run_until_complete(api.annotation.download_async(image_id))
1389
1389
  """
1390
1390
  if semaphore is None:
1391
- semaphore = self._api._get_default_semaphore()
1391
+ semaphore = self._api.get_default_semaphore()
1392
1392
  async with semaphore:
1393
1393
  response = await self._api.post_async(
1394
1394
  "annotations.info",
@@ -1501,7 +1501,7 @@ class AnnotationApi(ModuleApi):
1501
1501
  context["project_meta"] = project_meta
1502
1502
 
1503
1503
  if semaphore is None:
1504
- semaphore = self._api._get_default_semaphore()
1504
+ semaphore = self._api.get_default_semaphore()
1505
1505
  tasks = []
1506
1506
  for image in image_ids:
1507
1507
  task = self.download_async(
supervisely/api/api.py CHANGED
@@ -377,6 +377,7 @@ class Api:
377
377
 
378
378
  self.async_httpx_client: httpx.AsyncClient = None
379
379
  self.httpx_client: httpx.Client = None
380
+ self._semaphore = None
380
381
 
381
382
  @classmethod
382
383
  def normalize_server_address(cls, server_address: str) -> str:
@@ -999,7 +1000,10 @@ class Api:
999
1000
  def post_httpx(
1000
1001
  self,
1001
1002
  method: str,
1002
- data: Union[bytes, Dict],
1003
+ json: Dict = None,
1004
+ content: Union[str, bytes, Iterable[bytes], AsyncIterable[bytes]] = None,
1005
+ files: Union[Mapping] = None,
1006
+ params: Union[str, bytes] = None,
1003
1007
  headers: Optional[Dict[str, str]] = None,
1004
1008
  retries: Optional[int] = None,
1005
1009
  raise_error: Optional[bool] = False,
@@ -1009,8 +1013,14 @@ class Api:
1009
1013
 
1010
1014
  :param method: Method name.
1011
1015
  :type method: str
1012
- :param data: Bytes with data content or dictionary with params.
1013
- :type data: bytes or dict
1016
+ :param json: Dictionary to send in the body of request.
1017
+ :type json: dict, optional
1018
+ :param content: Bytes with data content or dictionary with params.
1019
+ :type content: bytes or dict, optional
1020
+ :param files: Files to send in the body of request.
1021
+ :type files: dict, optional
1022
+ :param params: URL query parameters.
1023
+ :type params: str, bytes, optional
1014
1024
  :param headers: Custom headers to include in the request.
1015
1025
  :type headers: dict, optional
1016
1026
  :param retries: The number of attempts to connect to the server.
@@ -1021,6 +1031,7 @@ class Api:
1021
1031
  :rtype: :class:`httpx.Response`
1022
1032
  """
1023
1033
  self._set_client()
1034
+
1024
1035
  if retries is None:
1025
1036
  retries = self.retry_count
1026
1037
 
@@ -1032,18 +1043,17 @@ class Api:
1032
1043
  else:
1033
1044
  headers = {**self.headers, **headers}
1034
1045
 
1035
- if isinstance(data, bytes):
1036
- request_params = {"content": data}
1037
- elif isinstance(data, Dict):
1038
- json_body = {**data, **self.additional_fields}
1039
- request_params = {"json": json_body}
1040
- else:
1041
- request_params = {"params": data}
1042
-
1043
1046
  for retry_idx in range(retries):
1044
1047
  response = None
1045
1048
  try:
1046
- response = self.httpx_client.post(url, headers=headers, **request_params)
1049
+ response = self.httpx_client.post(
1050
+ url,
1051
+ content=content,
1052
+ files=files,
1053
+ json=json,
1054
+ params=params,
1055
+ headers=headers,
1056
+ )
1047
1057
  if response.status_code != httpx.codes.OK:
1048
1058
  self._check_version()
1049
1059
  Api._raise_for_status_httpx(response)
@@ -1065,9 +1075,8 @@ class Api:
1065
1075
  )
1066
1076
  except Exception as exc:
1067
1077
  process_unhandled_request(self.logger, exc)
1068
- raise httpx.HTTPStatusError(
1069
- "Retry limit exceeded ({!r})".format(url),
1070
- response=response,
1078
+ raise httpx.RequestError(
1079
+ f"Retry limit exceeded ({url})",
1071
1080
  request=getattr(response, "request", None),
1072
1081
  )
1073
1082
 
@@ -1093,6 +1102,7 @@ class Api:
1093
1102
  :rtype: :class:`Response<Response>`
1094
1103
  """
1095
1104
  self._set_client()
1105
+
1096
1106
  if retries is None:
1097
1107
  retries = self.retry_count
1098
1108
 
@@ -1171,8 +1181,8 @@ class Api:
1171
1181
  :return: Generator object.
1172
1182
  :rtype: :class:`Generator`
1173
1183
  """
1174
-
1175
1184
  self._set_client()
1185
+
1176
1186
  if retries is None:
1177
1187
  retries = self.retry_count
1178
1188
 
@@ -1408,14 +1418,13 @@ class Api:
1408
1418
  url = self.api_server_address + "/v3/" + method
1409
1419
  if not use_public_api:
1410
1420
  url = os.path.join(self.server_address, method)
1421
+ logger.trace(f"{method_type} {url}")
1411
1422
 
1412
1423
  if headers is None:
1413
1424
  headers = self.headers.copy()
1414
1425
  else:
1415
1426
  headers = {**self.headers, **headers}
1416
1427
 
1417
- logger.trace(f"{method_type} {url}")
1418
-
1419
1428
  if isinstance(data, (bytes, Generator)):
1420
1429
  content = data
1421
1430
  json_body = None
@@ -1506,42 +1515,80 @@ class Api:
1506
1515
 
1507
1516
  def _set_async_client(self):
1508
1517
  """
1509
- Set async httpx client if it is not set yet.
1510
- Switch on HTTP/2 if the server address uses HTTPS.
1518
+ Set async httpx client with HTTP/2 if it is not set yet.
1511
1519
  """
1512
1520
  if self.async_httpx_client is None:
1513
- self._check_https_redirect()
1514
- if self.server_address.startswith("https://"):
1515
- self.async_httpx_client = httpx.AsyncClient(http2=True)
1516
- else:
1517
- self.async_httpx_client = httpx.AsyncClient()
1521
+ self.async_httpx_client = httpx.AsyncClient(http2=True)
1518
1522
 
1519
1523
  def _set_client(self):
1520
1524
  """
1521
- Set httpx client if it is not set yet.
1522
- Switch on HTTP/2 if the server address uses HTTPS.
1525
+ Set sync httpx client with HTTP/2 if it is not set yet.
1523
1526
  """
1524
1527
  if self.httpx_client is None:
1525
- self._check_https_redirect()
1526
- if self.server_address.startswith("https://"):
1527
- self.httpx_client = httpx.Client(http2=True)
1528
- else:
1529
- self.httpx_client = httpx.Client()
1528
+ self.httpx_client = httpx.Client(http2=True)
1529
+
1530
+ def get_default_semaphore(self) -> asyncio.Semaphore:
1531
+ """
1532
+ Get default global API semaphore for async requests.
1533
+ If the semaphore is not set, it will be initialized.
1534
+
1535
+ During initialization, the semaphore size will be set from the environment variable SUPERVISELY_ASYNC_SEMAPHORE.
1536
+ If the environment variable is not set, the default value will be set based on the server address.
1537
+ Depending on the server address, the semaphore size will be set to 10 for HTTPS and 5 for HTTP.
1538
+
1539
+ :return: Semaphore object.
1540
+ :rtype: :class:`asyncio.Semaphore`
1541
+ """
1542
+ if self._semaphore is None:
1543
+ self._initialize_semaphore()
1544
+ return self._semaphore
1530
1545
 
1531
- def _get_default_semaphore(self):
1546
+ def _initialize_semaphore(self):
1532
1547
  """
1533
- Get default semaphore for async requests.
1534
- Check if the environment variable SUPERVISELY_ASYNC_SEMAPHORE is set.
1535
- If it is set, create a semaphore with the given value.
1536
- Otherwise, create a semaphore with a default value.
1537
- If server supports HTTPS, create a semaphore with a higher value.
1548
+ Initialize the semaphore for async requests.
1549
+
1550
+ If the environment variable SUPERVISELY_ASYNC_SEMAPHORE is set, create a semaphore with the given value.
1551
+
1552
+ Otherwise, create a semaphore with a default value:
1553
+
1554
+ - If server supports HTTPS, create a semaphore with value 10.
1555
+ - If server supports HTTP, create a semaphore with value 5.
1538
1556
  """
1539
- env_semaphore = os.getenv("SUPERVISELY_ASYNC_SEMAPHORE")
1540
- if env_semaphore is not None:
1541
- return asyncio.Semaphore(int(env_semaphore))
1557
+ semaphore_size = sly_env.semaphore_size()
1558
+ if semaphore_size is not None:
1559
+ self._semaphore = asyncio.Semaphore(semaphore_size)
1560
+ logger.debug(
1561
+ f"Setting global API semaphore size to {semaphore_size} from environment variable"
1562
+ )
1542
1563
  else:
1543
1564
  self._check_https_redirect()
1544
1565
  if self.server_address.startswith("https://"):
1545
- return asyncio.Semaphore(25)
1566
+ self._semaphore = asyncio.Semaphore(10)
1567
+ logger.debug("Setting global API semaphore size to 10 for HTTPS")
1546
1568
  else:
1547
- return asyncio.Semaphore(5)
1569
+ self._semaphore = asyncio.Semaphore(5)
1570
+ logger.debug("Setting global API semaphore size to 5 for HTTP")
1571
+
1572
+ def set_semaphore_size(self, size: int = None):
1573
+ """
1574
+ Set the global API semaphore with the given size. Will replace the existing semaphore.
1575
+ If the size is not set, will set from the environment variable SUPERVISELY_ASYNC_SEMAPHORE.
1576
+ If the environment variable is not set, will set the default value.
1577
+
1578
+ :param size: Size of the semaphore.
1579
+ :type size: int, optional
1580
+ """
1581
+ if size is not None:
1582
+ self._semaphore = asyncio.Semaphore(size)
1583
+ else:
1584
+ self._initialize_semaphore()
1585
+
1586
+ @property
1587
+ def semaphore(self) -> asyncio.Semaphore:
1588
+ """
1589
+ Get the global API semaphore for async requests.
1590
+
1591
+ :return: Semaphore object.
1592
+ :rtype: :class:`asyncio.Semaphore`
1593
+ """
1594
+ return self._semaphore
@@ -551,7 +551,7 @@ class AppApi(TaskApi):
551
551
 
552
552
  def is_enabled(self) -> bool:
553
553
  """Check if the workflow functionality is enabled."""
554
- logger.info(f"Workflow check: is {'enabled' if self._enabled else 'disabled'}.")
554
+ logger.debug(f"Workflow check: is {'enabled' if self._enabled else 'disabled'}.")
555
555
  return self._enabled
556
556
 
557
557
  # pylint: disable=no-self-argument
@@ -579,8 +579,8 @@ class AppApi(TaskApi):
579
579
  ):
580
580
  self.__last_warning_time = time.monotonic()
581
581
  logger.warning(
582
- "Workflow is disabled in development mode. "
583
- "To enable it, use `api.app.workflow.enable()` right after Api initialization."
582
+ "Workflow is disabled. "
583
+ "To enable it, use `api.app.workflow.enable()`."
584
584
  )
585
585
  return
586
586
  if not check_workflow_compatibility(self._api, version_to_check):
@@ -74,7 +74,7 @@ class TagApi(ModuleApi):
74
74
 
75
75
  :param project_id: :class:`Dataset<supervisely.project.project.Project>` ID in Supervisely.
76
76
  :type project_id: int
77
- :param filters: List of parameters to sort output tags. See: https://dev.supervise.ly/api-docs/#tag/Advanced/paths/~1tags.list/get
77
+ :param filters: List of parameters to sort output tags. See: https://api.docs.supervisely.com/#tag/Advanced/paths/~1tags.list/get
78
78
  :type filters: List[Dict[str, str]], optional
79
79
  :return: List of the tags from the project with given id.
80
80
  :rtype: list
@@ -1646,7 +1646,7 @@ class FileApi(ModuleApiBase):
1646
1646
  loop.run_until_complete(api.file.download_async(8, path_to_file, local_save_path))
1647
1647
  """
1648
1648
  if semaphore is None:
1649
- semaphore = self._api._get_default_semaphore()
1649
+ semaphore = self._api.get_default_semaphore()
1650
1650
  async with semaphore:
1651
1651
  if self.is_on_agent(remote_path):
1652
1652
  # for optimized download from agent
@@ -1774,7 +1774,7 @@ class FileApi(ModuleApiBase):
1774
1774
  )
1775
1775
 
1776
1776
  if semaphore is None:
1777
- semaphore = self._api._get_default_semaphore()
1777
+ semaphore = self._api.get_default_semaphore()
1778
1778
 
1779
1779
  tasks = []
1780
1780
  for remote_path, local_path, cache in zip(
@@ -1836,7 +1836,7 @@ class FileApi(ModuleApiBase):
1836
1836
  """
1837
1837
 
1838
1838
  if semaphore is None:
1839
- semaphore = self._api._get_default_semaphore()
1839
+ semaphore = self._api.get_default_semaphore()
1840
1840
 
1841
1841
  if not remote_path.endswith("/"):
1842
1842
  remote_path += "/"
@@ -1925,7 +1925,7 @@ class FileApi(ModuleApiBase):
1925
1925
  """
1926
1926
 
1927
1927
  if semaphore is None:
1928
- semaphore = self._api._get_default_semaphore()
1928
+ semaphore = self._api.get_default_semaphore()
1929
1929
 
1930
1930
  remote_file_path = env.file(raise_not_found=False)
1931
1931
  remote_folder_path = env.folder(raise_not_found=False)
@@ -2061,7 +2061,7 @@ class FileApi(ModuleApiBase):
2061
2061
  # "sha256": sha256, #TODO add with resumaple api
2062
2062
  }
2063
2063
  if semaphore is None:
2064
- semaphore = self._api._get_default_semaphore()
2064
+ semaphore = self._api.get_default_semaphore()
2065
2065
  async with semaphore:
2066
2066
  async with aiofiles.open(src, "rb") as fd:
2067
2067
  item = await fd.read()
@@ -2129,7 +2129,7 @@ class FileApi(ModuleApiBase):
2129
2129
  )
2130
2130
  """
2131
2131
  if semaphore is None:
2132
- semaphore = self._api._get_default_semaphore()
2132
+ semaphore = self._api.get_default_semaphore()
2133
2133
  tasks = []
2134
2134
  for s, d in zip(src_paths, dst_paths):
2135
2135
  task = self.upload_async(
@@ -325,6 +325,7 @@ class ImageApi(RemoveableBulkModuleApi):
325
325
  return_first_response: Optional[bool] = False,
326
326
  project_id: Optional[int] = None,
327
327
  only_labelled: Optional[bool] = False,
328
+ fields: Optional[List[str]] = None,
328
329
  ) -> List[ImageInfo]:
329
330
  """
330
331
  List of Images in the given :class:`Dataset<supervisely.project.project.Dataset>`.
@@ -347,6 +348,8 @@ class ImageApi(RemoveableBulkModuleApi):
347
348
  :type project_id: :class:`int`
348
349
  :param only_labelled: If True, returns only images with labels.
349
350
  :type only_labelled: bool, optional
351
+ :param fields: List of fields to return. If None, returns all fields.
352
+ :type fields: List[str], optional
350
353
  :return: Objects with image information from Supervisely.
351
354
  :rtype: :class:`List[ImageInfo]<ImageInfo>`
352
355
  :Usage example:
@@ -419,7 +422,8 @@ class ImageApi(RemoveableBulkModuleApi):
419
422
  },
420
423
  }
421
424
  ]
422
-
425
+ if fields is not None:
426
+ data[ApiField.FIELDS] = fields
423
427
  return self.get_list_all_pages(
424
428
  "images.list",
425
429
  data=data,
@@ -3639,7 +3643,7 @@ class ImageApi(RemoveableBulkModuleApi):
3639
3643
  results = await asyncio.gather(*tasks)
3640
3644
  """
3641
3645
  if semaphore is None:
3642
- semaphore = self._api._get_default_semaphore()
3646
+ semaphore = self._api.get_default_semaphore()
3643
3647
 
3644
3648
  async with semaphore:
3645
3649
  async for response in self._download_async(id):
@@ -3697,7 +3701,7 @@ class ImageApi(RemoveableBulkModuleApi):
3697
3701
 
3698
3702
  """
3699
3703
  if semaphore is None:
3700
- semaphore = self._api._get_default_semaphore()
3704
+ semaphore = self._api.get_default_semaphore()
3701
3705
  tasks = [
3702
3706
  self.download_np_async(id, semaphore, keep_alpha, progress_cb, progress_cb_type)
3703
3707
  for id in ids
@@ -3772,7 +3776,7 @@ class ImageApi(RemoveableBulkModuleApi):
3772
3776
  ensure_base_path(path)
3773
3777
  hash_to_check = None
3774
3778
  if semaphore is None:
3775
- semaphore = self._api._get_default_semaphore()
3779
+ semaphore = self._api.get_default_semaphore()
3776
3780
  async with semaphore:
3777
3781
  async with aiofiles.open(path, writing_method) as fd:
3778
3782
  async for chunk, hhash in self._download_async(
@@ -3850,7 +3854,7 @@ class ImageApi(RemoveableBulkModuleApi):
3850
3854
  f'Length of "ids" and "paths" should be equal. {len(ids)} != {len(paths)}'
3851
3855
  )
3852
3856
  if semaphore is None:
3853
- semaphore = self._api._get_default_semaphore()
3857
+ semaphore = self._api.get_default_semaphore()
3854
3858
  tasks = []
3855
3859
  for img_id, img_path in zip(ids, paths):
3856
3860
  task = self.download_path_async(
@@ -3924,7 +3928,7 @@ class ImageApi(RemoveableBulkModuleApi):
3924
3928
  hash_to_check = None
3925
3929
 
3926
3930
  if semaphore is None:
3927
- semaphore = self._api._get_default_semaphore()
3931
+ semaphore = self._api.get_default_semaphore()
3928
3932
  async with semaphore:
3929
3933
  content = b""
3930
3934
  async for chunk, hhash in self._download_async(
@@ -3993,7 +3997,7 @@ class ImageApi(RemoveableBulkModuleApi):
3993
3997
  img_bytes_list = loop.run_until_complete(api.image.download_bytes_imgs_async(ids, semaphore))
3994
3998
  """
3995
3999
  if semaphore is None:
3996
- semaphore = self._api._get_default_semaphore()
4000
+ semaphore = self._api.get_default_semaphore()
3997
4001
  tasks = []
3998
4002
  for id in ids:
3999
4003
  task = self.download_bytes_single_async(
@@ -232,7 +232,7 @@ class PointcloudApi(RemoveableBulkModuleApi):
232
232
 
233
233
  :param dataset_id: :class:`Dataset<supervisely.project.project.Dataset>` ID in Supervisely.
234
234
  :type dataset_id: int
235
- :param filters: List of parameters to sort output Pointclouds. See: https://dev.supervise.ly/api-docs/#tag/Point-Clouds/paths/~1point-clouds.list/get
235
+ :param filters: List of parameters to sort output Pointclouds. See: https://api.docs.supervisely.com/#tag/Point-Clouds/paths/~1point-clouds.list/get
236
236
  :type filters: List[Dict[str, str]], optional
237
237
  :return: List of the point clouds objects from the dataset with given id.
238
238
  :rtype: :class:`List[PointcloudInfo]`
@@ -407,7 +407,7 @@ class PointcloudApi(RemoveableBulkModuleApi):
407
407
  # 'hash': 'vxA+emfDNUkFP9P6oitMB5Q0rMlnskmV2jvcf47OjGU=',
408
408
  # 'link': None,
409
409
  # 'preview': '/previews/q/ext:jpeg/resize:fill:50:0:0/q:50/plain/h5ad-public/images/original/S/j/hJ/PwMg.png',
410
- # 'fullStorageUrl': 'https://dev.supervise.ly/hs4-public/images/original/S/j/hJ/PwMg.png',
410
+ # 'fullStorageUrl': 'https://app.supervisely.com/hs4-public/images/original/S/j/hJ/PwMg.png',
411
411
  # 'name': 'img00'
412
412
  # }
413
413
  """
@@ -1166,7 +1166,7 @@ class PointcloudApi(RemoveableBulkModuleApi):
1166
1166
  ensure_base_path(path)
1167
1167
  hash_to_check = None
1168
1168
  if semaphore is None:
1169
- semaphore = self._api._get_default_semaphore()
1169
+ semaphore = self._api.get_default_semaphore()
1170
1170
  async with semaphore:
1171
1171
  async with aiofiles.open(path, writing_method) as fd:
1172
1172
  async for chunk, hhash in self._download_async(
@@ -1248,7 +1248,7 @@ class PointcloudApi(RemoveableBulkModuleApi):
1248
1248
  if len(ids) != len(paths):
1249
1249
  raise ValueError('Can not match "ids" and "paths" lists, len(ids) != len(paths)')
1250
1250
  if semaphore is None:
1251
- semaphore = self._api._get_default_semaphore()
1251
+ semaphore = self._api.get_default_semaphore()
1252
1252
  tasks = []
1253
1253
  for img_id, img_path in zip(ids, paths):
1254
1254
  task = self.download_path_async(
@@ -1322,7 +1322,7 @@ class PointcloudApi(RemoveableBulkModuleApi):
1322
1322
  ensure_base_path(path)
1323
1323
  hash_to_check = None
1324
1324
  if semaphore is None:
1325
- semaphore = self._api._get_default_semaphore()
1325
+ semaphore = self._api.get_default_semaphore()
1326
1326
  async with semaphore:
1327
1327
  async with aiofiles.open(path, "wb") as fd:
1328
1328
  async for chunk, hhash in self._api.stream_async(
@@ -1403,7 +1403,7 @@ class PointcloudApi(RemoveableBulkModuleApi):
1403
1403
  if len(ids) != len(paths):
1404
1404
  raise ValueError('Can not match "ids" and "paths" lists, len(ids) != len(paths)')
1405
1405
  if semaphore is None:
1406
- semaphore = self._api._get_default_semaphore()
1406
+ semaphore = self._api.get_default_semaphore()
1407
1407
  tasks = []
1408
1408
  for img_id, img_path in zip(ids, paths):
1409
1409
  task = self.download_related_image_async(
@@ -284,7 +284,7 @@ class VideoAnnotationAPI(EntityAnnotationAPI):
284
284
  video_info = self._api.video.get_info_by_id(video_id)
285
285
 
286
286
  if semaphore is None:
287
- semaphore = self._api._get_default_semaphore()
287
+ semaphore = self._api.get_default_semaphore()
288
288
 
289
289
  async with semaphore:
290
290
  response = await self._api.post_async(
@@ -339,16 +339,19 @@ class VideoApi(RemoveableBulkModuleApi):
339
339
  dataset_id: int,
340
340
  filters: Optional[List[Dict[str, str]]] = None,
341
341
  raw_video_meta: Optional[bool] = False,
342
+ fields: Optional[List[str]] = None,
342
343
  ) -> List[VideoInfo]:
343
344
  """
344
345
  Get list of information about all videos for a given dataset ID.
345
346
 
346
347
  :param dataset_id: :class:`Dataset<supervisely.project.project.Dataset>` ID in Supervisely.
347
348
  :type dataset_id: int
348
- :param filters: List of parameters to sort output Videos. See: https://dev.supervise.ly/api-docs/#tag/Videos/paths/~1videos.list/get
349
+ :param filters: List of parameters to sort output Videos. See: https://api.docs.supervisely.com/#tag/Videos/paths/~1videos.list/get
349
350
  :type filters: List[Dict[str, str]], optional
350
351
  :param raw_video_meta: Get normalized metadata from server if False.
351
352
  :type raw_video_meta: bool
353
+ :param fields: List of fields to return.
354
+ :type fields: List[str], optional
352
355
  :return: List of information about videos in given dataset.
353
356
  :rtype: :class:`List[VideoInfo]`
354
357
 
@@ -372,15 +375,14 @@ class VideoApi(RemoveableBulkModuleApi):
372
375
  print(filtered_video_infos)
373
376
  # Output: [VideoInfo(id=19371139, ...)]
374
377
  """
375
-
376
- return self.get_list_all_pages(
377
- "videos.list",
378
- {
379
- ApiField.DATASET_ID: dataset_id,
380
- ApiField.FILTER: filters or [],
381
- ApiField.RAW_VIDEO_META: raw_video_meta,
382
- },
383
- )
378
+ data = {
379
+ ApiField.DATASET_ID: dataset_id,
380
+ ApiField.FILTER: filters or [],
381
+ ApiField.RAW_VIDEO_META: raw_video_meta,
382
+ }
383
+ if fields is not None:
384
+ data[ApiField.FIELDS] = fields
385
+ return self.get_list_all_pages("videos.list", data)
384
386
 
385
387
  def get_list_generator(
386
388
  self,
@@ -2482,7 +2484,7 @@ class VideoApi(RemoveableBulkModuleApi):
2482
2484
  ensure_base_path(path)
2483
2485
  hash_to_check = None
2484
2486
  if semaphore is None:
2485
- semaphore = self._api._get_default_semaphore()
2487
+ semaphore = self._api.get_default_semaphore()
2486
2488
  async with semaphore:
2487
2489
  async with aiofiles.open(path, writing_method) as fd:
2488
2490
  async for chunk, hhash in self._download_async(
@@ -2562,7 +2564,7 @@ class VideoApi(RemoveableBulkModuleApi):
2562
2564
  if len(ids) != len(paths):
2563
2565
  raise ValueError('Can not match "ids" and "paths" lists, len(ids) != len(paths)')
2564
2566
  if semaphore is None:
2565
- semaphore = self._api._get_default_semaphore()
2567
+ semaphore = self._api.get_default_semaphore()
2566
2568
  tasks = []
2567
2569
  for img_id, img_path in zip(ids, paths):
2568
2570
  task = self.download_path_async(
@@ -65,7 +65,7 @@ class VolumeInfo(NamedTuple):
65
65
  'rescaleIntercept': 0
66
66
  },
67
67
  path_original='/h5af-public/images/original/M/e/7R/vsytec8zX0p.nrrd',
68
- full_storage_url='https://dev.supervise.ly/h5un-public/images/original/M/e/7R/zX0p.nrrd',
68
+ full_storage_url='https://app.supervisely.com/h5un-public/images/original/M/e/7R/zX0p.nrrd',
69
69
  tags=[],
70
70
  team_id=435,
71
71
  workspace_id=685,
@@ -260,7 +260,7 @@ class VolumeApi(RemoveableBulkModuleApi):
260
260
 
261
261
  :param dataset_id: :class:`Dataset<supervisely.project.project.Dataset>` ID in Supervisely.
262
262
  :type dataset_id: int
263
- :param filters: List of parameters to sort output Volumes. See: https://dev.supervise.ly/api-docs/#tag/Volumes/paths/~1volumes.list/get
263
+ :param filters: List of parameters to sort output Volumes. See: https://api.docs.supervisely.com/#tag/Volumes/paths/~1volumes.list/get
264
264
  :type filters: List[Dict[str, str]], optional
265
265
  :param sort: Attribute to sort the list by. The default is "id". Valid values are "id", "name", "description", "createdAt", "updatedAt".
266
266
  :type sort: :class:`str`
@@ -349,7 +349,7 @@ class VolumeApi(RemoveableBulkModuleApi):
349
349
  # 'rescaleIntercept': 0
350
350
  # },
351
351
  # path_original='/h5af-public/images/original/M/e/7R/vs0p.nrrd',
352
- # full_storage_url='https://dev.supervise.ly/.../original/M/e/7R/zX0p.nrrd',
352
+ # full_storage_url='https://app.supervisely.com/.../original/M/e/7R/zX0p.nrrd',
353
353
  # tags=[],
354
354
  # team_id=435,
355
355
  # workspace_id=685,
@@ -435,7 +435,7 @@ class VolumeApi(RemoveableBulkModuleApi):
435
435
  # 'rescaleIntercept': 0
436
436
  # },
437
437
  # path_original='/h5af-public/images/original/M/e/7R/zfsfX0p.nrrd',
438
- # full_storage_url='https://dev.supervise.ly/h5un-public/images/original/M/e/7R/zXdd0p.nrrd',
438
+ # full_storage_url='https://app.supervisely.com/h5un-public/images/original/M/e/7R/zXdd0p.nrrd',
439
439
  # tags=[],
440
440
  # team_id=435,
441
441
  # workspace_id=685,
@@ -1360,7 +1360,7 @@ class VolumeApi(RemoveableBulkModuleApi):
1360
1360
  ensure_base_path(path)
1361
1361
  hash_to_check = None
1362
1362
  if semaphore is None:
1363
- semaphore = self._api._get_default_semaphore()
1363
+ semaphore = self._api.get_default_semaphore()
1364
1364
  async with semaphore:
1365
1365
  async with aiofiles.open(path, writing_method) as fd:
1366
1366
  async for chunk, hhash in self._download_async(
@@ -1440,7 +1440,7 @@ class VolumeApi(RemoveableBulkModuleApi):
1440
1440
  if len(ids) != len(paths):
1441
1441
  raise ValueError(f'Can not match "ids" and "paths" lists, {len(ids)} != {len(paths)}')
1442
1442
  if semaphore is None:
1443
- semaphore = self._api._get_default_semaphore()
1443
+ semaphore = self._api.get_default_semaphore()
1444
1444
  tasks = []
1445
1445
  for img_id, img_path in zip(ids, paths):
1446
1446
  task = self.download_path_async(
@@ -762,7 +762,7 @@ def _init(
762
762
  await StateJson.from_request(request)
763
763
 
764
764
  if not ("application/json" not in request.headers.get("Content-Type", "")):
765
- # {'command': 'inference_batch_ids', 'context': {}, 'state': {'dataset_id': 49711, 'batch_ids': [3120204], 'settings': None}, 'user_api_key': 'XXX', 'api_token': 'XXX', 'instance_type': None, 'server_address': 'https://dev.supervise.ly'}
765
+ # {'command': 'inference_batch_ids', 'context': {}, 'state': {'dataset_id': 49711, 'batch_ids': [3120204], 'settings': None}, 'user_api_key': 'XXX', 'api_token': 'XXX', 'instance_type': None, 'server_address': 'https://app.supervisely.com'}
766
766
  content = await request.json()
767
767
 
768
768
  request.state.context = content.get("context")
@@ -14,4 +14,4 @@
14
14
  # }
15
15
 
16
16
  # context_root: Download as, Run App (default), Report
17
- # [![Views](https://dev.supervise.ly/public/api/v3/ecosystem.counters?repo=supervisely-ecosystem/roads-test&counter=views&label=custom)](https://supervise.ly)
17
+ # [![Views](https://app.supervisely.com/public/api/v3/ecosystem.counters?repo=supervisely-ecosystem/roads-test&counter=views&label=custom)](https://supervisely.com)
@@ -1386,3 +1386,17 @@ def get_labeling_tool_link(url: str, name: Optional[str] = "open in labeling too
1386
1386
  :rtype: str
1387
1387
  """
1388
1388
  return f'<a href="{url}" rel="noopener noreferrer" target="_blank">{name}<i class="zmdi zmdi-open-in-new" style="margin-left: 5px"></i></a>'
1389
+
1390
+
1391
+ def get_size_from_bytes(data: bytes) -> Tuple[int, int]:
1392
+ """
1393
+ Get size of image from bytes.
1394
+
1395
+ :param data: Bytes of image.
1396
+ :type data: bytes
1397
+ :return: Height and width of image
1398
+ :rtype: :class:`Tuple[int, int]`
1399
+ """
1400
+ image = PILImage.open(io.BytesIO(data))
1401
+ width, height = image.size
1402
+ return width, height
supervisely/io/env.py CHANGED
@@ -539,3 +539,18 @@ def mininum_instance_version_for_sdk() -> str:
539
539
  postprocess_fn=lambda x: x,
540
540
  raise_not_found=False,
541
541
  )
542
+
543
+
544
+ def semaphore_size() -> int:
545
+ """Returns semaphore size from environment variable using following
546
+ - SUPERVISELY_ASYNC_SEMAPHORE
547
+
548
+ :return: semaphore size
549
+ :rtype: int
550
+ """
551
+ return _parse_from_env(
552
+ name="semaphore_size",
553
+ keys=["SUPERVISELY_ASYNC_SEMAPHORE"],
554
+ postprocess_fn=lambda x: int(x),
555
+ raise_not_found=False,
556
+ )
@@ -233,7 +233,7 @@ def get_labeling_tool_url(dataset_id: int, pointcloud_id: int):
233
233
 
234
234
  print(url)
235
235
  # Output:
236
- # https://dev.supervise.ly/app/point-clouds/?datasetId=55875&pointCloudId=19373403
236
+ # https://app.supervisely.com/app/point-clouds/?datasetId=55875&pointCloudId=19373403
237
237
  """
238
238
 
239
239
  res = f"/app/point-clouds/?datasetId={dataset_id}&pointCloudId={pointcloud_id}"
@@ -280,7 +280,7 @@ def get_labeling_tool_link(url, name="open in labeling tool"):
280
280
  print(link)
281
281
  # Output:
282
282
  # <a
283
- # href="https://dev.supervise.ly/app/point-clouds/?datasetId=55875&pointCloudId=19373403"
283
+ # href="https://app.supervisely.com/app/point-clouds/?datasetId=55875&pointCloudId=19373403"
284
284
  # rel="noopener noreferrer"
285
285
  # target="_blank"
286
286
  # >
@@ -37,7 +37,7 @@ def get_labeling_tool_url(dataset_id, pointcloud_id):
37
37
 
38
38
  print(url)
39
39
  # Output:
40
- # https://dev.supervise.ly/app/point-clouds-tracking/?datasetId=55875&pointCloudId=19373403
40
+ # https://app.supervisely.com/app/point-clouds-tracking/?datasetId=55875&pointCloudId=19373403
41
41
  """
42
42
 
43
43
  res = f"/app/point-clouds-tracking/?datasetId={dataset_id}&pointCloudId={pointcloud_id}"
@@ -72,7 +72,7 @@ def get_labeling_tool_link(url, name="open in labeling tool"):
72
72
  api = sly.Api.from_env()
73
73
 
74
74
  # Pass values into the API constructor (optional, not recommended)
75
- # api = sly.Api(server_address="https://app.supervise.ly", token="4r47N...xaTatb")
75
+ # api = sly.Api(server_address="https://app.supervisely.com", token="4r47N...xaTatb")
76
76
 
77
77
  pointcloud_id = 19373403
78
78
  pcd_info = api.pointcloud.get_info_by_id(pointcloud_id)
@@ -84,7 +84,7 @@ def get_labeling_tool_link(url, name="open in labeling tool"):
84
84
  print(link)
85
85
  # Output:
86
86
  # <a
87
- # href="https://dev.supervise.ly/app/point-clouds/?datasetId=55875&pointCloudId=19373403"
87
+ # href="https://app.supervisely.com/app/point-clouds/?datasetId=55875&pointCloudId=19373403"
88
88
  # rel="noopener noreferrer"
89
89
  # target="_blank"
90
90
  # >
@@ -4387,7 +4387,7 @@ async def _download_project_async(
4387
4387
  resume_download: Optional[bool] = False,
4388
4388
  ):
4389
4389
  if semaphore is None:
4390
- semaphore = api._get_default_semaphore()
4390
+ semaphore = api.get_default_semaphore()
4391
4391
 
4392
4392
  dataset_ids = set(dataset_ids) if (dataset_ids is not None) else None
4393
4393
  project_fs = None
@@ -4418,7 +4418,12 @@ async def _download_project_async(
4418
4418
  else:
4419
4419
  dataset_fs = project_fs.create_dataset(dataset.name, dataset_path)
4420
4420
 
4421
- all_images = api.image.get_list(dataset_id, force_metadata_for_links=False)
4421
+ force_metadata_for_links = False
4422
+ if save_images is False and only_image_tags is True:
4423
+ force_metadata_for_links = True
4424
+ all_images = api.image.get_list(
4425
+ dataset_id, force_metadata_for_links=force_metadata_for_links
4426
+ )
4422
4427
  images = [image for image in all_images if images_ids is None or image.id in images_ids]
4423
4428
 
4424
4429
  ds_progress = progress_cb
@@ -4499,6 +4504,9 @@ async def _download_project_item_async(
4499
4504
  img_bytes = await api.image.download_bytes_single_async(
4500
4505
  img_info.id, semaphore=semaphore, check_hash=True
4501
4506
  )
4507
+ if None in [img_info.height, img_info.width]:
4508
+ width, height = sly.image.get_size_from_bytes(img_bytes)
4509
+ img_info = img_info._replace(height=height, width=width)
4502
4510
  else:
4503
4511
  img_bytes = None
4504
4512
 
@@ -4506,9 +4514,13 @@ async def _download_project_item_async(
4506
4514
  ann_info = await api.annotation.download_async(
4507
4515
  img_info.id,
4508
4516
  semaphore=semaphore,
4509
- force_metadata_for_links=False,
4517
+ force_metadata_for_links=not save_images,
4510
4518
  )
4511
4519
  ann_json = ann_info.annotation
4520
+ tmp_ann = Annotation.from_json(ann_json, meta)
4521
+ if None in tmp_ann.img_size:
4522
+ tmp_ann = tmp_ann.clone(img_size=(img_info.height, img_info.width))
4523
+ ann_json = tmp_ann.to_json()
4512
4524
  else:
4513
4525
  tags = TagCollection.from_api_response(
4514
4526
  img_info.tags,
@@ -1594,7 +1594,7 @@ async def download_video_project_async(
1594
1594
  )
1595
1595
  """
1596
1596
  if semaphore is None:
1597
- semaphore = api._get_default_semaphore()
1597
+ semaphore = api.get_default_semaphore()
1598
1598
 
1599
1599
  key_id_map = KeyIdMap()
1600
1600
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: supervisely
3
- Version: 6.73.228
3
+ Version: 6.73.230
4
4
  Summary: Supervisely Python SDK.
5
5
  Home-page: https://github.com/supervisely/supervisely
6
6
  Author: Supervisely
@@ -21,14 +21,14 @@ supervisely/annotation/tag_meta_mapper.py,sha256=RWeTrxJ64syodyhXIRSH007bX6Hr3B4
21
21
  supervisely/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  supervisely/api/advanced_api.py,sha256=Nd5cCnHFWc3PSUrCtENxTGtDjS37_lCHXsgXvUI3Ti8,2054
23
23
  supervisely/api/agent_api.py,sha256=ShWAIlXcWXcyI9fqVuP5GZVCigCMJmjnvdGUfLspD6Y,8890
24
- supervisely/api/annotation_api.py,sha256=kgbxlAmvwLX7nMFnQ23hZDZryD3tVSehfqRkLEGXQXA,58828
25
- supervisely/api/api.py,sha256=BdN99Znu_nLjnt--i6xoN9W4v0Am3kYlkqZZeIy4UuE,60633
26
- supervisely/api/app_api.py,sha256=hjoL24Nc1POlIqz5bkpMBij5D-cwCHvkznkaGpODyzA,67086
24
+ supervisely/api/annotation_api.py,sha256=s9kd1G759R8YSvbDcNXrPa9xv95j1cWE1RgD6XeJe2A,58826
25
+ supervisely/api/api.py,sha256=kDx9uE8fiRDnyJVuw4hG0YTuCglhzHQgnTa2-a4YEEM,62424
26
+ supervisely/api/app_api.py,sha256=-T4sISQ7POyR2yirf1kEWj4JaJFpJxCyRWqbf_99Jak,67036
27
27
  supervisely/api/dataset_api.py,sha256=2-SQBlgEnIN-0uvDbtPlSXr6ztBeZ3WPryhkOtpBmk4,40786
28
- supervisely/api/file_api.py,sha256=RM3clcdcfj0MtSqGdu6afCqUieYj_2q5gcEch_36tCE,82421
28
+ supervisely/api/file_api.py,sha256=WMg80fxqMKOo3ai-IGON2w-IDAySPk90USoVk29JOdE,82415
29
29
  supervisely/api/github_api.py,sha256=NIexNjEer9H5rf5sw2LEZd7C1WR-tK4t6IZzsgeAAwQ,623
30
30
  supervisely/api/image_annotation_tool_api.py,sha256=YcUo78jRDBJYvIjrd-Y6FJAasLta54nnxhyaGyanovA,5237
31
- supervisely/api/image_api.py,sha256=BMhlJZwfbxFx8eHBQaKNmGI9a7UbOpJrIEmC6Eci-Ck,162395
31
+ supervisely/api/image_api.py,sha256=X26mRA40-DLU-AGD3iTe5x9VtNgQRbTvFDXrkfwDwe8,162626
32
32
  supervisely/api/import_storage_api.py,sha256=BDCgmR0Hv6OoiRHLCVPKt3iDxSVlQp1WrnKhAK_Zl84,460
33
33
  supervisely/api/issues_api.py,sha256=BqDJXmNoTzwc3xe6_-mA7FDFC5QQ-ahGbXk_HmpkSeQ,17925
34
34
  supervisely/api/labeling_job_api.py,sha256=odnzZjp29yM16Gq-FYkv-OA4WFMNJCLFo4qSikW2A7c,56280
@@ -51,10 +51,10 @@ supervisely/api/entity_annotation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeR
51
51
  supervisely/api/entity_annotation/entity_annotation_api.py,sha256=K79KdDyepQv4FiNQHBj9V4-zLIemxK9WG1ig1bfBKb8,3083
52
52
  supervisely/api/entity_annotation/figure_api.py,sha256=WgeB6h8ZQsgeORXnEAq2LCCezLIMeVibetFTC1PxQM8,20896
53
53
  supervisely/api/entity_annotation/object_api.py,sha256=gbcNvN_KY6G80Me8fHKQgryc2Co7VU_kfFd1GYILZ4E,8875
54
- supervisely/api/entity_annotation/tag_api.py,sha256=jA6q5XuvJ6qAalM9ktGbscbNM07xw4Qo3odkkstvNKY,10882
54
+ supervisely/api/entity_annotation/tag_api.py,sha256=3PQEpLZaIL_3Ds2QWfyjHZctXA1KqvVVRYbVLw7npHU,10881
55
55
  supervisely/api/pointcloud/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
56
  supervisely/api/pointcloud/pointcloud_annotation_api.py,sha256=_QABI38FCKBc4_VQ0B7jLOKMoRN9FFSt-w-zlEHd44s,7658
57
- supervisely/api/pointcloud/pointcloud_api.py,sha256=EFOrUG0IO_xuqznoWrIRGcsE0ysGjJAz0RYuLJStbNY,53279
57
+ supervisely/api/pointcloud/pointcloud_api.py,sha256=pn72znCr5hkAfgniXxfD6Vi8-HqRb1Nrf6l23-HQ7Bc,53277
58
58
  supervisely/api/pointcloud/pointcloud_episode_annotation_api.py,sha256=YGpU7g05XNV9o5daH5mFcUMmPPfgd085yIMNzXOVJqc,7009
59
59
  supervisely/api/pointcloud/pointcloud_episode_api.py,sha256=K_oPJeibj5oRYooeEWuSe6VxlxCYK3D8yLunm7vDeM0,7919
60
60
  supervisely/api/pointcloud/pointcloud_episode_object_api.py,sha256=k2_wV0EVPo9vxSTVe1qOvqVOMSVE6zGDSkfR6TRNsKs,691
@@ -63,15 +63,15 @@ supervisely/api/pointcloud/pointcloud_figure_api.py,sha256=r1sk3g9IgYVHuNhxyZT1T
63
63
  supervisely/api/pointcloud/pointcloud_object_api.py,sha256=bO1USWb9HAywG_CW4CDu1HLu6l58OqQFuD3ikS9F3bM,5130
64
64
  supervisely/api/pointcloud/pointcloud_tag_api.py,sha256=iShtr052nOElxsyMyZEUT2vypEm6kP00gnP13ABX24A,4691
65
65
  supervisely/api/video/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
- supervisely/api/video/video_annotation_api.py,sha256=epOngGQRzaGHWG9kGxSpNwpoUM-LuFs3Y6zFwinuySI,10978
67
- supervisely/api/video/video_api.py,sha256=XbygE2XHOezjDXU5qYh4CM3r1uFpHy1vULmVTCyTlbE,92978
66
+ supervisely/api/video/video_annotation_api.py,sha256=Um_7UOJtP_E25X6v41mrZfDbJaJuLMGoZm2IULwyg3w,10977
67
+ supervisely/api/video/video_api.py,sha256=dAAftwLAnvLpyu3NopD2Cfk3vyhBiuCifSF3pEM_PVY,93152
68
68
  supervisely/api/video/video_figure_api.py,sha256=quksohjhgrK2l2-PtbbNE99fOW6uWXX59-_4xfc-I-k,6244
69
69
  supervisely/api/video/video_frame_api.py,sha256=4GwSI4xdCNYEUvTqzKc-Ewd44fw5zqkFoD24jrrN_aY,10214
70
70
  supervisely/api/video/video_object_api.py,sha256=IC0NP8EoIT_d3xxDRgz2cA3ixSiuJ5ymy64eS-RfmDM,2227
71
71
  supervisely/api/video/video_tag_api.py,sha256=oJgdJt_0w-5UfXaxZ7jdxK0PetZjax1vOfjm0IMYwe8,12266
72
72
  supervisely/api/volume/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
73
  supervisely/api/volume/volume_annotation_api.py,sha256=6s7p9nlNYHOMbhfFmVBGJizEKkA-yKEAiuHJZcAqEzM,18190
74
- supervisely/api/volume/volume_api.py,sha256=_HKlu3YBNk5aA3d8wMtVcMdhIBrRkhRl17FcbKJDYsk,55381
74
+ supervisely/api/volume/volume_api.py,sha256=-n3r5qj4I4EtoERKTHFT8PpsKFJ141SvQfamIcHqWK4,55387
75
75
  supervisely/api/volume/volume_figure_api.py,sha256=WwmcMw7o3Nvyv52tzmz64yF-WJI0qzAU-zL2JlD7_w0,26039
76
76
  supervisely/api/volume/volume_object_api.py,sha256=F7pLV2MTlBlyN6fEKdxBSUatIMGWSuu8bWj3Hvcageo,2139
77
77
  supervisely/api/volume/volume_tag_api.py,sha256=yNGgXz44QBSW2VGlNDOVLqLXnH8Q2fFrxDFb_girYXA,3639
@@ -93,11 +93,11 @@ supervisely/app/fastapi/index.html,sha256=4kF8PWYvssCX2iH0jOOq0dCcKxQfndpJbTzUF4
93
93
  supervisely/app/fastapi/no_html_main.html,sha256=NhQP7noyORBx72lFh1CQKgBRupkWjiq6Gaw-9Hkvg7c,37
94
94
  supervisely/app/fastapi/offline.py,sha256=CwMMkJ1frD6wiZS-SEoNDtQ1UJcJe1Ob6ohE3r4CQL8,7414
95
95
  supervisely/app/fastapi/request.py,sha256=NU7rKmxJ1pfkDZ7_yHckRcRAueJRQIqCor11UO2OHr8,766
96
- supervisely/app/fastapi/subapp.py,sha256=kvycQ2NSsitbdWxaSzGPjzNzvplONqi9UbNnfeAWryw,43411
96
+ supervisely/app/fastapi/subapp.py,sha256=PaVYX1VpmXsXMEgdCOhFXj4s8CwyeU25c4GXcZuMzL8,43414
97
97
  supervisely/app/fastapi/templating.py,sha256=3JO4WmQKfPMmb8xhSuV5knWCen3gTgfdqWpIx4RSJlg,2330
98
98
  supervisely/app/fastapi/utils.py,sha256=GZuTWLcVRGVx8TL3jVEYUOZIT2FawbwIe2kAOBLw9ho,398
99
99
  supervisely/app/fastapi/websocket.py,sha256=TlRSPOAhRItTv1HGvdukK1ZvhRjMUxRa-lJlsRR9rJw,1308
100
- supervisely/app/v1/__init__.py,sha256=iWJ_hlzURXkeC6eUy07qLESeY5JcpmHuH9wUafLow9o,842
100
+ supervisely/app/v1/__init__.py,sha256=OdU0PYv6hLwahYoyaLFO8m3cbJSchvPbqxuG1N3T734,848
101
101
  supervisely/app/v1/app_config.md,sha256=-8GKbiQoX25RhEj3EDJ7TxiYuFw5wL2TO3qV5AJLZTs,2536
102
102
  supervisely/app/v1/app_service.py,sha256=KGWns_M3OkQLdtsGpH3rBlA2hmSeqGkA-M5q5sTqxe4,23090
103
103
  supervisely/app/v1/constants.py,sha256=_BG2dsOSz-gAVKN9CN8--a4Tn1-osu1z9Cwy8ywIzH0,183
@@ -679,10 +679,10 @@ supervisely/imaging/_video.py,sha256=JgpHGbDTAqm_y67SDULk8tA7dN4Wq1j5gq7Koi7hw5Q
679
679
  supervisely/imaging/color.py,sha256=4SW3oIb5gnAQUEdJ-AgefatfXlYKHBG9Vy5hxA9eBEI,6991
680
680
  supervisely/imaging/colors.json.gz,sha256=KORWj3sbMFVHv11E4n94cVmbFdEnFO0EzX8k-ENrZLk,555428
681
681
  supervisely/imaging/font.py,sha256=0XcmWhlw7y2PAhrWgcsfInyRWj0WnlFpMSEXXilR8UA,2697
682
- supervisely/imaging/image.py,sha256=RxyQ1R5s-U5GlCJ648F9nNLV1Pbs4slfONflaJjx1gw,41532
682
+ supervisely/imaging/image.py,sha256=1KNc4qRbP9OlI4Yta07Kc2ohAgSBJ_9alF9Jag74w30,41873
683
683
  supervisely/io/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
684
684
  supervisely/io/docker_utils.py,sha256=hb_HXGM8IYB0PF-nD7NxMwaHgzaxIFxofsUzQ_RCUZI,7935
685
- supervisely/io/env.py,sha256=8HGnJz7ikkgjPhz77J3UyNU5_umvJlLhxVOKGCgvdas,16907
685
+ supervisely/io/env.py,sha256=rKLLw1XQqM3s3X3k3ke9Skyy5hPK0LE_xVUBq3Qko0Q,17284
686
686
  supervisely/io/exception_handlers.py,sha256=wvSP3Sp8HpAPSqri8rNAcitKO3I9dBfBp_somnmCA8A,36465
687
687
  supervisely/io/fs.py,sha256=2ZpAdt8zua423qSrmuXI71b52pGbZatgCeXqs48dufs,51322
688
688
  supervisely/io/fs_cache.py,sha256=985gvBGzveLcDudgz10E4EWVjP9jxdU1Pa0GFfCBoCA,6520
@@ -912,7 +912,7 @@ supervisely/nn/tracker/utils/gmc.py,sha256=3JX8979H3NA-YHNaRQyj9Z-xb9qtyMittPEjG
912
912
  supervisely/nn/tracker/utils/kalman_filter.py,sha256=XquwLRFVfZdJMHPqPUtq-kdtuKLY6zgGHbnPGTXL8qU,17044
913
913
  supervisely/output/__init__.py,sha256=OY-ZkdTkpg3qMkZa763Uk7UrRF1Q-p55qIBPo-tNPho,4585
914
914
  supervisely/pointcloud/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
915
- supervisely/pointcloud/pointcloud.py,sha256=rID4gWBgxSICX_VKyHzfOicmsgX1pozh_3jzdyKaarg,11030
915
+ supervisely/pointcloud/pointcloud.py,sha256=wWWnueObO7li5PckhRim7WxHytsm2zn1caK3zghQcfg,11036
916
916
  supervisely/pointcloud_annotation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
917
917
  supervisely/pointcloud_annotation/constants.py,sha256=5I_3V4WwAOdxPM9QOyVHv_o561-gjV5d_s5IM1RxWrM,360
918
918
  supervisely/pointcloud_annotation/pointcloud_annotation.py,sha256=XitdjdjOYujSZy0pHB14djViZcloyN6I0A2ZQ0M_bTw,15881
@@ -929,19 +929,19 @@ supervisely/pointcloud_annotation/pointcloud_object_collection.py,sha256=2Q41LTe
929
929
  supervisely/pointcloud_annotation/pointcloud_tag.py,sha256=2HFHZh953pbG5bIHTlT_qMokZn2Ao7xWYZUFt55BMps,14172
930
930
  supervisely/pointcloud_annotation/pointcloud_tag_collection.py,sha256=j_TAN23GkTcSNk5Yfwe2mrnigLlarMtJ3b4Jhu4GaEo,10825
931
931
  supervisely/pointcloud_episodes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
932
- supervisely/pointcloud_episodes/pointcloud_episodes.py,sha256=NqUkVdHBSIplB2wvzL6a8z8EuGNpAJuOn1j5UrmSrQw,3421
932
+ supervisely/pointcloud_episodes/pointcloud_episodes.py,sha256=cRXdtw7bMsbsdVQjxfWxFSESrO-LGiqqsZyyExl2Mbg,3430
933
933
  supervisely/project/__init__.py,sha256=hlzdj9Pgy53Q3qdP8LMtGTChvZHQuuShdtui2eRUQeE,2601
934
934
  supervisely/project/data_version.py,sha256=nknaWJSUCwoDyNG9_d1KA-GjzidhV9zd9Cn8cg15DOU,19270
935
935
  supervisely/project/download.py,sha256=qonvHBiKX-leHW9qWJdyBqFNmpI2_t9s54e68h9orq0,23687
936
936
  supervisely/project/pointcloud_episode_project.py,sha256=fcaFAaHVn_VvdiIfHl4IyEFE5-Q3VFGfo7_YoxEma0I,41341
937
937
  supervisely/project/pointcloud_project.py,sha256=Y8Xhi6Hg-KyztwFncezuDfKTt2FILss96EU_LdXzmrA,49172
938
- supervisely/project/project.py,sha256=8ghaq9OCFRdhTNuKo_morBgVxgFOS1KKpmU8Kyl1vdo,180328
938
+ supervisely/project/project.py,sha256=T2ge_9HXlaDyDziEhr-5lcyUcHskaUIbgwtrWs7PqYo,180929
939
939
  supervisely/project/project_meta.py,sha256=26s8IiHC5Pg8B1AQi6_CrsWteioJP2in00cRNe8QlW0,51423
940
940
  supervisely/project/project_settings.py,sha256=NLThzU_DCynOK6hkHhVdFyezwprn9UqlnrLDe_3qhkY,9347
941
941
  supervisely/project/project_type.py,sha256=_3RqW2CnDBKFOvSIrQT1RJQaiHirs34_jiQS8CkwCpo,530
942
942
  supervisely/project/readme_template.md,sha256=rGmSLRVUSGjvorjpzl0sZ7YA4sKfDexl95NFtMISj3I,9128
943
943
  supervisely/project/upload.py,sha256=AjgHYgVZwUE25ygC5pqvFjdAladbyB8T78mlet5Qpho,3750
944
- supervisely/project/video_project.py,sha256=AoZDIF3TAPke3WVZAOSWnuyIs12sFZsY5CxARSNQ5N8,63740
944
+ supervisely/project/video_project.py,sha256=8fJeicVWNMbek24PmNRBtbnFhvXsnxPg5dpNrL5VNW4,63739
945
945
  supervisely/project/volume_project.py,sha256=LL4IxQyx0DU4acj2imz6diWO3kHHaWnf7QiycTJUTMU,22367
946
946
  supervisely/pyscripts_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
947
947
  supervisely/pyscripts_utils/utils.py,sha256=scEwHJvHRQa8NHIOn2eTwH6-Zc8CGdLoxM-WzH9jcRo,314
@@ -997,9 +997,9 @@ supervisely/worker_proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
997
997
  supervisely/worker_proto/worker_api_pb2.py,sha256=VQfi5JRBHs2pFCK1snec3JECgGnua3Xjqw_-b3aFxuM,59142
998
998
  supervisely/worker_proto/worker_api_pb2_grpc.py,sha256=3BwQXOaP9qpdi0Dt9EKG--Lm8KGN0C5AgmUfRv77_Jk,28940
999
999
  supervisely_lib/__init__.py,sha256=7-3QnN8Zf0wj8NCr2oJmqoQWMKKPKTECvjH9pd2S5vY,159
1000
- supervisely-6.73.228.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1001
- supervisely-6.73.228.dist-info/METADATA,sha256=gEzztrS-yBBzf4a8JM9h_HWYtonbH_CrRzFgNqGr1Fs,33150
1002
- supervisely-6.73.228.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
1003
- supervisely-6.73.228.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
1004
- supervisely-6.73.228.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
1005
- supervisely-6.73.228.dist-info/RECORD,,
1000
+ supervisely-6.73.230.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1001
+ supervisely-6.73.230.dist-info/METADATA,sha256=DCXjusChZ2ySuzqPJXs1I9_aZeYNapIQb_LLwx9a8kw,33150
1002
+ supervisely-6.73.230.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
1003
+ supervisely-6.73.230.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
1004
+ supervisely-6.73.230.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
1005
+ supervisely-6.73.230.dist-info/RECORD,,