Skip to content

Development Guide

Contributing to DSPU development.

Getting Started

Fork and Clone

# Fork on GitHub
# Then clone your fork
git clone https://github.com/deepsaia/dspu.git
cd dspu

Development Setup

# Install uv (recommended)
curl -LsSf https://astral.sh/uv/install.sh | sh

# Create virtual environment and install dependencies
uv sync --all-extras

# Install pre-commit hooks
uv run pre-commit install

Project Structure

dspu/
├── src/
│   └── dspu/          # Main package
│       ├── core/          # Core utilities
│       ├── config/        # Configuration
│       ├── io/            # I/O operations
│       ├── aio/           # Async utilities
│       ├── validation/    # Data validation
│       ├── security/      # Security
│       ├── observability/ # Logging
│       └── ml/            # ML utilities
├── tests/
│   ├── unit/              # Unit tests
│   └── integration/       # Integration tests
├── docs/                  # Documentation
├── examples/              # Example code
└── pyproject.toml         # Project config

Development Workflow

Create a Branch

# Create feature branch
git checkout -b feature/my-feature

# Or bug fix branch
git checkout -b fix/my-fix

Make Changes

  1. Write code
  2. Add tests
  3. Update documentation
  4. Run linters and tests

Run Tests

# Run all tests
uv run pytest

# Run specific module
uv run pytest tests/unit/config/

# Run with coverage
uv run pytest --cov=src/dspu --cov-report=html

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

Run Linters

# Run all checks
uv run ruff check .
uv run ruff format --check .
uv run pyrefly check src

# Auto-fix issues
uv run ruff check --fix .
uv run ruff format .

Pre-commit Hooks

# Hooks run automatically on commit
git commit -m "feat: add new feature"

# Run manually
uv run pre-commit run --all-files

Adding New Features

1. Create Module

# src/dspu/mymodule/__init__.py
"""My new module."""

from .core import MyClass

__all__ = ["MyClass"]

2. Write Tests

# tests/unit/mymodule/test_core.py
import pytest
from dspu.mymodule import MyClass

def test_my_class():
    """Test MyClass functionality."""
    obj = MyClass()
    assert obj.method() == expected

3. Add Documentation

# docs/api/mymodule.md
# My Module API Reference

::: dspu.mymodule.MyClass

4. Add Examples

# examples/mymodule/01_basic.py
"""Basic usage of my module."""

from dspu.mymodule import MyClass

# Example usage
obj = MyClass()
result = obj.method()
print(result)

Testing Guidelines

Unit Tests

  • Test individual functions/classes in isolation
  • Mock external dependencies
  • Fast execution (< 1ms per test)
  • Use pytest fixtures
import pytest
from unittest.mock import Mock

@pytest.fixture
def mock_client():
    return Mock()

def test_function(mock_client):
    result = my_function(mock_client)
    assert result == expected

Integration Tests

  • Test interactions between components
  • Use real dependencies when possible
  • Mark as slow tests
import pytest

@pytest.mark.slow
@pytest.mark.integration
async def test_full_pipeline():
    # Test complete workflow
    ...

Test Coverage

Maintain > 90% coverage:

# Check coverage
uv run pytest --cov=src/dspu --cov-report=term-missing

# Generate HTML report
uv run pytest --cov=src/dspu --cov-report=html
open htmlcov/index.html

Documentation

Docstrings

Use Google style:

def my_function(arg1: str, arg2: int) -> bool:
    """Short description.

    Longer description explaining the function's purpose
    and behavior.

    Args:
        arg1: Description of arg1
        arg2: Description of arg2

    Returns:
        Description of return value

    Raises:
        ValueError: When arg1 is invalid

    Example:
        >>> my_function("test", 42)
        True
    """
    ...

API Documentation

Use mkdocstrings syntax:

::: dspu.module.Class
    options:
      show_source: true
      members:
        - method1
        - method2

Building Docs

# Install dependencies
uv sync --group docs

# Serve locally
uv run mkdocs serve

# Build
uv run mkdocs build

Code Style

Formatting

  • Use Ruff for formatting
  • Line length: 100 characters
  • Use type hints everywhere
from typing import Optional

def process_data(
    data: list[dict],
    filter_fn: Optional[callable] = None,
) -> list[dict]:
    """Process data with optional filtering."""
    ...

Naming Conventions

  • Classes: PascalCase
  • Functions: snake_case
  • Constants: UPPER_SNAKE_CASE
  • Private: _leading_underscore

Imports

Sort imports with ruff:

# Standard library
import os
from pathlib import Path

# Third-party
import httpx
from pydantic import BaseModel

# Local
from dspu.core import Registry

Pull Request Process

1. Update Your Branch

git fetch upstream
git rebase upstream/main

2. Run All Checks

# Tests
uv run pytest

# Linters
uv run ruff check .
uv run ruff format .
uv run pyrefly check src

# Docs
uv run mkdocs build

3. Commit Changes

Follow Conventional Commits:

# Feature
git commit -m "feat: add new validation filter"

# Fix
git commit -m "fix: handle empty list in scaler"

# Docs
git commit -m "docs: update configuration guide"

# Tests
git commit -m "test: add tests for ML module"

# Refactor
git commit -m "refactor: simplify storage backend"

4. Push and Create PR

git push origin feature/my-feature

Create PR on GitHub with: - Clear title following conventional commits - Description of changes - Related issues - Testing done

5. Code Review

  • Address review comments
  • Keep commits organized
  • Update documentation if needed

6. Merge

After approval, squash and merge.

Release Process

Version Bump

# Update version in pyproject.toml
# Update CHANGELOG.md

git commit -m "chore: bump version to 1.2.0"
git tag v1.2.0
git push origin main --tags

Build and Publish

# Build package
uv build

# Publish to PyPI
uv publish

Getting Help

Code of Conduct

Be respectful, inclusive, and professional. See CODE_OF_CONDUCT.md.