diff --git a/ChangeLog b/ChangeLog index 82afe7a..18fd87c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ -* 2.0.0 - Mar 18 2016 +* 3.0.0 - Mar 18 2016 - Change implementation to not leave lingering threads after a timeout occurs +- Split module into several parts +- Exportable "StoppableThread" impl, I may release later as a standalone +package. * 1.0.1 - Mar 15 2016 - Remove debugging print diff --git a/doc/func_timeout.StoppableThread.html b/doc/func_timeout.StoppableThread.html new file mode 100644 index 0000000..4880d33 --- /dev/null +++ b/doc/func_timeout.StoppableThread.html @@ -0,0 +1,296 @@ + +Python: module func_timeout.StoppableThread + + + + + +
 
+ 
func_timeout.StoppableThread
index
+

+

+ + + + + +
 
+Modules
       
ctypes
+
threading
+
time
+

+ + + + + +
 
+Classes
       
+
threading.Thread(builtins.object) +
+
+
JoinThread +
StoppableThread +
+
+
+

+ + + + + + + +
 
+class JoinThread(threading.Thread)
   JoinThread - The workhouse that stops the StoppableThread
 
 
Method resolution order:
+
JoinThread
+
threading.Thread
+
builtins.object
+
+
+Methods defined here:
+
__init__(self, otherThread, exception)
This constructor should always be called with keyword arguments. Arguments are:

+*group* should be None; reserved for future extension when a ThreadGroup
+class is implemented.

+*target* is the callable object to be invoked by the run()
+method. Defaults to None, meaning nothing is called.

+*name* is the thread name. By default, a unique name is constructed of
+the form "Thread-N" where N is a small decimal number.

+*args* is the argument tuple for the target invocation. Defaults to ().

+*kwargs* is a dictionary of keyword arguments for the target
+invocation. Defaults to {}.

+If a subclass overrides the constructor, it must make sure to invoke
+the base class constructor (Thread.__init__()) before doing anything
+else to the thread.
+ +
run(self)
Method representing the thread's activity.

+You may override this method in a subclass. The standard run() method
+invokes the callable object passed to the object's constructor as the
+target argument, if any, with sequential and keyword arguments taken
+from the args and kwargs arguments, respectively.
+ +
+Methods inherited from threading.Thread:
+
__repr__(self)
Return repr(self).
+ +
getName(self)
+ +
isAlive = is_alive(self)
Return whether the thread is alive.

+This method returns True just before the run() method starts until just
+after the run() method terminates. The module function enumerate()
+returns a list of all alive threads.
+ +
isDaemon(self)
+ +
is_alive(self)
Return whether the thread is alive.

+This method returns True just before the run() method starts until just
+after the run() method terminates. The module function enumerate()
+returns a list of all alive threads.
+ +
join(self, timeout=None)
Wait until the thread terminates.

+This blocks the calling thread until the thread whose join() method is
+called terminates -- either normally or through an unhandled exception
+or until the optional timeout occurs.

+When the timeout argument is present and not None, it should be a
+floating point number specifying a timeout for the operation in seconds
+(or fractions thereof). As join() always returns None, you must call
+isAlive() after join() to decide whether a timeout happened -- if the
+thread is still alive, the join() call timed out.

+When the timeout argument is not present or None, the operation will
+block until the thread terminates.

+A thread can be join()ed many times.

+join() raises a RuntimeError if an attempt is made to join the current
+thread as that would cause a deadlock. It is also an error to join() a
+thread before it has been started and attempts to do so raises the same
+exception.
+ +
setDaemon(self, daemonic)
+ +
setName(self, name)
+ +
start(self)
Start the thread's activity.

+It must be called at most once per thread object. It arranges for the
+object's run() method to be invoked in a separate thread of control.

+This method will raise a RuntimeError if called more than once on the
+same thread object.
+ +
+Data descriptors inherited from threading.Thread:
+
__dict__
+
dictionary for instance variables (if defined)
+
+
__weakref__
+
list of weak references to the object (if defined)
+
+
daemon
+
A boolean value indicating whether this thread is a daemon thread.

+This must be set before start() is called, otherwise RuntimeError is
+raised. Its initial value is inherited from the creating thread; the
+main thread is not a daemon thread and therefore all threads created in
+the main thread default to daemon = False.

