python-code-style

Par wshobson · agents

Style de code Python, linting, formatage, conventions de nommage et normes de documentation. À utiliser lors de l'écriture de nouveau code, de la revue de style, de la configuration des linters, de la rédaction de docstrings, ou de l'établissement des standards d'un projet.

npx skills add https://github.com/wshobson/agents --skill python-code-style

Style et Documentation du Code Python

Un style de code cohérent et une documentation claire rendent les bases de code maintenables et collaboratives. Cette compétence couvre les outils Python modernes, les conventions de nommage et les normes de documentation.

Quand Utiliser Cette Compétence

  • Configurer le linting et le formatting pour un nouveau projet
  • Écrire ou examiner des docstrings
  • Établir des normes de codage d'équipe
  • Configurer ruff, mypy ou pyright
  • Examiner le code pour la cohérence du style
  • Créer la documentation du projet

Concepts Fondamentaux

1. Formatting Automatisé

Laissez les outils gérer les débats de formatage. Configurez une fois, appliquez automatiquement.

2. Nommage Cohérent

Suivez les conventions PEP 8 avec des noms significatifs et descriptifs.

3. Documentation Comme Code

Les docstrings doivent être maintenues aux côtés du code qu'elles décrivent.

4. Annotations de Type

Le code Python moderne devrait inclure des type hints pour tous les API publiques.

Démarrage Rapide

# Installer les outils modernes
pip install ruff mypy

# Configurer dans pyproject.toml
[tool.ruff]
line-length = 120
target-version = "py312"  # Ajustez selon la version Python minimale de votre projet

[tool.mypy]
strict = true

Patterns Fondamentaux

Pattern 1 : Outils Python Modernes

Utilisez ruff comme linter et formateur tout-en-un. Il remplace flake8, isort et black par un seul outil rapide.

# pyproject.toml
[tool.ruff]
line-length = 120
target-version = "py312"  # Ajustez selon la version Python minimale de votre projet

[tool.ruff.lint]
select = [
    "E",    # pycodestyle errors
    "W",    # pycodestyle warnings
    "F",    # pyflakes
    "I",    # isort
    "B",    # flake8-bugbear
    "C4",   # flake8-comprehensions
    "UP",   # pyupgrade
    "SIM",  # flake8-simplify
]
ignore = ["E501"]  # Line length handled by formatter

[tool.ruff.format]
quote-style = "double"
indent-style = "space"

Exécutez avec :

ruff check --fix .  # Linter et corriger automatiquement
ruff format .       # Formater le code

Pattern 2 : Configuration du Type Checking

Configurez la vérification de type stricte pour le code de production.

# pyproject.toml
[tool.mypy]
python_version = "3.12"
strict = true
warn_return_any = true
warn_unused_ignores = true
disallow_untyped_defs = true
disallow_incomplete_defs = true

[[tool.mypy.overrides]]
module = "tests.*"
disallow_untyped_defs = false

Alternative : Utilisez pyright pour une vérification plus rapide.

[tool.pyright]
pythonVersion = "3.12"
typeCheckingMode = "strict"

Pattern 3 : Conventions de Nommage

Suivez PEP 8 en mettant l'accent sur la clarté plutôt que la concision.

Fichiers et Modules :

# Bon : snake_case descriptif
user_repository.py
order_processing.py
http_client.py

# À éviter : Abréviations
usr_repo.py
ord_proc.py
http_cli.py

Classes et Fonctions :

# Classes : PascalCase
class UserRepository:
    pass

class HTTPClientFactory:  # Les acronymes restent en majuscules
    pass

# Fonctions et variables : snake_case
def get_user_by_email(email: str) -> User | None:
    retry_count = 3
    max_connections = 100

Constantes :

# Constantes au niveau du module : SCREAMING_SNAKE_CASE
MAX_RETRY_ATTEMPTS = 3
DEFAULT_TIMEOUT_SECONDS = 30
API_BASE_URL = "https://api.example.com"

Pattern 4 : Organisation des Imports

Groupez les imports dans un ordre cohérent : bibliothèque standard, tiers, local.

# Bibliothèque standard
import os
from collections.abc import Callable
from typing import Any

# Packages tiers
import httpx
from pydantic import BaseModel
from sqlalchemy import Column

# Imports locaux
from myproject.models import User
from myproject.services import UserService

Utilisez exclusivement les imports absolus :

