Description
Describe the bug
Using server_default=sa.null()
in an alter_table
command triggers a typing error, even though the migration executes without any problems.
Note also that sa.null()
is type checked properly when used in a column definition like sa.Column("description", sa.Text, nullable=True, server_default=sa.null())
Expected behavior
No typing errors should be raised for valid code.
To Reproduce
The following valid code produces a typing error
def upgrade():
op.alter_column(
"table_name",
"column_name",
server_default=sa.null(),
nullable=True,
)
Error
error: Argument "server_default" to "alter_column" has incompatible type "Null"; expected "str | bool | Identity | Computed | TextClause | None" [arg-type]
Versions.
- Python: Python 3.12.9 (main, Feb 12 2025, 15:09:19) [Clang 19.1.6 ] on darwin
- Alembic: 1.16.1
- SQLAlchemy: 2.0.40
- Database: postgres
- mypy: mypy 1.15.0 (compiled: yes)
Additional context
This happens because there are some inconsistencies on how server_default
is typed throughout alembic's and sqlalchemy's codebases.
Sqlalchemy types server_default
on Column
as _ServerDefaultArgument
, which is defined as
_ServerDefaultArgument = Union["FetchedValue", str, TextClause, ColumnElement[Any]]
Whereas on alembic there are 2 definitions.
The signature exposed on op.pyi
types server_default
as
Union[str, bool, Identity, Computed, TextClause, None]
The signature defined on alembic.ddl.impl
types server_default
as Optional[Union[_ServerDefault, Literal[False]]]
, where _ServerDefault
is defined as
_ServerDefault = Union["TextClause", "FetchedValue", "Function[Any]", str]