GithubHelp home page GithubHelp logo

kk6 / python-annict Goto Github PK

View Code? Open in Web Editor NEW
10.0 2.0 2.0 413 KB

Annict API for python

Home Page: https://python-annict.readthedocs.io/en/latest/

License: MIT License

Python 99.97% Gherkin 0.03%
python annict library api-wrapper

python-annict's Introduction

python-annict

Annict API wrapper for Python

Codacy Badge CircleCI codecov PyPI License Code style: black

python-annict officially supports Python 3.6 or higher.

Installation

pip install annict

Quickstart

Authentication

Acquire the URL for authentication code.

>>> from annict.auth import OAuthHandler
>>> handler = OAuthHandler(client_id='Your client ID', client_secret='Your client secret')
>>> url = handler.get_authorization_url(scope='read write')
>>> print(url)

Open the browser and access the URL you obtained, the authentication code will be displayed. It will be passed to the handler.authenticate() 's argument to get the access token.

>>> handler.authenticate(code='Authentication code')
>>> print(handler.get_access_token())

Note that this authentication flow is unnecessary when issuing a personal access token on Annict and using it.

See: Annict API: 個人用アクセストークンが発行できるようになりました

Hello world

>>> from annict.api import API
>>> annict = API('Your access token')
>>> results = annict.works(filter_title="Re:ゼロから始める異世界生活")
>>> print(results[0].title)
Re:ゼロから始める異世界生活

Cache

For now, we do not have our own cache system. However, caching is also important to reduce the load on AnnictAPI.

So I introduce a cache plugin for requests library called requests_cache.

Install with pip.

pip insall requests_cache

requests_cache is very easy to use.

>>> import requests_cache
>>> requests_cache.install_cache(cache_name='annict', backend='memory', expire_after=300)
>>> # At first, from Annict API.
>>> api.me()
>>> # You can get results from cache, if it is within the expiration time.
>>> api.me()

For more information: Requests-cache documentation

Documentation

python-annict's People

Contributors

codacy-badger avatar dependabot-preview[bot] avatar dependabot-support avatar kk6 avatar takuan-osho avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

python-annict's Issues

Cursor mode.

For example:

class API:

    def works(self, ...):
        ...
    works.cursor_support = True
    
    def me(self, ...):
        ...
    
    def set_status(self, ...):
        ...

class SimpleCursor(object):

    def __init__(self, method, **kwargs):
        if not hasattr(method, 'cursor_support'):
            raise TypeError(f"Cursor does not support this method: {method.__func__.__qualname__}")
        self.method = method
        self.kwargs = kwargs
        if 'page' not in self.kwargs:
            self.kwargs['page'] = 1

    def cursor(self):
        while 1:
            results = self.method(**self.kwargs)
            for result in results:
                yield result
            self.kwargs['page'] += 1
            if not results.next_page or not results:
                raise StopIteration

Usage:

>>> for user in annict.utils.SimpleCursor(api.search_users, per_page=50, sort_id='desc').cursor():
...     print(user)
...

<User object>
<User object>


>>> for user in annict.utils.SimpleCursor(api.me).cursor():
...     print(user)
...
  
Traceback (most recent call last):
  ...
TypeError: This method does not correspond to Cursor: API.me

Some pre-commit hooks

automatically upgrade syntax for newer versions of the language.
https://github.com/asottile/pyupgrade

automatically add trailing commas to calls and literals.
https://github.com/asottile/add-trailing-comma

An enterprise friendly way of detecting and preventing secrets in code.
https://github.com/Yelp/detect-secrets

Mirror of the yapf package for pre-commit
https://github.com/humitos/mirrors-docformatter

sample config

-   repo: https://github.com/asottile/pyupgrade
    rev: v1.8.0
    hooks:
    -   id: pyupgrade
        args: [--py36-plus]
-   repo: https://github.com/asottile/add-trailing-comma
    rev: v0.7.1
    hooks:
    -   id: add-trailing-comma
        args: [--py36-plus]
-   repo: https://github.com/Yelp/detect-secrets
    rev: 0.9.1
    hooks:
    -   id: detect-secrets
        args: ['--baseline', '.secrets.baseline']
        exclude: .*tests/.*|.*yelp/testing/.*|\.pre-commit-config\.yaml
- repo: [email protected]:humitos/mirrors-docformatter.git
  rev: v1.0
  hooks:
    - id: docformatter
      args: ['--in-place', '--wrap-summaries=80', '--wrap-descriptions=80', '--pre-summary-newline']

Dependabot can't resolve your Python dependency files

Dependabot can't resolve your Python dependency files.

As a result, Dependabot couldn't update your dependencies.

The error Dependabot encountered was:

