classification
Title: weird dual behavior with changing __qualname__; different values observed through attribute and descriptor
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 3.4, Python 3.3
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: benjamin.peterson, christopherthemagnificent, ezio.melotti, pitrou, python-dev
Priority: normal Keywords: patch

Created on 2012-10-17 23:43 by christopherthemagnificent, last changed 2012-10-31 04:08 by python-dev. This issue is now closed.

Files
File name Uploaded Description Edit
parser_BUGGY2.py christopherthemagnificent, 2012-10-17 23:43 contains the code that reveals the presumed bug in Python
qualname-in-dict.patch benjamin.peterson, 2012-10-26 06:40 review
qualname2.patch benjamin.peterson, 2012-10-26 21:04 review
Messages (7)
msg173217 - (view) Author: Christopher the Magnificent (christopherthemagnificent) Date: 2012-10-17 23:43
The output below is NOT typed at the Python interactive interpeter.  The ">>> " shows what is being evaluated and the line below it shows what the result it.

The output gets generated here:  (lines 418-449 of the attached file)

    def name_globalize_class(name, second=None):
        def decorator(cls):
            
            def printval(source, value=None):
                print(">>> " + source)
                if value is not None:
                    print(repr(value))
            print("in decorator: new name is:", repr(name))
            print()
            printval("cls", cls)
            printval("cls.__name__", cls.__name__)
            printval("cls.__qualname__", cls.__qualname__)
            printval('type.__dict__["__qualname__"].__get__(cls)',
                     type.__dict__["__qualname__"].__get__(cls))
            print()
            
            cls.__name__ = name
            cls.__qualname__ = name
            
            stuff = ">>> cls.__name__ = {0}\n>>> cls.__qualname__ = {0}\n"
            print(stuff.format(repr(name)))
            
            printval("cls.__name__", cls.__name__)
            printval("cls.__qualname__", cls.__qualname__)
            printval('type.__dict__["__qualname__"].__get__(cls)',
                     type.__dict__["__qualname__"].__get__(cls))
            printval("cls", cls)
            print()
            globals()[name] = cls
            pdb.set_trace()
            return cls
        return decorator
    
HERE IS THE OUTPUT:

>>> cls
<class '__main__._maketokensnodes.<locals>._TokenClass'>
>>> cls.__name__
'_TokenClass'
>>> cls.__qualname__
'_maketokensnodes.<locals>._TokenClass'
>>> type.__dict__["__qualname__"].__get__(cls)
'_maketokensnodes.<locals>._TokenClass'

>>> cls.__name__ = 'KEYWORD'
>>> cls.__qualname__ = 'KEYWORD'

>>> cls.__name__
'KEYWORD'
>>> cls.__qualname__
'KEYWORD'
>>> type.__dict__["__qualname__"].__get__(cls)
'_maketokensnodes.<locals>._TokenClass'
>>> cls
<class '__main__._maketokensnodes.<locals>._TokenClass'>

END OF OUTPUT

Note how after assigning to cls.__qualname__ it looks like the class's dictionary object has been assigned into, masking the class's C-level type attribute-level ht_qualname!

My gut feeling is that this has to be some kind of a bug.  Let me know if it is.
msg173822 - (view) Author: Benjamin Peterson (benjamin.peterson) * (Python committer) Date: 2012-10-26 06:40
Here's a patch for 3.4. __qualname__ ought to have been implemented this way in the first place. I'll have to think about what can be done about 3.3. Maybe just the same fix without the removal of PyHeapType.ht_qualname. We can hope no one has written extensions relying on its value actually being correct.
msg173823 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2012-10-26 07:02
I'm not sure why this would be the correct way to do it. First you are removing the unicode check, which looks wrong to me. Second, if ht_name works, perhaps ht_qualname can be made to work as well?
msg173854 - (view) Author: Benjamin Peterson (benjamin.peterson) * (Python committer) Date: 2012-10-26 15:40
Was does qualname need to be on the struct?
msg173857 - (view) Author: Benjamin Peterson (benjamin.peterson) * (Python committer) Date: 2012-10-26 15:53
s/Was/Why/
msg173889 - (view) Author: Benjamin Peterson (benjamin.peterson) * (Python committer) Date: 2012-10-26 21:04
Here's the other option.
msg174261 - (view) Author: Roundup Robot (python-dev) Date: 2012-10-31 04:08
New changeset 1d700e1aff33 by Benjamin Peterson in branch '3.3':
don't shadow the __qualname__ descriptor with __qualname__ in the class's __dict__ (closes #16271)
http://hg.python.org/cpython/rev/1d700e1aff33
History
Date User Action Args
2012-10-31 04:08:12python-devsetstatus: open -> closed

nosy: + python-dev
messages: + msg174261

resolution: fixed
stage: resolved
2012-10-26 21:04:06benjamin.petersonsetfiles: + qualname2.patch

messages: + msg173889
2012-10-26 15:53:12benjamin.petersonsetmessages: + msg173857
2012-10-26 15:40:53benjamin.petersonsetmessages: + msg173854
2012-10-26 07:02:57pitrousetmessages: + msg173823
2012-10-26 06:40:49benjamin.petersonsetfiles: + qualname-in-dict.patch

nosy: + benjamin.peterson
messages: + msg173822

keywords: + patch
2012-10-25 17:27:57ezio.melottisetnosy: + pitrou, ezio.melotti

type: behavior
versions: + Python 3.4
2012-10-17 23:43:06christopherthemagnificentcreate