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.
- alembic/__init__.py +1 -1
- alembic/autogenerate/__init__.py +10 -10
- alembic/autogenerate/api.py +6 -4
- alembic/autogenerate/compare.py +5 -4
- alembic/autogenerate/render.py +9 -9
- alembic/autogenerate/rewriter.py +26 -13
- alembic/command.py +3 -1
- alembic/config.py +20 -9
- alembic/context.pyi +10 -5
- alembic/ddl/__init__.py +1 -1
- alembic/ddl/_autogen.py +4 -2
- alembic/ddl/base.py +12 -9
- alembic/ddl/impl.py +5 -2
- alembic/ddl/mssql.py +4 -1
- alembic/ddl/mysql.py +5 -3
- alembic/ddl/oracle.py +4 -1
- alembic/ddl/postgresql.py +16 -9
- alembic/ddl/sqlite.py +8 -6
- alembic/op.pyi +46 -8
- alembic/operations/base.py +70 -14
- alembic/operations/batch.py +7 -8
- alembic/operations/ops.py +52 -30
- alembic/operations/schemaobj.py +5 -4
- alembic/operations/toimpl.py +3 -0
- alembic/runtime/environment.py +15 -6
- alembic/runtime/migration.py +27 -11
- alembic/script/base.py +13 -15
- alembic/script/revision.py +30 -17
- alembic/script/write_hooks.py +3 -0
- alembic/util/__init__.py +31 -31
- alembic/util/compat.py +25 -8
- alembic/util/langhelpers.py +78 -33
- alembic/util/messaging.py +6 -3
- alembic/util/pyfiles.py +7 -3
- alembic/util/sqla_compat.py +43 -14
- {alembic-1.13.0.dist-info → alembic-1.13.1.dist-info}/METADATA +1 -1
- {alembic-1.13.0.dist-info → alembic-1.13.1.dist-info}/RECORD +41 -41
- {alembic-1.13.0.dist-info → alembic-1.13.1.dist-info}/LICENSE +0 -0
- {alembic-1.13.0.dist-info → alembic-1.13.1.dist-info}/WHEEL +0 -0
- {alembic-1.13.0.dist-info → alembic-1.13.1.dist-info}/entry_points.txt +0 -0
- {alembic-1.13.0.dist-info → alembic-1.13.1.dist-info}/top_level.txt +0 -0
alembic/operations/ops.py
CHANGED
@@ -5,6 +5,7 @@ import re
|
|
5
5
|
from typing import Any
|
6
6
|
from typing import Callable
|
7
7
|
from typing import cast
|
8
|
+
from typing import Dict
|
8
9
|
from typing import FrozenSet
|
9
10
|
from typing import Iterator
|
10
11
|
from typing import List
|
@@ -15,6 +16,7 @@ from typing import Set
|
|
15
16
|
from typing import Tuple
|
16
17
|
from typing import Type
|
17
18
|
from typing import TYPE_CHECKING
|
19
|
+
from typing import TypeVar
|
18
20
|
from typing import Union
|
19
21
|
|
20
22
|
from sqlalchemy.types import NULLTYPE
|
@@ -53,6 +55,9 @@ if TYPE_CHECKING:
|
|
53
55
|
from ..runtime.migration import MigrationContext
|
54
56
|
from ..script.revision import _RevIdType
|
55
57
|
|
58
|
+
_T = TypeVar("_T", bound=Any)
|
59
|
+
_AC = TypeVar("_AC", bound="AddConstraintOp")
|
60
|
+
|
56
61
|
|
57
62
|
class MigrateOperation:
|
58
63
|
"""base class for migration command and organization objects.
|
@@ -70,7 +75,7 @@ class MigrateOperation:
|
|
70
75
|
"""
|
71
76
|
|
72
77
|
@util.memoized_property
|
73
|
-
def info(self):
|
78
|
+
def info(self) -> Dict[Any, Any]:
|
74
79
|
"""A dictionary that may be used to store arbitrary information
|
75
80
|
along with this :class:`.MigrateOperation` object.
|
76
81
|
|
@@ -92,12 +97,14 @@ class AddConstraintOp(MigrateOperation):
|
|
92
97
|
add_constraint_ops = util.Dispatcher()
|
93
98
|
|
94
99
|
@property
|
95
|
-
def constraint_type(self):
|
100
|
+
def constraint_type(self) -> str:
|
96
101
|
raise NotImplementedError()
|
97
102
|
|
98
103
|
@classmethod
|
99
|
-
def register_add_constraint(
|
100
|
-
|
104
|
+
def register_add_constraint(
|
105
|
+
cls, type_: str
|
106
|
+
) -> Callable[[Type[_AC]], Type[_AC]]:
|
107
|
+
def go(klass: Type[_AC]) -> Type[_AC]:
|
101
108
|
cls.add_constraint_ops.dispatch_for(type_)(klass.from_constraint)
|
102
109
|
return klass
|
103
110
|
|
@@ -105,7 +112,7 @@ class AddConstraintOp(MigrateOperation):
|
|
105
112
|
|
106
113
|
@classmethod
|
107
114
|
def from_constraint(cls, constraint: Constraint) -> AddConstraintOp:
|
108
|
-
return cls.add_constraint_ops.dispatch(constraint.__visit_name__)(
|
115
|
+
return cls.add_constraint_ops.dispatch(constraint.__visit_name__)( # type: ignore[no-any-return] # noqa: E501
|
109
116
|
constraint
|
110
117
|
)
|
111
118
|
|
@@ -398,7 +405,7 @@ class CreateUniqueConstraintOp(AddConstraintOp):
|
|
398
405
|
|
399
406
|
uq_constraint = cast("UniqueConstraint", constraint)
|
400
407
|
|
401
|
-
kw:
|
408
|
+
kw: Dict[str, Any] = {}
|
402
409
|
if uq_constraint.deferrable:
|
403
410
|
kw["deferrable"] = uq_constraint.deferrable
|
404
411
|
if uq_constraint.initially:
|
@@ -532,7 +539,7 @@ class CreateForeignKeyOp(AddConstraintOp):
|
|
532
539
|
@classmethod
|
533
540
|
def from_constraint(cls, constraint: Constraint) -> CreateForeignKeyOp:
|
534
541
|
fk_constraint = cast("ForeignKeyConstraint", constraint)
|
535
|
-
kw:
|
542
|
+
kw: Dict[str, Any] = {}
|
536
543
|
if fk_constraint.onupdate:
|
537
544
|
kw["onupdate"] = fk_constraint.onupdate
|
538
545
|
if fk_constraint.ondelete:
|
@@ -897,7 +904,7 @@ class CreateIndexOp(MigrateOperation):
|
|
897
904
|
def from_index(cls, index: Index) -> CreateIndexOp:
|
898
905
|
assert index.table is not None
|
899
906
|
return cls(
|
900
|
-
index.name,
|
907
|
+
index.name,
|
901
908
|
index.table.name,
|
902
909
|
index.expressions,
|
903
910
|
schema=index.table.schema,
|
@@ -1054,6 +1061,7 @@ class DropIndexOp(MigrateOperation):
|
|
1054
1061
|
table_name=index.table.name,
|
1055
1062
|
schema=index.table.schema,
|
1056
1063
|
_reverse=CreateIndexOp.from_index(index),
|
1064
|
+
unique=index.unique,
|
1057
1065
|
**index.kwargs,
|
1058
1066
|
)
|
1059
1067
|
|
@@ -1182,7 +1190,7 @@ class CreateTableOp(MigrateOperation):
|
|
1182
1190
|
|
1183
1191
|
return cls(
|
1184
1192
|
table.name,
|
1185
|
-
list(table.c) + list(table.constraints),
|
1193
|
+
list(table.c) + list(table.constraints),
|
1186
1194
|
schema=table.schema,
|
1187
1195
|
_namespace_metadata=_namespace_metadata,
|
1188
1196
|
# given a Table() object, this Table will contain full Index()
|
@@ -1534,7 +1542,7 @@ class CreateTableCommentOp(AlterTableOp):
|
|
1534
1542
|
)
|
1535
1543
|
return operations.invoke(op)
|
1536
1544
|
|
1537
|
-
def reverse(self):
|
1545
|
+
def reverse(self) -> Union[CreateTableCommentOp, DropTableCommentOp]:
|
1538
1546
|
"""Reverses the COMMENT ON operation against a table."""
|
1539
1547
|
if self.existing_comment is None:
|
1540
1548
|
return DropTableCommentOp(
|
@@ -1550,14 +1558,16 @@ class CreateTableCommentOp(AlterTableOp):
|
|
1550
1558
|
schema=self.schema,
|
1551
1559
|
)
|
1552
1560
|
|
1553
|
-
def to_table(
|
1561
|
+
def to_table(
|
1562
|
+
self, migration_context: Optional[MigrationContext] = None
|
1563
|
+
) -> Table:
|
1554
1564
|
schema_obj = schemaobj.SchemaObjects(migration_context)
|
1555
1565
|
|
1556
1566
|
return schema_obj.table(
|
1557
1567
|
self.table_name, schema=self.schema, comment=self.comment
|
1558
1568
|
)
|
1559
1569
|
|
1560
|
-
def to_diff_tuple(self):
|
1570
|
+
def to_diff_tuple(self) -> Tuple[Any, ...]:
|
1561
1571
|
return ("add_table_comment", self.to_table(), self.existing_comment)
|
1562
1572
|
|
1563
1573
|
|
@@ -1629,18 +1639,20 @@ class DropTableCommentOp(AlterTableOp):
|
|
1629
1639
|
)
|
1630
1640
|
return operations.invoke(op)
|
1631
1641
|
|
1632
|
-
def reverse(self):
|
1642
|
+
def reverse(self) -> CreateTableCommentOp:
|
1633
1643
|
"""Reverses the COMMENT ON operation against a table."""
|
1634
1644
|
return CreateTableCommentOp(
|
1635
1645
|
self.table_name, self.existing_comment, schema=self.schema
|
1636
1646
|
)
|
1637
1647
|
|
1638
|
-
def to_table(
|
1648
|
+
def to_table(
|
1649
|
+
self, migration_context: Optional[MigrationContext] = None
|
1650
|
+
) -> Table:
|
1639
1651
|
schema_obj = schemaobj.SchemaObjects(migration_context)
|
1640
1652
|
|
1641
1653
|
return schema_obj.table(self.table_name, schema=self.schema)
|
1642
1654
|
|
1643
|
-
def to_diff_tuple(self):
|
1655
|
+
def to_diff_tuple(self) -> Tuple[Any, ...]:
|
1644
1656
|
return ("remove_table_comment", self.to_table())
|
1645
1657
|
|
1646
1658
|
|
@@ -1817,8 +1829,10 @@ class AlterColumnOp(AlterTableOp):
|
|
1817
1829
|
comment: Optional[Union[str, Literal[False]]] = False,
|
1818
1830
|
server_default: Any = False,
|
1819
1831
|
new_column_name: Optional[str] = None,
|
1820
|
-
type_: Optional[Union[TypeEngine, Type[TypeEngine]]] = None,
|
1821
|
-
existing_type: Optional[
|
1832
|
+
type_: Optional[Union[TypeEngine[Any], Type[TypeEngine[Any]]]] = None,
|
1833
|
+
existing_type: Optional[
|
1834
|
+
Union[TypeEngine[Any], Type[TypeEngine[Any]]]
|
1835
|
+
] = None,
|
1822
1836
|
existing_server_default: Optional[
|
1823
1837
|
Union[str, bool, Identity, Computed]
|
1824
1838
|
] = False,
|
@@ -1938,8 +1952,10 @@ class AlterColumnOp(AlterTableOp):
|
|
1938
1952
|
comment: Optional[Union[str, Literal[False]]] = False,
|
1939
1953
|
server_default: Any = False,
|
1940
1954
|
new_column_name: Optional[str] = None,
|
1941
|
-
type_: Optional[Union[TypeEngine, Type[TypeEngine]]] = None,
|
1942
|
-
existing_type: Optional[
|
1955
|
+
type_: Optional[Union[TypeEngine[Any], Type[TypeEngine[Any]]]] = None,
|
1956
|
+
existing_type: Optional[
|
1957
|
+
Union[TypeEngine[Any], Type[TypeEngine[Any]]]
|
1958
|
+
] = None,
|
1943
1959
|
existing_server_default: Optional[
|
1944
1960
|
Union[str, bool, Identity, Computed]
|
1945
1961
|
] = False,
|
@@ -2019,11 +2035,11 @@ class AddColumnOp(AlterTableOp):
|
|
2019
2035
|
) -> Tuple[str, Optional[str], str, Column[Any]]:
|
2020
2036
|
return ("add_column", self.schema, self.table_name, self.column)
|
2021
2037
|
|
2022
|
-
def to_column(self) -> Column:
|
2038
|
+
def to_column(self) -> Column[Any]:
|
2023
2039
|
return self.column
|
2024
2040
|
|
2025
2041
|
@classmethod
|
2026
|
-
def from_column(cls, col: Column) -> AddColumnOp:
|
2042
|
+
def from_column(cls, col: Column[Any]) -> AddColumnOp:
|
2027
2043
|
return cls(col.table.name, col, schema=col.table.schema)
|
2028
2044
|
|
2029
2045
|
@classmethod
|
@@ -2214,7 +2230,7 @@ class DropColumnOp(AlterTableOp):
|
|
2214
2230
|
|
2215
2231
|
def to_column(
|
2216
2232
|
self, migration_context: Optional[MigrationContext] = None
|
2217
|
-
) -> Column:
|
2233
|
+
) -> Column[Any]:
|
2218
2234
|
if self._reverse is not None:
|
2219
2235
|
return self._reverse.column
|
2220
2236
|
schema_obj = schemaobj.SchemaObjects(migration_context)
|
@@ -2298,7 +2314,7 @@ class BulkInsertOp(MigrateOperation):
|
|
2298
2314
|
def __init__(
|
2299
2315
|
self,
|
2300
2316
|
table: Union[Table, TableClause],
|
2301
|
-
rows: List[
|
2317
|
+
rows: List[Dict[str, Any]],
|
2302
2318
|
*,
|
2303
2319
|
multiinsert: bool = True,
|
2304
2320
|
) -> None:
|
@@ -2311,7 +2327,7 @@ class BulkInsertOp(MigrateOperation):
|
|
2311
2327
|
cls,
|
2312
2328
|
operations: Operations,
|
2313
2329
|
table: Union[Table, TableClause],
|
2314
|
-
rows: List[
|
2330
|
+
rows: List[Dict[str, Any]],
|
2315
2331
|
*,
|
2316
2332
|
multiinsert: bool = True,
|
2317
2333
|
) -> None:
|
@@ -2607,7 +2623,7 @@ class UpgradeOps(OpContainer):
|
|
2607
2623
|
self.upgrade_token = upgrade_token
|
2608
2624
|
|
2609
2625
|
def reverse_into(self, downgrade_ops: DowngradeOps) -> DowngradeOps:
|
2610
|
-
downgrade_ops.ops[:] = list(
|
2626
|
+
downgrade_ops.ops[:] = list(
|
2611
2627
|
reversed([op.reverse() for op in self.ops])
|
2612
2628
|
)
|
2613
2629
|
return downgrade_ops
|
@@ -2634,7 +2650,7 @@ class DowngradeOps(OpContainer):
|
|
2634
2650
|
super().__init__(ops=ops)
|
2635
2651
|
self.downgrade_token = downgrade_token
|
2636
2652
|
|
2637
|
-
def reverse(self):
|
2653
|
+
def reverse(self) -> UpgradeOps:
|
2638
2654
|
return UpgradeOps(
|
2639
2655
|
ops=list(reversed([op.reverse() for op in self.ops]))
|
2640
2656
|
)
|
@@ -2665,6 +2681,8 @@ class MigrationScript(MigrateOperation):
|
|
2665
2681
|
"""
|
2666
2682
|
|
2667
2683
|
_needs_render: Optional[bool]
|
2684
|
+
_upgrade_ops: List[UpgradeOps]
|
2685
|
+
_downgrade_ops: List[DowngradeOps]
|
2668
2686
|
|
2669
2687
|
def __init__(
|
2670
2688
|
self,
|
@@ -2692,7 +2710,7 @@ class MigrationScript(MigrateOperation):
|
|
2692
2710
|
self.downgrade_ops = downgrade_ops
|
2693
2711
|
|
2694
2712
|
@property
|
2695
|
-
def upgrade_ops(self):
|
2713
|
+
def upgrade_ops(self) -> Optional[UpgradeOps]:
|
2696
2714
|
"""An instance of :class:`.UpgradeOps`.
|
2697
2715
|
|
2698
2716
|
.. seealso::
|
@@ -2711,13 +2729,15 @@ class MigrationScript(MigrateOperation):
|
|
2711
2729
|
return self._upgrade_ops[0]
|
2712
2730
|
|
2713
2731
|
@upgrade_ops.setter
|
2714
|
-
def upgrade_ops(
|
2732
|
+
def upgrade_ops(
|
2733
|
+
self, upgrade_ops: Union[UpgradeOps, List[UpgradeOps]]
|
2734
|
+
) -> None:
|
2715
2735
|
self._upgrade_ops = util.to_list(upgrade_ops)
|
2716
2736
|
for elem in self._upgrade_ops:
|
2717
2737
|
assert isinstance(elem, UpgradeOps)
|
2718
2738
|
|
2719
2739
|
@property
|
2720
|
-
def downgrade_ops(self):
|
2740
|
+
def downgrade_ops(self) -> Optional[DowngradeOps]:
|
2721
2741
|
"""An instance of :class:`.DowngradeOps`.
|
2722
2742
|
|
2723
2743
|
.. seealso::
|
@@ -2736,7 +2756,9 @@ class MigrationScript(MigrateOperation):
|
|
2736
2756
|
return self._downgrade_ops[0]
|
2737
2757
|
|
2738
2758
|
@downgrade_ops.setter
|
2739
|
-
def downgrade_ops(
|
2759
|
+
def downgrade_ops(
|
2760
|
+
self, downgrade_ops: Union[DowngradeOps, List[DowngradeOps]]
|
2761
|
+
) -> None:
|
2740
2762
|
self._downgrade_ops = util.to_list(downgrade_ops)
|
2741
2763
|
for elem in self._downgrade_ops:
|
2742
2764
|
assert isinstance(elem, DowngradeOps)
|
alembic/operations/schemaobj.py
CHANGED
@@ -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
|
from typing import Any
|
@@ -274,10 +277,8 @@ class SchemaObjects:
|
|
274
277
|
ForeignKey.
|
275
278
|
|
276
279
|
"""
|
277
|
-
if isinstance(fk._colspec, str):
|
278
|
-
table_key, cname = fk._colspec.rsplit(
|
279
|
-
".", 1
|
280
|
-
)
|
280
|
+
if isinstance(fk._colspec, str):
|
281
|
+
table_key, cname = fk._colspec.rsplit(".", 1)
|
281
282
|
sname, tname = self._parse_table_key(table_key)
|
282
283
|
if table_key not in metadata.tables:
|
283
284
|
rel_t = sa_schema.Table(tname, metadata, schema=sname)
|
alembic/operations/toimpl.py
CHANGED
alembic/runtime/environment.py
CHANGED
@@ -228,9 +228,9 @@ class EnvironmentContext(util.ModuleClsProxy):
|
|
228
228
|
has been configured.
|
229
229
|
|
230
230
|
"""
|
231
|
-
return self.context_opts.get("as_sql", False)
|
231
|
+
return self.context_opts.get("as_sql", False) # type: ignore[no-any-return] # noqa: E501
|
232
232
|
|
233
|
-
def is_transactional_ddl(self):
|
233
|
+
def is_transactional_ddl(self) -> bool:
|
234
234
|
"""Return True if the context is configured to expect a
|
235
235
|
transactional DDL capable backend.
|
236
236
|
|
@@ -339,7 +339,7 @@ class EnvironmentContext(util.ModuleClsProxy):
|
|
339
339
|
line.
|
340
340
|
|
341
341
|
"""
|
342
|
-
return self.context_opts.get("tag", None)
|
342
|
+
return self.context_opts.get("tag", None) # type: ignore[no-any-return] # noqa: E501
|
343
343
|
|
344
344
|
@overload
|
345
345
|
def get_x_argument(self, as_dictionary: Literal[False]) -> List[str]:
|
@@ -367,7 +367,11 @@ class EnvironmentContext(util.ModuleClsProxy):
|
|
367
367
|
The return value is a list, returned directly from the ``argparse``
|
368
368
|
structure. If ``as_dictionary=True`` is passed, the ``x`` arguments
|
369
369
|
are parsed using ``key=value`` format into a dictionary that is
|
370
|
-
then returned.
|
370
|
+
then returned. If there is no ``=`` in the argument, value is an empty
|
371
|
+
string.
|
372
|
+
|
373
|
+
.. versionchanged:: 1.13.1 Support ``as_dictionary=True`` when
|
374
|
+
arguments are passed without the ``=`` symbol.
|
371
375
|
|
372
376
|
For example, to support passing a database URL on the command line,
|
373
377
|
the standard ``env.py`` script can be modified like this::
|
@@ -401,7 +405,12 @@ class EnvironmentContext(util.ModuleClsProxy):
|
|
401
405
|
else:
|
402
406
|
value = []
|
403
407
|
if as_dictionary:
|
404
|
-
|
408
|
+
dict_value = {}
|
409
|
+
for arg in value:
|
410
|
+
x_key, _, x_value = arg.partition("=")
|
411
|
+
dict_value[x_key] = x_value
|
412
|
+
value = dict_value
|
413
|
+
|
405
414
|
return value
|
406
415
|
|
407
416
|
def configure(
|
@@ -941,7 +950,7 @@ class EnvironmentContext(util.ModuleClsProxy):
|
|
941
950
|
def execute(
|
942
951
|
self,
|
943
952
|
sql: Union[Executable, str],
|
944
|
-
execution_options: Optional[
|
953
|
+
execution_options: Optional[Dict[str, Any]] = None,
|
945
954
|
) -> None:
|
946
955
|
"""Execute the given SQL using the current change context.
|
947
956
|
|
alembic/runtime/migration.py
CHANGED
@@ -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
|
from contextlib import contextmanager
|
@@ -521,7 +524,7 @@ class MigrationContext:
|
|
521
524
|
start_from_rev = None
|
522
525
|
elif start_from_rev is not None and self.script:
|
523
526
|
start_from_rev = [
|
524
|
-
|
527
|
+
self.script.get_revision(sfr).revision
|
525
528
|
for sfr in util.to_list(start_from_rev)
|
526
529
|
if sfr not in (None, "base")
|
527
530
|
]
|
@@ -652,7 +655,7 @@ class MigrationContext:
|
|
652
655
|
def execute(
|
653
656
|
self,
|
654
657
|
sql: Union[Executable, str],
|
655
|
-
execution_options: Optional[
|
658
|
+
execution_options: Optional[Dict[str, Any]] = None,
|
656
659
|
) -> None:
|
657
660
|
"""Execute a SQL construct or string statement.
|
658
661
|
|
@@ -1000,6 +1003,12 @@ class MigrationStep:
|
|
1000
1003
|
is_upgrade: bool
|
1001
1004
|
migration_fn: Any
|
1002
1005
|
|
1006
|
+
if TYPE_CHECKING:
|
1007
|
+
|
1008
|
+
@property
|
1009
|
+
def doc(self) -> Optional[str]:
|
1010
|
+
...
|
1011
|
+
|
1003
1012
|
@property
|
1004
1013
|
def name(self) -> str:
|
1005
1014
|
return self.migration_fn.__name__
|
@@ -1048,13 +1057,9 @@ class RevisionStep(MigrationStep):
|
|
1048
1057
|
self.revision = revision
|
1049
1058
|
self.is_upgrade = is_upgrade
|
1050
1059
|
if is_upgrade:
|
1051
|
-
self.migration_fn =
|
1052
|
-
revision.module.upgrade # type:ignore[attr-defined]
|
1053
|
-
)
|
1060
|
+
self.migration_fn = revision.module.upgrade
|
1054
1061
|
else:
|
1055
|
-
self.migration_fn =
|
1056
|
-
revision.module.downgrade # type:ignore[attr-defined]
|
1057
|
-
)
|
1062
|
+
self.migration_fn = revision.module.downgrade
|
1058
1063
|
|
1059
1064
|
def __repr__(self):
|
1060
1065
|
return "RevisionStep(%r, is_upgrade=%r)" % (
|
@@ -1070,7 +1075,7 @@ class RevisionStep(MigrationStep):
|
|
1070
1075
|
)
|
1071
1076
|
|
1072
1077
|
@property
|
1073
|
-
def doc(self) -> str:
|
1078
|
+
def doc(self) -> Optional[str]:
|
1074
1079
|
return self.revision.doc
|
1075
1080
|
|
1076
1081
|
@property
|
@@ -1168,7 +1173,18 @@ class RevisionStep(MigrationStep):
|
|
1168
1173
|
}
|
1169
1174
|
return tuple(set(self.to_revisions).difference(ancestors))
|
1170
1175
|
else:
|
1171
|
-
return
|
1176
|
+
# for each revision we plan to return, compute its ancestors
|
1177
|
+
# (excluding self), and remove those from the final output since
|
1178
|
+
# they are already accounted for.
|
1179
|
+
ancestors = {
|
1180
|
+
r.revision
|
1181
|
+
for to_revision in self.to_revisions
|
1182
|
+
for r in self.revision_map._get_ancestor_nodes(
|
1183
|
+
self.revision_map.get_revisions(to_revision), check=False
|
1184
|
+
)
|
1185
|
+
if r.revision != to_revision
|
1186
|
+
}
|
1187
|
+
return tuple(set(self.to_revisions).difference(ancestors))
|
1172
1188
|
|
1173
1189
|
def unmerge_branch_idents(
|
1174
1190
|
self, heads: Set[str]
|
@@ -1283,7 +1299,7 @@ class StampStep(MigrationStep):
|
|
1283
1299
|
def __eq__(self, other):
|
1284
1300
|
return (
|
1285
1301
|
isinstance(other, StampStep)
|
1286
|
-
and other.from_revisions == self.
|
1302
|
+
and other.from_revisions == self.from_revisions
|
1287
1303
|
and other.to_revisions == self.to_revisions
|
1288
1304
|
and other.branch_move == self.branch_move
|
1289
1305
|
and self.is_upgrade == other.is_upgrade
|
alembic/script/base.py
CHANGED
@@ -41,7 +41,7 @@ try:
|
|
41
41
|
from zoneinfo import ZoneInfoNotFoundError
|
42
42
|
else:
|
43
43
|
from backports.zoneinfo import ZoneInfo # type: ignore[import-not-found,no-redef] # noqa: E501
|
44
|
-
from backports.zoneinfo import ZoneInfoNotFoundError # type: ignore[
|
44
|
+
from backports.zoneinfo import ZoneInfoNotFoundError # type: ignore[no-redef] # noqa: E501
|
45
45
|
except ImportError:
|
46
46
|
ZoneInfo = None # type: ignore[assignment, misc]
|
47
47
|
|
@@ -119,7 +119,7 @@ class ScriptDirectory:
|
|
119
119
|
return loc[0]
|
120
120
|
|
121
121
|
@util.memoized_property
|
122
|
-
def _version_locations(self):
|
122
|
+
def _version_locations(self) -> Sequence[str]:
|
123
123
|
if self.version_locations:
|
124
124
|
return [
|
125
125
|
os.path.abspath(util.coerce_resource_to_filename(location))
|
@@ -303,24 +303,22 @@ class ScriptDirectory:
|
|
303
303
|
):
|
304
304
|
yield cast(Script, rev)
|
305
305
|
|
306
|
-
def get_revisions(self, id_: _GetRevArg) -> Tuple[
|
306
|
+
def get_revisions(self, id_: _GetRevArg) -> Tuple[Script, ...]:
|
307
307
|
"""Return the :class:`.Script` instance with the given rev identifier,
|
308
308
|
symbolic name, or sequence of identifiers.
|
309
309
|
|
310
310
|
"""
|
311
311
|
with self._catch_revision_errors():
|
312
312
|
return cast(
|
313
|
-
Tuple[
|
313
|
+
Tuple[Script, ...],
|
314
314
|
self.revision_map.get_revisions(id_),
|
315
315
|
)
|
316
316
|
|
317
|
-
def get_all_current(self, id_: Tuple[str, ...]) -> Set[
|
317
|
+
def get_all_current(self, id_: Tuple[str, ...]) -> Set[Script]:
|
318
318
|
with self._catch_revision_errors():
|
319
|
-
return cast(
|
320
|
-
Set[Optional[Script]], self.revision_map._get_all_current(id_)
|
321
|
-
)
|
319
|
+
return cast(Set[Script], self.revision_map._get_all_current(id_))
|
322
320
|
|
323
|
-
def get_revision(self, id_: str) ->
|
321
|
+
def get_revision(self, id_: str) -> Script:
|
324
322
|
"""Return the :class:`.Script` instance with the given rev id.
|
325
323
|
|
326
324
|
.. seealso::
|
@@ -330,7 +328,7 @@ class ScriptDirectory:
|
|
330
328
|
"""
|
331
329
|
|
332
330
|
with self._catch_revision_errors():
|
333
|
-
return cast(
|
331
|
+
return cast(Script, self.revision_map.get_revision(id_))
|
334
332
|
|
335
333
|
def as_revision_number(
|
336
334
|
self, id_: Optional[str]
|
@@ -585,7 +583,7 @@ class ScriptDirectory:
|
|
585
583
|
util.load_python_file(self.dir, "env.py")
|
586
584
|
|
587
585
|
@property
|
588
|
-
def env_py_location(self):
|
586
|
+
def env_py_location(self) -> str:
|
589
587
|
return os.path.abspath(os.path.join(self.dir, "env.py"))
|
590
588
|
|
591
589
|
def _generate_template(self, src: str, dest: str, **kw: Any) -> None:
|
@@ -684,7 +682,7 @@ class ScriptDirectory:
|
|
684
682
|
self.revision_map.get_revisions(head),
|
685
683
|
)
|
686
684
|
for h in heads:
|
687
|
-
assert h != "base"
|
685
|
+
assert h != "base" # type: ignore[comparison-overlap]
|
688
686
|
|
689
687
|
if len(set(heads)) != len(heads):
|
690
688
|
raise util.CommandError("Duplicate head revisions specified")
|
@@ -823,7 +821,7 @@ class Script(revision.Revision):
|
|
823
821
|
self.path = path
|
824
822
|
super().__init__(
|
825
823
|
rev_id,
|
826
|
-
module.down_revision,
|
824
|
+
module.down_revision,
|
827
825
|
branch_labels=util.to_tuple(
|
828
826
|
getattr(module, "branch_labels", None), default=()
|
829
827
|
),
|
@@ -856,7 +854,7 @@ class Script(revision.Revision):
|
|
856
854
|
if doc:
|
857
855
|
if hasattr(self.module, "_alembic_source_encoding"):
|
858
856
|
doc = doc.decode( # type: ignore[attr-defined]
|
859
|
-
self.module._alembic_source_encoding
|
857
|
+
self.module._alembic_source_encoding
|
860
858
|
)
|
861
859
|
return doc.strip() # type: ignore[union-attr]
|
862
860
|
else:
|
@@ -898,7 +896,7 @@ class Script(revision.Revision):
|
|
898
896
|
)
|
899
897
|
return entry
|
900
898
|
|
901
|
-
def __str__(self):
|
899
|
+
def __str__(self) -> str:
|
902
900
|
return "%s -> %s%s%s%s, %s" % (
|
903
901
|
self._format_down_revision(),
|
904
902
|
self.revision,
|