Code Quality and Style#
We enforce consistent code style using pre-commit hooks. All code must follow these guidelines:
Code Formatting#
We follow PEP 8 with some modifications:
Line length is 120 characters (not 79).
Uses
blackfor consistent formatting.Uses
isortfor import sorting with: - Single line imports. - Black-compatible formatting. - Project imports grouped underanemoi.
Import organization:
Imports are sorted using
isort.Force single-line imports.
Group order: standard library, third-party, anemoi packages.
Linting#
We use ruff for code linting, which checks for:
Code style violations.
Potential bugs.
Complexity issues.
Best practices.
Documentation Style#
Documentation follows strict guidelines:
RST files are formatted using
rstfmt.Docstrings must match function signatures (checked by
docsig).Sphinx documentation is linted (
sphinx-lint).
Pre-commit Checks#
All code is automatically checked using pre-commit hooks that verify:
Code formatting: Black formatting. Import sorting. Line endings and trailing whitespace.
Code quality: No debugger statements. No merge conflicts. Type annotations. No blanket
noqastatements.Documentation: Docstring validation. RST formatting. Sphinx linting.
File Organization#
Proper file organization is crucial for maintaining a clean and maintainable codebase. Follow these guidelines when adding new files or modifying existing ones:
Directory Structure#
Place new files in the appropriate package directory:
Core functionality goes in
src/anemoi/<package_name>/.Tests go in
tests/.Documentation in
docs/.Group related functionality together in the same module for better organisation and maintainability.
Note
When adding new files, ensure they are properly included in
__init__.py files if they should be part of the public API. Keep
it minimal. Use __init__.py to define package-level exports using
__all__.
- Utility Functions Organization:
Use
utils.pyonly for package-specific helper functions that don’t fit in other modules.If a utility function could be useful across multiple packages: - Move it to
anemoi-utilspackage. - Document its general-purpose nature. - Ensure it remains stateless and reusable.Avoid using
utils.pyas a catch-all; if multiple related utilities emerge, consider creating a dedicated module.
File Structure#
Within each file:
Start with the license header and imports:
Anemoi contributors license header.
Standard library imports.
Third-party imports.
Local imports.
Follow with any module-level constants or configurations.
Define classes and functions in a logical order:
Base classes before derived classes.
Related functions grouped together.
Public API before private implementations.
Note
Use absolute imports within the package. Avoid wildcard (*) imports.
Naming Conventions#
Use descriptive names that clearly indicate purpose or functionality.
Files and Modules:
Use lowercase with underscores
Examples:
reduced_gaussian_grid.py✅ReducedGaussianGrid.py❌rgrid.py❌ (too vague)
Classes:
Use PascalCase (CapWords)
Examples:
ReducedGaussianGridNodes✅MultiScaleEdges✅reduced_gaussian_grid_nodes❌Rgn❌ (too cryptic)
Functions and Variables:
Use snake_case
Use verbs for functions, nouns for variables
Examples:
calculate_edge_weights()✅get_coordinates()✅node_attributes✅calculateEdgeWeights()❌crds❌ (too vague)
Constants:
Use uppercase with underscores
Examples:
MAX_GRID_RESOLUTION✅DEFAULT_BATCH_SIZE✅MaxGridResolution❌
Private Names:
Prefix with single underscore for internal use
Examples:
_validate_input()✅_cached_result✅
Type Variables:
Use CamelCase, preferably single letters or short names
Examples:
T✅ (for generic type)NodeType✅EdgeAttr✅
Enums:
Use CamelCase for enum class names
Use UPPERCASE for enum members
Examples:
class NodeType(Enum):SOURCE = "source"TARGET = "target"
Test Names:
Prefix with
test_(methods) orTest(classes).Be descriptive about what is being tested.
Include the scenario and expected outcome.
Examples:
test_reduced_gaussian_grid_with_invalid_resolution✅test_edge_builder_handles_empty_graph✅test_coordinates_are_in_radians✅testGrid❌ (too vague)test1❌ (meaningless)
Note
Avoid abbreviations unless they are widely understood in the domain
(e.g., lat, lon for latitude/longitude). Clarity is more
important than brevity.