[py-svn] r57773 - in py/branch/py-compat-2.5.2: . contrib contrib/py_unittest py py/apigen/tracer py/code/testing py/compat py/compat/testing py/green py/test py/test/dsession/testing py/test/report py/test/report/testing py/test/testing

hpk at codespeak.net hpk at codespeak.net
Tue Sep 2 21:40:23 CEST 2008


Author: hpk
Date: Tue Sep  2 21:40:21 2008
New Revision: 57773

Added:
   py/branch/py-compat-2.5.2/
      - copied from r57745, py/trunk/
   py/branch/py-compat-2.5.2/MANIFEST
      - copied unchanged from r57755, py/trunk/MANIFEST
   py/branch/py-compat-2.5.2/README.txt
      - copied unchanged from r57755, py/trunk/README.txt
   py/branch/py-compat-2.5.2/contrib/
      - copied from r57756, py/trunk/contrib/
   py/branch/py-compat-2.5.2/contrib/py_unittest/
      - copied from r57771, py/trunk/contrib/py_unittest/
   py/branch/py-compat-2.5.2/py/
      - copied from r57755, py/trunk/py/
   py/branch/py-compat-2.5.2/py/code/testing/test_excinfo.py
      - copied unchanged from r57757, py/trunk/py/code/testing/test_excinfo.py
   py/branch/py-compat-2.5.2/py/compat/conftest.pyc   (contents, props changed)
   py/branch/py-compat-2.5.2/py/compat/linecache.py   (contents, props changed)
   py/branch/py-compat-2.5.2/py/compat/pdb.py   (contents, props changed)
   py/branch/py-compat-2.5.2/py/test/dsession/testing/test_functional_dsession.py
      - copied unchanged from r57758, py/trunk/py/test/dsession/testing/test_functional_dsession.py
   py/branch/py-compat-2.5.2/py/test/dsession/testing/test_hostmanage.py
      - copied unchanged from r57758, py/trunk/py/test/dsession/testing/test_hostmanage.py
   py/branch/py-compat-2.5.2/py/test/dsession/testing/test_masterslave.py
      - copied unchanged from r57758, py/trunk/py/test/dsession/testing/test_masterslave.py
   py/branch/py-compat-2.5.2/py/test/pycollect.py
      - copied unchanged from r57762, py/trunk/py/test/pycollect.py
   py/branch/py-compat-2.5.2/py/test/report/base.py
      - copied unchanged from r57762, py/trunk/py/test/report/base.py
   py/branch/py-compat-2.5.2/py/test/report/terminal.py
      - copied unchanged from r57762, py/trunk/py/test/report/terminal.py
   py/branch/py-compat-2.5.2/py/test/report/testing/test_basereporter.py
      - copied unchanged from r57762, py/trunk/py/test/report/testing/test_basereporter.py
   py/branch/py-compat-2.5.2/py/test/testing/suptest.py
      - copied unchanged from r57772, py/trunk/py/test/testing/suptest.py
   py/branch/py-compat-2.5.2/py/test/testing/test_collect.py
      - copied unchanged from r57762, py/trunk/py/test/testing/test_collect.py
   py/branch/py-compat-2.5.2/py/test/testing/test_config.py
      - copied unchanged from r57762, py/trunk/py/test/testing/test_config.py
   py/branch/py-compat-2.5.2/py/test/testing/test_event.py
      - copied unchanged from r57762, py/trunk/py/test/testing/test_event.py
   py/branch/py-compat-2.5.2/py/test/testing/test_session.py
      - copied unchanged from r57762, py/trunk/py/test/testing/test_session.py
   py/branch/py-compat-2.5.2/setup.py
      - copied unchanged from r57755, py/trunk/setup.py
Removed:
   py/branch/py-compat-2.5.2/py/compat/conftest.py
   py/branch/py-compat-2.5.2/py/green/
   py/branch/py-compat-2.5.2/py/test/dsession/testing/basetest.py
   py/branch/py-compat-2.5.2/py/test/testing/setupdata.py
   py/branch/py-compat-2.5.2/py/test/testing/test_repevent.py
Modified:
   py/branch/py-compat-2.5.2/py/__init__.py
   py/branch/py-compat-2.5.2/py/apigen/tracer/description.py
   py/branch/py-compat-2.5.2/py/compat/doctest.py
   py/branch/py-compat-2.5.2/py/compat/optparse.py
   py/branch/py-compat-2.5.2/py/compat/subprocess.py
   py/branch/py-compat-2.5.2/py/compat/testing/test_doctest.py
   py/branch/py-compat-2.5.2/py/compat/testing/test_doctest2.py
   py/branch/py-compat-2.5.2/py/compat/testing/test_optparse.py
   py/branch/py-compat-2.5.2/py/compat/testing/test_textwrap.py
   py/branch/py-compat-2.5.2/py/compat/textwrap.py
Log:
branch to use 2.5.2 compat modules, 
needs more work and fails on py/doc/apigen.txt text
which probably is an apigen bug. 


Modified: py/branch/py-compat-2.5.2/py/__init__.py
==============================================================================
--- py/trunk/py/__init__.py	(original)
+++ py/branch/py-compat-2.5.2/py/__init__.py	Tue Sep  2 21:40:21 2008
@@ -176,11 +176,12 @@
     'log.Syslog'             : ('./log/consumer.py', 'Syslog'),
     'log.get'                : ('./log/logger.py', 'get'), 
 
-    # compatibility modules (taken from 2.4.4) 
+    # compatibility modules (taken from 2.5.2) 
     'compat.__doc__'         : ('./compat/__init__.py', '__doc__'),
     'compat.doctest'         : ('./compat/doctest.py', '*'),
     'compat.optparse'        : ('./compat/optparse.py', '*'),
     'compat.textwrap'        : ('./compat/textwrap.py', '*'),
-    'compat.subprocess'      : ('./compat/subprocess.py', '*'),
+    'compat.pdb'             : ('./compat/pdb.py', '*'),
+    #'compat.subprocess'      : ('./compat/subprocess.py', '*'),
 })
 

Modified: py/branch/py-compat-2.5.2/py/apigen/tracer/description.py
==============================================================================
--- py/trunk/py/apigen/tracer/description.py	(original)
+++ py/branch/py-compat-2.5.2/py/apigen/tracer/description.py	Tue Sep  2 21:40:21 2008
@@ -78,6 +78,8 @@
     if upward_frame:
         if hasattr(upward_frame, 'raw'):
             upward_frame = upward_frame.raw
+        assert upward_frame in stack, (upward_frame, stack)
+        assert frame in stack, (frame, stack)
         lst = [py.code.Frame(i) for i in stack[stack.index(frame):\
                 stack.index(upward_frame)+1]]
         if len(lst) > 1:

Deleted: /py/trunk/py/compat/conftest.py
==============================================================================
--- /py/trunk/py/compat/conftest.py	Tue Sep  2 21:40:21 2008
+++ (empty file)
@@ -1,5 +0,0 @@
-import py
-
-class Directory(py.test.collect.Directory):
-    def collect(self):
-        py.test.skip("compat tests need to be run manually")

Added: py/branch/py-compat-2.5.2/py/compat/conftest.pyc
==============================================================================
Binary file. No diff available.

Modified: py/branch/py-compat-2.5.2/py/compat/doctest.py
==============================================================================
--- py/trunk/py/compat/doctest.py	(original)
+++ py/branch/py-compat-2.5.2/py/compat/doctest.py	Tue Sep  2 21:40:21 2008
@@ -54,6 +54,7 @@
     'DONT_ACCEPT_BLANKLINE',
     'NORMALIZE_WHITESPACE',
     'ELLIPSIS',
+    'SKIP',
     'IGNORE_EXCEPTION_DETAIL',
     'COMPARISON_FLAGS',
     'REPORT_UDIFF',
@@ -62,7 +63,6 @@
     'REPORT_ONLY_FIRST_FAILURE',
     'REPORTING_FLAGS',
     # 1. Utility Functions
-    'is_private',
     # 2. Example & DocTest
     'Example',
     'DocTest',
@@ -95,16 +95,11 @@
 
 import __future__
 
-import sys, traceback, inspect, linecache, os, re, types
+import sys, traceback, inspect, linecache, os, re
 import unittest, difflib, pdb, tempfile
 import warnings
 from StringIO import StringIO
 
-# Don't whine about the deprecated is_private function in this
-# module's tests.
-warnings.filterwarnings("ignore", "is_private", DeprecationWarning,
-                        __name__, 0)
-
 # There are 4 basic classes:
 #  - Example: a <source, want> pair, plus an intra-docstring line number.
 #  - DocTest: a collection of examples, parsed from a docstring, plus
@@ -135,12 +130,14 @@
 DONT_ACCEPT_BLANKLINE = register_optionflag('DONT_ACCEPT_BLANKLINE')
 NORMALIZE_WHITESPACE = register_optionflag('NORMALIZE_WHITESPACE')
 ELLIPSIS = register_optionflag('ELLIPSIS')
+SKIP = register_optionflag('SKIP')
 IGNORE_EXCEPTION_DETAIL = register_optionflag('IGNORE_EXCEPTION_DETAIL')
 
 COMPARISON_FLAGS = (DONT_ACCEPT_TRUE_FOR_1 |
                     DONT_ACCEPT_BLANKLINE |
                     NORMALIZE_WHITESPACE |
                     ELLIPSIS |
+                    SKIP |
                     IGNORE_EXCEPTION_DETAIL)
 
 REPORT_UDIFF = register_optionflag('REPORT_UDIFF')
@@ -175,35 +172,6 @@
 ## 1. Utility Functions
 ######################################################################
 
-def is_private(prefix, base):
-    """prefix, base -> true iff name prefix + "." + base is "private".
-
-    Prefix may be an empty string, and base does not contain a period.
-    Prefix is ignored (although functions you write conforming to this
-    protocol may make use of it).
-    Return true iff base begins with an (at least one) underscore, but
-    does not both begin and end with (at least) two underscores.
-
-    >>> is_private("a.b", "my_func")
-    False
-    >>> is_private("____", "_my_func")
-    True
-    >>> is_private("someclass", "__init__")
-    False
-    >>> is_private("sometypo", "__init_")
-    True
-    >>> is_private("x.y.z", "_")
-    True
-    >>> is_private("_x.y.z", "__")
-    False
-    >>> is_private("", "")  # senseless but consistent
-    False
-    """
-    warnings.warn("is_private is deprecated; it wasn't useful; "
-                  "examine DocTestFinder.find() lists instead",
-                  DeprecationWarning, stacklevel=2)
-    return base[:1] == "_" and not base[:2] == "__" == base[-2:]
-
 def _extract_future_flags(globs):
     """
     Return the compiler-flags associated with the future features that
@@ -235,6 +203,18 @@
     else:
         raise TypeError("Expected a module, string, or None")
 
+def _load_testfile(filename, package, module_relative):
+    if module_relative:
+        package = _normalize_module(package, 3)
+        filename = _module_relative_path(package, filename)
+        if hasattr(package, '__loader__'):
+            if hasattr(package.__loader__, 'get_data'):
+                file_contents = package.__loader__.get_data(filename)
+                # get_data() opens files as 'rb', so one must do the equivalent
+                # conversion as universal newlines would do.
+                return file_contents.replace(os.linesep, '\n'), filename
+    return open(filename).read(), filename
+
 def _indent(s, indent=4):
     """
     Add the given number of space characters to the beginning every
@@ -340,7 +320,20 @@
     """
     def __init__(self, out):
         self.__out = out
-        pdb.Pdb.__init__(self)
+        self.__debugger_used = False
+        pdb.Pdb.__init__(self, stdout=out)
+
+    def set_trace(self, frame=None):
+        self.__debugger_used = True
+        if frame is None:
+            frame = sys._getframe().f_back
+        pdb.Pdb.set_trace(self, frame)
+
+    def set_continue(self):
+        # Calling set_continue unconditionally would break unit test
+        # coverage reporting, as Bdb.set_continue calls sys.settrace(None).
+        if self.__debugger_used:
+            pdb.Pdb.set_continue(self)
 
     def trace_dispatch(self, *args):
         # Redirect stdout to the given stream.
@@ -747,7 +740,7 @@
     """
 
     def __init__(self, verbose=False, parser=DocTestParser(),
-                 recurse=True, _namefilter=None, exclude_empty=True):
+                 recurse=True, exclude_empty=True):
         """
         Create a new doctest finder.
 
@@ -767,12 +760,8 @@
         self._verbose = verbose
         self._recurse = recurse
         self._exclude_empty = exclude_empty
-        # _namefilter is undocumented, and exists only for temporary backward-
-        # compatibility support of testmod's deprecated isprivate mess.
-        self._namefilter = _namefilter
 
-    def find(self, obj, name=None, module=None, globs=None,
-             extraglobs=None):
+    def find(self, obj, name=None, module=None, globs=None, extraglobs=None):
         """
         Return a list of the DocTests that are defined by the given
         object's docstring, or by any of its contained objects'
@@ -855,13 +844,6 @@
         tests.sort()
         return tests
 
-    def _filter(self, obj, prefix, base):
-        """
-        Return true if the given object should not be examined.
-        """
-        return (self._namefilter is not None and
-                self._namefilter(prefix, base))
-
     def _from_module(self, module, object):
         """
         Return true if the given object is defined in the given
@@ -903,9 +885,6 @@
         # Look for tests in a module's contained objects.
         if inspect.ismodule(obj) and self._recurse:
             for valname, val in obj.__dict__.items():
-                # Check if this contained object should be ignored.
-                if self._filter(val, name, valname):
-                    continue
                 valname = '%s.%s' % (name, valname)
                 # Recurse to functions & classes.
                 if ((inspect.isfunction(val) or inspect.isclass(val)) and
@@ -934,9 +913,6 @@
         # Look for tests in a class's contained objects.
         if inspect.isclass(obj) and self._recurse:
             for valname, val in obj.__dict__.items():
-                # Check if this contained object should be ignored.
-                if self._filter(val, name, valname):
-                    continue
                 # Special handling for staticmethod/classmethod.
                 if isinstance(val, staticmethod):
                     val = getattr(obj, valname)
@@ -1229,6 +1205,10 @@
                     else:
                         self.optionflags &= ~optionflag
 
+            # If 'SKIP' is set, then skip this example.
+            if self.optionflags & SKIP:
+                continue
+
             # Record that we started this example.
             tries += 1
             if not quiet:
@@ -1324,13 +1304,13 @@
     __LINECACHE_FILENAME_RE = re.compile(r'<doctest '
                                          r'(?P<name>[\w\.]+)'
                                          r'\[(?P<examplenum>\d+)\]>$')
-    def __patched_linecache_getlines(self, filename, additional_arg=None):
+    def __patched_linecache_getlines(self, filename, module_globals=None):
         m = self.__LINECACHE_FILENAME_RE.match(filename)
         if m and m.group('name') == self.test.name:
             example = self.test.examples[int(m.group('examplenum'))]
             return example.source.splitlines(True)
         else:
-            return self.save_linecache_getlines(filename)
+            return self.save_linecache_getlines(filename, module_globals)
 
     def run(self, test, compileflags=None, out=None, clear_globs=True):
         """
@@ -1597,7 +1577,7 @@
 
     - test: the DocTest object being run
 
-    - excample: the Example object that failed
+    - example: the Example object that failed
 
     - got: the actual output
     """
@@ -1616,7 +1596,7 @@
 
     - test: the DocTest object being run
 
-    - excample: the Example object that failed
+    - example: the Example object that failed
 
     - exc_info: the exception info
     """
@@ -1740,17 +1720,16 @@
 # class, updated by testmod.
 master = None
 
-def testmod(m=None, name=None, globs=None, verbose=None, isprivate=None,
+def testmod(m=None, name=None, globs=None, verbose=None,
             report=True, optionflags=0, extraglobs=None,
             raise_on_error=False, exclude_empty=False):
-    """m=None, name=None, globs=None, verbose=None, isprivate=None,
-       report=True, optionflags=0, extraglobs=None, raise_on_error=False,
+    """m=None, name=None, globs=None, verbose=None, report=True,
+       optionflags=0, extraglobs=None, raise_on_error=False,
        exclude_empty=False
 
     Test examples in docstrings in functions and classes reachable
     from module m (or the current module if m is not supplied), starting
-    with m.__doc__.  Unless isprivate is specified, private names
-    are not skipped.
+    with m.__doc__.
 
     Also test examples reachable from dict m.__test__ if it exists and is
     not None.  m.__test__ maps names to functions, classes and strings;
@@ -1788,6 +1767,7 @@
         DONT_ACCEPT_BLANKLINE
         NORMALIZE_WHITESPACE
         ELLIPSIS
+        SKIP
         IGNORE_EXCEPTION_DETAIL
         REPORT_UDIFF
         REPORT_CDIFF
@@ -1798,13 +1778,6 @@
     first unexpected exception or failure. This allows failures to be
     post-mortem debugged.
 
-    Deprecated in Python 2.4:
-    Optional keyword arg "isprivate" specifies a function used to
-    determine whether a name is private.  The default function is
-    treat all functions as public.  Optionally, "isprivate" can be
-    set to doctest.is_private to skip over functions marked as private
-    using the underscore naming convention; see its docs for details.
-
     Advanced tomfoolery:  testmod runs methods of a local instance of
     class doctest.Tester, then merges the results into (or creates)
     global Tester instance doctest.master.  Methods of doctest.master
@@ -1815,11 +1788,6 @@
     """
     global master
 
-    if isprivate is not None:
-        warnings.warn("the isprivate argument is deprecated; "
-                      "examine DocTestFinder.find() lists instead",
-                      DeprecationWarning)
-
     # If no module was given, then use __main__.
     if m is None:
         # DWA - m will still be None if this wasn't invoked from the command
@@ -1836,7 +1804,7 @@
         name = m.__name__
 
     # Find, parse, and run all tests in the given module.
-    finder = DocTestFinder(_namefilter=isprivate, exclude_empty=exclude_empty)
+    finder = DocTestFinder(exclude_empty=exclude_empty)
 
     if raise_on_error:
         runner = DebugRunner(verbose=verbose, optionflags=optionflags)
@@ -1858,7 +1826,8 @@
 
 def testfile(filename, module_relative=True, name=None, package=None,
              globs=None, verbose=None, report=True, optionflags=0,
-             extraglobs=None, raise_on_error=False, parser=DocTestParser()):
+             extraglobs=None, raise_on_error=False, parser=DocTestParser(),
+             encoding=None):
     """
     Test examples in the given file.  Return (#failures, #tests).
 
@@ -1910,6 +1879,7 @@
         DONT_ACCEPT_BLANKLINE
         NORMALIZE_WHITESPACE
         ELLIPSIS
+        SKIP
         IGNORE_EXCEPTION_DETAIL
         REPORT_UDIFF
         REPORT_CDIFF
@@ -1923,6 +1893,9 @@
     Optional keyword arg "parser" specifies a DocTestParser (or
     subclass) that should be used to extract tests from the files.
 
+    Optional keyword arg "encoding" specifies an encoding that should
+    be used to convert the file to unicode.
+
     Advanced tomfoolery:  testmod runs methods of a local instance of
     class doctest.Tester, then merges the results into (or creates)
     global Tester instance doctest.master.  Methods of doctest.master
@@ -1938,9 +1911,7 @@
                          "relative paths.")
 
     # Relativize the path
-    if module_relative:
-        package = _normalize_module(package)
-        filename = _module_relative_path(package, filename)
+    text, filename = _load_testfile(filename, package, module_relative)
 
     # If no name was given, then use the file's name.
     if name is None:
@@ -1959,9 +1930,11 @@
     else:
         runner = DocTestRunner(verbose=verbose, optionflags=optionflags)
 
+    if encoding is not None:
+        text = text.decode(encoding)
+
     # Read the file, convert it to a test, and run it.
-    s = open(filename).read()
-    test = parser.get_doctest(s, globs, name, filename, 0)
+    test = parser.get_doctest(text, globs, name, filename, 0)
     runner.run(test)
 
     if report:
@@ -2004,8 +1977,7 @@
 # actually used in any way.
 
 class Tester:
-    def __init__(self, mod=None, globs=None, verbose=None,
-                 isprivate=None, optionflags=0):
+    def __init__(self, mod=None, globs=None, verbose=None, optionflags=0):
 
         warnings.warn("class Tester is deprecated; "
                       "use class doctest.DocTestRunner instead",
@@ -2020,9 +1992,8 @@
         self.globs = globs
 
         self.verbose = verbose
-        self.isprivate = isprivate
         self.optionflags = optionflags
-        self.testfinder = DocTestFinder(_namefilter=isprivate)
+        self.testfinder = DocTestFinder()
         self.testrunner = DocTestRunner(verbose=verbose,
                                         optionflags=optionflags)
 
@@ -2330,22 +2301,29 @@
                 )
 
 def DocFileTest(path, module_relative=True, package=None,
-                globs=None, parser=DocTestParser(), **options):
+                globs=None, parser=DocTestParser(),
+                encoding=None, **options):
     if globs is None:
         globs = {}
