Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for @overloaded callables #80

Open
CallumJHays opened this issue Jan 3, 2021 · 1 comment
Open

Support for @overloaded callables #80

CallumJHays opened this issue Jan 3, 2021 · 1 comment

Comments

@CallumJHays
Copy link

This is a bit of a tricky one, but suppose you had something like the following:

@overload
def test(a: int, b: float) -> str: ...
@overload
def test(a: List[int], b: List[float]) -> List[str]: ...
@runtime_validation
def test(a, b):
    return ...

It would be cool if the correct overload could be narrowed down to and validated with the arguments at runtime.

There has been some discussion in the official typing repo on how to accomplish this:
python/typing#711

The gist is to inject a custom @overload implementation. I imagine there'd be work in tricking intellisense servers into thinking it's the original.

@ken-morel
Copy link

Sure the logic in my packege pyoload will help.
We could:

  • Simply runtime check all the functions and skip all thos raising an exception
  • Building A custom argument matcher which will do the typecheck for you

pyoload uses the first a thus supports overloads with different parameter list length and further recursive argument casting... but I won't expose on that, imaging

Bit of clone of pyoload

def get_name(obj):
    return obj.__module__ + '.' + obj.__qualname__


overloads = {}

class Overload:
    @classmethod
    def overload(cls, func):
        name = get_name(func)
        if not name in overloads:
            overloads[name] = []
        overloads[name].append(runtime_check(func))

    def __init__(self):
        self.entries = []

    def __call__(self, *args, **kw):
        for func in self.entries:
            try:
                result = func(*args, **kw)
            except:
                pass
            else:
                return ret
        else:
            raise OverloadError(...)

@Overload.overload
def myfunc(d:dict[str, tuple[int]]): ...

@Overload.overload
def myfunc(c: int): ...

@Overload.overload
def myfunc(a: str): ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants