python / python/typeshed

`[Async]ContextDecorator.__call__` return type should depend on the underlying context manager's `_ExitT_co`

Ouverte
#13,512 4 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

Langage dominant
Python
Étoiles
5.1k
Forks
2.1k
Merge moyen
1 j 19 h
PR mergées (30 j)
82

Description

[!Important]
Please see https://discuss.python.org/t/support-suppressing-generator-context-managers/103615 first!

This is how ContextDecorator.__call__ is implemented in the Python standard library:

def __call__(self, func):
    @wraps(func)
    def inner(*args, **kwds):
        with self._recreate_cm():
            return func(*args, **kwds)
    return inner

In typeshed, ContextDecorator.__call__ currently has a return type of the original callable (func).
However, if the return value of self._recreate_cm().__call__ is truthy, the return type of ContextDecorator.__call__ can as well be None, like in the silly example below:

from collections.abc import Generator
from contextlib import contextmanager, suppress
from typing import reveal_type


@contextmanager
def zero_division_to_none() -> Generator[None]:
    with suppress(ZeroDivisionError):
        yield


@zero_division_to_none()
def div(a: int, b: int) -> float:
    return a / b


reveal_type(div(1, 0))
# mypy, pyright: Revealed type is "builtins.float"
# Runtime type is 'NoneType'

My first shot was to patch the proper __call__ functions to "extend" the return type with _ThrottledExcReturnT (a new type parameter of ContextDecorator), constrained by Never and None, with the default type Never for backward compatibility. To me, there's no way to declare the relationship symbolically, so it would have to be typed manually in classes implementing the context manager protocol.

Guide de contribution

Ouvrir le guide de contribution

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

Commencez par la discussion Python liée et l’implémentation de la bibliothèque standard dans Lib/contextlib.py, en vous concentrant sur ContextDecorator.call et sur le _ExitT_co du gestionnaire de contexte sous-jacent. Déterminez une relation prise en charge au niveau des types pour le type de retour de la fonction appelable encapsulée, puis vérifiez que l’annotation reflète les cas où la suppression par le gestionnaire de contexte renvoie None.

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

Évaluation

Stack technique
python
Domaine
developer-experience
Type d'issue
Bug
Difficulté
5/5
Temps estimé
Plus d'une semaine
Activité
À l'abandon
Clarté
À clarifier
Accessibilité débutants
35/100

Recevez les nouvelles issues par e-mail

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