Merge pull request #1318 from nicoddemus/doctest-unicode-error

Fix decode error in Python 2.7 when docstrings contain a non-ascii character
This commit is contained in:
Ronny Pfannschmidt 2016-01-11 08:37:24 +01:00
commit b2c0864fbf
3 changed files with 69 additions and 8 deletions

View File

@ -23,6 +23,9 @@
properly displayed.
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
-----

View File

@ -81,15 +81,15 @@ class DoctestItem(pytest.Item):
reprlocation = ReprFileLocation(filename, lineno, message)
checker = _get_unicode_checker()
REPORT_UDIFF = doctest.REPORT_UDIFF
filelines = py.path.local(filename).readlines(cr=0)
lines = []
if lineno is not None:
i = max(test.lineno, max(0, lineno - 10)) # XXX?
for line in filelines[i:lineno]:
lines.append("%03d %s" % (i+1, line))
i += 1
lines = doctestfailure.test.docstring.splitlines(False)
# add line numbers to the left of the error message
lines = ["%03d %s" % (i + test.lineno + 1, x)
for (i, x) in enumerate(lines)]
# trim docstring error lines to 10
lines = lines[example.lineno - 9:example.lineno + 1]
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 = '>>>'
for line in example.source.splitlines():
lines.append('??? %s %s' % (indent, line))

View File

@ -1,3 +1,4 @@
# encoding: utf-8
import sys
from _pytest.doctest import DoctestItem, DoctestModule, DoctestTextfile
import py
@ -109,6 +110,46 @@ class TestDoctests:
"*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):
testdir.tmpdir.join('hello.py').write(py.code.Source("""
class Fun(object):
@ -339,6 +380,23 @@ class TestDoctests:
reprec = testdir.inline_run(p, "--doctest-glob=x*.txt")
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):
p = testdir.makepyfile("""
import asdf
@ -579,4 +637,4 @@ class TestDoctestAutoUseFixtures:
""")
result = testdir.runpytest('--doctest-modules')
assert 'FAILURES' not in str(result.stdout.str())
result.stdout.fnmatch_lines(['*=== 1 passed in *'])
result.stdout.fnmatch_lines(['*=== 1 passed in *'])