testit-python-commons 3.11.2.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.
Files changed (52) hide show
  1. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/PKG-INFO +2 -2
  2. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/setup.py +2 -2
  3. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/client/api_client.py +83 -13
  4. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/client/helpers/bulk_autotest_helper.py +31 -7
  5. testit_python_commons-3.11.4.post560/src/testit_python_commons/services/retry.py +92 -0
  6. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons.egg-info/PKG-INFO +2 -2
  7. testit_python_commons-3.11.4.post560/src/testit_python_commons.egg-info/requires.txt +3 -0
  8. testit_python_commons-3.11.2.post560/src/testit_python_commons/services/retry.py +0 -29
  9. testit_python_commons-3.11.2.post560/src/testit_python_commons.egg-info/requires.txt +0 -3
  10. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/README.md +0 -0
  11. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/setup.cfg +0 -0
  12. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit.py +0 -0
  13. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/__init__.py +0 -0
  14. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/app_properties.py +0 -0
  15. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/client/__init__.py +0 -0
  16. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/client/client_configuration.py +0 -0
  17. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/client/converter.py +0 -0
  18. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/client/helpers/__init__.py +0 -0
  19. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/client/helpers/threads_manager.py +0 -0
  20. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/client/models/__init__.py +0 -0
  21. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/client/models/threads_for_create_and_result.py +0 -0
  22. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/client/models/threads_for_update_and_result.py +0 -0
  23. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/decorators.py +0 -0
  24. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/dynamic_methods.py +0 -0
  25. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/models/__init__.py +0 -0
  26. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/models/adapter_mode.py +0 -0
  27. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/models/fixture.py +0 -0
  28. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/models/link.py +0 -0
  29. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/models/link_type.py +0 -0
  30. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/models/outcome_type.py +0 -0
  31. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/models/step_result.py +0 -0
  32. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/models/test_result.py +0 -0
  33. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/models/test_result_with_all_fixture_step_results_model.py +0 -0
  34. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/services/__init__.py +0 -0
  35. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/services/adapter_manager.py +0 -0
  36. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/services/adapter_manager_configuration.py +0 -0
  37. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/services/fixture_manager.py +0 -0
  38. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/services/fixture_storage.py +0 -0
  39. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/services/logger.py +0 -0
  40. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/services/plugin_manager.py +0 -0
  41. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/services/step_manager.py +0 -0
  42. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/services/step_result_storage.py +0 -0
  43. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/services/utils.py +0 -0
  44. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/step.py +0 -0
  45. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/utils/__init__.py +0 -0
  46. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons/utils/html_escape_utils.py +0 -0
  47. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons.egg-info/SOURCES.txt +0 -0
  48. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons.egg-info/dependency_links.txt +0 -0
  49. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/src/testit_python_commons.egg-info/top_level.txt +0 -0
  50. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/tests/test_app_properties.py +0 -0
  51. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/tests/test_dynamic_methods.py +0 -0
  52. {testit_python_commons-3.11.2.post560 → testit_python_commons-3.11.4.post560}/tests/test_html_escape_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: testit-python-commons
3
- Version: 3.11.2.post560
3
+ Version: 3.11.4.post560
4
4
  Summary: Python commons for Test IT
5
5
  Home-page: https://github.com/testit-tms/adapters-python/
6
6
  Author: Integration team
@@ -17,7 +17,7 @@ Classifier: Programming Language :: Python :: 3.12
17
17
  Description-Content-Type: text/markdown
18
18
  Requires-Dist: pluggy
19
19
  Requires-Dist: tomli
20
- Requires-Dist: testit-api-client==7.4.0.post560
20
+ Requires-Dist: testit-api-client==7.5.0.post560
21
21
  Dynamic: author
22
22
  Dynamic: author-email
23
23
  Dynamic: classifier
@@ -1,6 +1,6 @@
1
1
  from setuptools import find_packages, setup
2
2
 
3
- VERSION = "3.11.2.post560"
3
+ VERSION = "3.11.4.post560"
4
4
 
5
5
  setup(
6
6
  name='testit-python-commons',
@@ -25,5 +25,5 @@ setup(
25
25
  py_modules=['testit', 'testit_python_commons'],
26
26
  packages=find_packages(where='src'),
27
27
  package_dir={'': 'src'},
28
- install_requires=['pluggy', 'tomli', 'testit-api-client==7.4.0.post560']
28
+ install_requires=['pluggy', 'tomli', 'testit-api-client==7.5.0.post560']
29
29
  )
@@ -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 retry
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
- @retry
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
- self.__autotest_api.delete_auto_test_link_from_work_item(
366
- id=autotest_global_id,
367
- work_item_id=work_item_id)
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
- self.__autotest_api.link_auto_test_to_work_item(
375
- autotest_global_id,
376
- link_auto_test_to_work_item_request=LinkAutoTestToWorkItemRequest(id=work_item_id))
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
- logging.error(f'Cannot update test result with id "{test_result.get_test_result_id()}" status: {exc}')
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
- attachment_response = self.__attachments_api.api_v2_attachments_post(file=open(path, "rb"))
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
- from testit_python_commons.services.retry import retry
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
- self.__autotests_api.delete_auto_test_link_from_work_item(
190
- id=autotest_global_id,
191
- work_item_id=work_item_id)
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
- self.__autotests_api.link_auto_test_to_work_item(
200
- autotest_global_id,
201
- link_auto_test_to_work_item_request=LinkAutoTestToWorkItemRequest(id=work_item_id))
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: testit-python-commons
3
- Version: 3.11.2.post560
3
+ Version: 3.11.4.post560
4
4
  Summary: Python commons for Test IT
5
5
  Home-page: https://github.com/testit-tms/adapters-python/
6
6
  Author: Integration team
@@ -17,7 +17,7 @@ Classifier: Programming Language :: Python :: 3.12
17
17
  Description-Content-Type: text/markdown
18
18
  Requires-Dist: pluggy
19
19
  Requires-Dist: tomli
20
- Requires-Dist: testit-api-client==7.4.0.post560
20
+ Requires-Dist: testit-api-client==7.5.0.post560
21
21
  Dynamic: author
22
22
  Dynamic: author-email
23
23
  Dynamic: classifier
@@ -0,0 +1,3 @@
1
+ pluggy
2
+ tomli
3
+ testit-api-client==7.5.0.post560
@@ -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
@@ -1,3 +0,0 @@
1
- pluggy
2
- tomli
3
- testit-api-client==7.4.0.post560