[Checkins] SVN: manuel/trunk/ major docs rework, added Sphinx, still needs more user-oriented docs

Benji York benji at zope.com
Mon Jun 15 20:06:35 EDT 2009


Log message for revision 101027:
  major docs rework, added Sphinx, still needs more user-oriented docs
  

Changed:
  _U  manuel/trunk/
  U   manuel/trunk/README.txt
  U   manuel/trunk/buildout.cfg
  U   manuel/trunk/setup.py
  A   manuel/trunk/sphinx/
  A   manuel/trunk/sphinx/conf.py
  A   manuel/trunk/src/index.txt
  A   manuel/trunk/src/intro.txt
  U   manuel/trunk/src/manuel/README.txt
  U   manuel/trunk/src/manuel/bugs.txt
  U   manuel/trunk/src/manuel/code-block.txt
  U   manuel/trunk/src/manuel/codeblock.py
  U   manuel/trunk/src/manuel/table-example.txt
  U   manuel/trunk/src/manuel/tests.py

-=-

Property changes on: manuel/trunk
___________________________________________________________________
Modified: svn:ignore
   - develop-eggs
Python-trunk
dist
bin
parts
.installed.cfg

   + develop-eggs
Python-trunk
docs
dist
bin
parts
.installed.cfg


Modified: manuel/trunk/README.txt
===================================================================
--- manuel/trunk/README.txt	2009-06-15 19:52:19 UTC (rev 101026)
+++ manuel/trunk/README.txt	2009-06-16 00:06:35 UTC (rev 101027)
@@ -1 +1 @@
-See src/manuel/README.txt
+See src/intro.txt

Modified: manuel/trunk/buildout.cfg
===================================================================
--- manuel/trunk/buildout.cfg	2009-06-15 19:52:19 UTC (rev 101026)
+++ manuel/trunk/buildout.cfg	2009-06-16 00:06:35 UTC (rev 101027)
@@ -1,6 +1,6 @@
 [buildout]
 develop = .
-parts = test interpreter
+parts = test interpreter sphinx-docs-html build-docs
 allow-picked-versions = false
 use-dependency-links = false
 versions = versions
@@ -16,9 +16,37 @@
 eggs = manuel
 interpreter = py
 
+# generate a script that will build the user docs (HTML)
+[sphinx-docs-html]
+recipe = zc.recipe.egg:script
+eggs =
+    docutils
+    Sphinx
+    PILwoTk
+scripts = sphinx-build=docs
+base-sphinx-args = ('-W -N -c ${buildout:directory}/sphinx ${buildout:directory}/src ${buildout:directory}/docs'.split())
+arguments = sys.argv + ${sphinx-docs-html:base-sphinx-args}
+initialization =
+    # XXX for some reason "import Image" doesn't work for us; hack it
+    import PIL.Image                                                                                                                                                                                                                    
+    sys.modules['Image'] = PIL.Image
+
+# build the (HTML) user docs each time the buildout is run
+[build-docs]
+recipe = iw.recipe.cmd
+on_install = true
+on_update = true
+cmds = ${buildout:directory}/bin/docs
+
 [versions]
+iw.recipe.cmd = 0.3
+docutils = 0.5
 setuptools = 0.6c9
+PILwoTk = 1.1.6.3
 zc.buildout = 1.2.1
+Sphinx = 0.6.1
+Jinja2 = 2.1.1
+Pygments = 1.0
 zc.recipe.egg = 1.2.2
 zc.recipe.testrunner = 1.2.0
 zope.interface = 3.5.1

Modified: manuel/trunk/setup.py
===================================================================
--- manuel/trunk/setup.py	2009-06-15 19:52:19 UTC (rev 101026)
+++ manuel/trunk/setup.py	2009-06-16 00:06:35 UTC (rev 101027)
@@ -1,11 +1,8 @@
+from setuptools import setup, find_packages
 import os
 
-from setuptools import setup, find_packages
-
 long_description = (
-    open(os.path.join('src', 'manuel', 'README.txt')).read()
-    #+ '\n\n'
-    #+ open(os.path.join('src', 'manuel', 'table-example.txt')).read()
+    open(os.path.join('README.txt')).read()
     + '\n\n'
     + open('CHANGES.txt').read()
     )

