← Back to team overview

configglue team mailing list archive

[Merge] lp:~ricardokirkner/configglue/docs into lp:configglue

 

Ricardo Kirkner has proposed merging lp:~ricardokirkner/configglue/docs into lp:configglue.

Requested reviews:
  Configglue developers (configglue)

For more details, see:
https://code.launchpad.net/~ricardokirkner/configglue/docs/+merge/59657

This branch essentially adds documentation for configglue, but it also added a few imports to make it backwards compatible with 0.9pre1.

The backwards-compatible-making changes are:

- imports added to configglue/pyschema/__init__.py
- added module configglue/pyschema/options.py
-- 
https://code.launchpad.net/~ricardokirkner/configglue/docs/+merge/59657
Your team Configglue developers is requested to review the proposed merge of lp:~ricardokirkner/configglue/docs into lp:configglue.
=== modified file 'configglue/__init__.py'
--- configglue/__init__.py	2010-12-27 15:21:03 +0000
+++ configglue/__init__.py	2011-05-02 13:17:34 +0000
@@ -15,4 +15,4 @@
 # 
 ###############################################################################
 
-__version__ = '0.9.1'
+__version__ = '0.10'

=== modified file 'configglue/pyschema/__init__.py'
--- configglue/pyschema/__init__.py	2011-01-10 12:50:01 +0000
+++ configglue/pyschema/__init__.py	2011-05-02 13:17:34 +0000
@@ -14,3 +14,7 @@
 # For bug reports, support, and new releases: http://launchpad.net/configglue
 # 
 ###############################################################################
+
+from .glue import *
+from .schema import *
+from .parser import *

=== modified file 'configglue/pyschema/glue.py'
--- configglue/pyschema/glue.py	2011-03-19 16:33:01 +0000
+++ configglue/pyschema/glue.py	2011-05-02 13:17:34 +0000
@@ -28,14 +28,17 @@
 ]
 
 
-SchemaGlue = namedtuple("SchemaGlue", "schema_parser option_parser options args")
+SchemaGlue = namedtuple("SchemaGlue",
+    "schema_parser option_parser options args")
 
 
 def schemaconfigglue(parser, op=None, argv=None):
-    """Populate an OptionParser with options and defaults taken from a
-    fully loaded SchemaConfigParser.
+    """Glue an OptionParser with a SchemaConfigParser.
+    
+    The OptionParser is populated with options and defaults taken from the
+    SchemaConfigParser.
+
     """
-
     def long_name(option):
         if option.section.name == '__main__':
             return option.name
@@ -79,6 +82,14 @@
 
 
 def configglue(schema_class, configs, usage=None):
+    """Parse configuration files using a provided schema.
+
+    The standard workflow for configglue is to instantiate a schema class,
+    feed it with some config files, and validate the parser state afterwards.
+    This utility function executes this standard worfklow so you don't have
+    to repeat yourself.
+
+    """
     scp = SchemaConfigParser(schema_class())
     scp.read(configs)
     if usage is not None:

=== added file 'configglue/pyschema/options.py'
--- configglue/pyschema/options.py	1970-01-01 00:00:00 +0000
+++ configglue/pyschema/options.py	2011-05-02 13:17:34 +0000
@@ -0,0 +1,1 @@
+from .schema import *

=== modified file 'configglue/pyschema/parser.py'
--- configglue/pyschema/parser.py	2011-02-20 23:42:55 +0000
+++ configglue/pyschema/parser.py	2011-05-02 13:17:34 +0000
@@ -41,7 +41,7 @@
 
 
 class SchemaValidationError(Exception):
-    pass
+    """Exception class raised for any schema validation error."""
 
 
 class SchemaConfigParser(BaseConfigParser, object):
@@ -54,6 +54,7 @@
     config.parse_all()
     ...
     profit!
+
     """
     def __init__(self, schema):
         super(SchemaConfigParser, self).__init__()
@@ -69,6 +70,12 @@
             lambda: collections.defaultdict(dict))
 
     def is_valid(self, report=False):
+        """Return if the state of the parser is valid.
+
+        This is useful to detect errors in configuration files, like type
+        errors or missing required options.
+
+        """
         valid = True
         errors = []
         try:
@@ -141,8 +148,10 @@
             return valid
 
     def items(self, section, raw=False, vars=None):
-        """Return a list of tuples with (name, value) for each option
-        in the section.
+        """Return the list of all options in a section.
+
+        The returned value is a list of tuples of (name, value) for each
+        option in the section.
 
         All % interpolations are expanded in the return values, based on the
         defaults passed into the constructor, unless the optional argument
