[Checkins] SVN: z3c.recipe.staticlxml/trunk/ Initial check-in.

Stefan Eletzhofer stefan.eletzhofer at inquant.de
Thu Nov 27 09:22:15 EST 2008


Log message for revision 93395:
  Initial check-in.

Changed:
  A   z3c.recipe.staticlxml/trunk/CHANGES.txt
  A   z3c.recipe.staticlxml/trunk/CONTRIBUTORS.txt
  A   z3c.recipe.staticlxml/trunk/README.txt
  A   z3c.recipe.staticlxml/trunk/bootstrap.py
  A   z3c.recipe.staticlxml/trunk/buildout.cfg
  A   z3c.recipe.staticlxml/trunk/downloads/
  A   z3c.recipe.staticlxml/trunk/setup.py
  A   z3c.recipe.staticlxml/trunk/src/
  A   z3c.recipe.staticlxml/trunk/src/z3c/
  A   z3c.recipe.staticlxml/trunk/src/z3c/__init__.py
  A   z3c.recipe.staticlxml/trunk/src/z3c/recipe/
  A   z3c.recipe.staticlxml/trunk/src/z3c/recipe/__init__.py
  A   z3c.recipe.staticlxml/trunk/src/z3c/recipe/staticlxml/
  A   z3c.recipe.staticlxml/trunk/src/z3c/recipe/staticlxml/README.txt
  A   z3c.recipe.staticlxml/trunk/src/z3c/recipe/staticlxml/__init__.py
  A   z3c.recipe.staticlxml/trunk/src/z3c/recipe/staticlxml/tests/
  A   z3c.recipe.staticlxml/trunk/src/z3c/recipe/staticlxml/tests/__init__.py
  A   z3c.recipe.staticlxml/trunk/src/z3c/recipe/staticlxml/tests/test_docs.py

-=-
Added: z3c.recipe.staticlxml/trunk/CHANGES.txt
===================================================================
--- z3c.recipe.staticlxml/trunk/CHANGES.txt	                        (rev 0)
+++ z3c.recipe.staticlxml/trunk/CHANGES.txt	2008-11-27 14:22:15 UTC (rev 93395)
@@ -0,0 +1,6 @@
+trunk
+=====
+
+- Added tweaks needed for Mac OS X [seletz]
+- Added basic build steps for liblxml2, libxslt and lxml. [seletz]
+- Created recipe with ZopeSkel [seletz].

Added: z3c.recipe.staticlxml/trunk/CONTRIBUTORS.txt
===================================================================
--- z3c.recipe.staticlxml/trunk/CONTRIBUTORS.txt	                        (rev 0)
+++ z3c.recipe.staticlxml/trunk/CONTRIBUTORS.txt	2008-11-27 14:22:15 UTC (rev 93395)
@@ -0,0 +1,2 @@
+Stefan Eletzhofer, Author
+

Added: z3c.recipe.staticlxml/trunk/README.txt
===================================================================
--- z3c.recipe.staticlxml/trunk/README.txt	                        (rev 0)
+++ z3c.recipe.staticlxml/trunk/README.txt	2008-11-27 14:22:15 UTC (rev 93395)
@@ -0,0 +1,10 @@
+*******************************************************************
+Recipe for building and installing a static version of the lxml egg
+*******************************************************************
+
+This recipe automates the installation of the ``lxml`` python package
+and, additionally, builds it **statically** against dependent libraries
+like ``libxml2``, ``libxlst``.
+
+.. contents::
+

Added: z3c.recipe.staticlxml/trunk/bootstrap.py
===================================================================
--- z3c.recipe.staticlxml/trunk/bootstrap.py	                        (rev 0)
+++ z3c.recipe.staticlxml/trunk/bootstrap.py	2008-11-27 14:22:15 UTC (rev 93395)
@@ -0,0 +1,52 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id$
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+ez = {}
+exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+                     ).read() in ez
+ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+import pkg_resources
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+if sys.platform == 'win32':
+    cmd = '"%s"' % cmd # work around spawn lamosity on windows
+
+ws = pkg_resources.working_set
+assert os.spawnle(
+    os.P_WAIT, sys.executable, sys.executable,
+    '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout',
+    dict(os.environ,
+         PYTHONPATH=
+         ws.find(pkg_resources.Requirement.parse('setuptools')).location
+         ),
+    ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)

