0
0
mirror of https://github.com/python/cpython.git synced 2024-11-24 00:38:00 +01:00

gh-126072: do not add None to co_consts if there is no docstring (GH-126101)

This commit is contained in:
Xuanteng Huang 2024-10-30 17:01:09 +08:00 committed by GitHub
parent 2ab377a47c
commit 35df4eb959
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 148 additions and 58 deletions

View File

@ -1700,6 +1700,14 @@ which is a bitmap of the following flags:
.. versionadded:: 3.6 .. versionadded:: 3.6
.. data:: CO_HAS_DOCSTRING
The flag is set when there is a docstring for the code object in
the source code. If set, it will be the first item in
:attr:`~codeobject.co_consts`.
.. versionadded:: 3.14
.. note:: .. note::
The flags are specific to CPython, and may not be defined in other The flags are specific to CPython, and may not be defined in other
Python implementations. Furthermore, the flags are an implementation Python implementations. Furthermore, the flags are an implementation

View File

@ -1536,9 +1536,9 @@ Other bits in :attr:`~codeobject.co_flags` are reserved for internal use.
.. index:: single: documentation string .. index:: single: documentation string
If a code object represents a function, the first item in If a code object represents a function and has a docstring,
:attr:`~codeobject.co_consts` is the first item in :attr:`~codeobject.co_consts` is
the documentation string of the function, or ``None`` if undefined. the docstring of the function.
Methods on code objects Methods on code objects
~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -174,6 +174,11 @@ struct PyCodeObject _PyCode_DEF(1);
#define CO_NO_MONITORING_EVENTS 0x2000000 #define CO_NO_MONITORING_EVENTS 0x2000000
/* Whether the code object has a docstring,
If so, it will be the first item in co_consts
*/
#define CO_HAS_DOCSTRING 0x4000000
/* This should be defined if a future statement modifies the syntax. /* This should be defined if a future statement modifies the syntax.
For example, when a keyword is added. For example, when a keyword is added.
*/ */

View File

@ -123,6 +123,7 @@ typedef struct _symtable_entry {
unsigned ste_comp_iter_target : 1; /* true if visiting comprehension target */ unsigned ste_comp_iter_target : 1; /* true if visiting comprehension target */
unsigned ste_can_see_class_scope : 1; /* true if this block can see names bound in an unsigned ste_can_see_class_scope : 1; /* true if this block can see names bound in an
enclosing class scope */ enclosing class scope */
unsigned ste_has_docstring : 1; /* true if docstring present */
int ste_comp_iter_expr; /* non-zero if visiting a comprehension range expression */ int ste_comp_iter_expr; /* non-zero if visiting a comprehension range expression */
_Py_SourceLocation ste_loc; /* source location of block */ _Py_SourceLocation ste_loc; /* source location of block */
struct _symtable_entry *ste_annotation_block; /* symbol table entry for this entry's annotations */ struct _symtable_entry *ste_annotation_block; /* symbol table entry for this entry's annotations */

View File

@ -161,6 +161,7 @@ COMPILER_FLAG_NAMES = {
128: "COROUTINE", 128: "COROUTINE",
256: "ITERABLE_COROUTINE", 256: "ITERABLE_COROUTINE",
512: "ASYNC_GENERATOR", 512: "ASYNC_GENERATOR",
0x4000000: "HAS_DOCSTRING",
} }
def pretty_flags(flags): def pretty_flags(flags):

View File

