Skip to content

Commit c1545b7

Browse files
committed
Fix most stubtest_allowlist entries in SQLAlchemy
1 parent 99ea07a commit c1545b7

File tree

16 files changed

+322
-1245
lines changed

16 files changed

+322
-1245
lines changed

stubs/SQLAlchemy/@tests/stubtest_allowlist.txt

Lines changed: 23 additions & 1151 deletions
Large diffs are not rendered by default.

stubs/SQLAlchemy/sqlalchemy/dialects/mssql/base.pyi

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,6 @@ class MSExecutionContext(default.DefaultExecutionContext):
197197
@property
198198
def rowcount(self): ...
199199
def handle_dbapi_exception(self, e) -> None: ...
200-
def get_result_cursor_strategy(self, result): ...
201200
def fire_sequence(self, seq, type_): ...
202201
def get_insert_default(self, column): ...
203202

stubs/SQLAlchemy/sqlalchemy/dialects/postgresql/base.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ class PGCompiler(compiler.SQLCompiler):
163163
class PGDDLCompiler(compiler.DDLCompiler):
164164
def get_column_specification(self, column, **kwargs): ...
165165
def visit_check_constraint(self, constraint): ...
166+
def visit_foreign_key_constraint(self, constraint) -> str: ... # type: ignore[override] # Different params
166167
def visit_drop_table_comment(self, drop): ...
167168
def visit_create_enum_type(self, create): ...
168169
def visit_drop_enum_type(self, drop): ...

stubs/SQLAlchemy/sqlalchemy/engine/interfaces.pyi

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ class ExecutionContext:
116116
def pre_exec(self) -> None: ...
117117
def get_out_parameter_values(self, out_param_names) -> None: ...
118118
def post_exec(self) -> None: ...
119-
def get_result_cursor_strategy(self, result) -> None: ...
120119
def handle_dbapi_exception(self, e) -> None: ...
121120
def should_autocommit_text(self, statement) -> None: ...
122121
def lastrow_has_defaults(self) -> None: ...

stubs/SQLAlchemy/sqlalchemy/event/base.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class _Dispatch:
1212
class _EventMeta(type):
1313
def __init__(cls, classname, bases, dict_) -> None: ...
1414

15-
class Events:
15+
class Events(metaclass=_EventMeta):
1616
dispatch: Any
1717

1818
class _JoinedDispatcher:

stubs/SQLAlchemy/sqlalchemy/orm/collections.pyi

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
from _typeshed import Incomplete
2-
from typing import Any
2+
from collections.abc import Iterable, Mapping
3+
from typing import Any, TypeVar, overload
4+
from typing_extensions import Literal, SupportsIndex
5+
6+
from ..orm.attributes import Event
7+
from ..util.langhelpers import _symbol, symbol
8+
9+
_T = TypeVar("_T")
10+
_KT = TypeVar("_KT")
11+
_VT = TypeVar("_VT")
312

413
class _PlainColumnGetter:
514
cols: Any
@@ -81,12 +90,38 @@ class CollectionAdapter:
8190
def fire_remove_event(self, item, initiator: Incomplete | None = ...) -> None: ...
8291
def fire_pre_remove_event(self, initiator: Incomplete | None = ...) -> None: ...
8392

84-
class InstrumentedList(list[Any]): ...
85-
class InstrumentedSet(set[Any]): ...
86-
class InstrumentedDict(dict[Any, Any]): ...
93+
class InstrumentedList(list[_T]):
94+
def append(self, item, _sa_initiator: Event | Literal[False] | None = None) -> None: ...
95+
def clear(self, index: SupportsIndex = -1) -> None: ...
96+
def extend(self, iterable: Iterable[_T]) -> None: ...
97+
def insert(self, index: SupportsIndex, value: _T) -> None: ...
98+
def pop(self, index: SupportsIndex = -1) -> _T: ...
99+
def remove(self, value: _T, _sa_initiator: Event | Literal[False] | None = None) -> None: ...
100+
101+
class InstrumentedSet(set[_T]):
102+
def add(self, value: _T, _sa_initiator: Event | Literal[False] | None = None) -> None: ...
103+
def difference_update(self, value: Iterable[_T]) -> None: ... # type: ignore[override]
104+
def discard(self, value: _T, _sa_initiator: Event | Literal[False] | None = None) -> None: ...
105+
def intersection_update(self, other: Iterable[_T]) -> None: ... # type: ignore[override]
106+
def remove(self, value: _T, _sa_initiator: Event | Literal[False] | None = None) -> None: ...
107+
def symmetric_difference_update(self, other: Iterable[_T]) -> None: ...
108+
def update(self, value: Iterable[_T]) -> None: ... # type: ignore[override]
109+
110+
class InstrumentedDict(dict[_KT, _VT]): ...
87111

