[Python-checkins] r74848 - in python/branches/release26-maint: Lib/test/test_exceptions.py Misc/NEWS Objects/exceptions.c
georg.brandl
python-checkins at python.org
Wed Sep 16 22:34:51 CEST 2009
Author: georg.brandl
Date: Wed Sep 16 22:34:51 2009
New Revision: 74848
Log:
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__.
........
Modified:
python/branches/release26-maint/ (props changed)
python/branches/release26-maint/Lib/test/test_exceptions.py
python/branches/release26-maint/Misc/NEWS
python/branches/release26-maint/Objects/exceptions.c
Modified: python/branches/release26-maint/Lib/test/test_exceptions.py
==============================================================================
--- python/branches/release26-maint/Lib/test/test_exceptions.py (original)
+++ python/branches/release26-maint/Lib/test/test_exceptions.py Wed Sep 16 22:34:51 2009
@@ -303,6 +303,45 @@
'pickled "%r", attribute "%s"' %
(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):
# Test that you can slice an exception directly instead of requiring
# going through the 'args' attribute.
Modified: python/branches/release26-maint/Misc/NEWS
==============================================================================
--- python/branches/release26-maint/Misc/NEWS (original)
+++ python/branches/release26-maint/Misc/NEWS Wed Sep 16 22:34:51 2009
@@ -12,6 +12,9 @@
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 #6707: dir() on an uninitialized module caused a crash.
Modified: python/branches/release26-maint/Objects/exceptions.c
==============================================================================
--- python/branches/release26-maint/Objects/exceptions.c (original)
+++ python/branches/release26-maint/Objects/exceptions.c Wed Sep 16 22:34:51 2009
@@ -301,30 +301,51 @@
static PyObject *
BaseException_get_message(PyBaseExceptionObject *self)
{
- int ret;
- ret = PyErr_WarnEx(PyExc_DeprecationWarning,
- "BaseException.message has been deprecated as "
- "of Python 2.6", 1);
- if (ret < 0)
- return NULL;
+ PyObject *msg;
+
+ /* if "message" is in self->dict, accessing a user-set message attribute */
+ if (self->dict &&
+ (msg = PyDict_GetItemString(self->dict, "message"))) {
+ Py_INCREF(msg);
+ return msg;
+ }
+
+ if (self->message == NULL) {
+ 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;
+ Py_INCREF(self->message);
+ return self->message;
}
static int
BaseException_set_message(PyBaseExceptionObject *self, PyObject *val)
{
- int ret;
- ret = PyErr_WarnEx(PyExc_DeprecationWarning,
- "BaseException.message has been deprecated as "
- "of Python 2.6", 1);
- if (ret < 0)
- return -1;
- Py_INCREF(val);
- Py_DECREF(self->message);
- self->message = val;
- return 0;
+ /* if val is NULL, delete the message attribute */
+ if (val == NULL) {
+ if (self->dict && PyDict_GetItemString(self->dict, "message")) {
+ if (PyDict_DelItemString(self->dict, "message") < 0)
+ return -1;
+ }
+ Py_XDECREF(self->message);
+ self->message = NULL;
+ 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[] = {
More information about the Python-checkins
mailing list