sqlalchemy-stubs
sqlalchemy-stubs copied to clipboard
Implement SQLResult
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
BasicDatainto something likeSQLResult[TypedDict(x=int, name=str)](SQLResultshould be declared a subclass ofRowProxy) - Another hook for attribute access, so that
SQLResultwill provide bothNamedTuple- andTypedDict-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.
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.
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