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.
Files changed (48) hide show
  1. alembic/__init__.py +1 -1
  2. alembic/autogenerate/__init__.py +10 -10
  3. alembic/autogenerate/api.py +9 -7
  4. alembic/autogenerate/compare.py +6 -5
  5. alembic/autogenerate/render.py +34 -24
  6. alembic/autogenerate/rewriter.py +26 -13
  7. alembic/command.py +27 -16
  8. alembic/config.py +25 -19
  9. alembic/context.pyi +10 -5
  10. alembic/ddl/__init__.py +1 -1
  11. alembic/ddl/_autogen.py +19 -13
  12. alembic/ddl/base.py +17 -13
  13. alembic/ddl/impl.py +27 -19
  14. alembic/ddl/mssql.py +4 -1
  15. alembic/ddl/mysql.py +54 -34
  16. alembic/ddl/oracle.py +9 -4
  17. alembic/ddl/postgresql.py +18 -10
  18. alembic/ddl/sqlite.py +8 -6
  19. alembic/op.pyi +46 -8
  20. alembic/operations/base.py +69 -16
  21. alembic/operations/batch.py +7 -8
  22. alembic/operations/ops.py +57 -35
  23. alembic/operations/schemaobj.py +11 -8
  24. alembic/operations/toimpl.py +3 -0
  25. alembic/runtime/environment.py +20 -13
  26. alembic/runtime/migration.py +34 -18
  27. alembic/script/base.py +24 -24
  28. alembic/script/revision.py +53 -33
  29. alembic/script/write_hooks.py +3 -0
  30. alembic/templates/async/alembic.ini.mako +3 -3
  31. alembic/templates/generic/alembic.ini.mako +2 -2
  32. alembic/templates/multidb/alembic.ini.mako +2 -2
  33. alembic/testing/fixtures.py +20 -8
  34. alembic/testing/suite/test_autogen_computed.py +1 -0
  35. alembic/testing/suite/test_environment.py +3 -3
  36. alembic/util/__init__.py +31 -31
  37. alembic/util/compat.py +25 -8
  38. alembic/util/langhelpers.py +78 -36
  39. alembic/util/messaging.py +15 -6
  40. alembic/util/pyfiles.py +7 -3
  41. alembic/util/sqla_compat.py +41 -14
  42. {alembic-1.13.0.dist-info → alembic-1.13.2.dist-info}/LICENSE +2 -2
  43. {alembic-1.13.0.dist-info → alembic-1.13.2.dist-info}/METADATA +1 -1
  44. alembic-1.13.2.dist-info/RECORD +83 -0
  45. {alembic-1.13.0.dist-info → alembic-1.13.2.dist-info}/WHEEL +1 -1
  46. alembic-1.13.0.dist-info/RECORD +0 -83
  47. {alembic-1.13.0.dist-info → alembic-1.13.2.dist-info}/entry_points.txt +0 -0
  48. {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
@@ -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=column.server_default
272
- if column.server_default is not None
273
- else False,
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
- compare["server_default"].text
302
- if "server_default" in compare
303
- else column.server_default.arg.text
304
- if column.server_default is not None
305
- else None,
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
- self.context.impl.output_buffer
29
- ) = io.StringIO()
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
- from sqlalchemy.util import inspect_getfullargspec # noqa
12
- from sqlalchemy.util.compat import inspect_formatargspec # noqa
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 importlib_resources
31
- from importlib import metadata as importlib_metadata
32
- from importlib.metadata import EntryPoint
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) # type: ignore
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(annotation, base_module=None):
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
- ) -> list[str]:
85
+ ) -> List[str]:
69
86
  if py310:
70
87
  return file_config.read(file_argument, encoding="locale")
71
88
  else:
@@ -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 memoized_property # noqa
23
- from sqlalchemy.util import to_list # noqa
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[type, Tuple[set, list]] = collections.defaultdict(
49
- lambda: (set(), [])
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(cls, globals_, locals_):
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(cls, globals_, locals_, attr_names):
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(cls, methname, globals_, locals_, attr_names):
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(cls, name, globals_, locals_):
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(fn_name, spec, translations, args, kw):
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: tuple) -> tuple:
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] = None) -> _T:
204
- ...
241
+ def to_tuple(x: None, default: Optional[_T] = ...) -> _T: ...
205
242
 
206
243
 
207
244
  @overload
208
- def to_tuple(x: Any, default: Optional[tuple] = None) -> 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(x, default=None):
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[tuple, Any] = {}
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(status_msg: str, newline: bool = False, quiet: bool = False):
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
- lines = textwrap.wrap(msg, TERMWIDTH)
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, " ", line, "\n")
99
- write_outstream(sys.stdout, " ", lines[-1], ("\n" if newline else ""))
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)