Creating virtualenv annict-ToFo54Py-py3.8 in /home/dependabot/.cache/pypoetry/virtualenvs
Updating dependencies
Resolving dependencies...

  PackageNotFound

  Package sphinxcontrib-htmlhelp (1.0.1) not found.

  at /usr/local/.pyenv/versions/3.8.6/lib/python3.8/site-packages/poetry/repositories/pool.py:144 in package
      140│                     self._packages.append(package)
      141│ 
      142│                     return package
      143│ 
    → 144│         raise PackageNotFound("Package {} ({}) not found.".format(name, version))
      145│ 
      146│     def find_packages(
      147│         self, dependency,
      148│     ):

If you think the above is an error on Dependabot's side please don't hesitate to get in touch - we'll do whatever we can to fix it.

View the update logs.

APIリニューアル

APIリファレンスを書こうと思ってshpinxで自動生成してみたけど、実装がPythonぽくなくて気持ちが悪いと気付いたので書き直したほうが良さそう。

  • 現状: api.me.records.create()
  • 理想: api.create_record()

現状の実装はたしかに「 me/records に対するPOSTリクエスト」というのがわかりやすいとはいえ、Pythonっぽくなくて逆にわかりにくい気がする。

必須パラメータが `allowed_params` に無いのは混乱を招く

現状、必須パラメータはメソッドの引数、非必須パラメータはサービスクラスの allowed_params に定義している。

しかしAPIドキュメントに書かれたパラメータのうち、必須パラメータが allowed_params に無いのは混乱を招く。

そこで

A案

  • 必須か否かに関わらず全てのパラメータを allowed_params に定義
  • メソッドの引数は原則として可変長の名前付き引数のみ受け付ける。つまり def m(**kwargs):
  • 従来の、渡された引数が allowed_params にあるかのチェックだけでなく、必須パラメータがちゃんと渡されているかのチェックも行う。必須パラメータはクラスに required_params などで定義する

B案

allowed_paramsallowed_options などにリネームする

ここからは別途Issue作成したほうがいいがメモとして。

A案で各サービスクラスのCRUDメソッドの引数が統一されたら、このあたりの冗長な部分が整理できそうな気がする。少なくともレスポンスを受け取るところまでは抽象化できる。

その際の問題として、エンドポイントによってGETしかない、GETは無いがPOST/PATCH/DELETEがある、などあるのでベースクラスに実装するわけにもいかない。

となるとクラスをやめて関数ベースにする?

Methods for extending the API

At the moment, the annict.api.API class implements only the method corresponding to the Annict API endpoint (exchanging direct communication with the API).

Although we use these conditions as parameters for the purpose and use it, sometimes there are requests that you know that you specify the same parameters every time (eg "I'd like to acquire the work list for the current season" etc.)

>>> api.works(filter_season='2017-spring', sort_watchers_count='desc')

It would be better to provide those with such a high possibility of being frequently used as shortcuts.

>>> api.get_works_for_current_season(sort_watchers_count='desc')

More examples

>>> api.get_ranking_for_current_season(sort_by='watchers')
>>> api.get_my_works_for_current_season(status='wanna_watch')
>>> api.batch_record(episode_ids=[3, 4, 5])
>>> api.bulk_record(work_id=123)  # Record all episodes of the work
>>> api.batch_update_status(work_ids=[123, 456, 789], status='wanna_watch')

Or, instead of extending the API class, prepare a module called annict.shortcuts and list functions there.

>>> from annict.shortcuts import batch_record
>>> batch_record(api, episode_ids=[3, 4, 5])

Implicit stop using StopIteration no longer allowed in Python 3.7

Manual StopIteration will cause the following RuntimeError exception.

RuntimeError: generator raised StopIteration

see PEP479

Probably the fix is ​​as follows.

diff --git a/annict/cursors.py b/annict/cursors.py
index b45891d..69d8d81 100644
--- a/annict/cursors.py
+++ b/annict/cursors.py
@@ -20,7 +20,7 @@ class SimpleCursor(object):
                 yield result
             self.kwargs['page'] += 1
             if not results.next_page or not results:
-                raise StopIteration
+                return


 def cursor_support(api_method):
diff --git a/tests/test_cursors.py b/tests/test_cursors.py
index 5d064f1..842c76e 100644
--- a/tests/test_cursors.py
+++ b/tests/test_cursors.py
@@ -52,6 +52,8 @@ def test_cursor_supported(api_factory):
     gen = SimpleCursor(api.works).cursor()
     result = next(gen)
     assert result.title == 'SHIROBAKO'
+    with pytest.raises(StopIteration):
+        next(gen)


 @responses.activate

This fix works correctly in both Python 3.6 and Python 3.7.

Install only necessary packages on CircleCI

Currently, buildbot tries to install all packages listed in pyproject.toml. However, we do not need to install sphinx etc on CI.

