-
- Check existing issues first
- Provide minimal reproducible examples
- Include Python version and operating system
- Describe expected vs. actual behavior
-
- Open a feature request
- Explain the use case and motivation
- Provide examples or references
- Discuss implementation approach
- Fix typos and clarify explanations
- Add examples and tutorials
- Improve docstrings and type hints
- Translate documentation
- Propose new heavy-tailed families
- Implement discrete distributions
- Add multivariate extensions
- Contribute copula models
- Increase test coverage
- Add edge case tests
- Cross-validate against SciPy/R
- Add performance benchmarks
Contributing to HeavyTails¶
Thank you for your interest in contributing to HeavyTails! This guide will help you get started with contributions, whether you're fixing bugs, adding features, improving documentation, or proposing new distributions.
Development Setup¶
Prerequisites¶
- Python 3.8+
- Poetry (recommended) or pip
- Git
Fork and Clone¶
- Fork the repository on GitHub
- Clone your fork:
- Add upstream remote:
Install Development Dependencies¶
```bash
# Install Poetry if needed
curl -sSL https://install.python-poetry.org | python3 -
# Install project and dev dependencies
poetry install --with dev,docs,test
# Activate virtual environment
poetry shell
```
```bash
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install in editable mode
pip install -e ".[dev,docs,test]"
```
Development Workflow¶
Create a Feature Branch¶
# Update your main branch
git checkout main
git pull upstream main
# Create feature branch
git checkout -b feature/your-feature-name
Make Changes¶
Follow the coding standards below when making changes.
Run Tests¶
# Run all tests
poetry run pytest
# Run with coverage
poetry run pytest --cov=heavytails --cov-report=html
# Run specific test file
poetry run pytest tests/test_pareto.py
# Run with verbose output
poetry run pytest -v
Check Code Quality¶
# Format code with ruff
poetry run ruff format .
# Lint code
poetry run ruff check .
# Fix auto-fixable issues
poetry run ruff check --fix .
# Type checking (if using mypy)
poetry run mypy heavytails
Build Documentation Locally¶
# Build docs
poetry run mkdocs build
# Serve docs locally
poetry run mkdocs serve
# Open http://127.0.0.1:8000 in your browser
Commit Changes¶
Write clear, descriptive commit messages:
git add .
git commit -m "feat: add Burr Type XII distribution
- Implement PDF, CDF, PPF, and sampling
- Add comprehensive tests
- Update documentation
"
Commit message format:
feat:New featurefix:Bug fixdocs:Documentation changestest:Test additions/changesrefactor:Code refactoringperf:Performance improvementsstyle:Formatting changeschore:Build/maintenance tasks
Push and Create Pull Request¶
Then create a Pull Request on GitHub:
- Go to your fork on GitHub
- Click "New Pull Request"
- Fill in the template
- Wait for review
Coding Standards¶
Code Style¶
- PEP 8 compliance (enforced by ruff)
- Type hints for all public functions
- Docstrings in NumPy style
- NumPy only in the core library. Anything further needs a reason that outweighs another dependency for everyone who installs it.
Example Function¶
from __future__ import annotations
from dataclasses import dataclass
import math
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from collections.abc import Sequence
@dataclass(frozen=True)
class MyDistribution:
"""
Brief one-line description.
Detailed description of the distribution, including mathematical
formulation and use cases.
Parameters
----------
alpha : float
Shape parameter, must be > 0.
beta : float
Scale parameter, must be > 0.
Examples
--------
>>> dist = MyDistribution(alpha=2.0, beta=1.0)
>>> samples = dist.rvs(100, seed=42)
>>> print(dist.mean())
1.0
Notes
-----
Mathematical details, references to papers, etc.
References
----------
.. [1] Author, A. (Year). "Title". Journal, vol(issue), pages.
"""
alpha: float
beta: float
def __post_init__(self) -> None:
"""Validate parameters."""
if self.alpha <= 0:
raise ValueError("alpha must be > 0")
if self.beta <= 0:
raise ValueError("beta must be > 0")
def pdf(self, x: float) -> float:
"""
Probability density function.
Parameters
----------
x : float
Evaluation point.
Returns
-------
float
PDF value at x.
"""
if x <= 0:
return 0.0
return (self.alpha / self.beta) * (x / self.beta) ** (self.alpha - 1)
Testing Standards¶
Every new feature must include tests:
import pytest
from heavytails import MyDistribution
def test_my_distribution_creation():
"""Test distribution initialization."""
dist = MyDistribution(alpha=2.0, beta=1.0)
assert dist.alpha == 2.0
assert dist.beta == 1.0
def test_my_distribution_invalid_params():
"""Test parameter validation."""
with pytest.raises(ValueError):
MyDistribution(alpha=-1.0, beta=1.0)
with pytest.raises(ValueError):
MyDistribution(alpha=2.0, beta=0.0)
def test_pdf_values():
"""Test PDF against known values."""
dist = MyDistribution(alpha=2.0, beta=1.0)
assert dist.pdf(0.5) == pytest.approx(1.0, rel=1e-6)
assert dist.pdf(1.0) == pytest.approx(2.0, rel=1e-6)
assert dist.pdf(-1.0) == 0.0
def test_sampling_reproducibility():
"""Test that sampling with seed is reproducible."""
dist = MyDistribution(alpha=2.0, beta=1.0)
samples1 = dist.rvs(100, seed=42)
samples2 = dist.rvs(100, seed=42)
assert samples1 == samples2
Adding a New Distribution¶
Step-by-Step Guide¶
-
Research the distribution
-
Mathematical properties
- Parameter constraints
- Tail behavior
-
Applications
-
Implement the class
Create in heavytails/extra_distributions.py or a new module:
@dataclass(frozen=True)
class NewDistribution(Samplable):
"""Distribution description."""
param1: float
param2: float
def __post_init__(self) -> None:
# Validate parameters
pass
def pdf(self, x: float) -> float:
"""Probability density function."""
pass
def cdf(self, x: float) -> float:
"""Cumulative distribution function."""
pass
def sf(self, x: float) -> float:
"""Survival function."""
return 1.0 - self.cdf(x)
def ppf(self, u: float) -> float:
"""Percent point function (quantile)."""
pass
def _rvs_one(self, rng: RNG) -> float:
"""Generate one random variate."""
return self.ppf(rng.uniform_0_1())
def mean(self) -> float:
"""Expected value (if exists)."""
pass
def variance(self) -> float:
"""Variance (if exists)."""
pass
- Write comprehensive tests
Create tests/test_new_distribution.py:
def test_pdf_integrates_to_one():
"""Test that PDF integrates to 1."""
pass
def test_cdf_bounds():
"""Test CDF is in [0, 1]."""
pass
def test_quantile_inversion():
"""Test PPF inverts CDF."""
pass
def test_moments():
"""Test analytical moments match numerical."""
pass
- Add documentation
Update:
docs/guide/distributions.md- Add to reference tabledocs/api/extra.md- API documentation-
README.md- Add to list if major distribution -
Update exports
In heavytails/__init__.py:
- Add example
Create example in examples/new_distribution_demo.py
Pull Request Guidelines¶
PR Checklist¶
- Code follows style guidelines (ruff passes)
- All tests pass (
pytest) - New tests added for new functionality
- Documentation updated
- Docstrings added/updated
- CHANGELOG.md updated (if applicable)
- No breaking changes (or clearly documented)
- Commit messages are clear and descriptive
PR Description Template¶
## Description
Brief description of changes.
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring
## Motivation
Why is this change needed?
## Testing
How was this tested?
## Related Issues
Closes #123, Relates to #456
## Checklist
- [ ] Tests added/updated
- [ ] Documentation updated
- [ ] Code follows style guide
- [ ] All tests pass
Code Review Process¶
- Maintainer review - Core team reviews code
- CI checks - Automated tests must pass
- Discussion - Feedback and iteration
- Approval - At least one maintainer approval
- Merge - Squash and merge to main
Release Process¶
Releases follow Semantic Versioning:
- Major (1.0.0): Breaking changes
- Minor (0.1.0): New features, backward compatible
- Patch (0.0.1): Bug fixes
Community Guidelines¶
Code of Conduct¶
- Be respectful and inclusive
- Welcome newcomers
- Provide constructive feedback
- Focus on technical merits
- Assume good intentions
Getting Help¶
- Questions: Use GitHub Discussions
- Bugs: Open an issue
- Email: dfr@esmad.ipp.pt
Recognition¶
Contributors are recognized in:
AUTHORS.mdfile- Release notes
- Documentation acknowledgments
Thank you for contributing to HeavyTails! 🎉