File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 11from .errors import HTTPError , RateLimitError , ShadeError
2+ from .errors import (
3+ AuthenticationError ,
4+ InvalidRequestError ,
5+ NetworkError ,
6+ NotFoundError ,
7+ ShadeError ,
8+ )
29from .gateway import Gateway
310from .http import AsyncHTTPClient , SyncHTTPClient
411
1118 "ShadeError" ,
1219 "HTTPError" ,
1320 "RateLimitError" ,
14- ]
21+ ]
22+ "AuthenticationError" ,
23+ "Gateway" ,
24+ "InvalidRequestError" ,
25+ "NetworkError" ,
26+ "NotFoundError" ,
27+ "ShadeError" ,
28+ ]
Original file line number Diff line number Diff line change @@ -39,4 +39,35 @@ def __str__(self) -> str: # pragma: no cover
3939 base = super ().__str__ ()
4040 if self .retry_after is not None :
4141 return f"{ base } (retry after { self .retry_after } s)"
42- return base
42+ return base
43+ def __init__ (
44+ self ,
45+ message : str ,
46+ status_code : Optional [int ] = None ,
47+ response_body : Optional [str ] = None ,
48+ ) -> None :
49+ self .message = message
50+ self .status_code = status_code
51+ self .response_body = response_body
52+ super ().__init__ (message )
53+
54+ def __str__ (self ) -> str :
55+ if self .status_code is None :
56+ return self .message
57+ return f"{ self .message } (status code: { self .status_code } )"
58+
59+
60+ class AuthenticationError (ShadeError ):
61+ """Raised when authentication fails or credentials are invalid."""
62+
63+
64+ class InvalidRequestError (ShadeError ):
65+ """Raised when a request is malformed or rejected by validation."""
66+
67+
68+ class NotFoundError (ShadeError ):
69+ """Raised when an API resource cannot be found."""
70+
71+
72+ class NetworkError (ShadeError ):
73+ """Raised when the SDK cannot complete a network request."""
Original file line number Diff line number Diff line change 1+ import shade
2+ from shade import (
3+ AuthenticationError ,
4+ InvalidRequestError ,
5+ NetworkError ,
6+ NotFoundError ,
7+ ShadeError ,
8+ )
9+
10+
11+ def test_shade_error_can_be_raised_standalone ():
12+ error = ShadeError ("contract rejected payment" )
13+
14+ assert str (error ) == "contract rejected payment"
15+ assert error .message == "contract rejected payment"
16+ assert error .status_code is None
17+ assert error .response_body is None
18+
19+
20+ def test_shade_error_includes_http_context ():
21+ error = ShadeError (
22+ "invalid request" ,
23+ status_code = 422 ,
24+ response_body = '{"error":"missing amount"}' ,
25+ )
26+
27+ assert str (error ) == "invalid request (status code: 422)"
28+ assert error .status_code == 422
29+ assert error .response_body == '{"error":"missing amount"}'
30+
31+
32+ def test_specific_errors_inherit_from_shade_error ():
33+ for error_type in (
34+ AuthenticationError ,
35+ InvalidRequestError ,
36+ NetworkError ,
37+ NotFoundError ,
38+ ):
39+ error = error_type ("request failed" , status_code = 400 , response_body = "raw" )
40+
41+ assert isinstance (error , ShadeError )
42+ assert str (error ) == "request failed (status code: 400)"
43+ assert error .response_body == "raw"
44+
45+
46+ def test_package_root_exports_error_classes ():
47+ assert shade .ShadeError is ShadeError
48+ assert shade .AuthenticationError is AuthenticationError
49+ assert shade .InvalidRequestError is InvalidRequestError
50+ assert shade .NetworkError is NetworkError
51+ assert shade .NotFoundError is NotFoundError
You can’t perform that action at this time.
0 commit comments