Support decorators that modify parameter types and preserve keywords
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 30/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Đình trệ
- Công nghệ
- python
- Lĩnh vực
- developer-experience
Hướng nghiên cứu
Bắt đầu với các ví dụ về decorator trong issue này và so sánh hành vi được yêu cầu với issue liên quan #1273. Xem xét cách các phép biến đổi dựa trên tham số nên tương tác với ParamSpec, các đối số từ khóa, Callable và các chữ ký của Protocol; công việc được xem là hoàn tất khi hành vi được đặc tả đủ rõ để hỗ trợ các lời gọi vị trí và từ khóa đã nêu.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
For osandov/drgn#364, I'd like to be able to define a decorator that modifies the parameter types of the functions it wraps, but also preserves keywords.
For a toy example, imagine a decorator that wraps a function taking an int as the first parameter (possibly as a keyword argument) so that it can also take a str that is automatically converted to an int. I can do this manually with overloads:
import inspect
import functools
from typing import Any, Callable, TypeVar, overload
R = TypeVar("R")
def takes_int_or_str(f: Callable[..., R]) -> Callable[..., R]:
param = next(iter(inspect.signature(f).parameters))
@functools.wraps(f)
def wrapper(*args: Any, **kwds: Any) -> R:
if param in kwds:
if isinstance(kwds[param], str):
kwds[param] = int(kwds[param])
elif isinstance(args[0], str):
return f(int(args[0]), *args[1:], **kwds)
return f(*args, **kwds)
return wrapper
@overload
def f(x: int) -> int: ...
@overload
def f(x: str) -> int: ...
@takes_int_or_str
def f(x: int) -> int:
return x * x
f(1)
f("2")
f(x="3")
But this is tedious and error-prone if you have a lot of functions using the decorator. ParamSpec almost gets me what I want, but it doesn't preserve keywords:
import inspect
import functools
from typing import Any, Callable, Concatenate, ParamSpec, TypeVar
P = ParamSpec("P")
R = TypeVar("R")
def takes_int_or_str(
f: Callable[Concatenate[int, P], R]
) -> Callable[Concatenate[int | str, P], R]:
param = next(iter(inspect.signature(f).parameters))
@functools.wraps(f)
def wrapper(*args: Any, **kwds: Any) -> R:
if param in kwds:
if isinstance(kwds[param], str):
kwds[param] = int(kwds[param])
elif isinstance(args[0], str):
return f(int(args[0]), *args[1:], **kwds)
return f(*args, **kwds)
return wrapper
@takes_int_or_str
def f(x: int) -> int:
return x * x
f(1)
f("2")
# error: Unexpected keyword argument "x" for "f" [call-arg]
f(x="3")
This seems somewhat related to #1273, although I want to specify the transformation by parameter, not by input type.
P.S. I used Callable here, but my real use cases need a Protocol with __call__ because they have more complicated signatures.
- Ngôn ngữ chính
- Python
- Star
- 1.8k
- Fork
- 302
- Merge trung bình
- 23 giờ
- Pull request đã merge (30 ngày)
- 8
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.
Issue khác của python/typing
-
topic: typing spec
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
-
topic: typing spec
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
-
topic: documentation
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
-
topic: documentation
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
-
topic: conformance tests topic: typing spec
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 72/100
Tất cả issue của python/typing
Issue tương tự
-
enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
canonical/paas-charm#368 · 1 bình luận ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
-
tech debt
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
-
addition to tracking list Đang mở
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 90/100
StevenBlack/hosts#3256 ·
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 90/100
qualcomm/qai-appbuilder#275 ·