various 3k related fixes and cleanups
removal of virtually unused py/rest/rst.py helpers --HG-- branch : trunk
This commit is contained in:
parent
5851471009
commit
6823fa634b
|
@ -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'),
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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'),
|
||||
)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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:
|
||||
|
|
417
py/rest/rst.py
417
py/rest/rst.py
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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>')
|
||||
|
|
@ -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)
|
||||
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue