fix(form): Ctrl+Enter submits with full flow (validate + clearOnSubmit)#8779
fix(form): Ctrl+Enter submits with full flow (validate + clearOnSubmit)#8779KJyang-0114 wants to merge 3 commits intomarimo-team:mainfrom
Conversation
On macOS with pip-installed Python (e.g. python.org installer),
only 'pip3' is available in PATH, not 'pip'. This caused
PipPackageManager.is_manager_installed() to return False because
shutil.which('pip') could not find it.
Changes:
- PipPackageManager.is_manager_installed(): add fallback check via
'python -m pip --version' when 'pip' is not in PATH
- PipPackageManager.install_command(): use 'python -m pip' instead of
'pip --python python_exe'
- PipPackageManager.uninstall(): same
- PipPackageManager.list_packages(): same
Fixes marimo-team#8775
…SError handling - Primary check: use python -m pip (consistent with actual invocation) - Fallback: check which(pip) for PATH-based pip - Catch OSError in addition to TimeoutExpired/FileNotFoundError - Add unit tests for fallback logic and PermissionError handling
…arOnSubmit) Ctrl+Enter in a form text input previously called setValue() directly, bypassing validation (shouldValidate) and clear_on_submit behavior. Now uses form.requestSubmit() to run the full onSubmit handler, matching the Submit button behavior. Fixes marimo-team#8324
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
I have read the CLA Document and I hereby sign the CLA 1 out of 2 committers have signed the CLA. |
There was a problem hiding this comment.
Pull request overview
This PR aims to make keyboard submission behavior consistent for forms (Ctrl/Cmd+Enter triggers the same validate → submit → clear flow as the Submit button) and also adjusts the internal pip package manager to invoke pip via python -m pip, adding a new availability check and corresponding tests.
Changes:
- Frontend: route Ctrl/Cmd+Enter through the form’s native submit path via
requestSubmit()so validation andclearOnSubmitare applied. - Runtime: change
PipPackageManagercommands frompip --python <exe> ...to<python> -m pip .... - Tests: add coverage for the new
PipPackageManager.is_manager_installed()logic and update command expectations.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
frontend/src/plugins/impl/FormPlugin.tsx |
Uses requestSubmit() on Ctrl/Cmd+Enter so keyboard submission uses the same onSubmit flow as the Submit button. |
marimo/_runtime/packages/pypi_package_manager.py |
Switches pip invocation to python -m pip and adds a pip availability check implementation. |
tests/_runtime/packages/test_pypi_package_manager.py |
Adds tests for pip availability checks and updates expected pip command invocations. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Fallback: check if pip is on PATH (handles cases where pip is | ||
| # available but python -m pip is not desired/needed) | ||
| if DependencyManager.which(self.name): | ||
| return True |
There was a problem hiding this comment.
is_manager_installed() returns True when python -m pip --version fails but pip exists on PATH. However this manager now always invokes pip via [self._python_exe, "-m", "pip", ...], so a PATH-only pip does not make pip usable for this manager and will lead to false positives (followed by install/list failures). Consider removing the PATH fallback (return False if python -m pip fails), or actually switching the subsequent commands to use the PATH pip when the fallback triggers.
| """Primary python -m pip fails but pip is on PATH → returns True (fallback).""" | ||
| mock_run.return_value = MagicMock(returncode=1) | ||
| mock_which.return_value = True | ||
| mgr = PipPackageManager() | ||
| assert mgr.is_manager_installed() is True | ||
| # Primary check was called and failed | ||
| mock_run.assert_called_once() | ||
| # Fallback which() was also called | ||
| mock_which.assert_called_once_with("pip") |
There was a problem hiding this comment.
This test asserts that is_manager_installed() should return True when the python -m pip check fails but pip is on PATH. Given PipPackageManager now always runs pip as python -m pip, this fallback behavior makes the availability check inconsistent with actual execution. Either adjust the test to expect False here, or update the implementation to truly use the PATH pip when the fallback path is taken.
| """Primary python -m pip fails but pip is on PATH → returns True (fallback).""" | |
| mock_run.return_value = MagicMock(returncode=1) | |
| mock_which.return_value = True | |
| mgr = PipPackageManager() | |
| assert mgr.is_manager_installed() is True | |
| # Primary check was called and failed | |
| mock_run.assert_called_once() | |
| # Fallback which() was also called | |
| mock_which.assert_called_once_with("pip") | |
| """Primary python -m pip fails even though pip is on PATH → returns False.""" | |
| mock_run.return_value = MagicMock(returncode=1) | |
| mock_which.return_value = True | |
| mgr = PipPackageManager() | |
| assert mgr.is_manager_installed() is False | |
| # Primary check was called and failed | |
| mock_run.assert_called_once() | |
| # We no longer rely on PATH `pip` as a successful fallback when `python -m pip` fails. | |
| # `mock_which` may or may not be consulted depending on the implementation, but it | |
| # should not cause this scenario to be treated as success. |
| class PipPackageManager(PypiPackageManager): | ||
| name = "pip" | ||
| docs_url = "https://pip.pypa.io/" | ||
|
|
||
| def is_manager_installed(self) -> bool: | ||
| """Check if pip is available. | ||
|
|
||
| On some platforms (e.g. macOS with pip-installed Python from python.org), | ||
| only `pip3` is available in PATH, not `pip`. We first try the method we | ||
| actually use to invoke pip (`python -m pip`), then fall back to a PATH | ||
| check for compatibility. | ||
| """ |
There was a problem hiding this comment.
The PR title/description focus on a frontend Form Ctrl+Enter submission fix, but this diff also changes the pip package manager invocation (pip --python → python -m pip) and adds new is_manager_installed() behavior + tests. Please update the PR description/title to reflect the additional scope, or split the pip-related changes into a separate PR so reviewers can assess/release them independently.
|
I have read the CLA Document and I hereby sign the CLA |
|
Can you break this into 2 PRs? I think you had it right before. |
On macOS with pip-installed Python (e.g. python.org installer),
only 'pip3' is available in PATH, not 'pip'. This caused
PipPackageManager.is_manager_installed() to return False because
shutil.which('pip') could not find it.
Changes:
- PipPackageManager.is_manager_installed(): primary check via
'python -m pip --version', fallback to which('pip')
- PipPackageManager.install_command(): use 'python -m pip' instead of
'pip --python python_exe'
- PipPackageManager.uninstall(): same
- PipPackageManager.list_packages(): same
- Add unit tests for fallback logic and error handling
Fixes #8775
Cherry-picked from PR #8779 (commits 6953b4a, db75b74)
…8840) Fixes #8775 Cherry picked from #8776 #8779 by @KJyang-0114 Co-authored-by: KJyang-0114 <kjyang011487@gmail.com>
Changes
File:
frontend/src/plugins/impl/FormPlugin.tsxProblem: When pressing Ctrl+Enter in a text input inside a form with
clear_on_submit=True, the form was NOT cleared. Additionally, Ctrl+Enter bypassed validation even whenshouldValidate=True.Root cause: the
onKeyDownhandler directly calledsetValue(newValue), bypassing theonSubmithandler which contains the validate → setValue → clear flow.Fix: Replace
setValue(newValue)withformDiv.current?.requestSubmit()in the Ctrl+Enter handler. This routes through the existingonSubmithandler, ensuring consistent behavior between the Submit button and Ctrl+Enter.Test evidence
Risk
requestSubmit()which fires the sameonSubmiteventRollback