Ruff jako linter i formatter, konfiguracja w pyproject.toml: - reguły E, W, F, I, N, UP, B, C4, SIM, TID, BLE, RUF - extend-immutable-calls dla fastapi.Depends, File i Query - wstrzykiwanie zależności opiera się na wywołaniach w wartościach domyślnych argumentów, więc bugbear B008 zgłaszał tam 66 fałszywych trafień - zakaz importów względnych, aby ścieżki w pakiecie czytało się jednoznacznie - katalog frontend wyłączony z analizy Poprawki, które wskazał linter: - Awaitable, Callable i AsyncIterator importowane z collections.abc zamiast z typing - zbędny argument trybu w open(path, "r") - contextlib.suppress zamiast try/except/pass przy anulowaniu zadania - zdjęte dwie niepotrzebne dyrektywy noqa - pięć linii przekraczających 100 znaków zawiniętych Całość przepuszczona przez ruff format. Do .gitignore dochodzi .ruff_cache/. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
54 lines
1.6 KiB
Python
54 lines
1.6 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
import logging
|
|
import os
|
|
from typing import Any
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class JsonFileStore:
|
|
"""Prosty magazyn słownika w pliku JSON, odporny na brakujący/uszkodzony plik."""
|
|
|
|
def __init__(self, path: str):
|
|
self._path = path
|
|
|
|
@property
|
|
def path(self) -> str:
|
|
return self._path
|
|
|
|
def read(self) -> dict[str, Any]:
|
|
if not os.path.exists(self._path):
|
|
return {}
|
|
try:
|
|
with open(self._path, encoding="utf-8") as handle:
|
|
data = json.load(handle)
|
|
except (OSError, ValueError) as error:
|
|
logger.error("Nie udało się odczytać %s: %s", self._path, error)
|
|
return {}
|
|
return data if isinstance(data, dict) else {}
|
|
|
|
def write(self, data: dict[str, Any]) -> bool:
|
|
directory = os.path.dirname(self._path)
|
|
try:
|
|
if directory:
|
|
os.makedirs(directory, exist_ok=True)
|
|
with open(self._path, "w", encoding="utf-8") as handle:
|
|
json.dump(data, handle, indent=4, ensure_ascii=False)
|
|
except OSError as error:
|
|
logger.error("Nie udało się zapisać %s: %s", self._path, error)
|
|
return False
|
|
return True
|
|
|
|
def set(self, key: str, value: Any) -> bool:
|
|
data = self.read()
|
|
if value is None:
|
|
data.pop(key, None)
|
|
else:
|
|
data[key] = value
|
|
return self.write(data)
|
|
|
|
def get(self, key: str, default: Any = None) -> Any:
|
|
return self.read().get(key, default)
|