capisuite/src/capisuite-py/config.py.in

226 lines
8.0 KiB
Python

# -*- mode: python -*-
"""capisuite.config
Handling of configuration and job description files.
This file contains CSConfigParser, a configuration parser derived from the
default Python parsers, but adapted to the needs of CapiSuite.
Additionally, the class JobDescription is defined, which allows to read and
write special text files used to store meta data about incoming and outgoing
voice and fax jobs/calls.
"""
__author__ = "Hartmut Goebel <h.goebel@crazy-compilers.com>"
__copyright__ = "Copyright (c) 2004 by Hartmut Goebel"
__version__ = "$Revision: 0.0 $"
__credits__ = "This is part of www.capisuite.de; thanks to Gernot Hillier"
__license__ = """
This program 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 2 of the License, or
(at your option) any later version.
"""
import os.path, types, string
# the name of the config file read by the scripts; see there for
# options and descriptions
pkgsysconfdir = "@pkgsysconfdir@"
configfile_fax = os.path.join(pkgsysconfdir, "fax.conf")
configfile_voice = os.path.join(pkgsysconfdir, "answering_machine.conf")
__all__ = ['configfile_fax', 'configfile_voice',
'CSConfigParser', 'JobDescription',
'readGlobalConfig', 'readDescription', 'createDescriptionFor',
'NoOptionError', 'NoGlobalSectionError']
# try to use RawConfigParser if available
try:
from ConfigParser import RawConfigParser as ConfigParser
except:
from ConfigParser import ConfigParser as ConfigParser
# capisuite stuff
import consts
from exceptions import NoGlobalSectionError, NoOptionError
#--- spezialied ConfigParser --#
class CSConfigParser(ConfigParser):
"""
Specialized version of Python ConfigParser:
- if no filenames are given, read the default config files
- values are automatically quoted on setting (if required) und
unquoted on reading
"""
def read(self, filenames):
"""Read configuration files given as filenames. If no names are given,
the default fax and voice files are read.
"""
if not filenames:
ConfigParser.read(self, configfile_fax)
ConfigParser.read(self, configfile_voice)
else:
ConfigParser.read(self, filenames)
def get(self, section, option):
"""Get the value of the option from the given section (w/o quot. marks)."""
value = ConfigParser.get(self, section, option)
if len(value) > 1 and value[0] == '"':
value = value[1:-1]
self.set(section, option, value)
return value
def getList(self, section, option):
"""Return the value of the option from the given section as a list.
Commas are used as separators and leading and trailing whitespaces are
removed from all items."""
return map(string.strip, self.get(section, option).split(','))
def getUser(self, user, option, default=None, fail=0):
"""Get an option from the user or global section.
The option is searched in the user's section and if not found
in the global section.
'config' the ConfigParser object containing the values
'user' user section to use, if empty only global section is read
'option' the name of the option to search for
Returns the value for this option or None if it's not found
"""
retval = None
if self.has_option(user, option):
retval = self.get(user, option)
elif self.has_option('GLOBAL', option):
retval = self.get('GLOBAL', option)
elif fail:
raise NoOptionError(user, option)
# don't return empty values
if not retval is None:
return retval
return default
def listUsers(self):
ul = [ u
for u in self.sections()
if u not in consts.__known_sections__ ]
return ul
def items(self, section):
"""
Return a dictionary (name, value) for each option in the section.
NB: This differs from ConfigParser.items() which returns a list of
tuples!
"""
items = {}
for key, value in ConfigParser.items(self, section):
if len(value) > 1 and value[0] == '"':
value = value[1:-1]
items[key] = value
return items
def set(self, section, option, value):
if isinstance(value, types.StringTypes):
if not value or value[0].isspace() or value[-1].isspace():
value = '"%s"' % value
ConfigParser.set(self, section, option, value)
class JobDescription:
def __init__(self, filename=None, defaults=None):
self._config = config = CSConfigParser(defaults)
config.add_section('GLOBAL')
if filename:
config.read(filename)
def add_section(self, section):
if 1: # PyChecker should _not_ take this a an abstract method
raise NotImplementedError
remove_section = add_section
def options(self): return self._config.options('GLOBAL')
def items(self): return self._config.items('GLOBAL')
def get(self, option): return self._config.get('GLOBAL', option)
def getint(self, option): return self._config.getint('GLOBAL', option)
def getfloat(self, option): return self._config.getfloat('GLOBAL', option)
def getboolean(self, option): return self._config.getboolean('GLOBAL', option)
def has_option(self, option): return self._config.has_option('GLOBAL', option)
def set(self, option, value): return self._config.set('GLOBAL', option, value)
def remove_option(self, option): return self._config.remove_option('GLOBAL',option)
def read(self, filenames): return self._config.read(filenames)
def readfp(self, fp, filename=None): return self._config.read(fp, filename)
def writefp(self, fp):
print >> fp, "# Description file for", self.get('filename')
print >> fp, "# This if for internal use of CapiSuite."
print >> fp, "# Only change if you know what you do!"
self._config.write(fp)
def write(self, filename):
self.writefp(open(filename, 'w'))
def x__getattr__(self, attr):
return getattr(self._config, attr)
def x__setattr__(self, attr, value):
setattr(self._config, attr, value)
###--- utility functions ---###
def readGlobalConfig(file=None):
"""read configuration file and return a ConfigParser object
The configfile is read from the path given above and the
surrounding quotation marks from the values are removed.
Returns the constructed CSConfigParser object
"""
config = CSConfigParser()
config.read(file)
if not config.has_section('GLOBAL'):
raise NoGlobalSectionError()
return config
def readDescription(jobfilename):
"""read (job) description file for received fax or voice
This function reads an INI-style description file which has prior
been written by writeDesc() .
jobfilename the job' filename (with extension .txt)
Returns the filename the data filename (with extension) and
content the description as a dictionary
"""
control = JobDescription()
control.read(jobfilename)
filename = control.get('filename')
description = control.items()
return filename, description
def createDescriptionFor(filename, **description):
"""write (job) description file for received fax or voice
This function writes an INI-style description file for the given
data file which can later on be read by the CSConfigParser
instance. The data file name is used, the extension stripped and
replaced by .txt
filename the data filename (with extension),
content the description as a dictionary
"""
assert isinstance(description, dict)
descrname = os.path.splitext(filename)[0] + '.txt'
control = JobDescription()
control.set('filename', filename)
for key, value in description.items():
control.set(key, value)
control.write(descrname)
return descrname