Add initial CLI support

This commit is contained in:
Andrew Mulbrook 2026-03-21 22:25:32 -05:00
parent e16d67e2f8
commit 22a9c68611
14 changed files with 168 additions and 26 deletions

5
trovedb/cli/__init__.py Normal file
View file

@ -0,0 +1,5 @@
"""Common Environment for CLI"""
from .cli_common import CliEnv
from ._cli_main import main as cli_main

5
trovedb/cli/__main__.py Normal file
View file

@ -0,0 +1,5 @@
#!/usr/bin/env python3
"""Command-line interface for trovedb"""
from ._cli_main import main
main()

38
trovedb/cli/_cli_main.py Normal file
View file

@ -0,0 +1,38 @@
import argparse
import importlib
import pkgutil
import trovedb.cli as cli
from . import cli_common
def _discover_commands():
commands = {}
for info in pkgutil.iter_modules(cli.__path__):
if info.name.startswith('_'):
continue
mod = importlib.import_module(f'trovedb.cli.{info.name}')
if hasattr(mod, 'setup') and hasattr(mod, 'run'):
# strip trailing _ so 'import_' becomes 'import'
name = info.name.rstrip('_')
commands[name] = mod
return commands
def main():
parser = argparse.ArgumentParser(prog='trove')
cli_common.common_args(parser)
subparsers = parser.add_subparsers(dest='command', required=True)
commands = _discover_commands()
for name, mod in sorted(commands.items()):
sub = subparsers.add_parser(name, help=getattr(mod, '__doc__', None))
mod.setup(sub)
args = parser.parse_args()
env = cli_common.get_env(args)
commands[args.command].run(env, args)
if __name__ == "__main__":
main()

29
trovedb/cli/cli_common.py Normal file
View file

@ -0,0 +1,29 @@
"""Common code for CLI subcommands"""
import argparse
import sys
from trovedb import trove_factory, user_env, trove as tr
def display_error(msg: str) -> None:
print(f"Error: {msg}", file=sys.stderr)
class CliEnv:
"""Environment for CLI subcommands"""
def __init__(self, verbose: bool = False):
self.verbose = verbose
self.local_trove = trove_factory.get_trove(user_env.TROVEBASE) if user_env.TROVEBASE else None
def checked_trove(self) -> tr.Trove:
if self.local_trove is None:
display_error("No local trove found")
raise SystemExit()
return self.local_trove
def common_args(parser: argparse.ArgumentParser) -> None:
parser.add_argument('-v', '--verbose', action='store_true')
def get_env(args: argparse.Namespace) -> CliEnv:
return CliEnv(args.verbose)

16
trovedb/cli/ls.py Normal file
View file

@ -0,0 +1,16 @@
"""Note List"""
import argparse
from trovedb.cli import CliEnv
def setup(parser: argparse.ArgumentParser) -> None:
"""Configure this subcommand's arguments."""
pass
def run(env: CliEnv, args: argparse.Namespace) -> None:
"""Entry point when this subcommand is invoked."""
trove = env.checked_trove()
for entry in trove.get_root().entries():
print(entry)

13
trovedb/cli/status.py Normal file
View file

@ -0,0 +1,13 @@
"""System Status"""
import argparse
from trovedb.cli import CliEnv
def setup(parser: argparse.ArgumentParser) -> None:
"""Configure this subcommand's arguments."""
pass
def run(env: CliEnv, args: argparse.Namespace) -> None:
"""Entry point when this subcommand is invoked."""
if env.local_trove:
print("Trove Detected")