##// END OF EJS Templates
shellglobals.py => core/shellglobals.py and imports updated.
Brian Granger -
Show More
1 NO CONTENT: file renamed from IPython/shellglobals.py to IPython/core/shellglobals.py
@@ -1,62 +1,65 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3
4 4 def test_import_completer():
5 5 from IPython.core import completer
6 6
7 7 def test_import_crashhandler():
8 8 from IPython.core import crashhandler
9 9
10 10 def test_import_debugger():
11 11 from IPython.core import debugger
12 12
13 13 def test_import_fakemodule():
14 14 from IPython.core import fakemodule
15 15
16 16 def test_import_excolors():
17 17 from IPython.core import excolors
18 18
19 19 def test_import_history():
20 20 from IPython.core import history
21 21
22 22 def test_import_hooks():
23 23 from IPython.core import hooks
24 24
25 25 def test_import_ipapi():
26 26 from IPython.core import ipapi
27 27
28 28 def test_import_iplib():
29 29 from IPython.core import iplib
30 30
31 31 def test_import_ipmaker():
32 32 from IPython.core import ipmaker
33 33
34 34 def test_import_logger():
35 35 from IPython.core import logger
36 36
37 37 def test_import_macro():
38 38 from IPython.core import macro
39 39
40 40 def test_import_magic():
41 41 from IPython.core import magic
42 42
43 43 def test_import_oinspect():
44 44 from IPython.core import oinspect
45 45
46 46 def test_import_outputtrap():
47 47 from IPython.core import outputtrap
48 48
49 49 def test_import_prefilter():
50 50 from IPython.core import prefilter
51 51
52 52 def test_import_prompts():
53 53 from IPython.core import prompts
54 54
55 55 def test_import_release():
56 56 from IPython.core import release
57 57
58 58 def test_import_shadowns():
59 59 from IPython.core import shadowns
60 60
61 61 def test_import_shell():
62 62 from IPython.core import shell
63
64 def test_import_shellglobals():
65 from IPython.core import shellglobals
@@ -1,282 +1,282 b''
1 1 """Twisted shell support.
2 2
3 3 XXX - This module is missing proper docs.
4 4 """
5 5 import sys
6 6
7 7 from twisted.internet import reactor, threads
8 8
9 9 from IPython.core.ipmaker import make_IPython
10 10 from IPython.core.iplib import InteractiveShell
11 11 from IPython.utils.ipstruct import Struct
12 12 import Queue,thread,threading,signal
13 13 from signal import signal, SIGINT
14 14 from IPython.utils.genutils import Term,warn,error,flag_calls, ask_yes_no
15 import shellglobals
15 from IPython.core import shellglobals
16 16
17 17 def install_gtk2():
18 18 """ Install gtk2 reactor, needs to be called bef """
19 19 from twisted.internet import gtk2reactor
20 20 gtk2reactor.install()
21 21
22 22
23 23 def hijack_reactor():
24 24 """Modifies Twisted's reactor with a dummy so user code does
25 25 not block IPython. This function returns the original
26 26 'twisted.internet.reactor' that has been hijacked.
27 27
28 28 NOTE: Make sure you call this *AFTER* you've installed
29 29 the reactor of your choice.
30 30 """
31 31 from twisted import internet
32 32 orig_reactor = internet.reactor
33 33
34 34 class DummyReactor(object):
35 35 def run(self):
36 36 pass
37 37 def __getattr__(self, name):
38 38 return getattr(orig_reactor, name)
39 39 def __setattr__(self, name, value):
40 40 return setattr(orig_reactor, name, value)
41 41
42 42 internet.reactor = DummyReactor()
43 43 return orig_reactor
44 44
45 45 class TwistedInteractiveShell(InteractiveShell):
46 46 """Simple multi-threaded shell."""
47 47
48 48 # Threading strategy taken from:
49 49 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65109, by Brian
50 50 # McErlean and John Finlay. Modified with corrections by Antoon Pardon,
51 51 # from the pygtk mailing list, to avoid lockups with system calls.
52 52
53 53 # class attribute to indicate whether the class supports threads or not.
54 54 # Subclasses with thread support should override this as needed.
55 55 isthreaded = True
56 56
57 57 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
58 58 user_ns=None,user_global_ns=None,banner2='',**kw):
59 59 """Similar to the normal InteractiveShell, but with threading control"""
60 60
61 61 InteractiveShell.__init__(self,name,usage,rc,user_ns,
62 62 user_global_ns,banner2)
63 63
64 64
65 65 # A queue to hold the code to be executed.
66 66 self.code_queue = Queue.Queue()
67 67
68 68 # Stuff to do at closing time
69 69 self._kill = None
70 70 on_kill = kw.get('on_kill', [])
71 71 # Check that all things to kill are callable:
72 72 for t in on_kill:
73 73 if not callable(t):
74 74 raise TypeError,'on_kill must be a list of callables'
75 75 self.on_kill = on_kill
76 76 # thread identity of the "worker thread" (that may execute code directly)
77 77 self.worker_ident = None
78 78 self.reactor_started = False
79 79 self.first_run = True
80 80
81 81 def runsource(self, source, filename="<input>", symbol="single"):
82 82 """Compile and run some source in the interpreter.
83 83
84 84 Modified version of code.py's runsource(), to handle threading issues.
85 85 See the original for full docstring details."""
86 86
87 87 # If Ctrl-C was typed, we reset the flag and return right away
88 88 if shellglobals.KBINT:
89 89 shellglobals.KBINT = False
90 90 return False
91 91
92 92 if self._kill:
93 93 # can't queue new code if we are being killed
94 94 return True
95 95
96 96 try:
97 97 code = self.compile(source, filename, symbol)
98 98 except (OverflowError, SyntaxError, ValueError):
99 99 # Case 1
100 100 self.showsyntaxerror(filename)
101 101 return False
102 102
103 103 if code is None:
104 104 # Case 2
105 105 return True
106 106
107 107 # shortcut - if we are in worker thread, or the worker thread is not running,
108 108 # execute directly (to allow recursion and prevent deadlock if code is run early
109 109 # in IPython construction)
110 110
111 111 if (not self.reactor_started or (self.worker_ident is None and not self.first_run)
112 112 or self.worker_ident == thread.get_ident() or shellglobals.run_in_frontend(source)):
113 113 InteractiveShell.runcode(self,code)
114 114 return
115 115
116 116 # Case 3
117 117 # Store code in queue, so the execution thread can handle it.
118 118
119 119 self.first_run = False
120 120 completed_ev, received_ev = threading.Event(), threading.Event()
121 121
122 122 self.code_queue.put((code,completed_ev, received_ev))
123 123
124 124 reactor.callLater(0.0,self.runcode)
125 125 received_ev.wait(5)
126 126 if not received_ev.isSet():
127 127 # the mainloop is dead, start executing code directly
128 128 print "Warning: Timeout for mainloop thread exceeded"
129 129 print "switching to nonthreaded mode (until mainloop wakes up again)"
130 130 self.worker_ident = None
131 131 else:
132 132 completed_ev.wait()
133 133
134 134 return False
135 135
136 136 def runcode(self):
137 137 """Execute a code object.
138 138
139 139 Multithreaded wrapper around IPython's runcode()."""
140 140
141 141
142 142 # we are in worker thread, stash out the id for runsource()
143 143 self.worker_ident = thread.get_ident()
144 144
145 145 if self._kill:
146 146 print >>Term.cout, 'Closing threads...',
147 147 Term.cout.flush()
148 148 for tokill in self.on_kill:
149 149 tokill()
150 150 print >>Term.cout, 'Done.'
151 151 # allow kill() to return
152 152 self._kill.set()
153 153 return True
154 154
155 155 # Install SIGINT handler. We do it every time to ensure that if user
156 156 # code modifies it, we restore our own handling.
157 157 try:
158 158 pass
159 159 signal(SIGINT,shellglobals.sigint_handler)
160 160 except SystemError:
161 161 # This happens under Windows, which seems to have all sorts
162 162 # of problems with signal handling. Oh well...
163 163 pass
164 164
165 165 # Flush queue of pending code by calling the run methood of the parent
166 166 # class with all items which may be in the queue.
167 167 code_to_run = None
168 168 while 1:
169 169 try:
170 170 code_to_run, completed_ev, received_ev = self.code_queue.get_nowait()
171 171 except Queue.Empty:
172 172 break
173 173 received_ev.set()
174 174
175 175
176 176 # Exceptions need to be raised differently depending on which
177 177 # thread is active. This convoluted try/except is only there to
178 178 # protect against asynchronous exceptions, to ensure that a shellglobals.KBINT
179 179 # at the wrong time doesn't deadlock everything. The global
180 180 # CODE_TO_RUN is set to true/false as close as possible to the
181 181 # runcode() call, so that the KBINT handler is correctly informed.
182 182 try:
183 183 try:
184 184 shellglobals.CODE_RUN = True
185 185 InteractiveShell.runcode(self,code_to_run)
186 186 except KeyboardInterrupt:
187 187 print "Keyboard interrupted in mainloop"
188 188 while not self.code_queue.empty():
189 189 code = self.code_queue.get_nowait()
190 190 break
191 191 finally:
192 192 shellglobals.CODE_RUN = False
193 193 # allow runsource() return from wait
194 194 completed_ev.set()
195 195
196 196 # This MUST return true for gtk threading to work
197 197 return True
198 198
199 199 def kill(self):
200 200 """Kill the thread, returning when it has been shut down."""
201 201 self._kill = threading.Event()
202 202 reactor.callLater(0.0,self.runcode)
203 203 self._kill.wait()
204 204
205 205
206 206
207 207 class IPShellTwisted:
208 208 """Run a Twisted reactor while in an IPython session.
209 209
210 210 Python commands can be passed to the thread where they will be
211 211 executed. This is implemented by periodically checking for
212 212 passed code using a Twisted reactor callback.
213 213 """
214 214
215 215 TIMEOUT = 0.01 # Millisecond interval between reactor runs.
216 216
217 217 def __init__(self, argv=None, user_ns=None, debug=1,
218 218 shell_class=TwistedInteractiveShell):
219 219
220 220 from twisted.internet import reactor
221 221 self.reactor = hijack_reactor()
222 222
223 223 mainquit = self.reactor.stop
224 224
225 225 # Make sure IPython keeps going after reactor stop.
226 226 def reactorstop():
227 227 pass
228 228 self.reactor.stop = reactorstop
229 229 reactorrun_orig = self.reactor.run
230 230 self.quitting = False
231 231 def reactorrun():
232 232 while True and not self.quitting:
233 233 reactorrun_orig()
234 234 self.reactor.run = reactorrun
235 235
236 236 self.IP = make_IPython(argv, user_ns=user_ns, debug=debug,
237 237 shell_class=shell_class,
238 238 on_kill=[mainquit])
239 239
240 240 # threading.Thread.__init__(self)
241 241
242 242 def run(self):
243 243 self.IP.mainloop()
244 244 self.quitting = True
245 245 self.IP.kill()
246 246
247 247 def mainloop(self):
248 248 def mainLoopThreadDeath(r):
249 249 print "mainLoopThreadDeath: ", str(r)
250 250 def spawnMainloopThread():
251 251 d=threads.deferToThread(self.run)
252 252 d.addBoth(mainLoopThreadDeath)
253 253 reactor.callWhenRunning(spawnMainloopThread)
254 254 self.IP.reactor_started = True
255 255 self.reactor.run()
256 256 print "mainloop ending...."
257 257
258 258 exists = True
259 259
260 260
261 261 if __name__ == '__main__':
262 262 # Sample usage.
263 263
264 264 # Create the shell object. This steals twisted.internet.reactor
265 265 # for its own purposes, to make sure you've already installed a
266 266 # reactor of your choice.
267 267 shell = IPShellTwisted(
268 268 argv=[],
269 269 user_ns={'__name__': '__example__',
270 270 'hello': 'world',
271 271 },
272 272 )
273 273
274 274 # Run the mainloop. This runs the actual reactor.run() method.
275 275 # The twisted.internet.reactor object at this point is a dummy
276 276 # object that passes through to the actual reactor, but prevents
277 277 # run() from being called on it again.
278 278 shell.mainloop()
279 279
280 280 # You must exit IPython to terminate your program.
281 281 print 'Goodbye!'
282 282
General Comments 0
You need to be logged in to leave comments. Login now