supervisely 6.73.230__py3-none-any.whl → 6.73.232__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 +54 -10
- supervisely/api/video/video_api.py +19 -6
- supervisely/convert/video/video_converter.py +2 -1
- supervisely/io/network_exceptions.py +126 -1
- supervisely/nn/inference/inference.py +2 -1
- supervisely/project/project.py +17 -2
- {supervisely-6.73.230.dist-info → supervisely-6.73.232.dist-info}/METADATA +1 -1
- {supervisely-6.73.230.dist-info → supervisely-6.73.232.dist-info}/RECORD +12 -12
- {supervisely-6.73.230.dist-info → supervisely-6.73.232.dist-info}/LICENSE +0 -0
- {supervisely-6.73.230.dist-info → supervisely-6.73.232.dist-info}/WHEEL +0 -0
- {supervisely-6.73.230.dist-info → supervisely-6.73.232.dist-info}/entry_points.txt +0 -0
- {supervisely-6.73.230.dist-info → supervisely-6.73.232.dist-info}/top_level.txt +0 -0
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1542
|
+
await process_requests_exception_async(
|
|
1499
1543
|
self.logger,
|
|
1500
1544
|
e,
|
|
1501
1545
|
method,
|
|
@@ -340,6 +340,7 @@ class VideoApi(RemoveableBulkModuleApi):
|
|
|
340
340
|
filters: Optional[List[Dict[str, str]]] = None,
|
|
341
341
|
raw_video_meta: Optional[bool] = False,
|
|
342
342
|
fields: Optional[List[str]] = None,
|
|
343
|
+
force_metadata_for_links: Optional[bool] = False,
|
|
343
344
|
) -> List[VideoInfo]:
|
|
344
345
|
"""
|
|
345
346
|
Get list of information about all videos for a given dataset ID.
|
|
@@ -352,6 +353,8 @@ class VideoApi(RemoveableBulkModuleApi):
|
|
|
352
353
|
:type raw_video_meta: bool
|
|
353
354
|
:param fields: List of fields to return.
|
|
354
355
|
:type fields: List[str], optional
|
|
356
|
+
:param force_metadata_for_links: Specify whether to force retrieving video metadata from the server.
|
|
357
|
+
:type force_metadata_for_links: Optional[bool]
|
|
355
358
|
:return: List of information about videos in given dataset.
|
|
356
359
|
:rtype: :class:`List[VideoInfo]`
|
|
357
360
|
|
|
@@ -379,6 +382,7 @@ class VideoApi(RemoveableBulkModuleApi):
|
|
|
379
382
|
ApiField.DATASET_ID: dataset_id,
|
|
380
383
|
ApiField.FILTER: filters or [],
|
|
381
384
|
ApiField.RAW_VIDEO_META: raw_video_meta,
|
|
385
|
+
ApiField.FORCE_METADATA_FOR_LINKS: force_metadata_for_links,
|
|
382
386
|
}
|
|
383
387
|
if fields is not None:
|
|
384
388
|
data[ApiField.FIELDS] = fields
|
|
@@ -393,6 +397,7 @@ class VideoApi(RemoveableBulkModuleApi):
|
|
|
393
397
|
limit: Optional[int] = None,
|
|
394
398
|
raw_video_meta: Optional[bool] = False,
|
|
395
399
|
batch_size: Optional[int] = None,
|
|
400
|
+
force_metadata_for_links: Optional[bool] = False,
|
|
396
401
|
) -> Iterator[List[VideoInfo]]:
|
|
397
402
|
data = {
|
|
398
403
|
ApiField.DATASET_ID: dataset_id,
|
|
@@ -401,6 +406,7 @@ class VideoApi(RemoveableBulkModuleApi):
|
|
|
401
406
|
ApiField.SORT_ORDER: sort_order,
|
|
402
407
|
ApiField.RAW_VIDEO_META: raw_video_meta,
|
|
403
408
|
ApiField.PAGINATION_MODE: ApiField.TOKEN,
|
|
409
|
+
ApiField.FORCE_METADATA_FOR_LINKS: force_metadata_for_links,
|
|
404
410
|
}
|
|
405
411
|
if batch_size is not None:
|
|
406
412
|
data[ApiField.PER_PAGE] = batch_size
|
|
@@ -428,7 +434,7 @@ class VideoApi(RemoveableBulkModuleApi):
|
|
|
428
434
|
:type id: int
|
|
429
435
|
:param raise_error: Return an error if the video info was not received.
|
|
430
436
|
:type raise_error: bool
|
|
431
|
-
:param force_metadata_for_links:
|
|
437
|
+
:param force_metadata_for_links: Specify whether to force retrieving video metadata from the server.
|
|
432
438
|
:type force_metadata_for_links: bool
|
|
433
439
|
:return: Information about Video. See :class:`info_sequence<info_sequence>`
|
|
434
440
|
:rtype: :class:`VideoInfo`
|
|
@@ -508,7 +514,7 @@ class VideoApi(RemoveableBulkModuleApi):
|
|
|
508
514
|
:type ids: List[int]
|
|
509
515
|
:param progress_cb: Function for tracking download progress.
|
|
510
516
|
:type progress_cb: Optional[Union[tqdm, Callable]]
|
|
511
|
-
:param force_metadata_for_links:
|
|
517
|
+
:param force_metadata_for_links: Specify whether to force retrieving video metadata from the server.
|
|
512
518
|
:type force_metadata_for_links: bool
|
|
513
519
|
:return: List of information about Videos. See :class:`info_sequence<info_sequence>`.
|
|
514
520
|
:rtype: List[VideoInfo]
|
|
@@ -582,6 +588,8 @@ class VideoApi(RemoveableBulkModuleApi):
|
|
|
582
588
|
:type id: int
|
|
583
589
|
:param raise_error: Return an error if the video info was not received.
|
|
584
590
|
:type raise_error: bool
|
|
591
|
+
:param force_metadata_for_links: Specify whether to force retrieving video metadata from the server.
|
|
592
|
+
:type force_metadata_for_links: bool
|
|
585
593
|
:return: Information about Video. See :class:`info_sequence<info_sequence>`
|
|
586
594
|
:rtype: dict
|
|
587
595
|
|
|
@@ -969,6 +977,7 @@ class VideoApi(RemoveableBulkModuleApi):
|
|
|
969
977
|
links_names,
|
|
970
978
|
metas=links_metas,
|
|
971
979
|
skip_download=True,
|
|
980
|
+
force_metadata_for_links=False,
|
|
972
981
|
)
|
|
973
982
|
|
|
974
983
|
for info, pos in zip(res_infos_links, links_order):
|
|
@@ -1044,7 +1053,7 @@ class VideoApi(RemoveableBulkModuleApi):
|
|
|
1044
1053
|
if len(set(vid_info.dataset_id for vid_info in ids_info)) > 1:
|
|
1045
1054
|
raise ValueError("Videos ids have to be from the same dataset")
|
|
1046
1055
|
|
|
1047
|
-
existing_videos = self.get_list(dst_dataset_id)
|
|
1056
|
+
existing_videos = self.get_list(dst_dataset_id, force_metadata_for_links=False)
|
|
1048
1057
|
existing_names = {video.name for video in existing_videos}
|
|
1049
1058
|
|
|
1050
1059
|
if change_name_if_conflict:
|
|
@@ -1848,7 +1857,7 @@ class VideoApi(RemoveableBulkModuleApi):
|
|
|
1848
1857
|
:type skip_download: Optional[bool]
|
|
1849
1858
|
:param progress_cb: Function for tracking the progress of copying.
|
|
1850
1859
|
:type progress_cb: tqdm or callable, optional
|
|
1851
|
-
:param force_metadata_for_links: Specify
|
|
1860
|
+
:param force_metadata_for_links: Specify whether to force retrieving videos metadata from the server after upload
|
|
1852
1861
|
:type force_metadata_for_links: Optional[bool]
|
|
1853
1862
|
:return: List with information about Videos. See :class:`info_sequence<info_sequence>`
|
|
1854
1863
|
:rtype: :class:`List[VideoInfo]`
|
|
@@ -1941,6 +1950,7 @@ class VideoApi(RemoveableBulkModuleApi):
|
|
|
1941
1950
|
hash: Optional[str] = None,
|
|
1942
1951
|
meta: Optional[List[Dict]] = None,
|
|
1943
1952
|
skip_download: Optional[bool] = False,
|
|
1953
|
+
force_metadata_for_links: Optional[bool] = True,
|
|
1944
1954
|
):
|
|
1945
1955
|
"""
|
|
1946
1956
|
Upload Video from given link to Dataset.
|
|
@@ -1959,6 +1969,8 @@ class VideoApi(RemoveableBulkModuleApi):
|
|
|
1959
1969
|
:type meta: List[Dict], optional
|
|
1960
1970
|
:param skip_download: Skip download video to local storage.
|
|
1961
1971
|
:type skip_download: Optional[bool]
|
|
1972
|
+
:param force_metadata_for_links: Specify whether to force retrieving video metadata from the server after upload
|
|
1973
|
+
:type force_metadata_for_links: Optional[bool]
|
|
1962
1974
|
:return: List with information about Video. See :class:`info_sequence<info_sequence>`
|
|
1963
1975
|
:rtype: :class:`List[VideoInfo]`
|
|
1964
1976
|
|
|
@@ -2043,6 +2055,7 @@ class VideoApi(RemoveableBulkModuleApi):
|
|
|
2043
2055
|
hashes=[h],
|
|
2044
2056
|
metas=[meta],
|
|
2045
2057
|
skip_download=skip_download,
|
|
2058
|
+
force_metadata_for_links=force_metadata_for_links
|
|
2046
2059
|
)
|
|
2047
2060
|
if len(links) != 1:
|
|
2048
2061
|
raise RuntimeError(
|
|
@@ -2218,7 +2231,7 @@ class VideoApi(RemoveableBulkModuleApi):
|
|
|
2218
2231
|
:rtype: List[str]
|
|
2219
2232
|
"""
|
|
2220
2233
|
|
|
2221
|
-
videos_in_dataset = self.get_list(dataset_id)
|
|
2234
|
+
videos_in_dataset = self.get_list(dataset_id, force_metadata_for_links=False)
|
|
2222
2235
|
used_names = {video_info.name for video_info in videos_in_dataset}
|
|
2223
2236
|
new_names = [
|
|
2224
2237
|
generate_free_name(used_names, name, with_ext=True, extend_used_names=True)
|
|
@@ -2244,7 +2257,7 @@ class VideoApi(RemoveableBulkModuleApi):
|
|
|
2244
2257
|
:return: None
|
|
2245
2258
|
:rtype: None
|
|
2246
2259
|
"""
|
|
2247
|
-
videos_in_dataset = self.get_list(dataset_id)
|
|
2260
|
+
videos_in_dataset = self.get_list(dataset_id, force_metadata_for_links=False)
|
|
2248
2261
|
used_names = {video_info.name for video_info in videos_in_dataset}
|
|
2249
2262
|
name_intersections = used_names.intersection(set(names))
|
|
2250
2263
|
if message is None:
|
|
@@ -123,7 +123,8 @@ class VideoConverter(BaseConverter):
|
|
|
123
123
|
|
|
124
124
|
meta, renamed_classes, renamed_tags = self.merge_metas_with_conflicts(api, dataset_id)
|
|
125
125
|
|
|
126
|
-
|
|
126
|
+
videos_in_dataset = api.video.get_list(dataset_id, force_metadata_for_links=False)
|
|
127
|
+
existing_names = {video_info.name for video_info in videos_in_dataset}
|
|
127
128
|
|
|
128
129
|
# check video codecs, mimetypes and convert if needed
|
|
129
130
|
convert_progress, convert_progress_cb = self.get_progress(
|
|
@@ -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.
|
|
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,
|
|
@@ -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
|
-
|
|
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:
|
supervisely/project/project.py
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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)
|
|
@@ -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=
|
|
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=
|
|
67
|
+
supervisely/api/video/video_api.py,sha256=2yFm1pbL-ziHl8vDyrf8z1qLbZxlo_22FyqjKPQbNg4,94228
|
|
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
|
|
@@ -623,7 +623,7 @@ supervisely/convert/pointcloud_episodes/sly/__init__.py,sha256=47DEQpj8HBSa-_TIm
|
|
|
623
623
|
supervisely/convert/pointcloud_episodes/sly/sly_pointcloud_episodes_converter.py,sha256=7ONcZMOUJCNpmc0tmMX6FnNG0lu8Nj9K2SSTQHaSXFM,6188
|
|
624
624
|
supervisely/convert/pointcloud_episodes/sly/sly_pointcloud_episodes_helper.py,sha256=h4WvNH6cEHtjxxhCnU7Hs2vkyJMye0qwabqXNYVTywE,3570
|
|
625
625
|
supervisely/convert/video/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
626
|
-
supervisely/convert/video/video_converter.py,sha256=
|
|
626
|
+
supervisely/convert/video/video_converter.py,sha256=f-b6FexBjXw9xWv5w8lxlNxCh4FvacNolX-WQDibWFs,11338
|
|
627
627
|
supervisely/convert/video/davis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
628
628
|
supervisely/convert/video/davis/davis_converter.py,sha256=zaPsJdN6AvyPT7fVnswuPbgrz5T-X2RFbHEdkuMhWGk,415
|
|
629
629
|
supervisely/convert/video/mot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -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=
|
|
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
|
|
@@ -817,7 +817,7 @@ supervisely/nn/benchmark/visualization/widgets/table/__init__.py,sha256=47DEQpj8
|
|
|
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
819
|
supervisely/nn/inference/cache.py,sha256=WylgHgPQRIoA_RDks8FyKgHqeZZ_YFoyddxkVvOX2YQ,25713
|
|
820
|
-
supervisely/nn/inference/inference.py,sha256=
|
|
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=
|
|
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.
|
|
1001
|
-
supervisely-6.73.
|
|
1002
|
-
supervisely-6.73.
|
|
1003
|
-
supervisely-6.73.
|
|
1004
|
-
supervisely-6.73.
|
|
1005
|
-
supervisely-6.73.
|
|
1000
|
+
supervisely-6.73.232.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
1001
|
+
supervisely-6.73.232.dist-info/METADATA,sha256=xZnrkZw3qSVTsMB9IDC8aQsI6xxhZRlM_9LNc9MBjXY,33150
|
|
1002
|
+
supervisely-6.73.232.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
|
|
1003
|
+
supervisely-6.73.232.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
|
|
1004
|
+
supervisely-6.73.232.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
|
|
1005
|
+
supervisely-6.73.232.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|