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.
Files changed (207) hide show
  1. ffbb_api_client_v3/__init__.py +25 -0
  2. ffbb_data_client/__init__.py +175 -0
  3. ffbb_data_client/clients/__init__.py +13 -0
  4. ffbb_data_client/clients/api_ffbb_app_client.py +2475 -0
  5. ffbb_data_client/clients/ffbb_data_client.py +2789 -0
  6. ffbb_data_client/clients/meilisearch_client.py +218 -0
  7. ffbb_data_client/clients/meilisearch_ffbb_client.py +647 -0
  8. ffbb_data_client/config.py +153 -0
  9. ffbb_data_client/data/__init__.py +25 -0
  10. ffbb_data_client/data/collections.json +1364 -0
  11. ffbb_data_client/data/endpoint_discovery.json +1875 -0
  12. ffbb_data_client/data/indexes.json +501 -0
  13. ffbb_data_client/data/openapi.json +35713 -0
  14. ffbb_data_client/data/openapi_full.json +37622 -0
  15. ffbb_data_client/helpers/__init__.py +27 -0
  16. ffbb_data_client/helpers/http_requests_helper.py +73 -0
  17. ffbb_data_client/helpers/http_requests_utils.py +502 -0
  18. ffbb_data_client/helpers/meilisearch_client_extension.py +153 -0
  19. ffbb_data_client/helpers/multi_search_query_helper.py +35 -0
  20. ffbb_data_client/models/__init__.py +241 -0
  21. ffbb_data_client/models/affiche.py +45 -0
  22. ffbb_data_client/models/cartographie.py +82 -0
  23. ffbb_data_client/models/categorie.py +55 -0
  24. ffbb_data_client/models/categorie_type.py +42 -0
  25. ffbb_data_client/models/clock.py +38 -0
  26. ffbb_data_client/models/club_contacts.py +77 -0
  27. ffbb_data_client/models/code.py +7 -0
  28. ffbb_data_client/models/commune.py +66 -0
  29. ffbb_data_client/models/competition_fields.py +309 -0
  30. ffbb_data_client/models/competition_id.py +116 -0
  31. ffbb_data_client/models/competition_id_categorie.py +31 -0
  32. ffbb_data_client/models/competition_id_sexe.py +31 -0
  33. ffbb_data_client/models/competition_id_type_competition.py +27 -0
  34. ffbb_data_client/models/competition_id_type_competition_generique.py +24 -0
  35. ffbb_data_client/models/competition_origine.py +69 -0
  36. ffbb_data_client/models/competition_origine_categorie.py +23 -0
  37. ffbb_data_client/models/competition_origine_type_competition.py +14 -0
  38. ffbb_data_client/models/competition_origine_type_competition_generique.py +24 -0
  39. ffbb_data_client/models/competition_type.py +6 -0
  40. ffbb_data_client/models/competitions_facet_distribution.py +65 -0
  41. ffbb_data_client/models/competitions_facet_stats.py +14 -0
  42. ffbb_data_client/models/competitions_hit.py +232 -0
  43. ffbb_data_client/models/competitions_multi_search_query.py +40 -0
  44. ffbb_data_client/models/competitions_query.py +11 -0
  45. ffbb_data_client/models/configuration_models.py +5 -0
  46. ffbb_data_client/models/contact_info.py +18 -0
  47. ffbb_data_client/models/content_multi_search_query.py +93 -0
  48. ffbb_data_client/models/coordonnees.py +27 -0
  49. ffbb_data_client/models/coordonnees_type.py +5 -0
  50. ffbb_data_client/models/document_flyer.py +205 -0
  51. ffbb_data_client/models/document_flyer_type.py +6 -0
  52. ffbb_data_client/models/engagement_contacts.py +97 -0
  53. ffbb_data_client/models/engagements_facet_distribution.py +59 -0
  54. ffbb_data_client/models/engagements_facet_stats.py +14 -0
  55. ffbb_data_client/models/engagements_hit.py +192 -0
  56. ffbb_data_client/models/engagements_multi_search_query.py +41 -0
  57. ffbb_data_client/models/etat.py +6 -0
  58. ffbb_data_client/models/external_competition_id.py +42 -0
  59. ffbb_data_client/models/external_id.py +72 -0
  60. ffbb_data_client/models/facet_distribution.py +13 -0
  61. ffbb_data_client/models/facet_stats.py +13 -0
  62. ffbb_data_client/models/field_set.py +10 -0
  63. ffbb_data_client/models/folder.py +35 -0
  64. ffbb_data_client/models/formation_session.py +60 -0
  65. ffbb_data_client/models/formations_facet_distribution.py +61 -0
  66. ffbb_data_client/models/formations_facet_stats.py +14 -0
  67. ffbb_data_client/models/formations_hit.py +277 -0
  68. ffbb_data_client/models/formations_multi_search_query.py +41 -0
  69. ffbb_data_client/models/game_stats_model.py +57 -0
  70. ffbb_data_client/models/game_stats_models.py +5 -0
  71. ffbb_data_client/models/generic_search.py +92 -0
  72. ffbb_data_client/models/geo.py +27 -0
  73. ffbb_data_client/models/geo_sort_order.py +6 -0
  74. ffbb_data_client/models/get_commune_response.py +18 -0
  75. ffbb_data_client/models/get_competition_response.py +523 -0
  76. ffbb_data_client/models/get_configuration_response.py +45 -0
  77. ffbb_data_client/models/get_engagement_response.py +23 -0
  78. ffbb_data_client/models/get_entraineur_response.py +18 -0
  79. ffbb_data_client/models/get_formation_response.py +28 -0
  80. ffbb_data_client/models/get_officiel_response.py +18 -0
  81. ffbb_data_client/models/get_organisme_response.py +476 -0
  82. ffbb_data_client/models/get_poule_response.py +68 -0
  83. ffbb_data_client/models/get_pratique_response.py +18 -0
  84. ffbb_data_client/models/get_rencontre_response.py +93 -0
  85. ffbb_data_client/models/get_saisons_response.py +56 -0
  86. ffbb_data_client/models/get_salle_response.py +20 -0
  87. ffbb_data_client/models/get_terrain_response.py +16 -0
  88. ffbb_data_client/models/get_tournoi_response.py +16 -0
  89. ffbb_data_client/models/gradient_color.py +27 -0
  90. ffbb_data_client/models/hit.py +16 -0
  91. ffbb_data_client/models/id_engagement_equipe.py +32 -0
  92. ffbb_data_client/models/id_organisme_equipe.py +51 -0
  93. ffbb_data_client/models/id_organisme_equipe1_logo.py +28 -0
  94. ffbb_data_client/models/id_poule.py +27 -0
  95. ffbb_data_client/models/jour.py +11 -0
  96. ffbb_data_client/models/label.py +15 -0
  97. ffbb_data_client/models/labellisation.py +30 -0
  98. ffbb_data_client/models/live.py +192 -0
  99. ffbb_data_client/models/lives.py +6 -0
  100. ffbb_data_client/models/logo.py +28 -0
  101. ffbb_data_client/models/multi_search_queries.py +24 -0
  102. ffbb_data_client/models/multi_search_query.py +96 -0
  103. ffbb_data_client/models/multi_search_result_competitions.py +14 -0
  104. ffbb_data_client/models/multi_search_result_engagements.py +14 -0
  105. ffbb_data_client/models/multi_search_result_formations.py +12 -0
  106. ffbb_data_client/models/multi_search_result_organismes.py +12 -0
  107. ffbb_data_client/models/multi_search_result_pratiques.py +12 -0
  108. ffbb_data_client/models/multi_search_result_rencontres.py +12 -0
  109. ffbb_data_client/models/multi_search_result_salles.py +12 -0
  110. ffbb_data_client/models/multi_search_result_terrains.py +12 -0
  111. ffbb_data_client/models/multi_search_result_tournois.py +12 -0
  112. ffbb_data_client/models/multi_search_results.py +103 -0
  113. ffbb_data_client/models/multi_search_results_class.py +96 -0
  114. ffbb_data_client/models/nature_sol.py +57 -0
  115. ffbb_data_client/models/niveau.py +10 -0
  116. ffbb_data_client/models/niveau_class.py +27 -0
  117. ffbb_data_client/models/niveau_extractor.py +214 -0
  118. ffbb_data_client/models/niveau_info.py +64 -0
  119. ffbb_data_client/models/niveau_models.py +14 -0
  120. ffbb_data_client/models/niveau_type.py +10 -0
  121. ffbb_data_client/models/objectif.py +7 -0
  122. ffbb_data_client/models/organisateur.py +197 -0
  123. ffbb_data_client/models/organisateur_type.py +6 -0
  124. ffbb_data_client/models/organisme_fields.py +327 -0
  125. ffbb_data_client/models/organisme_id_pere.py +177 -0
  126. ffbb_data_client/models/organismes_facet_distribution.py +46 -0
  127. ffbb_data_client/models/organismes_facet_stats.py +14 -0
  128. ffbb_data_client/models/organismes_hit.py +196 -0
  129. ffbb_data_client/models/organismes_multi_search_query.py +41 -0
  130. ffbb_data_client/models/organismes_query.py +8 -0
  131. ffbb_data_client/models/phase_code.py +23 -0
  132. ffbb_data_client/models/poule.py +35 -0
  133. ffbb_data_client/models/poule_fields.py +261 -0
  134. ffbb_data_client/models/poule_rencontre_item_model.py +69 -0
  135. ffbb_data_client/models/poules_models.py +6 -0
  136. ffbb_data_client/models/poules_query.py +9 -0
  137. ffbb_data_client/models/pratique.py +7 -0
  138. ffbb_data_client/models/pratiques_facet_distribution.py +29 -0
  139. ffbb_data_client/models/pratiques_facet_stats.py +14 -0
  140. ffbb_data_client/models/pratiques_hit.py +310 -0
  141. ffbb_data_client/models/pratiques_hit_type.py +9 -0
  142. ffbb_data_client/models/pratiques_multi_search_query.py +41 -0
  143. ffbb_data_client/models/pratiques_type_class.py +45 -0
  144. ffbb_data_client/models/publication_internet.py +6 -0
  145. ffbb_data_client/models/purple_logo.py +24 -0
  146. ffbb_data_client/models/query_fields_manager.py +75 -0
  147. ffbb_data_client/models/ranking_engagement.py +41 -0
  148. ffbb_data_client/models/rankings_models.py +6 -0
  149. ffbb_data_client/models/rencontres_engagement.py +23 -0
  150. ffbb_data_client/models/rencontres_facet_distribution.py +65 -0
  151. ffbb_data_client/models/rencontres_facet_stats.py +14 -0
  152. ffbb_data_client/models/rencontres_hit.py +271 -0
  153. ffbb_data_client/models/rencontres_multi_search_query.py +41 -0
  154. ffbb_data_client/models/saison.py +23 -0
  155. ffbb_data_client/models/saison_fields.py +36 -0
  156. ffbb_data_client/models/saisons_models.py +6 -0
  157. ffbb_data_client/models/saisons_query.py +9 -0
  158. ffbb_data_client/models/salle.py +56 -0
  159. ffbb_data_client/models/salles_facet_distribution.py +14 -0
  160. ffbb_data_client/models/salles_facet_stats.py +14 -0
  161. ffbb_data_client/models/salles_hit.py +153 -0
  162. ffbb_data_client/models/salles_multi_search_query.py +40 -0
  163. ffbb_data_client/models/sexe.py +9 -0
  164. ffbb_data_client/models/sexe_class.py +31 -0
  165. ffbb_data_client/models/source.py +5 -0
  166. ffbb_data_client/models/status.py +5 -0
  167. ffbb_data_client/models/team_engagement.py +56 -0
  168. ffbb_data_client/models/team_ranking.py +108 -0
  169. ffbb_data_client/models/terrains_categorie_championnat_3x3_libelle.py +5 -0
  170. ffbb_data_client/models/terrains_facet_distribution.py +41 -0
  171. ffbb_data_client/models/terrains_facet_stats.py +14 -0
  172. ffbb_data_client/models/terrains_hit.py +223 -0
  173. ffbb_data_client/models/terrains_multi_search_query.py +42 -0
  174. ffbb_data_client/models/terrains_name.py +5 -0
  175. ffbb_data_client/models/terrains_sexe_enum.py +7 -0
  176. ffbb_data_client/models/terrains_storage.py +5 -0
  177. ffbb_data_client/models/tournoi_type_class.py +35 -0
  178. ffbb_data_client/models/tournoi_type_enum.py +7 -0
  179. ffbb_data_client/models/tournoi_types_3x3.py +43 -0
  180. ffbb_data_client/models/tournoi_types_3x3_libelle.py +60 -0
  181. ffbb_data_client/models/tournoi_types_3x3_libelle_enum.py +10 -0
  182. ffbb_data_client/models/tournois_facet_distribution.py +41 -0
  183. ffbb_data_client/models/tournois_facet_stats.py +14 -0
  184. ffbb_data_client/models/tournois_hit.py +132 -0
  185. ffbb_data_client/models/tournois_hit_type.py +5 -0
  186. ffbb_data_client/models/tournois_libelle.py +7 -0
  187. ffbb_data_client/models/tournois_multi_search_query.py +40 -0
  188. ffbb_data_client/models/type_association.py +23 -0
  189. ffbb_data_client/models/type_association_libelle.py +30 -0
  190. ffbb_data_client/models/type_class.py +23 -0
  191. ffbb_data_client/models/type_competition.py +8 -0
  192. ffbb_data_client/models/type_competition_generique.py +31 -0
  193. ffbb_data_client/models/type_enum.py +7 -0
  194. ffbb_data_client/models/type_league.py +6 -0
  195. ffbb_data_client/py.typed +0 -0
  196. ffbb_data_client/utils/__init__.py +27 -0
  197. ffbb_data_client/utils/cache_manager.py +393 -0
  198. ffbb_data_client/utils/converter_utils.py +329 -0
  199. ffbb_data_client/utils/input_validation.py +360 -0
  200. ffbb_data_client/utils/retry_utils.py +478 -0
  201. ffbb_data_client/utils/secure_logging.py +153 -0
  202. ffbb_data_client/utils/token_manager.py +115 -0
  203. ffbb_data_client-2.0.0.dist-info/METADATA +339 -0
  204. ffbb_data_client-2.0.0.dist-info/RECORD +207 -0
  205. ffbb_data_client-2.0.0.dist-info/WHEEL +5 -0
  206. ffbb_data_client-2.0.0.dist-info/licenses/LICENSE.txt +201 -0
  207. ffbb_data_client-2.0.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,77 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Iterable
