ffbb-data-client 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ffbb_api_client_v3/__init__.py +25 -0
- ffbb_data_client/__init__.py +175 -0
- ffbb_data_client/clients/__init__.py +13 -0
- ffbb_data_client/clients/api_ffbb_app_client.py +2475 -0
- ffbb_data_client/clients/ffbb_data_client.py +2789 -0
- ffbb_data_client/clients/meilisearch_client.py +218 -0
- ffbb_data_client/clients/meilisearch_ffbb_client.py +647 -0
- ffbb_data_client/config.py +153 -0
- ffbb_data_client/data/__init__.py +25 -0
- ffbb_data_client/data/collections.json +1364 -0
- ffbb_data_client/data/endpoint_discovery.json +1875 -0
- ffbb_data_client/data/indexes.json +501 -0
- ffbb_data_client/data/openapi.json +35713 -0
- ffbb_data_client/data/openapi_full.json +37622 -0
- ffbb_data_client/helpers/__init__.py +27 -0
- ffbb_data_client/helpers/http_requests_helper.py +73 -0
- ffbb_data_client/helpers/http_requests_utils.py +502 -0
- ffbb_data_client/helpers/meilisearch_client_extension.py +153 -0
- ffbb_data_client/helpers/multi_search_query_helper.py +35 -0
- ffbb_data_client/models/__init__.py +241 -0
- ffbb_data_client/models/affiche.py +45 -0
- ffbb_data_client/models/cartographie.py +82 -0
- ffbb_data_client/models/categorie.py +55 -0
- ffbb_data_client/models/categorie_type.py +42 -0
- ffbb_data_client/models/clock.py +38 -0
- ffbb_data_client/models/club_contacts.py +77 -0
- ffbb_data_client/models/code.py +7 -0
- ffbb_data_client/models/commune.py +66 -0
- ffbb_data_client/models/competition_fields.py +309 -0
- ffbb_data_client/models/competition_id.py +116 -0
- ffbb_data_client/models/competition_id_categorie.py +31 -0
- ffbb_data_client/models/competition_id_sexe.py +31 -0
- ffbb_data_client/models/competition_id_type_competition.py +27 -0
- ffbb_data_client/models/competition_id_type_competition_generique.py +24 -0
- ffbb_data_client/models/competition_origine.py +69 -0
- ffbb_data_client/models/competition_origine_categorie.py +23 -0
- ffbb_data_client/models/competition_origine_type_competition.py +14 -0
- ffbb_data_client/models/competition_origine_type_competition_generique.py +24 -0
- ffbb_data_client/models/competition_type.py +6 -0
- ffbb_data_client/models/competitions_facet_distribution.py +65 -0
- ffbb_data_client/models/competitions_facet_stats.py +14 -0
- ffbb_data_client/models/competitions_hit.py +232 -0
- ffbb_data_client/models/competitions_multi_search_query.py +40 -0
- ffbb_data_client/models/competitions_query.py +11 -0
- ffbb_data_client/models/configuration_models.py +5 -0
- ffbb_data_client/models/contact_info.py +18 -0
- ffbb_data_client/models/content_multi_search_query.py +93 -0
- ffbb_data_client/models/coordonnees.py +27 -0
- ffbb_data_client/models/coordonnees_type.py +5 -0
- ffbb_data_client/models/document_flyer.py +205 -0
- ffbb_data_client/models/document_flyer_type.py +6 -0
- ffbb_data_client/models/engagement_contacts.py +97 -0
- ffbb_data_client/models/engagements_facet_distribution.py +59 -0
- ffbb_data_client/models/engagements_facet_stats.py +14 -0
- ffbb_data_client/models/engagements_hit.py +192 -0
- ffbb_data_client/models/engagements_multi_search_query.py +41 -0
- ffbb_data_client/models/etat.py +6 -0
- ffbb_data_client/models/external_competition_id.py +42 -0
- ffbb_data_client/models/external_id.py +72 -0
- ffbb_data_client/models/facet_distribution.py +13 -0
- ffbb_data_client/models/facet_stats.py +13 -0
- ffbb_data_client/models/field_set.py +10 -0
- ffbb_data_client/models/folder.py +35 -0
- ffbb_data_client/models/formation_session.py +60 -0
- ffbb_data_client/models/formations_facet_distribution.py +61 -0
- ffbb_data_client/models/formations_facet_stats.py +14 -0
- ffbb_data_client/models/formations_hit.py +277 -0
- ffbb_data_client/models/formations_multi_search_query.py +41 -0
- ffbb_data_client/models/game_stats_model.py +57 -0
- ffbb_data_client/models/game_stats_models.py +5 -0
- ffbb_data_client/models/generic_search.py +92 -0
- ffbb_data_client/models/geo.py +27 -0
- ffbb_data_client/models/geo_sort_order.py +6 -0
- ffbb_data_client/models/get_commune_response.py +18 -0
- ffbb_data_client/models/get_competition_response.py +523 -0
- ffbb_data_client/models/get_configuration_response.py +45 -0
- ffbb_data_client/models/get_engagement_response.py +23 -0
- ffbb_data_client/models/get_entraineur_response.py +18 -0
- ffbb_data_client/models/get_formation_response.py +28 -0
- ffbb_data_client/models/get_officiel_response.py +18 -0
- ffbb_data_client/models/get_organisme_response.py +476 -0
- ffbb_data_client/models/get_poule_response.py +68 -0
- ffbb_data_client/models/get_pratique_response.py +18 -0
- ffbb_data_client/models/get_rencontre_response.py +93 -0
- ffbb_data_client/models/get_saisons_response.py +56 -0
- ffbb_data_client/models/get_salle_response.py +20 -0
- ffbb_data_client/models/get_terrain_response.py +16 -0
- ffbb_data_client/models/get_tournoi_response.py +16 -0
- ffbb_data_client/models/gradient_color.py +27 -0
- ffbb_data_client/models/hit.py +16 -0
- ffbb_data_client/models/id_engagement_equipe.py +32 -0
- ffbb_data_client/models/id_organisme_equipe.py +51 -0
- ffbb_data_client/models/id_organisme_equipe1_logo.py +28 -0
- ffbb_data_client/models/id_poule.py +27 -0
- ffbb_data_client/models/jour.py +11 -0
- ffbb_data_client/models/label.py +15 -0
- ffbb_data_client/models/labellisation.py +30 -0
- ffbb_data_client/models/live.py +192 -0
- ffbb_data_client/models/lives.py +6 -0
- ffbb_data_client/models/logo.py +28 -0
- ffbb_data_client/models/multi_search_queries.py +24 -0
- ffbb_data_client/models/multi_search_query.py +96 -0
- ffbb_data_client/models/multi_search_result_competitions.py +14 -0
- ffbb_data_client/models/multi_search_result_engagements.py +14 -0
- ffbb_data_client/models/multi_search_result_formations.py +12 -0
- ffbb_data_client/models/multi_search_result_organismes.py +12 -0
- ffbb_data_client/models/multi_search_result_pratiques.py +12 -0
- ffbb_data_client/models/multi_search_result_rencontres.py +12 -0
- ffbb_data_client/models/multi_search_result_salles.py +12 -0
- ffbb_data_client/models/multi_search_result_terrains.py +12 -0
- ffbb_data_client/models/multi_search_result_tournois.py +12 -0
- ffbb_data_client/models/multi_search_results.py +103 -0
- ffbb_data_client/models/multi_search_results_class.py +96 -0
- ffbb_data_client/models/nature_sol.py +57 -0
- ffbb_data_client/models/niveau.py +10 -0
- ffbb_data_client/models/niveau_class.py +27 -0
- ffbb_data_client/models/niveau_extractor.py +214 -0
- ffbb_data_client/models/niveau_info.py +64 -0
- ffbb_data_client/models/niveau_models.py +14 -0
- ffbb_data_client/models/niveau_type.py +10 -0
- ffbb_data_client/models/objectif.py +7 -0
- ffbb_data_client/models/organisateur.py +197 -0
- ffbb_data_client/models/organisateur_type.py +6 -0
- ffbb_data_client/models/organisme_fields.py +327 -0
- ffbb_data_client/models/organisme_id_pere.py +177 -0
- ffbb_data_client/models/organismes_facet_distribution.py +46 -0
- ffbb_data_client/models/organismes_facet_stats.py +14 -0
- ffbb_data_client/models/organismes_hit.py +196 -0
- ffbb_data_client/models/organismes_multi_search_query.py +41 -0
- ffbb_data_client/models/organismes_query.py +8 -0
- ffbb_data_client/models/phase_code.py +23 -0
- ffbb_data_client/models/poule.py +35 -0
- ffbb_data_client/models/poule_fields.py +261 -0
- ffbb_data_client/models/poule_rencontre_item_model.py +69 -0
- ffbb_data_client/models/poules_models.py +6 -0
- ffbb_data_client/models/poules_query.py +9 -0
- ffbb_data_client/models/pratique.py +7 -0
- ffbb_data_client/models/pratiques_facet_distribution.py +29 -0
- ffbb_data_client/models/pratiques_facet_stats.py +14 -0
- ffbb_data_client/models/pratiques_hit.py +310 -0
- ffbb_data_client/models/pratiques_hit_type.py +9 -0
- ffbb_data_client/models/pratiques_multi_search_query.py +41 -0
- ffbb_data_client/models/pratiques_type_class.py +45 -0
- ffbb_data_client/models/publication_internet.py +6 -0
- ffbb_data_client/models/purple_logo.py +24 -0
- ffbb_data_client/models/query_fields_manager.py +75 -0
- ffbb_data_client/models/ranking_engagement.py +41 -0
- ffbb_data_client/models/rankings_models.py +6 -0
- ffbb_data_client/models/rencontres_engagement.py +23 -0
- ffbb_data_client/models/rencontres_facet_distribution.py +65 -0
- ffbb_data_client/models/rencontres_facet_stats.py +14 -0
- ffbb_data_client/models/rencontres_hit.py +271 -0
- ffbb_data_client/models/rencontres_multi_search_query.py +41 -0
- ffbb_data_client/models/saison.py +23 -0
- ffbb_data_client/models/saison_fields.py +36 -0
- ffbb_data_client/models/saisons_models.py +6 -0
- ffbb_data_client/models/saisons_query.py +9 -0
- ffbb_data_client/models/salle.py +56 -0
- ffbb_data_client/models/salles_facet_distribution.py +14 -0
- ffbb_data_client/models/salles_facet_stats.py +14 -0
- ffbb_data_client/models/salles_hit.py +153 -0
- ffbb_data_client/models/salles_multi_search_query.py +40 -0
- ffbb_data_client/models/sexe.py +9 -0
- ffbb_data_client/models/sexe_class.py +31 -0
- ffbb_data_client/models/source.py +5 -0
- ffbb_data_client/models/status.py +5 -0
- ffbb_data_client/models/team_engagement.py +56 -0
- ffbb_data_client/models/team_ranking.py +108 -0
- ffbb_data_client/models/terrains_categorie_championnat_3x3_libelle.py +5 -0
- ffbb_data_client/models/terrains_facet_distribution.py +41 -0
- ffbb_data_client/models/terrains_facet_stats.py +14 -0
- ffbb_data_client/models/terrains_hit.py +223 -0
- ffbb_data_client/models/terrains_multi_search_query.py +42 -0
- ffbb_data_client/models/terrains_name.py +5 -0
- ffbb_data_client/models/terrains_sexe_enum.py +7 -0
- ffbb_data_client/models/terrains_storage.py +5 -0
- ffbb_data_client/models/tournoi_type_class.py +35 -0
- ffbb_data_client/models/tournoi_type_enum.py +7 -0
- ffbb_data_client/models/tournoi_types_3x3.py +43 -0
- ffbb_data_client/models/tournoi_types_3x3_libelle.py +60 -0
- ffbb_data_client/models/tournoi_types_3x3_libelle_enum.py +10 -0
- ffbb_data_client/models/tournois_facet_distribution.py +41 -0
- ffbb_data_client/models/tournois_facet_stats.py +14 -0
- ffbb_data_client/models/tournois_hit.py +132 -0
- ffbb_data_client/models/tournois_hit_type.py +5 -0
- ffbb_data_client/models/tournois_libelle.py +7 -0
- ffbb_data_client/models/tournois_multi_search_query.py +40 -0
- ffbb_data_client/models/type_association.py +23 -0
- ffbb_data_client/models/type_association_libelle.py +30 -0
- ffbb_data_client/models/type_class.py +23 -0
- ffbb_data_client/models/type_competition.py +8 -0
- ffbb_data_client/models/type_competition_generique.py +31 -0
- ffbb_data_client/models/type_enum.py +7 -0
- ffbb_data_client/models/type_league.py +6 -0
- ffbb_data_client/py.typed +0 -0
- ffbb_data_client/utils/__init__.py +27 -0
- ffbb_data_client/utils/cache_manager.py +393 -0
- ffbb_data_client/utils/converter_utils.py +329 -0
- ffbb_data_client/utils/input_validation.py +360 -0
- ffbb_data_client/utils/retry_utils.py +478 -0
- ffbb_data_client/utils/secure_logging.py +153 -0
- ffbb_data_client/utils/token_manager.py +115 -0
- ffbb_data_client-2.0.0.dist-info/METADATA +339 -0
- ffbb_data_client-2.0.0.dist-info/RECORD +207 -0
- ffbb_data_client-2.0.0.dist-info/WHEEL +5 -0
- ffbb_data_client-2.0.0.dist-info/licenses/LICENSE.txt +201 -0
- ffbb_data_client-2.0.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,2475 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
from httpx import Client
|
|
7
|
+
from pydantic import TypeAdapter
|
|
8
|
+
|
|
9
|
+
from ..config import (
|
|
10
|
+
API_FFBB_BASE_URL,
|
|
11
|
+
DEFAULT_USER_AGENT,
|
|
12
|
+
ENDPOINT_COMMUNES,
|
|
13
|
+
ENDPOINT_COMPETITIONS,
|
|
14
|
+
ENDPOINT_CONFIGURATION,
|
|
15
|
+
ENDPOINT_EDF_MATCHES,
|
|
16
|
+
ENDPOINT_EDF_PLAYERS,
|
|
17
|
+
ENDPOINT_EDF_ROSTERS,
|
|
18
|
+
ENDPOINT_EDF_TEAMS,
|
|
19
|
+
ENDPOINT_ENGAGEMENTS,
|
|
20
|
+
ENDPOINT_ENTRAINEURS,
|
|
21
|
+
ENDPOINT_FORMATIONS,
|
|
22
|
+
ENDPOINT_GENIUS_SPORT_MATCHES,
|
|
23
|
+
ENDPOINT_GENIUS_SPORTS_LIVE_LOGS,
|
|
24
|
+
ENDPOINT_LIVES,
|
|
25
|
+
ENDPOINT_OFFICIELS,
|
|
26
|
+
ENDPOINT_OPENAPI,
|
|
27
|
+
ENDPOINT_ORGANISMES,
|
|
28
|
+
ENDPOINT_POULES,
|
|
29
|
+
ENDPOINT_PRATIQUES,
|
|
30
|
+
ENDPOINT_REMATCH_VIDEOS,
|
|
31
|
+
ENDPOINT_RENCONTRES,
|
|
32
|
+
ENDPOINT_SAISONS,
|
|
33
|
+
ENDPOINT_SALLES,
|
|
34
|
+
ENDPOINT_SESSIONS,
|
|
35
|
+
ENDPOINT_TERRAINS,
|
|
36
|
+
ENDPOINT_TOURNOIS,
|
|
37
|
+
)
|
|
38
|
+
from ..helpers.http_requests_helper import catch_result
|
|
39
|
+
from ..helpers.http_requests_utils import (
|
|
40
|
+
http_get_json,
|
|
41
|
+
http_get_json_async,
|
|
42
|
+
url_with_params,
|
|
43
|
+
)
|
|
44
|
+
from ..models.configuration_models import GetConfigurationResponse
|
|
45
|
+
from ..models.field_set import FieldSet
|
|
46
|
+
from ..models.get_commune_response import GetCommuneResponse
|
|
47
|
+
from ..models.get_competition_response import GetCompetitionResponse
|
|
48
|
+
from ..models.get_engagement_response import GetEngagementResponse
|
|
49
|
+
from ..models.get_entraineur_response import GetEntraineurResponse
|
|
50
|
+
from ..models.get_formation_response import GetFormationResponse
|
|
51
|
+
from ..models.get_officiel_response import GetOfficielResponse
|
|
52
|
+
from ..models.get_organisme_response import GetOrganismeResponse
|
|
53
|
+
from ..models.get_pratique_response import GetPratiqueResponse
|
|
54
|
+
from ..models.get_rencontre_response import GetRencontreResponse
|
|
55
|
+
from ..models.get_salle_response import GetSalleResponse
|
|
56
|
+
from ..models.get_terrain_response import GetTerrainResponse
|
|
57
|
+
from ..models.get_tournoi_response import GetTournoiResponse
|
|
58
|
+
from ..models.lives import Live
|
|
59
|
+
from ..models.poules_models import GetPouleResponse
|
|
60
|
+
from ..models.query_fields_manager import QueryFieldsManager
|
|
61
|
+
from ..models.saisons_models import GetSaisonsResponse
|
|
62
|
+
from ..models.team_ranking import TeamRanking
|
|
63
|
+
from ..utils.cache_manager import CacheConfig, CacheManager
|
|
64
|
+
from ..utils.retry_utils import (
|
|
65
|
+
RetryConfig,
|
|
66
|
+
TimeoutConfig,
|
|
67
|
+
get_default_retry_config,
|
|
68
|
+
get_default_timeout_config,
|
|
69
|
+
)
|
|
70
|
+
from ..utils.secure_logging import get_secure_logger, mask_token
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class ApiFFBBAppClient:
|
|
74
|
+
url: str = ""
|
|
75
|
+
debug: bool = False
|
|
76
|
+
headers: dict[str, str] = {}
|
|
77
|
+
cached_session: Client | None = None
|
|
78
|
+
async_cached_session: httpx.AsyncClient | None = None
|
|
79
|
+
retry_config: RetryConfig | None = None
|
|
80
|
+
timeout_config: TimeoutConfig | None = None
|
|
81
|
+
|
|
82
|
+
def __init__(
|
|
83
|
+
self,
|
|
84
|
+
bearer_token: str,
|
|
85
|
+
url: str = API_FFBB_BASE_URL,
|
|
86
|
+
debug: bool = False,
|
|
87
|
+
cached_session: Client | None = None,
|
|
88
|
+
async_cached_session: httpx.AsyncClient | None = None,
|
|
89
|
+
*,
|
|
90
|
+
retry_config: RetryConfig | None = None,
|
|
91
|
+
timeout_config: TimeoutConfig | None = None,
|
|
92
|
+
cache_config: CacheConfig | None = None,
|
|
93
|
+
):
|
|
94
|
+
"""
|
|
95
|
+
Initializes an instance of the ApiFFBBAppClient class.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
bearer_token (str): The bearer token used for authentication.
|
|
99
|
+
url (str, optional): The base URL. Defaults to "https://api.ffbb.app/".
|
|
100
|
+
debug (bool, optional): Whether to enable debug mode. Defaults to False.
|
|
101
|
+
cached_session (Client, optional): The cached session to use.
|
|
102
|
+
retry_config (RetryConfig, optional): Retry configuration. Defaults to None.
|
|
103
|
+
timeout_config (TimeoutConfig, optional): Timeout configuration.
|
|
104
|
+
Defaults to None.
|
|
105
|
+
cache_config (CacheConfig, optional): Cache configuration. Defaults to None.
|
|
106
|
+
"""
|
|
107
|
+
if not bearer_token or not bearer_token.strip():
|
|
108
|
+
raise ValueError("bearer_token cannot be None, empty, or whitespace-only")
|
|
109
|
+
|
|
110
|
+
# Store token securely (private attribute)
|
|
111
|
+
self._bearer_token = bearer_token
|
|
112
|
+
self.url = url
|
|
113
|
+
self.debug = debug
|
|
114
|
+
self.cached_session = cached_session
|
|
115
|
+
self.headers = {
|
|
116
|
+
"Authorization": f"Bearer {self._bearer_token}",
|
|
117
|
+
"user-agent": DEFAULT_USER_AGENT,
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
# Configure retry and timeout settings
|
|
121
|
+
self.retry_config = retry_config or get_default_retry_config()
|
|
122
|
+
self.timeout_config = timeout_config or get_default_timeout_config()
|
|
123
|
+
|
|
124
|
+
# Configure cache manager
|
|
125
|
+
self.cache_manager = CacheManager(cache_config)
|
|
126
|
+
|
|
127
|
+
if cached_session is None:
|
|
128
|
+
self.cached_session = self.cache_manager.session
|
|
129
|
+
else:
|
|
130
|
+
self.cached_session = cached_session
|
|
131
|
+
|
|
132
|
+
if async_cached_session is None:
|
|
133
|
+
self.async_cached_session = self.cache_manager.async_session
|
|
134
|
+
else:
|
|
135
|
+
self.async_cached_session = async_cached_session
|
|
136
|
+
|
|
137
|
+
# Initialize secure logger
|
|
138
|
+
self.logger = get_secure_logger(f"{self.__class__.__name__}")
|
|
139
|
+
|
|
140
|
+
# Log initialization with masked token
|
|
141
|
+
masked_token = mask_token(self._bearer_token)
|
|
142
|
+
if self.debug:
|
|
143
|
+
self.logger.info(f"ApiFFBBAppClient initialized with token: {masked_token}")
|
|
144
|
+
self.logger.info(
|
|
145
|
+
f"Retry config: {self.retry_config.max_attempts} attempts, "
|
|
146
|
+
f"timeout: {self.timeout_config.total_timeout}s"
|
|
147
|
+
)
|
|
148
|
+
else:
|
|
149
|
+
self.logger.info("ApiFFBBAppClient initialized successfully")
|
|
150
|
+
|
|
151
|
+
@property
|
|
152
|
+
def bearer_token(self) -> str:
|
|
153
|
+
"""Get the bearer token."""
|
|
154
|
+
return self._bearer_token
|
|
155
|
+
|
|
156
|
+
def get_organisme_for_search(
|
|
157
|
+
self,
|
|
158
|
+
organisme_id: int,
|
|
159
|
+
cached_session: Client | None = None,
|
|
160
|
+
) -> GetOrganismeResponse | None:
|
|
161
|
+
"""Version allégée de get_organisme() pour les contextes de recherche.
|
|
162
|
+
Retourne 31 champs au lieu de 77 (exclut membres, labellisation, salle).
|
|
163
|
+
"""
|
|
164
|
+
return self.get_organisme(
|
|
165
|
+
organisme_id=organisme_id,
|
|
166
|
+
fields=QueryFieldsManager.get_organisme_search_fields(),
|
|
167
|
+
cached_session=cached_session,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
async def get_organisme_for_search_async(
|
|
171
|
+
self,
|
|
172
|
+
organisme_id: int,
|
|
173
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
174
|
+
) -> GetOrganismeResponse | None:
|
|
175
|
+
"""Version async allégée de get_organisme() pour les contextes de recherche."""
|
|
176
|
+
return await self.get_organisme_async(
|
|
177
|
+
organisme_id=organisme_id,
|
|
178
|
+
fields=QueryFieldsManager.get_organisme_search_fields(),
|
|
179
|
+
cached_session=cached_session,
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
def _get_directus_item(
|
|
183
|
+
self,
|
|
184
|
+
endpoint: str,
|
|
185
|
+
id: str | int,
|
|
186
|
+
fields: list[str] | None = None,
|
|
187
|
+
cached_session: Client | None = None,
|
|
188
|
+
) -> dict[str, Any] | None:
|
|
189
|
+
url = f"{self.url}{endpoint}/{id}"
|
|
190
|
+
params: dict[str, Any] = {}
|
|
191
|
+
if fields:
|
|
192
|
+
params["fields[]"] = fields
|
|
193
|
+
final_url = url_with_params(url, params) if params else url
|
|
194
|
+
data = catch_result(
|
|
195
|
+
lambda: http_get_json(
|
|
196
|
+
final_url,
|
|
197
|
+
self.headers,
|
|
198
|
+
debug=self.debug,
|
|
199
|
+
cached_session=cached_session or self.cached_session,
|
|
200
|
+
retry_config=self.retry_config,
|
|
201
|
+
timeout_config=self.timeout_config,
|
|
202
|
+
)
|
|
203
|
+
)
|
|
204
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
205
|
+
return actual_data if isinstance(actual_data, dict) else None
|
|
206
|
+
|
|
207
|
+
async def _get_directus_item_async(
|
|
208
|
+
self,
|
|
209
|
+
endpoint: str,
|
|
210
|
+
id: str | int,
|
|
211
|
+
fields: list[str] | None = None,
|
|
212
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
213
|
+
) -> dict[str, Any] | None:
|
|
214
|
+
url = f"{self.url}{endpoint}/{id}"
|
|
215
|
+
params: dict[str, Any] = {}
|
|
216
|
+
if fields:
|
|
217
|
+
params["fields[]"] = fields
|
|
218
|
+
final_url = url_with_params(url, params) if params else url
|
|
219
|
+
try:
|
|
220
|
+
data = await http_get_json_async(
|
|
221
|
+
final_url,
|
|
222
|
+
self.headers,
|
|
223
|
+
debug=self.debug,
|
|
224
|
+
cached_session=cached_session or self.async_cached_session,
|
|
225
|
+
retry_config=self.retry_config,
|
|
226
|
+
timeout_config=self.timeout_config,
|
|
227
|
+
)
|
|
228
|
+
except Exception as e:
|
|
229
|
+
if self.debug:
|
|
230
|
+
self.logger.error(f"Error in _get_directus_item_async: {e}")
|
|
231
|
+
return None
|
|
232
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
233
|
+
return actual_data if isinstance(actual_data, dict) else None
|
|
234
|
+
|
|
235
|
+
def _list_directus_items(
|
|
236
|
+
self,
|
|
237
|
+
endpoint: str,
|
|
238
|
+
limit: int = 10,
|
|
239
|
+
fields: list[str] | None = None,
|
|
240
|
+
filter_criteria: str | None = None,
|
|
241
|
+
sort: str | list[str] | None = None,
|
|
242
|
+
offset: int | None = None,
|
|
243
|
+
search: str | None = None,
|
|
244
|
+
cached_session: Client | None = None,
|
|
245
|
+
) -> list[dict[str, Any]]:
|
|
246
|
+
url = f"{self.url}{endpoint}"
|
|
247
|
+
params: dict[str, Any] = {"limit": str(limit)}
|
|
248
|
+
if fields:
|
|
249
|
+
params["fields[]"] = fields
|
|
250
|
+
if filter_criteria:
|
|
251
|
+
params["filter"] = filter_criteria
|
|
252
|
+
if sort:
|
|
253
|
+
params["sort"] = sort
|
|
254
|
+
if offset:
|
|
255
|
+
params["offset"] = str(offset)
|
|
256
|
+
if search:
|
|
257
|
+
params["search"] = search
|
|
258
|
+
final_url = url_with_params(url, params)
|
|
259
|
+
data = catch_result(
|
|
260
|
+
lambda: http_get_json(
|
|
261
|
+
final_url,
|
|
262
|
+
self.headers,
|
|
263
|
+
debug=self.debug,
|
|
264
|
+
cached_session=cached_session or self.cached_session,
|
|
265
|
+
retry_config=self.retry_config,
|
|
266
|
+
timeout_config=self.timeout_config,
|
|
267
|
+
)
|
|
268
|
+
)
|
|
269
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
270
|
+
return actual_data if isinstance(actual_data, list) else []
|
|
271
|
+
|
|
272
|
+
async def _list_directus_items_async(
|
|
273
|
+
self,
|
|
274
|
+
endpoint: str,
|
|
275
|
+
limit: int = 10,
|
|
276
|
+
fields: list[str] | None = None,
|
|
277
|
+
filter_criteria: str | None = None,
|
|
278
|
+
sort: str | list[str] | None = None,
|
|
279
|
+
offset: int | None = None,
|
|
280
|
+
search: str | None = None,
|
|
281
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
282
|
+
) -> list[dict[str, Any]]:
|
|
283
|
+
url = f"{self.url}{endpoint}"
|
|
284
|
+
params: dict[str, Any] = {"limit": str(limit)}
|
|
285
|
+
if fields:
|
|
286
|
+
params["fields[]"] = fields
|
|
287
|
+
if filter_criteria:
|
|
288
|
+
params["filter"] = filter_criteria
|
|
289
|
+
if sort:
|
|
290
|
+
params["sort"] = sort
|
|
291
|
+
if offset:
|
|
292
|
+
params["offset"] = str(offset)
|
|
293
|
+
if search:
|
|
294
|
+
params["search"] = search
|
|
295
|
+
final_url = url_with_params(url, params)
|
|
296
|
+
try:
|
|
297
|
+
data = await http_get_json_async(
|
|
298
|
+
final_url,
|
|
299
|
+
self.headers,
|
|
300
|
+
debug=self.debug,
|
|
301
|
+
cached_session=cached_session or self.async_cached_session,
|
|
302
|
+
retry_config=self.retry_config,
|
|
303
|
+
timeout_config=self.timeout_config,
|
|
304
|
+
)
|
|
305
|
+
except Exception as e:
|
|
306
|
+
if self.debug:
|
|
307
|
+
self.logger.error(f"Error in _list_directus_items_async: {e}")
|
|
308
|
+
return []
|
|
309
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
310
|
+
return actual_data if isinstance(actual_data, list) else []
|
|
311
|
+
|
|
312
|
+
def get_openapi_spec(
|
|
313
|
+
self, cached_session: Client | None = None
|
|
314
|
+
) -> dict[str, Any] | None:
|
|
315
|
+
"""Retrieves the public Directus OpenAPI specification."""
|
|
316
|
+
url = f"{self.url}{ENDPOINT_OPENAPI}"
|
|
317
|
+
data = catch_result(
|
|
318
|
+
lambda: http_get_json(
|
|
319
|
+
url,
|
|
320
|
+
self.headers,
|
|
321
|
+
debug=self.debug,
|
|
322
|
+
cached_session=cached_session or self.cached_session,
|
|
323
|
+
retry_config=self.retry_config,
|
|
324
|
+
timeout_config=self.timeout_config,
|
|
325
|
+
)
|
|
326
|
+
)
|
|
327
|
+
return data if isinstance(data, dict) else None
|
|
328
|
+
|
|
329
|
+
def get_lives(self, cached_session: Client | None = None) -> list[Live] | None:
|
|
330
|
+
"""
|
|
331
|
+
Retrieves a list of live events with retry logic.
|
|
332
|
+
|
|
333
|
+
Args:
|
|
334
|
+
cached_session (Client, optional): The cached session to use
|
|
335
|
+
|
|
336
|
+
Returns:
|
|
337
|
+
List[Live]: A list of Live objects representing the live events.
|
|
338
|
+
"""
|
|
339
|
+
url = f"{self.url}{ENDPOINT_LIVES}"
|
|
340
|
+
|
|
341
|
+
raw_data = catch_result(
|
|
342
|
+
lambda: http_get_json(
|
|
343
|
+
url,
|
|
344
|
+
self.headers,
|
|
345
|
+
debug=self.debug,
|
|
346
|
+
cached_session=cached_session or self.cached_session,
|
|
347
|
+
retry_config=self.retry_config,
|
|
348
|
+
timeout_config=self.timeout_config,
|
|
349
|
+
)
|
|
350
|
+
)
|
|
351
|
+
if raw_data:
|
|
352
|
+
# data might be a list or a dict with "lives" key
|
|
353
|
+
if isinstance(raw_data, dict) and "lives" in raw_data:
|
|
354
|
+
raw_data = raw_data["lives"]
|
|
355
|
+
|
|
356
|
+
if not isinstance(raw_data, list):
|
|
357
|
+
return []
|
|
358
|
+
|
|
359
|
+
adapter = TypeAdapter(list[Live])
|
|
360
|
+
return adapter.validate_python(raw_data)
|
|
361
|
+
return None
|
|
362
|
+
|
|
363
|
+
async def get_lives_async(
|
|
364
|
+
self, cached_session: httpx.AsyncClient | None = None
|
|
365
|
+
) -> list[Live] | None:
|
|
366
|
+
"""
|
|
367
|
+
Retrieves a list of live events asynchroniously.
|
|
368
|
+
"""
|
|
369
|
+
url = f"{self.url}{ENDPOINT_LIVES}"
|
|
370
|
+
|
|
371
|
+
# Note: catch_result is not async-friendly, but http_get_json_async handles some errors
|
|
372
|
+
# In a real async environment, we might want an async_catch_result
|
|
373
|
+
try:
|
|
374
|
+
raw_data = await http_get_json_async(
|
|
375
|
+
url,
|
|
376
|
+
self.headers,
|
|
377
|
+
debug=self.debug,
|
|
378
|
+
cached_session=cached_session or self.async_cached_session,
|
|
379
|
+
retry_config=self.retry_config,
|
|
380
|
+
timeout_config=self.timeout_config,
|
|
381
|
+
)
|
|
382
|
+
if raw_data is not None:
|
|
383
|
+
# data might be a list or a dict with "lives" key
|
|
384
|
+
if isinstance(raw_data, dict) and "lives" in raw_data:
|
|
385
|
+
raw_data = raw_data["lives"]
|
|
386
|
+
|
|
387
|
+
if not isinstance(raw_data, list):
|
|
388
|
+
return []
|
|
389
|
+
|
|
390
|
+
adapter = TypeAdapter(list[Live])
|
|
391
|
+
return adapter.validate_python(raw_data)
|
|
392
|
+
except Exception as e:
|
|
393
|
+
if self.debug:
|
|
394
|
+
self.logger.error(f"Error in get_lives_async: {e}")
|
|
395
|
+
return None
|
|
396
|
+
|
|
397
|
+
def get_competition(
|
|
398
|
+
self,
|
|
399
|
+
competition_id: int,
|
|
400
|
+
deep_limit: str | None = "1000",
|
|
401
|
+
fields: list[str] | None = None,
|
|
402
|
+
cached_session: Client | None = None,
|
|
403
|
+
) -> GetCompetitionResponse | None:
|
|
404
|
+
"""
|
|
405
|
+
Retrieves detailed information about a competition.
|
|
406
|
+
|
|
407
|
+
Args:
|
|
408
|
+
competition_id (int): The ID of the competition
|
|
409
|
+
deep_limit (str, optional): Limit for nested rencontres.
|
|
410
|
+
Defaults to "1000".
|
|
411
|
+
fields (List[str], optional): List of fields to retrieve.
|
|
412
|
+
If None, uses default fields.
|
|
413
|
+
cached_session (Client, optional): The cached session to use
|
|
414
|
+
|
|
415
|
+
Returns:
|
|
416
|
+
GetCompetitionResponse: Competition data with nested phases,
|
|
417
|
+
poules, and rencontres
|
|
418
|
+
"""
|
|
419
|
+
url = f"{self.url}{ENDPOINT_COMPETITIONS}/{competition_id}"
|
|
420
|
+
|
|
421
|
+
params: dict[str, Any] = {}
|
|
422
|
+
if deep_limit:
|
|
423
|
+
params["deep[phases][poules][rencontres][_limit]"] = deep_limit
|
|
424
|
+
|
|
425
|
+
if fields:
|
|
426
|
+
for field in fields:
|
|
427
|
+
if "fields[]" not in params:
|
|
428
|
+
params["fields[]"] = []
|
|
429
|
+
params["fields[]"].append(field)
|
|
430
|
+
else:
|
|
431
|
+
# Use default fields from descriptor when no fields are specified
|
|
432
|
+
params["fields[]"] = QueryFieldsManager.get_competition_fields(
|
|
433
|
+
FieldSet.DEFAULT
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
final_url = url_with_params(url, params)
|
|
437
|
+
data = catch_result(
|
|
438
|
+
lambda: http_get_json(
|
|
439
|
+
final_url,
|
|
440
|
+
self.headers,
|
|
441
|
+
debug=self.debug,
|
|
442
|
+
cached_session=cached_session or self.cached_session,
|
|
443
|
+
)
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
# Extract the actual data from the response wrapper
|
|
447
|
+
|
|
448
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
449
|
+
if actual_data:
|
|
450
|
+
adapter = TypeAdapter(GetCompetitionResponse)
|
|
451
|
+
return adapter.validate_python(actual_data)
|
|
452
|
+
return None
|
|
453
|
+
|
|
454
|
+
async def get_competition_async(
|
|
455
|
+
self,
|
|
456
|
+
competition_id: int,
|
|
457
|
+
deep_limit: str | None = "1000",
|
|
458
|
+
fields: list[str] | None = None,
|
|
459
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
460
|
+
) -> GetCompetitionResponse | None:
|
|
461
|
+
"""
|
|
462
|
+
Retrieves detailed information about a competition asynchroniously.
|
|
463
|
+
"""
|
|
464
|
+
url = f"{self.url}{ENDPOINT_COMPETITIONS}/{competition_id}"
|
|
465
|
+
|
|
466
|
+
params: dict[str, Any] = {}
|
|
467
|
+
if deep_limit:
|
|
468
|
+
params["deep[phases][poules][rencontres][_limit]"] = deep_limit
|
|
469
|
+
|
|
470
|
+
if fields:
|
|
471
|
+
for field in fields:
|
|
472
|
+
if "fields[]" not in params:
|
|
473
|
+
params["fields[]"] = []
|
|
474
|
+
params["fields[]"].append(field)
|
|
475
|
+
else:
|
|
476
|
+
params["fields[]"] = QueryFieldsManager.get_competition_fields(
|
|
477
|
+
FieldSet.DEFAULT
|
|
478
|
+
)
|
|
479
|
+
|
|
480
|
+
final_url = url_with_params(url, params)
|
|
481
|
+
try:
|
|
482
|
+
data = await http_get_json_async(
|
|
483
|
+
final_url,
|
|
484
|
+
self.headers,
|
|
485
|
+
debug=self.debug,
|
|
486
|
+
cached_session=cached_session or self.async_cached_session,
|
|
487
|
+
)
|
|
488
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
489
|
+
if actual_data:
|
|
490
|
+
adapter = TypeAdapter(GetCompetitionResponse)
|
|
491
|
+
return adapter.validate_python(actual_data)
|
|
492
|
+
return None
|
|
493
|
+
except Exception as e:
|
|
494
|
+
if self.debug:
|
|
495
|
+
self.logger.error(f"Error in get_competition_async: {e}")
|
|
496
|
+
return None
|
|
497
|
+
|
|
498
|
+
def get_poule(
|
|
499
|
+
self,
|
|
500
|
+
poule_id: int,
|
|
501
|
+
deep_limit: str | None = "1000",
|
|
502
|
+
fields: list[str] | None = None,
|
|
503
|
+
cached_session: Client | None = None,
|
|
504
|
+
) -> GetPouleResponse | None:
|
|
505
|
+
"""
|
|
506
|
+
Retrieves detailed information about a poule.
|
|
507
|
+
|
|
508
|
+
Args:
|
|
509
|
+
poule_id (int): The ID of the poule
|
|
510
|
+
deep_limit (str, optional): Limit for nested rencontres.
|
|
511
|
+
Defaults to "1000".
|
|
512
|
+
fields (List[str], optional): List of fields to retrieve.
|
|
513
|
+
If None, uses default fields.
|
|
514
|
+
cached_session (Client, optional): The cached session to use
|
|
515
|
+
|
|
516
|
+
Returns:
|
|
517
|
+
GetPouleResponse: Poule data with rencontres
|
|
518
|
+
"""
|
|
519
|
+
url = f"{self.url}{ENDPOINT_POULES}/{poule_id}"
|
|
520
|
+
|
|
521
|
+
params: dict[str, Any] = {}
|
|
522
|
+
if deep_limit:
|
|
523
|
+
params["deep[rencontres][_limit]"] = deep_limit
|
|
524
|
+
params["deep[classements][_limit]"] = deep_limit
|
|
525
|
+
|
|
526
|
+
if fields:
|
|
527
|
+
params["fields[]"] = fields
|
|
528
|
+
else:
|
|
529
|
+
# Use default fields from descriptor when no fields are specified
|
|
530
|
+
params["fields[]"] = QueryFieldsManager.get_poule_fields(FieldSet.DEFAULT)
|
|
531
|
+
|
|
532
|
+
final_url = url_with_params(url, params)
|
|
533
|
+
data = catch_result(
|
|
534
|
+
lambda: http_get_json(
|
|
535
|
+
final_url,
|
|
536
|
+
self.headers,
|
|
537
|
+
debug=self.debug,
|
|
538
|
+
cached_session=cached_session or self.cached_session,
|
|
539
|
+
)
|
|
540
|
+
)
|
|
541
|
+
|
|
542
|
+
# Extract the actual data from the response wrapper
|
|
543
|
+
|
|
544
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
545
|
+
if actual_data:
|
|
546
|
+
return GetPouleResponse.from_dict(actual_data)
|
|
547
|
+
return None
|
|
548
|
+
|
|
549
|
+
async def get_poule_async(
|
|
550
|
+
self,
|
|
551
|
+
poule_id: int,
|
|
552
|
+
deep_limit: str | None = "1000",
|
|
553
|
+
fields: list[str] | None = None,
|
|
554
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
555
|
+
) -> GetPouleResponse | None:
|
|
556
|
+
"""
|
|
557
|
+
Retrieves detailed information about a poule asynchroniously.
|
|
558
|
+
"""
|
|
559
|
+
url = f"{self.url}{ENDPOINT_POULES}/{poule_id}"
|
|
560
|
+
|
|
561
|
+
params: dict[str, Any] = {}
|
|
562
|
+
if deep_limit:
|
|
563
|
+
params["deep[rencontres][_limit]"] = deep_limit
|
|
564
|
+
params["deep[classements][_limit]"] = deep_limit
|
|
565
|
+
|
|
566
|
+
if fields:
|
|
567
|
+
params["fields[]"] = fields
|
|
568
|
+
else:
|
|
569
|
+
params["fields[]"] = QueryFieldsManager.get_poule_fields(FieldSet.DEFAULT)
|
|
570
|
+
|
|
571
|
+
final_url = url_with_params(url, params)
|
|
572
|
+
try:
|
|
573
|
+
data = await http_get_json_async(
|
|
574
|
+
final_url,
|
|
575
|
+
self.headers,
|
|
576
|
+
debug=self.debug,
|
|
577
|
+
cached_session=cached_session or self.async_cached_session,
|
|
578
|
+
)
|
|
579
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
580
|
+
if actual_data:
|
|
581
|
+
return GetPouleResponse.from_dict(actual_data)
|
|
582
|
+
return None
|
|
583
|
+
except Exception as e:
|
|
584
|
+
if self.debug:
|
|
585
|
+
self.logger.error(f"Error in get_poule_async: {e}")
|
|
586
|
+
return None
|
|
587
|
+
|
|
588
|
+
def get_classement(
|
|
589
|
+
self,
|
|
590
|
+
poule_id: int,
|
|
591
|
+
cached_session: Client | None = None,
|
|
592
|
+
) -> list[TeamRanking] | None:
|
|
593
|
+
"""
|
|
594
|
+
Retrieves ONLY the ranking (classement) for a specific poule.
|
|
595
|
+
"""
|
|
596
|
+
res = self.get_poule(
|
|
597
|
+
poule_id=poule_id,
|
|
598
|
+
deep_limit="1000",
|
|
599
|
+
fields=QueryFieldsManager.get_classement_fields(),
|
|
600
|
+
cached_session=cached_session,
|
|
601
|
+
)
|
|
602
|
+
return res.classements if res else None
|
|
603
|
+
|
|
604
|
+
async def get_classement_async(
|
|
605
|
+
self,
|
|
606
|
+
poule_id: int,
|
|
607
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
608
|
+
) -> list[TeamRanking] | None:
|
|
609
|
+
"""
|
|
610
|
+
Asynchronously retrieves ONLY the ranking (classement) for a specific poule.
|
|
611
|
+
"""
|
|
612
|
+
res = await self.get_poule_async(
|
|
613
|
+
poule_id=poule_id,
|
|
614
|
+
deep_limit="1000",
|
|
615
|
+
fields=QueryFieldsManager.get_classement_fields(),
|
|
616
|
+
cached_session=cached_session,
|
|
617
|
+
)
|
|
618
|
+
return res.classements if res else None
|
|
619
|
+
|
|
620
|
+
def get_saisons(
|
|
621
|
+
self,
|
|
622
|
+
fields: list[str] | None = None,
|
|
623
|
+
filter_criteria: str | None = '{"actif":{"_eq":true}}',
|
|
624
|
+
cached_session: Client | None = None,
|
|
625
|
+
) -> list[GetSaisonsResponse]:
|
|
626
|
+
"""
|
|
627
|
+
Retrieves list of seasons.
|
|
628
|
+
|
|
629
|
+
Args:
|
|
630
|
+
fields (List[str], optional): List of fields to retrieve.
|
|
631
|
+
If None, uses default fields.
|
|
632
|
+
filter_criteria (str, optional): JSON filter criteria.
|
|
633
|
+
Defaults to active seasons.
|
|
634
|
+
cached_session (Client, optional): The cached session to use
|
|
635
|
+
|
|
636
|
+
Returns:
|
|
637
|
+
List[GetSaisonsResponse]: List of season data
|
|
638
|
+
"""
|
|
639
|
+
url = f"{self.url}{ENDPOINT_SAISONS}"
|
|
640
|
+
|
|
641
|
+
params: dict[str, Any] = {}
|
|
642
|
+
if fields:
|
|
643
|
+
params["fields[]"] = fields
|
|
644
|
+
else:
|
|
645
|
+
# Use default fields from descriptor when no fields are specified
|
|
646
|
+
params["fields[]"] = QueryFieldsManager.get_saison_fields(FieldSet.DEFAULT)
|
|
647
|
+
|
|
648
|
+
if filter_criteria:
|
|
649
|
+
params["filter"] = filter_criteria
|
|
650
|
+
|
|
651
|
+
final_url = url_with_params(url, params)
|
|
652
|
+
data = catch_result(
|
|
653
|
+
lambda: http_get_json(
|
|
654
|
+
final_url,
|
|
655
|
+
self.headers,
|
|
656
|
+
debug=self.debug,
|
|
657
|
+
cached_session=cached_session or self.cached_session,
|
|
658
|
+
)
|
|
659
|
+
)
|
|
660
|
+
|
|
661
|
+
# Extract the actual data from the response wrapper
|
|
662
|
+
|
|
663
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
664
|
+
if actual_data and isinstance(actual_data, list):
|
|
665
|
+
adapter = TypeAdapter(list[GetSaisonsResponse])
|
|
666
|
+
return adapter.validate_python(actual_data)
|
|
667
|
+
return []
|
|
668
|
+
|
|
669
|
+
async def get_saisons_async(
|
|
670
|
+
self,
|
|
671
|
+
fields: list[str] | None = None,
|
|
672
|
+
filter_criteria: str | None = '{"actif":{"_eq":true}}',
|
|
673
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
674
|
+
) -> list[GetSaisonsResponse]:
|
|
675
|
+
"""
|
|
676
|
+
Retrieves list of seasons asynchroniously.
|
|
677
|
+
"""
|
|
678
|
+
url = f"{self.url}{ENDPOINT_SAISONS}"
|
|
679
|
+
|
|
680
|
+
params: dict[str, Any] = {}
|
|
681
|
+
if fields:
|
|
682
|
+
params["fields[]"] = fields
|
|
683
|
+
else:
|
|
684
|
+
params["fields[]"] = QueryFieldsManager.get_saison_fields(FieldSet.DEFAULT)
|
|
685
|
+
|
|
686
|
+
if filter_criteria:
|
|
687
|
+
params["filter"] = filter_criteria
|
|
688
|
+
|
|
689
|
+
final_url = url_with_params(url, params)
|
|
690
|
+
try:
|
|
691
|
+
data = await http_get_json_async(
|
|
692
|
+
final_url,
|
|
693
|
+
self.headers,
|
|
694
|
+
debug=self.debug,
|
|
695
|
+
cached_session=cached_session or self.async_cached_session,
|
|
696
|
+
)
|
|
697
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
698
|
+
if actual_data and isinstance(actual_data, list):
|
|
699
|
+
adapter = TypeAdapter(list[GetSaisonsResponse])
|
|
700
|
+
return adapter.validate_python(actual_data)
|
|
701
|
+
except Exception as e:
|
|
702
|
+
if self.debug:
|
|
703
|
+
self.logger.error(f"Error in get_saisons_async: {e}")
|
|
704
|
+
return []
|
|
705
|
+
|
|
706
|
+
def get_organisme(
|
|
707
|
+
self,
|
|
708
|
+
organisme_id: int,
|
|
709
|
+
fields: list[str] | None = None,
|
|
710
|
+
cached_session: Client | None = None,
|
|
711
|
+
) -> GetOrganismeResponse | None:
|
|
712
|
+
"""
|
|
713
|
+
Retrieves detailed information about an organisme.
|
|
714
|
+
|
|
715
|
+
Args:
|
|
716
|
+
organisme_id (int): The ID of the organisme
|
|
717
|
+
fields (List[str], optional): List of fields to retrieve.
|
|
718
|
+
If None, uses default fields.
|
|
719
|
+
cached_session (Client, optional): The cached session to use
|
|
720
|
+
|
|
721
|
+
Returns:
|
|
722
|
+
GetOrganismeResponse: Organisme data with members, competitions, etc.
|
|
723
|
+
"""
|
|
724
|
+
url = f"{self.url}{ENDPOINT_ORGANISMES}/{organisme_id}"
|
|
725
|
+
|
|
726
|
+
params: dict[str, Any] = {}
|
|
727
|
+
if fields:
|
|
728
|
+
params["fields[]"] = fields
|
|
729
|
+
else:
|
|
730
|
+
# Use default fields from descriptor when no fields are specified
|
|
731
|
+
params["fields[]"] = QueryFieldsManager.get_organisme_fields(
|
|
732
|
+
FieldSet.DEFAULT
|
|
733
|
+
)
|
|
734
|
+
|
|
735
|
+
final_url = url_with_params(url, params)
|
|
736
|
+
data = catch_result(
|
|
737
|
+
lambda: http_get_json(
|
|
738
|
+
final_url,
|
|
739
|
+
self.headers,
|
|
740
|
+
debug=self.debug,
|
|
741
|
+
cached_session=cached_session or self.cached_session,
|
|
742
|
+
)
|
|
743
|
+
)
|
|
744
|
+
|
|
745
|
+
# Extract the actual data from the response wrapper
|
|
746
|
+
|
|
747
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
748
|
+
if actual_data:
|
|
749
|
+
return GetOrganismeResponse.from_dict(actual_data)
|
|
750
|
+
return None
|
|
751
|
+
|
|
752
|
+
async def get_organisme_async(
|
|
753
|
+
self,
|
|
754
|
+
organisme_id: int,
|
|
755
|
+
fields: list[str] | None = None,
|
|
756
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
757
|
+
) -> GetOrganismeResponse | None:
|
|
758
|
+
"""
|
|
759
|
+
Retrieves detailed information about an organisme asynchroniously.
|
|
760
|
+
"""
|
|
761
|
+
url = f"{self.url}{ENDPOINT_ORGANISMES}/{organisme_id}"
|
|
762
|
+
|
|
763
|
+
params: dict[str, Any] = {}
|
|
764
|
+
if fields:
|
|
765
|
+
params["fields[]"] = fields
|
|
766
|
+
else:
|
|
767
|
+
params["fields[]"] = QueryFieldsManager.get_organisme_fields(
|
|
768
|
+
FieldSet.DEFAULT
|
|
769
|
+
)
|
|
770
|
+
|
|
771
|
+
final_url = url_with_params(url, params)
|
|
772
|
+
try:
|
|
773
|
+
data = await http_get_json_async(
|
|
774
|
+
final_url,
|
|
775
|
+
self.headers,
|
|
776
|
+
debug=self.debug,
|
|
777
|
+
cached_session=cached_session or self.async_cached_session,
|
|
778
|
+
)
|
|
779
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
780
|
+
if actual_data:
|
|
781
|
+
return GetOrganismeResponse.from_dict(actual_data)
|
|
782
|
+
return None
|
|
783
|
+
except Exception as e:
|
|
784
|
+
if self.debug:
|
|
785
|
+
self.logger.error(f"Error in get_organisme_async: {e}")
|
|
786
|
+
return None
|
|
787
|
+
|
|
788
|
+
def get_equipes(
|
|
789
|
+
self,
|
|
790
|
+
organisme_id: int,
|
|
791
|
+
cached_session: Client | None = None,
|
|
792
|
+
) -> list[GetOrganismeResponse.EngagementsitemModel] | None:
|
|
793
|
+
"""
|
|
794
|
+
Retrieves ONLY the team commitments (engagements) for a specific club.
|
|
795
|
+
"""
|
|
796
|
+
res = self.get_organisme(
|
|
797
|
+
organisme_id=organisme_id,
|
|
798
|
+
fields=QueryFieldsManager.get_equipes_fields(),
|
|
799
|
+
cached_session=cached_session,
|
|
800
|
+
)
|
|
801
|
+
return res.engagements if res else None
|
|
802
|
+
|
|
803
|
+
async def get_equipes_async(
|
|
804
|
+
self,
|
|
805
|
+
organisme_id: int,
|
|
806
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
807
|
+
) -> list[GetOrganismeResponse.EngagementsitemModel] | None:
|
|
808
|
+
"""
|
|
809
|
+
Asynchronously retrieves ONLY the team commitments (engagements) for a specific club.
|
|
810
|
+
"""
|
|
811
|
+
res = await self.get_organisme_async(
|
|
812
|
+
organisme_id=organisme_id,
|
|
813
|
+
fields=QueryFieldsManager.get_equipes_fields(),
|
|
814
|
+
cached_session=cached_session,
|
|
815
|
+
)
|
|
816
|
+
return res.engagements if res else None
|
|
817
|
+
|
|
818
|
+
def list_competitions(
|
|
819
|
+
self,
|
|
820
|
+
limit: int = 10,
|
|
821
|
+
fields: list[str] | None = None,
|
|
822
|
+
cached_session: Client | None = None,
|
|
823
|
+
) -> list[GetCompetitionResponse | None]:
|
|
824
|
+
"""
|
|
825
|
+
Lists competitions with optional field selection.
|
|
826
|
+
|
|
827
|
+
Args:
|
|
828
|
+
limit (int): Maximum number of competitions to return. Defaults to 10.
|
|
829
|
+
fields (List[str], optional): List of fields to retrieve.
|
|
830
|
+
If None, uses basic fields (id, nom).
|
|
831
|
+
cached_session (Client, optional): The cached session to use
|
|
832
|
+
|
|
833
|
+
Returns:
|
|
834
|
+
list[GetCompetitionResponse]: List of competition data
|
|
835
|
+
"""
|
|
836
|
+
url = f"{self.url}{ENDPOINT_COMPETITIONS}"
|
|
837
|
+
|
|
838
|
+
params: dict[str, Any] = {"limit": str(limit)}
|
|
839
|
+
|
|
840
|
+
if fields:
|
|
841
|
+
params["fields[]"] = fields
|
|
842
|
+
else:
|
|
843
|
+
params["fields[]"] = ["id", "nom"]
|
|
844
|
+
|
|
845
|
+
final_url = url_with_params(url, params)
|
|
846
|
+
data = catch_result(
|
|
847
|
+
lambda: http_get_json(
|
|
848
|
+
final_url,
|
|
849
|
+
self.headers,
|
|
850
|
+
debug=self.debug,
|
|
851
|
+
cached_session=cached_session or self.cached_session,
|
|
852
|
+
)
|
|
853
|
+
)
|
|
854
|
+
|
|
855
|
+
# Extract the actual data from the response wrapper
|
|
856
|
+
|
|
857
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
858
|
+
if actual_data and isinstance(actual_data, list):
|
|
859
|
+
adapter = TypeAdapter(list[GetCompetitionResponse])
|
|
860
|
+
return adapter.validate_python(actual_data)
|
|
861
|
+
return []
|
|
862
|
+
|
|
863
|
+
async def list_competitions_async(
|
|
864
|
+
self,
|
|
865
|
+
limit: int = 10,
|
|
866
|
+
fields: list[str] | None = None,
|
|
867
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
868
|
+
) -> list[GetCompetitionResponse | None]:
|
|
869
|
+
"""
|
|
870
|
+
Lists competitions with optional field selection asynchroniously.
|
|
871
|
+
"""
|
|
872
|
+
url = f"{self.url}{ENDPOINT_COMPETITIONS}"
|
|
873
|
+
|
|
874
|
+
params: dict[str, Any] = {"limit": str(limit)}
|
|
875
|
+
|
|
876
|
+
if fields:
|
|
877
|
+
params["fields[]"] = fields
|
|
878
|
+
else:
|
|
879
|
+
params["fields[]"] = ["id", "nom"]
|
|
880
|
+
|
|
881
|
+
final_url = url_with_params(url, params)
|
|
882
|
+
try:
|
|
883
|
+
data = await http_get_json_async(
|
|
884
|
+
final_url,
|
|
885
|
+
self.headers,
|
|
886
|
+
debug=self.debug,
|
|
887
|
+
cached_session=cached_session or self.async_cached_session,
|
|
888
|
+
)
|
|
889
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
890
|
+
if actual_data and isinstance(actual_data, list):
|
|
891
|
+
adapter = TypeAdapter(list[GetCompetitionResponse])
|
|
892
|
+
return adapter.validate_python(actual_data)
|
|
893
|
+
except Exception as e:
|
|
894
|
+
if self.debug:
|
|
895
|
+
self.logger.error(f"Error in list_competitions_async: {e}")
|
|
896
|
+
return []
|
|
897
|
+
|
|
898
|
+
def get_configuration(
|
|
899
|
+
self,
|
|
900
|
+
cached_session: Client | None = None,
|
|
901
|
+
) -> GetConfigurationResponse | None:
|
|
902
|
+
"""
|
|
903
|
+
Retrieves the API configuration including bearer tokens.
|
|
904
|
+
|
|
905
|
+
This endpoint returns configuration data including:
|
|
906
|
+
- key_dh: The API bearer token for api.ffbb.app
|
|
907
|
+
- key_ms: The Meilisearch bearer token for meilisearch-prod.ffbb.app
|
|
908
|
+
|
|
909
|
+
Args:
|
|
910
|
+
cached_session (Client, optional): The cached session to use
|
|
911
|
+
|
|
912
|
+
Returns:
|
|
913
|
+
GetConfigurationResponse: Configuration data with tokens
|
|
914
|
+
"""
|
|
915
|
+
url = f"{self.url}{ENDPOINT_CONFIGURATION}"
|
|
916
|
+
data = catch_result(
|
|
917
|
+
lambda: http_get_json(
|
|
918
|
+
url,
|
|
919
|
+
self.headers,
|
|
920
|
+
debug=self.debug,
|
|
921
|
+
cached_session=cached_session or self.cached_session,
|
|
922
|
+
retry_config=self.retry_config,
|
|
923
|
+
timeout_config=self.timeout_config,
|
|
924
|
+
)
|
|
925
|
+
)
|
|
926
|
+
|
|
927
|
+
# Extract the actual data from the response wrapper
|
|
928
|
+
|
|
929
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
930
|
+
if actual_data:
|
|
931
|
+
adapter = TypeAdapter(GetConfigurationResponse)
|
|
932
|
+
return adapter.validate_python(actual_data)
|
|
933
|
+
return None
|
|
934
|
+
|
|
935
|
+
async def get_configuration_async(
|
|
936
|
+
self,
|
|
937
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
938
|
+
) -> GetConfigurationResponse | None:
|
|
939
|
+
"""
|
|
940
|
+
Retrieves the API configuration including bearer tokens asynchroniously.
|
|
941
|
+
"""
|
|
942
|
+
url = f"{self.url}{ENDPOINT_CONFIGURATION}"
|
|
943
|
+
try:
|
|
944
|
+
data = await http_get_json_async(
|
|
945
|
+
url,
|
|
946
|
+
self.headers,
|
|
947
|
+
debug=self.debug,
|
|
948
|
+
cached_session=cached_session or self.async_cached_session,
|
|
949
|
+
retry_config=self.retry_config,
|
|
950
|
+
timeout_config=self.timeout_config,
|
|
951
|
+
)
|
|
952
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
953
|
+
if actual_data:
|
|
954
|
+
adapter = TypeAdapter(GetConfigurationResponse)
|
|
955
|
+
return adapter.validate_python(actual_data)
|
|
956
|
+
return None
|
|
957
|
+
except Exception as e:
|
|
958
|
+
if self.debug:
|
|
959
|
+
self.logger.error(f"Error in get_configuration_async: {e}")
|
|
960
|
+
return None
|
|
961
|
+
|
|
962
|
+
def get_rencontre(
|
|
963
|
+
self, id: str, cached_session: Client | None = None
|
|
964
|
+
) -> GetRencontreResponse | None:
|
|
965
|
+
"""Retrieves detailed information about a rencontre."""
|
|
966
|
+
url = f"{self.url}{ENDPOINT_RENCONTRES}/{id}"
|
|
967
|
+
data = catch_result(
|
|
968
|
+
lambda: http_get_json(
|
|
969
|
+
url,
|
|
970
|
+
self.headers,
|
|
971
|
+
debug=self.debug,
|
|
972
|
+
cached_session=cached_session or self.cached_session,
|
|
973
|
+
)
|
|
974
|
+
)
|
|
975
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
976
|
+
return GetRencontreResponse.from_dict(actual_data) if actual_data else None
|
|
977
|
+
|
|
978
|
+
async def get_rencontre_async(
|
|
979
|
+
self, id: str, cached_session: httpx.AsyncClient | None = None
|
|
980
|
+
) -> GetRencontreResponse | None:
|
|
981
|
+
"""Asynchronously retrieves detailed information about a rencontre."""
|
|
982
|
+
url = f"{self.url}{ENDPOINT_RENCONTRES}/{id}"
|
|
983
|
+
try:
|
|
984
|
+
data = await http_get_json_async(
|
|
985
|
+
url,
|
|
986
|
+
self.headers,
|
|
987
|
+
debug=self.debug,
|
|
988
|
+
cached_session=cached_session or self.async_cached_session,
|
|
989
|
+
)
|
|
990
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
991
|
+
return GetRencontreResponse.from_dict(actual_data) if actual_data else None
|
|
992
|
+
except Exception as e:
|
|
993
|
+
if self.debug:
|
|
994
|
+
self.logger.error(f"Error in get_rencontre_async: {e}")
|
|
995
|
+
return None
|
|
996
|
+
|
|
997
|
+
def get_engagement(
|
|
998
|
+
self, id: str, cached_session: Client | None = None
|
|
999
|
+
) -> GetEngagementResponse | None:
|
|
1000
|
+
"""Retrieves detailed information about an engagement."""
|
|
1001
|
+
url = f"{self.url}{ENDPOINT_ENGAGEMENTS}/{id}"
|
|
1002
|
+
data = catch_result(
|
|
1003
|
+
lambda: http_get_json(
|
|
1004
|
+
url,
|
|
1005
|
+
self.headers,
|
|
1006
|
+
debug=self.debug,
|
|
1007
|
+
cached_session=cached_session or self.cached_session,
|
|
1008
|
+
)
|
|
1009
|
+
)
|
|
1010
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
1011
|
+
return GetEngagementResponse.from_dict(actual_data) if actual_data else None
|
|
1012
|
+
|
|
1013
|
+
async def get_engagement_async(
|
|
1014
|
+
self, id: str, cached_session: httpx.AsyncClient | None = None
|
|
1015
|
+
) -> GetEngagementResponse | None:
|
|
1016
|
+
"""Asynchronously retrieves detailed information about an engagement."""
|
|
1017
|
+
url = f"{self.url}{ENDPOINT_ENGAGEMENTS}/{id}"
|
|
1018
|
+
try:
|
|
1019
|
+
data = await http_get_json_async(
|
|
1020
|
+
url,
|
|
1021
|
+
self.headers,
|
|
1022
|
+
debug=self.debug,
|
|
1023
|
+
cached_session=cached_session or self.async_cached_session,
|
|
1024
|
+
)
|
|
1025
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
1026
|
+
return GetEngagementResponse.from_dict(actual_data) if actual_data else None
|
|
1027
|
+
except Exception as e:
|
|
1028
|
+
if self.debug:
|
|
1029
|
+
self.logger.error(f"Error in get_engagement_async: {e}")
|
|
1030
|
+
return None
|
|
1031
|
+
|
|
1032
|
+
def get_formation(
|
|
1033
|
+
self, id: str, cached_session: Client | None = None
|
|
1034
|
+
) -> GetFormationResponse | None:
|
|
1035
|
+
"""Retrieves detailed information about a formation."""
|
|
1036
|
+
url = f"{self.url}{ENDPOINT_FORMATIONS}/{id}"
|
|
1037
|
+
data = catch_result(
|
|
1038
|
+
lambda: http_get_json(
|
|
1039
|
+
url,
|
|
1040
|
+
self.headers,
|
|
1041
|
+
debug=self.debug,
|
|
1042
|
+
cached_session=cached_session or self.cached_session,
|
|
1043
|
+
)
|
|
1044
|
+
)
|
|
1045
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
1046
|
+
return GetFormationResponse.from_dict(actual_data) if actual_data else None
|
|
1047
|
+
|
|
1048
|
+
async def get_formation_async(
|
|
1049
|
+
self, id: str, cached_session: httpx.AsyncClient | None = None
|
|
1050
|
+
) -> GetFormationResponse | None:
|
|
1051
|
+
"""Asynchronously retrieves detailed information about a formation."""
|
|
1052
|
+
url = f"{self.url}{ENDPOINT_FORMATIONS}/{id}"
|
|
1053
|
+
try:
|
|
1054
|
+
data = await http_get_json_async(
|
|
1055
|
+
url,
|
|
1056
|
+
self.headers,
|
|
1057
|
+
debug=self.debug,
|
|
1058
|
+
cached_session=cached_session or self.async_cached_session,
|
|
1059
|
+
)
|
|
1060
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
1061
|
+
return GetFormationResponse.from_dict(actual_data) if actual_data else None
|
|
1062
|
+
except Exception as e:
|
|
1063
|
+
if self.debug:
|
|
1064
|
+
self.logger.error(f"Error in get_formation_async: {e}")
|
|
1065
|
+
return None
|
|
1066
|
+
|
|
1067
|
+
def get_entraineur(
|
|
1068
|
+
self, id: str, cached_session: Client | None = None
|
|
1069
|
+
) -> GetEntraineurResponse | None:
|
|
1070
|
+
"""Retrieves detailed information about an entraineur."""
|
|
1071
|
+
url = f"{self.url}{ENDPOINT_ENTRAINEURS}/{id}"
|
|
1072
|
+
data = catch_result(
|
|
1073
|
+
lambda: http_get_json(
|
|
1074
|
+
url,
|
|
1075
|
+
self.headers,
|
|
1076
|
+
debug=self.debug,
|
|
1077
|
+
cached_session=cached_session or self.cached_session,
|
|
1078
|
+
)
|
|
1079
|
+
)
|
|
1080
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
1081
|
+
return GetEntraineurResponse.from_dict(actual_data) if actual_data else None
|
|
1082
|
+
|
|
1083
|
+
async def get_entraineur_async(
|
|
1084
|
+
self, id: str, cached_session: httpx.AsyncClient | None = None
|
|
1085
|
+
) -> GetEntraineurResponse | None:
|
|
1086
|
+
"""Asynchronously retrieves detailed information about an entraineur."""
|
|
1087
|
+
url = f"{self.url}{ENDPOINT_ENTRAINEURS}/{id}"
|
|
1088
|
+
try:
|
|
1089
|
+
data = await http_get_json_async(
|
|
1090
|
+
url,
|
|
1091
|
+
self.headers,
|
|
1092
|
+
debug=self.debug,
|
|
1093
|
+
cached_session=cached_session or self.async_cached_session,
|
|
1094
|
+
)
|
|
1095
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
1096
|
+
return GetEntraineurResponse.from_dict(actual_data) if actual_data else None
|
|
1097
|
+
except Exception as e:
|
|
1098
|
+
if self.debug:
|
|
1099
|
+
self.logger.error(f"Error in get_entraineur_async: {e}")
|
|
1100
|
+
return None
|
|
1101
|
+
|
|
1102
|
+
def get_commune(
|
|
1103
|
+
self, id: str, cached_session: Client | None = None
|
|
1104
|
+
) -> GetCommuneResponse | None:
|
|
1105
|
+
"""Retrieves detailed information about a commune."""
|
|
1106
|
+
url = f"{self.url}{ENDPOINT_COMMUNES}/{id}"
|
|
1107
|
+
data = catch_result(
|
|
1108
|
+
lambda: http_get_json(
|
|
1109
|
+
url,
|
|
1110
|
+
self.headers,
|
|
1111
|
+
debug=self.debug,
|
|
1112
|
+
cached_session=cached_session or self.cached_session,
|
|
1113
|
+
)
|
|
1114
|
+
)
|
|
1115
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
1116
|
+
return GetCommuneResponse.from_dict(actual_data) if actual_data else None
|
|
1117
|
+
|
|
1118
|
+
async def get_commune_async(
|
|
1119
|
+
self, id: str, cached_session: httpx.AsyncClient | None = None
|
|
1120
|
+
) -> GetCommuneResponse | None:
|
|
1121
|
+
"""Asynchronously retrieves detailed information about a commune."""
|
|
1122
|
+
url = f"{self.url}{ENDPOINT_COMMUNES}/{id}"
|
|
1123
|
+
try:
|
|
1124
|
+
data = await http_get_json_async(
|
|
1125
|
+
url,
|
|
1126
|
+
self.headers,
|
|
1127
|
+
debug=self.debug,
|
|
1128
|
+
cached_session=cached_session or self.async_cached_session,
|
|
1129
|
+
)
|
|
1130
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
1131
|
+
return GetCommuneResponse.from_dict(actual_data) if actual_data else None
|
|
1132
|
+
except Exception as e:
|
|
1133
|
+
if self.debug:
|
|
1134
|
+
self.logger.error(f"Error in get_commune_async: {e}")
|
|
1135
|
+
return None
|
|
1136
|
+
|
|
1137
|
+
def get_officiel(
|
|
1138
|
+
self, id: str, cached_session: Client | None = None
|
|
1139
|
+
) -> GetOfficielResponse | None:
|
|
1140
|
+
"""Retrieves detailed information about an officiel."""
|
|
1141
|
+
url = f"{self.url}{ENDPOINT_OFFICIELS}/{id}"
|
|
1142
|
+
data = catch_result(
|
|
1143
|
+
lambda: http_get_json(
|
|
1144
|
+
url,
|
|
1145
|
+
self.headers,
|
|
1146
|
+
debug=self.debug,
|
|
1147
|
+
cached_session=cached_session or self.cached_session,
|
|
1148
|
+
)
|
|
1149
|
+
)
|
|
1150
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
1151
|
+
return GetOfficielResponse.from_dict(actual_data) if actual_data else None
|
|
1152
|
+
|
|
1153
|
+
async def get_officiel_async(
|
|
1154
|
+
self, id: str, cached_session: httpx.AsyncClient | None = None
|
|
1155
|
+
) -> GetOfficielResponse | None:
|
|
1156
|
+
"""Asynchronously retrieves detailed information about an officiel."""
|
|
1157
|
+
url = f"{self.url}{ENDPOINT_OFFICIELS}/{id}"
|
|
1158
|
+
try:
|
|
1159
|
+
data = await http_get_json_async(
|
|
1160
|
+
url,
|
|
1161
|
+
self.headers,
|
|
1162
|
+
debug=self.debug,
|
|
1163
|
+
cached_session=cached_session or self.async_cached_session,
|
|
1164
|
+
)
|
|
1165
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
1166
|
+
return GetOfficielResponse.from_dict(actual_data) if actual_data else None
|
|
1167
|
+
except Exception as e:
|
|
1168
|
+
if self.debug:
|
|
1169
|
+
self.logger.error(f"Error in get_officiel_async: {e}")
|
|
1170
|
+
return None
|
|
1171
|
+
|
|
1172
|
+
def get_salle(
|
|
1173
|
+
self, id: str, cached_session: Client | None = None
|
|
1174
|
+
) -> GetSalleResponse | None:
|
|
1175
|
+
"""Retrieves detailed information about a salle."""
|
|
1176
|
+
url = f"{self.url}{ENDPOINT_SALLES}/{id}"
|
|
1177
|
+
data = catch_result(
|
|
1178
|
+
lambda: http_get_json(
|
|
1179
|
+
url,
|
|
1180
|
+
self.headers,
|
|
1181
|
+
debug=self.debug,
|
|
1182
|
+
cached_session=cached_session or self.cached_session,
|
|
1183
|
+
)
|
|
1184
|
+
)
|
|
1185
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
1186
|
+
return GetSalleResponse.from_dict(actual_data) if actual_data else None
|
|
1187
|
+
|
|
1188
|
+
async def get_salle_async(
|
|
1189
|
+
self, id: str, cached_session: httpx.AsyncClient | None = None
|
|
1190
|
+
) -> GetSalleResponse | None:
|
|
1191
|
+
"""Asynchronously retrieves detailed information about a salle."""
|
|
1192
|
+
url = f"{self.url}{ENDPOINT_SALLES}/{id}"
|
|
1193
|
+
try:
|
|
1194
|
+
data = await http_get_json_async(
|
|
1195
|
+
url,
|
|
1196
|
+
self.headers,
|
|
1197
|
+
debug=self.debug,
|
|
1198
|
+
cached_session=cached_session or self.async_cached_session,
|
|
1199
|
+
)
|
|
1200
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
1201
|
+
return GetSalleResponse.from_dict(actual_data) if actual_data else None
|
|
1202
|
+
except Exception as e:
|
|
1203
|
+
if self.debug:
|
|
1204
|
+
self.logger.error(f"Error in get_salle_async: {e}")
|
|
1205
|
+
return None
|
|
1206
|
+
|
|
1207
|
+
def get_terrain(
|
|
1208
|
+
self, id: str, cached_session: Client | None = None
|
|
1209
|
+
) -> GetTerrainResponse | None:
|
|
1210
|
+
"""Retrieves detailed information about a terrain."""
|
|
1211
|
+
url = f"{self.url}{ENDPOINT_TERRAINS}/{id}"
|
|
1212
|
+
data = catch_result(
|
|
1213
|
+
lambda: http_get_json(
|
|
1214
|
+
url,
|
|
1215
|
+
self.headers,
|
|
1216
|
+
debug=self.debug,
|
|
1217
|
+
cached_session=cached_session or self.cached_session,
|
|
1218
|
+
)
|
|
1219
|
+
)
|
|
1220
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
1221
|
+
return GetTerrainResponse.from_dict(actual_data) if actual_data else None
|
|
1222
|
+
|
|
1223
|
+
async def get_terrain_async(
|
|
1224
|
+
self, id: str, cached_session: httpx.AsyncClient | None = None
|
|
1225
|
+
) -> GetTerrainResponse | None:
|
|
1226
|
+
"""Asynchronously retrieves detailed information about a terrain."""
|
|
1227
|
+
url = f"{self.url}{ENDPOINT_TERRAINS}/{id}"
|
|
1228
|
+
try:
|
|
1229
|
+
data = await http_get_json_async(
|
|
1230
|
+
url,
|
|
1231
|
+
self.headers,
|
|
1232
|
+
debug=self.debug,
|
|
1233
|
+
cached_session=cached_session or self.async_cached_session,
|
|
1234
|
+
)
|
|
1235
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
1236
|
+
return GetTerrainResponse.from_dict(actual_data) if actual_data else None
|
|
1237
|
+
except Exception as e:
|
|
1238
|
+
if self.debug:
|
|
1239
|
+
self.logger.error(f"Error in get_terrain_async: {e}")
|
|
1240
|
+
return None
|
|
1241
|
+
|
|
1242
|
+
def get_tournoi(
|
|
1243
|
+
self, id: str, cached_session: Client | None = None
|
|
1244
|
+
) -> GetTournoiResponse | None:
|
|
1245
|
+
"""Retrieves detailed information about a tournoi."""
|
|
1246
|
+
url = f"{self.url}{ENDPOINT_TOURNOIS}/{id}"
|
|
1247
|
+
data = catch_result(
|
|
1248
|
+
lambda: http_get_json(
|
|
1249
|
+
url,
|
|
1250
|
+
self.headers,
|
|
1251
|
+
debug=self.debug,
|
|
1252
|
+
cached_session=cached_session or self.cached_session,
|
|
1253
|
+
)
|
|
1254
|
+
)
|
|
1255
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
1256
|
+
return GetTournoiResponse.from_dict(actual_data) if actual_data else None
|
|
1257
|
+
|
|
1258
|
+
async def get_tournoi_async(
|
|
1259
|
+
self, id: str, cached_session: httpx.AsyncClient | None = None
|
|
1260
|
+
) -> GetTournoiResponse | None:
|
|
1261
|
+
"""Asynchronously retrieves detailed information about a tournoi."""
|
|
1262
|
+
url = f"{self.url}{ENDPOINT_TOURNOIS}/{id}"
|
|
1263
|
+
try:
|
|
1264
|
+
data = await http_get_json_async(
|
|
1265
|
+
url,
|
|
1266
|
+
self.headers,
|
|
1267
|
+
debug=self.debug,
|
|
1268
|
+
cached_session=cached_session or self.async_cached_session,
|
|
1269
|
+
)
|
|
1270
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
1271
|
+
return GetTournoiResponse.from_dict(actual_data) if actual_data else None
|
|
1272
|
+
except Exception as e:
|
|
1273
|
+
if self.debug:
|
|
1274
|
+
self.logger.error(f"Error in get_tournoi_async: {e}")
|
|
1275
|
+
return None
|
|
1276
|
+
|
|
1277
|
+
def get_pratique(
|
|
1278
|
+
self, id: str, cached_session: Client | None = None
|
|
1279
|
+
) -> GetPratiqueResponse | None:
|
|
1280
|
+
"""Retrieves detailed information about a pratique."""
|
|
1281
|
+
url = f"{self.url}{ENDPOINT_PRATIQUES}/{id}"
|
|
1282
|
+
data = catch_result(
|
|
1283
|
+
lambda: http_get_json(
|
|
1284
|
+
url,
|
|
1285
|
+
self.headers,
|
|
1286
|
+
debug=self.debug,
|
|
1287
|
+
cached_session=cached_session or self.cached_session,
|
|
1288
|
+
)
|
|
1289
|
+
)
|
|
1290
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
1291
|
+
return GetPratiqueResponse.from_dict(actual_data) if actual_data else None
|
|
1292
|
+
|
|
1293
|
+
async def get_pratique_async(
|
|
1294
|
+
self, id: str, cached_session: httpx.AsyncClient | None = None
|
|
1295
|
+
) -> GetPratiqueResponse | None:
|
|
1296
|
+
"""Asynchronously retrieves detailed information about a pratique."""
|
|
1297
|
+
url = f"{self.url}{ENDPOINT_PRATIQUES}/{id}"
|
|
1298
|
+
try:
|
|
1299
|
+
data = await http_get_json_async(
|
|
1300
|
+
url,
|
|
1301
|
+
self.headers,
|
|
1302
|
+
debug=self.debug,
|
|
1303
|
+
cached_session=cached_session or self.async_cached_session,
|
|
1304
|
+
)
|
|
1305
|
+
actual_data = data.get("data") if data and isinstance(data, dict) else data
|
|
1306
|
+
return GetPratiqueResponse.from_dict(actual_data) if actual_data else None
|
|
1307
|
+
except Exception as e:
|
|
1308
|
+
if self.debug:
|
|
1309
|
+
self.logger.error(f"Error in get_pratique_async: {e}")
|
|
1310
|
+
return None
|
|
1311
|
+
|
|
1312
|
+
def get_session(
|
|
1313
|
+
self,
|
|
1314
|
+
id: str,
|
|
1315
|
+
fields: list[str] | None = None,
|
|
1316
|
+
cached_session: Client | None = None,
|
|
1317
|
+
) -> dict[str, Any] | None:
|
|
1318
|
+
"""Retrieves detailed information about a formation session."""
|
|
1319
|
+
return self._get_directus_item(
|
|
1320
|
+
ENDPOINT_SESSIONS, id, fields=fields, cached_session=cached_session
|
|
1321
|
+
)
|
|
1322
|
+
|
|
1323
|
+
def list_sessions(
|
|
1324
|
+
self,
|
|
1325
|
+
limit: int = 10,
|
|
1326
|
+
fields: list[str] | None = None,
|
|
1327
|
+
filter_criteria: str | None = None,
|
|
1328
|
+
sort: str | list[str] | None = None,
|
|
1329
|
+
cached_session: Client | None = None,
|
|
1330
|
+
) -> list[dict[str, Any]]:
|
|
1331
|
+
"""Lists formation sessions."""
|
|
1332
|
+
return self._list_directus_items(
|
|
1333
|
+
ENDPOINT_SESSIONS,
|
|
1334
|
+
limit=limit,
|
|
1335
|
+
fields=fields,
|
|
1336
|
+
filter_criteria=filter_criteria,
|
|
1337
|
+
sort=sort,
|
|
1338
|
+
cached_session=cached_session,
|
|
1339
|
+
)
|
|
1340
|
+
|
|
1341
|
+
async def get_session_async(
|
|
1342
|
+
self,
|
|
1343
|
+
id: str,
|
|
1344
|
+
fields: list[str] | None = None,
|
|
1345
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
1346
|
+
) -> dict[str, Any] | None:
|
|
1347
|
+
"""Asynchronously retrieves detailed information about a formation session."""
|
|
1348
|
+
return await self._get_directus_item_async(
|
|
1349
|
+
ENDPOINT_SESSIONS, id, fields=fields, cached_session=cached_session
|
|
1350
|
+
)
|
|
1351
|
+
|
|
1352
|
+
async def list_sessions_async(
|
|
1353
|
+
self,
|
|
1354
|
+
limit: int = 10,
|
|
1355
|
+
fields: list[str] | None = None,
|
|
1356
|
+
filter_criteria: str | None = None,
|
|
1357
|
+
sort: str | list[str] | None = None,
|
|
1358
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
1359
|
+
) -> list[dict[str, Any]]:
|
|
1360
|
+
"""Asynchronously lists formation sessions."""
|
|
1361
|
+
return await self._list_directus_items_async(
|
|
1362
|
+
ENDPOINT_SESSIONS,
|
|
1363
|
+
limit=limit,
|
|
1364
|
+
fields=fields,
|
|
1365
|
+
filter_criteria=filter_criteria,
|
|
1366
|
+
sort=sort,
|
|
1367
|
+
cached_session=cached_session,
|
|
1368
|
+
)
|
|
1369
|
+
|
|
1370
|
+
# ---------- list_rencontres ----------
|
|
1371
|
+
def list_rencontres(
|
|
1372
|
+
self,
|
|
1373
|
+
limit: int = 10,
|
|
1374
|
+
filter_criteria: str | None = None,
|
|
1375
|
+
sort: list[str] | None = None,
|
|
1376
|
+
offset: int | None = None,
|
|
1377
|
+
search: str | None = None,
|
|
1378
|
+
cached_session: Client | None = None,
|
|
1379
|
+
) -> list[GetRencontreResponse]:
|
|
1380
|
+
raw = self._list_directus_items(
|
|
1381
|
+
ENDPOINT_RENCONTRES,
|
|
1382
|
+
limit=limit,
|
|
1383
|
+
filter_criteria=filter_criteria,
|
|
1384
|
+
sort=sort,
|
|
1385
|
+
offset=offset,
|
|
1386
|
+
search=search,
|
|
1387
|
+
cached_session=cached_session,
|
|
1388
|
+
)
|
|
1389
|
+
return [GetRencontreResponse.from_dict(r) for r in raw if r]
|
|
1390
|
+
|
|
1391
|
+
async def list_rencontres_async(
|
|
1392
|
+
self,
|
|
1393
|
+
limit: int = 10,
|
|
1394
|
+
filter_criteria: str | None = None,
|
|
1395
|
+
sort: list[str] | None = None,
|
|
1396
|
+
offset: int | None = None,
|
|
1397
|
+
search: str | None = None,
|
|
1398
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
1399
|
+
) -> list[GetRencontreResponse]:
|
|
1400
|
+
raw = await self._list_directus_items_async(
|
|
1401
|
+
ENDPOINT_RENCONTRES,
|
|
1402
|
+
limit=limit,
|
|
1403
|
+
filter_criteria=filter_criteria,
|
|
1404
|
+
sort=sort,
|
|
1405
|
+
offset=offset,
|
|
1406
|
+
search=search,
|
|
1407
|
+
cached_session=cached_session,
|
|
1408
|
+
)
|
|
1409
|
+
return [GetRencontreResponse.from_dict(r) for r in raw if r]
|
|
1410
|
+
|
|
1411
|
+
# ---------- list_salles ----------
|
|
1412
|
+
def list_salles(
|
|
1413
|
+
self,
|
|
1414
|
+
limit: int = 10,
|
|
1415
|
+
filter_criteria: str | None = None,
|
|
1416
|
+
sort: list[str] | None = None,
|
|
1417
|
+
offset: int | None = None,
|
|
1418
|
+
search: str | None = None,
|
|
1419
|
+
cached_session: Client | None = None,
|
|
1420
|
+
) -> list[GetSalleResponse]:
|
|
1421
|
+
raw = self._list_directus_items(
|
|
1422
|
+
ENDPOINT_SALLES,
|
|
1423
|
+
limit=limit,
|
|
1424
|
+
filter_criteria=filter_criteria,
|
|
1425
|
+
sort=sort,
|
|
1426
|
+
offset=offset,
|
|
1427
|
+
search=search,
|
|
1428
|
+
cached_session=cached_session,
|
|
1429
|
+
)
|
|
1430
|
+
return [GetSalleResponse.from_dict(r) for r in raw if r]
|
|
1431
|
+
|
|
1432
|
+
async def list_salles_async(
|
|
1433
|
+
self,
|
|
1434
|
+
limit: int = 10,
|
|
1435
|
+
filter_criteria: str | None = None,
|
|
1436
|
+
sort: list[str] | None = None,
|
|
1437
|
+
offset: int | None = None,
|
|
1438
|
+
search: str | None = None,
|
|
1439
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
1440
|
+
) -> list[GetSalleResponse]:
|
|
1441
|
+
raw = await self._list_directus_items_async(
|
|
1442
|
+
ENDPOINT_SALLES,
|
|
1443
|
+
limit=limit,
|
|
1444
|
+
filter_criteria=filter_criteria,
|
|
1445
|
+
sort=sort,
|
|
1446
|
+
offset=offset,
|
|
1447
|
+
search=search,
|
|
1448
|
+
cached_session=cached_session,
|
|
1449
|
+
)
|
|
1450
|
+
return [GetSalleResponse.from_dict(r) for r in raw if r]
|
|
1451
|
+
|
|
1452
|
+
# ---------- list_terrains ----------
|
|
1453
|
+
def list_terrains(
|
|
1454
|
+
self,
|
|
1455
|
+
limit: int = 10,
|
|
1456
|
+
filter_criteria: str | None = None,
|
|
1457
|
+
sort: list[str] | None = None,
|
|
1458
|
+
offset: int | None = None,
|
|
1459
|
+
search: str | None = None,
|
|
1460
|
+
cached_session: Client | None = None,
|
|
1461
|
+
) -> list[GetTerrainResponse]:
|
|
1462
|
+
raw = self._list_directus_items(
|
|
1463
|
+
ENDPOINT_TERRAINS,
|
|
1464
|
+
limit=limit,
|
|
1465
|
+
filter_criteria=filter_criteria,
|
|
1466
|
+
sort=sort,
|
|
1467
|
+
offset=offset,
|
|
1468
|
+
search=search,
|
|
1469
|
+
cached_session=cached_session,
|
|
1470
|
+
)
|
|
1471
|
+
return [GetTerrainResponse.from_dict(r) for r in raw if r]
|
|
1472
|
+
|
|
1473
|
+
async def list_terrains_async(
|
|
1474
|
+
self,
|
|
1475
|
+
limit: int = 10,
|
|
1476
|
+
filter_criteria: str | None = None,
|
|
1477
|
+
sort: list[str] | None = None,
|
|
1478
|
+
offset: int | None = None,
|
|
1479
|
+
search: str | None = None,
|
|
1480
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
1481
|
+
) -> list[GetTerrainResponse]:
|
|
1482
|
+
raw = await self._list_directus_items_async(
|
|
1483
|
+
ENDPOINT_TERRAINS,
|
|
1484
|
+
limit=limit,
|
|
1485
|
+
filter_criteria=filter_criteria,
|
|
1486
|
+
sort=sort,
|
|
1487
|
+
offset=offset,
|
|
1488
|
+
search=search,
|
|
1489
|
+
cached_session=cached_session,
|
|
1490
|
+
)
|
|
1491
|
+
return [GetTerrainResponse.from_dict(r) for r in raw if r]
|
|
1492
|
+
|
|
1493
|
+
# ---------- list_tournois ----------
|
|
1494
|
+
def list_tournois(
|
|
1495
|
+
self,
|
|
1496
|
+
limit: int = 10,
|
|
1497
|
+
filter_criteria: str | None = None,
|
|
1498
|
+
sort: list[str] | None = None,
|
|
1499
|
+
offset: int | None = None,
|
|
1500
|
+
search: str | None = None,
|
|
1501
|
+
cached_session: Client | None = None,
|
|
1502
|
+
) -> list[GetTournoiResponse]:
|
|
1503
|
+
raw = self._list_directus_items(
|
|
1504
|
+
ENDPOINT_TOURNOIS,
|
|
1505
|
+
limit=limit,
|
|
1506
|
+
filter_criteria=filter_criteria,
|
|
1507
|
+
sort=sort,
|
|
1508
|
+
offset=offset,
|
|
1509
|
+
search=search,
|
|
1510
|
+
cached_session=cached_session,
|
|
1511
|
+
)
|
|
1512
|
+
return [GetTournoiResponse.from_dict(r) for r in raw if r]
|
|
1513
|
+
|
|
1514
|
+
async def list_tournois_async(
|
|
1515
|
+
self,
|
|
1516
|
+
limit: int = 10,
|
|
1517
|
+
filter_criteria: str | None = None,
|
|
1518
|
+
sort: list[str] | None = None,
|
|
1519
|
+
offset: int | None = None,
|
|
1520
|
+
search: str | None = None,
|
|
1521
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
1522
|
+
) -> list[GetTournoiResponse]:
|
|
1523
|
+
raw = await self._list_directus_items_async(
|
|
1524
|
+
ENDPOINT_TOURNOIS,
|
|
1525
|
+
limit=limit,
|
|
1526
|
+
filter_criteria=filter_criteria,
|
|
1527
|
+
sort=sort,
|
|
1528
|
+
offset=offset,
|
|
1529
|
+
search=search,
|
|
1530
|
+
cached_session=cached_session,
|
|
1531
|
+
)
|
|
1532
|
+
return [GetTournoiResponse.from_dict(r) for r in raw if r]
|
|
1533
|
+
|
|
1534
|
+
# ---------- list_engagements ----------
|
|
1535
|
+
def list_engagements(
|
|
1536
|
+
self,
|
|
1537
|
+
limit: int = 10,
|
|
1538
|
+
filter_criteria: str | None = None,
|
|
1539
|
+
sort: list[str] | None = None,
|
|
1540
|
+
offset: int | None = None,
|
|
1541
|
+
search: str | None = None,
|
|
1542
|
+
cached_session: Client | None = None,
|
|
1543
|
+
) -> list[GetEngagementResponse]:
|
|
1544
|
+
raw = self._list_directus_items(
|
|
1545
|
+
ENDPOINT_ENGAGEMENTS,
|
|
1546
|
+
limit=limit,
|
|
1547
|
+
filter_criteria=filter_criteria,
|
|
1548
|
+
sort=sort,
|
|
1549
|
+
offset=offset,
|
|
1550
|
+
search=search,
|
|
1551
|
+
cached_session=cached_session,
|
|
1552
|
+
)
|
|
1553
|
+
return [GetEngagementResponse.from_dict(r) for r in raw if r]
|
|
1554
|
+
|
|
1555
|
+
async def list_engagements_async(
|
|
1556
|
+
self,
|
|
1557
|
+
limit: int = 10,
|
|
1558
|
+
filter_criteria: str | None = None,
|
|
1559
|
+
sort: list[str] | None = None,
|
|
1560
|
+
offset: int | None = None,
|
|
1561
|
+
search: str | None = None,
|
|
1562
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
1563
|
+
) -> list[GetEngagementResponse]:
|
|
1564
|
+
raw = await self._list_directus_items_async(
|
|
1565
|
+
ENDPOINT_ENGAGEMENTS,
|
|
1566
|
+
limit=limit,
|
|
1567
|
+
filter_criteria=filter_criteria,
|
|
1568
|
+
sort=sort,
|
|
1569
|
+
offset=offset,
|
|
1570
|
+
search=search,
|
|
1571
|
+
cached_session=cached_session,
|
|
1572
|
+
)
|
|
1573
|
+
return [GetEngagementResponse.from_dict(r) for r in raw if r]
|
|
1574
|
+
|
|
1575
|
+
# ---------- list_formations ----------
|
|
1576
|
+
def list_formations(
|
|
1577
|
+
self,
|
|
1578
|
+
limit: int = 10,
|
|
1579
|
+
filter_criteria: str | None = None,
|
|
1580
|
+
sort: list[str] | None = None,
|
|
1581
|
+
offset: int | None = None,
|
|
1582
|
+
search: str | None = None,
|
|
1583
|
+
cached_session: Client | None = None,
|
|
1584
|
+
) -> list[GetFormationResponse]:
|
|
1585
|
+
raw = self._list_directus_items(
|
|
1586
|
+
ENDPOINT_FORMATIONS,
|
|
1587
|
+
limit=limit,
|
|
1588
|
+
filter_criteria=filter_criteria,
|
|
1589
|
+
sort=sort,
|
|
1590
|
+
offset=offset,
|
|
1591
|
+
search=search,
|
|
1592
|
+
cached_session=cached_session,
|
|
1593
|
+
)
|
|
1594
|
+
return [GetFormationResponse.from_dict(r) for r in raw if r]
|
|
1595
|
+
|
|
1596
|
+
async def list_formations_async(
|
|
1597
|
+
self,
|
|
1598
|
+
limit: int = 10,
|
|
1599
|
+
filter_criteria: str | None = None,
|
|
1600
|
+
sort: list[str] | None = None,
|
|
1601
|
+
offset: int | None = None,
|
|
1602
|
+
search: str | None = None,
|
|
1603
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
1604
|
+
) -> list[GetFormationResponse]:
|
|
1605
|
+
raw = await self._list_directus_items_async(
|
|
1606
|
+
ENDPOINT_FORMATIONS,
|
|
1607
|
+
limit=limit,
|
|
1608
|
+
filter_criteria=filter_criteria,
|
|
1609
|
+
sort=sort,
|
|
1610
|
+
offset=offset,
|
|
1611
|
+
search=search,
|
|
1612
|
+
cached_session=cached_session,
|
|
1613
|
+
)
|
|
1614
|
+
return [GetFormationResponse.from_dict(r) for r in raw if r]
|
|
1615
|
+
|
|
1616
|
+
# ---------- list_entraineurs ----------
|
|
1617
|
+
def list_entraineurs(
|
|
1618
|
+
self,
|
|
1619
|
+
limit: int = 10,
|
|
1620
|
+
filter_criteria: str | None = None,
|
|
1621
|
+
sort: list[str] | None = None,
|
|
1622
|
+
offset: int | None = None,
|
|
1623
|
+
search: str | None = None,
|
|
1624
|
+
cached_session: Client | None = None,
|
|
1625
|
+
) -> list[GetEntraineurResponse]:
|
|
1626
|
+
raw = self._list_directus_items(
|
|
1627
|
+
ENDPOINT_ENTRAINEURS,
|
|
1628
|
+
limit=limit,
|
|
1629
|
+
filter_criteria=filter_criteria,
|
|
1630
|
+
sort=sort,
|
|
1631
|
+
offset=offset,
|
|
1632
|
+
search=search,
|
|
1633
|
+
cached_session=cached_session,
|
|
1634
|
+
)
|
|
1635
|
+
return [GetEntraineurResponse.from_dict(r) for r in raw if r]
|
|
1636
|
+
|
|
1637
|
+
async def list_entraineurs_async(
|
|
1638
|
+
self,
|
|
1639
|
+
limit: int = 10,
|
|
1640
|
+
filter_criteria: str | None = None,
|
|
1641
|
+
sort: list[str] | None = None,
|
|
1642
|
+
offset: int | None = None,
|
|
1643
|
+
search: str | None = None,
|
|
1644
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
1645
|
+
) -> list[GetEntraineurResponse]:
|
|
1646
|
+
raw = await self._list_directus_items_async(
|
|
1647
|
+
ENDPOINT_ENTRAINEURS,
|
|
1648
|
+
limit=limit,
|
|
1649
|
+
filter_criteria=filter_criteria,
|
|
1650
|
+
sort=sort,
|
|
1651
|
+
offset=offset,
|
|
1652
|
+
search=search,
|
|
1653
|
+
cached_session=cached_session,
|
|
1654
|
+
)
|
|
1655
|
+
return [GetEntraineurResponse.from_dict(r) for r in raw if r]
|
|
1656
|
+
|
|
1657
|
+
# ---------- list_communes ----------
|
|
1658
|
+
def list_communes(
|
|
1659
|
+
self,
|
|
1660
|
+
limit: int = 10,
|
|
1661
|
+
filter_criteria: str | None = None,
|
|
1662
|
+
sort: list[str] | None = None,
|
|
1663
|
+
offset: int | None = None,
|
|
1664
|
+
search: str | None = None,
|
|
1665
|
+
cached_session: Client | None = None,
|
|
1666
|
+
) -> list[GetCommuneResponse]:
|
|
1667
|
+
raw = self._list_directus_items(
|
|
1668
|
+
ENDPOINT_COMMUNES,
|
|
1669
|
+
limit=limit,
|
|
1670
|
+
filter_criteria=filter_criteria,
|
|
1671
|
+
sort=sort,
|
|
1672
|
+
offset=offset,
|
|
1673
|
+
search=search,
|
|
1674
|
+
cached_session=cached_session,
|
|
1675
|
+
)
|
|
1676
|
+
return [GetCommuneResponse.from_dict(r) for r in raw if r]
|
|
1677
|
+
|
|
1678
|
+
async def list_communes_async(
|
|
1679
|
+
self,
|
|
1680
|
+
limit: int = 10,
|
|
1681
|
+
filter_criteria: str | None = None,
|
|
1682
|
+
sort: list[str] | None = None,
|
|
1683
|
+
offset: int | None = None,
|
|
1684
|
+
search: str | None = None,
|
|
1685
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
1686
|
+
) -> list[GetCommuneResponse]:
|
|
1687
|
+
raw = await self._list_directus_items_async(
|
|
1688
|
+
ENDPOINT_COMMUNES,
|
|
1689
|
+
limit=limit,
|
|
1690
|
+
filter_criteria=filter_criteria,
|
|
1691
|
+
sort=sort,
|
|
1692
|
+
offset=offset,
|
|
1693
|
+
search=search,
|
|
1694
|
+
cached_session=cached_session,
|
|
1695
|
+
)
|
|
1696
|
+
return [GetCommuneResponse.from_dict(r) for r in raw if r]
|
|
1697
|
+
|
|
1698
|
+
# ---------- list_officiels ----------
|
|
1699
|
+
def list_officiels(
|
|
1700
|
+
self,
|
|
1701
|
+
limit: int = 10,
|
|
1702
|
+
filter_criteria: str | None = None,
|
|
1703
|
+
sort: list[str] | None = None,
|
|
1704
|
+
offset: int | None = None,
|
|
1705
|
+
search: str | None = None,
|
|
1706
|
+
cached_session: Client | None = None,
|
|
1707
|
+
) -> list[GetOfficielResponse]:
|
|
1708
|
+
raw = self._list_directus_items(
|
|
1709
|
+
ENDPOINT_OFFICIELS,
|
|
1710
|
+
limit=limit,
|
|
1711
|
+
filter_criteria=filter_criteria,
|
|
1712
|
+
sort=sort,
|
|
1713
|
+
offset=offset,
|
|
1714
|
+
search=search,
|
|
1715
|
+
cached_session=cached_session,
|
|
1716
|
+
)
|
|
1717
|
+
return [GetOfficielResponse.from_dict(r) for r in raw if r]
|
|
1718
|
+
|
|
1719
|
+
async def list_officiels_async(
|
|
1720
|
+
self,
|
|
1721
|
+
limit: int = 10,
|
|
1722
|
+
filter_criteria: str | None = None,
|
|
1723
|
+
sort: list[str] | None = None,
|
|
1724
|
+
offset: int | None = None,
|
|
1725
|
+
search: str | None = None,
|
|
1726
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
1727
|
+
) -> list[GetOfficielResponse]:
|
|
1728
|
+
raw = await self._list_directus_items_async(
|
|
1729
|
+
ENDPOINT_OFFICIELS,
|
|
1730
|
+
limit=limit,
|
|
1731
|
+
filter_criteria=filter_criteria,
|
|
1732
|
+
sort=sort,
|
|
1733
|
+
offset=offset,
|
|
1734
|
+
search=search,
|
|
1735
|
+
cached_session=cached_session,
|
|
1736
|
+
)
|
|
1737
|
+
return [GetOfficielResponse.from_dict(r) for r in raw if r]
|
|
1738
|
+
|
|
1739
|
+
# ---------- list_pratiques ----------
|
|
1740
|
+
def list_pratiques(
|
|
1741
|
+
self,
|
|
1742
|
+
limit: int = 10,
|
|
1743
|
+
filter_criteria: str | None = None,
|
|
1744
|
+
sort: list[str] | None = None,
|
|
1745
|
+
offset: int | None = None,
|
|
1746
|
+
search: str | None = None,
|
|
1747
|
+
cached_session: Client | None = None,
|
|
1748
|
+
) -> list[GetPratiqueResponse]:
|
|
1749
|
+
raw = self._list_directus_items(
|
|
1750
|
+
ENDPOINT_PRATIQUES,
|
|
1751
|
+
limit=limit,
|
|
1752
|
+
filter_criteria=filter_criteria,
|
|
1753
|
+
sort=sort,
|
|
1754
|
+
offset=offset,
|
|
1755
|
+
search=search,
|
|
1756
|
+
cached_session=cached_session,
|
|
1757
|
+
)
|
|
1758
|
+
return [GetPratiqueResponse.from_dict(r) for r in raw if r]
|
|
1759
|
+
|
|
1760
|
+
async def list_pratiques_async(
|
|
1761
|
+
self,
|
|
1762
|
+
limit: int = 10,
|
|
1763
|
+
filter_criteria: str | None = None,
|
|
1764
|
+
sort: list[str] | None = None,
|
|
1765
|
+
offset: int | None = None,
|
|
1766
|
+
search: str | None = None,
|
|
1767
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
1768
|
+
) -> list[GetPratiqueResponse]:
|
|
1769
|
+
raw = await self._list_directus_items_async(
|
|
1770
|
+
ENDPOINT_PRATIQUES,
|
|
1771
|
+
limit=limit,
|
|
1772
|
+
filter_criteria=filter_criteria,
|
|
1773
|
+
sort=sort,
|
|
1774
|
+
offset=offset,
|
|
1775
|
+
search=search,
|
|
1776
|
+
cached_session=cached_session,
|
|
1777
|
+
)
|
|
1778
|
+
return [GetPratiqueResponse.from_dict(r) for r in raw if r]
|
|
1779
|
+
|
|
1780
|
+
# ---------- Pagination helper: list all items ----------
|
|
1781
|
+
def _list_all_directus_items(
|
|
1782
|
+
self,
|
|
1783
|
+
endpoint: str,
|
|
1784
|
+
model_cls,
|
|
1785
|
+
filter_criteria: str | None = None,
|
|
1786
|
+
sort: list[str] | None = None,
|
|
1787
|
+
search: str | None = None,
|
|
1788
|
+
page_size: int = 100,
|
|
1789
|
+
max_items: int = 10000,
|
|
1790
|
+
cached_session: Client | None = None,
|
|
1791
|
+
) -> list:
|
|
1792
|
+
results: list = []
|
|
1793
|
+
offset = 0
|
|
1794
|
+
while len(results) < max_items:
|
|
1795
|
+
batch = self._list_directus_items(
|
|
1796
|
+
endpoint,
|
|
1797
|
+
limit=page_size,
|
|
1798
|
+
filter_criteria=filter_criteria,
|
|
1799
|
+
sort=sort,
|
|
1800
|
+
offset=offset,
|
|
1801
|
+
search=search,
|
|
1802
|
+
cached_session=cached_session,
|
|
1803
|
+
)
|
|
1804
|
+
if not batch:
|
|
1805
|
+
break
|
|
1806
|
+
results.extend([model_cls.from_dict(r) for r in batch if r])
|
|
1807
|
+
if len(batch) < page_size:
|
|
1808
|
+
break
|
|
1809
|
+
offset += page_size
|
|
1810
|
+
return results[:max_items]
|
|
1811
|
+
|
|
1812
|
+
def list_all_rencontres(
|
|
1813
|
+
self,
|
|
1814
|
+
filter_criteria: str | None = None,
|
|
1815
|
+
sort: list[str] | None = None,
|
|
1816
|
+
search: str | None = None,
|
|
1817
|
+
page_size: int = 100,
|
|
1818
|
+
max_items: int = 10000,
|
|
1819
|
+
cached_session: Client | None = None,
|
|
1820
|
+
) -> list[GetRencontreResponse]:
|
|
1821
|
+
return self._list_all_directus_items(
|
|
1822
|
+
ENDPOINT_RENCONTRES,
|
|
1823
|
+
GetRencontreResponse,
|
|
1824
|
+
filter_criteria=filter_criteria,
|
|
1825
|
+
sort=sort,
|
|
1826
|
+
search=search,
|
|
1827
|
+
page_size=page_size,
|
|
1828
|
+
max_items=max_items,
|
|
1829
|
+
cached_session=cached_session,
|
|
1830
|
+
)
|
|
1831
|
+
|
|
1832
|
+
def list_all_salles(
|
|
1833
|
+
self,
|
|
1834
|
+
filter_criteria: str | None = None,
|
|
1835
|
+
sort: list[str] | None = None,
|
|
1836
|
+
search: str | None = None,
|
|
1837
|
+
page_size: int = 100,
|
|
1838
|
+
max_items: int = 10000,
|
|
1839
|
+
cached_session: Client | None = None,
|
|
1840
|
+
) -> list[GetSalleResponse]:
|
|
1841
|
+
return self._list_all_directus_items(
|
|
1842
|
+
ENDPOINT_SALLES,
|
|
1843
|
+
GetSalleResponse,
|
|
1844
|
+
filter_criteria=filter_criteria,
|
|
1845
|
+
sort=sort,
|
|
1846
|
+
search=search,
|
|
1847
|
+
page_size=page_size,
|
|
1848
|
+
max_items=max_items,
|
|
1849
|
+
cached_session=cached_session,
|
|
1850
|
+
)
|
|
1851
|
+
|
|
1852
|
+
def list_all_terrains(
|
|
1853
|
+
self,
|
|
1854
|
+
filter_criteria: str | None = None,
|
|
1855
|
+
sort: list[str] | None = None,
|
|
1856
|
+
search: str | None = None,
|
|
1857
|
+
page_size: int = 100,
|
|
1858
|
+
max_items: int = 10000,
|
|
1859
|
+
cached_session: Client | None = None,
|
|
1860
|
+
) -> list[GetTerrainResponse]:
|
|
1861
|
+
return self._list_all_directus_items(
|
|
1862
|
+
ENDPOINT_TERRAINS,
|
|
1863
|
+
GetTerrainResponse,
|
|
1864
|
+
filter_criteria=filter_criteria,
|
|
1865
|
+
sort=sort,
|
|
1866
|
+
search=search,
|
|
1867
|
+
page_size=page_size,
|
|
1868
|
+
max_items=max_items,
|
|
1869
|
+
cached_session=cached_session,
|
|
1870
|
+
)
|
|
1871
|
+
|
|
1872
|
+
def list_all_tournois(
|
|
1873
|
+
self,
|
|
1874
|
+
filter_criteria: str | None = None,
|
|
1875
|
+
sort: list[str] | None = None,
|
|
1876
|
+
search: str | None = None,
|
|
1877
|
+
page_size: int = 100,
|
|
1878
|
+
max_items: int = 10000,
|
|
1879
|
+
cached_session: Client | None = None,
|
|
1880
|
+
) -> list[GetTournoiResponse]:
|
|
1881
|
+
return self._list_all_directus_items(
|
|
1882
|
+
ENDPOINT_TOURNOIS,
|
|
1883
|
+
GetTournoiResponse,
|
|
1884
|
+
filter_criteria=filter_criteria,
|
|
1885
|
+
sort=sort,
|
|
1886
|
+
search=search,
|
|
1887
|
+
page_size=page_size,
|
|
1888
|
+
max_items=max_items,
|
|
1889
|
+
cached_session=cached_session,
|
|
1890
|
+
)
|
|
1891
|
+
|
|
1892
|
+
def list_all_engagements(
|
|
1893
|
+
self,
|
|
1894
|
+
filter_criteria: str | None = None,
|
|
1895
|
+
sort: list[str] | None = None,
|
|
1896
|
+
search: str | None = None,
|
|
1897
|
+
page_size: int = 100,
|
|
1898
|
+
max_items: int = 10000,
|
|
1899
|
+
cached_session: Client | None = None,
|
|
1900
|
+
) -> list[GetEngagementResponse]:
|
|
1901
|
+
return self._list_all_directus_items(
|
|
1902
|
+
ENDPOINT_ENGAGEMENTS,
|
|
1903
|
+
GetEngagementResponse,
|
|
1904
|
+
filter_criteria=filter_criteria,
|
|
1905
|
+
sort=sort,
|
|
1906
|
+
search=search,
|
|
1907
|
+
page_size=page_size,
|
|
1908
|
+
max_items=max_items,
|
|
1909
|
+
cached_session=cached_session,
|
|
1910
|
+
)
|
|
1911
|
+
|
|
1912
|
+
def list_all_formations(
|
|
1913
|
+
self,
|
|
1914
|
+
filter_criteria: str | None = None,
|
|
1915
|
+
sort: list[str] | None = None,
|
|
1916
|
+
search: str | None = None,
|
|
1917
|
+
page_size: int = 100,
|
|
1918
|
+
max_items: int = 10000,
|
|
1919
|
+
cached_session: Client | None = None,
|
|
1920
|
+
) -> list[GetFormationResponse]:
|
|
1921
|
+
return self._list_all_directus_items(
|
|
1922
|
+
ENDPOINT_FORMATIONS,
|
|
1923
|
+
GetFormationResponse,
|
|
1924
|
+
filter_criteria=filter_criteria,
|
|
1925
|
+
sort=sort,
|
|
1926
|
+
search=search,
|
|
1927
|
+
page_size=page_size,
|
|
1928
|
+
max_items=max_items,
|
|
1929
|
+
cached_session=cached_session,
|
|
1930
|
+
)
|
|
1931
|
+
|
|
1932
|
+
def list_all_entraineurs(
|
|
1933
|
+
self,
|
|
1934
|
+
filter_criteria: str | None = None,
|
|
1935
|
+
sort: list[str] | None = None,
|
|
1936
|
+
search: str | None = None,
|
|
1937
|
+
page_size: int = 100,
|
|
1938
|
+
max_items: int = 10000,
|
|
1939
|
+
cached_session: Client | None = None,
|
|
1940
|
+
) -> list[GetEntraineurResponse]:
|
|
1941
|
+
return self._list_all_directus_items(
|
|
1942
|
+
ENDPOINT_ENTRAINEURS,
|
|
1943
|
+
GetEntraineurResponse,
|
|
1944
|
+
filter_criteria=filter_criteria,
|
|
1945
|
+
sort=sort,
|
|
1946
|
+
search=search,
|
|
1947
|
+
page_size=page_size,
|
|
1948
|
+
max_items=max_items,
|
|
1949
|
+
cached_session=cached_session,
|
|
1950
|
+
)
|
|
1951
|
+
|
|
1952
|
+
def list_all_communes(
|
|
1953
|
+
self,
|
|
1954
|
+
filter_criteria: str | None = None,
|
|
1955
|
+
sort: list[str] | None = None,
|
|
1956
|
+
search: str | None = None,
|
|
1957
|
+
page_size: int = 100,
|
|
1958
|
+
max_items: int = 10000,
|
|
1959
|
+
cached_session: Client | None = None,
|
|
1960
|
+
) -> list[GetCommuneResponse]:
|
|
1961
|
+
return self._list_all_directus_items(
|
|
1962
|
+
ENDPOINT_COMMUNES,
|
|
1963
|
+
GetCommuneResponse,
|
|
1964
|
+
filter_criteria=filter_criteria,
|
|
1965
|
+
sort=sort,
|
|
1966
|
+
search=search,
|
|
1967
|
+
page_size=page_size,
|
|
1968
|
+
max_items=max_items,
|
|
1969
|
+
cached_session=cached_session,
|
|
1970
|
+
)
|
|
1971
|
+
|
|
1972
|
+
def list_all_officiels(
|
|
1973
|
+
self,
|
|
1974
|
+
filter_criteria: str | None = None,
|
|
1975
|
+
sort: list[str] | None = None,
|
|
1976
|
+
search: str | None = None,
|
|
1977
|
+
page_size: int = 100,
|
|
1978
|
+
max_items: int = 10000,
|
|
1979
|
+
cached_session: Client | None = None,
|
|
1980
|
+
) -> list[GetOfficielResponse]:
|
|
1981
|
+
return self._list_all_directus_items(
|
|
1982
|
+
ENDPOINT_OFFICIELS,
|
|
1983
|
+
GetOfficielResponse,
|
|
1984
|
+
filter_criteria=filter_criteria,
|
|
1985
|
+
sort=sort,
|
|
1986
|
+
search=search,
|
|
1987
|
+
page_size=page_size,
|
|
1988
|
+
max_items=max_items,
|
|
1989
|
+
cached_session=cached_session,
|
|
1990
|
+
)
|
|
1991
|
+
|
|
1992
|
+
def list_all_pratiques(
|
|
1993
|
+
self,
|
|
1994
|
+
filter_criteria: str | None = None,
|
|
1995
|
+
sort: list[str] | None = None,
|
|
1996
|
+
search: str | None = None,
|
|
1997
|
+
page_size: int = 100,
|
|
1998
|
+
max_items: int = 10000,
|
|
1999
|
+
cached_session: Client | None = None,
|
|
2000
|
+
) -> list[GetPratiqueResponse]:
|
|
2001
|
+
return self._list_all_directus_items(
|
|
2002
|
+
ENDPOINT_PRATIQUES,
|
|
2003
|
+
GetPratiqueResponse,
|
|
2004
|
+
filter_criteria=filter_criteria,
|
|
2005
|
+
sort=sort,
|
|
2006
|
+
search=search,
|
|
2007
|
+
page_size=page_size,
|
|
2008
|
+
max_items=max_items,
|
|
2009
|
+
cached_session=cached_session,
|
|
2010
|
+
)
|
|
2011
|
+
|
|
2012
|
+
async def _list_all_directus_items_async(
|
|
2013
|
+
self,
|
|
2014
|
+
endpoint: str,
|
|
2015
|
+
model_cls,
|
|
2016
|
+
filter_criteria: str | None = None,
|
|
2017
|
+
sort: list[str] | None = None,
|
|
2018
|
+
search: str | None = None,
|
|
2019
|
+
page_size: int = 100,
|
|
2020
|
+
max_items: int = 10000,
|
|
2021
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
2022
|
+
) -> list:
|
|
2023
|
+
results: list = []
|
|
2024
|
+
offset = 0
|
|
2025
|
+
while len(results) < max_items:
|
|
2026
|
+
batch = await self._list_directus_items_async(
|
|
2027
|
+
endpoint,
|
|
2028
|
+
limit=page_size,
|
|
2029
|
+
filter_criteria=filter_criteria,
|
|
2030
|
+
sort=sort,
|
|
2031
|
+
offset=offset,
|
|
2032
|
+
search=search,
|
|
2033
|
+
cached_session=cached_session,
|
|
2034
|
+
)
|
|
2035
|
+
if not batch:
|
|
2036
|
+
break
|
|
2037
|
+
results.extend([model_cls.from_dict(r) for r in batch if r])
|
|
2038
|
+
if len(batch) < page_size:
|
|
2039
|
+
break
|
|
2040
|
+
offset += page_size
|
|
2041
|
+
return results[:max_items]
|
|
2042
|
+
|
|
2043
|
+
async def list_all_rencontres_async(
|
|
2044
|
+
self,
|
|
2045
|
+
filter_criteria: str | None = None,
|
|
2046
|
+
sort: list[str] | None = None,
|
|
2047
|
+
search: str | None = None,
|
|
2048
|
+
page_size: int = 100,
|
|
2049
|
+
max_items: int = 10000,
|
|
2050
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
2051
|
+
) -> list[GetRencontreResponse]:
|
|
2052
|
+
return await self._list_all_directus_items_async(
|
|
2053
|
+
ENDPOINT_RENCONTRES,
|
|
2054
|
+
GetRencontreResponse,
|
|
2055
|
+
filter_criteria=filter_criteria,
|
|
2056
|
+
sort=sort,
|
|
2057
|
+
search=search,
|
|
2058
|
+
page_size=page_size,
|
|
2059
|
+
max_items=max_items,
|
|
2060
|
+
cached_session=cached_session,
|
|
2061
|
+
)
|
|
2062
|
+
|
|
2063
|
+
async def list_all_salles_async(
|
|
2064
|
+
self,
|
|
2065
|
+
filter_criteria: str | None = None,
|
|
2066
|
+
sort: list[str] | None = None,
|
|
2067
|
+
search: str | None = None,
|
|
2068
|
+
page_size: int = 100,
|
|
2069
|
+
max_items: int = 10000,
|
|
2070
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
2071
|
+
) -> list[GetSalleResponse]:
|
|
2072
|
+
return await self._list_all_directus_items_async(
|
|
2073
|
+
ENDPOINT_SALLES,
|
|
2074
|
+
GetSalleResponse,
|
|
2075
|
+
filter_criteria=filter_criteria,
|
|
2076
|
+
sort=sort,
|
|
2077
|
+
search=search,
|
|
2078
|
+
page_size=page_size,
|
|
2079
|
+
max_items=max_items,
|
|
2080
|
+
cached_session=cached_session,
|
|
2081
|
+
)
|
|
2082
|
+
|
|
2083
|
+
async def list_all_terrains_async(
|
|
2084
|
+
self,
|
|
2085
|
+
filter_criteria: str | None = None,
|
|
2086
|
+
sort: list[str] | None = None,
|
|
2087
|
+
search: str | None = None,
|
|
2088
|
+
page_size: int = 100,
|
|
2089
|
+
max_items: int = 10000,
|
|
2090
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
2091
|
+
) -> list[GetTerrainResponse]:
|
|
2092
|
+
return await self._list_all_directus_items_async(
|
|
2093
|
+
ENDPOINT_TERRAINS,
|
|
2094
|
+
GetTerrainResponse,
|
|
2095
|
+
filter_criteria=filter_criteria,
|
|
2096
|
+
sort=sort,
|
|
2097
|
+
search=search,
|
|
2098
|
+
page_size=page_size,
|
|
2099
|
+
max_items=max_items,
|
|
2100
|
+
cached_session=cached_session,
|
|
2101
|
+
)
|
|
2102
|
+
|
|
2103
|
+
async def list_all_tournois_async(
|
|
2104
|
+
self,
|
|
2105
|
+
filter_criteria: str | None = None,
|
|
2106
|
+
sort: list[str] | None = None,
|
|
2107
|
+
search: str | None = None,
|
|
2108
|
+
page_size: int = 100,
|
|
2109
|
+
max_items: int = 10000,
|
|
2110
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
2111
|
+
) -> list[GetTournoiResponse]:
|
|
2112
|
+
return await self._list_all_directus_items_async(
|
|
2113
|
+
ENDPOINT_TOURNOIS,
|
|
2114
|
+
GetTournoiResponse,
|
|
2115
|
+
filter_criteria=filter_criteria,
|
|
2116
|
+
sort=sort,
|
|
2117
|
+
search=search,
|
|
2118
|
+
page_size=page_size,
|
|
2119
|
+
max_items=max_items,
|
|
2120
|
+
cached_session=cached_session,
|
|
2121
|
+
)
|
|
2122
|
+
|
|
2123
|
+
async def list_all_engagements_async(
|
|
2124
|
+
self,
|
|
2125
|
+
filter_criteria: str | None = None,
|
|
2126
|
+
sort: list[str] | None = None,
|
|
2127
|
+
search: str | None = None,
|
|
2128
|
+
page_size: int = 100,
|
|
2129
|
+
max_items: int = 10000,
|
|
2130
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
2131
|
+
) -> list[GetEngagementResponse]:
|
|
2132
|
+
return await self._list_all_directus_items_async(
|
|
2133
|
+
ENDPOINT_ENGAGEMENTS,
|
|
2134
|
+
GetEngagementResponse,
|
|
2135
|
+
filter_criteria=filter_criteria,
|
|
2136
|
+
sort=sort,
|
|
2137
|
+
search=search,
|
|
2138
|
+
page_size=page_size,
|
|
2139
|
+
max_items=max_items,
|
|
2140
|
+
cached_session=cached_session,
|
|
2141
|
+
)
|
|
2142
|
+
|
|
2143
|
+
async def list_all_formations_async(
|
|
2144
|
+
self,
|
|
2145
|
+
filter_criteria: str | None = None,
|
|
2146
|
+
sort: list[str] | None = None,
|
|
2147
|
+
search: str | None = None,
|
|
2148
|
+
page_size: int = 100,
|
|
2149
|
+
max_items: int = 10000,
|
|
2150
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
2151
|
+
) -> list[GetFormationResponse]:
|
|
2152
|
+
return await self._list_all_directus_items_async(
|
|
2153
|
+
ENDPOINT_FORMATIONS,
|
|
2154
|
+
GetFormationResponse,
|
|
2155
|
+
filter_criteria=filter_criteria,
|
|
2156
|
+
sort=sort,
|
|
2157
|
+
search=search,
|
|
2158
|
+
page_size=page_size,
|
|
2159
|
+
max_items=max_items,
|
|
2160
|
+
cached_session=cached_session,
|
|
2161
|
+
)
|
|
2162
|
+
|
|
2163
|
+
async def list_all_entraineurs_async(
|
|
2164
|
+
self,
|
|
2165
|
+
filter_criteria: str | None = None,
|
|
2166
|
+
sort: list[str] | None = None,
|
|
2167
|
+
search: str | None = None,
|
|
2168
|
+
page_size: int = 100,
|
|
2169
|
+
max_items: int = 10000,
|
|
2170
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
2171
|
+
) -> list[GetEntraineurResponse]:
|
|
2172
|
+
return await self._list_all_directus_items_async(
|
|
2173
|
+
ENDPOINT_ENTRAINEURS,
|
|
2174
|
+
GetEntraineurResponse,
|
|
2175
|
+
filter_criteria=filter_criteria,
|
|
2176
|
+
sort=sort,
|
|
2177
|
+
search=search,
|
|
2178
|
+
page_size=page_size,
|
|
2179
|
+
max_items=max_items,
|
|
2180
|
+
cached_session=cached_session,
|
|
2181
|
+
)
|
|
2182
|
+
|
|
2183
|
+
async def list_all_communes_async(
|
|
2184
|
+
self,
|
|
2185
|
+
filter_criteria: str | None = None,
|
|
2186
|
+
sort: list[str] | None = None,
|
|
2187
|
+
search: str | None = None,
|
|
2188
|
+
page_size: int = 100,
|
|
2189
|
+
max_items: int = 10000,
|
|
2190
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
2191
|
+
) -> list[GetCommuneResponse]:
|
|
2192
|
+
return await self._list_all_directus_items_async(
|
|
2193
|
+
ENDPOINT_COMMUNES,
|
|
2194
|
+
GetCommuneResponse,
|
|
2195
|
+
filter_criteria=filter_criteria,
|
|
2196
|
+
sort=sort,
|
|
2197
|
+
search=search,
|
|
2198
|
+
page_size=page_size,
|
|
2199
|
+
max_items=max_items,
|
|
2200
|
+
cached_session=cached_session,
|
|
2201
|
+
)
|
|
2202
|
+
|
|
2203
|
+
async def list_all_officiels_async(
|
|
2204
|
+
self,
|
|
2205
|
+
filter_criteria: str | None = None,
|
|
2206
|
+
sort: list[str] | None = None,
|
|
2207
|
+
search: str | None = None,
|
|
2208
|
+
page_size: int = 100,
|
|
2209
|
+
max_items: int = 10000,
|
|
2210
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
2211
|
+
) -> list[GetOfficielResponse]:
|
|
2212
|
+
return await self._list_all_directus_items_async(
|
|
2213
|
+
ENDPOINT_OFFICIELS,
|
|
2214
|
+
GetOfficielResponse,
|
|
2215
|
+
filter_criteria=filter_criteria,
|
|
2216
|
+
sort=sort,
|
|
2217
|
+
search=search,
|
|
2218
|
+
page_size=page_size,
|
|
2219
|
+
max_items=max_items,
|
|
2220
|
+
cached_session=cached_session,
|
|
2221
|
+
)
|
|
2222
|
+
|
|
2223
|
+
async def list_all_pratiques_async(
|
|
2224
|
+
self,
|
|
2225
|
+
filter_criteria: str | None = None,
|
|
2226
|
+
sort: list[str] | None = None,
|
|
2227
|
+
search: str | None = None,
|
|
2228
|
+
page_size: int = 100,
|
|
2229
|
+
max_items: int = 10000,
|
|
2230
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
2231
|
+
) -> list[GetPratiqueResponse]:
|
|
2232
|
+
return await self._list_all_directus_items_async(
|
|
2233
|
+
ENDPOINT_PRATIQUES,
|
|
2234
|
+
GetPratiqueResponse,
|
|
2235
|
+
filter_criteria=filter_criteria,
|
|
2236
|
+
sort=sort,
|
|
2237
|
+
search=search,
|
|
2238
|
+
page_size=page_size,
|
|
2239
|
+
max_items=max_items,
|
|
2240
|
+
cached_session=cached_session,
|
|
2241
|
+
)
|
|
2242
|
+
|
|
2243
|
+
def get_genius_sport_match(
|
|
2244
|
+
self,
|
|
2245
|
+
id: str,
|
|
2246
|
+
fields: list[str] | None = None,
|
|
2247
|
+
cached_session: Client | None = None,
|
|
2248
|
+
) -> dict[str, Any] | None:
|
|
2249
|
+
"""Retrieves detailed Genius Sports match statistics."""
|
|
2250
|
+
return self._get_directus_item(
|
|
2251
|
+
ENDPOINT_GENIUS_SPORT_MATCHES,
|
|
2252
|
+
id,
|
|
2253
|
+
fields=fields,
|
|
2254
|
+
cached_session=cached_session,
|
|
2255
|
+
)
|
|
2256
|
+
|
|
2257
|
+
def list_genius_sport_matches(
|
|
2258
|
+
self,
|
|
2259
|
+
limit: int = 10,
|
|
2260
|
+
fields: list[str] | None = None,
|
|
2261
|
+
filter_criteria: str | None = None,
|
|
2262
|
+
sort: str | list[str] | None = None,
|
|
2263
|
+
cached_session: Client | None = None,
|
|
2264
|
+
) -> list[dict[str, Any]]:
|
|
2265
|
+
"""Lists Genius Sports match statistics."""
|
|
2266
|
+
return self._list_directus_items(
|
|
2267
|
+
ENDPOINT_GENIUS_SPORT_MATCHES,
|
|
2268
|
+
limit=limit,
|
|
2269
|
+
fields=fields,
|
|
2270
|
+
filter_criteria=filter_criteria,
|
|
2271
|
+
sort=sort,
|
|
2272
|
+
cached_session=cached_session,
|
|
2273
|
+
)
|
|
2274
|
+
|
|
2275
|
+
async def get_genius_sport_match_async(
|
|
2276
|
+
self,
|
|
2277
|
+
id: str,
|
|
2278
|
+
fields: list[str] | None = None,
|
|
2279
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
2280
|
+
) -> dict[str, Any] | None:
|
|
2281
|
+
"""Asynchronously retrieves detailed Genius Sports match statistics."""
|
|
2282
|
+
return await self._get_directus_item_async(
|
|
2283
|
+
ENDPOINT_GENIUS_SPORT_MATCHES,
|
|
2284
|
+
id,
|
|
2285
|
+
fields=fields,
|
|
2286
|
+
cached_session=cached_session,
|
|
2287
|
+
)
|
|
2288
|
+
|
|
2289
|
+
async def list_genius_sport_matches_async(
|
|
2290
|
+
self,
|
|
2291
|
+
limit: int = 10,
|
|
2292
|
+
fields: list[str] | None = None,
|
|
2293
|
+
filter_criteria: str | None = None,
|
|
2294
|
+
sort: str | list[str] | None = None,
|
|
2295
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
2296
|
+
) -> list[dict[str, Any]]:
|
|
2297
|
+
"""Asynchronously lists Genius Sports match statistics."""
|
|
2298
|
+
return await self._list_directus_items_async(
|
|
2299
|
+
ENDPOINT_GENIUS_SPORT_MATCHES,
|
|
2300
|
+
limit=limit,
|
|
2301
|
+
fields=fields,
|
|
2302
|
+
filter_criteria=filter_criteria,
|
|
2303
|
+
sort=sort,
|
|
2304
|
+
cached_session=cached_session,
|
|
2305
|
+
)
|
|
2306
|
+
|
|
2307
|
+
def list_genius_sports_live_logs(
|
|
2308
|
+
self,
|
|
2309
|
+
limit: int = 10,
|
|
2310
|
+
fields: list[str] | None = None,
|
|
2311
|
+
filter_criteria: str | None = None,
|
|
2312
|
+
sort: str | list[str] | None = None,
|
|
2313
|
+
cached_session: Client | None = None,
|
|
2314
|
+
) -> list[dict[str, Any]]:
|
|
2315
|
+
"""Lists Genius Sports live logs."""
|
|
2316
|
+
return self._list_directus_items(
|
|
2317
|
+
ENDPOINT_GENIUS_SPORTS_LIVE_LOGS,
|
|
2318
|
+
limit=limit,
|
|
2319
|
+
fields=fields,
|
|
2320
|
+
filter_criteria=filter_criteria,
|
|
2321
|
+
sort=sort,
|
|
2322
|
+
cached_session=cached_session,
|
|
2323
|
+
)
|
|
2324
|
+
|
|
2325
|
+
def get_rematch_video(
|
|
2326
|
+
self,
|
|
2327
|
+
id: str,
|
|
2328
|
+
fields: list[str] | None = None,
|
|
2329
|
+
cached_session: Client | None = None,
|
|
2330
|
+
) -> dict[str, Any] | None:
|
|
2331
|
+
"""Retrieves a Rematch video linked to FFBB data."""
|
|
2332
|
+
return self._get_directus_item(
|
|
2333
|
+
ENDPOINT_REMATCH_VIDEOS, id, fields=fields, cached_session=cached_session
|
|
2334
|
+
)
|
|
2335
|
+
|
|
2336
|
+
def list_rematch_videos(
|
|
2337
|
+
self,
|
|
2338
|
+
limit: int = 10,
|
|
2339
|
+
fields: list[str] | None = None,
|
|
2340
|
+
filter_criteria: str | None = None,
|
|
2341
|
+
sort: str | list[str] | None = None,
|
|
2342
|
+
cached_session: Client | None = None,
|
|
2343
|
+
) -> list[dict[str, Any]]:
|
|
2344
|
+
"""Lists Rematch videos linked to FFBB data."""
|
|
2345
|
+
return self._list_directus_items(
|
|
2346
|
+
ENDPOINT_REMATCH_VIDEOS,
|
|
2347
|
+
limit=limit,
|
|
2348
|
+
fields=fields,
|
|
2349
|
+
filter_criteria=filter_criteria,
|
|
2350
|
+
sort=sort,
|
|
2351
|
+
cached_session=cached_session,
|
|
2352
|
+
)
|
|
2353
|
+
|
|
2354
|
+
async def get_rematch_video_async(
|
|
2355
|
+
self,
|
|
2356
|
+
id: str,
|
|
2357
|
+
fields: list[str] | None = None,
|
|
2358
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
2359
|
+
) -> dict[str, Any] | None:
|
|
2360
|
+
"""Asynchronously retrieves a Rematch video linked to FFBB data."""
|
|
2361
|
+
return await self._get_directus_item_async(
|
|
2362
|
+
ENDPOINT_REMATCH_VIDEOS, id, fields=fields, cached_session=cached_session
|
|
2363
|
+
)
|
|
2364
|
+
|
|
2365
|
+
async def list_rematch_videos_async(
|
|
2366
|
+
self,
|
|
2367
|
+
limit: int = 10,
|
|
2368
|
+
fields: list[str] | None = None,
|
|
2369
|
+
filter_criteria: str | None = None,
|
|
2370
|
+
sort: str | list[str] | None = None,
|
|
2371
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
2372
|
+
) -> list[dict[str, Any]]:
|
|
2373
|
+
"""Asynchronously lists Rematch videos linked to FFBB data."""
|
|
2374
|
+
return await self._list_directus_items_async(
|
|
2375
|
+
ENDPOINT_REMATCH_VIDEOS,
|
|
2376
|
+
limit=limit,
|
|
2377
|
+
fields=fields,
|
|
2378
|
+
filter_criteria=filter_criteria,
|
|
2379
|
+
sort=sort,
|
|
2380
|
+
cached_session=cached_session,
|
|
2381
|
+
)
|
|
2382
|
+
|
|
2383
|
+
def get_edf_match(
|
|
2384
|
+
self,
|
|
2385
|
+
id: str | int,
|
|
2386
|
+
fields: list[str] | None = None,
|
|
2387
|
+
cached_session: Client | None = None,
|
|
2388
|
+
) -> dict[str, Any] | None:
|
|
2389
|
+
"""Retrieves an Equipe de France match."""
|
|
2390
|
+
return self._get_directus_item(
|
|
2391
|
+
ENDPOINT_EDF_MATCHES, id, fields=fields, cached_session=cached_session
|
|
2392
|
+
)
|
|
2393
|
+
|
|
2394
|
+
def list_edf_matches(
|
|
2395
|
+
self,
|
|
2396
|
+
limit: int = 10,
|
|
2397
|
+
fields: list[str] | None = None,
|
|
2398
|
+
filter_criteria: str | None = None,
|
|
2399
|
+
sort: str | list[str] | None = None,
|
|
2400
|
+
cached_session: Client | None = None,
|
|
2401
|
+
) -> list[dict[str, Any]]:
|
|
2402
|
+
"""Lists Equipe de France matches."""
|
|
2403
|
+
return self._list_directus_items(
|
|
2404
|
+
ENDPOINT_EDF_MATCHES,
|
|
2405
|
+
limit=limit,
|
|
2406
|
+
fields=fields,
|
|
2407
|
+
filter_criteria=filter_criteria,
|
|
2408
|
+
sort=sort,
|
|
2409
|
+
cached_session=cached_session,
|
|
2410
|
+
)
|
|
2411
|
+
|
|
2412
|
+
def get_edf_player(
|
|
2413
|
+
self,
|
|
2414
|
+
id: str | int,
|
|
2415
|
+
fields: list[str] | None = None,
|
|
2416
|
+
cached_session: Client | None = None,
|
|
2417
|
+
) -> dict[str, Any] | None:
|
|
2418
|
+
"""Retrieves an Equipe de France player."""
|
|
2419
|
+
return self._get_directus_item(
|
|
2420
|
+
ENDPOINT_EDF_PLAYERS, id, fields=fields, cached_session=cached_session
|
|
2421
|
+
)
|
|
2422
|
+
|
|
2423
|
+
def list_edf_players(
|
|
2424
|
+
self,
|
|
2425
|
+
limit: int = 10,
|
|
2426
|
+
fields: list[str] | None = None,
|
|
2427
|
+
filter_criteria: str | None = None,
|
|
2428
|
+
sort: str | list[str] | None = None,
|
|
2429
|
+
cached_session: Client | None = None,
|
|
2430
|
+
) -> list[dict[str, Any]]:
|
|
2431
|
+
"""Lists Equipe de France players."""
|
|
2432
|
+
return self._list_directus_items(
|
|
2433
|
+
ENDPOINT_EDF_PLAYERS,
|
|
2434
|
+
limit=limit,
|
|
2435
|
+
fields=fields,
|
|
2436
|
+
filter_criteria=filter_criteria,
|
|
2437
|
+
sort=sort,
|
|
2438
|
+
cached_session=cached_session,
|
|
2439
|
+
)
|
|
2440
|
+
|
|
2441
|
+
def list_edf_teams(
|
|
2442
|
+
self,
|
|
2443
|
+
limit: int = 10,
|
|
2444
|
+
fields: list[str] | None = None,
|
|
2445
|
+
filter_criteria: str | None = None,
|
|
2446
|
+
sort: str | list[str] | None = None,
|
|
2447
|
+
cached_session: Client | None = None,
|
|
2448
|
+
) -> list[dict[str, Any]]:
|
|
2449
|
+
"""Lists Equipe de France teams."""
|
|
2450
|
+
return self._list_directus_items(
|
|
2451
|
+
ENDPOINT_EDF_TEAMS,
|
|
2452
|
+
limit=limit,
|
|
2453
|
+
fields=fields,
|
|
2454
|
+
filter_criteria=filter_criteria,
|
|
2455
|
+
sort=sort,
|
|
2456
|
+
cached_session=cached_session,
|
|
2457
|
+
)
|
|
2458
|
+
|
|
2459
|
+
def list_edf_rosters(
|
|
2460
|
+
self,
|
|
2461
|
+
limit: int = 10,
|
|
2462
|
+
fields: list[str] | None = None,
|
|
2463
|
+
filter_criteria: str | None = None,
|
|
2464
|
+
sort: str | list[str] | None = None,
|
|
2465
|
+
cached_session: Client | None = None,
|
|
2466
|
+
) -> list[dict[str, Any]]:
|
|
2467
|
+
"""Lists Equipe de France rosters."""
|
|
2468
|
+
return self._list_directus_items(
|
|
2469
|
+
ENDPOINT_EDF_ROSTERS,
|
|
2470
|
+
limit=limit,
|
|
2471
|
+
fields=fields,
|
|
2472
|
+
filter_criteria=filter_criteria,
|
|
2473
|
+
sort=sort,
|
|
2474
|
+
cached_session=cached_session,
|
|
2475
|
+
)
|