From 2598ef1d0aee359b4b6d5fdd1758916d5907d04f Mon Sep 17 00:00:00 2001
From: shadchin <shadchin@yandex-team.ru>
Date: Thu, 10 Feb 2022 16:44:30 +0300
Subject: Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit
 1 of 2.

---
 .../python/pytest/py3/_pytest/mark/structures.py   | 812 ++++++++++-----------
 1 file changed, 406 insertions(+), 406 deletions(-)

(limited to 'contrib/python/pytest/py3/_pytest/mark/structures.py')

diff --git a/contrib/python/pytest/py3/_pytest/mark/structures.py b/contrib/python/pytest/py3/_pytest/mark/structures.py
index f5736a4c1c..fb87c0a774 100644
--- a/contrib/python/pytest/py3/_pytest/mark/structures.py
+++ b/contrib/python/pytest/py3/_pytest/mark/structures.py
@@ -1,197 +1,197 @@
-import collections.abc
+import collections.abc 
 import inspect
 import warnings
-from typing import Any
-from typing import Callable
-from typing import Collection
-from typing import Iterable
-from typing import Iterator
-from typing import List
-from typing import Mapping
-from typing import MutableMapping
-from typing import NamedTuple
-from typing import Optional
-from typing import overload
-from typing import Sequence
-from typing import Set
-from typing import Tuple
-from typing import Type
-from typing import TYPE_CHECKING
-from typing import TypeVar
-from typing import Union
+from typing import Any 
+from typing import Callable 
+from typing import Collection 
+from typing import Iterable 
+from typing import Iterator 
+from typing import List 
+from typing import Mapping 
+from typing import MutableMapping 
+from typing import NamedTuple 
+from typing import Optional 
+from typing import overload 
+from typing import Sequence 
+from typing import Set 
+from typing import Tuple 
+from typing import Type 
+from typing import TYPE_CHECKING 
+from typing import TypeVar 
+from typing import Union 
 
 import attr
 
-from .._code import getfslineno
-from ..compat import ascii_escaped
-from ..compat import final
+from .._code import getfslineno 
+from ..compat import ascii_escaped 
+from ..compat import final 
 from ..compat import NOTSET
-from ..compat import NotSetType
-from _pytest.config import Config
+from ..compat import NotSetType 
+from _pytest.config import Config 
 from _pytest.outcomes import fail
-from _pytest.warning_types import PytestUnknownMarkWarning
-
-if TYPE_CHECKING:
-    from ..nodes import Node
-
+from _pytest.warning_types import PytestUnknownMarkWarning 
 
+if TYPE_CHECKING: 
+    from ..nodes import Node 
+ 
+ 
 EMPTY_PARAMETERSET_OPTION = "empty_parameter_set_mark"
 
 
-def istestfunc(func) -> bool:
+def istestfunc(func) -> bool: 
     return (
         hasattr(func, "__call__")
         and getattr(func, "__name__", "<lambda>") != "<lambda>"
     )
 
 
-def get_empty_parameterset_mark(
-    config: Config, argnames: Sequence[str], func
-) -> "MarkDecorator":
+def get_empty_parameterset_mark( 
+    config: Config, argnames: Sequence[str], func 
+) -> "MarkDecorator": 
     from ..nodes import Collector
 
-    fs, lineno = getfslineno(func)
-    reason = "got empty parameter set %r, function %s at %s:%d" % (
-        argnames,
-        func.__name__,
-        fs,
-        lineno,
-    )
-
+    fs, lineno = getfslineno(func) 
+    reason = "got empty parameter set %r, function %s at %s:%d" % ( 
+        argnames, 
+        func.__name__, 
+        fs, 
+        lineno, 
+    ) 
+ 
     requested_mark = config.getini(EMPTY_PARAMETERSET_OPTION)
     if requested_mark in ("", None, "skip"):
-        mark = MARK_GEN.skip(reason=reason)
+        mark = MARK_GEN.skip(reason=reason) 
     elif requested_mark == "xfail":
-        mark = MARK_GEN.xfail(reason=reason, run=False)
+        mark = MARK_GEN.xfail(reason=reason, run=False) 
     elif requested_mark == "fail_at_collect":
         f_name = func.__name__
         _, lineno = getfslineno(func)
         raise Collector.CollectError(
-            "Empty parameter set in '%s' at line %d" % (f_name, lineno + 1)
+            "Empty parameter set in '%s' at line %d" % (f_name, lineno + 1) 
         )
     else:
         raise LookupError(requested_mark)
