Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/connexion/exceptions.py: 54%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

81 statements  

1""" 

2This module defines Exception classes used by Connexion to generate a proper response. 

3""" 

4 

5import typing as t 

6 

7from jsonschema.exceptions import ValidationError 

8from starlette.exceptions import HTTPException 

9 

10from .problem import problem 

11 

12 

13class ConnexionException(Exception): 

14 """Base class for any exception thrown by the Connexion framework.""" 

15 

16 

17class ResolverError(LookupError, ConnexionException): 

18 """Error raised at startup when the resolver cannot find a view function for an endpoint in 

19 your specification, and no ``resolver_error`` is configured.""" 

20 

21 

22class InvalidSpecification(ValidationError, ConnexionException): 

23 """Error raised at startup when the provided specification cannot be validated.""" 

24 

25 

26class MissingMiddleware(ConnexionException): 

27 """Error raised when you're leveraging behavior that depends on a specific middleware, 

28 and that middleware is not part of your middleware stack.""" 

29 

30 

31# HTTP ERRORS 

32 

33 

34class ProblemException(HTTPException, ConnexionException): 

35 """ 

36 This exception holds arguments that are going to be passed to the 

37 `connexion.problem` function to generate a proper response. 

38 """ 

39 

40 def __init__( 

41 self, 

42 *, 

43 status=500, 

44 title=None, 

45 detail=None, 

46 type=None, 

47 instance=None, 

48 headers=None, 

49 ext=None, 

50 ): 

51 self.status = self.status_code = status 

52 self.title = title 

53 self.detail = detail 

54 self.type = type 

55 self.instance = instance 

56 self.headers = headers 

57 self.ext = ext 

58 

59 def to_problem(self): 

60 return problem( 

61 status=self.status, 

62 title=self.title, 

63 detail=self.detail, 

64 type=self.type, 

65 instance=self.instance, 

66 headers=self.headers, 

67 ext=self.ext, 

68 ) 

69 

70 

71# CLIENT ERRORS (4XX) 

72 

73 

74class ClientProblem(ProblemException): 

75 """Base exception for any 4XX error. Returns 400 by default, however 

76 :class:`BadRequestProblem` should be preferred for 400 errors.""" 

77 

78 def __init__(self, status: int = 400, title: str = None, *, detail: str = None): 

79 super().__init__(status=status, title=title, detail=detail) 

80 

81 

82class BadRequestProblem(ClientProblem): 

83 """Problem class for 400 Bad Request errors.""" 

84 

85 def __init__(self, detail=None): 

86 super().__init__(status=400, title="Bad Request", detail=detail) 

87 

88 

89class ExtraParameterProblem(BadRequestProblem): 

90 """Problem class for 400 Bad Request errors raised when extra query or form parameters are 

91 detected and ``strict_validation`` is enabled.""" 

92 

93 def __init__(self, *, param_type: str, extra_params: t.Iterable[str]): 

94 detail = f"Extra {param_type} parameter(s) {','.join(extra_params)} not in spec" 

95 super().__init__(detail=detail) 

96 

97 

98class TypeValidationError(BadRequestProblem): 

99 """Problem class for 400 Bad Request errors raised when path, query or form parameters with 

100 an incorrect type are detected.""" 

101 

102 def __init__(self, schema_type: str, parameter_type: str, parameter_name: str): 

103 detail = f"Wrong type, expected '{schema_type}' for {parameter_type} parameter '{parameter_name}'" 

104 super().__init__(detail=detail) 

105 

106 

107class Unauthorized(ClientProblem): 

108 """Problem class for 401 Unauthorized errors.""" 

109 

110 description = ( 

111 "The server could not verify that you are authorized to access" 

112 " the URL requested. You either supplied the wrong credentials" 

113 " (e.g. a bad password), or your browser doesn't understand" 

114 " how to supply the credentials required." 

115 ) 

116 

117 def __init__(self, detail: str = description): 

118 super().__init__(401, title="Unauthorized", detail=detail) 

119 

120 

121class OAuthProblem(Unauthorized): 

