def __call__(
        self,
        fn: Callable[ParamType, ReturnType],
        *args: ParamType.args,
        **kwargs: ParamType.kwargs,
    ) -> ReturnType:
        """Tries to execute fn with the given args and kwargs."""
        retries = 0
        while True:
            try:
                return fn(*args, **kwargs)
            except BaseException as ex:
                if retries >= self.config.max_retries:
                    raise MaxRetryError(
                        f"Calling '{fn.__name__}' failed after {retries} attempt(s). "
                        f"Args: {reprlib.repr(args)}; kwargs: {reprlib.repr(kwargs)}. "
                        f"Last error: {self.format_error(self._wrap_exception(ex))}"
                    ) from ex
                if not self.should_retry(ex):
                    raise self._wrap_exception(ex)
                # TODO(Guarin, 02/23): Disabled logging because it can be called from
                # a different process than the main process, resulting in a potential
                # deadlock. Enable logging again once we switch to using spawn or
                # forkserver to start processes. See LIG-2486.
                # logger.debug(
                #     f"Retrying: Retry {retries + 1} of {self.config.max_retries} after {repr(ex)}"
                # )
                backoff = self.calculate_backoff(retries, ex)
                time.sleep(backoff)
            retries += 1
Tries to execute fn with the given args and kwargs.
lightly/api/retry_utils.py