Metadata-Version: 2.4
Name: ffbb_api_client_v3
Version: 1.5.5
Summary: FFBB Python API client — French Basketball Federation clubs, teams, competitions & live scores. Type-safe Pydantic models, async/sync, Meilisearch search, MCP-ready.
Home-page: https://github.com/nickdesi/FFBBApiClientV3
Author: nickdesi
Author-email: nicolas.desimone@gmail.com
License: Apache-2.0
Project-URL: Documentation, https://github.com/nickdesi/FFBBApiClientV3/blob/main/README.md
Project-URL: Source, https://github.com/nickdesi/FFBBApiClientV3
Project-URL: Changelog, https://github.com/nickdesi/FFBBApiClientV3/blob/main/CHANGELOG.md
Project-URL: Tracker, https://github.com/nickdesi/FFBBApiClientV3/issues
Project-URL: Release Notes, https://github.com/nickdesi/FFBBApiClientV3/blob/main/RELEASE_NOTES.md
Keywords: ffbb basketball french-basketball-federation api-client pydantic meilisearch async sports-data sdk python ffbb-api
Platform: any
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Framework :: AsyncIO
Classifier: Operating System :: OS Independent
Classifier: Natural Language :: French
Classifier: License :: OSI Approved :: Apache Software License
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8
License-File: LICENSE.txt
Requires-Dist: python-dotenv
Requires-Dist: readme_renderer
Requires-Dist: python-dateutil
Requires-Dist: httpx>=0.27.0
Requires-Dist: hishel[async]>=0.0.32
Requires-Dist: pydantic>=2.0.0
Provides-Extra: testing
Requires-Dist: setuptools; extra == "testing"
Requires-Dist: coverage>=7.0.0; extra == "testing"
Requires-Dist: pytest>=9.0.0; extra == "testing"
Requires-Dist: pytest-xdist>=3.0.0; extra == "testing"
Requires-Dist: pytest-cov>=7.0.0; extra == "testing"
Requires-Dist: respx>=0.21.0; extra == "testing"
Requires-Dist: pytest-asyncio>=0.23.0; extra == "testing"
Provides-Extra: typing
Requires-Dist: types-python-dateutil; extra == "typing"
Dynamic: license-file

<div align="center">

# 🏀 FFBB API Client V3

**La FFBB expose des APIs modernes. Personne n'avait fait le SDK. Maintenant c'est fait.**

