"""Drop-in replacement for the thread module. | |
Meant to be used as a brain-dead substitute so that threaded code does | |
not need to be rewritten for when the thread module is not present. | |
Suggested usage is:: | |
try: | |
import thread | |
except ImportError: | |
import dummy_thread as thread | |
""" | |
# Exports only things specified by thread documentation; | |
# skipping obsolete synonyms allocate(), start_new(), exit_thread(). | |
__all__ = ['error', 'start_new_thread', 'exit', 'get_ident', 'allocate_lock', | |
'interrupt_main', 'LockType'] | |
import traceback as _traceback | |
class error(Exception): | |
"""Dummy implementation of thread.error.""" | |
def __init__(self, *args): | |
self.args = args | |
def start_new_thread(function, args, kwargs={}): | |
"""Dummy implementation of thread.start_new_thread(). | |
Compatibility is maintained by making sure that ``args`` is a | |
tuple and ``kwargs`` is a dictionary. If an exception is raised | |
and it is SystemExit (which can be done by thread.exit()) it is | |
caught and nothing is done; all other exceptions are printed out | |
by using traceback.print_exc(). | |
If the executed function calls interrupt_main the KeyboardInterrupt will be | |
raised when the function returns. | |
""" | |
if type(args) != type(tuple()): | |
raise TypeError("2nd arg must be a tuple") | |
if type(kwargs) != type(dict()): | |
raise TypeError("3rd arg must be a dict") | |
global _main | |
_main = False | |
try: | |
function(*args, **kwargs) | |
except SystemExit: | |
pass | |
except: | |
_traceback.print_exc() | |
_main = True | |
global _interrupt | |
if _interrupt: | |
_interrupt = False | |
raise KeyboardInterrupt | |
def exit(): | |
"""Dummy implementation of thread.exit().""" | |
raise SystemExit | |
def get_ident(): | |
"""Dummy implementation of thread.get_ident(). | |
Since this module should only be used when threadmodule is not | |
available, it is safe to assume that the current process is the | |
only thread. Thus a constant can be safely returned. | |
""" | |
return -1 | |
def allocate_lock(): | |
"""Dummy implementation of thread.allocate_lock().""" | |
return LockType() | |
def stack_size(size=None): | |
"""Dummy implementation of thread.stack_size().""" | |
if size is not None: | |
raise error("setting thread stack size not supported") | |
return 0 | |
class LockType(object): | |
"""Class implementing dummy implementation of thread.LockType. | |
Compatibility is maintained by maintaining self.locked_status | |
which is a boolean that stores the state of the lock. Pickling of | |
the lock, though, should not be done since if the thread module is | |
then used with an unpickled ``lock()`` from here problems could | |
occur from this class not having atomic methods. | |
""" | |
def __init__(self): | |
self.locked_status = False | |
def acquire(self, waitflag=None): | |
"""Dummy implementation of acquire(). | |
For blocking calls, self.locked_status is automatically set to | |
True and returned appropriately based on value of | |
``waitflag``. If it is non-blocking, then the value is | |
actually checked and not set if it is already acquired. This | |
is all done so that threading.Condition's assert statements | |
aren't triggered and throw a little fit. | |
""" | |
if waitflag is None or waitflag: | |
self.locked_status = True | |
return True | |
else: | |
if not self.locked_status: | |
self.locked_status = True | |
return True | |
else: | |
return False | |
__enter__ = acquire | |
def __exit__(self, typ, val, tb): | |
self.release() | |
def release(self): | |
"""Release the dummy lock.""" | |
# XXX Perhaps shouldn't actually bother to test? Could lead | |
# to problems for complex, threaded code. | |
if not self.locked_status: | |
raise error | |
self.locked_status = False | |
return True | |
def locked(self): | |
return self.locked_status | |
# Used to signal that interrupt_main was called in a "thread" | |
_interrupt = False | |
# True when not executing in a "thread" | |
_main = True | |
def interrupt_main(): | |
"""Set _interrupt flag to True to have start_new_thread raise | |
KeyboardInterrupt upon exiting.""" | |
if _main: | |
raise KeyboardInterrupt | |
else: | |
global _interrupt | |
_interrupt = True |