やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

GitHubAPI認証の実装について考える2

前回の続き。これまでの実装について見てみる。

これまでの実装

http://ytyaru.hatenablog.com/entry/2017/02/24/000000
http://ytyaru.hatenablog.com/entry/2017/03/01/000000

ソースコードの一部抜粋。

APIメソッドに認証情報を渡す

class Repository:
    def gets(self, username=None, password=None, otp=None, token=None):
        url = 'https://api.github.com/user/repos'
        if not(username is None or password is None):
            r = requests.get(f.url, headers=headers, auth=(username, password))
        elif not(token is None):
            r = requests.get(f.url, headers=headers)
        else:
            raise Exception('Account information is required.')
            return
class Repository:
    def create(self, username=None, password=None, otp=None, token=None, name=None, description=None, homepage=None):
        if (name is None):
            raise Exception('name is required.')
            return
        if not(username is None or password is None):
            r = requests.post(url, headers=headers, auth=(username, password), data=json.dumps(data))
        elif not(token is None):
            r = requests.post(url, headers=headers, data=json.dumps(data))
        else:
            raise Exception('Account information is required.')
            return

Basic認証、TwoFactor認証、Token認証の3パターンがありうる。問題点は以下3点。

  • エラーチェックなどが面倒になる
  • APIごとに埋め込んでいたらコードが重複する
  • APIのパラメータがあると引数がわかりづらくなる

とくに3番目が嫌。APIメソッドはAPIの引数だけを渡すのが望ましい。

アカウント設定用メソッド

class Language:
    def set_account(self, username, password, otp=None):
        self.username = username
        self.password = password
        self.otp = otp
        self.token = None
    def set_token(self, token, otp=None):
        self.token = token
        self.otp = otp
        self.username = None
        self.password = None
    def get(self, username, repo_name):
        url = 'https://api.github.com/repos/{0}/{1}/languages'.format(username, repo_name)
        headers = self._get_http_headers(self.otp, self.token)
        if not(self.token is None):
            r = requests.get(url, headers=headers)
        elif not(self.username is None or self.password is None):
            r = requests.get(url, headers=headers, auth=(self.username, self.password))
        else:
            raise Exception('Account information is required.')
            return
        ...

これでAPIメソッドの引数から認証情報が消えてすっきりした。しかし、それ以外の問題は解決していない。このままではAPIまたはclassの数だけアカウント関係の変数やメソッドが増えてしまう。かといって、全APIを1つのclassに含めると1ファイルの内容が膨大になってしまう。

所感

C#でいうpartialclassをPythonでできれば解決できそう。次回に続く。