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,28 @@
|
|
|
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 from_str, from_uuid
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class Logo:
|
|
12
|
+
id: UUID | None = None
|
|
13
|
+
gradient_color: str | None = None
|
|
14
|
+
|
|
15
|
+
@staticmethod
|
|
16
|
+
def from_dict(obj: Any) -> Logo:
|
|
17
|
+
assert isinstance(obj, dict)
|
|
18
|
+
id = from_uuid(obj, "id")
|
|
19
|
+
gradient_color = from_str(obj, "gradient_color")
|
|
20
|
+
return Logo(id=id, gradient_color=gradient_color)
|
|
21
|
+
|
|
22
|
+
def to_dict(self) -> dict:
|
|
23
|
+
result: dict = {}
|
|
24
|
+
if self.id is not None:
|
|
25
|
+
result["id"] = str(self.id)
|
|
26
|
+
if self.gradient_color is not None:
|
|
27
|
+
result["gradient_color"] = self.gradient_color
|
|
28
|
+
return result
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from ..utils.converter_utils import from_list
|
|
7
|
+
from .multi_search_query import MultiSearchQuery
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class MultiSearchQueries:
|
|
12
|
+
queries: list[MultiSearchQuery] | None = None
|
|
13
|
+
|
|
14
|
+
@staticmethod
|
|
15
|
+
def from_dict(obj: Any) -> MultiSearchQueries:
|
|
16
|
+
assert isinstance(obj, dict)
|
|
17
|
+
queries = from_list(MultiSearchQuery.from_dict, obj, "queries")
|
|
18
|
+
return MultiSearchQueries(queries=queries)
|
|
19
|
+
|
|
20
|
+
def to_dict(self) -> dict:
|
|
21
|
+
result: dict = {}
|
|
22
|
+
if self.queries is not None:
|
|
23
|
+
result["queries"] = [q.to_dict() for q in self.queries]
|
|
24
|
+
return result
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from ..utils.converter_utils import (
|
|
7
|
+
from_int,
|
|
8
|
+
from_list,
|
|
9
|
+
from_str,
|
|
10
|
+
)
|
|
11
|
+
from .facet_distribution import FacetDistribution
|
|
12
|
+
from .facet_stats import FacetStats
|
|
13
|
+
from .hit import Hit
|
|
14
|
+
from .multi_search_results import MultiSearchResult
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class MultiSearchQuery:
|
|
19
|
+
index_uid: str | None = None
|
|
20
|
+
q: str | None = None
|
|
21
|
+
facets: list[str] | None = None
|
|
22
|
+
limit: int | None = 10
|
|
23
|
+
offset: int | None = 0
|
|
24
|
+
filter: list[Any] | None = None
|
|
25
|
+
sort: list[Any] | None = None
|
|
26
|
+
lower_q: str | None = field(init=False, default=None, repr=False)
|
|
27
|
+
|
|
28
|
+
def __post_init__(self) -> None:
|
|
29
|
+
self.lower_q = self.q.lower() if self.q else None
|
|
30
|
+
|
|
31
|
+
@staticmethod
|
|
32
|
+
def from_dict(obj: Any) -> MultiSearchQuery:
|
|
33
|
+
assert isinstance(obj, dict)
|
|
34
|
+
index_uid = from_str(obj, "indexUid")
|
|
35
|
+
q = from_str(obj, "q")
|
|
36
|
+
facets = from_list(str, obj, "facets")
|
|
37
|
+
limit = from_int(obj, "limit")
|
|
38
|
+
offset = from_int(obj, "offset")
|
|
39
|
+
filter = from_list(lambda x: x, obj, "filter")
|
|
40
|
+
sort = from_list(lambda x: x, obj, "sort")
|
|
41
|
+
return MultiSearchQuery(
|
|
42
|
+
index_uid=index_uid,
|
|
43
|
+
q=q,
|
|
44
|
+
facets=facets,
|
|
45
|
+
limit=limit,
|
|
46
|
+
offset=offset,
|
|
47
|
+
filter=filter,
|
|
48
|
+
sort=sort,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
def to_dict(self) -> dict:
|
|
52
|
+
result: dict = {}
|
|
53
|
+
if self.index_uid is not None:
|
|
54
|
+
result["indexUid"] = self.index_uid
|
|
55
|
+
if self.q is not None:
|
|
56
|
+
result["q"] = self.q
|
|
57
|
+
if self.facets is not None:
|
|
58
|
+
result["facets"] = self.facets
|
|
59
|
+
if self.limit is not None:
|
|
60
|
+
result["limit"] = self.limit
|
|
61
|
+
if self.offset is not None:
|
|
62
|
+
result["offset"] = self.offset
|
|
63
|
+
if self.filter is not None:
|
|
64
|
+
result["filter"] = self.filter
|
|
65
|
+
if self.sort is not None:
|
|
66
|
+
result["sort"] = self.sort
|
|
67
|
+
return result
|
|
68
|
+
|
|
69
|
+
def is_valid_result(self, result: MultiSearchResult):
|
|
70
|
+
return result and (
|
|
71
|
+
isinstance(result, MultiSearchResult)
|
|
72
|
+
and (
|
|
73
|
+
result.facet_distribution is None
|
|
74
|
+
or isinstance(result.facet_distribution, FacetDistribution)
|
|
75
|
+
)
|
|
76
|
+
and (
|
|
77
|
+
result.facet_stats is None or isinstance(result.facet_stats, FacetStats)
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
def is_valid_hit(self, _hit: Hit):
|
|
82
|
+
return True
|
|
83
|
+
|
|
84
|
+
def filter_result(self, result: MultiSearchResult) -> MultiSearchResult:
|
|
85
|
+
if self.lower_q and result.hits:
|
|
86
|
+
# ⚡ Bolt optimization: Replace O(n²) list.remove in a loop with O(n) list comprehension for filtering hits.
|
|
87
|
+
valid_hits = [
|
|
88
|
+
hit for hit in result.hits if hit.is_valid_for_query(self.lower_q)
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
if len(valid_hits) < len(result.hits):
|
|
92
|
+
if result.estimated_total_hits is not None:
|
|
93
|
+
result.estimated_total_hits -= len(result.hits) - len(valid_hits)
|
|
94
|
+
|
|
95
|
+
result.hits = valid_hits
|
|
96
|
+
return result
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .competitions_facet_distribution import CompetitionsFacetDistribution
|
|
4
|
+
from .competitions_facet_stats import CompetitionsFacetStats
|
|
5
|
+
from .competitions_hit import CompetitionsHit
|
|
6
|
+
from .multi_search_results import MultiSearchResult
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class CompetitionsMultiSearchResult(
|
|
10
|
+
MultiSearchResult[
|
|
11
|
+
CompetitionsHit, CompetitionsFacetDistribution, CompetitionsFacetStats
|
|
12
|
+
]
|
|
13
|
+
):
|
|
14
|
+
"""MultiSearchResult for Competitions."""
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .engagements_facet_distribution import EngagementsFacetDistribution
|
|
4
|
+
from .engagements_facet_stats import EngagementsFacetStats
|
|
5
|
+
from .engagements_hit import EngagementsHit
|
|
6
|
+
from .multi_search_results import MultiSearchResult
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class EngagementsMultiSearchResult(
|
|
10
|
+
MultiSearchResult[
|
|
11
|
+
EngagementsHit, EngagementsFacetDistribution, EngagementsFacetStats
|
|
12
|
+
]
|
|
13
|
+
):
|
|
14
|
+
"""MultiSearchResult for Engagements."""
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .formations_facet_distribution import FormationsFacetDistribution
|
|
4
|
+
from .formations_facet_stats import FormationsFacetStats
|
|
5
|
+
from .formations_hit import FormationsHit
|
|
6
|
+
from .multi_search_results import MultiSearchResult
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class FormationsMultiSearchResult(
|
|
10
|
+
MultiSearchResult[FormationsHit, FormationsFacetDistribution, FormationsFacetStats]
|
|
11
|
+
):
|
|
12
|
+
"""MultiSearchResult for Formations."""
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .multi_search_results import MultiSearchResult
|
|
4
|
+
from .organismes_facet_distribution import OrganismesFacetDistribution
|
|
5
|
+
from .organismes_facet_stats import OrganismesFacetStats
|
|
6
|
+
from .organismes_hit import OrganismesHit
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class OrganismesMultiSearchResult(
|
|
10
|
+
MultiSearchResult[OrganismesHit, OrganismesFacetDistribution, OrganismesFacetStats]
|
|
11
|
+
):
|
|
12
|
+
"""MultiSearchResult for Organismes."""
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .multi_search_results import MultiSearchResult
|
|
4
|
+
from .pratiques_facet_distribution import PratiquesFacetDistribution
|
|
5
|
+
from .pratiques_facet_stats import PratiquesFacetStats
|
|
6
|
+
from .pratiques_hit import PratiquesHit
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class PratiquesMultiSearchResult(
|
|
10
|
+
MultiSearchResult[PratiquesHit, PratiquesFacetDistribution, PratiquesFacetStats]
|
|
11
|
+
):
|
|
12
|
+
"""MultiSearchResult for Pratiques."""
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .multi_search_results import MultiSearchResult
|
|
4
|
+
from .rencontres_facet_distribution import RencontresFacetDistribution
|
|
5
|
+
from .rencontres_facet_stats import RencontresFacetStats
|
|
6
|
+
from .rencontres_hit import RencontresHit
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class RencontresMultiSearchResult(
|
|
10
|
+
MultiSearchResult[RencontresHit, RencontresFacetDistribution, RencontresFacetStats]
|
|
11
|
+
):
|
|
12
|
+
"""MultiSearchResult for Rencontres."""
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .multi_search_results import MultiSearchResult
|
|
4
|
+
from .salles_facet_distribution import SallesFacetDistribution
|
|
5
|
+
from .salles_facet_stats import SallesFacetStats
|
|
6
|
+
from .salles_hit import SallesHit
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SallesMultiSearchResult(
|
|
10
|
+
MultiSearchResult[SallesHit, SallesFacetDistribution, SallesFacetStats]
|
|
11
|
+
):
|
|
12
|
+
"""MultiSearchResult for Salles."""
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .multi_search_results import MultiSearchResult
|
|
4
|
+
from .terrains_facet_distribution import TerrainsFacetDistribution
|
|
5
|
+
from .terrains_facet_stats import TerrainsFacetStats
|
|
6
|
+
from .terrains_hit import TerrainsHit
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TerrainsMultiSearchResult(
|
|
10
|
+
MultiSearchResult[TerrainsHit, TerrainsFacetDistribution, TerrainsFacetStats]
|
|
11
|
+
):
|
|
12
|
+
"""MultiSearchResult for Terrains."""
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from .multi_search_results import MultiSearchResult
|
|
4
|
+
from .tournois_facet_distribution import TournoisFacetDistribution
|
|
5
|
+
from .tournois_facet_stats import TournoisFacetStats
|
|
6
|
+
from .tournois_hit import TournoisHit
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TournoisMultiSearchResult(
|
|
10
|
+
MultiSearchResult[TournoisHit, TournoisFacetDistribution, TournoisFacetStats]
|
|
11
|
+
):
|
|
12
|
+
"""MultiSearchResult for Tournois."""
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any, Generic, TypeVar, get_args
|
|
5
|
+
|
|
6
|
+
from ..utils.converter_utils import (
|
|
7
|
+
from_int,
|
|
8
|
+
from_list,
|
|
9
|
+
from_str,
|
|
10
|
+
)
|
|
11
|
+
from .facet_distribution import FacetDistribution
|
|
12
|
+
from .facet_stats import FacetStats
|
|
13
|
+
from .hit import Hit
|
|
14
|
+
|
|
15
|
+
HitType = TypeVar("HitType", bound=Hit)
|
|
16
|
+
FacetDistributionType = TypeVar("FacetDistributionType", bound=FacetDistribution)
|
|
17
|
+
FacetStatsType = TypeVar("FacetStatsType", bound=FacetStats)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class MultiSearchResult(Generic[HitType, FacetDistributionType, FacetStatsType]):
|
|
22
|
+
index_uid: str | None = None
|
|
23
|
+
hits: list[HitType] | None = None
|
|
24
|
+
query: str | None = None
|
|
25
|
+
processing_time_ms: int | None = None
|
|
26
|
+
limit: int | None = None
|
|
27
|
+
offset: int | None = None
|
|
28
|
+
estimated_total_hits: int | None = None
|
|
29
|
+
facet_distribution: FacetDistributionType | None = None
|
|
30
|
+
facet_stats: FacetStatsType | None = None
|
|
31
|
+
|
|
32
|
+
@classmethod
|
|
33
|
+
def from_dict(
|
|
34
|
+
cls,
|
|
35
|
+
obj: Any,
|
|
36
|
+
) -> MultiSearchResult[HitType, FacetDistributionType, FacetStatsType]:
|
|
37
|
+
"""
|
|
38
|
+
Parse dict into the concrete MultiSearchResult subclass.
|
|
39
|
+
Types are extracted from the class's generic parameters.
|
|
40
|
+
"""
|
|
41
|
+
assert isinstance(obj, dict)
|
|
42
|
+
|
|
43
|
+
# Extract generic type arguments from class definition
|
|
44
|
+
# e.g., OrganismesMultiSearchResult inherits from
|
|
45
|
+
# MultiSearchResult[OrganismesHit, OrganismesFacetDistribution, OrganismesFacetStats]
|
|
46
|
+
orig_bases = getattr(cls, "__orig_bases__", ())
|
|
47
|
+
if not orig_bases:
|
|
48
|
+
raise TypeError(f"{cls.__name__} must be a generic subclass")
|
|
49
|
+
type_args = get_args(orig_bases[0])
|
|
50
|
+
hit_type: type[HitType] = type_args[0]
|
|
51
|
+
facet_distribution_type: type[FacetDistributionType] = type_args[1]
|
|
52
|
+
facet_stats_type: type[FacetStatsType] = type_args[2]
|
|
53
|
+
|
|
54
|
+
index_uid = from_str(obj, "indexUid")
|
|
55
|
+
hits = from_list(hit_type.from_dict, obj, "hits")
|
|
56
|
+
query = from_str(obj, "query")
|
|
57
|
+
processing_time_ms = from_int(obj, "processingTimeMs")
|
|
58
|
+
limit = from_int(obj, "limit")
|
|
59
|
+
offset = from_int(obj, "offset")
|
|
60
|
+
estimated_total_hits = from_int(obj, "estimatedTotalHits")
|
|
61
|
+
fd_val = obj.get("facetDistribution")
|
|
62
|
+
facet_distribution = (
|
|
63
|
+
facet_distribution_type.from_dict(fd_val)
|
|
64
|
+
if isinstance(fd_val, dict)
|
|
65
|
+
else None
|
|
66
|
+
)
|
|
67
|
+
fs_val = obj.get("facetStats")
|
|
68
|
+
facet_stats = (
|
|
69
|
+
facet_stats_type.from_dict(fs_val) if isinstance(fs_val, dict) else None
|
|
70
|
+
)
|
|
71
|
+
return cls(
|
|
72
|
+
index_uid=index_uid,
|
|
73
|
+
hits=hits, # type: ignore[arg-type] # from_dict returns Hit base type
|
|
74
|
+
query=query,
|
|
75
|
+
processing_time_ms=processing_time_ms,
|
|
76
|
+
limit=limit,
|
|
77
|
+
offset=offset,
|
|
78
|
+
estimated_total_hits=estimated_total_hits,
|
|
79
|
+
facet_distribution=facet_distribution, # type: ignore[arg-type] # dynamic type from generics
|
|
80
|
+
facet_stats=facet_stats, # type: ignore[arg-type] # dynamic type from generics
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
def to_dict(self) -> dict:
|
|
84
|
+
result: dict = {}
|
|
85
|
+
if self.index_uid is not None:
|
|
86
|
+
result["indexUid"] = self.index_uid
|
|
87
|
+
if self.hits is not None:
|
|
88
|
+
result["hits"] = [hit.to_dict() for hit in self.hits]
|
|
89
|
+
if self.query is not None:
|
|
90
|
+
result["query"] = self.query
|
|
91
|
+
if self.processing_time_ms is not None:
|
|
92
|
+
result["processingTimeMs"] = self.processing_time_ms
|
|
93
|
+
if self.limit is not None:
|
|
94
|
+
result["limit"] = self.limit
|
|
95
|
+
if self.offset is not None:
|
|
96
|
+
result["offset"] = self.offset
|
|
97
|
+
if self.estimated_total_hits is not None:
|
|
98
|
+
result["estimatedTotalHits"] = self.estimated_total_hits
|
|
99
|
+
if self.facet_distribution is not None:
|
|
100
|
+
result["facetDistribution"] = self.facet_distribution.to_dict()
|
|
101
|
+
if self.facet_stats is not None:
|
|
102
|
+
result["facetStats"] = self.facet_stats.to_dict()
|
|
103
|
+
return result
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from ..config import (
|
|
8
|
+
MEILISEARCH_INDEX_COMPETITIONS,
|
|
9
|
+
MEILISEARCH_INDEX_ENGAGEMENTS,
|
|
10
|
+
MEILISEARCH_INDEX_FORMATIONS,
|
|
11
|
+
MEILISEARCH_INDEX_GALERIES,
|
|
12
|
+
MEILISEARCH_INDEX_NEWS,
|
|
13
|
+
MEILISEARCH_INDEX_ORGANISMES,
|
|
14
|
+
MEILISEARCH_INDEX_PRATIQUES,
|
|
15
|
+
MEILISEARCH_INDEX_RENCONTRES,
|
|
16
|
+
MEILISEARCH_INDEX_RSS,
|
|
17
|
+
MEILISEARCH_INDEX_SALLES,
|
|
18
|
+
MEILISEARCH_INDEX_TERRAINS,
|
|
19
|
+
MEILISEARCH_INDEX_TOURNOIS,
|
|
20
|
+
MEILISEARCH_INDEX_UIDS,
|
|
21
|
+
MEILISEARCH_INDEX_YOUTUBE_VIDEOS,
|
|
22
|
+
)
|
|
23
|
+
from .generic_search import (
|
|
24
|
+
GaleriesMultiSearchResult,
|
|
25
|
+
NewsMultiSearchResult,
|
|
26
|
+
RssMultiSearchResult,
|
|
27
|
+
YoutubeVideosMultiSearchResult,
|
|
28
|
+
)
|
|
29
|
+
from .multi_search_result_competitions import CompetitionsMultiSearchResult
|
|
30
|
+
from .multi_search_result_engagements import EngagementsMultiSearchResult
|
|
31
|
+
from .multi_search_result_formations import FormationsMultiSearchResult
|
|
32
|
+
from .multi_search_result_organismes import OrganismesMultiSearchResult
|
|
33
|
+
from .multi_search_result_pratiques import PratiquesMultiSearchResult
|
|
34
|
+
from .multi_search_result_rencontres import RencontresMultiSearchResult
|
|
35
|
+
from .multi_search_result_salles import SallesMultiSearchResult
|
|
36
|
+
from .multi_search_result_terrains import TerrainsMultiSearchResult
|
|
37
|
+
from .multi_search_result_tournois import TournoisMultiSearchResult
|
|
38
|
+
from .multi_search_results import MultiSearchResult
|
|
39
|
+
|
|
40
|
+
# Re-export for backward compatibility
|
|
41
|
+
index_uids = MEILISEARCH_INDEX_UIDS
|
|
42
|
+
|
|
43
|
+
index_uids_converters: dict[str, Callable[[Any], MultiSearchResult[Any, Any, Any]]] = {
|
|
44
|
+
MEILISEARCH_INDEX_ORGANISMES: OrganismesMultiSearchResult.from_dict,
|
|
45
|
+
MEILISEARCH_INDEX_RENCONTRES: RencontresMultiSearchResult.from_dict,
|
|
46
|
+
MEILISEARCH_INDEX_TERRAINS: TerrainsMultiSearchResult.from_dict,
|
|
47
|
+
MEILISEARCH_INDEX_SALLES: SallesMultiSearchResult.from_dict,
|
|
48
|
+
MEILISEARCH_INDEX_TOURNOIS: TournoisMultiSearchResult.from_dict,
|
|
49
|
+
MEILISEARCH_INDEX_COMPETITIONS: CompetitionsMultiSearchResult.from_dict,
|
|
50
|
+
MEILISEARCH_INDEX_PRATIQUES: PratiquesMultiSearchResult.from_dict,
|
|
51
|
+
MEILISEARCH_INDEX_ENGAGEMENTS: EngagementsMultiSearchResult.from_dict,
|
|
52
|
+
MEILISEARCH_INDEX_FORMATIONS: FormationsMultiSearchResult.from_dict,
|
|
53
|
+
MEILISEARCH_INDEX_NEWS: NewsMultiSearchResult.from_dict,
|
|
54
|
+
MEILISEARCH_INDEX_YOUTUBE_VIDEOS: YoutubeVideosMultiSearchResult.from_dict,
|
|
55
|
+
MEILISEARCH_INDEX_RSS: RssMultiSearchResult.from_dict,
|
|
56
|
+
MEILISEARCH_INDEX_GALERIES: GaleriesMultiSearchResult.from_dict,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def result_from_list(s: list[Any]) -> list[MultiSearchResult[Any, Any, Any]]:
|
|
61
|
+
results: list[MultiSearchResult[Any, Any, Any]] = []
|
|
62
|
+
|
|
63
|
+
if s:
|
|
64
|
+
for element in s:
|
|
65
|
+
try:
|
|
66
|
+
index_uid = element["indexUid"]
|
|
67
|
+
from_dict_func = index_uids_converters[index_uid]
|
|
68
|
+
result = from_dict_func(element)
|
|
69
|
+
results.append(result)
|
|
70
|
+
except (KeyError, TypeError, ValueError, AssertionError):
|
|
71
|
+
# Skip invalid or unsupported index results
|
|
72
|
+
pass
|
|
73
|
+
|
|
74
|
+
return results
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@dataclass
|
|
78
|
+
class MultiSearchResults:
|
|
79
|
+
results: list[MultiSearchResult[Any, Any, Any]] | None = None
|
|
80
|
+
|
|
81
|
+
@staticmethod
|
|
82
|
+
def from_dict(obj: Any) -> MultiSearchResults:
|
|
83
|
+
assert isinstance(obj, dict)
|
|
84
|
+
results_raw = obj.get("results")
|
|
85
|
+
results = result_from_list(results_raw) if results_raw is not None else None
|
|
86
|
+
return MultiSearchResults(results=results)
|
|
87
|
+
|
|
88
|
+
def to_dict(self) -> dict:
|
|
89
|
+
result: dict = {}
|
|
90
|
+
if self.results is not None:
|
|
91
|
+
result["results"] = [r.to_dict() for r in self.results]
|
|
92
|
+
return result
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def multi_search_results_from_dict(s: Any) -> MultiSearchResults:
|
|
96
|
+
return MultiSearchResults.from_dict(s)
|
|
@@ -0,0 +1,57 @@
|
|
|
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_bool,
|
|
9
|
+
from_datetime,
|
|
10
|
+
from_enum,
|
|
11
|
+
from_str,
|
|
12
|
+
)
|
|
13
|
+
from .code import Code
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class NatureSol:
|
|
18
|
+
code: Code | None = None
|
|
19
|
+
date_created: datetime | None = None
|
|
20
|
+
date_updated: datetime | None = None
|
|
21
|
+
id: str | None = None
|
|
22
|
+
libelle: str | None = None
|
|
23
|
+
terrain: bool | None = None
|
|
24
|
+
|
|
25
|
+
@staticmethod
|
|
26
|
+
def from_dict(obj: Any) -> NatureSol:
|
|
27
|
+
assert isinstance(obj, dict)
|
|
28
|
+
code = from_enum(Code, obj, "code")
|
|
29
|
+
date_created = from_datetime(obj, "date_created")
|
|
30
|
+
date_updated = from_datetime(obj, "date_updated")
|
|
31
|
+
id = from_str(obj, "id")
|
|
32
|
+
libelle = from_str(obj, "libelle")
|
|
33
|
+
terrain = from_bool(obj, "terrain")
|
|
34
|
+
return NatureSol(
|
|
35
|
+
code=code,
|
|
36
|
+
date_created=date_created,
|
|
37
|
+
date_updated=date_updated,
|
|
38
|
+
id=id,
|
|
39
|
+
libelle=libelle,
|
|
40
|
+
terrain=terrain,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
def to_dict(self) -> dict:
|
|
44
|
+
result: dict = {}
|
|
45
|
+
if self.code is not None:
|
|
46
|
+
result["code"] = self.code.value
|
|
47
|
+
if self.date_created is not None:
|
|
48
|
+
result["date_created"] = self.date_created.isoformat()
|
|
49
|
+
if self.date_updated is not None:
|
|
50
|
+
result["date_updated"] = self.date_updated.isoformat()
|
|
51
|
+
if self.id is not None:
|
|
52
|
+
result["id"] = self.id
|
|
53
|
+
if self.libelle is not None:
|
|
54
|
+
result["libelle"] = self.libelle
|
|
55
|
+
if self.terrain is not None:
|
|
56
|
+
result["terrain"] = str(self.terrain).lower()
|
|
57
|
+
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 NiveauClass:
|
|
11
|
+
départemental: int | None = None
|
|
12
|
+
régional: int | None = None
|
|
13
|
+
|
|
14
|
+
@staticmethod
|
|
15
|
+
def from_dict(obj: Any) -> NiveauClass:
|
|
16
|
+
assert isinstance(obj, dict)
|
|
17
|
+
départemental = from_int(obj, "Départemental")
|
|
18
|
+
régional = from_int(obj, "Régional")
|
|
19
|
+
return NiveauClass(départemental=départemental, régional=régional)
|
|
20
|
+
|
|
21
|
+
def to_dict(self) -> dict:
|
|
22
|
+
result: dict = {}
|
|
23
|
+
if self.départemental is not None:
|
|
24
|
+
result["Départemental"] = self.départemental
|
|
25
|
+
if self.régional is not None:
|
|
26
|
+
result["Régional"] = self.régional
|
|
27
|
+
return result
|