Compare commits

...

92 Commits

Author SHA1 Message Date
DJ Gillespie
42473ad7ff bump to 4.3.7 since 4.3.6 was tagged but not released 2025-02-19 14:58:30 -07:00
DJ Gillespie
eeda3385eb add additonal python versions 2025-02-19 14:53:17 -07:00
Tim Savannah
50baa8db50 Fix years in copyright notice of func_timeout.exceptions. Will not be a new release just for this. 2019-08-19 17:52:33 -04:00
Tim Savannah
45cdbdfe4f 4.3.5 2019-08-19 17:31:36 -04:00
Tim Savannah
514225621f Update cachebust reference in READMEs to pydocs from 4.3.4 to 4.3.5 to reflect newest version 2019-08-19 17:31:29 -04:00
Tim Savannah
5452efab5b Regenerate pydocs 2019-08-19 17:31:02 -04:00
Tim Savannah
5d2afb9582 Changelog 2019-08-19 17:30:01 -04:00
Tim Savannah
af7d6e8a39 Allow instantiation of FunctionTimedOut with empty arguments (to support some patterns in unit testing / mocking). Will replace function name with "Unknown Function" if not provided, and timedOutAfter will be "Unknown" or a float of how long until timeout occurred. 2019-08-19 17:28:33 -04:00
Tim Savannah
cf8a9545bc Update to GoodTests runTests.py version 3.0.5 from 2.1.1 2019-08-19 17:16:48 -04:00
Tim Savannah
176ef7b9d9 Increase test timing and thresholds so it works on slower computers as well. 2019-08-19 17:14:48 -04:00
Tim Savannah
1eba58f599 4.3.4 2019-08-19 16:36:57 -04:00
Tim Savannah
f759dbfeec Add missing test_StoppableThread unit test, may need some minor cleanups and tweaking, but passes. 2019-08-19 16:36:45 -04:00
Tim Savannah
82493fe61d Fix missing newline in unit test TestUtils docstring 2019-08-19 16:36:19 -04:00
Tim Savannah
945b971637 Update cachebust reference on documentation from 4.3.3 to 4.3.4 2019-08-19 16:31:04 -04:00
Tim Savannah
64c3098922 Regen docs, py3 generation for all but py2_raise generated on 2.7 2019-08-19 16:30:15 -04:00
Tim Savannah
3fc998c3ca Changelog 2019-08-19 16:27:12 -04:00
Tim Savannah
caffd41f95
Merge pull request #7 from florczakraf/use_is_alive
Use is_alive in favor of isAlive
2019-08-19 16:22:00 -04:00
Rafał Florczak
1722f34da2
Use is_alive in favor of deprecated isAlive 2019-08-19 12:01:00 +02:00
Tim Savannah
bdc7072176 Update pydoc link with a different value on the GET params to force a regen if old version was cached. 2019-05-13 16:30:03 -04:00
Tim Savannah
e90d850871 Regen pydocs, and generate py2_raise again as well 2019-05-13 16:28:08 -04:00
Tim Savannah
8ab818f94a 4.3.3 2019-05-13 16:26:25 -04:00
Tim Savannah
317a65ce08 Changelog 2019-05-13 16:26:04 -04:00
Tim Savannah
5f9a1e493a Update READMEs and note both ways to create a thread, instead of I think implying that you MUST extend the class. 2019-05-13 16:25:45 -04:00
Tim Savannah
6e869794ef Add expected value before print on old testit.py, and docstring to note where other tests are located. 2019-05-13 11:47:07 -04:00
Tim Savannah
84528e67ed Update mkdoc.sh script to ensure we are in project root dir and to enable nullglob 2019-05-13 11:43:20 -04:00
Tim Savannah
81759d9b2b Remove TODO file 2019-05-13 11:39:16 -04:00
Tim Savannah
515988d9fc Regen pydocs 2019-05-13 11:34:10 -04:00
Tim Savannah
ac5eb257b0 Bump to 4.3.2 to re-release with up-to-date pydoc link. 2019-05-13 11:33:59 -04:00
Tim Savannah
45244ce98e Changelog 2019-05-13 11:33:46 -04:00
Tim Savannah
549251b2a3 Update link to pydoc to use githubpreview, as pythonhosted is old and not currently working. 2019-05-13 11:33:24 -04:00
Tim Savannah
cdd2d6d34f Regen docs for 4.3.1 2019-05-13 11:28:39 -04:00
Tim Savannah
5ab59fd709 Mark as 4.3.1 2019-05-13 11:28:26 -04:00
Tim Savannah
c52d7181d6 Strip trailing whitespace 2019-05-13 11:27:47 -04:00
Tim Savannah
874bc9b576 changelog 2019-05-13 11:27:13 -04:00
Tim Savannah
92dc986332 Regen pydocs 2019-05-13 11:25:41 -04:00
Tim Savannah
dc5fcfe507 Update READMEs, be more clear with sections, add more documentation on StoppableThread 2019-05-13 11:25:21 -04:00
Tim Savannah
f7f761789c Note it works with python 3.7 2019-05-13 11:24:40 -04:00
Tim Savannah
f793e36dc6 StoppableThread - Add more documentation to StoppableThread 2019-05-13 11:24:17 -04:00
Tim Savannah
089172fe0c Be explicit that StoppableThread.stop #exception argument needs to be a class/type, not an instance. 2019-05-13 11:07:33 -04:00
Tim Savannah
b427da2517 4.3.0 2017-08-10 18:50:20 -04:00
Tim Savannah
00685ec546 Issue #2 (Resolve) - Ensure we do not lose function information when using the func_set_timeout wrapper.
This includes things like like name, docstring, etc) when using the func_set_timeout wrapper.

This resolves using functools.wrap standard library function.

Includes unit test (failing before this commit, passing after)

Thanks to belongwqz for noting the issue and suggesting functools.wrap as resolution.
2017-08-10 18:48:50 -04:00
Tim Savannah
2bd33c12fd Tag 4.2.0 For Real and Update setup.py 2017-06-04 04:47:21 -04:00
Tim Savannah
5e15db92b6 Changelog 2017-06-04 04:47:10 -04:00
Tim Savannah
e99d1d8957 Add StoppableThread to the root module (so from 'func_timeout import StoppableThread' now works, instead of needing to do 'from func_timeout.StoppableThread import StoppableThread') 2017-06-04 04:46:47 -04:00
Tim Savannah
0e43f0b161 pydoc 2017-06-04 04:44:20 -04:00
Tim Savannah
f21d4b4b49 Update READMEs to note StoppableThread 2017-06-04 04:43:56 -04:00
Tim Savannah
6bee825db7 Add a bunch of comments to StoppableThread 2017-06-04 04:41:44 -04:00
Tim Savannah
19497ca229 4.2.0 2017-06-04 04:30:58 -04:00
Tim Savannah
4190710ec4 Update pydoc 2017-06-04 04:30:22 -04:00
Tim Savannah
57aed88c7a Add 'stop' method (rather than _stopThread) to StoppableThread 2017-05-28 01:11:42 -04:00
Tim Savannah
3f6d300aa0 4.1.0 2017-05-24 02:14:27 -04:00
Tim Savannah
0e2b0e9c3e doc 2017-05-24 02:14:11 -04:00
Tim Savannah
5e44de7210 Changelog 2017-05-24 02:12:07 -04:00
Tim Savannah
9e1ac2fb8c Change to using clever import strategy such that we dont have to use exec/eval 2017-05-24 02:08:15 -04:00
Tim Savannah
76cf4f6456 Much better exception handling - Have them make more sense. Get rid of the multiple traceback prints, one for each level of catchs on python3. Also improve traceback on both python3 and python2 to exclude the function wrapper, and instead follow the execution frame. Downside is that neither form compiles on the other python, so have to use exec... 2017-05-24 02:01:58 -04:00
Tim Savannah
fd0260fc05 For python >= 3.3, raise with the chained exception context disabled, since the funcwrap wrapper is within the context where the exception would be thrown (on python3+) 2017-05-24 01:32:55 -04:00
Tim Savannah
3275780482 Changelog 2017-05-24 01:23:34 -04:00
Tim Savannah
5a6187122d Force cleanup of thread if function completes in time. On python2 this forces the thread to be cleaned up right-away, on python3 it would get cleaned up during the next garbage-collect cycle. In python2 it may take several rounds. 2017-05-24 01:22:17 -04:00
Tim Savannah
3dcf6f921e pydoc update 2017-05-20 21:43:07 -04:00
Tim Savannah
38ec3de098 Fix date 2017-05-20 21:40:54 -04:00
Tim Savannah
0c1f6a7de6 README list pydocs 2017-05-20 21:40:34 -04:00
Tim Savannah
b6c02653b8 4.0.0 2017-05-20 21:38:02 -04:00
Tim Savannah
cfa466a302 Changelog 2017-05-20 21:30:36 -04:00
Tim Savannah
ca8a3a3534 Short README update 2017-05-20 21:30:13 -04:00
Tim Savannah
8af967169d Make python2 work as well as python3 2017-05-20 21:23:37 -04:00
Tim Savannah
f20e8e727c Fix so instantiation works in async exception. Also, dont need to worry about the exception comment, as we use BaseException and have for a while to prevent such. 2017-05-20 21:14:58 -04:00
Tim Savannah
525c291aef Regen html 2017-05-20 17:20:47 -04:00
Tim Savannah
d6ff5e1932 Make StoppableThread.JoinThread have a configurable retry interval (still default 2 seconds). Will attempt to retry stopping thread every this-many seconds 2017-05-20 17:20:23 -04:00
Tim Savannah
e554cd0252 Update docstring text 2017-05-20 17:18:06 -04:00
Tim Savannah
d10476b734 Update pydoc 2017-05-20 17:11:59 -04:00
Tim Savannah
63454c7178 Add mkdoc.sh script 2017-05-20 17:11:54 -04:00
Tim Savannah
9d3eec0475 Add README for tests dir, and add tests to MANIFEST.in 2017-05-20 17:10:16 -04:00
Tim Savannah
e4cf7fa765 Add TODO 2017-05-20 17:07:26 -04:00
Tim Savannah
ad944d3c2c Add tests 2017-05-20 17:06:51 -04:00
Tim Savannah
b729265855 Add msg property to FunctionTimedOut exception (also can get by str( exception ) 2017-05-20 17:04:22 -04:00
Tim Savannah
75d90251f6 Add missing import 2017-05-20 16:51:07 -04:00
Tim Savannah
2079932b4e Changelog 2017-05-20 16:24:24 -04:00
Tim Savannah
0ccca87e2c Some tests 2017-05-20 16:22:14 -04:00
Tim Savannah
36b7d6f266 Decrease thread join time. Because it is a daemon thread it will get closed automatically on garbage collect, just need to initate a join at all. 2017-05-20 16:21:43 -04:00
Tim Savannah
5b93fe5d7c Expand FunctionTimedOut exception to have attributes of the timeout, function that failed, args and kwargs. Also add a standard getMsg function for generating consistant message, and add a retry function to retry the function again with either same timeout, different timeout, or no timeout. 2017-05-20 16:04:39 -04:00
Tim Savannah
c3a114e1df Sometimes depending on critical section during timeout, traceback could be printed to stderr. Stop that. 2017-05-20 15:49:17 -04:00
Tim Savannah
b1a05fe92f Add GoodTests.py suite, some utils which will be used, and a test for the test. How meta! 2017-05-20 02:22:24 -04:00
Tim Savannah
32078a8065 Changeup how the function decorator works.
Rename to "set_func_timeout" - Give it 2 possible arguments.

First is either a floating point timeout, or a function which will be
invoked each call of decorated function and passed same arguments, to
calculate the timeout that should be used.

Second is "allowOverride", default False. If True, adds a kwarg to the
function being decorated, "forceTimeout", which if provided will
override any default timeout and prevent a calculation attempt.
2017-05-20 01:52:01 -04:00
Tim Savannah
84a3abd11d Revert 906f2b9028 on testit.py accidental commit 2017-05-20 00:06:54 -04:00
Tim Savannah
036c1dfa6f Add docstrings and imports 2017-05-19 21:01:07 -04:00
Tim Savannah
b778c644c3 Changelog 2017-05-19 20:50:25 -04:00
Tim Savannah
1a22f0f55b Merge branch 'master' into 4.0branch 2017-05-19 20:50:03 -04:00
Tim Savannah
906f2b9028 Version 4.0.0 2017-05-19 20:49:45 -04:00
Tim Savannah
1f4e536784 Changelog 2017-05-19 20:49:43 -04:00
Tim Savannah
f7baa18e64 Note set_timeout decorator in README 2017-05-19 20:49:42 -04:00
Tim Savannah
f8ec7f492c Add 'set_timeout' decorator for functions 2017-05-19 20:49:41 -04:00
Tim Savannah
3f4bae15c1 Fix year in changelog 2017-05-19 20:49:40 -04:00
29 changed files with 3205 additions and 486 deletions

View File

@ -1,3 +1,93 @@
* 4.3.5 - Aug 19 2019
- Increase times in unit tests to ensure passing on slow systems
- Allow instantiating FunctionTimedOut exception without arguments ( will replace function name with "Unknown Function" and timedOutAfter with "Unknown" when absent)
- Update runTests.py from latest GoodTests distrib, 3.0.5 from 2.1.1
* 4.3.4 - Aug 19 2019
- Merge patch by Rafal Florczak to use threading.Thread.is_alive vs now deprecated threading.Thread.isAlive
- Regenerate docs
* 4.3.3 - May 13 2019
- More documentation updates
* 4.3.2 - May 13 2019
- Update docs, update README, note that this still works with Python 3.7
- Update link to pydocs to be on githubpreview, as python hosted is broke right now.
* 4.3.0 - Aug 10 2017
- Ensure that functions wrapped with @func_set_timeout do not lose meta
information (such as name, docstrings, etc.). Special thanks to belongwqz on
github for noting the issue and suggesting functools.wraps
* 4.2.0 - Jun 4 2017
- Add "stop" method to StoppableThread (same as previous _stopThread method -
but with a 'public' name)
- Document StoppableThread a lot more
- Add "raiseEvery" to StoppableThread.stop to control the "repeatEvery" arg to
JoinThread (how often after the first raise the exception is retried)
* 4.1.0 - May 24 2017
- If func_timeout completes the function call in the alloted time, explicitly
clean up the thread (previously we were only cleaning it up in the time-out
path). On python3 it would get cleaned up anyway on the next garbage
collection cycle, on python2 it's a bit more finnikey (but will also,
eventually, get automatically joined)
- Be better at the traceback. Exclude the funcwrap from the call, and ensure
the raised Exception follows the actual path of execution (can be confusing to
read at first glance, but your function is at the bottom, then goes around a
bit.)
This uses PEP409/3134 in Python3 (available in 3.3+, we support 3.4+
officially).
Python2 doesn't have this, but has it's own syntax that doesn't work in
python3 to allow throwing a custom __traceback__.
You'd think both would support both, or at least python3 support both...
Anyway, this causes a kinda silly import-hack and adds an extra frame to the
exception handling part, but works to prevent default handlers from picking it
up.
This solves the multiple prints of exceptions on python3 in certain
circumstances(you catching and then raising an exception)
* 4.0.0 - May 20 2017
- Fixup short delay after a thread times out
- Fix where in some cases (depending on what was execution when abort was
called), a default handler could print the tracback to stderr outside of the
scope of the normal raise (it would still be raised, just handled twice).
- Add a function decorator which provides a default timeout, allows that
timeout to be overriden by adding a "forceTimeout" kwarg to the function
(configurable), or even running a function to calculate the timeout based on
args for each call
- Some improvements to python2 support
- Add GoodTests (Unit tests)
* 3.1.0 - Jan 4 2017
- Make windows compatible
- Add simple testcase, "testit.py"

View File

@ -7,3 +7,6 @@ include ChangeLog
include testit.py
recursive-include func_timeout *.py
recursive-include doc *.html
include tests/runTests.py
include tests/README
recursive-include tests/FuncTimeoutTests *.py

188
README.md
View File

