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¶
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
@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¶
Generate an automatic filename for reports.
PARAMETER | DESCRIPTION |
---|---|
path | The path that was examined TYPE: |
format | The output format (html, json, markdown, etc.) TYPE: |
timestamp | Optional timestamp to use (defaults to current time) |
RETURNS | DESCRIPTION |
---|---|
str | Generated filename like: tenets_report_{path}_{timestamp}.{format} |
Source code in tenets/cli/commands/examine.py
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}"