homedocs/scripts/check_routes.py
2025-03-30 23:42:24 +02:00

118 lines
3.9 KiB
Python
Executable file

#!/usr/bin/env python3
"""
Check for unused routes in Flask application
"""
import os
import sys
import re
from flask import Flask
# Add the parent directory to sys.path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
def find_all_routes():
"""Find all route definitions in Python files"""
routes = []
route_pattern = re.compile(r'@\w+\.route\([\'"]([^\'"]+)[\'"]')
for root, _, files in os.walk("app"):
for file in files:
if file.endswith(".py"):
file_path = os.path.join(root, file)
with open(file_path, "r") as f:
content = f.read()
matches = route_pattern.findall(content)
for match in matches:
routes.append(match)
return routes
def find_template_references():
"""Find all url_for calls in template files"""
references = []
url_for_pattern = re.compile(r'url_for\([\'"]([^\'"]+)[\'"]')
# Add patterns for direct links and HTMX references
direct_href_pattern = re.compile(r'href=[\'"]([^\'"]+)[\'"]')
htmx_pattern = re.compile(r'hx-(get|post|put|delete)=[\'"]([^\'"]+)[\'"]')
# Template files scanning
for root, _, files in os.walk("app/templates"):
for file in files:
if file.endswith(".html"):
file_path = os.path.join(root, file)
with open(file_path, "r") as f:
content = f.read()
# Find url_for references
matches = url_for_pattern.findall(content)
for match in matches:
references.append(match)
# Also check for direct route references in hrefs that aren't url_for
href_matches = direct_href_pattern.findall(content)
for href in href_matches:
if href.startswith("/") and not href.startswith("//"):
references.append(href)
# Check HTMX references
htmx_matches = htmx_pattern.findall(content)
for _, url in htmx_matches:
if url.startswith("/") and not url.startswith("//"):
references.append(url)
# Also check Python files for url_for calls
for root, _, files in os.walk("app"):
for file in files:
if file.endswith(".py"):
file_path = os.path.join(root, file)
with open(file_path, "r") as f:
content = f.read()
matches = url_for_pattern.findall(content)
for match in matches:
references.append(match)
return references
def check_unused_routes():
"""Find routes that are not referenced by url_for"""
from app import create_app
app = create_app()
# Get all route endpoints from the app
all_endpoints = set()
for rule in app.url_map.iter_rules():
all_endpoints.add(rule.endpoint)
# Get all url_for references
all_references = set(find_template_references())
# Find unused endpoints
unused_endpoints = all_endpoints - all_references
if unused_endpoints:
print(
"The following routes are defined but not referenced in templates or code:"
)
for endpoint in sorted(unused_endpoints):
# Skip static routes, error handlers, etc.
if endpoint.startswith("static") or endpoint == "static":
continue
print(f" - {endpoint}")
# Find the URL for this endpoint
for rule in app.url_map.iter_rules():
if rule.endpoint == endpoint:
print(f" URL: {rule}")
break
else:
print("All routes are referenced in templates or code. Good job!")
if __name__ == "__main__":
check_unused_routes()