Added: manuel/trunk/sphinx/conf.py
===================================================================
--- manuel/trunk/sphinx/conf.py	                        (rev 0)
+++ manuel/trunk/sphinx/conf.py	2009-06-16 00:06:35 UTC (rev 101027)
@@ -0,0 +1,14 @@
+source_suffix = '.txt'
+master_doc = 'index'
+project = 'Manuel'
+copyright = 'Benji York'
+version = '1'
+release = '1'
+today_fmt = '%Y-%m-%d'
+pygments_style = 'sphinx'
+
+html_last_updated_fmt = '%Y-%m-%d'
+html_title = 'Manuel Documentation'
+
+todo_include_todos = False
+exclude_dirnames = ['manuel.egg-info']


Property changes on: manuel/trunk/sphinx/conf.py
___________________________________________________________________
Added: svn:keywords
   + Id
Added: svn:eol-style
   + native

Added: manuel/trunk/src/index.txt
===================================================================
--- manuel/trunk/src/index.txt	                        (rev 0)
+++ manuel/trunk/src/index.txt	2009-06-16 00:06:35 UTC (rev 101027)
@@ -0,0 +1,15 @@
+====================
+Manuel documentation
+====================
+
+.. toctree::
+    :maxdepth: 1
+    :numbered:
+
+    intro.txt
+    manuel/README.txt
+    manuel/table-example.txt
+    manuel/code-block.txt
+    manuel/footnote.txt
+    manuel/isolation.txt
+    manuel/bugs.txt


Property changes on: manuel/trunk/src/index.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Added: manuel/trunk/src/intro.txt
===================================================================
--- manuel/trunk/src/intro.txt	                        (rev 0)
+++ manuel/trunk/src/intro.txt	2009-06-16 00:06:35 UTC (rev 101027)
@@ -0,0 +1,38 @@
+Introduction
+============
+
+Manuel lets you mix and match traditional doctests with new test syntax that
+you create or is included in Manuel.
+
+For example, if you've ever wanted to include a large chunk of Python in a
+doctest but were irritated by all the ">>>" and "..." prompts required, you'd
+like the "manuel.codeblock" module.  It lets you include code using Sphinx-style
+"..  code-block:: python" directives, like so:
+
+.. code-block:: python
+
+    import foo
+
+    def my_func(bar):
+        return foo.baz(bar)
+
+Incidentally, the implementation of manuel.codeblock is only 24 lines of code.
+
+For an example of creating your own test syntax, take a look at
+table-example.txt or for full details, README.txt.
+
+
+Included Functionality
+======================
+
+Manuel includes several extentions to doctest out of the box.
+
+manuel.codeblock
+    executes code in ".. code-block:: python" blocks
+
+manuel.footnote
+    executes code in reST-style footnodes each time they're referenced (good
+    for getting incedental code out of the main flow of a document)
+
+manuel.isolation
+    makes it easier to have test isolation in doctests


Property changes on: manuel/trunk/src/intro.txt
___________________________________________________________________
Added: svn:eol-style
   + native

Modified: manuel/trunk/src/manuel/README.txt
===================================================================
--- manuel/trunk/src/manuel/README.txt	2009-06-15 19:52:19 UTC (rev 101026)
+++ manuel/trunk/src/manuel/README.txt	2009-06-16 00:06:35 UTC (rev 101027)
@@ -1,22 +1,12 @@
-Contents
-========
+Theory of Operation
+===================
 
-.. contents::
+Manuel parses documents (tests), evaluates their contents, then formats the
+result of the evaluation.  The functionality is accessed via the "manuel"
+package.
 
-
-Overview
-========
-
-In short, Manuel parses documents (tests), evaluates their contents, then
-formats the result of the evaluation.
-
-The core functionality is accessed through an instance of a Manuel object.  It
-is used to build up the handling of a document type.  Each phase has a
-corresponding slot to which various implementations are attached.
-
     >>> import manuel
 
-
 Parsing
 -------
 