Added: z3c.recipe.staticlxml/trunk/buildout.cfg
===================================================================
--- z3c.recipe.staticlxml/trunk/buildout.cfg	                        (rev 0)
+++ z3c.recipe.staticlxml/trunk/buildout.cfg	2008-11-27 14:22:15 UTC (rev 93395)
@@ -0,0 +1,25 @@
+[buildout]
+parts =
+   lxml
+   pylxml
+develop = .
+
+log-level = DEBUG
+
+index = http://dist.repoze.org/lemonade/dev/simple
+
+download-directory = downloads
+download-cache = downloads
+
+[pylxml]
+recipe=zc.recipe.egg
+interpreter=pylxml
+eggs=
+    lxml
+
+[lxml]
+recipe = z3c.recipe.staticlxml
+egg = lxml==2.1.2
+build-libxml2 = true
+build-libxslt = true
+static-build = false

Added: z3c.recipe.staticlxml/trunk/setup.py
===================================================================
--- z3c.recipe.staticlxml/trunk/setup.py	                        (rev 0)
+++ z3c.recipe.staticlxml/trunk/setup.py	2008-11-27 14:22:15 UTC (rev 93395)
@@ -0,0 +1,70 @@
+# -*- coding: utf-8 -*-
+"""
+This module contains the tool of z3c.recipe.staticlxml
+"""
+import os
+from setuptools import setup, find_packages
+
+def read(*rnames):
+    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+version = '0.1'
+
+long_description = (
+    read('README.txt')
+    + '\n' +
+    'Detailed Documentation\n'
+    '**********************\n'
+    + '\n' +
+    read('src', 'z3c', 'recipe', 'staticlxml', 'README.txt')
+    + '\n' +
+    'Contributors\n' 
+    '************\n'
+    + '\n' +
+    read('CONTRIBUTORS.txt')
+    + '\n' +
+    'Change history\n'
+    '**************\n'
+    + '\n' + 
+    read('CHANGES.txt')
+    + '\n' +
+   'Download\n'
+    '********\n'
+    )
+entry_point = 'z3c.recipe.staticlxml:Recipe'
+entry_points = {"zc.buildout": ["default = %s" % entry_point]}
+
+tests_require=['zope.testing', 'zc.buildout']
+
+setup(name='z3c.recipe.staticlxml',
+      version=version,
+      description="A recipe to build lxml",
+      long_description=long_description,
+      classifiers=[
+        'Framework :: Buildout',
+        'Intended Audience :: Developers',
+        'Topic :: Software Development :: Build Tools',
+        'Topic :: Software Development :: Libraries :: Python Modules',
+        'License :: OSI Approved :: Zope Public License',
+        ],
+      keywords='buildout recipe lxml static',
+      author='Stefan Eletzhofer',
+      author_email='stefan.eletzhofer at inquant.de',
+      url='http://svn.zope.org/z3c.recipe.staticlxml/trunk',
+      license='ZPL',
+      packages=find_packages('src', exclude=['ez_setup']),
+      package_dir = {'': 'src'},
+      namespace_packages=['z3c', 'z3c.recipe'],
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'zc.buildout',
+                        'zc.recipe.egg',
+                        'zc.recipe.cmmi'
+                        # -*- Extra requirements: -*-
+                        ],
+      tests_require=tests_require,
+      extras_require=dict(tests=tests_require),
+      test_suite = 'z3c.recipe.staticlxml.tests.test_docs.test_suite',
+      entry_points=entry_points,
+      )

