diff --git a/apps/geocoder/src/parser.py b/apps/geocoder/src/parser.py index 22020c6..9cf9333 100644 --- a/apps/geocoder/src/parser.py +++ b/apps/geocoder/src/parser.py @@ -197,9 +197,18 @@ def build_fallback_queries(location_raw: str, country_code: str | None) -> list[ seen.add(q) result.append(q) + # Le code pays doit être cherché comme MOT ENTIER, pas comme sous-chaîne. + # `"DE" in "DRESDEN"` est vrai : le pays était donc considéré comme déjà + # présent, et la variante « ville, pays » se retrouvait reléguée APRÈS la + # ville nue. Or le worker s'arrête au premier résultat fiable — il + # interrogeait donc Geoapify sans aucun contexte pays, précisément sur les + # noms ambigus (il existe un Dresden dans l'Ohio). Le cas touchait environ + # une ville européenne sur quatre : Dresden/Dessau/Detmold (DE), + # Fresnes/Fréjus (FR), Notodden/Nordfjord (NO), Cáceres/Torres (ES)… + tokens = set(re.findall(r"[A-Za-z]+", location_raw.upper())) has_country = bool(country_name) and ( country_name.lower() in location_raw.lower() - or (country_code and country_code.upper() in location_raw.upper()) + or (country_code and country_code.upper() in tokens) ) # Requête complète + pays (si pays pas déjà dans le texte) diff --git a/apps/geocoder/tests/test_parser.py b/apps/geocoder/tests/test_parser.py index 8abaa64..28eb52d 100644 --- a/apps/geocoder/tests/test_parser.py +++ b/apps/geocoder/tests/test_parser.py @@ -132,6 +132,30 @@ class TestBuildFallbackQueries: queries = build_fallback_queries("Bergen, Norway", "NO") assert not any(q.count("Norway") > 1 for q in queries) + @pytest.mark.parametrize( + ("ville", "code", "pays"), + [ + ("Dresden", "DE", "Germany"), # "DE" est une sous-chaîne de "DRESDEN" + ("Dessau", "DE", "Germany"), + ("Fresnes", "FR", "France"), + ("Notodden", "NO", "Norway"), + ("Torres", "ES", "Spain"), + ], + ) + def test_le_contexte_pays_passe_en_premier(self, ville, code, pays): + # Le worker s'arrête au PREMIER résultat fiable : l'ordre est la seule + # chose qui compte. Un code pays contenu par hasard dans le nom de la + # ville faisait passer la requête nue devant, supprimant toute + # désambiguïsation là où elle était le plus nécessaire. + assert build_fallback_queries(ville, code)[0] == f"{ville}, {pays}" + + def test_le_code_pays_reellement_present_reste_prioritaire(self): + # Contrepartie : quand le code EST un mot du texte, le texte d'origine + # passe en premier — on ne le double pas d'un contexte redondant. La + # forme « ville, pays » reste en dernier recours, ce qui est voulu. + queries = build_fallback_queries("Berlin, DE", "DE") + assert queries[0] == "Berlin, DE" + def test_pays_inconnu_ne_plante_pas(self): assert build_fallback_queries("Bergen", "ZZ") == ["Bergen"] assert build_fallback_queries("Bergen", None) == ["Bergen"]