Coding Standards
Guidelines and best practices for contributing to the Zyeta backend codebase
This guide outlines the coding standards and best practices for the Zyeta backend codebase. Following these standards ensures code consistency, maintainability, and quality across the project.
Code Formatting and Linting
Ruff
We use Ruff as our primary linter and formatter. Ruff combines many Python linting tools into one fast package.
Our Ruff configuration is defined in ruff.toml
at the project root:
Key standards enforced by our Ruff configuration:
- Indentation: Use 2 spaces for indentation (not tabs)
- Line Length: Maximum 150 characters per line
- Python Version: Code should be compatible with Python 3.10+
- Whitespace: No trailing whitespace, consistent spacing around operators
Type Checking with Mypy
We use Mypy for static type checking. Our Mypy configuration is defined in mypy.ini
:
Key type checking requirements:
- Type Annotations: All function parameters and return values should have type annotations
- Imported Types: Use proper imports for types (e.g.,
from typing import List, Optional, Dict
) - Pydantic Models: Use properly typed Pydantic models for data validation
Pre-commit Hooks
We use pre-commit to run linting and type-checking automatically before commits. Our pre-commit configuration is in .pre-commit-config.yaml
:
To set up pre-commit:
- Install pre-commit:
pip install pre-commit
- Install hooks:
pre-commit install
Code Structure and Organization
Directory Structure
Follow the established directory structure:
Import Order
Organize imports in the following order, with a blank line between each group:
- Standard library imports
- Third-party library imports
- Application-specific imports
Example:
Naming Conventions
- Files and Directories: Use snake_case (e.g.,
user_service.py
) - Classes: Use PascalCase (e.g.,
UserService
) - Functions and Variables: Use snake_case (e.g.,
get_user_by_id
) - Constants: Use UPPER_SNAKE_CASE (e.g.,
MAX_CONNECTIONS
) - Database Models: Use PascalCase with “Model” suffix (e.g.,
UserModel
) - Pydantic Schemas: Use PascalCase with descriptive suffixes:
- Base schemas:
UserBase
- Create operations:
UserCreate
- Update operations:
UserUpdate
- Responses:
UserResponse
- Base schemas:
Documentation Standards
Docstrings
Use triple-quoted docstrings for modules, classes, and functions:
Comments
- Use comments to explain “why” not “what” when code is not self-explanatory
- Keep comments up-to-date with code changes
- Use complete sentences with proper punctuation
Error Handling
- HTTP Exceptions: Use FastAPI’s
HTTPException
with appropriate status codes - Validation Errors: Use Pydantic for input validation
- Database Errors: Catch and handle specific database exceptions
- Logging: Include appropriate logging for errors with context
Example:
Service Design Patterns
Dependency Injection
Use FastAPI’s dependency injection system for:
- Database sessions
- Authentication
- Authorization
- Configuration
Example:
Separation of Concerns
- Models: Define database structure only
- Schemas: Handle data validation and serialization
- Services: Implement business logic
- API Routes: Handle HTTP concerns only
Testing Standards
All code should include appropriate tests:
- Unit Tests: Test individual functions and methods
- Integration Tests: Test interactions between components
- API Tests: Test HTTP endpoints
Use pytest fixtures for common test setup and async testing support.
Example test:
Contributing Guidelines
Before submitting your code:
- Ensure all linting and type checking passes:
ruff check
andmypy src/
- Write or update tests for your changes
- Document new features or behavior changes
- Keep commits focused and with clear messages
- Rebase your branch on the latest main before requesting review
Common Mistakes to Avoid
- Circular Imports: Organize imports to prevent circular dependencies
- Missing Type Annotations: Ensure all functions have proper type hints
- Undocumented Magic: Avoid complex code without clear documentation
- Hardcoded Values: Use configuration instead of hardcoding sensitive data
- Overly Complex Functions: Keep functions focused on a single task
Best Practices
- Pagination: Always implement pagination for list endpoints
- Error Details: Provide specific, actionable error messages
- Defensive Programming: Validate inputs and handle unexpected cases
- Security: Follow security best practices for authentication and data handling
- Performance: Be mindful of database query efficiency
Was this page helpful?