@ -2,10 +2,12 @@
Python module to support running any existing function with a given timeout.
Package Includes
----------------
Function Timeout
================
**func\_timeout**
func\_timeout
-------------
This is the function wherein you pass the timeout, the function you want to call, and any arguments, and it runs it for up to #timeout# seconds, and will return/raise anything the passed function would otherwise return or raise.
@ -25,13 +27,10 @@ This is the function wherein you pass the timeout, the function you want to call
@return - The return value that #func# gives
'''
**FunctionTimedOut**
Exception raised if the function times out
**Example**
Example
-------
So, for esxample, if you have a function "doit('arg1', 'arg2')" that you want to limit to running for 5 seconds, with func\_timeout you can call it like this:
@ -49,6 +48,41 @@ So, for esxample, if you have a function "doit('arg1', 'arg2')" that you want to
# Handle any exceptions that doit might raise here
func\_set\_timeout
------------------
This is a decorator you can use on functions to apply func\_timeout.
Takes two arguments, "timeout" and "allowOverride"
If "allowOverride" is present, an optional keyword argument is added to the wrapped function, 'forceTimeout'. When provided, this will override the timeout used on this function.
The "timeout" parameter can be either a number (for a fixed timeout), or a function/lambda. If a function/lambda is used, it will be passed the same arguments as the called function was passed. It should return a number which will be used as the timeout for that paticular run. For example, if you have a method that calculates data, you'll want a higher timeout for 1 million records than 50 records.
**Example:**
@func_set_timeout(2.5)
def myFunction(self, arg1, arg2):
...
FunctionTimedOut
----------------
Exception raised if the function times out.
Has a "retry" method which takes the following arguments:
* No argument - Retry same args, same function, same timeout
* Number argument - Retry same args, same function, provided timeout
* None - Retry same args, same function, no timeout
How it works
------------
@ -57,10 +91,144 @@ If there is a return or an exception raised, it will be returned/raised as norma
If the timeout has exceeded, the "FunctionTimedOut" exception will be raised in the context of the function being called, as well as from the context of "func\_timeout". You should have your function catch the "FunctionTimedOut" exception and exit cleanly if possible. Every 2 seconds until your function is terminated, it will continue to raise FunctionTimedOut. The terminating of the timed-out function happens in the context of the thread and will not block main execution.
Support
-------
I've tested func\_timeout with python 2.7, 3.4, and 3.5. It should work on other versions as well.
StoppableThread
===============
StoppableThread is a subclass of threading.Thread, which supports stopping the thread (supports both python2 and python3). It will work to stop even in C code.
The way it works is that you pass it an exception, and it raises it via the cpython api (So the next time a "python" function is called from C api, or the next line is processed in python code, the exception is raised).
Using StoppableThread
---------------------
You can use StoppableThread one of two ways:
**As a Parent Class**
Your thread can extend func\_timeout.StoppableThread\.StoppableThread and implement the "run" method, same as a normal thread.
from func_timeout.StoppableThread import StoppableThread
class MyThread(StoppableThread):
def run(self):
# Code here
return
Then, you can create and start this thread like:
myThread = MyThread()
# Uncomment next line to start thread in "daemon mode" -- i.e. will terminate/join automatically upon main thread exit
#myThread.daemon = True
myThread.start()
Then, at any time during the thread's execution, you can call \.stop( StopExceptionType ) to stop it ( more in "Stopping a Thread" below
**Direct Thread To Execute A Function**
Alternatively, you can instantiate StoppableThread directly and pass the "target", "args", and "kwargs" arguments to the constructor
myThread = StoppableThread( target=myFunction, args=('ordered', 'args', 'here'), kwargs={ 'keyword args' : 'here' } )
# Uncomment next line to start thread in "daemon mode" -- i.e. will terminate/join automatically upon main thread exit
#myThread.daemon = True
myThread.start()
This will allow you to call functions in stoppable threads, for example handlers in an event loop, which can be stopped later via the \.stop() method.
Stopping a Thread
-----------------
The *StoppableThread* class (you must extend this for your thread) adds a function, *stop*, which can be called to stop the thread.
def stop(self, exception, raiseEvery=2.0):
'''
Stops the thread by raising a given exception.
@param exception <Exception type> - Exception to throw. Likely, you want to use something
that inherits from BaseException (so except Exception as e: continue; isn't a problem)
This should be a class/type, NOT an instance, i.e. MyExceptionType not MyExceptionType()
@param raiseEvery <float> Default 2.0 - We will keep raising this exception every #raiseEvery seconds,
until the thread terminates.
If your code traps a specific exception type, this will allow you #raiseEvery seconds to cleanup before exit.
If you're calling third-party code you can't control, which catches BaseException, set this to a low number
to break out of their exception handler.
@return <None>
'''
The "exception" param must be a type, and it must be instantiable with no arguments (i.e. MyExceptionType() must create the object).
Consider using a custom exception type which extends BaseException, which you can then use to do basic cleanup ( flush any open files, etc. ).
The exception type you pass will be raised every #raiseEvery seconds in the context of that stoppable thread. You can tweak this value to give yourself more time for cleanups, or you can shrink it down to break out of empty exception handlers ( try/except with bare except ).
**Notes on Exception Type**
It is recommended that you create an exception that extends BaseException instead of Exception, otherwise code like this will never stop:
while True:
try:
doSomething()
except Exception as e:
continue
If you can't avoid such code (third-party lib?) you can set the "repeatEvery" to a very very low number (like .00001 ), so hopefully it will raise, go to the except clause, and then raise again before "continue" is hit.
You may want to consider using singleton types with fixed error messages, so that tracebacks, etc. log that the call timed out.
For example:
class ServerShutdownExceptionType(BaseException):
def __init__(self, *args, **kwargs):
BaseException.__init__(self, 'Server is shutting down')
This will force 'Server is shutting down' as the message held by this exception.
Pydoc
=====
Find the latest pydoc at http://htmlpreview.github.io/?https://github.com/kata198/func_timeout/blob/master/doc/func_timeout.html?vers=4.3.5 .
Support
=======
I've tested func\_timeout with python 2.7, 3.4, 3.5, 3.6, 3.7. It should work on other versions as well.
Works on windows, linux/unix, cygwin, mac

View File

@ -1,87 +1,262 @@
func_timeout
func\_timeout
=============
Python module to support running any existing function with a given timeout.
Package Includes
----------------
Function Timeout
================
**func_timeout**
func\_timeout
-------------
This is the function wherein you pass the timeout, the function you want to call, and any arguments, and it runs it for up to #timeout# seconds, and will return/raise anything the passed function would otherwise return or raise.
def func_timeout(timeout, func, args=(), kwargs=None):
def func\_timeout(timeout, func, args=(), kwargs=None):
'''
func_timeout - Runs the given function for up to #timeout# seconds.
func\_timeout \- Runs the given function for up to #timeout# seconds.
Raises any exceptions #func# would raise, returns what #func# would return (unless timeout is exceeded), in which case it raises FunctionTimedOut
@param timeout <float> \- Maximum number of seconds to run #func# before terminating
@param timeout <float> - Maximum number of seconds to run #func# before terminating
@param func <function> \- The function to call
@param func <function> - The function to call
@param args <tuple> \- Any ordered arguments to pass to the function
@param args <tuple> - Any ordered arguments to pass to the function
@param kwargs <dict/None> \- Keyword arguments to pass to the function.
@param kwargs <dict/None> - Keyword arguments to pass to the function.
@raises \- FunctionTimedOut if #timeout# is exceeded, otherwise anything #func# could raise will be raised
@raises - FunctionTimedOut if #timeout# is exceeded, otherwise anything #func# could raise will be raised
@return - The return value that #func# gives
@return \- The return value that #func# gives
'''
**FunctionTimedOut**
Exception raised if the function times out
**Example**
Example
-------
So, for esxample, if you have a function "doit('arg1', 'arg2')" that you want to limit to running for 5 seconds, with func_timeout you can call it like this:
So, for esxample, if you have a function "doit('arg1', 'arg2')" that you want to limit to running for 5 seconds, with func\_timeout you can call it like this:
from func_timeout import func_timeout, FunctionTimedOut
from func\_timeout import func\_timeout, FunctionTimedOut
...
try:
doitReturnValue = func_timeout(5, doit, args=('arg1', 'arg2'))
doitReturnValue = func\_timeout(5, doit, args=('arg1', 'arg2'))
except FunctionTimedOut:
print ( "doit('arg1', 'arg2') could not complete within 5 seconds and was terminated.\n")
print ( "doit('arg1', 'arg2') could not complete within 5 seconds and was terminated.\\n")
except Exception as e:
# Handle any exceptions that doit might raise here
func\_set\_timeout
------------------
This is a decorator you can use on functions to apply func\_timeout.
Takes two arguments, "timeout" and "allowOverride"
If "allowOverride" is present, an optional keyword argument is added to the wrapped function, 'forceTimeout'. When provided, this will override the timeout used on this function.
The "timeout" parameter can be either a number (for a fixed timeout), or a function/lambda. If a function/lambda is used, it will be passed the same arguments as the called function was passed. It should return a number which will be used as the timeout for that paticular run. For example, if you have a method that calculates data, you'll want a higher timeout for 1 million records than 50 records.
**Example:**
@func\_set\_timeout(2.5)
def myFunction(self, arg1, arg2):
...
FunctionTimedOut
----------------
Exception raised if the function times out.
Has a "retry" method which takes the following arguments:
\* No argument \- Retry same args, same function, same timeout
\* Number argument \- Retry same args, same function, provided timeout
\* None \- Retry same args, same function, no timeout
How it works
------------
func_timeout will run the specified function in a thread with the specified arguments until it returns, raises an exception, or the timeout is exceeded.
func\_timeout will run the specified function in a thread with the specified arguments until it returns, raises an exception, or the timeout is exceeded.
If there is a return or an exception raised, it will be returned/raised as normal.
If the timeout has exceeded, the "FunctionTimedOut" exception will be raised in the context of the function being called, as well as from the context of "func_timeout". You should have your function catch the "FunctionTimedOut" exception and exit cleanly if possible. Every 2 seconds until your function is terminated, it will continue to raise FunctionTimedOut. The terminating of the timed-out function happens in the context of the thread and will not block main execution.
If the timeout has exceeded, the "FunctionTimedOut" exception will be raised in the context of the function being called, as well as from the context of "func\_timeout". You should have your function catch the "FunctionTimedOut" exception and exit cleanly if possible. Every 2 seconds until your function is terminated, it will continue to raise FunctionTimedOut. The terminating of the timed-out function happens in the context of the thread and will not block main execution.
StoppableThread
===============
StoppableThread is a subclass of threading.Thread, which supports stopping the thread (supports both python2 and python3). It will work to stop even in C code.
The way it works is that you pass it an exception, and it raises it via the cpython api (So the next time a "python" function is called from C api, or the next line is processed in python code, the exception is raised).
Using StoppableThread
---------------------
You can use StoppableThread one of two ways:
**As a Parent Class**
Your thread can extend func\_timeout.StoppableThread\.StoppableThread and implement the "run" method, same as a normal thread.
from func\_timeout.StoppableThread import StoppableThread
class MyThread(StoppableThread):
def run(self):
# Code here
return
Then, you can create and start this thread like:
myThread = MyThread()
# Uncomment next line to start thread in "daemon mode" \-\- i.e. will terminate/join automatically upon main thread exit
#myThread.daemon = True
myThread.start()
Then, at any time during the thread's execution, you can call \.stop( StopExceptionType ) to stop it ( more in "Stopping a Thread" below
**Direct Thread To Execute A Function**
Alternatively, you can instantiate StoppableThread directly and pass the "target", "args", and "kwargs" arguments to the constructor
myThread = StoppableThread( target=myFunction, args=('ordered', 'args', 'here'), kwargs={ 'keyword args' : 'here' } )
# Uncomment next line to start thread in "daemon mode" \-\- i.e. will terminate/join automatically upon main thread exit
#myThread.daemon = True
myThread.start()
This will allow you to call functions in stoppable threads, for example handlers in an event loop, which can be stopped later via the \.stop() method.
Stopping a Thread
-----------------
The *StoppableThread* class (you must extend this for your thread) adds a function, *stop*, which can be called to stop the thread.
def stop(self, exception, raiseEvery=2.0):
'''
Stops the thread by raising a given exception.
@param exception <Exception type> \- Exception to throw. Likely, you want to use something
that inherits from BaseException (so except Exception as e: continue; isn't a problem)
This should be a class/type, NOT an instance, i.e. MyExceptionType not MyExceptionType()
@param raiseEvery <float> Default 2.0 \- We will keep raising this exception every #raiseEvery seconds,
until the thread terminates.
If your code traps a specific exception type, this will allow you #raiseEvery seconds to cleanup before exit.
If you're calling third\-party code you can't control, which catches BaseException, set this to a low number
to break out of their exception handler.
@return <None>
'''
The "exception" param must be a type, and it must be instantiable with no arguments (i.e. MyExceptionType() must create the object).
Consider using a custom exception type which extends BaseException, which you can then use to do basic cleanup ( flush any open files, etc. ).
The exception type you pass will be raised every #raiseEvery seconds in the context of that stoppable thread. You can tweak this value to give yourself more time for cleanups, or you can shrink it down to break out of empty exception handlers ( try/except with bare except ).
**Notes on Exception Type**
It is recommended that you create an exception that extends BaseException instead of Exception, otherwise code like this will never stop:
while True:
try:
doSomething()
except Exception as e:
continue
If you can't avoid such code (third-party lib?) you can set the "repeatEvery" to a very very low number (like .00001 ), so hopefully it will raise, go to the except clause, and then raise again before "continue" is hit.
You may want to consider using singleton types with fixed error messages, so that tracebacks, etc. log that the call timed out.
For example:
class ServerShutdownExceptionType(BaseException):
def \_\_init\_\_(self, \*args, \*\*kwargs):
BaseException.\_\_init\_\_(self, 'Server is shutting down')
This will force 'Server is shutting down' as the message held by this exception.
Pydoc
=====
Find the latest pydoc at http://htmlpreview.github.io/?https://github.com/kata198/func_timeout/blob/master/doc/func_timeout.html?vers=4.3.5 .
Support
-------
=======
I've tested func\_timeout with python 2.7, 3.4, and 3.5. It should work on other versions as well.
I've tested func\_timeout with python 2.7, 3.4, 3.5, 3.6, 3.7. It should work on other versions as well.
Works on windows, linux/unix, cygwin, mac
ChangeLog can be found at https://raw.githubusercontent.com/kata198/func_timeout/master/ChangeLog
Pydoc can be found at: http://htmlpreview.github.io/?https://github.com/kata198/func_timeout/blob/master/doc/func_timeout.html?vers=1

View File

@ -1,184 +1,64 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Python: module func_timeout.StoppableThread</title>
<html><head><title>Python: class StoppableThread</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head><body bgcolor="#f0f0f8">
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
<tr bgcolor="#7799ee">
<td valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="func_timeout.html"><font color="#ffffff">func_timeout</font></a>.StoppableThread</strong></big></big></font></td
><td align=right valign=bottom
><font color="#ffffff" face="helvetica, arial"><a href="func_timeout.html">index</a></font></td></tr></table>
<p></p>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#aa55cc">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="ctypes.html">ctypes</a><br>
</td><td width="25%" valign=top><a href="threading.html">threading</a><br>
</td><td width="25%" valign=top><a href="time.html">time</a><br>
</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ee77aa">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><dl>
<dt><font face="helvetica, arial"><a href="threading.html#Thread">threading.Thread</a>(<a href="builtins.html#object">builtins.object</a>)
</font></dt><dd>
<dl>
<dt><font face="helvetica, arial"><a href="func_timeout.StoppableThread.html#JoinThread">JoinThread</a>
</font></dt><dt><font face="helvetica, arial"><a href="func_timeout.StoppableThread.html#StoppableThread">StoppableThread</a>
</font></dt></dl>
</dd>
</dl>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ffc8d8">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#000000" face="helvetica, arial"><a name="JoinThread">class <strong>JoinThread</strong></a>(<a href="threading.html#Thread">threading.Thread</a>)</font></td></tr>
<font color="#000000" face="helvetica, arial"><strong>func_timeout.StoppableThread</strong> = <a name="func_timeout.StoppableThread">class StoppableThread</a>(<a href="threading.html#Thread">threading.Thread</a>)</font></td></tr>
<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
<td colspan=2><tt><a href="#JoinThread">JoinThread</a>&nbsp;-&nbsp;The&nbsp;workhouse&nbsp;that&nbsp;stops&nbsp;the&nbsp;<a href="#StoppableThread">StoppableThread</a><br>&nbsp;</tt></td></tr>
<tr><td>&nbsp;</td>
<td width="100%"><dl><dt>Method resolution order:</dt>
<dd><a href="func_timeout.StoppableThread.html#JoinThread">JoinThread</a></dd>
<dd><a href="threading.html#Thread">threading.Thread</a></dd>
<dd><a href="builtins.html#object">builtins.object</a></dd>
</dl>
<hr>
Methods defined here:<br>
<dl><dt><a name="JoinThread-__init__"><strong>__init__</strong></a>(self, otherThread, exception)</dt><dd><tt>This&nbsp;constructor&nbsp;should&nbsp;always&nbsp;be&nbsp;called&nbsp;with&nbsp;keyword&nbsp;arguments.&nbsp;Arguments&nbsp;are:<br>
<td colspan=2><tt>func_timeout.StoppableThread(group=None,&nbsp;target=None,&nbsp;name=None,&nbsp;args=(),&nbsp;kwargs=None,&nbsp;*,&nbsp;daemon=None)<br>
&nbsp;<br>
*group*&nbsp;should&nbsp;be&nbsp;None;&nbsp;reserved&nbsp;for&nbsp;future&nbsp;extension&nbsp;when&nbsp;a&nbsp;ThreadGroup<br>
class&nbsp;is&nbsp;implemented.<br>
StoppableThread&nbsp;-&nbsp;A&nbsp;thread&nbsp;that&nbsp;can&nbsp;be&nbsp;stopped&nbsp;by&nbsp;forcing&nbsp;an&nbsp;exception&nbsp;in&nbsp;the&nbsp;execution&nbsp;context.<br>
&nbsp;<br>
*target*&nbsp;is&nbsp;the&nbsp;callable&nbsp;object&nbsp;to&nbsp;be&nbsp;invoked&nbsp;by&nbsp;the&nbsp;<a href="#JoinThread-run">run</a>()<br>
method.&nbsp;Defaults&nbsp;to&nbsp;None,&nbsp;meaning&nbsp;nothing&nbsp;is&nbsp;called.<br>
&nbsp;&nbsp;This&nbsp;works&nbsp;both&nbsp;to&nbsp;interrupt&nbsp;code&nbsp;that&nbsp;is&nbsp;in&nbsp;C&nbsp;or&nbsp;in&nbsp;python&nbsp;code,&nbsp;at&nbsp;either&nbsp;the&nbsp;next&nbsp;call&nbsp;to&nbsp;a&nbsp;python&nbsp;function,<br>
&nbsp;&nbsp;&nbsp;or&nbsp;the&nbsp;next&nbsp;line&nbsp;in&nbsp;python&nbsp;code.<br>
&nbsp;<br>
*name*&nbsp;is&nbsp;the&nbsp;thread&nbsp;name.&nbsp;By&nbsp;default,&nbsp;a&nbsp;unique&nbsp;name&nbsp;is&nbsp;constructed&nbsp;of<br>
the&nbsp;form&nbsp;"<a href="threading.html#Thread">Thread</a>-N"&nbsp;where&nbsp;N&nbsp;is&nbsp;a&nbsp;small&nbsp;decimal&nbsp;number.<br>
It&nbsp;is&nbsp;recommended&nbsp;that&nbsp;if&nbsp;you&nbsp;call&nbsp;stop&nbsp;(&nbsp;@see&nbsp;StoppableThread.stop&nbsp;)&nbsp;that&nbsp;you&nbsp;use&nbsp;an&nbsp;exception&nbsp;that&nbsp;inherits&nbsp;BaseException,&nbsp;to&nbsp;ensure&nbsp;it&nbsp;likely&nbsp;isn't&nbsp;caught.<br>
&nbsp;<br>
*args*&nbsp;is&nbsp;the&nbsp;argument&nbsp;tuple&nbsp;for&nbsp;the&nbsp;target&nbsp;invocation.&nbsp;Defaults&nbsp;to&nbsp;().<br>
&nbsp;Also,&nbsp;beware&nbsp;unmarked&nbsp;exception&nbsp;handlers&nbsp;in&nbsp;your&nbsp;code.&nbsp;Code&nbsp;like&nbsp;this:<br>
&nbsp;<br>
*kwargs*&nbsp;is&nbsp;a&nbsp;dictionary&nbsp;of&nbsp;keyword&nbsp;arguments&nbsp;for&nbsp;the&nbsp;target<br>
invocation.&nbsp;Defaults&nbsp;to&nbsp;{}.<br>
&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;True:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;doSomething()<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue<br>
&nbsp;<br>
If&nbsp;a&nbsp;subclass&nbsp;overrides&nbsp;the&nbsp;constructor,&nbsp;it&nbsp;must&nbsp;make&nbsp;sure&nbsp;to&nbsp;invoke<br>
the&nbsp;base&nbsp;class&nbsp;constructor&nbsp;(<a href="threading.html#Thread">Thread</a>.<a href="#JoinThread-__init__">__init__</a>())&nbsp;before&nbsp;doing&nbsp;anything<br>
else&nbsp;to&nbsp;the&nbsp;thread.</tt></dd></dl>
<dl><dt><a name="JoinThread-run"><strong>run</strong></a>(self)</dt><dd><tt>Method&nbsp;representing&nbsp;the&nbsp;thread's&nbsp;activity.<br>
will&nbsp;never&nbsp;be&nbsp;able&nbsp;to&nbsp;abort,&nbsp;because&nbsp;the&nbsp;exception&nbsp;you&nbsp;raise&nbsp;is&nbsp;immediately&nbsp;caught.<br>
&nbsp;<br>
You&nbsp;may&nbsp;override&nbsp;this&nbsp;method&nbsp;in&nbsp;a&nbsp;subclass.&nbsp;The&nbsp;standard&nbsp;<a href="#JoinThread-run">run</a>()&nbsp;method<br>
invokes&nbsp;the&nbsp;callable&nbsp;object&nbsp;passed&nbsp;to&nbsp;the&nbsp;object's&nbsp;constructor&nbsp;as&nbsp;the<br>
target&nbsp;argument,&nbsp;if&nbsp;any,&nbsp;with&nbsp;sequential&nbsp;and&nbsp;keyword&nbsp;arguments&nbsp;taken<br>
from&nbsp;the&nbsp;args&nbsp;and&nbsp;kwargs&nbsp;arguments,&nbsp;respectively.</tt></dd></dl>
<hr>
Methods inherited from <a href="threading.html#Thread">threading.Thread</a>:<br>
<dl><dt><a name="JoinThread-__repr__"><strong>__repr__</strong></a>(self)</dt><dd><tt>Return&nbsp;repr(self).</tt></dd></dl>
<dl><dt><a name="JoinThread-getName"><strong>getName</strong></a>(self)</dt></dl>
<dl><dt><a name="JoinThread-isAlive"><strong>isAlive</strong></a> = is_alive(self)</dt><dd><tt>Return&nbsp;whether&nbsp;the&nbsp;thread&nbsp;is&nbsp;alive.<br>
&nbsp;<br>
This&nbsp;method&nbsp;returns&nbsp;True&nbsp;just&nbsp;before&nbsp;the&nbsp;<a href="#JoinThread-run">run</a>()&nbsp;method&nbsp;starts&nbsp;until&nbsp;just<br>
after&nbsp;the&nbsp;<a href="#JoinThread-run">run</a>()&nbsp;method&nbsp;terminates.&nbsp;The&nbsp;module&nbsp;function&nbsp;enumerate()<br>
returns&nbsp;a&nbsp;list&nbsp;of&nbsp;all&nbsp;alive&nbsp;threads.</tt></dd></dl>
<dl><dt><a name="JoinThread-isDaemon"><strong>isDaemon</strong></a>(self)</dt></dl>
<dl><dt><a name="JoinThread-is_alive"><strong>is_alive</strong></a>(self)</dt><dd><tt>Return&nbsp;whether&nbsp;the&nbsp;thread&nbsp;is&nbsp;alive.<br>
&nbsp;<br>
This&nbsp;method&nbsp;returns&nbsp;True&nbsp;just&nbsp;before&nbsp;the&nbsp;<a href="#JoinThread-run">run</a>()&nbsp;method&nbsp;starts&nbsp;until&nbsp;just<br>
after&nbsp;the&nbsp;<a href="#JoinThread-run">run</a>()&nbsp;method&nbsp;terminates.&nbsp;The&nbsp;module&nbsp;function&nbsp;enumerate()<br>
returns&nbsp;a&nbsp;list&nbsp;of&nbsp;all&nbsp;alive&nbsp;threads.</tt></dd></dl>
<dl><dt><a name="JoinThread-join"><strong>join</strong></a>(self, timeout=None)</dt><dd><tt>Wait&nbsp;until&nbsp;the&nbsp;thread&nbsp;terminates.<br>
&nbsp;<br>
This&nbsp;blocks&nbsp;the&nbsp;calling&nbsp;thread&nbsp;until&nbsp;the&nbsp;thread&nbsp;whose&nbsp;<a href="#JoinThread-join">join</a>()&nbsp;method&nbsp;is<br>
called&nbsp;terminates&nbsp;--&nbsp;either&nbsp;normally&nbsp;or&nbsp;through&nbsp;an&nbsp;unhandled&nbsp;exception<br>
or&nbsp;until&nbsp;the&nbsp;optional&nbsp;timeout&nbsp;occurs.<br>
&nbsp;<br>
When&nbsp;the&nbsp;timeout&nbsp;argument&nbsp;is&nbsp;present&nbsp;and&nbsp;not&nbsp;None,&nbsp;it&nbsp;should&nbsp;be&nbsp;a<br>
floating&nbsp;point&nbsp;number&nbsp;specifying&nbsp;a&nbsp;timeout&nbsp;for&nbsp;the&nbsp;operation&nbsp;in&nbsp;seconds<br>
(or&nbsp;fractions&nbsp;thereof).&nbsp;As&nbsp;<a href="#JoinThread-join">join</a>()&nbsp;always&nbsp;returns&nbsp;None,&nbsp;you&nbsp;must&nbsp;call<br>
<a href="#JoinThread-isAlive">isAlive</a>()&nbsp;after&nbsp;<a href="#JoinThread-join">join</a>()&nbsp;to&nbsp;decide&nbsp;whether&nbsp;a&nbsp;timeout&nbsp;happened&nbsp;--&nbsp;if&nbsp;the<br>
thread&nbsp;is&nbsp;still&nbsp;alive,&nbsp;the&nbsp;<a href="#JoinThread-join">join</a>()&nbsp;call&nbsp;timed&nbsp;out.<br>
&nbsp;<br>
When&nbsp;the&nbsp;timeout&nbsp;argument&nbsp;is&nbsp;not&nbsp;present&nbsp;or&nbsp;None,&nbsp;the&nbsp;operation&nbsp;will<br>
block&nbsp;until&nbsp;the&nbsp;thread&nbsp;terminates.<br>
&nbsp;<br>
A&nbsp;thread&nbsp;can&nbsp;be&nbsp;<a href="#JoinThread-join">join</a>()ed&nbsp;many&nbsp;times.<br>
&nbsp;<br>
<a href="#JoinThread-join">join</a>()&nbsp;raises&nbsp;a&nbsp;RuntimeError&nbsp;if&nbsp;an&nbsp;attempt&nbsp;is&nbsp;made&nbsp;to&nbsp;join&nbsp;the&nbsp;current<br>
thread&nbsp;as&nbsp;that&nbsp;would&nbsp;cause&nbsp;a&nbsp;deadlock.&nbsp;It&nbsp;is&nbsp;also&nbsp;an&nbsp;error&nbsp;to&nbsp;<a href="#JoinThread-join">join</a>()&nbsp;a<br>
thread&nbsp;before&nbsp;it&nbsp;has&nbsp;been&nbsp;started&nbsp;and&nbsp;attempts&nbsp;to&nbsp;do&nbsp;so&nbsp;raises&nbsp;the&nbsp;same<br>
exception.</tt></dd></dl>
<dl><dt><a name="JoinThread-setDaemon"><strong>setDaemon</strong></a>(self, daemonic)</dt></dl>
<dl><dt><a name="JoinThread-setName"><strong>setName</strong></a>(self, name)</dt></dl>
<dl><dt><a name="JoinThread-start"><strong>start</strong></a>(self)</dt><dd><tt>Start&nbsp;the&nbsp;thread's&nbsp;activity.<br>
&nbsp;<br>
It&nbsp;must&nbsp;be&nbsp;called&nbsp;at&nbsp;most&nbsp;once&nbsp;per&nbsp;thread&nbsp;object.&nbsp;It&nbsp;arranges&nbsp;for&nbsp;the<br>
object's&nbsp;<a href="#JoinThread-run">run</a>()&nbsp;method&nbsp;to&nbsp;be&nbsp;invoked&nbsp;in&nbsp;a&nbsp;separate&nbsp;thread&nbsp;of&nbsp;control.<br>
&nbsp;<br>
This&nbsp;method&nbsp;will&nbsp;raise&nbsp;a&nbsp;RuntimeError&nbsp;if&nbsp;called&nbsp;more&nbsp;than&nbsp;once&nbsp;on&nbsp;the<br>
same&nbsp;thread&nbsp;object.</tt></dd></dl>
<hr>
Data descriptors inherited from <a href="threading.html#Thread">threading.Thread</a>:<br>
<dl><dt><strong>__dict__</strong></dt>
<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
</dl>
<dl><dt><strong>__weakref__</strong></dt>
<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
</dl>
<dl><dt><strong>daemon</strong></dt>
<dd><tt>A&nbsp;boolean&nbsp;value&nbsp;indicating&nbsp;whether&nbsp;this&nbsp;thread&nbsp;is&nbsp;a&nbsp;daemon&nbsp;thread.<br>
&nbsp;<br>
This&nbsp;must&nbsp;be&nbsp;set&nbsp;before&nbsp;start()&nbsp;is&nbsp;called,&nbsp;otherwise&nbsp;RuntimeError&nbsp;is<br>
raised.&nbsp;Its&nbsp;initial&nbsp;value&nbsp;is&nbsp;inherited&nbsp;from&nbsp;the&nbsp;creating&nbsp;thread;&nbsp;the<br>
main&nbsp;thread&nbsp;is&nbsp;not&nbsp;a&nbsp;daemon&nbsp;thread&nbsp;and&nbsp;therefore&nbsp;all&nbsp;threads&nbsp;created&nbsp;in<br>
the&nbsp;main&nbsp;thread&nbsp;default&nbsp;to&nbsp;daemon&nbsp;=&nbsp;False.<br>
&nbsp;<br>
The&nbsp;entire&nbsp;Python&nbsp;program&nbsp;exits&nbsp;when&nbsp;no&nbsp;alive&nbsp;non-daemon&nbsp;threads&nbsp;are<br>
left.</tt></dd>
</dl>
<dl><dt><strong>ident</strong></dt>
<dd><tt>Thread&nbsp;identifier&nbsp;of&nbsp;this&nbsp;thread&nbsp;or&nbsp;None&nbsp;if&nbsp;it&nbsp;has&nbsp;not&nbsp;been&nbsp;started.<br>
&nbsp;<br>
This&nbsp;is&nbsp;a&nbsp;nonzero&nbsp;integer.&nbsp;See&nbsp;the&nbsp;thread.get_ident()&nbsp;function.&nbsp;Thread<br>
identifiers&nbsp;may&nbsp;be&nbsp;recycled&nbsp;when&nbsp;a&nbsp;thread&nbsp;exits&nbsp;and&nbsp;another&nbsp;thread&nbsp;is<br>
created.&nbsp;The&nbsp;identifier&nbsp;is&nbsp;available&nbsp;even&nbsp;after&nbsp;the&nbsp;thread&nbsp;has&nbsp;exited.</tt></dd>
</dl>
<dl><dt><strong>name</strong></dt>
<dd><tt>A&nbsp;string&nbsp;used&nbsp;for&nbsp;identification&nbsp;purposes&nbsp;only.<br>
&nbsp;<br>
It&nbsp;has&nbsp;no&nbsp;semantics.&nbsp;Multiple&nbsp;threads&nbsp;may&nbsp;be&nbsp;given&nbsp;the&nbsp;same&nbsp;name.&nbsp;The<br>
initial&nbsp;name&nbsp;is&nbsp;set&nbsp;by&nbsp;the&nbsp;constructor.</tt></dd>
</dl>
</td></tr></table> <p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ffc8d8">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#000000" face="helvetica, arial"><a name="StoppableThread">class <strong>StoppableThread</strong></a>(<a href="threading.html#Thread">threading.Thread</a>)</font></td></tr>
<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
<td colspan=2><tt><a href="#StoppableThread">StoppableThread</a>&nbsp;-&nbsp;A&nbsp;thread&nbsp;that&nbsp;can&nbsp;be&nbsp;stopped&nbsp;by&nbsp;forcing&nbsp;an&nbsp;exception&nbsp;in&nbsp;the&nbsp;execution&nbsp;context.<br>&nbsp;</tt></td></tr>
The&nbsp;exception&nbsp;is&nbsp;raised&nbsp;over&nbsp;and&nbsp;over,&nbsp;with&nbsp;a&nbsp;specifed&nbsp;delay&nbsp;(default&nbsp;2.0&nbsp;seconds)<br>&nbsp;</tt></td></tr>
<tr><td>&nbsp;</td>
<td width="100%"><dl><dt>Method resolution order:</dt>
<dd><a href="func_timeout.StoppableThread.html#StoppableThread">StoppableThread</a></dd>
<dd><a href="threading.html#Thread">threading.Thread</a></dd>
<dd><a href="builtins.html#object">builtins.object</a></dd>
</dl>
<hr>
Methods defined here:<br>
<dl><dt><a name="StoppableThread-stop"><strong>stop</strong></a>(self, exception, raiseEvery=2.0)</dt><dd><tt>Stops&nbsp;the&nbsp;thread&nbsp;by&nbsp;raising&nbsp;a&nbsp;given&nbsp;exception.<br>
&nbsp;<br>
@param&nbsp;exception&nbsp;&lt;Exception&nbsp;type&gt;&nbsp;-&nbsp;Exception&nbsp;to&nbsp;throw.&nbsp;Likely,&nbsp;you&nbsp;want&nbsp;to&nbsp;use&nbsp;something<br>
&nbsp;<br>
&nbsp;&nbsp;that&nbsp;inherits&nbsp;from&nbsp;BaseException&nbsp;(so&nbsp;except&nbsp;Exception&nbsp;as&nbsp;e:&nbsp;continue;&nbsp;isn't&nbsp;a&nbsp;problem)<br>
&nbsp;<br>
&nbsp;&nbsp;This&nbsp;should&nbsp;be&nbsp;a&nbsp;class/type,&nbsp;NOT&nbsp;an&nbsp;instance,&nbsp;i.e.&nbsp;&nbsp;MyExceptionType&nbsp;&nbsp;&nbsp;not&nbsp;&nbsp;MyExceptionType()<br>
&nbsp;<br>
&nbsp;<br>
@param&nbsp;raiseEvery&nbsp;&lt;float&gt;&nbsp;Default&nbsp;2.0&nbsp;-&nbsp;We&nbsp;will&nbsp;keep&nbsp;raising&nbsp;this&nbsp;exception&nbsp;every&nbsp;#raiseEvery&nbsp;seconds,<br>
&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;until&nbsp;the&nbsp;thread&nbsp;terminates.<br>
&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;your&nbsp;code&nbsp;traps&nbsp;a&nbsp;specific&nbsp;exception&nbsp;type,&nbsp;this&nbsp;will&nbsp;allow&nbsp;you&nbsp;#raiseEvery&nbsp;seconds&nbsp;to&nbsp;cleanup&nbsp;before&nbsp;exit.<br>
&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;you're&nbsp;calling&nbsp;third-party&nbsp;code&nbsp;you&nbsp;can't&nbsp;control,&nbsp;which&nbsp;catches&nbsp;BaseException,&nbsp;set&nbsp;this&nbsp;to&nbsp;a&nbsp;low&nbsp;number<br>
&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;break&nbsp;out&nbsp;of&nbsp;their&nbsp;exception&nbsp;handler.<br>
&nbsp;<br>
&nbsp;<br>
&nbsp;@return&nbsp;&lt;None&gt;</tt></dd></dl>
<hr>
Methods inherited from <a href="threading.html#Thread">threading.Thread</a>:<br>
<dl><dt><a name="StoppableThread-__init__"><strong>__init__</strong></a>(self, group=None, target=None, name=None, args=(), kwargs=None, *, daemon=None)</dt><dd><tt>This&nbsp;constructor&nbsp;should&nbsp;always&nbsp;be&nbsp;called&nbsp;with&nbsp;keyword&nbsp;arguments.&nbsp;Arguments&nbsp;are:<br>
@ -186,11 +66,11 @@ Methods inherited from <a href="threading.html#Thread">threading.Thread</a>:<br>
*group*&nbsp;should&nbsp;be&nbsp;None;&nbsp;reserved&nbsp;for&nbsp;future&nbsp;extension&nbsp;when&nbsp;a&nbsp;ThreadGroup<br>
class&nbsp;is&nbsp;implemented.<br>
&nbsp;<br>
*target*&nbsp;is&nbsp;the&nbsp;callable&nbsp;object&nbsp;to&nbsp;be&nbsp;invoked&nbsp;by&nbsp;the&nbsp;<a href="#StoppableThread-run">run</a>()<br>
*target*&nbsp;is&nbsp;the&nbsp;callable&nbsp;object&nbsp;to&nbsp;be&nbsp;invoked&nbsp;by&nbsp;the&nbsp;<a href="#func_timeout.StoppableThread-run">run</a>()<br>
method.&nbsp;Defaults&nbsp;to&nbsp;None,&nbsp;meaning&nbsp;nothing&nbsp;is&nbsp;called.<br>
&nbsp;<br>
*name*&nbsp;is&nbsp;the&nbsp;thread&nbsp;name.&nbsp;By&nbsp;default,&nbsp;a&nbsp;unique&nbsp;name&nbsp;is&nbsp;constructed&nbsp;of<br>
the&nbsp;form&nbsp;"<a href="threading.html#Thread">Thread</a>-N"&nbsp;where&nbsp;N&nbsp;is&nbsp;a&nbsp;small&nbsp;decimal&nbsp;number.<br>
the&nbsp;form&nbsp;"Thread-N"&nbsp;where&nbsp;N&nbsp;is&nbsp;a&nbsp;small&nbsp;decimal&nbsp;number.<br>
&nbsp;<br>
*args*&nbsp;is&nbsp;the&nbsp;argument&nbsp;tuple&nbsp;for&nbsp;the&nbsp;target&nbsp;invocation.&nbsp;Defaults&nbsp;to&nbsp;().<br>
&nbsp;<br>
@ -198,52 +78,50 @@ the&nbsp;form&nbsp;"<a href="threading.html#Thread">Thread</a>-N"&nbsp;where&nbs
invocation.&nbsp;Defaults&nbsp;to&nbsp;{}.<br>
&nbsp;<br>
If&nbsp;a&nbsp;subclass&nbsp;overrides&nbsp;the&nbsp;constructor,&nbsp;it&nbsp;must&nbsp;make&nbsp;sure&nbsp;to&nbsp;invoke<br>
the&nbsp;base&nbsp;class&nbsp;constructor&nbsp;(<a href="threading.html#Thread">Thread</a>.<a href="#StoppableThread-__init__">__init__</a>())&nbsp;before&nbsp;doing&nbsp;anything<br>
the&nbsp;base&nbsp;class&nbsp;constructor&nbsp;(Thread.<a href="#func_timeout.StoppableThread-__init__">__init__</a>())&nbsp;before&nbsp;doing&nbsp;anything<br>
else&nbsp;to&nbsp;the&nbsp;thread.</tt></dd></dl>
<dl><dt><a name="StoppableThread-__repr__"><strong>__repr__</strong></a>(self)</dt><dd><tt>Return&nbsp;repr(self).</tt></dd></dl>
<dl><dt><a name="StoppableThread-getName"><strong>getName</strong></a>(self)</dt></dl>
<dl><dt><a name="StoppableThread-isAlive"><strong>isAlive</strong></a> = is_alive(self)</dt><dd><tt>Return&nbsp;whether&nbsp;the&nbsp;thread&nbsp;is&nbsp;alive.<br>
<dl><dt><a name="StoppableThread-isAlive"><strong>isAlive</strong></a>(self)</dt><dd><tt>Return&nbsp;whether&nbsp;the&nbsp;thread&nbsp;is&nbsp;alive.<br>
&nbsp;<br>
This&nbsp;method&nbsp;returns&nbsp;True&nbsp;just&nbsp;before&nbsp;the&nbsp;<a href="#StoppableThread-run">run</a>()&nbsp;method&nbsp;starts&nbsp;until&nbsp;just<br>
after&nbsp;the&nbsp;<a href="#StoppableThread-run">run</a>()&nbsp;method&nbsp;terminates.&nbsp;The&nbsp;module&nbsp;function&nbsp;enumerate()<br>
returns&nbsp;a&nbsp;list&nbsp;of&nbsp;all&nbsp;alive&nbsp;threads.</tt></dd></dl>
This&nbsp;method&nbsp;is&nbsp;deprecated,&nbsp;use&nbsp;<a href="#func_timeout.StoppableThread-is_alive">is_alive</a>()&nbsp;instead.</tt></dd></dl>
<dl><dt><a name="StoppableThread-isDaemon"><strong>isDaemon</strong></a>(self)</dt></dl>
<dl><dt><a name="StoppableThread-is_alive"><strong>is_alive</strong></a>(self)</dt><dd><tt>Return&nbsp;whether&nbsp;the&nbsp;thread&nbsp;is&nbsp;alive.<br>
&nbsp;<br>
This&nbsp;method&nbsp;returns&nbsp;True&nbsp;just&nbsp;before&nbsp;the&nbsp;<a href="#StoppableThread-run">run</a>()&nbsp;method&nbsp;starts&nbsp;until&nbsp;just<br>
after&nbsp;the&nbsp;<a href="#StoppableThread-run">run</a>()&nbsp;method&nbsp;terminates.&nbsp;The&nbsp;module&nbsp;function&nbsp;enumerate()<br>
This&nbsp;method&nbsp;returns&nbsp;True&nbsp;just&nbsp;before&nbsp;the&nbsp;<a href="#func_timeout.StoppableThread-run">run</a>()&nbsp;method&nbsp;starts&nbsp;until&nbsp;just<br>
after&nbsp;the&nbsp;<a href="#func_timeout.StoppableThread-run">run</a>()&nbsp;method&nbsp;terminates.&nbsp;The&nbsp;module&nbsp;function&nbsp;enumerate()<br>
returns&nbsp;a&nbsp;list&nbsp;of&nbsp;all&nbsp;alive&nbsp;threads.</tt></dd></dl>
<dl><dt><a name="StoppableThread-join"><strong>join</strong></a>(self, timeout=None)</dt><dd><tt>Wait&nbsp;until&nbsp;the&nbsp;thread&nbsp;terminates.<br>
&nbsp;<br>
This&nbsp;blocks&nbsp;the&nbsp;calling&nbsp;thread&nbsp;until&nbsp;the&nbsp;thread&nbsp;whose&nbsp;<a href="#StoppableThread-join">join</a>()&nbsp;method&nbsp;is<br>
This&nbsp;blocks&nbsp;the&nbsp;calling&nbsp;thread&nbsp;until&nbsp;the&nbsp;thread&nbsp;whose&nbsp;<a href="#func_timeout.StoppableThread-join">join</a>()&nbsp;method&nbsp;is<br>
called&nbsp;terminates&nbsp;--&nbsp;either&nbsp;normally&nbsp;or&nbsp;through&nbsp;an&nbsp;unhandled&nbsp;exception<br>
or&nbsp;until&nbsp;the&nbsp;optional&nbsp;timeout&nbsp;occurs.<br>
&nbsp;<br>
When&nbsp;the&nbsp;timeout&nbsp;argument&nbsp;is&nbsp;present&nbsp;and&nbsp;not&nbsp;None,&nbsp;it&nbsp;should&nbsp;be&nbsp;a<br>
floating&nbsp;point&nbsp;number&nbsp;specifying&nbsp;a&nbsp;timeout&nbsp;for&nbsp;the&nbsp;operation&nbsp;in&nbsp;seconds<br>
(or&nbsp;fractions&nbsp;thereof).&nbsp;As&nbsp;<a href="#StoppableThread-join">join</a>()&nbsp;always&nbsp;returns&nbsp;None,&nbsp;you&nbsp;must&nbsp;call<br>
<a href="#StoppableThread-isAlive">isAlive</a>()&nbsp;after&nbsp;<a href="#StoppableThread-join">join</a>()&nbsp;to&nbsp;decide&nbsp;whether&nbsp;a&nbsp;timeout&nbsp;happened&nbsp;--&nbsp;if&nbsp;the<br>
thread&nbsp;is&nbsp;still&nbsp;alive,&nbsp;the&nbsp;<a href="#StoppableThread-join">join</a>()&nbsp;call&nbsp;timed&nbsp;out.<br>
(or&nbsp;fractions&nbsp;thereof).&nbsp;As&nbsp;<a href="#func_timeout.StoppableThread-join">join</a>()&nbsp;always&nbsp;returns&nbsp;None,&nbsp;you&nbsp;must&nbsp;call<br>
<a href="#func_timeout.StoppableThread-is_alive">is_alive</a>()&nbsp;after&nbsp;<a href="#func_timeout.StoppableThread-join">join</a>()&nbsp;to&nbsp;decide&nbsp;whether&nbsp;a&nbsp;timeout&nbsp;happened&nbsp;--&nbsp;if&nbsp;the<br>
thread&nbsp;is&nbsp;still&nbsp;alive,&nbsp;the&nbsp;<a href="#func_timeout.StoppableThread-join">join</a>()&nbsp;call&nbsp;timed&nbsp;out.<br>
&nbsp;<br>
When&nbsp;the&nbsp;timeout&nbsp;argument&nbsp;is&nbsp;not&nbsp;present&nbsp;or&nbsp;None,&nbsp;the&nbsp;operation&nbsp;will<br>
block&nbsp;until&nbsp;the&nbsp;thread&nbsp;terminates.<br>
&nbsp;<br>
A&nbsp;thread&nbsp;can&nbsp;be&nbsp;<a href="#StoppableThread-join">join</a>()ed&nbsp;many&nbsp;times.<br>
A&nbsp;thread&nbsp;can&nbsp;be&nbsp;<a href="#func_timeout.StoppableThread-join">join</a>()ed&nbsp;many&nbsp;times.<br>
&nbsp;<br>
<a href="#StoppableThread-join">join</a>()&nbsp;raises&nbsp;a&nbsp;RuntimeError&nbsp;if&nbsp;an&nbsp;attempt&nbsp;is&nbsp;made&nbsp;to&nbsp;join&nbsp;the&nbsp;current<br>
thread&nbsp;as&nbsp;that&nbsp;would&nbsp;cause&nbsp;a&nbsp;deadlock.&nbsp;It&nbsp;is&nbsp;also&nbsp;an&nbsp;error&nbsp;to&nbsp;<a href="#StoppableThread-join">join</a>()&nbsp;a<br>
<a href="#func_timeout.StoppableThread-join">join</a>()&nbsp;raises&nbsp;a&nbsp;RuntimeError&nbsp;if&nbsp;an&nbsp;attempt&nbsp;is&nbsp;made&nbsp;to&nbsp;join&nbsp;the&nbsp;current<br>
thread&nbsp;as&nbsp;that&nbsp;would&nbsp;cause&nbsp;a&nbsp;deadlock.&nbsp;It&nbsp;is&nbsp;also&nbsp;an&nbsp;error&nbsp;to&nbsp;<a href="#func_timeout.StoppableThread-join">join</a>()&nbsp;a<br>
thread&nbsp;before&nbsp;it&nbsp;has&nbsp;been&nbsp;started&nbsp;and&nbsp;attempts&nbsp;to&nbsp;do&nbsp;so&nbsp;raises&nbsp;the&nbsp;same<br>
exception.</tt></dd></dl>
<dl><dt><a name="StoppableThread-run"><strong>run</strong></a>(self)</dt><dd><tt>Method&nbsp;representing&nbsp;the&nbsp;thread's&nbsp;activity.<br>
&nbsp;<br>
You&nbsp;may&nbsp;override&nbsp;this&nbsp;method&nbsp;in&nbsp;a&nbsp;subclass.&nbsp;The&nbsp;standard&nbsp;<a href="#StoppableThread-run">run</a>()&nbsp;method<br>
You&nbsp;may&nbsp;override&nbsp;this&nbsp;method&nbsp;in&nbsp;a&nbsp;subclass.&nbsp;The&nbsp;standard&nbsp;<a href="#func_timeout.StoppableThread-run">run</a>()&nbsp;method<br>
invokes&nbsp;the&nbsp;callable&nbsp;object&nbsp;passed&nbsp;to&nbsp;the&nbsp;object's&nbsp;constructor&nbsp;as&nbsp;the<br>
target&nbsp;argument,&nbsp;if&nbsp;any,&nbsp;with&nbsp;sequential&nbsp;and&nbsp;keyword&nbsp;arguments&nbsp;taken<br>
from&nbsp;the&nbsp;args&nbsp;and&nbsp;kwargs&nbsp;arguments,&nbsp;respectively.</tt></dd></dl>
@ -255,7 +133,7 @@ from&nbsp;the&nbsp;args&nbsp;and&nbsp;kwargs&nbsp;arguments,&nbsp;respectively.<
<dl><dt><a name="StoppableThread-start"><strong>start</strong></a>(self)</dt><dd><tt>Start&nbsp;the&nbsp;thread's&nbsp;activity.<br>
&nbsp;<br>
It&nbsp;must&nbsp;be&nbsp;called&nbsp;at&nbsp;most&nbsp;once&nbsp;per&nbsp;thread&nbsp;object.&nbsp;It&nbsp;arranges&nbsp;for&nbsp;the<br>
object's&nbsp;<a href="#StoppableThread-run">run</a>()&nbsp;method&nbsp;to&nbsp;be&nbsp;invoked&nbsp;in&nbsp;a&nbsp;separate&nbsp;thread&nbsp;of&nbsp;control.<br>
object's&nbsp;<a href="#func_timeout.StoppableThread-run">run</a>()&nbsp;method&nbsp;to&nbsp;be&nbsp;invoked&nbsp;in&nbsp;a&nbsp;separate&nbsp;thread&nbsp;of&nbsp;control.<br>
&nbsp;<br>
This&nbsp;method&nbsp;will&nbsp;raise&nbsp;a&nbsp;RuntimeError&nbsp;if&nbsp;called&nbsp;more&nbsp;than&nbsp;once&nbsp;on&nbsp;the<br>
same&nbsp;thread&nbsp;object.</tt></dd></dl>
@ -282,7 +160,7 @@ left.</tt></dd>
<dl><dt><strong>ident</strong></dt>
<dd><tt>Thread&nbsp;identifier&nbsp;of&nbsp;this&nbsp;thread&nbsp;or&nbsp;None&nbsp;if&nbsp;it&nbsp;has&nbsp;not&nbsp;been&nbsp;started.<br>
&nbsp;<br>
This&nbsp;is&nbsp;a&nbsp;nonzero&nbsp;integer.&nbsp;See&nbsp;the&nbsp;thread.get_ident()&nbsp;function.&nbsp;Thread<br>
This&nbsp;is&nbsp;a&nbsp;nonzero&nbsp;integer.&nbsp;See&nbsp;the&nbsp;get_ident()&nbsp;function.&nbsp;Thread<br>
identifiers&nbsp;may&nbsp;be&nbsp;recycled&nbsp;when&nbsp;a&nbsp;thread&nbsp;exits&nbsp;and&nbsp;another&nbsp;thread&nbsp;is<br>
created.&nbsp;The&nbsp;identifier&nbsp;is&nbsp;available&nbsp;even&nbsp;after&nbsp;the&nbsp;thread&nbsp;has&nbsp;exited.</tt></dd>
</dl>
@ -292,5 +170,5 @@ created.&nbsp;The&nbsp;identifier&nbsp;is&nbsp;available&nbsp;even&nbsp;after&nb
It&nbsp;has&nbsp;no&nbsp;semantics.&nbsp;Multiple&nbsp;threads&nbsp;may&nbsp;be&nbsp;given&nbsp;the&nbsp;same&nbsp;name.&nbsp;The<br>
initial&nbsp;name&nbsp;is&nbsp;set&nbsp;by&nbsp;the&nbsp;constructor.</tt></dd>
</dl>
</td></tr></table></td></tr></table>
</body></html>
</td></tr></table>
</body></html>

View File

@ -1,59 +1,111 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Python: module func_timeout.dafunc</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head><body bgcolor="#f0f0f8">
<html ><head ><title >Python: module func_timeout.dafunc</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head><body bgcolor="#f0f0f8" >
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
<tr bgcolor="#7799ee">
<td valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="func_timeout.html"><font color="#ffffff">func_timeout</font></a>.dafunc</strong></big></big></font></td
><td align=right valign=bottom
><font color="#ffffff" face="helvetica, arial"><a href="func_timeout.html">index</a></font></td></tr></table>
<p><tt>Copyright&nbsp;(c)&nbsp;2016&nbsp;Tim&nbsp;Savannah&nbsp;All&nbsp;Rights&nbsp;Reserved.<br>
&nbsp;<br>
Licensed&nbsp;under&nbsp;the&nbsp;Lesser&nbsp;GNU&nbsp;Public&nbsp;License&nbsp;Version&nbsp;3,&nbsp;LGPLv3.&nbsp;You&nbsp;should&nbsp;have&nbsp;recieved&nbsp;a&nbsp;copy&nbsp;of&nbsp;this&nbsp;with&nbsp;the&nbsp;source&nbsp;distribution&nbsp;as<br>
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="heading" >
<tr bgcolor="#7799ee" >
<td valign="bottom" >&nbsp;<br />
<font color="#ffffff" face="helvetica, arial" >&nbsp;<br /><big ><big ><strong ><a href="func_timeout.html" ><font color="#ffffff" >func_timeout</font></a>.dafunc</strong></big></big></font></td><td align="right" valign="bottom" ><font color="#ffffff" face="helvetica, arial" ><a href="func_timeout.html" >index</a></font></td></tr></table>
<p ><tt >Copyright&nbsp;(c)&nbsp;2016,&nbsp;2017&nbsp;Tim&nbsp;Savannah&nbsp;All&nbsp;Rights&nbsp;Reserved.<br />
&nbsp;<br />
Licensed&nbsp;under&nbsp;the&nbsp;Lesser&nbsp;GNU&nbsp;Public&nbsp;License&nbsp;Version&nbsp;3,&nbsp;LGPLv3.&nbsp;You&nbsp;should&nbsp;have&nbsp;recieved&nbsp;a&nbsp;copy&nbsp;of&nbsp;this&nbsp;with&nbsp;the&nbsp;source&nbsp;distribution&nbsp;as<br />
LICENSE,&nbsp;otherwise&nbsp;it&nbsp;is&nbsp;available&nbsp;at&nbsp;https://github.com/kata198/func_timeout/LICENSE</tt></p>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#aa55cc">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
<p >
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="section" >
<tr bgcolor="#aa55cc" >
<td colspan="3" valign="bottom" >&nbsp;<br />
<font color="#ffffff" face="helvetica, arial" ><big ><strong >Modules</strong></big></font></td></tr>
<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="threading.html">threading</a><br>
</td><td width="25%" valign=top><a href="time.html">time</a><br>
</td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#eeaa77">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
<tr ><td bgcolor="#aa55cc" ><tt >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td >&nbsp;</td>
<td width="100%" ><table width="100%" summary="list" ><tr ><td width="25%" valign="top" ><a href="copy.html" >copy</a><br />
<a href="inspect.html" >inspect</a><br />
</td><td width="25%" valign="top" ><a href="sys.html" >sys</a><br />
<a href="threading.html" >threading</a><br />
</td><td width="25%" valign="top" ><a href="time.html" >time</a><br />
<a href="types.html" >types</a><br />
</td><td width="25%" valign="top" ></td></tr></table></td></tr></table><p >
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="section" >
<tr bgcolor="#eeaa77" >
<td colspan="3" valign="bottom" >&nbsp;<br />
<font color="#ffffff" face="helvetica, arial" ><big ><strong >Functions</strong></big></font></td></tr>
<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><dl><dt><a name="-func_timeout"><strong>func_timeout</strong></a>(timeout, func, args=(), kwargs=None)</dt><dd><tt>func_timeout&nbsp;-&nbsp;Runs&nbsp;the&nbsp;given&nbsp;function&nbsp;for&nbsp;up&nbsp;to&nbsp;#timeout#&nbsp;seconds.<br>
&nbsp;<br>
Raises&nbsp;any&nbsp;exceptions&nbsp;#func#&nbsp;would&nbsp;raise,&nbsp;returns&nbsp;what&nbsp;#func#&nbsp;would&nbsp;return&nbsp;(unless&nbsp;timeout&nbsp;is&nbsp;exceeded),&nbsp;in&nbsp;which&nbsp;case&nbsp;it&nbsp;raises&nbsp;FunctionTimedOut<br>
&nbsp;<br>
@param&nbsp;timeout&nbsp;&lt;float&gt;&nbsp;-&nbsp;Maximum&nbsp;number&nbsp;of&nbsp;seconds&nbsp;to&nbsp;run&nbsp;#func#&nbsp;before&nbsp;terminating<br>
@param&nbsp;func&nbsp;&lt;function&gt;&nbsp;-&nbsp;The&nbsp;function&nbsp;to&nbsp;call<br>
@param&nbsp;args&nbsp;&nbsp;&nbsp;&nbsp;&lt;tuple&gt;&nbsp;-&nbsp;Any&nbsp;ordered&nbsp;arguments&nbsp;to&nbsp;pass&nbsp;to&nbsp;the&nbsp;function<br>
@param&nbsp;kwargs&nbsp;&nbsp;&lt;dict/None&gt;&nbsp;-&nbsp;Keyword&nbsp;arguments&nbsp;to&nbsp;pass&nbsp;to&nbsp;the&nbsp;function.<br>
&nbsp;<br>
@raises&nbsp;-&nbsp;FunctionTimedOut&nbsp;if&nbsp;#timeout#&nbsp;is&nbsp;exceeded,&nbsp;otherwise&nbsp;anything&nbsp;#func#&nbsp;could&nbsp;raise&nbsp;will&nbsp;be&nbsp;raised<br>
&nbsp;<br>
If&nbsp;the&nbsp;timeout&nbsp;is&nbsp;exceeded,&nbsp;FunctionTimedOut&nbsp;will&nbsp;be&nbsp;raised&nbsp;within&nbsp;the&nbsp;context&nbsp;of&nbsp;the&nbsp;called&nbsp;function&nbsp;every&nbsp;two&nbsp;seconds&nbsp;until&nbsp;it&nbsp;terminates,<br>
but&nbsp;will&nbsp;not&nbsp;block&nbsp;the&nbsp;calling&nbsp;thread&nbsp;(a&nbsp;new&nbsp;thread&nbsp;will&nbsp;be&nbsp;created&nbsp;to&nbsp;perform&nbsp;the&nbsp;join).&nbsp;If&nbsp;possible,&nbsp;you&nbsp;should&nbsp;try/except&nbsp;FunctionTimedOut<br>
to&nbsp;return&nbsp;cleanly,&nbsp;but&nbsp;in&nbsp;most&nbsp;cases&nbsp;it&nbsp;will&nbsp;'just&nbsp;work'.<br>
&nbsp;<br>
Be&nbsp;careful&nbsp;of&nbsp;code&nbsp;like:<br>
def&nbsp;myfunc():<br>
&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;True:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dosomething()<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except&nbsp;Exception:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue<br>
&nbsp;<br>
because&nbsp;it&nbsp;will&nbsp;never&nbsp;terminate.<br>
&nbsp;<br>
<tr ><td bgcolor="#eeaa77" ><tt >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td >&nbsp;</td>
<td width="100%" ><dl ><dt ><a name="-func_set_timeout" ><strong >func_set_timeout</strong></a>(timeout, allowOverride=False)</dt><dd ><tt >func_set_timeout&nbsp;-&nbsp;Decorator&nbsp;to&nbsp;run&nbsp;a&nbsp;function&nbsp;with&nbsp;a&nbsp;given/calculated&nbsp;timeout&nbsp;(max&nbsp;execution&nbsp;time).<br />
&nbsp;&nbsp;&nbsp;&nbsp;Optionally&nbsp;(if&nbsp;#allowOverride&nbsp;is&nbsp;True),&nbsp;adds&nbsp;a&nbsp;paramater,&nbsp;"forceTimeout",&nbsp;to&nbsp;the<br />
&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;which,&nbsp;if&nbsp;provided,&nbsp;will&nbsp;override&nbsp;the&nbsp;default&nbsp;timeout&nbsp;for&nbsp;that&nbsp;invocation.<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;#timeout&nbsp;is&nbsp;provided&nbsp;as&nbsp;a&nbsp;lambda/function,&nbsp;it&nbsp;will&nbsp;be&nbsp;called<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prior&nbsp;to&nbsp;each&nbsp;invocation&nbsp;of&nbsp;the&nbsp;decorated&nbsp;function&nbsp;to&nbsp;calculate&nbsp;the&nbsp;timeout&nbsp;to&nbsp;be&nbsp;used<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;that&nbsp;call,&nbsp;based&nbsp;on&nbsp;the&nbsp;arguments&nbsp;passed&nbsp;to&nbsp;the&nbsp;decorated&nbsp;function.<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;For&nbsp;example,&nbsp;you&nbsp;may&nbsp;have&nbsp;a&nbsp;"processData"&nbsp;function&nbsp;whose&nbsp;execution&nbsp;time<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;depends&nbsp;on&nbsp;the&nbsp;number&nbsp;of&nbsp;"data"&nbsp;elements,&nbsp;so&nbsp;you&nbsp;may&nbsp;want&nbsp;a&nbsp;million&nbsp;elements&nbsp;to&nbsp;have&nbsp;a<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;much&nbsp;higher&nbsp;timeout&nbsp;than&nbsp;seven&nbsp;elements.)<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;#allowOverride&nbsp;is&nbsp;True&nbsp;AND&nbsp;a&nbsp;kwarg&nbsp;of&nbsp;"forceTimeout"&nbsp;is&nbsp;passed&nbsp;to&nbsp;the&nbsp;wrapped&nbsp;function,&nbsp;that&nbsp;timeout<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;will&nbsp;be&nbsp;used&nbsp;for&nbsp;that&nbsp;single&nbsp;call.<br />
&nbsp;<br />
@param&nbsp;timeout&nbsp;&lt;float&nbsp;OR&nbsp;lambda/function&gt;&nbsp;-<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;**If&nbsp;float:**<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Default&nbsp;number&nbsp;of&nbsp;seconds&nbsp;max&nbsp;to&nbsp;allow&nbsp;function&nbsp;to&nbsp;execute<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;before&nbsp;throwing&nbsp;FunctionTimedOut<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;**If&nbsp;lambda/function:<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;a&nbsp;function/lambda&nbsp;is&nbsp;provided,&nbsp;it&nbsp;will&nbsp;be&nbsp;called&nbsp;for&nbsp;every<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;invocation&nbsp;of&nbsp;the&nbsp;decorated&nbsp;function&nbsp;(unless&nbsp;#allowOverride=True&nbsp;and&nbsp;"forceTimeout"&nbsp;was&nbsp;passed)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;determine&nbsp;the&nbsp;timeout&nbsp;to&nbsp;use&nbsp;based&nbsp;on&nbsp;the&nbsp;arguments&nbsp;to&nbsp;the&nbsp;decorated&nbsp;function.<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The&nbsp;arguments&nbsp;as&nbsp;passed&nbsp;into&nbsp;the&nbsp;decorated&nbsp;function&nbsp;will&nbsp;be&nbsp;passed&nbsp;to&nbsp;this&nbsp;function.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;They&nbsp;either&nbsp;must&nbsp;match&nbsp;exactly&nbsp;to&nbsp;what&nbsp;the&nbsp;decorated&nbsp;function&nbsp;has,&nbsp;OR<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;you&nbsp;prefer&nbsp;to&nbsp;get&nbsp;the&nbsp;*args&nbsp;(list&nbsp;of&nbsp;ordered&nbsp;args)&nbsp;and&nbsp;**kwargs&nbsp;(&nbsp;key&nbsp;:&nbsp;value&nbsp;&nbsp;keyword&nbsp;args&nbsp;form),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;define&nbsp;your&nbsp;calculate&nbsp;function&nbsp;like:<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;calculateTimeout(*args,&nbsp;**kwargs):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;or&nbsp;lambda&nbsp;like:<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;calculateTimeout&nbsp;=&nbsp;lambda&nbsp;*args,&nbsp;**kwargs&nbsp;:&nbsp;...<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;otherwise&nbsp;the&nbsp;args&nbsp;to&nbsp;your&nbsp;calculate&nbsp;function&nbsp;should&nbsp;match&nbsp;exactly&nbsp;the&nbsp;decorated&nbsp;function.<br />
&nbsp;<br />
&nbsp;<br />
@param&nbsp;allowOverride&nbsp;&lt;bool&gt;&nbsp;Default&nbsp;False,&nbsp;if&nbsp;True&nbsp;adds&nbsp;a&nbsp;keyword&nbsp;argument&nbsp;to&nbsp;the&nbsp;decorated&nbsp;function,<br />
&nbsp;&nbsp;&nbsp;&nbsp;"forceTimeout"&nbsp;which,&nbsp;if&nbsp;provided,&nbsp;will&nbsp;override&nbsp;the&nbsp;#timeout.&nbsp;If&nbsp;#timeout&nbsp;was&nbsp;provided&nbsp;as&nbsp;a&nbsp;lambda&nbsp;/&nbsp;function,&nbsp;it<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;will&nbsp;not&nbsp;be&nbsp;called.<br />
&nbsp;<br />
@throws&nbsp;FunctionTimedOut&nbsp;If&nbsp;time&nbsp;alloted&nbsp;passes&nbsp;without&nbsp;function&nbsp;returning&nbsp;naturally<br />
&nbsp;<br />
@see&nbsp;func_timeout</tt></dd></dl>
<dl ><dt ><a name="-func_timeout" ><strong >func_timeout</strong></a>(timeout, func, args=(), kwargs=None)</dt><dd ><tt >func_timeout&nbsp;-&nbsp;Runs&nbsp;the&nbsp;given&nbsp;function&nbsp;for&nbsp;up&nbsp;to&nbsp;#timeout#&nbsp;seconds.<br />
&nbsp;<br />
Raises&nbsp;any&nbsp;exceptions&nbsp;#func#&nbsp;would&nbsp;raise,&nbsp;returns&nbsp;what&nbsp;#func#&nbsp;would&nbsp;return&nbsp;(unless&nbsp;timeout&nbsp;is&nbsp;exceeded),&nbsp;in&nbsp;which&nbsp;case&nbsp;it&nbsp;raises&nbsp;FunctionTimedOut<br />
&nbsp;<br />
@param&nbsp;timeout&nbsp;&lt;float&gt;&nbsp;-&nbsp;Maximum&nbsp;number&nbsp;of&nbsp;seconds&nbsp;to&nbsp;run&nbsp;#func#&nbsp;before&nbsp;terminating<br />
&nbsp;<br />
@param&nbsp;func&nbsp;&lt;function&gt;&nbsp;-&nbsp;The&nbsp;function&nbsp;to&nbsp;call<br />
&nbsp;<br />
@param&nbsp;args&nbsp;&nbsp;&nbsp;&nbsp;&lt;tuple&gt;&nbsp;-&nbsp;Any&nbsp;ordered&nbsp;arguments&nbsp;to&nbsp;pass&nbsp;to&nbsp;the&nbsp;function<br />
&nbsp;<br />
@param&nbsp;kwargs&nbsp;&nbsp;&lt;dict/None&gt;&nbsp;-&nbsp;Keyword&nbsp;arguments&nbsp;to&nbsp;pass&nbsp;to&nbsp;the&nbsp;function.<br />
&nbsp;<br />
&nbsp;<br />
@raises&nbsp;-&nbsp;FunctionTimedOut&nbsp;if&nbsp;#timeout#&nbsp;is&nbsp;exceeded,&nbsp;otherwise&nbsp;anything&nbsp;#func#&nbsp;could&nbsp;raise&nbsp;will&nbsp;be&nbsp;raised<br />
&nbsp;<br />
If&nbsp;the&nbsp;timeout&nbsp;is&nbsp;exceeded,&nbsp;FunctionTimedOut&nbsp;will&nbsp;be&nbsp;raised&nbsp;within&nbsp;the&nbsp;context&nbsp;of&nbsp;the&nbsp;called&nbsp;function&nbsp;every&nbsp;two&nbsp;seconds&nbsp;until&nbsp;it&nbsp;terminates,<br />
but&nbsp;will&nbsp;not&nbsp;block&nbsp;the&nbsp;calling&nbsp;thread&nbsp;(a&nbsp;new&nbsp;thread&nbsp;will&nbsp;be&nbsp;created&nbsp;to&nbsp;perform&nbsp;the&nbsp;join).&nbsp;If&nbsp;possible,&nbsp;you&nbsp;should&nbsp;try/except&nbsp;FunctionTimedOut<br />
to&nbsp;return&nbsp;cleanly,&nbsp;but&nbsp;in&nbsp;most&nbsp;cases&nbsp;it&nbsp;will&nbsp;'just&nbsp;work'.<br />
&nbsp;<br />
@return&nbsp;-&nbsp;The&nbsp;return&nbsp;value&nbsp;that&nbsp;#func#&nbsp;gives</tt></dd></dl>
</td></tr></table>
</body></html>
</td></tr></table><p >
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="section" >
<tr bgcolor="#55aa55" >
<td colspan="3" valign="bottom" >&nbsp;<br />
<font color="#ffffff" face="helvetica, arial" ><big ><strong >Data</strong></big></font></td></tr>
<tr ><td bgcolor="#55aa55" ><tt >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td >&nbsp;</td>
<td width="100%" ><strong >__all__</strong> = ('func_timeout', 'func_set_timeout')</td></tr></table>
</p></p></p></body></html>

View File

@ -1,87 +1,137 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Python: module func_timeout.exceptions</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head><body bgcolor="#f0f0f8">
<html ><head ><title >Python: module func_timeout.exceptions</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head><body bgcolor="#f0f0f8" >
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
<tr bgcolor="#7799ee">
<td valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="func_timeout.html"><font color="#ffffff">func_timeout</font></a>.exceptions</strong></big></big></font></td
><td align=right valign=bottom
><font color="#ffffff" face="helvetica, arial"><a href="func_timeout.html">index</a></font></td></tr></table>
<p></p>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ee77aa">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="heading" >
<tr bgcolor="#7799ee" >
<td valign="bottom" >&nbsp;<br />
<font color="#ffffff" face="helvetica, arial" >&nbsp;<br /><big ><big ><strong ><a href="func_timeout.html" ><font color="#ffffff" >func_timeout</font></a>.exceptions</strong></big></big></font></td><td align="right" valign="bottom" ><font color="#ffffff" face="helvetica, arial" ><a href="func_timeout.html" >index</a></font></td></tr></table>
<p ><tt >Copyright&nbsp;(c)&nbsp;2016&nbsp;Tim&nbsp;Savannah&nbsp;All&nbsp;Rights&nbsp;Reserved.<br />
&nbsp;<br />
Licensed&nbsp;under&nbsp;the&nbsp;Lesser&nbsp;GNU&nbsp;Public&nbsp;License&nbsp;Version&nbsp;3,&nbsp;LGPLv3.&nbsp;You&nbsp;should&nbsp;have&nbsp;recieved&nbsp;a&nbsp;copy&nbsp;of&nbsp;this&nbsp;with&nbsp;the&nbsp;source&nbsp;distribution&nbsp;as<br />
LICENSE,&nbsp;otherwise&nbsp;it&nbsp;is&nbsp;available&nbsp;at&nbsp;https://github.com/kata198/func_timeout/LICENSE</tt></p>
<p >
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="section" >
<tr bgcolor="#ee77aa" >
<td colspan="3" valign="bottom" >&nbsp;<br />
<font color="#ffffff" face="helvetica, arial" ><big ><strong >Classes</strong></big></font></td></tr>
<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><dl>
<dt><font face="helvetica, arial"><a href="builtins.html#BaseException">builtins.BaseException</a>(<a href="builtins.html#object">builtins.object</a>)
</font></dt><dd>
<dl>
<dt><font face="helvetica, arial"><a href="func_timeout.exceptions.html#FunctionTimedOut">FunctionTimedOut</a>
<tr ><td bgcolor="#ee77aa" ><tt >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td >&nbsp;</td>
<td width="100%" ><dl >
<dt ><font face="helvetica, arial" ><a href="builtins.html#BaseException" >builtins.BaseException</a>(<a href="builtins.html#object" >builtins.object</a>)
</font></dt><dd >
<dl >
<dt ><font face="helvetica, arial" ><a href="func_timeout.exceptions.html#FunctionTimedOut" >FunctionTimedOut</a>
</font></dt></dl>
</dd>
</dl>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ffc8d8">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#000000" face="helvetica, arial"><a name="FunctionTimedOut">class <strong>FunctionTimedOut</strong></a>(<a href="builtins.html#BaseException">builtins.BaseException</a>)</font></td></tr>
<p >
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="section" >
<tr bgcolor="#ffc8d8" >
<td colspan="3" valign="bottom" >&nbsp;<br />
<font color="#000000" face="helvetica, arial" ><a name="FunctionTimedOut" >class <strong >FunctionTimedOut</strong></a>(<a href="builtins.html#BaseException" >builtins.BaseException</a>)</font></td></tr>
<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
<td colspan=2><tt>Common&nbsp;base&nbsp;class&nbsp;for&nbsp;all&nbsp;exceptions<br>&nbsp;</tt></td></tr>
<tr><td>&nbsp;</td>
<td width="100%"><dl><dt>Method resolution order:</dt>
<dd><a href="func_timeout.exceptions.html#FunctionTimedOut">FunctionTimedOut</a></dd>
<dd><a href="builtins.html#BaseException">builtins.BaseException</a></dd>
<dd><a href="builtins.html#object">builtins.object</a></dd>
<tr bgcolor="#ffc8d8" ><td rowspan="2" ><tt >&nbsp;&nbsp;&nbsp;</tt></td>
<td colspan="2" ><tt ><a href="#FunctionTimedOut" >FunctionTimedOut</a>(msg='',&nbsp;timedOutAfter=None,&nbsp;timedOutFunction=None,&nbsp;timedOutArgs=None,&nbsp;timedOutKwargs=None)<br />
&nbsp;<br />
<a href="#FunctionTimedOut" >FunctionTimedOut</a>&nbsp;-&nbsp;Exception&nbsp;raised&nbsp;when&nbsp;a&nbsp;function&nbsp;times&nbsp;out<br />
&nbsp;<br />
@property&nbsp;timedOutAfter&nbsp;-&nbsp;Number&nbsp;of&nbsp;seconds&nbsp;before&nbsp;timeout&nbsp;was&nbsp;triggered<br />
&nbsp;<br />
@property&nbsp;timedOutFunction&nbsp;-&nbsp;Function&nbsp;called&nbsp;which&nbsp;timed&nbsp;out<br />
@property&nbsp;timedOutArgs&nbsp;-&nbsp;Ordered&nbsp;args&nbsp;to&nbsp;function<br />
@property&nbsp;timedOutKwargs&nbsp;-&nbsp;Keyword&nbsp;args&nbsp;to&nbsp;function<br />
&nbsp;<br />
@method&nbsp;retry&nbsp;-&nbsp;Retries&nbsp;the&nbsp;function&nbsp;with&nbsp;same&nbsp;arguments,&nbsp;with&nbsp;option&nbsp;to&nbsp;run&nbsp;with&nbsp;original&nbsp;timeout,&nbsp;no&nbsp;timeout,&nbsp;or&nbsp;a&nbsp;different<br />
&nbsp;&nbsp;explicit&nbsp;timeout.&nbsp;@see&nbsp;<a href="#FunctionTimedOut" >FunctionTimedOut</a>.retry<br />&nbsp;</tt></td></tr>
<tr ><td >&nbsp;</td>
<td width="100%" ><dl ><dt >Method resolution order:</dt>
<dd ><a href="func_timeout.exceptions.html#FunctionTimedOut" >FunctionTimedOut</a></dd>
<dd ><a href="builtins.html#BaseException" >builtins.BaseException</a></dd>
<dd ><a href="builtins.html#object" >builtins.object</a></dd>
</dl>
<hr>
Data descriptors defined here:<br>
<dl><dt><strong>__weakref__</strong></dt>
<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
<hr />
Methods defined here:<br />
<dl ><dt ><a name="FunctionTimedOut-__init__" ><strong >__init__</strong></a>(self, msg='', timedOutAfter=None, timedOutFunction=None, timedOutArgs=None, timedOutKwargs=None)</dt><dd ><tt >__init__&nbsp;-&nbsp;Create&nbsp;this&nbsp;exception&nbsp;type.<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;You&nbsp;should&nbsp;not&nbsp;need&nbsp;to&nbsp;do&nbsp;this&nbsp;outside&nbsp;of&nbsp;testing,&nbsp;it&nbsp;will&nbsp;be&nbsp;created&nbsp;by&nbsp;the&nbsp;func_timeout&nbsp;API<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@param&nbsp;msg&nbsp;&lt;str&gt;&nbsp;-&nbsp;A&nbsp;predefined&nbsp;message,&nbsp;otherwise&nbsp;we&nbsp;will&nbsp;attempt&nbsp;to&nbsp;generate&nbsp;one&nbsp;from&nbsp;the&nbsp;other&nbsp;arguments.<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@param&nbsp;timedOutAfter&nbsp;&lt;None/float&gt;&nbsp;-&nbsp;Number&nbsp;of&nbsp;seconds&nbsp;before&nbsp;timing-out.&nbsp;Filled-in&nbsp;by&nbsp;API,&nbsp;None&nbsp;will&nbsp;produce&nbsp;"Unknown"<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@param&nbsp;timedOutFunction&nbsp;&lt;None/function&gt;&nbsp;-&nbsp;Reference&nbsp;to&nbsp;the&nbsp;function&nbsp;that&nbsp;timed-out.&nbsp;Filled-in&nbsp;by&nbsp;API."&nbsp;None&nbsp;will&nbsp;produce&nbsp;"Unknown&nbsp;Function"<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@param&nbsp;timedOutArgs&nbsp;&lt;None/tuple/list&gt;&nbsp;-&nbsp;List&nbsp;of&nbsp;fixed-order&nbsp;arguments&nbsp;(&nbsp;*args&nbsp;),&nbsp;or&nbsp;None&nbsp;for&nbsp;no&nbsp;args.<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@param&nbsp;timedOutKwargs&nbsp;&lt;None/dict&gt;&nbsp;-&nbsp;Dict&nbsp;of&nbsp;keyword&nbsp;arg&nbsp;(&nbsp;**kwargs&nbsp;)&nbsp;names&nbsp;to&nbsp;values,&nbsp;or&nbsp;None&nbsp;for&nbsp;no&nbsp;kwargs.</tt></dd></dl>
<dl ><dt ><a name="FunctionTimedOut-getMsg" ><strong >getMsg</strong></a>(self)</dt><dd ><tt >getMsg&nbsp;-&nbsp;Generate&nbsp;a&nbsp;default&nbsp;message&nbsp;based&nbsp;on&nbsp;parameters&nbsp;to&nbsp;<a href="#FunctionTimedOut" >FunctionTimedOut</a>&nbsp;exception'<br />
&nbsp;<br />
@return&nbsp;&lt;str&gt;&nbsp;-&nbsp;Message</tt></dd></dl>
<dl ><dt ><a name="FunctionTimedOut-retry" ><strong >retry</strong></a>(self, timeout='RETRY_SAME_TIMEOUT')</dt><dd ><tt >retry&nbsp;-&nbsp;Retry&nbsp;the&nbsp;timed-out&nbsp;function&nbsp;with&nbsp;same&nbsp;arguments.<br />
&nbsp;<br />
@param&nbsp;timeout&nbsp;&lt;float/RETRY_SAME_TIMEOUT/None&gt;&nbsp;Default&nbsp;RETRY_SAME_TIMEOUT<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;RETRY_SAME_TIMEOUT&nbsp;:&nbsp;Will&nbsp;retry&nbsp;the&nbsp;function&nbsp;same&nbsp;args,&nbsp;same&nbsp;timeout<br />
&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;a&nbsp;float/int&nbsp;:&nbsp;Will&nbsp;retry&nbsp;the&nbsp;function&nbsp;same&nbsp;args&nbsp;with&nbsp;provided&nbsp;timeout<br />
&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;None&nbsp;:&nbsp;Will&nbsp;retry&nbsp;function&nbsp;same&nbsp;args&nbsp;no&nbsp;timeout<br />
&nbsp;<br />
@return&nbsp;-&nbsp;Returnval&nbsp;from&nbsp;function</tt></dd></dl>
<hr />
Data descriptors defined here:<br />
<dl ><dt ><strong >__weakref__</strong></dt>
<dd ><tt >list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
</dl>
<hr>
Methods inherited from <a href="builtins.html#BaseException">builtins.BaseException</a>:<br>
<dl><dt><a name="FunctionTimedOut-__delattr__"><strong>__delattr__</strong></a>(self, name, /)</dt><dd><tt>Implement&nbsp;delattr(self,&nbsp;name).</tt></dd></dl>
<hr />
Methods inherited from <a href="builtins.html#BaseException" >builtins.BaseException</a>:<br />
<dl ><dt ><a name="FunctionTimedOut-__delattr__" ><strong >__delattr__</strong></a>(self, name, /)</dt><dd ><tt >Implement&nbsp;delattr(self,&nbsp;name).</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-__getattribute__"><strong>__getattribute__</strong></a>(self, name, /)</dt><dd><tt>Return&nbsp;getattr(self,&nbsp;name).</tt></dd></dl>
<dl ><dt ><a name="FunctionTimedOut-__getattribute__" ><strong >__getattribute__</strong></a>(self, name, /)</dt><dd ><tt >Return&nbsp;getattr(self,&nbsp;name).</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-__init__"><strong>__init__</strong></a>(self, /, *args, **kwargs)</dt><dd><tt>Initialize&nbsp;self.&nbsp;&nbsp;See&nbsp;help(type(self))&nbsp;for&nbsp;accurate&nbsp;signature.</tt></dd></dl>
<dl ><dt ><a name="FunctionTimedOut-__reduce__" ><strong >__reduce__</strong></a>(...)</dt><dd ><tt >Helper&nbsp;for&nbsp;pickle.</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-__new__"><strong>__new__</strong></a>(*args, **kwargs)<font color="#909090"><font face="helvetica, arial"> from <a href="builtins.html#type">builtins.type</a></font></font></dt><dd><tt>Create&nbsp;and&nbsp;return&nbsp;a&nbsp;new&nbsp;object.&nbsp;&nbsp;See&nbsp;help(type)&nbsp;for&nbsp;accurate&nbsp;signature.</tt></dd></dl>
<dl ><dt ><a name="FunctionTimedOut-__repr__" ><strong >__repr__</strong></a>(self, /)</dt><dd ><tt >Return&nbsp;repr(self).</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-__reduce__"><strong>__reduce__</strong></a>(...)</dt><dd><tt>helper&nbsp;for&nbsp;pickle</tt></dd></dl>
<dl ><dt ><a name="FunctionTimedOut-__setattr__" ><strong >__setattr__</strong></a>(self, name, value, /)</dt><dd ><tt >Implement&nbsp;setattr(self,&nbsp;name,&nbsp;value).</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-__repr__"><strong>__repr__</strong></a>(self, /)</dt><dd><tt>Return&nbsp;repr(self).</tt></dd></dl>
<dl ><dt ><a name="FunctionTimedOut-__setstate__" ><strong >__setstate__</strong></a>(...)</dt></dl>
<dl><dt><a name="FunctionTimedOut-__setattr__"><strong>__setattr__</strong></a>(self, name, value, /)</dt><dd><tt>Implement&nbsp;setattr(self,&nbsp;name,&nbsp;value).</tt></dd></dl>
<dl ><dt ><a name="FunctionTimedOut-__str__" ><strong >__str__</strong></a>(self, /)</dt><dd ><tt >Return&nbsp;str(self).</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
<dl ><dt ><a name="FunctionTimedOut-with_traceback" ><strong >with_traceback</strong></a>(...)</dt><dd ><tt >Exception.<a href="#FunctionTimedOut-with_traceback" >with_traceback</a>(tb)&nbsp;--<br />
set&nbsp;self.<strong >__traceback__</strong>&nbsp;to&nbsp;tb&nbsp;and&nbsp;return&nbsp;self.</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-__str__"><strong>__str__</strong></a>(self, /)</dt><dd><tt>Return&nbsp;str(self).</tt></dd></dl>
<hr />
Static methods inherited from <a href="builtins.html#BaseException" >builtins.BaseException</a>:<br />
<dl ><dt ><a name="FunctionTimedOut-__new__" ><strong >__new__</strong></a>(*args, **kwargs)<font color="#909090" ><font face="helvetica, arial" > from <a href="builtins.html#type" >builtins.type</a></font></font></dt><dd ><tt >Create&nbsp;and&nbsp;return&nbsp;a&nbsp;new&nbsp;object.&nbsp;&nbsp;See&nbsp;help(type)&nbsp;for&nbsp;accurate&nbsp;signature.</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-with_traceback"><strong>with_traceback</strong></a>(...)</dt><dd><tt>Exception.<a href="#FunctionTimedOut-with_traceback">with_traceback</a>(tb)&nbsp;--<br>
set&nbsp;self.<strong>__traceback__</strong>&nbsp;to&nbsp;tb&nbsp;and&nbsp;return&nbsp;self.</tt></dd></dl>
<hr>
Data descriptors inherited from <a href="builtins.html#BaseException">builtins.BaseException</a>:<br>
<dl><dt><strong>__cause__</strong></dt>
<dd><tt>exception&nbsp;cause</tt></dd>
<hr />
Data descriptors inherited from <a href="builtins.html#BaseException" >builtins.BaseException</a>:<br />
<dl ><dt ><strong >__cause__</strong></dt>
<dd ><tt >exception&nbsp;cause</tt></dd>
</dl>
<dl><dt><strong>__context__</strong></dt>
<dd><tt>exception&nbsp;context</tt></dd>
<dl ><dt ><strong >__context__</strong></dt>
<dd ><tt >exception&nbsp;context</tt></dd>
</dl>
<dl><dt><strong>__dict__</strong></dt>
<dl ><dt ><strong >__dict__</strong></dt>
</dl>
<dl><dt><strong>__suppress_context__</strong></dt>
<dl ><dt ><strong >__suppress_context__</strong></dt>
</dl>
<dl><dt><strong>__traceback__</strong></dt>
<dl ><dt ><strong >__traceback__</strong></dt>
</dl>
<dl><dt><strong>args</strong></dt>
<dl ><dt ><strong >args</strong></dt>
</dl>
</td></tr></table></td></tr></table>
</body></html>
</td></tr></table></p></td></tr></table><p >
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="section" >
<tr bgcolor="#55aa55" >
<td colspan="3" valign="bottom" >&nbsp;<br />
<font color="#ffffff" face="helvetica, arial" ><big ><strong >Data</strong></big></font></td></tr>
<tr ><td bgcolor="#55aa55" ><tt >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td >&nbsp;</td>
<td width="100%" ><strong >RETRY_SAME_TIMEOUT</strong> = 'RETRY_SAME_TIMEOUT'<br />
<strong >__all__</strong> = ('FunctionTimedOut', 'RETRY_SAME_TIMEOUT')</td></tr></table>
</p></p></body></html>

View File

@ -1,141 +1,399 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Python: package func_timeout</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head><body bgcolor="#f0f0f8">
<html ><head ><title >Python: package func_timeout</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head><body bgcolor="#f0f0f8" >
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
<tr bgcolor="#7799ee">
<td valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong>func_timeout</strong></big></big> (version 3.1.0)</font></td
><td align=right valign=bottom
><font color="#ffffff" face="helvetica, arial"><a href="func_timeout.html">index</a></font></td></tr></table>
<p><tt>Copyright&nbsp;(c)&nbsp;2016&nbsp;Tim&nbsp;Savannah&nbsp;All&nbsp;Rights&nbsp;Reserved.<br>
&nbsp;<br>
Licensed&nbsp;under&nbsp;the&nbsp;Lesser&nbsp;GNU&nbsp;Public&nbsp;License&nbsp;Version&nbsp;3,&nbsp;LGPLv3.&nbsp;You&nbsp;should&nbsp;have&nbsp;recieved&nbsp;a&nbsp;copy&nbsp;of&nbsp;this&nbsp;with&nbsp;the&nbsp;source&nbsp;distribution&nbsp;as<br>
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="heading" >
<tr bgcolor="#7799ee" >
<td valign="bottom" >&nbsp;<br />
<font color="#ffffff" face="helvetica, arial" >&nbsp;<br /><big ><big ><strong >func_timeout</strong></big></big> (version 4.3.5)</font></td><td align="right" valign="bottom" ><font color="#ffffff" face="helvetica, arial" ><a href="func_timeout.html" >index</a></font></td></tr></table>
<p ><tt >Copyright&nbsp;(c)&nbsp;2016,&nbsp;2017,&nbsp;2019&nbsp;Tim&nbsp;Savannah&nbsp;All&nbsp;Rights&nbsp;Reserved.<br />
&nbsp;<br />
Licensed&nbsp;under&nbsp;the&nbsp;Lesser&nbsp;GNU&nbsp;Public&nbsp;License&nbsp;Version&nbsp;3,&nbsp;LGPLv3.&nbsp;You&nbsp;should&nbsp;have&nbsp;recieved&nbsp;a&nbsp;copy&nbsp;of&nbsp;this&nbsp;with&nbsp;the&nbsp;source&nbsp;distribution&nbsp;as<br />
LICENSE,&nbsp;otherwise&nbsp;it&nbsp;is&nbsp;available&nbsp;at&nbsp;https://github.com/kata198/func_timeout/LICENSE</tt></p>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#aa55cc">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Package Contents</strong></big></font></td></tr>
<p >
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="section" >
<tr bgcolor="#aa55cc" >
<td colspan="3" valign="bottom" >&nbsp;<br />
<font color="#ffffff" face="helvetica, arial" ><big ><strong >Package Contents</strong></big></font></td></tr>
<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="func_timeout.StoppableThread.html">StoppableThread</a><br>
</td><td width="25%" valign=top><a href="func_timeout.dafunc.html">dafunc</a><br>
</td><td width="25%" valign=top><a href="func_timeout.exceptions.html">exceptions</a><br>
</td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ee77aa">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
<tr ><td bgcolor="#aa55cc" ><tt >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td >&nbsp;</td>
<td width="100%" ><table width="100%" summary="list" ><tr ><td width="25%" valign="top" ><a href="func_timeout.StoppableThread.html" >StoppableThread</a><br />
<a href="func_timeout.dafunc.html" >dafunc</a><br />
</td><td width="25%" valign="top" ><a href="func_timeout.exceptions.html" >exceptions</a><br />
<a href="func_timeout.py2_raise.html" >py2_raise</a><br />
</td><td width="25%" valign="top" ><a href="func_timeout.py3_raise.html" >py3_raise</a><br />
</td><td width="25%" valign="top" ></td></tr></table></td></tr></table><p >
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="section" >
<tr bgcolor="#ee77aa" >
<td colspan="3" valign="bottom" >&nbsp;<br />
<font color="#ffffff" face="helvetica, arial" ><big ><strong >Classes</strong></big></font></td></tr>
<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><dl>
<dt><font face="helvetica, arial"><a href="builtins.html#BaseException">builtins.BaseException</a>(<a href="builtins.html#object">builtins.object</a>)
</font></dt><dd>
<dl>
<dt><font face="helvetica, arial"><a href="func_timeout.exceptions.html#FunctionTimedOut">func_timeout.exceptions.FunctionTimedOut</a>
<tr ><td bgcolor="#ee77aa" ><tt >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td >&nbsp;</td>
<td width="100%" ><dl >
<dt ><font face="helvetica, arial" ><a href="builtins.html#BaseException" >builtins.BaseException</a>(<a href="builtins.html#object" >builtins.object</a>)
</font></dt><dd >
<dl >
<dt ><font face="helvetica, arial" ><a href="func_timeout.exceptions.html#FunctionTimedOut" >func_timeout.exceptions.FunctionTimedOut</a>
</font></dt></dl>
</dd>
<dt ><font face="helvetica, arial" ><a href="threading.html#Thread" >threading.Thread</a>(<a href="builtins.html#object" >builtins.object</a>)
</font></dt><dd >
<dl >
<dt ><font face="helvetica, arial" ><a href="func_timeout.StoppableThread.html#StoppableThread" >func_timeout.StoppableThread.StoppableThread</a>
</font></dt></dl>
</dd>
</dl>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ffc8d8">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#000000" face="helvetica, arial"><a name="FunctionTimedOut">class <strong>FunctionTimedOut</strong></a>(<a href="builtins.html#BaseException">builtins.BaseException</a>)</font></td></tr>
<p >
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="section" >
<tr bgcolor="#ffc8d8" >
<td colspan="3" valign="bottom" >&nbsp;<br />
<font color="#000000" face="helvetica, arial" ><a name="FunctionTimedOut" >class <strong >FunctionTimedOut</strong></a>(<a href="builtins.html#BaseException" >builtins.BaseException</a>)</font></td></tr>
<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
<td colspan=2><tt><a href="#FunctionTimedOut">FunctionTimedOut</a>&nbsp;-&nbsp;Exception&nbsp;raised&nbsp;when&nbsp;a&nbsp;function&nbsp;times&nbsp;out<br>&nbsp;</tt></td></tr>
<tr><td>&nbsp;</td>
<td width="100%"><dl><dt>Method resolution order:</dt>
<dd><a href="func_timeout.exceptions.html#FunctionTimedOut">FunctionTimedOut</a></dd>
<dd><a href="builtins.html#BaseException">builtins.BaseException</a></dd>
<dd><a href="builtins.html#object">builtins.object</a></dd>
<tr bgcolor="#ffc8d8" ><td rowspan="2" ><tt >&nbsp;&nbsp;&nbsp;</tt></td>
<td colspan="2" ><tt ><a href="#FunctionTimedOut" >FunctionTimedOut</a>(msg='',&nbsp;timedOutAfter=None,&nbsp;timedOutFunction=None,&nbsp;timedOutArgs=None,&nbsp;timedOutKwargs=None)<br />
&nbsp;<br />
<a href="#FunctionTimedOut" >FunctionTimedOut</a>&nbsp;-&nbsp;Exception&nbsp;raised&nbsp;when&nbsp;a&nbsp;function&nbsp;times&nbsp;out<br />
&nbsp;<br />
@property&nbsp;timedOutAfter&nbsp;-&nbsp;Number&nbsp;of&nbsp;seconds&nbsp;before&nbsp;timeout&nbsp;was&nbsp;triggered<br />
&nbsp;<br />
@property&nbsp;timedOutFunction&nbsp;-&nbsp;Function&nbsp;called&nbsp;which&nbsp;timed&nbsp;out<br />
@property&nbsp;timedOutArgs&nbsp;-&nbsp;Ordered&nbsp;args&nbsp;to&nbsp;function<br />
@property&nbsp;timedOutKwargs&nbsp;-&nbsp;Keyword&nbsp;args&nbsp;to&nbsp;function<br />
&nbsp;<br />
@method&nbsp;retry&nbsp;-&nbsp;Retries&nbsp;the&nbsp;function&nbsp;with&nbsp;same&nbsp;arguments,&nbsp;with&nbsp;option&nbsp;to&nbsp;run&nbsp;with&nbsp;original&nbsp;timeout,&nbsp;no&nbsp;timeout,&nbsp;or&nbsp;a&nbsp;different<br />
&nbsp;&nbsp;explicit&nbsp;timeout.&nbsp;@see&nbsp;<a href="#FunctionTimedOut" >FunctionTimedOut</a>.retry<br />&nbsp;</tt></td></tr>
<tr ><td >&nbsp;</td>
<td width="100%" ><dl ><dt >Method resolution order:</dt>
<dd ><a href="func_timeout.exceptions.html#FunctionTimedOut" >FunctionTimedOut</a></dd>
<dd ><a href="builtins.html#BaseException" >builtins.BaseException</a></dd>
<dd ><a href="builtins.html#object" >builtins.object</a></dd>
</dl>
<hr>
Data descriptors defined here:<br>
<dl><dt><strong>__weakref__</strong></dt>
<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
<hr />
Methods defined here:<br />
<dl ><dt ><a name="FunctionTimedOut-__init__" ><strong >__init__</strong></a>(self, msg='', timedOutAfter=None, timedOutFunction=None, timedOutArgs=None, timedOutKwargs=None)</dt><dd ><tt >__init__&nbsp;-&nbsp;Create&nbsp;this&nbsp;exception&nbsp;type.<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;You&nbsp;should&nbsp;not&nbsp;need&nbsp;to&nbsp;do&nbsp;this&nbsp;outside&nbsp;of&nbsp;testing,&nbsp;it&nbsp;will&nbsp;be&nbsp;created&nbsp;by&nbsp;the&nbsp;func_timeout&nbsp;API<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@param&nbsp;msg&nbsp;&lt;str&gt;&nbsp;-&nbsp;A&nbsp;predefined&nbsp;message,&nbsp;otherwise&nbsp;we&nbsp;will&nbsp;attempt&nbsp;to&nbsp;generate&nbsp;one&nbsp;from&nbsp;the&nbsp;other&nbsp;arguments.<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@param&nbsp;timedOutAfter&nbsp;&lt;None/float&gt;&nbsp;-&nbsp;Number&nbsp;of&nbsp;seconds&nbsp;before&nbsp;timing-out.&nbsp;Filled-in&nbsp;by&nbsp;API,&nbsp;None&nbsp;will&nbsp;produce&nbsp;"Unknown"<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@param&nbsp;timedOutFunction&nbsp;&lt;None/function&gt;&nbsp;-&nbsp;Reference&nbsp;to&nbsp;the&nbsp;function&nbsp;that&nbsp;timed-out.&nbsp;Filled-in&nbsp;by&nbsp;API."&nbsp;None&nbsp;will&nbsp;produce&nbsp;"Unknown&nbsp;Function"<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@param&nbsp;timedOutArgs&nbsp;&lt;None/tuple/list&gt;&nbsp;-&nbsp;List&nbsp;of&nbsp;fixed-order&nbsp;arguments&nbsp;(&nbsp;*args&nbsp;),&nbsp;or&nbsp;None&nbsp;for&nbsp;no&nbsp;args.<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@param&nbsp;timedOutKwargs&nbsp;&lt;None/dict&gt;&nbsp;-&nbsp;Dict&nbsp;of&nbsp;keyword&nbsp;arg&nbsp;(&nbsp;**kwargs&nbsp;)&nbsp;names&nbsp;to&nbsp;values,&nbsp;or&nbsp;None&nbsp;for&nbsp;no&nbsp;kwargs.</tt></dd></dl>
<dl ><dt ><a name="FunctionTimedOut-getMsg" ><strong >getMsg</strong></a>(self)</dt><dd ><tt >getMsg&nbsp;-&nbsp;Generate&nbsp;a&nbsp;default&nbsp;message&nbsp;based&nbsp;on&nbsp;parameters&nbsp;to&nbsp;<a href="#FunctionTimedOut" >FunctionTimedOut</a>&nbsp;exception'<br />
&nbsp;<br />
@return&nbsp;&lt;str&gt;&nbsp;-&nbsp;Message</tt></dd></dl>
<dl ><dt ><a name="FunctionTimedOut-retry" ><strong >retry</strong></a>(self, timeout='RETRY_SAME_TIMEOUT')</dt><dd ><tt >retry&nbsp;-&nbsp;Retry&nbsp;the&nbsp;timed-out&nbsp;function&nbsp;with&nbsp;same&nbsp;arguments.<br />
&nbsp;<br />
@param&nbsp;timeout&nbsp;&lt;float/RETRY_SAME_TIMEOUT/None&gt;&nbsp;Default&nbsp;RETRY_SAME_TIMEOUT<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;RETRY_SAME_TIMEOUT&nbsp;:&nbsp;Will&nbsp;retry&nbsp;the&nbsp;function&nbsp;same&nbsp;args,&nbsp;same&nbsp;timeout<br />
&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;a&nbsp;float/int&nbsp;:&nbsp;Will&nbsp;retry&nbsp;the&nbsp;function&nbsp;same&nbsp;args&nbsp;with&nbsp;provided&nbsp;timeout<br />
&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;None&nbsp;:&nbsp;Will&nbsp;retry&nbsp;function&nbsp;same&nbsp;args&nbsp;no&nbsp;timeout<br />
&nbsp;<br />
@return&nbsp;-&nbsp;Returnval&nbsp;from&nbsp;function</tt></dd></dl>
<hr />
Data descriptors defined here:<br />
<dl ><dt ><strong >__weakref__</strong></dt>
<dd ><tt >list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
</dl>
<hr>
Methods inherited from <a href="builtins.html#BaseException">builtins.BaseException</a>:<br>
<dl><dt><a name="FunctionTimedOut-__delattr__"><strong>__delattr__</strong></a>(self, name, /)</dt><dd><tt>Implement&nbsp;delattr(self,&nbsp;name).</tt></dd></dl>
<hr />
Methods inherited from <a href="builtins.html#BaseException" >builtins.BaseException</a>:<br />
<dl ><dt ><a name="FunctionTimedOut-__delattr__" ><strong >__delattr__</strong></a>(self, name, /)</dt><dd ><tt >Implement&nbsp;delattr(self,&nbsp;name).</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-__getattribute__"><strong>__getattribute__</strong></a>(self, name, /)</dt><dd><tt>Return&nbsp;getattr(self,&nbsp;name).</tt></dd></dl>
<dl ><dt ><a name="FunctionTimedOut-__getattribute__" ><strong >__getattribute__</strong></a>(self, name, /)</dt><dd ><tt >Return&nbsp;getattr(self,&nbsp;name).</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-__init__"><strong>__init__</strong></a>(self, /, *args, **kwargs)</dt><dd><tt>Initialize&nbsp;self.&nbsp;&nbsp;See&nbsp;help(type(self))&nbsp;for&nbsp;accurate&nbsp;signature.</tt></dd></dl>
<dl ><dt ><a name="FunctionTimedOut-__reduce__" ><strong >__reduce__</strong></a>(...)</dt><dd ><tt >Helper&nbsp;for&nbsp;pickle.</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-__new__"><strong>__new__</strong></a>(*args, **kwargs)<font color="#909090"><font face="helvetica, arial"> from <a href="builtins.html#type">builtins.type</a></font></font></dt><dd><tt>Create&nbsp;and&nbsp;return&nbsp;a&nbsp;new&nbsp;object.&nbsp;&nbsp;See&nbsp;help(type)&nbsp;for&nbsp;accurate&nbsp;signature.</tt></dd></dl>
<dl ><dt ><a name="FunctionTimedOut-__repr__" ><strong >__repr__</strong></a>(self, /)</dt><dd ><tt >Return&nbsp;repr(self).</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-__reduce__"><strong>__reduce__</strong></a>(...)</dt><dd><tt>helper&nbsp;for&nbsp;pickle</tt></dd></dl>
<dl ><dt ><a name="FunctionTimedOut-__setattr__" ><strong >__setattr__</strong></a>(self, name, value, /)</dt><dd ><tt >Implement&nbsp;setattr(self,&nbsp;name,&nbsp;value).</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-__repr__"><strong>__repr__</strong></a>(self, /)</dt><dd><tt>Return&nbsp;repr(self).</tt></dd></dl>
<dl ><dt ><a name="FunctionTimedOut-__setstate__" ><strong >__setstate__</strong></a>(...)</dt></dl>
<dl><dt><a name="FunctionTimedOut-__setattr__"><strong>__setattr__</strong></a>(self, name, value, /)</dt><dd><tt>Implement&nbsp;setattr(self,&nbsp;name,&nbsp;value).</tt></dd></dl>
<dl ><dt ><a name="FunctionTimedOut-__str__" ><strong >__str__</strong></a>(self, /)</dt><dd ><tt >Return&nbsp;str(self).</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-__setstate__"><strong>__setstate__</strong></a>(...)</dt></dl>
<dl ><dt ><a name="FunctionTimedOut-with_traceback" ><strong >with_traceback</strong></a>(...)</dt><dd ><tt >Exception.<a href="#FunctionTimedOut-with_traceback" >with_traceback</a>(tb)&nbsp;--<br />
set&nbsp;self.<strong >__traceback__</strong>&nbsp;to&nbsp;tb&nbsp;and&nbsp;return&nbsp;self.</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-__str__"><strong>__str__</strong></a>(self, /)</dt><dd><tt>Return&nbsp;str(self).</tt></dd></dl>
<hr />
Static methods inherited from <a href="builtins.html#BaseException" >builtins.BaseException</a>:<br />
<dl ><dt ><a name="FunctionTimedOut-__new__" ><strong >__new__</strong></a>(*args, **kwargs)<font color="#909090" ><font face="helvetica, arial" > from <a href="builtins.html#type" >builtins.type</a></font></font></dt><dd ><tt >Create&nbsp;and&nbsp;return&nbsp;a&nbsp;new&nbsp;object.&nbsp;&nbsp;See&nbsp;help(type)&nbsp;for&nbsp;accurate&nbsp;signature.</tt></dd></dl>
<dl><dt><a name="FunctionTimedOut-with_traceback"><strong>with_traceback</strong></a>(...)</dt><dd><tt>Exception.<a href="#FunctionTimedOut-with_traceback">with_traceback</a>(tb)&nbsp;--<br>
set&nbsp;self.<strong>__traceback__</strong>&nbsp;to&nbsp;tb&nbsp;and&nbsp;return&nbsp;self.</tt></dd></dl>
<hr>
Data descriptors inherited from <a href="builtins.html#BaseException">builtins.BaseException</a>:<br>
<dl><dt><strong>__cause__</strong></dt>
<dd><tt>exception&nbsp;cause</tt></dd>
<hr />
Data descriptors inherited from <a href="builtins.html#BaseException" >builtins.BaseException</a>:<br />
<dl ><dt ><strong >__cause__</strong></dt>
<dd ><tt >exception&nbsp;cause</tt></dd>
</dl>
<dl><dt><strong>__context__</strong></dt>
<dd><tt>exception&nbsp;context</tt></dd>
<dl ><dt ><strong >__context__</strong></dt>
<dd ><tt >exception&nbsp;context</tt></dd>
</dl>
<dl><dt><strong>__dict__</strong></dt>
<dl ><dt ><strong >__dict__</strong></dt>
</dl>
<dl><dt><strong>__suppress_context__</strong></dt>
<dl ><dt ><strong >__suppress_context__</strong></dt>
</dl>
<dl><dt><strong>__traceback__</strong></dt>
<dl ><dt ><strong >__traceback__</strong></dt>
</dl>
<dl><dt><strong>args</strong></dt>
<dl ><dt ><strong >args</strong></dt>
</dl>
</td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#eeaa77">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
</td></tr></table> <p >
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="section" >
<tr bgcolor="#ffc8d8" >
<td colspan="3" valign="bottom" >&nbsp;<br />
<font color="#000000" face="helvetica, arial" ><a name="StoppableThread" >class <strong >StoppableThread</strong></a>(<a href="threading.html#Thread" >threading.Thread</a>)</font></td></tr>
<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><dl><dt><a name="-func_timeout"><strong>func_timeout</strong></a>(timeout, func, args=(), kwargs=None)</dt><dd><tt>func_timeout&nbsp;-&nbsp;Runs&nbsp;the&nbsp;given&nbsp;function&nbsp;for&nbsp;up&nbsp;to&nbsp;#timeout#&nbsp;seconds.<br>
&nbsp;<br>
Raises&nbsp;any&nbsp;exceptions&nbsp;#func#&nbsp;would&nbsp;raise,&nbsp;returns&nbsp;what&nbsp;#func#&nbsp;would&nbsp;return&nbsp;(unless&nbsp;timeout&nbsp;is&nbsp;exceeded),&nbsp;in&nbsp;which&nbsp;case&nbsp;it&nbsp;raises&nbsp;<a href="#FunctionTimedOut">FunctionTimedOut</a><br>
&nbsp;<br>
@param&nbsp;timeout&nbsp;&lt;float&gt;&nbsp;-&nbsp;Maximum&nbsp;number&nbsp;of&nbsp;seconds&nbsp;to&nbsp;run&nbsp;#func#&nbsp;before&nbsp;terminating<br>
@param&nbsp;func&nbsp;&lt;function&gt;&nbsp;-&nbsp;The&nbsp;function&nbsp;to&nbsp;call<br>
@param&nbsp;args&nbsp;&nbsp;&nbsp;&nbsp;&lt;tuple&gt;&nbsp;-&nbsp;Any&nbsp;ordered&nbsp;arguments&nbsp;to&nbsp;pass&nbsp;to&nbsp;the&nbsp;function<br>
@param&nbsp;kwargs&nbsp;&nbsp;&lt;dict/None&gt;&nbsp;-&nbsp;Keyword&nbsp;arguments&nbsp;to&nbsp;pass&nbsp;to&nbsp;the&nbsp;function.<br>
&nbsp;<br>
@raises&nbsp;-&nbsp;<a href="#FunctionTimedOut">FunctionTimedOut</a>&nbsp;if&nbsp;#timeout#&nbsp;is&nbsp;exceeded,&nbsp;otherwise&nbsp;anything&nbsp;#func#&nbsp;could&nbsp;raise&nbsp;will&nbsp;be&nbsp;raised<br>
&nbsp;<br>
If&nbsp;the&nbsp;timeout&nbsp;is&nbsp;exceeded,&nbsp;<a href="#FunctionTimedOut">FunctionTimedOut</a>&nbsp;will&nbsp;be&nbsp;raised&nbsp;within&nbsp;the&nbsp;context&nbsp;of&nbsp;the&nbsp;called&nbsp;function&nbsp;every&nbsp;two&nbsp;seconds&nbsp;until&nbsp;it&nbsp;terminates,<br>
but&nbsp;will&nbsp;not&nbsp;block&nbsp;the&nbsp;calling&nbsp;thread&nbsp;(a&nbsp;new&nbsp;thread&nbsp;will&nbsp;be&nbsp;created&nbsp;to&nbsp;perform&nbsp;the&nbsp;join).&nbsp;If&nbsp;possible,&nbsp;you&nbsp;should&nbsp;try/except&nbsp;<a href="#FunctionTimedOut">FunctionTimedOut</a><br>
to&nbsp;return&nbsp;cleanly,&nbsp;but&nbsp;in&nbsp;most&nbsp;cases&nbsp;it&nbsp;will&nbsp;'just&nbsp;work'.<br>
&nbsp;<br>
Be&nbsp;careful&nbsp;of&nbsp;code&nbsp;like:<br>
def&nbsp;myfunc():<br>
&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;True:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dosomething()<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except&nbsp;Exception:<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue<br>
&nbsp;<br>
because&nbsp;it&nbsp;will&nbsp;never&nbsp;terminate.<br>
&nbsp;<br>
<tr bgcolor="#ffc8d8" ><td rowspan="2" ><tt >&nbsp;&nbsp;&nbsp;</tt></td>
<td colspan="2" ><tt ><a href="#StoppableThread" >StoppableThread</a>(group=None,&nbsp;target=None,&nbsp;name=None,&nbsp;args=(),&nbsp;kwargs=None,&nbsp;*,&nbsp;daemon=None)<br />
&nbsp;<br />
<a href="#StoppableThread" >StoppableThread</a>&nbsp;-&nbsp;A&nbsp;thread&nbsp;that&nbsp;can&nbsp;be&nbsp;stopped&nbsp;by&nbsp;forcing&nbsp;an&nbsp;exception&nbsp;in&nbsp;the&nbsp;execution&nbsp;context.<br />
&nbsp;<br />
&nbsp;&nbsp;This&nbsp;works&nbsp;both&nbsp;to&nbsp;interrupt&nbsp;code&nbsp;that&nbsp;is&nbsp;in&nbsp;C&nbsp;or&nbsp;in&nbsp;python&nbsp;code,&nbsp;at&nbsp;either&nbsp;the&nbsp;next&nbsp;call&nbsp;to&nbsp;a&nbsp;python&nbsp;function,<br />
&nbsp;&nbsp;&nbsp;or&nbsp;the&nbsp;next&nbsp;line&nbsp;in&nbsp;python&nbsp;code.<br />
&nbsp;<br />
It&nbsp;is&nbsp;recommended&nbsp;that&nbsp;if&nbsp;you&nbsp;call&nbsp;stop&nbsp;(&nbsp;@see&nbsp;<a href="#StoppableThread" >StoppableThread</a>.stop&nbsp;)&nbsp;that&nbsp;you&nbsp;use&nbsp;an&nbsp;exception&nbsp;that&nbsp;inherits&nbsp;<a href="builtins.html#BaseException" >BaseException</a>,&nbsp;to&nbsp;ensure&nbsp;it&nbsp;likely&nbsp;isn't&nbsp;caught.<br />
&nbsp;<br />
&nbsp;Also,&nbsp;beware&nbsp;unmarked&nbsp;exception&nbsp;handlers&nbsp;in&nbsp;your&nbsp;code.&nbsp;Code&nbsp;like&nbsp;this:<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;True:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;doSomething()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue<br />
&nbsp;<br />
will&nbsp;never&nbsp;be&nbsp;able&nbsp;to&nbsp;abort,&nbsp;because&nbsp;the&nbsp;exception&nbsp;you&nbsp;raise&nbsp;is&nbsp;immediately&nbsp;caught.<br />
&nbsp;<br />
The&nbsp;exception&nbsp;is&nbsp;raised&nbsp;over&nbsp;and&nbsp;over,&nbsp;with&nbsp;a&nbsp;specifed&nbsp;delay&nbsp;(default&nbsp;2.0&nbsp;seconds)<br />&nbsp;</tt></td></tr>
<tr ><td >&nbsp;</td>
<td width="100%" ><dl ><dt >Method resolution order:</dt>
<dd ><a href="func_timeout.StoppableThread.html#StoppableThread" >StoppableThread</a></dd>
<dd ><a href="threading.html#Thread" >threading.Thread</a></dd>
<dd ><a href="builtins.html#object" >builtins.object</a></dd>
</dl>
<hr />
Methods defined here:<br />
<dl ><dt ><a name="StoppableThread-stop" ><strong >stop</strong></a>(self, exception, raiseEvery=2.0)</dt><dd ><tt >Stops&nbsp;the&nbsp;thread&nbsp;by&nbsp;raising&nbsp;a&nbsp;given&nbsp;exception.<br />
&nbsp;<br />
@param&nbsp;exception&nbsp;&lt;Exception&nbsp;type&gt;&nbsp;-&nbsp;Exception&nbsp;to&nbsp;throw.&nbsp;Likely,&nbsp;you&nbsp;want&nbsp;to&nbsp;use&nbsp;something<br />
&nbsp;<br />
&nbsp;&nbsp;that&nbsp;inherits&nbsp;from&nbsp;<a href="builtins.html#BaseException" >BaseException</a>&nbsp;(so&nbsp;except&nbsp;Exception&nbsp;as&nbsp;e:&nbsp;continue;&nbsp;isn't&nbsp;a&nbsp;problem)<br />
&nbsp;<br />
&nbsp;&nbsp;This&nbsp;should&nbsp;be&nbsp;a&nbsp;class/type,&nbsp;NOT&nbsp;an&nbsp;instance,&nbsp;i.e.&nbsp;&nbsp;MyExceptionType&nbsp;&nbsp;&nbsp;not&nbsp;&nbsp;MyExceptionType()<br />
&nbsp;<br />
&nbsp;<br />
@param&nbsp;raiseEvery&nbsp;&lt;float&gt;&nbsp;Default&nbsp;2.0&nbsp;-&nbsp;We&nbsp;will&nbsp;keep&nbsp;raising&nbsp;this&nbsp;exception&nbsp;every&nbsp;#raiseEvery&nbsp;seconds,<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;until&nbsp;the&nbsp;thread&nbsp;terminates.<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;your&nbsp;code&nbsp;traps&nbsp;a&nbsp;specific&nbsp;exception&nbsp;type,&nbsp;this&nbsp;will&nbsp;allow&nbsp;you&nbsp;#raiseEvery&nbsp;seconds&nbsp;to&nbsp;cleanup&nbsp;before&nbsp;exit.<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;you're&nbsp;calling&nbsp;third-party&nbsp;code&nbsp;you&nbsp;can't&nbsp;control,&nbsp;which&nbsp;catches&nbsp;<a href="builtins.html#BaseException" >BaseException</a>,&nbsp;set&nbsp;this&nbsp;to&nbsp;a&nbsp;low&nbsp;number<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;break&nbsp;out&nbsp;of&nbsp;their&nbsp;exception&nbsp;handler.<br />
&nbsp;<br />
&nbsp;<br />
&nbsp;@return&nbsp;&lt;None&gt;</tt></dd></dl>
<hr />
Methods inherited from <a href="threading.html#Thread" >threading.Thread</a>:<br />
<dl ><dt ><a name="StoppableThread-__init__" ><strong >__init__</strong></a>(self, group=None, target=None, name=None, args=(), kwargs=None, *, daemon=None)</dt><dd ><tt >This&nbsp;constructor&nbsp;should&nbsp;always&nbsp;be&nbsp;called&nbsp;with&nbsp;keyword&nbsp;arguments.&nbsp;Arguments&nbsp;are:<br />
&nbsp;<br />
*group*&nbsp;should&nbsp;be&nbsp;None;&nbsp;reserved&nbsp;for&nbsp;future&nbsp;extension&nbsp;when&nbsp;a&nbsp;ThreadGroup<br />
class&nbsp;is&nbsp;implemented.<br />
&nbsp;<br />
*target*&nbsp;is&nbsp;the&nbsp;callable&nbsp;object&nbsp;to&nbsp;be&nbsp;invoked&nbsp;by&nbsp;the&nbsp;<a href="#StoppableThread-run" >run</a>()<br />
method.&nbsp;Defaults&nbsp;to&nbsp;None,&nbsp;meaning&nbsp;nothing&nbsp;is&nbsp;called.<br />
&nbsp;<br />
*name*&nbsp;is&nbsp;the&nbsp;thread&nbsp;name.&nbsp;By&nbsp;default,&nbsp;a&nbsp;unique&nbsp;name&nbsp;is&nbsp;constructed&nbsp;of<br />
the&nbsp;form&nbsp;"<a href="threading.html#Thread" >Thread</a>-N"&nbsp;where&nbsp;N&nbsp;is&nbsp;a&nbsp;small&nbsp;decimal&nbsp;number.<br />
&nbsp;<br />
*args*&nbsp;is&nbsp;the&nbsp;argument&nbsp;tuple&nbsp;for&nbsp;the&nbsp;target&nbsp;invocation.&nbsp;Defaults&nbsp;to&nbsp;().<br />
&nbsp;<br />
*kwargs*&nbsp;is&nbsp;a&nbsp;dictionary&nbsp;of&nbsp;keyword&nbsp;arguments&nbsp;for&nbsp;the&nbsp;target<br />
invocation.&nbsp;Defaults&nbsp;to&nbsp;{}.<br />
&nbsp;<br />
If&nbsp;a&nbsp;subclass&nbsp;overrides&nbsp;the&nbsp;constructor,&nbsp;it&nbsp;must&nbsp;make&nbsp;sure&nbsp;to&nbsp;invoke<br />
the&nbsp;base&nbsp;class&nbsp;constructor&nbsp;(<a href="threading.html#Thread" >Thread</a>.<a href="#StoppableThread-__init__" >__init__</a>())&nbsp;before&nbsp;doing&nbsp;anything<br />
else&nbsp;to&nbsp;the&nbsp;thread.</tt></dd></dl>
<dl ><dt ><a name="StoppableThread-__repr__" ><strong >__repr__</strong></a>(self)</dt><dd ><tt >Return&nbsp;repr(self).</tt></dd></dl>
<dl ><dt ><a name="StoppableThread-getName" ><strong >getName</strong></a>(self)</dt></dl>
<dl ><dt ><a name="StoppableThread-isAlive" ><strong >isAlive</strong></a>(self)</dt><dd ><tt >Return&nbsp;whether&nbsp;the&nbsp;thread&nbsp;is&nbsp;alive.<br />
&nbsp;<br />
This&nbsp;method&nbsp;is&nbsp;deprecated,&nbsp;use&nbsp;<a href="#StoppableThread-is_alive" >is_alive</a>()&nbsp;instead.</tt></dd></dl>
<dl ><dt ><a name="StoppableThread-isDaemon" ><strong >isDaemon</strong></a>(self)</dt></dl>
<dl ><dt ><a name="StoppableThread-is_alive" ><strong >is_alive</strong></a>(self)</dt><dd ><tt >Return&nbsp;whether&nbsp;the&nbsp;thread&nbsp;is&nbsp;alive.<br />
&nbsp;<br />
This&nbsp;method&nbsp;returns&nbsp;True&nbsp;just&nbsp;before&nbsp;the&nbsp;<a href="#StoppableThread-run" >run</a>()&nbsp;method&nbsp;starts&nbsp;until&nbsp;just<br />
after&nbsp;the&nbsp;<a href="#StoppableThread-run" >run</a>()&nbsp;method&nbsp;terminates.&nbsp;The&nbsp;module&nbsp;function&nbsp;enumerate()<br />
returns&nbsp;a&nbsp;list&nbsp;of&nbsp;all&nbsp;alive&nbsp;threads.</tt></dd></dl>
<dl ><dt ><a name="StoppableThread-join" ><strong >join</strong></a>(self, timeout=None)</dt><dd ><tt >Wait&nbsp;until&nbsp;the&nbsp;thread&nbsp;terminates.<br />
&nbsp;<br />
This&nbsp;blocks&nbsp;the&nbsp;calling&nbsp;thread&nbsp;until&nbsp;the&nbsp;thread&nbsp;whose&nbsp;<a href="#StoppableThread-join" >join</a>()&nbsp;method&nbsp;is<br />
called&nbsp;terminates&nbsp;--&nbsp;either&nbsp;normally&nbsp;or&nbsp;through&nbsp;an&nbsp;unhandled&nbsp;exception<br />
or&nbsp;until&nbsp;the&nbsp;optional&nbsp;timeout&nbsp;occurs.<br />
&nbsp;<br />
When&nbsp;the&nbsp;timeout&nbsp;argument&nbsp;is&nbsp;present&nbsp;and&nbsp;not&nbsp;None,&nbsp;it&nbsp;should&nbsp;be&nbsp;a<br />
floating&nbsp;point&nbsp;number&nbsp;specifying&nbsp;a&nbsp;timeout&nbsp;for&nbsp;the&nbsp;operation&nbsp;in&nbsp;seconds<br />
(or&nbsp;fractions&nbsp;thereof).&nbsp;As&nbsp;<a href="#StoppableThread-join" >join</a>()&nbsp;always&nbsp;returns&nbsp;None,&nbsp;you&nbsp;must&nbsp;call<br />
<a href="#StoppableThread-is_alive" >is_alive</a>()&nbsp;after&nbsp;<a href="#StoppableThread-join" >join</a>()&nbsp;to&nbsp;decide&nbsp;whether&nbsp;a&nbsp;timeout&nbsp;happened&nbsp;--&nbsp;if&nbsp;the<br />
thread&nbsp;is&nbsp;still&nbsp;alive,&nbsp;the&nbsp;<a href="#StoppableThread-join" >join</a>()&nbsp;call&nbsp;timed&nbsp;out.<br />
&nbsp;<br />
When&nbsp;the&nbsp;timeout&nbsp;argument&nbsp;is&nbsp;not&nbsp;present&nbsp;or&nbsp;None,&nbsp;the&nbsp;operation&nbsp;will<br />
block&nbsp;until&nbsp;the&nbsp;thread&nbsp;terminates.<br />
&nbsp;<br />
A&nbsp;thread&nbsp;can&nbsp;be&nbsp;<a href="#StoppableThread-join" >join</a>()ed&nbsp;many&nbsp;times.<br />
&nbsp;<br />
<a href="#StoppableThread-join" >join</a>()&nbsp;raises&nbsp;a&nbsp;RuntimeError&nbsp;if&nbsp;an&nbsp;attempt&nbsp;is&nbsp;made&nbsp;to&nbsp;join&nbsp;the&nbsp;current<br />
thread&nbsp;as&nbsp;that&nbsp;would&nbsp;cause&nbsp;a&nbsp;deadlock.&nbsp;It&nbsp;is&nbsp;also&nbsp;an&nbsp;error&nbsp;to&nbsp;<a href="#StoppableThread-join" >join</a>()&nbsp;a<br />
thread&nbsp;before&nbsp;it&nbsp;has&nbsp;been&nbsp;started&nbsp;and&nbsp;attempts&nbsp;to&nbsp;do&nbsp;so&nbsp;raises&nbsp;the&nbsp;same<br />
exception.</tt></dd></dl>
<dl ><dt ><a name="StoppableThread-run" ><strong >run</strong></a>(self)</dt><dd ><tt >Method&nbsp;representing&nbsp;the&nbsp;thread's&nbsp;activity.<br />
&nbsp;<br />
You&nbsp;may&nbsp;override&nbsp;this&nbsp;method&nbsp;in&nbsp;a&nbsp;subclass.&nbsp;The&nbsp;standard&nbsp;<a href="#StoppableThread-run" >run</a>()&nbsp;method<br />
invokes&nbsp;the&nbsp;callable&nbsp;object&nbsp;passed&nbsp;to&nbsp;the&nbsp;object's&nbsp;constructor&nbsp;as&nbsp;the<br />
target&nbsp;argument,&nbsp;if&nbsp;any,&nbsp;with&nbsp;sequential&nbsp;and&nbsp;keyword&nbsp;arguments&nbsp;taken<br />
from&nbsp;the&nbsp;args&nbsp;and&nbsp;kwargs&nbsp;arguments,&nbsp;respectively.</tt></dd></dl>
<dl ><dt ><a name="StoppableThread-setDaemon" ><strong >setDaemon</strong></a>(self, daemonic)</dt></dl>
<dl ><dt ><a name="StoppableThread-setName" ><strong >setName</strong></a>(self, name)</dt></dl>
<dl ><dt ><a name="StoppableThread-start" ><strong >start</strong></a>(self)</dt><dd ><tt >Start&nbsp;the&nbsp;thread's&nbsp;activity.<br />
&nbsp;<br />
It&nbsp;must&nbsp;be&nbsp;called&nbsp;at&nbsp;most&nbsp;once&nbsp;per&nbsp;thread&nbsp;object.&nbsp;It&nbsp;arranges&nbsp;for&nbsp;the<br />
object's&nbsp;<a href="#StoppableThread-run" >run</a>()&nbsp;method&nbsp;to&nbsp;be&nbsp;invoked&nbsp;in&nbsp;a&nbsp;separate&nbsp;thread&nbsp;of&nbsp;control.<br />
&nbsp;<br />
This&nbsp;method&nbsp;will&nbsp;raise&nbsp;a&nbsp;RuntimeError&nbsp;if&nbsp;called&nbsp;more&nbsp;than&nbsp;once&nbsp;on&nbsp;the<br />
same&nbsp;thread&nbsp;object.</tt></dd></dl>
<hr />
Data descriptors inherited from <a href="threading.html#Thread" >threading.Thread</a>:<br />
<dl ><dt ><strong >__dict__</strong></dt>
<dd ><tt >dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
</dl>
<dl ><dt ><strong >__weakref__</strong></dt>
<dd ><tt >list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
</dl>
<dl ><dt ><strong >daemon</strong></dt>
<dd ><tt >A&nbsp;boolean&nbsp;value&nbsp;indicating&nbsp;whether&nbsp;this&nbsp;thread&nbsp;is&nbsp;a&nbsp;daemon&nbsp;thread.<br />
&nbsp;<br />
This&nbsp;must&nbsp;be&nbsp;set&nbsp;before&nbsp;start()&nbsp;is&nbsp;called,&nbsp;otherwise&nbsp;RuntimeError&nbsp;is<br />
raised.&nbsp;Its&nbsp;initial&nbsp;value&nbsp;is&nbsp;inherited&nbsp;from&nbsp;the&nbsp;creating&nbsp;thread;&nbsp;the<br />
main&nbsp;thread&nbsp;is&nbsp;not&nbsp;a&nbsp;daemon&nbsp;thread&nbsp;and&nbsp;therefore&nbsp;all&nbsp;threads&nbsp;created&nbsp;in<br />
the&nbsp;main&nbsp;thread&nbsp;default&nbsp;to&nbsp;daemon&nbsp;=&nbsp;False.<br />
&nbsp;<br />
The&nbsp;entire&nbsp;Python&nbsp;program&nbsp;exits&nbsp;when&nbsp;no&nbsp;alive&nbsp;non-daemon&nbsp;threads&nbsp;are<br />
left.</tt></dd>
</dl>
<dl ><dt ><strong >ident</strong></dt>
<dd ><tt >Thread&nbsp;identifier&nbsp;of&nbsp;this&nbsp;thread&nbsp;or&nbsp;None&nbsp;if&nbsp;it&nbsp;has&nbsp;not&nbsp;been&nbsp;started.<br />
&nbsp;<br />
This&nbsp;is&nbsp;a&nbsp;nonzero&nbsp;integer.&nbsp;See&nbsp;the&nbsp;get_ident()&nbsp;function.&nbsp;Thread<br />
identifiers&nbsp;may&nbsp;be&nbsp;recycled&nbsp;when&nbsp;a&nbsp;thread&nbsp;exits&nbsp;and&nbsp;another&nbsp;thread&nbsp;is<br />
created.&nbsp;The&nbsp;identifier&nbsp;is&nbsp;available&nbsp;even&nbsp;after&nbsp;the&nbsp;thread&nbsp;has&nbsp;exited.</tt></dd>
</dl>
<dl ><dt ><strong >name</strong></dt>
<dd ><tt >A&nbsp;string&nbsp;used&nbsp;for&nbsp;identification&nbsp;purposes&nbsp;only.<br />
&nbsp;<br />
It&nbsp;has&nbsp;no&nbsp;semantics.&nbsp;Multiple&nbsp;threads&nbsp;may&nbsp;be&nbsp;given&nbsp;the&nbsp;same&nbsp;name.&nbsp;The<br />
initial&nbsp;name&nbsp;is&nbsp;set&nbsp;by&nbsp;the&nbsp;constructor.</tt></dd>
</dl>
</td></tr></table></p></p></td></tr></table><p >
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="section" >
<tr bgcolor="#eeaa77" >
<td colspan="3" valign="bottom" >&nbsp;<br />
<font color="#ffffff" face="helvetica, arial" ><big ><strong >Functions</strong></big></font></td></tr>
<tr ><td bgcolor="#eeaa77" ><tt >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td >&nbsp;</td>
<td width="100%" ><dl ><dt ><a name="-func_set_timeout" ><strong >func_set_timeout</strong></a>(timeout, allowOverride=False)</dt><dd ><tt >func_set_timeout&nbsp;-&nbsp;Decorator&nbsp;to&nbsp;run&nbsp;a&nbsp;function&nbsp;with&nbsp;a&nbsp;given/calculated&nbsp;timeout&nbsp;(max&nbsp;execution&nbsp;time).<br />
&nbsp;&nbsp;&nbsp;&nbsp;Optionally&nbsp;(if&nbsp;#allowOverride&nbsp;is&nbsp;True),&nbsp;adds&nbsp;a&nbsp;paramater,&nbsp;"forceTimeout",&nbsp;to&nbsp;the<br />
&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;which,&nbsp;if&nbsp;provided,&nbsp;will&nbsp;override&nbsp;the&nbsp;default&nbsp;timeout&nbsp;for&nbsp;that&nbsp;invocation.<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;#timeout&nbsp;is&nbsp;provided&nbsp;as&nbsp;a&nbsp;lambda/function,&nbsp;it&nbsp;will&nbsp;be&nbsp;called<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prior&nbsp;to&nbsp;each&nbsp;invocation&nbsp;of&nbsp;the&nbsp;decorated&nbsp;function&nbsp;to&nbsp;calculate&nbsp;the&nbsp;timeout&nbsp;to&nbsp;be&nbsp;used<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;that&nbsp;call,&nbsp;based&nbsp;on&nbsp;the&nbsp;arguments&nbsp;passed&nbsp;to&nbsp;the&nbsp;decorated&nbsp;function.<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;For&nbsp;example,&nbsp;you&nbsp;may&nbsp;have&nbsp;a&nbsp;"processData"&nbsp;function&nbsp;whose&nbsp;execution&nbsp;time<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;depends&nbsp;on&nbsp;the&nbsp;number&nbsp;of&nbsp;"data"&nbsp;elements,&nbsp;so&nbsp;you&nbsp;may&nbsp;want&nbsp;a&nbsp;million&nbsp;elements&nbsp;to&nbsp;have&nbsp;a<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;much&nbsp;higher&nbsp;timeout&nbsp;than&nbsp;seven&nbsp;elements.)<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;#allowOverride&nbsp;is&nbsp;True&nbsp;AND&nbsp;a&nbsp;kwarg&nbsp;of&nbsp;"forceTimeout"&nbsp;is&nbsp;passed&nbsp;to&nbsp;the&nbsp;wrapped&nbsp;function,&nbsp;that&nbsp;timeout<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;will&nbsp;be&nbsp;used&nbsp;for&nbsp;that&nbsp;single&nbsp;call.<br />
&nbsp;<br />
@param&nbsp;timeout&nbsp;&lt;float&nbsp;OR&nbsp;lambda/function&gt;&nbsp;-<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;**If&nbsp;float:**<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Default&nbsp;number&nbsp;of&nbsp;seconds&nbsp;max&nbsp;to&nbsp;allow&nbsp;function&nbsp;to&nbsp;execute<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;before&nbsp;throwing&nbsp;<a href="#FunctionTimedOut" >FunctionTimedOut</a><br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;**If&nbsp;lambda/function:<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If&nbsp;a&nbsp;function/lambda&nbsp;is&nbsp;provided,&nbsp;it&nbsp;will&nbsp;be&nbsp;called&nbsp;for&nbsp;every<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;invocation&nbsp;of&nbsp;the&nbsp;decorated&nbsp;function&nbsp;(unless&nbsp;#allowOverride=True&nbsp;and&nbsp;"forceTimeout"&nbsp;was&nbsp;passed)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;determine&nbsp;the&nbsp;timeout&nbsp;to&nbsp;use&nbsp;based&nbsp;on&nbsp;the&nbsp;arguments&nbsp;to&nbsp;the&nbsp;decorated&nbsp;function.<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The&nbsp;arguments&nbsp;as&nbsp;passed&nbsp;into&nbsp;the&nbsp;decorated&nbsp;function&nbsp;will&nbsp;be&nbsp;passed&nbsp;to&nbsp;this&nbsp;function.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;They&nbsp;either&nbsp;must&nbsp;match&nbsp;exactly&nbsp;to&nbsp;what&nbsp;the&nbsp;decorated&nbsp;function&nbsp;has,&nbsp;OR<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;you&nbsp;prefer&nbsp;to&nbsp;get&nbsp;the&nbsp;*args&nbsp;(list&nbsp;of&nbsp;ordered&nbsp;args)&nbsp;and&nbsp;**kwargs&nbsp;(&nbsp;key&nbsp;:&nbsp;value&nbsp;&nbsp;keyword&nbsp;args&nbsp;form),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;define&nbsp;your&nbsp;calculate&nbsp;function&nbsp;like:<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;calculateTimeout(*args,&nbsp;**kwargs):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;or&nbsp;lambda&nbsp;like:<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;calculateTimeout&nbsp;=&nbsp;lambda&nbsp;*args,&nbsp;**kwargs&nbsp;:&nbsp;...<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;otherwise&nbsp;the&nbsp;args&nbsp;to&nbsp;your&nbsp;calculate&nbsp;function&nbsp;should&nbsp;match&nbsp;exactly&nbsp;the&nbsp;decorated&nbsp;function.<br />
&nbsp;<br />
&nbsp;<br />
@param&nbsp;allowOverride&nbsp;&lt;bool&gt;&nbsp;Default&nbsp;False,&nbsp;if&nbsp;True&nbsp;adds&nbsp;a&nbsp;keyword&nbsp;argument&nbsp;to&nbsp;the&nbsp;decorated&nbsp;function,<br />
&nbsp;&nbsp;&nbsp;&nbsp;"forceTimeout"&nbsp;which,&nbsp;if&nbsp;provided,&nbsp;will&nbsp;override&nbsp;the&nbsp;#timeout.&nbsp;If&nbsp;#timeout&nbsp;was&nbsp;provided&nbsp;as&nbsp;a&nbsp;lambda&nbsp;/&nbsp;function,&nbsp;it<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;will&nbsp;not&nbsp;be&nbsp;called.<br />
&nbsp;<br />
@throws&nbsp;<a href="#FunctionTimedOut" >FunctionTimedOut</a>&nbsp;If&nbsp;time&nbsp;alloted&nbsp;passes&nbsp;without&nbsp;function&nbsp;returning&nbsp;naturally<br />
&nbsp;<br />
@see&nbsp;func_timeout</tt></dd></dl>
<dl ><dt ><a name="-func_timeout" ><strong >func_timeout</strong></a>(timeout, func, args=(), kwargs=None)</dt><dd ><tt >func_timeout&nbsp;-&nbsp;Runs&nbsp;the&nbsp;given&nbsp;function&nbsp;for&nbsp;up&nbsp;to&nbsp;#timeout#&nbsp;seconds.<br />
&nbsp;<br />
Raises&nbsp;any&nbsp;exceptions&nbsp;#func#&nbsp;would&nbsp;raise,&nbsp;returns&nbsp;what&nbsp;#func#&nbsp;would&nbsp;return&nbsp;(unless&nbsp;timeout&nbsp;is&nbsp;exceeded),&nbsp;in&nbsp;which&nbsp;case&nbsp;it&nbsp;raises&nbsp;<a href="#FunctionTimedOut" >FunctionTimedOut</a><br />
&nbsp;<br />
@param&nbsp;timeout&nbsp;&lt;float&gt;&nbsp;-&nbsp;Maximum&nbsp;number&nbsp;of&nbsp;seconds&nbsp;to&nbsp;run&nbsp;#func#&nbsp;before&nbsp;terminating<br />
&nbsp;<br />
@param&nbsp;func&nbsp;&lt;function&gt;&nbsp;-&nbsp;The&nbsp;function&nbsp;to&nbsp;call<br />
&nbsp;<br />
@param&nbsp;args&nbsp;&nbsp;&nbsp;&nbsp;&lt;tuple&gt;&nbsp;-&nbsp;Any&nbsp;ordered&nbsp;arguments&nbsp;to&nbsp;pass&nbsp;to&nbsp;the&nbsp;function<br />
&nbsp;<br />
@param&nbsp;kwargs&nbsp;&nbsp;&lt;dict/None&gt;&nbsp;-&nbsp;Keyword&nbsp;arguments&nbsp;to&nbsp;pass&nbsp;to&nbsp;the&nbsp;function.<br />
&nbsp;<br />
&nbsp;<br />
@raises&nbsp;-&nbsp;<a href="#FunctionTimedOut" >FunctionTimedOut</a>&nbsp;if&nbsp;#timeout#&nbsp;is&nbsp;exceeded,&nbsp;otherwise&nbsp;anything&nbsp;#func#&nbsp;could&nbsp;raise&nbsp;will&nbsp;be&nbsp;raised<br />
&nbsp;<br />
If&nbsp;the&nbsp;timeout&nbsp;is&nbsp;exceeded,&nbsp;<a href="#FunctionTimedOut" >FunctionTimedOut</a>&nbsp;will&nbsp;be&nbsp;raised&nbsp;within&nbsp;the&nbsp;context&nbsp;of&nbsp;the&nbsp;called&nbsp;function&nbsp;every&nbsp;two&nbsp;seconds&nbsp;until&nbsp;it&nbsp;terminates,<br />
but&nbsp;will&nbsp;not&nbsp;block&nbsp;the&nbsp;calling&nbsp;thread&nbsp;(a&nbsp;new&nbsp;thread&nbsp;will&nbsp;be&nbsp;created&nbsp;to&nbsp;perform&nbsp;the&nbsp;join).&nbsp;If&nbsp;possible,&nbsp;you&nbsp;should&nbsp;try/except&nbsp;<a href="#FunctionTimedOut" >FunctionTimedOut</a><br />
to&nbsp;return&nbsp;cleanly,&nbsp;but&nbsp;in&nbsp;most&nbsp;cases&nbsp;it&nbsp;will&nbsp;'just&nbsp;work'.<br />
&nbsp;<br />
@return&nbsp;-&nbsp;The&nbsp;return&nbsp;value&nbsp;that&nbsp;#func#&nbsp;gives</tt></dd></dl>
</td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#55aa55">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
</td></tr></table><p >
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="section" >
<tr bgcolor="#55aa55" >
<td colspan="3" valign="bottom" >&nbsp;<br />
<font color="#ffffff" face="helvetica, arial" ><big ><strong >Data</strong></big></font></td></tr>
<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><strong>__all__</strong> = ('func_timeout', 'FunctionTimedOut')<br>
<strong>__version_tuple__</strong> = (3, 0, 1)</td></tr></table>
</body></html>
<tr ><td bgcolor="#55aa55" ><tt >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td >&nbsp;</td>
<td width="100%" ><strong >__all__</strong> = ('func_timeout', 'func_set_timeout', 'FunctionTimedOut', 'StoppableThread')<br />
<strong >__version_tuple__</strong> = (4, 3, 5)</td></tr></table>
</p></p></p></p></body></html>

View File

@ -0,0 +1,20 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html ><head ><title >Python: module func_timeout.py2_raise</title>
<meta charset="utf-8" />
</head><body bgcolor="#f0f0f8" >
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="heading" >
<tr bgcolor="#7799ee" >
<td valign="bottom" >&nbsp;<br />
<font color="#ffffff" face="helvetica, arial" >&nbsp;<br /><big ><big ><strong ><a href="func_timeout.html" ><font color="#ffffff" >func_timeout</font></a>.py2_raise</strong></big></big></font></td><td align="right" valign="bottom" ><font color="#ffffff" face="helvetica, arial" ><a href="func_timeout.html" >index</a></font></td></tr></table>
<p ><tt >#&nbsp;Python2&nbsp;allows&nbsp;specifying&nbsp;an&nbsp;alternate&nbsp;traceback.</tt></p>
<p >
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="section" >
<tr bgcolor="#eeaa77" >
<td colspan="3" valign="bottom" >&nbsp;<br />
<font color="#ffffff" face="helvetica, arial" ><big ><strong >Functions</strong></big></font></td></tr>
<tr ><td bgcolor="#eeaa77" ><tt >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td >&nbsp;</td>
<td width="100%" ><dl ><dt ><a name="-raise_exception" ><strong >raise_exception</strong></a>(exception)</dt><dd ><tt >#&nbsp;Python2&nbsp;allows&nbsp;specifying&nbsp;an&nbsp;alternate&nbsp;traceback.</tt></dd></dl>
</td></tr></table>
</p></body></html>

View File

@ -0,0 +1,26 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html ><head ><title >Python: module func_timeout.py3_raise</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head><body bgcolor="#f0f0f8" >
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="heading" >
<tr bgcolor="#7799ee" >
<td valign="bottom" >&nbsp;<br />
<font color="#ffffff" face="helvetica, arial" >&nbsp;<br /><big ><big ><strong ><a href="func_timeout.html" ><font color="#ffffff" >func_timeout</font></a>.py3_raise</strong></big></big></font></td><td align="right" valign="bottom" ><font color="#ffffff" face="helvetica, arial" ><a href="func_timeout.html" >index</a></font></td></tr></table>
<p ><tt >#&nbsp;<a href="http://www.python.org/dev/peps/pep-0409/" >PEP&nbsp;409</a>&nbsp;-&nbsp;Raise&nbsp;with&nbsp;the&nbsp;chained&nbsp;exception&nbsp;context&nbsp;disabled<br />
#&nbsp;&nbsp;This,&nbsp;in&nbsp;effect,&nbsp;prevents&nbsp;the&nbsp;"funcwrap"&nbsp;wrapper&nbsp;(&nbsp;chained<br />
#&nbsp;&nbsp;&nbsp;in&nbsp;context&nbsp;to&nbsp;an&nbsp;exception&nbsp;raised&nbsp;here,&nbsp;due&nbsp;to&nbsp;scope&nbsp;)<br />
#&nbsp;Only&nbsp;available&nbsp;in&nbsp;python3.3+</tt></p>
<p >
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="section" >
<tr bgcolor="#eeaa77" >
<td colspan="3" valign="bottom" >&nbsp;<br />
<font color="#ffffff" face="helvetica, arial" ><big ><strong >Functions</strong></big></font></td></tr>
<tr ><td bgcolor="#eeaa77" ><tt >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td >&nbsp;</td>
<td width="100%" ><dl ><dt ><a name="-raise_exception" ><strong >raise_exception</strong></a>(exception)</dt><dd ><tt >#&nbsp;<a href="http://www.python.org/dev/peps/pep-0409/" >PEP&nbsp;409</a>&nbsp;-&nbsp;Raise&nbsp;with&nbsp;the&nbsp;chained&nbsp;exception&nbsp;context&nbsp;disabled<br />
#&nbsp;&nbsp;This,&nbsp;in&nbsp;effect,&nbsp;prevents&nbsp;the&nbsp;"funcwrap"&nbsp;wrapper&nbsp;(&nbsp;chained<br />
#&nbsp;&nbsp;&nbsp;in&nbsp;context&nbsp;to&nbsp;an&nbsp;exception&nbsp;raised&nbsp;here,&nbsp;due&nbsp;to&nbsp;scope&nbsp;)<br />
#&nbsp;Only&nbsp;available&nbsp;in&nbsp;python3.3+</tt></dd></dl>
</td></tr></table>
</p></body></html>

1
doc/index.html Symbolic link
View File

@ -0,0 +1 @@
func_timeout.html

View File

@ -1,5 +1,5 @@
'''
Copyright (c) 2016, 2017 Tim Savannah All Rights Reserved.
Copyright (c) 2016, 2017, 2019 Timothy Savannah All Rights Reserved.
Licensed under the Lesser GNU Public License Version 3, LGPLv3. You should have recieved a copy of this with the source distribution as
LICENSE, otherwise it is available at https://github.com/kata198/func_timeout/LICENSE
@ -8,39 +8,126 @@
import os
import ctypes
import threading
import time
__all__ = ('StoppableThread', 'JoinThread')
class StoppableThread(threading.Thread):
'''
StoppableThread - A thread that can be stopped by forcing an exception in the execution context.
This works both to interrupt code that is in C or in python code, at either the next call to a python function,
or the next line in python code.
It is recommended that if you call stop ( @see StoppableThread.stop ) that you use an exception that inherits BaseException, to ensure it likely isn't caught.
Also, beware unmarked exception handlers in your code. Code like this:
while True:
try:
doSomething()
except:
continue
will never be able to abort, because the exception you raise is immediately caught.
The exception is raised over and over, with a specifed delay (default 2.0 seconds)
'''
def _stopThread(self, exception):
if self.isAlive() is False:
def _stopThread(self, exception, raiseEvery=2.0):
'''
_stopThread - @see StoppableThread.stop
'''
if self.is_alive() is False:
return True
self._stderr = open(os.devnull, 'w')
joinThread = JoinThread(self, exception)
# Create "joining" thread which will raise the provided exception
# on a repeat, until the thread stops.
joinThread = JoinThread(self, exception, repeatEvery=raiseEvery)
# Try to prevent spurrious prints
joinThread._stderr = self._stderr
joinThread.start()
joinThread._stderr = self._stderr
def stop(self, exception, raiseEvery=2.0):
'''
Stops the thread by raising a given exception.
@param exception <Exception type> - Exception to throw. Likely, you want to use something
that inherits from BaseException (so except Exception as e: continue; isn't a problem)
This should be a class/type, NOT an instance, i.e. MyExceptionType not MyExceptionType()
@param raiseEvery <float> Default 2.0 - We will keep raising this exception every #raiseEvery seconds,
until the thread terminates.
If your code traps a specific exception type, this will allow you #raiseEvery seconds to cleanup before exit.
If you're calling third-party code you can't control, which catches BaseException, set this to a low number
to break out of their exception handler.
@return <None>
'''
return self._stopThread(exception, raiseEvery)
class JoinThread(threading.Thread):
'''
JoinThread - The workhouse that stops the StoppableThread
JoinThread - The workhouse that stops the StoppableThread.
Takes an exception, and upon being started immediately raises that exception in the current context
of the thread's execution (so next line of python gets it, or next call to a python api function in C code ).
@see StoppableThread for more details
'''
def __init__(self, otherThread, exception):
def __init__(self, otherThread, exception, repeatEvery=2.0):
'''
__init__ - Create a JoinThread (don't forget to call .start() ! )
@param otherThread <threading.Thread> - A thread
@param exception <BaseException> - An exception. Should be a BaseException, to prevent "catch Exception as e: continue" type code
from never being terminated. If such code is unavoidable, you can try setting #repeatEvery to a very low number, like .00001,
and it will hopefully raise within the context of the catch, and be able to break free.
@param repeatEvery <float> Default 2.0 - After starting, the given exception is immediately raised. Then, every #repeatEvery seconds,
it is raised again, until the thread terminates.
'''
threading.Thread.__init__(self)
self.otherThread = otherThread
self.exception = exception
self.repeatEvery = repeatEvery
self.daemon = True
def run(self):
while self.otherThread.isAlive():
'''
run - The thread main. Will attempt to stop and join the attached thread.
'''
# Try to silence default exception printing.
self.otherThread._Thread__stderr = self._stderr
if hasattr(self.otherThread, '_Thread__stop'):
# If py2, call this first to start thread termination cleanly.
# Python3 does not need such ( nor does it provide.. )
self.otherThread._Thread__stop()
while self.otherThread.is_alive():
# We loop raising exception incase it's caught hopefully this breaks us far out.
ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(self.otherThread.ident), ctypes.py_object(self.exception))
self.otherThread.join(2)
self.otherThread.join(self.repeatEvery)
try:
self._stderr.close()
except:
pass
# vim: set ts=4 sw=4 expandtab :

View File

@ -1,15 +1,16 @@
'''
Copyright (c) 2016, 2017 Tim Savannah All Rights Reserved.
Copyright (c) 2016, 2017, 2019 Tim Savannah All Rights Reserved.
Licensed under the Lesser GNU Public License Version 3, LGPLv3. You should have recieved a copy of this with the source distribution as
LICENSE, otherwise it is available at https://github.com/kata198/func_timeout/LICENSE
'''
__version__ = '3.1.0'
__version_tuple__ = (3, 1, 0)
__version__ = '4.3.5'
__version_tuple__ = (4, 3, 5)
__all__ = ('func_timeout', 'FunctionTimedOut')
__all__ = ('func_timeout', 'func_set_timeout', 'FunctionTimedOut', 'StoppableThread')
from .exceptions import FunctionTimedOut
from .dafunc import func_timeout
from .dafunc import func_timeout, func_set_timeout
from .StoppableThread import StoppableThread

View File

@ -1,15 +1,35 @@
# vim: set ts=4 sw=4 expandtab :
'''
Copyright (c) 2016 Tim Savannah All Rights Reserved.
Copyright (c) 2016, 2017 Tim Savannah All Rights Reserved.
Licensed under the Lesser GNU Public License Version 3, LGPLv3. You should have recieved a copy of this with the source distribution as
LICENSE, otherwise it is available at https://github.com/kata198/func_timeout/LICENSE
'''
import copy
import inspect
import threading
import time
import types
import sys
from .exceptions import FunctionTimedOut
from .StoppableThread import StoppableThread
try:
from .py3_raise import raise_exception
except SyntaxError:
from .py2_raise import raise_exception
except ImportError:
from .py2_raise import raise_exception
from functools import wraps
__all__ = ('func_timeout', 'func_set_timeout')
def func_timeout(timeout, func, args=(), kwargs=None):
'''
func_timeout - Runs the given function for up to #timeout# seconds.
@ -17,26 +37,20 @@ def func_timeout(timeout, func, args=(), kwargs=None):
Raises any exceptions #func# would raise, returns what #func# would return (unless timeout is exceeded), in which case it raises FunctionTimedOut
@param timeout <float> - Maximum number of seconds to run #func# before terminating
@param func <function> - The function to call
@param args <tuple> - Any ordered arguments to pass to the function
@param kwargs <dict/None> - Keyword arguments to pass to the function.
@raises - FunctionTimedOut if #timeout# is exceeded, otherwise anything #func# could raise will be raised
If the timeout is exceeded, FunctionTimedOut will be raised within the context of the called function every two seconds until it terminates,
but will not block the calling thread (a new thread will be created to perform the join). If possible, you should try/except FunctionTimedOut
to return cleanly, but in most cases it will 'just work'.
Be careful of code like:
def myfunc():
while True:
try:
dosomething()
except Exception:
continue
because it will never terminate.
@return - The return value that #func# gives
'''
@ -52,10 +66,18 @@ def func_timeout(timeout, func, args=(), kwargs=None):
def funcwrap(args2, kwargs2):
try:
ret.append( func(*args2, **kwargs2) )
except FunctionTimedOut:
# Don't print traceback to stderr if we time out
pass
except Exception as e:
exc_info = sys.exc_info()
if isStopped is False:
# Don't capture stopping exception
exception.append(e)
# Assemble the alternate traceback, excluding this function
# from the trace (by going to next frame)
# Pytohn3 reads native from __traceback__,
# python2 has a different form for "raise"
e.__traceback__ = exc_info[2].tb_next
exception.append( e )
thread = StoppableThread(target=funcwrap, args=(args, kwargs))
thread.daemon = True
@ -64,17 +86,151 @@ def func_timeout(timeout, func, args=(), kwargs=None):
thread.join(timeout)
stopException = None
if thread.isAlive():
if thread.is_alive():
isStopped = True
stopException = FunctionTimedOut
class FunctionTimedOutTempType(FunctionTimedOut):
def __init__(self):
return FunctionTimedOut.__init__(self, '', timeout, func, args, kwargs)
FunctionTimedOutTemp = type('FunctionTimedOut' + str( hash( "%d_%d_%d_%d" %(id(timeout), id(func), id(args), id(kwargs))) ), FunctionTimedOutTempType.__bases__, dict(FunctionTimedOutTempType.__dict__))
stopException = FunctionTimedOutTemp
thread._stopThread(stopException)
thread.join(.1)
raise FunctionTimedOut('Function %s (args=%s) (kwargs=%s) timed out after %f seconds.\n' %(func.__name__, str(args), str(kwargs), timeout))
thread.join(min(.1, timeout / 50.0))
raise FunctionTimedOut('', timeout, func, args, kwargs)
else:
# We can still cleanup the thread here..
# Still give a timeout... just... cuz..
thread.join(.5)
if exception:
raise exception[0]
raise_exception(exception)
if ret:
return ret[0]
def func_set_timeout(timeout, allowOverride=False):
'''
func_set_timeout - Decorator to run a function with a given/calculated timeout (max execution time).
Optionally (if #allowOverride is True), adds a paramater, "forceTimeout", to the
function which, if provided, will override the default timeout for that invocation.
If #timeout is provided as a lambda/function, it will be called
prior to each invocation of the decorated function to calculate the timeout to be used
for that call, based on the arguments passed to the decorated function.
For example, you may have a "processData" function whose execution time
depends on the number of "data" elements, so you may want a million elements to have a
much higher timeout than seven elements.)
If #allowOverride is True AND a kwarg of "forceTimeout" is passed to the wrapped function, that timeout
will be used for that single call.
@param timeout <float OR lambda/function> -
**If float:**
Default number of seconds max to allow function to execute
before throwing FunctionTimedOut
**If lambda/function:
If a function/lambda is provided, it will be called for every
invocation of the decorated function (unless #allowOverride=True and "forceTimeout" was passed)
to determine the timeout to use based on the arguments to the decorated function.
The arguments as passed into the decorated function will be passed to this function.
They either must match exactly to what the decorated function has, OR
if you prefer to get the *args (list of ordered args) and **kwargs ( key : value keyword args form),
define your calculate function like:
def calculateTimeout(*args, **kwargs):
...
or lambda like:
calculateTimeout = lambda *args, **kwargs : ...
otherwise the args to your calculate function should match exactly the decorated function.
@param allowOverride <bool> Default False, if True adds a keyword argument to the decorated function,
"forceTimeout" which, if provided, will override the #timeout. If #timeout was provided as a lambda / function, it
will not be called.
@throws FunctionTimedOut If time alloted passes without function returning naturally
@see func_timeout
'''
# Try to be as efficent as possible... don't compare the args more than once
# Helps closure issue on some versions of python
defaultTimeout = copy.copy(timeout)
isTimeoutAFunction = bool( issubclass(timeout.__class__, (types.FunctionType, types.MethodType, types.LambdaType, types.BuiltinFunctionType, types.BuiltinMethodType) ) )
if not isTimeoutAFunction:
if not issubclass(timeout.__class__, (float, int)):
try:
timeout = float(timeout)
except:
raise ValueError('timeout argument must be a float/int for number of seconds, or a function/lambda which gets passed the function arguments and returns a calculated timeout (as float or int). Passed type: < %s > is not of any of these, and cannot be converted to a float.' %( timeout.__class__.__name__, ))
if not allowOverride and not isTimeoutAFunction:
# Only defaultTimeout provided. Simple function wrapper
def _function_decorator(func):
return wraps(func)(lambda *args, **kwargs : func_timeout(defaultTimeout, func, args=args, kwargs=kwargs))
# def _function_wrapper(*args, **kwargs):
# return func_timeout(defaultTimeout, func, args=args, kwargs=kwargs)
# return _function_wrapper
return _function_decorator
if not isTimeoutAFunction:
# allowOverride is True and timeout is not a function. Simple conditional on every call
def _function_decorator(func):
def _function_wrapper(*args, **kwargs):
if 'forceTimeout' in kwargs:
useTimeout = kwargs.pop('forceTimeout')
else:
useTimeout = defaultTimeout
return func_timeout(useTimeout, func, args=args, kwargs=kwargs)
return wraps(func)(_function_wrapper)
return _function_decorator
# At this point, timeout IS known to be a function.
timeoutFunction = timeout
if allowOverride:
# Could use a lambda here... but want traceback to highlight the calculate function,
# and not the invoked function
def _function_decorator(func):
def _function_wrapper(*args, **kwargs):
if 'forceTimeout' in kwargs:
useTimeout = kwargs.pop('forceTimeout')
else:
useTimeout = timeoutFunction(*args, **kwargs)
return func_timeout(useTimeout, func, args=args, kwargs=kwargs)
return wraps(func)(_function_wrapper)
return _function_decorator
# Cannot override, and calculate timeout function
def _function_decorator(func):
def _function_wrapper(*args, **kwargs):
useTimeout = timeoutFunction(*args, **kwargs)
return func_timeout(useTimeout, func, args=args, kwargs=kwargs)
return wraps(func)(_function_wrapper)
return _function_decorator
# vim: set ts=4 sw=4 expandtab :

View File

@ -1,13 +1,98 @@
'''
Copyright (c) 2016 Tim Savannah All Rights Reserved.
Copyright (c) 2016, 2017, 2019 Tim Savannah All Rights Reserved.
Licensed under the Lesser GNU Public License Version 3, LGPLv3. You should have recieved a copy of this with the source distribution as
LICENSE, otherwise it is available at https://github.com/kata198/func_timeout/LICENSE
'''
__all__ = ('FunctionTimedOut', 'RETRY_SAME_TIMEOUT')
RETRY_SAME_TIMEOUT = 'RETRY_SAME_TIMEOUT'
class FunctionTimedOut(BaseException):
'''
FunctionTimedOut - Exception raised when a function times out
@property timedOutAfter - Number of seconds before timeout was triggered
@property timedOutFunction - Function called which timed out
@property timedOutArgs - Ordered args to function
@property timedOutKwargs - Keyword args to function
@method retry - Retries the function with same arguments, with option to run with original timeout, no timeout, or a different
explicit timeout. @see FunctionTimedOut.retry
'''
pass
def __init__(self, msg='', timedOutAfter=None, timedOutFunction=None, timedOutArgs=None, timedOutKwargs=None):
'''
__init__ - Create this exception type.
You should not need to do this outside of testing, it will be created by the func_timeout API
@param msg <str> - A predefined message, otherwise we will attempt to generate one from the other arguments.
@param timedOutAfter <None/float> - Number of seconds before timing-out. Filled-in by API, None will produce "Unknown"
@param timedOutFunction <None/function> - Reference to the function that timed-out. Filled-in by API." None will produce "Unknown Function"
@param timedOutArgs <None/tuple/list> - List of fixed-order arguments ( *args ), or None for no args.
@param timedOutKwargs <None/dict> - Dict of keyword arg ( **kwargs ) names to values, or None for no kwargs.
'''
self.timedOutAfter = timedOutAfter
self.timedOutFunction = timedOutFunction
self.timedOutArgs = timedOutArgs
self.timedOutKwargs = timedOutKwargs
if not msg:
msg = self.getMsg()
BaseException.__init__(self, msg)
self.msg = msg
def getMsg(self):
'''
getMsg - Generate a default message based on parameters to FunctionTimedOut exception'
@return <str> - Message
'''
# Try to gather the function name, if available.
# If it is not, default to an "unknown" string to allow default instantiation
if self.timedOutFunction is not None:
timedOutFuncName = self.timedOutFunction.__name__
else:
timedOutFuncName = 'Unknown Function'
if self.timedOutAfter is not None:
timedOutAfterStr = "%f" %(self.timedOutAfter, )
else:
timedOutAfterStr = "Unknown"
return 'Function %s (args=%s) (kwargs=%s) timed out after %s seconds.\n' %(timedOutFuncName, repr(self.timedOutArgs), repr(self.timedOutKwargs), timedOutAfterStr)
def retry(self, timeout=RETRY_SAME_TIMEOUT):
'''
retry - Retry the timed-out function with same arguments.
@param timeout <float/RETRY_SAME_TIMEOUT/None> Default RETRY_SAME_TIMEOUT
If RETRY_SAME_TIMEOUT : Will retry the function same args, same timeout
If a float/int : Will retry the function same args with provided timeout
If None : Will retry function same args no timeout
@return - Returnval from function
'''
if timeout is None:
return self.timedOutFunction(*(self.timedOutArgs), **self.timedOutKwargs)
from .dafunc import func_timeout
if timeout == RETRY_SAME_TIMEOUT:
timeout = self.timedOutAfter
return func_timeout(timeout, self.timedOutFunction, args=self.timedOutArgs, kwargs=self.timedOutKwargs)

View File

@ -0,0 +1,5 @@
# Python2 allows specifying an alternate traceback.
def raise_exception(exception):
raise exception[0] , None , exception[0].__traceback__

View File

@ -0,0 +1,7 @@
# PEP 409 - Raise with the chained exception context disabled
# This, in effect, prevents the "funcwrap" wrapper ( chained
# in context to an exception raised here, due to scope )
# Only available in python3.3+
def raise_exception(exception):
raise exception[0] from None

59
mkdoc.sh Executable file
View File

@ -0,0 +1,59 @@
#!/bin/bash
# Ensure we are in the project root directory
cd "$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
shopt -s nullglob
ALL_MODS="$(echo func_timeout/*.py | tr ' ' '\n' | sed -e 's|/|.|g' -e 's|.py$||g' -e 's|.__init__$||g' | tr '\n' ' ')"
pydoc -w ${ALL_MODS}
mv func_timeout*.html doc/
pushd doc >/dev/null 2>&1
rm -f index.html
for fname in `echo *.html`;
do
python <<EOT
import AdvancedHTMLParser
import sys
if __name__ == '__main__':
filename = "${fname}"
parser = AdvancedHTMLParser.AdvancedHTMLParser()
parser.parseFile(filename)
em = parser.filter(tagName='a', href='.')
if len(em) == 0:
sys.exit(0)
em = em[0]
em.href = 'func_timeout.html'
parentNode = em.parentNode
emIndex = parentNode.children.index(em)
i = len(parentNode.children) - 1
while i > emIndex:
parentNode.removeChild( parentNode.children[i] )
i -= 1
with open(filename, 'wt') as f:
f.write(parser.getHTML())
EOT
done
ln -s func_timeout.html index.html
popd >/dev/null 2>&1

View File

@ -20,7 +20,7 @@ if __name__ == '__main__':
if dirName and os.getcwd() != dirName:
os.chdir(dirName)
summary = 'Python module which allows you to specify timeouts when calling any existing function'
summary = 'Python module which allows you to specify timeouts when calling any existing function. Also provides support for stoppable-threads'
try:
with open('README.rst', 'rt') as f:
@ -30,7 +30,7 @@ if __name__ == '__main__':
log_description = summary
setup(name='func_timeout',
version='3.1.0',
version='4.3.7',
packages=['func_timeout'],
author='Tim Savannah',
author_email='kata198@gmail.com',
@ -48,6 +48,11 @@ if __name__ == '__main__':
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Topic :: Software Development :: Libraries :: Python Modules'
]
)