+    else:
+        globs = globs.copy()
 
     if package and not module_relative:
         raise ValueError("Package may only be specified for module-"
                          "relative paths.")
 
     # Relativize the path.
-    if module_relative:
-        package = _normalize_module(package)
-        path = _module_relative_path(package, path)
+    doc, path = _load_testfile(path, package, module_relative)
+
+    if "__file__" not in globs:
+        globs["__file__"] = path
 
     # Find the file and read it.
     name = os.path.basename(path)
-    doc = open(path).read()
+
+    # If an encoding is specified, use it to convert the file to unicode
+    if encoding is not None:
+        doc = doc.decode(encoding)
 
     # Convert it to a test, and wrap it in a DocFileCase.
     test = parser.get_doctest(doc, globs, name, path, 0)
@@ -2403,6 +2381,9 @@
     parser
       A DocTestParser (or subclass) that should be used to extract
       tests from the files.
+
+    encoding
+      An encoding that will be used to convert the files to unicode.
     """
     suite = unittest.TestSuite()
 

Added: py/branch/py-compat-2.5.2/py/compat/linecache.py
==============================================================================
--- (empty file)
+++ py/branch/py-compat-2.5.2/py/compat/linecache.py	Tue Sep  2 21:40:21 2008
@@ -0,0 +1,136 @@
+"""Cache lines from files.
+
+This is intended to read lines from modules imported -- hence if a filename
+is not found, it will look down the module search path for a file by
+that name.
+"""
+
+import sys
+import os
+
+__all__ = ["getline", "clearcache", "checkcache"]
+
+def getline(filename, lineno, module_globals=None):
+    lines = getlines(filename, module_globals)
+    if 1 <= lineno <= len(lines):
+        return lines[lineno-1]
+    else:
+        return ''
+
+
+# The cache
+
+cache = {} # The cache
+
+
+def clearcache():
+    """Clear the cache entirely."""
+
+    global cache
+    cache = {}
+
+
+def getlines(filename, module_globals=None):
+    """Get the lines for a file from the cache.
+    Update the cache if it doesn't contain an entry for this file already."""
+
+    if filename in cache:
+        return cache[filename][2]
+    else:
+        return updatecache(filename, module_globals)
+
+
+def checkcache(filename=None):
+    """Discard cache entries that are out of date.
+    (This is not checked upon each call!)"""
+
+    if filename is None:
+        filenames = cache.keys()
+    else:
+        if filename in cache:
+            filenames = [filename]
+        else:
+            return
+
+    for filename in filenames:
+        size, mtime, lines, fullname = cache[filename]
+        if mtime is None:
+            continue   # no-op for files loaded via a __loader__
+        try:
+            stat = os.stat(fullname)
+        except os.error:
+            del cache[filename]
+            continue
+        if size != stat.st_size or mtime != stat.st_mtime:
+            del cache[filename]
+
+
+def updatecache(filename, module_globals=None):
+    """Update a cache entry and return its list of lines.
+    If something's wrong, print a message, discard the cache entry,
+    and return an empty list."""
+
+    if filename in cache:
+        del cache[filename]
+    if not filename or filename[0] + filename[-1] == '<>':
+        return []
+
+    fullname = filename
+    try:
+        stat = os.stat(fullname)
+    except os.error, msg:
+        basename = os.path.split(filename)[1]
+
+        # Try for a __loader__, if available
+        if module_globals and '__loader__' in module_globals:
+            name = module_globals.get('__name__')
+            loader = module_globals['__loader__']
+            get_source = getattr(loader, 'get_source', None)
+
+            if name and get_source:
+                if basename.startswith(name.split('.')[-1]+'.'):
+                    try:
+                        data = get_source(name)
+                    except (ImportError, IOError):
+                        pass
+                    else:
+                        if data is None:
+                            # No luck, the PEP302 loader cannot find the source
+                            # for this module.
+                            return []
+                        cache[filename] = (
+                            len(data), None,
+                            [line+'\n' for line in data.splitlines()], fullname
+                        )
+                        return cache[filename][2]
+
+        # Try looking through the module search path.
+
+        for dirname in sys.path:
+            # When using imputil, sys.path may contain things other than
+            # strings; ignore them when it happens.
+            try:
+                fullname = os.path.join(dirname, basename)
+            except (TypeError, AttributeError):
+                # Not sufficiently string-like to do anything useful with.
+                pass
+            else:
+                try:
+                    stat = os.stat(fullname)
+                    break
+                except os.error:
+                    pass
+        else:
+            # No luck
+##          print '*** Cannot stat', filename, ':', msg
+            return []
+    try:
+        fp = open(fullname, 'rU')
+        lines = fp.readlines()
+        fp.close()
+    except IOError, msg:
+##      print '*** Cannot open', fullname, ':', msg
+        return []
+    size, mtime = stat.st_size, stat.st_mtime
+    cache[filename] = size, mtime, lines, fullname
+    return lines

Modified: py/branch/py-compat-2.5.2/py/compat/optparse.py
==============================================================================
--- py/trunk/py/compat/optparse.py	(original)
+++ py/branch/py-compat-2.5.2/py/compat/optparse.py	Tue Sep  2 21:40:21 2008
@@ -16,7 +16,7 @@
 # Python developers: please do not make changes to this file, since
 # it is automatically generated from the Optik source code.
 
-__version__ = "1.5a2"
+__version__ = "1.5.3"
 
 __all__ = ['Option',
            'SUPPRESS_HELP',
@@ -35,8 +35,8 @@
            'BadOptionError']
 
 __copyright__ = """
-Copyright (c) 2001-2004 Gregory P. Ward.  All rights reserved.
-Copyright (c) 2002-2004 Python Software Foundation.  All rights reserved.
+Copyright (c) 2001-2006 Gregory P. Ward.  All rights reserved.
+Copyright (c) 2002-2006 Python Software Foundation.  All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
@@ -69,17 +69,24 @@
 import sys, os
 import types
 import textwrap
-from gettext import gettext as _
 
 def _repr(self):
     return "<%s at 0x%x: %s>" % (self.__class__.__name__, id(self), self)
 
 
 # This file was generated from:
-#   Id: option_parser.py 421 2004-10-26 00:45:16Z greg
-#   Id: option.py 422 2004-10-26 00:53:47Z greg
-#   Id: help.py 367 2004-07-24 23:21:21Z gward
-#   Id: errors.py 367 2004-07-24 23:21:21Z gward
+#   Id: option_parser.py 527 2006-07-23 15:21:30Z greg
+#   Id: option.py 522 2006-06-11 16:22:03Z gward
+#   Id: help.py 527 2006-07-23 15:21:30Z greg
+#   Id: errors.py 509 2006-04-20 00:58:24Z gward
+
+try:
+    from gettext import gettext
+except ImportError:
+    def gettext(message):
+        return message
+_ = gettext
+
 
 class OptParseError (Exception):
     def __init__(self, msg):
@@ -118,8 +125,25 @@
 
 class BadOptionError (OptParseError):
     """
-    Raised if an invalid or ambiguous option is seen on the command-line.
+    Raised if an invalid option is seen on the command line.
+    """
+    def __init__(self, opt_str):
+        self.opt_str = opt_str
+
+    def __str__(self):
+        return _("no such option: %s") % self.opt_str
+
+class AmbiguousOptionError (BadOptionError):
+    """
+    Raised if an ambiguous option is seen on the command line.
     """
+    def __init__(self, opt_str, possibilities):
+        BadOptionError.__init__(self, opt_str)
+        self.possibilities = possibilities
+
+    def __str__(self):
+        return (_("ambiguous option: %s (%s?)")
+                % (self.opt_str, ", ".join(self.possibilities)))
 
 
 class HelpFormatter:
@@ -221,15 +245,30 @@
     def format_heading(self, heading):
         raise NotImplementedError, "subclasses must implement"
 
-    def format_description(self, description):
-        if not description:
-            return ""
-        desc_width = self.width - self.current_indent
+    def _format_text(self, text):
+        """
+        Format a paragraph of free-form text for inclusion in the
+        help output at the current indentation level.
+        """
+        text_width = self.width - self.current_indent
         indent = " "*self.current_indent
-        return textwrap.fill(description,
-                             desc_width,
+        return textwrap.fill(text,
+                             text_width,
                              initial_indent=indent,
-                             subsequent_indent=indent) + "\n"
+                             subsequent_indent=indent)
+
+    def format_description(self, description):
+        if description:
+            return self._format_text(description) + "\n"
+        else:
+            return ""
+
+    def format_epilog(self, epilog):
+        if epilog:
+            return "\n" + self._format_text(epilog) + "\n"
+        else:
+            return ""
+
 
     def expand_default(self, option):
         if self.parser is None or not self.default_tag:
@@ -326,7 +365,7 @@
             self, indent_increment, max_help_position, width, short_first)
 
     def format_usage(self, usage):
-        return _("usage: %s\n") % usage
+        return _("Usage: %s\n") % usage
 
     def format_heading(self, heading):
         return "%*s%s:\n" % (self.current_indent, "", heading)
@@ -351,8 +390,27 @@
         return "%s\n%s\n" % (heading, "=-"[self.level] * len(heading))
 
 
-_builtin_cvt = { "int" : (int, _("integer")),
-                 "long" : (long, _("long integer")),
+def _parse_num(val, type):
+    if val[:2].lower() == "0x":         # hexadecimal
+        radix = 16
+    elif val[:2].lower() == "0b":       # binary
+        radix = 2
+        val = val[2:] or "0"            # have to remove "0b" prefix
+    elif val[:1] == "0":                # octal
+        radix = 8
+    else:                               # decimal
+        radix = 10
+
+    return type(val, radix)
+
+def _parse_int(val):
+    return _parse_num(val, int)
+
+def _parse_long(val):
+    return _parse_num(val, long)
+
+_builtin_cvt = { "int" : (_parse_int, _("integer")),
+                 "long" : (_parse_long, _("long integer")),
                  "float" : (float, _("floating-point")),
                  "complex" : (complex, _("complex")) }
 
@@ -420,6 +478,7 @@
                "store_true",
                "store_false",
                "append",
+               "append_const",
                "count",
                "callback",
                "help",
@@ -433,6 +492,7 @@
                      "store_true",
                      "store_false",
                      "append",
+                     "append_const",
                      "count")
 
     # The set of actions for which it makes sense to supply a value
@@ -446,6 +506,10 @@
     ALWAYS_TYPED_ACTIONS = ("store",
                             "append")
 
+    # The set of actions which take a 'const' attribute.
+    CONST_ACTIONS = ("store_const",
+                     "append_const")
+
     # The set of known types for option parsers.  Again, listed here for
     # constructor argument validation.
     TYPES = ("string", "int", "long", "float", "complex", "choice")
@@ -572,9 +636,17 @@
                     # No type given?  "string" is the most sensible default.
                     self.type = "string"
         else:
-            # Allow type objects as an alternative to their names.
-            if type(self.type) is type:
+            # Allow type objects or builtin type conversion functions
+            # (int, str, etc.) as an alternative to their names.  (The
+            # complicated check of __builtin__ is only necessary for
+            # Python 2.1 and earlier, and is short-circuited by the
+            # first check on modern Pythons.)
+            import __builtin__
+            if ( type(self.type) is types.TypeType or
+                 (hasattr(self.type, "__name__") and
+                  getattr(__builtin__, self.type.__name__, None) is self.type) ):
                 self.type = self.type.__name__
+
             if self.type == "str":
                 self.type = "string"
 
@@ -613,7 +685,7 @@
                 self.dest = self._short_opts[0][1]
 
     def _check_const(self):
-        if self.action != "store_const" and self.const is not None:
+        if self.action not in self.CONST_ACTIONS and self.const is not None:
             raise OptionError(
                 "'const' must not be supplied for action %r" % self.action,
                 self)
@@ -720,6 +792,8 @@
             setattr(values, dest, False)
         elif action == "append":
             values.ensure_value(dest, []).append(value)
+        elif action == "append_const":
+            values.ensure_value(dest, []).append(self.const)
         elif action == "count":
             setattr(values, dest, values.ensure_value(dest, 0) + 1)
         elif action == "callback":
@@ -748,10 +822,15 @@
     True, False
 except NameError:
     (True, False) = (1, 0)
+
 try:
     basestring
 except NameError:
-    basestring = (str, unicode)
+    def isbasestring(x):
+        return isinstance(x, (types.StringType, types.UnicodeType))
+else:
+    def isbasestring(x):
+        return isinstance(x, basestring)
 
 
 class Values:
@@ -766,16 +845,13 @@
 
     __repr__ = _repr
 
-    def __eq__(self, other):
+    def __cmp__(self, other):
         if isinstance(other, Values):
-            return self.__dict__ == other.__dict__
-        elif isinstance(other, dict):
-            return self.__dict__ == other
+            return cmp(self.__dict__, other.__dict__)
+        elif isinstance(other, types.DictType):
+            return cmp(self.__dict__, other)
         else:
-            return False
-
-    def __ne__(self, other):
-        return not (self == other)
+            return -1
 
     def _update_careful(self, dict):
         """
@@ -893,6 +969,13 @@
         return self.description
 
 
+    def destroy(self):
+        """see OptionParser.destroy()."""
+        del self._short_opt
+        del self._long_opt
+        del self.defaults
+
+
     # -- Option-adding methods -----------------------------------------
 
     def _check_conflict(self, option):
@@ -1018,6 +1101,11 @@
     def set_title(self, title):
         self.title = title
 
+    def destroy(self):
+        """see OptionParser.destroy()."""
+        OptionContainer.destroy(self)
+        del self.option_list
+
     # -- Help-formatting methods ---------------------------------------
 
     def format_help(self, formatter):
@@ -1044,6 +1132,8 @@
       prog : string
         the name of the current program (to override
         os.path.basename(sys.argv[0])).
+      epilog : string
+        paragraph of help text to print after option help
 
       option_groups : [OptionGroup]
         list of option groups in this parser (option groups are
@@ -1102,7 +1192,8 @@
                  description=None,
                  formatter=None,
                  add_help_option=True,
-                 prog=None):
+                 prog=None,
+                 epilog=None):
         OptionContainer.__init__(
             self, option_class, conflict_handler, description)
         self.set_usage(usage)
@@ -1114,6 +1205,7 @@
             formatter = IndentedHelpFormatter()
         self.formatter = formatter
         self.formatter.set_parser(self)
+        self.epilog = epilog
 
         # Populate the option list; initial sources are the
         # standard_option_list class attribute, the 'option_list'
@@ -1124,6 +1216,22 @@
 
         self._init_parsing_state()
 
+
+    def destroy(self):
+        """
+        Declare that you are done with this OptionParser.  This cleans up
+        reference cycles so the OptionParser (and all objects referenced by
+        it) can be garbage-collected promptly.  After calling destroy(), the
+        OptionParser is unusable.
+        """
+        OptionContainer.destroy(self)
+        for group in self.option_groups:
+            group.destroy()
+        del self.option_list
+        del self.option_groups
+        del self.formatter
+
+
     # -- Private methods -----------------------------------------------
     # (used by our or OptionContainer's constructor)
 
@@ -1167,7 +1275,7 @@
         elif usage is SUPPRESS_USAGE:
             self.usage = None
         # For backwards compatibility with Optik 1.3 and earlier.
-        elif usage.startswith("usage:" + " "):
+        elif usage.lower().startswith("usage: "):
             self.usage = usage[7:]
         else:
             self.usage = usage
@@ -1201,7 +1309,7 @@
         defaults = self.defaults.copy()
         for option in self._get_all_options():
             default = defaults.get(option.dest)
-            if isinstance(default, basestring):
+            if isbasestring(default):
                 opt_str = option.get_opt_string()
                 defaults[option.dest] = option.check_value(opt_str, default)
 
@@ -1276,7 +1384,7 @@
         try:
             stop = self._process_args(largs, rargs, values)
         except (BadOptionError, OptionValueError), err:
-            self.error(err.msg)
+            self.error(str(err))
 
         args = largs + rargs
         return self.check_values(values, args)
@@ -1401,7 +1509,7 @@
             i += 1                      # we have consumed a character
 
             if not option:
-                self.error(_("no such option: %s") % opt)
+                raise BadOptionError(opt)
             if option.takes_value():
                 # Any characters left in arg?  Pretend they're the
                 # next arg, and stop consuming characters of arg.
@@ -1501,7 +1609,7 @@
             formatter = self.formatter
         formatter.store_option_strings(self)
         result = []
-        result.append(formatter.format_heading(_("options")))
+        result.append(formatter.format_heading(_("Options")))
         formatter.indent()
         if self.option_list:
             result.append(OptionContainer.format_option_help(self, formatter))
@@ -1513,6 +1621,9 @@
         # Drop the last "\n", or the header if no options or option groups:
         return "".join(result[:-1])
 
