Skip to content

Commit 8545fd9

Browse files
refactor(tests): code analysis engine
new_capabilities: - capability: deep code analysis engine impact: intelligent change detection - capability: code quality metrics impact: maintainability tracking - capability: multi-language support impact: universal code analysis - capability: code relationship mapping impact: architecture understanding - capability: CLI interface impact: improved user experience functional_components: - role: test case name: test_packaging_checker_modern_poetry - role: test case name: test_packaging_checker_missing_build_system - role: test case name: test_packaging_checker_missing_metadata - role: test case name: test_packaging_checker_initialization - role: test case name: test_release_checker_missing_dist architecture: - category: core files: 10 names: [Makefile, __init__.py, base.py, packaging.py, +6 more] - category: analyzer files: 8 names: [git_scan_example.py, benchmark_scan.py, test_analyzer.py, test_scan_integration.py, +4 more] - category: test files: 6 names: [test_packaging_checker.py, test_release_readiness_checker.py, test_reporter.py, test_security_checker.py, +2 more] - category: cli files: 2 names: [test_cli.py, cli.py] - category: config files: 1 names: [pyproject.toml] - category: docs files: 1 names: [README.md] - category: quality files: 1 names: [dependencies.py] impact: lines: "55% code reduction (-856 lines refactored, +690/-856, NET -166)" relations: "cli→git_scanner (1 clean relations)" test_coverage: "10/29 files (34%)" framework_score: 100 dependency_flow: chain: cli→git_scanner relations: - from: cli.py to: git_scanner.py files: core: 10 docs: 1 analyzer: 8 config: 1 cli: 2 test: 6 quality: 1
1 parent a1fe61f commit 8545fd9

31 files changed

Lines changed: 733 additions & 858 deletions

CHANGELOG.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,44 @@
1+
## [0.1.41] - 2026-02-15
2+
3+
### Summary
4+
5+
refactor(tests): code analysis engine
6+
7+
### Docs
8+
9+
- docs: update README
10+
11+
### Test
12+
13+
- update tests/benchmark_scan.py
14+
- update tests/test_analyzer.py
15+
- update tests/test_cli.py
16+
- update tests/test_packaging_checker.py
17+
- update tests/test_release_readiness_checker.py
18+
- update tests/test_reporter.py
19+
- update tests/test_scan_integration.py
20+
- update tests/test_security_checker.py
21+
- update tests/test_style_checker.py
22+
23+
### Build
24+
25+
- update pyproject.toml
26+
27+
### Other
28+
29+
- build: update Makefile
30+
- update examples/git_scan_example.py
31+
- update weekly/__init__.py
32+
- update weekly/checkers/base.py
33+
- update weekly/checkers/dependencies.py
34+
- update weekly/checkers/packaging.py
35+
- update weekly/checkers/release_readiness.py
36+
- update weekly/checkers/security.py
37+
- update weekly/checkers/testing.py
38+
- update weekly/cli.py
39+
- ... and 8 more
40+
41+
142
## [0.1.40] - 2026-02-15
243

344
### Summary

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,12 @@ publish:
135135
## Build documentation
136136
docs:
137137
@echo "${YELLOW}Building documentation...${RESET}"
138-
cd docs && poetry run make html
138+
poetry run mkdocs build
139139

140140
## Serve documentation locally
141141
serve:
142142
@echo "${YELLOW}Serving documentation at http://localhost:8000${RESET}"
143-
cd docs/_build/html && python -m http.server
143+
poetry run mkdocs serve
144144

145145
## Install pre-commit hooks
146146
pre-commit:

README.md

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,17 @@ Weekly is a comprehensive Python project quality analyzer that helps developers
2424

2525
## ✨ Features
2626

27-
- 🧪 **Test Coverage Analysis**: Check test coverage and test configuration
27+
- 🧪 **Test Coverage Analysis**: Check test coverage and test configuration (now parses `coverage.xml`)
2828
- 📚 **Documentation Check**: Verify README, LICENSE, CHANGELOG, and API docs
2929
- 🔄 **CI/CD Integration**: Detect CI/CD configuration and best practices
30-
- 📦 **Dependency Analysis**: Identify outdated or vulnerable dependencies
30+
- 📦 **Dependency Analysis**: Identify outdated or vulnerable dependencies (now with `pip-audit` integration and AST parsing)
3131
- 🛠️ **Code Quality**: Check for code style, formatting, and common issues
32+
- 🔒 **Security Checks**: Detect hardcoded secrets and insecure function usage
33+
- 📦 **Packaging Check**: Verify PEP 517/518 compliance and distribution metadata
34+
- 🚀 **Release Readiness**: Check version consistency and changelog status
3235
- 📊 **Interactive Reports**: Generate detailed reports in multiple formats (JSON, Markdown, Text, HTML)
33-
- 🔍 **Extensible Architecture**: Easy to add custom checkers and rules
34-
- 🚀 **Fast and Lightweight**: Minimal dependencies, fast analysis
35-
- 🔄 **Git Integration**: Works seamlessly with Git repositories
36-
- 🔍 **Multi-Repo Scanning**: Scan multiple Git repositories in a directory structure
37-
- 📅 **Date-based Filtering**: Only analyze repositories with recent changes
38-
- 📑 **HTML Reports**: Beautiful, interactive HTML reports with drill-down capabilities
39-
- 🔒 **Security Checks**: Identify potential security issues in your code
40-
- 📈 **Trend Analysis**: Track code quality metrics over time
36+
- 🔍 **Multi-Repo Scanning**: Scan multiple Git repositories with parallel processing
37+
- 📅 **Date-based Filtering**: Flexible date parsing for analyzing recent changes
4138