View File

@ -1,4 +1,9 @@
#!/usr/bin/env python
'''
testit.py - Example code for ad-hoc function timeouts.
Newer tests for all features found in "tests" directory.
'''
from func_timeout import func_timeout, FunctionTimedOut
import time
@ -15,8 +20,16 @@ if __name__ == '__main__':
print ( "\tGot Return: %s\n" %(str(func_timeout(4, doit, args=(6,))),) )
print ( "\nShould time out (exception):" )
myException = None
try:
print ("\tGot Return: %s\n" %(str(func_timeout(1, doit, kwargs={'howmany' : 16})),))
except FunctionTimedOut as e:
sys.stderr.write('\tGot Exception: %s\n' %(str(e),))
myException = e
pass
print ( "\nRetrying with longer timeout, should get 16+17=33:" )
if myException is not None:
print ( "\nGot: %s\n" %( str(myException.retry(2.5)), ) )
else:
sys.stderr.write('Did not get exception before?\n')

View File

@ -0,0 +1,190 @@
# vim: set ts=4 sw=4 expandtab :
'''
Copyright (c) 2017 Tim Savannah All Rights Reserved.
Licensed under the Lesser GNU Public License Version 3, LGPLv3. You should have recieved a copy of this with the source distribution as
LICENSE, otherwise it is available at https://github.com/kata198/func_timeout/LICENSE
TestUtils.py - Common functions and types used across unit tests
'''
import copy
import sys
import time
import uuid
__all__ = ('ARG_NO_DEFAULT', 'getSleepLambda', 'getSleepLambdaWithArgs', 'compareTimes')
class ARG_NO_DEFAULT_TYPE(object):
def __eq__(self, other):
'''
__eq__ - Equal operator ( == ). Returns True if both are instances of ARG_NO_DEFAULT_TYPE,
or either is the type itself.
@param other <anything, preferably an ARG_NO_DEFAULT_TYPE instance> - The other item to compare
against this item.
@return <bool> - True if both objects are instances of ARG_NO_DEFAULT_TYPE,
or either are the type itself.
'''
# Is self == ARG_NO_DEFAULT_TYPE ever going to be True? Just in case...
if issubclass(other.__class__, ARG_NO_DEFAULT_TYPE) or (other == ARG_NO_DEFAULT_TYPE or self == ARG_NO_DEFAULT_TYPE):
return True
return False
def __ne__(self, other):
'''
__ne__ - Not-equal operator ( != ). Equivilant to not ==.
@see ARG_NO_DEFAULT_TYPE.__eq__
'''
return not self.__eq__(other)
def __cmp__(self, other):
'''
__cmp__ - Perform a "cmp" operation between self and other.
Added for completeness, like python2 sorting etc.
@param other <anything> - Another object, preferably one of ARG_NO_DEFAULT_TYPE.
@return <int> - Returns 0 if the objects are both
equal (both instances of ARG_NO_DEFAULT_TYPE),
otherwise to prevent recursion in sorting etc,
the id (location in memory) is compared.
'''
if self.__eq__(other):
return 0
if id(self) > id(other):
return 1
return -1
ARG_NO_DEFAULT = ARG_NO_DEFAULT_TYPE()
def getUniqueID(prefix):
uniqueName = prefix + '_' + str(uuid.uuid4().hex)
return uniqueName
def getSleepLambda(sleepTime):
'''
getSleepLambda - Get a lambda that takes two integer arguments (a, b)
and sleeps for a given number of seconds before returning the sum
@param sleepTime <float> - The number of seconds to sleep
@return lambda takes two integer argumennts, "a" and "b".
NOTE: Lambda's are usually to functions, as functions may get their scope/closure overridden
@see getSleepLambdaWithArgs
'''
# Ensure we don't get a strange reference override on somne versions of python
_sleepTime = copy.copy(sleepTime)
return eval('''lambda a, b : int(bool(time.sleep(%f))) + a + b''' %(_sleepTime,))
def getSleepLambdaWithArgs(sleepTime, args):
'''
getSleepLambdaWithArgs - Get a lambda that takes a variable collection of arguments
and sleeps for a given number of seconds before returning the sum of arguments
@param sleepTime <float> - The number of seconds to sleep
@param args list <tuple < str, (int) > - A list that represents the arguments to
the returned lambda. Should be a list of tuples.
The first tuple element is the name of the parameter. If a second paramater is present,
it will be used as the default value for that argument.
Keep in mind order is important ( i.e. no args with default following args without default),
as they will be used in the order provided.
All arguments should expect integer values.
@return lambda with the provided arguments
NOTE: Lambda's are usually to functions, as functions may get their scope/closure overridden
@see getSleepLambda
'''
# Ensure we don't get a strange reference override on somne versions of python
_sleepTime = copy.copy(sleepTime)
if not args:
raise ValueError('Empty "args" param. See docstring for usage details. Got: ' + repr(args))
_args = copy.deepcopy(args)
argStrs = []
argNames = []
for arg in _args:
argNames.append(arg[0])
if len(arg) == 1:
argStrs.append(arg[0])
else:
argStrs.append('%s=%d' %( arg[0], arg[1] ) )
argStr = ', '.join(argStrs)
sumStr = ' + '.join(argNames)
# print ( 'Function is: %s' %('''lambda %s : int(bool(time.sleep(%f))) + %s''' %(argStr, sleepTime, sumStr, ) ) )
return eval('''lambda %s : int(bool(time.sleep(%f))) + %s''' % (argStr, sleepTime, sumStr, ) )
def compareTimes(timeEnd, timeStart, cmpTime, roundTo=None, deltaFixed=.05, deltaPct=None):
'''
compareTimes - Compare two times, with support for max error
@param timeEnd <float> - End time
@param timeStart<float> - Start time
@param cmpTime <float> - Time to compare against
@param roundTo <None/int> - Number of digits to round-off to
@param deltaFixed <float/None> Default .05, If provided and if difference is within this much, the two values are considered equal
@param deltaPct <float/None> Default None, if provided and if difference is within this much, the two values are considered equal. 1 = 100%, .5 = 50%
Example: if trying to determine if function ran for 2 seconds with an error of .05 seconds,
if compareTimes( timeEnd, timeStart, 2, deltaFixed=.05, deltaPct=None) == 0
@return <int> cmp style, < 0 if time delta is less than #cmpTime
= 0 if time delta is equal (taking into account #deltaFixed and #deltaPct)
> 0 if time delta is greater than #cmpTime
'''
timeDiff = timeEnd - timeStart
delta = timeDiff - cmpTime
if roundTo is not None:
delta = round(delta, roundTo)
absDelta = abs(delta)
if deltaFixed and absDelta <= deltaFixed:
return 0
if deltaPct and absDelta <= (cmpTime * float(deltaPct)):
return 0
return delta
# vim: set ts=4 sw=4 expandtab :

