Developer Tutorial: Contributing to Structum

[!NOTE] This guide walks you from setting up your development environment to actively contributing to the project.


Prerequisites

  • Python 3.11+

  • Git

  • uv - Installation

  • Editor with Python support (VS Code, PyCharm)


Part 1: Development Environment Setup

Step 1.1: Fork and Clone

# 1. Fork on GitHub: github.com/PythonWoods/structum
# 2. Clone your fork
git clone https://github.com/YOUR-USERNAME/structum.git
cd structum

# 3. Add upstream
git remote add upstream https://github.com/PythonWoods/structum.git

Step 1.2: Install Dependencies

uv sync --extra dev

This installs:

  • All packages in editable mode (packages/*)

  • Tools: pytest, mypy, ruff, black

  • Pre-commit hooks

Step 1.3: Configure Pre-commit

pre-commit install

Step 1.4: Verify Setup

# Test suite
pytest

# Type checking
mypy packages/core/src

# Linting
ruff check packages/

# Formatting
black --check packages/

Part 2: Project Structure

structum/
├── packages/                    # Distributable packages
│   ├── core/                    # structum-core (zero deps)
│   │   ├── src/structum/        # Base namespace
│   │   │   ├── config/          # Config interfaces
│   │   │   ├── logging/         # Logging interfaces
│   │   │   └── auth/            # Auth interfaces
│   │   └── tests/
│   │
│   ├── dynaconf/                # structum-dynaconf
│   │   └── src/structum/plugins/dynaconf/
│   │
│   ├── bootstrap/               # structum-bootstrap
│   ├── auth/                    # structum-auth
│   ├── database/                # structum-database
│   ├── di/                      # structum-di
│   ├── observability/           # structum-observability
│   └── meta/                    # structum (meta-package)
│
├── docs/                        # MkDocs documentation
├── demo/                        # Working examples
└── pyproject.toml               # Workspace root

2.1: Understanding Namespaces

Structum uses PEP 420 namespace packages:

# Core: interfaces in structum.*
from structum.config import ConfigProviderInterface

# Plugins: implementations in structum.plugins.*
from structum.plugins.dynaconf import DynaconfConfigProvider

Part 3: Development Workflow

Step 3.1: Create a Branch

git checkout -b feature/my-feature

Step 3.2: Make Changes

# Edit files
code packages/core/src/structum/config/interface.py

Step 3.3: Run Local Tests

# Test the specific package
pytest packages/core/tests -v

# Test with coverage
pytest packages/core/tests --cov=structum --cov-report=term-missing

Step 3.4: Type Check

# Check the modified package
mypy packages/core/src/structum

# Full check
mypy packages/*/src

Step 3.5: Commit

git add .
git commit -m "feat(core): add new feature X

- Added X functionality
- Updated tests
- Updated documentation"

Step 3.6: Push and PR

git push origin feature/my-feature
# Open PR on GitHub

Part 4: Code Analysis

4.1: Exploring Core Interfaces

# View main interfaces
cat packages/core/src/structum/config/interface.py

Key points:

  • ConfigProviderInterface: protocol for config providers

  • get_config(): global accessor

  • set_config_provider(): register implementation

4.2: Exploring a Plugin

# Plugin structure
ls packages/dynaconf/src/structum/plugins/dynaconf/

Typical pattern:

  1. __init__.py - public exports

  2. provider.py - main implementation

  3. models.py - Pydantic models (if used)

  4. exceptions.py - custom exceptions

4.3: Debugging with pytest

# Run with verbose output
pytest packages/core/tests -v -s

# Run a single test
pytest packages/core/tests/test_config.py::test_get_config -v

# With debugger
pytest packages/core/tests --pdb

Part 5: Types of Contributions

5.1: Bug Fix

  1. Create issue on GitHub describing the bug

  2. Create branch fix/issue-123

  3. Write test that reproduces the bug

  4. Implement fix

  5. Verify test passes

  6. Open PR with issue reference

5.2: New Feature

  1. Discuss feature via issue/discussion

  2. Create branch feature/feature-name

  3. Implement with tests

  4. Update documentation

  5. Open PR

5.3: Documentation Improvements

  1. Fork and modify files in docs/

  2. Local preview: mkdocs serve

  3. Open PR


Part 6: Code Conventions

6.1: Python Style

# ✅ Correct
from typing import Protocol

class MyInterface(Protocol):
    """Interface description."""
    
    def method(self, arg: str) -> bool:
        """Method description.
        
        Args:
            arg: Argument description
            
        Returns:
            True if successful
        """
        ...

# ❌ Avoid
def method(arg):  # No type hints
    pass  # No docstring

6.2: Commit Messages

type(scope): short description

- Detailed change 1
- Detailed change 2

Fixes #123

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


Part 7: Resources