##// END OF EJS Templates
Clean up some attributes which don't need to be traitlets
Thomas Kluyver -
Show More
@@ -1,462 +1,462 b''
1 1 # encoding: utf-8
2 2 """
3 3 An application for IPython.
4 4
5 5 All top-level applications should use the classes in this module for
6 6 handling configuration and creating configurables.
7 7
8 8 The job of an :class:`Application` is to create the master configuration
9 9 object and then create the configurable objects, passing the config to them.
10 10 """
11 11
12 12 # Copyright (c) IPython Development Team.
13 13 # Distributed under the terms of the Modified BSD License.
14 14
15 15 import atexit
16 16 from copy import deepcopy
17 17 import glob
18 18 import logging
19 19 import os
20 20 import shutil
21 21 import sys
22 22
23 23 from traitlets.config.application import Application, catch_config_error
24 24 from traitlets.config.loader import ConfigFileNotFound, PyFileConfigLoader
25 25 from IPython.core import release, crashhandler
26 26 from IPython.core.profiledir import ProfileDir, ProfileDirError
27 27 from IPython.paths import get_ipython_dir, get_ipython_package_dir
28 28 from IPython.utils.path import ensure_dir_exists
29 29 from traitlets import (
30 List, Unicode, Type, Bool, Dict, Set, Instance, Undefined,
30 List, Unicode, Type, Bool, Set, Instance, Undefined,
31 31 default, observe,
32 32 )
33 33
34 34 if os.name == 'nt':
35 35 programdata = os.environ.get('PROGRAMDATA', None)
36 36 if programdata:
37 37 SYSTEM_CONFIG_DIRS = [os.path.join(programdata, 'ipython')]
38 38 else: # PROGRAMDATA is not defined by default on XP.
39 39 SYSTEM_CONFIG_DIRS = []
40 40 else:
41 41 SYSTEM_CONFIG_DIRS = [
42 42 "/usr/local/etc/ipython",
43 43 "/etc/ipython",
44 44 ]
45 45
46 46
47 47 ENV_CONFIG_DIRS = []
48 48 _env_config_dir = os.path.join(sys.prefix, 'etc', 'ipython')
49 49 if _env_config_dir not in SYSTEM_CONFIG_DIRS:
50 50 # only add ENV_CONFIG if sys.prefix is not already included
51 51 ENV_CONFIG_DIRS.append(_env_config_dir)
52 52
53 53
54 54 _envvar = os.environ.get('IPYTHON_SUPPRESS_CONFIG_ERRORS')
55 55 if _envvar in {None, ''}:
56 56 IPYTHON_SUPPRESS_CONFIG_ERRORS = None
57 57 else:
58 58 if _envvar.lower() in {'1','true'}:
59 59 IPYTHON_SUPPRESS_CONFIG_ERRORS = True
60 60 elif _envvar.lower() in {'0','false'} :
61 61 IPYTHON_SUPPRESS_CONFIG_ERRORS = False
62 62 else:
63 63 sys.exit("Unsupported value for environment variable: 'IPYTHON_SUPPRESS_CONFIG_ERRORS' is set to '%s' which is none of {'0', '1', 'false', 'true', ''}."% _envvar )
64 64
65 65 # aliases and flags
66 66
67 67 base_aliases = {
68 68 'profile-dir' : 'ProfileDir.location',
69 69 'profile' : 'BaseIPythonApplication.profile',
70 70 'ipython-dir' : 'BaseIPythonApplication.ipython_dir',
71 71 'log-level' : 'Application.log_level',
72 72 'config' : 'BaseIPythonApplication.extra_config_file',
73 73 }
74 74
75 75 base_flags = dict(
76 76 debug = ({'Application' : {'log_level' : logging.DEBUG}},
77 77 "set log level to logging.DEBUG (maximize logging output)"),
78 78 quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
79 79 "set log level to logging.CRITICAL (minimize logging output)"),
80 80 init = ({'BaseIPythonApplication' : {
81 81 'copy_config_files' : True,
82 82 'auto_create' : True}
83 83 }, """Initialize profile with default config files. This is equivalent
84 84 to running `ipython profile create <profile>` prior to startup.
85 85 """)
86 86 )
87 87
88 88 class ProfileAwareConfigLoader(PyFileConfigLoader):
89 89 """A Python file config loader that is aware of IPython profiles."""
90 90 def load_subconfig(self, fname, path=None, profile=None):
91 91 if profile is not None:
92 92 try:
93 93 profile_dir = ProfileDir.find_profile_dir_by_name(
94 94 get_ipython_dir(),
95 95 profile,
96 96 )
97 97 except ProfileDirError:
98 98 return
99 99 path = profile_dir.location
100 100 return super(ProfileAwareConfigLoader, self).load_subconfig(fname, path=path)
101 101
102 102 class BaseIPythonApplication(Application):
103 103
104 name = Unicode(u'ipython')
104 name = u'ipython'
105 105 description = Unicode(u'IPython: an enhanced interactive Python shell.')
106 106 version = Unicode(release.version)
107 107
108 aliases = Dict(base_aliases)
109 flags = Dict(base_flags)
108 aliases = base_aliases
109 flags = base_flags
110 110 classes = List([ProfileDir])
111 111
112 112 # enable `load_subconfig('cfg.py', profile='name')`
113 113 python_config_loader_class = ProfileAwareConfigLoader
114 114
115 115 # Track whether the config_file has changed,
116 116 # because some logic happens only if we aren't using the default.
117 117 config_file_specified = Set()
118 118
119 119 config_file_name = Unicode()
120 120 @default('config_file_name')
121 121 def _config_file_name_default(self):
122 122 return self.name.replace('-','_') + u'_config.py'
123 123 @observe('config_file_name')
124 124 def _config_file_name_changed(self, change):
125 125 if change['new'] != change['old']:
126 126 self.config_file_specified.add(change['new'])
127 127
128 128 # The directory that contains IPython's builtin profiles.
129 129 builtin_profile_dir = Unicode(
130 130 os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
131 131 )
132 132
133 133 config_file_paths = List(Unicode())
134 134 @default('config_file_paths')
135 135 def _config_file_paths_default(self):
136 136 return [os.getcwd()]
137 137
138 138 extra_config_file = Unicode(
139 139 help="""Path to an extra config file to load.
140 140
141 141 If specified, load this config file in addition to any other IPython config.
142 142 """).tag(config=True)
143 143 @observe('extra_config_file')
144 144 def _extra_config_file_changed(self, change):
145 145 old = change['old']
146 146 new = change['new']
147 147 try:
148 148 self.config_files.remove(old)
149 149 except ValueError:
150 150 pass
151 151 self.config_file_specified.add(new)
152 152 self.config_files.append(new)
153 153
154 154 profile = Unicode(u'default',
155 155 help="""The IPython profile to use."""
156 156 ).tag(config=True)
157 157
158 158 @observe('profile')
159 159 def _profile_changed(self, change):
160 160 self.builtin_profile_dir = os.path.join(
161 161 get_ipython_package_dir(), u'config', u'profile', change['new']
162 162 )
163 163
164 164 ipython_dir = Unicode(
165 165 help="""
166 166 The name of the IPython directory. This directory is used for logging
167 167 configuration (through profiles), history storage, etc. The default
168 168 is usually $HOME/.ipython. This option can also be specified through
169 169 the environment variable IPYTHONDIR.
170 170 """
171 171 ).tag(config=True)
172 172 @default('ipython_dir')
173 173 def _ipython_dir_default(self):
174 174 d = get_ipython_dir()
175 175 self._ipython_dir_changed({
176 176 'name': 'ipython_dir',
177 177 'old': d,
178 178 'new': d,
179 179 })
180 180 return d
181 181
182 182 _in_init_profile_dir = False
183 183 profile_dir = Instance(ProfileDir, allow_none=True)
184 184 @default('profile_dir')
185 185 def _profile_dir_default(self):
186 186 # avoid recursion
187 187 if self._in_init_profile_dir:
188 188 return
189 189 # profile_dir requested early, force initialization
190 190 self.init_profile_dir()
191 191 return self.profile_dir
192 192
193 193 overwrite = Bool(False,
194 194 help="""Whether to overwrite existing config files when copying"""
195 195 ).tag(config=True)
196 196 auto_create = Bool(False,
197 197 help="""Whether to create profile dir if it doesn't exist"""
198 198 ).tag(config=True)
199 199
200 200 config_files = List(Unicode())
201 201 @default('config_files')
202 202 def _config_files_default(self):
203 203 return [self.config_file_name]
204 204
205 205 copy_config_files = Bool(False,
206 206 help="""Whether to install the default config files into the profile dir.
207 207 If a new profile is being created, and IPython contains config files for that
208 208 profile, then they will be staged into the new directory. Otherwise,
209 209 default config files will be automatically generated.
210 210 """).tag(config=True)
211 211
212 212 verbose_crash = Bool(False,
213 213 help="""Create a massive crash report when IPython encounters what may be an
214 214 internal error. The default is to append a short message to the
215 215 usual traceback""").tag(config=True)
216 216
217 217 # The class to use as the crash handler.
218 218 crash_handler_class = Type(crashhandler.CrashHandler)
219 219
220 220 @catch_config_error
221 221 def __init__(self, **kwargs):
222 222 super(BaseIPythonApplication, self).__init__(**kwargs)
223 223 # ensure current working directory exists
224 224 try:
225 225 os.getcwd()
226 226 except:
227 227 # exit if cwd doesn't exist
228 228 self.log.error("Current working directory doesn't exist.")
229 229 self.exit(1)
230 230
231 231 #-------------------------------------------------------------------------
232 232 # Various stages of Application creation
233 233 #-------------------------------------------------------------------------
234 234
235 235 deprecated_subcommands = {}
236 236
237 237 def initialize_subcommand(self, subc, argv=None):
238 238 if subc in self.deprecated_subcommands:
239 239 self.log.warning("Subcommand `ipython {sub}` is deprecated and will be removed "
240 240 "in future versions.".format(sub=subc))
241 241 self.log.warning("You likely want to use `jupyter {sub}` in the "
242 242 "future".format(sub=subc))
243 243 return super(BaseIPythonApplication, self).initialize_subcommand(subc, argv)
244 244
245 245 def init_crash_handler(self):
246 246 """Create a crash handler, typically setting sys.excepthook to it."""
247 247 self.crash_handler = self.crash_handler_class(self)
248 248 sys.excepthook = self.excepthook
249 249 def unset_crashhandler():
250 250 sys.excepthook = sys.__excepthook__
251 251 atexit.register(unset_crashhandler)
252 252
253 253 def excepthook(self, etype, evalue, tb):
254 254 """this is sys.excepthook after init_crashhandler
255 255
256 256 set self.verbose_crash=True to use our full crashhandler, instead of
257 257 a regular traceback with a short message (crash_handler_lite)
258 258 """
259 259
260 260 if self.verbose_crash:
261 261 return self.crash_handler(etype, evalue, tb)
262 262 else:
263 263 return crashhandler.crash_handler_lite(etype, evalue, tb)
264 264
265 265 @observe('ipython_dir')
266 266 def _ipython_dir_changed(self, change):
267 267 old = change['old']
268 268 new = change['new']
269 269 if old is not Undefined:
270 270 str_old = os.path.abspath(old)
271 271 if str_old in sys.path:
272 272 sys.path.remove(str_old)
273 273 str_path = os.path.abspath(new)
274 274 sys.path.append(str_path)
275 275 ensure_dir_exists(new)
276 276 readme = os.path.join(new, 'README')
277 277 readme_src = os.path.join(get_ipython_package_dir(), u'config', u'profile', 'README')
278 278 if not os.path.exists(readme) and os.path.exists(readme_src):
279 279 shutil.copy(readme_src, readme)
280 280 for d in ('extensions', 'nbextensions'):
281 281 path = os.path.join(new, d)
282 282 try:
283 283 ensure_dir_exists(path)
284 284 except OSError as e:
285 285 # this will not be EEXIST
286 286 self.log.error("couldn't create path %s: %s", path, e)
287 287 self.log.debug("IPYTHONDIR set to: %s" % new)
288 288
289 289 def load_config_file(self, suppress_errors=IPYTHON_SUPPRESS_CONFIG_ERRORS):
290 290 """Load the config file.
291 291
292 292 By default, errors in loading config are handled, and a warning
293 293 printed on screen. For testing, the suppress_errors option is set
294 294 to False, so errors will make tests fail.
295 295
296 296 `supress_errors` default value is to be `None` in which case the
297 297 behavior default to the one of `traitlets.Application`.
298 298
299 299 The default value can be set :
300 300 - to `False` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '0', or 'false' (case insensitive).
301 301 - to `True` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '1' or 'true' (case insensitive).
302 302 - to `None` by setting 'IPYTHON_SUPPRESS_CONFIG_ERRORS' environment variable to '' (empty string) or leaving it unset.
303 303
304 304 Any other value are invalid, and will make IPython exit with a non-zero return code.
305 305 """
306 306
307 307
308 308 self.log.debug("Searching path %s for config files", self.config_file_paths)
309 309 base_config = 'ipython_config.py'
310 310 self.log.debug("Attempting to load config file: %s" %
311 311 base_config)
312 312 try:
313 313 if suppress_errors is not None:
314 314 old_value = Application.raise_config_file_errors
315 315 Application.raise_config_file_errors = not suppress_errors;
316 316 Application.load_config_file(
317 317 self,
318 318 base_config,
319 319 path=self.config_file_paths
320 320 )
321 321 except ConfigFileNotFound:
322 322 # ignore errors loading parent
323 323 self.log.debug("Config file %s not found", base_config)
324 324 pass
325 325 if suppress_errors is not None:
326 326 Application.raise_config_file_errors = old_value
327 327
328 328 for config_file_name in self.config_files:
329 329 if not config_file_name or config_file_name == base_config:
330 330 continue
331 331 self.log.debug("Attempting to load config file: %s" %
332 332 self.config_file_name)
333 333 try:
334 334 Application.load_config_file(
335 335 self,
336 336 config_file_name,
337 337 path=self.config_file_paths
338 338 )
339 339 except ConfigFileNotFound:
340 340 # Only warn if the default config file was NOT being used.
341 341 if config_file_name in self.config_file_specified:
342 342 msg = self.log.warning
343 343 else:
344 344 msg = self.log.debug
345 345 msg("Config file not found, skipping: %s", config_file_name)
346 346 except Exception:
347 347 # For testing purposes.
348 348 if not suppress_errors:
349 349 raise
350 350 self.log.warning("Error loading config file: %s" %
351 351 self.config_file_name, exc_info=True)
352 352
353 353 def init_profile_dir(self):
354 354 """initialize the profile dir"""
355 355 self._in_init_profile_dir = True
356 356 if self.profile_dir is not None:
357 357 # already ran
358 358 return
359 359 if 'ProfileDir.location' not in self.config:
360 360 # location not specified, find by profile name
361 361 try:
362 362 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
363 363 except ProfileDirError:
364 364 # not found, maybe create it (always create default profile)
365 365 if self.auto_create or self.profile == 'default':
366 366 try:
367 367 p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
368 368 except ProfileDirError:
369 369 self.log.fatal("Could not create profile: %r"%self.profile)
370 370 self.exit(1)
371 371 else:
372 372 self.log.info("Created profile dir: %r"%p.location)
373 373 else:
374 374 self.log.fatal("Profile %r not found."%self.profile)
375 375 self.exit(1)
376 376 else:
377 377 self.log.debug("Using existing profile dir: %r"%p.location)
378 378 else:
379 379 location = self.config.ProfileDir.location
380 380 # location is fully specified
381 381 try:
382 382 p = ProfileDir.find_profile_dir(location, self.config)
383 383 except ProfileDirError:
384 384 # not found, maybe create it
385 385 if self.auto_create:
386 386 try:
387 387 p = ProfileDir.create_profile_dir(location, self.config)
388 388 except ProfileDirError:
389 389 self.log.fatal("Could not create profile directory: %r"%location)
390 390 self.exit(1)
391 391 else:
392 392 self.log.debug("Creating new profile dir: %r"%location)
393 393 else:
394 394 self.log.fatal("Profile directory %r not found."%location)
395 395 self.exit(1)
396 396 else:
397 397 self.log.info("Using existing profile dir: %r"%location)
398 398 # if profile_dir is specified explicitly, set profile name
399 399 dir_name = os.path.basename(p.location)
400 400 if dir_name.startswith('profile_'):
401 401 self.profile = dir_name[8:]
402 402
403 403 self.profile_dir = p
404 404 self.config_file_paths.append(p.location)
405 405 self._in_init_profile_dir = False
406 406
407 407 def init_config_files(self):
408 408 """[optionally] copy default config files into profile dir."""
409 409 self.config_file_paths.extend(ENV_CONFIG_DIRS)
410 410 self.config_file_paths.extend(SYSTEM_CONFIG_DIRS)
411 411 # copy config files
412 412 path = self.builtin_profile_dir
413 413 if self.copy_config_files:
414 414 src = self.profile
415 415
416 416 cfg = self.config_file_name
417 417 if path and os.path.exists(os.path.join(path, cfg)):
418 418 self.log.warning("Staging %r from %s into %r [overwrite=%s]"%(
419 419 cfg, src, self.profile_dir.location, self.overwrite)
420 420 )
421 421 self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
422 422 else:
423 423 self.stage_default_config_file()
424 424 else:
425 425 # Still stage *bundled* config files, but not generated ones
426 426 # This is necessary for `ipython profile=sympy` to load the profile
427 427 # on the first go
428 428 files = glob.glob(os.path.join(path, '*.py'))
429 429 for fullpath in files:
430 430 cfg = os.path.basename(fullpath)
431 431 if self.profile_dir.copy_config_file(cfg, path=path, overwrite=False):
432 432 # file was copied
433 433 self.log.warning("Staging bundled %s from %s into %r"%(
434 434 cfg, self.profile, self.profile_dir.location)
435 435 )
436 436
437 437
438 438 def stage_default_config_file(self):
439 439 """auto generate default config file, and stage it into the profile."""
440 440 s = self.generate_config_file()
441 441 fname = os.path.join(self.profile_dir.location, self.config_file_name)
442 442 if self.overwrite or not os.path.exists(fname):
443 443 self.log.warning("Generating default config file: %r"%(fname))
444 444 with open(fname, 'w') as f:
445 445 f.write(s)
446 446
447 447 @catch_config_error
448 448 def initialize(self, argv=None):
449 449 # don't hook up crash handler before parsing command-line
450 450 self.parse_command_line(argv)
451 451 self.init_crash_handler()
452 452 if self.subapp is not None:
453 453 # stop here if subapp is taking over
454 454 return
455 455 # save a copy of CLI config to re-load after config files
456 456 # so that it has highest priority
457 457 cl_config = deepcopy(self.config)
458 458 self.init_profile_dir()
459 459 self.init_config_files()
460 460 self.load_config_file()
461 461 # enforce cl-opts override configfile opts:
462 462 self.update_config(cl_config)
@@ -1,378 +1,378 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 The :class:`~IPython.core.application.Application` object for the command
5 5 line :command:`ipython` program.
6 6 """
7 7
8 8 # Copyright (c) IPython Development Team.
9 9 # Distributed under the terms of the Modified BSD License.
10 10
11 11
12 12 import logging
13 13 import os
14 14 import sys
15 15 import warnings
16 16
17 17 from traitlets.config.loader import Config
18 from traitlets.config.application import boolean_flag, catch_config_error, Application
18 from traitlets.config.application import boolean_flag, catch_config_error
19 19 from IPython.core import release
20 20 from IPython.core import usage
21 21 from IPython.core.completer import IPCompleter
22 22 from IPython.core.crashhandler import CrashHandler
23 23 from IPython.core.formatters import PlainTextFormatter
24 24 from IPython.core.history import HistoryManager
25 25 from IPython.core.application import (
26 26 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
27 27 )
28 28 from IPython.core.magics import (
29 29 ScriptMagics, LoggingMagics
30 30 )
31 31 from IPython.core.shellapp import (
32 32 InteractiveShellApp, shell_flags, shell_aliases
33 33 )
34 34 from IPython.extensions.storemagic import StoreMagics
35 35 from .interactiveshell import TerminalInteractiveShell
36 36 from IPython.paths import get_ipython_dir
37 37 from traitlets import (
38 Bool, List, Dict, default, observe, Type
38 Bool, List, default, observe, Type
39 39 )
40 40
41 41 #-----------------------------------------------------------------------------
42 42 # Globals, utilities and helpers
43 43 #-----------------------------------------------------------------------------
44 44
45 45 _examples = """
46 46 ipython --matplotlib # enable matplotlib integration
47 47 ipython --matplotlib=qt # enable matplotlib integration with qt4 backend
48 48
49 49 ipython --log-level=DEBUG # set logging to DEBUG
50 50 ipython --profile=foo # start with profile foo
51 51
52 52 ipython profile create foo # create profile foo w/ default config files
53 53 ipython help profile # show the help for the profile subcmd
54 54
55 55 ipython locate # print the path to the IPython directory
56 56 ipython locate profile foo # print the path to the directory for profile `foo`
57 57 """
58 58
59 59 #-----------------------------------------------------------------------------
60 60 # Crash handler for this application
61 61 #-----------------------------------------------------------------------------
62 62
63 63 class IPAppCrashHandler(CrashHandler):
64 64 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
65 65
66 66 def __init__(self, app):
67 67 contact_name = release.author
68 68 contact_email = release.author_email
69 69 bug_tracker = 'https://github.com/ipython/ipython/issues'
70 70 super(IPAppCrashHandler,self).__init__(
71 71 app, contact_name, contact_email, bug_tracker
72 72 )
73 73
74 74 def make_report(self,traceback):
75 75 """Return a string containing a crash report."""
76 76
77 77 sec_sep = self.section_sep
78 78 # Start with parent report
79 79 report = [super(IPAppCrashHandler, self).make_report(traceback)]
80 80 # Add interactive-specific info we may have
81 81 rpt_add = report.append
82 82 try:
83 83 rpt_add(sec_sep+"History of session input:")
84 84 for line in self.app.shell.user_ns['_ih']:
85 85 rpt_add(line)
86 86 rpt_add('\n*** Last line of input (may not be in above history):\n')
87 87 rpt_add(self.app.shell._last_input_line+'\n')
88 88 except:
89 89 pass
90 90
91 91 return ''.join(report)
92 92
93 93 #-----------------------------------------------------------------------------
94 94 # Aliases and Flags
95 95 #-----------------------------------------------------------------------------
96 96 flags = dict(base_flags)
97 97 flags.update(shell_flags)
98 98 frontend_flags = {}
99 99 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
100 100 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
101 101 'Turn on auto editing of files with syntax errors.',
102 102 'Turn off auto editing of files with syntax errors.'
103 103 )
104 104 addflag('simple-prompt', 'TerminalInteractiveShell.simple_prompt',
105 105 "Force simple minimal prompt using `raw_input`",
106 106 "Use a rich interactive prompt with prompt_toolkit",
107 107 )
108 108
109 109 addflag('banner', 'TerminalIPythonApp.display_banner',
110 110 "Display a banner upon starting IPython.",
111 111 "Don't display a banner upon starting IPython."
112 112 )
113 113 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
114 114 """Set to confirm when you try to exit IPython with an EOF (Control-D
115 115 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
116 116 you can force a direct exit without any confirmation.""",
117 117 "Don't prompt the user when exiting."
118 118 )
119 119 addflag('term-title', 'TerminalInteractiveShell.term_title',
120 120 "Enable auto setting the terminal title.",
121 121 "Disable auto setting the terminal title."
122 122 )
123 123 classic_config = Config()
124 124 classic_config.InteractiveShell.cache_size = 0
125 125 classic_config.PlainTextFormatter.pprint = False
126 126 classic_config.TerminalInteractiveShell.prompts_class='IPython.terminal.prompts.ClassicPrompts'
127 127 classic_config.InteractiveShell.separate_in = ''
128 128 classic_config.InteractiveShell.separate_out = ''
129 129 classic_config.InteractiveShell.separate_out2 = ''
130 130 classic_config.InteractiveShell.colors = 'NoColor'
131 131 classic_config.InteractiveShell.xmode = 'Plain'
132 132
133 133 frontend_flags['classic']=(
134 134 classic_config,
135 135 "Gives IPython a similar feel to the classic Python prompt."
136 136 )
137 137 # # log doesn't make so much sense this way anymore
138 138 # paa('--log','-l',
139 139 # action='store_true', dest='InteractiveShell.logstart',
140 140 # help="Start logging to the default log file (./ipython_log.py).")
141 141 #
142 142 # # quick is harder to implement
143 143 frontend_flags['quick']=(
144 144 {'TerminalIPythonApp' : {'quick' : True}},
145 145 "Enable quick startup with no config files."
146 146 )
147 147
148 148 frontend_flags['i'] = (
149 149 {'TerminalIPythonApp' : {'force_interact' : True}},
150 150 """If running code from the command line, become interactive afterwards.
151 151 It is often useful to follow this with `--` to treat remaining flags as
152 152 script arguments.
153 153 """
154 154 )
155 155 flags.update(frontend_flags)
156 156
157 157 aliases = dict(base_aliases)
158 158 aliases.update(shell_aliases)
159 159
160 160 #-----------------------------------------------------------------------------
161 161 # Main classes and functions
162 162 #-----------------------------------------------------------------------------
163 163
164 164
165 165 class LocateIPythonApp(BaseIPythonApplication):
166 166 description = """print the path to the IPython dir"""
167 subcommands = Dict(dict(
167 subcommands = dict(
168 168 profile=('IPython.core.profileapp.ProfileLocate',
169 169 "print the path to an IPython profile directory",
170 170 ),
171 ))
171 )
172 172 def start(self):
173 173 if self.subapp is not None:
174 174 return self.subapp.start()
175 175 else:
176 176 print(self.ipython_dir)
177 177
178 178
179 179 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
180 180 name = u'ipython'
181 181 description = usage.cl_usage
182 182 crash_handler_class = IPAppCrashHandler
183 183 examples = _examples
184 184
185 flags = Dict(flags)
186 aliases = Dict(aliases)
185 flags = flags
186 aliases = aliases
187 187 classes = List()
188 188
189 189 interactive_shell_class = Type(
190 190 klass=object, # use default_value otherwise which only allow subclasses.
191 191 default_value=TerminalInteractiveShell,
192 192 help="Class to use to instantiate the TerminalInteractiveShell object. Useful for custom Frontends"
193 193 ).tag(config=True)
194 194
195 195 @default('classes')
196 196 def _classes_default(self):
197 197 """This has to be in a method, for TerminalIPythonApp to be available."""
198 198 return [
199 199 InteractiveShellApp, # ShellApp comes before TerminalApp, because
200 200 self.__class__, # it will also affect subclasses (e.g. QtConsole)
201 201 TerminalInteractiveShell,
202 202 HistoryManager,
203 203 ProfileDir,
204 204 PlainTextFormatter,
205 205 IPCompleter,
206 206 ScriptMagics,
207 207 LoggingMagics,
208 208 StoreMagics,
209 209 ]
210 210
211 211 deprecated_subcommands = dict(
212 212 qtconsole=('qtconsole.qtconsoleapp.JupyterQtConsoleApp',
213 213 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter Qt Console."""
214 214 ),
215 215 notebook=('notebook.notebookapp.NotebookApp',
216 216 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter HTML Notebook Server."""
217 217 ),
218 218 console=('jupyter_console.app.ZMQTerminalIPythonApp',
219 219 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter terminal-based Console."""
220 220 ),
221 221 nbconvert=('nbconvert.nbconvertapp.NbConvertApp',
222 222 "DEPRECATED, Will be removed in IPython 6.0 : Convert notebooks to/from other formats."
223 223 ),
224 224 trust=('nbformat.sign.TrustNotebookApp',
225 225 "DEPRECATED, Will be removed in IPython 6.0 : Sign notebooks to trust their potentially unsafe contents at load."
226 226 ),
227 227 kernelspec=('jupyter_client.kernelspecapp.KernelSpecApp',
228 228 "DEPRECATED, Will be removed in IPython 6.0 : Manage Jupyter kernel specifications."
229 229 ),
230 230 )
231 231 subcommands = dict(
232 232 profile = ("IPython.core.profileapp.ProfileApp",
233 233 "Create and manage IPython profiles."
234 234 ),
235 235 kernel = ("ipykernel.kernelapp.IPKernelApp",
236 236 "Start a kernel without an attached frontend."
237 237 ),
238 238 locate=('IPython.terminal.ipapp.LocateIPythonApp',
239 239 LocateIPythonApp.description
240 240 ),
241 241 history=('IPython.core.historyapp.HistoryApp',
242 242 "Manage the IPython history database."
243 243 ),
244 244 )
245 245 deprecated_subcommands['install-nbextension'] = (
246 246 "notebook.nbextensions.InstallNBExtensionApp",
247 247 "DEPRECATED, Will be removed in IPython 6.0 : Install Jupyter notebook extension files"
248 248 )
249 249 subcommands.update(deprecated_subcommands)
250 250
251 251 # *do* autocreate requested profile, but don't create the config file.
252 252 auto_create=Bool(True)
253 253 # configurables
254 254 quick = Bool(False,
255 255 help="""Start IPython quickly by skipping the loading of config files."""
256 256 ).tag(config=True)
257 257 @observe('quick')
258 258 def _quick_changed(self, change):
259 259 if change['new']:
260 260 self.load_config_file = lambda *a, **kw: None
261 261
262 262 display_banner = Bool(True,
263 263 help="Whether to display a banner upon starting IPython."
264 264 ).tag(config=True)
265 265
266 266 # if there is code of files to run from the cmd line, don't interact
267 267 # unless the --i flag (App.force_interact) is true.
268 268 force_interact = Bool(False,
269 269 help="""If a command or file is given via the command-line,
270 270 e.g. 'ipython foo.py', start an interactive shell after executing the
271 271 file or command."""
272 272 ).tag(config=True)
273 273 @observe('force_interact')
274 274 def _force_interact_changed(self, change):
275 275 if change['new']:
276 276 self.interact = True
277 277
278 278 @observe('file_to_run', 'code_to_run', 'module_to_run')
279 279 def _file_to_run_changed(self, change):
280 280 new = change['new']
281 281 if new:
282 282 self.something_to_run = True
283 283 if new and not self.force_interact:
284 284 self.interact = False
285 285
286 286 # internal, not-configurable
287 287 something_to_run=Bool(False)
288 288
289 289 def parse_command_line(self, argv=None):
290 290 """override to allow old '-pylab' flag with deprecation warning"""
291 291
292 292 argv = sys.argv[1:] if argv is None else argv
293 293
294 294 if '-pylab' in argv:
295 295 # deprecated `-pylab` given,
296 296 # warn and transform into current syntax
297 297 argv = argv[:] # copy, don't clobber
298 298 idx = argv.index('-pylab')
299 299 warnings.warn("`-pylab` flag has been deprecated.\n"
300 300 " Use `--matplotlib <backend>` and import pylab manually.")
301 301 argv[idx] = '--pylab'
302 302
303 303 return super(TerminalIPythonApp, self).parse_command_line(argv)
304 304
305 305 @catch_config_error
306 306 def initialize(self, argv=None):
307 307 """Do actions after construct, but before starting the app."""
308 308 super(TerminalIPythonApp, self).initialize(argv)
309 309 if self.subapp is not None:
310 310 # don't bother initializing further, starting subapp
311 311 return
312 312 # print self.extra_args
313 313 if self.extra_args and not self.something_to_run:
314 314 self.file_to_run = self.extra_args[0]
315 315 self.init_path()
316 316 # create the shell
317 317 self.init_shell()
318 318 # and draw the banner
319 319 self.init_banner()
320 320 # Now a variety of things that happen after the banner is printed.
321 321 self.init_gui_pylab()
322 322 self.init_extensions()
323 323 self.init_code()
324 324
325 325 def init_shell(self):
326 326 """initialize the InteractiveShell instance"""
327 327 # Create an InteractiveShell instance.
328 328 # shell.display_banner should always be False for the terminal
329 329 # based app, because we call shell.show_banner() by hand below
330 330 # so the banner shows *before* all extension loading stuff.
331 331 self.shell = self.interactive_shell_class.instance(parent=self,
332 332 profile_dir=self.profile_dir,
333 333 ipython_dir=self.ipython_dir, user_ns=self.user_ns)
334 334 self.shell.configurables.append(self)
335 335
336 336 def init_banner(self):
337 337 """optionally display the banner"""
338 338 if self.display_banner and self.interact:
339 339 self.shell.show_banner()
340 340 # Make sure there is a space below the banner.
341 341 if self.log_level <= logging.INFO: print()
342 342
343 343 def _pylab_changed(self, name, old, new):
344 344 """Replace --pylab='inline' with --pylab='auto'"""
345 345 if new == 'inline':
346 346 warnings.warn("'inline' not available as pylab backend, "
347 347 "using 'auto' instead.")
348 348 self.pylab = 'auto'
349 349
350 350 def start(self):
351 351 if self.subapp is not None:
352 352 return self.subapp.start()
353 353 # perform any prexec steps:
354 354 if self.interact:
355 355 self.log.debug("Starting IPython's mainloop...")
356 356 self.shell.mainloop()
357 357 else:
358 358 self.log.debug("IPython not interactive...")
359 359
360 360 def load_default_config(ipython_dir=None):
361 361 """Load the default config file from the default ipython_dir.
362 362
363 363 This is useful for embedded shells.
364 364 """
365 365 if ipython_dir is None:
366 366 ipython_dir = get_ipython_dir()
367 367
368 368 profile_dir = os.path.join(ipython_dir, 'profile_default')
369 369 app = TerminalIPythonApp()
370 370 app.config_file_paths.append(profile_dir)
371 371 app.load_config_file()
372 372 return app.config
373 373
374 374 launch_new_instance = TerminalIPythonApp.launch_instance
375 375
376 376
377 377 if __name__ == '__main__':
378 378 launch_new_instance()
General Comments 0
You need to be logged in to leave comments. Login now