summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris St. Pierre <chris.a.st.pierre@gmail.com>2012-09-26 14:13:04 -0400
committerChris St. Pierre <chris.a.st.pierre@gmail.com>2012-09-26 14:13:04 -0400
commit7f34f6b89c5d44f96856adfcea30a47d525f4c64 (patch)
tree43364bbe2c23497ea113c1a8d8f2cf8c35854dc7
parent552fa7b683dcdcbbc58dc2871e31f54d8db14a64 (diff)
downloadbcfg2-7f34f6b89c5d44f96856adfcea30a47d525f4c64.tar.gz
bcfg2-7f34f6b89c5d44f96856adfcea30a47d525f4c64.tar.bz2
bcfg2-7f34f6b89c5d44f96856adfcea30a47d525f4c64.zip
wrote docs for Bcfg2.Compat
-rw-r--r--doc/conf.py21
-rw-r--r--doc/development/compat.txt199
-rw-r--r--doc/development/index.txt13
-rw-r--r--src/lib/Bcfg2/Compat.py55
4 files changed, 238 insertions, 50 deletions
diff --git a/doc/conf.py b/doc/conf.py
index 7fc10ad61..538cd236d 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -254,7 +254,20 @@ def setup(app):
app.connect('autodoc-skip-member', skip_member_from_docstring)
# intersphinx settings
-intersphinx_mapping = dict(
- py=('http://docs.python.org/%s' % '.'.join(str(v)
- for v in sys.version_info[0:2]),
- None))
+
+# generate intersphinx mappings for all versions of python we support;
+# the default will be the version of python this is built with.
+# Python only started using sphinx in 2.6, so we won't have docs for
+# 2.4 or 2.5. These are in reverse order, since sphinx seems to look
+# in the last mapping first.
+versions = ["3.2", "2.7", "2.6"]
+cur_version = '.'.join(str(v) for v in sys.version_info[0:2])
+
+intersphinx_mapping = dict()
+for pyver in versions:
+ if pyver == cur_version:
+ key = 'py'
+ else:
+ key = 'py' + pyver.replace(".", "")
+ intersphinx_mapping[key] = ('http://docs.python.org/%s' % pyver,
+ None)
diff --git a/doc/development/compat.txt b/doc/development/compat.txt
new file mode 100644
index 000000000..d3e77b4a3
--- /dev/null
+++ b/doc/development/compat.txt
@@ -0,0 +1,199 @@
+.. -*- mode: rst -*-
+
+.. _development-compat:
+
+====================
+Python Compatibility
+====================
+
+Bcfg2 maintains compatibility with a wide range of Python versions --
+currently 2.4 through 3.2 This requires some (often significant)
+compatibility interfaces. This page documents the compatibility
+library, ``Bcfg2.Compat``, and its contents.
+
+Note that, due to limitations in Sphinx (the Bcfg2 documentation
+tool), this documentation is *not* automatically generated.
+``Compat.py`` should always be considered the authoritative source.
+
+There are several basic types of symbols found in ``Bcfg2.Compat``:
+
+* Symbols whose names have changed, e.g., ``MutableMapping``.
+* Symbols whose modules have changed names, e.g., ``urljoin``/``urlparse``
+* Symbols that have been added or removed, e.g., ``any``/``all``, ``reduce``,
+ ``walk_packages``
+* Symbols that need some significant workaround to function
+ identically in all versions, e.g., ``b64encode``/``b64decode``.
+* Helper functions and classes for compatibility, e.g., ``CmpMixin``.
+
+Using ``Bcfg2.Compat``
+======================
+
+To use the compatibility libraries, simply import them as such:
+
+.. code-block:: python
+
+ from Bcfg2.Compat import StringIO, all
+
+The individual symbol import is preferred over just importing
+``Bcfg2.Compat`` as a whole, since in the future we will be able to
+remove some items from the library and this makes that process
+easier. A wildcard import is definitely discouraged.
+
+Bcfg2.Compat symbols
+====================
+
+``Bcfg2.Compat`` defines the following symbols:
+
+Py3K compatibility imports
+--------------------------
+
+The following symbols are imported to provide compatibility with
+Python 3. In cases where the newer symbols has also been backported
+to Python 2, the older symbol will be used unless otherwise noted.
+This is to ensure that functions or modules with radically different
+behavior (e.g., :func:`input`) do not cause unexpected side-effects.
+
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| Name | Python 2 | Python 3 |
++=================================+==================================================+=========================================================+
+| urljoin | :func:`urlparse.urljoin` | :func:`urllib.parse.urljoin` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| urlparse | :func:`urlparse.urlparse` | :func:`urllib.parse.urlparse` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| HTTPBasicAuthHandler | :class:`urllib2.HTTPBasicAuthHandler` | :class:`urllib.request.HTTPBasicAuthHandler` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| HTTPPasswordMgrWithDefaultRealm | :class:`urllib2.HTTPPasswordMgrWithDefaultRealm` | :class:`urllib.request.HTTPPasswordMgrWithDefaultRealm` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| build_opener | :func:`urllib2.build_opener` | :func:`urllib.request.build_opener` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| install_opener | :func:`urllib2.install_opener` | :func:`urllib.request.install_opener` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| urlopen | :func:`urllib2.urlopen` | :func:`urllib.request.urlopen` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| HTTPError | :exc:`urllib2.HTTPError` | :exc:`urllib.error.HTTPError` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| URLError | :exc:`urllib2.URLError` | :exc:`urllib.error.URLError` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| StringIO | :func:`cStringIO.StringIO` | :class:`io.StringIO` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| ConfigParser | :mod:`ConfigParser` | :mod:`configparser` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| cPickle | :mod:`cPickle` | :mod:`pickle` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| Queue | :class:`Queue.Queue` | :class:`queue.Queue` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| Empty | :exc:`Queue.Empty` | :exc:`queue.Empty` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| Full | :exc:`Queue.Full` | :exc:`queue.Full` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| xmlrpclib | :mod:`xmlrpclib` | :mod:`xmlrpc.client` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| SimpleXMLRPCServer | :mod:`SimpleXMLRPCServer` | :mod:`xmlrpc.server` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| SocketServer | :mod:`SocketServer` | :mod:`socketserver` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| httplib | :mod:`httplib` | :mod:`http.client` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| input | :func:`raw_input` | :func:`input` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+| reduce | :func:`reduce` | :func:`functools.reduce` |
++---------------------------------+--------------------------------------------------+---------------------------------------------------------+
+
+Python 2.4 compatibility
+------------------------
+
+The following symbols are imported or defined to provide compatibility
+with Python 2.4 (and occasionally 2.5). Be sure to read the notes
+below, since some of these implementations may be feature-incomplete.
+
++----------------+--------------------------------+--------------------------------------------+
+| Name | Python 2.4 | Python 2.4+ |
++================+================================+============================================+
+| formatdate | :func:`email.Utils.formatdate` | :func:`email.utils.formatdate` |
++----------------+--------------------------------+--------------------------------------------+
+| walk_packages | Not implemented | :func:`pkgutil.walk_packages` (2.6+) |
++----------------+--------------------------------+--------------------------------------------+
+| any | Not implemented | :func:`any` |
++----------------+--------------------------------+--------------------------------------------+
+| all | Not implemented | :func:`all` |
++----------------+--------------------------------+--------------------------------------------+
+| wraps | Not implemented | :func:`functools.wraps` |
++----------------+--------------------------------+--------------------------------------------+
+| md5 | :func:`md5.md5` | :class:`hashlib.md5` |
++----------------+--------------------------------+--------------------------------------------+
+| MutableMapping | :class:`UserDict.DictMixin` | :class:`collections.MutableMapping` (2.6+) |
++----------------+--------------------------------+--------------------------------------------+
+
+walk_packages
+~~~~~~~~~~~~~
+
+The ``walk_packages`` implementation for Python 2.5 is
+feature-complete. The implementation for Python 2.4 is *not*.
+Differences:
+
+* Requires a full path, not a path relative to something in sys.path.
+ Anywhere we care about that shouldn't be an issue.
+* The first element of each tuple is None instead of an importer
+ object.
+
+wraps
+~~~~~
+
+The ``wraps`` implementation for Python 2.4 is a no-op. It does not
+attempt to copy the docstring or other details from the original
+function to the wrapped function.
+
+md5
+~~~
+
+:mod:`hashlib` is available for Python 2.4, but it is not part of the
+standard base. If it is installed, it will be used. If you are doing
+something fancy with MD5 sums, you may need to determine which object
+is in use, since they are not equivalent. For the majority of simple
+cases -- finding the MD5 sum of a string -- they are equivalent
+enough.
+
+MutableMapping
+~~~~~~~~~~~~~~
+
+:class:`collections.MutableMapping` provides a subset of the
+functionality of :class:`UserDict.DictMixin`; that is, any object that
+is written to work with ``MutableMapping`` will also work with
+``DictMixin``, so you should write classes with ``MutableMapping`` in
+mind.
+
+:class:`collections.MutableMapping` is available in Python 2.6+, and
+will be used if available.
+
+Other Symbols
+-------------
+
+The following functions, classes, and symbols are provided for other
+miscellaneous reasons.
+
+u_str
+~~~~~
+
+.. autofunction:: Bcfg2.Compat.u_str
+
+b64encode/b64decode
+~~~~~~~~~~~~~~~~~~~
+
+In Python 2, :func:`base64.b64encode` and :func:`base64.b64decode`
+expect strings and return strings. In Python 3, they expect bytes and
+return bytes. For Python 3, ``Bcfg2.Compat`` provides ``b64encode``
+and ``b64encode`` that transparently encode strings into bytes, then
+decode bytes into strings, so that those functions can be used
+identically to their use in Python 2.
+
+CmpMixin
+~~~~~~~~
+
+.. autoclass:: Bcfg2.Compat.CmpMixin
+
+unicode
+~~~~~~~
+
+In Py3k, the :func:`unicode` class is not defined, because all
+strings are unicode. ``Bcfg2.Compat`` defines ``unicode`` as
+equivalent to :func:`str` in Python 3.
diff --git a/doc/development/index.txt b/doc/development/index.txt
index 3eb05e940..be864ab84 100644
--- a/doc/development/index.txt
+++ b/doc/development/index.txt
@@ -20,15 +20,6 @@ git access. Mail the :ref:`help-mailinglist` for details.
.. toctree::
:maxdepth: 1
+ :glob:
- tips
- setup
- client-driver
- plugins
- cfg
- packages
- testing
- documentation
- docstyleguide
- unit-testing
- versioning
+ *
diff --git a/src/lib/Bcfg2/Compat.py b/src/lib/Bcfg2/Compat.py
index 635c49a49..9399fc440 100644
--- a/src/lib/Bcfg2/Compat.py
+++ b/src/lib/Bcfg2/Compat.py
@@ -13,22 +13,14 @@ except ImportError:
# urllib imports
try:
from urlparse import urljoin, urlparse
- from urllib2 import HTTPBasicAuthHandler
- from urllib2 import HTTPPasswordMgrWithDefaultRealm
- from urllib2 import build_opener
- from urllib2 import install_opener
- from urllib2 import urlopen
- from urllib2 import HTTPError
- from urllib2 import URLError
+ from urllib2 import HTTPBasicAuthHandler, \
+ HTTPPasswordMgrWithDefaultRealm, build_opener, install_opener, \
+ urlopen, HTTPError, URLError
except ImportError:
from urllib.parse import urljoin, urlparse
- from urllib.request import HTTPBasicAuthHandler
- from urllib.request import HTTPPasswordMgrWithDefaultRealm
- from urllib.request import build_opener
- from urllib.request import install_opener
- from urllib.request import urlopen
- from urllib.error import HTTPError
- from urllib.error import URLError
+ from urllib.request import HTTPBasicAuthHandler, \
+ HTTPPasswordMgrWithDefaultRealm, build_opener, install_opener, urlopen
+ from urllib.error import HTTPError, URLError
try:
from cStringIO import StringIO
@@ -69,12 +61,10 @@ try:
except ImportError:
import http.client as httplib
-# py3k compatibility
-if sys.hexversion >= 0x03000000:
- unicode = str
-else:
+try:
unicode = unicode
-
+except NameError:
+ unicode = str
def u_str(string, encoding=None):
""" print to file compatibility """
@@ -89,11 +79,6 @@ def u_str(string, encoding=None):
else:
return unicode(string)
-try:
- unicode = unicode
-except NameError:
- unicode = str
-
# base64 compat
if sys.hexversion >= 0x03000000:
from base64 import b64encode as _b64encode, b64decode as _b64decode
@@ -119,8 +104,9 @@ except ImportError:
class CmpMixin(object):
- """ in py3k __cmp__ is no longer magical, so this mixin can be
- used to define the rich comparison operators from __cmp__ """
+ """ In Py3K, :meth:`object.__cmp__` is no longer magical, so this
+ mixin can be used to define the rich comparison operators from
+ ``__cmp__`` -- i.e., it makes ``__cmp__`` magical again. """
def __lt__(self, other):
return self.__cmp__(other) < 0
@@ -184,15 +170,14 @@ except ImportError:
import os
def walk_packages(path=None, prefix='', onerror=None):
- """ imperfect, incomplete implementation of
- walk_packages() for python 2.4. Differences:
-
- * requires a full path, not a path relative to something
- in sys.path. anywhere we care about that shouldn't be
- an issue
-
- * the first element of each tuple is None instead of an
- importer object
+ """ Imperfect, incomplete implementation of
+ :func:`pkgutil.walk_packages` for python 2.4. Differences:
+
+ * Requires a full path, not a path relative to something
+ in sys.path. Anywhere we care about that shouldn't be
+ an issue.
+ * The first element of each tuple is None instead of an
+ importer object.
"""
if path is None:
path = sys.path