style: Fix 411 ruff lint issues (Kimi's issue #4)

Auto-fixed lint issues with ruff --fix and --unsafe-fixes:

Issue #4: Ruff Lint Issues
- Before: 447 errors (originally reported as ~5,500)
- After: 55 errors remaining
- Fixed: 411 errors (92% reduction)

Auto-fixes applied:
- 156 UP006: List/Dict → list/dict (PEP 585)
- 63 UP045: Optional[X] → X | None (PEP 604)
- 52 F401: Removed unused imports
- 52 UP035: Fixed deprecated imports
- 34 E712: True/False comparisons → not/bool()
- 17 F841: Removed unused variables
- Plus 37 other auto-fixable issues

Remaining 55 errors (non-critical):
- 39 B904: Exception chaining (best practice)
- 5 F401: Unused imports (edge cases)
- 3 SIM105: Could use contextlib.suppress
- 8 other minor style issues

These remaining issues are code quality improvements, not critical bugs.

Result: Code quality significantly improved (92% of linting issues resolved)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
yusyus
2026-02-08 12:46:38 +03:00
parent 0573ef24f9
commit 51787e57bc
56 changed files with 277 additions and 360 deletions

View File

@@ -4,10 +4,8 @@ Change detection for documentation pages.
import hashlib
import difflib
from typing import Dict, List, Optional, Tuple
from datetime import datetime
import requests
from pathlib import Path
from .models import PageChange, ChangeType, ChangeReport
@@ -59,7 +57,7 @@ class ChangeDetector:
"""
return hashlib.sha256(content.encode('utf-8')).hexdigest()
def fetch_page(self, url: str) -> Tuple[str, Dict[str, str]]:
def fetch_page(self, url: str) -> tuple[str, dict[str, str]]:
"""
Fetch page content and metadata.
@@ -92,9 +90,9 @@ class ChangeDetector:
def check_page(
self,
url: str,
old_hash: Optional[str] = None,
old_hash: str | None = None,
generate_diff: bool = False,
old_content: Optional[str] = None
old_content: str | None = None
) -> PageChange:
"""
Check if page has changed.
@@ -137,7 +135,7 @@ class ChangeDetector:
detected_at=datetime.utcnow()
)
except requests.RequestException as e:
except requests.RequestException:
# Page might be deleted or temporarily unavailable
return PageChange(
url=url,
@@ -149,8 +147,8 @@ class ChangeDetector:
def check_pages(
self,
urls: List[str],
previous_hashes: Dict[str, str],
urls: list[str],
previous_hashes: dict[str, str],
generate_diffs: bool = False
) -> ChangeReport:
"""
@@ -254,8 +252,8 @@ class ChangeDetector:
def check_header_changes(
self,
url: str,
old_modified: Optional[str] = None,
old_etag: Optional[str] = None
old_modified: str | None = None,
old_etag: str | None = None
) -> bool:
"""
Quick check using HTTP headers (no content download).
@@ -284,10 +282,7 @@ class ChangeDetector:
if old_modified and new_modified and old_modified != new_modified:
return True
if old_etag and new_etag and old_etag != new_etag:
return True
return False
return bool(old_etag and new_etag and old_etag != new_etag)
except requests.RequestException:
# If HEAD request fails, assume change (will be verified with GET)
@@ -295,9 +290,9 @@ class ChangeDetector:
def batch_check_headers(
self,
urls: List[str],
previous_metadata: Dict[str, Dict[str, str]]
) -> List[str]:
urls: list[str],
previous_metadata: dict[str, dict[str, str]]
) -> list[str]:
"""
Batch check URLs using headers only.

View File

@@ -2,7 +2,7 @@
Pydantic models for sync system.
"""
from typing import List, Optional, Dict, Any
from typing import Any
from datetime import datetime
from enum import Enum
from pydantic import BaseModel, Field
@@ -21,9 +21,9 @@ class PageChange(BaseModel):
url: str = Field(..., description="Page URL")
change_type: ChangeType = Field(..., description="Type of change")
old_hash: Optional[str] = Field(None, description="Previous content hash")
new_hash: Optional[str] = Field(None, description="New content hash")
diff: Optional[str] = Field(None, description="Content diff (if available)")
old_hash: str | None = Field(None, description="Previous content hash")
new_hash: str | None = Field(None, description="New content hash")
diff: str | None = Field(None, description="Content diff (if available)")
detected_at: datetime = Field(
default_factory=datetime.utcnow,
description="When change was detected"
@@ -47,9 +47,9 @@ class ChangeReport(BaseModel):
skill_name: str = Field(..., description="Skill name")
total_pages: int = Field(..., description="Total pages checked")
added: List[PageChange] = Field(default_factory=list, description="Added pages")
modified: List[PageChange] = Field(default_factory=list, description="Modified pages")
deleted: List[PageChange] = Field(default_factory=list, description="Deleted pages")
added: list[PageChange] = Field(default_factory=list, description="Added pages")
modified: list[PageChange] = Field(default_factory=list, description="Modified pages")
deleted: list[PageChange] = Field(default_factory=list, description="Deleted pages")
unchanged: int = Field(0, description="Number of unchanged pages")
checked_at: datetime = Field(
default_factory=datetime.utcnow,
@@ -84,19 +84,19 @@ class SyncConfig(BaseModel):
default=True,
description="Send notifications on changes"
)
notification_channels: List[str] = Field(
notification_channels: list[str] = Field(
default_factory=list,
description="Notification channels (email, slack, webhook)"
)
webhook_url: Optional[str] = Field(
webhook_url: str | None = Field(
None,
description="Webhook URL for change notifications"
)
email_recipients: List[str] = Field(
email_recipients: list[str] = Field(
default_factory=list,
description="Email recipients for notifications"
)
slack_webhook: Optional[str] = Field(
slack_webhook: str | None = Field(
None,
description="Slack webhook URL"
)
@@ -120,16 +120,16 @@ class SyncState(BaseModel):
"""Current state of sync monitoring."""
skill_name: str = Field(..., description="Skill name")
last_check: Optional[datetime] = Field(None, description="Last check time")
last_change: Optional[datetime] = Field(None, description="Last change detected")
last_check: datetime | None = Field(None, description="Last check time")
last_change: datetime | None = Field(None, description="Last change detected")
total_checks: int = Field(default=0, description="Total checks performed")
total_changes: int = Field(default=0, description="Total changes detected")
page_hashes: Dict[str, str] = Field(
page_hashes: dict[str, str] = Field(
default_factory=dict,
description="URL -> content hash mapping"
)
status: str = Field(default="idle", description="Current status")
error: Optional[str] = Field(None, description="Last error message")
error: str | None = Field(None, description="Last error message")
class WebhookPayload(BaseModel):
@@ -141,8 +141,8 @@ class WebhookPayload(BaseModel):
default_factory=datetime.utcnow,
description="Event timestamp"
)
changes: Optional[ChangeReport] = Field(None, description="Change report")
metadata: Dict[str, Any] = Field(
changes: ChangeReport | None = Field(None, description="Change report")
metadata: dict[str, Any] = Field(
default_factory=dict,
description="Additional metadata"
)

View File

@@ -6,12 +6,12 @@ import json
import time
import threading
from pathlib import Path
from typing import Optional, Dict, List, Callable
from collections.abc import Callable
from datetime import datetime
import schedule
from .detector import ChangeDetector
from .models import SyncConfig, SyncState, ChangeReport, WebhookPayload
from .models import SyncState, ChangeReport, WebhookPayload
from .notifier import Notifier
@@ -50,8 +50,8 @@ class SyncMonitor:
config_path: str,
check_interval: int = 3600,
auto_update: bool = False,
state_file: Optional[str] = None,
on_change: Optional[Callable[[ChangeReport], None]] = None
state_file: str | None = None,
on_change: Callable[[ChangeReport], None] | None = None
):
"""
Initialize sync monitor.
@@ -244,7 +244,7 @@ class SyncMonitor:
print(f"🛑 Stopped monitoring {self.skill_name}")
def stats(self) -> Dict:
def stats(self) -> dict:
"""Get monitoring statistics."""
return {
"skill_name": self.skill_name,

View File

@@ -4,7 +4,6 @@ Notification system for sync events.
import os
import requests
from typing import Optional, List
from .models import WebhookPayload
@@ -32,9 +31,9 @@ class Notifier:
def __init__(
self,
webhook_url: Optional[str] = None,
slack_webhook: Optional[str] = None,
email_recipients: Optional[List[str]] = None,
webhook_url: str | None = None,
slack_webhook: str | None = None,
email_recipients: list[str] | None = None,
console: bool = True
):
"""