testit-python-commons 3.11.3.post560__tar.gz → 3.11.4.post560__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/PKG-INFO +1 -1
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/setup.py +1 -1
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/client/api_client.py +83 -13
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/client/helpers/bulk_autotest_helper.py +31 -7
- testit_python_commons-3.11.4.post560/src/testit_python_commons/services/retry.py +92 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons.egg-info/PKG-INFO +1 -1
- testit_python_commons-3.11.3.post560/src/testit_python_commons/services/retry.py +0 -29
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/README.md +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/setup.cfg +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/__init__.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/app_properties.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/client/__init__.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/client/client_configuration.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/client/converter.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/client/helpers/__init__.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/client/helpers/threads_manager.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/client/models/__init__.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/client/models/threads_for_create_and_result.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/client/models/threads_for_update_and_result.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/decorators.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/dynamic_methods.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/models/__init__.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/models/adapter_mode.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/models/fixture.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/models/link.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/models/link_type.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/models/outcome_type.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/models/step_result.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/models/test_result.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/models/test_result_with_all_fixture_step_results_model.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/services/__init__.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/services/adapter_manager.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/services/adapter_manager_configuration.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/services/fixture_manager.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/services/fixture_storage.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/services/logger.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/services/plugin_manager.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/services/step_manager.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/services/step_result_storage.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/services/utils.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/step.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/utils/__init__.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/utils/html_escape_utils.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons.egg-info/SOURCES.txt +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons.egg-info/dependency_links.txt +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons.egg-info/requires.txt +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons.egg-info/top_level.txt +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/tests/test_app_properties.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/tests/test_dynamic_methods.py +0 -0
- {testit_python_commons-3.11.3.post560 → testit_python_commons-3.11.4.post560}/tests/test_html_escape_utils.py +0 -0
|
@@ -2,6 +2,7 @@ import logging
|
|
|
2
2
|
import os
|
|
3
3
|
from datetime import datetime
|
|
4
4
|
|
|
5
|
+
import testit_api_client
|
|
5
6
|
from testit_api_client import ApiClient, Configuration
|
|
6
7
|
from testit_api_client.apis import AttachmentsApi, AutoTestsApi, TestRunsApi, TestResultsApi, WorkItemsApi
|
|
7
8
|
from testit_api_client.models import (
|
|
@@ -22,7 +23,12 @@ from testit_python_commons.client.converter import Converter
|
|
|
22
23
|
from testit_python_commons.client.helpers.bulk_autotest_helper import BulkAutotestHelper
|
|
23
24
|
from testit_python_commons.models.test_result import TestResult
|
|
24
25
|
from testit_python_commons.services.logger import adapter_logger
|
|
25
|
-
from testit_python_commons.services.retry import
|
|
26
|
+
from testit_python_commons.services.retry import (
|
|
27
|
+
is_non_retriable_api_exception,
|
|
28
|
+
is_retriable_connection_error,
|
|
29
|
+
retry,
|
|
30
|
+
retry_on_connection_error,
|
|
31
|
+
)
|
|
26
32
|
from typing import List
|
|
27
33
|
|
|
28
34
|
|
|
@@ -151,6 +157,7 @@ class ApiClientWorker:
|
|
|
151
157
|
return self.__autotest_api.api_v2_auto_tests_search_post(api_v2_auto_tests_search_post_request=model)
|
|
152
158
|
|
|
153
159
|
@adapter_logger
|
|
160
|
+
@retry
|
|
154
161
|
def write_test(self, test_result: TestResult) -> str:
|
|
155
162
|
model = Converter.project_id_and_external_id_to_auto_tests_search_post_request(
|
|
156
163
|
self.__config.get_project_id(),
|
|
@@ -170,6 +177,7 @@ class ApiClientWorker:
|
|
|
170
177
|
return self.__load_test_result(test_result)
|
|
171
178
|
|
|
172
179
|
@adapter_logger
|
|
180
|
+
@retry
|
|
173
181
|
def write_tests(self, test_results: List[TestResult], fixture_containers: dict) -> None:
|
|
174
182
|
bulk_autotest_helper = BulkAutotestHelper(self.__autotest_api, self.__test_run_api, self.__config)
|
|
175
183
|
|
|
@@ -282,11 +290,20 @@ class ApiClientWorker:
|
|
|
282
290
|
logging.debug(f'Got workitem {work_item}')
|
|
283
291
|
|
|
284
292
|
return work_item.id
|
|
293
|
+
except testit_api_client.exceptions.ApiException as exc:
|
|
294
|
+
if is_retriable_connection_error(exc):
|
|
295
|
+
raise
|
|
296
|
+
if is_non_retriable_api_exception(exc):
|
|
297
|
+
logging.warning(f'Getting workitem by id {work_item_id} status: {exc}')
|
|
298
|
+
return
|
|
299
|
+
raise
|
|
285
300
|
except Exception as exc:
|
|
301
|
+
if is_retriable_connection_error(exc):
|
|
302
|
+
raise
|
|
286
303
|
logging.error(f'Getting workitem by id {work_item_id} status: {exc}')
|
|
287
304
|
|
|
288
305
|
@adapter_logger
|
|
289
|
-
@
|
|
306
|
+
@retry_on_connection_error
|
|
290
307
|
def __get_work_items_linked_to_autotest(self, autotest_global_id: str) -> List[AutoTestWorkItemIdentifierApiResult]:
|
|
291
308
|
return self.__autotest_api.get_work_items_linked_to_auto_test(id=autotest_global_id)
|
|
292
309
|
|
|
@@ -346,6 +363,8 @@ class ApiClientWorker:
|
|
|
346
363
|
try:
|
|
347
364
|
self.__autotest_api.update_auto_test(update_auto_test_request=model)
|
|
348
365
|
except Exception as exc:
|
|
366
|
+
if is_retriable_connection_error(exc):
|
|
367
|
+
raise
|
|
349
368
|
logging.error(f'Cannot update autotest "{test_result.get_autotest_name()}" status: {exc}')
|
|
350
369
|
|
|
351
370
|
logging.debug(f'Autotest "{test_result.get_autotest_name()}" was updated')
|
|
@@ -362,18 +381,40 @@ class ApiClientWorker:
|
|
|
362
381
|
@adapter_logger
|
|
363
382
|
@retry
|
|
364
383
|
def __unlink_test_to_work_item(self, autotest_global_id: str, work_item_id: str) -> None:
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
384
|
+
try:
|
|
385
|
+
self.__autotest_api.delete_auto_test_link_from_work_item(
|
|
386
|
+
id=autotest_global_id,
|
|
387
|
+
work_item_id=work_item_id)
|
|
388
|
+
except testit_api_client.exceptions.ApiException as exc:
|
|
389
|
+
if is_non_retriable_api_exception(exc):
|
|
390
|
+
logging.warning(
|
|
391
|
+
'Cannot unlink autotest %s from work item %s: %s',
|
|
392
|
+
autotest_global_id,
|
|
393
|
+
work_item_id,
|
|
394
|
+
exc,
|
|
395
|
+
)
|
|
396
|
+
return
|
|
397
|
+
raise
|
|
368
398
|
|
|
369
399
|
logging.debug(f'Autotest was unlinked with workItem "{work_item_id}" by global id "{autotest_global_id}')
|
|
370
400
|
|
|
371
401
|
@adapter_logger
|
|
372
402
|
@retry
|
|
373
403
|
def __link_test_to_work_item(self, autotest_global_id: str, work_item_id: str) -> None:
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
404
|
+
try:
|
|
405
|
+
self.__autotest_api.link_auto_test_to_work_item(
|
|
406
|
+
autotest_global_id,
|
|
407
|
+
link_auto_test_to_work_item_request=LinkAutoTestToWorkItemRequest(id=work_item_id))
|
|
408
|
+
except testit_api_client.exceptions.ApiException as exc:
|
|
409
|
+
if is_non_retriable_api_exception(exc):
|
|
410
|
+
logging.warning(
|
|
411
|
+
'Cannot link autotest %s to work item %s: %s',
|
|
412
|
+
autotest_global_id,
|
|
413
|
+
work_item_id,
|
|
414
|
+
exc,
|
|
415
|
+
)
|
|
416
|
+
return
|
|
417
|
+
raise
|
|
377
418
|
|
|
378
419
|
logging.debug(f'Autotest was linked with workItem "{work_item_id}" by global id "{autotest_global_id}')
|
|
379
420
|
|
|
@@ -417,7 +458,17 @@ class ApiClientWorker:
|
|
|
417
458
|
id=test_result.get_test_result_id(),
|
|
418
459
|
api_v2_test_results_id_put_request=model)
|
|
419
460
|
except Exception as exc:
|
|
420
|
-
|
|
461
|
+
if is_retriable_connection_error(exc):
|
|
462
|
+
raise
|
|
463
|
+
logging.error(
|
|
464
|
+
f'Cannot update test result with id "{test_result.get_test_result_id()}" status: {exc}')
|
|
465
|
+
|
|
466
|
+
@adapter_logger
|
|
467
|
+
@retry
|
|
468
|
+
def __upload_attachment(self, path: str) -> AttachmentPutModel:
|
|
469
|
+
with open(path, "rb") as file:
|
|
470
|
+
attachment_response = self.__attachments_api.api_v2_attachments_post(file=file)
|
|
471
|
+
return AttachmentPutModel(attachment_response['id'])
|
|
421
472
|
|
|
422
473
|
@adapter_logger
|
|
423
474
|
def load_attachments(self, attach_paths: list or tuple) -> List[AttachmentPutModel]:
|
|
@@ -426,13 +477,32 @@ class ApiClientWorker:
|
|
|
426
477
|
for path in attach_paths:
|
|
427
478
|
if os.path.isfile(path):
|
|
428
479
|
try:
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
attachments.append(AttachmentPutModel(attachment_response['id']))
|
|
432
|
-
|
|
480
|
+
attachments.append(self.__upload_attachment(path))
|
|
433
481
|
logging.debug(f'Attachment "{path}" was uploaded')
|
|
434
482
|
except Exception as exc:
|
|
483
|
+
if is_retriable_connection_error(exc):
|
|
484
|
+
raise
|
|
435
485
|
logging.error(f'Upload attachment "{path}" status: {exc}')
|
|
436
486
|
else:
|
|
437
487
|
logging.error(f'File "{path}" was not found!')
|
|
438
488
|
return attachments
|
|
489
|
+
|
|
490
|
+
def get_configuration_id(self):
|
|
491
|
+
return self.__config.get_configuration_id()
|
|
492
|
+
|
|
493
|
+
@adapter_logger
|
|
494
|
+
@retry
|
|
495
|
+
def __get_project(self) -> ProjectModel:
|
|
496
|
+
return self.__projects_api.get_project_by_id(id=self.__config.get_project_id())
|
|
497
|
+
|
|
498
|
+
@adapter_logger
|
|
499
|
+
@retry
|
|
500
|
+
def __get_workflow_by_id(self, workflow_id: str) -> WorkflowApiResult:
|
|
501
|
+
return self.__workflows_api.api_v2_workflows_id_get(id=workflow_id)
|
|
502
|
+
|
|
503
|
+
@adapter_logger
|
|
504
|
+
def __get_status_codes(self) -> List[str]:
|
|
505
|
+
project: ProjectModel = self.__get_project()
|
|
506
|
+
workflow: WorkflowApiResult = self.__get_workflow_by_id(project.workflow_id)
|
|
507
|
+
|
|
508
|
+
return [status.code for status in workflow.statuses]
|
|
@@ -18,7 +18,9 @@ from testit_python_commons.client.models import (
|
|
|
18
18
|
ThreadsForUpdateAndResult
|
|
19
19
|
)
|
|
20
20
|
from testit_python_commons.services.logger import adapter_logger
|
|
21
|
-
|
|
21
|
+
import testit_api_client
|
|
22
|
+
|
|
23
|
+
from testit_python_commons.services.retry import is_non_retriable_api_exception, retry
|
|
22
24
|
from testit_python_commons.utils.html_escape_utils import HtmlEscapeUtils
|
|
23
25
|
from typing import Dict, List
|
|
24
26
|
|
|
@@ -186,9 +188,20 @@ class BulkAutotestHelper:
|
|
|
186
188
|
@adapter_logger
|
|
187
189
|
@retry
|
|
188
190
|
def __unlink_test_to_work_item(self, autotest_global_id: str, work_item_id: str):
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
191
|
+
try:
|
|
192
|
+
self.__autotests_api.delete_auto_test_link_from_work_item(
|
|
193
|
+
id=autotest_global_id,
|
|
194
|
+
work_item_id=work_item_id)
|
|
195
|
+
except testit_api_client.exceptions.ApiException as exc:
|
|
196
|
+
if is_non_retriable_api_exception(exc):
|
|
197
|
+
logging.warning(
|
|
198
|
+
'Cannot unlink autotest %s from work item %s: %s',
|
|
199
|
+
autotest_global_id,
|
|
200
|
+
work_item_id,
|
|
201
|
+
exc,
|
|
202
|
+
)
|
|
203
|
+
return
|
|
204
|
+
raise
|
|
192
205
|
|
|
193
206
|
logging.debug(f'Autotest was unlinked with workItem "{work_item_id}" by global id "{autotest_global_id}')
|
|
194
207
|
|
|
@@ -196,9 +209,20 @@ class BulkAutotestHelper:
|
|
|
196
209
|
@adapter_logger
|
|
197
210
|
@retry
|
|
198
211
|
def __link_test_to_work_item(self, autotest_global_id: str, work_item_id: str):
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
212
|
+
try:
|
|
213
|
+
self.__autotests_api.link_auto_test_to_work_item(
|
|
214
|
+
autotest_global_id,
|
|
215
|
+
link_auto_test_to_work_item_request=LinkAutoTestToWorkItemRequest(id=work_item_id))
|
|
216
|
+
except testit_api_client.exceptions.ApiException as exc:
|
|
217
|
+
if is_non_retriable_api_exception(exc):
|
|
218
|
+
logging.warning(
|
|
219
|
+
'Cannot link autotest %s to work item %s: %s',
|
|
220
|
+
autotest_global_id,
|
|
221
|
+
work_item_id,
|
|
222
|
+
exc,
|
|
223
|
+
)
|
|
224
|
+
return
|
|
225
|
+
raise
|
|
202
226
|
|
|
203
227
|
logging.debug(f'Autotest was linked with workItem "{work_item_id}" by global id "{autotest_global_id}')
|
|
204
228
|
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import random
|
|
3
|
+
import time
|
|
4
|
+
from http.client import RemoteDisconnected
|
|
5
|
+
|
|
6
|
+
import testit_api_client
|
|
7
|
+
import urllib3
|
|
8
|
+
|
|
9
|
+
CONNECTION_RETRIES = 3
|
|
10
|
+
CONNECTION_RETRY_DELAY_SEC = 1
|
|
11
|
+
API_EXCEPTION_RETRIES = 10
|
|
12
|
+
NON_RETRIABLE_API_STATUS_CODES = (400, 404)
|
|
13
|
+
|
|
14
|
+
_RETRIABLE_CONNECTION_TYPES = (
|
|
15
|
+
urllib3.exceptions.ProtocolError,
|
|
16
|
+
urllib3.exceptions.NewConnectionError,
|
|
17
|
+
ConnectionError,
|
|
18
|
+
ConnectionResetError,
|
|
19
|
+
ConnectionAbortedError,
|
|
20
|
+
RemoteDisconnected,
|
|
21
|
+
TimeoutError,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def is_non_retriable_api_exception(exc: BaseException) -> bool:
|
|
26
|
+
return (
|
|
27
|
+
isinstance(exc, testit_api_client.exceptions.ApiException)
|
|
28
|
+
and int(exc.status) in NON_RETRIABLE_API_STATUS_CODES
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def is_retriable_connection_error(exc: BaseException) -> bool:
|
|
33
|
+
seen = set()
|
|
34
|
+
current = exc
|
|
35
|
+
while current is not None and id(current) not in seen:
|
|
36
|
+
seen.add(id(current))
|
|
37
|
+
if isinstance(current, _RETRIABLE_CONNECTION_TYPES):
|
|
38
|
+
return True
|
|
39
|
+
current = current.__cause__ or current.__context__
|
|
40
|
+
return False
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _execute_with_connection_retries(func, args, kwargs):
|
|
44
|
+
connection_attempts = 0
|
|
45
|
+
|
|
46
|
+
while True:
|
|
47
|
+
try:
|
|
48
|
+
return func(*args, **kwargs)
|
|
49
|
+
except BaseException as e:
|
|
50
|
+
if not is_retriable_connection_error(e):
|
|
51
|
+
raise
|
|
52
|
+
|
|
53
|
+
connection_attempts += 1
|
|
54
|
+
logging.warning(
|
|
55
|
+
'Connection error in %s (attempt %d/%d): %s',
|
|
56
|
+
func.__name__,
|
|
57
|
+
connection_attempts,
|
|
58
|
+
CONNECTION_RETRIES,
|
|
59
|
+
e,
|
|
60
|
+
)
|
|
61
|
+
if connection_attempts > CONNECTION_RETRIES:
|
|
62
|
+
raise
|
|
63
|
+
|
|
64
|
+
time.sleep(CONNECTION_RETRY_DELAY_SEC)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def retry_on_connection_error(func):
|
|
68
|
+
def retry_wrapper(*args, **kwargs):
|
|
69
|
+
return _execute_with_connection_retries(func, args, kwargs)
|
|
70
|
+
|
|
71
|
+
return retry_wrapper
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def retry(func):
|
|
75
|
+
def retry_wrapper(*args, **kwargs):
|
|
76
|
+
api_attempts = 0
|
|
77
|
+
|
|
78
|
+
while True:
|
|
79
|
+
try:
|
|
80
|
+
return _execute_with_connection_retries(func, args, kwargs)
|
|
81
|
+
except testit_api_client.exceptions.ApiException as e:
|
|
82
|
+
if is_non_retriable_api_exception(e):
|
|
83
|
+
raise
|
|
84
|
+
|
|
85
|
+
api_attempts += 1
|
|
86
|
+
logging.error(e)
|
|
87
|
+
if api_attempts >= API_EXCEPTION_RETRIES:
|
|
88
|
+
raise
|
|
89
|
+
|
|
90
|
+
time.sleep(random.randrange(0, 100) / 100)
|
|
91
|
+
|
|
92
|
+
return retry_wrapper
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
import random
|
|
3
|
-
import time
|
|
4
|
-
|
|
5
|
-
import testit_api_client
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def retry(func):
|
|
9
|
-
def retry_wrapper(*args, **kwargs):
|
|
10
|
-
attempts = 0
|
|
11
|
-
retries = 10
|
|
12
|
-
|
|
13
|
-
while attempts < retries:
|
|
14
|
-
try:
|
|
15
|
-
return func(*args, **kwargs)
|
|
16
|
-
except testit_api_client.exceptions.ApiException as e:
|
|
17
|
-
sleep_time = random.randrange(0, 100)
|
|
18
|
-
time.sleep(sleep_time/100)
|
|
19
|
-
attempts += 1
|
|
20
|
-
|
|
21
|
-
logging.error(e)
|
|
22
|
-
if e.status == '404':
|
|
23
|
-
attempts = retries
|
|
24
|
-
return
|
|
25
|
-
if e.status == '400':
|
|
26
|
-
attempts = retries
|
|
27
|
-
return
|
|
28
|
-
|
|
29
|
-
return retry_wrapper
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|