sqlalchemy-stubs icon indicating copy to clipboard operation
sqlalchemy-stubs copied to clipboard

Implement SQLResult

Open ilevkivskyi opened this issue 7 years ago • 2 comments

A user should be able to annotate an argument/variable that is expected to take rows of a specific table/join/etc. For example:

class BasicData(SQLResult):
    id: int
    name: str

We can also support a Python 2 compatible syntax like for named tuples. This type should be added to an actual tiny runtime package that will be shipped with stubs/plugins. This should be accompanied by at least two plugin hooks:

  • One type analyzer hook that will transform an occurrence BasicData into something like SQLResult[TypedDict(x=int, name=str)] (SQLResult should be declared a subclass of RowProxy)
  • Another hook for attribute access, so that SQLResult will provide both NamedTuple- and TypedDict-like APIs (to match runtime magic).

Note that SQLResult, Iterable[SQLResult] can be used as a more precise result for some functions in https://github.com/dropbox/sqlalchemy-stubs/issues/4.

ilevkivskyi avatar Aug 27 '18 16:08 ilevkivskyi

Alternative idea may be to make RowProxy generic in a single argument that may be only a TypedDict or a NamedTuple. This way we can write:

class BasicData(NamedTuple):
    id: int
    name: str

row: RowProxy[BasicData]

I think we should also support SQLResult[<Table instance>]/RowProxy[<Table instance>] as a shortcut for very common case where a query returns just all columns from a given table.

ilevkivskyi avatar Aug 27 '18 16:08 ilevkivskyi

Just to clarify, this is how it is supposed to be used by an end user:


class BasicData(SQLResult):
    name: str
    id: int

def row_to_some_class(row: BasicData) -> SomeClass:
    name, id = row  # This is OK
    return SomeClass(row.id, row.name)  # Also OK

row = session.query(User.id, User.name).first()
row_to_some_class(row)  # OK

another_row = session.query(User).first()
row_to_some_class(another_row)  # Error, incompatible tuple type because of
                                # fullname and e-mail

ilevkivskyi avatar Aug 27 '18 16:08 ilevkivskyi