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]
Describe the bug
Using
server_default=sa.null()in analter_tablecommand 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 likesa.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
Error
Versions.
Additional context
This happens because there are some inconsistencies on how
server_defaultis typed throughout alembic's and sqlalchemy's codebases.Sqlalchemy types
server_defaultonColumnas_ServerDefaultArgument, which is defined asWhereas on alembic there are 2 definitions.
The signature exposed on
op.pyitypesserver_defaultasThe signature defined on
alembic.ddl.impltypesserver_defaultasOptional[Union[_ServerDefault, Literal[False]]], where_ServerDefaultis defined as