Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 31 additions & 3 deletions opencodeblocks/blocks/codeblock.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,16 @@ def init_run_button(self):
"""Initialize the run button"""
run_button = QPushButton(">", self.root)
run_button.move(int(self.edge_size), int(self.edge_size / 2))
run_button.setFixedSize(int(3 * self.edge_size), int(3 * self.edge_size))
run_button.setFixedSize(int(3 * self.edge_size),
int(3 * self.edge_size))
run_button.clicked.connect(self.run_left)
return run_button

def init_run_all_button(self):
"""Initialize the run all button"""
run_all_button = QPushButton(">>", self.root)
run_all_button.setFixedSize(int(3 * self.edge_size), int(3 * self.edge_size))
run_all_button.setFixedSize(
int(3 * self.edge_size), int(3 * self.edge_size))
run_all_button.clicked.connect(self.run_right)
run_all_button.raise_()

Expand Down Expand Up @@ -132,10 +134,26 @@ def has_output(self) -> bool:
return True
return False

def _interrupt_execution(self):
""" Interrupt an execution, reset the blocks in the queue """
for block, _ in self.source_editor.kernel.execution_queue:
# Reset the blocks that have not been run
block.reset_buttons()
block.has_been_run = False
# Clear the queue
self.source_editor.kernel.execution_queue = []
# Interrupt the kernel
self.source_editor.kernel.kernel_manager.interrupt_kernel()

def run_left(self, in_right_button=False):
"""
Run all of the block's dependencies and then run the block
"""
# If the user presses left run when running, cancel the execution
if self.run_button.text() == "..." and not in_right_button:
self._interrupt_execution()
return

# If no dependencies
if not self.has_input():
return self.run_code()
Expand Down Expand Up @@ -164,17 +182,27 @@ def run_left(self, in_right_button=False):

def run_right(self):
"""Run all of the output blocks and all their dependencies"""
# If the user presses right run when running, cancel the execution
if self.run_all_button.text() == "...":
self._interrupt_execution()
return

# If no output, run left
if not self.has_output():
return self.run_left(in_right_button=True)

# Same as run_left but instead of running the blocks, we'll use run_left
graph = self.scene().create_graph()
edges = bfs_edges(graph, self)
blocks_to_run: List["OCBCodeBlock"] = [self] + [v for _, v in edges]
blocks_to_run: List["OCBCodeBlock"] = [
self] + [v for _, v in edges]
for block in blocks_to_run[::-1]:
block.run_left(in_right_button=True)

def reset_has_been_run(self):
""" Reset has_been_run, is called when the output is an error """
self.has_been_run = False

def update_title(self):
"""Change the geometry of the title widget"""
self.title_widget.setGeometry(
Expand Down
3 changes: 2 additions & 1 deletion opencodeblocks/graphics/kernel.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def message_to_output(self, message: dict) -> Tuple[str, str]:
# output a print (print("Hello World"))
out = message['text']
elif 'traceback' in message:
message_type = 'text'
message_type = 'error'
# output an error
out = '\n'.join(message['traceback'])
else:
Expand All @@ -65,6 +65,7 @@ def run_block(self, block, code: str):
worker.signals.image.connect(block.handle_image)
worker.signals.finished.connect(self.run_queue)
worker.signals.finished_block.connect(block.reset_buttons)
worker.signals.error.connect(block.reset_has_been_run)
block.source_editor.threadpool.start(worker)

def run_queue(self):
Expand Down
3 changes: 3 additions & 0 deletions opencodeblocks/graphics/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class WorkerSignals(QObject):
image = pyqtSignal(str)
finished = pyqtSignal()
finished_block = pyqtSignal()
error = pyqtSignal()


class Worker(QRunnable):
Expand Down Expand Up @@ -40,6 +41,8 @@ async def run_code(self):
self.signals.stdout.emit(output)
elif output_type == 'image':
self.signals.image.emit(output)
elif output_type == 'error':
self.signals.error.emit()
self.signals.finished.emit()
self.signals.finished_block.emit()

Expand Down