coady / multimethod

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

TypeError when one of the type hints is type or another metaclass #25

Closed plammens closed 3 years ago

plammens commented 3 years ago

Using type (or any other subclass of type, e.g. a custom metaclass) as the type hint for one of the parameters of a function of a multimethod makes the dispatch process raise a TypeError when calling type.mro() (which expects the type object as an argument).

Example

@multimethod
def f(x: type):
    print("success")

Expected

>>> f(int)
success

Actual

>>> f(int)
TypeError: unbound method type.mro() needs an argument

Traceback:

``` Traceback (most recent call last): File "C:\Users\Paolo\Code\JB-PycharmProjects\LoveLetter\venv\lib\site-packages\IPython\core\interactiveshell.py", line 3418, in run_code exec(code_obj, self.user_global_ns, self.user_ns) File "", line 1, in f(int) File "C:\Users\Paolo\Code\JB-PycharmProjects\LoveLetter\venv\lib\site-packages\multimethod\__init__.py", line 184, in __call__ return self[tuple(map(self.get_type, args))](*args, **kwargs) File "C:\Users\Paolo\Code\JB-PycharmProjects\LoveLetter\venv\lib\site-packages\multimethod\__init__.py", line 184, in __call__ return self[tuple(map(self.get_type, args))](*args, **kwargs) File "C:\Users\Paolo\Code\JB-PycharmProjects\LoveLetter\venv\lib\site-packages\multimethod\__init__.py", line 174, in __missing__ groups = groupby(signature(types).__sub__, self.parents(types)) File "C:\Users\Paolo\Code\JB-PycharmProjects\LoveLetter\venv\lib\site-packages\multimethod\__init__.py", line 17, in groupby groups[func(value)].append(value) File "C:\Users\Paolo\Code\JB-PycharmProjects\LoveLetter\venv\lib\site-packages\multimethod\__init__.py", line 104, in __sub__ return tuple(mro.index(cls if cls in mro else object) for mro, cls in zip(mros, other)) File "C:\Users\Paolo\Code\JB-PycharmProjects\LoveLetter\venv\lib\site-packages\multimethod\__init__.py", line 104, in return tuple(mro.index(cls if cls in mro else object) for mro, cls in zip(mros, other)) File "C:\Users\Paolo\Code\JB-PycharmProjects\LoveLetter\venv\lib\site-packages\multimethod\__init__.py", line 103, in mros = (subclass.mro() for subclass in self) TypeError: unbound method type.mro() needs an argument ```

Cause

Methods of metaclasses like type, e.g. .mro() expect an explicit first argument which is the actual type object being used.