View File

@ -0,0 +1,188 @@
#!/usr/bin/env python
# vim: set ts=4 sw=4 expandtab :
'''
Copyright (c) 2017 Tim Savannah All Rights Reserved.
Licensed under the Lesser GNU Public License Version 3, LGPLv3. You should have recieved a copy of this with the source distribution as
LICENSE, otherwise it is available at https://github.com/kata198/func_timeout/LICENSE
'''
import copy
import gc
import sys
import time
import threading
import subprocess
from func_timeout import func_timeout, FunctionTimedOut, func_set_timeout
from TestUtils import ARG_NO_DEFAULT, getSleepLambda, getSleepLambdaWithArgs, compareTimes
class TestBasic(object):
'''
TestBasic - Perform tests using the basic func_timeout function
'''
def test_funcTimeout(self):
sleepFunction = getSleepLambda(2.00)
expectedResult = 5 + 13
startTime = time.time()
result = sleepFunction(5, 13)
endTime = time.time()
assert result == expectedResult , 'Did not get return from sleepFunction'
try:
result = func_timeout(2.5, sleepFunction, args=(5, 13))
except FunctionTimedOut as te:
raise AssertionError('Got unexpected timeout at 2.5 second timeout for 2.00 second function: %s' %(str(te),))
assert result == expectedResult , 'Got wrong return from func_timeout.\nGot: %s\nExpected: %s\n' %(repr(result), repr(expectedResult))
gotException = False
try:
result = func_timeout(1, sleepFunction, args=(5, 13))
except FunctionTimedOut as te:
gotException = True
assert gotException , 'Expected to get FunctionTimedOut exception for 1.25 sec function at 1s timeout'
try:
result = func_timeout(2.5, sleepFunction, args=(5,), kwargs={ 'b' : 13})
except FunctionTimedOut as te:
raise AssertionError('Got unexpected timeout at 2.5 second timeout for 2.00 second function: %s' %(str(te), ))
except Exception as e:
raise AssertionError('Got unknown exception mixing args and kwargs: < %s > %s' %(e.__class__.__name__, str(e)))
assert result == expectedResult , 'Got wrong result when mixing args and kwargs'
def test_retry(self):
sleepFunction = getSleepLambda(1.2)
expectedResult = 5 + 19
gotException = False
functionTimedOut = None
startTime = time.time()
try:
result = func_timeout(.8, sleepFunction, args=(5, 19))
except FunctionTimedOut as fte:
functionTimedOut = fte
gotException = True
endTime = time.time()
assert gotException , 'Expected to get exception'
assert compareTimes(endTime, startTime, .8, 3, deltaFixed=.15) == 0 , 'Expected to wait .8 seconds. Was: %f - %f = %f' %(endTime, startTime, round(endTime - startTime, 3))
gotException = False
startTime = time.time()
try:
result = functionTimedOut.retry()
except FunctionTimedOut:
gotException = True
endTime = time.time()
assert gotException , 'Expected to get exception on retry.'
assert compareTimes(endTime, startTime, .8, 3, deltaFixed=.15) == 0 , 'Expected retry with no arguments to use same timeout of .8'
gotException = False
startTime = time.time()
try:
result = functionTimedOut.retry(None)
except FunctionTimedOut:
gotException = True
endTime = time.time()
assert not gotException , 'Did NOT to get exception with no timeout'
assert compareTimes(endTime, startTime, 1.2, 3, deltaFixed=.15) == 0 , 'Expected retry with None as timeout to last full length of function'
gotException = False
startTime = time.time()
try:
result = functionTimedOut.retry(.55)
except FunctionTimedOut:
gotException = True
finally:
endTime = time.time()
assert gotException , 'Expected to time out after .55 seconds when providing .55'
assert compareTimes(endTime, startTime, .55, 3, deltaFixed=.15) == 0 , 'Expected providing .55 would allow timeout of up to .55 seconds'
threadsCleanedUp = False
for i in range(5):
time.sleep(1)
gc.collect()
if threading.active_count() == 1:
threadsCleanedUp = True
break
assert threadsCleanedUp , 'Expected other threads to get cleaned up after gc collection'
def test_exception(self):
sleepFunction = getSleepLambda(.85)
expectedResult = 5 + 19
gotException = False
functionTimedOut = None
startTime = time.time()
try:
result = func_timeout(.5, sleepFunction, args=(5, 19))
except FunctionTimedOut as fte:
functionTimedOut = fte
gotException = True
endTime = time.time()
assert gotException , 'Expected to get exception'
assert 'timed out after ' in functionTimedOut.msg , 'Expected message to be constructed. Got: %s' %(repr(functionTimedOut.msg), )
assert round(functionTimedOut.timedOutAfter, 1) == .5 , 'Expected timedOutAfter to equal timeout ( .5 ). Got: %s' %(str(round(functionTimedOut.timedOutAfter, 1)), )
assert functionTimedOut.timedOutFunction == sleepFunction , 'Expected timedOutFunction to equal sleepFunction'
assert functionTimedOut.timedOutArgs == (5, 19) , 'Expected args to equal (5, 19)'
assert functionTimedOut.timedOutKwargs == {} , 'Expected timedOutKwargs to equal {}'
def test_instantiateExceptionNoArgs(self):
gotException = False
try:
exc = FunctionTimedOut()
msg = str(exc)
msg2 = exc.getMsg()
except Exception as _e:
sys.stderr.write('Got unexpected exception in test_instantiateExceptionNoArgs with no arguments. %s %s\n\n' %(str(type(_e)), str(_e)))
gotException = True
assert gotException is False, 'Expected to be able to create FunctionTimedOut exception without arguments.'
gotException = False
try:
exc = FunctionTimedOut('test')
msg = str(exc)
msg2 = str(exc.getMsg())
except Exception as _e:
sys.stderr.write('Got unexpected exception in test_instantiateExceptionNoArgs with fixed message string. %s %s\n\n' %(str(type(_e)), str(_e)))
gotException = True
assert gotException is False , 'Expected to be able to create a FunctionTimedOut exception with a fixed message.'
# Other forms (providing the function name) are tested elsewhere.
if __name__ == '__main__':
sys.exit(subprocess.Popen('GoodTests.py -n1 "%s" %s' %(sys.argv[0], ' '.join(['"%s"' %(arg.replace('"', '\\"'), ) for arg in sys.argv[1:]]) ), shell=True).wait())
# vim: set ts=4 sw=4 expandtab :

