Skip to content
This repository

Draft of new main BaseIPythonApplication. #453

Closed
wants to merge 2 commits into from

1 participant

Brian E. Granger
Brian E. Granger
Owner

This new BaseIPythonApplication should be used as a base class for all IPython applications.

Brian E. Granger
Owner

Reopening as ipython/newapp.

Brian E. Granger ellisonbg closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.

Showing 2 changed files with 147 additions and 4 deletions. Show diff stats Hide diff stats

  1. +15 4 IPython/config/application.py
  2. +132 0 IPython/core/newapplication.py
19 IPython/config/application.py
@@ -61,6 +61,10 @@
61 61 #-----------------------------------------------------------------------------
62 62
63 63
  64 +class ApplicationError(Exception):
  65 + pass
  66 +
  67 +
64 68 class Application(SingletonConfigurable):
65 69 """A singleton application with full configuration support."""
66 70
@@ -111,7 +115,12 @@ def __init__(self, **kwargs):
111 115 assert isinstance(value[0], (dict, Config)), "Bad flag: %r:%s"%(key,value)
112 116 assert isinstance(value[1], basestring), "Bad flag: %r:%s"%(key,value)
113 117 self.init_logging()
114   -
  118 +
  119 + def _config_changed(self, name, old, new):
  120 + SingletonConfigurable._config_changed(self, name, old, new)
  121 + self.log.debug('Config changed:')
  122 + self.log.debug(repr(new))
  123 +
