Files
wikijs-sdk-python/docs/development.md
2025-07-29 20:16:11 -04:00

17 KiB

Development Guide

Guide for contributors and developers working on the Wiki.js Python SDK.

Table of Contents


Development Setup

Prerequisites

  • Python 3.8+ (tested with 3.8, 3.9, 3.10, 3.11, 3.12)
  • Git for version control
  • Wiki.js instance for testing (can be local or remote)

Environment Setup

  1. Clone the repository:

    git clone https://github.com/yourusername/wikijs-python-sdk.git
    cd wikijs-python-sdk
    
  2. Create a virtual environment:

    python -m venv .venv
    source .venv/bin/activate  # On Windows: .venv\Scripts\activate
    
  3. Install development dependencies:

    pip install -e ".[dev]"
    
  4. Set up pre-commit hooks:

    pre-commit install
    
  5. Configure environment variables:

    export WIKIJS_URL='https://your-test-wiki.example.com'
    export WIKIJS_API_KEY='your-test-api-key'
    

Verify Setup

# Run tests
pytest

# Check code quality
pre-commit run --all-files

# Verify package can be imported
python -c "from wikijs import WikiJSClient; print('✅ Setup successful!')"

Project Structure

wikijs-python-sdk/
├── wikijs/                    # Main package
│   ├── __init__.py           # Package exports
│   ├── version.py            # Version information
│   ├── client.py             # Main WikiJS client
│   ├── exceptions.py         # Exception classes
│   ├── auth/                 # Authentication handlers
│   │   ├── __init__.py       # Auth exports
│   │   ├── base.py           # Base auth handler
│   │   ├── api_key.py        # API key authentication
│   │   └── jwt.py            # JWT authentication
│   ├── endpoints/            # API endpoints
│   │   ├── __init__.py       # Endpoint exports
│   │   ├── base.py           # Base endpoint class
│   │   └── pages.py          # Pages API endpoint
│   ├── models/               # Data models
│   │   ├── __init__.py       # Model exports
│   │   ├── base.py           # Base model classes
│   │   └── page.py           # Page-related models
│   └── utils/                # Utility functions
│       ├── __init__.py       # Utility exports
│       └── helpers.py        # Helper functions
├── tests/                    # Test suite
│   ├── conftest.py          # Test configuration
│   ├── auth/                # Authentication tests
│   ├── endpoints/           # Endpoint tests
│   ├── models/              # Model tests
│   └── utils/               # Utility tests
├── docs/                    # Documentation
│   ├── api_reference.md     # API reference
│   ├── user_guide.md        # User guide
│   ├── development.md       # This file
│   └── ...
├── examples/                # Usage examples
├── .github/                 # GitHub workflows
│   └── workflows/           # CI/CD pipelines
├── pyproject.toml          # Project configuration
├── setup.py                # Package setup
├── requirements.txt        # Runtime dependencies
├── requirements-dev.txt    # Development dependencies
└── README.md               # Project README

Key Components

Client (wikijs/client.py)

  • Main entry point for the SDK
  • Manages HTTP sessions and requests
  • Handles authentication and error handling
  • Provides access to endpoint handlers

Authentication (wikijs/auth/)

  • Base authentication handler interface
  • Concrete implementations for API key and JWT auth
  • Extensible for custom authentication methods

Endpoints (wikijs/endpoints/)

  • API endpoint implementations
  • Each endpoint handles a specific Wiki.js API area
  • Base endpoint class provides common functionality

Models (wikijs/models/)

  • Pydantic models for data validation and serialization
  • Type-safe data structures
  • Input validation and error handling

Utilities (wikijs/utils/)

  • Helper functions for common operations
  • URL handling, response parsing, etc.
  • Shared utility functions

Development Workflow

Branch Strategy

  • main: Stable, production-ready code
  • develop: Integration branch for new features
  • Feature branches: feature/description for new features
  • Bug fixes: fix/description for bug fixes
  • Hotfixes: hotfix/description for critical fixes

Workflow Steps

  1. Create a feature branch:

    git checkout -b feature/new-awesome-feature
    
  2. Make your changes:

    • Write code following our style guidelines
    • Add tests for new functionality
    • Update documentation as needed
  3. Run quality checks:

    # Run tests
    pytest
    
    # Check code formatting
    black --check .
    
    # Check imports
    isort --check-only .
    
    # Type checking
    mypy wikijs
    
    # Linting
    flake8 wikijs
    
    # Security scan
    bandit -r wikijs
    
  4. Commit your changes:

    git add .
    git commit -m "feat: add awesome new feature"
    
  5. Push and create PR:

    git push origin feature/new-awesome-feature
    # Create pull request on GitHub
    

Commit Message Format

We follow Conventional Commits:

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

