Require id=... to be a string

This was documented before, but never enforced.  Passing non-strings could
have strange side-effects and enforcing a string simplifies other
implementation.
This commit is contained in:
Anthony Sottile 2018-11-18 14:16:13 -08:00
parent 3d92d5a659
commit 8395b9e25d
2 changed files with 31 additions and 12 deletions

View File

@ -5,6 +5,7 @@ from functools import reduce
from operator import attrgetter from operator import attrgetter
import attr import attr
import six
from six.moves import map from six.moves import map
from ..compat import getfslineno from ..compat import getfslineno
@ -70,10 +71,12 @@ class ParameterSet(namedtuple("ParameterSet", "values, marks, id")):
else: else:
assert isinstance(marks, (tuple, list, set)) assert isinstance(marks, (tuple, list, set))
def param_extract_id(id=None): id_ = kw.pop("id", None)
return id if id_ is not None:
if not isinstance(id_, six.string_types):
id_ = param_extract_id(**kw) raise TypeError(
"Expected id to be a string, got {}: {!r}".format(type(id_), id_)
)
return cls(values, marks, id_) return cls(values, marks, id_)
@classmethod @classmethod

View File

@ -5,20 +5,21 @@ from __future__ import print_function
import os import os
import sys import sys
import six
import pytest
from _pytest.mark import EMPTY_PARAMETERSET_OPTION
from _pytest.mark import MarkGenerator as Mark
from _pytest.mark import ParameterSet
from _pytest.mark import transfer_markers
from _pytest.nodes import Collector
from _pytest.nodes import Node
from _pytest.warnings import SHOW_PYTEST_WARNINGS_ARG from _pytest.warnings import SHOW_PYTEST_WARNINGS_ARG
try: try:
import mock import mock
except ImportError: except ImportError:
import unittest.mock as mock import unittest.mock as mock
import pytest
from _pytest.mark import (
MarkGenerator as Mark,
ParameterSet,
transfer_markers,
EMPTY_PARAMETERSET_OPTION,
)
from _pytest.nodes import Node, Collector
ignore_markinfo = pytest.mark.filterwarnings( ignore_markinfo = pytest.mark.filterwarnings(
"ignore:MarkInfo objects:pytest.RemovedInPytest4Warning" "ignore:MarkInfo objects:pytest.RemovedInPytest4Warning"
@ -1252,3 +1253,18 @@ def test_markers_from_parametrize(testdir):
result = testdir.runpytest(SHOW_PYTEST_WARNINGS_ARG) result = testdir.runpytest(SHOW_PYTEST_WARNINGS_ARG)
result.assert_outcomes(passed=4) result.assert_outcomes(passed=4)
def test_pytest_param_id_requires_string():
with pytest.raises(TypeError) as excinfo:
pytest.param(id=True)
msg, = excinfo.value.args
if six.PY2:
assert msg == "Expected id to be a string, got <type 'bool'>: True"
else:
assert msg == "Expected id to be a string, got <class 'bool'>: True"
@pytest.mark.parametrize("s", (None, "hello world"))
def test_pytest_param_id_allows_none_or_string(s):
assert pytest.param(id=s)