+    def format_epilog(self, formatter):
+        return formatter.format_epilog(self.epilog)
+
     def format_help(self, formatter=None):
         if formatter is None:
             formatter = self.formatter
@@ -1522,8 +1633,16 @@
         if self.description:
             result.append(self.format_description(formatter) + "\n")
         result.append(self.format_option_help(formatter))
+        result.append(self.format_epilog(formatter))
         return "".join(result)
 
+    # used by test suite
+    def _get_encoding(self, file):
+        encoding = getattr(file, "encoding", None)
+        if not encoding:
+            encoding = sys.getdefaultencoding()
+        return encoding
+
     def print_help(self, file=None):
         """print_help(file : file = stdout)
 
@@ -1532,7 +1651,8 @@
         """
         if file is None:
             file = sys.stdout
-        file.write(self.format_help())
+        encoding = self._get_encoding(file)
+        file.write(self.format_help().encode(encoding, "replace"))
 
 # class OptionParser
 
@@ -1555,12 +1675,11 @@
         if len(possibilities) == 1:
             return possibilities[0]
         elif not possibilities:
-            raise BadOptionError(_("no such option: %s") % s)
+            raise BadOptionError(s)
         else:
             # More than one possible completion: ambiguous prefix.
             possibilities.sort()
-            raise BadOptionError(_("ambiguous option: %s (%s?)")
-                                 % (s, ", ".join(possibilities)))
+            raise AmbiguousOptionError(s, possibilities)
 
 
 # Some day, there might be many Option classes.  As of Optik 1.3, the

