Skip to content

Commit c321283

Browse files
fix(configs): resolve all ruff and mypy linting issues
- Update Generic syntax for Python 3.13 - Fix type annotations and inheritance issues - Add missing docstrings to validators - Update deprecated ruff rule codes
1 parent 6c4b227 commit c321283

3 files changed

Lines changed: 43 additions & 10 deletions

File tree

archipy/configs/base_config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Generic, Self, TypeVar
1+
from typing import Self, TypeVar
22

33
from pydantic_settings import (
44
BaseSettings,
@@ -45,7 +45,7 @@
4545
R = TypeVar("R") # Runtime Config
4646

4747

48-
class BaseConfig(BaseSettings, Generic[R]):
48+
class BaseConfig[R](BaseSettings):
4949
"""Base configuration class for ArchiPy applications.
5050
5151
This class provides a comprehensive configuration system that loads settings

archipy/configs/config_template.py

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ class ElasticsearchAPMConfig(BaseModel):
110110
and error reporting.
111111
"""
112112

113-
API_REQUEST_SIZE: int = Field(default="768kb", description="Maximum size of API requests")
113+
API_REQUEST_SIZE: str = Field(default="768kb", description="Maximum size of API requests")
114114
API_REQUEST_TIME: str = Field(default="10s", description="Maximum time for API requests")
115115
AUTO_LOG_STACKS: bool = Field(default=True, description="Whether to automatically log stack traces")
116116
CAPTURE_BODY: str = Field(default="off", description="Level of request body capture")
@@ -119,7 +119,7 @@ class ElasticsearchAPMConfig(BaseModel):
119119
IS_ENABLED: bool = Field(default=False, description="Whether APM is enabled")
120120
ENVIRONMENT: str | None = Field(default=None, description="APM environment name")
121121
LOG_FILE: str = Field(default="", description="Path to APM log file")
122-
LOG_FILE_SIZE: int = Field(default="50mb", description="Maximum size of APM log file")
122+
LOG_FILE_SIZE: str = Field(default="50mb", description="Maximum size of APM log file")
123123
RECORDING: bool = Field(default=True, description="Whether to record transactions")
124124
SECRET_TOKEN: str | None = Field(default=None, description="APM secret token")
125125
SERVER_TIMEOUT: str = Field(default="5s", description="Server timeout duration")
@@ -308,6 +308,18 @@ class KafkaConfig(BaseModel):
308308

309309
@model_validator(mode="after")
310310
def validate_security_settings(self) -> "KafkaConfig":
311+
"""Validate security-related settings for Kafka configuration.
312+
313+
Ensures that SASL authentication settings are properly configured when
314+
using SASL security protocols, and warns about missing SSL certificates
315+
when SSL is enabled.
316+
317+
Returns:
318+
KafkaConfig: The validated configuration instance.
319+
320+
Raises:
321+
ValueError: If SASL authentication is incomplete.
322+
"""
311323
if self.SECURITY_PROTOCOL in ["SASL_PLAINTEXT", "SASL_SSL"]:
312324
if not (self.SASL_MECHANISM and self.USERNAME and self.PASSWORD):
313325
raise ValueError("SASL authentication requires SASL_MECHANISM, USERNAME, and PASSWORD to be set.")
@@ -318,6 +330,17 @@ def validate_security_settings(self) -> "KafkaConfig":
318330

319331
@model_validator(mode="after")
320332
def validate_consumer_settings(self) -> "KafkaConfig":
333+
"""Validate consumer-specific settings for Kafka configuration.
334+
335+
Ensures that auto-commit and offset reset settings are compatible,
336+
and that heartbeat interval is less than session timeout.
337+
338+
Returns:
339+
KafkaConfig: The validated configuration instance.
340+
341+
Raises:
342+
ValueError: If consumer settings are incompatible.
343+
"""
321344
if self.ENABLE_AUTO_COMMIT and self.AUTO_OFFSET_RESET == "none":
322345
raise ValueError("ENABLE_AUTO_COMMIT cannot be True when AUTO_OFFSET_RESET is 'none'.")
323346
if self.HEARTBEAT_INTERVAL_MS >= self.SESSION_TIMEOUT_MS:
@@ -326,6 +349,17 @@ def validate_consumer_settings(self) -> "KafkaConfig":
326349

327350
@model_validator(mode="after")
328351
def validate_idempotence_and_transactions(self) -> "KafkaConfig":
352+
"""Validate idempotence and transaction settings for Kafka configuration.
353+
354+
Ensures that idempotence is properly configured with 'all' acknowledgments,
355+
and that transactional producers have idempotence enabled.
356+
357+
Returns:
358+
KafkaConfig: The validated configuration instance.
359+
360+
Raises:
361+
ValueError: If idempotence or transaction settings are invalid.
362+
"""
329363
if self.ENABLE_IDEMPOTENCE and self.ACKS != "all":
330364
raise ValueError("ENABLE_IDEMPOTENCE requires ACKS to be 'all'.")
331365
if self.TRANSACTIONAL_ID is not None and not self.ENABLE_IDEMPOTENCE:
@@ -406,7 +440,7 @@ class SQLiteSQLAlchemyConfig(SQLAlchemyConfig):
406440
DRIVER_NAME: str = Field(default="sqlite+aiosqlite", description="SQLite driver name")
407441
DATABASE: str = Field(default=":memory:", description="SQLite database path")
408442
ISOLATION_LEVEL: str | None = Field(default=None, description="SQLite isolation level")
409-
PORT: str | None = Field(default=None, description="Not used for SQLite")
443+
PORT: int | None = Field(default=None, description="Not used for SQLite")
410444

411445

412446
class PostgresSQLAlchemyConfig(SQLAlchemyConfig):
@@ -455,8 +489,8 @@ def extract_connection_parts(self) -> Self:
455489
url = str(self.POSTGRES_DSN)
456490
parsed = urlparse(url)
457491

458-
# Extract scheme/driver
459-
if self.DRIVER_NAME is None and parsed.scheme:
492+
# Extract scheme/driver (override default if URL scheme is different)
493+
if parsed.scheme and parsed.scheme != self.DRIVER_NAME:
460494
self.DRIVER_NAME = parsed.scheme
461495

462496
# Extract username and password

pyproject.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,6 @@ lint.select = [
158158
lint.ignore = [
159159
"ANN002", # Missing type annotation for *args
160160
"ANN003", # Missing type annotation for **kwargs
161-
"ANN101", # Missing type annotation for self in method
162-
"ANN102", # Missing type annotation for cls in classmethod
163161
"BLE001", # Do not catch blind exception: `Exception`
164162
"C901", # Function is too complex (McCabe complexity)
165163
"D100", # Missing docstring in public module
@@ -175,7 +173,7 @@ lint.ignore = [
175173
"S101", # Ignore assert used (equivalent to bandit's B101)
176174
"S301", # Ignore pickle usage (equivalent to bandit's B301)
177175
"S403", # Ignore pickle usage (equivalent to bandit's B403)
178-
"TCH002", # Type-checking import issues
176+
"TC002", # Type-checking import issues
179177
"TRY003", #Avoid specifying long messages outside the exception class
180178
"TRY301", # Abstract raise into a function
181179
]
@@ -197,6 +195,7 @@ target-version = "py313"
197195
# Per-file ignores
198196
[tool.ruff.lint.per-file-ignores]
199197
# Ignore F811 (redefinition of function) in steps implementations
198+
"archipy/configs/config_template.py" = ["S104"] # Allow binding to all interfaces for containerized deployments
200199
"archipy/helpers/decorators/*" = ["ANN401"]
201200
"archipy/helpers/utils/jwt_utils.py" = ["S105"]
202201
"archipy/helpers/decorators/sqlalchemy_atomic.py" = ["BLE001"]

0 commit comments

Comments
 (0)