Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async Coroutine was never awaited. (Missing __await__ method) #506

Open
TheMasteredPanda opened this issue Aug 23, 2022 · 5 comments
Open
Assignees
Labels
Feature Request for developer-valued functionality Help Wanted Help wanted to get a resolution implemented faster To Start Description reviewed and a maintainer needs "to start" triage

Comments

@TheMasteredPanda
Copy link

Describe the issue briefly here, including:

Testing out RpyC for the groundwork of a project. I've setup a custom service that runs Discord.py on a seperate thread while RpyC runs on the main thread. I expected, from studying the documentation on RpyC, that the async_ wrapper is used for remote execution of asynchronous functions, and that executing a function wrapped in async_ would produce, in my case, a text message sent on on a text channel in a Discord Server.

The actual result is an error that is thrown service side stating that the "coroutine 'Messable.send' was never awaited".

Steps to reproduce:
Copy the server code into a script and run, obviously you'll need to fetch a key from the Discord Developer Console.
Run the client code in a script, you'll need to create a Discord guild/server you to add the bot to as well as supply the correct guild id and channel id. the result should produce the same error I have.

/home/johndoe/.local/lib/python3.10/site-packages/rpyc/core/protocol.py:362: RuntimeWarning: coroutine 'Messageable.send' was never awaited
  self._dispatch_request(seq, args)
Environment
  • rpyc version: 5.2.3
  • python version: 3.10
  • operating system: Kali Linux
Minimal example

Server:

from threading import Thread
import rpyc
from rpyc.utils.server import ThreadedServer
import discord
from discord.ext.commands import Bot, when_mentioned_or
import asyncio

client = discord.Client(intents=discord.Intents.all())

class DiscordService(rpyc.Service):
    def __init__(self):
        super().__init__()
        loop = asyncio.get_event_loop()
        loop.create_task(client.start('key'))
        Thread(target=loop.run_forever).start()
        print('Started Client.')

    exposed_client = client

    @client.event
    async def on_ready():
        await client.get_channel(836607364832296990).send('This is from the service')


t = ThreadedServer(DiscordService(), port=18861, protocol_config={'allow_public_attrs': True})
print('Starting service.')
t

Client:

import rpyc
from rpyc.utils.helpers import _Async
import discord
import asyncio

conn = rpyc.connect('localhost', port=18861)
d_client: discord.Client = conn.root.exposed_client
channel: discord.TextChannel = d_client.get_guild(412361411159785493).get_channel(836607364832296990)
channel_send = rpyc.async_(channel.send)
c_result = channel_send('testing')
c_result.wait()

For benefit of ease, the function I am attempting to execute clientside (the send function): https://discordpy.readthedocs.io/en/stable/api.html?highlight=textchannel#discord.TextChannel.send

@notEvil
Copy link

notEvil commented Sep 15, 2022

The error you get is not related to rpyc. You try to call an async function outside of an event loop.

I expected, from studying the documentation on RpyC, that the async_ wrapper is used for remote execution of asynchronous functions,

rpyc is not async in asyncio terminology. rpyc.async_ gives you the opportunity to do things while the remote is busy, but its still synchronous

@comrumino
Copy link
Collaborator

comrumino commented Sep 16, 2022

@notEvil is correct. There is room for improvement in the current design. Since that functionality was released in 2015 and tracing the source for async_.py goes all the way back to 2009, I think AsyncResult is in need of an update.

It seems that the current design is older than awaitable objects and coroutine functions. I think the starting point here is seeing if what functionality is needed:

  • the __await__ method on the AsyncResult object.
  • considering making __await__ a safe attribute, in rpyc/core/protocol.py
  • determine if we can enhance AsyncResult in a backwards compatible way.

@comrumino comrumino self-assigned this Sep 16, 2022
@comrumino comrumino added Help Wanted Help wanted to get a resolution implemented faster To Start Description reviewed and a maintainer needs "to start" triage Feature Request for developer-valued functionality labels Sep 16, 2022
@comrumino comrumino changed the title Async Coroutine was never awaited. Async Coroutine was never awaited. (Missing __await__ method) Sep 16, 2022
@eliiik
Copy link

eliiik commented Nov 24, 2023

Any update on it? want this feature, too

@glyh
Copy link

glyh commented Apr 19, 2024

If there's nobody working on this I may take a look on it.

@comrumino
Copy link
Collaborator

I'm always open to taking PRs. I haven't spent as much time as I used to maintaining RPyC since my current employer does not use it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature Request for developer-valued functionality Help Wanted Help wanted to get a resolution implemented faster To Start Description reviewed and a maintainer needs "to start" triage
Projects
None yet
Development

No branches or pull requests

5 participants