[![PyPI](https://img.shields.io/pypi/v/ffbb_api_client_v3?color=blue&label=PyPI&logo=python)](https://pypi.org/project/ffbb_api_client_v3/)
[![Python](https://img.shields.io/pypi/pyversions/ffbb_api_client_v3?logo=python)](https://pypi.org/project/ffbb_api_client_v3/)
[![CI](https://github.com/nickdesi/FFBBApiClientV3/actions/workflows/ci.yml/badge.svg)](https://github.com/nickdesi/FFBBApiClientV3/actions/workflows/ci.yml)
[![Downloads](https://img.shields.io/pypi/dm/ffbb_api_client_v3?label=downloads%2Fmonth&color=orange)](https://pypi.org/project/ffbb_api_client_v3/)
[![License](https://img.shields.io/pypi/l/ffbb_api_client_v3?color=green)](LICENSE.txt)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.rst)
[![GitHub Stars](https://img.shields.io/github/stars/nickdesi/FFBBApiClientV3?style=social)](https://github.com/nickdesi/FFBBApiClientV3/stargazers)

[🚀 Quick Start](#-démarrage-en-30-secondes) •
[🔍 9 Index Meilisearch](#-les-9-index-meilisearch) •
[🤖 MCP / IA](#-intégration-ia--mcp-server) •
[🤝 Contribuer](#-contribuer) •
[📋 Changelog](CHANGELOG.md)

---

> **English:** The missing Python SDK for the French Basketball Federation (FFBB) APIs.
> Typed Pydantic models, async/sync, Meilisearch search across 9 indexes, HTTP caching, retry/timeout, token auto-renewal. **MCP-ready for AI agents.**

</div>

---

## Le problème

Tu veux construire une appli autour des données FFBB.

Tu appelles l'API. Tu récupères des `dict` bruts. Tu gères les tokens à la main. Il n'y a pas de types. Pas de cache. Pas d'async. Et si tu veux chercher sur plusieurs ressources, c'est 9 appels séparés.

**Ce projet résout tout ça.**

| Sans ce SDK | Avec ce SDK |
|---|---|
| `dict` bruts, zéro typage | ✅ ~60 modèles Pydantic v2 validés |
| Tokens manuels, renouvellement à la main | ✅ `TokenManager` auto-renouvellement |
| Chaque appel → quota + latence | ✅ Cache HTTP intégré (SQLite / mémoire) |
| Synchrone uniquement | ✅ Toutes les méthodes en `async/await` |
| 9 index Meilisearch = 9 appels séparés | ✅ `multi_search()` — 1 seul appel réseau |
| Aucun SDK officiel | ✅ Ce projet |

---

## 🚀 Démarrage en 30 secondes

```bash
pip install ffbb_api_client_v3
```

```python
from ffbb_api_client_v3 import FFBBAPIClientV3, TokenManager

# Les tokens publics FFBB sont résolus automatiquement
tokens = TokenManager.get_tokens()
client = FFBBAPIClientV3.create(
    api_bearer_token=tokens.api_token,
    meilisearch_bearer_token=tokens.meilisearch_token,
)

# Rechercher un club — résultat typé, pas de dict brut
clubs = client.search_organismes("Pau")
print(clubs.hits[0].nom)  # autocomplétion, validation, zéro KeyError

# Matchs en direct right now
lives = client.get_lives()

# Filtre natif Meilisearch
comps = client.search_competitions("Pro A", sort=["libelle:asc"], limit=5)

# Tout en async — FastAPI, agents IA, MCP
import asyncio
result = asyncio.run(client.search_organismes_async("Lyon"))
```

---

## ✨ Fonctionnalités

- 🏀 **Couverture API complète** — clubs, compétitions, saisons, poules, classements, matchs en direct
- 🔍 **9 index Meilisearch** — organismes, compétitions, rencontres, salles, pratiques, terrains, tournois, engagements, formations
- 🎛️ **Filtrage & tri natifs** — `filter`, `sort`, `limit` sur toutes les méthodes de recherche
- ⚡ **Sync + Async** — chaque méthode disponible en `async/await`
- 🔒 **Type-safe** — ~60 modèles Pydantic v2, zéro `dict` brut dans ton code
- 📦 **Cache HTTP intégré** — SQLite ou mémoire via `hishel[async]`, configurable
- 🔄 **Retry + Timeout** — robustesse réseau out-of-the-box, configurable
- 🔐 **Logging sécurisé** — tokens masqués automatiquement dans tous les logs
- 🤖 **MCP-ready** — wrapper officiel pour Claude, Cursor, Copilot
- 🧪 **400+ tests** — unitaires et d'intégration, CI GitHub Actions

---

## 🔍 Les 9 index Meilisearch

| Index | Sync | Async | Description |
|---|---|---|---|
| `ffbbserver_organismes` | `search_organismes()` | `…_async()` | Clubs, comités, ligues |
| `ffbbserver_competitions` | `search_competitions()` | `…_async()` | Compétitions officielles |
| `ffbbserver_rencontres` | `search_rencontres()` | `…_async()` | Matchs et rencontres |
| `ffbbserver_salles` | `search_salles()` | `…_async()` | Salles et gymnases |
| `ffbbserver_pratiques` | `search_pratiques()` | `…_async()` | Lieux de pratique |
| `ffbbserver_terrains` | `search_terrains()` | `…_async()` | Terrains de basket |
| `ffbbserver_tournois` | `search_tournois()` | `…_async()` | Tournois |
| `ffbbserver_engagements` | `search_engagements()` | `…_async()` | Engagements équipes ✨ v1.5 |
| `ffbbserver_formations` | `search_formations()` | `…_async()` | Formations & stages ✨ v1.5 |

```python
# 1 appel réseau → 9 index interrogés simultanément
results = client.multi_search("Clermont")

# Filtrage natif Meilisearch
organismes = client.search_organismes(
    "Clermont",
    filter=['codePostal = "63000"'],
    sort=["nom:asc"],
    limit=10,
)
```

---

## 🤖 Intégration IA / MCP Server

Tu construis un agent IA. Tu veux des données FFBB en temps réel.

👉 **[FFBB MCP Server](https://github.com/nickdesi/FFBB-MCP-Server)** — le wrapper MCP officiel construit sur ce SDK.

Compatible **Claude Desktop**, **Cursor**, **Copilot**, et tout agent [MCP](https://modelcontextprotocol.io/).

```bash
pip install ffbb-mcp-server
```

---

## 🏗 Architecture

```text
src/ffbb_api_client_v3/
├── clients/
│   ├── ffbb_api_client_v3.py       # Point d'entrée unique (façade)
│   ├── api_ffbb_app_client.py      # REST FFBB — clubs, poules, lives, saisons
│   └── meilisearch_ffbb_client.py  # Meilisearch — 9 index, search, multi_search
├── models/                         # ~60 modèles Pydantic type-safe
├── helpers/                        # HTTP utils, multi-search, cache extension
├── utils/
│   ├── token_manager.py            # Auto-résolution et renouvellement des tokens
│   ├── cache_manager.py            # SQLite / mémoire via hishel, configurable
│   ├── retry_utils.py              # Retry + timeout configurable
│   └── secure_logging.py           # Masquage automatique des tokens dans les logs
└── config.py                       # URLs et constantes FFBB
```

---

## ☁️ Production

```python
# FastAPI — initialisation unique au démarrage
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request
from ffbb_api_client_v3 import FFBBAPIClientV3, TokenManager

@asynccontextmanager
async def lifespan(app: FastAPI):
    tokens = TokenManager.get_tokens()
    app.state.ffbb = FFBBAPIClientV3.create(
        api_bearer_token=tokens.api_token,
        meilisearch_bearer_token=tokens.meilisearch_token,
    )
    yield

app = FastAPI(lifespan=lifespan)

@app.get("/clubs/{ville}")
async def clubs(ville: str, request: Request):
    return await request.app.state.ffbb.search_organismes_async(ville)
```

```dockerfile
FROM python:3.12-slim
WORKDIR /app
RUN pip install "ffbb_api_client_v3>=1.5.4"
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
```

---

## 🔐 Variables d'environnement

| Variable | Description | Requis |
|---|---|---|
| `API_FFBB_APP_BEARER_TOKEN` | Token API REST FFBB | Non (auto-résolu) |
| `MEILISEARCH_BEARER_TOKEN` | Token Meilisearch FFBB | Non (auto-résolu) |
| `FFBB_API_BASE_URL` | Override URL API REST | Non |
| `FFBB_MEILI_BASE_URL` | Override URL Meilisearch | Non |

---

## 🛠 Développement local

```bash
git clone https://github.com/nickdesi/FFBBApiClientV3.git
cd FFBBApiClientV3
pip install -e ".[testing]"
pytest tests/ --cov=src -v    # tests complets
tox                            # identique au CI GitHub Actions
```

---

## 🚑 Troubleshooting

<details>
<summary><strong>401 Unauthorized / Forbidden</strong></summary>

Les tokens FFBB expirent. Forcer un renouvellement :

```python
from ffbb_api_client_v3 import TokenManager
tokens = TokenManager.get_tokens(use_cache=False)
```
</details>

<details>
<summary><strong>Pydantic ValidationError — champ manquant</strong></summary>

L'API FFBB évolue. Mettre à jour le package :

```bash
pip install --upgrade ffbb_api_client_v3
```
</details>

<details>
<summary><strong>Données en cache périmées</strong></summary>

```python
from ffbb_api_client_v3.utils.cache_manager import CacheManager
CacheManager().clear()
```
</details>

---

## 🤝 Contribuer

Ce projet est ouvert. Il a besoin de toi.

**Signaler un bug** → [ouvrir une issue](https://github.com/nickdesi/FFBBApiClientV3/issues)
**Proposer une feature** → [discussions](https://github.com/nickdesi/FFBBApiClientV3/discussions)
**Soumettre un PR** → [guide de contribution](CONTRIBUTING.rst)

```bash
git checkout -b feat/ma-feature
# code, tests, commit
git push origin feat/ma-feature
# → Pull Request
```

Tout PR avec tests est accepté en revue dans les 48h.

---

## 🗺 Roadmap

- [ ] Documentation ReadTheDocs complète
- [ ] Exemples avancés — classements, stats équipes, analyse de saison
- [ ] CLI intégrée — `ffbb search "Pau Orthez"`
- [ ] Streaming des lives en temps réel
- [ ] Support Python 3.13

---

## 📋 Changelog

Voir [CHANGELOG.md](CHANGELOG.md) pour l'historique complet.

**v1.5.x —** `search_engagements()` + `search_formations()`, filtrage `filter/sort/limit` natif, logging sécurisé, +150 tests.

---

## 📄 Licence

[Apache 2.0](LICENSE.txt). Utilisation libre, y compris commerciale.

---

<div align="center">

Fait pour la communauté basketball française et les développeurs qui n'ont pas envie de réinventer la roue.

**Si ce projet t'aide, une étoile fait toute la différence.**

[![GitHub stars](https://img.shields.io/github/stars/nickdesi/FFBBApiClientV3?style=social)](https://github.com/nickdesi/FFBBApiClientV3/stargazers)
[![GitHub forks](https://img.shields.io/github/forks/nickdesi/FFBBApiClientV3?style=social)](https://github.com/nickdesi/FFBBApiClientV3/network/members)

</div>