-    return mark
-
-
-class ParameterSet(
-    NamedTuple(
-        "ParameterSet",
-        [
-            ("values", Sequence[Union[object, NotSetType]]),
-            ("marks", Collection[Union["MarkDecorator", "Mark"]]),
-            ("id", Optional[str]),
-        ],
-    )
-):
+    return mark 
+
+
+class ParameterSet( 
+    NamedTuple( 
+        "ParameterSet", 
+        [ 
+            ("values", Sequence[Union[object, NotSetType]]), 
+            ("marks", Collection[Union["MarkDecorator", "Mark"]]), 
+            ("id", Optional[str]), 
+        ], 
+    ) 
+): 
     @classmethod
-    def param(
-        cls,
-        *values: object,
-        marks: Union["MarkDecorator", Collection[Union["MarkDecorator", "Mark"]]] = (),
-        id: Optional[str] = None,
-    ) -> "ParameterSet":
+    def param( 
+        cls, 
+        *values: object, 
+        marks: Union["MarkDecorator", Collection[Union["MarkDecorator", "Mark"]]] = (), 
+        id: Optional[str] = None, 
+    ) -> "ParameterSet": 
         if isinstance(marks, MarkDecorator):
             marks = (marks,)
         else:
-            assert isinstance(marks, collections.abc.Collection)
+            assert isinstance(marks, collections.abc.Collection) 
 
-        if id is not None:
-            if not isinstance(id, str):
-                raise TypeError(
-                    "Expected id to be a string, got {}: {!r}".format(type(id), id)
-                )
-            id = ascii_escaped(id)
-        return cls(values, marks, id)
+        if id is not None: 
+            if not isinstance(id, str): 
+                raise TypeError( 
+                    "Expected id to be a string, got {}: {!r}".format(type(id), id) 
+                ) 
+            id = ascii_escaped(id) 
+        return cls(values, marks, id) 
 
     @classmethod
-    def extract_from(
-        cls,
-        parameterset: Union["ParameterSet", Sequence[object], object],
-        force_tuple: bool = False,
-    ) -> "ParameterSet":
-        """Extract from an object or objects.
-
+    def extract_from( 
+        cls, 
+        parameterset: Union["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.
+            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.
+        :param force_tuple: 
+            Enforce tuple wrapping so single argument tuple values 
+            don't get decomposed and break tests. 
         """
 
         if isinstance(parameterset, cls):
             return parameterset
-        if force_tuple:
+        if force_tuple: 
             return cls.param(parameterset)
-        else:
-            # TODO: Refactor to fix this type-ignore. Currently the following
-            # passes type-checking but crashes:
-            #
-            #   @pytest.mark.parametrize(('x', 'y'), [1, 2])
-            #   def test_foo(x, y): pass
-            return cls(parameterset, marks=[], id=None)  # type: ignore[arg-type]
-
-    @staticmethod
-    def _parse_parametrize_args(
-        argnames: Union[str, List[str], Tuple[str, ...]],
-        argvalues: Iterable[Union["ParameterSet", Sequence[object], object]],
-        *args,
-        **kwargs,
-    ) -> Tuple[Union[List[str], Tuple[str, ...]], bool]:
+        else: 
+            # TODO: Refactor to fix this type-ignore. Currently the following 
+            # passes type-checking but crashes: 
+            # 
+            #   @pytest.mark.parametrize(('x', 'y'), [1, 2]) 
+            #   def test_foo(x, y): pass 
+            return cls(parameterset, marks=[], id=None)  # type: ignore[arg-type] 
+
+    @staticmethod 
+    def _parse_parametrize_args( 
+        argnames: Union[str, List[str], Tuple[str, ...]], 
+        argvalues: Iterable[Union["ParameterSet", Sequence[object], object]], 
+        *args, 
+        **kwargs, 
+    ) -> Tuple[Union[List[str], Tuple[str, ...]], bool]: 
         if not isinstance(argnames, (tuple, list)):
             argnames = [x.strip() for x in argnames.split(",") if x.strip()]
             force_tuple = len(argnames) == 1
         else:
             force_tuple = False