@@ -150,7 +159,9 @@
         `vars' argument, which must be a dictionary whose contents overrides
         any pre-existing defaults.
 
-        The section DEFAULT is special.
+        The section __main__ is special as it's implicitly defined and used
+        for options not explicitly included in any section.
+
         """
         d = self._defaults.copy()
         try:
@@ -184,7 +195,7 @@
             return items
 
     def values(self, section=None, parse=True):
-        """Returns multiple values, in a dict.
+        """Returns multiple values in a dict.
 
         This method can return the value of multiple options in a single call,
         unlike get() that returns a single option's value.
@@ -194,6 +205,7 @@
 
         Section is to be specified *by name*, not by
         passing in real ConfigSection objects.
+
         """
         values = collections.defaultdict(dict)
         if section is None:
@@ -231,6 +243,7 @@
         return read_ok
 
     def readfp(self, fp, filename=None):
+        """Like ConfigParser.readfp, but consider the encoding."""
         # wrap the StringIO so it can read encoded text
         decoded_fp = codecs.getreader(CONFIG_FILE_ENCODING)(fp)
         self._read(decoded_fp, filename)
@@ -291,6 +304,14 @@
                         self._location[option] = filename
 
     def parse(self, section, option, value):
+        """Parse the value of an option.
+
+        This method raises NoSectionError if an invalid section name is
+        passed in.
+
+        This method raises ValueError if the value is not parseable.
+
+        """
         if section == '__main__':
             option_obj = getattr(self.schema, option, None)
         else:
@@ -342,8 +363,11 @@
         """Go through all sections and options attempting to parse each one.
 
         If any options are omitted from the config file, provide the
-        default value from the schema.  If the option has fatal=True, raise
-        an exception.
+        default value from the schema.
+
+        In the case of an NoSectionError or NoOptionError, raise it if the option
+        has *fatal* set to *True*.
+
         """
         for section in self.schema.sections():
             for option in section.options():
@@ -354,6 +378,7 @@
                         raise
 
     def locate(self, option=None):
+        """Return the location (file) where the option was last defined."""
         return self._location.get(option)
 
     def _get_interpolation_keys(self, section, option):
@@ -444,6 +469,16 @@
             return unicode(value)
 
     def get(self, section, option, raw=False, vars=None, parse=True):
+        """Return the parsed value of an option.
+
+        If *raw* is True, return the value as it's stored in the parser,
+        without parsing it.
+
+        Extra *vars* can be passed in to be evaluated during parsing.
+
+        If *parse* is False, return the string representation of the value.
+
+        """
         try:
             # get option's raw mode setting
             try:
@@ -481,11 +516,17 @@
         return value
 
     def set(self, section, option, value):
+        """Set an option's raw value."""
         super(SchemaConfigParser, self).set(section, option, value)
         filename = self.locate(option)
         self._dirty[filename][section][option] = value
 
     def save(self, fp=None):
+        """Save the parser contents to a file.
+
+        The data will be saved as a ini file.
+
+        """
         if fp is not None:
             if isinstance(fp, basestring):
                 fp = open(fp, 'w')

=== modified file 'configglue/pyschema/schema.py'
--- configglue/pyschema/schema.py	2011-04-09 15:56:14 +0000
+++ configglue/pyschema/schema.py	2011-05-02 13:17:34 +0000
@@ -58,6 +58,7 @@
     One ConfigOption comes already defined in Schema, 'includes' in the
     '__main__' section, that allows configuration files to include other
     configuration files.
+
     """
 
     def __init__(self):
@@ -96,12 +97,14 @@
                 self.includes == other.includes)
 
     def is_valid(self):
+        """Return wether the schema has a valid structure."""
         explicit_default_section = isinstance(getattr(self, '__main__', None),
                                               ConfigSection)
         is_valid = not explicit_default_section
         return is_valid
 
     def has_section(self, name):
+        """Return whether the schema as a given section."""
         """Return True if a ConfigSection with the given name is available"""
         return name in self._sections.keys()
 
@@ -121,6 +124,7 @@
         If section is omitted, returns all the options in the configuration
         file, flattening out any sections.
         To get options from the default section, specify section='__main__'
+
         """
         if isinstance(section, basestring):
             section = self.section(section)
@@ -144,6 +148,7 @@
 
     After instantiating the Schema, each ConfigSection will know its own
     name.
+
     """
     def __init__(self, name=''):
         self.name = name
@@ -202,6 +207,7 @@
 
     In runtime, after instantiating the Schema, each ConfigOption will also
     know its own name and to which section it belongs.
+
     """
 
     require_parser = False
@@ -252,6 +258,7 @@
         return None
 
     def parse(self, value):
+        """Parse the given value."""
         raise NotImplementedError()
 
 
@@ -262,6 +269,11 @@
         return False
 
     def parse(self, value, raw=False):
+        """Parse the given value.
+
+        If *raw* is *True*, return the value unparsed.
+
+        """
         if raw:
             return value
 
@@ -280,6 +292,11 @@
         return 0
 
     def parse(self, value, raw=False):
+        """Parse the given value.
+
+        If *raw* is *True*, return the value unparsed.
+
+        """
         if raw:
             return value
 
@@ -299,12 +316,28 @@
     if remove_duplicates == True, duplicate elements in the lines will be
     removed.  Only the first occurrence of any item will be kept,
     otherwise the general order of the list will be preserved.
+
     """
 
+    def __init__(self, name='', item=None, raw=False, default=NO_DEFAULT,
+        fatal=False, help='', action='store', remove_duplicates=False):
+        super(LinesConfigOption, self).__init__(name=name, raw=raw,
+            default=default, fatal=fatal, help=help, action=action)
+        self.item = item
+        self.require_parser = item.require_parser
+        self.raw = item.raw
+        self.remove_duplicates = remove_duplicates
+
     def _get_default(self):
         return []
 
     def parse(self, value, parser=None, raw=False):
+        """Parse the given value.
+
+        A *parser* object is used to parse individual list items.
+        If *raw* is *True*, return the value unparsed.
+
+        """
         def _parse_item(value):
             if self.require_parser:
                 value = self.item.parse(value, parser=parser, raw=raw)
@@ -320,27 +353,30 @@
             items = filtered_items
         return items
 
-    def __init__(self, name='', item=None, raw=False, default=NO_DEFAULT,
-        fatal=False, help='', action='store', remove_duplicates=False):
-        super(LinesConfigOption, self).__init__(name=name, raw=raw,
-            default=default, fatal=fatal, help=help, action=action)
-        self.item = item
-        self.require_parser = item.require_parser
-        self.raw = item.raw
-        self.remove_duplicates = remove_duplicates
-
 
 class StringConfigOption(ConfigOption):
     """A ConfigOption that is parsed into a string.
 
     If null==True, a value of 'None' will be parsed in to None instead of
     just leaving it as the string 'None'.
+
     """
 
+    def __init__(self, name='', raw=False, default=NO_DEFAULT, fatal=False,
+        null=False, help='', action='store'):
+        self.null = null
+        super(StringConfigOption, self).__init__(name=name, raw=raw,
+            default=default, fatal=fatal, help=help, action=action)
+
     def _get_default(self):
         return '' if not self.null else None
 
     def parse(self, value, raw=False):
+        """Parse the given value.
+
+        If *raw* is *True*, return the value unparsed.
+
+        """
         if raw:
             result = value
         elif self.null:
@@ -351,18 +387,13 @@
             result = repr(value)
         return result
 
-    def __init__(self, name='', raw=False, default=NO_DEFAULT, fatal=False,
-        null=False, help='', action='store'):
-        self.null = null
-        super(StringConfigOption, self).__init__(name=name, raw=raw,
-            default=default, fatal=fatal, help=help, action=action)
-
 
 class TupleConfigOption(ConfigOption):
     """A ConfigOption that is parsed into a fixed-size tuple of strings.
 
     The number of items in the tuple should be specified with the 'length'
     constructor argument.
+
     """
 
     def __init__(self, name='', length=0, raw=False, default=NO_DEFAULT,
@@ -375,6 +406,11 @@
         return ()
 
     def parse(self, value, raw=False):
+        """Parse the given value.
+
+        If *raw* is *True*, return the value unparsed.
+
+        """
         parts = [part.strip() for part in value.split(',')]
         if parts == ['()']:
             result = ()
@@ -400,7 +436,9 @@
     argument, that should be in turn a dictionary.  spec's keys are the
     available keys for the config file, and spec's values should be
     ConfigOptions that will be used to parse the values in the config file.
+
     """
+
     require_parser = True
 
     def __init__(self, name='', spec=None, strict=False, raw=False,
@@ -423,6 +461,12 @@
         return default
 
     def parse(self, section, parser=None, raw=False):
+        """Parse the given value.
+
+        A *parser* object is used to parse individual dict items.
+        If *raw* is *True*, return the value unparsed.
+
+        """
         parsed = dict(parser.items(section))
         result = {}
 

=== modified file 'doc/conf.py'
--- doc/conf.py	2010-10-13 16:23:00 +0000
+++ doc/conf.py	2011-05-02 13:17:34 +0000
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 #
-# configglue documentation build configuration file, created by
-# sphinx-quickstart on Wed Oct 13 13:20:17 2010.
+# configglue documentation build configuration file
+#
 #
 # This file is execfile()d with the current directory set to its containing dir.
 #
@@ -11,12 +11,13 @@
 # All configuration values have a default; values that are commented out
 # serve to show the default.
 
-import sys, os
+import sys
+import 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('.'))
+sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '_ext')))
 
 # -- General configuration -----------------------------------------------------
 
@@ -38,16 +39,16 @@
 
 # General information about the project.
 project = u'configglue'
-copyright = u'2010, John R. Lenton, Ricardo Kirkner'
+copyright = u'John R. Lenton, Ricardo Kirkner'
 
 # 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.9'
+version = '0.10'
 # The full version, including alpha/beta/rc tags.
-release = '0.9pre1'
+release = '0.10'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
@@ -70,11 +71,11 @@
 #default_role = None
 
 # If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
+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
+add_module_names = False
 
 # If true, sectionauthor and moduleauthor directives will be shown in the
 # output. They are ignored by default.
@@ -84,7 +85,7 @@
 pygments_style = 'sphinx'
 
 # A list of ignored prefixes for module index sorting.
-#modindex_common_prefix = []
+modindex_common_prefix = ['configglue.']
 
 
 # -- Options for HTML output ---------------------------------------------------
@@ -128,7 +129,7 @@
 
 # If true, SmartyPants will be used to convert quotes and dashes to
 # typographically correct entities.
-#html_use_smartypants = True
+html_use_smartypants = True
 
 # Custom sidebar templates, maps document names to template names.
 #html_sidebars = {}

=== added file 'doc/contents.rst'
--- doc/contents.rst	1970-01-01 00:00:00 +0000
+++ doc/contents.rst	2011-05-02 13:17:34 +0000
@@ -0,0 +1,27 @@
+.. _contents:
+
+=================================
+configglue documentation contents
+=================================
+
+.. toctree::
+    :hidden:
+
+    contents
+
+.. toctree::
+    :maxdepth: 3
+
+    intro/index
+    topics/index
+    howto/index
+    faq/index
+    ref/index
+    misc/index
+
+Indices, glossary and tables
+============================
+
+* :ref:`genindex`
+* :ref:`modindex`
+

=== added directory 'doc/faq'
=== added file 'doc/faq/index.rst'
--- doc/faq/index.rst	1970-01-01 00:00:00 +0000
+++ doc/faq/index.rst	2011-05-02 13:17:34 +0000
@@ -0,0 +1,8 @@
+==============
+configglue FAQ
+==============
+
+.. toctree::
+   :maxdepth: 2
+   
+   install

=== added file 'doc/faq/install.rst'
--- doc/faq/install.rst	1970-01-01 00:00:00 +0000
+++ doc/faq/install.rst	2011-05-02 13:17:34 +0000
@@ -0,0 +1,47 @@
+FAQ: Installation
+=================
+
+How do I get started?
+---------------------
+
+    #. `Download the code`_.
+    #. Install configglue (read the :doc:`installation guide </intro/install>`).
+    #. Walk through the :doc:`quickstart guide </intro/quickstart>`.
+    #. Check out the rest of the :doc:`documentation </index>`, and `ask questions`_ if you
+       run into trouble.
+
+.. _`Download the code`: https://launchpad.net/configglue/+download
+.. _ask questions: https://answers.launchpad.net/configglue/
+
+What are configglue's prerequisites?
+------------------------------------
+
+configglue requires Python_, specifically any version of Python from 2.6
+through 2.7. No other Python libraries are required for basic configglue
+usage.
+
+.. _Python: http://www.python.org/
+
+Can I use Django with Python 3?
+-------------------------------
+
+Not at the moment. Python 3.0 introduced a number of
+backwards-incompatible changes to the Python language, and although
+these changes are generally a good thing for Python's future, it will
+be a while before most Python software catches up and is able to run
+on Python 3.0. For configglue, the transition is expected to happen
+soon, so keep around!
+
+In the meantime, Python 2.x releases will be supported and provided
+with bug fixes and security updates by the Python development team, so
+continuing to use a Python 2.x release during the transition should
+not present any risk.
+
+Should I use the stable version or development version?
+-------------------------------------------------------
+
+Generally, if you're using code in production, you should be using a
+stable release. The configglue project is currently in it's pre-1.0 stage,
+so there are still issues being worked on that can break API compatiblity.
+Once we reach 1.0, API backwards compatibility should be better guaranteed.
+

=== added directory 'doc/howto'
=== added file 'doc/howto/custom-schema-options.rst'
--- doc/howto/custom-schema-options.rst	1970-01-01 00:00:00 +0000
+++ doc/howto/custom-schema-options.rst	2011-05-02 13:17:34 +0000
@@ -0,0 +1,87 @@
+===========================
+Writing custom option types
+===========================
+
+.. currentmodule:: configglue.pyschema.schema
+
+Introduction
+============
+
+The :doc:`schema reference </topics/schemas>` documentation explains how to
+use configglue's standard option classes --
+:class:`~configglue.pyschema.schema.BoolConfigOption`,
+:class:`~configglue.pyschema.schema.IntConfigOption`, etc. For many purposes,
+those classes are all you'll need. Sometimes, though, the configglue version
+won't meet your precise requirements, or you'll want to use a option that is
+entirely different from those shipped with configglue.
+
+configglue's built-in option types don't cover every possible data type --
+only the common types, such as ``bool`` and ``int``. For more obscure data
+types, such as complex numbers or even user-created types you can define your
+own configglue :class:`~configglue.pyschema.schema.ConfigOption` subclasses.
+
+Writing an option subclass
+==========================
+
+When planning your :class:`~configglue.pyschema.schema.ConfigOption` subclass,
+first give some thought to which existing
+:class:`~configglue.pyschema.schema.ConfigOption` class your new option
+is most similar to. Can you subclass an existing configglue option and save
+yourself some work? If not, you should subclass the
+:class:`~configglue.pyschema.schema.ConfigOption` class, from which everything
+is descended.
+
+Initializing your new option is a matter of separating out any arguments that are
+specific to your case from the common arguments and passing the latter to the
+:meth:`~configglue.pyschema.schema.ConfigOption.__init__` method of
+:class:`~configglue.pyschema.schema.ConfigOption` (or your parent class).
+
+In our example, we'll call our option ``UpperCaseDictConfigOption``. (It's a
+good idea to call your :class:`~configglue.pyschema.schema.ConfigOption`
+subclass ``<Something>ConfigOption``, so it's easily identifiable as a
+:class:`~configglue.pyschema.schema.ConfigOption` subclass.) It behaves
+mostly like a :class:`~configglue.pyschema.schema.DictConfigOption`, so we'll
+subclass from that::
+
+    from configglue import pyschema
+
+    class UpperCaseDictConfigOption(pyschema.DictConfigOption):
+        """ A DictConfigOption with all upper-case keys. """
+
+        def parse(self, section, parser=None, raw=False):
+            parsed = super(UpperCaseDictConfigOption, self).parse(
+                section, parser, raw)
+            result = {}
+            for k, v in parsed.items():
+                result[k.upper()] = v
+            return result
+
+
+Our ``UpperCaseDictConfigOption`` will represent a dictionary with all-uppercase
+keys.
+
+So, let's assume we have a configuration file (see documentation on 
+:doc:`configuration files </topics/config-file>` for details) that includes::
+
+    [__main__]
+    mydict = mydict_section
+
+    [mydict_section]
+    foo = 1
+    bar = 2
+
+and a schema like::
+
+    class MySchema(pyschema.Schema):
+        mydict = UpperCaseDictConfigOption()
+
+When parsing this configuration file, the parser will contain the following
+value for the ``mydict`` attribute::
+
+    {'FOO': '1', 'BAR': '2'}
+
+.. note::
+    Note that the dictionary values are strings because we didn't specify an
+    item type for the ``UpperCaseDictConfigOption``, and so it defaulted to
+    :class:`~configglue.pyschema.schema.StringConfigOption`.
+

=== added file 'doc/howto/index.rst'
--- doc/howto/index.rst	1970-01-01 00:00:00 +0000
+++ doc/howto/index.rst	2011-05-02 13:17:34 +0000
@@ -0,0 +1,13 @@
+"How-to" guides
+===============
+
+Here you'll find short answers to "How do I....?" types of questions. These
+how-to guides don't cover topics in depth -- you'll find that material in the
+:doc:`/topics/index` and the :doc:`/ref/index`. However, these guides will help
+you quickly accomplish common tasks.
+
+.. toctree::
+   :maxdepth: 1
+
+   custom-schema-options
+

=== modified file 'doc/index.rst'
--- doc/index.rst	2010-10-18 18:27:03 +0000
+++ doc/index.rst	2011-05-02 13:17:34 +0000
@@ -1,15 +1,60 @@
-.. configglue documentation master file, created by
-   sphinx-quickstart on Wed Oct 13 13:20:17 2010.
-   You can adapt this file completely to your liking, but it should at least
-   contain the root `toctree` directive.
-
-Welcome to configglue's documentation!
-======================================
-
-Contents:
-
-.. toctree::
-    :maxdepth: 2
-
-    intro
-    quickstart
+
+.. _index:
+
+========================
+configglue documentation
+========================
+
+Getting help
+============
+
+Having trouble? We'd like to help!
+
+* Try the :doc:`FAQ <faq/index>` -- it's got answers to many common questions.
+
+* Looking for specific information? Try the :ref:`genindex`, :ref:`modindex`
+  or the :doc:`detailed table of contents <contents>`.
+
+* Ask a question in the `#configglue IRC channel`_.
+
+* Report bugs with configglue in our `ticket tracker`_.
+
+.. _#configglue IRC channel: irc://irc.freenode.net/configglue
+.. _ticket tracker: https://bugs.launchpad.net/configglue
+
+First steps
+===========
+
+    * **From scratch:**
+      :doc:`Overview <intro/overview>` |
+      :doc:`Installation <intro/install>` |
+      :doc:`Quickstart <intro/quickstart>`
+
+The schema
+==========
+
+    * **Schemas:**
+      :doc:`Schema syntax <topics/schemas>` |
+      :doc:`ConfigOption types <ref/schemas/options>`
+
+    * **Advanced:**
+      :doc:`Custom options <howto/custom-schema-options>`
+
+The configuration file
+======================
+
+    * **Configuration files:**
+      :doc:`Syntax overview <topics/config-file>`
+
+The command-line
+================
+
+    * **Command-line integration:**
+      :doc:`Overview <topics/command-line>`
+
+The configglue open-source project
+==================================
+
+    * **Third-party distributions:**
+      :doc:`Overview <misc/distributions>`
+

