Python responder v1.3.1 -> v1.3.2 変更・追加まとめ

ついに Python responder が更新されました！
そこで前回のバージョンから今回のバージョンとの間の変更・追加機能をまとめたいと思います

responder とはなんぞや？という人はこちらの記事をご参照ください
→ [Python responder 入門のために… 下調べ](https://qiita.com/y_k/items/6e4da3bef5c8d8bd2730)

# TL;DR
Release 情報的には「ASGI 3 Support !」です。

CHENGELOG 的には以下の通りです。

* 追加: ASGI 3 のサポート
* 追加: python 3.8-dev の CI test
* 追加: リクエストの `state` は mapping オブジェクトになりました
* 非推奨: ASGI 2

以上の情報で満足される方は以降は読み飛ばして頂いて構いません。


# ASGI 3 のサポート
starlette と responder の更新により， ASGI 3 がサポートされました。
それに伴い， ASGI 2 は非推奨となりました。

```python
import responder
from logging import getLogger

from sentry_asgi import SentryMiddleware
import sentry_sdk

logger = getLogger(__name__)

sentry_sdk.init($URL)

api = responder.API()
api.add_middleware(SentryMiddleware)


@api.route("/")
def index(req, resp):
    division_by_zero = 1 / 0
    resp.text = ""

if __name__ == "__main__":
    api.run(address="0.0.0.0", port=5000, debug=True)
```

```
INFO: Started server process [6]
INFO: Waiting for application startup.
INFO: Uvicorn running on http://0.0.0.0:5000 (Press CTRL+C to quit)
INFO: ('172.19.0.1', 44572) - "GET / HTTP/1.1" 500
ERROR: Exception in ASGI application
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/dist-packages/uvicorn/protocols/http/httptools_impl.py", line 375, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "/usr/local/lib/python3.7/dist-packages/uvicorn/middleware/debug.py", line 81, in __call__
    raise exc from None
  File "/usr/local/lib/python3.7/dist-packages/uvicorn/middleware/debug.py", line 78, in __call__
    await self.app(scope, receive, inner_send)
  File "/usr/local/lib/python3.7/dist-packages/responder/api.py", line 277, in __call__
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.7/dist-packages/sentry_asgi/middleware.py", line 22, in __call__
    raise exc from None
  File "/usr/local/lib/python3.7/dist-packages/sentry_asgi/middleware.py", line 19, in __call__
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.7/dist-packages/starlette/middleware/errors.py", line 177, in __call__
    raise exc from None
  File "/usr/local/lib/python3.7/dist-packages/starlette/middleware/errors.py", line 155, in __call__
    await self.app(scope, receive, _send)
  File "/usr/local/lib/python3.7/dist-packages/starlette/middleware/trustedhost.py", line 34, in __call__
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.7/dist-packages/starlette/middleware/gzip.py", line 20, in __call__
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.7/dist-packages/responder/api.py", line 287, in asgi
    req, scope=scope, send=send, receive=receive
  File "/usr/local/lib/python3.7/dist-packages/responder/api.py", line 304, in _dispatch_http
    await self._execute_route(route=route, req=req, resp=resp, **options)
  File "/usr/local/lib/python3.7/dist-packages/responder/api.py", line 391, in _execute_route
    await r
  File "/usr/local/lib/python3.7/dist-packages/responder/background.py", line 44, in __call__
    return await run_in_threadpool(func, *args, **kwargs)
  File "/usr/local/lib/python3.7/dist-packages/starlette/concurrency.py", line 25, in run_in_threadpool
    return await loop.run_in_executor(None, func, *args)
  File "/usr/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "main.py", line 18, in index
    division_by_zero = 1 / 0
ZeroDivisionError: division by zero
```

<img width="874" alt="スクリーンショット 2019-08-18 12.15.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59163/e85b79d4-5964-7535-8756-da6c8bd543ee.png">

このようにサードパーティのミドルウェアを導入できます。

詳しくは [Starlette Middleware](https://www.starlette.io/middleware/) を確認してください。


# Python のサポートバージョンの拡大
python 3.7, 3.8-dev の CI test が追加され，サポートされるようになりました。


# request.state プロパティ
実体は `starlette.requests.State` です。

```python
import responder
import time
from logging import getLogger

logger = getLogger(__name__)

api = responder.API()

@api.route("/")
def index(req, resp):
    logger.info(req.state)
    logger.info(req.state._state)
    req.state.time_started = time.time()
    logger.info(req.state)
    logger.info(req.state._state)
    resp.text = f"{time.time() - req.state.time_started}"

if __name__ == "__main__":
  api.run(address="0.0.0.0", port=5000, debug=True)
```


```bash
$ curl localhost:5000
0.0002288818359375$
```


```
INFO: Started server process [6]
INFO: Waiting for application startup.
INFO: Uvicorn running on http://0.0.0.0:5000 (Press CTRL+C to quit)
INFO: <starlette.requests.State object at 0x7fb61efc2240>
INFO: {}
INFO: <starlette.requests.State object at 0x7fb61efc2240>
INFO: {'time_started': 1566091621.639762}
INFO: ('172.19.0.1', 44320) - "GET / HTTP/1.1" 200
```

`request.state` は初期では何も入っていないのが確認できます。
この `request.state` には任意の変数名，値が保存できます。

middleware とのやりとりなどに使えそうです。

# on_event
starlette 側により api.on_event のイベントは startup と shutdown の 2 種類のみの対応となるため，ドキュメントが修正されました。 (だいぶ前からだった気が…)


# その他細かな変更点
## Added
* `multipart/form-data` のファイル以外のデータに対応

## Rename
* api.\_dispatch\_request → api.\_dispatch\_http

## Remove
* api.dispatch

## 依存ライブラリ周り
* starlette 0.10.* → starlette 0.12.*
* uvicorn → uvicorn>=0.7, <0.9


# コミットログ一覧
* e52c927: lock ファイル更新
* b2dd2c2: test ファイルの修正
* cf5447d: schema ドキュメントのタイポ修正
* 0bdde6d: merge cf5447d
* a1a0a1b:
    * リファクタリング
    * api.\_dispatch\_request -> api.\_dispatch\_http
* a6955b5:
    * lock ファイル更新
    * starlette 0.11.* へのバージョンアップ対応
* 78b5bef: merge a1a0a1b, a6955b5
* 05035e0: リファクタリング
* d0016ac: README の更新
* e6b880b: コメントのスペルミスの修正
* 8ccb395: merge e6b880b
* fb71abe: ドキュメントの更新
* 63f2e83: merge fb71abe
* 70e6bc0: ドキュメントの更新
* 877fe14: merge 70e6bc0
* 6dbbad1: merge 05035e0
* a802245: format_form での mimetype multipart/form-data の対応
* f01b1d4:
    * CI 環境の OS バージョンアップ
    * CI test に 3.7 追加
* 8b87f63: merge f01b1d4
* 555e1f7: Pipfile の更新
* 38dea83: Pipfile の更新
* 67a6c25: merge 555e1f7, 38dea83
* 7afce42: README の更新
* 3a8113d: ドキュメントの更新
* ee6efe5: merge 7afce42, 3a8113d
* ed8afea: merge a802245
* 37ba3d2: README の更新
* bd2efb6: a802245 に対応するテストの追加
* 22af42e: merge 37ba3d2
* 0529629: merge bd2efb6
* f3c9320:
    * CHANGELOG の更新
    * lock ファイルの更新
    * ASGI 3 のサポート
    * 依存ライブラリの更新
* 54cbbdf: merge f3c9320
* ef33013: CHANGELOG のリファクタリング
* e4f6898: merge ef33013
* 93156fd: 3.8-dev の CI test を追加
* 784c7e7: merge 93156fd
* 8101e7d: request.state プロパティの追加 (starlette.requests.State)
* d73243a: lint
* e6d302a: merge d73243a
* 7219856: CHANGELOG の更新，メタ情報更新
* d820f02: merge 7219856

# 参考
* [GitHub: taoufik07/responder](https://github.com/taoufik07/responder)
* [Starlette](https://www.starlette.io)