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

Preferring explicit Incomplete for unannotated arguments #8472

Closed
hauntsaninja opened this issue Aug 2, 2022 · 6 comments
Closed

Preferring explicit Incomplete for unannotated arguments #8472

hauntsaninja opened this issue Aug 2, 2022 · 6 comments
Labels
project: policy Organization of the typeshed project

Comments

@hauntsaninja
Copy link
Collaborator

hauntsaninja commented Aug 2, 2022

This came up in #8458

Currently CONTRIBUTING.md states:

Included functions and methods must list all arguments, but the arguments can be left unannotated. Do not use Any to mark unannotated arguments or return values.

Leaving things unannotated helps distinguish from cases where we actually need Any. But we didn't have Incomplete when that was written. Incomplete accomplishes the same thing and is easier to grep for, e.g. #4641 mentions grepping for incomplete as a good way to find potential areas to contribute.

@hauntsaninja hauntsaninja added the project: policy Organization of the typeshed project label Aug 2, 2022
@AlexWaygood
Copy link
Member

For me, a key factor here is pyright. Pyright infers an unannotated argument or return type as Unknown, which is a different type to Any. With looser pyright settings, Unknown is treated similarly to Any by pyright, but with stricter pyright settings enabled, Unknown is treated much more severely than Any by pyright.

Other type checkers could plausibly also introduce similar distinctions in the future between types explicitly annotated with Any and those which are explicitly left unannotated.

_typeshed.Incomplete, on the other hand, is a simple alias to Any, so (while greppability and readability is greatly improved for humans over Any), pyright can't treat it specially in the same way it treats unannotated objects.

@hauntsaninja
Copy link
Collaborator Author

Oh, interesting. Agreed that we should prioritise type checker results over usability for ourselves.

That said, there's a quick and easy hack that seems to get us best of both worlds:

diff --git a/stdlib/_typeshed/__init__.pyi b/stdlib/_typeshed/__init__.pyi
index 89ca9d81..3a4840b1 100644
--- a/stdlib/_typeshed/__init__.pyi
+++ b/stdlib/_typeshed/__init__.pyi
@@ -34,7 +34,7 @@ AnyStr_co = TypeVar("AnyStr_co", str, bytes, covariant=True)  # noqa: Y001
 # isn't possible or a type is already partially known. In cases like these,
 # use Incomplete instead of Any as a marker. For example, use
 # "Incomplete | None" instead of "Any | None".
-Incomplete: TypeAlias = Any
+from ._does_not_exist import Incomplete as Incomplete  # type: ignore
 
 # stable
 class IdentityFunction(Protocol):

Screen Shot 2022-08-02 at 1 12 49 PM

Alternatively, we could maybe ask Eric to bless Incomplete

@Akuli
Copy link
Collaborator

Akuli commented Aug 2, 2022

Mypy has different behaviour for unannotated arguments too, although it's more complicated:

  • If anything at all in a function is annotated (some argument or the return type), the function is "typed" and everything unannotated behaves as if it was Any.
  • If nothing is annotated, arguments behave as if they were Any typed, but the function is also marked as being "untyped", and using it at all will generates errors by default if you use --strict.

@srittau
Copy link
Collaborator

srittau commented Aug 2, 2022

Apart from typechecker issues, I have a slight preference for unannotated items:

  • I think it's a bit easier to manually spot an unannotated argument or return type than with "just another annotation".
  • It doesn't require an import.
  • Currently stubgen generates unannotated fields, although this could be changed, of course.

That said, I don't have strong feelings either way.

@AlexWaygood
Copy link
Member

Alternatively, we could maybe ask Eric to bless Incomplete

Since, as @Akuli points out, we'd probably want mypy to bless Incomplete as well, that sounds kinda like you're proposing writing a PEP ;)

@hauntsaninja
Copy link
Collaborator Author

Okay, sounds like there's maybe too much going on here to mess with + no one else really seems in favour of explicit Incomplete

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
project: policy Organization of the typeshed project
Projects
None yet
Development

No branches or pull requests

4 participants