Added: py/branch/py-compat-2.5.2/py/compat/pdb.py
==============================================================================
--- (empty file)
+++ py/branch/py-compat-2.5.2/py/compat/pdb.py	Tue Sep  2 21:40:21 2008
@@ -0,0 +1,1234 @@
+#! /usr/bin/env python
+
+"""A Python debugger."""
+
+# (See pdb.doc for documentation.)
+
+import sys
+import linecache
+import cmd
+import bdb
+from repr import Repr
+import os
+import re
+import pprint
+import traceback
+# Create a custom safe Repr instance and increase its maxstring.
+# The default of 30 truncates error messages too easily.
+_repr = Repr()
+_repr.maxstring = 200
+_saferepr = _repr.repr
+
+__all__ = ["run", "pm", "Pdb", "runeval", "runctx", "runcall", "set_trace",
+           "post_mortem", "help"]
+
+def find_function(funcname, filename):
+    cre = re.compile(r'def\s+%s\s*[(]' % funcname)
+    try:
+        fp = open(filename)
+    except IOError:
+        return None
+    # consumer of this info expects the first line to be 1
+    lineno = 1
+    answer = None
+    while 1:
+        line = fp.readline()
+        if line == '':
+            break
+        if cre.match(line):
+            answer = funcname, filename, lineno
+            break
+        lineno = lineno + 1
+    fp.close()
+    return answer
+
+
+# Interaction prompt line will separate file and call info from code
+# text using value of line_prefix string.  A newline and arrow may
+# be to your liking.  You can set it once pdb is imported using the
+# command "pdb.line_prefix = '\n% '".
+# line_prefix = ': '    # Use this to get the old situation back
+line_prefix = '\n-> '   # Probably a better default
+
+class Pdb(bdb.Bdb, cmd.Cmd):
+
+    def __init__(self, completekey='tab', stdin=None, stdout=None):
+        bdb.Bdb.__init__(self)
+        cmd.Cmd.__init__(self, completekey, stdin, stdout)
+        if stdout:
+            self.use_rawinput = 0
+        self.prompt = '(Pdb) '
+        self.aliases = {}
+        self.mainpyfile = ''
+        self._wait_for_mainpyfile = 0
+        # Try to load readline if it exists
+        try:
+            import readline
+        except ImportError:
+            pass
+
+        # Read $HOME/.pdbrc and ./.pdbrc
+        self.rcLines = []
+        if 'HOME' in os.environ:
+            envHome = os.environ['HOME']
+            try:
+                rcFile = open(os.path.join(envHome, ".pdbrc"))
+            except IOError:
+                pass
+            else:
+                for line in rcFile.readlines():
+                    self.rcLines.append(line)
+                rcFile.close()
+        try:
+            rcFile = open(".pdbrc")
+        except IOError:
+            pass
+        else:
+            for line in rcFile.readlines():
+                self.rcLines.append(line)
+            rcFile.close()
+
+        self.commands = {} # associates a command list to breakpoint numbers
+        self.commands_doprompt = {} # for each bp num, tells if the prompt must be disp. after execing the cmd list
+        self.commands_silent = {} # for each bp num, tells if the stack trace must be disp. after execing the cmd list
+        self.commands_defining = False # True while in the process of defining a command list
+        self.commands_bnum = None # The breakpoint number for which we are defining a list
+
+    def reset(self):
+        bdb.Bdb.reset(self)
+        self.forget()
+
+    def forget(self):
+        self.lineno = None
+        self.stack = []
+        self.curindex = 0
+        self.curframe = None
+
+    def setup(self, f, t):
+        self.forget()
+        self.stack, self.curindex = self.get_stack(f, t)
+        self.curframe = self.stack[self.curindex][0]
+        self.execRcLines()
+
+    # Can be executed earlier than 'setup' if desired
+    def execRcLines(self):
+        if self.rcLines:
+            # Make local copy because of recursion
+            rcLines = self.rcLines
+            # executed only once
+            self.rcLines = []
+            for line in rcLines:
+                line = line[:-1]
+                if len(line) > 0 and line[0] != '#':
+                    self.onecmd(line)
+
+    # Override Bdb methods
+
+    def user_call(self, frame, argument_list):
+        """This method is called when there is the remote possibility
+        that we ever need to stop in this function."""
+        if self._wait_for_mainpyfile:
+            return
+        if self.stop_here(frame):
+            print >>self.stdout, '--Call--'
+            self.interaction(frame, None)
+
+    def user_line(self, frame):
+        """This function is called when we stop or break at this line."""
+        if self._wait_for_mainpyfile:
+            if (self.mainpyfile != self.canonic(frame.f_code.co_filename)
+                or frame.f_lineno<= 0):
+                return
+            self._wait_for_mainpyfile = 0
+        if self.bp_commands(frame):
+            self.interaction(frame, None)
+
+    def bp_commands(self,frame):
+        """ Call every command that was set for the current active breakpoint (if there is one)
+        Returns True if the normal interaction function must be called, False otherwise """
+        #self.currentbp is set in bdb.py in bdb.break_here if a breakpoint was hit
+        if getattr(self,"currentbp",False) and self.currentbp in self.commands:
+            currentbp = self.currentbp
+            self.currentbp = 0
+            lastcmd_back = self.lastcmd
+            self.setup(frame, None)
+            for line in self.commands[currentbp]:
+                self.onecmd(line)
+            self.lastcmd = lastcmd_back
+            if not self.commands_silent[currentbp]:
+                self.print_stack_entry(self.stack[self.curindex])
+            if self.commands_doprompt[currentbp]:
+                self.cmdloop()
+            self.forget()
+            return
+        return 1
+
+    def user_return(self, frame, return_value):
+        """This function is called when a return trap is set here."""
+        frame.f_locals['__return__'] = return_value
+        print >>self.stdout, '--Return--'
+        self.interaction(frame, None)
+
+    def user_exception(self, frame, (exc_type, exc_value, exc_traceback)):
+        """This function is called if an exception occurs,
+        but only if we are to stop at or just below this level."""
+        frame.f_locals['__exception__'] = exc_type, exc_value
+        if type(exc_type) == type(''):
+            exc_type_name = exc_type
+        else: exc_type_name = exc_type.__name__
+        print >>self.stdout, exc_type_name + ':', _saferepr(exc_value)
+        self.interaction(frame, exc_traceback)
+
+    # General interaction function
+
+    def interaction(self, frame, traceback):
+        self.setup(frame, traceback)
+        self.print_stack_entry(self.stack[self.curindex])
+        self.cmdloop()
+        self.forget()
+
+    def default(self, line):
+        if line[:1] == '!': line = line[1:]
+        locals = self.curframe.f_locals
+        globals = self.curframe.f_globals
+        try:
+            code = compile(line + '\n', '<stdin>', 'single')
+            exec code in globals, locals
+        except:
+            t, v = sys.exc_info()[:2]
+            if type(t) == type(''):
+                exc_type_name = t
+            else: exc_type_name = t.__name__
+            print >>self.stdout, '***', exc_type_name + ':', v
+
+    def precmd(self, line):
+        """Handle alias expansion and ';;' separator."""
+        if not line.strip():
+            return line
+        args = line.split()
+        while args[0] in self.aliases:
+            line = self.aliases[args[0]]
+            ii = 1
+            for tmpArg in args[1:]:
+                line = line.replace("%" + str(ii),
+                                      tmpArg)
+                ii = ii + 1
+            line = line.replace("%*", ' '.join(args[1:]))
+            args = line.split()
+        # split into ';;' separated commands
+        # unless it's an alias command
+        if args[0] != 'alias':
+            marker = line.find(';;')
+            if marker >= 0:
+                # queue up everything after marker
+                next = line[marker+2:].lstrip()
+                self.cmdqueue.append(next)
+                line = line[:marker].rstrip()
+        return line
+
+    def onecmd(self, line):
+        """Interpret the argument as though it had been typed in response
+        to the prompt.
+
+        Checks whether this line is typed at the normal prompt or in
+        a breakpoint command list definition.
+        """
+        if not self.commands_defining:
+            return cmd.Cmd.onecmd(self, line)
+        else:
+            return self.handle_command_def(line)
+
+    def handle_command_def(self,line):
+        """ Handles one command line during command list definition. """
+        cmd, arg, line = self.parseline(line)
+        if cmd == 'silent':
+            self.commands_silent[self.commands_bnum] = True
+            return # continue to handle other cmd def in the cmd list
+        elif cmd == 'end':
+            self.cmdqueue = []
+            return 1 # end of cmd list
+        cmdlist = self.commands[self.commands_bnum]
+        if (arg):
+            cmdlist.append(cmd+' '+arg)
+        else:
+            cmdlist.append(cmd)
+        # Determine if we must stop
+        try:
+            func = getattr(self, 'do_' + cmd)
+        except AttributeError:
+            func = self.default
+        if func.func_name in self.commands_resuming : # one of the resuming commands.
+            self.commands_doprompt[self.commands_bnum] = False
+            self.cmdqueue = []
+            return 1
+        return
+
+    # Command definitions, called by cmdloop()
+    # The argument is the remaining string on the command line
+    # Return true to exit from the command loop
+
+    do_h = cmd.Cmd.do_help
+
+    def do_commands(self, arg):
+        """Defines a list of commands associated to a breakpoint
+        Those commands will be executed whenever the breakpoint causes the program to stop execution."""
+        if not arg:
+            bnum = len(bdb.Breakpoint.bpbynumber)-1
+        else:
+            try:
+                bnum = int(arg)
+            except:
+                print >>self.stdout, "Usage : commands [bnum]\n        ...\n        end"
+                return
+        self.commands_bnum = bnum
+        self.commands[bnum] = []
+        self.commands_doprompt[bnum] = True
+        self.commands_silent[bnum] = False
+        prompt_back = self.prompt
+        self.prompt = '(com) '
+        self.commands_defining = True
+        self.cmdloop()
+        self.commands_defining = False
+        self.prompt = prompt_back
+
+    def do_break(self, arg, temporary = 0):
+        # break [ ([filename:]lineno | function) [, "condition"] ]
+        if not arg:
+            if self.breaks:  # There's at least one
+                print >>self.stdout, "Num Type         Disp Enb   Where"
+                for bp in bdb.Breakpoint.bpbynumber:
+                    if bp:
+                        bp.bpprint(self.stdout)
+            return
+        # parse arguments; comma has lowest precedence
+        # and cannot occur in filename
+        filename = None
+        lineno = None
+        cond = None
+        comma = arg.find(',')
+        if comma > 0:
+            # parse stuff after comma: "condition"
+            cond = arg[comma+1:].lstrip()
+            arg = arg[:comma].rstrip()
+        # parse stuff before comma: [filename:]lineno | function
+        colon = arg.rfind(':')
+        funcname = None
+        if colon >= 0:
+            filename = arg[:colon].rstrip()
+            f = self.lookupmodule(filename)
+            if not f:
+                print >>self.stdout, '*** ', repr(filename),
+                print >>self.stdout, 'not found from sys.path'
+                return
+            else:
+                filename = f
+            arg = arg[colon+1:].lstrip()
+            try:
+                lineno = int(arg)
+            except ValueError, msg:
+                print >>self.stdout, '*** Bad lineno:', arg
+                return
+        else:
+            # no colon; can be lineno or function
+            try:
+                lineno = int(arg)
+            except ValueError:
+                try:
+                    func = eval(arg,
+                                self.curframe.f_globals,
+                                self.curframe.f_locals)
+                except:
+                    func = arg
+                try:
+                    if hasattr(func, 'im_func'):
+                        func = func.im_func
+                    code = func.func_code
+                    #use co_name to identify the bkpt (function names
+                    #could be aliased, but co_name is invariant)
+                    funcname = code.co_name
+                    lineno = code.co_firstlineno
+                    filename = code.co_filename
+                except:
+                    # last thing to try
+                    (ok, filename, ln) = self.lineinfo(arg)
+                    if not ok:
+                        print >>self.stdout, '*** The specified object',
+                        print >>self.stdout, repr(arg),
+                        print >>self.stdout, 'is not a function'
+                        print >>self.stdout, 'or was not found along sys.path.'
+                        return
+                    funcname = ok # ok contains a function name
+                    lineno = int(ln)
+        if not filename:
+            filename = self.defaultFile()
+        # Check for reasonable breakpoint
+        line = self.checkline(filename, lineno)
+        if line:
+            # now set the break point
+            err = self.set_break(filename, line, temporary, cond, funcname)
+            if err: print >>self.stdout, '***', err
+            else:
+                bp = self.get_breaks(filename, line)[-1]
+                print >>self.stdout, "Breakpoint %d at %s:%d" % (bp.number,
+                                                                 bp.file,
+                                                                 bp.line)
+
+    # To be overridden in derived debuggers
+    def defaultFile(self):
+        """Produce a reasonable default."""
+        filename = self.curframe.f_code.co_filename
+        if filename == '<string>' and self.mainpyfile:
+            filename = self.mainpyfile
+        return filename
+
+    do_b = do_break
+
+    def do_tbreak(self, arg):
+        self.do_break(arg, 1)
+
+    def lineinfo(self, identifier):
+        failed = (None, None, None)
+        # Input is identifier, may be in single quotes
+        idstring = identifier.split("'")
+        if len(idstring) == 1:
+            # not in single quotes
+            id = idstring[0].strip()
+        elif len(idstring) == 3:
+            # quoted
+            id = idstring[1].strip()
+        else:
+            return failed
+        if id == '': return failed
+        parts = id.split('.')
+        # Protection for derived debuggers
+        if parts[0] == 'self':
+            del parts[0]
+            if len(parts) == 0:
+                return failed
+        # Best first guess at file to look at
+        fname = self.defaultFile()
+        if len(parts) == 1:
+            item = parts[0]
+        else:
+            # More than one part.
+            # First is module, second is method/class
+            f = self.lookupmodule(parts[0])
+            if f:
+                fname = f
+            item = parts[1]
+        answer = find_function(item, fname)
+        return answer or failed
+
+    def checkline(self, filename, lineno):
+        """Check whether specified line seems to be executable.
+
+        Return `lineno` if it is, 0 if not (e.g. a docstring, comment, blank
+        line or EOF). Warning: testing is not comprehensive.
+        """
+        line = linecache.getline(filename, lineno)
+        if not line:
+            print >>self.stdout, 'End of file'
+            return 0
+        line = line.strip()
+        # Don't allow setting breakpoint at a blank line
+        if (not line or (line[0] == '#') or
+             (line[:3] == '"""') or line[:3] == "'''"):
+            print >>self.stdout, '*** Blank or comment'
+            return 0
+        return lineno
+
+    def do_enable(self, arg):
+        args = arg.split()
+        for i in args:
+            try:
+                i = int(i)
+            except ValueError:
+                print >>self.stdout, 'Breakpoint index %r is not a number' % i
+                continue
+
+            if not (0 <= i < len(bdb.Breakpoint.bpbynumber)):
+                print >>self.stdout, 'No breakpoint numbered', i
+                continue
+
+            bp = bdb.Breakpoint.bpbynumber[i]
+            if bp:
+                bp.enable()
+
+    def do_disable(self, arg):
+        args = arg.split()
+        for i in args:
+            try:
+                i = int(i)
+            except ValueError:
+                print >>self.stdout, 'Breakpoint index %r is not a number' % i
+                continue
+
+            if not (0 <= i < len(bdb.Breakpoint.bpbynumber)):
+                print >>self.stdout, 'No breakpoint numbered', i
+                continue
+
+            bp = bdb.Breakpoint.bpbynumber[i]
+            if bp:
+                bp.disable()
+
+    def do_condition(self, arg):
+        # arg is breakpoint number and condition
+        args = arg.split(' ', 1)
+        try:
+            bpnum = int(args[0].strip())
+        except ValueError:
+            # something went wrong
+            print >>self.stdout, \
+                'Breakpoint index %r is not a number' % args[0]
+            return
+        try:
+            cond = args[1]
+        except:
+            cond = None
+        try:
+            bp = bdb.Breakpoint.bpbynumber[bpnum]
+        except IndexError:
+            print >>self.stdout, 'Breakpoint index %r is not valid' % args[0]
+            return
+        if bp:
+            bp.cond = cond
+            if not cond:
+                print >>self.stdout, 'Breakpoint', bpnum,
+                print >>self.stdout, 'is now unconditional.'
+
+    def do_ignore(self,arg):
+        """arg is bp number followed by ignore count."""
+        args = arg.split()
+        try:
+            bpnum = int(args[0].strip())
+        except ValueError:
+            # something went wrong
+            print >>self.stdout, \
+                'Breakpoint index %r is not a number' % args[0]
+            return
+        try:
+            count = int(args[1].strip())
+        except:
+            count = 0
+        try:
+            bp = bdb.Breakpoint.bpbynumber[bpnum]
+        except IndexError:
+            print >>self.stdout, 'Breakpoint index %r is not valid' % args[0]
+            return
+        if bp:
+            bp.ignore = count
+            if count > 0:
+                reply = 'Will ignore next '
+                if count > 1:
+                    reply = reply + '%d crossings' % count
+                else:
+                    reply = reply + '1 crossing'
+                print >>self.stdout, reply + ' of breakpoint %d.' % bpnum
+            else:
+                print >>self.stdout, 'Will stop next time breakpoint',
+                print >>self.stdout, bpnum, 'is reached.'
+
+    def do_clear(self, arg):
+        """Three possibilities, tried in this order:
+        clear -> clear all breaks, ask for confirmation
+        clear file:lineno -> clear all breaks at file:lineno
+        clear bpno bpno ... -> clear breakpoints by number"""
+        if not arg:
+            try:
+                reply = raw_input('Clear all breaks? ')
+            except EOFError:
+                reply = 'no'
+            reply = reply.strip().lower()
+            if reply in ('y', 'yes'):
+                self.clear_all_breaks()
+            return
+        if ':' in arg:
+            # Make sure it works for "clear C:\foo\bar.py:12"
+            i = arg.rfind(':')
+            filename = arg[:i]
+            arg = arg[i+1:]
+            try:
+                lineno = int(arg)
+            except ValueError:
+                err = "Invalid line number (%s)" % arg
+            else:
+                err = self.clear_break(filename, lineno)
+            if err: print >>self.stdout, '***', err
+            return
+        numberlist = arg.split()
+        for i in numberlist:
+            try:
+                i = int(i)
+            except ValueError:
+                print >>self.stdout, 'Breakpoint index %r is not a number' % i
+                continue
+
+            if not (0 <= i < len(bdb.Breakpoint.bpbynumber)):
+                print >>self.stdout, 'No breakpoint numbered', i
+                continue
+            err = self.clear_bpbynumber(i)
+            if err:
+                print >>self.stdout, '***', err
+            else:
+                print >>self.stdout, 'Deleted breakpoint', i
+    do_cl = do_clear # 'c' is already an abbreviation for 'continue'
+
+    def do_where(self, arg):
+        self.print_stack_trace()
+    do_w = do_where
+    do_bt = do_where
+
+    def do_up(self, arg):
+        if self.curindex == 0:
+            print >>self.stdout, '*** Oldest frame'
+        else:
+            self.curindex = self.curindex - 1
+            self.curframe = self.stack[self.curindex][0]
+            self.print_stack_entry(self.stack[self.curindex])
+            self.lineno = None
+    do_u = do_up
+
+    def do_down(self, arg):
+        if self.curindex + 1 == len(self.stack):
+            print >>self.stdout, '*** Newest frame'
+        else:
+            self.curindex = self.curindex + 1
+            self.curframe = self.stack[self.curindex][0]
+            self.print_stack_entry(self.stack[self.curindex])
+            self.lineno = None
+    do_d = do_down
+
+    def do_step(self, arg):
+        self.set_step()
+        return 1
+    do_s = do_step
+
+    def do_next(self, arg):
+        self.set_next(self.curframe)
+        return 1
+    do_n = do_next
+
+    def do_return(self, arg):
+        self.set_return(self.curframe)
+        return 1
+    do_r = do_return
+
+    def do_continue(self, arg):
+        self.set_continue()
+        return 1
+    do_c = do_cont = do_continue
+
+    def do_jump(self, arg):
+        if self.curindex + 1 != len(self.stack):
+            print >>self.stdout, "*** You can only jump within the bottom frame"
+            return
+        try:
+            arg = int(arg)
+        except ValueError:
+            print >>self.stdout, "*** The 'jump' command requires a line number."
+        else:
+            try:
+                # Do the jump, fix up our copy of the stack, and display the
+                # new position
+                self.curframe.f_lineno = arg
+                self.stack[self.curindex] = self.stack[self.curindex][0], arg
+                self.print_stack_entry(self.stack[self.curindex])
+            except ValueError, e:
+                print >>self.stdout, '*** Jump failed:', e
+    do_j = do_jump
+
+    def do_debug(self, arg):
+        sys.settrace(None)
+        globals = self.curframe.f_globals
+        locals = self.curframe.f_locals
+        p = Pdb(self.completekey, self.stdin, self.stdout)
+        p.prompt = "(%s) " % self.prompt.strip()
+        print >>self.stdout, "ENTERING RECURSIVE DEBUGGER"
+        sys.call_tracing(p.run, (arg, globals, locals))
+        print >>self.stdout, "LEAVING RECURSIVE DEBUGGER"
+        sys.settrace(self.trace_dispatch)
+        self.lastcmd = p.lastcmd
+
+    def do_quit(self, arg):
+        self._user_requested_quit = 1
+        self.set_quit()
+        return 1
+
+    do_q = do_quit
+    do_exit = do_quit
+
+    def do_EOF(self, arg):
+        print >>self.stdout
+        self._user_requested_quit = 1
+        self.set_quit()
+        return 1
+
+    def do_args(self, arg):
+        f = self.curframe
+        co = f.f_code
+        dict = f.f_locals
+        n = co.co_argcount
+        if co.co_flags & 4: n = n+1
+        if co.co_flags & 8: n = n+1
+        for i in range(n):
+            name = co.co_varnames[i]
+            print >>self.stdout, name, '=',
+            if name in dict: print >>self.stdout, dict[name]
+            else: print >>self.stdout, "*** undefined ***"
+    do_a = do_args
+
+    def do_retval(self, arg):
+        if '__return__' in self.curframe.f_locals:
+            print >>self.stdout, self.curframe.f_locals['__return__']
+        else:
+            print >>self.stdout, '*** Not yet returned!'
+    do_rv = do_retval
+
+    def _getval(self, arg):
+        try:
+            return eval(arg, self.curframe.f_globals,
+                        self.curframe.f_locals)
+        except:
+            t, v = sys.exc_info()[:2]
+            if isinstance(t, str):
+                exc_type_name = t
+            else: exc_type_name = t.__name__
+            print >>self.stdout, '***', exc_type_name + ':', repr(v)
+            raise
+
+    def do_p(self, arg):
+        try:
+            print >>self.stdout, repr(self._getval(arg))
+        except:
+            pass
+
+    def do_pp(self, arg):
+        try:
+            pprint.pprint(self._getval(arg), self.stdout)
+        except:
+            pass
+
+    def do_list(self, arg):
+        self.lastcmd = 'list'
+        last = None
+        if arg:
+            try:
+                x = eval(arg, {}, {})
+                if type(x) == type(()):
+                    first, last = x
+                    first = int(first)
+                    last = int(last)
+                    if last < first:
+                        # Assume it's a count
+                        last = first + last
+                else:
+                    first = max(1, int(x) - 5)
+            except:
+                print >>self.stdout, '*** Error in argument:', repr(arg)
+                return
+        elif self.lineno is None:
+            first = max(1, self.curframe.f_lineno - 5)
+        else:
+            first = self.lineno + 1
+        if last is None:
+            last = first + 10
+        filename = self.curframe.f_code.co_filename
+        breaklist = self.get_file_breaks(filename)
+        try:
+            for lineno in range(first, last+1):
+                line = linecache.getline(filename, lineno)
+                if not line:
+                    print >>self.stdout, '[EOF]'
+                    break
+                else:
+                    s = repr(lineno).rjust(3)
+                    if len(s) < 4: s = s + ' '
+                    if lineno in breaklist: s = s + 'B'
+                    else: s = s + ' '
+                    if lineno == self.curframe.f_lineno:
+                        s = s + '->'
+                    print >>self.stdout, s + '\t' + line,
+                    self.lineno = lineno
+        except KeyboardInterrupt:
+            pass
+    do_l = do_list
+
+    def do_whatis(self, arg):
+        try:
+            value = eval(arg, self.curframe.f_globals,
+                            self.curframe.f_locals)
+        except:
+            t, v = sys.exc_info()[:2]
+            if type(t) == type(''):
+                exc_type_name = t
+            else: exc_type_name = t.__name__
+            print >>self.stdout, '***', exc_type_name + ':', repr(v)
+            return
+        code = None
+        # Is it a function?
+        try: code = value.func_code
+        except: pass
+        if code:
+            print >>self.stdout, 'Function', code.co_name
+            return
+        # Is it an instance method?
+        try: code = value.im_func.func_code
+        except: pass
+        if code:
+            print >>self.stdout, 'Method', code.co_name
+            return
+        # None of the above...
+        print >>self.stdout, type(value)
+
+    def do_alias(self, arg):
+        args = arg.split()
+        if len(args) == 0:
+            keys = self.aliases.keys()
+            keys.sort()
+            for alias in keys:
+                print >>self.stdout, "%s = %s" % (alias, self.aliases[alias])
+            return
+        if args[0] in self.aliases and len(args) == 1:
+            print >>self.stdout, "%s = %s" % (args[0], self.aliases[args[0]])
+        else:
+            self.aliases[args[0]] = ' '.join(args[1:])
+
+    def do_unalias(self, arg):
+        args = arg.split()
+        if len(args) == 0: return
+        if args[0] in self.aliases:
+            del self.aliases[args[0]]
+
+    #list of all the commands making the program resume execution.
+    commands_resuming = ['do_continue', 'do_step', 'do_next', 'do_return',
+                         'do_quit', 'do_jump']
+
+    # Print a traceback starting at the top stack frame.
+    # The most recently entered frame is printed last;
+    # this is different from dbx and gdb, but consistent with
+    # the Python interpreter's stack trace.
+    # It is also consistent with the up/down commands (which are
+    # compatible with dbx and gdb: up moves towards 'main()'
+    # and down moves towards the most recent stack frame).
+
+    def print_stack_trace(self):
+        try:
+            for frame_lineno in self.stack:
+                self.print_stack_entry(frame_lineno)
+        except KeyboardInterrupt:
+            pass
+
+    def print_stack_entry(self, frame_lineno, prompt_prefix=line_prefix):
+        frame, lineno = frame_lineno
+        if frame is self.curframe:
+            print >>self.stdout, '>',
+        else:
+            print >>self.stdout, ' ',
+        print >>self.stdout, self.format_stack_entry(frame_lineno,
+                                                     prompt_prefix)
+
+
+    # Help methods (derived from pdb.doc)
+
+    def help_help(self):
+        self.help_h()
+
+    def help_h(self):
+        print >>self.stdout, """h(elp)
+Without argument, print the list of available commands.
+With a command name as argument, print help about that command
+"help pdb" pipes the full documentation file to the $PAGER
+"help exec" gives help on the ! command"""
+
+    def help_where(self):
+        self.help_w()
+
+    def help_w(self):
+        print >>self.stdout, """w(here)
+Print a stack trace, with the most recent frame at the bottom.
+An arrow indicates the "current frame", which determines the
+context of most commands.  'bt' is an alias for this command."""
+
+    help_bt = help_w
+
+    def help_down(self):
+        self.help_d()
+
+    def help_d(self):
+        print >>self.stdout, """d(own)
+Move the current frame one level down in the stack trace
+(to a newer frame)."""
+
+    def help_up(self):
+        self.help_u()
+
+    def help_u(self):
+        print >>self.stdout, """u(p)
+Move the current frame one level up in the stack trace
+(to an older frame)."""
+
+    def help_break(self):
+        self.help_b()
+
+    def help_b(self):
+        print >>self.stdout, """b(reak) ([file:]lineno | function) [, condition]
+With a line number argument, set a break there in the current
+file.  With a function name, set a break at first executable line
+of that function.  Without argument, list all breaks.  If a second
+argument is present, it is a string specifying an expression
+which must evaluate to true before the breakpoint is honored.
+
+The line number may be prefixed with a filename and a colon,
+to specify a breakpoint in another file (probably one that
+hasn't been loaded yet).  The file is searched for on sys.path;
+the .py suffix may be omitted."""
+
+    def help_clear(self):
+        self.help_cl()
+
+    def help_cl(self):
+        print >>self.stdout, "cl(ear) filename:lineno"
+        print >>self.stdout, """cl(ear) [bpnumber [bpnumber...]]
+With a space separated list of breakpoint numbers, clear
+those breakpoints.  Without argument, clear all breaks (but
+first ask confirmation).  With a filename:lineno argument,
+clear all breaks at that line in that file.
+
+Note that the argument is different from previous versions of
+the debugger (in python distributions 1.5.1 and before) where
+a linenumber was used instead of either filename:lineno or
+breakpoint numbers."""
+
+    def help_tbreak(self):
+        print >>self.stdout, """tbreak  same arguments as break, but breakpoint is
+removed when first hit."""
+
+    def help_enable(self):
+        print >>self.stdout, """enable bpnumber [bpnumber ...]
+Enables the breakpoints given as a space separated list of
+bp numbers."""
+
+    def help_disable(self):
+        print >>self.stdout, """disable bpnumber [bpnumber ...]
+Disables the breakpoints given as a space separated list of
+bp numbers."""
+
+    def help_ignore(self):
+        print >>self.stdout, """ignore bpnumber count
+Sets the ignore count for the given breakpoint number.  A breakpoint
+becomes active when the ignore count is zero.  When non-zero, the
+count is decremented each time the breakpoint is reached and the
+breakpoint is not disabled and any associated condition evaluates
+to true."""
+
+    def help_condition(self):
+        print >>self.stdout, """condition bpnumber str_condition
+str_condition is a string specifying an expression which
+must evaluate to true before the breakpoint is honored.
+If str_condition is absent, any existing condition is removed;
+i.e., the breakpoint is made unconditional."""
+
+    def help_step(self):
+        self.help_s()
+
+    def help_s(self):
+        print >>self.stdout, """s(tep)
+Execute the current line, stop at the first possible occasion
+(either in a function that is called or in the current function)."""
+
+    def help_next(self):
+        self.help_n()
+
+    def help_n(self):
+        print >>self.stdout, """n(ext)
+Continue execution until the next line in the current function
+is reached or it returns."""
+
+    def help_return(self):
+        self.help_r()
+
+    def help_r(self):
+        print >>self.stdout, """r(eturn)
+Continue execution until the current function returns."""
+
+    def help_continue(self):
+        self.help_c()
+
+    def help_cont(self):
+        self.help_c()
+
+    def help_c(self):
+        print >>self.stdout, """c(ont(inue))
+Continue execution, only stop when a breakpoint is encountered."""
+
+    def help_jump(self):
+        self.help_j()
+
+    def help_j(self):
+        print >>self.stdout, """j(ump) lineno
+Set the next line that will be executed."""
+
+    def help_debug(self):
+        print >>self.stdout, """debug code
+Enter a recursive debugger that steps through the code argument
+(which is an arbitrary expression or statement to be executed
+in the current environment)."""
+
+    def help_list(self):
+        self.help_l()
+
+    def help_l(self):
+        print >>self.stdout, """l(ist) [first [,last]]
+List source code for the current file.
+Without arguments, list 11 lines around the current line
+or continue the previous listing.
+With one argument, list 11 lines starting at that line.
+With two arguments, list the given range;
+if the second argument is less than the first, it is a count."""
+
+    def help_args(self):
+        self.help_a()
+
+    def help_a(self):
+        print >>self.stdout, """a(rgs)
+Print the arguments of the current function."""
+
+    def help_p(self):
+        print >>self.stdout, """p expression
+Print the value of the expression."""
+
+    def help_pp(self):
+        print >>self.stdout, """pp expression
+Pretty-print the value of the expression."""
+
+    def help_exec(self):
+        print >>self.stdout, """(!) statement
+Execute the (one-line) statement in the context of
+the current stack frame.
+The exclamation point can be omitted unless the first word
+of the statement resembles a debugger command.
+To assign to a global variable you must always prefix the
+command with a 'global' command, e.g.:
+(Pdb) global list_options; list_options = ['-l']
+(Pdb)"""
+
+    def help_quit(self):
+        self.help_q()
+
+    def help_q(self):
+        print >>self.stdout, """q(uit) or exit - Quit from the debugger.
+The program being executed is aborted."""
+
+    help_exit = help_q
+
+    def help_whatis(self):
+        print >>self.stdout, """whatis arg
+Prints the type of the argument."""
+
+    def help_EOF(self):
+        print >>self.stdout, """EOF
+Handles the receipt of EOF as a command."""
+
+    def help_alias(self):
+        print >>self.stdout, """alias [name [command [parameter parameter ...] ]]
+Creates an alias called 'name' the executes 'command'.  The command
+must *not* be enclosed in quotes.  Replaceable parameters are
+indicated by %1, %2, and so on, while %* is replaced by all the
+parameters.  If no command is given, the current alias for name
+is shown. If no name is given, all aliases are listed.
+
+Aliases may be nested and can contain anything that can be
+legally typed at the pdb prompt.  Note!  You *can* override
+internal pdb commands with aliases!  Those internal commands
+are then hidden until the alias is removed.  Aliasing is recursively
+applied to the first word of the command line; all other words
+in the line are left alone.
+
+Some useful aliases (especially when placed in the .pdbrc file) are:
+
+#Print instance variables (usage "pi classInst")
+alias pi for k in %1.__dict__.keys(): print "%1.",k,"=",%1.__dict__[k]
+
+#Print instance variables in self
+alias ps pi self
+"""
+
+    def help_unalias(self):
+        print >>self.stdout, """unalias name
+Deletes the specified alias."""
+
+    def help_commands(self):
+        print >>self.stdout, """commands [bpnumber]
+(com) ...
+(com) end
+(Pdb)
+
+Specify a list of commands for breakpoint number bpnumber.  The
+commands themselves appear on the following lines.  Type a line
+containing just 'end' to terminate the commands.
+
+To remove all commands from a breakpoint, type commands and
+follow it immediately with  end; that is, give no commands.
+
+With no bpnumber argument, commands refers to the last
+breakpoint set.
+
+You can use breakpoint commands to start your program up again.
+Simply use the continue command, or step, or any other
+command that resumes execution.
+
+Specifying any command resuming execution (currently continue,
+step, next, return, jump, quit and their abbreviations) terminates
+the command list (as if that command was immediately followed by end).
+This is because any time you resume execution
+(even with a simple next or step), you may encounter
+another breakpoint--which could have its own command list, leading to
+ambiguities about which list to execute.
+
+   If you use the 'silent' command in the command list, the
+usual message about stopping at a breakpoint is not printed.  This may
+be desirable for breakpoints that are to print a specific message and
+then continue.  If none of the other commands print anything, you
+see no sign that the breakpoint was reached.
+"""
+
+    def help_pdb(self):
+        help()
+
+    def lookupmodule(self, filename):
+        """Helper function for break/clear parsing -- may be overridden.
+
+        lookupmodule() translates (possibly incomplete) file or module name
+        into an absolute file name.
+        """
+        if os.path.isabs(filename) and  os.path.exists(filename):
+            return filename
+        f = os.path.join(sys.path[0], filename)
+        if  os.path.exists(f) and self.canonic(f) == self.mainpyfile:
+            return f
+        root, ext = os.path.splitext(filename)
+        if ext == '':
+            filename = filename + '.py'
+        if os.path.isabs(filename):
+            return filename
+        for dirname in sys.path:
+            while os.path.islink(dirname):
+                dirname = os.readlink(dirname)
+            fullname = os.path.join(dirname, filename)
+            if os.path.exists(fullname):
+                return fullname
+        return None
+
+    def _runscript(self, filename):
+        # Start with fresh empty copy of globals and locals and tell the script
+        # that it's being run as __main__ to avoid scripts being able to access
+        # the pdb.py namespace.
+        globals_ = {"__name__" : "__main__", "__file__" : filename}
+        locals_ = globals_
+
+        # When bdb sets tracing, a number of call and line events happens
+        # BEFORE debugger even reaches user's code (and the exact sequence of
+        # events depends on python version). So we take special measures to
+        # avoid stopping before we reach the main script (see user_line and
+        # user_call for details).
+        self._wait_for_mainpyfile = 1
+        self.mainpyfile = self.canonic(filename)
+        self._user_requested_quit = 0
+        statement = 'execfile( "%s")' % filename
+        self.run(statement, globals=globals_, locals=locals_)
+
+# Simplified interface
+
+def run(statement, globals=None, locals=None):
+    Pdb().run(statement, globals, locals)
+
+def runeval(expression, globals=None, locals=None):
+    return Pdb().runeval(expression, globals, locals)
+
+def runctx(statement, globals, locals):
+    # B/W compatibility
+    run(statement, globals, locals)
+
+def runcall(*args, **kwds):
+    return Pdb().runcall(*args, **kwds)
+
+def set_trace():
+    Pdb().set_trace(sys._getframe().f_back)
+
+# Post-Mortem interface
+
+def post_mortem(t):
+    p = Pdb()
+    p.reset()
+    while t.tb_next is not None:
+        t = t.tb_next
+    p.interaction(t.tb_frame, t)
+
+def pm():
+    post_mortem(sys.last_traceback)
+
+
+# Main program for testing
+
+TESTCMD = 'import x; x.main()'
+
+def test():
+    run(TESTCMD)
+
+# print help
+def help():
+    for dirname in sys.path:
+        fullname = os.path.join(dirname, 'pdb.doc')
+        if os.path.exists(fullname):
+            sts = os.system('${PAGER-more} '+fullname)
+            if sts: print '*** Pager exit status:', sts
+            break
+    else:
+        print 'Sorry, can\'t find the help file "pdb.doc"',
+        print 'along the Python search path'
+
+def main():
+    if not sys.argv[1:]:
+        print "usage: pdb.py scriptfile [arg] ..."
+        sys.exit(2)
+
+    mainpyfile =  sys.argv[1]     # Get script filename
+    if not os.path.exists(mainpyfile):
+        print 'Error:', mainpyfile, 'does not exist'
+        sys.exit(1)
+
+    del sys.argv[0]         # Hide "pdb.py" from argument list
+
+    # Replace pdb's dir with script's dir in front of module search path.
+    sys.path[0] = os.path.dirname(mainpyfile)
+
+    # Note on saving/restoring sys.argv: it's a good idea when sys.argv was
+    # modified by the script being debugged. It's a bad idea when it was
+    # changed by the user from the command line. The best approach would be to
+    # have a "restart" command which would allow explicit specification of
+    # command line arguments.
+    pdb = Pdb()
+    while 1:
+        try:
+            pdb._runscript(mainpyfile)
+            if pdb._user_requested_quit:
+                break
+            print "The program finished and will be restarted"
+        except SystemExit:
+            # In most cases SystemExit does not warrant a post-mortem session.
+            print "The program exited via sys.exit(). Exit status: ",
+            print sys.exc_info()[1]
+        except:
+            traceback.print_exc()
+            print "Uncaught exception. Entering post mortem debugging"
+            print "Running 'cont' or 'step' will restart the program"
+            t = sys.exc_info()[2]
+            while t.tb_next is not None:
+                t = t.tb_next
+            pdb.interaction(t.tb_frame,t)
+            print "Post mortem debugger finished. The "+mainpyfile+" will be restarted"
+
+
+# When invoked as main program, invoke the debugger on a script
+if __name__=='__main__':
+    main()

