We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Stream argument to ProfilerMiddleware is not typed hinted correctly
The profiler middleware `src/werkzeug/middleware/profiler.py:80` documentation and implementation states that the argument `stream` can be set to `None` to disable output.
 
However the type hints specifies `stream: t.IO[str] = sys.stdout,` which is inconsistent with the documentation and the implementation.

To replicate the issue run a type hint aware validator against something initiating a `ProfilerMiddleware` with the `stream` argument set to `None`:
```
ProfilerMiddleware(
    app,
    stream=None
)
```
It will cause an error stating that `None` is not an acceptable value for `stream`.

It's a minor and easy fix that I'm happy to provide a PR for if deemed acceptable with the proposed change:
```
stream: t.Union[t.IO[str], None] = sys.stdout,
```

Environment:

- Python version: 3.10
- Werkzeug version: 2.2.3


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/werkzeug/middleware/profiler.py`
Content:
```
1 """
2 Application Profiler
3 ====================
4 
5 This module provides a middleware that profiles each request with the
6 :mod:`cProfile` module. This can help identify bottlenecks in your code
7 that may be slowing down your application.
8 
9 .. autoclass:: ProfilerMiddleware
10 
11 :copyright: 2007 Pallets
12 :license: BSD-3-Clause
13 """
14 import os.path
15 import sys
16 import time
17 import typing as t
18 from pstats import Stats
19 
20 try:
21     from cProfile import Profile
22 except ImportError:
23     from profile import Profile  # type: ignore
24 
25 if t.TYPE_CHECKING:
26     from _typeshed.wsgi import StartResponse
27     from _typeshed.wsgi import WSGIApplication
28     from _typeshed.wsgi import WSGIEnvironment
29 
30 
31 class ProfilerMiddleware:
32     """Wrap a WSGI application and profile the execution of each
33     request. Responses are buffered so that timings are more exact.
34 
35     If ``stream`` is given, :class:`pstats.Stats` are written to it
36     after each request. If ``profile_dir`` is given, :mod:`cProfile`
37     data files are saved to that directory, one file per request.
38 
39     The filename can be customized by passing ``filename_format``. If
40     it is a string, it will be formatted using :meth:`str.format` with
41     the following fields available:
42 
43     -   ``{method}`` - The request method; GET, POST, etc.
44     -   ``{path}`` - The request path or 'root' should one not exist.
45     -   ``{elapsed}`` - The elapsed time of the request.
46     -   ``{time}`` - The time of the request.
47 
48     If it is a callable, it will be called with the WSGI ``environ``
49     dict and should return a filename.
50 
51     :param app: The WSGI application to wrap.
52     :param stream: Write stats to this stream. Disable with ``None``.
53     :param sort_by: A tuple of columns to sort stats by. See
54         :meth:`pstats.Stats.sort_stats`.
55     :param restrictions: A tuple of restrictions to filter stats by. See
56         :meth:`pstats.Stats.print_stats`.
57     :param profile_dir: Save profile data files to this directory.
58     :param filename_format: Format string for profile data file names,
59         or a callable returning a name. See explanation above.
60 
61     .. code-block:: python
62 
63         from werkzeug.middleware.profiler import ProfilerMiddleware
64         app = ProfilerMiddleware(app)
65 
66     .. versionchanged:: 0.15
67         Stats are written even if ``profile_dir`` is given, and can be
68         disable by passing ``stream=None``.
69 
70     .. versionadded:: 0.15
71         Added ``filename_format``.
72 
73     .. versionadded:: 0.9
74         Added ``restrictions`` and ``profile_dir``.
75     """
76 
77     def __init__(
78         self,
79         app: "WSGIApplication",
80         stream: t.IO[str] = sys.stdout,
81         sort_by: t.Iterable[str] = ("time", "calls"),
82         restrictions: t.Iterable[t.Union[str, int, float]] = (),
83         profile_dir: t.Optional[str] = None,
84         filename_format: str = "{method}.{path}.{elapsed:.0f}ms.{time:.0f}.prof",
85     ) -> None:
86         self._app = app
87         self._stream = stream
88         self._sort_by = sort_by
89         self._restrictions = restrictions
90         self._profile_dir = profile_dir
91         self._filename_format = filename_format
92 
93     def __call__(
94         self, environ: "WSGIEnvironment", start_response: "StartResponse"
95     ) -> t.Iterable[bytes]:
96         response_body: t.List[bytes] = []
97 
98         def catching_start_response(status, headers, exc_info=None):  # type: ignore
99             start_response(status, headers, exc_info)
100             return response_body.append
101 
102         def runapp() -> None:
103             app_iter = self._app(
104                 environ, t.cast("StartResponse", catching_start_response)
105             )
106             response_body.extend(app_iter)
107 
108             if hasattr(app_iter, "close"):
109                 app_iter.close()
110 
111         profile = Profile()
112         start = time.time()
113         profile.runcall(runapp)
114         body = b"".join(response_body)
115         elapsed = time.time() - start
116 
117         if self._profile_dir is not None:
118             if callable(self._filename_format):
119                 filename = self._filename_format(environ)
120             else:
121                 filename = self._filename_format.format(
122                     method=environ["REQUEST_METHOD"],
123                     path=environ["PATH_INFO"].strip("/").replace("/", ".") or "root",
124                     elapsed=elapsed * 1000.0,
125                     time=time.time(),
126                 )
127             filename = os.path.join(self._profile_dir, filename)
128             profile.dump_stats(filename)
129 
130         if self._stream is not None:
131             stats = Stats(profile, stream=self._stream)
132             stats.sort_stats(*self._sort_by)
133             print("-" * 80, file=self._stream)
134             path_info = environ.get("PATH_INFO", "")
135             print(f"PATH: {path_info!r}", file=self._stream)
136             stats.print_stats(*self._restrictions)
137             print(f"{'-' * 80}\n", file=self._stream)
138 
139         return [body]
140
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/werkzeug/middleware/profiler.py b/src/werkzeug/middleware/profiler.py
--- a/src/werkzeug/middleware/profiler.py
+++ b/src/werkzeug/middleware/profiler.py
@@ -77,7 +77,7 @@
     def __init__(
         self,
         app: "WSGIApplication",
-        stream: t.IO[str] = sys.stdout,
+        stream: t.Union[t.IO[str], None] = sys.stdout,
         sort_by: t.Iterable[str] = ("time", "calls"),
         restrictions: t.Iterable[t.Union[str, int, float]] = (),
         profile_dir: t.Optional[str] = None,

{"golden_diff": "diff --git a/src/werkzeug/middleware/profiler.py b/src/werkzeug/middleware/profiler.py\n--- a/src/werkzeug/middleware/profiler.py\n+++ b/src/werkzeug/middleware/profiler.py\n@@ -77,7 +77,7 @@\n     def __init__(\n         self,\n         app: \"WSGIApplication\",\n-        stream: t.IO[str] = sys.stdout,\n+        stream: t.Union[t.IO[str], None] = sys.stdout,\n         sort_by: t.Iterable[str] = (\"time\", \"calls\"),\n         restrictions: t.Iterable[t.Union[str, int, float]] = (),\n         profile_dir: t.Optional[str] = None,\n", "issue": "Stream argument to ProfilerMiddleware is not typed hinted correctly\nThe profiler middleware `src/werkzeug/middleware/profiler.py:80` documentation and implementation states that the argument `stream` can be set to `None` to disable output.\r\n \r\nHowever the type hints specifies `stream: t.IO[str] = sys.stdout,` which is inconsistent with the documentation and the implementation.\r\n\r\nTo replicate the issue run a type hint aware validator against something initiating a `ProfilerMiddleware` with the `stream` argument set to `None`:\r\n```\r\nProfilerMiddleware(\r\n    app,\r\n    stream=None\r\n)\r\n```\r\nIt will cause an error stating that `None` is not an acceptable value for `stream`.\r\n\r\nIt's a minor and easy fix that I'm happy to provide a PR for if deemed acceptable with the proposed change:\r\n```\r\nstream: t.Union[t.IO[str], None] = sys.stdout,\r\n```\r\n\r\nEnvironment:\r\n\r\n- Python version: 3.10\r\n- Werkzeug version: 2.2.3\r\n\n", "before_files": [{"content": "\"\"\"\nApplication Profiler\n====================\n\nThis module provides a middleware that profiles each request with the\n:mod:`cProfile` module. This can help identify bottlenecks in your code\nthat may be slowing down your application.\n\n.. autoclass:: ProfilerMiddleware\n\n:copyright: 2007 Pallets\n:license: BSD-3-Clause\n\"\"\"\nimport os.path\nimport sys\nimport time\nimport typing as t\nfrom pstats import Stats\n\ntry:\n    from cProfile import Profile\nexcept ImportError:\n    from profile import Profile  # type: ignore\n\nif t.TYPE_CHECKING:\n    from _typeshed.wsgi import StartResponse\n    from _typeshed.wsgi import WSGIApplication\n    from _typeshed.wsgi import WSGIEnvironment\n\n\nclass ProfilerMiddleware:\n    \"\"\"Wrap a WSGI application and profile the execution of each\n    request. Responses are buffered so that timings are more exact.\n\n    If ``stream`` is given, :class:`pstats.Stats` are written to it\n    after each request. If ``profile_dir`` is given, :mod:`cProfile`\n    data files are saved to that directory, one file per request.\n\n    The filename can be customized by passing ``filename_format``. If\n    it is a string, it will be formatted using :meth:`str.format` with\n    the following fields available:\n\n    -   ``{method}`` - The request method; GET, POST, etc.\n    -   ``{path}`` - The request path or 'root' should one not exist.\n    -   ``{elapsed}`` - The elapsed time of the request.\n    -   ``{time}`` - The time of the request.\n\n    If it is a callable, it will be called with the WSGI ``environ``\n    dict and should return a filename.\n\n    :param app: The WSGI application to wrap.\n    :param stream: Write stats to this stream. Disable with ``None``.\n    :param sort_by: A tuple of columns to sort stats by. See\n        :meth:`pstats.Stats.sort_stats`.\n    :param restrictions: A tuple of restrictions to filter stats by. See\n        :meth:`pstats.Stats.print_stats`.\n    :param profile_dir: Save profile data files to this directory.\n    :param filename_format: Format string for profile data file names,\n        or a callable returning a name. See explanation above.\n\n    .. code-block:: python\n\n        from werkzeug.middleware.profiler import ProfilerMiddleware\n        app = ProfilerMiddleware(app)\n\n    .. versionchanged:: 0.15\n        Stats are written even if ``profile_dir`` is given, and can be\n        disable by passing ``stream=None``.\n\n    .. versionadded:: 0.15\n        Added ``filename_format``.\n\n    .. versionadded:: 0.9\n        Added ``restrictions`` and ``profile_dir``.\n    \"\"\"\n\n    def __init__(\n        self,\n        app: \"WSGIApplication\",\n        stream: t.IO[str] = sys.stdout,\n        sort_by: t.Iterable[str] = (\"time\", \"calls\"),\n        restrictions: t.Iterable[t.Union[str, int, float]] = (),\n        profile_dir: t.Optional[str] = None,\n        filename_format: str = \"{method}.{path}.{elapsed:.0f}ms.{time:.0f}.prof\",\n    ) -> None:\n        self._app = app\n        self._stream = stream\n        self._sort_by = sort_by\n        self._restrictions = restrictions\n        self._profile_dir = profile_dir\n        self._filename_format = filename_format\n\n    def __call__(\n        self, environ: \"WSGIEnvironment\", start_response: \"StartResponse\"\n    ) -> t.Iterable[bytes]:\n        response_body: t.List[bytes] = []\n\n        def catching_start_response(status, headers, exc_info=None):  # type: ignore\n            start_response(status, headers, exc_info)\n            return response_body.append\n\n        def runapp() -> None:\n            app_iter = self._app(\n                environ, t.cast(\"StartResponse\", catching_start_response)\n            )\n            response_body.extend(app_iter)\n\n            if hasattr(app_iter, \"close\"):\n                app_iter.close()\n\n        profile = Profile()\n        start = time.time()\n        profile.runcall(runapp)\n        body = b\"\".join(response_body)\n        elapsed = time.time() - start\n\n        if self._profile_dir is not None:\n            if callable(self._filename_format):\n                filename = self._filename_format(environ)\n            else:\n                filename = self._filename_format.format(\n                    method=environ[\"REQUEST_METHOD\"],\n                    path=environ[\"PATH_INFO\"].strip(\"/\").replace(\"/\", \".\") or \"root\",\n                    elapsed=elapsed * 1000.0,\n                    time=time.time(),\n                )\n            filename = os.path.join(self._profile_dir, filename)\n            profile.dump_stats(filename)\n\n        if self._stream is not None:\n            stats = Stats(profile, stream=self._stream)\n            stats.sort_stats(*self._sort_by)\n            print(\"-\" * 80, file=self._stream)\n            path_info = environ.get(\"PATH_INFO\", \"\")\n            print(f\"PATH: {path_info!r}\", file=self._stream)\n            stats.print_stats(*self._restrictions)\n            print(f\"{'-' * 80}\\n\", file=self._stream)\n\n        return [body]\n", "path": "src/werkzeug/middleware/profiler.py"}], "after_files": [{"content": "\"\"\"\nApplication Profiler\n====================\n\nThis module provides a middleware that profiles each request with the\n:mod:`cProfile` module. This can help identify bottlenecks in your code\nthat may be slowing down your application.\n\n.. autoclass:: ProfilerMiddleware\n\n:copyright: 2007 Pallets\n:license: BSD-3-Clause\n\"\"\"\nimport os.path\nimport sys\nimport time\nimport typing as t\nfrom pstats import Stats\n\ntry:\n    from cProfile import Profile\nexcept ImportError:\n    from profile import Profile  # type: ignore\n\nif t.TYPE_CHECKING:\n    from _typeshed.wsgi import StartResponse\n    from _typeshed.wsgi import WSGIApplication\n    from _typeshed.wsgi import WSGIEnvironment\n\n\nclass ProfilerMiddleware:\n    \"\"\"Wrap a WSGI application and profile the execution of each\n    request. Responses are buffered so that timings are more exact.\n\n    If ``stream`` is given, :class:`pstats.Stats` are written to it\n    after each request. If ``profile_dir`` is given, :mod:`cProfile`\n    data files are saved to that directory, one file per request.\n\n    The filename can be customized by passing ``filename_format``. If\n    it is a string, it will be formatted using :meth:`str.format` with\n    the following fields available:\n\n    -   ``{method}`` - The request method; GET, POST, etc.\n    -   ``{path}`` - The request path or 'root' should one not exist.\n    -   ``{elapsed}`` - The elapsed time of the request.\n    -   ``{time}`` - The time of the request.\n\n    If it is a callable, it will be called with the WSGI ``environ``\n    dict and should return a filename.\n\n    :param app: The WSGI application to wrap.\n    :param stream: Write stats to this stream. Disable with ``None``.\n    :param sort_by: A tuple of columns to sort stats by. See\n        :meth:`pstats.Stats.sort_stats`.\n    :param restrictions: A tuple of restrictions to filter stats by. See\n        :meth:`pstats.Stats.print_stats`.\n    :param profile_dir: Save profile data files to this directory.\n    :param filename_format: Format string for profile data file names,\n        or a callable returning a name. See explanation above.\n\n    .. code-block:: python\n\n        from werkzeug.middleware.profiler import ProfilerMiddleware\n        app = ProfilerMiddleware(app)\n\n    .. versionchanged:: 0.15\n        Stats are written even if ``profile_dir`` is given, and can be\n        disable by passing ``stream=None``.\n\n    .. versionadded:: 0.15\n        Added ``filename_format``.\n\n    .. versionadded:: 0.9\n        Added ``restrictions`` and ``profile_dir``.\n    \"\"\"\n\n    def __init__(\n        self,\n        app: \"WSGIApplication\",\n        stream: t.Union[t.IO[str], None] = sys.stdout,\n        sort_by: t.Iterable[str] = (\"time\", \"calls\"),\n        restrictions: t.Iterable[t.Union[str, int, float]] = (),\n        profile_dir: t.Optional[str] = None,\n        filename_format: str = \"{method}.{path}.{elapsed:.0f}ms.{time:.0f}.prof\",\n    ) -> None:\n        self._app = app\n        self._stream = stream\n        self._sort_by = sort_by\n        self._restrictions = restrictions\n        self._profile_dir = profile_dir\n        self._filename_format = filename_format\n\n    def __call__(\n        self, environ: \"WSGIEnvironment\", start_response: \"StartResponse\"\n    ) -> t.Iterable[bytes]:\n        response_body: t.List[bytes] = []\n\n        def catching_start_response(status, headers, exc_info=None):  # type: ignore\n            start_response(status, headers, exc_info)\n            return response_body.append\n\n        def runapp() -> None:\n            app_iter = self._app(\n                environ, t.cast(\"StartResponse\", catching_start_response)\n            )\n            response_body.extend(app_iter)\n\n            if hasattr(app_iter, \"close\"):\n                app_iter.close()\n\n        profile = Profile()\n        start = time.time()\n        profile.runcall(runapp)\n        body = b\"\".join(response_body)\n        elapsed = time.time() - start\n\n        if self._profile_dir is not None:\n            if callable(self._filename_format):\n                filename = self._filename_format(environ)\n            else:\n                filename = self._filename_format.format(\n                    method=environ[\"REQUEST_METHOD\"],\n                    path=environ[\"PATH_INFO\"].strip(\"/\").replace(\"/\", \".\") or \"root\",\n                    elapsed=elapsed * 1000.0,\n                    time=time.time(),\n                )\n            filename = os.path.join(self._profile_dir, filename)\n            profile.dump_stats(filename)\n\n        if self._stream is not None:\n            stats = Stats(profile, stream=self._stream)\n            stats.sort_stats(*self._sort_by)\n            print(\"-\" * 80, file=self._stream)\n            path_info = environ.get(\"PATH_INFO\", \"\")\n            print(f\"PATH: {path_info!r}\", file=self._stream)\n            stats.print_stats(*self._restrictions)\n            print(f\"{'-' * 80}\\n\", file=self._stream)\n\n        return [body]\n", "path": "src/werkzeug/middleware/profiler.py"}]}