##// END OF EJS Templates
sys.displayhook is now managed dynamically by display_trap.
Brian Granger -
r2231:732f3d1a
parent child
Show More
@@ -0,0 +1,62
1 #!/usr/bin/env python
2 # encoding: utf-8
3 """
4 A context manager for handling sys.displayhook.
5
6 Authors:
7
8 * Robert Kern
9 * Brian Granger
10 """
11
12 #-----------------------------------------------------------------------------
13 # Copyright (C) 2008-2009 The IPython Development Team
14 #
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
18
19 #-----------------------------------------------------------------------------
20 # Imports
21 #-----------------------------------------------------------------------------
22
23 import sys
24
25 from IPython.core.component import Component
26
27 #-----------------------------------------------------------------------------
28 # Classes and functions
29 #-----------------------------------------------------------------------------
30
31
32 class DisplayTrap(Component):
33 """Object to manage sys.displayhook.
34
35 This came from IPython.core.kernel.display_hook, but is simplified
36 (no callbacks or formatters) until more of the core is refactored.
37 """
38
39 def __init__(self, parent, hook):
40 super(DisplayTrap, self).__init__(parent, None, None)
41
42 self.hook = hook
43 self.old_hook = None
44
45 def __enter__(self):
46 self.set()
47 return self
48
49 def __exit__(self, type, value, traceback):
50 self.unset()
51 return True
52
53 def set(self):
54 """Set the hook."""
55 if sys.displayhook is not self.hook:
56 self.old_hook = sys.displayhook
57 sys.displayhook = self.hook
58
59 def unset(self):
60 """Unset the hook."""
61 sys.displayhook = self.old_hook
62
@@ -38,8 +38,8 BuiltinUndefined = BuiltinUndefined()
38 class BuiltinTrap(Component):
38 class BuiltinTrap(Component):
39 shell = Instance('IPython.core.iplib.InteractiveShell')
39 shell = Instance('IPython.core.iplib.InteractiveShell')
40
40
41 def __init__(self, parent, name=None, config=None):
41 def __init__(self, parent):
42 super(BuiltinTrap, self).__init__(parent, name, config)
42 super(BuiltinTrap, self).__init__(parent, None, None)
43 # Don't just grab parent!!!
43 # Don't just grab parent!!!
44 self.shell = Component.get_instances(root=self.root,
44 self.shell = Component.get_instances(root=self.root,
45 klass='IPython.core.iplib.InteractiveShell')[0]
45 klass='IPython.core.iplib.InteractiveShell')[0]
@@ -26,6 +26,7 Notes
26 from __future__ import with_statement
26 from __future__ import with_statement
27
27
28 import sys
28 import sys
29 from contextlib import nested
29
30
30 from IPython.core import ultratb
31 from IPython.core import ultratb
31 from IPython.core.iplib import InteractiveShell
32 from IPython.core.iplib import InteractiveShell
@@ -67,18 +68,14 class InteractiveShellEmbed(InteractiveShell):
67 banner1=None, banner2=None,
68 banner1=None, banner2=None,
68 custom_exceptions=((),None), exit_msg=''):
69 custom_exceptions=((),None), exit_msg=''):
69
70
70 # First we need to save the state of sys.displayhook and
71 # sys.ipcompleter so we can restore it when we are done.
72 self.save_sys_displayhook()
73 self.save_sys_ipcompleter()
71 self.save_sys_ipcompleter()
74
72
75 super(InteractiveShellEmbed,self).__init__(
73 super(InteractiveShellEmbed,self).__init__(
76 parent=parent, config=config, ipythondir=ipythondir, usage=usage,
74 parent=parent, config=config, ipythondir=ipythondir, usage=usage,
77 user_ns=user_ns, user_global_ns=user_global_ns,
75 user_ns=user_ns, user_global_ns=user_global_ns,
78 banner1=banner1, banner2=banner2,
76 banner1=banner1, banner2=banner2,
79 custom_exceptions=custom_exceptions)
77 custom_exceptions=custom_exceptions)
80
78
81 self.save_sys_displayhook_embed()
82 self.exit_msg = exit_msg
79 self.exit_msg = exit_msg
83 self.define_magic("kill_embedded", kill_embedded)
80 self.define_magic("kill_embedded", kill_embedded)
84
81
@@ -88,17 +85,11 class InteractiveShellEmbed(InteractiveShell):
88 mode=self.xmode,
85 mode=self.xmode,
89 call_pdb=self.pdb)
86 call_pdb=self.pdb)
90
87
91 self.restore_sys_displayhook()
92 self.restore_sys_ipcompleter()
88 self.restore_sys_ipcompleter()
93
89
94 def init_sys_modules(self):
90 def init_sys_modules(self):
95 pass
91 pass
96
92
97 def save_sys_displayhook(self):
98 # sys.displayhook is a global, we need to save the user's original
99 # Don't rely on __displayhook__, as the user may have changed that.
100 self.sys_displayhook_orig = sys.displayhook
101
102 def save_sys_ipcompleter(self):
93 def save_sys_ipcompleter(self):
103 """Save readline completer status."""
94 """Save readline completer status."""
104 try:
95 try:
@@ -107,9 +98,6 class InteractiveShellEmbed(InteractiveShell):
107 except:
98 except:
108 pass # not nested with IPython
99 pass # not nested with IPython
109
100
110 def restore_sys_displayhook(self):
111 sys.displayhook = self.sys_displayhook_orig
112
113 def restore_sys_ipcompleter(self):
101 def restore_sys_ipcompleter(self):
114 """Restores the readline completer which was in place.
102 """Restores the readline completer which was in place.
115
103
@@ -122,12 +110,6 class InteractiveShellEmbed(InteractiveShell):
122 except:
110 except:
123 pass
111 pass
124
112
125 def save_sys_displayhook_embed(self):
126 self.sys_displayhook_embed = sys.displayhook
127
128 def restore_sys_displayhook_embed(self):
129 sys.displayhook = self.sys_displayhook_embed
130
131 def __call__(self, header='', local_ns=None, global_ns=None, dummy=None,
113 def __call__(self, header='', local_ns=None, global_ns=None, dummy=None,
132 stack_depth=1):
114 stack_depth=1):
133 """Activate the interactive interpreter.
115 """Activate the interactive interpreter.
@@ -161,8 +143,6 class InteractiveShellEmbed(InteractiveShell):
161 if dummy or (dummy != 0 and self.dummy_mode):
143 if dummy or (dummy != 0 and self.dummy_mode):
162 return
144 return
163
145
164 self.restore_sys_displayhook_embed()
165
166 if self.has_readline:
146 if self.has_readline:
167 self.set_completer()
147 self.set_completer()
168
148
@@ -174,14 +154,12 class InteractiveShellEmbed(InteractiveShell):
174
154
175 # Call the embedding code with a stack depth of 1 so it can skip over
155 # Call the embedding code with a stack depth of 1 so it can skip over
176 # our call and get the original caller's namespaces.
156 # our call and get the original caller's namespaces.
177 self.mainloop(banner, local_ns, global_ns,
157 self.mainloop(banner, local_ns, global_ns,
178 stack_depth=stack_depth)
158 stack_depth=stack_depth)
179
159
180 if self.exit_msg is not None:
160 if self.exit_msg is not None:
181 print self.exit_msg
161 print self.exit_msg
182
162
183 # Restore global systems (display, completion)
184 self.restore_sys_displayhook()
185 self.restore_sys_ipcompleter()
163 self.restore_sys_ipcompleter()
186
164
187 def mainloop(self,header='',local_ns=None,global_ns=None,stack_depth=0):
165 def mainloop(self,header='',local_ns=None,global_ns=None,stack_depth=0):
@@ -240,7 +218,7 class InteractiveShellEmbed(InteractiveShell):
240 # actually completes using the frame's locals/globals
218 # actually completes using the frame's locals/globals
241 self.set_completer_frame()
219 self.set_completer_frame()
242
220
243 with self.builtin_trap:
221 with nested(self.builtin_trap, self.display_trap):
244 self.interact(header)
222 self.interact(header)
245
223
246 # now, purge out the user namespace from anything we might have added
224 # now, purge out the user namespace from anything we might have added
@@ -33,6 +33,7 import shutil
33 import string
33 import string
34 import sys
34 import sys
35 import tempfile
35 import tempfile
36 from contextlib import nested
36
37
37 from IPython.core import ultratb
38 from IPython.core import ultratb
38 from IPython.core import debugger, oinspect
39 from IPython.core import debugger, oinspect
@@ -41,6 +42,7 from IPython.core import history as ipcorehist
41 from IPython.core import prefilter
42 from IPython.core import prefilter
42 from IPython.core.autocall import IPyAutocall
43 from IPython.core.autocall import IPyAutocall
43 from IPython.core.builtin_trap import BuiltinTrap
44 from IPython.core.builtin_trap import BuiltinTrap
45 from IPython.core.display_trap import DisplayTrap
44 from IPython.core.fakemodule import FakeModule, init_fakemod_dict
46 from IPython.core.fakemodule import FakeModule, init_fakemod_dict
45 from IPython.core.logger import Logger
47 from IPython.core.logger import Logger
46 from IPython.core.magic import Magic
48 from IPython.core.magic import Magic
@@ -940,13 +942,7 class InteractiveShell(Component, Magic):
940 pass
942 pass
941
943
942 def init_displayhook(self):
944 def init_displayhook(self):
943 # I don't like assigning globally to sys, because it means when
945 self.display_trap = DisplayTrap(self, self.outputcache)
944 # embedding instances, each embedded instance overrides the previous
945 # choice. But sys.displayhook seems to be called internally by exec,
946 # so I don't see a way around it. We first save the original and then
947 # overwrite it.
948 self.sys_displayhook = sys.displayhook
949 sys.displayhook = self.outputcache
950
946
951 def init_reload_doctest(self):
947 def init_reload_doctest(self):
952 # Do a proper resetting of doctest, including the necessary displayhook
948 # Do a proper resetting of doctest, including the necessary displayhook
@@ -1061,7 +1057,6 class InteractiveShell(Component, Magic):
1061 self._orig_sys_module_state['stdin'] = sys.stdin
1057 self._orig_sys_module_state['stdin'] = sys.stdin
1062 self._orig_sys_module_state['stdout'] = sys.stdout
1058 self._orig_sys_module_state['stdout'] = sys.stdout
1063 self._orig_sys_module_state['stderr'] = sys.stderr
1059 self._orig_sys_module_state['stderr'] = sys.stderr
1064 self._orig_sys_module_state['displayhook'] = sys.displayhook
1065 self._orig_sys_module_state['excepthook'] = sys.excepthook
1060 self._orig_sys_module_state['excepthook'] = sys.excepthook
1066 try:
1061 try:
1067 self._orig_sys_modules_main_name = self.user_ns['__name__']
1062 self._orig_sys_modules_main_name = self.user_ns['__name__']
@@ -1251,7 +1246,7 class InteractiveShell(Component, Magic):
1251 error("Magic function `%s` not found." % magic_name)
1246 error("Magic function `%s` not found." % magic_name)
1252 else:
1247 else:
1253 magic_args = self.var_expand(magic_args,1)
1248 magic_args = self.var_expand(magic_args,1)
1254 with self.builtin_trap:
1249 with nested(self.builtin_trap, self.display_trap):
1255 return fn(magic_args)
1250 return fn(magic_args)
1256 # return result
1251 # return result
1257
1252
@@ -1348,7 +1343,7 class InteractiveShell(Component, Magic):
1348
1343
1349 def ex(self, cmd):
1344 def ex(self, cmd):
1350 """Execute a normal python statement in user namespace."""
1345 """Execute a normal python statement in user namespace."""
1351 with self.builtin_trap:
1346 with nested(self.builtin_trap, self.display_trap):
1352 exec cmd in self.user_global_ns, self.user_ns
1347 exec cmd in self.user_global_ns, self.user_ns
1353
1348
1354 def ev(self, expr):
1349 def ev(self, expr):
@@ -1356,7 +1351,7 class InteractiveShell(Component, Magic):
1356
1351
1357 Returns the result of evaluation
1352 Returns the result of evaluation
1358 """
1353 """
1359 with self.builtin_trap:
1354 with nested(self.builtin_trap, self.display_trap):
1360 return eval(expr, self.user_global_ns, self.user_ns)
1355 return eval(expr, self.user_global_ns, self.user_ns)
1361
1356
1362 def getoutput(self, cmd):
1357 def getoutput(self, cmd):
@@ -1688,6 +1683,8 class InteractiveShell(Component, Magic):
1688 try:
1683 try:
1689 f = file(err.filename)
1684 f = file(err.filename)
1690 try:
1685 try:
1686 # This should be inside a display_trap block and I
1687 # think it is.
1691 sys.displayhook(f.read())
1688 sys.displayhook(f.read())
1692 finally:
1689 finally:
1693 f.close()
1690 f.close()
@@ -1805,7 +1802,7 class InteractiveShell(Component, Magic):
1805 internally created default banner.
1802 internally created default banner.
1806 """
1803 """
1807
1804
1808 with self.builtin_trap:
1805 with nested(self.builtin_trap, self.display_trap):
1809 if self.c: # Emulate Python's -c option
1806 if self.c: # Emulate Python's -c option
1810 self.exec_init_cmd()
1807 self.exec_init_cmd()
1811
1808
@@ -2237,7 +2234,7 class InteractiveShell(Component, Magic):
2237 lines = lines.splitlines()
2234 lines = lines.splitlines()
2238 more = 0
2235 more = 0
2239
2236
2240 with self.builtin_trap:
2237 with nested(self.builtin_trap, self.display_trap):
2241 for line in lines:
2238 for line in lines:
2242 # skip blank lines so we don't mess up the prompt counter, but do
2239 # skip blank lines so we don't mess up the prompt counter, but do
2243 # NOT skip even a blank line if we are in a code block (more is
2240 # NOT skip even a blank line if we are in a code block (more is
@@ -69,7 +69,8 possible inclusion in future releases.
69 # the file COPYING, distributed as part of this software.
69 # the file COPYING, distributed as part of this software.
70 #*****************************************************************************
70 #*****************************************************************************
71
71
72 # Required modules
72 from __future__ import with_statement
73
73 import inspect
74 import inspect
74 import keyword
75 import keyword
75 import linecache
76 import linecache
@@ -85,16 +86,17 import types
85
86
86 # For purposes of monkeypatching inspect to fix a bug in it.
87 # For purposes of monkeypatching inspect to fix a bug in it.
87 from inspect import getsourcefile, getfile, getmodule,\
88 from inspect import getsourcefile, getfile, getmodule,\
88 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
89 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
89
90
90
91
91 # IPython's own modules
92 # IPython's own modules
92 # Modified pdb which doesn't damage IPython's readline handling
93 # Modified pdb which doesn't damage IPython's readline handling
93 from IPython.utils import PyColorize
94 from IPython.utils import PyColorize
94 from IPython.core import debugger, ipapi
95 from IPython.core import debugger, ipapi
96 from IPython.core.display_trap import DisplayTrap
95 from IPython.utils.ipstruct import Struct
97 from IPython.utils.ipstruct import Struct
96 from IPython.core.excolors import exception_colors
98 from IPython.core.excolors import exception_colors
97 from IPython.utils.genutils import Term,uniq_stable,error,info
99 from IPython.utils.genutils import Term, uniq_stable, error, info
98
100
99 # Globals
101 # Globals
100 # amount of space to put line numbers before verbose tracebacks
102 # amount of space to put line numbers before verbose tracebacks
@@ -848,24 +850,21 class VerboseTB(TBTools):
848 self.color_scheme_table.active_scheme_name)
850 self.color_scheme_table.active_scheme_name)
849 # the system displayhook may have changed, restore the original
851 # the system displayhook may have changed, restore the original
850 # for pdb
852 # for pdb
851 dhook = sys.displayhook
853 display_trap = DisplayTrap(None, sys.__displayhook__)
852 sys.displayhook = sys.__displayhook__
854 with display_trap:
853 self.pdb.reset()
855 self.pdb.reset()
854 # Find the right frame so we don't pop up inside ipython itself
856 # Find the right frame so we don't pop up inside ipython itself
855 if hasattr(self,'tb'):
857 if hasattr(self,'tb'):
856 etb = self.tb
858 etb = self.tb
857 else:
859 else:
858 etb = self.tb = sys.last_traceback
860 etb = self.tb = sys.last_traceback
859 while self.tb.tb_next is not None:
861 while self.tb.tb_next is not None:
860 self.tb = self.tb.tb_next
862 self.tb = self.tb.tb_next
861 try:
862 if etb and etb.tb_next:
863 if etb and etb.tb_next:
863 etb = etb.tb_next
864 etb = etb.tb_next
864 self.pdb.botframe = etb.tb_frame
865 self.pdb.botframe = etb.tb_frame
865 self.pdb.interaction(self.tb.tb_frame, self.tb)
866 self.pdb.interaction(self.tb.tb_frame, self.tb)
866 finally:
867
867 sys.displayhook = dhook
868
869 if hasattr(self,'tb'):
868 if hasattr(self,'tb'):
870 del self.tb
869 del self.tb
871
870
General Comments 0
You need to be logged in to leave comments. Login now