aio-libs / aiohttp

Asynchronous HTTP client/server framework for asyncio and Python
https://docs.aiohttp.org
Other
15.13k stars 2.02k forks source link

Registered functors raise a bare func deprecation warning #4519

Closed vmarkovtsev closed 4 years ago

vmarkovtsev commented 4 years ago

Long story short

Class instance with async def __call__ triggers DeprecationWarning: Bare functions are deprecated. This is different from #3252 where functools.partial generates a sync def __call__.

Steps to reproduce

class AsyncPartial:
    def __init__(self, arg):
        self.arg = arg

    async def __call__(self, request):
        return do_smth_with(request, self.arg)

app.router.add_get("/xxx", AsyncPartial(42))  # DeprecationWarning
app.router.add_get("/xxx", AsyncPartial(42).__call__)  # No warning, ugly

Your environment

Python 3.7.5 aiohttp 3.6.2

asvetlov commented 4 years ago

Sorry, the problem is out of aiohttp scope. asyncio.iscoroutinefunction() (or ispect.iscoroutinefunction()) should be fixed. See also https://bugs.python.org/issue38225 discussion

vmarkovtsev commented 4 years ago

@asvetlov when you are saying "out of scope", you really mean that I should file a dedicated bug report on bugs.python.org, correct?

asvetlov commented 4 years ago

I think we need to make decision about mentioned issue, select the attribute name, and write a patch for cpython. Nothing to do on aiohttp side

vmarkovtsev commented 4 years ago

@asvetlov Sorry, I am not sure what you mean. aiohttp is irrelevant - this one I don't doubt and I understood at once :smile:

What decision? Do you mean whether that is officially acknowledged on bugs.python.org? Which attribute, do you mean __call__? Why select the name? Do you mean adding another check in the iscoroutinefunction() implementation? :question:

What shall I do in the end? Clone this issue to bugs.python.org? Submit a cpython patch for your consideration? Do nothing and you've got it covered?

asvetlov commented 4 years ago

I mean something like the following may work eventually after making https://bugs.python.org/issue38225 done:

class A:
    async def __call__(self, *args):
        pass

    __call__.__async__ = True

I have no evidence if this feature will be implemented this way until a (not existing yet) pull request is landed. The next step on moving the issue forward is making a tested prototype. Caution, it can take longer and harder than you expect if you have no experience of hacking CPython.