##// END OF EJS Templates
Move gui and pylab options to InteractiveShellApp.
Bradley M. Froehle -
Show More
@@ -29,9 +29,12 b' import sys'
29 from IPython.config.application import boolean_flag
29 from IPython.config.application import boolean_flag
30 from IPython.config.configurable import Configurable
30 from IPython.config.configurable import Configurable
31 from IPython.config.loader import Config
31 from IPython.config.loader import Config
32 from IPython.core import pylabtools
32 from IPython.utils import py3compat
33 from IPython.utils import py3compat
33 from IPython.utils.path import filefind
34 from IPython.utils.path import filefind
34 from IPython.utils.traitlets import Unicode, Instance, List, Bool
35 from IPython.utils.traitlets import (
36 Unicode, Instance, List, Bool, CaselessStrEnum
37 )
35
38
36 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
37 # Aliases and Flags
40 # Aliases and Flags
@@ -94,7 +97,11 b" nosep_config.InteractiveShell.separate_out = ''"
94 nosep_config.InteractiveShell.separate_out2 = ''
97 nosep_config.InteractiveShell.separate_out2 = ''
95
98
96 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
99 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
97
100 shell_flags['pylab'] = (
101 {'InteractiveShellApp' : {'pylab' : 'auto'}},
102 """Pre-load matplotlib and numpy for interactive use with
103 the default matplotlib backend."""
104 )
98
105
99 # it's possible we don't want short aliases for *all* of these:
106 # it's possible we don't want short aliases for *all* of these:
100 shell_aliases = dict(
107 shell_aliases = dict(
@@ -105,6 +112,8 b' shell_aliases = dict('
105 c='InteractiveShellApp.code_to_run',
112 c='InteractiveShellApp.code_to_run',
106 m='InteractiveShellApp.module_to_run',
113 m='InteractiveShellApp.module_to_run',
107 ext='InteractiveShellApp.extra_extension',
114 ext='InteractiveShellApp.extra_extension',
115 gui='InteractiveShellApp.gui',
116 pylab='InteractiveShellApp.pylab',
108 )
117 )
109 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
118 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
110
119
@@ -118,9 +127,14 b' class InteractiveShellApp(Configurable):'
118 Provides configurables for loading extensions and executing files
127 Provides configurables for loading extensions and executing files
119 as part of configuring a Shell environment.
128 as part of configuring a Shell environment.
120
129
121 Provides init_path(), to be called before, and init_extensions() and
130 The following methods should be called by the :meth:`initialize` method
122 init_code() methods, to be called after init_shell(), which must be
131 of the subclass:
123 implemented by subclasses.
132
133 - :meth:`init_path`
134 - :meth:`init_shell` (to be implemented by the subclass)
135 - :meth:`init_gui_pylab`
136 - :meth:`init_extensions`
137 - :meth:`init_code`
124 """
138 """
125 extensions = List(Unicode, config=True,
139 extensions = List(Unicode, config=True,
126 help="A list of dotted module names of IPython extensions to load."
140 help="A list of dotted module names of IPython extensions to load."
@@ -151,6 +165,15 b' class InteractiveShellApp(Configurable):'
151 module_to_run = Unicode('', config=True,
165 module_to_run = Unicode('', config=True,
152 help="Run the module as a script."
166 help="Run the module as a script."
153 )
167 )
168 gui = CaselessStrEnum(('qt', 'wx', 'gtk', 'glut', 'pyglet'), config=True,
169 help="Enable GUI event loop integration ('qt', 'wx', 'gtk', 'glut', 'pyglet')."
170 )
171 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'],
172 config=True,
173 help="""Pre-load matplotlib and numpy for interactive use,
174 selecting a particular matplotlib backend and loop integration.
175 """
176 )
154 pylab_import_all = Bool(True, config=True,
177 pylab_import_all = Bool(True, config=True,
155 help="""If true, an 'import *' is done from numpy and pylab,
178 help="""If true, an 'import *' is done from numpy and pylab,
156 when using pylab"""
179 when using pylab"""
@@ -164,7 +187,25 b' class InteractiveShellApp(Configurable):'
164
187
165 def init_shell(self):
188 def init_shell(self):
166 raise NotImplementedError("Override in subclasses")
189 raise NotImplementedError("Override in subclasses")
167
190
191 def init_gui_pylab(self):
192 """Enable GUI event loop integration, taking pylab into account."""
193 if self.gui or self.pylab:
194 shell = self.shell
195 try:
196 if self.pylab:
197 gui, backend = pylabtools.find_gui_and_backend(self.pylab)
198 self.log.info("Enabling GUI event loop integration, "
199 "toolkit=%s, pylab=%s" % (gui, self.pylab))
200 shell.enable_pylab(gui, import_all=self.pylab_import_all)
201 else:
202 self.log.info("Enabling GUI event loop integration, "
203 "toolkit=%s" % self.gui)
204 shell.enable_gui(self.gui)
205 except Exception:
206 self.log.warn("GUI event loop or pylab initialization failed")
207 self.shell.showtraceback()
208
168 def init_extensions(self):
209 def init_extensions(self):
169 """Load all IPython extensions in IPythonApp.extensions.
210 """Load all IPython extensions in IPythonApp.extensions.
170
211
@@ -52,8 +52,6 b' flags = dict(flags)'
52 frontend_flags = dict(app_flags)
52 frontend_flags = dict(app_flags)
53 # add TerminalIPApp flags:
53 # add TerminalIPApp flags:
54 frontend_flags.update(term_flags)
54 frontend_flags.update(term_flags)
55 # pylab is not frontend-specific in two-process IPython
56 frontend_flags.pop('pylab')
57 # disable quick startup, as it won't propagate to the kernel anyway
55 # disable quick startup, as it won't propagate to the kernel anyway
58 frontend_flags.pop('quick')
56 frontend_flags.pop('quick')
59 # update full dict with frontend flags:
57 # update full dict with frontend flags:
@@ -171,22 +171,11 b" frontend_flags['i'] = ("
171 """If running code from the command line, become interactive afterwards.
171 """If running code from the command line, become interactive afterwards.
172 Note: can also be given simply as '-i.'"""
172 Note: can also be given simply as '-i.'"""
173 )
173 )
174 frontend_flags['pylab'] = (
175 {'TerminalIPythonApp' : {'pylab' : 'auto'}},
176 """Pre-load matplotlib and numpy for interactive use with
177 the default matplotlib backend."""
178 )
179 flags.update(frontend_flags)
174 flags.update(frontend_flags)
180
175
181 aliases = dict(base_aliases)
176 aliases = dict(base_aliases)
182 aliases.update(shell_aliases)
177 aliases.update(shell_aliases)
183
178
184 # it's possible we don't want short aliases for *all* of these:
185 aliases.update(dict(
186 gui='TerminalIPythonApp.gui',
187 pylab='TerminalIPythonApp.pylab',
188 ))
189
190 #-----------------------------------------------------------------------------
179 #-----------------------------------------------------------------------------
191 # Main classes and functions
180 # Main classes and functions
192 #-----------------------------------------------------------------------------
181 #-----------------------------------------------------------------------------
@@ -246,15 +235,6 b' class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):'
246 self.load_config_file = lambda *a, **kw: None
235 self.load_config_file = lambda *a, **kw: None
247 self.ignore_old_config=True
236 self.ignore_old_config=True
248
237
249 gui = CaselessStrEnum(('qt', 'wx', 'gtk', 'glut', 'pyglet'), config=True,
250 help="Enable GUI event loop integration ('qt', 'wx', 'gtk', 'glut', 'pyglet')."
251 )
252 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'auto'],
253 config=True,
254 help="""Pre-load matplotlib and numpy for interactive use,
255 selecting a particular matplotlib backend and loop integration.
256 """
257 )
258 display_banner = Bool(True, config=True,
238 display_banner = Bool(True, config=True,
259 help="Whether to display a banner upon starting IPython."
239 help="Whether to display a banner upon starting IPython."
260 )
240 )
@@ -344,34 +324,12 b' class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):'
344 # Make sure there is a space below the banner.
324 # Make sure there is a space below the banner.
345 if self.log_level <= logging.INFO: print
325 if self.log_level <= logging.INFO: print
346
326
347
327 def _pylab_changed(self, name, old, new):
348 def init_gui_pylab(self):
328 """Replace --pylab='inline' with --pylab='auto'"""
349 """Enable GUI event loop integration, taking pylab into account."""
329 if new == 'inline':
350 gui = self.gui
330 warn.warn("'inline' not available as pylab backend, "
351
331 "using 'auto' instead.\n")
352 # Using `pylab` will also require gui activation, though which toolkit
332 self.pylab = 'auto'
353 # to use may be chosen automatically based on mpl configuration.
354 if self.pylab:
355 activate = self.shell.enable_pylab
356 if self.pylab == 'auto':
357 gui = None
358 else:
359 gui = self.pylab
360 else:
361 # Enable only GUI integration, no pylab
362 activate = inputhook.enable_gui
363
364 if gui or self.pylab:
365 try:
366 self.log.info("Enabling GUI event loop integration, "
367 "toolkit=%s, pylab=%s" % (gui, self.pylab) )
368 if self.pylab:
369 activate(gui, import_all=self.pylab_import_all)
370 else:
371 activate(gui)
372 except:
373 self.log.warn("Error in enabling GUI event loop integration:")
374 self.shell.showtraceback()
375
333
376 def start(self):
334 def start(self):
377 if self.subapp is not None:
335 if self.subapp is not None:
@@ -35,7 +35,6 b' from zmq.eventloop import ioloop'
35 from zmq.eventloop.zmqstream import ZMQStream
35 from zmq.eventloop.zmqstream import ZMQStream
36
36
37 # Local imports
37 # Local imports
38 from IPython.core import pylabtools
39 from IPython.config.configurable import Configurable
38 from IPython.config.configurable import Configurable
40 from IPython.config.application import boolean_flag, catch_config_error
39 from IPython.config.application import boolean_flag, catch_config_error
41 from IPython.core.application import ProfileDir
40 from IPython.core.application import ProfileDir
@@ -772,12 +771,6 b" flags['pylab'] = ("
772 aliases = dict(kernel_aliases)
771 aliases = dict(kernel_aliases)
773 aliases.update(shell_aliases)
772 aliases.update(shell_aliases)
774
773
775 # it's possible we don't want short aliases for *all* of these:
776 aliases.update(dict(
777 gui='IPKernelApp.gui',
778 pylab='IPKernelApp.pylab',
779 ))
780
781 #-----------------------------------------------------------------------------
774 #-----------------------------------------------------------------------------
782 # The IPKernelApp class
775 # The IPKernelApp class
783 #-----------------------------------------------------------------------------
776 #-----------------------------------------------------------------------------
@@ -788,18 +781,7 b' class IPKernelApp(KernelApp, InteractiveShellApp):'
788 aliases = Dict(aliases)
781 aliases = Dict(aliases)
789 flags = Dict(flags)
782 flags = Dict(flags)
790 classes = [Kernel, ZMQInteractiveShell, ProfileDir, Session]
783 classes = [Kernel, ZMQInteractiveShell, ProfileDir, Session]
791
784
792 # configurables
793 gui = CaselessStrEnum(('qt', 'wx', 'gtk', 'glut', 'pyglet'), config=True,
794 help="Enable GUI event loop integration ('qt', 'wx', 'gtk', 'glut', 'pyglet')."
795 )
796 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'inline', 'auto'],
797 config=True,
798 help="""Pre-load matplotlib and numpy for interactive use,
799 selecting a particular matplotlib backend and loop integration.
800 """
801 )
802
803 @catch_config_error
785 @catch_config_error
804 def initialize(self, argv=None):
786 def initialize(self, argv=None):
805 super(IPKernelApp, self).initialize(argv)
787 super(IPKernelApp, self).initialize(argv)
@@ -826,36 +808,25 b' class IPKernelApp(KernelApp, InteractiveShellApp):'
826
808
827 def init_gui_pylab(self):
809 def init_gui_pylab(self):
828 """Enable GUI event loop integration, taking pylab into account."""
810 """Enable GUI event loop integration, taking pylab into account."""
829 if self.gui or self.pylab:
811
830 shell = self.shell
812 # Provide a wrapper for :meth:`InteractiveShellApp.init_gui_pylab`
831 try:
813 # to ensure that any exception is printed straight to stderr.
832 if self.pylab:
814 # Normally _showtraceback associates the reply with an execution,
833 gui, backend = pylabtools.find_gui_and_backend(self.pylab)
815 # which means frontends will never draw it, as this exception
834 shell.enable_pylab(gui, import_all=self.pylab_import_all)
816 # is not associated with any execute request.
835 else:
817
836 shell.enable_gui(self.gui)
818 shell = self.shell
837 except Exception:
819 _showtraceback = shell._showtraceback
838 self.log.error("GUI event loop or pylab initialization failed",
820 try:
839 exc_info=True)
821 # replace pyerr-sending traceback with stderr
840 # print exception straight to stdout, because normally
822 def print_tb(etype, evalue, stb):
841 # _showtraceback associates the reply with an execution,
823 print ("GUI event loop or pylab initialization failed",
842 # which means frontends will never draw it, as this exception
824 file=io.stderr)
843 # is not associated with any execute request.
825 print (shell.InteractiveTB.stb2text(stb), file=io.stderr)
844
826 shell._showtraceback = print_tb
845 # replace pyerr-sending traceback with stdout
827 InteractiveShellApp.init_gui_pylab(self)
846 _showtraceback = shell._showtraceback
828 finally:
847 def print_tb(etype, evalue, stb):
829 shell._showtraceback = _showtraceback
848 print ("GUI event loop or pylab initialization failed",
849 file=io.stderr)
850 print (shell.InteractiveTB.stb2text(stb), file=io.stdout)
851 shell._showtraceback = print_tb
852
853 # send the traceback over stdout
854 shell.showtraceback(tb_offset=0)
855
856 # restore proper _showtraceback method
857 shell._showtraceback = _showtraceback
858
859
830
860 def init_shell(self):
831 def init_shell(self):
861 self.shell = self.kernel.shell
832 self.shell = self.kernel.shell
General Comments 0
You need to be logged in to leave comments. Login now