module Noir::PythonRouteExtractor

Overview

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:

  1. @<var>.route("/path", methods=[...])
  2. @<var>.<method>("/path") # method in {get, post, …}
  3. <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.

Extended Modules

Defined in:

miniparsers/python_route_extractor.cr

Constant Summary

HTTP_METHODS = ["get", "post", "put", "patch", "delete", "head", "options", "trace"] of ::String
PYTHON_VAR_NAME = /[a-zA-Z_][a-zA-Z0-9_]*/

Instance Method Summary

Instance Method Detail

def find_def_line(lines : Array(String), line_index : Int32, direction : Symbol = :down) : Int32 #

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.


[View source]
def scan_blueprint(line : String, module_names : Array(String), original_line : String | Nil = nil) : Tuple(String, String) | Nil #

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.


[View source]
def scan_decorators(line : String, original_line : String | Nil = nil) : Array(Decoration) #

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).


[View source]