@@ -1704,10 +1704,16 @@ compiler_body(struct compiler *c, location loc, asdl_stmt_seq *stmts)
1704
1704
if (c -> c_optimize < 2 ) {
1705
1705
docstring = _PyAST_GetDocString (stmts );
1706
1706
if (docstring ) {
1707
+ PyObject * cleandoc = _PyCompile_CleanDoc (docstring );
1708
+ if (cleandoc == NULL ) {
1709
+ return ERROR ;
1710
+ }
1707
1711
i = 1 ;
1708
1712
st = (stmt_ty )asdl_seq_GET (stmts , 0 );
1709
1713
assert (st -> kind == Expr_kind );
1710
- VISIT (c , expr , st -> v .Expr .value );
1714
+ location loc = LOC (st -> v .Expr .value );
1715
+ ADDOP_LOAD_CONST (c , loc , cleandoc );
1716
+ Py_DECREF (cleandoc );
1711
1717
RETURN_IF_ERROR (compiler_nameop (c , NO_LOCATION , & _Py_ID (__doc__ ), Store ));
1712
1718
}
1713
1719
}
@@ -2252,11 +2258,19 @@ compiler_function_body(struct compiler *c, stmt_ty s, int is_async, Py_ssize_t f
2252
2258
/* if not -OO mode, add docstring */
2253
2259
if (c -> c_optimize < 2 ) {
2254
2260
docstring = _PyAST_GetDocString (body );
2261
+ if (docstring ) {
2262
+ docstring = _PyCompile_CleanDoc (docstring );
2263
+ if (docstring == NULL ) {
2264
+ compiler_exit_scope (c );
2265
+ return ERROR ;
2266
+ }
2267
+ }
2255
2268
}
2256
2269
if (compiler_add_const (c -> c_const_cache , c -> u , docstring ? docstring : Py_None ) < 0 ) {
2257
2270
compiler_exit_scope (c );
2258
2271
return ERROR ;
2259
2272
}
2273
+ Py_XDECREF (docstring );
2260
2274
2261
2275
c -> u -> u_metadata .u_argcount = asdl_seq_LEN (args -> args );
2262
2276
c -> u -> u_metadata .u_posonlyargcount = asdl_seq_LEN (args -> posonlyargs );
@@ -7967,6 +7981,89 @@ cfg_to_instructions(cfg_builder *g)
7967
7981
return NULL ;
7968
7982
}
7969
7983
7984
+ // C implementation of inspect.cleandoc()
7985
+ //
7986
+ // Difference from inspect.cleandoc():
7987
+ // - Do not remove leading and trailing blank lines to keep lineno.
7988
+ PyObject *
7989
+ _PyCompile_CleanDoc (PyObject * doc )
7990
+ {
7991
+ doc = PyObject_CallMethod (doc , "expandtabs" , NULL );
7992
+ if (doc == NULL ) {
7993
+ return NULL ;
7994
+ }
7995
+
7996
+ Py_ssize_t doc_size ;
7997
+ const char * doc_utf8 = PyUnicode_AsUTF8AndSize (doc , & doc_size );
7998
+ if (doc_utf8 == NULL ) {
7999
+ Py_DECREF (doc );
8000
+ return NULL ;
8001
+ }
8002
+ const char * p = doc_utf8 ;
8003
+ const char * pend = p + doc_size ;
8004
+
8005
+ // First pass: find minimum indentation of any non-blank lines
8006
+ // after first line.
8007
+ while (p < pend && * p ++ != '\n' ) {
8008
+ }
8009
+
8010
+ Py_ssize_t margin = PY_SSIZE_T_MAX ;
8011
+ while (p < pend ) {
8012
+ const char * s = p ;
8013
+ while (* p == ' ' ) p ++ ;
8014
+ if (p < pend && * p != '\n' ) {
8015
+ margin = Py_MIN (margin , p - s );
8016
+ }
8017
+ while (p < pend && * p ++ != '\n' ) {
8018
+ }
8019
+ }
8020
+ if (margin == PY_SSIZE_T_MAX ) {
8021
+ margin = 0 ;
8022
+ }
8023
+
8024
+ // Second pass: write cleandoc into buff.
8025
+
8026
+ // copy first line without leading spaces.
8027
+ p = doc_utf8 ;
8028
+ while (* p == ' ' ) {
8029
+ p ++ ;
8030
+ }
8031
+ if (p == doc_utf8 && margin == 0 ) {
8032
+ // doc is already clean.
8033
+ return doc ;
8034
+ }
8035
+
8036
+ char * buff = PyMem_Malloc (doc_size );
8037
+ char * w = buff ;
8038
+
8039
+ while (p < pend ) {
8040
+ int ch = * w ++ = * p ++ ;
8041
+ if (ch == '\n' ) {
8042
+ break ;
8043
+ }
8044
+ }
8045
+
8046
+ // copy subsequent lines without margin.
8047
+ while (p < pend ) {
8048
+ for (Py_ssize_t i = 0 ; i < margin ; i ++ , p ++ ) {
8049
+ if (* p != ' ' ) {
8050
+ assert (* p == '\n' || * p == '\0' );
8051
+ break ;
8052
+ }
8053
+ }
8054
+ while (p < pend ) {
8055
+ int ch = * w ++ = * p ++ ;
8056
+ if (ch == '\n' ) {
8057
+ break ;
8058
+ }
8059
+ }
8060
+ }
8061
+
8062
+ Py_DECREF (doc );
8063
+ return PyUnicode_FromStringAndSize (buff , w - buff );
8064
+ }
8065
+
8066
+
7970
8067
PyObject *
7971
8068
_PyCompile_CodeGen (PyObject * ast , PyObject * filename , PyCompilerFlags * pflags ,
7972
8069
int optimize , int compile_mode )
0 commit comments