Skip to content

Commit 60c31f9

Browse files
authored
improve op() typing (#159)
1 parent 4631862 commit 60c31f9

File tree

2 files changed

+35
-12
lines changed

2 files changed

+35
-12
lines changed

sqlalchemy-stubs/sql/operators.pyi

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ from typing import NoReturn
2424
from typing import Optional
2525
from typing import Type
2626
from typing import TypeVar
27+
from typing import overload
2728
from typing import Union
2829

2930
from . import sqltypes
@@ -34,13 +35,15 @@ from .type_api import TypeEngine
3435
_F = TypeVar("_F", bound=Callable[..., Any])
3536
_T = TypeVar("_T")
3637
_TE = TypeVar("_TE", bound=TypeEngine[Any])
38+
_OTE = TypeVar("_OTE", bound=TypeEngine[Any])
39+
_CE = TypeVar("_CE", bound=ClauseElement)
3740

3841
div = truediv
3942

40-
class Operators:
41-
def __and__(self, other: Any) -> ClauseElement: ...
42-
def __or__(self, other: Any) -> ClauseElement: ...
43-
def __invert__(self) -> ClauseElement: ...
43+
class Operators(Generic[_CE]):
44+
def __and__(self, other: Any) -> _CE: ...
45+
def __or__(self, other: Any) -> _CE: ...
46+
def __invert__(self) -> _CE: ...
4447
def op(
4548
self,
4649
opstring: Any,
@@ -52,13 +55,9 @@ class Operators:
5255
) -> Callable[[Any], ClauseElement]: ...
5356
def bool_op(
5457
self, opstring: Any, precedence: int = ...
55-
) -> Callable[[Any], ClauseElement]: ...
56-
def operate(
57-
self, op: Any, *other: Any, **kwargs: Any
58-
) -> ClauseElement: ...
59-
def reverse_operate(
60-
self, op: Any, other: Any, **kwargs: Any
61-
) -> ClauseElement: ...
58+
) -> Callable[[Any], _CE]: ...
59+
def operate(self, op: Any, *other: Any, **kwargs: Any) -> _CE: ...
60+
def reverse_operate(self, op: Any, other: Any, **kwargs: Any) -> _CE: ...
6261

6362
class custom_op:
6463
__name__: str = ...
@@ -83,7 +82,23 @@ class custom_op:
8382
def __hash__(self) -> int: ...
8483
def __call__(self, left: Any, right: Any, **kw: Any) -> ClauseElement: ...
8584

86-
class ColumnOperators(Operators, Generic[_TE]):
85+
class ColumnOperators(Operators[ColumnElement[_TE]], Generic[_TE]):
86+
# op requires custom override
87+
@overload
88+
def op(
89+
self,
90+
opstring: Any,
91+
precedence: int = ...,
92+
is_comparison: bool = ...,
93+
) -> Callable[[Any], ColumnElement[_TE]]: ...
94+
@overload
95+
def op(
96+
self,
97+
opstring: Any,
98+
precedence: int = ...,
99+
is_comparison: bool = ...,
100+
return_type: Union[Type[_OTE], _OTE] = ...,
101+
) -> Callable[[Any], ColumnElement[_OTE]]: ...
87102
timetuple: Any = ...
88103
# TODO https://github.com/sqlalchemy/sqlalchemy2-stubs/issues/114
89104
# Can we also limit the "other" parameter? Most should be

test/files/operators.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from sqlalchemy.sql import column, ColumnElement
2+
from sqlalchemy.types import Integer, BigInteger, String
3+
4+
col = column("flags", Integer)
5+
a: "ColumnElement[Integer]" = col.op("&")(1)
6+
b: "ColumnElement[Integer]" = col.op("&", return_type=Integer)(1)
7+
c: "ColumnElement[String]" = col.op("&", return_type=String)(1)
8+
d: "ColumnElement[BigInteger]" = col.op("&", return_type=BigInteger)(1)

0 commit comments

Comments
 (0)