diff --git a/newsfragments/3216.change.rst b/newsfragments/3216.change.rst new file mode 100644 index 000000000..5c892d5ff --- /dev/null +++ b/newsfragments/3216.change.rst @@ -0,0 +1 @@ +Remove supported inline type-checking comments by teaching Ruff about runtime-evaluated ``beartype`` annotations and postponing test annotations. diff --git a/pyproject.toml b/pyproject.toml index 4ca745ee7..fc683446e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -161,6 +161,7 @@ lint.flake8-tidy-imports.banned-api."operator.attrgetter".msg = "operator.attrge lint.flake8-tidy-imports.banned-api."typing.cast".msg = """\ typing.cast is banned: use explicit type narrowing or a typed variable instead.\ """ +lint.flake8-type-checking.runtime-evaluated-decorators = [ "beartype.beartype" ] lint.pydocstyle.convention = "google" lint.preview = true diff --git a/src/vws/_async_vws_request.py b/src/vws/_async_vws_request.py index bd8d91422..4ebd50c86 100644 --- a/src/vws/_async_vws_request.py +++ b/src/vws/_async_vws_request.py @@ -5,8 +5,8 @@ from beartype import BeartypeConf, beartype from vws_auth_tools import authorization_header, rfc_1123_date -from vws.response import Response # noqa: TC001 -from vws.transports import AsyncTransport # noqa: TC001 +from vws.response import Response +from vws.transports import AsyncTransport @beartype(conf=BeartypeConf(is_pep484_tower=True)) diff --git a/src/vws/_model_targets.py b/src/vws/_model_targets.py index 9ed51c437..fd37ac14f 100644 --- a/src/vws/_model_targets.py +++ b/src/vws/_model_targets.py @@ -2,7 +2,7 @@ import base64 import json -from collections.abc import Sequence # noqa: TC003 +from collections.abc import Sequence from http import HTTPStatus from typing import Any @@ -18,13 +18,13 @@ UnknownModelTargetDatasetError, ) from vws.exceptions.vws_exceptions import TooManyRequestsError -from vws.model_target_datasets import ( # noqa: TC001 +from vws.model_target_datasets import ( ModelTargetDatasetType, ModelTargetModel, ModelTargetView, ) from vws.reports import ModelTargetDatasetStatusReport -from vws.response import Response # noqa: TC001 +from vws.response import Response OAUTH2_TOKEN_PATH = "/oauth2/token" # noqa: S105 OAUTH2_TOKEN_BODY = b"grant_type=client_credentials" diff --git a/src/vws/_reco_counts.py b/src/vws/_reco_counts.py index 6ae8010ac..0654174cf 100644 --- a/src/vws/_reco_counts.py +++ b/src/vws/_reco_counts.py @@ -1,6 +1,6 @@ """Internal helpers for the database reco counts report endpoints.""" -import calendar # noqa: TC003 +import calendar import json from http import HTTPStatus @@ -12,7 +12,7 @@ RecoCountsReportNotReadyError, ) from vws.reports import RecoCountsReport -from vws.response import Response # noqa: TC001 +from vws.response import Response @beartype(conf=BeartypeConf(is_pep484_tower=True)) diff --git a/src/vws/_vws_request.py b/src/vws/_vws_request.py index 3153dce0c..8e08cf863 100644 --- a/src/vws/_vws_request.py +++ b/src/vws/_vws_request.py @@ -5,8 +5,8 @@ from beartype import BeartypeConf, beartype from vws_auth_tools import authorization_header, rfc_1123_date -from vws.response import Response # noqa: TC001 -from vws.transports import Transport # noqa: TC001 +from vws.response import Response +from vws.transports import Transport @beartype(conf=BeartypeConf(is_pep484_tower=True)) diff --git a/src/vws/exceptions/model_target_exceptions.py b/src/vws/exceptions/model_target_exceptions.py index cbbf80a0d..0031d35b3 100644 --- a/src/vws/exceptions/model_target_exceptions.py +++ b/src/vws/exceptions/model_target_exceptions.py @@ -10,7 +10,7 @@ from beartype import beartype from vws.reports import ModelTargetGenerationDetail -from vws.response import Response # noqa: TC001 +from vws.response import Response @beartype diff --git a/src/vws/model_target_datasets.py b/src/vws/model_target_datasets.py index 95a9eaa18..0cbfe08a1 100644 --- a/src/vws/model_target_datasets.py +++ b/src/vws/model_target_datasets.py @@ -4,7 +4,7 @@ https://developer.vuforia.com/library/vuforia-engine/web-api/model-target-web-api/. """ -from collections.abc import Sequence # noqa: TC003 +from collections.abc import Sequence from dataclasses import dataclass from enum import StrEnum, unique diff --git a/src/vws/reports.py b/src/vws/reports.py index b18ffb9b4..ee6a0288f 100644 --- a/src/vws/reports.py +++ b/src/vws/reports.py @@ -3,7 +3,7 @@ import csv import datetime import io -from collections.abc import Sequence # noqa: TC003 +from collections.abc import Sequence from dataclasses import dataclass from enum import Enum, unique from typing import Any, Self diff --git a/tests/conftest.py b/tests/conftest.py index 515034e35..de156b759 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,10 +1,9 @@ """Configuration, plugins and fixtures for `pytest`.""" +from __future__ import annotations + import datetime -import io # noqa: TC003 -from collections.abc import AsyncGenerator, Generator # noqa: TC003 -from pathlib import Path # noqa: TC003 -from typing import BinaryIO, Literal +from typing import TYPE_CHECKING, BinaryIO, Literal import pytest import pytest_asyncio @@ -29,6 +28,11 @@ ModelTargetView, ) +if TYPE_CHECKING: + import io + from collections.abc import AsyncGenerator, Generator + from pathlib import Path + # The mock accepts one hard-coded pair of Model Target Web API OAuth2 # credentials, which it does not expose. _MODEL_TARGET_CLIENT_ID = "client-id" diff --git a/tests/test_async_cloud_reco_exceptions.py b/tests/test_async_cloud_reco_exceptions.py index 67c2637dc..4cbc83498 100644 --- a/tests/test_async_cloud_reco_exceptions.py +++ b/tests/test_async_cloud_reco_exceptions.py @@ -2,10 +2,12 @@ AsyncCloudRecoService. """ -import io # noqa: TC003 +from __future__ import annotations + import json import uuid from http import HTTPStatus +from typing import TYPE_CHECKING import pytest from mock_vws import CloudQueryFailureResponse, MockVWS @@ -23,6 +25,9 @@ RequestEntityTooLargeError, ) +if TYPE_CHECKING: + import io + @pytest.mark.asyncio async def test_too_many_max_results( diff --git a/tests/test_async_query.py b/tests/test_async_query.py index 2026d491a..ac81a594c 100644 --- a/tests/test_async_query.py +++ b/tests/test_async_query.py @@ -1,8 +1,9 @@ """Tests for the ``AsyncCloudRecoService`` querying functionality.""" -import io # noqa: TC003 +from __future__ import annotations + import uuid -from typing import BinaryIO +from typing import TYPE_CHECKING, BinaryIO import pytest from mock_vws import MockVWS @@ -11,6 +12,9 @@ from vws import AsyncCloudRecoService, AsyncVWS from vws.include_target_data import CloudRecoIncludeTargetData +if TYPE_CHECKING: + import io + class TestQuery: """Tests for making async image queries.""" diff --git a/tests/test_async_vws.py b/tests/test_async_vws.py index 166224a25..3453a1a34 100644 --- a/tests/test_async_vws.py +++ b/tests/test_async_vws.py @@ -1,13 +1,13 @@ """Tests for async helper functions for managing a Vuforia database.""" +from __future__ import annotations + import base64 import calendar -import datetime # noqa: TC003 -import io # noqa: TC003 import time import uuid from http import HTTPStatus -from typing import BinaryIO +from typing import TYPE_CHECKING, BinaryIO import pytest from mock_vws import MockVWS @@ -33,6 +33,10 @@ from vws.response import Response from vws.vumark_accept import VuMarkAccept +if TYPE_CHECKING: + import datetime + import io + class TestAddTarget: """Tests for adding a target.""" diff --git a/tests/test_async_vws_exceptions.py b/tests/test_async_vws_exceptions.py index 94c654ad8..cae7ad6c1 100644 --- a/tests/test_async_vws_exceptions.py +++ b/tests/test_async_vws_exceptions.py @@ -1,5 +1,7 @@ """Tests for VWS exceptions raised from async clients.""" +from __future__ import annotations + import base64 import io import uuid @@ -11,7 +13,6 @@ from mock_vws.states import States from vws import AsyncVuMarkService, AsyncVWS -from vws.exceptions.base_exceptions import VWSError # noqa: TC001 from vws.exceptions.custom_exceptions import ( ServerError, ) @@ -156,7 +157,9 @@ async def test_target_quota_reached( async def test_project_state_error( *, state: States, - expected_exception: type[VWSError], + expected_exception: type[ + ProjectSuspendedError | ProjectHasNoAPIAccessError + ], ) -> None: """Configured project states raise their matching exceptions.""" database = CloudDatabase(state=state) @@ -414,7 +417,9 @@ async def test_invalid_instance_id( async def test_documented_vumark_error_codes( *, failure: VuMarkGenerationFailure, - exception_type: type[VWSError], + exception_type: type[ + QuotaExceededError | LicenseCheckFailedError | AuthorizationFailedError + ], status_code: HTTPStatus, ) -> None: """Documented VuMark failures raise matching exceptions.""" diff --git a/tests/test_cloud_reco_exceptions.py b/tests/test_cloud_reco_exceptions.py index 92727fa14..cb8d4b600 100644 --- a/tests/test_cloud_reco_exceptions.py +++ b/tests/test_cloud_reco_exceptions.py @@ -1,9 +1,11 @@ """Tests for exceptions raised when using the CloudRecoService.""" -import io # noqa: TC003 +from __future__ import annotations + import json import uuid from http import HTTPStatus +from typing import TYPE_CHECKING import pytest from mock_vws import CloudQueryFailureResponse, MockVWS @@ -23,6 +25,9 @@ RequestEntityTooLargeError, ) +if TYPE_CHECKING: + import io + def test_too_many_max_results( *, diff --git a/tests/test_query.py b/tests/test_query.py index cb30318cc..003a924e5 100644 --- a/tests/test_query.py +++ b/tests/test_query.py @@ -1,12 +1,13 @@ """Tests for the ``CloudRecoService`` querying functionality.""" +from __future__ import annotations + import datetime -import io # noqa: TC003 import json import secrets import uuid from http import HTTPStatus -from typing import BinaryIO +from typing import TYPE_CHECKING, BinaryIO import pytest import requests @@ -18,6 +19,9 @@ from vws.include_target_data import CloudRecoIncludeTargetData from vws.response import Response +if TYPE_CHECKING: + import io + class _JSONResponseTransport: """A transport which returns one JSON response body.""" diff --git a/tests/test_transports.py b/tests/test_transports.py index a3494b67c..f30d6b827 100644 --- a/tests/test_transports.py +++ b/tests/test_transports.py @@ -1,8 +1,10 @@ """Tests for HTTP transport implementations.""" -import io # noqa: TC003 +from __future__ import annotations + import uuid from http import HTTPStatus +from typing import TYPE_CHECKING import httpx import httpx2 @@ -36,6 +38,9 @@ ) from vws.vumark_accept import VuMarkAccept +if TYPE_CHECKING: + import io + class TestHTTPXTransport: """Tests for ``HTTPXTransport``.""" diff --git a/tests/test_vws.py b/tests/test_vws.py index 9313455a0..90657420e 100644 --- a/tests/test_vws.py +++ b/tests/test_vws.py @@ -1,15 +1,16 @@ """Tests for helper functions for managing a Vuforia database.""" +from __future__ import annotations + import base64 import calendar import datetime -import io # noqa: TC003 import json import secrets import time import uuid from http import HTTPStatus -from typing import BinaryIO +from typing import TYPE_CHECKING, BinaryIO import pytest import requests @@ -40,6 +41,9 @@ from vws.response import Response from vws.vumark_accept import VuMarkAccept +if TYPE_CHECKING: + import io + class _JSONResponseTransport: """A transport which returns one JSON response body."""