VMM{/Config}: reduced docstrings. Added doc to the repository. v0.6.x
authorPascal Volk <neverseen@users.sourceforge.net>
Mon, 22 Feb 2010 10:20:46 +0000
branchv0.6.x
changeset 209 c705a9e38962
parent 208 efa1327b721f
child 210 3ddb735ec9d2
VMM{/Config}: reduced docstrings. Added doc to the repository.
VirtualMailManager/Config.py
VirtualMailManager/__init__.py
doc/Makefile
doc/source/conf.py
doc/source/index.rst
doc/source/vmm.rst
doc/source/vmm_config.rst
--- 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.