Skip to content

Commit 14bc3c4

Browse files
committed
Fix pastebin when captured output contains non-ascii characters
Fix pytest-dev#1219
1 parent 7232b45 commit 14bc3c4

File tree

3 files changed

+43
-9
lines changed

3 files changed

+43
-9
lines changed

CHANGELOG

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
- fix #1198: ``--pastebin`` option now works on Python 3. Thanks
1010
Mehdy Khoshnoody for the PR.
1111

12+
- fix #1219: ``--pastebin`` now works correctly when captured output contains
13+
non-ascii characters. Thanks Bruno Oliveira for the PR.
14+
1215
- fix #1204: another error when collecting with a nasty __getattr__().
1316
Thanks Florian Bruhin for the PR.
1417

_pytest/pastebin.py

+9-5
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,21 @@ def pytest_addoption(parser):
1313

1414
@pytest.hookimpl(trylast=True)
1515
def pytest_configure(config):
16+
import py
1617
if config.option.pastebin == "all":
1718
tr = config.pluginmanager.getplugin('terminalreporter')
1819
# if no terminal reporter plugin is present, nothing we can do here;
1920
# this can happen when this function executes in a slave node
2021
# when using pytest-xdist, for example
2122
if tr is not None:
22-
config._pastebinfile = tempfile.TemporaryFile('w+')
23+
# pastebin file will be utf-8 encoded binary file
24+
config._pastebinfile = tempfile.TemporaryFile('w+b')
2325
oldwrite = tr._tw.write
2426
def tee_write(s, **kwargs):
2527
oldwrite(s, **kwargs)
26-
config._pastebinfile.write(str(s))
28+
if py.builtin._istext(s):
29+
s = s.encode('utf-8')
30+
config._pastebinfile.write(s)
2731
tr._tw.write = tee_write
2832

2933
def pytest_unconfigure(config):
@@ -45,7 +49,7 @@ def create_new_paste(contents):
4549
"""
4650
Creates a new paste using bpaste.net service.
4751
48-
:contents: paste contents
52+
:contents: paste contents as utf-8 encoded bytes
4953
:returns: url to the pasted contents
5054
"""
5155
import re
@@ -61,8 +65,8 @@ def create_new_paste(contents):
6165
'expiry': '1week',
6266
}
6367
url = 'https://bpaste.net'
64-
response = urlopen(url, data=urlencode(params).encode()).read()
65-
m = re.search(r'href="/raw/(\w+)"', response.decode())
68+
response = urlopen(url, data=urlencode(params).encode('ascii')).read()
69+
m = re.search(r'href="/raw/(\w+)"', response.decode('utf-8'))
6670
if m:
6771
return '%s/show/%s' % (url, m.group(1))
6872
else:

testing/test_pastebin.py

+31-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# encoding: utf-8
12
import sys
23
import pytest
34

@@ -27,6 +28,7 @@ def test_skip():
2728
assert reprec.countoutcomes() == [1,1,1]
2829

2930
def test_all(self, testdir, pastebinlist):
31+
from _pytest.pytester import LineMatcher
3032
testpath = testdir.makepyfile("""
3133
import pytest
3234
def test_pass():
@@ -39,9 +41,34 @@ def test_skip():
3941
reprec = testdir.inline_run(testpath, "--pastebin=all", '-v')
4042
assert reprec.countoutcomes() == [1,1,1]
4143
assert len(pastebinlist) == 1
42-
s = pastebinlist[0]
43-
for x in 'test_fail test_skip test_pass'.split():
44-
assert x in s
44+
contents = pastebinlist[0].decode('utf-8')
45+
matcher = LineMatcher(contents.splitlines())
46+
matcher.fnmatch_lines([
47+
'*test_pass PASSED*',
48+
'*test_fail FAILED*',
49+
'*test_skip SKIPPED*',
50+
'*== 1 failed, 1 passed, 1 skipped in *'
51+
])
52+
53+
def test_non_ascii_paste_text(self, testdir):
54+
"""Make sure that text which contains non-ascii characters is pasted
55+
correctly. See #1219.
56+
"""
57+
testdir.makepyfile(test_unicode="""
58+
# encoding: utf-8
59+
def test():
60+
assert '☺' == 1
61+
""")
62+
result = testdir.runpytest('--pastebin=all')
63+
if sys.version_info[0] == 3:
64+
expected_msg = "*assert '☺' == 1*"
65+
else:
66+
expected_msg = "*assert '\\xe2\\x98\\xba' == 1*"
67+
result.stdout.fnmatch_lines([
68+
expected_msg,
69+
"*== 1 failed in *",
70+
'*Sending information to Paste Service*',
71+
])
4572

4673

4774
class TestPaste:
@@ -74,7 +101,7 @@ def read(self):
74101
return calls
75102

76103
def test_create_new_paste(self, pastebin, mocked_urlopen):
77-
result = pastebin.create_new_paste('full-paste-contents')
104+
result = pastebin.create_new_paste(b'full-paste-contents')
78105
assert result == 'https://bpaste.net/show/3c0c6750bd'
79106
assert len(mocked_urlopen) == 1
80107
url, data = mocked_urlopen[0]

0 commit comments

Comments
 (0)