From e9a074ebfc69757bca931dbe42c93f911d489a5e Mon Sep 17 00:00:00 2001 From: mkh-user Date: Wed, 10 Jun 2026 08:45:31 +0330 Subject: [PATCH] style(dashboard): Improve code quality and fix warnings Code quality improve for dashboard: - Add '_' prefix to unused arguments - Rename shadowed names (internals) - Mark unused 'app.run(debug)' as TODO (follow-up) - Improve grammar in docs - Convert simple functions to static methods - Cleanup sorting logic and clarify its real behavior --- fenn/dashboard/app.py | 9 +++++---- fenn/dashboard/auth.py | 2 +- fenn/dashboard/scanner.py | 35 +++++++++++++++++++---------------- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/fenn/dashboard/app.py b/fenn/dashboard/app.py index e3208ae..9bd9340 100644 --- a/fenn/dashboard/app.py +++ b/fenn/dashboard/app.py @@ -126,7 +126,7 @@ def _require_login(): @app.errorhandler(CSRFError) -def _csrf_failed(e): +def _csrf_failed(_e): return render_template( "connect.html", error_message="Form expired. Please try again.", @@ -233,7 +233,7 @@ def api_sessions(): default 0), sort (field, optionally ``-`` prefixed for descending). """ try: - project = request.args.get("project") or None + project_name = request.args.get("project") or None status = request.args.get("status") or None sort = request.args.get("sort") or "-started" limit = _parse_int_arg( @@ -243,7 +243,7 @@ def api_sessions(): try: result = scanner.list_sessions( - project=project, + project=project_name, status=status, limit=limit, offset=offset, @@ -262,7 +262,7 @@ def api_sessions(): @app.errorhandler(404) -def not_found(e): +def not_found(_e): return render_template("404.html", **scanner.get_overview()), 404 @@ -332,6 +332,7 @@ def logout(): # --------------------------------------------------------------------------- # +# TODO: Use 'debug' in logger def run( host: str = "127.0.0.1", port: int = 5000, debug: bool = False, log_dirs=None ) -> None: diff --git a/fenn/dashboard/auth.py b/fenn/dashboard/auth.py index 87640b8..1511cca 100644 --- a/fenn/dashboard/auth.py +++ b/fenn/dashboard/auth.py @@ -3,7 +3,7 @@ The dashboard is a localhost-only Flask app. To authenticate, the user generates a "dashboard token" on pyfenn.com, pastes it into the ``/connect`` page, and the server validates it once against -``https://pyfenn.com/api/dashboard/me``. On success we store +``https://pyfenn.com/api/dashboard/me``. On success, we store ``{user_id, email}`` in a signed Flask session cookie and discard the token — it is never written to disk or kept in memory. """ diff --git a/fenn/dashboard/scanner.py b/fenn/dashboard/scanner.py index 5db488b..606b8b6 100644 --- a/fenn/dashboard/scanner.py +++ b/fenn/dashboard/scanner.py @@ -4,7 +4,7 @@ import time from pathlib import Path from typing import Any, Dict, List, Optional, Tuple -from xml.etree import ElementTree as ET +from xml.etree import ElementTree # Default directories to scan (resolved at runtime) _DEFAULT_DIRS = [ @@ -106,7 +106,7 @@ def find_fn_files(self) -> List[Path]: if f not in seen: seen.add(f) unique.append(f) - ordered = sorted(unique, key=lambda f: f.stat().st_mtime, reverse=True) + ordered = sorted(unique, key=lambda path: path.stat().st_mtime, reverse=True) self._files_cache = (now, ordered) return ordered @@ -137,25 +137,23 @@ def parse_fn_file(self, path: Path) -> Optional[Dict[str, Any]]: self._parse_cache[key] = (mtime, parsed) return self._refresh_running_status(parsed, mtime) - def _parse_uncached( - self, path: Path, stat: os.stat_result - ) -> Optional[Dict[str, Any]]: + @staticmethod + def _parse_uncached(path: Path, stat: os.stat_result) -> Optional[Dict[str, Any]]: try: content = path.read_text(encoding="utf-8") except (OSError, PermissionError): return None - root = None status = "completed" try: - root = ET.fromstring(content) - except ET.ParseError: + root = ElementTree.fromstring(content) + except ElementTree.ParseError: # Session may still be running — try appending the closing tag try: - root = ET.fromstring(content + "\n") + root = ElementTree.fromstring(content + "\n") status = "running" - except ET.ParseError: + except ElementTree.ParseError: return None # Override status from if present @@ -261,7 +259,9 @@ def _build_projects_list(sessions: List[Dict[str, Any]]) -> List[Dict[str, Any]] p["running_count"] += 1 elif s["status"] == "crashed": p["crashed_count"] += 1 - return sorted(projects.values(), key=lambda p: p["last_active"], reverse=True) + return sorted( + projects.values(), key=lambda project: project["last_active"], reverse=True + ) def get_overview(self) -> Dict[str, Any]: """Aggregate stats for the dashboard home page.""" @@ -360,11 +360,12 @@ def list_sessions( if status: sessions = [s for s in sessions if s["status"] == status] - # Sentinel keeps None values consistently last (asc) / first (desc) - # without crashing the comparison on mixed types. + # Sorts None values last (ascending) / first (descending) without comparing None to + # non-None values, but may raise TypeError if non-None values are of different types + # (e.g., int vs str). def sort_key(s: Dict[str, Any]): v = s.get(field) - return (v is None, v if v is not None else "") + return v is None, v sessions.sort(key=sort_key, reverse=descending) @@ -380,7 +381,8 @@ def sort_key(s: Dict[str, Any]): "offset": offset, } - def format_duration(self, seconds: Optional[int]) -> str: + @staticmethod + def format_duration(seconds: Optional[int]) -> str: if seconds is None: return "—" if seconds < 60: @@ -391,7 +393,8 @@ def format_duration(self, seconds: Optional[int]) -> str: m = (seconds % 3600) // 60 return f"{h}h {m}m" - def format_size(self, size_bytes: int) -> str: + @staticmethod + def format_size(size_bytes: int) -> str: if size_bytes < 1024: return f"{size_bytes} B" if size_bytes < 1024 * 1024: