Skip to content

Commit 53cd7fd

Browse files
committed
Introduce new warning subclasses
Fix #5177
1 parent 8532e99 commit 53cd7fd

File tree

9 files changed

+102
-33
lines changed

9 files changed

+102
-33
lines changed

doc/en/warnings.rst

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,10 +415,20 @@ The following warning types ares used by pytest and are part of the public API:
415415

416416
.. autoclass:: pytest.PytestWarning
417417

418-
.. autoclass:: pytest.PytestDeprecationWarning
418+
.. autoclass:: pytest.PytestAssertRewriteWarning
419419

420-
.. autoclass:: pytest.RemovedInPytest4Warning
420+
.. autoclass:: pytest.PytestCacheWarning
421+
422+
.. autoclass:: pytest.PytestCollectionWarning
423+
424+
.. autoclass:: pytest.PytestConfigWarning
425+
426+
.. autoclass:: pytest.PytestDeprecationWarning
421427

422428
.. autoclass:: pytest.PytestExperimentalApiWarning
423429

430+
.. autoclass:: pytest.PytestUnhandledCoroutineWarning
431+
424432
.. autoclass:: pytest.PytestUnknownMarkWarning
433+
434+
.. autoclass:: pytest.RemovedInPytest4Warning

src/_pytest/assertion/rewrite.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -268,11 +268,13 @@ def mark_rewrite(self, *names):
268268
self._marked_for_rewrite_cache.clear()
269269

270270
def _warn_already_imported(self, name):
271-
from _pytest.warning_types import PytestWarning
271+
from _pytest.warning_types import PytestAssertRewriteWarning
272272
from _pytest.warnings import _issue_warning_captured
273273

