# Development Guide Guide for contributors and developers working on the Wiki.js Python SDK. ## Table of Contents - [Development Setup](#development-setup) - [Project Structure](#project-structure) - [Development Workflow](#development-workflow) - [Testing](#testing) - [Code Quality](#code-quality) - [Documentation](#documentation) - [Release Process](#release-process) --- ## 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:** ```bash git clone https://github.com/yourusername/wikijs-python-sdk.git cd wikijs-python-sdk ``` 2. **Create a virtual environment:** ```bash python -m venv .venv source .venv/bin/activate # On Windows: .venv\Scripts\activate ``` 3. **Install development dependencies:** ```bash pip install -e ".[dev]" ``` 4. **Set up pre-commit hooks:** ```bash pre-commit install ``` 5. **Configure environment variables:** ```bash export WIKIJS_URL='https://your-test-wiki.example.com' export WIKIJS_API_KEY='your-test-api-key' ``` ### Verify Setup ```bash # 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:** ```bash 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:** ```bash # 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:** ```bash git add . git commit -m "feat: add awesome new feature" ``` 5. **Push and create PR:** ```bash git push origin feature/new-awesome-feature # Create pull request on GitHub ``` ### Commit Message Format We follow [Conventional Commits](https://www.conventionalcommits.org/): ``` [optional scope]: [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 ```bash # 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 ```python """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` ```python """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` ```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 ```yaml # .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: ```bash # 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: ```python 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 ```bash # 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](https://semver.org/): - **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**: ```bash git add . git commit -m "chore: bump version to v1.2.3" ``` 5. **Create and push tag**: ```bash 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 ```bash # Install package in development mode pip install -e . # Verify Python path python -c "import sys; print(sys.path)" ``` #### Test Failures ```bash # 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 ```bash # Run mypy on specific file mypy wikijs/module_name.py # Show mypy configuration mypy --config-file ``` ### Debugging Tools #### Logging ```python import logging # Enable debug logging logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger('wikijs') logger.setLevel(logging.DEBUG) ``` #### Python Debugger ```python import pdb # Set breakpoint pdb.set_trace() # Or use built-in breakpoint() (Python 3.7+) breakpoint() ``` #### HTTP Debugging ```python import http.client # Enable HTTP debugging http.client.HTTPConnection.debuglevel = 1 ``` --- ## Resources ### Useful Links - **[Wiki.js API Documentation](https://docs.js.wiki/dev/api)** - Official API docs - **[GraphQL](https://graphql.org/learn/)** - GraphQL learning resources - **[Pydantic](https://pydantic-docs.helpmanual.io/)** - Data validation library - **[Requests](https://docs.python-requests.org/)** - HTTP library documentation - **[pytest](https://docs.pytest.org/)** - Testing framework documentation ### 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! 🚀