=== added directory 'doc/intro'
=== added file 'doc/intro/index.rst'
--- doc/intro/index.rst	1970-01-01 00:00:00 +0000
+++ doc/intro/index.rst	2011-05-02 13:17:34 +0000
@@ -0,0 +1,31 @@
+Getting started
+===============
+
+New to configglue? Well, you came to the right place: read this material to
+quickly get up and running.
+
+.. toctree::
+   :maxdepth: 1
+    
+   overview
+   install
+   quickstart
+   whatsnext
+   
+.. seealso::
+
+    If you're new to Python_, you might want to start by getting an idea of what
+    the language is like. configglue is 100% Python, so if you've got minimal
+    comfort with Python you'll probably get a lot more out of configglue.
+    
+    If you're new to programming entirely, you might want to start with this
+    `list of Python resources for non-programmers`_
+    
+    If you already know a few other languages and want to get up to speed with
+    Python quickly, we recommend `Dive Into Python`_. If that's not quite your
+    style, there are quite a few other `books about Python`_.
+    
+    .. _python: http://python.org/
+    .. _list of Python resources for non-programmers: http://wiki.python.org/moin/BeginnersGuide/NonProgrammers
+    .. _dive into python: http://diveintopython.org/
+    .. _books about Python: http://wiki.python.org/moin/PythonBooks

