alembic 1.13.0__py3-none-any.whl → 1.13.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.
- alembic/__init__.py +1 -1
- alembic/autogenerate/__init__.py +10 -10
- alembic/autogenerate/api.py +9 -7
- alembic/autogenerate/compare.py +6 -5
- alembic/autogenerate/render.py +34 -24
- alembic/autogenerate/rewriter.py +26 -13
- alembic/command.py +27 -16
- alembic/config.py +25 -19
- alembic/context.pyi +10 -5
- alembic/ddl/__init__.py +1 -1
- alembic/ddl/_autogen.py +19 -13
- alembic/ddl/base.py +17 -13
- alembic/ddl/impl.py +27 -19
- alembic/ddl/mssql.py +4 -1
- alembic/ddl/mysql.py +54 -34
- alembic/ddl/oracle.py +9 -4
- alembic/ddl/postgresql.py +18 -10
- alembic/ddl/sqlite.py +8 -6
- alembic/op.pyi +46 -8
- alembic/operations/base.py +69 -16
- alembic/operations/batch.py +7 -8
- alembic/operations/ops.py +57 -35
- alembic/operations/schemaobj.py +11 -8
- alembic/operations/toimpl.py +3 -0
- alembic/runtime/environment.py +20 -13
- alembic/runtime/migration.py +34 -18
- alembic/script/base.py +24 -24
- alembic/script/revision.py +53 -33
- alembic/script/write_hooks.py +3 -0
- alembic/templates/async/alembic.ini.mako +3 -3
- alembic/templates/generic/alembic.ini.mako +2 -2
- alembic/templates/multidb/alembic.ini.mako +2 -2
- alembic/testing/fixtures.py +20 -8
- alembic/testing/suite/test_autogen_computed.py +1 -0
- alembic/testing/suite/test_environment.py +3 -3
- alembic/util/__init__.py +31 -31
- alembic/util/compat.py +25 -8
- alembic/util/langhelpers.py +78 -36
- alembic/util/messaging.py +15 -6
- alembic/util/pyfiles.py +7 -3
- alembic/util/sqla_compat.py +41 -14
- {alembic-1.13.0.dist-info → alembic-1.13.2.dist-info}/LICENSE +2 -2
- {alembic-1.13.0.dist-info → alembic-1.13.2.dist-info}/METADATA +1 -1
- alembic-1.13.2.dist-info/RECORD +83 -0
- {alembic-1.13.0.dist-info → alembic-1.13.2.dist-info}/WHEEL +1 -1
- alembic-1.13.0.dist-info/RECORD +0 -83
- {alembic-1.13.0.dist-info → alembic-1.13.2.dist-info}/entry_points.txt +0 -0
- {alembic-1.13.0.dist-info → alembic-1.13.2.dist-info}/top_level.txt +0 -0
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
|
@@ -220,10 +223,12 @@ class SchemaObjects:
|
|
220
223
|
t = sa_schema.Table(name, m, *cols, **kw)
|
221
224
|
|
222
225
|
constraints = [
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
226
|
+
(
|
227
|
+
sqla_compat._copy(elem, target_table=t)
|
228
|
+
if getattr(elem, "parent", None) is not t
|
229
|
+
and getattr(elem, "parent", None) is not None
|
230
|
+
else elem
|
231
|
+
)
|
227
232
|
for elem in columns
|
228
233
|
if isinstance(elem, (Constraint, Index))
|
229
234
|
]
|
@@ -274,10 +279,8 @@ class SchemaObjects:
|
|
274
279
|
ForeignKey.
|
275
280
|
|
276
281
|
"""
|
277
|
-
if isinstance(fk._colspec, str):
|
278
|
-
table_key, cname = fk._colspec.rsplit(
|
279
|
-
".", 1
|
280
|
-
)
|
282
|
+
if isinstance(fk._colspec, str):
|
283
|
+
table_key, cname = fk._colspec.rsplit(".", 1)
|
281
284
|
sname, tname = self._parse_table_key(table_key)
|
282
285
|
if table_key not in metadata.tables:
|
283
286
|
rel_t = sa_schema.Table(tname, metadata, schema=sname)
|
alembic/operations/toimpl.py
CHANGED
alembic/runtime/environment.py
CHANGED
@@ -108,7 +108,6 @@ CompareType = Callable[
|
|
108
108
|
|
109
109
|
|
110
110
|
class EnvironmentContext(util.ModuleClsProxy):
|
111
|
-
|
112
111
|
"""A configurational facade made available in an ``env.py`` script.
|
113
112
|
|
114
113
|
The :class:`.EnvironmentContext` acts as a *facade* to the more
|
@@ -228,9 +227,9 @@ class EnvironmentContext(util.ModuleClsProxy):
|
|
228
227
|
has been configured.
|
229
228
|
|
230
229
|
"""
|
231
|
-
return self.context_opts.get("as_sql", False)
|
230
|
+
return self.context_opts.get("as_sql", False) # type: ignore[no-any-return] # noqa: E501
|
232
231
|
|
233
|
-
def is_transactional_ddl(self):
|
232
|
+
def is_transactional_ddl(self) -> bool:
|
234
233
|
"""Return True if the context is configured to expect a
|
235
234
|
transactional DDL capable backend.
|
236
235
|
|
@@ -339,21 +338,20 @@ class EnvironmentContext(util.ModuleClsProxy):
|
|
339
338
|
line.
|
340
339
|
|
341
340
|
"""
|
342
|
-
return self.context_opts.get("tag", None)
|
341
|
+
return self.context_opts.get("tag", None) # type: ignore[no-any-return] # noqa: E501
|
343
342
|
|
344
343
|
@overload
|
345
|
-
def get_x_argument(self, as_dictionary: Literal[False]) -> List[str]:
|
346
|
-
...
|
344
|
+
def get_x_argument(self, as_dictionary: Literal[False]) -> List[str]: ...
|
347
345
|
|
348
346
|
@overload
|
349
|
-
def get_x_argument(
|
350
|
-
|
347
|
+
def get_x_argument(
|
348
|
+
self, as_dictionary: Literal[True]
|
349
|
+
) -> Dict[str, str]: ...
|
351
350
|
|
352
351
|
@overload
|
353
352
|
def get_x_argument(
|
354
353
|
self, as_dictionary: bool = ...
|
355
|
-
) -> Union[List[str], Dict[str, str]]:
|
356
|
-
...
|
354
|
+
) -> Union[List[str], Dict[str, str]]: ...
|
357
355
|
|
358
356
|
def get_x_argument(
|
359
357
|
self, as_dictionary: bool = False
|
@@ -367,7 +365,11 @@ class EnvironmentContext(util.ModuleClsProxy):
|
|
367
365
|
The return value is a list, returned directly from the ``argparse``
|
368
366
|
structure. If ``as_dictionary=True`` is passed, the ``x`` arguments
|
369
367
|
are parsed using ``key=value`` format into a dictionary that is
|
370
|
-
then returned.
|
368
|
+
then returned. If there is no ``=`` in the argument, value is an empty
|
369
|
+
string.
|
370
|
+
|
371
|
+
.. versionchanged:: 1.13.1 Support ``as_dictionary=True`` when
|
372
|
+
arguments are passed without the ``=`` symbol.
|
371
373
|
|
372
374
|
For example, to support passing a database URL on the command line,
|
373
375
|
the standard ``env.py`` script can be modified like this::
|
@@ -401,7 +403,12 @@ class EnvironmentContext(util.ModuleClsProxy):
|
|
401
403
|
else:
|
402
404
|
value = []
|
403
405
|
if as_dictionary:
|
404
|
-
|
406
|
+
dict_value = {}
|
407
|
+
for arg in value:
|
408
|
+
x_key, _, x_value = arg.partition("=")
|
409
|
+
dict_value[x_key] = x_value
|
410
|
+
value = dict_value
|
411
|
+
|
405
412
|
return value
|
406
413
|
|
407
414
|
def configure(
|
@@ -941,7 +948,7 @@ class EnvironmentContext(util.ModuleClsProxy):
|
|
941
948
|
def execute(
|
942
949
|
self,
|
943
950
|
sql: Union[Executable, str],
|
944
|
-
execution_options: Optional[
|
951
|
+
execution_options: Optional[Dict[str, Any]] = None,
|
945
952
|
) -> None:
|
946
953
|
"""Execute the given SQL using the current change context.
|
947
954
|
|
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
|
@@ -83,7 +86,6 @@ class _ProxyTransaction:
|
|
83
86
|
|
84
87
|
|
85
88
|
class MigrationContext:
|
86
|
-
|
87
89
|
"""Represent the database state made available to a migration
|
88
90
|
script.
|
89
91
|
|
@@ -215,9 +217,11 @@ class MigrationContext:
|
|
215
217
|
log.info("Generating static SQL")
|
216
218
|
log.info(
|
217
219
|
"Will assume %s DDL.",
|
218
|
-
|
219
|
-
|
220
|
-
|
220
|
+
(
|
221
|
+
"transactional"
|
222
|
+
if self.impl.transactional_ddl
|
223
|
+
else "non-transactional"
|
224
|
+
),
|
221
225
|
)
|
222
226
|
|
223
227
|
@classmethod
|
@@ -342,9 +346,9 @@ class MigrationContext:
|
|
342
346
|
# except that it will not know it's in "autocommit" and will
|
343
347
|
# emit deprecation warnings when an autocommit action takes
|
344
348
|
# place.
|
345
|
-
self.connection = (
|
346
|
-
|
347
|
-
)
|
349
|
+
self.connection = self.impl.connection = (
|
350
|
+
base_connection.execution_options(isolation_level="AUTOCOMMIT")
|
351
|
+
)
|
348
352
|
|
349
353
|
# sqlalchemy future mode will "autobegin" in any case, so take
|
350
354
|
# control of that "transaction" here
|
@@ -521,7 +525,7 @@ class MigrationContext:
|
|
521
525
|
start_from_rev = None
|
522
526
|
elif start_from_rev is not None and self.script:
|
523
527
|
start_from_rev = [
|
524
|
-
|
528
|
+
self.script.get_revision(sfr).revision
|
525
529
|
for sfr in util.to_list(start_from_rev)
|
526
530
|
if sfr not in (None, "base")
|
527
531
|
]
|
@@ -652,7 +656,7 @@ class MigrationContext:
|
|
652
656
|
def execute(
|
653
657
|
self,
|
654
658
|
sql: Union[Executable, str],
|
655
|
-
execution_options: Optional[
|
659
|
+
execution_options: Optional[Dict[str, Any]] = None,
|
656
660
|
) -> None:
|
657
661
|
"""Execute a SQL construct or string statement.
|
658
662
|
|
@@ -1000,6 +1004,11 @@ class MigrationStep:
|
|
1000
1004
|
is_upgrade: bool
|
1001
1005
|
migration_fn: Any
|
1002
1006
|
|
1007
|
+
if TYPE_CHECKING:
|
1008
|
+
|
1009
|
+
@property
|
1010
|
+
def doc(self) -> Optional[str]: ...
|
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
|
|
@@ -56,7 +56,6 @@ _split_on_space_comma_colon = re.compile(r", *|(?: +)|\:")
|
|
56
56
|
|
57
57
|
|
58
58
|
class ScriptDirectory:
|
59
|
-
|
60
59
|
"""Provides operations upon an Alembic script directory.
|
61
60
|
|
62
61
|
This object is useful to get information as to current revisions,
|
@@ -119,7 +118,7 @@ class ScriptDirectory:
|
|
119
118
|
return loc[0]
|
120
119
|
|
121
120
|
@util.memoized_property
|
122
|
-
def _version_locations(self):
|
121
|
+
def _version_locations(self) -> Sequence[str]:
|
123
122
|
if self.version_locations:
|
124
123
|
return [
|
125
124
|
os.path.abspath(util.coerce_resource_to_filename(location))
|
@@ -303,24 +302,22 @@ class ScriptDirectory:
|
|
303
302
|
):
|
304
303
|
yield cast(Script, rev)
|
305
304
|
|
306
|
-
def get_revisions(self, id_: _GetRevArg) -> Tuple[
|
305
|
+
def get_revisions(self, id_: _GetRevArg) -> Tuple[Script, ...]:
|
307
306
|
"""Return the :class:`.Script` instance with the given rev identifier,
|
308
307
|
symbolic name, or sequence of identifiers.
|
309
308
|
|
310
309
|
"""
|
311
310
|
with self._catch_revision_errors():
|
312
311
|
return cast(
|
313
|
-
Tuple[
|
312
|
+
Tuple[Script, ...],
|
314
313
|
self.revision_map.get_revisions(id_),
|
315
314
|
)
|
316
315
|
|
317
|
-
def get_all_current(self, id_: Tuple[str, ...]) -> Set[
|
316
|
+
def get_all_current(self, id_: Tuple[str, ...]) -> Set[Script]:
|
318
317
|
with self._catch_revision_errors():
|
319
|
-
return cast(
|
320
|
-
Set[Optional[Script]], self.revision_map._get_all_current(id_)
|
321
|
-
)
|
318
|
+
return cast(Set[Script], self.revision_map._get_all_current(id_))
|
322
319
|
|
323
|
-
def get_revision(self, id_: str) ->
|
320
|
+
def get_revision(self, id_: str) -> Script:
|
324
321
|
"""Return the :class:`.Script` instance with the given rev id.
|
325
322
|
|
326
323
|
.. seealso::
|
@@ -330,7 +327,7 @@ class ScriptDirectory:
|
|
330
327
|
"""
|
331
328
|
|
332
329
|
with self._catch_revision_errors():
|
333
|
-
return cast(
|
330
|
+
return cast(Script, self.revision_map.get_revision(id_))
|
334
331
|
|
335
332
|
def as_revision_number(
|
336
333
|
self, id_: Optional[str]
|
@@ -585,7 +582,7 @@ class ScriptDirectory:
|
|
585
582
|
util.load_python_file(self.dir, "env.py")
|
586
583
|
|
587
584
|
@property
|
588
|
-
def env_py_location(self):
|
585
|
+
def env_py_location(self) -> str:
|
589
586
|
return os.path.abspath(os.path.join(self.dir, "env.py"))
|
590
587
|
|
591
588
|
def _generate_template(self, src: str, dest: str, **kw: Any) -> None:
|
@@ -612,7 +609,7 @@ class ScriptDirectory:
|
|
612
609
|
if self.timezone is not None:
|
613
610
|
if ZoneInfo is None:
|
614
611
|
raise util.CommandError(
|
615
|
-
"Python >= 3.9 is required for timezone support or"
|
612
|
+
"Python >= 3.9 is required for timezone support or "
|
616
613
|
"the 'backports.zoneinfo' package must be installed."
|
617
614
|
)
|
618
615
|
# First, assume correct capitalization
|
@@ -684,7 +681,7 @@ class ScriptDirectory:
|
|
684
681
|
self.revision_map.get_revisions(head),
|
685
682
|
)
|
686
683
|
for h in heads:
|
687
|
-
assert h != "base"
|
684
|
+
assert h != "base" # type: ignore[comparison-overlap]
|
688
685
|
|
689
686
|
if len(set(heads)) != len(heads):
|
690
687
|
raise util.CommandError("Duplicate head revisions specified")
|
@@ -734,9 +731,11 @@ class ScriptDirectory:
|
|
734
731
|
if depends_on:
|
735
732
|
with self._catch_revision_errors():
|
736
733
|
resolved_depends_on = [
|
737
|
-
|
738
|
-
|
739
|
-
|
734
|
+
(
|
735
|
+
dep
|
736
|
+
if dep in rev.branch_labels # maintain branch labels
|
737
|
+
else rev.revision
|
738
|
+
) # resolve partial revision identifiers
|
740
739
|
for rev, dep in [
|
741
740
|
(not_none(self.revision_map.get_revision(dep)), dep)
|
742
741
|
for dep in util.to_list(depends_on)
|
@@ -810,7 +809,6 @@ class ScriptDirectory:
|
|
810
809
|
|
811
810
|
|
812
811
|
class Script(revision.Revision):
|
813
|
-
|
814
812
|
"""Represent a single revision file in a ``versions/`` directory.
|
815
813
|
|
816
814
|
The :class:`.Script` instance is returned by methods
|
@@ -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,
|
@@ -932,9 +930,11 @@ class Script(revision.Revision):
|
|
932
930
|
if head_indicators or tree_indicators:
|
933
931
|
text += "%s%s%s" % (
|
934
932
|
" (head)" if self._is_real_head else "",
|
935
|
-
|
936
|
-
|
937
|
-
|
933
|
+
(
|
934
|
+
" (effective head)"
|
935
|
+
if self.is_head and not self._is_real_head
|
936
|
+
else ""
|
937
|
+
),
|
938
938
|
" (current)" if self._db_current_indicator else "",
|
939
939
|
)
|
940
940
|
if tree_indicators:
|
alembic/script/revision.py
CHANGED
@@ -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,17 @@ _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
|
+
|
50
62
|
class RevisionError(Exception):
|
51
63
|
pass
|
52
64
|
|
@@ -396,7 +408,7 @@ class RevisionMap:
|
|
396
408
|
for rev in self._get_ancestor_nodes(
|
397
409
|
[revision],
|
398
410
|
include_dependencies=False,
|
399
|
-
map_=
|
411
|
+
map_=map_,
|
400
412
|
):
|
401
413
|
if rev is revision:
|
402
414
|
continue
|
@@ -707,9 +719,11 @@ class RevisionMap:
|
|
707
719
|
resolved_target = target
|
708
720
|
|
709
721
|
resolved_test_against_revs = [
|
710
|
-
|
711
|
-
|
712
|
-
|
722
|
+
(
|
723
|
+
self._revision_for_ident(test_against_rev)
|
724
|
+
if not isinstance(test_against_rev, Revision)
|
725
|
+
else test_against_rev
|
726
|
+
)
|
713
727
|
for test_against_rev in util.to_tuple(
|
714
728
|
test_against_revs, default=()
|
715
729
|
)
|
@@ -791,7 +805,7 @@ class RevisionMap:
|
|
791
805
|
The iterator yields :class:`.Revision` objects.
|
792
806
|
|
793
807
|
"""
|
794
|
-
fn:
|
808
|
+
fn: _CollectRevisionsProtocol
|
795
809
|
if select_for_downgrade:
|
796
810
|
fn = self._collect_downgrade_revisions
|
797
811
|
else:
|
@@ -818,7 +832,7 @@ class RevisionMap:
|
|
818
832
|
) -> Iterator[Any]:
|
819
833
|
if omit_immediate_dependencies:
|
820
834
|
|
821
|
-
def fn(rev):
|
835
|
+
def fn(rev: Revision) -> Iterable[str]:
|
822
836
|
if rev not in targets:
|
823
837
|
return rev._all_nextrev
|
824
838
|
else:
|
@@ -826,12 +840,12 @@ class RevisionMap:
|
|
826
840
|
|
827
841
|
elif include_dependencies:
|
828
842
|
|
829
|
-
def fn(rev):
|
843
|
+
def fn(rev: Revision) -> Iterable[str]:
|
830
844
|
return rev._all_nextrev
|
831
845
|
|
832
846
|
else:
|
833
847
|
|
834
|
-
def fn(rev):
|
848
|
+
def fn(rev: Revision) -> Iterable[str]:
|
835
849
|
return rev.nextrev
|
836
850
|
|
837
851
|
return self._iterate_related_revisions(
|
@@ -847,12 +861,12 @@ class RevisionMap:
|
|
847
861
|
) -> Iterator[Revision]:
|
848
862
|
if include_dependencies:
|
849
863
|
|
850
|
-
def fn(rev):
|
864
|
+
def fn(rev: Revision) -> Iterable[str]:
|
851
865
|
return rev._normalized_down_revisions
|
852
866
|
|
853
867
|
else:
|
854
868
|
|
855
|
-
def fn(rev):
|
869
|
+
def fn(rev: Revision) -> Iterable[str]:
|
856
870
|
return rev._versioned_down_revisions
|
857
871
|
|
858
872
|
return self._iterate_related_revisions(
|
@@ -861,7 +875,7 @@ class RevisionMap:
|
|
861
875
|
|
862
876
|
def _iterate_related_revisions(
|
863
877
|
self,
|
864
|
-
fn: Callable,
|
878
|
+
fn: Callable[[Revision], Iterable[str]],
|
865
879
|
targets: Collection[Optional[_RevisionOrBase]],
|
866
880
|
map_: Optional[_RevisionMapType],
|
867
881
|
check: bool = False,
|
@@ -923,7 +937,7 @@ class RevisionMap:
|
|
923
937
|
|
924
938
|
id_to_rev = self._revision_map
|
925
939
|
|
926
|
-
def get_ancestors(rev_id):
|
940
|
+
def get_ancestors(rev_id: str) -> Set[str]:
|
927
941
|
return {
|
928
942
|
r.revision
|
929
943
|
for r in self._get_ancestor_nodes([id_to_rev[rev_id]])
|
@@ -1003,9 +1017,9 @@ class RevisionMap:
|
|
1003
1017
|
# each time but it was getting complicated
|
1004
1018
|
current_heads[current_candidate_idx] = heads_to_add[0]
|
1005
1019
|
current_heads.extend(heads_to_add[1:])
|
1006
|
-
ancestors_by_idx[
|
1007
|
-
|
1008
|
-
|
1020
|
+
ancestors_by_idx[current_candidate_idx] = (
|
1021
|
+
get_ancestors(heads_to_add[0])
|
1022
|
+
)
|
1009
1023
|
ancestors_by_idx.extend(
|
1010
1024
|
get_ancestors(head) for head in heads_to_add[1:]
|
1011
1025
|
)
|
@@ -1041,7 +1055,7 @@ class RevisionMap:
|
|
1041
1055
|
children: Sequence[Optional[_RevisionOrBase]]
|
1042
1056
|
for _ in range(abs(steps)):
|
1043
1057
|
if steps > 0:
|
1044
|
-
assert initial != "base"
|
1058
|
+
assert initial != "base" # type: ignore[comparison-overlap]
|
1045
1059
|
# Walk up
|
1046
1060
|
walk_up = [
|
1047
1061
|
is_revision(rev)
|
@@ -1055,7 +1069,7 @@ class RevisionMap:
|
|
1055
1069
|
children = walk_up
|
1056
1070
|
else:
|
1057
1071
|
# Walk down
|
1058
|
-
if initial == "base":
|
1072
|
+
if initial == "base": # type: ignore[comparison-overlap]
|
1059
1073
|
children = ()
|
1060
1074
|
else:
|
1061
1075
|
children = self.get_revisions(
|
@@ -1170,9 +1184,13 @@ class RevisionMap:
|
|
1170
1184
|
branch_label = symbol
|
1171
1185
|
# Walk down the tree to find downgrade target.
|
1172
1186
|
rev = self._walk(
|
1173
|
-
start=
|
1174
|
-
|
1175
|
-
|
1187
|
+
start=(
|
1188
|
+
self.get_revision(symbol)
|
1189
|
+
if branch_label is None
|
1190
|
+
else self.get_revision(
|
1191
|
+
"%s@%s" % (branch_label, symbol)
|
1192
|
+
)
|
1193
|
+
),
|
1176
1194
|
steps=rel_int,
|
1177
1195
|
no_overwalk=assert_relative_length,
|
1178
1196
|
)
|
@@ -1189,7 +1207,7 @@ class RevisionMap:
|
|
1189
1207
|
# No relative destination given, revision specified is absolute.
|
1190
1208
|
branch_label, _, symbol = target.rpartition("@")
|
1191
1209
|
if not branch_label:
|
1192
|
-
branch_label = None
|
1210
|
+
branch_label = None
|
1193
1211
|
return branch_label, self.get_revision(symbol)
|
1194
1212
|
|
1195
1213
|
def _parse_upgrade_target(
|
@@ -1290,9 +1308,13 @@ class RevisionMap:
|
|
1290
1308
|
)
|
1291
1309
|
return (
|
1292
1310
|
self._walk(
|
1293
|
-
start=
|
1294
|
-
|
1295
|
-
|
1311
|
+
start=(
|
1312
|
+
self.get_revision(symbol)
|
1313
|
+
if branch_label is None
|
1314
|
+
else self.get_revision(
|
1315
|
+
"%s@%s" % (branch_label, symbol)
|
1316
|
+
)
|
1317
|
+
),
|
1296
1318
|
steps=relative,
|
1297
1319
|
no_overwalk=assert_relative_length,
|
1298
1320
|
),
|
@@ -1301,11 +1323,11 @@ class RevisionMap:
|
|
1301
1323
|
def _collect_downgrade_revisions(
|
1302
1324
|
self,
|
1303
1325
|
upper: _RevisionIdentifierType,
|
1304
|
-
|
1326
|
+
lower: _RevisionIdentifierType,
|
1305
1327
|
inclusive: bool,
|
1306
1328
|
implicit_base: bool,
|
1307
1329
|
assert_relative_length: bool,
|
1308
|
-
) ->
|
1330
|
+
) -> Tuple[Set[Revision], Tuple[Optional[_RevisionOrBase], ...]]:
|
1309
1331
|
"""
|
1310
1332
|
Compute the set of current revisions specified by :upper, and the
|
1311
1333
|
downgrade target specified by :target. Return all dependents of target
|
@@ -1316,7 +1338,7 @@ class RevisionMap:
|
|
1316
1338
|
|
1317
1339
|
branch_label, target_revision = self._parse_downgrade_target(
|
1318
1340
|
current_revisions=upper,
|
1319
|
-
target=
|
1341
|
+
target=lower,
|
1320
1342
|
assert_relative_length=assert_relative_length,
|
1321
1343
|
)
|
1322
1344
|
if target_revision == "base":
|
@@ -1408,7 +1430,7 @@ class RevisionMap:
|
|
1408
1430
|
inclusive: bool,
|
1409
1431
|
implicit_base: bool,
|
1410
1432
|
assert_relative_length: bool,
|
1411
|
-
) -> Tuple[Set[Revision], Tuple[
|
1433
|
+
) -> Tuple[Set[Revision], Tuple[Revision, ...]]:
|
1412
1434
|
"""
|
1413
1435
|
Compute the set of required revisions specified by :upper, and the
|
1414
1436
|
current set of active revisions specified by :lower. Find the
|
@@ -1500,7 +1522,7 @@ class RevisionMap:
|
|
1500
1522
|
)
|
1501
1523
|
needs.intersection_update(lower_descendents)
|
1502
1524
|
|
1503
|
-
return needs, tuple(targets)
|
1525
|
+
return needs, tuple(targets)
|
1504
1526
|
|
1505
1527
|
def _get_all_current(
|
1506
1528
|
self, id_: Tuple[str, ...]
|
@@ -1681,15 +1703,13 @@ class Revision:
|
|
1681
1703
|
|
1682
1704
|
|
1683
1705
|
@overload
|
1684
|
-
def tuple_rev_as_scalar(rev: None) -> None:
|
1685
|
-
...
|
1706
|
+
def tuple_rev_as_scalar(rev: None) -> None: ...
|
1686
1707
|
|
1687
1708
|
|
1688
1709
|
@overload
|
1689
1710
|
def tuple_rev_as_scalar(
|
1690
1711
|
rev: Union[Tuple[_T, ...], List[_T]]
|
1691
|
-
) -> Union[_T, Tuple[_T, ...], List[_T]]:
|
1692
|
-
...
|
1712
|
+
) -> Union[_T, Tuple[_T, ...], List[_T]]: ...
|
1693
1713
|
|
1694
1714
|
|
1695
1715
|
def tuple_rev_as_scalar(
|
alembic/script/write_hooks.py
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# A generic, single database configuration.
|
2
2
|
|
3
3
|
[alembic]
|
4
|
-
# path to migration scripts
|
4
|
+
# path to migration scripts.
|
5
|
+
# Use forward slashes (/) also on windows to provide an os agnostic path
|
5
6
|
script_location = ${script_location}
|
6
7
|
|
7
8
|
# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
|
@@ -20,8 +21,7 @@ prepend_sys_path = .
|
|
20
21
|
# leave blank for localtime
|
21
22
|
# timezone =
|
22
23
|
|
23
|
-
# max length of characters to apply to the
|
24
|
-
# "slug" field
|
24
|
+
# max length of characters to apply to the "slug" field
|
25
25
|
# truncate_slug_length = 40
|
26
26
|
|
27
27
|
# set to 'true' to run the environment during
|