NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #154 most downloaded on PyPI
A database migration tool for SQLAlchemy.
Last release 23 days ago
11 Sep 2026
Release timing varies
gaps range from 2 weeks to 4 months
Nearly every release is documented
notes for 60 of the last 60 stable releases
2 versions withdrawn
withdrawn after publishing
15 years old
148 releases · first in 2011
[usecase] [batch] Added a warning for the case where an unnamed CHECK constraint on a reflected table is omitted from a batch "recreate" operation. An
Released: September 11, 2026
[usecase] [batch] Added a warning for the case where an unnamed CHECK constraint on a
reflected table is omitted from a batch "recreate" operation. An unnamed
CHECK constraint can't be reliably carried over in a batch recreate
as it may refer to columns that are being dropped or changed. This
omission was previously a silent operation. The presence of any
~sqlalchemy.schema.CheckConstraint in
Operations.batch_alter_table.table_args is taken to indicate
that the case has been accommodated, and no warning is emitted.
References: #1846
[usecase] [autogenerate] Autogenerate now renders a warning comment above any rendered
Operations.drop_constraint() directive for which the constraint name
is None, as is the case when a constraint that has no name in the model
is dropped, most typically within the downgrade() function of a
migration that adds an unnamed constraint. A warning is also emitted on
the console when the migration script is generated. The directive
requires a non-None name in order to be able to emit a "DROP CONSTRAINT"
command.
References: #916
[bug] [batch] Fixed bug in batch mode where adding a column with a type that generates
its own CHECK constraint, such as ~sqlalchemy.types.Boolean or
~sqlalchemy.types.Enum with
~sqlalchemy.types.Boolean.create_constraint set to True,
would emit the constraint twice when the table was recreated, once under
the name generated by the naming convention in use and once under the
name given to the type. The constraint is now emitted once, using the
same name that would be used outside of batch mode.
References: #1768
[bug] [batch] Fixed bug in batch mode where a CHECK constraint generated by a type such
as ~sqlalchemy.types.Boolean or ~sqlalchemy.types.Enum
would lose the name established for it by the naming convention in use
when the table was recreated, as the constraint was regenerated against
the temporary table used for the recreate operation. The naming
convention is now resolved against the name of the table being replaced.
As part of this change, a type that generates a CHECK constraint but has
no name of its own, used in conjunction with a naming convention that
includes the %(constraint_name)s token, now emits a warning, as the
convention has no name to interpolate; the constraint continues to be
emitted without a name. As noted at batch_check_constraints,
these datatypes should be given a name in order to participate fully in
batch mode.
References: #1844
[bug] [batch] Fixed bug in batch mode where the
Operations.batch_alter_table.naming_convention parameter
would re-generate the names of constraints that already had a name when
reflected, in the case where the convention included the
%(constraint_name)s token, leading to a name that included the
convention's own prefix twice. The convention is now applied only to
those constraints that are reflected without a name, which is the use
case the parameter is documented for.
References: #1845
[bug] [mysql] Fixed bug where autogenerate with
EnvironmentContext.configure.compare_server_default would
report a persistent server default change for Float, Numeric and
other decimal columns on MySQL. MySQL reports a literal server default
for such a column either in quoted form, e.g. '1', or, when the
value is fractional, as a parenthesized expression, e.g. (2.5);
neither form was accommodated for columns other than those of
Integer affinity, so that a default such as server_default="1"
on a sqlalchemy.Float column would never compare as equal to
the reflected value.
References: #1866
[bug] [mysql] Fixed bug where autogenerate with
EnvironmentContext.configure.compare_server_default would
report a persistent server default change for an expression server
default such as (rand()). MySQL reports such a default with the
surrounding parenthesis included whereas MariaDB reports it without
them, so that the parenthesis are now disregarded when comparing.
References: #1866
[change] [general] Support for SQLAlchemy 1.4 is dropped as of Alembic 1.20.0; SQLAlchemy
2.0.0 is now the minimum required version. SQLAlchemy 1.4 has no support
for Python 3.13 and above, and the version-conditional code paths it
required throughout Alembic have been removed in favor of the SQLAlchemy
2.0 API.
References: #1851
One column per quarter.
[changed] [autogenerate] The autogenerate plugin for CHECK constraint detection by name, added in 1.19.0. for #508 , is no longer enabled by default.
Released: September 4, 2026
[changed] [autogenerate] The autogenerate plugin for CHECK constraint detection by name, added in
1.19.0. for #508, is no longer enabled by default. It has been
renamed from alembic.autogenerate.checkconstraint_byname to
alembic.ext.checkconstraint_byname and no longer matches on the
"alembic.autogenerate.*" wildcard, which remains the default plugin
specification. The previous name will still function as well if placed in
the plugins list explicitly, both to enable the plugin and within a
"~" exclusion, so that an env.py written against 1.19.0 or 1.19.1
requires no change.
The plugin is now recommended only for schemas that ensure the naming of
all constraints using a client side naming convention, otherwise there's a
persistent risk of false positives. See
autogenerate_check_constraints for background on things to be aware
of when using this plugin.
As part of this change "type bound" CHECK constraints, which include
constraints generated for the Boolean and Enum datatypes when the
create_constraint parameter is set to True, are no longer ignored in
the metadata side, so that normal name-based matching can occur for
these constraints.
References: #1859
[usecase] [autogenerate] [batch] The target of a ~sqlalchemy.schema.ForeignKey is now located
using the ForeignKey.target_tokens and
ForeignKey.target_table_key accessors added in SQLAlchemy 2.1, rather
than by splitting the dotted string form of that target on ".". As a
dot inside a schema, table or column name cannot be told apart from the
separator between those names, a foreign key whose target name contained
a dot was previously mis-parsed by autogenerate rendering as well as by
batch migrations. The dotted string continues to be split when running
against SQLAlchemy 2.0, where these accessors are not present. Thanks to
Gyanu Mayank for the initial pull request.
References: #1860
[bug] [autogenerate] Fixed bug in the check constraint detection implemented in #508 that failed to take into account column bound check constraints,
[changed] [installation] Environmental updates:
Released: August 4, 2026
[changed] [installation] Environmental updates:
- Trove classifiers now include Python 3.15 which is now part of CI
integration
- Python 3.14 is also added to trove classifiers which had been previously
omitted
- Implemented [PEP 604](https://peps.python.org/pep-0604) style unions in type annotations
[feature] [autogenerate] Autogenerate now detects the addition and removal of named CHECK
constraints, as part of the default autogenerate behavior. Detection is
name-based only; a constraint whose name is unchanged is presumed
equivalent regardless of its expression text, as reliably normalizing
SQL expressions across backends for comparison purposes is not generally
feasible. This behavior is implemented as a plugin named
alembic.autogenerate.checkconstraint_byname, and may be disabled if not
desired by excluding it from the
EnvironmentContext.configure.autogenerate_plugins list.
Pull request courtesy Francois van Kempen.
References: #508
[bug] [commands] Fixed inconsistency where running stamp or downgrade to base in
offline (--sql) mode would emit a DROP TABLE alembic_version
statement, while the same operations in online mode never drop the version
table. Offline mode no longer emits this DROP, matching online
behavior. The version table continues to be created when it does not exist;
only the spurious offline-only drop has been removed. Pull request
courtesy imurodl.
References: #1822
[usecase] [commands] Added --splice support to the merge() command. Previously, the merge command would suggest using --splice when attempting to merg
Released: June 25, 2026
[usecase] [commands] Added --splice support to the merge() command. Previously, the
merge command would suggest using --splice when attempting to merge
non-head revisions, but the flag was not actually accepted by the command.
The splice parameter is now available in both the command-line
interface and the command.merge() function, matching the existing
support in command.revision(). Pull request courtesy Kadir Can
Ozden.
References: #1712
[usecase] [environment] Added ScriptDirectory.get_heads.consider_depends_on
parameter to ScriptDirectory.get_heads(). When set to True,
head revisions that are also a dependency of another revision via
depends_on are excluded from the result, matching the effective
heads that would be present in the alembic_version table after
running all upgrades.
References: #1806
[bug] [autogenerate] Fixed rendering of dialect keyword arguments containing
~sqlalchemy.schema.Column objects within sequences, such as
postgresql_include. These were previously rendered using repr(),
producing invalid Python in the generated migration scripts. Column
objects within list or tuple values are now correctly rendered as their
string column names. Pull request courtesy Ajay Singh.
References: #1258
[bug] [mysql] Implemented type comparison for ENUM datatypes on MySQL, which
checks that the individual enum values are equivalent. If additional
entries are on either side, this generates a diff. Changes of order do not
generate a diff. Pull request courtesy Furkan Köykıran.
[bug] [operations] Fixed bug where the inline_references parameter of
Operations.add_column() did not include foreign key referential
actions such as ON DELETE, ON UPDATE, DEFERRABLE,
INITIALLY, and MATCH when rendering the inline REFERENCES
clause.
References: #1820
[bug] [operations] Reverted the behavior of Operations.add_column() that would automatically render the "PRIMARY KEY" keyword inline when a Column wit
Released: February 10, 2026
[bug] [operations] Reverted the behavior of Operations.add_column() that would
automatically render the "PRIMARY KEY" keyword inline when a
Column with primary_key=True is added. The automatic
behavior, added in version 1.18.2, is now opt-in via the new
Operations.add_column.inline_primary_key parameter. This
change restores the ability to render a PostgreSQL SERIAL column, which is
required to be primary_key=True, while not impacting the ability to
render a separate primary key constraint. This also provides consistency
with the Operations.add_column.inline_references parameter and
gives users explicit control over SQL generation.
To render PRIMARY KEY inline, use the
Operations.add_column.inline_primary_key parameter set to
True:
op.add_column(
"my_table",
Column("id", Integer, primary_key=True),
inline_primary_key=True
)References: #1232
[bug] [autogenerate] Fixed regression in version 1.18.0 due to #1771 where autogenerate would raise NoReferencedTableError when a foreign key constrai
Released: January 29, 2026
[bug] [autogenerate] Fixed regression in version 1.18.0 due to #1771 where autogenerate
would raise NoReferencedTableError when a foreign key constraint
referenced a table that was not part of the initial table load, including
tables filtered out by the
EnvironmentContext.configure.include_name callable or tables
in remote schemas that were not included in the initial reflection run.
The change in #1771 was a performance optimization that eliminated
additional reflection queries for tables that were only referenced by
foreign keys but not explicitly included in the main reflection run.
However, this optimization inadvertently removed the creation of
Table objects for these referenced tables, causing autogenerate
to fail when processing foreign key constraints that pointed to them.
The fix creates placeholder Table objects for foreign key targets
that are not reflected, allowing the autogenerate comparison to proceed
without error while maintaining the performance improvement from
#1771. When multiple foreign keys reference different columns in
the same filtered table, the placeholder table accumulates all necessary
columns. These placeholder tables may be visible when using the
EnvironmentContext.configure.include_object callable to
inspect ForeignKeyConstraint objects; they will have the name,
schema and basic column information for the relevant columns present.
References: #1787
[bug] [general] Fixed regression caused by #1669 which requires SQLAlchemy objects
to support generic type subscripting; for the older SQLAlchemy 1.4 series,
this requires version 1.4.23. Changed the minimum requirements to require
version 1.4.23 rather than 1.4.0.
References: #1788
[usecase] [operations] The primary_key parameter on Column is now honored when Operations.add_column() is used, and will emit the "PRIMARY KEY" keywor
Released: January 28, 2026
[usecase] [operations] The primary_key parameter on Column is now honored when
Operations.add_column() is used, and will emit the "PRIMARY KEY"
keyword inline within the ADD COLUMN directive. This is strictly a syntax
enhancement; no attempt is made to reconcile the column's primary key
status with any existing primary key constraint or particular backend
limitations on adding columns to the primary key.
References: #1232
[usecase] [operations] Added inline_references parameter to Operations.add_column()
which allows rendering of REFERENCES clauses inline within the ADD COLUMN directive rather than as a separate ADD CONSTRAINT directive.
This syntax is supported by PostgreSQL, Oracle, MySQL 5.7+, and MariaDB
10.5+, and can provide performance benefits on large tables by avoiding
full table validation when adding a nullable foreign key column.
References: #1780
[bug] [typing] Fixed typing issue where the AlterColumnOp.server_default and
AlterColumnOp.existing_server_default parameters failed to
accommodate common SQLAlchemy SQL constructs such as null() and
text(). Pull request courtesy Sebastian Kreft.
References: #1669
Released: January 28, 2026
[usecase] [operations] ¶ The primary_key parameter on Column is now honored when Operations.add_column() is used, and will emit the “PRIMARY KEY” keyword inline within the ADD COLUMN directive. This is strictly a syntax enhancement; no attempt is made to reconcile the column’s primary key status with any existing primary key constraint or particular backend limitations on adding columns to the primary key.
Note
As of version 1.18.4, this behavior has been amended to be opt-in via the new Operations.add_column.inline_primary_key parameter to Operations.add_column() , rather than occurring automatically when primary_key=True is set on the Column object.
References: #1232
[usecase] [operations] ¶ Added inline_references parameter to Operations.add_column() which allows rendering of REFERENCES clauses inline within the ADD COLUMN directive rather than as a separate ADD CONSTRAINT directive. This syntax is supported by PostgreSQL, Oracle, MySQL 5.7+, and MariaDB 10.5+, and can provide performance benefits on large tables by avoiding full table validation when adding a nullable foreign key column.
References: #1780
[bug] [typing] ¶ Fixed typing issue where the AlterColumnOp.server_default and AlterColumnOp.existing_server_default parameters failed to accommodate common SQLAlchemy SQL constructs such as null() and text() . Pull request courtesy Sebastian Kreft.
Note
This fix is not compatible with older SQLAlchemy versions prior to 1.4.23.
References: #1669
[bug] [operations] Revised the change regarding SQLAlchemy 2.1 and deprecation warnings related to isolate_from_table=True . Further developments in r…
Released: January 14, 2026
[bug] [autogenerate] Fixed issue in new plugin system where the configured logger was not
correctly using the __name__ token to identify the logger.
References: #1779
[bug] [operations] Revised the change regarding SQLAlchemy 2.1 and deprecation warnings
related to isolate_from_table=True. Further developments in release 2.1
have revised how this parameter will be modified.
[usecase] Avoid deprecation warning in add/drop constraint added in SQLAlchemy 2.1. Ensure that alembic is compatible with the changes added in sqlalc…
Released: January 9, 2026
[feature] [operations] When alembic is run in "verbose" mode, alembic now logs a message to
indicate from which file is used to load the configuration.
References: #1737
[feature] [autogenerate] Autogenerate reflection sweeps now use the "bulk" inspector methods
introduced in SQLAlchemy 2.0, which for selected dialects including
PostgreSQL and Oracle use batched queries to reflect whole collections of
tables using O(1) queries rather than O(N).
References: #1771
[feature] [autogenerate] Release 1.18.0 introduces a plugin system that allows for automatic
loading of third-party extensions as well as configurable autogenerate
compare functionality on a per-environment basis.
The Plugin class provides a common interface for extensions that
register handlers among Alembic's existing extension points such as
Operations.register_operation() and
Operations.implementation_for(). A new interface for registering
autogenerate comparison handlers,
Plugin.add_autogenerate_comparator(), provides for autogenerate
compare functionality that may be custom-configured on a per-environment
basis using the new
EnvironmentContext.configure.autogenerate_plugins parameter.
The change does not impact well known Alembic add-ons such as
alembic-utils, which continue to work as before; however, such add-ons
have the option to provide plugin entrypoints going forward.
As part of this change, Alembic's autogenerate compare functionality is
reorganized into a series of internal plugins under the
alembic.autogenerate namespace, which may be individually or
collectively identified for inclusion and/or exclusion within the
EnvironmentContext.configure() call using a new parameter
EnvironmentContext.configure.autogenerate_plugins. This
parameter is also where third party comparison plugins may also be
indicated.
See alembic.plugins.toplevel for complete documentation on
the new Plugin class as well as autogenerate-specific usage
instructions.
[usecase] [environment] The file_template configuration option now supports directory paths,
allowing migration files to be organized into subdirectories. When using
directory separators in file_template (e.g.,
%(year)d/%(month).2d/%(day).2d_%(rev)s_%(slug)s), Alembic will
automatically create the necessary directory structure. The
recursive_version_locations setting must be set to true when using
this feature in order for the revision files to be located for subsequent
commands.
References: #1774
[usecase] Avoid deprecation warning in add/drop constraint added in SQLAlchemy 2.1.
Ensure that alembic is compatible with the changes added in
sqlalchemy/sqlalchemy#13006
by explicitly setting isolate_from_table=True when running with
SQLAlchemy 2.1 or greater.
[bug] [postgresql] Fixed issue where PostgreSQL sequence defaults on non-primary key columns
were incorrectly detected as changed on every autogenerate run. Server
default comparison logic is adjusted to filter out the ::regclass
expression added by the server which interferes with the comparison.
References: #1507
[bug] [mssql] Implemented DDL for column comment add/update/delete when using the
Operations.alter_column.comment parameter with
Operations.alter_column() on Microsoft SQL Server. Previously,
these functions were not implemented for SQL Server and would raise
UnsupportedCompilationError.
References: #1755
[feature] [operations] Added Operations.implementation_for.replace parameter to Operations.implementation_for() , allowing replacement of existing ope
Released: November 14, 2025
[feature] [operations] Added Operations.implementation_for.replace parameter to
Operations.implementation_for(), allowing replacement of existing
operation implementations. This allows for existing operations such as
CreateTableOp to be extended directly. Pull request courtesy
justanothercatgirl.
References: #1750
[bug] [mssql] Fixed issue in SQL Server dialect where the DROP that's automatically
emitted for existing default constraints during an ALTER COLUMN needs to
take place before not just the modification of the column's default, but
also before the column's type is changed.
References: #1744
[usecase] [commands] Added command.current.check_heads parameter to command.current() command, available from the command line via the --check-heads o
Released: October 28, 2025
[usecase] [commands] Added command.current.check_heads parameter to
command.current() command, available from the command line via the
--check-heads option to alembic current. This tests if all head
revisions are applied to the database and raises DatabaseNotAtHead
(or from the command line, exits with a non-zero exit code) if this is not
the case. The parameter operates equvialently to the cookbook recipe
cookbook_check_heads. Pull request courtesy Stefan Scherfke.
References: #1705
[bug] [commands] Disallow ':' character in custom revision identifiers. Previously, using a
colon in a revision ID (e.g., 'REV:1') would create the revision, however
revisions with colons in them are not correctly interpreted by other
commands, as it overlaps with the revision range syntax. Pull request
courtesy Kim Wooseok with original implementation by Hrushikesh Patil.
References: #1540
[change] [tests] The top-level test runner has been changed to use nox, adding a noxfile.py as well as some included modules. The tox.ini file remains
Released: October 11, 2025
[change] [tests] The top-level test runner has been changed to use nox, adding a
noxfile.py as well as some included modules. The tox.ini file
remains in place so that tox runs will continue to function in the near
term, however it will be eventually removed and improvements and
maintenance going forward will be only towards noxfile.py.
[change] [general] The minimum Python version is now 3.10, as Python 3.9 is EOL.
[bug] [mysql] Fixed Python-side autogenerate rendering of index expressions in MySQL dialect by aligning it with SQLAlchemy's MySQL index expression r
Released: August 27, 2025
[bug] [mysql] Fixed Python-side autogenerate rendering of index expressions in MySQL dialect by aligning it with SQLAlchemy's MySQL index expression rules. Pull request courtesy david-fed.
References: #1492
[bug] [config] Fixed issue where new pyproject.toml config would fail to parse the integer
value used for the truncate_slug_length parameter. Pull request
courtesy Luís Henrique Allebrandt Schunemann.
References: #1709
[bug] [config] Fixed issue in new pyproject.toml support where boolean values, such as those used for the recursive_version_locations and sourceless c
Released: July 10, 2025
[bug] [config] Fixed issue in new pyproject.toml support where boolean values, such as
those used for the recursive_version_locations and sourceless
configuration parameters, would not be accepted.
References: #1694
[usecase] [commands] Added new pyproject_async template, combining the new pyproject template with the async template. Pull request courtesy Alc-Alc.
Released: July 8, 2025
[usecase] [commands] Added new pyproject_async template, combining the new pyproject
template with the async template. Pull request courtesy Alc-Alc.
References: #1683
[usecase] [autogenerate] Add "module" post-write hook. This hook type is almost identical to the
console_scripts hook, except it's running python -m black instead of
using black's console_script. It is mainly useful for tools without
console scripts (e.g. ruff), but has semantics closer to the
console_scripts hook in that it finds the ruff module available to the
running interpreter instead of finding an executable by path. Pull request
courtesy Frazer McLean.
References: #1686
[bug] [autogenerate] Fixed the rendering of server_default=FetchedValue() to ensure it is
preceded by the sa. prefix in the migration script. Pull request
courtesy david-fed.
References: #1633
[bug] [autogenerate] Fixed autogenerate rendering bug which failed to render foreign key
constraints local to a CreateTableOp object if it did not refer
to a MetaData collection via a private constructor argument that would
not ordinarily be passed in user-defined rewriter recipes, including ones
in the Alembic cookbook section of the docs.
References: #1692
[bug] [autogenerate] Fixed issue where dialect-specific keyword arguments in dialect_kwargs were not rendered when rendering the Operations.create_for
Released: June 16, 2025
[bug] [autogenerate] Fixed issue where dialect-specific keyword arguments in dialect_kwargs
were not rendered when rendering the Operations.create_foreign_key()
operation. This prevented dialect-specific keywords from being rendered
using custom Rewriter recipes that modify
ops.CreateForeignKeyOp, similar to other issues such as
#1635. Pull request courtesy Justin Malin.
References: #1671
[bug] [command] Fixed rendering of pyproject.toml to include two newlines when
appending content to an existing file. Pull request courtesy Jonathan
Vanasco.
References: #1679
[bug] [command] Fixed regression caused by the pathlib refactoring that removed the use of Config.get_template_directory() as the canonical source of
Released: May 21, 2025
[bug] [command] Fixed regression caused by the pathlib refactoring that removed the use
of Config.get_template_directory() as the canonical source of
templates; the method is still present however it no longer would be
consulted for a custom config subclass, as was the case with flask-migrate.
References: #1660
[bug] [command] Fixed regression caused by the pathlib refactoring where the "missing
template" error message failed to render the name of the template that
could not be found.
References: #1659
…continues to be split on spaces/commas/colons. A deprecation warning is emitted for these fallback scenarios.
Released: May 21, 2025
[feature] [environment] Added optional PEP 621 support to Alembic, allowing all source code
related configuration (e.g. local file paths, post write hook
configurations, etc) to be configured in the project's pyproject.toml
file. A new init template pyproject is added which illustrates a
basic PEP 621 setup.
Besides being better integrated with a Python project's existing source
code configuration, the TOML format allows for more flexible structures,
allowing configuration items like version_locations and
prepend_sys_path to be configured as lists of path strings without the
need for path separator characters used by ConfigParser format. The
feature continues to support the %(here)s token which can substitute
the absolute parent directory of the pyproject.toml file when
consumed.
The PEP 621 feature supports configuration values that are relevant to
source code organization and generation only; it does not accommodate
configuration of database connectivity or logging, which remain under the
category of "deployment" configuration and continue to be part of
alembic.ini, or whatever configurational method is established by the
env.py file. Using the combination of pyproject.toml for source
code configuration along with a custom database/logging configuration
method established in env.py will allow the alembic.ini file to be
omitted altogether.
References: #1082
[feature] [commands] Added new CommandLine.register_command() method to
CommandLine, intended to facilitate adding custom commands to
Alembic's command line tool with minimal code required; previously this
logic was embedded internally and was not publicly accessible. A new
recipe demonstrating this use is added. Pull request courtesy Mikhail
Bulash.
References: #1610
[usecase] [environment] Added new option to the ConfigParser (e.g. alembic.ini) configuration
path_separator, which supersedes the existing version_path_separator
option. path_separator specifies the path separator character that
will be recognized for both the version_locations option as well
as the prepend_sys_path option, defaulting to os which indicates
that the value of os.pathsep should be used.
The new attribute applies necessary os-dependent path splitting to the
prepend_sys_path option so that windows paths which contain drive
letters with colons are not inadvertently split, whereas previously
os-dependent path splitting were only available for the version_locations option.
Existing installations that don't indicate path_separator
will continue to use the older behavior, where version_path_separator
may be configured for version_locations, and prepend_sys_path
continues to be split on spaces/commas/colons. A deprecation warning
is emitted for these fallback scenarios.
When using the new pyproject.toml configuration detailed at
using_pep_621, the whole issue of "path separators" is sidestepped
and parameters like path_separator are unnecessary, as the TOML based
configuration configures version locations and sys path elements as
lists.
Pull request courtesy Mike Werezak.
References: #1330
[usecase] [operations] Added Operations.add_column.if_not_exists and
Operations.drop_column.if_exists to render IF [NOT] EXISTS
for ADD COLUMN and DROP COLUMN operations, a feature available on
some database backends such as PostgreSQL, MariaDB, as well as third party
backends. The parameters also support autogenerate rendering allowing them
to be added to autogenerate scripts via a custom Rewriter. Pull
request courtesy of Louis-Amaury Chaib (@lachaib).
References: #1626
[usecase] [operations] Added Operations.drop_constraint.if_exists parameter to
Operations.drop_constraint() which will render DROP CONSTRAINT IF EXISTS. The parameter also supports autogenerate rendering allowing it to
be added to autogenerate scripts via a custom Rewriter. Pull
request courtesy Aaron Griffin.
References: #1650
[bug] [general] The pyproject.toml file used by the Alembic project itself for its
Python package configuration has been amended to use the updated PEP 639
configuration for license, which eliminates loud deprecation warnings when
building the package. Note this necessarily bumps setuptools build
requirement to 77.0.3.
References: #1637
[bug] [environment] Fixed issue where use of deprecated utcnow() function would generate
warnings. Has been replaced with now(UTC). Pull request courtesy
Jens Tröger.
References: #1643
[bug] [autogenerate] The Operations.execute() operation when rendered in autogenerate
(which would necessarily be only when using a custom writer that embeds
ExecuteSQLOp) now correctly takes into account the value
configured in configure.alembic_module_prefix when rendering
the operation with its prefixing namespace; previously this was hardcoded
to op.. Pull request courtesy Avery Fischer.
References: #1656
[bug] [autogenerate] The autogenerate process will now apply the Operations.f() modifier
to the names of all constraints and indexes that are reflected from the
target database when generating migrations, which has the effect that these
names will not have any subsequent naming conventions applied to them when
the migration operations proceed. As reflected objects already include the
exact name that's present in the database, these names should not be
modified. The fix repairs the issue when using custom naming conventions
which feature the %(constraint_name)s token would cause names to be
double-processed, leading to errors in migration runs.
References: #264
[refactored] [environment] The command, config and script modules now rely on pathlib.Path for
internal path manipulations, instead of os.path() operations. This
has some impact on both public and private (i.e. underscored) API functions:
- Public API functions that accept parameters indicating file and directory
paths as strings will continue to do so, but now will also accept
`os.PathLike` objects as well.
- Public API functions and accessors that return directory paths as strings
such as `ScriptDirectory.dir`, `Config.config_file_name`
will continue to do so.
- Private API functions and accessors, i.e. all those that are prefixed
with an underscore, that previously returned directory paths as
strings may now return a Path object instead.
[bug] [autogenerate] Fixed issue where the "modified_name" of AlterColumnOp would not be considered when rendering op directives for autogenerate. Whi
Released: March 28, 2025
[bug] [autogenerate] Fixed issue where the "modified_name" of AlterColumnOp would not
be considered when rendering op directives for autogenerate. While
autogenerate cannot detect changes in column name, this would nonetheless
impact approaches that made use of this attribute in rewriter recipes. Pull
request courtesy lenvk.
References: #1635
[bug] [installation] Fixed an issue in the new PEP 621 pyproject.toml layout that prevented Alembic's template files from being included in the .whl f
[changed] [general] Support for Python 3.8 is dropped as of Alembic 1.15.0; this version is now EOL so Python 3.9 or higher is required for Alembic 1.
Released: March 4, 2025
[changed] [general] Support for Python 3.8 is dropped as of Alembic 1.15.0; this version is now EOL so Python 3.9 or higher is required for Alembic 1.15.
[changed] [general] Support for SQLAlchemy 1.3, which was EOL as of 2021, is now dropped from Alembic as of version 1.15.0. SQLAlchemy version 1.4 or greater is required for use with Alembic 1.15.0.
[changed] [general] Installation has been converted to use PEP 621, e.g. pyproject.toml.
[usecase] [autogenerate] Index autogenerate will now render labels for expressions that use them. This is useful when applying operator classes in PostgreSQL that can be keyed on the label name.
References: #1603
[usecase] [autogenerate] Add revision context to AutogenerateDiffsDetected so that command can be wrapped and diffs may be output in a different format. Pull request courtesy Louis-Amaury Chaib (@lachaib).
References: #1597
[bug] [environment] Added a basic docstring to the migration template files so that the upgrade/downgrade methods pass the D103 linter check which requires a docstring for public functions. Pull request courtesy Peter Cock.
References: #1567
[bug] [autogenerate] Fixed autogenerate rendering bug where the deferrable element of
UniqueConstraint, a bool, were being stringified rather than repr'ed
when generating Python code.
References: #1613
[usecase] [sqlite] Modified SQLite's dialect to render "ALTER TABLE RENAME COLUMN" when Operations.alter_column() is used with a straight rename, supp
Released: January 19, 2025
[usecase] [sqlite] Modified SQLite's dialect to render "ALTER TABLE <t> RENAME COLUMN" when
Operations.alter_column() is used with a straight rename, supporting
SQLite's recently added column rename feature.
References: #1576
[bug] [environment] Added tzdata to tz extras, which is required on some platforms such as Windows. Pull request courtesy Danipulok.
References: #1556
[bug] [autogenerate] Fixed bug where autogen render of a "variant" type would fail to catch the variants if the leading type were a dialect-specific type, rather than a generic type.
References: #1585
[usecase] [runtime] Added a new hook to the DefaultImpl DefaultImpl.version_table_impl(). This allows third party dialects to define the exact structu
Released: November 4, 2024
[usecase] [runtime] Added a new hook to the DefaultImpl
DefaultImpl.version_table_impl(). This allows third party dialects
to define the exact structure of the alembic_version table, to include use
cases where the table requires special directives and/or additional columns
so that it may function correctly on a particular backend. This is not
intended as a user-expansion hook, only a dialect implementation hook to
produce a working alembic_version table. Pull request courtesy Maciek
Bryński.
References: #1560
[usecase] [autogenerate] Render if_exists and if_not_exists parameters in CreateTableOp, CreateIndexOp, DropTableOp and DropIndexOp in an autogenerate
Released: September 23, 2024
[usecase] [autogenerate] Render if_exists and if_not_exists parameters in
CreateTableOp, CreateIndexOp, DropTableOp and
DropIndexOp in an autogenerate context. While Alembic does not
set these parameters during an autogenerate run, they can be enabled using
a custom Rewriter in the env.py file, where they will now be
part of the rendered Python code in revision files. Pull request courtesy
of Louis-Amaury Chaib (@lachaib).
[usecase] [environment] Enhance version_locations parsing to handle paths containing newlines.
References: #1509
[usecase] [operations] Added support for Operations.create_table.if_not_exists and
Operations.drop_table.if_exists, adding similar functionality
to render IF [NOT] EXISTS for table operations in a similar way as with
indexes. Pull request courtesy Aaron Griffin.
References: #1520
setuptools<69.3 in pyproject.toml has been removed.
This pin was to prevent a sudden change to PEP 625 in setuptools from
taking place which changes the file name of SQLAlchemy's source
distribution on pypi to be an all lower case name, and the change was
extended to all SQLAlchemy projects to prevent any further surprises.
However, the presence of this pin is now holding back environments that
otherwise want to use a newer setuptools, so we've decided to move forward
with this change, with the assumption that build environments will have
largely accommodated the setuptools change by now.In SQLAlchemy 2.1 this case will be deprecated as "empty sequence" is ambiguous as to its intent.
Released: June 26, 2024
[usecase] [autogenerate] Improve computed column compare function to support multi-line expressions. Pull request courtesy of Georg Wicke-Arndt.
References: #1391
[bug] [commands] Fixed bug in alembic command stdout where long messages were not properly wrapping at the terminal width. Pull request courtesy Saif Hakim.
References: #1384
[bug] [execution] Fixed internal issue where Alembic would call connection.execute()
sending an empty tuple to indicate "no params". In SQLAlchemy 2.1 this
case will be deprecated as "empty sequence" is ambiguous as to its intent.
References: #1394
[bug] [tests] Fixes to support pytest 8.1 for the test suite.
References: #1435
[bug] [autogenerate] [postgresql] Fixed the detection of serial column in autogenerate with tables not under default schema on PostgreSQL
References: #1479
[bug] [autogenerate] Fixed Rewriter so that more than two instances could be chained together correctly, also allowing multiple process_revision_direc
Released: December 20, 2023
[bug] [autogenerate] Fixed Rewriter so that more than two instances could be chained
together correctly, also allowing multiple process_revision_directives
callables to be chained. Pull request courtesy zrotceh.
References: #1337
[bug] [environment] Fixed issue where the method EnvironmentContext.get_x_argument()
using the EnvironmentContext.get_x_argument.as_dictionary
parameter would fail if an argument key were passed on the command line as
a name alone, that is, without an equal sign = or a value. Behavior is
repaired where this condition is detected and will return a blank string
for the given key, consistent with the behavior where the = sign is
present and no value. Pull request courtesy Iuri de Silvio.
References: #1369
[bug] [autogenerate] Fixed issue where the "unique" flag of an Index would not be maintained
when generating downgrade migrations. Pull request courtesy Iuri de
Silvio.
References: #1370
[bug] [versioning] Fixed bug in versioning model where a downgrade across a revision with two down revisions with one down revision depending on the other, would produce an erroneous state in the alembic_version table, making upgrades impossible without manually repairing the table. Thanks much to Saif Hakim for the great work on this.
References: #1373
[bug] [typing] Updated pep-484 typing to pass mypy "strict" mode, however including per-module qualifications for specific typing elements not yet complete. This allows us to catch specific typing issues that have been ongoing such as import symbols not properly exported.
References: #1377
[changed] [installation] Alembic 1.13 now supports Python 3.8 and above.
Released: December 1, 2023
[changed] [installation] Alembic 1.13 now supports Python 3.8 and above.
References: #1359
[usecase] [operations] Updated logic introduced in #151 to allow if_exists and
if_not_exists on index operations also on SQLAlchemy
1.4 series. Previously this feature was mistakenly requiring
the 2.0 series.
References: #1323
[usecase] Replaced python-dateutil with the standard library module
zoneinfo.
This module was added in Python 3.9, so previous version will been
to install the backport of it, available by installing the backports.zoneinfo
library. The alembic[tz] option has been updated accordingly.
References: #1339
[bug] [commands] Fixed issue where the alembic check command did not function correctly
with upgrade structures that have multiple, top-level elements, as are
generated from the "multi-env" environment template. Pull request courtesy
Neil Williams.
References: #1234
[bug] [autogenerate] Fixed autogenerate issue where create_table_comment() and
drop_table_comment() rendering in a batch table modify would include
the "table" and "schema" arguments, which are not accepted in batch as
these are already part of the top level block.
References: #1361
[bug] [postgresql] Additional fixes to PostgreSQL expression index compare feature. The compare now correctly accommodates casts and differences in spacing. Added detection logic for operation clauses inside the expression, skipping the compare of these expressions. To accommodate these changes the logic for the comparison of the indexes and unique constraints was moved to the dialect implementation, allowing greater flexibility.
[usecase] Alembic now accommodates for Sequence and Identity that support dialect kwargs. This is a change that will be added to SQLAlchemy v2.1.
Released: October 26, 2023
[usecase] Alembic now accommodates for Sequence and Identity that support dialect kwargs. This is a change that will be added to SQLAlchemy v2.1.
References: #1304
[bug] [autogenerate] [regression] Fixed regression caused by #879 released in 1.7.0 where the
".info" dictionary of Table would not render in autogenerate create
table statements. This can be useful for custom create table DDL rendering
schemes so it is restored.
References: #1329
[bug] [typing] Improved typing in the
EnvironmentContext.configure.process_revision_directives
callable to better indicate that the passed-in type is
MigrationScript, not the MigrationOperation base class,
and added typing to the example at cookbook_no_empty_migrations to
illustrate.
References: #1325
[bug] [operations] Repaired ExecuteSQLOp so that it can participate in "diff"
operations; while this object is typically not present in a reflected
operation stream, custom hooks may be adding this construct where it needs
to have the correct to_diff_tuple() method. Pull request courtesy
Sebastian Bayer.
References: #1335
[bug] [typing] Improved the op.execute() method to correctly accept the
Executable type that is the same which is used in SQLAlchemy
Connection.execute(). Pull request courtesy Mihail Milushev.
[bug] [typing] Improve typing of the revision parameter in various command functions.
References: #930
[bug] [typing] Properly type the Operations.create_check_constraint.condition
parameter of Operations.create_check_constraint() to accept boolean
expressions.
References: #1266
[bug] [postgresql] Fixed autogen render issue where expressions inside of indexes for PG need
to be double-parenthesized, meaning a single parens must be present within
the generated text() construct.
References: #1322
[feature] [autogenerate] Added new feature to the "code formatter" function which allows standalone executable tools to be run against code, without g
Released: August 31, 2023
[feature] [autogenerate] Added new feature to the "code formatter" function which allows standalone
executable tools to be run against code, without going through the Python
interpreter. Known as the exec runner, it complements the existing
console_scripts runner by allowing non-Python tools such as ruff to
be used. Pull request courtesy Mihail Milushev.
References: #1275
[usecase] [autogenerate] Change the default value of
EnvironmentContext.configure.compare_type to True.
As Alembic's autogenerate for types was dramatically improved in
version 1.4 released in 2020, the type comparison feature is now much
more reliable so is now enabled by default.
References: #1248
[bug] [operations] Added support for op.drop_constraint() to support PostrgreSQL
ExcludeConstraint objects, as well as other constraint-like objects
that may be present in third party dialects, by resolving the type_
parameter to be None for this case. Autogenerate has also been
enhanced to exclude the type_ parameter from rendering within this
command when type_ is None. Pull request courtesy David Hills.
References: #1300
[bug] [commmands] Fixed issue where the revision_environment directive in alembic.ini
was ignored by the alembic merge command, leading to issues when other
configurational elements depend upon env.py being invoked within the
command.
References: #1299
[bug] [autogenerate] Fixed issue where the ForeignKeyConstraint.match parameter would not be
rendered in autogenerated migrations. Pull request courtesy Asib
Kamalsada.
References: #1302
[bug] [autogenerate] [postgresql] Improved autogenerate compare of expression based indexes on PostgreSQL to produce fewer wrong detections.
Released: August 16, 2023
[bug] [autogenerate] [postgresql] Improved autogenerate compare of expression based indexes on PostgreSQL to produce fewer wrong detections.
References: #1270
[bug] [autogenerate] Fixed issue with NULLS NOT DISTINCT detection in postgresql that
would keep detecting changes in the index or unique constraint.
References: #1291
[bug] [commands] Added encoding="locale" setting to the use of Python's
ConfigParser.read(), so that a warning is not generated when using the
recently added Python feature PYTHONWARNDEFAULTENCODING specified in
PEP 597. The encoding is passed as the "locale" string under Python
3.10 and greater, which indicates that the system-level locale should be
used, as was the case already here. Pull request courtesy Kevin Kirsche.
References: #1273
[feature] [operations] Added parameters if_exists and if_not_exists for index operations. Pull request courtesy of Max Adrian.
Released: August 4, 2023
[feature] [operations] Added parameters if_exists and if_not_exists for index operations. Pull request courtesy of Max Adrian.
References: #151
[usecase] [typing] Added typing to the default script mako templates.
References: #1253
[usecase] [autogenerate] Added support in autogenerate for NULLS NOT DISTINCT in the PostgreSQL dialect.
References: #1248
[bug] Fixed format string logged when running a post write hook Pull request curtesy of Mathieu Défosse.
References: #1261
However, two of these changes were identified as possibly problematic without a more formal deprecation warning being emitted which were the table_nam…
Released: May 17, 2023
[bug] [autogenerate] [regression] As Alembic 1.11.0 is considered a major release (Alembic does not use
semver, nor does its parent project SQLAlchemy; this has been
clarified <versioning_scheme> in the documentation), change
#1130 modified calling signatures for most operations to consider
all optional keyword parameters to be keyword-only arguments, to match what
was always documented and generated by autogenerate. However, two of these
changes were identified as possibly problematic without a more formal
deprecation warning being emitted which were the table_name parameter
to Operations.drop_index(), which was generated positionally by
autogenerate prior to version 0.6.3 released in 2014, and type_ in
Operations.drop_constraint() and
BatchOperations.drop_constraint(), which was documented positionally
in one example in the batch documentation.
These two signatures have been restored to allow those particular parameters to be passed positionally. A future change will include formal deprecation paths (with warnings) for these arguments where they will again become keyword-only in a future "Significant Minor" release.
[bug] [typing] Fixed typing use of ~sqlalchemy.schema.Column and other
generic SQLAlchemy classes.
References: #1246
[bug] [regression] [typing] Restored the output type of Config.get_section() to include
Dict[str, str] as a potential return type, which had been changed to
immutable Mapping[str, str]. When a section is returned and the default
is not used, a mutable dictionary is returned.
References: #1244
[usecase] [commands] Added quiet option to the command line, using the -q/--quiet option. This flag will prevent alembic from logging anything to stdo
Released: May 15, 2023
[usecase] [commands] Added quiet option to the command line, using the -q/--quiet
option. This flag will prevent alembic from logging anything
to stdout.
References: #1109
[usecase] [asyncio] Added AbstractOperations.run_async() to the operation module to
allow running async functions in the upgrade or downgrade migration
function when running alembic using an async dialect. This function will
receive as first argument an
~sqlalchemy.ext.asyncio.AsyncConnection sharing the transaction
used in the migration context.
References: #1231
[bug] [batch] Added placeholder classes for ~.sqla.Computed and
~.sqla.Identity when older 1.x SQLAlchemy versions are in use,
namely prior to SQLAlchemy 1.3.11 when the ~.sqla.Computed
construct was introduced. Previously these were set to None, however this
could cause issues with certain codepaths that were using isinstance()
such as one within "batch mode".
References: #1237
[bug] [batch] Correctly pass previously ignored arguments insert_before and
insert_after in batch_alter_column
References: #1221
[bug] [postgresql] Fix autogenerate issue with PostgreSQL ExcludeConstraint
that included sqlalchemy functions. The function text was previously
rendered as a plain string without surrounding with text().
References: #1230
[bug] [mysql] [regression] Fixed regression caused by #1166 released in version 1.10.0 which caused MySQL unique constraints with multiple columns to not compare correctly within autogenerate, due to different sorting rules on unique constraints vs. indexes, which in MySQL are shared constructs.
References: #1240
[bug] [typing] Updated stub generator script to also add stubs method definitions for the
Operations class and the BatchOperations class obtained
from Operations.batch_alter_table(). As part of this change, the
class hierarchy of Operations and BatchOperations has
been rearranged on top of a common base class AbstractOperations
in order to type correctly, as BatchOperations uses different
method signatures for operations than Operations.
References: #1093
[bug] [typing] Repaired the return signatures for Operations that mostly
return None, and were erroneously referring to Optional[Table]
in many cases.
[bug] [autogenerate] Modified the autogenerate implementation for comparing "server default"
values from user-defined metadata to not apply any quoting to the value
before comparing it to the server-reported default, except for within
dialect-specific routines as needed. This change will affect the format of
the server default as passed to the
EnvironmentContext.configure.compare_server_default hook, as
well as for third party dialects that implement a custom
compare_server_default hook in their alembic impl, to be passed "as is"
and not including additional quoting. Custom implementations which rely
on this quoting should adjust their approach based on observed formatting.
References: #1178
[bug] [api] [autogenerate] Fixed issue where autogenerate.render_python_code() function did not
provide a default value for the user_module_prefix variable, leading to
NoneType errors when autogenerate structures included user-defined
types. Added new parameter
autogenerate.render_python_code.user_module_prefix to allow
this to be set as well as to default to None. Pull request courtesy
tangkikodo.
References: #1235
[change] [py3k] Argument signatures of Alembic operations now enforce keyword-only
arguments as passed as keyword and not positionally, such as
Operations.create_table.schema,
Operations.add_column.type_, etc.
References: #1130
[misc] Update code snippets within docstrings to use black code formatting.
Pull request courtesy of James Addison.
References: #1220
[bug] [operations] Fixed issue where using a directive such as op.create_foreign_key() to create a self-referential constraint on a single table where
Released: April 24, 2023
[bug] [operations] Fixed issue where using a directive such as op.create_foreign_key() to
create a self-referential constraint on a single table where the same
column were present on both sides (e.g. within a composite foreign key)
would produce an error under SQLAlchemy 2.0 and a warning under SQLAlchemy
1.4 indicating that a duplicate column were being added to a table.
References: #1215
[autogenerate] [postgresql] Added support for autogenerate comparison of indexes on PostgreSQL which
include SQL sort option, such as ASC or NULLS FIRST.
References: #1213
Released: April 24, 2023
[feature] [autogenerate] [postgresql] ¶ Added support for autogenerate comparison of indexes on PostgreSQL which include SQL sort option, such as ASC or NULLS FIRST . The sort options are correctly detected only when defined using the sqlalchemy modifier functions, such as asc() or nulls_first() , or the equivalent methods. Passing sort options inside the postgresql_ops dict is not supported.
References: #1213
[bug] [operations] ¶ Fixed issue where using a directive such as op.create_foreign_key() to create a self-referential constraint on a single table where the same column were present on both sides (e.g. within a composite foreign key) would produce an error under SQLAlchemy 2.0 and a warning under SQLAlchemy 1.4 indicating that a duplicate column were being added to a table.
References: #1215
[bug] [typing] Fixed various typing issues observed with pyright, including issues involving the combination of Function and MigrationContext.begin_tr
Released: April 5, 2023
[bug] [typing] Fixed various typing issues observed with pyright, including issues
involving the combination of Function and
MigrationContext.begin_transaction().
[bug] [autogenerate] Fixed error raised by alembic when running autogenerate after removing a function based index.
References: #1212
[bug] [ops] Fixed regression where Alembic would not run with older SQLAlchemy 1.3 versions prior to 1.3.24 due to a missing symbol. Workarounds have
Released: March 8, 2023
[bug] [ops] Fixed regression where Alembic would not run with older SQLAlchemy 1.3 versions prior to 1.3.24 due to a missing symbol. Workarounds have been applied for older 1.3 versions.
References: #1196
[bug] [postgresql] Fixed issue regarding PostgreSQL ExcludeConstraint, where constraint elements which made use of literal_column() could not be rende
Released: March 6, 2023
[bug] [postgresql] Fixed issue regarding PostgreSQL ExcludeConstraint, where
constraint elements which made use of literal_column() could not be
rendered for autogenerate. Additionally, using SQLAlchemy 2.0.5 or greater,
text() constructs are also supported within PostgreSQL
ExcludeConstraint objects for autogenerate render. Pull request
courtesy Jan Katins.
References: #1184
[bug] [batch] [regression] Fixed regression for 1.10.0 where Constraint objects were
suddenly required to have non-None name fields when using batch mode, which
was not previously a requirement.
References: #1195
[feature] [revisioning] Recursive traversal of revision files in a particular revision directory is now supported, by indicating recursive_version_loc
Released: March 5, 2023
[feature] [revisioning] Recursive traversal of revision files in a particular revision directory is
now supported, by indicating recursive_version_locations = true in
alembic.ini. Pull request courtesy ostr00000.
References: #760
[bug] [autogenerate] Fixed issue in index detection where autogenerate change detection would consider indexes with the same columns but with different order as equal, while in general they are not equivalent in how a database will use them.
References: #1166
[bug] [autogenerate] [sqlite] Fixed issue where indexes on SQLite which include SQL expressions would not compare correctly, generating false positives under autogenerate. These indexes are now skipped, generating a warning, in the same way that expression-based indexes on PostgreSQL are skipped and generate warnings when SQLAlchemy 1.x installations are in use. Note that reflection of SQLite expression-based indexes continues to not yet be supported under SQLAlchemy 2.0, even though PostgreSQL expression-based indexes have now been implemented.
References: #1165
[bug] [mssql] Properly escape constraint name on SQL Server when dropping
a column while specifying mssql_drop_default=True or
mssql_drop_check=True or mssql_drop_foreign_key=True.
References: #1187
[bug] [mssql] Ongoing fixes for SQL Server server default comparisons under autogenerate, adjusting for SQL Server's collapsing of whitespace between
Released: February 16, 2023
[bug] [mssql] Ongoing fixes for SQL Server server default comparisons under autogenerate, adjusting for SQL Server's collapsing of whitespace between SQL function arguments when reporting on a function-based server default, as well as its arbitrary addition of parenthesis within arguments; the approach has now been made more aggressive by stripping the two default strings to compare of all whitespace, parenthesis, and quoting characters.
References: #1177
[bug] [postgresql] Fixed PostgreSQL server default comparison to handle SQL expressions
sent as text() constructs, such as text("substring('name', 1, 3)"),
which previously would raise errors when attempting to run a server-based
comparison.
[bug] [autogenerate] Removed a mis-use of the
EnvironmentContext.configure.render_item callable where the
"server_default" renderer would be erroneously used within the server
default comparison process, which is working against SQL expressions, not
Python code.
References: #1180
[bug] [commands] Fixed regression introduced in 1.7.0 where the "config" object passed to
the template context when running the merge() command
programmatically failed to be correctly populated. Pull request courtesy
Brendan Gann.
[bug] [autogenerate] Fixed issue where rendering of user-defined types that then went onto use the .with_variant() method would fail to render, if usi
Released: February 7, 2023
[bug] [autogenerate] Fixed issue where rendering of user-defined types that then went onto use
the .with_variant() method would fail to render, if using SQLAlchemy
2.0's version of variants.
References: #1167
[bug] [typing] Fixed typing definitions for EnvironmentContext.get_x_argument().
Released: January 14, 2023
[bug] [typing] Fixed typing definitions for EnvironmentContext.get_x_argument().
Typing stubs are now generated for overloaded proxied methods such as
EnvironmentContext.get_x_argument().
[bug] [autogenerate] Fixed regression caused by #1145 where the string transformations
applied to server defaults caused expressions such as (getdate()) to no
longer compare as equivalent on SQL Server, others.
References: #1152
[bug] [autogenerate] Fixed issue where server default compare would not work for string defaults that contained backslashes, due to mis-rendering of t
Released: December 23, 2022
[bug] [autogenerate] Fixed issue where server default compare would not work for string defaults that contained backslashes, due to mis-rendering of these values when comparing their contents.
References: #1145
[bug] [oracle] Implemented basic server default comparison for the Oracle backend; previously, Oracle's formatting of reflected defaults prevented any matches from occurring.
[bug] [sqlite] Adjusted SQLite's compare server default implementation to better handle defaults with or without parens around them, from both the reflected and the local metadata side.
[bug] [mssql] Adjusted SQL Server's compare server default implementation to better handle defaults with or without parens around them, from both the reflected and the local metadata side.
[feature] [commands] Added new Alembic command alembic check. This performs the widely requested feature of running an "autogenerate" comparison betwe
Released: December 15, 2022
[feature] [commands] Added new Alembic command alembic check. This performs the widely
requested feature of running an "autogenerate" comparison between the
current database and the MetaData that's currently set up for
autogenerate, returning an error code if the two do not match, based on
current autogenerate settings. Pull request courtesy Nathan Louie.
References: #724
[bug] [tests] Fixed issue in tox.ini file where changes in the tox 4.0 series to the format of "passenv" caused tox to not function correctly, in particular raising an error as of tox 4.0.6.
[bug] [typing] Fixed typing issue where revision.process_revision_directives
was not fully typed; additionally ensured all Callable and Dict
arguments to EnvironmentContext.configure() include parameters in
the typing declaration.
Additionally updated the codebase for Mypy 0.990 compliance.
References: #1110
[bug] [sqlite] Fixed bug where the SQLite implementation of Operations.rename_table() would render an explicit schema name for both the old and new ta
Released: July 13, 2022
[bug] [sqlite] Fixed bug where the SQLite implementation of
Operations.rename_table() would render an explicit schema name for
both the old and new table name, which while is the standard ALTER syntax,
is not accepted by SQLite's syntax which doesn't support a rename across
schemas. In particular, the syntax issue would prevent batch mode from
working for SQLite databases that made use of attached databases (which are
treated as "schemas" in SQLAlchemy).
References: #1065
[bug] [batch] Added an error raise for the condition where
Operations.batch_alter_table() is used in --sql mode, where the
operation requires table reflection, as is the case when running against
SQLite without giving it a fixed Table object. Previously the operation
would fail with an internal error. To get a "move and copy" batch
operation as a SQL script without connecting to a database,
a Table object should be passed to the
Operations.batch_alter_table.copy_from parameter so that
reflection may be skipped.
References: #1021
[changed] [installation] Alembic 1.8 now supports Python 3.7 and above.
Released: May 31, 2022
[changed] [installation] Alembic 1.8 now supports Python 3.7 and above.
References: #1025
[changed] [environment] The "Pylons" environment template has been removed as of Alembic 1.8. This template was based on the very old pre-Pyramid Pylons web framework which has been long superseded by Pyramid.
References: #987
[feature] [typing] PEP 484 typing annotations have been added to the env.py and
revision template files within migration templates. Pull request by Nikita
Sobolev.
References: #764
[usecase] [operations] The op.drop_table() operation directive will now trigger the
before_drop() and after_drop() DDL event hooks at the table level,
which is similar to how the before_create() and after_create()
hooks are triggered by the op.create_table() directive. Note that as
op.drop_table() accepts only a table name and optional schema name, the
Table object received by the event will not have any information within
it other than the table name and schema name.
References: #1037
[usecase] [commands] Added new token epoch to the file_template option, which will
populate the integer epoch as determined by int(create_date.timestamp()).
Pull request courtesy Caio Carvalho.
References: #1027
[bug] [revisioning] Fixed issue where a downgrade using a relative revision would fail in case of multiple branches with a single effectively head due to interdependencies between revisions.
References: #1026
[bug] [batch] Fixed issue in batch mode where CREATE INDEX would not use a new column name in the case of a column rename.
References: #1034
[bug] [operations] Fixed issue where using Operations.create_table() in conjunction with a CheckConstraint that referred to table-bound Column objects
Released: March 14, 2022
[bug] [operations] Fixed issue where using Operations.create_table() in conjunction
with a CheckConstraint that referred to table-bound
Column objects rather than string expressions would be added to
the parent table potentially multiple times, resulting in an incorrect DDL
sequence. Pull request courtesy Nicolas CANIART.
References: #1004
[bug] [environment] The logging.fileConfig() line in env.py templates, which is used
to setup Python logging for the migration run, is now conditional on
Config.config_file_name not being None. Otherwise, the line
is skipped as there is no default logging configuration present.
References: #986
[bug] [mssql] Fixed bug where an Operations.alter_column() operation would change
a "NOT NULL" column to "NULL" by emitting an ALTER COLUMN statement that
did not specify "NOT NULL". (In the absence of "NOT NULL" T-SQL was
implicitly assuming "NULL"). An Operations.alter_column() operation
that specifies Operations.alter_column.type should also
specify include either Operations.alter_column.nullable or
Operations.alter_column.existing_nullable to inform Alembic as
to whether the emitted DDL should include "NULL" or "NOT NULL"; a warning
is now emitted if this is missing under this scenario.
References: #977
[usecase] [commands] Add a new command alembic ensure_version, which will ensure that the Alembic version table is present in the target database, but
Released: February 1, 2022
[usecase] [commands] Add a new command alembic ensure_version, which will ensure that the
Alembic version table is present in the target database, but does not
alter its contents. Pull request courtesy Kai Mueller.
References: #964
[bug] [batch] [regression] Fixed regression where usage of a with_variant() datatype in
conjunction with the existing_type option of op.alter_column()
under batch mode would lead to an internal exception.
References: #982
[bug] [autogenerate] Implemented support for recognizing and rendering SQLAlchemy "variant" types going forward into SQLAlchemy 2.0, where the architecture of "variant" datatypes will be changing.
[bug] [autogenerate] [mysql] Added a rule to the MySQL impl so that the translation between JSON / LONGTEXT is accommodated by autogenerate, treating LONGTEXT from the server as equivalent to an existing JSON in the model.
References: #968
[bug] [tests] Adjustments to the test suite to accommodate for error message changes occurring as of SQLAlchemy 1.4.27.
Released: November 11, 2021
[bug] [regression] Fixed a regression that prevented the use of post write hooks on python version lower than 3.9
Released: October 6, 2021
[bug] [regression] Fixed a regression that prevented the use of post write hooks on python version lower than 3.9
References: #934
[bug] [environment] Fixed issue where the MigrationContext.autocommit_block() feature
would fail to function when using a SQLAlchemy engine using 2.0 future
mode.
References: #944
[bug] [mypy] Fixed type annotations for the "constraint_name" argument of operations create_primary_key(), create_foreign_key(). Pull request courtesy
Released: September 17, 2021
[bug] [mypy] Fixed type annotations for the "constraint_name" argument of operations
create_primary_key(), create_foreign_key(). Pull request courtesy
TilmanK.
References: #914
[bug] [typing] Added missing attributes from context stubs.
Released: September 17, 2021
[bug] [typing] Added missing attributes from context stubs.
References: #900
[bug] [mypy] Fixed an import in one of the .pyi files that was triggering an assertion error in some versions of mypy.
References: #897
[bug] [ops] [regression] Fixed issue where registration of custom ops was prone to failure due to
the registration process running exec() on generated code that as of
the 1.7 series includes pep-484 annotations, which in the case of end user
code would result in name resolution errors when the exec occurs. The logic
in question has been altered so that the annotations are rendered as
forward references so that the exec() can proceed.
References: #920
[bug] [installation] Corrected "universal wheel" directive in setup.cfg so that building a wheel does not target Python 2. The PyPi files index for 1.
Released: August 30, 2021
[bug] [installation] Corrected "universal wheel" directive in setup.cfg so that building a wheel does not target Python 2. The PyPi files index for 1.7.0 was corrected manually. Pull request courtesy layday.
References: #893
[bug] [pep484] Fixed issue in generated .pyi files where default values for Optional
arguments were missing, thereby causing mypy to consider them as required.
References: #895
[bug] [batch] [regression] Fixed regression in batch mode due to #883 where the "auto" mode
of batch would fail to accommodate any additional migration directives
beyond encountering an add_column() directive, due to a mis-application
of the conditional logic that was added as part of this change, leading to
"recreate" mode not being used in cases where it is required for SQLite
such as for unique constraints.
References: #896
[changed] [installation] Alembic 1.7 now supports Python 3.6 and above; support for prior versions including Python 2.7 has been dropped.
Released: August 30, 2021
[changed] [installation] Alembic 1.7 now supports Python 3.6 and above; support for prior versions including Python 2.7 has been dropped.
[changed] [installation] Make the python-dateutil library an optional dependency.
This library is only required if the timezone option
is used in the Alembic configuration.
An extra require named tz is available with
pip install alembic[tz] to install it.
References: #674
[changed] [installation] The dependency on pkg_resources which is part of setuptools has
been removed, so there is no longer any runtime dependency on
setuptools. The functionality has been replaced with
importlib.metadata and importlib.resources which are both part of
Python std.lib, or via pypy dependency importlib-metadata for Python
version < 3.8 and importlib-resources for Python version < 3.9
(while importlib.resources was added to Python in 3.7, it did not include
the "files" API until 3.9).
References: #885
[feature] [environment] Enhance version_locations parsing to handle paths containing spaces.
The new configuration option version_path_separator specifies the
character to use when splitting the version_locations string. The
default for new configurations is version_path_separator = os,
which will use os.pathsep (e.g., ; on Windows).
References: #842
[feature] [tests] Created a "test suite" similar to the one for SQLAlchemy, allowing developers of third-party dialects to test their code against a set of Alembic tests that have been specially selected to exercise back-end database operations. At the time of release, third-party dialects that have adopted the Alembic test suite to verify compatibility include CockroachDB and SAP ASE (Sybase).
References: #855
[feature] [general] pep-484 type annotations have been added throughout the library.
Additionally, stub .pyi files have been added for the "dynamically"
generated Alembic modules alembic.op and alembic.config, which
include complete function signatures and docstrings, so that the functions
in these namespaces will have both IDE support (vscode, pycharm, etc) as
well as support for typing tools like Mypy. The files themselves are
statically generated from their source functions within the source tree.
[usecase] [batch] Named CHECK constraints are now supported by batch mode, and will
automatically be part of the recreated table assuming they are named. They
also can be explicitly dropped using op.drop_constraint(). For
"unnamed" CHECK constraints, these are still skipped as they cannot be
distinguished from the CHECK constraints that are generated by the
Boolean and Enum datatypes.
Note that this change may require adjustments to migrations that drop or
rename columns which feature an associated named check constraint, such
that an additional op.drop_constraint() directive should be added for
that named constraint as there will no longer be an associated column
for it; for the Boolean and Enum datatypes, an existing_type
keyword may be passed to BatchOperations.drop_constraint as well.
References: #884
[bug] [operations] Fixed regression due to #803 where the .info and .comment
attributes of Table would be lost inside of the DropTableOp
class, which when "reversed" into a CreateTableOp would then have
lost these elements. Pull request courtesy Nicolas CANIART.
References: #879
[bug] [batch] [sqlite] Batch "auto" mode will now select for "recreate" if the add_column()
operation is used on SQLite, and the column itself meets the criteria for
SQLite where ADD COLUMN is not allowed, in this case a functional or
parenthesized SQL expression or a Computed (i.e. generated) column.
References: #883
[bug] [commands] Re-implemented the python-editor dependency as a small internal
function to avoid the need for external dependencies.
References: #856
[bug] [postgresql] Fixed issue where usage of the PostgreSQL postgresql_include option
within a Operations.create_index() would raise a KeyError, as the
additional column(s) need to be added to the table object used by the
construct internally. The issue is equivalent to the SQL Server issue fixed
in #513. Pull request courtesy Steven Bronson.
References: #874
[bug] [autogenerate] Fixed issue where dialect-specific keyword arguments within the DropIndex operation directive would not render in the autogenerat
Released: May 27, 2021
[bug] [autogenerate] Fixed issue where dialect-specific keyword arguments within the
DropIndex operation directive would not render in the
autogenerated Python code. As support was improved for adding dialect
specific arguments to directives as part of #803, in particular
arguments such as "postgresql_concurrently" which apply to the actual
create/drop of the index, support was needed for these to render even in a
drop index operation. Pull request courtesy Jet Zhou.
References: #849
[bug] [op directives] [regression] Fixed regression caused by just fixed #844 that scaled back the filter for unique=True/index=True too far such that
[bug] [autogenerate] [regression] Fixed 1.6-series regression where UniqueConstraint and to a lesser extent Index objects would be doubled up in the g
Released: May 21, 2021
[bug] [autogenerate] [regression] Fixed 1.6-series regression where UniqueConstraint and to a lesser
extent Index objects would be doubled up in the generated model when
the unique=True / index=True flags were used.
References: #844
[bug] [autogenerate] Fixed a bug where paths defined in post-write hook options would be wrongly escaped in non posix environment (Windows).
References: #839
[bug] [regression] [versioning] Fixed regression where a revision file that contained its own down revision as a dependency would cause an endless loop in the traversal logic.
References: #843
[bug] [regression] [versioning] Fixed additional regression nearly the same as that of #838 just released in 1.6.1 but within a slightly different cod
[bug] [regression] [versioning] Fixed regression in new revisioning traversal where "alembic downgrade base" would fail if the database itself were cl
Released: May 6, 2021
[bug] [regression] [versioning] Fixed regression in new revisioning traversal where "alembic downgrade base" would fail if the database itself were clean and unversioned; additionally repairs the case where downgrade would fail if attempting to downgrade to the current head that is already present.
References: #838
…and maintainability. This change includes that a deprecation warning is emitted if an ambiguous command such as "downgrade -1" when multiple heads are…
Released: May 3, 2021
[feature] [autogenerate] Fix the documentation regarding the default command-line argument position of
the revision script filename within the post-write hook arguments. Implement a
REVISION_SCRIPT_FILENAME token, enabling the position to be changed. Switch
from str.split() to shlex.split() for more robust command-line argument
parsing.
References: #819
[feature] Implement a .cwd (current working directory) suboption for post-write hooks
(of type console_scripts). This is useful for tools like pre-commit, which
rely on the working directory to locate the necessary config files. Add
pre-commit as an example to the documentation. Minor change: rename some variables
from ticket #819 to improve readability.
References: #822
[bug] [autogenerate] Refactored the implementation of MigrateOperation constructs such
as CreateIndexOp, CreateTableOp, etc. so that they no
longer rely upon maintaining a persistent version of each schema object
internally; instead, the state variables of each operation object will be
used to produce the corresponding construct when the operation is invoked.
The rationale is so that environments which make use of
operation-manipulation schemes such as those those discussed in
autogen_rewriter are better supported, allowing end-user code to
manipulate the public attributes of these objects which will then be
expressed in the final output, an example is
some_create_index_op.kw["postgresql_concurrently"] = True.
Previously, these objects when generated from autogenerate would typically hold onto the original, reflected element internally without honoring the other state variables of each construct, preventing the public API from working.
References: #803
[bug] [environment] Fixed regression caused by the SQLAlchemy 1.4/2.0 compatibility switch
where calling .rollback() or .commit() explicitly within the
context.begin_transaction() context manager would cause it to fail when
the block ended, as it did not expect that the transaction was manually
closed.
References: #829
[bug] [autogenerate] Improved the rendering of op.add_column() operations when adding
multiple columns to an existing table, so that the order of these
statements matches the order in which the columns were declared in the
application's table metadata. Previously the added columns were being
sorted alphabetically.
References: #827
[bug] [versioning] The algorithm used for calculating downgrades/upgrades/iterating revisions has been rewritten, to resolve ongoing issues of branches not being handled consistently particularly within downgrade operations, as well as for overall clarity and maintainability. This change includes that a deprecation warning is emitted if an ambiguous command such as "downgrade -1" when multiple heads are present is given.
In particular, the change implements a long-requested use case of allowing downgrades of a single branch to a branchpoint.
Huge thanks to Simon Bowly for their impressive efforts in successfully tackling this very difficult problem.
[bug] [batch] Added missing batch_op.create_table_comment(),
batch_op.drop_table_comment() directives to batch ops.
References: #799
Your coding agent can read these notes before it upgrades. Set up the MCP server →