Modified: py/branch/py-compat-2.5.2/py/compat/subprocess.py
==============================================================================
--- py/trunk/py/compat/subprocess.py	(original)
+++ py/branch/py-compat-2.5.2/py/compat/subprocess.py	Tue Sep  2 21:40:21 2008
@@ -109,7 +109,7 @@
 
 This module also defines two shortcut functions:
 
-call(*args, **kwargs):
+call(*popenargs, **kwargs):
     Run command with arguments.  Wait for command to complete, then
     return the returncode attribute.
 
@@ -117,6 +117,15 @@
 
     retcode = call(["ls", "-l"])
 
+check_call(*popenargs, **kwargs):
+    Run command with arguments.  Wait for command to complete.  If the
+    exit code was zero then return, otherwise raise
+    CalledProcessError.  The CalledProcessError object will have the
+    return code in the returncode attribute.
+
+    The arguments are the same as for the Popen constructor.  Example:
+
+    check_call(["ls", "-l"])
 
 Exceptions
 ----------
@@ -132,6 +141,9 @@
 
 A ValueError will be raised if Popen is called with invalid arguments.
 
+check_call() will raise CalledProcessError, if the called process
+returns a non-zero return code.
+
 
 Security
 --------
@@ -154,7 +166,7 @@
 communicate(input=None)
     Interact with process: Send data to stdin.  Read data from stdout
     and stderr, until end-of-file is reached.  Wait for process to
-    terminate.  The optional stdin argument should be a string to be
+    terminate.  The optional input argument should be a string to be
     sent to the child process, or None, if no data should be sent to
     the child.
 
@@ -222,7 +234,7 @@
 sts = os.system("mycmd" + " myarg")
 ==>
 p = Popen("mycmd" + " myarg", shell=True)
-sts = os.waitpid(p.pid, 0)
+pid, sts = os.waitpid(p.pid, 0)
 
 Note:
 
@@ -328,7 +340,7 @@
           stdin=PIPE, stdout=PIPE, close_fds=True)
 (child_stdout, child_stdin) = (p.stdout, p.stdin)
 
-The popen2.Popen3 and popen3.Popen4 basically works as subprocess.Popen,
+The popen2.Popen3 and popen2.Popen4 basically works as subprocess.Popen,
 except that:
 
 * subprocess.Popen raises an exception if the execution fails
@@ -346,6 +358,19 @@
 import os
 import types
 import traceback
+import gc
+
+# Exception classes used by this module.
+class CalledProcessError(Exception):
+    """This exception is raised when a process run by check_call() returns
+    a non-zero exit status.  The exit status will be stored in the
+    returncode attribute."""
+    def __init__(self, returncode, cmd):
+        self.returncode = returncode
+        self.cmd = cmd
+    def __str__(self):
+        return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode)
+
 
 if mswindows:
     import threading
@@ -378,7 +403,7 @@
     import fcntl
     import pickle
 
-__all__ = ["Popen", "PIPE", "STDOUT", "call"]
+__all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", "CalledProcessError"]
 
 try:
     MAXFD = os.sysconf("SC_OPEN_MAX")
@@ -396,13 +421,19 @@
 
 def _cleanup():
     for inst in _active[:]:
-        inst.poll()
+        if inst.poll(_deadstate=sys.maxint) >= 0:
+            try:
+                _active.remove(inst)
+            except ValueError:
+                # This can happen if two threads create a new Popen instance.
+                # It's harmless that it was already removed, so ignore.
+                pass
 
 PIPE = -1
 STDOUT = -2
 
 
-def call(*args, **kwargs):
+def call(*popenargs, **kwargs):
     """Run command with arguments.  Wait for command to complete, then
     return the returncode attribute.
 
@@ -410,7 +441,26 @@
 
     retcode = call(["ls", "-l"])
     """
-    return Popen(*args, **kwargs).wait()
+    return Popen(*popenargs, **kwargs).wait()
+
+
+def check_call(*popenargs, **kwargs):
+    """Run command with arguments.  Wait for command to complete.  If
+    the exit code was zero then return, otherwise raise
+    CalledProcessError.  The CalledProcessError object will have the
+    return code in the returncode attribute.
+
+    The arguments are the same as for the Popen constructor.  Example:
+
+    check_call(["ls", "-l"])
+    """
+    retcode = call(*popenargs, **kwargs)
+    cmd = kwargs.get("args")
+    if cmd is None:
+        cmd = popenargs[0]
+    if retcode:
+        raise CalledProcessError(retcode, cmd)
+    return retcode
 
 
 def list2cmdline(seq):
@@ -450,7 +500,7 @@
         if result:
             result.append(' ')
 
-        needquote = (" " in arg) or ("\t" in arg)
+        needquote = (" " in arg) or ("\t" in arg) or arg == ""
         if needquote:
             result.append('"')
 
@@ -490,6 +540,7 @@
         """Create new Popen instance."""
         _cleanup()
 
+        self._child_created = False
         if not isinstance(bufsize, (int, long)):
             raise TypeError("bufsize must be an integer")
 
@@ -542,6 +593,22 @@
                             c2pread, c2pwrite,
                             errread, errwrite)
 
+        # On Windows, you cannot just redirect one or two handles: You
+        # either have to redirect all three or none. If the subprocess
+        # user has only redirected one or two handles, we are
+        # automatically creating PIPEs for the rest. We should close
+        # these after the process is started. See bug #1124861.
+        if mswindows:
+            if stdin is None and p2cwrite is not None:
+                os.close(p2cwrite)
+                p2cwrite = None
+            if stdout is None and c2pread is not None:
+                os.close(c2pread)
+                c2pread = None
+            if stderr is None and errread is not None:
+                os.close(errread)
+                errread = None
+
         if p2cwrite:
             self.stdin = os.fdopen(p2cwrite, 'wb', bufsize)
         if c2pread:
@@ -555,8 +622,6 @@
             else:
                 self.stderr = os.fdopen(errread, 'rb', bufsize)
 
-        _active.append(self)
-
 
     def _translate_newlines(self, data):
         data = data.replace("\r\n", "\n")
@@ -564,6 +629,45 @@
         return data
 
 
+    def __del__(self, sys=sys):
+        if not self._child_created:
+            # We didn't get to successfully create a child process.
+            return
+        # In case the child hasn't been waited on, check if it's done.
+        self.poll(_deadstate=sys.maxint)
+        if self.returncode is None and _active is not None:
+            # Child is still running, keep us alive until we can wait on it.
+            _active.append(self)
+
+
+    def communicate(self, input=None):
+        """Interact with process: Send data to stdin.  Read data from
+        stdout and stderr, until end-of-file is reached.  Wait for
+        process to terminate.  The optional input argument should be a
+        string to be sent to the child process, or None, if no data
+        should be sent to the child.
+
+        communicate() returns a tuple (stdout, stderr)."""
+
+        # Optimization: If we are only using one pipe, or no pipe at
+        # all, using select() or threads is unnecessary.
+        if [self.stdin, self.stdout, self.stderr].count(None) >= 2:
+            stdout = None
+            stderr = None
+            if self.stdin:
+                if input:
+                    self.stdin.write(input)
+                self.stdin.close()
+            elif self.stdout:
+                stdout = self.stdout.read()
+            elif self.stderr:
+                stderr = self.stderr.read()
+            self.wait()
+            return (stdout, stderr)
+
+        return self._communicate(input)
+
+
     if mswindows:
         #
         # Windows methods
@@ -572,51 +676,57 @@
             """Construct and return tupel with IO objects:
             p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite
             """
-            if stdin == None and stdout == None and stderr == None:
+            if stdin is None and stdout is None and stderr is None:
                 return (None, None, None, None, None, None)
 
             p2cread, p2cwrite = None, None
             c2pread, c2pwrite = None, None
             errread, errwrite = None, None
 
-            if stdin == None:
+            if stdin is None:
                 p2cread = GetStdHandle(STD_INPUT_HANDLE)
-            elif stdin == PIPE:
+            if p2cread is not None:
+                pass
+            elif stdin is None or stdin == PIPE:
                 p2cread, p2cwrite = CreatePipe(None, 0)
                 # Detach and turn into fd
                 p2cwrite = p2cwrite.Detach()
                 p2cwrite = msvcrt.open_osfhandle(p2cwrite, 0)
-            elif type(stdin) == types.IntType:
+            elif isinstance(stdin, int):
                 p2cread = msvcrt.get_osfhandle(stdin)
             else:
                 # Assuming file-like object
                 p2cread = msvcrt.get_osfhandle(stdin.fileno())
             p2cread = self._make_inheritable(p2cread)
 
-            if stdout == None:
+            if stdout is None:
                 c2pwrite = GetStdHandle(STD_OUTPUT_HANDLE)
-            elif stdout == PIPE:
+            if c2pwrite is not None:
+                pass
+            elif stdout is None or stdout == PIPE:
                 c2pread, c2pwrite = CreatePipe(None, 0)
                 # Detach and turn into fd
                 c2pread = c2pread.Detach()
                 c2pread = msvcrt.open_osfhandle(c2pread, 0)
-            elif type(stdout) == types.IntType:
+            elif isinstance(stdout, int):
                 c2pwrite = msvcrt.get_osfhandle(stdout)
             else:
                 # Assuming file-like object
                 c2pwrite = msvcrt.get_osfhandle(stdout.fileno())
             c2pwrite = self._make_inheritable(c2pwrite)
 
-            if stderr == None:
+            if stderr is None:
                 errwrite = GetStdHandle(STD_ERROR_HANDLE)
-            elif stderr == PIPE:
+            if errwrite is not None:
+                pass
+            elif stderr is None or stderr == PIPE:
                 errread, errwrite = CreatePipe(None, 0)
                 # Detach and turn into fd
                 errread = errread.Detach()
                 errread = msvcrt.open_osfhandle(errread, 0)
             elif stderr == STDOUT:
                 errwrite = c2pwrite
-            elif type(stderr) == types.IntType:
+            elif isinstance(stderr, int):
                 errwrite = msvcrt.get_osfhandle(stderr)
             else:
                 # Assuming file-like object
@@ -663,7 +773,7 @@
                 args = list2cmdline(args)
 
             # Process startup details
-            if startupinfo == None:
+            if startupinfo is None:
                 startupinfo = STARTUPINFO()
             if None not in (p2cread, c2pwrite, errwrite):
                 startupinfo.dwFlags |= STARTF_USESTDHANDLES
@@ -712,6 +822,7 @@
                 raise WindowsError(*e.args)
 
             # Retain the process handle, but close the thread handle
+            self._child_created = True
             self._handle = hp
             self.pid = pid
             ht.Close()
@@ -722,31 +833,29 @@
             # output pipe are maintained in this process or else the
             # pipe will not close when the child process exits and the
             # ReadFile will hang.
-            if p2cread != None:
+            if p2cread is not None:
                 p2cread.Close()
-            if c2pwrite != None:
+            if c2pwrite is not None:
                 c2pwrite.Close()
-            if errwrite != None:
+            if errwrite is not None:
                 errwrite.Close()
 
 
-        def poll(self):
+        def poll(self, _deadstate=None):
             """Check if child process has terminated.  Returns returncode
             attribute."""
-            if self.returncode == None:
+            if self.returncode is None:
                 if WaitForSingleObject(self._handle, 0) == WAIT_OBJECT_0:
                     self.returncode = GetExitCodeProcess(self._handle)
-                    _active.remove(self)
             return self.returncode
 
 
         def wait(self):
             """Wait for child process to terminate.  Returns returncode
             attribute."""
-            if self.returncode == None:
+            if self.returncode is None:
                 obj = WaitForSingleObject(self._handle, INFINITE)
                 self.returncode = GetExitCodeProcess(self._handle)
-                _active.remove(self)
             return self.returncode
 
 
@@ -754,14 +863,7 @@
             buffer.append(fh.read())
 
 
-        def communicate(self, input=None):
-            """Interact with process: Send data to stdin.  Read data from
-            stdout and stderr, until end-of-file is reached.  Wait for
-            process to terminate.  The optional input argument should be a
-            string to be sent to the child process, or None, if no data
-            should be sent to the child.
-
-            communicate() returns a tuple (stdout, stderr)."""
+        def _communicate(self, input):
             stdout = None # Return
             stderr = None # Return
 
@@ -779,7 +881,7 @@
                 stderr_thread.start()
 
             if self.stdin:
-                if input != None:
+                if input is not None:
                     self.stdin.write(input)
                 self.stdin.close()
 
@@ -789,16 +891,16 @@
                 stderr_thread.join()
 
             # All data exchanged.  Translate lists into strings.
-            if stdout != None:
+            if stdout is not None:
                 stdout = stdout[0]
-            if stderr != None:
+            if stderr is not None:
                 stderr = stderr[0]
 
             # Translate newlines, if requested.  We cannot let the file
             # object do the translation: It is based on stdio, which is
             # impossible to combine with select (unless forcing no
             # buffering).
-            if self.universal_newlines and hasattr(open, 'newlines'):
+            if self.universal_newlines and hasattr(file, 'newlines'):
                 if stdout:
                     stdout = self._translate_newlines(stdout)
                 if stderr:
@@ -819,33 +921,33 @@
             c2pread, c2pwrite = None, None
             errread, errwrite = None, None
 
-            if stdin == None:
+            if stdin is None:
                 pass
             elif stdin == PIPE:
                 p2cread, p2cwrite = os.pipe()
-            elif type(stdin) == types.IntType:
+            elif isinstance(stdin, int):
                 p2cread = stdin
             else:
                 # Assuming file-like object
                 p2cread = stdin.fileno()
 
-            if stdout == None:
+            if stdout is None:
                 pass
             elif stdout == PIPE:
                 c2pread, c2pwrite = os.pipe()
-            elif type(stdout) == types.IntType:
+            elif isinstance(stdout, int):
                 c2pwrite = stdout
             else:
                 # Assuming file-like object
                 c2pwrite = stdout.fileno()
 
-            if stderr == None:
+            if stderr is None:
                 pass
             elif stderr == PIPE:
                 errread, errwrite = os.pipe()
             elif stderr == STDOUT:
                 errwrite = c2pwrite
-            elif type(stderr) == types.IntType:
+            elif isinstance(stderr, int):
                 errwrite = stderr
             else:
                 # Assuming file-like object
@@ -886,11 +988,13 @@
 
             if isinstance(args, types.StringTypes):
                 args = [args]
+            else:
+                args = list(args)
 
             if shell:
                 args = ["/bin/sh", "-c"] + args
 
-            if executable == None:
+            if executable is None:
                 executable = args[0]
 
             # For transferring possible exec failure from child to parent
@@ -899,7 +1003,17 @@
             errpipe_read, errpipe_write = os.pipe()
             self._set_cloexec_flag(errpipe_write)
 
-            self.pid = os.fork()
+            gc_was_enabled = gc.isenabled()
+            # Disable gc to avoid bug where gc -> file_dealloc ->
+            # write to stderr -> hang.  http://bugs.python.org/issue1336
+            gc.disable()
+            try:
+                self.pid = os.fork()
+            except:
+                if gc_was_enabled:
+                    gc.enable()
+                raise
+            self._child_created = True
             if self.pid == 0:
                 # Child
                 try:
@@ -920,26 +1034,26 @@
                     if errwrite:
                         os.dup2(errwrite, 2)
 
-                    # Close pipe fds.  Make sure we doesn't close the same
-                    # fd more than once.
-                    if p2cread:
+                    # Close pipe fds.  Make sure we don't close the same
+                    # fd more than once, or standard fds.
+                    if p2cread and p2cread not in (0,):
                         os.close(p2cread)
