Conventions Python
Ce document definit les conventions de codage Python pour l'organisation. Il couvre le
nommage, les annotations de type, les docstrings, les patterns interdits et requis, le
formatage avec Ruff, et la structure de projet. Tout code Python doit respecter ces regles
sans exception.
Portee
Ce standard s'applique a tous les contributeurs (humains et agents IA) qui ecrivent ou
modifient du code Python sur les repositories de l'organisation. Cela inclut les scripts de
build, les outils internes, les tests, et les applications Python.
Langue obligatoire — Anglais
Tout le code, les commentaires, les noms de variables, les noms de fonctions, les
docstrings et la documentation doivent etre en anglais americain (U.S. English).
Aucune exception.
Nommage
Conventions generales
| Element |
Convention |
Exemple |
| Variables, fonctions |
snake_case |
total_bytes, calculate_offset() |
| Classes |
PascalCase |
ConfigLoader, TopologyParser |
| Constantes |
SCREAMING_SNAKE_CASE |
MAX_RETRIES, DEFAULT_TIMEOUT |
| Fichiers |
snake_case.py |
config_loader.py, topology_parser.py |
| Repertoires |
snake_case |
data_utils/, auth_service/ |
| Membres prives |
_snake_case |
_internal_state, _parse_header() |
| Methodes dunder |
__snake_case__ |
__init__, __repr__, __enter__ |
Noms de methodes — verbes obligatoires
Les noms de methodes doivent etre des verbes decrivant l'effet ou la valeur retournee.
| Bon |
Mauvais |
Pourquoi |
is_ready() |
ready() |
Un booleen commence par is_, has_, can_ |
calculate_offset() |
offset() |
Le nom doit decrire l'action |
get_user() |
user() |
Accesseur explicite |
validate_input() |
validation() |
Un verbe, pas un nom |
Noms eviter
| Pattern a eviter |
Alternative |
Noms a une lettre (x, d, l) |
Nom descriptif (index, data, items) |
Abbreviations ambigues (cfg, mgr, ctx) |
Mot complet (config, manager, context) |
Noms generiques (data, info, result) seuls |
Qualifier : user_data, error_info, parse_result |
Prefixe my_ ou the_ |
Supprimer le prefixe |
Annotations de type (type hints)
Les annotations de type sont obligatoires sur toutes les fonctions et methodes publiques.
Elles sont fortement recommandees sur les fonctions internes.
Regles
Signature typeedef calculate_offset(base: int, size: int) -> int:
return base + size
| Regle |
Detail |
from __future__ import annotations |
Obligatoire en tete de fichier pour les forward references |
| Types nullables |
X \| None (Python 3.10+) ou Optional[X] |
| Types complexes |
TypeAlias pour les definitions de type complexes |
| Fonctions publiques |
Jamais laisser une signature publique sans type hints |
Retour None |
Annoter explicitement -> None pour les fonctions sans retour |
Exemples
Annotations courantesfrom __future__ import annotations
from collections.abc import Sequence
from pathlib import Path
from typing import TypeAlias
# TypeAlias pour les types complexes
NodeId: TypeAlias = int
AdjacencyList: TypeAlias = dict[NodeId, list[NodeId]]
def load_config(path: Path) -> dict[str, str]:
"""Load configuration from a YAML file."""
...
def find_nodes(graph: AdjacencyList, start: NodeId) -> list[NodeId]:
"""Find all reachable nodes from a starting node."""
...
def process_batch(items: Sequence[str], limit: int | None = None) -> int:
"""Process a batch of items, optionally limited."""
...
Docstrings
Style Google
Toutes les fonctions, classes et modules publics doivent avoir une docstring au format
Google. Les docstrings doivent etre en anglais.
Docstring Google-style completedef transfer_data(source: int, target: int, count: int) -> bool:
"""Transfer data blocks between storage nodes.
Moves the specified number of blocks from the source node to the
target node. The transfer is atomic: either all blocks are moved
or none are.
Args:
source: Source storage node ID.
target: Target storage node ID.
count: Number of blocks to transfer.
Returns:
True if all blocks were transferred successfully.
Raises:
ConnectionError: If the target node is unreachable.
ValueError: If count is negative.
"""
Regles
| Regle |
Detail |
| Premiere ligne |
Resume en une phrase, terminee par un point |
Sections Args |
Un par parametre, description courte |
Section Returns |
Description du type de retour et sa semantique |
Section Raises |
Exceptions que la fonction peut lever |
| Longueur |
Concise — ne pas restater ce que la signature dit deja |
Classes
Docstring de classeclass ConfigLoader:
"""Load and validate project configuration files.
Supports YAML and TOML formats. Configuration values are validated
against a predefined schema at load time.
Attributes:
path: Path to the configuration file.
data: Parsed configuration data.
"""
def __init__(self, path: Path) -> None:
self.path = path
self.data: dict[str, str] = {}
Patterns interdits
| Pattern interdit |
Raison |
Alternative |
from module import * |
Pollue le namespace, conflits de noms |
Imports explicites |
Arguments par defaut mutables (def f(x=[])) |
Valeur partagee entre tous les appels |
None + creation conditionnelle |
except: nu (sans type) |
Capture tout, y compris KeyboardInterrupt |
Capturer des exceptions specifiques |
print() en production |
Pas de niveaux, pas de filtrage |
Module logging |
| Etat global mutable |
Couplage fort, tests impossibles |
Injection de dependance |
| Francais dans le code |
Incoherence, lisibilite reduite |
Anglais exclusivement |
Exemple — argument mutable par defaut# INTERDIT
def process(items: list[str] = []) -> None:
items.append("new") # Bug : modifie la valeur par defaut !
# CORRECT
def process(items: list[str] | None = None) -> None:
if items is None:
items = []
items.append("new")
Patterns requis
| Pattern requis |
Raison |
A eviter |
if __name__ == "__main__": guard |
Empeche l'execution a l'import |
Code au top-level |
Context managers (with) |
Liberation garantie des ressources |
open() sans with |
| f-strings pour le formatage |
Lisibilite, performance |
% ou .format() |
pathlib.Path pour les chemins |
API objet, cross-platform |
os.path |
Exemple — pathlib et context managerfrom pathlib import Path
config_path = Path("config") / "settings.yaml"
if config_path.exists():
content = config_path.read_text()
Ruff — outil unique
L'organisation utilise Ruff comme outil unique de formatage et de linting.
| Outil |
Commande |
Role |
| Formatage |
ruff format |
Formatage automatique du code |
| Linting |
ruff check |
Verification des regles de qualite |
| Fix automatique |
ruff check --fix |
Correction automatique des problemes simples |
Obligation : toujours executer ruff format et ruff check avant chaque commit.
| Regle |
Valeur |
| Indentation |
4 espaces (jamais de tabulations) |
| Largeur de ligne |
88 colonnes |
| Guillemets |
Doubles (") par defaut |
| Virgule finale |
Oui, dans les collections multi-lignes |
| Lignes vides |
2 entre les definitions de top-level, 1 entre les methodes |
Configuration dans pyproject.toml
Configuration Ruff minimale[tool.ruff]
line-length = 88
target-version = "py312"
[tool.ruff.lint]
select = ["E", "F", "W", "I", "N", "UP", "B", "SIM", "RUF"]
[tool.ruff.format]
quote-style = "double"
Structure de projet
pyproject.toml obligatoire
Tout projet Python utilise pyproject.toml pour sa configuration. L'utilisation de
setup.py ou setup.cfg est obsolete et interdite pour les nouveaux projets.
pyproject.toml — structure type[project]
name = "my-project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
"pyyaml>=6.0,<7",
"httpx>=0.27,<1",
]
[project.optional-dependencies]
dev = [
"pytest>=8.0",
"ruff>=0.8",
]
Dependances
| Regle |
Detail |
| Contraintes de version |
Toujours epingler avec >=X.Y,<Z |
| Dependances dev |
Separees dans [project.optional-dependencies] |
| Environnements virtuels |
venv, poetry, uv ou equivalent |
| Lock file |
Recommande pour les applications (pas les libraries) |
Arborescence type
my_project/
+-- pyproject.toml
+-- src/
| +-- my_project/
| +-- __init__.py
| +-- config.py
| +-- services/
| +-- __init__.py
| +-- auth.py
+-- tests/
| +-- __init__.py
| +-- test_config.py
| +-- test_auth.py
+-- scripts/
+-- setup_env.py
| Repertoire |
Role |
src/ |
Code source (layout src recommande) |
tests/ |
Tests (miroir de la structure source) |
scripts/ |
Scripts utilitaires et d'automatisation |
Resume des regles critiques
| Regle |
Statut |
| Tout en anglais (code, commentaires, docstrings) |
Obligatoire |
snake_case pour variables et fonctions |
Obligatoire |
PascalCase pour les classes |
Obligatoire |
| Type hints sur les fonctions publiques |
Obligatoire |
| Docstrings Google-style sur les APIs publiques |
Obligatoire |
from module import * |
Interdit |
| Arguments par defaut mutables |
Interdit |
except: nu |
Interdit |
print() en production |
Interdit |
Guard __main__ dans les scripts |
Obligatoire |
with pour les fichiers et ressources |
Obligatoire |
| f-strings pour le formatage |
Obligatoire |
pathlib.Path pour les chemins |
Obligatoire |
ruff format + ruff check avant commit |
Obligatoire |
pyproject.toml pour la configuration |
Obligatoire |
References