diff --git a/pyiceberg/catalog/__init__.py b/pyiceberg/catalog/__init__.py index b4ca9a2e5f..8628f6b64a 100644 --- a/pyiceberg/catalog/__init__.py +++ b/pyiceberg/catalog/__init__.py @@ -218,6 +218,14 @@ def infer_catalog_type(name: str, catalog_properties: RecursiveDict) -> CatalogT ) +def _check_required_catalog_properties(name: str, catalog_type: CatalogType, conf: RecursiveDict) -> None: + """Validate required properties for explicitly selected catalog types.""" + if catalog_type in {CatalogType.REST, CatalogType.HIVE, CatalogType.SQL} and URI not in conf: + raise ValueError( + f"URI missing, please provide using --uri, the config or environment variable PYICEBERG_CATALOG__{name.upper()}__URI" + ) + + def load_catalog(name: str | None = None, **properties: str | None) -> Catalog: """Load the catalog based on the properties. @@ -263,6 +271,7 @@ def load_catalog(name: str | None = None, **properties: str | None) -> Catalog: catalog_type = infer_catalog_type(name, conf) if catalog_type: + _check_required_catalog_properties(name, catalog_type, conf) return AVAILABLE_CATALOGS[catalog_type](name, cast(dict[str, str], conf)) raise ValueError(f"Could not initialize catalog with the following properties: {properties}") diff --git a/tests/cli/test_console.py b/tests/cli/test_console.py index 0f896dc93f..81165e8b40 100644 --- a/tests/cli/test_console.py +++ b/tests/cli/test_console.py @@ -48,6 +48,19 @@ def test_missing_uri(mocker: MockFixture, empty_home_dir_path: str) -> None: assert result.output == "Could not initialize catalog with the following properties: {}\n" +def test_hive_catalog_missing_uri_shows_helpful_error(mocker: MockFixture) -> None: + mock_env_config = mocker.MagicMock() + mock_env_config.get_catalog_config.return_value = {"type": "hive"} + mocker.patch("pyiceberg.catalog._ENV_CONFIG", mock_env_config) + + runner = CliRunner() + result = runner.invoke(run, ["--catalog", "my_hive_catalog", "list"]) + + assert result.exit_code == 1 + assert "URI missing, please provide using --uri" in result.output + assert "'uri'" not in result.output + + @pytest.fixture(autouse=True) def env_vars(mocker: MockFixture) -> None: mocker.patch.dict(os.environ, MOCK_ENVIRONMENT)