rel_2_1_0rc1
Breaking Changes📦 sqlalchemyView on GitHub →
⚠ 2 breaking✨ 5 features🐛 6 fixes⚡ 1 deprecations🔧 15 symbols
Summary
This release requires Python 3.11+, adds Python 3.15 support, and includes numerous ORM improvements including better error messages, runtime Python source compilation for debugging, and fixes for session flushing and loader strategy issues.
⚠️ Breaking Changes
- Python 3.11 or above is now required. Support for Python 3.10, 3.9, 3.8, and 3.7 is dropped. This change is to align with Python's EOL schedule and provide more room for the SQLAlchemy 2.1 series.
- Calling `_orm.aliased()` against a `_sql.select()` or `_sql.union()` / `_sql.CompoundSelect` construct will now raise an error in SQLAlchemy 2.1. Previously, it failed with an obscure `AttributeError`. In SQLAlchemy 2.0, this will emit a deprecation warning as it coerces the construct into a subquery.
Migration Steps
- Update Python to version 3.11 or higher.
✨ New Features
- Python 3.15 support has been added and tested.
- Improved error message when a `Session` is used inside a context manager after the transaction has been rolled back. The `InvalidRequestError` now includes the original exception that triggered the rollback.
- Improved error messages for ORM loader strategy options that cannot be applied to a query. Messages now render the offending option in a user-friendly form and include the option that triggered the error.
- Python source generated at runtime is now compiled against a descriptive filename registered with the `linecache` module, allowing generated functions in stack traces to render with their source.
- When a subclass overrides a `_orm.validates()` method, only the subclass validator is now invoked. The subclass validator may call `super()` to also invoke the parent class validator.
🐛 Bug Fixes
- Fixed a result-column misalignment bug in ORM-enabled UPDATE statements with `synchronize_session="fetch"` where columns in rows returned by `.returning()` could be returned under incorrect keys.
- Fixed bug where a failed `_orm.Session.bulk_insert_mappings()`, `_orm.Session.bulk_update_mappings()`, or `_orm.Session.bulk_save_objects()` call could leave the `_orm.Session` permanently in a "flushing" state.
- Fixed issue where unpickling an ORM object loaded using loader options with wildcard tokens (e.g., `_orm.load_only()` or `_orm.raiseload()` with "*") would fail with `KeyError` or `IndexError` if the unpickling process had not yet constructed a loader path using that same token.
- Fixed issue where a string ending in `"*"` passed to a `_orm.Load` strategy method would bypass the check rejecting string attribute names, silently producing a loader path that matched nothing. Such a string now raises `ArgumentError`.
- Fixed regression where passing `_orm.relationship.default_factory` as `list` to a relationship using `_orm.WriteOnlyMapped` or `_orm.DynamicMapped` annotation would raise an error at mapper configuration time. `list` is now accepted.
- Fixed long-standing issue where an object loaded at more than one path within a single query would retain the loader options of whichever path the query happened to see last. The options an object retains are now applied to all paths.
Affected Symbols
⚡ Deprecations
- Calling `_orm.aliased()` against a `_sql.select()` or `_sql.union()` / `_sql.CompoundSelect` construct emits a deprecation warning under SQLAlchemy 2.0 as it coerces the construct into a subquery instead.