Added: z3c.recipe.staticlxml/trunk/src/z3c/__init__.py
===================================================================
--- z3c.recipe.staticlxml/trunk/src/z3c/__init__.py	                        (rev 0)
+++ z3c.recipe.staticlxml/trunk/src/z3c/__init__.py	2008-11-27 14:22:15 UTC (rev 93395)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

Added: z3c.recipe.staticlxml/trunk/src/z3c/recipe/__init__.py
===================================================================
--- z3c.recipe.staticlxml/trunk/src/z3c/recipe/__init__.py	                        (rev 0)
+++ z3c.recipe.staticlxml/trunk/src/z3c/recipe/__init__.py	2008-11-27 14:22:15 UTC (rev 93395)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

Added: z3c.recipe.staticlxml/trunk/src/z3c/recipe/staticlxml/README.txt
===================================================================
--- z3c.recipe.staticlxml/trunk/src/z3c/recipe/staticlxml/README.txt	                        (rev 0)
+++ z3c.recipe.staticlxml/trunk/src/z3c/recipe/staticlxml/README.txt	2008-11-27 14:22:15 UTC (rev 93395)
@@ -0,0 +1,61 @@
+Supported options
+=================
+
+The recipe supports the following options:
+
+egg
+    Set to the desired lxml egg, e.g. ``lxml`` or ``lxml==2.1.2``
+
+build-libxslt, build-libxml2
+    Set to ``true`` if these should be build.  Needed for a static build.
+
+static-build
+    ``true``or ``false``
+
+xml2-loction
+    Needed if ``libxml2`` is not built.
+
+xslt-loction
+    Needed if ``libxml2`` is not built.
+
+xslt-config
+    Path to the ``xslt-config`` binary.  Not needed if ``build-libxslt`` is
+    set to true.
+
+xml2-config
+    Path to the ``xml2-config`` binary.  Not needed if ``build-libxml2`` is
+    set to true.
+
+force
+    Set to ``true`` to force rebuilding libraries every time.
+
+
+Example usage
+=============
+
+We'll start by creating a buildout that uses the recipe::
+
+    >>> xsltconfig = "foo"
+    >>> xml2config = "bar"
+    >>> write('buildout.cfg',
+    ... """
+    ... [buildout]
+    ... parts = test1
+    ... log-level = INFO
+    ... index = http://dist.repoze.org/lemonade/dev/simple
+    ...
+    ... [test1]
+    ... recipe = z3c.recipe.staticlxml
+    ... xslt-config = %(xsltconfig)s
+    ... xml2-config = %(xml2config)s
+    ... """ % locals())
+
+Running the buildout gives us::
+
+    >>> system(buildout) 
+    Installing test1.
+    xslt-config: foo
+    xml2-config: bar
+    <BLANKLINE>
+
+

