alembic 1.12.1__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 -3
- alembic/autogenerate/__init__.py +10 -10
- alembic/autogenerate/api.py +8 -5
- alembic/autogenerate/compare.py +134 -199
- alembic/autogenerate/render.py +39 -24
- alembic/autogenerate/rewriter.py +26 -13
- alembic/command.py +7 -2
- alembic/config.py +20 -9
- alembic/context.pyi +12 -6
- alembic/ddl/__init__.py +1 -1
- alembic/ddl/_autogen.py +325 -0
- alembic/ddl/base.py +12 -9
- alembic/ddl/impl.py +110 -13
- alembic/ddl/mssql.py +4 -1
- alembic/ddl/mysql.py +9 -6
- alembic/ddl/oracle.py +4 -1
- alembic/ddl/postgresql.py +147 -73
- 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 +53 -31
- alembic/operations/schemaobj.py +5 -4
- alembic/operations/toimpl.py +8 -5
- alembic/runtime/environment.py +17 -7
- alembic/runtime/migration.py +27 -11
- alembic/script/base.py +34 -27
- alembic/script/revision.py +30 -17
- alembic/script/write_hooks.py +3 -0
- alembic/templates/async/alembic.ini.mako +3 -3
- alembic/templates/generic/alembic.ini.mako +3 -3
- alembic/templates/multidb/alembic.ini.mako +3 -3
- alembic/testing/requirements.py +12 -0
- alembic/testing/schemacompare.py +9 -0
- alembic/util/__init__.py +31 -31
- alembic/util/compat.py +25 -9
- alembic/util/langhelpers.py +78 -33
- alembic/util/messaging.py +6 -3
- alembic/util/pyfiles.py +7 -3
- alembic/util/sqla_compat.py +52 -26
- {alembic-1.12.1.dist-info → alembic-1.13.1.dist-info}/METADATA +5 -4
- alembic-1.13.1.dist-info/RECORD +83 -0
- {alembic-1.12.1.dist-info → alembic-1.13.1.dist-info}/WHEEL +1 -1
- alembic-1.12.1.dist-info/RECORD +0 -82
- {alembic-1.12.1.dist-info → alembic-1.13.1.dist-info}/LICENSE +0 -0
- {alembic-1.12.1.dist-info → alembic-1.13.1.dist-info}/entry_points.txt +0 -0
- {alembic-1.12.1.dist-info → alembic-1.13.1.dist-info}/top_level.txt +0 -0
alembic/script/base.py
CHANGED
@@ -23,6 +23,7 @@ from . import revision
|
|
23
23
|
from . import write_hooks
|
24
24
|
from .. import util
|
25
25
|
from ..runtime import migration
|
26
|
+
from ..util import compat
|
26
27
|
from ..util import not_none
|
27
28
|
|
28
29
|
if TYPE_CHECKING:
|
@@ -35,9 +36,14 @@ if TYPE_CHECKING:
|
|
35
36
|
from ..runtime.migration import StampStep
|
36
37
|
|
37
38
|
try:
|
38
|
-
|
39
|
+
if compat.py39:
|
40
|
+
from zoneinfo import ZoneInfo
|
41
|
+
from zoneinfo import ZoneInfoNotFoundError
|
42
|
+
else:
|
43
|
+
from backports.zoneinfo import ZoneInfo # type: ignore[import-not-found,no-redef] # noqa: E501
|
44
|
+
from backports.zoneinfo import ZoneInfoNotFoundError # type: ignore[no-redef] # noqa: E501
|
39
45
|
except ImportError:
|
40
|
-
|
46
|
+
ZoneInfo = None # type: ignore[assignment, misc]
|
41
47
|
|
42
48
|
_sourceless_rev_file = re.compile(r"(?!\.\#|__init__)(.*\.py)(c|o)?$")
|
43
49
|
_only_source_rev_file = re.compile(r"(?!\.\#|__init__)(.*\.py)$")
|
@@ -113,7 +119,7 @@ class ScriptDirectory:
|
|
113
119
|
return loc[0]
|
114
120
|
|
115
121
|
@util.memoized_property
|
116
|
-
def _version_locations(self):
|
122
|
+
def _version_locations(self) -> Sequence[str]:
|
117
123
|
if self.version_locations:
|
118
124
|
return [
|
119
125
|
os.path.abspath(util.coerce_resource_to_filename(location))
|
@@ -297,24 +303,22 @@ class ScriptDirectory:
|
|
297
303
|
):
|
298
304
|
yield cast(Script, rev)
|
299
305
|
|
300
|
-
def get_revisions(self, id_: _GetRevArg) -> Tuple[
|
306
|
+
def get_revisions(self, id_: _GetRevArg) -> Tuple[Script, ...]:
|
301
307
|
"""Return the :class:`.Script` instance with the given rev identifier,
|
302
308
|
symbolic name, or sequence of identifiers.
|
303
309
|
|
304
310
|
"""
|
305
311
|
with self._catch_revision_errors():
|
306
312
|
return cast(
|
307
|
-
Tuple[
|
313
|
+
Tuple[Script, ...],
|
308
314
|
self.revision_map.get_revisions(id_),
|
309
315
|
)
|
310
316
|
|
311
|
-
def get_all_current(self, id_: Tuple[str, ...]) -> Set[
|
317
|
+
def get_all_current(self, id_: Tuple[str, ...]) -> Set[Script]:
|
312
318
|
with self._catch_revision_errors():
|
313
|
-
return cast(
|
314
|
-
Set[Optional[Script]], self.revision_map._get_all_current(id_)
|
315
|
-
)
|
319
|
+
return cast(Set[Script], self.revision_map._get_all_current(id_))
|
316
320
|
|
317
|
-
def get_revision(self, id_: str) ->
|
321
|
+
def get_revision(self, id_: str) -> Script:
|
318
322
|
"""Return the :class:`.Script` instance with the given rev id.
|
319
323
|
|
320
324
|
.. seealso::
|
@@ -324,7 +328,7 @@ class ScriptDirectory:
|
|
324
328
|
"""
|
325
329
|
|
326
330
|
with self._catch_revision_errors():
|
327
|
-
return cast(
|
331
|
+
return cast(Script, self.revision_map.get_revision(id_))
|
328
332
|
|
329
333
|
def as_revision_number(
|
330
334
|
self, id_: Optional[str]
|
@@ -579,7 +583,7 @@ class ScriptDirectory:
|
|
579
583
|
util.load_python_file(self.dir, "env.py")
|
580
584
|
|
581
585
|
@property
|
582
|
-
def env_py_location(self):
|
586
|
+
def env_py_location(self) -> str:
|
583
587
|
return os.path.abspath(os.path.join(self.dir, "env.py"))
|
584
588
|
|
585
589
|
def _generate_template(self, src: str, dest: str, **kw: Any) -> None:
|
@@ -604,23 +608,26 @@ class ScriptDirectory:
|
|
604
608
|
|
605
609
|
def _generate_create_date(self) -> datetime.datetime:
|
606
610
|
if self.timezone is not None:
|
607
|
-
if
|
611
|
+
if ZoneInfo is None:
|
608
612
|
raise util.CommandError(
|
609
|
-
"
|
610
|
-
"
|
613
|
+
"Python >= 3.9 is required for timezone support or"
|
614
|
+
"the 'backports.zoneinfo' package must be installed."
|
611
615
|
)
|
612
616
|
# First, assume correct capitalization
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
tzinfo =
|
617
|
+
try:
|
618
|
+
tzinfo = ZoneInfo(self.timezone)
|
619
|
+
except ZoneInfoNotFoundError:
|
620
|
+
tzinfo = None
|
617
621
|
if tzinfo is None:
|
618
|
-
|
619
|
-
|
620
|
-
|
622
|
+
try:
|
623
|
+
tzinfo = ZoneInfo(self.timezone.upper())
|
624
|
+
except ZoneInfoNotFoundError:
|
625
|
+
raise util.CommandError(
|
626
|
+
"Can't locate timezone: %s" % self.timezone
|
627
|
+
) from None
|
621
628
|
create_date = (
|
622
629
|
datetime.datetime.utcnow()
|
623
|
-
.replace(tzinfo=
|
630
|
+
.replace(tzinfo=datetime.timezone.utc)
|
624
631
|
.astimezone(tzinfo)
|
625
632
|
)
|
626
633
|
else:
|
@@ -675,7 +682,7 @@ class ScriptDirectory:
|
|
675
682
|
self.revision_map.get_revisions(head),
|
676
683
|
)
|
677
684
|
for h in heads:
|
678
|
-
assert h != "base"
|
685
|
+
assert h != "base" # type: ignore[comparison-overlap]
|
679
686
|
|
680
687
|
if len(set(heads)) != len(heads):
|
681
688
|
raise util.CommandError("Duplicate head revisions specified")
|
@@ -814,7 +821,7 @@ class Script(revision.Revision):
|
|
814
821
|
self.path = path
|
815
822
|
super().__init__(
|
816
823
|
rev_id,
|
817
|
-
module.down_revision,
|
824
|
+
module.down_revision,
|
818
825
|
branch_labels=util.to_tuple(
|
819
826
|
getattr(module, "branch_labels", None), default=()
|
820
827
|
),
|
@@ -847,7 +854,7 @@ class Script(revision.Revision):
|
|
847
854
|
if doc:
|
848
855
|
if hasattr(self.module, "_alembic_source_encoding"):
|
849
856
|
doc = doc.decode( # type: ignore[attr-defined]
|
850
|
-
self.module._alembic_source_encoding
|
857
|
+
self.module._alembic_source_encoding
|
851
858
|
)
|
852
859
|
return doc.strip() # type: ignore[union-attr]
|
853
860
|
else:
|
@@ -889,7 +896,7 @@ class Script(revision.Revision):
|
|
889
896
|
)
|
890
897
|
return entry
|
891
898
|
|
892
|
-
def __str__(self):
|
899
|
+
def __str__(self) -> str:
|
893
900
|
return "%s -> %s%s%s%s, %s" % (
|
894
901
|
self._format_down_revision(),
|
895
902
|
self.revision,
|
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,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_=
|
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:
|
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
|
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
|
-
|
1317
|
+
lower: _RevisionIdentifierType,
|
1305
1318
|
inclusive: bool,
|
1306
1319
|
implicit_base: bool,
|
1307
1320
|
assert_relative_length: bool,
|
1308
|
-
) ->
|
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=
|
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[
|
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)
|
1516
|
+
return needs, tuple(targets)
|
1504
1517
|
|
1505
1518
|
def _get_all_current(
|
1506
1519
|
self, id_: Tuple[str, ...]
|
alembic/script/write_hooks.py
CHANGED
@@ -14,9 +14,9 @@ prepend_sys_path = .
|
|
14
14
|
|
15
15
|
# timezone to use when rendering the date within the migration file
|
16
16
|
# as well as the filename.
|
17
|
-
# If specified, requires the python
|
18
|
-
# installed by adding `alembic[tz]` to the pip requirements
|
19
|
-
# string value is passed to
|
17
|
+
# If specified, requires the python>=3.9 or backports.zoneinfo library.
|
18
|
+
# Any required deps can installed by adding `alembic[tz]` to the pip requirements
|
19
|
+
# string value is passed to ZoneInfo()
|
20
20
|
# leave blank for localtime
|
21
21
|
# timezone =
|
22
22
|
|
@@ -16,9 +16,9 @@ prepend_sys_path = .
|
|
16
16
|
|
17
17
|
# timezone to use when rendering the date within the migration file
|
18
18
|
# as well as the filename.
|
19
|
-
# If specified, requires the python
|
20
|
-
# installed by adding `alembic[tz]` to the pip requirements
|
21
|
-
# string value is passed to
|
19
|
+
# If specified, requires the python>=3.9 or backports.zoneinfo library.
|
20
|
+
# Any required deps can installed by adding `alembic[tz]` to the pip requirements
|
21
|
+
# string value is passed to ZoneInfo()
|
22
22
|
# leave blank for localtime
|
23
23
|
# timezone =
|
24
24
|
|
@@ -16,9 +16,9 @@ prepend_sys_path = .
|
|
16
16
|
|
17
17
|
# timezone to use when rendering the date within the migration file
|
18
18
|
# as well as the filename.
|
19
|
-
# If specified, requires the python
|
20
|
-
# installed by adding `alembic[tz]` to the pip requirements
|
21
|
-
# string value is passed to
|
19
|
+
# If specified, requires the python>=3.9 or backports.zoneinfo library.
|
20
|
+
# Any required deps can installed by adding `alembic[tz]` to the pip requirements
|
21
|
+
# string value is passed to ZoneInfo()
|
22
22
|
# leave blank for localtime
|
23
23
|
# timezone =
|
24
24
|
|
alembic/testing/requirements.py
CHANGED
@@ -95,6 +95,18 @@ class SuiteRequirements(Requirements):
|
|
95
95
|
"SQLAlchemy 2.x test",
|
96
96
|
)
|
97
97
|
|
98
|
+
@property
|
99
|
+
def asyncio(self):
|
100
|
+
def go(config):
|
101
|
+
try:
|
102
|
+
import greenlet # noqa: F401
|
103
|
+
except ImportError:
|
104
|
+
return False
|
105
|
+
else:
|
106
|
+
return True
|
107
|
+
|
108
|
+
return self.sqlalchemy_14 + exclusions.only_if(go)
|
109
|
+
|
98
110
|
@property
|
99
111
|
def comments(self):
|
100
112
|
return exclusions.only_if(
|
alembic/testing/schemacompare.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
from itertools import zip_longest
|
2
2
|
|
3
3
|
from sqlalchemy import schema
|
4
|
+
from sqlalchemy.sql.elements import ClauseList
|
4
5
|
|
5
6
|
|
6
7
|
class CompareTable:
|
@@ -60,6 +61,14 @@ class CompareIndex:
|
|
60
61
|
def __ne__(self, other):
|
61
62
|
return not self.__eq__(other)
|
62
63
|
|
64
|
+
def __repr__(self):
|
65
|
+
expr = ClauseList(*self.index.expressions)
|
66
|
+
try:
|
67
|
+
expr_str = expr.compile().string
|
68
|
+
except Exception:
|
69
|
+
expr_str = str(expr)
|
70
|
+
return f"<CompareIndex {self.index.name}({expr_str})>"
|
71
|
+
|
63
72
|
|
64
73
|
class CompareCheckConstraint:
|
65
74
|
def __init__(self, constraint):
|
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,18 +7,26 @@ 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
|
-
|
12
|
-
|
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
|
|
16
27
|
py311 = sys.version_info >= (3, 11)
|
17
28
|
py310 = sys.version_info >= (3, 10)
|
18
29
|
py39 = sys.version_info >= (3, 9)
|
19
|
-
py38 = sys.version_info >= (3, 8)
|
20
30
|
|
21
31
|
|
22
32
|
# produce a wrapper that allows encoded text to stream
|
@@ -28,9 +38,13 @@ class EncodedIO(io.TextIOWrapper):
|
|
28
38
|
|
29
39
|
|
30
40
|
if py39:
|
31
|
-
from importlib import resources as
|
32
|
-
|
33
|
-
|
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
|
34
48
|
else:
|
35
49
|
import importlib_resources # type:ignore # noqa
|
36
50
|
import importlib_metadata # type:ignore # noqa
|
@@ -40,12 +54,14 @@ else:
|
|
40
54
|
def importlib_metadata_get(group: str) -> Sequence[EntryPoint]:
|
41
55
|
ep = importlib_metadata.entry_points()
|
42
56
|
if hasattr(ep, "select"):
|
43
|
-
return ep.select(group=group)
|
57
|
+
return ep.select(group=group)
|
44
58
|
else:
|
45
59
|
return ep.get(group, ()) # type: ignore
|
46
60
|
|
47
61
|
|
48
|
-
def formatannotation_fwdref(
|
62
|
+
def formatannotation_fwdref(
|
63
|
+
annotation: Any, base_module: Optional[Any] = None
|
64
|
+
) -> str:
|
49
65
|
"""vendored from python 3.7"""
|
50
66
|
# copied over _formatannotation from sqlalchemy 2.0
|
51
67
|
|
@@ -66,7 +82,7 @@ def formatannotation_fwdref(annotation, base_module=None):
|
|
66
82
|
def read_config_parser(
|
67
83
|
file_config: ConfigParser,
|
68
84
|
file_argument: Sequence[Union[str, os.PathLike[str]]],
|
69
|
-
) ->
|
85
|
+
) -> List[str]:
|
70
86
|
if py310:
|
71
87
|
return file_config.read(file_argument, encoding="locale")
|
72
88
|
else:
|