4239
## 🔍 Git Repository Scanning
4340

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.1.40
1+
0.1.41

examples/git_scan_example.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,48 @@
33
"""
44

55
import sys
6-
from pathlib import Path
76
from datetime import datetime, timedelta
7+
from pathlib import Path
88

99
# Add the parent directory to the path so we can import weekly
1010
sys.path.append(str(Path(__file__).parent.parent))
1111

1212
from weekly import GitScanner
1313

14-
def main():
14+
15+
def main() -> None:
1516
# Configuration
1617
root_dir = Path.home() / "github" # Directory containing your Git repositories
1718
output_dir = Path("weekly-reports") # Where to save the reports
1819
since_days = 7 # Only include repositories with changes in the last X days
19-
20+
2021
# Create a scanner instance
2122
scanner = GitScanner(
2223
root_dir=root_dir,
2324
output_dir=output_dir,
2425
since=datetime.now() - timedelta(days=since_days),
2526
recursive=True,
26-
jobs=4
27+
jobs=4,
2728
)
28-
29+
2930
# Run the scan
3031
print(f"🔍 Scanning Git repositories in {root_dir}...")
3132
results = scanner.scan_all()
32-
33+
3334
# Print a summary
3435
print(f"\n✅ Scan complete! Generated reports for {len(results)} repositories.")
3536
print(f"📊 Summary report: {output_dir / 'summary.html'}")
36-
37+
3738
for result in results:
3839
ok_results = [r for r in result.results.values() if r is not None]
39-
status = "✅" if not result.error and all(getattr(r, "is_ok", True) for r in ok_results) else "❌"
40-
print(f"{status} {result.repo.org}/{result.repo.name}: {len(result.results)} checks")
40+
status = (
41+
"✅"
42+
if not result.error and all(getattr(r, "is_ok", True) for r in ok_results)
43+
else "❌"
44+
)
45+
print(
46+
f"{status} {result.repo.org}/{result.repo.name}: {len(result.results)} checks"
47+
)
4148
if result.error:
4249
print(f" Error: {result.error}")
4350
for name, check in result.results.items():
@@ -48,5 +55,6 @@ def main():
4855
status = "✓" if getattr(check, "is_ok", False) else "✗"
4956
print(f" {status} {name}: {getattr(check, 'message', str(check))}")
5057

58+
5159
if __name__ == "__main__":
5260
main()

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "weekly"
3-
version = "0.1.40"
3+
version = "0.1.41"
44
description = "A comprehensive Python project quality analyzer that automatically detects issues in code style, documentation, CI/CD, and dependencies, providing actionable next steps and detailed reports."
55
authors = [
66
"Tom Sapletta <tom@sapletta.com>"
@@ -29,7 +29,7 @@ classifiers = [
2929
[tool.poetry.dependencies]
3030
python = ">=3.8.1,<4.0"
3131
click = "^8.1.3"
32-
tomli = { version = "^2.0.1", python = "<3.11" }
32+
tomli = { version = "2.0.1", python = "<3.11" }
3333
toml = "^0.10.2" # For parsing TOML files
3434
pyyaml = "^6.0.0"
3535
rich = "^13.4.1" # For beautiful console output

tests/benchmark_scan.py

Lines changed: 55 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,77 +2,106 @@
22
Benchmark script for Weekly scan command.
33
Measures performance when scanning many repositories.
44
"""
5-
import time
5+
import argparse
66
import shutil
77
import subprocess
8-
from pathlib import Path
8+
import time
99
from datetime import datetime, timedelta
10-
import argparse
10+
from pathlib import Path
11+
1112

