with conn.cursor(row_factory=my_row_factory) as cur:
cur.execute("select 1")
reveal_type(cur)
# Revealed type is 'psycopg3.cursor.Cursor[R`-1]'
r = cur.fetchone()
reveal_type(r)
# Revealed type is 'Union[R`-1, None]'
The definition of RowMaker and RowFactory protocols needs two distinct
type variable because the former is covariant on Row (using 'Row_co'
type variable) and the latter is invariant on Row.
In Cursor.__init__(), row_factory argument is now required as we remove
its default value 'tuple_row'; this is helpful in order to keep Cursor
definition generic on Row, which would be more difficult when specifying
a concrete RowFactory by default binding Row to Tuple.
The Connection is not (yet) generic on Row, so we use RowFactory[Any].
Still, in cursor() methods, we get a fully typed Cursor value when a
row_factory argument is passed. We add two overloaded variants of these
cursor() methods depending on whether row_factory is passed or not (in
the former case, we return a Cursor[Row], in the latter case, a
Cursor[Any]).
A noticeable improvement is that we no longer need to explicitly declare
or ignore types in Transformer's load_row() and load_rows() as this is
not correctly inferred. Similarly, type annotations are not needed
anymore in callers of these methods (Cursor's fetch*() methods).
In TypeInfo's fetch*() method, we can drop superfluous type annotations.