[Cronet] Delay StartNetLog and StopNetLog until native request context is initialized
[chromium-blink-merge.git] / build / android / pylib / device / decorators.py
blob074a0fcac14131abe15fc3cdbf719c15849f7908
1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 """
6 Function/method decorators that provide timeout and retry logic.
7 """
9 import functools
10 import os
11 import sys
12 import threading
14 from pylib import constants
15 from pylib.device import device_errors
16 from pylib.utils import reraiser_thread
17 from pylib.utils import timeout_retry
19 # TODO(jbudorick) Remove once the DeviceUtils implementations are no longer
20 # backed by AndroidCommands / android_testrunner.
21 sys.path.append(os.path.join(constants.DIR_SOURCE_ROOT, 'third_party',
22 'android_testrunner'))
23 import errors as old_errors
25 DEFAULT_TIMEOUT_ATTR = '_default_timeout'
26 DEFAULT_RETRIES_ATTR = '_default_retries'
29 def _TimeoutRetryWrapper(f, timeout_func, retries_func, pass_values=False):
30 """ Wraps a funcion with timeout and retry handling logic.
32 Args:
33 f: The function to wrap.
34 timeout_func: A callable that returns the timeout value.
35 retries_func: A callable that returns the retries value.
36 pass_values: If True, passes the values returned by |timeout_func| and
37 |retries_func| to the wrapped function as 'timeout' and
38 'retries' kwargs, respectively.
39 Returns:
40 The wrapped function.
41 """
42 @functools.wraps(f)
43 def TimeoutRetryWrapper(*args, **kwargs):
44 timeout = timeout_func(*args, **kwargs)
45 retries = retries_func(*args, **kwargs)
46 if pass_values:
47 kwargs['timeout'] = timeout
48 kwargs['retries'] = retries
49 def impl():
50 return f(*args, **kwargs)
51 try:
52 if isinstance(threading.current_thread(),
53 timeout_retry.TimeoutRetryThread):
54 return impl()
55 else:
56 return timeout_retry.Run(impl, timeout, retries)
57 except old_errors.WaitForResponseTimedOutError as e:
58 raise device_errors.CommandTimeoutError(str(e)), None, (
59 sys.exc_info()[2])
60 except old_errors.DeviceUnresponsiveError as e:
61 raise device_errors.DeviceUnreachableError(str(e)), None, (
62 sys.exc_info()[2])
63 except reraiser_thread.TimeoutError as e:
64 raise device_errors.CommandTimeoutError(str(e)), None, (
65 sys.exc_info()[2])
66 return TimeoutRetryWrapper
69 def WithTimeoutAndRetries(f):
70 """A decorator that handles timeouts and retries.
72 'timeout' and 'retries' kwargs must be passed to the function.
74 Args:
75 f: The function to decorate.
76 Returns:
77 The decorated function.
78 """
79 get_timeout = lambda *a, **kw: kw['timeout']
80 get_retries = lambda *a, **kw: kw['retries']
81 return _TimeoutRetryWrapper(f, get_timeout, get_retries)
84 def WithExplicitTimeoutAndRetries(timeout, retries):
85 """Returns a decorator that handles timeouts and retries.
87 The provided |timeout| and |retries| values are always used.
89 Args:
90 timeout: The number of seconds to wait for the decorated function to
91 return. Always used.
92 retries: The number of times the decorated function should be retried on
93 failure. Always used.
94 Returns:
95 The actual decorator.
96 """
97 def decorator(f):
98 get_timeout = lambda *a, **kw: timeout
99 get_retries = lambda *a, **kw: retries
100 return _TimeoutRetryWrapper(f, get_timeout, get_retries)
101 return decorator
104 def WithTimeoutAndRetriesDefaults(default_timeout, default_retries):
105 """Returns a decorator that handles timeouts and retries.
107 The provided |default_timeout| and |default_retries| values are used only
108 if timeout and retries values are not provided.
110 Args:
111 default_timeout: The number of seconds to wait for the decorated function
112 to return. Only used if a 'timeout' kwarg is not passed
113 to the decorated function.
114 default_retries: The number of times the decorated function should be
115 retried on failure. Only used if a 'retries' kwarg is not
116 passed to the decorated function.
117 Returns:
118 The actual decorator.
120 def decorator(f):
121 get_timeout = lambda *a, **kw: kw.get('timeout', default_timeout)
122 get_retries = lambda *a, **kw: kw.get('retries', default_retries)
123 return _TimeoutRetryWrapper(f, get_timeout, get_retries, pass_values=True)
124 return decorator
127 def WithTimeoutAndRetriesFromInstance(
128 default_timeout_name=DEFAULT_TIMEOUT_ATTR,
129 default_retries_name=DEFAULT_RETRIES_ATTR):
130 """Returns a decorator that handles timeouts and retries.
132 The provided |default_timeout_name| and |default_retries_name| are used to
133 get the default timeout value and the default retries value from the object
134 instance if timeout and retries values are not provided.
136 Note that this should only be used to decorate methods, not functions.
138 Args:
139 default_timeout_name: The name of the default timeout attribute of the
140 instance.
141 default_retries_name: The name of the default retries attribute of the
142 instance.
143 Returns:
144 The actual decorator.
146 def decorator(f):
147 def get_timeout(inst, *_args, **kwargs):
148 return kwargs.get('timeout', getattr(inst, default_timeout_name))
149 def get_retries(inst, *_args, **kwargs):
150 return kwargs.get('retries', getattr(inst, default_retries_name))
151 return _TimeoutRetryWrapper(f, get_timeout, get_retries, pass_values=True)
152 return decorator