sqlalchemy2-stubs
sqlalchemy2-stubs copied to clipboard
no implementation for hybrids available
re: #170
this worked for sqlalchemy-stubs, but does not seem to work here
POC from https://github.com/dropbox/sqlalchemy-stubs/issues/98#issuecomment-781794732
from typing import Any
from typing import Callable
from typing import Generic
from typing import Optional
from typing import overload
from typing import Type
from typing import TypeVar
from typing import Union
from sqlalchemy import column
from sqlalchemy import Integer
from sqlalchemy.sql import ColumnElement
_T = TypeVar("_T")
class hybrid_property(Generic[_T]):
def __init__(
self,
fget: Callable[[Any], _T],
expr: Callable[[Any], ColumnElement[_T]],
):
self.fget = fget
self.expr = expr
@overload
def __get__(
self, instance: None, owner: Optional[Type[Any]]
) -> "ColumnElement[_T]":
...
@overload
def __get__(self, instance: object, owner: Optional[Type[Any]]) -> _T:
...
def __get__(
self, instance: Union[object, None], owner: Optional[Type[Any]] = None
) -> Any:
if instance is None:
return self.expr(owner)
else:
return self.fget(instance)
def expression(
self, expr: "Callable[[Any], ColumnElement[_T]]"
) -> "hybrid_property[_T]":
return hybrid_property(self.fget, expr)
class MyClass:
def my_thing_inst(self) -> int:
return 5
def my_thing_expr(cls) -> "ColumnElement[int]":
return column("five", Integer)
my_thing = hybrid_property(my_thing_inst, my_thing_expr)
mc = MyClass()
int_value: int = mc.my_thing
expr: ColumnElement[int] = MyClass.my_thing
sure :)
The normal definition does not work with mypy:
import sqlalchemy as sa
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import registry
R: registry = registry()
@R.mapped
class SomeModel:
__tablename__ = "some_model"
a = sa.Column(sa.Float, primary_key=True)
@hybrid_property
def hp(self) -> float:
return abs(self.a) / 2 if self.a else 0
@hp.setter # type:ignore[no-redef]
def hp(self, value: float) -> None:
self.a = value * 2
@hp.deleter # type:ignore[no-redef]
def hp(self):
self.a = None
@hp.expression # type:ignore[no-redef]
def hp(cls) -> sa.sql.ColumnElement[sa.Float]:
return sa.func.abs(cls.a) / 2
obj = SomeModel()
obj.hp + 1
this will error with:
test\files\hybrid.py:31: error: Unsupported operand types for + ("Callable[..., Any]" and "int") [operator]
This looks like a mypy bug, since removing @hp.setter and the other @hp definition it does better, but it still fails to get the float:
test\files\hybrid.py:15: error: Unsupported operand types for / ("object" and "int") [operator]
I've opened a pr, but it does not work. Can you take a look?