Skip to content

Commit 32c7e44

Browse files
committed
style: fix typechecking issues
1 parent d52a8be commit 32c7e44

35 files changed

Lines changed: 233 additions & 113 deletions

.pre-commit-config.yaml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,14 @@ repos:
99
rev: 0.7.15
1010
hooks:
1111
- id: uv-lock
12-
- repo: https://github.com/DetachHead/basedpyright-pre-commit-mirror
13-
rev: v1.13.0
12+
- repo: local
1413
hooks:
1514
- id: basedpyright
15+
name: basedpyright
16+
entry: basedpyright
17+
language: system
18+
types_or: [python, pyi]
19+
pass_filenames: false
1620
- repo: https://github.com/pre-commit/pre-commit-hooks
1721
rev: v5.0.0
1822
hooks:

examples/classify_single_example.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,14 @@ async def classify_single_image_example(
3030
"""Demonstrate single image classification.
3131
3232
Args:
33+
----
3334
logger: Logger instance for output
3435
options: Configuration options for the Athena client
3536
credential_helper: OAuth credential helper for authentication
3637
image_path: Path to image file to classify (optional)
3738
3839
Returns:
40+
-------
3941
True if classification was successful, False otherwise
4042
4143
"""
@@ -117,12 +119,14 @@ async def classify_multiple_single_images_example(
117119
when you want individual control over each classification request.
118120
119121
Args:
122+
----
120123
logger: Logger instance for output
121124
options: Configuration options for the Athena client
122125
credential_helper: OAuth credential helper for authentication
123126
num_images: Number of test images to classify
124127
125128
Returns:
129+
-------
126130
Number of successfully classified images
127131
128132
"""
@@ -185,7 +189,7 @@ async def classify_multiple_single_images_example(
185189
async def main() -> int:
186190
"""Run the classify_single examples."""
187191
logger = logging.getLogger(__name__)
188-
load_dotenv()
192+
_ = load_dotenv()
189193

190194
# OAuth credentials from environment
191195
client_id = os.getenv("OAUTH_CLIENT_ID")

examples/example.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ async def run_oauth_example(
135135
async def main() -> int:
136136
"""Run the OAuth classification example."""
137137
logger = logging.getLogger(__name__)
138-
load_dotenv()
138+
_ = load_dotenv()
139139

140140
# Configuration
141141
max_test_images = 10_000

pyproject.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ exclude = ["src/resolver_athena_client/generated/*", "docs"]
6262

6363
[tool.ruff.lint]
6464
select = ["ALL"]
65-
ignore = ["COM812", "D213", "D211", "D203", "S324"]
65+
ignore = ["COM812", "D213", "D211", "D203", "S324", "ASYNC109"]
6666

6767
[tool.ruff.lint.per-file-ignores]
6868
# Ignore doc lint rules in tests.
@@ -72,6 +72,9 @@ ignore = ["COM812", "D213", "D211", "D203", "S324"]
7272
exclude = ["src/resolver_athena_client/generated/*", ".venv"]
7373
venvPath = "."
7474
venv = ".venv"
75+
stubPath = "stubs"
76+
reportImplicitStringConcatenation = false
77+
reportAny = false
7578

7679
[tool.pytest.ini_options]
7780
markers = [

src/resolver_athena_client/client/athena_client.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,25 @@ def __init__(
5858
"""Initialize the Athena Client.
5959
6060
Args:
61+
----
6162
channel: The gRPC channel to use for communication.
6263
options: Configuration options for the Athena client.
6364
6465
"""
65-
self.logger = logging.getLogger(__name__)
66-
self.options = options
67-
self.channel = channel
68-
self.classifier = ClassifierServiceClient(self.channel)
66+
self.logger: logging.Logger = logging.getLogger(__name__)
67+
self.options: AthenaOptions = options
68+
self.channel: grpc.aio.Channel = channel
69+
self.classifier: ClassifierServiceClient = ClassifierServiceClient(
70+
self.channel
71+
)
6972

7073
async def classify_images(
7174
self, images: AsyncIterator[ImageData]
7275
) -> AsyncIterator[ClassifyResponse]:
7376
"""Classify images using the Athena service.
7477
7578
Args:
79+
----
7680
images: An async iterator of ImageData objects containing image
7781
bytes and hash lists tracking transformations. Users must create
7882
ImageData objects from raw image bytes before passing to this
@@ -82,9 +86,11 @@ async def classify_images(
8286
operations.
8387
8488
Yields:
89+
------
8590
Classification responses from the service.
8691
8792
Example:
93+
-------
8894
# Create ImageData from raw bytes
8995
image_data = ImageData(image_bytes)
9096
print(f"Initial hashes: {len(image_data.sha256_hashes)}") # 1
@@ -180,6 +186,7 @@ async def classify_single(
180186
- Testing and debugging individual image classifications
181187
182188
Args:
189+
----
183190
image_data: ImageData object containing image bytes and metadata.
184191
The image will be processed through the same transformation
185192
pipeline as the streaming classify method (resize, compression)
@@ -189,14 +196,17 @@ async def classify_single(
189196
automatically.
190197
191198
Returns:
199+
-------
192200
ClassificationOutput containing either classification results or
193201
error information for the single image.
194202
195203
Raises:
204+
------
196205
AthenaError: If the service returns an error.
197206
grpc.aio.AioRpcError: For gRPC communication errors.
198207
199208
Example:
209+
-------
200210
# Create ImageData from raw bytes
201211
image_data = ImageData(image_bytes)
202212

src/resolver_athena_client/client/channel.py

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import asyncio
44
import json
55
import time
6+
from typing import override
67

78
import grpc
89
import httpx
@@ -22,11 +23,13 @@ def __init__(self, token: str) -> None:
2223
"""Initialize the plugin with the auth token.
2324
2425
Args:
26+
----
2527
token: The authorization token to add to requests
2628
2729
"""
28-
self._token = token
30+
self._token: str = token
2931

32+
@override
3033
def __call__(
3134
self,
3235
_: grpc.AuthMetadataContext,
@@ -37,6 +40,7 @@ def __call__(
3740
This method will be invoked asynchronously in a separate thread.
3841
3942
Args:
43+
----
4044
callback: An AuthMetadataPluginCallback to be invoked either
4145
synchronously or asynchronously.
4246
@@ -58,6 +62,7 @@ def __init__(
5862
"""Initialize the credential helper.
5963
6064
Args:
65+
----
6166
client_id: OAuth client ID
6267
client_secret: OAuth client secret
6368
auth_url: OAuth token endpoint URL
@@ -71,24 +76,26 @@ def __init__(
7176
msg = "client_secret cannot be empty"
7277
raise CredentialError(msg)
7378

74-
self._client_id = client_id
75-
self._client_secret = client_secret
76-
self._auth_url = auth_url
77-
self._audience = audience
79+
self._client_id: str = client_id
80+
self._client_secret: str = client_secret
81+
self._auth_url: str = auth_url
82+
self._audience: str = audience
7883
self._token: str | None = None
7984
self._token_expires_at: float | None = None
80-
self._lock = asyncio.Lock()
85+
self._lock: asyncio.Lock = asyncio.Lock()
8186

8287
async def get_token(self) -> str:
8388
"""Get a valid authentication token.
8489
8590
This method will return a cached token if it's still valid,
8691
or fetch a new token if needed.
8792
88-
Returns:
93+
Returns
94+
-------
8995
A valid authentication token
9096
91-
Raises:
97+
Raises
98+
------
9299
OAuthError: If token acquisition fails
93100
TokenExpiredError: If token has expired and refresh fails
94101
@@ -109,7 +116,8 @@ async def get_token(self) -> str:
109116
def _is_token_valid(self) -> bool:
110117
"""Check if the current token is valid and not expired.
111118
112-
Returns:
119+
Returns
120+
-------
113121
True if token is valid, False otherwise
114122
115123
"""
@@ -122,7 +130,8 @@ def _is_token_valid(self) -> bool:
122130
async def _refresh_token(self) -> None:
123131
"""Refresh the authentication token by making an OAuth request.
124132
125-
Raises:
133+
Raises
134+
------
126135
OAuthError: If the OAuth request fails
127136
128137
"""
@@ -143,7 +152,7 @@ async def _refresh_token(self) -> None:
143152
headers=headers,
144153
timeout=30.0,
145154
)
146-
response.raise_for_status()
155+
_ = response.raise_for_status()
147156

148157
token_data = response.json()
149158
self._token = token_data["access_token"]
@@ -195,13 +204,16 @@ async def create_channel_with_credentials(
195204
"""Create a gRPC channel with OAuth credential helper.
196205
197206
Args:
207+
----
198208
host: The host address to connect to
199209
credential_helper: The credential helper for OAuth authentication
200210
201211
Returns:
212+
-------
202213
A secure gRPC channel with OAuth authentication
203214
204215
Raises:
216+
------
205217
InvalidHostError: If host is empty
206218
OAuthError: If OAuth authentication fails
207219

src/resolver_athena_client/client/correlation.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import abc
66
import hashlib
7+
from typing import override
78

89
from resolver_athena_client.client.consts import MAX_DEPLOYMENT_ID_LENGTH
910

@@ -23,14 +24,17 @@ def get_correlation_id(self, input_data: bytes | str | bytearray) -> str:
2324
"""Generate a correlation ID for the given input data.
2425
2526
Args:
27+
----
2628
input_data: Data to use as the basis for correlation ID generation.
2729
The type and structure of this data depends on the specific
2830
implementation.
2931
3032
Returns:
33+
-------
3134
A string containing the generated correlation ID.
3235
3336
Raises:
37+
------
3438
ValueError: If the input data is not in a format supported by
3539
the implementation.
3640
@@ -45,6 +49,7 @@ class HashCorrelationProvider(CorrelationProvider):
4549
input data's bytes, which serves as the correlation ID.
4650
"""
4751

52+
@override
4853
def get_correlation_id(self, input_data: bytes | str | bytearray) -> str:
4954
"""Generate a correlation ID by hashing the input data.
5055
@@ -54,12 +59,15 @@ def get_correlation_id(self, input_data: bytes | str | bytearray) -> str:
5459
- Otherwise, convert to string and encode as UTF-8
5560
5661
Args:
62+
----
5763
input_data: Data to hash for correlation ID generation.
5864
5965
Returns:
66+
-------
6067
A hex string of the SHA-256 hash of the input data.
6168
6269
Raises:
70+
------
6371
ValueError: If the input data cannot be converted to bytes.
6472
6573
"""

src/resolver_athena_client/client/exceptions.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Base classes for all Athena exceptions."""
22

3-
from typing import TYPE_CHECKING
3+
from typing import TYPE_CHECKING, final
44

55
if TYPE_CHECKING:
66
from resolver_athena_client.generated.athena.models_pb2 import (
@@ -15,45 +15,46 @@ class AthenaError(Exception):
1515
class InvalidRequestError(AthenaError):
1616
"""Raised when the request is invalid."""
1717

18-
default_message = "Invalid request"
18+
default_message: str = "Invalid request"
1919

2020

2121
class InvalidResponseError(AthenaError):
2222
"""Raised when the response is invalid."""
2323

24-
default_message = "Invalid response"
24+
default_message: str = "Invalid response"
2525

2626

2727
class InvalidAuthError(AthenaError):
2828
"""Raised when the authentication is invalid."""
2929

30-
default_message = "auth_token cannot be empty"
30+
default_message: str = "auth_token cannot be empty"
3131

3232

3333
class InvalidHostError(AthenaError):
3434
"""Raised when the host is invalid."""
3535

36-
default_message = "host cannot be empty"
36+
default_message: str = "host cannot be empty"
3737

3838

3939
class OAuthError(AthenaError):
4040
"""Raised when OAuth authentication fails."""
4141

42-
default_message = "OAuth authentication failed"
42+
default_message: str = "OAuth authentication failed"
4343

4444

4545
class TokenExpiredError(AthenaError):
4646
"""Raised when the authentication token has expired."""
4747

48-
default_message = "Authentication token has expired"
48+
default_message: str = "Authentication token has expired"
4949

5050

5151
class CredentialError(AthenaError):
5252
"""Raised when there are issues with credential management."""
5353

54-
default_message = "Credential management error"
54+
default_message: str = "Credential management error"
5555

5656

57+
@final
5758
class ClassificationOutputError(AthenaError):
5859
"""Raised when an individual classification output contains an error."""
5960

@@ -66,6 +67,7 @@ def __init__(
6667
"""Initialize the classification output error.
6768
6869
Args:
70+
----
6971
correlation_id: The correlation ID of the failed output
7072
error: The ClassificationError from the protobuf response
7173
message: Optional custom error message

0 commit comments

Comments
 (0)