Metadata-Version: 2.4
Name: repo-inspector
Version: 0.1.1
Summary: Offline CLI tool for static analysis of Python repositories
Project-URL: Homepage, https://github.com/samcab28/Repo-Inspector
Project-URL: Repository, https://github.com/samcab28/Repo-Inspector
Project-URL: Issues, https://github.com/samcab28/Repo-Inspector/issues
Author: Repo Inspector Contributors
License: MIT
License-File: LICENSE
Keywords: ast,cli,code-quality,complexity,static-analysis
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.11
Requires-Dist: chardet>=5
Requires-Dist: networkx>=3
Requires-Dist: pathspec>=0.12
Requires-Dist: radon>=6
Requires-Dist: rich>=13
Requires-Dist: typer>=0.12
Provides-Extra: dev
Requires-Dist: hatch>=1.12; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Description-Content-Type: text/markdown

# Repo Inspector

> Offline static analysis CLI for Python repositories. No API keys. No internet. Just your code.

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
[![PyPI version](https://img.shields.io/pypi/v/repo-inspector.svg)](https://pypi.org/project/repo-inspector/)

Repo Inspector parses your Python project with the standard library `ast` module and surfaces code quality metrics, architectural problems, and technical debt — all without touching the network.

---

## Features

- **Cyclomatic complexity** — per-function CC scores via Radon, God Object file detection
- **Dead code** — heuristic detection of unreferenced functions, classes, and files
- **Module coupling** — fan-in / fan-out scores, highlights highly coupled modules
- **Import graph** — visualizes the internal dependency tree, detects circular imports
- **Duplicate code** — AST-normalized structural similarity hashing
- **Change impact** — BFS on the reversed import graph to find blast radius of a change
- **Health score** — weighted 0–10 score across six signals (tests, docs, CI, complexity, coupling, dead code)
- **TODO scanner** — inventories TODO / FIXME / HACK / NOQA / XXX comments
- **Respects `.gitignore`** — never traverses `.git/`, `__pycache__/`, `.venv/`, `dist/`

---

## Installation

```bash
pip install repo-inspector
```

**Requirements:** Python 3.11 or later, no other system dependencies.

---

## Quick Start

```bash
# Full analysis summary
repo-inspector scan /path/to/your/project

# With all individual findings printed
repo-inspector scan /path/to/your/project --full

# Export results to JSON
repo-inspector scan /path/to/your/project --output report.json
```

**Example output:**

```
────────────────────── Project Analysis Summary ──────────────────────
   Root path      /path/to/your/project
   Total files    84
   Python files   71
   Lines of code  24,392
   Functions      512
   Classes        73

  Analyzer                Critical  Warning  Info
  Complexity Analysis            0        4     0
  Import Analysis                1        0     0
  Coupling Analysis              0        2     0
  Dead Code Analysis             0        0    18
  Duplication Analysis           0        3     0
  TODO/FIXME Analysis            0        0    11
  Health Analysis                0        1     0

  Health Score  ███████░░░  7.2/10
```

---

## Commands

| Command | Description |
|---|---|
| `scan <path>` | Full analysis summary across all analyzers |
| `complexity <path>` | Cyclomatic complexity per function, large file detection |
| `deadcode <path>` | Unused functions, classes, and unreferenced files |
| `coupling <path>` | Fan-in / fan-out module coupling scores |
| `imports <path>` | Import graph tree and circular dependency detection |
| `impact <path> <file>` | Modules affected if a given file changes |
| `health <path>` | Aggregated repository health score (0–10) |
| `duplication <path>` | Structurally identical function bodies |
| `todos <path>` | TODO / FIXME / HACK / NOQA / XXX inventory |

### Flags

```bash
repo-inspector scan . --full          # Print all individual findings after the summary
repo-inspector scan . --output out.json  # Write full results to a JSON file
```

---

## Thresholds

| Metric | Warning | Critical |
|---|---|---|
| Cyclomatic complexity | >= 10 | >= 20 |
| Function size (lines) | >= 50 | >= 80 |
| File size (lines) | >= 500 | >= 1000 |
| Coupling score (fan-in + fan-out) | >= 10 | >= 20 |

---

## Health Score Signals

The `health` command produces a weighted score out of 10. Weights are defined in `analysis/health.py`.

| Signal | Weight | Description |
|---|---|---|
| Test coverage estimate | 0.25 | Ratio of test files to source files |
| Avg complexity score | 0.20 | Inverted average cyclomatic complexity |
| Documentation ratio | 0.20 | Functions with docstrings / total functions |
| CI pipeline present | 0.15 | `.github/workflows/`, `.gitlab-ci.yml`, or `Jenkinsfile` |
| Dead code ratio | 0.10 | Inverted ratio of unreferenced functions |
| Linting config present | 0.10 | `.flake8`, `.pylintrc`, `pyproject.toml [tool.ruff]`, etc. |

---

## How It Works

1. `scan_project()` traverses the directory respecting `.gitignore`, builds a `ProjectIndex`
2. Each analyzer receives the immutable `ProjectIndex` and returns an `AnalysisResult`
3. `cli.py` calls all analyzers and passes results to `report/formatter.py` for Rich rendering
4. No analyzer touches the filesystem directly after the index is built

---

## Development Setup

```bash
git clone https://github.com/samcab28/Repo-Inspector
cd repo-inspector
python -m venv .venv
source .venv/bin/activate        # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
pytest
```

### Running the test suite

```bash
pytest                  # all 211 tests
pytest --tb=short -v    # verbose with short tracebacks
pytest tests/test_complexity.py  # single module
```

### Building the package

```bash
python -m build
# Produces:
#   dist/repo_inspector-0.1.0-py3-none-any.whl
#   dist/repo_inspector-0.1.0.tar.gz
```

---

## Project Structure

```
repo_inspector/
├── cli.py                    # Typer CLI — all command definitions
├── scanner/
│   └── project_scanner.py    # File traversal, .gitignore handling, ProjectIndex builder
├── analysis/
│   ├── complexity.py         # Cyclomatic complexity, function/file size
│   ├── coupling.py           # Fan-in / fan-out per module
│   ├── deadcode.py           # Unused functions, classes, unreferenced files
│   ├── health.py             # Health score aggregator (weights live here)
│   ├── impact.py             # Change impact via reverse dependency BFS
│   ├── imports.py            # Import graph, circular dependency detection
│   ├── similarity.py         # Duplicate function detection via AST hashing
│   └── todos.py              # TODO/FIXME/HACK/NOQA/XXX comment scanner
├── utils/
│   ├── ast_parser.py         # Dataclasses: ProjectIndex, ModuleInfo, Finding, …
│   └── graph_builder.py      # NetworkX DiGraph construction from ProjectIndex
└── report/
    └── formatter.py          # Rich-based console output (tables, trees, rules)

tests/
├── conftest.py               # Shared fixtures: make_project_index, make_module_info
├── test_integration.py       # End-to-end subprocess tests for every CLI command
├── test_ast_parser.py
├── test_scanner.py
├── test_complexity.py
├── test_coupling.py
├── test_deadcode.py
├── test_health.py
├── test_impact.py
├── test_imports.py
├── test_similarity.py
└── test_todos.py
```

---

## Architecture Rules

These constraints are enforced by convention and tested indirectly:

1. **Single public function per analyzer:** each module in `analysis/` exposes exactly `analyze(index: ProjectIndex) -> AnalysisResult`.
2. **Immutable `ProjectIndex`:** frozen dataclass — no analyzer may mutate it.
3. **No `print()` in analyzers:** all output goes through `report/formatter.py`.
4. **`cli.py` is the only cross-layer importer** — it imports from both `analysis/` and `report/`; analyzers never import from `report/`.
5. **NetworkX for all graph work** — `graph_builder.py` returns `nx.DiGraph`; all cycles/BFS use NetworkX algorithms.

---

## Contributing

Contributions are welcome. Please open an issue before submitting a large change so we can discuss the approach.

```bash
# Fork, clone, create a branch
git checkout -b feature/my-analyzer

# Make changes, add tests, confirm the suite passes
pytest --tb=short

# Open a pull request against main
```

**Adding a new analyzer:**

1. Create `repo_inspector/analysis/my_analyzer.py` with `analyze(index) -> AnalysisResult`
2. Add the corresponding `tests/test_my_analyzer.py`
3. Import and wire up in `cli.py`
4. Add it to the `scan` command's `results` dict in `cli.py`

---

## License

[MIT](LICENSE) — © 2026 Repo Inspector Contributors
