Skip to content

Commit e07154f

Browse files
authored
gh-123958: apply docstring removal optimization in ast_opt instead of codegen (#123959)
1 parent 2938c3d commit e07154f

File tree

5 files changed

+47
-23
lines changed

5 files changed

+47
-23
lines changed

Doc/whatsnew/3.14.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,11 @@ ast
123123
(Contributed by Batuhan Taskaya and Jeremy Hylton in :issue:`15987`.)
124124

125125
* Add support for :func:`copy.replace` for AST nodes.
126-
127126
(Contributed by Bénédikt Tran in :gh:`121141`.)
128127

128+
* Docstrings are now removed from an optimized AST in optimization level 2.
129+
(Contributed by Irit Katriel in :gh:`123958`.)
130+
129131

130132
ctypes
131133
------

Lib/test/test_compile.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,10 @@ def test_docstring(self):
876876
def with_docstring():
877877
"docstring"
878878
879+
def two_strings():
880+
"docstring"
881+
"not docstring"
882+
879883
def with_fstring():
880884
f"not docstring"
881885
@@ -891,8 +895,10 @@ def with_const_expression():
891895

892896
if opt < 2:
893897
self.assertEqual(ns['with_docstring'].__doc__, "docstring")
898+
self.assertEqual(ns['two_strings'].__doc__, "docstring")
894899
else:
895900
self.assertIsNone(ns['with_docstring'].__doc__)
901+
self.assertIsNone(ns['two_strings'].__doc__)
896902
self.assertIsNone(ns['with_fstring'].__doc__)
897903
self.assertIsNone(ns['with_const_expression'].__doc__)
898904

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
docstrings are now removed from the optimized AST in optimization level 2.

Python/ast_opt.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,10 +673,31 @@ static int astfold_type_param(type_param_ty node_, PyArena *ctx_, _PyASTOptimize
673673
}
674674

675675

676+
static int
677+
stmt_seq_remove_item(asdl_stmt_seq *stmts, Py_ssize_t idx)
678+
{
679+
if (idx >= asdl_seq_LEN(stmts)) {
680+
return 0;
681+
}
682+
for (Py_ssize_t i = idx; i < asdl_seq_LEN(stmts) - 1; i++) {
683+
stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, i+1);
684+
asdl_seq_SET(stmts, i, st);
685+
}
686+
stmts->size--;
687+
return 1;
688+
}
689+
676690
static int
677691
astfold_body(asdl_stmt_seq *stmts, PyArena *ctx_, _PyASTOptimizeState *state)
678692
{
679693
int docstring = _PyAST_GetDocString(stmts) != NULL;
694+
if (docstring && (state->optimize >= 2)) {
695+
/* remove the docstring */
696+
if (!stmt_seq_remove_item(stmts, 0)) {
697+
return 0;
698+
}
699+
docstring = 0;
700+
}
680701
CALL_SEQ(astfold_stmt, stmt, stmts);
681702
if (!docstring && _PyAST_GetDocString(stmts) != NULL) {
682703
stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);

Python/codegen.c

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -763,19 +763,18 @@ _PyCodegen_Body(compiler *c, location loc, asdl_stmt_seq *stmts)
763763
PyObject *docstring = _PyAST_GetDocString(stmts);
764764
if (docstring) {
765765
first_instr = 1;
766-
/* if not -OO mode, set docstring */
767-
if (OPTIMIZATION_LEVEL(c) < 2) {
768-
PyObject *cleandoc = _PyCompile_CleanDoc(docstring);
769-
if (cleandoc == NULL) {
770-
return ERROR;
771-
}
772-
stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
773-
assert(st->kind == Expr_kind);
774-
location loc = LOC(st->v.Expr.value);
775-
ADDOP_LOAD_CONST(c, loc, cleandoc);
776-
Py_DECREF(cleandoc);
777-
RETURN_IF_ERROR(codegen_nameop(c, NO_LOCATION, &_Py_ID(__doc__), Store));
766+
/* set docstring */
767+
assert(OPTIMIZATION_LEVEL(c) < 2);
768+
PyObject *cleandoc = _PyCompile_CleanDoc(docstring);
769+
if (cleandoc == NULL) {
770+
return ERROR;
778771
}
772+
stmt_ty st = (stmt_ty)asdl_seq_GET(stmts, 0);
773+
assert(st->kind == Expr_kind);
774+
location loc = LOC(st->v.Expr.value);
775+
ADDOP_LOAD_CONST(c, loc, cleandoc);
776+
Py_DECREF(cleandoc);
777+
RETURN_IF_ERROR(codegen_nameop(c, NO_LOCATION, &_Py_ID(__doc__), Store));
779778
}
780779
}
781780
for (Py_ssize_t i = first_instr; i < asdl_seq_LEN(stmts); i++) {
@@ -1230,18 +1229,13 @@ codegen_function_body(compiler *c, stmt_ty s, int is_async, Py_ssize_t funcflags
12301229

12311230
Py_ssize_t first_instr = 0;
12321231
PyObject *docstring = _PyAST_GetDocString(body);
1232+
assert(OPTIMIZATION_LEVEL(c) < 2 || docstring == NULL);
12331233
if (docstring) {
12341234
first_instr = 1;
1235-
/* if not -OO mode, add docstring */
1236-
if (OPTIMIZATION_LEVEL(c) < 2) {
1237-
docstring = _PyCompile_CleanDoc(docstring);
1238-
if (docstring == NULL) {
1239-
_PyCompile_ExitScope(c);
1240-
return ERROR;
1241-
}
1242-
}
1243-
else {
1244-
docstring = NULL;
1235+
docstring = _PyCompile_CleanDoc(docstring);
1236+
if (docstring == NULL) {
1237+
_PyCompile_ExitScope(c);
1238+
return ERROR;
12451239
}
12461240
}
12471241
Py_ssize_t idx = _PyCompile_AddConst(c, docstring ? docstring : Py_None);

0 commit comments

Comments
 (0)