Source code for pyamp.config.configFile
# Copyright 2012 Brett Ponsler
# This file is part of pyamp.
#
# pyamp is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyamp is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pyamp. If not, see <http://www.gnu.org/licenses/>.
'''The configFile module contains the ConfigFile class which provides
the ability to parse a configuration file for configured :class:`Option`
objects.
'''
from os.path import exists
from ConfigParser import ConfigParser
from pyamp.logging import Loggable
__all__ = ["ConfigFile"]
[docs]class ConfigFile(Loggable):
'''The ConfigFile class is responsible for parsing a configuration file
with the given dictionary of sections and options, and variables.
The ConfigFile class takes a dictionary of options which map the
configuration section names to the list of configuration :class:`Option`
objects associated with that section. It also takes a dictionary of
variables mapping the name of the variable to the value for the variable.
The variable names can then be used in a configuration file by adding
a $ before the variable name. This value will then be replaced with the
value assigned in the variables dictionary.
This class implements the :class:`Loggable` interface. This class uses the
:mod:`ConfigParser` module to parse the configuration file, and thus parses
configuration files of the same format.
'''
def __init__(self, configurationFile=None, options=None, variables=None,
logger=None):
'''
* configurationFile -- The configuration file to load
* options -- The dictionary of supported options
* variables -- The dictionary of supported variables
* logger -- The logger
'''
Loggable.__init__(self, self.__class__.__name__, logger)
# Define the set of variables that can be used in the config file
# Note: Each variable must be used with a $ before it to indicate that
# it is a config variable that should be replaced. Variable names
# should also be all caps, and do not include spaces.
self.__variables = {} if variables is None else variables
# A dictionary mapping section names to the Option objects that each
# section contains
self.__options = {} if options is None else options
self.__settings = {}
# Initialize all of the variables which will store options
# prior to parsing the configuration file
for section, sectionOptions in self.__options.iteritems():
# Ensure that a list of options is given
objType = type(self.__options[section])
if objType != type(list()):
raise Exception("Section [%s] must have a list of options " \
"not a '%s'!" % (section, objType))
for option in sectionOptions:
setattr(self, option.getName(), option.getDefaultValue())
# Print all of the variables for debugging
for name, value in self.__variables.iteritems():
self.debug("Variable: [%s] = %s" % (name, str(value)), level=5)
if configurationFile is not None:
self.parse(configurationFile)
[docs] def getSettings(self):
'''Get the settings dictionary.'''
return self.__settings
[docs] def get(self, section, option, defaultValue=None):
'''Get the value of the given configuration option from the given
section.
* section -- The section name
* option -- The option
* defaultValue -- The default value if the option does not exist
'''
sectionOptions = self.__settings.get(section, {})
return sectionOptions.get(option, defaultValue)
[docs] def parse(self, filename):
'''Parse a configuration file.
* filename -- The configuration file to parse
'''
if exists(filename):
self.__configParser = ConfigParser()
self.__configParser.read(filename)
# Traverse all of the configuration sections found
for section in self.__configParser.sections():
configSection = self.__getSectionOptions(section)
# Determine if the section exists before proceeding
if configSection is not None:
# Create the section entry in our settings dictionary
if section not in self.__settings:
self.__settings[section] = {}
# Traverse all of the configuration options
for optionName in self.__configParser.options(section):
# Continue only if we found the current option
if optionName in configSection:
optionObj = configSection.get(optionName)
value = self.__configParser.get(section,
optionName)
finalValue = self.__getValue(optionObj, value)
self.__settings[section][optionName] = finalValue
else:
self.warn("Unknown configuration option " \
"[%s/%s]" % (section, optionName))
else:
self.warn("Unknown configuration section [%s]" % section)
def __getValue(self, optionObj, value):
'''Get the complete value for the given option.
* option -- The option
* value -- The value
'''
# Replace all variables, and convert the value to the expected type
optionValue = self.__replaceVariables(value)
return optionObj.convert(optionValue)
def __replaceVariables(self, optionValue):
'''Replace all variables found within the option value.
* optionValue -- The value of the option
'''
# Replace all of the variables with their corresponding replacements
for variable, replacement in self.__variables.iteritems():
variable = "$%s" % variable.upper()
optionValue = optionValue.replace(variable, replacement)
return optionValue
def __getSectionOptions(self, section):
'''Return a dictionary mapping Option names to the actual Option
objects for the given section.
* section -- The section
'''
optionsDict = {}
for option in self.__options.get(section, []):
if option is not None:
optionsDict[option.getName()] = option
return optionsDict