hack-house/.venv/lib/python3.12/site-packages/sanic/cli/executor.py
leetcrypt bb1d662ee1 chore: rename project coven → hack-house ⛧
Rebrand the Rust client crate (coven/ → hh/, package+binary "hack-house"),
README, CLI strings, and branch (coven → hack-house). Gitea repo renamed
cmd-chat → hack-house to match. Crypto/server logic unchanged; selftest +
golden-vector test still green, binary is now `hack-house`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 13:29:14 -07:00

101 lines
3.2 KiB
Python

import shutil
from argparse import ArgumentParser
from asyncio import run
from inspect import signature
from typing import Callable
from sanic import Sanic
from sanic.application.logo import get_logo
from sanic.cli.base import (
SanicArgumentParser,
SanicHelpFormatter,
)
def make_executor_parser(parser: ArgumentParser) -> None:
parser.add_argument(
"command",
help="Command to execute",
)
class ExecutorSubParser(ArgumentParser):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not self.description:
self.description = ""
self.description = get_logo(True) + self.description
class Executor:
def __init__(self, app: Sanic, kwargs: dict) -> None:
self.app = app
self.kwargs = kwargs
self.commands = self._make_commands()
self.parser = self._make_parser()
def run(self, command: str, args: list[str]) -> None:
if command == "exec":
args = ["--help"]
parsed_args = self.parser.parse_args(args)
if command not in self.commands:
raise ValueError(f"Unknown command: {command}")
parsed_kwargs = vars(parsed_args)
parsed_kwargs.pop("command")
run(self.commands[command](**parsed_kwargs))
def _make_commands(self) -> dict[str, Callable]:
commands = {c.name: c.func for c in self.app._future_commands}
return commands
def _make_parser(self) -> SanicArgumentParser:
width = shutil.get_terminal_size().columns
parser = SanicArgumentParser(
prog="sanic",
description=get_logo(True),
formatter_class=lambda prog: SanicHelpFormatter(
prog,
max_help_position=36 if width > 96 else 24,
indent_increment=4,
width=None,
),
)
subparsers = parser.add_subparsers(
dest="command",
title=" Commands",
parser_class=ExecutorSubParser,
)
for command in self.app._future_commands:
sub = subparsers.add_parser(
command.name,
help=command.func.__doc__ or f"Execute {command.name}",
formatter_class=SanicHelpFormatter,
)
self._add_arguments(sub, command.func)
return parser
def _add_arguments(self, parser: ArgumentParser, func: Callable) -> None:
sig = signature(func)
for param in sig.parameters.values():
kwargs = {}
if param.default is not param.empty:
kwargs["default"] = param.default
# In Python 3.14+, argparse validates help strings and rejects
# non-string types. Convert annotations to string representation.
help_text = None
if param.annotation is not param.empty:
if isinstance(param.annotation, str):
help_text = param.annotation
else:
help_text = getattr(
param.annotation, "__name__", str(param.annotation)
)
parser.add_argument(
f"--{param.name}",
help=help_text,
**kwargs,
)