Qu’est-ce que WordPress et pourquoi l’utiliser en 2025 ?
Introduction Vous avez probablement entendu parler de WordPress, mais savez-vous réellement ce que c'est et…
"""
project/library.py - Système de gestion de bibliothèque complet
"""
from typing import List, Optional, Dict, Set
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from abc import ABC, abstractmethod
from enum import Enum
import json
class StatutEmprunt(Enum):
"""Statuts possibles d'un emprunt."""
ENCOURS = "en cours"
RETOURNE = "retourné"
ENRETARD = "en retard"
class TypeDocument(Enum):
"""Types de documents disponibles."""
LIVRE = "livre"
MAGAZINE = "magazine"
DVD = "dvd"
CD = "cd"
# Classes de base
class Document(ABC):
"""
Classe abstraite représentant un document de bibliothèque.
Attributes:
id: Identifiant unique
titre: Titre du document
disponible: Si le document est disponible
"""
def init(self, iddoc: str, titre: str) -> None:
"""
Initialise un document.
Args:
iddoc: Identifiant unique
titre: Titre du document
"""
self.id = iddoc
self.titre = titre
self.disponible = True
self.dateajout = datetime.now()
@abstractmethod
def dureeemprunt(self) -> int:
"""Retourne la durée d'emprunt en jours."""
pass
@abstractmethod
def typedocument(self) -> TypeDocument:
"""Retourne le type du document."""
pass
def emprunter(self) -> bool:
"""
Marque le document comme emprunté.
Returns:
True si l'emprunt est possible
"""
if not self.disponible:
return False
self.disponible = False
return True
def retourner(self) -> bool:
"""
Marque le document comme retourné.
Returns:
True si le retour est effectué
"""
if self.disponible:
return False
self.disponible = True
return True
def str(self) -> str:
"""Représentation string du document."""
statut = "Disponible" if self.disponible else "Emprunté"
return f"[{self.id}] {self.titre} - {statut}"
def eq(self, other: object) -> bool:
"""Comparaison d'égalité."""
if not isinstance(other, Document):
return NotImplemented
return self.id == other.id
def hash(self) -> int:
"""Hash pour utilisation dans sets et dict."""
return hash(self.id)
class Livre(Document):
"""
Livre de bibliothèque.
Attributes:
auteur: Auteur du livre
isbn: Code ISBN
nombrepages: Nombre de pages
"""
def init(
self,
iddoc: str,
titre: str,
auteur: str,
isbn: str,
nombrepages: int
) -> None:
"""
Initialise un livre.
Args:
iddoc: Identifiant unique
titre: Titre du livre
auteur: Auteur
isbn: Code ISBN
nombrepages: Nombre de pages
"""
super().init(iddoc, titre)
self.auteur = auteur
self.isbn = isbn
self.nombrepages = nombrepages
def dureeemprunt(self) -> int:
"""Durée d'emprunt d'un livre: 21 jours."""
return 21
def typedocument(self) -> TypeDocument:
"""Type: livre."""
return TypeDocument.LIVRE
def str(self) -> str:
"""Représentation string du livre."""
base = super().str()
return f"{base} par {self.auteur}"
class Magazine(Document):
"""
Magazine de bibliothèque.
Attributes:
numero: Numéro du magazine
mois: Mois de publication
annee: Année de publication
"""
def init(
self,
iddoc: str,
titre: str,
numero: int,
mois: str,
annee: int
) -> None:
"""
Initialise un magazine.
Args:
iddoc: Identifiant unique
titre: Titre du magazine
numero: Numéro
mois: Mois de publication
annee: Année de publication
"""
super().init(iddoc, titre)
self.numero = numero
self.mois = mois
self.annee = annee
def dureeemprunt(self) -> int:
"""Durée d'emprunt d'un magazine: 7 jours."""
return 7
def typedocument(self) -> TypeDocument:
"""Type: magazine."""
return TypeDocument.MAGAZINE
def str(self) -> str:
"""Représentation string du magazine."""
base = super().str()
return f"{base} - N°{self.numero} ({self.mois} {self.annee})"
class DVD(Document):
"""
DVD de bibliothèque.
Attributes:
realisateur: Réalisateur du film
dureeminutes: Durée en minutes
"""
def init(
self,
iddoc: str,
titre: str,
realisateur: str,
dureeminutes: int
) -> None:
"""
Initialise un DVD.
Args:
iddoc: Identifiant unique
titre: Titre du film
realisateur: Réalisateur
dureeminutes: Durée
"""
super().init(iddoc, titre)
self.realisateur = realisateur
self.dureeminutes = dureeminutes
def dureeemprunt(self) -> int:
"""Durée d'emprunt d'un DVD: 14 jours."""
return 14
def typedocument(self) -> TypeDocument:
"""Type: DVD."""
return TypeDocument.DVD
def str(self) -> str:
"""Représentation string du DVD."""
base = super().str()
return f"{base} de {self.realisateur}"
@dataclass
class Emprunt:
"""
Représente un emprunt de document.
Attributes:
document: Document emprunté
dateemprunt: Date de l'emprunt
dateretourprevue: Date de retour prévue
dateretoureffective: Date de retour effective (None si en cours)
"""
document: Document
dateemprunt: datetime = field(defaultfactory=datetime.now)
dateretourprevue: datetime = field(init=False)
dateretoureffective: Optional[datetime] = None
def postinit(self) -> None:
"""Calcule la date de retour prévue."""
self.dateretourprevue = (
self.dateemprunt + timedelta(days=self.document.dureeemprunt())
)
@property
def statut(self) -> StatutEmprunt:
"""Détermine le statut de l'emprunt."""
if self.dateretoureffective:
return StatutEmprunt.RETOURNE
if datetime.now() > self.dateretourprevue:
return StatutEmprunt.ENRETARD
return StatutEmprunt.ENCOURS
@property
def joursretard(self) -> int:
"""Calcule le nombre de jours de retard."""
if self.statut != StatutEmprunt.ENRETARD:
return 0
datereference = self.dateretoureffective or datetime.now()
delta = datereference - self.dateretourprevue
return max(0, delta.days)
def calculerpenalite(self, tarifjour: float = 0.50) -> float:
"""
Calcule la pénalité de retard.
Args:
tarifjour: Tarif par jour de retard
Returns:
Montant de la pénalité
"""
return self.joursretard tarifjour
def str(self) -> str:
"""Représentation string de l'emprunt."""
retardinfo = f" - {self.joursretard}j de retard" if self.joursretard > 0 else ""
return (
f"{self.document.titre} "
f"(emprunté le {self.dateemprunt.strftime('%d/%m/%Y')}) "
f"- {self.statut.value}{retardinfo}"
)
class Adherent:
"""
Adhérent de la bibliothèque.
Attributes:
id: Identifiant unique
nom: Nom de famille
prenom: Prénom
email: Adresse email
"""
MAXEMPRUNTS: int = 5 # Nombre max d'emprunts simultanés
def init(
self,
idadherent: str,
nom: str,
prenom: str,
email: str
) -> None:
"""
Initialise un adhérent.
Args:
idadherent: Identifiant unique
nom: Nom de famille
prenom: Prénom
email: Adresse email
"""
self.id = idadherent
self.nom = nom
self.prenom = prenom
self.email = email
self.dateinscription = datetime.now()
self.empruntsencours: List[Emprunt] = []
self.historiqueemprunts: List[Emprunt] = []
@property
def nomcomplet(self) -> str:
"""Retourne le nom complet."""
return f"{self.prenom} {self.nom}"
def peutemprunter(self) -> bool:
"""Vérifie si l'adhérent peut emprunter."""
# Ne peut pas emprunter si nombre max atteint
if len(self.empruntsencours) >= self.MAXEMPRUNTS:
return False
# Ne peut pas emprunter s'il a des retards
for emprunt in self.empruntsencours:
if emprunt.statut == StatutEmprunt.ENRETARD:
return False
return True
def emprunterdocument(self, document: Document) -> bool:
"""
Emprunte un document.
Args:
document: Document à emprunter
Returns:
True si l'emprunt est effectué
"""
if not self.peutemprunter():
return False
if not document.emprunter():
return False
emprunt = Emprunt(document)
self.empruntsencours.append(emprunt)
return True
def retournerdocument(self, document: Document) -> bool:
"""
Retourne un document.
Args:
document: Document à retourner
Returns:
True si le retour est effectué
"""
# Trouver l'emprunt correspondant
emprunttrouve = None
for emprunt in self.empruntsencours:
if emprunt.document == document:
emprunttrouve = emprunt
break
if not emprunttrouve:
return False
# Marquer comme retourné
emprunttrouve.dateretoureffective = datetime.now()
document.retourner()
# Déplacer dans l'historique
self.empruntsencours.remove(emprunttrouve)
self.historiqueemprunts.append(emprunttrouve)
return True
def penalitestotales(self) -> float:
"""Calcule le total des pénalités."""
return sum(
emprunt.calculerpenalite()
for emprunt in self.empruntsencours
if emprunt.statut == StatutEmprunt.ENRETARD
)
def str(self) -> str:
"""Représentation string de l'adhérent."""
return (
f"{self.nomcomplet} ({self.id}) - "
f"{len(self.empruntsencours)} emprunt(s) en cours"
)
class Bibliotheque:
"""
Gestionnaire principal de la bibliothèque.
Attributes:
nom: Nom de la bibliothèque
documents: Collection de documents
adherents: Collection d'adhérents
"""
def init(self, nom: str) -> None:
"""
Initialise la bibliothèque.
Args:
nom: Nom de la bibliothèque
"""
self.nom = nom
self.documents: Dict[str, Document] = {}
self.adherents: Dict[str, Adherent] = {}
# Gestion des documents
def ajouterdocument(self, document: Document) -> None:
"""
Ajoute un document au catalogue.
Args:
document: Document à ajouter
Raises:
ValueError: Si l'ID existe déjà
"""
if document.id in self.documents:
raise ValueError(f"Document {document.id} existe déjà")
self.documents[document.id] = document
print(f"✓ Document ajouté: {document}")
def retirerdocument(self, iddoc: str) -> bool:
"""
Retire un document du catalogue.
Args:
iddoc: ID du document
Returns:
True si retiré avec succès
"""
if iddoc not in self.documents:
return False
document = self.documents[iddoc]
if not document.disponible:
print(f"✗ Impossible de retirer {document}: document emprunté")
return False
del self.documents[iddoc]
print(f"✓ Document retiré: {document}")
return True
def rechercherdocuments(
self,
titre: Optional[str] = None,
typedoc: Optional[TypeDocument] = None,
disponibleseulement: bool = False
) -> List[Document]:
"""
Recherche des documents.
Args:
titre: Recherche dans le titre (partielle)
typedoc: Filtrer par type
disponibleseulement: Uniquement les documents disponibles
Returns:
Liste des documents correspondants
"""
resultats = list(self.documents.values())
if titre:
resultats = [
d for d in resultats
if titre.lower() in d.titre.lower()
]
if typedoc:
resultats = [
d for d in resultats
if d.typedocument() == typedoc
]
if disponibleseulement:
resultats = [d for d in resultats if d.disponible]
return resultats
# Gestion des adhérents
def inscrireadherent(self, adherent: Adherent) -> None:
"""
Inscrit un adhérent.
Args:
adherent: Adhérent à inscrire
Raises:
ValueError: Si l'ID existe déjà
"""
if adherent.id in self.adherents:
raise ValueError(f"Adhérent {adherent.id} existe déjà")
self.adherents[adherent.id] = adherent
print(f"✓ Adhérent inscrit: {adherent}")
def desinscrireadherent(self, idadherent: str) -> bool:
"""
Désinscrit un adhérent.
Args:
idadherent: ID de l'adhérent
Returns:
True si désinscrit avec succès
"""
if idadherent not in self.adherents:
return False
adherent = self.adherents[idadherent]
if adherent.empruntsencours:
print(f"✗ Impossible de désinscrire {adherent}: emprunts en cours")
return False
del self.adherents[idadherent]
print(f"✓ Adhérent désinscrit: {adherent}")
return True
# Gestion des emprunts
def emprunter(self, idadherent: str, iddocument: str) -> bool:
"""
Effectue un emprunt.
Args:
idadherent: ID de l'adhérent
iddocument: ID du document
Returns:
True si l'emprunt est effectué
"""
if idadherent not in self.adherents:
print(f"✗ Adhérent {idadherent} inconnu")
return False
if iddocument not in self.documents:
print(f"✗ Document {iddocument} inconnu")
return False
adherent = self.adherents[idadherent]
document = self.documents[iddocument]
if not adherent.peutemprunter():
print(f"✗ {adherent.nomcomplet} ne peut pas emprunter")
return False
if adherent.emprunterdocument(document):
print(f"✓ {adherent.nomcomplet} a emprunté: {document.titre}")
return True
print(f"✗ Document {document.titre} non disponible")
return False
def retourner(self, idadherent: str, iddocument: str) -> bool:
"""
Effectue un retour.
Args:
idadherent: ID de l'adhérent
iddocument: ID du document
Returns:
True si le retour est effectué
"""
if idadherent not in self.adherents:
return False
if iddocument not in self.documents:
return False
adherent = self.adherents[idadherent]
document = self.documents[iddocument]
if adherent.retournerdocument(document):
penalite = 0
for emprunt in adherent.historiqueemprunts:
if emprunt.document == document:
penalite = emprunt.calculerpenalite()
break
msg = f"✓ {adherent.nomcomplet} a retourné: {document.titre}"
if penalite > 0:
msg += f" (pénalité: {penalite}€)"
print(msg)
return True
print(f"✗ Erreur lors du retour")
return False
# Statistiques et rapports
def statistiques(self) -> Dict[str, any]:
"""Génère des statistiques sur la bibliothèque."""
totaldocuments = len(self.documents)
documentsdisponibles = sum(
1 for d in self.documents.values() if d.disponible
)
empruntsencours = sum(
len(a.empruntsencours) for a in self.adherents.values()
)
empruntsenretard = sum(
1 for a in self.adherents.values()
for e in a.empruntsencours
if e.statut == StatutEmprunt.ENRETARD
)
penalitestotales = sum(
a.penalitestotales() for a in self.adherents.values()
)
return {
"totaldocuments": totaldocuments,
"documentsdisponibles": documentsdisponibles,
"documentsempruntes": totaldocuments - documentsdisponibles,
"totaladherents": len(self.adherents),
"empruntsencours": empruntsencours,
"empruntsenretard": empruntsenretard,
"penalitestotales": penalitestotales
}
def afficherstatistiques(self) -> None:
"""Affiche les statistiques."""
stats = self.statistiques()
print(f"n=== Statistiques - {self.nom} ===")
print(f"Documents: {stats['totaldocuments']} "
f"({stats['documentsdisponibles']} disponibles)")
print(f"Adhérents: {stats['totaladherents']}")
print(f"Emprunts en cours: {stats['empruntsencours']}")
print(f"Emprunts en retard: {stats['empruntsenretard']}")
print(f"Pénalités totales: {stats['penalitestotales']}€")
def documentspopulaires(self, limite: int = 5) -> List[tuple]:
"""
Retourne les documents les plus empruntés.
Args:
limite: Nombre de documents à retourner
Returns:
Liste de tuples (document, nombreemprunts)
"""
compteur: Dict[Document, int] = {}
for adherent in self.adherents.values():
tousemprunts = (
adherent.empruntsencours +
adherent.historiqueemprunts
)
for emprunt in tousemprunts:
doc = emprunt.document
compteur[doc] = compteur.get(doc, 0) + 1
# Trier par nombre d'emprunts décroissant
populaires = sorted(
compteur.items(),
key=lambda x: x[1],
reverse=True
)
return populaires[:limite]
def demobibliotheque() -> None:
"""Démonstration du système de bibliothèque."""
# Création de la bibliothèque
biblio = Bibliotheque("Bibliothèque Municipale")
print("=== Ajout de documents ===n")
# Ajout de livres
livre1 = Livre(
"L001",
"1984",
"George Orwell",
"978-0451524935",
328
)
livre2 = Livre(
"L002",
"Le Petit Prince",
"Antoine de Saint-Exupéry",
"978-0156012195",
96
)
biblio.ajouterdocument(livre1)
biblio.ajouterdocument(livre2)
# Ajout de magazines
mag1 = Magazine("M001", "Science & Vie", 1250, "Janvier", 2024)
biblio.ajouterdocument(mag1)
# Ajout de DVDs
dvd1 = DVD("D001", "Inception", "Christopher Nolan", 148)
biblio.ajouterdocument(dvd1)
# Inscription d'adhérents
print("n=== Inscription d'adhérents ===n")
adherent1 = Adherent("A001", "Dupont", "Marie", "marie.dupont@example.com")
adherent2 = Adherent("A002", "Martin", "Pierre", "pierre.martin@example.com")
biblio.inscrireadherent(adherent1)
biblio.inscrireadherent(adherent2)
# Emprunts
print("n=== Emprunts ===n")
biblio.emprunter("A001", "L001")
biblio.emprunter("A001", "M001")
biblio.emprunter("A002", "D001")
# Recherche
print("n=== Recherche de documents ===n")
livresdispo = biblio.rechercherdocuments(
typedoc=TypeDocument.LIVRE,
disponibleseulement=True
)
print(f"Livres disponibles: {len(livresdispo)}")
for livre in livresdispo:
print(f" - {livre}")
# Statistiques
biblio.afficherstatistiques()
# Retour
print("n=== Retours ===n")
biblio.retourner("A001", "L001")
# Statistiques finales
biblio.afficherstatistiques()
# Documents populaires
print("n=== Documents populaires ===n")
for doc, nombre in biblio.documentspopulaires(3):
print(f"{doc.titre}: {nombre} emprunt(s)")
if name == "main":
demobibliotheque()
"""
tests/testlibrary.py - Tests pour le système de bibliothèque
"""
import pytest
from datetime import datetime, timedelta
from project.library import (
Livre,
Magazine,
DVD,
Adherent,
Bibliotheque,
Emprunt,
StatutEmprunt,
TypeDocument
)
class TestDocument:
"""Tests pour les classes de documents."""
def testcreationlivre(self):
"""Test de création d'un livre."""
livre = Livre("L001", "Test", "Auteur", "123456", 200)
assert livre.id == "L001"
assert livre.titre == "Test"
assert livre.auteur == "Auteur"
assert livre.disponible is True
assert livre.dureeemprunt() == 21
assert livre.typedocument() == TypeDocument.LIVRE
def testcreationmagazine(self):
"""Test de création d'un magazine."""
mag = Magazine("M001", "Test Mag", 1, "Janvier", 2024)
assert mag.numero == 1
assert mag.dureeemprunt() == 7
assert mag.typedocument() == TypeDocument.MAGAZINE
def testcreationdvd(self):
"""Test de création d'un DVD."""
dvd = DVD("D001", "Test Film", "Réalisateur", 120)
assert dvd.realisateur == "Réalisateur"
assert dvd.dureeemprunt() == 14
assert dvd.typedocument() == TypeDocument.DVD
def testempruntdocument(self):
"""Test de l'emprunt d'un document."""
livre = Livre("L001", "Test", "Auteur", "123456", 200)
assert livre.emprunter() is True
assert livre.disponible is False
assert livre.emprunter() is False # Déjà emprunté
def testretourdocument(self):
"""Test du retour d'un document."""
livre = Livre("L001", "Test", "Auteur", "123456", 200)
livre.emprunter()
assert livre.retourner() is True
assert livre.disponible is True
class TestEmprunt:
"""Tests pour la classe Emprunt."""
def testcreationemprunt(self):
"""Test de création d'un emprunt."""
livre = Livre("L001", "Test", "Auteur", "123456", 200)
emprunt = Emprunt(livre)
assert emprunt.document == livre
assert emprunt.statut == StatutEmprunt.ENCOURS
def testcalculdateretour(self):
"""Test du calcul de la date de retour."""
livre = Livre("L001", "Test", "Auteur", "123456", 200)
emprunt = Emprunt(livre)
expecteddate = datetime.now() + timedelta(days=21)
assert emprunt.dateretourprevue.date() == expecteddate.date()
def teststatutenretard(self):
"""Test du statut en retard."""
livre = Livre("L001", "Test", "Auteur", "123456", 200)
emprunt = Emprunt(livre)
# Simuler un emprunt en retard
emprunt.dateemprunt = datetime.now() - timedelta(days=30)
emprunt.dateretourprevue = datetime.now() - timedelta(days=9)
assert emprunt.statut == StatutEmprunt.ENRETARD
assert emprunt.joursretard > 0
def testcalculpenalite(self):
"""Test du calcul des pénalités."""
livre = Livre("L001", "Test", "Auteur", "123456", 200)
emprunt = Emprunt(livre)
# Simuler 10 jours de retard
emprunt.dateemprunt = datetime.now() - timedelta(days=31)
emprunt.dateretourprevue = datetime.now() - timedelta(days=10)
penalite = emprunt.calculerpenalite(0.50)
assert penalite == 10 0.50
class TestAdherent:
"""Tests pour la classe Adhérent."""
@pytest.fixture
def adherent(self):
"""Fixture pour créer un adhérent."""
return Adherent("A001", "Dupont", "Marie", "marie@example.com")
@pytest.fixture
def livre(self):
"""Fixture pour créer un livre."""
return Livre("L001", "Test", "Auteur", "123456", 200)
def testcreationadherent(self, adherent):
"""Test de création d'un adhérent."""
assert adherent.id == "A001"
assert adherent.nom == "Dupont"
assert adherent.nomcomplet == "Marie Dupont"
assert len(adherent.empruntsencours) == 0
def testempruntdocument(self, adherent, livre):
"""Test d'emprunt de document."""
assert adherent.emprunterdocument(livre) is True
assert len(adherent.empruntsencours) == 1
assert livre.disponible is False
def testlimiteemprunts(self, adherent):
"""Test de la limite d'emprunts."""
# Emprunter 5 livres (limite max)
for i in range(5):
livre = Livre(f"L{i}", f"Livre {i}", "Auteur", f"ISBN{i}", 200)
adherent.emprunterdocument(livre)
# Le 6ème emprunt doit échouer
livre6 = Livre("L006", "Livre 6", "Auteur", "ISBN6", 200)
assert adherent.peutemprunter() is False
assert adherent.emprunterdocument(livre6) is False
def testretourdocument(self, adherent, livre):
"""Test de retour de document."""
adherent.emprunterdocument(livre)
assert adherent.retournerdocument(livre) is True
assert len(adherent.empruntsencours) == 0
assert len(adherent.historiqueemprunts) == 1
assert livre.disponible is True
class TestBibliotheque:
"""Tests pour la classe Bibliothèque."""
@pytest.fixture
def bibliotheque(self):
"""Fixture pour créer une bibliothèque."""
return Bibliotheque("Test Library")
@pytest.fixture
def livre(self):
"""Fixture pour créer un livre."""
return Livre("L001", "Test", "Auteur", "123456", 200)
@pytest.fixture
def adherent(self):
"""Fixture pour créer un adhérent."""
return Adherent("A001", "Dupont", "Marie", "marie@example.com")
def testcreationbibliotheque(self, bibliotheque):
"""Test de création de bibliothèque."""
assert bibliotheque.nom == "Test Library"
assert len(bibliotheque.documents) == 0
assert len(bibliotheque.adherents) == 0
def testajouterdocument(self, bibliotheque, livre):
"""Test d'ajout de document."""
bibliotheque.ajouterdocument(livre)
assert len(bibliotheque.documents) == 1
assert "L001" in bibliotheque.documents
def testajouterdocumentdoublon(self, bibliotheque, livre):
"""Test d'ajout de document avec ID existant."""
bibliotheque.ajouterdocument(livre)
with pytest.raises(ValueError):
bibliotheque.ajouterdocument(livre)
def testretirerdocument(self, bibliotheque, livre):
"""Test de retrait de document."""
bibliotheque.ajouterdocument(livre)
assert bibliotheque.retirerdocument("L001") is True
assert len(bibliotheque.documents) == 0
def testrechercherdocuments(self, bibliotheque):
"""Test de recherche de documents."""
livre1 = Livre("L001", "Python Programming", "Author1", "123", 200)
livre2 = Livre("L002", "Java Programming", "Author2", "456", 300)
mag = Magazine("M001", "Python Magazine", 1, "Jan", 2024)
bibliotheque.ajouterdocument(livre1)
bibliotheque.ajouterdocument(livre2)
bibliotheque.ajouterdocument(mag)
# Recherche par titre
resultats = bibliotheque.rechercherdocuments(titre="Python")
assert len(resultats) == 2
# Recherche par type
livres = bibliotheque.rechercherdocuments(typedoc=TypeDocument.LIVRE)
assert len(livres) == 2
def testinscrireadherent(self, bibliotheque, adherent):
"""Test d'inscription d'adhérent."""
bibliotheque.inscrireadherent(adherent)
assert len(bibliotheque.adherents) == 1
assert "A001" in bibliotheque.adherents
def testempruntcomplet(self, bibliotheque, livre, adherent):
"""Test du processus d'emprunt complet."""
bibliotheque.ajouterdocument(livre)
bibliotheque.inscrireadherent(adherent)
assert bibliotheque.emprunter("A001", "L001") is True
assert livre.disponible is False
assert len(adherent.empruntsencours) == 1
def testretourcomplet(self, bibliotheque, livre, adherent):
"""Test du processus de retour complet."""
bibliotheque.ajouterdocument(livre)
bibliotheque.inscrireadherent(adherent)
bibliotheque.emprunter("A001", "L001")
assert bibliotheque.retourner("A001", "L001") is True
assert livre.disponible is True
assert len(adherent.empruntsencours) == 0
def teststatistiques(self, bibliotheque, livre, adherent):
"""Test des statistiques."""
bibliotheque.ajouterdocument(livre)
bibliotheque.inscrireadherent(adherent)
bibliotheque.emprunter("A001", "L001")
stats = bibliotheque.statistiques()
assert stats["totaldocuments"] == 1
assert stats["documentsdisponibles"] == 0
assert stats["documentsempruntes"] == 1
assert stats["totaladherents"] == 1
assert stats["empruntsen_cours"] == 1
if name == "main":
pytest.main([file, "-v", "--cov=project.library"])
Dans cet article, vous avez découvert la programmation orientée objet en Python avec:
– Single Responsibility: Une classe = une responsabilité
– Open/Closed: Ouvert à l’extension, fermé à la modification
– Liskov Substitution: Les sous-classes doivent être substituables
– Interface Segregation: Interfaces spécifiques plutôt que génériques
– Dependency Inversion: Dépendre d’abstractions, pas d’implémentations
Continuez votre apprentissage avec:
Cet article est vivant — corrections, contre-arguments et retours de production sont les bienvenus. Trois canaux, choisissez celui qui vous convient.