Decorator objects

The previous example requires three levels of nested functions. The first it is going to be a function that receives the parameters of the decorator we want to use. Inside this function, the rest of the functions are closures that use these parameters along with the logic of the decorator.

A cleaner implementation of this would be to use a class to define the decorator. In this case, we can pass the parameters in the __init__ method, and then implement the logic of the decorator on the magic method named __call__.

The code for the decorator will look like it does in the following example:

class WithRetry:

def __init__(self, retries_limit=RETRIES_LIMIT, allowed_exceptions=None):
self.retries_limit = retries_limit
self.allowed_exceptions = allowed_exceptions or (ControlledException,)

def __call__(self, operation):

@wraps(operation)
def wrapped(*args, **kwargs):
last_raised = None

for _ in range(self.retries_limit):
try:
return operation(*args, **kwargs)
except self.allowed_exceptions as e:
logger.info("retrying %s due to %s", operation, e)
last_raised = e
raise last_raised

return wrapped

And this decorator can be applied pretty much like the previous one, like so:

@WithRetry(retries_limit=5)
def run_with_custom_retries_limit(task):
return task.run()

It is important to note how the Python syntax takes effect here. First, we create the object, so before the @ operation is applied, the object is created with its parameters passed to it. This will create a new object and initialize it with these parameters, as defined in the init method. After this, the @ operation is invoked, so this object will wrap the function named run_with_custom_reries_limit, meaning that it will be passed to the call magic method.

Inside this call magic method, we defined the logic of the decorator as we normally do—we wrap the original function, returning a new one with the logic we want instead.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
13.59.95.150