dataclasses-json：`from __future__ import annotations`がある状態で`.schema().dump()`を実行すると、UserWarningが発生する

# 実行環境
* Python3.8.6
* dataclasses-json 0.4.5

# やりたいこと
[dataclasses-json](https://github.com/lidatong/dataclasses-json)を使って、データクラスからdictに変換したいです。


# 何が起きたのか
`.schema().dump(...)`を使って、データクラス`Person`のlistを、dictのlistに変換します。

https://github.com/lidatong/dataclasses-json#encode-or-decode-into-python-listsdictionaries-rather-than-json

`foo.py`では、型ヒントに`list`や`dict`などを使うため、ファイルの先頭で`from __future__ import annotations`を記載しました。python3.7以降で型ヒントに`list`や`dict`を使う場合は、先頭に`from __future__ import annotations`を記述する必要があります。

https://future-architect.github.io/articles/20201223/#%E3%82%B8%E3%82%A7%E3%83%8D%E3%83%AA%E3%82%AF%E3%82%B9



```python:foo.py
from __future__ import annotations

from dataclasses import dataclass
from dataclasses_json import dataclass_json


@dataclass_json
@dataclass
class Person:
    name: str


people = [Person("Alice")]
dict_people = Person.schema().dump(people, many=True)
print(dict_people)
```

`foo.py`を実行すると、`UserWarning: Unknown type str at Person.name`という警告が発生しました。


```
$ python foo.py
/home/vagrant/.pyenv/versions/3.8.6/lib/python3.8/site-packages/dataclasses_json/mm.py:270: UserWarning: Unknown type str at Person.name: str It's advised to pass the correct marshmallow type to `mm_field`.
  warnings.warn(
[{'name': 'Alice'}]
```

# 警告が発生する条件を調べる

`from __future__ import annotations`を取り除けば、警告は発生しませんでした。
Python3.9.7でも警告は発生しました。


# 警告が発生する原因

警告が発生している関数は以下の部分です。

```python:dataclasses_json/mm.py
def build_type(type_, options, mixin, field, cls):
    def inner(type_, options):
        ...
        origin = getattr(type_, '__origin__', type_)
        args = [inner(a, {}) for a in getattr(type_, '__args__', []) if
                a is not type(None)]

        if _is_optional(type_):
            options["allow_none"] = True

        if origin in TYPES:
            return TYPES[origin](*args, **options)

        if _issubclass_safe(origin, Enum):
            return EnumField(enum=origin, by_value=True, *args, **options)

        if is_union_type(type_):
            union_types = [a for a in getattr(type_, '__args__', []) if
                           a is not type(None)]
            union_desc = dict(zip(union_types, args))
            return _UnionField(union_desc, cls, field, **options)

        warnings.warn(
            f"Unknown type {type_} at {cls.__name__}.{field.name}: {field.type} "
            f"It's advised to pass the correct marshmallow type to `mm_field`.")
        return fields.Field(**options)

    return inner(type_, options)
```

https://github.com/lidatong/dataclasses-json/blob/a5fd1b53b4e9c192a2ecfd851502d056309c36c8/dataclasses_json/mm.py#L256-L274

本来`if origin in TYPES:`文の中を通過するはずなのですが、この条件が通らないため`warnings.warn`を呼び出しているようです。
変数`origin`を`print(f"{origin=}, {type(origin)=}")`で出力してみると、以下の結果になりました。

```
# `from __future__ import annotations` あり
origin='str', type(origin)=<class 'str'>

# `from __future__ import annotations` なし
origin=<class 'str'>, type(origin)=<class 'type'>
```

`from __future__ import annotations`を付けると、`Person.name`に対応する`origin`が`'str'`になってしまうことにより、警告が発生することが分かりました。
`from __future__ import annotations`の有無で、なぜ変数`origin`が変わってしまうのかは、分かりませんでした。

# 回避策

警告メッセージに従い`mm_field`を指定すれば、警告は出なくなります。
が、この書き方は冗長なので、採用しない方がよいです。大人しく`typing.List`を使った方がよいでしょう。

```python:foo.py
from __future__ import annotations

from dataclasses import dataclass, field
from dataclasses_json import dataclass_json, config
from marshmallow import fields


@dataclass_json
@dataclass
class Person:
    name: str = field(metadata=config(mm_field=fields.Str()))
```