1 # Copyright (C) 2012 W. Trevor King <wking@tremily.us>
3 # This file is part of rss2email.
5 # rss2email is free software: you can redistribute it and/or modify it under
6 # the terms of the GNU General Public License as published by the Free Software
7 # Foundation, either version 2 of the License, or (at your option) version 3 of
10 # rss2email is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License along with
15 # rss2email. If not, see <http://www.gnu.org/licenses/>.
21 import threading as _threading
23 from . import error as _error
26 class TimeLimitedFunction (_threading.Thread):
27 """Run `function` with a time limit of `timeout` seconds.
30 >>> def sleeping_return(sleep, x):
33 >>> TimeLimitedFunction(0.5, sleeping_return)(0.1, 'x')
35 >>> TimeLimitedFunction(0.5, sleeping_return)(10, 'y')
36 Traceback (most recent call last):
38 rss2email.error.TimeoutError: 0.5 second timeout exceeded
39 >>> TimeLimitedFunction(0.5, time.sleep)('x')
40 Traceback (most recent call last):
42 rss2email.error.TimeoutError: error while running time limited function: a float is required
44 def __init__(self, timeout, target, **kwargs):
45 super(TimeLimitedFunction, self).__init__(target=target, **kwargs)
46 self.setDaemon(True) # daemon kwarg only added in Python 3.3.
47 self.timeout = timeout
52 """Based on Thread.run().
54 We add handling for self.result and self.error.
58 self.result = self._target(*self._args, **self._kwargs)
60 self.error = _sys.exc_info()
62 # Avoid a refcycle if the thread is running a function with
63 # an argument that has a member that points to the thread.
64 del self._target, self._args, self._kwargs
66 def __call__(self, *args, **kwargs):
70 self.join(self.timeout)
72 raise _error.TimeoutError(
73 time_limited_function=self) from self.error[1]
75 raise _error.TimeoutError(time_limited_function=self)