Author eryksun
Recipients Stanisław Skonieczny (Uosiu), eryksun
Date 2015-11-25.17:47:17
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1448473638.59.0.581945004588.issue25731@psf.upfronthosting.co.za>
In-reply-to
Content
For "del X.__new__", type_setattro in Objects/typeobject.c indirectly calls update_one_slot. This finds object.__new__ fom the base object class when it looks up __new__ on the type. Since __new__ for built-in types is special-cased to be a built-in method instead of a slot wrapper, update_one_slot takes the branch for "Py_TYPE(descr) == &PyCFunction_Type", which assigns the existing tp_new to "specific". In this case that's slot_tp_new instead of object_new due to the previous assignment of the "new" function to X.__new__.  

slot_tp_new looks up and calls __new__, which in this case, as noted above, is object.__new__. This built-in method calls tp_new_wrapper, which calls the wrapped tp_new function. In this case that's object_new. If the type's tp_init is object_init (i.e. not overridden) or tp_new is not object_new (i.e. overridden), then object_new raises a TypeError when called with arguments. The problem in this case is that __new__ isn't overridden anymore. 

It seems to me that update_one_slot needs to install the tp_new that tp_new_wrapper would call, e.g. 

    specific = (void *)(
                 (PyTypeObject *)PyCFunction_GET_SELF(descr))->tp_new;

In this case that's object_new. Thus after "del X.__new__", X would be restored as if __new__ was never overridden.
History
Date User Action Args
2015-11-25 17:47:18eryksunsetrecipients: + eryksun, StanisÅ‚aw Skonieczny (Uosiu)
2015-11-25 17:47:18eryksunsetmessageid: <1448473638.59.0.581945004588.issue25731@psf.upfronthosting.co.za>
2015-11-25 17:47:18eryksunlinkissue25731 messages
2015-11-25 17:47:17eryksuncreate