-                    if c2pwrite and c2pwrite not in (p2cread,):
+                    if c2pwrite and c2pwrite not in (p2cread, 1):
                         os.close(c2pwrite)
-                    if errwrite and errwrite not in (p2cread, c2pwrite):
+                    if errwrite and errwrite not in (p2cread, c2pwrite, 2):
                         os.close(errwrite)
 
                     # Close all other fds, if asked for
                     if close_fds:
                         self._close_fds(but=errpipe_write)
 
-                    if cwd != None:
+                    if cwd is not None:
                         os.chdir(cwd)
 
                     if preexec_fn:
                         apply(preexec_fn)
 
-                    if env == None:
+                    if env is None:
                         os.execvp(executable, args)
                     else:
                         os.execvpe(executable, args, env)
@@ -958,6 +1072,8 @@
                 os._exit(255)
 
             # Parent
+            if gc_was_enabled:
+                gc.enable()
             os.close(errpipe_write)
             if p2cread and p2cwrite:
                 os.close(p2cread)
@@ -984,39 +1100,31 @@
                 # Should never happen
                 raise RuntimeError("Unknown child exit status!")
 
-            _active.remove(self)
-
 
-        def poll(self):
+        def poll(self, _deadstate=None):
             """Check if child process has terminated.  Returns returncode
             attribute."""
-            if self.returncode == None:
+            if self.returncode is None:
                 try:
                     pid, sts = os.waitpid(self.pid, os.WNOHANG)
                     if pid == self.pid:
                         self._handle_exitstatus(sts)
                 except os.error:
-                    pass
+                    if _deadstate is not None:
+                        self.returncode = _deadstate
             return self.returncode
 
 
         def wait(self):
             """Wait for child process to terminate.  Returns returncode
             attribute."""
-            if self.returncode == None:
+            if self.returncode is None:
                 pid, sts = os.waitpid(self.pid, 0)
                 self._handle_exitstatus(sts)
             return self.returncode
 
 
-        def communicate(self, input=None):
-            """Interact with process: Send data to stdin.  Read data from
-            stdout and stderr, until end-of-file is reached.  Wait for
-            process to terminate.  The optional input argument should be a
-            string to be sent to the child process, or None, if no data
-            should be sent to the child.
-
-            communicate() returns a tuple (stdout, stderr)."""
+        def _communicate(self, input):
             read_set = []
             write_set = []
             stdout = None # Return
@@ -1037,6 +1145,7 @@
                 read_set.append(self.stderr)
                 stderr = []
 
+            input_offset = 0
             while read_set or write_set:
                 rlist, wlist, xlist = select.select(read_set, write_set, [])
 
@@ -1044,9 +1153,9 @@
                     # When select has indicated that the file is writable,
                     # we can write up to PIPE_BUF bytes without risk
                     # blocking.  POSIX defines PIPE_BUF >= 512
-                    bytes_written = os.write(self.stdin.fileno(), input[:512])
-                    input = input[bytes_written:]
-                    if not input:
+                    bytes_written = os.write(self.stdin.fileno(), buffer(input, input_offset, 512))
+                    input_offset += bytes_written
+                    if input_offset >= len(input):
                         self.stdin.close()
                         write_set.remove(self.stdin)
 
@@ -1065,16 +1174,16 @@
                     stderr.append(data)
 
             # All data exchanged.  Translate lists into strings.
-            if stdout != None:
+            if stdout is not None:
                 stdout = ''.join(stdout)
-            if stderr != None:
+            if stderr is not None:
                 stderr = ''.join(stderr)
 
             # Translate newlines, if requested.  We cannot let the file
             # object do the translation: It is based on stdio, which is
             # impossible to combine with select (unless forcing no
             # buffering).
-            if self.universal_newlines and hasattr(open, 'newlines'):
+            if self.universal_newlines and hasattr(file, 'newlines'):
                 if stdout:
                     stdout = self._translate_newlines(stdout)
                 if stderr:

Modified: py/branch/py-compat-2.5.2/py/compat/testing/test_doctest.py
==============================================================================
--- py/trunk/py/compat/testing/test_doctest.py	(original)
+++ py/branch/py-compat-2.5.2/py/compat/testing/test_doctest.py	Tue Sep  2 21:40:21 2008
@@ -3,15 +3,9 @@
 """
 
 from test import test_support
+import doctest
 import warnings
 
-import py
-doctest = py.compat.doctest
-
-import sys
-sys.modules['doctest'] = py.compat.doctest
-
-
 ######################################################################
 ## Sample Objects (used by test cases)
 ######################################################################
@@ -514,21 +508,20 @@
     >>> tests[1].name.split('.')[-1] in ['f', 'g']
     True
 
-Filter Functions
-~~~~~~~~~~~~~~~~
-A filter function can be used to restrict which objects get examined,
-but this is temporary, undocumented internal support for testmod's
-deprecated isprivate gimmick.
-
-    >>> def namefilter(prefix, base):
-    ...     return base.startswith('a_')
-    >>> tests = doctest.DocTestFinder(_namefilter=namefilter).find(SampleClass)
+Empty Tests
+~~~~~~~~~~~
+By default, an object with no doctests doesn't create any tests:
+
+    >>> tests = doctest.DocTestFinder().find(SampleClass)
     >>> for t in tests:
     ...     print '%2s  %s' % (len(t.examples), t.name)
      3  SampleClass
      3  SampleClass.NestedClass
      1  SampleClass.NestedClass.__init__
      1  SampleClass.__init__
+     2  SampleClass.a_classmethod
+     1  SampleClass.a_property
+     1  SampleClass.a_staticmethod
      1  SampleClass.double
      1  SampleClass.get
 
@@ -537,8 +530,7 @@
 is really to support backward compatibility in what doctest.master.summarize()
 displays.
 
-    >>> tests = doctest.DocTestFinder(_namefilter=namefilter,
-    ...                                exclude_empty=False).find(SampleClass)
+    >>> tests = doctest.DocTestFinder(exclude_empty=False).find(SampleClass)
     >>> for t in tests:
     ...     print '%2s  %s' % (len(t.examples), t.name)
      3  SampleClass
@@ -547,35 +539,12 @@
      0  SampleClass.NestedClass.get
      0  SampleClass.NestedClass.square
      1  SampleClass.__init__
-     1  SampleClass.double
-     1  SampleClass.get
-
-If a given object is filtered out, then none of the objects that it
-contains will be added either:
-
-    >>> def namefilter(prefix, base):
-    ...     return base == 'NestedClass'
-    >>> tests = doctest.DocTestFinder(_namefilter=namefilter).find(SampleClass)
-    >>> tests.sort()
-    >>> for t in tests:
-    ...     print '%2s  %s' % (len(t.examples), t.name)
-     3  SampleClass
-     1  SampleClass.__init__
      2  SampleClass.a_classmethod
      1  SampleClass.a_property
      1  SampleClass.a_staticmethod
      1  SampleClass.double
      1  SampleClass.get
 
-The filter function apply to contained objects, and *not* to the
-object explicitly passed to DocTestFinder:
-
-    >>> def namefilter(prefix, base):
-    ...     return base == 'SampleClass'
-    >>> tests = doctest.DocTestFinder(_namefilter=namefilter).find(SampleClass)
-    >>> len(tests)
-    9
-
 Turning off Recursion
 ~~~~~~~~~~~~~~~~~~~~~
 DocTestFinder can be told not to look for tests in contained objects
@@ -603,7 +572,7 @@
     ...     >>> for x in range(10):
     ...     ...     print x,
     ...     0 1 2 3 4 5 6 7 8 9
-    ...     >>> x/2
+    ...     >>> x//2
     ...     6
     ...     '''
     >>> test = doctest.DocTestFinder().find(f)[0]
@@ -678,7 +647,7 @@
     ...     >>> x = 12
     ...     >>> print x
     ...     12
-    ...     >>> x/2
+    ...     >>> x//2
     ...     6
     ...     '''
     >>> test = doctest.DocTestFinder().find(f)[0]
@@ -699,7 +668,7 @@
     ...     >>> x = 12
     ...     >>> print x
     ...     14
-    ...     >>> x/2
+    ...     >>> x//2
     ...     6
     ...     '''
     >>> test = doctest.DocTestFinder().find(f)[0]
@@ -722,7 +691,7 @@
     Got:
         12
     Trying:
-        x/2
+        x//2
     Expecting:
         6
     ok
@@ -737,7 +706,7 @@
     ...     >>> x = 12
     ...     >>> print x
     ...     12
-    ...     >>> x/2
+    ...     >>> x//2
     ...     6
     ...     '''
     >>> test = doctest.DocTestFinder().find(f)[0]
@@ -753,7 +722,7 @@
         12
     ok
     Trying:
-        x/2
+        x//2
     Expecting:
         6
     ok
@@ -783,7 +752,7 @@
         12
     ok
     Trying:
-        x/2
+        x//2
     Expecting:
         6
     ok
@@ -805,7 +774,7 @@
     >>> def f(x):
     ...     '''
     ...     >>> x = 12
-    ...     >>> print x/0
+    ...     >>> print x//0
     ...     Traceback (most recent call last):
     ...     ZeroDivisionError: integer division or modulo by zero
     ...     '''
@@ -821,7 +790,7 @@
     >>> def f(x):
     ...     '''
     ...     >>> x = 12
-    ...     >>> print 'pre-exception output', x/0
+    ...     >>> print 'pre-exception output', x//0
     ...     pre-exception output
     ...     Traceback (most recent call last):
     ...     ZeroDivisionError: integer division or modulo by zero
@@ -832,7 +801,7 @@
     **********************************************************************
     File ..., line 4, in f
     Failed example:
-        print 'pre-exception output', x/0
+        print 'pre-exception output', x//0
     Exception raised:
         ...
         ZeroDivisionError: integer division or modulo by zero
@@ -919,7 +888,7 @@
 
     >>> def f(x):
     ...     r'''
-    ...     >>> 1/0
+    ...     >>> 1//0
     ...     0
     ...     '''
     >>> test = doctest.DocTestFinder().find(f)[0]
@@ -928,7 +897,7 @@
     **********************************************************************
     File ..., line 3, in f
     Failed example:
-        1/0
+        1//0
     Exception raised:
         Traceback (most recent call last):
         ...
@@ -1078,6 +1047,25 @@
     ...                 # doctest: +NORMALIZE_WHITESPACE
     [0,    1, ...,   18,    19]
 
+The SKIP flag causes an example to be skipped entirely.  I.e., the
+example is not run.  It can be useful in contexts where doctest
+examples serve as both documentation and test cases, and an example
+should be included for documentation purposes, but should not be
+checked (e.g., because its output is random, or depends on resources
+which would be unavailable.)  The SKIP flag can also be used for
+'commenting out' broken examples.
+
+    >>> import unavailable_resource           # doctest: +SKIP
+    >>> unavailable_resource.do_something()   # doctest: +SKIP
+    >>> unavailable_resource.blow_up()        # doctest: +SKIP
+    Traceback (most recent call last):
+        ...
+    UncheckedBlowUpError:  Nobody checks me.
+
+    >>> import random
+    >>> print random.random() # doctest: +SKIP
+    0.721216923889
+
 The REPORT_UDIFF flag causes failures that involve multi-line expected
 and actual outputs to be displayed using a unified diff:
 
@@ -1578,11 +1566,11 @@
 
     >>> try: doctest.debug_src(s)
     ... finally: sys.stdin = real_stdin
-    > <string>(1)?()
+    > <string>(1)<module>()
     (Pdb) next
     12
     --Return--
-    > <string>(1)?()->None
+    > <string>(1)<module>()->None
     (Pdb) print x
     12
     (Pdb) continue
@@ -1620,7 +1608,7 @@
       >>> try: runner.run(test)
       ... finally: sys.stdin = real_stdin
       --Return--
-      > <doctest foo[1]>(1)?()->None
+      > <doctest foo[1]>(1)<module>()->None
       -> import pdb; pdb.set_trace()
       (Pdb) print x
       42
@@ -1656,7 +1644,7 @@
       (Pdb) print y
       2
       (Pdb) up
-      > <doctest foo[1]>(1)?()
+      > <doctest foo[1]>(1)<module>()
       -> calls_set_trace()
       (Pdb) print x
       1
@@ -1705,7 +1693,7 @@
       [EOF]
       (Pdb) next
       --Return--
-      > <doctest foo[2]>(1)?()->None
+      > <doctest foo[2]>(1)<module>()->None
       -> f(3)
       (Pdb) list
         1  -> f(3)
@@ -1798,7 +1786,7 @@
     (Pdb) print y
     1
     (Pdb) up
-    > <doctest foo[1]>(1)?()
+    > <doctest foo[1]>(1)<module>()
     -> calls_set_trace()
     (Pdb) print foo
     *** NameError: name 'foo' is not defined
@@ -1893,20 +1881,6 @@
        modified the test globals, which are a copy of the
        sample_doctest module dictionary.  The test globals are
        automatically cleared for us after a test.
-
-       Finally, you can provide an alternate test finder.  Here we'll
-       use a custom test_finder to to run just the test named bar.
-       However, the test in the module docstring, and the two tests
-       in the module __test__ dict, aren't filtered, so we actually
-       run three tests besides bar's.  The filtering mechanisms are
-       poorly conceived, and will go away someday.
-
-         >>> finder = doctest.DocTestFinder(
-         ...    _namefilter=lambda prefix, base: base!='bar')
-         >>> suite = doctest.DocTestSuite('test.sample_doctest',
-         ...                              test_finder=finder)
-         >>> suite.run(unittest.TestResult())
-         <unittest.TestResult run=4 errors=0 failures=1>
        """
 
 def test_DocFileSuite():
@@ -1917,9 +1891,10 @@
 
          >>> import unittest
          >>> suite = doctest.DocFileSuite('test_doctest.txt',
-         ...                              'test_doctest2.txt')
+         ...                              'test_doctest2.txt',
+         ...                              'test_doctest4.txt')
          >>> suite.run(unittest.TestResult())
-         <unittest.TestResult run=2 errors=0 failures=2>
+         <unittest.TestResult run=3 errors=0 failures=3>
 
        The test files are looked for in the directory containing the
        calling module.  A package keyword argument can be provided to
@@ -1928,9 +1903,29 @@
          >>> import unittest
          >>> suite = doctest.DocFileSuite('test_doctest.txt',
          ...                              'test_doctest2.txt',
+         ...                              'test_doctest4.txt',
          ...                              package='test')
          >>> suite.run(unittest.TestResult())
-         <unittest.TestResult run=2 errors=0 failures=2>
+         <unittest.TestResult run=3 errors=0 failures=3>
+
+       Support for using a package's __loader__.get_data() is also
+       provided.
+
+         >>> import unittest, pkgutil, test
+         >>> added_loader = False
+         >>> if not hasattr(test, '__loader__'):
+         ...     test.__loader__ = pkgutil.get_loader(test)
+         ...     added_loader = True
+         >>> try:
+         ...     suite = doctest.DocFileSuite('test_doctest.txt',
+         ...                                  'test_doctest2.txt',
+         ...                                  'test_doctest4.txt',
+         ...                                  package='test')
+         ...     suite.run(unittest.TestResult())
+         ... finally:
+         ...     if added_loader:
+         ...         del test.__loader__
+         <unittest.TestResult run=3 errors=0 failures=3>
 
        '/' should be used as a path separator.  It will be converted
        to a native separator at run time:
@@ -1975,19 +1970,21 @@
 
          >>> suite = doctest.DocFileSuite('test_doctest.txt',
          ...                              'test_doctest2.txt',
+         ...                              'test_doctest4.txt',
          ...                              globs={'favorite_color': 'blue'})
          >>> suite.run(unittest.TestResult())
-         <unittest.TestResult run=2 errors=0 failures=1>
+         <unittest.TestResult run=3 errors=0 failures=2>
 
        In this case, we supplied a missing favorite color. You can
        provide doctest options:
 
          >>> suite = doctest.DocFileSuite('test_doctest.txt',
          ...                              'test_doctest2.txt',
+         ...                              'test_doctest4.txt',
          ...                         optionflags=doctest.DONT_ACCEPT_BLANKLINE,
          ...                              globs={'favorite_color': 'blue'})
          >>> suite.run(unittest.TestResult())
-         <unittest.TestResult run=2 errors=0 failures=2>
+         <unittest.TestResult run=3 errors=0 failures=3>
 
        And, you can provide setUp and tearDown functions:
 
@@ -2005,9 +2002,10 @@
 
          >>> suite = doctest.DocFileSuite('test_doctest.txt',
          ...                              'test_doctest2.txt',
+         ...                              'test_doctest4.txt',
          ...                              setUp=setUp, tearDown=tearDown)
          >>> suite.run(unittest.TestResult())
-         <unittest.TestResult run=2 errors=0 failures=1>
+         <unittest.TestResult run=3 errors=0 failures=2>
 
        But the tearDown restores sanity:
 
@@ -2032,6 +2030,25 @@
        modified the test globals.  The test globals are
        automatically cleared for us after a test.
 
+       Tests in a file run using `DocFileSuite` can also access the
+       `__file__` global, which is set to the name of the file
+       containing the tests:
+
+         >>> suite = doctest.DocFileSuite('test_doctest3.txt')
+         >>> suite.run(unittest.TestResult())
+         <unittest.TestResult run=1 errors=0 failures=0>
+
+       If the tests contain non-ASCII characters, we have to specify which
+       encoding the file is encoded with. We do so by using the `encoding`
+       parameter:
+
+         >>> suite = doctest.DocFileSuite('test_doctest.txt',
+         ...                              'test_doctest2.txt',
+         ...                              'test_doctest4.txt',
+         ...                              encoding='utf-8')
+         >>> suite.run(unittest.TestResult())
+         <unittest.TestResult run=3 errors=0 failures=2>
+
        """
 
 def test_trailing_space_in_test():
@@ -2238,6 +2255,32 @@
     Traceback (most recent call last):
     UnexpectedException: ...
     >>> doctest.master = None  # Reset master.
+
+If the tests contain non-ASCII characters, the tests might fail, since
+it's unknown which encoding is used. The encoding can be specified
+using the optional keyword argument `encoding`:
+
+    >>> doctest.testfile('test_doctest4.txt') # doctest: +ELLIPSIS
+    **********************************************************************
+    File "...", line 7, in test_doctest4.txt
+    Failed example:
+        u'...'
+    Expected:
+        u'f\xf6\xf6'
+    Got:
+        u'f\xc3\xb6\xc3\xb6'
+    **********************************************************************
+    ...
+    **********************************************************************
+    1 items had failures:
+       2 of   4 in test_doctest4.txt
+    ***Test Failed*** 2 failures.
+    (2, 4)
+    >>> doctest.master = None  # Reset master.
+
+    >>> doctest.testfile('test_doctest4.txt', encoding='utf-8')
+    (0, 4)
+    >>> doctest.master = None  # Reset master.
 """
 
 # old_test1, ... used to live in doctest.py, but cluttered it.  Note

