-
Notifications
You must be signed in to change notification settings - Fork 557
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Async execute cells #1406
Async execute cells #1406
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,10 +3,11 @@ | |
|
||
# Copyright (c) IPython Development Team. | ||
# Distributed under the terms of the Modified BSD License. | ||
import asyncio | ||
from typing import Optional | ||
from nbformat import NotebookNode | ||
from nbclient import NotebookClient, execute as _execute | ||
from nbclient.util import run_sync | ||
from nbclient.util import ensure_async | ||
# Backwards compatability for imported name | ||
from nbclient.exceptions import CellExecutionError | ||
|
||
|
@@ -76,7 +77,12 @@ def preprocess(self, nb, resources=None, km=None): | |
""" | ||
NotebookClient.__init__(self, nb, km) | ||
self._check_assign_resources(resources) | ||
self.execute() | ||
try: | ||
loop = asyncio.get_event_loop() | ||
except RuntimeError: | ||
loop = asyncio.new_event_loop() | ||
asyncio.set_event_loop(loop) | ||
loop.run_until_complete(self.async_execute()) | ||
return self.nb, self.resources | ||
|
||
async def async_execute_cell( | ||
|
@@ -120,13 +126,13 @@ async def async_execute_cell( | |
""" | ||
# Copied and intercepted to allow for custom preprocess_cell contracts to be fullfilled | ||
self.store_history = store_history | ||
cell, resources = self.preprocess_cell(cell, self.resources, cell_index) | ||
cell, resources = await ensure_async(self.preprocess_cell(cell, self.resources, cell_index)) | ||
# Apply rules from nbclient for where to apply execution counts | ||
if execution_count and cell.cell_type == 'code' and cell.source.strip(): | ||
cell['execution_count'] = execution_count | ||
return cell, resources | ||
|
||
def preprocess_cell(self, cell, resources, index, **kwargs): | ||
async def preprocess_cell(self, cell, resources, index, **kwargs): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. other preprocessors' There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, I think we just need to ensure it is async, I'm pushing another commit. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it will most likely have consequences, because anyone overriding There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think so, since we now call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. as discussed in person, for people who override There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is an issue and it will break downstream projects like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should try because I don't think it is a problem with the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe it will be an issue to mix:
Making the subclass aware of the parent being async but not being async itself on the override does weird things too:
|
||
""" | ||
Override if you want to apply some preprocessing to each cell. | ||
Must return modified cell and resource dictionary. | ||
|
@@ -142,6 +148,5 @@ def preprocess_cell(self, cell, resources, index, **kwargs): | |
Index of the cell being processed | ||
""" | ||
self._check_assign_resources(resources) | ||
# Because nbclient is an async library, we need to wrap the parent async call to generate a syncronous version. | ||
cell = run_sync(NotebookClient.async_execute_cell)(self, cell, index, store_history=self.store_history) | ||
await NotebookClient.async_execute_cell(self, cell, index, store_history=self.store_history) | ||
return cell, self.resources |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may be just moving the issue here.
run_until_complete
will fail if the loop is already running.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, if nbconvert is used in a notebook for instance. But not if it is used from the CLI.