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

Currying support for generic attrs classes #1100

Open
JarnoRFB opened this issue Oct 12, 2021 · 2 comments
Open

Currying support for generic attrs classes #1100

JarnoRFB opened this issue Oct 12, 2021 · 2 comments
Labels
bug Something isn't working

Comments

@JarnoRFB
Copy link

Bug report

I tried out returns, because I was looking for typesafe curry implementation, but I hit a problem with my Generic / Protocol implementing attrs classes.

What's wrong

from typing import TypeVar, Generic

from attr import frozen
from returns.curry import curry

T = TypeVar("T")

@curry
@frozen(kw_only=True)
class Pair(Generic[T]):
    _a: T
    _b: T

p = Pair(b=1)(a=2)
print(p)
TypeError: __init__() missing 1 required keyword-only argument: 'a'

How is that should be

The above code should simply print

Pair(_a=2, _b=1)

This seems to be due to python-attrs/attrs#374

A fix I hacked together could be something like this.

def curry(function: Callable[..., _ReturnType]) -> Callable[..., _ReturnType]:
    import inspect
    if inspect.isclass(function):
        init_signature = Signature.from_callable(function.__init__)
        init_params_without_self = tuple(init_signature.parameters.values())[1:]
        argspec = init_signature.replace(parameters=init_params_without_self).bind_partial()
    else:
        argspec = Signature.from_callable(function).bind_partial()

    def decorator(*args, **kwargs):
        return _eager_curry(function, argspec, args, kwargs)
    return wraps(function)(decorator)

If you are interested in support this admittedly special use case, I could submit a PR.

System information

  • python version: 3.7
  • returns version: 0.17.0
  • mypy version: 0.910
@JarnoRFB JarnoRFB added the bug Something isn't working label Oct 12, 2021
@sobolevn
Copy link
Member

Thanks!

The same would be needed for our mypy plugin.
Also, what about __new__ method?

@JarnoRFB
Copy link
Author

Also, what about new method?

Not exactly sure what you mean, but as far as I understood it, the problem is that by default __new__ get's picked up by Signature.from_callable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Development

No branches or pull requests

2 participants