SDK Python moderne, typé et asynchrone pour exploiter les données publiques FFBB : clubs, compétitions, rencontres, classements, salles, officiels et recherche Meilisearch.
Installation ⹠Démarrage rapide ⹠Fonctionnalités ⹠Recherche ⹠Async ⹠Développement
ffbb_data_client simplifie l'accĂšs aux API FFBB et Ă leurs index Meilisearch avec :
- une façade unique :
FFBBDataClient; - des modÚles Pydantic v2 typés ;
- une API utilisable en synchrone ou en
async/await; - une gestion automatique des tokens via
TokenManager; - du cache HTTP configurable via
hishel; - des helpers prĂȘts pour l'intĂ©gration MCP / agents IA.
Principales évolutions récentes :
- refactor architecture :
FFBBDataClient(2865 â 272 lignes) dĂ©coupĂ© en_RestFacade+_SearchFacadeâ API publique 100% compatible ; - unification sync/async : les mĂ©thodes synchrones dĂ©lĂšguent Ă leurs homologues asynchrones via
_run_async(), éliminant ~604 lignes de duplication ; - nouvelles entités : EDF (matches, joueurs, rosters, équipes), Genius Sport (matches, live logs), Rematch Videos ;
- cache SQLite concurrency-safe : fichiers séparés pour sync (
http_cache.db) et async (http_cache_async.db) ; - CI renforcée : mypy + pyright + CodeQL + Dependabot + hook pre-push + wrapper parity check ;
- nettoyage : suppression du shim
ffbb_api_client_v3, scripts morts et code mort (invalidate_pattern).
Voir aussi : CHANGELOG.md et RELEASE_NOTES.md.
pip install ffbb-data-clientPour contribuer ou exécuter les tests :
git clone https://github.com/nickdesi/ffbb-data-client.git
cd ffbb-data-client
pip install -e ".[testing]"Prérequis : Python >=3.10.
from ffbb_data_client import FFBBDataClient
client = FFBBDataClient.create()
# Recherche globale sur les index FFBB
results = client.multi_search("Pau Orthez")
for result in results or []:
print(result.index_uid, len(result.hits or []))
# Lives en cours
lives = client.get_lives()FFBBDataClient.create() résout automatiquement les tokens si aucun token n'est passé explicitement.
| Domaine | Capacités |
|---|---|
| API FFBB | clubs, compétitions, organismes, saisons, poules, classements, rencontres, lives |
| Entités additionnelles | EDF (matches, joueurs, rosters, équipes), Genius Sport, Rematch Videos |
| Recherche | organismes, compétitions, rencontres, salles, terrains, pratiques, tournois, engagements et formations |
| REST typé | récupération de ressources individuelles avec modÚles Pydantic v2 |
| Async | mĂ©thodes *_async() â source de vĂ©ritĂ© ; sync dĂ©lĂšgue via _run_async() |
| Cache | cache HTTP hishel, sessions httpx réutilisées, retries configurables, SQLite séparés sync/async |
| Sécurité | masquage des tokens dans les logs, CodeQL scanning, Dependabot |
| IA / MCP | structure compatible avec des wrappers MCP et agents IA |
results = client.multi_search("Clermont")organismes = client.search_organismes(
"Clermont",
filter=['codePostal = "63000"'],
sort=["nom:asc"],
limit=10,
)
rencontres = client.search_rencontres("N1M", limit=20)
salles = client.search_salles("Maison des Sports", limit=5)
engagements = client.search_engagements("U15M", limit=20)clubs = client.search_organismes_by_geo(
lat=45.7772,
lng=3.0870,
radius_km=20,
limit=20,
)| Ressource | Méthode sync | Méthode async |
|---|---|---|
| Recherche globale | multi_search() |
multi_search_async() |
| Clubs / organismes | search_organismes() |
search_organismes_async() |
| Compétitions | search_competitions() |
search_competitions_async() |
| Rencontres | search_rencontres() |
search_rencontres_async() |
| Salles | search_salles() |
search_salles_async() |
| Terrains | search_terrains() |
search_terrains_async() |
| Pratiques | search_pratiques() |
search_pratiques_async() |
| Tournois | search_tournois() |
search_tournois_async() |
| Engagements | search_engagements() |
search_engagements_async() |
| Formations | search_formations() |
search_formations_async() |
# Ressources principales
organisme = client.get_organisme(12345)
competition = client.get_competition(67890)
poule = client.get_poule(11111)
# Ressources ajoutées récemment
rencontre = client.get_rencontre(22222)
officiel = client.get_officiel(33333)
entraineur = client.get_entraineur(44444)Les assets Directus et autres collections peuvent ĂȘtre exploitĂ©s via les mĂ©thodes REST/listing dĂ©diĂ©es exposĂ©es par le client lorsque disponibles.
Les réponses sont converties en modÚles Pydantic lorsque le schéma est connu, ce qui apporte validation, autocomplétion et sérialisation propre.
import asyncio
from ffbb_data_client import FFBBDataClient
async def main() -> None:
client = FFBBDataClient.create()
results = await client.search_organismes_async("ASVEL")
lives = await client.get_lives_async()
print(results.estimated_total_hits if results else 0)
print(len(lives or []))
asyncio.run(main())Par défaut, le client utilise TokenManager.get_tokens() au moment de la création :
from ffbb_data_client import FFBBDataClient, TokenManager
tokens = TokenManager.get_tokens()
client = FFBBDataClient.create(
api_bearer_token=tokens.api_token,
meilisearch_bearer_token=tokens.meilisearch_token,
)Il est donc possible de laisser le client résoudre les tokens automatiquement ou de les fournir explicitement selon le contexte d'exécution.
src/ffbb_data_client/
âââ clients/
â âââ ffbb_data_client.py # Façade publique (272 lignes, delegation)
â âââ _rest_facade.py # Façade REST API (Directus)
â âââ _search_facade.py # Façade recherche Meilisearch
â âââ api_ffbb_app_client.py # Client REST FFBB (async source of truth)
â âââ meilisearch_ffbb_client.py # Client recherche Meilisearch
âââ helpers/ # RequĂȘtes HTTP, multi-search, conversions
âââ models/ # ModĂšles Pydantic v2
âââ utils/ # cache (sync/async sĂ©parĂ©s), tokens, logging sĂ©curisĂ©
âââ data/ # schĂ©mas et mĂ©tadonnĂ©es embarquĂ©s
Architecture sync/async : Depuis v2.1.0, les méthodes asynchrones sont la source de vérité. Les méthodes synchrones délÚguent via
_run_async(), un helper qui gÚre les event loops imbriqués avecThreadPoolExecutor.Architecture facades : Depuis v2.2.0,
FFBBDataClientest une fine coquille qui compose_RestFacadeet_SearchFacade. L'API publique reste identique âclient.get_organisme(123)fonctionne comme avant.
pip install -e ".[testing]"
pytest tests/Commandes utiles :
pytest tests/unit/
pytest tests/integration/
pytest tests/ --cov=src
tox -e type # mypy + pyrightHooks automatiques :
- pre-push : exécute mypy + pyright avant chaque push
- pre-commit : black, isort, flake8, trailing-whitespace
Documentation complémentaire :
Le projet intÚgre un systÚme robuste de surveillance quotidienne de l'API de production de la FFBB (Directus & Meilisearch) afin de détecter immédiatement l'apparition de nouvelles ressources, de nouveaux champs ou de changements de types.
- Script de découverte :
scripts/discover_endpoints.pyinterroge dynamiquement l'OpenAPI spec Directus de la FFBB, extrait toutes les collections, sonde les index Meilisearch (via un échantillonnage agrégé sur 20 hits) et calcule les différences structurelles avec les fichiers locaux. - Détection de dérive : Le script compare les structures internes de chaque modÚle (propriétés ajoutées, supprimées ou types modifiés) ainsi que les attributs Meilisearch, et génÚre un rapport consolidé dans
data/api_update_summary.md.
Un workflow quotidien (update-ffbb-api-discovery.yml) s'exécute chaque matin à 5h17 UTC pour :
- Télécharger l'OpenAPI spec et sonder Meilisearch en production.
- Analyser les dérives structurelles.
- Si un changement structurel est détecté (ajout de collection, de propriétés ou d'index), le workflow ouvre automatiquement une Pull Request sur GitHub contenant un résumé des modifications pour permettre aux développeurs de mettre à jour les modÚles Pydantic.
Pour lancer manuellement la découverte d'API et mettre à jour les fichiers de schémas locaux :
python scripts/discover_endpoints.pyLe client sert de base au serveur MCP FFBB et expose une API stable pour construire des outils agent-friendly : recherche de clubs, récupération de poules, classements, lives, calendriers et détails de rencontres.
Projet associé : FFBB-MCP-Server
Les contributions sont bienvenues :
- ouvrez une issue pour un bug ;
- proposez une évolution via les discussions ;
- lancez les tests localement avant une pull request.
Distribué sous licence Apache-2.0. Voir LICENSE.txt.