-
Notifications
You must be signed in to change notification settings - Fork 480
Expand file tree
/
Copy pathresponse.py
More file actions
115 lines (99 loc) · 4.02 KB
/
response.py
File metadata and controls
115 lines (99 loc) · 4.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from json import JSONDecodeError
from typing import Literal
from pydantic import Field, ValidationError
from requests import HTTPError
from pyiceberg.exceptions import (
AuthorizationExpiredError,
BadRequestError,
ForbiddenError,
OAuthError,
RESTError,
ServerError,
ServiceUnavailableError,
UnauthorizedError,
)
from pyiceberg.typedef import IcebergBaseModel
class TokenResponse(IcebergBaseModel):
access_token: str = Field()
token_type: str = Field()
expires_in: int | None = Field(default=None)
issued_token_type: str | None = Field(default=None)
refresh_token: str | None = Field(default=None)
scope: str | None = Field(default=None)
class ErrorResponseMessage(IcebergBaseModel):
message: str = Field()
type: str = Field()
code: int = Field()
class ErrorResponse(IcebergBaseModel):
error: ErrorResponseMessage = Field()
class OAuthErrorResponse(IcebergBaseModel):
error: Literal[
"invalid_request", "invalid_client", "invalid_grant", "unauthorized_client", "unsupported_grant_type", "invalid_scope"
]
error_description: str | None = None
error_uri: str | None = None
def _handle_non_200_response(exc: HTTPError, error_handler: dict[int, type[Exception]]) -> None:
exception: type[Exception]
if exc.response is None:
raise ValueError("Did not receive a response")
code = exc.response.status_code
if code in error_handler:
exception = error_handler[code]
elif code == 400:
exception = BadRequestError
elif code == 401:
exception = UnauthorizedError
elif code == 403:
exception = ForbiddenError
elif code == 422:
exception = RESTError
elif code == 419:
exception = AuthorizationExpiredError
elif code == 501:
exception = NotImplementedError
elif code == 503:
exception = ServiceUnavailableError
elif 500 <= code < 600:
exception = ServerError
else:
exception = RESTError
try:
if exception == OAuthError:
# The OAuthErrorResponse has a different format
error = OAuthErrorResponse.model_validate_json(exc.response.text)
response = str(error.error)
if description := error.error_description:
response += f": {description}"
if uri := error.error_uri:
response += f" ({uri})"
else:
# Handle empty response bodies (Specifically HEAD requests via exist requests)
if not exc.response.text:
response = f"{exception.__name__}: {exc.response.reason}"
else:
error = ErrorResponse.model_validate_json(exc.response.text).error
response = f"{error.type}: {error.message}"
except JSONDecodeError:
# In the case we don't have a proper response
response = f"RESTError {exc.response.status_code}: Could not decode json payload: {exc.response.text}"
except ValidationError as e:
# In the case we don't have a proper response
errs = ", ".join(err["msg"] for err in e.errors())
response = f"RESTError {exc.response.status_code}: Received unexpected JSON Payload: {exc.response.text}, errors: {errs}"
raise exception(response) from exc