##// END OF EJS Templates
Merge pull request #660 from minrk/i658...
Min RK -
r4464:d932a915 merge
parent child Browse files
Show More
@@ -1,426 +1,427 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 A base class for a configurable application.
3 A base class for a configurable application.
4
4
5 Authors:
5 Authors:
6
6
7 * Brian Granger
7 * Brian Granger
8 * Min RK
8 * Min RK
9 """
9 """
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Copyright (C) 2008-2011 The IPython Development Team
12 # Copyright (C) 2008-2011 The IPython Development Team
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is in
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
15 # the file COPYING, distributed as part of this software.
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 import logging
22 import logging
23 import os
23 import os
24 import re
24 import re
25 import sys
25 import sys
26 from copy import deepcopy
26 from copy import deepcopy
27
27
28 from IPython.config.configurable import SingletonConfigurable
28 from IPython.config.configurable import SingletonConfigurable
29 from IPython.config.loader import (
29 from IPython.config.loader import (
30 KeyValueConfigLoader, PyFileConfigLoader, Config, ArgumentError
30 KeyValueConfigLoader, PyFileConfigLoader, Config, ArgumentError
31 )
31 )
32
32
33 from IPython.utils.traitlets import (
33 from IPython.utils.traitlets import (
34 Unicode, List, Int, Enum, Dict, Instance, TraitError
34 Unicode, List, Int, Enum, Dict, Instance, TraitError
35 )
35 )
36 from IPython.utils.importstring import import_item
36 from IPython.utils.importstring import import_item
37 from IPython.utils.text import indent, wrap_paragraphs, dedent
37 from IPython.utils.text import indent, wrap_paragraphs, dedent
38
38
39 #-----------------------------------------------------------------------------
39 #-----------------------------------------------------------------------------
40 # function for re-wrapping a helpstring
40 # function for re-wrapping a helpstring
41 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
42
42
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44 # Descriptions for the various sections
44 # Descriptions for the various sections
45 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
46
46
47 # merge flags&aliases into options
47 # merge flags&aliases into options
48 option_description = """
48 option_description = """
49 IPython command-line arguments are passed as '--<flag>', or '--<name>=<value>'.
49 IPython command-line arguments are passed as '--<flag>', or '--<name>=<value>'.
50
50
51 Arguments that take values are actually convenience aliases to full
51 Arguments that take values are actually convenience aliases to full
52 Configurables, whose aliases are listed on the help line. For more information
52 Configurables, whose aliases are listed on the help line. For more information
53 on full configurables, see '--help-all'.
53 on full configurables, see '--help-all'.
54 """.strip() # trim newlines of front and back
54 """.strip() # trim newlines of front and back
55
55
56 keyvalue_description = """
56 keyvalue_description = """
57 Parameters are set from command-line arguments of the form:
57 Parameters are set from command-line arguments of the form:
58 `--Class.trait=value`.
58 `--Class.trait=value`.
59 This line is evaluated in Python, so simple expressions are allowed, e.g.::
59 This line is evaluated in Python, so simple expressions are allowed, e.g.::
60 `--C.a='range(3)'` For setting C.a=[0,1,2].
60 `--C.a='range(3)'` For setting C.a=[0,1,2].
61 """.strip() # trim newlines of front and back
61 """.strip() # trim newlines of front and back
62
62
63 subcommand_description = """
63 subcommand_description = """
64 Subcommands are launched as `{app} cmd [args]`. For information on using
64 Subcommands are launched as `{app} cmd [args]`. For information on using
65 subcommand 'cmd', do: `{app} cmd -h`.
65 subcommand 'cmd', do: `{app} cmd -h`.
66 """.strip().format(app=os.path.basename(sys.argv[0]))
66 """.strip().format(app=os.path.basename(sys.argv[0]))
67 # get running program name
67 # get running program name
68
68
69 #-----------------------------------------------------------------------------
69 #-----------------------------------------------------------------------------
70 # Application class
70 # Application class
71 #-----------------------------------------------------------------------------
71 #-----------------------------------------------------------------------------
72
72
73
73
74 class ApplicationError(Exception):
74 class ApplicationError(Exception):
75 pass
75 pass
76
76
77
77
78 class Application(SingletonConfigurable):
78 class Application(SingletonConfigurable):
79 """A singleton application with full configuration support."""
79 """A singleton application with full configuration support."""
80
80
81 # The name of the application, will usually match the name of the command
81 # The name of the application, will usually match the name of the command
82 # line application
82 # line application
83 name = Unicode(u'application')
83 name = Unicode(u'application')
84
84
85 # The description of the application that is printed at the beginning
85 # The description of the application that is printed at the beginning
86 # of the help.
86 # of the help.
87 description = Unicode(u'This is an application.')
87 description = Unicode(u'This is an application.')
88 # default section descriptions
88 # default section descriptions
89 option_description = Unicode(option_description)
89 option_description = Unicode(option_description)
90 keyvalue_description = Unicode(keyvalue_description)
90 keyvalue_description = Unicode(keyvalue_description)
91 subcommand_description = Unicode(subcommand_description)
91 subcommand_description = Unicode(subcommand_description)
92
92
93 # The usage and example string that goes at the end of the help string.
93 # The usage and example string that goes at the end of the help string.
94 examples = Unicode()
94 examples = Unicode()
95
95
96 # A sequence of Configurable subclasses whose config=True attributes will
96 # A sequence of Configurable subclasses whose config=True attributes will
97 # be exposed at the command line.
97 # be exposed at the command line.
98 classes = List([])
98 classes = List([])
99
99
100 # The version string of this application.
100 # The version string of this application.
101 version = Unicode(u'0.0')
101 version = Unicode(u'0.0')
102
102
103 # The log level for the application
103 # The log level for the application
104 log_level = Enum((0,10,20,30,40,50,'DEBUG','INFO','WARN','ERROR','CRITICAL'),
104 log_level = Enum((0,10,20,30,40,50,'DEBUG','INFO','WARN','ERROR','CRITICAL'),
105 default_value=logging.WARN,
105 default_value=logging.WARN,
106 config=True,
106 config=True,
107 help="Set the log level by value or name.")
107 help="Set the log level by value or name.")
108 def _log_level_changed(self, name, old, new):
108 def _log_level_changed(self, name, old, new):
109 """Adjust the log level when log_level is set."""
109 """Adjust the log level when log_level is set."""
110 if isinstance(new, basestring):
110 if isinstance(new, basestring):
111 new = getattr(logging, new)
111 new = getattr(logging, new)
112 self.log_level = new
112 self.log_level = new
113 self.log.setLevel(new)
113 self.log.setLevel(new)
114
114
115 # the alias map for configurables
115 # the alias map for configurables
116 aliases = Dict({'log-level' : 'Application.log_level'})
116 aliases = Dict({'log-level' : 'Application.log_level'})
117
117
118 # flags for loading Configurables or store_const style flags
118 # flags for loading Configurables or store_const style flags
119 # flags are loaded from this dict by '--key' flags
119 # flags are loaded from this dict by '--key' flags
120 # this must be a dict of two-tuples, the first element being the Config/dict
120 # this must be a dict of two-tuples, the first element being the Config/dict
121 # and the second being the help string for the flag
121 # and the second being the help string for the flag
122 flags = Dict()
122 flags = Dict()
123 def _flags_changed(self, name, old, new):
123 def _flags_changed(self, name, old, new):
124 """ensure flags dict is valid"""
124 """ensure flags dict is valid"""
125 for key,value in new.iteritems():
125 for key,value in new.iteritems():
126 assert len(value) == 2, "Bad flag: %r:%s"%(key,value)
126 assert len(value) == 2, "Bad flag: %r:%s"%(key,value)
127 assert isinstance(value[0], (dict, Config)), "Bad flag: %r:%s"%(key,value)
127 assert isinstance(value[0], (dict, Config)), "Bad flag: %r:%s"%(key,value)
128 assert isinstance(value[1], basestring), "Bad flag: %r:%s"%(key,value)
128 assert isinstance(value[1], basestring), "Bad flag: %r:%s"%(key,value)
129
129
130
130
131 # subcommands for launching other applications
131 # subcommands for launching other applications
132 # if this is not empty, this will be a parent Application
132 # if this is not empty, this will be a parent Application
133 # this must be a dict of two-tuples,
133 # this must be a dict of two-tuples,
134 # the first element being the application class/import string
134 # the first element being the application class/import string
135 # and the second being the help string for the subcommand
135 # and the second being the help string for the subcommand
136 subcommands = Dict()
136 subcommands = Dict()
137 # parse_command_line will initialize a subapp, if requested
137 # parse_command_line will initialize a subapp, if requested
138 subapp = Instance('IPython.config.application.Application', allow_none=True)
138 subapp = Instance('IPython.config.application.Application', allow_none=True)
139
139
140 # extra command-line arguments that don't set config values
140 # extra command-line arguments that don't set config values
141 extra_args = List(Unicode)
141 extra_args = List(Unicode)
142
142
143
143
144 def __init__(self, **kwargs):
144 def __init__(self, **kwargs):
145 SingletonConfigurable.__init__(self, **kwargs)
145 SingletonConfigurable.__init__(self, **kwargs)
146 # Add my class to self.classes so my attributes appear in command line
146 # Ensure my class is in self.classes, so my attributes appear in command line
147 # options.
147 # options and config files.
148 self.classes.insert(0, self.__class__)
148 if self.__class__ not in self.classes:
149 self.classes.insert(0, self.__class__)
149
150
150 self.init_logging()
151 self.init_logging()
151
152
152 def _config_changed(self, name, old, new):
153 def _config_changed(self, name, old, new):
153 SingletonConfigurable._config_changed(self, name, old, new)
154 SingletonConfigurable._config_changed(self, name, old, new)
154 self.log.debug('Config changed:')
155 self.log.debug('Config changed:')
155 self.log.debug(repr(new))
156 self.log.debug(repr(new))
156
157
157 def init_logging(self):
158 def init_logging(self):
158 """Start logging for this application.
159 """Start logging for this application.
159
160
160 The default is to log to stdout using a StreaHandler. The log level
161 The default is to log to stdout using a StreaHandler. The log level
161 starts at loggin.WARN, but this can be adjusted by setting the
162 starts at loggin.WARN, but this can be adjusted by setting the
162 ``log_level`` attribute.
163 ``log_level`` attribute.
163 """
164 """
164 self.log = logging.getLogger(self.__class__.__name__)
165 self.log = logging.getLogger(self.__class__.__name__)
165 self.log.setLevel(self.log_level)
166 self.log.setLevel(self.log_level)
166 if sys.executable.endswith('pythonw.exe'):
167 if sys.executable.endswith('pythonw.exe'):
167 # this should really go to a file, but file-logging is only
168 # this should really go to a file, but file-logging is only
168 # hooked up in parallel applications
169 # hooked up in parallel applications
169 self._log_handler = logging.StreamHandler(open(os.devnull, 'w'))
170 self._log_handler = logging.StreamHandler(open(os.devnull, 'w'))
170 else:
171 else:
171 self._log_handler = logging.StreamHandler()
172 self._log_handler = logging.StreamHandler()
172 self._log_formatter = logging.Formatter("[%(name)s] %(message)s")
173 self._log_formatter = logging.Formatter("[%(name)s] %(message)s")
173 self._log_handler.setFormatter(self._log_formatter)
174 self._log_handler.setFormatter(self._log_formatter)
174 self.log.addHandler(self._log_handler)
175 self.log.addHandler(self._log_handler)
175
176
176 def initialize(self, argv=None):
177 def initialize(self, argv=None):
177 """Do the basic steps to configure me.
178 """Do the basic steps to configure me.
178
179
179 Override in subclasses.
180 Override in subclasses.
180 """
181 """
181 self.parse_command_line(argv)
182 self.parse_command_line(argv)
182
183
183
184
184 def start(self):
185 def start(self):
185 """Start the app mainloop.
186 """Start the app mainloop.
186
187
187 Override in subclasses.
188 Override in subclasses.
188 """
189 """
189 if self.subapp is not None:
190 if self.subapp is not None:
190 return self.subapp.start()
191 return self.subapp.start()
191
192
192 def print_alias_help(self):
193 def print_alias_help(self):
193 """Print the alias part of the help."""
194 """Print the alias part of the help."""
194 if not self.aliases:
195 if not self.aliases:
195 return
196 return
196
197
197 lines = []
198 lines = []
198 classdict = {}
199 classdict = {}
199 for cls in self.classes:
200 for cls in self.classes:
200 # include all parents (up to, but excluding Configurable) in available names
201 # include all parents (up to, but excluding Configurable) in available names
201 for c in cls.mro()[:-3]:
202 for c in cls.mro()[:-3]:
202 classdict[c.__name__] = c
203 classdict[c.__name__] = c
203
204
204 for alias, longname in self.aliases.iteritems():
205 for alias, longname in self.aliases.iteritems():
205 classname, traitname = longname.split('.',1)
206 classname, traitname = longname.split('.',1)
206 cls = classdict[classname]
207 cls = classdict[classname]
207
208
208 trait = cls.class_traits(config=True)[traitname]
209 trait = cls.class_traits(config=True)[traitname]
209 help = cls.class_get_trait_help(trait).splitlines()
210 help = cls.class_get_trait_help(trait).splitlines()
210 # reformat first line
211 # reformat first line
211 help[0] = help[0].replace(longname, alias) + ' (%s)'%longname
212 help[0] = help[0].replace(longname, alias) + ' (%s)'%longname
212 lines.extend(help)
213 lines.extend(help)
213 # lines.append('')
214 # lines.append('')
214 print os.linesep.join(lines)
215 print os.linesep.join(lines)
215
216
216 def print_flag_help(self):
217 def print_flag_help(self):
217 """Print the flag part of the help."""
218 """Print the flag part of the help."""
218 if not self.flags:
219 if not self.flags:
219 return
220 return
220
221
221 lines = []
222 lines = []
222 for m, (cfg,help) in self.flags.iteritems():
223 for m, (cfg,help) in self.flags.iteritems():
223 lines.append('--'+m)
224 lines.append('--'+m)
224 lines.append(indent(dedent(help.strip())))
225 lines.append(indent(dedent(help.strip())))
225 # lines.append('')
226 # lines.append('')
226 print os.linesep.join(lines)
227 print os.linesep.join(lines)
227
228
228 def print_options(self):
229 def print_options(self):
229 if not self.flags and not self.aliases:
230 if not self.flags and not self.aliases:
230 return
231 return
231 lines = ['Options']
232 lines = ['Options']
232 lines.append('-'*len(lines[0]))
233 lines.append('-'*len(lines[0]))
233 lines.append('')
234 lines.append('')
234 for p in wrap_paragraphs(self.option_description):
235 for p in wrap_paragraphs(self.option_description):
235 lines.append(p)
236 lines.append(p)
236 lines.append('')
237 lines.append('')
237 print os.linesep.join(lines)
238 print os.linesep.join(lines)
238 self.print_flag_help()
239 self.print_flag_help()
239 self.print_alias_help()
240 self.print_alias_help()
240 print
241 print
241
242
242 def print_subcommands(self):
243 def print_subcommands(self):
243 """Print the subcommand part of the help."""
244 """Print the subcommand part of the help."""
244 if not self.subcommands:
245 if not self.subcommands:
245 return
246 return
246
247
247 lines = ["Subcommands"]
248 lines = ["Subcommands"]
248 lines.append('-'*len(lines[0]))
249 lines.append('-'*len(lines[0]))
249 lines.append('')
250 lines.append('')
250 for p in wrap_paragraphs(self.subcommand_description):
251 for p in wrap_paragraphs(self.subcommand_description):
251 lines.append(p)
252 lines.append(p)
252 lines.append('')
253 lines.append('')
253 for subc, (cls, help) in self.subcommands.iteritems():
254 for subc, (cls, help) in self.subcommands.iteritems():
254 lines.append(subc)
255 lines.append(subc)
255 if help:
256 if help:
256 lines.append(indent(dedent(help.strip())))
257 lines.append(indent(dedent(help.strip())))
257 lines.append('')
258 lines.append('')
258 print os.linesep.join(lines)
259 print os.linesep.join(lines)
259
260
260 def print_help(self, classes=False):
261 def print_help(self, classes=False):
261 """Print the help for each Configurable class in self.classes.
262 """Print the help for each Configurable class in self.classes.
262
263
263 If classes=False (the default), only flags and aliases are printed.
264 If classes=False (the default), only flags and aliases are printed.
264 """
265 """
265 self.print_subcommands()
266 self.print_subcommands()
266 self.print_options()
267 self.print_options()
267
268
268 if classes:
269 if classes:
269 if self.classes:
270 if self.classes:
270 print "Class parameters"
271 print "Class parameters"
271 print "----------------"
272 print "----------------"
272 print
273 print
273 for p in wrap_paragraphs(self.keyvalue_description):
274 for p in wrap_paragraphs(self.keyvalue_description):
274 print p
275 print p
275 print
276 print
276
277
277 for cls in self.classes:
278 for cls in self.classes:
278 cls.class_print_help()
279 cls.class_print_help()
279 print
280 print
280 else:
281 else:
281 print "To see all available configurables, use `--help-all`"
282 print "To see all available configurables, use `--help-all`"
282 print
283 print
283
284
284 def print_description(self):
285 def print_description(self):
285 """Print the application description."""
286 """Print the application description."""
286 for p in wrap_paragraphs(self.description):
287 for p in wrap_paragraphs(self.description):
287 print p
288 print p
288 print
289 print
289
290
290 def print_examples(self):
291 def print_examples(self):
291 """Print usage and examples.
292 """Print usage and examples.
292
293
293 This usage string goes at the end of the command line help string
294 This usage string goes at the end of the command line help string
294 and should contain examples of the application's usage.
295 and should contain examples of the application's usage.
295 """
296 """
296 if self.examples:
297 if self.examples:
297 print "Examples"
298 print "Examples"
298 print "--------"
299 print "--------"
299 print
300 print
300 print indent(dedent(self.examples.strip()))
301 print indent(dedent(self.examples.strip()))
301 print
302 print
302
303
303 def print_version(self):
304 def print_version(self):
304 """Print the version string."""
305 """Print the version string."""
305 print self.version
306 print self.version
306
307
307 def update_config(self, config):
308 def update_config(self, config):
308 """Fire the traits events when the config is updated."""
309 """Fire the traits events when the config is updated."""
309 # Save a copy of the current config.
310 # Save a copy of the current config.
310 newconfig = deepcopy(self.config)
311 newconfig = deepcopy(self.config)
311 # Merge the new config into the current one.
312 # Merge the new config into the current one.
312 newconfig._merge(config)
313 newconfig._merge(config)
313 # Save the combined config as self.config, which triggers the traits
314 # Save the combined config as self.config, which triggers the traits
314 # events.
315 # events.
315 self.config = newconfig
316 self.config = newconfig
316
317
317 def initialize_subcommand(self, subc, argv=None):
318 def initialize_subcommand(self, subc, argv=None):
318 """Initialize a subcommand with argv."""
319 """Initialize a subcommand with argv."""
319 subapp,help = self.subcommands.get(subc)
320 subapp,help = self.subcommands.get(subc)
320
321
321 if isinstance(subapp, basestring):
322 if isinstance(subapp, basestring):
322 subapp = import_item(subapp)
323 subapp = import_item(subapp)
323
324
324 # clear existing instances
325 # clear existing instances
325 self.__class__.clear_instance()
326 self.__class__.clear_instance()
326 # instantiate
327 # instantiate
327 self.subapp = subapp.instance()
328 self.subapp = subapp.instance()
328 # and initialize subapp
329 # and initialize subapp
329 self.subapp.initialize(argv)
330 self.subapp.initialize(argv)
330
331
331 def parse_command_line(self, argv=None):
332 def parse_command_line(self, argv=None):
332 """Parse the command line arguments."""
333 """Parse the command line arguments."""
333 argv = sys.argv[1:] if argv is None else argv
334 argv = sys.argv[1:] if argv is None else argv
334
335
335 if self.subcommands and len(argv) > 0:
336 if self.subcommands and len(argv) > 0:
336 # we have subcommands, and one may have been specified
337 # we have subcommands, and one may have been specified
337 subc, subargv = argv[0], argv[1:]
338 subc, subargv = argv[0], argv[1:]
338 if re.match(r'^\w(\-?\w)*$', subc) and subc in self.subcommands:
339 if re.match(r'^\w(\-?\w)*$', subc) and subc in self.subcommands:
339 # it's a subcommand, and *not* a flag or class parameter
340 # it's a subcommand, and *not* a flag or class parameter
340 return self.initialize_subcommand(subc, subargv)
341 return self.initialize_subcommand(subc, subargv)
341
342
342 if '-h' in argv or '--help' in argv or '--help-all' in argv:
343 if '-h' in argv or '--help' in argv or '--help-all' in argv:
343 self.print_description()
344 self.print_description()
344 self.print_help('--help-all' in argv)
345 self.print_help('--help-all' in argv)
345 self.print_examples()
346 self.print_examples()
346 self.exit(0)
347 self.exit(0)
347
348
348 if '--version' in argv:
349 if '--version' in argv:
349 self.print_version()
350 self.print_version()
350 self.exit(0)
351 self.exit(0)
351
352
352 loader = KeyValueConfigLoader(argv=argv, aliases=self.aliases,
353 loader = KeyValueConfigLoader(argv=argv, aliases=self.aliases,
353 flags=self.flags)
354 flags=self.flags)
354 try:
355 try:
355 config = loader.load_config()
356 config = loader.load_config()
356 self.update_config(config)
357 self.update_config(config)
357 except (TraitError, ArgumentError) as e:
358 except (TraitError, ArgumentError) as e:
358 self.print_description()
359 self.print_description()
359 self.print_help()
360 self.print_help()
360 self.print_examples()
361 self.print_examples()
361 self.log.fatal(str(e))
362 self.log.fatal(str(e))
362 self.exit(1)
363 self.exit(1)
363 # store unparsed args in extra_args
364 # store unparsed args in extra_args
364 self.extra_args = loader.extra_args
365 self.extra_args = loader.extra_args
365
366
366 def load_config_file(self, filename, path=None):
367 def load_config_file(self, filename, path=None):
367 """Load a .py based config file by filename and path."""
368 """Load a .py based config file by filename and path."""
368 loader = PyFileConfigLoader(filename, path=path)
369 loader = PyFileConfigLoader(filename, path=path)
369 try:
370 try:
370 config = loader.load_config()
371 config = loader.load_config()
371 except Exception:
372 except Exception:
372 self.log.error("Exception while loading config file %s [path=%s]"%
373 self.log.error("Exception while loading config file %s [path=%s]"%
373 (filename, path), exc_info=True)
374 (filename, path), exc_info=True)
374 else:
375 else:
375 self.update_config(config)
376 self.update_config(config)
376
377
377 def generate_config_file(self):
378 def generate_config_file(self):
378 """generate default config file from Configurables"""
379 """generate default config file from Configurables"""
379 lines = ["# Configuration file for %s."%self.name]
380 lines = ["# Configuration file for %s."%self.name]
380 lines.append('')
381 lines.append('')
381 lines.append('c = get_config()')
382 lines.append('c = get_config()')
382 lines.append('')
383 lines.append('')
383 for cls in self.classes:
384 for cls in self.classes:
384 lines.append(cls.class_config_section())
385 lines.append(cls.class_config_section())
385 return '\n'.join(lines)
386 return '\n'.join(lines)
386
387
387 def exit(self, exit_status=0):
388 def exit(self, exit_status=0):
388 self.log.debug("Exiting application: %s" % self.name)
389 self.log.debug("Exiting application: %s" % self.name)
389 sys.exit(exit_status)
390 sys.exit(exit_status)
390
391
391 #-----------------------------------------------------------------------------
392 #-----------------------------------------------------------------------------
392 # utility functions, for convenience
393 # utility functions, for convenience
393 #-----------------------------------------------------------------------------
394 #-----------------------------------------------------------------------------
394
395
395 def boolean_flag(name, configurable, set_help='', unset_help=''):
396 def boolean_flag(name, configurable, set_help='', unset_help=''):
396 """Helper for building basic --trait, --no-trait flags.
397 """Helper for building basic --trait, --no-trait flags.
397
398
398 Parameters
399 Parameters
399 ----------
400 ----------
400
401
401 name : str
402 name : str
402 The name of the flag.
403 The name of the flag.
403 configurable : str
404 configurable : str
404 The 'Class.trait' string of the trait to be set/unset with the flag
405 The 'Class.trait' string of the trait to be set/unset with the flag
405 set_help : unicode
406 set_help : unicode
406 help string for --name flag
407 help string for --name flag
407 unset_help : unicode
408 unset_help : unicode
408 help string for --no-name flag
409 help string for --no-name flag
409
410
410 Returns
411 Returns
411 -------
412 -------
412
413
413 cfg : dict
414 cfg : dict
414 A dict with two keys: 'name', and 'no-name', for setting and unsetting
415 A dict with two keys: 'name', and 'no-name', for setting and unsetting
415 the trait, respectively.
416 the trait, respectively.
416 """
417 """
417 # default helpstrings
418 # default helpstrings
418 set_help = set_help or "set %s=True"%configurable
419 set_help = set_help or "set %s=True"%configurable
419 unset_help = unset_help or "set %s=False"%configurable
420 unset_help = unset_help or "set %s=False"%configurable
420
421
421 cls,trait = configurable.split('.')
422 cls,trait = configurable.split('.')
422
423
423 setter = {cls : {trait : True}}
424 setter = {cls : {trait : True}}
424 unsetter = {cls : {trait : False}}
425 unsetter = {cls : {trait : False}}
425 return {name : (setter, set_help), 'no-'+name : (unsetter, unset_help)}
426 return {name : (setter, set_help), 'no-'+name : (unsetter, unset_help)}
426
427
@@ -1,374 +1,383 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 The :class:`~IPython.core.application.Application` object for the command
4 The :class:`~IPython.core.application.Application` object for the command
5 line :command:`ipython` program.
5 line :command:`ipython` program.
6
6
7 Authors
7 Authors
8 -------
8 -------
9
9
10 * Brian Granger
10 * Brian Granger
11 * Fernando Perez
11 * Fernando Perez
12 * Min Ragan-Kelley
12 * Min Ragan-Kelley
13 """
13 """
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Copyright (C) 2008-2010 The IPython Development Team
16 # Copyright (C) 2008-2010 The IPython Development Team
17 #
17 #
18 # Distributed under the terms of the BSD License. The full license is in
18 # Distributed under the terms of the BSD License. The full license is in
19 # the file COPYING, distributed as part of this software.
19 # the file COPYING, distributed as part of this software.
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23 # Imports
23 # Imports
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25
25
26 from __future__ import absolute_import
26 from __future__ import absolute_import
27
27
28 import logging
28 import logging
29 import os
29 import os
30 import sys
30 import sys
31
31
32 from IPython.config.loader import (
32 from IPython.config.loader import (
33 Config, PyFileConfigLoader
33 Config, PyFileConfigLoader
34 )
34 )
35 from IPython.config.application import boolean_flag
35 from IPython.config.application import boolean_flag
36 from IPython.core import release
36 from IPython.core import release
37 from IPython.core import usage
37 from IPython.core import usage
38 from IPython.core.crashhandler import CrashHandler
38 from IPython.core.crashhandler import CrashHandler
39 from IPython.core.formatters import PlainTextFormatter
39 from IPython.core.formatters import PlainTextFormatter
40 from IPython.core.application import (
40 from IPython.core.application import (
41 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
41 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
42 )
42 )
43 from IPython.core.shellapp import (
43 from IPython.core.shellapp import (
44 InteractiveShellApp, shell_flags, shell_aliases
44 InteractiveShellApp, shell_flags, shell_aliases
45 )
45 )
46 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
46 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
47 from IPython.lib import inputhook
47 from IPython.lib import inputhook
48 from IPython.utils import warn
48 from IPython.utils import warn
49 from IPython.utils.path import get_ipython_dir, check_for_old_config
49 from IPython.utils.path import get_ipython_dir, check_for_old_config
50 from IPython.utils.traitlets import (
50 from IPython.utils.traitlets import (
51 Bool, Dict, CaselessStrEnum
51 Bool, List, Dict, CaselessStrEnum
52 )
52 )
53
53
54 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
55 # Globals, utilities and helpers
55 # Globals, utilities and helpers
56 #-----------------------------------------------------------------------------
56 #-----------------------------------------------------------------------------
57
57
58 #: The default config file name for this application.
58 #: The default config file name for this application.
59 default_config_file_name = u'ipython_config.py'
59 default_config_file_name = u'ipython_config.py'
60
60
61 _examples = """
61 _examples = """
62 ipython --pylab # start in pylab mode
62 ipython --pylab # start in pylab mode
63 ipython --pylab=qt # start in pylab mode with the qt4 backend
63 ipython --pylab=qt # start in pylab mode with the qt4 backend
64 ipython --log-level=DEBUG # set logging to DEBUG
64 ipython --log-level=DEBUG # set logging to DEBUG
65 ipython --profile=foo # start with profile foo
65 ipython --profile=foo # start with profile foo
66
66
67 ipython qtconsole # start the qtconsole GUI application
67 ipython qtconsole # start the qtconsole GUI application
68 ipython qtconsole -h # show the help string for the qtconsole subcmd
68 ipython qtconsole -h # show the help string for the qtconsole subcmd
69
69
70 ipython profile create foo # create profile foo w/ default config files
70 ipython profile create foo # create profile foo w/ default config files
71 ipython profile -h # show the help string for the profile subcmd
71 ipython profile -h # show the help string for the profile subcmd
72 """
72 """
73
73
74 #-----------------------------------------------------------------------------
74 #-----------------------------------------------------------------------------
75 # Crash handler for this application
75 # Crash handler for this application
76 #-----------------------------------------------------------------------------
76 #-----------------------------------------------------------------------------
77
77
78 class IPAppCrashHandler(CrashHandler):
78 class IPAppCrashHandler(CrashHandler):
79 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
79 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
80
80
81 def __init__(self, app):
81 def __init__(self, app):
82 contact_name = release.authors['Fernando'][0]
82 contact_name = release.authors['Fernando'][0]
83 contact_email = release.authors['Fernando'][1]
83 contact_email = release.authors['Fernando'][1]
84 bug_tracker = 'http://github.com/ipython/ipython/issues'
84 bug_tracker = 'http://github.com/ipython/ipython/issues'
85 super(IPAppCrashHandler,self).__init__(
85 super(IPAppCrashHandler,self).__init__(
86 app, contact_name, contact_email, bug_tracker
86 app, contact_name, contact_email, bug_tracker
87 )
87 )
88
88
89 def make_report(self,traceback):
89 def make_report(self,traceback):
90 """Return a string containing a crash report."""
90 """Return a string containing a crash report."""
91
91
92 sec_sep = self.section_sep
92 sec_sep = self.section_sep
93 # Start with parent report
93 # Start with parent report
94 report = [super(IPAppCrashHandler, self).make_report(traceback)]
94 report = [super(IPAppCrashHandler, self).make_report(traceback)]
95 # Add interactive-specific info we may have
95 # Add interactive-specific info we may have
96 rpt_add = report.append
96 rpt_add = report.append
97 try:
97 try:
98 rpt_add(sec_sep+"History of session input:")
98 rpt_add(sec_sep+"History of session input:")
99 for line in self.app.shell.user_ns['_ih']:
99 for line in self.app.shell.user_ns['_ih']:
100 rpt_add(line)
100 rpt_add(line)
101 rpt_add('\n*** Last line of input (may not be in above history):\n')
101 rpt_add('\n*** Last line of input (may not be in above history):\n')
102 rpt_add(self.app.shell._last_input_line+'\n')
102 rpt_add(self.app.shell._last_input_line+'\n')
103 except:
103 except:
104 pass
104 pass
105
105
106 return ''.join(report)
106 return ''.join(report)
107
107
108 #-----------------------------------------------------------------------------
108 #-----------------------------------------------------------------------------
109 # Aliases and Flags
109 # Aliases and Flags
110 #-----------------------------------------------------------------------------
110 #-----------------------------------------------------------------------------
111 flags = dict(base_flags)
111 flags = dict(base_flags)
112 flags.update(shell_flags)
112 flags.update(shell_flags)
113 addflag = lambda *args: flags.update(boolean_flag(*args))
113 addflag = lambda *args: flags.update(boolean_flag(*args))
114 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
114 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
115 'Turn on auto editing of files with syntax errors.',
115 'Turn on auto editing of files with syntax errors.',
116 'Turn off auto editing of files with syntax errors.'
116 'Turn off auto editing of files with syntax errors.'
117 )
117 )
118 addflag('banner', 'TerminalIPythonApp.display_banner',
118 addflag('banner', 'TerminalIPythonApp.display_banner',
119 "Display a banner upon starting IPython.",
119 "Display a banner upon starting IPython.",
120 "Don't display a banner upon starting IPython."
120 "Don't display a banner upon starting IPython."
121 )
121 )
122 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
122 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
123 """Set to confirm when you try to exit IPython with an EOF (Control-D
123 """Set to confirm when you try to exit IPython with an EOF (Control-D
124 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
124 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
125 you can force a direct exit without any confirmation.""",
125 you can force a direct exit without any confirmation.""",
126 "Don't prompt the user when exiting."
126 "Don't prompt the user when exiting."
127 )
127 )
128 addflag('term-title', 'TerminalInteractiveShell.term_title',
128 addflag('term-title', 'TerminalInteractiveShell.term_title',
129 "Enable auto setting the terminal title.",
129 "Enable auto setting the terminal title.",
130 "Disable auto setting the terminal title."
130 "Disable auto setting the terminal title."
131 )
131 )
132 classic_config = Config()
132 classic_config = Config()
133 classic_config.InteractiveShell.cache_size = 0
133 classic_config.InteractiveShell.cache_size = 0
134 classic_config.PlainTextFormatter.pprint = False
134 classic_config.PlainTextFormatter.pprint = False
135 classic_config.InteractiveShell.prompt_in1 = '>>> '
135 classic_config.InteractiveShell.prompt_in1 = '>>> '
136 classic_config.InteractiveShell.prompt_in2 = '... '
136 classic_config.InteractiveShell.prompt_in2 = '... '
137 classic_config.InteractiveShell.prompt_out = ''
137 classic_config.InteractiveShell.prompt_out = ''
138 classic_config.InteractiveShell.separate_in = ''
138 classic_config.InteractiveShell.separate_in = ''
139 classic_config.InteractiveShell.separate_out = ''
139 classic_config.InteractiveShell.separate_out = ''
140 classic_config.InteractiveShell.separate_out2 = ''
140 classic_config.InteractiveShell.separate_out2 = ''
141 classic_config.InteractiveShell.colors = 'NoColor'
141 classic_config.InteractiveShell.colors = 'NoColor'
142 classic_config.InteractiveShell.xmode = 'Plain'
142 classic_config.InteractiveShell.xmode = 'Plain'
143
143
144 flags['classic']=(
144 flags['classic']=(
145 classic_config,
145 classic_config,
146 "Gives IPython a similar feel to the classic Python prompt."
146 "Gives IPython a similar feel to the classic Python prompt."
147 )
147 )
148 # # log doesn't make so much sense this way anymore
148 # # log doesn't make so much sense this way anymore
149 # paa('--log','-l',
149 # paa('--log','-l',
150 # action='store_true', dest='InteractiveShell.logstart',
150 # action='store_true', dest='InteractiveShell.logstart',
151 # help="Start logging to the default log file (./ipython_log.py).")
151 # help="Start logging to the default log file (./ipython_log.py).")
152 #
152 #
153 # # quick is harder to implement
153 # # quick is harder to implement
154 flags['quick']=(
154 flags['quick']=(
155 {'TerminalIPythonApp' : {'quick' : True}},
155 {'TerminalIPythonApp' : {'quick' : True}},
156 "Enable quick startup with no config files."
156 "Enable quick startup with no config files."
157 )
157 )
158
158
159 flags['i'] = (
159 flags['i'] = (
160 {'TerminalIPythonApp' : {'force_interact' : True}},
160 {'TerminalIPythonApp' : {'force_interact' : True}},
161 """If running code from the command line, become interactive afterwards.
161 """If running code from the command line, become interactive afterwards.
162 Note: can also be given simply as '-i.'"""
162 Note: can also be given simply as '-i.'"""
163 )
163 )
164 flags['pylab'] = (
164 flags['pylab'] = (
165 {'TerminalIPythonApp' : {'pylab' : 'auto'}},
165 {'TerminalIPythonApp' : {'pylab' : 'auto'}},
166 """Pre-load matplotlib and numpy for interactive use with
166 """Pre-load matplotlib and numpy for interactive use with
167 the default matplotlib backend."""
167 the default matplotlib backend."""
168 )
168 )
169
169
170 aliases = dict(base_aliases)
170 aliases = dict(base_aliases)
171 aliases.update(shell_aliases)
171 aliases.update(shell_aliases)
172
172
173 # it's possible we don't want short aliases for *all* of these:
173 # it's possible we don't want short aliases for *all* of these:
174 aliases.update(dict(
174 aliases.update(dict(
175 gui='TerminalIPythonApp.gui',
175 gui='TerminalIPythonApp.gui',
176 pylab='TerminalIPythonApp.pylab',
176 pylab='TerminalIPythonApp.pylab',
177 ))
177 ))
178
178
179 #-----------------------------------------------------------------------------
179 #-----------------------------------------------------------------------------
180 # Main classes and functions
180 # Main classes and functions
181 #-----------------------------------------------------------------------------
181 #-----------------------------------------------------------------------------
182
182
183 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
183 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
184 name = u'ipython'
184 name = u'ipython'
185 description = usage.cl_usage
185 description = usage.cl_usage
186 default_config_file_name = default_config_file_name
186 default_config_file_name = default_config_file_name
187 crash_handler_class = IPAppCrashHandler
187 crash_handler_class = IPAppCrashHandler
188 examples = _examples
188 examples = _examples
189
189
190 flags = Dict(flags)
190 flags = Dict(flags)
191 aliases = Dict(aliases)
191 aliases = Dict(aliases)
192 classes = [InteractiveShellApp, TerminalInteractiveShell, ProfileDir,
192 classes = List()
193 PlainTextFormatter]
193 def _classes_default(self):
194 """This has to be in a method, for TerminalIPythonApp to be available."""
195 return [
196 InteractiveShellApp, # ShellApp comes before TerminalApp, because
197 self.__class__, # it will also affect subclasses (e.g. QtConsole)
198 TerminalInteractiveShell,
199 ProfileDir,
200 PlainTextFormatter,
201 ]
202
194 subcommands = Dict(dict(
203 subcommands = Dict(dict(
195 qtconsole=('IPython.frontend.qt.console.qtconsoleapp.IPythonQtConsoleApp',
204 qtconsole=('IPython.frontend.qt.console.qtconsoleapp.IPythonQtConsoleApp',
196 """Launch the IPython Qt Console."""
205 """Launch the IPython Qt Console."""
197 ),
206 ),
198 profile = ("IPython.core.profileapp.ProfileApp",
207 profile = ("IPython.core.profileapp.ProfileApp",
199 "Create and manage IPython profiles.")
208 "Create and manage IPython profiles.")
200 ))
209 ))
201
210
202 # *do* autocreate requested profile, but don't create the config file.
211 # *do* autocreate requested profile, but don't create the config file.
203 auto_create=Bool(True)
212 auto_create=Bool(True)
204 # configurables
213 # configurables
205 ignore_old_config=Bool(False, config=True,
214 ignore_old_config=Bool(False, config=True,
206 help="Suppress warning messages about legacy config files"
215 help="Suppress warning messages about legacy config files"
207 )
216 )
208 quick = Bool(False, config=True,
217 quick = Bool(False, config=True,
209 help="""Start IPython quickly by skipping the loading of config files."""
218 help="""Start IPython quickly by skipping the loading of config files."""
210 )
219 )
211 def _quick_changed(self, name, old, new):
220 def _quick_changed(self, name, old, new):
212 if new:
221 if new:
213 self.load_config_file = lambda *a, **kw: None
222 self.load_config_file = lambda *a, **kw: None
214 self.ignore_old_config=True
223 self.ignore_old_config=True
215
224
216 gui = CaselessStrEnum(('qt','wx','gtk'), config=True,
225 gui = CaselessStrEnum(('qt','wx','gtk'), config=True,
217 help="Enable GUI event loop integration ('qt', 'wx', 'gtk')."
226 help="Enable GUI event loop integration ('qt', 'wx', 'gtk')."
218 )
227 )
219 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'auto'],
228 pylab = CaselessStrEnum(['tk', 'qt', 'wx', 'gtk', 'osx', 'auto'],
220 config=True,
229 config=True,
221 help="""Pre-load matplotlib and numpy for interactive use,
230 help="""Pre-load matplotlib and numpy for interactive use,
222 selecting a particular matplotlib backend and loop integration.
231 selecting a particular matplotlib backend and loop integration.
223 """
232 """
224 )
233 )
225 display_banner = Bool(True, config=True,
234 display_banner = Bool(True, config=True,
226 help="Whether to display a banner upon starting IPython."
235 help="Whether to display a banner upon starting IPython."
227 )
236 )
228
237
229 # if there is code of files to run from the cmd line, don't interact
238 # if there is code of files to run from the cmd line, don't interact
230 # unless the --i flag (App.force_interact) is true.
239 # unless the --i flag (App.force_interact) is true.
231 force_interact = Bool(False, config=True,
240 force_interact = Bool(False, config=True,
232 help="""If a command or file is given via the command-line,
241 help="""If a command or file is given via the command-line,
233 e.g. 'ipython foo.py"""
242 e.g. 'ipython foo.py"""
234 )
243 )
235 def _force_interact_changed(self, name, old, new):
244 def _force_interact_changed(self, name, old, new):
236 if new:
245 if new:
237 self.interact = True
246 self.interact = True
238
247
239 def _file_to_run_changed(self, name, old, new):
248 def _file_to_run_changed(self, name, old, new):
240 if new and not self.force_interact:
249 if new and not self.force_interact:
241 self.interact = False
250 self.interact = False
242 _code_to_run_changed = _file_to_run_changed
251 _code_to_run_changed = _file_to_run_changed
243
252
244 # internal, not-configurable
253 # internal, not-configurable
245 interact=Bool(True)
254 interact=Bool(True)
246
255
247
256
248 def parse_command_line(self, argv=None):
257 def parse_command_line(self, argv=None):
249 """override to allow old '-pylab' flag with deprecation warning"""
258 """override to allow old '-pylab' flag with deprecation warning"""
250
259
251 argv = sys.argv[1:] if argv is None else argv
260 argv = sys.argv[1:] if argv is None else argv
252
261
253 if '-pylab' in argv:
262 if '-pylab' in argv:
254 # deprecated `-pylab` given,
263 # deprecated `-pylab` given,
255 # warn and transform into current syntax
264 # warn and transform into current syntax
256 argv = argv[:] # copy, don't clobber
265 argv = argv[:] # copy, don't clobber
257 idx = argv.index('-pylab')
266 idx = argv.index('-pylab')
258 warn.warn("`-pylab` flag has been deprecated.\n"
267 warn.warn("`-pylab` flag has been deprecated.\n"
259 " Use `--pylab` instead, or `--pylab=foo` to specify a backend.")
268 " Use `--pylab` instead, or `--pylab=foo` to specify a backend.")
260 sub = '--pylab'
269 sub = '--pylab'
261 if len(argv) > idx+1:
270 if len(argv) > idx+1:
262 # check for gui arg, as in '-pylab qt'
271 # check for gui arg, as in '-pylab qt'
263 gui = argv[idx+1]
272 gui = argv[idx+1]
264 if gui in ('wx', 'qt', 'qt4', 'gtk', 'auto'):
273 if gui in ('wx', 'qt', 'qt4', 'gtk', 'auto'):
265 sub = '--pylab='+gui
274 sub = '--pylab='+gui
266 argv.pop(idx+1)
275 argv.pop(idx+1)
267 argv[idx] = sub
276 argv[idx] = sub
268
277
269 return super(TerminalIPythonApp, self).parse_command_line(argv)
278 return super(TerminalIPythonApp, self).parse_command_line(argv)
270
279
271 def initialize(self, argv=None):
280 def initialize(self, argv=None):
272 """Do actions after construct, but before starting the app."""
281 """Do actions after construct, but before starting the app."""
273 super(TerminalIPythonApp, self).initialize(argv)
282 super(TerminalIPythonApp, self).initialize(argv)
274 if self.subapp is not None:
283 if self.subapp is not None:
275 # don't bother initializing further, starting subapp
284 # don't bother initializing further, starting subapp
276 return
285 return
277 if not self.ignore_old_config:
286 if not self.ignore_old_config:
278 check_for_old_config(self.ipython_dir)
287 check_for_old_config(self.ipython_dir)
279 # print self.extra_args
288 # print self.extra_args
280 if self.extra_args:
289 if self.extra_args:
281 self.file_to_run = self.extra_args[0]
290 self.file_to_run = self.extra_args[0]
282 # create the shell
291 # create the shell
283 self.init_shell()
292 self.init_shell()
284 # and draw the banner
293 # and draw the banner
285 self.init_banner()
294 self.init_banner()
286 # Now a variety of things that happen after the banner is printed.
295 # Now a variety of things that happen after the banner is printed.
287 self.init_gui_pylab()
296 self.init_gui_pylab()
288 self.init_extensions()
297 self.init_extensions()
289 self.init_code()
298 self.init_code()
290
299
291 def init_shell(self):
300 def init_shell(self):
292 """initialize the InteractiveShell instance"""
301 """initialize the InteractiveShell instance"""
293 # I am a little hesitant to put these into InteractiveShell itself.
302 # I am a little hesitant to put these into InteractiveShell itself.
294 # But that might be the place for them
303 # But that might be the place for them
295 sys.path.insert(0, '')
304 sys.path.insert(0, '')
296
305
297 # Create an InteractiveShell instance.
306 # Create an InteractiveShell instance.
298 # shell.display_banner should always be False for the terminal
307 # shell.display_banner should always be False for the terminal
299 # based app, because we call shell.show_banner() by hand below
308 # based app, because we call shell.show_banner() by hand below
300 # so the banner shows *before* all extension loading stuff.
309 # so the banner shows *before* all extension loading stuff.
301 self.shell = TerminalInteractiveShell.instance(config=self.config,
310 self.shell = TerminalInteractiveShell.instance(config=self.config,
302 display_banner=False, profile_dir=self.profile_dir,
311 display_banner=False, profile_dir=self.profile_dir,
303 ipython_dir=self.ipython_dir)
312 ipython_dir=self.ipython_dir)
304
313
305 def init_banner(self):
314 def init_banner(self):
306 """optionally display the banner"""
315 """optionally display the banner"""
307 if self.display_banner and self.interact:
316 if self.display_banner and self.interact:
308 self.shell.show_banner()
317 self.shell.show_banner()
309 # Make sure there is a space below the banner.
318 # Make sure there is a space below the banner.
310 if self.log_level <= logging.INFO: print
319 if self.log_level <= logging.INFO: print
311
320
312
321
313 def init_gui_pylab(self):
322 def init_gui_pylab(self):
314 """Enable GUI event loop integration, taking pylab into account."""
323 """Enable GUI event loop integration, taking pylab into account."""
315 gui = self.gui
324 gui = self.gui
316
325
317 # Using `pylab` will also require gui activation, though which toolkit
326 # Using `pylab` will also require gui activation, though which toolkit
318 # to use may be chosen automatically based on mpl configuration.
327 # to use may be chosen automatically based on mpl configuration.
319 if self.pylab:
328 if self.pylab:
320 activate = self.shell.enable_pylab
329 activate = self.shell.enable_pylab
321 if self.pylab == 'auto':
330 if self.pylab == 'auto':
322 gui = None
331 gui = None
323 else:
332 else:
324 gui = self.pylab
333 gui = self.pylab
325 else:
334 else:
326 # Enable only GUI integration, no pylab
335 # Enable only GUI integration, no pylab
327 activate = inputhook.enable_gui
336 activate = inputhook.enable_gui
328
337
329 if gui or self.pylab:
338 if gui or self.pylab:
330 try:
339 try:
331 self.log.info("Enabling GUI event loop integration, "
340 self.log.info("Enabling GUI event loop integration, "
332 "toolkit=%s, pylab=%s" % (gui, self.pylab) )
341 "toolkit=%s, pylab=%s" % (gui, self.pylab) )
333 activate(gui)
342 activate(gui)
334 except:
343 except:
335 self.log.warn("Error in enabling GUI event loop integration:")
344 self.log.warn("Error in enabling GUI event loop integration:")
336 self.shell.showtraceback()
345 self.shell.showtraceback()
337
346
338 def start(self):
347 def start(self):
339 if self.subapp is not None:
348 if self.subapp is not None:
340 return self.subapp.start()
349 return self.subapp.start()
341 # perform any prexec steps:
350 # perform any prexec steps:
342 if self.interact:
351 if self.interact:
343 self.log.debug("Starting IPython's mainloop...")
352 self.log.debug("Starting IPython's mainloop...")
344 self.shell.mainloop()
353 self.shell.mainloop()
345 else:
354 else:
346 self.log.debug("IPython not interactive...")
355 self.log.debug("IPython not interactive...")
347
356
348
357
349 def load_default_config(ipython_dir=None):
358 def load_default_config(ipython_dir=None):
350 """Load the default config file from the default ipython_dir.
359 """Load the default config file from the default ipython_dir.
351
360
352 This is useful for embedded shells.
361 This is useful for embedded shells.
353 """
362 """
354 if ipython_dir is None:
363 if ipython_dir is None:
355 ipython_dir = get_ipython_dir()
364 ipython_dir = get_ipython_dir()
356 profile_dir = os.path.join(ipython_dir, 'profile_default')
365 profile_dir = os.path.join(ipython_dir, 'profile_default')
357 cl = PyFileConfigLoader(default_config_file_name, profile_dir)
366 cl = PyFileConfigLoader(default_config_file_name, profile_dir)
358 try:
367 try:
359 config = cl.load_config()
368 config = cl.load_config()
360 except IOError:
369 except IOError:
361 # no config found
370 # no config found
362 config = Config()
371 config = Config()
363 return config
372 return config
364
373
365
374
366 def launch_new_instance():
375 def launch_new_instance():
367 """Create and run a full blown IPython instance"""
376 """Create and run a full blown IPython instance"""
368 app = TerminalIPythonApp.instance()
377 app = TerminalIPythonApp.instance()
369 app.initialize()
378 app.initialize()
370 app.start()
379 app.start()
371
380
372
381
373 if __name__ == '__main__':
382 if __name__ == '__main__':
374 launch_new_instance()
383 launch_new_instance()
General Comments 0
You need to be logged in to leave comments. Login now