(Внутри функция преобразует значение в заданный тип с помощью Pydantic. В приведенном ниже примере нетипизированное значение — это параметр input_value, но в реальном коде оно возвращается API.)
Я хочу, чтобы следующий код работал:
Код: Выделить всё
from typing import Annotated, Any, TypeVar, overload
from typing_extensions import assert_type
from pydantic import TypeAdapter
T = TypeVar("T")
@overload
def convert(value: Any) -> Any:
...
@overload
def convert(value: Any, output_type: type[T]) -> T:
...
def convert(value: Any, output_type: type[T] | Any = Any) -> T:
adapter = TypeAdapter(output_type)
return adapter.validate_python(value)
assert_type(convert(1), Any)
assert_type(convert(1, int), int)
assert_type(convert(1, int | str), int | str)
# "assert_type" mismatch: expected "int | str" but received "Unknown"
assert_type(convert(1, Annotated[int, "foo"]), Annotated[int, "foo"])
# Argument of type "Annotated" cannot be assigned to parameter "output_type" of type "type[T@convert]" in function "convert"
# Type "Annotated" is not assignable to type "type[T@convert]"
# "assert_type" mismatch: expected "int" but received "Unknown"
Код: Выделить всё
ty check typing_test.py:
error[type-assertion-failure]: Argument does not have asserted type `int | str`
--> typing_test.py:24:1
|
22 | assert_type(convert(1, int), int)
23 |
24 | assert_type(convert(1, int | str), int | str)
| ^^^^^^^^^^^^---------------------^^^^^^^^^^^^
| |
| Inferred type is `Unknown`
25 | # "assert_type" mismatch: expected "int | str" but received "Unknown"
|
info: `int | str` and `Unknown` are not equivalent types
info: rule `type-assertion-failure` is enabled by default
error[invalid-argument-type]: Argument to function `convert` is incorrect
--> typing_test.py:24:24
|
22 | assert_type(convert(1, int), int)
23 |
24 | assert_type(convert(1, int | str), int | str)
| ^^^^^^^^^ Expected `type[Unknown]`, found ``
25 | # "assert_type" mismatch: expected "int | str" but received "Unknown"
|
info: Matching overload defined here
--> typing_test.py:13:5
|
12 | @overload
13 | def convert(object: Any, output_type: type[T]) -> T:
| ^^^^^^^ -------------------- Parameter declared here
14 | ...
|
info: Non-matching overloads for function `convert`:
info: (object: Any) -> Any
info: rule `invalid-argument-type` is enabled by default
error[type-assertion-failure]: Argument does not have asserted type `int`
--> typing_test.py:27:1
|
25 | # "assert_type" mismatch: expected "int | str" but received "Unknown"
26 |
27 | assert_type(convert(1, Annotated[int, "foo"]), Annotated[int, "foo"])
| ^^^^^^^^^^^^---------------------------------^^^^^^^^^^^^^^^^^^^^^^^^
| |
| Inferred type is `Unknown`
28 | # Argument of type "Annotated" cannot be assigned to parameter "output_type" of type "type[T@convert]" in function "convert"
29 | # Type "Annotated" is not assignable to type "type[T@convert]"
|
info: `int` and `Unknown` are not equivalent types
info: rule `type-assertion-failure` is enabled by default
error[invalid-argument-type]: Argument to function `convert` is incorrect
--> typing_test.py:27:24
|
25 | # "assert_type" mismatch: expected "int | str" but received "Unknown"
26 |
27 | assert_type(convert(1, Annotated[int, "foo"]), Annotated[int, "foo"])
| ^^^^^^^^^^^^^^^^^^^^^ Expected `type[Unknown]`, found ``
28 | # Argument of type "Annotated" cannot be assigned to parameter "output_type" of type "type[T@convert]" in function "convert"
29 | # Type "Annotated" is not assignable to type "type[T@convert]"
|
info: Matching overload defined here
--> typing_test.py:13:5
|
12 | @overload
13 | def convert(object: Any, output_type: type[T]) -> T:
| ^^^^^^^ -------------------- Parameter declared here
14 | ...
|
info: Non-matching overloads for function `convert`:
info: (object: Any) -> Any
info: rule `invalid-argument-type` is enabled by default
Found 4 diagnostics
Код: Выделить всё
mypy typing_test.py:
typing_test.py:24: error: Expression is of type "int", not "int | str" [assert-type]
assert_type(convert(1, int | str), int | str)
^
typing_test.py:24: error: Argument 2 to "convert" has incompatible type "UnionType | type[int]"; expected "type[int]" [arg-type]
assert_type(convert(1, int | str), int | str)
^~~~~~~~~
typing_test.py:27: error: Expression is of type "Any", not "int" [assert-type]
assert_type(convert(1, Annotated[int, "foo"]), Annotated[int, "foo"])
^
typing_test.py:27: error: No overload variant of "convert" matches argument types "int", "" [call-overload]
assert_type(convert(1, Annotated[int, "foo"]), Annotated[int, "foo"])
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
typing_test.py:27: note: Possible overload variants:
typing_test.py:27: note: def convert(object: Any) -> Any
typing_test.py:27: note: def [T] convert(object: Any, output_type: type[T]) -> T
Found 4 errors in 1 file (checked 1 source file)
Это не дубликат Python: ввод универсальной функции, которая получает тип и возвращает экземпляр этого типа, потому что этот вопрос (и решение) работает только для конкретных типов-s, но не работает с аннотациями типов в целом. Я использовал то же решение в качестве отправной точки, но я ищу решение, которое также поддерживает любые аннотации, аналогично самому pydantic или функции typing.cast().
Какую аннотацию типа использовать для аннотации типа? может быть связано (возможно, основная причина в том, что моя аннотация output_type: type[T] неверна, и я не знаю, как аннотировать тип аннотации типа.
Подробнее здесь: https://stackoverflow.com/questions/799 ... d-apply-it
Мобильная версия