Commit 08a9b939 authored by Robert Bradshaw's avatar Robert Bradshaw

Fix classmethod for non-cdef classes.

parent cd1f577d
......@@ -1343,7 +1343,7 @@ def p_statement(s, level, cdef_flag = 0, visibility = 'private', api = 0):
elif s.sy == 'pass' and level <> 'property':
return p_pass_statement(s, with_newline = 1)
else:
if level in ('c_class', 'c_class_pxd', 'property'):
if level in ('c_class_pxd', 'property'):
s.error("Executable statement not allowed here")
if s.sy == 'if':
return p_if_statement(s)
......
......@@ -1071,6 +1071,21 @@ class ClassScope(Scope):
def add_string_const(self, value):
return self.outer_scope.add_string_const(value)
def lookup(self, name):
if name == "classmethod":
# We don't want to use the builtin classmethod here 'cause it won't do the
# right thing in this scope (as the class memebers aren't still functions).
# Don't want to add a cfunction to this scope 'cause that would mess with
# the type definition, so we just return the right entry.
self.use_utility_code(classmethod_utility_code)
entry = Entry("classmethod",
"__Pyx_Method_ClassMethod",
CFuncType(py_object_type, [CFuncTypeArg("", py_object_type, None)], 0, 0))
entry.is_cfunction = 1
return entry
else:
return Scope.lookup(self, name)
class PyClassScope(ClassScope):
# Namespace of a Python class.
......@@ -1290,21 +1305,6 @@ class CClassScope(ClassScope):
def release_temp(self, cname):
return Scope.release_temp(self.global_scope(), cname)
def lookup(self, name):
if name == "classmethod":
# We don't want to use the builtin classmethod here 'cause it won't do the
# right thing in this scope (as the class memebers aren't still functions).
# Don't want to add a cfunction to this scope 'cause that would mess with
# the type definition, so we just return the right entry.
self.use_utility_code(classmethod_utility_code)
entry = Entry("classmethod",
"__Pyx_Method_ClassMethod",
CFuncType(py_object_type, [CFuncTypeArg("", py_object_type, None)], 0, 0))
entry.is_cfunction = 1
return entry
else:
return Scope.lookup(self, name)
class PropertyScope(Scope):
# Scope holding the __get__, __set__ and __del__ methods for
......@@ -1337,12 +1337,15 @@ static PyObject* __Pyx_Method_ClassMethod(PyObject *method); /*proto*/
static PyObject* __Pyx_Method_ClassMethod(PyObject *method) {
/* It appears that PyMethodDescr_Type is not anywhere exposed in the Python/C API */
/* if (!PyObject_TypeCheck(method, &PyMethodDescr_Type)) { */
if (strcmp(method->ob_type->tp_name, "method_descriptor") != 0) {
PyErr_Format(PyExc_TypeError, "Extension type classmethod() can only be called on a method_descriptor.");
return NULL;
if (strcmp(method->ob_type->tp_name, "method_descriptor") == 0) { /* cdef classes */
PyMethodDescrObject *descr = (PyMethodDescrObject *)method;
return PyDescr_NewClassMethod(descr->d_type, descr->d_method);
}
else if (PyMethod_Check(method)) { /* python classes */
return PyClassMethod_New(PyMethod_GET_FUNCTION(method));
}
PyMethodDescrObject *descr = (PyMethodDescrObject *)method;
return PyDescr_NewClassMethod(descr->d_type, descr->d_method);
PyErr_Format(PyExc_TypeError, "Class-level classmethod() can only be called on a method_descriptor or instance method.");
return 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