@@ -32,7 +22,7 @@
     >>> document = manuel.Document(source)
 
 For example purposes we will create a type of test that consists of a sequence
-of numbers so lets create a NumbersTest object to represent the parsed list.
+of numbers. Lets create a NumbersTest object to represent the parsed list.
 
     >>> class NumbersTest(object):
     ...     def __init__(self, description, numbers):
@@ -99,6 +89,8 @@
         ...
     ValueError: Regions must start at the begining of a line.
 
+.. more "whole-line" tests.
+
     >>> document.find_regions('three')
     Traceback (most recent call last):
         ...
@@ -149,23 +141,26 @@
 
 After a document has been parsed the resulting tests are evaluated.  Unlike
 parsing and formatting, evaluation is done one region at a time, in the order
-that the regions appear in the document.  Manuel provides another method to
-evaluate tests.  Lets define a function to evaluate NumberTests.  The function
-determines whether or not the numbers are in sorted order and records the
-result along with the description of the list of numbers.
+that the regions appear in the document.  Lets define a function to evaluate
+NumberTests.  The function determines whether or not the numbers are in sorted
+order and records the result along with the description of the list of numbers.
 
-    >>> class NumbersResult(object):
-    ...     def __init__(self, test, passed):
-    ...         self.test = test
-    ...         self.passed = passed
+.. code-block:: python
 
-    >>> def evaluate(region, document, globs):
-    ...     if not isinstance(region.parsed, NumbersTest):
-    ...         return
-    ...     test = region.parsed
-    ...     passed = sorted(test.numbers) == test.numbers
-    ...     region.evaluated = NumbersResult(test, passed)
+   class NumbersResult(object):
+       def __init__(self, test, passed):
+           self.test = test
+           self.passed = passed
 
+   def evaluate(region, document, globs):
+       if not isinstance(region.parsed, NumbersTest):
+           return
+       test = region.parsed
+       passed = sorted(test.numbers) == test.numbers
+       region.evaluated = NumbersResult(test, passed)
+
+.. a test of the above
+
     >>> for region in document:
     ...     evaluate(region, document, {})
     >>> [region.evaluated for region in document]
@@ -183,18 +178,21 @@
 a message about whether or not our lists of numbers are sorted properly.  A
 formatting function returns None when it has no output, or a string otherwise.
 
-    >>> def format(document):
-    ...     for region in document:
-    ...         if not isinstance(region.evaluated, NumbersResult):
-    ...             continue
-    ...         result = region.evaluated
-    ...         if not result.passed:
-    ...             region.formatted = (
-    ...                 "the numbers aren't in sorted order: "
-    ...                 + ', '.join(map(str, result.test.numbers)))
+.. code-block:: python
 
-Since our test case passed we don't get anything out of the report function.
+    def format(document):
+        for region in document:
+            if not isinstance(region.evaluated, NumbersResult):
+                continue
+            result = region.evaluated
+            if not result.passed:
+                region.formatted = (
+                    "the numbers aren't in sorted order: "
+                    + ', '.join(map(str, result.test.numbers)))
 
+Since one of the test cases failed we get an appropriate message out of the
+formatter.
+
     >>> format(document)
     >>> [region.formatted for region in document]
     [None, None, None, "the numbers aren't in sorted order: 3, 5, 1"]
@@ -211,7 +209,7 @@
 
 
 Doctests
-========
+--------
 
 We can use Manuel to run doctests.  Let's create a simple doctest to
 demonstrate with.
@@ -261,7 +259,6 @@
     ...     >>> 1 + 1
     ...     42
     ... """)
-
     >>> document.process_with(m, globs={})
     >>> print document.formatted()
     File "<memory>", line 4, in <memory>
@@ -301,14 +298,14 @@
     ...
     ...     >>> string.digits
     ...     '0123456789'
-    ...     
+    ...
     ... """)
     >>> document.process_with(m, globs={})
     >>> print document.formatted()
 
 
 Combining Test Types
-====================
+--------------------
 
 Now that we have both doctests and the silly "sorted numbers" tests, lets
 create a single document that has both.
@@ -369,7 +366,7 @@
 
 
 Priorities
