alembic 1.13.0__py3-none-any.whl → 1.13.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. alembic/__init__.py +1 -1
  2. alembic/autogenerate/__init__.py +10 -10
  3. alembic/autogenerate/api.py +6 -4
  4. alembic/autogenerate/compare.py +5 -4
  5. alembic/autogenerate/render.py +9 -9
  6. alembic/autogenerate/rewriter.py +26 -13
  7. alembic/command.py +3 -1
  8. alembic/config.py +20 -9
  9. alembic/context.pyi +10 -5
  10. alembic/ddl/__init__.py +1 -1
  11. alembic/ddl/_autogen.py +4 -2
  12. alembic/ddl/base.py +12 -9
  13. alembic/ddl/impl.py +5 -2
  14. alembic/ddl/mssql.py +4 -1
  15. alembic/ddl/mysql.py +5 -3
  16. alembic/ddl/oracle.py +4 -1
  17. alembic/ddl/postgresql.py +16 -9
  18. alembic/ddl/sqlite.py +8 -6
  19. alembic/op.pyi +46 -8
  20. alembic/operations/base.py +70 -14
  21. alembic/operations/batch.py +7 -8
  22. alembic/operations/ops.py +52 -30
  23. alembic/operations/schemaobj.py +5 -4
  24. alembic/operations/toimpl.py +3 -0
  25. alembic/runtime/environment.py +15 -6
  26. alembic/runtime/migration.py +27 -11
  27. alembic/script/base.py +13 -15
  28. alembic/script/revision.py +30 -17
  29. alembic/script/write_hooks.py +3 -0
  30. alembic/util/__init__.py +31 -31
  31. alembic/util/compat.py +25 -8
  32. alembic/util/langhelpers.py +78 -33
  33. alembic/util/messaging.py +6 -3
  34. alembic/util/pyfiles.py +7 -3
  35. alembic/util/sqla_compat.py +43 -14
  36. {alembic-1.13.0.dist-info → alembic-1.13.1.dist-info}/METADATA +1 -1
  37. {alembic-1.13.0.dist-info → alembic-1.13.1.dist-info}/RECORD +41 -41
  38. {alembic-1.13.0.dist-info → alembic-1.13.1.dist-info}/LICENSE +0 -0
  39. {alembic-1.13.0.dist-info → alembic-1.13.1.dist-info}/WHEEL +0 -0
  40. {alembic-1.13.0.dist-info → alembic-1.13.1.dist-info}/entry_points.txt +0 -0
  41. {alembic-1.13.0.dist-info → alembic-1.13.1.dist-info}/top_level.txt +0 -0
@@ -14,6 +14,7 @@ from typing import Iterator
14
14
  from typing import List
15
15
  from typing import Optional
16
16
  from typing import overload
17
+ from typing import Protocol
17
18
  from typing import Sequence
18
19
  from typing import Set
19
20
  from typing import Tuple
@@ -47,6 +48,18 @@ _relative_destination = re.compile(r"(?:(.+?)@)?(\w+)?((?:\+|-)\d+)")
47
48
  _revision_illegal_chars = ["@", "-", "+"]
48
49
 
49
50
 
51
+ class _CollectRevisionsProtocol(Protocol):
52
+ def __call__(
53
+ self,
54
+ upper: _RevisionIdentifierType,
55
+ lower: _RevisionIdentifierType,
56
+ inclusive: bool,
57
+ implicit_base: bool,
58
+ assert_relative_length: bool,
59
+ ) -> Tuple[Set[Revision], Tuple[Optional[_RevisionOrBase], ...]]:
60
+ ...
61
+
62
+
50
63
  class RevisionError(Exception):
51
64
  pass
52
65
 
@@ -396,7 +409,7 @@ class RevisionMap:
396
409
  for rev in self._get_ancestor_nodes(
397
410
  [revision],
398
411
  include_dependencies=False,
399
- map_=cast(_RevisionMapType, map_),
412
+ map_=map_,
400
413
  ):
401
414
  if rev is revision:
402
415
  continue
@@ -791,7 +804,7 @@ class RevisionMap:
791
804
  The iterator yields :class:`.Revision` objects.
792
805
 
