[py-svn] r33502 - in py/dist/py/rst: . testing

guido at codespeak.net guido at codespeak.net
Fri Oct 20 15:27:01 CEST 2006


Author: guido
Date: Fri Oct 20 15:26:58 2006
New Revision: 33502

Modified:
   py/dist/py/rst/rst.py
   py/dist/py/rst/testing/test_rst.py
Log:
Small cleanups, added comments, renamed 'childs' to 'children', added some 
simple node types.


Modified: py/dist/py/rst/rst.py
==============================================================================
--- py/dist/py/rst/rst.py	(original)
+++ py/dist/py/rst/rst.py	Fri Oct 20 15:26:58 2006
@@ -1,5 +1,12 @@
 
-""" reStructuredText manipulation tools
+""" reStructuredText generation tools
+
+    provides an api to build a tree from nodes, which can be converted to
+    ReStructuredText on demand
+
+    note that not all of ReST is supported, a usable subset is offered, but
+    certain features aren't supported, and also certain details (like how links
+    are generated, or how escaping is done) can not be controlled
 """
 
 from __future__ import generators
@@ -8,7 +15,7 @@
 
 def escape(txt):
     """escape ReST markup"""
-    for c in '*`[|':
+    for c in '\\*`[|:':
         txt = txt.replace(c, '\\%s' % (c,))
     return txt
 
@@ -34,7 +41,7 @@
         return obj
 
 class AbstractNode(object):
-    """ Basic class implementing writing rest code
+    """ Base class implementing rest generation
     """
     sep = ''
     __metaclass__ = AbstractMetaclass
@@ -45,17 +52,25 @@
     
     def __init__(self, *args, **kwargs):
         self.parent = None
-        self.childs = []
+        self.children = []
         for child in args:
             self._add(child)
         for arg in kwargs:
             setattr(self, arg, kwargs[arg])
     
     def join(self, child):
+        """ adds a child node
+        
+            returns a reference to self
+        """
         self._add(child)
         return self
     
     def add(self, child):
+        """ adds a child node
+            
+            returns a reference to the child
+        """
         self._add(child)
         return child
         
@@ -63,19 +78,21 @@
         if child.__class__ not in self.allowed_child:
             raise RestError("%r cannot be child of %r" % \
                 (child.__class__, self.__class__))
-        self.childs.append(child)
+        self.children.append(child)
         child.parent = self
     
     def __getitem__(self, item):
-        return self.childs[item]
+        return self.children[item]
     
     def __setitem__(self, item, value):
-        self.childs[item] = value
+        self.children[item] = value
 
     def text(self):
-        return self.sep.join([child.text() for child in self.childs])
+        """ return a ReST string representation of the node """
+        return self.sep.join([child.text() for child in self.children])
     
     def wordlist(self):
+        """ return a list of ReST strings for this node and its children """ 
         return [self.text()]
 
 class Rest(AbstractNode):
@@ -85,22 +102,35 @@
         self.links = {}
     
     def render_links(self, check=False):
+        """render the link attachents of the document"""
         assert not check, "Link checking not implemented"
         if not self.links:
             return ""
         link_texts = []
+        # XXX this could check for duplicates and remove them...
         for link, target in self.links.iteritems():
             link_texts.append(".. _`%s`: %s" % (escape(link), escape(target)))
         return "\n" + "\n".join(link_texts) + "\n\n"
 
     def text(self):
         outcome = []
-        for child in self.childs:
+        for child in self.children:
             outcome.append(child.text())
         
         text = self.sep.join(outcome) + "\n" # trailing newline
         return text + self.render_links()
 
+class Transition(AbstractNode):
+    parentclass = Rest
+
+    def __init__(self, char='-', width=80, *args, **kwargs):
+        self.char = char
+        self.width = width
+        super(Transition, self).__init__(*args, **kwargs)
+        
+    def text(self):
+        return (self.width - 1) * self.char
+
 class Paragraph(AbstractNode):
     parentclass = Rest
     sep = " "
@@ -117,7 +147,7 @@
     
     def text(self):
         texts = []
-        for child in self.childs:
+        for child in self.children:
             texts += child.wordlist()
         
         buf = []
