[Checkins] SVN: manuel/trunk/src/manuel/ make the global state ("globs") shared between all evaluators, not

Benji York benji at zope.com
Sat May 2 13:36:56 EDT 2009


Log message for revision 99674:
  make the global state ("globs") shared between all evaluators, not
  just doctest
  

Changed:
  U   manuel/trunk/src/manuel/README.txt
  U   manuel/trunk/src/manuel/__init__.py
  U   manuel/trunk/src/manuel/doctest.py
  U   manuel/trunk/src/manuel/footnote.txt
  U   manuel/trunk/src/manuel/testing.py

-=-
Modified: manuel/trunk/src/manuel/README.txt
===================================================================
--- manuel/trunk/src/manuel/README.txt	2009-05-02 16:47:08 UTC (rev 99673)
+++ manuel/trunk/src/manuel/README.txt	2009-05-02 17:36:55 UTC (rev 99674)
@@ -164,7 +164,7 @@
     ...         self.test = test
     ...         self.passed = passed
 
-    >>> def evaluate(region, document):
+    >>> def evaluate(region, document, globs):
     ...     if not isinstance(region.parsed, NumbersTest):
     ...         return
     ...     test = region.parsed
@@ -172,7 +172,7 @@
     ...     region.evaluated = NumbersResult(test, passed)
 
     >>> for region in document:
-    ...     evaluate(region, document)
+    ...     evaluate(region, document, {})
     >>> [region.evaluated for region in document]
     [None,
      <NumbersResult object at 0x...>,
@@ -243,7 +243,7 @@
 
 Now we can evaluate the examples.
 
-    >>> document.evaluate_with(m)
+    >>> document.evaluate_with(m, globs={})
     >>> for region in document:
     ...     print (region.lineno, region.evaluated or region.source)
     (1, 'This is my\ndoctest.\n\n')
@@ -267,7 +267,7 @@
     ...     42
     ... """)
 
-    >>> document.process_with(m)
+    >>> document.process_with(m, globs={})
     >>> print document.formatted()
     File "<memory>", line 4, in <memory>
     Failed example:
@@ -281,9 +281,11 @@
 Globals
 -------
 
-Even though each example is parsed into its own object, state is still shared
-between them.
+Even though each region is parsed into its own object, state is still shared
+between them.  Each region of the document is executed in order so state
+changes made by earlier evaluaters are available to the current evaluator.
 
+
     >>> document = manuel.Document("""
     ...     >>> x = 1
     ...
@@ -292,7 +294,7 @@
     ...     >>> x
     ...     1
     ... """)
-    >>> document.process_with(m)
+    >>> document.process_with(m, globs={})
     >>> print document.formatted()
 
 Imported modules are added to the global namespace as well.
@@ -306,7 +308,7 @@
     ...     '0123456789'
     ...     
     ... """)
-    >>> document.process_with(m)
+    >>> document.process_with(m, globs={})
     >>> print document.formatted()
 
 
@@ -341,7 +343,7 @@
 Now we can process our source that combines both types of tests and see what
 we get.
 
-    >>> document.process_with(m)
+    >>> document.process_with(m, globs={})
 
 The document was parsed and has a mixture of prose and parsed doctests and
 number tests.
