@@ -234,6 +234,46 @@ def bar(x):
234234 expected = "(30, None, [\' def foo(x):\\ n\' , \' return x + 1\\ n\' , \' \\ n\' ], \' <stdin>\' )"
235235 self .assertIn (expected , output , expected )
236236
237+ def test_pythonstartup_success (self ):
238+ # errors based on https://github.com/python/cpython/issues/137576
239+ # case 1: error in user input, but PYTHONSTARTUP is fine
240+ startup_code = "print('notice from pythonstartup')"
241+ with new_startup_env (code = startup_code , histfile = ".pythonhist" ) as startup_env :
242+ # -q to suppress noise
243+ p = spawn_repl ("-q" , env = os .environ | startup_env , isolated = False )
244+ p .stdin .write ("1/0" )
245+ output_lines = kill_python (p ).splitlines ()
246+ traceback_lines = output_lines [2 :- 1 ]
247+ expected_lines = [
248+ 'Traceback (most recent call last):' ,
249+ ' File "<stdin>", line 1, in <module>' ,
250+ ' 1/0' ,
251+ ' ~^~' ,
252+ 'ZeroDivisionError: division by zero' ,
253+ ]
254+ self .assertEqual (output_lines [0 ], 'notice from pythonstartup' )
255+ self .assertEqual (traceback_lines , expected_lines )
256+
257+ def test_pythonstartup_failure (self ):
258+ # case 2: error in PYTHONSTARTUP triggered by user input
259+ startup_code = "def foo():\n 1/0\n "
260+ with new_startup_env (code = startup_code , histfile = ".asyncio_history" ) as startup_env :
261+ # -q to suppress noise
262+ p = spawn_repl ("-q" , env = os .environ | startup_env , isolated = False )
263+ p .stdin .write ("foo()" )
264+ traceback_lines = kill_python (p ).splitlines ()[1 :- 1 ]
265+ expected_lines = [
266+ 'Traceback (most recent call last):' ,
267+ ' File "<stdin>", line 1, in <module>' ,
268+ ' foo()' ,
269+ ' ~~~^^' ,
270+ f' File "{ startup_env ['PYTHONSTARTUP' ]} ", line 2, in foo' ,
271+ ' 1/0' ,
272+ ' ~^~' ,
273+ 'ZeroDivisionError: division by zero' ,
274+ ]
275+ self .assertEqual (traceback_lines , expected_lines )
276+
237277 @unittest .skipUnless (pty , "requires pty" )
238278 def test_asyncio_repl_is_ok (self ):
239279 m , s = pty .openpty ()
@@ -279,55 +319,6 @@ def new_startup_env(*, code: str, histfile: str = ".pythonhist"):
279319 yield {"PYTHONSTARTUP" : filename , "PYTHON_HISTORY" : os .path .join (tmpdir , histfile )}
280320
281321
282- @support .force_not_colorized_test_class
283- class TestPythonStartup (unittest .TestCase ):
284- REPLS = [
285- ("REPL" , spawn_repl , ".pythonhist" ),
286- ("asyncio REPL" , spawn_asyncio_repl , ".asyncio_history" ),
287- ]
288-
289- def test_pythonstartup_success (self ):
290- # errors based on https://github.com/python/cpython/issues/137576
291- # case 1: error in user input, but PYTHONSTARTUP is fine
292- startup_code = "print('from pythonstartup')"
293- for repl_name , repl_factory , histfile in self .REPLS :
294- with (
295- self .subTest (repl_name ),
296- new_startup_env (code = startup_code , histfile = histfile ) as startup_env
297- ):
298- p = repl_factory (env = os .environ | startup_env , isolated = False )
299- p .stdin .write ("1/0" )
300- output = kill_python (p )
301-
302- for expected in (
303- "from pythonstartup" ,
304- "Traceback (most recent call last):" ,
305- 'File "<stdin>", line 1, in <module>' ,
306- "ZeroDivisionError: division by zero" ,
307- ):
308- self .assertIn (expected , output )
309-
310- def test_pythonstartup_failure (self ):
311- # case 2: error in PYTHONSTARTUP triggered by user input
312- startup_code = "def foo():\n 1/0\n "
313- for repl_name , repl_factory , histfile in self .REPLS :
314- with (
315- self .subTest (repl_name ),
316- new_startup_env (code = startup_code , histfile = histfile ) as startup_env
317- ):
318- p = repl_factory (env = os .environ | startup_env , isolated = False )
319- p .stdin .write ('foo()' )
320- output = kill_python (p )
321-
322- for expected in (
323- "Traceback (most recent call last):" ,
324- 'File "<stdin>", line 1, in <module>' ,
325- f'File "{ startup_env ['PYTHONSTARTUP' ]} ", line ' ,
326- "ZeroDivisionError: division by zero" ,
327- ):
328- self .assertIn (expected , output )
329-
330-
331322@support .force_not_colorized_test_class
332323class TestInteractiveModeSyntaxErrors (unittest .TestCase ):
333324
@@ -347,6 +338,7 @@ def f():
347338 self .assertEqual (traceback_lines , expected_lines )
348339
349340
341+ @support .force_not_colorized_test_class
350342class TestAsyncioREPL (unittest .TestCase ):
351343 def test_multiple_statements_fail_early (self ):
352344 user_input = "1 / 0; print(f'afterwards: {1+1}')"
@@ -391,6 +383,56 @@ def test_toplevel_contextvars_async(self):
391383 expected = "toplevel contextvar test: ok"
392384 self .assertIn (expected , output , expected )
393385
386+ def test_pythonstartup_success (self ):
387+ startup_code = "import sys\n print('notice from pythonstartup in asyncio repl', file=sys.stderr)"
388+ with new_startup_env (code = startup_code , histfile = ".asyncio_history" ) as startup_env :
389+ p = spawn_asyncio_repl (env = os .environ | startup_env , stderr = subprocess .PIPE , isolated = False )
390+ p .stdin .write ("1/0" )
391+ kill_python (p )
392+ output_lines = p .stderr .read ().splitlines ()
393+ p .stderr .close ()
394+ self .assertEqual (output_lines [3 ], 'notice from pythonstartup in asyncio repl' )
395+ tb_start_lines = output_lines [4 :6 ]
396+ tb_final_lines = output_lines [13 :]
397+ expected_lines = [
398+ '>>> import asyncio' ,
399+ 'Traceback (most recent call last):' ,
400+ ' File "<stdin>", line 1, in <module>' ,
401+ ' 1/0' ,
402+ ' ~^~' ,
403+ 'ZeroDivisionError: division by zero' ,
404+ '' ,
405+ 'exiting asyncio REPL...' ,
406+ ]
407+ self .assertEqual (tb_start_lines + tb_final_lines , expected_lines )
408+ self .assertEqual (tb_start_lines + tb_final_lines , expected_lines )
409+
410+ def test_pythonstartup_failure (self ):
411+ startup_code = "def foo():\n 1/0\n "
412+ with new_startup_env (code = startup_code , histfile = ".asyncio_history" ) as startup_env :
413+ p = spawn_asyncio_repl (env = os .environ | startup_env , stderr = subprocess .PIPE , isolated = False )
414+ p .stdin .write ("foo()" )
415+ kill_python (p )
416+ output = p .stderr .read ()
417+ p .stderr .close ()
418+ tb_start_lines = output .splitlines ()[3 :5 ]
419+ tb_final_lines = output .splitlines ()[12 :]
420+
421+ expected_lines = [
422+ '>>> import asyncio' ,
423+ 'Traceback (most recent call last):' ,
424+ ' File "<stdin>", line 1, in <module>' ,
425+ ' foo()' ,
426+ ' ~~~^^' ,
427+ f' File "{ startup_env ['PYTHONSTARTUP' ]} ", line 2, in foo' ,
428+ ' 1/0' ,
429+ ' ~^~' ,
430+ 'ZeroDivisionError: division by zero' ,
431+ '' ,
432+ 'exiting asyncio REPL...' ,
433+ ]
434+ self .assertEqual (tb_start_lines + tb_final_lines , expected_lines )
435+
394436
395437if __name__ == "__main__" :
396438 unittest .main ()
0 commit comments