122 """Problem class for 401 Unauthorized errors raised when there is an issue with the received 

123 OAuth headers.""" 

124 

125 pass 

126 

127 

128class OAuthResponseProblem(OAuthProblem): 

129 """Problem class for 401 Unauthorized errors raised when improper OAuth credentials are 

130 retrieved from your OAuth server.""" 

131 

132 pass 

133 

134 

135class Forbidden(HTTPException): 

136 """Problem class for 403 Unauthorized errors.""" 

137 

138 def __init__(self, detail: t.Optional[str] = None): 

139 if detail is None: 

140 detail = ( 

141 "You don't have the permission to access the requested" 

142 " resource. It is either read-protected or not readable by the" 

143 " server." 

144 ) 

145 super().__init__(403, detail=detail) 

146 

147 

148class OAuthScopeProblem(Forbidden): 

149 """Problem class for 403 Unauthorized errors raised because of OAuth scope validation errors.""" 

150 

151 def __init__(self, token_scopes: list, required_scopes: list) -> None: 

152 self.required_scopes = required_scopes 

153 self.token_scopes = token_scopes 

154 detail = ( 

155 f"Provided token does not have the required scopes. " 

156 f"Provided: {token_scopes}; Required: {required_scopes}" 

157 ) 

158 super().__init__(detail=detail) 

159 

160 

161class UnsupportedMediaTypeProblem(ClientProblem): 

162 """Problem class for 415 Unsupported Media Type errors which are raised when Connexion 

163 receives a request with an unsupported media type header.""" 

164 

165 def __init__(self, detail: t.Optional[str] = None): 

166 super().__init__(status=415, title="Unsupported Media Type", detail=detail) 

167 

168 

169# SERVER ERRORS (5XX) 

170 

171 

172class ServerError(ProblemException): 

173 """Base exception for any 5XX error. Returns 500 by default, however 

174 :class:`InternalServerError` should be preferred for 500 errors.""" 

175 

176 def __init__( 

177 self, 

178 status: int = 500, 

179 title: t.Optional[str] = None, 

180 *, 

181 detail: t.Optional[str] = None, 

182 ): 

183 if title is None: 

184 title = "Internal Server Error" 

185 

186 super().__init__(status=status, title=title, detail=detail) 

187 

188 

189class InternalServerError(ServerError): 

190 """Problem class for 500 Internal Server errors.""" 

191 

192 def __init__(self, detail: t.Optional[str] = None): 

193 if detail is None: 

194 detail = ( 

195 "The server encountered an internal error and was unable to complete your " 

196 "request. Either the server is overloaded or there is an error in the application." 

197 ) 

198 super().__init__(status=500, title="Internal Server Error", detail=detail) 

199 

200 

201class NonConformingResponse(InternalServerError): 

202 """Problem class for 500 Internal Server errors raised because of a returned response not 

203 matching the specification if response validation is enabled.""" 

204 

205 def __init__(self, detail: t.Optional[str] = None): 

206 super().__init__(detail=detail) 

207 

208 

209class NonConformingResponseBody(NonConformingResponse): 

210 """Problem class for 500 Internal Server errors raised because of a returned response body not 

211 matching the specification if response validation is enabled.""" 

212 

213 def __init__(self, detail: t.Optional[str] = None): 

214 if detail is None: 

215 detail = "Response body does not conform to specification" 

216 

217 super().__init__(detail=detail) 

218 

219 

220class NonConformingResponseHeaders(NonConformingResponse): 

221 """Problem class for 500 Internal Server errors raised because of a returned response headers 

222 not matching the specification if response validation is enabled.""" 

223 

224 def __init__(self, detail: t.Optional[str] = None): 

225 if detail is None: 

226 detail = "Response headers do not conform to specification" 

227 

228 super().__init__(detail=detail) 

229 

230 

231class ResolverProblem(ServerError): 

232 """Problem class for 501 Not Implemented errors raised when the resolver cannot find a view 

233 function to handle the incoming request.""" 

234 

235 def __init__(self, status: int = 501, *, detail: t.Optional[str] = None): 

236 super().__init__(status=status, title="Not Implemented", detail=detail)