Author: Armin Rigo <[email protected]>
Branch: py3.5
Changeset: r89345:018a60dc3997
Date: 2017-01-03 19:26 +0100
http://bitbucket.org/pypy/pypy/changeset/018a60dc3997/
Log: Update the _warnings module to CPython 3.5
diff --git a/pypy/module/_warnings/__init__.py
b/pypy/module/_warnings/__init__.py
--- a/pypy/module/_warnings/__init__.py
+++ b/pypy/module/_warnings/__init__.py
@@ -7,6 +7,7 @@
interpleveldefs = {
'warn' : 'interp_warnings.warn',
'warn_explicit': 'interp_warnings.warn_explicit',
+ '_filters_mutated': 'interp_warnings.filters_mutated',
}
appleveldefs = {
diff --git a/pypy/module/_warnings/interp_warnings.py
b/pypy/module/_warnings/interp_warnings.py
--- a/pypy/module/_warnings/interp_warnings.py
+++ b/pypy/module/_warnings/interp_warnings.py
@@ -11,6 +11,10 @@
self.init_filters(space)
self.w_once_registry = space.newdict()
self.w_default_action = space.wrap("default")
+ self.filters_mutated(space)
+
+ def filters_mutated(self, space):
+ self.w_filters_version = space.call_function(space.w_object)
def init_filters(self, space):
filters_w = []
@@ -32,6 +36,8 @@
filters_w.append(create_filter(
space, space.w_BytesWarning, action))
+ # note: in CPython, resource usage warnings are enabled by default
+ # in pydebug mode
filters_w.append(create_filter(
space, space.w_ResourceWarning, "ignore"))
@@ -61,19 +67,52 @@
w_category = space.w_UserWarning
# Validate category
- if not space.abstract_issubclass_w(w_category, space.w_Warning):
+ try:
+ if not space.abstract_issubclass_w(w_category, space.w_Warning):
+ raise oefmt(space.w_ValueError,
+ "category is not a subclass of Warning")
+ except OperationError as e:
+ if e.async(space):
+ raise
raise oefmt(space.w_ValueError,
- "category is not a subclass of Warning")
+ "category must be a Warning subclass, not '%T'",
+ w_category)
return w_category
+def is_internal_frame(space, frame):
+ if frame is None:
+ return False
+ code = frame.getcode()
+ if code is None or code.co_filename is None:
+ return False
+ # XXX XXX HAAAACK copied directly from CPython, which I'm particularly
+ # unhappy about, but I can't do anything more than say "bah"
+ return "importlib" in code.co_filename and "_bootstrap" in code.co_filename
+
+def next_external_frame(space, frame):
+ ec = space.getexecutioncontext()
+ while True:
+ frame = ec.getnextframe_nohidden(frame)
+ if frame is None or not is_internal_frame(space, frame):
+ return frame
+
def setup_context(space, stacklevel):
# Setup globals and lineno
ec = space.getexecutioncontext()
+
+ # Direct copy of CPython's logic, which has grown its own notion of
+ # "internal frames". xxx not sure I understand this logic.
frame = ec.gettopframe_nohidden()
- while frame and stacklevel > 1:
- frame = ec.getnextframe_nohidden(frame)
- stacklevel -= 1
+ if stacklevel <= 0 or is_internal_frame(space, frame):
+ while stacklevel > 1 and frame:
+ frame = ec.getnextframe_nohidden(frame)
+ stacklevel -= 1
+ else:
+ while stacklevel > 1 and frame:
+ frame = next_external_frame(space, frame)
+ stacklevel -= 1
+
if frame:
w_globals = frame.get_w_globals()
lineno = frame.get_last_lineno()
@@ -116,8 +155,7 @@
w_filename = w_module
else:
lc_filename = filename.lower()
- if (lc_filename.endswith(".pyc") or
- lc_filename.endswith(".pyo")):
+ if lc_filename.endswith(".pyc"):
# strip last character
w_filename = space.wrap(filename[:-1])
@@ -173,27 +211,30 @@
return already_warned(space, w_registry, w_key, should_set=True)
def already_warned(space, w_registry, w_key, should_set=False):
- try:
- w_warned = space.getitem(w_registry, w_key)
- except OperationError as e:
- if not e.match(space, space.w_KeyError):
- raise
- if should_set:
- space.setitem(w_registry, w_key, space.w_True)
- return False
+ w_version_obj = space.finditem_str(w_registry, "version")
+ state = space.fromcache(State)
+ if w_version_obj is not state.w_filters_version:
+ space.call_method(w_registry, "clear")
+ space.setitem_str(w_registry, "version", state.w_filters_version)
else:
- return space.is_true(w_warned)
+ w_already_warned = space.finditem(w_registry, w_key)
+ if w_already_warned is not None and space.is_true(w_already_warned):
+ return True
+ # This warning wasn't found in the registry, set it.
+ if should_set:
+ space.setitem(w_registry, w_key, space.w_True)
+ return False
def normalize_module(space, w_filename):
- if not space.is_true(w_filename):
+ filename = space.identifier_w(w_filename)
+ if len(filename) == 0:
return space.wrap("<unknown>")
-
- filename = space.str_w(w_filename)
if filename.endswith(".py"):
n = len(filename) - 3
assert n >= 0
filename = filename[:n]
- return space.wrap(filename)
+ return space.newutf8(filename)
+ return w_filename
def show_warning(space, w_filename, lineno, w_text, w_category,
w_sourceline=None):
@@ -308,6 +349,7 @@
@unwrap_spec(stacklevel=int)
def warn(space, w_message, w_category=None, stacklevel=1):
+ "Issue a warning, or maybe ignore it or raise an exception."
w_category = get_category(space, w_message, w_category);
do_warn(space, w_message, w_category, stacklevel)
@@ -350,9 +392,13 @@
w_module_globals = WrappedDefault(None))
def warn_explicit(space, w_message, w_category, w_filename, lineno,
w_module=None, w_registry=None, w_module_globals=None):
+ "Low-level inferface to warnings functionality."
w_source_line = get_source_line(space, w_module_globals, lineno)
do_warn_explicit(space, w_category, w_message,
(w_filename, lineno, w_module, w_registry),
w_source_line)
+
+def filters_mutated(space):
+ space.fromcache(State).filters_mutated(space)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit