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