Merge pull request #7176 from bluetech/warnings-optimize-parse
warnings: speed up work done in catch_warnings_for_item()
This commit is contained in:
commit
32c00db0bf
|
@ -1,34 +1,52 @@
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
import warnings
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
from functools import lru_cache
|
||||||
from typing import Generator
|
from typing import Generator
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from _pytest.compat import TYPE_CHECKING
|
||||||
from _pytest.main import Session
|
from _pytest.main import Session
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from typing_extensions import Type
|
||||||
|
|
||||||
def _setoption(wmod, arg):
|
|
||||||
"""
|
@lru_cache(maxsize=50)
|
||||||
Copy of the warning._setoption function but does not escape arguments.
|
def _parse_filter(
|
||||||
|
arg: str, *, escape: bool
|
||||||
|
) -> "Tuple[str, str, Type[Warning], str, int]":
|
||||||
|
"""Parse a warnings filter string.
|
||||||
|
|
||||||
|
This is copied from warnings._setoption, but does not apply the filter,
|
||||||
|
only parses it, and makes the escaping optional.
|
||||||
"""
|
"""
|
||||||
parts = arg.split(":")
|
parts = arg.split(":")
|
||||||
if len(parts) > 5:
|
if len(parts) > 5:
|
||||||
raise wmod._OptionError("too many fields (max 5): {!r}".format(arg))
|
raise warnings._OptionError("too many fields (max 5): {!r}".format(arg))
|
||||||
while len(parts) < 5:
|
while len(parts) < 5:
|
||||||
parts.append("")
|
parts.append("")
|
||||||
action, message, category, module, lineno = [s.strip() for s in parts]
|
action_, message, category_, module, lineno_ = [s.strip() for s in parts]
|
||||||
action = wmod._getaction(action)
|
action = warnings._getaction(action_) # type: str # type: ignore[attr-defined]
|
||||||
category = wmod._getcategory(category)
|
category = warnings._getcategory(
|
||||||
if lineno:
|
category_
|
||||||
|
) # type: Type[Warning] # type: ignore[attr-defined]
|
||||||
|
if message and escape:
|
||||||
|
message = re.escape(message)
|
||||||
|
if module and escape:
|
||||||
|
module = re.escape(module) + r"\Z"
|
||||||
|
if lineno_:
|
||||||
try:
|
try:
|
||||||
lineno = int(lineno)
|
lineno = int(lineno_)
|
||||||
if lineno < 0:
|
if lineno < 0:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
except (ValueError, OverflowError):
|
except (ValueError, OverflowError):
|
||||||
raise wmod._OptionError("invalid lineno {!r}".format(lineno))
|
raise warnings._OptionError("invalid lineno {!r}".format(lineno_))
|
||||||
else:
|
else:
|
||||||
lineno = 0
|
lineno = 0
|
||||||
wmod.filterwarnings(action, message, category, module, lineno)
|
return (action, message, category, module, lineno)
|
||||||
|
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
|
@ -79,15 +97,15 @@ def catch_warnings_for_item(config, ihook, when, item):
|
||||||
# filters should have this precedence: mark, cmdline options, ini
|
# filters should have this precedence: mark, cmdline options, ini
|
||||||
# filters should be applied in the inverse order of precedence
|
# filters should be applied in the inverse order of precedence
|
||||||
for arg in inifilters:
|
for arg in inifilters:
|
||||||
_setoption(warnings, arg)
|
warnings.filterwarnings(*_parse_filter(arg, escape=False))
|
||||||
|
|
||||||
for arg in cmdline_filters:
|
for arg in cmdline_filters:
|
||||||
warnings._setoption(arg)
|
warnings.filterwarnings(*_parse_filter(arg, escape=True))
|
||||||
|
|
||||||
if item is not None:
|
if item is not None:
|
||||||
for mark in item.iter_markers(name="filterwarnings"):
|
for mark in item.iter_markers(name="filterwarnings"):
|
||||||
for arg in mark.args:
|
for arg in mark.args:
|
||||||
_setoption(warnings, arg)
|
warnings.filterwarnings(*_parse_filter(arg, escape=False))
|
||||||
|
|
||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue