Thank you for your interest in contributing to devscope! This document provides guidelines and instructions for contributing.
Be respectful, inclusive, and considerate in all interactions.
git clone https://github.com/yourusername/devscope.git
cd devscopeUsing uv (Recommended):
# Install uv if needed
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install dependencies
uv sync --all-extras
# Verify setup
uv run devscope --versionUsing pip:
python -m venv venv
source venv/bin/activate
pip install -e ".[dev]"git checkout -b feature/your-feature-name# Run all tests
uv run pytest
# Run with coverage
uv run pytest --cov=devscope
# Run specific test file
uv run pytest tests/test_analyzer.py
# Run specific test
uv run pytest tests/test_analyzer.py::TestCodebaseAnalyzer::test_language_detection# Format code
uv run ruff format .
# Lint code
uv run ruff check .
# Fix auto-fixable issues
uv run ruff check . --fix
# Type check
uv run mypy src/devscope
# Run all checks at once
./scripts/check.sh# Test on current directory
uv run devscope scan .
# Test on specific path
uv run devscope scan /path/to/project
# Test with options
uv run devscope scan . --no-git- Follow PEP 8 conventions
- Use type hints for all functions
- Maximum line length: 100 characters
- Use ruff for formatting and linting
All functions must have type annotations:
def analyze_code(path: Path, depth: int = 3) -> AnalysisResult:
"""Analyze code at the given path.
Args:
path: Path to analyze
depth: Maximum directory depth
Returns:
Analysis results
"""
...- Add docstrings to all public functions and classes
- Use Google-style docstrings
- Include examples for complex functionality
def complex_function(arg1: str, arg2: int) -> dict[str, Any]:
"""Brief description.
Longer description with more details.
Args:
arg1: Description of arg1
arg2: Description of arg2
Returns:
Description of return value
Raises:
ValueError: When something goes wrong
Examples:
>>> result = complex_function("test", 42)
>>> result["status"]
"success"
"""
...- Aim for >80% code coverage
- Test both success and failure cases
- Use descriptive test names
- Keep tests focused and isolated
class TestAnalyzer:
"""Test the analyzer module."""
def test_language_detection_with_python_files(self) -> None:
"""Test that Python files are detected correctly."""
# Arrange
...
# Act
result = analyzer.analyze()
# Assert
assert "Python" in result.languagestests/
├── test_analyzer.py # Core analysis tests
├── test_cli.py # CLI interface tests
└── test_utils.py # Utility function tests
- Open an issue to discuss the feature first
- Get feedback before starting implementation
- Break down large features into smaller PRs
- Write tests first (TDD recommended)
- Keep changes focused and atomic
- Add documentation
- Update README if needed
Follow the modular architecture:
- CLI Layer (
cli.py): User interface, argument parsing - Analysis Engine (
analyzer.py): Core logic - Models (
models.py): Data structures - Utilities (
utils.py): Helper functions
Example of adding a new analyzer:
# src/devscope/analyzers/complexity.py
from devscope.models import AnalysisResult
class ComplexityAnalyzer:
"""Analyze code complexity metrics."""
def analyze(self, path: Path) -> dict[str, Any]:
"""Analyze complexity."""
...-
Run all checks:
./scripts/check.sh
-
Update tests:
- Add tests for new functionality
- Ensure all tests pass
- Maintain or improve coverage
-
Update documentation:
- Update README if needed
- Add docstrings
- Update CHANGELOG
-
Commit messages:
feat: Add complexity analysis - Implement cyclomatic complexity calculation - Add complexity metrics to report - Include tests and documentationUse conventional commits:
feat:New featurefix:Bug fixdocs:Documentationtest:Testsrefactor:Code refactoringchore:Maintenance
-
Push to your fork:
git push origin feature/your-feature-name
-
Open a Pull Request on GitHub
-
Fill out the PR template:
- Description of changes
- Motivation and context
- How to test
- Checklist items
- Maintainers will review your PR
- Address feedback promptly
- Be open to suggestions
- CI must pass before merging
-
Update
LANGUAGE_MAPinanalyzer.py:LANGUAGE_MAP = { ... ".new": "NewLang", }
-
Add tests:
def test_new_language_detection(self) -> None: """Test NewLang file detection.""" ...
-
Update
cli.py:@click.option("--new-option", help="Description") def scan(path: str, new_option: bool) -> None: ...
-
Update analyzer to use the option
-
Add tests for the new option
-
Update README
-
Profile first:
python -m cProfile -o profile.stats -m devscope scan large-repo
-
Analyze results:
python -m pstats profile.stats
-
Make targeted improvements
-
Add benchmarks if needed
devscope/
├── src/devscope/ # Source code
│ ├── __init__.py
│ ├── cli.py # CLI interface
│ ├── analyzer.py # Analysis engine
│ ├── models.py # Data models
│ └── utils.py # Utilities
├── tests/ # Test suite
│ ├── test_analyzer.py
│ ├── test_cli.py
│ └── test_utils.py
├── scripts/ # Dev scripts
│ ├── setup.sh
│ └── check.sh
├── pyproject.toml # Project config
├── README.md
├── INSTALL.md
└── CONTRIBUTING.md
(For maintainers)
- Update version in
pyproject.tomland__init__.py - Update CHANGELOG.md
- Create release tag:
git tag -a v0.2.0 -m "Release v0.2.0" git push origin v0.2.0 - Build and publish:
uv build uv publish
- 📖 Read the README
- 💬 Open a Discussion
- 🐛 Report Issues
- 📧 Email maintainers (if provided)
Contributors will be:
- Listed in CONTRIBUTORS.md
- Mentioned in release notes
- Credited in documentation
Thank you for contributing to devscope! 🚀