Support for `ParamSpec` for `type`
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 30/100
Research direction
Review the ParamSpec behavior for type and Callable described in the examples, then compare it with the possible direction in typing issue #1966. Done would require an agreed representation that preserves constructor parameter information and makes the proposed overload distinguishable, but this issue does not name implementation files or tests.
Written by the indexing model from the issue text.
Description
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.
- Dominant language
- Python
- Stars
- 1.8k
- Forks
- 302
- Avg merge
- 23h
- Merged PRs (30d)
- 8
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from python/typing
-
topic: typing spec
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
topic: typing spec
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
-
topic: documentation
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
topic: documentation
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
-
topic: conformance tests topic: typing spec
Difficulty 3/5 1-2 days Newbie friendliness 72/100
Similar issues
-
Add: hunch Open
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
AbdelStark/awesome-typesafe#104 ·
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
DiamondLightSource/dodal#2211 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
openml/openml-python#1749 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
sipyourdrink-ltd/bernstein#6191 ·