Kaydet (Commit) 1eaf0742 authored tarafından Brett Cannon's avatar Brett Cannon

Move test.test_support.catch_warning() to the warnings module, rename it

catch_warnings(), and clean up the API.

While expanding the test suite, a bug was found where a warning about the
'line' argument to showwarning() was not letting functions with '*args' go
without a warning.

Closes issue 3602.
Code review by Benjamin Peterson.
üst 86533776
...@@ -263,3 +263,53 @@ Available Functions ...@@ -263,3 +263,53 @@ Available Functions
:func:`filterwarnings`, including that of the :option:`-W` command line options :func:`filterwarnings`, including that of the :option:`-W` command line options
and calls to :func:`simplefilter`. and calls to :func:`simplefilter`.
Available Classes
-----------------
.. class:: catch_warnings([record=False[, module=None]])
A context manager that guards the warnings filter from being permanentally
mutated. The manager returns an instance of :class:`WarningsRecorder`. The
*record* argument specifies whether warnings that would typically be
handled by :func:`showwarning` should instead be recorded by the
:class:`WarningsRecorder` instance. This argument is typically set when
testing for expected warnings behavior. The *module* argument may be a
module object that is to be used instead of the :mod:`warnings` module.
This argument should only be set when testing the :mod:`warnings` module
or some similar use-case.
Typical usage of the context manager is like so::
def fxn():
warn("fxn is deprecated", DeprecationWarning)
return "spam spam bacon spam"
# The function 'fxn' is known to raise a DeprecationWarning.
with catch_warnings() as w:
warnings.filterwarning('ignore', 'fxn is deprecated', DeprecationWarning)
fxn() # DeprecationWarning is temporarily suppressed.
.. note::
In Python 3.0, the arguments to the constructor for
:class:`catch_warnings` are keyword-only arguments.
.. versionadded:: 2.6
.. class:: WarningsRecorder()
A subclass of :class:`list` that stores all warnings passed to
:func:`showwarning` when returned by a :class:`catch_warnings` context
manager created with its *record* argument set to ``True``. Each recorded
warning is represented by an object whose attributes correspond to the
arguments to :func:`showwarning`. As a convenience, a
:class:`WarningsRecorder` instance has the attributes of the last
recorded warning set on the :class:`WarningsRecorder` instance as well.
.. method:: reset()
Delete all recorded warnings.
.. versionadded:: 2.6
...@@ -73,9 +73,9 @@ __all__ = ["HTTPServer", "BaseHTTPRequestHandler"] ...@@ -73,9 +73,9 @@ __all__ = ["HTTPServer", "BaseHTTPRequestHandler"]
import sys import sys
import time import time
import socket # For gethostbyaddr() import socket # For gethostbyaddr()
from test.test_support import catch_warning from warnings import filterwarnings, catch_warnings
from warnings import filterwarnings with catch_warnings():
with catch_warning(record=False): if sys.py3kwarning:
filterwarnings("ignore", ".*mimetools has been removed", filterwarnings("ignore", ".*mimetools has been removed",
DeprecationWarning) DeprecationWarning)
import mimetools import mimetools
......
...@@ -49,8 +49,9 @@ you - by calling your self.found_terminator() method. ...@@ -49,8 +49,9 @@ you - by calling your self.found_terminator() method.
import socket import socket
import asyncore import asyncore
from collections import deque from collections import deque
from sys import py3kwarning
from test.test_support import catch_warning from test.test_support import catch_warning
from warnings import filterwarnings from warnings import filterwarnings, catch_warnings
class async_chat (asyncore.dispatcher): class async_chat (asyncore.dispatcher):
"""This is an abstract class. You must derive from this class, and add """This is an abstract class. You must derive from this class, and add
...@@ -218,7 +219,8 @@ class async_chat (asyncore.dispatcher): ...@@ -218,7 +219,8 @@ class async_chat (asyncore.dispatcher):
# handle classic producer behavior # handle classic producer behavior
obs = self.ac_out_buffer_size obs = self.ac_out_buffer_size
try: try:
with catch_warning(record=False): with catch_warnings():
if py3kwarning:
filterwarnings("ignore", ".*buffer", DeprecationWarning) filterwarnings("ignore", ".*buffer", DeprecationWarning)
data = buffer(first, 0, obs) data = buffer(first, 0, obs)
except TypeError: except TypeError:
......
...@@ -39,12 +39,13 @@ import sys ...@@ -39,12 +39,13 @@ import sys
import os import os
import urllib import urllib
import UserDict import UserDict
from test.test_support import catch_warning from warnings import filterwarnings, catch_warnings
from warnings import filterwarnings with catch_warnings():
with catch_warning(record=False): if sys.py3kwarning:
filterwarnings("ignore", ".*mimetools has been removed", filterwarnings("ignore", ".*mimetools has been removed",
DeprecationWarning) DeprecationWarning)
import mimetools import mimetools
if sys.py3kwarning:
filterwarnings("ignore", ".*rfc822 has been removed", DeprecationWarning) filterwarnings("ignore", ".*rfc822 has been removed", DeprecationWarning)
import rfc822 import rfc822
......
...@@ -67,10 +67,11 @@ Req-sent-unread-response _CS_REQ_SENT <response_class> ...@@ -67,10 +67,11 @@ Req-sent-unread-response _CS_REQ_SENT <response_class>
""" """
import socket import socket
from sys import py3kwarning
from urlparse import urlsplit from urlparse import urlsplit
import warnings import warnings
from test.test_support import catch_warning with warnings.catch_warnings():
with catch_warning(record=False): if py3kwarning:
warnings.filterwarnings("ignore", ".*mimetools has been removed", warnings.filterwarnings("ignore", ".*mimetools has been removed",
DeprecationWarning) DeprecationWarning)
import mimetools import mimetools
......
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
import os import os
import sys
import tempfile import tempfile
from test.test_support import catch_warning from warnings import filterwarnings, catch_warnings
from warnings import filterwarnings with catch_warnings(record=False):
with catch_warning(record=False): if sys.py3kwarning:
filterwarnings("ignore", ".*rfc822 has been removed", DeprecationWarning) filterwarnings("ignore", ".*rfc822 has been removed", DeprecationWarning)
import rfc822 import rfc822
......
...@@ -18,7 +18,7 @@ __all__ = ["Error", "TestFailed", "TestSkipped", "ResourceDenied", "import_modul ...@@ -18,7 +18,7 @@ __all__ = ["Error", "TestFailed", "TestSkipped", "ResourceDenied", "import_modul
"is_resource_enabled", "requires", "find_unused_port", "bind_port", "is_resource_enabled", "requires", "find_unused_port", "bind_port",
"fcmp", "have_unicode", "is_jython", "TESTFN", "HOST", "FUZZ", "fcmp", "have_unicode", "is_jython", "TESTFN", "HOST", "FUZZ",
"findfile", "verify", "vereq", "sortdict", "check_syntax_error", "findfile", "verify", "vereq", "sortdict", "check_syntax_error",
"open_urlresource", "WarningMessage", "catch_warning", "CleanImport", "open_urlresource", "catch_warning", "CleanImport",
"EnvironmentVarGuard", "captured_output", "EnvironmentVarGuard", "captured_output",
"captured_stdout", "TransientResource", "transient_internet", "captured_stdout", "TransientResource", "transient_internet",
"run_with_locale", "set_memlimit", "bigmemtest", "bigaddrspacetest", "run_with_locale", "set_memlimit", "bigmemtest", "bigaddrspacetest",
...@@ -381,71 +381,8 @@ def open_urlresource(url): ...@@ -381,71 +381,8 @@ def open_urlresource(url):
return open(fn) return open(fn)
class WarningMessage(object):
"Holds the result of a single showwarning() call"
_WARNING_DETAILS = "message category filename lineno line".split()
def __init__(self, message, category, filename, lineno, line=None):
for attr in self._WARNING_DETAILS:
setattr(self, attr, locals()[attr])
self._category_name = category.__name__ if category else None
def __str__(self):
return ("{message : %r, category : %r, filename : %r, lineno : %s, "
"line : %r}" % (self.message, self._category_name,
self.filename, self.lineno, self.line))
class WarningRecorder(object):
"Records the result of any showwarning calls"
def __init__(self):
self.warnings = []
self._set_last(None)
def _showwarning(self, message, category, filename, lineno,
file=None, line=None):
wm = WarningMessage(message, category, filename, lineno, line)
self.warnings.append(wm)
self._set_last(wm)
def _set_last(self, last_warning):
if last_warning is None:
for attr in WarningMessage._WARNING_DETAILS:
setattr(self, attr, None)
else:
for attr in WarningMessage._WARNING_DETAILS:
setattr(self, attr, getattr(last_warning, attr))
def reset(self):
self.warnings = []
self._set_last(None)
def __str__(self):
return '[%s]' % (', '.join(map(str, self.warnings)))
@contextlib.contextmanager
def catch_warning(module=warnings, record=True): def catch_warning(module=warnings, record=True):
"""Guard the warnings filter from being permanently changed and return warnings.catch_warnings(record=record, module=module)
optionally record the details of any warnings that are issued.
Use like this:
with catch_warning() as w:
warnings.warn("foo")
assert str(w.message) == "foo"
"""
original_filters = module.filters
original_showwarning = module.showwarning
if record:
recorder = WarningRecorder()
module.showwarning = recorder._showwarning
else:
recorder = None
try:
# Replace the filters with a copy of the original
module.filters = module.filters[:]
yield recorder
finally:
module.showwarning = original_showwarning
module.filters = original_filters
class CleanImport(object): class CleanImport(object):
......
...@@ -79,20 +79,19 @@ class FilterTests(object): ...@@ -79,20 +79,19 @@ class FilterTests(object):
"FilterTests.test_error") "FilterTests.test_error")
def test_ignore(self): def test_ignore(self):
with test_support.catch_warning(self.module) as w: with test_support.catch_warning(module=self.module) as w:
self.module.resetwarnings() self.module.resetwarnings()
self.module.filterwarnings("ignore", category=UserWarning) self.module.filterwarnings("ignore", category=UserWarning)
self.module.warn("FilterTests.test_ignore", UserWarning) self.module.warn("FilterTests.test_ignore", UserWarning)
self.assert_(not w.message) self.assertEquals(len(w), 0)
def test_always(self): def test_always(self):
with test_support.catch_warning(self.module) as w: with test_support.catch_warning(module=self.module) as w:
self.module.resetwarnings() self.module.resetwarnings()
self.module.filterwarnings("always", category=UserWarning) self.module.filterwarnings("always", category=UserWarning)
message = "FilterTests.test_always" message = "FilterTests.test_always"
self.module.warn(message, UserWarning) self.module.warn(message, UserWarning)
self.assert_(message, w.message) self.assert_(message, w.message)
w.message = None # Reset.
self.module.warn(message, UserWarning) self.module.warn(message, UserWarning)
self.assert_(w.message, message) self.assert_(w.message, message)
...@@ -107,7 +106,7 @@ class FilterTests(object): ...@@ -107,7 +106,7 @@ class FilterTests(object):
self.assertEquals(w.message, message) self.assertEquals(w.message, message)
w.reset() w.reset()
elif x == 1: elif x == 1:
self.assert_(not w.message, "unexpected warning: " + str(w)) self.assert_(not len(w), "unexpected warning: " + str(w))
else: else:
raise ValueError("loop variant unhandled") raise ValueError("loop variant unhandled")
...@@ -120,7 +119,7 @@ class FilterTests(object): ...@@ -120,7 +119,7 @@ class FilterTests(object):
self.assertEquals(w.message, message) self.assertEquals(w.message, message)
w.reset() w.reset()
self.module.warn(message, UserWarning) self.module.warn(message, UserWarning)
self.assert_(not w.message, "unexpected message: " + str(w)) self.assert_(not len(w), "unexpected message: " + str(w))
def test_once(self): def test_once(self):
with test_support.catch_warning(self.module) as w: with test_support.catch_warning(self.module) as w:
...@@ -133,10 +132,10 @@ class FilterTests(object): ...@@ -133,10 +132,10 @@ class FilterTests(object):
w.reset() w.reset()
self.module.warn_explicit(message, UserWarning, "test_warnings.py", self.module.warn_explicit(message, UserWarning, "test_warnings.py",
13) 13)
self.assert_(not w.message) self.assertEquals(len(w), 0)
self.module.warn_explicit(message, UserWarning, "test_warnings2.py", self.module.warn_explicit(message, UserWarning, "test_warnings2.py",
42) 42)
self.assert_(not w.message) self.assertEquals(len(w), 0)
def test_inheritance(self): def test_inheritance(self):
with test_support.catch_warning(self.module) as w: with test_support.catch_warning(self.module) as w:
...@@ -156,7 +155,7 @@ class FilterTests(object): ...@@ -156,7 +155,7 @@ class FilterTests(object):
self.module.warn("FilterTests.test_ordering", UserWarning) self.module.warn("FilterTests.test_ordering", UserWarning)
except UserWarning: except UserWarning:
self.fail("order handling for actions failed") self.fail("order handling for actions failed")
self.assert_(not w.message) self.assertEquals(len(w), 0)
def test_filterwarnings(self): def test_filterwarnings(self):
# Test filterwarnings(). # Test filterwarnings().
...@@ -317,7 +316,6 @@ class WarnTests(unittest.TestCase): ...@@ -317,7 +316,6 @@ class WarnTests(unittest.TestCase):
None, Warning, None, 1, registry=42) None, Warning, None, 1, registry=42)
class CWarnTests(BaseTest, WarnTests): class CWarnTests(BaseTest, WarnTests):
module = c_warnings module = c_warnings
...@@ -377,7 +375,7 @@ class _WarningsTests(BaseTest): ...@@ -377,7 +375,7 @@ class _WarningsTests(BaseTest):
self.failUnlessEqual(w.message, message) self.failUnlessEqual(w.message, message)
w.reset() w.reset()
self.module.warn_explicit(message, UserWarning, "file", 42) self.module.warn_explicit(message, UserWarning, "file", 42)
self.assert_(not w.message) self.assertEquals(len(w), 0)
# Test the resetting of onceregistry. # Test the resetting of onceregistry.
self.module.onceregistry = {} self.module.onceregistry = {}
__warningregistry__ = {} __warningregistry__ = {}
...@@ -388,7 +386,7 @@ class _WarningsTests(BaseTest): ...@@ -388,7 +386,7 @@ class _WarningsTests(BaseTest):
del self.module.onceregistry del self.module.onceregistry
__warningregistry__ = {} __warningregistry__ = {}
self.module.warn_explicit(message, UserWarning, "file", 42) self.module.warn_explicit(message, UserWarning, "file", 42)
self.failUnless(not w.message) self.assertEquals(len(w), 0)
finally: finally:
self.module.onceregistry = original_registry self.module.onceregistry = original_registry
...@@ -489,45 +487,45 @@ class PyWarningsDisplayTests(BaseTest, WarningsDisplayTests): ...@@ -489,45 +487,45 @@ class PyWarningsDisplayTests(BaseTest, WarningsDisplayTests):
class WarningsSupportTests(object): class CatchWarningTests(BaseTest):
"""Test the warning tools from test support module"""
def test_catch_warning_restore(self): """Test catch_warnings()."""
def test_catch_warnings_restore(self):
wmod = self.module wmod = self.module
orig_filters = wmod.filters orig_filters = wmod.filters
orig_showwarning = wmod.showwarning orig_showwarning = wmod.showwarning
with test_support.catch_warning(wmod): with wmod.catch_warnings(record=True, module=wmod):
wmod.filters = wmod.showwarning = object() wmod.filters = wmod.showwarning = object()
self.assert_(wmod.filters is orig_filters) self.assert_(wmod.filters is orig_filters)
self.assert_(wmod.showwarning is orig_showwarning) self.assert_(wmod.showwarning is orig_showwarning)
with test_support.catch_warning(wmod, record=False): with wmod.catch_warnings(module=wmod, record=False):
wmod.filters = wmod.showwarning = object() wmod.filters = wmod.showwarning = object()
self.assert_(wmod.filters is orig_filters) self.assert_(wmod.filters is orig_filters)
self.assert_(wmod.showwarning is orig_showwarning) self.assert_(wmod.showwarning is orig_showwarning)
def test_catch_warning_recording(self): def test_catch_warnings_recording(self):
wmod = self.module wmod = self.module
with test_support.catch_warning(wmod) as w: with wmod.catch_warnings(module=wmod, record=True) as w:
self.assertEqual(w.warnings, []) self.assertEqual(w, [])
wmod.simplefilter("always") wmod.simplefilter("always")
wmod.warn("foo") wmod.warn("foo")
self.assertEqual(str(w.message), "foo") self.assertEqual(str(w.message), "foo")
wmod.warn("bar") wmod.warn("bar")
self.assertEqual(str(w.message), "bar") self.assertEqual(str(w.message), "bar")
self.assertEqual(str(w.warnings[0].message), "foo") self.assertEqual(str(w[0].message), "foo")
self.assertEqual(str(w.warnings[1].message), "bar") self.assertEqual(str(w[1].message), "bar")
w.reset() w.reset()
self.assertEqual(w.warnings, []) self.assertEqual(w, [])
orig_showwarning = wmod.showwarning orig_showwarning = wmod.showwarning
with test_support.catch_warning(wmod, record=False) as w: with wmod.catch_warnings(module=wmod, record=False) as w:
self.assert_(w is None) self.assert_(w is None)
self.assert_(wmod.showwarning is orig_showwarning) self.assert_(wmod.showwarning is orig_showwarning)
class CCatchWarningTests(CatchWarningTests):
class CWarningsSupportTests(BaseTest, WarningsSupportTests):
module = c_warnings module = c_warnings
class PyWarningsSupportTests(BaseTest, WarningsSupportTests): class PyCatchWarningTests(CatchWarningTests):
module = py_warnings module = py_warnings
...@@ -539,14 +537,24 @@ class ShowwarningDeprecationTests(BaseTest): ...@@ -539,14 +537,24 @@ class ShowwarningDeprecationTests(BaseTest):
def bad_showwarning(message, category, filename, lineno, file=None): def bad_showwarning(message, category, filename, lineno, file=None):
pass pass
@staticmethod
def ok_showwarning(*args):
pass
def test_deprecation(self): def test_deprecation(self):
# message, category, filename, lineno[, file[, line]] # message, category, filename, lineno[, file[, line]]
args = ("message", UserWarning, "file name", 42) args = ("message", UserWarning, "file name", 42)
with test_support.catch_warning(self.module): with test_support.catch_warning(module=self.module):
self.module.filterwarnings("error", category=DeprecationWarning) self.module.filterwarnings("error", category=DeprecationWarning)
self.module.showwarning = self.bad_showwarning self.module.showwarning = self.bad_showwarning
self.assertRaises(DeprecationWarning, self.module.warn_explicit, self.assertRaises(DeprecationWarning, self.module.warn_explicit,
*args) *args)
self.module.showwarning = self.ok_showwarning
try:
self.module.warn_explicit(*args)
except DeprecationWarning as exc:
self.fail('showwarning(*args) should not trigger a '
'DeprecationWarning')
class CShowwarningDeprecationTests(ShowwarningDeprecationTests): class CShowwarningDeprecationTests(ShowwarningDeprecationTests):
module = c_warnings module = c_warnings
...@@ -559,14 +567,12 @@ class PyShowwarningDeprecationTests(ShowwarningDeprecationTests): ...@@ -559,14 +567,12 @@ class PyShowwarningDeprecationTests(ShowwarningDeprecationTests):
def test_main(): def test_main():
py_warnings.onceregistry.clear() py_warnings.onceregistry.clear()
c_warnings.onceregistry.clear() c_warnings.onceregistry.clear()
test_support.run_unittest(CFilterTests, test_support.run_unittest(CFilterTests, PyFilterTests,
PyFilterTests, CWarnTests, PyWarnTests,
CWarnTests,
PyWarnTests,
CWCmdLineTests, PyWCmdLineTests, CWCmdLineTests, PyWCmdLineTests,
_WarningsTests, _WarningsTests,
CWarningsDisplayTests, PyWarningsDisplayTests, CWarningsDisplayTests, PyWarningsDisplayTests,
CWarningsSupportTests, PyWarningsSupportTests, CCatchWarningTests, PyCatchWarningTests,
CShowwarningDeprecationTests, CShowwarningDeprecationTests,
PyShowwarningDeprecationTests, PyShowwarningDeprecationTests,
) )
......
...@@ -272,7 +272,8 @@ def warn_explicit(message, category, filename, lineno, ...@@ -272,7 +272,8 @@ def warn_explicit(message, category, filename, lineno,
fxn_code = showwarning.__func__.func_code fxn_code = showwarning.__func__.func_code
if fxn_code: if fxn_code:
args = fxn_code.co_varnames[:fxn_code.co_argcount] args = fxn_code.co_varnames[:fxn_code.co_argcount]
if 'line' not in args: CO_VARARGS = 0x4
if 'line' not in args and not fxn_code.co_flags & CO_VARARGS:
showwarning_msg = ("functions overriding warnings.showwarning() " showwarning_msg = ("functions overriding warnings.showwarning() "
"must support the 'line' argument") "must support the 'line' argument")
if message == showwarning_msg: if message == showwarning_msg:
...@@ -283,6 +284,78 @@ def warn_explicit(message, category, filename, lineno, ...@@ -283,6 +284,78 @@ def warn_explicit(message, category, filename, lineno,
showwarning(message, category, filename, lineno) showwarning(message, category, filename, lineno)
class WarningMessage(object):
"""Holds the result of a single showwarning() call."""
_WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
"line")
def __init__(self, message, category, filename, lineno, file=None,
line=None):
local_values = locals()
for attr in self._WARNING_DETAILS:
setattr(self, attr, local_values[attr])
self._category_name = category.__name__ if category else None
def __str__(self):
return ("{message : %r, category : %r, filename : %r, lineno : %s, "
"line : %r}" % (self.message, self._category_name,
self.filename, self.lineno, self.line))
class WarningsRecorder(list):
"""Record the result of various showwarning() calls."""
# Explicitly stated arguments so as to not trigger DeprecationWarning
# about adding 'line'.
def showwarning(self, *args, **kwargs):
self.append(WarningMessage(*args, **kwargs))
def __getattr__(self, attr):
return getattr(self[-1], attr)
def reset(self):
del self[:]
class catch_warnings(object):
"""Guard the warnings filter from being permanently changed and optionally
record the details of any warnings that are issued.
Context manager returns an instance of warnings.WarningRecorder which is a
list of WarningMessage instances. Attributes on WarningRecorder are
redirected to the last created WarningMessage instance.
"""
def __init__(self, record=False, module=None):
"""Specify whether to record warnings and if an alternative module
should be used other than sys.modules['warnings'].
For compatibility with Python 3.0, please consider all arguments to be
keyword-only.
"""
self._recorder = WarningsRecorder() if record else None
self._module = sys.modules['warnings'] if module is None else module
def __enter__(self):
self._filters = self._module.filters
self._module.filters = self._filters[:]
self._showwarning = self._module.showwarning
if self._recorder is not None:
self._recorder.reset() # In case the instance is being reused.
self._module.showwarning = self._recorder.showwarning
return self._recorder
def __exit__(self, *exc_info):
self._module.filters = self._filters
self._module.showwarning = self._showwarning
# filters contains a sequence of filter 5-tuples # filters contains a sequence of filter 5-tuples
# The components of the 5-tuple are: # The components of the 5-tuple are:
# - an action: error, ignore, always, default, module, or once # - an action: error, ignore, always, default, module, or once
......
...@@ -53,6 +53,11 @@ C-API ...@@ -53,6 +53,11 @@ C-API
Library Library
------- -------
- Issue 3602: Moved test.test_support.catch_warning() to
warnings.catch_warnings() along with some API cleanup. Expanding the tests
for catch_warnings() also led to an improvement in the raising of a
DeprecationWarning related to warnings.warn_explicit().
- The deprecation warnings for the old camelCase threading API were removed. - The deprecation warnings for the old camelCase threading API were removed.
- logging: fixed lack of use of encoding attribute specified on a stream. - logging: fixed lack of use of encoding attribute specified on a stream.
......
#include "Python.h" #include "Python.h"
#include "code.h" /* For DeprecationWarning about adding 'line'. */
#include "frameobject.h" #include "frameobject.h"
#define MODULE_NAME "_warnings" #define MODULE_NAME "_warnings"
...@@ -416,11 +417,16 @@ warn_explicit(PyObject *category, PyObject *message, ...@@ -416,11 +417,16 @@ warn_explicit(PyObject *category, PyObject *message,
/* A proper implementation of warnings.showwarning() should /* A proper implementation of warnings.showwarning() should
have at least two default arguments. */ have at least two default arguments. */
if ((defaults == NULL) || (PyTuple_Size(defaults) < 2)) { if ((defaults == NULL) || (PyTuple_Size(defaults) < 2)) {
if (PyErr_WarnEx(PyExc_DeprecationWarning, msg, 1) < 0) { PyCodeObject *code = (PyCodeObject *)
PyFunction_GetCode(check_fxn);
if (!(code->co_flags & CO_VARARGS)) {
if (PyErr_WarnEx(PyExc_DeprecationWarning, msg, 1) <
0) {
Py_DECREF(show_fxn); Py_DECREF(show_fxn);
goto cleanup; goto cleanup;
} }
} }
}
res = PyObject_CallFunctionObjArgs(show_fxn, message, category, res = PyObject_CallFunctionObjArgs(show_fxn, message, category,
filename, lineno_obj, filename, lineno_obj,
NULL); NULL);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment