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

Code before:
        )
    else:
        raise LookupError(requested_mark)
    return mark


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

    @classmethod
    def param(
        cls,
        *values: object,
        marks: MarkDecorator | Collection[MarkDecorator | Mark] = (),
        id: str | 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 "
                "https://github.com/pytest-dev/pytest/issues/4112"
            )

        if id is not None:
            if not isinstance(id, str):
                raise TypeError(f"Expected id to be a string, got {type(id)}: {id!r}")
            id = ascii_escaped(id)
        return cls(values, marks, id)

    @classmethod
    def extract_from(
        cls,
        parameterset: ParameterSet | Sequence[object] | object,
        force_tuple: bool = False,
    ) -> ParameterSet:
        """Extract from an object or objects.

        :param parameterset:
            A legacy style parameterset that may or may not be a tuple,
            and may or may not be wrapped into a mess of mark objects.

        :param force_tuple:
            Enforce tuple wrapping so single argument tuple values
            don't get decomposed and break tests.
        """
        if isinstance(parameterset, cls):

Review comment (suggestion):
```suggestion
                "https://docs.pytest.org/en/stable/reference/reference.html#pytest-param"
```

Code after:
        )
    else:
        raise LookupError(requested_mark)
    return mark


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

    @classmethod
    def param(
        cls,
        *values: object,
        marks: MarkDecorator | Collection[MarkDecorator | Mark] = (),
        id: str | 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 "
                "https://docs.pytest.org/en/stable/reference/reference.html#pytest-param"
            )

        if id is not None:
            if not isinstance(id, str):
                raise TypeError(f"Expected id to be a string, got {type(id)}: {id!r}")
            id = ascii_escaped(id)
        return cls(values, marks, id)

    @classmethod
    def extract_from(
        cls,
        parameterset: ParameterSet | Sequence[object] | object,
        force_tuple: bool = False,
    ) -> ParameterSet:
        """Extract from an object or objects.

        :param parameterset:
            A legacy style parameterset that may or may not be a tuple,
            and may or may not be wrapped into a mess of mark objects.

        :param force_tuple:
            Enforce tuple wrapping so single argument tuple values
            don't get decomposed and break tests.
        """
        if isinstance(parameterset, cls):