Closed dimaqq closed 3 weeks ago
Pyright is working as intended here, so I don't consider this a bug.
The reveal_type
function is specified here in the typing spec. The actual value of the string that a type checker emits here is type-checker specific. It is not recommended that you use this string for test purposes. The assert_type
function was added for this purpose. It accepts a type expression as a second argument, and all type checkers should interpret type expressions in the same way, according to the typing spec.
Granted, assert_type
is useful in some cases.
But seemingly not in others.
For example, how can I assert that a specific thing can be called in a specific way, when it's not necessarily a function?
assert_type(str.lower, Callable[[str], str])
fails with "assert_type" mismatch: expected "(str) -> str" but received "(self: str) -> str" (reportAssertTypeFailure)
and there's no way to inject self:
into the Callable signature is there?
For the time being, I'm using a dummy variable as a work-around:
dummy1: Callable[[str], str] = str.lower
dummy2: Callable[[str], str] = some_callable_object
dummy3: Callable[[str], str] = some_callable_module.__call__
I can use functions directly;
I can use simple callable objects directly as well;
But not a module that extends ModuleType
and implements __call__
, for that I have to slap __call__
at the end.
Is this the way, or there perhaps a better way?
assert_type
tests for type equivalency. If you want to test for assignability, you can assign the value to a variable with a declared type, as you've done above with dummy1
, etc.
For more complex cases that involve structural types, you can define a protocol class in your tests. The protocol should define the attributes and methods that must be present in the assigned object.
Describe the bug I'm trying to use
reveal_type
to check random callables.reveal_type(some_object_with__call__)
returns the class name, and I need theCallable[...]
signature.I can use
reveal_type(some_object.__call__)
on callable objects.For pure functions it's the inverse.
I can use
reveal_type(pure_func)
and I cannot usereveal_type(pure_func.__call__)
, even they behave equivalently at runtime.Code or Screenshots If possible, provide a minimal, self-contained code sample (surrounded by triple back ticks) to demonstrate the issue. The code should define or import all referenced symbols.
The result:
Tested with pyright v1.1.370 and v1.1.377
Suggestion
I wonder if it would be in line with Python and the typing PEP that defines
reveal_type
, if revealed type for the callable and callable.call would be the same, at least in cases where these are same at run time.