cli-cleanup #1

Merged
aetos merged 6 commits from cli-cleanup into main 2026-01-21 13:23:33 +00:00
7 changed files with 68 additions and 19 deletions
Showing only changes of commit 711bef1dce - Show all commits

View File

@@ -2,8 +2,9 @@ import click
from pathlib import Path from pathlib import Path
from typing import Sequence, Optional from typing import Sequence, Optional
from docforge.loaders import GriffeLoader from docforge.loaders import GriffeLoader
from docforge.cli.mkdocs import logic as mkdocs_logic from docforge.cli import mkdocs_utils
from docforge.cli.mcp import logic as mcp_logic from docforge.cli import mcp_utils
@click.group() @click.group()
def cli() -> None: def cli() -> None:
@@ -13,6 +14,7 @@ def cli() -> None:
""" """
pass pass
@cli.command() @cli.command()
@click.option("--mcp", is_flag=True, help="Build MCP resources") @click.option("--mcp", is_flag=True, help="Build MCP resources")
@click.option("--mkdocs", is_flag=True, help="Build MkDocs site") @click.option("--mkdocs", is_flag=True, help="Build MkDocs site")
@@ -21,7 +23,8 @@ def cli() -> None:
# MkDocs specific # MkDocs specific
@click.option("--site-name", help="MkDocs site name") @click.option("--site-name", help="MkDocs site name")
@click.option("--docs-dir", type=click.Path(path_type=Path), default=Path("docs"), help="Directory for MD sources") @click.option("--docs-dir", type=click.Path(path_type=Path), default=Path("docs"), help="Directory for MD sources")
@click.option("--nav", "nav_file", type=click.Path(path_type=Path), default=Path("docforge.nav.yml"), help="Nav spec path") @click.option("--nav", "nav_file", type=click.Path(path_type=Path), default=Path("docforge.nav.yml"),
help="Nav spec path")
@click.option("--template", type=click.Path(path_type=Path), help="MkDocs template path") @click.option("--template", type=click.Path(path_type=Path), help="MkDocs template path")
@click.option("--mkdocs-yml", type=click.Path(path_type=Path), default=Path("mkdocs.yml"), help="Output config path") @click.option("--mkdocs-yml", type=click.Path(path_type=Path), default=Path("mkdocs.yml"), help="Output config path")
# MCP specific # MCP specific
@@ -51,13 +54,13 @@ def build(
site_name = module site_name = module
click.echo(f"Generating MkDocs sources in {docs_dir}...") click.echo(f"Generating MkDocs sources in {docs_dir}...")
mkdocs_logic.generate_sources(module, project_name, docs_dir) mkdocs_utils.generate_sources(module, project_name, docs_dir)
click.echo(f"Generating MkDocs config {mkdocs_yml}...") click.echo(f"Generating MkDocs config {mkdocs_yml}...")
mkdocs_logic.generate_config(docs_dir, nav_file, template, mkdocs_yml, site_name) mkdocs_utils.generate_config(docs_dir, nav_file, template, mkdocs_yml, site_name)
click.echo("Running MkDocs build...") click.echo("Running MkDocs build...")
mkdocs_logic.build(mkdocs_yml) mkdocs_utils.build(mkdocs_yml)
click.echo("MkDocs build completed.") click.echo("MkDocs build completed.")
if mcp: if mcp:
@@ -65,9 +68,10 @@ def build(
raise click.UsageError("--module is required for MCP build") raise click.UsageError("--module is required for MCP build")
click.echo(f"Generating MCP resources in {out_dir}...") click.echo(f"Generating MCP resources in {out_dir}...")
mcp_logic.generate_resources(module, project_name, out_dir) mcp_utils.generate_resources(module, project_name, out_dir)
click.echo("MCP build completed.") click.echo("MCP build completed.")
@cli.command() @cli.command()
@click.option("--mcp", is_flag=True, help="Serve MCP documentation") @click.option("--mcp", is_flag=True, help="Serve MCP documentation")
@click.option("--mkdocs", is_flag=True, help="Serve MkDocs site") @click.option("--mkdocs", is_flag=True, help="Serve MkDocs site")
@@ -88,9 +92,10 @@ def serve(
raise click.UsageError("Must specify either --mcp or --mkdocs") raise click.UsageError("Must specify either --mcp or --mkdocs")
if mkdocs: if mkdocs:
mkdocs_logic.serve(mkdocs_yml) mkdocs_utils.serve(mkdocs_yml)
elif mcp: elif mcp:
mcp_logic.serve(out_dir) mcp_utils.serve(out_dir)
@cli.command() @cli.command()
@click.option( @click.option(
@@ -120,6 +125,7 @@ def tree(
for obj in module.get_all_objects(): for obj in module.get_all_objects():
_print_object(obj, indent="") _print_object(obj, indent="")
def _print_object(obj, indent: str) -> None: def _print_object(obj, indent: str) -> None:
""" """
Recursive helper to print doc objects and their members to the console. Recursive helper to print doc objects and their members to the console.

View File

@@ -1,6 +1,4 @@
import json
from pathlib import Path from pathlib import Path
from click.testing import CliRunner
from docforge.cli.main import cli from docforge.cli.main import cli
def test_mcp_build(cli_runner): def test_mcp_build(cli_runner):

View File

@@ -48,7 +48,52 @@ def test_mkdocs_build_missing_module_fails(cli_runner):
assert result.exit_code != 0 assert result.exit_code != 0
assert "--module is required" in result.output assert "--module is required" in result.output
def test_mkdocs_build_missing_site_name_fails(cli_runner): def test_mkdocs_build_without_site_name_uses_module_as_default_full_flow(
result = cli_runner.invoke(cli, ["build", "--mkdocs", "--module", "testpkg"]) cli_runner,
assert result.exit_code != 0 mock_mkdocs_build,
assert "--site-name is required" in result.output mock_mkdocs_load_config,
):
# Full integration test: real generation, real config, mocked mkdocs build
with cli_runner.isolated_filesystem():
cwd = Path.cwd()
# Create a minimal Python package
pkg = cwd / "testpkg"
pkg.mkdir()
(pkg / "__init__.py").write_text("")
(pkg / "mod.py").write_text("def f(): ...\n")
# Create nav spec expected by generate_config
nav_file = cwd / "docforge.nav.yml"
nav_file.write_text(
"home: testpkg/index.md\ngroups: {}\n",
encoding="utf-8",
)
result = cli_runner.invoke(
cli,
[
"build",
"--mkdocs",
"--module",
"testpkg",
"--docs-dir",
"docs",
"--mkdocs-yml",
"mkdocs.yml",
],
)
assert result.exit_code == 0
assert mock_mkdocs_build() is True
# MkDocs config must exist
mkdocs_yml = cwd / "mkdocs.yml"
assert mkdocs_yml.exists()
# Site name must default to module name
content = mkdocs_yml.read_text()
assert "site_name: testpkg" in content
# Docs must be generated
assert (cwd / "docs" / "testpkg" / "mod.md").exists()