The WSGI specification requires that all middlewares and gateways respect the `close` callback of the iterable returned by the application. Because it is useful to add another close action to a returned iterable and adding a custom iterable is a boring task this class can be used for
| 223 | |
| 224 | |
| 225 | class ClosingIterator: |
| 226 | """The WSGI specification requires that all middlewares and gateways |
| 227 | respect the `close` callback of the iterable returned by the application. |
| 228 | Because it is useful to add another close action to a returned iterable |
| 229 | and adding a custom iterable is a boring task this class can be used for |
| 230 | that:: |
| 231 | |
| 232 | return ClosingIterator(app(environ, start_response), [cleanup_session, |
| 233 | cleanup_locals]) |
| 234 | |
| 235 | If there is just one close function it can be passed instead of the list. |
| 236 | |
| 237 | A closing iterator is not needed if the application uses response objects |
| 238 | and finishes the processing if the response is started:: |
| 239 | |
| 240 | try: |
| 241 | return response(environ, start_response) |
| 242 | finally: |
| 243 | cleanup_session() |
| 244 | cleanup_locals() |
| 245 | """ |
| 246 | |
| 247 | def __init__( |
| 248 | self, |
| 249 | iterable: t.Iterable[bytes], |
| 250 | callbacks: None |
| 251 | | (t.Callable[[], None] | t.Iterable[t.Callable[[], None]]) = None, |
| 252 | ) -> None: |
| 253 | iterator = iter(iterable) |
| 254 | self._next = t.cast(t.Callable[[], bytes], partial(next, iterator)) |
| 255 | if callbacks is None: |
| 256 | callbacks = [] |
| 257 | elif callable(callbacks): |
| 258 | callbacks = [callbacks] |
| 259 | else: |
| 260 | callbacks = list(callbacks) |
| 261 | iterable_close = getattr(iterable, "close", None) |
| 262 | if iterable_close: |
| 263 | callbacks.insert(0, iterable_close) |
| 264 | self._callbacks = callbacks |
| 265 | |
| 266 | def __iter__(self) -> ClosingIterator: |
| 267 | return self |
| 268 | |
| 269 | def __next__(self) -> bytes: |
| 270 | return self._next() |
| 271 | |
| 272 | def close(self) -> None: |
| 273 | for callback in self._callbacks: |
| 274 | callback() |
| 275 | |
| 276 | |
| 277 | def wrap_file( |
no outgoing calls