Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Python: Checkins

cpython (2.7): fix calling the classmethod descriptor directly (closes #14699)

 

 

Python checkins RSS feed   Index | Next | Previous | View Threaded


python-checkins at python

May 1, 2012, 6:56 AM

Post #1 of 1 (44 views)
Permalink
cpython (2.7): fix calling the classmethod descriptor directly (closes #14699)

http://hg.python.org/cpython/rev/6484f5a51285
changeset: 76698:6484f5a51285
branch: 2.7
parent: 76679:4c3c4891fd6a
user: Benjamin Peterson <benjamin [at] python>
date: Tue May 01 09:51:09 2012 -0400
summary:
fix calling the classmethod descriptor directly (closes #14699)

files:
Lib/test/test_descr.py | 16 ++++++++++
Misc/NEWS | 2 +
Objects/descrobject.c | 44 +++++++++++++++++++++++++++--
3 files changed, 59 insertions(+), 3 deletions(-)


diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -1419,6 +1419,22 @@
self.assertEqual(x, spam.spamlist)
self.assertEqual(a, a1)
self.assertEqual(d, d1)
+ spam_cm = spam.spamlist.__dict__['classmeth']
+ x2, a2, d2 = spam_cm(spam.spamlist, *a, **d)
+ self.assertEqual(x2, spam.spamlist)
+ self.assertEqual(a2, a1)
+ self.assertEqual(d2, d1)
+ class SubSpam(spam.spamlist): pass
+ x2, a2, d2 = spam_cm(SubSpam, *a, **d)
+ self.assertEqual(x2, SubSpam)
+ self.assertEqual(a2, a1)
+ self.assertEqual(d2, d1)
+ with self.assertRaises(TypeError):
+ spam_cm()
+ with self.assertRaises(TypeError):
+ spam_cm(spam.spamlist())
+ with self.assertRaises(TypeError):
+ spam_cm(list)

def test_staticmethods(self):
# Testing static methods...
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -9,6 +9,8 @@
Core and Builtins
-----------------

+- Issue #14699: Fix calling the classmethod descriptor directly.
+
- Issue #11603 (again): Setting __repr__ to __str__ now raises a RuntimeError
when repr() or str() is called on such an object.

diff --git a/Objects/descrobject.c b/Objects/descrobject.c
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -254,14 +254,52 @@
classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
PyObject *kwds)
{
- PyObject *func, *result;
+ Py_ssize_t argc;
+ PyObject *self, *func, *result;

- func = PyCFunction_New(descr->d_method, (PyObject *)descr->d_type);
+ /* Make sure that the first argument is acceptable as 'self' */
+ assert(PyTuple_Check(args));
+ argc = PyTuple_GET_SIZE(args);
+ if (argc < 1) {
+ PyErr_Format(PyExc_TypeError,
+ "descriptor '%V' of '%.100s' "
+ "object needs an argument",
+ descr_name((PyDescrObject *)descr), "?",
+ descr->d_type->tp_name);
+ return NULL;
+ }
+ self = PyTuple_GET_ITEM(args, 0);
+ if (!PyType_Check(self)) {
+ PyErr_Format(PyExc_TypeError,
+ "descriptor '%V' requires a type "
+ "but received a '%.100s'",
+ descr_name((PyDescrObject *)descr), "?",
+ descr->d_type->tp_name,
+ self->ob_type->tp_name);
+ return NULL;
+ }
+ if (!PyType_IsSubtype((PyTypeObject *)self, descr->d_type)) {
+ PyErr_Format(PyExc_TypeError,
+ "descriptor '%V' "
+ "requires a subtype of '%.100s' "
+ "but received '%.100s",
+ descr_name((PyDescrObject *)descr), "?",
+ descr->d_type->tp_name,
+ self->ob_type->tp_name);
+ return NULL;
+ }
+
+ func = PyCFunction_New(descr->d_method, self);
if (func == NULL)
return NULL;
-
+ args = PyTuple_GetSlice(args, 1, argc);
+ if (args == NULL) {
+ Py_DECREF(func);
+ return NULL;
+ }
result = PyEval_CallObjectWithKeywords(func, args, kwds);
Py_DECREF(func);
+ Py_DECREF(args);
return result;
}


--
Repository URL: http://hg.python.org/cpython

Python checkins RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.