From 19739d17f407344172cfc0b3070c5230134769f8 Mon Sep 17 00:00:00 2001 From: Ethan Paul <24588726+enpaul@users.noreply.github.com> Date: Sat, 30 Oct 2021 11:51:41 -0400 Subject: [PATCH] Fix typing errors Fix missing dependencies in static tox envs --- kodak/configuration.py | 16 ++++++++-------- kodak/database/__init__.py | 3 ++- kodak/database/_shared.py | 7 +++++-- kodak/exceptions.py | 6 ++++++ kodak/resources/__init__.py | 3 ++- tests/test_configuration.py | 7 +++++++ tests/test_openapi.py | 4 ++++ tox.ini | 4 +++- 8 files changed, 37 insertions(+), 13 deletions(-) diff --git a/kodak/configuration.py b/kodak/configuration.py index 87031f2..b3fa410 100644 --- a/kodak/configuration.py +++ b/kodak/configuration.py @@ -136,7 +136,7 @@ class ManipCropConfig: def from_env(cls, key: str): """Build dataclass from environment""" return cls( - anchor=_get_enum_by_value( + anchor=_get_enum_by_value( # type: ignore f"KODAK_MANIP_{key}_CROP_ANCHOR", constants.CropAnchor, cls.anchor ), horizontal=_get_int(f"KODAK_MANIP_{key}_CROP_HORIZONTAL", cls.horizontal), @@ -173,16 +173,16 @@ class ManipScaleConfig: ) if strategy == constants.ScaleStrategy.ABSOLUTE: - parser = _get_int + parser = _get_int # type: ignore elif strategy == constants.ScaleStrategy.RELATIVE: - parser = _get_float + parser = _get_float # type: ignore else: raise RuntimeError("This path should not be possible") return cls( - strategy=strategy, - vertical=parser(f"KODAK_MANIP_{key}_SCALE_VERTICAL", cls.vertical), - horizontal=parser(f"KODAK_MANIP_{key}_SCALE_HORIZONTAL", cls.horizontal), + strategy=strategy, # type: ignore + vertical=parser(f"KODAK_MANIP_{key}_SCALE_VERTICAL", cls.vertical), # type: ignore + horizontal=parser(f"KODAK_MANIP_{key}_SCALE_HORIZONTAL", cls.horizontal), # type: ignore ) @@ -198,8 +198,8 @@ class ManipConfig: """ name: str - crop: ManipCropConfig = field(default_factory=ManipCropConfig.from_env) - scale: ManipScaleConfig = field(default_factory=ManipScaleConfig.from_env) + crop: ManipCropConfig = field(default_factory=ManipCropConfig) + scale: ManipScaleConfig = field(default_factory=ManipScaleConfig) formats: Set[constants.ImageFormat] = field( default_factory=lambda: constants.DEFAULT_SUPPORTED_FORMATS ) diff --git a/kodak/database/__init__.py b/kodak/database/__init__.py index e336aff..93f5143 100644 --- a/kodak/database/__init__.py +++ b/kodak/database/__init__.py @@ -1,5 +1,6 @@ import logging from typing import Tuple +from typing import Type import peewee @@ -13,7 +14,7 @@ from kodak.database.alias import AliasRecord from kodak.database.image import ImageRecord -MODELS: Tuple[KodakModel, ...] = (ImageRecord, AliasRecord, AccessRecord) +MODELS: Tuple[Type[KodakModel], ...] = (ImageRecord, AliasRecord, AccessRecord) def initialize(config: KodakConfig): diff --git a/kodak/database/_shared.py b/kodak/database/_shared.py index 2968978..bff09c9 100644 --- a/kodak/database/_shared.py +++ b/kodak/database/_shared.py @@ -1,12 +1,15 @@ import datetime import enum -import hashlib +import typing import uuid from typing import NamedTuple from typing import Type import peewee +if typing.TYPE_CHECKING: + import _hashlib + INTERFACE = peewee.DatabaseProxy() @@ -22,7 +25,7 @@ class Checksum(NamedTuple): digest: str @classmethod - def from_hash(cls, data: hashlib._hashlib.HASH): # pylint: disable=protected-access + def from_hash(cls, data: "_hashlib.HASH"): """Construct from a hashlib object""" return cls(algorithm=data.name, digest=data.hexdigest()) diff --git a/kodak/exceptions.py b/kodak/exceptions.py index 19fa416..691a7c7 100644 --- a/kodak/exceptions.py +++ b/kodak/exceptions.py @@ -29,6 +29,12 @@ class ImageResourceDeletedError(ClientError): status = 410 +class IAmATeapotError(ClientError): + """User tried to brew coffee, but application is a teapot""" + + status = 418 + + class ServerError(KodakException): """Error while processing server side data""" diff --git a/kodak/resources/__init__.py b/kodak/resources/__init__.py index 1f80309..e3d17f3 100644 --- a/kodak/resources/__init__.py +++ b/kodak/resources/__init__.py @@ -1,4 +1,5 @@ from typing import Tuple +from typing import Type from kodak.resources._shared import KodakResource from kodak.resources.alias import ImageAlias @@ -7,7 +8,7 @@ from kodak.resources.image import Image from kodak.resources.openapi import OpenAPI -RESOURCES: Tuple[KodakResource, ...] = ( +RESOURCES: Tuple[Type[KodakResource], ...] = ( Heartbeat, Image, ImageAlias, diff --git a/tests/test_configuration.py b/tests/test_configuration.py index 0ecfbde..5cb6887 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -12,6 +12,7 @@ from kodak import exceptions @contextlib.contextmanager def mockenv(patch, env: Dict[str, str]): + """Simple context manager for patching in a bunch of env vars""" for key, value in env.items(): patch.setenv(key, value) yield @@ -20,6 +21,8 @@ def mockenv(patch, env: Dict[str, str]): def test_conf_global(monkeypatch): + """Test the global config object and env parser""" + assert configuration.KodakConfig() == configuration.load() with mockenv( @@ -53,6 +56,8 @@ def test_conf_global(monkeypatch): def test_conf_database(monkeypatch): + """Test the database config object and env parser""" + with mockenv(monkeypatch, {"KODAK_DATABASE_BACKEND": "couchdb"}): with pytest.raises(exceptions.ConfigurationError): configuration.load() @@ -94,6 +99,8 @@ def test_conf_database(monkeypatch): def test_conf_manip(monkeypatch): + """Test the manipulation config object and env parser""" + with mockenv( monkeypatch, { diff --git a/tests/test_openapi.py b/tests/test_openapi.py index 2620e4d..cff1931 100644 --- a/tests/test_openapi.py +++ b/tests/test_openapi.py @@ -10,11 +10,15 @@ yaml = ruamel.yaml.YAML(typ="safe") # pylint: disable=invalid-name def test_openapi(): + """Validate the OpenAPI specification document structure""" openapi_spec_validator.validate_spec( yaml.load(importlib.resources.read_text("kodak", "openapi.yaml")) ) def test_openapi_version(): + """Check that the OpenAPI metadata matches the package metadata""" spec = yaml.load(importlib.resources.read_text("kodak", "openapi.yaml")) assert spec["info"]["version"] == __about__.__version__ + assert spec["info"]["license"]["name"] == __about__.__license__ + assert spec["info"]["title"].lower() == __about__.__title__.lower() diff --git a/tox.ini b/tox.ini index fa225b7..54b5d7b 100644 --- a/tox.ini +++ b/tox.ini @@ -44,8 +44,10 @@ description = Static formatting and quality enforcement for the tests basepython = python3.8 ignore_errors = true locked_deps = - pylint mypy + pylint + pytest + openapi-spec-validator commands = pylint --rcfile {toxinidir}/.pylintrc {toxinidir}/tests/ mypy --ignore-missing-imports --no-strict-optional {toxinidir}/tests/