Joran van Apeldoorn <g...@blubmail.nl> added the comment:

Digging around with the disassembler shows that this originates in the 
bytecode. 
Code:
--------
import dis
src = """
def printingdec(f):
    raise Exception()
    return f

def dummydec(f):
    return f

@printingdec
@dummydec
def foo():
    pass
"""
code = compile(src,filename="bug.py",mode='exec')
print(dis.dis(code))
--------- 

gives on 3.6:
  2           0 LOAD_CONST               0 (<code object printingdec at 
0x7f86c87171e0, file "bug.py", line 2>)
              2 LOAD_CONST               1 ('printingdec')
              4 MAKE_FUNCTION            0
              6 STORE_NAME               0 (printingdec)

  6           8 LOAD_CONST               2 (<code object dummydec at 
0x7f86c84b8660, file "bug.py", line 6>)
             10 LOAD_CONST               3 ('dummydec')
             12 MAKE_FUNCTION            0
             14 STORE_NAME               1 (dummydec)

  9          16 LOAD_NAME                0 (printingdec)

 10          18 LOAD_NAME                1 (dummydec)
             20 LOAD_CONST               4 (<code object foo at 0x7f86c84b8540, 
file "bug.py", line 9>)
             22 LOAD_CONST               5 ('foo')
             24 MAKE_FUNCTION            0
             26 CALL_FUNCTION            1
             28 CALL_FUNCTION            1
             30 STORE_NAME               2 (foo)
             32 LOAD_CONST               6 (None)
             34 RETURN_VALUE
None



and on 3.9:
  2           0 LOAD_CONST               0 (<code object printingdec at 
0x7f5e13aaca80, file "bug.py", line 2>)
              2 LOAD_CONST               1 ('printingdec')
              4 MAKE_FUNCTION            0
              6 STORE_NAME               0 (printingdec)

  6           8 LOAD_CONST               2 (<code object dummydec at 
0x7f5e13aacb30, file "bug.py", line 6>)
             10 LOAD_CONST               3 ('dummydec')
             12 MAKE_FUNCTION            0
             14 STORE_NAME               1 (dummydec)

  9          16 LOAD_NAME                0 (printingdec)

 10          18 LOAD_NAME                1 (dummydec)

 11          20 LOAD_CONST               4 (<code object foo at 0x7f5e13aacbe0, 
file "bug.py", line 9>)
             22 LOAD_CONST               5 ('foo')
             24 MAKE_FUNCTION            0
             26 CALL_FUNCTION            1
             28 CALL_FUNCTION            1
             30 STORE_NAME               2 (foo)
             32 LOAD_CONST               6 (None)
             34 RETURN_VALUE

Disassembly of <code object printingdec at 0x7f5e13aaca80, file "bug.py", line 
2>:
  3           0 LOAD_GLOBAL              0 (Exception)
              2 CALL_FUNCTION            0
              4 RAISE_VARARGS            1

  4           6 LOAD_FAST                0 (f)
              8 RETURN_VALUE

Disassembly of <code object dummydec at 0x7f5e13aacb30, file "bug.py", line 6>:
  7           0 LOAD_FAST                0 (f)
              2 RETURN_VALUE

Disassembly of <code object foo at 0x7f5e13aacbe0, file "bug.py", line 9>:
 12           0 LOAD_CONST               0 (None)
              2 RETURN_VALUE
None


The change from 3.6 seems to be that a new line number is introduced for 
instruction 20, loading the function code, which seems reasonable.
It would feel natural if the line number of the decorator would be used for 
instructions 26 & 28, the decorator call.

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue37971>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to