+The entire Python program exits when no alive non-daemon threads are
+left.
+
+
ident
+
Thread identifier of this thread or None if it has not been started.

+This is a nonzero integer. See the thread.get_ident() function. Thread
+identifiers may be recycled when a thread exits and another thread is
+created. The identifier is available even after the thread has exited.
+
+
name
+
A string used for identification purposes only.

+It has no semantics. Multiple threads may be given the same name. The
+initial name is set by the constructor.
+
+

+ + + + + + + +
 
+class StoppableThread(threading.Thread)
   StoppableThread - A thread that can be stopped by forcing an exception in the execution context.
 
 
Method resolution order:
+
StoppableThread
+
threading.Thread
+
builtins.object
+
+
+Methods inherited from threading.Thread:
+
__init__(self, group=None, target=None, name=None, args=(), kwargs=None, *, daemon=None)
This constructor should always be called with keyword arguments. Arguments are:

+*group* should be None; reserved for future extension when a ThreadGroup
+class is implemented.

+*target* is the callable object to be invoked by the run()
+method. Defaults to None, meaning nothing is called.

+*name* is the thread name. By default, a unique name is constructed of
+the form "Thread-N" where N is a small decimal number.

+*args* is the argument tuple for the target invocation. Defaults to ().

+*kwargs* is a dictionary of keyword arguments for the target
+invocation. Defaults to {}.

+If a subclass overrides the constructor, it must make sure to invoke
+the base class constructor (Thread.__init__()) before doing anything
+else to the thread.
+ +
__repr__(self)
Return repr(self).
+ +
getName(self)
+ +
isAlive = is_alive(self)
Return whether the thread is alive.

+This method returns True just before the run() method starts until just
+after the run() method terminates. The module function enumerate()
+returns a list of all alive threads.
+ +
isDaemon(self)
+ +
is_alive(self)
Return whether the thread is alive.

+This method returns True just before the run() method starts until just
+after the run() method terminates. The module function enumerate()
+returns a list of all alive threads.
+ +
join(self, timeout=None)
Wait until the thread terminates.

+This blocks the calling thread until the thread whose join() method is
+called terminates -- either normally or through an unhandled exception
+or until the optional timeout occurs.

+When the timeout argument is present and not None, it should be a
+floating point number specifying a timeout for the operation in seconds
+(or fractions thereof). As join() always returns None, you must call
+isAlive() after join() to decide whether a timeout happened -- if the
+thread is still alive, the join() call timed out.

+When the timeout argument is not present or None, the operation will
+block until the thread terminates.

+A thread can be join()ed many times.

+join() raises a RuntimeError if an attempt is made to join the current
+thread as that would cause a deadlock. It is also an error to join() a
+thread before it has been started and attempts to do so raises the same
+exception.
+ +
run(self)
Method representing the thread's activity.

+You may override this method in a subclass. The standard run() method
+invokes the callable object passed to the object's constructor as the
+target argument, if any, with sequential and keyword arguments taken
+from the args and kwargs arguments, respectively.
+ +
setDaemon(self, daemonic)
+ +
setName(self, name)
+ +
start(self)
Start the thread's activity.

+It must be called at most once per thread object. It arranges for the
+object's run() method to be invoked in a separate thread of control.

+This method will raise a RuntimeError if called more than once on the
+same thread object.
+ +
+Data descriptors inherited from threading.Thread:
+
__dict__
+
dictionary for instance variables (if defined)
+
+
__weakref__
+
list of weak references to the object (if defined)
+
+
daemon
+
A boolean value indicating whether this thread is a daemon thread.

+This must be set before start() is called, otherwise RuntimeError is
+raised. Its initial value is inherited from the creating thread; the
+main thread is not a daemon thread and therefore all threads created in
+the main thread default to daemon = False.

+The entire Python program exits when no alive non-daemon threads are
+left.
+
+
ident
+
Thread identifier of this thread or None if it has not been started.

+This is a nonzero integer. See the thread.get_ident() function. Thread
+identifiers may be recycled when a thread exits and another thread is
+created. The identifier is available even after the thread has exited.
+
+
name
+
A string used for identification purposes only.

+It has no semantics. Multiple threads may be given the same name. The
+initial name is set by the constructor.
+
+

