Repository: aio-libs/aiohttp

Issue:
Type annotations: `print` parameter of `run_app` should be `Optional`
### Describe the bug

The [documentation](https://docs.aiohttp.org/en/stable/web_reference.html#aiohttp.web.run_app) says the following about `run_app`'s `print` parameter:

> Passing None disables output.

Looking at the code, this looks correct:

https://github.com/aio-libs/aiohttp/blob/1f97c55a93c4dd7e7dfe9b5850bdbfa0daa273de/aiohttp/web.py#L419-L424

However, the `print` parameter is typed as a `Callable`, which does not allow a value of `None`. It should be an `Optional[Callable[...]]`.

### To Reproduce

1. Call `run_app` with a `print` parameter set to `None`
2. Run `mypy`

### Expected behavior

`mypy` is not complaining about passing `None` to `print`.

### Logs/tracebacks

```python-traceback
$ mypy --show-error-codes .
xxxx.py:yy: error: Argument "print" to "run_app" has incompatible type "None"; expected "Callable[..., None]"  [arg-type]
```


### Python Version

```console
$ python --version
Python 3.10.8
```


### aiohttp Version

```console
$ python -m pip show aiohttp
Name: aiohttp
Version: 3.8.3
Summary: Async http client/server framework (asyncio)
Home-page: https://github.com/aio-libs/aiohttp
Author: 
Author-email: 
License: Apache 2
Location: /home/babolivier/.virtualenvs/mcs-py310/lib/python3.10/site-packages
Requires: aiosignal, async-timeout, attrs, charset-normalizer, frozenlist, multidict, yarl
Required-by: mautrix
```


### multidict Version

```console
$ python -m pip show multidict
Name: multidict
Version: 6.0.2
Summary: multidict implementation
Home-page: https://github.com/aio-libs/multidict
Author: Andrew Svetlov
Author-email: andrew.svetlov@gmail.com
License: Apache 2
Location: /home/babolivier/.virtualenvs/mcs-py310/lib/python3.10/site-packages
Requires: 
Required-by: aiohttp, yarl
```


### yarl Version

```console
$ python -m pip show yarl
Name: yarl
Version: 1.8.1
Summary: Yet another URL library
Home-page: https://github.com/aio-libs/yarl/
Author: Andrew Svetlov
Author-email: andrew.svetlov@gmail.com
License: Apache 2
Location: /home/babolivier/.virtualenvs/mcs-py310/lib/python3.10/site-packages
Requires: idna, multidict
Required-by: aiohttp, mautrix
```


### OS

Arch Linux

### Related component

Server

### Additional context

_No response_

### Code of Conduct

- [X] I agree to follow the aio-libs Code of Conduct
Type annotations: `print` parameter of `run_app` should be `Optional`
### Describe the bug

The [documentation](https://docs.aiohttp.org/en/stable/web_reference.html#aiohttp.web.run_app) says the following about `run_app`'s `print` parameter:

> Passing None disables output.

Looking at the code, this looks correct:

https://github.com/aio-libs/aiohttp/blob/1f97c55a93c4dd7e7dfe9b5850bdbfa0daa273de/aiohttp/web.py#L419-L424

However, the `print` parameter is typed as a `Callable`, which does not allow a value of `None`. It should be an `Optional[Callable[...]]`.

### To Reproduce

1. Call `run_app` with a `print` parameter set to `None`
2. Run `mypy`

### Expected behavior

`mypy` is not complaining about passing `None` to `print`.

### Logs/tracebacks

```python-traceback
$ mypy --show-error-codes .
xxxx.py:yy: error: Argument "print" to "run_app" has incompatible type "None"; expected "Callable[..., None]"  [arg-type]
```


### Python Version

```console
$ python --version
Python 3.10.8
```


### aiohttp Version

```console
$ python -m pip show aiohttp
Name: aiohttp
Version: 3.8.3
Summary: Async http client/server framework (asyncio)
Home-page: https://github.com/aio-libs/aiohttp
Author: 
Author-email: 
License: Apache 2
Location: /home/babolivier/.virtualenvs/mcs-py310/lib/python3.10/site-packages
Requires: aiosignal, async-timeout, attrs, charset-normalizer, frozenlist, multidict, yarl
Required-by: mautrix
```


### multidict Version

```console
$ python -m pip show multidict
Name: multidict
Version: 6.0.2
Summary: multidict implementation
Home-page: https://github.com/aio-libs/multidict
Author: Andrew Svetlov
Author-email: andrew.svetlov@gmail.com
License: Apache 2
Location: /home/babolivier/.virtualenvs/mcs-py310/lib/python3.10/site-packages
Requires: 
Required-by: aiohttp, yarl
```


### yarl Version

```console
$ python -m pip show yarl
Name: yarl
Version: 1.8.1
Summary: Yet another URL library
Home-page: https://github.com/aio-libs/yarl/
Author: Andrew Svetlov
Author-email: andrew.svetlov@gmail.com
License: Apache 2
Location: /home/babolivier/.virtualenvs/mcs-py310/lib/python3.10/site-packages
Requires: idna, multidict
Required-by: aiohttp, mautrix
```


### OS

Arch Linux

### Related component

Server

### Additional context

_No response_

### Code of Conduct

- [X] I agree to follow the aio-libs Code of Conduct


Discussion:

Resolving patch:
diff --git a/aiohttp/web.py b/aiohttp/web.py
--- a/aiohttp/web.py
+++ b/aiohttp/web.py
@@ -299,7 +299,7 @@ async def _run_app(
     shutdown_timeout: float = 60.0,
     keepalive_timeout: float = 75.0,
     ssl_context: Optional[SSLContext] = None,
-    print: Callable[..., None] = print,
+    print: Optional[Callable[..., None]] = print,
     backlog: int = 128,
     access_log_class: Type[AbstractAccessLogger] = AccessLogger,
     access_log_format: str = AccessLogger.LOG_FORMAT,
@@ -474,7 +474,7 @@ def run_app(
     shutdown_timeout: float = 60.0,
     keepalive_timeout: float = 75.0,
     ssl_context: Optional[SSLContext] = None,
-    print: Callable[..., None] = print,
+    print: Optional[Callable[..., None]] = print,
     backlog: int = 128,
     access_log_class: Type[AbstractAccessLogger] = AccessLogger,
     access_log_format: str = AccessLogger.LOG_FORMAT,


Test patch: