alembic 1.14.1__py3-none-any.whl → 1.15.0__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 (42) hide show
  1. alembic/__init__.py +1 -1
  2. alembic/autogenerate/compare.py +11 -23
  3. alembic/autogenerate/render.py +25 -19
  4. alembic/command.py +3 -1
  5. alembic/context.pyi +5 -2
  6. alembic/ddl/base.py +2 -2
  7. alembic/ddl/impl.py +8 -9
  8. alembic/ddl/mysql.py +1 -2
  9. alembic/ddl/postgresql.py +5 -5
  10. alembic/ddl/sqlite.py +2 -1
  11. alembic/op.pyi +1 -2
  12. alembic/operations/base.py +1 -2
  13. alembic/operations/batch.py +5 -4
  14. alembic/operations/ops.py +1 -2
  15. alembic/operations/toimpl.py +0 -13
  16. alembic/runtime/environment.py +2 -2
  17. alembic/runtime/migration.py +4 -4
  18. alembic/testing/assertions.py +2 -3
  19. alembic/testing/env.py +62 -78
  20. alembic/testing/fixtures.py +3 -15
  21. alembic/testing/requirements.py +1 -35
  22. alembic/testing/suite/test_autogen_computed.py +2 -62
  23. alembic/testing/warnings.py +0 -9
  24. alembic/util/__init__.py +0 -7
  25. alembic/util/exc.py +20 -1
  26. alembic/util/messaging.py +1 -4
  27. alembic/util/sqla_compat.py +72 -238
  28. {alembic-1.14.1.dist-info → alembic-1.15.0.dist-info}/METADATA +7 -11
  29. {alembic-1.14.1.dist-info → alembic-1.15.0.dist-info}/RECORD +33 -42
  30. {alembic-1.14.1.dist-info → alembic-1.15.0.dist-info}/WHEEL +1 -1
  31. alembic/templates/async/README +0 -1
  32. alembic/templates/async/alembic.ini.mako +0 -117
  33. alembic/templates/async/script.py.mako +0 -26
  34. alembic/templates/generic/README +0 -1
  35. alembic/templates/generic/alembic.ini.mako +0 -119
  36. alembic/templates/generic/script.py.mako +0 -26
  37. alembic/templates/multidb/README +0 -12
  38. alembic/templates/multidb/alembic.ini.mako +0 -124
  39. alembic/templates/multidb/script.py.mako +0 -47
  40. {alembic-1.14.1.dist-info → alembic-1.15.0.dist-info}/LICENSE +0 -0
  41. {alembic-1.14.1.dist-info → alembic-1.15.0.dist-info}/entry_points.txt +0 -0
  42. {alembic-1.14.1.dist-info → alembic-1.15.0.dist-info}/top_level.txt +0 -0
alembic/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  from . import context
2
2
  from . import op
3
3
 
4
- __version__ = "1.14.1"
4
+ __version__ = "1.15.0"
@@ -216,7 +216,7 @@ def _compare_tables(
216
216
  (inspector),
217
217
  # fmt: on
218
218
  )
219
- sqla_compat._reflect_table(inspector, t)
219
+ inspector.reflect_table(t, include_columns=None)
220
220
  if autogen_context.run_object_filters(t, tname, "table", True, None):
221
221
  modify_table_ops = ops.ModifyTableOps(tname, [], schema=s)
222
222
 
@@ -246,7 +246,7 @@ def _compare_tables(
246
246
  _compat_autogen_column_reflect(inspector),
247
247
  # fmt: on
248
248
  )
249
- sqla_compat._reflect_table(inspector, t)
249
+ inspector.reflect_table(t, include_columns=None)
250
250
  conn_column_info[(s, tname)] = t
251
251
 
252
252
  for s, tname in sorted(existing_tables, key=lambda x: (x[0] or "", x[1])):
