This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: super passes bad arguments to __get__ when used w/class
Type: Stage:
Components: Interpreter Core Versions: Python 2.3
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: pje Nosy List: gvanrossum, mwh, pje
Priority: normal Keywords:

Created on 2003-05-25 18:00 by pje, last changed 2022-04-10 16:08 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
descrpatch pje, 2004-03-06 12:35 Patch against CVS head
Messages (9)
msg16153 - (view) Author: PJ Eby (pje) * (Python committer) Date: 2003-05-25 18:00
Run the following code to demonstrate the issue:

====
class Getter(object):
    def __get__(self, ob, typ=None):
        print "called with", (ob, typ)

class Base(object):
    foo = Getter()

class Subclass(Base):
    pass

print
print

Base().foo
Subclass().foo
super(Subclass,Subclass()).foo

Base.foo
Subclass.foo
super(Subclass,Subclass).foo
====

Notice that super(Subclass,Subclass).foo is calling the
descriptor with the *class* object, not 'None' as is
done for the analagous cases that don't use super().

The only reason this ever "works" is because
'classmethod' ignores the 'ob' parameter to '__get__'.
 However, this breaks when using 'super' to access
property descriptors in 2.3, and it will also break any
user-defined descriptors that are accessed via super().

The behavior is the same in 2.2, and is arguably broken
there as well.  For example,
'super(someclass,someclass).X' (where 'X' is a normal
instance method) results in X being a *bound* method,
bound to the class, rather than an *unbound* method,
ready for use with an explicit instance.

Personally, I would be happy if super() grew an extra
argument to disambiguate whether you are doing a
(class,instance) or (class,class) call, anyway.  When
using super() with metaclasses, I've encountered
situations where super() guessed wrong, because I was
using a type that was both an instance of, and a
subclass of, the same type.  Being able to explicitly
request that this "class method" form of super is being
used, would eliminate this confusion as well.  In the
face of ambiguity... ;)
msg16154 - (view) Author: PJ Eby (pje) * (Python committer) Date: 2004-02-25 07:06
Logged In: YES 
user_id=56214

Assigning to Guido to request pronouncement on the correct
way to fix this before I attempt to create patch(es).
msg16155 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2004-02-25 15:57
Logged In: YES 
user_id=6380

> However, this breaks when using 'super' to access
> property descriptors in 2.3, and it will also break any
> user-defined descriptors that are accessed via super().

Can you give an example of this use case?

I don't have a strong opinion on this; methinks you should
go ahead and prepa patch...
msg16156 - (view) Author: PJ Eby (pje) * (Python committer) Date: 2004-02-25 19:06
Logged In: YES 
user_id=56214

super().descriptor example:

class Base(object):
    aProp = property(lambda self: "foo")

class Sub(Base):
    def test(klass):
        print super(Sub,klass).aProp
    test = classmethod(test)

Sub.test()

This prints "foo", when it should print "<property object at
0x4024f84c>" instead.

To be precise, the issue is that accessing any descriptor
that behaves differently when retrieved on the class vs. the
instance, will behave incorrectly when accessed via super()
from a classmethod in a subclass.  Classmethods themselves
work correctly because they behave the same way no matter
how you retrieve them.

At present I think the patch should simply change the
descr_get call in super_getattro so that it checks whether
su->obj==su->obj_type, and if so, pass in NULL instead of
su->obj as the second argument to descr_get.

Should I create this patch against the 2.3 maintenance
branch, or against the head?  I'd like to make sure it gets
into the next 2.3.x bugfix release.  (I didn't realize this
bug was still open until I stumbled across it the other day,
and I'm not expecting to upgrade to 2.3 production use for a
few months yet.  I've been using a pure-Python
reimplementation of super() as a workaround.)
msg16157 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2004-02-25 19:09
Logged In: YES 
user_id=6656

I don't think you'll find any difference between the trunk
and release23-maint in this area, so it doesn't make much
difference.
msg16158 - (view) Author: PJ Eby (pje) * (Python committer) Date: 2004-03-06 12:35
Logged In: YES 
user_id=56214

Here's a patch against the CVS head to add a test for the
problem, and fix it.  Please backport to the 2.3 branch as
well.  Thanks!
msg16159 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2004-03-20 22:54
Logged In: YES 
user_id=6380

Phillip, now that you have CVS perms, please check this in
yourself (and backport).
msg16160 - (view) Author: PJ Eby (pje) * (Python committer) Date: 2004-03-25 02:49
Logged In: YES 
user_id=56214

Committed and backported.
msg16161 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2004-03-29 11:23
Logged In: YES 
user_id=6656

Phillip, it's a bit less of an issue as you've already backported this, 
but it helps if you mention the fixing revisions of the various files 
in the bug report.  Conversely, you should mention the bug # in 
the checkin message, but you did that already :-)
History
Date User Action Args
2022-04-10 16:08:54adminsetgithub: 38548
2003-05-25 18:00:46pjecreate