From 3d92d5a6595a6f5df5849e5355a8dbd6bda9843d Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sun, 18 Nov 2018 14:32:32 -0800 Subject: [PATCH] Make sure parametrize ids are printable --- src/_pytest/compat.py | 21 ++++++++++++++++----- testing/python/metafunc.py | 22 +++++++++++++++++----- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index ead9ffd8d..87d4d51c1 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -182,6 +182,15 @@ def get_default_arg_names(function): ) +_non_printable_ascii_translate_table = { + i: u"\\x{:02x}".format(i) for i in range(128) if i not in range(32, 127) +} + + +def _translate_non_printable(s): + return s.translate(_non_printable_ascii_translate_table) + + if _PY3: STRING_TYPES = bytes, str UNICODE_TYPES = six.text_type @@ -221,9 +230,10 @@ if _PY3: """ if isinstance(val, bytes): - return _bytes_to_ascii(val) + ret = _bytes_to_ascii(val) else: - return val.encode("unicode_escape").decode("ascii") + ret = val.encode("unicode_escape").decode("ascii") + return _translate_non_printable(ret) else: @@ -241,11 +251,12 @@ else: """ if isinstance(val, bytes): try: - return val.encode("ascii") + ret = val.decode("ascii") except UnicodeDecodeError: - return val.encode("string-escape") + ret = val.encode("string-escape").decode("ascii") else: - return val.encode("unicode-escape") + ret = val.encode("unicode-escape").decode("ascii") + return _translate_non_printable(ret) class _PytestWrapper(object): diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 1a9cbf408..605814e65 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -5,6 +5,7 @@ import textwrap import attr import hypothesis +import six from hypothesis import strategies import pytest @@ -262,11 +263,8 @@ class TestMetafunc(object): from _pytest.python import _idval escaped = _idval(value, "a", 6, None, item=None, config=None) - assert isinstance(escaped, str) - if PY3: - escaped.encode("ascii") - else: - escaped.decode("ascii") + assert isinstance(escaped, six.text_type) + escaped.encode("ascii") def test_unicode_idval(self): """This tests that Unicode strings outside the ASCII character set get @@ -382,6 +380,20 @@ class TestMetafunc(object): "\\xc3\\xb4-other", ] + def test_idmaker_non_printable_characters(self): + from _pytest.python import idmaker + + result = idmaker( + ("s", "n"), + [ + pytest.param("\x00", 1), + pytest.param("\x05", 2), + pytest.param(b"\x00", 3), + pytest.param(b"\x05", 4), + ], + ) + assert result == ["\\x00-1", "\\x05-2", "\\x00-3", "\\x05-4"] + def test_idmaker_enum(self): from _pytest.python import idmaker