Modified: py/branch/py-compat-2.5.2/py/compat/testing/test_doctest2.py
==============================================================================
--- py/trunk/py/compat/testing/test_doctest2.py	(original)
+++ py/branch/py-compat-2.5.2/py/compat/testing/test_doctest2.py	Tue Sep  2 21:40:21 2008
@@ -80,6 +80,7 @@
         -12
         """)
 
+    @staticmethod
     def statm():
         """
         A static method.
@@ -91,8 +92,7 @@
         """
         return 666
 
-    statm = staticmethod(statm)
-
+    @classmethod
     def clsm(cls, val):
         """
         A class method.
@@ -104,10 +104,8 @@
         """
         return val
 
-    clsm = classmethod(clsm)
-
 def test_main():
-    from py.__.compat.testing import test_doctest2
+    from test import test_doctest2
     EXPECTED = 19
     f, t = test_support.run_doctest(test_doctest2)
     if t != EXPECTED:
@@ -116,7 +114,7 @@
 
 # Pollute the namespace with a bunch of imported functions and classes,
 # to make sure they don't get tested.
-from py.compat.doctest import *
+from doctest import *
 
 if __name__ == '__main__':
     test_main()

Modified: py/branch/py-compat-2.5.2/py/compat/testing/test_optparse.py
==============================================================================
--- py/trunk/py/compat/testing/test_optparse.py	(original)
+++ py/branch/py-compat-2.5.2/py/compat/testing/test_optparse.py	Tue Sep  2 21:40:21 2008
@@ -1,31 +1,31 @@
-#!/usr/bin/env python
+#!/usr/bin/python
 
 #
 # Test suite for Optik.  Supplied by Johannes Gijsbers
 # (taradino at softhome.net) -- translated from the original Optik
 # test suite to this PyUnit-based version.
 #
-# $Id: test_optparse.py 46506 2006-05-28 18:15:43Z armin.rigo $
+# $Id: test_optparse.py 50791 2006-07-23 16:05:51Z greg.ward $
 #
 
 import sys
 import os
+import re
 import copy
+import types
 import unittest
 
-from cStringIO import StringIO
+from StringIO import StringIO
 from pprint import pprint
 from test import test_support
 
-import py
-optparse = py.compat.optparse 
-import sys
-sys.modules['optparse'] = optparse
 
 from optparse import make_option, Option, IndentedHelpFormatter, \
      TitledHelpFormatter, OptionParser, OptionContainer, OptionGroup, \
      SUPPRESS_HELP, SUPPRESS_USAGE, OptionError, OptionConflictError, \
-     BadOptionError, OptionValueError, Values, _match_abbrev
+     BadOptionError, OptionValueError, Values
+from optparse import _match_abbrev
+from optparse import _parse_num
 
 # Do the right thing with boolean values for all known Python versions.
 try:
@@ -33,6 +33,7 @@
 except NameError:
     (True, False) = (1, 0)
 
+retype = type(re.compile(''))
 
 class InterceptedError(Exception):
     def __init__(self,
@@ -101,7 +102,8 @@
           args -- positional arguments to `func`
           kwargs -- keyword arguments to `func`
           expected_exception -- exception that should be raised
-          expected_output -- output we expect to see
+          expected_message -- expected exception message (or pattern
+            if a compiled regex object)
 
         Returns the exception raised for further testing.
         """
@@ -114,14 +116,23 @@
             func(*args, **kwargs)
         except expected_exception, err:
             actual_message = str(err)
-            self.assertEqual(actual_message,
-                             expected_message,
+            if isinstance(expected_message, retype):
+                self.assert_(expected_message.search(actual_message),
                              """\
+expected exception message pattern:
+/%s/
+actual exception message:
+'''%s'''
+""" % (expected_message.pattern, actual_message))
+            else:
+                self.assertEqual(actual_message,
+                                 expected_message,
+                                 """\
 expected exception message:
-'''%(expected_message)s'''
+'''%s'''
 actual exception message:
-'''%(actual_message)s'''
-""" % locals())
+'''%s'''
+""" % (expected_message, actual_message))
 
             return err
         else:
@@ -153,16 +164,26 @@
                      expected_error=None):
         """Assert the parser prints the expected output on stdout."""
         save_stdout = sys.stdout
+        encoding = getattr(save_stdout, 'encoding', None)
         try:
             try:
                 sys.stdout = StringIO()
+                if encoding:
+                    sys.stdout.encoding = encoding
                 self.parser.parse_args(cmdline_args)
             finally:
                 output = sys.stdout.getvalue()
                 sys.stdout = save_stdout
 
         except InterceptedError, err:
-            self.assertEqual(output, expected_output)
+            self.assert_(
+                type(output) is types.StringType,
+                "expected output to be an ordinary string, not %r"
+                % type(output))
+
+            if output != expected_output:
+                self.fail("expected: \n'''\n" + expected_output +
+                          "'''\nbut got \n'''\n" + output + "'''")
             self.assertEqual(err.exit_status, expected_status)
             self.assertEqual(err.exit_message, expected_error)
         else:
@@ -371,6 +392,23 @@
         self.assertRaises(self.parser.remove_option, ('foo',), None,
                           ValueError, "no such option 'foo'")
 
+    def test_refleak(self):
+        # If an OptionParser is carrying around a reference to a large
+        # object, various cycles can prevent it from being GC'd in
+        # a timely fashion.  destroy() breaks the cycles to ensure stuff
+        # can be cleaned up.
+        big_thing = [42]
+        refcount = sys.getrefcount(big_thing)
+        parser = OptionParser()
+        parser.add_option("-a", "--aaarggh")
+        parser.big_thing = big_thing
+
+        parser.destroy()
+        #self.assertEqual(refcount, sys.getrefcount(big_thing))
+        del parser
+        self.assertEqual(refcount, sys.getrefcount(big_thing))
+
+
 class TestOptionValues(BaseTest):
     def setUp(self):
         pass
@@ -396,13 +434,21 @@
     def setUp(self):
         self.parser = OptionParser()
 
-    def test_type_aliases(self):
-        self.parser.add_option("-x", type=int)
+    def test_str_aliases_string(self):
+        self.parser.add_option("-s", type="str")
+        self.assertEquals(self.parser.get_option("-s").type, "string")
+
+    def test_new_type_object(self):
         self.parser.add_option("-s", type=str)
-        self.parser.add_option("-t", type="str")
+        self.assertEquals(self.parser.get_option("-s").type, "string")
+        self.parser.add_option("-x", type=int)
         self.assertEquals(self.parser.get_option("-x").type, "int")
+
+    def test_old_type_object(self):
+        self.parser.add_option("-s", type=types.StringType)
         self.assertEquals(self.parser.get_option("-s").type, "string")
-        self.assertEquals(self.parser.get_option("-t").type, "string")
+        self.parser.add_option("-x", type=types.IntType)
+        self.assertEquals(self.parser.get_option("-x").type, "int")
 
 
 # Custom type for testing processing of default values.
@@ -492,13 +538,13 @@
         save_argv = sys.argv[:]
         try:
             sys.argv[0] = os.path.join("foo", "bar", "baz.py")
-            parser = OptionParser("usage: %prog ...", version="%prog 1.2")
-            expected_usage = "usage: baz.py ...\n"
+            parser = OptionParser("%prog ...", version="%prog 1.2")
+            expected_usage = "Usage: baz.py ...\n"
             self.assertUsage(parser, expected_usage)
             self.assertVersion(parser, "baz.py 1.2")
             self.assertHelp(parser,
                             expected_usage + "\n" +
-                            "options:\n"
+                            "Options:\n"
                             "  --version   show program's version number and exit\n"
                             "  -h, --help  show this help message and exit\n")
         finally:
@@ -510,7 +556,7 @@
                               usage="%prog arg arg")
         parser.remove_option("-h")
         parser.remove_option("--version")
-        expected_usage = "usage: thingy arg arg\n"
+        expected_usage = "Usage: thingy arg arg\n"
         self.assertUsage(parser, expected_usage)
         self.assertVersion(parser, "thingy 0.1")
         self.assertHelp(parser, expected_usage + "\n")
@@ -520,9 +566,9 @@
     def setUp(self):
         self.parser = OptionParser(prog="test")
         self.help_prefix = """\
-usage: test [options]
+Usage: test [options]
 
-options:
+Options:
   -h, --help            show this help message and exit
 """
         self.file_help = "read from FILE [default: %default]"
@@ -703,13 +749,16 @@
         self.assertParseOK(["-a", "--", "foo", "bar"],
                            {'a': "--", 'boo': None, 'foo': None},
                            ["foo", "bar"]),
+        self.assertParseOK(["-a", "--", "--foo", "bar"],
+                           {'a': "--", 'boo': None, 'foo': ["bar"]},
+                           []),
 
     def test_short_option_joined_and_separator(self):
         self.assertParseOK(["-ab", "--", "--foo", "bar"],
                            {'a': "b", 'boo': None, 'foo': None},
                            ["--foo", "bar"]),
 
-    def test_invalid_option_becomes_positional_arg(self):
+    def test_hyphen_becomes_positional_arg(self):
         self.assertParseOK(["-ab", "-", "--foo", "bar"],
                            {'a': "b", 'boo': None, 'foo': ["bar"]},
                            ["-"])
@@ -874,6 +923,8 @@
                                type="float", dest="point")
         self.parser.add_option("-f", "--foo", action="append", nargs=2,
                                type="int", dest="foo")
+        self.parser.add_option("-z", "--zero", action="append_const",
+                               dest="foo", const=(0, 0))
 
     def test_nargs_append(self):
         self.assertParseOK(["-f", "4", "-3", "blah", "--foo", "1", "666"],
@@ -889,6 +940,11 @@
                            {'point': None, 'foo':[(3, 4)]},
                            [])
 
+    def test_nargs_append_const(self):
+        self.assertParseOK(["--zero", "--foo", "3", "4", "-z"],
+                           {'point': None, 'foo':[(0, 0), (3, 4), (0, 0)]},
+                           [])
+
 class TestVersion(BaseTest):
     def test_version(self):
         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
@@ -964,8 +1020,14 @@
         self.parser.add_option("-a", None, type="string", dest="a")
         self.parser.add_option("-f", "--file", type="file", dest="file")
 
+    def tearDown(self):
+        if os.path.isdir(test_support.TESTFN):
+            os.rmdir(test_support.TESTFN)
+        elif os.path.isfile(test_support.TESTFN):
+            os.unlink(test_support.TESTFN)
+
     class MyOption (Option):
-        def check_file (option, opt, value):
+        def check_file(option, opt, value):
             if not os.path.exists(value):
                 raise OptionValueError("%s: file does not exist" % value)
             elif not os.path.isfile(value):
@@ -976,25 +1038,23 @@
         TYPE_CHECKER = copy.copy(Option.TYPE_CHECKER)
         TYPE_CHECKER["file"] = check_file
 
-    def test_extend_file(self):
+    def test_filetype_ok(self):
         open(test_support.TESTFN, "w").close()
         self.assertParseOK(["--file", test_support.TESTFN, "-afoo"],
                            {'file': test_support.TESTFN, 'a': 'foo'},
                            [])
 
-        os.unlink(test_support.TESTFN)
-
-    def test_extend_file_nonexistent(self):
+    def test_filetype_noexist(self):
         self.assertParseFail(["--file", test_support.TESTFN, "-afoo"],
                              "%s: file does not exist" %
                              test_support.TESTFN)
 
-    def test_file_irregular(self):
+    def test_filetype_notfile(self):
         os.mkdir(test_support.TESTFN)
         self.assertParseFail(["--file", test_support.TESTFN, "-afoo"],
                              "%s: not a regular file" %
                              test_support.TESTFN)
-        os.rmdir(test_support.TESTFN)
+
 
 class TestExtendAddActions(BaseTest):
     def setUp(self):
@@ -1007,7 +1067,7 @@
         STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",)
         TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",)
 
-        def take_action (self, action, dest, opt, value, values, parser):
+        def take_action(self, action, dest, opt, value, values, parser):
             if action == "extend":
                 lvalue = value.split(",")
                 values.ensure_value(dest, []).extend(lvalue)
@@ -1076,7 +1136,7 @@
                           callback=lambda: None, type="string",
                           help="foo")
 
-        expected_help = ("options:\n"
+        expected_help = ("Options:\n"
                          "  -t TEST, --test=TEST  foo\n")
         self.assertHelp(parser, expected_help)
 
@@ -1089,7 +1149,7 @@
                                dest="points", default=[])]
         self.parser = OptionParser(option_list=options)
 
-    def process_tuple (self, option, opt, value, parser_, len, type):
+    def process_tuple(self, option, opt, value, parser_, len, type):
         self.assertEqual(len, 3)
         self.assert_(type is int)
 
@@ -1114,7 +1174,7 @@
         self.parser = OptionParser(option_list=options)
 
     # Callback that meddles in rargs, largs
-    def process_n (self, option, opt, value, parser_):
+    def process_n(self, option, opt, value, parser_):
         # option is -3, -5, etc.
         nargs = int(opt[1:])
         rargs = parser_.rargs
@@ -1143,7 +1203,7 @@
                                callback=self.process_many, type="int")]
         self.parser = OptionParser(option_list=options)
 
-    def process_many (self, option, opt, value, parser_):
+    def process_many(self, option, opt, value, parser_):
         if opt == "-a":
             self.assertEqual(value, ("foo", "bar"))
         elif opt == "--apple":
@@ -1166,7 +1226,7 @@
         self.parser.add_option("--foo-bar", action="callback",
                                callback=self.check_abbrev)
 
-    def check_abbrev (self, option, opt, value, parser):
+    def check_abbrev(self, option, opt, value, parser):
         self.assertEqual(opt, "--foo-bar")
 
     def test_abbrev_callback_expansion(self):
@@ -1181,7 +1241,7 @@
         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
                                                option_list=options)
 
-    def variable_args (self, option, opt, value, parser):
+    def variable_args(self, option, opt, value, parser):
         self.assert_(value is None)
         done = 0
         value = []
@@ -1233,7 +1293,7 @@
         self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
                                                option_list=options)
 
-    def show_version (self, option, opt, value, parser):
+    def show_version(self, option, opt, value, parser):
         parser.values.show_version = 1
 
 class TestConflict(ConflictBase):
@@ -1284,7 +1344,7 @@
 
     def test_conflict_resolve_help(self):
         self.assertOutput(["-h"], """\
-options:
+Options:
   --verbose      increment verbosity
   -h, --help     show this help message and exit
   -v, --version  show version
@@ -1323,7 +1383,7 @@
 
     def test_conflict_override_help(self):
         self.assertOutput(["-h"], """\
-options:
+Options:
   -h, --help     show this help message and exit
   -n, --dry-run  dry run mode
 """)
@@ -1336,9 +1396,9 @@
 # -- Other testing. ----------------------------------------------------
 
 _expected_help_basic = """\
-usage: bar.py [options]
+Usage: bar.py [options]
 
-options:
+Options:
   -a APPLE           throw APPLEs at basket
   -b NUM, --boo=NUM  shout "boo!" NUM times (in order to frighten away all the
                      evil spirits that cause trouble and mayhem)
@@ -1347,9 +1407,9 @@
 """
 
 _expected_help_long_opts_first = """\
-usage: bar.py [options]
+Usage: bar.py [options]
 
-options:
+Options:
   -a APPLE           throw APPLEs at basket
   --boo=NUM, -b NUM  shout "boo!" NUM times (in order to frighten away all the
                      evil spirits that cause trouble and mayhem)
@@ -1362,7 +1422,7 @@
 =====
   bar.py [options]
 
-options
+Options
 =======
 -a APPLE           throw APPLEs at basket
 --boo=NUM, -b NUM  shout "boo!" NUM times (in order to frighten away all the
@@ -1372,9 +1432,9 @@
 """
 
 _expected_help_short_lines = """\
-usage: bar.py [options]
+Usage: bar.py [options]
 
-options:
+Options:
   -a APPLE           throw APPLEs at basket
   -b NUM, --boo=NUM  shout "boo!" NUM times (in order to
                      frighten away all the evil spirits
@@ -1400,10 +1460,26 @@
             make_option("--foo", action="append", type="string", dest='foo',
                         help="store FOO in the foo list for later fooing"),
             ]
+
+        # We need to set COLUMNS for the OptionParser constructor, but
+        # we must restore its original value -- otherwise, this test
+        # screws things up for other tests when it's part of the Python
+        # test suite.
+        orig_columns = os.environ.get('COLUMNS')
         os.environ['COLUMNS'] = str(columns)
-        return InterceptingOptionParser(option_list=options)
+        try:
+            return InterceptingOptionParser(option_list=options)
+        finally:
+            if orig_columns is None:
+                del os.environ['COLUMNS']
+            else:
+                os.environ['COLUMNS'] = orig_columns
 
     def assertHelpEquals(self, expected_output):
+        if type(expected_output) is types.UnicodeType:
+            encoding = self.parser._get_encoding(sys.stdout)
+            expected_output = expected_output.encode(encoding, "replace")
+
         save_argv = sys.argv[:]
         try:
             # Make optparse believe bar.py is being executed.
@@ -1416,7 +1492,7 @@
         self.assertHelpEquals(_expected_help_basic)
 
     def test_help_old_usage(self):
-        self.parser.set_usage("usage: %prog [options]")
+        self.parser.set_usage("Usage: %prog [options]")
         self.assertHelpEquals(_expected_help_basic)
 
     def test_help_long_opts_first(self):
@@ -1434,6 +1510,27 @@
         self.parser = self.make_parser(60)
         self.assertHelpEquals(_expected_help_short_lines)
 
+    def test_help_unicode(self):
+        self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE)
+        self.parser.add_option("-a", action="store_true", help=u"ol\u00E9!")
+        expect = u"""\
+Options:
+  -h, --help  show this help message and exit
+  -a          ol\u00E9!
+"""
+        self.assertHelpEquals(expect)
+
+    def test_help_unicode_description(self):
+        self.parser = InterceptingOptionParser(usage=SUPPRESS_USAGE,
+                                               description=u"ol\u00E9!")
+        expect = u"""\
+ol\u00E9!
+
+Options:
+  -h, --help  show this help message and exit
+"""
+        self.assertHelpEquals(expect)
+
     def test_help_description_groups(self):
         self.parser.set_description(
             "This is the program description for %prog.  %prog has "
@@ -1446,13 +1543,13 @@
         group.add_option("-g", action="store_true", help="Group option.")
         self.parser.add_option_group(group)
 
-        self.assertHelpEquals("""\
-usage: bar.py [options]
+        expect = """\
+Usage: bar.py [options]
 
 This is the program description for bar.py.  bar.py has an option group as
 well as single options.
 
-options:
+Options:
   -a APPLE           throw APPLEs at basket
   -b NUM, --boo=NUM  shout "boo!" NUM times (in order to frighten away all the
                      evil spirits that cause trouble and mayhem)
@@ -1464,9 +1561,12 @@
     that some of them bite.
 
     -g               Group option.
-""")
+"""
 
+        self.assertHelpEquals(expect)
 
+        self.parser.epilog = "Please report bugs to /dev/null."
+        self.assertHelpEquals(expect + "\nPlease report bugs to /dev/null.\n")
 
 
 class TestMatchAbbrev(BaseTest):
@@ -1486,6 +1586,43 @@
             BadOptionError, "ambiguous option: --f (--fie, --foo, --foz?)")
 
 
+class TestParseNumber(BaseTest):
+    def setUp(self):
+        self.parser = InterceptingOptionParser()
+        self.parser.add_option("-n", type=int)
+        self.parser.add_option("-l", type=long)
+
+    def test_parse_num_fail(self):
+        self.assertRaises(
+            _parse_num, ("", int), {},
+            ValueError,
+            re.compile(r"invalid literal for int().*: '?'?"))
+        self.assertRaises(
+            _parse_num, ("0xOoops", long), {},
+            ValueError,
+            re.compile(r"invalid literal for long().*: '?0xOoops'?"))
+
+    def test_parse_num_ok(self):
+        self.assertEqual(_parse_num("0", int), 0)
+        self.assertEqual(_parse_num("0x10", int), 16)
+        self.assertEqual(_parse_num("0XA", long), 10L)
+        self.assertEqual(_parse_num("010", long), 8L)
+        self.assertEqual(_parse_num("0b11", int), 3)
+        self.assertEqual(_parse_num("0b", long), 0L)
+
+    def test_numeric_options(self):
+        self.assertParseOK(["-n", "42", "-l", "0x20"],
+                           { "n": 42, "l": 0x20 }, [])
+        self.assertParseOK(["-n", "0b0101", "-l010"],
+                           { "n": 5, "l": 8 }, [])
+        self.assertParseFail(["-n008"],
+                             "option -n: invalid integer value: '008'")
+        self.assertParseFail(["-l0b0123"],
+                             "option -l: invalid long integer value: '0b0123'")
+        self.assertParseFail(["-l", "0x12x"],
+                             "option -l: invalid long integer value: '0x12x'")
+
+
 def _testclasses():
     mod = sys.modules[__name__]
     return [getattr(mod, name) for name in dir(mod) if name.startswith('Test')]

Modified: py/branch/py-compat-2.5.2/py/compat/testing/test_textwrap.py
==============================================================================
--- py/trunk/py/compat/testing/test_textwrap.py	(original)
+++ py/branch/py-compat-2.5.2/py/compat/testing/test_textwrap.py	Tue Sep  2 21:40:21 2008
@@ -5,18 +5,14 @@
 # Converted to PyUnit by Peter Hansen <peter at engcorp.com>.
 # Currently maintained by Greg Ward.
 #
-# $Id: test_textwrap.py 38573 2005-03-05 02:38:33Z gward $
+# $Id: test_textwrap.py 46863 2006-06-11 19:42:51Z tim.peters $
 #
 
 import unittest
 from test import test_support
 
-import py
-textwrap = py.compat.textwrap
-TextWrapper = textwrap.TextWrapper
-wrap = textwrap.wrap
-fill = textwrap.fill
-dedent = textwrap.dedent
+from textwrap import TextWrapper, wrap, fill, dedent
+
 
 class BaseTestCase(unittest.TestCase):
     '''Parent class with utility methods for textwrap tests.'''
@@ -332,17 +328,18 @@
         self.check_wrap(text, 30,
                         [" This is a sentence with", "leading whitespace."])
 
-    def test_unicode(self):
-        # *Very* simple test of wrapping Unicode strings.  I'm sure
-        # there's more to it than this, but let's at least make
-        # sure textwrap doesn't crash on Unicode input!
-        text = u"Hello there, how are you today?"
-        self.check_wrap(text, 50, [u"Hello there, how are you today?"])
-        self.check_wrap(text, 20, [u"Hello there, how are", "you today?"])
-        olines = self.wrapper.wrap(text)
-        assert isinstance(olines, list) and isinstance(olines[0], unicode)
-        otext = self.wrapper.fill(text)
-        assert isinstance(otext, unicode)
+    if test_support.have_unicode:
+        def test_unicode(self):
+            # *Very* simple test of wrapping Unicode strings.  I'm sure
+            # there's more to it than this, but let's at least make
+            # sure textwrap doesn't crash on Unicode input!
+            text = u"Hello there, how are you today?"
+            self.check_wrap(text, 50, [u"Hello there, how are you today?"])
+            self.check_wrap(text, 20, [u"Hello there, how are", "you today?"])
+            olines = self.wrapper.wrap(text)
+            assert isinstance(olines, list) and isinstance(olines[0], unicode)
+            otext = self.wrapper.fill(text)
+            assert isinstance(otext, unicode)
 
     def test_split(self):
         # Ensure that the standard _split() method works as advertised
@@ -463,38 +460,42 @@
 # of IndentTestCase!
 class DedentTestCase(unittest.TestCase):
 
+    def assertUnchanged(self, text):
+        """assert that dedent() has no effect on 'text'"""
+        self.assertEquals(text, dedent(text))
+
     def test_dedent_nomargin(self):
         # No lines indented.
         text = "Hello there.\nHow are you?\nOh good, I'm glad."
-        self.assertEquals(dedent(text), text)
+        self.assertUnchanged(text)
 
         # Similar, with a blank line.
         text = "Hello there.\n\nBoo!"
-        self.assertEquals(dedent(text), text)
+        self.assertUnchanged(text)
 
         # Some lines indented, but overall margin is still zero.
         text = "Hello there.\n  This is indented."
-        self.assertEquals(dedent(text), text)
+        self.assertUnchanged(text)
 
         # Again, add a blank line.
         text = "Hello there.\n\n  Boo!\n"
-        self.assertEquals(dedent(text), text)
+        self.assertUnchanged(text)
 
     def test_dedent_even(self):
         # All lines indented by two spaces.
         text = "  Hello there.\n  How are ya?\n  Oh good."
         expect = "Hello there.\nHow are ya?\nOh good."
-        self.assertEquals(dedent(text), expect)
+        self.assertEquals(expect, dedent(text))
 
         # Same, with blank lines.
         text = "  Hello there.\n\n  How are ya?\n  Oh good.\n"
         expect = "Hello there.\n\nHow are ya?\nOh good.\n"
-        self.assertEquals(dedent(text), expect)
+        self.assertEquals(expect, dedent(text))
 
         # Now indent one of the blank lines.
         text = "  Hello there.\n  \n  How are ya?\n  Oh good.\n"
         expect = "Hello there.\n\nHow are ya?\nOh good.\n"
-        self.assertEquals(dedent(text), expect)
+        self.assertEquals(expect, dedent(text))
 
     def test_dedent_uneven(self):
         # Lines indented unevenly.
@@ -508,18 +509,53 @@
     while 1:
         return foo
 '''
-        self.assertEquals(dedent(text), expect)
+        self.assertEquals(expect, dedent(text))
 
         # Uneven indentation with a blank line.
         text = "  Foo\n    Bar\n\n   Baz\n"
         expect = "Foo\n  Bar\n\n Baz\n"
-        self.assertEquals(dedent(text), expect)
+        self.assertEquals(expect, dedent(text))
 
         # Uneven indentation with a whitespace-only line.
         text = "  Foo\n    Bar\n \n   Baz\n"
         expect = "Foo\n  Bar\n\n Baz\n"
-        self.assertEquals(dedent(text), expect)
+        self.assertEquals(expect, dedent(text))
 
+    # dedent() should not mangle internal tabs
+    def test_dedent_preserve_internal_tabs(self):
+        text = "  hello\tthere\n  how are\tyou?"
+        expect = "hello\tthere\nhow are\tyou?"
+        self.assertEquals(expect, dedent(text))
+
+        # make sure that it preserves tabs when it's not making any
+        # changes at all
+        self.assertEquals(expect, dedent(expect))
+
+    # dedent() should not mangle tabs in the margin (i.e.
+    # tabs and spaces both count as margin, but are *not*
+    # considered equivalent)
+    def test_dedent_preserve_margin_tabs(self):
+        text = "  hello there\n\thow are you?"
+        self.assertUnchanged(text)
+
+        # same effect even if we have 8 spaces
+        text = "        hello there\n\thow are you?"
+        self.assertUnchanged(text)
+
+        # dedent() only removes whitespace that can be uniformly removed!
+        text = "\thello there\n\thow are you?"
+        expect = "hello there\nhow are you?"
+        self.assertEquals(expect, dedent(text))
+
+        text = "  \thello there\n  \thow are you?"
+        self.assertEquals(expect, dedent(text))
+
+        text = "  \t  hello there\n  \t  how are you?"
+        self.assertEquals(expect, dedent(text))
+
+        text = "  \thello there\n  \t  how are you?"
+        expect = "hello there\n  how are you?"
+        self.assertEquals(expect, dedent(text))
 
 
 def test_main():

Modified: py/branch/py-compat-2.5.2/py/compat/textwrap.py
==============================================================================
--- py/trunk/py/compat/textwrap.py	(original)
+++ py/branch/py-compat-2.5.2/py/compat/textwrap.py	Tue Sep  2 21:40:21 2008
@@ -317,41 +317,58 @@
 
 # -- Loosely related functionality -------------------------------------
 
-def dedent(text):
-    """dedent(text : string) -> string
+_whitespace_only_re = re.compile('^[ \t]+$', re.MULTILINE)
+_leading_whitespace_re = re.compile('(^[ \t]*)(?:[^ \t\n])', re.MULTILINE)
 
