11"""Client for minFraud Score, Insights, and Factors."""
22
3+ from __future__ import annotations
4+
35import json
4- from collections .abc import Sequence
56from functools import partial
6- from typing import Any , Callable , Optional , Union , cast
7+ from typing import TYPE_CHECKING , Any , Callable , cast
78
89import aiohttp
910import aiohttp .http
1011import requests
1112import requests .utils
12- from requests .models import Response
1313
1414from .errors import (
1515 AuthenticationError ,
2323from .request import prepare_report , prepare_transaction
2424from .version import __version__
2525
26+ if TYPE_CHECKING :
27+ import sys
28+ import types
29+ from collections .abc import Sequence
30+
31+ from requests .models import Response
32+
33+ if sys .version_info >= (3 , 11 ):
34+ from typing import Self
35+ else :
36+ from typing_extensions import Self
37+
2638_AIOHTTP_UA = f"minFraud-API/{ __version__ } { aiohttp .http .SERVER_SOFTWARE } "
2739
2840_REQUEST_UA = f"minFraud-API/{ __version__ } { requests .utils .default_user_agent ()} "
@@ -68,32 +80,35 @@ def _handle_success(
6880 raw_body : str ,
6981 uri : str ,
7082 model_class : Callable ,
71- ) -> Union [ Score , Factors , Insights ] :
83+ ) -> Score | Factors | Insights :
7284 """Handle successful response."""
7385 try :
7486 decoded_body = json .loads (raw_body )
7587 except ValueError as ex :
76- raise MinFraudError (
88+ msg = (
7789 "Received a 200 response but could not decode the "
78- f"response as JSON: { raw_body } " ,
90+ f"response as JSON: { raw_body } "
91+ )
92+ raise MinFraudError (
93+ msg ,
7994 200 ,
8095 uri ,
8196 ) from ex
82- return model_class (** decoded_body ) # type: ignore
97+ return model_class (** decoded_body )
8398
8499 def _exception_for_error (
85100 self ,
86101 status : int ,
87- content_type : Optional [ str ] ,
102+ content_type : str | None ,
88103 raw_body : str ,
89104 uri : str ,
90- ) -> Union [
91- AuthenticationError ,
92- InsufficientFundsError ,
93- InvalidRequestError ,
94- HTTPError ,
95- PermissionRequiredError ,
96- ] :
105+ ) -> (
106+ AuthenticationError
107+ | InsufficientFundsError
108+ | InvalidRequestError
109+ | HTTPError
110+ | PermissionRequiredError
111+ ) :
97112 """Return the exception for the error responses."""
98113 if 400 <= status < 500 :
99114 return self ._exception_for_4xx_status (status , content_type , raw_body , uri )
@@ -104,16 +119,16 @@ def _exception_for_error(
104119 def _exception_for_4xx_status (
105120 self ,
106121 status : int ,
107- content_type : Optional [ str ] ,
122+ content_type : str | None ,
108123 raw_body : str ,
109124 uri : str ,
110- ) -> Union [
111- AuthenticationError ,
112- InsufficientFundsError ,
113- InvalidRequestError ,
114- HTTPError ,
115- PermissionRequiredError ,
116- ] :
125+ ) -> (
126+ AuthenticationError
127+ | InsufficientFundsError
128+ | InvalidRequestError
129+ | HTTPError
130+ | PermissionRequiredError
131+ ) :
117132 """Return exception for error responses with 4xx status codes."""
118133 if not raw_body :
119134 return HTTPError (
@@ -161,12 +176,12 @@ def _exception_for_web_service_error(
161176 code : str ,
162177 status : int ,
163178 uri : str ,
164- ) -> Union [
165- InvalidRequestError ,
166- AuthenticationError ,
167- PermissionRequiredError ,
168- InsufficientFundsError ,
169- ] :
179+ ) -> (
180+ InvalidRequestError
181+ | AuthenticationError
182+ | PermissionRequiredError
183+ | InsufficientFundsError
184+ ) :
170185 """Return exception for error responses with the JSON body."""
171186 if code in (
172187 "ACCOUNT_ID_REQUIRED" ,
@@ -185,7 +200,7 @@ def _exception_for_web_service_error(
185200 @staticmethod
186201 def _exception_for_5xx_status (
187202 status : int ,
188- raw_body : Optional [ str ] ,
203+ raw_body : str | None ,
189204 uri : str ,
190205 ) -> HTTPError :
191206 """Return exception for error response with 5xx status codes."""
@@ -199,7 +214,7 @@ def _exception_for_5xx_status(
199214 @staticmethod
200215 def _exception_for_unexpected_status (
201216 status : int ,
202- raw_body : Optional [ str ] ,
217+ raw_body : str | None ,
203218 uri : str ,
204219 ) -> HTTPError :
205220 """Return exception for responses with unexpected status codes."""
@@ -215,7 +230,7 @@ class AsyncClient(BaseClient):
215230 """Async client for accessing the minFraud web services."""
216231
217232 _existing_session : aiohttp .ClientSession
218- _proxy : Optional [ str ]
233+ _proxy : str | None
219234
220235 def __init__ (
221236 self ,
@@ -224,7 +239,7 @@ def __init__(
224239 host : str = "minfraud.maxmind.com" ,
225240 locales : Sequence [str ] = ("en" ,),
226241 timeout : float = 60 ,
227- proxy : Optional [ str ] = None ,
242+ proxy : str | None = None ,
228243 ) -> None :
229244 """Construct AsyncClient.
230245
@@ -368,7 +383,7 @@ async def score(
368383
369384 async def report (
370385 self ,
371- report : dict [str , Optional [ str ] ],
386+ report : dict [str , str | None ],
372387 validate : bool = True ,
373388 ) -> None :
374389 """Send a transaction report to the Report Transaction endpoint.
@@ -405,7 +420,7 @@ async def _response_for(
405420 request : dict [str , Any ],
406421 validate : bool ,
407422 hash_email : bool ,
408- ) -> Union [ Score , Factors , Insights ] :
423+ ) -> Score | Factors | Insights :
409424 """Send request and create response object."""
410425 prepared_request = prepare_transaction (request , validate , hash_email )
411426 async with await self ._do_request (uri , prepared_request ) as response :
@@ -443,17 +458,22 @@ async def close(self) -> None:
443458 if hasattr (self , "_existing_session" ):
444459 await self ._existing_session .close ()
445460
446- async def __aenter__ (self ) -> "AsyncClient" :
461+ async def __aenter__ (self ) -> Self :
447462 return self
448463
449- async def __aexit__ (self , exc_type : None , exc_value : None , traceback : None ) -> None :
464+ async def __aexit__ (
465+ self ,
466+ exc_type : type [BaseException ] | None ,
467+ exc_value : BaseException | None ,
468+ traceback : types .TracebackType | None ,
469+ ) -> None :
450470 await self .close ()
451471
452472
453473class Client (BaseClient ):
454474 """Synchronous client for accessing the minFraud web services."""
455475
456- _proxies : Optional [ dict [str , str ]]
476+ _proxies : dict [str , str ] | None
457477 _session : requests .Session
458478
459479 def __init__ (
@@ -463,7 +483,7 @@ def __init__(
463483 host : str = "minfraud.maxmind.com" ,
464484 locales : Sequence [str ] = ("en" ,),
465485 timeout : float = 60 ,
466- proxy : Optional [ str ] = None ,
486+ proxy : str | None = None ,
467487 ) -> None :
468488 """Construct Client.
469489
@@ -619,7 +639,7 @@ def score(
619639 ),
620640 )
621641
622- def report (self , report : dict [str , Optional [ str ] ], validate : bool = True ) -> None :
642+ def report (self , report : dict [str , str | None ], validate : bool = True ) -> None :
623643 """Send a transaction report to the Report Transaction endpoint.
624644
625645 :param report: A dictionary containing the transaction report to be sent
@@ -654,7 +674,7 @@ def _response_for(
654674 request : dict [str , Any ],
655675 validate : bool ,
656676 hash_email : bool ,
657- ) -> Union [ Score , Factors , Insights ] :
677+ ) -> Score | Factors | Insights :
658678 """Send request and create response object."""
659679 prepared_request = prepare_transaction (request , validate , hash_email )
660680
@@ -681,8 +701,13 @@ def close(self) -> None:
681701 """
682702 self ._session .close ()
683703
684- def __enter__ (self ) -> "Client" :
704+ def __enter__ (self ) -> Self :
685705 return self
686706
687- def __exit__ (self , exc_type : None , exc_value : None , traceback : None ) -> None :
707+ def __exit__ (
708+ self ,
709+ exc_type : type [BaseException ] | None ,
710+ exc_value : BaseException | None ,
711+ traceback : types .TracebackType | None ,
712+ ) -> None :
688713 self .close ()
0 commit comments