Thank you for your interest in contributing to verso! This document provides guidelines and information for contributors.
# clone the repository
git clone https://github.com/example/verso.git
cd verso
# install with uv (recommended)
uv sync --all-extras
# or with pip
pip install -e ".[dev]"# run tests
uv run pytest tests/ -v
# or with just
just test# all tests
just test
# with coverage
just test-cov
# specific test file
just test-file tests/test_schema.py
# tests matching pattern
just test-match "test_heading"# lint
just lint
# fix lint issues
just lint-fix
# format code
just fmt
# type check
just typecheck
# run all checks
just checkWe recommend using pre-commit hooks:
just pre-commit-install- Follow PEP 8
- Use type hints for all public functions
- Maximum line length: 88 characters (enforced by ruff)
- Use double quotes for strings
- Sort imports with isort (via ruff)
Use Google-style docstrings:
def extract(source: str, config: Config | None = None) -> Document:
"""Extract content from a document.
Args:
source: Path to the document file.
config: Optional configuration object.
Returns:
Document object containing extracted content.
Raises:
ValueError: If the file format is not supported.
"""Use conventional commits:
feat:new featurefix:bug fixdocs:documentation changestest:test changesrefactor:code refactoringperf:performance improvementchore:maintenance tasks
Examples:
feat: add support for EPUB format
fix: correct heading detection for small fonts
docs: update API reference
test: add tests for list detection
verso/
├── src/verso/ # main package
│ ├── __init__.py # public API
│ ├── cli.py # command-line interface
│ ├── config.py # configuration
│ ├── schema.py # data structures
│ ├── structure.py # structure detection
│ ├── pipeline.py # processing pipeline
│ ├── analyzer.py # document analysis
│ ├── detect.py # format detection
│ ├── mcp_server.py # MCP server
│ ├── providers/ # document providers
│ │ ├── pdf.py # pdftext backend
│ │ ├── pdf_mupdf.py # MuPDF backend
│ │ └── ...
│ ├── processors/ # content processors
│ ├── renderers/ # output renderers
│ └── backends/ # compute backends
├── tests/ # test files
├── scripts/ # utility scripts
├── research/ # research documents
└── docs/ # documentation
- Create
src/verso/providers/your_provider.py - Implement
BaseProviderinterface - Add format detection in
src/verso/detect.py - Register in
src/verso/providers/__init__.py - Add tests in
tests/test_your_provider.py
- Create processor in
src/verso/processors/ - Implement
BaseProcessorinterface - Integrate into pipeline
- Add tests
- Create renderer in
src/verso/renderers/ - Implement
BaseRendererinterface - Add output format option
- Add tests
class TestFeatureName:
def test_basic_case(self):
"""Test the most common use case."""
...
def test_edge_case(self):
"""Test edge cases."""
...
def test_error_handling(self):
"""Test error conditions."""
...- Use fixtures for common test data
- Keep test PDFs small (<100KB)
- Use tempfile for generated files
- Clean up resources in teardown
@pytest.mark.slow # slow tests
@pytest.mark.integration # integration tests- Fork the repository
- Create a feature branch from
main - Make your changes
- Ensure all tests pass:
just check - Update documentation if needed
- Update CHANGELOG.md
- Submit pull request
- Tests pass locally
- Code is formatted and linted
- Type hints are complete
- Docstrings are updated
- CHANGELOG.md is updated
- No breaking changes (or documented)
Releases are automated via GitHub Actions:
- Update version in
src/verso/__init__.py - Update CHANGELOG.md
- Create a GitHub release
- CI publishes to PyPI
- Open an issue for bugs or feature requests
- Start a discussion for questions
- Check existing issues before creating new ones
Be respectful and inclusive. We follow the Contributor Covenant.
By contributing, you agree that your contributions will be licensed under the MIT License.