Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: mypy issues #990

Merged
merged 5 commits into from
May 29, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ files =
uvicorn/lifespan,
tests/test_lifespan.py,
uvicorn/importer.py,
uvicorn/protocols/utils.py
uvicorn/protocols/utils.py,
uvicorn/loops,
uvicorn/main.py,
uvicorn/workers.py,
uvicorn/protocols/http/auto.py,
uvicorn/protocols/websockets/auto.py,
uvicorn/supervisors/__init__.py


[mypy-tests.*]
Expand Down
3 changes: 2 additions & 1 deletion uvicorn/loops/asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import sys


def asyncio_setup():
def asyncio_setup() -> None:
loop: asyncio.AbstractEventLoop
if (
sys.version_info.major >= 3
and sys.version_info.minor >= 8
Expand Down
2 changes: 1 addition & 1 deletion uvicorn/loops/auto.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
def auto_loop_setup():
def auto_loop_setup() -> None:
try:
import uvloop # noqa
except ImportError: # pragma: no cover
Expand Down
2 changes: 1 addition & 1 deletion uvicorn/loops/uvloop.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
import uvloop


def uvloop_setup():
def uvloop_setup() -> None:
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
17 changes: 7 additions & 10 deletions uvicorn/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
logger = logging.getLogger("uvicorn.error")


def print_version(ctx, param, value):
def print_version(ctx: click.Context, param: click.Parameter, value: bool) -> None:
if not value or ctx.resilient_parsing:
return
click.echo(
Expand Down Expand Up @@ -281,7 +281,7 @@ def print_version(ctx, param, value):
show_default=True,
)
def main(
app,
app: str,
host: str,
port: int,
uds: str,
Expand Down Expand Up @@ -318,11 +318,10 @@ def main(
use_colors: bool,
app_dir: str,
factory: bool,
):
) -> None:
sys.path.insert(0, app_dir)

kwargs = {
"app": app,
"host": host,
"port": port,
"uds": uds,
Expand Down Expand Up @@ -359,10 +358,10 @@ def main(
"use_colors": use_colors,
"factory": factory,
}
run(**kwargs)
run(app, **kwargs)


def run(app, **kwargs):
def run(app: str, **kwargs: typing.Any) -> None:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#990 (comment)

I'm not sure if the app parameter on run() should be str? 🤔 On the main I think it is, but on run, should it? On Config, I'm sure it's not.

As mentioned in the related PR #992, app: Union[ASGIApplication, str] could work, based on the definition added to uvicorn._types. If not, a less strict annotation like Union[Callable, str] could work.

It could be helpful to be slightly more specific with the annotation of kwargs also. The kwargs should be a dict, so **kwargs: dict.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be helpful to be slightly more specific with the annotation of kwargs also. The kwargs should be a dict, so **kwargs: dict.

https://www.python.org/dev/peps/pep-0484/#arbitrary-argument-lists-and-default-argument-values

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the confusion there, I was tired and thinking of the packed forms. I meant to put the dict annotation on the kwargs object under def main, because you would need an annotation there.

To use something more specific than Any, something like this could work, based on the annotations you added:

def run(
    app: str, **kwargs: typing.Union[typing.Optional[list], bool, float, int, str]
) -> None:
    config = Config(app, **kwargs)
    server = Server(config=config)
    ...

It's a bit clumsy to list off all those types, so a type alias could be helpful.

Copy link
Member Author

@Kludex Kludex May 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've applied the app one, thanks.

As for the **kwargs... I'm not sure the real benefit of doing that with so many types.

config = Config(app, **kwargs)
server = Server(config=config)

Expand All @@ -376,12 +375,10 @@ def run(app, **kwargs):

if config.should_reload:
sock = config.bind_socket()
supervisor = ChangeReload(config, target=server.run, sockets=[sock])
supervisor.run()
ChangeReload(config, target=server.run, sockets=[sock]).run()
elif config.workers > 1:
sock = config.bind_socket()
supervisor = Multiprocess(config, target=server.run, sockets=[sock])
supervisor.run()
Multiprocess(config, target=server.run, sockets=[sock]).run()
else:
server.run()

Expand Down
4 changes: 4 additions & 0 deletions uvicorn/protocols/http/auto.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import asyncio
from typing import Type

AutoHTTPProtocol: Type[asyncio.Protocol]
try:
import httptools # noqa
except ImportError: # pragma: no cover
Expand Down
4 changes: 4 additions & 0 deletions uvicorn/protocols/websockets/auto.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import asyncio
import typing

AutoWebSocketsProtocol: typing.Optional[typing.Type[asyncio.Protocol]]
try:
import websockets # noqa
except ImportError: # pragma: no cover
Expand Down
14 changes: 10 additions & 4 deletions uvicorn/supervisors/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import typing

from uvicorn.supervisors.basereload import BaseReload
from uvicorn.supervisors.multiprocess import Multiprocess

try:
from uvicorn.supervisors.watchgodreload import WatchGodReload as ChangeReload
except ImportError: # pragma: no cover
from uvicorn.supervisors.statreload import StatReload as ChangeReload
if typing.TYPE_CHECKING:
ChangeReload: typing.Type[BaseReload] # pragma: no cover
else:
try:
from uvicorn.supervisors.watchgodreload import WatchGodReload as ChangeReload
except ImportError: # pragma: no cover
from uvicorn.supervisors.statreload import StatReload as ChangeReload

__all__ = ["Multiprocess", "ChangeReload"]
11 changes: 6 additions & 5 deletions uvicorn/workers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import asyncio
import logging
import signal
from typing import Any

from gunicorn.workers.base import Worker

Expand All @@ -16,7 +17,7 @@ class UvicornWorker(Worker):

CONFIG_KWARGS = {"loop": "uvloop", "http": "httptools"}

def __init__(self, *args, **kwargs):
def __init__(self, *args: Any, **kwargs: Any) -> None:
Kludex marked this conversation as resolved.
Show resolved Hide resolved
super(UvicornWorker, self).__init__(*args, **kwargs)

logger = logging.getLogger("uvicorn.error")
Expand Down Expand Up @@ -58,24 +59,24 @@ def __init__(self, *args, **kwargs):

self.config = Config(**config_kwargs)

def init_process(self):
def init_process(self) -> None:
self.config.setup_event_loop()
super(UvicornWorker, self).init_process()

def init_signals(self):
def init_signals(self) -> None:
# Reset signals so Gunicorn doesn't swallow subprocess return codes
# other signals are set up by Server.install_signal_handlers()
# See: https://github.com/encode/uvicorn/issues/894
for s in self.SIGNALS:
signal.signal(s, signal.SIG_DFL)

def run(self):
def run(self) -> None:
self.config.app = self.wsgi
server = Server(config=self.config)
loop = asyncio.get_event_loop()
loop.run_until_complete(server.serve(sockets=self.sockets))

async def callback_notify(self):
async def callback_notify(self) -> None:
self.notify()


Expand Down