webdrop-bridge/CONTRIBUTING.md

10 KiB

Contributing to WebDrop Bridge

Thank you for your interest in contributing! This document provides guidelines and instructions for contributing to the WebDrop Bridge project.

Code of Conduct

Please be respectful and constructive in all interactions. We're building a welcoming community for developers of all experience levels.

Getting Started

Prerequisites

  • Python 3.10+
  • Git
  • Familiarity with Qt/PySide6 or willingness to learn

Setup Development Environment

# Fork and clone the repository
git clone https://github.com/yourusername/webdrop-bridge.git
cd webdrop-bridge

# Create virtual environment
python -m venv venv
source venv/bin/activate  # macOS/Linux
# venv\Scripts\activate  # Windows

# Install development dependencies
pip install -r requirements-dev.txt

# Install pre-commit hooks (optional)
pip install pre-commit
pre-commit install

Development Workflow

1. Create a Feature Branch

git checkout -b feature/your-feature-name

Use descriptive names:

  • feature/drag-performance-optimization
  • bugfix/path-validation-windows
  • docs/add-architecture-guide

2. Write Tests First (TDD)

# Create test file
touch tests/unit/test_my_feature.py

# Write failing tests
pytest tests/unit/test_my_feature.py

# Implement feature
# Re-run tests until passing

3. Implement Your Feature

# Follow the project structure
src/webdrop_bridge/
├── core/       # Core logic
├── ui/         # UI components
└── utils/      # Utilities

4. Code Quality Checks

# Format code
tox -e format

# Run linting
tox -e lint

# Type checking
tox -e type

# Full test suite
pytest --cov

# All checks
tox

5. Write Documentation

  • Add docstrings to all functions/classes
  • Update README.md if adding features
  • Add examples for new APIs

6. Commit and Push

# Commit with meaningful message
git commit -m "feat: add feature description

- Detailed explanation of changes
- Bullet points for key changes
- References to related issues"

# Push to your fork
git push origin feature/your-feature-name