793
806
  """
794
- fn: Callable
807
+ fn: _CollectRevisionsProtocol
795
808
  if select_for_downgrade:
796
809
  fn = self._collect_downgrade_revisions
797
810
  else:
@@ -818,7 +831,7 @@ class RevisionMap:
818
831
  ) -> Iterator[Any]:
819
832
  if omit_immediate_dependencies:
820
833
 
821
- def fn(rev):
834
+ def fn(rev: Revision) -> Iterable[str]:
822
835
  if rev not in targets:
823
836
  return rev._all_nextrev
824
837
  else:
@@ -826,12 +839,12 @@ class RevisionMap:
826
839
 
827
840
  elif include_dependencies:
828
841
 
829
- def fn(rev):
842
+ def fn(rev: Revision) -> Iterable[str]:
830
843
  return rev._all_nextrev
831
844
 
832
845
  else:
833
846
 
834
- def fn(rev):
847
+ def fn(rev: Revision) -> Iterable[str]:
835
848
  return rev.nextrev
836
849
 
837
850
  return self._iterate_related_revisions(
@@ -847,12 +860,12 @@ class RevisionMap:
847
860
  ) -> Iterator[Revision]:
848
861
  if include_dependencies:
849
862
 
850
- def fn(rev):
863
+ def fn(rev: Revision) -> Iterable[str]:
851
864
  return rev._normalized_down_revisions
852
865
 
853
866
  else:
854
867
 
855
- def fn(rev):
868
+ def fn(rev: Revision) -> Iterable[str]:
856
869
  return rev._versioned_down_revisions
857
870
 
858
871
  return self._iterate_related_revisions(
@@ -861,7 +874,7 @@ class RevisionMap:
861
874
 
862
875
  def _iterate_related_revisions(
863
876
  self,
864
- fn: Callable,
877
+ fn: Callable[[Revision], Iterable[str]],
865
878
  targets: Collection[Optional[_RevisionOrBase]],
866
879
  map_: Optional[_RevisionMapType],
867
880
  check: bool = False,
@@ -923,7 +936,7 @@ class RevisionMap:
923
936
 
924
937
  id_to_rev = self._revision_map
925
938
 
926
- def get_ancestors(rev_id):
939
+ def get_ancestors(rev_id: str) -> Set[str]:
927
940
  return {
928
941
  r.revision
929
942
  for r in self._get_ancestor_nodes([id_to_rev[rev_id]])
@@ -1041,7 +1054,7 @@ class RevisionMap:
1041
1054
  children: Sequence[Optional[_RevisionOrBase]]
1042
1055
  for _ in range(abs(steps)):
1043
1056
  if steps > 0:
1044
- assert initial != "base"
1057
+ assert initial != "base" # type: ignore[comparison-overlap]
1045
1058
  # Walk up
1046
1059
  walk_up = [
1047
1060
  is_revision(rev)
@@ -1055,7 +1068,7 @@ class RevisionMap:
1055
1068
  children = walk_up
1056
1069
  else:
1057
1070
  # Walk down
1058
- if initial == "base":
1071
+ if initial == "base": # type: ignore[comparison-overlap]
1059
1072
  children = ()
1060
1073
  else:
1061
1074
  children = self.get_revisions(
@@ -1189,7 +1202,7 @@ class RevisionMap:
1189
1202
  # No relative destination given, revision specified is absolute.
1190
1203
  branch_label, _, symbol = target.rpartition("@")
1191
1204
  if not branch_label:
1192
- branch_label = None # type:ignore[assignment]
1205
+ branch_label = None
1193
1206
  return branch_label, self.get_revision(symbol)
1194
1207
 
1195
1208
  def _parse_upgrade_target(
@@ -1301,11 +1314,11 @@ class RevisionMap:
1301
1314
  def _collect_downgrade_revisions(
1302
1315
  self,
1303
1316
  upper: _RevisionIdentifierType,
1304
- target: _RevisionIdentifierType,
1317
+ lower: _RevisionIdentifierType,
1305
1318
  inclusive: bool,
1306
1319
  implicit_base: bool,
1307
1320
  assert_relative_length: bool,
1308
- ) -> Any:
1321
+ ) -> Tuple[Set[Revision], Tuple[Optional[_RevisionOrBase], ...]]:
1309
1322
  """
1310
1323
  Compute the set of current revisions specified by :upper, and the
1311
1324
  downgrade target specified by :target. Return all dependents of target
