alembic 1.11.1__py3-none-any.whl → 1.11.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 (37) hide show
  1. alembic/__init__.py +1 -1
  2. alembic/autogenerate/api.py +0 -2
  3. alembic/autogenerate/compare.py +12 -23
  4. alembic/autogenerate/render.py +18 -36
  5. alembic/command.py +0 -1
  6. alembic/config.py +0 -2
  7. alembic/ddl/impl.py +10 -5
  8. alembic/ddl/mssql.py +2 -5
  9. alembic/ddl/mysql.py +0 -1
  10. alembic/ddl/postgresql.py +31 -10
  11. alembic/ddl/sqlite.py +0 -2
  12. alembic/op.pyi +29 -17
  13. alembic/operations/base.py +29 -17
  14. alembic/operations/batch.py +4 -5
  15. alembic/operations/ops.py +49 -24
  16. alembic/operations/toimpl.py +18 -4
  17. alembic/runtime/environment.py +0 -1
  18. alembic/runtime/migration.py +0 -4
  19. alembic/script/base.py +3 -7
  20. alembic/script/revision.py +0 -4
  21. alembic/script/write_hooks.py +8 -7
  22. alembic/templates/async/script.py.mako +6 -4
  23. alembic/templates/generic/script.py.mako +6 -4
  24. alembic/templates/multidb/script.py.mako +6 -4
  25. alembic/testing/assertions.py +0 -3
  26. alembic/testing/env.py +0 -3
  27. alembic/testing/fixtures.py +0 -2
  28. alembic/testing/suite/_autogen_fixtures.py +0 -1
  29. alembic/util/langhelpers.py +0 -1
  30. alembic/util/pyfiles.py +0 -1
  31. alembic/util/sqla_compat.py +0 -1
  32. {alembic-1.11.1.dist-info → alembic-1.11.2.dist-info}/METADATA +1 -1
  33. {alembic-1.11.1.dist-info → alembic-1.11.2.dist-info}/RECORD +37 -37
  34. {alembic-1.11.1.dist-info → alembic-1.11.2.dist-info}/WHEEL +1 -1
  35. {alembic-1.11.1.dist-info → alembic-1.11.2.dist-info}/LICENSE +0 -0
  36. {alembic-1.11.1.dist-info → alembic-1.11.2.dist-info}/entry_points.txt +0 -0
  37. {alembic-1.11.1.dist-info → alembic-1.11.2.dist-info}/top_level.txt +0 -0
alembic/__init__.py CHANGED
@@ -3,4 +3,4 @@ import sys
3
3
  from . import context
4
4
  from . import op
5
5
 
6
- __version__ = "1.11.1"
6
+ __version__ = "1.11.2"
@@ -331,7 +331,6 @@ class AutogenContext:
331
331
  opts: Optional[dict] = None,
332
332
  autogenerate: bool = True,
333
333
  ) -> None:
