-
-
Notifications
You must be signed in to change notification settings - Fork 33.9k
gh-127750: Fix annotations in singledispatchmethod signature tests #143571
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
base: main
Are you sure you want to change the base?
Conversation
… the right params See https://github.com/python/cpython/pull/130309/changes#r2663516538. These functions don't annotate parameters for values used in single-dispatching (`item`), they annotate parameters one later (`arg`). This being legal relies on a bug -- pythonGH-84644, which is that `singledispatch` doesn't verify the annotation is on the "first" parameter. I think these functions should look like ```diff @functools.singledispatchmethod - def func(self, item, arg: int) -> str: + def func(self, item: int, arg) -> str: return str(item) @func.register - def _(self, item, arg: bytes) -> str: + def _(self, item: bytes, arg) -> str: return str(item) ``` (and signature tests updated accordingly) In practice, it doesn't matter how you annotate `func` here, because it's a default callback. But what matters is that any function passed to `register()` annotates the target parameter (always first positional in `singledispatch` and always second positional in `singledispatchmethod` (unless staticmethod, then the first) etc.) for the value to single-dispatch on; not some other, unrelated parameter (or return type, as presented in pythonGH-84644). Let's have a class with the same registree signature as these from the test: ```py class A: @functools.singledispatchmethod def func(self, item, arg: int) -> str: return 'argint' @func.register def _(self, item, arg: bytes) -> str: return 'argbytes' a = A() print(a.func(b'', 1)) ``` For this code, the output would be `argbytes`, even though `arg` is an integer `1`.
| def m(self, item: int, arg) -> str: | ||
| return str(item) | ||
| @classmethod | ||
| def cm(cls, item, arg: int) -> str: | ||
| def cm(cls, item: int, arg) -> str: | ||
| return str(item) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can remove these methods if they are not used.
| return str(item) | ||
| @functools.singledispatchmethod | ||
| def func(self, item, arg: int) -> str: | ||
| def func(self, item: int, arg) -> str: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leave item not annotated here. This is the generic variant. But keep annotation for arg, so it will be seen in the result.
| return str(item) | ||
| @func.register | ||
| def _(self, item, arg: bytes) -> str: | ||
| def _(self, item: bytes, arg) -> str: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep annotation for arg.
| def _(self, item: bytes, arg) -> str: | |
| def _(self, item: int, arg: bytes) -> str: |
See test_signatures above. These examples should be similar.
Follow-up to gh-130309.
See https://github.com/python/cpython/pull/130309/changes#r2663516538.
Details
These functions don't annotate parameters for values used in single-dispatching (
item), they annotate parameters one later (arg).This being legal relies on a bug -- GH-84644, which is that
singledispatchdoesn't verify the annotation is on the "first" parameter.In practice, it doesn't matter how you annotate
funchere, because it's a default callback. But what matters is that any function passed toregister()annotates the target parameter (always first positional insingledispatchand always second positional insingledispatchmethod(unless staticmethod, then the first) etc.) for the value to single-dispatch on; not some other, unrelated parameter (or return type, as presented in GH-84644).Let's have a class with the same registree signature as these from the test:
For this code, the output would be
argbytes, even thoughargis an integer1.