Types:

  • feat: A new feature
  • fix: A bug fix
  • docs: Documentation only changes
  • style: Changes that don't affect code meaning
  • refactor: Code change that neither fixes a bug nor adds a feature
  • test: Adding missing tests or correcting existing tests
  • chore: Other changes that don't modify src or test files

Examples:

feat(auth): add JWT authentication support
fix(client): handle connection timeout properly
docs: update API reference for pages endpoint
test: add comprehensive model validation tests

Testing

Test Organization

  • Unit tests: Test individual components in isolation
  • Integration tests: Test component interactions
  • End-to-end tests: Test complete workflows
  • Mock tests: Test with mocked external dependencies

Running Tests

# Run all tests
pytest

# Run with coverage
pytest --cov=wikijs --cov-report=html

# Run specific test file
pytest tests/test_client.py

# Run specific test
pytest tests/test_client.py::TestWikiJSClient::test_basic_initialization

# Run tests with verbose output
pytest -v

# Run tests and stop on first failure
pytest -x

Writing Tests

Test Structure

"""Tests for module_name."""

import pytest
from unittest.mock import Mock, patch

from wikijs.module_name import ClassUnderTest
from wikijs.exceptions import SomeException


class TestClassUnderTest:
    """Test suite for ClassUnderTest."""
    
    @pytest.fixture
    def sample_data(self):
        """Sample data for testing."""
        return {"key": "value"}
    
    def test_basic_functionality(self, sample_data):
        """Test basic functionality."""
        # Arrange
        instance = ClassUnderTest()
        
        # Act
        result = instance.some_method(sample_data)
        
        # Assert
        assert result is not None
        assert result.key == "value"
    
    def test_error_handling(self):
        """Test proper error handling."""
        instance = ClassUnderTest()
        
        with pytest.raises(SomeException, match="Expected error message"):
            instance.method_that_should_fail()
    
    @patch('wikijs.module_name.external_dependency')
    def test_with_mocking(self, mock_dependency):
        """Test with mocked dependencies."""
        # Setup mock
        mock_dependency.return_value = "mocked result"
        
        # Test
        instance = ClassUnderTest()
        result = instance.method_using_dependency()
        
        # Verify
        assert result == "mocked result"
        mock_dependency.assert_called_once()

Test Guidelines

  1. Follow AAA pattern: Arrange, Act, Assert
  2. Use descriptive test names that explain what is being tested
  3. Test both success and failure cases
  4. Mock external dependencies (HTTP requests, file system, etc.)
  5. Use fixtures for common test data and setup
  6. Maintain high test coverage (target: >85%)

Test Configuration

conftest.py

"""Shared test configuration and fixtures."""

import pytest
from unittest.mock import Mock

from wikijs import WikiJSClient


@pytest.fixture
def mock_client():
    """Create a mock WikiJS client for testing."""
    client = Mock(spec=WikiJSClient)
    client.base_url = "https://test-wiki.example.com"
    return client


@pytest.fixture
def sample_page_data():
    """Sample page data for testing."""
    return {
        "id": 123,
        "title": "Test Page",
        "path": "test-page",
        "content": "# Test\n\nContent here.",
        "is_published": True,
        "tags": ["test"]
    }

Code Quality

Code Style

We use several tools to maintain code quality:

  • Black: Code formatting
  • isort: Import sorting
  • flake8: Linting
  • mypy: Type checking
  • bandit: Security scanning

Configuration Files

pyproject.toml

[tool.black]
line-length = 88
target-version = ['py38']
include = '\.pyi?$'

[tool.isort]
profile = "black"
multi_line_output = 3
line_length = 88

[tool.mypy]
python_version = "3.8"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true

