| |
| """ |
| The :class:`~traitlets.config.application.Application` object for the command |
| line :command:`ipython` program. |
| """ |
|
|
| |
| |
|
|
|
|
| import logging |
| import os |
| import sys |
| import warnings |
|
|
| from traitlets.config.loader import Config |
| from traitlets.config.application import boolean_flag, catch_config_error |
| from IPython.core import release |
| from IPython.core import usage |
| from IPython.core.completer import IPCompleter |
| from IPython.core.crashhandler import CrashHandler |
| from IPython.core.formatters import PlainTextFormatter |
| from IPython.core.history import HistoryManager |
| from IPython.core.application import ( |
| ProfileDir, BaseIPythonApplication, base_flags, base_aliases |
| ) |
| from IPython.core.magic import MagicsManager |
| from IPython.core.magics import ( |
| ScriptMagics, LoggingMagics |
| ) |
| from IPython.core.shellapp import ( |
| InteractiveShellApp, shell_flags, shell_aliases |
| ) |
| from IPython.extensions.storemagic import StoreMagics |
| from .interactiveshell import TerminalInteractiveShell |
| from IPython.paths import get_ipython_dir |
| from traitlets import ( |
| Bool, List, default, observe, Type |
| ) |
|
|
| |
| |
| |
|
|
| _examples = """ |
| ipython --matplotlib # enable matplotlib integration |
| ipython --matplotlib=qt # enable matplotlib integration with qt4 backend |
| |
| ipython --log-level=DEBUG # set logging to DEBUG |
| ipython --profile=foo # start with profile foo |
| |
| ipython profile create foo # create profile foo w/ default config files |
| ipython help profile # show the help for the profile subcmd |
| |
| ipython locate # print the path to the IPython directory |
| ipython locate profile foo # print the path to the directory for profile `foo` |
| """ |
|
|
| |
| |
| |
|
|
| class IPAppCrashHandler(CrashHandler): |
| """sys.excepthook for IPython itself, leaves a detailed report on disk.""" |
|
|
| def __init__(self, app): |
| contact_name = release.author |
| contact_email = release.author_email |
| bug_tracker = 'https://github.com/ipython/ipython/issues' |
| super(IPAppCrashHandler,self).__init__( |
| app, contact_name, contact_email, bug_tracker |
| ) |
|
|
| def make_report(self,traceback): |
| """Return a string containing a crash report.""" |
|
|
| sec_sep = self.section_sep |
| |
| report = [super(IPAppCrashHandler, self).make_report(traceback)] |
| |
| rpt_add = report.append |
| try: |
| rpt_add(sec_sep+"History of session input:") |
| for line in self.app.shell.user_ns['_ih']: |
| rpt_add(line) |
| rpt_add('\n*** Last line of input (may not be in above history):\n') |
| rpt_add(self.app.shell._last_input_line+'\n') |
| except: |
| pass |
|
|
| return ''.join(report) |
|
|
| |
| |
| |
| flags = dict(base_flags) |
| flags.update(shell_flags) |
| frontend_flags = {} |
| addflag = lambda *args: frontend_flags.update(boolean_flag(*args)) |
| addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax', |
| 'Turn on auto editing of files with syntax errors.', |
| 'Turn off auto editing of files with syntax errors.' |
| ) |
| addflag('simple-prompt', 'TerminalInteractiveShell.simple_prompt', |
| "Force simple minimal prompt using `raw_input`", |
| "Use a rich interactive prompt with prompt_toolkit", |
| ) |
|
|
| addflag('banner', 'TerminalIPythonApp.display_banner', |
| "Display a banner upon starting IPython.", |
| "Don't display a banner upon starting IPython." |
| ) |
| addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit', |
| """Set to confirm when you try to exit IPython with an EOF (Control-D |
| in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit', |
| you can force a direct exit without any confirmation.""", |
| "Don't prompt the user when exiting." |
| ) |
| addflag('term-title', 'TerminalInteractiveShell.term_title', |
| "Enable auto setting the terminal title.", |
| "Disable auto setting the terminal title." |
| ) |
| classic_config = Config() |
| classic_config.InteractiveShell.cache_size = 0 |
| classic_config.PlainTextFormatter.pprint = False |
| classic_config.TerminalInteractiveShell.prompts_class='IPython.terminal.prompts.ClassicPrompts' |
| classic_config.InteractiveShell.separate_in = '' |
| classic_config.InteractiveShell.separate_out = '' |
| classic_config.InteractiveShell.separate_out2 = '' |
| classic_config.InteractiveShell.colors = 'NoColor' |
| classic_config.InteractiveShell.xmode = 'Plain' |
|
|
| frontend_flags['classic']=( |
| classic_config, |
| "Gives IPython a similar feel to the classic Python prompt." |
| ) |
| |
| |
| |
| |
| |
| |
| frontend_flags['quick']=( |
| {'TerminalIPythonApp' : {'quick' : True}}, |
| "Enable quick startup with no config files." |
| ) |
|
|
| frontend_flags['i'] = ( |
| {'TerminalIPythonApp' : {'force_interact' : True}}, |
| """If running code from the command line, become interactive afterwards. |
| It is often useful to follow this with `--` to treat remaining flags as |
| script arguments. |
| """ |
| ) |
| flags.update(frontend_flags) |
|
|
| aliases = dict(base_aliases) |
| aliases.update(shell_aliases) |
|
|
| |
| |
| |
|
|
|
|
| class LocateIPythonApp(BaseIPythonApplication): |
| description = """print the path to the IPython dir""" |
| subcommands = dict( |
| profile=('IPython.core.profileapp.ProfileLocate', |
| "print the path to an IPython profile directory", |
| ), |
| ) |
| def start(self): |
| if self.subapp is not None: |
| return self.subapp.start() |
| else: |
| print(self.ipython_dir) |
|
|
|
|
| class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp): |
| name = "ipython" |
| description = usage.cl_usage |
| crash_handler_class = IPAppCrashHandler |
| examples = _examples |
|
|
| flags = flags |
| aliases = aliases |
| classes = List() |
|
|
| interactive_shell_class = Type( |
| klass=object, |
| default_value=TerminalInteractiveShell, |
| help="Class to use to instantiate the TerminalInteractiveShell object. Useful for custom Frontends" |
| ).tag(config=True) |
|
|
| @default('classes') |
| def _classes_default(self): |
| """This has to be in a method, for TerminalIPythonApp to be available.""" |
| return [ |
| InteractiveShellApp, |
| self.__class__, |
| TerminalInteractiveShell, |
| HistoryManager, |
| MagicsManager, |
| ProfileDir, |
| PlainTextFormatter, |
| IPCompleter, |
| ScriptMagics, |
| LoggingMagics, |
| StoreMagics, |
| ] |
|
|
| subcommands = dict( |
| profile = ("IPython.core.profileapp.ProfileApp", |
| "Create and manage IPython profiles." |
| ), |
| kernel = ("ipykernel.kernelapp.IPKernelApp", |
| "Start a kernel without an attached frontend." |
| ), |
| locate=('IPython.terminal.ipapp.LocateIPythonApp', |
| LocateIPythonApp.description |
| ), |
| history=('IPython.core.historyapp.HistoryApp', |
| "Manage the IPython history database." |
| ), |
| ) |
|
|
| |
| auto_create = Bool(True).tag(config=True) |
|
|
| |
| quick = Bool(False, |
| help="""Start IPython quickly by skipping the loading of config files.""" |
| ).tag(config=True) |
| @observe('quick') |
| def _quick_changed(self, change): |
| if change['new']: |
| self.load_config_file = lambda *a, **kw: None |
|
|
| display_banner = Bool(True, |
| help="Whether to display a banner upon starting IPython." |
| ).tag(config=True) |
|
|
| |
| |
| force_interact = Bool(False, |
| help="""If a command or file is given via the command-line, |
| e.g. 'ipython foo.py', start an interactive shell after executing the |
| file or command.""" |
| ).tag(config=True) |
| @observe('force_interact') |
| def _force_interact_changed(self, change): |
| if change['new']: |
| self.interact = True |
|
|
| @observe('file_to_run', 'code_to_run', 'module_to_run') |
| def _file_to_run_changed(self, change): |
| new = change['new'] |
| if new: |
| self.something_to_run = True |
| if new and not self.force_interact: |
| self.interact = False |
|
|
| |
| something_to_run=Bool(False) |
|
|
| @catch_config_error |
| def initialize(self, argv=None): |
| """Do actions after construct, but before starting the app.""" |
| super(TerminalIPythonApp, self).initialize(argv) |
| if self.subapp is not None: |
| |
| return |
| |
| if self.extra_args and not self.something_to_run: |
| self.file_to_run = self.extra_args[0] |
| self.init_path() |
| |
| self.init_shell() |
| |
| self.init_banner() |
| |
| self.init_gui_pylab() |
| self.init_extensions() |
| self.init_code() |
|
|
| def init_shell(self): |
| """initialize the InteractiveShell instance""" |
| |
| |
| |
| |
| self.shell = self.interactive_shell_class.instance(parent=self, |
| profile_dir=self.profile_dir, |
| ipython_dir=self.ipython_dir, user_ns=self.user_ns) |
| self.shell.configurables.append(self) |
|
|
| def init_banner(self): |
| """optionally display the banner""" |
| if self.display_banner and self.interact: |
| self.shell.show_banner() |
| |
| if self.log_level <= logging.INFO: print() |
|
|
| def _pylab_changed(self, name, old, new): |
| """Replace --pylab='inline' with --pylab='auto'""" |
| if new == 'inline': |
| warnings.warn("'inline' not available as pylab backend, " |
| "using 'auto' instead.") |
| self.pylab = 'auto' |
|
|
| def start(self): |
| if self.subapp is not None: |
| return self.subapp.start() |
| |
| if self.interact: |
| self.log.debug("Starting IPython's mainloop...") |
| self.shell.mainloop() |
| else: |
| self.log.debug("IPython not interactive...") |
| self.shell.restore_term_title() |
| if not self.shell.last_execution_succeeded: |
| sys.exit(1) |
|
|
| def load_default_config(ipython_dir=None): |
| """Load the default config file from the default ipython_dir. |
| |
| This is useful for embedded shells. |
| """ |
| if ipython_dir is None: |
| ipython_dir = get_ipython_dir() |
|
|
| profile_dir = os.path.join(ipython_dir, 'profile_default') |
| app = TerminalIPythonApp() |
| app.config_file_paths.append(profile_dir) |
| app.load_config_file() |
| return app.config |
|
|
| launch_new_instance = TerminalIPythonApp.launch_instance |
|
|