Added: z3c.recipe.staticlxml/trunk/src/z3c/recipe/staticlxml/__init__.py
===================================================================
--- z3c.recipe.staticlxml/trunk/src/z3c/recipe/staticlxml/__init__.py	                        (rev 0)
+++ z3c.recipe.staticlxml/trunk/src/z3c/recipe/staticlxml/__init__.py	2008-11-27 14:22:15 UTC (rev 93395)
@@ -0,0 +1,252 @@
+# -*- coding: utf-8 -*-
+"""Recipe staticlxml"""
+
+import sys
+import os
+import pkg_resources
+import logging
+import subprocess
+from fnmatch import fnmatch
+
+import distutils.core
+from distutils import sysconfig
+import setuptools.command.easy_install
+
+from zc.buildout import UserError
+from zc.buildout import easy_install
+
+from zc.recipe.egg.custom import Custom
+from zc.recipe.egg.custom import build_ext
+
+import zc.recipe.cmmi
+
+
+def which(fname, path=None):
+    """Return first matching binary in path or os.environ["PATH"]
+    """
+    if path is None:
+        path = os.environ.get("PATH")
+    fullpath = filter(os.path.isdir,path.split(os.pathsep))
+
+    out = []
+    if '.' not in fullpath:
+        fullpath = ['.'] + fullpath
+    fn = fname
+    for p in fullpath:
+        for f in os.listdir(p):
+            head, ext = os.path.splitext(f)
+            if f == fn or fnmatch(head, fn):
+                return os.path.join(p,f)
+    return None
+
+
+class Recipe(object):
+    """zc.buildout recipe"""
+
+    def __init__(self, buildout, name, options):
+        self.buildout, self.name, self.options = buildout, name, options
+        self.logger = logging.getLogger(name)
+
+        self.xslt_cmmi = zc.recipe.cmmi.Recipe(buildout, "libxslt", options.copy())
+        self.xml2_cmmi = zc.recipe.cmmi.Recipe(buildout, "libxml2", options.copy())
+
+        # force build option
+        force = options.get("force")
+        self.force = force in ("true", "True")
+        options["force"] = force and "true" or "false"
+
+        # XLST build or location option
+        build_xslt = options.get("build-libxslt")
+        self.build_xslt = build_xslt in ("true", "True")
+        options["build-libxslt"] = build_xslt and "true" or "false"
+
+        if not self.build_xslt:
+            self.xslt_location = options.get("xslt-location")
+            if not self.xslt_location:
+                raise UserError("You must either configure ``xslt-location`` or set"
+                        " ``build-libxslt`` to ``true``")
+
+        # XML2 build or location option
+        build_xml2 = options.get("build-libxml2")
+        self.build_xml2 = build_xml2 in ("true", "True")
+        options["build-libxml2"] = build_xml2 and "true" or "false"
+
+        if not self.build_xml2:
+            self.xml2_location = options.get("xml2-location")
+            if not self.xml2_location:
+                raise UserError("You must either configure ``xml2-location`` or set"
+                        " ``build-libxml2`` to ``true``")
+
+        # static build option
+        static_build = options.get("static-build")
+        self.static_build = static_build in ("true", "True")
+        if self.static_build and not (self.build_xml2 and self.build_xslt):
+            raise UserError("Static build is only possible if both "
+                    "``build-libxml2`` and ``build-libxslt`` are ``true``.")
+        if self.static_build:
+            self.logger.info("Static build requested.")
+        options["static-build"] = self.static_build and "true" or "false"
+
+        # our location
+        location = options.get(
+            'location', buildout['buildout']['parts-directory'])
+        options['location'] = os.path.join(location, name)
+
+    def build_libxslt(self):
+        self.logger.info("CMMI libxslt ...")
+        self.options["libxslt-url"] = self.xslt_url = self.options.get("libxslt-url",
+                "http://dist.repoze.org/lemonade/dev/cmmi/libxslt-1.1.24.tar.gz")
+        self.logger.info("Using libxslt download url %s" % self.xslt_url)
+        self.xslt_cmmi.options["url"] = self.xslt_url
+        self.xslt_cmmi.options["extra_options"] = "--with-libxml-prefix=%s --without-python" % self.xml2_location
+
+        if os.path.exists(os.path.join(self.xslt_cmmi.options["location"], "bin", "xslt-config")):
+            self.logger.info("Skipping build of libxslt: already there")
+            loc = self.xslt_cmmi.options.get("location")
+        else:
+            loc = self.xslt_cmmi.install()
+
+        self.options["xslt-location"] = self.xslt_location = loc
+
+    def build_libxml2(self):
+        self.logger.info("CMMI libxml2 ...")
+        self.options["libxml2-url"] = self.xml2_url = self.options.get("libxml2-url",
+                "http://dist.repoze.org/lemonade/dev/cmmi/libxml2-2.6.32.tar.gz")
+        self.logger.info("Using libxml2 download url %s" % self.xml2_url)
+
+        self.xml2_cmmi.options["url"] = self.xml2_url
+        self.xml2_cmmi.options["extra_options"] = "--without-python"
+
+        if not self.force and os.path.exists(os.path.join(self.xml2_cmmi.options["location"], "bin", "xml2-config")):
+            self.logger.info("Skipping build of libxml2: already there")
+            loc = self.xml2_cmmi.options["location"]
+        else:
+            loc = self.xml2_cmmi.install()
+        self.options["xml2-location"] = self.xml2_location = loc
+
+    def install(self):
+
+        # build dependent libs if requested
+        if self.build_xml2:
+            self.build_libxml2()
+        else:
+            self.logger.warn("Using configured libxml2 at %s" % self.xml2_location)
+
+        if self.build_xslt:
+            self.build_libxslt()
+        else:
+            self.logger.warn("Using configured libxslt at %s" % self.xslt_location)
+
+        # get the config executables
+        self.get_configs( os.path.join(self.xml2_location, "bin"), os.path.join(self.xslt_location, "bin"))
+
+        if self.static_build:
+            self.remove_dynamic_libs(self.xslt_location)
+            self.remove_dynamic_libs(self.xml2_location)
+
+        # build LXML
+        dest = self.options.get("location")
+        if not os.path.exists(dest):
+            os.mkdir(dest)
+
+        self.options["include-dirs"] = "%s %s" % (
+                os.path.join(self.xml2_location, "include", "libxml2"),
+                os.path.join(self.xslt_location, "include"),
+                )
+        self.options["library-dirs"] = "%s %s" % (
+                os.path.join(self.xml2_location, "lib"),
+                os.path.join(self.xslt_location, "lib"),
+                )
+        self.options["rpath"] = "%s %s" % (
+                os.path.join(self.xml2_location, "lib"),
+                os.path.join(self.xslt_location, "lib"),
+                )
+        self.lxml_custom = Custom(self.buildout, self.name, self.options)
+        self.lxml_custom.environment = self.lxml_build_env()
+
+        self.logger.info("Building lxml ...")
+        self.lxml_dest = self.lxml_custom.install()
+
+        dest = [dest, ] # dont report libxml2 and libxslt to buildout -- BO removes them
+        dest.extend(self.lxml_dest)
+        return tuple(dest)
+
+    def get_ldshared(self):
+        import distutils.sysconfig
+        LDSHARED = sysconfig.get_config_vars().get("LDSHARED")
+        self.logger.debug("LDSHARED=%s" % LDSHARED)
+        if "darwin" in sys.platform:
+            self.logger.warn("OS X detected.")
+            # remove macports "-L/opt/local/lib"
+            if "-L/opt/local/lib" in LDSHARED:
+                self.logger.warn("*** Removing '-L/opt/local/lib' from 'LDSHARED'")
+                LDSHARED = LDSHARED.replace("-L/opt/local/lib", "")
+            if self.static_build:
+                self.logger.info("Static build -- adding '-Wl,-search_paths_first'")
+                LDSHARED = LDSHARED + " -Wl,-search_paths_first "
+        self.logger.debug("LDSHARED'=%s" % LDSHARED)
+        return LDSHARED
+
+    def remove_dynamic_libs(self, path):
+        self.logger.info("Removing dynamic libs form path %s ..." % path)
+        soext = "so"
+
+        if "darwin" in sys.platform:
+            soext = "dylib"
+
+        path = os.path.join(path, "lib")
+
+        for fname in os.listdir(path):
+            if fname.endswith(soext):
+                os.unlink(os.path.join(path, fname))
+                self.logger.debug("removing %s" % fname)
+
+    def get_configs(self, xml2_location=None, xslt_location=None):
+        """Get the executables for libxml2 and libxslt configuration
+
+        If not configured, then try to get them from a built location.
+        If the location is not given, then search os.environ["PATH"] and
+        warn the user about that.
+        """
+        self.xslt_config = self.options.get("xslt-config")
+        if not self.xslt_config:
+            self.xslt_config = which("xslt-config", xslt_location)
+            if not self.xslt_config:
+                raise UserError("No ``xslt-config`` binary coinfigured and none found in path.")
+            self.logger.warn("Using xslt-config found in %s." % self.xslt_config)
+
+        self.xml2_config = self.options.get("xml2-config")
+        if not self.xml2_config:
+            self.xml2_config = which("xml2-config", xml2_location)
+            if not self.xml2_config:
+                raise UserError("No ``xml2-config`` binary coinfigured and none found in path.")
+            self.logger.warn("Using xml2-config found in %s." % self.xml2_config)
+
+        self.logger.debug("xslt-config: %s" % self.xslt_config)
+        self.logger.debug("xml2-config: %s" % self.xml2_config)
+
+    update = install
+
+    def lxml_build_ext(self):
+        """
+        [lxml]
+        recipe = zc.recipe.egg:custom
+        egg = lxml
+        include-dirs = ${libxml2:location}/include/libxml2
+                       ${libxslt:location}/include
+        library-dirs = ${libxml2:location}/lib
+                       ${libxslt:location}/lib
+        rpath = ${libxml2:location}/lib
+                ${libxslt:location}/lib
+        """
+        return dict(
+                include
+            )
+
+    def lxml_build_env(self):
+        return dict(
+                XSLT_CONFIG=self.xslt_config,
+                XML_CONFIG=self.xml2_config,
+                LDSHARED=self.get_ldshared())
+
+# vim: set ft=python ts=4 sw=4 expandtab : 

