2626import pydantic
2727from pydantic import PrivateAttr
2828
29- from ._types import (
30- Query ,
31- ModelT ,
32- Timeout ,
33- Transport ,
34- ProxiesTypes ,
35- RequestOptions ,
36- FinalRequestOptions ,
37- )
38- from ._models import BaseModel , NoneModel , GenericModel
29+ from ._types import Query , ModelT , Timeout , Transport , ProxiesTypes , RequestOptions
30+ from ._models import BaseModel , NoneModel , GenericModel , FinalRequestOptions
3931from .exceptions import (
4032 APITimeoutError ,
4133 APIConnectionError ,
@@ -65,14 +57,9 @@ class BasePage(GenericModel, Generic[ModelT, PageParamsT]):
6557 _model : Type [ModelT ] = PrivateAttr ()
6658
6759 def has_next_page (self ) -> bool :
68- ...
60+ return self . next_page_params () is not None
6961
7062 def next_page_params (self ) -> Optional [PageParamsT ]:
71- if self .has_next_page ():
72- return self ._next_page_params ()
73- return None
74-
75- def _next_page_params (self ) -> PageParamsT :
7663 ...
7764
7865 def _get_page_items (self ) -> Iterable [ModelT ]:
@@ -115,15 +102,14 @@ def iter_pages(self: SyncPageT) -> Iterator[SyncPageT]:
115102 return
116103
117104 def get_next_page (self : SyncPageT ) -> SyncPageT :
118- page_params = self ._next_page_params ()
119- params = self ._options .get ("params" , {}) or {}
120- options : Mapping [str , object ] = {** self ._options , "params" : {** params , ** page_params }}
121- return self ._client .request_api_list (
122- self ._model ,
123- page = self .__class__ ,
124- # TODO: validate that what we pass is actually valid at runtime
125- options = options , # type: ignore
126- )
105+ next_params = self .next_page_params ()
106+ if not next_params :
107+ raise StopIteration ()
108+
109+ options = self ._options .copy ()
110+ options .params = {** options .params , ** next_params }
111+
112+ return self ._client .request_api_list (self ._model , page = self .__class__ , options = options )
127113
128114
129115class AsyncPaginator (Generic [ModelT , AsyncPageT ]):
@@ -189,15 +175,13 @@ async def iter_pages(self: AsyncPageT) -> AsyncIterator[AsyncPageT]:
189175 return
190176
191177 async def get_next_page (self : AsyncPageT ) -> AsyncPageT :
192- page_params = self ._next_page_params ()
193- params = self ._options .get ("params" , {}) or {}
194- options : Mapping [str , object ] = {** self ._options , "params" : {** params , ** page_params }}
195- return await self ._client .request_api_list (
196- self ._model ,
197- page = self .__class__ ,
198- # TODO: validate that what we pass is actually valid at runtime
199- options = options , # type: ignore
200- )
178+ next_params = self .next_page_params ()
179+ if not next_params :
180+ raise StopIteration ()
181+
182+ options = self ._options .copy ()
183+ options .params = {** options .params , ** next_params }
184+ return await self ._client .request_api_list (self ._model , page = self .__class__ , options = options )
201185
202186
203187class BaseClient :
@@ -226,18 +210,13 @@ def remaining_retries(
226210 remaining_retries : Optional [int ],
227211 options : FinalRequestOptions ,
228212 ) -> int :
229- return remaining_retries if remaining_retries is not None else options .get ( "max_retries" , self .max_retries )
213+ return remaining_retries if remaining_retries is not None else options .get_max_retries ( self .max_retries )
230214
231215 def prepare_request_args (
232216 self ,
233217 options : FinalRequestOptions ,
234218 ) -> Dict [str , Any ]:
235- headers = {** self .default_headers (), ** options .get ("headers" , {})}
236- req_args : Dict [str , Any ] = {** options , "headers" : headers , "timeout" : options .get ("timeout" , self .timeout )}
237-
238- # ensure we only returned expected keyword arguments to `build_request()` to avoid a `TypeError: build_request()
239- # got an unexpected keyword argument 'max_retries'`.
240- return {k : v for k , v in req_args .items () if k in [p .name for p in BUILD_REQUEST_PARAMS ]}
219+ return options .to_request_args (default_headers = self .default_headers (), default_timeout = self .timeout )
241220
242221 def process_response (
243222 self , model : Type [ResponseT ], options : FinalRequestOptions , response : httpx .Response
@@ -282,7 +261,7 @@ def calculate_retry_timeout(
282261 options : FinalRequestOptions ,
283262 response_headers : Optional [httpx .Headers ] = None ,
284263 ) -> float :
285- max_retries = options .get ( "max_retries" , self .max_retries )
264+ max_retries = options .get_max_retries ( self .max_retries )
286265 try :
287266 # About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
288267 #
@@ -416,7 +395,7 @@ def request_api_list(
416395 self ,
417396 model : Type [ModelT ],
418397 page : Type [SyncPageT ],
419- options : FinalRequestOptions = {} ,
398+ options : FinalRequestOptions ,
420399 ) -> SyncPageT :
421400 resp = self .request (page , options )
422401 resp ._set_private_attributes ( # pyright: ignore[reportPrivateUsage]
@@ -431,10 +410,10 @@ def get(
431410 path : str ,
432411 * ,
433412 model : Type [ResponseT ],
434- query : Query | None = None ,
413+ query : Query = {} ,
435414 options : RequestOptions = {},
436415 ) -> ResponseT :
437- opts = FinalRequestOptions (method = "get" , url = path , params = query , ** options ) # type: ignore[misc]
416+ opts = FinalRequestOptions (method = "get" , url = path , params = query , ** options )
438417 return self .request (model , opts )
439418
440419 def post (
@@ -445,7 +424,7 @@ def post(
445424 body : Query | None = None ,
446425 options : RequestOptions = {},
447426 ) -> ResponseT :
448- opts = FinalRequestOptions (method = "post" , url = path , json = body , ** options ) # type: ignore[misc]
427+ opts = FinalRequestOptions (method = "post" , url = path , json_data = body , ** options )
449428 return self .request (model , opts )
450429
451430 def patch (
@@ -456,7 +435,7 @@ def patch(
456435 body : Query | None = None ,
457436 options : RequestOptions = {},
458437 ) -> ResponseT :
459- opts = FinalRequestOptions (method = "patch" , url = path , json = body , ** options ) # type: ignore[misc]
438+ opts = FinalRequestOptions (method = "patch" , url = path , json_data = body , ** options )
460439 return self .request (model , opts )
461440
462441 def put (
@@ -467,7 +446,7 @@ def put(
467446 body : Query | None = None ,
468447 options : RequestOptions = {},
469448 ) -> ResponseT :
470- opts = FinalRequestOptions (method = "put" , url = path , json = body , ** options ) # type: ignore[misc]
449+ opts = FinalRequestOptions (method = "put" , url = path , json_data = body , ** options )
471450 return self .request (model , opts )
472451
473452 def delete (
@@ -478,19 +457,19 @@ def delete(
478457 body : Query | None = None ,
479458 options : RequestOptions = {},
480459 ) -> ResponseT :
481- opts = FinalRequestOptions (method = "delete" , url = path , json = body , ** options ) # type: ignore[misc]
460+ opts = FinalRequestOptions (method = "delete" , url = path , json_data = body , ** options )
482461 return self .request (model , opts )
483462
484463 def get_api_list (
485464 self ,
486465 path : str ,
487466 * ,
488- query : Query | None = None ,
489467 model : Type [ModelT ],
490468 page : Type [SyncPageT ],
469+ query : Query = {},
491470 options : RequestOptions = {},
492471 ) -> SyncPageT :
493- opts = FinalRequestOptions (method = "get" , url = path , params = query , ** options ) # type: ignore[misc]
472+ opts = FinalRequestOptions (method = "get" , url = path , params = query , ** options )
494473 return self .request_api_list (model , page , opts )
495474
496475
@@ -584,7 +563,7 @@ def request_api_list(
584563 self ,
585564 model : Type [ModelT ],
586565 page : Type [AsyncPageT ],
587- options : FinalRequestOptions = {} ,
566+ options : FinalRequestOptions ,
588567 ) -> AsyncPaginator [ModelT , AsyncPageT ]:
589568 return AsyncPaginator (client = self , options = options , page_cls = page , model = model )
590569
@@ -593,10 +572,10 @@ async def get(
593572 path : str ,
594573 * ,
595574 model : Type [ResponseT ],
596- query : Query | None = None ,
575+ query : Query = {} ,
597576 options : RequestOptions = {},
598577 ) -> ResponseT :
599- opts = FinalRequestOptions (method = "get" , url = path , params = query , ** options ) # type: ignore[misc]
578+ opts = FinalRequestOptions (method = "get" , url = path , params = query , ** options )
600579 return await self .request (model , opts )
601580
602581 async def post (
@@ -607,7 +586,7 @@ async def post(
607586 body : Query | None = None ,
608587 options : RequestOptions = {},
609588 ) -> ResponseT :
610- opts = FinalRequestOptions (method = "post" , url = path , json = body , ** options ) # type: ignore[misc]
589+ opts = FinalRequestOptions (method = "post" , url = path , json_data = body , ** options )
611590 return await self .request (model , opts )
612591
613592 async def patch (
@@ -618,7 +597,7 @@ async def patch(
618597 body : Query | None = None ,
619598 options : RequestOptions = {},
620599 ) -> ResponseT :
621- opts = FinalRequestOptions (method = "patch" , url = path , json = body , ** options ) # type: ignore[misc]
600+ opts = FinalRequestOptions (method = "patch" , url = path , json_data = body , ** options )
622601 return await self .request (model , opts )
623602
624603 async def put (
@@ -629,7 +608,7 @@ async def put(
629608 body : Query | None = None ,
630609 options : RequestOptions = {},
631610 ) -> ResponseT :
632- opts = FinalRequestOptions (method = "put" , url = path , json = body , ** options ) # type: ignore[misc]
611+ opts = FinalRequestOptions (method = "put" , url = path , json_data = body , ** options )
633612 return await self .request (model , opts )
634613
635614 async def delete (
@@ -640,19 +619,19 @@ async def delete(
640619 body : Query | None = None ,
641620 options : RequestOptions = {},
642621 ) -> ResponseT :
643- opts = FinalRequestOptions (method = "delete" , url = path , json = body , ** options ) # type: ignore[misc]
622+ opts = FinalRequestOptions (method = "delete" , url = path , json_data = body , ** options )
644623 return await self .request (model , opts )
645624
646625 def get_api_list (
647626 self ,
648627 path : str ,
649628 * ,
650- query : Query | None = None ,
651629 model : Type [ModelT ],
652630 page : Type [AsyncPageT ],
631+ query : Query = {},
653632 options : RequestOptions = {},
654633 ) -> AsyncPaginator [ModelT , AsyncPageT ]:
655- opts = FinalRequestOptions (method = "get" , url = path , params = query , ** options ) # type: ignore[misc]
634+ opts = FinalRequestOptions (method = "get" , url = path , params = query , ** options )
656635 return self .request_api_list (model , page , opts )
657636
658637
@@ -662,10 +641,14 @@ def make_request_options(
662641 timeout : float | Timeout | None = None ,
663642) -> RequestOptions :
664643 """Create a dict of type RequestOptions without keys of None values."""
665- d = {
666- "headers" : headers ,
667- "max_retries" : max_retries ,
668- "timeout" : timeout ,
669- }
670- filtered = {k : v for k , v in d .items () if v is not None }
671- return RequestOptions (** filtered ) # type: ignore
644+ options : RequestOptions = {}
645+ if headers is not None :
646+ options ["headers" ] = headers
647+
648+ if max_retries is not None :
649+ options ["max_retries" ] = max_retries
650+
651+ if timeout is not None :
652+ options ["timeout" ] = timeout
653+
654+ return options
0 commit comments