@@ -62,4 +62,67 @@ static_assert(not is_gradual_equivalent_to(tuple[str, int], tuple[str, int, byte
6262static_assert(not is_gradual_equivalent_to(tuple[str , int ], tuple[int , str ]))
6363```
6464
65+ ## Callable
66+
67+ ``` py
68+ from knot_extensions import Unknown, CallableTypeFromFunction, is_gradual_equivalent_to, static_assert
69+ from typing import Any, Callable
70+
71+ static_assert(is_gradual_equivalent_to(Callable[... , int ], Callable[... , int ]))
72+ static_assert(is_gradual_equivalent_to(Callable[... , Any], Callable[... , Unknown]))
73+ static_assert(is_gradual_equivalent_to(Callable[[int , Any], None ], Callable[[int , Unknown], None ]))
74+
75+ static_assert(not is_gradual_equivalent_to(Callable[[int , Any], None ], Callable[[Any, int ], None ]))
76+ static_assert(not is_gradual_equivalent_to(Callable[[int , str ], None ], Callable[[int , str , bytes ], None ]))
77+ static_assert(not is_gradual_equivalent_to(Callable[... , None ], Callable[[], None ]))
78+ ```
79+
80+ A function with no explicit return type should be gradual equivalent to a callable with a return
81+ type of ` Any ` .
82+
83+ ``` py
84+ def f1 ():
85+ return
86+
87+ static_assert(is_gradual_equivalent_to(CallableTypeFromFunction[f1], Callable[[], Any]))
88+ ```
89+
90+ And, similarly for parameters with no annotations.
91+
92+ ``` py
93+ def f2 (a , b ) -> None :
94+ return
95+
96+ static_assert(is_gradual_equivalent_to(CallableTypeFromFunction[f2], Callable[[Any, Any], None ]))
97+ ```
98+
99+ Additionally, as per the spec, a function definition that includes both ` *args ` and ` **kwargs `
100+ parameter that are annotated as ` Any ` or kept unannotated should be gradual equivalent to a callable
101+ with ` ... ` as the parameter type.
102+
103+ ``` py
104+ def variadic_without_annotation (* args , ** kwargs ):
105+ return
106+
107+ def variadic_with_annotation (* args : Any, ** kwargs : Any) -> Any:
108+ return
109+
110+ static_assert(is_gradual_equivalent_to(CallableTypeFromFunction[variadic_without_annotation], Callable[... , Any]))
111+ static_assert(is_gradual_equivalent_to(CallableTypeFromFunction[variadic_with_annotation], Callable[... , Any]))
112+ ```
113+
114+ But, a function with either ` *args ` or ` **kwargs ` is not gradual equivalent to a callable with ` ... `
115+ as the parameter type.
116+
117+ ``` py
118+ def variadic_args (* args ):
119+ return
120+
121+ def variadic_kwargs (** kwargs ):
122+ return
123+
124+ static_assert(not is_gradual_equivalent_to(CallableTypeFromFunction[variadic_args], Callable[... , Any]))
125+ static_assert(not is_gradual_equivalent_to(CallableTypeFromFunction[variadic_kwargs], Callable[... , Any]))
126+ ```
127+
65128[ materializations ] : https://typing.readthedocs.io/en/latest/spec/glossary.html#term-materialize
0 commit comments