Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
9 changes: 9 additions & 0 deletions marimo/_cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -1119,6 +1119,15 @@ def run(
run_in_sandbox,
)

# click consumes `--` as an option terminator and does not pass it
# through to `args`. Recover this sentinel from raw argv so splitting
# logic can preserve "args after --" semantics.
if "--" not in args and "--" in sys.argv[1:]:
double_dash_index = sys.argv[1:].index("--")
tail_after_double_dash = tuple(sys.argv[double_dash_index + 2 :])
if tail_after_double_dash == args:
args = ("--",) + args

paths, notebook_args = _split_run_paths_and_args(name, args)

if len(paths) == 1 and prompt_run_in_docker_container(
Expand Down
43 changes: 43 additions & 0 deletions tests/_cli/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from typing import TYPE_CHECKING, Any
from unittest.mock import patch

import click
import pytest
from click.testing import CliRunner

Expand Down Expand Up @@ -1720,6 +1721,48 @@ def test_cli_run_sandbox_prompt_yes() -> None:
p.kill()


@pytest.mark.parametrize(
"tail_args",
[
["experiment_name=my-exp", "epochs=25"],
["--key", "value"],
["--key"],
["-key", "value"],
],
)
def test_cli_run_double_dash_reaches_splitter(tail_args: list[str]) -> None:
runner = CliRunner()
captured: dict[str, Any] = {}

def _capture(
name: str, args: tuple[str, ...]
) -> tuple[list[str], tuple[str, ...]]:
captured["name"] = name
captured["args"] = args
raise click.ClickException("stop after capture")

with (
patch(
"marimo._cli.cli._split_run_paths_and_args", side_effect=_capture
),
patch(
"marimo._cli.cli.sys.argv",
["marimo", "run", "notebook.py", "--", *tail_args],
),
):
result = runner.invoke(
cli_main,
["run", "notebook.py", "--", *tail_args],
)

assert result.exit_code != 0
assert "stop after capture" in result.output
assert captured["name"] == "notebook.py"
# Desired behavior: splitter should receive the `--` sentinel.
# This currently fails because click consumes `--` before invoking the command.
assert captured["args"] == ("--", *tail_args)


def test_cli_with_custom_pyproject_config(tmp_path: Path) -> None:
# Create a custom pyproject.toml with special marimo config
pyproject_path = tmp_path / "pyproject.toml"
Expand Down
Loading