classification
Title: Add co_qualname attribute in code objects
Type: enhancement Stage: patch review
Components: Interpreter Core Versions: Python 3.3
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Arfrever, James.Pye, eric.snow, georg.brandl, jcea, meador.inge, pitrou
Priority: normal Keywords: patch

Created on 2011-12-28 19:19 by Arfrever, last changed 2013-04-13 19:26 by James.Pye.

Files
File name Uploaded Description Edit
issue13672-v0.patch meador.inge, 2012-01-24 20:09 review
Messages (9)
msg150312 - (view) Author: Arfrever Frehtes Taifersar Arahesis (Arfrever) * Date: 2011-12-28 19:19
PEP 3155 added qualified name as __qualname__ attribute in classes and functions. It would be useful if qualified name was also available as co_qualname attribute of code objects.

>>> import sys
>>> class A:
...     def f1():
...         return B.f2()
... 
>>> class B:
...     def f2():
...         return sys._getframe(1)
...
>>> A.f1.__name__
'f1'
>>> A.f1.__qualname__
'A.f1'
>>> B.f2.__name__
'f2'
>>> B.f2.__qualname__
'B.f2'
>>> frame = A.f1()
>>> frame
<frame object at 0x7f9c1adca3a0>
>>> frame.f_code
<code object f1 at 0x7f9c1ae4be40, file "<stdin>", line 2>
>>> frame.f_code.co_name
'f1'
>>> frame.f_code.co_qualname
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'code' object has no attribute 'co_qualname'


Suggested behavior:
>>> frame.f_code.co_qualname
'A.f1'
msg150313 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2011-12-28 20:08
with f_func (see #12857) you would get that for free:

>>> frame.f_func.__qualname__
'A.f1'
msg150316 - (view) Author: Arfrever Frehtes Taifersar Arahesis (Arfrever) * Date: 2011-12-28 20:36
co_qualname could still be useful if somebody has code object without frame object.
msg150317 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2011-12-28 21:11
True.  I wonder, though if perhaps a co_func (as a weak ref) or co_orig_func would be better, since co_qualname would be built from the original function anyway.  Then you could call "code.co_func.func_qualname".

One sticky point is that there isn't a guarantee of one-to-one between function object and code object.  A code object could be bound to several different functions as happens with function definitions (particularly lambdas) inside comprehensions.

Also, if a code object is not associated with a function, i.e. one generated by exec, what should the qualname for the code object be?  How about, in CPython, the code objects created for classes and modules?
msg151922 - (view) Author: Meador Inge (meador.inge) * (Python committer) Date: 2012-01-24 19:41
On Wed, Dec 28, 2011 at 3:11 PM, Eric Snow <report@bugs.python.org> wrote:

> One sticky point is that there isn't a guarantee of one-to-one between function object and code object.  A code object could be bound to several
> different functions as happens with function definitions (particularly lambdas) inside comprehensions.
>
> Also, if a code object is not associated with a function, i.e. one generated by exec, what should the qualname for the code object be?  How
> about, in CPython, the code objects created for classes and modules?

We already these issues with 'co_name', though.  These cases can be
treated the same as they are for 'co_name':

'<listcomp>'
>>> compile('[i for i in [1, 2]]', '<foo>', 'exec').co_consts[0].co_qualname
'<listcomp>'
>>> compile('class T: pass', '<foo>', 'exec').co_consts[0].co_qualname
'T'
>>> compile('class T: pass', '<foo>', 'exec').co_consts[0].co_name
'T'
>>> compile('a = 12', '<foo>', 'exec').co_name
'<module>'
>>> compile('a = 12', '<foo>', 'exec').co_qualname
'<module>'
>>> compile('lambda x: x', '<foo>', 'exec').co_consts[0].co_qualname
'<lambda>'
>>> compile('lambda x: x', '<foo>', 'exec').co_consts[0].co_name
'<lambda>'
msg151924 - (view) Author: Meador Inge (meador.inge) * (Python committer) Date: 2012-01-24 20:09
This seems to be a useful feature to me.  Another area where it can help
is with fixing function types.  Currently the qualname can be lost:

>>> def f():
...    def g():
...       pass
...    return g
... 
>>> g = f()
>>> g
<function f.<locals>.g at 0x7f1dac4d8ba0>
>>> types.FunctionType(f.__code__, {})
<function f at 0x7f1dac4dfae0>
>>> types.FunctionType(g.__code__, {})

There is no way to specify a qualname when constructing a
'FunctionType'.  The name is derived from the code object.  The
qualname could be too if we fix this issue.  I will open another issue
for the 'FunctionType' problem.

I have attached a WIP patch.  It passes the full test suite.  I am 
somewhat unsure about the CAPI changes, though.  They are a breaking API
change.  Do we need a *_QualName version instead like we did for
'PyFunction_NewWithQualName'?  I think probably so.  I will add doc
updates to the patch once the API stuff gets worked out.
msg164011 - (view) Author: Arfrever Frehtes Taifersar Arahesis (Arfrever) * Date: 2012-06-25 20:17
Could this patch be included in Python 3.3?
msg164012 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2012-06-25 20:20
PyCode_New and PyCode_NewEmpty are documented public APIs, so you can't change their signatures like that.
msg186802 - (view) Author: James Pye (James.Pye) Date: 2013-04-13 19:26
Considering the API changes necessary for adding qualname, perhaps a better solution would be to just start using the qualname instead of the function's "basename"--co_name is the qualname. This would offer an automatic improvement to the readability of coverage/profiling tool reports. Admittedly, not sure what kind of breakage might ensue... =\
History
Date User Action Args
2013-04-13 19:26:10James.Pyesetnosy: + James.Pye
messages: + msg186802
2012-06-25 20:20:07pitrousetnosy: + georg.brandl

messages: + msg164012
stage: needs patch -> patch review
2012-06-25 20:17:38Arfreversetmessages: + msg164011
2012-01-24 20:09:55meador.ingesetfiles: + issue13672-v0.patch
keywords: + patch
messages: + msg151924
2012-01-24 19:41:25meador.ingesetmessages: + msg151922
2011-12-28 23:11:17meador.ingesetnosy: + meador.inge

type: enhancement
stage: needs patch
2011-12-28 22:36:29jceasetnosy: + jcea
2011-12-28 21:11:24eric.snowsetmessages: + msg150317
2011-12-28 20:36:35Arfreversetmessages: + msg150316
2011-12-28 20:08:10eric.snowsetnosy: + eric.snow
messages: + msg150313
2011-12-28 19:19:59Arfrevercreate