style: formater le depot avec ruff format

QUA-002, premiere moitie. **Ce commit ne fait que reformater** : aucun
changement de comportement, aucune ligne de logique touchee. 72 fichiers,
4 restaient deja conformes. Il est isole exprès, pour que `git log -p` sur
les commits voisins reste lisible.

`quote-style = "preserve"` etait deja pose dans pyproject.toml, ce qui
evite le brassage guillemets simples / doubles : le diff porte sur les
retours a la ligne, l indentation des appels longs et les virgules
finales, pas sur le style de chaine.

Verification : 263 tests passent avant et apres, ruff check propre.

L activation en CI arrive dans le commit suivant, separement, pour que ce
diff-ci ne contienne rien d autre.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
GGThed
2026-08-08 15:53:10 -04:00
co-authored by Claude Opus 5
parent 2f40290f00
commit 7cec18c139
72 changed files with 2658 additions and 1449 deletions
+63 -67
View File
@@ -12,7 +12,15 @@ Usage:
import re
from flask_babel import lazy_gettext as _l
from marshmallow import Schema, fields, validate, ValidationError, pre_load, validates_schema, EXCLUDE
from marshmallow import (
Schema,
fields,
validate,
ValidationError,
pre_load,
validates_schema,
EXCLUDE,
)
from app.models import USER_TYPES
@@ -20,58 +28,55 @@ from app.models import USER_TYPES
# Custom Validators
# =============================================================================
PASSWORD_POLICY = re.compile(
r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$'
)
PASSWORD_POLICY = re.compile(r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$')
"""Password policy: minimum 8 chars, 1 uppercase, 1 lowercase, 1 digit."""
def validate_password(value):
"""Validate password meets strength requirements.
Requires: minimum 8 characters, at least one uppercase letter,
one lowercase letter, and one digit.
Args:
value: The password string to validate.
Raises:
ValidationError: If password does not meet requirements.
"""
if not PASSWORD_POLICY.match(value):
raise ValidationError(_l(
'Password must be at least 8 characters with uppercase, '
'lowercase, and a number.'
))
raise ValidationError(
_l('Password must be at least 8 characters with uppercase, lowercase, and a number.')
)
def validate_username(value):
"""Validate username format.
Usernames must be 3-30 characters and contain only alphanumeric
characters, underscores, and hyphens.
Args:
value: The username string to validate.
Raises:
ValidationError: If username does not meet requirements.
"""
if not re.match(r'^[a-zA-Z0-9_-]{3,30}$', value):
raise ValidationError(_l(
'Username must be 3-30 characters (letters, numbers, underscore, hyphen).'
))
raise ValidationError(
_l('Username must be 3-30 characters (letters, numbers, underscore, hyphen).')
)
def validate_discord_username(value):
"""Validate Discord username format if provided.
Accepts empty strings (optional field). Validates that the username
matches common Discord username patterns.
Args:
value: The Discord username to validate.
Raises:
ValidationError: If the format is invalid.
"""
@@ -83,12 +88,12 @@ def validate_discord_username(value):
def validate_discord_user_id(value):
"""Validate Discord user ID (snowflake) if provided.
Discord user IDs are 17-20 digit numbers.
Args:
value: The Discord user ID to validate.
Raises:
ValidationError: If the format is invalid.
"""
@@ -100,12 +105,12 @@ def validate_discord_user_id(value):
def validate_phone(value):
"""Validate optional phone number format.
Accepts empty strings. Validates common phone formats.
Args:
value: The phone number to validate.
Raises:
ValidationError: If the format is invalid.
"""
@@ -120,21 +125,23 @@ def validate_phone(value):
# Validation Schemas
# =============================================================================
class StripMixin(Schema):
"""Mixin that automatically strips whitespace from all string fields
and ignores unknown fields (e.g., csrf_token from Flask-WTF)."""
class Meta:
"""Marshmallow Meta options."""
unknown = EXCLUDE # Ignore csrf_token and other unknown fields
@pre_load
def strip_strings(self, data, **kwargs):
"""Strip whitespace from all string values in the input data.
Args:
data: The input dictionary.
Returns:
dict: Data with stripped strings.
"""
@@ -145,11 +152,12 @@ class StripMixin(Schema):
class LoginSchema(StripMixin):
"""Validate login form input.
Fields:
username: 3-30 chars, required.
password: Non-empty, required.
"""
username = fields.String(
required=True,
validate=validate.Length(min=1, max=80, error=_l('Username is required.')),
@@ -162,7 +170,7 @@ class LoginSchema(StripMixin):
class RegisterSchema(StripMixin):
"""Validate player registration form input.
Fields:
username: 3-30 chars alphanumeric, required.
email: Valid email, required.
@@ -174,6 +182,7 @@ class RegisterSchema(StripMixin):
discord_username: Optional, valid format.
league_os_profile: Optional URL.
"""
username = fields.String(
required=True,
validate=[
@@ -223,10 +232,10 @@ class RegisterSchema(StripMixin):
@validates_schema
def validate_password_match(self, data, **kwargs):
"""Ensure confirm_password matches password.
Args:
data: The validated data dictionary.
Raises:
ValidationError: If passwords do not match.
"""
@@ -236,7 +245,7 @@ class RegisterSchema(StripMixin):
class CreateUserSchema(StripMixin):
"""Validate president-created user form input.
Fields:
username: 3-30 chars alphanumeric, required.
email: Valid email, required.
@@ -245,6 +254,7 @@ class CreateUserSchema(StripMixin):
role: Must be valid role, required.
phone: Optional, valid phone format.
"""
username = fields.String(
required=True,
validate=[
@@ -267,10 +277,7 @@ class CreateUserSchema(StripMixin):
)
role = fields.String(
required=True,
validate=validate.OneOf(
USER_TYPES,
error=_l('Invalid role selected.')
),
validate=validate.OneOf(USER_TYPES, error=_l('Invalid role selected.')),
)
phone = fields.String(
validate=validate_phone,
@@ -281,7 +288,7 @@ class CreateUserSchema(StripMixin):
class EditUserSchema(StripMixin):
"""Validate president-edited user form input.
Fields:
full_name: 1-100 chars, required.
email: Valid email, required.
@@ -294,6 +301,7 @@ class EditUserSchema(StripMixin):
league_os_profile: Optional.
games: Optional list.
"""
full_name = fields.String(
required=True,
validate=validate.Length(min=1, max=100, error=_l('Full name is required.')),
@@ -304,10 +312,7 @@ class EditUserSchema(StripMixin):
)
role = fields.String(
required=True,
validate=validate.OneOf(
USER_TYPES,
error=_l('Invalid role selected.')
),
validate=validate.OneOf(USER_TYPES, error=_l('Invalid role selected.')),
)
is_active_account = fields.Boolean(load_default=True)
phone = fields.String(
@@ -341,7 +346,7 @@ class EditUserSchema(StripMixin):
class EditProfileSchema(StripMixin):
"""Validate self-edit profile form input.
Fields:
username: 3-30 chars, required.
full_name: 1-100 chars, required.
@@ -353,6 +358,7 @@ class EditProfileSchema(StripMixin):
league_os_profile: Optional.
games: Optional list.
"""
username = fields.String(
required=True,
validate=[
@@ -399,11 +405,12 @@ class EditProfileSchema(StripMixin):
class UploadContractSchema(StripMixin):
"""Validate contract upload form input.
Fields:
player_id: Integer, required.
notes: Optional text.
"""
player_id = fields.Integer(
required=True,
validate=validate.Range(min=1, error=_l('Player must be selected.')),
@@ -417,33 +424,27 @@ class UploadContractSchema(StripMixin):
class OneOnOneRequestSchema(StripMixin):
"""Validate One on One session request form input.
Fields:
date: Date string (YYYY-MM-DD), required.
start_time: Time string (HH:MM), required.
end_time: Time string (HH:MM), required.
points: Optional text.
"""
date = fields.String(
required=True,
validate=validate.Regexp(
r'^\d{4}-\d{2}-\d{2}$',
error=_l('Date must be in YYYY-MM-DD format.')
r'^\d{4}-\d{2}-\d{2}$', error=_l('Date must be in YYYY-MM-DD format.')
),
)
start_time = fields.String(
required=True,
validate=validate.Regexp(
r'^\d{2}:\d{2}$',
error=_l('Start time must be in HH:MM format.')
),
validate=validate.Regexp(r'^\d{2}:\d{2}$', error=_l('Start time must be in HH:MM format.')),
)
end_time = fields.String(
required=True,
validate=validate.Regexp(
r'^\d{2}:\d{2}$',
error=_l('End time must be in HH:MM format.')
),
validate=validate.Regexp(r'^\d{2}:\d{2}$', error=_l('End time must be in HH:MM format.')),
)
points = fields.String(
validate=validate.Length(max=2000, error=_l('Points must be 2000 characters or less.')),
@@ -454,22 +455,17 @@ class OneOnOneRequestSchema(StripMixin):
class DisponibilityAddSchema(StripMixin):
"""Validate disponibility block addition.
Fields:
day_of_week: Integer 0-6, required.
start_time: Time string (HH:MM), required.
"""
day_of_week = fields.Integer(
required=True,
validate=validate.Range(
min=0, max=6,
error=_l('Day must be 0 (Monday) to 6 (Sunday).')
),
validate=validate.Range(min=0, max=6, error=_l('Day must be 0 (Monday) to 6 (Sunday).')),
)
start_time = fields.String(
required=True,
validate=validate.Regexp(
r'^\d{2}:\d{2}$',
error=_l('Start time must be in HH:MM format.')
),
)
validate=validate.Regexp(r'^\d{2}:\d{2}$', error=_l('Start time must be in HH:MM format.')),
)