summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRan Benita <ran@unusedvar.com>2020-12-20 15:11:01 +0200
committerRan Benita <ran@unusedvar.com>2020-12-20 15:59:06 +0200
commit69c302479e3f76450f29e7d2de24254d5eda6492 (patch)
treeb5e02c2bb307f32cd8a6c2afbac9d50b16cd7e97 /src
parent2ec372df8b987207efc4ad0f33c2f82df5c9e2e5 (diff)
downloadpytest-69c302479e3f76450f29e7d2de24254d5eda6492.tar.gz
mark: export pytest.MarkDecorator for typing purposes
The type cannot be constructed directly, but is exported for use in type annotations, since it is reachable through existing public API.
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",