3434import bpython .scrollfrontend .replpainter as paint
3535import fmtstr .events as events
3636from bpython .scrollfrontend .friendly import NotImplementedError
37+ from bpython .scrollfrontend .coderunner import CodeRunner , FakeOutput
3738
3839#TODO implement paste mode and figure out what the deal with config.paste_time is
3940#TODO figure out how config.auto_display_list=False behaves and implement it
5152class FakeStdout (object ):
5253 def __init__ (self ):
5354 self .data = StringIO ()
54- def seek (self , pos , mode = 0 ): return self .data .seek (pos , mode )
55- def tell (self ): return self .data .tell ()
5655 def read (self , n = None ):
5756 data = self .data .read ()
5857 if isinstance (data , bytes ):
@@ -76,7 +75,7 @@ def __init__(self, on_receive_tuple):
7675
7776 def wait_for_request_or_finish (self ):
7877 logging .debug ('waiting for message from running code (stack depth %r)' , len (traceback .format_stack ()))
79- msg = self .request_from_executing_code .get (timeout = 3 )
78+ msg = self .request_from_executing_code .get ()
8079 logging .debug ('FakeStdin received message %r' , msg )
8180 self .process_request (msg )
8281
@@ -112,7 +111,7 @@ def process_event(self, e):
112111
113112 def readline (self ):
114113 self .request_from_executing_code .put ('can haz stdin line plz' )
115- return self .response_queue .get (timeout = 15 )
114+ return self .response_queue .get ()
116115
117116
118117class Repl (BpythonRepl ):
@@ -134,7 +133,7 @@ class Repl(BpythonRepl):
134133 """
135134
136135 ## initialization, cleanup
137- def __init__ (self , locals_ = None , config = None ):
136+ def __init__ (self , locals_ = None , config = None , stuff_a_refresh_request = None ):
138137 logging .debug ("starting init" )
139138 interp = code .InteractiveInterpreter (locals = locals_ )
140139
@@ -171,6 +170,8 @@ def __init__(self, locals_=None, config=None):
171170 self .cursor_offset_in_line = 0 # from the left, 0 means first char
172171 self .done = True
173172
173+ self .coderunner = CodeRunner (self .interp , stuff_a_refresh_request )
174+ self .stdout = FakeOutput (self .coderunner , self .send_to_stdout )
174175 self .stdin = FakeStdin (self .on_finish_running_code )
175176
176177 self .paste_mode = False
@@ -186,7 +187,7 @@ def __enter__(self):
186187 self .orig_stdout = sys .stdout
187188 self .orig_stderr = sys .stderr
188189 self .orig_stdin = sys .stdin
189- sys .stdout = FakeStdout ()
190+ sys .stdout = self . stdout
190191 sys .stderr = StringIO ()
191192 sys .stdin = self .stdin
192193 return self
@@ -218,9 +219,12 @@ def clean_up_current_line_for_exit(self):
218219 def process_event (self , e ):
219220 """Returns True if shutting down, otherwise mutates state of Repl object"""
220221
222+ logging .debug ("processing event %r" , e )
223+ if isinstance (e , events .RefreshRequestEvent ):
224+ self .run_runsource_part_2_when_finished ()
225+ return
221226 self .last_events .append (e )
222227 self .last_events .pop (0 )
223- #logging.debug("processing event %r", e)
224228 if isinstance (e , events .WindowChangeEvent ):
225229 logging .debug ('window change to %d %d' , e .width , e .height )
226230 self .width , self .height = e .width , e .height
@@ -311,9 +315,12 @@ def on_enter(self, insert_into_history=True):
311315 self .history .append (self ._current_line )
312316 self .push (self ._current_line , insert_into_history = insert_into_history )
313317
318+ def send_to_stdout (self , output ):
319+ self .display_lines .extend (sum ([paint .display_linize (line , self .width ) for line in output .split ('\n ' )], []))
320+
314321 def on_finish_running_code (self , output , error , done , indent ):
315- if output :
316- self .display_lines .extend (sum ([paint .display_linize (line , self .width ) for line in output .split ('\n ' )], []))
322+ # if output:
323+ # self.display_lines.extend(sum([paint.display_linize(line, self.width) for line in output.split('\n')], []))
317324 if error :
318325 self .display_lines .extend ([func_for_letter (self .config .color_scheme ['error' ])(line )
319326 for line in sum ([paint .display_linize (line , self .width )
@@ -405,12 +412,7 @@ def push(self, line, insert_into_history=True):
405412 """
406413 if insert_into_history :
407414 self .insert_into_history (line )
408- t = threading .Thread (target = self .runsource , args = (line ,))
409- t .daemon = True
410- t .start ()
411- logging .debug ('push() is now waiting' )
412- self .stdin .wait_for_request_or_finish ()
413- logging .debug ('push() done waiting' )
415+ self .runsource (line )
414416
415417 def runsource (self , line ):
416418 """Push a line of code on to the buffer, run the buffer, clean up
@@ -429,20 +431,36 @@ def runsource(self, line):
429431 indent = max (0 , indent - self .config .tab_length )
430432 elif line and ':' not in line and line .strip ().startswith (('return' , 'pass' , 'raise' , 'yield' )):
431433 indent = max (0 , indent - self .config .tab_length )
432- out_spot = sys .stdout .tell ()
433434 err_spot = sys .stderr .tell ()
434435 logging .debug ('running %r in interpreter' , self .buffer )
435- unfinished = self .interp .runsource ('\n ' .join (self .buffer ))
436+ self .coderunner .load_code ('\n ' .join (self .buffer ))
437+ self .saved_err_spot = err_spot
438+ self .saved_indent = indent
439+ self .saved_line = line
436440
437441 #current line not added to display buffer if quitting
438442 if self .config .syntax :
439443 self .display_buffer .append (bpythonparse (format (self .tokenize (line ), self .formatter )))
440444 else :
441445 self .display_buffer .append (fmtstr (line ))
442446
443- sys .stdout .seek (out_spot )
447+ if code .compile_command ('\n ' .join (self .buffer )):
448+ logging .debug ('finished - buffer cleared' )
449+ self .display_lines .extend (self .display_buffer_lines )
450+ self .display_buffer = []
451+ self .buffer = []
452+
453+ self .run_runsource_part_2_when_finished ()
454+
455+ def run_runsource_part_2_when_finished (self ):
456+ r = self .coderunner .run_code ()
457+ if r :
458+ unfinished = r == 'unfinished'
459+ self .runsource_part_2 (self .saved_line , self .saved_err_spot , unfinished , self .saved_indent )
460+ self .stdin .wait_for_request_or_finish ()
461+
462+ def runsource_part_2 (self , line , err_spot , unfinished , indent ):
444463 sys .stderr .seek (err_spot )
445- out = sys .stdout .read ()
446464 err = sys .stderr .read ()
447465
448466 # easier debugging: save only errors that aren't from this interpreter
@@ -455,14 +473,10 @@ def runsource(self, line):
455473 logging .debug ('unfinished - line added to buffer' )
456474 self .stdin .request_from_executing_code .put ((None , None , False , indent ))
457475 else :
458- logging .debug ('finished - buffer cleared' )
459- self .display_lines .extend (self .display_buffer_lines )
460- self .display_buffer = []
461- self .buffer = []
462476 if err :
463477 indent = 0
464478 logging .debug ('sending output info' )
465- self .stdin .request_from_executing_code .put ((out [: - 1 ] , err [:- 1 ], True , indent ))
479+ self .stdin .request_from_executing_code .put ((None , err [:- 1 ], True , indent ))
466480 logging .debug ('sent output info' )
467481
468482 def unhighlight_paren (self ):
0 commit comments