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,153 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Sequence
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
from httpx import Client
|
|
7
|
+
|
|
8
|
+
from ..clients.meilisearch_client import MeilisearchClient
|
|
9
|
+
from ..models.multi_search_query import MultiSearchQuery
|
|
10
|
+
from ..models.multi_search_results_class import MultiSearchResults
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class MeilisearchClientExtension(MeilisearchClient):
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
bearer_token: str,
|
|
17
|
+
url: str,
|
|
18
|
+
debug: bool = False,
|
|
19
|
+
cached_session: Client | None = None,
|
|
20
|
+
*,
|
|
21
|
+
async_cached_session: httpx.AsyncClient | None = None,
|
|
22
|
+
):
|
|
23
|
+
super().__init__(
|
|
24
|
+
bearer_token,
|
|
25
|
+
url,
|
|
26
|
+
debug,
|
|
27
|
+
cached_session,
|
|
28
|
+
async_cached_session=async_cached_session,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
def smart_multi_search(
|
|
32
|
+
self,
|
|
33
|
+
queries: Sequence[MultiSearchQuery] | None = None,
|
|
34
|
+
cached_session: Client | None = None,
|
|
35
|
+
) -> MultiSearchResults | None:
|
|
36
|
+
results = self.multi_search(queries, cached_session)
|
|
37
|
+
|
|
38
|
+
# Should filter results.hits according to query.q
|
|
39
|
+
if queries and results and results.results:
|
|
40
|
+
results.results = [
|
|
41
|
+
query.filter_result(res) if query.q else res
|
|
42
|
+
for query, res in zip(queries, results.results, strict=True)
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
return results
|
|
46
|
+
|
|
47
|
+
async def smart_multi_search_async(
|
|
48
|
+
self,
|
|
49
|
+
queries: Sequence[MultiSearchQuery] | None = None,
|
|
50
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
51
|
+
) -> MultiSearchResults | None:
|
|
52
|
+
results = await self.multi_search_async(queries, cached_session)
|
|
53
|
+
|
|
54
|
+
# Should filter results.hits according to query.q
|
|
55
|
+
if queries and results and results.results:
|
|
56
|
+
results.results = [
|
|
57
|
+
query.filter_result(res) if query.q else res
|
|
58
|
+
for query, res in zip(queries, results.results, strict=True)
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
return results
|
|
62
|
+
|
|
63
|
+
def recursive_smart_multi_search(
|
|
64
|
+
self,
|
|
65
|
+
queries: Sequence[MultiSearchQuery] | None = None,
|
|
66
|
+
cached_session: Client | None = None,
|
|
67
|
+
) -> MultiSearchResults | None:
|
|
68
|
+
result = self.smart_multi_search(queries, cached_session)
|
|
69
|
+
if not result or not queries or not result.results:
|
|
70
|
+
return result
|
|
71
|
+
|
|
72
|
+
next_queries: list[MultiSearchQuery] = []
|
|
73
|
+
# Store original query indexes to merge results correctly later
|
|
74
|
+
query_indices: list[int] = []
|
|
75
|
+
|
|
76
|
+
for i, (querie, query_result) in enumerate(
|
|
77
|
+
zip(queries, result.results, strict=True)
|
|
78
|
+
):
|
|
79
|
+
nb_hits = len(query_result.hits) if query_result.hits else 0
|
|
80
|
+
querie_offset = querie.offset or 0
|
|
81
|
+
querie_limit = querie.limit or 10
|
|
82
|
+
|
|
83
|
+
if query_result.estimated_total_hits is not None and nb_hits < (
|
|
84
|
+
query_result.estimated_total_hits - querie_offset
|
|
85
|
+
):
|
|
86
|
+
querie.offset = querie_offset + querie_limit
|
|
87
|
+
querie.limit = query_result.estimated_total_hits - nb_hits
|
|
88
|
+
next_queries.append(querie)
|
|
89
|
+
query_indices.append(i)
|
|
90
|
+
|
|
91
|
+
if next_queries:
|
|
92
|
+
new_result = self.recursive_smart_multi_search(next_queries, cached_session)
|
|
93
|
+
|
|
94
|
+
if new_result and new_result.results:
|
|
95
|
+
for orig_idx, query_result in zip(
|
|
96
|
+
query_indices, new_result.results, strict=True
|
|
97
|
+
):
|
|
98
|
+
orig_result = result.results[orig_idx]
|
|
99
|
+
hits_list = orig_result.hits
|
|
100
|
+
if query_result.hits and hits_list is not None:
|
|
101
|
+
hits_list.extend(query_result.hits)
|
|
102
|
+
return result
|
|
103
|
+
|
|
104
|
+
async def recursive_smart_multi_search_async(
|
|
105
|
+
self,
|
|
106
|
+
queries: Sequence[MultiSearchQuery] | None = None,
|
|
107
|
+
cached_session: httpx.AsyncClient | None = None,
|
|
108
|
+
) -> MultiSearchResults | None:
|
|
109
|
+
result = await self.smart_multi_search_async(queries, cached_session)
|
|
110
|
+
if not result or not queries or not result.results:
|
|
111
|
+
return result
|
|
112
|
+
|
|
113
|
+
next_queries: list[MultiSearchQuery] = []
|
|
114
|
+
# Store original query indexes to merge results correctly later
|
|
115
|
+
query_indices: list[int] = []
|
|
116
|
+
|
|
117
|
+
for i, (querie, query_result) in enumerate(
|
|
118
|
+
zip(queries, result.results, strict=True)
|
|
119
|
+
):
|
|
120
|
+
nb_hits = len(query_result.hits) if query_result.hits else 0
|
|
121
|
+
querie_offset = querie.offset or 0
|
|
122
|
+
querie_limit = querie.limit or 10
|
|
123
|
+
|
|
124
|
+
if query_result.estimated_total_hits is not None and nb_hits < (
|
|
125
|
+
query_result.estimated_total_hits - querie_offset
|
|
126
|
+
):
|
|
127
|
+
querie.offset = querie_offset + querie_limit
|
|
128
|
+
querie.limit = query_result.estimated_total_hits - nb_hits
|
|
129
|
+
next_queries.append(querie)
|
|
130
|
+
query_indices.append(i)
|
|
131
|
+
|
|
132
|
+
if next_queries:
|
|
133
|
+
new_result = await self.recursive_smart_multi_search_async(
|
|
134
|
+
next_queries, cached_session
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
if new_result and new_result.results:
|
|
138
|
+
for orig_idx, query_result in zip(
|
|
139
|
+
query_indices, new_result.results, strict=True
|
|
140
|
+
):
|
|
141
|
+
orig_result = result.results[orig_idx]
|
|
142
|
+
hits_list = orig_result.hits
|
|
143
|
+
if query_result.hits and hits_list is not None:
|
|
144
|
+
hits_list.extend(query_result.hits)
|
|
145
|
+
return result
|
|
146
|
+
|
|
147
|
+
def recursive_multi_search(
|
|
148
|
+
self,
|
|
149
|
+
queries: Sequence[MultiSearchQuery] | None = None,
|
|
150
|
+
cached_session: Client | None = None,
|
|
151
|
+
) -> MultiSearchResults | None:
|
|
152
|
+
"""Alias for recursive_smart_multi_search for backward compatibility."""
|
|
153
|
+
return self.recursive_smart_multi_search(queries, cached_session)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from ..models.competitions_multi_search_query import CompetitionsMultiSearchQuery
|
|
4
|
+
from ..models.content_multi_search_query import (
|
|
5
|
+
GaleriesMultiSearchQuery,
|
|
6
|
+
NewsMultiSearchQuery,
|
|
7
|
+
RssMultiSearchQuery,
|
|
8
|
+
YoutubeVideosMultiSearchQuery,
|
|
9
|
+
)
|
|
10
|
+
from ..models.engagements_multi_search_query import EngagementsMultiSearchQuery
|
|
11
|
+
from ..models.formations_multi_search_query import FormationsMultiSearchQuery
|
|
12
|
+
from ..models.organismes_multi_search_query import OrganismesMultiSearchQuery
|
|
13
|
+
from ..models.pratiques_multi_search_query import PratiquesMultiSearchQuery
|
|
14
|
+
from ..models.rencontres_multi_search_query import RencontresMultiSearchQuery
|
|
15
|
+
from ..models.salles_multi_search_query import SallesMultiSearchQuery
|
|
16
|
+
from ..models.terrains_multi_search_query import TerrainsMultiSearchQuery
|
|
17
|
+
from ..models.tournois_multi_search_query import TournoisMultiSearchQuery
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def generate_queries(search_name: str | None = None, limit: int | None = 1):
|
|
21
|
+
return [
|
|
22
|
+
OrganismesMultiSearchQuery(search_name, limit=limit),
|
|
23
|
+
RencontresMultiSearchQuery(search_name, limit=limit),
|
|
24
|
+
TerrainsMultiSearchQuery(search_name, limit=limit),
|
|
25
|
+
CompetitionsMultiSearchQuery(search_name, limit=limit),
|
|
26
|
+
SallesMultiSearchQuery(search_name, limit=limit),
|
|
27
|
+
TournoisMultiSearchQuery(search_name, limit=limit),
|
|
28
|
+
PratiquesMultiSearchQuery(search_name, limit=limit),
|
|
29
|
+
EngagementsMultiSearchQuery(search_name, limit=limit),
|
|
30
|
+
FormationsMultiSearchQuery(search_name, limit=limit),
|
|
31
|
+
NewsMultiSearchQuery(search_name, limit=limit),
|
|
32
|
+
YoutubeVideosMultiSearchQuery(search_name, limit=limit),
|
|
33
|
+
RssMultiSearchQuery(search_name, limit=limit),
|
|
34
|
+
GaleriesMultiSearchQuery(search_name, limit=limit),
|
|
35
|
+
]
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"""Data models for FFBB API client."""
|
|
2
|
+
|
|
3
|
+
# Import existing model files (all now in snake_case)
|
|
4
|
+
from .affiche import Affiche
|
|
5
|
+
from .cartographie import Cartographie
|
|
6
|
+
from .categorie import Categorie
|
|
7
|
+
from .clock import Clock
|
|
8
|
+
from .code import Code
|
|
9
|
+
from .commune import Commune
|
|
10
|
+
from .competition_fields import CompetitionFields
|
|
11
|
+
from .competition_id import CompetitionID
|
|
12
|
+
from .competition_id_categorie import CompetitionIDCategorie
|
|
13
|
+
from .competition_id_sexe import CompetitionIDSexe
|
|
14
|
+
from .competition_id_type_competition import CompetitionIDTypeCompetition
|
|
15
|
+
from .competition_id_type_competition_generique import (
|
|
16
|
+
CompetitionIDTypeCompetitionGenerique,
|
|
17
|
+
)
|
|
18
|
+
from .competition_origine import CompetitionOrigine
|
|
19
|
+
from .competition_origine_categorie import CompetitionOrigineCategorie
|
|
20
|
+
from .competition_origine_type_competition import CompetitionOrigineTypeCompetition
|
|
21
|
+
from .competition_origine_type_competition_generique import (
|
|
22
|
+
CompetitionOrigineTypeCompetitionGenerique,
|
|
23
|
+
)
|
|
24
|
+
from .competition_type import CompetitionType
|
|
25
|
+
from .competitions_multi_search_query import CompetitionsMultiSearchQuery
|
|
26
|
+
from .competitions_query import CompetitionsQuery
|
|
27
|
+
from .coordonnees import Coordonnees
|
|
28
|
+
from .coordonnees_type import CoordonneesType
|
|
29
|
+
from .document_flyer import DocumentFlyer
|
|
30
|
+
from .document_flyer_type import DocumentFlyerType
|
|
31
|
+
from .engagements_facet_distribution import EngagementsFacetDistribution
|
|
32
|
+
from .engagements_facet_stats import EngagementsFacetStats
|
|
33
|
+
from .engagements_hit import EngagementsHit
|
|
34
|
+
from .engagements_multi_search_query import EngagementsMultiSearchQuery
|
|
35
|
+
from .etat import Etat
|
|
36
|
+
from .external_competition_id import ExternalCompetitionID
|
|
37
|
+
from .external_id import ExternalID
|
|
38
|
+
from .facet_distribution import FacetDistribution
|
|
39
|
+
from .facet_stats import FacetStats
|
|
40
|
+
from .field_set import FieldSet
|
|
41
|
+
from .folder import Folder
|
|
42
|
+
from .formation_session import FormationSession
|
|
43
|
+
from .formations_facet_distribution import FormationsFacetDistribution
|
|
44
|
+
from .formations_facet_stats import FormationsFacetStats
|
|
45
|
+
from .formations_hit import FormationsHit
|
|
46
|
+
from .formations_multi_search_query import FormationsMultiSearchQuery
|
|
47
|
+
from .game_stats_model import GameStatsModel
|
|
48
|
+
from .geo import Geo
|
|
49
|
+
from .get_competition_response import GetCompetitionResponse
|
|
50
|
+
from .get_configuration_response import GetConfigurationResponse
|
|
51
|
+
from .get_organisme_response import GetOrganismeResponse
|
|
52
|
+
from .get_poule_response import GetPouleResponse
|
|
53
|
+
from .get_saisons_response import GetSaisonsResponse
|
|
54
|
+
from .gradient_color import GradientColor
|
|
55
|
+
from .hit import Hit
|
|
56
|
+
from .id_engagement_equipe import IDEngagementEquipe
|
|
57
|
+
from .id_organisme_equipe import IDOrganismeEquipe
|
|
58
|
+
from .id_organisme_equipe1_logo import IDOrganismeEquipe1Logo
|
|
59
|
+
from .id_poule import IDPoule
|
|
60
|
+
from .jour import Jour
|
|
61
|
+
from .label import Label
|
|
62
|
+
from .labellisation import Labellisation
|
|
63
|
+
from .live import Live, lives_from_dict
|
|
64
|
+
from .logo import Logo
|
|
65
|
+
from .multi_search_queries import MultiSearchQueries
|
|
66
|
+
from .multi_search_query import MultiSearchQuery
|
|
67
|
+
from .multi_search_result_competitions import CompetitionsMultiSearchResult
|
|
68
|
+
from .multi_search_result_engagements import EngagementsMultiSearchResult
|
|
69
|
+
from .multi_search_result_formations import FormationsMultiSearchResult
|
|
70
|
+
from .multi_search_result_organismes import OrganismesMultiSearchResult
|
|
71
|
+
from .multi_search_result_pratiques import PratiquesMultiSearchResult
|
|
72
|
+
from .multi_search_result_rencontres import RencontresMultiSearchResult
|
|
73
|
+
from .multi_search_result_salles import SallesMultiSearchResult
|
|
74
|
+
from .multi_search_result_terrains import TerrainsMultiSearchResult
|
|
75
|
+
from .multi_search_result_tournois import TournoisMultiSearchResult
|
|
76
|
+
from .multi_search_results import MultiSearchResult
|
|
77
|
+
from .multi_search_results_class import multi_search_results_from_dict
|
|
78
|
+
from .nature_sol import NatureSol
|
|
79
|
+
from .niveau import Niveau
|
|
80
|
+
from .niveau_class import NiveauClass
|
|
81
|
+
from .objectif import Objectif
|
|
82
|
+
from .organisateur import Organisateur
|
|
83
|
+
from .organisateur_type import OrganisateurType
|
|
84
|
+
from .organisme_fields import OrganismeFields
|
|
85
|
+
from .organisme_id_pere import OrganismeIDPere
|
|
86
|
+
from .organismes_multi_search_query import OrganismesMultiSearchQuery
|
|
87
|
+
from .organismes_query import OrganismesQuery
|
|
88
|
+
from .phase_code import PhaseCode
|
|
89
|
+
from .poule import Poule
|
|
90
|
+
from .poule_fields import PouleFields
|
|
91
|
+
from .poules_query import PoulesQuery
|
|
92
|
+
from .pratique import Pratique
|
|
93
|
+
from .pratiques_multi_search_query import PratiquesMultiSearchQuery
|
|
94
|
+
from .pratiques_type_class import PratiquesTypeClass
|
|
95
|
+
from .publication_internet import PublicationInternet
|
|
96
|
+
from .purple_logo import PurpleLogo
|
|
97
|
+
from .query_fields_manager import QueryFieldsManager
|
|
98
|
+
from .ranking_engagement import RankingEngagement
|
|
99
|
+
from .rencontres_multi_search_query import RencontresMultiSearchQuery
|
|
100
|
+
from .saison import Saison
|
|
101
|
+
from .saison_fields import SaisonFields
|
|
102
|
+
from .saisons_query import SaisonsQuery
|
|
103
|
+
from .salle import Salle
|
|
104
|
+
from .salles_multi_search_query import SallesMultiSearchQuery
|
|
105
|
+
from .sexe import Sexe
|
|
106
|
+
from .sexe_class import SexeClass
|
|
107
|
+
from .source import Source
|
|
108
|
+
from .status import Status
|
|
109
|
+
from .team_engagement import TeamEngagement
|
|
110
|
+
from .team_ranking import TeamRanking
|
|
111
|
+
from .terrains_multi_search_query import TerrainsMultiSearchQuery
|
|
112
|
+
from .tournoi_type_class import TournoiTypeClass
|
|
113
|
+
from .tournoi_type_enum import TournoiTypeEnum
|
|
114
|
+
from .tournois_multi_search_query import TournoisMultiSearchQuery
|
|
115
|
+
from .type_association import TypeAssociation
|
|
116
|
+
from .type_association_libelle import TypeAssociationLibelle
|
|
117
|
+
from .type_class import TypeClass
|
|
118
|
+
from .type_competition import TypeCompetition
|
|
119
|
+
from .type_competition_generique import TypeCompetitionGenerique
|
|
120
|
+
from .type_enum import TypeEnum
|
|
121
|
+
from .type_league import TypeLeague
|
|
122
|
+
|
|
123
|
+
__all__ = [
|
|
124
|
+
# Classes from snake_case files
|
|
125
|
+
"Affiche",
|
|
126
|
+
"Cartographie",
|
|
127
|
+
"Categorie",
|
|
128
|
+
"Clock",
|
|
129
|
+
"Code",
|
|
130
|
+
"Commune",
|
|
131
|
+
"CompetitionID",
|
|
132
|
+
"CompetitionIDCategorie",
|
|
133
|
+
"CompetitionIDSexe",
|
|
134
|
+
"CompetitionIDTypeCompetition",
|
|
135
|
+
"CompetitionIDTypeCompetitionGenerique",
|
|
136
|
+
"CompetitionOrigine",
|
|
137
|
+
"CompetitionOrigineCategorie",
|
|
138
|
+
"CompetitionOrigineTypeCompetition",
|
|
139
|
+
"CompetitionOrigineTypeCompetitionGenerique",
|
|
140
|
+
"CompetitionType",
|
|
141
|
+
"CompetitionsMultiSearchQuery",
|
|
142
|
+
"CompetitionsMultiSearchResult",
|
|
143
|
+
"CompetitionsQuery",
|
|
144
|
+
"Coordonnees",
|
|
145
|
+
"CoordonneesType",
|
|
146
|
+
"DocumentFlyer",
|
|
147
|
+
"DocumentFlyerType",
|
|
148
|
+
"EngagementsFacetDistribution",
|
|
149
|
+
"EngagementsFacetStats",
|
|
150
|
+
"EngagementsHit",
|
|
151
|
+
"EngagementsMultiSearchQuery",
|
|
152
|
+
"EngagementsMultiSearchResult",
|
|
153
|
+
"Etat",
|
|
154
|
+
"ExternalCompetitionID",
|
|
155
|
+
"ExternalID",
|
|
156
|
+
"FacetDistribution",
|
|
157
|
+
"FacetStats",
|
|
158
|
+
"Folder",
|
|
159
|
+
"FormationSession",
|
|
160
|
+
"FormationsFacetDistribution",
|
|
161
|
+
"FormationsFacetStats",
|
|
162
|
+
"FormationsHit",
|
|
163
|
+
"FormationsMultiSearchQuery",
|
|
164
|
+
"FormationsMultiSearchResult",
|
|
165
|
+
"GameStatsModel",
|
|
166
|
+
"Geo",
|
|
167
|
+
"GetCompetitionResponse",
|
|
168
|
+
"GetConfigurationResponse",
|
|
169
|
+
"GetOrganismeResponse",
|
|
170
|
+
"GetPouleResponse",
|
|
171
|
+
"GetSaisonsResponse",
|
|
172
|
+
"GradientColor",
|
|
173
|
+
"Hit",
|
|
174
|
+
"IDEngagementEquipe",
|
|
175
|
+
"IDOrganismeEquipe",
|
|
176
|
+
"IDOrganismeEquipe1Logo",
|
|
177
|
+
"IDPoule",
|
|
178
|
+
"Jour",
|
|
179
|
+
"Label",
|
|
180
|
+
"Labellisation",
|
|
181
|
+
"Live",
|
|
182
|
+
"Logo",
|
|
183
|
+
"MultiSearchQueries",
|
|
184
|
+
"MultiSearchQuery",
|
|
185
|
+
"MultiSearchResult",
|
|
186
|
+
"NatureSol",
|
|
187
|
+
"Niveau",
|
|
188
|
+
"NiveauClass",
|
|
189
|
+
"Objectif",
|
|
190
|
+
"Organisateur",
|
|
191
|
+
"OrganisateurType",
|
|
192
|
+
"OrganismeIDPere",
|
|
193
|
+
"OrganismesMultiSearchQuery",
|
|
194
|
+
"OrganismesMultiSearchResult",
|
|
195
|
+
"OrganismesQuery",
|
|
196
|
+
"PhaseCode",
|
|
197
|
+
"Poule",
|
|
198
|
+
"PoulesQuery",
|
|
199
|
+
"Pratique",
|
|
200
|
+
"RankingEngagement",
|
|
201
|
+
"PratiquesMultiSearchQuery",
|
|
202
|
+
"PratiquesMultiSearchResult",
|
|
203
|
+
"PublicationInternet",
|
|
204
|
+
"PurpleLogo",
|
|
205
|
+
"QueryFieldsManager",
|
|
206
|
+
"OrganismeFields",
|
|
207
|
+
"CompetitionFields",
|
|
208
|
+
"PouleFields",
|
|
209
|
+
"SaisonFields",
|
|
210
|
+
"FieldSet",
|
|
211
|
+
"RencontresMultiSearchQuery",
|
|
212
|
+
"RencontresMultiSearchResult",
|
|
213
|
+
"Saison",
|
|
214
|
+
"SaisonsQuery",
|
|
215
|
+
"Salle",
|
|
216
|
+
"SallesMultiSearchQuery",
|
|
217
|
+
"SallesMultiSearchResult",
|
|
218
|
+
"Sexe",
|
|
219
|
+
"Source",
|
|
220
|
+
"Status",
|
|
221
|
+
"TeamEngagement",
|
|
222
|
+
"TerrainsMultiSearchQuery",
|
|
223
|
+
"TerrainsMultiSearchResult",
|
|
224
|
+
"TournoisMultiSearchQuery",
|
|
225
|
+
"TeamRanking",
|
|
226
|
+
"TournoisMultiSearchResult",
|
|
227
|
+
"TournoiTypeClass",
|
|
228
|
+
"TournoiTypeEnum",
|
|
229
|
+
"TypeAssociation",
|
|
230
|
+
"TypeAssociationLibelle",
|
|
231
|
+
"TypeClass",
|
|
232
|
+
"TypeCompetition",
|
|
233
|
+
"TypeCompetitionGenerique",
|
|
234
|
+
"TypeEnum",
|
|
235
|
+
"PratiquesTypeClass",
|
|
236
|
+
"SexeClass",
|
|
237
|
+
"TypeLeague",
|
|
238
|
+
# Functions
|
|
239
|
+
"lives_from_dict",
|
|
240
|
+
"multi_search_results_from_dict",
|
|
241
|
+
]
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any
|
|
5
|
+
from uuid import UUID
|
|
6
|
+
|
|
7
|
+
from ..utils.converter_utils import (
|
|
8
|
+
from_int,
|
|
9
|
+
from_str,
|
|
10
|
+
from_uuid,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class Affiche:
|
|
16
|
+
affiche_id: UUID | None = None
|
|
17
|
+
gradient_color: str | None = None
|
|
18
|
+
width: int | None = None
|
|
19
|
+
height: int | None = None
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
def from_dict(obj: Any) -> Affiche:
|
|
23
|
+
assert isinstance(obj, dict)
|
|
24
|
+
affiche_id = from_uuid(obj, "id")
|
|
25
|
+
gradient_color = from_str(obj, "gradient_color")
|
|
26
|
+
width = from_int(obj, "width")
|
|
27
|
+
height = from_int(obj, "height")
|
|
28
|
+
return Affiche(
|
|
29
|
+
affiche_id=affiche_id,
|
|
30
|
+
gradient_color=gradient_color,
|
|
31
|
+
width=width,
|
|
32
|
+
height=height,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
def to_dict(self) -> dict:
|
|
36
|
+
result: dict = {}
|
|
37
|
+
if self.affiche_id is not None:
|
|
38
|
+
result["id"] = str(self.affiche_id)
|
|
39
|
+
if self.gradient_color is not None:
|
|
40
|
+
result["gradient_color"] = self.gradient_color
|
|
41
|
+
if self.width is not None:
|
|
42
|
+
result["width"] = self.width
|
|
43
|
+
if self.height is not None:
|
|
44
|
+
result["height"] = self.height
|
|
45
|
+
return result
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from ..utils.converter_utils import (
|
|
8
|
+
from_datetime,
|
|
9
|
+
from_float,
|
|
10
|
+
from_obj,
|
|
11
|
+
from_str,
|
|
12
|
+
)
|
|
13
|
+
from .coordonnees import Coordonnees
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class Cartographie:
|
|
18
|
+
adresse: str | None = None
|
|
19
|
+
code_postal: str | None = None
|
|
20
|
+
coordonnees: Coordonnees | None = None
|
|
21
|
+
date_created: datetime | None = None
|
|
22
|
+
date_updated: datetime | None = None
|
|
23
|
+
cartographie_id: str | None = None
|
|
24
|
+
latitude: float | None = None
|
|
25
|
+
longitude: float | None = None
|
|
26
|
+
title: str | None = None
|
|
27
|
+
ville: str | None = None
|
|
28
|
+
status: str | None = None
|
|
29
|
+
|
|
30
|
+
@staticmethod
|
|
31
|
+
def from_dict(obj: Any) -> Cartographie:
|
|
32
|
+
assert isinstance(obj, dict)
|
|
33
|
+
adresse = from_str(obj, "adresse")
|
|
34
|
+
code_postal = from_str(obj, "codePostal")
|
|
35
|
+
coordonnees = from_obj(Coordonnees.from_dict, obj, "coordonnees")
|
|
36
|
+
date_created = from_datetime(obj, "date_created")
|
|
37
|
+
date_updated = from_datetime(obj, "date_updated")
|
|
38
|
+
cartographie_id = from_str(obj, "id")
|
|
39
|
+
latitude = from_float(obj, "latitude")
|
|
40
|
+
longitude = from_float(obj, "longitude")
|
|
41
|
+
title = from_str(obj, "title")
|
|
42
|
+
ville = from_str(obj, "ville")
|
|
43
|
+
status = from_str(obj, "status")
|
|
44
|
+
return Cartographie(
|
|
45
|
+
adresse=adresse,
|
|
46
|
+
code_postal=code_postal,
|
|
47
|
+
coordonnees=coordonnees,
|
|
48
|
+
date_created=date_created,
|
|
49
|
+
date_updated=date_updated,
|
|
50
|
+
cartographie_id=cartographie_id,
|
|
51
|
+
latitude=latitude,
|
|
52
|
+
longitude=longitude,
|
|
53
|
+
title=title,
|
|
54
|
+
ville=ville,
|
|
55
|
+
status=status,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
def to_dict(self) -> dict:
|
|
59
|
+
result: dict = {}
|
|
60
|
+
if self.adresse is not None:
|
|
61
|
+
result["adresse"] = self.adresse
|
|
62
|
+
if self.code_postal is not None:
|
|
63
|
+
result["codePostal"] = self.code_postal
|
|
64
|
+
if self.coordonnees is not None:
|
|
65
|
+
result["coordonnees"] = self.coordonnees.to_dict()
|
|
66
|
+
if self.date_created is not None:
|
|
67
|
+
result["date_created"] = self.date_created.isoformat()
|
|
68
|
+
if self.date_updated is not None:
|
|
69
|
+
result["date_updated"] = self.date_updated.isoformat()
|
|
70
|
+
if self.cartographie_id is not None:
|
|
71
|
+
result["id"] = self.cartographie_id
|
|
72
|
+
if self.latitude is not None:
|
|
73
|
+
result["latitude"] = self.latitude
|
|
74
|
+
if self.longitude is not None:
|
|
75
|
+
result["longitude"] = self.longitude
|
|
76
|
+
if self.title is not None:
|
|
77
|
+
result["title"] = self.title
|
|
78
|
+
if self.ville is not None:
|
|
79
|
+
result["ville"] = self.ville
|
|
80
|
+
if self.status is not None:
|
|
81
|
+
result["status"] = self.status
|
|
82
|
+
return result
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
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 Categorie:
|
|
16
|
+
code: str | None = None
|
|
17
|
+
date_created: datetime | None = None
|
|
18
|
+
date_updated: datetime | None = None
|
|
19
|
+
categorie_id: str | None = None
|
|
20
|
+
libelle: str | None = None
|
|
21
|
+
ordre: int | None = None
|
|
22
|
+
|
|
23
|
+
@staticmethod
|
|
24
|
+
def from_dict(obj: Any) -> Categorie:
|
|
25
|
+
assert isinstance(obj, dict)
|
|
26
|
+
code = from_str(obj, "code")
|
|
27
|
+
date_created = from_datetime(obj, "date_created")
|
|
28
|
+
date_updated = from_datetime(obj, "date_updated")
|
|
29
|
+
categorie_id = from_str(obj, "id")
|
|
30
|
+
libelle = from_str(obj, "libelle")
|
|
31
|
+
ordre = from_int(obj, "ordre")
|
|
32
|
+
return Categorie(
|
|
33
|
+
code=code,
|
|
34
|
+
date_created=date_created,
|
|
35
|
+
date_updated=date_updated,
|
|
36
|
+
categorie_id=categorie_id,
|
|
37
|
+
libelle=libelle,
|
|
38
|
+
ordre=ordre,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
def to_dict(self) -> dict:
|
|
42
|
+
result: dict = {}
|
|
43
|
+
if self.code is not None:
|
|
44
|
+
result["code"] = self.code
|
|
45
|
+
if self.date_created is not None:
|
|
46
|
+
result["date_created"] = self.date_created.isoformat()
|
|
47
|
+
if self.date_updated is not None:
|
|
48
|
+
result["date_updated"] = self.date_updated.isoformat()
|
|
49
|
+
if self.categorie_id is not None:
|
|
50
|
+
result["id"] = self.categorie_id
|
|
51
|
+
if self.libelle is not None:
|
|
52
|
+
result["libelle"] = self.libelle
|
|
53
|
+
if self.ordre is not None:
|
|
54
|
+
result["ordre"] = self.ordre
|
|
55
|
+
return result
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class CategorieType(Enum):
|
|
5
|
+
"""Enumération des catégories d'âge en basketball."""
|
|
6
|
+
|
|
7
|
+
# Catégories jeunes
|
|
8
|
+
U7 = "U7"
|
|
9
|
+
U9 = "U9"
|
|
10
|
+
U11 = "U11"
|
|
11
|
+
U13 = "U13"
|
|
12
|
+
U15 = "U15"
|
|
13
|
+
U17 = "U17"
|
|
14
|
+
U18 = "U18"
|
|
15
|
+
U20 = "U20"
|
|
16
|
+
U21 = "U21"
|
|
17
|
+
|
|
18
|
+
# Catégories seniors
|
|
19
|
+
SENIOR = "SENIOR"
|
|
20
|
+
SENIORS = "SENIORS"
|
|
21
|
+
|
|
22
|
+
# Catégories vétérans
|
|
23
|
+
VETERAN = "VETERAN"
|
|
24
|
+
VETERANS = "VETERANS"
|
|
25
|
+
V35 = "V35"
|
|
26
|
+
V40 = "V40"
|
|
27
|
+
V45 = "V45"
|
|
28
|
+
V50 = "V50"
|
|
29
|
+
|
|
30
|
+
# Catégories spéciales
|
|
31
|
+
ESPOIR = "ESPOIR"
|
|
32
|
+
ESPOIRS = "ESPOIRS"
|
|
33
|
+
CADET = "CADET"
|
|
34
|
+
CADETS = "CADETS"
|
|
35
|
+
MINIME = "MINIME"
|
|
36
|
+
MINIMES = "MINIMES"
|
|
37
|
+
BENJAMIN = "BENJAMIN"
|
|
38
|
+
BENJAMINS = "BENJAMINS"
|
|
39
|
+
POUSSIN = "POUSSIN"
|
|
40
|
+
POUSSINS = "POUSSINS"
|
|
41
|
+
MINI_POUSSIN = "MINI_POUSSIN"
|
|
42
|
+
MINI_POUSSINS = "MINI_POUSSINS"
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class Clock:
|
|
9
|
+
minutes: int = 0
|
|
10
|
+
seconds: int = 0
|
|
11
|
+
milliseconds: int = 0
|
|
12
|
+
|
|
13
|
+
@staticmethod
|
|
14
|
+
def from_str(obj: str) -> Clock:
|
|
15
|
+
minutes, seconds, milliseconds = obj.split(":") if obj else ["0", "0", "0"]
|
|
16
|
+
return Clock(
|
|
17
|
+
minutes=int(minutes), seconds=int(seconds), milliseconds=int(milliseconds)
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
@classmethod
|
|
21
|
+
def __get_pydantic_core_schema__(cls, _source_type: Any, handler: Any) -> Any:
|
|
22
|
+
from pydantic_core import core_schema
|
|
23
|
+
|
|
24
|
+
return core_schema.no_info_before_validator_function(
|
|
25
|
+
cls._parse_pydantic,
|
|
26
|
+
handler(_source_type),
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
@classmethod
|
|
30
|
+
def _parse_pydantic(cls, value: Any) -> Any:
|
|
31
|
+
if isinstance(value, str):
|
|
32
|
+
return cls.from_str(value)
|
|
33
|
+
elif isinstance(value, dict):
|
|
34
|
+
return Clock(**value)
|
|
35
|
+
return value
|
|
36
|
+
|
|
37
|
+
def to_str(self) -> str:
|
|
38
|
+
return f"{self.minutes}:{self.seconds}:{self.milliseconds}"
|