274274
_issue_warning_captured(
275-
PytestWarning("Module already imported so cannot be rewritten: %s" % name),
275+
PytestAssertRewriteWarning(
276+
"Module already imported so cannot be rewritten: %s" % name
277+
),
276278
self.config.hook,
277279
stacklevel=5,
278280
)
@@ -819,11 +821,13 @@ def visit_Assert(self, assert_):
819821
820822
"""
821823
if isinstance(assert_.test, ast.Tuple) and len(assert_.test.elts) >= 1:
822-
from _pytest.warning_types import PytestWarning
824+
from _pytest.warning_types import PytestAssertRewriteWarning
823825
import warnings
824826

825827
warnings.warn_explicit(
826-
PytestWarning("assertion is always true, perhaps remove parentheses?"),
828+
PytestAssertRewriteWarning(
829+
"assertion is always true, perhaps remove parentheses?"
830+
),
827831
category=None,
828832
filename=str(self.module_path),
829833
lineno=assert_.lineno,
@@ -887,10 +891,10 @@ def warn_about_none_ast(self, node, module_path, lineno):
887891
val_is_none = ast.Compare(node, [ast.Is()], [AST_NONE])
888892
send_warning = ast.parse(
889893
"""
890-
from _pytest.warning_types import PytestWarning
894+
from _pytest.warning_types import PytestAssertRewriteWarning
891895
from warnings import warn_explicit
892896
warn_explicit(
893-
PytestWarning('asserting the value None, please use "assert is None"'),
897+
PytestAssertRewriteWarning('asserting the value None, please use "assert is None"'),
894898
category=None,
895899
filename={filename!r},
896900
lineno={lineno},

src/_pytest/cacheprovider.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ def cache_dir_from_config(config):
6060

6161
def warn(self, fmt, **args):
6262
from _pytest.warnings import _issue_warning_captured
63-
from _pytest.warning_types import PytestWarning
63+
from _pytest.warning_types import PytestCacheWarning
6464

6565
_issue_warning_captured(
66-
PytestWarning(fmt.format(**args) if args else fmt),
66+
PytestCacheWarning(fmt.format(**args) if args else fmt),
6767
self._config.hook,
6868
stacklevel=3,
6969
)

src/_pytest/config/__init__.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
from _pytest.compat import safe_str
3333
from _pytest.outcomes import fail
3434
from _pytest.outcomes import Skipped
35-
from _pytest.warning_types import PytestWarning
35+
from _pytest.warning_types import PytestConfigWarning
3636

3737
hookimpl = HookimplMarker("pytest")
3838
hookspec = HookspecMarker("pytest")
@@ -307,7 +307,7 @@ def parse_hookspec_opts(self, module_or_class, name):
307307
def register(self, plugin, name=None):
308308
if name in ["pytest_catchlog", "pytest_capturelog"]:
309309
warnings.warn(
310-
PytestWarning(
310+
PytestConfigWarning(
311311
"{} plugin has been merged into the core, "
312312
"please remove it from your requirements.".format(
313313
name.replace("_", "-")
@@ -574,7 +574,7 @@ def import_plugin(self, modname, consider_entry_points=False):
574574
from _pytest.warnings import _issue_warning_captured
575575

576576
_issue_warning_captured(
577-
PytestWarning("skipped plugin %r: %s" % (modname, e.msg)),
577+
PytestConfigWarning("skipped plugin %r: %s" % (modname, e.msg)),
578578
self.hook,
579579
stacklevel=1,
580580
)
@@ -863,7 +863,7 @@ def _preparse(self, args, addopts=True):
863863
from _pytest.warnings import _issue_warning_captured
864864

865865
_issue_warning_captured(
866-
PytestWarning(
866+
PytestConfigWarning(
867867
"could not load initial conftests: {}".format(e.path)
868868
),
869869
self.hook,

src/_pytest/junitxml.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,9 +307,11 @@ def record_xml_attribute(request):
307307
The fixture is callable with ``(name, value)``, with value being
308308
automatically xml-encoded
309309
"""
310-
from _pytest.warning_types import PytestWarning
310+
from _pytest.warning_types import PytestExperimentalApiWarning, PytestWarning
311311

312-
request.node.warn(PytestWarning("record_xml_attribute is an experimental feature"))
312+
request.node.warn(
313+
PytestExperimentalApiWarning("record_xml_attribute is an experimental feature")
314+
)
313315

314316
# Declare noop
315317
def add_attr_noop(name, value):

src/_pytest/python.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@
4545
from _pytest.outcomes import fail
4646
from _pytest.outcomes import skip
4747
from _pytest.pathlib import parts
48-
from _pytest.warning_types import PytestWarning
48+
from _pytest.warning_types import PytestCollectionWarning
49+
from _pytest.warning_types import PytestUnhandledCoroutineWarning
4950

5051

5152
def pyobj_property(name):
@@ -171,7 +172,7 @@ def pytest_pyfunc_call(pyfuncitem):
171172
msg += " - pytest-asyncio\n"
172173
msg += " - pytest-trio\n"
173174
msg += " - pytest-tornasync"
174-
warnings.warn(PytestWarning(msg.format(pyfuncitem.nodeid)))
175+
warnings.warn(PytestUnhandledCoroutineWarning(msg.format(pyfuncitem.nodeid)))
175176
skip(msg="coroutine function and no async plugin installed (see warnings)")
176177
funcargs = pyfuncitem.funcargs
177178
testargs = {arg: funcargs[arg] for arg in pyfuncitem._fixtureinfo.argnames}
@@ -221,7 +222,7 @@ def pytest_pycollect_makeitem(collector, name, obj):
221222
if not (isfunction(obj) or isfunction(get_real_func(obj))):
222223
filename, lineno = getfslineno(obj)
223224
warnings.warn_explicit(
224-
message=PytestWarning(
225+
message=PytestCollectionWarning(
225226
"cannot collect %r because it is not a function." % name
226227
),
227228
category=None,
@@ -233,7 +234,7 @@ def pytest_pycollect_makeitem(collector, name, obj):
233234
res = Function(name, parent=collector)
234235
reason = deprecated.YIELD_TESTS.format(name=name)
235236
res.add_marker(MARK_GEN.xfail(run=False, reason=reason))
236-
res.warn(PytestWarning(reason))
237+
res.warn(PytestCollectionWarning(reason))
237238
else:
238239
res = list(collector._genfunctions(name, obj))
239240
outcome.force_result(res)
@@ -721,15 +722,15 @@ def collect(self):
721722
return []
722723
if hasinit(self.obj):
723724
self.warn(
724-
PytestWarning(
725+
PytestCollectionWarning(
725726
"cannot collect test class %r because it has a "
726727
"__init__ constructor" % self.obj.__name__
727728
)
728729
)
729730
return []
730731
elif hasnew(self.obj):
731732
self.warn(
732-
PytestWarning(
733+
PytestCollectionWarning(
733734
"cannot collect test class %r because it has a "
734735
"__new__ constructor" % self.obj.__name__
735736
)

src/_pytest/warning_types.py

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,43 @@ class PytestWarning(UserWarning):
99
"""
1010

1111

12-
class PytestUnknownMarkWarning(PytestWarning):
12+
class PytestAssertRewriteWarning(PytestWarning):
1313
"""
1414
Bases: :class:`PytestWarning`.
1515
16-
Warning emitted on use of unknown markers.
17-
See https://docs.pytest.org/en/latest/mark.html for details.
16+
Warning emitted by the pytest assert rewrite module.
1817
"""
1918

2019

21-
class PytestDeprecationWarning(PytestWarning, DeprecationWarning):
20+
class PytestCacheWarning(PytestWarning):
2221
"""
23-
Bases: :class:`pytest.PytestWarning`, :class:`DeprecationWarning`.
22+
Bases: :class:`PytestWarning`.
2423
25-
Warning class for features that will be removed in a future version.
24+
Warning emitted by the cache plugin in various situations.
2625
"""
2726

2827

29-
class RemovedInPytest4Warning(PytestDeprecationWarning):
28+
class PytestConfigWarning(PytestWarning):
3029
"""
31-
Bases: :class:`pytest.PytestDeprecationWarning`.
30+
Bases: :class:`PytestWarning`.
3231
33-
Warning class for features scheduled to be removed in pytest 4.0.
32+
Warning emitted for configuration issues.
33+
"""
34+
35+
36+
class PytestCollectionWarning(PytestWarning):
37+
"""
38+
Bases: :class:`PytestWarning`.
39+
40+
Warning emitted when pytest is not able to collect a file or symbol in a module.
41+
"""
42+
43+
44+
class PytestDeprecationWarning(PytestWarning, DeprecationWarning):
45+
"""
46+
Bases: :class:`pytest.PytestWarning`, :class:`DeprecationWarning`.
47+
48+
Warning class for features that will be removed in a future version.
3449
"""
3550

3651

@@ -51,6 +66,33 @@ def simple(cls, apiname):
5166
)
5267

5368

69+
class PytestUnhandledCoroutineWarning(PytestWarning):
70+
"""
71+
Bases: :class:`PytestWarning`.
72+
73+
Warning emitted when pytest encounters a test function which is a coroutine,
74+
but it was not handled by any async-aware plugin. Coroutine test functions
75+
are not natively supported.
76+
"""
77+
78+
79+
class PytestUnknownMarkWarning(PytestWarning):
80+
"""
81+
Bases: :class:`PytestWarning`.
82+
83+
Warning emitted on use of unknown markers.
84+
See https://docs.pytest.org/en/latest/mark.html for details.
85+
"""
86+
87+
88+
class RemovedInPytest4Warning(PytestDeprecationWarning):
89+
"""
90+
Bases: :class:`pytest.PytestDeprecationWarning`.
91+
92+
Warning class for features scheduled to be removed in pytest 4.0.
93+
"""
94+
95+
5496
@attr.s
5597
class UnformattedWarning(object):
5698
"""Used to hold warnings that need to format their message at runtime, as opposed to a direct message.

src/pytest.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,13 @@
3535
from _pytest.python_api import raises
3636
from _pytest.recwarn import deprecated_call
3737
from _pytest.recwarn import warns
38+
from _pytest.warning_types import PytestAssertRewriteWarning
39+
from _pytest.warning_types import PytestCacheWarning
40+
from _pytest.warning_types import PytestCollectionWarning
41+
from _pytest.warning_types import PytestConfigWarning
3842
from _pytest.warning_types import PytestDeprecationWarning
3943
from _pytest.warning_types import PytestExperimentalApiWarning
44+
from _pytest.warning_types import PytestUnhandledCoroutineWarning
4045
from _pytest.warning_types import PytestUnknownMarkWarning
4146
from _pytest.warning_types import PytestWarning
4247
from _pytest.warning_types import RemovedInPytest4Warning
@@ -67,13 +72,18 @@
6772
"Module",
6873
"Package",
6974
"param",
75+
"PytestAssertRewriteWarning",
76+
"PytestCacheWarning",
77+
"PytestCollectionWarning",
78+
"PytestConfigWarning",
7079
"PytestDeprecationWarning",
7180
"PytestExperimentalApiWarning",
81+
"PytestUnhandledCoroutineWarning",
82+
"PytestUnknownMarkWarning",
7283
"PytestWarning",
7384
"raises",
7485
"register_assert_rewrite",
7586
"RemovedInPytest4Warning",
76-
"PytestUnknownMarkWarning",
7787
"Session",
7888
"set_trace",
7989
"skip",

testing/test_warnings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ def test():
630630
class TestAssertionWarnings:
631631
@staticmethod
632632
def assert_result_warns(result, msg):
633-
result.stdout.fnmatch_lines(["*PytestWarning: %s*" % msg])
633+
result.stdout.fnmatch_lines(["*PytestAssertRewriteWarning: %s*" % msg])
634634

635635
def test_tuple_warning(self, testdir):
636636
testdir.makepyfile(

0 commit comments

Comments
 (0)