[Zope3-checkins] CVS: Zope3 - test.py:1.26

Barry Warsaw barry@wooz.org
Thu, 19 Dec 2002 17:23:26 -0500


Update of /cvs-repository/Zope3
In directory cvs.zope.org:/tmp/cvs-serv10538

Modified Files:
	test.py 
Log Message:
Working code to run the tests from the build directory, and from the
source directory, depending on whether the -b or -B option was given.
If neither was given then we guess based on the existance of
build/lib.<plat>


=== Zope3/test.py 1.25 => 1.26 ===
--- Zope3/test.py:1.25	Thu Dec 19 15:50:19 2002
+++ Zope3/test.py	Thu Dec 19 17:23:26 2002
@@ -122,11 +122,11 @@
 import unittest
 import linecache
 import traceback
-from os.path import join, commonprefix
 
 from distutils.util import get_platform
 
 PROGRAM = sys.argv[0]
+PLAT_SPEC = "%s-%s" % (get_platform(), sys.version[0:3])
 
 # For Python's earlier than 2.2.2
 try:
@@ -251,12 +251,35 @@
 
 # setup list of directories to put on the path
 
-def setup_path():
-    DIRS = [join('lib','python'),
-            ]
-    cwd = os.getcwd()
-    for d in DIRS:
-        sys.path.insert(0, join(cwd, d))
+class PathInit:
+    def __init__(self):
+        self.inplace = None
+        # Figure out if we should test in-place or test in-build.  If the -b
+        # or -B option was given, test in the place we were told to build in.
+        # Otherwise, we'll look for a build directory and if we find one,
+        # we'll test there, otherwise we'll test in-place.
+        #
+        # XXX build and build_inplace are globals created in process_args()
+        if build:
+            self.inplace = build_inplace
+        if self.inplace is None:
+            # Need to figure it out
+            if os.path.isdir(os.path.join('build', 'lib.%s' % PLAT_SPEC)):
+                self.inplace = False
+            else:
+                self.inplace = True
+        # Calculate which directories we're going to add to sys.path, and cd
+        # to the appropriate working directory
+        if self.inplace:
+            self.libdir = os.path.join('lib', 'python')
+        else:
+            self.libdir = 'lib.%s' % PLAT_SPEC
+            os.chdir('build')
+        # Hack sys.path
+        self.cwd = os.getcwd()
+        print 'Running tests from', self.cwd
+        sys.path.insert(0, os.path.join(self.cwd, self.libdir))
+
 
 def match(rx, s):
     if not rx:
@@ -266,13 +289,14 @@
     else:
         return re.search(rx, s) is not None
 
+
 class TestFileFinder:
     def __init__(self, prefix):
         self.files = []
-        self.prefix = prefix
+        self._plen = len(prefix)+1
 
     def visit(self, rx, dir, files):
-        if not dir.endswith('tests'):
+        if os.path.split(dir)[-1] != 'tests':
             return
         # ignore tests that aren't in packages
         if not "__init__.py" in files:
@@ -280,10 +304,9 @@
                 return
             print "not a package", dir
             return
-
         # ignore tests when the package can't be imported, possibly due to
         # dependency failures.
-        pkg = dir[len(self.prefix)+1:].replace(os.sep, '.')
+        pkg = dir[self._plen:].replace(os.sep, '.')
         try:
             __import__(pkg)
         # We specifically do not want to catch ImportError since that's useful
@@ -291,38 +314,38 @@
         except RuntimeError, e:
             print 'skipping', pkg, 'because:', e
             return
-
         for file in files:
-            if file[:4] == "test" and file[-3:] == ".py":
-                path = join(dir, file)
+            if file.startswith('test') and os.path.splitext(file)[-1] == '.py':
+                path = os.path.join(dir, file)
                 if match(rx, path):
                     self.files.append(path)
 