+ diff --git a/doc/func_timeout.dafunc.html b/doc/func_timeout.dafunc.html new file mode 100644 index 0000000..12c86a1 --- /dev/null +++ b/doc/func_timeout.dafunc.html @@ -0,0 +1,42 @@ + +Python: module func_timeout.dafunc + + + + + +
 
+ 
func_timeout.dafunc
index
+

+

+ + + + + +
 
+Modules
       
threading
+
time
+

+ + + + + +
 
+Functions
       
func_timeout(timeout, func, args=(), kwargs=None)
func_timeout - Runs the given function for up to #timeout# seconds.

+Raises any exceptions #func# would raise, returns what #func# would return (unless timeout is exceeded), in which case it raises FunctionTimedOut

+@param timeout <float> - Maximum number of seconds to run #func# before terminating
+@param func <function> - The function to call
+@param args    <tuple> - Any ordered arguments to pass to the function
+@param kwargs  <dict/None> - Keyword arguments to pass to the function.

+@raises - FunctionTimedOut if #timeout# is exceeded, otherwise anything #func# could raise will be raised

+@return - The return value that #func# gives
+
+ diff --git a/doc/func_timeout.exceptions.html b/doc/func_timeout.exceptions.html new file mode 100644 index 0000000..b8036f9 --- /dev/null +++ b/doc/func_timeout.exceptions.html @@ -0,0 +1,87 @@ + +Python: module func_timeout.exceptions + + + + + +
 
+ 
func_timeout.exceptions
index
+

+

+ + + + + +
 
+Classes
       
+
builtins.BaseException(builtins.object) +
+
+
FunctionTimedOut +
+
+
+

+ + + + + + + +
 
+class FunctionTimedOut(builtins.BaseException)
   Common base class for all exceptions
 
 
Method resolution order:
+
FunctionTimedOut
+
builtins.BaseException
+
builtins.object
+
+
+Data descriptors defined here:
+
__weakref__
+
list of weak references to the object (if defined)
+
+
+Methods inherited from builtins.BaseException:
+
__delattr__(self, name, /)
Implement delattr(self, name).
+ +
__getattribute__(self, name, /)
Return getattr(self, name).
+ +
__init__(self, /, *args, **kwargs)
Initialize self.  See help(type(self)) for accurate signature.
+ +
__new__(*args, **kwargs) from builtins.type
Create and return a new object.  See help(type) for accurate signature.
+ +
__reduce__(...)
helper for pickle
+ +
__repr__(self, /)
Return repr(self).
+ +
__setattr__(self, name, value, /)
Implement setattr(self, name, value).
+ +
__setstate__(...)
+ +
__str__(self, /)
Return str(self).
+ +
with_traceback(...)
Exception.with_traceback(tb) --
+set self.__traceback__ to tb and return self.
+ +
+Data descriptors inherited from builtins.BaseException:
+
__cause__
+
exception cause
+
+
__context__
+
exception context
+
+
__dict__
+
+
__suppress_context__
+
+
__traceback__
+
+
args
+
+

+ diff --git a/doc/func_timeout.html b/doc/func_timeout.html index 9ac4ce2..9b74a9e 100644 --- a/doc/func_timeout.html +++ b/doc/func_timeout.html @@ -6,7 +6,7 @@  
func_timeout (version 2.0.0)
 
- 
func_timeout (version 1.0.1)
index

Copyright (c) 2016 Tim Savannah All Rights Reserved.
@@ -20,7 +20,10 @@ LICENSE, otherwise it is available at https://gith Package Contents         -

+
StoppableThread
+
dafunc
+
exceptions
+

 
@@ -28,10 +31,10 @@ LICENSE, otherwise it is available at https://gith
       
-
builtins.Exception(builtins.BaseException) +
builtins.BaseException(builtins.object)
-
FunctionTimedOut +
func_timeout.exceptions.FunctionTimedOut
@@ -39,14 +42,13 @@ LICENSE, otherwise it is available at https://gith +class FunctionTimedOut(builtins.BaseException) - +
 
-class FunctionTimedOut(builtins.Exception)
   Common base class for all non-exit exceptions.
 
