[Zodb-checkins] CVS: ZEO - setup.py:1.1.2.1 test.py:1.1.2.1

Jeremy Hylton jeremy@zope.com
Mon, 20 May 2002 15:38:11 -0400


Update of /cvs-repository/ZEO
In directory cvs.zope.org:/tmp/cvs-serv32055

Added Files:
      Tag: ZEO2-branch
	setup.py test.py 
Log Message:
Add a setup.py and test.py based on StandaloneZODB.


=== Added File ZEO/setup.py ===
from distutils.core import setup

packages = ['ZEO', 'ZEO.zrpc', 'ZEO.tests']

setup(name="ZEO",
      version="2.0a1",
      description="Zope Enterprise Objects",
      maintainer="Zope Corp.",
      maintainer_email="zodb-dev@zope.org",
      url = "http://www.zope.org/Products/ZEO",

      packages = packages,
      )


=== Added File ZEO/test.py ===
"""Test harness for StandaloneZODB"""

import os
import re
import sys
import traceback
import unittest

from distutils.util import get_platform

class ImmediateTestResult(unittest._TextTestResult):

    def _print_traceback(self, msg, err, test, errlist):
        if self.showAll or self.dots:
            self.stream.writeln("\n")

        tb = ''.join(traceback.format_exception(*err))
        self.stream.writeln(msg)
        self.stream.writeln(tb)
        errlist.append((test, tb))

    def addError(self, test, err):
        self._print_traceback("Error in test %s" % test, err,
                              test, self.errors)

    def addFailure(self, test, err):
        self._print_traceback("Failure in test %s" % test, err,
                              test, self.failures)

    def printErrorList(self, flavor, errors):
        for test, err in errors:
            self.stream.writeln(self.separator1)
            self.stream.writeln("%s: %s" % (flavor, self.getDescription(test)))
            self.stream.writeln(self.separator2)
            self.stream.writeln(err)
        

class ImmediateTestRunner(unittest.TextTestRunner):

    def _makeResult(self):
        return ImmediateTestResult(self.stream, self.descriptions,
                                   self.verbosity)

# setup list of directories to put on the path

PLAT_SPEC = "%s-%s" % (get_platform(), sys.version[0:3])

def setup_path():
    DIRS = ["lib",
            "lib.%s" % PLAT_SPEC,
            ]
    for d in DIRS:
        sys.path.insert(0, d)


# Find test files.
# They live under either a lib.PLAT_SPEC or plain "lib" directory.
_sep = re.escape(os.sep)
_pat = "%s(%s|lib)%s" % (_sep, re.escape("lib." + PLAT_SPEC), _sep)
hasgooddir = re.compile(_pat).search
del _sep, _pat

class TestFileFinder:
    def __init__(self):
        self.files = []

    def visit(self, rx, dir, files):
        if dir[-5:] != "tests":
            return
        # ignore tests that aren't in packages
        if not "__init__.py" in files:
            print "not a package", dir
            return
        for file in files:
            if file[:4] == "test" and file[-3:] == ".py":
                path = os.path.join(dir, file)
                if not hasgooddir(path):
                    # built for a different version
                    continue
                if rx is not None:
                    if rx.search(path):
                        self.files.append(path)
                else:
                    self.files.append(path)

def find_tests(filter):
    if filter is not None:
        rx = re.compile(filter)
    else:
        rx = None
    finder = TestFileFinder()
    os.path.walk("build", finder.visit, rx)
    return finder.files

def package_import(modname):
    mod = __import__(modname)
    for part in modname.split(".")[1:]:
        mod = getattr(mod, part)
    return mod

def module_from_path(path):
    """Return the Python package name indiciated by the filesystem path.

    The path starts with build/lib or build /lib.mumble..."""

    assert path[-3:] == '.py'
    path = path[:-3]
    dirs = []
    while path:
        path, end = os.path.split(path)
        dirs.insert(0, end)
    assert dirs[0] == "build"
    assert dirs[1][:3] == "lib"
    return ".".join(dirs[2:])

def get_suite(file):
    assert file[:5] == "build"
    assert file[-3:] == '.py'
    modname = module_from_path(file)
    mod = package_import(modname)
    try:
        return mod.test_suite()
    except AttributeError:
        return None

def match(rx, s):
    if not rx:
        return 1
    if rx[0] == '!':
        return re.search(rx[1:], s) is None
    else:
        return re.search(rx, s) is not None

def filter_testcases(s, rx):
    new = unittest.TestSuite()
    for test in s._tests:
        if isinstance(test, unittest.TestCase):
            name = test.id() # Full test name: package.module.class.method
            name = name[1 + name.rfind('.'):] # extract method name
            if match(rx, name):
                new.addTest(test)
        else:
            filtered = filter_testcases(test, rx)
            if filtered:
                new.addTest(filtered)
    return new

def runner(files, test_filter, debug):
    runner = ImmediateTestRunner(verbosity=VERBOSE)
    suite = unittest.TestSuite()
    for file in files:
        s = get_suite(file)
        if s is not None:
            if test_filter is not None:
                s = filter_testcases(s, test_filter)
            suite.addTest(s)
    if debug:
        suite.debug()
        return 0
    r = runner.run(suite)
    return len(r.errors) + len(r.failures)

def main(module_filter, test_filter):
    setup_path()
    files = find_tests(module_filter)
    files.sort()

    os.chdir("build") 

    if LOOP:
        while 1:
            runner(files, test_filter, debug)
    else:
        runner(files, test_filter, debug)

if __name__ == "__main__":
    import getopt

    module_filter = None
    test_filter = None
    VERBOSE = 0
    LOOP = 0
    debug = 0 # Don't collect test results; simply let tests crash
    build = 0

    try:
        opts, args = getopt.getopt(sys.argv[1:], 'vdLbh')
    except getopt.error, msg:
        print msg
        print "Try `python %s -h' for more information." % sys.argv[0]
        sys.exit(2)

    for k, v in opts:
        if k == '-v':
            VERBOSE = VERBOSE + 1
        elif k == '-d':
            debug = 1
        elif k == '-L':
            LOOP = 1
        elif k == '-b':
            build = 1
        elif k == '-h':
            print __doc__
            sys.exit(0)

    if build:
        cmd = sys.executable + " setup.py -q build"
        if VERBOSE:
            print cmd
        sts = os.system(cmd)
        if sts:
            print "Build failed", hex(sts)
            sys.exit(1)

    if args:
        if len(args) > 1:
            test_filter = args[1]
        module_filter = args[0]
    try:
        bad = main(module_filter, test_filter)
        if bad:
            sys.exit(1)
    except ImportError, err:
        print err
        print sys.path
        raise