You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polaris.apache.org by yz...@apache.org on 2026/07/26 04:30:59 UTC

(polaris) branch main updated: Handle null/blank catalog type (#5153)

This is an automated email from the ASF dual-hosted git repository.

MonkeyCanCode pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/polaris.git


The following commit(s) were added to refs/heads/main by this push:
     new c336c27188 Handle null/blank catalog type (#5153)
c336c27188 is described below

commit c336c2718838571c54bd0019d3680528b333ed87
Author: Yong Zheng <yo...@gmail.com>
AuthorDate: Sat Jul 25 23:30:54 2026 -0500

    Handle null/blank catalog type (#5153)
---
 CHANGELOG.md                                      |  1 +
 client/python/apache_polaris/cli/command/setup.py |  4 ++--
 client/python/tests/test_setup_command.py         | 28 +++++++++++++++++++++++
 3 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 22f12585d8..a42de0cdc6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -101,6 +101,7 @@ request adding CHANGELOG notes for breaking (!) changes and possibly other secti
 - `ManifestFileCleanupTaskHandler` now handles Iceberg v2 delete manifests in addition to data manifests. Previously, `DROP TABLE PURGE` on a v2 table that had been updated via merge-on-read DML left position-delete files and their manifests as orphans in object storage; the cleanup task failed silently because `ManifestFiles.read()` rejects delete manifests.
 - OPA authorizer now includes the realm identifier in the authorization context sent to OPA (`input.context.realm`). This ensures OPA policies can enforce tenant isolation across realms, preventing potential collisions if identical principal or resource names exist in different realms.
 - Management API delete operations for principals, principal roles, catalog roles, and catalogs now return error messages that match the actual failure reason (for example, concurrent modification no longer reports a misleading protected-entity message).
+- Python CLI `setup apply` now defaults to an `INTERNAL` catalog type when the `type` field is left blank or null in the setup config, instead of crashing with `AttributeError`
 
 ## [1.6.0]
 
diff --git a/client/python/apache_polaris/cli/command/setup.py b/client/python/apache_polaris/cli/command/setup.py
index 1f0831995d..f9b32fa4d7 100644
--- a/client/python/apache_polaris/cli/command/setup.py
+++ b/client/python/apache_polaris/cli/command/setup.py
@@ -891,8 +891,8 @@ class SetupCommand(Command):
                     command_args = {
                         "catalogs_subcommand": Subcommands.CREATE,
                         "catalog_name": catalog_name,
-                        "catalog_type": catalog_data.get(
-                            "type", CatalogType.INTERNAL.value
+                        "catalog_type": (
+                            catalog_data.get("type") or CatalogType.INTERNAL.value
                         ).lower(),
                     }
                     command_args.update(self._map_storage_properties(catalog_data))
diff --git a/client/python/tests/test_setup_command.py b/client/python/tests/test_setup_command.py
index d7f075b418..0e031753cd 100644
--- a/client/python/tests/test_setup_command.py
+++ b/client/python/tests/test_setup_command.py
@@ -290,3 +290,31 @@ class TestSetupCommand(CLITestBase):
         mock_client.list_catalogs.assert_called()
         mock_client.list_catalog_roles.assert_called_with("my_catalog")
         mock_client.get_catalog.assert_called_with("my_catalog")
+
+    @patch("apache_polaris.cli.command.setup.os.path.isfile")
+    def test_setup_apply_treats_null_type_as_internal(
+        self, mock_isfile: MagicMock
+    ) -> None:
+        mock_client = self.build_mock_client()
+        mock_isfile.return_value = True
+        mock_client.list_principals.side_effect = RuntimeError("listing unavailable")
+        setup_yaml = (
+            "catalogs:\n"
+            "  - name: my_catalog\n"
+            "    type: null\n"
+            "    storage_type: file\n"
+            "    default_base_location: file:///path"
+        )
+
+        with (
+            patch(
+                "apache_polaris.cli.command.setup.open",
+                mock_open(read_data=setup_yaml),
+            ),
+        ):
+            self.mock_execute(
+                mock_client,
+                ["setup", "apply", "config.yaml"]
+            )
+        call_args = mock_client.create_catalog.call_args[0][0]
+        self.assertEqual(call_args.catalog.type, "INTERNAL")