@@ -217,13 +247,21 @@
     def text(self):
         oldindent = self.indent
         self.indent = oldindent + '  '
-        txt = Paragraph.text(self)
+        try:
+            txt = Paragraph.text(self)
+        finally:
+            self.indent = oldindent
         txt = self.item_char + txt[1:]
-        self.indent = oldindent
         return txt
 
 class OrderedListItem(ListItem):
-    item_char = "#"
+    item_char = "#."
+
+class DListItem(ListItem):
+    item_char = None
+    def __init__(self, term, definition, *args, **kwargs):
+        self.item_char = '%s\n ' % (term,)
+        super(DListItem, self).__init__(definition, *args, **kwargs)
 
 class Link(AbstractText):
     start = '`'

Modified: py/dist/py/rst/testing/test_rst.py
==============================================================================
--- py/dist/py/rst/testing/test_rst.py	(original)
+++ py/dist/py/rst/testing/test_rst.py	Fri Oct 20 15:26:58 2006
@@ -4,6 +4,14 @@
 
 from py.__.rst.rst import *
 
+def test_escape():
+    txt = Paragraph('*escape* ``test``').text()
+    assert txt == '\\*escape\\* \\`\\`test\\`\\`'
+    txt = Strong('*strong*').text()
+    assert txt == '**\\*strong\\***'
+    txt = Rest(Paragraph(Link('foo[bar]', 'foo[bar]'))).text()
+    assert txt == "`foo\\[bar]`_\n\n.. _`foo\\[bar]`: foo\\[bar]\n\n"
+
 def test_illegal_parent():
     Rest(Paragraph(Text('spam')))
     py.test.raises(RestError, 'Rest(Text("spam"))')
@@ -12,6 +20,12 @@
 def test_text_basic():
     assert Text("dupa").text() == "dupa"
 
+def test_basic_inline():
+    txt = Em('foo').text()
+    assert txt == '*foo*'
+    txt = Strong('bar').text()
+    assert txt == '**bar**'
+
 def test_text_join():
     assert Paragraph(Text("dupa"), Text("dupa")).text() == "dupa dupa"
 
@@ -67,7 +81,7 @@
 
 ::
 
- def fun():
+ def fun()\\:
   some
 
 Paragraph
@@ -161,6 +175,12 @@
                         'commodo pellentesque mi.')).text()
     assert txt == expected
 
+def test_ordered_list():
+    expected = "#. foo\n\n#. bar\n\n#. baz\n"
+    txt = Rest(OrderedListItem('foo'), OrderedListItem('bar'),
+               OrderedListItem('baz')).text()
+    assert txt == expected
+
 def test_title_following_links_empty_line():
     expected = """\
 Foo, bar and `baz`_.
@@ -175,17 +195,20 @@
     txt = Rest(Paragraph("Foo, bar and ", Link("baz", "http://www.baz.com")),
                Title('Spam'), Paragraph('Spam, eggs and spam.'))
 
-def test_basic_inline():
-    txt = Em('foo').text()
-    assert txt == '*foo*'
-    txt = Strong('bar').text()
-    assert txt == '**bar**'
+def test_definition_list():
+    expected = """\
+foo
+  bar, baz and qux!
 
-def test_escape():
-    txt = Paragraph('*escape* ``test``').text()
-    assert txt == '\\*escape\\* \\`\\`test\\`\\`'
-    txt = Strong('*strong*').text()
-    assert txt == '**\\*strong\\***'
-    txt = Rest(Paragraph(Link('foo[bar]', 'foo[bar]'))).text()
-    assert txt == "`foo\\[bar]`_\n\n.. _`foo\\[bar]`: foo\\[bar]\n\n"
+spam
+  eggs, spam, spam, eggs, spam and spam...
+"""
+    txt = Rest(DListItem("foo", "bar, baz and qux!"),
+               DListItem("spam", "eggs, spam, spam, eggs, spam and spam...")
+               ).text()
+    assert txt == expected
+
+def test_transition():
+    assert Rest(Transition()).text() == '%s\n' % ('-' * 79,)
+    assert Rest(Transition('+')).text() == '%s\n' % ('+' * 79,)
 



More information about the pytest-commit mailing list