python / python/cpython

async callable not awaited in side_effect for AsyncMock

Aperta
#156,460 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

stdlib type-bug
Lingua principale
Python
Stelle
77.2k
Fork
35.9k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

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

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia in Lib/unittest/mock.py, in AsyncMockMixin._execute_mock_call, e analizza la PR collegata gh-156465. Conferma il comportamento di un oggetto la cui call asincrona viene usata come AsyncMock.side_effect, quindi aggiungi o aggiorna la copertura di regressione in modo che quell'oggetto callable venga sottoposto correttamente ad await.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
python
Ambito
testing-qa
Tipo di issue
Bug
Difficoltà
2/5
Tempo stimato
1-3 ore
Stato di attività
Ferma
Chiarezza
Specificata chiaramente
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.