supervisely 6.73.231__py3-none-any.whl → 6.73.233__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.

Potentially problematic release.


This version of supervisely might be problematic. Click here for more details.

supervisely/api/api.py CHANGED
@@ -67,6 +67,7 @@ from supervisely._utils import camel_to_snake, is_community, is_development
67
67
  from supervisely.api.module_api import ApiField
68
68
  from supervisely.io.network_exceptions import (
69
69
  process_requests_exception,
70
+ process_requests_exception_async,
70
71
  process_unhandled_request,
71
72
  )
72
73
  from supervisely.project.project_meta import ProjectMeta
@@ -806,10 +807,13 @@ class Api:
806
807
  reason = "Can't get reason"
807
808
 
808
809
  def decode_response_content(response: httpx.Response):
809
- if hasattr(response, "is_stream_consumed"):
810
- return "Content is not acessible for streaming responses"
811
- else:
810
+ try:
812
811
  return response.content.decode("utf-8")
812
+ except Exception as e:
813
+ if hasattr(response, "is_stream_consumed"):
814
+ return f"Stream is consumed. {e}"
815
+ else:
816
+ return f"Can't decode response content: {e}"
813
817
 
814
818
  if 400 <= response.status_code < 500:
815
819
  http_error_msg = "%s Client Error: %s for url: %s (%s)" % (
@@ -1058,7 +1062,15 @@ class Api:
1058
1062
  self._check_version()
1059
1063
  Api._raise_for_status_httpx(response)
1060
1064
  return response
1061
- except httpx.RequestError as exc:
1065
+ except (httpx.RequestError, httpx.HTTPStatusError) as exc:
1066
+ if (
1067
+ isinstance(exc, httpx.HTTPStatusError)
1068
+ and response.status_code == 400
1069
+ and self.token is None
1070
+ ):
1071
+ self.logger.warning(
1072
+ "API_TOKEN env variable is undefined. See more: https://developer.supervisely.com/getting-started/basics-of-authentication"
1073
+ )
1062
1074
  if raise_error:
1063
1075
  raise exc
1064
1076
  else:
@@ -1123,7 +1135,15 @@ class Api:
1123
1135
  if response.status_code != httpx.codes.OK:
1124
1136
  Api._raise_for_status_httpx(response)
1125
1137
  return response
1126
- except httpx.RequestError as exc:
1138
+ except (httpx.RequestError, httpx.HTTPStatusError) as exc:
1139
+ if (
1140
+ isinstance(exc, httpx.HTTPStatusError)
1141
+ and response.status_code == 400
1142
+ and self.token is None
1143
+ ):
1144
+ self.logger.warning(
1145
+ "API_TOKEN env variable is undefined. See more: https://developer.supervisely.com/getting-started/basics-of-authentication"
1146
+ )
1127
1147
  process_requests_exception(
1128
1148
  self.logger,
1129
1149
  exc,
@@ -1260,7 +1280,15 @@ class Api:
1260
1280
  )
1261
1281
  logger.trace(f"Streamed size: {total_streamed}, expected size: {expected_size}")
1262
1282
  return
1263
- except httpx.RequestError as e:
1283
+ except (httpx.RequestError, httpx.HTTPStatusError) as e:
1284
+ if (
1285
+ isinstance(e, httpx.HTTPStatusError)
1286
+ and resp.status_code == 400
1287
+ and self.token is None
1288
+ ):
1289
+ self.logger.warning(
1290
+ "API_TOKEN env variable is undefined. See more: https://developer.supervisely.com/getting-started/basics-of-authentication"
1291
+ )
1264
1292
  retry_range_start = total_streamed + (range_start or 0)
1265
1293
  if total_streamed != 0:
1266
1294
  retry_range_start += 1
@@ -1348,11 +1376,19 @@ class Api:
1348
1376
  self._check_version()
1349
1377
  Api._raise_for_status_httpx(response)
1350
1378
  return response
1351
- except httpx.RequestError as exc:
1379
+ except (httpx.RequestError, httpx.HTTPStatusError) as exc:
1380
+ if (
1381
+ isinstance(exc, httpx.HTTPStatusError)
1382
+ and response.status_code == 400
1383
+ and self.token is None
1384
+ ):
1385
+ self.logger.warning(
1386
+ "API_TOKEN env variable is undefined. See more: https://developer.supervisely.com/getting-started/basics-of-authentication"
1387
+ )
1352
1388
  if raise_error:
1353
1389
  raise exc
1354
1390
  else:
1355
- process_requests_exception(
1391
+ await process_requests_exception_async(
1356
1392
  self.logger,
1357
1393
  exc,
1358
1394
  method,
@@ -1489,13 +1525,21 @@ class Api:
1489
1525
  )
1490
1526
  logger.trace(f"Streamed size: {total_streamed}, expected size: {expected_size}")
1491
1527
  return
1492
- except httpx.RequestError as e:
1528
+ except (httpx.RequestError, httpx.HTTPStatusError) as e:
1529
+ if (
1530
+ isinstance(e, httpx.HTTPStatusError)
1531
+ and resp.status_code == 400
1532
+ and self.token is None
1533
+ ):
1534
+ self.logger.warning(
1535
+ "API_TOKEN env variable is undefined. See more: https://developer.supervisely.com/getting-started/basics-of-authentication"
1536
+ )
1493
1537
  retry_range_start = total_streamed + (range_start or 0)
1494
1538
  if total_streamed != 0:
1495
1539
  retry_range_start += 1
1496
1540
  headers["Range"] = f"bytes={retry_range_start}-{range_end or ''}"
1497
1541
  logger.debug(f"Setting Range header {headers['Range']} for retry")
1498
- process_requests_exception(
1542
+ await process_requests_exception_async(
1499
1543
  self.logger,
1500
1544
  e,
1501
1545
  method,
@@ -1372,6 +1372,19 @@ class VideoApi(RemoveableBulkModuleApi):
1372
1372
  },
1373
1373
  )
1374
1374
 
1375
+ def notify_tracking_warning(self, track_id: int, video_id: int, message: str):
1376
+ self._api.post(
1377
+ "videos.notify-annotation-tool",
1378
+ data={
1379
+ "type": "videos:tracking-warning",
1380
+ "data": {
1381
+ ApiField.VIDEO_ID: str(video_id),
1382
+ ApiField.TRACK_ID: str(track_id),
1383
+ ApiField.MESSAGE: message,
1384
+ },
1385
+ },
1386
+ )
1387
+
1375
1388
  # def upload(self):
1376
1389
  # #"/videos.bulk.upload"
1377
1390
  # pass
@@ -2055,7 +2068,7 @@ class VideoApi(RemoveableBulkModuleApi):
2055
2068
  hashes=[h],
2056
2069
  metas=[meta],
2057
2070
  skip_download=skip_download,
2058
- force_metadata_for_links=force_metadata_for_links
2071
+ force_metadata_for_links=force_metadata_for_links,
2059
2072
  )
2060
2073
  if len(links) != 1:
2061
2074
  raise RuntimeError(
@@ -1,5 +1,6 @@
1
1
  # coding: utf-8
2
2
 
3
+ import asyncio
3
4
  import time
4
5
  import traceback
5
6
 
@@ -27,6 +28,92 @@ RETRY_STATUS_CODES = {
27
28
  }
28
29
 
29
30
 
31
+ async def process_requests_exception_async(
32
+ external_logger,
33
+ exc,
34
+ api_method_name,
35
+ url,
36
+ verbose=True,
37
+ swallow_exc=False,
38
+ sleep_sec=None,
39
+ response=None,
40
+ retry_info=None,
41
+ ):
42
+ recommended_sleep = None
43
+ try:
44
+ if hasattr(exc, "response") and exc.response.status_code == 429:
45
+ recommended_sleep = exc.response.headers.get("Retry-After")
46
+ elif response is not None and response.status_code == 429:
47
+ recommended_sleep = response.headers.get("Retry-After")
48
+ if recommended_sleep and int(recommended_sleep) > sleep_sec:
49
+ sleep_sec = int(recommended_sleep)
50
+ except Exception:
51
+ pass
52
+
53
+ is_connection_error = isinstance(
54
+ exc,
55
+ (
56
+ requests.exceptions.ConnectionError,
57
+ requests.exceptions.Timeout,
58
+ requests.exceptions.TooManyRedirects,
59
+ requests.exceptions.ChunkedEncodingError,
60
+ httpx.NetworkError,
61
+ httpx.TimeoutException,
62
+ httpx.TooManyRedirects,
63
+ httpx.ProtocolError,
64
+ ),
65
+ )
66
+
67
+ is_server_retryable_error = (
68
+ isinstance(exc, (requests.exceptions.HTTPError, httpx.HTTPStatusError))
69
+ and hasattr(exc, "response")
70
+ and (exc.response.status_code in RETRY_STATUS_CODES)
71
+ )
72
+
73
+ is_need_ping_error = False
74
+ if (
75
+ isinstance(exc, (requests.exceptions.HTTPError, httpx.HTTPStatusError))
76
+ and hasattr(exc, "response")
77
+ and (exc.response.status_code == 400)
78
+ ):
79
+ try:
80
+ server_explanation = exc.response.json()
81
+ is_need_ping_error = server_explanation.get("error", None) == SPECIAL_RECONNECT_ERROR
82
+ except (AttributeError, ValueError):
83
+ pass
84
+
85
+ if is_connection_error or is_server_retryable_error:
86
+ await process_retryable_request_async(
87
+ external_logger,
88
+ exc,
89
+ api_method_name,
90
+ url,
91
+ CONNECTION_ERROR,
92
+ verbose=verbose,
93
+ swallow_exc=swallow_exc,
94
+ sleep_sec=sleep_sec,
95
+ retry_info=retry_info,
96
+ )
97
+ elif is_need_ping_error:
98
+ await process_retryable_request_async(
99
+ external_logger,
100
+ exc,
101
+ api_method_name,
102
+ url,
103
+ AGENT_CONNECTION_ERROR,
104
+ verbose=verbose,
105
+ swallow_exc=swallow_exc,
106
+ sleep_sec=sleep_sec,
107
+ retry_info=retry_info,
108
+ )
109
+ elif response is None:
110
+ process_unhandled_request(external_logger, exc)
111
+ elif isinstance(exc, (requests.exceptions.HTTPError, httpx.HTTPStatusError)):
112
+ process_invalid_request(external_logger, exc, response, verbose)
113
+ else:
114
+ process_unhandled_request(external_logger, exc)
115
+
116
+
30
117
  def process_requests_exception(
31
118
  external_logger,
32
119
  exc,
@@ -38,6 +125,17 @@ def process_requests_exception(
38
125
  response=None,
39
126
  retry_info=None,
40
127
  ):
128
+ recommended_sleep = None
129
+ try:
130
+ if hasattr(exc, "response") and exc.response.status_code == 429:
131
+ recommended_sleep = exc.response.headers.get("Retry-After")
132
+ elif response is not None and response.status_code == 429:
133
+ recommended_sleep = response.headers.get("Retry-After")
134
+ if recommended_sleep and int(recommended_sleep) > sleep_sec:
135
+ sleep_sec = int(recommended_sleep)
136
+ except Exception:
137
+ pass
138
+
41
139
  is_connection_error = isinstance(
42
140
  exc,
43
141
  (
@@ -45,7 +143,7 @@ def process_requests_exception(
45
143
  requests.exceptions.Timeout,
46
144
  requests.exceptions.TooManyRedirects,
47
145
  requests.exceptions.ChunkedEncodingError,
48
- httpx.ConnectError,
146
+ httpx.NetworkError,
49
147
  httpx.TimeoutException,
50
148
  httpx.TooManyRedirects,
51
149
  httpx.ProtocolError,
@@ -102,6 +200,33 @@ def process_requests_exception(
102
200
  process_unhandled_request(external_logger, exc)
103
201
 
104
202
 
203
+ async def process_retryable_request_async(
204
+ external_logger,
205
+ exc,
206
+ api_method_name,
207
+ url,
208
+ user_message,
209
+ verbose=True,
210
+ swallow_exc=False,
211
+ sleep_sec=None,
212
+ retry_info=None,
213
+ ):
214
+ if retry_info is not None:
215
+ retry_idx = retry_info["retry_idx"]
216
+ retry_limit = retry_info["retry_limit"]
217
+ user_message = "{}: Retrying ({}/{}).".format(user_message, retry_idx, retry_limit)
218
+ if verbose:
219
+ external_logger.warn(
220
+ user_message, extra={"method": api_method_name, "url": url, "details": str(exc)}
221
+ )
222
+
223
+ if sleep_sec is not None:
224
+ await asyncio.sleep(sleep_sec)
225
+
226
+ if not swallow_exc:
227
+ raise exc
228
+
229
+
105
230
  def process_retryable_request(
106
231
  external_logger,
107
232
  exc,
@@ -1,7 +1,6 @@
1
1
  import json
2
- import os
3
2
  import shutil
4
- from concurrent.futures import ThreadPoolExecutor
3
+ from concurrent.futures import ThreadPoolExecutor, as_completed
5
4
  from enum import Enum
6
5
  from logging import Logger
7
6
  from pathlib import Path
@@ -16,6 +15,7 @@ from cachetools import Cache, LRUCache, TTLCache
16
15
  from fastapi import BackgroundTasks, FastAPI, Form, Request, UploadFile
17
16
 
18
17
  import supervisely as sly
18
+ from supervisely._utils import batched
19
19
  from supervisely.io.fs import silent_remove
20
20
 
21
21
 
@@ -151,6 +151,38 @@ class PersistentImageTTLCache(TTLCache):
151
151
  def get_project_meta(self, project_meta_name):
152
152
  return self[project_meta_name]
153
153
 
154
+ def copy_to(self, name, path):
155
+ shutil.copyfile(str(self[name]), path)
156
+
157
+
158
+ class VideoFrameReader:
159
+ def __init__(self, video_path: str, frame_indexes: List[int]):
160
+ self.video_path = video_path
161
+ self.frame_indexes = frame_indexes
162
+ self.cap = None
163
+ self.prev_idx = -1
164
+
165
+ def __enter__(self):
166
+ self.cap = cv2.VideoCapture(str(self.video_path))
167
+ return self
168
+
169
+ def __exit__(self, exc_type, exc_val, exc_tb):
170
+ if self.cap is not None:
171
+ self.cap.release()
172
+
173
+ def read_frames(self) -> Generator:
174
+ try:
175
+ for frame_index in self.frame_indexes:
176
+ if frame_index != self.prev_idx + 1:
177
+ self.cap.set(cv2.CAP_PROP_POS_FRAMES, frame_index)
178
+ ret, frame = self.cap.read()
179
+ if not ret:
180
+ raise KeyError(f"Frame {frame_index} not found in video {self.video_path}")
181
+ yield cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
182
+ self.prev_idx = frame_index
183
+ finally:
184
+ self.cap.release()
185
+
154
186
 
155
187
  class InferenceImageCache:
156
188
  class _LoadType(Enum):
@@ -238,25 +270,18 @@ class InferenceImageCache:
238
270
  return_images,
239
271
  )
240
272
 
273
+ def _read_frames_from_cached_video_iter(self, video_id, frame_indexes):
274
+ video_path = self._cache.get_video_path(video_id)
275
+ with VideoFrameReader(video_path, frame_indexes) as reader:
276
+ for frame in reader.read_frames():
277
+ yield frame
278
+
241
279
  def _read_frames_from_cached_video(
242
280
  self, video_id: int, frame_indexes: List[int]
243
281
  ) -> List[np.ndarray]:
244
- video_path = self._cache.get_video_path(video_id)
245
- if video_path is None or not video_path.exists():
246
- raise KeyError(f"Video {video_id} not found in cache")
247
- cap = cv2.VideoCapture(str(video_path))
248
- frames = []
249
- prev_idx = -1
250
- for frame_index in frame_indexes:
251
- if frame_index != prev_idx + 1:
252
- cap.set(cv2.CAP_PROP_POS_FRAMES, frame_index)
253
- ret, frame = cap.read()
254
- if not ret:
255
- raise KeyError(f"Frame {frame_index} not found in video {video_id}")
256
- frames.append(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
257
- prev_idx = frame_index
258
- cap.release()
259
- return frames
282
+ return [
283
+ frame for frame in self._read_frames_from_cached_video_iter(video_id, frame_indexes)
284
+ ]
260
285
 
261
286
  def get_frame_from_cache(self, video_id: int, frame_index: int) -> np.ndarray:
262
287
  name = self._frame_name(video_id, frame_index)
@@ -664,3 +689,39 @@ class InferenceImageCache:
664
689
  # TODO: sleep if slowdown
665
690
  sleep(0.1)
666
691
  continue
692
+
693
+ def download_frames_to_paths(self, api, video_id, frame_indexes, paths, progress_cb=None):
694
+ def _download_frame(frame_index):
695
+ self.download_frame(api, video_id, frame_index)
696
+ name = self._frame_name(video_id, frame_index)
697
+ return frame_index, name
698
+
699
+ def _download_and_save(this_frame_indexes, this_paths):
700
+ if video_id in self._cache:
701
+ for path, frame in zip(
702
+ this_paths,
703
+ self._read_frames_from_cached_video_iter(video_id, this_frame_indexes),
704
+ ):
705
+ sly.image.write(path, frame)
706
+ if progress_cb is not None:
707
+ progress_cb()
708
+ return
709
+
710
+ futures = []
711
+ frame_index_to_path = {}
712
+ for frame_index, path in zip(this_frame_indexes[:5], this_paths[:5]):
713
+ frame_index_to_path[frame_index] = path
714
+ futures.append(executor.submit(_download_frame, frame_index))
715
+ for future in as_completed(futures):
716
+ frame_index, name = future.result()
717
+ path = frame_index_to_path[frame_index]
718
+ self._cache.copy_to(name, path)
719
+ if progress_cb is not None:
720
+ progress_cb()
721
+ if len(this_frame_indexes) > 5:
722
+ _download_and_save(this_frame_indexes[5:], this_paths[5:])
723
+
724
+ # optimization for frame read from video file
725
+ frame_indexes, paths = zip(*sorted(zip(frame_indexes, paths), key=lambda x: x[0]))
726
+ executor = ThreadPoolExecutor(max_workers=5)
727
+ _download_and_save(frame_indexes, paths)
@@ -580,7 +580,8 @@ class Inference:
580
580
  continue
581
581
  if "classes_whitelist" in inspect.signature(self._create_label).parameters:
582
582
  # pylint: disable=unexpected-keyword-arg
583
- label = self._create_label(prediction, classes_whitelist) # pylint: disable=too-many-function-args
583
+ # pylint: disable=too-many-function-args
584
+ label = self._create_label(prediction, classes_whitelist)
584
585
  else:
585
586
  label = self._create_label(prediction)
586
587
  if label is None:
@@ -36,6 +36,7 @@ from supervisely.collection.key_indexed_collection import (
36
36
  from supervisely.geometry.bitmap import Bitmap
37
37
  from supervisely.imaging import image as sly_image
38
38
  from supervisely.io.fs import (
39
+ clean_dir,
39
40
  copy_file,
40
41
  copy_file_async,
41
42
  dir_empty,
@@ -3592,7 +3593,14 @@ def _download_project(
3592
3593
  meta = ProjectMeta.from_json(api.project.get_meta(project_id, with_settings=True))
3593
3594
  if os.path.exists(dest_dir) and resume_download:
3594
3595
  dump_json_file(meta.to_json(), os.path.join(dest_dir, "meta.json"))
3595
- project_fs = Project(dest_dir, OpenMode.READ)
3596
+ try:
3597
+ project_fs = Project(dest_dir, OpenMode.READ)
3598
+ except RuntimeError as e:
3599
+ if "Project is empty" in str(e):
3600
+ clean_dir(dest_dir)
3601
+ project_fs = None
3602
+ else:
3603
+ raise
3596
3604
  if project_fs is None:
3597
3605
  project_fs = Project(dest_dir, OpenMode.CREATE)
3598
3606
  project_fs.set_meta(meta)
@@ -4394,7 +4402,14 @@ async def _download_project_async(
4394
4402
  meta = ProjectMeta.from_json(api.project.get_meta(project_id, with_settings=True))
4395
4403
  if os.path.exists(dest_dir) and resume_download:
4396
4404
  dump_json_file(meta.to_json(), os.path.join(dest_dir, "meta.json"))
4397
- project_fs = Project(dest_dir, OpenMode.READ)
4405
+ try:
4406
+ project_fs = Project(dest_dir, OpenMode.READ)
4407
+ except RuntimeError as e:
4408
+ if "Project is empty" in str(e):
4409
+ clean_dir(dest_dir)
4410
+ project_fs = None
4411
+ else:
4412
+ raise
4398
4413
  if project_fs is None:
4399
4414
  project_fs = Project(dest_dir, OpenMode.CREATE)
4400
4415
  project_fs.set_meta(meta)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: supervisely
3
- Version: 6.73.231
3
+ Version: 6.73.233
4
4
  Summary: Supervisely Python SDK.
5
5
  Home-page: https://github.com/supervisely/supervisely
6
6
  Author: Supervisely
@@ -22,7 +22,7 @@ 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
24
  supervisely/api/annotation_api.py,sha256=s9kd1G759R8YSvbDcNXrPa9xv95j1cWE1RgD6XeJe2A,58826
25
- supervisely/api/api.py,sha256=kDx9uE8fiRDnyJVuw4hG0YTuCglhzHQgnTa2-a4YEEM,62424
25
+ supervisely/api/api.py,sha256=SI7DuSi2Jnj5NFS_V9aQ9Sg3CrS97Y5p1pqeeb-4Jb4,64729
26
26
  supervisely/api/app_api.py,sha256=-T4sISQ7POyR2yirf1kEWj4JaJFpJxCyRWqbf_99Jak,67036
27
27
  supervisely/api/dataset_api.py,sha256=2-SQBlgEnIN-0uvDbtPlSXr6ztBeZ3WPryhkOtpBmk4,40786
28
28
  supervisely/api/file_api.py,sha256=WMg80fxqMKOo3ai-IGON2w-IDAySPk90USoVk29JOdE,82415
@@ -64,7 +64,7 @@ supervisely/api/pointcloud/pointcloud_object_api.py,sha256=bO1USWb9HAywG_CW4CDu1
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
66
  supervisely/api/video/video_annotation_api.py,sha256=Um_7UOJtP_E25X6v41mrZfDbJaJuLMGoZm2IULwyg3w,10977
67
- supervisely/api/video/video_api.py,sha256=2yFm1pbL-ziHl8vDyrf8z1qLbZxlo_22FyqjKPQbNg4,94228
67
+ supervisely/api/video/video_api.py,sha256=KO_Nfqa4xDWrc7FqOR14PciC0TX8PF0g0peqgPnctEE,94677
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
@@ -689,7 +689,7 @@ supervisely/io/fs_cache.py,sha256=985gvBGzveLcDudgz10E4EWVjP9jxdU1Pa0GFfCBoCA,65
689
689
  supervisely/io/github_utils.py,sha256=jGmvQJ5bjtACuSFABzrxL0jJdh14SezovrHp8T-9y8g,1779
690
690
  supervisely/io/json.py,sha256=VvyqXZl22nb6_DJK3TUOPetd5xq9xwRFKumWqsGs7iI,8679
691
691
  supervisely/io/multipart_stream_decoder.py,sha256=rCheeSCAGdw2tNyaWEYa4dvoIDuldXOxH86RVB82c78,14417
692
- supervisely/io/network_exceptions.py,sha256=eegxgbtkbKpbjPdiATXpvUSMpe6AFPiu0IAKyxPSXms,4777
692
+ supervisely/io/network_exceptions.py,sha256=pEhw0jKw_p-Rl42SMOexVU6SW2Z_xIl1kTryNb3EvIQ,8716
693
693
  supervisely/labeling_jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
694
694
  supervisely/labeling_jobs/constants.py,sha256=GF_pwF9fC9_DGbpD3cAk3llifskAxpDmyuXwxM1f3Hw,104
695
695
  supervisely/labeling_jobs/utils.py,sha256=XOGF2cbnTGbXFdT5jGL1LIPQfiCEJgRkmKNIjTlFois,22656
@@ -816,8 +816,8 @@ supervisely/nn/benchmark/visualization/widgets/sidebar/sidebar.py,sha256=tKPURRS
816
816
  supervisely/nn/benchmark/visualization/widgets/table/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
817
817
  supervisely/nn/benchmark/visualization/widgets/table/table.py,sha256=YiCpt-mdINJnNBWsUTPkRR_9w09Ne2Y0n93DY8vsE8I,4090
818
818
  supervisely/nn/inference/__init__.py,sha256=mtEci4Puu-fRXDnGn8RP47o97rv3VTE0hjbYO34Zwqg,1622
819
- supervisely/nn/inference/cache.py,sha256=WylgHgPQRIoA_RDks8FyKgHqeZZ_YFoyddxkVvOX2YQ,25713
820
- supervisely/nn/inference/inference.py,sha256=jqhugSdwrKPyimiSxGvsJYLTjAyrxVmOl2FNql6f4aA,116982
819
+ supervisely/nn/inference/cache.py,sha256=KvzCgMbEBLdiJAxJDLicIPKAlYb52P9_kpNPWfiVY8Y,28194
820
+ supervisely/nn/inference/inference.py,sha256=CmQe6QnhZuUV128jcIp2YKsgeggAtmc1NL7PdFnc_hw,116997
821
821
  supervisely/nn/inference/session.py,sha256=jmkkxbe2kH-lEgUU6Afh62jP68dxfhF5v6OGDfLU62E,35757
822
822
  supervisely/nn/inference/video_inference.py,sha256=8Bshjr6rDyLay5Za8IB8Dr6FURMO2R_v7aELasO8pR4,5746
823
823
  supervisely/nn/inference/gui/__init__.py,sha256=e3RKi93bI1r_0Dkvs_gaR1p_jkzkBMNjrcx-RVlm93k,88
@@ -935,7 +935,7 @@ supervisely/project/data_version.py,sha256=nknaWJSUCwoDyNG9_d1KA-GjzidhV9zd9Cn8c
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=T2ge_9HXlaDyDziEhr-5lcyUcHskaUIbgwtrWs7PqYo,180929
938
+ supervisely/project/project.py,sha256=byf0WUxIvfoqFwq57Yea0hnljHWVrZMYMH8cGCH_rCM,181356
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
@@ -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.231.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1001
- supervisely-6.73.231.dist-info/METADATA,sha256=6Nn3J-8unL0hd-sYLQcavVvRFWolrgNpy30IxKd6-So,33150
1002
- supervisely-6.73.231.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
1003
- supervisely-6.73.231.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
1004
- supervisely-6.73.231.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
1005
- supervisely-6.73.231.dist-info/RECORD,,
1000
+ supervisely-6.73.233.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1001
+ supervisely-6.73.233.dist-info/METADATA,sha256=MJtm60rKHXwewU1uAmNhtaWHuI_g_Y4oGxJbqM-oiFM,33150
1002
+ supervisely-6.73.233.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
1003
+ supervisely-6.73.233.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
1004
+ supervisely-6.73.233.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
1005
+ supervisely-6.73.233.dist-info/RECORD,,