Some thoughts:
- AwaitableGenerator
I think it’s still cleaner if this class doesn’t exist in typeshed; @type_check_only
functions are confusing for users and ideally limited to private implementation details. But I agree that the existence of the @type_check_only
decorator makes it less urgent to move.
(Minor correction: it’s in typing
, not builtins
.)
- function
I think having a name in builtins that doesn’t actually exist is confusing for users, so I’d strongly prefer to get this out of the builtins namespace.
currently the two definitions differ slightly, BTW
The current differences are:
__kwdefaults__
has | None
in its type on FunctionType but not function. This seems like an oversight we should fix.
__new__
is missing on function but present on FunctionType. Again, this should probably be fixed.
__call__
is also missing on function but present on FunctionType. Of course, functions really are callable, but it’s typed as (*args: Any, **kwargs: Any) -> Any
, and I think if we add that to function mypy will start thinking any function can be called with any arguments.
__get__
is typed differently, with some comments about how mypy special-cases the descriptor.
Ideally we should resolve these differences and just use types.FunctionType
. (Edit: removed two in https://github.com/python/typeshed/pull/14094 .) One practical issue is that stubs just use def
for all functions, but builtin functions are not in fact instances of types.FunctionType
, and don’t have some of the same attributes.
This leads pyright to accept the following program, which fails at runtime (because len
is a builtin function and doesn’t have a __defaults__
attribute):
def f(x: function):
print(x.__defaults__)
f(len)
Ideally this should be fixed so we represent the runtime objects more precisely, but it doesn’t feel high priority.
- NamedTuple
I think ideally we’d have NamedTuple as a function in the stub to represent the runtime more precisely, but I’m fine with the other solutions suggested in this thread.
- Long-term plan to stop relying on
_typeshed
One motivation for doing this is that the current type checker internal classes appear to be tuned for mypy in a way that doesn’t necessarily translate to other type checkers. For example, typing._TypedDict has several comments talking about how things have to be a certain way for a mypy plugin to work correctly.
Typeshed should ideally be type checker-agnostic, not tuned to the oddities of particular type checkers. If we kept typing._TypedDict
in typeshed, how would we know that the implementation is “correct” if different type checkers might interpret it in different ways?