[pypy-commit] pypy py3.6: warnings.warn() now has a "source" argument.

amauryfa pypy.commits at gmail.com
Thu Jan 4 03:17:27 EST 2018


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3.6
Changeset: r93625:dbcd63982736
Date: 2018-01-04 09:15 +0100
http://bitbucket.org/pypy/pypy/changeset/dbcd63982736/

Log:	warnings.warn() now has a "source" argument.

	In the future, ResourceWarnings might log the traceback where this
	object was allocated (when tracemalloc works on PyPy)

	In the mean time, this fixes the last failures in test_io.

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
@@ -276,12 +276,12 @@
             break
     space.call_method(w_stderr, "write", space.newunicode(message))
 
-def do_warn(space, w_message, w_category, stacklevel):
+def do_warn(space, w_message, w_category, stacklevel, w_source=None):
     context_w = setup_context(space, stacklevel)
-    do_warn_explicit(space, w_category, w_message, context_w)
+    do_warn_explicit(space, w_category, w_message, context_w, w_source=w_source)
 
 def do_warn_explicit(space, w_category, w_message, context_w,
-                     w_sourceline=None):
+                     w_sourceline=None, w_source=None):
     w_filename, lineno, w_module, w_registry = context_w
 
     # normalize module
@@ -342,19 +342,32 @@
     if warned:
         # Already warned for this module
         return
-    w_show_fxn = get_warnings_attr(space, "showwarning")
-    if w_show_fxn is None:
+
+    w_show_fn = get_warnings_attr(space, "_showwarnmsg")
+    if w_show_fn is None:
         show_warning(space, w_filename, lineno, w_text, w_category,
                      w_sourceline)
-    else:
-        space.call_function(
-            w_show_fxn, w_message, w_category, w_filename, w_lineno)
+        return
+
+    if not space.is_true(space.callable(w_show_fn)):
+        raise oefmt(space.w_TypeError,
+                    "warnings._showwarnmsg() must be set to a callable")
+    w_message_cls = get_warnings_attr(space, "WarningMessage")
+    if w_message_cls is None:
+        raise oefmt(space.w_RuntimeError,
+                    "unable to get warnings.WarningMessage")
+    w_source = w_source or space.w_None
+    w_msg = space.call_function(
+        w_message_cls, w_message, w_category,
+        w_filename, w_lineno, space.w_None, space.w_None, w_source)
+    space.call_function(w_show_fn, w_msg)
+
 
 @unwrap_spec(stacklevel=int)
-def warn(space, w_message, w_category=None, stacklevel=1):
+def warn(space, w_message, w_category=None, stacklevel=1, w_source=None):
     "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)
+    do_warn(space, w_message, w_category, stacklevel, w_source)
 
 
 def get_source_line(space, w_globals, lineno):
@@ -394,14 +407,15 @@
              w_registry = WrappedDefault(None),
              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):
+                  w_module=None, w_registry=None, w_module_globals=None,
+                  w_source=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)
+                     w_source_line, w_source)
 
 def filters_mutated(space):
     space.fromcache(State).filters_mutated(space)
diff --git a/pypy/module/_warnings/test/test_warnings.py b/pypy/module/_warnings/test/test_warnings.py
--- a/pypy/module/_warnings/test/test_warnings.py
+++ b/pypy/module/_warnings/test/test_warnings.py
@@ -42,6 +42,13 @@
         _warnings.warn_explicit("some message", Warning,
                                 "<string>", 1, module_globals=globals())
 
+    def test_with_source(self):
+        import warnings, _warnings
+        source = []
+        with warnings.catch_warnings(record=True) as w:
+            _warnings.warn("some message", Warning, source=source)
+        assert w[0].source is source
+
     def test_default_action(self):
         import warnings, _warnings
         warnings.defaultaction = 'ignore'


More information about the pypy-commit mailing list