Noir::PythonRouteExtractor
Pure parsing helpers for Python framework route idioms.
Framework adapters (Flask, Sanic, …) iterate source files and call
these helpers per line. The extractor has no file I/O, no Analyzer
dependency, and no framework-specific state — it just recognizes
the three most common Python route-related idioms so adapters stop
duplicating the regexes:
@<var>.route("/path", methods=[...])@<var>.<method>("/path")# method in {get, post, …}<var> = Blueprint(url_prefix="…")
Plus a helper to locate the def/class that a decorator applies to.
This is the Python analogue of js_route_extractor.cr / go_route_extractor.cr.
Framework-specific behaviour (flask_restx, Sanic's class views, cross-file
register_blueprint, etc.) stays in the adapters.
Constants
query (RFC 10008) recognizes @<var>.query("/path") shortcut
decorators (Flask/Werkzeug shipped this; other decorator-based
frameworks fall through harmlessly if they never define it).
Instance methods
Locate the def/async def/class that a decorator applies to.
direction: :down walks forward past additional decorators and blank
lines, stopping at the first non-decorator line (the one we want, or
something that breaks the decorator chain). direction: :up walks
backward, used when the decorator sits on a method whose enclosing
class was found elsewhere.
Returns the index of the def/class line, or the original line_index
when nothing matches.
Detect a <name> = (module.)?Blueprint(url_prefix="...") assignment.
Returns {name, prefix} if matched, nil otherwise.
module_names is the list of optional module prefixes a framework
allows — Flask accepts flask.Blueprint, Sanic accepts sanic.Blueprint,
or a bare Blueprint after an import.
original_line is used to read url_prefix, so if the caller
space-stripped line, spaces inside the prefix value still survive.
Scan one line for @<var>.route(...) and @<var>.<method>(...) and
return every decorator found. Typically 0 or 1 per line.
original_line defaults to line. Callers that have space-stripped
line for regex-matching convenience should pass the original here
so paths that contain spaces survive (Flask does this; Sanic doesn't
need to because its fixtures never have space-bearing paths).