various 3k related fixes and cleanups

removal of virtually unused py/rest/rst.py helpers

--HG--
branch : trunk
This commit is contained in:
holger krekel 2009-09-04 18:15:41 +02:00
parent 5851471009
commit 6823fa634b
13 changed files with 16 additions and 1132 deletions

View File

@ -147,7 +147,6 @@ initpkg(__name__,
'builtin.print_' : ('./builtin/builtin31.py', 'print_'),
'builtin._reraise' : ('./builtin/builtin31.py', '_reraise'),
'builtin.exec_' : ('./builtin/builtin31.py', 'exec_'),
'builtin.intern' : ('./builtin/builtin31.py', 'intern'),
'builtin._basestring' : ('./builtin/builtin31.py', '_basestring'),
'builtin._totext' : ('./builtin/builtin31.py', '_totext'),
'builtin._isbytes' : ('./builtin/builtin31.py', '_isbytes'),

View File

@ -10,7 +10,6 @@ def test_varnames():
def f(self, y):
pass
assert varnames(f) == ("x",)
assert varnames(A.f) == ('y',)
assert varnames(A().f) == ('y',)
class TestMultiCall:
@ -121,7 +120,7 @@ class TestRegistry:
class api4:
x = 44
l = list(plugins.listattr('x', extra=(api4,)))
assert l == range(41, 45)
assert l == [41,42,43,44]
assert len(list(plugins)) == 3 # otherwise extra added
def test_api_and_defaults():

View File

@ -50,21 +50,14 @@ def test_importall():
base = py.path.local(py.__file__).dirpath()
nodirs = (
base.join('test', 'testing', 'data'),
base.join('apigen', 'tracer', 'testing', 'package'),
base.join('test', 'testing', 'test'),
base.join('test', 'rsession', 'webjs.py'),
base.join('apigen', 'source', 'server.py'),
base.join('magic', 'greenlet.py'),
base.join('test', 'web'),
base.join('path', 'gateway',),
base.join('doc',),
base.join('rest', 'directive.py'),
base.join('test', 'testing', 'import_test'),
base.join('c-extension',),
base.join('test', 'report', 'web.py'),
base.join('test', 'report', 'webjs.py'),
base.join('test', 'report', 'rest.py'),
base.join('magic', 'greenlet.py'),
base.join('bin'),
base.join('code', 'oldmagic.py'),
base.join('code', '_assertionold.py'),
base.join('execnet', 'script'),
base.join('compat', 'testing'),
)

View File

@ -8,7 +8,7 @@ def check_assertion():
raise ValueError("assertion not enabled: got %s" % s)
def test_invoke_assertion(recwarn, monkeypatch):
monkeypatch.setattr(py.std.__builtin__, 'AssertionError', None)
monkeypatch.setattr(py.builtin.builtins, 'AssertionError', None)
py.magic.invoke(assertion=True)
try:
check_assertion()
@ -17,7 +17,7 @@ def test_invoke_assertion(recwarn, monkeypatch):
recwarn.pop(DeprecationWarning)
def test_invoke_compile(recwarn, monkeypatch):
monkeypatch.setattr(py.std.__builtin__, 'compile', None)
monkeypatch.setattr(py.builtin.builtins, 'compile', None)
py.magic.invoke(compile=True)
try:
co = compile("""if 1:

View File

@ -10,7 +10,7 @@ def setup_module(mod):
def checkmain(name):
main = getattr(py.cmdline, name)
assert callable(main)
assert py.builtin.callable(main)
assert name[:2] == "py"
scriptname = "py." + name[2:]
assert binpath.join(scriptname).check()

View File

@ -1,7 +1,8 @@
""" deprecated module for turning on/off some features. """
import py
import __builtin__ as cpy_builtin
from py.builtin import builtins as cpy_builtin
def invoke(assertion=False, compile=False):
""" (deprecated) invoke magic, currently you can specify:

View File

@ -171,8 +171,8 @@ class ApiModule(ModuleType):
dict = dictdescr.__get__(self)
if dict is not None:
if '*' not in self.__map__:
for name in self.__map__.keys():
hasattr(self, name) # force attribute to be loaded, ignore errors
for name in list(self.__map__):
hasattr(self, name) # force attribute load, ignore errors
assert not self.__map__, "%r not empty" % self.__map__
else:
fsname = self.__map__['*'][0]

View File

@ -46,7 +46,7 @@ class ForkedFunc(object):
fdstderr = stderr.fileno()
if fdstderr != 2:
os.dup2(fdstderr, 2)
retvalf = self.RETVAL.open("w")
retvalf = self.RETVAL.open("wb")
EXITSTATUS = 0
try:
if nice_level:
@ -79,7 +79,7 @@ class ForkedFunc(object):
exitstatus = 0
signal = systemstatus & 0x7f
if not exitstatus and not signal:
retval = self.RETVAL.open()
retval = self.RETVAL.open('rb')
try:
retval_data = retval.read()
finally:

View File

@ -1,417 +0,0 @@
""" 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
import py
def escape(txt):
"""escape ReST markup"""
if not isinstance(txt, str) and not isinstance(txt, unicode):
txt = str(txt)
# XXX this takes a very naive approach to escaping, but it seems to be
# sufficient...
for c in '\\*`|:_':
txt = txt.replace(c, '\\%s' % (c,))
return txt
class RestError(Exception):
""" raised on containment errors (wrong parent) """
class AbstractMetaclass(type):
def __new__(cls, *args):
obj = super(AbstractMetaclass, cls).__new__(cls, *args)
parent_cls = obj.parentclass
if parent_cls is None:
return obj
if not isinstance(parent_cls, list):
class_list = [parent_cls]
else:
class_list = parent_cls
if obj.allow_nesting:
class_list.append(obj)
for _class in class_list:
if not _class.allowed_child:
_class.allowed_child = {obj:True}
else:
_class.allowed_child[obj] = True
return obj
class AbstractNode(object):
""" Base class implementing rest generation
"""
sep = ''
__metaclass__ = AbstractMetaclass
parentclass = None # this exists to allow parent to know what
# children can exist
allow_nesting = False
allowed_child = {}
defaults = {}
_reg_whitespace = py.std.re.compile('\s+')
def __init__(self, *args, **kwargs):
self.parent = None
self.children = []
for child in args:
self._add(child)
for arg in kwargs:
setattr(self, arg, kwargs[arg])
def join(self, *children):
""" add child nodes
returns a reference to self
"""
for child in children:
self._add(child)
return self
def add(self, child):
""" adds a child node
returns a reference to the child
"""
self._add(child)
return child
def _add(self, child):
if child.__class__ not in self.allowed_child:
raise RestError("%r cannot be child of %r" % \
(child.__class__, self.__class__))
self.children.append(child)
child.parent = self
def __getitem__(self, item):
return self.children[item]
def __setitem__(self, item, value):
self.children[item] = value
def text(self):
""" 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):
""" Root node of a document """
sep = "\n\n"
def __init__(self, *args, **kwargs):
AbstractNode.__init__(self, *args, **kwargs)
self.links = {}
def render_links(self, check=False):
"""render the link attachments 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.items():
link_texts.append(".. _`%s`: %s" % (escape(link), target))
return "\n" + "\n".join(link_texts) + "\n\n"
def text(self):
outcome = []
if (isinstance(self.children[0], Transition) or
isinstance(self.children[-1], Transition)):
raise ValueError('document must not begin or end with a '
'transition')
for child in self.children:
outcome.append(child.text())
# always a trailing newline
text = self.sep.join([i for i in outcome if i]) + "\n"
return text + self.render_links()
class Transition(AbstractNode):
""" a horizontal line """
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):
""" simple paragraph """
parentclass = Rest
sep = " "
indent = ""
width = 80
def __init__(self, *args, **kwargs):
# make shortcut
args = list(args)
for num, arg in enumerate(args):
if isinstance(arg, str):
args[num] = Text(arg)
super(Paragraph, self).__init__(*args, **kwargs)
def text(self):
texts = []
for child in self.children:
texts += child.wordlist()
buf = []
outcome = []
lgt = len(self.indent)
def grab(buf):
outcome.append(self.indent + self.sep.join(buf))
texts.reverse()
while texts:
next = texts[-1]
if not next:
texts.pop()
continue
if lgt + len(self.sep) + len(next) <= self.width or not buf:
buf.append(next)
lgt += len(next) + len(self.sep)
texts.pop()
else:
grab(buf)
lgt = len(self.indent)
buf = []
grab(buf)
return "\n".join(outcome)
class SubParagraph(Paragraph):
""" indented sub paragraph """
indent = " "
class Title(Paragraph):
""" title element """
parentclass = Rest
belowchar = "="
abovechar = ""
def text(self):
txt = self._get_text()
lines = []
if self.abovechar:
lines.append(self.abovechar * len(txt))
lines.append(txt)
if self.belowchar:
lines.append(self.belowchar * len(txt))
return "\n".join(lines)
def _get_text(self):
txt = []
for node in self.children:
txt += node.wordlist()
return ' '.join(txt)
class AbstractText(AbstractNode):
parentclass = [Paragraph, Title]
start = ""
end = ""
def __init__(self, _text):
self._text = _text
def text(self):
text = self.escape(self._text)
return self.start + text + self.end
def escape(self, text):
if not isinstance(text, str) and not isinstance(text, unicode):
text = str(text)
if self.start:
text = text.replace(self.start, '\\%s' % (self.start,))
if self.end and self.end != self.start:
text = text.replace(self.end, '\\%s' % (self.end,))
return text
class Text(AbstractText):
def wordlist(self):
text = escape(self._text)
return self._reg_whitespace.split(text)
class LiteralBlock(AbstractText):
parentclass = Rest
start = '::\n\n'
def text(self):
if not self._text.strip():
return ''
text = self.escape(self._text).split('\n')
for i, line in enumerate(text):
if line.strip():
text[i] = ' %s' % (line,)
return self.start + '\n'.join(text)
class Em(AbstractText):
start = "*"
end = "*"
class Strong(AbstractText):
start = "**"
end = "**"
class Quote(AbstractText):
start = '``'
end = '``'
class Anchor(AbstractText):
start = '_`'
end = '`'
class Footnote(AbstractText):
def __init__(self, note, symbol=False):
raise NotImplemented('XXX')
class Citation(AbstractText):
def __init__(self, text, cite):
raise NotImplemented('XXX')
class ListItem(Paragraph):
allow_nesting = True
item_chars = '*+-'
def text(self):
idepth = self.get_indent_depth()
indent = self.indent + (idepth + 1) * ' '
txt = '\n\n'.join(self.render_children(indent))
ret = []
item_char = self.item_chars[idepth]
ret += [indent[len(item_char)+1:], item_char, ' ', txt[len(indent):]]
return ''.join(ret)
def render_children(self, indent):
txt = []
buffer = []
def render_buffer(fro, to):
if not fro:
return
p = Paragraph(indent=indent, *fro)
p.parent = self.parent
to.append(p.text())
for child in self.children:
if isinstance(child, AbstractText):
buffer.append(child)
else:
if buffer:
render_buffer(buffer, txt)
buffer = []
txt.append(child.text())
render_buffer(buffer, txt)
return txt
def get_indent_depth(self):
depth = 0
current = self
while (current.parent is not None and
isinstance(current.parent, ListItem)):
depth += 1
current = current.parent
return depth
class OrderedListItem(ListItem):
item_chars = ["#."] * 5
class DListItem(ListItem):
item_chars = None
def __init__(self, term, definition, *args, **kwargs):
self.term = term
super(DListItem, self).__init__(definition, *args, **kwargs)
def text(self):
idepth = self.get_indent_depth()
indent = self.indent + (idepth + 1) * ' '
txt = '\n\n'.join(self.render_children(indent))
ret = []
ret += [indent[2:], self.term, '\n', txt]
return ''.join(ret)
class Link(AbstractText):
start = '`'
end = '`_'
def __init__(self, _text, target):
self._text = _text
self.target = target
self.rest = None
def text(self):
if self.rest is None:
self.rest = self.find_rest()
if self.rest.links.get(self._text, self.target) != self.target:
raise ValueError('link name %r already in use for a different '
'target' % (self.target,))
self.rest.links[self._text] = self.target
return AbstractText.text(self)
def find_rest(self):
# XXX little overkill, but who cares...
next = self
while next.parent is not None:
next = next.parent
return next
class InternalLink(AbstractText):
start = '`'
end = '`_'
class LinkTarget(Paragraph):
def __init__(self, name, target):
self.name = name
self.target = target
def text(self):
return ".. _`%s`:%s\n" % (self.name, self.target)
class Substitution(AbstractText):
def __init__(self, text, **kwargs):
raise NotImplemented('XXX')
class Directive(Paragraph):
indent = ' '
def __init__(self, name, *args, **options):
self.name = name
self.content = options.pop('content', [])
children = list(args)
super(Directive, self).__init__(*children)
self.options = options
def text(self):
# XXX not very pretty...
namechunksize = len(self.name) + 2
self.children.insert(0, Text('X' * namechunksize))
txt = super(Directive, self).text()
txt = '.. %s::%s' % (self.name, txt[namechunksize + 3:],)
options = '\n'.join([' :%s: %s' % (k, v) for (k, v) in
self.options.items()])
if options:
txt += '\n%s' % (options,)
if self.content:
txt += '\n'
for item in self.content:
assert item.parentclass == Rest, 'only top-level items allowed'
assert not item.indent
item.indent = ' '
txt += '\n' + item.text()
return txt

View File

@ -1,468 +0,0 @@
""" rst generation tests
"""
import py
py.test.importorskip("docutils")
from py.__.rest.rst import *
from py.__.rest.resthtml import process as restcheck
import traceback
tempdir = py.test.ensuretemp('rest')
def checkrest(rest):
fname = traceback.extract_stack()[-2][2]
i = 0
while True:
if i == 0:
filename = '%s.txt' % (fname,)
else:
filename = '%s_%s.txt' % (fname, i)
tempfile = tempdir.join(filename)
if not tempfile.check():
break
i += 1
tempfile.write(rest)
restcheck(tempfile)
return tempfile.new(ext='.html').read()
def test_escape_text():
txt = Paragraph('*escape* ``test``').text()
assert txt == '\\*escape\\* \\`\\`test\\`\\`'
html = checkrest(txt)
assert '*escape* ``test``' in html
def test_escape_markup_simple():
txt = Paragraph(Em('*em*')).text()
assert txt == '*\\*em\\**'
html = checkrest(txt)
assert '<em>*em*</em>' in html
def test_escape_underscore():
txt = Rest(Paragraph('foo [1]_')).text()
assert txt == "foo [1]\\_\n"
html = checkrest(txt)
assert 'foo [1]_' in html
def test_escape_markup_spaces_docutils_nastyness():
txt = Rest(Paragraph(Em('foo *bar* baz'))).text()
assert txt == '*foo \\*bar\\* baz*\n'
html = checkrest(txt)
assert '<em>foo *bar* baz</em>' in html
def test_escape_literal():
txt = LiteralBlock('*escape* ``test``').text()
assert txt == '::\n\n *escape* ``test``'
html = checkrest(txt)
assert '>\n*escape* ``test``\n</pre>' in html
def test_escape_markup_obvious():
txt = Em('foo*bar').text()
assert txt == '*foo\\*bar*'
html = checkrest(txt)
assert '<em>foo*bar</em>' in html
def test_escape_markup_text_1():
txt = Paragraph(Em('foo'), "*bar").text()
assert txt == '*foo* \\*bar'
html = checkrest(txt)
assert '<em>foo</em> *bar' in html
def test_escape_markup_text_2():
txt = Paragraph(Em('foo'), "bar*").text()
assert txt == '*foo* bar\\*'
html = checkrest(txt)
assert '<em>foo</em> bar*' in html
def test_illegal_parent():
Rest(Paragraph(Text('spam')))
py.test.raises(RestError, 'Rest(Text("spam"))')
py.test.raises(RestError, 'ListItem(Paragraph(Text("eggs")))')
def test_text_basic():
txt = Text("dupa").text()
assert txt == "dupa"
def test_basic_inline():
txt = Em('foo').text()
assert txt == '*foo*'
def test_basic_inline_2():
txt = Strong('bar').text()
assert txt == '**bar**'
def test_text_multiple_arguments():
txt = Paragraph(Text("dupa"), Text("dupa")).text()
assert txt == "dupa dupa"
def test_text_join():
txt = Paragraph(Text("worse things"))
txt = txt.join(Text("happen at sea"), Text("you know"))
assert txt.text() == "worse things happen at sea you know"
def test_text_add():
p = Paragraph(Text('grmbl'))
p2 = p.add(Text('grmbl too'))
assert p2.text() == 'grmbl too'
assert p.text() == 'grmbl grmbl too'
def test_paragraph_basic():
txt = Paragraph(Text('spam')).text()
assert txt == 'spam'
def test_paragraph_string():
txt = Paragraph("eggs").text()
assert txt == "eggs"
checkrest(txt)
def test_paragraph_join():
txt = Rest(Paragraph(Text("a")), Paragraph(Text("b"))).text()
assert txt == "a\n\nb\n"
def test_paragraph_indent():
txt = Paragraph(Text("a"), indent=" ").text()
assert txt == " a"
checkrest(txt)
txt = Paragraph(Text(" a "), indent=" ").text()
assert txt == " a"
def test_paragraph_width():
txt = Paragraph(Text("a b c d e f"), width=3, indent=" ").text()
assert txt == ' a\n b\n c\n d\n e\n f'
checkrest(txt)
text = """
Lorem ipsum dolor sit amet, consectetuer
adipiscing elit. Vestibulum malesuada
eleifend leo. Sed faucibus commodo libero.
Mauris elementum fringilla velit. Ut
sem urna, aliquet sed, molestie at, viverra
id, justo. In ornare lacinia turpis. Etiam
et ipsum. Quisque at lacus. Etiam
pellentesque, enim porta pulvinar viverra,
libero elit iaculis justo, vitae convallis
pede purus vel arcu. Morbi aliquam lacus
et urna. Donec commodo pellentesque mi.
"""
expected = """\
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vestibulum malesuada
eleifend leo. Sed faucibus commodo libero. Mauris elementum fringilla velit. Ut
sem urna, aliquet sed, molestie at, viverra id, justo. In ornare lacinia
turpis. Etiam et ipsum. Quisque at lacus. Etiam pellentesque, enim porta
pulvinar viverra, libero elit iaculis justo, vitae convallis pede purus vel
arcu. Morbi aliquam lacus et urna. Donec commodo pellentesque mi."""
txt = Paragraph(text, width=80).text()
print(repr(txt))
print(repr(expected))
assert txt == expected
checkrest(txt)
def test_paragraph_stripping():
txt = Paragraph(Text('\n foo bar\t')).text()
assert txt == 'foo bar'
checkrest(txt)
def test_blockquote():
expected = """\
Text
::
def fun():
some
Paragraph
"""
txt = Rest(Paragraph("Text"), LiteralBlock("def fun():\n some"), \
Paragraph("Paragraph")).text()
print(repr(txt))
assert txt == expected
checkrest(txt)
def test_blockquote_empty():
expected = """\
Foo
Bar
"""
txt = Rest(Paragraph('Foo'), LiteralBlock(''), Paragraph('Bar')).text()
print(repr(txt))
assert txt == expected
checkrest(txt)
def test_title():
txt = Title(Text("Some title"), belowchar="=").text()
assert txt == "Some title\n=========="
checkrest(txt)
txt = Title("Some title", belowchar="#", abovechar="#").text()
assert txt == "##########\nSome title\n##########"
html = checkrest(txt)
assert '>Some title</h1>' in html
def test_title_long():
txt = Title('Some very long title that doesn\'t fit on a single line '
'but still should not be split into multiple lines').text()
assert txt == ("Some very long title that doesn't fit on a single line "
"but still should not be split into multiple lines\n"
"======================================================="
"=================================================")
checkrest(txt)
def test_title_long_with_markup():
txt = Title('Some very long title with', Em('some markup'),
'to test whether that works as expected too...').text()
assert txt == ("Some very long title with *some markup* to test whether "
"that works as expected too...\n"
"========================================================"
"=============================")
checkrest(txt)
def test_title_escaping():
txt = Title('foo *bar* baz').text()
assert txt == 'foo \\*bar\\* baz\n==============='
checkrest(txt)
def test_link():
expected = "`some link`_\n\n.. _`some link`: http://codespeak.net\n\n"
txt = Rest(Paragraph(Link("some link", "http://codespeak.net"))).text()
assert txt == expected
html = checkrest(txt)
assert ' href="http://codespeak.net">some link</a>' in html
def test_link_same_text_and_target():
txt = Rest(Paragraph(Link('some link', 'bar'), 'foo',
Link('some link', 'bar'))
).text()
expected = '`some link`_ foo `some link`_\n\n.. _`some link`: bar\n\n'
assert txt == expected
def test_link_same_text_different_target():
py.test.raises(ValueError, ("Rest(Paragraph(Link('some link', 'foo'),"
"Link('some link', 'bar'))).text()"))
def test_text_multiline():
expected = """\
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vestibulum malesuada
eleifend leo. Sed faucibus commodo libero. Mauris elementum fringilla velit. Ut
sem urna, aliquet sed, molestie at, viverra id, justo. In ornare lacinia
turpis. Etiam et ipsum. Quisque at lacus. Etiam pellentesque, enim porta
pulvinar viverra, libero elit iaculis justo, vitae convallis pede purus vel
arcu. Morbi aliquam lacus et urna. Donec commodo pellentesque mi.
"""
txt = Rest(Paragraph('Lorem ipsum dolor sit amet, consectetuer adipiscing '
'elit. Vestibulum malesuada eleifend leo. Sed '
'faucibus commodo libero. Mauris elementum fringilla '
'velit. Ut sem urna, aliquet sed, molestie at, '
'viverra id, justo. In ornare lacinia turpis. Etiam '
'et ipsum. Quisque at lacus. Etiam pellentesque, '
'enim porta pulvinar viverra, libero elit iaculis '
'justo, vitae convallis pede purus vel arcu. Morbi '
'aliquam lacus et urna. Donec commodo pellentesque '
'mi.')).text()
assert txt == expected
checkrest(txt)
def test_text_indented():
expected = """\
This is a paragraph with some indentation. The indentation should be removed
and the lines split up nicely. This is still part of the first paragraph.
"""
txt = Rest(Paragraph('This is a paragraph with some\n'
' indentation. The indentation\n'
' should be removed and the lines split up nicely.\n'
'\nThis is still part of the first paragraph.')
).text()
assert txt == expected
checkrest(txt)
def test_text_strip():
expected = "foo\n"
txt = Rest(Paragraph(Text(' foo '))).text()
assert txt == expected
checkrest(txt)
def test_list():
expected = "* a\n\n* b\n"
txt = Rest(ListItem("a"), ListItem("b")).text()
assert txt == expected
checkrest(txt)
def test_list_item_multiple_args():
expected = "* foo bar baz\n"
txt = Rest(ListItem('foo', 'bar', 'baz')).text()
assert txt == expected
checkrest(txt)
def test_list_multiline():
expected = """\
* Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Vestibulum
malesuada eleifend leo. Sed faucibus commodo libero.
* Mauris elementum fringilla velit. Ut sem urna, aliquet sed, molestie at,
viverra id, justo. In ornare lacinia turpis. Etiam et ipsum. Quisque at
lacus.
* Etiam pellentesque, enim porta pulvinar viverra, libero elit iaculis justo,
vitae convallis pede purus vel arcu. Morbi aliquam lacus et urna. Donec
commodo pellentesque mi.
"""
txt = Rest(ListItem('Lorem ipsum dolor sit amet, consectetuer adipiscing '
'elit. Vestibulum malesuada eleifend leo. Sed '
'faucibus commodo libero.'),
ListItem('Mauris elementum fringilla velit. Ut sem urna, '
'aliquet sed, molestie at, viverra id, justo. In '
'ornare lacinia turpis. Etiam et ipsum. Quisque at '
'lacus.'),
ListItem('Etiam pellentesque, enim porta pulvinar viverra, '
'libero elit iaculis justo, vitae convallis pede '
'purus vel arcu. Morbi aliquam lacus et urna. Donec '
'commodo pellentesque mi.')).text()
assert txt == expected
checkrest(txt)
def test_list_multiline_no_parent():
expected = ("* test **strong**\n thisisaverylongwordthatdoesntfiton"
"thepreviouslineandthereforeshouldbeindented")
txt = ListItem(Text('test'), Strong('strong'),
Text('thisisaverylongwordthatdoesntfitontheprevious'
'lineandthereforeshouldbeindented')).text()
assert txt == expected
checkrest(txt)
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
checkrest(txt)
def test_nested_lists():
expected = """\
* foo
* bar
+ baz
"""
txt = Rest(ListItem('foo'), ListItem('bar', ListItem('baz'))).text()
assert txt == expected
checkrest(txt)
def test_nested_nested_lists():
expected = """\
* foo
+ bar
- baz
+ qux
* quux
"""
txt = Rest(ListItem('foo', ListItem('bar', ListItem('baz')),
ListItem('qux')), ListItem('quux')).text()
print(txt)
assert txt == expected
checkrest(txt)
def test_definition_list():
expected = """\
foo
bar, baz and qux!
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
checkrest(txt)
def test_nested_dlists():
expected = """\
foo
bar baz
qux
quux
"""
txt = Rest(DListItem('foo', 'bar baz', DListItem('qux', 'quux'))).text()
assert txt == expected
def test_nested_list_dlist():
expected = """\
* foo
foobar
baz
"""
txt = Rest(ListItem('foo', DListItem('foobar', 'baz'))).text()
assert txt == expected
def test_transition():
txt = Rest(Paragraph('foo'), Transition(), Paragraph('bar')).text()
assert txt == 'foo\n\n%s\n\nbar\n' % ('-' * 79,)
checkrest(txt)
txt = Rest(Paragraph('foo'), Transition('+'), Paragraph('bar')).text()
assert txt == 'foo\n\n%s\n\nbar\n' % ('+' * 79,)
checkrest(txt)
py.test.raises(ValueError, 'Rest(Transition(), Paragraph("foo")).text()')
py.test.raises(ValueError, 'Rest(Paragraph("foo"), Transition()).text()')
def test_directive_simple():
txt = Rest(Directive('image', 'images/foo.png')).text()
assert txt == '.. image:: images/foo.png\n'
def test_directive_metadata():
txt = Rest(Directive('image', 'images/foo.png',
width=200, height=150)).text()
assert txt == ('.. image:: images/foo.png\n :width: 200\n'
' :height: 150\n')
def test_directive_multiline():
txt = Rest(Directive('note', ('This is some string that is too long to '
'fit on a single line, so it should be '
'broken up.'))).text()
assert txt == """\
.. note:: This is some string that is too long to fit on a single line, so it
should be broken up.
"""
def test_directive_content():
txt = Rest(Directive('image', 'foo.png', width=200, height=100,
content=[Paragraph('Some paragraph content.')])).text()
assert txt == """\
.. image:: foo.png
:width: 200
:height: 100
Some paragraph content.
"""
def test_title_following_links_empty_line():
expected = """\
Foo, bar and `baz`_
Spam
====
Spam, eggs and spam.
.. _`baz`: http://www.baz.com
"""
txt = Rest(Paragraph("Foo, bar and ", Link("baz", "http://www.baz.com")),
Title('Spam'), Paragraph('Spam, eggs and spam.')).text()
assert txt == expected
checkrest(txt)
def test_nonstring_text():
expected = """\
<foobar>
"""
class FooBar(object):
def __str__(self):
return '<foobar>'
txt = Rest(Paragraph(Text(FooBar()))).text()
assert txt == expected

View File

@ -1,39 +0,0 @@
import py
from py.__.rest.rst import *
from py.__.rest.transform import *
def convert_to_html(tree):
handler = HTMLHandler()
t = RestTransformer(tree)
t.parse(handler)
return handler.html
class HTMLHandler(py.__.rest.transform.HTMLHandler):
def startDocument(self):
pass
endDocument = startDocument
def test_transform_basic_html():
for rest, expected in ((Rest(Title('foo')), '<h1>foo</h1>'),
(Rest(Paragraph('foo')), '<p>foo</p>'),
(Rest(SubParagraph('foo')),
'<p class="sub">foo</p>'),
(Rest(LiteralBlock('foo\tbar')),
'<pre>foo\tbar</pre>'),
(Rest(Paragraph(Link('foo',
'http://www.foo.com/'))),
'<p><a href="http://www.foo.com/">foo</a></p>')):
html = convert_to_html(rest)
assert html == expected
def test_transform_list_simple():
rest = Rest(ListItem('foo'), ListItem('bar'))
html = convert_to_html(rest)
assert html == '<ul>\n <li>foo</li>\n <li>bar</li></ul>'
def test_transform_list_nested():
rest = Rest(ListItem('foo'), ListItem('bar', ListItem('baz')))
html = convert_to_html(rest)
assert html == ('<ul>\n <li>foo</li>\n <li>bar\n <ul>'
'\n <li>baz</li></ul></li></ul>')

View File

@ -1,184 +0,0 @@
import py
from py.__.rest import rst
from py.xml import html
class RestTransformer(object):
def __init__(self, tree):
self.tree = tree
self._titledepths = {}
self._listmarkers = []
def parse(self, handler):
handler.startDocument()
self.parse_nodes(self.tree.children, handler)
handler.endDocument()
def parse_nodes(self, nodes, handler):
for node in nodes:
name = node.__class__.__name__
if name == 'Rest':
continue
getattr(self, 'handle_%s' % (name,))(node, handler)
def handle_Title(self, node, handler):
depthkey = (node.abovechar, node.belowchar)
if depthkey not in self._titledepths:
if not self._titledepths:
depth = 1
else:
depth = max(self._titledepths.values()) + 1
self._titledepths[depthkey] = depth
else:
depth = self._titledepths[depthkey]
handler.startTitle(depth)
self.parse_nodes(node.children, handler)
handler.endTitle(depth)
def handle_ListItem(self, node, handler):
# XXX oomph...
startlist = False
c = node.parent.children
nodeindex = c.index(node)
if nodeindex == 0:
startlist = True
else:
prev = c[nodeindex - 1]
if not isinstance(prev, rst.ListItem):
startlist = True
elif prev.indent < node.indent:
startlist = True
endlist = False
if nodeindex == len(c) - 1:
endlist = True
else:
next = c[nodeindex + 1]
if not isinstance(next, rst.ListItem):
endlist = True
elif next.indent < node.indent:
endlist = True
type = isinstance(node, rst.OrderedListItem) and 'o' or 'u'
handler.startListItem('u', startlist)
self.parse_nodes(node.children, handler)
handler.endListItem('u', endlist)
def handle_Transition(self, node, handler):
handler.handleTransition()
def handle_Paragraph(self, node, handler):
handler.startParagraph()
self.parse_nodes(node.children, handler)
handler.endParagraph()
def handle_SubParagraph(self, node, handler):
handler.startSubParagraph()
self.parse_nodes(node.children, handler)
handler.endSubParagraph()
def handle_LiteralBlock(self, node, handler):
handler.handleLiteralBlock(node._text)
def handle_Text(self, node, handler):
handler.handleText(node._text)
def handle_Em(self, node, handler):
handler.handleEm(node._text)
def handle_Strong(self, node, handler):
handler.handleStrong(node._text)
def handle_Quote(self, node, handler):
handler.handleQuote(node._text)
def handle_Link(self, node, handler):
handler.handleLink(node._text, node.target)
def entitize(txt):
for char, repl in (('&', 'amp'), ('>', 'gt'), ('<', 'lt'), ('"', 'quot'),
("'", 'apos')):
txt = txt.replace(char, '&%s;' % (repl,))
return txt
class HTMLHandler(object):
def __init__(self, title='untitled rest document'):
self.title = title
self.root = None
self.tagstack = []
self._currlist = None
def startDocument(self):
h = html.html()
self.head = head = html.head()
self.title = title = html.title(self.title)
self._push(h)
h.append(head)
h.append(title)
self.body = body = html.body()
self._push(body)
def endDocument(self):
self._pop() # body
self._pop() # html
def startTitle(self, depth):
h = getattr(html, 'h%s' % (depth,))()
self._push(h)
def endTitle(self, depth):
self._pop()
def startParagraph(self):
self._push(html.p())
def endParagraph(self):
self._pop()
def startSubParagraph(self):
self._push(html.p(**{'class': 'sub'}))
def endSubParagraph(self):
self._pop()
def handleLiteralBlock(self, text):
pre = html.pre(text)
if self.tagstack:
self.tagstack[-1].append(pre)
else:
self.root = pre
def handleText(self, text):
self.tagstack[-1].append(text)
def handleEm(self, text):
self.tagstack[-1].append(html.em(text))
def handleStrong(self, text):
self.tagstack[-1].append(html.strong(text))
def startListItem(self, type, startlist):
if startlist:
nodename = type == 'o' and 'ol' or 'ul'
self._push(getattr(html, nodename)())
self._push(html.li())
def endListItem(self, type, closelist):
self._pop()
if closelist:
self._pop()
def handleLink(self, text, target):
self.tagstack[-1].append(html.a(text, href=target))
def _push(self, el):
if self.tagstack:
self.tagstack[-1].append(el)
else:
self.root = el
self.tagstack.append(el)
def _pop(self):
self.tagstack.pop()
def _html(self):
return self.root.unicode()
html = property(_html)

View File

@ -9,9 +9,9 @@ import sys
#
# ===============================================================================
import pytest_runner as runner # XXX
from pytest_terminal import TerminalReporter, CollectonlyReporter
from pytest_terminal import repr_pythonversion, folded_skips
from py.__.test.plugin.pytest_terminal import TerminalReporter, \
CollectonlyReporter, repr_pythonversion, folded_skips
from py.__.test.plugin import pytest_runner as runner
def basic_run_report(item):
return runner.call_and_report(item, "call", log=False)