334
-
335
334
  if (
336
335
  autogenerate
337
336
  and migration_context is not None
@@ -431,7 +430,6 @@ class AutogenContext:
431
430
  parent_names["schema_qualified_table_name"] = table_name
432
431
 
433
432
  for fn in self._name_filters:
434
-
435
433
  if not fn(name, type_, parent_names):
436
434
  return False
437
435
  else:
@@ -66,7 +66,6 @@ comparators = util.Dispatcher(uselist=True)
66
66
  def _produce_net_changes(
67
67
  autogen_context: AutogenContext, upgrade_ops: UpgradeOps
68
68
  ) -> None:
69
-
70
69
  connection = autogen_context.connection
71
70
  assert connection is not None
72
71
  include_schemas = autogen_context.opts.get("include_schemas", False)
@@ -145,7 +144,6 @@ def _compare_tables(
145
144
  upgrade_ops: UpgradeOps,
146
145
  autogen_context: AutogenContext,
147
146
  ) -> None:
148
-
149
147
  default_schema = inspector.bind.dialect.default_schema_name
150
148
 
151
149
  # tables coming from the connection will not have "schema"
@@ -214,7 +212,6 @@ def _compare_tables(
214
212
  )
215
213
  sqla_compat._reflect_table(inspector, t)
216
214
  if autogen_context.run_object_filters(t, tname, "table", True, None):
217
-
218
215
  modify_table_ops = ops.ModifyTableOps(tname, [], schema=s)
219
216
 
220
217
  comparators.dispatch("table")(
@@ -255,7 +252,6 @@ def _compare_tables(
255
252
  if autogen_context.run_object_filters(
256
253
  metadata_table, tname, "table", False, conn_table
257
254
  ):
258
-
259
255
  modify_table_ops = ops.ModifyTableOps(tname, [], schema=s)
260
256
  with _compare_columns(
261
257
  s,
@@ -266,7 +262,6 @@ def _compare_tables(
266
262
  autogen_context,
267
263
  inspector,
268
264
  ):
269
-
270
265
  comparators.dispatch("table")(
271
266
  autogen_context,
272
267
  modify_table_ops,
@@ -449,11 +444,11 @@ class _uq_constraint_sig(_constraint_sig):
449
444
  is_index = False
450
445
  is_unique = True
451
446
 
452
- def __init__(self, const: UniqueConstraint) -> None:
447
+ def __init__(self, const: UniqueConstraint, impl: DefaultImpl) -> None:
453
448
  self.const = const
454
449
  self.name = const.name
455
- self.sig = ("UNIQUE_CONSTRAINT",) + tuple(
456
- sorted([col.name for col in const.columns])
450
+ self.sig = ("UNIQUE_CONSTRAINT",) + impl.create_unique_constraint_sig(
451
+ const
457
452
  )
458
453
 
459
454
  @property
@@ -534,7 +529,6 @@ def _compare_indexes_and_uniques(
534
529
  conn_table: Optional[Table],
535
530
  metadata_table: Optional[Table],
536
531
  ) -> None:
537
-
538
532
  inspector = autogen_context.inspector
539
533
  is_create_table = conn_table is None
540
534
  is_drop_table = metadata_table is None
@@ -622,6 +616,7 @@ def _compare_indexes_and_uniques(
622
616
  # 2a. if the dialect dupes unique indexes as unique constraints
623
617
  # (mysql and oracle), correct for that
624
618
 
619
+ impl = autogen_context.migration_context.impl
625
620
  if unique_constraints_duplicate_unique_indexes:
626
621
  _correct_for_uq_duplicates_uix(
627
622
  conn_uniques,
@@ -629,6 +624,7 @@ def _compare_indexes_and_uniques(
629
624
  metadata_unique_constraints,
630
625
  metadata_indexes,
631
626
  autogen_context.dialect,
627
+ impl,
632
628
  )
633
629
 
634
630
  # 3. give the dialect a chance to omit indexes and constraints that
@@ -646,15 +642,16 @@ def _compare_indexes_and_uniques(
646
642
  # Index and UniqueConstraint so we can easily work with them
647
643
  # interchangeably
648
644
  metadata_unique_constraints_sig = {
649
- _uq_constraint_sig(uq) for uq in metadata_unique_constraints
645
+ _uq_constraint_sig(uq, impl) for uq in metadata_unique_constraints
650
646
  }
651
647
 
652
- impl = autogen_context.migration_context.impl
653
648
  metadata_indexes_sig = {
654
649
  _ix_constraint_sig(ix, impl) for ix in metadata_indexes
655
650
  }
656
651
 
657
- conn_unique_constraints = {_uq_constraint_sig(uq) for uq in conn_uniques}
652
+ conn_unique_constraints = {
653
+ _uq_constraint_sig(uq, impl) for uq in conn_uniques
654
+ }
658
655
 
659
656
  conn_indexes_sig = {_ix_constraint_sig(ix, impl) for ix in conn_indexes}
660
657
 
@@ -864,6 +861,7 @@ def _correct_for_uq_duplicates_uix(
864
861
  metadata_unique_constraints,
865
862
  metadata_indexes,
866
863
  dialect,
864
+ impl,
867
865
  ):
868
866
  # dedupe unique indexes vs. constraints, since MySQL / Oracle
869
867
  # doesn't really have unique constraints as a separate construct.
@@ -886,7 +884,7 @@ def _correct_for_uq_duplicates_uix(
886
884
  }
887
885
 
888
886
  unnamed_metadata_uqs = {
889
- _uq_constraint_sig(cons).sig
887
+ _uq_constraint_sig(cons, impl).sig
890
888
  for name, cons in metadata_cons_names
891
889
  if name is None
892
890
  }
@@ -910,10 +908,9 @@ def _correct_for_uq_duplicates_uix(
910
908
  for overlap in uqs_dupe_indexes:
911
909
  if overlap not in metadata_uq_names:
912
910
  if (
913
- _uq_constraint_sig(uqs_dupe_indexes[overlap]).sig
911
+ _uq_constraint_sig(uqs_dupe_indexes[overlap], impl).sig
914
912
  not in unnamed_metadata_uqs
915
913
  ):
916
-
917
914
  conn_unique_constraints.discard(uqs_dupe_indexes[overlap])
918
915
  elif overlap not in metadata_ix_names:
919
916
  conn_indexes.discard(conn_ix_names[overlap])
@@ -929,7 +926,6 @@ def _compare_nullable(
929
926
  conn_col: Column[Any],
930
927
  metadata_col: Column[Any],
931
928
  ) -> None:
932
-
933
929
  metadata_col_nullable = metadata_col.nullable
934
930
  conn_col_nullable = conn_col.nullable
935
931
  alter_column_op.existing_nullable = conn_col_nullable
@@ -971,7 +967,6 @@ def _setup_autoincrement(
971
967
  conn_col: Column[Any],
972
968
  metadata_col: Column[Any],
973
969
  ) -> None:
974
-
975
970
  if metadata_col.table._autoincrement_column is metadata_col:
976
971
  alter_column_op.kw["autoincrement"] = True
977
972
  elif metadata_col.autoincrement is True:
@@ -990,7 +985,6 @@ def _compare_type(
990
985
  conn_col: Column[Any],
991
986
  metadata_col: Column[Any],
992
987
  ) -> None:
993
-
994
988
  conn_type = conn_col.type
995
989
  alter_column_op.existing_type = conn_type
996
990
  metadata_type = metadata_col.type
@@ -1027,7 +1021,6 @@ def _compare_type(
1027
1021
  def _render_server_default_for_compare(
1028
1022
  metadata_default: Optional[Any], autogen_context: AutogenContext
1029
1023
  ) -> Optional[str]:
1030
-
1031
1024
  if isinstance(metadata_default, sa_schema.DefaultClause):
1032
1025
  if isinstance(metadata_default.arg, str):
1033
1026
  metadata_default = metadata_default.arg
@@ -1129,7 +1122,6 @@ def _compare_server_default(
1129
1122
  conn_col: Column[Any],
1130
1123
  metadata_col: Column[Any],
1131
1124
  ) -> Optional[bool]:
1132
-
1133
1125
  metadata_default = metadata_col.server_default
1134
1126
  conn_col_default = conn_col.server_default
1135
1127
  if conn_col_default is None and metadata_default is None:
@@ -1218,7 +1210,6 @@ def _compare_column_comment(
1218
1210
  conn_col: Column[Any],
1219
1211
  metadata_col: Column[Any],
1220
1212
  ) -> Optional[Literal[False]]:
1221
-
1222
1213
  assert autogen_context.dialect is not None
1223
1214
  if not autogen_context.dialect.supports_comments:
1224
1215
  return None
@@ -1246,7 +1237,6 @@ def _compare_foreign_keys(
1246
1237
  conn_table: Optional[Table],
1247
1238
  metadata_table: Optional[Table],
1248
1239
  ) -> None:
1249
-
1250
1240
  # if we're doing CREATE TABLE, all FKs are created
1251
1241
  # inline within the table def
1252
1242
  if conn_table is None or metadata_table is None:
@@ -1366,7 +1356,6 @@ def _compare_table_comment(
1366
1356
  conn_table: Optional[Table],
1367
1357
  metadata_table: Optional[Table],
1368
1358
  ) -> None:
1369
-
1370
1359
  assert autogen_context.dialect is not None
1371
1360
  if not autogen_context.dialect.supports_comments:
1372
1361
  return
@@ -26,6 +26,7 @@ from ..util import sqla_compat
26
26
  if TYPE_CHECKING:
27
27
  from typing import Literal
28
28
 
29
+ from sqlalchemy.sql.base import DialectKWArgs
29
30
  from sqlalchemy.sql.elements import ColumnElement
30
31
  from sqlalchemy.sql.elements import TextClause
31
32
  from sqlalchemy.sql.schema import CheckConstraint
@@ -94,7 +95,6 @@ def _render_cmd_body(
94
95
  op_container: ops.OpContainer,
95
96
  autogen_context: AutogenContext,
96
97
  ) -> str:
97
-
98
98
  buf = StringIO()
99
99
  printer = PythonPrinter(buf)
100
100
 
@@ -165,7 +165,6 @@ def _render_modify_table(
165
165
  def _render_create_table_comment(
166
166
  autogen_context: AutogenContext, op: ops.CreateTableCommentOp
167
167
  ) -> str:
168
-
169
168
  templ = (
170
169
  "{prefix}create_table_comment(\n"
171
170
  "{indent}'{tname}',\n"
@@ -190,7 +189,6 @@ def _render_create_table_comment(
190
189
  def _render_drop_table_comment(
191
190
  autogen_context: AutogenContext, op: ops.DropTableCommentOp
192
191
  ) -> str:
193
-
194
192
  templ = (
195
193
  "{prefix}drop_table_comment(\n"
196
194
  "{indent}'{tname}',\n"
@@ -271,6 +269,15 @@ def _drop_table(autogen_context: AutogenContext, op: ops.DropTableOp) -> str:
271
269
  return text
272
270
 
273
271
 
272
+ def _render_dialect_kwargs_items(
273
+ autogen_context: AutogenContext, item: DialectKWArgs
274
+ ) -> list[str]:
275
+ return [
276
+ f"{key}={_render_potential_expr(val, autogen_context)}"
277
+ for key, val in item.dialect_kwargs.items()
278
+ ]
279
+
280
+
274
281
  @renderers.dispatch_for(ops.CreateIndexOp)
275
282
  def _add_index(autogen_context: AutogenContext, op: ops.CreateIndexOp) -> str:
276
283
  index = op.to_index()
@@ -289,6 +296,8 @@ def _add_index(autogen_context: AutogenContext, op: ops.CreateIndexOp) -> str:
289
296
  )
290
297
 
291
298
  assert index.table is not None
299
+
300
+ opts = _render_dialect_kwargs_items(autogen_context, index)
292
301
  text = tmpl % {
293
302
  "prefix": _alembic_autogenerate_prefix(autogen_context),
294
303
  "name": _render_gen_name(autogen_context, index.name),
@@ -300,18 +309,7 @@ def _add_index(autogen_context: AutogenContext, op: ops.CreateIndexOp) -> str:
300
309
  "schema": (", schema=%r" % _ident(index.table.schema))
301
310
  if index.table.schema
302
311
  else "",
303
- "kwargs": (
304
- ", "
305
- + ", ".join(
306
- [
307
- "%s=%s"
308
- % (key, _render_potential_expr(val, autogen_context))
309
- for key, val in index.kwargs.items()
310
- ]
311
- )
312
- )
313
- if len(index.kwargs)
314
- else "",
312
+ "kwargs": ", " + ", ".join(opts) if opts else "",
315
313
  }
316
314
  return text
317
315
 
@@ -329,24 +327,13 @@ def _drop_index(autogen_context: AutogenContext, op: ops.DropIndexOp) -> str:
329
327
  "%(prefix)sdrop_index(%(name)r, "
330
328
  "table_name=%(table_name)r%(schema)s%(kwargs)s)"
331
329
  )
332
-
330
+ opts = _render_dialect_kwargs_items(autogen_context, index)
333
331
  text = tmpl % {
334
332
  "prefix": _alembic_autogenerate_prefix(autogen_context),
335
333
  "name": _render_gen_name(autogen_context, op.index_name),
336
334
  "table_name": _ident(op.table_name),
337
335
  "schema": ((", schema=%r" % _ident(op.schema)) if op.schema else ""),
338
- "kwargs": (
339
- ", "
340
- + ", ".join(
341
- [
342
- "%s=%s"
343
- % (key, _render_potential_expr(val, autogen_context))
344
- for key, val in index.kwargs.items()
345
- ]
346
- )
347
- )
348
- if len(index.kwargs)
349
- else "",
336
+ "kwargs": ", " + ", ".join(opts) if opts else "",
350
337
  }
351
338
  return text
352
339
 
@@ -362,7 +349,6 @@ def _add_unique_constraint(
362
349
  def _add_fk_constraint(
363
350
  autogen_context: AutogenContext, op: ops.CreateForeignKeyOp
364
351
  ) -> str:
365
-
366
352
  args = [repr(_render_gen_name(autogen_context, op.constraint_name))]
367
353
  if not autogen_context._has_batch:
368
354
  args.append(repr(_ident(op.source_table)))
@@ -411,7 +397,6 @@ def _add_check_constraint(constraint, autogen_context):
411
397
  def _drop_constraint(
412
398
  autogen_context: AutogenContext, op: ops.DropConstraintOp
413
399
  ) -> str:
414
-
415
400
  if autogen_context._has_batch:
416
401
  template = "%(prefix)sdrop_constraint" "(%(name)r, type_=%(type)r)"
417
402
  else:
@@ -432,7 +417,6 @@ def _drop_constraint(
432
417
 
433
418
  @renderers.dispatch_for(ops.AddColumnOp)
434
419
  def _add_column(autogen_context: AutogenContext, op: ops.AddColumnOp) -> str:
435
-
436
420
  schema, tname, column = op.schema, op.table_name, op.column
437
421
  if autogen_context._has_batch:
438
422
  template = "%(prefix)sadd_column(%(column)s)"
@@ -452,7 +436,6 @@ def _add_column(autogen_context: AutogenContext, op: ops.AddColumnOp) -> str:
452
436
 
453
437
  @renderers.dispatch_for(ops.DropColumnOp)
454
438
  def _drop_column(autogen_context: AutogenContext, op: ops.DropColumnOp) -> str:
455
-
456
439
  schema, tname, column_name = op.schema, op.table_name, op.column_name
457
440
 
458
441
  if autogen_context._has_batch:
@@ -476,7 +459,6 @@ def _drop_column(autogen_context: AutogenContext, op: ops.DropColumnOp) -> str:
476
459
  def _alter_column(
477
460
  autogen_context: AutogenContext, op: ops.AlterColumnOp
478
461
  ) -> str:
479
-
480
462
  tname = op.table_name
481
463
  cname = op.column_name
482
464
  server_default = op.modify_server_default
@@ -566,7 +548,6 @@ def _render_potential_expr(
566
548
  is_server_default: bool = False,
567
549
  ) -> str:
568
550
  if isinstance(value, sql.ClauseElement):
569
-
570
551
  if wrap_in_text:
571
552
  template = "%(prefix)stext(%(sql)r)"
572
553
  else:
@@ -613,6 +594,7 @@ def _uq_constraint(
613
594
  opts.append(
614
595
  ("name", _render_gen_name(autogen_context, constraint.name))
615
596
  )
597
+ dialect_options = _render_dialect_kwargs_items(autogen_context, constraint)
616
598
 
617
599
  if alter:
618
600
  args = [repr(_render_gen_name(autogen_context, constraint.name))]
@@ -620,6 +602,7 @@ def _uq_constraint(
620
602
  args += [repr(_ident(constraint.table.name))]
621
603
  args.append(repr([_ident(col.name) for col in constraint.columns]))
622
604
  args.extend(["%s=%r" % (k, v) for k, v in opts])
605
+ args.extend(dialect_options)
623
606
  return "%(prefix)screate_unique_constraint(%(args)s)" % {
624
607
  "prefix": _alembic_autogenerate_prefix(autogen_context),
625
608
  "args": ", ".join(args),
@@ -627,6 +610,7 @@ def _uq_constraint(
627
610
  else:
628
611
  args = [repr(_ident(col.name)) for col in constraint.columns]
629
612
  args.extend(["%s=%r" % (k, v) for k, v in opts])
613
+ args.extend(dialect_options)
630
614
  return "%(prefix)sUniqueConstraint(%(args)s)" % {
631
615
  "prefix": _sqlalchemy_autogenerate_prefix(autogen_context),
632
616
  "args": ", ".join(args),
@@ -675,7 +659,6 @@ def _render_column(
675
659
  opts: List[Tuple[str, Any]] = []
676
660
 
677
661
  if column.server_default:
678
-
679
662
  rendered = _render_server_default( # type:ignore[assignment]
680
663
  column.server_default, autogen_context
681
664
  )
@@ -984,7 +967,6 @@ def _fk_colspec(
984
967
  def _populate_render_fk_opts(
985
968
  constraint: ForeignKeyConstraint, opts: List[Tuple[str, str]]
986
969
  ) -> None:
987
-
988
970
  if constraint.onupdate:
989
971
  opts.append(("onupdate", repr(constraint.onupdate)))
990
972
  if constraint.ondelete:
alembic/command.py CHANGED
@@ -494,7 +494,6 @@ def history(
494
494
  for sc in script.walk_revisions(
495
495
  base=base or "base", head=head or "heads"
496
496
  ):
497
-
498
497
  if indicate_current:
499
498
  sc._db_current_indicator = sc.revision in currents
500
499
 
alembic/config.py CHANGED
@@ -24,7 +24,6 @@ from .util import compat
24
24
 
25
25
 
26
26
  class Config:
27
-
28
27
  r"""Represent an Alembic configuration.
29
28
 
30
29
  Within an ``env.py`` script, this is available
@@ -563,7 +562,6 @@ class CommandLine:
563
562
  and fn.__name__[0] != "_"
564
563
  and fn.__module__ == "alembic.command"
565
564
  ):
566
-
567
565
  spec = compat.inspect_getfullargspec(fn)
568
566
  if spec[3] is not None:
569
567
  positional = spec[0][1 : -len(spec[3])]
alembic/ddl/impl.py CHANGED
@@ -379,8 +379,8 @@ class DefaultImpl(metaclass=ImplMeta):
379
379
  table, self.connection, checkfirst=False, _ddl_runner=self
380
380
  )
381
381
 
382
- def create_index(self, index: Index) -> None:
383
- self._exec(schema.CreateIndex(index))
382
+ def create_index(self, index: Index, **kw: Any) -> None:
383
+ self._exec(schema.CreateIndex(index, **kw))
384
384
 
385
385
  def create_table_comment(self, table: Table) -> None:
386
386
  self._exec(schema.SetTableComment(table))
@@ -391,8 +391,8 @@ class DefaultImpl(metaclass=ImplMeta):
391
391
  def create_column_comment(self, column: ColumnElement[Any]) -> None:
392
392
  self._exec(schema.SetColumnComment(column))
393
393
 
394
- def drop_index(self, index: Index) -> None:
395
- self._exec(schema.DropIndex(index))
394
+ def drop_index(self, index: Index, **kw: Any) -> None:
395
+ self._exec(schema.DropIndex(index, **kw))
396
396
 
397
397
  def bulk_insert(
398
398
  self,
@@ -637,7 +637,6 @@ class DefaultImpl(metaclass=ImplMeta):
637
637
  return False
638
638
 
639
639
  def _compare_identity_default(self, metadata_identity, inspector_identity):
640
-
641
640
  # ignored contains the attributes that were not considered
642
641
  # because assumed to their default values in the db.
643
642
  diff, ignored = _compare_identity_options(
@@ -669,6 +668,12 @@ class DefaultImpl(metaclass=ImplMeta):
669
668
  # order of col matters in an index
670
669
  return tuple(col.name for col in index.columns)
671
670
 
671
+ def create_unique_constraint_sig(
672
+ self, const: UniqueConstraint
673
+ ) -> Tuple[Any, ...]:
674
+ # order of col does not matters in an unique constraint
675
+ return tuple(sorted([col.name for col in const.columns]))
676
+
672
677
  def _skip_functional_indexes(self, metadata_indexes, conn_indexes):
673
678
  conn_indexes_by_name = {c.name: c for c in conn_indexes}
674
679
 
alembic/ddl/mssql.py CHANGED
@@ -98,7 +98,6 @@ class MSSQLImpl(DefaultImpl):
98
98
  existing_nullable: Optional[bool] = None,
99
99
  **kw: Any,
100
100
  ) -> None:
101
-
102
101
  if nullable is not None:
103
102
  if type_ is not None:
104
103
  # the NULL/NOT NULL alter will handle
@@ -171,7 +170,7 @@ class MSSQLImpl(DefaultImpl):
171
170
  table_name, column_name, schema=schema, name=name
172
171
  )
173
172
 
174
- def create_index(self, index: Index) -> None:
173
+ def create_index(self, index: Index, **kw: Any) -> None:
175
174
  # this likely defaults to None if not present, so get()
176
175
  # should normally not return the default value. being
177
176
  # defensive in any case
@@ -180,7 +179,7 @@ class MSSQLImpl(DefaultImpl):
180
179
  for col in mssql_include:
181
180
  if col not in index.table.c:
182
181
  index.table.append_column(Column(col, sqltypes.NullType))
183
- self._exec(CreateIndex(index))
182
+ self._exec(CreateIndex(index, **kw))
184
183
 
185
184
  def bulk_insert( # type:ignore[override]
186
185
  self, table: Union[TableClause, Table], rows: List[dict], **kw: Any
@@ -231,9 +230,7 @@ class MSSQLImpl(DefaultImpl):
231
230
  rendered_metadata_default,
232
231
  rendered_inspector_default,
233
232
  ):
234
-
235
233
  if rendered_metadata_default is not None:
236
-
237
234
  rendered_metadata_default = re.sub(
238
235
  r"[\(\) \"\']", "", rendered_metadata_default
239
236
  )
alembic/ddl/mysql.py CHANGED
@@ -240,7 +240,6 @@ class MySQLImpl(DefaultImpl):
240
240
  metadata_unique_constraints,
241
241
  metadata_indexes,
242
242
  ):
243
-
244
243
  # TODO: if SQLA 1.0, make use of "duplicates_index"
245
244
  # metadata
246
245
  removed = set()
alembic/ddl/postgresql.py CHANGED
@@ -12,7 +12,6 @@ from typing import TYPE_CHECKING
12
12
  from typing import Union
13
13
 
14
14
  from sqlalchemy import Column
15
- from sqlalchemy import Index
16
15
  from sqlalchemy import literal_column
17
16
  from sqlalchemy import Numeric
18
17
  from sqlalchemy import text
@@ -50,6 +49,8 @@ from ..util import sqla_compat
50
49
  if TYPE_CHECKING:
51
50
  from typing import Literal
52
51
 
52
+ from sqlalchemy import Index
53
+ from sqlalchemy import UniqueConstraint
53
54
  from sqlalchemy.dialects.postgresql.array import ARRAY
54
55
  from sqlalchemy.dialects.postgresql.base import PGDDLCompiler
55
56
  from sqlalchemy.dialects.postgresql.hstore import HSTORE
@@ -79,18 +80,19 @@ class PostgresqlImpl(DefaultImpl):
79
80
  )
80
81
  identity_attrs_ignore = ("on_null", "order")
81
82
 
82
- def create_index(self, index):
83
+ def create_index(self, index: Index, **kw: Any) -> None:
83
84
  # this likely defaults to None if not present, so get()
84
85
  # should normally not return the default value. being
85
86
  # defensive in any case
86
87
  postgresql_include = index.kwargs.get("postgresql_include", None) or ()
87
88
  for col in postgresql_include:
88
- if col not in index.table.c:
89
- index.table.append_column(Column(col, sqltypes.NullType))
90
- self._exec(CreateIndex(index))
89
+ if col not in index.table.c: # type: ignore[union-attr]
90
+ index.table.append_column( # type: ignore[union-attr]
91
+ Column(col, sqltypes.NullType)
92
+ )
93
+ self._exec(CreateIndex(index, **kw))
91
94
 
92
95
  def prep_table_for_batch(self, batch_impl, table):
93
-
94
96
  for constraint in table.constraints:
95
97
  if (
96
98
  constraint.name is not None
@@ -157,7 +159,6 @@ class PostgresqlImpl(DefaultImpl):
157
159
  existing_autoincrement: Optional[bool] = None,
158
160
  **kw: Any,
159
161
  ) -> None:
160
-
161
162
  using = kw.pop("postgresql_using", None)
162
163
 
163
164
  if using is not None and type_ is None:
@@ -239,7 +240,6 @@ class PostgresqlImpl(DefaultImpl):
239
240
  metadata_unique_constraints,
240
241
  metadata_indexes,
241
242
  ):
242
-
243
243
  doubled_constraints = {
244
244
  index
245
245
  for index in conn_indexes
@@ -308,6 +308,21 @@ class PostgresqlImpl(DefaultImpl):
308
308
  break
309
309
  return to_remove
310
310
 
311
+ def _dialect_sig(
312
+ self, item: Union[Index, UniqueConstraint]
313
+ ) -> Tuple[Any, ...]:
314
+ if (
315
+ item.dialect_kwargs.get("postgresql_nulls_not_distinct")
316
+ is not None
317
+ ):
318
+ return (
319
+ (
320
+ "nulls_not_distinct",
321
+ item.dialect_kwargs["postgresql_nulls_not_distinct"],
322
+ ),
323
+ )
324
+ return ()
325
+
311
326
  def create_index_sig(self, index: Index) -> Tuple[Any, ...]:
312
327
  return tuple(
313
328
  self._cleanup_index_expr(
@@ -319,7 +334,14 @@ class PostgresqlImpl(DefaultImpl):
319
334
  ),
320
335
  )
321
336
  for e in index.expressions
322
- )
337
+ ) + self._dialect_sig(index)
338
+
339
+ def create_unique_constraint_sig(
340
+ self, const: UniqueConstraint
341
+ ) -> Tuple[Any, ...]:
342
+ return tuple(
343
+ sorted([col.name for col in const.columns])
344
+ ) + self._dialect_sig(const)
323
345
 
324
346
  def _compile_element(self, element: ClauseElement) -> str:
325
347
  return element.compile(
@@ -638,7 +660,6 @@ def _render_inline_exclude_constraint(
638
660
 
639
661
 
640
662
  def _postgresql_autogenerate_prefix(autogen_context: AutogenContext) -> str:
641
-
642
663
  imports = autogen_context.imports
643
664
  if imports is not None:
644
665
  imports.add("from sqlalchemy.dialects import postgresql")
alembic/ddl/sqlite.py CHANGED
@@ -100,7 +100,6 @@ class SQLiteImpl(DefaultImpl):
100
100
  rendered_metadata_default: Optional[str],
101
101
  rendered_inspector_default: Optional[str],
102
102
  ) -> bool:
103
-
104
103
  if rendered_metadata_default is not None:
105
104
  rendered_metadata_default = re.sub(
106
105
  r"^\((.+)\)$", r"\1", rendered_metadata_default
@@ -193,7 +192,6 @@ class SQLiteImpl(DefaultImpl):
193
192
  metadata_unique_constraints,
194
193
  metadata_indexes,
195
194
  ):
196
-
197
195
  self._skip_functional_indexes(metadata_indexes, conn_indexes)
198
196
 
199
197