@@ -1316,7 +1329,7 @@ class RevisionMap:
1316
1329
 
1317
1330
  branch_label, target_revision = self._parse_downgrade_target(
1318
1331
  current_revisions=upper,
1319
- target=target,
1332
+ target=lower,
1320
1333
  assert_relative_length=assert_relative_length,
1321
1334
  )
1322
1335
  if target_revision == "base":
@@ -1408,7 +1421,7 @@ class RevisionMap:
1408
1421
  inclusive: bool,
1409
1422
  implicit_base: bool,
1410
1423
  assert_relative_length: bool,
1411
- ) -> Tuple[Set[Revision], Tuple[Optional[_RevisionOrBase]]]:
1424
+ ) -> Tuple[Set[Revision], Tuple[Revision, ...]]:
1412
1425
  """
1413
1426
  Compute the set of required revisions specified by :upper, and the
1414
1427
  current set of active revisions specified by :lower. Find the
@@ -1500,7 +1513,7 @@ class RevisionMap:
1500
1513
  )
1501
1514
  needs.intersection_update(lower_descendents)
1502
1515
 
1503
- return needs, tuple(targets) # type:ignore[return-value]
1516
+ return needs, tuple(targets)
1504
1517
 
1505
1518
  def _get_all_current(
1506
1519
  self, id_: Tuple[str, ...]
@@ -1,3 +1,6 @@
1
+ # mypy: allow-untyped-defs, allow-incomplete-defs, allow-untyped-calls
2
+ # mypy: no-warn-return-any, allow-any-generics
3
+
1
4
  from __future__ import annotations
2
5
 
3
6
  import shlex
alembic/util/__init__.py CHANGED
@@ -1,34 +1,34 @@
1
- from .editor import open_in_editor
2
- from .exc import AutogenerateDiffsDetected
3
- from .exc import CommandError
4
- from .langhelpers import _with_legacy_names
5
- from .langhelpers import asbool
6
- from .langhelpers import dedupe_tuple
7
- from .langhelpers import Dispatcher
8
- from .langhelpers import EMPTY_DICT
9
- from .langhelpers import immutabledict
10
- from .langhelpers import memoized_property
11
- from .langhelpers import ModuleClsProxy
12
- from .langhelpers import not_none
13
- from .langhelpers import rev_id
14
- from .langhelpers import to_list
15
- from .langhelpers import to_tuple
16
- from .langhelpers import unique_list
17
- from .messaging import err
18
- from .messaging import format_as_comma
19
- from .messaging import msg
20
- from .messaging import obfuscate_url_pw
21
- from .messaging import status
22
- from .messaging import warn
23
- from .messaging import write_outstream
24
- from .pyfiles import coerce_resource_to_filename
25
- from .pyfiles import load_python_file
26
- from .pyfiles import pyc_file_from_path
27
- from .pyfiles import template_to_file
28
- from .sqla_compat import has_computed
29
- from .sqla_compat import sqla_13
30
- from .sqla_compat import sqla_14
31
- from .sqla_compat import sqla_2
1
+ from .editor import open_in_editor as open_in_editor
2
+ from .exc import AutogenerateDiffsDetected as AutogenerateDiffsDetected
3
+ from .exc import CommandError as CommandError
4
+ from .langhelpers import _with_legacy_names as _with_legacy_names
5
+ from .langhelpers import asbool as asbool
6
+ from .langhelpers import dedupe_tuple as dedupe_tuple
7
+ from .langhelpers import Dispatcher as Dispatcher
8
+ from .langhelpers import EMPTY_DICT as EMPTY_DICT
9
+ from .langhelpers import immutabledict as immutabledict
10
+ from .langhelpers import memoized_property as memoized_property
11
+ from .langhelpers import ModuleClsProxy as ModuleClsProxy
12
+ from .langhelpers import not_none as not_none
13
+ from .langhelpers import rev_id as rev_id
14
+ from .langhelpers import to_list as to_list
15
+ from .langhelpers import to_tuple as to_tuple
16
+ from .langhelpers import unique_list as unique_list
17
+ from .messaging import err as err
18
+ from .messaging import format_as_comma as format_as_comma
19
+ from .messaging import msg as msg
20
+ from .messaging import obfuscate_url_pw as obfuscate_url_pw
21
+ from .messaging import status as status
22
+ from .messaging import warn as warn
23
+ from .messaging import write_outstream as write_outstream
24
+ from .pyfiles import coerce_resource_to_filename as coerce_resource_to_filename
25
+ from .pyfiles import load_python_file as load_python_file
26
+ from .pyfiles import pyc_file_from_path as pyc_file_from_path
27
+ from .pyfiles import template_to_file as template_to_file
28
+ from .sqla_compat import has_computed as has_computed
29
+ from .sqla_compat import sqla_13 as sqla_13
30
+ from .sqla_compat import sqla_14 as sqla_14
31
+ from .sqla_compat import sqla_2 as sqla_2
32
32
 
33
33
 
34
34
  if not sqla_13:
alembic/util/compat.py CHANGED
@@ -1,3 +1,5 @@
1
+ # mypy: no-warn-unused-ignores
2
+
1
3
  from __future__ import annotations
2
4
 
3
5
  from configparser import ConfigParser
@@ -5,11 +7,20 @@ import io
5
7
  import os
6
8
  import sys
7
9
  import typing
10
+ from typing import Any
11
+ from typing import List
12
+ from typing import Optional
8
13
  from typing import Sequence
9
14
  from typing import Union
10
15
 
11
- from sqlalchemy.util import inspect_getfullargspec # noqa
12
- from sqlalchemy.util.compat import inspect_formatargspec # noqa
16
+ if True:
17
+ # zimports hack for too-long names
18
+ from sqlalchemy.util import ( # noqa: F401
19
+ inspect_getfullargspec as inspect_getfullargspec,
20
+ )
21
+ from sqlalchemy.util.compat import ( # noqa: F401
22
+ inspect_formatargspec as inspect_formatargspec,
23
+ )
13
24
 
14
25
  is_posix = os.name == "posix"
15
26
 
@@ -27,9 +38,13 @@ class EncodedIO(io.TextIOWrapper):
27
38
 
28
39
 
29
40
  if py39:
30
- from importlib import resources as importlib_resources
31
- from importlib import metadata as importlib_metadata
32
- from importlib.metadata import EntryPoint
41
+ from importlib import resources as _resources
42
+
43
+ importlib_resources = _resources
44
+ from importlib import metadata as _metadata
45
+
46
+ importlib_metadata = _metadata
47
+ from importlib.metadata import EntryPoint as EntryPoint
33
48
  else:
34
49
  import importlib_resources # type:ignore # noqa
35
50
  import importlib_metadata # type:ignore # noqa
@@ -39,12 +54,14 @@ else:
39
54
  def importlib_metadata_get(group: str) -> Sequence[EntryPoint]:
40
55
  ep = importlib_metadata.entry_points()
41
56
  if hasattr(ep, "select"):
42
- return ep.select(group=group) # type: ignore
57
+ return ep.select(group=group)
43
58
  else:
44
59
  return ep.get(group, ()) # type: ignore
45
60
 
46
61
 
47
- def formatannotation_fwdref(annotation, base_module=None):
62
+ def formatannotation_fwdref(
63
+ annotation: Any, base_module: Optional[Any] = None
64
+ ) -> str:
48
65
  """vendored from python 3.7"""
49
66
  # copied over _formatannotation from sqlalchemy 2.0
50
67
 
@@ -65,7 +82,7 @@ def formatannotation_fwdref(annotation, base_module=None):
65
82
  def read_config_parser(
66
83
  file_config: ConfigParser,
67
84
  file_argument: Sequence[Union[str, os.PathLike[str]]],
68
- ) -> list[str]:
85
+ ) -> List[str]:
69
86
  if py310:
70
87
  return file_config.read(file_argument, encoding="locale")
71
88
  else:
@@ -5,33 +5,46 @@ from collections.abc import Iterable
5
5
  import textwrap
6
6
  from typing import Any
7
7
  from typing import Callable
8
+ from typing import cast
8
9
  from typing import Dict
9
10
  from typing import List
10
11
  from typing import Mapping
12
+ from typing import MutableMapping
13
+ from typing import NoReturn
11
14
  from typing import Optional
12
15
  from typing import overload
13
16
  from typing import Sequence
17
+ from typing import Set
14
18
  from typing import Tuple
19
+ from typing import Type
20
+ from typing import TYPE_CHECKING
15
21
  from typing import TypeVar
16
22
  from typing import Union
17
23
  import uuid
18
24
  import warnings
19
25
 
20
- from sqlalchemy.util import asbool # noqa
21
- from sqlalchemy.util import immutabledict # noqa
22
- from sqlalchemy.util import memoized_property # noqa
23
- from sqlalchemy.util import to_list # noqa
24
- from sqlalchemy.util import unique_list # noqa
26
+ from sqlalchemy.util import asbool as asbool # noqa: F401
27
+ from sqlalchemy.util import immutabledict as immutabledict # noqa: F401
28
+ from sqlalchemy.util import to_list as to_list # noqa: F401
29
+ from sqlalchemy.util import unique_list as unique_list
25
30
 
26
31
  from .compat import inspect_getfullargspec
27
32
 
33
+ if True:
34
+ # zimports workaround :(
35
+ from sqlalchemy.util import ( # noqa: F401
36
+ memoized_property as memoized_property,
37
+ )
38
+
28
39
 
29
40
  EMPTY_DICT: Mapping[Any, Any] = immutabledict()
30
- _T = TypeVar("_T")
41
+ _T = TypeVar("_T", bound=Any)
42
+
43
+ _C = TypeVar("_C", bound=Callable[..., Any])
31
44
 
32
45
 
33
46
  class _ModuleClsMeta(type):
34
- def __setattr__(cls, key: str, value: Callable) -> None:
47
+ def __setattr__(cls, key: str, value: Callable[..., Any]) -> None:
35
48
  super().__setattr__(key, value)
36
49
  cls._update_module_proxies(key) # type: ignore
37
50
 
@@ -45,9 +58,13 @@ class ModuleClsProxy(metaclass=_ModuleClsMeta):
45
58
 
46
59
  """
