Compare commits

..

No commits in common. "master" and "4.1branch" have entirely different histories.

22 changed files with 520 additions and 1378 deletions

View File

@ -1,46 +1,3 @@
* 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 * 4.1.0 - May 24 2017
- If func_timeout completes the function call in the alloted time, explicitly - If func_timeout completes the function call in the alloted time, explicitly

208
README.md
View File

@ -2,12 +2,10 @@
Python module to support running any existing function with a given timeout. Python module to support running any existing function with a given timeout.
Function Timeout Package Includes
================ ----------------
**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. 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.
@ -27,10 +25,38 @@ This is the function wherein you pass the timeout, the function you want to call
@return - The return value that #func# gives @return - The return value that #func# gives
''' '''
**func\_set\_timeout**
**Example** 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
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:
@ -48,41 +74,6 @@ So, for esxample, if you have a function "doit('arg1', 'arg2')" that you want to
# Handle any exceptions that doit might raise here # 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 How it works
------------ ------------
@ -92,143 +83,16 @@ 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. 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 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 . Find pydoc at https://pythonhosted.org/func_timeout
Support 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. I've tested func\_timeout with python 2.7, 3.4, 3.5, 3.6. It should work on other versions as well.
Works on windows, linux/unix, cygwin, mac Works on windows, linux/unix, cygwin, mac

View File

@ -1,70 +1,45 @@
func\_timeout func_timeout
============= =============
Python module to support running any existing function with a given timeout. Python module to support running any existing function with a given timeout.
Function Timeout Package Includes
================ ----------------
**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. 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 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 timeout <float> - Maximum number of seconds to run #func# before terminating
@param args <tuple> \- Any ordered arguments to pass to the function @param func <function> - The function to call
@param kwargs <dict/None> \- Keyword arguments to pass to the function. @param args <tuple> - Any ordered arguments to pass to the function
@raises \- FunctionTimedOut if #timeout# is exceeded, otherwise anything #func# could raise will be raised @param kwargs <dict/None> - Keyword arguments to pass to the function.
@return \- The return value that #func# gives
@raises - FunctionTimedOut if #timeout# is exceeded, otherwise anything #func# could raise will be raised
@return - The return value that #func# gives
''' '''
**Example** **func_set_timeout**
This is a decorator you can use on functions to apply func_timeout.
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
...
try:
doitReturnValue = func\_timeout(5, doit, args=('arg1', 'arg2'))
except FunctionTimedOut:
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" Takes two arguments, "timeout" and "allowOverride"
@ -73,190 +48,75 @@ If "allowOverride" is present, an optional keyword argument is added to the wrap
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. 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:
**Example:** @func_set_timeout(2.5)
@func\_set\_timeout(2.5)
def myFunction(self, arg1, arg2): def myFunction(self, arg1, arg2):
... ...
FunctionTimedOut **FunctionTimedOut**
----------------
Exception raised if the function times out. Exception raised if the function times out.
Has a "retry" method which takes the following arguments: Has a "retry" method which takes the following arguments:
\* No argument \- Retry same args, same function, same timeout * No argument - Retry same args, same function, same timeout
\* Number argument \- Retry same args, same function, provided timeout * Number argument - Retry same args, same function, provided timeout
\* None \- Retry same args, same function, no timeout * None - Retry same args, same function, no timeout
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:
from func_timeout import func_timeout, FunctionTimedOut
...
try:
doitReturnValue = func_timeout(5, doit, args=('arg1', 'arg2'))
except FunctionTimedOut:
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
How it works 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 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 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 . Find pydoc at https://pythonhosted.org/func_timeout
Support 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. I've tested func_timeout with python 2.7, 3.4, 3.5, 3.6. It should work on other versions as well.
Works on windows, linux/unix, cygwin, mac Works on windows, linux/unix, cygwin, mac
ChangeLog can be found at https://raw.githubusercontent.com/kata198/func_timeout/master/ChangeLog 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 Pydoc can be found at: http://htmlpreview.github.io/?https://github.com/kata198/func_timeout/blob/master/doc/func_timeout.html?vers=1

2
TODO Normal file
View File

@ -0,0 +1,2 @@
Update READMEs

View File