88-
class MappedCollection(dict[Any, Any]):
112+
class MappedCollection(dict[_KT, _VT]):
89113
keyfunc: Any
90114
def __init__(self, keyfunc) -> None: ...
91-
def set(self, value, _sa_initiator: Incomplete | None = ...) -> None: ...
92-
def remove(self, value, _sa_initiator: Incomplete | None = ...) -> None: ...
115+
def set(self, value: _VT, _sa_initiator: Event | Literal[False] | None = ...) -> None: ...
116+
def remove(self, value: _VT, _sa_initiator: Event | Literal[False] | None = ...) -> None: ...
117+
def __delitem__(self, key: _KT, _sa_initiatorEvent: Event | Literal[False] | None = None) -> None: ...
118+
def __setitem__(self, key: _KT, value: _VT, _sa_initiator: Event | Literal[False] | None = None) -> None: ...
119+
@overload
120+
def pop(self, key: _KT) -> _VT: ...
121+
@overload
122+
def pop(self, key: _KT, default: _VT | _T | _symbol | symbol = ...) -> _VT | _T: ...
123+
@overload # type: ignore[override]
124+
def setdefault(self, key: _KT, default: _T) -> _VT | _T: ...
125+
@overload
126+
def setdefault(self, key: _KT, default: None = None) -> _VT | None: ...
127+
def update(self, __other: Mapping[_KT, _VT] = ..., **kw: _VT) -> None: ... # type: ignore[override]
Lines changed: 109 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from _typeshed import Incomplete
2-
from typing import Any
2+
from collections import Callable
3+
from typing import Any, Generic, Protocol, TypeVar
34

45
from ..sql.base import Generative
56
from .interfaces import LoaderOption
@@ -23,44 +24,116 @@ class Load(Generative, LoaderOption):
2324
def set_generic_strategy(self, attrs, strategy) -> None: ...
2425
def set_class_strategy(self, strategy, opts) -> None: ...
2526
# added dynamically at runtime
26-
def contains_eager(self, attr, alias: Incomplete | None = ...): ...
27-
def load_only(self, *attrs): ...
28-
def joinedload(self, attr, innerjoin: Incomplete | None = ...): ...
29-
def subqueryload(self, attr): ...
30-
def selectinload(self, attr): ...
31-
def lazyload(self, attr): ...
32-
def immediateload(self, attr): ...
33-
def noload(self, attr): ...
34-
def raiseload(self, attr, sql_only: bool = ...): ...
35-
def defaultload(self, attr): ...
36-
def defer(self, key, raiseload: bool = ...): ...
37-
def undefer(self, key): ...
38-
def undefer_group(self, name): ...
39-
def with_expression(self, key, expression): ...
40-
def selectin_polymorphic(self, classes): ...
27+
def contains_eager(loadopt, attr, alias: Incomplete | None = ...): ...
28+
def load_only(loadopt, *attrs): ...
29+
def joinedload(loadopt, attr, innerjoin: Incomplete | None = ...): ...
30+
def subqueryload(loadopt, attr): ...
31+
def selectinload(loadopt, attr): ...
32+
def lazyload(loadopt, attr): ...
33+
def immediateload(loadopt, attr): ...
34+
def noload(loadopt, attr): ...
35+
def raiseload(loadopt, attr, sql_only: bool = ...): ...
36+
def defaultload(loadopt, attr): ...
37+
def defer(loadopt, key, raiseload: bool = ...): ...
38+
def undefer(loadopt, key): ...
39+
def undefer_group(loadopt, name): ...
40+
def with_expression(loadopt, key, expression): ...
41+
def selectin_polymorphic(loadopt, classes): ...
4142

4243
class _UnboundLoad(Load):
4344
path: Any
4445
local_opts: Any
4546
def __init__(self) -> None: ...
4647

