Contributing: Coding Style
This document outlines the coding conventions to be followed in this project. Adhering to these conventions ensures consistency, readability, and maintainability of the codebase.
Python Style
- Version: Write code compatible with Python 3.12 features and style.
- Formatting & Linting: We use
rufffor all formatting, linting, and import sorting. Adhere to the configurations defined inpyproject.tomlandruff.toml.- To format your code, run:
make format - To sort imports, run:
make isort - To check for issues, run:
make check - Most issues can be fixed automatically by running:
make fix
- To format your code, run:
- Naming:
- Use
snake_casefor variables, functions, methods, and modules. - Use
PascalCasefor classes. - Use
UPPER_SNAKE_CASEfor constants.
- Use
- Docstrings: Write clear and concise docstrings for all public modules, classes, functions, and methods. Google style docstrings are preferred.
- Import conditions: Do not safeguard imports to check if a library is not installed. If it's not installed then the program will fail as expected. This is part of dependency management.
- Code organization: Split code into modules and packages for various features. Aim for short, focused Python files.
Don't Safeguard Imports
- Bad:
python try: import pydot except ImportError: pydot = None - Good:
python import pydot
Code Comments
- Focus: Comments should explain the why behind the code, clarify complex logic, or document non-obvious decisions. They should not just describe what the code is doing.
- Timelessness: Write comments that will remain true and relevant over time. Avoid comments that refer to the development process, specific points in time, or temporary states.
- Avoid Redundancy: Do not comment on obvious code. Good code should be largely self-documenting.
Type Hinting
- Mandatory: All function signatures, method signatures, and variables where the type isn't immediately obvious should have type hints.
- Style: Use Python 3.10+ style type hints:
- Use built-in generic types (e.g.,
list[int],dict[str, float]) instead of importing fromtyping(List,Dict) where possible. - Use the
|operator for unions (e.g.,int | str) instead oftyping.Union. - Use
X | Nonefor optional types (e.g.,str | None) instead oftyping.Optional.
- Use built-in generic types (e.g.,
Pydantic (v2)
- Usage: Use Pydantic models for data validation, serialization/deserialization, API request/response models, and complex configuration structures.
- Field Definitions:
- Always initialize fields using
Field(). - Provide a
default=value ordefault_factory=for optional fields withinField(). - Use
Field(..., description="...")for required fields. - Include a
description=for all fields to improve clarity.
- Always initialize fields using
- Methods: Use
model_validate()for parsing/validation andmodel_dump()for serialization instead of the deprecated V1 methods.