From 1f5069ced95989545d3fe3a1968f0f91e9ce7109 Mon Sep 17 00:00:00 2001 From: Mrutunjay Kinagi Date: Tue, 17 Feb 2026 22:01:31 +0530 Subject: [PATCH] feat(cli): add --prefix option for REST catalog (#3059) --- mkdocs/docs/cli.md | 3 ++- pyiceberg/cli/console.py | 4 ++++ tests/cli/test_console.py | 15 +++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/mkdocs/docs/cli.md b/mkdocs/docs/cli.md index 2fbac5e816..e8cdba66a6 100644 --- a/mkdocs/docs/cli.md +++ b/mkdocs/docs/cli.md @@ -26,7 +26,7 @@ hide: Pyiceberg comes with a CLI that's available after installing the `pyiceberg` package. -You can pass the path to the Catalog using the `--uri` and `--credential` argument, but it is recommended to setup a `~/.pyiceberg.yaml` config as described in the [Catalog](configuration.md) section. +You can pass the path to the Catalog using `--uri` and `--credential`. For REST catalogs that require a path prefix, you can also set `--prefix`. It is still recommended to set up a `~/.pyiceberg.yaml` config as described in the [Catalog](configuration.md) section. ```sh ➜ pyiceberg --help @@ -39,6 +39,7 @@ Options: --ugi TEXT --uri TEXT --credential TEXT + --prefix TEXT --help Show this message and exit. Commands: diff --git a/pyiceberg/cli/console.py b/pyiceberg/cli/console.py index 6c14eea062..8e6fc37001 100644 --- a/pyiceberg/cli/console.py +++ b/pyiceberg/cli/console.py @@ -66,6 +66,7 @@ def wrapper(*args: Any, **kwargs: Any): # type: ignore @click.option("--ugi") @click.option("--uri") @click.option("--credential") +@click.option("--prefix") @click.pass_context def run( ctx: Context, @@ -76,6 +77,7 @@ def run( ugi: str | None, uri: str | None, credential: str | None, + prefix: str | None, ) -> None: logging.basicConfig( level=getattr(logging, log_level.upper()), @@ -89,6 +91,8 @@ def run( properties[URI] = uri if credential: properties["credential"] = credential + if prefix: + properties["prefix"] = prefix ctx.ensure_object(dict) if output == "text": diff --git a/tests/cli/test_console.py b/tests/cli/test_console.py index f4b343f683..0f896dc93f 100644 --- a/tests/cli/test_console.py +++ b/tests/cli/test_console.py @@ -1029,3 +1029,18 @@ def test_log_level_cli_overrides_env(mocker: MockFixture) -> None: mock_basicConfig.assert_called_once() call_kwargs = mock_basicConfig.call_args[1] assert call_kwargs["level"] == logging.ERROR + + +def test_prefix_cli_option_forwarded_to_catalog(mocker: MockFixture) -> None: + mock_basicConfig = mocker.patch("logging.basicConfig") + mock_catalog = MagicMock(spec=InMemoryCatalog) + mock_catalog.list_tables.return_value = [] + mock_catalog.list_namespaces.return_value = [] + mock_load_catalog = mocker.patch("pyiceberg.cli.console.load_catalog", return_value=mock_catalog) + + runner = CliRunner() + result = runner.invoke(run, ["--catalog", "rest", "--uri", "https://example.invalid", "--prefix", "v1/ws", "list"]) + + assert result.exit_code == 0 + mock_basicConfig.assert_called_once() + mock_load_catalog.assert_called_once_with("rest", uri="https://example.invalid", prefix="v1/ws")