[Checkins] SVN: manuel/trunk/ fix a bug that caused instances of zope.testin.doctest.Example (and instances

Benji York benji at zope.com
Mon Dec 7 15:15:04 EST 2009


Log message for revision 106256:
  fix a bug that caused instances of zope.testin.doctest.Example (and instances
  of subclasses of the same) to be silently ignored
  

Changed:
  U   manuel/trunk/CHANGES.txt
  U   manuel/trunk/src/manuel/__init__.py
  U   manuel/trunk/src/manuel/bugs.txt
  U   manuel/trunk/src/manuel/doctest.py
  U   manuel/trunk/src/manuel/testing.py

-=-
Modified: manuel/trunk/CHANGES.txt
===================================================================
--- manuel/trunk/CHANGES.txt	2009-12-07 19:35:08 UTC (rev 106255)
+++ manuel/trunk/CHANGES.txt	2009-12-07 20:15:04 UTC (rev 106256)
@@ -1,6 +1,13 @@
 CHANGES
 =======
 
+1.0.2 (2009-12-07)
+------------------
+
+- fix a bug that caused instances of zope.testin.doctest.Example (and instances
+  of subclasses of the same) to be silently ignored
+
+
 1.0.1 (2009-08-31)
 ------------------
 

Modified: manuel/trunk/src/manuel/__init__.py
===================================================================
--- manuel/trunk/src/manuel/__init__.py	2009-12-07 19:35:08 UTC (rev 106255)
+++ manuel/trunk/src/manuel/__init__.py	2009-12-07 20:15:04 UTC (rev 106256)
@@ -1,5 +1,6 @@
 import imp
 import re
+import sys
 
 # constants for use with "timing" decorator
 EARLY = 'early'
@@ -22,7 +23,21 @@
     return decorate
 
 
+def normalize_module_path(module_path):
+    if module_path.endswith('.pyc'):
+        module_path = module_path[:-1]
+    return module_path
+
 def absolute_import(name):
+    module_path = normalize_module_path(imp.find_module(name)[1])
+
+    # don't create a new module object if there's already one that we can reuse
+    for module in sys.modules.values():
+        if module is None or not hasattr(module, '__file__'):
+            continue
+        if module_path == normalize_module_path(module.__file__):
+            return module
+
     return imp.load_module(name, *imp.find_module(name))
 
 

Modified: manuel/trunk/src/manuel/bugs.txt
===================================================================
--- manuel/trunk/src/manuel/bugs.txt	2009-12-07 19:35:08 UTC (rev 106255)
+++ manuel/trunk/src/manuel/bugs.txt	2009-12-07 20:15:04 UTC (rev 106256)
@@ -17,7 +17,7 @@
 
     >>> source = """\
     ... Blah, blah.
-    ... 
+    ...
     ... xxx
     ... some text
     ... xxx
@@ -29,3 +29,65 @@
     >>> start = end = re.compile(r'^xxx$', re.MULTILINE)
     >>> document.find_regions(start, end)
     [<manuel.Region object at ...]
+
+
+Doctest Doppelganger
+--------------------
+
+The manuel.doctest module should be willing to run doctest Examples from either
+the standard library's doctest module, from zope.testing.doctest, or from
+subclasses of those.
+
+Here's a failing test we'll use to make sure this works::
+
+    This is my failing doctest.
+
+    >>> 1 + 1
+    42
+
+.. -> source
+
+    >>> document = manuel.Document(source)
+
+First we'll show that it fails using the normal Manuel pieces.
+
+    >>> m = manuel.doctest.Manuel()
+    >>> document.process_with(m, globs={})
+    >>> print document.formatted(),
+    File "<memory>", line 3, in <memory>
+    Failed example:
+        1 + 1
+    Expected:
+        42
+    Got:
+        2
+
+Now we'll create a subclass of zope.testing.doctest.Example, it should work too
+(but didn't at one point).
+
+.. code-block: python
+
+    import zope.testing.doctest
+
+    class MyExample(zope.testing.doctest.Example):
+        pass
+
+Now if we replace the stdlib doctest.Example in the parsed document, the
+failure is still reported.
+
+    >>> my_example = MyExample('2+2', '88')
+    >>> region = list(document)[1]
+    >>> region.parsed = my_example
+    >>> region.evaluated = None
+    >>> region.formatted = None
+    >>> manuel.doctest.evaluate(m, region, document, {})
+    >>> print region.evaluated.getvalue()
+    <BLANKLINE>
+    File "<memory>", line 3, in <memory>
+    Failed example:
+        2+2
+    Expected:
+        88
+    Got:
+        4
+    <BLANKLINE>

Modified: manuel/trunk/src/manuel/doctest.py
===================================================================
--- manuel/trunk/src/manuel/doctest.py	2009-12-07 19:35:08 UTC (rev 106255)
+++ manuel/trunk/src/manuel/doctest.py	2009-12-07 20:15:04 UTC (rev 106256)
@@ -1,10 +1,11 @@
 import StringIO
 import manuel
 import os.path
+import zope.testing.doctest
 
 doctest = manuel.absolute_import('doctest')
-#from zope.testing import doctest
 
+
 class DocTestResult(StringIO.StringIO):
     pass
 
@@ -44,8 +45,12 @@
 
 
 def evaluate(m, region, document, globs):
-    if not isinstance(region.parsed, doctest.Example):
+    # If the parsed object is not a doctest Example (from either the stdlib
+    # doctest or zope.testing.doctest), then we don't need to handle it.
+    if not isinstance(region.parsed, doctest.Example) \
+    and not isinstance(region.parsed, zope.testing.doctest.Example):
         return
+
     result = DocTestResult()
     test_name = os.path.split(document.location)[1]
     if m.debug:

Modified: manuel/trunk/src/manuel/testing.py
===================================================================
--- manuel/trunk/src/manuel/testing.py	2009-12-07 19:35:08 UTC (rev 106255)
+++ manuel/trunk/src/manuel/testing.py	2009-12-07 20:15:04 UTC (rev 106256)
@@ -2,10 +2,8 @@
 import manuel
 import os.path
 import unittest
+import zope.testing.doctest
 
-#doctest = manuel.absolute_import('doctest')
-from zope.testing import doctest
-
 __all__ = ['TestSuite']
 
 class TestCaseMarker(object):
@@ -38,7 +36,7 @@
         results = [r.formatted for r in self.regions if r.formatted]
         if results:
             DIVIDER = '-'*70 + '\n'
-            raise doctest.DocTestFailureException(
+            raise zope.testing.doctest.DocTestFailureException(
                 '\n' + DIVIDER + DIVIDER.join(results))
 
     def debug(self):
@@ -132,7 +130,8 @@
     # walk up the stack frame to find the module that called this function
     for depth in range(2, 5):
         try:
-            calling_module = doctest._normalize_module(None, depth=depth)
+            calling_module = zope.testing.doctest._normalize_module(
+                None, depth=depth)
         except KeyError:
             continue
         else:
@@ -143,7 +142,8 @@
             abs_path = os.path.normpath(path)
         else:
             abs_path = os.path.abspath(
-                doctest._module_relative_path(calling_module, path))
+                zope.testing.doctest._module_relative_path(
+                    calling_module, path))
 
         document = manuel.Document(open(abs_path).read(), location=abs_path)
         document.parse_with(m)



More information about the checkins mailing list