alembic 1.11.1__py3-none-any.whl → 1.11.2__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 (37) hide show
  1. alembic/__init__.py +1 -1
  2. alembic/autogenerate/api.py +0 -2
  3. alembic/autogenerate/compare.py +12 -23
  4. alembic/autogenerate/render.py +18 -36
  5. alembic/command.py +0 -1
  6. alembic/config.py +0 -2
  7. alembic/ddl/impl.py +10 -5
  8. alembic/ddl/mssql.py +2 -5
  9. alembic/ddl/mysql.py +0 -1
  10. alembic/ddl/postgresql.py +31 -10
  11. alembic/ddl/sqlite.py +0 -2
  12. alembic/op.pyi +29 -17
  13. alembic/operations/base.py +29 -17
  14. alembic/operations/batch.py +4 -5
  15. alembic/operations/ops.py +49 -24
  16. alembic/operations/toimpl.py +18 -4
  17. alembic/runtime/environment.py +0 -1
  18. alembic/runtime/migration.py +0 -4
  19. alembic/script/base.py +3 -7
  20. alembic/script/revision.py +0 -4
  21. alembic/script/write_hooks.py +8 -7
  22. alembic/templates/async/script.py.mako +6 -4
  23. alembic/templates/generic/script.py.mako +6 -4
  24. alembic/templates/multidb/script.py.mako +6 -4
  25. alembic/testing/assertions.py +0 -3
  26. alembic/testing/env.py +0 -3
  27. alembic/testing/fixtures.py +0 -2
  28. alembic/testing/suite/_autogen_fixtures.py +0 -1
  29. alembic/util/langhelpers.py +0 -1
  30. alembic/util/pyfiles.py +0 -1
  31. alembic/util/sqla_compat.py +0 -1
  32. {alembic-1.11.1.dist-info → alembic-1.11.2.dist-info}/METADATA +1 -1
  33. {alembic-1.11.1.dist-info → alembic-1.11.2.dist-info}/RECORD +37 -37
  34. {alembic-1.11.1.dist-info → alembic-1.11.2.dist-info}/WHEEL +1 -1
  35. {alembic-1.11.1.dist-info → alembic-1.11.2.dist-info}/LICENSE +0 -0
  36. {alembic-1.11.1.dist-info → alembic-1.11.2.dist-info}/entry_points.txt +0 -0
  37. {alembic-1.11.1.dist-info → alembic-1.11.2.dist-info}/top_level.txt +0 -0
alembic/op.pyi CHANGED
@@ -646,6 +646,7 @@ def create_index(
646
646
  *,
647
647
  schema: Optional[str] = None,
648
648
  unique: bool = False,
649
+ if_not_exists: Optional[bool] = None,
649
650
  **kw: Any,
650
651
  ) -> None:
651
652
  r"""Issue a "create index" instruction using the current
@@ -675,20 +676,24 @@ def create_index(
675
676
  :class:`~sqlalchemy.sql.elements.quoted_name`.
676
677
  :param unique: If True, create a unique index.
677
678
 
678
- :param quote:
679
- Force quoting of this column's name on or off, corresponding
680
- to ``True`` or ``False``. When left at its default
681
- of ``None``, the column identifier will be quoted according to
682
- whether the name is case sensitive (identifiers with at least one
683
- upper case character are treated as case sensitive), or if it's a
684
- reserved word. This flag is only needed to force quoting of a
685
- reserved word which is not known by the SQLAlchemy dialect.
679
+ :param quote: Force quoting of this column's name on or off,
680
+ corresponding to ``True`` or ``False``. When left at its default
681
+ of ``None``, the column identifier will be quoted according to
682
+ whether the name is case sensitive (identifiers with at least one
683
+ upper case character are treated as case sensitive), or if it's a
684
+ reserved word. This flag is only needed to force quoting of a
685
+ reserved word which is not known by the SQLAlchemy dialect.
686
+
687
+ :param if_not_exists: If True, adds IF NOT EXISTS operator when
688
+ creating the new index.
689
+
690
+ .. versionadded:: 1.12.0
686
691
 
687
692
  :param \**kw: Additional keyword arguments not mentioned above are
688
- dialect specific, and passed in the form
689
- ``<dialectname>_<argname>``.
690
- See the documentation regarding an individual dialect at
691
- :ref:`dialect_toplevel` for detail on documented arguments.
693
+ dialect specific, and passed in the form
694
+ ``<dialectname>_<argname>``.
695
+ See the documentation regarding an individual dialect at
696
+ :ref:`dialect_toplevel` for detail on documented arguments.
692
697
 
693
698
  """
