Source code for schrodinger.test.pytest.warnings
"""
Turn existing python warnings into failures, for use in pytest. Uses the
internals of the cpython warning module to modify existing warning filters to
change warnings.filterwarnings action into errors.
"""
import copy
import dataclasses
import re
import warnings
from typing import Optional
@dataclasses.dataclass
class _WarningFilter:
action: str
message: Optional[re.Pattern]
category: Warning
module: Optional[re.Pattern]
lineno: int
def as_filterwarnings_args(self):
new_filter = copy.copy(self)
new_filter.message = _munge_regex_to_str(new_filter.message)
new_filter.module = _munge_regex_to_str(new_filter.module)
return dataclasses.astuple(new_filter)
def _get_new_warning_filter(warning_filter) -> _WarningFilter:
"""
Modify an existing warning filter, to change modes to error from printing.
"""
new_filter = _WarningFilter(*warning_filter)
if new_filter.action in {"always", "default", "module"}:
new_filter.action = "error"
return new_filter.as_filterwarnings_args()
[docs]def mark_warnings_as_errors():
"""
Modify existing warning filters using python internals to mark warnings
as errors, causing them to raise as pytest errors. Does not apply to
subprocesses.
"""
existing_filters = warnings.filters.copy()
warnings.resetwarnings()
for existing_warning in reversed(existing_filters):
warnings.filterwarnings(*_get_new_warning_filter(existing_warning))
def _munge_regex_to_str(regex: Optional[re.Pattern]) -> str:
"""
Helper function to convert compiled regex objects back to str, for use
in reconstructing python warning objects.
"""
if regex:
try:
return regex.pattern
except AttributeError:
if isinstance(regex, str):
return regex
raise
return ""