fix issue94 make reporting more robust against bogus source code

(and internally be more careful when presenting unexpected byte sequences)
also make py.code.Source accept a list of lines directly.

--HG--
branch : trunk
This commit is contained in:
holger krekel 2010-05-21 16:42:46 +02:00
parent 93f91c9607
commit 578cba20d4
4 changed files with 34 additions and 4 deletions

View File

@ -17,6 +17,9 @@ Changes between 1.3.0 and 1.3.1
declarative approach with the @py.test.mark.xfail cannot declarative approach with the @py.test.mark.xfail cannot
be used as it would mark all configurations as xfail. be used as it would mark all configurations as xfail.
- fix issue94: make reporting more robust against bogus source code
(and internally be more careful when presenting unexpected byte sequences)
- improve and refine letter reporting in the progress bar: - improve and refine letter reporting in the progress bar:
. pass . pass
f failed test f failed test

View File

@ -26,6 +26,8 @@ class Source(object):
partlines = [] partlines = []
if isinstance(part, Source): if isinstance(part, Source):
partlines = part.lines partlines = part.lines
elif isinstance(part, (tuple, list)):
partlines = [x.rstrip("\n") for x in part]
elif isinstance(part, py.builtin._basestring): elif isinstance(part, py.builtin._basestring):
partlines = part.split('\n') partlines = part.split('\n')
if rstrip: if rstrip:
@ -172,7 +174,9 @@ class Source(object):
try: try:
#compile(source+'\n', "x", "exec") #compile(source+'\n', "x", "exec")
syntax_checker(source+'\n') syntax_checker(source+'\n')
except SyntaxError: except KeyboardInterrupt:
raise
except Exception:
return False return False
else: else:
return True return True

View File

@ -110,7 +110,7 @@ class TmpTestdir:
def _makefile(self, ext, args, kwargs): def _makefile(self, ext, args, kwargs):
items = list(kwargs.items()) items = list(kwargs.items())
if args: if args:
source = "\n".join(map(str, args)) source = "\n".join(map(str, args)) + "\n"
basename = self.request.function.__name__ basename = self.request.function.__name__
items.insert(0, (basename, source)) items.insert(0, (basename, source))
ret = None ret = None
@ -294,8 +294,10 @@ class TmpTestdir:
ret = popen.wait() ret = popen.wait()
f1.close() f1.close()
f2.close() f2.close()
out = p1.read("rb").decode("utf-8").splitlines() out = p1.read("rb")
err = p2.read("rb").decode("utf-8").splitlines() out = getdecoded(out).splitlines()
err = p2.read("rb")
err = getdecoded(err).splitlines()
def dump_lines(lines, fp): def dump_lines(lines, fp):
try: try:
for line in lines: for line in lines:
@ -360,6 +362,13 @@ class TmpTestdir:
child.timeout = expect_timeout child.timeout = expect_timeout
return child return child
def getdecoded(out):
try:
return out.decode("utf-8")
except UnicodeDecodeError:
return "INTERNAL not-utf8-decodeable, truncated string:\n%s" % (
py.io.saferepr(out),)
class PseudoPlugin: class PseudoPlugin:
def __init__(self, vars): def __init__(self, vars):
self.__dict__.update(vars) self.__dict__.update(vars)

View File

@ -36,6 +36,19 @@ def test_source_from_function():
source = py.code.Source(test_source_str_function) source = py.code.Source(test_source_str_function)
assert str(source).startswith('def test_source_str_function():') assert str(source).startswith('def test_source_str_function():')
def test_source_from_method():
class TestClass:
def test_method(self):
pass
source = py.code.Source(TestClass().test_method)
assert source.lines == ["def test_method(self):",
" pass"]
def test_source_from_lines():
lines = ["a \n", "b\n", "c"]
source = py.code.Source(lines)
assert source.lines == ['a ', 'b', 'c']
def test_source_from_inner_function(): def test_source_from_inner_function():
def f(): def f():
pass pass
@ -92,6 +105,7 @@ def test_isparseable():
assert Source(" \nif 1:\n pass").isparseable() assert Source(" \nif 1:\n pass").isparseable()
assert not Source("if 1:\n").isparseable() assert not Source("if 1:\n").isparseable()
assert not Source(" \nif 1:\npass").isparseable() assert not Source(" \nif 1:\npass").isparseable()
assert not Source(chr(0)).isparseable()
class TestAccesses: class TestAccesses:
source = Source("""\ source = Source("""\