##// END OF EJS Templates
First semi-complete support for -pylab and %pylab....
Fernando Perez -
Show More
@@ -0,0 +1,146 b''
1 # -*- coding: utf-8 -*-
2 """Pylab (matplotlib) support utilities.
3
4 Authors
5 -------
6 Fernando Perez.
7 """
8
9 #-----------------------------------------------------------------------------
10 # Copyright (C) 2009 The IPython Development Team
11 #
12 # Distributed under the terms of the BSD License. The full license is in
13 # the file COPYING, distributed as part of this software.
14 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Imports
17 #-----------------------------------------------------------------------------
18 from IPython.utils.genutils import flag_calls
19
20 #-----------------------------------------------------------------------------
21 # Main classes and functions
22 #-----------------------------------------------------------------------------
23
24 def pylab_activate(user_ns, gui=None, import_all=True):
25 """Activate pylab mode in the user's namespace.
26
27 Loads and initializes numpy, matplotlib and friends for interactive use.
28
29 Parameters
30 ----------
31 user_ns : dict
32 Namespace where the imports will occur.
33
34 gui : optional, string
35 A valid gui name following the conventions of the %gui magic.
36
37 import_all : optional, boolean
38 If true, an 'import *' is done from numpy and pylab.
39
40 Returns
41 -------
42 The actual gui used (if not given as input, it was obtained from matplotlib
43 itself, and will be needed next to configure IPython's gui integration.
44 """
45
46 # Initialize matplotlib to interactive mode always
47 import matplotlib
48
49 # If user specifies a GUI, that dictates the backend, otherwise we read the
50 # user's mpl default from the mpl rc structure
51 g2b = {'tk': 'TkAgg',
52 'gtk': 'GTKAgg',
53 'wx': 'WXAgg',
54 'qt': 'Qt4Agg', # qt3 not supported
55 'qt4': 'Qt4Agg' }
56
57 if gui:
58 # select backend based on requested gui
59 backend = g2b[gui]
60 else:
61 backend = matplotlib.rcParams['backend']
62 # In this case, we need to find what the appropriate gui selection call
63 # should be for IPython, so we can activate inputhook accordingly
64 b2g = dict(zip(g2b.values(),g2b.keys()))
65 gui = b2g[backend]
66
67 # We must set the desired backend before importing pylab
68 matplotlib.use(backend)
69
70 # This must be imported last in the matplotlib series, after
71 # backend/interactivity choices have been made
72 import matplotlib.pylab as pylab
73
74 # XXX For now leave this commented out, but depending on discussions with
75 # mpl-dev, we may be able to allow interactive switching...
76 #import matplotlib.pyplot
77 #matplotlib.pyplot.switch_backend(backend)
78
79 pylab.show._needmain = False
80 # We need to detect at runtime whether show() is called by the user.
81 # For this, we wrap it into a decorator which adds a 'called' flag.
82 pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
83
84 # Import numpy as np/pyplot as plt are conventions we're trying to
85 # somewhat standardize on. Making them available to users by default
86 # will greatly help this.
87 exec ("import numpy\n"
88 "import matplotlib\n"
89 "from matplotlib import pylab, mlab, pyplot\n"
90 "np = numpy\n"
91 "plt = pyplot\n"
92 ) in user_ns
93
94 if import_all:
95 exec("from matplotlib.pylab import *\n"
96 "from numpy import *\n") in user_ns
97
98 matplotlib.interactive(True)
99
100 print """
101 Welcome to pylab, a matplotlib-based Python environment.
102 Backend in use: %s
103 For more information, type 'help(pylab)'.""" % backend
104
105 return gui
106
107 # We need a little factory function here to create the closure where
108 # safe_execfile can live.
109 def mpl_runner(safe_execfile):
110 """Factory to return a matplotlib-enabled runner for %run.
111
112 Parameters
113 ----------
114 safe_execfile : function
115 This must be a function with the same interface as the
116 :meth:`safe_execfile` method of IPython.
117
118 Returns
119 -------
120 A function suitable for use as the ``runner`` argument of the %run magic
121 function.
122 """
123
124 def mpl_execfile(fname,*where,**kw):
125 """matplotlib-aware wrapper around safe_execfile.
126
127 Its interface is identical to that of the :func:`execfile` builtin.
128
129 This is ultimately a call to execfile(), but wrapped in safeties to
130 properly handle interactive rendering."""
131
132 import matplotlib
133 import matplotlib.pylab as pylab
134
135 #print '*** Matplotlib runner ***' # dbg
136 # turn off rendering until end of script
137 is_interactive = matplotlib.rcParams['interactive']
138 matplotlib.interactive(False)
139 safe_execfile(fname,*where,**kw)
140 matplotlib.interactive(is_interactive)
141 # make rendering call now, if the user tried to do it
142 if pylab.draw_if_interactive.called:
143 pylab.draw()
144 pylab.draw_if_interactive.called = False
145
146 return mpl_execfile
@@ -27,53 +27,30 b' Notes'
27 27 import logging
28 28 import os
29 29 import sys
30 import warnings
31 30
32 from IPython.core.application import Application, BaseAppArgParseConfigLoader
33 31 from IPython.core import release
32 from IPython.core.application import Application, BaseAppArgParseConfigLoader
33 from IPython.core.error import UsageError
34 34 from IPython.core.iplib import InteractiveShell
35 from IPython.core.pylabtools import pylab_activate
35 36 from IPython.config.loader import (
36 37 NoConfigDefault,
37 38 Config,
38 39 PyFileConfigLoader
39 40 )
40
41 41 from IPython.lib import inputhook
42
43 42 from IPython.utils.genutils import filefind, get_ipython_dir
44 43
45 44 #-----------------------------------------------------------------------------
46 45 # Utilities and helpers
47 46 #-----------------------------------------------------------------------------
48 47
49
50 48 ipython_desc = """
51 49 A Python shell with automatic history (input and output), dynamic object
52 50 introspection, easier configuration, command completion, access to the system
53 51 shell and more.
54 52 """
55 53
56 def pylab_warning():
57 msg = """
58
59 IPython's -pylab mode has been disabled until matplotlib supports this version
60 of IPython. This version of IPython has greatly improved GUI integration that
61 matplotlib will soon be able to take advantage of. This will eventually
62 result in greater stability and a richer API for matplotlib under IPython.
63 However during this transition, you will either need to use an older version
64 of IPython, or do the following to use matplotlib interactively::
65
66 import matplotlib
67 matplotlib.interactive(True)
68 matplotlib.use('wxagg') # adjust for your backend
69 %gui -a wx # adjust for your GUI
70 from matplotlib import pyplot as plt
71
72 See the %gui magic for information on the new interface.
73 """
74 warnings.warn(msg, category=DeprecationWarning, stacklevel=1)
75
76
77 54 #-----------------------------------------------------------------------------
78 55 # Main classes and functions
79 56 #-----------------------------------------------------------------------------
@@ -267,23 +244,21 b' cl_args = ('
267 244 action='store_true', dest='Global.force_interact', default=NoConfigDefault,
268 245 help="If running code from the command line, become interactive afterwards.")
269 246 ),
270 (('--wthread',), dict(
247 (('--wthread','-wthread'), dict(
271 248 action='store_true', dest='Global.wthread', default=NoConfigDefault,
272 249 help="Enable wxPython event loop integration.")
273 250 ),
274 (('--q4thread','--qthread'), dict(
251 (('--q4thread','--qthread','-q4thread','-qthread'), dict(
275 252 action='store_true', dest='Global.q4thread', default=NoConfigDefault,
276 253 help="Enable Qt4 event loop integration. Qt3 is no longer supported.")
277 254 ),
278 (('--gthread',), dict(
255 (('--gthread','-gthread'), dict(
279 256 action='store_true', dest='Global.gthread', default=NoConfigDefault,
280 257 help="Enable GTK event loop integration.")
281 258 ),
282 # # These are only here to get the proper deprecation warnings
283 259 (('--pylab',), dict(
284 260 action='store_true', dest='Global.pylab', default=NoConfigDefault,
285 help="Disabled. Pylab has been disabled until matplotlib "
286 "supports this version of IPython.")
261 help="Pre-load matplotlib and numpy for interactive use.")
287 262 )
288 263 )
289 264
@@ -341,6 +316,9 b' class IPythonApp(Application):'
341 316 Global.q4thread = False
342 317 Global.gthread = False
343 318
319 # Pylab off by default
320 Global.pylab = False
321
344 322 def create_command_line_config(self):
345 323 """Create and return a command line config loader."""
346 324 return IPythonAppCLConfigLoader(
@@ -348,14 +326,6 b' class IPythonApp(Application):'
348 326 version=release.version
349 327 )
350 328
351 def post_load_command_line_config(self):
352 """Do actions after loading cl config."""
353 clc = self.command_line_config
354
355 # Display the deprecation warnings about threaded shells
356 if hasattr(clc.Global, 'pylab'):
357 pylab_warning()
358 del clc.Global['pylab']
359 329
360 330 def load_file_config(self):
361 331 if hasattr(self.command_line_config.Global, 'quick'):
@@ -433,30 +403,44 b' class IPythonApp(Application):'
433 403 if self.log_level <= logging.INFO: print
434 404
435 405 # Now a variety of things that happen after the banner is printed.
436 self._enable_gui()
406 self._enable_gui_pylab()
437 407 self._load_extensions()
438 408 self._run_exec_lines()
439 409 self._run_exec_files()
440 410 self._run_cmd_line_code()
411 self._configure_xmode()
412
413 def _enable_gui_pylab(self):
414 """Enable GUI event loop integration, taking pylab into account."""
415 Global = self.master_config.Global
416
417 # Select which gui to use
418 if Global.wthread:
419 gui = inputhook.GUI_WX
420 elif Global.q4thread:
421 gui = inputhook.GUI_QT
422 elif Global.gthread:
423 gui = inputhook.GUI_GTK
424 else:
425 gui = None
441 426
442 def _enable_gui(self):
443 """Enable GUI event loop integration."""
444 config = self.master_config
427 if Global.pylab:
428 activate = self.shell.enable_pylab
429 else:
430 # Enable only GUI integration, no pylab
431 activate = inputhook.enable_gui
432
433 if gui or Global.pylab:
445 434 try:
446 # Enable GUI integration
447 if config.Global.wthread:
448 self.log.info("Enabling wx GUI event loop integration")
449 inputhook.enable_wx(app=True)
450 elif config.Global.q4thread:
451 self.log.info("Enabling Qt4 GUI event loop integration")
452 inputhook.enable_qt4(app=True)
453 elif config.Global.gthread:
454 self.log.info("Enabling GTK GUI event loop integration")
455 inputhook.enable_gtk(app=True)
435 m = "Enabling GUI event loop integration, toolkit=%s, pylab=%s"\
436 % (gui, Global.pylab)
437 self.log.info(m)
438 activate(gui)
456 439 except:
457 440 self.log.warn("Error in enabling GUI event loop integration:")
458 441 self.shell.showtraceback()
459 442
443
460 444 def _load_extensions(self):
461 445 """Load all IPython extensions in Global.extensions.
462 446
@@ -540,12 +524,18 b' class IPythonApp(Application):'
540 524 self.log.warn("Error in executing file in user namespace: %s" % fname)
541 525 self.shell.showtraceback()
542 526
527 def _configure_xmode(self):
528 # XXX - shouldn't this be read from the config? I'm still a little
529 # lost with all the details of handling the new config guys...
530 self.shell.InteractiveTB.set_mode(mode=self.shell.xmode)
531
543 532 def start_app(self):
544 533 if self.master_config.Global.interact:
545 534 self.log.debug("Starting IPython's mainloop...")
546 535 self.shell.mainloop()
547 536
548 537
538
549 539 def load_default_config(ipython_dir=None):
550 540 """Load the default config file from the default ipython_dir.
551 541
@@ -31,34 +31,37 b' import sys'
31 31 import tempfile
32 32 from contextlib import nested
33 33
34 from IPython.core import ultratb
35 34 from IPython.core import debugger, oinspect
36 from IPython.core import shadowns
37 35 from IPython.core import history as ipcorehist
38 36 from IPython.core import prefilter
37 from IPython.core import shadowns
38 from IPython.core import ultratb
39 39 from IPython.core.alias import AliasManager
40 40 from IPython.core.builtin_trap import BuiltinTrap
41 from IPython.core.component import Component
41 42 from IPython.core.display_trap import DisplayTrap
43 from IPython.core.error import TryNext, UsageError
42 44 from IPython.core.fakemodule import FakeModule, init_fakemod_dict
43 45 from IPython.core.logger import Logger
44 46 from IPython.core.magic import Magic
45 from IPython.core.prompts import CachedOutput
46 47 from IPython.core.prefilter import PrefilterManager
47 from IPython.core.component import Component
48 from IPython.core.prompts import CachedOutput
49 from IPython.core.pylabtools import pylab_activate
48 50 from IPython.core.usage import interactive_usage, default_banner
49 from IPython.core.error import TryNext, UsageError
50
51 from IPython.utils import pickleshare
52 51 from IPython.external.Itpl import ItplNS
52 from IPython.lib.inputhook import enable_gui
53 53 from IPython.lib.backgroundjobs import BackgroundJobManager
54 from IPython.utils.ipstruct import Struct
55 54 from IPython.utils import PyColorize
56 from IPython.utils.genutils import *
55 from IPython.utils import pickleshare
57 56 from IPython.utils.genutils import get_ipython_dir
57 from IPython.utils.ipstruct import Struct
58 58 from IPython.utils.platutils import toggle_set_term_title, set_term_title
59 59 from IPython.utils.strdispatch import StrDispatch
60 60 from IPython.utils.syspathcontext import prepended_to_syspath
61 61
62 # XXX - need to clean up this import * line
63 from IPython.utils.genutils import *
64
62 65 # from IPython.utils import growl
63 66 # growl.start("IPython")
64 67
@@ -70,7 +73,6 b' from IPython.utils.traitlets import ('
70 73 # Globals
71 74 #-----------------------------------------------------------------------------
72 75
73
74 76 # store the builtin raw_input globally, and use this always, in case user code
75 77 # overwrites it (like wx.py.PyShell does)
76 78 raw_input_original = raw_input
@@ -78,12 +80,10 b' raw_input_original = raw_input'
78 80 # compiled regexps for autoindent management
79 81 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
80 82
81
82 83 #-----------------------------------------------------------------------------
83 84 # Utilities
84 85 #-----------------------------------------------------------------------------
85 86
86
87 87 ini_spaces_re = re.compile(r'^(\s+)')
88 88
89 89
@@ -2445,6 +2445,18 b' class InteractiveShell(Component, Magic):'
2445 2445 return ask_yes_no(prompt,default)
2446 2446
2447 2447 #-------------------------------------------------------------------------
2448 # Things related to GUI support and pylab
2449 #-------------------------------------------------------------------------
2450
2451 def enable_pylab(self, gui=None):
2452 """
2453 """
2454 gui = pylab_activate(self.user_ns, gui)
2455 enable_gui(gui)
2456 self.magic_run = self._pylab_magic_run
2457
2458
2459 #-------------------------------------------------------------------------
2448 2460 # Things related to IPython exiting
2449 2461 #-------------------------------------------------------------------------
2450 2462
@@ -44,21 +44,26 b' except ImportError:'
44 44
45 45 # Homebrewed
46 46 import IPython
47 from IPython.utils import wildcard
47 import IPython.utils.generics
48
48 49 from IPython.core import debugger, oinspect
49 50 from IPython.core.error import TryNext
51 from IPython.core.error import UsageError
50 52 from IPython.core.fakemodule import FakeModule
53 from IPython.core.macro import Macro
54 from IPython.core.page import page
51 55 from IPython.core.prefilter import ESC_MAGIC
56 from IPython.core.pylabtools import mpl_runner
57 from IPython.lib.inputhook import enable_gui
52 58 from IPython.external.Itpl import Itpl, itpl, printpl,itplns
59 from IPython.testing import decorators as testdec
60 from IPython.utils import platutils
61 from IPython.utils import wildcard
53 62 from IPython.utils.PyColorize import Parser
54 63 from IPython.utils.ipstruct import Struct
55 from IPython.core.macro import Macro
64
65 # XXX - We need to switch to explicit imports here with genutils
56 66 from IPython.utils.genutils import *
57 from IPython.core.page import page
58 from IPython.utils import platutils
59 import IPython.utils.generics
60 from IPython.core.error import UsageError
61 from IPython.testing import decorators as testdec
62 67
63 68 #***************************************************************************
64 69 # Utility functions
@@ -82,130 +87,6 b' def compress_dhist(dh):'
82 87 return newhead + tail
83 88
84 89
85 def pylab_activate(user_ns, gui=None, import_all=True):
86 """Activate pylab mode in the user's namespace.
87
88 Loads and initializes numpy, matplotlib and friends for interactive use.
89
90 Parameters
91 ----------
92 user_ns : dict
93 Namespace where the imports will occur.
94
95 gui : optional, string
96 A valid gui name following the conventions of the %gui magic.
97
98 import_all : optional, boolean
99 If true, an 'import *' is done from numpy and pylab.
100
101 Returns
102 -------
103 The actual gui used (if not given as input, it was obtained from matplotlib
104 itself, and will be needed next to configure IPython's gui integration.
105 """
106
107 # Initialize matplotlib to interactive mode always
108 import matplotlib
109
110 # If user specifies a GUI, that dictates the backend, otherwise we read the
111 # user's mpl default from the mpl rc structure
112 g2b = {'tk': 'TkAgg',
113 'gtk': 'GTKAgg',
114 'wx': 'WXAgg',
115 'qt': 'Qt4Agg', # qt3 not supported
116 'qt4': 'Qt4Agg' }
117
118 if gui:
119 # select backend based on requested gui
120 backend = g2b[gui]
121 else:
122 backend = matplotlib.rcParams['backend']
123 # In this case, we need to find what the appropriate gui selection call
124 # should be for IPython, so we can activate inputhook accordingly
125 b2g = dict(zip(g2b.values(),g2b.keys()))
126 gui = b2g[backend]
127
128 # We must set the desired backend before importing pylab
129 matplotlib.use(backend)
130
131 # This must be imported last in the matplotlib series, after
132 # backend/interactivity choices have been made
133 import matplotlib.pylab as pylab
134
135 # XXX For now leave this commented out, but depending on discussions with
136 # mpl-dev, we may be able to allow interactive switching...
137 #import matplotlib.pyplot
138 #matplotlib.pyplot.switch_backend(backend)
139
140 pylab.show._needmain = False
141 # We need to detect at runtime whether show() is called by the user.
142 # For this, we wrap it into a decorator which adds a 'called' flag.
143 pylab.draw_if_interactive = flag_calls(pylab.draw_if_interactive)
144
145 # Import numpy as np/pyplot as plt are conventions we're trying to
146 # somewhat standardize on. Making them available to users by default
147 # will greatly help this.
148 exec ("import numpy\n"
149 "import numpy as np\n"
150 "import matplotlib\n"
151 "from matplotlib import pylab, mlab, pyplot as plt\n"
152 ) in user_ns
153
154 if import_all:
155 exec("from matplotlib.pylab import *\n"
156 "from numpy import *\n") in user_ns
157
158 matplotlib.interactive(True)
159
160 print """
161 Welcome to pylab, a matplotlib-based Python environment.
162 Backend in use: %s
163 For more information, type 'help(pylab)'.""" % backend
164
165 return gui
166
167 # We need a little factory function here to create the closure where
168 # safe_execfile can live.
169 def mpl_runner(safe_execfile):
170 """Factory to return a matplotlib-enabled runner for %run.
171
172 Parameters
173 ----------
174 safe_execfile : function
175 This must be a function with the same interface as the
176 :meth:`safe_execfile` method of IPython.
177
178 Returns
179 -------
180 A function suitable for use as the ``runner`` argument of the %run magic
181 function.
182 """
183
184 def mpl_execfile(fname,*where,**kw):
185 """matplotlib-aware wrapper around safe_execfile.
186
187 Its interface is identical to that of the :func:`execfile` builtin.
188
189 This is ultimately a call to execfile(), but wrapped in safeties to
190 properly handle interactive rendering."""
191
192 import matplotlib
193 import matplotlib.pylab as pylab
194
195 #print '*** Matplotlib runner ***' # dbg
196 # turn off rendering until end of script
197 is_interactive = matplotlib.rcParams['interactive']
198 matplotlib.interactive(False)
199 safe_execfile(fname,*where,**kw)
200 matplotlib.interactive(is_interactive)
201 # make rendering call now, if the user tried to do it
202 if pylab.draw_if_interactive.called:
203 pylab.draw()
204 pylab.draw_if_interactive.called = False
205
206 return mpl_execfile
207
208
209 90 #***************************************************************************
210 91 # Main class implementing Magic functionality
211 92
@@ -3624,26 +3505,9 b' Defaulting color scheme to \'NoColor\'"""'
3624 3505
3625 3506 This is highly recommended for most users.
3626 3507 """
3627 from IPython.lib import inputhook
3628
3629 3508 opts, arg = self.parse_options(parameter_s,'a')
3630 if not arg:
3631 inputhook.clear_inputhook()
3632 return
3633
3634 guis = {'tk': inputhook.enable_tk,
3635 'gtk':inputhook.enable_gtk,
3636 'wx': inputhook.enable_wx,
3637 'qt': inputhook.enable_qt4, # qt3 not supported
3638 'qt4': inputhook.enable_qt4 }
3639 try:
3640 gui = guis[arg]
3641 except KeyError:
3642 e="Invalid GUI request %r, valid ones are:%s" % (arg, guis.keys())
3643 raise UsageError(e)
3644
3645 #print 'Switching IPython gui support to:', arg, 'a' in opts # dbg
3646 return gui('a' in opts)
3509 if arg=='': arg = None
3510 return enable_gui(arg, 'a' in opts)
3647 3511
3648 3512 def magic_load_ext(self, module_str):
3649 3513 """Load an IPython extension by its module name."""
@@ -3757,9 +3621,6 b' Defaulting color scheme to \'NoColor\'"""'
3757 3621 Backend in use: Qt4Agg
3758 3622 For more information, type 'help(pylab)'.
3759 3623 """
3760
3761 gui = pylab_activate(self.shell.user_ns, s)
3762 self.shell.magic_gui('-a %s' % gui)
3763 self.shell.magic_run = self._pylab_magic_run
3624 self.shell.enable_pylab(s)
3764 3625
3765 3626 # end Magic
@@ -1,5 +1,5 b''
1 1 #!/usr/bin/env python
2 # encoding: utf-8
2 # coding: utf-8
3 3 """
4 4 Inputhook management for GUI event loop integration.
5 5 """
@@ -24,6 +24,7 b' import sys'
24 24
25 25 # Constants for identifying the GUI toolkits.
26 26 GUI_WX = 'wx'
27 GUI_QT = 'qt'
27 28 GUI_QT4 = 'qt4'
28 29 GUI_GTK = 'gtk'
29 30 GUI_TK = 'tk'
@@ -326,8 +327,17 b' class InputHookManager(object):'
326 327 self._installed = True
327 328 return original
328 329
329 def clear_inputhook(self):
330 """Set PyOS_InputHook to NULL and return the previous one."""
330 def clear_inputhook(self, app=None):
331 """Set PyOS_InputHook to NULL and return the previous one.
332
333 Parameters
334 ----------
335 app : optional, ignored
336 This parameter is allowed only so that clear_inputhook() can be
337 called with a similar interface as all the ``enable_*`` methods. But
338 the actual value of the parameter is ignored. This uniform interface
339 makes it easier to have user-level entry points in the main IPython
340 app like :meth:`enable_gui`."""
331 341 pyos_inputhook_ptr = self.get_pyos_inputhook()
332 342 original = self.get_pyos_inputhook_as_func()
333 343 pyos_inputhook_ptr.value = ctypes.c_void_p(None).value
@@ -523,3 +533,39 b' set_inputhook = inputhook_manager.set_inputhook'
523 533 current_gui = inputhook_manager.current_gui
524 534 clear_app_refs = inputhook_manager.clear_app_refs
525 535 spin = inputhook_manager.spin
536
537
538 # Convenience function to switch amongst them
539 def enable_gui(gui=None, app=True):
540 """Switch amongst GUI input hooks by name.
541
542 This is just a utility wrapper around the methods of the InputHookManager
543 object.
544
545 Parameters
546 ----------
547 gui : optional, string or None
548 If None, clears input hook, otherwise it must be one of the recognized
549 GUI names (see ``GUI_*`` constants in module).
550
551 app : optional, bool
552 If true, create an app object and return it.
553
554 Returns
555 -------
556 The output of the underlying gui switch routine, typically the actual
557 PyOS_InputHook wrapper object or the GUI toolkit app created, if there was
558 one.
559 """
560 guis = {None: clear_inputhook,
561 GUI_TK: enable_tk,
562 GUI_GTK: enable_gtk,
563 GUI_WX: enable_wx,
564 GUI_QT: enable_qt4, # qt3 not supported
565 GUI_QT4: enable_qt4 }
566 try:
567 gui_hook = guis[gui]
568 except KeyError:
569 e="Invalid GUI request %r, valid ones are:%s" % (gui, guis.keys())
570 raise ValueError(e)
571 return gui_hook(app)
General Comments 0
You need to be logged in to leave comments. Login now