View File

@ -0,0 +1,441 @@
#!/usr/bin/env python
# vim: set ts=4 sw=4 expandtab :
'''
Copyright (c) 2017 Tim Savannah All Rights Reserved.
Licensed under the Lesser GNU Public License Version 3, LGPLv3. You should have recieved a copy of this with the source distribution as
LICENSE, otherwise it is available at https://github.com/kata198/func_timeout/LICENSE
'''
import copy
import gc
import sys
import time
import threading
import subprocess
from func_timeout import func_timeout, FunctionTimedOut, func_set_timeout
from TestUtils import ARG_NO_DEFAULT, getSleepLambda, getSleepLambdaWithArgs, compareTimes
SLEEP_TIME = 1.25
def doSleep(a, b):
time.sleep(a)
return a + b
def calculateSleep(a, b):
return a * 1.15
class TestDecorator(object):
'''
TestDecorator - Perform tests using the func_set_timeout wrapper
'''
def test_funcSetTimeout(self):
@func_set_timeout(SLEEP_TIME)
def doSleepFunc(a, b):
time.sleep(a)
return a + b
expected = SLEEP_TIME * 1.3 + 4
gotException = False
startTime = time.time()
try:
result = doSleepFunc(SLEEP_TIME * 1.3, 4)
except FunctionTimedOut as fte:
gotException = True
endTime = time.time()
assert gotException , 'Expected to get exception at sleep time'
assert compareTimes(endTime, startTime, SLEEP_TIME, None, deltaFixed=.15) == 0 , 'Expected to sleep up to sleep time'
expected = SLEEP_TIME * .8 + 4
gotException = False
startTime = time.time()
try:
result = doSleepFunc(SLEEP_TIME * .8, 4)
except FunctionTimedOut as fte:
gotException = True
endTime = time.time()
assert not gotException , 'Expected not to get exception at 80% sleep time'
assert compareTimes(endTime, startTime, SLEEP_TIME * .8, None, deltaFixed=.15) == 0 , 'Expected to only sleep for 80% of sleep time'
assert result == expected , 'Got wrong result'
def test_funcSetTimeoutOverride(self):
@func_set_timeout(SLEEP_TIME, allowOverride=True)
def doSleepFunc(a, b):
time.sleep(a)
return a + b
expected = SLEEP_TIME * 1.3 + 4
gotException = False
startTime = time.time()
try:
result = doSleepFunc(SLEEP_TIME * 1.3, 4, forceTimeout=SLEEP_TIME * 1.2)
except FunctionTimedOut as fte:
gotException = True
except Exception as e:
raise AssertionError('Expected to be able to override forceTimeout when allowOverride=True')
endTime = time.time()
assert gotException , 'Expected to get exception at 130% sleep time'
assert compareTimes(endTime, startTime, SLEEP_TIME * 1.2, None, deltaFixed=.15) == 0 , 'Expected to sleep up to 120% of sleep time'
@func_set_timeout(SLEEP_TIME, allowOverride=False)
def doSleepFuncNoOverride(a, b):
time.sleep(a)
return a + b
gotException = False
try:
doSleepFuncNoOverride(SLEEP_TIME * 1.3, 4, forceTimeout=SLEEP_TIME * 1.2)
except Exception as e:
gotException = True
except FunctionTimedOut as fte:
raise AssertionError('Expected to NOT be able to pass forceTimeout when allowOverride=False, but got FunctionTimedOut exception')
assert gotException , 'Expected to NOT be able to pass forceTimeout when allowOverride=False, but did not get exception'
expected = SLEEP_TIME + 4
gotException = False
startTime = time.time()
try:
result = doSleepFunc(SLEEP_TIME, 4, forceTimeout=SLEEP_TIME * 1.15)
except FunctionTimedOut as fte:
gotException = True
endTime = time.time()
assert not gotException , 'Expected not to get exception with forced 115% sleep time'
assert compareTimes(endTime, startTime, SLEEP_TIME, None, deltaFixed=.15) == 0 , 'Expected to sleep for SLEEP_TIME'
assert result == expected , 'Got wrong result'
def test_funcSetTimeCalculate(self):
def calculateSleepOver(a, b):
return a * 1.2
def calculateSleepUnder(a, b):
return a * .8
def calculateSleepOverArgs(*args, **kwargs):
return args[0] * 1.2
def calculateSleepUnderArgs(*args, **kwargs):
return args[0] * .8
@func_set_timeout(calculateSleepOver, allowOverride=False)
def doSleepFuncOver(a, b):
time.sleep(a)
return a + b
expected = SLEEP_TIME + 4
gotException = False
startTime = time.time()
try:
result = doSleepFuncOver(SLEEP_TIME, 4)
except FunctionTimedOut as fte:
gotException = True
endTime = time.time()
assert not gotException , 'Expected not to get exception with calculated 120% timeout on sleep time'
assert compareTimes(endTime, startTime, SLEEP_TIME, None, deltaFixed=.15) == 0 , 'Expected to sleep for SLEEP_TIME'
assert result == expected , 'Got wrong result'
@func_set_timeout(calculateSleepUnder, allowOverride=False)
def doSleepFuncUnder(a, b):
time.sleep(a)
return a + b
expected = SLEEP_TIME + 4
gotException = False
startTime = time.time()
try:
result = doSleepFuncUnder(SLEEP_TIME, 4)
except FunctionTimedOut as fte:
gotException = True
endTime = time.time()
assert gotException , 'Expected to get exception with calculated 80% timeout on sleep time'
assert compareTimes(endTime, startTime, SLEEP_TIME * .8, None, deltaFixed=.15) == 0 , 'Expected to sleep for 80% SLEEP_TIME'
@func_set_timeout(calculateSleepOverArgs, allowOverride=False)
def doSleepFuncOverArgs(a, b):
time.sleep(a)
return a + b
expected = SLEEP_TIME + 4
gotException = False
startTime = time.time()
try:
result = doSleepFuncOverArgs(SLEEP_TIME, 4)
except FunctionTimedOut as fte:
gotException = True
endTime = time.time()
assert not gotException , 'Expected not to get exception with calculated 120% timeout on sleep time using *args'
assert compareTimes(endTime, startTime, SLEEP_TIME, None, deltaFixed=.15) == 0 , 'Expected to sleep for SLEEP_TIME using *args'
assert result == expected , 'Got wrong result'
@func_set_timeout(calculateSleepUnderArgs, allowOverride=False)
def doSleepFuncUnderArgs(a, b):
time.sleep(a)
return a + b
expected = SLEEP_TIME + 4
gotException = False
startTime = time.time()
try:
result = doSleepFuncUnderArgs(SLEEP_TIME, 4)
except FunctionTimedOut as fte:
gotException = True
endTime = time.time()
assert gotException , 'Expected to get exception with calculated 80% timeout on sleep time using *args'
assert compareTimes(endTime, startTime, SLEEP_TIME * .8, None, deltaFixed=.15) == 0 , 'Expected to sleep for 80% SLEEP_TIME using *args'
def test_funcSetTimeCalculateWithOverride(self):
def calculateSleepOver(a, b):
return a * 1.2
def calculateSleepUnder(a, b):
return a * .8
def calculateSleepOverArgs(*args, **kwargs):
return args[0] * 1.2
def calculateSleepUnderArgs(*args, **kwargs):
return args[0] * .8
@func_set_timeout(calculateSleepOver, allowOverride=True)
def doSleepFuncOver(a, b):
time.sleep(a)
return a + b
expected = SLEEP_TIME + 4
gotException = False
startTime = time.time()
try:
result = doSleepFuncOver(SLEEP_TIME, 4)
except FunctionTimedOut as fte:
gotException = True
endTime = time.time()
assert not gotException , 'Expected not to get exception with calculated 120% timeout on sleep time'
assert compareTimes(endTime, startTime, SLEEP_TIME, None, deltaFixed=.15) == 0 , 'Expected to sleep for SLEEP_TIME'
assert result == expected , 'Got wrong result'
expected = SLEEP_TIME + 4
gotException = False
startTime = time.time()
try:
result = doSleepFuncOver(SLEEP_TIME, 4, forceTimeout= SLEEP_TIME * 1.5)
except FunctionTimedOut as fte:
gotException = True
endTime = time.time()
assert not gotException , 'Expected not to get exception with calculated 120% timeout on sleep time but 150% timeout on override'
assert compareTimes(endTime, startTime, SLEEP_TIME, None, deltaFixed=.15) == 0 , 'Expected to sleep for SLEEP_TIME with 150% timeout on override'
assert result == expected , 'Got wrong result'
expected = SLEEP_TIME + 4
gotException = False
startTime = time.time()
try:
result = doSleepFuncOver(SLEEP_TIME, 4, forceTimeout=SLEEP_TIME * .7)
except FunctionTimedOut as fte:
gotException = True
endTime = time.time()
assert gotException , 'Expected to get exception with calculated 120% timeout on sleep time but 70% timeout on override'
assert compareTimes(endTime, startTime, SLEEP_TIME * .7, None, deltaFixed=.15) == 0 , 'Expected to sleep for 70% SLEEP_TIME with 70% timeout on override'
@func_set_timeout(calculateSleepUnder, allowOverride=True)
def doSleepFuncUnder(a, b):
time.sleep(a)
return a + b
expected = SLEEP_TIME + 4
gotException = False
startTime = time.time()
try:
result = doSleepFuncUnder(SLEEP_TIME, 4)
except FunctionTimedOut as fte:
gotException = True
endTime = time.time()
assert gotException , 'Expected to get exception with calculated 80% timeout on sleep time'
assert compareTimes(endTime, startTime, SLEEP_TIME * .8, None, deltaFixed=.15) == 0 , 'Expected to sleep for 80% SLEEP_TIME'
expected = SLEEP_TIME + 4
gotException = False
startTime = time.time()
try:
result = doSleepFuncUnder(SLEEP_TIME, 4, forceTimeout=SLEEP_TIME * 1.2)
except FunctionTimedOut as fte:
gotException = True
endTime = time.time()
assert not gotException , 'Expected not to get exception with calculated 80% timeout on sleep time but 120% timeout on override'
assert compareTimes(endTime, startTime, SLEEP_TIME , None, deltaFixed=.15) == 0 , 'Expected to sleep for SLEEP_TIME with 120% timeout on override'
def test_setFuncTimeoutetry(self):
def calculateSleepOver(a, b):
return a * 1.2
def calculateSleepUnder(a, b):
return a * .8
def calculateSleepOverArgs(*args, **kwargs):
return args[0] * 1.2
def calculateSleepUnderArgs(*args, **kwargs):
return args[0] * .8
@func_set_timeout(calculateSleepUnder, allowOverride=True)
def doSleepFuncUnder(a, b):
time.sleep(a)
return a + b
expected = SLEEP_TIME + 4
gotException = False
functionTimedOut = None
startTime = time.time()
try:
result = doSleepFuncUnder(SLEEP_TIME, 4)
except FunctionTimedOut as fte:
gotException = True
functionTimedOut = fte
endTime = time.time()
assert gotException , 'Expected to get exception with calculated 80% timeout'
assert compareTimes(endTime, startTime, SLEEP_TIME * .8, None, deltaFixed=.15) == 0 , 'Expected to sleep for 80% SLEEP_TIME with 80% timeout'
gotException = False
startTime = time.time()
try:
functionTimedOut.retry()
except FunctionTimedOut as fte2:
gotException = True
except Exception as e:
raise AssertionError('Got exception trying to retry with same timeout: < %s > : %s' %(e.__name__, str(e)))
endTime = time.time()
assert gotException , 'Expected to get exception with calculated same 80% timeout on retry'
assert compareTimes(endTime, startTime, SLEEP_TIME * .8, None, deltaFixed=.15) == 0 , 'Expected to sleep for 80% SLEEP_TIME with same 80% timeout on retry'
result = None
gotException = False
startTime = time.time()
try:
result = functionTimedOut.retry(None)
except FunctionTimedOut as fte2:
gotException = True
except Exception as e:
raise AssertionError('Got exception trying to retry with same timeout: < %s > : %s' %(e.__name__, str(e)))
endTime = time.time()
assert not gotException , 'Expected to get exception with calculated 80% timeout on retry ( None ) [ No timeout ]'
assert compareTimes(endTime, startTime, SLEEP_TIME, None, deltaFixed=.15) == 0 , 'Expected to sleep for 100% SLEEP_TIME with 80% timeout overriden on retry ( None ) [ No timeout ]'
assert result == expected , 'Got wrong result'
gotException = False
startTime = time.time()
try:
functionTimedOut.retry(SLEEP_TIME * .6)
except FunctionTimedOut as fte2:
gotException = True
except Exception as e:
raise AssertionError('Got exception trying to retry with same timeout: < %s > : %s' %(e.__name__, str(e)))
endTime = time.time()
assert gotException , 'Expected to get exception with calculated 80% timeout overriden by 60% timeout on retry'
assert compareTimes(endTime, startTime, SLEEP_TIME * .6, None, deltaFixed=.15) == 0 , 'Expected to sleep for 60% SLEEP_TIME with 80% timeout overriden on retry ( SLEEP_TIME * .6 ) [ 60% timeout ]'
result = None
gotException = False
startTime = time.time()
try:
result = functionTimedOut.retry(SLEEP_TIME * 1.5)
except FunctionTimedOut as fte2:
gotException = True
except Exception as e:
raise AssertionError('Got exception trying to retry with same timeout: < %s > : %s' %(e.__name__, str(e)))
endTime = time.time()
assert not gotException , 'Expected to get exception with calculated 80% timeout overriden by 150% timeout on retry'
assert compareTimes(endTime, startTime, SLEEP_TIME , None, deltaFixed=.15) == 0 , 'Expected to sleep for 100% SLEEP_TIME with 80% timeout overriden on retry ( SLEEP_TIME * 1.5 ) [ 150% timeout ]'
assert result == expected
threadsCleanedUp = False
for i in range(5):
time.sleep(1)
gc.collect()
if threading.active_count() == 1:
threadsCleanedUp = True
break
assert threadsCleanedUp , 'Expected other threads to get cleaned up after gc collection'
def test_nameRetained(self):
# Case of just timeout
@func_set_timeout(2, allowOverride=False)
def hello():
pass
assert hello.__name__ == 'hello'
del hello
def getTimeoutFunc():
return 2
# Timeout is function
@func_set_timeout(getTimeoutFunc, allowOverride=False)
def hello2():
pass
assert hello2.__name__ == 'hello2'
del hello2
# Now the same with allowOverride=True
@func_set_timeout(2, allowOverride=True)
def hello3():
pass
assert hello3.__name__ == 'hello3'
del hello3
@func_set_timeout(getTimeoutFunc, allowOverride=True)
def hello4():
pass
assert hello4.__name__ == 'hello4'
if __name__ == '__main__':
sys.exit(subprocess.Popen('GoodTests.py -n1 "%s" %s' %(sys.argv[0], ' '.join(['"%s"' %(arg.replace('"', '\\"'), ) for arg in sys.argv[1:]]) ), shell=True).wait())
# vim: set ts=4 sw=4 expandtab :

