Mike Bayer [Tue, 24 Jun 2025 18:04:56 +0000 (14:04 -0400)]
try flake8-import-order 0.19.2
the big new thang is that it is doing import order checks inside of
TYPE_CHECKING blocks. Introduces some new codes that we
enthusiastically add to our ignore list.
Justin Malin [Thu, 12 Jun 2025 19:56:36 +0000 (15:56 -0400)]
[Fixes #1671] Passthrough `dialect_kwargs` to `ops.create_foreign_key()`
<!-- Provide a general summary of your proposed changes in the Title field above -->
### Description
<!-- Describe your changes in detail -->
Fixes #1671
SqlAlchemy supports adding dialect kwargs for foreign keys, as does `op.create_foreign_key()`, but the renderer for `ops.CreateForeignKeyOp` does not pass through `dialect_kwargs`. An example of this is `postgresql_not_valid`.
### Checklist
<!-- go over following points. check them with an `x` if they do apply, (they turn into clickable checkboxes once the PR is submitted, so no need to do everything at once)
-->
This pull request is:
- [ ] A documentation / typographical error fix
- Good to go, no issue or tests are needed
- [x] A short code fix
- please include the issue number, and create an issue if none exists, which
must include a complete example of the issue. one line code fixes without an
issue and demonstration will not be accepted.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests. one line code fixes without tests will not be accepted.
- [ ] A new feature implementation
- please include the issue number, and create an issue if none exists, which must
include a complete example of how the feature would look.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.
Mike Bayer [Sun, 8 Jun 2025 20:14:19 +0000 (16:14 -0400)]
updates for mypy 1.16
some errors go away, others come in. basically moving
ignores around. need to pin to 1.16 at the lowest as these
would now fail on earlier mypy versions
Simon Tas [Thu, 29 May 2025 00:11:58 +0000 (20:11 -0400)]
allow tuple type in down_revision in migration templates
<!-- Provide a general summary of your proposed changes in the Title field above -->
FIXES #1665
Currently the type of `down_revision` in migration templates is `Union[str, None]`. However, when you generate a migration using `alembic merge heads` it will generate a migration with a tuple of strings in `down_revision` which causes a type error.
### Description
f.e. when you have 2 heads and run `alembic merge heads` you will get a migration that looks like this:
which will give a type error with type checkers like mypy and pyright. This change fixes this. From the code it seems like just like `branch_labels` and `depends_on` the `down_revision` is first casted to a tuple if needed so typing it as `Sequence[str]` and not `Tuple[str, ...]` should be safe.
### Checklist
<!-- go over following points. check them with an `x` if they do apply, (they turn into clickable checkboxes once the PR is submitted, so no need to do everything at once)
-->
This pull request is:
- [ ] A documentation / typographical error fix
- Good to go, no issue or tests are needed
- [x] A short code fix
- please include the issue number, and create an issue if none exists, which
must include a complete example of the issue. one line code fixes without an
issue and demonstration will not be accepted.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests. one line code fixes without tests will not be accepted.
- [ ] A new feature implementation
- please include the issue number, and create an issue if none exists, which must
include a complete example of how the feature would look.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.
Mike Bayer [Wed, 21 May 2025 21:14:37 +0000 (17:14 -0400)]
honor get_templates_path() first
Fixed regression caused by the ``pathlib`` refactoring that removed the use
of :meth:`.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.
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.
Mike Bayer [Wed, 21 May 2025 14:09:46 +0000 (10:09 -0400)]
ensure conv is applied to all reflected index and constraint names
The autogenerate process will now apply the :meth:`.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.
Mike Bayer [Wed, 21 May 2025 03:40:33 +0000 (23:40 -0400)]
more tweaks
this is primarily cleanup of the changelog section which is
extensive for this release.
Additionally, limited Config.config_file_name and Config.toml_file_name
to string only when accessed, making use of _preserving_path_as_str()
for these on the parameter side.
Jens Troeger [Tue, 20 May 2025 21:01:45 +0000 (17:01 -0400)]
Replace use of utcnow() with now() for Python 3.13 compatibility, Fixes #1643
Fixed issue where use of deprecated ``utcnow()`` function would generate
warnings. Has been replaced with ``now(UTC)``. Pull request courtesy
Jens Tröger.
Mike Bayer [Tue, 20 May 2025 20:32:31 +0000 (16:32 -0400)]
now get %(here)s to work for all special pyproject config values
batting 1000 here, the %(here)s token was totally not handled
in any of version_locations, prepend_sys_path_paths, post_write_hooks.
All params that definitely need this token.
Mike Bayer [Tue, 20 May 2025 19:17:54 +0000 (15:17 -0400)]
make sure no-ini-file actually works
because Config has an alembic.ini path in it by default, if the file
doesnt exist it will raise when you call get_main_option(). make sure
no alembic function calls upon get_main_option() directly at all so that
configparser is entirely not required
Mike Bayer [Tue, 20 May 2025 14:12:30 +0000 (10:12 -0400)]
use Path.name for split target
some code dealing with .pyc names that needs the first token of the
dot-separated filename is clearer based on path.name, full filename,
rather than .stem
Mike Bayer [Mon, 19 May 2025 17:06:56 +0000 (13:06 -0400)]
use pathlib for file operations across the board
The command, config and script modules now rely on ``pathlib.Path`` for
internal path manipulations, instead of ``os.path()`` operations. Public
API functions that accept string directories and filenames continue to do
so but also accept ``os.PathLike`` objects. Public API functions and
accessors that return paths as strings continue to do so. Private API
functions and accessors, i.e. all those that are prefixed with an
underscore, may now return a Path object rather than a string to indicate
file paths.
Mike Bayer [Mon, 19 May 2025 16:24:44 +0000 (12:24 -0400)]
add autogen render for drop_constraint.if_exists
I've maintained all along that #1650 and #1626 are the same thing
and should have been one big PR. Here we complete the autogen
portion of the #1650 PR that was omitted.
Add support of IF [NOT] EXISTS for ADD/DROP COLUMN in Postgresql
Added :paramref:`.Operations.add_column.if_not_exists` and
:paramref:`.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 turned on via a custom :class:`.Rewriter`. Pull request courtesy of
Louis-Amaury Chaib (@lachaib).
Mike Bayer [Tue, 13 May 2025 14:14:10 +0000 (10:14 -0400)]
allow pep 621 configuration
Added optional :pep:`621` support to Alembic, where a subset of the
project-centric configuration normally found in the ``alembic.ini`` file
can now be retrieved from the project-wide ``pyproject.toml`` file. A new
init template ``pyproject`` is added which illustrates a basic :pep:`621`
setup. The :pep:`621` feature supports configuration values that are
relevant to code locations and code production only; it does not
accommodate database connectivity, configuration, or logging configuration.
These latter configurational elements remain as elements that can be
present either in the ``alembic.ini`` file, or retrieved elsewhere within
the ``env.py`` file. The change also allows the ``alembic.ini`` file to
be completely optional if the ``pyproject.toml`` file contains a base
alembic configuration section.
<!-- Provide a general summary of your proposed changes in the Title field above -->
### Description
Rendering ExecuteSQLOp did not respect the `alembic_module_prefix` setting due
to having `op.` hard-coded in its template.
This change updates the render logic to use the same
`_alembic_autogenerate_prefix()` as it seems the rest of the ops use.
### Checklist
This pull request is:
- [ ] A documentation / typographical error fix
- Good to go, no issue or tests are needed
- [x] A short code fix
- please include the issue number, and create an issue if none exists, which
must include a complete example of the issue. one line code fixes without an
issue and demonstration will not be accepted.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests. one line code fixes without tests will not be accepted.
- [ ] A new feature implementation
- please include the issue number, and create an issue if none exists, which must
include a complete example of how the feature would look.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.
Mike Werezak [Sat, 26 Apr 2025 18:57:24 +0000 (14:57 -0400)]
Add file_path_separator to apply to all path splitting
Added new option to the ConfigParser config (typically via ``alembic.ini``)
``path_separator``. This new option supersedes the previous similar
option ``version_path_separator``. The new ``path_separator`` option
applies to the path splitting mechanism of both the ``version_locations``
option as well as the ``prepend_sys_path`` option, and in newly
rendered ``alembic.ini`` files will use the value ``os``, which means to
use the operating system path separator when splitting these string values
into a list of paths.
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 do not have ``path_separator`` present
will continue to make use of ``version_path_separator`` when parsing the
``version_locations`` option, or splitting on spaces / commas if
``version_path_separator`` is also not present. ``prepend_sys_path`` will
continue to be split on spaces/commas/colons if ``path_separator`` is
not present. Under all of these fallback conditions, a deprecation
warning is now emitted encouraging to set ``path_separator``.
Pull request courtesy Mike Werezak.
This change also begins to move some of the role of interpreting
of specific config options into the Config object. This process will
continue as we look to add toml support to config.
Mike Bayer [Wed, 7 May 2025 15:34:49 +0000 (11:34 -0400)]
use pep639
The pyproject.toml 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.
Also bump black, flake8, see what's coming.
this change is modeled after the same change made in dogpile.cache
which has since been released.
Added new :meth:`.CommandLine.register_command` method to
:class:`.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.
Added :paramref:`.op.drop_constraint.if_exists` parameter to
:func:`.op.drop_constraint` which will render "DROP CONSTRAINT IF EXISTS".
Pull request courtesy Aaron Griffin.
Also attempting to fix unrelated issue w/ test_stubs and python
versions which may be in a separate patch if it can't work here
Follow-up commit db12e1918556dd463847db9ffb3e761231df9b1d (which is probably sufficient for type checking) by making all annotations of server_default consistent.
The docstring of `alter_column` states: "Set to `None` to have the default removed". The type hint should accept None.
### Checklist
This pull request is:
- [ ] A documentation / typographical error fix
- Good to go, no issue or tests are needed
- [x] A short code fix
- please include the issue number, and create an issue if none exists, which
must include a complete example of the issue. one line code fixes without an
issue and demonstration will not be accepted.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests. one line code fixes without tests will not be accepted.
- [ ] A new feature implementation
- please include the issue number, and create an issue if none exists, which must
include a complete example of how the feature would look.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.
el [Fri, 28 Mar 2025 13:22:29 +0000 (09:22 -0400)]
fix AlterColumnOp modify_name ignorance
Fixed issue where the "modified_name" of :class:`.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.
DanCardin [Tue, 4 Mar 2025 21:07:59 +0000 (16:07 -0500)]
Add TextClause to alter_column's server_default fields.
Given sqlalchemy models with server_defaults, alembic may autogenerate
`existing_server_default=sa.text("...")`, which fails typechecking on
the resultant migration because `TextClause` is not currently a valid
annotated type.
Mike Bayer [Tue, 4 Mar 2025 19:33:59 +0000 (14:33 -0500)]
fix template files include
Fixed an issue in the new :pep:`621` ``pyproject.toml`` layout that
prevented Alembic's template files from being included in the ``.whl`` file
in the distribution.
Mike Bayer [Wed, 26 Feb 2025 14:09:51 +0000 (09:09 -0500)]
dont stringify uq deferrable
Fixed autogenerate rendering bug where the ``deferrable`` element of
``UniqueConstraint``, a bool, were being stringified rather than repr'ed
when generating Python code.
Mike Bayer [Thu, 13 Feb 2025 16:53:25 +0000 (11:53 -0500)]
use pep 621
Installation has been converted to use :pep:`621`, e.g. ``pyproject.toml``.
note that the introduction of pyproject with min python version of 3.9
is also consumed by Black which now wants to format a few test files
differently, so that is included as well.
Mike Bayer [Sat, 8 Feb 2025 17:04:53 +0000 (12:04 -0500)]
drop SQLAlchemy 1.3, Python 3.8
Jenkins issues reveal that SQLAlchemy 1.3's testing provision has
unidentified deficiencies that are causing instability with the
mssql engine. As provisioning was highly refactored in 1.4, just drop
1.3 support rather than trying to figure out the exact thing that
changed.
Support for SQLAlchemy 1.3, which was EOL as of 2021, is now dropped from
Alembic as of version 1.15.0.
Support for Python 3.8 is dropped as of Alembic 1.15.0. Python 3.8 is EOL.
Try pytest 8.3 as this seems to be running fine for SQLAlchemy
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.
Peter Cock [Wed, 6 Nov 2024 17:07:02 +0000 (12:07 -0500)]
Avoid D103 linter warnings via script.py.mako
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.
refactor: add revision context to AutogenerateDiffsDetected so that wrappers may make other formatting of the diff
### Description
As discussed in #1597, AutogenerateDiffsDetected should hold contextual information so that command can be wrapped for another format (CI, pre-commit hook...)
### Checklist
<!-- go over following points. check them with an `x` if they do apply, (they turn into clickable checkboxes once the PR is submitted, so no need to do everything at once)
-->
This pull request is:
- [ ] A documentation / typographical error fix
- Good to go, no issue or tests are needed
- [x] A short code fix
- please include the issue number, and create an issue if none exists, which
must include a complete example of the issue. one line code fixes without an
issue and demonstration will not be accepted.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests. one line code fixes without tests will not be accepted.
- [ ] A new feature implementation
- please include the issue number, and create an issue if none exists, which must
include a complete example of how the feature would look.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.
Mike Bayer [Tue, 24 Dec 2024 15:30:10 +0000 (10:30 -0500)]
check for variants (recursion branch) first in all cases
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.
Mike Bayer [Fri, 29 Nov 2024 16:58:53 +0000 (11:58 -0500)]
ensure rename_column works on SQLite
Modified SQLite's dialect to render "ALTER TABLE <t> RENAME COLUMN" when
:meth:`.Operations.alter_column` is used with a straight rename, supporting
SQLite's recently added column rename feature.
Mike Bayer [Mon, 25 Nov 2024 18:57:58 +0000 (13:57 -0500)]
support separation of Numeric/Float
in [1] we are considering separating Numeric and Float.
For Alembic PostgreSQL backend we need this isinstance therefore
to check for both Numeric and Float.
By keeping it to these two types, rather than targeting the
NumericCommon type being added in [1], the patch can work with
SQLAlchemy without the separation change as well.
Peter Cock [Thu, 7 Nov 2024 14:51:22 +0000 (09:51 -0500)]
Clarify what autogenerate compares
### Description
<!-- Describe your changes in detail -->
I was struggling with empty upgrade/downgrade functions because both my database and my ORM were up to date. I wrongly assumed the comparison was against the previous database scheme as per the prior revision script(s).
### Checklist
<!-- go over following points. check them with an `x` if they do apply, (they turn into clickable checkboxes once the PR is submitted, so no need to do everything at once)
-->
This pull request is:
- [x] A documentation / typographical error fix
- Good to go, no issue or tests are needed
- [ ] A short code fix
- please include the issue number, and create an issue if none exists, which
must include a complete example of the issue. one line code fixes without an
issue and demonstration will not be accepted.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests. one line code fixes without tests will not be accepted.
- [ ] A new feature implementation
- please include the issue number, and create an issue if none exists, which must
include a complete example of how the feature would look.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.
Michael Bayer [Wed, 6 Nov 2024 23:43:43 +0000 (18:43 -0500)]
Fix `alembic.ini` templates to match `configparser` file format.
In the `alembic.ini` templates, I moved the inline comment about `version_path_separator` to their own lines as required by `configparser`.
### Description
In a recent project, I included the following configuration values in my `alembic.ini`. Note that the last line is the default line from the current generic `alembic.ini` template.
```
# version location specification; This defaults
# to migrations/versions. When using multiple version
# directories, initial revisions must be specified with --version-path.
# The path separator used here should be the separator specified by "version_path_separator" below.
version_locations = %(here)s/migrations/versions
# version path separator; As mentioned above, this is the character used to split
# version_locations. The default within new alembic.ini files is "os", which uses os.pathsep.
# If this key is omitted entirely, it falls back to the legacy behavior of splitting on spaces and/or commas.
# Valid values for version_path_separator are:
#
# version_path_separator = :
# version_path_separator = ;
# version_path_separator = space
version_path_separator = os # Use os.pathsep. Default configuration used for new projects.
```
When running `alembic check`, I encountered:
```
ValueError: 'os # Use os.pathsep. Default configuration used for new projects.' is not a valid value for version_path_separator; expected 'space', 'os', ':', ';'
```
It seemed that the comment in the last line was being included as part of the parsed config value, which should be `os`.
Alembic currently [uses `configparser.ConfigParser` from the standard libary](https://github.com/sqlalchemy/alembic/blob/2d60c77c81a72a78b575b96aef511e658073dec5/alembic/util/compat.py#L82-L89) to parse `alembic.ini` files. The [default `configparser` file format](https://docs.python.org/3/library/configparser.html#supported-ini-file-structure) requires that comments be on their own lines, although this can be customized. I changed the three copies of this line in Alembic's `alembic.ini` templates to remove the inline comments. In my case, this change fixed the `ValueError`.
This issue could also be fixed by changing [the default instance of `ConfigParser`](https://github.com/sqlalchemy/alembic/blob/2d60c77c81a72a78b575b96aef511e658073dec5/alembic/config.py#L202), using `inline_comment_prefixes=("#",)`. I imagine, however, that it might be better to use the default file format.
### Checklist
<!-- go over following points. check them with an `x` if they do apply, (they turn into clickable checkboxes once the PR is submitted, so no need to do everything at once)
-->
This pull request is:
- [x] A documentation / typographical error fix
- Good to go, no issue or tests are needed
- [ ] A short code fix
- please include the issue number, and create an issue if none exists, which
must include a complete example of the issue. one line code fixes without an
issue and demonstration will not be accepted.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests. one line code fixes without tests will not be accepted.
- [ ] A new feature implementation
- please include the issue number, and create an issue if none exists, which must
include a complete example of how the feature would look.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.
Aaron Griffin [Wed, 6 Nov 2024 20:40:56 +0000 (15:40 -0500)]
Improve write_pyi usage
Fixes #1524
### Description
Due to some problems when running write_pyi, this includes the following changes:
1. move the sys.path.append up before alembic is imported - this is using global imports otherwise
2. use tox to run write_pyi in order to avoid globally installed dependencies
### Checklist
<!-- go over following points. check them with an `x` if they do apply, (they turn into clickable checkboxes once the PR is submitted, so no need to do everything at once)
-->
This pull request is:
- [ ] A documentation / typographical error fix
- Good to go, no issue or tests are needed
- [x] A short code fix
- please include the issue number, and create an issue if none exists, which
must include a complete example of the issue. one line code fixes without an
issue and demonstration will not be accepted.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests. one line code fixes without tests will not be accepted.
- [ ] A new feature implementation
- please include the issue number, and create an issue if none exists, which must
include a complete example of how the feature would look.
- Please include: `Fixes: #<issue number>` in the commit message
- please include tests.