##// END OF EJS Templates
allow utils.text.indent to [optionally] flatten existing indentation.
allow utils.text.indent to [optionally] flatten existing indentation.

File last commit:

r3943:1b5d4b7e
r3943:1b5d4b7e
Show More
application.py
241 lines | 8.2 KiB | text/x-python | PythonLexer
Brian Granger
Created config.application and updated Configurable.
r3790 # encoding: utf-8
"""
A base class for a configurable application.
Authors:
* Brian Granger
"""
#-----------------------------------------------------------------------------
# Copyright (C) 2008-2011 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
#-----------------------------------------------------------------------------
from copy import deepcopy
Brian Granger
IPython.config.application.Application updates....
r3794 import logging
Brian Granger
Created config.application and updated Configurable.
r3790 import sys
Brian Granger
IPython.config.application.Application updates....
r3794 from IPython.config.configurable import SingletonConfigurable
Brian Granger
Created config.application and updated Configurable.
r3790 from IPython.config.loader import (
MinRK
rename macros/shortnames to flags/aliases...
r3861 KeyValueConfigLoader, PyFileConfigLoader, Config
Brian Granger
Created config.application and updated Configurable.
r3790 )
MinRK
move shortname to Application...
r3852 from IPython.utils.traitlets import (
Unicode, List, Int, Enum, Dict
)
from IPython.utils.text import indent
Brian Granger
Created config.application and updated Configurable.
r3790 #-----------------------------------------------------------------------------
MinRK
add descriptions for the various help sections
r3855 # Descriptions for
#-----------------------------------------------------------------------------
MinRK
rename macros/shortnames to flags/aliases...
r3861 flag_description = """
MinRK
add descriptions for the various help sections
r3855 Flags are command-line arguments passed as '--<flag>'.
These take no parameters, unlike regular key-value arguments.
They are typically used for setting boolean flags, or enabling
modes that involve setting multiple options together.
""".strip() # trim newlines of front and back
MinRK
rename macros/shortnames to flags/aliases...
r3861 alias_description = """
MinRK
add descriptions for the various help sections
r3855 These are commonly set parameters, given abbreviated aliases for convenience.
They are set in the same `name=value` way as class parameters, where
<name> is replaced by the real parameter for which it is an alias.
""".strip() # trim newlines of front and back
keyvalue_description = """
Parameters are set from command-line arguments of the form:
`Class.trait=value`. Parameters will *never* be prefixed with '-'.
This line is evaluated in Python, so simple expressions are allowed, e.g.
`C.a='range(3)'` For setting C.a=[0,1,2]
""".strip() # trim newlines of front and back
#-----------------------------------------------------------------------------
Brian Granger
Created config.application and updated Configurable.
r3790 # Application class
#-----------------------------------------------------------------------------
Brian Granger
Updates to config/application.
r3940 class ApplicationError(Exception):
pass
Brian Granger
IPython.config.application.Application updates....
r3794 class Application(SingletonConfigurable):
Brian Granger
Adding more documentation to config.application related files.
r3796 """A singleton application with full configuration support."""
Brian Granger
Created config.application and updated Configurable.
r3790
# The name of the application, will usually match the name of the command
# line application
Brian Granger
Fixing bugs in BaseIPythonApplication....
r3942 name = Unicode(u'application')
Brian Granger
Created config.application and updated Configurable.
r3790
# The description of the application that is printed at the beginning
# of the help.
description = Unicode(u'This is an application.')
MinRK
add descriptions for the various help sections
r3855 # default section descriptions
MinRK
rename macros/shortnames to flags/aliases...
r3861 flag_description = Unicode(flag_description)
alias_description = Unicode(alias_description)
MinRK
add descriptions for the various help sections
r3855 keyvalue_description = Unicode(keyvalue_description)
Brian Granger
Created config.application and updated Configurable.
r3790
# A sequence of Configurable subclasses whose config=True attributes will
MinRK
rename macros/shortnames to flags/aliases...
r3861 # be exposed at the command line.
Brian Granger
Created config.application and updated Configurable.
r3790 classes = List([])
# The version string of this application.
version = Unicode(u'0.0')
Brian Granger
Added tests for IPython.config.application.Application
r3795 # The log level for the application
log_level = Enum((0,10,20,30,40,50), default_value=logging.WARN,
MinRK
move shortname to Application...
r3852 config=True,
Brian Granger
Added tests for IPython.config.application.Application
r3795 help="Set the log level (0,10,20,30,40,50).")
MinRK
move shortname to Application...
r3852
MinRK
rename macros/shortnames to flags/aliases...
r3861 # the alias map for configurables
aliases = Dict(dict(log_level='Application.log_level'))
MinRK
move shortname to Application...
r3852
MinRK
rename macros/shortnames to flags/aliases...
r3861 # flags for loading Configurables or store_const style flags
# flags are loaded from this dict by '--key' flags
# this must be a dict of two-tuples, the first element being the Config/dict
# and the second being the help string for the flag
flags = Dict()
MinRK
move shortname to Application...
r3852
Brian Granger
IPython.config.application.Application updates....
r3794
Brian Granger
Created config.application and updated Configurable.
r3790 def __init__(self, **kwargs):
Brian Granger
IPython.config.application.Application updates....
r3794 SingletonConfigurable.__init__(self, **kwargs)
Brian Granger
Created config.application and updated Configurable.
r3790 # Add my class to self.classes so my attributes appear in command line
# options.
self.classes.insert(0, self.__class__)
MinRK
move shortname to Application...
r3852
MinRK
rename macros/shortnames to flags/aliases...
r3861 # ensure self.flags dict is valid
for key,value in self.flags.iteritems():
assert len(value) == 2, "Bad flag: %r:%s"%(key,value)
assert isinstance(value[0], (dict, Config)), "Bad flag: %r:%s"%(key,value)
assert isinstance(value[1], basestring), "Bad flag: %r:%s"%(key,value)
Brian Granger
IPython.config.application.Application updates....
r3794 self.init_logging()
Brian Granger
Updates to config/application.
r3940
def _config_changed(self, name, old, new):
SingletonConfigurable._config_changed(self, name, old, new)
self.log.debug('Config changed:')
self.log.debug(repr(new))
Brian Granger
IPython.config.application.Application updates....
r3794 def init_logging(self):
"""Start logging for this application.
The default is to log to stdout using a StreaHandler. The log level
starts at loggin.WARN, but this can be adjusted by setting the
``log_level`` attribute.
"""
self.log = logging.getLogger(self.__class__.__name__)
self.log.setLevel(self.log_level)
self._log_handler = logging.StreamHandler()
self._log_formatter = logging.Formatter("[%(name)s] %(message)s")
self._log_handler.setFormatter(self._log_formatter)
self.log.addHandler(self._log_handler)
def _log_level_changed(self, name, old, new):
"""Adjust the log level when log_level is set."""
self.log.setLevel(new)
MinRK
move shortname to Application...
r3852
MinRK
rename macros/shortnames to flags/aliases...
r3861 def print_alias_help(self):
"""print the alias part of the help"""
if not self.aliases:
MinRK
move shortname to Application...
r3852 return
print "Aliases"
print "-------"
MinRK
rename macros/shortnames to flags/aliases...
r3861 print self.alias_description
MinRK
add descriptions for the various help sections
r3855 print
MinRK
move shortname to Application...
r3852 classdict = {}
for c in self.classes:
classdict[c.__name__] = c
MinRK
add descriptions for the various help sections
r3855
MinRK
rename macros/shortnames to flags/aliases...
r3861 for alias, longname in self.aliases.iteritems():
MinRK
move shortname to Application...
r3852 classname, traitname = longname.split('.',1)
cls = classdict[classname]
trait = cls.class_traits(config=True)[traitname]
help = trait.get_metadata('help')
MinRK
rename macros/shortnames to flags/aliases...
r3861 print alias, "(%s)"%longname, ':', trait.__class__.__name__
MinRK
move shortname to Application...
r3852 if help:
MinRK
allow utils.text.indent to [optionally] flatten existing indentation.
r3943 print indent(help, flatten=True)
MinRK
move shortname to Application...
r3852 print
MinRK
rename macros/shortnames to flags/aliases...
r3861 def print_flag_help(self):
"""print the flag part of the help"""
if not self.flags:
MinRK
move shortname to Application...
r3852 return
print "Flags"
print "-----"
MinRK
rename macros/shortnames to flags/aliases...
r3861 print self.flag_description
MinRK
add descriptions for the various help sections
r3855 print
MinRK
move shortname to Application...
r3852
MinRK
rename macros/shortnames to flags/aliases...
r3861 for m, (cfg,help) in self.flags.iteritems():
MinRK
move shortname to Application...
r3852 print '--'+m
MinRK
allow utils.text.indent to [optionally] flatten existing indentation.
r3943 print indent(help, flatten=True)
MinRK
move shortname to Application...
r3852 print
Brian Granger
Created config.application and updated Configurable.
r3790 def print_help(self):
"""Print the help for each Configurable class in self.classes."""
MinRK
rename macros/shortnames to flags/aliases...
r3861 self.print_flag_help()
self.print_alias_help()
MinRK
add descriptions for the various help sections
r3855 if self.classes:
print "Class parameters"
print "----------------"
print self.keyvalue_description
print
Brian Granger
Created config.application and updated Configurable.
r3790 for cls in self.classes:
cls.class_print_help()
print
def print_description(self):
"""Print the application description."""
print self.description
print
def print_version(self):
"""Print the version string."""
print self.version
def update_config(self, config):
Brian Granger
Adding more documentation to config.application related files.
r3796 """Fire the traits events when the config is updated."""
Brian Granger
Created config.application and updated Configurable.
r3790 # Save a copy of the current config.
newconfig = deepcopy(self.config)
# Merge the new config into the current one.
newconfig._merge(config)
# Save the combined config as self.config, which triggers the traits
# events.
Brian Granger
Fixing minor bug in config.application.
r3941 self.config = newconfig
Brian Granger
Created config.application and updated Configurable.
r3790
def parse_command_line(self, argv=None):
"""Parse the command line arguments."""
Brian Granger
Added tests for IPython.config.application.Application
r3795 argv = sys.argv[1:] if argv is None else argv
Brian Granger
Created config.application and updated Configurable.
r3790
MinRK
move shortname to Application...
r3852 if '-h' in argv or '--help' in argv:
Brian Granger
Created config.application and updated Configurable.
r3790 self.print_description()
self.print_help()
Brian Granger
Updates to config/application.
r3940 self.exit(1)
Brian Granger
Created config.application and updated Configurable.
r3790
if '--version' in argv:
self.print_version()
Brian Granger
Updates to config/application.
r3940 self.exit(1)
MinRK
rename macros/shortnames to flags/aliases...
r3861
loader = KeyValueConfigLoader(argv=argv, aliases=self.aliases,
flags=self.flags)
Brian Granger
Created config.application and updated Configurable.
r3790 config = loader.load_config()
self.update_config(config)
def load_config_file(self, filename, path=None):
"""Load a .py based config file by filename and path."""
loader = PyFileConfigLoader(filename, path=path)
config = loader.load_config()
self.update_config(config)
Brian Granger
Updates to config/application.
r3940 def exit(self, exit_status=0):
self.log.debug("Exiting application: %s" % self.name)
sys.exit(exit_status)