From 9c68e3993e7360e1025ce433056f265b34121dde Mon Sep 17 00:00:00 2001 From: Kevin Liu Date: Sat, 24 Oct 2026 19:08:34 -0700 Subject: [PATCH] Require metadata-location in REST view responses The REST spec marks metadata-location as required in LoadViewResult, and Java's LoadViewResponseParser rejects responses without it. Make ViewResponse.metadata_location required to match. Behavior change: create_view, load_view, and register_view now raise a pydantic ValidationError for non-compliant servers that omit metadata-location, instead of silently accepting the response. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- pyiceberg/catalog/rest/__init__.py | 2 +- tests/catalog/test_rest.py | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/pyiceberg/catalog/rest/__init__.py b/pyiceberg/catalog/rest/__init__.py index 2b8b4496f8..29facfea2a 100644 --- a/pyiceberg/catalog/rest/__init__.py +++ b/pyiceberg/catalog/rest/__init__.py @@ -361,7 +361,7 @@ class LoadCredentialsResponse(IcebergBaseModel): class ViewResponse(IcebergBaseModel): - metadata_location: str | None = Field(alias="metadata-location", default=None) + metadata_location: str = Field(..., alias="metadata-location") metadata: ViewMetadata config: Properties = Field(default_factory=dict) diff --git a/tests/catalog/test_rest.py b/tests/catalog/test_rest.py index 4877ee2f73..690ee2b785 100644 --- a/tests/catalog/test_rest.py +++ b/tests/catalog/test_rest.py @@ -26,6 +26,7 @@ from urllib.parse import parse_qs, urlsplit import pytest +from pydantic import ValidationError from requests import Request from requests.adapters import HTTPAdapter from requests.exceptions import HTTPError @@ -1851,6 +1852,19 @@ def test_load_view_200(rest_mock: Mocker, example_view_metadata_rest_json: dict[ assert actual.config == example_view_metadata_rest_json["config"] +def test_load_view_missing_metadata_location(rest_mock: Mocker, example_view_metadata_rest_json: dict[str, Any]) -> None: + response = {k: v for k, v in example_view_metadata_rest_json.items() if k != "metadata-location"} + rest_mock.get( + f"{TEST_URI}v1/namespaces/fokko/views/view", + json=response, + status_code=200, + request_headers=TEST_HEADERS, + ) + catalog = RestCatalog("rest", uri=TEST_URI, token=TEST_TOKEN) + with pytest.raises(ValidationError, match="metadata-location"): + catalog.load_view(("fokko", "view")) + + def test_load_view_404(rest_mock: Mocker) -> None: rest_mock.get( f"{TEST_URI}v1/namespaces/fokko/views/non_existent_view",