View File

@ -0,0 +1,159 @@
#!/usr/bin/env python
# vim: set ts=4 sw=4 expandtab :
'''
Copyright (c) 2017 Tim Savannah All Rights Reserved.
Licensed under the Lesser GNU Public License Version 3, LGPLv3. You should have recieved a copy of this with the source distribution as
LICENSE, otherwise it is available at https://github.com/kata198/func_timeout/LICENSE
'''
import copy
import gc
import sys
import time
import threading
import subprocess
from func_timeout import func_timeout, FunctionTimedOut, func_set_timeout
from TestUtils import ARG_NO_DEFAULT, getSleepLambda, getSleepLambdaWithArgs, compareTimes
class TestBasic(object):
'''
TestBasic - Perform tests using the basic func_timeout function
'''
def test_funcTimeout(self):
sleepFunction = getSleepLambda(1.25)
expectedResult = 5 + 13
startTime = time.time()
result = sleepFunction(5, 13)
endTime = time.time()
assert result == expectedResult , 'Did not get return from sleepFunction'
try:
result = func_timeout(1.5, sleepFunction, args=(5, 13))
except FunctionTimedOut as te:
raise AssertionError('Got unexpected timeout at 1.5 second timeout for 1.25 second function: %s' %(str(te),))
assert result == expectedResult , 'Got wrong return from func_timeout.\nGot: %s\nExpected: %s\n' %(repr(result), repr(expectedResult))
gotException = False
try:
result = func_timeout(1, sleepFunction, args=(5, 13))
except FunctionTimedOut as te:
gotException = True
assert gotException , 'Expected to get FunctionTimedOut exception for 1.25 sec function at 1s timeout'
try:
result = func_timeout(1.5, sleepFunction, args=(5,), kwargs={ 'b' : 13})
except FunctionTimedOut as te:
raise AssertionError('Got unexpected timeout at 1.5 second timeout for 1.25 second function: %s' %(str(te), ))
except Exception as e:
raise AssertionError('Got unknown exception mixing args and kwargs: < %s > %s' %(e.__class__.__name__, str(e)))
assert result == expectedResult , 'Got wrong result when mixing args and kwargs'
def test_retry(self):
sleepFunction = getSleepLambda(.5)
expectedResult = 5 + 19
gotException = False
functionTimedOut = None
startTime = time.time()
try:
result = func_timeout(.3, sleepFunction, args=(5, 19))
except FunctionTimedOut as fte:
functionTimedOut = fte
gotException = True
endTime = time.time()
assert gotException , 'Expected to get exception'
assert compareTimes(endTime, startTime, .3, 3, .15, None) == 0 , 'Expected to wait .3 seconds. Was: %f - %f = %f' %(endTime, startTime, round(endTime - startTime, 3))
gotException = False
startTime = time.time()
try:
result = functionTimedOut.retry()
except FunctionTimedOut:
gotException = True
endTime = time.time()
assert gotException , 'Expected to get exception on retry.'
assert compareTimes(endTime, startTime, .3, 3, .1, None) == 0 , 'Expected retry with no arguments to use same timeout of .3'
gotException = False
startTime = time.time()
try:
result = functionTimedOut.retry(None)
except FunctionTimedOut:
gotException = True
endTime = time.time()
assert not gotException , 'Did NOT to get exception with no timeout'
assert compareTimes(endTime, startTime, .5, 3, .1, None) == 0 , 'Expected retry with None as timeout to last full length of function'
gotException = False
startTime = time.time()
try:
result = functionTimedOut.retry(.4)
except FunctionTimedOut:
gotException = True
finally:
endTime = time.time()
assert gotException , 'Expected to time out after .5 seconds when providing .5'
assert compareTimes(endTime, startTime, .5, 3, .1, None) == 0 , 'Expected providing .5 would allow timeout of up to .5 seconds'
threadsCleanedUp = False
for i in range(5):
time.sleep(1)
gc.collect()
if threading.active_count() == 1:
threadsCleanedUp = True
break
assert threadsCleanedUp , 'Expected other threads to get cleaned up after gc collection'
def test_exception(self):
sleepFunction = getSleepLambda(.5)
expectedResult = 5 + 19
gotException = False
functionTimedOut = None
startTime = time.time()
try:
result = func_timeout(.3, sleepFunction, args=(5, 19))
except FunctionTimedOut as fte:
functionTimedOut = fte
gotException = True
endTime = time.time()
assert gotException , 'Expected to get exception'
assert 'timed out after ' in functionTimedOut.msg , 'Expected message to be constructed. Got: %s' %(repr(functionTimedOut.msg), )
assert round(functionTimedOut.timedOutAfter, 1) == .3 , 'Expected timedOutAfter to equal timeout ( .3 ). Got: %s' %(str(round(functionTimedOut.timedOutAfter, 1)), )
assert functionTimedOut.timedOutFunction == sleepFunction , 'Expected timedOutFunction to equal sleepFunction'
assert functionTimedOut.timedOutArgs == (5, 19) , 'Expected args to equal (5, 19)'
assert functionTimedOut.timedOutKwargs == {} , 'Expected timedOutKwargs to equal {}'
if __name__ == '__main__':
sys.exit(subprocess.Popen('GoodTests.py -n1 "%s" %s' %(sys.argv[0], ' '.join(['"%s"' %(arg.replace('"', '\\"'), ) for arg in sys.argv[1:]]) ), shell=True).wait())
# vim: set ts=4 sw=4 expandtab :