@ -56,6 +56,7 @@ __all__ = [
"CO_OPTIMIZED", "CO_OPTIMIZED",
"CO_VARARGS", "CO_VARARGS",
"CO_VARKEYWORDS", "CO_VARKEYWORDS",
"CO_HAS_DOCSTRING",
"ClassFoundException", "ClassFoundException",
"ClosureVars", "ClosureVars",
"EndOfBlock", "EndOfBlock",
@ -409,6 +410,7 @@ def iscode(object):
co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg
| 16=nested | 32=generator | 64=nofree | 128=coroutine | 16=nested | 32=generator | 64=nofree | 128=coroutine
| 256=iterable_coroutine | 512=async_generator | 256=iterable_coroutine | 512=async_generator
| 0x4000000=has_docstring
co_freevars tuple of names of free variables co_freevars tuple of names of free variables
co_posonlyargcount number of positional only arguments co_posonlyargcount number of positional only arguments
co_kwonlyargcount number of keyword only arguments (not including ** arg) co_kwonlyargcount number of keyword only arguments (not including ** arg)

View File

@ -17,7 +17,7 @@ cellvars: ('x',)
freevars: () freevars: ()
nlocals: 2 nlocals: 2
flags: 3 flags: 3
consts: ('None', '<code object g>') consts: ('<code object g>',)
>>> dump(f(4).__code__) >>> dump(f(4).__code__)
name: g name: g
@ -86,7 +86,7 @@ varnames: ()
cellvars: () cellvars: ()
freevars: () freevars: ()
nlocals: 0 nlocals: 0
flags: 3 flags: 67108867
consts: ("'doc string'", 'None') consts: ("'doc string'", 'None')
>>> def keywordonly_args(a,b,*,k1): >>> def keywordonly_args(a,b,*,k1):
@ -123,6 +123,61 @@ nlocals: 3
flags: 3 flags: 3
consts: ('None',) consts: ('None',)
>>> def has_docstring(x: str):
... 'This is a one-line doc string'
... x += x
... x += "hello world"
... # co_flags should be 0x4000003 = 67108867
... return x
>>> dump(has_docstring.__code__)
name: has_docstring
argcount: 1
posonlyargcount: 0
kwonlyargcount: 0
names: ()
varnames: ('x',)
cellvars: ()
freevars: ()
nlocals: 1
flags: 67108867
consts: ("'This is a one-line doc string'", "'hello world'")
>>> async def async_func_docstring(x: str, y: str):
... "This is a docstring from async function"
... import asyncio
... await asyncio.sleep(1)
... # co_flags should be 0x4000083 = 67108995
... return x + y
>>> dump(async_func_docstring.__code__)
name: async_func_docstring
argcount: 2
posonlyargcount: 0
kwonlyargcount: 0
names: ('asyncio', 'sleep')
varnames: ('x', 'y', 'asyncio')
cellvars: ()
freevars: ()
nlocals: 3
flags: 67108995
consts: ("'This is a docstring from async function'", 'None')
>>> def no_docstring(x, y, z):
... return x + "hello" + y + z + "world"
>>> dump(no_docstring.__code__)
name: no_docstring
argcount: 3
posonlyargcount: 0
kwonlyargcount: 0
names: ()
varnames: ('x', 'y', 'z')
cellvars: ()
freevars: ()
nlocals: 3
flags: 3
consts: ("'hello'", "'world'")
""" """
import copy import copy

View File

@ -834,7 +834,7 @@ class TestSpecifics(unittest.TestCase):
return "unused" return "unused"
self.assertEqual(f.__code__.co_consts, self.assertEqual(f.__code__.co_consts,
(None, "used")) (True, "used"))
@support.cpython_only @support.cpython_only
def test_remove_unused_consts_extended_args(self): def test_remove_unused_consts_extended_args(self):
@ -852,9 +852,9 @@ class TestSpecifics(unittest.TestCase):
eval(compile(code, "file.py", "exec"), g) eval(compile(code, "file.py", "exec"), g)
exec(code, g) exec(code, g)
f = g['f'] f = g['f']
expected = tuple([None, ''] + [f't{i}' for i in range(N)]) expected = tuple([''] + [f't{i}' for i in range(N)])
self.assertEqual(f.__code__.co_consts, expected) self.assertEqual(f.__code__.co_consts, expected)
expected = "".join(expected[2:]) expected = "".join(expected[1:])
self.assertEqual(expected, f()) self.assertEqual(expected, f())
# Stripping unused constants is not a strict requirement for the # Stripping unused constants is not a strict requirement for the
@ -1244,7 +1244,7 @@ class TestSpecifics(unittest.TestCase):
y) y)
genexp_lines = [0, 4, 2, 0, 4] genexp_lines = [0, 4, 2, 0, 4]
genexp_code = return_genexp.__code__.co_consts[1] genexp_code = return_genexp.__code__.co_consts[0]
code_lines = self.get_code_lines(genexp_code) code_lines = self.get_code_lines(genexp_code)
self.assertEqual(genexp_lines, code_lines) self.assertEqual(genexp_lines, code_lines)

View File

