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/util/langhelpers.py
CHANGED
@@ -5,33 +5,46 @@ from collections.abc import Iterable
|
|
5
5
|
import textwrap
|
6
6
|
from typing import Any
|
7
7
|
from typing import Callable
|
8
|
+
from typing import cast
|
8
9
|
from typing import Dict
|
9
10
|
from typing import List
|
10
11
|
from typing import Mapping
|
12
|
+
from typing import MutableMapping
|
13
|
+
from typing import NoReturn
|
11
14
|
from typing import Optional
|
12
15
|
from typing import overload
|
13
16
|
from typing import Sequence
|
17
|
+
from typing import Set
|
14
18
|
from typing import Tuple
|
19
|
+
from typing import Type
|
20
|
+
from typing import TYPE_CHECKING
|
15
21
|
from typing import TypeVar
|
16
22
|
from typing import Union
|
17
23
|
import uuid
|
18
24
|
import warnings
|
19
25
|
|
20
|
-
from sqlalchemy.util import asbool # noqa
|
21
|
-
from sqlalchemy.util import immutabledict # noqa
|
22
|
-
from sqlalchemy.util import
|
23
|
-
from sqlalchemy.util import
|
24
|
-
from sqlalchemy.util import unique_list # noqa
|
26
|
+
from sqlalchemy.util import asbool as asbool # noqa: F401
|
27
|
+
from sqlalchemy.util import immutabledict as immutabledict # noqa: F401
|
28
|
+
from sqlalchemy.util import to_list as to_list # noqa: F401
|
29
|
+
from sqlalchemy.util import unique_list as unique_list
|
25
30
|
|
26
31
|
from .compat import inspect_getfullargspec
|
27
32
|
|
33
|
+
if True:
|
34
|
+
# zimports workaround :(
|
35
|
+
from sqlalchemy.util import ( # noqa: F401
|
36
|
+
memoized_property as memoized_property,
|
37
|
+
)
|
38
|
+
|
28
39
|
|
29
40
|
EMPTY_DICT: Mapping[Any, Any] = immutabledict()
|
30
|
-
_T = TypeVar("_T")
|
41
|
+
_T = TypeVar("_T", bound=Any)
|
42
|
+
|
43
|
+
_C = TypeVar("_C", bound=Callable[..., Any])
|
31
44
|
|
32
45
|
|
33
46
|
class _ModuleClsMeta(type):
|
34
|
-
def __setattr__(cls, key: str, value: Callable) -> None:
|
47
|
+
def __setattr__(cls, key: str, value: Callable[..., Any]) -> None:
|
35
48
|
super().__setattr__(key, value)
|
36
49
|
cls._update_module_proxies(key) # type: ignore
|
37
50
|
|
@@ -45,9 +58,13 @@ class ModuleClsProxy(metaclass=_ModuleClsMeta):
|
|
45
58
|
|
46
59
|
"""
|
47
60
|
|
48
|
-
_setups: Dict[
|
49
|
-
|
50
|
-
|
61
|
+
_setups: Dict[
|
62
|
+
Type[Any],
|
63
|
+
Tuple[
|
64
|
+
Set[str],
|
65
|
+
List[Tuple[MutableMapping[str, Any], MutableMapping[str, Any]]],
|
66
|
+
],
|
67
|
+
] = collections.defaultdict(lambda: (set(), []))
|
51
68
|
|
52
69
|
@classmethod
|
53
70
|
def _update_module_proxies(cls, name: str) -> None:
|
@@ -70,18 +87,33 @@ class ModuleClsProxy(metaclass=_ModuleClsMeta):
|
|
70
87
|
del globals_[attr_name]
|
71
88
|
|
72
89
|
@classmethod
|
73
|
-
def create_module_class_proxy(
|
90
|
+
def create_module_class_proxy(
|
91
|
+
cls,
|
92
|
+
globals_: MutableMapping[str, Any],
|
93
|
+
locals_: MutableMapping[str, Any],
|
94
|
+
) -> None:
|
74
95
|
attr_names, modules = cls._setups[cls]
|
75
96
|
modules.append((globals_, locals_))
|
76
97
|
cls._setup_proxy(globals_, locals_, attr_names)
|
77
98
|
|
78
99
|
@classmethod
|
79
|
-
def _setup_proxy(
|
100
|
+
def _setup_proxy(
|
101
|
+
cls,
|
102
|
+
globals_: MutableMapping[str, Any],
|
103
|
+
locals_: MutableMapping[str, Any],
|
104
|
+
attr_names: Set[str],
|
105
|
+
) -> None:
|
80
106
|
for methname in dir(cls):
|
81
107
|
cls._add_proxied_attribute(methname, globals_, locals_, attr_names)
|
82
108
|
|
83
109
|
@classmethod
|
84
|
-
def _add_proxied_attribute(
|
110
|
+
def _add_proxied_attribute(
|
111
|
+
cls,
|
112
|
+
methname: str,
|
113
|
+
globals_: MutableMapping[str, Any],
|
114
|
+
locals_: MutableMapping[str, Any],
|
115
|
+
attr_names: Set[str],
|
116
|
+
) -> None:
|
85
117
|
if not methname.startswith("_"):
|
86
118
|
meth = getattr(cls, methname)
|
87
119
|
if callable(meth):
|
@@ -92,10 +124,15 @@ class ModuleClsProxy(metaclass=_ModuleClsMeta):
|
|
92
124
|
attr_names.add(methname)
|
93
125
|
|
94
126
|
@classmethod
|
95
|
-
def _create_method_proxy(
|
127
|
+
def _create_method_proxy(
|
128
|
+
cls,
|
129
|
+
name: str,
|
130
|
+
globals_: MutableMapping[str, Any],
|
131
|
+
locals_: MutableMapping[str, Any],
|
132
|
+
) -> Callable[..., Any]:
|
96
133
|
fn = getattr(cls, name)
|
97
134
|
|
98
|
-
def _name_error(name, from_):
|
135
|
+
def _name_error(name: str, from_: Exception) -> NoReturn:
|
99
136
|
raise NameError(
|
100
137
|
"Can't invoke function '%s', as the proxy object has "
|
101
138
|
"not yet been "
|
@@ -119,7 +156,9 @@ class ModuleClsProxy(metaclass=_ModuleClsMeta):
|
|
119
156
|
translations,
|
120
157
|
)
|
121
158
|
|
122
|
-
def translate(
|
159
|
+
def translate(
|
160
|
+
fn_name: str, spec: Any, translations: Any, args: Any, kw: Any
|
161
|
+
) -> Any:
|
123
162
|
return_kw = {}
|
124
163
|
return_args = []
|
125
164
|
|
@@ -176,15 +215,15 @@ class ModuleClsProxy(metaclass=_ModuleClsMeta):
|
|
176
215
|
"doc": fn.__doc__,
|
177
216
|
}
|
178
217
|
)
|
179
|
-
lcl = {}
|
218
|
+
lcl: MutableMapping[str, Any] = {}
|
180
219
|
|
181
|
-
exec(func_text, globals_, lcl)
|
182
|
-
return lcl[name]
|
220
|
+
exec(func_text, cast("Dict[str, Any]", globals_), lcl)
|
221
|
+
return cast("Callable[..., Any]", lcl[name])
|
183
222
|
|
184
223
|
|
185
|
-
def _with_legacy_names(translations):
|
186
|
-
def decorate(fn):
|
187
|
-
fn._legacy_translations = translations
|
224
|
+
def _with_legacy_names(translations: Any) -> Any:
|
225
|
+
def decorate(fn: _C) -> _C:
|
226
|
+
fn._legacy_translations = translations # type: ignore[attr-defined]
|
188
227
|
return fn
|
189
228
|
|
190
229
|
return decorate
|
@@ -195,21 +234,25 @@ def rev_id() -> str:
|
|
195
234
|
|
196
235
|
|
197
236
|
@overload
|
198
|
-
def to_tuple(x: Any, default:
|
237
|
+
def to_tuple(x: Any, default: Tuple[Any, ...]) -> Tuple[Any, ...]:
|
199
238
|
...
|
200
239
|
|
201
240
|
|
202
241
|
@overload
|
203
|
-
def to_tuple(x: None, default: Optional[_T] =
|
242
|
+
def to_tuple(x: None, default: Optional[_T] = ...) -> _T:
|
204
243
|
...
|
205
244
|
|
206
245
|
|
207
246
|
@overload
|
208
|
-
def to_tuple(
|
247
|
+
def to_tuple(
|
248
|
+
x: Any, default: Optional[Tuple[Any, ...]] = None
|
249
|
+
) -> Tuple[Any, ...]:
|
209
250
|
...
|
210
251
|
|
211
252
|
|
212
|
-
def to_tuple(
|
253
|
+
def to_tuple(
|
254
|
+
x: Any, default: Optional[Tuple[Any, ...]] = None
|
255
|
+
) -> Optional[Tuple[Any, ...]]:
|
213
256
|
if x is None:
|
214
257
|
return default
|
215
258
|
elif isinstance(x, str):
|
@@ -226,13 +269,13 @@ def dedupe_tuple(tup: Tuple[str, ...]) -> Tuple[str, ...]:
|
|
226
269
|
|
227
270
|
class Dispatcher:
|
228
271
|
def __init__(self, uselist: bool = False) -> None:
|
229
|
-
self._registry: Dict[
|
272
|
+
self._registry: Dict[Tuple[Any, ...], Any] = {}
|
230
273
|
self.uselist = uselist
|
231
274
|
|
232
275
|
def dispatch_for(
|
233
276
|
self, target: Any, qualifier: str = "default"
|
234
|
-
) -> Callable:
|
235
|
-
def decorate(fn):
|
277
|
+
) -> Callable[[_C], _C]:
|
278
|
+
def decorate(fn: _C) -> _C:
|
236
279
|
if self.uselist:
|
237
280
|
self._registry.setdefault((target, qualifier), []).append(fn)
|
238
281
|
else:
|
@@ -244,7 +287,7 @@ class Dispatcher:
|
|
244
287
|
|
245
288
|
def dispatch(self, obj: Any, qualifier: str = "default") -> Any:
|
246
289
|
if isinstance(obj, str):
|
247
|
-
targets: Sequence = [obj]
|
290
|
+
targets: Sequence[Any] = [obj]
|
248
291
|
elif isinstance(obj, type):
|
249
292
|
targets = obj.__mro__
|
250
293
|
else:
|
@@ -259,11 +302,13 @@ class Dispatcher:
|
|
259
302
|
raise ValueError("no dispatch function for object: %s" % obj)
|
260
303
|
|
261
304
|
def _fn_or_list(
|
262
|
-
self, fn_or_list: Union[List[Callable], Callable]
|
263
|
-
) -> Callable:
|
305
|
+
self, fn_or_list: Union[List[Callable[..., Any]], Callable[..., Any]]
|
306
|
+
) -> Callable[..., Any]:
|
264
307
|
if self.uselist:
|
265
308
|
|
266
|
-
def go(*arg, **kw):
|
309
|
+
def go(*arg: Any, **kw: Any) -> None:
|
310
|
+
if TYPE_CHECKING:
|
311
|
+
assert isinstance(fn_or_list, Sequence)
|
267
312
|
for fn in fn_or_list:
|
268
313
|
fn(*arg, **kw)
|
269
314
|
|
alembic/util/messaging.py
CHANGED
@@ -5,6 +5,7 @@ from contextlib import contextmanager
|
|
5
5
|
import logging
|
6
6
|
import sys
|
7
7
|
import textwrap
|
8
|
+
from typing import Iterator
|
8
9
|
from typing import Optional
|
9
10
|
from typing import TextIO
|
10
11
|
from typing import Union
|
@@ -53,7 +54,9 @@ def write_outstream(
|
|
53
54
|
|
54
55
|
|
55
56
|
@contextmanager
|
56
|
-
def status(
|
57
|
+
def status(
|
58
|
+
status_msg: str, newline: bool = False, quiet: bool = False
|
59
|
+
) -> Iterator[None]:
|
57
60
|
msg(status_msg + " ...", newline, flush=True, quiet=quiet)
|
58
61
|
try:
|
59
62
|
yield
|
@@ -66,7 +69,7 @@ def status(status_msg: str, newline: bool = False, quiet: bool = False):
|
|
66
69
|
write_outstream(sys.stdout, " done\n")
|
67
70
|
|
68
71
|
|
69
|
-
def err(message: str, quiet: bool = False):
|
72
|
+
def err(message: str, quiet: bool = False) -> None:
|
70
73
|
log.error(message)
|
71
74
|
msg(f"FAILED: {message}", quiet=quiet)
|
72
75
|
sys.exit(-1)
|
@@ -74,7 +77,7 @@ def err(message: str, quiet: bool = False):
|
|
74
77
|
|
75
78
|
def obfuscate_url_pw(input_url: str) -> str:
|
76
79
|
u = url.make_url(input_url)
|
77
|
-
return sqla_compat.url_render_as_string(u, hide_password=True)
|
80
|
+
return sqla_compat.url_render_as_string(u, hide_password=True) # type: ignore # noqa: E501
|
78
81
|
|
79
82
|
|
80
83
|
def warn(msg: str, stacklevel: int = 2) -> None:
|
alembic/util/pyfiles.py
CHANGED
@@ -8,6 +8,8 @@ import importlib.util
|
|
8
8
|
import os
|
9
9
|
import re
|
10
10
|
import tempfile
|
11
|
+
from types import ModuleType
|
12
|
+
from typing import Any
|
11
13
|
from typing import Optional
|
12
14
|
|
13
15
|
from mako import exceptions
|
@@ -18,7 +20,7 @@ from .exc import CommandError
|
|
18
20
|
|
19
21
|
|
20
22
|
def template_to_file(
|
21
|
-
template_file: str, dest: str, output_encoding: str, **kw
|
23
|
+
template_file: str, dest: str, output_encoding: str, **kw: Any
|
22
24
|
) -> None:
|
23
25
|
template = Template(filename=template_file)
|
24
26
|
try:
|
@@ -82,7 +84,7 @@ def pyc_file_from_path(path: str) -> Optional[str]:
|
|
82
84
|
return None
|
83
85
|
|
84
86
|
|
85
|
-
def load_python_file(dir_: str, filename: str):
|
87
|
+
def load_python_file(dir_: str, filename: str) -> ModuleType:
|
86
88
|
"""Load a file from the given path as a Python module."""
|
87
89
|
|
88
90
|
module_id = re.sub(r"\W", "_", filename)
|
@@ -99,10 +101,12 @@ def load_python_file(dir_: str, filename: str):
|
|
99
101
|
module = load_module_py(module_id, pyc_path)
|
100
102
|
elif ext in (".pyc", ".pyo"):
|
101
103
|
module = load_module_py(module_id, path)
|
104
|
+
else:
|
105
|
+
assert False
|
102
106
|
return module
|
103
107
|
|
104
108
|
|
105
|
-
def load_module_py(module_id: str, path: str):
|
109
|
+
def load_module_py(module_id: str, path: str) -> ModuleType:
|
106
110
|
spec = importlib.util.spec_from_file_location(module_id, path)
|
107
111
|
assert spec
|
108
112
|
module = importlib.util.module_from_spec(spec)
|
alembic/util/sqla_compat.py
CHANGED
@@ -1,13 +1,20 @@
|
|
1
|
+
# mypy: allow-untyped-defs, allow-incomplete-defs, allow-untyped-calls
|
2
|
+
# mypy: no-warn-return-any, allow-any-generics
|
3
|
+
|
1
4
|
from __future__ import annotations
|
2
5
|
|
3
6
|
import contextlib
|
4
7
|
import re
|
5
8
|
from typing import Any
|
9
|
+
from typing import Callable
|
6
10
|
from typing import Dict
|
7
11
|
from typing import Iterable
|
8
12
|
from typing import Iterator
|
9
13
|
from typing import Mapping
|
10
14
|
from typing import Optional
|
15
|
+
from typing import Protocol
|
16
|
+
from typing import Set
|
17
|
+
from typing import Type
|
11
18
|
from typing import TYPE_CHECKING
|
12
19
|
from typing import TypeVar
|
13
20
|
from typing import Union
|
@@ -18,7 +25,6 @@ from sqlalchemy import schema
|
|
18
25
|
from sqlalchemy import sql
|
19
26
|
from sqlalchemy import types as sqltypes
|
20
27
|
from sqlalchemy.engine import url
|
21
|
-
from sqlalchemy.ext.compiler import compiles
|
22
28
|
from sqlalchemy.schema import CheckConstraint
|
23
29
|
from sqlalchemy.schema import Column
|
24
30
|
from sqlalchemy.schema import ForeignKeyConstraint
|
@@ -33,6 +39,7 @@ from sqlalchemy.sql.visitors import traverse
|
|
33
39
|
from typing_extensions import TypeGuard
|
34
40
|
|
35
41
|
if TYPE_CHECKING:
|
42
|
+
from sqlalchemy import ClauseElement
|
36
43
|
from sqlalchemy import Index
|
37
44
|
from sqlalchemy import Table
|
38
45
|
from sqlalchemy.engine import Connection
|
@@ -51,6 +58,11 @@ if TYPE_CHECKING:
|
|
51
58
|
_CE = TypeVar("_CE", bound=Union["ColumnElement[Any]", "SchemaItem"])
|
52
59
|
|
53
60
|
|
61
|
+
class _CompilerProtocol(Protocol):
|
62
|
+
def __call__(self, element: Any, compiler: Any, **kw: Any) -> str:
|
63
|
+
...
|
64
|
+
|
65
|
+
|
54
66
|
def _safe_int(value: str) -> Union[int, str]:
|
55
67
|
try:
|
56
68
|
return int(value)
|
@@ -70,7 +82,7 @@ sqla_2 = _vers >= (2,)
|
|
70
82
|
sqlalchemy_version = __version__
|
71
83
|
|
72
84
|
try:
|
73
|
-
from sqlalchemy.sql.naming import _NONE_NAME as _NONE_NAME
|
85
|
+
from sqlalchemy.sql.naming import _NONE_NAME as _NONE_NAME # type: ignore[attr-defined] # noqa: E501
|
74
86
|
except ImportError:
|
75
87
|
from sqlalchemy.sql.elements import _NONE_NAME as _NONE_NAME # type: ignore # noqa: E501
|
76
88
|
|
@@ -79,8 +91,18 @@ class _Unsupported:
|
|
79
91
|
"Placeholder for unsupported SQLAlchemy classes"
|
80
92
|
|
81
93
|
|
94
|
+
if TYPE_CHECKING:
|
95
|
+
|
96
|
+
def compiles(
|
97
|
+
element: Type[ClauseElement], *dialects: str
|
98
|
+
) -> Callable[[_CompilerProtocol], _CompilerProtocol]:
|
99
|
+
...
|
100
|
+
|
101
|
+
else:
|
102
|
+
from sqlalchemy.ext.compiler import compiles
|
103
|
+
|
82
104
|
try:
|
83
|
-
from sqlalchemy import Computed
|
105
|
+
from sqlalchemy import Computed as Computed
|
84
106
|
except ImportError:
|
85
107
|
if not TYPE_CHECKING:
|
86
108
|
|
@@ -94,7 +116,7 @@ else:
|
|
94
116
|
has_computed_reflection = _vers >= (1, 3, 16)
|
95
117
|
|
96
118
|
try:
|
97
|
-
from sqlalchemy import Identity
|
119
|
+
from sqlalchemy import Identity as Identity
|
98
120
|
except ImportError:
|
99
121
|
if not TYPE_CHECKING:
|
100
122
|
|
@@ -250,7 +272,7 @@ def _idx_table_bound_expressions(idx: Index) -> Iterable[ColumnElement[Any]]:
|
|
250
272
|
|
251
273
|
def _copy(schema_item: _CE, **kw) -> _CE:
|
252
274
|
if hasattr(schema_item, "_copy"):
|
253
|
-
return schema_item._copy(**kw)
|
275
|
+
return schema_item._copy(**kw)
|
254
276
|
else:
|
255
277
|
return schema_item.copy(**kw) # type: ignore[union-attr]
|
256
278
|
|
@@ -368,7 +390,12 @@ else:
|
|
368
390
|
return type_.impl, type_.mapping
|
369
391
|
|
370
392
|
|
371
|
-
def _fk_spec(constraint):
|
393
|
+
def _fk_spec(constraint: ForeignKeyConstraint) -> Any:
|
394
|
+
if TYPE_CHECKING:
|
395
|
+
assert constraint.columns is not None
|
396
|
+
assert constraint.elements is not None
|
397
|
+
assert isinstance(constraint.parent, Table)
|
398
|
+
|
372
399
|
source_columns = [
|
373
400
|
constraint.columns[key].name for key in constraint.column_keys
|
374
401
|
]
|
@@ -397,7 +424,7 @@ def _fk_spec(constraint):
|
|
397
424
|
|
398
425
|
|
399
426
|
def _fk_is_self_referential(constraint: ForeignKeyConstraint) -> bool:
|
400
|
-
spec = constraint.elements[0]._get_colspec()
|
427
|
+
spec = constraint.elements[0]._get_colspec()
|
401
428
|
tokens = spec.split(".")
|
402
429
|
tokens.pop(-1) # colname
|
403
430
|
tablekey = ".".join(tokens)
|
@@ -409,13 +436,13 @@ def _is_type_bound(constraint: Constraint) -> bool:
|
|
409
436
|
# this deals with SQLAlchemy #3260, don't copy CHECK constraints
|
410
437
|
# that will be generated by the type.
|
411
438
|
# new feature added for #3260
|
412
|
-
return constraint._type_bound
|
439
|
+
return constraint._type_bound
|
413
440
|
|
414
441
|
|
415
442
|
def _find_columns(clause):
|
416
443
|
"""locate Column objects within the given expression."""
|
417
444
|
|
418
|
-
cols = set()
|
445
|
+
cols: Set[ColumnElement[Any]] = set()
|
419
446
|
traverse(clause, {}, {"column": cols.add})
|
420
447
|
return cols
|
421
448
|
|
@@ -524,14 +551,6 @@ def _render_literal_bindparam(
|
|
524
551
|
return compiler.render_literal_bindparam(element, **kw)
|
525
552
|
|
526
553
|
|
527
|
-
def _get_index_expressions(idx):
|
528
|
-
return list(idx.expressions)
|
529
|
-
|
530
|
-
|
531
|
-
def _get_index_column_names(idx):
|
532
|
-
return [getattr(exp, "name", None) for exp in _get_index_expressions(idx)]
|
533
|
-
|
534
|
-
|
535
554
|
def _column_kwargs(col: Column) -> Mapping:
|
536
555
|
if sqla_13:
|
537
556
|
return col.kwargs
|
@@ -570,9 +589,7 @@ def _get_constraint_final_name(
|
|
570
589
|
if isinstance(constraint, schema.Index):
|
571
590
|
# name should not be quoted.
|
572
591
|
d = dialect.ddl_compiler(dialect, None) # type: ignore[arg-type]
|
573
|
-
return d._prepared_index_name(
|
574
|
-
constraint
|
575
|
-
)
|
592
|
+
return d._prepared_index_name(constraint)
|
576
593
|
else:
|
577
594
|
# name should not be quoted.
|
578
595
|
return dialect.identifier_preparer.format_constraint(constraint)
|
@@ -616,7 +633,11 @@ def _insert_inline(table: Union[TableClause, Table]) -> Insert:
|
|
616
633
|
|
617
634
|
if sqla_14:
|
618
635
|
from sqlalchemy import create_mock_engine
|
619
|
-
|
636
|
+
|
637
|
+
# weird mypy workaround
|
638
|
+
from sqlalchemy import select as _sa_select
|
639
|
+
|
640
|
+
_select = _sa_select
|
620
641
|
else:
|
621
642
|
from sqlalchemy import create_engine
|
622
643
|
|
@@ -625,15 +646,20 @@ else:
|
|
625
646
|
"postgresql://", strategy="mock", executor=executor
|
626
647
|
)
|
627
648
|
|
628
|
-
def _select(*columns, **kw) -> Select:
|
649
|
+
def _select(*columns, **kw) -> Select:
|
629
650
|
return sql.select(list(columns), **kw) # type: ignore[call-overload]
|
630
651
|
|
631
652
|
|
632
653
|
def is_expression_index(index: Index) -> bool:
|
633
|
-
expr: Any
|
634
654
|
for expr in index.expressions:
|
635
|
-
|
636
|
-
expr = expr.element
|
637
|
-
if not isinstance(expr, ColumnClause) or expr.is_literal:
|
655
|
+
if is_expression(expr):
|
638
656
|
return True
|
639
657
|
return False
|
658
|
+
|
659
|
+
|
660
|
+
def is_expression(expr: Any) -> bool:
|
661
|
+
while isinstance(expr, UnaryExpression):
|
662
|
+
expr = expr.element
|
663
|
+
if not isinstance(expr, ColumnClause) or expr.is_literal:
|
664
|
+
return True
|
665
|
+
return False
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: alembic
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.13.1
|
4
4
|
Summary: A database migration tool for SQLAlchemy.
|
5
5
|
Home-page: https://alembic.sqlalchemy.org
|
6
6
|
Author: Mike Bayer
|
@@ -17,14 +17,15 @@ Classifier: License :: OSI Approved :: MIT License
|
|
17
17
|
Classifier: Operating System :: OS Independent
|
18
18
|
Classifier: Programming Language :: Python
|
19
19
|
Classifier: Programming Language :: Python :: 3
|
20
|
-
Classifier: Programming Language :: Python :: 3.7
|
21
20
|
Classifier: Programming Language :: Python :: 3.8
|
22
21
|
Classifier: Programming Language :: Python :: 3.9
|
23
22
|
Classifier: Programming Language :: Python :: 3.10
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
24
25
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
25
26
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
26
27
|
Classifier: Topic :: Database :: Front-Ends
|
27
|
-
Requires-Python: >=3.
|
28
|
+
Requires-Python: >=3.8
|
28
29
|
Description-Content-Type: text/x-rst
|
29
30
|
License-File: LICENSE
|
30
31
|
Requires-Dist: SQLAlchemy >=1.3.0
|
@@ -33,7 +34,7 @@ Requires-Dist: typing-extensions >=4
|
|
33
34
|
Requires-Dist: importlib-metadata ; python_version < "3.9"
|
34
35
|
Requires-Dist: importlib-resources ; python_version < "3.9"
|
35
36
|
Provides-Extra: tz
|
36
|
-
Requires-Dist:
|
37
|
+
Requires-Dist: backports.zoneinfo ; (python_version < "3.9") and extra == 'tz'
|
37
38
|
|
38
39
|
Alembic is a database migrations tool written by the author
|
39
40
|
of `SQLAlchemy <http://www.sqlalchemy.org>`_. A migrations tool
|
@@ -0,0 +1,83 @@
|
|
1
|
+
alembic/__init__.py,sha256=PMiQT_1tHyC_Od3GDBArBk7r14v8F62_xkzliPq9tLU,63
|
2
|
+
alembic/__main__.py,sha256=373m7-TBh72JqrSMYviGrxCHZo-cnweM8AGF8A22PmY,78
|
3
|
+
alembic/command.py,sha256=jWFNS-wPWA-Klfm0GsPfWh_8sPj4n7rKROJ0zrwhoR0,21712
|
4
|
+
alembic/config.py,sha256=I12lm4V-AXSt-7nvub-Vtx5Zfa68pYP5xSrFQQd45rQ,22256
|
5
|
+
alembic/context.py,sha256=hK1AJOQXJ29Bhn276GYcosxeG7pC5aZRT5E8c4bMJ4Q,195
|
6
|
+
alembic/context.pyi,sha256=hUHbSnbSeEEMVkk0gDSXOq4_9edSjYzsjmmf-mL9Iao,31737
|
7
|
+
alembic/environment.py,sha256=MM5lPayGT04H3aeng1H7GQ8HEAs3VGX5yy6mDLCPLT4,43
|
8
|
+
alembic/migration.py,sha256=MV6Fju6rZtn2fTREKzXrCZM6aIBGII4OMZFix0X-GLs,41
|
9
|
+
alembic/op.py,sha256=flHtcsVqOD-ZgZKK2pv-CJ5Cwh-KJ7puMUNXzishxLw,167
|
10
|
+
alembic/op.pyi,sha256=8R6SJr1dQharU0blmMJJj23XFO_hk9ZmAQBJBQOeXRU,49816
|
11
|
+
alembic/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
|
+
alembic/autogenerate/__init__.py,sha256=ntmUTXhjLm4_zmqIwyVaECdpPDn6_u1yM9vYk6-553E,543
|
13
|
+
alembic/autogenerate/api.py,sha256=Oc7MRtDhkSICsQ82fYP9bBMYaAjzzW2X_izM3AQU-OY,22171
|
14
|
+
alembic/autogenerate/compare.py,sha256=3QLK2yCDW37bXbAIXcHGz4YOFlOW8bSfLHJ8bmzgG1M,44938
|
15
|
+
alembic/autogenerate/render.py,sha256=uSbCpkh72mo00xGZ8CJa3teM_gqulCoNtxH0Ey8Ny1k,34939
|
16
|
+
alembic/autogenerate/rewriter.py,sha256=uZWRkTYJoncoEJ5WY1QBRiozjyChqZDJPy4LtcRibjM,7846
|
17
|
+
alembic/ddl/__init__.py,sha256=Df8fy4Vn_abP8B7q3x8gyFwEwnLw6hs2Ljt_bV3EZWE,152
|
18
|
+
alembic/ddl/_autogen.py,sha256=0no9ywWP8gjvO57Ozc2naab4qNusVNn2fiJekjc275g,9179
|
19
|
+
alembic/ddl/base.py,sha256=Jd7oPoAOGjOMcdMUIzSKnTjd8NKnTd7IjBXXyVpDCkU,9955
|
20
|
+
alembic/ddl/impl.py,sha256=vkhkXFpLPJBG9jW2kv_sR5CC5czNd1ERLjLtfLuOFP0,28778
|
21
|
+
alembic/ddl/mssql.py,sha256=ydvgBSaftKYjaBaMyqius66Ta4CICQSj79Og3Ed2atY,14219
|
22
|
+
alembic/ddl/mysql.py,sha256=am221U_UK3wX33tNcXNiOObZV-Pa4CXuv7vN-epF9IU,16788
|
23
|
+
alembic/ddl/oracle.py,sha256=TmoCq_FlbfyWAAk3e_q6mMQU0YmlfIcgKHpRfNMmgr0,6211
|
24
|
+
alembic/ddl/postgresql.py,sha256=dcWLdDSqivzizVCce_H6RnOVAayPXDFfns-NC4-UaA8,29842
|
25
|
+
alembic/ddl/sqlite.py,sha256=wLXhb8bJWRspKQTb-iVfepR4LXYgOuEbUWKX5qwDhIQ,7570
|
26
|
+
alembic/operations/__init__.py,sha256=e0KQSZAgLpTWvyvreB7DWg7RJV_MWSOPVDgCqsd2FzY,318
|
27
|
+
alembic/operations/base.py,sha256=LCx4NH5NA2NLWQFaZTqE_p2KgLtqJ76oVcp1Grj-zFM,74004
|
28
|
+
alembic/operations/batch.py,sha256=YqtD4hJ3_RkFxvI7zbmBwxcLEyLHYyWQpsz4l5L85yI,26943
|
29
|
+
alembic/operations/ops.py,sha256=2vtYFhYFDEVq158HwORfGTsobDM7c-t0lewuR7JKw7g,94353
|
30
|
+
alembic/operations/schemaobj.py,sha256=vjoD57QvjbzzA-jyPIXulbOmb5_bGPtxoq58KsKI4Y0,9424
|
31
|
+
alembic/operations/toimpl.py,sha256=SoNY2_gZX2baXTD-pNjpCWnON8D2QBSYQBIjo13-WKA,7115
|
32
|
+
alembic/runtime/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
33
|
+
alembic/runtime/environment.py,sha256=9wSJaePNAXBXvirif_85ql7dSq4bXM1E6pSb2k-6uGI,41508
|
34
|
+
alembic/runtime/migration.py,sha256=Yfv2fa11wiQ0WgoZaFldlWxCPq4dVDOCEOxST_-1VB0,50066
|
35
|
+
alembic/script/__init__.py,sha256=lSj06O391Iy5avWAiq8SPs6N8RBgxkSPjP8wpXcNDGg,100
|
36
|
+
alembic/script/base.py,sha256=4gkppn2FKCYDoBgzGkTslcwdyxSabmHvGq0uGKulwbI,37586
|
37
|
+
alembic/script/revision.py,sha256=sfnXQw2UwiXs0E6gEPHBKWuSsB5KyuxZPTrFn__hIEk,62060
|
38
|
+
alembic/script/write_hooks.py,sha256=NGB6NGgfdf7HK6XNNpSKqUCfzxazj-NRUePgFx7MJSM,5036
|
39
|
+
alembic/templates/async/README,sha256=ISVtAOvqvKk_5ThM5ioJE-lMkvf9IbknFUFVU_vPma4,58
|
40
|
+
alembic/templates/async/alembic.ini.mako,sha256=uuhJETLWQuiYcs_jAOXHEjshEJ7VslEc1q4RRj0HWbE,3525
|
41
|
+
alembic/templates/async/env.py,sha256=zbOCf3Y7w2lg92hxSwmG1MM_7y56i_oRH4AKp0pQBYo,2389
|
42
|
+
alembic/templates/async/script.py.mako,sha256=MEqL-2qATlST9TAOeYgscMn1uy6HUS9NFvDgl93dMj8,635
|
43
|
+
alembic/templates/generic/README,sha256=MVlc9TYmr57RbhXET6QxgyCcwWP7w-vLkEsirENqiIQ,38
|
44
|
+
alembic/templates/generic/alembic.ini.mako,sha256=sT7F852yN3c8X1-GKFlhuWExXxw9hY1eb1ZZ9flFSzc,3634
|
45
|
+
alembic/templates/generic/env.py,sha256=TLRWOVW3Xpt_Tpf8JFzlnoPn_qoUu8UV77Y4o9XD6yI,2103
|
46
|
+
alembic/templates/generic/script.py.mako,sha256=MEqL-2qATlST9TAOeYgscMn1uy6HUS9NFvDgl93dMj8,635
|
47
|
+
alembic/templates/multidb/README,sha256=dWLDhnBgphA4Nzb7sNlMfCS3_06YqVbHhz-9O5JNqyI,606
|
48
|
+
alembic/templates/multidb/alembic.ini.mako,sha256=mPh8JFJfWiGs6tMtL8_HAQ-Dz1QOoJgE5Vm76nIMqgU,3728
|
49
|
+
alembic/templates/multidb/env.py,sha256=6zNjnW8mXGUk7erTsAvrfhvqoczJ-gagjVq1Ypg2YIQ,4230
|
50
|
+
alembic/templates/multidb/script.py.mako,sha256=N06nMtNSwHkgl0EBXDyMt8njp9tlOesR583gfq21nbY,1090
|
51
|
+
alembic/testing/__init__.py,sha256=kOxOh5nwmui9d-_CCq9WA4Udwy7ITjm453w74CTLZDo,1159
|
52
|
+
alembic/testing/assertions.py,sha256=1CbJk8c8-WO9eJ0XJ0jJvMsNRLUrXV41NOeIJUAlOBk,5015
|
53
|
+
alembic/testing/env.py,sha256=zJacVb_z6uLs2U1TtkmnFH9P3_F-3IfYbVv4UEPOvfo,10754
|
54
|
+
alembic/testing/fixtures.py,sha256=NyP4wE_dFN9ZzSGiBagRu1cdzkka03nwJYJYHYrrkSY,9112
|
55
|
+
alembic/testing/requirements.py,sha256=dKeAO1l5TwBqXarJN-IPORlCqCJv-41Dj6oXoEikxHQ,5133
|
56
|
+
alembic/testing/schemacompare.py,sha256=N5UqSNCOJetIKC4vKhpYzQEpj08XkdgIoqBmEPQ3tlc,4838
|
57
|
+
alembic/testing/util.py,sha256=CQrcQDA8fs_7ME85z5ydb-Bt70soIIID-qNY1vbR2dg,3350
|
58
|
+
alembic/testing/warnings.py,sha256=RxA7x_8GseANgw07Us8JN_1iGbANxaw6_VitX2ZGQH4,1078
|
59
|
+
alembic/testing/plugin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
60
|
+
alembic/testing/plugin/bootstrap.py,sha256=9C6wtjGrIVztZ928w27hsQE0KcjDLIUtUN3dvZKsMVk,50
|
61
|
+
alembic/testing/suite/__init__.py,sha256=MvE7-hwbaVN1q3NM-ztGxORU9dnIelUCINKqNxewn7Y,288
|
62
|
+
alembic/testing/suite/_autogen_fixtures.py,sha256=cDq1pmzHe15S6dZPGNC6sqFaCQ3hLT_oPV2IDigUGQ0,9880
|
63
|
+
alembic/testing/suite/test_autogen_comments.py,sha256=aEGqKUDw4kHjnDk298aoGcQvXJWmZXcIX_2FxH4cJK8,6283
|
64
|
+
alembic/testing/suite/test_autogen_computed.py,sha256=qJeBpc8urnwTFvbwWrSTIbHVkRUuCXP-dKaNbUK2U2U,6077
|
65
|
+
alembic/testing/suite/test_autogen_diffs.py,sha256=T4SR1n_kmcOKYhR4W1-dA0e5sddJ69DSVL2HW96kAkE,8394
|
66
|
+
alembic/testing/suite/test_autogen_fks.py,sha256=AqFmb26Buex167HYa9dZWOk8x-JlB1OK3bwcvvjDFaU,32927
|
67
|
+
alembic/testing/suite/test_autogen_identity.py,sha256=kcuqngG7qXAKPJDX4U8sRzPKHEJECHuZ0DtuaS6tVkk,5824
|
68
|
+
alembic/testing/suite/test_environment.py,sha256=w9F0xnLEbALeR8k6_-Tz6JHvy91IqiTSypNasVzXfZQ,11877
|
69
|
+
alembic/testing/suite/test_op.py,sha256=2XQCdm_NmnPxHGuGj7hmxMzIhKxXNotUsKdACXzE1mM,1343
|
70
|
+
alembic/util/__init__.py,sha256=KSZ7UT2YzH6CietgUtljVoE3QnGjoFKOi7RL5sgUxrk,1688
|
71
|
+
alembic/util/compat.py,sha256=RjHdQa1NomU3Zlvgfvza0OMiSRQSLRL3xVl3OdUy2UE,2594
|
72
|
+
alembic/util/editor.py,sha256=JIz6_BdgV8_oKtnheR6DZoB7qnrHrlRgWjx09AsTsUw,2546
|
73
|
+
alembic/util/exc.py,sha256=KQTru4zcgAmN4IxLMwLFS56XToUewaXB7oOLcPNjPwg,98
|
74
|
+
alembic/util/langhelpers.py,sha256=KYyOjFjJ26evPmrwhdTvLQNXN0bK7AIy5sRdKD91Fvg,10038
|
75
|
+
alembic/util/messaging.py,sha256=BM5OCZ6qmLftFRw5yPSxj539_QmfVwNYoU8qYsDqoJY,3132
|
76
|
+
alembic/util/pyfiles.py,sha256=zltVdcwEJJCPS2gHsQvkHkQakuF6wXiZ6zfwHbGNT0g,3489
|
77
|
+
alembic/util/sqla_compat.py,sha256=toD1S63PgZ6iEteP9bwIf5E7DIUdQPo0UQ_Fn18qWnI,19536
|
78
|
+
alembic-1.13.1.dist-info/LICENSE,sha256=soUmiob0QW6vTQWyrjiAwVb3xZqPk1pAK8BW6vszrwg,1058
|
79
|
+
alembic-1.13.1.dist-info/METADATA,sha256=W1F2NBRkhqW55HiGmEIpdmiRt2skU5wwJd21UHFbSdQ,7390
|
80
|
+
alembic-1.13.1.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
81
|
+
alembic-1.13.1.dist-info/entry_points.txt,sha256=aykM30soxwGN0pB7etLc1q0cHJbL9dy46RnK9VX4LLw,48
|
82
|
+
alembic-1.13.1.dist-info/top_level.txt,sha256=FwKWd5VsPFC8iQjpu1u9Cn-JnK3-V1RhUCmWqz1cl-s,8
|
83
|
+
alembic-1.13.1.dist-info/RECORD,,
|