694
699
 
@@ -955,6 +960,7 @@ def drop_index(
955
960
  table_name: Optional[str] = None,
956
961
  *,
957
962
  schema: Optional[str] = None,
963
+ if_exists: Optional[bool] = None,
958
964
  **kw: Any,
959
965
  ) -> None:
960
966
  r"""Issue a "drop index" instruction using the current
@@ -971,11 +977,17 @@ def drop_index(
971
977
  quoting of the schema outside of the default behavior, use
972
978
  the SQLAlchemy construct
973
979
  :class:`~sqlalchemy.sql.elements.quoted_name`.
980
+
981
+ :param if_exists: If True, adds IF EXISTS operator when
982
+ dropping the index.
983
+
984
+ .. versionadded:: 1.12.0
985
+
974
986
  :param \**kw: Additional keyword arguments not mentioned above are
975
- dialect specific, and passed in the form
976
- ``<dialectname>_<argname>``.
977
- See the documentation regarding an individual dialect at
978
- :ref:`dialect_toplevel` for detail on documented arguments.
987
+ dialect specific, and passed in the form
988
+ ``<dialectname>_<argname>``.
989
+ See the documentation regarding an individual dialect at
990
+ :ref:`dialect_toplevel` for detail on documented arguments.
979
991
 
980
992
  """
981
993
 
@@ -1228,7 +1240,7 @@ def invoke(operation: MigrateOperation) -> Any:
1228
1240
 
1229
1241
  def register_operation(
1230
1242
  name: str, sourcename: Optional[str] = None
1231
- ) -> Callable[..., Any]:
1243
+ ) -> Callable[[_T], _T]:
1232
1244
  """Register a new operation for this class.
1233
1245
 
1234
1246
  This method is normally used to add new operations
@@ -86,7 +86,7 @@ class AbstractOperations(util.ModuleClsProxy):
86
86
  @classmethod
87
87
  def register_operation(
88
88
  cls, name: str, sourcename: Optional[str] = None
89
- ) -> Callable[..., Any]:
89
+ ) -> Callable[[_T], _T]:
90
90
  """Register a new operation for this class.
91
91
 
92
92
  This method is normally used to add new operations
@@ -1035,6 +1035,7 @@ class Operations(AbstractOperations):
1035
1035
  *,
1036
1036
  schema: Optional[str] = None,
1037
1037
  unique: bool = False,
1038
+ if_not_exists: Optional[bool] = None,
1038
1039
  **kw: Any,
1039
1040
  ) -> None:
1040
1041
  r"""Issue a "create index" instruction using the current
@@ -1064,20 +1065,24 @@ class Operations(AbstractOperations):
1064
1065
  :class:`~sqlalchemy.sql.elements.quoted_name`.
1065
1066
  :param unique: If True, create a unique index.
1066
1067
 
1067
- :param quote:
1068
- Force quoting of this column's name on or off, corresponding
1069
- to ``True`` or ``False``. When left at its default
1070
- of ``None``, the column identifier will be quoted according to
1071
- whether the name is case sensitive (identifiers with at least one
1072
- upper case character are treated as case sensitive), or if it's a
1073
- reserved word. This flag is only needed to force quoting of a
1074
- reserved word which is not known by the SQLAlchemy dialect.
1068
+ :param quote: Force quoting of this column's name on or off,
1069
+ corresponding to ``True`` or ``False``. When left at its default
1070
+ of ``None``, the column identifier will be quoted according to
1071
+ whether the name is case sensitive (identifiers with at least one
1072
+ upper case character are treated as case sensitive), or if it's a
1073
+ reserved word. This flag is only needed to force quoting of a
1074
+ reserved word which is not known by the SQLAlchemy dialect.
1075
+
1076
+ :param if_not_exists: If True, adds IF NOT EXISTS operator when
1077
+ creating the new index.
1078
+
1079
+ .. versionadded:: 1.12.0
1075
1080
 
1076
1081
  :param \**kw: Additional keyword arguments not mentioned above are
1077
- dialect specific, and passed in the form
1078
- ``<dialectname>_<argname>``.
1079
- See the documentation regarding an individual dialect at
1080
- :ref:`dialect_toplevel` for detail on documented arguments.
1082
+ dialect specific, and passed in the form
1083
+ ``<dialectname>_<argname>``.
1084
+ See the documentation regarding an individual dialect at
1085
+ :ref:`dialect_toplevel` for detail on documented arguments.
1081
1086
 
1082
1087
  """ # noqa: E501