@@ -1067,27 +1067,15 @@ def _compare_server_default(
1067
1067
  return False
1068
1068
 
1069
1069
  if sqla_compat._server_default_is_computed(metadata_default):
1070
- # return False in case of a computed column as the server
1071
- # default. Note that DDL for adding or removing "GENERATED AS" from
1072
- # an existing column is not currently known for any backend.
1073
- # Once SQLAlchemy can reflect "GENERATED" as the "computed" element,
1074
- # we would also want to ignore and/or warn for changes vs. the
1075
- # metadata (or support backend specific DDL if applicable).
1076
- if not sqla_compat.has_computed_reflection:
1077
- return False
1078
-
1079
- else:
1080
- return (
1081
- _compare_computed_default( # type:ignore[func-returns-value]
1082
- autogen_context,
1083
- alter_column_op,
1084
- schema,
1085
- tname,
1086
- cname,
1087
- conn_col,
1088
- metadata_col,
1089
- )
1090
- )
1070
+ return _compare_computed_default( # type:ignore[func-returns-value]
1071
+ autogen_context,
1072
+ alter_column_op,
1073
+ schema,
1074
+ tname,
1075
+ cname,
1076
+ conn_col,
1077
+ metadata_col,
1078
+ )
1091
1079
  if sqla_compat._server_default_is_computed(conn_col_default):
1092
1080
  _warn_computed_not_supported(tname, cname)
1093
1081
  return False
@@ -19,6 +19,7 @@ from sqlalchemy import schema as sa_schema
19
19
  from sqlalchemy import sql
20
20
  from sqlalchemy import types as sqltypes
21
21
  from sqlalchemy.sql.elements import conv
22
+ from sqlalchemy.sql.elements import Label
22
23
  from sqlalchemy.sql.elements import quoted_name
23
24
 
24
25
  from .. import util
@@ -28,6 +29,8 @@ from ..util import sqla_compat
28
29
  if TYPE_CHECKING:
29
30
  from typing import Literal
30
31
 
32
+ from sqlalchemy import Computed
33
+ from sqlalchemy import Identity
31
34
  from sqlalchemy.sql.base import DialectKWArgs
32
35
  from sqlalchemy.sql.elements import ColumnElement
33
36
  from sqlalchemy.sql.elements import TextClause
@@ -48,8 +51,6 @@ if TYPE_CHECKING:
48
51
  from alembic.config import Config
49
52
  from alembic.operations.ops import MigrationScript
50
53
  from alembic.operations.ops import ModifyTableOps
51
- from alembic.util.sqla_compat import Computed
52
- from alembic.util.sqla_compat import Identity
53
54
 
54
55
 
55
56
  MAX_PYTHON_ARGS = 255
@@ -584,23 +585,28 @@ def _render_potential_expr(
584
585
  value: Any,
585
586
  autogen_context: AutogenContext,
586
587
  *,
587
- wrap_in_text: bool = True,
588
+ wrap_in_element: bool = True,
588
589
  is_server_default: bool = False,
589
590
  is_index: bool = False,
590
591
  ) -> str:
591
592
  if isinstance(value, sql.ClauseElement):
592
- if wrap_in_text:
593
- template = "%(prefix)stext(%(sql)r)"
593
+ sql_text = autogen_context.migration_context.impl.render_ddl_sql_expr(
594
+ value, is_server_default=is_server_default, is_index=is_index
595
+ )
596
+ if wrap_in_element:
597
+ prefix = _sqlalchemy_autogenerate_prefix(autogen_context)
598
+ element = "literal_column" if is_index else "text"
599
+ value_str = f"{prefix}{element}({sql_text!r})"
600
+ if (
601
+ is_index
602
+ and isinstance(value, Label)
603
+ and type(value.name) is str
604
+ ):
605
+ return value_str + f".label({value.name!r})"
606
+ else:
607
+ return value_str
594
608
  else:
595
- template = "%(sql)r"
596
-
597
- return template % {
598
- "prefix": _sqlalchemy_autogenerate_prefix(autogen_context),
599
- "sql": autogen_context.migration_context.impl.render_ddl_sql_expr(
600
- value, is_server_default=is_server_default, is_index=is_index
601
- ),
602
- }
603
-
609
+ return repr(sql_text)
604
610
  else:
605
611
  return repr(value)
606
612
 
@@ -628,9 +634,9 @@ def _uq_constraint(
628
634
  has_batch = autogen_context._has_batch
629
635
 
630
636
  if constraint.deferrable:
631
- opts.append(("deferrable", str(constraint.deferrable)))
637
+ opts.append(("deferrable", constraint.deferrable))
632
638
  if constraint.initially:
633
- opts.append(("initially", str(constraint.initially)))
639
+ opts.append(("initially", constraint.initially))
634
640
  if not has_batch and alter and constraint.table.schema:
635
641
  opts.append(("schema", _ident(constraint.table.schema)))
636
642
  if not alter and constraint.name:
@@ -741,7 +747,7 @@ def _render_column(
741
747
  + [
742
748
  "%s=%s"
743
749
  % (key, _render_potential_expr(val, autogen_context))
744
- for key, val in sqla_compat._column_kwargs(column).items()
750
+ for key, val in column.kwargs.items()
745
751
  ]
746
752
  )
747
753
  ),
@@ -787,7 +793,7 @@ def _render_computed(
787
793
  computed: Computed, autogen_context: AutogenContext
788
794
  ) -> str:
789
795
  text = _render_potential_expr(
790
- computed.sqltext, autogen_context, wrap_in_text=False
796
+ computed.sqltext, autogen_context, wrap_in_element=False
791
797
  )
792
798
 
793
799
  kwargs = {}
@@ -1101,7 +1107,7 @@ def _render_check_constraint(
1101
1107
  else ""
1102
1108
  ),
1103
1109
  "sqltext": _render_potential_expr(
1104
- constraint.sqltext, autogen_context, wrap_in_text=False
1110
+ constraint.sqltext, autogen_context, wrap_in_element=False
1105
1111
  ),
1106
1112
  }