=== added file 'doc/intro/install.rst'
--- doc/intro/install.rst	1970-01-01 00:00:00 +0000
+++ doc/intro/install.rst	2011-05-02 13:17:34 +0000
@@ -0,0 +1,45 @@
+Quick install guide
+===================
+
+Install configglue
+------------------
+
+You've got three easy options to install configglue:
+
+    * Install a version of configglue :doc:`provided by your operating system
+      distribution </misc/distributions>`. This is the quickest option for those
+      who have operating systems that distribute configglue.
+
+    * :ref:`Install an official release <installing-official-release>`. This
+      is the best approach for users who want a stable version number and aren't
+      concerned about running a slightly older version of configglue.
+
+    * :ref:`Install the latest development version
+      <installing-development-version>`. This is best for users who want the
+      latest-and-greatest features and aren't afraid of running brand-new code.
+
+.. admonition:: Always refer to the documentation that corresponds to the
+    version of configglue you're using!
+
+    If you do either of the first two steps, keep an eye out for parts of the
+    documentation marked **new in development version**. That phrase flags
+    features that are only available in development versions of configglue, and
+    they likely won't work with an official release.
+
+
+Verifying
+---------
+
+To verify that configglue can be seen by Python, type ``python`` from your shell.
+Then at the Python prompt, try to import configglue::
+
+    >>> import configglue
+    >>> print configglue.__version__
+    0.10
+
+
+That's it!
+----------
+
+That's it -- you can now :doc:`move onto the quickstart guide </intro/quickstart>`.
+

=== renamed file 'doc/intro.rst' => 'doc/intro/overview.rst'
--- doc/intro.rst	2010-10-18 15:03:20 +0000
+++ doc/intro/overview.rst	2011-05-02 13:17:34 +0000
@@ -1,20 +1,20 @@
-============
-Introduction
-============
+======================
+configglue at a glance
+======================
 
 What is configglue?
 ===================
 
-configglue is a library that glues together Python's  optparse.OptionParser and
+configglue is a library that glues together Python's optparse.OptionParser and
 ConfigParser.ConfigParser, so that you don't have to repeat yourself when you
-want to export the same options to a configuration file and a commandline
+want to export the same options to a configuration file and a command-line
 interface.
 
 The main features of configglue are:
 
 - ini-style configuration files
 - schema-based configuration
-- commandline integration
+- command-line integration
 - configuration validation
 
 
@@ -30,29 +30,16 @@
 - use standard types out of the box (integer, string, bool, tuple, list, dict)
 - use standards-compatible configuration files (standard ini-files)
 - create your own custom types beyond what's provided in the library 
-- easily support commandline integration
+- easily support command-line integration
 - override options locally by using several configuration files (useful for
   separating configuration files for different environments)
 
-configglue and django-configglue are already available in Ubuntu 10.10
-(Maverick), so they can be installed via apt-get. configglue should already be
-installed if you have the desktop edition, as it's being used by Ubuntu One's
-client.
-
-Who else is using configglue?
-=============================
-
-- Ubuntu Pay 
-- Ubuntu Software Center
-- Ubuntu Single Sign On
-- Ubuntu One 
-
 
 Got curious?
 ============
 
 You can find a quickstart guide for configglue on 
-:ref:`quickstart` and you can get its code at
+:doc:`quickstart` and you can get its code at
 http://launchpad.net/configglue.
 
 As an additional bonus, there is another project called 

=== renamed file 'doc/quickstart.rst' => 'doc/intro/quickstart.rst'
--- doc/quickstart.rst	2010-10-18 18:27:03 +0000
+++ doc/intro/quickstart.rst	2011-05-02 13:17:34 +0000
@@ -1,13 +1,12 @@
-.. _quickstart:
-
-configglue 101
-==============
+=================================================
+Writing your first configglue-enabled application
+=================================================
 
 This is a minimalistic step-by-step guide on how to start using configglue to
 manage configuration settings for your application.
 
