Analyzer::Python::Cli
Inherits CliEndpointSupport < Analyzer::Python::PythonEngine < Analyzer < FileHelper < Reference < Object
Surfaces the command-line attack surface of Python programs as cli://
endpoints: one endpoint per (sub)command, with named options
(param_type "flag"), positional arguments ("argument"), and consumed
environment variables ("env"). Covers stdlib argparse / getopt /
sys.argv plus click, typer, fire, docopt, Abseil (absl-py) flags, and
Cleo commands.
Line-scan analyzer (the house style for non-tree-sitter Python adapters, e.g. bottle). Endpoints are merged by URL so options registered across decorators/functions collect onto a single command.
Constants
Abseil (absl-py): flags.DEFINE_* calls register a single flat flag namespace consumed via FLAGS.<name> after app.run(main) — there is no subcommand concept, so every flag attaches to the binary's root URL.
argparse
^ in Crystal/PCRE without the multiline flag anchors to the start of
the whole subject, not each line — fine for the per-line line.match
use in scan_cleo below, but a separate (?:^|\n)-anchored variant is
needed to test this against the full multi-line file content. Both
variants are column-0 anchored (no \s* before class) so the
entrypoint gate below matches exactly what scan_cleo can extract — a
class Foo(Command) nested inside a function/method (indented) is
never resolved by scan_cleo, so it must not satisfy the gate either,
or the file gets treated as a CLI entrypoint with no real command found
(scan_stdlib then fires unconditionally on an unrelated env/argv read).
Cleo: a Command subclass declares its subcommand name as a class attribute, then reads its own arguments/options back out by name inside its methods (self.argument("x") / self.option("y")) — that readback call is also the most reliable textual anchor for the option/argument name itself.
The seven literal markers below were seven separate Rabin-Karp
passes over the whole file, run for every .py in the tree. One
precompiled union is the same predicate in a single pass. The
remaining tests go through content_matches? so PCRE2 skips its
per-call UTF-8 revalidation of the buffer. The gate is a pure OR,
so collapsing and reordering its terms cannot change the answer.
click / typer decorators
stdlib argv / env / getopt
typer
Web frameworks: their os.environ/os.getenv reads are config, not a CLI surface, so raw env is suppressed when one is present (framework-bound env via click/typer is still emitted).
Class methods
Instance methods
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.