1 """Drop-in replacement for the thread module. 2 3 Meant to be used as a brain-dead substitute so that threaded code does 4 not need to be rewritten for when the thread module is not present. 5 6 Suggested usage is:: 7 8 try: 9 import thread 10 except ImportError: 11 import dummy_thread as thread 12 13 """ 14 # Exports only things specified by thread documentation; 15 # skipping obsolete synonyms allocate(), start_new(), exit_thread(). 16 __all__ = ['error', 'start_new_thread', 'exit', 'get_ident', 'allocate_lock', 17 'interrupt_main', 'LockType'] 18 19 import traceback as _traceback 20 21 class error(Exception): 22 """Dummy implementation of thread.error.""" 23 24 def __init__(self, *args): 25 self.args = args 26 27 def start_new_thread(function, args, kwargs={}): 28 """Dummy implementation of thread.start_new_thread(). 29 30 Compatibility is maintained by making sure that ``args`` is a 31 tuple and ``kwargs`` is a dictionary. If an exception is raised 32 and it is SystemExit (which can be done by thread.exit()) it is 33 caught and nothing is done; all other exceptions are printed out 34 by using traceback.print_exc(). 35 36 If the executed function calls interrupt_main the KeyboardInterrupt will be 37 raised when the function returns. 38 39 """ 40 if type(args) != type(tuple()): 41 raise TypeError("2nd arg must be a tuple") 42 if type(kwargs) != type(dict()): 43 raise TypeError("3rd arg must be a dict") 44 global _main 45 _main = False 46 try: 47 function(*args, **kwargs) 48 except SystemExit: 49 pass 50 except: 51 _traceback.print_exc() 52 _main = True 53 global _interrupt 54 if _interrupt: 55 _interrupt = False 56 raise KeyboardInterrupt 57 58 def exit(): 59 """Dummy implementation of thread.exit().""" 60 raise SystemExit 61 62 def get_ident(): 63 """Dummy implementation of thread.get_ident(). 64 65 Since this module should only be used when threadmodule is not 66 available, it is safe to assume that the current process is the 67 only thread. Thus a constant can be safely returned. 68 """ 69 return -1 70 71 def allocate_lock(): 72 """Dummy implementation of thread.allocate_lock().""" 73 return LockType() 74 75 def stack_size(size=None): 76 """Dummy implementation of thread.stack_size().""" 77 if size is not None: 78 raise error("setting thread stack size not supported") 79 return 0 80 81 class LockType(object): 82 """Class implementing dummy implementation of thread.LockType. 83 84 Compatibility is maintained by maintaining self.locked_status 85 which is a boolean that stores the state of the lock. Pickling of 86 the lock, though, should not be done since if the thread module is 87 then used with an unpickled ``lock()`` from here problems could 88 occur from this class not having atomic methods. 89 90 """ 91 92 def __init__(self): 93 self.locked_status = False 94 95 def acquire(self, waitflag=None): 96 """Dummy implementation of acquire(). 97 98 For blocking calls, self.locked_status is automatically set to 99 True and returned appropriately based on value of 100 ``waitflag``. If it is non-blocking, then the value is 101 actually checked and not set if it is already acquired. This 102 is all done so that threading.Condition's assert statements 103 aren't triggered and throw a little fit. 104 105 """ 106 if waitflag is None or waitflag: 107 self.locked_status = True 108 return True 109 else: 110 if not self.locked_status: 111 self.locked_status = True 112 return True 113 else: 114 return False 115 116 __enter__ = acquire 117 118 def __exit__(self, typ, val, tb): 119 self.release() 120 121 def release(self): 122 """Release the dummy lock.""" 123 # XXX Perhaps shouldn't actually bother to test? Could lead 124 # to problems for complex, threaded code. 125 if not self.locked_status: 126 raise error 127 self.locked_status = False 128 return True 129 130 def locked(self): 131 return self.locked_status 132 133 # Used to signal that interrupt_main was called in a "thread" 134 _interrupt = False 135 # True when not executing in a "thread" 136 _main = True 137 138 def interrupt_main(): 139 """Set _interrupt flag to True to have start_new_thread raise 140 KeyboardInterrupt upon exiting.""" 141 if _main: 142 raise KeyboardInterrupt 143 else: 144 global _interrupt 145 _interrupt = True 146