47
60
 
48
- _setups: Dict[type, Tuple[set, list]] = collections.defaultdict(
49
- lambda: (set(), [])
50
- )
61
+ _setups: Dict[
62
+ Type[Any],
63
+ Tuple[
64
+ Set[str],
65
+ List[Tuple[MutableMapping[str, Any], MutableMapping[str, Any]]],
66
+ ],
67
+ ] = collections.defaultdict(lambda: (set(), []))
51
68
 
52
69
  @classmethod
53
70
  def _update_module_proxies(cls, name: str) -> None:
@@ -70,18 +87,33 @@ class ModuleClsProxy(metaclass=_ModuleClsMeta):
70
87
  del globals_[attr_name]
71
88
 
72
89
  @classmethod
73
- def create_module_class_proxy(cls, globals_, locals_):
90
+ def create_module_class_proxy(
91
+ cls,
92
+ globals_: MutableMapping[str, Any],
93
+ locals_: MutableMapping[str, Any],
94
+ ) -> None:
74
95
  attr_names, modules = cls._setups[cls]
75
96
  modules.append((globals_, locals_))
76
97
  cls._setup_proxy(globals_, locals_, attr_names)
77
98
 
78
99
  @classmethod
79
- def _setup_proxy(cls, globals_, locals_, attr_names):
100
+ def _setup_proxy(
101
+ cls,
102
+ globals_: MutableMapping[str, Any],
103
+ locals_: MutableMapping[str, Any],
104
+ attr_names: Set[str],
105
+ ) -> None:
80
106
  for methname in dir(cls):
