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,45 @@
1
+ """Configuration models for FFBB API."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+
7
+
8
+ @dataclass
9
+ class GetConfigurationResponse:
10
+ """Response model for /items/configuration endpoint."""
11
+
12
+ id: int
13
+ key_dh: str
14
+ key_ms: str
15
+ key_directus_website: str | None = None
16
+ key_directus_competitions: str | None = None
17
+ ios_version: str | None = None
18
+ android_version: str | None = None
19
+ date_created: str | None = None
20
+ date_updated: str | None = None
21
+
22
+ @classmethod
23
+ def from_dict(cls, data: dict) -> GetConfigurationResponse:
24
+ """Create a GetConfigurationResponse from a dictionary."""
25
+ return cls(
26
+ id=data.get("id", 0),
27
+ key_dh=data.get("key_dh", ""),
28
+ key_ms=data.get("key_ms", ""),
29
+ key_directus_website=data.get("key_directus_website"),
30
+ key_directus_competitions=data.get("key_directus_competitions"),
31
+ ios_version=data.get("ios_version"),
32
+ android_version=data.get("android_version"),
33
+ date_created=data.get("date_created"),
34
+ date_updated=data.get("date_updated"),
35
+ )
36
+
37
+ @property
38
+ def api_bearer_token(self) -> str:
39
+ """Alias for key_dh - the API bearer token."""
40
+ return self.key_dh
41
+
42
+ @property
43
+ def meilisearch_token(self) -> str:
44
+ """Alias for key_ms - the Meilisearch token."""
45
+ return self.key_ms
@@ -0,0 +1,23 @@
1
+ from dataclasses import dataclass
2
+ from typing import Any
3
+
4
+
5
+ @dataclass
6
+ class GetEngagementResponse:
7
+ id: str
8
+ numeroEquipe: str | None = None
9
+ idPoule: Any | None = None
10
+ idCompetition: Any | None = None
11
+ idOrganisme: Any | None = None
12
+
13
+ @classmethod
14
+ def from_dict(cls, data: dict) -> "GetEngagementResponse | None":
15
+ if not data or not isinstance(data, dict):
16
+ return None
17
+ return cls(
18
+ id=str(data.get("id", "")),
19
+ numeroEquipe=data.get("numeroEquipe"),
20
+ idPoule=data.get("idPoule"),
21
+ idCompetition=data.get("idCompetition"),
22
+ idOrganisme=data.get("idOrganisme"),
23
+ )
@@ -0,0 +1,18 @@
1
+ from dataclasses import dataclass
2
+
3
+
4
+ @dataclass
5
+ class GetEntraineurResponse:
6
+ id: str
7
+ nom: str | None = None
8
+ prenom: str | None = None
9
+
10
+ @classmethod
11
+ def from_dict(cls, data: dict) -> "GetEntraineurResponse | None":
12
+ if not data or not isinstance(data, dict):
13
+ return None
14
+ return cls(
15
+ id=str(data.get("id", "")),
16
+ nom=data.get("nom"),
17
+ prenom=data.get("prenom"),
18
+ )
@@ -0,0 +1,28 @@
1
+ from dataclasses import dataclass
2
+
3
+
4
+ @dataclass
5
+ class GetFormationResponse:
6
+ id: str
7
+ theme: str | None = None
8
+ type: str | None = None
9
+ domain: str | None = None
10
+ mode: str | None = None
11
+ place: str | None = None
12
+ date_start: str | None = None
13
+ date_end: str | None = None
14
+
15
+ @classmethod
16
+ def from_dict(cls, data: dict) -> "GetFormationResponse | None":
17
+ if not data or not isinstance(data, dict):
18
+ return None
19
+ return cls(
20
+ id=str(data.get("id", "")),
21
+ theme=data.get("theme"),
22
+ type=data.get("type"),
23
+ domain=data.get("domain"),
24
+ mode=data.get("mode"),
25
+ place=data.get("place"),
26
+ date_start=data.get("date_start"),
27
+ date_end=data.get("date_end"),
28
+ )
@@ -0,0 +1,18 @@
1
+ from dataclasses import dataclass
2
+
3
+
4
+ @dataclass
5
+ class GetOfficielResponse:
6
+ id: str
7
+ nom: str | None = None
8
+ prenom: str | None = None
9
+
10
+ @classmethod
11
+ def from_dict(cls, data: dict) -> "GetOfficielResponse | None":
12
+ if not data or not isinstance(data, dict):
13
+ return None
14
+ return cls(
15
+ id=str(data.get("id", "")),
16
+ nom=data.get("nom"),
17
+ prenom=data.get("prenom"),
18
+ )
@@ -0,0 +1,476 @@
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 .niveau_models import NiveauInfo, get_niveau_from_idcompetition
8
+
9
+
10
+ @dataclass
11
+ class GetOrganismeResponse:
12
+ id: str
13
+ nom: str
14
+ code: str
15
+ telephone: str
16
+ adresse: str
17
+ mail: str
18
+ type: str = ""
19
+ nom_simple: Any | None = None
20
+ urlSiteWeb: str = ""
21
+ nomClubPro: str = ""
22
+ adresseClubPro: Any | None = None
23
+
24
+ @dataclass
25
+ class CommuneModel:
26
+ codePostal: str
27
+ libelle: str
28
+
29
+ commune: CommuneModel | None = None
30
+
31
+ @dataclass
32
+ class CartographieModel:
33
+ latitude: float
34
+ longitude: float
35
+
36
+ cartographie: CartographieModel | None = None
37
+ communeClubPro: Any | None = None
38
+
39
+ @dataclass
40
+ class MembresitemModel:
41
+ id: str
42
+ nom: str
43
+ prenom: str
44
+ adresse1: str
45
+ adresse2: Any | None = None
46
+ codePostal: str = ""
47
+ ville: str = ""
48
+ mail: str = ""
49
+ telephoneFixe: Any | None = None
50
+ telephonePortable: str = ""
51
+ codeFonction: str = ""
52
+
53
+ membres: list[MembresitemModel] = field(default_factory=list)
54
+ competitions: list[Any] = field(default_factory=list)
55
+
56
+ @dataclass
57
+ class EngagementsitemModel:
58
+ id: str
59
+ numeroEquipe: str | None = None
60
+
61
+ @property
62
+ def poule_id(self) -> str | None:
63
+ """Convenience property to access nested poule ID."""
64
+ return self.idPoule.id if self.idPoule else None
65
+
66
+ @property
67
+ def competition_nom(self) -> str | None:
68
+ """Convenience property to access nested competition name."""
69
+ return self.idCompetition.nom if self.idCompetition else None
70
+
71
+ @property
72
+ def numero_equipe(self) -> str | None:
73
+ """Convenience alias for .numeroEquipe."""
74
+ return self.numeroEquipe
75
+
76
+ @dataclass
77
+ class IdpouleModel:
78
+ id: str
79
+
80
+ idPoule: IdpouleModel | None = None
81
+
82
+ @dataclass
83
+ class IdcompetitionModel:
84
+ id: str
85
+ nom: str
86
+ code: str
87
+ sexe: str
88
+ competition_origine: str
89
+ competition_origine_nom: str
90
+ competition_origine_niveau: int
91
+ typeCompetition: str
92
+ logo: Any | None = None
93
+
94
+ @dataclass
95
+ class SaisonModel:
96
+ id: str
97
+
98
+ saison: SaisonModel | None = None
99
+ idCompetitionPere: Any | None = None
100
+
101
+ @dataclass
102
+ class OrganisateurModel:
103
+ type: str
104
+
105
+ organisateur: OrganisateurModel | None = None
106
+
107
+ @dataclass
108
+ class TypecompetitiongeneriqueModel:
109
+
110
+ @dataclass
111
+ class LogoModel:
112
+ id: str
113
+ gradient_color: str
114
+
115
+ logo: LogoModel | None = None
116
+
117
+ typeCompetitionGenerique: TypecompetitiongeneriqueModel | None = None
118
+
119
+ @dataclass
120
+ class CategorieModel:
121
+ code: str
122
+ ordre: int
123
+
124
+ categorie: CategorieModel | None = None
125
+
126
+ @property
127
+ def niveau(self) -> NiveauInfo | None:
128
+ """Extrait automatiquement le niveau depuis le nom de la competition."""
129
+ return get_niveau_from_idcompetition(self)
130
+
131
+ idCompetition: IdcompetitionModel | None = None
132
+
133
+ engagements: list[EngagementsitemModel] = field(default_factory=list)
134
+ organismes_fils: list[Any] = field(default_factory=list)
135
+
136
+ @dataclass
137
+ class OffrespratiquesitemModel:
138
+
139
+ @dataclass
140
+ class Ffbbserver_Offres_Pratiques_IdModel:
141
+ id: str
142
+ title: str
143
+ categoriePratique: str
144
+ typePratique: str
145
+
146
+ ffbbserver_offres_pratiques_id: Ffbbserver_Offres_Pratiques_IdModel | None = (
147
+ None
148
+ )
149
+
150
+ offresPratiques: list[OffrespratiquesitemModel] = field(default_factory=list)
151
+
152
+ @dataclass
153
+ class LabellisationitemModel:
154
+ id: str
155
+ debut: datetime
156
+ fin: datetime
157
+
158
+ @dataclass
159
+ class IdlabellisationprogrammeModel:
160
+ id: str
161
+ libelle: str
162
+ labellisationLabel: str
163
+ logo_vertical: Any | None = None
164
+
165
+ idLabellisationProgramme: IdlabellisationprogrammeModel | None = None
166
+
167
+ labellisation: list[LabellisationitemModel] = field(default_factory=list)
168
+
169
+ @dataclass
170
+ class SalleModel:
171
+ id: str
172
+ numero: str
173
+ libelle: str
174
+ libelle2: str
175
+ adresse: str
176
+ adresseComplement: str
177
+
178
+ @dataclass
179
+ class CommuneModel:
180
+ codePostal: str
181
+ libelle: str
182
+
183
+ commune: CommuneModel | None = None
184
+
185
+ @dataclass
186
+ class CartographieModel:
187
+ latitude: float
188
+ longitude: float
189
+
190
+ cartographie: CartographieModel | None = None
191
+
192
+ salle: SalleModel | None = None
193
+
194
+ @dataclass
195
+ class LogoModel:
196
+ id: str
197
+ gradient_color: str
198
+
199
+ logo: LogoModel | None = None
200
+
201
+ @classmethod
202
+ def from_dict(cls, data: dict[str, Any]) -> GetOrganismeResponse | None:
203
+ """Convert dictionary to OrganismesModel instance."""
204
+ if not data:
205
+ return None
206
+
207
+ # Handle case where data is not a dictionary
208
+ if not isinstance(data, dict):
209
+ return None
210
+
211
+ # Handle API error responses
212
+ if "errors" in data:
213
+ return None
214
+
215
+ # Extract nested commune data
216
+ commune_data = data.get("commune", {})
217
+ commune = (
218
+ cls.CommuneModel(
219
+ codePostal=commune_data.get("codePostal", ""),
220
+ libelle=commune_data.get("libelle", ""),
221
+ )
222
+ if commune_data
223
+ else None
224
+ )
225
+
226
+ # Extract nested cartographie data
227
+ cartographie_data = data.get("cartographie", {})
228
+ cartographie = (
229
+ cls.CartographieModel(
230
+ latitude=float(cartographie_data.get("latitude", 0.0)),
231
+ longitude=float(cartographie_data.get("longitude", 0.0)),
232
+ )
233
+ if cartographie_data
234
+ else None
235
+ )
236
+
237
+ # Extract membres data
238
+ membres = []
239
+ for membre_data in data.get("membres", []):
240
+ if membre_data:
241
+ membre = cls.MembresitemModel(
242
+ id=str(membre_data.get("id", "")),
243
+ nom=str(membre_data.get("nom", "")),
244
+ prenom=str(membre_data.get("prenom", "")),
245
+ adresse1=str(membre_data.get("adresse1", "")),
246
+ adresse2=membre_data.get("adresse2"),
247
+ codePostal=str(membre_data.get("codePostal", "")),
248
+ ville=str(membre_data.get("ville", "")),
249
+ mail=str(membre_data.get("mail", "")),
250
+ telephoneFixe=membre_data.get("telephoneFixe"),
251
+ telephonePortable=str(membre_data.get("telephonePortable", "")),
252
+ codeFonction=str(membre_data.get("codeFonction", "")),
253
+ )
254
+ membres.append(membre)
255
+
256
+ # Extract engagements data
257
+ engagements = []
258
+ for engagement_data in data.get("engagements", []):
259
+ if engagement_data:
260
+ # Extract idPoule
261
+ poule_data = engagement_data.get("idPoule", {})
262
+ id_poule = (
263
+ cls.EngagementsitemModel.IdpouleModel(
264
+ id=str(poule_data.get("id", ""))
265
+ )
266
+ if poule_data
267
+ else None
268
+ )
269
+
270
+ # Extract idCompetition
271
+ competition_data = engagement_data.get("idCompetition", {})
272
+ id_competition = None
273
+ if competition_data:
274
+ saison_data = competition_data.get("saison", {})
275
+ saison = (
276
+ cls.EngagementsitemModel.IdcompetitionModel.SaisonModel(
277
+ id=str(saison_data.get("id", ""))
278
+ )
279
+ if saison_data
280
+ else None
281
+ )
282
+
283
+ organisateur_data = competition_data.get("organisateur", {})
284
+ organisateur = (
285
+ cls.EngagementsitemModel.IdcompetitionModel.OrganisateurModel(
286
+ type=str(organisateur_data.get("type", ""))
287
+ )
288
+ if organisateur_data
289
+ else None
290
+ )
291
+
292
+ type_comp_generique_data = competition_data.get(
293
+ "typeCompetitionGenerique", {}
294
+ )
295
+ type_comp_generique = None
296
+ if type_comp_generique_data:
297
+ logo_data = type_comp_generique_data.get("logo", {})
298
+ # Use shorter aliases to avoid line length issues
299
+ IdComp = cls.EngagementsitemModel.IdcompetitionModel
300
+ LogoClass = IdComp.TypecompetitiongeneriqueModel.LogoModel
301
+ logo_tcg = (
302
+ LogoClass(
303
+ id=str(logo_data.get("id", "")),
304
+ gradient_color=str(logo_data.get("gradient_color", "")),
305
+ )
306
+ if logo_data
307
+ else None
308
+ )
309
+
310
+ TypeCompGenClass = IdComp.TypecompetitiongeneriqueModel
311
+ type_comp_generique = TypeCompGenClass(logo=logo_tcg)
312
+
313
+ categorie_data = competition_data.get("categorie", {})
314
+ categorie = (
315
+ cls.EngagementsitemModel.IdcompetitionModel.CategorieModel(
316
+ code=str(categorie_data.get("code", "")),
317
+ ordre=int(categorie_data.get("ordre", 0)),
318
+ )
319
+ if categorie_data
320
+ else None
321
+ )
322
+
323
+ id_competition = cls.EngagementsitemModel.IdcompetitionModel(
324
+ id=str(competition_data.get("id", "")),
325
+ nom=str(competition_data.get("nom", "")),
326
+ code=str(competition_data.get("code", "")),
327
+ sexe=str(competition_data.get("sexe", "")),
328
+ competition_origine=str(
329
+ competition_data.get("competition_origine", "")
330
+ ),
331
+ competition_origine_nom=str(
332
+ competition_data.get("competition_origine_nom", "")
333
+ ),
334
+ competition_origine_niveau=int(
335
+ competition_data.get("competition_origine_niveau", 0)
336
+ ),
337
+ typeCompetition=str(
338
+ competition_data.get("typeCompetition", "")
339
+ ),
340
+ logo=competition_data.get("logo"),
341
+ saison=saison,
342
+ idCompetitionPere=competition_data.get("idCompetitionPere"),
343
+ organisateur=organisateur,
344
+ typeCompetitionGenerique=type_comp_generique,
345
+ categorie=categorie,
346
+ )
347
+
348
+ engagement = cls.EngagementsitemModel(
349
+ id=str(engagement_data.get("id", "")),
350
+ numeroEquipe=engagement_data.get("numeroEquipe"),
351
+ idPoule=id_poule,
352
+ idCompetition=id_competition,
353
+ )
354
+ engagements.append(engagement)
355
+
356
+ # Extract offres pratiques
357
+ offres_pratiques = []
358
+ for offre_data in data.get("offresPratiques", []):
359
+ if offre_data:
360
+ ffbb_pratique_data = offre_data.get(
361
+ "ffbbserver_offres_pratiques_id", {}
362
+ )
363
+ ffbb_pratique = (
364
+ cls.OffrespratiquesitemModel.Ffbbserver_Offres_Pratiques_IdModel(
365
+ id=str(ffbb_pratique_data.get("id", "")),
366
+ title=str(ffbb_pratique_data.get("title", "")),
367
+ categoriePratique=str(
368
+ ffbb_pratique_data.get("categoriePratique", "")
369
+ ),
370
+ typePratique=str(ffbb_pratique_data.get("typePratique", "")),
371
+ )
372
+ if ffbb_pratique_data
373
+ else None
374
+ )
375
+
376
+ offre = cls.OffrespratiquesitemModel(
377
+ ffbbserver_offres_pratiques_id=ffbb_pratique
378
+ )
379
+ offres_pratiques.append(offre)
380
+
381
+ # Extract labellisation
382
+ labellisations = []
383
+ for label_data in data.get("labellisation", []):
384
+ if label_data:
385
+ programme_data = label_data.get("idLabellisationProgramme", {})
386
+ programme = (
387
+ cls.LabellisationitemModel.IdlabellisationprogrammeModel(
388
+ id=str(programme_data.get("id", "")),
389
+ libelle=str(programme_data.get("libelle", "")),
390
+ labellisationLabel=str(
391
+ programme_data.get("labellisationLabel", "")
392
+ ),
393
+ logo_vertical=programme_data.get("logo_vertical"),
394
+ )
395
+ if programme_data
396
+ else None
397
+ )
398
+
399
+ label = cls.LabellisationitemModel(
400
+ id=str(label_data.get("id", "")),
401
+ debut=datetime.fromisoformat(label_data.get("debut", "1970-01-01")),
402
+ fin=datetime.fromisoformat(label_data.get("fin", "1970-01-01")),
403
+ idLabellisationProgramme=programme,
404
+ )
405
+ labellisations.append(label)
406
+
407
+ # Extract salle
408
+ salle_data = data.get("salle", {})
409
+ salle = None
410
+ if salle_data:
411
+ salle_commune_data = salle_data.get("commune", {})
412
+ salle_commune = (
413
+ cls.SalleModel.CommuneModel(
414
+ codePostal=str(salle_commune_data.get("codePostal", "")),
415
+ libelle=str(salle_commune_data.get("libelle", "")),
416
+ )
417
+ if salle_commune_data
418
+ else None
419
+ )
420
+
421
+ salle_cartographie_data = salle_data.get("cartographie", {})
422
+ salle_cartographie = (
423
+ cls.SalleModel.CartographieModel(
424
+ latitude=float(salle_cartographie_data.get("latitude", 0.0)),
425
+ longitude=float(salle_cartographie_data.get("longitude", 0.0)),
426
+ )
427
+ if salle_cartographie_data
428
+ else None
429
+ )
430
+
431
+ salle = cls.SalleModel(
432
+ id=str(salle_data.get("id", "")),
433
+ numero=str(salle_data.get("numero", "")),
434
+ libelle=str(salle_data.get("libelle", "")),
435
+ libelle2=str(salle_data.get("libelle2", "")),
436
+ adresse=str(salle_data.get("adresse", "")),
437
+ adresseComplement=str(salle_data.get("adresseComplement", "")),
438
+ commune=salle_commune,
439
+ cartographie=salle_cartographie,
440
+ )
441
+
442
+ # Extract logo
443
+ logo_data = data.get("logo", {})
444
+ logo = (
445
+ cls.LogoModel(
446
+ id=str(logo_data.get("id", "")),
447
+ gradient_color=str(logo_data.get("gradient_color", "")),
448
+ )
449
+ if logo_data
450
+ else None
451
+ )
452
+
453
+ return cls(
454
+ id=str(data.get("id", "")),
455
+ nom=str(data.get("nom", "")),
456
+ code=str(data.get("code", "")),
457
+ telephone=str(data.get("telephone", "")),
458
+ adresse=str(data.get("adresse", "")),
459
+ mail=str(data.get("mail", "")),
460
+ type=str(data.get("type", "")),
461
+ nom_simple=data.get("nom_simple"),
462
+ urlSiteWeb=str(data.get("urlSiteWeb", "")),
463
+ nomClubPro=str(data.get("nomClubPro", "")),
464
+ adresseClubPro=data.get("adresseClubPro"),
465
+ commune=commune,
466
+ cartographie=cartographie,
467
+ communeClubPro=data.get("communeClubPro"),
468
+ membres=membres,
469
+ competitions=data.get("competitions", []),
470
+ engagements=engagements,
471
+ organismes_fils=data.get("organismes_fils", []),
472
+ offresPratiques=offres_pratiques,
473
+ labellisation=labellisations,
474
+ salle=salle,
475
+ logo=logo,
476
+ )
@@ -0,0 +1,68 @@
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 .poule_rencontre_item_model import PouleRencontreItemModel
8
+ from .team_ranking import TeamRanking
9
+
10
+
11
+ @dataclass
12
+ class GetPouleResponse:
13
+ id: str
14
+
15
+ # Keep nested alias for backward compatibility
16
+ RencontresitemModel = PouleRencontreItemModel
17
+
18
+ rencontres: list[PouleRencontreItemModel] = field(default_factory=list)
19
+ classements: list[TeamRanking] | None = None
20
+
21
+ @classmethod
22
+ def from_dict(cls, data: dict[str, Any]) -> GetPouleResponse | None:
23
+ """Convert dictionary to PoulesModel instance."""
24
+ if not data:
25
+ return None
26
+
27
+ # Handle case where data is not a dictionary
28
+ if not isinstance(data, dict):
29
+ return None
30
+
31
+ # Handle API error responses
32
+ if "errors" in data:
33
+ return None
34
+
35
+ # Basic implementation - can be expanded later
36
+ rencontres = []
37
+ for rencontre_data in data.get("rencontres", []):
38
+ if rencontre_data:
39
+ rencontre = PouleRencontreItemModel(
40
+ id=str(rencontre_data.get("id", "")),
41
+ numero=str(rencontre_data.get("numero", "")),
42
+ numeroJournee=str(rencontre_data.get("numeroJournee", "")),
43
+ idPoule=str(rencontre_data.get("idPoule", "")),
44
+ competitionId=str(rencontre_data.get("competitionId", "")),
45
+ resultatEquipe1=str(rencontre_data.get("resultatEquipe1", "")),
46
+ resultatEquipe2=str(rencontre_data.get("resultatEquipe2", "")),
47
+ joue=int(rencontre_data.get("joue", 0)),
48
+ nomEquipe1=str(rencontre_data.get("nomEquipe1", "")),
49
+ nomEquipe2=str(rencontre_data.get("nomEquipe2", "")),
50
+ date_rencontre=datetime.fromisoformat(
51
+ rencontre_data.get("date_rencontre", "1970-01-01")
52
+ ),
53
+ )
54
+ rencontres.append(rencontre)
55
+
56
+ # Process classements
57
+ classements = []
58
+ for classement_data in data.get("classements", []):
59
+ if classement_data:
60
+ classement = TeamRanking.from_dict(classement_data)
61
+ if classement:
62
+ classements.append(classement)
63
+
64
+ return cls(
65
+ id=str(data.get("id", "")),
66
+ rencontres=rencontres,
67
+ classements=classements if classements else None,
68
+ )