# Code Standards This document defines the code quality standards for the ThrillWiki backend. ## Formatting & Style ### PEP 8 Compliance All Python code must comply with PEP 8, verified using: - **black**: Code formatting (line length: 88) - **flake8**: Style checking (max-line-length: 88, max-complexity: 10) - **ruff**: Fast linting and import sorting ### Running Formatters ```bash # Format code uv run black backend/ # Check style uv run flake8 backend/ --max-line-length=88 --max-complexity=10 # Lint and fix uv run ruff check backend/ --fix ``` ## Docstring Requirements ### Coverage - 100% coverage for public classes and methods - 100% coverage for all functions - Optional for private methods (but encouraged) ### Style Follow Google-style docstrings: ```python def function_name(arg1: Type1, arg2: Type2) -> ReturnType: """ Brief description of what this function does. Longer description if needed, explaining the purpose, behavior, and any important details. Args: arg1: Description of arg1 arg2: Description of arg2 Returns: Description of return value Raises: ExceptionType: When this exception is raised Example: >>> function_name("value1", "value2") "result" """ ``` ### Class Docstrings ```python class ClassName: """ Brief description of what this class does. Longer description if needed. Attributes: attr1: Description of attr1 attr2: Description of attr2 Example: instance = ClassName() instance.method() """ ``` ### View Docstrings Views should include URL patterns and permissions: ```python class MyView(DetailView): """ Brief description of what this view does. View Type: CBV (DetailView) URL Pattern: /resource// Template: app/resource_detail.html Permissions: LoginRequired """ ``` ## Complexity Guidelines ### Limits - **Maximum McCabe complexity**: 10 - **Maximum method length**: 50 lines - **Maximum nesting depth**: 3 levels ### Checking Complexity ```bash # Check McCabe complexity uv run flake8 backend/ --max-complexity=10 --select=C901 # Get complexity metrics uv run radon cc backend/apps/ -a ``` ### Refactoring Strategies 1. **Extract helper methods** for distinct responsibilities: ```python # Before def process_data(self, data): # Validate data (10 lines) # Transform data (10 lines) # Save data (10 lines) # Send notifications (10 lines) pass # After def process_data(self, data): self._validate_data(data) transformed = self._transform_data(data) result = self._save_data(transformed) self._send_notifications(result) return result ``` 2. **Use early returns** to reduce nesting: ```python # Before def process(self, data): if data: if data.get('field1'): if data.get('field2'): return result return None # After def process(self, data): if not data: return None if not data.get('field1'): return None if not data.get('field2'): return None return result ``` 3. **Move complex logic to service layer** ## Service Layer Patterns ### Service Method Signature Always use keyword-only arguments for service methods: ```python class MyService: @staticmethod def create_entity( *, # Force keyword-only arguments name: str, description: str = "", created_by: Optional[User] = None, ) -> Entity: """Create a new entity.""" pass ``` ### Validation Pattern Always call `full_clean()` before save: ```python @staticmethod def create_park(*, name: str, ...) -> Park: with transaction.atomic(): park = Park(name=name, ...) park.full_clean() # Validate before save park.save() return park ``` ## Import Organization Imports should be organized in this order: 1. Standard library 2. Third-party packages 3. Django imports 4. Local app imports ```python import logging from typing import Any, Dict, Optional from django.contrib.auth import get_user_model from django.db import transaction from rest_framework import status from apps.core.exceptions import ServiceError from .models import MyModel ``` ## Type Hints Use type hints for all function signatures: ```python def process_data( data: Dict[str, Any], user: Optional[User] = None, ) -> ProcessResult: """Process data and return result.""" pass ``` ## Testing Requirements - Maintain or improve test coverage with changes - Add tests for new service methods - Add tests for new mixins and base classes - Run tests before committing: ```bash pytest backend/tests/ --cov=backend/apps --cov-report=html ``` ## Pre-commit Configuration The following pre-commit hooks are configured: ```yaml repos: - repo: https://github.com/psf/black rev: 24.1.0 hooks: - id: black - repo: https://github.com/pycqa/flake8 rev: 7.1.1 hooks: - id: flake8 args: [--max-line-length=88, --max-complexity=10] - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.12.10 hooks: - id: ruff args: [--fix] ```