1083
1088
  ...
@@ -1359,6 +1364,7 @@ class Operations(AbstractOperations):
1359
1364
  table_name: Optional[str] = None,
1360
1365
  *,
1361
1366
  schema: Optional[str] = None,
1367
+ if_exists: Optional[bool] = None,
1362
1368
  **kw: Any,
1363
1369
  ) -> None:
1364
1370
  r"""Issue a "drop index" instruction using the current
@@ -1375,11 +1381,17 @@ class Operations(AbstractOperations):
1375
1381
  quoting of the schema outside of the default behavior, use
1376
1382
  the SQLAlchemy construct
1377
1383
  :class:`~sqlalchemy.sql.elements.quoted_name`.
1384
+
1385
+ :param if_exists: If True, adds IF EXISTS operator when
1386
+ dropping the index.
1387
+
1388
+ .. versionadded:: 1.12.0
1389
+
1378
1390
  :param \**kw: Additional keyword arguments not mentioned above are
1379
- dialect specific, and passed in the form
1380
- ``<dialectname>_<argname>``.
1381
- See the documentation regarding an individual dialect at
1382
- :ref:`dialect_toplevel` for detail on documented arguments.
1391
+ dialect specific, and passed in the form
1392
+ ``<dialectname>_<argname>``.
1393
+ See the documentation regarding an individual dialect at
1394
+ :ref:`dialect_toplevel` for detail on documented arguments.
1383
1395
 
1384
1396
  """ # noqa: E501
1385
1397
  ...
@@ -185,11 +185,11 @@ class BatchOperationsImpl:
185
185
  def rename_table(self, *arg, **kw):
186
186
  self.batch.append(("rename_table", arg, kw))
187
187
 
188
- def create_index(self, idx: Index) -> None:
189
- self.batch.append(("create_index", (idx,), {}))
188
+ def create_index(self, idx: Index, **kw: Any) -> None:
189
+ self.batch.append(("create_index", (idx,), kw))
190
190
 
191
- def drop_index(self, idx: Index) -> None:
192
- self.batch.append(("drop_index", (idx,), {}))
191
+ def drop_index(self, idx: Index, **kw: Any) -> None:
192
+ self.batch.append(("drop_index", (idx,), kw))
193
193
 
194
194
  def create_table_comment(self, table):
195
195
  self.batch.append(("create_table_comment", (table,), {}))
@@ -337,7 +337,6 @@ class ApplyBatchImpl:
337
337
  for const in (
338
338
  list(self.named_constraints.values()) + self.unnamed_constraints
339
339
  ):
340
-
341
340
  const_columns = {c.key for c in _columns_for_constraint(const)}
342
341
 
343
342
  if not const_columns.issubset(self.column_transfers):
alembic/operations/ops.py CHANGED
@@ -53,6 +53,7 @@ if TYPE_CHECKING:
53
53
 
54
54
  from ..autogenerate.rewriter import Rewriter
55
55
  from ..runtime.migration import MigrationContext
56
+ from ..script.revision import _RevIdType
56
57
 
57
58
 
58
59
  class MigrateOperation:
