Skip to content

Commit e769c94

Browse files
hydrargyrumCaselIT
andauthored
hybrid.pyi: decorators should return the same type (#164)
* hybrid.pyi: decorators should return the same type This code triggered warnings: class SomeModel(...): @hybrid_property def stuff(self): ... @properties.setter def stuff(self, value): ... obj = SomeModel() obj.stuff = ... The same is done in "python/typeshed" repository in "stdlib/builtins.pyi" in class property. * reformat code * add hybrid tests Co-authored-by: Federico Caselli <cfederico87@gmail.com>
1 parent 8457a90 commit e769c94

File tree

5 files changed

+45
-10
lines changed

5 files changed

+45
-10
lines changed

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ install_requires =
3636
incremental = True
3737
strict = True
3838
warn_unused_ignores = False
39-
39+
show_error_codes = True
4040
plugins = sqlalchemy.ext.mypy.plugin
4141

4242

sqlalchemy-stubs/ext/hybrid.pyi

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from typing import Any
2+
from typing import Callable
23
from typing import Optional
34

45
from .. import util as util
@@ -16,7 +17,7 @@ class hybrid_method(interfaces.InspectionAttrInfo):
1617
def __init__(self, func: Any, expr: Optional[Any] = ...) -> None: ...
1718
def __get__(self, instance: Any, owner: Any): ...
1819
expr: Any = ...
19-
def expression(self, expr: Any): ...
20+
def expression(self, expr: Any) -> hybrid_method: ...
2021

2122
class hybrid_property(interfaces.InspectionAttrInfo):
2223
is_attribute: bool = ...
@@ -41,12 +42,16 @@ class hybrid_property(interfaces.InspectionAttrInfo):
4142
def __delete__(self, instance: Any) -> None: ...
4243
@property
4344
def overrides(self): ...
44-
def getter(self, fget: Any): ...
45-
def setter(self, fset: Any): ...
46-
def deleter(self, fdel: Any): ...
47-
def expression(self, expr: Any): ...
48-
def comparator(self, comparator: Any): ...
49-
def update_expression(self, meth: Any): ...
45+
def getter(self, fget: Callable[[Any], Any]) -> hybrid_property: ...
46+
def setter(self, fset: Callable[[Any, Any], None]) -> hybrid_property: ...
47+
def deleter(self, fdel: Callable[[Any], None]) -> hybrid_property: ...
48+
def expression(self, expr: Callable[[Any], Any]) -> hybrid_property: ...
49+
def comparator(
50+
self, comparator: Callable[[Any], Any]
51+
) -> hybrid_property: ...
52+
def update_expression(
53+
self, meth: Callable[[Any, Any], Any]
54+
) -> hybrid_property: ...
5055

5156
class Comparator(interfaces.PropComparator):
5257
property: Any = ...

sqlalchemy-stubs/sql/operators.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ from typing import Callable
2222
from typing import Generic
2323
from typing import NoReturn
2424
from typing import Optional
25+
from typing import overload
2526
from typing import Type
2627
from typing import TypeVar
27-
from typing import overload
2828
from typing import Union
2929

3030
from . import sqltypes

sqlalchemy-stubs/sql/schema.pyi

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ from .elements import ClauseElement
2929
from .elements import ColumnClause
3030
from .elements import ColumnElement
3131
from .elements import TextClause
32-
from .functions import FunctionElement
3332
from .events import DDLEvents
3433
from .selectable import TableClause
3534
from .. import util

test/files/hybrid.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import sqlalchemy as sa
2+
from sqlalchemy.ext.hybrid import hybrid_property
3+
from sqlalchemy.orm import registry
4+
5+
R: registry = registry()
6+
7+
8+
@R.mapped
9+
class SomeModel:
10+
__tablename__ = "some_model"
11+
a = sa.Column(sa.Float, primary_key=True)
12+
13+
@hybrid_property
14+
def hp(self) -> float:
15+
return abs(self.a) / 2 if self.a else 0
16+
17+
@hp.setter # type:ignore[no-redef]
18+
def hp(self, value: float) -> None:
19+
self.a = value * 2
20+
21+
@hp.deleter # type:ignore[no-redef]
22+
def hp(self):
23+
self.a = None
24+
25+
@hp.expression # type:ignore[no-redef]
26+
def hp(cls) -> sa.sql.ClauseElement:
27+
return sa.func.abs(cls.a) / 2
28+
29+
30+
obj = SomeModel()
31+
obj.hp

0 commit comments

Comments
 (0)