Support for `ParamSpec` for `type`
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- Python
- Star
- 1.8k
- Fork
- 302
- Merge trung bình
- 23 giờ
- Pull request đã merge (30 ngày)
- 8
Mô tả
The problem I'm having is that the type doesn't support ParamSpec, so I can't use that to enforce args and kwargs, in the same way as as Callable. I'm not 100% sure whether this is correct, but isn't every type a Callable, so in a sense that type is a subtype of Callable, so there should be a way to represent type in the same way as a Callable to obey Liskov?
For example, I'm trying to write an overload such that passing in a type will return ExpectType, while a general Callable returns ExpectCallable:
from collections.abc import Callable
import typing_extensions as t
P = t.ParamSpec("P")
T_co = t.TypeVar("T_co", covariant=True)
class ExpectCallable(t.Generic[P, T_co]): ...
class ExpectType(ExpectCallable[P, T_co]): ...
@t.overload
def expect(
v: type[T_co], /, *args: P.args, **kwargs: P.kwargs
) -> ExpectType[P, T_co]: ...
@t.overload
def expect(
v: Callable[P, T_co], /, *args: P.args, **kwargs: P.kwargs
) -> ExpectCallable[P, T_co]: ...
def expect(
v: type[T_co] | Callable[P, T_co], /, *args: P.args, **kwargs: P.kwargs
) -> ExpectType[P, T_co] | ExpectCallable[P, T_co]:
return ExpectType() if isinstance(v, type) else ExpectCallable()
class A:
def __init__(self, inp: str, /) -> None: ...
def fn(inp: str, /) -> None: ...
t.assert_type(expect(A), ExpectType[[], A]) # Shouldn't be allowed
t.assert_type(expect(fn, "inp"), ExpectCallable[[str], None])
As you can see that t.assert_type(expect(A), ExpectType[[], A]) passes with no errors, even though A is suppose to take in a str argument. I'm expecting expect(A) to require a str argument, similar to how expect(fn, "inp") requires the second parameter "inp".
Note that I haven't used *args and **kwargs in the example for simplicity, but they are meant to be used inside of the Expect classes.
Maybe the simplest way is to add a new class TypeCallable that allows for TypeCallable[P, T] instead of modifying type, so the above example is achievable:
@t.overload
def expect(
v: TypeCallable[P, T_co], /, *args: P.args, **kwargs: P.kwargs
) -> ExpectType[P, T_co]: ...
@t.overload
def expect(
v: Callable[P, T_co], /, *args: P.args, **kwargs: P.kwargs
) -> ExpectCallable[P, T_co]: ...
def expect(
v: TypeCallable[P, T_co] | Callable[P, T_co], /, *args: P.args, **kwargs: P.kwargs
) -> ExpectType[P, T_co] | ExpectCallable[P, T_co]:
return ExpectType() if isinstance(v, type) else ExpectCallable()
Note that I think https://github.com/python/typing/issues/1966 might also solve the above problem.
Hướng dẫn đóng góp
Chưa lập chỉ mục được hướng dẫn đóng góp cho kho mã nguồn này
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- 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.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Xem xét hành vi của ParamSpec đối với type và Callable được mô tả trong các ví dụ, sau đó so sánh với hướng khả thi trong typing issue #1966. Công việc được xem là hoàn tất khi có một biểu diễn được thống nhất, bảo toàn thông tin về các tham số của constructor và khiến overload được đề xuất có thể phân biệt được, nhưng issue này không nêu tên các tệp triển khai hoặc các bài kiểm thử.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- python
- Lĩnh vực
- tooling
- Loại issue
- Tính năng
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Cần làm rõ
- Mức phù hợp với người mới
- 30/100