def __init__(self, *args, **kwargs): super(InterpreterGui, self).__init__(*args, **kwargs) self.animation = Animation(input_fail_alpha=0., t='out_expo', duration=0.5) self.interpreter = InterpreterWrapper( 'Interpreter', use_thread=True, throttle_output=App.get_running_app().setting__throttle_output, thread_name='interpreter') self.interpreter.bind( interpreter_state=self.setter('interpreter_state')) self.interpreter.bind(lock_input=self.setter('lock_input')) self.interpreter.bind(on_execution_complete=self.execution_complete) self.interpreter.bind(on_stdout=self.on_stdout) self.interpreter.bind(on_stderr=self.on_stderr) self.interpreter.bind(on_notification=self.on_notification) self.interpreter.bind(on_user_message=self.on_user_message) self.interpreter.bind(on_missing_labels=self.on_missing_labels) self.interpreter.bind(on_request_input=self.on_request_input) self.size_hint = .5, .5 Clock.schedule_once(self.post_init_check, 0)
def __init__(self, *args, **kwargs): super(InterpreterGui, self).__init__(*args, **kwargs) self.animation = Animation(input_fail_alpha=0., t='out_expo', duration=0.5) self.interpreter = InterpreterWrapper( 'Interpreter', use_thread=True, throttle_output=self.setting__throttle_output, thread_name='interpreter') self.interpreter.bind( interpreter_state=self.setter('interpreter_state')) self.interpreter.bind(lock_input=self.setter('lock_input')) self.interpreter.bind(on_execution_complete=self.execution_complete) self.interpreter.bind(on_stdout=self.on_stdout) self.interpreter.bind(on_stderr=self.on_stderr) self.interpreter.bind(on_notification=self.on_notification) self.interpreter.bind(on_user_message=self.on_user_message) self.interpreter.bind(on_missing_labels=self.on_missing_labels) self.interpreter.bind(on_request_input=self.on_request_input) # self.interpreter = DummyInterpreter() # Clock.schedule_interval(self._dequeue_output_label, 0.05) # Clock.schedule_interval(self._clear_output_label_queue, 1) Clock.schedule_once(self.post_init_check, 0)
class InterpreterGui(ScatterLayout): c1 = NumericProperty() c2 = NumericProperty() c3 = NumericProperty() c4 = NumericProperty() fontSizer = NumericProperty() c1 = 1 c2 = .3 c3 = .4 c4 = .85 fontSizer = 24 output_window = ObjectProperty() code_input = ObjectProperty() #scrollview = ObjectProperty() scatter = ObjectProperty() b = ObjectProperty() subprocesses = [] off = False input_fail_alpha = NumericProperty(0.) lock_input = BooleanProperty(False) _lock_input = BooleanProperty(False) halting = BooleanProperty(False) '''True when the interpreter has been asked to stop but has not yet done so.''' interpreter_state = OptionProperty( 'waiting', options=['waiting', 'interpreting', 'not_responding', 'restarting']) status_label_colour = StringProperty('b2ade6') _output_label_queue = ListProperty([]) dequeue_scheduled = ObjectProperty(None, allownone=True) clear_scheduled = ObjectProperty(None, allownone=True) awaiting_label_display_completion = BooleanProperty(False) throttle_label_output = BooleanProperty() '''Whether to clear the output label queue regularly. If False, labels will always be displayed, but this *will* cause problems with e.g. a constantly printing while loop. ''' interpreted_lines = ListProperty([]) '''A list of the lines of code that have been executed so far.''' completion_threads = [] '''The threads running jedi completion functions.''' most_recent_completion_time = 0. '''The most recent timestamp from a completion. New completions with older timestamps will be ignored.''' move_lock = False scale_lock_left = False scale_lock_right = False scale_lock_top = False scale_lock_bottom = False disp = 1 outDisp = 3 def __init__(self, *args, **kwargs): super(InterpreterGui, self).__init__(*args, **kwargs) self.animation = Animation(input_fail_alpha=0., t='out_expo', duration=0.5) self.interpreter = InterpreterWrapper( 'Interpreter', use_thread=True, throttle_output=App.get_running_app().setting__throttle_output, thread_name='interpreter') self.interpreter.bind( interpreter_state=self.setter('interpreter_state')) self.interpreter.bind(lock_input=self.setter('lock_input')) self.interpreter.bind(on_execution_complete=self.execution_complete) self.interpreter.bind(on_stdout=self.on_stdout) self.interpreter.bind(on_stderr=self.on_stderr) self.interpreter.bind(on_notification=self.on_notification) self.interpreter.bind(on_user_message=self.on_user_message) self.interpreter.bind(on_missing_labels=self.on_missing_labels) self.interpreter.bind(on_request_input=self.on_request_input) self.size_hint = .5, .5 Clock.schedule_once(self.post_init_check, 0) def flip(self): if self.disp == 1: self.code_input.disabled = True self.output_window.disabled = True self.disp = 0 else: self.code_input.disabled = False self.output_window.disabled = False self.disp = 1 def post_init_check(self, *args): if App.get_running_app().ctypes_working: return self.add_user_message_label( ('Could not load ctypes on this device. Keyboard interrupt ' 'will not be available.'), background_colour=(1, 0.6, 0, 1)) def on_lock_input(self, instance, value): if value: self.input_focus_on_disable = self.code_input.focus self._lock_input = True else: self._lock_input = False self.code_input.focus = self.input_focus_on_disable self.ensure_no_ctrl_c_button() self.halting = False def on_stdout(self, interpreter, text): kids = self.output_window.children if len(kids) > self.outDisp: self.output_window.remove_widget(kids[-2]) self.add_output_label(text, 'stdout') def on_stderr(self, interpreter, text): kids = self.output_window.children if len(kids) > self.outDisp: self.output_window.remove_widget(kids[-2]) self.add_output_label(text, 'stderr') def on_notification(self, interpreter, text): self.add_notification_label(text) def on_user_message(self, interpreter, text): self.add_user_message_label(text, background_colour=(1, 0.6, 0, 1)) def on_request_input(self, interpreter, prompt): self.show_input_popup(prompt) def show_input_popup(self, prompt): # Window.softinput_mode = 'below_target' p = InputPopup(prompt=prompt, submit_func=self.send_input) p.open() def send_input(self, text): '''Send the given input to the Python interpreter.''' self.interpreter.send_input(text) def ensure_ctrl_c_button(self): if not App.get_running_app().ctypes_working: return Clock.schedule_once(self._switch_to_ctrl_c_button, 0.4) def _switch_to_ctrl_c_button(self, *args): c = self.ids.carousel if c.index == 0: c.load_next() def clear_output(self): for child in self.output_window.children[:-1]: self.output_window.remove_widget(child) def exec_file(self): App.get_running_app().root.switch_to('filechooser', open_method=self._exec_file, success_screen_name='interpreter', purpose='exec file') def _exec_file(self, filename): self.add_user_message_label('Executing {}...'.format(filename)) self.ensure_ctrl_c_button() self.interpreter.exec_file(filename) def ensure_no_ctrl_c_button(self): Clock.unschedule(self._switch_to_ctrl_c_button) c = self.ids.carousel if c.index == 1: c.load_previous() else: Animation.cancel_all(c) c._start_animation(new_offset=0) def on_interpreter_state(self, instance, value): if value == 'waiting': self.status_label_colour = 'b2ade6' elif value == 'interpreting': self.status_label_colour = 'ade6b4' elif value == 'not_responding': self.status_label_colour = 'e6adad' elif value == 'restarting': self.status_label_colour = 'e6adad' def interpret_line_from_code_input(self): text = self.code_input.text if text == '': self.flash_input_fail() return self.code_input.text = '' self.interpret_line(text) def flash_input_fail(self): self.animation.stop(self) self.input_fail_alpha = 1. self.animation.start(self) def interpret_line(self, text): self.interpreted_lines.append(text) index = self.interpreter.interpret_line(text) self.add_input_label(text, index) self.ensure_ctrl_c_button() def add_user_message_label(self, text, **kwargs): l = UserMessageLabel(text=text, **kwargs) kids = self.output_window.children if len(kids) > self.outDisp: self.output_window.remove_widget(kids[-2]) self.output_window.add_widget(l) #self.scrollview.scroll_to(l) def add_doc_label(self, text, **kwargs): l = DocLabel(text=text, **kwargs) kids = self.output_window.children if len(kids) > self.outDisp: self.output_window.remove_widget(kids[-2]) self.output_window.add_widget(l) #self.scrollview.scroll_to(l) def add_input_label(self, text, index): kids = self.output_window.children if len(kids) > self.outDisp: self.output_window.remove_widget(kids[-2]) l = InputLabel(text=text, index=index, root=self) self.output_window.add_widget(l) #self.scrollview.scroll_to(l) def add_output_label(self, text, stream='stdout'): kids = self.output_window.children if len(kids) > self.outDisp: self.output_window.remove_widget(kids[-2]) self._output_label_queue.append((text, stream)) # self._dequeue_output_label(0) def _add_output_label(self, text, stream='stdout', scroll_to=True): l = OutputLabel(text=text, stream=stream) kids = self.output_window.children if len(kids) > self.outDisp: self.output_window.remove_widget(kids[-2]) self.output_window.add_widget(l) return l def _dequeue_output_label(self, dt): if not self._output_label_queue: return # print('dequeueing', self._output_label_queue) t = time() i = 0 while (time() - t) < 0.005: i += 1 if not self._output_label_queue: break label_text = self._output_label_queue.pop(0) label = self._add_output_label(*label_text, scroll_to=False) print('Rendered {} labels in {}'.format(i, time() - t)) # Animation.stop_all(self.scrollview, 'scroll_x', 'scroll_y') # self.scrollview.scroll_to(label) self.dequeue_scheduled.cancel() self.dequeue_scheduled = None if len(self._output_label_queue) == 0 and self.clear_scheduled: self.clear_scheduled.cancel() self.clear_scheduled = None elif len(self._output_label_queue) > 0: self.dequeue_scheduled = Clock.schedule_once( self._dequeue_output_label, 0.05) if (self.awaiting_label_display_completion and len(self._output_label_queue) == 0): self.awaiting_label_display_completion = False self._execution_complete() def _clear_output_label_queue(self, dt): if not self.throttle_label_output: return labels = self._output_label_queue self._output_label_queue = [] if labels: self.add_missing_labels_marker(labels=labels) if self.dequeue_scheduled: self.dequeue_scheduled.cancel() self.dequeue_scheduled = None if self.clear_scheduled: self.clear_scheduled.cancel() self.clear_scheduled = None if self.awaiting_label_display_completion: self.awaiting_label_display_completion = False self._execution_complete() def on__output_label_queue(self, instance, values): # print('olq', self.dequeue_scheduled, self.clear_scheduled) if self.dequeue_scheduled: return if not self.dequeue_scheduled: self.dequeue_scheduled = Clock.schedule_once( self._dequeue_output_label, 0) if not self.clear_scheduled: self.clear_scheduled = Clock.schedule_once( self._clear_output_label_queue, 1) def on_throttle_label_output(self, instance, value): self.interpreter.set_service_output_throttling(value) def on_missing_labels(self, instance, number): self.add_missing_labels_marker(num_labels=number) def add_missing_labels_marker(self, num_labels=None, labels=None): if labels is not None: num_labels = len(labels) self.add_user_message_label( '{} lines omitted (too many to render)'.format(num_labels), background_colour=(1, 0.6, 0, 1)) # l.labels = labels def add_notification_label(self, text): self.add_break() l = NotificationLabel(text=text) self.output_window.add_widget(l) #self.scrollview.scroll_to(l) self.add_break() def add_break(self): b = BreakMarker() self.output_window.add_widget(b) #self.scrollview.scroll_to(b) def insert_previous_code(self, index, clear=False): if clear: self.code_input.text = '' code = self.interpreter.inputs[index] if self.code_input.text == '': self.code_input.text = code else: self.code_input.text += '\n' + code def send_sigint(self): self.halting = True self.interpreter.send_sigint() def restart_interpreter(self): self.interpreted_lines = [] self.interpreter.restart() def query_restart(self): popup = RestartPopup(interpreter_gui=self) popup.open() def execution_complete(self, *args): '''Called when execution is complete so the TextInput should be unlocked etc., but first this is delayed until messages finish printing. ''' if len(self._output_label_queue) == 0: self._execution_complete() else: self.awaiting_label_display_completion = True def _execution_complete(self): self.add_break() self.lock_input = False self.halting = False self.ensure_no_ctrl_c_button() def get_defs(self): previous_text = '\n'.join(self.interpreted_lines) num_previous_lines = len(previous_text.split('\n')) text = self.code_input.text row_index, line, col_index = self.code_input.currently_edited_line() get_defs('\n'.join([previous_text, text]), self.show_defs, line=row_index + num_previous_lines + 1, col=col_index) def show_defs(self, defs, sigs, error=None): print('docs are', defs) if error is not None: self.add_doc_label(error) return if not defs and not sigs: self.add_doc_label('No definition found at cursor') return if defs: d = defs[0] else: d = sigs[0] if hasattr(d, 'params'): text = '{}({})\n{}'.format( d.desc_with_module, ', '.join([p.description for p in d.params]), d.doc) else: text = '{}\n{}'.format(d.desc_with_module, d.doc) self.add_doc_label(text) def on_touch_up(self, touch): self.move_lock = False self.scale_lock_left = False self.scale_lock_right = False self.scale_lock_top = False self.scale_lock_bottom = False self.size_hint = None, None if touch.grab_current is self: touch.ungrab(self) x = self.pos[0] / 10 x = round(x, 0) x = x * 10 y = self.pos[1] / 10 y = round(y, 0) y = y * 10 self.pos = x, y return super(InterpreterGui, self).on_touch_up(touch) # def transform_with_touch(self, touch): # self.size_hint = None,None # changed = False # x = self.bbox[0][0] # y = self.bbox[0][1] # width = self.bbox[1][0] # height = self.bbox[1][1] # mid_x = x + width / 2 # mid_y = y + height / 2 # inner_width = width * 0.5 # inner_height = height * 0.5 # left = mid_x - (inner_width / 2) # right = mid_x + (inner_width / 2) # top = mid_y + (inner_height / 2) # bottom = mid_y - (inner_height / 2) # # just do a simple one finger drag # if len(self._touches) == self.translation_touches: # # _last_touch_pos has last pos in correct parent space, # # just like incoming touch # dx = (touch.x - self._last_touch_pos[touch][0]) \ # * self.do_translation_x # dy = (touch.y - self._last_touch_pos[touch][1]) \ # * self.do_translation_y # dx = dx / self.translation_touches # dy = dy / self.translation_touches # dx = dx # dy = dy # if (touch.x > left and touch.x < right and touch.y < top and touch.y > bottom or self.move_lock) and not self.scale_lock_left and not self.scale_lock_right and not self.scale_lock_top and not self.scale_lock_bottom: # self.move_lock = True # self.apply_transform(Matrix().translate(dx, dy, 0)) # changed = True # change_x = touch.x - self.prev_x # change_y = touch.y - self.prev_y # anchor_sign = 1 # sign = 1 # if abs(change_x) >= 9 and not self.move_lock and not self.scale_lock_top and not self.scale_lock_bottom: # if change_x < 0: # sign = -1 # if (touch.x < left or self.scale_lock_left) and not self.scale_lock_right: # self.scale_lock_left = True # self.pos = (self.pos[0] + (sign * 10), self.pos[1]) # anchor_sign = -1 # elif (touch.x > right or self.scale_lock_right) and not self.scale_lock_left: # self.scale_lock_right = True # self.size[0] = self.size[0] + (sign * anchor_sign * 10) # self.prev_x = touch.x # changed = True # if abs(change_y) >= 9 and not self.move_lock and not self.scale_lock_left and not self.scale_lock_right: # if change_y < 0: # sign = -1 # if (touch.y > top or self.scale_lock_top) and not self.scale_lock_bottom: # self.scale_lock_top = True # elif (touch.y < bottom or self.scale_lock_bottom) and not self.scale_lock_top: # self.scale_lock_bottom = True # self.pos = (self.pos[0], self.pos[1] + (sign * 10)) # anchor_sign = -1 # self.size[1] = self.size[1] + (sign * anchor_sign * 10) # self.prev_y = touch.y # changed = True # return changed def on_touch_down(self, touch): parent = self.parent.parent me = self.parent parent.remove_widget(me) parent.add_widget(me) self.size_hint = None, None x, y = touch.x, touch.y self.prev_x = touch.x self.prev_y = touch.y # if the touch isnt on the widget we do nothing if not self.do_collide_after_children: if not self.collide_point(x, y): return False # let the child widgets handle the event if they want touch.push() touch.apply_transform_2d(self.to_local) if super(Scatter, self).on_touch_down(touch): # ensure children don't have to do it themselves if 'multitouch_sim' in touch.profile: touch.multitouch_sim = True touch.pop() self._bring_to_front(touch) return True touch.pop() # if our child didn't do anything, and if we don't have any active # interaction control, then don't accept the touch. if not self.do_translation_x and \ not self.do_translation_y and \ not self.do_rotation and \ not self.do_scale: return False if self.do_collide_after_children: if not self.collide_point(x, y): return False if 'multitouch_sim' in touch.profile: touch.multitouch_sim = True # grab the touch so we get all it later move events for sure self._bring_to_front(touch) touch.grab(self) self._touches.append(touch) self._last_touch_pos[touch] = touch.pos return True def Save(self): lifeRaft = [] lifeRaft.append(self.interpreted_lines) lifeRaft.append(self.code_input.text) return lifeRaft def Load(self, prior, curr): self.restart_interpreter() t.sleep(1) self.clear_output() t.sleep(10 / 1000) for i in prior: self.interpret_line(i) t.sleep(10 / 1000) self.code_input.text = curr self.clear_output()
class InterpreterGui(BoxLayout): subprocesses = [] output_window = ObjectProperty() code_input = ObjectProperty() scrollview = ObjectProperty() input_fail_alpha = NumericProperty(0.) lock_input = BooleanProperty(False) _lock_input = BooleanProperty(False) halting = BooleanProperty(False) '''True when the interpreter has been asked to stop but has not yet done so.''' interpreter_state = OptionProperty( 'waiting', options=['waiting', 'interpreting', 'not_responding', 'restarting']) status_label_colour = StringProperty('b2ade6') _output_label_queue = ListProperty([]) dequeue_scheduled = ObjectProperty(None, allownone=True) clear_scheduled = ObjectProperty(None, allownone=True) awaiting_label_display_completion = BooleanProperty(False) throttle_label_output = BooleanProperty() '''Whether to clear the output label queue regularly. If False, labels will always be displayed, but this *will* cause problems with e.g. a constantly printing while loop. ''' interpreted_lines = ListProperty([]) '''A list of the lines of code that have been executed so far.''' completion_threads = [] '''The threads running jedi completion functions.''' most_recent_completion_time = 0. '''The most recent timestamp from a completion. New completions with older timestamps will be ignored.''' def __init__(self, *args, **kwargs): super(InterpreterGui, self).__init__(*args, **kwargs) self.animation = Animation(input_fail_alpha=0., t='out_expo', duration=0.5) self.interpreter = InterpreterWrapper( 'Interpreter', use_thread=True, throttle_output=self.setting__throttle_output, thread_name='interpreter') self.interpreter.bind( interpreter_state=self.setter('interpreter_state')) self.interpreter.bind(lock_input=self.setter('lock_input')) self.interpreter.bind(on_execution_complete=self.execution_complete) self.interpreter.bind(on_stdout=self.on_stdout) self.interpreter.bind(on_stderr=self.on_stderr) self.interpreter.bind(on_notification=self.on_notification) self.interpreter.bind(on_user_message=self.on_user_message) self.interpreter.bind(on_missing_labels=self.on_missing_labels) self.interpreter.bind(on_request_input=self.on_request_input) # self.interpreter = DummyInterpreter() # Clock.schedule_interval(self._dequeue_output_label, 0.05) # Clock.schedule_interval(self._clear_output_label_queue, 1) Clock.schedule_once(self.post_init_check, 0) def post_init_check(self, *args): if self.ctypes_working: return self.add_user_message_label( ('Could not load ctypes on this device. Keyboard interrupt ' 'will not be available.'), background_colour=(1, 0.6, 0, 1)) def on_lock_input(self, instance, value): if value: self.input_focus_on_disable = self.code_input.focus self._lock_input = True else: self._lock_input = False self.code_input.focus = self.input_focus_on_disable self.ensure_no_ctrl_c_button() self.halting = False def on_stdout(self, interpreter, text): self.add_output_label(text, 'stdout') def on_stderr(self, interpreter, text): self.add_output_label(text, 'stderr') def on_notification(self, interpreter, text): self.add_notification_label(text) def on_user_message(self, interpreter, text): self.add_user_message_label(text, background_colour=(1, 0.6, 0, 1)) def on_request_input(self, interpreter, prompt): self.show_input_popup(prompt) def show_input_popup(self, prompt): # Window.softinput_mode = 'below_target' p = InputPopup(prompt=prompt, submit_func=self.send_input) p.open() def send_input(self, text): '''Send the given input to the Python interpreter.''' self.interpreter.send_input(text) def ensure_ctrl_c_button(self): if not self.ctypes_working: return Clock.schedule_once(self._switch_to_ctrl_c_button, 0.4) def _switch_to_ctrl_c_button(self, *args): c = self.ids.carousel if c.index == 0: c.load_next() def clear_output(self): for child in self.output_window.children[:-1]: self.output_window.remove_widget(child) def exec_file(self): self.root.switch_to('filechooser', open_method=self._exec_file, success_screen_name='interpreter', purpose='exec file') def _exec_file(self, filename): self.add_user_message_label('Executing {}...'.format(filename)) self.ensure_ctrl_c_button() self.interpreter.exec_file(filename) def ensure_no_ctrl_c_button(self): Clock.unschedule(self._switch_to_ctrl_c_button) c = self.ids.carousel if c.index == 1: c.load_previous() else: Animation.cancel_all(c) c._start_animation(new_offset=0) def on_interpreter_state(self, instance, value): if value == 'waiting': self.status_label_colour = 'b2ade6' elif value == 'interpreting': self.status_label_colour = 'ade6b4' elif value == 'not_responding': self.status_label_colour = 'e6adad' elif value == 'restarting': self.status_label_colour = 'e6adad' def interpret_line_from_code_input(self): text = self.code_input.text if text == '': self.flash_input_fail() return self.code_input.text = '' self.interpret_line(text) def flash_input_fail(self): self.animation.stop(self) self.input_fail_alpha = 1. self.animation.start(self) def interpret_line(self, text): self.interpreted_lines.append(text) index = self.interpreter.interpret_line(text) self.add_input_label(text, index) self.ensure_ctrl_c_button() def add_user_message_label(self, text, **kwargs): l = UserMessageLabel(text=text, **kwargs) self.output_window.add_widget(l) self.scrollview.scroll_to(l) def add_doc_label(self, text, **kwargs): l = DocLabel(text=text, **kwargs) self.output_window.add_widget(l) self.scrollview.scroll_to(l) def add_input_label(self, text, index): l = InputLabel(text=text, index=index, root=self) self.output_window.add_widget(l) self.scrollview.scroll_to(l) def add_output_label(self, text, stream='stdout'): self._output_label_queue.append((text, stream)) # self._dequeue_output_label(0) def _add_output_label(self, text, stream='stdout', scroll_to=True): l = OutputLabel(text=text, stream=stream) self.output_window.add_widget(l) if scroll_to: self.scrollview.scroll_to(l) return l def _dequeue_output_label(self, dt): if not self._output_label_queue: return # print('dequeueing', self._output_label_queue) t = time() i = 0 while (time() - t) < 0.005: i += 1 if not self._output_label_queue: break label_text = self._output_label_queue.pop(0) label = self._add_output_label(*label_text, scroll_to=False) print('Rendered {} labels in {}'.format(i, time() - t)) Animation.stop_all(self.scrollview, 'scroll_x', 'scroll_y') self.scrollview.scroll_to(label) self.dequeue_scheduled.cancel() self.dequeue_scheduled = None if len(self._output_label_queue) == 0 and self.clear_scheduled: self.clear_scheduled.cancel() self.clear_scheduled = None elif len(self._output_label_queue) > 0: self.dequeue_scheduled = Clock.schedule_once( self._dequeue_output_label, 0.05) if (self.awaiting_label_display_completion and len(self._output_label_queue) == 0): self.awaiting_label_display_completion = False self._execution_complete() def _clear_output_label_queue(self, dt): if not self.throttle_label_output: return labels = self._output_label_queue self._output_label_queue = [] if labels: self.add_missing_labels_marker(labels=labels) if self.dequeue_scheduled: self.dequeue_scheduled.cancel() self.dequeue_scheduled = None if self.clear_scheduled: self.clear_scheduled.cancel() self.clear_scheduled = None if self.awaiting_label_display_completion: self.awaiting_label_display_completion = False self._execution_complete() def on__output_label_queue(self, instance, values): # print('olq', self.dequeue_scheduled, self.clear_scheduled) if self.dequeue_scheduled: return if not self.dequeue_scheduled: self.dequeue_scheduled = Clock.schedule_once( self._dequeue_output_label, 0) if not self.clear_scheduled: self.clear_scheduled = Clock.schedule_once( self._clear_output_label_queue, 1) def on_throttle_label_output(self, instance, value): self.interpreter.set_service_output_throttling(value) def on_missing_labels(self, instance, number): self.add_missing_labels_marker(num_labels=number) def add_missing_labels_marker(self, num_labels=None, labels=None): if labels is not None: num_labels = len(labels) self.add_user_message_label( '{} lines omitted (too many to render)'.format(num_labels), background_colour=(1, 0.6, 0, 1)) # l.labels = labels def add_notification_label(self, text): self.add_break() l = NotificationLabel(text=text) self.output_window.add_widget(l) self.scrollview.scroll_to(l) self.add_break() def add_break(self): b = BreakMarker() self.output_window.add_widget(b) self.scrollview.scroll_to(b) def insert_previous_code(self, index, clear=False): if clear: self.code_input.text = '' code = self.interpreter.inputs[index] if self.code_input.text == '': self.code_input.text = code else: self.code_input.text += '\n' + code def send_sigint(self): self.halting = True self.interpreter.send_sigint() def restart_interpreter(self): self.interpreted_lines = [] self.interpreter.restart() def query_restart(self): popup = RestartPopup(interpreter_gui=self) popup.open() def execution_complete(self, *args): '''Called when execution is complete so the TextInput should be unlocked etc., but first this is delayed until messages finish printing. ''' if len(self._output_label_queue) == 0: self._execution_complete() else: self.awaiting_label_display_completion = True def _execution_complete(self): self.add_break() self.lock_input = False self.halting = False self.ensure_no_ctrl_c_button() def get_defs(self): previous_text = '\n'.join(self.interpreted_lines) num_previous_lines = len(previous_text.split('\n')) text = self.code_input.text row_index, line, col_index = self.code_input.currently_edited_line() get_defs('\n'.join([previous_text, text]), self.show_defs, line=row_index + num_previous_lines + 1, col=col_index) def show_defs(self, defs, sigs, error=None): print('docs are', defs) if error is not None: self.add_doc_label(error) return if not defs and not sigs: self.add_doc_label('No definition found at cursor') return if defs: d = defs[0] else: d = sigs[0] if hasattr(d, 'params'): text = '{}({})\n{}'.format( d.desc_with_module, ', '.join([p.description for p in d.params]), d.doc) else: text = '{}\n{}'.format(d.desc_with_module, d.doc) self.add_doc_label(text)