@@ -175,7 +176,6 @@ class DropConstraintOp(MigrateOperation):
175
176
  )
176
177
 
177
178
  def to_constraint(self) -> Constraint:
178
-
179
179
  if self._reverse is not None:
180
180
  constraint = self._reverse.to_constraint()
181
181
  constraint.name = self.constraint_name
@@ -396,7 +396,6 @@ class CreateUniqueConstraintOp(AddConstraintOp):
396
396
  def from_constraint(
397
397
  cls, constraint: Constraint
398
398
  ) -> CreateUniqueConstraintOp:
399
-
400
399
  constraint_table = sqla_compat._table_for_constraint(constraint)
401
400
 
402
401
  uq_constraint = cast("UniqueConstraint", constraint)
@@ -534,7 +533,6 @@ class CreateForeignKeyOp(AddConstraintOp):
534
533
 
535
534
  @classmethod
536
535
  def from_constraint(cls, constraint: Constraint) -> CreateForeignKeyOp:
537
-
538
536
  fk_constraint = cast("ForeignKeyConstraint", constraint)
539
537
  kw: dict = {}
540
538
  if fk_constraint.onupdate:
@@ -878,6 +876,7 @@ class CreateIndexOp(MigrateOperation):
878
876
  *,
879
877
  schema: Optional[str] = None,
880
878
  unique: bool = False,
879
+ if_not_exists: Optional[bool] = None,
881
880
  **kw: Any,
882
881
  ) -> None:
883
882
  self.index_name = index_name
@@ -885,6 +884,7 @@ class CreateIndexOp(MigrateOperation):
885
884
  self.columns = columns
886
885
  self.schema = schema
887
886
  self.unique = unique
887
+ self.if_not_exists = if_not_exists
888
888
  self.kw = kw
889
889
 
890
890
  def reverse(self) -> DropIndexOp:
@@ -930,6 +930,7 @@ class CreateIndexOp(MigrateOperation):
930
930
  *,
931
931
  schema: Optional[str] = None,
932
932
  unique: bool = False,
933
+ if_not_exists: Optional[bool] = None,
933
934
  **kw: Any,
934
935
  ) -> None:
935
936
  r"""Issue a "create index" instruction using the current
@@ -959,24 +960,34 @@ class CreateIndexOp(MigrateOperation):
959
960
  :class:`~sqlalchemy.sql.elements.quoted_name`.
960
961
  :param unique: If True, create a unique index.
961
962
 
962
- :param quote:
963
- Force quoting of this column's name on or off, corresponding
964
- to ``True`` or ``False``. When left at its default
965
- of ``None``, the column identifier will be quoted according to
966
- whether the name is case sensitive (identifiers with at least one
967
- upper case character are treated as case sensitive), or if it's a
968
- reserved word. This flag is only needed to force quoting of a
969
- reserved word which is not known by the SQLAlchemy dialect.
963
+ :param quote: Force quoting of this column's name on or off,
964
+ corresponding to ``True`` or ``False``. When left at its default
965
+ of ``None``, the column identifier will be quoted according to
966
+ whether the name is case sensitive (identifiers with at least one
967
+ upper case character are treated as case sensitive), or if it's a
968
+ reserved word. This flag is only needed to force quoting of a
969
+ reserved word which is not known by the SQLAlchemy dialect.
970
+
971
+ :param if_not_exists: If True, adds IF NOT EXISTS operator when
972
+ creating the new index.
973
+
974
+ .. versionadded:: 1.12.0
970
975
 
971
976
  :param \**kw: Additional keyword arguments not mentioned above are
972
- dialect specific, and passed in the form
973
- ``<dialectname>_<argname>``.
974
- See the documentation regarding an individual dialect at
975
- :ref:`dialect_toplevel` for detail on documented arguments.
977
+ dialect specific, and passed in the form
978
+ ``<dialectname>_<argname>``.
979
+ See the documentation regarding an individual dialect at
980
+ :ref:`dialect_toplevel` for detail on documented arguments.
976
981
 
977
982
  """
