Contributing to Recursivist¶
Thank you for your interest in contributing to Recursivist! This document provides guidelines and instructions for contributing to this project.
Table of Contents¶
- Code of Conduct
- Getting Started
- Setting Up Your Development Environment
- Development Workflow
- Creating a Branch
- Making Changes
- Testing Your Changes
- Submitting a Pull Request
- Coding Standards
- Code Style
- Documentation
- Type Annotations
- Testing
- Running Tests
- Writing Tests
- Bug Reports and Feature Requests
- Reporting Bugs
- Suggesting Features
- Release Process
- Community
Code of Conduct¶
By participating in this project, you agree to abide by our Code of Conduct. Please be respectful, inclusive, and considerate when interacting with other contributors.
Getting Started¶
Setting Up Your Development Environment¶
- Fork the repository:
-
Visit the Recursivist repository and click the "Fork" button to create your own copy.
-
Clone your fork:
- Install uv (used for all environment and dependency management):
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
- Create a virtual environment and install development dependencies:
- Install pre-commit hooks:
The pre-commit hooks will automatically run Ruff (lint + format) and mypy/pyright type checks on every commit.
Development Workflow¶
Creating a Branch¶
- Create a new branch for your feature or bugfix:
Making Changes¶
-
Make your changes to the codebase according to our coding standards.
-
Commit your changes with clear and descriptive commit messages:
Pre-commit hooks will run automatically on commit. If they flag issues, fix them and commit again.
- Keep your branch updated with the upstream repository by syncing your fork on GitHub and pulling locally:
Testing Your Changes¶
We use Nox as the task runner. All sessions run inside isolated uv-managed virtual environments.
- Run the full test suite across all supported Python versions:
- Run linting and type checks:
- Build and preview the documentation:
- Test the CLI to verify it works as expected:
Submitting a Pull Request¶
- Push your branch to your fork:
- Create a Pull Request from your fork to the main repository:
- Go to the Recursivist repository
- Click "Pull Requests" > "New Pull Request"
- Select "compare across forks" and choose your fork and branch
-
Click "Create Pull Request"
-
Describe your changes in the PR:
- What problem does it solve?
- How can it be tested?
-
Any dependencies or breaking changes?
-
Address review feedback if requested by maintainers.
Coding Standards¶
Code Style¶
We use Ruff for both linting and formatting. You can run it directly or via Nox:
Ruff is also run automatically by the pre-commit hooks on every commit.
Documentation¶
- Write docstrings for all public modules, functions, classes, and methods.
- Follow the Google docstring style as shown in existing code.
Example docstring:
def function(arg1: str, arg2: int) -> bool:
"""A short description of the function.
A more detailed description explaining the behavior, edge cases,
and implementation details if relevant.
Args:
arg1: Description of the first argument
arg2: Description of the second argument
Returns:
Description of the return value
Raises:
ValueError: When the input is invalid
"""
Type Annotations¶
All code must pass both mypy (strict mode) and pyright type checks. Use standard type hints:
def process_data(
data: dict[str, list[str]],
options: set[str] | None = None,
) -> bool:
return True
Run type checks via Nox:
This will run both mypy --strict and pyright against the codebase.
Testing¶
Running Tests¶
We use pytest via Nox. Coverage reporting is enabled by default (configured in pyproject.toml).
# Run tests across all supported Python versions (3.9–3.13)
nox -s tests
# Pass extra arguments to pytest (e.g. run a specific test)
nox -s tests -- -k test_something
# Run pytest directly in your active environment
pytest
Writing Tests¶
- Write tests for all new features and bug fixes.
- Place tests in the
tests/directory with a name matching the module being tested (e.g.tests/test_core.py). - Follow the test style used in existing tests.
Example test:
# tests/test_core.py
from recursivist.core import generate_color_for_extension
def test_generate_color_for_extension():
# Given
extension = ".py"
# When
color = generate_color_for_extension(extension)
# Then
assert isinstance(color, str)
assert color.startswith("#")
assert len(color) == 7
Bug Reports and Feature Requests¶
Reporting Bugs¶
Please report bugs by opening an issue on GitHub with the following information:
- A clear and descriptive title
- Steps to reproduce the issue
- Expected behavior
- Actual behavior
- Environment details (OS, Python version, etc.)
- Any relevant logs or screenshots
Suggesting Features¶
We welcome feature requests! Please open an issue with:
- A clear and descriptive title
- A detailed description of the proposed feature
- Any relevant examples or use cases
- Information about why this feature would be useful
Release Process¶
Releases are largely automated via GitHub Actions.
- Bump the version in
pyproject.toml:
- Commit and push to
main:
-
Automatic tagging: The
tag-releaseworkflow detects the version change inpyproject.toml, checks that the tag doesn't already exist, and creates and pushes the Git tag automatically. No manual tagging is required. -
Publish to PyPI (maintainers only):
Community¶
- GitHub Discussions Use this for questions and general discussion.
- Issues Bug reports and feature requests.
- Pull Requests Submit changes to the codebase.
Thank you for contributing to Recursivist! Your efforts help make this project better for everyone.