@ -1,174 +1,306 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Python: class StoppableThread</title> <html ><head ><title >Python: module func_timeout.StoppableThread</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head><body bgcolor="#f0f0f8"> </head><body bgcolor="#f0f0f8" >
<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"><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>func_timeout.StoppableThread(group=None,&nbsp;target=None,&nbsp;name=None,&nbsp;args=(),&nbsp;kwargs=None,&nbsp;*,&nbsp;daemon=None)<br>
&nbsp;<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>
&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;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>
&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;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> <table width="100%" cellspacing="0" cellpadding="2" border="0" summary="heading" >
Methods inherited from <a href="threading.html#Thread">threading.Thread</a>:<br> <tr bgcolor="#7799ee" >
<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> <td valign="bottom" >&nbsp;<br />
&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>
*group*&nbsp;should&nbsp;be&nbsp;None;&nbsp;reserved&nbsp;for&nbsp;future&nbsp;extension&nbsp;when&nbsp;a&nbsp;ThreadGroup<br> <p ><tt >Copyright&nbsp;(c)&nbsp;2016,&nbsp;2017&nbsp;Tim&nbsp;Savannah&nbsp;All&nbsp;Rights&nbsp;Reserved.<br />
class&nbsp;is&nbsp;implemented.<br> &nbsp;<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 />
*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> LICENSE,&nbsp;otherwise&nbsp;it&nbsp;is&nbsp;available&nbsp;at&nbsp;https://github.com/kata198/func_timeout/LICENSE</tt></p>
method.&nbsp;Defaults&nbsp;to&nbsp;None,&nbsp;meaning&nbsp;nothing&nbsp;is&nbsp;called.<br> <p >
&nbsp;<br> <table width="100%" cellspacing="0" cellpadding="2" border="0" summary="section" >
*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> <tr bgcolor="#aa55cc" >
the&nbsp;form&nbsp;"Thread-N"&nbsp;where&nbsp;N&nbsp;is&nbsp;a&nbsp;small&nbsp;decimal&nbsp;number.<br> <td colspan="3" valign="bottom" >&nbsp;<br />
&nbsp;<br> <font color="#ffffff" face="helvetica, arial" ><big ><strong >Modules</strong></big></font></td></tr>
*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> <tr ><td bgcolor="#aa55cc" ><tt >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td >&nbsp;</td>
*kwargs*&nbsp;is&nbsp;a&nbsp;dictionary&nbsp;of&nbsp;keyword&nbsp;arguments&nbsp;for&nbsp;the&nbsp;target<br> <td width="100%" ><table width="100%" summary="list" ><tr ><td width="25%" valign="top" ><a href="ctypes.html" >ctypes</a><br />
invocation.&nbsp;Defaults&nbsp;to&nbsp;{}.<br> <a href="os.html" >os</a><br />
&nbsp;<br> </td><td width="25%" valign="top" ><a href="sys.html" >sys</a><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> <a href="threading.html" >threading</a><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> </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>
<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, repeatEvery=2.0)</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="#JoinThread-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="#JoinThread-__init__" >__init__</a>())&nbsp;before&nbsp;doing&nbsp;anything<br />
else&nbsp;to&nbsp;the&nbsp;thread.</tt></dd></dl> 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="JoinThread-run" ><strong >run</strong></a>(self)</dt><dd ><tt >Method&nbsp;representing&nbsp;the&nbsp;thread's&nbsp;activity.<br />
&nbsp;<br />
<dl><dt><a name="StoppableThread-getName"><strong>getName</strong></a>(self)</dt></dl> 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 />
<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> target&nbsp;argument,&nbsp;if&nbsp;any,&nbsp;with&nbsp;sequential&nbsp;and&nbsp;keyword&nbsp;arguments&nbsp;taken<br />
&nbsp;<br>
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="#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="#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="#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="#func_timeout.StoppableThread-join">join</a>()ed&nbsp;many&nbsp;times.<br>
&nbsp;<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="#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> 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> <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="StoppableThread-setName"><strong>setName</strong></a>(self, name)</dt></dl> <dl ><dt ><a name="JoinThread-getName" ><strong >getName</strong></a>(self)</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> <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> &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> 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 />
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> after&nbsp;the&nbsp;<a href="#JoinThread-run" >run</a>()&nbsp;method&nbsp;terminates.&nbsp;The&nbsp;module&nbsp;function&nbsp;enumerate()<br />
&nbsp;<br> returns&nbsp;a&nbsp;list&nbsp;of&nbsp;all&nbsp;alive&nbsp;threads.</tt></dd></dl>
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>
<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> same&nbsp;thread&nbsp;object.</tt></dd></dl>
<hr> <hr />
Data descriptors inherited from <a href="threading.html#Thread">threading.Thread</a>:<br> Data descriptors inherited from <a href="threading.html#Thread" >threading.Thread</a>:<br />
<dl><dt><strong>__dict__</strong></dt> <dl ><dt ><strong >__dict__</strong></dt>
<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd> <dd ><tt >dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
</dl> </dl>
<dl><dt><strong>__weakref__</strong></dt> <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> <dd ><tt >list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
</dl> </dl>
<dl><dt><strong>daemon</strong></dt> <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> <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> &nbsp;<br />
This&nbsp;must&nbsp;be&nbsp;set&nbsp;before&nbsp;start()&nbsp;is&nbsp;called,&nbsp;otherwise&nbsp;RuntimeError&nbsp;is<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> 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> 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> the&nbsp;main&nbsp;thread&nbsp;default&nbsp;to&nbsp;daemon&nbsp;=&nbsp;False.<br />
&nbsp;<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> 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> left.</tt></dd>
</dl> </dl>
<dl><dt><strong>ident</strong></dt> <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> <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> &nbsp;<br />
This&nbsp;is&nbsp;a&nbsp;nonzero&nbsp;integer.&nbsp;See&nbsp;the&nbsp;get_ident()&nbsp;function.&nbsp;Thread<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> 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> 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>
<dl><dt><strong>name</strong></dt> <dl ><dt ><strong >name</strong></dt>
<dd><tt>A&nbsp;string&nbsp;used&nbsp;for&nbsp;identification&nbsp;purposes&nbsp;only.<br> <dd ><tt >A&nbsp;string&nbsp;used&nbsp;for&nbsp;identification&nbsp;purposes&nbsp;only.<br />
&nbsp;<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> 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> initial&nbsp;name&nbsp;is&nbsp;set&nbsp;by&nbsp;the&nbsp;constructor.</tt></dd>
</dl> </dl>
</td></tr></table> </td></tr></table> <p >
</body></html> <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>
<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 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> = 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="#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-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-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 />
&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;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></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 >__all__</strong> = ('StoppableThread', 'JoinThread')</td></tr></table>
</p></p></p></body></html>

View File