4
+ from dataclasses import dataclass, field
5
+
6
+ from .contact_info import ContactInfo
7
+ from .get_organisme_response import GetOrganismeResponse
8
+
9
+
10
+ def _normalize_phone(raw: str | None) -> str | None:
11
+ if not raw:
12
+ return None
13
+ return str(raw).strip()
14
+
15
+
16
+ def _sanitize_name(name: str | None) -> str | None:
17
+ return name.strip().title() if name else None
18
+
19
+
20
+ @dataclass
21
+ class ClubContacts:
22
+ """Contacts for a club: extracted club-level contact + members (dirigeants).
23
+
24
+ `organisme` is kept for callers who want the original source object.
25
+ """
26
+
27
+ organisme: GetOrganismeResponse
28
+ club_contact: ContactInfo | None
29
+ membres: list[ContactInfo] = field(default_factory=list)
30
+
31
+
32
+ def extract_club_info(organisme: GetOrganismeResponse) -> ContactInfo | None:
33
+ """Extract club-level contact info (phone / mail) from an organisme."""
34
+ phone = _normalize_phone(getattr(organisme, "telephone", None))
35
+ email = getattr(organisme, "mail", None) or None
36
+ if not phone and not email:
37
+ return None
38
+ return ContactInfo(
39
+ nom=getattr(organisme, "nom", None),
40
+ prenom=None,
41
+ telephone=phone,
42
+ email=email,
43
+ role="club",
44
+ )
45
+
46
+
47
+ def extract_membres_contacts(organisme: GetOrganismeResponse) -> list[ContactInfo]:
48
+ """Extract contacts from the `membres` list on an organisme.
49
+
50
+ This is defensive: it accepts multiple possible attribute names used by
51
+ different model versions (camelCase or snake_case) and falls back to
52
+ reasonable defaults.
53
+ """
54
+ contacts: list[ContactInfo] = []
55
+ membres: Iterable = getattr(organisme, "membres", []) or []
56
+ for membre in membres:
57
+ phone = _normalize_phone(
58
+ getattr(membre, "telephonePortable", None)
59
+ or getattr(membre, "telephone_portable", None)
60
+ or getattr(membre, "telephoneFixe", None)
61
+ or getattr(membre, "telephone_fixe", None)
62
+ )
63
+ email = getattr(membre, "mail", None) or None
64
+ if not phone and not email:
65
+ continue
66
+ contacts.append(
67
+ ContactInfo(
68
+ nom=_sanitize_name(getattr(membre, "nom", None)),
69
+ prenom=_sanitize_name(getattr(membre, "prenom", None)),
70
+ telephone=phone,
71
+ email=email,
72
+ role=getattr(membre, "codeFonction", None)
73
+ or getattr(membre, "code_fonction", None)
74
+ or "membre",
75
+ )
76
+ )
77
+ return contacts
@@ -0,0 +1,7 @@
1
+ from enum import Enum
2
+
3
+
4
+ class Code(Enum):
5
+ BIT = "BIT"
6
+ BT = "BT"
7
+ SS = "SS"
@@ -0,0 +1,66 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass, field
4
+ from datetime import datetime
5
+ from typing import Any
6
+
7
+ from ..utils.converter_utils import (
8
+ from_datetime,
9
+ from_int,
10
+ from_str,
11
+ )
12
+
13
+
14
+ @dataclass
15
+ class Commune:
16
+ code_insee: str | None = None
17
+ code_postal: str | None = None
18
+ date_created: datetime | None = None
19
+ date_updated: datetime | None = None
20
+ commune_id: str | None = None
21
+ libelle: str | None = None
22
+ departement: str | None = None
23
+ lower_libelle: str | None = field(init=False, default=None, repr=False)
24
+ lower_departement: str | None = field(init=False, default=None, repr=False)
25
+
26
+ def __post_init__(self) -> None:
27
+ self.lower_libelle = self.libelle.lower() if self.libelle else None
28
+ self.lower_departement = self.departement.lower() if self.departement else None
29
+
30
+ @staticmethod
31
+ def from_dict(obj: Any) -> Commune:
32
+ assert isinstance(obj, dict)
33
+ code_insee = from_str(obj, "codeInsee")
34
+ code_postal = from_str(obj, "codePostal")
35
+ date_created = from_datetime(obj, "date_created")
36
+ date_updated = from_datetime(obj, "date_updated")
37
+ commune_id = from_int(obj, "id")
38
+ libelle = from_str(obj, "libelle")
39
+ departement = from_str(obj, "departement")
40
+ return Commune(
41
+ code_insee=code_insee,
42
+ code_postal=code_postal,
43
+ date_created=date_created,
44
+ date_updated=date_updated,
45
+ commune_id=commune_id,
46
+ libelle=libelle,
47
+ departement=departement,
48
+ )
49
+
50
+ def to_dict(self) -> dict:
51
+ result: dict = {}
52
+ if self.code_insee is not None:
53
+ result["codeInsee"] = self.code_insee
54
+ if self.code_postal is not None:
55
+ result["codePostal"] = self.code_postal
56
+ if self.date_created is not None:
57
+ result["date_created"] = self.date_created.isoformat()
58
+ if self.date_updated is not None:
59
+ result["date_updated"] = self.date_updated.isoformat()
60
+ if self.commune_id is not None:
61
+ result["id"] = str(self.commune_id)
62
+ if self.libelle is not None:
63
+ result["libelle"] = self.libelle
64
+ if self.departement is not None:
65
+ result["departement"] = self.departement
66
+ return result
@@ -0,0 +1,309 @@
1
+ class CompetitionFields:
2
+ """Default fields for competition queries."""
3
+
4
+ # Basic fields
5
+ ID = "id"
6
+ NOM = "nom"
7
+ SEXE = "sexe"
8
+ SAISON = "saison"
9
+ CODE = "code"
10
+ TYPE_COMPETITION = "typeCompetition"
11
+ LIVE_STAT = "liveStat"
12
+ COMPETITION_ORIGINE = "competition_origine"
13
+ COMPETITION_ORIGINE_NOM = "competition_origine_nom"
14
+
15
+ # Categorie fields
16
+ CATEGORIE_CODE = "categorie.code"
17
+ CATEGORIE_ORDRE = "categorie.ordre"
18
+
19
+ # Logo fields
20
+ LOGO_ID = "logo.id"
21
+ LOGO_GRADIENT_COLOR = "logo.gradient_color"
22
+ TYPE_COMPETITION_GENERIQUE_LOGO_ID = "typeCompetitionGenerique.logo.id"
23
+ TYPE_COMPETITION_GENERIQUE_LOGO_GRADIENT_COLOR = (
24
+ "typeCompetitionGenerique.logo.gradient_color"
25
+ )
26
+
27
+ # Other fields
28
+ PUBLICATION_INTERNET = "publicationInternet"
29
+ POULES_ID = "poules.id"
30
+ POULES_NOM = "poules.nom"
31
+
32
+ # Phases fields (additional)
33
+ PHASES_LIVE_STAT = "phases.liveStat"
34
+ PHASES_PHASE_CODE = "phases.phase_code"
35
+
36
+ # Additional rencontres fields
37
+ PHASES_POULES_RENCONTRES_NUMERO_JOURNEE = "phases.poules.rencontres.numeroJournee"
38
+ PHASES_POULES_RENCONTRES_ID_POULE = "phases.poules.rencontres.idPoule"
39
+ PHASES_POULES_RENCONTRES_COMPETITION_ID = "phases.poules.rencontres.competitionId"
40
+ PHASES_POULES_RENCONTRES_RESULTAT_EQUIPE1 = (
41
+ "phases.poules.rencontres.resultatEquipe1"
42
+ )
43
+ PHASES_POULES_RENCONTRES_RESULTAT_EQUIPE2 = (
44
+ "phases.poules.rencontres.resultatEquipe2"
45
+ )
46
+ PHASES_POULES_RENCONTRES_JOUE = "phases.poules.rencontres.joue"
47
+ PHASES_POULES_RENCONTRES_NOM_EQUIPE1 = "phases.poules.rencontres.nomEquipe1"
48
+ PHASES_POULES_RENCONTRES_NOM_EQUIPE2 = "phases.poules.rencontres.nomEquipe2"
49
+
50
+ # Engagements fields
51
+ PHASES_POULES_ENGAGEMENTS_ID = "phases.poules.engagements.id"
52
+ PHASES_POULES_ENGAGEMENTS_ID_ORGANISME_ID = (
53
+ "phases.poules.engagements.idOrganisme.id"
54
+ )
55
+
56
+ # Phases fields
57
+ PHASES_ID = "phases.id"
58
+ PHASES_NOM = "phases.nom"
59
+
60
+ # Poules fields (nested in phases)
61
+ PHASES_POULES_ID = "phases.poules.id"
62
+ PHASES_POULES_NOM = "phases.poules.nom"
63
+
64
+ # Rencontres fields (nested in poules)
65
+ PHASES_POULES_RENCONTRES_ID = "phases.poules.rencontres.id"
66
+ PHASES_POULES_RENCONTRES_NUMERO = "phases.poules.rencontres.numero"
67
+ PHASES_POULES_RENCONTRES_DATE = "phases.poules.rencontres.date_rencontre"
68
+
69
+ # GameStats fields (nested in rencontres)
70
+ PHASES_POULES_RENCONTRES_GSID_MATCH_ID = "phases.poules.rencontres.gsId.matchId"
71
+ PHASES_POULES_RENCONTRES_GSID_CURRENT_STATUS = (
72
+ "phases.poules.rencontres.gsId.currentStatus"
73
+ )
74
+ PHASES_POULES_RENCONTRES_GSID_CURRENT_PERIOD = (
75
+ "phases.poules.rencontres.gsId.currentPeriod"
76
+ )
77
+ PHASES_POULES_RENCONTRES_GSID_SCORE_Q1_HOME = (
78
+ "phases.poules.rencontres.gsId.score_q1_home"
79
+ )
80
+ PHASES_POULES_RENCONTRES_GSID_SCORE_Q2_HOME = (
81
+ "phases.poules.rencontres.gsId.score_q2_home"
82
+ )
83
+ PHASES_POULES_RENCONTRES_GSID_SCORE_Q3_HOME = (
84
+ "phases.poules.rencontres.gsId.score_q3_home"
85
+ )
86
+ PHASES_POULES_RENCONTRES_GSID_SCORE_Q4_HOME = (
87
+ "phases.poules.rencontres.gsId.score_q4_home"
88
+ )
89
+ PHASES_POULES_RENCONTRES_GSID_SCORE_OT1_HOME = (
90
+ "phases.poules.rencontres.gsId.score_ot1_home"
91
+ )
92
+ PHASES_POULES_RENCONTRES_GSID_SCORE_OT2_HOME = (
93
+ "phases.poules.rencontres.gsId.score_ot2_home"
94
+ )
95
+ PHASES_POULES_RENCONTRES_GSID_SCORE_Q1_OUT = (
96
+ "phases.poules.rencontres.gsId.score_q1_out"
97
+ )
98
+ PHASES_POULES_RENCONTRES_GSID_SCORE_Q2_OUT = (
99
+ "phases.poules.rencontres.gsId.score_q2_out"
100
+ )
101
+ PHASES_POULES_RENCONTRES_GSID_SCORE_Q3_OUT = (
102
+ "phases.poules.rencontres.gsId.score_q3_out"
103
+ )
104
+ PHASES_POULES_RENCONTRES_GSID_SCORE_Q4_OUT = (
105
+ "phases.poules.rencontres.gsId.score_q4_out"
106
+ )
107
+ PHASES_POULES_RENCONTRES_GSID_SCORE_OT1_OUT = (
108
+ "phases.poules.rencontres.gsId.score_ot1_out"
109
+ )
110
+ PHASES_POULES_RENCONTRES_GSID_SCORE_OT2_OUT = (
111
+ "phases.poules.rencontres.gsId.score_ot2_out"
112
+ )
113
+
114
+ # Officiels fields (nested in rencontres)
115
+ PHASES_POULES_RENCONTRES_OFFICIELS_ORDRE = (
116
+ "phases.poules.rencontres.officiels.ordre"
117
+ )
118
+ PHASES_POULES_RENCONTRES_OFFICIELS_FONCTION_LIBELLE = (
119
+ "phases.poules.rencontres.officiels.fonction.libelle"
120
+ )
121
+ PHASES_POULES_RENCONTRES_OFFICIELS_OFFICIEL_NOM = (
122
+ "phases.poules.rencontres.officiels.officiel.nom"
123
+ )
124
+ PHASES_POULES_RENCONTRES_OFFICIELS_OFFICIEL_PRENOM = (
125
+ "phases.poules.rencontres.officiels.officiel.prenom"
126
+ )
127
+
128
+ # idOrganismeEquipe logo fields
129
+ PHASES_POULES_RENCONTRES_ID_ORGANISME_EQUIPE1_LOGO_ID = (
130
+ "phases.poules.rencontres.idOrganismeEquipe1.logo.id"
131
+ )
132
+ PHASES_POULES_RENCONTRES_ID_ORGANISME_EQUIPE2_LOGO_ID = (
133
+ "phases.poules.rencontres.idOrganismeEquipe2.logo.id"
134
+ )
135
+
136
+ # idEngagementEquipe1 fields (model: Idengagementequipe1Model)
137
+ PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE1_ID = (
138
+ "phases.poules.rencontres.idEngagementEquipe1.id"
139
+ )
140
+ PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE1_NOM = (
141
+ "phases.poules.rencontres.idEngagementEquipe1.nom"
142
+ )
143
+ PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE1_NOM_OFFICIEL = (
144
+ "phases.poules.rencontres.idEngagementEquipe1.nomOfficiel"
145
+ )
146
+ PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE1_NOM_USUEL = (
147
+ "phases.poules.rencontres.idEngagementEquipe1.nomUsuel"
148
+ )
149
+ PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE1_CODE_ABREGE = (
150
+ "phases.poules.rencontres.idEngagementEquipe1.codeAbrege"
151
+ )
152
+ PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE1_LOGO = (
153
+ "phases.poules.rencontres.idEngagementEquipe1.logo"
154
+ )
155
+
156
+ # idEngagementEquipe2 fields (model: Idengagementequipe2Model)
157
+ PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE2_ID = (
158
+ "phases.poules.rencontres.idEngagementEquipe2.id"
159
+ )
160
+ PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE2_NOM = (
161
+ "phases.poules.rencontres.idEngagementEquipe2.nom"
162
+ )
163
+ PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE2_NOM_OFFICIEL = (
164
+ "phases.poules.rencontres.idEngagementEquipe2.nomOfficiel"
165
+ )
166
+ PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE2_NOM_USUEL = (
167
+ "phases.poules.rencontres.idEngagementEquipe2.nomUsuel"
168
+ )
169
+ PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE2_CODE_ABREGE = (
170
+ "phases.poules.rencontres.idEngagementEquipe2.codeAbrege"
171
+ )
172
+ PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE2_LOGO = (
173
+ "phases.poules.rencontres.idEngagementEquipe2.logo"
174
+ )
175
+
176
+ # Salle in rencontres (model: SalleModel)
177
+ PHASES_POULES_RENCONTRES_SALLE_ID = "phases.poules.rencontres.salle.id"
178
+ PHASES_POULES_RENCONTRES_SALLE_NUMERO = "phases.poules.rencontres.salle.numero"
179
+ PHASES_POULES_RENCONTRES_SALLE_LIBELLE = "phases.poules.rencontres.salle.libelle"
180
+ PHASES_POULES_RENCONTRES_SALLE_LIBELLE2 = "phases.poules.rencontres.salle.libelle2"
181
+ PHASES_POULES_RENCONTRES_SALLE_ADRESSE = "phases.poules.rencontres.salle.adresse"
182
+ PHASES_POULES_RENCONTRES_SALLE_ADRESSE_COMPLEMENT = (
183
+ "phases.poules.rencontres.salle.adresseComplement"
184
+ )
185
+ PHASES_POULES_RENCONTRES_SALLE_COMMUNE_CP = (
186
+ "phases.poules.rencontres.salle.commune.codePostal"
187
+ )
188
+ PHASES_POULES_RENCONTRES_SALLE_COMMUNE_LIBELLE = (
189
+ "phases.poules.rencontres.salle.commune.libelle"
190
+ )
191
+ PHASES_POULES_RENCONTRES_SALLE_CARTO_LAT = (
192
+ "phases.poules.rencontres.salle.cartographie.latitude"
193
+ )
194
+ PHASES_POULES_RENCONTRES_SALLE_CARTO_LNG = (
195
+ "phases.poules.rencontres.salle.cartographie.longitude"
196
+ )
197
+
198
+ @classmethod
199
+ def get_default_fields(cls) -> list[str]:
200
+ """Get default fields for competition queries based on real API usage."""
201
+ return [
202
+ # Basic competition fields
203
+ cls.ID,
204
+ cls.NOM,
205
+ cls.SEXE,
206
+ cls.CATEGORIE_CODE,
207
+ cls.CATEGORIE_ORDRE,
208
+ cls.SAISON,
209
+ cls.CODE,
210
+ cls.TYPE_COMPETITION,
211
+ cls.LIVE_STAT,
212
+ cls.COMPETITION_ORIGINE,
213
+ cls.COMPETITION_ORIGINE_NOM,
214
+ cls.TYPE_COMPETITION_GENERIQUE_LOGO_ID,
215
+ cls.TYPE_COMPETITION_GENERIQUE_LOGO_GRADIENT_COLOR,
216
+ cls.LOGO_ID,
217
+ cls.LOGO_GRADIENT_COLOR,
218
+ cls.POULES_ID,
219
+ cls.POULES_NOM,
220
+ cls.PUBLICATION_INTERNET,
221
+ # Phases fields
222
+ cls.PHASES_ID,
223
+ cls.PHASES_NOM,
224
+ cls.PHASES_LIVE_STAT,
225
+ cls.PHASES_PHASE_CODE,
226
+ # Phases > Poules fields
227
+ cls.PHASES_POULES_ID,
228
+ cls.PHASES_POULES_NOM,
229
+ # Phases > Poules > Rencontres essential fields
230
+ cls.PHASES_POULES_RENCONTRES_ID,
231
+ cls.PHASES_POULES_RENCONTRES_NUMERO,
232
+ cls.PHASES_POULES_RENCONTRES_NUMERO_JOURNEE,
233
+ cls.PHASES_POULES_RENCONTRES_ID_POULE,
234
+ cls.PHASES_POULES_RENCONTRES_COMPETITION_ID,
235
+ cls.PHASES_POULES_RENCONTRES_RESULTAT_EQUIPE1,
236
+ cls.PHASES_POULES_RENCONTRES_RESULTAT_EQUIPE2,
237
+ cls.PHASES_POULES_RENCONTRES_JOUE,
238
+ cls.PHASES_POULES_RENCONTRES_NOM_EQUIPE1,
239
+ cls.PHASES_POULES_RENCONTRES_NOM_EQUIPE2,
240
+ cls.PHASES_POULES_RENCONTRES_DATE,
241
+ # Phases > Poules > Engagements
242
+ cls.PHASES_POULES_ENGAGEMENTS_ID,
243
+ cls.PHASES_POULES_ENGAGEMENTS_ID_ORGANISME_ID,
244
+ # idOrganismeEquipe logo
245
+ cls.PHASES_POULES_RENCONTRES_ID_ORGANISME_EQUIPE1_LOGO_ID,
246
+ cls.PHASES_POULES_RENCONTRES_ID_ORGANISME_EQUIPE2_LOGO_ID,
247
+ # idEngagementEquipe1
248
+ cls.PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE1_ID,
249
+ cls.PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE1_NOM,
250
+ cls.PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE1_NOM_OFFICIEL,
251
+ cls.PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE1_NOM_USUEL,
252
+ cls.PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE1_CODE_ABREGE,
253
+ cls.PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE1_LOGO,
254
+ # idEngagementEquipe2
255
+ cls.PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE2_ID,
256
+ cls.PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE2_NOM,
257
+ cls.PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE2_NOM_OFFICIEL,
258
+ cls.PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE2_NOM_USUEL,
259
+ cls.PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE2_CODE_ABREGE,
260
+ cls.PHASES_POULES_RENCONTRES_ID_ENGAGEMENT_EQUIPE2_LOGO,
261
+ # Salle in rencontres
262
+ cls.PHASES_POULES_RENCONTRES_SALLE_ID,
263
+ cls.PHASES_POULES_RENCONTRES_SALLE_NUMERO,
264
+ cls.PHASES_POULES_RENCONTRES_SALLE_LIBELLE,
265
+ cls.PHASES_POULES_RENCONTRES_SALLE_LIBELLE2,
266
+ cls.PHASES_POULES_RENCONTRES_SALLE_ADRESSE,
267
+ cls.PHASES_POULES_RENCONTRES_SALLE_ADRESSE_COMPLEMENT,
268
+ cls.PHASES_POULES_RENCONTRES_SALLE_COMMUNE_CP,
269
+ cls.PHASES_POULES_RENCONTRES_SALLE_COMMUNE_LIBELLE,
270
+ cls.PHASES_POULES_RENCONTRES_SALLE_CARTO_LAT,
271
+ cls.PHASES_POULES_RENCONTRES_SALLE_CARTO_LNG,
272
+ # GameStats fields for live match data
273
+ cls.PHASES_POULES_RENCONTRES_GSID_MATCH_ID,
274
+ cls.PHASES_POULES_RENCONTRES_GSID_CURRENT_STATUS,
275
+ cls.PHASES_POULES_RENCONTRES_GSID_CURRENT_PERIOD,
276
+ cls.PHASES_POULES_RENCONTRES_GSID_SCORE_Q1_HOME,
277
+ cls.PHASES_POULES_RENCONTRES_GSID_SCORE_Q2_HOME,
278
+ cls.PHASES_POULES_RENCONTRES_GSID_SCORE_Q3_HOME,
279
+ cls.PHASES_POULES_RENCONTRES_GSID_SCORE_Q4_HOME,
280
+ cls.PHASES_POULES_RENCONTRES_GSID_SCORE_OT1_HOME,
281
+ cls.PHASES_POULES_RENCONTRES_GSID_SCORE_OT2_HOME,
282
+ cls.PHASES_POULES_RENCONTRES_GSID_SCORE_Q1_OUT,
283
+ cls.PHASES_POULES_RENCONTRES_GSID_SCORE_Q2_OUT,
284
+ cls.PHASES_POULES_RENCONTRES_GSID_SCORE_Q3_OUT,
285
+ cls.PHASES_POULES_RENCONTRES_GSID_SCORE_Q4_OUT,
286
+ cls.PHASES_POULES_RENCONTRES_GSID_SCORE_OT1_OUT,
287
+ cls.PHASES_POULES_RENCONTRES_GSID_SCORE_OT2_OUT,
288
+ # Officiels fields
289
+ cls.PHASES_POULES_RENCONTRES_OFFICIELS_ORDRE,
290
+ cls.PHASES_POULES_RENCONTRES_OFFICIELS_FONCTION_LIBELLE,
291
+ cls.PHASES_POULES_RENCONTRES_OFFICIELS_OFFICIEL_NOM,
292
+ cls.PHASES_POULES_RENCONTRES_OFFICIELS_OFFICIEL_PRENOM,
293
+ ]
294
+
295
+ @classmethod
296
+ def get_basic_fields(cls) -> list[str]:
297
+ """Get basic fields for simple competition queries."""
298
+ return [
299
+ cls.ID,
300
+ cls.NOM,
301
+ cls.SEXE,
302
+ cls.SAISON,
303
+ cls.CODE,
304
+ ]
305
+
306
+ @classmethod
307
+ def get_detailed_fields(cls) -> list[str]:
308
+ """Get detailed fields (all fields now included in default)."""
309
+ return cls.get_default_fields()
@@ -0,0 +1,116 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Any
5
+
6
+ from ..utils.converter_utils import (
7
+ from_bool,
8
+ from_obj,
9
+ from_str,
10
+ )
11
+ from .competition_id_categorie import CompetitionIDCategorie
12
+ from .competition_id_type_competition_generique import (
13
+ CompetitionIDTypeCompetitionGenerique,
14
+ )
15
+ from .competition_origine import CompetitionOrigine
16
+ from .logo import Logo
17
+
18
+
19
+ @dataclass
20
+ class CompetitionID:
21
+ id: str | None = None
22
+ nom: str | None = None
23
+ competition_origine_nom: str | None = None
24
+ code: str | None = None
25
+ creation_en_cours: bool | None = None
26
+ live_stat: bool | None = None
27
+ publication_internet: str | None = None
28
+ sexe: str | None = None
29
+ type_competition: str | None = None
30
+ pro: bool | None = None
31
+ logo: Logo | None = None
32
+ categorie: CompetitionIDCategorie | None = None
33
+ type_competition_generique: CompetitionIDTypeCompetitionGenerique | None = None
34
+ competition_origine: CompetitionOrigine | None = None
35
+ nom_extended: str | None = None
36
+
37
+ @staticmethod
38
+ def from_dict(obj: Any) -> CompetitionID:
39
+ try:
40
+ assert isinstance(obj, dict)
41
+ id = from_str(obj, "id")
42
+ nom = from_str(obj, "nom")
43
+ competition_origine_nom = from_str(obj, "competition_origine_nom")
44
+ code = from_str(obj, "code")
45
+ creation_en_cours = from_bool(obj, "creationEnCours")
46
+ live_stat = from_bool(obj, "liveStat")
47
+ publication_internet = from_str(obj, "publicationInternet")
48
+ sexe = from_str(obj, "sexe")
49
+ type_competition = from_str(obj, "typeCompetition")
50
+ pro = from_bool(obj, "pro")
51
+ logo = from_obj(Logo.from_dict, obj, "logo")
52
+ categorie = from_obj(CompetitionIDCategorie.from_dict, obj, "categorie")
53
+ type_competition_generique = from_obj(
54
+ CompetitionIDTypeCompetitionGenerique.from_dict,
55
+ obj,
56
+ "typeCompetitionGenerique",
57
+ )
58
+ competition_origine = from_obj(
59
+ CompetitionOrigine.from_dict, obj, "competition_origine"
60
+ )
61
+ nom_extended = from_str(obj, "nomExtended")
62
+ return CompetitionID(
63
+ id=id,
64
+ nom=nom,
65
+ competition_origine_nom=competition_origine_nom,
66
+ code=code,
67
+ creation_en_cours=creation_en_cours,
68
+ live_stat=live_stat,
69
+ publication_internet=publication_internet,
70
+ sexe=sexe,
71
+ type_competition=type_competition,
72
+ pro=pro,
73
+ logo=logo,
74
+ categorie=categorie,
75
+ type_competition_generique=type_competition_generique,
76
+ competition_origine=competition_origine,
77
+ nom_extended=nom_extended,
78
+ )
79
+ except Exception as e:
80
+ raise ValueError("Invalid CompetitionID object") from e
81
+
82
+ def to_dict(self) -> dict:
83
+ result: dict = {}
84
+ if self.id is not None:
85
+ result["id"] = self.id
86
+ if self.nom is not None:
87
+ result["nom"] = self.nom
88
+ if self.competition_origine_nom is not None:
89
+ result["competition_origine_nom"] = self.competition_origine_nom
90
+ if self.code is not None:
91
+ result["code"] = self.code
92
+ if self.creation_en_cours is not None:
93
+ result["creationEnCours"] = self.creation_en_cours
94
+ if self.live_stat is not None:
95
+ result["liveStat"] = self.live_stat
96
+ if self.publication_internet is not None:
97
+ result["publicationInternet"] = self.publication_internet
98
+ if self.sexe is not None:
99
+ result["sexe"] = self.sexe
100
+ if self.type_competition is not None:
101
+ result["typeCompetition"] = self.type_competition
102
+ if self.pro is not None:
103
+ result["pro"] = self.pro
104
+ if self.logo is not None:
105
+ result["logo"] = self.logo.to_dict()
106
+ if self.categorie is not None:
107
+ result["categorie"] = self.categorie.to_dict()
108
+ if self.type_competition_generique is not None:
109
+ result["typeCompetitionGenerique"] = (
110
+ self.type_competition_generique.to_dict()
111
+ )
112
+ if self.competition_origine is not None:
113
+ result["competition_origine"] = self.competition_origine.to_dict()
114
+ if self.nom_extended is not None:
115
+ result["nomExtended"] = self.nom_extended
116
+ return result
@@ -0,0 +1,31 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Any
5
+
6
+ from ..utils.converter_utils import from_int, from_str
7
+
8
+
9
+ @dataclass
10
+ class CompetitionIDCategorie:
11
+ code: str | None = None
12
+ libelle: str | None = None
13
+ ordre: int | None = None
14
+
15
+ @staticmethod
16
+ def from_dict(obj: Any) -> CompetitionIDCategorie:
17
+ assert isinstance(obj, dict)
18
+ code = from_str(obj, "code")
19
+ libelle = from_str(obj, "libelle")
20
+ ordre = from_int(obj, "ordre")
21
+ return CompetitionIDCategorie(code=code, libelle=libelle, ordre=ordre)
22
+
23
+ def to_dict(self) -> dict:
24
+ result: dict = {}
25
+ if self.code is not None:
26
+ result["code"] = self.code
27
+ if self.libelle is not None:
28
+ result["libelle"] = self.libelle
29
+ if self.ordre is not None:
30
+ result["ordre"] = self.ordre
31
+ return result
@@ -0,0 +1,31 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Any
5
+
6
+ from ..utils.converter_utils import from_int
7
+
8
+
9
+ @dataclass
10
+ class CompetitionIDSexe:
11
+ feminine: int | None = None
12
+ masculine: int | None = None
13
+ mixed: int | None = None
14
+
15
+ @staticmethod
16
+ def from_dict(obj: Any) -> CompetitionIDSexe:
17
+ assert isinstance(obj, dict)
18
+ feminine = from_int(obj, "Féminin")
19
+ masculine = from_int(obj, "Masculin")
20
+ mixed = from_int(obj, "Mixte")
21
+ return CompetitionIDSexe(feminine=feminine, masculine=masculine, mixed=mixed)
22
+
23
+ def to_dict(self) -> dict:
24
+ result: dict = {}
25
+ if self.feminine is not None:
26
+ result["Féminin"] = self.feminine
27
+ if self.masculine is not None:
28
+ result["Masculin"] = self.masculine
29
+ if self.mixed is not None:
30
+ result["Mixte"] = self.mixed
31
+ return result
@@ -0,0 +1,27 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Any
5
+
6
+ from ..utils.converter_utils import from_int
7
+
8
+
9
+ @dataclass
10
+ class CompetitionIDTypeCompetition:
11
+ championnat: int | None = None
12
+ coupe: int | None = None
13
+
14
+ @staticmethod
15
+ def from_dict(obj: Any) -> CompetitionIDTypeCompetition:
16
+ assert isinstance(obj, dict)
17
+ championnat = from_int(obj, "Championnat")
18
+ coupe = from_int(obj, "Coupe")
19
+ return CompetitionIDTypeCompetition(championnat=championnat, coupe=coupe)
20
+
21
+ def to_dict(self) -> dict:
22
+ result: dict = {}
23
+ if self.championnat is not None:
24
+ result["Championnat"] = self.championnat
25
+ if self.coupe is not None:
26
+ result["Coupe"] = self.coupe
27
+ return result