SPB Git forge

spb/job-ka

Public
229commits 1branches 0releases
38.1 MBsize
maindefault branch
4 h agolast push
HTML 82.1% Python 14.6% TypeScript 1.9% CSS 1% JavaScript 0.5%
3.3 KB · 88 lines python
Raw Blame History
1# =============================================================================2# Job·Ka — Groupe KA3# Auteur  : Simon-Pierre Boucher4# Contact : contact@spboucher.ai5# Fichier : jobka/regions.py6# Rôle    : Région administrative du Québec (17 régions) depuis la ville —7#           répertoire MAMH embarqué (data/regions-qc.json) + arrondissements8# Créé    : 2026-08-19   Modifié : 2026-08-199# =============================================================================10"""Dérivation de la région administrative (17 régions du Québec).1112Source : Répertoire des municipalités du MAMH (données ouvertes, colonne13`regadm`), figé dans ``data/regions-qc.json`` (~1 260 entrées : municipalités14+ arrondissements/quartiers fréquents dans les libellés d'offres). Clé de15recherche : nom de ville minuscules sans accents. Ville inconnue -> "" —16jamais de région inventée.17"""18from __future__ import annotations1920import json21from functools import lru_cache22from pathlib import Path2324from .normalize import canonical_city, strip_accents2526_DATA_PATH = Path(__file__).resolve().parent.parent / "data" / "regions-qc.json"2728# Les 17 régions administratives (référence pour validation/affichage)29REGIONS_QC = (30    "Abitibi-Témiscamingue", "Bas-Saint-Laurent", "Capitale-Nationale",31    "Centre-du-Québec", "Chaudière-Appalaches", "Côte-Nord", "Estrie",32    "Gaspésie–Îles-de-la-Madeleine", "Lanaudière", "Laurentides", "Laval",33    "Mauricie", "Montérégie", "Montréal", "Nord-du-Québec", "Outaouais",34    "Saguenay–Lac-Saint-Jean",35)363738@lru_cache(maxsize=1)39def _mapping() -> dict[str, str]:40    try:41        return json.loads(_DATA_PATH.read_text(encoding="utf-8"))42    except (OSError, ValueError):43        return {}444546def _key(city: str) -> str:47    return " ".join(strip_accents((city or "").lower()).split())484950def city_from_slug_tokens(tokens: list[str]) -> str:51    """Plus long préfixe de `tokens` (segments d'un slug d'URL) qui forme une52    municipalité québécoise connue — résout « Pointe-Claire-Analyste-… » où53    ville et titre partagent le même séparateur « - ». Retourne la ville54    reconstituée (« Pointe-Claire »), ou "" si aucun préfixe ne correspond.55    """56    from .normalize import _QC_CITIES  # table des libellés fréquents57    table = _mapping()58    for n in range(min(len(tokens), 5), 0, -1):59        raw = "-".join(t for t in tokens[:n] if t)60        k = _key(raw)61        k2 = k.replace("st-", "saint-").replace("ste-", "sainte-")62        if k in table or k2 in table or k in _QC_CITIES or k2 in _QC_CITIES:63            return raw64    return ""656667def region_for_city(city: str) -> str:68    """Ville -> région administrative (« Montérégie »…), ou "" si inconnue.6970    La ville est d'abord canonicalisée (« Quebec City » -> « Québec ») ; les71    préfixes de type « Ville de » sont tolérés.72    """73    if not city:74        return ""75    table = _mapping()76    for candidate in (canonical_city(city), city):77        k = _key(candidate)78        if not k:79            continue80        if k in table:81            return table[k]82        # « ville de sherbrooke », « st-jerome » (st- = saint-)83        k2 = k.removeprefix("ville de ").replace("st-", "saint-") \84              .replace("ste-", "sainte-")85        if k2 in table:86            return table[k2]87    return ""88