-        return argnames, force_tuple
-
-    @staticmethod
-    def _parse_parametrize_parameters(
-        argvalues: Iterable[Union["ParameterSet", Sequence[object], object]],
-        force_tuple: bool,
-    ) -> List["ParameterSet"]:
-        return [
-            ParameterSet.extract_from(x, force_tuple=force_tuple) for x in argvalues
+        return argnames, force_tuple 
+ 
+    @staticmethod 
+    def _parse_parametrize_parameters( 
+        argvalues: Iterable[Union["ParameterSet", Sequence[object], object]], 
+        force_tuple: bool, 
+    ) -> List["ParameterSet"]: 
+        return [ 
+            ParameterSet.extract_from(x, force_tuple=force_tuple) for x in argvalues 
         ]
-
-    @classmethod
-    def _for_parametrize(
-        cls,
-        argnames: Union[str, List[str], Tuple[str, ...]],
-        argvalues: Iterable[Union["ParameterSet", Sequence[object], object]],
-        func,
-        config: Config,
-        nodeid: str,
-    ) -> Tuple[Union[List[str], Tuple[str, ...]], List["ParameterSet"]]:
-        argnames, force_tuple = cls._parse_parametrize_args(argnames, argvalues)
-        parameters = cls._parse_parametrize_parameters(argvalues, force_tuple)
+ 
+    @classmethod 
+    def _for_parametrize( 
+        cls, 
+        argnames: Union[str, List[str], Tuple[str, ...]], 
+        argvalues: Iterable[Union["ParameterSet", Sequence[object], object]], 
+        func, 
+        config: Config, 
+        nodeid: str, 
+    ) -> Tuple[Union[List[str], Tuple[str, ...]], List["ParameterSet"]]: 
+        argnames, force_tuple = cls._parse_parametrize_args(argnames, argvalues) 
+        parameters = cls._parse_parametrize_parameters(argvalues, force_tuple) 
         del argvalues
 
         if parameters:
-            # Check all parameter sets have the correct number of values.
+            # Check all parameter sets have the correct number of values. 
             for param in parameters:
                 if len(param.values) != len(argnames):
-                    msg = (
-                        '{nodeid}: in "parametrize" the number of names ({names_len}):\n'
-                        "  {names}\n"
-                        "must be equal to the number of values ({values_len}):\n"
-                        "  {values}"
-                    )
-                    fail(
-                        msg.format(
-                            nodeid=nodeid,
-                            values=param.values,
-                            names=argnames,
-                            names_len=len(argnames),
-                            values_len=len(param.values),
-                        ),
-                        pytrace=False,
+                    msg = ( 
+                        '{nodeid}: in "parametrize" the number of names ({names_len}):\n' 
+                        "  {names}\n" 
+                        "must be equal to the number of values ({values_len}):\n" 
+                        "  {values}" 
                     )
+                    fail( 
+                        msg.format( 
+                            nodeid=nodeid, 
+                            values=param.values, 
+                            names=argnames, 
+                            names_len=len(argnames), 
+                            values_len=len(param.values), 
+                        ), 
+                        pytrace=False, 
+                    ) 
         else:
-            # Empty parameter set (likely computed at runtime): create a single
-            # parameter set with NOTSET values, with the "empty parameter set" mark applied to it.
+            # Empty parameter set (likely computed at runtime): create a single 
+            # parameter set with NOTSET values, with the "empty parameter set" mark applied to it. 
             mark = get_empty_parameterset_mark(config, argnames, func)
             parameters.append(
                 ParameterSet(values=(NOTSET,) * len(argnames), marks=[mark], id=None)
@@ -199,339 +199,339 @@ class ParameterSet(
         return argnames, parameters
 
 
-@final
+@final 
 @attr.s(frozen=True)
-class Mark:
-    #: Name of the mark.
+class Mark: 
+    #: Name of the mark. 
     name = attr.ib(type=str)
-    #: Positional arguments of the mark decorator.
-    args = attr.ib(type=Tuple[Any, ...])
-    #: Keyword arguments of the mark decorator.
-    kwargs = attr.ib(type=Mapping[str, Any])
-
-    #: Source Mark for ids with parametrize Marks.
-    _param_ids_from = attr.ib(type=Optional["Mark"], default=None, repr=False)
-    #: Resolved/generated ids with parametrize Marks.
-    _param_ids_generated = attr.ib(
-        type=Optional[Sequence[str]], default=None, repr=False
-    )
-
-    def _has_param_ids(self) -> bool:
-        return "ids" in self.kwargs or len(self.args) >= 4
-
-    def combined_with(self, other: "Mark") -> "Mark":
-        """Return a new Mark which is a combination of this
-        Mark and another Mark.
-
-        Combines by appending args and merging kwargs.
-
-        :param Mark other: The mark to combine with.
+    #: Positional arguments of the mark decorator. 
+    args = attr.ib(type=Tuple[Any, ...]) 
+    #: Keyword arguments of the mark decorator. 
+    kwargs = attr.ib(type=Mapping[str, Any]) 
+
+    #: Source Mark for ids with parametrize Marks. 
+    _param_ids_from = attr.ib(type=Optional["Mark"], default=None, repr=False) 
+    #: Resolved/generated ids with parametrize Marks. 
+    _param_ids_generated = attr.ib( 
+        type=Optional[Sequence[str]], default=None, repr=False 
+    ) 
+ 
+    def _has_param_ids(self) -> bool: 
+        return "ids" in self.kwargs or len(self.args) >= 4 
+ 
+    def combined_with(self, other: "Mark") -> "Mark": 
+        """Return a new Mark which is a combination of this 
+        Mark and another Mark. 
+ 
+        Combines by appending args and merging kwargs. 
+ 
+        :param Mark other: The mark to combine with. 
         :rtype: Mark
         """
         assert self.name == other.name
-
-        # Remember source of ids with parametrize Marks.
-        param_ids_from: Optional[Mark] = None
-        if self.name == "parametrize":
-            if other._has_param_ids():
-                param_ids_from = other
-            elif self._has_param_ids():
-                param_ids_from = self
-
+ 
+        # Remember source of ids with parametrize Marks. 
+        param_ids_from: Optional[Mark] = None 
+        if self.name == "parametrize": 
+            if other._has_param_ids(): 
+                param_ids_from = other 
+            elif self._has_param_ids(): 
+                param_ids_from = self 
+ 
         return Mark(
-            self.name,
-            self.args + other.args,
-            dict(self.kwargs, **other.kwargs),
-            param_ids_from=param_ids_from,
+            self.name, 
+            self.args + other.args, 
+            dict(self.kwargs, **other.kwargs), 
+            param_ids_from=param_ids_from, 
         )
 
 
-# A generic parameter designating an object to which a Mark may
-# be applied -- a test function (callable) or class.
-# Note: a lambda is not allowed, but this can't be represented.
-_Markable = TypeVar("_Markable", bound=Union[Callable[..., object], type])
-
-
+# A generic parameter designating an object to which a Mark may 
+# be applied -- a test function (callable) or class. 
+# Note: a lambda is not allowed, but this can't be represented. 
+_Markable = TypeVar("_Markable", bound=Union[Callable[..., object], type]) 
+ 
+ 
 @attr.s
-class MarkDecorator:
-    """A decorator for applying a mark on test functions and classes.
+class MarkDecorator: 
+    """A decorator for applying a mark on test functions and classes. 
 
-    MarkDecorators are created with ``pytest.mark``::
-
-        mark1 = pytest.mark.NAME              # Simple MarkDecorator
-        mark2 = pytest.mark.NAME(name1=value) # Parametrized MarkDecorator
+    MarkDecorators are created with ``pytest.mark``:: 
 
+        mark1 = pytest.mark.NAME              # Simple MarkDecorator 
+        mark2 = pytest.mark.NAME(name1=value) # Parametrized MarkDecorator 
+ 
     and can then be applied as decorators to test functions::
 
         @mark2
         def test_function():
             pass
 
-    When a MarkDecorator is called it does the following:
-
-    1. If called with a single class as its only positional argument and no
-       additional keyword arguments, it attaches the mark to the class so it
-       gets applied automatically to all test cases found in that class.
-
-    2. If called with a single function as its only positional argument and
-       no additional keyword arguments, it attaches the mark to the function,
-       containing all the arguments already stored internally in the
-       MarkDecorator.
-
-    3. When called in any other case, it returns a new MarkDecorator instance
-       with the original MarkDecorator's content updated with the arguments
-       passed to this call.
-
-    Note: The rules above prevent MarkDecorators from storing only a single
-    function or class reference as their positional argument with no
-    additional keyword or positional arguments. You can work around this by
-    using `with_args()`.
+    When a MarkDecorator is called it does the following: 
+
+    1. If called with a single class as its only positional argument and no 
+       additional keyword arguments, it attaches the mark to the class so it 
+       gets applied automatically to all test cases found in that class. 
+ 
+    2. If called with a single function as its only positional argument and 
+       no additional keyword arguments, it attaches the mark to the function, 
+       containing all the arguments already stored internally in the 
+       MarkDecorator. 
+ 
+    3. When called in any other case, it returns a new MarkDecorator instance 
+       with the original MarkDecorator's content updated with the arguments 
+       passed to this call. 
+
+    Note: The rules above prevent MarkDecorators from storing only a single 
+    function or class reference as their positional argument with no 
+    additional keyword or positional arguments. You can work around this by 
+    using `with_args()`. 
     """
 
-    mark = attr.ib(type=Mark, validator=attr.validators.instance_of(Mark))
-
-    @property
-    def name(self) -> str:
-        """Alias for mark.name."""
-        return self.mark.name
-
-    @property
-    def args(self) -> Tuple[Any, ...]:
-        """Alias for mark.args."""
-        return self.mark.args
+    mark = attr.ib(type=Mark, validator=attr.validators.instance_of(Mark)) 
 
-    @property
-    def kwargs(self) -> Mapping[str, Any]:
-        """Alias for mark.kwargs."""
-        return self.mark.kwargs
+    @property 
+    def name(self) -> str: 
+        """Alias for mark.name.""" 
+        return self.mark.name 
 
     @property
-    def markname(self) -> str:
+    def args(self) -> Tuple[Any, ...]: 
+        """Alias for mark.args.""" 
+        return self.mark.args 
+ 
+    @property 
+    def kwargs(self) -> Mapping[str, Any]: 
+        """Alias for mark.kwargs.""" 
+        return self.mark.kwargs 
+ 
+    @property 
+    def markname(self) -> str: 
         return self.name  # for backward-compat (2.4.1 had this attr)
 
-    def __repr__(self) -> str:
-        return f"<MarkDecorator {self.mark!r}>"
+    def __repr__(self) -> str: 
+        return f"<MarkDecorator {self.mark!r}>" 
 
-    def with_args(self, *args: object, **kwargs: object) -> "MarkDecorator":
-        """Return a MarkDecorator with extra arguments added.
+    def with_args(self, *args: object, **kwargs: object) -> "MarkDecorator": 
+        """Return a MarkDecorator with extra arguments added. 
 
-        Unlike calling the MarkDecorator, with_args() can be used even
-        if the sole argument is a callable/class.
+        Unlike calling the MarkDecorator, with_args() can be used even 
+        if the sole argument is a callable/class. 
 
-        :rtype: MarkDecorator
+        :rtype: MarkDecorator 
         """
         mark = Mark(self.name, args, kwargs)
         return self.__class__(self.mark.combined_with(mark))
 
-    # Type ignored because the overloads overlap with an incompatible
-    # return type. Not much we can do about that. Thankfully mypy picks
-    # the first match so it works out even if we break the rules.
-    @overload
-    def __call__(self, arg: _Markable) -> _Markable:  # type: ignore[misc]
-        pass
-
-    @overload
-    def __call__(self, *args: object, **kwargs: object) -> "MarkDecorator":
-        pass
-
-    def __call__(self, *args: object, **kwargs: object):
-        """Call the MarkDecorator."""
+    # Type ignored because the overloads overlap with an incompatible 
+    # return type. Not much we can do about that. Thankfully mypy picks 
+    # the first match so it works out even if we break the rules. 
+    @overload 
+    def __call__(self, arg: _Markable) -> _Markable:  # type: ignore[misc] 
+        pass 
+ 
+    @overload 
+    def __call__(self, *args: object, **kwargs: object) -> "MarkDecorator": 
+        pass 
+ 
+    def __call__(self, *args: object, **kwargs: object): 
+        """Call the MarkDecorator.""" 
         if args and not kwargs:
             func = args[0]
             is_class = inspect.isclass(func)
             if len(args) == 1 and (istestfunc(func) or is_class):
-                store_mark(func, self.mark)
+                store_mark(func, self.mark) 
                 return func
         return self.with_args(*args, **kwargs)
 
 
-def get_unpacked_marks(obj) -> List[Mark]:
-    """Obtain the unpacked marks that are stored on an object."""
+def get_unpacked_marks(obj) -> List[Mark]: 
+    """Obtain the unpacked marks that are stored on an object.""" 
     mark_list = getattr(obj, "pytestmark", [])
     if not isinstance(mark_list, list):
         mark_list = [mark_list]
     return normalize_mark_list(mark_list)
 
 
-def normalize_mark_list(mark_list: Iterable[Union[Mark, MarkDecorator]]) -> List[Mark]:
-    """Normalize marker decorating helpers to mark objects.
+def normalize_mark_list(mark_list: Iterable[Union[Mark, MarkDecorator]]) -> List[Mark]: 
+    """Normalize marker decorating helpers to mark objects. 
 
-    :type List[Union[Mark, Markdecorator]] mark_list:
+    :type List[Union[Mark, Markdecorator]] mark_list: 
     :rtype: List[Mark]
     """
-    extracted = [
-        getattr(mark, "mark", mark) for mark in mark_list
-    ]  # unpack MarkDecorator
-    for mark in extracted:
-        if not isinstance(mark, Mark):
-            raise TypeError(f"got {mark!r} instead of Mark")
-    return [x for x in extracted if isinstance(x, Mark)]
-
-
-def store_mark(obj, mark: Mark) -> None:
-    """Store a Mark on an object.
-
-    This is used to implement the Mark declarations/decorators correctly.
+    extracted = [ 
+        getattr(mark, "mark", mark) for mark in mark_list 
+    ]  # unpack MarkDecorator 
+    for mark in extracted: 
+        if not isinstance(mark, Mark): 
+            raise TypeError(f"got {mark!r} instead of Mark") 
+    return [x for x in extracted if isinstance(x, Mark)] 
+
+
+def store_mark(obj, mark: Mark) -> None: 
+    """Store a Mark on an object. 
+ 
+    This is used to implement the Mark declarations/decorators correctly. 
     """
     assert isinstance(mark, Mark), mark
-    # Always reassign name to avoid updating pytestmark in a reference that
-    # was only borrowed.
+    # Always reassign name to avoid updating pytestmark in a reference that 
+    # was only borrowed. 
     obj.pytestmark = get_unpacked_marks(obj) + [mark]
 
 
-# Typing for builtin pytest marks. This is cheating; it gives builtin marks
-# special privilege, and breaks modularity. But practicality beats purity...
-if TYPE_CHECKING:
-    from _pytest.fixtures import _Scope
-
-    class _SkipMarkDecorator(MarkDecorator):
-        @overload  # type: ignore[override,misc]
-        def __call__(self, arg: _Markable) -> _Markable:
-            ...
-
-        @overload
-        def __call__(self, reason: str = ...) -> "MarkDecorator":
-            ...
-
-    class _SkipifMarkDecorator(MarkDecorator):
-        def __call__(  # type: ignore[override]
-            self,
-            condition: Union[str, bool] = ...,
-            *conditions: Union[str, bool],
-            reason: str = ...,
-        ) -> MarkDecorator:
-            ...
-
-    class _XfailMarkDecorator(MarkDecorator):
-        @overload  # type: ignore[override,misc]
-        def __call__(self, arg: _Markable) -> _Markable:
-            ...
-
-        @overload
-        def __call__(
-            self,
-            condition: Union[str, bool] = ...,
-            *conditions: Union[str, bool],
-            reason: str = ...,
-            run: bool = ...,
-            raises: Union[Type[BaseException], Tuple[Type[BaseException], ...]] = ...,
-            strict: bool = ...,
-        ) -> MarkDecorator:
-            ...
-
-    class _ParametrizeMarkDecorator(MarkDecorator):
-        def __call__(  # type: ignore[override]
-            self,
-            argnames: Union[str, List[str], Tuple[str, ...]],
-            argvalues: Iterable[Union[ParameterSet, Sequence[object], object]],
-            *,
-            indirect: Union[bool, Sequence[str]] = ...,
-            ids: Optional[
-                Union[
-                    Iterable[Union[None, str, float, int, bool]],
-                    Callable[[Any], Optional[object]],
-                ]
-            ] = ...,
-            scope: Optional[_Scope] = ...,
-        ) -> MarkDecorator:
-            ...
-
-    class _UsefixturesMarkDecorator(MarkDecorator):
-        def __call__(  # type: ignore[override]
-            self, *fixtures: str
-        ) -> MarkDecorator:
-            ...
-
-    class _FilterwarningsMarkDecorator(MarkDecorator):
-        def __call__(  # type: ignore[override]
-            self, *filters: str
-        ) -> MarkDecorator:
-            ...
-
-
-@final
-class MarkGenerator:
-    """Factory for :class:`MarkDecorator` objects - exposed as
-    a ``pytest.mark`` singleton instance.
-
-    Example::
-
+# Typing for builtin pytest marks. This is cheating; it gives builtin marks 
+# special privilege, and breaks modularity. But practicality beats purity... 
+if TYPE_CHECKING: 
+    from _pytest.fixtures import _Scope 
+ 
+    class _SkipMarkDecorator(MarkDecorator): 
+        @overload  # type: ignore[override,misc] 
+        def __call__(self, arg: _Markable) -> _Markable: 
+            ... 
+ 
+        @overload 
+        def __call__(self, reason: str = ...) -> "MarkDecorator": 
+            ... 
+ 
+    class _SkipifMarkDecorator(MarkDecorator): 
+        def __call__(  # type: ignore[override] 
+            self, 
+            condition: Union[str, bool] = ..., 
+            *conditions: Union[str, bool], 
+            reason: str = ..., 
+        ) -> MarkDecorator: 
+            ... 
+ 
+    class _XfailMarkDecorator(MarkDecorator): 
+        @overload  # type: ignore[override,misc] 
+        def __call__(self, arg: _Markable) -> _Markable: 
+            ... 
+ 
+        @overload 
+        def __call__( 
+            self, 
+            condition: Union[str, bool] = ..., 
+            *conditions: Union[str, bool], 
+            reason: str = ..., 
+            run: bool = ..., 
+            raises: Union[Type[BaseException], Tuple[Type[BaseException], ...]] = ..., 
+            strict: bool = ..., 
+        ) -> MarkDecorator: 
+            ... 
+ 
+    class _ParametrizeMarkDecorator(MarkDecorator): 
+        def __call__(  # type: ignore[override] 
+            self, 
+            argnames: Union[str, List[str], Tuple[str, ...]], 
+            argvalues: Iterable[Union[ParameterSet, Sequence[object], object]], 
+            *, 
+            indirect: Union[bool, Sequence[str]] = ..., 
+            ids: Optional[ 
+                Union[ 
+                    Iterable[Union[None, str, float, int, bool]], 
+                    Callable[[Any], Optional[object]], 
+                ] 
+            ] = ..., 
+            scope: Optional[_Scope] = ..., 
+        ) -> MarkDecorator: 
+            ... 
+ 
+    class _UsefixturesMarkDecorator(MarkDecorator): 
+        def __call__(  # type: ignore[override] 
+            self, *fixtures: str 
+        ) -> MarkDecorator: 
+            ... 
+ 
+    class _FilterwarningsMarkDecorator(MarkDecorator): 
+        def __call__(  # type: ignore[override] 
+            self, *filters: str 
+        ) -> MarkDecorator: 
+            ... 
+ 
+ 
+@final 
+class MarkGenerator: 
+    """Factory for :class:`MarkDecorator` objects - exposed as 
+    a ``pytest.mark`` singleton instance. 
+
+    Example:: 
+ 
          import pytest
-
+ 
          @pytest.mark.slowtest
          def test_function():
             pass
 
-    applies a 'slowtest' :class:`Mark` on ``test_function``.
-    """
-
-    _config: Optional[Config] = None
-    _markers: Set[str] = set()
-
-    # See TYPE_CHECKING above.
-    if TYPE_CHECKING:
-        skip: _SkipMarkDecorator
-        skipif: _SkipifMarkDecorator
-        xfail: _XfailMarkDecorator
-        parametrize: _ParametrizeMarkDecorator
-        usefixtures: _UsefixturesMarkDecorator
-        filterwarnings: _FilterwarningsMarkDecorator
-
-    def __getattr__(self, name: str) -> MarkDecorator:
+    applies a 'slowtest' :class:`Mark` on ``test_function``. 
+    """ 
+
+    _config: Optional[Config] = None 
+    _markers: Set[str] = set() 
+
+    # See TYPE_CHECKING above. 
+    if TYPE_CHECKING: 
+        skip: _SkipMarkDecorator 
+        skipif: _SkipifMarkDecorator 
+        xfail: _XfailMarkDecorator 
+        parametrize: _ParametrizeMarkDecorator 
+        usefixtures: _UsefixturesMarkDecorator 
+        filterwarnings: _FilterwarningsMarkDecorator 
+ 
+    def __getattr__(self, name: str) -> MarkDecorator: 
         if name[0] == "_":
             raise AttributeError("Marker name must NOT start with underscore")
-
+ 
         if self._config is not None:
-            # We store a set of markers as a performance optimisation - if a mark
-            # name is in the set we definitely know it, but a mark may be known and
-            # not in the set.  We therefore start by updating the set!
-            if name not in self._markers:
-                for line in self._config.getini("markers"):
-                    # example lines: "skipif(condition): skip the given test if..."
-                    # or "hypothesis: tests which use Hypothesis", so to get the
-                    # marker name we split on both `:` and `(`.
-                    if line == "ya:external":
-                        marker = line
-                    else:
-                        marker = line.split(":")[0].split("(")[0].strip()
-                    self._markers.add(marker)
-
-            # If the name is not in the set of known marks after updating,
-            # then it really is time to issue a warning or an error.
-            if name not in self._markers:
-                if self._config.option.strict_markers or self._config.option.strict:
-                    fail(
-                        f"{name!r} not found in `markers` configuration option",
-                        pytrace=False,
-                    )
-
-                # Raise a specific error for common misspellings of "parametrize".
-                if name in ["parameterize", "parametrise", "parameterise"]:
-                    __tracebackhide__ = True
-                    fail(f"Unknown '{name}' mark, did you mean 'parametrize'?")
-
-                warnings.warn(
-                    "Unknown pytest.mark.%s - is this a typo?  You can register "
-                    "custom marks to avoid this warning - for details, see "
-                    "https://docs.pytest.org/en/stable/mark.html" % name,
-                    PytestUnknownMarkWarning,
-                    2,
-                )
-
+            # We store a set of markers as a performance optimisation - if a mark 
+            # name is in the set we definitely know it, but a mark may be known and 
+            # not in the set.  We therefore start by updating the set! 
+            if name not in self._markers: 
+                for line in self._config.getini("markers"): 
+                    # example lines: "skipif(condition): skip the given test if..." 
+                    # or "hypothesis: tests which use Hypothesis", so to get the 
+                    # marker name we split on both `:` and `(`. 
+                    if line == "ya:external": 
+                        marker = line 
+                    else: 
+                        marker = line.split(":")[0].split("(")[0].strip() 
+                    self._markers.add(marker) 
+ 
+            # If the name is not in the set of known marks after updating, 
+            # then it really is time to issue a warning or an error. 
+            if name not in self._markers: 
+                if self._config.option.strict_markers or self._config.option.strict: 
+                    fail( 
+                        f"{name!r} not found in `markers` configuration option", 
+                        pytrace=False, 
+                    ) 
+ 
+                # Raise a specific error for common misspellings of "parametrize". 
+                if name in ["parameterize", "parametrise", "parameterise"]: 
+                    __tracebackhide__ = True 
+                    fail(f"Unknown '{name}' mark, did you mean 'parametrize'?") 
+ 
+                warnings.warn( 
+                    "Unknown pytest.mark.%s - is this a typo?  You can register " 
+                    "custom marks to avoid this warning - for details, see " 
+                    "https://docs.pytest.org/en/stable/mark.html" % name, 
+                    PytestUnknownMarkWarning, 
+                    2, 
+                ) 
+ 
         return MarkDecorator(Mark(name, (), {}))
 
 
 MARK_GEN = MarkGenerator()
 
 
-@final
-class NodeKeywords(MutableMapping[str, Any]):
-    def __init__(self, node: "Node") -> None:
+@final 
+class NodeKeywords(MutableMapping[str, Any]): 
+    def __init__(self, node: "Node") -> None: 
         self.node = node
         self.parent = node.parent
         self._markers = {node.name: True}
 
-    def __getitem__(self, key: str) -> Any:
+    def __getitem__(self, key: str) -> Any: 
         try:
             return self._markers[key]
         except KeyError:
@@ -539,24 +539,24 @@ class NodeKeywords(MutableMapping[str, Any]):
                 raise
             return self.parent.keywords[key]
 
-    def __setitem__(self, key: str, value: Any) -> None:
+    def __setitem__(self, key: str, value: Any) -> None: 
         self._markers[key] = value
 
-    def __delitem__(self, key: str) -> None:
+    def __delitem__(self, key: str) -> None: 
         raise ValueError("cannot delete key in keywords dict")
 
-    def __iter__(self) -> Iterator[str]:
+    def __iter__(self) -> Iterator[str]: 
         seen = self._seen()
         return iter(seen)
 
-    def _seen(self) -> Set[str]:
+    def _seen(self) -> Set[str]: 
         seen = set(self._markers)
         if self.parent is not None:
             seen.update(self.parent.keywords)
         return seen
 
-    def __len__(self) -> int:
+    def __len__(self) -> int: 
         return len(self._seen())
 
-    def __repr__(self) -> str:
-        return f"<NodeKeywords for node {self.node}>"
+    def __repr__(self) -> str: 
+        return f"<NodeKeywords for node {self.node}>" 
-- 
cgit v1.2.3