+    def module_from_path(self, path):
+        """Return the Python package name indiciated by the filesystem path."""
+        assert path.endswith('.py')
+        path = path[self._plen:-3]
+        mod = path.replace(os.sep, '.')
+        return mod
+
+
 def find_tests(rx):
-    prefix = join('lib', 'python')
+    global finder
+    # pathinit is a global created in main()
+    prefix = pathinit.libdir
     finder = TestFileFinder(prefix)
     os.path.walk(prefix, 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."""
-
-    assert path.endswith('.py')
-    path = path[:-3]
-    dirs = []
-    while path:
-        path, end = os.path.split(path)
-        dirs.insert(0, end)
-    return ".".join(dirs[2:])
 
 def get_suite(file):
-    modname = module_from_path(file)
+    modname = finder.module_from_path(file)
     try:
         mod = package_import(modname)
     except ImportError, err:
@@ -340,6 +363,7 @@
         return None
     return suite_func()
 
+
 def filter_testcases(s, rx):
     new = unittest.TestSuite()
     for test in s._tests:
@@ -354,8 +378,9 @@
                 new.addTest(filtered)
     return new
 
+
 def gui_runner(files, test_filter):
-    sys.path.insert(0, join(os.getcwd(), 'utilities'))
+    sys.path.insert(0, os.path.join(os.getcwd(), 'utilities'))
     import unittestgui
     suites = []
     for file in files:
@@ -365,6 +390,7 @@
     minimal = (GUI == 'minimal')
     unittestgui.main(suites, minimal)
 
+
 def runner(files, test_filter, debug):
     runner = ImmediateTestRunner(verbosity=VERBOSE, debug=debug,
                                  progress=progress)
@@ -384,6 +410,7 @@
         else:
             raise
 
+
 def remove_stale_bytecode(arg, dirname, names):
     names = map(os.path.normcase, names)
     for name in names:
@@ -394,9 +421,13 @@
                 print "Removing stale bytecode file", fullname
                 os.unlink(fullname)
 
+
 def main(module_filter, test_filter):
+    global pathinit
+
     os.path.walk(os.curdir, remove_stale_bytecode, None)
-    setup_path()
+    # Initialize the path and cwd
+    pathinit = PathInit()
 
     # Initialize the logging module.
     import logging.config
@@ -415,7 +446,7 @@
         while 1:
             runner(files, test_filter, debug)
     elif TRACE:
-        coverdir = os.path.join(os.getcwd(),"coverage")
+        coverdir = os.path.join(os.getcwd(), "coverage")
         import trace
         tracer = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix],
                              trace=0, count=1)
@@ -521,11 +552,11 @@
             val |= v
         gc.set_debug(v)
 
-    # XXX support not-build-in-place, when we get a setup.py
+    # Do the builds
     if build:
-        cmd = sys.executable + " stupid_build.py"
-        if VERBOSE:
-            print cmd
+        cmd = sys.executable + ' setup.py -q build'
+        if build_inplace:
+            cmd += '_ext -i'
         sts = os.system(cmd)
         if sts:
             print "Build failed", hex(sts)
@@ -571,8 +602,6 @@
         if line: file.write('    %s\n' % line.strip())
         break
 
-if __name__ == "__main__":
-    process_args()
 
 # The following method is for debugging unit tests from a Python prompt:
 def debug(args=""):
@@ -581,18 +610,19 @@
     Just run the debug function with a string containing command-line
     arguments. (The function uses a cheesy parser, aka split. ;)
 
-    For example, to debug the tests in package Zope.App.DublinCore::
+    For example, to debug the tests in package Zope.App.DublinCore:
 
       import test
       test.debug('Zope.App.DublinCore')
 
     At the first failure or error, an exception will be raised. At
-    that point, you can use pdb's post-mortem debugger::
+    that point, you can use pdb's post-mortem debugger:
 
       import pdb
       pdb.pm()
-
     """    
-    
     process_args(["", "-d"] + args.split())
     
+
+if __name__ == "__main__":
+    process_args()