Contributing#
Guidelines for contributing to titanite.
Development Workflow#
1. Create a Worktree#
Use git worktree to work on isolated branches:
# Create worktree for feature branch
git worktree add ../worktrees/feature-name -b feature-name
cd ../worktrees/feature-name
2. Setup Environment#
# Set up development environment
task env:setup
# Install pre-commit hooks
poetry run pre-commit install
3. Make Changes#
Create your implementation following code style guidelines.
4. Run Quality Checks#
Before committing, run all checks:
# Run tests
task test
# Format code
task format
# Lint code
task lint
# Run pre-commit hooks
task pre-commit
All checks must pass before committing.
5. Commit Changes#
Use conventional commits with clear messages:
git add <files>
git commit -m "type(scope): description"
Valid types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
Examples:
feat(cli): add new command for data exportfix(processor): handle missing values in binningdocs(guide): improve plugin development documentationtest(schema): add tests for geographic splitting
6. Push and Create PR#
git push origin feature-name
gh pr create --title "Feature description" --body "Detailed description"
Reference related issues:
Closes #123
7. Cleanup#
After PR is merged:
cd ../../surveys
git fetch --prune
git pull
git worktree remove ../worktrees/feature-name
Code Style#
Python#
Follow PEP 8 conventions:
Use
snake_casefor variables and functionsUse
PascalCasefor classesLine length: 100 characters (enforced by ruff)
Use type hints where helpful
Naming conventions:
# Functions and variables
def process_data():
survey_responses = []
return survey_responses
# Classes
class SurveySchema:
pass
# Constants
MAX_RESPONSES = 1000
Code Organization#
Imports - Group and sort:
# Standard library
import os
from pathlib import Path
# Third-party
import pandas as pd
import numpy as np
# Local
from titanite.core import SurveySchema
from titanite.analysis import chi2_test
Functions - Keep focused and short:
# Good - Clear purpose, <50 lines
def replace_values(df: pd.DataFrame, rules: dict) -> pd.DataFrame:
"""Replace values in DataFrame according to rules."""
result = df.copy()
for column, replacements in rules.items():
result[column] = result[column].replace(replacements)
return result
# Avoid - Too complex
def process_everything(df, rules, splits, clusters):
# 200 lines of mixed logic
pass
Documentation#
Docstrings - Use Google style:
def split_column(df: pd.DataFrame, column: str, delimiter: str) -> pd.DataFrame:
"""
Split a composite column into multiple columns.
Args:
df: Input DataFrame
column: Column name to split
delimiter: String delimiter separating values
Returns:
DataFrame with split columns
Example:
>>> df = pd.DataFrame({"location": ["USA - California"]})
>>> split_column(df, "location", " - ")
# Returns: df with ["country", "state"] columns
"""
pass
Comments - Only for non-obvious logic:
# Good - Explains why
# Use majority vote for gender clustering because single response
# may not represent full gender identity
result = majority_vote(gender_columns)
# Bad - Explains what (already clear from code)
# Loop through each row
for idx, row in df.iterrows():
pass
Type Hints#
Use type hints for clarity:
# Good
def process(data: pd.DataFrame) -> pd.DataFrame:
pass
# Good - Complex types
from typing import list
def get_columns(df: pd.DataFrame, types: list[str]) -> list[str]:
pass
# Avoid - No hints
def process(data):
pass
Testing Requirements#
All new code must include tests:
Unit tests - Test individual functions
Integration tests - Test with real data
Coverage - Maintain >80% code coverage
# Write tests in tests/test_new_feature.py
poetry run pytest tests/test_new_feature.py -v
# Check coverage
poetry run pytest --cov=titanite tests/
See Testing for detailed guidelines.
PR Review Process#
Before Submitting#
Ensure your PR:
Passes all tests (
task test)Follows code style (
task format,task lint)Has clear commit messages (conventional commits)
Includes relevant tests
Updates documentation if needed
References related issues
Review Checklist#
Reviewers will check:
Functionality - Does it work as intended?
Testing - Are there adequate tests?
Code quality - Does it follow style guidelines?
Documentation - Are changes documented?
Performance - No obvious performance issues?
Security - No security vulnerabilities?
Common Contributions#
Adding a New Command#
Implement command in
titanite/cli.pyAdd logic in
titanite/analysis.pyortitanite/core.pyWrite tests in
tests/test_cli.pyUpdate docs in
docs/guides/user/cli-commands.md
Example:
# titanite/cli.py
@click.command()
def my_command():
"""Description of what command does."""
pass
# tests/test_cli.py
def test_my_command(runner):
result = runner.invoke(my_command)
assert result.exit_code == 0
# docs/guides/user/cli-commands.md
### `ti my-command`
Description and usage examples...
Creating a New Plugin#
Create plugin directory -
plugins/your_survey/Implement schema - Inherit from
SurveySchemaWrite tests - In
tests/test_your_survey_schema.pyDocument - In
docs/guides/developer/plugin-development.md
See Plugin Development for detailed guide.
Fixing a Bug#
Create issue if one doesn’t exist
Write failing test that reproduces bug
Implement fix
Verify test passes
Create PR referencing issue
Commit message:
fix(scope): brief description
Closes #123
Detailed explanation of what was wrong and how it was fixed.
Documentation Improvements#
Improve docs by:
Clarifying existing docs
Adding examples
Fixing typos/grammar
Adding missing sections
Docs are in docs/guides/, use Markdown format.
Release Process#
Releases follow semantic versioning:
# Check what needs updating
task deps:check
# Update if needed
task deps:update
# Commit and tag
poetry run cz bump --changelog --check-consistency
git push origin --tags
Getting Help#
Questions: Open an issue or discussion
Bug reports: Create issue with reproduction steps
Feature requests: Open issue with use case
PR feedback: Ask reviewers for clarification
Communication#
Commit Messages#
Be clear and descriptive:
# Good
feat(plugin): add support for custom survey schema with clustering rules
# Bad
update stuff
fix things
add feature
PR Descriptions#
Include:
What - What changes are made?
Why - Why are these changes needed?
How - How do the changes work?
Testing - How was this tested?
Template:
## Summary
Brief description of changes.
## Changes
- Bullet points of specific changes
- Changed X to improve Y
- Added tests for Z
## Testing
How was this tested?
- [ ] Unit tests pass
- [ ] Integration tests pass
- [ ] Manual testing (describe)
Closes #123
Repository Structure#
├── titanite/ # Main package
├── plugins/ # Survey plugins
├── tests/ # Test suite
├── docs/ # Documentation
├── notebooks/ # Jupyter notebooks
├── data/ # Data files
├── sandbox/ # CLI working directory
├── Taskfile.yml # Task automation
├── pyproject.toml # Project configuration
└── CLAUDE.md # Developer guide
Useful Commands#
# Setup
task env:setup
poetry run pre-commit install
# Development
task test # Run tests
task format # Format code
task lint # Lint code
task pre-commit # Run pre-commit checks
# Documentation
task docs:serve # Serve docs locally
task docs:build # Build docs
# Utilities
task version # Check version
task deps:check # Check outdated packages
task deps:update # Update dependencies
Code Review Expectations#
Respond to feedback promptly
Be respectful and constructive
Ask questions if feedback is unclear
Acknowledge good suggestions even if you don’t implement them
Acknowledgment#
All contributors are recognized in:
Git commit history
GitHub contributors page
Release notes (for significant contributions)
Thank you for contributing!