Skip to content

Commit 172d9a7

Browse files
authored
REST: Delegate parsing to Pydantic (#1847)
# Rationale for this change Right now we deserialize the JSON into a dict, which is then passed into the Pydantic model. It is better to fully delegate this to pydantic because it is probably faster, and we can detect when models are created from json or from Python dicts. Required by #1770 This is also a recommendation by Pydantic itself: https://docs.pydantic.dev/latest/concepts/performance/#in-general-use-model_validate_json-not-model_validatejsonloads # Are these changes tested? Existing tests # Are there any user-facing changes? No <!-- In the case of user-facing changes, please add the changelog label. -->
1 parent 7a6a7c8 commit 172d9a7

File tree

1 file changed

+13
-13
lines changed

1 file changed

+13
-13
lines changed

pyiceberg/catalog/rest.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ def _fetch_access_token(self, session: Session, credential: str) -> str:
370370
except HTTPError as exc:
371371
self._handle_non_200_response(exc, {400: OAuthError, 401: OAuthError})
372372

373-
return TokenResponse(**response.json()).access_token
373+
return TokenResponse.model_validate_json(response.text).access_token
374374

375375
def _fetch_config(self) -> None:
376376
params = {}
@@ -383,7 +383,7 @@ def _fetch_config(self) -> None:
383383
response.raise_for_status()
384384
except HTTPError as exc:
385385
self._handle_non_200_response(exc, {})
386-
config_response = ConfigResponse(**response.json())
386+
config_response = ConfigResponse.model_validate_json(response.text)
387387

388388
config = config_response.defaults
389389
config.update(self.properties)
@@ -443,14 +443,14 @@ def _handle_non_200_response(self, exc: HTTPError, error_handler: Dict[int, Type
443443
try:
444444
if exception == OAuthError:
445445
# The OAuthErrorResponse has a different format
446-
error = OAuthErrorResponse(**exc.response.json())
446+
error = OAuthErrorResponse.model_validate_json(exc.response.text)
447447
response = str(error.error)
448448
if description := error.error_description:
449449
response += f": {description}"
450450
if uri := error.error_uri:
451451
response += f" ({uri})"
452452
else:
453-
error = ErrorResponse(**exc.response.json()).error
453+
error = ErrorResponse.model_validate_json(exc.response.text).error
454454
response = f"{error.type}: {error.message}"
455455
except JSONDecodeError:
456456
# In the case we don't have a proper response
@@ -588,7 +588,7 @@ def _create_table(
588588
response.raise_for_status()
589589
except HTTPError as exc:
590590
self._handle_non_200_response(exc, {409: TableAlreadyExistsError})
591-
return TableResponse(**response.json())
591+
return TableResponse.model_validate_json(response.text)
592592

593593
@retry(**_RETRY_ARGS)
594594
def create_table(
@@ -662,7 +662,7 @@ def register_table(self, identifier: Union[str, Identifier], metadata_location:
662662
except HTTPError as exc:
663663
self._handle_non_200_response(exc, {409: TableAlreadyExistsError})
664664

665-
table_response = TableResponse(**response.json())
665+
table_response = TableResponse.model_validate_json(response.text)
666666
return self._response_to_table(self.identifier_to_tuple(identifier), table_response)
667667

668668
@retry(**_RETRY_ARGS)
@@ -674,7 +674,7 @@ def list_tables(self, namespace: Union[str, Identifier]) -> List[Identifier]:
674674
response.raise_for_status()
675675
except HTTPError as exc:
676676
self._handle_non_200_response(exc, {404: NoSuchNamespaceError})
677-
return [(*table.namespace, table.name) for table in ListTablesResponse(**response.json()).identifiers]
677+
return [(*table.namespace, table.name) for table in ListTablesResponse.model_validate_json(response.text).identifiers]
678678

679679
@retry(**_RETRY_ARGS)
680680
def load_table(self, identifier: Union[str, Identifier]) -> Table:
@@ -684,7 +684,7 @@ def load_table(self, identifier: Union[str, Identifier]) -> Table:
684684
except HTTPError as exc:
685685
self._handle_non_200_response(exc, {404: NoSuchTableError})
686686

687-
table_response = TableResponse(**response.json())
687+
table_response = TableResponse.model_validate_json(response.text)
688688
return self._response_to_table(self.identifier_to_tuple(identifier), table_response)
689689

690690
@retry(**_RETRY_ARGS)
@@ -735,7 +735,7 @@ def list_views(self, namespace: Union[str, Identifier]) -> List[Identifier]:
735735
response.raise_for_status()
736736
except HTTPError as exc:
737737
self._handle_non_200_response(exc, {404: NoSuchNamespaceError})
738-
return [(*view.namespace, view.name) for view in ListViewsResponse(**response.json()).identifiers]
738+
return [(*view.namespace, view.name) for view in ListViewsResponse.model_validate_json(response.text).identifiers]
739739

740740
@retry(**_RETRY_ARGS)
741741
def commit_table(
@@ -781,7 +781,7 @@ def commit_table(
781781
504: CommitStateUnknownException,
782782
},
783783
)
784-
return CommitTableResponse(**response.json())
784+
return CommitTableResponse.model_validate_json(response.text)
785785

786786
@retry(**_RETRY_ARGS)
787787
def create_namespace(self, namespace: Union[str, Identifier], properties: Properties = EMPTY_DICT) -> None:
@@ -818,7 +818,7 @@ def list_namespaces(self, namespace: Union[str, Identifier] = ()) -> List[Identi
818818
except HTTPError as exc:
819819
self._handle_non_200_response(exc, {})
820820

821-
return ListNamespaceResponse(**response.json()).namespaces
821+
return ListNamespaceResponse.model_validate_json(response.text).namespaces
822822

823823
@retry(**_RETRY_ARGS)
824824
def load_namespace_properties(self, namespace: Union[str, Identifier]) -> Properties:
@@ -830,7 +830,7 @@ def load_namespace_properties(self, namespace: Union[str, Identifier]) -> Proper
830830
except HTTPError as exc:
831831
self._handle_non_200_response(exc, {404: NoSuchNamespaceError})
832832

833-
return NamespaceResponse(**response.json()).properties
833+
return NamespaceResponse.model_validate_json(response.text).properties
834834

835835
@retry(**_RETRY_ARGS)
836836
def update_namespace_properties(
@@ -844,7 +844,7 @@ def update_namespace_properties(
844844
response.raise_for_status()
845845
except HTTPError as exc:
846846
self._handle_non_200_response(exc, {404: NoSuchNamespaceError})
847-
parsed_response = UpdateNamespacePropertiesResponse(**response.json())
847+
parsed_response = UpdateNamespacePropertiesResponse.model_validate_json(response.text)
848848
return PropertiesUpdateSummary(
849849
removed=parsed_response.removed,
850850
updated=parsed_response.updated,

0 commit comments

Comments
 (0)