-Jump in
--------
+Jump right in
+=============
 
 Most of the time the code needed to make your application work with configglue
 will look like the following snippet, so let's look at it in detail::
@@ -25,21 +24,19 @@
                 print "%s option has default value: %s" % (opt, option.default)
 
     if __name__ == '__main__':
-        from configglue.pyschema import (
-            IntConfigOption, BoolConfigOption, Schema, SchemaConfigParser,
-            schemaconfigglue)
+        from configglue import pyschema
 
         # create the schema
-        class MySchema(Schema):
-            foo = IntConfigOption()
-            bar = BoolConfigOption()
+        class MySchema(pyschema.Schema):
+            foo = pyschema.IntConfigOption()
+            bar = pyschema.BoolConfigOption()
 
         # read the configuration files
-        scp = SchemaConfigParser(MySchema())
+        scp = pyschema.SchemaConfigParser(MySchema())
         scp.read(['config.ini'])
 
         # support command-line integration
-        op, opts, args = schemaconfigglue(scp)
+        op, opts, args = pyschema.schemaconfigglue(scp)
 
         # validate the config (after taking into account any command-line
         # provided options
@@ -75,15 +72,15 @@
 
     ::
 
-        class MySchema(Schema):
-            foo = IntConfigOption()
-            bar = BoolConfigOption()
+        class MySchema(pyschema.Schema):
+            foo = pyschema.IntConfigOption()
+            bar = pyschema.BoolConfigOption()
 
 #. Create a parser for that schema
 
     ::
 
-        scp = SchemaConfigParser(MySchema())
+        scp = pyschema.SchemaConfigParser(MySchema())
 
 #. Read the configuration files (to get the statically defined configuration
    values)
@@ -97,7 +94,7 @@
 
     ::
 
-        op, opts, args = schemaconfigglue(scp)
+        op, opts, args = pyschema.schemaconfigglue(scp)
 
 #. (Optional) Validate the effective configuration (to capture any
    configuration issues)
@@ -108,8 +105,42 @@
         if not is_valid:
             op.error(reasons[0])
 
-Test
-----
+Since this code will be structured the same for any configglue-enabled project
+you do, there is also a utility function you can use to avoid repeating
+yourself.
+
+When using that function (see :func:`configglue.pyschema.glue.configglue`),
+this code would look like::
+
+    def main(config, opts):
+        # do something
+        values = config.values('__main__')
+        for opt in ('foo', 'bar'):
+            option = config.schema.section('__main__').option(opt)
+            value = values.get(opt)
+            if value != option.default:
+                print "%s option has been configured with value: %s" % (opt,
+                    value)
+            else:
+                print "%s option has default value: %s" % (opt, option.default)
+
+    if __name__ == '__main__':
+        from configglue import pyschema
+
+        # create the schema
+        class MySchema(pyschema.Schema):
+            foo = pyschema.IntConfigOption()
+            bar = pyschema.BoolConfigOption()
+
+        # glue everything together
+        glue = pyschema.configglue(MySchema, ['config.ini'])
+
+        # run
+        main(glue.schema_parser, glue.options)
+
+
+Test it
+=======
 
 To test our configglue support, let's try out different use cases.
 
@@ -149,7 +180,7 @@
 
 
 Profit!
--------
+=======
 
 That's it! Your application now uses configglue to manage it's configuration.
 Congratulations!

=== added file 'doc/intro/whatsnext.rst'
--- doc/intro/whatsnext.rst	1970-01-01 00:00:00 +0000
+++ doc/intro/whatsnext.rst	2011-05-02 13:17:34 +0000
@@ -0,0 +1,50 @@
+=================
+What to read next
+=================
+
+So you've read all the :doc:`introductory material </intro/index>` and have
+decided you'd like to keep using configglue. We've only just scratched the
+surface with this intro.
+
+So what's next?
+
+Well, we've always been big fans of learning by doing. At this point you should
+know enough to start fooling around. As you need to learn new tricks, come back
+to the documentation.
+
+We've put a lot of effort into making confgglue's documentation useful, easy to
+read and as complete as possible. The rest of this document explains more about
+how the documentation works so that you can get the most out of it.
+
+How the documentation is organized
+==================================
+
+configglue's main documentation is broken up into "chunks" designed to fill
+different needs:
+
+    * The :doc:`introductory material </intro/index>` is designed for people new
+      to configglue. It doesn't cover anything in depth, but instead gives a
+      high-level overview of how developing in configglue "feels".
+
+    * The :doc:`topic guides </topics/index>`, on the other hand, dive deep into
+      individual parts of configglue. There are complete guides to configglue's
+      :doc:`schema system </topics/schemas>`,
+      :doc:`configuration files </topics/config-file>`,
+      :doc:`command-line integration </topics/command-line>`, and much more.
+
+      This is probably where you'll want to spend most of your time; if you work
+      your way through these guides you should come out knowing pretty much
+      everything there is to know about configglue.
+
+    * We've written a set of :doc:`how-to guides </howto/index>` that answer
+      common "How do I ...?" questions. Here you'll find information about
+      :doc:`writing custom option types </howto/custom-schema-options>`,
+      and more.
+
+    * The guides and how-to's don't cover every single class, function, and
+      method available in configglue -- that would be overwhelming when you're
+      trying to learn. Instead, details about individual classes, functions,
+      methods, and modules are kept in the :doc:`reference </ref/index>`. This is
+      where you'll turn to find the details of a particular function or
+      whathaveyou.
+

=== added directory 'doc/misc'
=== added file 'doc/misc/distributions.rst'
--- doc/misc/distributions.rst	1970-01-01 00:00:00 +0000
+++ doc/misc/distributions.rst	2011-05-02 13:17:34 +0000
@@ -0,0 +1,35 @@
+=======================================
+Third-party distributions of configglue
+=======================================
+
+Many third-party distributors are now providing versions of configglue integrated
+with their package-management systems. These can make installation and upgrading
+much easier for users of configglue.
+
+Typically, these packages are based on the latest stable release of configglue, so
+if you want to use the development version of configglue you'll need to follow the
+instructions for :ref:`installing the development version
+<installing-development-version>` from Launchpad.
+
+If you're using Linux or a Unix installation, such as OpenSolaris,
+check with your distributor to see if they already package configglue. If
+you're using a Linux distro and don't know how to find out if a package
+is available, then now is a good time to learn.
+
+Currently known distributions that ship configglue are:
+
+  * Ubuntu
+
+    `all Ubuntu releases`_, see also `Ubuntu documentation`_ on "Adding and Removing Software"
+
+.. _all Ubuntu releases: http://packages.ubuntu.com/search?searchon=names&keywords=python-configglue
+.. _Ubuntu documentation: https://help.ubuntu.com/
+
+
+For distributors
+================
+
+If you'd like to package configglue for distribution, we'd be happy to help out!
+Please join the `configglue-developers mailing list`_ and introduce yourself.
+
+.. _configglue-developers mailing list: https://lists.launchpad.net/configglue/

=== added file 'doc/misc/index.rst'
--- doc/misc/index.rst	1970-01-01 00:00:00 +0000
+++ doc/misc/index.rst	2011-05-02 13:17:34 +0000
@@ -0,0 +1,10 @@
+Meta-documentation and miscellany
+=================================
+
+Documentation that we can't find a more organized place for. Like that drawer in
+your kitchen with the scissors, batteries, duct tape, and other junk.
+
+.. toctree::
+   :maxdepth: 2
+   
+   distributions