[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = "--strict-markers --disable-warnings"

Pre-commit Hooks

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/psf/black
    rev: 23.3.0
    hooks:
      - id: black
  
  - repo: https://github.com/pycqa/isort
    rev: 5.12.0
    hooks:
      - id: isort
  
  - repo: https://github.com/pycqa/flake8
    rev: 6.0.0
    hooks:
      - id: flake8
  
  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.3.0
    hooks:
      - id: mypy
        additional_dependencies: [types-requests]

Quality Checks

Run these commands before committing:

# Format code
black .
isort .

# Check formatting
black --check .
isort --check-only .

# Lint code
flake8 wikijs tests

# Type checking
mypy wikijs

# Security scan
bandit -r wikijs

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

Documentation

Documentation Types

  1. API Reference: Auto-generated from docstrings
  2. User Guide: Manual documentation for end users
  3. Development Guide: This document
  4. Examples: Practical usage examples
  5. Changelog: Version history and changes

Writing Documentation

Docstring Format

We use Google-style docstrings:

def create_page(self, page_data: PageCreate) -> Page:
    """Create a new page in the wiki.
    
    Args:
        page_data: Page creation data containing title, path, content, etc.
        
    Returns:
        The created Page object with assigned ID and metadata.
        
    Raises:
        ValidationError: If page data is invalid.
        APIError: If the API request fails.
        AuthenticationError: If authentication fails.
        
    Example:
        >>> from wikijs.models import PageCreate
        >>> page_data = PageCreate(
        ...     title="My Page",
        ...     path="my-page",
        ...     content="# Hello World"
        ... )
        >>> created_page = client.pages.create(page_data)
        >>> print(f"Created page with ID: {created_page.id}")
    """

Documentation Guidelines

  1. Be clear and concise in explanations
  2. Include examples for complex functionality
  3. Document all public APIs with proper docstrings
  4. Keep documentation up to date with code changes
  5. Use consistent formatting and style

Building Documentation

# Install documentation dependencies
pip install -e ".[docs]"

# Build documentation (if using Sphinx)
cd docs
make html

# Serve documentation locally
python -m http.server 8000 -d _build/html

Release Process

Version Management

We use Semantic Versioning:

  • MAJOR: Incompatible API changes
  • MINOR: New functionality (backward compatible)
  • PATCH: Bug fixes (backward compatible)

Release Steps

  1. Update version number in wikijs/version.py
  2. Update CHANGELOG.md with new version details
  3. Run full test suite and ensure all checks pass
  4. Create release commit:
    git add .
    git commit -m "chore: bump version to v1.2.3"
    
  5. Create and push tag:
    git tag v1.2.3
    git push origin main --tags
    
  6. GitHub Actions will automatically:
    • Run tests
    • Build package
    • Publish to PyPI
    • Create GitHub release

Pre-release Checklist

  • All tests pass
  • Code coverage meets requirements (>85%)
  • Documentation is updated
  • CHANGELOG.md is updated
  • Version number is bumped
  • No breaking changes without major version bump
  • Examples work with new version

Release Automation

Our CI/CD pipeline automatically handles:

  • Testing: Run test suite on multiple Python versions
  • Quality checks: Code formatting, linting, type checking
  • Security: Vulnerability scanning
  • Building: Create source and wheel distributions
  • Publishing: Upload to PyPI on tagged releases
  • Documentation: Update documentation site

Contributing Guidelines

Getting Started

  1. Fork the repository on GitHub
  2. Create a feature branch from develop
  3. Make your changes following our guidelines
  4. Add tests for new functionality
  5. Update documentation as needed
  6. Submit a pull request

Pull Request Process

  1. Ensure CI passes - all tests and quality checks must pass
  2. Update documentation - include any necessary documentation updates
  3. Add tests - maintain or improve test coverage
  4. Follow conventions - use consistent code style and commit messages
  5. Be responsive - address feedback and review comments promptly

Code Review Guidelines

As a reviewer:

  • Be constructive and helpful in feedback
  • Check for correctness and potential issues
  • Verify tests cover new functionality
  • Ensure documentation is adequate
  • Approve when ready or request specific changes

As an author:

  • Respond promptly to review feedback
  • Make requested changes or explain why they're not needed
  • Keep PRs focused - one feature or fix per PR
  • Test thoroughly before requesting review

Debugging and Troubleshooting

Common Development Issues

Import Errors

# Install package in development mode
pip install -e .

# Verify Python path
python -c "import sys; print(sys.path)"

Test Failures

# Run specific failing test with verbose output
pytest -xvs tests/path/to/failing_test.py::test_name

# Debug with pdb
pytest --pdb tests/path/to/failing_test.py::test_name

Type Checking Issues

# Run mypy on specific file
mypy wikijs/module_name.py

# Show mypy configuration
mypy --config-file

Debugging Tools

Logging

import logging

# Enable debug logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger('wikijs')
logger.setLevel(logging.DEBUG)

Python Debugger

import pdb

# Set breakpoint
pdb.set_trace()

# Or use built-in breakpoint() (Python 3.7+)
breakpoint()

HTTP Debugging

import http.client

# Enable HTTP debugging
http.client.HTTPConnection.debuglevel = 1

Resources

Development Tools

  • VS Code Extensions: Python, Pylance, Black Formatter, isort
  • PyCharm: Professional Python IDE
  • Postman: API testing tool
  • GraphQL Playground: GraphQL query testing

Community

  • GitHub Discussions: Ask questions and share ideas
  • GitHub Issues: Report bugs and request features
  • Pull Requests: Contribute code improvements

Questions?

If you have questions about development:

  1. Check this documentation and the API reference
  2. Search existing issues on GitHub
  3. Ask in GitHub Discussions for community help
  4. Create an issue for bugs or feature requests

Happy coding! 🚀