Contributing to kstlib

Thank you for your interest in contributing to kstlib! 🎉

🤝 Code of Conduct

Be respectful, inclusive, and professional. We’re all here to learn and improve kstlib together.

🚀 Getting Started

Prerequisites

  • Python 3.10+

  • Git

  • uv (recommended) or pip

  • Familiarity with pytest, Ruff, and mypy

Fork and Clone

  1. Fork the repository on GitHub

  2. Clone your fork locally:

    git clone https://github.com/KaminoU/kstlib.git
    cd kstlib
    

🛠️ Development Setup

2. Create a virtual environment

# Using uv (recommended - faster)
uv venv
source .venv/bin/activate  # On Windows: .venv\Scripts\activate

# Or using venv
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Or using conda
conda create -n kstlib_dev python=3.10
conda activate kstlib_dev

Optional: Windows hardening (OneDrive users)

If you develop on Windows with OneDrive (or any other folder-sync tool) syncing your project folder, placing .venv directly inside the synced folder can cause issues:

  • SSD saturation when sync replicates thousands of small files (binaries, dist-info, packages) in the venv

  • Windows file locks during uv sync / uv run that may fail partially when sync, antivirus, or IDE holds files open

  • Slow startup because the sync engine traverses the venv on every project open

To avoid this, host the venv outside the synced folder and point uv at it via the UV_PROJECT_ENVIRONMENT environment variable (session isolation: defined explicitly per terminal session, never persisted globally):

# 1. One-time setup: create the venv outside OneDrive
mkdir -Force C:\dev\uvenv\kstlib
uv venv --python 3.10 C:\dev\uvenv\kstlib\py310

# 2. Per-session isolation: point uv at the off-OneDrive venv (before uv run, uv sync, etc.)
$env:UV_PROJECT_ENVIRONMENT = "C:\dev\uvenv\kstlib\py310"

# 3. Verify
uv run python -c "import sys; print(sys.executable)"
# Expected: a path under C:\dev\uvenv\kstlib\py310 (outside the synced folder)

# 4. Install dependencies + pre-commit hook
uv sync --all-extras
uv run pre-commit install

Note: UV_PROJECT_ENVIRONMENT is set per-session for explicit isolation (not persisted to setx, not in a .env file, not in $PROFILE). Define it explicitly each time you open a new terminal for kstlib work. This is intentional: zero global pollution, no versioned secret leak, and the absence triggers an explicit error rather than a silent fallback to the OneDrive-synced location.

Symlink-based approaches are NOT recommended: OneDrive (and most folder-sync tools) traverse symbolic links and sync the target content anyway, defeating the purpose. The session-isolated environment variable approach is the only reliable workaround.

3. Install in development mode

Alternative: Dynamic resolution (no guarantees)

pip install -e .[dev]

This resolves dependencies at install time. Acceptable for quick local experiments, but offers no supply chain verification. If tests pass locally but fail in CI, dependency version drift is a likely cause.

4. Verify setup

# Run tests
pytest

# Check linting
ruff check .

# Check formatting
ruff format --check .

# Check types
mypy src/

5. Install pre-commit hooks

pre-commit install

Pre-commit hooks run automatically on each git commit to check:

  • Lockfile is up to date (uv lock --check)

  • Code formatting (ruff format --check)

  • Linting (ruff check)

You can also run them manually:

# Run all hooks on all files
pre-commit run --all-files

# Run full tox suite (manual stage)
pre-commit run tox --hook-stage manual

✏️ Making Changes

1. Create a branch

git checkout main
git pull origin main
git checkout -b feature/your-feature-name

Branch naming conventions:

  • feature/ - New features

  • fix/ - Bug fixes

  • docs/ - Documentation updates

  • refactor/ - Code refactoring

  • test/ - Test additions/updates

2. Make your changes

  • Follow the Code Style guidelines

  • Add tests for new features

  • Update documentation as needed

  • Keep commits atomic and well-described

3. Commit your changes

git add .
git commit -m "feat: add awesome feature

- Implement feature X
- Add tests for feature X
- Update documentation"

Commit message format:

<type>: <short description>

<detailed description>
<list of changes>

Types: feat, fix, docs, refactor, test, chore

🔐 Security Notes