47-
class loader_option:
48-
name: Any
49-
fn: Any
50-
def __call__(self, fn): ...
51-
52-
def contains_eager(loadopt, attr, alias: Incomplete | None = ...): ...
53-
def load_only(loadopt, *attrs): ...
54-
def joinedload(loadopt, attr, innerjoin: Incomplete | None = ...): ...
55-
def subqueryload(loadopt, attr): ...
56-
def selectinload(loadopt, attr): ...
57-
def lazyload(loadopt, attr): ...
58-
def immediateload(loadopt, attr): ...
59-
def noload(loadopt, attr): ...
60-
def raiseload(loadopt, attr, sql_only: bool = ...): ...
61-
def defaultload(loadopt, attr): ...
62-
def defer(loadopt, key, raiseload: bool = ...): ...
63-
def undefer(loadopt, key): ...
64-
def undefer_group(loadopt, name): ...
65-
def with_expression(loadopt, key, expression): ...
66-
def selectin_polymorphic(loadopt, classes): ...
48+
###
49+
# The methods below are decorated with the class loader_option
50+
# They dynamically become instances of loader_option,
51+
# wich is callable with their original parameters.
52+
#
53+
# While both mypy and pyright's validation work, Pylance is unable to
54+
# show the parameters and return types.
55+
#
56+
# There is a workaround (define the method for Pylance, then reassign
57+
# an instance of loader_option to it for mypy, and add pyright+Flake8
58+
# suppressions), but it is too hacky and relies on some unsupported quirks.
59+
#
60+
# Asking Pylance to add support for these generic callables might be preferable.
61+
###
62+
63+
_F = TypeVar("_F", bound=Callable[..., loader_option[Any]])
64+
65+
class loader_option(Generic[_F]):
66+
name: str
67+
_dynamic: _F
68+
fn: _F
69+
__call__: _F # Cheesy "__call__" definition to use the dynamic methods instead
70+
71+
class _contains_eager(Protocol):
72+
def __call__(self, loadopt, attr, alias: Incomplete | None = ...) -> loader_option[_contains_eager]: ...
73+
74+
contains_eager: loader_option[_contains_eager]
75+
76+
class _load_only(Protocol):
77+
def __call__(self, loadopt, *attrs) -> loader_option[_load_only]: ...
78+
79+
load_only: loader_option[_load_only]
80+
81+
class _subqueryload(Protocol):
82+
def __call__(self, loadopt, attr) -> loader_option[_subqueryload]: ...
83+
84+
subqueryload: loader_option[_subqueryload]
85+
86+
class _selectinload(Protocol):
87+
def __call__(self, loadopt, attr) -> loader_option[_selectinload]: ...
88+
89+
selectinload: loader_option[_selectinload]
90+
91+
class _lazyload(Protocol):
92+
def __call__(self, loadopt, attr) -> loader_option[_lazyload]: ...
93+
94+
lazyload: loader_option[_lazyload]
95+
96+
class _immediateload(Protocol):
97+
def __call__(self, loadopt, attr) -> loader_option[_immediateload]: ...
98+
99+
immediateload: loader_option[_immediateload]
100+
101+
class _noload(Protocol):
102+
def __call__(self, loadopt, attr) -> loader_option[_noload]: ...
103+
104+
noload: loader_option[_noload]
105+
106+
class _raiseload(Protocol):
107+
def __call__(self, loadopt, attr, sql_only: bool = ...) -> loader_option[_raiseload]: ...
108+
109+
raiseload: loader_option[_raiseload]
110+
111+
class _defaultload(Protocol):
112+
def __call__(self, loadopt, attr) -> loader_option[_defaultload]: ...
113+
114+
defaultload: loader_option[_defaultload]
115+
116+
class _defer(Protocol):
117+
def __call__(self, loadopt, attr, sql_only: bool = ...) -> loader_option[_defer]: ...
118+
119+
defer: loader_option[_defer]
120+
121+
class _undefer(Protocol):
122+
def __call__(self, loadopt, key) -> loader_option[_undefer]: ...
123+
124+
undefer: loader_option[_undefer]
125+
126+
class _undefer_group(Protocol):
127+
def __call__(self, loadopt, name) -> loader_option[_undefer_group]: ...
128+
129+
undefer_group: loader_option[_undefer_group]
130+
131+
class _with_expression(Protocol):
132+
def __call__(self, loadopt, key, expression) -> loader_option[_with_expression]: ...
133+
134+
with_expression: loader_option[_with_expression]
135+
136+
class _selectin_polymorphic(Protocol):
137+
def __call__(self, loadopt, classes) -> loader_option[_selectin_polymorphic]: ...
138+
139+
selectin_polymorphic: loader_option[_selectin_polymorphic]

stubs/SQLAlchemy/sqlalchemy/sql/base.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class _MetaOptions(type):
7272
def __init__(cls, classname, bases, dict_) -> None: ...
7373
def __add__(self, other): ...
7474

75-
class Options:
75+
class Options(metaclass=_MetaOptions):
7676
def __init__(self, **kw) -> None: ...
7777
def __add__(self, other): ...
7878
def __eq__(self, other): ...

stubs/SQLAlchemy/sqlalchemy/sql/compiler.pyi

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from _typeshed import Incomplete
22
from typing import NamedTuple
33

4+
from sqlalchemy.util.langhelpers import EnsureKWArgType
5+
46
from ..util import memoized_property
57
from . import elements
68

@@ -67,7 +69,7 @@ class Compiled:
6769
@property
6870
def params(self): ...
6971

70-
class TypeCompiler:
72+
class TypeCompiler(metaclass=EnsureKWArgType):
7173
ensure_kwarg: str
7274
dialect: Incomplete
7375
def __init__(self, dialect) -> None: ...

stubs/SQLAlchemy/sqlalchemy/sql/functions.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ class Function(FunctionElement):
8787
class _GenericMeta(TraversibleType):
8888
def __init__(cls, clsname, bases, clsdict) -> None: ...
8989

90-
class GenericFunction:
90+
class GenericFunction(Function, metaclass=_GenericMeta):
9191
name: Incomplete
9292
identifier: Incomplete
9393
coerce_arguments: bool

0 commit comments

Comments
 (0)