1213
def create_mock_repo(repo_path: Path, index: int):
1314
"""Create a mock Git repository with some files and commits."""
1415
repo_path.mkdir(parents=True, exist_ok=True)
1516
subprocess.run(["git", "init", "-q"], cwd=repo_path, check=True)
16-
subprocess.run(["git", "config", "user.email", "bench@example.com"], cwd=repo_path, check=True)
17-
subprocess.run(["git", "config", "user.name", "Bench User"], cwd=repo_path, check=True)
18-
17+
subprocess.run(
18+
["git", "config", "user.email", "bench@example.com"], cwd=repo_path, check=True
19+
)
20+
subprocess.run(
21+
["git", "config", "user.name", "Bench User"], cwd=repo_path, check=True
22+
)
23+
1924
# Create some files
20-
(repo_path / "README.md").write_text(f"# Mock Repo {index}\nThis is mock repository number {index}.")
21-
(repo_path / "requirements.txt").write_text("requests==2.28.1\npytest\nblack==23.1.0")
22-
(repo_path / "app.py").write_text("def main():\n print('hello')\n\nif __name__ == '__main__':\n main()")
23-
25+
(repo_path / "README.md").write_text(
26+
f"# Mock Repo {index}\nThis is mock repository number {index}."
27+
)
28+
(repo_path / "requirements.txt").write_text(
29+
"requests==2.28.1\npytest\nblack==23.1.0"
30+
)
31+
(repo_path / "app.py").write_text(
32+
"def main():\n print('hello')\n\nif __name__ == '__main__':\n main()"
33+
)
34+
2435
# Initial commit
2536
subprocess.run(["git", "add", "."], cwd=repo_path, check=True)
26-
subprocess.run(["git", "commit", "-m", "feat: initial commit", "-q"], cwd=repo_path, check=True)
37+
subprocess.run(
38+
["git", "commit", "-m", "feat: initial commit", "-q"], cwd=repo_path, check=True
39+
)
40+
2741

2842
def run_benchmark(num_repos: int, jobs: int):
2943
"""Run the benchmark with a specified number of repositories and parallel jobs."""
3044
bench_dir = Path("bench_workdir")
3145
if bench_dir.exists():
3246
shutil.rmtree(bench_dir)
3347
bench_dir.mkdir()
34-
48+
3549
repos_root = bench_dir / "repos"
3650
output_dir = bench_dir / "reports"
37-
51+
3852
print(f"Creating {num_repos} mock repositories...")
3953
start_create = time.time()
4054
for i in range(num_repos):
4155
create_mock_repo(repos_root / f"repo_{i}", i)
4256
end_create = time.time()
43-
print(f"Created {num_repos} repositories in {end_create - start_create:.2f} seconds.")
44-
57+
print(
58+
f"Created {num_repos} repositories in {end_create - start_create:.2f} seconds."
59+
)
60+
4561
print(f"\nRunning 'weekly scan' with jobs={jobs}...")
4662
# Use 'python -m weekly.cli' or 'weekly' if installed
4763
cmd = [
48-
"python3", "-m", "weekly.cli", "scan",
64+
"python3",
65+
"-m",
66+
"weekly.cli",
67+
"scan",
4968
str(repos_root),
50-
"--output", str(output_dir),
51-
"--jobs", str(jobs),
52-
"--no-recursive"
69+
"--output",
70+
str(output_dir),
71+
"--jobs",
72+
str(jobs),
73+
"--no-recursive",
5374
]
54-
75+
5576
start_scan = time.time()
5677
result = subprocess.run(cmd, capture_output=True, text=True)
5778
end_scan = time.time()
58-
79+
5980
if result.returncode != 0:
6081
print(f"Scan failed with return code {result.returncode}")
6182
print("STDOUT:", result.stdout)
6283
print("STDERR:", result.stderr)
6384
return
64-
85+
6586
scan_time = end_scan - start_scan
6687
print(f"Scan completed in {scan_time:.2f} seconds.")
6788
print(f"Average time per repository: {scan_time / num_repos:.3f} seconds.")
68-
89+
6990
# Cleanup
7091
shutil.rmtree(bench_dir)
7192

93+
7294
if __name__ == "__main__":
7395
parser = argparse.ArgumentParser(description="Benchmark Weekly scan performance.")
74-
parser.add_argument("--repos", type=int, default=20, help="Number of repositories to create (default: 20)")
75-
parser.add_argument("--jobs", type=int, default=4, help="Number of parallel jobs (default: 4)")
76-
96+
parser.add_argument(
97+
"--repos",
98+
type=int,
99+
default=20,
100+
help="Number of repositories to create (default: 20)",
101+
)
102+
parser.add_argument(
103+
"--jobs", type=int, default=4, help="Number of parallel jobs (default: 4)"
104+
)
105+
77106
args = parser.parse_args()
78107
run_benchmark(args.repos, args.jobs)

0 commit comments

Comments
 (0)