configglue team mailing list archive
-
configglue team
-
Mailing list archive
-
Message #00067
[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.