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-optimizationbugfix/path-validation-windowsdocs/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 timeconfig.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! 🎉