VMM{/Config}: reduced docstrings. Added doc to the repository.
--- a/VirtualMailManager/Config.py Mon Feb 22 04:26:52 2010 +0000
+++ b/VirtualMailManager/Config.py Mon Feb 22 10:20:46 2010 +0000
@@ -6,33 +6,6 @@
VirtualMailManager.Config
VMM's configuration module for simplified configuration access.
-
-This module defines a few classes:
-
-``LazyConfig``
- This class provides the following additonal methods
-
- * `LazyConfig.pget()`
- polymorphic getter which returns the value with the appropriate
- type.
- * `LazyConfig.dget()`
- like *pget()*, but checks additonal for default values in
- `LazyConfig._cfg`.
- * `LazyConfig.set()`
- like `RawConfigParser.set()`, but converts the new value to the
- appropriate type/class and optional validates the new value.
- * `LazyConfig.bool_new()`
- converts data from raw_input into boolean values.
- * `LazyConfig.get_boolean()`
- like `RawConfigParser.getboolean()`, but doesn't fail on real
- `bool` values.
-
-``Config``
- The Config class used by vmm.
-
-``LazyConfigOption``
- The class for the configuration objects in the ``Config`` class'
- ``_cfg`` dictionary.
"""
@@ -69,19 +42,17 @@
There are two additional getters:
- `LazyConfig.pget()`
- The polymorphic getter, which returns a option's value with the
- appropriate type.
- `LazyConfig.dget()`
- Like `LazyConfig.pget()`, but returns the option's default, from
- `LazyConfig._cfg['sectionname']['optionname'].default`, if the
- option is not configured in a ini-like configuration file.
+ `pget()`
+ The polymorphic getter, which returns a option's value with the
+ appropriate type.
+ `dget()`
+ Like `LazyConfig.pget()`, but returns the option's default, from
+ `LazyConfig._cfg['sectionname']['optionname'].default`, if the
+ option is not configured in a ini-like configuration file.
-
- `LazyConfig.set()` differs from ``RawConfigParser``'s ``set()`` method.
- ``LazyConfig.set()`` takes the ``section`` and ``option`` arguments
- combined to a single string in the form
- "``section``\ **.**\ ``option``".
+ `set()` differs from `RawConfigParser`'s `set()` method. `set()` takes
+ the `section` and `option` arguments combined to a single string in the
+ form "section.option".
"""
def __init__(self):
@@ -97,10 +68,10 @@
def bool_new(self, value):
"""Converts the string `value` into a `bool` and returns it.
- | '1', 'on', 'yes' and 'true' will become ``True``
- | '0', 'off', 'no' and 'false' will become ``False``
+ | '1', 'on', 'yes' and 'true' will become `True`
+ | '0', 'off', 'no' and 'false' will become `False`
- Throws a `ConfigValueError` for all other values, except ``bool``\ s.
+ Throws a `ConfigValueError` for all other values, except bools.
"""
if isinstance(value, bool):
return value
@@ -200,10 +171,10 @@
return self._cfg[section][option].getter(section, option)
def set(self, option, value):
- """Set the value of an option.
+ """Set the `value` of the `option`.
- Throws a ``ValueError`` if `value` couldn't be converted to
- ``LazyConfigOption.cls``"""
+ Throws a `ValueError` if `value` couldn't be converted using
+ `LazyConfigOption.cls`"""
section, option = self._get_section_option(option)
val = self._cfg[section][option].cls(value)
if self._cfg[section][option].validate:
@@ -214,12 +185,12 @@
self._modified = True
def has_section(self, section):
- """Checks if ``section`` is a known configuration section."""
+ """Checks if `section` is a known configuration section."""
return section.lower() in self._cfg
def has_option(self, option):
- """Checks if the option (section\ **.**\ option) is a known
- configuration option."""
+ """Checks if the option (section.option) is a known configuration
+ option."""
try:
self._get_section_option(option)
return True
@@ -234,28 +205,28 @@
class LazyConfigOption(object):
"""A simple container class for configuration settings.
- ``LazyConfigOption`` instances are required by `LazyConfig` instances,
- and instances of classes derived from ``LazyConfig``, like the
- `Config` class.
+ `LazyConfigOption` instances are required by `LazyConfig` instances,
+ and instances of classes derived from `LazyConfig`, like the
+ `Config` class.
"""
__slots__ = ('__cls', '__default', '__getter', '__validate')
def __init__(self, cls, default, getter, validate=None):
- """Creates a new ``LazyConfigOption`` instance.
+ """Creates a new `LazyConfigOption` instance.
Arguments:
- ``cls`` : type
- The class/type of the option's value
- ``default``
- Default value of the option. Use ``None`` if the option should
- not have a default value.
- ``getter`` : callable
- A method's name of `RawConfigParser` and derived classes, to
- get a option's value, e.g. `self.getint`.
- ``validate`` : NoneType or a callable
- None or any method, that takes one argument, in order to check
- the value, when `LazyConfig.set()` is called.
+ `cls` : type
+ The class/type of the option's value
+ `default`
+ Default value of the option. Use ``None`` if the option should not
+ have a default value.
+ `getter` : callable
+ A method's name of `RawConfigParser` and derived classes, to get a
+ option's value, e.g. `self.getint`.
+ `validate` : NoneType or a callable
+ None or any method, that takes one argument, in order to check the
+ value, when `LazyConfig.set()` is called.
"""
self.__cls = cls
if not default is None:# enforce the type of the default value
@@ -278,7 +249,7 @@
@property
def default(self):
- """The option's default value, may be ``None``"""
+ """The option's default value, may be `None`"""
return self.__default
@property
@@ -300,8 +271,8 @@
Arguments:
- ``filename``
- path to the configuration file
+ `filename` : str
+ path to the configuration file
"""
LazyConfig.__init__(self)
self._cfgFileName = filename
@@ -389,7 +360,7 @@
raise VMMConfigException(errmsg.getvalue(), CONF_ERROR)
def known_scheme(self, scheme):
- """Converts ``scheme`` to upper case and checks if is known by
+ """Converts `scheme` to upper case and checks if is known by
Dovecot (listed in VirtualMailManager.SCHEMES).
Throws a `ConfigValueError` if the scheme is not listed in
@@ -399,15 +370,14 @@
# TODO: VMM.SCHEMES
def unicode(self, section, option):
- """Returns the value of the ``option`` from ``section``, converted
- to Unicode.
- """
+ """Returns the value of the `option` from `section`, converted to
+ Unicode."""
return get_unicode(self.get(section, option))
def __chkCfg(self):
"""Checks all section's options for settings w/o a default value.
- Returns ``True`` if everything is fine, else ``False``."""
+ Returns `True` if everything is fine, else `False`."""
errors = False
for section in self._cfg.iterkeys():
missing = []
--- a/VirtualMailManager/__init__.py Mon Feb 22 04:26:52 2010 +0000
+++ b/VirtualMailManager/__init__.py Mon Feb 22 10:20:46 2010 +0000
@@ -1,8 +1,12 @@
# -*- coding: UTF-8 -*-
# Copyright (c) 2007 - 2010, Pascal Volk
# See COPYING for distribution information.
-# package initialization code
-#
+
+"""
+ VirtualMailManager
+
+ VirtualMailManager package initialization code
+"""
import gettext
import os
@@ -23,7 +27,7 @@
'os', 're', 'locale',
# version information from VERSION
'__author__', '__date__', '__version__',
- # error codes
+ # defined stuff
'ENCODING', 'ace2idna', 'check_domainname', 'check_localpart', 'exec_ok',
'expand_path', 'get_unicode', 'idn2ascii', 'is_dir',
]
@@ -66,29 +70,29 @@
def is_dir(path):
- """Checks if ``path`` is a directory.
+ """Checks if `path` is a directory.
- Throws a `VMMException` if ``path`` is not a directory.
+ Throws a `VMMException` if `path` is not a directory.
"""
path = expand_path(path)
if not os.path.isdir(path):
- raise VMMException(_(u'“%s” is not a directory') %
+ raise VMMException(_(u"'%s' is not a directory") %
get_unicode(path), NO_SUCH_DIRECTORY)
return path
def exec_ok(binary):
- """Checks if the ``binary`` exists and if it is executable.
+ """Checks if the `binary` exists and if it is executable.
- Throws a `VMMException` if the ``binary`` isn't a file or is not
+ Throws a `VMMException` if the `binary` isn't a file or is not
executable.
"""
binary = expand_path(binary)
if not os.path.isfile(binary):
- raise VMMException(_(u'“%s” is not a file') % get_unicode(binary),
+ raise VMMException(_(u"'%s' is not a file") % get_unicode(binary),
NO_SUCH_BINARY)
if not os.access(binary, os.X_OK):
- raise VMMException(_(u'File is not executable: “%s”') %
+ raise VMMException(_(u"File is not executable: '%s'") %
get_unicode(binary), NOT_EXECUTABLE)
return binary
@@ -122,7 +126,7 @@
def check_localpart(localpart):
- """Returns the validated local-part *localpart*.
+ """Returns the validated local-part `localpart`.
Throws a `VMMException` if the local-part is too long or contains
invalid characters.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/Makefile Mon Feb 22 10:20:46 2010 +0000
@@ -0,0 +1,89 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = build
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
+
+.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ -rm -rf $(BUILDDIR)/*
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/vmm.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/vmm.qhc"
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+ "run these through (pdf)latex."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/conf.py Mon Feb 22 10:20:46 2010 +0000
@@ -0,0 +1,199 @@
+# -*- coding: utf-8 -*-
+#
+# vmm documentation build configuration file, created by
+# sphinx-quickstart on Sun Feb 14 00:08:08 2010.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.append(os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.intersphinx']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['.templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'vmm'
+copyright = u'2010, Pascal Volk'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '0.6'
+# The full version, including alpha/beta/rc tags.
+release = '0.6.x'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# List of directories, relative to source directory, that shouldn't be searched
+# for source files.
+exclude_trees = []
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. Major themes that come with
+# Sphinx are currently 'default' and 'sphinxdoc'.
+html_theme = 'default'
+#html_theme = 'sphinxdoc'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['.static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_use_modindex = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'vmmdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('index', 'vmm.tex', u'vmm Documentation',
+ u'Pascal Volk', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True
+
+
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {'http://docs.python.org/': None}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/index.rst Mon Feb 22 10:20:46 2010 +0000
@@ -0,0 +1,24 @@
+======================
+VirtualMailManager API
+======================
+
+:Author: Pascal Volk <neverseen@users.sourceforge.net>
+:Date: |today|
+:Release: |version|
+
+Contents:
+
+.. toctree::
+ :maxdepth: 1
+ :numbered:
+
+ vmm.rst
+ vmm_config.rst
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/vmm.rst Mon Feb 22 10:20:46 2010 +0000
@@ -0,0 +1,145 @@
+:mod:`VirtualMailManager` --- Initialization code and some functions
+=====================================================================
+
+.. module:: VirtualMailManager
+ :synopsis: Initialization code and some functions
+
+.. moduleauthor:: Pascal Volk <neverseen@users.sourceforge.net>
+
+.. toctree::
+ :maxdepth: 2
+
+When the VirtualMailManager module, or one of its sub modules, is imported,
+the following actions will be performed:
+
+ - :func:`locale.setlocale` (with :const:`locale.LC_ALL`) is called, to set
+ :const:`ENCODING`
+ - :func:`gettext.install` is called, to have 18N support.
+
+Constants and data
+------------------
+
+.. data:: ENCODING
+
+ The systems current character encoding, e.g. ``'UTF-8'`` or
+ ``'ANSI_X3.4-1968'`` (aka ASCII).
+
+.. data:: __author__
+
+ The author's name
+
+.. data:: __date__
+
+ The release date
+
+.. data:: __version__
+
+ VirtualMailManager's version
+
+
+Functions
+---------
+
+.. function:: ace2idna(domainname)
+
+ Converts the idn domain name *domainname* into punycode.
+
+ :param domainname: the domain-ace representation (``xn--…``)
+ :type domainname: str
+ :rtype: unicode
+
+.. function:: check_domainname(domainname)
+
+ Returns the validated domain name *domainname*.
+
+ It also converts the name of the domain from IDN to ASCII, if necessary.
+
+ :param domainname: the name of the domain
+ :type domainname: :obj:`basestring`
+ :rtype: str
+ :raise VirtualMailManager.Exceptions.VMMException: if the domain name is
+ too long or doesn't look like a valid domain name (label.label.label).
+
+.. function:: check_localpart(localpart)
+
+ Returns the validated local-part *localpart* of an e-mail address.
+
+ :param localpart: The local-part of an e-mail address.
+ :type localpart: str
+ :rtype: str
+ :raise VirtualMailManager.Exceptions.VMMException: if the local-part is too
+ long or contains invalid characters.
+
+.. function:: exec_ok(binary)
+
+ Checks if the *binary* exists and if it is executable.
+
+ :param binary: path to the binary
+ :type binary: str
+ :rtype: str
+ :raise VirtualMailManager.Exceptions.VMMException: if *binary* isn't a file
+ or is not executable.
+
+.. function:: expand_path(path)
+
+ Expands paths, starting with ``.`` or ``~``, to an absolute path.
+
+ :param path: Path to a file or directory
+ :type path: str
+ :rtype: str
+
+.. function:: get_unicode(string)
+
+ Converts `string` to `unicode`, if necessary.
+
+ :param string: The string taht should be converted
+ :type string: str
+ :rtype: unicode
+
+.. function:: idn2ascii(domainname)
+
+ Converts the idn domain name *domainname* into punycode.
+
+ :param domainname: the unicode representation of the domain name
+ :type domainname: unicode
+ :rtype: str
+
+.. function:: is_dir(path)
+
+ Checks if *path* is a directory.
+
+ :param path: Path to a directory
+ :type path: str
+ :rtype: str
+ :raise VirtualMailManager.Exceptions.VMMException: if *path* is not a
+ directory.
+
+
+Examples
+--------
+
+ >>> from VirtualMailManager import *
+ >>> ace2idna('xn--pypal-4ve.tld')
+ u'p\u0430ypal.tld'
+ >>> idn2ascii(u'öko.de')
+ 'xn--ko-eka.de'
+ >>> check_domainname(u'pаypal.tld')
+ 'xn--pypal-4ve.tld'
+ >>> check_localpart('john.doe')
+ 'john.doe'
+ >>> exec_ok('usr/bin/vim')
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ File "./VirtualMailManager/__init__.py", line 93, in exec_ok
+ NO_SUCH_BINARY)
+ VirtualMailManager.Exceptions.VMMException: 'usr/bin/vim' is not a file
+ >>> exec_ok('/usr/bin/vim')
+ '/usr/bin/vim'
+ >>> expand_path('.')
+ '/home/user/hg/vmm'
+ >>> get_unicode('hello world')
+ u'hello world'
+ >>> is_dir('~/hg')
+ '/home/user/hg'
+ >>>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/source/vmm_config.rst Mon Feb 22 10:20:46 2010 +0000
@@ -0,0 +1,275 @@
+:mod:`VirtualMailManager.Config` --- Simplified configuration access
+======================================================================
+
+.. module:: VirtualMailManager.Config
+ :synopsis: Simplified configuration access
+
+.. moduleauthor:: Pascal Volk <neverseen@users.sourceforge.net>
+
+.. toctree::
+ :maxdepth: 2
+
+
+This module provides a few classes for simplified configuration handling
+and the validation of the setting's *type* and *value*.
+
+:class:`LazyConfig` is derived from Python's
+:class:`ConfigParser.RawConfigParser`. It doesn't use ``RawConfigParser``'s
+``DEFAULT`` section. All settings and their defaults, if supposed, are
+handled by :class:`LazyConfigOption` objects in the :attr:`LazyConfig._cfg`
+*dict*.
+
+``LazyConfig``'s setters and getters for options are taking a single string
+for the *section* and *option* argument, e.g. ``config.pget('database.user')``
+instead of ``config.get('database', 'user')``.
+
+
+
+LazyConfig
+----------
+.. class:: LazyConfig
+
+ Bases: :class:`ConfigParser.RawConfigParser`
+
+ .. versionadded:: 0.6.0
+
+ .. attribute:: _cfg
+
+ a multi dimensional :class:`dict`, containing *sections* and *options*,
+ represented by :class:`LazyConfigOption` objects.
+
+ For example::
+
+ from VirtualMailManager.Config import LazyConfig, LazyConfigOption
+
+ class FooConfig(LazyConfig):
+ def __init__(self, ...):
+ LazyConfig.__init__(self)
+ ...
+ LCO = LazyConfigOption
+ self._cfg = {
+ 'database': {# section database:
+ 'host': LCO(str, '::1', self.get),# options of the
+ 'name': LCO(str, 'dbx', self.get),# database section.
+ 'pass': LCO(str, None, self.get),# No defaults for the
+ 'user': LCO(str, None, self.get),# user and pass options
+ }
+ }
+
+ ...
+
+
+ .. method:: bool_new(value)
+
+ Converts the string *value* into a `bool` and returns it.
+
+ | ``'1'``, ``'on'``, ``'yes'`` and ``'true'`` will become :const:`True`
+ | ``'0'``, ``'off'``, ``'no'`` and ``'false'`` will become :const:`False`
+
+ :param value: one of the above mentioned strings
+ :type value: :obj:`basestring`
+ :rtype: bool
+ :raise ConfigValueError: for all other values, except ``bool``\ s
+
+ .. method:: dget(option)
+
+ Like :meth:`pget`, but returns the *option*'s default value, from
+ :attr:`_cfg` (defined by :attr:`LazyConfigOption.default`) if the *option*
+ is not configured in a ini-like configuration file.
+
+ :param option: the section.option combination
+ :type option: :obj:`basestring`
+ :raise NoDefaultError: if the *option* couldn't be found in the
+ configuration file and no default value was passed to
+ :class:`LazyConfigOption`'s constructor for the requested *option*.
+
+ .. method:: getboolean(section, option)
+
+ Returns the boolean value of the *option*, in the given *section*.
+
+ For a boolean :const:`True`, the value must be set to ``'1'``, ``'on'``,
+ ``'yes'``, ``'true'`` or :const:`True`. For a boolean :const:`False`, the
+ value must set to ``'0'``, ``'off'``, ``'no'``, ``'false'`` or
+ :const:`False`.
+
+ :param section: The section's name
+ :type section: :obj:`basestring`
+ :param option: The option's name
+ :type option: :obj:`basestring`
+ :rtype: bool
+ :raise ValueError: if the option has an other value than the values
+ mentioned above.
+
+ .. method:: has_option(option)
+
+ Checks if the *option* (section\ **.**\ option) is a known configuration
+ option.
+
+ :param option: The option's name
+ :type option: :obj:`basestring`
+ :rtype: bool
+
+ .. method:: has_section(section)
+
+ Checks if *section* is a known configuration section.
+
+ :param section: The section's name
+ :type section: :obj:`basestring`
+ :rtype: bool
+
+ .. method:: items(section)
+
+ Returns an iterator for ``key, value`` :obj:`tuple`\ s for each option in
+ the given *section*.
+
+ :param section: The section's name
+ :type section: :obj:`basestring`
+ :raise NoSectionError: if the given *section* is not known.
+
+ .. method:: pget(option)
+
+ Polymorphic getter which returns the *option*'s value (by calling
+ :attr:`LazyConfigOption.getter`) with the appropriate type, defined by
+ :attr:`LazyConfigOption.cls`.
+
+ :param option: the section.option combination
+ :type option: :obj:`basestring`
+
+ .. method:: sections()
+
+ Returns an iterator object for all configuration sections from the
+ :attr:`_cfg` dictionary.
+
+ :rtype: :obj:`dictionary-keyiterator`
+
+ .. method:: set(option, value)
+
+ Like :meth:`ConfigParser.RawConfigParser.set`, but converts the *option*'s
+ new *value* (by calling :attr:`LazyConfigOption.cls`) to the appropriate
+ type/class. When the ``LazyConfigOption``'s optional parameter *validate*
+ was not :const:`None`, the new *value* will be also validated.
+
+ :param option: the section.option combination
+ :type option: :obj:`basestring`
+ :param value: the new value to be set
+ :type value: :obj:`basestring`
+ :rtype: :const:`None`
+ :raise ConfigValueError: if a boolean value shout be set (:meth:`bool_new`)
+ and it fails
+ :raise ValueError: if an other setter (:attr:`LazyConfigOption.cls`) or
+ validator (:attr:`LazyConfigOption.validate`) fails.
+ :raise VirtualMailManager.Exceptions.VMMException: if
+ :attr:`LazyConfigOption.validate` is set to
+ :func:`VirtualMailManager.exec_ok` or :func:`VirtualMailManager.is_dir`.
+
+
+LazyConfigOption
+----------------
+LazyConfigOption instances are required by :class:`LazyConfig` instances, and
+instances of classes derived from `LazyConfig`, like the :class:`Config`
+class.
+
+.. class:: LazyConfigOption (cls, default, getter[, validate=None])
+
+ .. versionadded:: 0.6.0
+
+ The constructor's parameters are:
+
+ ``cls`` : :obj:`type`
+ The class/type of the option's value.
+ ``default`` : :obj:`str` or the one defined by ``cls``
+ Default value of the option. Use :const:`None` if the option shouldn't
+ have a default value.
+ ``getter``: :obj:`callable`
+ A method's name of :class:`ConfigParser.RawConfigParser` and derived
+ classes, to get a option's value, e.g. `self.getint`.
+ ``validate`` : :obj:`callable` or :const:`None`
+ :const:`None` or any function, which takes one argument and returns the
+ validated argument with the appropriate type (for example:
+ :meth:`LazyConfig.bool_new`). The function should raise a
+ :exc:`ConfigValueError` if the validation fails. This function checks the
+ new value when :meth:`LazyConfig.set()` is called.
+
+ Each LazyConfigOption object has the following read-only attributes:
+
+ .. attribute:: cls
+
+ The class of the option's value e.g. `str`, `unicode` or `bool`. Used as
+ setter method when :meth:`LazyConfig.set` (or the ``set()`` method of a
+ derived class) is called.
+
+ .. attribute:: default
+
+ The option's default value, may be ``None``
+
+ .. attribute:: getter
+
+ A method's name of :class:`ConfigParser.RawConfigParser` and derived
+ classes, to get a option's value, e.g. ``self.getint``.
+
+ .. attribute:: validate
+
+ A method or function to validate the option's new value.
+
+
+Config
+------
+The final configuration class of the virtual mail manager.
+
+.. class:: Config (filename)
+
+ Bases: :class:`LazyConfig`
+
+ :param filename: absolute path to the configuration file.
+ :type filename: :obj:`basestring`
+
+ .. attribute:: _cfg
+
+ The configuration ``dict``, containing all configuration sections and
+ options, as described in :attr:`LazyConfig._cfg`.
+
+ .. method:: check()
+
+ Checks all section's options for settings w/o a default value.
+
+ :raise VirtualMailManager.Exceptions.VMMConfigException: if the check fails
+
+ .. method:: load()
+
+ Loads the configuration read-only.
+
+ :raise VirtualMailManager.Exceptions.VMMConfigException: if the
+ configuration syntax is invalid
+
+ .. method:: unicode(section, option)
+
+ Returns the value of the *option* from *section*, converted to Unicode.
+ This method is intended for the :attr:`LazyConfigOption.getter`.
+
+ :param section: The name of the configuration section
+ :type section: :obj:`basestring`
+ :param option: The name of the configuration option
+ :type option: :obj:`basestring`
+ :rtype: :obj:`unicode`
+
+
+Exceptions
+----------
+
+.. exception:: BadOptionError (msg)
+
+ Bases: :exc:`ConfigParser.Error`
+
+ Raised when a option isn't in the format 'section.option'.
+
+.. exception:: ConfigValueError (msg)
+
+ Bases: :exc:`ConfigParser.Error`
+
+ Raised when creating or validating of new values fails.
+
+.. exception:: NoDefaultError (section, option)
+
+ Bases: :exc:`ConfigParser.Error`
+
+ Raised when the requested option has no default value.