Closed
Description
In psycopg 3 we have generators returning a final result, which sometimes is None, sometimes a different object. We also have some consumers of these generators, which wait for I/O completion according to the values yielded by the generators and finally return the final generator result.
Something similar can be represented with the following code:
from typing import Any, Generator, TypeAlias, TypeVar
RV = TypeVar("RV")
PQGen: TypeAlias = Generator[Any, Any, RV]
def str_gen() -> PQGen[str]:
yield 10
return "abc"
def none_gen() -> PQGen[None]:
yield 10
return None
def wait(gen: PQGen[RV]) -> RV:
try:
while True:
next(gen)
except StopIteration as ex:
rv: RV = ex.args[0] if ex.args else None
return rv
print(f"{wait(str_gen())=}")
print(f"{wait(none_gen())=}")
If a generator returns None
, the StopIteration.args
tuple will empty, which is accounted for in the wait()
's return statement (removing the check will cause an IndexError on wait(none_gen())
). However, since Mypy 1.12, the return statement in the wait returns an error:
bug_mypy.py:24: error: Incompatible types in assignment (expression has type "Any | None", variable has type "RV") [assignment]
This wasn't reported as error in Mypy 1.11