def test_pub_sub_select_channel(self): # Connect self._context1.bind("localhost:test1") self._context2.connect("localhost:test1") # Create channels pub1 = yoton.PubChannel(self._context1, "foo1") pub2 = yoton.PubChannel(self._context1, "foo2") # sub1 = yoton.SubChannel(self._context2, "foo1") sub2 = yoton.SubChannel(self._context2, "foo2") # Send a bunch of messages ii = [0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1] for i in range(len(ii)): pub = [pub1, pub2][ii[i]] pub.send(str(i)) time.sleep(0.1) # Receive in right order count = 0 while True: sub = yoton.select_sub_channel(sub1, sub2) if sub: i = int(sub.recv()) self.assertEqual(i, count) count += 1 else: break # Test count self.assertEqual(count, len(ii))
def test_pub_sub_select_channel(self): # Connect self._context1.bind('localhost:test1') self._context2.connect('localhost:test1') # Create channels pub1 = yoton.PubChannel(self._context1, 'foo1') pub2 = yoton.PubChannel(self._context1, 'foo2') # sub1 = yoton.SubChannel(self._context2, 'foo1') sub2 = yoton.SubChannel(self._context2, 'foo2') # Send a bunch of messages I = [0,1,0,0,1,0,1,1,1,0,0,1,0,0,0,1,1,0,1] for i in range(len(I)): pub = [pub1, pub2][I[i]] pub.send(str(i)) time.sleep(0.1) # Receive in right order count = 0 while True: sub = yoton.select_sub_channel(sub1, sub2) if sub: i = int(sub.recv()) self.assertEqual(i, count) count += 1 else: break # Test count self.assertEqual(count, len(I))
def _process_commands(self): # Run startup code/script inside the loop (only the first time) # so that keyboard interrupt will work if self._codeToRunOnStartup: self.context._stat_interpreter.send('Busy') self._codeToRunOnStartup, tmp = None, self._codeToRunOnStartup self.pushline(tmp) if self._scriptToRunOnStartup: self.context._stat_interpreter.send('Busy') self._scriptToRunOnStartup, tmp = None, self._scriptToRunOnStartup self.runfile(tmp) # Flush real stdout / stderr sys.__stdout__.flush() sys.__stderr__.flush() # Set status and prompt? # Prompt is allowed to be an object with __str__ method if self.newPrompt: self.newPrompt = False ps = [sys.ps1, sys.ps2][bool(self.more)] self.context._strm_prompt.send(str(ps)) if True: # Determine state. The message is really only send # when the state is different. Note that the kernelbroker # can also set the state ("Very busy", "Busy", "Dead") if self._dbFrames: self.context._stat_interpreter.send('Debug') elif self.more: self.context._stat_interpreter.send('More') else: self.context._stat_interpreter.send('Ready') # Are we still connected? if sys.stdin.closed or not self.context.connection_count: # Exit from main loop. # This will raise SystemExit and will shut us down in the # most appropriate way sys.exit() # Get channel to take a message from ch = yoton.select_sub_channel(self.context._ctrl_command, self.context._ctrl_code) if ch is None: pass # No messages waiting elif ch is self.context._ctrl_command: # Read command line1 = self.context._ctrl_command.recv(False) # Command if line1: # Notify what we're doing self.context._strm_echo.send(line1) self.context._stat_interpreter.send('Busy') self.newPrompt = True # Convert command # (only a few magics are supported if IPython is active) line2 = self.magician.convert_command(line1.rstrip('\n')) # Execute actual code if line2 is not None: for line3 in line2.split('\n'): # not splitlines! self.more = self.pushline(line3) else: self.more = False self._resetbuffer() elif ch is self.context._ctrl_code: # Read larger block of code (dict) msg = self.context._ctrl_code.recv(False) if msg: # Notify what we're doing # (runlargecode() sends on stdin-echo) self.context._stat_interpreter.send('Busy') self.newPrompt = True # Execute code self.runlargecode(msg) # Reset more stuff self._resetbuffer() self.more = False else: # This should not happen, but if it does, just flush! ch.recv(False)
def _mainloop(self): """ The actual main loop of the interpreter. """ # Get channels as local variables ctrl_command = self.context._ctrl_command ctrl_code = self.context._ctrl_code strm_echo = self.context._strm_echo strm_prompt = self.context._strm_prompt stat_interpreter = self.context._stat_interpreter # To keep track of whether to send a new prompt, and whether more # code is expected. more = 0 newPrompt = True while True: try: # Run startup script inside the loop (only the first time) # so that keyboard interrupt will work if self._scriptToRunOnStartup: stat_interpreter.send('Busy') self._scriptToRunOnStartup, tmp = None, self._scriptToRunOnStartup self.runfile(tmp) # Set status and prompt? # Prompt is allowed to be an object with __str__ method if newPrompt: newPrompt = False # Write prompt (note that the second "if" is not an "elif"! preamble = '' if self._dbFrames: preamble = '(' + self._dbFrameName + ')' if more: strm_prompt.send(preamble + str(sys.ps2)) else: strm_prompt.send(preamble + str(sys.ps1)) if True: # Determine state. The message is really only send # when the state is different. Note that the kernelbroker # can also set the state ("Very busy", "Busy", "Dead") if self._dbFrames: stat_interpreter.send('Debug') elif more: stat_interpreter.send('More') else: stat_interpreter.send('Ready') # Are we still connected? if sys.stdin.closed or not self.context.connection_count: # Exit from main loop break # Get channel to take a message from ch = yoton.select_sub_channel(ctrl_command, ctrl_code) if ch is None: pass # No messages waiting elif ch is ctrl_command: # Read command line1 = ctrl_command.recv(False) # Command if line1: # Notify what we're doing strm_echo.send(line1) stat_interpreter.send('Busy') newPrompt = True # Convert command line2 = self.magician.convert_command( line1.rstrip('\n')) # Execute actual code if line2 is not None: for line3 in line2.split('\n'): # not splitlines! more = self.pushline(line3) else: more = False self._resetbuffer() elif ch is ctrl_code: # Read larger block of code (dict) msg = ctrl_code.recv(False) if msg: # Notify what we're doing # (runlargecode() sends on stdin-echo) stat_interpreter.send('Busy') newPrompt = True # Execute code self.runlargecode(msg) # Reset more stuff self._resetbuffer() more = False else: # This should not happen, but if it does, just flush! ch.recv(False) # Keep GUI toolkit up to date if self.guiApp: self.guiApp.processEvents() # Wait for a bit at each round time.sleep(self.sleeptime) # 50 ms except KeyboardInterrupt: self.write("\nKeyboardInterrupt\n") self._resetbuffer() more = 0 except TypeError: # For some reason, when wx is hijacked, keyboard interrupts # result in a TypeError. # I tried to find the source, but did not find it. If anyone # has an idea, please e-mail me! if self.guiName == 'WX': self.write( "\nKeyboard Interrupt\n") # space to see difference self._resetbuffer() more = 0 except SystemExit: # Exit from interpreter (essentially SystemExit falls through) raise
def poll(self, channel=None): """ poll() To keep the shell up-to-date. Call this periodically. """ if self._write_buffer: # There is still data in the buffer sub, M = self._write_buffer else: # Check what subchannel has the latest message pending sub = yoton.select_sub_channel(self._strm_out, self._strm_err, self._strm_echo, self._strm_raw, self._strm_broker, self._strm_prompt) # Read messages from it if sub: M = sub.recv_selected() #M = [sub.recv()] # Slow version (for testing) # Optimization: handle backspaces on stack of messages if sub is self._strm_out: M = self._handleBackspacesOnList(M) # New prompt? if sub is self._strm_prompt: self.stateChanged.emit(self) # Write all pending messages that are later than any other message if sub: # Select messages to process N = 256 M, buffer = M[:N], M[N:] # Buffer the rest if buffer: self._write_buffer = sub, buffer else: self._write_buffer = None # Get how to deal with prompt prompt = 0 if sub is self._strm_echo: prompt = 1 elif sub is self._strm_prompt: prompt = 2 # Get color color = None if sub is self._strm_broker: color = '#000' elif sub is self._strm_raw: color = '#888888' # Halfway elif sub is self._strm_err: color = '#F00' # Write self.write(''.join(M), prompt, color) # Do any actions? action = self._strm_action.recv(False) if action: if action.startswith('open '): fname = action.split(' ', 1)[1] iep.editors.loadFile(fname) else: print('Unkown action: %s' % action) # Update status state = self._stat_interpreter.recv() if state != self._state: self._state = state self.stateChanged.emit(self) # Update debug status state = self._stat_debug.recv() if state != self._debugState: self._debugState = state self.debugStateChanged.emit(self)
def poll(self, channel=None): """ poll() To keep the shell up-to-date. Call this periodically. """ if self._write_buffer: # There is still data in the buffer sub, M = self._write_buffer else: # Check what subchannel has the latest message pending sub = yoton.select_sub_channel(self._strm_out, self._strm_err, self._strm_echo, self._strm_raw, self._strm_broker, self._strm_prompt ) # Read messages from it if sub: M = sub.recv_selected() #M = [sub.recv()] # Slow version (for testing) # Optimization: handle backspaces on stack of messages if sub is self._strm_out: M = self._handleBackspacesOnList(M) # New prompt? if sub is self._strm_prompt: self.stateChanged.emit(self) # Write all pending messages that are later than any other message if sub: # Select messages to process N = 256 M, buffer = M[:N], M[N:] # Buffer the rest if buffer: self._write_buffer = sub, buffer else: self._write_buffer = None # Get how to deal with prompt prompt = 0 if sub is self._strm_echo: prompt = 1 elif sub is self._strm_prompt: prompt = 2 # Get color color = None if sub is self._strm_broker: color = '#000' elif sub is self._strm_raw: color = '#888888' # Halfway elif sub is self._strm_err: color = '#F00' # Write self.write(''.join(M), prompt, color) # Do any actions? action = self._strm_action.recv(False) if action: if action.startswith('open '): fname = action.split(' ',1)[1] iep.editors.loadFile(fname) else: print('Unkown action: %s' % action) # Update status state = self._stat_interpreter.recv() if state != self._state: self._state = state self.stateChanged.emit(self) # Update debug status state = self._stat_debug.recv() if state != self._debugState: self._debugState = state self.debugStateChanged.emit(self)
def _mainloop(self): """ The actual main loop of the interpreter. """ # Get channels as local variables ctrl_command = self.context._ctrl_command ctrl_code = self.context._ctrl_code strm_echo = self.context._strm_echo strm_prompt = self.context._strm_prompt stat_interpreter = self.context._stat_interpreter # To keep track of whether to send a new prompt, and whether more # code is expected. more = 0 newPrompt = True while True: try: # Run startup script inside the loop (only the first time) # so that keyboard interrupt will work if self._scriptToRunOnStartup: stat_interpreter.send('Busy') self._scriptToRunOnStartup, tmp = None, self._scriptToRunOnStartup self.runfile(tmp) # Set status and prompt? # Prompt is allowed to be an object with __str__ method if newPrompt: newPrompt = False # Write prompt (note that the second "if" is not an "elif"! preamble = '' if self._dbFrames: preamble = '('+self._dbFrameName+')' if more: strm_prompt.send(preamble+str(sys.ps2)) else: strm_prompt.send(preamble+str(sys.ps1)) if True: # Determine state. The message is really only send # when the state is different. Note that the kernelbroker # can also set the state ("Very busy", "Busy", "Dead") if self._dbFrames: stat_interpreter.send('Debug') elif more: stat_interpreter.send('More') else: stat_interpreter.send('Ready') # Are we still connected? if sys.stdin.closed or not self.context.connection_count: # Exit from main loop break # Get channel to take a message from ch = yoton.select_sub_channel(ctrl_command, ctrl_code) if ch is None: pass # No messages waiting elif ch is ctrl_command: # Read command line1 = ctrl_command.recv(False) # Command if line1: # Notify what we're doing strm_echo.send(line1) stat_interpreter.send('Busy') newPrompt = True # Convert command line2 = self.magician.convert_command(line1.rstrip('\n')) # Execute actual code if line2 is not None: for line3 in line2.split('\n'): # not splitlines! more = self.pushline(line3) else: more = False self._resetbuffer() elif ch is ctrl_code: # Read larger block of code (dict) msg = ctrl_code.recv(False) if msg: # Notify what we're doing # (runlargecode() sends on stdin-echo) stat_interpreter.send('Busy') newPrompt = True # Execute code self.runlargecode(msg) # Reset more stuff self._resetbuffer() more = False else: # This should not happen, but if it does, just flush! ch.recv(False) # Keep GUI toolkit up to date if self.guiApp: self.guiApp.processEvents() # Wait for a bit at each round time.sleep(self.sleeptime) # 50 ms except KeyboardInterrupt: self.write("\nKeyboardInterrupt\n") self._resetbuffer() more = 0 except TypeError: # For some reason, when wx is hijacked, keyboard interrupts # result in a TypeError. # I tried to find the source, but did not find it. If anyone # has an idea, please e-mail me! if self.guiName == 'WX': self.write("\nKeyboard Interrupt\n") # space to see difference self._resetbuffer() more = 0 except SystemExit: # Exit from interpreter (essentially SystemExit falls through) raise