orchestrata_tools.main
Reference › orchestrata_tools › main
This module is the command-line entry point of orchestrata_tools, run as python -m orchestrata_tools. Nothing imports it. Every command reads a serialized AST file given by the global --ast option (default plans/ast-ultimate.json) with json_loader and builds an ASTIndex.
There are three subcommands, each handled by one function that returns an exit code:
discover(cmd_discover) prints a summary with--summary, untested public methods with--untested, coverage percentages with--coverage, and coverage gaps with--gaps. The test-related options load a second AST file given by--test-ast(defaultplans/ast-tests.json) and useTestMatcherandCoverageAnalyzerfrom test_analyzer.--limitcaps listed items.diagram(cmd_diagram) prints Mermaid for one class (--class-name), one module (--module), or the full set, using class_diagram.query(cmd_query) turns an expression such as methods filtered bytested=false and public=trueinto aQueryfrom dsl and evaluates it with evaluator. Valuestrueandfalsebecome booleans and digit strings become integers. Query targets are always methods in this command.
The same functions exist in older form in backcompat.
At a glance
| Source | src/orchestrata_tools/__main__.py |
| Lines of code | 151 |
| Classes | 0 |
| Functions | 4 |
| Imports (internal) | orchestrata_tools.diagram, orchestrata_tools.parser, orchestrata_tools.query, orchestrata_tools.test_analyzer |
| Imported by | none |
| Tests that import it | none |
Class diagram
No classes; see Functions.
Dependency diagram
API
Functions
| Function | Signature | Summary |
|---|---|---|
cmd_discover |
cmd_discover(args: argparse.Namespace) -> int |
|
cmd_diagram |
cmd_diagram(args: argparse.Namespace) -> int |
|
cmd_query |
cmd_query(args: argparse.Namespace) -> int |
|
main |
main(argv: list[str] | None = None) -> int |
Source
"""CLI entry point for orchestrata_tools.
Usage:
python -m orchestrata_tools discover --ast plans/ast-ultimate.json --untested
python -m orchestrata_tools diagram --module session.session
python -m orchestrata_tools query 'methods where tested=false'
"""
from __future__ import annotations
import argparse
import sys
from orchestrata_tools.diagram import ClassDiagramGenerator
from orchestrata_tools.parser import ASTIndex, JSONASTLoader
from orchestrata_tools.query import Query, QueryEvaluator
from orchestrata_tools.test_analyzer import CoverageAnalyzer, TestMatcher
def cmd_discover(args: argparse.Namespace) -> int:
ast = JSONASTLoader().load(args.ast)
index = ASTIndex(ast)
if args.summary:
print(f"Modules: {len(ast.modules)}")
print(f"Classes: {len(ast.all_classes)}")
print(f"Methods: {len(ast.all_methods)}")
print(f"LOC: {ast.total_loc}")
if args.untested:
test_ast = JSONASTLoader().load(args.test_ast)
matcher = TestMatcher(test_ast)
untested = matcher.find_untested_methods(index)
print(f"\nUntested public methods: {len(untested)}")
for m in untested[: args.limit]:
print(f" {m.module_path}.{m.class_name}.{m.name}")
if args.coverage:
test_ast = JSONASTLoader().load(args.test_ast)
matcher = TestMatcher(test_ast)
analyzer = CoverageAnalyzer(matcher, index)
report = analyzer.analyze()
print(f"\nMethod coverage: {report.method_coverage_pct}%")
print(f"Class coverage: {report.class_coverage_pct}%")
print(f"Untested: {len(report.gaps)}")
if args.gaps:
test_ast = JSONASTLoader().load(args.test_ast)
matcher = TestMatcher(test_ast)
analyzer = CoverageAnalyzer(matcher, index)
report = analyzer.analyze()
for gap in report.gaps[: args.limit]:
print(f" {gap.module_path}.{gap.class_name}.{gap.method.name}")
return 0
def cmd_diagram(args: argparse.Namespace) -> int:
ast = JSONASTLoader().load(args.ast)
index = ASTIndex(ast)
gen = ClassDiagramGenerator(index)
if args.class_name:
diagram = gen.generate_for_class(args.class_name)
elif args.module:
diagram = gen.generate_for_module(args.module)
else:
diagram = gen.generate_full()
print(diagram.render())
return 0
def cmd_query(args: argparse.Namespace) -> int:
ast = JSONASTLoader().load(args.ast)
index = ASTIndex(ast)
matcher = None
if args.test_ast:
test_ast = JSONASTLoader().load(args.test_ast)
matcher = TestMatcher(test_ast)
evaluator = QueryEvaluator(index, matcher)
# Simple parsing: "methods where tested=false and public=true"
q = Query().methods()
if args.where:
parts = args.where.split(" and ")
for part in parts:
if "=" in part:
key, val = part.split("=", 1)
key = key.strip()
val_str = val.strip()
if val_str == "true":
val = True
elif val_str == "false":
val = False
elif val_str.isdigit():
val = int(val_str)
else:
val = val_str
q = q.where(**{key: val})
results = evaluator.evaluate(q)
for r in results[: args.limit]:
if hasattr(r, "qualified_name"):
print(r.qualified_name)
elif hasattr(r, "path"):
print(r.path)
else:
print(r)
return 0
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(prog="orchestrata_tools")
parser.add_argument(
"--ast", default="plans/ast-ultimate.json", help="Path to AST JSON"
)
subparsers = parser.add_subparsers(dest="command")
discover = subparsers.add_parser("discover", help="Discover codebase info")
discover.add_argument("--summary", action="store_true")
discover.add_argument("--untested", action="store_true")
discover.add_argument("--coverage", action="store_true")
discover.add_argument("--gaps", action="store_true")
discover.add_argument("--test-ast", default="plans/ast-tests.json")
discover.add_argument("--limit", type=int, default=20)
diagram = subparsers.add_parser("diagram", help="Generate Mermaid diagrams")
diagram.add_argument("--class-name", help="Generate diagram for a class")
diagram.add_argument("--module", help="Generate diagram for a module")
query_cmd = subparsers.add_parser("query", help="Query the AST")
query_cmd.add_argument("where", nargs="?", help="Query filter expression")
query_cmd.add_argument("--test-ast", default="plans/ast-tests.json")
query_cmd.add_argument("--limit", type=int, default=20)
args = parser.parse_args(argv)
if args.command == "discover":
return cmd_discover(args)
elif args.command == "diagram":
return cmd_diagram(args)
elif args.command == "query":
return cmd_query(args)
else:
parser.print_help()
return 1
if __name__ == "__main__":
sys.exit(main())