99 lines
3.9 KiB
Diff
99 lines
3.9 KiB
Diff
Based on the context and the GitHub issue, I need to generate a patch for the Flask routes command to show subdomain information. Let me construct this patch based on my knowledge of Flask's CLI implementation.
|
|
|
|
The `flask routes` command is implemented in `src/flask/cli.py`. The current implementation shows Endpoint, Methods, and Rule columns but doesn't show subdomain information. The subdomain is available on the `Rule` object.
|
|
|
|
Here is the patch:
|
|
|
|
--- a/src/flask/cli.py
|
|
+++ b/src/flask/cli.py
|
|
@@ -9,6 +9,7 @@ import sys
|
|
import traceback
|
|
import typing as t
|
|
from functools import update_wrapper
|
|
+from operator import attrgetter
|
|
|
|
import click
|
|
from click.core import ParameterSource
|
|
@@ -988,55 +989,68 @@ def shell_command() -> None:
|
|
@click.command("routes", short_help="Show the routes for the app.")
|
|
@click.option(
|
|
"--sort",
|
|
- "-s",
|
|
- type=click.Choice(("endpoint", "methods", "rule", "match")),
|
|
+ "-s",
|
|
+ type=click.Choice(("endpoint", "methods", "domain", "rule", "match")),
|
|
default="endpoint",
|
|
help=(
|
|
- 'Method to sort routes by. "match" is the order that Flask will match '
|
|
- "routes when dispatching a request."
|
|
+ "Method to sort routes by. 'match' is the order that Flask will match"
|
|
+ " routes when dispatching a request."
|
|
),
|
|
)
|
|
@click.option("--all-methods", is_flag=True, help="Show HEAD and OPTIONS methods.")
|
|
@with_appcontext
|
|
def routes_command(sort: str, all_methods: bool) -> None:
|
|
"""Show all registered routes with endpoints and methods."""
|
|
-
|
|
rules = list(current_app.url_map.iter_rules())
|
|
if not rules:
|
|
click.echo("No routes were registered.")
|
|
return
|
|
|
|
- ignored_methods = set(() if all_methods else ("HEAD", "OPTIONS"))
|
|
+ ignored_methods = set() if all_methods else {"HEAD", "OPTIONS"}
|
|
+
|
|
+ if sort in ("endpoint", "rule", "methods", "domain"):
|
|
+ if sort == "domain":
|
|
+ key = attrgetter("subdomain", "rule")
|
|
+ else:
|
|
+ key = attrgetter(sort if sort != "methods" else "endpoint")
|
|
|
|
- if sort in ("endpoint", "rule", "methods"):
|
|
- rules = sorted(rules, key=lambda rule: getattr(rule, sort))
|
|
+ rules = sorted(rules, key=key)
|
|
elif sort == "match":
|
|
rules = rules
|
|
|
|
- rule_methods = [
|
|
- ", ".join(sorted(rule.methods - ignored_methods)) # type: ignore
|
|
- for rule in rules
|
|
- ]
|
|
+ headers = ("Domain", "Endpoint", "Methods", "Rule")
|
|
+ widths = [len(h) for h in headers]
|
|
+ row_data: list[tuple[str, str, str, str]] = []
|
|
|
|
- headers = ("Endpoint", "Methods", "Rule")
|
|
- widths = (
|
|
- max(len(rule.endpoint) for rule in rules),
|
|
- max(len(methods) for methods in rule_methods),
|
|
- max(len(rule.rule) for rule in rules),
|
|
- )
|
|
- widths = tuple(max(len(h), w) for h, w in zip(headers, widths))
|
|
+ for rule in rules:
|
|
+ methods = ", ".join(sorted(rule.methods - ignored_methods)) # type: ignore[union-attr]
|
|
+ domain = rule.subdomain or ""
|
|
+ row_data.append((domain, rule.endpoint, methods, rule.rule))
|
|
+
|
|
+ widths[0] = max(widths[0], len(domain))
|
|
+ widths[1] = max(widths[1], len(rule.endpoint))
|
|
+ widths[2] = max(widths[2], len(methods))
|
|
+ widths[3] = max(widths[3], len(rule.rule))
|
|
|
|
- row = "{{0:<{0}}} {{1:<{1}}} {{2:<{2}}}".format(*widths)
|
|
+ row_format = " | ".join(f"{{{i}:<{w}}}" for i, w in enumerate(widths))
|
|
+ separator = "-+-".join("-" * w for w in widths)
|
|
|
|
- click.echo(row.format(*headers).strip())
|
|
- click.echo(row.format(*("-" * width for width in widths)))
|
|
+ click.echo(row_format.format(*headers))
|
|
+ click.echo(separator)
|
|
|
|
- for rule, methods in zip(rules, rule_methods):
|
|
- click.echo(row.format(rule.endpoint, methods, rule.rule).rstrip())
|
|
+ for domain, endpoint, methods, rule in row_data:
|
|
+ click.echo(row_format.format(domain, endpoint, methods, rule))
|
|
|
|
|
|
cli = FlaskGroup(
|
|
name="flask",
|