]> granicus.if.org Git - python/commitdiff
Add a source parameter to warnings.warn()
authorVictor Stinner <victor.stinner@gmail.com>
Tue, 22 Mar 2016 23:28:08 +0000 (00:28 +0100)
committerVictor Stinner <victor.stinner@gmail.com>
Tue, 22 Mar 2016 23:28:08 +0000 (00:28 +0100)
Issue #26604:

* Add a new optional source parameter to _warnings.warn() and warnings.warn()
* Modify asyncore, asyncio and _pyio modules to set the source parameter when
  logging a ResourceWarning warning

13 files changed:
Doc/library/warnings.rst
Lib/_pyio.py
Lib/asyncio/base_events.py
Lib/asyncio/base_subprocess.py
Lib/asyncio/proactor_events.py
Lib/asyncio/selector_events.py
Lib/asyncio/sslproto.py
Lib/asyncio/unix_events.py
Lib/asyncio/windows_utils.py
Lib/asyncore.py
Lib/tempfile.py
Lib/warnings.py
Python/_warnings.c

index 4ce88ab3344a027d9ad57fa925dc34116bf14902..4fec3657162c60a0dc5783b2a4bbc177c69f9e09 100644 (file)
@@ -300,7 +300,7 @@ Available Functions
 -------------------
 
 
-.. function:: warn(message, category=None, stacklevel=1)
+.. function:: warn(message, category=None, stacklevel=1, source=None)
 
    Issue a warning, or maybe ignore it or raise an exception.  The *category*
    argument, if given, must be a warning category class (see above); it defaults to
@@ -318,6 +318,12 @@ Available Functions
    source of :func:`deprecation` itself (since the latter would defeat the purpose
    of the warning message).
 
+   *source*, if supplied, is the destroyed object which emitted a
+   :exc:`ResourceWarning`.
+
+   .. versionchanged:: 3.6
+      Added *source* parameter.
+
 
 .. function:: warn_explicit(message, category, filename, lineno, module=None, registry=None, module_globals=None, source=None)
 
index c3ad81e6db7eff06b60b11880b80060ee3293606..972c082803d72e905fadb82462fab9298de004af 100644 (file)
@@ -1514,7 +1514,7 @@ class FileIO(RawIOBase):
         if self._fd >= 0 and self._closefd and not self.closed:
             import warnings
             warnings.warn('unclosed file %r' % (self,), ResourceWarning,
-                          stacklevel=2)
+                          stacklevel=2, source=self)
             self.close()
 
     def __getstate__(self):
index 9d07673fbad2120f7d65e0963b601f7eb0f0ea06..3a42b10cb1bcf4f609c3efb9ea6d5e8ba2376306 100644 (file)
@@ -412,7 +412,8 @@ class BaseEventLoop(events.AbstractEventLoop):
     if compat.PY34:
         def __del__(self):
             if not self.is_closed():
-                warnings.warn("unclosed event loop %r" % self, ResourceWarning)
+                warnings.warn("unclosed event loop %r" % self, ResourceWarning,
+                              source=self)
                 if not self.is_running():
                     self.close()
 
index 73425d9bbcc9640b923ce7960a0412400cbf0224..efe08313e7a703787810f5468e2c8fd3d10e0607 100644 (file)
@@ -122,7 +122,8 @@ class BaseSubprocessTransport(transports.SubprocessTransport):
     if compat.PY34:
         def __del__(self):
             if not self._closed:
-                warnings.warn("unclosed transport %r" % self, ResourceWarning)
+                warnings.warn("unclosed transport %r" % self, ResourceWarning,
+                              source=self)
                 self.close()
 
     def get_pid(self):