=== added directory 'doc/ref'
=== added file 'doc/ref/index.rst'
--- doc/ref/index.rst	1970-01-01 00:00:00 +0000
+++ doc/ref/index.rst	2011-05-02 13:17:34 +0000
@@ -0,0 +1,9 @@
+=============
+API Reference
+=============
+
+.. toctree::
+   :maxdepth: 1
+
+   schemas/index
+

=== added directory 'doc/ref/schemas'
=== added file 'doc/ref/schemas/index.rst'
--- doc/ref/schemas/index.rst	1970-01-01 00:00:00 +0000
+++ doc/ref/schemas/index.rst	2011-05-02 13:17:34 +0000
@@ -0,0 +1,10 @@
+=======
+Schemas
+=======
+
+Schema API reference. For introductory material, see :doc:`/topics/schemas`.
+
+.. toctree::
+   :maxdepth: 1
+
+   options

=== added file 'doc/ref/schemas/options.rst'
--- doc/ref/schemas/options.rst	1970-01-01 00:00:00 +0000
+++ doc/ref/schemas/options.rst	2011-05-02 13:17:34 +0000
@@ -0,0 +1,199 @@
+=======================
+Schema option reference
+=======================
+
+.. module:: configglue.pyschema.schema
+    :synopsis: Built-in options types.
+
+.. currentmodule:: configglue.pyschema
+
+This document contains details about the `option attributes`_ and
+`option types`_ included in configglue.
+
+.. seealso::
+
+    If the built-in options don't do the trick, you can easily
+    :doc:`write your own custom schema options </howto/custom-schema-options>`. 
+
+.. note::
+
+    Technically, these classes are defined in
+    :mod:`configglue.pyschema.schema`, but for convenience they're imported
+    into :mod:`configglue.pyschema`; the standard convention is to use
+    ``from configglue import pyschema`` and refer to classes as
+    ``pyschema.<Foo>ConfigOption``.
+
+.. _common-schema-option-attributes:
+
+Option attributes
+=================
+
+The following arguments are available to all option types. All are
+*optional*.
+
+``name``
+--------
+
+.. attribute:: ConfigOption.name
+
+The name of the option. This will be automatically set to the name assigned to
+the option in the schema definition.
+
+``raw``
+-------
+
+.. attribute:: ConfigOption.raw
+
+If ``True``, variable interpolation will not be carried out for this option.
+
+Default is ``False``.
+
+``default``
+-----------
+
+.. attribute:: ConfigOption.default
+
+The default value for this option, if none is provided in the config file.
+
+Default is ``configglue.pyschema.schema.NO_DEFAULT``.
+
+``fatal``
+---------
+
+.. attribute:: ConfigOption.fatal
+
+If ``True``, ``SchemaConfigParser.parse_all`` will raise an exception if no
+value is provided in the configuration file for this option. Otherwise,
+``self.default`` will be used. 
+
+Default is ``False``.
+
+``help``
+--------
+
+.. attribute:: ConfigOption.help
+
+The help text describing this option. This text will be used as the
+``optparse.OptParser`` help text.
+
+Default is ``''``.
+
+``section``
+-----------
+
+.. attribute:: ConfigOption.section
+
+The :class:`~configglue.pyschema.ConfigSection` object where this option was
+defined.
+
+Default is ``None``.
+
+.. ``action``
+..  ----------
+..
+..  .. attribute:: ConfigOption.action
+..
+..  lorem ipsum
+.. 
+..  Default is ``'store'``.
+
+.. _schema-option-types:
+
+Option types
+============
+
+.. currentmodule:: configglue.pyschema.schema
+
+``BoolConfigOption``
+--------------------
+
+.. class:: BoolConfigOption([**attributes])
+
+A true/false option.
+
+``IntConfigOption``
+-------------------
+
+.. class:: IntConfigOption([**attributes])
+
+An integer.
+
+``LinesConfigOption``
+---------------------
+
+.. class:: LinesConfigOption(item, [remove_duplicates=False, **attributes])
+
+A list of items.
+
+.. attribute:: LinesConfigOption.item
+
+    *Required*.
+
+    List elements will be parsed as being of this type. Should be an
+    instance of a subclass of :class:`~configglue.pyschema.schema.ConfigOption`.
+
+.. attribute:: LinesConfigOption.remove_duplicates
+
+    *Optional*.
+
+    If ``True``, duplicate elements will be removed from the parsed
+    value.
+
+``StringConfigOption``
+----------------------
+
+.. class:: StringConfigOption([null=False, **attributes])
+
+A string.
+
+.. attribute:: StringConfigOption.null
+
+    *Optional*.
+
+    If ``True``, a value of 'None' will be parsed into ``None``
+    instead of just leaving it as the string 'None'.
+
+
+``TupleConfigOption``
+---------------------
+
+.. class:: TupleConfigOption([length=0, **attributes])
+
+A tuple of elements.
+
+.. attribute:: TupleConfigOption.length
+
+    *Optional*.
+
+    If not 0, the tuple has to have exactly this number of elements.
+
+``DictConfigOption``
+--------------------
+
+.. class:: DictConfigOption([spec=None, strict=False, item=None, **attributes])
+
+A dictionary.
+
+.. attribute:: DictConfigOption.spec
+
+    *Optional*.
+
+    If not ``None``, should be a ``dict`` instance, such that its values
+    are instances of a subclass of
+    :class:`~configglue.pyschema.schema.ConfigOption`.
+
+.. attribute:: DictConfigOption.strict
+
+    *Optional*.
+
+    If ``True``, no keys will be allowed other than those specified
+    in the :attr:`~DictConfigOption.spec`.
+
+.. attribute:: DictConfigOption.item
+
+    *Optional*.
+
+    Any not explicitelly defined attributes will be parsed as being
+    of this type. This should be an instance of a subclass of
+    :class:`~configglue.pyschema.schema.ConfigOption`.
+

=== added directory 'doc/topics'
=== added file 'doc/topics/command-line.rst'
--- doc/topics/command-line.rst	1970-01-01 00:00:00 +0000
+++ doc/topics/command-line.rst	2011-05-02 13:17:34 +0000
@@ -0,0 +1,26 @@
+================
+The command-line
+================
+
+One of the nicest things about configglue is its ability to easily integrate
+the command line for specifying or overriding configuration values.
+
+In the example given in the :doc:`quickstart guide </intro/quickstart>`, it can
+be seen how the command line is used to supply the value of a configuration
+option.
+
+Top-level configuration options are matched using the simple
+::
+
+    --option=value
+
+syntax.
+
+Options that are within a section will be matched using the compound
+::
+
+    --section_option=value
+
+syntax; therefore it's not possible to have a section or option name contain
+underscore characters, as they would clash with the command line argument name
+resolution method.

