From 5b537c4ac27f69bfeedc73aa1fb5eb437d78fe94 Mon Sep 17 00:00:00 2001 From: Peter Pfeufer Date: Tue, 17 Mar 2026 01:02:58 +0100 Subject: [PATCH] [CHANGE] (Internal) Better type hinting --- CHANGELOG.md | 4 ++++ pyproject.toml | 6 +++++ sovtimer/providers.py | 21 +++++++++++----- sovtimer/tests/test_providers.py | 41 ++++++++++++++++++++++++++++++++ tox.ini | 10 ++++---- 5 files changed, 71 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54e41805..a6b84efc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,10 @@ Section Order: +### Changed + +- (Internal) Better type hinting + ## [4.0.1] - 2026-02-27 ### Removed diff --git a/pyproject.toml b/pyproject.toml index ba0ddc06..14d44352 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,6 +43,12 @@ dependencies = [ "django-esi>=8.3.1", "django-eveonline-sde>=0.0.1b1", ] +optional-dependencies.tests-allianceauth-development = [ + "allianceauth @ git+https://gitlab.com/allianceauth/allianceauth#egg=master", + "coverage", + "django-webtest", + "requests-mock", +] optional-dependencies.tests-allianceauth-latest = [ "coverage", "django-webtest", diff --git a/sovtimer/providers.py b/sovtimer/providers.py index c9950c95..85a2bbe2 100644 --- a/sovtimer/providers.py +++ b/sovtimer/providers.py @@ -4,6 +4,7 @@ # Standard Library import logging +import typing from typing import Any # Third Party @@ -24,6 +25,14 @@ __version__, ) +if typing.TYPE_CHECKING: + # Alliance Auth + from esi.stubs import ( + AllianceDetail, + SovereigntyCampaignsGet, + SovereigntyStructuresGet, + ) + # ESI client esi = ESIClientProvider( # Use the latest compatibility date, see https://esi.evetech.net/meta/compatibility-dates @@ -108,7 +117,7 @@ def result( # pylint: disable=too-many-arguments, too-many-positional-arguments @classmethod def get_alliances_alliance_id( cls, alliance_id: int, force_refresh: bool = False - ) -> dict | None: + ) -> "AllianceDetail | None": """ Get alliance information from ESI. @@ -117,7 +126,7 @@ def get_alliances_alliance_id( :param force_refresh: Whether to force a refresh of the data from ESI, bypassing any caches. :type force_refresh: bool :return: Alliance information or None if an error occurred. - :rtype: dict | None + :rtype: AllianceDetail | None """ logger.debug( @@ -134,12 +143,12 @@ def get_alliances_alliance_id( @classmethod def get_sovereignty_campaigns( cls, force_refresh: bool = False - ) -> list[dict] | None: + ) -> "list[SovereigntyCampaignsGet] | None": """ Get sovereignty campaigns from ESI. :return: List of sovereignty campaigns or None if an error occurred. - :rtype: list[dict] | None + :rtype: list[SovereigntyCampaignsGet] | None """ logger.debug("Fetching sovereignty campaigns from ESI...") @@ -152,12 +161,12 @@ def get_sovereignty_campaigns( @classmethod def get_sovereignty_structures( cls, force_refresh: bool = False - ) -> list[dict] | None: + ) -> "list[SovereigntyStructuresGet] | None": """ Get sovereignty structures from ESI. :return: List of sovereignty structures or None if an error occurred. - :rtype: list[dict] | None + :rtype: list[SovereigntyStructuresGet] | None """ logger.debug("Fetching sovereignty structures from ESI...") diff --git a/sovtimer/tests/test_providers.py b/sovtimer/tests/test_providers.py index b6eb931f..494678ec 100644 --- a/sovtimer/tests/test_providers.py +++ b/sovtimer/tests/test_providers.py @@ -3,7 +3,11 @@ """ # Standard Library +import importlib import logging +import sys +import types +import typing from http import HTTPStatus from unittest.mock import MagicMock, patch @@ -18,6 +22,43 @@ from sovtimer.tests import BaseTestCase +class TestTypingTypeCheckingIfCondition(BaseTestCase): + def test_when_typing_TYPE_CHECKING_true_then_stub_types_are_imported_into_module_namespace( + self, + ): + """ + Test that when `typing.TYPE_CHECKING` is set to `True`, the stub types from `esi.stubs` are imported into the module namespace. + + :return: + :rtype: + """ + fake_stubs = types.ModuleType("esi.stubs") + fake_stubs.AllianceDetail = type("AllianceDetail", (), {}) + fake_stubs.SovereigntyCampaignsGet = type("SovereigntyCampaignsGet", (), {}) + fake_stubs.SovereigntyStructuresGet = type("SovereigntyStructuresGet", (), {}) + + original_sys_modules = sys.modules.copy() + + try: + sys.modules["esi.stubs"] = fake_stubs + + with patch.object(typing, "TYPE_CHECKING", True): + providers = importlib.import_module("sovtimer.providers") + importlib.reload(providers) + + self.assertTrue(hasattr(providers, "AllianceDetail")) + self.assertTrue(hasattr(providers, "SovereigntyCampaignsGet")) + self.assertTrue(hasattr(providers, "SovereigntyStructuresGet")) + finally: + sys.modules.clear() + sys.modules.update(original_sys_modules) + + try: + importlib.reload(importlib.import_module("sovtimer.providers")) + except Exception: + pass + + class TestESIHandlerResult(BaseTestCase): """ Test the ESIHandler.result method. diff --git a/tox.ini b/tox.ini index c3912c31..fbfba0a4 100644 --- a/tox.ini +++ b/tox.ini @@ -2,7 +2,7 @@ requires = tox>=4.2 env_list = - allianceauth-{latest, testing} + allianceauth-{latest, development} py{312, 311, 310} no_package = true usedevelop = True @@ -25,10 +25,10 @@ commands = set_env = DJANGO_SETTINGS_MODULE = testauth.settings.local install_command = - python -m pip install -e ".[tests-allianceauth-latest]" -U {opts} {packages} + python -m pip install --ignore-requires-python -e ".[tests-allianceauth-latest]" -U {opts} {packages} -[testenv:allianceauth-testing] +[testenv:allianceauth-development] set_env = - DJANGO_SETTINGS_MODULE = testauth.settings.testing.local + DJANGO_SETTINGS_MODULE = testauth.settings.development.local install_command = - python -m pip install -e ".[tests-allianceauth-testing]" -U {opts} {packages} + python -m pip install --ignore-requires-python -e ".[tests-allianceauth-development]" -U {opts} {packages}