1107
1113
 
alembic/command.py CHANGED
@@ -298,7 +298,9 @@ def check(config: "Config") -> None:
298
298
 
299
299
  if diffs:
300
300
  raise util.AutogenerateDiffsDetected(
301
- f"New upgrade operations detected: {diffs}"
301
+ f"New upgrade operations detected: {diffs}",
302
+ revision_context=revision_context,
303
+ diffs=diffs,
302
304
  )
303
305
  else:
304
306
  config.print_stdout("No new upgrade operations detected.")
alembic/context.pyi CHANGED
@@ -5,7 +5,6 @@ from __future__ import annotations
5
5
  from typing import Any
6
6
  from typing import Callable
7
7
  from typing import Collection
8
- from typing import ContextManager
9
8
  from typing import Dict
10
9
  from typing import Iterable
11
10
  from typing import List
@@ -20,6 +19,8 @@ from typing import Tuple
20
19
  from typing import TYPE_CHECKING
21
20
  from typing import Union
22
21
 
22
+ from typing_extensions import ContextManager
23
+
23
24
  if TYPE_CHECKING:
24
25
  from sqlalchemy.engine.base import Connection
25
26
  from sqlalchemy.engine.url import URL
@@ -40,7 +41,9 @@ if TYPE_CHECKING:
40
41
 
41
42
  ### end imports ###
42
43
 
