Repository: pytest-dev/pytest
File: src/_pytest/mark/structures.py (Python)

Code before:
    config: Config, argnames: Sequence[str], func
) -> MarkDecorator:
    from ..nodes import Collector

    argslisting = ", ".join(argnames)

    fs, lineno = getfslineno(func)
    reason = f"got empty parameter set for ({argslisting})"
    requested_mark = config.getini(EMPTY_PARAMETERSET_OPTION)
    if requested_mark in ("", None, "skip"):
        mark = MARK_GEN.skip(reason=reason)
    elif requested_mark == "xfail":
        mark = MARK_GEN.xfail(reason=reason, run=False)
    elif requested_mark == "fail_at_collect":
        raise Collector.CollectError(
            f"Empty parameter set in '{func.__name__}' at line {lineno + 1}"
        )
    else:
        raise LookupError(requested_mark)
    return mark


# Singleton type for HIDDEN_PARAM, as described in:
# https://www.python.org/dev/peps/pep-0484/#support-for-singleton-types-in-unions
class _HiddenParam(enum.Enum):
    token = 0


#: Can be used as a parameter set id to hide it from the test name.
HIDDEN_PARAM = _HiddenParam.token


class ParameterSet(NamedTuple):
    values: Sequence[object | NotSetType]
    marks: Collection[MarkDecorator | Mark]
    id: str | _HiddenParam | None

    @classmethod
    def param(
        cls,
        *values: object,
        marks: MarkDecorator | Collection[MarkDecorator | Mark] = (),
        id: str | _HiddenParam | None = None,
    ) -> ParameterSet:
        if isinstance(marks, MarkDecorator):
            marks = (marks,)
        else:
            assert isinstance(marks, collections.abc.Collection)
        if any(i.name == "usefixtures" for i in marks):
            raise ValueError(
                "pytest.param cannot add pytest.mark.usefixtures; see "

Review comment (bug):
An arbitrary integer feels wrong here. Why can't it be a new object?
```suggestion
    token = object()
```

Code after:

#: Can be used as a parameter set id to hide it from the test name.
HIDDEN_PARAM = _HiddenParam.token


def istestfunc(func) -> bool:
    return callable(func) and getattr(func, "__name__", "<lambda>") != "<lambda>"


def get_empty_parameterset_mark(
    config: Config, argnames: Sequence[str], func
) -> MarkDecorator:
    from ..nodes import Collector

    argslisting = ", ".join(argnames)

    fs, lineno = getfslineno(func)
    reason = f"got empty parameter set for ({argslisting})"
    requested_mark = config.getini(EMPTY_PARAMETERSET_OPTION)
    if requested_mark in ("", None, "skip"):
        mark = MARK_GEN.skip(reason=reason)
    elif requested_mark == "xfail":
        mark = MARK_GEN.xfail(reason=reason, run=False)
    elif requested_mark == "fail_at_collect":
        raise Collector.CollectError(
            f"Empty parameter set in '{func.__name__}' at line {lineno + 1}"
        )
    else:
        raise LookupError(requested_mark)
    return mark


class ParameterSet(NamedTuple):
    values: Sequence[object | NotSetType]
    marks: Collection[MarkDecorator | Mark]
    id: str | _HiddenParam | None

    @classmethod
    def param(
        cls,
        *values: object,
        marks: MarkDecorator | Collection[MarkDecorator | Mark] = (),
        id: str | _HiddenParam | None = None,
    ) -> ParameterSet:
        if isinstance(marks, MarkDecorator):
            marks = (marks,)
        else:
            assert isinstance(marks, collections.abc.Collection)
        if any(i.name == "usefixtures" for i in marks):
            raise ValueError(
                "pytest.param cannot add pytest.mark.usefixtures; see "