summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/_pytest/fixtures.py2
-rw-r--r--src/_pytest/mark/structures.py40
-rw-r--r--src/pytest/__init__.py2
3 files changed, 25 insertions, 19 deletions
diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py
index c24ab7069..dbb039bf2 100644
--- a/src/_pytest/fixtures.py
+++ b/src/_pytest/fixtures.py
@@ -551,7 +551,7 @@ class FixtureRequest:
on all function invocations.
:param marker:
- A :py:class:`_pytest.mark.MarkDecorator` object created by a call
+ A :class:`pytest.MarkDecorator` object created by a call
to ``pytest.mark.NAME(...)``.
"""
self.node.add_marker(marker)
diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py
index 29b958687..8bce33e68 100644
--- a/src/_pytest/mark/structures.py
+++ b/src/_pytest/mark/structures.py
@@ -268,14 +268,14 @@ class Mark:
# 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])
+Markable = TypeVar("Markable", bound=Union[Callable[..., object], type])
-@attr.s
+@attr.s(init=False, auto_attribs=True)
class MarkDecorator:
"""A decorator for applying a mark on test functions and classes.
- MarkDecorators are created with ``pytest.mark``::
+ ``MarkDecorators`` are created with ``pytest.mark``::
mark1 = pytest.mark.NAME # Simple MarkDecorator
mark2 = pytest.mark.NAME(name1=value) # Parametrized MarkDecorator
@@ -286,7 +286,7 @@ class MarkDecorator:
def test_function():
pass
- When a MarkDecorator is called it does the following:
+ 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
@@ -295,19 +295,24 @@ class MarkDecorator:
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.
+ ``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.
+ 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
+ Note: The rules above prevent a ``MarkDecorator`` from storing only a
+ single function or class reference as its 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))
+ mark: Mark
+
+ def __init__(self, mark: Mark, *, _ispytest: bool = False) -> None:
+ """:meta private:"""
+ check_ispytest(_ispytest)
+ self.mark = mark
@property
def name(self) -> str:
@@ -326,6 +331,7 @@ class MarkDecorator:
@property
def markname(self) -> str:
+ """:meta private:"""
return self.name # for backward-compat (2.4.1 had this attr)
def __repr__(self) -> str:
@@ -336,17 +342,15 @@ class MarkDecorator:
Unlike calling the MarkDecorator, with_args() can be used even
if the sole argument is a callable/class.
-
- :rtype: MarkDecorator
"""
mark = Mark(self.name, args, kwargs, _ispytest=True)
- return self.__class__(self.mark.combined_with(mark))
+ return MarkDecorator(self.mark.combined_with(mark), _ispytest=True)
# 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]
+ def __call__(self, arg: Markable) -> Markable: # type: ignore[misc]
pass
@overload
@@ -405,7 +409,7 @@ if TYPE_CHECKING:
class _SkipMarkDecorator(MarkDecorator):
@overload # type: ignore[override,misc]
- def __call__(self, arg: _Markable) -> _Markable:
+ def __call__(self, arg: Markable) -> Markable:
...
@overload
@@ -423,7 +427,7 @@ if TYPE_CHECKING:
class _XfailMarkDecorator(MarkDecorator):
@overload # type: ignore[override,misc]
- def __call__(self, arg: _Markable) -> _Markable:
+ def __call__(self, arg: Markable) -> Markable:
...
@overload
@@ -534,7 +538,7 @@ class MarkGenerator:
2,
)
- return MarkDecorator(Mark(name, (), {}, _ispytest=True))
+ return MarkDecorator(Mark(name, (), {}, _ispytest=True), _ispytest=True)
MARK_GEN = MarkGenerator()
diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py
index 4b194e0c8..1d5b38ee0 100644
--- a/src/pytest/__init__.py
+++ b/src/pytest/__init__.py
@@ -23,6 +23,7 @@ from _pytest.logging import LogCaptureFixture
from _pytest.main import Session
from _pytest.mark import Mark
from _pytest.mark import MARK_GEN as mark
+from _pytest.mark import MarkDecorator
from _pytest.mark import param
from _pytest.monkeypatch import MonkeyPatch
from _pytest.nodes import Collector
@@ -91,6 +92,7 @@ __all__ = [
"main",
"mark",
"Mark",
+ "MarkDecorator",
"Module",
"MonkeyPatch",
"Package",