View File

@ -0,0 +1,58 @@
#!/usr/bin/env python
# vim: set ts=4 sw=4 expandtab :
'''
Copyright (c) 2017 Tim Savannah All Rights Reserved.
Licensed under the Lesser GNU Public License Version 3, LGPLv3. You should have recieved a copy of this with the source distribution as
LICENSE, otherwise it is available at https://github.com/kata198/func_timeout/LICENSE
'''
import copy
import sys
import subprocess
import time
from func_timeout import func_timeout, FunctionTimedOut, func_set_timeout
from TestUtils import ARG_NO_DEFAULT, ARG_NO_DEFAULT_TYPE, getSleepLambda, getSleepLambdaWithArgs, compareTimes
class TestTestUtils(object):
'''
TestTestUtils - Perform tests using the basic func_timeout function
'''
def test_ArgNoDefault(self):
assert ARG_NO_DEFAULT == ARG_NO_DEFAULT , 'Expected ARG_NO_DEFAULT to equal itself'
assert (ARG_NO_DEFAULT != ARG_NO_DEFAULT) is False , 'Expected ARG_NO_DEFAULT to not not equal itself'
assert ARG_NO_DEFAULT == ARG_NO_DEFAULT_TYPE , 'Expected ARG_NO_DEFAULT to equal ARG_NO_DEFAULT_TYPE'
assert ARG_NO_DEFAULT_TYPE == ARG_NO_DEFAULT , '2Expected ARG_NO_DEFAULT to equal ARG_NO_DEFAULT_TYPE'
otherInstance = ARG_NO_DEFAULT_TYPE()
assert otherInstance == ARG_NO_DEFAULT , 'Assert ARG_NO_DEFAULT_TYPE instances equal eachother'
assert not (otherInstance != ARG_NO_DEFAULT) , 'Assert ARG_NO_DEFAULT_TYPE instances not not-equal eachother'
def test_compareTimes(self):
startTime = 50.00
endTime = 52.03
assert compareTimes(endTime, startTime, 2, roundTo=2, deltaFixed=.05, deltaPct=None) == 0 , 'Expected deltaFixed to be > abs(delta) to show times equal'
assert compareTimes(endTime, startTime, 2, roundTo=2, deltaFixed=.01, deltaPct=None) == .03 , 'Expected when deltaFixed is less than the abs delta, actual diff to be returned.'
assert compareTimes(endTime, startTime, 2, roundTo=2, deltaFixed=None, deltaPct=.2) == 0 , 'Expected deltaPct * cmpTime when greater than abs delta to be equal'
assert compareTimes(endTime, startTime, 2, roundTo=2, deltaFixed=None, deltaPct=.0002) == .03 , 'Expected deltaPct * cmpTime when less than abs delta to be actual diff'
if __name__ == '__main__':
sys.exit(subprocess.Popen('GoodTests.py -n1 "%s" %s' %(sys.argv[0], ' '.join(['"%s"' %(arg.replace('"', '\\"'), ) for arg in sys.argv[1:]]) ), shell=True).wait())
# vim: set ts=4 sw=4 expandtab :