-==========
+----------
 
 Some functionality requires that code be called early or late in a phase.  The
 "timing" decorator allows either EARLY or LATE to be specified.
@@ -411,9 +408,9 @@
     ... This is my clone:
     ...
     ... clone: 1, 2, 3
-    ... 
+    ...
     ... I want some copies of my clone.
-    ... 
+    ...
     ... For example, I'd like a clone before *here*.
     ...
     ... I'd also like a clone after *here*.
@@ -437,21 +434,23 @@
 First we'll create an evaluater that includes pertinant variable binding
 information on failures.
 
-    >>> import doctest
+.. code-block:: python
 
-    >>> def informative_evaluater(region, document, globs):
-    ...     if not isinstance(region.parsed, doctest.Example):
-    ...         return
-    ...     if region.evaluated.getvalue():
-    ...         info = ''
-    ...         for name in sorted(globs):
-    ...             if name in region.parsed.source:
-    ...                 info += '\n    ' + name + ' = ' + repr(globs[name])
-    ...
-    ...         if info:
-    ...             region.evaluated.write('Additional Information:')
-    ...             region.evaluated.write(info)
+    import doctest
 
+    def informative_evaluater(region, document, globs):
+        if not isinstance(region.parsed, doctest.Example):
+            return
+        if region.evaluated.getvalue():
+            info = ''
+            for name in sorted(globs):
+                if name in region.parsed.source:
+                    info += '\n    ' + name + ' = ' + repr(globs[name])
+
+            if info:
+                region.evaluated.write('Additional Information:')
+                region.evaluated.write(info)
+
 To do that we'll start with an instance of manuel.doctest.Manuel and add in our
 additional functionality.
 
