@@ -220,6 +220,131 @@ def test_negative_locations_for_compile(self):
220220                # This also must not crash: 
221221                ast .parse (tree , optimize = 2 )
222222
223+     def  test_docstring_optimization_single_node (self ):
224+         # https://github.com/python/cpython/issues/137308 
225+         class_example1  =  textwrap .dedent (''' 
226+             class A: 
227+                 """Docstring""" 
228+         ''' )
229+         class_example2  =  textwrap .dedent (''' 
230+             class A: 
231+                 """ 
232+                 Docstring""" 
233+         ''' )
234+         def_example1  =  textwrap .dedent (''' 
235+             def some(): 
236+                 """Docstring""" 
237+         ''' )
238+         def_example2  =  textwrap .dedent (''' 
239+             def some(): 
240+                 """Docstring 
241+                                        """ 
242+         ''' )
243+         async_def_example1  =  textwrap .dedent (''' 
244+             async def some(): 
245+                 """Docstring""" 
246+         ''' )
247+         async_def_example2  =  textwrap .dedent (''' 
248+             async def some(): 
249+                 """ 
250+                 Docstring 
251+             """ 
252+         ''' )
253+         for  code  in  [
254+             class_example1 ,
255+             class_example2 ,
256+             def_example1 ,
257+             def_example2 ,
258+             async_def_example1 ,
259+             async_def_example2 ,
260+         ]:
261+             for  opt_level  in  [0 , 1 , 2 ]:
262+                 with  self .subTest (code = code , opt_level = opt_level ):
263+                     mod  =  ast .parse (code , optimize = opt_level )
264+                     self .assertEqual (len (mod .body [0 ].body ), 1 )
265+                     if  opt_level  ==  2 :
266+                         pass_stmt  =  mod .body [0 ].body [0 ]
267+                         self .assertIsInstance (pass_stmt , ast .Pass )
268+                         self .assertEqual (
269+                             vars (pass_stmt ),
270+                             {
271+                                 'lineno' : 3 ,
272+                                 'col_offset' : 4 ,
273+                                 'end_lineno' : 3 ,
274+                                 'end_col_offset' : 8 ,
275+                             },
276+                         )
277+                     else :
278+                         self .assertIsInstance (mod .body [0 ].body [0 ], ast .Expr )
279+                         self .assertIsInstance (
280+                             mod .body [0 ].body [0 ].value ,
281+                             ast .Constant ,
282+                         )
283+ 
284+                     compile (code , "a" , "exec" )
285+                     compile (code , "a" , "exec" , optimize = opt_level )
286+                     compile (mod , "a" , "exec" )
287+                     compile (mod , "a" , "exec" , optimize = opt_level )
288+ 
289+     def  test_docstring_optimization_multiple_nodes (self ):
290+         # https://github.com/python/cpython/issues/137308 
291+         class_example  =  textwrap .dedent (
292+             """ 
293+             class A: 
294+                 ''' 
295+                 Docstring 
296+                 ''' 
297+                 x = 1 
298+             """ 
299+         )
300+ 
301+         def_example  =  textwrap .dedent (
302+             """ 
303+             def some(): 
304+                 ''' 
305+                 Docstring 
306+ 
307+             ''' 
308+                 x = 1 
309+             """ 
310+         )
311+ 
312+         async_def_example  =  textwrap .dedent (
313+             """ 
314+             async def some(): 
315+ 
316+                 '''Docstring 
317+ 
318+             ''' 
319+                 x = 1 
320+             """ 
321+         )
322+ 
323+         for  code  in  [
324+             class_example ,
325+             def_example ,
326+             async_def_example ,
327+         ]:
328+             for  opt_level  in  [0 , 1 , 2 ]:
329+                 with  self .subTest (code = code , opt_level = opt_level ):
330+                     mod  =  ast .parse (code , optimize = opt_level )
331+                     if  opt_level  ==  2 :
332+                         self .assertNotIsInstance (
333+                             mod .body [0 ].body [0 ],
334+                             (ast .Pass , ast .Expr ),
335+                         )
336+                     else :
337+                         self .assertIsInstance (mod .body [0 ].body [0 ], ast .Expr )
338+                         self .assertIsInstance (
339+                             mod .body [0 ].body [0 ].value ,
340+                             ast .Constant ,
341+                         )
342+ 
343+                     compile (code , "a" , "exec" )
344+                     compile (code , "a" , "exec" , optimize = opt_level )
345+                     compile (mod , "a" , "exec" )
346+                     compile (mod , "a" , "exec" , optimize = opt_level )
347+ 
223348    def  test_slice (self ):
224349        slc  =  ast .parse ("x[::]" ).body [0 ].value .slice 
225350        self .assertIsNone (slc .upper )
0 commit comments