index 14c0659ddee466a0b1bcee4e09335eb39d61e20e..2671a94d55a01570ffbdd8b3d3a61e67a1fdafb8 100644 (file)
@@ -86,7 +86,8 @@ class _ProactorBasePipeTransport(transports._FlowControlMixin,
     if compat.PY34:
         def __del__(self):
             if self._sock is not None:
-                warnings.warn("unclosed transport %r" % self, ResourceWarning)
+                warnings.warn("unclosed transport %r" % self, ResourceWarning,
+                              source=self)
                 self.close()
 
     def _fatal_error(self, exc, message='Fatal error on pipe transport'):
index 812fac19f86095d63e68d0e4ee7d0e7c4eff8815..cbb36250c968908eb710b1b14b5c40a7485bfece 100644 (file)
@@ -573,7 +573,8 @@ class _SelectorTransport(transports._FlowControlMixin,
     if compat.PY34:
         def __del__(self):
             if self._sock is not None:
-                warnings.warn("unclosed transport %r" % self, ResourceWarning)
+                warnings.warn("unclosed transport %r" % self, ResourceWarning,
+                              source=self)
                 self._sock.close()
 
     def _fatal_error(self, exc, message='Fatal error on transport'):
index dde980b68f835e73e53e2c10cbe8f126946aea53..1cea850475da3bfb9255fb0c58f7544dcb274cd3 100644 (file)
@@ -324,7 +324,8 @@ class _SSLProtocolTransport(transports._FlowControlMixin,
     if compat.PY34:
         def __del__(self):
             if not self._closed:
-                warnings.warn("unclosed transport %r" % self, ResourceWarning)
+                warnings.warn("unclosed transport %r" % self, ResourceWarning,
+                              source=self)
                 self.close()
 
     def pause_reading(self):
index 7747ff41bb8812ffc038c442384155bfcf779b37..2beba3e3abc55c08eda2e59a9acc85e710916cb1 100644 (file)
@@ -378,7 +378,8 @@ class _UnixReadPipeTransport(transports.ReadTransport):
     if compat.PY34:
         def __del__(self):
             if self._pipe is not None:
-                warnings.warn("unclosed transport %r" % self, ResourceWarning)
+                warnings.warn("unclosed transport %r" % self, ResourceWarning,
+                              source=self)
                 self._pipe.close()
 
     def _fatal_error(self, exc, message='Fatal error on pipe transport'):
@@ -567,7 +568,8 @@ class _UnixWritePipeTransport(transports._FlowControlMixin,
     if compat.PY34:
         def __del__(self):
             if self._pipe is not None:
-                warnings.warn("unclosed transport %r" % self, ResourceWarning)
+                warnings.warn("unclosed transport %r" % self, ResourceWarning,
+                              source=self)
                 self._pipe.close()
 
     def abort(self):
index 870cd13abe6cf2ff33425a7d93bbca78b1c75f06..7c63fb904b3bdd90b56d6c9b000d913d9653de0a 100644 (file)
@@ -159,7 +159,8 @@ class PipeHandle:
 
     def __del__(self):
         if self._handle is not None:
-            warnings.warn("unclosed %r" % self, ResourceWarning)
+            warnings.warn("unclosed %r" % self, ResourceWarning,
+                          source=self)
             self.close()
 
     def __enter__(self):
index 3b51f0f337fe2d7c02a4bfd1b53551850ddb8c5f..4b046d67e3969f446d135498b76a960bd0792a90 100644 (file)
@@ -595,7 +595,8 @@ if os.name == 'posix':
 
         def __del__(self):
             if self.fd >= 0:
-                warnings.warn("unclosed file %r" % self, ResourceWarning)
+                warnings.warn("unclosed file %r" % self, ResourceWarning,
+                              source=self)
             self.close()
 
         def recv(self, *args):
index ad687b9a03d36669170bcd4a3d574965f15e69d2..61462357c7283e13716b6a3fe431b7ca64b11a3d 100644 (file)
@@ -797,7 +797,6 @@ class TemporaryDirectory(object):
         _shutil.rmtree(name)
         _warnings.warn(warn_message, ResourceWarning)
 
-
     def __repr__(self):
         return "<{} {!r}>".format(self.__class__.__name__, self.name)
 
index 9fb21a878259e07e9ce7a58d7a5ca988d365aad6..d4f591ee71d85744442da571551663378b88161d 100644 (file)
@@ -233,7 +233,7 @@ def _next_external_frame(frame):
 
 
 # Code typically replaced by _warnings
-def warn(message, category=None, stacklevel=1):
+def warn(message, category=None, stacklevel=1, source=None):
     """Issue a warning, or maybe ignore it or raise an exception."""
     # Check if message is already a Warning object
     if isinstance(message, Warning):
@@ -283,7 +283,7 @@ def warn(message, category=None, stacklevel=1):
             filename = module
     registry = globals.setdefault("__warningregistry__", {})
     warn_explicit(message, category, filename, lineno, module, registry,
-                  globals)
+                  globals, source)
 
 def warn_explicit(message, category, filename, lineno,
                   module=None, registry=None, module_globals=None,
index 25299fb622fe29b689fe992b3934d0cd70c8b431..dcac57bda58811261d9f7403b18470f6e4f26a7e 100644 (file)
@@ -787,18 +787,19 @@ do_warn(PyObject *message, PyObject *category, Py_ssize_t stack_level,
 static PyObject *
 warnings_warn(PyObject *self, PyObject *args, PyObject *kwds)
 {
-    static char *kw_list[] = { "message", "category", "stacklevel", 0 };
-    PyObject *message, *category = NULL;
+    static char *kw_list[] = {"message", "category", "stacklevel",
+                              "source", NULL};
+    PyObject *message, *category = NULL, *source = NULL;
     Py_ssize_t stack_level = 1;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|On:warn", kw_list,
-                                     &message, &category, &stack_level))
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OnO:warn", kw_list,
+                                     &message, &category, &stack_level, &source))
         return NULL;
 
     category = get_category(message, category);
     if (category == NULL)
         return NULL;
-    return do_warn(message, category, stack_level, NULL);
+    return do_warn(message, category, stack_level, source);
 }
 
 static PyObject *