7. Submit Pull Request

  • Use clear, descriptive title
  • Reference related issues (#123)
  • Describe changes and testing approach
  • Include screenshots/videos if UI-related

Code Style

Python Style Guide

Follow PEP 8, enforced by Black and Ruff:

# Good
def validate_path(path: Path, allowed_roots: List[Path]) -> bool:
    """Validate path against allowed roots."""
    resolved = path.resolve()
    return any(is_relative_to(resolved, root) for root in allowed_roots)


# Bad
def validate_path(path,allowed_roots):
    resolved=path.resolve()
    return any(is_relative_to(resolved,root)for root in allowed_roots)

Type Hints

Always use type hints:

from typing import Optional, List
from pathlib import Path

def process_files(files: List[Path], validate: bool = True) -> Optional[int]:
    """Process a list of files."""
    pass

Docstrings

Use Google-style docstrings:

def validate_path(path: Path, allowed_roots: List[Path]) -> bool:
    """Validate that path is within allowed roots.
    
    Args:
        path: File path to validate
        allowed_roots: List of allowed root directories
        
    Returns:
        True if path is valid, False otherwise
        
    Raises:
        ValueError: If path cannot be resolved
    """

Testing Guidelines

Unit Tests

Test individual functions/classes in isolation:

# tests/unit/test_validator.py
import pytest
from webdrop_bridge.core.validator import PathValidator
from pathlib import Path

@pytest.fixture
def validator():
    allowed_roots = [Path("C:/Users/Public")]
    return PathValidator(allowed_roots)

def test_valid_path(validator):
    """Test that valid paths are accepted."""
    path = Path("C:/Users/Public/Documents/file.txt")
    assert validator.is_allowed(path)

def test_invalid_path(validator):
    """Test that invalid paths are rejected."""
    path = Path("C:/Windows/System32/file.txt")
    assert not validator.is_allowed(path)

Integration Tests

Test components working together:

# tests/integration/test_drag_workflow.py
def test_complete_drag_workflow(temp_test_dir):
    """Test complete drag-and-drop workflow."""
    # Setup
    test_file = temp_test_dir / "test.txt"
    test_file.write_text("content")
    
    # Execute
    validator = PathValidator([temp_test_dir])
    result = validator.is_valid_file(test_file)
    
    # Verify
    assert result is True

Test Coverage

  • Aim for 80%+ code coverage
  • All public APIs must have tests
  • Test both happy path and error cases
# Check coverage
pytest --cov=src/webdrop_bridge --cov-report=html

# View detailed report
open htmlcov/index.html  # macOS
start htmlcov\index.html # Windows

Platform-Specific Development

Windows

# For Windows-specific tests
pytest -m windows

# Build Windows installer
python build/scripts/build_windows.py

macOS

# For macOS-specific tests
pytest -m macos

# Build macOS DMG
bash build/scripts/build_macos.sh

Common Issues

Import Errors

Ensure project is in PYTHONPATH:

export PYTHONPATH="${PYTHONPATH}:$(pwd)/src"  # macOS/Linux
set PYTHONPATH=%PYTHONPATH%;%cd%\src  # Windows

Or install in development mode:

pip install -e .

PySide6 Installation Issues

# Force reinstall
pip install --force-reinstall --no-cache-dir PySide6

# On macOS with Apple Silicon
pip install PySide6 --target $PYTHON_ENV

Test Failures in CI but Not Locally

  • Check Python version: python --version
  • Verify all dependencies: pip list
  • Clear cache: rm -rf .pytest_cache build/
  • Try clean venv: rm -rf venv && python -m venv venv

Documentation

API Documentation

Docstrings are automatically converted to HTML:

tox -e docs

# View documentation
open docs/_build/html/index.html  # macOS
start docs\_build\html\index.html # Windows

Writing Documentation

  • Use Markdown for guides
  • Include code examples
  • Add screenshots for UI features
  • Keep language clear and concise

Writing Integration Tests

Integration tests should cover workflows across multiple components. See tests/integration/test_update_flow.py for an example covering the update system.

Release Process

Versioning & Release Process

Version Management

WebDrop Bridge uses semantic versioning (MAJOR.MINOR.PATCH). The version is centralized in one location:

Single Source of Truth: src/webdrop_bridge/__init__.py

__version__ = "1.0.0"

Shared Version Utility: build/scripts/version_utils.py

All build scripts and version management tools use a shared utility to read the version from __init__.py, ensuring consistency across:

  • pyproject.toml - Reads dynamically at build time
  • config.py - Reads dynamically at startup
  • .env.example - Updated by sync script (optional)
  • CHANGELOG.md - Updated by sync script

Releasing a New Version

Step 1: Update the Version (Only Place to Edit)

Edit src/webdrop_bridge/__init__.py and change __version__:

__version__ = "1.2.0"  # Change this to your new version

Step 2: Sync Version to Changelog

Run the sync script to update the changelog:

python scripts/sync_version.py

Or let the build script do it automatically:

# Windows
python build/scripts/build_windows.py

# macOS
bash build/scripts/build_macos.sh

Both the build script and sync script use the shared build/scripts/version_utils.py utility.

Step 3: Update CHANGELOG.md Manually (Content Only)

The sync script adds the version header with the date. Now add your changes under each section:

## [1.2.0] - 2026-01-15

### Added
- New feature description

### Changed
- Breaking change description

### Fixed
- Bug fix description

Step 4: Commit and Tag

git add -A
git commit -m "chore: release v1.2.0

- Feature 1 details
- Feature 2 details"

git tag -a v1.2.0 -m "Release version 1.2.0"
git push origin main --tags

Manual Version Sync (If Needed)

If you need to sync versions without building:

python scripts/sync_version.py

To set a specific version:

python scripts/sync_version.py --version 1.2.0

Querying Version in Code

Always import from the package:

from webdrop_bridge import __version__

print(__version__)  # "1.2.0"

Environment Override (Development Only)

If needed for testing, you can override with .env:

# .env (development only)
APP_VERSION=1.2.0-dev

Config loads it via lazy import (to avoid circular dependencies):

if not os.getenv("APP_VERSION"):
    from webdrop_bridge import __version__
    app_version = __version__
else:
    app_version = os.getenv("APP_VERSION")

Shared Version Utility

Both build scripts and the sync script use build/scripts/version_utils.py to read the version:

from version_utils import get_current_version, get_project_root

version = get_current_version()  # Reads from __init__.py
root = get_project_root()        # Gets project root

This ensures:

  • No duplication - Single implementation used everywhere
  • Consistency - All tools read from the same source
  • Maintainability - Update once, affects all tools

If you create new build scripts or tools, import from this utility instead of implementing version reading again.


Summary of Version Management

Task How Location
Define version Edit __version__ src/webdrop_bridge/__init__.py
Read version in app Lazy import __init__.py src/webdrop_bridge/config.py
Read version in builds Use shared utility build/scripts/version_utils.py
Update changelog Run sync script scripts/sync_version.py
Release new version Edit __init__.py, run sync, commit/tag See "Releasing a New Version" above

Golden Rule: Only edit src/webdrop_bridge/__init__.py. Everything else is automated or handled by scripts.

Getting Help

  • Issues: Report bugs or request features
  • Discussions: Ask questions or discuss ideas
  • Documentation: Check docs/ folder
  • Code Examples: Look at tests/ folder

Review Process

All pull requests require:

  • Tests pass (100% on target platforms)
  • Code review approved
  • No lint/type warnings
  • Documentation updated
  • Coverage maintained or improved

Recognition

Contributors are recognized in:

  • CONTRIBUTORS.md
  • GitHub releases
  • Project website

Thank you for contributing to WebDrop Bridge! 🎉