=== added file 'doc/topics/config-file.rst'
--- doc/topics/config-file.rst	1970-01-01 00:00:00 +0000
+++ doc/topics/config-file.rst	2011-05-02 13:17:34 +0000
@@ -0,0 +1,114 @@
+===================
+Configuration files
+===================
+
+configglue uses standard INI-style configuration files to store the values for
+the configuration, in the same format supported by ConfigParser. Within a
+configuration file, there a few special syntax constructs you should be aware of. 
+
+A ConfigSection is matched by a ConfigParser section, which is defined like::
+
+    [my_section]
+
+A ConfigOption is matched by a ConfigParser option, which is defined by a
+simple key, value pair, like::
+
+    my_option = the value
+
+So, a very simple configuration file could look like::
+
+    [my_section]
+    my_option = the value
+
+This configuration file would match with a schema like the following::
+
+    class MySchema(pyschema.Schema):
+        my_section = pyschema.ConfigSection()
+        my_section.my_option = pyschema.StringConfigOption()
+
+======================
+Special considerations
+======================
+
+There is always an implicitely defined section called ``__main__``
+==================================================================
+
+A few special considerations have to be kept in mind while working with these
+configuration files. As ConfigParser requires a config file to have at least
+one section defined, any top-level ConfigOptions are added to an implicitely
+defined section called ``__main__``.
+
+Therefore, if you have a schema like::
+
+    class MySchema(pyschema.Schema):
+        foo = IntConfigOption()
+
+and you want to write a configuration file to match it, it would have to look
+like::
+
+    [__main__]
+    foo = 42
+
+
+Specifying configuration values for basic data types
+====================================================
+
+For any basic data types, such as strings, numbers and booleans, specifying
+those in your configuration files is trivial; you just have to write them down
+as `key = value` pairs.
+
+Specifying more complex data
+============================
+
+For more advanced data types, such as lists, tuples or dictionaries there are
+a few syntactic conventions you should be aware of.
+
+Tuples
+------
+
+For specifying the value of a :class:`~configglue.pyschema.schema.TupleConfigOption`,
+you just put all the values in the same line, separated by `,`, as shown::
+
+    my_tuple = 1, 2, 3
+
+This will be parsed as the tuple `(1, 2, 3)`.
+
+Lists
+-----
+
+For specifying the value of a :class:`~configglue.pyschema.schema.LinesConfigOption`,
+you just put each value on a different line, as shown::
+
+    my_list = 1
+              2
+              3
+
+This will be parsed as the list `[1, 2, 3]`.
+
+Dictionaries
+------------
+
+For specifying the value of a :class:`~configglue.pyschema.schema.DictConfigOption`,
+a special syntax convention was defined. The value of a 
+:class:`~configglue.pyschema.schema.DictConfigOption` is the name of a section
+describing the structure of that dictionary.
+
+For example, given the configuration file::
+
+    my_dict = my_dict_sect
+
+    [my_dict_sect]
+    foo = 1
+    bar = true
+
+and the schema::
+
+    class MySchema(pyschema.Schema):
+        my_dict = pyschema.DictConfigOption(
+            spec={'foo': pyschema.IntConfigOption(),
+                  'bar': pyschema.BoolConfigOption()})
+
+`my_dict` would be parsed as::
+
+    {'foo': 1, 'bar': True}
+

=== added file 'doc/topics/index.rst'
--- doc/topics/index.rst	1970-01-01 00:00:00 +0000
+++ doc/topics/index.rst	2011-05-02 13:17:34 +0000
@@ -0,0 +1,13 @@
+Using configglue
+================
+
+Introductions to all the key parts of configglue you'll need to know:
+
+.. toctree::
+   :maxdepth: 1
+
+   install
+   schemas
+   config-file
+   command-line
+

=== added file 'doc/topics/install.rst'
--- doc/topics/install.rst	1970-01-01 00:00:00 +0000
+++ doc/topics/install.rst	2011-05-02 13:17:34 +0000
@@ -0,0 +1,139 @@
+=========================
+How to install configglue
+=========================
+
+This document will get you up and running with configglue.
+
+Install Python
+==============
+
+Being a Python library, configglue requires Python.
+
+It works with any Python version from 2.6 to 2.7 (due to backwards
+incompatibilities in Python 3.0, configglue does not currently work with
+Python 3.0; see :doc:`the configglue FAQ </faq/install>` for more
+information on supported Python versions and the 3.0 transition).
+
+Get Python at http://www.python.org. If you're running Linux or Mac OS X, you
+probably already have it installed.
+
+
+Remove any old versions of configglue
+=====================================
+
+If you are upgrading your installation of configglue from a previous version,
+you will need to uninstall the old configglue version before installing the
+new version.
+
+If you installed configglue using ``setup.py install``, uninstalling
+is as simple as deleting the ``configglue`` directory from your Python
+``site-packages``.
+
+If you installed configglue from a Python egg, remove the configglue ``.egg`` file,
+and remove the reference to the egg in the file named ``easy-install.pth``.
+This file should also be located in your ``site-packages`` directory.
+
+.. _finding-site-packages:
+
+.. admonition:: Where are my ``site-packages`` stored?
+
+    The location of the ``site-packages`` directory depends on the operating
+    system, and the location in which Python was installed. To find out your
+    system's ``site-packages`` location, execute the following:
+
+    .. code-block:: bash
+
+        python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"
+
+    (Note that this should be run from a shell prompt, not a Python interactive
+    prompt.)
+
+.. _install-configglue-code:
+
+Install the configglue code
+===========================
+
+Installation instructions are slightly different depending on whether you're
+installing a distribution-specific package, downloading the latest official
+release, or fetching the latest development version.
+
+It's easy, no matter which way you choose.
+
+Installing a distribution-specific package
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Check the :doc:`distribution specific notes </misc/distributions>` to see if your
+platform/distribution provides official configglue packages/installers.
+Distribution-provided packages will typically allow for automatic installation
+of dependencies and easy upgrade paths.
+
+.. _installing-official-release:
+
+Installing an official release
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    1. Download the latest release from our `download page`_.
+
+    2. Untar the downloaded file (e.g. ``tar xzvf configglue-NNN.tar.gz``,
+       where ``NNN`` is the version number of the latest release).
+       If you're using Windows, you can download the command-line tool
+       bsdtar_ to do this, or you can use a GUI-based tool such as 7-zip_.
+
+    3. Change into the directory created in step 2 (e.g. ``cd configglue-NNN``).
+
+    4. If you're using Linux, Mac OS X or some other flavor of Unix, enter
+       the command ``sudo python setup.py install`` at the shell prompt.
+       If you're using Windows, start up a command shell with administrator
+       privileges and run the command ``setup.py install``.
+
+These commands will install configglue in your Python installation's
+``site-packages`` directory.
+
+.. _bsdtar: http://gnuwin32.sourceforge.net/packages/bsdtar.htm
+.. _7-zip: http://www.7-zip.org/
+
+.. _installing-development-version:
+
+Installing the development version
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. admonition:: Tracking configglue development
+
+    If you decide to use the latest development version of configglue,
+    you'll want to pay close attention to the changes made on trunk, until
+    we manage to implement a better way of notifying about changes being made.
+    This will help you stay on top
+    of any new features you might want to use, as well as any changes
+    you'll need to make to your code when updating your copy of configglue.
+    (For stable releases, any necessary changes are documented in the
+    release notes.)
+
+If you'd like to be able to update your configglue code occasionally with the
+latest bug fixes and improvements, follow these instructions:
+
+1. Make sure that you have Bazaar_ installed, and that you can run its
+   commands from a shell. (Enter ``bzr help`` at a shell prompt to test
+   this.)
+
+2. Check out configglue's main development branch (the 'trunk') like so:
+
+   .. code-block:: bash
+
+       bzr branch https://code.launchpad.net/~configglue/configglue/trunk configglue-trunk
+
+3. Next, make sure that the Python interpreter can load configglue's code. The most
+   convenient way to do this is to use setuptools' develop target.
+   For example, on a Unix-like system:
+
+   .. code-block:: bash
+
+       cd configglue-trunk
+       python setup.py develop
+
+When you want to update your copy of the configglue source code, just run the
+command ``bzr pull`` from within the ``configglue-trunk`` directory. When you do
+this, Bazaar will automatically download any changes.
+
+.. _`download page`: https://launchpad.net/configglue/+download
+.. _Bazaar: http://bazaar-vcs.org/
+.. _`modify Python's search path`: http://docs.python.org/install/index.html#mo