978
983
  op = cls(
979
- index_name, table_name, columns, schema=schema, unique=unique, **kw
984
+ index_name,
985
+ table_name,
986
+ columns,
987
+ schema=schema,
988
+ unique=unique,
989
+ if_not_exists=if_not_exists,
990
+ **kw,
980
991
  )
981
992
  return operations.invoke(op)
982
993
 
@@ -1018,12 +1029,14 @@ class DropIndexOp(MigrateOperation):
1018
1029
  table_name: Optional[str] = None,
1019
1030
  *,
1020
1031
  schema: Optional[str] = None,
1032
+ if_exists: Optional[bool] = None,
1021
1033
  _reverse: Optional[CreateIndexOp] = None,
1022
1034
  **kw: Any,
1023
1035
  ) -> None:
1024
1036
  self.index_name = index_name
1025
1037
  self.table_name = table_name
1026
1038
  self.schema = schema
1039
+ self.if_exists = if_exists
1027
1040
  self._reverse = _reverse
1028
1041
  self.kw = kw
1029
1042
 
@@ -1067,6 +1080,7 @@ class DropIndexOp(MigrateOperation):
1067
1080
  table_name: Optional[str] = None,
1068
1081
  *,
1069
1082
  schema: Optional[str] = None,
1083
+ if_exists: Optional[bool] = None,
1070
1084
  **kw: Any,
1071
1085
  ) -> None:
1072
1086
  r"""Issue a "drop index" instruction using the current
@@ -1083,14 +1097,26 @@ class DropIndexOp(MigrateOperation):
1083
1097
  quoting of the schema outside of the default behavior, use
1084
1098
  the SQLAlchemy construct
1085
1099
  :class:`~sqlalchemy.sql.elements.quoted_name`.
1100
+
1101
+ :param if_exists: If True, adds IF EXISTS operator when
1102
+ dropping the index.
1103
+
1104
+ .. versionadded:: 1.12.0
1105
+
1086
1106
  :param \**kw: Additional keyword arguments not mentioned above are
1087
- dialect specific, and passed in the form
1088
- ``<dialectname>_<argname>``.
1089
- See the documentation regarding an individual dialect at
1090
- :ref:`dialect_toplevel` for detail on documented arguments.
1107
+ dialect specific, and passed in the form
1108
+ ``<dialectname>_<argname>``.
1109
+ See the documentation regarding an individual dialect at
1110
+ :ref:`dialect_toplevel` for detail on documented arguments.
1091
1111
 
1092
1112
  """
1093
- op = cls(index_name, table_name=table_name, schema=schema, **kw)
1113
+ op = cls(
1114
+ index_name,
1115
+ table_name=table_name,
1116
+ schema=schema,
1117
+ if_exists=if_exists,
1118
+ **kw,
1119
+ )
1094
1120
  return operations.invoke(op)
1095
1121
 
1096
1122
  @classmethod
@@ -1757,7 +1783,6 @@ class AlterColumnOp(AlterTableOp):
1757
1783
  return False
1758
1784
 
1759
1785
  def reverse(self) -> AlterColumnOp:
1760
-
1761
1786
  kw = self.kw.copy()
1762
1787
  kw["existing_type"] = self.existing_type
1763
1788
  kw["existing_nullable"] = self.existing_nullable
@@ -2667,9 +2692,9 @@ class MigrationScript(MigrateOperation):
2667
2692
  imports: Set[str] = set(),
2668
2693
  head: Optional[str] = None,
2669
2694
  splice: Optional[bool] = None,
2670
- branch_label: Optional[str] = None,
2695
+ branch_label: Optional[_RevIdType] = None,
2671
2696
  version_path: Optional[str] = None,
2672
- depends_on: Optional[Union[str, Sequence[str]]] = None,
2697
+ depends_on: Optional[_RevIdType] = None,
2673
2698
  ) -> None:
2674
2699
  self.rev_id = rev_id
2675
2700
  self.message = message
@@ -5,6 +5,7 @@ from sqlalchemy import schema as sa_schema
5
5
  from . import ops
6
6
  from .base import Operations
7
7
  from ..util.sqla_compat import _copy