Common base class for all exceptions
 
 
Method resolution order:
-
FunctionTimedOut
-
builtins.Exception
+
FunctionTimedOut
builtins.BaseException
builtins.object
@@ -55,18 +57,16 @@ Data descriptors defined here:
__weakref__
list of weak references to the object (if defined)
-
-Methods inherited from builtins.Exception:
-
__init__(self, /, *args, **kwargs)
Initialize self.  See help(type(self)) for accurate signature.
- -
__new__(*args, **kwargs) from builtins.type
Create and return a new object.  See help(type) for accurate signature.
-
Methods inherited from builtins.BaseException:
__delattr__(self, name, /)
Implement delattr(self, name).
__getattribute__(self, name, /)
Return getattr(self, name).
+
__init__(self, /, *args, **kwargs)
Initialize self.  See help(type(self)) for accurate signature.
+ +
__new__(*args, **kwargs) from builtins.type
Create and return a new object.  See help(type) for accurate signature.
+
__reduce__(...)
helper for pickle
__repr__(self, /)
Return repr(self).
@@ -77,7 +77,7 @@ Methods inherited from builtins.BaseExcept
__str__(self, /)
Return str(self).
-
with_traceback(...)
Exception.with_traceback(tb) --
+
with_traceback(...)
Exception.with_traceback(tb) --
set self.__traceback__ to tb and return self.

@@ -123,5 +123,5 @@ Raises any exceptions #func# would raise, returns&
        __all__ = ('func_timeout', 'FunctionTimedOut')
-__version_tuple__ = (1, 0, 1)
+__version_tuple__ = (2, 0, 0)
diff --git a/func_timeout/StoppableThread.py b/func_timeout/StoppableThread.py index 860ce7d..37a87d8 100644 --- a/func_timeout/StoppableThread.py +++ b/func_timeout/StoppableThread.py @@ -1,8 +1,16 @@ +''' + 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 + LICENSE, otherwise it is available at https://github.com/kata198/func_timeout/LICENSE +''' import ctypes import threading import time +__all__ = ('StoppableThread', 'JoinThread') + class StoppableThread(threading.Thread): ''' StoppableThread - A thread that can be stopped by forcing an exception in the execution context. @@ -13,8 +21,10 @@ class StoppableThread(threading.Thread): if self.isAlive() is False: return True + self._stderr = open('/dev/null', 'w') joinThread = JoinThread(self, exception) joinThread.start() + joinThread._stderr = self._stderr class JoinThread(threading.Thread): ''' diff --git a/func_timeout/dafunc.py b/func_timeout/dafunc.py index f603caa..8ac7373 100644 --- a/func_timeout/dafunc.py +++ b/func_timeout/dafunc.py @@ -1,3 +1,9 @@ +''' + 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 + LICENSE, otherwise it is available at https://github.com/kata198/func_timeout/LICENSE +''' import threading import time @@ -46,10 +52,10 @@ def func_timeout(timeout, func, args=(), kwargs=None): stopException = None if thread.isAlive(): isStopped = True - stopException = FunctionTimedOut('Function %s (args=%s) (kwargs=%s) timed out after %f seconds.\n' %(func.__name__, str(args), str(kwargs), timeout)) + stopException = FunctionTimedOut thread._stopThread(stopException) thread.join(.1) - raise stopException + raise FunctionTimedOut('Function %s (args=%s) (kwargs=%s) timed out after %f seconds.\n' %(func.__name__, str(args), str(kwargs), timeout)) if exception: raise exception[0] diff --git a/func_timeout/exceptions.py b/func_timeout/exceptions.py index 680ffdb..62e2c3a 100644 --- a/func_timeout/exceptions.py +++ b/func_timeout/exceptions.py @@ -1,4 +1,13 @@ +''' + 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 + LICENSE, otherwise it is available at https://github.com/kata198/func_timeout/LICENSE +''' -class FunctionTimedOut(Exception): +class FunctionTimedOut(BaseException): + ''' + FunctionTimedOut - Exception raised when a function times out + ''' pass diff --git a/setup.py b/setup.py index 2d01454..7d40491 100755 --- a/setup.py +++ b/setup.py @@ -30,7 +30,7 @@ if __name__ == '__main__': log_description = summary setup(name='func_timeout', - version='2.0.0', + version='3.0.0', packages=['func_timeout'], author='Tim Savannah', author_email='kata198@gmail.com',