Commit 352c4191 authored by Jeroen Demeyer's avatar Jeroen Demeyer Committed by Stefan Behnel

Special-case setting __new__ in class (GH-3102)

parent 5cfa3bd4
......@@ -2297,8 +2297,10 @@ class NameNode(AtomicExprNode):
setter = 'PyDict_SetItem'
namespace = Naming.moddict_cname
elif entry.is_pyclass_attr:
code.globalstate.use_utility_code(UtilityCode.load_cached("SetNameInClass", "ObjectHandling.c"))
setter = '__Pyx_SetNameInClass'
# Special-case setting __new__
n = "SetNewInClass" if self.name == "__new__" else "SetNameInClass"
code.globalstate.use_utility_code(UtilityCode.load_cached(n, "ObjectHandling.c"))
setter = '__Pyx_' + n
else:
assert False, repr(entry)
code.put_error_if_neg(
......
......@@ -1218,6 +1218,30 @@ static PyObject *__Pyx__GetNameInClass(PyObject *nmspace, PyObject *name) {
#define __Pyx_SetNameInClass(ns, name, value) PyObject_SetItem(ns, name, value)
#endif
/////////////// SetNewInClass.proto ///////////////
static int __Pyx_SetNewInClass(PyObject *ns, PyObject *name, PyObject *value);
/////////////// SetNewInClass ///////////////
//@requires: SetNameInClass
// Special-case setting __new__: if it's a Cython function, wrap it in a
// staticmethod. This is similar to what Python does for a Python function
// called __new__.
static int __Pyx_SetNewInClass(PyObject *ns, PyObject *name, PyObject *value) {
#ifdef __Pyx_CyFunction_USED
int ret;
if (__Pyx_CyFunction_Check(value)) {
PyObject *staticnew = PyStaticMethod_New(value);
if (unlikely(!staticnew)) return -1;
ret = __Pyx_SetNameInClass(ns, name, staticnew);
Py_DECREF(staticnew);
return ret;
}
#endif
return __Pyx_SetNameInClass(ns, name, value);
}
/////////////// GetModuleGlobalName.proto ///////////////
//@requires: PyDictVersioning
......
"""
>>> X = make_class_with_new(cynew)
>>> X.__new__ is cynew
True
>>> X().__new__ is cynew
True
>>> def pynew(cls): return object.__new__(cls)
>>> X = make_class_with_new(pynew)
>>> X.__new__ is pynew
True
>>> X().__new__ is pynew
True
"""
def make_class_with_new(n):
class X(object):
__new__ = n
return X
def cynew(cls):
return object.__new__(cls)
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