python / python/typing

Support for `ParamSpec` for `type`

Ouverte
#1,991 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

topic: feature
Langage dominant
Python
Étoiles
1.8k
Forks
302
Merge moyen
23 h
PR mergées (30 j)
8

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.

Guide de contribution

Aucun guide de contribution indexé pour ce dépôt

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Piste de recherche

Examinez le comportement de ParamSpec pour type et Callable décrit dans les exemples, puis comparez-le avec l'orientation possible dans typing issue #1966. La tâche serait terminée lorsqu'une représentation acceptée préserverait les informations sur les paramètres du constructeur et rendrait la surcharge proposée distinguable, mais cette issue ne nomme ni fichiers d'implémentation ni tests.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Évaluation

Stack technique
python
Domaine
tooling
Type d'issue
Fonctionnalité
Difficulté
5/5
Temps estimé
Plus d'une semaine
Activité
À l'abandon
Clarté
À clarifier
Accessibilité débutants
30/100

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.