gh-86178: Add wsgiref.types (GH-32335)

This commit is contained in:
Sebastian Rittau 2022-04-16 19:37:58 +02:00 committed by GitHub
parent 1adc837bf1
commit 0ddc63b240
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 123 additions and 7 deletions

View File

@ -23,6 +23,7 @@ an existing framework.
be used to add WSGI support to a web server or framework. It provides utilities
for manipulating WSGI environment variables and response headers, base classes
for implementing WSGI servers, a demo HTTP server that serves WSGI applications,
types for static type checking,
and a validation tool that checks WSGI servers and applications for conformance
to the WSGI specification (:pep:`3333`).
@ -43,7 +44,9 @@ This module provides a variety of utility functions for working with WSGI
environments. A WSGI environment is a dictionary containing HTTP request
variables as described in :pep:`3333`. All of the functions taking an *environ*
parameter expect a WSGI-compliant dictionary to be supplied; please see
:pep:`3333` for a detailed specification.
:pep:`3333` for a detailed specification and
:data:`~wsgiref.types.WSGIEnvironment` for a type alias that can be used
in type annotations.
.. function:: guess_scheme(environ)
@ -150,7 +153,9 @@ also provides these miscellaneous utilities:
.. class:: FileWrapper(filelike, blksize=8192)
A wrapper to convert a file-like object to an :term:`iterator`. The resulting objects
A concrete implementation of the :class:`wsgiref.types.FileWrapper`
protocol used to convert a file-like object to an :term:`iterator`.
The resulting objects
are :term:`iterable`\ s. As the object is iterated over, the
optional *blksize* parameter will be repeatedly passed to the *filelike*
object's :meth:`read` method to obtain bytestrings to yield. When :meth:`read`
@ -349,7 +354,8 @@ request. (E.g., using the :func:`shift_path_info` function from
.. method:: WSGIRequestHandler.get_environ()
Returns a dictionary containing the WSGI environment for a request. The default
Return a :data:`~wsgiref.types.WSGIEnvironment` dictionary for a
request. The default
implementation copies the contents of the :class:`WSGIServer` object's
:attr:`base_environ` dictionary attribute and then adds various headers derived
from the HTTP request. Each call to this method should return a new dictionary
@ -558,13 +564,15 @@ input, output, and error streams.
.. method:: BaseHandler.get_stdin()
Return an input stream object suitable for use as the ``wsgi.input`` of the
Return an object compatible with :class:`~wsgiref.types.InputStream`
suitable for use as the ``wsgi.input`` of the
request currently being processed.
.. method:: BaseHandler.get_stderr()
Return an output stream object suitable for use as the ``wsgi.errors`` of the
Return an object compatible with :class:`~wsgiref.types.ErrorStream`
suitable for use as the ``wsgi.errors`` of the
request currently being processed.
@ -703,8 +711,9 @@ input, output, and error streams.
.. attribute:: BaseHandler.wsgi_file_wrapper
A ``wsgi.file_wrapper`` factory, or ``None``. The default value of this
attribute is the :class:`wsgiref.util.FileWrapper` class.
A ``wsgi.file_wrapper`` factory, compatible with
:class:`wsgiref.types.FileWrapper`, or ``None``. The default value
of this attribute is the :class:`wsgiref.util.FileWrapper` class.
.. method:: BaseHandler.sendfile()
@ -754,6 +763,51 @@ input, output, and error streams.
.. versionadded:: 3.2
:mod:`wsgiref.types` -- WSGI types for static type checking
-----------------------------------------------------------
.. module:: wsgiref.types
:synopsis: WSGI types for static type checking
This module provides various types for static type checking as described
in :pep:`3333`.
.. versionadded:: 3.11
.. class:: StartResponse()
A :class:`typing.Protocol` describing `start_response()
<https://peps.python.org/pep-3333/#the-start-response-callable>`_
callables (:pep:`3333`).
.. data:: WSGIEnvironment
A type alias describing a WSGI environment dictionary.
.. data:: WSGIApplication
A type alias describing a WSGI application callable.
.. class:: InputStream()
A :class:`typing.Protocol` describing a `WSGI Input Stream
<https://peps.python.org/pep-3333/#input-and-error-streams>`_.
.. class:: ErrorStream()
A :class:`typing.Protocol` describing a `WSGI Error Stream
<https://peps.python.org/pep-3333/#input-and-error-streams>`_.
.. class:: FileWrapper()
A :class:`typing.Protocol` describing a `file wrapper
<https://peps.python.org/pep-3333/#optional-platform-specific-file-handling>`_.
See :class:`wsgiref.util.FileWrapper` for a concrete implementation of this
protocol.
Examples
--------

View File

@ -233,6 +233,10 @@ New Modules
* A new module, :mod:`tomllib`, was added for parsing TOML.
(Contributed by Taneli Hukkinen in :issue:`40059`.)
* :mod:`wsgiref.types`, containing WSGI-specific types for static type
checking, was added.
(Contributed by Sebastian Rittau in :issue:`42012`.)
Improved Modules
================

View File

@ -13,6 +13,8 @@ Current Contents:
* validate -- validation wrapper that sits between an app and a server
to detect errors in either
* types -- collection of WSGI-related types for static type checking
To-Do:
* cgi_gateway -- Run WSGI apps under CGI (pending a deployment standard)

54
Lib/wsgiref/types.py Normal file
View File

@ -0,0 +1,54 @@
"""WSGI-related types for static type checking"""
from collections.abc import Callable, Iterable
from types import TracebackType
from typing import Any, Protocol, TypeAlias
__all__ = [
"StartResponse",
"WSGIEnvironment",
"WSGIApplication",
"InputStream",
"ErrorStream",
"FileWrapper",
]
_ExcInfo = tuple[type[BaseException], BaseException, TracebackType]
_OptExcInfo = _ExcInfo | tuple[None, None, None]
class StartResponse(Protocol):
"""start_response() callable as defined in PEP 3333"""
def __call__(
self,
status: str,
headers: list[tuple[str, str]],
exc_info: _OptExcInfo | None = ...,
/,
) -> Callable[[bytes], object]: ...
WSGIEnvironment: TypeAlias = dict[str, Any]
WSGIApplication: TypeAlias = Callable[[WSGIEnvironment, StartResponse],
Iterable[bytes]]
class InputStream(Protocol):
"""WSGI input stream as defined in PEP 3333"""
def read(self, size: int = ..., /) -> bytes: ...
def readline(self, size: int = ..., /) -> bytes: ...
def readlines(self, hint: int = ..., /) -> list[bytes]: ...
def __iter__(self) -> Iterable[bytes]: ...
class ErrorStream(Protocol):
"""WSGI error stream as defined in PEP 3333"""
def flush(self) -> object: ...
def write(self, s: str, /) -> object: ...
def writelines(self, seq: list[str], /) -> object: ...
class _Readable(Protocol):
def read(self, size: int = ..., /) -> bytes: ...
# Optional: def close(self) -> object: ...
class FileWrapper(Protocol):
"""WSGI file wrapper as defined in PEP 3333"""
def __call__(
self, file: _Readable, block_size: int = ..., /,
) -> Iterable[bytes]: ...

View File

@ -0,0 +1,2 @@
Add :mod:`wsgiref.types`, containing WSGI-specific types for static type
checking.