Skip to content

Conversation

dgrahn
Copy link
Contributor

@dgrahn dgrahn commented Jul 17, 2025

This PR is in response to #329. It adds a handler which allows the user of the NotebookClient to respond to input requests. This feature is lacking in many tools that run Jupyter Notebooks via script. Hopefully this will help facilitate the functionality in other places. I personally plan to use this feature very soon from the repo directly and will upgrade to pip as soon as it is available.

The implementation was fairly straightforward, but slightly more complicated than the original issue to blend more seamlessly. There is now a new async polling task that watches for input requests and then hands them off to the handler. The handler receives cell, cell_index, and input_request. If the handler is not set, this task is never spawned and functionality remains as is.

Tests were also modified to ensure that this new functionality was covered.

Usage

import nbformat
from nbclient import NotebookClient

# Create a notebook with an input cell
nb = nbformat.v4.new_notebook()

# Add a cell that requests user input
cell = nbformat.v4.new_code_cell(
    source='''
# This cell requests user input
name = input("Enter your name: ")
age = input("Enter your age: ")
print(f"Hello {name}, you are {age} years old!")
'''
)
nb.cells.append(cell)

def handle_input_request(cell, cell_index, input_request):
    """Provide predefined responses to input requests."""
    print(f"📝 Input request from cell {cell_index}, {cell}, {input_request}")
    return "Response"

# Create and configure the client
client = NotebookClient(
    nb=nb,
    timeout=10,
    on_cell_input_request=handle_input_request
)

# Execute the notebook
client.execute()
nbformat.write(nb, "output_notebook.ipynb")

Detailed Changes

  • Added a new on_cell_input_request hook to the NotebookClient class, allowing users to handle input requests during cell execution. The hook is called with arguments cell, cell_index, and input_request. (nbclient/client.py, nbclient/client.pyR328-R338)
  • Updated the kernel client configuration to enable allow_stdin only if the on_cell_input_request hook is defined. (nbclient/client.py, nbclient/client.pyL575-R586)
  • Implemented _async_poll_stdin_msg, an asynchronous method to handle input requests from the kernel by invoking the on_cell_input_request hook and sending the response back to the kernel. (nbclient/client.py, nbclient/client.pyR772-R796)
  • Integrated the new input request handling into the async_execute_cell method, ensuring input polling tasks are created, managed, and properly canceled. (nbclient/client.py, Fae205e2L996R1050)
  • Added a new test notebook (InputRequest.ipynb) containing a cell with an input() call to validate the input request functionality. (tests/files/InputRequest.ipynb, tests/files/InputRequest.ipynbR1-R21)
  • Updated the test framework to include the on_cell_input_request hook and mock its behavior for various test cases. (tests/test_client.py, [1] [2]
  • Added a dedicated test (test_input_request_hook) to verify the on_cell_input_request hook is called correctly and with the expected arguments when a cell requests input. (tests/test_client.py, tests/test_client.pyR974-R1005)

Fixes: #329

@dgrahn
Copy link
Contributor Author

dgrahn commented Jul 18, 2025 via email

@davidbrochart
Copy link
Member

Would you like that as part of this PR or a separate one?

What are you referring to?

@dgrahn
Copy link
Contributor Author

dgrahn commented Jul 21, 2025

Sorry. That was mean to be in reply to the conversation about ensure_future vs. create_task. If all of the ensure_futures should be updated to create_task, it may make sense to have a clean PR which just does that and to leave this as ensure_future right now for consistency.

@davidbrochart
Copy link
Member

As you wish, I think it's fine to do it in this PR.

@dgrahn
Copy link
Contributor Author

dgrahn commented Jul 21, 2025

I'll submit another PR changing all of them.

@dgrahn
Copy link
Contributor Author

dgrahn commented Jul 25, 2025

The switch from ensure_task to create_tasks caused some test failures in the CI environment that I did not see locally. I'll need time to review these. In the meantime, are we OK to merge and close this PR?

@dgrahn
Copy link
Contributor Author

dgrahn commented Jul 30, 2025

Hi @davidbrochart. Are you and the team planning to merge this? I'm trying to decide whether to fork and run with the project there or continue contributing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add on_cell_input Callable to Support Input
2 participants