43
- def begin_transaction() -> Union[_ProxyTransaction, ContextManager[None]]:
44
+ def begin_transaction() -> (
45
+ Union[_ProxyTransaction, ContextManager[None, Optional[bool]]]
46
+ ):
44
47
  """Return a context manager that will
45
48
  enclose an operation within a "transaction",
46
49
  as defined by the environment's offline
alembic/ddl/base.py CHANGED
@@ -25,6 +25,8 @@ from ..util.sqla_compat import _table_for_constraint # noqa
25
25
  if TYPE_CHECKING:
26
26
  from typing import Any
27
27
 
28
+ from sqlalchemy import Computed
29
+ from sqlalchemy import Identity
28
30
  from sqlalchemy.sql.compiler import Compiled
29
31
  from sqlalchemy.sql.compiler import DDLCompiler
30
32
  from sqlalchemy.sql.elements import TextClause
@@ -33,8 +35,6 @@ if TYPE_CHECKING:
33
35
  from sqlalchemy.sql.type_api import TypeEngine
34
36
 
35
37
  from .impl import DefaultImpl
36
- from ..util.sqla_compat import Computed
37
- from ..util.sqla_compat import Identity
38
38
 
39
39
  _ServerDefault = Union["TextClause", "FetchedValue", "Function[Any]", str]
40
40
 
alembic/ddl/impl.py CHANGED
@@ -459,7 +459,9 @@ class DefaultImpl(metaclass=ImplMeta):
459
459
  if self.as_sql:
460
460
  for row in rows:
461
461
  self._exec(
462
- sqla_compat._insert_inline(table).values(
462
+ table.insert()
463
+ .inline()
464
+ .values(
463
465
  **{
464
466
  k: (
465
467
  sqla_compat._literal_bindparam(
@@ -477,14 +479,10 @@ class DefaultImpl(metaclass=ImplMeta):
477
479
  else:
478
480
  if rows:
479
481
  if multiinsert:
480
- self._exec(
481
- sqla_compat._insert_inline(table), multiparams=rows
482
- )
482
+ self._exec(table.insert().inline(), multiparams=rows)
483
483
  else:
484
484
  for row in rows:
485
- self._exec(
486
- sqla_compat._insert_inline(table).values(**row)
487
- )
485
+ self._exec(table.insert().inline().values(**row))
488
486
 
489
487
  def _tokenize_column_type(self, column: Column) -> Params:
490
488
  definition: str
@@ -693,7 +691,7 @@ class DefaultImpl(metaclass=ImplMeta):
693
691
  diff, ignored = _compare_identity_options(
694
692
  metadata_identity,
695
693
  inspector_identity,
696
- sqla_compat.Identity(),
694
+ schema.Identity(),
697
695
  skip={"always"},
698
696
  )
699
697
 
@@ -874,12 +872,13 @@ def _compare_identity_options(
874
872
  set(meta_d).union(insp_d),
875
873
  )
876
874
  if sqla_compat.identity_has_dialect_kwargs:
875
+ assert hasattr(default_io, "dialect_kwargs")
877
876
  # use only the dialect kwargs in inspector_io since metadata_io
878
877
  # can have options for many backends
879
878
  check_dicts(
880
879
  getattr(metadata_io, "dialect_kwargs", {}),
881
880
  getattr(inspector_io, "dialect_kwargs", {}),
882
- default_io.dialect_kwargs, # type: ignore[union-attr]
881
+ default_io.dialect_kwargs,
883
882
  getattr(inspector_io, "dialect_kwargs", {}),
884
883
  )
885
884
 
alembic/ddl/mysql.py CHANGED
@@ -23,7 +23,6 @@ from .base import format_server_default
23
23
  from .impl import DefaultImpl
24
24
  from .. import util
25
25
  from ..util import sqla_compat
26
- from ..util.sqla_compat import _is_mariadb
27
26
  from ..util.sqla_compat import _is_type_bound
28
27
  from ..util.sqla_compat import compiles
29
28
 
@@ -475,7 +474,7 @@ def _mysql_drop_constraint(
475
474
  # note that SQLAlchemy as of 1.2 does not yet support
476
475
  # DROP CONSTRAINT for MySQL/MariaDB, so we implement fully
477
476
  # here.
478
- if _is_mariadb(compiler.dialect):
477
+ if compiler.dialect.is_mariadb: # type: ignore[attr-defined]
479
478
  return "ALTER TABLE %s DROP CONSTRAINT %s" % (
480
479
  compiler.preparer.format_table(constraint.table),
481
480
  compiler.preparer.format_constraint(constraint),
alembic/ddl/postgresql.py CHANGED
@@ -17,8 +17,10 @@ from typing import Union
17
17
 
18
18
  from sqlalchemy import Column
19
19
  from sqlalchemy import Float
20
+ from sqlalchemy import Identity
20
21
  from sqlalchemy import literal_column
21
22
  from sqlalchemy import Numeric
23
+ from sqlalchemy import select
22
24
  from sqlalchemy import text
23
25
  from sqlalchemy import types as sqltypes
24
26
  from sqlalchemy.dialects.postgresql import BIGINT
@@ -143,9 +145,7 @@ class PostgresqlImpl(DefaultImpl):
143
145
  conn = self.connection
144
146
  assert conn is not None
145
147
  return not conn.scalar(
146
- sqla_compat._select(
147
- literal_column(conn_col_default) == metadata_default
148
- )
148
+ select(literal_column(conn_col_default) == metadata_default)
149
149
  )
150
150
 
151
151
  def alter_column( # type:ignore[override]
@@ -586,7 +586,7 @@ def visit_identity_column(
586
586
  )
587
587
  else:
588
588
  text += "SET %s " % compiler.get_identity_options(
589
- sqla_compat.Identity(**{attr: getattr(identity, attr)})
589
+ Identity(**{attr: getattr(identity, attr)})
590
590
  )
591
591
  return text
592
592
 
@@ -846,5 +846,5 @@ def _render_potential_column(
846
846
  return render._render_potential_expr(
847
847
  value,
848
848
  autogen_context,
849
- wrap_in_text=isinstance(value, (TextClause, FunctionElement)),
849
+ wrap_in_element=isinstance(value, (TextClause, FunctionElement)),
850
850
  )
alembic/ddl/sqlite.py CHANGED
@@ -11,6 +11,7 @@ from typing import TYPE_CHECKING
11
11
  from typing import Union
12
12
 
13
13
  from sqlalchemy import cast
14
+ from sqlalchemy import Computed
14
15
  from sqlalchemy import JSON
15
16
  from sqlalchemy import schema
16
17
  from sqlalchemy import sql
@@ -64,7 +65,7 @@ class SQLiteImpl(DefaultImpl):
64
65
  ) and isinstance(col.server_default.arg, sql.ClauseElement):
65
66
  return True
66
67
  elif (
67
- isinstance(col.server_default, util.sqla_compat.Computed)
68
+ isinstance(col.server_default, Computed)
68
69
  and col.server_default.persisted
69
70
  ):
70
71
  return True
alembic/op.pyi CHANGED
@@ -27,7 +27,6 @@ if TYPE_CHECKING:
27
27
  from sqlalchemy.sql.elements import conv
28
28
  from sqlalchemy.sql.elements import TextClause
29
29
  from sqlalchemy.sql.expression import TableClause
30
- from sqlalchemy.sql.functions import Function
31
30
  from sqlalchemy.sql.schema import Column
32
31
  from sqlalchemy.sql.schema import Computed
33
32
  from sqlalchemy.sql.schema import Identity
@@ -650,7 +649,7 @@ def create_foreign_key(
650
649
  def create_index(
651
650
  index_name: Optional[str],
652
651
  table_name: str,
653
- columns: Sequence[Union[str, TextClause, Function[Any]]],
652
+ columns: Sequence[Union[str, TextClause, ColumnElement[Any]]],
654
653
  *,
655
654
  schema: Optional[str] = None,
656
655
  unique: bool = False,
@@ -43,7 +43,6 @@ if TYPE_CHECKING:
43
43
  from sqlalchemy.sql.expression import ColumnElement
44
44
  from sqlalchemy.sql.expression import TableClause
45
45
  from sqlalchemy.sql.expression import TextClause
46
- from sqlalchemy.sql.functions import Function
47
46
  from sqlalchemy.sql.schema import Column
48
47
  from sqlalchemy.sql.schema import Computed
49
48
  from sqlalchemy.sql.schema import Identity
@@ -1074,7 +1073,7 @@ class Operations(AbstractOperations):
1074
1073
  self,
1075
1074
  index_name: Optional[str],
1076
1075
  table_name: str,
1077
- columns: Sequence[Union[str, TextClause, Function[Any]]],
1076
+ columns: Sequence[Union[str, TextClause, ColumnElement[Any]]],
1078
1077
  *,
1079
1078
  schema: Optional[str] = None,
1080
1079
  unique: bool = False,
@@ -18,6 +18,7 @@ from sqlalchemy import Index
18
18
  from sqlalchemy import MetaData
19
19
  from sqlalchemy import PrimaryKeyConstraint
20
20
  from sqlalchemy import schema as sql_schema
21
+ from sqlalchemy import select
21
22
  from sqlalchemy import Table
22
23
  from sqlalchemy import types as sqltypes
23
24
  from sqlalchemy.sql.schema import SchemaEventTarget
@@ -31,11 +32,9 @@ from ..util.sqla_compat import _copy_expression
31
32
  from ..util.sqla_compat import _ensure_scope_for_ddl
32
33
  from ..util.sqla_compat import _fk_is_self_referential
33
34
  from ..util.sqla_compat import _idx_table_bound_expressions
34
- from ..util.sqla_compat import _insert_inline
35
35
  from ..util.sqla_compat import _is_type_bound
36
36
  from ..util.sqla_compat import _remove_column_from_collection
37
37
  from ..util.sqla_compat import _resolve_for_variant
38
- from ..util.sqla_compat import _select
39
38
  from ..util.sqla_compat import constraint_name_defined
40
39
  from ..util.sqla_compat import constraint_name_string
41
40
 
@@ -449,13 +448,15 @@ class ApplyBatchImpl:
449
448
 
450
449
  try:
451
450
  op_impl._exec(
452
- _insert_inline(self.new_table).from_select(
451
+ self.new_table.insert()
452
+ .inline()
453
+ .from_select(
453
454
  list(
454
455
  k
455
456
  for k, transfer in self.column_transfers.items()
456
457
  if "expr" in transfer
457
458
  ),
458
- _select(
459
+ select(
459
460
  *[
460
461
  transfer["expr"]
461
462
  for transfer in self.column_transfers.values()
alembic/operations/ops.py CHANGED
@@ -35,7 +35,6 @@ if TYPE_CHECKING:
35
35
  from sqlalchemy.sql.elements import conv
36
36
  from sqlalchemy.sql.elements import quoted_name
37
37
  from sqlalchemy.sql.elements import TextClause
38
- from sqlalchemy.sql.functions import Function
39
38
  from sqlalchemy.sql.schema import CheckConstraint
40
39
  from sqlalchemy.sql.schema import Column
41
40
  from sqlalchemy.sql.schema import Computed
@@ -933,7 +932,7 @@ class CreateIndexOp(MigrateOperation):
933
932
  operations: Operations,
934
933
  index_name: Optional[str],
935
934
  table_name: str,
936
- columns: Sequence[Union[str, TextClause, Function[Any]]],
935
+ columns: Sequence[Union[str, TextClause, ColumnElement[Any]]],
937
936
  *,
938
937
  schema: Optional[str] = None,
939
938
  unique: bool = False,
@@ -8,7 +8,6 @@ from sqlalchemy import schema as sa_schema
8
8
  from . import ops
9
9
  from .base import Operations
10
10
  from ..util.sqla_compat import _copy
11
- from ..util.sqla_compat import sqla_14
12
11
 
13
12
  if TYPE_CHECKING:
14
13
  from sqlalchemy.sql.schema import Table
@@ -81,9 +80,6 @@ def alter_column(
81
80
  def drop_table(operations: "Operations", operation: "ops.DropTableOp") -> None:
82
81
  kw = {}
83
82
  if operation.if_exists is not None:
84
- if not sqla_14:
85
- raise NotImplementedError("SQLAlchemy 1.4+ required")
86
-
87
83
  kw["if_exists"] = operation.if_exists
88
84
  operations.impl.drop_table(
89
85
  operation.to_table(operations.migration_context), **kw
@@ -107,9 +103,6 @@ def create_index(
107
103
  idx = operation.to_index(operations.migration_context)
108
104
  kw = {}
109
105
  if operation.if_not_exists is not None:
110
- if not sqla_14:
111
- raise NotImplementedError("SQLAlchemy 1.4+ required")
112
-
113
106
  kw["if_not_exists"] = operation.if_not_exists
114
107
  operations.impl.create_index(idx, **kw)
115
108
 
@@ -118,9 +111,6 @@ def create_index(
118
111
  def drop_index(operations: "Operations", operation: "ops.DropIndexOp") -> None:
119
112
  kw = {}
120
113
  if operation.if_exists is not None:
121
- if not sqla_14:
122
- raise NotImplementedError("SQLAlchemy 1.4+ required")
123
-
124
114
  kw["if_exists"] = operation.if_exists
125
115
 
126
116
  operations.impl.drop_index(
@@ -135,9 +125,6 @@ def create_table(
135
125
  ) -> "Table":
136
126
  kw = {}
137
127
  if operation.if_not_exists is not None:
138
- if not sqla_14:
139
- raise NotImplementedError("SQLAlchemy 1.4+ required")
140
-
141
128
  kw["if_not_exists"] = operation.if_not_exists
142
129
  table = operation.to_table(operations.migration_context)
143
130
  operations.impl.create_table(table, **kw)
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  from typing import Any
4
4
  from typing import Callable
5
5
  from typing import Collection
6
- from typing import ContextManager
7
6
  from typing import Dict
8
7
  from typing import List
9
8
  from typing import Mapping
@@ -18,6 +17,7 @@ from typing import Union
18
17
 
19
18
  from sqlalchemy.sql.schema import Column
20
19
  from sqlalchemy.sql.schema import FetchedValue
20
+ from typing_extensions import ContextManager
21
21
  from typing_extensions import Literal
22
22
 
23
23
  from .migration import _ProxyTransaction
@@ -976,7 +976,7 @@ class EnvironmentContext(util.ModuleClsProxy):
976
976
 
977
977
  def begin_transaction(
978
978
  self,
979
- ) -> Union[_ProxyTransaction, ContextManager[None]]:
979
+ ) -> Union[_ProxyTransaction, ContextManager[None, Optional[bool]]]:
980
980
  """Return a context manager that will
