-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Add decorator for delegating arguments #5559
Conversation
Thanks for the PR! TBH I am not sure I like this idea. I understand the problem, but current approach has several problems:
I would prefer just allow using |
Thanks for your feedback. Here are my counterarguments:
It is meant for a particular problem, but I think it's a problem that appears often (as was pointed out repeatedly in the issue) and is worth solving on its own.
Can you elaborate how it might be confusing? I don't see it. Is it more confusing than, say, functools.wraps? I think it's fairly simple to explain the concept. Start with the simplest, most common case: @delegate(foo)
def bar(*args, **kwargs): means that
Is your concern now about implementation or still about the concept? In any case I will have to defer to you and other people who understand how mypy works, but if
Is it important to check that it does? I don't see much potential for introducing errors if there's no delegation.
This doesn't work in general. If I have: def bar(*args, **kwargs):
foo(*args, **kwargs)
def foo(a: int, b: int = 0, c: int = 1): ... Then
How would I do that with Moreover, this is about more than type checking. I use PyCharm, as do many other people. If I encounter a call to Suppose I want to see what the parameters mean. Typically my next step would be to Ctrl+click on It was pointed out in the issue that the decorator aids readability. I think it's useful to know that Personally I often can't be bothered to add type annotations to my own code. I certainly don't want to annotate kwargs with a TypedDict. |
Contradiction is not an argument :-) (I don't know if you are familiar, this is a reference to a classic sketch). Seriously however mypy (== Python static type system here) is already complex. I would avoid any ad-hoc solutions, unless there are no other way to solve it.
It looked confusing to me, it was necessary to read the original issue to understand semantics.
Hm, maybe then a better option would be to allow using callback protocols to re-use function signatures? For example, class DoStuff(Protocol):
def __call__(a: int, b: int = ..., c: int = ...) -> None: ...
f: DoStuff
def f(*args, **kwargs):
...
g: DoStuff
def g(*args, **kwargs):
f(*args, **kwargs)
Some other people may say similar about To summarize, it was way too soon to make a PR for this without agreeing at least on large-scale design. I think it is better to return back to the issue. |
Well I'd expect that because at the moment there is no other documentation. I didn't feel the need to write any at this stage because (1) the PR was still tentative, and (2) I expected people to read the issue since it contains other important information. I don't think it should be a requirement that this decorator is so self-evident that it can be understood without reading anything.
Your example means that the body of A decorator also allows attaching information which can be retrieved at runtime by functions like
Well if they say the same it would probably be for different reasons. I'm saying I don't want the effort, clutter, and repetition of a verbose type annotation (and this applies even more to
Presumably it doesn't need a PEP just to get into
The discussion on the issue had stopped and I didn't think there was anything to add. People seemed to think it was a good idea and it didn't seem very complicated. I just thought no one was willing to implement it, so I decided to do it myself. Doing so made me aware of some of the nitty gritty issues which I thought were worth discussing. I also wanted to share the work I had done so far and give people an opportunity to checkout the branch and play with the decorator themselves rather than just imagine what it would do. Had I not done any of this then the issue would still be dead and we wouldn't be debating alternatives. I'm not sure what damage you think a PR does, since a PR is not that different from a non-PR issue and we're having plenty of valuable discussion here. I'm guessing perhaps you're worried people will be distracted by less important details in the code? In any case I will take your advice and put a proper proposal in the issue. For now the only comments I will make here will be in response to other comments here. |
I think that this might be a useful feature to have in This at least partially addresses a common use case that is a real pain point. However, I agree with @ilevkivskyi that we should continue to discuss the design of the feature a bit more in the original issue, though this PR is useful in getting the ball rolling. (I can't promise that the feature will be accepted soon, but I see some hope.) |
Thanks for investing your time in this, and sorry if I sounded harsh. I just think this needs more thought before moving forward, I will add some comments in the issue. |
together with allowing the same for the add_int: Callable[[int, int], int]
def add_int(a,b):
return a + b is also more in line with how functional languages like Haskell annotate functions. See also #1641 |
@SaschaSchlemmer as others suggested, keep discussion in the issue python/typing#270. I suggest copying this comment there. |
Closing, since the underlying issue has been closed following the acceptance of PEP 612. |
This is an attempt to implement python/typing#270. (I would suggest for now only reading the 2016 comments, after that it turns in a different direction which is for now irrelevant)
I've never contributed to this project before so I'm hesitant to try and do it all at once, hence I'm presenting this first draft to see if I'm on the right track (am I?) and ask some questions. If someone thinks I should just go ahead and fill in the remaining gaps as I see fit, I can do that too.
I've put this in mypy_extensions because it seems like the appropriate place to start (is there an alternative?) but eventually I would love to see this in the standard library. The applications go well beyond type checking, for example IDEs could use it for parameter hints and autocompletion. However they're not likely to implement that unless this is in the standard library.
Two major open questions are:
delegate
and also other decorators? In most cases mypy doesn't support decent type checking with other decorators, so if we took them into account the result ofdelegate
would either be lost or trivial. Even if there is a decorator that changes the signature in a way that mypy can understand, reading the function definition with the decorators and trying to figure out the correct signature may be very confusing for a reader. Therefore I'm considering ignoring all other decorators when determining the signature of the function -delegate
has the final say. That also doesn't sound great. Thoughts?*args
be delegated? Currently only**kwargs
are handled, and they are replaced by any keyword arguments in the base function (whether optional, required, or variadic). I'm thinking*args
should similarly be replaced by any positional arguments in the base function. Thoughts?