Fix decode error in Python 2.7 when docstrings contain a non-ascii character
Fix #628
This commit is contained in:
parent
29b05c8391
commit
3c19cfcd9a
|
@ -19,6 +19,9 @@
|
||||||
properly displayed.
|
properly displayed.
|
||||||
Thanks Ionel Maries Cristian for the report and Bruno Oliveira for the PR.
|
Thanks Ionel Maries Cristian for the report and Bruno Oliveira for the PR.
|
||||||
|
|
||||||
|
- fix #628: fixed internal UnicodeDecodeError when doctests contain unicode.
|
||||||
|
Thanks Jason R. Coombs for the report and Bruno Oliveira for the PR.
|
||||||
|
|
||||||
|
|
||||||
2.8.5
|
2.8.5
|
||||||
-----
|
-----
|
||||||
|
|
|
@ -81,15 +81,15 @@ class DoctestItem(pytest.Item):
|
||||||
reprlocation = ReprFileLocation(filename, lineno, message)
|
reprlocation = ReprFileLocation(filename, lineno, message)
|
||||||
checker = _get_unicode_checker()
|
checker = _get_unicode_checker()
|
||||||
REPORT_UDIFF = doctest.REPORT_UDIFF
|
REPORT_UDIFF = doctest.REPORT_UDIFF
|
||||||
filelines = py.path.local(filename).readlines(cr=0)
|
|
||||||
lines = []
|
|
||||||
if lineno is not None:
|
if lineno is not None:
|
||||||
i = max(test.lineno, max(0, lineno - 10)) # XXX?
|
lines = doctestfailure.test.docstring.splitlines(False)
|
||||||
for line in filelines[i:lineno]:
|
# add line numbers to the left of the error message
|
||||||
lines.append("%03d %s" % (i+1, line))
|
lines = ["%03d %s" % (i + test.lineno + 1, x)
|
||||||
i += 1
|
for (i, x) in enumerate(lines)]
|
||||||
|
# trim docstring error lines to 10
|
||||||
|
lines = lines[example.lineno - 9:example.lineno + 1]
|
||||||
else:
|
else:
|
||||||
lines.append('EXAMPLE LOCATION UNKNOWN, not showing all tests of that example')
|
lines = ['EXAMPLE LOCATION UNKNOWN, not showing all tests of that example']
|
||||||
indent = '>>>'
|
indent = '>>>'
|
||||||
for line in example.source.splitlines():
|
for line in example.source.splitlines():
|
||||||
lines.append('??? %s %s' % (indent, line))
|
lines.append('??? %s %s' % (indent, line))
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
# encoding: utf-8
|
||||||
import sys
|
import sys
|
||||||
from _pytest.doctest import DoctestItem, DoctestModule, DoctestTextfile
|
from _pytest.doctest import DoctestItem, DoctestModule, DoctestTextfile
|
||||||
import py
|
import py
|
||||||
|
@ -109,6 +110,46 @@ class TestDoctests:
|
||||||
"*UNEXPECTED*ZeroDivision*",
|
"*UNEXPECTED*ZeroDivision*",
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def test_docstring_context_around_error(self, testdir):
|
||||||
|
"""Test that we show some context before the actual line of a failing
|
||||||
|
doctest.
|
||||||
|
"""
|
||||||
|
testdir.makepyfile('''
|
||||||
|
def foo():
|
||||||
|
"""
|
||||||
|
text-line-1
|
||||||
|
text-line-2
|
||||||
|
text-line-3
|
||||||
|
text-line-4
|
||||||
|
text-line-5
|
||||||
|
text-line-6
|
||||||
|
text-line-7
|
||||||
|
text-line-8
|
||||||
|
text-line-9
|
||||||
|
text-line-10
|
||||||
|
text-line-11
|
||||||
|
>>> 1 + 1
|
||||||
|
3
|
||||||
|
|
||||||
|
text-line-after
|
||||||
|
"""
|
||||||
|
''')
|
||||||
|
result = testdir.runpytest('--doctest-modules')
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
'*docstring_context_around_error*',
|
||||||
|
'005*text-line-3',
|
||||||
|
'006*text-line-4',
|
||||||
|
'013*text-line-11',
|
||||||
|
'014*>>> 1 + 1',
|
||||||
|
'Expected:',
|
||||||
|
' 3',
|
||||||
|
'Got:',
|
||||||
|
' 2',
|
||||||
|
])
|
||||||
|
# lines below should be trimmed out
|
||||||
|
assert 'text-line-2' not in result.stdout.str()
|
||||||
|
assert 'text-line-after' not in result.stdout.str()
|
||||||
|
|
||||||
def test_doctest_linedata_missing(self, testdir):
|
def test_doctest_linedata_missing(self, testdir):
|
||||||
testdir.tmpdir.join('hello.py').write(py.code.Source("""
|
testdir.tmpdir.join('hello.py').write(py.code.Source("""
|
||||||
class Fun(object):
|
class Fun(object):
|
||||||
|
@ -339,6 +380,23 @@ class TestDoctests:
|
||||||
reprec = testdir.inline_run(p, "--doctest-glob=x*.txt")
|
reprec = testdir.inline_run(p, "--doctest-glob=x*.txt")
|
||||||
reprec.assertoutcome(failed=1, passed=0)
|
reprec.assertoutcome(failed=1, passed=0)
|
||||||
|
|
||||||
|
def test_contains_unicode(self, testdir):
|
||||||
|
"""Fix internal error with docstrings containing non-ascii characters.
|
||||||
|
"""
|
||||||
|
testdir.makepyfile(u'''
|
||||||
|
# encoding: utf-8
|
||||||
|
def foo():
|
||||||
|
"""
|
||||||
|
>>> name = 'с' # not letter 'c' but instead Cyrillic 's'.
|
||||||
|
'anything'
|
||||||
|
"""
|
||||||
|
''')
|
||||||
|
result = testdir.runpytest('--doctest-modules')
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
'Got nothing',
|
||||||
|
'* 1 failed in*',
|
||||||
|
])
|
||||||
|
|
||||||
def test_ignore_import_errors_on_doctest(self, testdir):
|
def test_ignore_import_errors_on_doctest(self, testdir):
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
import asdf
|
import asdf
|
||||||
|
@ -579,4 +637,4 @@ class TestDoctestAutoUseFixtures:
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest('--doctest-modules')
|
result = testdir.runpytest('--doctest-modules')
|
||||||
assert 'FAILURES' not in str(result.stdout.str())
|
assert 'FAILURES' not in str(result.stdout.str())
|
||||||
result.stdout.fnmatch_lines(['*=== 1 passed in *'])
|
result.stdout.fnmatch_lines(['*=== 1 passed in *'])
|
||||||
|
|
Loading…
Reference in New Issue