class

Analyzer::Python::Django

Inherits Analyzer::Python::PythonEngine < Analyzer < FileHelper < Reference < Object

Constants

DECORATOR_METHOD_NAME_REGEXES = HTTP_METHODS_EXCLUDING_QUERY.to_h do |m| {m, /[^a-zA-Z0-9](#{m})[^a-zA-Z0-9]/} end

HTTP_METHODS is a fixed table (from PythonEngine), so the decorator-stack scan and the request.method == "..." scan below (each an .each loop run per decorator line / per function-body line) can look up a precompiled regex per method name instead of interpolating and recompiling one on every iteration. Purely a lookup-table hoist — the matched text/capture groups are unchanged, so it doesn't affect the line/offset values computed elsewhere in this file.

DECORATOR_METHOD_NAME_REGEXES also uses HTTP_METHODS_EXCLUDING_QUERY, for the OTHER reason that constant documents: it bare-word-matches a method name anywhere in a decorator's text (this scan is not CBV- specific — it runs over the decorator stack above a plain function too), and real decorators (e.g. DRF-spectacular's OpenApiParameter("query", ...)) commonly carry query as a parameter name rather than a verb restriction. REQUEST_METHOD_NAME_REGEXES keeps the full list: it only fires on an explicit, quoted request.method == "QUERY" comparison, which is unambiguous developer-written evidence, not a name collision.

REGEX_CBV_METHOD_DEF = /\s+(?:async\s+)?def\s+(#{HTTP_METHODS_EXCLUDING_QUERY.join("|")})\s*\(/

def get(...) / async def post(...) method heads in class-based views. Precompiled — an interpolated literal would be recompiled on every line of every CBV class body. Uses HTTP_METHODS_EXCLUDING_QUERY (see PythonEngine): Django's CBV dispatch (View.dispatch) looks up request.method.lower() against the class's http_method_names allowlist, which does not include query upstream — unlike Flask's duck-typed getattr(self, request.method.lower()) dispatch, a def query(self): method is genuinely inert unless a view manually widens that allowlist, so matching it here would report a phantom route.

REGEX_INCLUDE_URLS = /\binclude\s*\(\s*r?['"]([^'"\\]*)['"]/
REGEX_ROOT_URLCONF = /\s*ROOT_URLCONF\s*=\s*r?['"]([^'"\\]*)['"]/

Regular expressions for extracting Django URL configurations

REQUEST_METHOD_NAME_REGEXES = HTTP_METHODS.to_h do |m| {m, /['"](#{m})['"]/} end
REQUEST_PARAM_FIELD_MAP = {"GET" => {["GET"], "query"}, "POST" => {["POST"], "form"}, "COOKIES" => {nil, "cookie"}, "META" => {nil, "header"}, "data" => {["POST", "PUT", "PATCH"], "form"}, "query_params" => {nil, "query"}}

Map request parameters to their respective fields

REQUEST_PARAM_FIELD_PATTERNS = REQUEST_PARAM_FIELD_MAP.map do |field_name, tuple| {field_name, tuple[0], tuple[1], Regex.new("request\\.#{field_name}\\[[rf]?['\"]([^'\"]*)['\"]\\]"), Regex.new("request\\.#{field_name}\\.get(?:list)?\\([rf]?['\"]([^'\"]*)['\"]")} end

Precompiled per-field access patterns so extract_params_from_line never rebuilds a PCRE2 regex per request field. Compiled once from REQUEST_PARAM_FIELD_MAP. {field_name, field_methods, param_type, bracket_re, get_re}

REQUEST_PARAM_TYPE_MAP = {"query" => nil, "form" => ["POST", "PUT", "PATCH"], "cookie" => nil, "header" => nil}

Map request parameter types to HTTP methods

Class methods

tech_name
Source

Instance methods

analyze
Source
extract_endpoints(django_urls : DjangoUrls) : Array(Endpoint)

Extract endpoints from a Django URL configuration file

Source
extract_endpoints_from_file(url : String, filepath : String, function_or_class_name : String)

Extract endpoints from a given file

Source
extract_params_from_line(line : String, endpoint_methods : Array(String))

Extract parameters from a line of code

Source
filter_params(method : String, params : Array(Param))

Filter parameters based on HTTP method

Source
find_root_django_urls

Find all root Django URLs

Source
tech

Instance-side view of the same declaration. The per-file rescues live on this base class, which has no way to name the analyzer that is running inside them, so a skipped file could not be attributed to a tech. Deriving it from analyzer_for keeps the name written exactly once.

Source

Nested types