Skip to content

Commit 6aa4d1c

Browse files
committed
mark: export pytest.MarkGenerator 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.
1 parent 69c3024 commit 6aa4d1c

File tree

6 files changed

+14
-7
lines changed

6 files changed

+14
-7
lines changed

changelog/7469.deprecation.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ Directly constructing the following classes is now deprecated:
22

33
- ``_pytest.mark.structures.Mark``
44
- ``_pytest.mark.structures.MarkDecorator``
5+
- ``_pytest.mark.structures.MarkGenerator``
56

67
These have always been considered private, but now issue a deprecation warning, which may become a hard error in pytest 7.0.0.

changelog/7469.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ The newly-exported types are:
44

55
- ``pytest.Mark`` for :class:`marks <pytest.Mark>`.
66
- ``pytest.MarkDecorator`` for :class:`mark decorators <pytest.MarkDecorator>`.
7+
- ``pytest.MarkGenerator`` for the :class:`pytest.mark <pytest.MarkGenerator>` singleton.
78

89
Constructing them directly is not supported; they are only meant for use in type annotations.
910
Doing so will emit a deprecation warning, and may become a hard-error in pytest 7.0.

doc/en/reference.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -856,7 +856,7 @@ MarkDecorator
856856
MarkGenerator
857857
~~~~~~~~~~~~~
858858

859-
.. autoclass:: _pytest.mark.MarkGenerator
859+
.. autoclass:: pytest.MarkGenerator()
860860
:members:
861861

862862

src/_pytest/mark/structures.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -488,9 +488,6 @@ def test_function():
488488
applies a 'slowtest' :class:`Mark` on ``test_function``.
489489
"""
490490

491-
_config: Optional[Config] = None
492-
_markers: Set[str] = set()
493-
494491
# See TYPE_CHECKING above.
495492
if TYPE_CHECKING:
496493
skip: _SkipMarkDecorator
@@ -500,7 +497,13 @@ def test_function():
500497
usefixtures: _UsefixturesMarkDecorator
501498
filterwarnings: _FilterwarningsMarkDecorator
502499

500+
def __init__(self, *, _ispytest: bool = False) -> None:
501+
check_ispytest(_ispytest)
502+
self._config: Optional[Config] = None
503+
self._markers: Set[str] = set()
504+
503505
def __getattr__(self, name: str) -> MarkDecorator:
506+
"""Generate a new :class:`MarkDecorator` with the given name."""
504507
if name[0] == "_":
505508
raise AttributeError("Marker name must NOT start with underscore")
506509

@@ -541,7 +544,7 @@ def __getattr__(self, name: str) -> MarkDecorator:
541544
return MarkDecorator(Mark(name, (), {}, _ispytest=True), _ispytest=True)
542545

543546

544-
MARK_GEN = MarkGenerator()
547+
MARK_GEN = MarkGenerator(_ispytest=True)
545548

546549

547550
@final

src/pytest/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from _pytest.mark import Mark
2525
from _pytest.mark import MARK_GEN as mark
2626
from _pytest.mark import MarkDecorator
27+
from _pytest.mark import MarkGenerator
2728
from _pytest.mark import param
2829
from _pytest.monkeypatch import MonkeyPatch
2930
from _pytest.nodes import Collector
@@ -93,6 +94,7 @@
9394
"mark",
9495
"Mark",
9596
"MarkDecorator",
97+
"MarkGenerator",
9698
"Module",
9799
"MonkeyPatch",
98100
"Package",

testing/test_mark.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def test_pytest_exists_in_namespace_all(self, attr: str, modulename: str) -> Non
2121
assert attr in module.__all__ # type: ignore
2222

2323
def test_pytest_mark_notcallable(self) -> None:
24-
mark = MarkGenerator()
24+
mark = MarkGenerator(_ispytest=True)
2525
with pytest.raises(TypeError):
2626
mark() # type: ignore[operator]
2727

@@ -40,7 +40,7 @@ class SomeClass:
4040
assert pytest.mark.foo.with_args(SomeClass) is not SomeClass # type: ignore[comparison-overlap]
4141

4242
def test_pytest_mark_name_starts_with_underscore(self) -> None:
43-
mark = MarkGenerator()
43+
mark = MarkGenerator(_ispytest=True)
4444
with pytest.raises(AttributeError):
4545
mark._some_name
4646

0 commit comments

Comments
 (0)