Added: z3c.recipe.staticlxml/trunk/src/z3c/recipe/staticlxml/tests/__init__.py
===================================================================
--- z3c.recipe.staticlxml/trunk/src/z3c/recipe/staticlxml/tests/__init__.py	                        (rev 0)
+++ z3c.recipe.staticlxml/trunk/src/z3c/recipe/staticlxml/tests/__init__.py	2008-11-27 14:22:15 UTC (rev 93395)
@@ -0,0 +1 @@
+# package

Added: z3c.recipe.staticlxml/trunk/src/z3c/recipe/staticlxml/tests/test_docs.py
===================================================================
--- z3c.recipe.staticlxml/trunk/src/z3c/recipe/staticlxml/tests/test_docs.py	                        (rev 0)
+++ z3c.recipe.staticlxml/trunk/src/z3c/recipe/staticlxml/tests/test_docs.py	2008-11-27 14:22:15 UTC (rev 93395)
@@ -0,0 +1,52 @@
+# -*- coding: utf-8 -*-
+"""
+Doctest runner for 'z3c.recipe.staticlxml'.
+"""
+__docformat__ = 'restructuredtext'
+
+import os
+import unittest
+import zc.buildout.tests
+import zc.buildout.testing
+
+from zope.testing import doctest, renormalizing
+
+optionflags =  (doctest.ELLIPSIS |
+                doctest.NORMALIZE_WHITESPACE |
+                doctest.REPORT_ONLY_FIRST_FAILURE)
+
+test_dir = os.path.dirname(os.path.abspath(__file__))
+
+def setUp(test):
+    zc.buildout.testing.buildoutSetUp(test)
+
+    # Install the recipe in develop mode
+    zc.buildout.testing.install_develop('z3c.recipe.staticlxml', test)
+
+    # Install any other recipes that should be available in the tests
+    zc.buildout.testing.install('zc.recipe.egg', test)
+    zc.buildout.testing.install('zc.recipe.cmmi', test)
+
+def test_suite():
+    suite = unittest.TestSuite((
+            doctest.DocFileSuite(
+                '../README.txt',
+                setUp=setUp,
+                tearDown=zc.buildout.testing.buildoutTearDown,
+                optionflags=optionflags,
+                globs=dict(test_dir=test_dir),
+                checker=renormalizing.RENormalizing([
+                        # If want to clean up the doctest output you
+                        # can register additional regexp normalizers
+                        # here. The format is a two-tuple with the RE
+                        # as the first item and the replacement as the
+                        # second item, e.g.
+                        # (re.compile('my-[rR]eg[eE]ps'), 'my-regexps')
+                        zc.buildout.testing.normalize_path,
+                        ]),
+                ),
+            ))
+    return suite
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')



More information about the Checkins mailing list