8
+ from ..util.sqla_compat import sqla_2
8
9
 
9
10
  if TYPE_CHECKING:
10
11
  from sqlalchemy.sql.schema import Table
@@ -14,7 +15,6 @@ if TYPE_CHECKING:
14
15
  def alter_column(
15
16
  operations: "Operations", operation: "ops.AlterColumnOp"
16
17
  ) -> None:
17
-
18
18
  compiler = operations.impl.dialect.statement_compiler(
19
19
  operations.impl.dialect, None
20
20
  )
@@ -60,7 +60,7 @@ def alter_column(
60
60
  existing_nullable=existing_nullable,
61
61
  comment=comment,
62
62
  existing_comment=existing_comment,
63
- **operation.kw
63
+ **operation.kw,
64
64
  )
65
65
 
66
66
  if type_:
@@ -96,13 +96,27 @@ def create_index(
96
96
  operations: "Operations", operation: "ops.CreateIndexOp"
97
97
  ) -> None:
98
98
  idx = operation.to_index(operations.migration_context)
99
- operations.impl.create_index(idx)
99
+ kw = {}
100
+ if operation.if_not_exists is not None:
101
+ if not sqla_2:
102
+ raise NotImplementedError("SQLAlchemy 2.0+ required")
103
+
104
+ kw["if_not_exists"] = operation.if_not_exists
105
+ operations.impl.create_index(idx, **kw)
100
106
 
101
107
 
102
108
  @Operations.implementation_for(ops.DropIndexOp)
103
109
  def drop_index(operations: "Operations", operation: "ops.DropIndexOp") -> None:
110
+ kw = {}
111
+ if operation.if_exists is not None:
112
+ if not sqla_2:
113
+ raise NotImplementedError("SQLAlchemy 2.0+ required")
114
+
115
+ kw["if_exists"] = operation.if_exists
116
+
104
117
  operations.impl.drop_index(
105
- operation.to_index(operations.migration_context)
118
+ operation.to_index(operations.migration_context),
119
+ **kw,
106
120
  )
107
121
 
108
122
 
@@ -25,7 +25,6 @@ from .. import util
25
25
  from ..operations import Operations
26
26
 
27
27
  if TYPE_CHECKING:
28
-
29
28
  from sqlalchemy.engine import URL
30
29
  from sqlalchemy.engine.base import Connection
31
30
  from sqlalchemy.sql.elements import ClauseElement
@@ -522,7 +522,6 @@ class MigrationContext:
522
522
  if start_from_rev == "base":
523
523
  start_from_rev = None
524
524
  elif start_from_rev is not None and self.script:
525
-
526
525
  start_from_rev = [
527
526
  cast("Script", self.script.get_revision(sfr)).revision
528
527
  for sfr in util.to_list(start_from_rev)
@@ -614,7 +613,6 @@ class MigrationContext:
614
613
  assert self._migrations_fn is not None
615
614
  for step in self._migrations_fn(heads, self):
616
615
  with self.begin_transaction(_per_migration=True):
617
-
618
616
  if self.as_sql and not head_maintainer.heads:
619
617
  # for offline mode, include a CREATE TABLE from
620
618
  # the base
@@ -733,7 +731,6 @@ class MigrationContext:
733
731
  rendered_metadata_default: Optional[str],
734
732
  rendered_column_default: Optional[str],
735
733
  ) -> bool:
736
-
737
734
  if self._user_compare_server_default is False:
738
735
  return False
739
736
 
@@ -1000,7 +997,6 @@ class MigrationInfo:
1000
997
 
1001
998
 
1002
999
  class MigrationStep:
1003
-
1004
1000
  from_revisions_no_deps: Tuple[str, ...]
1005
1001
  to_revisions_no_deps: Tuple[str, ...]
1006
1002
  is_upgrade: bool
alembic/script/base.py CHANGED
@@ -26,23 +26,21 @@ from ..runtime import migration
26
26
  from ..util import not_none
27
27
 
28
28
  if TYPE_CHECKING:
29
+ from .revision import _RevIdType
30
+ from .revision import Revision
29
31
  from ..config import Config
