coady / multimethod

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

Using >1 different Union raises TypeError #79

Closed IsaacBreen closed 1 year ago

IsaacBreen commented 1 year ago

I tried to find a minimal example (tested with Python 3.10 and 3.11):

from multimethod import multimethod

@multimethod
def f(x: int | float): ...

@multimethod
def f(x: tuple | list): ...
│ ~/miniforge3/envs/py311/lib/python3.11/site-packages/multimethod/__init__.py:110 in                  │
│ __subclasscheck__                                                                                                    │
│                                                                                                                      │
│   107 │   │   │   return issubclass(origin, self.__origin__)                                                         │
│   108 │   │   return (  # check args first to avoid a recursion error in ABCMeta                                     │
│   109 │   │   │   len(args) == nargs                                                                                 │
│ ❱ 110 │   │   │   and issubclass(origin, self.__origin__)                                                            │
│   111 │   │   │   and all(map(issubclass, args, self.__args__))                                                      │
│   112 │   │   )                                                                                                      │
│   113                                                                                                                │
│                                                                                                                      │
│ ╭─────────────────── locals ────────────────────╮                                                                    │
│ │     args = (<class 'tuple'>, <class 'list'>)  │                                                                    │
│ │    nargs = 2                                  │                                                                    │
│ │   origin = tuple | list                       │                                                                    │
│ │     self = <class 'multimethod.int | float'>  │                                                                    │
│ │ subclass = <class 'multimethod.tuple | list'> │                                                                    │
│ ╰───────────────────────────────────────────────╯                                                                    │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
TypeError: issubclass() arg 1 must be a class

Worth noting that this works fine:

@multimethod
def f(x: Union[int, float]): ...

@multimethod
def f(x: tuple | list): ...
coady commented 1 year ago

Interesting, the | syntax isn't just syntactic sugar for Union. It added a new UnionType, which will need its own support.

Thanks for the report.