58 lines
1.9 KiB
Python
58 lines
1.9 KiB
Python
#
|
|
# Copyright(c) 2021 Intel Corporation
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
#
|
|
|
|
from datetime import datetime, timedelta
|
|
from functools import partial
|
|
|
|
from core.test_run import TestRun
|
|
|
|
|
|
class Retry:
|
|
"""
|
|
The Retry class implements methods designed to retry execution until desired result.
|
|
The func parameter is meant to be a method. If this method needs args/kwargs, they should be
|
|
encapsulated with the method, i.e. using a partial function (an example of this is contained
|
|
within run_command_until_success())
|
|
"""
|
|
@classmethod
|
|
def run_command_until_success(
|
|
cls, command: str, retries: int = None, timeout: timedelta = None
|
|
):
|
|
# encapsulate method and args/kwargs as a partial function
|
|
func = partial(TestRun.executor.run_expect_success, command)
|
|
return cls.run_while_exception(func, retries=retries, timeout=timeout)
|
|
|
|
@classmethod
|
|
def run_while_exception(cls, func, retries: int = None, timeout: timedelta = None):
|
|
result = None
|
|
|
|
def wrapped_func():
|
|
nonlocal result
|
|
try:
|
|
result = func()
|
|
return True
|
|
except:
|
|
return False
|
|
|
|
cls.run_while_false(wrapped_func, retries=retries, timeout=timeout)
|
|
return result
|
|
|
|
@classmethod
|
|
def run_while_false(cls, func, retries: int = None, timeout: timedelta = None):
|
|
if retries is None and timeout is None:
|
|
raise AttributeError("At least one stop condition is required for Retry calls!")
|
|
start = datetime.now()
|
|
retry_calls = 0
|
|
result = func()
|
|
|
|
while not result:
|
|
result = func()
|
|
retry_calls += 1
|
|
if result \
|
|
or (timeout is not None and datetime.now() - start > timeout) \
|
|
or (retries is not None and retry_calls == retries):
|
|
break
|
|
return result
|