Skip to content

Param ids fix #1092

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 1, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
2.8.2.dev
---------

- fix #1085: proper handling of encoding errors when passing encoded byte
strings to pytest.parametrize in Python 2.
Thanks Themanwithoutaplan for the report and Bruno Oliveira for the PR.

- fix #1087: handling SystemError when passing empty byte strings to
pytest.parametrize in Python 3.
Thanks Paul Kehrer for the report and Bruno Oliveira for the PR.

- fix #995: fixed internal error when filtering tracebacks where one entry
was generated by an exec() statement.
Thanks Daniel Hahler, Ashley C Straw, Philippe Gauthier and Pavel Savchenko
Expand Down
19 changes: 12 additions & 7 deletions _pytest/python.py
Original file line number Diff line number Diff line change
Expand Up @@ -1048,6 +1048,8 @@ def addcall(self, funcargs=None, id=_notexists, param=_notexists):


if _PY3:
import codecs

def _escape_bytes(val):
"""
If val is pure ascii, returns it as a str(), otherwise escapes
Expand All @@ -1060,18 +1062,21 @@ def _escape_bytes(val):
want to return escaped bytes for any byte, even if they match
a utf-8 string.
"""
# source: http://goo.gl/bGsnwC
import codecs
encoded_bytes, _ = codecs.escape_encode(val)
return encoded_bytes.decode('ascii')
if val:
# source: http://goo.gl/bGsnwC
encoded_bytes, _ = codecs.escape_encode(val)
return encoded_bytes.decode('ascii')
else:
# empty bytes crashes codecs.escape_encode (#1087)
return ''
else:
def _escape_bytes(val):
"""
In py2 bytes and str are the same, so return it unchanged if it
In py2 bytes and str are the same type, so return it unchanged if it
is a full ascii string, otherwise escape it into its binary form.
"""
try:
return val.encode('ascii')
return val.decode('ascii')
except UnicodeDecodeError:
return val.encode('string-escape')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

im not 100% sure off-hand is string-escape correctly used that way?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems so:

Python 2.7.10 (default, May 23 2015, 09:40:32) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> u'ação'
u'a\xe7\xe3o'
>>> u'ação'.encode('utf-8')
'a\xc3\xa7\xc3\xa3o'
>>> s=_
>>> s.encode('string-escape')
'a\\xc3\\xa7\\xc3\\xa3o'


Expand Down Expand Up @@ -1100,7 +1105,7 @@ def _idval(val, argname, idx, idfn):
# convertible to ascii, return it as an str() object instead
try:
return str(val)
except UnicodeDecodeError:
except UnicodeError:
# fallthrough
pass
return str(argname)+str(idx)
Expand Down
36 changes: 36 additions & 0 deletions testing/python/metafunc.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
import re

import pytest, py
Expand Down Expand Up @@ -118,6 +119,41 @@ class A:
assert metafunc._calls[2].id == "x1-a"
assert metafunc._calls[3].id == "x1-b"

@pytest.mark.skipif('sys.version_info[0] >= 3')
def test_unicode_idval_python2(self):
"""unittest for the expected behavior to obtain ids for parametrized
unicode values in Python 2: if convertible to ascii, they should appear
as ascii values, otherwise fallback to hide the value behind the name
of the parametrized variable name. #1086
"""
from _pytest.python import _idval
values = [
(u'', ''),
(u'ascii', 'ascii'),
(u'ação', 'a6'),
(u'josé@blah.com', 'a6'),
(u'δοκ.ιμή@παράδειγμα.δοκιμή', 'a6'),
]
for val, expected in values:
assert _idval(val, 'a', 6, None) == expected

def test_bytes_idval(self):
"""unittest for the expected behavior to obtain ids for parametrized
bytes values:
- python2: non-ascii strings are considered bytes and formatted using
"binary escape", where any byte < 127 is escaped into its hex form.
- python3: bytes objects are always escaped using "binary escape".
"""
from _pytest.python import _idval
values = [
(b'', ''),
(b'\xc3\xb4\xff\xe4', '\\xc3\\xb4\\xff\\xe4'),
(b'ascii', 'ascii'),
(u'αρά'.encode('utf-8'), '\\xce\\xb1\\xcf\\x81\\xce\\xac'),
]
for val, expected in values:
assert _idval(val, 'a', 6, None) == expected

@pytest.mark.issue250
def test_idmaker_autoname(self):
from _pytest.python import idmaker
Expand Down