Add NEWS entry as per RDM's suggestion (the bug was actually present
[python.git] / Lib / dummy_thread.py
blob198dc49dba39e6550bc1c1c701009a7a43d2a93d
1 """Drop-in replacement for the thread module.
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.
6 Suggested usage is::
8 try:
9 import thread
10 except ImportError:
11 import dummy_thread as thread
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']
19 import traceback as _traceback
21 class error(Exception):
22 """Dummy implementation of thread.error."""
24 def __init__(self, *args):
25 self.args = args
27 def start_new_thread(function, args, kwargs={}):
28 """Dummy implementation of thread.start_new_thread().
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().
36 If the executed function calls interrupt_main the KeyboardInterrupt will be
37 raised when the function returns.
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
58 def exit():
59 """Dummy implementation of thread.exit()."""
60 raise SystemExit
62 def get_ident():
63 """Dummy implementation of thread.get_ident().
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
71 def allocate_lock():
72 """Dummy implementation of thread.allocate_lock()."""
73 return LockType()
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
81 class LockType(object):
82 """Class implementing dummy implementation of thread.LockType.
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.
90 """
92 def __init__(self):
93 self.locked_status = False
95 def acquire(self, waitflag=None):
96 """Dummy implementation of acquire().
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.
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
116 __enter__ = acquire
118 def __exit__(self, typ, val, tb):
119 self.release()
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
130 def locked(self):
131 return self.locked_status
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
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