@@ -1704,10 +1704,16 @@ compiler_body(struct compiler *c, location loc, asdl_stmt_seq *stmts)
17041704 if (c -> c_optimize < 2 ) {
17051705 docstring = _PyAST_GetDocString (stmts );
17061706 if (docstring ) {
1707+ PyObject * cleandoc = _PyCompile_CleanDoc (docstring );
1708+ if (cleandoc == NULL ) {
1709+ return ERROR ;
1710+ }
17071711 i = 1 ;
17081712 st = (stmt_ty )asdl_seq_GET (stmts , 0 );
17091713 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 );
17111717 RETURN_IF_ERROR (compiler_nameop (c , NO_LOCATION , & _Py_ID (__doc__ ), Store ));
17121718 }
17131719 }
@@ -2252,11 +2258,19 @@ compiler_function_body(struct compiler *c, stmt_ty s, int is_async, Py_ssize_t f
22522258 /* if not -OO mode, add docstring */
22532259 if (c -> c_optimize < 2 ) {
22542260 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+ }
22552268 }
22562269 if (compiler_add_const (c -> c_const_cache , c -> u , docstring ? docstring : Py_None ) < 0 ) {
22572270 compiler_exit_scope (c );
22582271 return ERROR ;
22592272 }
2273+ Py_XDECREF (docstring );
22602274
22612275 c -> u -> u_metadata .u_argcount = asdl_seq_LEN (args -> args );
22622276 c -> u -> u_metadata .u_posonlyargcount = asdl_seq_LEN (args -> posonlyargs );
@@ -7967,6 +7981,89 @@ cfg_to_instructions(cfg_builder *g)
79677981 return NULL ;
79687982}
79697983
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+
79708067PyObject *
79718068_PyCompile_CodeGen (PyObject * ast , PyObject * filename , PyCompilerFlags * pflags ,
79728069 int optimize , int compile_mode )
0 commit comments