1+ from __future__ import annotations
12import inspect
23from pyramid .config import PHASE1_CONFIG
34from pyramid .exceptions import ConfigurationError
5+ import typing as t
46from zope .interface import (
57 Attribute ,
68 Interface ,
911 implementer ,
1012)
1113
14+ if t .TYPE_CHECKING : # pragma: no cover
15+ from collections .abc import Callable
16+ from pyramid .config import Configurator
17+ from pyramid .request import Request
18+ from pyramid .response import Response
19+ from pyramid .router import Router
20+
1221
1322class IRetryableError (Interface ):
1423 """
@@ -55,7 +64,9 @@ class BeforeRetry(object):
5564
5665 """
5766
58- def __init__ (self , request , exception , response = None ):
67+ def __init__ (
68+ self , request : Request , exception : Exception , response : Response = None
69+ ):
5970 self .request = request
6071 self .environ = request .environ
6172 self .exception = exception
@@ -67,7 +78,10 @@ class RetryableException(Exception):
6778 """A retryable exception should be raised when an error occurs."""
6879
6980
70- def RetryableExecutionPolicy (attempts = 3 , activate_hook = None ):
81+ def RetryableExecutionPolicy (
82+ attempts : int = 3 ,
83+ activate_hook : Callable [..., int | None ] | None = None ,
84+ ) -> Callable [..., Response ]:
7185 """
7286 Create a :term:`execution policy` that catches any
7387 :term:`retryable error` and sends it through the pipeline again up to
@@ -81,7 +95,7 @@ def RetryableExecutionPolicy(attempts=3, activate_hook=None):
8195 """
8296 assert attempts > 0
8397
84- def retry_policy (environ , router ) :
98+ def retry_policy (environ : dict [ str , t . Any ], router : Router ) -> Response :
8599 # make the original request
86100 request_ctx = router .request_context (environ )
87101 request = request_ctx .begin ()
@@ -164,7 +178,7 @@ def retry_policy(environ, router):
164178 return retry_policy
165179
166180
167- def mark_error_retryable (error ) :
181+ def mark_error_retryable (error : t . Any ) -> None :
168182 """
169183 Mark an exception instance or type as retryable. If this exception
170184 is caught by ``pyramid_retry`` then it may retry the request.
@@ -173,14 +187,14 @@ def mark_error_retryable(error):
173187 if isinstance (error , Exception ):
174188 alsoProvides (error , IRetryableError )
175189 elif inspect .isclass (error ) and issubclass (error , Exception ):
176- classImplements (error , IRetryableError )
190+ classImplements (error , IRetryableError ) # type: ignore[misc] # TODO: https://github.com/Shoobx/mypy-zope/issues/50
177191 else :
178192 raise ValueError (
179193 'only exception objects or types may be marked retryable'
180194 )
181195
182196
183- def is_error_retryable (request , exc ) :
197+ def is_error_retryable (request : Request , exc : Exception | None ) -> bool :
184198 """
185199 Return ``True`` if the exception is recognized as :term:`retryable error`.
186200
@@ -197,7 +211,7 @@ def is_error_retryable(request, exc):
197211 )
198212
199213
200- def is_last_attempt (request ) :
214+ def is_last_attempt (request : Request ) -> bool :
201215 """
202216 Return ``True`` if the request is on its last attempt, meaning that
203217 ``pyramid_retry`` will not be issuing any new attempts, regardless of
@@ -213,7 +227,7 @@ def is_last_attempt(request):
213227 if attempt is None or attempts is None :
214228 return True
215229
216- return attempt + 1 == attempts
230+ return attempt + 1 == attempts # type: ignore[no-any-return] # TODO: what's the best way to determine these?
217231
218232
219233class RetryableErrorPredicate (object ):
@@ -226,20 +240,20 @@ class RetryableErrorPredicate(object):
226240
227241 """
228242
229- def __init__ (self , val , config ):
243+ def __init__ (self , val : t . Any , config : Configurator ):
230244 if not isinstance (val , bool ):
231245 raise ConfigurationError (
232246 'The "retryable_error" view predicate value must be '
233247 'True or False.' ,
234248 )
235249 self .val = val
236250
237- def text (self ):
251+ def text (self ) -> str :
238252 return 'retryable_error = %s' % (self .val ,)
239253
240254 phash = text
241255
242- def __call__ (self , context , request ) :
256+ def __call__ (self , context : t . Any , request : Request ) -> bool :
243257 exc = getattr (request , 'exception' , None )
244258 is_retryable = is_error_retryable (request , exc )
245259 return (self .val and is_retryable ) or (
@@ -257,25 +271,25 @@ class LastAttemptPredicate(object):
257271
258272 """
259273
260- def __init__ (self , val , config ):
274+ def __init__ (self , val : t . Any , config : Configurator ):
261275 if not isinstance (val , bool ):
262276 raise ConfigurationError (
263277 'The "last_retry_attempt" view predicate value must be '
264278 'True or False.' ,
265279 )
266280 self .val = val
267281
268- def text (self ):
282+ def text (self ) -> str :
269283 return 'last_retry_attempt = %s' % (self .val ,)
270284
271285 phash = text
272286
273- def __call__ (self , context , request ) :
287+ def __call__ (self , contex : t . Any , request : Request ) -> bool :
274288 is_last = is_last_attempt (request )
275289 return (self .val and is_last ) or (not self .val and not is_last )
276290
277291
278- def includeme (config ) :
292+ def includeme (config : Configurator ) -> None :
279293 """
280294 Activate the ``pyramid_retry`` execution policy in your application.
281295
@@ -294,7 +308,7 @@ def includeme(config):
294308 config .add_view_predicate ('last_retry_attempt' , LastAttemptPredicate )
295309 config .add_view_predicate ('retryable_error' , RetryableErrorPredicate )
296310
297- def register ():
311+ def register () -> None :
298312 attempts = int (settings .get ('retry.attempts' ) or 3 )
299313 settings ['retry.attempts' ] = attempts
300314
0 commit comments