chore(lint): trier les imports, sauf la facade des modeles

Active la regle isort (I) de ruff. 45 fichiers reordonnes, aucun
changement de comportement : la suite passe avant comme apres.

app/models/__init__.py en est exclu. Ses imports sont ranges en onze
couches commentees qui decrivent le graphe de dependances ; trier par
ordre alphabetique laisse chaque titre au-dessus d un import qu il ne
decrit pas, et ce fichier n a qu un role, etre lu.

Commit isole, comme le formatage : un diff de brassage ne doit pas
servir de couverture a un changement de comportement.
This commit is contained in:
GGThed
2026-08-11 11:40:41 -04:00
parent ab0b975211
commit 47ff544848
45 changed files with 213 additions and 170 deletions
+9 -8
View File
@@ -7,14 +7,15 @@ the Flask application instance with comprehensive security hardening.
import os
import secrets
from flask import Flask, g, request, redirect, jsonify, render_template, url_for
from flask_cors import CORS
from app.extensions import db, login_manager, csrf, limiter, babel
from sqlalchemy import text
from werkzeug.exceptions import HTTPException
import markupsafe
from dotenv import load_dotenv
from flask import Flask, g, jsonify, redirect, render_template, request, url_for
from flask_cors import CORS
from sqlalchemy import text
from werkzeug.exceptions import HTTPException
from app import i18n
from app.extensions import babel, csrf, db, limiter, login_manager
load_dotenv()
@@ -265,13 +266,13 @@ def create_app(config=None):
configure_logging(app)
from app.routes.auth import auth_bp
from app.routes.tryouts import tryouts_bp
from app.routes.evaluations import evaluations_bp
from app.routes.users import users_bp
from app.routes.main import main_bp
from app.routes.teams import teams_bp
from app.routes.matches import matches_bp
from app.routes.team_matches import team_matches_bp
from app.routes.teams import teams_bp
from app.routes.tryouts import tryouts_bp
from app.routes.users import users_bp
app.register_blueprint(auth_bp)
app.register_blueprint(tryouts_bp)
+13 -11
View File
@@ -6,21 +6,22 @@ This module provides a persistent bot that handles:
- Daily reminders at 18:00 EDT for upcoming events
"""
import os
import asyncio
import json
import logging
import os
import tempfile
import time
import asyncio
import threading
import time
import traceback
from datetime import datetime, timedelta
from queue import Empty, Queue
from zoneinfo import ZoneInfo
from queue import Queue, Empty
from discord import Intents
from discord.ext import commands
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.cron import CronTrigger
from discord import Intents
from discord.ext import commands
from dotenv import load_dotenv
load_dotenv()
@@ -453,8 +454,8 @@ class TeamTryoutsBot(commands.Bot):
async def handle_one_on_one_approve(self, coach, message_id, request_id, channel):
"""Handle coach approving a One on One request."""
try:
from app.models import OneOnOneRequest
from app.extensions import db
from app.models import OneOnOneRequest
request = OneOnOneRequest.query.get(request_id)
if not request:
@@ -498,8 +499,8 @@ class TeamTryoutsBot(commands.Bot):
async def handle_one_on_one_reject(self, coach, message_id, request_id, channel):
"""Handle coach rejecting a One on One request."""
try:
from app.models import OneOnOneRequest
from app.extensions import db
from app.models import OneOnOneRequest
request = OneOnOneRequest.query.get(request_id)
if not request:
@@ -743,14 +744,15 @@ class TeamTryoutsBot(commands.Bot):
async def _send_daily_reminders_impl(self):
"""Internal implementation of daily reminders with proper app context."""
try:
from sqlalchemy.orm import joinedload
from app.models import (
Match,
Tryout,
MatchParticipant,
TryoutRegistration,
OneOnOneRequest,
Tryout,
TryoutRegistration,
)
from sqlalchemy.orm import joinedload
now = datetime.now(self.timezone)
tomorrow = now.date() + timedelta(days=1)
+5 -5
View File
@@ -1,10 +1,10 @@
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flask_wtf.csrf import CSRFProtect
from werkzeug.security import generate_password_hash, check_password_hash
from flask_babel import Babel
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
from flask_babel import Babel
from flask_login import LoginManager
from flask_sqlalchemy import SQLAlchemy
from flask_wtf.csrf import CSRFProtect
from werkzeug.security import check_password_hash, generate_password_hash
# Database and extension initialization
db = SQLAlchemy()
+1 -1
View File
@@ -11,8 +11,8 @@ Usage:
import logging
import os
from logging.handlers import RotatingFileHandler
import re
from logging.handlers import RotatingFileHandler
class SensitiveDataFilter(logging.Filter):
-1
View File
@@ -2,7 +2,6 @@
from app.extensions import db
org_team_coaches = db.Table(
'org_team_coaches',
db.Column(
+1 -1
View File
@@ -1,7 +1,7 @@
"""Availability models — BaseAvailability and its concrete subclasses."""
from app.models.availability.base import BaseAvailability
from app.models.availability.player_disponibility import PlayerDisponibility
from app.models.availability.coach_availability import CoachAvailability
from app.models.availability.player_disponibility import PlayerDisponibility
__all__ = ['BaseAvailability', 'PlayerDisponibility', 'CoachAvailability']
+2 -1
View File
@@ -1,8 +1,9 @@
"""Abstract base class for availability models (PlayerDisponibility + CoachAvailability)."""
from app.extensions import db
from datetime import datetime
from app.extensions import db
class BaseAvailability(db.Model):
"""Shared schema for player disponibilities and coach availabilities."""
+3 -2
View File
@@ -1,8 +1,9 @@
"""Contract documents for players to sign."""
from app.extensions import db
from datetime import datetime
from app.extensions import db
class Contract(db.Model):
"""Contract documents for players to sign."""
@@ -48,8 +49,8 @@ class Contract(db.Model):
return True
from app.models.user_model.admin import Admin
from app.models.user_model.manager import Manager
from app.models.user_model.coach import Coach
from app.models.user_model.manager import Manager
from app.models.user_model.user import User
from app.permissions import coach_can_access_player
+2 -1
View File
@@ -1,8 +1,9 @@
"""Player evaluation record."""
from app.extensions import db
from datetime import datetime
from app.extensions import db
class Evaluation(db.Model):
"""Player evaluation record."""
+2 -1
View File
@@ -1,8 +1,9 @@
"""Abstract base class for match models (Match + TeamMatch)."""
from app.extensions import db
from datetime import datetime
from app.extensions import db
class BaseMatch(db.Model):
"""Shared schema for tryout-scoped matches and regular-season team matches."""
+2 -1
View File
@@ -1,8 +1,9 @@
"""Request from player to coach for a One on One session."""
from app.extensions import db
from datetime import datetime
from app.extensions import db
class OneOnOneRequest(db.Model):
"""Request from player to coach for a One on One session."""
+2 -1
View File
@@ -1,8 +1,9 @@
"""Persistent organisation team (e.g. Varsity, JV)."""
from datetime import datetime
from app.extensions import db
from app.models._associations import org_team_coaches, org_team_managers
from datetime import datetime
class OrgTeam(db.Model):
+2 -1
View File
@@ -1,8 +1,9 @@
"""Many-to-many junction: player to org-team."""
from app.extensions import db
from datetime import datetime
from app.extensions import db
class TeamPlayer(db.Model):
"""Many-to-many: player to org-team."""
+2 -1
View File
@@ -1,8 +1,9 @@
"""Abstract base class for match participant models."""
from app.extensions import db
from datetime import datetime
from app.extensions import db
class BaseParticipant(db.Model):
"""Shared schema for match participants."""
+2 -1
View File
@@ -1,8 +1,9 @@
"""Personal notes from coach to individual player."""
from app.extensions import db
from datetime import datetime
from app.extensions import db
class PersonalNote(db.Model):
"""Personal notes from coach to individual player."""
+2 -1
View File
@@ -1,8 +1,9 @@
"""Tryout-specific team (e.g. Alpha, Bravo within a single tryout)."""
from app.extensions import db
from datetime import datetime
from app.extensions import db
class Team(db.Model):
"""Tryout-specific team (e.g. Alpha, Bravo within a single tryout)."""
+2 -1
View File
@@ -1,8 +1,9 @@
"""Link between a player and a tryout-specific team."""
from app.extensions import db
from datetime import datetime
from app.extensions import db
class TeamMember(db.Model):
"""Link between a player and a tryout-specific team."""
+2 -1
View File
@@ -1,8 +1,9 @@
"""Team improvement notes from coach."""
from app.extensions import db
from datetime import datetime
from app.extensions import db
class TeamNote(db.Model):
"""Team improvement notes from coach."""
+2 -1
View File
@@ -1,8 +1,9 @@
"""Tryout event for player evaluations and team formation."""
from datetime import datetime
from app.extensions import db
from app.models._associations import tryout_coaches
from datetime import datetime
class Tryout(db.Model):
+2 -1
View File
@@ -1,8 +1,9 @@
"""Registration linking a player to a tryout."""
from app.extensions import db
from datetime import datetime
from app.extensions import db
class TryoutRegistration(db.Model):
"""Registration linking a player to a tryout."""
+3 -2
View File
@@ -1,9 +1,10 @@
"""Store gamertag per game for each user."""
from app.extensions import db
from app.models._constants import TRN_URLS, PLATFORM_CODES, PLATFORM_DEFAULTS
from urllib.parse import quote
from app.extensions import db
from app.models._constants import PLATFORM_CODES, PLATFORM_DEFAULTS, TRN_URLS
class UserGamertag(db.Model):
"""Store gamertag per game for each user."""
+2 -2
View File
@@ -1,10 +1,10 @@
"""User hierarchy — single-table polymorphic inheritance (User → Admin, Manager, Coach, Player, Scout)."""
from app.models.user_model.user import User
from app.models.user_model.admin import Admin
from app.models.user_model.manager import Manager
from app.models.user_model.coach import Coach
from app.models.user_model.manager import Manager
from app.models.user_model.player import Player
from app.models.user_model.scout import Scout
from app.models.user_model.user import User
__all__ = ['User', 'Admin', 'Manager', 'Coach', 'Player', 'Scout']
+2 -1
View File
@@ -27,9 +27,10 @@ class Manager(User):
return True
def get_visible_tryouts(self):
from app.models.tryout.tryout import Tryout
from sqlalchemy import or_
from app.models.tryout.tryout import Tryout
return (
Tryout.query.filter(or_(Tryout.created_by == self.id, Tryout.manager_id == self.id))
.order_by(Tryout.date)
+1 -1
View File
@@ -9,9 +9,9 @@ class Player(User):
__mapper_args__ = {'polymorphic_identity': 'player'}
def get_visible_tryouts(self):
from app.models.tryout.tryout import Tryout
from app.models.match_model.match import Match
from app.models.participant.match_participant import MatchParticipant
from app.models.tryout.tryout import Tryout
# tryouts they registered for
player_tryout_ids = [r.tryout_id for r in self.tryout_registrations.all()]
+4 -2
View File
@@ -1,9 +1,11 @@
"""Base User model — shared fields and polymorphic configuration."""
from app.extensions import db
from flask_login import UserMixin
from datetime import datetime
from flask_login import UserMixin
from app.extensions import db
class User(UserMixin, db.Model):
"""Base user model — shared fields for every role.
-1
View File
@@ -28,7 +28,6 @@ and from tests without a request context.
from app.extensions import db
# ---------------------------------------------------------------------------
# Team attachment
# ---------------------------------------------------------------------------
+12 -10
View File
@@ -5,21 +5,23 @@ protection, logout with session clearing, and new user registration with
password policy enforcement and CAPTCHA verification.
"""
import uuid
import os
import secrets
import uuid
from datetime import datetime, timedelta
from flask import Blueprint, render_template, redirect, url_for, flash, request, session
from flask_login import login_user, logout_user, login_required, current_user
from app.extensions import db, hash_password, check_password, limiter
from app.models import User, Player, ESPORT_GAMES
from app.validators import RegisterSchema, LoginSchema
from urllib.parse import urlencode, urlparse
import requests
from flask import Blueprint, flash, redirect, render_template, request, session, url_for
from flask_babel import gettext as _
from flask_login import current_user, login_required, login_user, logout_user
from marshmallow import ValidationError
from app.extensions import check_password, db, hash_password, limiter
from app.i18n import LOCALE_SESSION_KEY
from app.logging_config import log_auth_event
from flask_babel import gettext as _
from marshmallow import ValidationError
from urllib.parse import urlparse, urlencode
import requests
from app.models import ESPORT_GAMES, Player, User
from app.validators import LoginSchema, RegisterSchema
#: Session key holding the pending OAuth2 anti-forgery token.
DISCORD_STATE_KEY = 'discord_oauth_state'
+13 -12
View File
@@ -3,22 +3,23 @@
Uses polymorphic isinstance checks instead of role-string comparisons.
"""
from flask import Blueprint, render_template, redirect, url_for, flash, request
from flask_login import login_required, current_user
from flask import Blueprint, flash, redirect, render_template, request, url_for
from flask_babel import gettext as _
from app.extensions import db
from app.models import (
Admin,
Player,
User,
Tryout,
Evaluation,
TryoutRegistration,
GAME_POSITIONS,
)
from flask_login import current_user, login_required
from sqlalchemy import func
from sqlalchemy.orm import aliased
from app.extensions import db
from app.models import (
GAME_POSITIONS,
Admin,
Evaluation,
Player,
Tryout,
TryoutRegistration,
User,
)
evaluations_bp = Blueprint('evaluations', __name__, url_prefix='/evaluations')
+13 -11
View File
@@ -3,27 +3,29 @@
Uses polymorphic isinstance checks instead of role-string comparisons.
"""
from flask import Blueprint, render_template, redirect, url_for, flash, request
from flask_login import login_required, current_user
from datetime import date
from flask import Blueprint, flash, redirect, render_template, request, url_for
from flask_babel import gettext as _
from flask_login import current_user, login_required
from sqlalchemy import func
from app.extensions import db
from app.models import (
Admin,
Manager,
Coach,
Player,
Scout,
User,
Tryout,
Evaluation,
TryoutRegistration,
TeamMember,
Manager,
Match,
MatchParticipant,
Player,
Scout,
TeamMember,
Tryout,
TryoutRegistration,
User,
)
from app.permissions import coach_tryout_ids
from sqlalchemy import func
from datetime import date
main_bp = Blueprint('main', __name__)
+15 -14
View File
@@ -3,30 +3,31 @@
Uses polymorphic isinstance checks instead of role-string comparisons.
"""
from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify
from flask_login import login_required, current_user
from datetime import datetime, timedelta
from flask import Blueprint, flash, jsonify, redirect, render_template, request, url_for
from flask_babel import gettext as _
from flask_login import current_user, login_required
from sqlalchemy.orm import joinedload
from app.extensions import db
from app.models import (
Admin,
Manager,
Coach,
Player,
Scout,
User,
Tryout,
Manager,
Match,
MatchParticipant,
Team,
TeamMember,
TryoutRegistration,
PlayerDisponibility,
OneOnOneRequest,
PersonalNote,
Player,
PlayerDisponibility,
Scout,
Team,
TeamMember,
Tryout,
TryoutRegistration,
User,
)
from datetime import datetime, timedelta
from sqlalchemy.orm import joinedload
from app.services.scheduling import notify_participants, zip_participants
matches_bp = Blueprint('matches', __name__, url_prefix='/matches')
+7 -5
View File
@@ -3,22 +3,24 @@
Uses polymorphic isinstance checks instead of role-string comparisons.
"""
from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify
from flask_login import login_required, current_user
from datetime import datetime, timedelta
from flask import Blueprint, flash, jsonify, redirect, render_template, request, url_for
from flask_babel import gettext as _
from flask_login import current_user, login_required
from app.extensions import db
from app.models import (
Admin,
Manager,
Coach,
Player,
Manager,
OrgTeam,
Player,
TeamMatch,
TeamMatchParticipant,
TeamPlayer,
)
from app.permissions import can_manage_org_team, coach_org_teams, visible_org_teams
from datetime import datetime, timedelta
from app.services.scheduling import notify_participants, zip_participants
team_matches_bp = Blueprint('team_matches', __name__, url_prefix='/team-matches')
+14 -12
View File
@@ -3,27 +3,29 @@
Uses polymorphic isinstance checks instead of role-string comparisons.
"""
from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify
from flask_login import login_required, current_user
from datetime import datetime
from flask import Blueprint, flash, jsonify, redirect, render_template, request, url_for
from flask_babel import gettext as _
from flask_login import current_user, login_required
from app.extensions import db
from app.models import (
Admin,
Manager,
Coach,
Player,
OrgTeam,
User,
PersonalNote,
TeamNote,
Tryout,
TeamPlayer,
TeamMatch,
Contract,
Manager,
OneOnOneRequest,
OrgTeam,
PersonalNote,
Player,
TeamMatch,
TeamNote,
TeamPlayer,
Tryout,
User,
)
from app.permissions import visible_org_teams
from datetime import datetime
teams_bp = Blueprint('teams', __name__, url_prefix='/teams')
+20 -18
View File
@@ -4,30 +4,32 @@ This module handles CRUD operations for tryouts and player registrations.
Uses polymorphic isinstance checks instead of role-string comparisons.
"""
from flask import Blueprint, render_template, redirect, url_for, flash, request, abort
from flask_login import login_required, current_user
from datetime import datetime
from flask import Blueprint, abort, flash, redirect, render_template, request, url_for
from flask_babel import gettext as _
from flask_login import current_user, login_required
from app.extensions import db
from app.models import (
Admin,
Manager,
Coach,
Player,
Scout,
User,
Tryout,
TryoutRegistration,
Evaluation,
Team,
TeamMember,
OrgTeam,
Match,
MatchParticipant,
PersonalNote,
ESPORT_GAMES,
GAME_POSITIONS,
Admin,
Coach,
Evaluation,
Manager,
Match,
MatchParticipant,
OrgTeam,
PersonalNote,
Player,
Scout,
Team,
TeamMember,
Tryout,
TryoutRegistration,
User,
)
from datetime import datetime
tryouts_bp = Blueprint('tryouts', __name__, url_prefix='/tryouts')
+9 -8
View File
@@ -9,16 +9,16 @@ keeps its single `from app.routes.users import users_bp`. The blueprint
itself lives in blueprint.py to keep that import one-directional.
"""
from app.routes.users.blueprint import users_bp
# Imported for their side effect: each module attaches its routes to
# users_bp. Order does not matter; none of them import each other.
from app.routes.users import accounts # noqa: F401,E402
from app.routes.users import availability # noqa: F401,E402
from app.routes.users import contracts # noqa: F401,E402
from app.routes.users import notes # noqa: F401,E402
from app.routes.users import one_on_one # noqa: F401,E402
from app.routes.users import profile # noqa: F401,E402
from app.routes.users import (
accounts, # noqa: F401,E402
availability, # noqa: F401,E402
contracts, # noqa: F401,E402
notes, # noqa: F401,E402
one_on_one, # noqa: F401,E402
profile, # noqa: F401,E402
)
# Re-exported because tests and other modules reach for them by name.
from app.routes.users._shared import ( # noqa: F401,E402
@@ -26,6 +26,7 @@ from app.routes.users._shared import ( # noqa: F401,E402
ALLOWED_SIGNED_EXTENSIONS,
pdf_upload_error,
)
from app.routes.users.blueprint import users_bp
__all__ = [
'ALLOWED_CONTRACT_EXTENSIONS',
+1 -1
View File
@@ -8,7 +8,7 @@ from flask import flash, request
from flask_babel import gettext as _
from app.extensions import db
from app.models import Admin, Coach, Manager, Player, Scout, GAME_PLATFORMS, UserGamertag
from app.models import GAME_PLATFORMS, Admin, Coach, Manager, Player, Scout, UserGamertag
ALLOWED_CONTRACT_EXTENSIONS = {'pdf'}
ALLOWED_SIGNED_EXTENSIONS = {'pdf'}
+3 -3
View File
@@ -12,12 +12,13 @@ from marshmallow import ValidationError
from app.extensions import db, hash_password
from app.logging_config import log_auth_event
from app.models import (
ESPORT_GAMES,
GAME_PLATFORMS,
USER_TYPES,
Admin,
CoachAvailability,
Contract,
ESPORT_GAMES,
Evaluation,
GAME_PLATFORMS,
Match,
MatchParticipant,
OneOnOneRequest,
@@ -31,7 +32,6 @@ from app.models import (
TeamPlayer,
Tryout,
TryoutRegistration,
USER_TYPES,
User,
UserGamertag,
)
-1
View File
@@ -15,7 +15,6 @@ from app.extensions import db
from app.models import Coach, CoachAvailability, PlayerDisponibility, User
from app.routes.users.blueprint import users_bp
DAY_NAMES = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
+2 -1
View File
@@ -119,7 +119,8 @@ def one_on_one():
return redirect(url_for('users.one_on_one'))
# Build list of upcoming dates that have coach availability
from datetime import date as date_cls, timedelta as td
from datetime import date as date_cls
from datetime import timedelta as td
today = date_cls.today()
available_days = {av['day_of_week'] for av in coach_availability}
+3 -3
View File
@@ -8,11 +8,11 @@ from marshmallow import ValidationError
from app.extensions import db, hash_password
from app.logging_config import log_auth_event
from app.models import (
CoachAvailability,
Coach,
Contract,
ESPORT_GAMES,
GAME_PLATFORMS,
Coach,
CoachAvailability,
Contract,
Player,
User,
)
+3 -1
View File
@@ -13,10 +13,12 @@ Accept the self-signed certificate warning in your browser to proceed.
import os
import socket
import subprocess
import ssl
import subprocess
import sys
from waitress.server import create_server
from app.app import create_app
CERT_FILE = 'certs/localhost.pem'
+4 -4
View File
@@ -12,12 +12,12 @@ Usage:
python security_scan.py [--url http://localhost:5000]
"""
import os
import sys
import json
import subprocess
import urllib.request
import os
import ssl
import subprocess
import sys
import urllib.request
from datetime import datetime
+8 -7
View File
@@ -11,18 +11,19 @@ Usage:
"""
import re
from flask_babel import lazy_gettext as _l
from marshmallow import (
Schema,
fields,
validate,
ValidationError,
pre_load,
validates_schema,
EXCLUDE,
Schema,
ValidationError,
fields,
pre_load,
validate,
validates_schema,
)
from app.models import USER_TYPES
from app.models import USER_TYPES
# =============================================================================
# Custom Validators