Package operations: 56 installs, 0 updates, 0 removals

  - Installing certifi (2018.11.29)
  - Installing chardet (3.0.4)
  - Installing idna (2.8)
  - Installing markupsafe (1.1.0)
  - Installing pyparsing (2.3.0)
  - Installing pytz (2018.7)
  - Installing six (1.12.0)
  - Installing urllib3 (1.24.1)
  - Installing alabaster (0.7.12)
  - Installing atomicwrites (1.2.1)
  - Installing attrs (18.2.0)
  - Installing babel (2.6.0)
  - Installing docutils (0.14)
  - Installing imagesize (1.1.0)
  - Installing jinja2 (2.10)
  - Installing mccabe (0.6.1)
  - Installing more-itertools (4.3.0)
  - Installing packaging (18.0)
  - Installing pluggy (0.8.0)
  - Installing py (1.7.0)
  - Installing pycodestyle (2.4.0)
  - Installing pyflakes (2.0.0)
  - Installing pygments (2.3.1)
  - Installing pyyaml (3.13)
  - Installing requests (2.21.0)
  - Installing snowballstemmer (1.2.1)
  - Installing sphinxcontrib-websupport (1.1.0)
  - Installing zipp (0.3.3)
  - Installing aspy.yaml (1.1.1)
  - Installing cfgv (1.4.0)
  - Installing click (7.0)
  - Installing coverage (4.5.2)
  - Installing filelock (3.0.10)
  - Installing flake8 (3.6.0)
  - Installing identify (1.1.8)
  - Installing importlib-metadata (0.8)
  - Installing incremental (17.5.0)
  - Installing nodeenv (1.3.3)
  - Installing orderedmultidict (1.0)
  - Installing pytest (4.0.2)
  - Installing python-dateutil (2.7.5)
  - Installing sphinx (1.8.2)
  - Installing toml (0.10.0)
  - Installing virtualenv (16.1.0)
  - Installing arrow (0.12.1)
  - Installing furl (2.0.0)
  - Installing pre-commit (1.14.1)
  - Installing pytest-cov (2.6.0)
  - Installing pytest-flake8 (1.0.2)
  - Installing pytest-runner (4.2)
  - Installing rauth (0.7.3)
  - Installing requests-cache (0.4.13)
  - Installing responses (0.10.5)
  - Installing sphinx-rtd-theme (0.4.2)
  - Installing towncrier (18.6.0)
  - Installing tox (3.6.0)
  - Installing annict (0.7.0)

HINT: pyproject.toml's [tool.poetry.extras] section
https://poetry.eustace.io/docs/pyproject/#extras

In addition, since the package necessary for Read the Docs is managed separately, I think that it is not necessary to consider.

入力値のバリデーション

GET /v1/recordsfilter_has_record_comment の概要は

ミュート機能でミュートしているユーザを除外するかどうかを指定します。 true で除外、 false で除外しないようにできます。デフォルトは true (除外する) です。

のとおりだが、現状だとバリデーションしていないので filter_muted=0.5 とか送れてしまう。

試しに送ってみたらサーバー側ではバリデーションしてくれてるのでエラーが返ってくるが、クライアント側でもバリデーションしたほうがいいのでは。

{
"errors": [
  {
"type": "invalid_params",
"message": "リクエストに失敗しました",
"developer_message": "filter_has_record_commentには `true` または `false` を指定してください"
}
],
}

未実装API

いつの間にか公式のAPIドキュメントが移動してた

https://docs.annict.com/ja/

エンドポイントも幾つか増えているので対応が必要。

  • /v1/users
  • /v1/following
  • /v1/followers
  • /v1/activities
  • /v1/me
  • /v1/me/following_activities

以上。全てGETのみ。

requestsのraise_for_statusを使う

HTTPステータスが400番台、500番台の場合は resp.raise_for_status()HTTPError にしてくれるので、自前のエラーよりもこっち使うようが良さそう

Dependabot can't resolve your Python dependency files

Dependabot can't resolve your Python dependency files.

As a result, Dependabot couldn't update your dependencies.

The error Dependabot encountered was:

Creating virtualenv annict-SHlPt6oC-py3.9 in /home/dependabot/.cache/pypoetry/virtualenvs
Updating dependencies
Resolving dependencies...

  PackageNotFound

  Package pre-commit (2.9.1) not found.

  at /usr/local/.pyenv/versions/3.9.0/lib/python3.9/site-packages/poetry/repositories/pool.py:144 in package
      140│                     self._packages.append(package)
      141│ 
      142│                     return package
      143│ 
    → 144│         raise PackageNotFound("Package {} ({}) not found.".format(name, version))
      145│ 
      146│     def find_packages(
      147│         self, dependency,
      148│     ):

If you think the above is an error on Dependabot's side please don't hesitate to get in touch - we'll do whatever we can to fix it.

View the update logs.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.