()
| 112 | return update_wrapper(decorator, generator_or_function) # type: ignore[arg-type] |
| 113 | |
| 114 | def generator() -> t.Iterator[t.AnyStr]: |
| 115 | if (req_ctx := _cv_request.get(None)) is None: |
| 116 | raise RuntimeError( |
| 117 | "'stream_with_context' can only be used when a request" |
| 118 | " context is active, such as in a view function." |
| 119 | ) |
| 120 | |
| 121 | app_ctx = _cv_app.get() |
| 122 | # Setup code below will run the generator to this point, so that the |
| 123 | # current contexts are recorded. The contexts must be pushed after, |
| 124 | # otherwise their ContextVar will record the wrong event loop during |
| 125 | # async view functions. |
| 126 | yield None # type: ignore[misc] |
| 127 | |
| 128 | # Push the app context first, so that the request context does not |
| 129 | # automatically create and push a different app context. |
| 130 | with app_ctx, req_ctx: |
| 131 | try: |
| 132 | yield from gen |
| 133 | finally: |
| 134 | # Clean up in case the user wrapped a WSGI iterator. |
| 135 | if hasattr(gen, "close"): |
| 136 | gen.close() |
| 137 | |
| 138 | # Execute the generator to the sentinel value. This ensures the context is |
| 139 | # preserved in the generator's state. Further iteration will push the |
no test coverage detected