python / python/cpython

async callable not awaited in side_effect for AsyncMock

Aberta
#156,460 1 comentário 0 reações 0 responsáveis Ver no GitHub

Ninguém assumiu esta issue ainda.

stdlib type-bug
Linguagem predominante
Python
Estrelas
77.2k
Forks
36k
Métricas de merge de PRs
Métricas de PR pendentes

Descrição

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

Guia de contribuição

Abrir o guia de contribuição

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Direção de pesquisa

Comece em Lib/unittest/mock.py, em AsyncMockMixin._execute_mock_call, e analise o PR vinculado gh-156465. Confirme o comportamento de um objeto cujo método assíncrono call é usado como AsyncMock.side_effect e adicione ou atualize a cobertura de regressão para que esse objeto chamável seja corretamente aguardado.

Escrita pelo modelo de indexação a partir do texto da issue.

Avaliação

Stack de tecnologia
python
Domínio
testing-qa
Tipo de issue
Bug
Dificuldade
2/5
Tempo estimado
1-3 horas
Status de atividade
Estagnada
Clareza
Claramente especificada
Facilidade para iniciantes
35/100

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.