@@ -502,75 +502,79 @@ def sigint(*args):
502502 orig_stdin = sys .stdin
503503 orig_stdout = sys .stdout
504504 orig_stderr = sys .stderr
505- try :
506- # XXX aargh, we have to leave sys.stdin alone for now:
507- # urwid.display_common.RealTerminal.tty_signal_keys calls
508- # sys.stdin.fileno() instead of getting stdin passed in as
509- # raw_display.Screen._term_input_file :(
510-
511- # XXX no stdin for you! What to do here?
512- #sys.stdin = None #FakeStdin(myrepl)
513- sys .stdout = myrepl
514- sys .stderr = myrepl
515-
516- # This needs more thought. What needs to happen inside the mainloop?
517- # Note that we need the mainloop started before our stdio
518- # redirection is hit.
519- def start (main_loop , user_data ):
520- if exec_args :
521- bpargs .exec_code (interpreter , exec_args )
522- if not options .interactive :
523- raise urwid .ExitMainLoop ()
524- if not exec_args :
525- sys .path .insert (0 , '' )
526- # this is CLIRepl.startup inlined.
527- filename = os .environ .get ('PYTHONSTARTUP' )
528- if filename and os .path .isfile (filename ):
529- with open (filename , 'r' ) as f :
530- if py3 :
531- interpreter .runsource (f .read (), filename , 'exec' )
532- else :
533- interpreter .runsource (f .read (), filename , 'exec' ,
534- encode = False )
535-
536- if banner is not None :
537- repl .write (banner )
538- repl .write ('\n ' )
539- myrepl .start ()
540-
541- # This bypasses main_loop.set_alarm_in because we must *not*
542- # hit the draw_screen call (it's unnecessary and slow).
543- def run_find_coroutine ():
544- if find_coroutine ():
545- main_loop .event_loop .alarm (0 , run_find_coroutine )
546-
547- run_find_coroutine ()
548-
549- loop .set_alarm_in (0 , start )
550-
551- while True :
552- try :
553- loop .run ()
554- except KeyboardInterrupt :
555- # HACK: if we run under a twisted mainloop this should
556- # never happen: we have a SIGINT handler set.
557- # If we use the urwid select-based loop we just restart
558- # that loop if interrupted, instead of trying to cook
559- # up an equivalent to reactor.callFromThread (which
560- # is what our Twisted sigint handler does)
561- loop .set_alarm_in (0 ,
562- lambda * args : myrepl .keyboard_interrupt ())
563- continue
564- break
565-
566- if config .hist_length :
567- histfilename = os .path .expanduser (config .hist_file )
568- myrepl .rl_history .save (histfilename ,
569- locale .getpreferredencoding ())
570- finally :
571- sys .stdin = orig_stdin
572- sys .stderr = orig_stderr
573- sys .stdout = orig_stdout
505+ # urwid's screen start() and stop() calls currently hit sys.stdin
506+ # directly (via RealTerminal.tty_signal_keys), so start the screen
507+ # before swapping sys.std*, and swap them back before restoring
508+ # the screen. This also avoids crashes if our redirected sys.std*
509+ # are called before we get around to starting the mainloop
510+ # (urwid raises an exception if we try to draw to the screen
511+ # before starting it).
512+ def run_with_screen_before_mainloop ():
513+ try :
514+ # XXX no stdin for you! What to do here?
515+ sys .stdin = None #FakeStdin(myrepl)
516+ sys .stdout = myrepl
517+ sys .stderr = myrepl
518+
519+ loop .set_alarm_in (0 , start )
520+
521+ while True :
522+ try :
523+ loop .run ()
524+ except KeyboardInterrupt :
525+ # HACK: if we run under a twisted mainloop this should
526+ # never happen: we have a SIGINT handler set.
527+ # If we use the urwid select-based loop we just restart
528+ # that loop if interrupted, instead of trying to cook
529+ # up an equivalent to reactor.callFromThread (which
530+ # is what our Twisted sigint handler does)
531+ loop .set_alarm_in (
532+ 0 , lambda * args : myrepl .keyboard_interrupt ())
533+ continue
534+ break
535+
536+ if config .hist_length :
537+ histfilename = os .path .expanduser (config .hist_file )
538+ myrepl .rl_history .save (histfilename ,
539+ locale .getpreferredencoding ())
540+
541+ finally :
542+ sys .stdin = orig_stdin
543+ sys .stderr = orig_stderr
544+ sys .stdout = orig_stdout
545+
546+ # This needs more thought. What needs to happen inside the mainloop?
547+ def start (main_loop , user_data ):
548+ if exec_args :
549+ bpargs .exec_code (interpreter , exec_args )
550+ if not options .interactive :
551+ raise urwid .ExitMainLoop ()
552+ if not exec_args :
553+ sys .path .insert (0 , '' )
554+ # this is CLIRepl.startup inlined.
555+ filename = os .environ .get ('PYTHONSTARTUP' )
556+ if filename and os .path .isfile (filename ):
557+ with open (filename , 'r' ) as f :
558+ if py3 :
559+ interpreter .runsource (f .read (), filename , 'exec' )
560+ else :
561+ interpreter .runsource (f .read (), filename , 'exec' ,
562+ encode = False )
563+
564+ if banner is not None :
565+ repl .write (banner )
566+ repl .write ('\n ' )
567+ myrepl .start ()
568+
569+ # This bypasses main_loop.set_alarm_in because we must *not*
570+ # hit the draw_screen call (it's unnecessary and slow).
571+ def run_find_coroutine ():
572+ if find_coroutine ():
573+ main_loop .event_loop .alarm (0 , run_find_coroutine )
574+
575+ run_find_coroutine ()
576+
577+ loop .screen .run_wrapper (run_with_screen_before_mainloop )
574578
575579 if config .flush_output and not options .quiet :
576580 sys .stdout .write (myrepl .getstdout ())
0 commit comments