@ -38,34 +38,34 @@ LICENSE,&nbsp;otherwise&nbsp;it&nbsp;is&nbsp;available&nbsp;at&nbsp;https://gith
&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;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;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;&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;<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;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;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&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;much&nbsp;higher&nbsp;timeout&nbsp;than&nbsp;seven&nbsp;elements.)<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;much&nbsp;higher&nbsp;timeout&nbsp;than&nbsp;seven&nbsp;elements.)<br />
&nbsp;<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;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;&nbsp;&nbsp;&nbsp;&nbsp;will&nbsp;be&nbsp;used&nbsp;for&nbsp;that&nbsp;single&nbsp;call.<br />
&nbsp;<br /> &nbsp;<br />
@param&nbsp;timeout&nbsp;&lt;float&nbsp;OR&nbsp;lambda/function&gt;&nbsp;-<br /> @param&nbsp;timeout&nbsp;&lt;float&nbsp;OR&nbsp;lambda/function&gt;&nbsp;-&nbsp;<br />
&nbsp;<br /> &nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;**If&nbsp;float:**<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;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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;before&nbsp;throwing&nbsp;FunctionTimedOut<br />
&nbsp;<br /> &nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;**If&nbsp;lambda/function:<br /> &nbsp;&nbsp;&nbsp;&nbsp;**If&nbsp;lambda/function:<br />
&nbsp;<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;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;invocation&nbsp;of&nbsp;the&nbsp;decorated&nbsp;function&nbsp;(unless&nbsp;#allowOverride=True&nbsp;and&nbsp;"forceTimeout"&nbsp;was&nbsp;passed)&nbsp;<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;&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;<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;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;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;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;&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;<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;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;&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;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;or&nbsp;lambda&nbsp;like:<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;or&nbsp;lambda&nbsp;like:<br />
&nbsp;<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;&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 />

View File

@ -33,9 +33,7 @@ LICENSE,&nbsp;otherwise&nbsp;it&nbsp;is&nbsp;available&nbsp;at&nbsp;https://gith
<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> <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> <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 /> <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;<br />
<a href="#FunctionTimedOut" >FunctionTimedOut</a>&nbsp;-&nbsp;Exception&nbsp;raised&nbsp;when&nbsp;a&nbsp;function&nbsp;times&nbsp;out<br />
&nbsp;<br /> &nbsp;<br />
@property&nbsp;timedOutAfter&nbsp;-&nbsp;Number&nbsp;of&nbsp;seconds&nbsp;before&nbsp;timeout&nbsp;was&nbsp;triggered<br /> @property&nbsp;timedOutAfter&nbsp;-&nbsp;Number&nbsp;of&nbsp;seconds&nbsp;before&nbsp;timeout&nbsp;was&nbsp;triggered<br />
&nbsp;<br /> &nbsp;<br />
@ -53,19 +51,7 @@ LICENSE,&nbsp;otherwise&nbsp;it&nbsp;is&nbsp;available&nbsp;at&nbsp;https://gith
</dl> </dl>
<hr /> <hr />
Methods defined here:<br /> 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 /> <dl ><dt ><a name="FunctionTimedOut-__init__" ><strong >__init__</strong></a>(self, msg='', timedOutAfter=None, timedOutFunction=None, timedOutArgs=None, timedOutKwargs=None)</dt><dd ><tt >Initialize&nbsp;self.&nbsp;&nbsp;See&nbsp;help(type(self))&nbsp;for&nbsp;accurate&nbsp;signature.</tt></dd></dl>
&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 /> <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 /> &nbsp;<br />
@ -74,7 +60,7 @@ Methods defined here:<br />
<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 /> <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 /> &nbsp;<br />
@param&nbsp;timeout&nbsp;&lt;float/RETRY_SAME_TIMEOUT/None&gt;&nbsp;Default&nbsp;RETRY_SAME_TIMEOUT<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;<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;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;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;&nbsp;&nbsp;&nbsp;If&nbsp;None&nbsp;:&nbsp;Will&nbsp;retry&nbsp;function&nbsp;same&nbsp;args&nbsp;no&nbsp;timeout<br />
@ -92,7 +78,9 @@ Methods inherited from <a href="builtins.html#BaseException" >builtins.BaseExcep
<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-__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-__reduce__" ><strong >__reduce__</strong></a>(...)</dt><dd ><tt >helper&nbsp;for&nbsp;pickle</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-__repr__" ><strong >__repr__</strong></a>(self, /)</dt><dd ><tt >Return&nbsp;repr(self).</tt></dd></dl>
@ -105,10 +93,6 @@ Methods inherited from <a href="builtins.html#BaseException" >builtins.BaseExcep
<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 /> <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> set&nbsp;self.<strong >__traceback__</strong>&nbsp;to&nbsp;tb&nbsp;and&nbsp;return&nbsp;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>
<hr /> <hr />
Data descriptors inherited from <a href="builtins.html#BaseException" >builtins.BaseException</a>:<br /> Data descriptors inherited from <a href="builtins.html#BaseException" >builtins.BaseException</a>:<br />
<dl ><dt ><strong >__cause__</strong></dt> <dl ><dt ><strong >__cause__</strong></dt>

View File

@ -6,8 +6,8 @@
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="heading" > <table width="100%" cellspacing="0" cellpadding="2" border="0" summary="heading" >
<tr bgcolor="#7799ee" > <tr bgcolor="#7799ee" >
<td valign="bottom" >&nbsp;<br /> <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> <font color="#ffffff" face="helvetica, arial" >&nbsp;<br /><big ><big ><strong >func_timeout</strong></big></big> (version 4.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;2017,&nbsp;2019&nbsp;Tim&nbsp;Savannah&nbsp;All&nbsp;Rights&nbsp;Reserved.<br /> <p ><tt >Copyright&nbsp;(c)&nbsp;2016,&nbsp;2017&nbsp;Tim&nbsp;Savannah&nbsp;All&nbsp;Rights&nbsp;Reserved.<br />
&nbsp;<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 /> 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> LICENSE,&nbsp;otherwise&nbsp;it&nbsp;is&nbsp;available&nbsp;at&nbsp;https://github.com/kata198/func_timeout/LICENSE</tt></p>
@ -37,12 +37,6 @@ LICENSE,&nbsp;otherwise&nbsp;it&nbsp;is&nbsp;available&nbsp;at&nbsp;https://gith
<dt ><font face="helvetica, arial" ><a href="func_timeout.exceptions.html#FunctionTimedOut" >func_timeout.exceptions.FunctionTimedOut</a> <dt ><font face="helvetica, arial" ><a href="func_timeout.exceptions.html#FunctionTimedOut" >func_timeout.exceptions.FunctionTimedOut</a>
</font></dt></dl> </font></dt></dl>
</dd> </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> </dl>
<p > <p >
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="section" > <table width="100%" cellspacing="0" cellpadding="2" border="0" summary="section" >
@ -51,9 +45,7 @@ LICENSE,&nbsp;otherwise&nbsp;it&nbsp;is&nbsp;available&nbsp;at&nbsp;https://gith
<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> <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> <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 /> <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;<br />
<a href="#FunctionTimedOut" >FunctionTimedOut</a>&nbsp;-&nbsp;Exception&nbsp;raised&nbsp;when&nbsp;a&nbsp;function&nbsp;times&nbsp;out<br />
&nbsp;<br /> &nbsp;<br />
@property&nbsp;timedOutAfter&nbsp;-&nbsp;Number&nbsp;of&nbsp;seconds&nbsp;before&nbsp;timeout&nbsp;was&nbsp;triggered<br /> @property&nbsp;timedOutAfter&nbsp;-&nbsp;Number&nbsp;of&nbsp;seconds&nbsp;before&nbsp;timeout&nbsp;was&nbsp;triggered<br />
&nbsp;<br /> &nbsp;<br />
@ -71,19 +63,7 @@ LICENSE,&nbsp;otherwise&nbsp;it&nbsp;is&nbsp;available&nbsp;at&nbsp;https://gith
</dl> </dl>
<hr /> <hr />
Methods defined here:<br /> 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 /> <dl ><dt ><a name="FunctionTimedOut-__init__" ><strong >__init__</strong></a>(self, msg='', timedOutAfter=None, timedOutFunction=None, timedOutArgs=None, timedOutKwargs=None)</dt><dd ><tt >Initialize&nbsp;self.&nbsp;&nbsp;See&nbsp;help(type(self))&nbsp;for&nbsp;accurate&nbsp;signature.</tt></dd></dl>
&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 /> <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 /> &nbsp;<br />
@ -92,7 +72,7 @@ Methods defined here:<br />
<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 /> <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 /> &nbsp;<br />
@param&nbsp;timeout&nbsp;&lt;float/RETRY_SAME_TIMEOUT/None&gt;&nbsp;Default&nbsp;RETRY_SAME_TIMEOUT<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;<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;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;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;&nbsp;&nbsp;&nbsp;If&nbsp;None&nbsp;:&nbsp;Will&nbsp;retry&nbsp;function&nbsp;same&nbsp;args&nbsp;no&nbsp;timeout<br />
@ -110,7 +90,9 @@ Methods inherited from <a href="builtins.html#BaseException" >builtins.BaseExcep
<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-__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-__reduce__" ><strong >__reduce__</strong></a>(...)</dt><dd ><tt >helper&nbsp;for&nbsp;pickle</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-__repr__" ><strong >__repr__</strong></a>(self, /)</dt><dd ><tt >Return&nbsp;repr(self).</tt></dd></dl>
@ -123,10 +105,6 @@ Methods inherited from <a href="builtins.html#BaseException" >builtins.BaseExcep
<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 /> <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> set&nbsp;self.<strong >__traceback__</strong>&nbsp;to&nbsp;tb&nbsp;and&nbsp;return&nbsp;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>
<hr /> <hr />
Data descriptors inherited from <a href="builtins.html#BaseException" >builtins.BaseException</a>:<br /> Data descriptors inherited from <a href="builtins.html#BaseException" >builtins.BaseException</a>:<br />
<dl ><dt ><strong >__cause__</strong></dt> <dl ><dt ><strong >__cause__</strong></dt>
@ -143,175 +121,7 @@ Data descriptors inherited from <a href="builtins.html#BaseException" >builtins.
</dl> </dl>
<dl ><dt ><strong >args</strong></dt> <dl ><dt ><strong >args</strong></dt>
</dl> </dl>
</td></tr></table> <p > </td></tr></table></p></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>(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" > <table width="100%" cellspacing="0" cellpadding="2" border="0" summary="section" >
<tr bgcolor="#eeaa77" > <tr bgcolor="#eeaa77" >
<td colspan="3" valign="bottom" >&nbsp;<br /> <td colspan="3" valign="bottom" >&nbsp;<br />
@ -325,34 +135,34 @@ initial&nbsp;name&nbsp;is&nbsp;set&nbsp;by&nbsp;the&nbsp;constructor.</tt></dd>
&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;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;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;&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;<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;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;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&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;much&nbsp;higher&nbsp;timeout&nbsp;than&nbsp;seven&nbsp;elements.)<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;much&nbsp;higher&nbsp;timeout&nbsp;than&nbsp;seven&nbsp;elements.)<br />
&nbsp;<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;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;&nbsp;&nbsp;&nbsp;&nbsp;will&nbsp;be&nbsp;used&nbsp;for&nbsp;that&nbsp;single&nbsp;call.<br />
&nbsp;<br /> &nbsp;<br />
@param&nbsp;timeout&nbsp;&lt;float&nbsp;OR&nbsp;lambda/function&gt;&nbsp;-<br /> @param&nbsp;timeout&nbsp;&lt;float&nbsp;OR&nbsp;lambda/function&gt;&nbsp;-&nbsp;<br />
&nbsp;<br /> &nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;**If&nbsp;float:**<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;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;&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;<br />
&nbsp;&nbsp;&nbsp;&nbsp;**If&nbsp;lambda/function:<br /> &nbsp;&nbsp;&nbsp;&nbsp;**If&nbsp;lambda/function:<br />
&nbsp;<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;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;invocation&nbsp;of&nbsp;the&nbsp;decorated&nbsp;function&nbsp;(unless&nbsp;#allowOverride=True&nbsp;and&nbsp;"forceTimeout"&nbsp;was&nbsp;passed)&nbsp;<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;&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;<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;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;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;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;&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;<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;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;&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;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;or&nbsp;lambda&nbsp;like:<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;or&nbsp;lambda&nbsp;like:<br />
&nbsp;<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;&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 />
@ -394,6 +204,6 @@ to&nbsp;return&nbsp;cleanly,&nbsp;but&nbsp;in&nbsp;most&nbsp;cases&nbsp;it&nbsp;
<font color="#ffffff" face="helvetica, arial" ><big ><strong >Data</strong></big></font></td></tr> <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> <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 /> <td width="100%" ><strong >__all__</strong> = ('func_timeout', 'func_set_timeout', 'FunctionTimedOut')<br />
<strong >__version_tuple__</strong> = (4, 3, 5)</td></tr></table> <strong >__version_tuple__</strong> = (4, 1, 0)</td></tr></table>
</p></p></p></p></body></html> </p></p></p></p></body></html>

View File

@ -1,20 +1,23 @@
<!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" > <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<tr bgcolor="#7799ee" > <html><head><title>Python: module func_timeout.py2_raise</title>
<td valign="bottom" >&nbsp;<br /> <meta charset="utf-8">
<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> </head><body bgcolor="#f0f0f8">
<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="heading">
<table width="100%" cellspacing="0" cellpadding="2" border="0" summary="section" > <tr bgcolor="#7799ee">
<tr bgcolor="#eeaa77" > <td valign=bottom>&nbsp;<br>
<td colspan="3" 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
<font color="#ffffff" face="helvetica, arial" ><big ><strong >Functions</strong></big></font></td></tr> ><td align=right valign=bottom
><font color="#ffffff" face="helvetica, arial"><a href="func_timeout.html">index</a><br></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> <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 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> </td></tr></table>
</p></body></html> </body></html>

View File

@ -1,5 +1,5 @@
''' '''
Copyright (c) 2016, 2017, 2019 Timothy 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 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 LICENSE, otherwise it is available at https://github.com/kata198/func_timeout/LICENSE
@ -8,101 +8,43 @@
import os import os
import ctypes import ctypes
import threading import threading
import time
import sys
__all__ = ('StoppableThread', 'JoinThread') __all__ = ('StoppableThread', 'JoinThread')
class StoppableThread(threading.Thread): class StoppableThread(threading.Thread):
''' '''
StoppableThread - A thread that can be stopped by forcing an exception in the execution context. 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, raiseEvery=2.0): def _stopThread(self, exception):
''' if self.isAlive() is False:
_stopThread - @see StoppableThread.stop
'''
if self.is_alive() is False:
return True return True
self._stderr = open(os.devnull, 'w') 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._stderr = self._stderr
joinThread.start() joinThread.start()
joinThread._stderr = self._stderr joinThread._stderr = self._stderr
def stop(self, exception):
def stop(self, exception, raiseEvery=2.0):
''' '''
Stops the thread by raising a given exception. Stops the thread by raising a given exception.
@param exception <Exception type> - Exception to throw. Likely, you want to use something @param exception <Exception> - Exception to throw. Likely, you want to use something
that inherits from BaseException (so except Exception as e: continue; isn't a problem) 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) return self._stopThread(exception)
class JoinThread(threading.Thread): 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, repeatEvery=2.0): 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) threading.Thread.__init__(self)
self.otherThread = otherThread self.otherThread = otherThread
self.exception = exception self.exception = exception
@ -110,9 +52,6 @@ class JoinThread(threading.Thread):
self.daemon = True self.daemon = True
def run(self): def run(self):
'''
run - The thread main. Will attempt to stop and join the attached thread.
'''
# Try to silence default exception printing. # Try to silence default exception printing.
self.otherThread._Thread__stderr = self._stderr self.otherThread._Thread__stderr = self._stderr
@ -120,7 +59,7 @@ class JoinThread(threading.Thread):
# If py2, call this first to start thread termination cleanly. # If py2, call this first to start thread termination cleanly.
# Python3 does not need such ( nor does it provide.. ) # Python3 does not need such ( nor does it provide.. )
self.otherThread._Thread__stop() self.otherThread._Thread__stop()
while self.otherThread.is_alive(): while self.otherThread.isAlive():
# We loop raising exception incase it's caught hopefully this breaks us far out. # 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)) ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(self.otherThread.ident), ctypes.py_object(self.exception))
self.otherThread.join(self.repeatEvery) self.otherThread.join(self.repeatEvery)
@ -130,4 +69,4 @@ class JoinThread(threading.Thread):
except: except:
pass pass
# vim: set ts=4 sw=4 expandtab :