# Préféré
from myproject.utils import retry_decorator

# À éviter : imports relatifs
from ..utils import retry_decorator

Patterns Avancés

Pattern 5 : Docstrings Style Google

Écrivez des docstrings pour tous les classes, méthodes et fonctions publiques.

Fonction Simple :

def get_user(user_id: str) -> User:
    """Récupérer un utilisateur par son identifiant unique."""
    ...

Fonction Complexe :

def process_batch(
    items: list[Item],
    max_workers: int = 4,
    on_progress: Callable[[int, int], None] | None = None,
) -> BatchResult:
    """Traiter les éléments de manière concurrente avec un pool de workers.

    Traite chaque élément du batch en utilisant le nombre configuré de
    workers. La progression peut être suivie via le callback optionnel.

    Args:
        items: Les éléments à traiter. Ne doit pas être vide.
        max_workers: Nombre maximum de workers concurrents. Par défaut 4.
        on_progress: Callback optionnel recevant les comptes (complétés, total).

    Returns:
        BatchResult contenant les éléments réussis et les échecs avec
        leurs exceptions associées.

    Raises:
        ValueError: Si items est vide.
        ProcessingError: Si le batch ne peut pas être traité.

    Example:
        >>> result = process_batch(items, max_workers=8)
        >>> print(f"Processed {len(result.succeeded)} items")
    """
    ...

Docstring de Classe :

class UserService:
    """Service pour gérer les opérations utilisateur.

    Fournit des méthodes pour créer, récupérer, mettre à jour et
    supprimer des utilisateurs avec validation et gestion d'erreurs appropriées.

    Attributes:
        repository: La couche d'accès aux données pour la persistance des utilisateurs.
        logger: Instance de logger pour le suivi des opérations.

    Example:
        >>> service = UserService(repository, logger)
        >>> user = service.create_user(CreateUserInput(...))
    """

    def __init__(self, repository: UserRepository, logger: Logger) -> None:
        """Initialiser le service utilisateur.

        Args:
            repository: Couche d'accès aux données pour les utilisateurs.
            logger: Logger pour le suivi des opérations.
        """
        self.repository = repository
        self.logger = logger

Pattern 6 : Longueur de Ligne et Formatting

Définissez la longueur de ligne à 120 caractères pour les affichages modernes tout en maintenant la lisibilité.

# Bon : Sauts de ligne lisibles
def create_user(
    email: str,
    name: str,
    role: UserRole = UserRole.MEMBER,
    notify: bool = True,
) -> User:
    ...

# Bon : Chaîner les appels de méthode clairement
result = (
    db.query(User)
    .filter(User.active == True)
    .order_by(User.created_at.desc())
    .limit(10)
    .all()
)

# Bon : Formater les longues chaînes
error_message = (
    f"Failed to process user {user_id}: "
    f"received status {response.status_code} "
    f"with body {response.text[:100]}"
)

Pattern 7 : Documentation du Projet

Structure README :

# Project Name

Brève description de ce que fait le projet.

## Installation

\`\`\`bash
pip install myproject
\`\`\`

## Démarrage Rapide

\`\`\`python
from myproject import Client

client = Client(api_key="...")
result = client.process(data)
\`\`\`

## Configuration

Documentez les variables d'environnement et les options de configuration.

## Développement

\`\`\`bash
pip install -e ".[dev]"
pytest
\`\`\`

Format CHANGELOG (Keep a Changelog) :

# Changelog

## [Unreleased]

### Added
- New feature X

### Changed
- Modified behavior of Y

### Fixed
- Bug in Z

Résumé des Bonnes Pratiques

  1. Utiliser ruff - Outil unique pour le linting et le formatting
  2. Activer mypy strict - Détecter les erreurs de type avant l'exécution
  3. Lignes de 120 caractères - Standard moderne pour la lisibilité
  4. Noms descriptifs - Clarté plutôt que concision
  5. Imports absolus - Plus maintenables que les imports relatifs
  6. Docstrings style Google - Documentation cohérente et lisible
  7. Documenter les API publiques - Chaque fonction publique a besoin d'une docstring
  8. Garder la documentation à jour - Traiter la documentation comme du code
  9. Automatiser en CI - Exécuter les linters à chaque commit
  10. Cibler Python 3.10+ - Pour les nouveaux projets, Python 3.12+ est recommandé pour les fonctionnalités modernes du langage

Skills similaires