From e08ba9ed4bda27f31aee97984b2650daa72ff142 Mon Sep 17 00:00:00 2001 From: Andreas Motl Date: Wed, 10 Apr 2024 16:55:23 +0200 Subject: [PATCH] Chore: Update to mypy 1.10 --- .github/dependabot.yml | 3 +-- .pre-commit-config.yaml | 2 +- croud/api.py | 6 +++--- croud/printer.py | 13 ++++++++----- croud/regions/commands.py | 2 +- croud/server.py | 4 ++-- pyproject.toml | 6 ++++++ setup.cfg | 3 --- setup.py | 4 +++- tests/commands/test_clusters.py | 8 ++++---- tests/test_api.py | 5 ++++- tests/test_printer.py | 2 ++ tests/util/fake_cloud.py | 4 +++- 13 files changed, 38 insertions(+), 24 deletions(-) create mode 100644 pyproject.toml diff --git a/.github/dependabot.yml b/.github/dependabot.yml index c0c002f5..206af82d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -18,5 +18,4 @@ updates: - "> 5.6.4" - dependency-name: mypy versions: - - "> 0.812" - + - "> 1.9.0" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1a9fc034..d25615de 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,6 +22,6 @@ repos: types: - python - repo: https://github.com/pre-commit/mirrors-mypy - rev: "v0.812" + rev: "v1.9.0" hooks: - id: mypy diff --git a/croud/api.py b/croud/api.py index 2a889694..4dc303a9 100644 --- a/croud/api.py +++ b/croud/api.py @@ -21,7 +21,7 @@ import os from argparse import Namespace from platform import python_version -from typing import Any, Callable, Dict, Optional, Tuple +from typing import Any, Callable, Dict, Optional, Tuple, cast import requests from yarl import URL @@ -108,7 +108,7 @@ def __init__( "Only the token will be used." ) - self.session.cookies["session"] = self._token + self.session.cookies["session"] = cast(str, self._token) if _verify_ssl is False: self.session.verify = False if region: @@ -156,7 +156,7 @@ def request( response = self.session.request(method.value, url, **kwargs) except requests.RequestException as e: message = ( - f"Failed to perform request on '{e.request.url}'. " + f"Failed to perform request on '{e.request and e.request.url}'. " f"Original error was: '{e}'" ) return None, {"message": message, "success": False} diff --git a/croud/printer.py b/croud/printer.py index 52bd3901..2731e780 100644 --- a/croud/printer.py +++ b/croud/printer.py @@ -21,7 +21,7 @@ import functools import json import sys -from typing import Any, Callable, Dict, List, Optional, Type, Union +from typing import Any, Callable, Dict, List, Optional, Type, Union, cast import yaml from colorama import Fore, Style @@ -30,9 +30,12 @@ from croud.tools.spinner import HALO from croud.typing import JsonDict +RowsType = Union[List[JsonDict], JsonDict] +ErrorsType = Union[Dict[str, Union[str, RowsType]], None] + def print_format( - rows: Union[List[JsonDict], JsonDict], + rows: RowsType, format: str, keys: Optional[List[str]] = None, transforms: Optional[Dict[str, Callable[[Any], Any]]] = None, @@ -48,7 +51,7 @@ def print_format( def print_response( data, - errors, + errors: ErrorsType, output_fmt, success_message: str = None, keys: List[str] = None, @@ -56,9 +59,9 @@ def print_response( ): if errors: if "message" in errors: - print_error(errors["message"]) + print_error(cast(str, errors["message"])) if "errors" in errors: - print_format(errors["errors"], "json") + print_format(cast(RowsType, errors["errors"]), "json") else: print_format(errors, "json") return diff --git a/croud/regions/commands.py b/croud/regions/commands.py index bf62d2e2..347cd5f5 100644 --- a/croud/regions/commands.py +++ b/croud/regions/commands.py @@ -138,7 +138,7 @@ def regions_delete(args: Namespace) -> None: print_response( data=data, errors={ - "message": region_errors.get("message"), + "message": region_errors.get("message", "unknown error"), "errors": {"related_resources": region_errors.get("related_resources")}, }, output_fmt=get_output_format(args), diff --git a/croud/server.py b/croud/server.py index 4df2b538..c2d887b7 100644 --- a/croud/server.py +++ b/croud/server.py @@ -57,7 +57,7 @@ def do_GET(self): msg = SetTokenHandler.DUPLICATE_TOKEN_MSG else: token = query["token"][0] - self.server.on_token(token) + self.server.on_token(token) # type: ignore[attr-defined] code = 200 msg = SetTokenHandler.SUCCESS_MSG self.send_response(code) @@ -69,7 +69,7 @@ def do_GET(self): # We cannot use `self.server.shutdown()` here because we're in the same # thread as the one who'd be waiting for the shutdown, thus causing a # deadlock. - self.server._BaseServer__shutdown_request = True + self.server._BaseServer__shutdown_request = True # type: ignore[attr-defined] def log_request(self, *args, **kwargs): # Just don't log anything ... diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..b71069d6 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,6 @@ +[tool.mypy] +check_untyped_defs = true +ignore_missing_imports = true +implicit_optional = true +install_types = true +non_interactive = true diff --git a/setup.cfg b/setup.cfg index 2b46c11e..8338f894 100644 --- a/setup.cfg +++ b/setup.cfg @@ -13,9 +13,6 @@ multi_line_output = 3 addopts = --doctest-modules --doctest-glob='**/*.rst' --ignore=docs doctest_optionflags = NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL ELLIPSIS -[mypy] -ignore_missing_imports = true - [flake8] max-line-length = 88 ignore = E203 W503 diff --git a/setup.py b/setup.py index 4bf2bb68..1d86e796 100644 --- a/setup.py +++ b/setup.py @@ -19,6 +19,8 @@ # with Crate these terms will supersede the license and you may use the # software solely pursuant to the terms of the relevant commercial agreement. +# type: ignore + from pkg_resources.extern.packaging.version import Version from setuptools import find_packages, setup @@ -64,7 +66,7 @@ "black==24.3.0", "flake8==7.0.0", "isort==5.12.0", - "mypy==0.812", + "mypy<1.11", ], }, python_requires=">=3.8", diff --git a/tests/commands/test_clusters.py b/tests/commands/test_clusters.py index ac13b316..0c3fe5d3 100644 --- a/tests/commands/test_clusters.py +++ b/tests/commands/test_clusters.py @@ -1968,7 +1968,7 @@ def test_export_job_create(mock_client_request, mock_copy, save_file): with mock.patch("requests.get", return_value=mock_response): with mock.patch("builtins.open", mock.mock_open(read_data="id,name,path")): - cmd = ( + cmd = [ "croud", "clusters", "export-jobs", @@ -1981,12 +1981,12 @@ def test_export_job_create(mock_client_request, mock_copy, save_file): "my-table", "--compression", "gzip", - ) + ] if save_file: - cmd = cmd + ( + cmd += [ "--save-as", "./my_table.csv", - ) + ] call_command(*cmd) body = { diff --git a/tests/test_api.py b/tests/test_api.py index 388af04e..e60f1b0d 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -81,6 +81,7 @@ def test_send_user_agent_header(config): client = Client(config.endpoint, region="bregenz.a1", _verify_ssl=False) resp_data, errors = client.get("/client-headers") expected_ua = f"Croud/{croud.__version__} Python/{python_version()}" + assert isinstance(resp_data, dict) assert resp_data["User-Agent"] == expected_ua @@ -90,6 +91,7 @@ def test_send_user_agent_header(config): def test_send_region_header(argument, is_header_present, config): client = Client(config.endpoint, region=argument, _verify_ssl=False) resp_data, errors = client.get("/client-headers") + assert isinstance(resp_data, dict) if is_header_present: assert resp_data["X-Region"] == argument # type: ignore else: @@ -116,8 +118,8 @@ def test_error_message_on_connection_error(config): ) client = Client(config.endpoint, _verify_ssl=False) resp_data, errors = client.get("/me") - print(resp_data, errors) assert resp_data is None + assert isinstance(errors, dict) assert expected_message_re.match(errors["message"]) is not None assert errors["success"] is False @@ -127,4 +129,5 @@ def test_auth_with_key_and_secret(config): config.endpoint, key="some-key", secret="some-secret", _verify_ssl=False ) resp_data, errors = client.get("/client-headers") + assert isinstance(resp_data, dict) assert resp_data["Authorization"] == "Basic c29tZS1rZXk6c29tZS1zZWNyZXQ=" diff --git a/tests/test_printer.py b/tests/test_printer.py index 9d905b19..22dd4c64 100644 --- a/tests/test_printer.py +++ b/tests/test_printer.py @@ -17,6 +17,8 @@ # with Crate these terms will supersede the license and you may use the # software solely pursuant to the terms of the relevant commercial agreement. +# type: ignore + import pytest from croud.printer import ( diff --git a/tests/util/fake_cloud.py b/tests/util/fake_cloud.py index 61fc1155..3081f218 100644 --- a/tests/util/fake_cloud.py +++ b/tests/util/fake_cloud.py @@ -51,7 +51,7 @@ def __init__(self, *args, **kwargs): here = pathlib.Path(__file__) self.ssl_cert = here.parent / "server.crt" ssl_key = here.parent / "server.key" - self.socket = ssl.wrap_socket( + self.socket = ssl.wrap_socket( # type: ignore[attr-defined] self.socket, keyfile=str(ssl_key), certfile=str(self.ssl_cert), @@ -61,6 +61,8 @@ def __init__(self, *args, **kwargs): class FakeCrateDBCloudRequestHandler(BaseHTTPRequestHandler): def __init__(self, *args, **kwargs): + self.body = None + self.cookies = {} self.routes: Dict[str, Callable[[], Response]] = { "/data/data-key": self.data_data_key, "/data/no-key": self.data_no_key,