View File

@ -1,16 +1,15 @@
''' '''
Copyright (c) 2016, 2017, 2019 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 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 LICENSE, otherwise it is available at https://github.com/kata198/func_timeout/LICENSE
''' '''
__version__ = '4.3.5' __version__ = '4.1.0'
__version_tuple__ = (4, 3, 5) __version_tuple__ = (4, 1, 0)
__all__ = ('func_timeout', 'func_set_timeout', 'FunctionTimedOut', 'StoppableThread') __all__ = ('func_timeout', 'func_set_timeout', 'FunctionTimedOut')
from .exceptions import FunctionTimedOut from .exceptions import FunctionTimedOut
from .dafunc import func_timeout, func_set_timeout from .dafunc import func_timeout, func_set_timeout
from .StoppableThread import StoppableThread

View File

@ -25,8 +25,6 @@ except SyntaxError:
except ImportError: except ImportError:
from .py2_raise import raise_exception from .py2_raise import raise_exception
from functools import wraps
__all__ = ('func_timeout', 'func_set_timeout') __all__ = ('func_timeout', 'func_set_timeout')
@ -74,7 +72,7 @@ def func_timeout(timeout, func, args=(), kwargs=None):
if isStopped is False: if isStopped is False:
# Assemble the alternate traceback, excluding this function # Assemble the alternate traceback, excluding this function
# from the trace (by going to next frame) # from the trace (by going to next frame)
# Pytohn3 reads native from __traceback__, # Pytohn3 reads native from __traceback__,
# python2 has a different form for "raise" # python2 has a different form for "raise"
e.__traceback__ = exc_info[2].tb_next e.__traceback__ = exc_info[2].tb_next
exception.append( e ) exception.append( e )
@ -86,7 +84,7 @@ def func_timeout(timeout, func, args=(), kwargs=None):
thread.join(timeout) thread.join(timeout)
stopException = None stopException = None
if thread.is_alive(): if thread.isAlive():
isStopped = True isStopped = True
class FunctionTimedOutTempType(FunctionTimedOut): class FunctionTimedOutTempType(FunctionTimedOut):
@ -120,34 +118,34 @@ def func_set_timeout(timeout, allowOverride=False):
If #timeout is provided as a lambda/function, it will be called 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 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 that call, based on the arguments passed to the decorated function.
For example, you may have a "processData" function whose execution time 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 depends on the number of "data" elements, so you may want a million elements to have a
much higher timeout than seven elements.) much higher timeout than seven elements.)
If #allowOverride is True AND a kwarg of "forceTimeout" is passed to the wrapped function, that timeout If #allowOverride is True AND a kwarg of "forceTimeout" is passed to the wrapped function, that timeout
will be used for that single call. will be used for that single call.
@param timeout <float OR lambda/function> - @param timeout <float OR lambda/function> -
**If float:** **If float:**
Default number of seconds max to allow function to execute Default number of seconds max to allow function to execute
before throwing FunctionTimedOut before throwing FunctionTimedOut
**If lambda/function: **If lambda/function:
If a function/lambda is provided, it will be called for every If a function/lambda is provided, it will be called for every
invocation of the decorated function (unless #allowOverride=True and "forceTimeout" was passed) 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. 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. 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 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), if you prefer to get the *args (list of ordered args) and **kwargs ( key : value keyword args form),
define your calculate function like: define your calculate function like:
def calculateTimeout(*args, **kwargs): def calculateTimeout(*args, **kwargs):
... ...
or lambda like: or lambda like:
calculateTimeout = lambda *args, **kwargs : ... calculateTimeout = lambda *args, **kwargs : ...
@ -182,7 +180,7 @@ def func_set_timeout(timeout, allowOverride=False):
# Only defaultTimeout provided. Simple function wrapper # Only defaultTimeout provided. Simple function wrapper
def _function_decorator(func): def _function_decorator(func):
return wraps(func)(lambda *args, **kwargs : func_timeout(defaultTimeout, func, args=args, kwargs=kwargs)) return lambda *args, **kwargs : func_timeout(defaultTimeout, func, args=args, kwargs=kwargs)
# def _function_wrapper(*args, **kwargs): # def _function_wrapper(*args, **kwargs):
# return func_timeout(defaultTimeout, func, args=args, kwargs=kwargs) # return func_timeout(defaultTimeout, func, args=args, kwargs=kwargs)
@ -200,7 +198,7 @@ def func_set_timeout(timeout, allowOverride=False):
return func_timeout(useTimeout, func, args=args, kwargs=kwargs) return func_timeout(useTimeout, func, args=args, kwargs=kwargs)
return wraps(func)(_function_wrapper) return _function_wrapper
return _function_decorator return _function_decorator
@ -219,7 +217,7 @@ def func_set_timeout(timeout, allowOverride=False):
return func_timeout(useTimeout, func, args=args, kwargs=kwargs) return func_timeout(useTimeout, func, args=args, kwargs=kwargs)
return wraps(func)(_function_wrapper) return _function_wrapper
return _function_decorator return _function_decorator
# Cannot override, and calculate timeout function # Cannot override, and calculate timeout function
@ -229,7 +227,7 @@ def func_set_timeout(timeout, allowOverride=False):
return func_timeout(useTimeout, func, args=args, kwargs=kwargs) return func_timeout(useTimeout, func, args=args, kwargs=kwargs)
return wraps(func)(_function_wrapper) return _function_wrapper
return _function_decorator return _function_decorator

View File

@ -1,5 +1,5 @@
''' '''
Copyright (c) 2016, 2017, 2019 Tim Savannah All Rights Reserved. Copyright (c) 2016 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 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 LICENSE, otherwise it is available at https://github.com/kata198/func_timeout/LICENSE
@ -25,22 +25,6 @@ class FunctionTimedOut(BaseException):
def __init__(self, msg='', timedOutAfter=None, timedOutFunction=None, timedOutArgs=None, timedOutKwargs=None): 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.timedOutAfter = timedOutAfter
@ -62,25 +46,14 @@ class FunctionTimedOut(BaseException):
@return <str> - Message @return <str> - Message
''' '''
# Try to gather the function name, if available. return 'Function %s (args=%s) (kwargs=%s) timed out after %f seconds.\n' %(self.timedOutFunction.__name__, repr(self.timedOutArgs), repr(self.timedOutKwargs), self.timedOutAfter)
# 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): def retry(self, timeout=RETRY_SAME_TIMEOUT):
''' '''
retry - Retry the timed-out function with same arguments. retry - Retry the timed-out function with same arguments.
@param timeout <float/RETRY_SAME_TIMEOUT/None> Default RETRY_SAME_TIMEOUT @param timeout <float/RETRY_SAME_TIMEOUT/None> Default RETRY_SAME_TIMEOUT
If RETRY_SAME_TIMEOUT : Will retry the function same args, 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 a float/int : Will retry the function same args with provided timeout
If None : Will retry function same args no timeout If None : Will retry function same args no timeout
@ -89,7 +62,7 @@ class FunctionTimedOut(BaseException):
''' '''
if timeout is None: if timeout is None:
return self.timedOutFunction(*(self.timedOutArgs), **self.timedOutKwargs) return self.timedOutFunction(*(self.timedOutArgs), **self.timedOutKwargs)
from .dafunc import func_timeout from .dafunc import func_timeout
if timeout == RETRY_SAME_TIMEOUT: if timeout == RETRY_SAME_TIMEOUT:

View File

@ -1,13 +1,9 @@
#!/bin/bash #!/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' ' ')" 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} pydoc -w ${ALL_MODS}
mv func_timeout*.html doc/ mv *.html doc/
pushd doc >/dev/null 2>&1 pushd doc >/dev/null 2>&1
rm -f index.html rm -f index.html

View File

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

View File

@ -1,9 +1,4 @@
#!/usr/bin/env python #!/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 from func_timeout import func_timeout, FunctionTimedOut
import time import time
@ -28,7 +23,6 @@ if __name__ == '__main__':
myException = e myException = e
pass pass
print ( "\nRetrying with longer timeout, should get 16+17=33:" )
if myException is not None: if myException is not None:
print ( "\nGot: %s\n" %( str(myException.retry(2.5)), ) ) print ( "\nGot: %s\n" %( str(myException.retry(2.5)), ) )
else: else:

View File

@ -160,7 +160,6 @@ def compareTimes(timeEnd, timeStart, cmpTime, roundTo=None, deltaFixed=.05, delt
@param roundTo <None/int> - Number of digits to round-off to @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 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% @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, Example: if trying to determine if function ran for 2 seconds with an error of .05 seconds,

View File

@ -25,7 +25,7 @@ class TestBasic(object):
''' '''
def test_funcTimeout(self): def test_funcTimeout(self):
sleepFunction = getSleepLambda(2.00) sleepFunction = getSleepLambda(1.25)
expectedResult = 5 + 13 expectedResult = 5 + 13
@ -36,9 +36,9 @@ class TestBasic(object):
assert result == expectedResult , 'Did not get return from sleepFunction' assert result == expectedResult , 'Did not get return from sleepFunction'
try: try:
result = func_timeout(2.5, sleepFunction, args=(5, 13)) result = func_timeout(1.5, sleepFunction, args=(5, 13))
except FunctionTimedOut as te: except FunctionTimedOut as te:
raise AssertionError('Got unexpected timeout at 2.5 second timeout for 2.00 second function: %s' %(str(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)) assert result == expectedResult , 'Got wrong return from func_timeout.\nGot: %s\nExpected: %s\n' %(repr(result), repr(expectedResult))
@ -51,16 +51,16 @@ class TestBasic(object):
assert gotException , 'Expected to get FunctionTimedOut exception for 1.25 sec function at 1s timeout' assert gotException , 'Expected to get FunctionTimedOut exception for 1.25 sec function at 1s timeout'
try: try:
result = func_timeout(2.5, sleepFunction, args=(5,), kwargs={ 'b' : 13}) result = func_timeout(1.5, sleepFunction, args=(5,), kwargs={ 'b' : 13})
except FunctionTimedOut as te: except FunctionTimedOut as te:
raise AssertionError('Got unexpected timeout at 2.5 second timeout for 2.00 second function: %s' %(str(te), )) raise AssertionError('Got unexpected timeout at 1.5 second timeout for 1.25 second function: %s' %(str(te), ))
except Exception as e: except Exception as e:
raise AssertionError('Got unknown exception mixing args and kwargs: < %s > %s' %(e.__class__.__name__, str(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' assert result == expectedResult , 'Got wrong result when mixing args and kwargs'
def test_retry(self): def test_retry(self):
sleepFunction = getSleepLambda(1.2) sleepFunction = getSleepLambda(.5)
expectedResult = 5 + 19 expectedResult = 5 + 19
@ -69,14 +69,14 @@ class TestBasic(object):
startTime = time.time() startTime = time.time()
try: try:
result = func_timeout(.8, sleepFunction, args=(5, 19)) result = func_timeout(.3, sleepFunction, args=(5, 19))
except FunctionTimedOut as fte: except FunctionTimedOut as fte:
functionTimedOut = fte functionTimedOut = fte
gotException = True gotException = True
endTime = time.time() endTime = time.time()
assert gotException , 'Expected to get exception' 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)) assert compareTimes(endTime, startTime, .3, 3, None, .10) == 0 , 'Expected to wait .3 seconds. Was: %f - %f = %f' %(endTime, startTime, round(endTime - startTime, 3))
gotException = False gotException = False
startTime = time.time() startTime = time.time()
@ -87,7 +87,7 @@ class TestBasic(object):
endTime = time.time() endTime = time.time()
assert gotException , 'Expected to get exception on retry.' 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' assert compareTimes(endTime, startTime, .3, 3, None, .10) == 0 , 'Expected retry with no arguments to use same timeout of .3'
gotException = False gotException = False
startTime = time.time() startTime = time.time()
@ -98,19 +98,19 @@ class TestBasic(object):
endTime = time.time() endTime = time.time()
assert not gotException , 'Did NOT to get exception with no timeout' 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' assert compareTimes(endTime, startTime, .5, 3, None, .10) == 0 , 'Expected retry with None as timeout to last full length of function'
gotException = False gotException = False
startTime = time.time() startTime = time.time()
try: try:
result = functionTimedOut.retry(.55) result = functionTimedOut.retry(.4)
except FunctionTimedOut: except FunctionTimedOut:
gotException = True gotException = True
finally: finally:
endTime = time.time() endTime = time.time()
assert gotException , 'Expected to time out after .55 seconds when providing .55' assert gotException , 'Expected to time out after .4 seconds when providing .4'
assert compareTimes(endTime, startTime, .55, 3, deltaFixed=.15) == 0 , 'Expected providing .55 would allow timeout of up to .55 seconds' assert compareTimes(endTime, startTime, .4, 3, .05, None) == 0 , 'Expected providing .4 would allow timeout of up to .4 seconds'
threadsCleanedUp = False threadsCleanedUp = False
@ -122,11 +122,11 @@ class TestBasic(object):
threadsCleanedUp = True threadsCleanedUp = True
break break
assert threadsCleanedUp , 'Expected other threads to get cleaned up after gc collection' assert threadsCleanedUp , 'Expected other threads to get cleaned up after gc collection'
def test_exception(self): def test_exception(self):
sleepFunction = getSleepLambda(.85) sleepFunction = getSleepLambda(.5)
expectedResult = 5 + 19 expectedResult = 5 + 19
@ -135,7 +135,7 @@ class TestBasic(object):
startTime = time.time() startTime = time.time()
try: try:
result = func_timeout(.5, sleepFunction, args=(5, 19)) result = func_timeout(.3, sleepFunction, args=(5, 19))
except FunctionTimedOut as fte: except FunctionTimedOut as fte:
functionTimedOut = fte functionTimedOut = fte
gotException = True gotException = True
@ -144,43 +144,14 @@ class TestBasic(object):
assert gotException , 'Expected to get exception' assert gotException , 'Expected to get exception'
assert 'timed out after ' in functionTimedOut.msg , 'Expected message to be constructed. Got: %s' %(repr(functionTimedOut.msg), ) 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 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.timedOutFunction == sleepFunction , 'Expected timedOutFunction to equal sleepFunction'
assert functionTimedOut.timedOutArgs == (5, 19) , 'Expected args to equal (5, 19)' assert functionTimedOut.timedOutArgs == (5, 19) , 'Expected args to equal (5, 19)'
assert functionTimedOut.timedOutKwargs == {} , 'Expected timedOutKwargs to equal {}' 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__': 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()) 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())

View File

@ -19,7 +19,7 @@ from func_timeout import func_timeout, FunctionTimedOut, func_set_timeout
from TestUtils import ARG_NO_DEFAULT, getSleepLambda, getSleepLambdaWithArgs, compareTimes from TestUtils import ARG_NO_DEFAULT, getSleepLambda, getSleepLambdaWithArgs, compareTimes
SLEEP_TIME = 1.25 SLEEP_TIME = .5
def doSleep(a, b): def doSleep(a, b):
time.sleep(a) time.sleep(a)
@ -52,7 +52,7 @@ class TestDecorator(object):
endTime = time.time() endTime = time.time()
assert gotException , 'Expected to get exception at sleep 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' assert compareTimes(endTime, startTime, SLEEP_TIME, None, .1) == 0 , 'Expected to sleep up to sleep time'
expected = SLEEP_TIME * .8 + 4 expected = SLEEP_TIME * .8 + 4
gotException = False gotException = False
@ -64,7 +64,7 @@ class TestDecorator(object):
endTime = time.time() endTime = time.time()
assert not gotException , 'Expected not to get exception at 80% sleep 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 compareTimes(endTime, startTime, SLEEP_TIME * .8, None, .1) == 0 , 'Expected to only sleep for 80% of sleep time'
assert result == expected , 'Got wrong result' assert result == expected , 'Got wrong result'
def test_funcSetTimeoutOverride(self): def test_funcSetTimeoutOverride(self):
@ -85,7 +85,7 @@ class TestDecorator(object):
endTime = time.time() endTime = time.time()
assert gotException , 'Expected to get exception at 130% sleep 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' assert compareTimes(endTime, startTime, SLEEP_TIME * 1.2, None, .1) == 0 , 'Expected to sleep up to 120% of sleep time'
@func_set_timeout(SLEEP_TIME, allowOverride=False) @func_set_timeout(SLEEP_TIME, allowOverride=False)
def doSleepFuncNoOverride(a, b): def doSleepFuncNoOverride(a, b):
@ -113,7 +113,7 @@ class TestDecorator(object):
endTime = time.time() endTime = time.time()
assert not gotException , 'Expected not to get exception with forced 115% sleep 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 compareTimes(endTime, startTime, SLEEP_TIME, None, .1) == 0 , 'Expected to sleep for SLEEP_TIME'
assert result == expected , 'Got wrong result' assert result == expected , 'Got wrong result'
def test_funcSetTimeCalculate(self): def test_funcSetTimeCalculate(self):
@ -145,7 +145,7 @@ class TestDecorator(object):
endTime = time.time() endTime = time.time()
assert not gotException , 'Expected not to get exception with calculated 120% timeout on sleep 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 compareTimes(endTime, startTime, SLEEP_TIME, None, .1) == 0 , 'Expected to sleep for SLEEP_TIME'
assert result == expected , 'Got wrong result' assert result == expected , 'Got wrong result'
@ -164,7 +164,7 @@ class TestDecorator(object):
endTime = time.time() endTime = time.time()
assert gotException , 'Expected to get exception with calculated 80% timeout on sleep 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' assert compareTimes(endTime, startTime, SLEEP_TIME * .8, None, .1) == 0 , 'Expected to sleep for 80% SLEEP_TIME'
@func_set_timeout(calculateSleepOverArgs, allowOverride=False) @func_set_timeout(calculateSleepOverArgs, allowOverride=False)
def doSleepFuncOverArgs(a, b): def doSleepFuncOverArgs(a, b):
@ -181,7 +181,7 @@ class TestDecorator(object):
endTime = time.time() endTime = time.time()
assert not gotException , 'Expected not to get exception with calculated 120% timeout on sleep time using *args' 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 compareTimes(endTime, startTime, SLEEP_TIME, None, .1) == 0 , 'Expected to sleep for SLEEP_TIME using *args'
assert result == expected , 'Got wrong result' assert result == expected , 'Got wrong result'
@func_set_timeout(calculateSleepUnderArgs, allowOverride=False) @func_set_timeout(calculateSleepUnderArgs, allowOverride=False)
@ -199,7 +199,7 @@ class TestDecorator(object):
endTime = time.time() endTime = time.time()
assert gotException , 'Expected to get exception with calculated 80% timeout on sleep time using *args' 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' assert compareTimes(endTime, startTime, SLEEP_TIME * .8, None, .1) == 0 , 'Expected to sleep for 80% SLEEP_TIME using *args'
def test_funcSetTimeCalculateWithOverride(self): def test_funcSetTimeCalculateWithOverride(self):
@ -231,7 +231,7 @@ class TestDecorator(object):
endTime = time.time() endTime = time.time()
assert not gotException , 'Expected not to get exception with calculated 120% timeout on sleep 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 compareTimes(endTime, startTime, SLEEP_TIME, None, .1) == 0 , 'Expected to sleep for SLEEP_TIME'
assert result == expected , 'Got wrong result' assert result == expected , 'Got wrong result'
expected = SLEEP_TIME + 4 expected = SLEEP_TIME + 4
@ -244,7 +244,7 @@ class TestDecorator(object):
endTime = time.time() endTime = time.time()
assert not gotException , 'Expected not to get exception with calculated 120% timeout on sleep time but 150% timeout on override' 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 compareTimes(endTime, startTime, SLEEP_TIME, None, .1) == 0 , 'Expected to sleep for SLEEP_TIME with 150% timeout on override'
assert result == expected , 'Got wrong result' assert result == expected , 'Got wrong result'
@ -258,7 +258,7 @@ class TestDecorator(object):
endTime = time.time() endTime = time.time()
assert gotException , 'Expected to get exception with calculated 120% timeout on sleep time but 70% timeout on override' 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' assert compareTimes(endTime, startTime, SLEEP_TIME * .7, None, .1) == 0 , 'Expected to sleep for 70% SLEEP_TIME with 70% timeout on override'
@func_set_timeout(calculateSleepUnder, allowOverride=True) @func_set_timeout(calculateSleepUnder, allowOverride=True)
@ -276,7 +276,7 @@ class TestDecorator(object):
endTime = time.time() endTime = time.time()
assert gotException , 'Expected to get exception with calculated 80% timeout on sleep 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' assert compareTimes(endTime, startTime, SLEEP_TIME * .8, None, .1) == 0 , 'Expected to sleep for 80% SLEEP_TIME'
expected = SLEEP_TIME + 4 expected = SLEEP_TIME + 4
gotException = False gotException = False
@ -288,7 +288,7 @@ class TestDecorator(object):
endTime = time.time() endTime = time.time()
assert not gotException , 'Expected not to get exception with calculated 80% timeout on sleep time but 120% timeout on override' 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' assert compareTimes(endTime, startTime, SLEEP_TIME , None, .1) == 0 , 'Expected to sleep for SLEEP_TIME with 120% timeout on override'
def test_setFuncTimeoutetry(self): def test_setFuncTimeoutetry(self):
@ -322,7 +322,7 @@ class TestDecorator(object):
endTime = time.time() endTime = time.time()
assert gotException , 'Expected to get exception with calculated 80% timeout' 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' assert compareTimes(endTime, startTime, SLEEP_TIME * .8, None, .1) == 0 , 'Expected to sleep for 80% SLEEP_TIME with 80% timeout'
gotException = False gotException = False
startTime = time.time() startTime = time.time()
@ -335,7 +335,7 @@ class TestDecorator(object):
endTime = time.time() endTime = time.time()
assert gotException , 'Expected to get exception with calculated same 80% timeout on retry' 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' assert compareTimes(endTime, startTime, SLEEP_TIME * .8, None, .1) == 0 , 'Expected to sleep for 80% SLEEP_TIME with same 80% timeout on retry'
result = None result = None
gotException = False gotException = False
@ -349,7 +349,7 @@ class TestDecorator(object):
endTime = time.time() endTime = time.time()
assert not gotException , 'Expected to get exception with calculated 80% timeout on retry ( None ) [ No timeout ]' 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 compareTimes(endTime, startTime, SLEEP_TIME, None, .1) == 0 , 'Expected to sleep for 100% SLEEP_TIME with 80% timeout overriden on retry ( None ) [ No timeout ]'
assert result == expected , 'Got wrong result' assert result == expected , 'Got wrong result'
@ -365,7 +365,7 @@ class TestDecorator(object):
endTime = time.time() endTime = time.time()
assert gotException , 'Expected to get exception with calculated 80% timeout overriden by 60% timeout on retry' 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 ]' assert compareTimes(endTime, startTime, SLEEP_TIME * .6, None, .1) == 0 , 'Expected to sleep for 60% SLEEP_TIME with 80% timeout overriden on retry ( SLEEP_TIME * .6 ) [ 60% timeout ]'
result = None result = None
gotException = False gotException = False
@ -379,7 +379,7 @@ class TestDecorator(object):
endTime = time.time() endTime = time.time()
assert not gotException , 'Expected to get exception with calculated 80% timeout overriden by 150% timeout on retry' 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 compareTimes(endTime, startTime, SLEEP_TIME , None, .1) == 0 , 'Expected to sleep for 100% SLEEP_TIME with 80% timeout overriden on retry ( SLEEP_TIME * 1.5 ) [ 150% timeout ]'
assert result == expected assert result == expected
threadsCleanedUp = False threadsCleanedUp = False
@ -394,45 +394,6 @@ class TestDecorator(object):
assert threadsCleanedUp , 'Expected other threads to get cleaned up after gc collection' 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__': if __name__ == '__main__':

View File

@ -1,159 +0,0 @@
#!/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

@ -35,7 +35,7 @@ class TestBasicSleepWithArgs(object):
raise AssertionError('Expected to have 1 default arg and 2 standard. Tried 3 args') raise AssertionError('Expected to have 1 default arg and 2 standard. Tried 3 args')
endTime = time.time() endTime = time.time()
assert compareTimes(endTime, startTime, 2, 2, deltaFixed=.15, deltaPct=None) == 0 , 'Expected getSleepLambdaWithArgs(2) to take 2 seconds.' assert compareTimes(endTime, startTime, 2, 2, deltaFixed=.1, deltaPct=None) == 0 , 'Expected getSleepLambdaWithArgs(2) to take 2 seconds.'
try: try:
sleepLambda(4, 7, 12) sleepLambda(4, 7, 12)
@ -54,7 +54,7 @@ class TestBasicSleepWithArgs(object):
endTime = time.time() endTime = time.time()
assert result == expectedResult , 'Got wrong result' 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.' assert compareTimes(endTime, startTime, 1.75, 2, deltaFixed=.1, deltaPct=None) == 0 , 'Expected getSleepLambdaWithArgs(1.75) to take 1.75 seconds.'
expectedResult = 5 + 13 expectedResult = 5 + 13
@ -63,7 +63,7 @@ class TestBasicSleepWithArgs(object):
endTime = time.time() endTime = time.time()
assert result == expectedResult , 'Did not get return from sleepFunction' 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.' assert compareTimes(endTime, startTime, 1.75, 2, deltaFixed=.1, deltaPct=None) == 0 , 'Expected getSleepLambda(1.75) to take 1.75 seconds.'
if __name__ == '__main__': 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()) 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())

View File

@ -12,62 +12,7 @@
# NOTE: Since version 1.2.3, you can also import this (like from a graphical application) and call the "main()" function. # 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). # 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 import imp
# 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 os
import subprocess import subprocess
@ -87,8 +32,8 @@ ALLOW_SITE_INSTALL = False
# This is the test directory that should contain all your tests. This should be a directory in your "tests" folder # This is the test directory that should contain all your tests. This should be a directory in your "tests" folder
MY_TEST_DIRECTORY = 'FuncTimeoutTests' MY_TEST_DIRECTORY = 'FuncTimeoutTests'
__version__ = '3.0.5' __version__ = '2.1.1'
__version_tuple__ = (3, 0, 5) __version_tuple__ = (2, 1, 1)
def findGoodTests(): def findGoodTests():
''' '''
@ -120,83 +65,8 @@ def findGoodTests():
"success" : success "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(): def try_pip_install():
''' pipe = subprocess.Popen('pip install GoodTests', shell=True)
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() res = pipe.wait()
return res return res
@ -325,7 +195,7 @@ def main(thisDir=None, additionalArgs=[], MY_PACKAGE_MODULE=None, ALLOW_SITE_INS
elif dirName == '': elif dirName == '':
inCurrentDir = False inCurrentDir = False
try: try:
find_mod(MY_PACKAGE_MODULE) imp.find_module(MY_PACKAGE_MODULE)
inCurrentDir = True inCurrentDir = True
except ImportError: except ImportError:
# COMPAT WITH PREVIOUS runTests.py: Try plain module in parent directory # COMPAT WITH PREVIOUS runTests.py: Try plain module in parent directory
@ -333,7 +203,7 @@ def main(thisDir=None, additionalArgs=[], MY_PACKAGE_MODULE=None, ALLOW_SITE_INS
oldSysPath = sys.path[:] oldSysPath = sys.path[:]
sys.path = [os.path.realpath(os.getcwd() + os.sep + '..' + os.sep)] sys.path = [os.path.realpath(os.getcwd() + os.sep + '..' + os.sep)]
try: try:
find_mod(MY_PACKAGE_MODULE) imp.find_module(MY_PACKAGE_MODULE)
foundIt = True foundIt = True
sys.path = oldSysPath sys.path = oldSysPath
except ImportError as e: except ImportError as e:
@ -364,15 +234,8 @@ def main(thisDir=None, additionalArgs=[], MY_PACKAGE_MODULE=None, ALLOW_SITE_INS
if baseName.endswith(('.py', '.pyc', '.pyo')): if baseName.endswith(('.py', '.pyc', '.pyo')):
MY_PACKAGE_MODULE = baseName[ : baseName.rindex('.')] MY_PACKAGE_MODULE = baseName[ : baseName.rindex('.')]
try: if e.name != MY_PACKAGE_MODULE:
eName = e.name 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' %(e.name, str(e), 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 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))) 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 return 1
@ -390,7 +253,8 @@ def main(thisDir=None, additionalArgs=[], MY_PACKAGE_MODULE=None, ALLOW_SITE_INS
didTerminate = False didTerminate = False
pipe = subprocess.Popen([sys.executable, goodTestsInfo['path']] + additionalArgs + [MY_TEST_DIRECTORY], env=os.environ, shell=False)
pipe = subprocess.Popen([goodTestsInfo['path']] + additionalArgs + [MY_TEST_DIRECTORY], env=os.environ, shell=False)
while True: while True:
try: try:
pipe.wait() pipe.wait()