30
32
  from ..config import MessagingOptions
31
33
  from ..runtime.migration import RevisionStep
32
34
  from ..runtime.migration import StampStep
33
- from ..script.revision import Revision
34
35
 
35
36
  try:
36
37
  from dateutil import tz
37
38
  except ImportError:
38
39
  tz = None # type: ignore[assignment]
39
40
 
40
- _RevIdType = Union[str, Sequence[str]]
41
-
42
41
  _sourceless_rev_file = re.compile(r"(?!\.\#|__init__)(.*\.py)(c|o)?$")
43
42
  _only_source_rev_file = re.compile(r"(?!\.\#|__init__)(.*\.py)$")
44
43
  _legacy_rev = re.compile(r"([a-f0-9]+)\.py$")
45
- _mod_def_re = re.compile(r"(upgrade|downgrade)_([a-z0-9]+)")
46
44
  _slug_re = re.compile(r"\w+")
47
45
  _default_file_template = "%(rev)s_%(slug)s"
48
46
  _split_on_space_comma = re.compile(r", *|(?: +)")
@@ -481,7 +479,6 @@ class ScriptDirectory:
481
479
  multiple_heads="Multiple heads are present; please specify a "
482
480
  "single target revision"
483
481
  ):
484
-
485
482
  heads_revs = self.get_revisions(heads)
486
483
 
487
484
  steps = []
@@ -504,7 +501,6 @@ class ScriptDirectory:
504
501
  dests = self.get_revisions(revision) or [None]
505
502
 
506
503
  for dest in dests:
507
-
508
504
  if dest is None:
509
505
  # dest is 'base'. Return a "delete branch" migration
510
506
  # for all applicable heads.
@@ -637,7 +633,7 @@ class ScriptDirectory:
637
633
  head: Optional[str] = None,
638
634
  refresh: bool = False,
639
635
  splice: Optional[bool] = False,
640
- branch_labels: Optional[str] = None,
636
+ branch_labels: Optional[_RevIdType] = None,
641
637
  version_path: Optional[str] = None,
642
638
  depends_on: Optional[_RevIdType] = None,
643
639
  **kw: Any,
@@ -336,7 +336,6 @@ class RevisionMap:
336
336
  and not parent._is_real_branch_point
337
337
  and not parent.is_merge_point
338
338
  ):
339
-
340
339
  parent.branch_labels.update(revision.branch_labels)
341
340
  if parent.down_revision:
342
341
  parent = map_[parent.down_revision]
@@ -813,7 +812,6 @@ class RevisionMap:
813
812
  omit_immediate_dependencies: bool = False,
814
813
  include_dependencies: bool = True,
815
814
  ) -> Iterator[Any]:
816
-
817
815
  if omit_immediate_dependencies:
818
816
 
819
817
  def fn(rev):
@@ -843,7 +841,6 @@ class RevisionMap:
843
841
  check: bool = False,
844
842
  include_dependencies: bool = True,
845
843
  ) -> Iterator[Revision]:
846
-
847
844
  if include_dependencies:
848
845
 
849
846
  def fn(rev):
@@ -945,7 +942,6 @@ class RevisionMap:
945
942
 
946
943
  current_candidate_idx = 0
947
944
  while current_heads:
948
-
949
945
  candidate = current_heads[current_candidate_idx]
950
946
 
951
947
  for check_head_index, ancestors in enumerate(ancestors_by_idx):
