chore(lint): elargir les regles ruff et rendre le format bloquant en CI

QUA-002, seconde moitie. Le depot etant formate, l elargissement porte sur
des defauts et non sur du brassage.

Ajoute a la selection : B (bugbear), C4, RET, SIM, UP. Le lot entier n a
produit que 24 signalements sur 76 fichiers -- le code etait plus propre
que l audit ne le craignait. Neuf corriges automatiquement, quinze a la
main.

SIM108 est ignore : forcer un ternaire se lit moins bien que le if/else
qu il remplace, au seul endroit ou il se declenche.

isort (I) n est PAS active. Il reordonnerait les imports de 48 fichiers,
soit une seconde passe de pur brassage juste apres le commit de formatage.
A faire, mais seul.

Deux vrais defauts trouves par les nouvelles regles
  - team_matches.edit_match faisait `except ValueError: pass` sur l heure de
    debut et l heure de fin, trois lignes sous un champ date qui, lui,
    signale et redirige. Une heure mal saisie etait donc acceptee par le
    formulaire, jetee, l ancienne valeur conservee -- et la page annoncait
    la reussite. Meme traitement que la date desormais.
  - backup.py levait BackupError depuis deux blocs `except` sans `from`,
    ce qui perdait la cause d origine dans la trace.

Ainsi que : un `return` explicite dans force_https, `%`-formatage remplace
dans log_auth_event (operations de chaine avant journalisation, pas des
gabarits de logger -- la redaction n est pas affectee), une compréhension
inutile, un `set(...)` en compréhension d ensemble, `open(..., 'r')`, une
variable de boucle inutilisee, et `contextlib.suppress` dans conftest.

CI : `ruff format --check` remplace le commentaire qui expliquait pourquoi
il etait absent.

263 tests passent. Les deux nouveaux messages sont traduits ; attention,
pybabel les avait apparies en `fuzzy` avec des entrees « date » existantes,
et une entree fuzzy est ignoree a l execution.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
GGThed
2026-08-08 15:59:40 -04:00
co-authored by Claude Opus 5
parent 7cec18c139
commit 8e3865f557
17 changed files with 475 additions and 439 deletions
+4 -4
View File
@@ -167,13 +167,13 @@ def backup_database(conn):
text=True,
timeout=900,
)
except FileNotFoundError:
except FileNotFoundError as err:
raise BackupError(
f'{PG_DUMP} not found. Install the PostgreSQL client tools, or set '
'PG_DUMP to its full path.'
)
except subprocess.TimeoutExpired:
raise BackupError('pg_dump timed out after 15 minutes.')
) from err
except subprocess.TimeoutExpired as err:
raise BackupError('pg_dump timed out after 15 minutes.') from err
if result.returncode != 0:
raise BackupError(f'pg_dump failed: {result.stderr.strip()}')
+25 -28
View File
@@ -176,29 +176,27 @@ def check_dependencies():
if result.returncode == 0:
print('[OK] No known vulnerabilities found')
return True
else:
try:
data = json.loads(result.stdout)
# pip-audit's "dependencies" array lists EVERY dependency, each
# carrying a "vulns" list that is empty when the package is
# clean. Treating the array itself as the vulnerability list
# reported all ~45 installed packages as vulnerable on every
# run, which is why this check was pure noise.
affected = [dep for dep in data.get('dependencies', []) if dep.get('vulns')]
if affected:
for dep in affected:
ids = ', '.join(v.get('id', '?') for v in dep.get('vulns', []))
print(f'[FAIL] {dep["name"]}=={dep["version"]}: {ids}')
return False
else:
print('[OK] No vulnerabilities found')
return True
except json.JSONDecodeError:
if result.stdout:
print(f'[INFO] {result.stdout.strip()}')
if result.stderr:
print(f'[WARN] {result.stderr.strip()}')
return True
try:
data = json.loads(result.stdout)
# pip-audit's "dependencies" array lists EVERY dependency, each
# carrying a "vulns" list that is empty when the package is
# clean. Treating the array itself as the vulnerability list
# reported all ~45 installed packages as vulnerable on every
# run, which is why this check was pure noise.
affected = [dep for dep in data.get('dependencies', []) if dep.get('vulns')]
if affected:
for dep in affected:
ids = ', '.join(v.get('id', '?') for v in dep.get('vulns', []))
print(f'[FAIL] {dep["name"]}=={dep["version"]}: {ids}')
return False
print('[OK] No vulnerabilities found')
return True
except json.JSONDecodeError:
if result.stdout:
print(f'[INFO] {result.stdout.strip()}')
if result.stderr:
print(f'[WARN] {result.stderr.strip()}')
return True
except FileNotFoundError:
print('[SKIP] pip-audit not installed. Run: pip install pip-audit')
return True
@@ -223,7 +221,7 @@ def check_file_permissions():
gitignore_path = os.path.join(os.getcwd(), '.gitignore')
if os.path.exists(gitignore_path):
required_patterns = ['.env', 'instance/', '*.db', '*.log']
with open(gitignore_path, 'r') as f:
with open(gitignore_path) as f:
content = f.read()
for pattern in required_patterns:
@@ -245,7 +243,7 @@ def check_file_permissions():
# Check for leftover .pyc or __pycache__
pycache_count = 0
for root, dirs, files in os.walk(os.getcwd()):
for _root, dirs, files in os.walk(os.getcwd()):
if '__pycache__' in dirs:
pycache_count += 1
for f in files:
@@ -402,9 +400,8 @@ def main():
if failed == 0:
print('\n[OK] All security checks passed!')
return 0
else:
print(f'\n[WARN] {failed} check(s) failed. Review the output above.')
return 1
print(f'\n[WARN] {failed} check(s) failed. Review the output above.')
return 1
if __name__ == '__main__':