@@ -46,11 +46,19 @@ def get_empty_parameterset_mark(
46
46
) -> "MarkDecorator" :
47
47
from ..nodes import Collector
48
48
49
+ fs , lineno = getfslineno (func )
50
+ reason = "got empty parameter set %r, function %s at %s:%d" % (
51
+ argnames ,
52
+ func .__name__ ,
53
+ fs ,
54
+ lineno ,
55
+ )
56
+
49
57
requested_mark = config .getini (EMPTY_PARAMETERSET_OPTION )
50
58
if requested_mark in ("" , None , "skip" ):
51
- mark = MARK_GEN .skip
59
+ mark = MARK_GEN .skip ( reason = reason )
52
60
elif requested_mark == "xfail" :
53
- mark = MARK_GEN .xfail (run = False )
61
+ mark = MARK_GEN .xfail (reason = reason , run = False )
54
62
elif requested_mark == "fail_at_collect" :
55
63
f_name = func .__name__
56
64
_ , lineno = getfslineno (func )
@@ -59,14 +67,7 @@ def get_empty_parameterset_mark(
59
67
)
60
68
else :
61
69
raise LookupError (requested_mark )
62
- fs , lineno = getfslineno (func )
63
- reason = "got empty parameter set %r, function %s at %s:%d" % (
64
- argnames ,
65
- func .__name__ ,
66
- fs ,
67
- lineno ,
68
- )
69
- return mark (reason = reason )
70
+ return mark
70
71
71
72
72
73
class ParameterSet (
@@ -379,6 +380,76 @@ def store_mark(obj, mark: Mark) -> None:
379
380
obj .pytestmark = get_unpacked_marks (obj ) + [mark ]
380
381
381
382
383
+ # Typing for builtin pytest marks. This is cheating; it gives builtin marks
384
+ # special privilege, and breaks modularity. But practicality beats purity...
385
+ if TYPE_CHECKING :
386
+ from _pytest .fixtures import _Scope
387
+
388
+ class _SkipMarkDecorator (MarkDecorator ):
389
+ @overload # type: ignore[override,misc]
390
+ def __call__ (self , arg : _Markable ) -> _Markable :
391
+ raise NotImplementedError ()
392
+
393
+ @overload # noqa: F811
394
+ def __call__ (self , reason : str = ...) -> "MarkDecorator" : # noqa: F811
395
+ raise NotImplementedError ()
396
+
397
+ class _SkipifMarkDecorator (MarkDecorator ):
398
+ def __call__ ( # type: ignore[override]
399
+ self ,
400
+ condition : Union [str , bool ] = ...,
401
+ * conditions : Union [str , bool ],
402
+ reason : str = ...
403
+ ) -> MarkDecorator :
404
+ raise NotImplementedError ()
405
+
406
+ class _XfailMarkDecorator (MarkDecorator ):
407
+ @overload # type: ignore[override,misc]
408
+ def __call__ (self , arg : _Markable ) -> _Markable :
409
+ raise NotImplementedError ()
410
+
411
+ @overload # noqa: F811
412
+ def __call__ ( # noqa: F811
413
+ self ,
414
+ condition : Union [str , bool ] = ...,
415
+ * conditions : Union [str , bool ],
416
+ reason : str = ...,
417
+ run : bool = ...,
418
+ raises : Union [BaseException , Tuple [BaseException , ...]] = ...,
419
+ strict : bool = ...
420
+ ) -> MarkDecorator :
421
+ raise NotImplementedError ()
422
+
423
+ class _ParametrizeMarkDecorator (MarkDecorator ):
424
+ def __call__ ( # type: ignore[override]
425
+ self ,
426
+ argnames : Union [str , List [str ], Tuple [str , ...]],
427
+ argvalues : Iterable [Union [ParameterSet , Sequence [object ], object ]],
428
+ * ,
429
+ indirect : Union [bool , Sequence [str ]] = ...,
430
+ ids : Optional [
431
+ Union [
432
+ Iterable [Union [None , str , float , int , bool ]],
433
+ Callable [[object ], Optional [object ]],
434
+ ]
435
+ ] = ...,
436
+ scope : Optional [_Scope ] = ...
437
+ ) -> MarkDecorator :
438
+ raise NotImplementedError ()
439
+
440
+ class _UsefixturesMarkDecorator (MarkDecorator ):
441
+ def __call__ ( # type: ignore[override]
442
+ self , * fixtures : str
443
+ ) -> MarkDecorator :
444
+ raise NotImplementedError ()
445
+
446
+ class _FilterwarningsMarkDecorator (MarkDecorator ):
447
+ def __call__ ( # type: ignore[override]
448
+ self , * filters : str
449
+ ) -> MarkDecorator :
450
+ raise NotImplementedError ()
451
+
452
+
382
453
class MarkGenerator :
383
454
"""Factory for :class:`MarkDecorator` objects - exposed as
384
455
a ``pytest.mark`` singleton instance.
@@ -397,6 +468,15 @@ def test_function():
397
468
_config = None # type: Optional[Config]
398
469
_markers = set () # type: Set[str]
399
470
471
+ # See TYPE_CHECKING above.
472
+ if TYPE_CHECKING :
473
+ skip = None # type: _SkipMarkDecorator
474
+ skipif = None # type: _SkipifMarkDecorator
475
+ xfail = None # type: _XfailMarkDecorator
476
+ parametrize = None # type: _ParametrizeMarkDecorator
477
+ usefixtures = None # type: _UsefixturesMarkDecorator
478
+ filterwarnings = None # type: _FilterwarningsMarkDecorator
479
+
400
480
def __getattr__ (self , name : str ) -> MarkDecorator :
401
481
if name [0 ] == "_" :
402
482
raise AttributeError ("Marker name must NOT start with underscore" )
0 commit comments