forked from Rust-related/RustPython
Upgrade warnings.py from Python 3.11
This commit is contained in:
104
Lib/warnings.py
vendored
104
Lib/warnings.py
vendored
@@ -33,9 +33,8 @@ def _showwarnmsg_impl(msg):
|
||||
pass
|
||||
|
||||
def _formatwarnmsg_impl(msg):
|
||||
s = ("%s:%s: %s: %s\n"
|
||||
% (msg.filename, msg.lineno, msg.category.__name__,
|
||||
msg.message))
|
||||
category = msg.category.__name__
|
||||
s = f"{msg.filename}:{msg.lineno}: {category}: {msg.message}\n"
|
||||
|
||||
if msg.line is None:
|
||||
try:
|
||||
@@ -55,11 +54,20 @@ def _formatwarnmsg_impl(msg):
|
||||
if msg.source is not None:
|
||||
try:
|
||||
import tracemalloc
|
||||
tb = tracemalloc.get_object_traceback(msg.source)
|
||||
# Logging a warning should not raise a new exception:
|
||||
# catch Exception, not only ImportError and RecursionError.
|
||||
except Exception:
|
||||
# When a warning is logged during Python shutdown, tracemalloc
|
||||
# and the import machinery don't work anymore
|
||||
# don't suggest to enable tracemalloc if it's not available
|
||||
tracing = True
|
||||
tb = None
|
||||
else:
|
||||
tracing = tracemalloc.is_tracing()
|
||||
try:
|
||||
tb = tracemalloc.get_object_traceback(msg.source)
|
||||
except Exception:
|
||||
# When a warning is logged during Python shutdown, tracemalloc
|
||||
# and the import machinery don't work anymore
|
||||
tb = None
|
||||
|
||||
if tb is not None:
|
||||
s += 'Object allocated at (most recent call last):\n'
|
||||
@@ -77,6 +85,9 @@ def _formatwarnmsg_impl(msg):
|
||||
if line:
|
||||
line = line.strip()
|
||||
s += ' %s\n' % line
|
||||
elif not tracing:
|
||||
s += (f'{category}: Enable tracemalloc to get the object '
|
||||
f'allocation traceback\n')
|
||||
return s
|
||||
|
||||
# Keep a reference to check if the function was replaced
|
||||
@@ -113,7 +124,7 @@ def _formatwarnmsg(msg):
|
||||
if fw is not _formatwarning_orig:
|
||||
# warnings.formatwarning() was replaced
|
||||
return fw(msg.message, msg.category,
|
||||
msg.filename, msg.lineno, line=msg.line)
|
||||
msg.filename, msg.lineno, msg.line)
|
||||
return _formatwarnmsg_impl(msg)
|
||||
|
||||
def filterwarnings(action, message="", category=Warning, module="", lineno=0,
|
||||
@@ -200,7 +211,6 @@ def _processoptions(args):
|
||||
|
||||
# Helper for _processoptions()
|
||||
def _setoption(arg):
|
||||
import re
|
||||
parts = arg.split(':')
|
||||
if len(parts) > 5:
|
||||
raise _OptionError("too many fields (max 5): %r" % (arg,))
|
||||
@@ -209,11 +219,13 @@ def _setoption(arg):
|
||||
action, message, category, module, lineno = [s.strip()
|
||||
for s in parts]
|
||||
action = _getaction(action)
|
||||
message = re.escape(message)
|
||||
category = _getcategory(category)
|
||||
module = re.escape(module)
|
||||
if message or module:
|
||||
import re
|
||||
if message:
|
||||
message = re.escape(message)
|
||||
if module:
|
||||
module = module + '$'
|
||||
module = re.escape(module) + r'\Z'
|
||||
if lineno:
|
||||
try:
|
||||
lineno = int(lineno)
|
||||
@@ -237,26 +249,21 @@ def _getaction(action):
|
||||
|
||||
# Helper for _setoption()
|
||||
def _getcategory(category):
|
||||
import re
|
||||
if not category:
|
||||
return Warning
|
||||
if re.match("^[a-zA-Z0-9_]+$", category):
|
||||
try:
|
||||
cat = eval(category)
|
||||
except NameError:
|
||||
raise _OptionError("unknown warning category: %r" % (category,)) from None
|
||||
if '.' not in category:
|
||||
import builtins as m
|
||||
klass = category
|
||||
else:
|
||||
i = category.rfind(".")
|
||||
module = category[:i]
|
||||
klass = category[i+1:]
|
||||
module, _, klass = category.rpartition('.')
|
||||
try:
|
||||
m = __import__(module, None, None, [klass])
|
||||
except ImportError:
|
||||
raise _OptionError("invalid module name: %r" % (module,)) from None
|
||||
try:
|
||||
cat = getattr(m, klass)
|
||||
except AttributeError:
|
||||
raise _OptionError("unknown warning category: %r" % (category,)) from None
|
||||
try:
|
||||
cat = getattr(m, klass)
|
||||
except AttributeError:
|
||||
raise _OptionError("unknown warning category: %r" % (category,)) from None
|
||||
if not issubclass(cat, Warning):
|
||||
raise _OptionError("invalid warning category: %r" % (category,))
|
||||
return cat
|
||||
@@ -303,28 +310,16 @@ def warn(message, category=None, stacklevel=1, source=None):
|
||||
raise ValueError
|
||||
except ValueError:
|
||||
globals = sys.__dict__
|
||||
filename = "sys"
|
||||
lineno = 1
|
||||
else:
|
||||
globals = frame.f_globals
|
||||
filename = frame.f_code.co_filename
|
||||
lineno = frame.f_lineno
|
||||
if '__name__' in globals:
|
||||
module = globals['__name__']
|
||||
else:
|
||||
module = "<string>"
|
||||
filename = globals.get('__file__')
|
||||
if filename:
|
||||
fnl = filename.lower()
|
||||
if fnl.endswith(".pyc"):
|
||||
filename = filename[:-1]
|
||||
else:
|
||||
if module == "__main__":
|
||||
try:
|
||||
filename = sys.argv[0]
|
||||
except AttributeError:
|
||||
# embedded interpreters don't have sys.argv, see bug #839151
|
||||
filename = '__main__'
|
||||
if not filename:
|
||||
filename = module
|
||||
registry = globals.setdefault("__warningregistry__", {})
|
||||
warn_explicit(message, category, filename, lineno, module, registry,
|
||||
globals, source)
|
||||
@@ -437,9 +432,13 @@ class catch_warnings(object):
|
||||
named 'warnings' and imported under that name. This argument is only useful
|
||||
when testing the warnings module itself.
|
||||
|
||||
If the 'action' argument is not None, the remaining arguments are passed
|
||||
to warnings.simplefilter() as if it were called immediately on entering the
|
||||
context.
|
||||
"""
|
||||
|
||||
def __init__(self, *, record=False, module=None):
|
||||
def __init__(self, *, record=False, module=None,
|
||||
action=None, category=Warning, lineno=0, append=False):
|
||||
"""Specify whether to record warnings and if an alternative module
|
||||
should be used other than sys.modules['warnings'].
|
||||
|
||||
@@ -450,6 +449,10 @@ class catch_warnings(object):
|
||||
self._record = record
|
||||
self._module = sys.modules['warnings'] if module is None else module
|
||||
self._entered = False
|
||||
if action is None:
|
||||
self._filter = None
|
||||
else:
|
||||
self._filter = (action, category, lineno, append)
|
||||
|
||||
def __repr__(self):
|
||||
args = []
|
||||
@@ -469,6 +472,8 @@ class catch_warnings(object):
|
||||
self._module._filters_mutated()
|
||||
self._showwarning = self._module.showwarning
|
||||
self._showwarnmsg_impl = self._module._showwarnmsg_impl
|
||||
if self._filter is not None:
|
||||
simplefilter(*self._filter)
|
||||
if self._record:
|
||||
log = []
|
||||
self._module._showwarnmsg_impl = log.append
|
||||
@@ -488,6 +493,27 @@ class catch_warnings(object):
|
||||
self._module._showwarnmsg_impl = self._showwarnmsg_impl
|
||||
|
||||
|
||||
_DEPRECATED_MSG = "{name!r} is deprecated and slated for removal in Python {remove}"
|
||||
|
||||
def _deprecated(name, message=_DEPRECATED_MSG, *, remove, _version=sys.version_info):
|
||||
"""Warn that *name* is deprecated or should be removed.
|
||||
|
||||
RuntimeError is raised if *remove* specifies a major/minor tuple older than
|
||||
the current Python version or the same version but past the alpha.
|
||||
|
||||
The *message* argument is formatted with *name* and *remove* as a Python
|
||||
version (e.g. "3.11").
|
||||
|
||||
"""
|
||||
remove_formatted = f"{remove[0]}.{remove[1]}"
|
||||
if (_version[:2] > remove) or (_version[:2] == remove and _version[3] != "alpha"):
|
||||
msg = f"{name!r} was slated for removal after Python {remove_formatted} alpha"
|
||||
raise RuntimeError(msg)
|
||||
else:
|
||||
msg = message.format(name=name, remove=remove_formatted)
|
||||
warn(msg, DeprecationWarning, stacklevel=3)
|
||||
|
||||
|
||||
# Private utility function called by _PyErr_WarnUnawaitedCoroutine
|
||||
def _warn_unawaited_coroutine(coro):
|
||||
msg_lines = [
|
||||
|
||||
Reference in New Issue
Block a user