]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-86178: Add wsgiref.types (GH-32335)
authorSebastian Rittau <srittau@rittau.biz>
Sat, 16 Apr 2022 17:37:58 +0000 (19:37 +0200)
committerGitHub <noreply@github.com>
Sat, 16 Apr 2022 17:37:58 +0000 (10:37 -0700)
Doc/library/wsgiref.rst
Doc/whatsnew/3.11.rst
Lib/wsgiref/__init__.py
Lib/wsgiref/types.py [new file with mode: 0644]
Misc/NEWS.d/next/Library/2022-04-05-17-18-13.bpo-42012.zMocQz.rst [new file with mode: 0644]

index e924448b86d7f379cc328e33d00cf4bbb9e9597d..0ca7b003bf4dd21e0e82c3d104c2ff6780b71ac1 100644 (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
 --------
 
index b5b2a7648c55ea51646e0ef872b54fd70404837d..19e3d2f92fb948864f6e757943dbdf440c0ee728 100644 (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
 ================
index 1efbba01a306ea075777ae00c6403fdba96b44bd..59ee48fddec232b485a3559f7ccc80585616dfd7 100644 (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)
diff --git a/Lib/wsgiref/types.py b/Lib/wsgiref/types.py
new file mode 100644 (file)
index 0000000..4a519e5
--- /dev/null
@@ -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]: ...
diff --git a/Misc/NEWS.d/next/Library/2022-04-05-17-18-13.bpo-42012.zMocQz.rst b/Misc/NEWS.d/next/Library/2022-04-05-17-18-13.bpo-42012.zMocQz.rst
new file mode 100644 (file)
index 0000000..ba84041
--- /dev/null
@@ -0,0 +1,2 @@
+Add :mod:`wsgiref.types`, containing WSGI-specific types for static type
+checking.