on_version_apply is typed as a positional callable, but alembic calls it with keyword arguments

Đang mở Phù hợp với người mới
#1,883 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

  • #1886 của @anish-yen — đã đóng, không merge

Đánh giá

Độ khó
2/5
Thời gian dự kiến
1-3 giờ
Mức phù hợp với người mới
82/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
python, sqlalchemy
Lĩnh vực
backend, databases

Hướng nghiên cứu

Đọc các định nghĩa OnVersionApplyFn trong alembic/runtime/environment.py và alembic/context.pyi, sau đó so sánh chúng với lời gọi bằng đối số từ khóa trong alembic/runtime/migration.py. Cập nhật kiểu có thể gọi để khớp với các đối số từ khóa được tài liệu hóa và kiểm tra độ bao phủ kiểm tra kiểu liên quan. Công việc hoàn tất khi các trình kiểm tra kiểu chấp nhận callback được viết theo tài liệu và từ chối callback chỉ nhận đối số vị trí.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

Describe the bug

EnvironmentContext.configure(on_version_apply=...) documents that "Each callable accepts no positional arguments and the following keyword arguments: ctx, step, heads, run_args", and MigrationContext.run_migrations() calls each callable that way (alembic/runtime/migration.py):

callback(
    ctx=self,
    step=step.info,
    heads=set(head_maintainer.heads),
    run_args=kw,
)

But the parameter is typed as a callable of four positional arguments, in alembic/runtime/environment.py and in alembic/context.pyi:

OnVersionApplyFn = Callable[
    [MigrationContext, "MigrationInfo", Collection[Any], Mapping[str, Any]],
    None,
]

So a type checker rejects a callback written as documented, and accepts one that fails at runtime.

Expected behavior

The type of on_version_apply describes the keyword arguments, for example:

class OnVersionApplyFn(Protocol):
    def __call__(
        self,
        *,
        ctx: MigrationContext,
        step: MigrationInfo,
        heads: Collection[Any],
        run_args: Mapping[str, Any],
    ) -> None: ...

To Reproduce

from typing import Any

from alembic import context
from alembic.runtime.migration import MigrationContext, MigrationInfo


def as_documented(
    *,
    ctx: MigrationContext,
    step: MigrationInfo,
    heads: set[str],
    run_args: dict[str, Any],
) -> None:
    """Takes the arguments by keyword, as documented."""


context.configure(on_version_apply=as_documented)  # rejected by type checkers


def as_typed(
    context_: MigrationContext, step: MigrationInfo, heads: Any, args: Any
) -> None:
    """Takes them by place, as typed."""


context.configure(on_version_apply=as_typed)  # accepted; run_migrations() then fails

Error

pyright 1.1.407:
error: Argument of type "(*, ctx: MigrationContext, step: MigrationInfo, heads: set[str], run_args: dict[str, Any]) -> None" cannot be assigned to parameter "on_version_apply" of type "((MigrationContext, MigrationInfo, Collection[Any], Mapping[str, Any]) -> None) | None" in function "configure" (reportArgumentType)

pyrefly 1.3.2:
ERROR Argument `(*, ctx: MigrationContext, step: MigrationInfo, heads: set[str], run_args: dict[str, Any]) -> None` is not assignable to parameter `on_version_apply` with type `((MigrationContext, MigrationInfo, Collection[Any], Mapping[str, Any]) -> None) | None` in function `alembic.context.configure` [bad-argument-type]

at runtime, with as_typed:
TypeError: as_typed() got an unexpected keyword argument 'ctx'

Versions.

  • OS: Linux, macOS
  • Python: 3.14
  • Alembic: 1.20.0
  • SQLAlchemy: 2.0.54
  • Database: PostgreSQL 17
  • DBAPI: asyncpg

Additional context

Our workaround takes the arguments both ways: def on_apply(ctx, step, heads, run_args) -> None, the parameters named as alembic passes them.

Have a nice day!

Ngôn ngữ chính
Python
Star
4.5k
Fork
391
Chỉ số merge pull request
Không có pull request nào được merge trong 30 ngày

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của sqlalchemy/alembic

Tất cả issue của sqlalchemy/alembic

Issue tương tự

Thêm issue về Python

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.