-    Remove any whitespace than can be uniformly removed from the left
-    of every line in `text`.
+def dedent(text):
+    """Remove any common leading whitespace from every line in `text`.
 
-    This can be used e.g. to make triple-quoted strings line up with
-    the left edge of screen/whatever, while still presenting it in the
-    source code in indented form.
-
-    For example:
-
-        def test():
-            # end first line with \ to avoid the empty line!
-            s = '''\
-            hello
-              world
-            '''
-            print repr(s)          # prints '    hello\n      world\n    '
-            print repr(dedent(s))  # prints 'hello\n  world\n'
+    This can be used to make triple-quoted strings line up with the left
+    edge of the display, while still presenting them in the source code
+    in indented form.
+
+    Note that tabs and spaces are both treated as whitespace, but they
+    are not equal: the lines "  hello" and "\thello" are
+    considered to have no common leading whitespace.  (This behaviour is
+    new in Python 2.5; older versions of this module incorrectly
+    expanded tabs before searching for common leading whitespace.)
     """
-    lines = text.expandtabs().split('\n')
+    # Look for the longest leading string of spaces and tabs common to
+    # all lines.
     margin = None
-    for line in lines:
-        content = line.lstrip()
-        if not content:
-            continue
-        indent = len(line) - len(content)
+    text = _whitespace_only_re.sub('', text)
+    indents = _leading_whitespace_re.findall(text)
+    for indent in indents:
         if margin is None:
             margin = indent
-        else:
-            margin = min(margin, indent)
 
-    if margin is not None and margin > 0:
-        for i in range(len(lines)):
-            lines[i] = lines[i][margin:]
+        # Current line more deeply indented than previous winner:
+        # no change (previous winner is still on top).
+        elif indent.startswith(margin):
+            pass
+
+        # Current line consistent with and no deeper than previous winner:
+        # it's the new winner.
+        elif margin.startswith(indent):
+            margin = indent
+
+        # Current line and previous winner have no common whitespace:
+        # there is no margin.
+        else:
+            margin = ""
+            break
 
-    return '\n'.join(lines)
+    # sanity check (testing/debugging only)
+    if 0 and margin:
+        for line in text.split("\n"):
+            assert not line or line.startswith(margin), \
+                   "line = %r, margin = %r" % (line, margin)
+
+    if margin:
+        text = re.sub(r'(?m)^' + margin, '', text)
+    return text
+
+if __name__ == "__main__":
+    #print dedent("\tfoo\n\tbar")
+    #print dedent("  \thello there\n  \t  how are you?")
+    print dedent("Hello there.\n  This is indented.")

Deleted: /py/trunk/py/test/dsession/testing/basetest.py
==============================================================================
--- /py/trunk/py/test/dsession/testing/basetest.py	Tue Sep  2 21:40:21 2008
+++ (empty file)
@@ -1,32 +0,0 @@
-
-""" Support module for running tests
-"""
-
-import py
-from py.__.test.testing.setupdata import getexamplefile 
-
-class DirSetup(object):
-    def setup_method(self, method):
-        name = "%s.%s" %(self.__class__.__name__, method.func_name)
-        self.tmpdir = py.test.ensuretemp(name)
-        self.source = self.tmpdir.ensure("source", dir=1)
-        self.dest = self.tmpdir.join("dest")
-
-
-class BasicRsessionTest(object):
-    def setup_class(cls):
-        path = getexamplefile("test_funcexamples.py")
-        cls.config = py.test.config._reparse([path.dirpath()])
-        cls.modulecol = cls.config.getfsnode(path)
-
-    def setup_method(self, method):
-        self.session = self.config.initsession()
-        
-    def getfunc(self, name):
-        funcname = "test_func" + name
-        col = self.modulecol.join(funcname) 
-        assert col is not None, funcname
-        return col
-
-    def getdocexample(self):
-        return getexamplefile("docexample.txt")

Deleted: /py/trunk/py/test/testing/setupdata.py
==============================================================================
--- /py/trunk/py/test/testing/setupdata.py	Tue Sep  2 21:40:21 2008
+++ (empty file)
@@ -1,173 +0,0 @@
-import py
-
-#def setup_module(mod):
-#    mod.datadir = setupdatadir()
-#    mod.tmpdir = py.test.ensuretemp(mod.__name__) 
-
-#def setupdatadir():
-#    datadir = py.test.ensuretemp("datadir")
-#    for name in namecontent:
-#        getexamplefile(name)
-#    return datadir
-
-def getexamplefile(basename, tmpdir=None):
-    if tmpdir is None: 
-        tmpdir = py.test.ensuretemp("example") 
-        tmpdir.ensure("__init__.py")
-    path = tmpdir.join(basename) 
-    if not path.check():
-        path.write(py.code.Source(namecontent[basename]))
-        print "creating testfile", path
-    return path 
-
-def getexamplecollector(names, tmpdir=None): 
-    fn = getexamplefile(names[0], tmpdir=tmpdir)  
-    config = py.test.config._reparse([fn.dirpath()])
-    col = config.getfsnode(fn)
-    return col._getitembynames(names[1:])
-
-namecontent = {
-    'syntax_error.py': "this is really not python\n",
-
-    'disabled_module.py': '''
-        disabled = True
-
-        def setup_module(mod):
-            raise ValueError
-
-        class TestClassOne:
-            def test_func(self):
-                raise ValueError
-
-        class TestClassTwo:
-            def setup_class(cls):
-                raise ValueError
-            def test_func(self):
-                raise ValueError
-    ''', 
-
-    'brokenrepr.py': '''
-        import py
-
-        class BrokenRepr1:
-            """A broken class with lots of broken methods. Let's try to make the test framework 
-            immune to these."""
-            foo=0
-            def __repr__(self):
-                raise Exception("Ha Ha fooled you, I'm a broken repr().")
-
-        class BrokenRepr2:
-            """A broken class with lots of broken methods. Let's try to make the test framework 
-            immune to these."""
-            foo=0
-            def __repr__(self):
-                raise "Ha Ha fooled you, I'm a broken repr()."
-
-            
-        class TestBrokenClass:
-
-            def test_explicit_bad_repr(self):
-                t = BrokenRepr1()
-                py.test.raises(Exception, 'repr(t)')
-                
-            def test_implicit_bad_repr1(self):
-                t = BrokenRepr1()
-                assert t.foo == 1
-
-            def test_implicit_bad_repr2(self):
-                t = BrokenRepr2()
-                assert t.foo == 1
-    ''', 
-
-    'failingimport.py': "import gruetzelmuetzel\n", 
-
-    'test_mod.py': """
-        class TestA:
-            def test_m1(self):
-                pass
-        def test_f1():
-            pass
-        def test_g1():
-            yield lambda x: None, 42
-    """,
-
-    'file_test.py': """
-        def test_one(): 
-            assert 42 == 43
-
-        class TestClass(object): 
-            def test_method_one(self): 
-                assert 42 == 43 
-
-    """,
-
-    'test_threepass.py': """
-        def test_one():
-            assert 1
-
-        def test_two():
-            assert 1
-
-        def test_three():
-            assert 1
-    """,
-
-    'testspecial_importerror.py': """
-
-        import asdasd
-
-    """,
-
-    'disabled.py': """
-        class TestDisabled:
-            disabled = True
-            def test_method(self): 
-                pass
-    """,
-
-    'test_funcexamples.py': """
-        import py
-        import time
-        def test_funcpassed(): 
-            pass
-
-        def test_funcfailed():
-            raise AssertionError("hello world")
-
-        def test_funcskipped():
-            py.test.skip("skipped")
-
-        def test_funcprint():
-            print "samfing"
-
-        def test_funcprinterr():
-            print >>py.std.sys.stderr, "samfing"
-
-        def test_funcprintfail():
-            print "samfing elz"
-            asddsa
-
-        def test_funcexplicitfail():
-            py.test.fail("3")
-
-        def test_funcraisesfails():
-            py.test.raises(ValueError, lambda: 123) 
-
-        def test_funcoptioncustom():
-            assert py.test.config.getvalue("custom")
-
-        def test_funchang():
-            import time
-            time.sleep(1000)
-
-        def test_funckill15():
-            import os
-            os.kill(os.getpid(), 15)
-    """,
-
-    'docexample.txt': """ 
-        Aha!!!!!!
-        =========
-     """,
-
-} 

Deleted: /py/trunk/py/test/testing/test_repevent.py
==============================================================================
--- /py/trunk/py/test/testing/test_repevent.py	Tue Sep  2 21:40:21 2008
+++ (empty file)
@@ -1,30 +0,0 @@
-
-from py.__.test import event 
-import setupdata, suptest
-from py.__.code.testing.test_excinfo import TWMock
-
-
-
-class TestItemTestReport(object):
-
-    def test_toterminal(self):
-        sorter = suptest.events_run_example("file_test.py")
-        reports = sorter.get(event.ItemTestReport)
-        ev = reports[0] 
-        assert ev.failed 
-        twmock = TWMock()
-        ev.toterminal(twmock)
-        assert twmock.lines
-        twmock = TWMock()
-        ev.outcome.longrepr = "hello"
-        ev.toterminal(twmock)
-        assert twmock.lines[0] == "hello"
-        assert not twmock.lines[1:]
-
-        ##assert ev.repr_run.find("AssertionError") != -1
-        filepath = ev.colitem.fspath
-        #filepath , modpath = ev.itemrepr_path
-        assert str(filepath).endswith("file_test.py")
-        #assert modpath.endswith("file_test.test_one")
-        
-



More information about the pytest-commit mailing list