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

Replace eval with eval_code_async to support top level await #125

Closed
whitphx opened this issue Aug 17, 2022 · 3 comments · Fixed by #514
Closed

Replace eval with eval_code_async to support top level await #125

whitphx opened this issue Aug 17, 2022 · 3 comments · Fixed by #514

Comments

@whitphx
Copy link
Owner

whitphx commented Aug 17, 2022

In the Pyodide environment, there are some restrictions for example time.sleep() cannot be used. Using async methods such as asyncio.sleep() would be the workaround, but in Streamlit app scripts it's not possible because Streamlit executes the script with eval() so the top-level await-s cannot be used.

So try to replace the native eval() with pyodide.code.eval_code_async: https://pyodide.org/en/stable/usage/api/python-api/code.html#pyodide.code.eval_code_async to support the top-level await-s in the user scripts.

@stefanonardo
Copy link

Hi @whitphx , is there any update on this?

@whitphx
Copy link
Owner Author

whitphx commented Mar 4, 2023

Hmm, it's not straightforward.

It's not eval() but exec() that is used in Streamlit.
https://github.com/streamlit/streamlit/blob/1.19.0/lib/streamlit/runtime/scriptrunner/script_runner.py#L565
It seems not to be simply replaced with Pyodide's async exec?


Possible options:

  • Manipulate the code fed to exec() to be async by wrapping the original code with async def some_func(): and asyncio.run().

@whitphx
Copy link
Owner Author

whitphx commented Mar 19, 2023

The solution would be whitphx/streamlit@d116796

  • compile the source code with ast.PyCF_ALLOW_TOP_LEVEL_AWAIT, which outputs the code object as a coroutine when the source includes top-level await-s.
  • Run the compiled code object with eval() instead of exec() when the code object is a coroutine so that the eval-ed coroutine is awaited. To await the eval-ed coroutine, its wrapper method, ScriptRunner._run_script(), needed to be modified to be an async function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants