Thank you for your interest in contributing to the Shadow Payroll Calculator! This document provides guidelines and instructions for contributing to this project.
- Fork the repository on GitHub
- Clone your fork locally:
git clone https://github.com/YOUR_USERNAME/ShadowPayrollAgent.git cd ShadowPayrollAgent
- Python 3.10 or higher
- pip (Python package manager)
- Git
-
Create a virtual environment:
python -m venv .venv
-
Activate the virtual environment:
- Windows:
.venv\Scripts\activate
- macOS/Linux:
source .venv/bin/activate
- Windows:
-
Install dependencies:
pip install -r requirements.txt
-
Set up environment variables:
cp .env.example .env # Edit .env and add your OpenAI API key -
Install pre-commit hooks:
pre-commit install
We use several tools to maintain code quality:
Format your code with Black:
black src/ tests/Lint your code with Ruff:
ruff check src/ tests/To auto-fix issues:
ruff check --fix src/ tests/Run type checking:
mypy src/shadow_payrollPre-commit hooks will run automatically before each commit. To run manually:
pre-commit run --all-filesRun all tests:
pytestRun tests with coverage:
pytest --cov=src/shadow_payroll --cov-report=htmlRun specific test file:
pytest tests/test_calculations.pyRun specific test:
pytest tests/test_calculations.py::TestPayrollCalculator::test_calculate_base_basic- Place tests in the
tests/directory - Use descriptive test names following the pattern
test_<what_is_being_tested> - Group related tests in classes
- Use fixtures from
conftest.pyfor common test data - Aim for high test coverage (>80%)
Example test:
def test_calculate_base_with_valid_inputs(sample_payroll_input):
"""Test base calculation with valid inputs."""
calculator = PayrollCalculator()
result = calculator.calculate_base(sample_payroll_input)
assert result.gross_monthly_ars > 0
assert result.fx_rate == sample_payroll_input.fx_rateFollow these guidelines for commit messages:
- Use the present tense ("Add feature" not "Added feature")
- Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
- Limit the first line to 72 characters or less
- Reference issues and pull requests liberally after the first line
Example:
Add input validation for FX rates
- Validate FX rate is positive
- Reject unreasonably high/low rates
- Add comprehensive tests
Closes #123
-
Create a new branch for your feature:
git checkout -b feature/your-feature-name
-
Make your changes and commit them:
git add . git commit -m "Your commit message"
-
Push to your fork:
git push origin feature/your-feature-name
-
Open a Pull Request on GitHub
-
Ensure all CI checks pass
-
Request review from maintainers
Before submitting a PR, ensure:
- Code follows the project style (Black, Ruff pass)
- All tests pass (
pytest) - New code has tests
- Documentation is updated if needed
- Commit messages are clear and descriptive
- Pre-commit hooks pass
- Follow PEP 8 style guide
- Use type hints where appropriate
- Write docstrings for all public functions/classes
- Keep functions focused and single-purpose
- Prefer explicit over implicit
Use Google-style docstrings:
def calculate_something(value: float, rate: float) -> float:
"""
Calculate something important.
Args:
value: The base value
rate: The rate to apply
Returns:
float: The calculated result
Raises:
ValueError: If value is negative
"""
if value < 0:
raise ValueError("Value must be positive")
return value * rateShadowPayrollAgent/
├── src/
│ └── shadow_payroll/
│ ├── __init__.py
│ ├── config.py # Configuration
│ ├── models.py # Pydantic models
│ ├── calculations.py # Business logic
│ ├── llm_handler.py # LLM integration
│ ├── utils.py # Utilities
│ ├── excel_exporter.py # Excel generation
│ └── ui.py # Streamlit UI
├── tests/
│ ├── __init__.py
│ ├── conftest.py # Test fixtures
│ ├── test_calculations.py
│ ├── test_models.py
│ └── test_utils.py
├── app.py # Main entry point
├── requirements.txt # Dependencies
├── pyproject.toml # Project config
└── README.md # Documentation
If you have questions, please:
- Check existing issues
- Open a new issue with the "question" label
- Be specific and provide context
Thank you for contributing!