Issue 805304: super instances don't support item assignment (original) (raw)

Created on 2003-09-12 20:10 by fdrake, last changed 2022-04-10 16:11 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
abstract2.diff rhettinger,2003-09-14 02:07 Diff for Objects\abstract.c using &PySuper_Type
Messages (6)
msg18148 - (view) Author: Fred Drake (fdrake) (Python committer) Date: 2003-09-12 20:10
This snippet produces a TypeError in Python 2.2.3, 2.3, and CVS: class C(object): def __setitem__(self, name, value): print (name, value) class D(C): def __setitem__(self, name, value): super(D, self)[name] = value d = D() d['foo'] = 'bar' Here's the traceback: Traceback (most recent call last): File "/home/fdrake/tmp/setitem.py", line 10, in ? d['foo'] = 'bar' File "/home/fdrake/tmp/setitem.py", line 7, in __setitem__ super(D, self)[name] = value TypeError: object does not support item assignment The problem appears to be that the item assignment isn't getting mapped to the __setitem__ of the base class, so this is probably somewhere deep in Objects/typeobject.c.
msg18149 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2003-09-13 06:50
Logged In: YES user_id=80475 This one is tough. All of super's magic happens with descriptors upon attribute lookup. The example above will work fine if the call were written as: "super(D, self).__setitem__(name)". However, when written as "super(D, self)[name]", ceval.c triggers a STORE_SUBSCR opcode which calls PyObject_SetItem which in turns looks directly at the super object's type table (and finding nothing). Nowhere in this process is an attribute lookup called or a descriptor invoked. The current implementation waits until attribute binding time to search the bases. Hence, at the time the super object is created, it doesn't know enough information to fill out its table about which methods will be available. Consequently, direct table probes will fail. To make a general purpose fix would be a mess and involves changing the semantics of super to do its base search at the time the super object is created and to fillout its table with the appropriate methods. Unfortunately, any dynamic changes to the methods in the base object would *not* get reflected at lookup. There may be a reasonable special purpose fix. Fill-out the entire superobject table with custom methods that trigger an attribute lookup. For instance, fillout the sq_ass_item slot with a function that calls self.__setitem__ which will trigger the attribute search. Even this approach has problems because the super object has no way of knowing in advance whether sq_ass_item or mp_ass_subscript is the appropriate method for the object being referred to (is it a mapping or a sequence?). I recommend punting on this one and documenting that direct syntax manipulation of super objects is not defined and the super().__special_method__ format be used instead. Perhaps, all of super's unfilled slots can be filled with a placeholder method that emits an explanatory error message.
msg18150 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2003-09-13 23:19
Logged In: YES user_id=80475 Okay, let's apply the two-step problem solving approach. First, declare the problem impossible to solve. Then, propose a solution ;-) The attached patch is a proof-of-concept. It teaches PyObject_SetItem to use an attribute lookup for super objects whenever a direct table lookup fails. If the approach is approved, the final version of the patch should also address PyObject_GetItem and other ways that the attribute lookup mechanism can be bypassed. Also, the test for super can be improved by adding PySuper_Check() to the typeobject.c API. Of course, there is also the question as to whether fixing this is a bug or a feature. It does enable a whole set of programs to run under Py2.3.1 and Py2.2.4 that would not run under Py2.3.0 and Py2.2.3.
msg18151 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2003-09-16 04:48
Logged In: YES user_id=80475 Referring to Guido for pronouncement. I've been thinking that this one could be left alone and just document that super objects only do their magic upon explicit attribute lookup. Otherwise, fixing it completely involves combing Python for every place that directly calls functions from the slots table, and then adding a followup call using attribute lookup if the slot is empty. When it comes to functions like repr(obj), I think we want the super object to identify itself rather than forwarding the call to the target object's __repr__() method. The downside of leaving it alone is that it breaks the symmetry between obj[k] and obj.__getitem__[k].
msg18152 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2004-03-20 22:56
Logged In: YES user_id=6380 This should be coded as Raymond originally recommended: super(D, self).__setitem__(name, value). Raymond, can you update the docs?
msg18153 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2004-08-17 02:22
Logged In: YES user_id=80475 Documented in Doc/lib/libfuncs.tex 1.173.
History
Date User Action Args
2022-04-10 16:11:08 admin set github: 39223
2003-09-12 20:10:43 fdrake create