環境

  • Python 3.7

背景

PythonでWeb Apiのクライアントライブラリを作成しています。APIのアクセス過多で失敗したときでもリトライするよう、my_retryというデコレータを作成しました。

def my_retry(self, function):
    """
    HTTP Status Codeが429 or 5XXのときはリトライする. 最大5分間リトライする。
    """

    @functools.wraps(function)
    def wrapped(*args, **kwargs):
        def fatal_code(e):
            """Too many Request以外の4XXはretryしない"""
            code = e.response.status_code
            return code != 429 and code < 500

        return backoff.on_exception(backoff.expo, requests.exceptions.RequestException,
                                    jitter=backoff.full_jitter,
                                    max_time=300,
                                    giveup=fatal_code)(function)(*args, **kwargs)

    return wrapped

以下、読みやすさのために my_retry を簡略化しています。

# coding: utf-8
import functools

def my_retry(function):
    @functools.wraps(function)
    def wrapped(*args, **kwargs):
        print("my_retry calls", function.__name__, end=", ")
        return function(*args, **kwargs)

    return wrapped

class ApiClient:
    def __init__(self):
        pass

    @my_retry
    def execute_hoge_api(self):
        print("hoge!")


    @my_retry
    def execute_fuga_api(self):
        print("fuga!")

def main():
    ac = ApiClient()
    ac.execute_hoge_api()
    ac.execute_fuga_api()


if __name__ == '__main__':
    main()

やりたいこと

ApiClientクラスのユーザが、リトライ用の関数を変更できるようにしたいです。
具体的には、ApiClientのコンストラクタ引数にリトライ用関数を指定するなどの方法を考えています。

どのようなコードを書けばよいでしょうか?

検討したこと

以下のコードのように、my_retry関数をApiClientクラスのインスタンスメソッドにしてみました。
この場合、@my_retryの引数には何を渡せばよいか分からず、詰まってしまいました。

class ApiClient:
    def __init__(self, my_retry=None):
        if my_retry is not None:
            self.my_retry = my_retry
        pass

    # デコレータの引数には何を指定すればよい?
    @my_retry
    def execute_hoge_api(self):
        print("hoge!")


    @my_retry
    def execute_fuga_api(self):
        print("fuga!")