@@ -56,7 +56,7 @@ def _invoke(
56
56
  hook = _registry[name]
57
57
  except KeyError as ke:
58
58
  raise util.CommandError(
59
- "No formatter with name '%s' registered" % name
59
+ f"No formatter with name '{name}' registered"
60
60
  ) from ke
61
61
  else:
62
62
  return hook(revision, options)
@@ -82,10 +82,12 @@ def _run_hooks(path: str, hook_config: Mapping[str, str]) -> None:
82
82
  type_ = opts["type"]
83
83
  except KeyError as ke:
84
84
  raise util.CommandError(
85
- "Key %s.type is required for post write hook %r" % (name, name)
85
+ f"Key {name}.type is required for post write hook {name!r}"
86
86
  ) from ke
87
87
  else:
88
- with util.status("Running post write hook {name!r}", newline=True):
88
+ with util.status(
89
+ f"Running post write hook {name!r}", newline=True
90
+ ):
89
91
  _invoke(type_, path, opts)
90
92
 
91
93
 
@@ -114,13 +116,12 @@ def _parse_cmdline_options(cmdline_options_str: str, path: str) -> List[str]:
114
116
  def console_scripts(
115
117
  path: str, options: dict, ignore_output: bool = False
116
118
  ) -> None:
117
-
118
119
  try:
119
120
  entrypoint_name = options["entrypoint"]
120
121
  except KeyError as ke:
121
122
  raise util.CommandError(
122
- "Key %s.entrypoint is required for post write hook %r"
123
- % (options["_hook_name"], options["_hook_name"])
123
+ f"Key {options['_hook_name']}.entrypoint is required for post "
124
+ f"write hook {options['_hook_name']!r}"
124
125
  ) from ke
125
126
  for entry in compat.importlib_metadata_get("console_scripts"):
126
127
  if entry.name == entrypoint_name:
@@ -142,7 +143,7 @@ def console_scripts(
142
143
  [
143
144
  sys.executable,
144
145
  "-c",
145
- "import %s; %s.%s()" % (impl.module, impl.module, impl.attr),
146
+ f"import {impl.module}; {impl.module}.{impl.attr}()",
146
147
  ]
147
148
  + cmdline_options_list,
148
149
  cwd=cwd,
@@ -5,15 +5,17 @@ Revises: ${down_revision | comma,n}
5
5
  Create Date: ${create_date}
6
6
 
7
7
  """
8
+ from typing import Sequence, Union
9
+
8
10
  from alembic import op
9
11
  import sqlalchemy as sa
10
12
  ${imports if imports else ""}
11
13
 
12
14
  # revision identifiers, used by Alembic.
13
- revision = ${repr(up_revision)}
14
- down_revision = ${repr(down_revision)}
15
- branch_labels = ${repr(branch_labels)}
16
- depends_on = ${repr(depends_on)}
15
+ revision: str = ${repr(up_revision)}
16
+ down_revision: Union[str, None] = ${repr(down_revision)}
17
+ branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
18
+ depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
17
19
 
18
20
 
19
21
  def upgrade() -> None:
@@ -5,15 +5,17 @@ Revises: ${down_revision | comma,n}
5
5
  Create Date: ${create_date}
6
6
 
7
7
  """
8
+ from typing import Sequence, Union
9
+
8
10
  from alembic import op
9
11
  import sqlalchemy as sa
10
12
  ${imports if imports else ""}
11
13
 
12
14
  # revision identifiers, used by Alembic.
13
- revision = ${repr(up_revision)}
14
- down_revision = ${repr(down_revision)}
15
- branch_labels = ${repr(branch_labels)}
16
- depends_on = ${repr(depends_on)}
15
+ revision: str = ${repr(up_revision)}
16
+ down_revision: Union[str, None] = ${repr(down_revision)}
17
+ branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
18
+ depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
17
19
 
18
20
 
19
21
  def upgrade() -> None:
@@ -8,15 +8,17 @@ Revises: ${down_revision | comma,n}
8
8
  Create Date: ${create_date}
9
9
 
10
10
  """
11
+ from typing import Sequence, Union
12
+
11
13
  from alembic import op
12
14
  import sqlalchemy as sa
13
15
  ${imports if imports else ""}
14
16
 
15
17
  # revision identifiers, used by Alembic.
16
- revision = ${repr(up_revision)}
17
- down_revision = ${repr(down_revision)}
18
- branch_labels = ${repr(branch_labels)}
19
- depends_on = ${repr(depends_on)}
18
+ revision: str = ${repr(up_revision)}
19
+ down_revision: Union[str, None] = ${repr(down_revision)}
20
+ branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
21
+ depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
20
22
 
21
23
 
22
24
  def upgrade(engine_name: str) -> None: