Fix Python 3.9 compatibility + add .claude project settings

- Replace `str | list[str]` with `Union[str, List[str]]` (3.9 compat)
- Replace `str | None` with `Optional[str]` in validator.py
- Replace `Live | None` with `Optional[Live]` in display.py
- Add .claude/settings.json: auto-allow git, ruff, pytest, pip, soup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Alpamys 2026-02-20 16:36:18 +05:00
parent 7665e7c3aa
commit d167cd4ddd
4 changed files with 33 additions and 5 deletions

24
.claude/settings.json Normal file
View File

@ -0,0 +1,24 @@
{
"permissions": {
"allow": [
"Bash(git status*)",
"Bash(git diff*)",
"Bash(git log*)",
"Bash(git add*)",
"Bash(git commit*)",
"Bash(git push*)",
"Bash(git branch*)",
"Bash(git checkout*)",
"Bash(git stash*)",
"Bash(git remote*)",
"Bash(ruff check*)",
"Bash(ruff format*)",
"Bash(pytest*)",
"Bash(python -m pytest*)",
"Bash(pip install*)",
"Bash(pip list*)",
"Bash(soup *)",
"Bash(python -m soup_cli*)"
]
}
}

View File

@ -1,6 +1,6 @@
"""Pydantic schemas for soup.yaml config — single source of truth.""" """Pydantic schemas for soup.yaml config — single source of truth."""
from typing import Literal, Optional from typing import List, Literal, Optional, Union
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
@ -9,7 +9,7 @@ class LoraConfig(BaseModel):
r: int = Field(default=64, description="LoRA rank") r: int = Field(default=64, description="LoRA rank")
alpha: int = Field(default=16, description="LoRA alpha") alpha: int = Field(default=16, description="LoRA alpha")
dropout: float = Field(default=0.05, description="LoRA dropout") dropout: float = Field(default=0.05, description="LoRA dropout")
target_modules: str | list[str] = Field( target_modules: Union[str, List[str]] = Field(
default="auto", default="auto",
description="Target modules for LoRA. 'auto' = let peft decide.", description="Target modules for LoRA. 'auto' = let peft decide.",
) )
@ -28,7 +28,7 @@ class DataConfig(BaseModel):
class TrainingConfig(BaseModel): class TrainingConfig(BaseModel):
epochs: int = Field(default=3, ge=1, description="Number of training epochs") epochs: int = Field(default=3, ge=1, description="Number of training epochs")
lr: float = Field(default=2e-5, gt=0, description="Learning rate") lr: float = Field(default=2e-5, gt=0, description="Learning rate")
batch_size: int | Literal["auto"] = Field( batch_size: Union[int, Literal["auto"]] = Field(
default="auto", default="auto",
description="Batch size. 'auto' = find max that fits in memory.", description="Batch size. 'auto' = find max that fits in memory.",
) )

View File

@ -1,9 +1,11 @@
"""Dataset validation and statistics.""" """Dataset validation and statistics."""
from typing import Optional
from soup_cli.data.formats import FORMAT_SIGNATURES from soup_cli.data.formats import FORMAT_SIGNATURES
def validate_and_stats(data: list[dict], expected_format: str | None = None) -> dict: def validate_and_stats(data: list[dict], expected_format: Optional[str] = None) -> dict:
"""Compute stats and validate dataset.""" """Compute stats and validate dataset."""
if not data: if not data:
return { return {

View File

@ -1,5 +1,7 @@
"""Rich live training dashboard in the terminal.""" """Rich live training dashboard in the terminal."""
from typing import Optional
from rich.console import Console from rich.console import Console
from rich.live import Live from rich.live import Live
from rich.panel import Panel from rich.panel import Panel
@ -23,7 +25,7 @@ class TrainingDisplay:
self.grad_norm = 0.0 self.grad_norm = 0.0
self.gpu_mem = "" self.gpu_mem = ""
self.speed = 0.0 self.speed = 0.0
self._live: Live | None = None self._live: Optional[Live] = None
def start(self, total_steps: int): def start(self, total_steps: int):
"""Start the live display.""" """Start the live display."""