view.py
view.py copied to clipboard
Yielded Responses
Feature description
As a means of making things easier for the developer, View could support using yield as a means of returning a partial response. For example, the user could yield a status code early on, and then return the body at the end of the function. Likewise, they can do the inverse and yield the response, and then finally return the status code.
Multiple yields of the same data (such as a int, indicating a status code, followed by another int, once again indicating a status code) should do what they can to merge. For example, two strings yielded would result in them being concatenated, and two dictionaries would result in them being merged (PyDict_Merge in C, but dict.update in Python). Integers should probably just overwrite each other, so 200 followed by 400 would result in 400.
This should try to be as asynchronous as possible. I'm not too sure about the semantics, but I'm assuming the generator can just be exhausted after receiving it from the PyAwaitable callback. If that's so, there shouldn't be too much view.py has to do, but if not, then there might be some chaos in terms of sending generators back and forth between PyAwaitable.
As a final note, if we're going to be messing with the PyAwaitable anyway, something similar to Starlette's background tasks could be integrated, allowing the user to yield coroutines to be executed later by the event loop.
Feature example API
from view import new_app
app = new_app()
@app.get("/")
async def index():
yield {"hello": "world"}
if "foo" != "bar":
yield {"foo_is_not": "bar"}
yield 201
if "something":
yield some_funny_coro()
return "Hello, view.py!"
app.run()
Anything else?
No response
Note that this should stream the response incrementally as well.