| Index: build/android/pylib/device/decorators.py
|
| diff --git a/build/android/pylib/device/decorators.py b/build/android/pylib/device/decorators.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..73c13da8b09b9c0c2ffe6053f6fac529801ed997
|
| --- /dev/null
|
| +++ b/build/android/pylib/device/decorators.py
|
| @@ -0,0 +1,157 @@
|
| +# Copyright 2014 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +"""
|
| +Function/method decorators that provide timeout and retry logic.
|
| +"""
|
| +
|
| +import functools
|
| +import os
|
| +import sys
|
| +import threading
|
| +
|
| +from pylib import cmd_helper
|
| +from pylib import constants
|
| +from pylib.device import device_errors
|
| +from pylib.utils import reraiser_thread
|
| +from pylib.utils import timeout_retry
|
| +
|
| +# TODO(jbudorick) Remove once the DeviceUtils implementations are no longer
|
| +# backed by AndroidCommands / android_testrunner.
|
| +sys.path.append(os.path.join(constants.DIR_SOURCE_ROOT, 'third_party',
|
| + 'android_testrunner'))
|
| +import errors as old_errors
|
| +
|
| +DEFAULT_TIMEOUT_ATTR = '_default_timeout'
|
| +DEFAULT_RETRIES_ATTR = '_default_retries'
|
| +
|
| +
|
| +def _TimeoutRetryWrapper(f, timeout_func, retries_func, pass_values=False):
|
| + """ Wraps a funcion with timeout and retry handling logic.
|
| +
|
| + Args:
|
| + f: The function to wrap.
|
| + timeout_func: A callable that returns the timeout value.
|
| + retries_func: A callable that returns the retries value.
|
| + pass_values: If True, passes the values returned by |timeout_func| and
|
| + |retries_func| to the wrapped function as 'timeout' and
|
| + 'retries' kwargs, respectively.
|
| + Returns:
|
| + The wrapped function.
|
| + """
|
| + @functools.wraps(f)
|
| + def TimeoutRetryWrapper(*args, **kwargs):
|
| + timeout = timeout_func(*args, **kwargs)
|
| + retries = retries_func(*args, **kwargs)
|
| + if pass_values:
|
| + kwargs['timeout'] = timeout
|
| + kwargs['retries'] = retries
|
| + def impl():
|
| + return f(*args, **kwargs)
|
| + try:
|
| + if isinstance(threading.current_thread(),
|
| + timeout_retry.TimeoutRetryThread):
|
| + return impl()
|
| + else:
|
| + return timeout_retry.Run(impl, timeout, retries)
|
| + except old_errors.WaitForResponseTimedOutError as e:
|
| + raise device_errors.CommandTimeoutError(str(e)), None, (
|
| + sys.exc_info()[2])
|
| + except old_errors.DeviceUnresponsiveError as e:
|
| + raise device_errors.DeviceUnreachableError(str(e)), None, (
|
| + sys.exc_info()[2])
|
| + except reraiser_thread.TimeoutError as e:
|
| + raise device_errors.CommandTimeoutError(str(e)), None, (
|
| + sys.exc_info()[2])
|
| + except cmd_helper.TimeoutError as e:
|
| + raise device_errors.CommandTimeoutError(str(e)), None, (
|
| + sys.exc_info()[2])
|
| + return TimeoutRetryWrapper
|
| +
|
| +
|
| +def WithTimeoutAndRetries(f):
|
| + """A decorator that handles timeouts and retries.
|
| +
|
| + 'timeout' and 'retries' kwargs must be passed to the function.
|
| +
|
| + Args:
|
| + f: The function to decorate.
|
| + Returns:
|
| + The decorated function.
|
| + """
|
| + get_timeout = lambda *a, **kw: kw['timeout']
|
| + get_retries = lambda *a, **kw: kw['retries']
|
| + return _TimeoutRetryWrapper(f, get_timeout, get_retries)
|
| +
|
| +
|
| +def WithExplicitTimeoutAndRetries(timeout, retries):
|
| + """Returns a decorator that handles timeouts and retries.
|
| +
|
| + The provided |timeout| and |retries| values are always used.
|
| +
|
| + Args:
|
| + timeout: The number of seconds to wait for the decorated function to
|
| + return. Always used.
|
| + retries: The number of times the decorated function should be retried on
|
| + failure. Always used.
|
| + Returns:
|
| + The actual decorator.
|
| + """
|
| + def decorator(f):
|
| + get_timeout = lambda *a, **kw: timeout
|
| + get_retries = lambda *a, **kw: retries
|
| + return _TimeoutRetryWrapper(f, get_timeout, get_retries)
|
| + return decorator
|
| +
|
| +
|
| +def WithTimeoutAndRetriesDefaults(default_timeout, default_retries):
|
| + """Returns a decorator that handles timeouts and retries.
|
| +
|
| + The provided |default_timeout| and |default_retries| values are used only
|
| + if timeout and retries values are not provided.
|
| +
|
| + Args:
|
| + default_timeout: The number of seconds to wait for the decorated function
|
| + to return. Only used if a 'timeout' kwarg is not passed
|
| + to the decorated function.
|
| + default_retries: The number of times the decorated function should be
|
| + retried on failure. Only used if a 'retries' kwarg is not
|
| + passed to the decorated function.
|
| + Returns:
|
| + The actual decorator.
|
| + """
|
| + def decorator(f):
|
| + get_timeout = lambda *a, **kw: kw.get('timeout', default_timeout)
|
| + get_retries = lambda *a, **kw: kw.get('retries', default_retries)
|
| + return _TimeoutRetryWrapper(f, get_timeout, get_retries, pass_values=True)
|
| + return decorator
|
| +
|
| +
|
| +def WithTimeoutAndRetriesFromInstance(
|
| + default_timeout_name=DEFAULT_TIMEOUT_ATTR,
|
| + default_retries_name=DEFAULT_RETRIES_ATTR):
|
| + """Returns a decorator that handles timeouts and retries.
|
| +
|
| + The provided |default_timeout_name| and |default_retries_name| are used to
|
| + get the default timeout value and the default retries value from the object
|
| + instance if timeout and retries values are not provided.
|
| +
|
| + Note that this should only be used to decorate methods, not functions.
|
| +
|
| + Args:
|
| + default_timeout_name: The name of the default timeout attribute of the
|
| + instance.
|
| + default_retries_name: The name of the default retries attribute of the
|
| + instance.
|
| + Returns:
|
| + The actual decorator.
|
| + """
|
| + def decorator(f):
|
| + def get_timeout(inst, *_args, **kwargs):
|
| + return kwargs.get('timeout', getattr(inst, default_timeout_name))
|
| + def get_retries(inst, *_args, **kwargs):
|
| + return kwargs.get('retries', getattr(inst, default_retries_name))
|
| + return _TimeoutRetryWrapper(f, get_timeout, get_retries, pass_values=True)
|
| + return decorator
|
| +
|
|
|