@@ -422,7 +424,7 @@
     ... I'd also like a clone after *here*.
     ... """
     >>> document = manuel.Document(source)
-    >>> document.process_with(m)
+    >>> document.process_with(m, globs={})
     >>> [(r.source, r.provenance) for r in document]
     [('This is my clone:\n\n', None),
      ('clone: 1, 2, 3\n', None),

Modified: manuel/trunk/src/manuel/__init__.py
===================================================================
--- manuel/trunk/src/manuel/__init__.py	2009-05-02 16:47:08 UTC (rev 99673)
+++ manuel/trunk/src/manuel/__init__.py	2009-05-02 17:36:55 UTC (rev 99674)
@@ -5,7 +5,14 @@
 EARLY = 'early'
 LATE = 'late'
 
+class GlobWrapper(dict):
 
+    def copy(self):
+        # XXX hack to trick doctest into making changes to the shared state
+        # instead of keeping a private copy
+        return self
+
+
 def timing(timing):
     assert timing in (EARLY, LATE)
     def decorate(func):
@@ -242,20 +249,21 @@
         for parser in sort_handlers(m.parsers):
             parser(self)
 
-    def evaluate_with(self, m):
+    def evaluate_with(self, m, globs):
+        globs = GlobWrapper(globs)
         for evaluater in sort_handlers(m.evaluaters):
             for region in list(self):
-                evaluater(region, self)
+                evaluater(region, self, globs)
 
     def format_with(self, m):
         for formatter in sort_handlers(m.formatters):
             formatter(self)
 
-    def process_with(self, m):
+    def process_with(self, m, globs):
         """Run all phases of document processing using a Manuel instance.
         """
         self.parse_with(m)
-        self.evaluate_with(m)
+        self.evaluate_with(m, globs)
         self.format_with(m)
 
     def formatted(self):

Modified: manuel/trunk/src/manuel/doctest.py
===================================================================
--- manuel/trunk/src/manuel/doctest.py	2009-05-02 16:47:08 UTC (rev 99673)
+++ manuel/trunk/src/manuel/doctest.py	2009-05-02 17:36:55 UTC (rev 99674)
@@ -9,12 +9,6 @@
     pass
 
 
-class SharedGlobs(dict):
-
-    def copy(self):
-        return self
-
-
 def parse(document):
     for region in list(document):
         if region.parsed:
@@ -41,7 +35,7 @@
             assert region in document
 
 
-def evaluate(m, region, document):
+def evaluate(m, region, document, globs):
     if not isinstance(region.parsed, doctest.Example):
         return
     result = DocTestResult()
@@ -53,7 +47,7 @@
 
     runner.DIVIDER = '' # disable unwanted result formatting
     runner.run(
-        doctest.DocTest([region.parsed], m.globs, test_name,
+        doctest.DocTest([region.parsed], globs, test_name,
             document.location, 0, None),
         out=result.write, clear_globs=False)
     region.evaluated = result
@@ -72,9 +66,8 @@
         self.runner = doctest.DocTestRunner(optionflags=optionflags,
             checker=checker)
         self.debug_runner = doctest.DebugRunner(optionflags=optionflags)
-        self.globs = SharedGlobs()
         self.debug = False
-        def evaluate_closure(region, document):
+        def evaluate_closure(region, document, globs):
             # capture "self"
-            evaluate(self, region, document)
+            evaluate(self, region, document, globs)
         manuel.Manuel.__init__(self, [parse], [evaluate_closure], [format])

Modified: manuel/trunk/src/manuel/footnote.txt
===================================================================
--- manuel/trunk/src/manuel/footnote.txt	2009-05-02 16:47:08 UTC (rev 99673)
+++ manuel/trunk/src/manuel/footnote.txt	2009-05-02 17:36:55 UTC (rev 99674)
@@ -37,7 +37,7 @@
     ...     >>> raise RuntimeError('nooooo!')
     ... """)
 
-    >>> document.process_with(m)
+    >>> document.process_with(m, globs={})
 
 Since all the examples in the doctest above are correct, we expect no errors.
 
@@ -66,7 +66,7 @@
     ...     >>> b = a + 1
     ...     
     ... """)
-    >>> document.process_with(m)
+    >>> document.process_with(m, globs={})
     >>> print document.formatted()
 
 It is possible to reference more than one footnote on a single line.
@@ -94,5 +94,5 @@
     ...     >>> z = w * x * y
     ...     
     ... """)
-    >>> document.process_with(m)
+    >>> document.process_with(m, globs={})
     >>> print document.formatted()

Modified: manuel/trunk/src/manuel/testing.py
===================================================================
--- manuel/trunk/src/manuel/testing.py	2009-05-02 16:47:08 UTC (rev 99673)
+++ manuel/trunk/src/manuel/testing.py	2009-05-02 17:36:55 UTC (rev 99674)
@@ -6,14 +6,16 @@
 __all__ = ['TestSuite']
 
 class TestCase(unittest.TestCase):
-    def __init__(self, m, document, setUp=None, tearDown=None,
-            globs=None):
+    def __init__(self, m, document, setUp=None, tearDown=None, globs=None):
         unittest.TestCase.__init__(self)
         self.manuel = m
         self.document = document
         self.setUp_func = setUp
         self.tearDown_func = tearDown
-        self.globs = globs
+        if globs is None:
+            self.globs = {}
+        else:
+            self.globs = globs
 
         # we want to go ahead and do the parse phase so the countTestCases
         # method can get a good idea of how many tests there are
@@ -21,14 +23,14 @@
 
     def setUp(self):
         if self.setUp_func is not None:
-            self.setUp_func(self.manuel)
+            self.setUp_func(self)
 
     def tearDown(self):
         if self.tearDown_func is not None:
-            self.tearDown_func(self.manuel)
+            self.tearDown_func(self)
 
     def runTest(self):
-        self.document.evaluate_with(self.manuel)
+        self.document.evaluate_with(self.manuel, self.globs)
         self.document.format_with(self.manuel)
         results = [r.formatted for r in self.document if r.formatted]
         if results:
@@ -39,7 +41,7 @@
     def debug(self):
         self.setUp()
         self.manuel.debug = True
-        self.document.evaluate_with(self.manuel)
+        self.document.evaluate_with(self.manuel, self.globs)
         self.tearDown()
 
     def countTestCases(self):
@@ -63,7 +65,7 @@
 
     `setUp`
       A set-up function.  This is called before running the tests in each file.
-      The setUp function will be passed a Manuel object.  The setUp function
+      The setUp function will be passed a TestCase object.  The setUp function
       can access the test globals as the `globs` attribute of the instance
       passed.
 



More information about the Checkins mailing list