Contributing¶
Thank you for your interest in contributing to Species Explorer! This guide explains how to contribute to the project.
Code of Conduct¶
Please be respectful and constructive in all interactions. We welcome contributors of all backgrounds and experience levels.
Ways to Contribute¶
Report Bugs¶
Found a bug? Please open an issue with:
- Clear description of the problem
- Steps to reproduce
- Expected vs actual behavior
- QGIS and plugin versions
- Screenshots if applicable
Suggest Features¶
Have an idea? Open a feature request with:
- Clear description of the feature
- Use case and benefits
- Possible implementation approach
Improve Documentation¶
Documentation improvements are always welcome:
- Fix typos and errors
- Add examples and tutorials
- Improve explanations
- Translate documentation
Submit Code¶
Ready to code? Follow these steps:
Development Workflow¶
1. Fork and Clone¶
# Fork on GitHub, then:
git clone https://github.com/YOUR-USERNAME/SpeciesExplorer.git
cd SpeciesExplorer
git remote add upstream https://github.com/kartoza/SpeciesExplorer.git
2. Create a Branch¶
Use descriptive branch names:
feature/add-export-csvfix/handle-empty-resultsdocs/improve-installation
3. Set Up Environment¶
4. Make Changes¶
Write your code following our standards:
- Format with black:
nix run .#format - Lint with flake8:
nix run .#lint - Test your changes:
nix run .#test
5. Commit Changes¶
Write clear commit messages:
git commit -m "Add CSV export functionality
- Add export_to_csv() function
- Add Export button to dialog
- Update documentation"
6. Push and Create PR¶
Then open a Pull Request on GitHub.
Code Standards¶
Python Style¶
- Python 3.9+ compatibility
- 120 character line length
- Black formatting (automatic with pre-commit)
- isort for imports (automatic with pre-commit)
Docstrings¶
Use Google-style docstrings:
def fetch_species(name: str, limit: int = 100) -> list:
"""Fetch species occurrences from GBIF.
Args:
name: Scientific or common name to search.
limit: Maximum number of records to fetch.
Returns:
List of occurrence dictionaries.
Raises:
ConnectionError: If GBIF API is unreachable.
"""
Type Hints¶
Use type hints for function signatures:
def create_layer(
name: str,
occurrences: list[dict],
crs: str = "EPSG:4326"
) -> QgsVectorLayer:
...
Testing¶
- Write tests for new functionality
- Maintain or improve code coverage
- Tests should be independent and repeatable
def test_fetch_species_returns_list():
"""Test that fetch_species returns a list."""
result = fetch_species("Panthera leo")
assert isinstance(result, list)
Pull Request Guidelines¶
Before Submitting¶
- Code passes all linting checks
- Tests pass and coverage is maintained
- Documentation is updated if needed
- Commit messages are clear
PR Description¶
Include in your PR description:
- Summary of changes
- Related issue numbers (fixes #123)
- Screenshots for UI changes
- Testing instructions
Review Process¶
- Maintainers will review your PR
- Address any requested changes
- Once approved, it will be merged
- You'll be credited in the release notes
Release Process¶
Releases are managed by maintainers:
- Update version in
metadata.txt - Update CHANGELOG
- Create and push version tag
- GitHub Actions builds and publishes release
Getting Help¶
- Questions: Open a Discussion
- Bugs: Open an Issue
- Chat: Contact Kartoza
Recognition¶
Contributors are recognized in:
- Release notes
- README credits section
- This documentation
Thank you for contributing to Species Explorer!