Guidelines and procedures for contributing to PrePrimer development.
- Python 3.11 or later
- Git version control
- Virtual environment support
# Clone the repository
git clone https://github.com/FOI-Bioinformatics/preprimer.git
cd preprimer
# Create virtual environment
python3 -m venv preprimer-dev
source preprimer-dev/bin/activate # Linux/macOS
# preprimer-dev\Scripts\activate # Windows (WSL recommended)
# Install development dependencies
pip install -e ".[dev]"
# Install pre-commit hooks
pre-commit install# Run test suite
python -m pytest
# Check code formatting
pre-commit run --all-files
# Verify package installation
python -c "import preprimer; print('Installation successful')"- main: Production-ready code
- develop: Integration branch for features
- feature/: Individual feature development
- bugfix/: Bug fix branches
- Create Branch:
git checkout -b feature/your-feature-name - Develop: Implement feature with tests
- Test: Ensure all tests pass
- Document: Update relevant documentation
- Review: Submit pull request for review
- Merge: Merge after approval and CI success
Follow conventional commit format:
type(scope): description
feat(parser): add new format parser for Format X
fix(security): resolve path traversal vulnerability
docs(api): update API documentation for new methods
test(integration): add end-to-end workflow tests
Commit Types:
feat: New featuresfix: Bug fixesdocs: Documentation changestest: Test additions or modificationsrefactor: Code refactoringperf: Performance improvements
All code must pass:
- Black: Code formatting
- isort: Import sorting
- flake8: Linting and style checking
- mypy: Type checking
- pytest: Test suite (>95% coverage)
# Run all pre-commit checks
pre-commit run --all-files
# Individual checks
black --check preprimer/ tests/
isort --check-only preprimer/ tests/
flake8 preprimer/ tests/
mypy preprimer/ --ignore-missing-imports"""Module docstring describing purpose and functionality."""
import standard_library
import third_party_library
from preprimer.core import interfaces
from preprimer.core.security import PathValidator
logger = logging.getLogger(__name__)
class ExampleClass(interfaces.BaseInterface):
"""Class docstring describing purpose and usage.
Args:
param: Parameter description with type information
Returns:
Return value description with type information
Raises:
SpecificError: Description of when this error occurs
"""
def __init__(self, param: str) -> None:
"""Initialize with proper type hints."""
self._param = param
def public_method(self, input_data: str) -> bool:
"""Public method with comprehensive documentation."""
# Implementation with proper error handling
try:
result = self._private_method(input_data)
return result
except Exception as e:
logger.error(f"Error in public_method: {e}")
raise
def _private_method(self, data: str) -> bool:
"""Private method for internal operations."""
return bool(data)- Minimum Coverage: 95% line coverage
- Test Types: Unit, integration, property-based, security
- Error Handling: All exception paths tested
- Edge Cases: Boundary conditions validated
"""Test module following naming convention test_<module>.py"""
import pytest
from hypothesis import given, strategies as st
from preprimer.module import ClassUnderTest
from preprimer.core.exceptions import ExpectedError
class TestClassUnderTest:
"""Test class mirroring production class structure."""
def test_normal_operation(self):
"""Test normal operation with valid inputs."""
instance = ClassUnderTest("valid_input")
result = instance.process()
assert result.is_valid()
def test_error_handling(self):
"""Test proper error handling for invalid inputs."""
instance = ClassUnderTest("invalid_input")
with pytest.raises(ExpectedError, match="Expected error message"):
instance.process()
@given(st.text(min_size=1, max_size=100))
def test_property_based(self, random_text):
"""Property-based test with random inputs."""
instance = ClassUnderTest(random_text)
# Test invariant properties that should always hold
assert len(instance.get_processed()) >= 0
def test_integration_workflow(self, tmp_path):
"""Integration test with temporary files."""
test_file = tmp_path / "test_data.txt"
test_file.write_text("test content")
instance = ClassUnderTest(str(test_file))
result = instance.process_file()
assert result.success# Complete test suite
python -m pytest
# Specific test categories
python -m pytest tests/test_security.py -v
python -m pytest tests/test_integration.py -v
# Coverage report
python -m pytest --cov=preprimer --cov-report=html
# Performance benchmarks
python -m pytest tests/test_benchmarks.py --benchmark-only- Create Parser File:
preprimer/parsers/new_format_parser.py - Implement Interface:
from preprimer.core.standardized_parser import StandardizedParser
class NewFormatParser(StandardizedParser):
@classmethod
def format_name(cls) -> str:
return "new_format"
@classmethod
def file_extensions(cls) -> List[str]:
return [".new", ".nfmt"]
def validate_file(self, file_path: Union[str, Path]) -> bool:
# Format validation logic
def _parse_file_content(self, file_path: Path, prefix: str) -> Dict[str, AmpliconData]:
# Parsing implementation- Register Parser: Import in
preprimer/parsers/__init__.py - Add Tests: Create
tests/test_new_format_parser.py - Add Documentation: Update format documentation
- Create Writer File:
preprimer/writers/new_format_writer.py - Implement Interface:
from preprimer.core.interfaces import OutputWriter
class NewFormatWriter(OutputWriter):
@classmethod
def format_name(cls) -> str:
return "new_format"
def write(self, amplicons: List[AmpliconData], output_path: Path, **kwargs) -> Path:
# Writing implementation- Register Writer: Import in
preprimer/writers/__init__.py - Add Tests: Include in writer test suite
- Update Documentation: Document output format
All file operations must use security utilities:
from preprimer.core.security import PathValidator, InputValidator
# Always validate paths
safe_path = PathValidator.sanitize_path(user_input)
# Validate file content
validated_content = InputValidator.validate_file_content(content)
# Use secure file operations
with SecurityUtils.create_temp_file() as tmp_file:
# File operationsAdd security tests for new functionality:
def test_security_validation(self):
"""Test security validation for new functionality."""
# Test path traversal prevention
with pytest.raises(SecurityError):
NewClass.process_path("../../../etc/passwd")
# Test input size limits
with pytest.raises(SecurityError):
NewClass.process_content("x" * 1000000) # Too large- Module docstrings: Purpose and functionality
- Class docstrings: Usage and behavior
- Method docstrings: Parameters, returns, exceptions
- Type hints: All public interfaces
When adding new features, update:
- README.md: If user-facing changes
- User guides: For new CLI options or workflows
- API documentation: For new programmatic interfaces
- Architecture documentation: For structural changes
- Tests Pass: All 226 tests must pass
- Coverage Maintained: >95% coverage requirement
- Code Quality: All pre-commit checks pass
- Documentation: Relevant docs updated
- Performance: No significant performance regressions
## Description
Brief description of changes and motivation.
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
- [ ] Added tests for new functionality
- [ ] All existing tests pass
- [ ] Coverage maintained >95%
## Documentation
- [ ] Updated relevant documentation
- [ ] Added docstrings for new code
- [ ] Updated API documentation if needed
## Performance
- [ ] No performance regressions
- [ ] Added benchmarks if relevant- Automated Checks: CI/CD pipeline validation
- Code Review: Maintainer review for quality and design
- Testing: Comprehensive test validation
- Documentation Review: Documentation accuracy and completeness
- Approval: Maintainer approval required for merge
- Semantic Versioning: MAJOR.MINOR.PATCH format
- Version Updates: Update in
__init__.pyandpyproject.toml - Changelog: Maintain detailed changelog
- Version Bump: Update version numbers
- Changelog: Update with new features and fixes
- Tests: Full test suite validation
- Documentation: Update version-specific documentation
- Tag: Create git tag for release
- Build: Generate distribution packages
- Deploy: Release to package repositories
- Issues: GitHub issues for bugs and feature requests
- Discussions: GitHub discussions for questions
- Email: Project maintainers for security issues
- Architecture Guide: Understanding system design
- API Documentation: Programmatic interface reference
- User Guides: End-user functionality
- Testing Guide: Comprehensive testing information
- Environment Setup: Virtual environment configuration
- Dependency Conflicts: Package version management
- Test Failures: Debugging test issues
- Performance: Optimization strategies
- Respectful Communication: Professional and courteous interaction
- Constructive Feedback: Focus on code improvement, not personal criticism
- Collaboration: Willingness to help and learn from others
- Quality Focus: Commitment to high-quality code and documentation
- Personal attacks or harassment
- Discriminatory language or behavior
- Spam or off-topic contributions
- Violation of project guidelines
Report code of conduct violations to project maintainers through private communication channels.
Thank you for contributing to PrePrimer! Your contributions help improve primer scheme conversion for the scientific community.