Supply Chain

  • Always use lockfile installation (uv pip sync pylock.toml) when running tests or deploying. This ensures SHA256-verified, reproducible builds.

  • We use PEP 751 standard format (pylock.toml) for future pip interoperability.

  • If you add or update dependencies, regenerate the lockfile:

    uv lock && uv export --format pylock.toml --all-extras -o pylock.toml
    
  • Never commit a lockfile without verifying tests pass with tox (full matrix).

Code Security

  • Leave the JSON serializer as the default for FileCacheStrategy. Discuss any change to pickle/auto defaults with maintainers before submitting a PR.

  • Reuse the provided email validators and placeholder helpers; do not bypass the sanitisation they provide when composing messages or formatting logs.

  • When touching the SOPS provider, keep stderr redaction intact and add tests to cover the expected [REDACTED] markers in tests/secrets/test_providers.py.

  • New code that handles secrets must include tests and docs describing the threat model, and must pass ruff, mypy --strict src and pytest --cov before review.

🧪 Testing

Run all tests

pytest

Run with coverage

pytest --cov=src --cov-report=term --cov-report=html

Run specific tests

# Test a specific file
pytest tests/config/test_loader.py

# Test a specific function
pytest tests/config/test_loader.py::test_load_config_basic

# Run only fast tests
pytest -m "not slow"

Test guidelines

  • Aim for 95%+ coverage

  • Test edge cases and error conditions

  • Use descriptive test names: test_<what>_<condition>_<expected>

  • Use pytest fixtures for setup/teardown

  • Mock external dependencies

Test across Python versions with tox

Before submitting your PR, ensure tests pass on all supported Python versions (3.10-3.14):

# Install tox with uv support (10-100x faster than pip)
pip install tox tox-uv

# Run tests on all Python versions
tox

# Run only linting checks
tox -e lint

# Run on specific Python version
tox -e py311

Note: tox is configured to use uv for dependency installation, making test environment creation significantly faster. CI will automatically test on Python 3.10, 3.11, 3.12, 3.13, and 3.14 across Windows, macOS, and Linux.

📤 Submitting Changes

1. Push your branch

git push origin feature/your-feature-name

2. Create a Pull Request

  • Go to GitHub and create a PR from your branch to main

  • Fill out the PR template completely

  • Link related issues with Closes #123 or Fixes #456

  • Wait for CI checks to pass

  • Request review from maintainers

3. Address review feedback

  • Make requested changes

  • Push updates to your branch

  • Respond to review comments

  • Keep the PR up-to-date with main branch

🎨 Code Style

Python Style

We use Ruff for linting and formatting:

# Format code
ruff format .

# Check linting
ruff check .

# Auto-fix issues
ruff check --fix .

Type Hints

All public functions must have type hints:

def load_config(file_path: str, strict: bool = False) -> Box:
    """Load configuration from file."""
    ...

Docstrings

Use Google style docstrings:

def example_function(param1: str, param2: int = 0) -> bool:
    """Short description.

    Longer description if needed.

    Args:
        param1: Description of param1
        param2: Description of param2 (default: 0)

    Returns:
        Description of return value

    Raises:
        ValueError: Description of when this is raised

    Examples:
        Basic usage::

            result = example_function("test", 42)
            assert result is True
    """
    ...

Code Conventions

  • Line length: 100 characters max

  • Imports: Always use absolute imports (from kstlib...). Ruff will keep them sorted and grouped automatically.

  • Naming:

    • snake_case for functions and variables

    • PascalCase for classes

    • UPPER_SNAKE_CASE for constants

    • _prefix for private/internal

🐛 Reporting Bugs

Use the Bug Report template and include:

  • OS and Python version

  • kstlib version

  • Steps to reproduce

  • Expected vs actual behavior

  • Error messages/logs

💡 Suggesting Features

Use the Feature Request template and include:

  • Use case description

  • Proposed solution

  • Alternative solutions considered

  • Examples/mockups

📚 Documentation

  • Update docstrings for code changes

  • Update Sphinx docs in docs/source/ if needed

  • Add examples in examples/ for new features

  • Update CHANGELOG.md with your changes

❓ Questions?

  • Open a Discussion

  • Ask in issues with the question label

🎯 Development Workflow Summary

  1. Fork and clone the repository

  2. Create a branch from main

  3. Make changes following code style

  4. Add tests (95%+ coverage)

  5. Run ruff format ., ruff check ., mypy src/, pytest

  6. Commit with descriptive messages

  7. Push and create PR to main

  8. Address review feedback

  9. Merge when approved! 🎉


Thank you for contributing to kstlib! 🚀