=== added file 'doc/topics/schemas.rst'
--- doc/topics/schemas.rst	1970-01-01 00:00:00 +0000
+++ doc/topics/schemas.rst	2011-05-02 13:17:34 +0000
@@ -0,0 +1,192 @@
+=======
+Schemas
+=======
+
+.. module:: configglue.pyschema.schema
+
+A schema is a static declaration of all your configuration settings. It
+contains metadata about each setting so that the configuration can later
+be validated.
+
+The basics:
+
+    * Each schema is a Python class that subclasses
+      :class:`~configglue.pyschema.schema.Schema`.
+
+    * Each attribute of the schema represents either a configuration section
+      (see :class:`~configglue.pyschema.schema.ConfigSection`) or
+      option (see :class:`~configglue.pyschema.schema.ConfigOption`).
+
+Quick example
+=============
+
+This example schema defines the configuration for a database connection::
+
+    from configglue import pyschema
+
+    class DatabaseConnection(pyschema.Schema):
+        host = pyschema.StringConfigOption(
+            default='localhost',
+            help='Host where the database engine is listening on')
+        port = pyschema.IntConfigOption(
+            default=5432,
+            help='Port where the database engine is listening on')
+        dbname = pyschema.StringConfigOption(
+            fatal=True,
+            help='Name of the database to connect to')
+        user = pyschema.StringConfigOption(
+            help='Username to use for the connection')
+        password = pyschema.StringConfigOption(
+            help='Password to use fot the connection')
+
+``host``, ``port``, ``dbname``, ``user`` and ``password`` are options_ of the
+schema. Each option is specified as a class attribute.
+
+Options
+=======
+
+The most important part of a schema is the list of configuration options it
+defines. Options are specified by class attributes.
+
+Example::
+
+    class OvenSettings(pyschema.Schema):
+        temperature = pyschema.IntConfigOption()
+        time = pyschema.IntConfigOption()
+
+Option types
+------------
+
+Each option in your schema should be an instance of the appropriate
+:class:`~configglue.pyschema.schema.ConfigOption` class.
+
+configglue ships with a couple of built-in option types; you can find the
+complete list in the :ref:`schema option reference <schema-option-types>`. You
+can easily write your own options if configglue's built-in ones don't do the
+trick; see :doc:`/howto/custom-schema-options`.
+
+Option attributes
+-----------------
+
+Each option takes a certain set of option-specific arguments (documented in
+the :ref:`schema option reference <schema-option-types>`). For example,
+:class:`~configglue.pyschema.schema.LinesConfigOption` (and its subclasses)
+require a :attr:`~configglue.pyschema.schema.LinesConfigOption.item` argument
+which specifies the type of the items contained in the list.
+
+There's also a set of common arguments available to all option types. All are
+optional. They're fully explained in the :ref:`reference
+<common-schema-option-attributes>`, but here's a quick summary of the most
+often-used ones:
+
+    :attr:`~ConfigOption.default`
+        The default value for this option, if none is provided in the config file.
+        Default is :attr:`configglue.pyschema.schema.NO_DEFAULT`.
+
+    :attr:`~ConfigOption.fatal`
+        If ``True``, :func:`SchemaConfigParser.parse_all` will raise an exception if no
+        value is provided in the configuration file for this option. Otherwise,
+        :attr:`self.default` will be used. 
+        Default is ``False``.
+
+    :attr:`~ConfigOption.help`
+        The help text describing this option. This text will be used as the
+        :class:`optparse.OptParser` help text.
+        Default is ``''``.
+
+Again, these are just short descriptions of the most common option attributes.
+Full details can be found in the :ref:`common schema option attribute reference <common-schema-option-attributes>`.
+
+Option name restrictions
+------------------------
+
+configglue places only one restriction on schema option names:
+
+    A option name cannot be a Python reserved word, because that would
+    result in a Python syntax error. For example::
+
+        class Example(pyschema.Schema):
+            pass = pyschema.IntConfigOption() # 'pass' is a reserved word!
+
+Custom option types
+-------------------
+
+If one of the existing options cannot be used to fit your purposes, you can
+create your own option class. Full coverage of creating your own options is
+provided in :doc:`/howto/custom-schema-options`.
+
+.. _schema-inheritance:
+
+Schema inheritance
+==================
+
+Schema inheritance in configglue works almost identically to the way normal
+class inheritance works in Python.
+
+Section name "hiding"
+---------------------
+
+In normal Python class inheritance, it is permissible for a child class to
+override any attribute from the parent class.
+
+In order to allow easy extending of schemas, configglue overloads the standard
+Python inheritance model. Whenever a schema is created, it will inherit all
+its attributes from the base classes.
+
+This poses a slight problem for attributes of type
+:class:`~configglue.pyschema.schema.ConfigSection`. Usually, you'll want to
+extend a :class:`~configglue.pyschema.schema.ConfigSection` instead of
+overriding it. In order to achieve this, in your schema subclass, copy the
+parent's attribute explicitely, to avoid modifying the parent schema class.
+Option attributes (derived from
+:class:`~configglue.pyschema.schema.ConfigOption`) will be overridden, as
+expected.
+
+For example::
+
+    from copy import deepcopy
+
+    from configglue import pyschema
+
+
+    class BaseSchema(pyschema.Schema):
+        option1 = pyschema.IntConfigOption()
+        section1 = pyschema.ConfigSection()
+        section1.option1 = pyschema.BoolConfigOption()
+
+
+    class ChildSchema(BaseSchema):
+        option2 = pyschema.IntConfigOption()
+        section1 = deepcopy(BaseSchema.section1)
+        section1.option2 = IntConfigOption()
+
+In this example :class:`ChildSchema` will have two top-level options,
+:attr:`option1` and :attr:`option2`, and one section :attr:`section1`, which
+will have also two options within in (:attr:`section1.option1` and
+:attr:`section1.option2`). So, defining :class:`ChildSchema` in this way
+produces the same result as explicitely describing each attribute, as
+expected::
+
+    from configglue import pyschema
+
+    class ChildSchema(pyschema.Schema):
+        option1 = pyschema.IntConfigOption()
+        option2 = pyschema.IntConfigOption()
+        section1 = pyschema.ConfigSection()
+        section1.option1 = pyschema.BoolConfigOption()
+        section1.option2 = IntConfigOption()
+
+
+Multiple inheritance
+--------------------
+
+Just as with Python's subclassing, it's possible for a configglue schema to
+inherit from multiple parent schemas. Keep in mind that normal Python name
+resolution rules apply.
+
+Generally, you won't need to inherit from multiple parents. The main use-case
+where this is useful is for "mix-in" classes: adding a particular extra option
+to every class that inherits the mix-in. Try to keep your inheritance
+hierarchies as simple and straightforward as possible so that you won't have
+to struggle to work out where a particular piece of information is coming
+from.