@@ -473,6 +472,9 @@
     ...     5
     ... """)
 
+When we run the document through our Manuel instance, we see the additional
+information.
+
     >>> document.process_with(m, globs={})
     >>> print document.formatted()
     File "<memory>", line 10, in <memory>

Modified: manuel/trunk/src/manuel/bugs.txt
===================================================================
--- manuel/trunk/src/manuel/bugs.txt	2009-06-15 19:52:19 UTC (rev 101026)
+++ manuel/trunk/src/manuel/bugs.txt	2009-06-16 00:06:35 UTC (rev 101027)
@@ -1,8 +1,5 @@
-Miscellaneous Tests
-===================
-
 Fixed Bugs
-----------
+==========
 
 If a line of text matches both a "start" and "end" regular expression, no
 exception should be raised.

Modified: manuel/trunk/src/manuel/code-block.txt
===================================================================
--- manuel/trunk/src/manuel/code-block.txt	2009-06-15 19:52:19 UTC (rev 101026)
+++ manuel/trunk/src/manuel/code-block.txt	2009-06-16 00:06:35 UTC (rev 101027)
@@ -1,4 +1,4 @@
-Code blocks
+Code Blocks
 ===========
 
 `Sphinx <http://sphinx.pocoo.org/>`_ and other docutils `extensions

Modified: manuel/trunk/src/manuel/codeblock.py
===================================================================
--- manuel/trunk/src/manuel/codeblock.py	2009-06-15 19:52:19 UTC (rev 101026)
+++ manuel/trunk/src/manuel/codeblock.py	2009-06-16 00:06:35 UTC (rev 101027)
@@ -3,8 +3,11 @@
 import textwrap
 
 CODEBLOCK_START = re.compile(
-    r'^\.\.\s*code-block::\s*python\s*$', re.MULTILINE)
+    r'(?<=\n\n)\.\.\s*code-block::?\s*python\s*\n', re.DOTALL)
 
+# XXX document code-blocks that don't get executed and code-blocks that are
+# really comments but get executed anyway (perhaps with better syntax for both)
+
 # XXX should probably take end-of-file into account
 CODEBLOCK_END = re.compile(r'^\S.*$', re.MULTILINE)
 

Modified: manuel/trunk/src/manuel/table-example.txt
===================================================================
--- manuel/trunk/src/manuel/table-example.txt	2009-06-15 19:52:19 UTC (rev 101026)
+++ manuel/trunk/src/manuel/table-example.txt	2009-06-16 00:06:35 UTC (rev 101027)
@@ -140,13 +140,12 @@
     False  True   True
     True   True   True
     =====  =====  ======
-
     >>> region.parsed
     <Table object at ...>
 
 
 Evaluating
-==========
+----------
 
 Now that we can find and extract the tables from the source, we need to be able
 to check them for correctness.
@@ -231,7 +230,7 @@
 
 
 Formatting Errors
-=================
+-----------------
 
 Now that we can parse the tables and evaluate them, we need to be able to
 display the results in a readable fashion.
@@ -268,17 +267,22 @@
 
 
 All Together Now
-================
+----------------
 
 All the pieces (parsing, evaluating, and formatting) are available now, so we
 just have to put them together into a single "Manuel" object.
 
-    >>> m = manuel.Manuel(parsers=[parse_tables], evaluaters=[evaluate_table],
-    ...     formatters=[format_table_errors])
+.. code-block:: python
 
-Now we can create a fresh document and tell it to do all the above steps with
-our Manuel instance.
+    class Manuel(manuel.Manuel):
+        def __init__(self):
+            manuel.Manuel.__init__(self, [parse_tables], [evaluate_table],
+                [format_table_errors])
 
+Now we can create a fresh document and tell it to do all the above steps
+(parse, evaluate, format) an instance of our table example Manuel.
+
+    >>> m = Manuel()
     >>> document = manuel.Document(source_with_errors, location='fake.txt')
     >>> document.process_with(m, globs={})
     >>> print document.formatted(),
@@ -292,15 +296,32 @@
     >>> document.process_with(m, globs={})
     >>> print document.formatted()
 
-If we wanted to use our new table tests in a file named "table-example.txt" and
-include them in a unittest TestSuite, it would look something like this:
 
+Unittest Integration
+--------------------
+
+If we wanted to use our new table tests in conjunction with unittest, we could
+put the code above in tableexample.py.  Then to use the new syntax in a test
+file named "my-table-tests.txt" we can create a file named tests.py and build a
+TestSuite like so:
+
+.. this next chunk isn't actually executed by tests, so watch out
 .. code-block:: python
 
     import unittest
     import manuel.testing
+    import tableexample
 
-    suite = unittest.TestSuite()
+    def test_suite():
+        m = tableexample.Manuel()
+        return manuel.testing.TestSuite(m, 'my-table-tests.txt')
+
+.. this next bit is actually a reST comment, but it is run during tests anyway
+    (note the single colon instead of double colon)
+
+.. code-block: python
+
+    import unittest
     suite = manuel.testing.TestSuite(m, 'table-example.txt')
 
 If the tests are run (e.g., by a test runner), everything works.

Modified: manuel/trunk/src/manuel/tests.py
===================================================================
--- manuel/trunk/src/manuel/tests.py	2009-06-15 19:52:19 UTC (rev 101026)
+++ manuel/trunk/src/manuel/tests.py	2009-06-16 00:06:35 UTC (rev 101027)
@@ -17,19 +17,13 @@
     suite = unittest.TestSuite()
 
     tests = ['README.txt', 'footnote.txt', 'bugs.txt', 'code-block.txt',
-        'isolation.txt']
+        'isolation.txt', 'table-example.txt']
 
-    # Run the tests once with doctest.
-    suite.addTest(
-        doctest.DocFileSuite(optionflags=optionflags, checker=checker, *tests))
-
-    # Run them again with Manuel's doctest support.
+    # run the tests with Manuel's doctest support
     m = manuel.doctest.Manuel(optionflags=optionflags, checker=checker)
+    # add in the codeblock extension
+    m.extend(manuel.codeblock.Manuel())
+    # build the test suite
     suite.addTest(manuel.testing.TestSuite(m, *tests))
 
-    # Run the table example with doctest plus the codeblock extension.
-    m = manuel.doctest.Manuel(optionflags=optionflags, checker=checker)
-    m.extend(manuel.codeblock.Manuel())
-    suite.addTest(manuel.testing.TestSuite(
-        m, 'table-example.txt'))
     return suite



More information about the Checkins mailing list