Robot Framework
__init__.py
Go to the documentation of this file.
1 # Copyright 2008-2015 Nokia Networks
2 # Copyright 2016- Robot Framework Foundation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 
16 import time
17 
18 from robot.utils import Sortable, secs_to_timestr, timestr_to_secs, WINDOWS
19 from robot.errors import TimeoutError, DataError, FrameworkError
20 
21 if WINDOWS:
22  from .windows import Timeout
23 else:
24  from .posix import Timeout
25 
26 
27 class _Timeout(Sortable):
28 
29  def __init__(self, timeout=None, variables=None):
30  self.stringstring = timeout or ''
31  self.secssecs = -1
32  self.starttimestarttime = -1
33  self.errorerror = None
34  if variables:
35  self.replace_variablesreplace_variables(variables)
36 
37  @property
38  active = property
39 
40  def active(self):
41  return self.starttimestarttime > 0
42 
43  def replace_variables(self, variables):
44  try:
45  self.stringstring = variables.replace_string(self.stringstring)
46  if not self:
47  return
48  self.secssecs = timestr_to_secs(self.stringstring)
49  self.stringstring = secs_to_timestr(self.secssecs)
50  except (DataError, ValueError) as err:
51  self.secssecs = 0.000001 # to make timeout active
52  self.errorerror = ('Setting %s timeout failed: %s' % (self.type.lower(), err))
53 
54  def start(self):
55  if self.secssecs > 0:
56  self.starttimestarttime = time.time()
57 
58  def time_left(self):
59  if not self.activeactiveactive:
60  return -1
61  elapsed = time.time() - self.starttimestarttime
62  # Timeout granularity is 1ms. Without rounding some timeout tests fail
63  # intermittently on Windows, probably due to threading.Event.wait().
64  return round(self.secssecs - elapsed, 3)
65 
66  def timed_out(self):
67  return self.activeactiveactive and self.time_lefttime_left() <= 0
68 
69  def run(self, runnable, args=None, kwargs=None):
70  if self.errorerror:
71  raise DataError(self.errorerror)
72  if not self.activeactiveactive:
73  raise FrameworkError('Timeout is not active')
74  timeout = self.time_lefttime_left()
75  error = TimeoutError(self._timeout_error_timeout_error_timeout_error,
76  test_timeout=isinstance(self, TestTimeout))
77  if timeout <= 0:
78  raise error
79  executable = lambda: runnable(*(args or ()), **(kwargs or {}))
80  return Timeout(timeout, error).execute(executable)
81 
82  def get_message(self):
83  if not self.activeactiveactive:
84  return '%s timeout not active.' % self.type
85  if not self.timed_outtimed_out():
86  return '%s timeout %s active. %s seconds left.' \
87  % (self.type, self.stringstring, self.time_lefttime_left())
88  return self._timeout_error_timeout_error_timeout_error
89 
90  @property
91  _timeout_error = property
92 
93  def _timeout_error(self):
94  return '%s timeout %s exceeded.' % (self.type, self.stringstring)
95 
96  def __str__(self):
97  return self.stringstring
98 
99  def __bool__(self):
100  return bool(self.stringstring and self.stringstring.upper() != 'NONE')
101 
102  @property
103  _sort_key = property
104 
105  def _sort_key(self):
106  return not self.activeactiveactive, self.time_lefttime_left()
107 
108  def __eq__(self, other):
109  return self is other
110 
111  def __hash__(self):
112  return id(self)
113 
114 
116  type = 'Test'
117 
120  _keyword_timeout_occurred = False
121 
122  def __init__(self, timeout=None, variables=None, rpa=False):
123  if rpa:
124  self.typetypetype = 'Task'
125  _Timeout.__init__(self, timeout, variables)
126 
127  def set_keyword_timeout(self, timeout_occurred):
128  if timeout_occurred:
129  self._keyword_timeout_occurred_keyword_timeout_occurred_keyword_timeout_occurred = True
130 
132  return self.timed_outtimed_out() or self._keyword_timeout_occurred_keyword_timeout_occurred_keyword_timeout_occurred
133 
134 
136  type = 'Keyword'
Can be used when the core framework goes to unexpected state.
Definition: errors.py:53
Used when a test or keyword timeout occurs.
Definition: errors.py:93
def __init__(self, timeout=None, variables=None, rpa=False)
Definition: __init__.py:122
def set_keyword_timeout(self, timeout_occurred)
Definition: __init__.py:127
def run(self, runnable, args=None, kwargs=None)
Definition: __init__.py:69
def replace_variables(self, variables)
Definition: __init__.py:43
def __init__(self, timeout=None, variables=None)
Definition: __init__.py:29
def secs_to_timestr(secs, compact=False)
Converts time in seconds to a string representation.
Definition: robottime.py:151
def timestr_to_secs(timestr, round_to=3, accept_plain_values=True)
Parses time strings like '1h 10s', '01:00:10' and '42' and returns seconds.
Definition: robottime.py:55