-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
Allow @overload outside stubs #1136
Comments
I think it can be done with typevars: AnyStr is defined as
TypeVar('AnyStr', str, bytes). It's not special in any way though. You
should be able to define your own typevar as OptAnyStr =
TypeVar('OptAnyStr', None, str, bytes).
I think we're not in principle against eventually considering the .pyi and
.py files together, but it would be a lot of work to add this to mypy, and
your use case (@overload) is pretty much the only one.
(I vaguely recall another issue discussing this, but I can't find it here.
Maybe it's in the typeshed repo or even in typehinting, which is for PEP
484 and the PyPI version of typing.py.)
|
I'm sure there's a better way to support |
I don't see how I'd be happy with a non-stub way to express overloads (and would prefer it to a requirement for separate stub files to use this feature). The Overloads that can't be satisfied with The interaction between stub files and source files is generally awkward. I just realized that the type annotations I've been adding to Tornado source files aren't actually used outside those files because there are stubs for Tornado in typeshed ( |
Wow, you're really bleeding edge here. Great to see you exploring this and
helping us find the gray areas.
Short term, the only solution I can think of for utf8() would be to move it
to a separate file and have a stub for that file containing the @overload
declarations. That's awkward, but it can work with today's mypy.
Longer term, this example suggests that we really need to thing harder
about allowing @overload in non-stub files. That's a PEP 484 change and we
should discuss it on python-dev, but we might as well first prepare a
proposal. I've started laying out the problem in
python/typing#175 -- let's continue the
discussion there.
Regarding inline annotations vs typeshed, that's another unsolved problem.
I've opened python/typeshed#52 for it, but I
frankly don't know how to solve it.
Please join those discussions!
|
Actually, as I wrote in python/typeshed#52,
the stubs vs. real code problem is easily solved by setting MYPYPATH
to include the version of Tornado you're using -- the stubs in
typeshed are searched last.
The solution for @overload utf8() is to change the PEP, which I will do shortly.
|
The PEP is now updated. This issue should stay open until it's been implemented in mypy. |
What's the idea for how this would actually work in a user program? After all I think there needs to be just one function body, that mypy will type check with each of the overloaded types. Straw-man syntax in a minimal example: @overload
def f(x: str) -> str: ... # literal ...
@overload
def f(x: int) -> int:
return x At runtime |
Oh interesting, there's actually an example of the expected (but not yet implemented) syntax in the docstring for @overload
def utf8(value: None) -> None: ...
@overload
def utf8(value: bytes) -> bytes: ...
@overload
def utf8(value: str) -> bytes: ...
def utf8(value):
# implementation goes here |
Yeah, that's how it should work. The overloads are for the type checker, the final non-overloaded function is for the interpreter. If the latter has annotations it should be checked as a regular function; separately mypy might want to check that it can handle all the overloads; when type-checking a call, only the overloads should be considered. |
I was looking into implementing this. From what I can see, the example above (
The error on line 9 can be fixed by adding an The errors about overlapping signatures are because Is there a reason for not putting the implementation in the final |
I guess the reason for the "overlap" errors is that that example can only
work with --strict-optional.
If the final overload also had the implementation, it would be hard to
type-check its body. Also we want to syntactically distinguish between
stubs (where there is no implementation) and non-stubs (where there must be
an implementation).
|
@sixolet Adding you to this issue for coordination purposes. |
Fixes #1136. - The implementation must directly follow all the overloads - The implementation is typechecked exactly according to its own declared types - Indicates an error if the implementation's argument list is not more general than every override variant - Also indicates an error if the implementation's return type is also not more general than the return type of every override variant It also limits overloads to the decorators that are specifically geared towards providing overload-type functionality -- @overload, but also @Property and its cousins @funcname.setter and @funcname.deleter. All other decorators are treated purely as decorators, and now provide redefinition errors if you repeat a function definition with them, instead of errors about an overload you probably did not mean.
It doesn't. Guido was referring to python/typeshed#1136 (on typeshed tracker) |
Although 0.520-dev (GitHub master) does seem to handle #2305... Maybe that's because installing MyPy from GitHub master requires preparing the latest typeshed? |
@ilevkivskyi can you clarify? |
mypy master is synced with typeshed every two-three days. PR python/typeshed#1136 was merged more than two months ago. |
Mypy does not consider the stub file for the module it is currently type-checking (and doing so was apparently considered and rejected recently). However,
@overload
as defined in the PEP is only allowed to appear in stubs, which implies a requirement for type checkers to consider a module's own stubs when type checking it. Otherwise, the ability to type check a module which defines an overloaded function is limited.My motivating example:
This could be expressed as
def utf8(s: Optional[AnyStr]) -> Optional[bytes]
, but I'm trying to capture the fact that if the argument is not None then the result is also guaranteed not to be None, so it doesn't introduce unnecessaryOptional
-ness. (Is there a way to express this with aTypeVar
? I don't see one). I can put the overloads in a stub for the benefit of external callers of this module, but then I need to put all the type information for this module in the stub and can't type check it internally (I could duplicate all the non-overload type info in the module itself and get partial coverage). I could also put overloaded functions in their own tiny modules to minimize the impact, but that just feels silly.The text was updated successfully, but these errors were encountered: