dtlpy 1.115.44__py3-none-any.whl → 1.117.6__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.
- dtlpy/__init__.py +491 -491
- dtlpy/__version__.py +1 -1
- dtlpy/assets/__init__.py +26 -26
- dtlpy/assets/code_server/config.yaml +2 -2
- dtlpy/assets/code_server/installation.sh +24 -24
- dtlpy/assets/code_server/launch.json +13 -13
- dtlpy/assets/code_server/settings.json +2 -2
- dtlpy/assets/main.py +53 -53
- dtlpy/assets/main_partial.py +18 -18
- dtlpy/assets/mock.json +11 -11
- dtlpy/assets/model_adapter.py +83 -83
- dtlpy/assets/package.json +61 -61
- dtlpy/assets/package_catalog.json +29 -29
- dtlpy/assets/package_gitignore +307 -307
- dtlpy/assets/service_runners/__init__.py +33 -33
- dtlpy/assets/service_runners/converter.py +96 -96
- dtlpy/assets/service_runners/multi_method.py +49 -49
- dtlpy/assets/service_runners/multi_method_annotation.py +54 -54
- dtlpy/assets/service_runners/multi_method_dataset.py +55 -55
- dtlpy/assets/service_runners/multi_method_item.py +52 -52
- dtlpy/assets/service_runners/multi_method_json.py +52 -52
- dtlpy/assets/service_runners/single_method.py +37 -37
- dtlpy/assets/service_runners/single_method_annotation.py +43 -43
- dtlpy/assets/service_runners/single_method_dataset.py +43 -43
- dtlpy/assets/service_runners/single_method_item.py +41 -41
- dtlpy/assets/service_runners/single_method_json.py +42 -42
- dtlpy/assets/service_runners/single_method_multi_input.py +45 -45
- dtlpy/assets/voc_annotation_template.xml +23 -23
- dtlpy/caches/base_cache.py +32 -32
- dtlpy/caches/cache.py +473 -473
- dtlpy/caches/dl_cache.py +201 -201
- dtlpy/caches/filesystem_cache.py +89 -89
- dtlpy/caches/redis_cache.py +84 -84
- dtlpy/dlp/__init__.py +20 -20
- dtlpy/dlp/cli_utilities.py +367 -367
- dtlpy/dlp/command_executor.py +764 -764
- dtlpy/dlp/dlp +1 -1
- dtlpy/dlp/dlp.bat +1 -1
- dtlpy/dlp/dlp.py +128 -128
- dtlpy/dlp/parser.py +651 -651
- dtlpy/entities/__init__.py +83 -83
- dtlpy/entities/analytic.py +347 -347
- dtlpy/entities/annotation.py +1879 -1879
- dtlpy/entities/annotation_collection.py +699 -699
- dtlpy/entities/annotation_definitions/__init__.py +20 -20
- dtlpy/entities/annotation_definitions/base_annotation_definition.py +100 -100
- dtlpy/entities/annotation_definitions/box.py +195 -195
- dtlpy/entities/annotation_definitions/classification.py +67 -67
- dtlpy/entities/annotation_definitions/comparison.py +72 -72
- dtlpy/entities/annotation_definitions/cube.py +204 -204
- dtlpy/entities/annotation_definitions/cube_3d.py +149 -149
- dtlpy/entities/annotation_definitions/description.py +32 -32
- dtlpy/entities/annotation_definitions/ellipse.py +124 -124
- dtlpy/entities/annotation_definitions/free_text.py +62 -62
- dtlpy/entities/annotation_definitions/gis.py +69 -69
- dtlpy/entities/annotation_definitions/note.py +139 -139
- dtlpy/entities/annotation_definitions/point.py +117 -117
- dtlpy/entities/annotation_definitions/polygon.py +182 -182
- dtlpy/entities/annotation_definitions/polyline.py +111 -111
- dtlpy/entities/annotation_definitions/pose.py +92 -92
- dtlpy/entities/annotation_definitions/ref_image.py +86 -86
- dtlpy/entities/annotation_definitions/segmentation.py +240 -240
- dtlpy/entities/annotation_definitions/subtitle.py +34 -34
- dtlpy/entities/annotation_definitions/text.py +85 -85
- dtlpy/entities/annotation_definitions/undefined_annotation.py +74 -74
- dtlpy/entities/app.py +220 -220
- dtlpy/entities/app_module.py +107 -107
- dtlpy/entities/artifact.py +174 -174
- dtlpy/entities/assignment.py +399 -399
- dtlpy/entities/base_entity.py +214 -214
- dtlpy/entities/bot.py +113 -113
- dtlpy/entities/codebase.py +292 -292
- dtlpy/entities/collection.py +38 -38
- dtlpy/entities/command.py +169 -169
- dtlpy/entities/compute.py +449 -449
- dtlpy/entities/dataset.py +1299 -1299
- dtlpy/entities/directory_tree.py +44 -44
- dtlpy/entities/dpk.py +470 -470
- dtlpy/entities/driver.py +235 -235
- dtlpy/entities/execution.py +397 -397
- dtlpy/entities/feature.py +124 -124
- dtlpy/entities/feature_set.py +152 -145
- dtlpy/entities/filters.py +798 -798
- dtlpy/entities/gis_item.py +107 -107
- dtlpy/entities/integration.py +184 -184
- dtlpy/entities/item.py +975 -959
- dtlpy/entities/label.py +123 -123
- dtlpy/entities/links.py +85 -85
- dtlpy/entities/message.py +175 -175
- dtlpy/entities/model.py +684 -684
- dtlpy/entities/node.py +1005 -1005
- dtlpy/entities/ontology.py +810 -803
- dtlpy/entities/organization.py +287 -287
- dtlpy/entities/package.py +657 -657
- dtlpy/entities/package_defaults.py +5 -5
- dtlpy/entities/package_function.py +185 -185
- dtlpy/entities/package_module.py +113 -113
- dtlpy/entities/package_slot.py +118 -118
- dtlpy/entities/paged_entities.py +299 -299
- dtlpy/entities/pipeline.py +624 -624
- dtlpy/entities/pipeline_execution.py +279 -279
- dtlpy/entities/project.py +394 -394
- dtlpy/entities/prompt_item.py +505 -505
- dtlpy/entities/recipe.py +301 -301
- dtlpy/entities/reflect_dict.py +102 -102
- dtlpy/entities/resource_execution.py +138 -138
- dtlpy/entities/service.py +974 -963
- dtlpy/entities/service_driver.py +117 -117
- dtlpy/entities/setting.py +294 -294
- dtlpy/entities/task.py +495 -495
- dtlpy/entities/time_series.py +143 -143
- dtlpy/entities/trigger.py +426 -426
- dtlpy/entities/user.py +118 -118
- dtlpy/entities/webhook.py +124 -124
- dtlpy/examples/__init__.py +19 -19
- dtlpy/examples/add_labels.py +135 -135
- dtlpy/examples/add_metadata_to_item.py +21 -21
- dtlpy/examples/annotate_items_using_model.py +65 -65
- dtlpy/examples/annotate_video_using_model_and_tracker.py +75 -75
- dtlpy/examples/annotations_convert_to_voc.py +9 -9
- dtlpy/examples/annotations_convert_to_yolo.py +9 -9
- dtlpy/examples/convert_annotation_types.py +51 -51
- dtlpy/examples/converter.py +143 -143
- dtlpy/examples/copy_annotations.py +22 -22
- dtlpy/examples/copy_folder.py +31 -31
- dtlpy/examples/create_annotations.py +51 -51
- dtlpy/examples/create_video_annotations.py +83 -83
- dtlpy/examples/delete_annotations.py +26 -26
- dtlpy/examples/filters.py +113 -113
- dtlpy/examples/move_item.py +23 -23
- dtlpy/examples/play_video_annotation.py +13 -13
- dtlpy/examples/show_item_and_mask.py +53 -53
- dtlpy/examples/triggers.py +49 -49
- dtlpy/examples/upload_batch_of_items.py +20 -20
- dtlpy/examples/upload_items_and_custom_format_annotations.py +55 -55
- dtlpy/examples/upload_items_with_modalities.py +43 -43
- dtlpy/examples/upload_segmentation_annotations_from_mask_image.py +44 -44
- dtlpy/examples/upload_yolo_format_annotations.py +70 -70
- dtlpy/exceptions.py +125 -125
- dtlpy/miscellaneous/__init__.py +20 -20
- dtlpy/miscellaneous/dict_differ.py +95 -95
- dtlpy/miscellaneous/git_utils.py +217 -217
- dtlpy/miscellaneous/json_utils.py +14 -14
- dtlpy/miscellaneous/list_print.py +105 -105
- dtlpy/miscellaneous/zipping.py +130 -130
- dtlpy/ml/__init__.py +20 -20
- dtlpy/ml/base_feature_extractor_adapter.py +27 -27
- dtlpy/ml/base_model_adapter.py +1287 -1230
- dtlpy/ml/metrics.py +461 -461
- dtlpy/ml/predictions_utils.py +274 -274
- dtlpy/ml/summary_writer.py +57 -57
- dtlpy/ml/train_utils.py +60 -60
- dtlpy/new_instance.py +252 -252
- dtlpy/repositories/__init__.py +56 -56
- dtlpy/repositories/analytics.py +85 -85
- dtlpy/repositories/annotations.py +916 -916
- dtlpy/repositories/apps.py +383 -383
- dtlpy/repositories/artifacts.py +452 -452
- dtlpy/repositories/assignments.py +599 -599
- dtlpy/repositories/bots.py +213 -213
- dtlpy/repositories/codebases.py +559 -559
- dtlpy/repositories/collections.py +332 -332
- dtlpy/repositories/commands.py +152 -152
- dtlpy/repositories/compositions.py +61 -61
- dtlpy/repositories/computes.py +439 -439
- dtlpy/repositories/datasets.py +1585 -1504
- dtlpy/repositories/downloader.py +1157 -923
- dtlpy/repositories/dpks.py +433 -433
- dtlpy/repositories/drivers.py +482 -482
- dtlpy/repositories/executions.py +815 -815
- dtlpy/repositories/feature_sets.py +256 -226
- dtlpy/repositories/features.py +255 -255
- dtlpy/repositories/integrations.py +484 -484
- dtlpy/repositories/items.py +912 -912
- dtlpy/repositories/messages.py +94 -94
- dtlpy/repositories/models.py +1000 -1000
- dtlpy/repositories/nodes.py +80 -80
- dtlpy/repositories/ontologies.py +511 -511
- dtlpy/repositories/organizations.py +525 -525
- dtlpy/repositories/packages.py +1941 -1941
- dtlpy/repositories/pipeline_executions.py +451 -451
- dtlpy/repositories/pipelines.py +640 -640
- dtlpy/repositories/projects.py +539 -539
- dtlpy/repositories/recipes.py +429 -399
- dtlpy/repositories/resource_executions.py +137 -137
- dtlpy/repositories/schema.py +120 -120
- dtlpy/repositories/service_drivers.py +213 -213
- dtlpy/repositories/services.py +1704 -1704
- dtlpy/repositories/settings.py +339 -339
- dtlpy/repositories/tasks.py +1477 -1477
- dtlpy/repositories/times_series.py +278 -278
- dtlpy/repositories/triggers.py +536 -536
- dtlpy/repositories/upload_element.py +257 -257
- dtlpy/repositories/uploader.py +661 -661
- dtlpy/repositories/webhooks.py +249 -249
- dtlpy/services/__init__.py +22 -22
- dtlpy/services/aihttp_retry.py +131 -131
- dtlpy/services/api_client.py +1786 -1785
- dtlpy/services/api_reference.py +40 -40
- dtlpy/services/async_utils.py +133 -133
- dtlpy/services/calls_counter.py +44 -44
- dtlpy/services/check_sdk.py +68 -68
- dtlpy/services/cookie.py +115 -115
- dtlpy/services/create_logger.py +156 -156
- dtlpy/services/events.py +84 -84
- dtlpy/services/logins.py +235 -235
- dtlpy/services/reporter.py +256 -256
- dtlpy/services/service_defaults.py +91 -91
- dtlpy/utilities/__init__.py +20 -20
- dtlpy/utilities/annotations/__init__.py +16 -16
- dtlpy/utilities/annotations/annotation_converters.py +269 -269
- dtlpy/utilities/base_package_runner.py +285 -264
- dtlpy/utilities/converter.py +1650 -1650
- dtlpy/utilities/dataset_generators/__init__.py +1 -1
- dtlpy/utilities/dataset_generators/dataset_generator.py +670 -670
- dtlpy/utilities/dataset_generators/dataset_generator_tensorflow.py +23 -23
- dtlpy/utilities/dataset_generators/dataset_generator_torch.py +21 -21
- dtlpy/utilities/local_development/__init__.py +1 -1
- dtlpy/utilities/local_development/local_session.py +179 -179
- dtlpy/utilities/reports/__init__.py +2 -2
- dtlpy/utilities/reports/figures.py +343 -343
- dtlpy/utilities/reports/report.py +71 -71
- dtlpy/utilities/videos/__init__.py +17 -17
- dtlpy/utilities/videos/video_player.py +598 -598
- dtlpy/utilities/videos/videos.py +470 -470
- {dtlpy-1.115.44.data → dtlpy-1.117.6.data}/scripts/dlp +1 -1
- dtlpy-1.117.6.data/scripts/dlp.bat +2 -0
- {dtlpy-1.115.44.data → dtlpy-1.117.6.data}/scripts/dlp.py +128 -128
- {dtlpy-1.115.44.dist-info → dtlpy-1.117.6.dist-info}/METADATA +186 -186
- dtlpy-1.117.6.dist-info/RECORD +239 -0
- {dtlpy-1.115.44.dist-info → dtlpy-1.117.6.dist-info}/WHEEL +1 -1
- {dtlpy-1.115.44.dist-info → dtlpy-1.117.6.dist-info}/licenses/LICENSE +200 -200
- tests/features/environment.py +551 -551
- dtlpy/assets/__pycache__/__init__.cpython-310.pyc +0 -0
- dtlpy-1.115.44.data/scripts/dlp.bat +0 -2
- dtlpy-1.115.44.dist-info/RECORD +0 -240
- {dtlpy-1.115.44.dist-info → dtlpy-1.117.6.dist-info}/entry_points.txt +0 -0
- {dtlpy-1.115.44.dist-info → dtlpy-1.117.6.dist-info}/top_level.txt +0 -0
dtlpy/services/aihttp_retry.py
CHANGED
|
@@ -1,131 +1,131 @@
|
|
|
1
|
-
# from https://pypi.org/project/aiohttp-retry/ with modification to python 3.5.4
|
|
2
|
-
import asyncio
|
|
3
|
-
import logging
|
|
4
|
-
from aiohttp import ClientSession, ClientResponse
|
|
5
|
-
from typing import Any, Callable, Optional, Set, Type
|
|
6
|
-
|
|
7
|
-
# Options
|
|
8
|
-
_RETRY_ATTEMPTS = 3
|
|
9
|
-
_RETRY_START_TIMEOUT = 0.1
|
|
10
|
-
_RETRY_MAX_TIMEOUT = 30
|
|
11
|
-
_RETRY_FACTOR = 2
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class _RequestContext:
|
|
15
|
-
def __init__(self, request: Callable[..., Any], # Request operation, like POST or GET
|
|
16
|
-
url: str, # Just url
|
|
17
|
-
retry_attempts: int = _RETRY_ATTEMPTS, # How many times we should retry
|
|
18
|
-
retry_start_timeout: float = _RETRY_START_TIMEOUT, # Base timeout time, then it exponentially grow
|
|
19
|
-
retry_max_timeout: float = _RETRY_MAX_TIMEOUT, # Max possible timeout between tries
|
|
20
|
-
retry_factor: float = _RETRY_FACTOR, # How much we increase timeout each time
|
|
21
|
-
retry_for_statuses: Optional[Set[int]] = None, # On which statuses we should retry
|
|
22
|
-
retry_exceptions: Optional[Set[Type]] = None, # On which exceptions we should retry
|
|
23
|
-
**kwargs: Any
|
|
24
|
-
) -> None:
|
|
25
|
-
self._request = request
|
|
26
|
-
self._url = url
|
|
27
|
-
|
|
28
|
-
self._retry_attempts = retry_attempts
|
|
29
|
-
self._retry_start_timeout = retry_start_timeout
|
|
30
|
-
self._retry_max_timeout = retry_max_timeout
|
|
31
|
-
self._retry_factor = retry_factor
|
|
32
|
-
|
|
33
|
-
if retry_for_statuses is None:
|
|
34
|
-
retry_for_statuses = set()
|
|
35
|
-
self._retry_for_statuses = retry_for_statuses
|
|
36
|
-
|
|
37
|
-
if retry_exceptions is None:
|
|
38
|
-
retry_exceptions = set()
|
|
39
|
-
self._retry_exceptions = retry_exceptions
|
|
40
|
-
|
|
41
|
-
self._kwargs = kwargs
|
|
42
|
-
|
|
43
|
-
self._current_attempt = 0
|
|
44
|
-
self._response = None
|
|
45
|
-
|
|
46
|
-
def _exponential_timeout(self) -> float:
|
|
47
|
-
timeout = self._retry_start_timeout * (self._retry_factor ** (self._current_attempt - 1))
|
|
48
|
-
return min(timeout, self._retry_max_timeout)
|
|
49
|
-
|
|
50
|
-
def _check_code(self, code: int) -> bool:
|
|
51
|
-
return 500 <= code <= 599 or code in self._retry_for_statuses
|
|
52
|
-
|
|
53
|
-
async def _do_request(self) -> ClientResponse:
|
|
54
|
-
try:
|
|
55
|
-
self._current_attempt += 1
|
|
56
|
-
response = await self._request(url=self._url, **self._kwargs)
|
|
57
|
-
code = response.status
|
|
58
|
-
if self._current_attempt < self._retry_attempts and self._check_code(code):
|
|
59
|
-
retry_wait = self._exponential_timeout()
|
|
60
|
-
await asyncio.sleep(retry_wait)
|
|
61
|
-
return await self._do_request()
|
|
62
|
-
self._response = response
|
|
63
|
-
return response
|
|
64
|
-
|
|
65
|
-
except Exception as e:
|
|
66
|
-
retry_wait = self._exponential_timeout()
|
|
67
|
-
if self._current_attempt < self._retry_attempts:
|
|
68
|
-
for exc in self._retry_exceptions:
|
|
69
|
-
if isinstance(e, exc):
|
|
70
|
-
await asyncio.sleep(retry_wait)
|
|
71
|
-
return await self._do_request()
|
|
72
|
-
|
|
73
|
-
raise e
|
|
74
|
-
|
|
75
|
-
async def __aenter__(self) -> ClientResponse:
|
|
76
|
-
return await self._do_request()
|
|
77
|
-
|
|
78
|
-
async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
|
|
79
|
-
if self._response is not None:
|
|
80
|
-
if not self._response.closed:
|
|
81
|
-
self._response.close()
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
class RetryClient:
|
|
85
|
-
def __init__(self, logger: Any = None, *args: Any, **kwargs: Any) -> None:
|
|
86
|
-
self._client = ClientSession(*args, **kwargs)
|
|
87
|
-
self._closed = False
|
|
88
|
-
|
|
89
|
-
if logger is None:
|
|
90
|
-
logger = logging.getLogger("aiohttp_retry")
|
|
91
|
-
|
|
92
|
-
self._logger = logger
|
|
93
|
-
|
|
94
|
-
def __del__(self) -> None:
|
|
95
|
-
if not self._closed:
|
|
96
|
-
self._logger.warning("Aiohttp retry client was not closed")
|
|
97
|
-
|
|
98
|
-
@staticmethod
|
|
99
|
-
def _request(request: Callable[..., Any], url: str, **kwargs: Any) -> _RequestContext:
|
|
100
|
-
return _RequestContext(request, url, **kwargs)
|
|
101
|
-
|
|
102
|
-
def get(self, url: str, **kwargs: Any) -> _RequestContext:
|
|
103
|
-
return self._request(self._client.get, url, **kwargs)
|
|
104
|
-
|
|
105
|
-
def options(self, url: str, **kwargs: Any) -> _RequestContext:
|
|
106
|
-
return self._request(self._client.options, url, **kwargs)
|
|
107
|
-
|
|
108
|
-
def head(self, url: str, **kwargs: Any) -> _RequestContext:
|
|
109
|
-
return self._request(self._client.head, url, **kwargs)
|
|
110
|
-
|
|
111
|
-
def post(self, url: str, **kwargs: Any) -> _RequestContext:
|
|
112
|
-
return self._request(self._client.post, url, **kwargs)
|
|
113
|
-
|
|
114
|
-
def put(self, url: str, **kwargs: Any) -> _RequestContext:
|
|
115
|
-
return self._request(self._client.put, url, **kwargs)
|
|
116
|
-
|
|
117
|
-
def patch(self, url: str, **kwargs: Any) -> _RequestContext:
|
|
118
|
-
return self._request(self._client.patch, url, **kwargs)
|
|
119
|
-
|
|
120
|
-
def delete(self, url: str, **kwargs: Any) -> _RequestContext:
|
|
121
|
-
return self._request(self._client.delete, url, **kwargs)
|
|
122
|
-
|
|
123
|
-
async def close(self) -> None:
|
|
124
|
-
await self._client.close()
|
|
125
|
-
self._closed = True
|
|
126
|
-
|
|
127
|
-
async def __aenter__(self) -> 'RetryClient':
|
|
128
|
-
return self
|
|
129
|
-
|
|
130
|
-
async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
|
|
131
|
-
await self.close()
|
|
1
|
+
# from https://pypi.org/project/aiohttp-retry/ with modification to python 3.5.4
|
|
2
|
+
import asyncio
|
|
3
|
+
import logging
|
|
4
|
+
from aiohttp import ClientSession, ClientResponse
|
|
5
|
+
from typing import Any, Callable, Optional, Set, Type
|
|
6
|
+
|
|
7
|
+
# Options
|
|
8
|
+
_RETRY_ATTEMPTS = 3
|
|
9
|
+
_RETRY_START_TIMEOUT = 0.1
|
|
10
|
+
_RETRY_MAX_TIMEOUT = 30
|
|
11
|
+
_RETRY_FACTOR = 2
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class _RequestContext:
|
|
15
|
+
def __init__(self, request: Callable[..., Any], # Request operation, like POST or GET
|
|
16
|
+
url: str, # Just url
|
|
17
|
+
retry_attempts: int = _RETRY_ATTEMPTS, # How many times we should retry
|
|
18
|
+
retry_start_timeout: float = _RETRY_START_TIMEOUT, # Base timeout time, then it exponentially grow
|
|
19
|
+
retry_max_timeout: float = _RETRY_MAX_TIMEOUT, # Max possible timeout between tries
|
|
20
|
+
retry_factor: float = _RETRY_FACTOR, # How much we increase timeout each time
|
|
21
|
+
retry_for_statuses: Optional[Set[int]] = None, # On which statuses we should retry
|
|
22
|
+
retry_exceptions: Optional[Set[Type]] = None, # On which exceptions we should retry
|
|
23
|
+
**kwargs: Any
|
|
24
|
+
) -> None:
|
|
25
|
+
self._request = request
|
|
26
|
+
self._url = url
|
|
27
|
+
|
|
28
|
+
self._retry_attempts = retry_attempts
|
|
29
|
+
self._retry_start_timeout = retry_start_timeout
|
|
30
|
+
self._retry_max_timeout = retry_max_timeout
|
|
31
|
+
self._retry_factor = retry_factor
|
|
32
|
+
|
|
33
|
+
if retry_for_statuses is None:
|
|
34
|
+
retry_for_statuses = set()
|
|
35
|
+
self._retry_for_statuses = retry_for_statuses
|
|
36
|
+
|
|
37
|
+
if retry_exceptions is None:
|
|
38
|
+
retry_exceptions = set()
|
|
39
|
+
self._retry_exceptions = retry_exceptions
|
|
40
|
+
|
|
41
|
+
self._kwargs = kwargs
|
|
42
|
+
|
|
43
|
+
self._current_attempt = 0
|
|
44
|
+
self._response = None
|
|
45
|
+
|
|
46
|
+
def _exponential_timeout(self) -> float:
|
|
47
|
+
timeout = self._retry_start_timeout * (self._retry_factor ** (self._current_attempt - 1))
|
|
48
|
+
return min(timeout, self._retry_max_timeout)
|
|
49
|
+
|
|
50
|
+
def _check_code(self, code: int) -> bool:
|
|
51
|
+
return 500 <= code <= 599 or code in self._retry_for_statuses
|
|
52
|
+
|
|
53
|
+
async def _do_request(self) -> ClientResponse:
|
|
54
|
+
try:
|
|
55
|
+
self._current_attempt += 1
|
|
56
|
+
response = await self._request(url=self._url, **self._kwargs)
|
|
57
|
+
code = response.status
|
|
58
|
+
if self._current_attempt < self._retry_attempts and self._check_code(code):
|
|
59
|
+
retry_wait = self._exponential_timeout()
|
|
60
|
+
await asyncio.sleep(retry_wait)
|
|
61
|
+
return await self._do_request()
|
|
62
|
+
self._response = response
|
|
63
|
+
return response
|
|
64
|
+
|
|
65
|
+
except Exception as e:
|
|
66
|
+
retry_wait = self._exponential_timeout()
|
|
67
|
+
if self._current_attempt < self._retry_attempts:
|
|
68
|
+
for exc in self._retry_exceptions:
|
|
69
|
+
if isinstance(e, exc):
|
|
70
|
+
await asyncio.sleep(retry_wait)
|
|
71
|
+
return await self._do_request()
|
|
72
|
+
|
|
73
|
+
raise e
|
|
74
|
+
|
|
75
|
+
async def __aenter__(self) -> ClientResponse:
|
|
76
|
+
return await self._do_request()
|
|
77
|
+
|
|
78
|
+
async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
|
|
79
|
+
if self._response is not None:
|
|
80
|
+
if not self._response.closed:
|
|
81
|
+
self._response.close()
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class RetryClient:
|
|
85
|
+
def __init__(self, logger: Any = None, *args: Any, **kwargs: Any) -> None:
|
|
86
|
+
self._client = ClientSession(*args, **kwargs)
|
|
87
|
+
self._closed = False
|
|
88
|
+
|
|
89
|
+
if logger is None:
|
|
90
|
+
logger = logging.getLogger("aiohttp_retry")
|
|
91
|
+
|
|
92
|
+
self._logger = logger
|
|
93
|
+
|
|
94
|
+
def __del__(self) -> None:
|
|
95
|
+
if not self._closed:
|
|
96
|
+
self._logger.warning("Aiohttp retry client was not closed")
|
|
97
|
+
|
|
98
|
+
@staticmethod
|
|
99
|
+
def _request(request: Callable[..., Any], url: str, **kwargs: Any) -> _RequestContext:
|
|
100
|
+
return _RequestContext(request, url, **kwargs)
|
|
101
|
+
|
|
102
|
+
def get(self, url: str, **kwargs: Any) -> _RequestContext:
|
|
103
|
+
return self._request(self._client.get, url, **kwargs)
|
|
104
|
+
|
|
105
|
+
def options(self, url: str, **kwargs: Any) -> _RequestContext:
|
|
106
|
+
return self._request(self._client.options, url, **kwargs)
|
|
107
|
+
|
|
108
|
+
def head(self, url: str, **kwargs: Any) -> _RequestContext:
|
|
109
|
+
return self._request(self._client.head, url, **kwargs)
|
|
110
|
+
|
|
111
|
+
def post(self, url: str, **kwargs: Any) -> _RequestContext:
|
|
112
|
+
return self._request(self._client.post, url, **kwargs)
|
|
113
|
+
|
|
114
|
+
def put(self, url: str, **kwargs: Any) -> _RequestContext:
|
|
115
|
+
return self._request(self._client.put, url, **kwargs)
|
|
116
|
+
|
|
117
|
+
def patch(self, url: str, **kwargs: Any) -> _RequestContext:
|
|
118
|
+
return self._request(self._client.patch, url, **kwargs)
|
|
119
|
+
|
|
120
|
+
def delete(self, url: str, **kwargs: Any) -> _RequestContext:
|
|
121
|
+
return self._request(self._client.delete, url, **kwargs)
|
|
122
|
+
|
|
123
|
+
async def close(self) -> None:
|
|
124
|
+
await self._client.close()
|
|
125
|
+
self._closed = True
|
|
126
|
+
|
|
127
|
+
async def __aenter__(self) -> 'RetryClient':
|
|
128
|
+
return self
|
|
129
|
+
|
|
130
|
+
async def __aexit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
|
|
131
|
+
await self.close()
|