Skip to content

examine

Full name: tenets.cli.commands.examine

examine

Examine command implementation.

This module provides a Typer-compatible examine app that performs comprehensive code examination including complexity analysis, metrics calculation, hotspot detection, ownership analysis, and multiple output formats. Tests import the exported examine symbol and invoke it directly using Typer's CliRunner, so we expose a Typer app via a callback rather than a bare Click command.

Classes

Functions

run

Python
run(path: str = typer.Argument('.', help='Path to analyze'), output: Optional[str] = typer.Option(None, '--output', '-o', help='Output file for report'), output_format: str = typer.Option('terminal', '--format', '-f', help='Output format'), metrics: List[str] = typer.Option([], '--metrics', '-m', help='Specific metrics to calculate', show_default=False), threshold: int = typer.Option(10, '--threshold', '-t', help='Complexity threshold'), include: List[str] = typer.Option([], '--include', '-i', help='File patterns to include', show_default=False), exclude: List[str] = typer.Option([], '--exclude', '-e', help='File patterns to exclude', show_default=False), include_minified: bool = typer.Option(False, '--include-minified', help='Include minified/built files (*.min.js, dist/, etc.) normally excluded'), max_depth: int = typer.Option(5, '--max-depth', help='Maximum directory depth'), show_details: bool = typer.Option(False, '--show-details', help='Show details'), hotspots: bool = typer.Option(False, '--hotspots', help='Include hotspot analysis'), ownership: bool = typer.Option(False, '--ownership', help='Include ownership analysis'), complexity_trend: bool = typer.Option(False, '--complexity-trend', help='Include complexity trend hook in results (experimental)'))

Typer app callback for the examine command.

This mirrors the legacy Click command interface while ensuring compatibility with Typer's testing harness.

Source code in tenets/cli/commands/examine.py
Python
@examine.callback()
def run(
    path: str = typer.Argument(".", help="Path to analyze"),
    output: Optional[str] = typer.Option(None, "--output", "-o", help="Output file for report"),
    output_format: str = typer.Option("terminal", "--format", "-f", help="Output format"),
    metrics: List[str] = typer.Option(
        [], "--metrics", "-m", help="Specific metrics to calculate", show_default=False
    ),
    threshold: int = typer.Option(10, "--threshold", "-t", help="Complexity threshold"),
    include: List[str] = typer.Option(
        [], "--include", "-i", help="File patterns to include", show_default=False
    ),
    exclude: List[str] = typer.Option(
        [], "--exclude", "-e", help="File patterns to exclude", show_default=False
    ),
    include_minified: bool = typer.Option(
        False,
        "--include-minified",
        help="Include minified/built files (*.min.js, dist/, etc.) normally excluded",
    ),
    max_depth: int = typer.Option(5, "--max-depth", help="Maximum directory depth"),
    show_details: bool = typer.Option(False, "--show-details", help="Show details"),
    hotspots: bool = typer.Option(False, "--hotspots", help="Include hotspot analysis"),
    ownership: bool = typer.Option(False, "--ownership", help="Include ownership analysis"),
    complexity_trend: bool = typer.Option(
        False,
        "--complexity-trend",
        help="Include complexity trend hook in results (experimental)",
    ),
):
    """Typer app callback for the examine command.

    This mirrors the legacy Click command interface while ensuring
    compatibility with Typer's testing harness.
    """
    _run_examination(
        path=path,
        output=output,
        output_format=output_format,
        metrics=list(metrics) if metrics else [],
        threshold=threshold,
        include=list(include) if include else [],
        exclude=list(exclude) if exclude else [],
        include_minified=include_minified,
        max_depth=max_depth,
        show_details=show_details,
        hotspots=hotspots,
        ownership=ownership,
        complexity_trend=complexity_trend,
    )

generate_auto_filename

Python
generate_auto_filename(path: str, format: str, timestamp: Optional[datetime] = None) -> str

Generate an automatic filename for reports.

PARAMETERDESCRIPTION
path

The path that was examined

TYPE:str

format

The output format (html, json, markdown, etc.)

TYPE:str

timestamp

Optional timestamp to use (defaults to current time)

TYPE:Optional[datetime]DEFAULT:None

RETURNSDESCRIPTION
str

Generated filename like: tenets_report_{path}_{timestamp}.{format}

Source code in tenets/cli/commands/examine.py
Python
def generate_auto_filename(path: str, format: str, timestamp: Optional[datetime] = None) -> str:
    """Generate an automatic filename for reports.

    Args:
        path: The path that was examined
        format: The output format (html, json, markdown, etc.)
        timestamp: Optional timestamp to use (defaults to current time)

    Returns:
        Generated filename like: tenets_report_{path}_{timestamp}.{format}
    """
    # Use provided timestamp or current time
    ts = timestamp or datetime.now()

    # Extract base name from path
    if str(path) in [".", ""]:
        # Handle current directory or empty path
        safe_path_name = "project"
    elif isinstance(path, Path):
        examined_path = path.name if path.name else "project"
        safe_path_name = "".join(c if c.isalnum() or c in "-_" else "_" for c in str(examined_path))
    elif "/" in str(path) or "\\" in str(path):
        path_obj = Path(path)
        examined_path = path_obj.name if path_obj.name else "project"
        safe_path_name = "".join(c if c.isalnum() or c in "-_" else "_" for c in str(examined_path))
    else:
        # Just a name, not a path
        safe_path_name = "".join(c if c.isalnum() or c in "-_" else "_" for c in str(path))

    # Handle edge cases where the name becomes empty or just underscores
    if not safe_path_name or all(c == "_" for c in safe_path_name):
        safe_path_name = "project"

    # Generate timestamp string
    timestamp_str = ts.strftime("%Y%m%d_%H%M%S")

    # Create filename: tenets_report_{path}_{timestamp}.{format}
    return f"tenets_report_{safe_path_name}_{timestamp_str}.{format}"