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
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
[alembic]
|
4
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
|
@@ -22,8 +23,7 @@ prepend_sys_path = .
|
|
22
23
|
# leave blank for localtime
|
23
24
|
# timezone =
|
24
25
|
|
25
|
-
# max length of characters to apply to the
|
26
|
-
# "slug" field
|
26
|
+
# max length of characters to apply to the "slug" field
|
27
27
|
# truncate_slug_length = 40
|
28
28
|
|
29
29
|
# set to 'true' to run the environment during
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
[alembic]
|
4
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
|
@@ -22,8 +23,7 @@ prepend_sys_path = .
|
|
22
23
|
# leave blank for localtime
|
23
24
|
# timezone =
|
24
25
|
|
25
|
-
# max length of characters to apply to the
|
26
|
-
# "slug" field
|
26
|
+
# max length of characters to apply to the "slug" field
|
27
27
|
# truncate_slug_length = 40
|
28
28
|
|
29
29
|
# set to 'true' to run the environment during
|
alembic/testing/fixtures.py
CHANGED
@@ -49,6 +49,12 @@ class TestBase(SQLAlchemyTestBase):
|
|
49
49
|
connection, opts=dict(transaction_per_migration=True)
|
50
50
|
)
|
51
51
|
|
52
|
+
@testing.fixture
|
53
|
+
def as_sql_migration_context(self, connection):
|
54
|
+
return MigrationContext.configure(
|
55
|
+
connection, opts=dict(transaction_per_migration=True, as_sql=True)
|
56
|
+
)
|
57
|
+
|
52
58
|
@testing.fixture
|
53
59
|
def connection(self):
|
54
60
|
with config.db.connect() as conn:
|
@@ -268,9 +274,11 @@ class AlterColRoundTripFixture:
|
|
268
274
|
"x",
|
269
275
|
column.name,
|
270
276
|
existing_type=column.type,
|
271
|
-
existing_server_default=
|
272
|
-
|
273
|
-
|
277
|
+
existing_server_default=(
|
278
|
+
column.server_default
|
279
|
+
if column.server_default is not None
|
280
|
+
else False
|
281
|
+
),
|
274
282
|
existing_nullable=True if column.nullable else False,
|
275
283
|
# existing_comment=column.comment,
|
276
284
|
nullable=to_.get("nullable", None),
|
@@ -298,9 +306,13 @@ class AlterColRoundTripFixture:
|
|
298
306
|
new_col["type"],
|
299
307
|
new_col.get("default", None),
|
300
308
|
compare.get("type", old_col["type"]),
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
309
|
+
(
|
310
|
+
compare["server_default"].text
|
311
|
+
if "server_default" in compare
|
312
|
+
else (
|
313
|
+
column.server_default.arg.text
|
314
|
+
if column.server_default is not None
|
315
|
+
else None
|
316
|
+
)
|
317
|
+
),
|
306
318
|
)
|
@@ -124,6 +124,7 @@ class AutogenerateComputedTest(AutogenFixtureTest, TestBase):
|
|
124
124
|
lambda: (None, None),
|
125
125
|
lambda: (sa.Computed("5"), sa.Computed("5")),
|
126
126
|
lambda: (sa.Computed("bar*5"), sa.Computed("bar*5")),
|
127
|
+
lambda: (sa.Computed("bar*5"), sa.Computed("bar * \r\n\t5")),
|
127
128
|
(
|
128
129
|
lambda: (sa.Computed("bar*5"), None),
|
129
130
|
config.requirements.computed_doesnt_reflect_as_server_default,
|
@@ -24,9 +24,9 @@ class MigrationTransactionTest(TestBase):
|
|
24
24
|
self.context = MigrationContext.configure(
|
25
25
|
dialect=conn.dialect, opts=opts
|
26
26
|
)
|
27
|
-
self.context.output_buffer = (
|
28
|
-
|
29
|
-
)
|
27
|
+
self.context.output_buffer = self.context.impl.output_buffer = (
|
28
|
+
io.StringIO()
|
29
|
+
)
|
30
30
|
else:
|
31
31
|
self.context = MigrationContext.configure(
|
32
32
|
connection=conn, opts=opts
|
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,11 +7,20 @@ 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
|
|
@@ -27,9 +38,13 @@ class EncodedIO(io.TextIOWrapper):
|
|
27
38
|
|
28
39
|
|
29
40
|
if py39:
|
30
|
-
from importlib import resources as
|
31
|
-
|
32
|
-
|
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
|
33
48
|
else:
|
34
49
|
import importlib_resources # type:ignore # noqa
|
35
50
|
import importlib_metadata # type:ignore # noqa
|
@@ -39,12 +54,14 @@ else:
|
|
39
54
|
def importlib_metadata_get(group: str) -> Sequence[EntryPoint]:
|
40
55
|
ep = importlib_metadata.entry_points()
|
41
56
|
if hasattr(ep, "select"):
|
42
|
-
return ep.select(group=group)
|
57
|
+
return ep.select(group=group)
|
43
58
|
else:
|
44
59
|
return ep.get(group, ()) # type: ignore
|
45
60
|
|
46
61
|
|
47
|
-
def formatannotation_fwdref(
|
62
|
+
def formatannotation_fwdref(
|
63
|
+
annotation: Any, base_module: Optional[Any] = None
|
64
|
+
) -> str:
|
48
65
|
"""vendored from python 3.7"""
|
49
66
|
# copied over _formatannotation from sqlalchemy 2.0
|
50
67
|
|
@@ -65,7 +82,7 @@ def formatannotation_fwdref(annotation, base_module=None):
|
|
65
82
|
def read_config_parser(
|
66
83
|
file_config: ConfigParser,
|
67
84
|
file_argument: Sequence[Union[str, os.PathLike[str]]],
|
68
|
-
) ->
|
85
|
+
) -> List[str]:
|
69
86
|
if py310:
|
70
87
|
return file_config.read(file_argument, encoding="locale")
|
71
88
|
else:
|
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,22 @@ def rev_id() -> str:
|
|
195
234
|
|
196
235
|
|
197
236
|
@overload
|
198
|
-
def to_tuple(x: Any, default:
|
199
|
-
...
|
237
|
+
def to_tuple(x: Any, default: Tuple[Any, ...]) -> Tuple[Any, ...]: ...
|
200
238
|
|
201
239
|
|
202
240
|
@overload
|
203
|
-
def to_tuple(x: None, default: Optional[_T] =
|
204
|
-
...
|
241
|
+
def to_tuple(x: None, default: Optional[_T] = ...) -> _T: ...
|
205
242
|
|
206
243
|
|
207
244
|
@overload
|
208
|
-
def to_tuple(
|
209
|
-
...
|
245
|
+
def to_tuple(
|
246
|
+
x: Any, default: Optional[Tuple[Any, ...]] = None
|
247
|
+
) -> Tuple[Any, ...]: ...
|
210
248
|
|
211
249
|
|
212
|
-
def to_tuple(
|
250
|
+
def to_tuple(
|
251
|
+
x: Any, default: Optional[Tuple[Any, ...]] = None
|
252
|
+
) -> Optional[Tuple[Any, ...]]:
|
213
253
|
if x is None:
|
214
254
|
return default
|
215
255
|
elif isinstance(x, str):
|
@@ -226,13 +266,13 @@ def dedupe_tuple(tup: Tuple[str, ...]) -> Tuple[str, ...]:
|
|
226
266
|
|
227
267
|
class Dispatcher:
|
228
268
|
def __init__(self, uselist: bool = False) -> None:
|
229
|
-
self._registry: Dict[
|
269
|
+
self._registry: Dict[Tuple[Any, ...], Any] = {}
|
230
270
|
self.uselist = uselist
|
231
271
|
|
232
272
|
def dispatch_for(
|
233
273
|
self, target: Any, qualifier: str = "default"
|
234
|
-
) -> Callable:
|
235
|
-
def decorate(fn):
|
274
|
+
) -> Callable[[_C], _C]:
|
275
|
+
def decorate(fn: _C) -> _C:
|
236
276
|
if self.uselist:
|
237
277
|
self._registry.setdefault((target, qualifier), []).append(fn)
|
238
278
|
else:
|
@@ -244,7 +284,7 @@ class Dispatcher:
|
|
244
284
|
|
245
285
|
def dispatch(self, obj: Any, qualifier: str = "default") -> Any:
|
246
286
|
if isinstance(obj, str):
|
247
|
-
targets: Sequence = [obj]
|
287
|
+
targets: Sequence[Any] = [obj]
|
248
288
|
elif isinstance(obj, type):
|
249
289
|
targets = obj.__mro__
|
250
290
|
else:
|
@@ -259,11 +299,13 @@ class Dispatcher:
|
|
259
299
|
raise ValueError("no dispatch function for object: %s" % obj)
|
260
300
|
|
261
301
|
def _fn_or_list(
|
262
|
-
self, fn_or_list: Union[List[Callable], Callable]
|
263
|
-
) -> Callable:
|
302
|
+
self, fn_or_list: Union[List[Callable[..., Any]], Callable[..., Any]]
|
303
|
+
) -> Callable[..., Any]:
|
264
304
|
if self.uselist:
|
265
305
|
|
266
|
-
def go(*arg, **kw):
|
306
|
+
def go(*arg: Any, **kw: Any) -> None:
|
307
|
+
if TYPE_CHECKING:
|
308
|
+
assert isinstance(fn_or_list, Sequence)
|
267
309
|
for fn in fn_or_list:
|
268
310
|
fn(*arg, **kw)
|
269
311
|
|
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:
|
@@ -92,11 +95,17 @@ def msg(
|
|
92
95
|
write_outstream(sys.stdout, "\n")
|
93
96
|
else:
|
94
97
|
# left indent output lines
|
95
|
-
|
98
|
+
indent = " "
|
99
|
+
lines = textwrap.wrap(
|
100
|
+
msg,
|
101
|
+
TERMWIDTH,
|
102
|
+
initial_indent=indent,
|
103
|
+
subsequent_indent=indent,
|
104
|
+
)
|
96
105
|
if len(lines) > 1:
|
97
106
|
for line in lines[0:-1]:
|
98
|
-
write_outstream(sys.stdout,
|
99
|
-
write_outstream(sys.stdout,
|
107
|
+
write_outstream(sys.stdout, line, "\n")
|
108
|
+
write_outstream(sys.stdout, lines[-1], ("\n" if newline else ""))
|
100
109
|
if flush:
|
101
110
|
sys.stdout.flush()
|
102
111
|
|
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)
|