81
107
  cls._add_proxied_attribute(methname, globals_, locals_, attr_names)
82
108
 
83
109
  @classmethod
84
- def _add_proxied_attribute(cls, methname, globals_, locals_, attr_names):
110
+ def _add_proxied_attribute(
111
+ cls,
112
+ methname: str,
113
+ globals_: MutableMapping[str, Any],
114
+ locals_: MutableMapping[str, Any],
115
+ attr_names: Set[str],
116
+ ) -> None:
85
117
  if not methname.startswith("_"):
86
118
  meth = getattr(cls, methname)
87
119
  if callable(meth):
@@ -92,10 +124,15 @@ class ModuleClsProxy(metaclass=_ModuleClsMeta):
92
124
  attr_names.add(methname)
93
125
 
94
126
  @classmethod
95
- def _create_method_proxy(cls, name, globals_, locals_):
127
+ def _create_method_proxy(
128
+ cls,
129
+ name: str,
130
+ globals_: MutableMapping[str, Any],
131
+ locals_: MutableMapping[str, Any],
132
+ ) -> Callable[..., Any]:
96
133
  fn = getattr(cls, name)
97
134
 
98
- def _name_error(name, from_):
135
+ def _name_error(name: str, from_: Exception) -> NoReturn:
99
136
  raise NameError(
100
137
  "Can't invoke function '%s', as the proxy object has "
101
138
  "not yet been "
@@ -119,7 +156,9 @@ class ModuleClsProxy(metaclass=_ModuleClsMeta):
119
156
  translations,
120
157
  )