981
981
  enclose an operation within a "transaction",
982
982
  as defined by the environment's offline
@@ -11,7 +11,6 @@ from typing import Any
11
11
  from typing import Callable
12
12
  from typing import cast
13
13
  from typing import Collection
14
- from typing import ContextManager
15
14
  from typing import Dict
16
15
  from typing import Iterable
17
16
  from typing import Iterator
@@ -24,15 +23,16 @@ from typing import Union
24
23
 
25
24
  from sqlalchemy import Column
26
25
  from sqlalchemy import literal_column
26
+ from sqlalchemy import select
27
27
  from sqlalchemy.engine import Engine
28
28
  from sqlalchemy.engine import url as sqla_url
29
29
  from sqlalchemy.engine.strategies import MockEngineStrategy
30
+ from typing_extensions import ContextManager
30
31
 
31
32
  from .. import ddl
32
33
  from .. import util
33
34
  from ..util import sqla_compat
34
35
  from ..util.compat import EncodedIO
35
- from ..util.sqla_compat import _select
36
36
 
37
37
  if TYPE_CHECKING:
38
38
  from sqlalchemy.engine import Dialect
@@ -368,7 +368,7 @@ class MigrationContext:
368
368
 
369
369
  def begin_transaction(
370
370
  self, _per_migration: bool = False
371
- ) -> Union[_ProxyTransaction, ContextManager[None]]:
371
+ ) -> Union[_ProxyTransaction, ContextManager[None, Optional[bool]]]:
372
372
  """Begin a logical transaction for migration operations.
373
373
 
374
374
  This method is used within an ``env.py`` script to demarcate where
@@ -534,7 +534,7 @@ class MigrationContext:
534
534
  return tuple(
535
535
  row[0]
536
536
  for row in self.connection.execute(
537
- _select(self._version.c.version_num)
537
+ select(self._version.c.version_num)
538
538
  )
539
539
  )
540
540
 
@@ -8,6 +8,7 @@ from typing import Dict
8
8
 
9
9
  from sqlalchemy import exc as sa_exc
10
10
  from sqlalchemy.engine import default
11
+ from sqlalchemy.engine import URL
11
12
  from sqlalchemy.testing.assertions import _expect_warnings
12
13
  from sqlalchemy.testing.assertions import eq_ # noqa
13
14
  from sqlalchemy.testing.assertions import is_ # noqa
@@ -17,8 +18,6 @@ from sqlalchemy.testing.assertions import is_true # noqa
17
18
  from sqlalchemy.testing.assertions import ne_ # noqa
18
19
  from sqlalchemy.util import decorator
19
20
 
20
- from ..util import sqla_compat
21
-
22
21
 
23
22
  def _assert_proper_exception_context(exception):
24
23
  """assert that any exception we're catching does not have a __context__
@@ -127,7 +126,7 @@ def _get_dialect(name):
127
126
  if name is None or name == "default":
128
127
  return default.DefaultDialect()
129
128
  else:
130
- d = sqla_compat._create_url(name).get_dialect()()
129
+ d = URL.create(name).get_dialect()()
131
130
 
132
131
  if name == "postgresql":
133
132
  d.implicit_returning = True