python / python/cpython

async callable not awaited in side_effect for AsyncMock

Ouverte
#156,460 1 commentaire 0 réactions 0 personnes assignées Voir sur GitHub

Personne n'a encore pris cette issue.

stdlib type-bug
Langage dominant
Python
Étoiles
77.2k
Forks
36k
Métriques de merge des PR
Métriques de PR en attente

Description

Bug report

Bug description:

In the AsyncMockMixin._execute_mock_call, the following test is done:

        if effect is not None:
            if _is_exception(effect):
                raise effect
            elif not _callable(effect):
                try:
                    result = next(effect)
                except StopIteration:
                    # It is impossible to propagate a StopIteration
                    # through coroutines because of PEP 479
                    raise StopAsyncIteration
                if _is_exception(result):
                    raise result
            elif iscoroutinefunction(effect):
                result = await effect(*args, **kwargs)
            else:
                result = effect(*args, **kwargs)

However elif iscoroutinefunction(effect) will return False for an awaitable that was defined this way:

    class AsyncCallable:
        async def __call__(self, *args, **kwargs):
            # await stuff
            pass

Note that __call__ is awaitable here but not detected as such.

iscoroutinefunction(effect.__call__) would return True in such a case however, so the fix might be as simple as:

            elif iscoroutinefunction(effect) or iscoroutinefunction(getattr(effect, '__call__', None)):

In the meantime, the workaround is to add markcoroutinefunction(self) to the class.

    class AsyncCallable:
        def __init__(self, *args, **kwargs):
            # init code
            markcoroutinefunction(self)  # workaround for iscoroutinefunction check in side_effect to return True

        ...
CPython versions tested on:

3.14

Operating systems tested on:

Linux

Linked PRs
  • gh-156465

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 dans Lib/unittest/mock.py, au niveau de AsyncMockMixin._execute_mock_call, et examinez la PR liée gh-156465. Confirmez le comportement d’un objet dont la méthode asynchrone call est utilisée comme AsyncMock.side_effect, puis ajoutez ou mettez à jour la couverture de régression afin que cet objet appelable soit correctement awaité.

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

Évaluation

Stack technique
python
Domaine
testing-qa
Type d'issue
Bug
Difficulté
2/5
Temps estimé
1-3 heures
Activité
À l'abandon
Clarté
Clairement spécifiée
Accessibilité débutants
35/100

Recevez les nouvelles issues par e-mail

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