121
158
 
122
- def translate(fn_name, spec, translations, args, kw):
159
+ def translate(
160
+ fn_name: str, spec: Any, translations: Any, args: Any, kw: Any
161
+ ) -> Any:
123
162
  return_kw = {}
124
163
  return_args = []
125
164
 
@@ -176,15 +215,15 @@ class ModuleClsProxy(metaclass=_ModuleClsMeta):
176
215
  "doc": fn.__doc__,
177
216
  }
178
217
  )
179
- lcl = {}
218
+ lcl: MutableMapping[str, Any] = {}
180
219
 
181
- exec(func_text, globals_, lcl)
182
- return lcl[name]
220
+ exec(func_text, cast("Dict[str, Any]", globals_), lcl)
221
+ return cast("Callable[..., Any]", lcl[name])
183
222
 
184
223
 
185
- def _with_legacy_names(translations):
186
- def decorate(fn):
187
- fn._legacy_translations = translations
224
+ def _with_legacy_names(translations: Any) -> Any:
225
+ def decorate(fn: _C) -> _C:
226
+ fn._legacy_translations = translations # type: ignore[attr-defined]
188
227
  return fn
189
228
 
190
229
  return decorate
@@ -195,21 +234,25 @@ def rev_id() -> str:
195
234
 
196
235
 
197
236
  @overload
198
- def to_tuple(x: Any, default: tuple) -> tuple:
237
+ def to_tuple(x: Any, default: Tuple[Any, ...]) -> Tuple[Any, ...]:
199
238
  ...
200
239
 
201
240
 
202
241
  @overload
203
- def to_tuple(x: None, default: Optional[_T] = None) -> _T:
242
+ def to_tuple(x: None, default: Optional[_T] = ...) -> _T:
204
243
  ...
205
244
 
206
245
 
207
246
  @overload
208
- def to_tuple(x: Any, default: Optional[tuple] = None) -> tuple:
247
+ def to_tuple(
248
+ x: Any, default: Optional[Tuple[Any, ...]] = None
249
+ ) -> Tuple[Any, ...]:
209
250
  ...
210
251
 
211
252
 
212
- def to_tuple(x, default=None):
253
+ def to_tuple(
254
+ x: Any, default: Optional[Tuple[Any, ...]] = None
255
+ ) -> Optional[Tuple[Any, ...]]:
213
256
  if x is None:
214
257
  return default
215
258
  elif isinstance(x, str):
@@ -226,13 +269,13 @@ def dedupe_tuple(tup: Tuple[str, ...]) -> Tuple[str, ...]:
226
269
 
227
270
  class Dispatcher:
228
271
  def __init__(self, uselist: bool = False) -> None:
229
- self._registry: Dict[tuple, Any] = {}
272
+ self._registry: Dict[Tuple[Any, ...], Any] = {}
230
273
  self.uselist = uselist
231
274
 
232
275
  def dispatch_for(
233
276
  self, target: Any, qualifier: str = "default"
234
- ) -> Callable:
235
- def decorate(fn):
277
+ ) -> Callable[[_C], _C]:
278
+ def decorate(fn: _C) -> _C:
236
279
  if self.uselist:
237
280
  self._registry.setdefault((target, qualifier), []).append(fn)
238
281
  else:
@@ -244,7 +287,7 @@ class Dispatcher:
244
287
 
245
288
  def dispatch(self, obj: Any, qualifier: str = "default") -> Any:
246
289
  if isinstance(obj, str):
247
- targets: Sequence = [obj]
290
+ targets: Sequence[Any] = [obj]
248
291
  elif isinstance(obj, type):
249
292
  targets = obj.__mro__
