##// END OF EJS Templates
rename core.newapplication -> core.application
rename core.newapplication -> core.application

File last commit:

r4023:0869c345
r4023:0869c345
Show More
application.py
429 lines | 15.6 KiB | text/x-python | PythonLexer
Brian Granger
Working version of the new config loaders for .py files and argparse.
r2185 # encoding: utf-8
"""
Brian Granger
ipcontroller/ipengine use the new clusterdir.py module.
r2301 An application for IPython.
All top-level applications should use the classes in this module for
handling configuration and creating componenets.
The job of an :class:`Application` is to create the master configuration
Brian Granger
First draft of refactored Component->Configurable.
r2731 object and then create the configurable objects, passing the config to them.
Brian Granger
Working version of the new config loaders for .py files and argparse.
r2185
Authors:
* Brian Granger
* Fernando Perez
MinRK
rename core.newapplication -> core.application
r4023 * Min RK
Brian Granger
Working version of the new config loaders for .py files and argparse.
r2185
Notes
-----
"""
#-----------------------------------------------------------------------------
# Copyright (C) 2008-2009 The IPython Development Team
#
# Distributed under the terms of the BSD License. The full license is in
# the file COPYING, distributed as part of this software.
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
Brian Granger
Work on startup related things....
r2252 import logging
Brian Granger
Semi-final Application and minor work on traitlets.
r2200 import os
MinRK
rename core.newapplication -> core.application
r4023 import shutil
Brian Granger
Working version of the new config loaders for .py files and argparse.
r2185 import sys
Brian Granger
Massive refactoring of of the core....
r2245
MinRK
rename core.newapplication -> core.application
r4023 from IPython.config.application import Application
from IPython.config.configurable import Configurable
from IPython.config.loader import Config
Fernando Perez
Move crash handling to the application level and simplify class structure....
r2403 from IPython.core import release, crashhandler
MinRK
rename core.newapplication -> core.application
r4023 from IPython.utils.path import get_ipython_dir, get_ipython_package_dir, expand_path
from IPython.utils.traitlets import List, Unicode, Type, Bool, Dict
Brian Granger
Working version of the new config loaders for .py files and argparse.
r2185
#-----------------------------------------------------------------------------
# Classes and functions
#-----------------------------------------------------------------------------
MinRK
rename core.newapplication -> core.application
r4023
#-----------------------------------------------------------------------------
# Module errors
#-----------------------------------------------------------------------------
class ProfileDirError(Exception):
Brian Granger
Working version of the new config loaders for .py files and argparse.
r2185 pass
MinRK
rename core.newapplication -> core.application
r4023 #-----------------------------------------------------------------------------
# Class for managing profile directories
#-----------------------------------------------------------------------------
Brian Granger
Working version of the new config loaders for .py files and argparse.
r2185
MinRK
rename core.newapplication -> core.application
r4023 class ProfileDir(Configurable):
"""An object to manage the profile directory and its resources.
Fernando Perez
Move crash handling to the application level and simplify class structure....
r2403
MinRK
rename core.newapplication -> core.application
r4023 The profile directory is used by all IPython applications, to manage
configuration, logging and security.
Brian Granger
Work on Application and loader testing.
r2187
MinRK
rename core.newapplication -> core.application
r4023 This object knows how to find, create and manage these directories. This
should be used by any code that wants to handle profiles.
"""
Brian Granger
Work on Application and loader testing.
r2187
MinRK
rename core.newapplication -> core.application
r4023 security_dir_name = Unicode('security')
log_dir_name = Unicode('log')
pid_dir_name = Unicode('pid')
security_dir = Unicode(u'')
log_dir = Unicode(u'')
pid_dir = Unicode(u'')
location = Unicode(u'', config=True,
help="""Set the profile location directly. This overrides the logic used by the
`profile` option.""",
)
Fernando Perez
Move crash handling to the application level and simplify class structure....
r2403
MinRK
rename core.newapplication -> core.application
r4023 _location_isset = Bool(False) # flag for detecting multiply set location
Brian Granger
All code startup related things are working....
r2253
MinRK
rename core.newapplication -> core.application
r4023 def _location_changed(self, name, old, new):
if self._location_isset:
raise RuntimeError("Cannot set profile location more than once.")
self._location_isset = True
if not os.path.isdir(new):
os.makedirs(new)
# ensure config files exist:
self.security_dir = os.path.join(new, self.security_dir_name)
self.log_dir = os.path.join(new, self.log_dir_name)
self.pid_dir = os.path.join(new, self.pid_dir_name)
self.check_dirs()
Brian Granger
General work on the kernel config.
r2294
MinRK
rename core.newapplication -> core.application
r4023 def _log_dir_changed(self, name, old, new):
self.check_log_dir()
Brian Granger
Semi-final Application and minor work on traitlets.
r2200
MinRK
rename core.newapplication -> core.application
r4023 def check_log_dir(self):
if not os.path.isdir(self.log_dir):
os.mkdir(self.log_dir)
Brian Granger
Semi-final Application and minor work on traitlets.
r2200
MinRK
rename core.newapplication -> core.application
r4023 def _security_dir_changed(self, name, old, new):
self.check_security_dir()
Brian Granger
Work on Application and loader testing.
r2187
MinRK
rename core.newapplication -> core.application
r4023 def check_security_dir(self):
if not os.path.isdir(self.security_dir):
os.mkdir(self.security_dir, 0700)
else:
os.chmod(self.security_dir, 0700)
Brian Granger
Work on startup related things....
r2252
MinRK
rename core.newapplication -> core.application
r4023 def _pid_dir_changed(self, name, old, new):
self.check_pid_dir()
Brian Granger
Semi-final Application and minor work on traitlets.
r2200
MinRK
rename core.newapplication -> core.application
r4023 def check_pid_dir(self):
if not os.path.isdir(self.pid_dir):
os.mkdir(self.pid_dir, 0700)
else:
os.chmod(self.pid_dir, 0700)
Brian Granger
Working version of the new config loaders for .py files and argparse.
r2185
MinRK
rename core.newapplication -> core.application
r4023 def check_dirs(self):
self.check_security_dir()
self.check_log_dir()
self.check_pid_dir()
Brian Granger
General work on the kernel config.
r2294
MinRK
rename core.newapplication -> core.application
r4023 def copy_config_file(self, config_file, path=None, overwrite=False):
"""Copy a default config file into the active profile directory.
Brian Granger
Semi-final Application and minor work on traitlets.
r2200
MinRK
rename core.newapplication -> core.application
r4023 Default configuration files are kept in :mod:`IPython.config.default`.
This function moves these from that location to the working profile
directory.
Brian Granger
Semi-final Application and minor work on traitlets.
r2200 """
MinRK
rename core.newapplication -> core.application
r4023 dst = os.path.join(self.location, config_file)
if os.path.isfile(dst) and not overwrite:
return
if path is None:
path = os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
src = os.path.join(path, config_file)
shutil.copy(src, dst)
@classmethod
def create_profile_dir(cls, profile_dir, config=None):
"""Create a new profile directory given a full path.
Parameters
----------
profile_dir : str
The full path to the profile directory. If it does exist, it will
be used. If not, it will be created.
"""
return cls(location=profile_dir, config=config)
@classmethod
def create_profile_dir_by_name(cls, path, name=u'default', config=None):
"""Create a profile dir by profile name and path.
Parameters
----------
path : unicode
The path (directory) to put the profile directory in.
name : unicode
The name of the profile. The name of the profile directory will
be "profile_<profile>".
Brian Granger
Lots more work on the kernel scripts.
r2303 """
MinRK
rename core.newapplication -> core.application
r4023 if not os.path.isdir(path):
raise ProfileDirError('Directory not found: %s' % path)
profile_dir = os.path.join(path, u'profile_' + name)
return cls(location=profile_dir, config=config)
@classmethod
def find_profile_dir_by_name(cls, ipython_dir, name=u'default', config=None):
"""Find an existing profile dir by profile name, return its ProfileDir.
This searches through a sequence of paths for a profile dir. If it
is not found, a :class:`ProfileDirError` exception will be raised.
The search path algorithm is:
1. ``os.getcwd()``
2. ``ipython_dir``
Parameters
----------
ipython_dir : unicode or str
The IPython directory to use.
name : unicode or str
The name of the profile. The name of the profile directory
will be "profile_<profile>".
"""
dirname = u'profile_' + name
paths = [os.getcwdu(), ipython_dir]
for p in paths:
profile_dir = os.path.join(p, dirname)
if os.path.isdir(profile_dir):
return cls(location=profile_dir, config=config)
else:
raise ProfileDirError('Profile directory not found in paths: %s' % dirname)
Brian Granger
Lots more work on the kernel scripts.
r2303
MinRK
rename core.newapplication -> core.application
r4023 @classmethod
def find_profile_dir(cls, profile_dir, config=None):
"""Find/create a profile dir and return its ProfileDir.
Brian Granger
Semi-final Application and minor work on traitlets.
r2200
MinRK
rename core.newapplication -> core.application
r4023 This will create the profile directory if it doesn't exist.
Brian Granger
General work on the kernel config.
r2294
MinRK
rename core.newapplication -> core.application
r4023 Parameters
----------
profile_dir : unicode or str
The path of the profile directory. This is expanded using
:func:`IPython.utils.genutils.expand_path`.
Brian Granger
Semi-final Application and minor work on traitlets.
r2200 """
MinRK
rename core.newapplication -> core.application
r4023 profile_dir = expand_path(profile_dir)
if not os.path.isdir(profile_dir):
raise ProfileDirError('Profile directory not found: %s' % profile_dir)
return cls(location=profile_dir, config=config)
Brian Granger
More work on getting rid of ipmaker.
r2203
Brian Granger
Semi-final Application and minor work on traitlets.
r2200
MinRK
rename core.newapplication -> core.application
r4023 #-----------------------------------------------------------------------------
# Base Application Class
#-----------------------------------------------------------------------------
# aliases and flags
base_aliases = dict(
profile='BaseIPythonApplication.profile',
ipython_dir='BaseIPythonApplication.ipython_dir',
)
Brian Granger
General work on the kernel config.
r2294
MinRK
rename core.newapplication -> core.application
r4023 base_flags = dict(
debug = ({'Application' : {'log_level' : logging.DEBUG}},
"set log level to logging.DEBUG (maximize logging output)"),
quiet = ({'Application' : {'log_level' : logging.CRITICAL}},
"set log level to logging.CRITICAL (minimize logging output)"),
init = ({'BaseIPythonApplication' : {
'copy_config_files' : True,
'auto_create' : True}
}, "Initialize profile with default config files")
)
class BaseIPythonApplication(Application):
name = Unicode(u'ipython')
description = Unicode(u'IPython: an enhanced interactive Python shell.')
version = Unicode(release.version)
aliases = Dict(base_aliases)
flags = Dict(base_flags)
# Track whether the config_file has changed,
# because some logic happens only if we aren't using the default.
config_file_specified = Bool(False)
config_file_name = Unicode(u'ipython_config.py')
def _config_file_name_changed(self, name, old, new):
if new != old:
self.config_file_specified = True
# The directory that contains IPython's builtin profiles.
builtin_profile_dir = Unicode(
os.path.join(get_ipython_package_dir(), u'config', u'profile', u'default')
)
config_file_paths = List(Unicode)
def _config_file_paths_default(self):
return [os.getcwdu()]
profile = Unicode(u'default', config=True,
help="""The IPython profile to use."""
)
def _profile_changed(self, name, old, new):
self.builtin_profile_dir = os.path.join(
get_ipython_package_dir(), u'config', u'profile', new
)
ipython_dir = Unicode(get_ipython_dir(), config=True,
help="""
The name of the IPython directory. This directory is used for logging
configuration (through profiles), history storage, etc. The default
is usually $HOME/.ipython. This options can also be specified through
the environment variable IPYTHON_DIR.
Brian Granger
General work on the kernel config.
r2294 """
MinRK
rename core.newapplication -> core.application
r4023 )
overwrite = Bool(False, config=True,
help="""Whether to overwrite existing config files when copying""")
auto_create = Bool(False, config=True,
help="""Whether to create profile dir if it doesn't exist""")
config_files = List(Unicode)
def _config_files_default(self):
return [u'ipython_config.py']
copy_config_files = Bool(False, config=True,
help="""Whether to copy the default config files into the profile dir.""")
# The class to use as the crash handler.
crash_handler_class = Type(crashhandler.CrashHandler)
def __init__(self, **kwargs):
super(BaseIPythonApplication, self).__init__(**kwargs)
# ensure even default IPYTHON_DIR exists
if not os.path.exists(self.ipython_dir):
self._ipython_dir_changed('ipython_dir', self.ipython_dir, self.ipython_dir)
#-------------------------------------------------------------------------
# Various stages of Application creation
#-------------------------------------------------------------------------
Brian Granger
Semi-final Application and minor work on traitlets.
r2200
MinRK
rename core.newapplication -> core.application
r4023 def init_crash_handler(self):
"""Create a crash handler, typically setting sys.excepthook to it."""
self.crash_handler = self.crash_handler_class(self)
sys.excepthook = self.crash_handler
Brian Granger
Working version of the new config loaders for .py files and argparse.
r2185
MinRK
rename core.newapplication -> core.application
r4023 def _ipython_dir_changed(self, name, old, new):
if old in sys.path:
sys.path.remove(old)
sys.path.append(os.path.abspath(new))
if not os.path.isdir(new):
os.makedirs(new, mode=0777)
readme = os.path.join(new, 'README')
if not os.path.exists(readme):
path = os.path.join(get_ipython_package_dir(), u'config', u'profile')
shutil.copy(os.path.join(path, 'README'), readme)
self.log.debug("IPYTHON_DIR set to: %s" % new)
def load_config_file(self, suppress_errors=True):
Brian Granger
Semi-final Application and minor work on traitlets.
r2200 """Load the config file.
MinRK
rename core.newapplication -> core.application
r4023
Thomas Kluyver
Tweak code with suggestions from yesterday.
r3458 By default, errors in loading config are handled, and a warning
printed on screen. For testing, the suppress_errors option is set
to False, so errors will make tests fail.
Brian Granger
Semi-final Application and minor work on traitlets.
r2200 """
Fernando Perez
Improve pylab support, find profiles in IPython's own directory....
r2357 self.log.debug("Attempting to load config file: %s" %
self.config_file_name)
Brian Granger
Semi-final Application and minor work on traitlets.
r2200 try:
MinRK
rename core.newapplication -> core.application
r4023 Application.load_config_file(
self,
self.config_file_name,
path=self.config_file_paths
)
Brian Granger
Semi-final Application and minor work on traitlets.
r2200 except IOError:
Brian Granger
Don't warn the user if the default config file is missing....
r2257 # Only warn if the default config file was NOT being used.
MinRK
rename core.newapplication -> core.application
r4023 if self.config_file_specified:
Fernando Perez
Improve pylab support, find profiles in IPython's own directory....
r2357 self.log.warn("Config file not found, skipping: %s" %
MinRK
rename core.newapplication -> core.application
r4023 self.config_file_name)
Brian Granger
Work on startup related things....
r2252 except:
MinRK
rename core.newapplication -> core.application
r4023 # For testing purposes.
if not suppress_errors:
Thomas Kluyver
IPython behaves properly when started in a directory with non-ascii characters in the name. + Unit test....
r3451 raise
Fernando Perez
Improve pylab support, find profiles in IPython's own directory....
r2357 self.log.warn("Error loading config file: %s" %
Brian Granger
Beginning to transition all paths, files, dirs over to unicode....
r2328 self.config_file_name, exc_info=True)
Brian Granger
General work on the kernel config.
r2294
MinRK
rename core.newapplication -> core.application
r4023 def init_profile_dir(self):
"""initialize the profile dir"""
try:
# location explicitly specified:
location = self.config.ProfileDir.location
except AttributeError:
# location not specified, find by profile name
Brian Granger
Fixing minor bug with the logging level in ipapp.py.
r2270 try:
MinRK
rename core.newapplication -> core.application
r4023 p = ProfileDir.find_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
except ProfileDirError:
# not found, maybe create it (always create default profile)
if self.auto_create or self.profile=='default':
try:
p = ProfileDir.create_profile_dir_by_name(self.ipython_dir, self.profile, self.config)
except ProfileDirError:
self.log.fatal("Could not create profile: %r"%self.profile)
self.exit(1)
else:
self.log.info("Created profile dir: %r"%p.location)
else:
self.log.fatal("Profile %r not found."%self.profile)
self.exit(1)
else:
self.log.info("Using existing profile dir: %r"%p.location)
Brian Granger
Lots more work on the kernel scripts.
r2303 else:
MinRK
rename core.newapplication -> core.application
r4023 # location is fully specified
try:
p = ProfileDir.find_profile_dir(location, self.config)
except ProfileDirError:
# not found, maybe create it
if self.auto_create:
try:
p = ProfileDir.create_profile_dir(location, self.config)
except ProfileDirError:
self.log.fatal("Could not create profile directory: %r"%location)
self.exit(1)
else:
self.log.info("Creating new profile dir: %r"%location)
else:
self.log.fatal("Profile directory %r not found."%location)
self.exit(1)
else:
self.log.info("Using existing profile dir: %r"%location)
self.profile_dir = p
self.config_file_paths.append(p.location)
def init_config_files(self):
"""[optionally] copy default config files into profile dir."""
# copy config files
if self.copy_config_files:
path = self.builtin_profile_dir
src = self.profile
if not os.path.exists(path):
# use default if new profile doesn't have a preset
path = None
src = 'default'
self.log.debug("Staging %s config files into %r [overwrite=%s]"%(
src, self.profile_dir.location, self.overwrite)
)
for cfg in self.config_files:
self.profile_dir.copy_config_file(cfg, path=path, overwrite=self.overwrite)
def initialize(self, argv=None):
self.init_crash_handler()
self.parse_command_line(argv)
cl_config = self.config
self.init_profile_dir()
self.init_config_files()
self.load_config_file()
# enforce cl-opts override configfile opts:
self.update_config(cl_config)
Brian Granger
Work on ipcontroller....
r2296