pyre-check icon indicating copy to clipboard operation
pyre-check copied to clipboard

Problem defining a type including LiteralString

Open dvarrazzo opened this issue 3 years ago • 0 comments

Hello,

I am introducing LiteralString in psycopg 3: see the literal-string branch. As a final result, functions such as cursor.execute() would require a literal string rather than any string expression.

Running pyre on psycopg codebase found some of the places where regular string were passed to functions accepting LiteralString (https://github.com/psycopg/psycopg/commit/600d6dfaf1366d2eca4486f7686c57da88f2b807 fixes some of them). However, running pyre on a test script using psycopg objects doesn't produce the expected warning.

Drilling down more, I've created this test script:

from typing import Any, Union, TYPE_CHECKING
from typing_extensions import TypeAlias, LiteralString

import psycopg
if TYPE_CHECKING:
    from psycopg import sql

Query: TypeAlias = Union[LiteralString, bytes, "sql.SQL", "sql.Composed"]

def test_query(q: Query) -> None:
    pass

def test_pgq(q: psycopg.abc.Query) -> None:
    pass

def test(s: str):
    conn: psycopg.Connection[Any] = psycopg.connect()
    reveal_type(conn)
    test_query(s)
    test_pgq(s)
    conn.execute(s)

The definition of the Query type is identical to psycopg.abc.Query. However pyre finds some problem in psycopg definition and fails to identify that conn.execute() parameter must be a literal string. Running pyre on the script, results in the warnings:

ƛ Found 3 type errors!
test-literal.py:13:16 Undefined or invalid type [11]: Annotation `psycopg.abc.Query` is not defined as a type.
test-literal.py:18:4 Revealed type [-1]: Revealed type for `conn` is `psycopg.connection.Connection[typing.Any]`.
test-literal.py:19:15 Incompatible parameter type [6]: In call `test_query`, for 1st positional only parameter expected `Union[typing_extensions.LiteralString, bytes, Composed, SQL]` but got `str`.

I would have expected "incompatible parameter" on the test_pgq() and the onn.execute() calls too, similarly to the test_query() call. I understand that the difference is caused by the error at line 12.

What is wrong in the definition in psycopg.abc? Pyre finds hundreds of problems with the psycopg codebase (which is checked with mypy) and at the moment I don't have the goal to make it completely compatible with pyre, but I don't see any specific problem there and it would be nice if pyre+psycopg users could make use of the LiteralString check.

Cheers!

dvarrazzo avatar Jun 30 '22 14:06 dvarrazzo