coady / multimethod

Multiple argument dispatching.
https://coady.github.io/multimethod
Other
284 stars 23 forks source link

TypeError: type 'dict_keys' is not an acceptable base type #84

Closed Dvergatal closed 1 year ago

Dvergatal commented 1 year ago

Hi, we have probably found an issue in multimethod code which can be reproduced using below code snippet:

from typing import Any, Iterable, TypeVar, Generic, List, Container
from multimethod import multimethod
from types import GenericAlias
#from _collections_abc import KeysView

@multimethod
def validate_enum_list(key: str, value: str, allowed_values: Iterable[str]) -> None:
    print("key: str, value: str, allowed_values: MyIterable[str]")
    print(type(value))
    print(type(allowed_values))

@validate_enum_list.register
def _(key: str, value: List[str], allowed_values: List[List[str]]) -> None:
    print("key: str, value: MyIterable[str], allowed_values: MyIterable[MyIterable[str]]")
    print(type(value))
    print(type(allowed_values))

validate_enum_list("test1", "test1", ["test1"])
validate_enum_list("test2", ["test2"], [["fremen", "atreides", "harkonnen"]])
d = {'a':'aaa','b':'bbb','c':'ccc'}
validate_enum_list("test1", "test2", d.keys())

which produces an error which looks like below:

key: str, value: str, allowed_values: MyIterable[str]
<class 'str'>
<class 'list'>
key: str, value: MyIterable[str], allowed_values: MyIterable[MyIterable[str]]
<class 'list'>
<class 'list'>
Traceback (most recent call last):
  File "/home/plobacz/workspace/multi6.py", line 26, in <module>
    validate_enum_list("test1", "test2", d.keys())
  File "/home/plobacz/.local/lib/python3.10/site-packages/multimethod/__init__.py", line 313, in __call__
    func = self[tuple(func(arg) for func, arg in zip(self.type_checkers, args))]
  File "/home/plobacz/.local/lib/python3.10/site-packages/multimethod/__init__.py", line 313, in <genexpr>
    func = self[tuple(func(arg) for func, arg in zip(self.type_checkers, args))]
  File "/home/plobacz/.local/lib/python3.10/site-packages/multimethod/__init__.py", line 141, in get_type
    tps = {subtype.get_type(tp_arg, arg) for tp_arg in self.__args__}
  File "/home/plobacz/.local/lib/python3.10/site-packages/multimethod/__init__.py", line 141, in <setcomp>
    tps = {subtype.get_type(tp_arg, arg) for tp_arg in self.__args__}
  File "/home/plobacz/.local/lib/python3.10/site-packages/multimethod/__init__.py", line 160, in get_type
    return subtype(type(arg), *(subscripts or [Empty]))
  File "/home/plobacz/.local/lib/python3.10/site-packages/multimethod/__init__.py", line 69, in __new__
    return type.__new__(cls, str(tp), bases, namespace)
TypeError: type 'dict_keys' is not an acceptable base type