Merged revisions 74845 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r74845 | georg.brandl | 2009-09-16 22:30:09 +0200 (Mi, 16 Sep 2009) | 5 lines

  #6844: do not emit DeprecationWarnings on access if Exception.message has been set by the user.

  This works by always setting it in __dict__, except when it's implicitly set in __init__.
........
This commit is contained in:
Georg Brandl 2009-09-16 20:34:51 +00:00
parent 6bb97a2ec4
commit 8997103be0
3 changed files with 81 additions and 18 deletions

View File

@ -303,6 +303,45 @@ class ExceptionTests(unittest.TestCase):
'pickled "%r", attribute "%s"' % 'pickled "%r", attribute "%s"' %
(e, checkArgName)) (e, checkArgName))
def testDeprecatedMessageAttribute(self):
# Accessing BaseException.message and relying on its value set by
# BaseException.__init__ triggers a deprecation warning.
exc = BaseException("foo")
with warnings.catch_warnings(record=True) as w:
self.assertEquals(exc.message, "foo")
self.assertEquals(len(w), 1)
self.assertEquals(w[0].category, DeprecationWarning)
self.assertEquals(
str(w[0].message),
"BaseException.message has been deprecated as of Python 2.6")
def testRegularMessageAttribute(self):
# Accessing BaseException.message after explicitly setting a value
# for it does not trigger a deprecation warning.
exc = BaseException("foo")
exc.message = "bar"
with warnings.catch_warnings(record=True) as w:
self.assertEquals(exc.message, "bar")
self.assertEquals(len(w), 0)
# Deleting the message is supported, too.
del exc.message
self.assertRaises(AttributeError, getattr, exc, "message")
def testPickleMessageAttribute(self):
# Pickling with message attribute must work, as well.
e = Exception("foo")
f = Exception("foo")
f.message = "bar"
for p in pickle, cPickle:
ep = p.loads(p.dumps(e))
with warnings.catch_warnings():
ignore_message_warning()
self.assertEqual(ep.message, "foo")
fp = p.loads(p.dumps(f))
self.assertEqual(fp.message, "bar")
def testSlicing(self): def testSlicing(self):
# Test that you can slice an exception directly instead of requiring # Test that you can slice an exception directly instead of requiring
# going through the 'args' attribute. # going through the 'args' attribute.

View File

@ -12,6 +12,9 @@ What's New in Python 2.6.3
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #6844: Do not emit DeprecationWarnings when accessing a "message"
attribute on exceptions that was set explicitly.
- Issue #6846: Fix bug where bytearray.pop() returns negative integers. - Issue #6846: Fix bug where bytearray.pop() returns negative integers.
- Issue #6707: dir() on an uninitialized module caused a crash. - Issue #6707: dir() on an uninitialized module caused a crash.

View File

@ -301,30 +301,51 @@ BaseException_set_args(PyBaseExceptionObject *self, PyObject *val)
static PyObject * static PyObject *
BaseException_get_message(PyBaseExceptionObject *self) BaseException_get_message(PyBaseExceptionObject *self)
{ {
int ret; PyObject *msg;
ret = PyErr_WarnEx(PyExc_DeprecationWarning,
"BaseException.message has been deprecated as " /* if "message" is in self->dict, accessing a user-set message attribute */
"of Python 2.6", 1); if (self->dict &&
if (ret < 0) (msg = PyDict_GetItemString(self->dict, "message"))) {
return NULL; Py_INCREF(msg);
return msg;
}
Py_INCREF(self->message); if (self->message == NULL) {
return self->message; PyErr_SetString(PyExc_AttributeError, "message attribute was deleted");
return NULL;
}
/* accessing the deprecated "builtin" message attribute of Exception */
if (PyErr_WarnEx(PyExc_DeprecationWarning,
"BaseException.message has been deprecated as "
"of Python 2.6", 1) < 0)
return NULL;
Py_INCREF(self->message);
return self->message;
} }
static int static int
BaseException_set_message(PyBaseExceptionObject *self, PyObject *val) BaseException_set_message(PyBaseExceptionObject *self, PyObject *val)
{ {
int ret; /* if val is NULL, delete the message attribute */
ret = PyErr_WarnEx(PyExc_DeprecationWarning, if (val == NULL) {
"BaseException.message has been deprecated as " if (self->dict && PyDict_GetItemString(self->dict, "message")) {
"of Python 2.6", 1); if (PyDict_DelItemString(self->dict, "message") < 0)
if (ret < 0) return -1;
return -1; }
Py_INCREF(val); Py_XDECREF(self->message);
Py_DECREF(self->message); self->message = NULL;
self->message = val; return 0;
return 0; }
/* else set it in __dict__, but may need to create the dict first */
if (self->dict == NULL) {
self->dict = PyDict_New();
if (!self->dict)
return -1;
}
return PyDict_SetItemString(self->dict, "message", val);
} }
static PyGetSetDef BaseException_getset[] = { static PyGetSetDef BaseException_getset[] = {