@ -84,7 +84,7 @@ class IsolatedAssembleTests(AssemblerTestCase):
return x return x
return inner() % 2 return inner() % 2
inner_code = mod_two.__code__.co_consts[1] inner_code = mod_two.__code__.co_consts[0]
assert isinstance(inner_code, types.CodeType) assert isinstance(inner_code, types.CodeType)
metadata = { metadata = {

View File

@ -197,7 +197,7 @@ dis_bug1333982 = """\
%3d RESUME 0 %3d RESUME 0
%3d LOAD_COMMON_CONSTANT 0 (AssertionError) %3d LOAD_COMMON_CONSTANT 0 (AssertionError)
LOAD_CONST 1 (<code object <genexpr> at 0x..., file "%s", line %d>) LOAD_CONST 0 (<code object <genexpr> at 0x..., file "%s", line %d>)
MAKE_FUNCTION MAKE_FUNCTION
LOAD_FAST 0 (x) LOAD_FAST 0 (x)
GET_ITER GET_ITER
@ -276,10 +276,10 @@ dis_kw_names = """\
LOAD_SMALL_INT 1 LOAD_SMALL_INT 1
LOAD_SMALL_INT 2 LOAD_SMALL_INT 2
LOAD_SMALL_INT 5 LOAD_SMALL_INT 5
LOAD_CONST 1 (('c',)) LOAD_CONST 0 (('c',))
CALL_KW 3 CALL_KW 3
POP_TOP POP_TOP
LOAD_CONST 0 (None) LOAD_CONST 1 (None)
RETURN_VALUE RETURN_VALUE
""" % (wrap_func_w_kwargs.__code__.co_firstlineno, """ % (wrap_func_w_kwargs.__code__.co_firstlineno,
wrap_func_w_kwargs.__code__.co_firstlineno + 1) wrap_func_w_kwargs.__code__.co_firstlineno + 1)
@ -500,18 +500,18 @@ dis_fstring = """\
%3d LOAD_FAST 0 (a) %3d LOAD_FAST 0 (a)
FORMAT_SIMPLE FORMAT_SIMPLE
LOAD_CONST 1 (' ') LOAD_CONST 0 (' ')
LOAD_FAST 1 (b) LOAD_FAST 1 (b)
LOAD_CONST 2 ('4') LOAD_CONST 1 ('4')
FORMAT_WITH_SPEC FORMAT_WITH_SPEC
LOAD_CONST 1 (' ') LOAD_CONST 0 (' ')
LOAD_FAST 2 (c) LOAD_FAST 2 (c)
CONVERT_VALUE 2 (repr) CONVERT_VALUE 2 (repr)
FORMAT_SIMPLE FORMAT_SIMPLE
LOAD_CONST 1 (' ') LOAD_CONST 0 (' ')
LOAD_FAST 3 (d) LOAD_FAST 3 (d)
CONVERT_VALUE 2 (repr) CONVERT_VALUE 2 (repr)
LOAD_CONST 2 ('4') LOAD_CONST 1 ('4')
FORMAT_WITH_SPEC FORMAT_WITH_SPEC
BUILD_STRING 7 BUILD_STRING 7
RETURN_VALUE RETURN_VALUE
@ -785,7 +785,7 @@ dis_nested_0 = """\
%4d LOAD_FAST 0 (y) %4d LOAD_FAST 0 (y)
BUILD_TUPLE 1 BUILD_TUPLE 1
LOAD_CONST 1 (<code object foo at 0x..., file "%s", line %d>) LOAD_CONST 0 (<code object foo at 0x..., file "%s", line %d>)
MAKE_FUNCTION MAKE_FUNCTION
SET_FUNCTION_ATTRIBUTE 8 (closure) SET_FUNCTION_ATTRIBUTE 8 (closure)
STORE_FAST 1 (foo) STORE_FAST 1 (foo)
@ -884,7 +884,7 @@ dis_loop_test_quickened_code = """\
%3d RESUME_CHECK 0 %3d RESUME_CHECK 0
%3d BUILD_LIST 0 %3d BUILD_LIST 0
LOAD_CONST 1 ((1, 2, 3)) LOAD_CONST 0 ((1, 2, 3))
LIST_EXTEND 1 LIST_EXTEND 1
LOAD_SMALL_INT 3 LOAD_SMALL_INT 3
BINARY_OP 5 (*) BINARY_OP 5 (*)
@ -900,7 +900,7 @@ dis_loop_test_quickened_code = """\
%3d L2: END_FOR %3d L2: END_FOR
POP_TOP POP_TOP
LOAD_CONST_IMMORTAL 0 (None) LOAD_CONST_IMMORTAL 1 (None)
RETURN_VALUE RETURN_VALUE
""" % (loop_test.__code__.co_firstlineno, """ % (loop_test.__code__.co_firstlineno,
loop_test.__code__.co_firstlineno + 1, loop_test.__code__.co_firstlineno + 1,
@ -913,12 +913,12 @@ def extended_arg_quick():
dis_extended_arg_quick_code = """\ dis_extended_arg_quick_code = """\
%3d RESUME 0 %3d RESUME 0
%3d LOAD_CONST 1 (Ellipsis) %3d LOAD_CONST 0 (Ellipsis)
EXTENDED_ARG 1 EXTENDED_ARG 1
UNPACK_EX 256 UNPACK_EX 256
POP_TOP POP_TOP
STORE_FAST 0 (_) STORE_FAST 0 (_)
LOAD_CONST 0 (None) LOAD_CONST 1 (None)
RETURN_VALUE RETURN_VALUE
"""% (extended_arg_quick.__code__.co_firstlineno, """% (extended_arg_quick.__code__.co_firstlineno,
extended_arg_quick.__code__.co_firstlineno + 1,) extended_arg_quick.__code__.co_firstlineno + 1,)
@ -1465,7 +1465,7 @@ Positional-only arguments: 0
Kw-only arguments: 0 Kw-only arguments: 0
Number of locals: 1 Number of locals: 1
Stack size: \\d+ Stack size: \\d+
Flags: OPTIMIZED, NEWLOCALS Flags: OPTIMIZED, NEWLOCALS, HAS_DOCSTRING
Constants: Constants:
{code_info_consts} {code_info_consts}
Names: Names:
@ -1491,8 +1491,8 @@ Number of locals: 10
Stack size: \\d+ Stack size: \\d+
Flags: OPTIMIZED, NEWLOCALS, VARARGS, VARKEYWORDS, GENERATOR Flags: OPTIMIZED, NEWLOCALS, VARARGS, VARKEYWORDS, GENERATOR
Constants: Constants:
0: None 0: <code object f at (.*), file "(.*)", line (.*)>
1: <code object f at (.*), file "(.*)", line (.*)> 1: None
Variable names: Variable names:
0: a 0: a
1: b 1: b
@ -1510,10 +1510,12 @@ Cell variables:
2: [abedfxyz] 2: [abedfxyz]
3: [abedfxyz] 3: [abedfxyz]
4: [abedfxyz] 4: [abedfxyz]
5: [abedfxyz]""" 5: [abedfxyz]
6: [abedfxyz]
7: [abedfxyz]"""
# NOTE: the order of the cell variables above depends on dictionary order! # NOTE: the order of the cell variables above depends on dictionary order!
co_tricky_nested_f = tricky.__func__.__code__.co_consts[1] co_tricky_nested_f = tricky.__func__.__code__.co_consts[0]
code_info_tricky_nested_f = """\ code_info_tricky_nested_f = """\
Filename: (.*) Filename: (.*)
@ -1677,9 +1679,9 @@ def jumpy():
# End fodder for opinfo generation tests # End fodder for opinfo generation tests
expected_outer_line = 1 expected_outer_line = 1
_line_offset = outer.__code__.co_firstlineno - 1 _line_offset = outer.__code__.co_firstlineno - 1
code_object_f = outer.__code__.co_consts[1] code_object_f = outer.__code__.co_consts[0]
expected_f_line = code_object_f.co_firstlineno - _line_offset expected_f_line = code_object_f.co_firstlineno - _line_offset
code_object_inner = code_object_f.co_consts[1] code_object_inner = code_object_f.co_consts[0]
expected_inner_line = code_object_inner.co_firstlineno - _line_offset expected_inner_line = code_object_inner.co_firstlineno - _line_offset
expected_jumpy_line = 1 expected_jumpy_line = 1
@ -1735,11 +1737,11 @@ expected_opinfo_outer = [
Instruction(opname='MAKE_CELL', opcode=92, arg=0, argval='a', argrepr='a', offset=0, start_offset=0, starts_line=True, line_number=None, label=None, positions=None, cache_info=None), Instruction(opname='MAKE_CELL', opcode=92, arg=0, argval='a', argrepr='a', offset=0, start_offset=0, starts_line=True, line_number=None, label=None, positions=None, cache_info=None),
Instruction(opname='MAKE_CELL', opcode=92, arg=1, argval='b', argrepr='b', offset=2, start_offset=2, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), Instruction(opname='MAKE_CELL', opcode=92, arg=1, argval='b', argrepr='b', offset=2, start_offset=2, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
Instruction(opname='RESUME', opcode=149, arg=0, argval=0, argrepr='', offset=4, start_offset=4, starts_line=True, line_number=1, label=None, positions=None, cache_info=None), Instruction(opname='RESUME', opcode=149, arg=0, argval=0, argrepr='', offset=4, start_offset=4, starts_line=True, line_number=1, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_CONST', opcode=79, arg=4, argval=(3, 4), argrepr='(3, 4)', offset=6, start_offset=6, starts_line=True, line_number=2, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_CONST', opcode=79, arg=3, argval=(3, 4), argrepr='(3, 4)', offset=6, start_offset=6, starts_line=True, line_number=2, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_FAST', opcode=81, arg=0, argval='a', argrepr='a', offset=8, start_offset=8, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_FAST', opcode=81, arg=0, argval='a', argrepr='a', offset=8, start_offset=8, starts_line=False, line_number=2, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_FAST', opcode=81, arg=1, argval='b', argrepr='b', offset=10, start_offset=10, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_FAST', opcode=81, arg=1, argval='b', argrepr='b', offset=10, start_offset=10, starts_line=False, line_number=2, label=None, positions=None, cache_info=None),
Instruction(opname='BUILD_TUPLE', opcode=48, arg=2, argval=2, argrepr='', offset=12, start_offset=12, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), Instruction(opname='BUILD_TUPLE', opcode=48, arg=2, argval=2, argrepr='', offset=12, start_offset=12, starts_line=False, line_number=2, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_CONST', opcode=79, arg=1, argval=code_object_f, argrepr=repr(code_object_f), offset=14, start_offset=14, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_CONST', opcode=79, arg=0, argval=code_object_f, argrepr=repr(code_object_f), offset=14, start_offset=14, starts_line=False, line_number=2, label=None, positions=None, cache_info=None),
Instruction(opname='MAKE_FUNCTION', opcode=23, arg=None, argval=None, argrepr='', offset=16, start_offset=16, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), Instruction(opname='MAKE_FUNCTION', opcode=23, arg=None, argval=None, argrepr='', offset=16, start_offset=16, starts_line=False, line_number=2, label=None, positions=None, cache_info=None),
Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=103, arg=8, argval=8, argrepr='closure', offset=18, start_offset=18, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=103, arg=8, argval=8, argrepr='closure', offset=18, start_offset=18, starts_line=False, line_number=2, label=None, positions=None, cache_info=None),
Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=103, arg=1, argval=1, argrepr='defaults', offset=20, start_offset=20, starts_line=False, line_number=2, label=None, positions=None, cache_info=None), Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=103, arg=1, argval=1, argrepr='defaults', offset=20, start_offset=20, starts_line=False, line_number=2, label=None, positions=None, cache_info=None),
@ -1747,11 +1749,11 @@ expected_opinfo_outer = [
Instruction(opname='LOAD_GLOBAL', opcode=87, arg=1, argval='print', argrepr='print + NULL', offset=24, start_offset=24, starts_line=True, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), Instruction(opname='LOAD_GLOBAL', opcode=87, arg=1, argval='print', argrepr='print + NULL', offset=24, start_offset=24, starts_line=True, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
Instruction(opname='LOAD_DEREF', opcode=80, arg=0, argval='a', argrepr='a', offset=34, start_offset=34, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_DEREF', opcode=80, arg=0, argval='a', argrepr='a', offset=34, start_offset=34, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_DEREF', opcode=80, arg=1, argval='b', argrepr='b', offset=36, start_offset=36, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_DEREF', opcode=80, arg=1, argval='b', argrepr='b', offset=36, start_offset=36, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_CONST', opcode=79, arg=2, argval='', argrepr="''", offset=38, start_offset=38, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_CONST', opcode=79, arg=1, argval='', argrepr="''", offset=38, start_offset=38, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_SMALL_INT', opcode=89, arg=1, argval=1, argrepr='', offset=40, start_offset=40, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_SMALL_INT', opcode=89, arg=1, argval=1, argrepr='', offset=40, start_offset=40, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
Instruction(opname='BUILD_LIST', opcode=43, arg=0, argval=0, argrepr='', offset=42, start_offset=42, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), Instruction(opname='BUILD_LIST', opcode=43, arg=0, argval=0, argrepr='', offset=42, start_offset=42, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
Instruction(opname='BUILD_MAP', opcode=44, arg=0, argval=0, argrepr='', offset=44, start_offset=44, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), Instruction(opname='BUILD_MAP', opcode=44, arg=0, argval=0, argrepr='', offset=44, start_offset=44, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_CONST', opcode=79, arg=3, argval='Hello world!', argrepr="'Hello world!'", offset=46, start_offset=46, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_CONST', opcode=79, arg=2, argval='Hello world!', argrepr="'Hello world!'", offset=46, start_offset=46, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
Instruction(opname='CALL', opcode=49, arg=7, argval=7, argrepr='', offset=48, start_offset=48, starts_line=False, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), Instruction(opname='CALL', opcode=49, arg=7, argval=7, argrepr='', offset=48, start_offset=48, starts_line=False, line_number=7, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=56, start_offset=56, starts_line=False, line_number=7, label=None, positions=None, cache_info=None), Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=56, start_offset=56, starts_line=False, line_number=7, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_FAST', opcode=81, arg=2, argval='f', argrepr='f', offset=58, start_offset=58, starts_line=True, line_number=8, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_FAST', opcode=81, arg=2, argval='f', argrepr='f', offset=58, start_offset=58, starts_line=True, line_number=8, label=None, positions=None, cache_info=None),
@ -1763,13 +1765,13 @@ expected_opinfo_f = [
Instruction(opname='MAKE_CELL', opcode=92, arg=0, argval='c', argrepr='c', offset=2, start_offset=2, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), Instruction(opname='MAKE_CELL', opcode=92, arg=0, argval='c', argrepr='c', offset=2, start_offset=2, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
Instruction(opname='MAKE_CELL', opcode=92, arg=1, argval='d', argrepr='d', offset=4, start_offset=4, starts_line=False, line_number=None, label=None, positions=None, cache_info=None), Instruction(opname='MAKE_CELL', opcode=92, arg=1, argval='d', argrepr='d', offset=4, start_offset=4, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
Instruction(opname='RESUME', opcode=149, arg=0, argval=0, argrepr='', offset=6, start_offset=6, starts_line=True, line_number=2, label=None, positions=None, cache_info=None), Instruction(opname='RESUME', opcode=149, arg=0, argval=0, argrepr='', offset=6, start_offset=6, starts_line=True, line_number=2, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_CONST', opcode=79, arg=2, argval=(5, 6), argrepr='(5, 6)', offset=8, start_offset=8, starts_line=True, line_number=3, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_CONST', opcode=79, arg=1, argval=(5, 6), argrepr='(5, 6)', offset=8, start_offset=8, starts_line=True, line_number=3, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_FAST', opcode=81, arg=3, argval='a', argrepr='a', offset=10, start_offset=10, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_FAST', opcode=81, arg=3, argval='a', argrepr='a', offset=10, start_offset=10, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_FAST', opcode=81, arg=4, argval='b', argrepr='b', offset=12, start_offset=12, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_FAST', opcode=81, arg=4, argval='b', argrepr='b', offset=12, start_offset=12, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_FAST', opcode=81, arg=0, argval='c', argrepr='c', offset=14, start_offset=14, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_FAST', opcode=81, arg=0, argval='c', argrepr='c', offset=14, start_offset=14, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_FAST', opcode=81, arg=1, argval='d', argrepr='d', offset=16, start_offset=16, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_FAST', opcode=81, arg=1, argval='d', argrepr='d', offset=16, start_offset=16, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
Instruction(opname='BUILD_TUPLE', opcode=48, arg=4, argval=4, argrepr='', offset=18, start_offset=18, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), Instruction(opname='BUILD_TUPLE', opcode=48, arg=4, argval=4, argrepr='', offset=18, start_offset=18, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_CONST', opcode=79, arg=1, argval=code_object_inner, argrepr=repr(code_object_inner), offset=20, start_offset=20, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_CONST', opcode=79, arg=0, argval=code_object_inner, argrepr=repr(code_object_inner), offset=20, start_offset=20, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
Instruction(opname='MAKE_FUNCTION', opcode=23, arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), Instruction(opname='MAKE_FUNCTION', opcode=23, arg=None, argval=None, argrepr='', offset=22, start_offset=22, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=103, arg=8, argval=8, argrepr='closure', offset=24, start_offset=24, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=103, arg=8, argval=8, argrepr='closure', offset=24, start_offset=24, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=103, arg=1, argval=1, argrepr='defaults', offset=26, start_offset=26, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), Instruction(opname='SET_FUNCTION_ATTRIBUTE', opcode=103, arg=1, argval=1, argrepr='defaults', offset=26, start_offset=26, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
@ -1827,7 +1829,7 @@ expected_opinfo_jumpy = [
Instruction(opname='END_FOR', opcode=9, arg=None, argval=None, argrepr='', offset=88, start_offset=88, starts_line=True, line_number=3, label=4, positions=None, cache_info=None), Instruction(opname='END_FOR', opcode=9, arg=None, argval=None, argrepr='', offset=88, start_offset=88, starts_line=True, line_number=3, label=4, positions=None, cache_info=None),
Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=90, start_offset=90, starts_line=False, line_number=3, label=None, positions=None, cache_info=None), Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=90, start_offset=90, starts_line=False, line_number=3, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_GLOBAL', opcode=87, arg=3, argval='print', argrepr='print + NULL', offset=92, start_offset=92, starts_line=True, line_number=10, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), Instruction(opname='LOAD_GLOBAL', opcode=87, arg=3, argval='print', argrepr='print + NULL', offset=92, start_offset=92, starts_line=True, line_number=10, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
Instruction(opname='LOAD_CONST', opcode=79, arg=1, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=102, start_offset=102, starts_line=False, line_number=10, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_CONST', opcode=79, arg=0, argval='I can haz else clause?', argrepr="'I can haz else clause?'", offset=102, start_offset=102, starts_line=False, line_number=10, label=None, positions=None, cache_info=None),
Instruction(opname='CALL', opcode=49, arg=1, argval=1, argrepr='', offset=104, start_offset=104, starts_line=False, line_number=10, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), Instruction(opname='CALL', opcode=49, arg=1, argval=1, argrepr='', offset=104, start_offset=104, starts_line=False, line_number=10, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=112, start_offset=112, starts_line=False, line_number=10, label=None, positions=None, cache_info=None), Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=112, start_offset=112, starts_line=False, line_number=10, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_FAST_CHECK', opcode=83, arg=0, argval='i', argrepr='i', offset=114, start_offset=114, starts_line=True, line_number=11, label=5, positions=None, cache_info=None), Instruction(opname='LOAD_FAST_CHECK', opcode=83, arg=0, argval='i', argrepr='i', offset=114, start_offset=114, starts_line=True, line_number=11, label=5, positions=None, cache_info=None),
@ -1853,7 +1855,7 @@ expected_opinfo_jumpy = [
Instruction(opname='JUMP_BACKWARD', opcode=72, arg=39, argval=114, argrepr='to L5', offset=188, start_offset=188, starts_line=False, line_number=16, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]), Instruction(opname='JUMP_BACKWARD', opcode=72, arg=39, argval=114, argrepr='to L5', offset=188, start_offset=188, starts_line=False, line_number=16, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
Instruction(opname='JUMP_FORWARD', opcode=74, arg=11, argval=216, argrepr='to L9', offset=192, start_offset=192, starts_line=True, line_number=17, label=7, positions=None, cache_info=None), Instruction(opname='JUMP_FORWARD', opcode=74, arg=11, argval=216, argrepr='to L9', offset=192, start_offset=192, starts_line=True, line_number=17, label=7, positions=None, cache_info=None),
Instruction(opname='LOAD_GLOBAL', opcode=87, arg=3, argval='print', argrepr='print + NULL', offset=194, start_offset=194, starts_line=True, line_number=19, label=8, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), Instruction(opname='LOAD_GLOBAL', opcode=87, arg=3, argval='print', argrepr='print + NULL', offset=194, start_offset=194, starts_line=True, line_number=19, label=8, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
Instruction(opname='LOAD_CONST', opcode=79, arg=2, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=204, start_offset=204, starts_line=False, line_number=19, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_CONST', opcode=79, arg=1, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=204, start_offset=204, starts_line=False, line_number=19, label=None, positions=None, cache_info=None),
Instruction(opname='CALL', opcode=49, arg=1, argval=1, argrepr='', offset=206, start_offset=206, starts_line=False, line_number=19, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), Instruction(opname='CALL', opcode=49, arg=1, argval=1, argrepr='', offset=206, start_offset=206, starts_line=False, line_number=19, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=214, start_offset=214, starts_line=False, line_number=19, label=None, positions=None, cache_info=None), Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=214, start_offset=214, starts_line=False, line_number=19, label=None, positions=None, cache_info=None),
Instruction(opname='NOP', opcode=27, arg=None, argval=None, argrepr='', offset=216, start_offset=216, starts_line=True, line_number=20, label=9, positions=None, cache_info=None), Instruction(opname='NOP', opcode=27, arg=None, argval=None, argrepr='', offset=216, start_offset=216, starts_line=True, line_number=20, label=9, positions=None, cache_info=None),
@ -1870,19 +1872,19 @@ expected_opinfo_jumpy = [
Instruction(opname='CALL', opcode=49, arg=0, argval=0, argrepr='', offset=240, start_offset=240, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), Instruction(opname='CALL', opcode=49, arg=0, argval=0, argrepr='', offset=240, start_offset=240, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
Instruction(opname='STORE_FAST', opcode=107, arg=1, argval='dodgy', argrepr='dodgy', offset=248, start_offset=248, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), Instruction(opname='STORE_FAST', opcode=107, arg=1, argval='dodgy', argrepr='dodgy', offset=248, start_offset=248, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_GLOBAL', opcode=87, arg=3, argval='print', argrepr='print + NULL', offset=250, start_offset=250, starts_line=True, line_number=26, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), Instruction(opname='LOAD_GLOBAL', opcode=87, arg=3, argval='print', argrepr='print + NULL', offset=250, start_offset=250, starts_line=True, line_number=26, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
Instruction(opname='LOAD_CONST', opcode=79, arg=3, argval='Never reach this', argrepr="'Never reach this'", offset=260, start_offset=260, starts_line=False, line_number=26, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_CONST', opcode=79, arg=2, argval='Never reach this', argrepr="'Never reach this'", offset=260, start_offset=260, starts_line=False, line_number=26, label=None, positions=None, cache_info=None),
Instruction(opname='CALL', opcode=49, arg=1, argval=1, argrepr='', offset=262, start_offset=262, starts_line=False, line_number=26, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), Instruction(opname='CALL', opcode=49, arg=1, argval=1, argrepr='', offset=262, start_offset=262, starts_line=False, line_number=26, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=270, start_offset=270, starts_line=False, line_number=26, label=None, positions=None, cache_info=None), Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=270, start_offset=270, starts_line=False, line_number=26, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_CONST', opcode=79, arg=0, argval=None, argrepr='None', offset=272, start_offset=272, starts_line=True, line_number=25, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_CONST', opcode=79, arg=3, argval=None, argrepr='None', offset=272, start_offset=272, starts_line=True, line_number=25, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_CONST', opcode=79, arg=0, argval=None, argrepr='None', offset=274, start_offset=274, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_CONST', opcode=79, arg=3, argval=None, argrepr='None', offset=274, start_offset=274, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_CONST', opcode=79, arg=0, argval=None, argrepr='None', offset=276, start_offset=276, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_CONST', opcode=79, arg=3, argval=None, argrepr='None', offset=276, start_offset=276, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
Instruction(opname='CALL', opcode=49, arg=3, argval=3, argrepr='', offset=278, start_offset=278, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), Instruction(opname='CALL', opcode=49, arg=3, argval=3, argrepr='', offset=278, start_offset=278, starts_line=False, line_number=25, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=286, start_offset=286, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=286, start_offset=286, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_GLOBAL', opcode=87, arg=3, argval='print', argrepr='print + NULL', offset=288, start_offset=288, starts_line=True, line_number=28, label=10, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]), Instruction(opname='LOAD_GLOBAL', opcode=87, arg=3, argval='print', argrepr='print + NULL', offset=288, start_offset=288, starts_line=True, line_number=28, label=10, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('index', 1, b'\x00\x00'), ('module_keys_version', 1, b'\x00\x00'), ('builtin_keys_version', 1, b'\x00\x00')]),
Instruction(opname='LOAD_CONST', opcode=79, arg=5, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=298, start_offset=298, starts_line=False, line_number=28, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_CONST', opcode=79, arg=5, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=298, start_offset=298, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
Instruction(opname='CALL', opcode=49, arg=1, argval=1, argrepr='', offset=300, start_offset=300, starts_line=False, line_number=28, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]), Instruction(opname='CALL', opcode=49, arg=1, argval=1, argrepr='', offset=300, start_offset=300, starts_line=False, line_number=28, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('func_version', 2, b'\x00\x00\x00\x00')]),
Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=308, start_offset=308, starts_line=False, line_number=28, label=None, positions=None, cache_info=None), Instruction(opname='POP_TOP', opcode=29, arg=None, argval=None, argrepr='', offset=308, start_offset=308, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
Instruction(opname='LOAD_CONST', opcode=79, arg=0, argval=None, argrepr='None', offset=310, start_offset=310, starts_line=False, line_number=28, label=None, positions=None, cache_info=None), Instruction(opname='LOAD_CONST', opcode=79, arg=3, argval=None, argrepr='None', offset=310, start_offset=310, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
Instruction(opname='RETURN_VALUE', opcode=33, arg=None, argval=None, argrepr='', offset=312, start_offset=312, starts_line=False, line_number=28, label=None, positions=None, cache_info=None), Instruction(opname='RETURN_VALUE', opcode=33, arg=None, argval=None, argrepr='', offset=312, start_offset=312, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
Instruction(opname='PUSH_EXC_INFO', opcode=30, arg=None, argval=None, argrepr='', offset=314, start_offset=314, starts_line=True, line_number=25, label=None, positions=None, cache_info=None), Instruction(opname='PUSH_EXC_INFO', opcode=30, arg=None, argval=None, argrepr='', offset=314, start_offset=314, starts_line=True, line_number=25, label=None, positions=None, cache_info=None),
Instruction(opname='WITH_EXCEPT_START', opcode=41, arg=None, argval=None, argrepr='', offset=316, start_offset=316, starts_line=False, line_number=25, label=None, positions=None, cache_info=None), Instruction(opname='WITH_EXCEPT_START', opcode=41, arg=None, argval=None, argrepr='', offset=316, start_offset=316, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),

View File

@ -5373,7 +5373,7 @@ class TestSignatureBind(unittest.TestCase):
# Issue #19611: getcallargs should work with comprehensions # Issue #19611: getcallargs should work with comprehensions
def make_set(): def make_set():
return set(z * z for z in range(5)) return set(z * z for z in range(5))
gencomp_code = make_set.__code__.co_consts[1] gencomp_code = make_set.__code__.co_consts[0]
gencomp_func = types.FunctionType(gencomp_code, {}) gencomp_func = types.FunctionType(gencomp_code, {})
iterator = iter(range(5)) iterator = iter(range(5))

View File

@ -0,0 +1,3 @@
Add a new attribute in :attr:`~codeobject.co_flags` to indicate whether the
first item in :attr:`~codeobject.co_consts` is the docstring. If a code
object has no docstring, ``None`` will **NOT** be inserted.

View File

@ -162,7 +162,8 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname
PyObject *consts = code_obj->co_consts; PyObject *consts = code_obj->co_consts;
assert(PyTuple_Check(consts)); assert(PyTuple_Check(consts));
PyObject *doc; PyObject *doc;
if (PyTuple_Size(consts) >= 1) { if (code_obj->co_flags & CO_HAS_DOCSTRING) {
assert(PyTuple_Size(consts) >= 1);
doc = PyTuple_GetItem(consts, 0); doc = PyTuple_GetItem(consts, 0);
if (!PyUnicode_Check(doc)) { if (!PyUnicode_Check(doc)) {
doc = Py_None; doc = Py_None;

View File

@ -1243,10 +1243,10 @@ codegen_function_body(compiler *c, stmt_ty s, int is_async, Py_ssize_t funcflags
_PyCompile_ExitScope(c); _PyCompile_ExitScope(c);
return ERROR; return ERROR;
} }
} Py_ssize_t idx = _PyCompile_AddConst(c, docstring);
Py_ssize_t idx = _PyCompile_AddConst(c, docstring ? docstring : Py_None); Py_DECREF(docstring);
Py_XDECREF(docstring);
RETURN_IF_ERROR_IN_SCOPE(c, idx < 0 ? ERROR : SUCCESS); RETURN_IF_ERROR_IN_SCOPE(c, idx < 0 ? ERROR : SUCCESS);
}
NEW_JUMP_TARGET_LABEL(c, start); NEW_JUMP_TARGET_LABEL(c, start);
USE_LABEL(c, start); USE_LABEL(c, start);

View File

@ -1285,6 +1285,8 @@ compute_code_flags(compiler *c)
flags |= CO_VARARGS; flags |= CO_VARARGS;
if (ste->ste_varkeywords) if (ste->ste_varkeywords)
flags |= CO_VARKEYWORDS; flags |= CO_VARKEYWORDS;
if (ste->ste_has_docstring)
flags |= CO_HAS_DOCSTRING;
} }
if (ste->ste_coroutine && !ste->ste_generator) { if (ste->ste_coroutine && !ste->ste_generator) {

View File

@ -136,6 +136,8 @@ ste_new(struct symtable *st, identifier name, _Py_block_ty block,
ste->ste_needs_classdict = 0; ste->ste_needs_classdict = 0;
ste->ste_annotation_block = NULL; ste->ste_annotation_block = NULL;
ste->ste_has_docstring = 0;
ste->ste_symbols = PyDict_New(); ste->ste_symbols = PyDict_New();
ste->ste_varnames = PyList_New(0); ste->ste_varnames = PyList_New(0);
ste->ste_children = PyList_New(0); ste->ste_children = PyList_New(0);
@ -1841,6 +1843,10 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
return 0; return 0;
} }
if (_PyAST_GetDocString(s->v.FunctionDef.body)) {
new_ste->ste_has_docstring = 1;
}
if (!symtable_visit_annotations(st, s, s->v.FunctionDef.args, if (!symtable_visit_annotations(st, s, s->v.FunctionDef.args,
s->v.FunctionDef.returns, new_ste)) { s->v.FunctionDef.returns, new_ste)) {
Py_DECREF(new_ste); Py_DECREF(new_ste);
@ -2168,6 +2174,10 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
return 0; return 0;
} }
if (_PyAST_GetDocString(s->v.AsyncFunctionDef.body)) {
new_ste->ste_has_docstring = 1;
}
if (!symtable_visit_annotations(st, s, s->v.AsyncFunctionDef.args, if (!symtable_visit_annotations(st, s, s->v.AsyncFunctionDef.args,
s->v.AsyncFunctionDef.returns, new_ste)) { s->v.AsyncFunctionDef.returns, new_ste)) {
Py_DECREF(new_ste); Py_DECREF(new_ste);