View File

@ -0,0 +1,59 @@
#!/usr/bin/env python
# vim: set ts=4 sw=4 expandtab :
'''
Copyright (c) 2017 Tim Savannah All Rights Reserved.
Licensed under the Lesser GNU Public License Version 3, LGPLv3. You should have recieved a copy of this with the source distribution as
LICENSE, otherwise it is available at https://github.com/kata198/func_timeout/LICENSE
'''
import copy
import sys
import subprocess
import time
from func_timeout import func_timeout, FunctionTimedOut, func_set_timeout
from TestUtils import ARG_NO_DEFAULT, ARG_NO_DEFAULT_TYPE, getSleepLambda, getSleepLambdaWithArgs, compareTimes
class TestBasicSleep(object):
'''
TestBasicSleep - Perform test on the sleep generator function.
Seperate file so runs in separate GoodTests process ( for performance reasons )
'''
def test_getSleepLambda(self):
sleepLambda = getSleepLambda(2)
startTime = time.time()
sleepLambda(2, 3)
endTime = time.time()
assert compareTimes(endTime, startTime, 2, 2, deltaFixed=.1, deltaPct=None) == 0 , 'Expected getSleepLambda(2) to take 2 seconds.'
sleepLambda = getSleepLambda(1.75)
expectedResult = 2 + 3
startTime = time.time()
result = sleepLambda(2, 3)
endTime = time.time()
assert result == expectedResult , 'Got wrong result'
assert compareTimes(endTime, startTime, 1.75, 2, deltaFixed=.1, deltaPct=None) == 0 , 'Expected getSleepLambda(1.75) to take 1.75 seconds.'
expectedResult = 5 + 13
startTime = time.time()
result = sleepLambda(5, 13)
endTime = time.time()
assert result == expectedResult , 'Did not get return from sleepFunction'
assert compareTimes(endTime, startTime, 1.75, 2, deltaFixed=.1, deltaPct=None) == 0 , 'Expected getSleepLambda(1.75) to take 1.75 seconds.'
if __name__ == '__main__':
sys.exit(subprocess.Popen('GoodTests.py -n1 "%s" %s' %(sys.argv[0], ' '.join(['"%s"' %(arg.replace('"', '\\"'), ) for arg in sys.argv[1:]]) ), shell=True).wait())
# vim: set ts=4 sw=4 expandtab :

View File

@ -0,0 +1,71 @@
#!/usr/bin/env python
# vim: set ts=4 sw=4 expandtab :
'''
Copyright (c) 2017 Tim Savannah All Rights Reserved.
Licensed under the Lesser GNU Public License Version 3, LGPLv3. You should have recieved a copy of this with the source distribution as
LICENSE, otherwise it is available at https://github.com/kata198/func_timeout/LICENSE
'''
import copy
import sys
import subprocess
import time
from func_timeout import func_timeout, FunctionTimedOut, func_set_timeout
from TestUtils import ARG_NO_DEFAULT, ARG_NO_DEFAULT_TYPE, getSleepLambda, getSleepLambdaWithArgs, compareTimes
class TestBasicSleepWithArgs(object):
'''
TestBasicSleepWithArgs - Perform test on the sleep generator with args function.
Seperate file so runs in separate GoodTests process ( for performance reasons )
'''
def test_getSleepLambdaWithArgs(self):
sleepLambda = getSleepLambdaWithArgs(2, [ ('a', ), ('b', ), ('c', 4) ] )
startTime = time.time()
try:
sleepLambda(1, 2)
except:
raise AssertionError('Expected to have 1 default arg and 2 standard. Tried 3 args')
endTime = time.time()
assert compareTimes(endTime, startTime, 2, 2, deltaFixed=.15, deltaPct=None) == 0 , 'Expected getSleepLambdaWithArgs(2) to take 2 seconds.'
try:
sleepLambda(4, 7, 12)
except:
raise AssertionError('Expected to have 1 default arg and 2 standard. Tried 3 args.')
expectedResult = 2 + 3
sleepLambda = getSleepLambdaWithArgs(1.75, [ ('a', ), ('xxx', )] )
startTime = time.time()
try:
result = sleepLambda(xxx=2, a=3)
except:
raise AssertionError('Expected to be able to use provided field names when calling function')
endTime = time.time()
assert result == expectedResult , 'Got wrong result'
assert compareTimes(endTime, startTime, 1.75, 2, deltaFixed=.15, deltaPct=None) == 0 , 'Expected getSleepLambdaWithArgs(1.75) to take 1.75 seconds.'
expectedResult = 5 + 13
startTime = time.time()
result = sleepLambda(5, 13)
endTime = time.time()
assert result == expectedResult , 'Did not get return from sleepFunction'
assert compareTimes(endTime, startTime, 1.75, 2, deltaFixed=.15, deltaPct=None) == 0 , 'Expected getSleepLambda(1.75) to take 1.75 seconds.'
if __name__ == '__main__':
sys.exit(subprocess.Popen('GoodTests.py -n1 "%s" %s' %(sys.argv[0], ' '.join(['"%s"' %(arg.replace('"', '\\"'), ) for arg in sys.argv[1:]]) ), shell=True).wait())
# vim: set ts=4 sw=4 expandtab :

3
tests/README Normal file
View File

@ -0,0 +1,3 @@
Run ./runTests.py to execute all unit tests against parent directory "func_timeout" (will not run against site install.)
This will download GoodTests.py if not already present in PATH, and use it to execute the unit tests in parallel, forcing resolution to the parent func_timeout dir

411
tests/runTests.py Executable file
View File

@ -0,0 +1,411 @@
#!/usr/bin/env python
#
# Copyright (c) 2015, 2016, 2017 Tim Savannah under following terms:
# You may modify and redistribe this script with your project
#
# It will download the latest GoodTests.py and use it to execute the tests.
#
# This should be placed in a directory, "tests", at the root of your project. It assumes that ../$MY_PACKAGE_MODULE is the path to your test module, and will create a symlink to it in order to run tests.
# The tests should be found in $MY_TEST_DIRECTORY in given "tests" folder.
# NOTE: Since version 1.2.3, you can also import this (like from a graphical application) and call the "main()" function.
# All of the following globals are the defaults, but can be overridden when calling main() (params have the same name as the globals).
# Assign a local function, "find_mod" to the interface to search
# PYTHONPATH for importable module
try:
# imp.find_module has been deprecated as of python 3.7, so
# prefer some alternate/newer interfaces first.
import importlib
try:
# If we have the newest and therefore least-deprecated
# way, use it.
_findModSpec = importlib.util.find_spec
def find_mod(modName):
'''
find_mod - Find a module by name.
Similar to import #modName but only finds importable module,
does not actually import.
@raises ImportError on failure
'''
modSpec = _findModSpec(modName)
if not modSpec:
# imp.find_module raises import error if cannot find,
# but find_spec just returns None
# So simulate the ImportError for common interface
raise ImportError('No module named %s' %(modName, ))
return modSpec
except AttributeError:
# We have importlib, but don't have importlib.util.find_spec
# We could use importlib.import_module which is present in
# python 2.7, but that changes behaviour by actually
# importing (and thus additionally checking syntax/other).
#
# So just fall back to the old imp.find_module in this case
try:
# Clean up namespace
del importlib
except:
pass
# Fall back to imp.find_module implementation below
raise ImportError('importlib but no importlib.util')
#find_mod = lambda modName : importlib.import_module(modName)
except:
# importlib is not present or has an unknown/dated interface,
# so fallback to the deprecated but oldest form
import imp
# Use a lambda to ensure only one arg is passed as that is
# our standard interface
find_mod = lambda modName : imp.find_module(modName)
import os
import subprocess
import sys
# URL to current version of GoodTests.py - You only need to change this if you host an internal copy.
GOODTESTS_URL = 'https://raw.githubusercontent.com/kata198/GoodTests/master/GoodTests.py'
# This should be your module name, and can be any relative or absolute path, or just a module name.
# If just a module name is given, the directory must be in current directory or parent directory.
MY_PACKAGE_MODULE = 'func_timeout'
# Normally, you want to test the codebase during development, so you don't care about the site-packages installed version.
# If you want to allow testing with any module by @MY_PACKAGE_MODULE in the python path, change this to True.
ALLOW_SITE_INSTALL = False
# This is the test directory that should contain all your tests. This should be a directory in your "tests" folder
MY_TEST_DIRECTORY = 'FuncTimeoutTests'
__version__ = '3.0.5'
__version_tuple__ = (3, 0, 5)
def findGoodTests():
'''
findGoodTests - Tries to find GoodTests.py
@return <dict> {
'path' <str> -> Path to GoodTests.py (for execution)
'success' <bool> -> True/False if we successfully found GoodTests.py
}
'''
pathSplit = os.environ['PATH'].split(':')
if '.' not in pathSplit:
pathSplit = ['.'] + pathSplit
os.environ['PATH'] = ':'.join(pathSplit)
result = ''
success = False
for path in pathSplit:
if path.endswith('/'):
path = path[:-1]
guess = path + '/GoodTests.py'
if os.path.exists(guess):
success = True
result = guess
break
return {
'path' : result,
"success" : success
}
def findExecutable(execName):
'''
findExecutable - Search PATH for an executable
@return <dict> {
'path' <str> -> Path to executable (if found, see "success")
'success' <bool> -> True/False if we successfully found requested executable
}
'''
pathSplit = os.environ['PATH'].split(':')
if '.' not in pathSplit:
pathSplit = ['.'] + pathSplit
os.environ['PATH'] = ':'.join(pathSplit)
result = ''
success = False
for path in pathSplit:
if path.endswith(os.sep):
path = path[:-1]
guess = path + os.sep + execName
if os.path.exists(guess):
success = True
result = guess
break
return {
"path" : result,
"success" : success
}
def findGoodTests():
return findExecutable('GoodTests.py')
def try_pip_install():
'''
try to pip install GoodTests.py
First, try via pip module.
If that fails, try to locate pip by dirname(current python executable) + os.sep + pip
If that does not exist, scan PATH for pip
If found a valid pip executable, invoke it to install GoodTests
otherwise, fail.
'''
didImport = False
try:
import pip
didImport = True
except:
pass
if didImport is True:
print ( "Found pip as module=pip")
res = pip.main(['install', 'GoodTests'])
if res == 0:
return 0
sys.stderr.write('Failed to install GoodTests via pip module. Falling back to pip executable...\n\n')
pipPath = os.path.dirname(sys.executable) + os.sep + 'pip'
print ( 'Searching for pip at "%s"' %(pipPath, ) )
if not os.path.exists(pipPath):
print ( '"%s" does not exist. Scanning PATH to locate a usable pip executable' %(pipPath, ))
pipPath = None
searchResults = findExecutable('pip')
if not searchResults['success']:
sys.stderr.write('Failed to find a usable pip executable in PATH.\n')
return 1 # Failed to locate a usable pip
pipPath = searchResults['path']
print ( 'Found pip executable at "%s"' %(pipPath, ) )
print ( "Executing: %s %s 'install' 'GoodTests'" %(sys.executable, pipPath) )
pipe = subprocess.Popen([sys.executable, pipPath, 'install', 'GoodTests'], shell=False, env=os.environ)
res = pipe.wait()
return res
def download_goodTests(GOODTESTS_URL=None):
'''
download_goodTests - Attempts to download GoodTests, using the default global url (or one provided).
@return <int> - 0 on success (program should continue), otherwise non-zero (program should abort with this exit status)
'''
if GOODTESTS_URL is None:
GOODTESTS_URL = globals()['GOODTESTS_URL']
validAnswer = False
while validAnswer == False:
sys.stdout.write('GoodTests not found. Would you like to install it to local folder? (y/n): ')
sys.stdout.flush()
answer = sys.stdin.readline().strip().lower()
if answer not in ('y', 'n', 'yes', 'no'):
continue
validAnswer = True
answer = answer[0]
if answer == 'n':
sys.stderr.write('Cannot run tests without installing GoodTests. http://pypi.python.org/pypi/GoodTests or https://github.com/kata198/Goodtests\n')
return 1
try:
import urllib2 as urllib
except ImportError:
try:
import urllib.request as urllib
except:
sys.stderr.write('Failed to import urllib. Trying pip.\n')
res = try_pip_install()
if res != 0:
sys.stderr.write('Failed to install GoodTests with pip or direct download. aborting.\n')
return 1
try:
response = urllib.urlopen(GOODTESTS_URL)
contents = response.read()
if str != bytes:
contents = contents.decode('ascii')
except Exception as e:
sys.stderr.write('Failed to download GoodTests.py from "%s"\n%s\n' %(GOODTESTS_URL, str(e)))
sys.stderr.write('\nTrying pip.\n')
res = try_pip_install()
if res != 0:
sys.stderr.write('Failed to install GoodTests with pip or direct download. aborting.\n')
return 1
try:
with open('GoodTests.py', 'w') as f:
f.write(contents)
except Exception as e:
sys.stderr.write('Failed to write to GoodTests.py\n%s\n' %(str(e,)))
return 1
try:
os.chmod('GoodTests.py', 0o775)
except:
sys.stderr.write('WARNING: Failed to chmod +x GoodTests.py, may not be able to be executed.\n')
try:
import GoodTests
except ImportError:
sys.stderr.write('Seemed to download GoodTests okay, but still cannot import. Aborting.\n')
return 1
return 0
def main(thisDir=None, additionalArgs=[], MY_PACKAGE_MODULE=None, ALLOW_SITE_INSTALL=None, MY_TEST_DIRECTORY=None, GOODTESTS_URL=None):
'''
Do the work - Try to find GoodTests.py, else prompt to download it, then run the tests.
@param thisDir <None/str> - None to use default (directory this test file is in, or if not obtainable, current directory).
@param additionalArgs <list> - Any additional args to pass to GoodTests.py
Remainder of params take their global (top of file) defaults unless explicitly set here. See top of file for documentation.
@return <int> - Exit code of application. 0 on success, non-zero on failure.
TODO: Standardize return codes so external applications can derive failure without parsing error strings.
'''
if MY_PACKAGE_MODULE is None:
MY_PACKAGE_MODULE = globals()['MY_PACKAGE_MODULE']
if ALLOW_SITE_INSTALL is None:
ALLOW_SITE_INSTALL = globals()['ALLOW_SITE_INSTALL']
if MY_TEST_DIRECTORY is None:
MY_TEST_DIRECTORY = globals()['MY_TEST_DIRECTORY']
if GOODTESTS_URL is None:
GOODTESTS_URL = globals()['GOODTESTS_URL']
if not thisDir:
thisDir = os.path.dirname(__file__)
if not thisDir:
thisDir = str(os.getcwd())
elif not thisDir.startswith('/'):
thisDir = str(os.getcwd()) + '/' + thisDir
# If GoodTests is in current directory, make sure we find it later
if os.path.exists('./GoodTests.py'):
os.environ['PATH'] = str(os.getcwd()) + ':' + os.environ['PATH']
os.chdir(thisDir)
goodTestsInfo = findGoodTests()
if goodTestsInfo['success'] is False:
downloadRet = download_goodTests(GOODTESTS_URL)
if downloadRet != 0:
return downloadRet
goodTestsInfo = findGoodTests()
if goodTestsInfo['success'] is False:
sys.stderr.write('Could not download or find GoodTests.py. Try to download it yourself using "pip install GoodTests", or wget %s\n' %( GOODTESTS_URL,))
return 1
baseName = os.path.basename(MY_PACKAGE_MODULE)
dirName = os.path.dirname(MY_PACKAGE_MODULE)
newPath = None
if dirName not in ('.', ''):
if dirName.startswith('.'):
dirName = os.getcwd() + os.sep + dirName + os.sep
newPath = dirName
elif dirName == '':
inCurrentDir = False
try:
find_mod(MY_PACKAGE_MODULE)
inCurrentDir = True
except ImportError:
# COMPAT WITH PREVIOUS runTests.py: Try plain module in parent directory
foundIt = False
oldSysPath = sys.path[:]
sys.path = [os.path.realpath(os.getcwd() + os.sep + '..' + os.sep)]
try:
find_mod(MY_PACKAGE_MODULE)
foundIt = True
sys.path = oldSysPath
except ImportError as e:
sys.path = oldSysPath
if not ALLOW_SITE_INSTALL:
sys.stderr.write('Cannot find "%s" locally.\n' %(MY_PACKAGE_MODULE,))
return 2
else:
try:
__import__(baseName)
except:
sys.stderr.write('Cannot find "%s" locally or in global python path.\n' %(MY_PACKAGE_MODULE,))
return 2
if foundIt is True:
newPath = os.path.realpath(os.getcwd() + os.sep + '..' + os.sep)
if inCurrentDir is True:
newPath = os.path.realpath(os.getcwd() + os.sep + '..' + os.sep)
if newPath:
newPythonPath = [newPath] + [x for x in os.environ.get('PYTHONPATH', '').split(':') if x]
os.environ['PYTHONPATH'] = ':'.join(newPythonPath)
sys.path = [newPath] + sys.path
try:
__import__(baseName)
except ImportError as e:
if baseName.endswith(('.py', '.pyc', '.pyo')):
MY_PACKAGE_MODULE = baseName[ : baseName.rindex('.')]
try:
eName = e.name
except AttributeError as noNameE:
# Some platforms python2 does not have this attribute
# so pull it from the message
eName = e.message.split()[-1]
if eName != MY_PACKAGE_MODULE:
sys.stderr.write('Error while importing %s: %s\n Likely this is another dependency that needs to be installed\nPerhaps run "pip install %s" or install the providing package.\n\n' %(eName, str(e), eName))
return 1
sys.stderr.write('Could not import %s. Either install it or otherwise add to PYTHONPATH\n%s\n' %(MY_PACKAGE_MODULE, str(e)))
return 1
if not os.path.isdir(MY_TEST_DIRECTORY):
if not os.path.exists(MY_TEST_DIRECTORY):
sys.stderr.write('Cannot find test directory: %s\n' %(MY_TEST_DIRECTORY,))
else:
sys.stderr.write('Provided test directory, "%s" is not a directory.\n' %(MY_TEST_DIRECTORY,))
return 3
sys.stdout.write('Starting test..\n')
sys.stdout.flush()
sys.stderr.flush()
didTerminate = False
pipe = subprocess.Popen([sys.executable, goodTestsInfo['path']] + additionalArgs + [MY_TEST_DIRECTORY], env=os.environ, shell=False)
while True:
try:
pipe.wait()
break
except KeyboardInterrupt:
if not didTerminate:
pipe.terminate()
didTerminate = True
else:
pipe.kill()
break
return 0
if __name__ == '__main__':
ret = main(None, sys.argv[1:])
sys.exit(ret)