From 88e5cb5b440940048f80c50e8bccb6b11b677a07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul?= Date: Sun, 14 Nov 2021 14:42:02 +0100 Subject: [PATCH] Finish strict typing --- .github/workflows/ci.yml | 7 ++++--- .pre-commit-config.yaml | 2 +- pyproject.toml | 23 +++++++++++++++++++++++ requirements-mypy.txt | 4 ++++ src/runboat/api.py | 10 +++++----- src/runboat/controller.py | 2 +- src/runboat/k8s.py | 10 +++++----- src/runboat/models.py | 2 +- src/runboat/uvicorn.py | 2 +- src/runboat/webui.py | 4 ++-- 10 files changed, 47 insertions(+), 19 deletions(-) create mode 100644 requirements-mypy.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d113aab..2fe2aa2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,10 +16,11 @@ jobs: - name: Install project run: | pip install -U "pip>=21.3.1" - pip install -e .[test] -c requirements.txt -c requirements-test.txt + pip install -e .[test,mypy] -c requirements.txt -c requirements-test.txt -c requirements-mypy.txt - name: Run tests - run: | - pytest -v --cov --cov-report=xml ./tests + run: pytest -v --cov --cov-report=xml ./tests + - name: Run mypy + run: mypy ./src/runboat ./tests - uses: codecov/codecov-action@v1 build-image: runs-on: ubuntu-latest diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fb8818b..fc5094c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -39,4 +39,4 @@ repos: rev: v2.29.0 hooks: - id: pyupgrade - args: ["--py38-plus"] + args: ["--py39-plus"] diff --git a/pyproject.toml b/pyproject.toml index c1509c7..ca069ad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,6 +27,9 @@ test = [ "pytest-cov", "pytest-dotenv", ] +mypy = [ + "mypy", +] [project.urls] Home = "https://github.com/sbidoul/runboat" @@ -39,3 +42,23 @@ env_override_existing_values = 1 env_files = [".env.test"] # flake8 config is in .flake8 + +[tool.mypy] +strict = true +show_error_codes = true + +[[tool.mypy.overrides]] +module = "uvicorn.*" +ignore_missing_imports = true + +[[tool.mypy.overrides]] +module = "urllib3.*" +ignore_missing_imports = true + +[[tool.mypy.overrides]] +module = "kubernetes.*" +ignore_missing_imports = true + +[[tool.mypy.overrides]] +module = "ansi2html" +ignore_missing_imports = true diff --git a/requirements-mypy.txt b/requirements-mypy.txt new file mode 100644 index 0000000..444c145 --- /dev/null +++ b/requirements-mypy.txt @@ -0,0 +1,4 @@ +# frozen requirements generated by pip-deepfreeze +mypy==0.910 +mypy-extensions==0.4.3 +toml==0.10.2 diff --git a/src/runboat/api.py b/src/runboat/api.py index ca1fef2..ca81e4c 100644 --- a/src/runboat/api.py +++ b/src/runboat/api.py @@ -1,7 +1,7 @@ import datetime from typing import Optional -from ansi2html import Ansi2HTMLConverter # type: ignore +from ansi2html import Ansi2HTMLConverter from fastapi import APIRouter, Depends, HTTPException, status from fastapi.responses import HTMLResponse from pydantic import BaseModel @@ -124,24 +124,24 @@ async def build(name: str) -> models.Build: "/builds/{name}/init-log", response_class=HTMLResponse, ) -async def init_log(name: str): +async def init_log(name: str) -> str: build = await _build_by_name(name) log = await build.init_log() if not log: raise HTTPException(status_code=HTTP_404_NOT_FOUND, detail="No log found.") - return Ansi2HTMLConverter().convert(log) + return Ansi2HTMLConverter().convert(log) # type: ignore [no-any-return] @router.get( "/builds/{name}/log", response_class=HTMLResponse, ) -async def log(name: str): +async def log(name: str) -> str: build = await _build_by_name(name) log = await build.log() if not log: raise HTTPException(status_code=HTTP_404_NOT_FOUND, detail="No log found.") - return Ansi2HTMLConverter().convert(log) + return Ansi2HTMLConverter().convert(log) # type: ignore [no-any-return] @router.post("/builds/{name}/start") diff --git a/src/runboat/controller.py b/src/runboat/controller.py index 7180bd0..cc3b8a5 100644 --- a/src/runboat/controller.py +++ b/src/runboat/controller.py @@ -30,7 +30,7 @@ class Controller: """ db: BuildsDb - _tasks: list[asyncio.Task] + _tasks: list[asyncio.Task[None]] _wakeup_initializer: asyncio.Event _wakeup_stopper: asyncio.Event _wakeup_undeployer: asyncio.Event diff --git a/src/runboat/k8s.py b/src/runboat/k8s.py index b0b920b..35f2f13 100644 --- a/src/runboat/k8s.py +++ b/src/runboat/k8s.py @@ -11,12 +11,12 @@ from importlib import resources from pathlib import Path from typing import Any, Callable, Generator, Optional, TypedDict, cast -import urllib3 # type: ignore +import urllib3 from jinja2 import Template -from kubernetes import client, config, watch # type: ignore -from kubernetes.client.exceptions import ApiException # type: ignore -from kubernetes.client.models.v1_deployment import V1Deployment # type: ignore -from kubernetes.client.models.v1_job import V1Job # type: ignore +from kubernetes import client, config, watch +from kubernetes.client.exceptions import ApiException +from kubernetes.client.models.v1_deployment import V1Deployment +from kubernetes.client.models.v1_job import V1Job from pydantic import BaseModel from .settings import settings diff --git a/src/runboat/models.py b/src/runboat/models.py index 609e506..7a2c483 100644 --- a/src/runboat/models.py +++ b/src/runboat/models.py @@ -4,7 +4,7 @@ import uuid from enum import Enum from typing import Optional -from kubernetes.client.models.v1_deployment import V1Deployment # type: ignore +from kubernetes.client.models.v1_deployment import V1Deployment from pydantic import BaseModel from . import github, k8s diff --git a/src/runboat/uvicorn.py b/src/runboat/uvicorn.py index c60e707..aa60081 100644 --- a/src/runboat/uvicorn.py +++ b/src/runboat/uvicorn.py @@ -1,4 +1,4 @@ -from uvicorn.workers import UvicornWorker # type: ignore +from uvicorn.workers import UvicornWorker from .settings import settings diff --git a/src/runboat/webui.py b/src/runboat/webui.py index 8c4cdd6..9f4a99f 100644 --- a/src/runboat/webui.py +++ b/src/runboat/webui.py @@ -1,7 +1,7 @@ from pathlib import Path from typing import Optional -from fastapi import APIRouter, HTTPException, Request, status +from fastapi import APIRouter, HTTPException, Request, Response, status from fastapi.responses import HTMLResponse, RedirectResponse from fastapi.templating import Jinja2Templates @@ -13,7 +13,7 @@ templates = Jinja2Templates(directory=str(Path(__file__).parent / "webui")) @router.get("/builds/{name}", response_class=HTMLResponse) -async def build(request: Request, name: str, live: Optional[str] = None): +async def build(request: Request, name: str, live: Optional[str] = None) -> Response: build = controller.db.get(name) if not build: raise HTTPException(status.HTTP_404_NOT_FOUND)