115 124 def init_logging(self):
116 125 """Start logging for this application.
117 126
@@ -210,11 +219,11 @@ def parse_command_line(self, argv=None):
210 219 if '-h' in argv or '--help' in argv:
211 220 self.print_description()
212 221 self.print_help()
213   - sys.exit(1)
  222 + self.exit(1)
214 223
215 224 if '--version' in argv:
216 225 self.print_version()
217   - sys.exit(1)
  226 + self.exit(1)
218 227
219 228 loader = KeyValueConfigLoader(argv=argv, aliases=self.aliases,
220 229 flags=self.flags)
@@ -223,8 +232,10 @@ def parse_command_line(self, argv=None):
223 232
224 233 def load_config_file(self, filename, path=None):
225 234 """Load a .py based config file by filename and path."""
226   - # TODO: this raises IOError if filename does not exist.
227 235 loader = PyFileConfigLoader(filename, path=path)
228 236 config = loader.load_config()
229 237 self.update_config(config)
230 238
  239 + def exit(self, exit_status=0):
  240 + self.log.debug("Exiting application: %s" % self.name)
  241 + sys.exit(exit_status)
132 IPython/core/newapplication.py
... ... @@ -0,0 +1,132 @@
  1 +# encoding: utf-8
  2 +"""
  3 +An application for IPython.
  4 +
  5 +All top-level applications should use the classes in this module for
  6 +handling configuration and creating componenets.
  7 +
  8 +The job of an :class:`Application` is to create the master configuration
  9 +object and then create the configurable objects, passing the config to them.
  10 +
  11 +Authors:
  12 +
  13 +* Brian Granger
  14 +* Fernando Perez
  15 +
  16 +Notes
  17 +-----
  18 +"""
  19 +
  20 +#-----------------------------------------------------------------------------
  21 +# Copyright (C) 2008-2009 The IPython Development Team
  22 +#
  23 +# Distributed under the terms of the BSD License. The full license is in
  24 +# the file COPYING, distributed as part of this software.
  25 +#-----------------------------------------------------------------------------
  26 +
  27 +#-----------------------------------------------------------------------------
  28 +# Imports
  29 +#-----------------------------------------------------------------------------
  30 +
  31 +import os
  32 +import sys
  33 +
  34 +from IPython.config.application import Application
  35 +from IPython.core import release, crashhandler
  36 +from IPython.utils.path import get_ipython_dir, get_ipython_package_dir
  37 +from IPython.utils.traitlets import Tuple, Unicode, Type
  38 +
  39 +#-----------------------------------------------------------------------------
  40 +# Classes and functions
  41 +#-----------------------------------------------------------------------------
  42 +
  43 +
  44 +class BaseIPythonApplication(Application):
  45 +
  46 + app_name = Unicode(u'ipython')
  47 + description = Unicode(u'IPython: an enhanced interactive Python shell.')
  48 + version = Unicode(release.version)
  49 +
  50 + # The name of the default config file. Track separately from the actual
  51 + # name because some logic happens only if we aren't using the default.
  52 + default_config_file_name = Unicode(u'ipython_config.py')
  53 +
  54 + # The directory that contains IPython's builtin profiles.
  55 + builtin_profile_dir = Unicode(
  56 + os.path.join(get_ipython_package_dir(), u'config', u'profile')
  57 + )
  58 +
  59 + config_file_paths = Tuple(Unicode)
  60 + def _config_file_paths_default(self):
  61 + return (os.getcwdu(), self.ipython_dir, self.builtin_profile_dir)
  62 +
  63 + profile_name = Unicode(u'', config=True,
  64 + help="""The IPython profile to use."""
  65 + )
  66 +
  67 + ipython_dir = Unicode(get_ipython_dir(), config=True, help=
  68 + """
  69 + The name of the IPython directory. This directory is used for logging
  70 + configuration (through profiles), history storage, etc. The default
  71 + is usually $HOME/.ipython. This options can also be specified through
  72 + the environment variable IPYTHON_DIR.
  73 + """
  74 + )
  75 +
  76 + # The class to use as the crash handler.
  77 + crash_handler_class = Type(crashhandler.CrashHandler)
  78 +
  79 + #-------------------------------------------------------------------------
  80 + # Various stages of Application creation
  81 + #-------------------------------------------------------------------------
  82 +
  83 + def init_crash_handler(self):
  84 + """Create a crash handler, typically setting sys.excepthook to it."""
  85 + self.crash_handler = self.crash_handler_class(self)
  86 + sys.excepthook = self.crash_handler
  87 +
  88 + def _ipython_dir_changed(self, name, old, new):
  89 + if old in sys.path:
  90 + sys.path.remove(old)
  91 + sys.path.append(os.path.abspath(new))
  92 + if not os.path.isdir(new):
  93 + os.makedirs(new, mode=0777)
  94 + self.config_file_paths = (os.getcwdu(), new, self.builtin_profile_dir)
  95 + self.log.debug("IPYTHON_DIR set to: %s" % new)
  96 +
  97 + @property
  98 + def config_file_name(self):
  99 + """Find the config file name for this application."""
  100 + if self.profile_name:
  101 + name_parts = self.default_config_file_name.split('.')
  102 + name_parts.insert(1, u'_' + self.profile_name + u'.')
  103 + return ''.join(name_parts)
  104 + else:
  105 + return self.default_config_file_name
  106 +
  107 + def load_config_file(self, suppress_errors=True):
  108 + """Load the config file.
  109 +
  110 + By default, errors in loading config are handled, and a warning
  111 + printed on screen. For testing, the suppress_errors option is set
  112 + to False, so errors will make tests fail.
  113 + """
  114 + self.log.debug("Attempting to load config file: %s" %
  115 + self.config_file_name)
  116 + try:
  117 + Application.load_config_file(
  118 + self,
  119 + self.config_file_name,
  120 + path=self.config_file_paths
  121 + )
  122 + except IOError:
  123 + # Only warn if the default config file was NOT being used.
  124 + if not self.config_file_name == self.default_config_file_name:
  125 + self.log.warn("Config file not found, skipping: %s" %
  126 + self.config_file_name, exc_info=True)
  127 + except:
  128 + if not suppress_errors: # For testing purposes
  129 + raise
  130 + self.log.warn("Error loading config file: %s" %
  131 + self.config_file_name, exc_info=True)
  132 +

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.