250
293
  else:
@@ -259,11 +302,13 @@ class Dispatcher:
259
302
  raise ValueError("no dispatch function for object: %s" % obj)
260
303
 
261
304
  def _fn_or_list(
262
- self, fn_or_list: Union[List[Callable], Callable]
263
- ) -> Callable:
305
+ self, fn_or_list: Union[List[Callable[..., Any]], Callable[..., Any]]
306
+ ) -> Callable[..., Any]:
264
307
  if self.uselist:
265
308
 
266
- def go(*arg, **kw):
309
+ def go(*arg: Any, **kw: Any) -> None:
310
+ if TYPE_CHECKING:
311
+ assert isinstance(fn_or_list, Sequence)
267
312
  for fn in fn_or_list:
268
313
  fn(*arg, **kw)
269
314
 
alembic/util/messaging.py CHANGED
@@ -5,6 +5,7 @@ from contextlib import contextmanager
5
5
  import logging
6
6
  import sys
7
7
  import textwrap
8
+ from typing import Iterator
8
9
  from typing import Optional
9
10
  from typing import TextIO
10
11
  from typing import Union
@@ -53,7 +54,9 @@ def write_outstream(
53
54
 
54
55
 
55
56
  @contextmanager
56
- def status(status_msg: str, newline: bool = False, quiet: bool = False):
57
+ def status(
58
+ status_msg: str, newline: bool = False, quiet: bool = False
59
+ ) -> Iterator[None]:
57
60
  msg(status_msg + " ...", newline, flush=True, quiet=quiet)
58
61
  try:
59
62
  yield
@@ -66,7 +69,7 @@ def status(status_msg: str, newline: bool = False, quiet: bool = False):
66
69
  write_outstream(sys.stdout, " done\n")
67
70
 
68
71
 
69
- def err(message: str, quiet: bool = False):
72
+ def err(message: str, quiet: bool = False) -> None:
70
73
  log.error(message)
71
74
  msg(f"FAILED: {message}", quiet=quiet)
72
75
  sys.exit(-1)
@@ -74,7 +77,7 @@ def err(message: str, quiet: bool = False):
74
77
 
75
78
  def obfuscate_url_pw(input_url: str) -> str:
76
79
  u = url.make_url(input_url)
77
- return sqla_compat.url_render_as_string(u, hide_password=True)
80
+ return sqla_compat.url_render_as_string(u, hide_password=True) # type: ignore # noqa: E501
78
81
 
79
82
 
80
83
  def warn(msg: str, stacklevel: int = 2) -> None:
alembic/util/pyfiles.py CHANGED
@@ -8,6 +8,8 @@ import importlib.util
8
8
  import os
9
9
  import re
10
10
  import tempfile
11
+ from types import ModuleType
12
+ from typing import Any
11
13
  from typing import Optional
12
14
 
13
15
  from mako import exceptions
@@ -18,7 +20,7 @@ from .exc import CommandError
18
20
 
19
21
 
20
22
  def template_to_file(
21
- template_file: str, dest: str, output_encoding: str, **kw
23
+ template_file: str, dest: str, output_encoding: str, **kw: Any
22
24
  ) -> None:
23
25
  template = Template(filename=template_file)
24
26
  try:
@@ -82,7 +84,7 @@ def pyc_file_from_path(path: str) -> Optional[str]:
82
84
  return None
83
85
 
84
86
 
85
- def load_python_file(dir_: str, filename: str):
87
+ def load_python_file(dir_: str, filename: str) -> ModuleType:
86
88
  """Load a file from the given path as a Python module."""
87
89
 
88
90
  module_id = re.sub(r"\W", "_", filename)
@@ -99,10 +101,12 @@ def load_python_file(dir_: str, filename: str):
99
101
  module = load_module_py(module_id, pyc_path)
100
102
  elif ext in (".pyc", ".pyo"):
101
103
  module = load_module_py(module_id, path)
104
+ else:
105
+ assert False
102
106
  return module
103
107
 
104
108
 
105
- def load_module_py(module_id: str, path: str):
109
+ def load_module_py(module_id: str, path: str) -> ModuleType:
106
110
  spec = importlib.util.spec_from_file_location(module_id, path)
107
111
  assert spec
108
112
  module = importlib.util.module_from_spec(spec)