From 4bfa6409e5e0a89046716e55362ff30d3d2c9aa8 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Fri, 19 Dec 2025 15:02:21 +0000 Subject: [PATCH 01/92] typo meteo + link broken --- source/projects/meteo/tutorial.qmd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/projects/meteo/tutorial.qmd b/source/projects/meteo/tutorial.qmd index 0c367535..f5fbdb74 100644 --- a/source/projects/meteo/tutorial.qmd +++ b/source/projects/meteo/tutorial.qmd @@ -30,11 +30,11 @@ import solutions L'API de prédiction d'open-meteo prend en entrée les coordonnées géographiques (latitude, longitude) du lieu où seront réalisées les prédictions. On pourrait récupérer manuellement les coordonnées du lieu qui nous intéresse, mais cela limiterait la reproductibilité de nos analyses avec d'autres lieux que celui choisi. On va donc utiliser une seconde API, `Nominatim`, pour obtenir ces coordonnées pour un lieu donné. -Lorsque l'on travaille à partir d'une API, la première étape est toujours de lire sa documentation. C'est elle qui indique à quelle adresse nous devons envoyer nos requêtes, sous quel format, et ce que va nous répondre l'API. Dans notre cas, la docuemntation de `Nominatim` se trouve à [cette adresse](https://nominatim.org/release-docs/develop/api/Overview/). N'hésitez pas à la parcourir rapidement pour évaluer les possibilités de l'API. +Lorsque l'on travaille à partir d'une API, la première étape est toujours de lire sa documentation. C'est elle qui indique à quelle adresse nous devons envoyer nos requêtes, sous quel format, et ce que va nous répondre l'API. Dans notre cas, la documentation de `Nominatim` se trouve à [cette adresse](https://nominatim.org/release-docs/develop/api/Overview/). N'hésitez pas à la parcourir rapidement pour évaluer les possibilités de l'API. ### Question 1 -La première caractéristique essentielle d'une API est le *endpoint*, c'est à dire l'URL à laquelle on va envoyer des requêtes. Dans notre cas, on va utiliser le *endpoint* `/search` dans la mesure où l'on veut trouver un objet géographique (des coordonnées) à partir d'un nom de localisation. La [page de documentation]([/search](https://nominatim.org/release-docs/develop/api/Search/)) associée à ce *endpoint* nous donne toutes les informations dont nous avons besoin : +La première caractéristique essentielle d'une API est le *endpoint*, c'est à dire l'URL à laquelle on va envoyer des requêtes. Dans notre cas, on va utiliser le *endpoint* `/search` dans la mesure où l'on veut trouver un objet géographique (des coordonnées) à partir d'un nom de localisation. La [page de documentation](https://nominatim.org/release-docs/develop/api/Search/) associée à ce *endpoint* nous donne toutes les informations dont nous avons besoin : - le format d'une requête est `https://nominatim.openstreetmap.org/search?` où `` doit être remplacé par les paramètres de la requête, séparés par le symbole `&` - dans la section [Structured Query](https://nominatim.org/release-docs/develop/api/Search/#structured-query), on voit que l'API admet comme paramètres `country` (pays) et `city` (ville), que l'on va utiliser pour paramétrer notre requête. From b5e480e7c7f1fff2f2dc7e31176af8a18188034c Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 24 Dec 2025 10:37:37 +0000 Subject: [PATCH 02/92] Q3 : correction counting total rows --- source/projects/RP/solutions.py | 1 + 1 file changed, 1 insertion(+) diff --git a/source/projects/RP/solutions.py b/source/projects/RP/solutions.py index bbc68b91..e83f687d 100644 --- a/source/projects/RP/solutions.py +++ b/source/projects/RP/solutions.py @@ -80,6 +80,7 @@ def plot_population_by_gender_per_department(df, department_code): # Filter out the total population rows df = df[df["genre"] != "Ensemble"] + df = df[df["age"] != "Total"] # Create a pivot table with population values by year and gender df_pivot = df.pivot_table( From 0e6f72d619d5c568ca0ef057f7af7c5d1a373526 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Mon, 5 Jan 2026 10:40:23 +0000 Subject: [PATCH 03/92] fix link to BAN API issue #30 --- .../manipulation/csv-json-files/tutorial.qmd | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/source/manipulation/csv-json-files/tutorial.qmd b/source/manipulation/csv-json-files/tutorial.qmd index dda963d2..5e72f34d 100644 --- a/source/manipulation/csv-json-files/tutorial.qmd +++ b/source/manipulation/csv-json-files/tutorial.qmd @@ -60,7 +60,7 @@ rows[:4] On retrouve bien la même syntaxe que pour les fichiers texte simples : une fois le `reader` créé, on peut itérer sur les lignes et réaliser des opérations avec celles-ci ; par exemple, les stocker dans une liste comme ci-dessus. -Lorsqu'on a un fichier CSV avec des noms de colonne comme dans notre cas, il est intéressant de les utiliser pour manipuler la donnée nommée, plutôt que par position en utilisant une liste simple. On utilise pour cela un `DictReader` au lieu du `reader`. A présent, lorsqu'on itère sur l'objet `DictReader` créé, chaque ligne est un dictionnaire, donc la clé est le nom de la colonne et la valeur la donnée de la cellule. +Lorsqu'on a un fichier CSV avec des noms de colonne comme dans notre cas, il est intéressant de les utiliser pour manipuler la donnée nommée, plutôt que par position en utilisant une liste simple. On utilise pour cela un `DictReader` au lieu du `reader`. A présent, lorsqu'on itère sur l'objet `DictReader` créé, chaque ligne est un dictionnaire, donc la clé est le nom de la colonne et la valeur la donnée de la cellule. Pour illustrer son intérêt, affichons les noms des départements donc le numéro de département est compris entre 20 et 29. @@ -142,9 +142,9 @@ En pratique, comme pour l'encodage d'un fichier texte, **il y a peu de raison va ### Les fichiers JSON -Le JSON (*JavaScript Object Notation*) est un format de fichier très populaire pour écrire et échanger de la donnée sous la forme d'une chaîne de caractères unique et lisible par l'humain (*human-readable*) — du moins en théorie. +Le JSON (*JavaScript Object Notation*) est un format de fichier très populaire pour écrire et échanger de la donnée sous la forme d'une chaîne de caractères unique et lisible par l'humain (*human-readable*) — du moins en théorie. -Comme son nom le suggère, le JSON est lié au langage *JavaScript* dans la mesure où il constitue un dérivé de la notation des objets dans ce langage. Le format est cependant désormais indépendant de tout langage de programmation, mais est très fréquemment utilisé dans différents langages. +Comme son nom le suggère, le JSON est lié au langage *JavaScript* dans la mesure où il constitue un dérivé de la notation des objets dans ce langage. Le format est cependant désormais indépendant de tout langage de programmation, mais est très fréquemment utilisé dans différents langages. Le format JSON est particulièrement important pour les statisticiens et data scientists car il constitue le **format quasi-standard de réponse des [API](https://fr.wikipedia.org/wiki/Interface_de_programmation)**. Le dialogue avec les API va au delà du programme de ce cours d'introduction. Cependant, les API tendant à se généraliser comme mode de communication standard pour l'échange de données, il est important de maîtriser les bases du format JSON afin de manipuler les réponses des API lorsqu'on doit interagir avec celles-ci. @@ -171,7 +171,7 @@ On le voit : la représentation JSON est assez proche de celle du dictionnaire P ### Le module `json` -Le module `json` gère l'import de fichiers JSON et l'export d'objets Python au format JSON. Il s'occupe notamment de gérer les contraintes de conversion en JSON évoquées précédemment, comme celle des accents. +Le module `json` gère l'import de fichiers JSON et l'export d'objets Python au format JSON. Il s'occupe notamment de gérer les contraintes de conversion en JSON évoquées précédemment, comme celle des accents. En particulier, **le JSON peut stocker la majorité des types d'objets *built-in* de Python** que nous avons vus jusqu'à présent (*strings*, valeurs numériques, Booléens, listes, dictionnaires, `NoneType`) et bien d'autres, mais il ne peut pas représenter des objets Python créés manuellement via des classes par exemple. @@ -220,7 +220,7 @@ Reprenons le CV que nous avons sérialisé précédemment au format JSON pour il ```{python} with open("cv.json", "r") as file_in: data = json.load(file_in) - + data ``` @@ -233,7 +233,7 @@ import requests ``` ```{python} -response = requests.get("https://api-adresse.data.gouv.fr/search/?q=comedie&type=street") +response = requests.get("https://data.geopf.fr/geocodage/search?q=comedie&type=street") r_text = response.text print(r_text[:150]) ``` @@ -313,7 +313,7 @@ r_dict["features"][1] - 9/ La sérialisation d'un objet Python (sérialisable) consiste à convertir la donnée contenue dans cet objet en une séquence d'octets, c'est à dire en un message qui peut être compris par n'importe quel ordinateur. -- 10/ Ce sont des fichiers texte. +- 10/ Ce sont des fichiers texte. - 11/ Non, les fichiers JSON comme les fichiers CSV sont des fichiers texte. L'extension est une convention qui permet dans la grande majorité des cas de savoir ce que contient le fichier, mais elle ne peut pas le garantir. @@ -360,7 +360,7 @@ with open("data_sorted.json", "w") as file_out: Nous avons vu que les objets que l'on crée manuellement via des classes ne sont généralement pas sérialisables. La cellule suivante en montre un exemple avec notre objet `Citron` utilisé dans le tutoriel sur la POO. Essayer de convertir directement l'objet en JSON renvoie une erreur. -Vous devez modifier le code suivant afin de pouvoir sérialiser l'objet. Pour cela, vous devez : +Vous devez modifier le code suivant afin de pouvoir sérialiser l'objet. Pour cela, vous devez : - convertir l'instance `mon_citron` en utilisant la méthode *built-in* `__dict__` que possèdent tous les objets Python @@ -375,7 +375,7 @@ class Citron: self.saveur = "acide" self.couleur = couleur self.jus = qte_jus - + mon_citron = Citron(couleur="jaune", qte_jus=45) json.dumps(mon_citron) ``` @@ -399,7 +399,7 @@ class Citron: self.saveur = "acide" self.couleur = couleur self.jus = qte_jus - + mon_citron = Citron(couleur="jaune", qte_jus=45) mon_citron_dict = mon_citron.__dict__ @@ -413,7 +413,7 @@ json.dumps(mon_citron_dict) ### Changer le délimiteur d'un fichier CSV -Votre répertoire courant contient le fichier `nat2020.csv`. Il s'agit du fichier des prénoms diffusé par l'Insee : il contient des données sur les prénoms attribués aux enfants nés en France entre 1900 et 2020. +Votre répertoire courant contient le fichier `nat2020.csv`. Il s'agit du fichier des prénoms diffusé par l'Insee : il contient des données sur les prénoms attribués aux enfants nés en France entre 1900 et 2020. Problème : contrairement au standard CSV, le délimiteur utilisé n'est pas la virgule. Vous devez donc : @@ -443,7 +443,7 @@ with open('nat2020.csv', 'r') as file_in: writer = csv.writer(file_out) # Par défaut, le délimiteur est la virgule for row in reader: writer.writerow(row) - + # Vérification à l'aide d'une commande shell !head -n 3 nat2020_corr.csv ``` @@ -457,7 +457,7 @@ with open('nat2020.csv', 'r') as file_in: L'exercice consiste à effectuer une requête à l'API de la Base Adresse Nationale, et sauvegarder les résultats dans un fichier CSV. Voici les étapes à implémenter : -- effectuer une requête de nom de rue avec un mot clé comme dans le tutoriel (si vous souhaitez faire une requête plus complexe, vous pouvez regarder la [documentation de l'API](https://adresse.data.gouv.fr/api-doc/adresse)) et stocker les résultats dans un dictionnaire +- effectuer une requête de nom de rue avec un mot clé comme dans le tutoriel (si vous souhaitez faire une requête plus complexe, vous pouvez regarder la [documentation de l'API et son swagger](https://www.data.gouv.fr/dataservices/api-adresse-base-adresse-nationale-ban)) et stockxer les résultats dans un dictionnaire - créer un fichier CSV `resultats_ban.csv` dans lequel on va stocker les informations suivantes : 'nom', 'ville', 'code_commune', 'longitude', 'latitude' @@ -485,7 +485,7 @@ Rue de l’Ancienne Comedie,Poitiers,86194,0.342649,46.580457 Afficher la solution ```python -response = requests.get("https://api-adresse.data.gouv.fr/search/?q=comedie&type=street") +response = requests.get("https://data.geopf.fr/geocodage/search?q=comedie&type=street") r_text = response.text r_dict = json.loads(r_text) @@ -511,11 +511,11 @@ with open('resultats_ban.csv', 'w') as file_out: L'objectif de cet exercice est de découper le fichier CSV des départements que nous avons utilisé dans le tutoriel en plusieurs petits CSV, un par région. Ce type d'opération peut être utile par exemple lorsqu'on travaille avec un fichier de très grande taille, qui ne passe pas en mémoire ; le découper en plusieurs fichiers que l'on traite indépendamment, lorsque cela est possible, permet de réduire la volumétrie. -Voici la liste des opérations à effectuer : +Voici la liste des opérations à effectuer : - créer un dossier `dep` dans le répertoire courant à l'aide du module `pathlib` (cf. tutoriel précédent) -- avec un objet `reader` du module `csv`, faire une boucle sur les lignes du fichier CSV des départements. Attention à ne pas inclure le *header*, en utilisant la fonction `next` pour passer la première ligne. Pour chaque ligne suivante : +- avec un objet `reader` du module `csv`, faire une boucle sur les lignes du fichier CSV des départements. Attention à ne pas inclure le *header*, en utilisant la fonction `next` pour passer la première ligne. Pour chaque ligne suivante : - récupérer le code région (variable `REG`) @@ -819,7 +819,7 @@ Let's reuse the CV we serialized earlier into JSON format to illustrate reading ```{python} with open("cv.json", "r") as file_in: data = json.load(file_in) - + data ``` @@ -832,7 +832,7 @@ import requests ``` ```{python} -response = requests.get("https://api-adresse.data.gouv.fr/search/?q=comedie&type=street") +response = requests.get("https://data.geopf.fr/geocodage/search?q=comedie&type=street") r_text = response.text print(r_text[:150]) ``` @@ -948,7 +948,7 @@ class Citron: self.flavor = "acidic" self.color = color self.juice = juice_qty - + mon_citron = Citron(color="yellow", juice_qty=45) json.dumps(mon_citron) ``` @@ -971,7 +971,7 @@ class Citron: self.flavor = "acidic" self.color = color self.juice = juice_qty - + mon_citron = Citron(color="yellow", juice_qty=45) mon_citron_dict = mon_citron.__dict__ @@ -1012,7 +1012,7 @@ with open('nat2020.csv', 'r') as file_in: writer = csv.writer(file_out) # By default, the delimiter is a comma for row in reader: writer.writerow(row) - + # Verify with a shell command !head -n 3 nat2020_corr.csv ``` @@ -1025,7 +1025,7 @@ with open('nat2020.csv', 'r') as file_in: The exercise is to make a request to the National Address Base API and save the results in a CSV file. Here are the steps to implement: -- Make a street name request with a keyword like in the tutorial (if you want to make a more complex request, you can check the [API documentation](https://adresse.data.gouv.fr/api-doc/adresse)) and store the results in a dictionary. +- Make a street name request with a keyword like in the tutorial (if you want to make a more complex request, you can check the [API documentation and its swagger](https://www.data.gouv.fr/dataservices/api-adresse-base-adresse-nationale-ban)) and store the results in a dictionary. - Create a CSV file `resultats_ban.csv` in which we will store the following information: 'name', 'city', 'city_code', 'longitude', 'latitude'. - Using a `writer` object and a loop on the results returned by the API, write each line to the CSV. @@ -1051,7 +1051,7 @@ Rue de l’Ancienne Comedie,Poitiers,86194,0.342649,46.580457 Show solution ```{python} -response = requests.get("https://api-adresse.data.gouv.fr/search/?q=comedie&type=street") +response = requests.get("https://data.geopf.fr/geocodage/search?q=comedie&type=street") r_text = response.text r_dict = json.loads(r_text) @@ -1165,4 +1165,4 @@ for path in dep_files_paths: ::: -::: \ No newline at end of file +::: From ed18c7e02c5ace779801727e8aab4ebdcf7f9258 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Mon, 5 Jan 2026 11:25:24 +0000 Subject: [PATCH 04/92] initialisation polars #31 --- source/manipulation/polars/data/communes.csv | 34996 ++++++++++++++++ .../polars/data/departement2021.csv | 102 + .../polars/data/departement2021.parquet | Bin 0 -> 9640 bytes .../polars/data/serie_glaces_metadonnees.csv | 15 + .../polars/data/serie_glaces_valeurs.csv | 205 + source/manipulation/polars/img/joins.png | Bin 0 -> 21090 bytes .../manipulation/polars/img/structure_df.png | Bin 0 -> 164895 bytes source/manipulation/polars/output/.gitignore | 2 + source/manipulation/polars/tutorial.qmd | 4173 ++ 9 files changed, 39493 insertions(+) create mode 100644 source/manipulation/polars/data/communes.csv create mode 100644 source/manipulation/polars/data/departement2021.csv create mode 100644 source/manipulation/polars/data/departement2021.parquet create mode 100644 source/manipulation/polars/data/serie_glaces_metadonnees.csv create mode 100644 source/manipulation/polars/data/serie_glaces_valeurs.csv create mode 100644 source/manipulation/polars/img/joins.png create mode 100644 source/manipulation/polars/img/structure_df.png create mode 100644 source/manipulation/polars/output/.gitignore create mode 100644 source/manipulation/polars/tutorial.qmd diff --git a/source/manipulation/polars/data/communes.csv b/source/manipulation/polars/data/communes.csv new file mode 100644 index 00000000..5e2194ae --- /dev/null +++ b/source/manipulation/polars/data/communes.csv @@ -0,0 +1,34996 @@ +DEPCOM;COM;PMUN;PCAP;PTOT +01001;L' Abergement-Clémenciat;776;18;794 +01002;L' Abergement-de-Varey;248;1;249 +01004;Ambérieu-en-Bugey;14035;393;14428 +01005;Ambérieux-en-Dombes;1689;34;1723 +01006;Ambléon;111;6;117 +01007;Ambronay;2726;115;2841 +01008;Ambutrix;752;15;767 +01009;Andert-et-Condon;330;9;339 +01010;Anglefort;1115;17;1132 +01011;Apremont;376;11;387 +01012;Aranc;326;4;330 +01013;Arandas;144;4;148 +01014;Arbent;3367;92;3459 +01016;Arbigny;463;5;468 +01015;Arboys en Bugey;644;17;661 +01017;Argis;442;16;458 +01019;Armix;28;1;29 +01021;Ars-sur-Formans;1408;30;1438 +01022;Artemare;1237;18;1255 +01453;Arvière-en-Valromey;713;22;735 +01023;Asnières-sur-Saône;66;0;66 +01024;Attignat;3211;64;3275 +01025;Bâgé-Dommartin;4092;108;4200 +01026;Bâgé-le-Châtel;923;60;983 +01027;Balan;2684;57;2741 +01028;Baneins;602;9;611 +01170;Béard-Géovreissiat;1051;28;1079 +01029;Beaupont;689;8;697 +01030;Beauregard;866;14;880 +01032;Béligneux;3333;29;3362 +01034;Belley;9103;396;9499 +01035;Belleydoux;314;8;322 +01031;Bellignat;3624;235;3859 +01037;Bénonces;298;4;302 +01038;Bény;756;21;777 +01039;Béon;454;8;462 +01040;Béréziat;496;5;501 +01041;Bettant;748;21;769 +01042;Bey;279;14;293 +01043;Beynost;4613;108;4721 +01044;Billiat;622;15;637 +01045;Birieux;283;4;287 +01046;Biziat;876;9;885 +01047;Blyes;1007;25;1032 +01245;Bohas-Meyriat-Rignat;913;21;934 +01049;La Boisse;3229;38;3267 +01050;Boissey;336;6;342 +01051;Bolozon;89;1;90 +01052;Bouligneux;328;6;334 +01053;Bourg-en-Bresse;41527;1779;43306 +01054;Bourg-Saint-Christophe;1366;29;1395 +01056;Boyeux-Saint-Jérôme;346;5;351 +01057;Boz;512;7;519 +01058;Brégnier-Cordon;839;13;852 +01060;Brénod;509;21;530 +01061;Brens;1166;27;1193 +01130;Bresse Vallons;2282;45;2327 +01062;Bressolles;911;20;931 +01063;Brion;521;7;528 +01064;Briord;1016;10;1026 +01065;Buellas;1782;63;1845 +01066;La Burbanche;77;1;78 +01067;Ceignes;254;13;267 +01068;Cerdon;783;14;797 +01069;Certines;1517;40;1557 +01071;Cessy;4856;116;4972 +01072;Ceyzériat;3157;61;3218 +01073;Ceyzérieu;1007;26;1033 +01074;Chalamont;2451;33;2484 +01075;Chaleins;1342;34;1376 +01076;Chaley;130;3;133 +01077;Challes-la-Montagne;194;3;197 +01078;Challex;1481;17;1498 +01079;Champagne-en-Valromey;820;31;851 +01080;Champdor-Corcelles;651;14;665 +01081;Champfromier;729;21;750 +01082;Chanay;625;14;639 +01083;Chaneins;910;15;925 +01084;Chanoz-Châtenay;844;17;861 +01085;La Chapelle-du-Châtelard;388;5;393 +01087;Charix;285;10;295 +01088;Charnoz-sur-Ain;913;27;940 +01089;Château-Gaillard;2138;49;2187 +01090;Châtenay;341;4;345 +01092;Châtillon-la-Palud;1584;68;1652 +01093;Châtillon-sur-Chalaronne;4859;201;5060 +01094;Chavannes-sur-Reyssouze;753;12;765 +01096;Chaveyriat;1008;29;1037 +01098;Chazey-Bons;1112;36;1148 +01099;Chazey-sur-Ain;1514;37;1551 +01100;Cheignieu-la-Balme;134;4;138 +01101;Chevillard;151;9;160 +01102;Chevroux;952;15;967 +01103;Chevry;1812;40;1852 +01104;Chézery-Forens;467;11;478 +01105;Civrieux;1680;56;1736 +01106;Cize;173;8;181 +01107;Cleyzieu;136;4;140 +01108;Coligny;1181;25;1206 +01109;Collonges;2219;46;2265 +01110;Colomieu;140;2;142 +01111;Conand;124;1;125 +01112;Condamine;411;37;448 +01113;Condeissiat;822;13;835 +01114;Confort;648;12;660 +01115;Confrançon;1336;29;1365 +01116;Contrevoz;499;11;510 +01117;Conzieu;148;2;150 +01118;Corbonod;1264;33;1297 +01121;Corlier;114;1;115 +01123;Cormoranche-sur-Saône;1138;37;1175 +01124;Cormoz;664;15;679 +01125;Corveissiat;621;13;634 +01127;Courmangoux;507;9;516 +01128;Courtes;313;2;315 +01129;Crans;266;4;270 +01133;Cressin-Rochefort;392;11;403 +01134;Crottet;1734;43;1777 +01135;Crozet;2138;63;2201 +01136;Cruzilles-lès-Mépillat;868;20;888 +01138;Culoz;3035;47;3082 +01139;Curciat-Dongalon;440;5;445 +01140;Curtafond;770;19;789 +01141;Cuzieu;448;15;463 +01142;Dagneux;4717;55;4772 +01143;Divonne-les-Bains;9644;234;9878 +01146;Dompierre-sur-Chalaronne;435;10;445 +01145;Dompierre-sur-Veyle;1166;21;1187 +01147;Domsure;486;3;489 +01148;Dortan;1846;44;1890 +01149;Douvres;1041;26;1067 +01150;Drom;216;5;221 +01151;Druillat;1159;19;1178 +01152;Échallon;757;20;777 +01153;Échenevex;2132;73;2205 +01155;Évosges;145;2;147 +01156;Faramans;806;12;818 +01157;Fareins;2204;42;2246 +01158;Farges;1038;11;1049 +01159;Feillens;3291;69;3360 +01160;Ferney-Voltaire;9766;162;9928 +01162;Flaxieu;68;3;71 +01163;Foissiat;2085;39;2124 +01165;Francheleins;1611;32;1643 +01166;Frans;2351;56;2407 +01167;Garnerans;647;25;672 +01169;Genouilleux;612;20;632 +01171;Géovreisset;874;43;917 +01173;Gex;13118;257;13375 +01174;Giron;183;4;187 +01175;Gorrevod;835;25;860 +01177;Grand-Corent;177;6;183 +01179;Grièges;1876;52;1928 +01180;Grilly;833;20;853 +01181;Groissiat;1229;52;1281 +01338;Groslée-Saint-Benoit;1193;36;1229 +01183;Guéreins;1452;25;1477 +01187;Haut Valromey;669;22;691 +01184;Hautecourt-Romanèche;777;20;797 +01188;Illiat;627;17;644 +01189;Injoux-Génissiat;1136;26;1162 +01190;Innimond;89;3;92 +01191;Izenave;156;4;160 +01192;Izernore;2247;62;2309 +01193;Izieu;235;7;242 +01194;Jassans-Riottier;6339;119;6458 +01195;Jasseron;1755;52;1807 +01196;Jayat;1182;12;1194 +01197;Journans;355;14;369 +01198;Joyeux;271;3;274 +01199;Jujurieux;2156;44;2200 +01200;Labalme;210;2;212 +01202;Lagnieu;7143;146;7289 +01203;Laiz;1212;39;1251 +01206;Lantenay;277;6;283 +01207;Lapeyrouse;316;12;328 +01208;Lavours;124;6;130 +01209;Léaz;739;15;754 +01210;Lélex;227;4;231 +01211;Lent;1405;34;1439 +01212;Lescheroux;735;8;743 +01213;Leyment;1303;29;1332 +01214;Leyssard;152;4;156 +01216;Lhuis;889;21;910 +01219;Lompnas;168;3;171 +01224;Loyettes;3146;30;3176 +01225;Lurcy;384;9;393 +01227;Magnieu;644;13;657 +01228;Maillat;635;13;648 +01229;Malafretaz;1216;24;1240 +01230;Mantenay-Montlin;313;7;320 +01231;Manziat;1963;49;2012 +01232;Marboz;2244;47;2291 +01233;Marchamp;131;3;134 +01234;Marignieu;172;3;175 +01235;Marlieux;1112;95;1207 +01236;Marsonnas;991;28;1019 +01237;Martignat;1654;66;1720 +01238;Massieux;2590;60;2650 +01239;Massignieu-de-Rives;614;14;628 +01240;Matafelon-Granges;641;17;658 +01241;Meillonnas;1335;33;1368 +01242;Mérignat;130;4;134 +01243;Messimy-sur-Saône;1224;32;1256 +01244;Meximieux;7743;128;7871 +01246;Mézériat;2172;37;2209 +01247;Mijoux;341;12;353 +01248;Mionnay;2100;47;2147 +01249;Miribel;9963;112;10075 +01250;Misérieux;1941;254;2195 +01252;Mogneneins;778;23;801 +01254;Montagnat;1992;48;2040 +01255;Montagnieu;622;12;634 +01257;Montanges;344;10;354 +01258;Montceaux;1195;36;1231 +01259;Montcet;691;15;706 +01260;Le Montellier;297;8;305 +01261;Monthieux;646;23;669 +01262;Montluel;6964;84;7048 +01263;Montmerle-sur-Saône;3793;66;3859 +01264;Montracol;1040;20;1060 +01265;Montréal-la-Cluse;3435;70;3505 +01266;Montrevel-en-Bresse;2489;42;2531 +01268;Murs-et-Gélignieux;252;4;256 +01269;Nantua;3446;138;3584 +01272;Neuville-les-Dames;1510;21;1531 +01273;Neuville-sur-Ain;1756;28;1784 +01274;Les Neyrolles;639;15;654 +01275;Neyron;2527;49;2576 +01276;Niévroz;1619;27;1646 +01095;Nivigne et Suran;814;11;825 +01277;Nivollet-Montgriffon;119;2;121 +01267;Nurieux-Volognat;1028;24;1052 +01279;Oncieu;89;6;95 +01280;Ordonnaz;141;1;142 +01281;Ornex;4410;165;4575 +01282;Outriaz;260;6;266 +01283;Oyonnax;22427;516;22943 +01284;Ozan;686;6;692 +01285;Parcieux;1206;29;1235 +01286;Parves et Nattages;942;38;980 +01288;Péron;2620;53;2673 +01289;Péronnas;6385;290;6675 +01290;Pérouges;1201;27;1228 +01291;Perrex;838;7;845 +01293;Peyriat;157;4;161 +01294;Peyrieu;873;15;888 +01295;Peyzieux-sur-Saône;661;13;674 +01296;Pirajoux;408;7;415 +01297;Pizay;820;14;834 +01298;Plagne;132;2;134 +01299;Le Plantay;564;9;573 +01185;Plateau d'Hauteville;4853;178;5031 +01204;Le Poizat-Lalleyriat;720;15;735 +01301;Polliat;2511;61;2572 +01302;Pollieu;159;6;165 +01303;Poncin;1703;35;1738 +01304;Pont-d'Ain;2964;29;2993 +01305;Pont-de-Vaux;2258;45;2303 +01306;Pont-de-Veyle;1625;65;1690 +01307;Port;849;20;869 +01308;Pougny;812;14;826 +01309;Pouillat;88;0;88 +01310;Prémeyzel;248;4;252 +01311;Prémillieu;45;0;45 +01313;Prévessin-Moëns;8233;198;8431 +01314;Priay;1729;34;1763 +01317;Ramasse;324;6;330 +01318;Rancé;727;17;744 +01319;Relevant;463;5;468 +01320;Replonges;3717;79;3796 +01321;Revonnas;905;29;934 +01322;Reyrieux;4797;132;4929 +01323;Reyssouze;980;13;993 +01325;Rignieux-le-Franc;971;17;988 +01328;Romans;590;4;594 +01329;Rossillon;151;6;157 +01330;Ruffieu;186;5;191 +01331;Saint-Alban;178;4;182 +01334;Saint-André-d'Huiriat;626;9;635 +01332;Saint-André-de-Bâgé;751;22;773 +01333;Saint-André-de-Corcy;3354;54;3408 +01335;Saint-André-le-Bouchoux;390;6;396 +01336;Saint-André-sur-Vieux-Jonc;1147;29;1176 +01337;Saint-Bénigne;1265;27;1292 +01339;Saint-Bernard;1433;42;1475 +01343;Saint-Cyr-sur-Menthon;1776;40;1816 +01345;Saint-Denis-en-Bugey;2309;27;2336 +01344;Saint-Denis-lès-Bourg;5747;161;5908 +01346;Saint-Didier-d'Aussiat;871;13;884 +01347;Saint-Didier-de-Formans;1960;69;2029 +01348;Saint-Didier-sur-Chalaronne;2875;63;2938 +01349;Saint-Éloi;456;5;461 +01350;Saint-Étienne-du-Bois;2448;37;2485 +01351;Saint-Étienne-sur-Chalaronne;1555;27;1582 +01352;Saint-Étienne-sur-Reyssouze;571;6;577 +01354;Saint-Genis-Pouilly;12544;181;12725 +01355;Saint-Genis-sur-Menthon;472;7;479 +01356;Saint-Georges-sur-Renon;214;5;219 +01357;Saint-Germain-de-Joux;501;5;506 +01358;Saint-Germain-les-Paroisses;434;3;437 +01359;Saint-Germain-sur-Renon;236;4;240 +01360;Saint-Jean-de-Gonville;1787;44;1831 +01361;Saint-Jean-de-Niost;1477;42;1519 +01362;Saint-Jean-de-Thurigneux;771;13;784 +01363;Saint-Jean-le-Vieux;1723;79;1802 +01364;Saint-Jean-sur-Reyssouze;744;7;751 +01365;Saint-Jean-sur-Veyle;1149;20;1169 +01367;Saint-Julien-sur-Reyssouze;749;4;753 +01368;Saint-Julien-sur-Veyle;817;15;832 +01369;Saint-Just;926;24;950 +01370;Saint-Laurent-sur-Saône;1722;27;1749 +01371;Saint-Marcel;1279;25;1304 +01372;Saint-Martin-de-Bavel;438;5;443 +01373;Saint-Martin-du-Frêne;1049;36;1085 +01374;Saint-Martin-du-Mont;1826;45;1871 +01375;Saint-Martin-le-Châtel;787;20;807 +01376;Saint-Maurice-de-Beynost;3967;39;4006 +01378;Saint-Maurice-de-Gourdans;2572;53;2625 +01379;Saint-Maurice-de-Rémens;756;9;765 +01380;Saint-Nizier-le-Bouchoux;680;12;692 +01381;Saint-Nizier-le-Désert;916;19;935 +01383;Saint-Paul-de-Varax;1529;20;1549 +01384;Saint-Rambert-en-Bugey;2269;33;2302 +01385;Saint-Rémy;994;23;1017 +01386;Saint-Sorlin-en-Bugey;1157;62;1219 +01387;Saint-Sulpice;257;4;261 +01388;Saint-Trivier-de-Courtes;1093;9;1102 +01389;Saint-Trivier-sur-Moignans;1799;41;1840 +01390;Saint-Vulbas;1286;20;1306 +01342;Sainte-Croix;570;8;578 +01353;Sainte-Euphémie;1667;28;1695 +01366;Sainte-Julie;1017;17;1034 +01382;Sainte-Olive;283;2;285 +01391;Salavre;272;9;281 +01392;Samognat;653;27;680 +01393;Sandrans;530;5;535 +01396;Sault-Brénaz;953;13;966 +01397;Sauverny;1009;21;1030 +01398;Savigneux;1351;16;1367 +01399;Ségny;2062;50;2112 +01400;Seillonnaz;137;3;140 +01401;Sergy;2084;40;2124 +01402;Sermoyer;668;20;688 +01403;Serrières-de-Briord;1264;18;1282 +01404;Serrières-sur-Ain;134;2;136 +01405;Servas;1247;28;1275 +01406;Servignat;175;1;176 +01407;Seyssel;999;18;1017 +01408;Simandre-sur-Suran;671;12;683 +01410;Sonthonnax-la-Montagne;312;7;319 +01411;Souclin;273;6;279 +01412;Sulignat;586;12;598 +01215;Surjoux-Lhopital;131;3;134 +01415;Talissieu;450;10;460 +01416;Tenay;1035;12;1047 +01418;Thil;1088;25;1113 +01419;Thoiry;6038;177;6215 +01420;Thoissey;1741;15;1756 +01421;Torcieu;726;16;742 +01422;Tossiat;1362;36;1398 +01423;Toussieux;1091;20;1111 +01424;Tramoyes;1681;43;1724 +01425;La Tranclière;286;7;293 +01427;Trévoux;6845;164;7009 +01426;Val-Revermont;2601;53;2654 +01428;Valeins;130;1;131 +01036;Valromey-sur-Séran;1311;18;1329 +01033;Valserhône;16423;381;16804 +01429;Vandeins;687;13;700 +01430;Varambon;584;14;598 +01431;Vaux-en-Bugey;1224;30;1254 +01432;Verjon;295;2;297 +01433;Vernoux;330;1;331 +01434;Versailleux;438;9;447 +01435;Versonnex;2176;70;2246 +01436;Vesancy;484;11;495 +01437;Vescours;241;5;246 +01439;Vésines;99;4;103 +01441;Vieu-d'Izenave;707;17;724 +01443;Villars-les-Dombes;4795;89;4884 +01444;Villebois;1173;17;1190 +01445;Villemotier;656;22;678 +01446;Villeneuve;1501;36;1537 +01447;Villereversure;1291;48;1339 +01448;Villes;376;8;384 +01449;Villette-sur-Ain;755;12;767 +01450;Villieu-Loyes-Mollon;3653;64;3717 +01451;Viriat;6418;148;6566 +01452;Virieu-le-Grand;1081;25;1106 +01454;Virignin;1097;21;1118 +01456;Vongnes;70;2;72 +01457;Vonnas;2961;58;3019 +02001;Abbécourt;498;8;506 +02002;Achery;598;8;606 +02003;Acy;1012;23;1035 +02004;Agnicourt-et-Séchelles;177;8;185 +02005;Aguilcourt;384;8;392 +02006;Aisonville-et-Bernoville;255;9;264 +02007;Aizelles;125;1;126 +02008;Aizy-Jouy;291;4;295 +02009;Alaincourt;543;6;549 +02010;Allemant;177;4;181 +02011;Ambleny;1155;54;1209 +02012;Ambrief;70;0;70 +02013;Amifontaine;404;9;413 +02014;Amigny-Rouy;744;14;758 +02015;Ancienville;75;0;75 +02016;Andelain;228;9;237 +02017;Anguilcourt-le-Sart;315;4;319 +02018;Anizy-le-Grand;2533;51;2584 +02019;Annois;364;5;369 +02020;Any-Martin-Rieux;456;4;460 +02021;Archon;87;3;90 +02022;Arcy-Sainte-Restitue;403;6;409 +02023;Armentières-sur-Ourcq;103;3;106 +02024;Arrancy;53;0;53 +02025;Artemps;371;2;373 +02027;Assis-sur-Serre;222;8;230 +02028;Athies-sous-Laon;2604;59;2663 +02029;Attilly;363;12;375 +02030;Aubencheul-aux-Bois;269;4;273 +02031;Aubenton;657;6;663 +02032;Aubigny-aux-Kaisnes;253;4;257 +02033;Aubigny-en-Laonnois;105;2;107 +02034;Audignicourt;118;4;122 +02035;Audigny;279;8;287 +02036;Augy;82;1;83 +02037;Aulnois-sous-Laon;1422;31;1453 +02038;Les Autels;57;0;57 +02039;Autremencourt;169;3;172 +02040;Autreppes;178;4;182 +02041;Autreville;814;13;827 +02042;Azy-sur-Marne;389;2;391 +02043;Bagneux;69;1;70 +02044;Bancigny;26;0;26 +02046;Barenton-Bugny;555;8;563 +02047;Barenton-Cel;114;6;120 +02048;Barenton-sur-Serre;134;4;138 +02049;Barisis-aux-Bois;740;12;752 +02050;Barzy-en-Thiérache;330;2;332 +02051;Barzy-sur-Marne;384;6;390 +02052;Bassoles-Aulers;139;6;145 +02054;Bazoches-sur-Vesles;460;4;464 +02055;Beaumé;92;2;94 +02056;Beaumont-en-Beine;177;1;178 +02057;Beaurevoir;1424;19;1443 +02058;Beaurieux;844;10;854 +02059;Beautor;2699;28;2727 +02060;Beauvois-en-Vermandois;268;7;275 +02061;Becquigny;250;7;257 +02062;Belleau;136;4;140 +02063;Bellenglise;381;9;390 +02064;Belleu;3810;51;3861 +02065;Bellicourt;602;12;614 +02066;Benay;204;2;206 +02067;Bergues-sur-Sambre;213;6;219 +02068;Berlancourt;103;5;108 +02069;Berlise;111;2;113 +02070;Bernot;452;12;464 +02071;Berny-Rivière;651;16;667 +02072;Berrieux;188;1;189 +02073;Berry-au-Bac;653;5;658 +02074;Bertaucourt-Epourdon;604;10;614 +02075;Berthenicourt;199;2;201 +02076;Bertricourt;162;3;165 +02077;Berzy-le-Sec;385;9;394 +02078;Besmé;160;2;162 +02079;Besmont;152;0;152 +02080;Besny-et-Loizy;350;10;360 +02081;Béthancourt-en-Vaux;440;8;448 +02082;Beugneux;111;0;111 +02083;Beuvardes;749;15;764 +02084;Bézu-le-Guéry;260;5;265 +02085;Bézu-Saint-Germain;1043;26;1069 +02086;Bichancourt;1048;10;1058 +02087;Bieuxy;30;1;31 +02088;Bièvres;88;3;91 +02089;Billy-sur-Aisne;1154;21;1175 +02090;Billy-sur-Ourcq;213;10;223 +02091;Blanzy-lès-Fismes;106;1;107 +02093;Blérancourt;1290;58;1348 +02094;Blesmes;447;9;456 +02095;Bohain-en-Vermandois;5664;90;5754 +02096;Bois-lès-Pargny;201;3;204 +02097;Boncourt;259;2;261 +02098;Bonneil;375;14;389 +02099;Bonnesvalyn;236;5;241 +02100;Bony;137;1;138 +02101;Bosmont-sur-Serre;193;5;198 +02102;Bouconville-Vauclair;187;6;193 +02103;Boué;1324;15;1339 +02104;Bouffignereux;102;4;106 +02105;Bouresches;202;5;207 +02106;Bourg-et-Comin;822;11;833 +02107;Bourguignon-sous-Coucy;103;4;107 +02108;Bourguignon-sous-Montbavin;158;4;162 +02109;La Bouteille;486;10;496 +02110;Braine;2213;25;2238 +02111;Brancourt-en-Laonnois;708;12;720 +02112;Brancourt-le-Grand;565;13;578 +02114;Brasles;1529;36;1565 +02117;Bray-Saint-Christophe;67;0;67 +02118;Braye;121;2;123 +02115;Braye-en-Laonnois;203;6;209 +02116;Braye-en-Thiérache;146;1;147 +02119;Brécy;340;7;347 +02120;Brenelle;195;4;199 +02121;Breny;244;4;248 +02122;Brie;53;2;55 +02123;Brissay-Choigny;303;6;309 +02124;Brissy-Hamégicourt;653;10;663 +02125;Brumetz;213;3;216 +02126;Brunehamel;456;5;461 +02128;Bruyères-et-Montbérault;1532;36;1568 +02127;Bruyères-sur-Fère;189;5;194 +02129;Bruys;19;0;19 +02130;Bucilly;193;7;200 +02131;Bucy-le-Long;1880;42;1922 +02132;Bucy-lès-Cerny;203;3;206 +02133;Bucy-lès-Pierrepont;411;6;417 +02134;Buire;869;17;886 +02135;Buironfosse;1168;16;1184 +02136;Burelles;128;4;132 +02137;Bussiares;152;0;152 +02138;Buzancy;190;2;192 +02139;Caillouël-Crépigny;438;8;446 +02140;Camelin;454;7;461 +02141;La Capelle;1788;79;1867 +02142;Castres;244;5;249 +02143;Le Catelet;192;6;198 +02144;Caulaincourt;145;3;148 +02145;Caumont;546;18;564 +02146;Celles-lès-Condé;87;1;88 +02148;Celles-sur-Aisne;258;2;260 +02149;Cerizy;67;0;67 +02150;Cerny-en-Laonnois;64;0;64 +02151;Cerny-lès-Bucy;115;3;118 +02152;Cerseuil;89;1;90 +02153;Cessières-Suzy;763;20;783 +02154;Chacrise;361;7;368 +02155;Chaillevois;174;5;179 +02156;Chalandry;253;1;254 +02157;Chambry;848;12;860 +02158;Chamouille;284;2;286 +02159;Champs;280;3;283 +02160;Chaourse;539;11;550 +02162;La Chapelle-sur-Chézy;278;5;283 +02163;Charly-sur-Marne;2617;42;2659 +02164;Le Charmel;316;7;323 +02165;Charmes;1652;28;1680 +02166;Chartèves;352;9;361 +02167;Chassemy;881;14;895 +02168;Château-Thierry;15107;379;15486 +02169;Châtillon-lès-Sons;83;0;83 +02170;Châtillon-sur-Oise;127;3;130 +02171;Chaudardes;87;1;88 +02172;Chaudun;249;10;259 +02173;Chauny;11878;439;12317 +02174;Chavignon;818;24;842 +02175;Chavigny;150;4;154 +02176;Chavonne;205;3;208 +02177;Chérêt;142;2;144 +02178;Chermizy-Ailles;106;2;108 +02179;Chéry-Chartreuve;392;10;402 +02180;Chéry-lès-Pouilly;710;8;718 +02181;Chéry-lès-Rozoy;80;1;81 +02182;Chevennes;125;3;128 +02183;Chevregny;187;1;188 +02184;Chevresis-Monceau;355;5;360 +02185;Chézy-en-Orxois;404;15;419 +02186;Chézy-sur-Marne;1353;45;1398 +02187;Chierry;1109;15;1124 +02188;Chigny;149;4;153 +02189;Chivres-en-Laonnois;362;8;370 +02190;Chivres-Val;530;12;542 +02191;Chivy-lès-Étouvelles;510;5;515 +02192;Chouy;370;7;377 +02193;Cierges;66;1;67 +02194;Cilly;193;8;201 +02195;Ciry-Salsogne;930;9;939 +02196;Clacy-et-Thierret;314;7;321 +02197;Clairfontaine;552;86;638 +02198;Clamecy;228;2;230 +02199;Clastres;635;9;644 +02200;Clermont-les-Fermes;120;1;121 +02203;Coincy;1310;19;1329 +02204;Coingt;68;1;69 +02205;Colligis-Crandelain;248;3;251 +02206;Colonfay;78;3;81 +02207;Commenchon;214;3;217 +02208;Concevreux;278;5;283 +02209;Condé-en-Brie;685;10;695 +02210;Condé-sur-Aisne;360;6;366 +02211;Condé-sur-Suippe;285;3;288 +02212;Condren;707;11;718 +02213;Connigis;332;2;334 +02214;Contescourt;61;1;62 +02215;Corbeny;801;6;807 +02216;Corcy;306;4;310 +02219;Coucy-la-Ville;219;70;289 +02217;Coucy-le-Château-Auffrique;1014;17;1031 +02218;Coucy-lès-Eppes;624;12;636 +02220;Coulonges-Cohan;436;15;451 +02221;Coupru;149;5;154 +02222;Courbes;31;0;31 +02223;Courboin;300;12;312 +02224;Courcelles-sur-Vesle;350;4;354 +02225;Courchamps;88;2;90 +02226;Courmelles;1826;30;1856 +02227;Courmont;133;1;134 +02228;Courtemont-Varennes;333;6;339 +02229;Courtrizy-et-Fussigny;66;1;67 +02230;Couvrelles;188;11;199 +02231;Couvron-et-Aumencourt;938;9;947 +02232;Coyolles;344;21;365 +02233;Cramaille;143;8;151 +02234;Craonne;82;0;82 +02235;Craonnelle;117;3;120 +02236;Crécy-au-Mont;346;3;349 +02237;Crécy-sur-Serre;1498;17;1515 +02238;Crépy;1837;31;1868 +02239;Crézancy;1230;84;1314 +02240;Croix-Fonsomme;257;3;260 +02241;La Croix-sur-Ourcq;105;2;107 +02242;Crouttes-sur-Marne;647;11;658 +02243;Crouy;2905;47;2952 +02244;Crupilly;64;3;67 +02245;Cuffies;1789;35;1824 +02246;Cugny;606;5;611 +02248;Cuirieux;157;3;160 +02249;Cuiry-Housse;102;0;102 +02250;Cuiry-lès-Chaudardes;76;4;80 +02251;Cuiry-lès-Iviers;28;1;29 +02252;Cuissy-et-Geny;71;2;73 +02253;Cuisy-en-Almont;355;3;358 +02254;Cutry;128;5;133 +02255;Cys-la-Commune;143;2;145 +02201;Cœuvres-et-Valsery;438;6;444 +02256;Dagny-Lambercy;125;3;128 +02257;Dallon;436;13;449 +02258;Dammard;379;13;392 +02259;Dampleux;398;15;413 +02260;Danizy;650;11;661 +02261;Dercy;391;9;400 +02262;Deuillet;216;3;219 +02263;Dhuizel;114;0;114 +02458;Dhuys et Morin-en-Brie;818;16;834 +02264;Dizy-le-Gros;747;15;762 +02265;Dohis;99;2;101 +02266;Dolignon;49;2;51 +02267;Dommiers;289;10;299 +02268;Domptin;654;14;668 +02269;Dorengt;154;6;160 +02270;Douchy;162;4;166 +02271;Dravegny;132;2;134 +02272;Droizy;75;2;77 +02273;Dury;222;5;227 +02274;Ébouleau;200;6;206 +02275;Effry;324;5;329 +02276;Englancourt;122;5;127 +02277;Épagny;340;6;346 +02278;Éparcy;30;6;36 +02279;Épaux-Bézu;556;19;575 +02280;Épieds;392;12;404 +02281;L' Épine-aux-Bois;261;11;272 +02282;Eppes;417;14;431 +02283;Erlon;284;9;293 +02284;Erloy;97;1;98 +02286;Esquéhéries;858;11;869 +02287;Essigny-le-Grand;1022;24;1046 +02288;Essigny-le-Petit;344;5;349 +02289;Essises;417;11;428 +02290;Essômes-sur-Marne;2776;75;2851 +02291;Estrées;412;8;420 +02292;Étampes-sur-Marne;1253;27;1280 +02293;Étaves-et-Bocquiaux;557;10;567 +02294;Étouvelles;213;8;221 +02295;Étréaupont;859;8;867 +02296;Étreillers;1208;21;1229 +02297;Étrépilly;118;1;119 +02298;Étreux;1459;9;1468 +02299;Évergnicourt;570;6;576 +02302;Faverolles;317;12;329 +02303;Fayet;654;17;671 +02304;La Fère;2859;140;2999 +02305;Fère-en-Tardenois;3053;55;3108 +02306;La Ferté-Chevresis;542;8;550 +02307;La Ferté-Milon;2085;158;2243 +02308;Fesmy-le-Sart;486;8;494 +02309;Festieux;680;5;685 +02310;Fieulaine;256;7;263 +02311;Filain;129;2;131 +02312;La Flamengrie;1118;10;1128 +02313;Flavigny-le-Grand-et-Beaurain;468;5;473 +02315;Flavy-le-Martel;1687;29;1716 +02316;Fleury;136;5;141 +02317;Fluquières;220;4;224 +02318;Folembray;1386;18;1404 +02319;Fonsomme;469;7;476 +02320;Fontaine-lès-Clercs;250;4;254 +02321;Fontaine-lès-Vervins;913;182;1095 +02322;Fontaine-Notre-Dame;389;3;392 +02323;Fontaine-Uterte;127;4;131 +02324;Fontenelle;277;3;280 +02326;Fontenoy;489;9;498 +02327;Foreste;165;1;166 +02328;Fossoy;524;6;530 +02329;Fourdrain;419;9;428 +02330;Francilly-Selency;474;7;481 +02331;Franqueville;113;3;116 +02332;Fresnes-en-Tardenois;268;4;272 +02333;Fresnes-sous-Coucy;161;0;161 +02334;Fresnoy-le-Grand;2945;69;3014 +02335;Fressancourt;192;5;197 +02336;Frières-Faillouël;998;15;1013 +02337;Froidestrées;176;4;180 +02338;Froidmont-Cohartille;261;8;269 +02339;Gandelu;687;9;696 +02340;Gauchy;5276;84;5360 +02341;Gercy;277;1;278 +02342;Gergny;135;2;137 +02343;Germaine;81;0;81 +02345;Gibercourt;42;1;43 +02346;Gizy;672;12;684 +02347;Gland;450;6;456 +02349;Goudelancourt-lès-Berrieux;57;0;57 +02350;Goudelancourt-lès-Pierrepont;135;2;137 +02351;Goussancourt;116;6;122 +02352;Gouy;560;10;570 +02665;Grand-Rozoy;304;5;309 +02783;Grand-Verly;138;0;138 +02353;Grandlup-et-Fay;301;11;312 +02354;Grandrieux;83;2;85 +02355;Gricourt;980;27;1007 +02356;Grisolles;252;2;254 +02357;Gronard;73;2;75 +02358;Grougis;358;5;363 +02359;Grugies;1355;27;1382 +02361;Guise;4824;105;4929 +02362;Guivry;243;11;254 +02363;Guny;423;4;427 +02364;Guyencourt;253;5;258 +02366;Hannapes;318;6;324 +02367;Happencourt;133;4;137 +02368;Haramont;580;8;588 +02369;Harcigny;242;2;244 +02370;Hargicourt;598;4;602 +02371;Harly;1610;36;1646 +02372;Hartennes-et-Taux;371;10;381 +02373;Hary;208;5;213 +02375;Hautevesnes;167;3;170 +02376;Hauteville;166;5;171 +02377;Haution;144;7;151 +02378;La Hérie;143;6;149 +02379;Le Hérie-la-Viéville;230;121;351 +02380;Hinacourt;25;1;26 +02381;Hirson;8813;188;9001 +02382;Holnon;1387;40;1427 +02383;Homblières;1464;46;1510 +02384;Houry;53;2;55 +02385;Housset;149;7;156 +02386;Iron;239;2;241 +02387;Itancourt;1031;35;1066 +02388;Iviers;232;2;234 +02389;Jaulgonne;645;16;661 +02390;Jeancourt;271;2;273 +02391;Jeantes;205;0;205 +02392;Joncourt;299;3;302 +02393;Jouaignes;144;5;149 +02395;Jumencourt;146;6;152 +02396;Jumigny;64;1;65 +02397;Jussy;1260;18;1278 +02398;Juvigny;277;4;281 +02399;Juvincourt-et-Damary;599;5;604 +02400;Laffaux;149;4;153 +02401;Laigny;196;1;197 +02402;Lanchy;37;1;38 +02403;Landifay-et-Bertaignemont;269;7;276 +02404;Landouzy-la-Cour;187;0;187 +02405;Landouzy-la-Ville;541;5;546 +02406;Landricourt;137;5;142 +02407;Laniscourt;182;5;187 +02408;Laon;24876;673;25549 +02409;Lappion;268;4;272 +02410;Largny-sur-Automne;244;11;255 +02411;Latilly;208;5;213 +02412;Launoy;99;1;100 +02413;Laval-en-Laonnois;250;4;254 +02414;Lavaqueresse;202;5;207 +02415;Laversine;159;4;163 +02374;Lehaucourt;877;8;885 +02416;Lemé;430;11;441 +02417;Lempire;100;0;100 +02418;Lerzy;213;4;217 +02419;Leschelle;270;9;279 +02420;Lesdins;832;12;844 +02421;Lesges;102;1;103 +02422;Lesquielles-Saint-Germain;810;7;817 +02423;Leuilly-sous-Coucy;420;8;428 +02424;Leury;106;0;106 +02425;Leuze;173;3;176 +02426;Levergies;545;10;555 +02427;Lhuys;141;1;142 +02428;Licy-Clignon;74;2;76 +02429;Lierval;118;1;119 +02430;Liesse-Notre-Dame;1298;106;1404 +02431;Liez;391;10;401 +02432;Limé;187;3;190 +02433;Lislet;225;10;235 +02435;Logny-lès-Aubenton;74;0;74 +02438;Longpont;262;9;271 +02440;Lor;142;0;142 +02441;Louâtre;199;3;202 +02442;Loupeigne;91;1;92 +02443;Lucy-le-Bocage;195;7;202 +02444;Lugny;114;0;114 +02445;Luzoir;285;6;291 +02446;Ly-Fontaine;121;1;122 +02447;Maast-et-Violaine;147;5;152 +02448;Mâchecourt;122;3;125 +02449;Macogny;73;3;76 +02450;Macquigny;376;2;378 +02451;Magny-la-Fosse;125;1;126 +02452;Maissemy;239;7;246 +02453;Maizy;411;3;414 +02454;La Malmaison;410;3;413 +02455;Malzy;203;1;204 +02456;Manicamp;307;4;311 +02457;Marchais;435;3;438 +02459;Marcy;173;8;181 +02460;Marcy-sous-Marle;192;3;195 +02461;Marest-Dampcourt;369;6;375 +02462;Mareuil-en-Dôle;240;2;242 +02463;Marfontaine;86;2;88 +02464;Margival;370;2;372 +02465;Marigny-en-Orxois;485;5;490 +02467;Marizy-Saint-Mard;50;1;51 +02466;Marizy-Sainte-Geneviève;130;0;130 +02468;Marle;2268;37;2305 +02469;Marly-Gomont;475;15;490 +02470;Martigny;434;12;446 +02471;Martigny-Courpierre;124;2;126 +02472;Mauregny-en-Haye;420;4;424 +02473;Mayot;211;1;212 +02474;Mennessis;408;4;412 +02476;Mennevret;651;12;663 +02477;Mercin-et-Vaux;962;21;983 +02478;Merlieux-et-Fouquerolles;259;8;267 +02480;Mesbrecourt-Richecourt;305;2;307 +02481;Mesnil-Saint-Laurent;476;16;492 +02482;Meurival;52;0;52 +02483;Mézières-sur-Oise;516;8;524 +02484;Mézy-Moulins;517;8;525 +02485;Missy-aux-Bois;97;3;100 +02486;Missy-lès-Pierrepont;108;1;109 +02487;Missy-sur-Aisne;640;18;658 +02488;Molain;152;1;153 +02489;Molinchart;329;8;337 +02490;Monampteuil;131;7;138 +02491;Monceau-le-Neuf-et-Faucouzy;319;9;328 +02493;Monceau-le-Waast;220;6;226 +02492;Monceau-lès-Leups;473;7;480 +02494;Monceau-sur-Oise;128;2;130 +02495;Mondrepuis;1040;15;1055 +02496;Monnes;104;0;104 +02497;Mons-en-Laonnois;1152;28;1180 +02503;Mont-d'Origny;847;4;851 +02520;Mont-Notre-Dame;736;7;743 +02522;Mont-Saint-Jean;75;2;77 +02523;Mont-Saint-Martin;74;2;76 +02524;Mont-Saint-Père;700;14;714 +02498;Montaigu;761;10;771 +02499;Montbavin;44;2;46 +02500;Montbrehain;810;19;829 +02501;Montchâlons;84;2;86 +02502;Montcornet;1338;9;1347 +02504;Montescourt-Lizerolles;1648;31;1679 +02505;Montfaucon;203;5;208 +02506;Montgobert;193;6;199 +02507;Montgru-Saint-Hilaire;32;1;33 +02508;Monthenault;152;6;158 +02509;Monthiers;161;4;165 +02510;Monthurel;151;2;153 +02511;Montigny-en-Arrouaise;291;4;295 +02512;Montigny-l'Allier;274;5;279 +02513;Montigny-le-Franc;142;2;144 +02514;Montigny-Lengrain;702;16;718 +02515;Montigny-lès-Condé;59;6;65 +02516;Montigny-sous-Marle;63;1;64 +02517;Montigny-sur-Crécy;315;5;320 +02518;Montlevon;301;3;304 +02519;Montloué;187;4;191 +02521;Montreuil-aux-Lions;1369;14;1383 +02525;Morcourt;574;14;588 +02526;Morgny-en-Thiérache;89;3;92 +02527;Morsain;444;9;453 +02528;Mortefontaine;233;5;238 +02529;Mortiers;187;1;188 +02530;Moulins;76;1;77 +02531;Moussy-Verneuil;123;1;124 +02532;Moÿ-de-l'Aisne;975;18;993 +02533;Muret-et-Crouttes;119;8;127 +02534;Muscourt;52;1;53 +02535;Nampcelles-la-Cour;118;4;122 +02536;Nampteuil-sous-Muret;103;1;104 +02537;Nanteuil-la-Fosse;193;1;194 +02538;Nanteuil-Notre-Dame;62;0;62 +02539;Nauroy;703;9;712 +02540;Nesles-la-Montagne;1230;35;1265 +02541;Neufchâtel-sur-Aisne;423;7;430 +02542;Neuflieux;91;2;93 +02543;Neuilly-Saint-Front;2078;34;2112 +02544;Neuve-Maison;611;14;625 +02545;La Neuville-Bosmont;187;2;189 +02546;La Neuville-en-Beine;197;3;200 +02547;La Neuville-Housset;67;2;69 +02548;La Neuville-lès-Dorengt;380;6;386 +02549;Neuville-Saint-Amand;842;20;862 +02550;Neuville-sur-Ailette;105;2;107 +02551;Neuville-sur-Margival;117;0;117 +02552;Neuvillette;186;9;195 +02553;Nizy-le-Comte;244;4;248 +02555;Nogent-l'Artaud;2167;47;2214 +02554;Nogentel;1012;23;1035 +02556;Noircourt;81;0;81 +02557;Noroy-sur-Ourcq;130;0;130 +02558;Le Nouvion-en-Thiérache;2602;28;2630 +02559;Nouvion-et-Catillon;474;4;478 +02560;Nouvion-le-Comte;249;9;258 +02561;Nouvion-le-Vineux;165;3;168 +02562;Nouvron-Vingré;225;2;227 +02563;Noyales;167;3;170 +02564;Noyant-et-Aconin;502;5;507 +02566;Ognes;1113;22;1135 +02567;Ohis;303;8;311 +02568;Oigny-en-Valois;155;4;159 +02569;Oisy;466;3;469 +02570;Ollezy;184;0;184 +02571;Omissy;714;81;795 +02572;Orainville;507;9;516 +02573;Orgeval;66;2;68 +02574;Origny-en-Thiérache;1453;28;1481 +02575;Origny-Sainte-Benoite;1685;16;1701 +02576;Osly-Courtil;326;8;334 +02577;Ostel;80;1;81 +02578;Oulches-la-Vallée-Foulon;85;1;86 +02579;Oulchy-la-Ville;122;9;131 +02580;Oulchy-le-Château;823;10;833 +02581;Paars;314;1;315 +02582;Paissy;75;2;77 +02583;Pancy-Courtecon;56;2;58 +02584;Papleux;128;0;128 +02585;Parcy-et-Tigny;256;7;263 +02586;Parfondeval;142;6;148 +02587;Parfondru;352;7;359 +02588;Pargnan;74;3;77 +02589;Pargny-Filain;259;0;259 +02590;Pargny-la-Dhuys;170;4;174 +02591;Pargny-les-Bois;131;1;132 +02592;Parpeville;189;6;195 +02593;Pasly;1019;20;1039 +02594;Passy-en-Valois;148;7;155 +02595;Passy-sur-Marne;126;2;128 +02596;Pavant;781;15;796 +02598;Pernant;650;22;672 +02784;Petit-Verly;149;0;149 +02599;Pierremande;279;2;281 +02600;Pierrepont;370;6;376 +02601;Pignicourt;197;2;199 +02602;Pinon;1765;15;1780 +02604;Pithon;83;1;84 +02605;Pleine-Selve;172;4;176 +02606;Le Plessier-Huleu;71;3;74 +02607;Ploisy;77;2;79 +02608;Plomion;462;2;464 +02609;Ployart-et-Vaurseine;21;0;21 +02610;Pommiers;688;11;699 +02612;Pont-Arcy;127;1;128 +02616;Pont-Saint-Mard;205;3;208 +02613;Pontavert;610;9;619 +02614;Pontru;251;10;261 +02615;Pontruet;344;5;349 +02617;Pouilly-sur-Serre;502;3;505 +02618;Prémont;700;13;713 +02619;Prémontré;661;0;661 +02620;Presles-et-Boves;360;9;369 +02621;Presles-et-Thierny;385;15;400 +02622;Priez;52;0;52 +02623;Prisces;103;3;106 +02624;Proisy;274;65;339 +02625;Proix;144;2;146 +02626;Prouvais;319;7;326 +02627;Proviseux-et-Plesnoy;120;3;123 +02628;Puiseux-en-Retz;214;6;220 +02629;Puisieux-et-Clanlieu;289;9;298 +02631;Quierzy;420;6;426 +02632;Quincy-Basse;60;1;61 +02633;Quincy-sous-le-Mont;61;0;61 +02634;Raillimont;79;4;83 +02635;Ramicourt;150;5;155 +02636;Regny;201;5;206 +02637;Remaucourt;299;10;309 +02638;Remies;235;1;236 +02639;Remigny;351;8;359 +02640;Renansart;164;4;168 +02641;Renneval;113;3;116 +02642;Résigny;186;1;187 +02643;Ressons-le-Long;772;8;780 +02644;Retheuil;359;13;372 +02645;Reuilly-Sauvigny;201;9;210 +02647;Ribeauville;63;0;63 +02648;Ribemont;1982;27;2009 +02649;Rocourt-Saint-Martin;289;4;293 +02650;Rocquigny;361;5;366 +02651;Rogécourt;105;1;106 +02652;Rogny;112;1;113 +02653;Romeny-sur-Marne;504;13;517 +02654;Romery;82;1;83 +02655;Ronchères;112;3;115 +02656;Roucy;394;11;405 +02657;Rougeries;243;4;247 +02658;Roupy;230;7;237 +02659;Rouvroy;510;12;522 +02660;Rouvroy-sur-Serre;39;2;41 +02661;Royaucourt-et-Chailvet;252;3;255 +02662;Rozet-Saint-Albin;309;11;320 +02663;Rozières-sur-Crise;227;5;232 +02664;Rozoy-Bellevalle;116;3;119 +02666;Rozoy-sur-Serre;1007;15;1022 +02667;Saconin-et-Breuil;228;7;235 +02668;Sains-Richaumont;1043;20;1063 +02670;Saint-Algis;156;0;156 +02671;Saint-Aubin;291;5;296 +02672;Saint-Bandry;267;4;271 +02673;Saint-Christophe-à-Berry;447;5;452 +02674;Saint-Clément;50;0;50 +02676;Saint-Erme-Outre-et-Ramecourt;1726;37;1763 +02677;Saint-Eugène;244;2;246 +02679;Saint-Gengoulph;148;4;152 +02680;Saint-Gobain;2282;38;2320 +02681;Saint-Gobert;267;5;272 +02682;Saint-Mard;112;3;115 +02683;Saint-Martin-Rivière;115;3;118 +02684;Saint-Michel;3417;58;3475 +02685;Saint-Nicolas-aux-Bois;119;1;120 +02686;Saint-Paul-aux-Bois;389;4;393 +02687;Saint-Pierre-Aigle;334;9;343 +02688;Saint-Pierre-lès-Franqueville;53;2;55 +02689;Saint-Pierremont;43;1;44 +02691;Saint-Quentin;53816;1282;55098 +02693;Saint-Rémy-Blanzy;219;3;222 +02694;Saint-Simon;635;8;643 +02695;Saint-Thibaut;78;0;78 +02696;Saint-Thomas;80;4;84 +02675;Sainte-Croix;130;1;131 +02678;Sainte-Geneviève;71;0;71 +02690;Sainte-Preuve;82;1;83 +02697;Samoussy;387;4;391 +02698;Sancy-les-Cheminots;100;2;102 +02699;Saponay;289;5;294 +02701;Saulchery;724;8;732 +02702;Savy;609;22;631 +02703;Seboncourt;1097;12;1109 +02704;Selens;250;4;254 +02705;La Selve;217;6;223 +02706;Septmonts;560;11;571 +02439;Les Septvallons;1180;20;1200 +02707;Septvaux;179;0;179 +02708;Sequehart;209;8;217 +02709;Serain;405;9;414 +02710;Seraucourt-le-Grand;769;17;786 +02711;Serches;309;7;316 +02712;Sergy;151;3;154 +02713;Seringes-et-Nesles;276;4;280 +02714;Sermoise;349;2;351 +02716;Servais;287;6;293 +02715;Serval;52;2;54 +02717;Séry-lès-Mézières;576;11;587 +02718;Silly-la-Poterie;126;2;128 +02719;Sinceny;2040;42;2082 +02720;Sissonne;2055;78;2133 +02721;Sissy;476;2;478 +02722;Soissons;28530;646;29176 +02723;Soize;101;1;102 +02724;Sommelans;61;1;62 +02725;Sommeron;142;9;151 +02726;Sommette-Eaucourt;193;1;194 +02727;Sons-et-Ronchères;240;0;240 +02728;Sorbais;274;4;278 +02729;Soucy;97;1;98 +02730;Soupir;273;6;279 +02731;Le Sourd;168;2;170 +02732;Surfontaine;102;0;102 +02734;Taillefontaine;276;6;282 +02735;Tannières;16;0;16 +02736;Tartiers;166;5;171 +02737;Tavaux-et-Pontséricourt;569;12;581 +02738;Tergnier;13456;186;13642 +02739;Terny-Sorny;330;6;336 +02740;Thenailles;220;7;227 +02741;Thenelles;550;5;555 +02742;Thiernu;102;0;102 +02743;Le Thuel;168;1;169 +02744;Torcy-en-Valois;73;2;75 +02745;Toulis-et-Attencourt;128;2;130 +02746;Travecy;670;9;679 +02747;Trefcon;85;0;85 +02748;Trélou-sur-Marne;948;19;967 +02749;Troësnes;224;7;231 +02750;Trosly-Loire;613;11;624 +02751;Trucy;145;3;148 +02752;Tugny-et-Pont;275;4;279 +02753;Tupigny;335;3;338 +02754;Ugny-le-Gay;182;2;184 +02755;Urcel;585;9;594 +02756;Urvillers;659;11;670 +02757;Vadencourt;540;9;549 +02758;Vailly-sur-Aisne;2003;37;2040 +02759;La Vallée-au-Blé;365;3;368 +02760;La Vallée-Mulâtre;148;3;151 +02053;Vallées en Champagne;570;5;575 +02761;Variscourt;197;4;201 +02762;Vassens;151;5;156 +02763;Vasseny;215;4;219 +02764;Vassogne;87;3;90 +02765;Vaucelles-et-Beffecourt;265;9;274 +02766;Vaudesson;238;6;244 +02769;Vaux-Andigny;923;13;936 +02772;Vaux-en-Vermandois;153;1;154 +02768;Vauxaillon;540;6;546 +02770;Vauxbuin;786;20;806 +02767;Vauxrezis;324;3;327 +02773;Vauxtin;39;0;39 +02774;Vendelles;117;1;118 +02775;Vendeuil;951;12;963 +02776;Vendhuile;556;12;568 +02777;Vendières;160;8;168 +02778;Vendresse-Beaulne;102;1;103 +02779;Vénérolles;223;3;226 +02780;Venizel;1378;17;1395 +02781;Verdilly;461;16;477 +02782;Le Verguier;219;2;221 +02785;Vermand;1092;31;1123 +02786;Verneuil-sous-Coucy;129;3;132 +02787;Verneuil-sur-Serre;254;2;256 +02788;Versigny;468;7;475 +02789;Vervins;2552;108;2660 +02790;Vesles-et-Caumont;231;3;234 +02791;Veslud;242;6;248 +02792;Veuilly-la-Poterie;155;7;162 +02793;Vézaponin;125;1;126 +02794;Vézilly;185;4;189 +02795;Vic-sur-Aisne;1645;31;1676 +02796;Vichel-Nanteuil;87;0;87 +02797;Viel-Arcy;179;1;180 +02798;Viels-Maisons;1234;13;1247 +02799;Vierzy;435;10;445 +02800;Viffort;320;5;325 +02801;Vigneux-Hocquet;268;3;271 +02802;La Ville-aux-Bois-lès-Dizy;207;0;207 +02803;La Ville-aux-Bois-lès-Pontavert;143;5;148 +02817;Ville-Savoye;82;1;83 +02804;Villemontoire;186;3;189 +02805;Villeneuve-Saint-Germain;2490;43;2533 +02360;Villeneuve-sur-Aisne;2704;36;2740 +02806;Villeneuve-sur-Fère;285;6;291 +02807;Villequier-Aumont;646;25;671 +02808;Villeret;300;6;306 +02809;Villers-Agron-Aiguizy;74;3;77 +02810;Villers-Cotterêts;10872;437;11309 +02812;Villers-Hélon;217;6;223 +02813;Villers-le-Sec;267;8;275 +02814;Villers-lès-Guise;169;1;170 +02815;Villers-Saint-Christophe;435;12;447 +02816;Villers-sur-Fère;527;6;533 +02818;Villiers-Saint-Denis;1127;11;1138 +02819;Vincy-Reuil-et-Magny;117;1;118 +02820;Viry-Noureuil;1695;48;1743 +02821;Vivaise;698;21;719 +02822;Vivières;394;12;406 +02823;Voharies;73;0;73 +02824;Vorges;370;8;378 +02826;Voulpaix;372;7;379 +02827;Voyenne;324;2;326 +02828;Vregny;93;0;93 +02829;Vuillery;43;1;44 +02830;Wassigny;959;16;975 +02831;Watigny;379;6;385 +02832;Wiège-Faty;200;5;205 +02833;Wimy;487;7;494 +02834;Wissignicourt;167;6;173 +02565;Œuilly;290;3;293 +03001;Abrest;2931;47;2978 +03002;Agonges;309;14;323 +03003;Ainay-le-Château;994;26;1020 +03004;Andelaroche;258;7;265 +03005;Archignat;336;4;340 +03006;Arfeuilles;648;17;665 +03007;Arpheuilles-Saint-Priest;356;7;363 +03008;Arronnes;374;14;388 +03009;Aubigny;139;29;168 +03010;Audes;433;14;447 +03011;Aurouër;413;9;422 +03012;Autry-Issards;325;6;331 +03013;Avermes;3966;98;4064 +03014;Avrilly;135;3;138 +03015;Bagneux;321;10;331 +03016;Barberier;143;2;145 +03017;Barrais-Bussolles;192;6;198 +03018;Bayet;698;14;712 +03019;Beaulon;1651;24;1675 +03020;Beaune-d'Allier;291;7;298 +03021;Bègues;227;2;229 +03022;Bellenaves;1020;19;1039 +03023;Bellerive-sur-Allier;8500;263;8763 +03024;Bert;243;6;249 +03025;Bessay-sur-Allier;1335;30;1365 +03026;Besson;768;18;786 +03027;Bézenet;948;23;971 +03028;Billezois;379;9;388 +03029;Billy;781;12;793 +03030;Biozat;845;15;860 +03031;Bizeneuille;294;9;303 +03032;Blomard;247;3;250 +03033;Bost;188;4;192 +03034;Boucé;508;12;520 +03035;Le Bouchaud;214;4;218 +03036;Bourbon-l'Archambault;2559;73;2632 +03037;Braize;257;3;260 +03038;Bransat;512;7;519 +03039;Bresnay;383;7;390 +03040;Bressolles;1113;28;1141 +03041;Le Brethon;325;12;337 +03042;Le Breuil;532;17;549 +03043;Broût-Vernet;1169;75;1244 +03044;Brugheas;1484;33;1517 +03045;Busset;910;20;930 +03046;Buxières-les-Mines;1058;30;1088 +03047;La Celle;413;10;423 +03048;Cérilly;1311;24;1335 +03049;Cesset;416;10;426 +03050;La Chabanne;186;11;197 +03051;Chambérat;305;6;311 +03052;Chamblet;1097;29;1126 +03053;Chantelle;1077;23;1100 +03054;Chapeau;232;6;238 +03055;La Chapelaude;1007;15;1022 +03056;La Chapelle;370;13;383 +03057;La Chapelle-aux-Chasses;210;3;213 +03058;Chappes;229;6;235 +03059;Chareil-Cintrat;358;7;365 +03060;Charmeil;983;16;999 +03061;Charmes;398;6;404 +03062;Charroux;362;8;370 +03063;Chassenard;989;21;1010 +03064;Château-sur-Allier;179;2;181 +03065;Châtel-de-Neuvre;542;9;551 +03066;Châtel-Montagne;347;5;352 +03067;Châtelperron;146;4;150 +03068;Châtelus;108;1;109 +03069;Châtillon;314;6;320 +03070;Chavenon;134;1;135 +03071;Chavroches;247;3;250 +03072;Chazemais;495;12;507 +03073;Chemilly;639;12;651 +03074;Chevagnes;663;16;679 +03075;Chezelle;175;2;177 +03076;Chézy;243;5;248 +03077;Chirat-l'Église;128;3;131 +03078;Chouvigny;227;8;235 +03079;Cindré;301;8;309 +03080;Cognat-Lyonne;694;10;704 +03081;Colombier;332;12;344 +03082;Commentry;6239;188;6427 +03083;Contigny;592;12;604 +03084;Cosne-d'Allier;2039;34;2073 +03085;Coulandon;650;62;712 +03086;Coulanges;354;3;357 +03087;Couleuvre;581;7;588 +03088;Courçais;325;2;327 +03089;Coutansouze;154;1;155 +03090;Couzon;299;8;307 +03091;Créchy;455;9;464 +03092;Cressanges;626;15;641 +03093;Creuzier-le-Neuf;1166;26;1192 +03094;Creuzier-le-Vieux;3304;101;3405 +03095;Cusset;12661;481;13142 +03096;Deneuille-lès-Chantelle;81;2;83 +03097;Deneuille-les-Mines;362;9;371 +03098;Désertines;4422;86;4508 +03099;Deux-Chaises;392;9;401 +03100;Diou;1398;25;1423 +03101;Domérat;8780;166;8946 +03102;Dompierre-sur-Besbre;3040;57;3097 +03103;Le Donjon;1069;27;1096 +03104;Doyet;1183;31;1214 +03105;Droiturier;336;7;343 +03106;Durdat-Larequille;1328;118;1446 +03107;Ébreuil;1265;29;1294 +03108;Échassières;385;7;392 +03109;Escurolles;775;32;807 +03110;Espinasse-Vozelle;991;27;1018 +03111;Estivareilles;1103;16;1119 +03112;Étroussat;655;9;664 +03113;Ferrières-sur-Sichon;552;17;569 +03114;La Ferté-Hauterive;296;10;306 +03115;Fleuriel;335;4;339 +03116;Fourilles;195;5;200 +03117;Franchesse;471;12;483 +03118;Gannat;5832;200;6032 +03119;Gannay-sur-Loire;409;4;413 +03120;Garnat-sur-Engièvre;705;12;717 +03121;Gennetines;670;15;685 +03122;Gipcy;238;6;244 +03124;Gouise;219;3;222 +03125;La Guillermie;127;2;129 +03158;Haut-Bocage;888;20;908 +03126;Hauterive;1169;14;1183 +03127;Hérisson;622;10;632 +03128;Huriel;2646;56;2702 +03129;Hyds;320;14;334 +03130;Isle-et-Bardais;272;6;278 +03131;Isserpent;534;13;547 +03132;Jaligny-sur-Besbre;575;15;590 +03133;Jenzat;508;15;523 +03134;Laféline;197;3;200 +03135;Lalizolle;380;9;389 +03136;Lamaids;222;5;227 +03137;Langy;272;6;278 +03138;Lapalisse;3123;78;3201 +03139;Laprugne;317;11;328 +03140;Lavault-Sainte-Anne;1165;33;1198 +03141;Lavoine;146;2;148 +03142;Lenax;253;5;258 +03143;Lételon;106;3;109 +03144;Liernolles;213;8;221 +03145;Lignerolles;742;13;755 +03146;Limoise;156;35;191 +03147;Loddes;164;2;166 +03148;Loriges;350;9;359 +03149;Louchy-Montfand;437;16;453 +03150;Louroux-Bourbonnais;211;5;216 +03151;Louroux-de-Beaune;165;3;168 +03152;Louroux-de-Bouble;239;8;247 +03154;Luneau;291;2;293 +03155;Lurcy-Lévis;1893;39;1932 +03156;Lusigny;1698;54;1752 +03157;Magnet;989;17;1006 +03159;Malicorne;796;14;810 +03160;Marcenat;405;4;409 +03161;Marcillat-en-Combraille;905;30;935 +03162;Marigny;204;6;210 +03163;Mariol;797;19;816 +03164;Le Mayet-d'École;269;3;272 +03165;Le Mayet-de-Montagne;1383;84;1467 +03166;Mazerier;301;5;306 +03167;Mazirat;282;4;286 +03168;Meaulne-Vitray;889;15;904 +03169;Meillard;318;6;324 +03170;Meillers;136;6;142 +03171;Mercy;261;3;264 +03172;Mesples;124;2;126 +03173;Molinet;1150;33;1183 +03174;Molles;898;26;924 +03175;Monestier;282;12;294 +03176;Monétay-sur-Allier;524;10;534 +03177;Monétay-sur-Loire;264;6;270 +03179;Montaigu-le-Blin;302;10;312 +03178;Montaiguët-en-Forez;313;8;321 +03180;Montbeugny;681;11;692 +03181;Montcombroux-les-Mines;313;3;316 +03182;Monteignet-sur-l'Andelot;266;1;267 +03183;Le Montet;467;4;471 +03184;Montilly;508;8;516 +03185;Montluçon;35653;1093;36746 +03186;Montmarault;1521;23;1544 +03187;Montoldre;632;9;641 +03188;Montord;215;1;216 +03189;Montvicq;720;24;744 +03190;Moulins;19664;563;20227 +03191;Murat;295;17;312 +03192;Nades;153;4;157 +03193;Nassigny;182;4;186 +03194;Naves;119;2;121 +03195;Néris-les-Bains;2553;93;2646 +03196;Neuilly-en-Donjon;222;3;225 +03197;Neuilly-le-Réal;1456;33;1489 +03198;Neure;188;0;188 +03200;Neuvy;1595;224;1819 +03201;Nizerolles;314;14;328 +03202;Noyant-d'Allier;627;16;643 +03203;Paray-le-Frésil;389;10;399 +03204;Paray-sous-Briailles;633;9;642 +03205;Périgny;440;11;451 +03206;La Petite-Marche;176;6;182 +03207;Pierrefitte-sur-Loire;509;14;523 +03208;Le Pin;411;7;418 +03209;Poëzat;148;3;151 +03210;Pouzy-Mésangy;402;10;412 +03211;Prémilhat;2458;49;2507 +03212;Quinssaines;1487;25;1512 +03213;Reugny;249;3;252 +03214;Rocles;380;3;383 +03215;Rongères;565;13;578 +03216;Ronnet;174;3;177 +03217;Saint-Angel;754;35;789 +03218;Saint-Aubin-le-Monial;266;8;274 +03219;Saint-Bonnet-de-Four;212;4;216 +03220;Saint-Bonnet-de-Rochefort;698;14;712 +03221;Saint-Bonnet-Tronçais;725;9;734 +03222;Saint-Caprais;90;5;95 +03223;Saint-Christophe;466;15;481 +03224;Saint-Clément;300;7;307 +03225;Saint-Désiré;447;9;456 +03226;Saint-Didier-en-Donjon;259;4;263 +03227;Saint-Didier-la-Forêt;379;8;387 +03228;Saint-Éloy-d'Allier;43;0;43 +03229;Saint-Ennemond;626;18;644 +03230;Saint-Étienne-de-Vicq;526;17;543 +03231;Saint-Fargeol;190;5;195 +03232;Saint-Félix;315;10;325 +03233;Saint-Genest;407;7;414 +03234;Saint-Gérand-de-Vaux;381;11;392 +03235;Saint-Gérand-le-Puy;993;9;1002 +03237;Saint-Germain-de-Salles;425;9;434 +03236;Saint-Germain-des-Fossés;3656;66;3722 +03238;Saint-Hilaire;543;5;548 +03239;Saint-Léger-sur-Vouzance;265;10;275 +03240;Saint-Léon;549;11;560 +03241;Saint-Léopardin-d'Augy;362;43;405 +03242;Saint-Loup;568;14;582 +03244;Saint-Marcel-en-Marcillat;136;2;138 +03243;Saint-Marcel-en-Murat;124;6;130 +03245;Saint-Martin-des-Lais;123;1;124 +03246;Saint-Martinien;602;13;615 +03247;Saint-Menoux;1045;32;1077 +03248;Saint-Nicolas-des-Biefs;171;2;173 +03249;Saint-Palais;164;2;166 +03250;Saint-Pierre-Laval;357;6;363 +03251;Saint-Plaisir;379;11;390 +03252;Saint-Pont;656;15;671 +03253;Saint-Pourçain-sur-Besbre;418;10;428 +03254;Saint-Pourçain-sur-Sioule;5160;120;5280 +03255;Saint-Priest-d'Andelot;145;4;149 +03256;Saint-Priest-en-Murat;223;7;230 +03257;Saint-Prix;796;19;815 +03258;Saint-Rémy-en-Rollat;1706;35;1741 +03259;Saint-Sauvier;348;3;351 +03260;Saint-Sornin;225;4;229 +03262;Saint-Victor;2098;39;2137 +03263;Saint-Voir;190;7;197 +03264;Saint-Yorre;2561;53;2614 +03261;Sainte-Thérence;184;7;191 +03265;Saligny-sur-Roudon;681;79;760 +03266;Sanssat;259;5;264 +03267;Saulcet;693;25;718 +03268;Saulzet;387;3;390 +03269;Sauvagny;89;2;91 +03270;Sazeret;148;5;153 +03271;Serbannes;820;31;851 +03272;Servilly;295;6;301 +03273;Seuillet;508;7;515 +03274;Sorbier;315;6;321 +03275;Souvigny;1828;50;1878 +03276;Sussat;101;6;107 +03277;Target;254;12;266 +03278;Taxat-Senat;196;4;200 +03279;Teillet-Argenty;556;10;566 +03280;Terjat;196;10;206 +03281;Le Theil;404;4;408 +03282;Theneuille;365;14;379 +03283;Thiel-sur-Acolin;1125;16;1141 +03284;Thionne;313;10;323 +03285;Tortezais;175;3;178 +03286;Toulon-sur-Allier;1135;34;1169 +03287;Treban;387;9;396 +03288;Treignat;396;8;404 +03289;Treteau;519;13;532 +03290;Trévol;1625;59;1684 +03291;Trézelles;404;13;417 +03292;Tronget;897;14;911 +03293;Urçay;264;10;274 +03294;Ussel-d'Allier;162;1;163 +03295;Valignat;77;0;77 +03296;Valigny;376;12;388 +03297;Vallon-en-Sully;1564;29;1593 +03298;Varennes-sur-Allier;3561;72;3633 +03299;Varennes-sur-Tèche;245;9;254 +03300;Vaumas;538;12;550 +03301;Vaux;1121;25;1146 +03302;Veauce;38;1;39 +03303;Venas;235;8;243 +03304;Vendat;2216;58;2274 +03305;Verneix;603;11;614 +03306;Le Vernet;1941;57;1998 +03307;Verneuil-en-Bourbonnais;244;2;246 +03308;Vernusse;153;6;159 +03309;Le Veurdre;455;10;465 +03310;Vichy;24166;357;24523 +03311;Vicq;331;6;337 +03312;Vieure;279;6;285 +03313;Le Vilhain;275;8;283 +03314;Villebret;1316;36;1352 +03315;Villefranche-d'Allier;1328;43;1371 +03316;Villeneuve-sur-Allier;1071;16;1087 +03317;Viplaix;300;8;308 +03319;Voussac;480;10;490 +03320;Ygrande;775;16;791 +03321;Yzeure;13088;537;13625 +04001;Aiglun;1440;27;1467 +04004;Allemagne-en-Provence;539;28;567 +04005;Allons;143;2;145 +04006;Allos;797;7;804 +04007;Angles;68;0;68 +04008;Annot;1042;37;1079 +04009;Archail;15;0;15 +04012;Aubenas-les-Alpes;98;0;98 +04013;Aubignosc;592;15;607 +04016;Authon;62;0;62 +04017;Auzet;98;5;103 +04018;Banon;970;15;985 +04019;Barcelonnette;2598;202;2800 +04020;Barles;134;2;136 +04021;Barras;142;4;146 +04022;Barrême;432;8;440 +04023;Bayons;183;4;187 +04024;Beaujeu;130;3;133 +04025;Beauvezer;377;7;384 +04026;Bellaffaire;144;5;149 +04027;Bevons;240;54;294 +04028;Beynes;125;9;134 +04030;Blieux;60;0;60 +04031;Bras-d'Asse;568;10;578 +04032;Braux;125;0;125 +04034;La Brillanne;1149;15;1164 +04035;Brunet;278;6;284 +04036;Le Brusquet;958;28;986 +04037;Le Caire;71;2;73 +04039;Castellane;1524;40;1564 +04040;Le Castellard-Mélan;64;1;65 +04041;Le Castellet;293;6;299 +04042;Castellet-lès-Sausses;137;1;138 +04045;Céreste;1199;20;1219 +04046;Le Chaffaut-Saint-Jurson;689;114;803 +04047;Champtercier;844;20;864 +04049;Château-Arnoux-Saint-Auban;5139;109;5248 +04050;Châteaufort;28;0;28 +04051;Châteauneuf-Miravail;69;0;69 +04053;Châteauneuf-Val-Saint-Donat;504;20;524 +04054;Châteauredon;73;1;74 +04055;Chaudon-Norante;183;2;185 +04057;Clamensane;172;3;175 +04058;Claret;269;5;274 +04059;Clumanc;215;1;216 +04061;Colmars;496;5;501 +04062;La Condamine-Châtelard;155;4;159 +04063;Corbières-en-Provence;1184;32;1216 +04065;Cruis;642;5;647 +04066;Curbans;575;12;587 +04067;Curel;55;1;56 +04068;Dauphin;831;13;844 +04069;Demandolx;135;3;138 +04070;Digne-les-Bains;16460;869;17329 +04072;Draix;115;2;117 +04073;Enchastrayes;396;12;408 +04074;Entrages;104;2;106 +04075;Entrepierres;379;12;391 +04076;Entrevaux;852;22;874 +04077;Entrevennes;168;3;171 +04079;L' Escale;1389;35;1424 +04081;Esparron-de-Verdon;398;5;403 +04084;Estoublon;486;7;493 +04086;Faucon-de-Barcelonnette;319;16;335 +04085;Faucon-du-Caire;53;1;54 +04087;Fontienne;128;2;130 +04088;Forcalquier;5018;85;5103 +04090;Le Fugeret;200;2;202 +04091;Ganagobie;96;0;96 +04092;La Garde;89;3;92 +04093;Gigors;60;1;61 +04094;Gréoux-les-Bains;2634;47;2681 +04177;Hautes-Duyes;43;0;43 +04095;L' Hospitalet;90;0;90 +04096;Jausiers;1130;29;1159 +04097;La Javie;404;6;410 +04099;Lambruisse;95;5;100 +04101;Lardiers;126;3;129 +04102;Le Lauzet-Ubaye;186;2;188 +04104;Limans;369;10;379 +04106;Lurs;382;10;392 +04107;Majastres;4;0;4 +04108;Malijai;1975;30;2005 +04109;Mallefougasse-Augès;327;4;331 +04110;Mallemoisson;1046;25;1071 +04111;Mane;1349;26;1375 +04112;Manosque;22333;659;22992 +04113;Marcoux;464;15;479 +04115;Méailles;115;2;117 +04116;Les Mées;3735;43;3778 +04118;Melve;119;2;121 +04161;Méolans-Revel;339;8;347 +04121;Mézel;656;21;677 +04122;Mirabeau;511;10;521 +04123;Mison;1128;33;1161 +04124;Montagnac-Montpezat;424;11;435 +04126;Montclar;414;12;426 +04127;Montfort;332;3;335 +04128;Montfuron;210;0;210 +04129;Montjustin;58;1;59 +04130;Montlaux;195;2;197 +04132;Montsalier;139;1;140 +04133;Moriez;238;1;239 +04134;La Motte-du-Caire;560;5;565 +04135;Moustiers-Sainte-Marie;709;16;725 +04136;La Mure-Argens;325;8;333 +04137;Nibles;42;0;42 +04138;Niozelles;271;6;277 +04139;Noyers-sur-Jabron;524;7;531 +04140;Les Omergues;130;3;133 +04141;Ongles;372;9;381 +04142;Oppedette;52;1;53 +04143;Oraison;5882;73;5955 +04144;La Palud-sur-Verdon;349;3;352 +04145;Peipin;1464;35;1499 +04148;Peyroules;240;9;249 +04149;Peyruis;2858;49;2907 +04150;Piégut;186;4;190 +04151;Pierrerue;493;12;505 +04152;Pierrevert;3816;122;3938 +04154;Pontis;84;3;87 +04155;Prads-Haute-Bléone;182;1;183 +04156;Puimichel;247;1;248 +04157;Puimoisson;723;9;732 +04158;Quinson;417;9;426 +04159;Redortiers;81;5;86 +04160;Reillanne;1675;37;1712 +04162;Revest-des-Brousses;268;6;274 +04163;Revest-du-Bion;562;5;567 +04164;Revest-Saint-Martin;85;1;86 +04166;Riez;1856;26;1882 +04167;La Robine-sur-Galabre;299;6;305 +04169;La Rochegiron;100;3;103 +04170;La Rochette;70;0;70 +04171;Rougon;110;0;110 +04172;Roumoules;746;18;764 +04173;Saint-André-les-Alpes;1008;21;1029 +04174;Saint-Benoît;149;1;150 +04178;Saint-Étienne-les-Orgues;1296;34;1330 +04179;Saint-Geniez;96;2;98 +04180;Saint-Jacques;78;4;82 +04181;Saint-Jeannet;54;1;55 +04182;Saint-Julien-d'Asse;212;2;214 +04183;Saint-Julien-du-Verdon;144;3;147 +04184;Saint-Jurs;138;3;141 +04186;Saint-Laurent-du-Verdon;97;4;101 +04187;Saint-Lions;49;1;50 +04188;Saint-Maime;860;8;868 +04189;Saint-Martin-de-Brômes;590;12;602 +04190;Saint-Martin-les-Eaux;114;3;117 +04191;Saint-Martin-lès-Seyne;14;2;16 +04192;Saint-Michel-l'Observatoire;1238;25;1263 +04193;Saint-Paul-sur-Ubaye;186;7;193 +04194;Saint-Pierre;96;2;98 +04195;Saint-Pons;626;12;638 +04199;Saint-Vincent-sur-Jabron;191;11;202 +04175;Sainte-Croix-à-Lauze;88;1;89 +04176;Sainte-Croix-du-Verdon;119;4;123 +04197;Sainte-Tulle;3408;78;3486 +04200;Salignac;634;21;655 +04201;Saumane;118;3;121 +04202;Sausses;127;2;129 +04203;Selonnet;464;9;473 +04204;Senez;167;4;171 +04205;Seyne;1362;26;1388 +04206;Sigonce;428;11;439 +04207;Sigoyer;107;2;109 +04208;Simiane-la-Rotonde;596;16;612 +04209;Sisteron;7460;237;7697 +04210;Soleilhas;100;4;104 +04211;Sourribes;179;2;181 +04214;Tartonne;135;1;136 +04216;Thèze;236;4;240 +04217;Thoard;723;18;741 +04218;Thorame-Basse;226;3;229 +04219;Thorame-Haute;240;6;246 +04220;Les Thuiles;397;15;412 +04222;Turriers;318;9;327 +04033;Ubaye-Serre-Ponçon;741;18;759 +04224;Ubraye;92;1;93 +04226;Uvernet-Fours;586;14;600 +04227;Vachères;283;7;290 +04120;Val d'Oronaye;121;1;122 +04043;Val-de-Chalvagne;87;3;90 +04228;Valavoire;40;0;40 +04229;Valbelle;278;7;285 +04230;Valensole;3204;59;3263 +04231;Valernes;250;6;256 +04233;Vaumeilh;262;9;271 +04234;Venterol;241;2;243 +04235;Verdaches;59;1;60 +04236;Vergons;111;0;111 +04237;Le Vernet;129;3;132 +04240;Villars-Colmars;246;4;250 +04241;Villemus;189;5;194 +04242;Villeneuve;4196;75;4271 +04244;Volonne;1650;37;1687 +04245;Volx;3171;75;3246 +05001;Abriès-Ristolas;385;8;393 +05003;Aiguilles;429;9;438 +05004;Ancelle;916;15;931 +05006;L' Argentière-la-Bessée;2279;86;2365 +05007;Arvieux;365;4;369 +05008;Aspremont;358;4;362 +05009;Aspres-lès-Corps;104;3;107 +05010;Aspres-sur-Buëch;821;10;831 +05039;Aubessagne;698;12;710 +05011;Avançon;404;9;413 +05012;Baratier;603;10;613 +05013;Barcillonnette;136;5;141 +05014;Barret-sur-Méouge;220;3;223 +05016;La Bâtie-Montsaléon;254;1;255 +05017;La Bâtie-Neuve;2534;51;2585 +05018;La Bâtie-Vieille;342;12;354 +05019;La Beaume;154;3;157 +05021;Le Bersac;148;0;148 +05022;Bréziers;230;3;233 +05023;Briançon;11625;325;11950 +05025;Buissard;208;7;215 +05026;Ceillac;292;3;295 +05027;Cervières;188;4;192 +05028;Chabestan;129;4;133 +05029;Chabottes;825;23;848 +05031;Champcella;188;2;190 +05032;Champoléon;140;3;143 +05033;Chanousse;39;0;39 +05064;La Chapelle-en-Valgaudémar;104;3;107 +05038;Château-Ville-Vieille;345;10;355 +05035;Châteauneuf-d'Oze;28;3;31 +05036;Châteauroux-les-Alpes;1197;32;1229 +05037;Châteauvieux;490;19;509 +05040;Chorges;2973;80;3053 +05044;Crévoux;130;3;133 +05045;Crots;1075;27;1102 +05139;Dévoluy;966;27;993 +05046;Embrun;6155;411;6566 +05047;Éourres;137;4;141 +05048;L' Épine;196;6;202 +05049;Esparron;51;0;51 +05050;Espinasses;796;10;806 +05051;Étoile-Saint-Cyrice;30;2;32 +05052;Eygliers;791;12;803 +05054;La Fare-en-Champsaur;438;3;441 +05055;La Faurie;325;4;329 +05056;Forest-Saint-Julien;328;11;339 +05057;Fouillouse;243;5;248 +05058;Freissinières;210;6;216 +05059;La Freissinouse;849;21;870 +05060;Furmeyer;163;8;171 +05061;Gap;40895;1592;42487 +05053;Garde-Colombe;539;9;548 +05062;Le Glaizil;166;1;167 +05063;La Grave;482;10;492 +05065;Guillestre;2344;83;2427 +05066;La Haute-Beaume;9;0;9 +05068;Jarjayes;450;13;463 +05070;Laragne-Montéglin;3511;57;3568 +05071;Lardier-et-Valença;332;20;352 +05072;Laye;234;7;241 +05073;Lazer;359;15;374 +05074;Lettret;182;0;182 +05075;Manteyer;429;7;436 +05076;Méreuil;84;3;87 +05077;Molines-en-Queyras;300;5;305 +05078;Monêtier-Allemont;283;11;294 +05079;Le Monêtier-les-Bains;1056;23;1079 +05082;Mont-Dauphin;164;2;166 +05080;Montbrand;62;0;62 +05081;Montclus;57;4;61 +05084;Montgardin;464;5;469 +05085;Montgenèvre;456;14;470 +05086;Montjay;104;2;106 +05087;Montmaur;512;15;527 +05089;Montrond;74;1;75 +05090;La Motte-en-Champsaur;217;6;223 +05091;Moydans;44;2;46 +05092;Neffes;748;16;764 +05093;Névache;356;11;367 +05094;Nossage-et-Bénévent;15;1;16 +05095;Le Noyer;292;4;296 +05096;Orcières;690;19;709 +05097;Orpierre;352;34;386 +05098;Les Orres;577;7;584 +05099;Oze;106;1;107 +05100;Pelleautier;715;25;740 +05102;La Piarre;93;2;95 +05103;Le Poët;798;21;819 +05104;Poligny;296;7;303 +05106;Prunières;298;6;304 +05107;Puy-Saint-André;462;25;487 +05108;Puy-Saint-Eusèbe;138;3;141 +05109;Puy-Saint-Pierre;538;20;558 +05110;Puy-Saint-Vincent;288;5;293 +05111;Puy-Sanières;283;9;292 +05112;Rabou;79;0;79 +05113;Rambaud;376;16;392 +05114;Réallon;256;4;260 +05115;Remollon;442;3;445 +05116;Réotier;200;2;202 +05117;Ribeyret;113;0;113 +05119;Risoul;644;14;658 +05122;La Roche-de-Rame;824;27;851 +05123;La Roche-des-Arnauds;1521;37;1558 +05121;Rochebrune;171;2;173 +05124;La Rochette;466;9;475 +05126;Rosans;468;11;479 +05127;Rousset;183;5;188 +05128;Saint-André-d'Embrun;661;22;683 +05129;Saint-André-de-Rosans;151;2;153 +05130;Saint-Apollinaire;141;5;146 +05131;Saint-Auban-d'Oze;90;1;91 +05132;Saint-Bonnet-en-Champsaur;2036;69;2105 +05133;Saint-Chaffrey;1604;49;1653 +05134;Saint-Clément-sur-Durance;309;4;313 +05136;Saint-Crépin;733;16;749 +05140;Saint-Étienne-le-Laus;284;7;291 +05142;Saint-Firmin;458;18;476 +05144;Saint-Jacques-en-Valgodemard;147;2;149 +05145;Saint-Jean-Saint-Nicolas;1041;99;1140 +05146;Saint-Julien-en-Beauchêne;127;1;128 +05147;Saint-Julien-en-Champsaur;360;5;365 +05148;Saint-Laurent-du-Cros;532;18;550 +05149;Saint-Léger-les-Mélèzes;350;11;361 +05151;Saint-Martin-de-Queyrières;1130;34;1164 +05152;Saint-Maurice-en-Valgodemard;127;4;131 +05153;Saint-Michel-de-Chaillol;335;13;348 +05155;Saint-Pierre-Avez;29;1;30 +05154;Saint-Pierre-d'Argençon;156;5;161 +05156;Saint-Sauveur;499;11;510 +05157;Saint-Véran;236;6;242 +05135;Sainte-Colombe;55;0;55 +05158;Le Saix;107;1;108 +05159;Saléon;91;3;94 +05160;Salérans;90;0;90 +05161;La Salle-les-Alpes;982;24;1006 +05162;La Saulce;1555;32;1587 +05163;Le Sauze-du-Lac;146;4;150 +05164;Savines-le-Lac;1058;40;1098 +05165;Savournon;259;7;266 +05166;Serres;1287;27;1314 +05167;Sigottier;92;0;92 +05168;Sigoyer;665;20;685 +05169;Sorbiers;36;1;37 +05170;Tallard;2206;46;2252 +05171;Théus;200;9;209 +05172;Trescléoux;317;6;323 +05173;Upaix;450;5;455 +05118;Val Buëch-Méouge;1349;26;1375 +05174;Val-des-Prés;641;25;666 +05024;Valdoule;216;9;225 +05101;Vallouise-Pelvoux;1210;40;1250 +05176;Valserres;261;3;264 +05177;Vars;525;10;535 +05178;Ventavon;575;37;612 +05179;Veynes;3182;149;3331 +05180;Les Vigneaux;534;14;548 +05181;Villar-d'Arêne;311;14;325 +05182;Villar-Loubière;41;3;44 +05183;Villar-Saint-Pancrace;1472;54;1526 +05184;Vitrolles;204;8;212 +06001;Aiglun;91;0;91 +06002;Amirat;67;0;67 +06003;Andon;620;5;625 +06004;Antibes;72999;1162;74161 +06005;Ascros;169;0;169 +06006;Aspremont;2187;31;2218 +06007;Auribeau-sur-Siagne;3249;63;3312 +06008;Auvare;31;2;33 +06009;Bairols;105;1;106 +06010;Le Bar-sur-Loup;2936;64;3000 +06011;Beaulieu-sur-Mer;3715;28;3743 +06012;Beausoleil;13607;137;13744 +06013;Belvédère;677;11;688 +06014;Bendejun;952;6;958 +06015;Berre-les-Alpes;1253;21;1274 +06016;Beuil;525;4;529 +06017;Bézaudun-les-Alpes;249;5;254 +06018;Biot;9733;351;10084 +06019;Blausasc;1583;19;1602 +06020;La Bollène-Vésubie;575;12;587 +06021;Bonson;737;5;742 +06022;Bouyon;538;4;542 +06023;Breil-sur-Roya;2158;52;2210 +06024;Briançonnet;221;2;223 +06162;La Brigue;700;10;710 +06025;Le Broc;1413;8;1421 +06026;Cabris;1324;26;1350 +06027;Cagnes-sur-Mer;50928;478;51406 +06028;Caille;426;5;431 +06029;Cannes;73868;818;74686 +06030;Le Cannet;41471;393;41864 +06031;Cantaron;1306;11;1317 +06032;Cap-d'Ail;4594;72;4666 +06033;Carros;12329;140;12469 +06034;Castagniers;1616;14;1630 +06035;Castellar;1100;9;1109 +06036;Castillon;367;7;374 +06037;Caussols;287;3;290 +06040;Châteauneuf-d'Entraunes;58;0;58 +06038;Châteauneuf-Grasse;3505;59;3564 +06039;Châteauneuf-Villevieille;922;9;931 +06041;Cipières;396;2;398 +06042;Clans;638;13;651 +06043;Coaraze;831;4;835 +06044;La Colle-sur-Loup;7838;153;7991 +06045;Collongues;78;2;80 +06046;Colomars;3424;41;3465 +06047;Conségudes;99;1;100 +06048;Contes;7424;88;7512 +06049;Courmes;120;1;121 +06050;Coursegoules;531;5;536 +06051;La Croix-sur-Roudoule;97;2;99 +06052;Cuébris;172;2;174 +06053;Daluis;146;2;148 +06054;Drap;4546;37;4583 +06055;Duranus;140;3;143 +06056;Entraunes;138;2;140 +06057;L' Escarène;2520;17;2537 +06058;Escragnolles;609;5;614 +06059;Èze;2239;58;2297 +06060;Falicon;1992;33;2025 +06061;Les Ferres;105;0;105 +06062;Fontan;341;1;342 +06063;Gars;72;0;72 +06064;Gattières;4117;54;4171 +06065;La Gaude;6623;95;6718 +06066;Gilette;1596;11;1607 +06067;Gorbio;1549;14;1563 +06068;Gourdon;381;10;391 +06069;Grasse;50396;946;51342 +06070;Gréolières;586;13;599 +06071;Guillaumes;631;6;637 +06072;Ilonse;193;0;193 +06073;Isola;681;12;693 +06074;Lantosque;1312;10;1322 +06075;Levens;4738;46;4784 +06076;Lieuche;46;3;49 +06077;Lucéram;1284;12;1296 +06078;Malaussène;311;0;311 +06079;Mandelieu-la-Napoule;22452;263;22715 +06080;Marie;105;4;109 +06081;Le Mas;155;0;155 +06082;Massoins;102;1;103 +06083;Menton;28958;503;29461 +06084;Mouans-Sartoux;9701;318;10019 +06085;Mougins;19473;392;19865 +06086;Moulinet;273;4;277 +06087;Les Mujouls;51;1;52 +06088;Nice;340017;2962;342979 +06089;Opio;2214;72;2286 +06090;Pégomas;7972;88;8060 +06091;Peille;2376;19;2395 +06092;Peillon;1457;13;1470 +06093;La Penne;221;1;222 +06094;Péone;787;8;795 +06095;Peymeinade;8151;143;8294 +06096;Pierlas;103;0;103 +06097;Pierrefeu;324;0;324 +06098;Puget-Rostang;129;1;130 +06099;Puget-Théniers;1880;65;1945 +06100;Revest-les-Roches;235;1;236 +06101;Rigaud;211;3;214 +06102;Rimplas;91;5;96 +06107;La Roque-en-Provence;77;1;78 +06103;Roquebillière;1841;49;1890 +06104;Roquebrune-Cap-Martin;12639;187;12826 +06105;Roquefort-les-Pins;6762;180;6942 +06106;Roquestéron;581;6;587 +06108;La Roquette-sur-Siagne;5390;94;5484 +06109;La Roquette-sur-Var;940;4;944 +06110;Roubion;121;4;125 +06111;Roure;173;4;177 +06112;Le Rouret;3999;119;4118 +06114;Saint-André-de-la-Roche;5458;29;5487 +06115;Saint-Antonin;93;0;93 +06116;Saint-Auban;222;3;225 +06117;Saint-Blaise;1019;8;1027 +06118;Saint-Cézaire-sur-Siagne;3908;99;4007 +06119;Saint-Dalmas-le-Selvage;118;2;120 +06120;Saint-Étienne-de-Tinée;1531;160;1691 +06121;Saint-Jean-Cap-Ferrat;1573;8;1581 +06122;Saint-Jeannet;4128;106;4234 +06123;Saint-Laurent-du-Var;28453;203;28656 +06124;Saint-Léger;51;0;51 +06125;Saint-Martin-d'Entraunes;142;2;144 +06126;Saint-Martin-du-Var;3000;20;3020 +06127;Saint-Martin-Vésubie;1411;12;1423 +06128;Saint-Paul-de-Vence;3477;72;3549 +06129;Saint-Sauveur-sur-Tinée;308;82;390 +06130;Saint-Vallier-de-Thiey;3594;103;3697 +06113;Sainte-Agnès;1328;24;1352 +06131;Sallagriffon;49;2;51 +06132;Saorge;459;10;469 +06133;Sauze;70;1;71 +06134;Séranon;526;6;532 +06135;Sigale;198;2;200 +06136;Sospel;3831;70;3901 +06137;Spéracèdes;1264;26;1290 +06163;Tende;2178;49;2227 +06138;Théoule-sur-Mer;1413;14;1427 +06139;Thiéry;106;3;109 +06140;Le Tignet;3146;54;3200 +06141;Toudon;344;1;345 +06142;Touët-de-l'Escarène;282;1;283 +06143;Touët-sur-Var;672;11;683 +06144;La Tour;567;4;571 +06145;Tourette-du-Château;130;1;131 +06146;Tournefort;167;1;168 +06147;Tourrette-Levens;4951;46;4997 +06148;Tourrettes-sur-Loup;3999;79;4078 +06149;La Trinité;10017;60;10077 +06150;La Turbie;3063;55;3118 +06151;Utelle;873;1;874 +06152;Valbonne;13325;525;13850 +06153;Valdeblore;853;254;1107 +06154;Valderoure;452;8;460 +06155;Vallauris;26672;162;26834 +06156;Venanson;159;1;160 +06157;Vence;18465;304;18769 +06158;Villars-sur-Var;761;4;765 +06159;Villefranche-sur-Mer;5091;48;5139 +06160;Villeneuve-d'Entraunes;80;0;80 +06161;Villeneuve-Loubet;15241;184;15425 +07001;Accons;382;25;407 +07002;Ailhon;554;18;572 +07003;Aizac;169;4;173 +07004;Ajoux;77;2;79 +07005;Alba-la-Romaine;1444;35;1479 +07006;Albon-d'Ardèche;159;7;166 +07007;Alboussière;1004;14;1018 +07008;Alissas;1479;55;1534 +07009;Andance;1185;21;1206 +07010;Annonay;16345;611;16956 +07012;Arcens;376;9;385 +07013;Ardoix;1262;11;1273 +07014;Arlebosc;331;7;338 +07015;Arras-sur-Rhône;520;22;542 +07017;Les Assions;740;17;757 +07018;Astet;42;0;42 +07019;Aubenas;12172;761;12933 +07020;Aubignas;469;11;480 +07022;Baix;1164;25;1189 +07023;Balazuc;377;4;381 +07024;Banne;666;24;690 +07025;Barnas;207;2;209 +07026;Le Béage;255;8;263 +07027;Beauchastel;1822;29;1851 +07028;Beaulieu;498;15;513 +07029;Beaumont;244;3;247 +07030;Beauvène;210;5;215 +07165;Belsentes;550;18;568 +07031;Berrias-et-Casteljau;762;18;780 +07032;Berzème;174;1;175 +07033;Bessas;216;4;220 +07034;Bidon;241;2;243 +07035;Boffres;633;20;653 +07036;Bogy;434;11;445 +07037;Borée;151;3;154 +07038;Borne;51;0;51 +07040;Boucieu-le-Roi;269;5;274 +07041;Boulieu-lès-Annonay;2300;65;2365 +07042;Bourg-Saint-Andéol;7116;162;7278 +07039;Bozas;245;9;254 +07044;Brossainc;279;5;284 +07045;Burzet;439;6;445 +07047;Cellier-du-Luc;77;0;77 +07048;Chalencon;311;7;318 +07049;Le Chambon;46;3;49 +07050;Chambonas;905;15;920 +07051;Champagne;598;20;618 +07052;Champis;623;9;632 +07053;Chandolas;506;4;510 +07054;Chanéac;256;9;265 +07055;Charmes-sur-Rhône;2930;73;3003 +07056;Charnas;931;7;938 +07058;Chassiers;1022;34;1056 +07059;Châteaubourg;244;7;251 +07060;Châteauneuf-de-Vernoux;249;5;254 +07061;Chauzon;386;12;398 +07062;Chazeaux;139;3;142 +07063;Cheminas;402;9;411 +07064;Le Cheylard;2952;156;3108 +07065;Chirols;241;3;244 +07066;Chomérac;3030;175;3205 +07067;Colombier-le-Cardinal;292;4;296 +07068;Colombier-le-Jeune;573;6;579 +07069;Colombier-le-Vieux;661;20;681 +07070;Cornas;2237;47;2284 +07071;Coucouron;802;13;815 +07072;Coux;1642;42;1684 +07073;Le Crestet;519;11;530 +07074;Creysseilles;147;2;149 +07075;Cros-de-Géorand;159;4;163 +07076;Cruas;3008;66;3074 +07077;Darbres;248;3;251 +07078;Davézieux;3162;87;3249 +07079;Désaignes;1111;20;1131 +07080;Devesset;295;7;302 +07081;Dompnac;62;1;63 +07082;Dornas;207;12;219 +07083;Dunière-sur-Eyrieux;431;11;442 +07084;Eclassan;1025;39;1064 +07085;Empurany;598;14;612 +07086;Étables;906;18;924 +07087;Fabras;410;5;415 +07088;Faugères;100;2;102 +07089;Félines;1652;46;1698 +07090;Flaviac;1223;17;1240 +07091;Fons;329;12;341 +07092;Freyssenet;47;1;48 +07093;Genestelle;276;7;283 +07094;Gilhac-et-Bruzac;170;3;173 +07095;Gilhoc-sur-Ormèze;455;3;458 +07096;Gluiras;369;3;372 +07097;Glun;696;19;715 +07098;Gourdon;88;4;92 +07099;Gras;635;19;654 +07100;Gravières;474;11;485 +07101;Grospierres;885;22;907 +07102;Guilherand-Granges;10961;243;11204 +07104;Issamoulenc;91;3;94 +07105;Issanlas;102;3;105 +07106;Issarlès;145;2;147 +07107;Jaujac;1228;22;1250 +07108;Jaunac;127;9;136 +07109;Joannas;302;7;309 +07110;Joyeuse;1721;29;1750 +07111;Juvinas;172;4;176 +07113;Labastide-de-Virac;301;7;308 +07112;Labastide-sur-Bésorgues;258;6;264 +07114;Labatie-d'Andaure;206;2;208 +07115;Labeaume;677;11;688 +07116;Labégude;1393;19;1412 +07117;Lablachère;2143;35;2178 +07118;Laboule;137;6;143 +07119;Le Lac-d'Issarlès;286;6;292 +07120;Lachamp-Raphaël;63;0;63 +07121;Lachapelle-Graillouse;199;0;199 +07122;Lachapelle-sous-Aubenas;1604;44;1648 +07123;Lachapelle-sous-Chanéac;172;3;175 +07124;Lafarre;39;1;40 +07126;Lagorce;1160;23;1183 +07127;Lalevade-d'Ardèche;1107;15;1122 +07128;Lalouvesc;386;5;391 +07129;Lamastre;2318;68;2386 +07130;Lanarce;200;2;202 +07131;Lanas;430;35;465 +07132;Largentière;1629;68;1697 +07133;Larnas;238;3;241 +07134;Laurac-en-Vivarais;995;25;1020 +07136;Laveyrune;107;1;108 +07137;Lavillatte;57;0;57 +07138;Lavilledieu;2122;42;2164 +07139;Laviolle;109;2;111 +07140;Lemps;785;24;809 +07141;Lentillères;231;7;238 +07142;Lespéron;320;7;327 +07143;Limony;758;18;776 +07144;Loubaresse;41;2;43 +07145;Lussas;1159;25;1184 +07146;Lyas;601;15;616 +07147;Malarce-sur-la-Thines;244;5;249 +07148;Malbosc;145;8;153 +07149;Marcols-les-Eaux;296;5;301 +07150;Mariac;572;20;592 +07151;Mars;264;7;271 +07152;Mauves;1177;26;1203 +07153;Mayres;262;5;267 +07154;Mazan-l'Abbaye;122;1;123 +07155;Mercuer;1210;47;1257 +07156;Meyras;938;29;967 +07157;Meysse;1319;15;1334 +07158;Mézilhac;95;0;95 +07159;Mirabel;654;13;667 +07160;Monestier;61;1;62 +07161;Montpezat-sous-Bauzon;797;23;820 +07162;Montréal;572;19;591 +07163;Montselgues;82;7;89 +07166;Nozières;258;5;263 +07167;Les Ollières-sur-Eyrieux;990;19;1009 +07168;Orgnac-l'Aven;585;17;602 +07169;Ozon;398;2;400 +07170;Pailharès;244;6;250 +07171;Payzac;536;6;542 +07172;Peaugres;2148;48;2196 +07173;Péreyres;49;0;49 +07174;Peyraud;495;6;501 +07175;Le Plagnal;77;1;78 +07176;Planzolles;135;2;137 +07177;Plats;854;14;868 +07178;Pont-de-Labeaume;571;14;585 +07179;Pourchères;131;2;133 +07181;Le Pouzin;2879;39;2918 +07182;Prades;1213;31;1244 +07183;Pradons;470;10;480 +07184;Pranles;491;13;504 +07185;Préaux;690;15;705 +07186;Privas;8266;340;8606 +07187;Prunet;132;4;136 +07188;Quintenas;1630;36;1666 +07189;Ribes;295;4;299 +07190;Rochecolombe;211;5;216 +07191;Rochemaure;2281;49;2330 +07192;Rochepaule;259;8;267 +07193;Rocher;270;4;274 +07194;Rochessauve;450;10;460 +07195;La Rochette;59;2;61 +07196;Rocles;249;4;253 +07197;Roiffieux;2785;85;2870 +07198;Rompon;1083;29;1112 +07199;Rosières;1190;39;1229 +07200;Le Roux;53;1;54 +07201;Ruoms;2253;28;2281 +07202;Sablières;164;4;168 +07203;Sagnes-et-Goudoulet;117;0;117 +07204;Saint-Agrève;2353;63;2416 +07207;Saint-Alban-Auriolles;1091;16;1107 +07205;Saint-Alban-d'Ay;1397;23;1420 +07206;Saint-Alban-en-Montagne;93;1;94 +07208;Saint-Andéol-de-Berg;123;3;126 +07209;Saint-Andéol-de-Fourchades;53;2;55 +07210;Saint-Andéol-de-Vals;526;11;537 +07211;Saint-André-de-Cruzières;464;14;478 +07212;Saint-André-en-Vivarais;213;3;216 +07213;Saint-André-Lachamp;154;1;155 +07214;Saint-Apollinaire-de-Rias;201;2;203 +07216;Saint-Barthélemy-Grozon;506;25;531 +07215;Saint-Barthélemy-le-Meil;195;6;201 +07217;Saint-Barthélemy-le-Plain;825;20;845 +07218;Saint-Basile;353;10;363 +07219;Saint-Bauzile;308;6;314 +07220;Saint-Christol;103;0;103 +07221;Saint-Cierge-la-Serre;249;4;253 +07222;Saint-Cierge-sous-le-Cheylard;203;5;208 +07223;Saint-Cirgues-de-Prades;140;5;145 +07224;Saint-Cirgues-en-Montagne;210;16;226 +07225;Saint-Clair;1119;42;1161 +07226;Saint-Clément;86;0;86 +07227;Saint-Cyr;1372;46;1418 +07228;Saint-Désirat;877;25;902 +07229;Saint-Didier-sous-Aubenas;961;26;987 +07230;Saint-Étienne-de-Boulogne;404;14;418 +07231;Saint-Étienne-de-Fontbellon;2717;81;2798 +07232;Saint-Étienne-de-Lugdarès;419;8;427 +07233;Saint-Étienne-de-Serre;221;5;226 +07234;Saint-Étienne-de-Valoux;294;3;297 +07236;Saint-Félicien;1191;20;1211 +07237;Saint-Fortunat-sur-Eyrieux;775;14;789 +07238;Saint-Genest-de-Beauzon;318;7;325 +07239;Saint-Genest-Lachamp;104;2;106 +07240;Saint-Georges-les-Bains;2282;42;2324 +07241;Saint-Germain;710;17;727 +07242;Saint-Gineis-en-Coiron;115;4;119 +07243;Saint-Jacques-d'Atticieux;309;6;315 +07244;Saint-Jean-Chambre;265;5;270 +07245;Saint-Jean-de-Muzols;2458;66;2524 +07247;Saint-Jean-le-Centenier;776;13;789 +07248;Saint-Jean-Roure;258;11;269 +07249;Saint-Jeure-d'Andaure;102;2;104 +07250;Saint-Jeure-d'Ay;479;9;488 +07251;Saint-Joseph-des-Bancs;174;3;177 +07103;Saint-Julien-d'Intres;329;3;332 +07253;Saint-Julien-du-Gua;190;3;193 +07254;Saint-Julien-du-Serre;879;19;898 +07255;Saint-Julien-en-Saint-Alban;1514;25;1539 +07257;Saint-Julien-le-Roux;109;3;112 +07258;Saint-Julien-Vocance;227;2;229 +07259;Saint-Just-d'Ardèche;1684;37;1721 +07260;Saint-Lager-Bressac;922;16;938 +07261;Saint-Laurent-du-Pape;1566;39;1605 +07262;Saint-Laurent-les-Bains-Laval-d'Aurelle;177;2;179 +07263;Saint-Laurent-sous-Coiron;100;4;104 +07264;Saint-Marcel-d'Ardèche;2375;68;2443 +07265;Saint-Marcel-lès-Annonay;1422;36;1458 +07267;Saint-Martial;251;4;255 +07268;Saint-Martin-d'Ardèche;979;12;991 +07269;Saint-Martin-de-Valamas;1115;38;1153 +07270;Saint-Martin-sur-Lavezon;432;12;444 +07272;Saint-Maurice-d'Ardèche;306;12;318 +07273;Saint-Maurice-d'Ibie;221;4;225 +07274;Saint-Maurice-en-Chalencon;220;6;226 +07275;Saint-Mélany;111;3;114 +07276;Saint-Michel-d'Aurance;274;21;295 +07277;Saint-Michel-de-Boulogne;156;5;161 +07278;Saint-Michel-de-Chabrillanoux;354;12;366 +07279;Saint-Montan;1897;45;1942 +07280;Saint-Paul-le-Jeune;970;20;990 +07281;Saint-Péray;7692;239;7931 +07282;Saint-Pierre-de-Colombier;411;25;436 +07283;Saint-Pierre-la-Roche;59;2;61 +07284;Saint-Pierre-Saint-Jean;145;4;149 +07285;Saint-Pierre-sur-Doux;107;1;108 +07286;Saint-Pierreville;544;11;555 +07287;Saint-Pons;293;17;310 +07288;Saint-Priest;1200;50;1250 +07289;Saint-Privat;1735;52;1787 +07290;Saint-Prix;276;7;283 +07291;Saint-Remèze;871;19;890 +07292;Saint-Romain-d'Ay;1214;36;1250 +07293;Saint-Romain-de-Lerps;873;18;891 +07294;Saint-Sauveur-de-Cruzières;531;14;545 +07295;Saint-Sauveur-de-Montagut;1111;29;1140 +07296;Saint-Sernin;1663;44;1707 +07297;Saint-Sylvestre;508;7;515 +07299;Saint-Symphorien-de-Mahun;120;4;124 +07298;Saint-Symphorien-sous-Chomérac;757;30;787 +07300;Saint-Thomé;445;15;460 +07301;Saint-Victor;949;12;961 +07302;Saint-Vincent-de-Barrès;837;22;859 +07303;Saint-Vincent-de-Durfort;225;5;230 +07235;Sainte-Eulalie;215;4;219 +07266;Sainte-Marguerite-Lafigère;107;2;109 +07304;Salavas;682;11;693 +07305;Les Salelles;366;9;375 +07306;Sampzon;228;7;235 +07307;Sanilhac;446;9;455 +07308;Sarras;2199;35;2234 +07309;Satillieu;1546;31;1577 +07310;Savas;900;24;924 +07311;Sceautres;144;7;151 +07312;Sécheras;554;4;558 +07313;Serrières;1146;17;1163 +07314;Silhac;368;12;380 +07315;La Souche;370;10;380 +07316;Soyons;2238;47;2285 +07317;Talencieux;1067;31;1098 +07318;Tauriers;192;5;197 +07319;Le Teil;8677;219;8896 +07321;Thorrenc;233;6;239 +07322;Thueyts;1203;25;1228 +07323;Toulaud;1700;52;1752 +07324;Tournon-sur-Rhône;10307;515;10822 +07325;Ucel;2043;72;2115 +07326;Usclades-et-Rieutord;115;0;115 +07327;Uzer;414;12;426 +07328;Vagnas;544;8;552 +07329;Valgorge;436;7;443 +07011;Vallées-d'Antraigues-Asperjoc;947;12;959 +07330;Vallon-Pont-d'Arc;2382;40;2422 +07331;Vals-les-Bains;3582;71;3653 +07332;Valvignères;466;13;479 +07333;Vanosc;936;13;949 +07334;Les Vans;2672;62;2734 +07335;Vaudevant;205;2;207 +07336;Vernon;232;7;239 +07337;Vernosc-lès-Annonay;2647;42;2689 +07338;Vernoux-en-Vivarais;1958;31;1989 +07339;Vesseaux;1928;56;1984 +07340;Veyras;1527;49;1576 +07341;Villeneuve-de-Berg;2944;129;3073 +07342;Villevocance;1171;28;1199 +07343;Vinezac;1371;39;1410 +07344;Vinzieux;453;3;456 +07345;Vion;939;23;962 +07346;Viviers;3730;57;3787 +07347;Vocance;610;3;613 +07348;Vogüé;1087;27;1114 +07349;La Voulte-sur-Rhône;4987;59;5046 +08001;Acy-Romance;446;3;449 +08003;Aiglemont;1634;34;1668 +08004;Aire;220;4;224 +08005;Alincourt;150;2;152 +08006;Alland'Huy-et-Sausseuil;245;4;249 +08008;Amagne;725;6;731 +08010;Ambly-Fleury;134;5;139 +08011;Anchamps;217;4;221 +08013;Angecourt;392;4;396 +08014;Annelles;141;6;147 +08015;Antheny;99;5;104 +08016;Aouste;207;2;209 +08017;Apremont;117;3;120 +08018;Ardeuil-et-Montfauxelles;68;1;69 +08021;Arnicourt;157;3;160 +08022;Arreux;324;12;336 +08023;Artaise-le-Vivier;66;1;67 +08024;Asfeld;1116;16;1132 +08025;Attigny;1128;24;1152 +08026;Aubigny-les-Pothées;315;6;321 +08027;Auboncourt-Vauzelles;100;3;103 +08028;Aubrives;910;19;929 +08029;Auflance;86;3;89 +08030;Auge;60;0;60 +08031;Aure;48;4;52 +08032;Aussonce;215;3;218 +08033;Authe;90;4;94 +08034;Autrecourt-et-Pourron;342;6;348 +08035;Autruche;69;4;73 +08036;Autry;117;8;125 +08037;Auvillers-les-Forges;877;10;887 +08038;Avançon;313;6;319 +08039;Avaux;466;13;479 +08040;Les Ayvelles;897;12;909 +08041;Baâlons;207;8;215 +08116;Bairon et ses environs;1041;17;1058 +08043;Balan;1618;30;1648 +08044;Balham;152;1;153 +08045;Ballay;289;7;296 +08046;Banogne-Recouvrance;157;4;161 +08049;Bar-lès-Buzancy;125;3;128 +08047;Barbaise;101;0;101 +08048;Barby;415;4;419 +08052;Bayonville;99;5;104 +08053;Bazeilles;2394;218;2612 +08055;Beaumont-en-Argonne;430;9;439 +08056;Beffu-et-le-Morthomme;48;0;48 +08057;Belleville-et-Châtillon-sur-Bar;272;50;322 +08058;Belval;222;6;228 +08059;Belval-Bois-des-Dames;33;1;34 +08060;Bergnicourt;285;1;286 +08061;La Berlière;40;1;41 +08062;Bertoncourt;127;8;135 +08063;La Besace;141;0;141 +08064;Biermes;307;5;312 +08065;Bièvres;49;1;50 +08066;Bignicourt;68;1;69 +08067;Blagny;1190;19;1209 +08069;Blanchefosse-et-Bay;151;1;152 +08070;Blanzy-la-Salonnaise;344;6;350 +08071;Blombay;139;2;141 +08081;Bogny-sur-Meuse;5100;74;5174 +08073;Bossus-lès-Rumigny;103;1;104 +08074;Bouconville;53;3;56 +08075;Boult-aux-Bois;138;3;141 +08076;Boulzicourt;958;19;977 +08077;Bourcq;52;1;53 +08078;Bourg-Fidèle;862;15;877 +08080;Bouvellemont;121;0;121 +08082;Brécy-Brières;76;2;78 +08083;Brévilly;367;7;374 +08084;Brienne-sur-Aisne;258;2;260 +08085;Brieulles-sur-Bar;217;7;224 +08086;Briquenay;98;7;105 +08087;Brognon;148;2;150 +08088;Bulson;134;4;138 +08089;Buzancy;348;9;357 +08090;Carignan;2885;45;2930 +08092;Cauroy;189;8;197 +08094;Cernion;58;3;61 +08095;Chagny;184;6;190 +08096;Chalandry-Elaire;669;14;683 +08097;Challerange;447;7;454 +08099;Champigneul-sur-Vence;122;4;126 +08098;Champigneulle;59;1;60 +08100;Champlin;71;3;74 +08101;La Chapelle;178;4;182 +08102;Chappes;101;0;101 +08103;Charbogne;225;8;233 +08104;Chardeny;55;1;56 +08105;Charleville-Mézières;46428;1143;47571 +08106;Charnois;77;0;77 +08107;Château-Porcien;1367;17;1384 +08109;Chatel-Chéhéry;146;3;149 +08111;Le Châtelet-sur-Retourne;794;10;804 +08110;Le Châtelet-sur-Sormonne;160;2;162 +08113;Chaumont-Porcien;485;10;495 +08115;Chémery-Chéhéry;578;13;591 +08117;Chesnois-Auboncourt;169;0;169 +08119;Cheveuges;430;7;437 +08120;Chevières;45;2;47 +08121;Chilly;143;5;148 +08122;Chooz;745;17;762 +08123;Chuffilly-Roche;75;1;76 +08124;Clavy-Warby;348;9;357 +08125;Cliron;377;9;386 +08128;Condé-lès-Autry;67;2;69 +08126;Condé-lès-Herpy;217;4;221 +08130;Contreuve;80;3;83 +08131;Cornay;63;3;66 +08132;Corny-Machéroménil;193;2;195 +08133;Coucy;505;6;511 +08134;Coulommes-et-Marqueny;83;1;84 +08135;La Croix-aux-Bois;149;3;152 +08136;Daigny;349;8;357 +08137;Damouzy;447;12;459 +08138;Les Deux-Villes;254;3;257 +08139;Deville;1041;10;1051 +08140;Dom-le-Mesnil;1087;19;1106 +08141;Dommery;181;4;185 +08142;Donchery;2087;28;2115 +08143;Doumely-Bégny;76;0;76 +08144;Doux;100;0;100 +08145;Douzy;2167;61;2228 +08146;Draize;103;0;103 +08147;Dricourt;84;9;93 +08148;L' Écaille;275;7;282 +08149;L' Échelle;137;5;142 +08150;Écly;176;5;181 +08151;Écordal;324;8;332 +08153;Escombres-et-le-Chesnois;349;5;354 +08154;Estrebay;74;3;77 +08155;Étalle;103;5;108 +08156;Éteignières;516;3;519 +08158;Étrépigny;291;8;299 +08159;Euilly-et-Lombut;114;4;118 +08160;Évigny;190;4;194 +08161;Exermont;42;1;43 +08162;Fagnon;342;6;348 +08163;Faissault;251;4;255 +08164;Falaise;331;8;339 +08165;Faux;57;1;58 +08166;Fépin;265;2;267 +08167;La Férée;83;2;85 +08168;La Ferté-sur-Chiers;172;4;176 +08169;Flaignes-Havys;121;1;122 +08170;Fleigneux;202;7;209 +08171;Fléville;97;4;101 +08172;Fligny;185;1;186 +08173;Flize;1723;52;1775 +08174;Floing;2349;56;2405 +08175;Foisches;204;7;211 +08176;Fossé;54;1;55 +08178;Fraillicourt;189;5;194 +08179;Francheval;609;13;622 +08180;La Francheville;1685;45;1730 +08182;Le Fréty;58;0;58 +08183;Fromelennes;1038;22;1060 +08184;Fromy;82;2;84 +08185;Fumay;3481;60;3541 +08186;Germont;48;0;48 +08187;Gernelle;313;8;321 +08188;Gespunsart;1057;22;1079 +08189;Girondelle;153;2;155 +08190;Givet;6749;159;6908 +08191;Givonne;1043;34;1077 +08192;Givron;86;1;87 +08193;Givry;272;6;278 +08194;Glaire;884;13;897 +08195;Gomont;326;3;329 +08196;Grandchamp;97;0;97 +08019;Les Grandes-Armoises;61;0;61 +08197;Grandham;39;1;40 +08198;Grandpré;540;17;557 +08199;La Grandville;795;17;812 +08200;Grivy-Loisy;184;6;190 +08201;Gruyères;99;2;101 +08202;Gué-d'Hossus;526;3;529 +08203;Guignicourt-sur-Vence;302;6;308 +08204;Guincourt;90;2;92 +08205;Hagnicourt;80;3;83 +08206;Ham-les-Moines;372;5;377 +08207;Ham-sur-Meuse;238;2;240 +08208;Hannappes;141;0;141 +08209;Hannogne-Saint-Martin;465;5;470 +08210;Hannogne-Saint-Rémy;113;4;117 +08211;Haraucourt;731;4;735 +08212;Harcy;507;10;517 +08214;Hargnies;484;3;487 +08215;Harricourt;40;2;42 +08216;Haudrecy;305;13;318 +08217;Haulmé;91;1;92 +08218;Les Hautes-Rivières;1482;25;1507 +08219;Hauteville;108;1;109 +08220;Hauviné;327;8;335 +08222;Haybes;1885;57;1942 +08223;Herbeuval;121;2;123 +08225;Herpy-l'Arlésienne;199;5;204 +08226;Hierges;195;5;200 +08228;La Horgne;194;9;203 +08229;Houdilcourt;133;7;140 +08230;Houldizy;374;5;379 +08232;Illy;411;9;420 +08233;Imécourt;49;1;50 +08234;Inaumont;99;0;99 +08235;Issancourt-et-Rumel;384;12;396 +08236;Jandun;285;10;295 +08237;Joigny-sur-Meuse;678;19;697 +08238;Jonval;98;1;99 +08239;Juniville;1226;28;1254 +08240;Justine-Herbigny;175;1;176 +08242;Laifour;449;8;457 +08243;Lalobbe;169;4;173 +08244;Lametz;72;3;75 +08246;Landres-et-Saint-Georges;79;1;80 +08247;Landrichamps;131;2;133 +08245;Lançon;33;3;36 +08248;Launois-sur-Vence;699;9;708 +08249;Laval-Morency;243;10;253 +08250;Leffincourt;189;6;195 +08251;Lépron-les-Vallées;78;2;80 +08252;Létanne;129;3;132 +08254;Liart;605;10;615 +08255;Linay;250;3;253 +08256;Liry;88;1;89 +08257;Logny-Bogny;168;3;171 +08259;Longwé;73;2;75 +08260;Lonny;648;11;659 +08262;Lucquy;580;34;614 +08263;Lumes;1142;25;1167 +08264;Machault;505;11;516 +08268;Maisoncelle-et-Villers;69;4;73 +08269;Malandry;82;1;83 +08271;Manre;100;6;106 +08272;Maranwez;61;0;61 +08273;Marby;62;1;63 +08274;Marcq;100;1;101 +08275;Margny;192;4;196 +08276;Margut;770;15;785 +08277;Marlemont;140;4;144 +08278;Marquigny;84;0;84 +08279;Mars-sous-Bourcq;55;2;57 +08280;Marvaux-Vieux;73;2;75 +08281;Matton-et-Clémency;469;9;478 +08282;Maubert-Fontaine;1031;71;1102 +08283;Mazerny;125;1;126 +08284;Les Mazures;903;23;926 +08286;Ménil-Annelles;108;5;113 +08287;Ménil-Lépinois;136;2;138 +08288;Mesmont;95;1;96 +08289;Messincourt;612;8;620 +08291;Mogues;216;4;220 +08293;Moiry;148;0;148 +08294;La Moncelle;141;2;143 +08295;Mondigny;171;4;175 +08300;Le Mont-Dieu;16;0;16 +08306;Mont-Laurent;62;1;63 +08308;Mont-Saint-Martin;83;0;83 +08309;Mont-Saint-Remy;56;1;57 +08296;Montcheutin;128;8;136 +08297;Montcornet;297;8;305 +08298;Montcy-Notre-Dame;1600;44;1644 +08301;Montgon;66;4;70 +08302;Monthermé;2335;85;2420 +08303;Monthois;374;10;384 +08304;Montigny-sur-Meuse;80;2;82 +08305;Montigny-sur-Vence;243;5;248 +08307;Montmeillant;83;1;84 +08310;Mouron;73;5;78 +08311;Mouzon;2305;40;2345 +08312;Murtin-et-Bogny;182;7;189 +08313;Nanteuil-sur-Aisne;135;4;139 +08314;Neuflize;783;23;806 +08315;Neufmaison;69;2;71 +08316;Neufmanil;1020;16;1036 +08317;La Neuville-à-Maire;123;4;127 +08318;La Neuville-aux-Joûtes;361;8;369 +08321;Neuville-Day;158;2;160 +08320;La Neuville-en-Tourne-à-Fuy;578;10;588 +08322;Neuville-lès-This;376;14;390 +08323;La Neuville-lès-Wasigny;160;1;161 +08319;Neuville-lez-Beaulieu;335;8;343 +08324;Neuvizy;117;2;119 +08325;Noirval;27;1;28 +08326;Nouart;141;2;143 +08327;Nouvion-sur-Meuse;2250;36;2286 +08328;Nouzonville;5836;110;5946 +08329;Novion-Porcien;488;10;498 +08330;Novy-Chevrières;735;9;744 +08331;Noyers-Pont-Maugis;684;14;698 +08332;Oches;44;4;48 +08333;Olizy-Primat;234;9;243 +08334;Omicourt;40;2;42 +08335;Omont;84;1;85 +08336;Osnes;230;3;233 +08338;Pauvres;188;3;191 +08339;Perthes;309;8;317 +08020;Les Petites-Armoises;63;0;63 +08340;Poilcourt-Sydney;181;4;185 +08341;Poix-Terron;819;41;860 +08342;Pouru-aux-Bois;266;5;271 +08343;Pouru-Saint-Remy;1163;25;1188 +08344;Prez;136;2;138 +08346;Prix-lès-Mézières;1340;31;1371 +08347;Puilly-et-Charbeaux;227;5;232 +08348;Puiseux;116;3;119 +08349;Pure;604;6;610 +08350;Quatre-Champs;218;3;221 +08351;Quilly;82;0;82 +08352;Raillicourt;202;4;206 +08353;Rancennes;719;23;742 +08354;Raucourt-et-Flaba;841;13;854 +08355;Regniowez;391;7;398 +08356;Remaucourt;173;1;174 +08357;Remilly-Aillicourt;780;15;795 +08358;Remilly-les-Pothées;254;4;258 +08360;Renneville;203;5;208 +08361;Renwez;1688;44;1732 +08362;Rethel;7592;303;7895 +08363;Revin;6239;140;6379 +08364;Rilly-sur-Aisne;141;3;144 +08365;Rimogne;1383;22;1405 +08366;Rocquigny;686;10;696 +08367;Rocroi;2330;29;2359 +08368;Roizy;219;3;222 +08369;La Romagne;130;2;132 +08370;Rouvroy-sur-Audry;583;5;588 +08372;Rubigny;67;0;67 +08373;Rumigny;328;4;332 +08374;La Sabotterie;112;3;115 +08375;Sachy;182;6;188 +08376;Sailly;253;3;256 +08377;Saint-Aignan;149;2;151 +08378;Saint-Clément-à-Arnes;107;1;108 +08379;Saint-Étienne-à-Arnes;242;2;244 +08380;Saint-Fergeux;210;4;214 +08381;Saint-Germainmont;842;12;854 +08382;Saint-Jean-aux-Bois;107;3;110 +08383;Saint-Juvin;104;4;108 +08384;Saint-Lambert-et-Mont-de-Jeux;145;4;149 +08385;Saint-Laurent;1104;171;1275 +08386;Saint-Loup-en-Champagne;323;7;330 +08387;Saint-Loup-Terrier;179;6;185 +08388;Saint-Marceau;346;11;357 +08389;Saint-Marcel;358;7;365 +08391;Saint-Menges;972;16;988 +08392;Saint-Morel;210;7;217 +08393;Saint-Pierre-à-Arnes;67;2;69 +08395;Saint-Pierre-sur-Vence;121;5;126 +08394;Saint-Pierremont;73;3;76 +08396;Saint-Quentin-le-Petit;120;0;120 +08397;Saint-Remy-le-Petit;42;2;44 +08390;Sainte-Marie;80;4;84 +08398;Sainte-Vaubourg;87;2;89 +08400;Sapogne-et-Feuchères;516;10;526 +08399;Sapogne-sur-Marche;138;3;141 +08401;Saulces-Champenoises;243;1;244 +08402;Saulces-Monclin;811;10;821 +08403;Sault-lès-Rethel;1915;18;1933 +08404;Sault-Saint-Remy;204;3;207 +08405;Sauville;245;8;253 +08406;Savigny-sur-Aisne;375;12;387 +08407;Séchault;61;0;61 +08408;Sécheval;554;10;564 +08409;Sedan;16428;349;16777 +08410;Semide;190;19;209 +08411;Semuy;90;0;90 +08412;Senuc;167;2;169 +08413;Seraincourt;279;3;282 +08415;Sery;357;7;364 +08416;Seuil;158;6;164 +08417;Sévigny-la-Forêt;276;8;284 +08418;Sévigny-Waleppe;227;3;230 +08419;Signy-l'Abbaye;1363;28;1391 +08420;Signy-le-Petit;1243;23;1266 +08421;Signy-Montlibert;92;0;92 +08422;Singly;135;3;138 +08424;Sommauthe;114;0;114 +08425;Sommerance;37;2;39 +08426;Son;99;0;99 +08427;Sorbon;196;2;198 +08428;Sorcy-Bauthémont;151;4;155 +08429;Sormonne;544;14;558 +08430;Stonne;41;2;43 +08431;Sugny;100;3;103 +08432;Sury;108;4;112 +08433;Suzanne;64;2;66 +08434;Sy;51;1;52 +08435;Tagnon;884;13;897 +08436;Taillette;402;7;409 +08437;Tailly;174;6;180 +08438;Taizy;105;2;107 +08439;Tannay;156;4;160 +08440;Tarzy;154;2;156 +08444;Tétaigne;131;3;134 +08445;Thelonne;406;2;408 +08446;Thénorgues;84;0;84 +08448;Thilay;1061;12;1073 +08449;Thin-le-Moutier;623;10;633 +08450;This;227;6;233 +08451;Le Thour;402;9;411 +08452;Thugny-Trugny;266;0;266 +08453;Toges;101;3;104 +08454;Touligny;85;2;87 +08455;Tourcelles-Chaumont;92;1;93 +08456;Tournavaux;241;4;245 +08457;Tournes;1076;27;1103 +08458;Tourteron;179;4;183 +08459;Tremblois-lès-Carignan;168;1;169 +08460;Tremblois-lès-Rocroi;156;0;156 +08461;Vandy;207;1;208 +08462;Vaux-Champagne;129;4;133 +08463;Vaux-en-Dieulet;54;1;55 +08464;Vaux-lès-Mouron;81;3;84 +08466;Vaux-lès-Mouzon;73;2;75 +08465;Vaux-lès-Rubigny;47;3;50 +08467;Vaux-Montreuil;108;0;108 +08468;Vaux-Villaine;195;1;196 +08469;Vendresse;494;12;506 +08470;Verpel;67;3;70 +08471;Verrières;27;2;29 +08472;Viel-Saint-Remy;301;2;303 +08473;Vieux-lès-Asfeld;314;7;321 +08483;Ville-sur-Lumes;520;16;536 +08484;Ville-sur-Retourne;83;1;84 +08476;Villers-devant-le-Thour;419;6;425 +08477;Villers-devant-Mouzon;101;0;101 +08478;Villers-le-Tilleul;237;3;240 +08479;Villers-le-Tourneur;194;2;196 +08480;Villers-Semeuse;3604;69;3673 +08481;Villers-sur-Bar;247;5;252 +08482;Villers-sur-le-Mont;110;4;114 +08485;Villy;215;2;217 +08486;Vireux-Molhain;1498;32;1530 +08487;Vireux-Wallerand;1962;57;2019 +08488;Vivier-au-Court;2954;90;3044 +08489;Voncq;217;6;223 +08490;Vouziers;4340;149;4489 +08491;Vrigne aux Bois;3623;78;3701 +08492;Vrigne-Meuse;300;1;301 +08494;Wadelincourt;473;5;478 +08496;Wagnon;128;1;129 +08497;Warcq;1275;25;1300 +08498;Warnécourt;372;16;388 +08499;Wasigny;331;3;334 +08500;Wignicourt;58;1;59 +08501;Williers;42;3;45 +08502;Yoncq;101;3;104 +08503;Yvernaumont;139;5;144 +09001;Aigues-Juntes;67;0;67 +09002;Aigues-Vives;666;13;679 +09003;L' Aiguillon;429;10;439 +09004;Albiès;123;7;130 +09005;Aleu;130;2;132 +09006;Alliat;51;1;52 +09007;Allières;71;1;72 +09008;Alos;117;2;119 +09009;Alzen;260;11;271 +09011;Antras;65;1;66 +09012;Appy;25;0;25 +09013;Arabaux;76;2;78 +09014;Argein;194;7;201 +09015;Arignac;707;8;715 +09016;Arnave;207;7;214 +09017;Arrien-en-Bethmale;111;2;113 +09018;Arrout;85;4;89 +09019;Artigat;564;10;574 +09020;Artigues;56;1;57 +09021;Artix;141;3;144 +09022;Arvigna;223;0;223 +09023;Ascou;121;1;122 +09024;Aston;220;2;222 +09025;Aucazein;59;2;61 +09026;Audressein;139;3;142 +09027;Augirein;76;4;80 +09296;Aulos-Sinsat;166;3;169 +09029;Aulus-les-Bains;158;6;164 +09030;Auzat;488;11;499 +09032;Ax-les-Thermes;1267;65;1332 +09031;Axiat;41;1;42 +09033;Bagert;38;1;39 +09034;Balacet;26;2;28 +09035;Balaguères;197;2;199 +09037;Barjac;42;0;42 +09038;La Bastide-de-Besplas;380;7;387 +09039;La Bastide-de-Bousignac;338;14;352 +09040;La Bastide-de-Lordat;286;7;293 +09042;La Bastide-de-Sérou;957;18;975 +09041;La Bastide-du-Salat;182;6;188 +09043;La Bastide-sur-l'Hers;678;13;691 +09044;Baulou;168;3;171 +09045;Bédeilhac-et-Aynat;192;3;195 +09046;Bédeille;70;3;73 +09047;Bélesta;1064;18;1082 +09048;Belloc;76;1;77 +09049;Bénac;182;5;187 +09050;Benagues;514;9;523 +09051;Bénaix;147;4;151 +09052;Besset;164;8;172 +09053;Bestiac;19;3;22 +09054;Betchat;333;5;338 +09055;Bethmale;95;0;95 +09056;Bézac;357;5;362 +09057;Biert;316;5;321 +09058;Bompas;195;5;200 +09059;Bonac-Irazein;119;4;123 +09060;Bonnac;733;10;743 +09061;Les Bordes-sur-Arize;518;7;525 +09062;Bordes-Uchentein;174;2;176 +09063;Le Bosc;97;2;99 +09064;Bouan;38;0;38 +09065;Boussenac;214;4;218 +09066;Brassac;632;10;642 +09067;Brie;219;4;223 +09068;Burret;39;1;40 +09069;Buzan;29;0;29 +09070;Les Cabannes;333;9;342 +09071;Cadarcet;224;7;231 +09072;Calzan;32;0;32 +09073;Camarade;182;0;182 +09074;Camon;143;1;144 +09075;Campagne-sur-Arize;272;8;280 +09076;Canté;205;7;212 +09077;Capoulet-et-Junac;168;1;169 +09078;Carcanières;76;2;78 +09079;Carla-Bayle;780;14;794 +09080;Carla-de-Roquefort;169;2;171 +09081;Le Carlaret;277;11;288 +09082;Castelnau-Durban;449;7;456 +09083;Castéras;24;0;24 +09084;Castex;94;1;95 +09085;Castillon-en-Couserans;400;5;405 +09086;Caumont;326;5;331 +09087;Caussou;54;0;54 +09088;Caychax;14;0;14 +09089;Cazals-des-Baylès;56;2;58 +09090;Cazaux;39;5;44 +09091;Cazavet;223;3;226 +09092;Cazenave-Serres-et-Allens;51;3;54 +09093;Celles;148;0;148 +09094;Cérizols;142;9;151 +09095;Cescau;141;1;142 +09096;Château-Verdun;43;3;46 +09097;Clermont;114;0;114 +09098;Contrazy;69;2;71 +09099;Cos;393;19;412 +09100;Couflens;86;1;87 +09101;Coussa;265;3;268 +09102;Coutens;172;2;174 +09103;Crampagna;840;18;858 +09104;Dalou;772;20;792 +09105;Daumazan-sur-Arize;719;12;731 +09106;Dreuilhe;355;16;371 +09107;Dun;586;14;600 +09108;Durban-sur-Arize;185;2;187 +09109;Durfort;146;1;147 +09110;Encourtiech;90;4;94 +09111;Engomer;297;4;301 +09113;Ercé;539;3;542 +09114;Erp;121;2;123 +09115;Esclagne;146;3;149 +09116;Escosse;417;10;427 +09117;Esplas;103;6;109 +09118;Esplas-de-Sérou;182;4;186 +09119;Eycheil;550;6;556 +09120;Fabas;351;4;355 +09121;Ferrières-sur-Ariège;771;99;870 +09122;Foix;9532;331;9863 +09123;Fornex;113;1;114 +09124;Le Fossat;1037;13;1050 +09125;Fougax-et-Barrineuf;436;5;441 +09126;Freychenet;90;2;92 +09127;Gabre;123;4;127 +09128;Gajan;309;10;319 +09129;Galey;117;0;117 +09130;Ganac;718;9;727 +09131;Garanou;159;0;159 +09132;Gaudiès;243;4;247 +09133;Génat;21;1;22 +09134;Gestiès;28;1;29 +09136;Gourbit;76;3;79 +09137;Gudas;183;4;187 +09138;L' Herm;201;19;220 +09139;L' Hospitalet-près-l'Andorre;95;0;95 +09140;Ignaux;113;2;115 +09142;Ilhat;111;2;113 +09141;Illartein;73;0;73 +09143;Illier-et-Laramade;25;0;25 +09145;Les Issards;236;5;241 +09146;Justiniac;55;0;55 +09147;Labatut;176;1;177 +09148;Lacave;145;6;151 +09149;Lacourt;196;5;201 +09150;Lagarde;194;6;200 +09151;Lanoux;50;1;51 +09152;Lapège;29;0;29 +09153;Lapenne;127;4;131 +09154;Larbont;57;2;59 +09155;Larcat;44;0;44 +09156;Larnat;21;0;21 +09157;Laroque-d'Olmes;2433;53;2486 +09158;Lasserre;247;7;254 +09159;Lassur;87;2;89 +09160;Lavelanet;6137;168;6305 +09161;Léran;591;23;614 +09162;Lercoul;22;0;22 +09163;Lescousse;75;2;77 +09164;Lescure;499;21;520 +09165;Lesparrou;232;1;233 +09166;Leychert;99;6;105 +09167;Lézat-sur-Lèze;2323;30;2353 +09168;Lieurac;190;5;195 +09169;Limbrassac;133;3;136 +09170;Lissac;246;6;252 +09171;Lordat;68;0;68 +09289;Lorp-Sentaraille;1467;34;1501 +09172;Loubaut;28;0;28 +09173;Loubens;274;5;279 +09174;Loubières;337;13;350 +09175;Ludiès;90;4;94 +09176;Luzenac;538;15;553 +09177;Madière;211;5;216 +09178;Malegoude;46;4;50 +09179;Malléon;73;1;74 +09180;Manses;126;1;127 +09181;Le Mas-d'Azil;1166;11;1177 +09182;Massat;659;8;667 +09183;Mauvezin-de-Prat;102;1;103 +09184;Mauvezin-de-Sainte-Croix;36;0;36 +09185;Mazères;3877;62;3939 +09186;Méras;111;0;111 +09187;Mercenac;363;14;377 +09188;Mercus-Garrabet;1199;24;1223 +09189;Mérens-les-Vals;168;4;172 +09190;Mérigon;115;0;115 +09192;Miglos;117;3;120 +09193;Mijanès;59;0;59 +09194;Mirepoix;3158;141;3299 +09195;Monesple;27;0;27 +09196;Montagagne;76;0;76 +09197;Montaillou;17;1;18 +09198;Montardit;190;4;194 +09199;Montaut;715;19;734 +09200;Montbel;110;2;112 +09201;Montégut-en-Couserans;76;1;77 +09202;Montégut-Plantaurel;335;9;344 +09203;Montels;158;9;167 +09204;Montesquieu-Avantès;245;5;250 +09205;Montfa;82;2;84 +09206;Montferrier;495;13;508 +09207;Montgaillard;1463;30;1493 +09208;Montgauch;122;0;122 +09209;Montjoie-en-Couserans;1082;32;1114 +09210;Montoulieu;410;7;417 +09211;Montségur;119;1;120 +09212;Montseron;94;0;94 +09213;Moulin-Neuf;238;2;240 +09214;Moulis;761;12;773 +09215;Nalzen;136;4;140 +09216;Nescus;62;1;63 +09217;Niaux;165;2;167 +09218;Orgeix;87;1;88 +09219;Orgibet;187;5;192 +09220;Orlu;160;3;163 +09221;Ornolac-Ussat-les-Bains;236;1;237 +09222;Orus;25;0;25 +09223;Oust;545;7;552 +09224;Pailhès;472;8;480 +09225;Pamiers;15675;470;16145 +09226;Pech;37;0;37 +09227;Péreille;210;5;215 +09228;Perles-et-Castelet;223;3;226 +09229;Le Peyrat;473;8;481 +09230;Le Pla;55;1;56 +09231;Le Port;154;1;155 +09232;Prades;33;0;33 +09233;Pradettes;50;0;50 +09234;Pradières;115;0;115 +09235;Prat-Bonrepaux;917;18;935 +09236;Prayols;371;17;388 +09237;Le Puch;29;0;29 +09238;Les Pujols;805;17;822 +09239;Quérigut;133;4;137 +09240;Quié;302;3;305 +09241;Rabat-les-Trois-Seigneurs;356;5;361 +09242;Raissac;48;1;49 +09243;Régat;85;3;88 +09244;Rieucros;702;8;710 +09245;Rieux-de-Pelleport;1304;27;1331 +09246;Rimont;530;21;551 +09247;Rivèrenert;170;9;179 +09249;Roquefixade;149;4;153 +09250;Roquefort-les-Cascades;91;2;93 +09251;Roumengoux;166;8;174 +09252;Rouze;85;1;86 +09253;Sabarat;361;5;366 +09254;Saint-Amadou;241;7;248 +09255;Saint-Amans;46;2;48 +09256;Saint-Bauzeil;57;0;57 +09258;Saint-Félix-de-Rieutord;460;9;469 +09259;Saint-Félix-de-Tournegat;142;4;146 +09261;Saint-Girons;6383;398;6781 +09262;Saint-Jean-d'Aigues-Vives;387;6;393 +09264;Saint-Jean-de-Verges;1249;28;1277 +09263;Saint-Jean-du-Castillonnais;23;1;24 +09265;Saint-Jean-du-Falga;2934;68;3002 +09266;Saint-Julien-de-Gras-Capou;54;1;55 +09267;Saint-Lary;131;2;133 +09268;Saint-Lizier;1418;34;1452 +09270;Saint-Martin-d'Oydes;226;4;230 +09269;Saint-Martin-de-Caralp;357;9;366 +09271;Saint-Michel;72;4;76 +09272;Saint-Paul-de-Jarrat;1313;27;1340 +09273;Saint-Pierre-de-Rivière;644;22;666 +09274;Saint-Quentin-la-Tour;337;6;343 +09275;Saint-Quirc;368;7;375 +09276;Saint-Victor-Rouzaud;231;9;240 +09277;Saint-Ybars;667;12;679 +09257;Sainte-Croix-Volvestre;626;16;642 +09260;Sainte-Foi;26;0;26 +09342;Sainte-Suzanne;238;3;241 +09279;Salsein;44;0;44 +09280;Saurat;636;10;646 +09281;Sautel;109;2;111 +09282;Saverdun;4844;171;5015 +09283;Savignac-les-Ormeaux;371;14;385 +09284;Ségura;184;2;186 +09285;Seix;702;14;716 +09287;Senconac;12;0;12 +09290;Sentein;150;3;153 +09291;Sentenac-d'Oust;108;3;111 +09292;Sentenac-de-Sérou;52;0;52 +09293;Serres-sur-Arget;687;11;698 +09294;Sieuras;96;1;97 +09295;Siguer;98;0;98 +09297;Sor;29;0;29 +09298;Sorgeat;82;2;84 +09299;Soueix-Rogalle;418;9;427 +09300;Soula;177;7;184 +09301;Soulan;373;3;376 +09303;Surba;325;8;333 +09304;Suzan;16;1;17 +09305;Tabre;368;8;376 +09306;Tarascon-sur-Ariège;3044;32;3076 +09307;Taurignan-Castet;165;2;167 +09308;Taurignan-Vieux;206;8;214 +09309;Teilhet;154;2;156 +09310;Thouars-sur-Arize;52;3;55 +09311;Tignac;25;2;27 +09312;La Tour-du-Crieu;3167;74;3241 +09313;Tourtouse;146;7;153 +09314;Tourtrol;298;8;306 +09315;Trémoulet;125;0;125 +09316;Troye-d'Ariège;86;2;88 +09318;Unac;120;2;122 +09319;Unzent;117;4;121 +09320;Urs;33;1;34 +09321;Ussat;322;4;326 +09322;Ustou;301;11;312 +09334;Val-de-Sos;627;64;691 +09323;Vals;98;1;99 +09324;Varilhes;3424;55;3479 +09325;Vaychis;22;1;23 +09326;Vèbre;125;2;127 +09327;Ventenac;235;2;237 +09328;Verdun;221;9;230 +09329;Vernajoul;654;21;675 +09330;Vernaux;28;1;29 +09331;Le Vernet;708;3;711 +09332;Verniolle;2288;65;2353 +09335;Villeneuve;36;0;36 +09336;Villeneuve-d'Olmes;989;18;1007 +09338;Villeneuve-du-Latou;158;4;162 +09339;Villeneuve-du-Paréage;765;14;779 +09340;Vira;160;5;165 +09341;Viviès;124;0;124 +10002;Ailleville;251;6;257 +10003;Aix-Villemaur-Pâlis;3554;38;3592 +10004;Allibaudières;209;2;211 +10005;Amance;274;13;287 +10006;Arcis-sur-Aube;2870;80;2950 +10007;Arconville;105;2;107 +10008;Argançon;108;1;109 +10009;Arrelles;86;2;88 +10010;Arrembécourt;50;2;52 +10011;Arrentières;214;1;215 +10012;Arsonval;322;5;327 +10013;Assenay;146;2;148 +10014;Assencières;171;3;174 +10015;Aubeterre;357;7;364 +10017;Aulnay;129;3;132 +10018;Auxon;1005;10;1015 +10020;Avant-lès-Marcilly;508;11;519 +10021;Avant-lès-Ramerupt;157;4;161 +10022;Avirey-Lingey;206;9;215 +10023;Avon-la-Pèze;193;7;200 +10024;Avreuil;165;3;168 +10025;Bagneux-la-Fosse;168;8;176 +10026;Bailly-le-Franc;37;0;37 +10027;Balignicourt;61;5;66 +10028;Balnot-la-Grange;120;0;120 +10029;Balnot-sur-Laignes;155;1;156 +10033;Bar-sur-Aube;4902;173;5075 +10034;Bar-sur-Seine;3018;184;3202 +10030;Barberey-Saint-Sulpice;1449;20;1469 +10031;Barbuise;465;8;473 +10032;Baroville;306;9;315 +10035;Bayel;758;10;768 +10037;Bercenay-en-Othe;477;12;489 +10038;Bercenay-le-Hayer;191;2;193 +10039;Bergères;123;1;124 +10040;Bernon;164;7;171 +10041;Bertignolles;52;1;53 +10042;Bérulle;234;5;239 +10043;Bessy;140;2;142 +10044;Bétignicourt;33;0;33 +10045;Beurey;195;9;204 +10046;Blaincourt-sur-Aube;109;1;110 +10047;Blignicourt;40;1;41 +10048;Bligny;160;7;167 +10049;Les Bordes-Aumont;543;8;551 +10050;Bossancourt;206;3;209 +10051;Bouilly;1074;48;1122 +10052;Boulages;221;4;225 +10053;Bouranton;572;10;582 +10054;Bourdenay;117;1;118 +10055;Bourguignons;283;12;295 +10056;Bouy-Luxembourg;228;1;229 +10057;Bouy-sur-Orvin;56;1;57 +10058;Bragelogne-Beauvoir;243;9;252 +10059;Braux;108;4;112 +10060;Bréviandes;2826;54;2880 +10061;Brévonnes;686;11;697 +10062;Briel-sur-Barse;206;2;208 +10063;Brienne-la-Vieille;423;13;436 +10064;Brienne-le-Château;2826;26;2852 +10065;Brillecourt;89;1;90 +10066;Bucey-en-Othe;430;10;440 +10067;Buchères;1688;33;1721 +10068;Buxeuil;130;6;136 +10069;Buxières-sur-Arce;121;0;121 +10070;Celles-sur-Ource;505;15;520 +10071;Chacenay;49;2;51 +10072;La Chaise;37;0;37 +10073;Chalette-sur-Voire;133;2;135 +10074;Chamoy;508;7;515 +10078;Champ-sur-Barse;27;0;27 +10075;Champfleury;102;5;107 +10076;Champignol-lez-Mondeville;276;7;283 +10077;Champigny-sur-Aube;106;2;108 +10079;Channes;123;1;124 +10080;Chaource;1081;14;1095 +10081;La Chapelle-Saint-Luc;12319;77;12396 +10082;Chapelle-Vallon;243;4;247 +10083;Chappes;322;4;326 +10084;Charmont-sous-Barbuise;1017;26;1043 +10085;Charmoy;70;0;70 +10086;Charny-le-Bachot;258;8;266 +10087;Chaserey;54;1;55 +10089;Châtres;699;13;712 +10090;Chauchigny;246;2;248 +10091;Chaudrey;144;3;147 +10092;Chauffour-lès-Bailly;122;0;122 +10093;Chaumesnil;103;2;105 +10094;Chavanges;591;12;603 +10095;Le Chêne;293;5;298 +10096;Chennegy;438;8;446 +10097;Chervey;164;4;168 +10098;Chesley;325;9;334 +10099;Chessy-les-Prés;501;8;509 +10100;Clérey;1100;21;1121 +10101;Coclois;178;3;181 +10102;Colombé-la-Fosse;192;4;196 +10103;Colombé-le-Sec;149;1;150 +10104;Cormost;307;2;309 +10105;Courcelles-sur-Voire;27;1;28 +10106;Courceroy;127;1;128 +10107;Coursan-en-Othe;105;0;105 +10108;Courtaoult;83;0;83 +10109;Courtenot;231;8;239 +10110;Courteranges;570;9;579 +10111;Courteron;105;5;110 +10112;Coussegrey;190;2;192 +10113;Couvignon;202;6;208 +10114;Crancey;719;14;733 +10115;Creney-près-Troyes;1845;31;1876 +10116;Crésantignes;312;5;317 +10117;Crespy-le-Neuf;153;7;160 +10118;Les Croûtes;97;4;101 +10119;Cunfin;177;4;181 +10120;Cussangy;239;7;246 +10121;Dampierre;301;7;308 +10122;Davrey;237;3;240 +10123;Dienville;881;16;897 +10124;Dierrey-Saint-Julien;261;13;274 +10125;Dierrey-Saint-Pierre;298;5;303 +10126;Dolancourt;136;4;140 +10127;Dommartin-le-Coq;62;0;62 +10128;Donnement;77;1;78 +10129;Dosches;295;9;304 +10130;Dosnon;106;6;112 +10131;Droupt-Saint-Basle;355;4;359 +10132;Droupt-Sainte-Marie;236;5;241 +10133;Eaux-Puiseaux;255;10;265 +10134;Échemines;94;6;100 +10135;Éclance;101;3;104 +10136;Éguilly-sous-Bois;117;2;119 +10137;Engente;36;0;36 +10138;Épagne;136;2;138 +10139;Épothémont;179;1;180 +10140;Ervy-le-Châtel;1193;9;1202 +10141;Essoyes;715;9;724 +10142;Estissac;1855;19;1874 +10143;Étourvy;173;5;178 +10144;Étrelles-sur-Aube;155;3;158 +10145;Faux-Villecerf;221;2;223 +10146;Fay-lès-Marcilly;87;3;90 +10147;Fays-la-Chapelle;130;4;134 +10148;Ferreux-Quincey;399;10;409 +10149;Feuges;332;4;336 +10150;Fontaine;258;6;264 +10151;Fontaine-les-Grès;876;9;885 +10153;Fontaine-Mâcon;652;15;667 +10154;Fontenay-de-Bossery;72;1;73 +10155;Fontette;206;9;215 +10156;Fontvannes;717;8;725 +10157;La Fosse-Corduan;218;6;224 +10158;Fouchères;531;16;547 +10159;Fralignes;87;1;88 +10160;Fravaux;47;1;48 +10161;Fresnay;47;3;50 +10162;Fresnoy-le-Château;279;6;285 +10163;Fuligny;45;2;47 +10164;Gélannes;736;11;747 +10165;Géraudot;337;6;343 +10166;Les Grandes-Chapelles;393;6;399 +10167;Grandville;95;1;96 +10168;Les Granges;75;0;75 +10169;Gumery;233;8;241 +10170;Gyé-sur-Seine;492;8;500 +10171;Hampigny;238;9;247 +10172;Herbisse;166;1;167 +10174;Isle-Aubigny;179;3;182 +10173;Isle-Aumont;472;8;480 +10175;Jasseines;177;3;180 +10176;Jaucourt;166;7;173 +10177;Javernant;150;7;157 +10178;Jessains;275;9;284 +10179;Jeugny;490;10;500 +10180;Joncreuil;92;4;96 +10181;Jully-sur-Sarce;238;10;248 +10182;Juvancourt;122;1;123 +10183;Juvanzé;35;1;36 +10184;Juzanvigny;127;1;128 +10185;Lagesse;205;3;208 +10186;Laines-aux-Bois;523;15;538 +10187;Landreville;441;11;452 +10188;Lantages;230;7;237 +10189;Lassicourt;63;0;63 +10190;Laubressel;539;5;544 +10191;Lavau;943;10;953 +10192;Lentilles;125;1;126 +10193;Lesmont;306;7;313 +10194;Lévigny;96;2;98 +10195;Lhuître;298;4;302 +10196;Lignières;212;1;213 +10197;Lignol-le-Château;199;9;208 +10198;Lirey;104;3;107 +10199;Loches-sur-Ource;353;8;361 +10200;La Loge-aux-Chèvres;84;0;84 +10201;La Loge-Pomblin;68;0;68 +10202;Les Loges-Margueron;201;64;265 +10203;Longchamp-sur-Aujon;420;6;426 +10204;Longeville-sur-Mogne;158;0;158 +10205;Longpré-le-Sec;85;2;87 +10206;Longsols;125;1;126 +10207;Longueville-sur-Aube;123;3;126 +10208;La Louptière-Thénard;289;8;297 +10209;Lusigny-sur-Barse;2167;55;2222 +10210;Luyères;452;6;458 +10211;Macey;964;16;980 +10212;Machy;115;4;119 +10213;Magnant;162;5;167 +10214;Magnicourt;82;1;83 +10215;Magny-Fouchard;267;4;271 +10216;Mailly-le-Camp;1579;37;1616 +10217;Maison-des-Champs;33;0;33 +10218;Maisons-lès-Chaource;158;3;161 +10219;Maisons-lès-Soulaines;63;3;66 +10220;Maizières-la-Grande-Paroisse;1492;45;1537 +10221;Maizières-lès-Brienne;164;0;164 +10222;Maraye-en-Othe;446;3;449 +10223;Marcilly-le-Hayer;725;9;734 +10224;Marigny-le-Châtel;1752;33;1785 +10225;Marnay-sur-Seine;229;6;235 +10226;Marolles-lès-Bailly;106;2;108 +10227;Marolles-sous-Lignières;333;5;338 +10228;Mathaux;200;2;202 +10229;Maupas;105;2;107 +10230;Mergey;690;11;701 +10231;Le Mériot;614;10;624 +10232;Merrey-sur-Arce;321;4;325 +10233;Méry-sur-Seine;1526;49;1575 +10234;Mesgrigny;292;1;293 +10235;Mesnil-la-Comtesse;45;0;45 +10236;Mesnil-Lettre;58;1;59 +10237;Mesnil-Saint-Loup;600;29;629 +10238;Mesnil-Saint-Père;496;6;502 +10239;Mesnil-Sellières;584;10;594 +10240;Messon;466;11;477 +10241;Metz-Robert;61;0;61 +10242;Meurville;173;3;176 +10243;Molins-sur-Aube;108;5;113 +10245;Montaulin;807;25;832 +10246;Montceaux-lès-Vaudes;256;16;272 +10247;Montfey;134;3;137 +10248;Montgueux;399;11;410 +10250;Montier-en-l'Isle;235;6;241 +10249;Montiéramey;403;7;410 +10251;Montigny-les-Monts;250;5;255 +10252;Montmartin-le-Haut;53;2;55 +10253;Montmorency-Beaufort;137;1;138 +10254;Montpothier;331;9;340 +10255;Montreuil-sur-Barse;298;13;311 +10256;Montsuzain;409;4;413 +10257;Morembert;31;0;31 +10258;Morvilliers;300;7;307 +10259;La Motte-Tilly;372;3;375 +10260;Moussey;638;16;654 +10261;Mussy-sur-Seine;1019;15;1034 +10262;Neuville-sur-Seine;454;10;464 +10263;Neuville-sur-Vanne;423;5;428 +10264;Noé-les-Mallets;117;1;118 +10265;Les Noës-près-Troyes;3282;33;3315 +10266;Nogent-en-Othe;46;3;49 +10267;Nogent-sur-Aube;322;4;326 +10268;Nogent-sur-Seine;5980;117;6097 +10269;Nozay;148;5;153 +10270;Onjon;250;6;256 +10271;Origny-le-Sec;606;11;617 +10272;Ormes;181;3;184 +10273;Ortillon;24;0;24 +10274;Orvilliers-Saint-Julien;311;4;315 +10275;Ossey-les-Trois-Maisons;592;7;599 +10276;Paisy-Cosdon;338;6;344 +10278;Pargues;138;2;140 +10279;Pars-lès-Chavanges;66;4;70 +10280;Pars-lès-Romilly;824;9;833 +10281;Le Pavillon-Sainte-Julie;291;8;299 +10282;Payns;1363;19;1382 +10283;Pel-et-Der;133;2;135 +10284;Périgny-la-Rose;140;3;143 +10285;Perthes-lès-Brienne;81;3;84 +10286;Petit-Mesnil;216;7;223 +10287;Piney;1484;16;1500 +10288;Plaines-Saint-Lange;261;1;262 +10289;Plancy-l'Abbaye;973;17;990 +10290;Planty;242;6;248 +10291;Plessis-Barbuise;202;4;206 +10293;Poivres;159;2;161 +10294;Poligny;64;2;66 +10295;Polisot;326;5;331 +10296;Polisy;193;9;202 +10297;Pont-Sainte-Marie;5166;129;5295 +10298;Pont-sur-Seine;1161;20;1181 +10299;Pouan-les-Vallées;539;17;556 +10300;Pougy;290;2;292 +10301;Pouy-sur-Vannes;156;4;160 +10302;Praslin;90;2;92 +10303;Précy-Notre-Dame;82;2;84 +10304;Précy-Saint-Martin;187;2;189 +10305;Prémierfait;88;3;91 +10306;Proverville;239;6;245 +10307;Prugny;375;11;386 +10308;Prunay-Belleville;217;8;225 +10309;Prusy;94;1;95 +10310;Puits-et-Nuisement;214;5;219 +10312;Racines;167;6;173 +10313;Radonvilliers;376;2;378 +10314;Ramerupt;408;5;413 +10315;Rances;44;2;46 +10316;Rhèges;232;4;236 +10317;Les Riceys;1243;24;1267 +10318;Rigny-la-Nonneuse;171;1;172 +10319;Rigny-le-Ferron;352;6;358 +10320;Rilly-Sainte-Syre;233;5;238 +10321;La Rivière-de-Corps;3396;107;3503 +10323;Romilly-sur-Seine;14451;305;14756 +10324;Roncenay;159;2;161 +10325;Rosières-près-Troyes;4165;342;4507 +10326;Rosnay-l'Hôpital;181;9;190 +10327;La Rothière;109;1;110 +10328;Rouilly-Sacey;386;4;390 +10329;Rouilly-Saint-Loup;517;46;563 +10330;Rouvres-les-Vignes;106;2;108 +10331;Rumilly-lès-Vaudes;542;10;552 +10332;Ruvigny;494;11;505 +10333;Saint-André-les-Vergers;12311;188;12499 +10334;Saint-Aubin;588;8;596 +10335;Saint-Benoist-sur-Vanne;237;6;243 +10336;Saint-Benoît-sur-Seine;400;5;405 +10337;Saint-Christophe-Dodinicourt;34;1;35 +10338;Saint-Étienne-sous-Barbuise;167;3;170 +10339;Saint-Flavy;283;6;289 +10340;Saint-Germain;2304;50;2354 +10341;Saint-Hilaire-sous-Romilly;351;9;360 +10342;Saint-Jean-de-Bonneval;396;8;404 +10343;Saint-Julien-les-Villas;6811;140;6951 +10344;Saint-Léger-près-Troyes;880;14;894 +10345;Saint-Léger-sous-Brienne;386;11;397 +10346;Saint-Léger-sous-Margerie;59;6;65 +10347;Saint-Loup-de-Buffigny;210;6;216 +10348;Saint-Lupien;236;0;236 +10349;Saint-Lyé;2915;62;2977 +10350;Saint-Mards-en-Othe;640;10;650 +10351;Saint-Martin-de-Bossenay;368;5;373 +10353;Saint-Mesmin;843;10;853 +10354;Saint-Nabord-sur-Aube;139;5;144 +10355;Saint-Nicolas-la-Chapelle;66;0;66 +10356;Saint-Oulph;287;8;295 +10357;Saint-Parres-aux-Tertres;3126;52;3178 +10358;Saint-Parres-lès-Vaudes;1004;14;1018 +10359;Saint-Phal;523;11;534 +10360;Saint-Pouange;914;221;1135 +10361;Saint-Remy-sous-Barbuise;231;5;236 +10363;Saint-Thibault;555;7;562 +10364;Saint-Usage;76;2;78 +10352;Sainte-Maure;1655;301;1956 +10362;Sainte-Savine;10573;438;11011 +10365;Salon;120;1;121 +10366;Saulcy;68;1;69 +10367;La Saulsotte;704;3;707 +10368;Savières;1005;11;1016 +10369;Semoine;199;6;205 +10370;Soligny-les-Étangs;239;6;245 +10371;Sommeval;311;5;316 +10372;Soulaines-Dhuys;413;6;419 +10373;Souligny;400;21;421 +10374;Spoy;177;1;178 +10375;Thennelières;338;10;348 +10376;Thieffrain;154;3;157 +10377;Thil;114;9;123 +10378;Thors;71;3;74 +10379;Torcy-le-Grand;443;10;453 +10380;Torcy-le-Petit;82;4;86 +10381;Torvilliers;969;17;986 +10382;Traînel;1062;13;1075 +10383;Trancault;186;3;189 +10384;Trannes;243;5;248 +10386;Trouans;228;7;235 +10387;Troyes;61652;1176;62828 +10388;Turgy;45;1;46 +10389;Unienville;125;4;129 +10390;Urville;130;2;132 +10391;Vailly;287;10;297 +10019;Val-d'Auzon;381;5;386 +10392;Vallant-Saint-Georges;384;9;393 +10393;Vallentigny;183;3;186 +10394;Vallières;150;1;151 +10395;Vanlay;304;2;306 +10396;Vauchassis;503;5;508 +10397;Vauchonvilliers;158;2;160 +10398;Vaucogne;74;4;78 +10399;Vaudes;716;8;724 +10400;Vaupoisson;120;5;125 +10401;Vendeuvre-sur-Barse;2317;38;2355 +10402;La Vendue-Mignot;250;5;255 +10403;Vernonvilliers;58;1;59 +10404;Verpillières-sur-Ource;109;2;111 +10405;Verricourt;53;0;53 +10406;Verrières;1870;35;1905 +10408;Viâpres-le-Petit;126;5;131 +10409;Villacerf;589;4;593 +10410;Villadin;112;4;116 +10411;La Ville-aux-Bois;30;0;30 +10426;Ville-sous-la-Ferté;1066;13;1079 +10427;Ville-sur-Arce;212;12;224 +10428;Ville-sur-Terre;103;2;105 +10412;Villechétif;927;13;940 +10414;Villeloup;121;5;126 +10416;Villemereuil;247;9;256 +10417;Villemoiron-en-Othe;198;8;206 +10418;Villemorien;207;6;213 +10419;Villemoyenne;776;8;784 +10420;Villenauxe-la-Grande;2721;31;2752 +10421;La Villeneuve-au-Châtelot;146;4;150 +10422;Villeneuve-au-Chemin;185;2;187 +10423;La Villeneuve-au-Chêne;424;12;436 +10424;Villeret;63;2;65 +10425;Villery;275;3;278 +10429;Villette-sur-Aube;258;3;261 +10430;Villiers-Herbisse;87;3;90 +10431;Villiers-le-Bois;96;1;97 +10432;Villiers-sous-Praslin;71;0;71 +10433;Villy-en-Trodes;246;8;254 +10434;Villy-le-Bois;55;0;55 +10435;Villy-le-Maréchal;188;4;192 +10436;Vinets;170;6;176 +10437;Virey-sous-Bar;621;9;630 +10438;Vitry-le-Croisé;234;5;239 +10439;Viviers-sur-Artaut;128;4;132 +10440;Voigny;158;6;164 +10441;Vosnon;233;2;235 +10442;Voué;681;8;689 +10443;Vougrey;48;3;51 +10444;Vulaines;225;3;228 +10445;Yèvres-le-Petit;57;9;66 +11001;Aigues-Vives;584;7;591 +11002;Airoux;163;2;165 +11003;Ajac;187;3;190 +11004;Alaigne;326;9;335 +11005;Alairac;1330;33;1363 +11006;Albas;77;2;79 +11007;Albières;118;4;122 +11008;Alet-les-Bains;406;3;409 +11009;Alzonne;1522;21;1543 +11010;Antugnac;268;6;274 +11011;Aragon;433;12;445 +11012;Argeliers;2139;31;2170 +11013;Argens-Minervois;347;6;353 +11014;Armissan;1520;30;1550 +11015;Arques;254;3;257 +11016;Arquettes-en-Val;79;2;81 +11017;Artigues;73;5;78 +11018;Arzens;1238;18;1256 +11019;Aunat;67;0;67 +11020;Auriac;43;0;43 +11021;Axat;547;11;558 +11022;Azille;1144;23;1167 +11023;Badens;785;15;800 +11024;Bages;803;16;819 +11025;Bagnoles;308;3;311 +11026;Baraigne;174;3;177 +11027;Barbaira;750;19;769 +11028;Belcaire;394;11;405 +11029;Belcastel-et-Buc;58;2;60 +11030;Belflou;121;6;127 +11031;Belfort-sur-Rebenty;26;1;27 +11032;Bellegarde-du-Razès;238;2;240 +11033;Belpech;1273;12;1285 +11034;Belvèze-du-Razès;868;8;876 +11035;Belvianes-et-Cavirac;255;6;261 +11036;Belvis;160;3;163 +11037;Berriac;954;10;964 +11038;Bessède-de-Sault;47;0;47 +11039;La Bezole;44;1;45 +11040;Bizanet;1685;28;1713 +11041;Bize-Minervois;1185;16;1201 +11042;Blomac;227;6;233 +11043;Bouilhonnac;227;6;233 +11044;Bouisse;100;0;100 +11045;Bouriège;127;1;128 +11046;Bourigeole;51;0;51 +11047;Le Bousquet;44;1;45 +11048;Boutenac;721;16;737 +11049;Bram;3204;82;3286 +11051;Brézilhac;174;4;178 +11052;Brousses-et-Villaret;344;5;349 +11053;Brugairolles;273;5;278 +11054;Les Brunels;273;11;284 +11055;Bugarach;228;4;232 +11056;Cabrespine;176;4;180 +11057;Cahuzac;32;0;32 +11058;Cailhau;266;9;275 +11059;Cailhavel;132;1;133 +11060;Cailla;48;1;49 +11061;Cambieure;304;4;308 +11062;Campagna-de-Sault;19;0;19 +11063;Campagne-sur-Aude;581;5;586 +11064;Camplong-d'Aude;367;5;372 +11065;Camps-sur-l'Agly;55;1;56 +11066;Camurac;98;0;98 +11067;Canet;1778;18;1796 +11068;Capendu;1468;66;1534 +11069;Carcassonne;46031;1334;47365 +11070;Carlipa;340;5;345 +11071;Cascastel-des-Corbières;221;7;228 +11072;La Cassaigne;169;8;177 +11073;Cassaignes;56;0;56 +11074;Les Cassés;295;2;297 +11075;Castans;134;2;136 +11077;Castelnau-d'Aude;491;9;500 +11076;Castelnaudary;11598;538;12136 +11078;Castelreng;207;7;214 +11079;Caudebronde;189;2;191 +11081;Caunes-Minervois;1654;35;1689 +11082;Caunette-sur-Lauquet;4;0;4 +11083;Caunettes-en-Val;44;1;45 +11084;Caux-et-Sauzens;979;23;1002 +11085;Cavanac;923;38;961 +11086;Caves;875;13;888 +11087;Cazalrenoux;91;1;92 +11088;Cazilhac;1648;52;1700 +11089;Cenne-Monestiés;401;7;408 +11090;Cépie;646;17;663 +11091;Chalabre;1118;12;1130 +11092;Citou;89;1;90 +11093;Le Clat;31;2;33 +11094;Clermont-sur-Lauquet;26;0;26 +11095;Comigne;305;7;312 +11096;Comus;43;3;46 +11098;Conilhac-Corbières;917;19;936 +11099;Conques-sur-Orbiel;2525;54;2579 +11100;Corbières;27;1;28 +11101;Coudons;52;1;53 +11102;Couffoulens;601;8;609 +11103;Couiza;1111;26;1137 +11104;Counozouls;48;0;48 +11105;Cournanel;714;10;724 +11106;Coursan;5908;93;6001 +11107;Courtauly;73;1;74 +11108;La Courtète;45;1;46 +11109;Coustaussa;52;1;53 +11110;Coustouge;121;0;121 +11111;Cruscades;926;6;932 +11112;Cubières-sur-Cinoble;96;1;97 +11113;Cucugnan;123;5;128 +11114;Cumiès;36;2;38 +11115;Cuxac-Cabardès;911;24;935 +11116;Cuxac-d'Aude;4030;70;4100 +11117;Davejean;117;1;118 +11118;Dernacueillette;41;2;43 +11119;La Digne-d'Amont;287;7;294 +11120;La Digne-d'Aval;536;4;540 +11121;Donazac;109;1;110 +11122;Douzens;733;12;745 +11123;Duilhac-sous-Peyrepertuse;146;2;148 +11124;Durban-Corbières;649;11;660 +11125;Embres-et-Castelmaure;152;0;152 +11126;Escales;465;4;469 +11127;Escouloubre;73;3;76 +11128;Escueillens-et-Saint-Just-de-Bélengard;156;2;158 +11129;Espéraza;1870;33;1903 +11130;Espezel;206;4;210 +11132;Fabrezan;1291;17;1308 +11133;Fajac-en-Val;38;0;38 +11134;Fajac-la-Relenque;50;4;54 +11135;La Fajolle;11;1;12 +11136;Fanjeaux;834;88;922 +11137;Félines-Termenès;117;4;121 +11138;Fendeille;532;16;548 +11139;Fenouillet-du-Razès;85;0;85 +11140;Ferrals-les-Corbières;1192;18;1210 +11141;Ferran;111;1;112 +11142;Festes-et-Saint-André;206;6;212 +11143;Feuilla;104;0;104 +11144;Fitou;1060;12;1072 +11145;Fleury;3825;63;3888 +11146;Floure;407;8;415 +11147;Fontanès-de-Sault;5;0;5 +11148;Fontcouverte;546;10;556 +11149;Fonters-du-Razès;79;1;80 +11150;Fontiers-Cabardès;454;50;504 +11151;Fontiès-d'Aude;481;10;491 +11152;Fontjoncouse;131;4;135 +11153;La Force;222;3;225 +11154;Fournes-Cabardès;50;0;50 +11155;Fourtou;73;1;74 +11156;Fraisse-Cabardès;104;2;106 +11157;Fraissé-des-Corbières;220;5;225 +11158;Gaja-et-Villedieu;292;11;303 +11159;Gaja-la-Selve;143;2;145 +11160;Galinagues;35;0;35 +11161;Gardie;121;3;124 +11162;Generville;60;1;61 +11163;Gincla;48;0;48 +11164;Ginestas;1445;20;1465 +11165;Ginoles;303;13;316 +11166;Gourvieille;76;0;76 +11167;Gramazie;117;2;119 +11168;Granès;97;0;97 +11169;Greffeil;79;5;84 +11170;Gruissan;5000;63;5063 +11172;Homps;591;11;602 +11173;Hounoux;136;3;139 +11174;Les Ilhes;52;0;52 +11175;Issel;488;9;497 +11176;Jonquières;59;2;61 +11177;Joucou;35;1;36 +11178;Labastide-d'Anjou;1326;15;1341 +11179;Labastide-en-Val;92;2;94 +11180;Labastide-Esparbairenque;73;0;73 +11181;Labécède-Lauragais;412;9;421 +11182;Lacombe;172;3;175 +11183;Ladern-sur-Lauquet;266;9;275 +11184;Lafage;89;3;92 +11185;Lagrasse;545;9;554 +11186;Lairière;52;2;54 +11187;Lanet;50;1;51 +11189;Laprade;95;1;96 +11191;Laroque-de-Fa;151;7;158 +11192;Lasbordes;788;30;818 +11193;Lasserre-de-Prouille;267;3;270 +11194;Lastours;159;3;162 +11195;Laurabuc;412;9;421 +11196;Laurac;175;8;183 +11197;Lauraguel;609;16;625 +11198;Laure-Minervois;1055;15;1070 +11199;Lavalette;1499;26;1525 +11200;Lespinassière;133;7;140 +11201;Leuc;849;15;864 +11202;Leucate;4428;57;4485 +11203;Lézignan-Corbières;11168;164;11332 +11204;Lignairolles;43;0;43 +11205;Limousis;129;2;131 +11206;Limoux;10066;548;10614 +11207;Loupia;240;5;245 +11208;La Louvière-Lauragais;77;2;79 +11209;Luc-sur-Aude;246;7;253 +11210;Luc-sur-Orbieu;1144;10;1154 +11211;Magrie;528;10;538 +11212;Mailhac;567;10;577 +11213;Maisons;46;0;46 +11214;Malras;396;12;408 +11215;Malves-en-Minervois;854;25;879 +11216;Malviès;369;12;381 +11217;Marcorignan;1300;27;1327 +11218;Marquein;82;0;82 +11219;Marsa;18;0;18 +11220;Marseillette;712;14;726 +11221;Les Martys;293;5;298 +11222;Mas-Cabardès;185;4;189 +11223;Mas-des-Cours;25;0;25 +11225;Mas-Saintes-Puelles;922;22;944 +11224;Massac;29;1;30 +11226;Mayreville;75;3;78 +11227;Mayronnes;35;1;36 +11228;Mazerolles-du-Razès;154;4;158 +11229;Mazuby;25;1;26 +11230;Mérial;31;0;31 +11231;Mézerville;95;0;95 +11232;Miraval-Cabardès;46;0;46 +11233;Mirepeisset;769;6;775 +11234;Mireval-Lauragais;171;5;176 +11235;Missègre;63;2;65 +11236;Molandier;237;6;243 +11238;Molleville;130;6;136 +11239;Montauriol;88;2;90 +11240;Montazels;560;10;570 +11241;Montbrun-des-Corbières;309;2;311 +11242;Montclar;171;0;171 +11243;Montferrand;565;9;574 +11244;Montfort-sur-Boulzane;88;3;91 +11245;Montgaillard;42;0;42 +11246;Montgradail;47;0;47 +11247;Monthaut;38;0;38 +11248;Montirat;74;1;75 +11249;Montjardin;87;1;88 +11250;Montjoi;37;1;38 +11252;Montmaur;307;9;316 +11253;Montolieu;846;15;861 +11254;Montréal;1896;174;2070 +11255;Montredon-des-Corbières;1477;15;1492 +11256;Montséret;594;12;606 +11257;Monze;227;2;229 +11258;Moussan;1940;46;1986 +11259;Moussoulens;1018;30;1048 +11260;Mouthoumet;107;3;110 +11261;Moux;701;9;710 +11262;Narbonne;54700;1176;55876 +11263;Nébias;246;5;251 +11264;Névian;1301;33;1334 +11265;Niort-de-Sault;32;1;33 +11267;Ornaisons;1181;26;1207 +11268;Orsans;104;0;104 +11269;Ouveillan;2463;50;2513 +11270;Padern;132;1;133 +11271;Palairac;30;0;30 +11272;Palaja;2357;97;2454 +11188;La Palme;1693;30;1723 +11273;Paraza;622;12;634 +11274;Pauligne;357;14;371 +11275;Payra-sur-l'Hers;205;3;208 +11276;Paziols;528;7;535 +11278;Pech-Luna;75;2;77 +11277;Pécharic-et-le-Py;27;0;27 +11279;Pennautier;2554;58;2612 +11280;Pépieux;1068;28;1096 +11281;Pexiora;1226;18;1244 +11282;Peyrefitte-du-Razès;48;2;50 +11283;Peyrefitte-sur-l'Hers;75;8;83 +11284;Peyrens;496;13;509 +11285;Peyriac-de-Mer;1113;23;1136 +11286;Peyriac-Minervois;1139;20;1159 +11287;Peyrolles;86;3;89 +11288;Pezens;1525;165;1690 +11289;Pieusse;987;18;1005 +11290;Plaigne;116;1;117 +11291;Plavilla;110;4;114 +11292;La Pomarède;143;3;146 +11293;Pomas;887;23;910 +11294;Pomy;59;1;60 +11266;Port-la-Nouvelle;5567;69;5636 +11295;Portel-des-Corbières;1357;20;1377 +11296;Pouzols-Minervois;547;8;555 +11297;Pradelles-Cabardès;143;1;144 +11299;Preixan;619;9;628 +11300;Puginier;152;0;152 +11301;Puichéric;1191;19;1210 +11302;Puilaurens;271;9;280 +11303;Puivert;471;16;487 +11304;Quillan;3258;111;3369 +11305;Quintillan;52;0;52 +11306;Quirbajou;51;2;53 +11307;Raissac-d'Aude;263;5;268 +11308;Raissac-sur-Lampy;456;9;465 +11190;La Redorte;1161;19;1180 +11309;Rennes-le-Château;80;3;83 +11310;Rennes-les-Bains;205;1;206 +11311;Ribaute;276;7;283 +11312;Ribouisse;109;5;114 +11313;Ricaud;299;7;306 +11314;Rieux-en-Val;88;7;95 +11315;Rieux-Minervois;1987;28;2015 +11316;Rivel;199;3;202 +11317;Rodome;124;3;127 +11318;Roquecourbe-Minervois;132;6;138 +11319;Roquefère;79;1;80 +11320;Roquefeuil;289;4;293 +11321;Roquefort-de-Sault;84;0;84 +11322;Roquefort-des-Corbières;1024;18;1042 +11323;Roquetaillade-et-Conilhac;277;2;279 +11324;Roubia;509;13;522 +11325;Rouffiac-d'Aude;441;11;452 +11326;Rouffiac-des-Corbières;86;1;87 +11327;Roullens;465;14;479 +11328;Routier;248;6;254 +11330;Rustiques;507;12;519 +11331;Saint-Amans;64;3;67 +11332;Saint-André-de-Roquelongue;1390;17;1407 +11333;Saint-Benoît;105;3;108 +11337;Saint-Couat-d'Aude;404;4;408 +11338;Saint-Couat-du-Razès;51;1;52 +11339;Saint-Denis;512;12;524 +11341;Saint-Ferriol;116;2;118 +11342;Saint-Frichoux;255;7;262 +11343;Saint-Gaudéric;115;2;117 +11344;Saint-Hilaire;773;15;788 +11345;Saint-Jean-de-Barrou;254;0;254 +11346;Saint-Jean-de-Paracol;124;3;127 +11347;Saint-Julia-de-Bec;104;3;107 +11348;Saint-Julien-de-Briola;89;1;90 +11350;Saint-Just-et-le-Bézu;44;3;47 +11351;Saint-Laurent-de-la-Cabrerisse;736;26;762 +11352;Saint-Louis-et-Parahou;55;2;57 +11353;Saint-Marcel-sur-Aude;2005;28;2033 +11355;Saint-Martin-de-Villereglan;363;8;371 +11354;Saint-Martin-des-Puits;28;0;28 +11356;Saint-Martin-Lalande;1124;20;1144 +11357;Saint-Martin-le-Vieil;226;8;234 +11358;Saint-Martin-Lys;25;2;27 +11359;Saint-Michel-de-Lanès;464;12;476 +11360;Saint-Nazaire-d'Aude;2032;36;2068 +11361;Saint-Papoul;835;19;854 +11362;Saint-Paulet;199;4;203 +11363;Saint-Pierre-des-Champs;181;4;185 +11364;Saint-Polycarpe;147;2;149 +11365;Saint-Sernin;38;2;40 +11334;Sainte-Camelle;119;2;121 +11335;Sainte-Colombe-sur-Guette;46;0;46 +11336;Sainte-Colombe-sur-l'Hers;435;7;442 +11340;Sainte-Eulalie;506;9;515 +11366;Sainte-Valière;563;10;573 +11367;Saissac;929;26;955 +11368;Sallèles-Cabardès;119;3;122 +11369;Sallèles-d'Aude;2922;45;2967 +11370;Salles-d'Aude;3255;75;3330 +11371;Salles-sur-l'Hers;701;13;714 +11372;Salsigne;390;4;394 +11373;Salvezines;77;0;77 +11374;Salza;17;0;17 +11375;Seignalens;32;1;33 +11376;La Serpent;92;4;96 +11377;Serres;65;2;67 +11378;Serviès-en-Val;213;6;219 +11379;Sigean;5477;94;5571 +11380;Sonnac-sur-l'Hers;135;3;138 +11381;Sougraigne;112;6;118 +11382;Souilhanels;365;64;429 +11383;Souilhe;319;9;328 +11384;Soulatgé;128;0;128 +11385;Soupex;246;7;253 +11386;Talairan;467;7;474 +11387;Taurize;113;1;114 +11388;Termes;38;0;38 +11389;Terroles;17;0;17 +11390;Thézan-des-Corbières;544;10;554 +11391;La Tourette-Cabardès;23;2;25 +11392;Tournissan;272;4;276 +11393;Tourouzelle;469;6;475 +11394;Tourreilles;127;0;127 +11395;Trassanel;34;0;34 +11396;Trausse;590;3;593 +11397;Trèbes;5601;159;5760 +11398;Treilles;247;4;251 +11399;Tréville;104;5;109 +11400;Tréziers;100;1;101 +11401;Tuchan;786;11;797 +11251;Val-de-Dagne;739;11;750 +11080;Val de Lambronne;185;2;187 +11131;Val-du-Faby;562;19;581 +11402;Valmigère;17;0;17 +11404;Ventenac-Cabardès;959;45;1004 +11405;Ventenac-en-Minervois;553;10;563 +11406;Véraza;32;2;34 +11407;Verdun-en-Lauragais;273;6;279 +11408;Verzeille;493;8;501 +11409;Vignevieille;105;1;106 +11410;Villalier;1004;17;1021 +11411;Villanière;137;1;138 +11414;Villar-en-Val;26;1;27 +11415;Villar-Saint-Anselme;121;0;121 +11412;Villardebelle;53;0;53 +11413;Villardonnel;498;12;510 +11416;Villarzel-Cabardès;238;5;243 +11417;Villarzel-du-Razès;103;0;103 +11418;Villasavary;1209;28;1237 +11419;Villautou;63;0;63 +11420;Villebazy;127;2;129 +11421;Villedaigne;510;8;518 +11422;Villedubert;345;15;360 +11423;Villefloure;165;4;169 +11424;Villefort;89;1;90 +11425;Villegailhenc;1735;42;1777 +11426;Villegly;1134;23;1157 +11427;Villelongue-d'Aude;305;8;313 +11428;Villemagne;261;6;267 +11429;Villemoustaussou;4423;79;4502 +11430;Villeneuve-la-Comptal;1305;40;1345 +11431;Villeneuve-les-Corbières;242;5;247 +11432;Villeneuve-lès-Montréal;300;10;310 +11433;Villeneuve-Minervois;1019;9;1028 +11434;Villepinte;1303;24;1327 +11435;Villerouge-Termenès;147;5;152 +11436;Villesèque-des-Corbières;374;2;376 +11437;Villesèquelande;896;17;913 +11438;Villesiscle;383;6;389 +11439;Villespy;373;7;380 +11440;Villetritouls;38;3;41 +11441;Vinassan;2646;43;2689 +12001;Agen-d'Aveyron;1051;30;1081 +12002;Aguessac;867;24;891 +12003;Les Albres;346;6;352 +12004;Almont-les-Junies;464;20;484 +12006;Alrance;358;11;369 +12007;Ambeyrac;174;6;180 +12008;Anglars-Saint-Félix;820;21;841 +12223;Argences en Aubrac;1646;37;1683 +12009;Arnac-sur-Dourdou;34;1;35 +12010;Arques;135;2;137 +12011;Arvieu;783;29;812 +12012;Asprières;733;7;740 +12013;Aubin;3761;116;3877 +12015;Auriac-Lagast;229;3;232 +12016;Auzits;846;28;874 +12017;Ayssènes;216;3;219 +12018;Balaguier-d'Olt;162;6;168 +12019;Balaguier-sur-Rance;92;2;94 +12056;Baraqueville;3142;84;3226 +12021;Le Bas Ségala;1581;55;1636 +12022;La Bastide-Pradines;101;2;103 +12023;La Bastide-Solages;108;0;108 +12024;Belcastel;191;3;194 +12025;Belmont-sur-Rance;976;12;988 +12026;Bertholène;1046;21;1067 +12027;Bessuéjouls;213;8;221 +12028;Boisse-Penchot;515;10;525 +12029;Bor-et-Bar;194;4;198 +12030;Bouillac;414;16;430 +12031;Bournazel;348;5;353 +12032;Boussac;579;13;592 +12033;Bozouls;2871;61;2932 +12034;Brandonnet;319;16;335 +12035;Brasc;167;7;174 +12036;Brommat;638;8;646 +12037;Broquiès;612;16;628 +12038;Brousse-le-Château;158;4;162 +12039;Brusque;276;6;282 +12041;Cabanès;252;7;259 +12042;Calmels-et-le-Viala;208;11;219 +12043;Calmont;2053;72;2125 +12044;Camarès;1038;32;1070 +12045;Camboulazet;398;10;408 +12046;Camjac;572;15;587 +12047;Campagnac;450;6;456 +12048;Campouriez;350;7;357 +12049;Campuac;451;7;458 +12050;Canet-de-Salars;431;5;436 +12051;Cantoin;305;2;307 +12052;Capdenac-Gare;4505;123;4628 +12053;La Capelle-Balaguier;306;8;314 +12054;La Capelle-Bleys;361;8;369 +12055;La Capelle-Bonance;83;0;83 +12057;Cassagnes-Bégonhès;904;36;940 +12058;Cassuéjouls;108;5;113 +12059;Castanet;513;24;537 +12060;Castelmary;115;4;119 +12061;Castelnau-de-Mandailles;586;11;597 +12062;Castelnau-Pégayrols;333;4;337 +12257;Causse-et-Diège;758;18;776 +12063;La Cavalerie;1441;29;1470 +12064;Le Cayrol;259;4;263 +12065;Centrès;459;10;469 +12066;Clairvaux-d'Aveyron;1144;26;1170 +12067;Le Clapier;78;0;78 +12068;Colombiès;903;27;930 +12069;Combret;270;7;277 +12070;Compeyre;530;18;548 +12071;Compolibat;347;6;353 +12072;Comprégnac;249;9;258 +12073;Comps-la-Grand-Ville;624;20;644 +12074;Condom-d'Aubrac;301;13;314 +12075;Connac;109;3;112 +12076;Conques-en-Rouergue;1673;51;1724 +12077;Cornus;524;12;536 +12078;Les Costes-Gozon;186;1;187 +12079;Coubisou;492;14;506 +12080;Coupiac;392;9;401 +12082;La Couvertoirade;188;2;190 +12083;Cransac;1508;55;1563 +12084;Creissels;1591;47;1638 +12085;Crespin;312;0;312 +12086;La Cresse;317;14;331 +12307;Curan;302;14;316 +12088;Curières;226;4;230 +12089;Decazeville;5360;204;5564 +12090;Druelle Balsac;3143;91;3234 +12091;Drulhe;446;13;459 +12092;Durenque;524;9;533 +12094;Entraygues-sur-Truyère;996;14;1010 +12095;Escandolières;234;6;240 +12096;Espalion;4516;127;4643 +12097;Espeyrac;245;3;248 +12098;Estaing;473;16;489 +12099;Fayet;257;4;261 +12093;Le Fel;176;1;177 +12100;Firmi;2393;66;2459 +12101;Flagnac;1060;36;1096 +12102;Flavin;2322;48;2370 +12103;Florentin-la-Capelle;279;8;287 +12104;Foissac;476;10;486 +12155;Fondamente;327;10;337 +12105;La Fouillade;1081;25;1106 +12106;Gabriac;504;10;514 +12107;Gaillac-d'Aveyron;307;4;311 +12108;Galgan;373;7;380 +12109;Gissac;103;2;105 +12110;Golinhac;336;17;353 +12111;Goutrens;509;19;528 +12113;Gramond;498;7;505 +12115;L' Hospitalet-du-Larzac;280;2;282 +12116;Huparlac;257;7;264 +12118;Lacroix-Barrez;506;13;519 +12119;Laguiole;1242;26;1268 +12120;Laissac-Sévérac l'Église;2120;102;2222 +12121;Lanuéjouls;731;17;748 +12122;Lapanouse-de-Cernon;123;8;131 +12124;Lassouts;289;13;302 +12125;Laval-Roquecezière;282;4;286 +12127;Lédergues;644;20;664 +12128;Lescure-Jaoul;229;6;235 +12129;Lestrade-et-Thouels;493;9;502 +12130;Livinhac-le-Haut;1123;34;1157 +12131;La Loubière;1472;46;1518 +12133;Luc-la-Primaube;5969;163;6132 +12134;Lugan;337;10;347 +12135;Lunac;434;16;450 +12136;Maleville;953;18;971 +12137;Manhac;819;11;830 +12138;Marcillac-Vallon;1707;50;1757 +12139;Marnhagues-et-Latour;139;1;140 +12140;Martiel;1009;24;1033 +12141;Martrin;226;7;233 +12142;Mayran;635;15;650 +12143;Mélagues;60;0;60 +12144;Meljac;130;2;132 +12145;Millau;22109;735;22844 +12146;Le Monastère;2283;75;2358 +12147;Montagnol;133;1;134 +12148;Montbazens;1388;43;1431 +12149;Montclar;161;5;166 +12150;Monteils;542;89;631 +12151;Montézic;226;8;234 +12152;Montfranc;124;2;126 +12153;Montjaux;406;7;413 +12154;Montlaur;626;25;651 +12156;Montpeyroux;541;11;552 +12157;Montrozier;1630;47;1677 +12158;Montsalès;330;5;335 +12159;Morlhon-le-Haut;557;24;581 +12160;Mostuéjouls;315;5;320 +12192;Mounes-Prohencoux;182;8;190 +12161;Mouret;538;19;557 +12162;Moyrazès;1109;28;1137 +12164;Mur-de-Barrez;759;19;778 +12163;Murasson;194;4;198 +12165;Muret-le-Château;352;16;368 +12166;Murols;113;1;114 +12167;Najac;698;22;720 +12168;Nant;1004;19;1023 +12169;Naucelle;2004;145;2149 +12170;Naussac;373;8;381 +12171;Nauviale;553;19;572 +12172;Le Nayrac;512;12;524 +12174;Olemps;3403;92;3495 +12175;Ols-et-Rinhodes;173;2;175 +12176;Onet-le-Château;11881;574;12455 +12177;Palmas d'Aveyron;1024;15;1039 +12178;Paulhe;389;9;398 +12179;Peux-et-Couffouleux;87;1;88 +12180;Peyreleau;74;5;79 +12181;Peyrusse-le-Roc;227;5;232 +12182;Pierrefiche;274;5;279 +12183;Plaisance;221;6;227 +12184;Pomayrols;119;4;123 +12185;Pont-de-Salars;1652;43;1695 +12186;Pousthomy;211;3;214 +12187;Prades-d'Aubrac;378;4;382 +12188;Prades-Salars;309;5;314 +12189;Pradinas;360;6;366 +12190;Prévinquières;308;6;314 +12191;Privezac;323;10;333 +12193;Pruines;297;13;310 +12194;Quins;844;21;865 +12195;Rebourguil;280;4;284 +12197;Réquista;2005;94;2099 +12198;Rieupeyroux;1974;71;2045 +12199;Rignac;1946;139;2085 +12200;Rivière-sur-Tarn;1043;23;1066 +12201;Rodelle;1066;41;1107 +12202;Rodez;24057;1848;25905 +12204;La Roque-Sainte-Marguerite;182;6;188 +12203;Roquefort-sur-Soulzon;552;15;567 +12205;La Rouquette;784;32;816 +12206;Roussennac;628;17;645 +12207;Rullac-Saint-Cirq;344;5;349 +12208;Saint-Affrique;8089;657;8746 +12209;Saint-Amans-des-Cots;754;13;767 +12210;Saint-André-de-Najac;442;4;446 +12211;Saint-André-de-Vézines;135;1;136 +12212;Saint-Beaulize;89;8;97 +12213;Saint-Beauzély;596;15;611 +12214;Saint-Chély-d'Aubrac;529;14;543 +12215;Saint-Christophe-Vallon;1138;40;1178 +12216;Saint-Côme-d'Olt;1349;29;1378 +12221;Saint-Félix-de-Lunel;347;9;356 +12222;Saint-Félix-de-Sorgues;213;4;217 +12224;Saint Geniez d'Olt et d'Aubrac;2196;39;2235 +12225;Saint-Georges-de-Luzençon;1617;38;1655 +12226;Saint-Hippolyte;435;12;447 +12227;Saint-Igest;191;5;196 +12228;Saint-Izaire;303;9;312 +12229;Saint-Jean-d'Alcapiès;255;8;263 +12230;Saint-Jean-Delnous;418;16;434 +12231;Saint-Jean-du-Bruel;702;7;709 +12232;Saint-Jean-et-Saint-Paul;278;8;286 +12233;Saint-Juéry;287;3;290 +12235;Saint-Just-sur-Viaur;209;7;216 +12237;Saint-Laurent-d'Olt;646;80;726 +12236;Saint-Laurent-de-Lévézou;153;5;158 +12238;Saint-Léons;398;9;407 +12239;Saint-Martin-de-Lenne;302;12;314 +12240;Saint-Parthem;406;10;416 +12242;Saint-Rémy;317;15;332 +12243;Saint-Rome-de-Cernon;925;12;937 +12244;Saint-Rome-de-Tarn;871;17;888 +12246;Saint-Santin;555;10;565 +12247;Saint-Saturnin-de-Lenne;295;7;302 +12248;Saint-Sernin-sur-Rance;622;116;738 +12249;Saint-Sever-du-Moustier;201;8;209 +12250;Saint-Symphorien-de-Thénières;211;2;213 +12251;Saint-Victor-et-Melvieu;365;7;372 +12217;Sainte-Croix;736;18;754 +12219;Sainte-Eulalie-d'Olt;374;14;388 +12220;Sainte-Eulalie-de-Cernon;286;2;288 +12234;Sainte-Juliette-sur-Viaur;598;7;605 +12241;Sainte-Radegonde;1756;64;1820 +12252;Salles-Courbatiès;417;9;426 +12253;Salles-Curan;1043;29;1072 +12254;Salles-la-Source;2220;75;2295 +12255;Salmiech;773;24;797 +12256;Salvagnac-Cajarc;378;6;384 +12258;La Salvetat-Peyralès;976;15;991 +12259;Sanvensa;654;17;671 +12260;Sauclières;170;2;172 +12261;Saujac;125;3;128 +12262;Sauveterre-de-Rouergue;777;15;792 +12263;Savignac;721;23;744 +12264;Sébazac-Concourès;3253;90;3343 +12265;Sébrazac;506;6;512 +12266;Ségur;557;5;562 +12267;La Selve;628;12;640 +12268;Sénergues;421;16;437 +12269;La Serre;120;3;123 +12270;Sévérac d'Aveyron;4084;128;4212 +12272;Sonnac;518;10;528 +12273;Soulages-Bonneval;293;8;301 +12274;Sylvanès;111;2;113 +12275;Tauriac-de-Camarès;41;1;42 +12276;Tauriac-de-Naucelle;372;13;385 +12277;Taussac;520;4;524 +12278;Tayrac;176;2;178 +12280;Thérondels;406;7;413 +12281;Toulonjac;747;22;769 +12282;Tournemire;427;8;435 +12283;Trémouilles;504;13;517 +12284;Le Truel;345;7;352 +12286;Vabres-l'Abbaye;1200;32;1232 +12287;Vailhourles;634;20;654 +12288;Valady;1536;36;1572 +12289;Valzergues;214;11;225 +12290;Vaureilles;499;11;510 +12291;Verrières;454;8;462 +12292;Versols-et-Lapeyre;420;14;434 +12293;Veyreau;137;1;138 +12294;Vézins-de-Lévézou;656;15;671 +12295;Viala-du-Pas-de-Jaux;99;2;101 +12296;Viala-du-Tarn;504;10;514 +12297;Le Vibal;507;19;526 +12298;Villecomtal;403;8;411 +12299;Villefranche-de-Panat;703;27;730 +12300;Villefranche-de-Rouergue;11867;624;12491 +12301;Villeneuve;1988;47;2035 +12303;Vimenet;244;8;252 +12305;Viviez;1274;33;1307 +13001;Aix-en-Provence;142482;3194;145676 +13002;Allauch;21187;207;21394 +13003;Alleins;2512;50;2562 +13004;Arles;52548;770;53318 +13005;Aubagne;46209;412;46621 +13006;Aureille;1522;27;1549 +13007;Auriol;11908;176;12084 +13008;Aurons;551;16;567 +13009;La Barben;845;33;878 +13010;Barbentane;4143;189;4332 +13011;Les Baux-de-Provence;355;8;363 +13012;Beaurecueil;582;54;636 +13013;Belcodène;1898;34;1932 +13014;Berre-l'Étang;13472;91;13563 +13015;Bouc-Bel-Air;14654;292;14946 +13016;La Bouilladisse;6194;81;6275 +13017;Boulbon;1506;19;1525 +13018;Cabannes;4441;59;4500 +13019;Cabriès;9751;329;10080 +13020;Cadolive;2161;44;2205 +13119;Carnoux-en-Provence;6600;83;6683 +13021;Carry-le-Rouet;5823;128;5951 +13022;Cassis;7149;101;7250 +13023;Ceyreste;4584;92;4676 +13024;Charleval;2700;36;2736 +13025;Châteauneuf-le-Rouge;2235;72;2307 +13026;Châteauneuf-les-Martigues;16850;70;16920 +13027;Châteaurenard;15814;227;16041 +13028;La Ciotat;35174;389;35563 +13029;Cornillon-Confoux;1373;22;1395 +13118;Coudoux;3765;51;3816 +13030;Cuges-les-Pins;5080;54;5134 +13031;La Destrousse;3503;42;3545 +13032;Éguilles;7856;140;7996 +13033;Ensuès-la-Redonne;5484;92;5576 +13034;Eygalières;1839;30;1869 +13035;Eyguières;7008;168;7176 +13036;Eyragues;4468;128;4596 +13037;La Fare-les-Oliviers;8476;98;8574 +13038;Fontvieille;3591;91;3682 +13039;Fos-sur-Mer;15494;160;15654 +13040;Fuveau;10157;181;10338 +13041;Gardanne;20794;349;21143 +13042;Gémenos;6502;124;6626 +13043;Gignac-la-Nerthe;9326;83;9409 +13044;Grans;5118;82;5200 +13045;Graveson;4864;80;4944 +13046;Gréasque;4235;74;4309 +13047;Istres;43133;684;43817 +13048;Jouques;4413;97;4510 +13049;Lamanon;2004;42;2046 +13050;Lambesc;9672;247;9919 +13051;Lançon-Provence;8959;116;9075 +13052;Maillane;2582;32;2614 +13053;Mallemort;6019;113;6132 +13054;Marignane;32920;242;33162 +13201;Marseille 1er Arrondissement;39786;181;39967 +13202;Marseille 2e Arrondissement;24810;63;24873 +13203;Marseille 3e Arrondissement;48764;226;48990 +13204;Marseille 4e Arrondissement;48459;332;48791 +13205;Marseille 5e Arrondissement;46199;300;46499 +13206;Marseille 6e Arrondissement;42827;422;43249 +13207;Marseille 7e Arrondissement;34909;319;35228 +13208;Marseille 8e Arrondissement;81028;1180;82208 +13209;Marseille 9e Arrondissement;75914;658;76572 +13210;Marseille 10e Arrondissement;56138;374;56512 +13211;Marseille 11e Arrondissement;56790;457;57247 +13212;Marseille 12e Arrondissement;60634;591;61225 +13213;Marseille 13e Arrondissement;91992;736;92728 +13214;Marseille 14e Arrondissement;62951;271;63222 +13215;Marseille 15e Arrondissement;75901;317;76218 +13216;Marseille 16e Arrondissement;16208;78;16286 +13056;Martigues;48188;468;48656 +13057;Mas-Blanc-des-Alpilles;511;11;522 +13058;Maussane-les-Alpilles;2289;48;2337 +13059;Meyrargues;3804;53;3857 +13060;Meyreuil;5669;87;5756 +13062;Mimet;4482;78;4560 +13063;Miramas;26470;357;26827 +13064;Mollégès;2594;28;2622 +13065;Mouriès;3409;49;3458 +13066;Noves;5891;75;5966 +13067;Orgon;2963;36;2999 +13068;Paradou;2023;33;2056 +13069;Pélissanne;10344;259;10603 +13070;La Penne-sur-Huveaune;6436;59;6495 +13071;Les Pennes-Mirabeau;21046;275;21321 +13072;Peynier;3480;132;3612 +13073;Peypin;5495;75;5570 +13074;Peyrolles-en-Provence;5105;89;5194 +13076;Plan-d'Orgon;3453;48;3501 +13075;Plan-de-Cuques;10934;110;11044 +13077;Port-de-Bouc;16516;122;16638 +13078;Port-Saint-Louis-du-Rhône;8449;84;8533 +13080;Le Puy-Sainte-Réparade;5719;92;5811 +13079;Puyloubier;1792;103;1895 +13081;Rognac;12223;107;12330 +13082;Rognes;4735;127;4862 +13083;Rognonas;4101;59;4160 +13084;La Roque-d'Anthéron;5455;108;5563 +13085;Roquefort-la-Bédoule;5688;71;5759 +13086;Roquevaire;9003;142;9145 +13087;Rousset;4844;127;4971 +13088;Le Rove;5128;44;5172 +13089;Saint-Andiol;3247;43;3290 +13090;Saint-Antonin-sur-Bayon;124;4;128 +13091;Saint-Cannat;5634;115;5749 +13092;Saint-Chamas;8574;125;8699 +13093;Saint-Estève-Janson;381;8;389 +13094;Saint-Étienne-du-Grès;2481;43;2524 +13095;Saint-Marc-Jaumegarde;1250;43;1293 +13097;Saint-Martin-de-Crau;13389;267;13656 +13098;Saint-Mitre-les-Remparts;5837;110;5947 +13099;Saint-Paul-lès-Durance;871;17;888 +13061;Saint-Pierre-de-Mézoargues;207;5;212 +13100;Saint-Rémy-de-Provence;9893;224;10117 +13101;Saint-Savournin;3361;56;3417 +13102;Saint-Victoret;6625;59;6684 +13096;Saintes-Maries-de-la-Mer;2330;22;2352 +13103;Salon-de-Provence;45528;582;46110 +13104;Sausset-les-Pins;7568;144;7712 +13105;Sénas;6965;87;7052 +13106;Septèmes-les-Vallons;11019;75;11094 +13107;Simiane-Collongue;5596;91;5687 +13108;Tarascon;14813;140;14953 +13109;Le Tholonet;2305;57;2362 +13110;Trets;10613;162;10775 +13111;Vauvenargues;1013;20;1033 +13112;Velaux;8689;153;8842 +13113;Venelles;8383;185;8568 +13114;Ventabren;5459;145;5604 +13115;Vernègues;1845;37;1882 +13116;Verquières;818;17;835 +13117;Vitrolles;33310;340;33650 +14001;Ablon;1204;44;1248 +14003;Agy;292;6;298 +14006;Amayé-sur-Orne;1001;19;1020 +14007;Amayé-sur-Seulles;230;4;234 +14009;Amfreville;1399;20;1419 +14012;Angerville;172;1;173 +14015;Anisy;730;17;747 +14016;Annebault;448;13;461 +14019;Arganchy;227;3;230 +14020;Argences;3718;30;3748 +14021;Arromanches-les-Bains;489;12;501 +14022;Asnelles;595;8;603 +14023;Asnières-en-Bessin;65;2;67 +14024;Auberville;574;12;586 +14025;Aubigny;308;3;311 +14026;Audrieu;1046;19;1065 +14591;Aure sur Mer;739;9;748 +14011;Aurseulles;1916;40;1956 +14030;Authie;1595;47;1642 +14032;Les Authieux-sur-Calonne;286;11;297 +14033;Auvillars;227;2;229 +14034;Avenay;557;2;559 +14035;Balleroy-sur-Drôme;1408;57;1465 +14036;Banneville-la-Campagne;173;1;174 +14038;Banville;792;9;801 +14039;Barbery;825;17;842 +14040;Barbeville;178;3;181 +14041;Barneville-la-Bertran;127;2;129 +14042;Baron-sur-Odon;939;18;957 +14043;Barou-en-Auge;78;0;78 +14044;Basly;1105;17;1122 +14045;Basseneville;257;1;258 +14046;Bavent;1814;14;1828 +14047;Bayeux;13121;370;13491 +14049;Bazenville;137;2;139 +14050;La Bazoque;183;2;185 +14231;Beaufour-Druval;444;12;456 +14053;Beaumais;181;1;182 +14054;Beaumesnil;203;3;206 +14055;Beaumont-en-Auge;400;8;408 +14527;Belle Vie en Auge;533;8;541 +14057;Bellengreville;1493;17;1510 +14059;Benerville-sur-Mer;420;33;453 +14060;Bénouville;2049;39;2088 +14062;Bény-sur-Mer;445;8;453 +14063;Bernesq;204;1;205 +14064;Bernières-d'Ailly;243;7;250 +14066;Bernières-sur-Mer;2308;36;2344 +14069;Beuvillers;1351;27;1378 +14070;Beuvron-en-Auge;188;6;194 +14068;Biéville-Beuville;3391;71;3462 +14076;Blainville-sur-Orne;5801;75;5876 +14077;Blangy-le-Château;700;77;777 +14078;Blay;383;6;389 +14079;Blonville-sur-Mer;1545;35;1580 +14080;Le Bô;116;5;121 +14082;La Boissière;189;4;193 +14083;Bonnebosq;677;15;692 +14084;Bonnemaison;404;8;412 +14085;Bonneville-la-Louvet;756;11;767 +14086;Bonneville-sur-Touques;347;14;361 +14087;Bonnœil;131;1;132 +14088;Bons-Tassilly;404;8;412 +14089;Bougy;402;7;409 +14090;Boulon;681;6;687 +14091;Bourgeauville;107;1;108 +14092;Bourguébus;2016;22;2038 +14093;Branville;196;4;200 +14096;Brémoy;227;6;233 +14097;Bretteville-le-Rabet;305;5;310 +14100;Bretteville-sur-Laize;1876;25;1901 +14101;Bretteville-sur-Odon;3833;80;3913 +14102;Le Breuil-en-Auge;1028;23;1051 +14103;Le Breuil-en-Bessin;399;7;406 +14104;Le Brévedent;172;4;176 +14106;Bréville-les-Monts;655;5;660 +14107;Bricqueville;183;3;186 +14110;Brucourt;115;2;117 +14116;Le Bû-sur-Rouvres;100;2;102 +14111;Bucéels;397;6;403 +14117;Cabourg;3650;32;3682 +14118;Caen;105354;2169;107523 +14119;Cagny;1910;24;1934 +14120;Cahagnes;1394;25;1419 +14121;Cahagnolles;254;1;255 +14122;La Caine;158;2;160 +14123;Cairon;1987;46;2033 +14124;La Cambe;561;10;571 +14125;Cambes-en-Plaine;1722;49;1771 +14126;Cambremer;1359;24;1383 +14127;Campagnolles;535;0;535 +14130;Campigny;189;1;190 +14131;Canapville;233;5;238 +14132;Canchy;205;0;205 +14134;Canteloup;179;8;187 +14135;Carcagny;281;6;287 +14136;Cardonville;112;0;112 +14137;Carpiquet;2607;23;2630 +14138;Cartigny-l'Épinay;298;6;304 +14554;Le Castelet;1516;11;1527 +14140;Castillon;344;7;351 +14141;Castillon-en-Auge;166;2;168 +14538;Castine-en-Plaine;1552;21;1573 +14143;Caumont-sur-Aure;2368;25;2393 +14145;Cauvicourt;507;4;511 +14146;Cauville;164;3;167 +14147;Cernay;141;1;142 +14149;Cesny-aux-Vignes;419;13;432 +14150;Cesny-les-Sources;1334;28;1362 +14159;Chouain;224;13;237 +14160;Cintheaux;190;6;196 +14161;Clarbec;360;10;370 +14162;Clécy;1276;14;1290 +14163;Cléville;372;2;374 +14166;Colleville-Montgomery;2437;41;2478 +14165;Colleville-sur-Mer;175;4;179 +14167;Colombelles;6918;58;6976 +14168;Colombières;210;3;213 +14169;Colombiers-sur-Seulles;164;7;171 +14014;Colomby-Anguerny;1108;32;1140 +14171;Combray;148;1;149 +14172;Commes;401;10;411 +14174;Condé-en-Normandie;6634;278;6912 +14173;Condé-sur-Ifs;445;14;459 +14175;Condé-sur-Seulles;293;5;298 +14177;Coquainvilliers;856;20;876 +14179;Cordebugle;157;5;162 +14180;Cordey;154;3;157 +14181;Cormelles-le-Royal;4898;42;4940 +14182;Cormolain;419;3;422 +14183;Cossesseville;95;2;97 +14184;Cottun;222;0;222 +14190;Courcy;134;5;139 +14191;Courseulles-sur-Mer;4199;59;4258 +14193;Courtonne-la-Meurdrac;663;20;683 +14194;Courtonne-les-Deux-Églises;658;11;669 +14195;Courvaudon;239;1;240 +14196;Crépon;212;6;218 +14197;Cresserons;1145;28;1173 +14198;Cresseveuille;262;8;270 +14200;Creully sur Seulles;2278;79;2357 +14202;Cricquebœuf;293;6;299 +14203;Cricqueville-en-Auge;185;7;192 +14204;Cricqueville-en-Bessin;194;3;197 +14205;Cristot;214;6;220 +14206;Crocy;311;10;321 +14207;Croisilles;646;7;653 +14209;Crouay;529;10;539 +14211;Culey-le-Patry;357;4;361 +14214;Cussy;186;3;189 +14215;Cuverville;2130;32;2162 +14216;Damblainville;241;3;244 +14218;Danestal;385;7;392 +14220;Deauville;3604;61;3665 +14221;Démouville;3189;48;3237 +14223;Le Détroit;87;2;89 +14224;Deux-Jumeaux;55;3;58 +14347;Dialan sur Chaîne;1068;15;1083 +14225;Dives-sur-Mer;5546;186;5732 +14226;Donnay;279;2;281 +14227;Douville-en-Auge;213;6;219 +14228;Douvres-la-Délivrande;5062;212;5274 +14229;Dozulé;2284;23;2307 +14230;Drubec;118;1;119 +14232;Ducy-Sainte-Marguerite;160;3;163 +14236;Ellon;504;6;510 +14237;Émiéville;588;7;595 +14238;Englesqueville-en-Auge;110;2;112 +14239;Englesqueville-la-Percée;104;0;104 +14240;Épaney;514;11;525 +14241;Épinay-sur-Odon;614;10;624 +14242;Épron;1634;26;1660 +14243;Équemauville;1444;5;1449 +14244;Eraines;349;8;357 +14245;Ernes;322;10;332 +14246;Escoville;803;4;807 +14248;Espins;245;5;250 +14249;Esquay-Notre-Dame;1433;10;1443 +14250;Esquay-sur-Seulles;291;6;297 +14251;Esson;516;10;526 +14252;Estrées-la-Campagne;248;3;251 +14254;Éterville;1631;27;1658 +14256;Étréham;349;5;354 +14257;Évrecy;2008;37;2045 +14258;Falaise;8186;305;8491 +14260;Fauguernon;246;7;253 +14261;Le Faulq;343;7;350 +14266;Feuguerolles-Bully;1428;24;1452 +14269;Fierville-les-Parcs;212;4;216 +14270;Firfol;414;16;430 +14271;Fleury-sur-Orne;4915;70;4985 +14272;La Folie;99;2;101 +14273;La Folletière-Abenon;129;1;130 +14274;Fontaine-Étoupefour;2348;58;2406 +14275;Fontaine-Henry;466;6;472 +14276;Fontaine-le-Pin;357;4;361 +14277;Fontenay-le-Marmion;1930;23;1953 +14278;Fontenay-le-Pesnel;1160;17;1177 +14280;Formentin;250;5;255 +14281;Formigny La Bataille;731;14;745 +14282;Foulognes;197;3;200 +14283;Fourches;231;4;235 +14284;Fourneaux-le-Val;158;4;162 +14285;Le Fournet;62;0;62 +14286;Fourneville;495;22;517 +14287;Frénouville;1948;14;1962 +14288;Le Fresne-Camilly;900;23;923 +14289;Fresné-la-Mère;604;14;618 +14290;Fresney-le-Puceux;822;7;829 +14291;Fresney-le-Vieux;272;5;277 +14293;Fumichon;283;6;289 +14297;Gavrus;555;7;562 +14298;Géfosse-Fontenay;141;0;141 +14299;Genneville;827;18;845 +14300;Gerrots;53;3;56 +14301;Giberville;4967;53;5020 +14302;Glanville;172;15;187 +14303;Glos;924;21;945 +14306;Gonneville-en-Auge;392;4;396 +14304;Gonneville-sur-Honfleur;875;34;909 +14305;Gonneville-sur-Mer;673;13;686 +14308;Goustranville;201;3;204 +14309;Gouvix;843;3;846 +14310;Grainville-Langannerie;701;7;708 +14311;Grainville-sur-Odon;1037;9;1046 +14312;Grandcamp-Maisy;1563;24;1587 +14316;Grangues;249;3;252 +14318;Graye-sur-Mer;685;9;694 +14319;Grentheville;901;7;908 +14320;Grimbosq;287;7;294 +14322;Guéron;243;7;250 +14325;Hermanville-sur-Mer;3110;40;3150 +14326;Hermival-les-Vaux;813;38;851 +14327;Hérouville-Saint-Clair;22954;260;23214 +14328;Hérouvillette;1275;9;1284 +14329;Heuland;97;3;100 +14332;La Hoguette;714;19;733 +14689;Le Hom;3689;60;3749 +14333;Honfleur;7425;227;7652 +14334;L' Hôtellerie;313;8;321 +14335;Hotot-en-Auge;302;3;305 +14336;Hottot-les-Bagues;483;8;491 +14337;La Houblonnière;330;9;339 +14338;Houlgate;1873;39;1912 +14341;Ifs;11766;196;11962 +14342;Isigny-sur-Mer;3639;45;3684 +14343;Les Isles-Bardel;64;0;64 +14344;Janville;368;9;377 +14345;Jort;299;1;300 +14346;Juaye-Mondaye;670;14;684 +14348;Juvigny-sur-Seulles;84;1;85 +14349;Laize-Clinchamps;2017;22;2039 +14352;Landelles-et-Coupigny;861;20;881 +14353;Landes-sur-Ajon;426;5;431 +14354;Langrune-sur-Mer;1824;43;1867 +14358;Léaupartie;88;2;90 +14360;Leffard;204;2;206 +14362;Lessard-et-le-Chêne;158;0;158 +14364;Lingèvres;464;6;470 +14365;Lion-sur-Mer;2461;39;2500 +14366;Lisieux;20318;668;20986 +14367;Lison;443;5;448 +14368;Lisores;260;13;273 +14369;Litteau;293;3;296 +14371;Livarot-Pays-d'Auge;6323;114;6437 +14374;Les Loges;132;2;134 +14375;Les Loges-Saulces;170;3;173 +14377;Longues-sur-Mer;606;15;621 +14378;Longueville;279;9;288 +14379;Longvillers;360;5;365 +14380;Loucelles;183;5;188 +14381;Louvagny;60;3;63 +14383;Louvigny;2742;39;2781 +14384;Luc-sur-Mer;3182;53;3235 +14385;Magny-en-Bessin;155;8;163 +14389;Maisoncelles-Pelvey;262;9;271 +14390;Maisoncelles-sur-Ajon;189;4;193 +14391;Maisons;388;4;392 +14393;Maizet;363;4;367 +14394;Maizières;444;15;459 +14037;Malherbe-sur-Ajon;548;13;561 +14396;Maltot;1036;21;1057 +14397;Mandeville-en-Bessin;336;7;343 +14398;Manerbe;555;16;571 +14399;Manneville-la-Pipard;290;8;298 +14400;Le Manoir;219;3;222 +14401;Manvieux;131;6;137 +14402;Le Marais-la-Chapelle;108;2;110 +14403;Marolles;768;22;790 +14404;Martainville;119;1;120 +14405;Martigny-sur-l'Ante;319;6;325 +14407;Mathieu;2223;66;2289 +14408;May-sur-Orne;1960;15;1975 +14409;Merville-Franceville-Plage;2169;36;2205 +14410;Méry-Bissières-en-Auge;1106;8;1114 +14411;Meslay;292;5;297 +14412;Le Mesnil-au-Grain;77;2;79 +14419;Le Mesnil-Eudes;258;8;266 +14421;Le Mesnil-Guillaume;605;6;611 +14424;Le Mesnil-Robert;193;2;195 +14425;Le Mesnil-Simon;180;7;187 +14426;Le Mesnil-sur-Blangy;166;7;173 +14427;Le Mesnil-Villement;299;3;302 +14430;Meuvaines;144;3;147 +14431;Mézidon Vallée d'Auge;9712;116;9828 +14370;Le Molay-Littry;2988;36;3024 +14435;Les Monceaux;181;3;184 +14436;Monceaux-en-Bessin;563;4;567 +14437;Mondeville;9868;263;10131 +14438;Mondrainville;521;9;530 +14439;Monfréville;94;2;96 +14445;Montfiquet;106;2;108 +14446;Montigny;96;2;98 +14713;Montillières-sur-Orne;596;11;607 +14448;Montreuil-en-Auge;57;0;57 +14027;Les Monts d'Aunay;4669;65;4734 +14449;Monts-en-Bessin;415;5;420 +14452;Morteaux-Coulibœuf;647;4;651 +14453;Mosles;354;4;358 +14454;Mouen;1601;22;1623 +14455;Moulines;303;5;308 +14406;Moulins en Bessin;1171;21;1192 +14456;Moult-Chicheboville;3095;31;3126 +14457;Les Moutiers-en-Auge;122;3;125 +14458;Les Moutiers-en-Cinglais;517;59;576 +14460;Moyaux;1359;33;1392 +14461;Mutrécy;359;2;361 +14465;Nonant;496;13;509 +14466;Norolles;318;8;326 +14467;Noron-l'Abbaye;301;6;307 +14468;Noron-la-Poterie;397;5;402 +14469;Norrey-en-Auge;93;3;96 +14474;Notre-Dame-d'Estrées-Corbon;225;4;229 +14473;Notre-Dame-de-Livaye;117;3;120 +14658;Noues de Sienne;4423;100;4523 +14476;Olendon;184;3;187 +14478;Orbec;2013;49;2062 +14480;Osmanville;533;7;540 +14482;Ouézy;239;2;241 +14483;Ouffières;189;3;192 +14484;Ouilly-du-Houley;240;8;248 +14486;Ouilly-le-Tesson;591;10;601 +14487;Ouilly-le-Vicomte;810;24;834 +14488;Ouistreham;9081;148;9229 +14491;Parfouru-sur-Odon;196;11;207 +14492;Pennedepie;290;7;297 +14494;Périers-en-Auge;138;3;141 +14495;Périers-sur-le-Dan;513;6;519 +14496;Périgny;58;4;62 +14497;Perrières;327;6;333 +14498;Pertheville-Ners;245;5;250 +14499;Petiville;508;4;512 +14500;Pierrefitte-en-Auge;159;6;165 +14501;Pierrefitte-en-Cinglais;257;6;263 +14502;Pierrepont;93;1;94 +14504;Le Pin;812;21;833 +14506;Planquery;241;0;241 +14509;Plumetot;215;5;220 +14510;La Pommeraye;56;3;59 +14511;Pont-Bellanger;66;0;66 +14764;Pont-d'Ouilly;999;16;1015 +14514;Pont-l'Évêque;4662;70;4732 +14512;Pontécoulant;80;2;82 +14355;Ponts sur Seulles;1169;20;1189 +14515;Port-en-Bessin-Huppain;1942;20;1962 +14516;Potigny;2075;17;2092 +14520;Le Pré-d'Auge;887;22;909 +14519;Préaux-Bocage;123;0;123 +14522;Prêtreville;399;7;406 +14524;Putot-en-Auge;296;5;301 +14528;Quetteville;375;8;383 +14529;Ranchy;248;3;251 +14530;Ranville;1805;29;1834 +14531;Rapilly;47;0;47 +14533;Repentigny;89;3;92 +14534;Reux;410;6;416 +14535;Reviers;566;13;579 +14536;La Rivière-Saint-Sauveur;2538;36;2574 +14540;Rocques;286;14;300 +14541;La Roque-Baignard;118;1;119 +14542;Rosel;541;11;552 +14543;Rots;2438;71;2509 +14546;Rouvres;218;2;220 +14547;Rubercy;171;3;174 +14550;Rumesnil;101;3;104 +14552;Ryes;517;16;533 +14555;Saint-André-d'Hébertot;444;6;450 +14556;Saint-André-sur-Orne;1831;23;1854 +14557;Saint-Arnoult;1165;12;1177 +14558;Saint-Aubin-d'Arquenay;1070;15;1085 +14559;Saint-Aubin-des-Bois;234;1;235 +14562;Saint-Aubin-sur-Mer;2387;40;2427 +14563;Saint-Benoît-d'Hébertot;425;9;434 +14565;Saint-Côme-de-Fresné;263;4;267 +14566;Saint-Contest;2517;52;2569 +14571;Saint-Denis-de-Mailloc;301;5;306 +14572;Saint-Denis-de-Méré;834;12;846 +14574;Saint-Désir;1710;95;1805 +14575;Saint-Étienne-la-Thillaye;414;27;441 +14578;Saint-Gatien-des-Bois;1314;29;1343 +14582;Saint-Germain-de-Livet;769;17;786 +14586;Saint-Germain-du-Pert;179;1;180 +14587;Saint-Germain-la-Blanche-Herbe;2306;37;2343 +14588;Saint-Germain-Langot;319;4;323 +14589;Saint-Germain-le-Vasson;937;9;946 +14593;Saint-Hymer;664;11;675 +14595;Saint-Jean-de-Livet;221;5;226 +14598;Saint-Jouin;211;3;214 +14601;Saint-Julien-sur-Calonne;165;5;170 +14602;Saint-Lambert;275;2;277 +14603;Saint-Laurent-de-Condel;501;8;509 +14605;Saint-Laurent-sur-Mer;261;8;269 +14606;Saint-Léger-Dubosq;182;2;184 +14607;Saint-Louet-sur-Seulles;148;1;149 +14609;Saint-Loup-Hors;512;9;521 +14610;Saint-Manvieu-Norrey;1927;113;2040 +14613;Saint-Marcouf;102;2;104 +14620;Saint-Martin-aux-Chartrains;412;9;421 +14621;Saint-Martin-de-Bienfaite-la-Cressonnière;452;7;459 +14622;Saint-Martin-de-Blagny;131;6;137 +14623;Saint-Martin-de-Fontenay;2560;19;2579 +14625;Saint-Martin-de-la-Lieue;782;14;796 +14626;Saint-Martin-de-Mailloc;902;20;922 +14627;Saint-Martin-de-Mieux;423;8;431 +14630;Saint-Martin-des-Entrées;686;15;701 +14635;Saint-Omer;184;2;186 +14637;Saint-Ouen-du-Mesnil-Oger;208;3;211 +14639;Saint-Ouen-le-Pin;259;9;268 +14640;Saint-Pair;219;2;221 +14643;Saint-Paul-du-Vernay;818;14;832 +14644;Saint-Philbert-des-Champs;644;14;658 +14645;Saint-Pierre-Azif;164;9;173 +14646;Saint-Pierre-Canivet;400;3;403 +14648;Saint-Pierre-des-Ifs;451;19;470 +14649;Saint-Pierre-du-Bû;477;10;487 +14650;Saint-Pierre-du-Fresne;195;5;200 +14651;Saint-Pierre-du-Jonquet;237;1;238 +14652;Saint-Pierre-du-Mont;80;1;81 +14654;Saint-Pierre-en-Auge;7676;310;7986 +14656;Saint-Rémy;1001;15;1016 +14657;Saint-Samson;308;4;312 +14659;Saint-Sylvain;1435;24;1459 +14660;Saint-Vaast-en-Auge;95;3;98 +14661;Saint-Vaast-sur-Seulles;147;1;148 +14663;Saint-Vigor-le-Grand;2438;51;2489 +14569;Sainte-Croix-sur-Mer;246;6;252 +14590;Sainte-Honorine-de-Ducy;127;3;130 +14592;Sainte-Honorine-du-Fay;1339;18;1357 +14614;Sainte-Marguerite-d'Elle;767;13;780 +14619;Sainte-Marie-Outre-l'Eau;123;2;125 +14712;Saline;5428;117;5545 +14664;Sallen;302;7;309 +14665;Sallenelles;294;3;297 +14667;Saon;225;4;229 +14668;Saonnet;305;3;308 +14669;Sassy;209;3;212 +14579;Seulline;1343;18;1361 +14674;Soignolles;123;3;126 +14675;Soliers;2070;25;2095 +14676;Sommervieu;990;23;1013 +14677;Soulangy;255;6;261 +14061;Souleuvre en Bocage;8839;155;8994 +14678;Soumont-Saint-Quentin;542;7;549 +14679;Subles;672;21;693 +14680;Sully;140;9;149 +14681;Surrain;158;3;161 +14682;Surville;442;13;455 +14357;Terres de Druance;947;23;970 +14684;Tessel;249;3;252 +14685;Thaon;1571;31;1602 +14687;Le Theil-en-Auge;186;3;189 +14098;Thue et Mue;5904;94;5998 +14692;Tilly-sur-Seulles;1700;22;1722 +14694;Le Torquesne;509;19;528 +14698;Touffréville;372;1;373 +14699;Touques;3679;67;3746 +14700;Tour-en-Bessin;658;10;668 +14701;Tourgéville;799;20;819 +14705;Tournières;152;1;153 +14706;Tourville-en-Auge;234;11;245 +14707;Tourville-sur-Odon;1032;14;1046 +14708;Tracy-Bocage;303;7;310 +14709;Tracy-sur-Mer;341;7;348 +14710;Tréprel;108;0;108 +14711;Trévières;924;10;934 +14714;Le Tronquay;776;10;786 +14715;Trouville-sur-Mer;4628;89;4717 +14716;Trungy;215;3;218 +14719;Urville;671;6;677 +14720;Ussy;872;26;898 +14721;Vacognes-Neuilly;627;10;637 +14475;Val d'Arry;2256;48;2304 +14672;Val de Drôme;857;14;871 +14576;Val-de-Vie;540;13;553 +14005;Valambray;1769;25;1794 +14726;Valdallière;5951;119;6070 +14570;Valorbiquet;2508;45;2553 +14723;Valsemé;276;11;287 +14724;Varaville;954;20;974 +14728;Vaucelles;455;7;462 +14731;Vauville;189;13;202 +14732;Vaux-sur-Aure;336;12;348 +14733;Vaux-sur-Seulles;305;9;314 +14734;Vendes;320;8;328 +14735;Vendeuvre;774;11;785 +14739;Ver-sur-Mer;1625;41;1666 +14737;Versainville;469;8;477 +14738;Verson;3616;52;3668 +14740;La Vespière-Friardel;1199;17;1216 +14741;Le Vey;117;3;120 +14742;Vicques;70;0;70 +14743;Victot-Pontfol;107;4;111 +14744;Vienne-en-Bessin;297;4;301 +14745;Vierville-sur-Mer;229;4;233 +14747;Vieux;686;8;694 +14748;Vieux-Bourg;78;1;79 +14751;Vignats;289;8;297 +14752;Villers-Bocage;3108;35;3143 +14753;Villers-Canivet;771;21;792 +14754;Villers-sur-Mer;2644;60;2704 +14755;Villerville;627;14;641 +14756;La Villette;226;3;229 +14758;Villons-les-Buissons;749;24;773 +14760;Villy-Bocage;782;6;788 +14759;Villy-lez-Falaise;273;8;281 +14761;Vimont;746;14;760 +14762;Vire Normandie;17178;891;18069 +15025;Albepierre-Bredons;246;6;252 +15001;Allanche;790;9;799 +15002;Alleuze;216;4;220 +15003;Ally;605;12;617 +15004;Andelat;466;8;474 +15005;Anglards-de-Saint-Flour;349;16;365 +15006;Anglards-de-Salers;777;24;801 +15007;Anterrieux;123;7;130 +15008;Antignac;281;1;282 +15009;Apchon;186;6;192 +15010;Arches;181;3;184 +15011;Arnac;171;2;173 +15012;Arpajon-sur-Cère;6217;170;6387 +15013;Auriac-l'Église;153;0;153 +15014;Aurillac;25499;1329;26828 +15015;Auzers;166;4;170 +15016;Ayrens;652;14;666 +15017;Badailhac;139;6;145 +15018;Barriac-les-Bosquets;124;4;128 +15019;Bassignac;231;4;235 +15020;Beaulieu;94;4;98 +15269;Besse;126;3;129 +15021;Boisset;630;16;646 +15022;Bonnac;164;6;170 +15024;Brageac;76;0;76 +15026;Brezons;183;1;184 +15028;Carlat;352;10;362 +15029;Cassaniouze;528;17;545 +15030;Cayrols;294;7;301 +15032;Celoux;64;1;65 +15033;Cézens;218;4;222 +15034;Chaliers;160;8;168 +15036;Chalvignac;469;7;476 +15037;Champagnac;1095;24;1119 +15038;Champs-sur-Tarentaine-Marchal;1061;31;1092 +15040;Chanterelle;95;7;102 +15041;La Chapelle-d'Alagnon;249;6;255 +15042;La Chapelle-Laurent;261;3;264 +15043;Charmensac;85;2;87 +15045;Chaudes-Aigues;886;26;912 +15046;Chaussenac;219;3;222 +15048;Chazelles;33;0;33 +15049;Cheylade;225;6;231 +15050;Le Claux;181;2;183 +15051;Clavières;209;5;214 +15052;Collandres;152;12;164 +15053;Coltines;454;10;464 +15054;Condat;995;25;1020 +15055;Coren;434;12;446 +15056;Crandelles;845;22;867 +15057;Cros-de-Montvert;194;4;198 +15058;Cros-de-Ronesque;143;1;144 +15059;Cussac;127;7;134 +15060;Deux-Verges;50;2;52 +15061;Dienne;273;4;277 +15063;Drugeac;349;8;357 +15064;Escorailles;79;1;80 +15065;Espinasse;82;2;84 +15066;Le Falgoux;120;2;122 +15067;Le Fau;29;1;30 +15069;Ferrières-Saint-Mary;245;2;247 +15070;Fontanges;199;4;203 +15072;Freix-Anglards;218;6;224 +15073;Fridefont;103;2;105 +15074;Giou-de-Mamou;785;24;809 +15075;Girgols;76;4;80 +15076;Glénat;174;4;178 +15077;Gourdièges;60;0;60 +15078;Jabrun;155;2;157 +15079;Jaleyrac;370;9;379 +15081;Jou-sous-Monjou;102;2;104 +15080;Joursac;146;4;150 +15082;Junhac;301;11;312 +15083;Jussac;2019;72;2091 +15084;Labesserette;293;9;302 +15085;Labrousse;512;14;526 +15086;Lacapelle-Barrès;57;2;59 +15087;Lacapelle-del-Fraisse;344;10;354 +15088;Lacapelle-Viescamp;515;13;528 +15089;Ladinhac;458;8;466 +15090;Lafeuillade-en-Vézie;595;17;612 +15091;Landeyrat;89;5;94 +15092;Lanobre;1419;42;1461 +15093;Lapeyrugue;103;3;106 +15094;Laroquebrou;880;18;898 +15095;Laroquevieille;353;4;357 +15096;Lascelle;299;6;305 +15097;Lastic;122;4;126 +15098;Laurie;91;1;92 +15100;Laveissenet;130;3;133 +15101;Laveissière;524;14;538 +15102;Lavigerie;107;0;107 +15103;Leucamp;234;6;240 +15104;Leynhac;343;9;352 +15105;Leyvaux;37;3;40 +15106;Lieutadès;162;3;165 +15107;Lorcières;173;3;176 +15110;Lugarde;145;6;151 +15111;Madic;207;10;217 +15112;Malbo;97;5;102 +15113;Mandailles-Saint-Julien;187;3;190 +15114;Marcenat;515;7;522 +15116;Marchastel;154;11;165 +15117;Marcolès;595;60;655 +15118;Marmanhac;730;31;761 +15119;Massiac;1745;73;1818 +15120;Mauriac;3603;241;3844 +15121;Maurines;109;0;109 +15122;Maurs;2144;75;2219 +15123;Méallet;170;2;172 +15124;Menet;555;24;579 +15125;Mentières;127;3;130 +15126;Molèdes;92;2;94 +15127;Molompize;287;3;290 +15128;La Monselie;111;3;114 +15129;Montboudif;190;7;197 +15130;Montchamp;136;4;140 +15131;Le Monteil;285;12;297 +15132;Montgreleix;44;0;44 +15133;Montmurat;134;1;135 +15134;Montsalvy;817;12;829 +15135;Montvert;118;3;121 +15137;Moussages;273;7;280 +15138;Murat;1878;98;1976 +15139;Narnhac;72;0;72 +15140;Naucelles;2024;56;2080 +15141;Neussargues en Pinatelle;1818;30;1848 +15142;Neuvéglise-sur-Truyère;1746;43;1789 +15143;Nieudan;106;1;107 +15144;Omps;342;10;352 +15146;Pailherols;127;5;132 +15147;Parlan;437;14;451 +15148;Paulhac;414;11;425 +15149;Paulhenc;252;2;254 +15151;Peyrusse;153;0;153 +15152;Pierrefort;897;22;919 +15153;Pleaux;1489;35;1524 +15154;Polminhac;1163;28;1191 +15155;Pradiers;89;2;91 +15156;Prunet;677;15;692 +15027;Puycapel;783;14;797 +15157;Quézac;339;43;382 +15158;Rageade;100;2;102 +15159;Raulhac;272;7;279 +15160;Reilhac;1105;33;1138 +15161;Rézentières;110;2;112 +15162;Riom-ès-Montagnes;2513;63;2576 +15163;Roannes-Saint-Mary;1088;31;1119 +15164;Roffiac;615;18;633 +15165;Rouffiac;205;5;210 +15268;Le Rouget-Pers;1250;26;1276 +15166;Roumégoux;313;10;323 +15167;Rouziers;121;4;125 +15168;Ruynes-en-Margeride;707;24;731 +15169;Saignes;835;15;850 +15170;Saint-Amandin;231;4;235 +15172;Saint-Antoine;106;1;107 +15173;Saint-Bonnet-de-Condat;116;3;119 +15174;Saint-Bonnet-de-Salers;273;6;279 +15175;Saint-Cernin;1072;28;1100 +15176;Saint-Chamant;239;9;248 +15178;Saint-Cirgues-de-Jordanne;137;7;144 +15179;Saint-Cirgues-de-Malbert;249;4;253 +15180;Saint-Clément;75;1;76 +15181;Saint-Constant-Fournoulès;605;12;617 +15182;Saint-Étienne-Cantalès;132;3;135 +15183;Saint-Étienne-de-Carlat;132;2;134 +15185;Saint-Étienne-de-Chomeil;230;11;241 +15184;Saint-Étienne-de-Maurs;784;19;803 +15187;Saint-Flour;6435;512;6947 +15188;Saint-Georges;1177;30;1207 +15189;Saint-Gérons;217;7;224 +15190;Saint-Hippolyte;117;4;121 +15191;Saint-Illide;656;10;666 +15192;Saint-Jacques-des-Blats;330;5;335 +15194;Saint-Julien-de-Toursac;113;5;118 +15196;Saint-Mamet-la-Salvetat;1550;45;1595 +15199;Saint-Martial;81;1;82 +15200;Saint-Martin-Cantalès;146;3;149 +15201;Saint-Martin-sous-Vigouroux;236;5;241 +15202;Saint-Martin-Valmeroux;734;18;752 +15203;Saint-Mary-le-Plain;159;5;164 +15205;Saint-Paul-de-Salers;105;4;109 +15204;Saint-Paul-des-Landes;1534;47;1581 +15206;Saint-Pierre;134;2;136 +15207;Saint-Poncy;355;12;367 +15208;Saint-Projet-de-Salers;138;1;139 +15209;Saint-Rémy-de-Chaudes-Aigues;119;5;124 +15211;Saint-Santin-Cantalès;307;8;315 +15212;Saint-Santin-de-Maurs;356;15;371 +15213;Saint-Saturnin;205;4;209 +15214;Saint-Saury;185;5;190 +15215;Saint-Simon;1140;38;1178 +15216;Saint-Urcize;417;11;428 +15217;Saint-Victor;107;3;110 +15218;Saint-Vincent-de-Salers;66;2;68 +15186;Sainte-Eulalie;219;3;222 +15198;Sainte-Marie;108;1;109 +15219;Salers;329;5;334 +15220;Salins;147;2;149 +15221;Sansac-de-Marmiesse;1360;34;1394 +15222;Sansac-Veinazès;216;10;226 +15223;Sauvat;214;6;220 +15224;La Ségalassière;125;12;137 +15225;Ségur-les-Villas;202;5;207 +15226;Sénezergues;194;3;197 +15228;Siran;476;11;487 +15229;Soulages;80;3;83 +15230;Sourniac;201;9;210 +15231;Talizat;581;15;596 +15232;Tanavelle;234;8;242 +15233;Teissières-de-Cornet;293;5;298 +15234;Teissières-lès-Bouliès;329;6;335 +15235;Les Ternes;584;15;599 +15236;Thiézac;604;19;623 +15237;Tiviers;172;6;178 +15238;Tournemire;126;3;129 +15240;Trémouille;175;7;182 +15241;La Trinitat;48;4;52 +15242;Le Trioulou;103;3;106 +15243;Trizac;513;9;522 +15244;Ussel;479;9;488 +15245;Vabres;250;4;254 +15108;Val d'Arcomie;987;22;1009 +15246;Valette;228;8;236 +15247;Valjouze;24;0;24 +15248;Valuéjols;565;11;576 +15249;Le Vaulmier;71;4;75 +15250;Vebret;506;9;515 +15251;Védrines-Saint-Loup;141;7;148 +15252;Velzic;430;15;445 +15253;Vernols;65;1;66 +15254;Veyrières;112;3;115 +15255;Vézac;1205;36;1241 +15256;Vèze;56;5;61 +15257;Vezels-Roussy;130;3;133 +15258;Vic-sur-Cère;1828;33;1861 +15259;Vieillespesse;248;2;250 +15260;Vieillevie;111;4;115 +15261;Le Vigean;820;21;841 +15262;Villedieu;556;11;567 +15263;Virargues;133;6;139 +15264;Vitrac;265;6;271 +15265;Ydes;1699;30;1729 +15266;Yolet;550;10;560 +15267;Ytrac;4293;103;4396 +16001;Abzac;484;1;485 +16002;Les Adjots;525;8;533 +16003;Agris;857;10;867 +16005;Aigre;1591;39;1630 +16007;Alloue;468;11;479 +16008;Ambérac;319;2;321 +16009;Ambernac;368;6;374 +16010;Ambleville;180;4;184 +16011;Anais;581;21;602 +16012;Angeac-Champagne;509;9;518 +16013;Angeac-Charente;329;8;337 +16014;Angeduc;127;0;127 +16015;Angoulême;41740;1673;43413 +16016;Ansac-sur-Vienne;829;23;852 +16018;Ars;723;18;741 +16019;Asnières-sur-Nouère;1224;22;1246 +16020;Aubeterre-sur-Dronne;386;1;387 +16023;Aunac-sur-Charente;621;7;628 +16024;Aussac-Vadalle;513;8;521 +16025;Baignes-Sainte-Radegonde;1257;29;1286 +16026;Balzac;1337;33;1370 +16027;Barbezières;125;3;128 +16028;Barbezieux-Saint-Hilaire;4672;223;4895 +16029;Bardenac;228;9;237 +16030;Barret;1027;21;1048 +16031;Barro;413;11;424 +16032;Bassac;524;7;531 +16034;Bazac;143;5;148 +16035;Beaulieu-sur-Sonnette;207;3;210 +16036;Bécheresse;290;9;299 +16204;Bellevigne;1329;25;1354 +16037;Bellon;156;6;162 +16038;Benest;315;9;324 +16039;Bernac;489;9;498 +16040;Berneuil;316;6;322 +16041;Bessac;107;1;108 +16042;Bessé;121;7;128 +16044;Bioussac;227;7;234 +16045;Birac;361;5;366 +16047;Blanzaguet-Saint-Cybard;296;5;301 +16048;Boisbreteau;136;0;136 +16082;Boisné-La Tude;693;12;705 +16049;Bonnes;406;9;415 +16050;Bonneuil;260;1;261 +16053;Bors (Canton de Charente-Sud);116;1;117 +16052;Bors (Canton de Tude-et-Lavalette);268;4;272 +16054;Le Bouchage;166;1;167 +16055;Bouëx;892;12;904 +16056;Bourg-Charente;904;13;917 +16057;Bouteville;322;6;328 +16058;Boutiers-Saint-Trojan;1430;51;1481 +16059;Brettes;175;4;179 +16060;Bréville;466;13;479 +16061;Brie;4221;83;4304 +16062;Brie-sous-Barbezieux;130;1;131 +16063;Brie-sous-Chalais;154;0;154 +16064;Brigueuil;1096;17;1113 +16065;Brillac;639;6;645 +16066;Brossac;486;10;496 +16067;Bunzac;463;10;473 +16068;Cellefrouin;572;6;578 +16069;Cellettes;402;3;405 +16070;Chabanais;1651;33;1684 +16071;Chabrac;570;16;586 +16072;Chadurie;508;9;517 +16073;Chalais;1759;33;1792 +16074;Challignac;324;7;331 +16076;Champagne-Mouton;874;16;890 +16075;Champagne-Vigny;247;4;251 +16077;Champmillon;501;9;510 +16078;Champniers;5151;116;5267 +16079;Chantillac;332;3;335 +16081;La Chapelle;214;5;219 +16083;Charmé;355;6;361 +16084;Charras;337;3;340 +16085;Chasseneuil-sur-Bonnieure;3046;269;3315 +16086;Chassenon;880;20;900 +16087;Chassiecq;143;2;145 +16088;Chassors;1102;37;1139 +16089;Châteaubernard;3714;63;3777 +16090;Châteauneuf-sur-Charente;3536;62;3598 +16091;Châtignac;176;3;179 +16093;Chazelles;1558;25;1583 +16095;Chenon;135;5;140 +16096;Cherves-Châtelars;413;3;416 +16097;Cherves-Richemont;2344;101;2445 +16098;La Chèvrerie;140;2;142 +16099;Chillac;220;3;223 +16100;Chirac;751;17;768 +16101;Claix;1029;6;1035 +16102;Cognac;18825;450;19275 +16103;Combiers;124;5;129 +16104;Condac;477;9;486 +16105;Condéon;607;7;614 +16106;Confolens;2670;155;2825 +16046;Coteaux-du-Blanzacais;1033;18;1051 +16107;Coulgens;537;6;543 +16108;Coulonges;133;1;134 +16109;Courbillac;733;7;740 +16110;Courcôme;792;20;812 +16111;Courgeac;189;3;192 +16112;Courlac;54;2;56 +16113;La Couronne;7732;255;7987 +16114;Couture;159;3;162 +16116;Criteuil-la-Magdeleine;404;9;413 +16117;Curac;125;2;127 +16118;Deviat;143;0;143 +16119;Dignac;1322;15;1337 +16120;Dirac;1518;21;1539 +16121;Douzat;469;14;483 +16122;Ébréon;143;4;147 +16123;Échallat;497;4;501 +16124;Écuras;582;10;592 +16125;Édon;252;6;258 +16127;Empuré;100;3;103 +16128;Épenède;185;6;191 +16130;Les Essards;193;7;200 +16131;Esse;498;7;505 +16132;Étagnac;991;9;1000 +16133;Étriac;201;3;204 +16134;Exideuil-sur-Vienne;1014;27;1041 +16135;Eymouthiers;302;4;306 +16136;La Faye;596;11;607 +16137;Feuillade;310;6;316 +16138;Fléac;3742;103;3845 +16139;Fleurac;242;2;244 +16140;Fontclaireau;436;15;451 +16141;Fontenille;322;11;333 +16142;La Forêt-de-Tessé;189;6;195 +16143;Fouquebrune;682;13;695 +16144;Fouqueure;402;6;408 +16145;Foussignac;635;20;655 +16146;Garat;2055;34;2089 +16147;Gardes-le-Pontaroux;275;7;282 +16148;Genac-Bignac;997;13;1010 +16150;Gensac-la-Pallue;1549;41;1590 +16151;Genté;884;20;904 +16152;Gimeux;716;20;736 +16154;Gond-Pontouvre;6010;114;6124 +16155;Les Gours;108;1;109 +16157;Le Grand-Madieu;173;3;176 +16158;Grassac;323;5;328 +16297;Graves-Saint-Amant;334;10;344 +16160;Guimps;477;8;485 +16161;Guizengeard;170;2;172 +16162;Gurat;180;2;182 +16163;Hiersac;1101;20;1121 +16164;Hiesse;243;2;245 +16165;Houlette;368;4;372 +16166;L' Isle-d'Espagnac;5604;153;5757 +16167;Jarnac;4403;133;4536 +16168;Jauldes;801;8;809 +16169;Javrezac;583;8;591 +16170;Juignac;408;1;409 +16171;Juillac-le-Coq;649;12;661 +16173;Juillé;184;4;188 +16174;Julienne;508;11;519 +16176;Lachaise;319;6;325 +16177;Ladiville;120;2;122 +16178;Lagarde-sur-le-Né;184;5;189 +16180;Laprade;247;5;252 +16183;Lésignac-Durand;187;2;189 +16181;Lessac;535;11;546 +16182;Lesterps;479;15;494 +16184;Lichères;87;0;87 +16185;Ligné;159;2;161 +16186;Lignières-Sonneville;585;19;604 +16187;Linars;2078;48;2126 +16188;Le Lindois;345;4;349 +16189;Londigny;251;6;257 +16190;Longré;187;5;192 +16191;Lonnes;178;1;179 +16193;Louzac-Saint-André;995;18;1013 +16194;Lupsault;99;1;100 +16195;Lussac;290;7;297 +16196;Luxé;723;7;730 +16197;La Magdeleine;114;7;121 +16198;Magnac-Lavalette-Villars;440;5;445 +16199;Magnac-sur-Touvre;3139;68;3207 +16200;Maine-de-Boixe;484;3;487 +16153;Mainxe-Gondeville;1159;24;1183 +16203;Mainzac;110;0;110 +16205;Manot;550;5;555 +16206;Mansle;1671;17;1688 +16207;Marcillac-Lanville;511;10;521 +16208;Mareuil;405;4;409 +16209;Marillac-le-Franc;824;9;833 +16210;Marsac;827;11;838 +16211;Marthon;559;7;566 +16212;Massignac;390;6;396 +16213;Mazerolles;305;5;310 +16215;Médillac;158;5;163 +16216;Mérignac;839;14;853 +16217;Merpins;1104;40;1144 +16218;Mesnac;405;22;427 +16220;Les Métairies;727;15;742 +16221;Mons;247;4;251 +16222;Montboyer;350;7;357 +16223;Montbron;2028;23;2051 +16225;Montembœuf;653;29;682 +16226;Montignac-Charente;728;10;738 +16227;Montignac-le-Coq;138;2;140 +16229;Montjean;236;4;240 +16224;Montmérac;722;17;739 +16230;Montmoreau;2575;102;2677 +16231;Montrollet;312;2;314 +16232;Mornac;2172;51;2223 +16233;Mosnac;451;5;456 +16234;Moulidars;725;8;733 +16406;Moulins-sur-Tardoire;777;15;792 +16236;Mouthiers-sur-Boëme;2436;59;2495 +16237;Mouton;224;3;227 +16238;Moutonneau;115;0;115 +16239;Mouzon;131;2;133 +16240;Nabinaud;100;0;100 +16241;Nanclars;204;5;209 +16242;Nanteuil-en-Vallée;1359;25;1384 +16243;Nercillac;1081;22;1103 +16244;Nersac;2416;53;2469 +16245;Nieuil;932;22;954 +16246;Nonac;281;7;288 +16248;Oradour;164;1;165 +16249;Oradour-Fanais;396;3;399 +16250;Orgedeuil;229;1;230 +16251;Oriolles;255;6;261 +16252;Orival;154;3;157 +16253;Paizay-Naudouin-Embourie;368;3;371 +16254;Palluaud;228;6;234 +16255;Parzac;140;5;145 +16256;Passirac;240;11;251 +16258;Pérignac;462;10;472 +16260;Pillac;266;5;271 +16261;Les Pins;462;15;477 +16263;Plassac-Rouffiac;401;6;407 +16264;Pleuville;342;6;348 +16267;Poullignac;87;1;88 +16268;Poursac;204;2;206 +16269;Pranzac;903;10;913 +16270;Pressignac;349;5;354 +16271;Puymoyen;2377;145;2522 +16272;Puyréaux;533;9;542 +16273;Raix;141;7;148 +16275;Ranville-Breuillaud;176;2;178 +16276;Reignac;747;16;763 +16277;Réparsac;601;11;612 +16279;Rioux-Martin;233;3;236 +16280;Rivières;1999;31;2030 +16281;La Rochefoucauld-en-Angoumois;3981;155;4136 +16282;La Rochette;533;11;544 +16283;Ronsenac;571;7;578 +16284;Rouffiac;122;0;122 +16285;Rougnac;407;5;412 +16286;Rouillac;2976;50;3026 +16287;Roullet-Saint-Estèphe;4262;67;4329 +16289;Roussines;283;2;285 +16290;Rouzède;241;4;245 +16291;Ruelle-sur-Touvre;7201;205;7406 +16292;Ruffec;3410;161;3571 +16293;Saint-Adjutory;481;7;488 +16295;Saint-Amant-de-Boixe;1370;23;1393 +16298;Saint-Amant-de-Nouère;404;3;407 +16301;Saint-Aulais-la-Chapelle;233;3;236 +16302;Saint-Avit;199;2;201 +16303;Saint-Bonnet;407;6;413 +16304;Saint-Brice;965;34;999 +16306;Saint-Christophe;332;8;340 +16307;Saint-Ciers-sur-Bonnieure;334;14;348 +16308;Saint-Claud;1057;24;1081 +16310;Saint-Coutant;220;2;222 +16312;Saint-Cybardeaux;829;12;841 +16315;Saint-Félix;111;1;112 +16316;Saint-Fort-sur-le-Né;372;6;378 +16317;Saint-Fraigne;442;5;447 +16318;Saint-Front;369;1;370 +16320;Saint-Genis-d'Hiersac;907;18;925 +16321;Saint-Georges;54;0;54 +16323;Saint-Germain-de-Montbron;477;11;488 +16325;Saint-Gourson;140;1;141 +16326;Saint-Groux;137;0;137 +16329;Saint-Laurent-de-Céris;778;15;793 +16330;Saint-Laurent-de-Cognac;829;27;856 +16331;Saint-Laurent-des-Combes;92;2;94 +16334;Saint-Martial;131;3;134 +16335;Saint-Martin-du-Clocher;123;3;126 +16336;Saint-Mary;348;3;351 +16337;Saint-Maurice-des-Lions;881;24;905 +16338;Saint-Médard;326;4;330 +16340;Saint-Même-les-Carrières;1068;29;1097 +16341;Saint-Michel;3227;39;3266 +16342;Saint-Palais-du-Né;289;6;295 +16343;Saint-Preuil;292;10;302 +16346;Saint-Quentin-de-Chalais;255;8;263 +16345;Saint-Quentin-sur-Charente;215;2;217 +16347;Saint-Romain;529;14;543 +16348;Saint-Saturnin;1292;31;1323 +16350;Saint-Séverin;774;6;780 +16351;Saint-Simeux;594;13;607 +16352;Saint-Simon;203;3;206 +16353;Saint-Sornin;801;16;817 +16355;Saint-Sulpice-de-Cognac;1216;16;1232 +16356;Saint-Sulpice-de-Ruffec;31;0;31 +16357;Saint-Vallier;136;1;137 +16358;Saint-Yrieix-sur-Charente;7274;223;7497 +16349;Sainte-Sévère;524;11;535 +16354;Sainte-Souline;118;4;122 +16359;Salles-d'Angles;1026;28;1054 +16360;Salles-de-Barbezieux;427;92;519 +16361;Salles-de-Villefagnan;323;6;329 +16362;Salles-Lavalette;352;13;365 +16363;Saulgond;522;10;532 +16364;Sauvagnac;62;2;64 +16365;Sauvignac;104;1;105 +16366;Segonzac;2089;79;2168 +16368;Sers;871;20;891 +16369;Sigogne;992;20;1012 +16370;Sireuil;1158;42;1200 +16372;Souffrignac;134;2;136 +16373;Souvigné;208;6;214 +16374;Soyaux;9351;308;9659 +16375;Suaux;390;5;395 +16377;La Tâche;115;0;115 +16378;Taizé-Aizie;577;16;593 +16379;Taponnat-Fleurignac;1504;27;1531 +16380;Le Tâtre;394;6;400 +16192;Terres-de-Haute-Charente;3953;105;4058 +16381;Theil-Rabier;171;2;173 +16382;Torsac;749;32;781 +16383;Tourriers;758;9;767 +16384;Touvérac;626;6;632 +16385;Touvre;1191;26;1217 +16387;Triac-Lautrait;453;62;515 +16388;Trois-Palis;955;21;976 +16389;Turgon;86;3;89 +16390;Tusson;221;7;228 +16339;Val-d'Auge;811;19;830 +16300;Val-de-Bonnieure;1301;17;1318 +16175;Val des Vignes;1428;24;1452 +16392;Valence;197;4;201 +16393;Vars;2081;31;2112 +16394;Vaux-Lavalette;93;2;95 +16395;Vaux-Rouillac;297;3;300 +16396;Ventouse;126;0;126 +16397;Verdille;353;7;360 +16398;Verneuil;98;5;103 +16399;Verrières;352;9;361 +16400;Verteuil-sur-Charente;658;5;663 +16401;Vervant;146;2;148 +16402;Vibrac;287;5;292 +16403;Le Vieux-Cérier;131;3;134 +16404;Vieux-Ruffec;106;2;108 +16405;Vignolles;168;10;178 +16408;Villebois-Lavalette;744;20;764 +16409;Villefagnan;999;11;1010 +16412;Villejoubert;332;1;333 +16413;Villiers-le-Roux;137;2;139 +16414;Villognon;321;5;326 +16415;Vindelle;1075;18;1093 +16416;Vitrac-Saint-Vincent;521;10;531 +16419;Vouharte;329;2;331 +16420;Voulgézac;248;4;252 +16421;Vouthon;419;6;425 +16422;Vouzan;780;8;788 +16418;Vœuil-et-Giget;1509;27;1536 +16423;Xambes;293;4;297 +16424;Yviers;510;4;514 +16425;Yvrac-et-Malleyrand;547;10;557 +17002;Agudelle;134;4;138 +17003;Aigrefeuille-d'Aunis;4037;71;4108 +17005;Allas-Bocage;195;1;196 +17006;Allas-Champagne;264;4;268 +17007;Anais;320;7;327 +17008;Andilly;2235;33;2268 +17009;Angliers;1060;8;1068 +17010;Angoulins;3940;99;4039 +17011;Annepont;377;5;382 +17012;Annezay;162;5;167 +17013;Antezant-la-Chapelle;349;7;356 +17015;Arces;753;8;761 +17016;Archiac;772;12;784 +17017;Archingeay;671;13;684 +17018;Ardillières;849;13;862 +17019;Ars-en-Ré;1307;23;1330 +17020;Arthenac;345;4;349 +17021;Arvert;3448;78;3526 +17022;Asnières-la-Giraud;1050;31;1081 +17023;Aujac;369;6;375 +17024;Aulnay;1369;25;1394 +17025;Aumagne;707;11;718 +17026;Authon-Ébéon;390;5;395 +17027;Avy;476;7;483 +17028;Aytré;8725;160;8885 +17029;Bagnizeau;207;1;208 +17030;Balanzac;549;6;555 +17031;Ballans;197;2;199 +17032;Ballon;795;7;802 +17033;La Barde;497;6;503 +17034;Barzan;470;7;477 +17035;Bazauges;117;3;120 +17036;Beaugeay;779;20;799 +17037;Beauvais-sur-Matha;635;9;644 +17038;Bedenac;686;6;692 +17039;Belluire;208;1;209 +17041;Benon;1625;15;1640 +17042;Bercloux;439;9;448 +17043;Bernay-Saint-Martin;767;12;779 +17044;Berneuil;1146;21;1167 +17045;Beurlay;1034;18;1052 +17046;Bignay;411;13;424 +17047;Biron;230;1;231 +17048;Blanzac-lès-Matha;328;4;332 +17049;Blanzay-sur-Boutonne;82;5;87 +17050;Bois;530;132;662 +17051;Le Bois-Plage-en-Ré;2248;31;2279 +17052;Boisredon;702;9;711 +17053;Bords;1347;29;1376 +17054;Boresse-et-Martron;210;11;221 +17055;Boscamnant;387;2;389 +17056;Bougneau;605;14;619 +17057;Bouhet;903;16;919 +17058;Bourcefranc-le-Chapus;3454;119;3573 +17059;Bourgneuf;1275;23;1298 +17060;Boutenac-Touvent;224;5;229 +17061;Bran;130;2;132 +17486;La Brée-les-Bains;695;5;700 +17062;Bresdon;223;4;227 +17063;Breuil-la-Réorte;457;7;464 +17065;Breuil-Magné;1685;48;1733 +17064;Breuillet;2917;58;2975 +17066;Brie-sous-Archiac;241;5;246 +17067;Brie-sous-Matha;179;4;183 +17068;Brie-sous-Mortagne;236;3;239 +17069;Brives-sur-Charente;233;6;239 +17070;Brizambourg;905;15;920 +17071;La Brousse;509;9;518 +17072;Burie;1279;26;1305 +17074;Bussac-Forêt;1034;16;1050 +17073;Bussac-sur-Charente;1266;39;1305 +17075;Cabariot;1341;24;1365 +17076;Celles;323;3;326 +17077;Cercoux;1171;14;1185 +17078;Chadenac;498;7;505 +17079;Chaillevette;1565;33;1598 +17080;Chambon;928;12;940 +17081;Chamouillac;374;7;381 +17082;Champagnac;529;8;537 +17083;Champagne;611;12;623 +17084;Champagnolles;648;8;656 +17085;Champdolent;400;7;407 +17086;Chaniers;3590;90;3680 +17087;Chantemerle-sur-la-Soie;185;3;188 +17089;La Chapelle-des-Pots;1002;23;1025 +17091;Charron;1989;23;2012 +17092;Chartuzac;151;2;153 +17093;Le Château-d'Oléron;4184;66;4250 +17094;Châtelaillon-Plage;5846;91;5937 +17095;Chatenet;222;7;229 +17096;Chaunac;78;2;80 +17097;Le Chay;767;15;782 +17098;Chenac-Saint-Seurin-d'Uzet;594;13;607 +17099;Chepniers;646;11;657 +17100;Chérac;1104;16;1120 +17101;Cherbonnières;338;2;340 +17102;Chermignac;1247;34;1281 +17104;Chevanceaux;1044;113;1157 +17105;Chives;331;1;332 +17106;Cierzac;307;5;312 +17107;Ciré-d'Aunis;1361;23;1384 +17108;Clam;418;15;433 +17109;Clavette;1380;19;1399 +17110;Clérac;977;16;993 +17111;Clion;813;12;825 +17112;La Clisse;691;15;706 +17113;La Clotte;708;7;715 +17114;Coivert;213;2;215 +17115;Colombiers;313;7;320 +17116;Consac;211;8;219 +17117;Contré;145;2;147 +17118;Corignac;360;10;370 +17119;Corme-Écluse;1113;22;1135 +17120;Corme-Royal;1839;38;1877 +17121;La Couarde-sur-Mer;1206;20;1226 +17122;Coulonges;241;4;245 +17124;Courant;414;5;419 +17125;Courcelles;471;10;481 +17126;Courcerac;296;6;302 +17128;Courcoury;690;12;702 +17129;Courpignac;412;6;418 +17127;Courçon;1740;28;1768 +17130;Coux;456;13;469 +17131;Cozes;2142;43;2185 +17132;Cramchaban;655;13;668 +17133;Cravans;872;75;947 +17134;Crazannes;440;10;450 +17135;Cressé;240;3;243 +17136;Croix-Chapeau;1245;27;1272 +17137;La Croix-Comtesse;223;3;226 +17138;Dampierre-sur-Boutonne;282;3;285 +17457;La Devise;1121;17;1138 +17140;Dolus-d'Oléron;3229;67;3296 +17141;Dompierre-sur-Charente;458;9;467 +17142;Dompierre-sur-Mer;5482;139;5621 +17143;Le Douhet;713;13;726 +17139;Dœuil-sur-le-Mignon;338;7;345 +17145;Échebrune;485;8;493 +17146;Échillais;3545;60;3605 +17147;Écoyeux;1354;23;1377 +17148;Écurat;471;15;486 +17149;Les Éduts;62;1;63 +17150;Les Églises-d'Argenteuil;519;7;526 +17151;L' Éguille;872;21;893 +17152;Épargnes;843;7;850 +17153;Esnandes;2069;24;2093 +17154;Les Essards;698;8;706 +17277;Essouvert;1163;76;1239 +17155;Étaules;2475;42;2517 +17156;Expiremont;127;3;130 +17157;Fenioux;160;2;162 +17158;Ferrières;922;7;929 +17159;Fléac-sur-Seugne;373;7;380 +17160;Floirac;371;4;375 +17161;La Flotte;2762;42;2804 +17162;Fontaine-Chalendray;201;0;201 +17163;Fontaines-d'Ozillac;520;12;532 +17164;Fontcouverte;2354;55;2409 +17165;Fontenet;396;13;409 +17166;Forges;1301;14;1315 +17167;Le Fouilloux;774;14;788 +17168;Fouras;4006;76;4082 +17171;Geay;747;20;767 +17172;Gémozac;2851;29;2880 +17173;La Genétouze;230;8;238 +17174;Genouillé;895;9;904 +17175;Germignac;651;7;658 +17176;Gibourne;112;0;112 +17177;Le Gicq;125;0;125 +17178;Givrezac;68;1;69 +17179;Les Gonds;1726;70;1796 +17180;Gourvillette;89;3;92 +17485;Le Grand-Village-Plage;1051;14;1065 +17181;Grandjean;300;6;306 +17182;La Grève-sur-Mignon;563;11;574 +17183;Grézac;929;19;948 +17184;La Gripperie-Saint-Symphorien;593;5;598 +17185;Le Gua;2097;33;2130 +17186;Le Gué-d'Alleré;928;11;939 +17187;Guitinières;542;6;548 +17188;Haimps;464;9;473 +17190;L' Houmeau;2853;56;2909 +17004;Île-d'Aix;224;5;229 +17191;La Jard;422;3;425 +17192;Jarnac-Champagne;786;20;806 +17193;La Jarne;2490;42;2532 +17194;La Jarrie;3265;68;3333 +17195;La Jarrie-Audouin;265;15;280 +17196;Jazennes;532;7;539 +17197;Jonzac;3432;224;3656 +17198;Juicq;294;0;294 +17199;Jussas;150;2;152 +17200;Lagord;7048;151;7199 +17201;La Laigne;474;5;479 +17202;Landes;611;17;628 +17203;Landrais;736;9;745 +17204;Léoville;312;8;320 +17205;Loire-les-Marais;393;9;402 +17206;Loiré-sur-Nie;284;4;288 +17207;Loix;729;17;746 +17208;Longèves;975;15;990 +17209;Lonzac;271;4;275 +17210;Lorignac;493;4;497 +17211;Loulay;766;9;775 +17212;Louzignac;160;1;161 +17213;Lozay;136;4;140 +17214;Luchat;525;11;536 +17215;Lussac;52;0;52 +17216;Lussant;1002;14;1016 +17217;Macqueville;290;8;298 +17218;Marans;4497;64;4561 +17219;Marennes-Hiers-Brouage;6252;104;6356 +17220;Marignac;422;17;439 +17221;Marsais;922;21;943 +17222;Marsilly;3045;88;3133 +17223;Massac;175;2;177 +17224;Matha;2166;80;2246 +17225;Les Mathes;1974;29;2003 +17226;Mazeray;959;14;973 +17227;Mazerolles;228;3;231 +17228;Médis;2881;68;2949 +17229;Mérignac;224;3;227 +17230;Meschers-sur-Gironde;3110;64;3174 +17231;Messac;105;6;111 +17232;Meursac;1489;21;1510 +17233;Meux;316;7;323 +17234;Migré;331;6;337 +17235;Migron;724;15;739 +17236;Mirambeau;1492;31;1523 +17237;Moëze;564;4;568 +17239;Mons;438;8;446 +17240;Montendre;3242;55;3297 +17241;Montguyon;1576;23;1599 +17242;Montils;853;12;865 +17243;Montlieu-la-Garde;1264;10;1274 +17244;Montpellier-de-Médillan;682;8;690 +17245;Montroy;893;13;906 +17246;Moragne;507;7;514 +17247;Mornac-sur-Seudre;841;12;853 +17248;Mortagne-sur-Gironde;904;11;915 +17249;Mortiers;186;1;187 +17250;Mosnac;466;5;471 +17252;Le Mung;305;8;313 +17253;Muron;1344;17;1361 +17254;Nachamps;194;4;198 +17255;Nancras;786;12;798 +17256;Nantillé;326;12;338 +17257;Néré;734;8;742 +17258;Neuillac;302;11;313 +17259;Neulles;148;2;150 +17260;Neuvicq;452;5;457 +17261;Neuvicq-le-Château;321;5;326 +17263;Nieul-le-Virouil;578;18;596 +17262;Nieul-lès-Saintes;1252;22;1274 +17264;Nieul-sur-Mer;5759;144;5903 +17265;Nieulle-sur-Seudre;1227;20;1247 +17266;Les Nouillers;698;8;706 +17267;Nuaillé-d'Aunis;1139;15;1154 +17268;Nuaillé-sur-Boutonne;198;7;205 +17269;Orignolles;676;7;683 +17270;Ozillac;626;14;640 +17271;Paillé;315;6;321 +17273;Pérignac;1017;13;1030 +17274;Périgny;8428;184;8612 +17275;Pessines;745;29;774 +17276;Le Pin;80;1;81 +17278;Pisany;738;10;748 +17279;Plassac;597;5;602 +17280;Plassay;721;18;739 +17281;Polignac;170;3;173 +17282;Pommiers-Moulons;207;2;209 +17283;Pons;4182;249;4431 +17284;Pont-l'Abbé-d'Arnoult;1807;235;2042 +17285;Port-d'Envaux;1154;28;1182 +17484;Port-des-Barques;1777;17;1794 +17286;Les Portes-en-Ré;606;12;618 +17287;Pouillac;249;0;249 +17288;Poursay-Garnaud;315;6;321 +17289;Préguillac;450;18;468 +17290;Prignac;297;9;306 +17291;Puilboreau;6182;117;6299 +17292;Puy-du-Lac;487;5;492 +17293;Puyravault;673;10;683 +17294;Puyrolland;201;1;202 +17295;Réaux sur Trèfle;821;15;836 +17296;Rétaud;1069;19;1088 +17298;Rioux;960;18;978 +17297;Rivedoux-Plage;2280;45;2325 +17299;Rochefort;24151;694;24845 +17300;La Rochelle;75735;2120;77855 +17301;Romazières;71;1;72 +17302;Romegoux;603;8;611 +17303;La Ronde;1050;32;1082 +17304;Rouffiac;459;5;464 +17305;Rouffignac;422;9;431 +17306;Royan;18398;551;18949 +17307;Sablonceaux;1397;31;1428 +17308;Saint-Agnant;2682;61;2743 +17309;Saint-Aigulin;1911;40;1951 +17310;Saint-André-de-Lidon;1105;14;1119 +17311;Saint-Augustin;1351;24;1375 +17312;Saint-Bonnet-sur-Gironde;825;14;839 +17313;Saint-Bris-des-Bois;389;9;398 +17314;Saint-Césaire;875;17;892 +17315;Saint-Christophe;1357;27;1384 +17316;Saint-Ciers-Champagne;416;13;429 +17317;Saint-Ciers-du-Taillon;550;8;558 +17318;Saint-Clément-des-Baleines;644;10;654 +17320;Saint-Coutant-le-Grand;421;1;422 +17321;Saint-Crépin;347;3;350 +17322;Saint-Cyr-du-Doret;656;4;660 +17323;Saint-Denis-d'Oléron;1320;22;1342 +17324;Saint-Dizant-du-Bois;111;1;112 +17325;Saint-Dizant-du-Gua;533;3;536 +17326;Saint-Eugène;276;5;281 +17327;Saint-Félix;299;3;302 +17328;Saint-Fort-sur-Gironde;909;10;919 +17329;Saint-Froult;335;7;342 +17331;Saint-Genis-de-Saintonge;1244;51;1295 +17332;Saint-Georges-Antignac;379;6;385 +17337;Saint-Georges-d'Oléron;3719;56;3775 +17333;Saint-Georges-de-Didonne;5360;111;5471 +17334;Saint-Georges-de-Longuepierre;230;4;234 +17335;Saint-Georges-des-Agoûts;288;3;291 +17336;Saint-Georges-des-Coteaux;2692;58;2750 +17338;Saint-Georges-du-Bois;1774;32;1806 +17339;Saint-Germain-de-Lusignan;1303;125;1428 +17341;Saint-Germain-de-Vibrac;190;2;192 +17342;Saint-Germain-du-Seudre;433;8;441 +17343;Saint-Grégoire-d'Ardennes;151;3;154 +17344;Saint-Hilaire-de-Villefranche;1321;15;1336 +17345;Saint-Hilaire-du-Bois;332;6;338 +17346;Saint-Hippolyte;1416;15;1431 +17347;Saint-Jean-d'Angély;6976;441;7417 +17348;Saint-Jean-d'Angle;693;7;700 +17349;Saint-Jean-de-Liversay;2891;41;2932 +17350;Saint-Julien-de-l'Escap;891;20;911 +17351;Saint-Just-Luzac;1993;36;2029 +17353;Saint-Laurent-de-la-Prée;2114;39;2153 +17354;Saint-Léger;632;12;644 +17356;Saint-Loup;303;4;307 +17357;Saint-Maigrin;531;10;541 +17358;Saint-Mandé-sur-Brédoire;309;6;315 +17359;Saint-Mard;1198;18;1216 +17361;Saint-Martial;116;2;118 +17362;Saint-Martial-de-Mirambeau;270;6;276 +17363;Saint-Martial-de-Vitaterne;548;14;562 +17364;Saint-Martial-sur-Né;452;10;462 +17365;Saint-Martin-d'Ary;473;12;485 +17366;Saint-Martin-de-Coux;461;4;465 +17367;Saint-Martin-de-Juillers;158;3;161 +17369;Saint-Martin-de-Ré;2231;20;2251 +17372;Saint-Médard;75;1;76 +17373;Saint-Médard-d'Aunis;2255;43;2298 +17375;Saint-Nazaire-sur-Charente;1186;25;1211 +17376;Saint-Ouen-d'Aunis;1730;28;1758 +17377;Saint-Ouen-la-Thène;114;6;120 +17378;Saint-Palais-de-Négrignac;438;6;444 +17379;Saint-Palais-de-Phiolin;208;3;211 +17380;Saint-Palais-sur-Mer;3897;91;3988 +17381;Saint-Pardoult;241;4;245 +17382;Saint-Pierre-d'Amilly;529;5;534 +17385;Saint-Pierre-d'Oléron;6743;137;6880 +17383;Saint-Pierre-de-Juillers;363;3;366 +17384;Saint-Pierre-de-l'Isle;264;4;268 +17386;Saint-Pierre-du-Palais;366;8;374 +17340;Saint-Pierre-La-Noue;1575;60;1635 +17387;Saint-Porchaire;1862;32;1894 +17388;Saint-Quantin-de-Rançanne;268;7;275 +17391;Saint-Rogatien;2206;50;2256 +17393;Saint-Romain-de-Benet;1712;27;1739 +17394;Saint-Saturnin-du-Bois;891;18;909 +17395;Saint-Sauvant;485;9;494 +17396;Saint-Sauveur-d'Aunis;1704;28;1732 +17397;Saint-Savinien;2433;106;2539 +17398;Saint-Seurin-de-Palenne;165;7;172 +17400;Saint-Sever-de-Saintonge;614;15;629 +17401;Saint-Séverin-sur-Boutonne;99;7;106 +17402;Saint-Sigismond-de-Clermont;159;3;162 +17403;Saint-Simon-de-Bordes;734;13;747 +17404;Saint-Simon-de-Pellouaille;654;7;661 +17405;Saint-Sorlin-de-Conac;198;2;200 +17406;Saint-Sornin;389;3;392 +17408;Saint-Sulpice-d'Arnoult;865;10;875 +17409;Saint-Sulpice-de-Royan;3204;60;3264 +17410;Saint-Thomas-de-Conac;559;9;568 +17411;Saint-Trojan-les-Bains;1262;23;1285 +17412;Saint-Vaize;651;8;659 +17413;Saint-Vivien;1307;19;1326 +17414;Saint-Xandre;4848;158;5006 +17319;Sainte-Colombe;109;1;110 +17330;Sainte-Gemme;1320;15;1335 +17355;Sainte-Lheurine;512;10;522 +17360;Sainte-Marie-de-Ré;3366;107;3473 +17374;Sainte-Même;244;2;246 +17389;Sainte-Radegonde;580;11;591 +17390;Sainte-Ramée;121;4;125 +17407;Sainte-Soulle;4533;90;4623 +17415;Saintes;25470;1343;26813 +17416;Saleignes;62;0;62 +17417;Salignac-de-Mirambeau;164;1;165 +17418;Salignac-sur-Charente;599;16;615 +17420;Salles-sur-Mer;2153;58;2211 +17421;Saujon;7165;114;7279 +17422;Seigné;77;0;77 +17423;Semillac;72;1;73 +17424;Semoussac;364;3;367 +17425;Semussac;2333;46;2379 +17426;Le Seure;255;4;259 +17427;Siecq;215;5;220 +17428;Sonnac;505;10;515 +17429;Soubise;2998;29;3027 +17430;Soubran;380;6;386 +17431;Soulignonne;701;6;707 +17432;Souméras;363;6;369 +17433;Sousmoulins;219;7;226 +17434;Surgères;6807;186;6993 +17435;Taillant;182;1;183 +17436;Taillebourg;731;22;753 +17437;Talmont-sur-Gironde;100;1;101 +17438;Tanzac;312;3;315 +17439;Taugon;791;13;804 +17440;Ternant;379;8;387 +17441;Tesson;1075;23;1098 +17442;Thaims;384;3;387 +17443;Thairé;1691;42;1733 +17444;Thénac;1677;276;1953 +17445;Thézac;321;5;326 +17446;Thors;460;6;466 +17447;Le Thou;1900;31;1931 +17448;Tonnay-Boutonne;1151;11;1162 +17449;Tonnay-Charente;8010;134;8144 +17450;Torxé;202;8;210 +17451;Les Touches-de-Périgny;568;10;578 +17452;La Tremblade;4336;63;4399 +17453;Trizay;1476;33;1509 +17454;Tugéras-Saint-Maurice;376;6;382 +17455;La Vallée;677;11;688 +17458;Vanzac;148;1;149 +17459;Varaize;560;10;570 +17460;Varzay;816;14;830 +17461;Vaux-sur-Mer;3798;75;3873 +17462;Vénérand;761;16;777 +17463;Vergeroux;1208;22;1230 +17465;La Vergne;585;8;593 +17464;Vergné;138;3;141 +17466;Vérines;2245;31;2276 +17467;Vervant;238;2;240 +17468;Vibrac;152;3;155 +17469;Villars-en-Pons;566;12;578 +17470;Villars-les-Bois;246;9;255 +17471;La Villedieu;209;2;211 +17472;Villedoux;2237;17;2254 +17473;Villemorin;97;0;97 +17474;Villeneuve-la-Comtesse;741;15;756 +17476;Villexavier;272;3;275 +17477;Villiers-Couture;116;1;117 +17478;Vinax;61;1;62 +17479;Virollet;275;4;279 +17480;Virson;760;10;770 +17481;Voissay;156;3;159 +17482;Vouhé;656;11;667 +17483;Yves;1477;24;1501 +18001;Achères;380;7;387 +18002;Ainay-le-Vieil;186;4;190 +18003;Les Aix-d'Angillon;1916;28;1944 +18004;Allogny;1017;22;1039 +18005;Allouis;1071;21;1092 +18006;Annoix;233;2;235 +18007;Apremont-sur-Allier;71;3;74 +18009;Arcomps;306;12;318 +18010;Ardenais;200;8;208 +18011;Argent-sur-Sauldre;2102;40;2142 +18012;Argenvières;461;6;467 +18013;Arpheuilles;297;5;302 +18008;Arçay;510;10;520 +18014;Assigny;152;7;159 +18015;Aubigny-sur-Nère;5488;130;5618 +18016;Aubinges;394;3;397 +18017;Augy-sur-Aubois;290;2;292 +18018;Avord;2613;32;2645 +18019;Azy;445;7;452 +18020;Bannay;907;14;921 +18021;Bannegon;274;4;278 +18022;Barlieu;359;8;367 +18023;Baugy;1721;29;1750 +18024;Beddes;93;3;96 +18025;Beffes;641;12;653 +18026;Belleville-sur-Loire;1058;28;1086 +18027;Bengy-sur-Craon;663;65;728 +18028;Berry-Bouy;1189;37;1226 +18029;Bessais-le-Fromental;312;4;316 +18030;Blancafort;1038;33;1071 +18031;Blet;575;6;581 +18032;Boulleret;1436;33;1469 +18033;Bourges;64551;2038;66589 +18034;Bouzais;313;8;321 +18035;Brécy;1013;24;1037 +18036;Brinay;522;7;529 +18037;Brinon-sur-Sauldre;982;14;996 +18038;Bruère-Allichamps;564;10;574 +18039;Bué;313;8;321 +18040;Bussy;380;6;386 +18041;La Celette;181;2;183 +18042;La Celle;348;2;350 +18043;La Celle-Condé;202;0;202 +18044;Cerbois;435;9;444 +18045;Chalivoy-Milon;431;8;439 +18046;Chambon;173;3;176 +18047;La Chapelle-d'Angillon;629;9;638 +18048;La Chapelle-Hugon;387;5;392 +18049;La Chapelle-Montlinard;471;9;480 +18050;La Chapelle-Saint-Ursin;3542;79;3621 +18051;La Chapelotte;151;2;153 +18052;Charenton-du-Cher;1045;21;1066 +18053;Charentonnay;289;8;297 +18054;Charly;249;3;252 +18055;Chârost;980;13;993 +18056;Chassy;241;5;246 +18057;Châteaumeillant;1780;20;1800 +18058;Châteauneuf-sur-Cher;1454;19;1473 +18059;Le Châtelet;994;13;1007 +18060;Chaumont;54;0;54 +18061;Chaumoux-Marcilly;95;1;96 +18062;Le Chautay;293;2;295 +18063;Chavannes;173;5;178 +18064;Chéry;214;9;223 +18065;Chezal-Benoît;829;13;842 +18066;Civray;920;14;934 +18067;Clémont;719;8;727 +18068;Cogny;35;2;37 +18069;Colombiers;408;16;424 +18070;Concressault;204;2;206 +18071;Contres;32;0;32 +18072;Cornusse;268;4;272 +18073;Corquoy;209;8;217 +18074;Couargues;205;5;210 +18075;Cours-les-Barres;1034;25;1059 +18076;Coust;445;8;453 +18077;Couy;355;10;365 +18079;Crézancy-en-Sancerre;486;8;494 +18078;Crézançay-sur-Cher;56;1;57 +18080;Croisy;163;1;164 +18081;Crosses;391;3;394 +18082;Cuffy;1075;31;1106 +18083;Culan;715;6;721 +18084;Dampierre-en-Crot;204;4;208 +18085;Dampierre-en-Graçay;248;6;254 +18086;Drevant;543;16;559 +18087;Dun-sur-Auron;3844;77;3921 +18088;Ennordres;210;7;217 +18089;Épineuil-le-Fleuriel;443;9;452 +18090;Étréchy;456;8;464 +18091;Farges-Allichamps;241;2;243 +18092;Farges-en-Septaine;1009;23;1032 +18093;Faverdines;142;3;145 +18094;Feux;343;8;351 +18095;Flavigny;205;2;207 +18096;Foëcy;2085;23;2108 +18097;Fussy;1982;32;2014 +18098;Gardefort;142;5;147 +18099;Garigny;236;3;239 +18100;Genouilly;680;16;696 +18101;Germigny-l'Exempt;307;4;311 +18102;Givardon;298;4;302 +18103;Graçay;1447;13;1460 +18104;Groises;131;2;133 +18105;Gron;469;9;478 +18106;Grossouvre;274;4;278 +18107;La Groutte;127;8;135 +18108;La Guerche-sur-l'Aubois;3274;37;3311 +18109;Henrichemont;1760;21;1781 +18110;Herry;988;25;1013 +18111;Humbligny;190;0;190 +18112;Ids-Saint-Roch;299;1;300 +18113;Ignol;180;3;183 +18114;Ineuil;238;4;242 +18115;Ivoy-le-Pré;803;8;811 +18116;Jalognes;292;3;295 +18117;Jars;507;5;512 +18118;Jouet-sur-l'Aubois;1348;36;1384 +18119;Jussy-Champagne;194;5;199 +18120;Jussy-le-Chaudrier;607;14;621 +18121;Lantan;91;2;93 +18122;Lapan;207;2;209 +18124;Lazenay;342;5;347 +18125;Léré;1098;22;1120 +18126;Levet;1392;34;1426 +18127;Lignières;1355;28;1383 +18128;Limeux;162;0;162 +18129;Lissay-Lochy;224;5;229 +18130;Loye-sur-Arnon;305;6;311 +18131;Lugny-Bourbonnais;35;0;35 +18132;Lugny-Champagne;142;1;143 +18133;Lunery;1570;17;1587 +18134;Lury-sur-Arnon;668;15;683 +18135;Maisonnais;239;5;244 +18137;Mareuil-sur-Arnon;532;10;542 +18138;Marmagne;1960;58;2018 +18139;Marseilles-lès-Aubigny;657;9;666 +18136;Marçais;282;5;287 +18140;Massay;1390;27;1417 +18141;Mehun-sur-Yèvre;6562;125;6687 +18142;Meillant;686;17;703 +18143;Menetou-Couture;365;8;373 +18144;Menetou-Râtel;484;10;494 +18145;Menetou-Salon;1617;32;1649 +18146;Ménétréol-sous-Sancerre;315;13;328 +18147;Ménétréol-sur-Sauldre;212;4;216 +18148;Méreau;2610;63;2673 +18149;Méry-ès-Bois;577;14;591 +18150;Méry-sur-Cher;678;16;694 +18151;Montigny;387;7;394 +18152;Montlouis;109;0;109 +18153;Morlac;329;3;332 +18154;Mornay-Berry;183;4;187 +18155;Mornay-sur-Allier;431;9;440 +18156;Morogues;438;9;447 +18157;Morthomiers;761;24;785 +18158;Moulins-sur-Yèvre;852;17;869 +18159;Nançay;832;30;862 +18160;Nérondes;1481;35;1516 +18161;Neuilly-en-Dun;224;2;226 +18162;Neuilly-en-Sancerre;253;1;254 +18163;Neuvy-Deux-Clochers;280;5;285 +18164;Neuvy-le-Barrois;139;2;141 +18165;Neuvy-sur-Barangeon;1156;33;1189 +18166;Nohant-en-Goût;600;9;609 +18167;Nohant-en-Graçay;306;2;308 +18168;Le Noyer;219;3;222 +18169;Nozières;215;7;222 +18170;Oizon;675;15;690 +18171;Orcenais;253;4;257 +18172;Orval;1814;44;1858 +18173;Osmery;263;2;265 +18174;Osmoy;269;3;272 +18175;Ourouer-les-Bourdelins;615;3;618 +18176;Parassy;414;5;419 +18177;Parnay;64;0;64 +18178;La Perche;205;3;208 +18179;Pigny;962;19;981 +18180;Plaimpied-Givaudins;1999;65;2064 +18181;Plou;529;8;537 +18182;Poisieux;223;4;227 +18183;Le Pondy;144;3;147 +18184;Précy;345;1;346 +18185;Presly;248;11;259 +18186;Preuilly;441;8;449 +18187;Préveranges;525;10;535 +18188;Primelles;247;6;253 +18189;Quantilly;470;4;474 +18190;Quincy;868;19;887 +18191;Raymond;199;2;201 +18192;Reigny;256;3;259 +18193;Rezay;213;5;218 +18194;Rians;973;19;992 +18195;Sagonne;190;6;196 +18196;Saint-Aignan-des-Noyers;94;0;94 +18197;Saint-Amand-Montrond;9437;277;9714 +18198;Saint-Ambroix;364;9;373 +18199;Saint-Baudel;250;4;254 +18200;Saint-Bouize;312;14;326 +18201;Saint-Caprais;767;15;782 +18202;Saint-Céols;14;0;14 +18203;Saint-Christophe-le-Chaudry;104;1;105 +18204;Saint-Denis-de-Palin;302;8;310 +18205;Saint-Doulchard;9505;247;9752 +18206;Saint-Éloy-de-Gy;1541;52;1593 +18207;Saint-Florent-sur-Cher;6537;102;6639 +18209;Saint-Georges-de-Poisieux;456;9;465 +18210;Saint-Georges-sur-la-Prée;611;11;622 +18211;Saint-Georges-sur-Moulon;696;12;708 +18212;Saint-Germain-des-Bois;628;15;643 +18213;Saint-Germain-du-Puy;5085;114;5199 +18214;Saint-Hilaire-de-Court;595;13;608 +18215;Saint-Hilaire-de-Gondilly;179;5;184 +18216;Saint-Hilaire-en-Lignières;491;14;505 +18217;Saint-Jeanvrin;152;4;156 +18218;Saint-Just;643;4;647 +18219;Saint-Laurent;502;10;512 +18220;Saint-Léger-le-Petit;355;5;360 +18221;Saint-Loup-des-Chaumes;299;2;301 +18223;Saint-Martin-d'Auxigny;2397;38;2435 +18224;Saint-Martin-des-Champs;304;9;313 +18225;Saint-Maur;295;4;299 +18226;Saint-Michel-de-Volangis;468;16;484 +18228;Saint-Outrille;220;3;223 +18229;Saint-Palais;619;19;638 +18230;Saint-Pierre-les-Bois;287;11;298 +18231;Saint-Pierre-les-Étieux;711;17;728 +18232;Saint-Priest-la-Marche;229;3;232 +18233;Saint-Satur;1426;50;1476 +18234;Saint-Saturnin;422;8;430 +18236;Saint-Symphorien;134;1;135 +18238;Saint-Vitte;131;3;134 +18208;Sainte-Gemme-en-Sancerrois;427;7;434 +18227;Sainte-Montaine;181;4;185 +18235;Sainte-Solange;1135;19;1154 +18237;Sainte-Thorette;480;3;483 +18240;Sancergues;649;10;659 +18241;Sancerre;1393;39;1432 +18242;Sancoins;3080;44;3124 +18243;Santranges;410;8;418 +18244;Saugy;79;0;79 +18245;Saulzais-le-Potier;497;9;506 +18246;Savigny-en-Sancerre;1030;21;1051 +18247;Savigny-en-Septaine;712;14;726 +18248;Senneçay;472;6;478 +18249;Sens-Beaujeu;399;14;413 +18250;Serruelles;74;2;76 +18251;Sévry;62;2;64 +18252;Sidiailles;303;5;308 +18253;Soulangis;497;8;505 +18254;Soye-en-Septaine;583;15;598 +18255;Le Subdray;932;205;1137 +18256;Subligny;341;7;348 +18258;Sury-en-Vaux;703;17;720 +18259;Sury-ès-Bois;270;2;272 +18257;Sury-près-Léré;711;14;725 +18260;Tendron;93;2;95 +18261;Thaumiers;417;7;424 +18262;Thauvenay;332;8;340 +18263;Thénioux;664;9;673 +18264;Thou;76;2;78 +18265;Torteron;795;16;811 +18266;Touchay;262;10;272 +18267;Trouy;3959;116;4075 +18268;Uzay-le-Venon;401;9;410 +18269;Vailly-sur-Sauldre;654;21;675 +18270;Vallenay;741;12;753 +18271;Vasselay;1447;27;1474 +18272;Veaugues;633;22;655 +18273;Venesmes;821;16;837 +18274;Verdigny;309;3;312 +18275;Vereaux;140;7;147 +18276;Vernais;193;1;194 +18277;Verneuil;34;0;34 +18278;Vesdun;564;10;574 +18279;Vierzon;25903;538;26441 +18280;Vignoux-sous-les-Aix;719;22;741 +18281;Vignoux-sur-Barangeon;2119;37;2156 +18282;Villabon;577;10;587 +18283;Villecelin;94;0;94 +18284;Villegenon;218;7;225 +18285;Villeneuve-sur-Cher;444;6;450 +18286;Villequiers;479;9;488 +18287;Vinon;297;9;306 +18288;Vorly;232;7;239 +18289;Vornay;593;14;607 +18290;Vouzeron;566;10;576 +19001;Affieux;359;13;372 +19002;Aix;392;6;398 +19003;Albignac;254;2;256 +19004;Albussac;731;9;740 +19005;Allassac;3903;103;4006 +19006;Alleyrat;98;0;98 +19007;Altillac;861;31;892 +19008;Ambrugeat;205;4;209 +19009;Les Angles-sur-Corrèze;112;1;113 +19010;Argentat-sur-Dordogne;3016;120;3136 +19011;Arnac-Pompadour;1133;14;1147 +19012;Astaillac;232;6;238 +19013;Aubazines;914;16;930 +19014;Auriac;229;6;235 +19015;Ayen;714;7;721 +19016;Bar;308;8;316 +19017;Bassignac-le-Bas;91;1;92 +19018;Bassignac-le-Haut;179;5;184 +19019;Beaulieu-sur-Dordogne;1299;22;1321 +19020;Beaumont;114;7;121 +19021;Bellechassagne;89;4;93 +19022;Benayes;228;5;233 +19023;Beynat;1258;20;1278 +19024;Beyssac;615;24;639 +19025;Beyssenac;368;4;372 +19026;Bilhac;246;4;250 +19027;Bonnefond;113;0;113 +19028;Bort-les-Orgues;2677;103;2780 +19029;Branceilles;279;5;284 +19030;Brignac-la-Plaine;980;17;997 +19031;Brive-la-Gaillarde;46916;1286;48202 +19033;Bugeat;803;10;813 +19034;Camps-Saint-Mathurin-Léobazel;237;6;243 +19035;Chabrignac;572;20;592 +19036;Chamberet;1372;13;1385 +19037;Chamboulive;1209;31;1240 +19038;Chameyrat;1535;51;1586 +19039;Champagnac-la-Noaille;233;5;238 +19040;Champagnac-la-Prune;163;6;169 +19041;Chanac-les-Mines;485;20;505 +19042;Chanteix;610;13;623 +19043;La Chapelle-aux-Brocs;427;9;436 +19044;La Chapelle-aux-Saints;266;10;276 +19045;La Chapelle-Saint-Géraud;198;9;207 +19046;Chapelle-Spinasse;115;1;116 +19047;Chartrier-Ferrière;369;4;373 +19048;Le Chastang;365;11;376 +19049;Chasteaux;762;21;783 +19050;Chauffour-sur-Vell;419;9;428 +19051;Chaumeil;158;4;162 +19052;Chavanac;51;1;52 +19053;Chaveroche;233;4;237 +19054;Chenailler-Mascheix;208;6;214 +19055;Chirac-Bellevue;294;11;305 +19056;Clergoux;412;11;423 +19057;Collonges-la-Rouge;486;19;505 +19058;Combressol;346;16;362 +19059;Concèze;413;9;422 +19060;Condat-sur-Ganaveix;672;12;684 +19167;Confolent-Port-Dieu;40;0;40 +19061;Cornil;1340;12;1352 +19062;Corrèze;1128;46;1174 +19063;Cosnac;2981;78;3059 +19064;Couffy-sur-Sarsonne;76;2;78 +19065;Courteix;66;0;66 +19066;Cublac;1695;34;1729 +19067;Curemonte;209;10;219 +19068;Dampniat;727;6;733 +19069;Darazac;138;3;141 +19070;Darnets;361;8;369 +19071;Davignac;208;3;211 +19072;Donzenac;2651;64;2715 +19073;Égletons;4298;788;5086 +19074;L' Église-aux-Bois;55;0;55 +19075;Espagnac;377;8;385 +19076;Espartignac;441;7;448 +19077;Estivals;127;2;129 +19078;Estivaux;434;1;435 +19079;Eyburie;497;8;505 +19080;Eygurande;685;11;696 +19081;Eyrein;500;13;513 +19082;Favars;1072;23;1095 +19083;Feyt;132;2;134 +19084;Forgès;286;12;298 +19085;Gimel-les-Cascades;794;7;801 +19086;Goulles;332;6;338 +19087;Gourdon-Murat;108;4;112 +19088;Grandsaigne;52;1;53 +19089;Gros-Chastang;181;3;184 +19090;Gumond;95;6;101 +19091;Hautefage;313;13;326 +19092;Le Jardin;81;1;82 +19093;Jugeals-Nazareth;972;24;996 +19094;Juillac;1126;25;1151 +19095;Lacelle;137;1;138 +19096;Ladignac-sur-Rondelles;406;9;415 +19097;Lafage-sur-Sombre;124;1;125 +19098;Lagarde-Marc-la-Tour;978;18;996 +19099;Lagleygeolle;220;10;230 +19100;Lagraulière;1100;19;1119 +19101;Laguenne-sur-Avalouze;1548;38;1586 +19102;Lamazière-Basse;299;3;302 +19103;Lamazière-Haute;67;1;68 +19104;Lamongerie;117;2;119 +19105;Lanteuil;507;14;521 +19106;Lapleau;381;2;383 +19107;Larche;1583;44;1627 +19108;Laroche-près-Feyt;63;2;65 +19109;Lascaux;218;7;225 +19110;Latronche;134;0;134 +19111;Laval-sur-Luzège;99;0;99 +19112;Lestards;106;0;106 +19113;Liginiac;606;43;649 +19114;Lignareix;164;10;174 +19115;Ligneyrac;299;8;307 +19116;Liourdres;248;5;253 +19117;Lissac-sur-Couze;730;21;751 +19118;Le Lonzac;805;13;818 +19119;Lostanges;139;1;140 +19120;Louignac;236;1;237 +19121;Lubersac;2230;41;2271 +19122;Madranges;193;11;204 +19123;Malemort;7985;166;8151 +19124;Mansac;1427;23;1450 +19125;Marcillac-la-Croisille;794;16;810 +19126;Marcillac-la-Croze;178;1;179 +19128;Margerides;305;6;311 +19129;Masseret;676;9;685 +19130;Maussac;439;9;448 +19131;Meilhards;517;23;540 +19132;Ménoire;118;1;119 +19133;Mercœur;245;1;246 +19134;Merlines;718;20;738 +19135;Mestes;355;4;359 +19136;Meymac;2366;196;2562 +19137;Meyrignac-l'Église;62;0;62 +19138;Meyssac;1275;53;1328 +19139;Millevaches;81;1;82 +19140;Monceaux-sur-Dordogne;636;19;655 +19141;Monestier-Merlines;299;6;305 +19142;Monestier-Port-Dieu;103;2;105 +19143;Montaignac-Saint-Hippolyte;581;11;592 +19144;Montgibaud;239;5;244 +19145;Moustier-Ventadour;451;75;526 +19146;Naves;2320;230;2550 +19147;Nespouls;635;14;649 +19148;Neuvic;1648;254;1902 +19149;Neuville;189;5;194 +19150;Noailhac;378;6;384 +19151;Noailles;910;18;928 +19152;Nonards;447;8;455 +19153;Objat;3640;95;3735 +19154;Orgnac-sur-Vézère;313;5;318 +19155;Orliac-de-Bar;283;4;287 +19156;Palazinges;153;2;155 +19157;Palisse;225;2;227 +19158;Pandrignes;166;4;170 +19159;Péret-Bel-Air;91;2;93 +19160;Pérols-sur-Vézère;185;2;187 +19161;Perpezac-le-Blanc;468;6;474 +19162;Perpezac-le-Noir;1166;19;1185 +19163;Le Pescher;288;7;295 +19164;Peyrelevade;850;11;861 +19165;Peyrissac;127;3;130 +19166;Pierrefitte;91;0;91 +19168;Pradines;91;3;94 +19169;Puy-d'Arnac;288;4;292 +19170;Queyssac-les-Vignes;203;8;211 +19171;Reygade;189;4;193 +19172;Rilhac-Treignac;110;7;117 +19173;Rilhac-Xaintrie;300;6;306 +19174;La Roche-Canillac;142;4;146 +19175;Roche-le-Peyroux;96;0;96 +19176;Rosiers-d'Égletons;1070;39;1109 +19177;Rosiers-de-Juillac;181;4;185 +19178;Sadroc;937;16;953 +19179;Saillac;205;6;211 +19180;Saint-Angel;709;14;723 +19181;Saint-Augustin;423;7;430 +19182;Saint-Aulaire;779;23;802 +19184;Saint-Bazile-de-Meyssac;130;4;134 +19186;Saint-Bonnet-Elvert;207;5;212 +19188;Saint-Bonnet-l'Enfantier;400;5;405 +19187;Saint-Bonnet-la-Rivière;387;5;392 +19189;Saint-Bonnet-les-Tours-de-Merle;48;1;49 +19190;Saint-Bonnet-près-Bort;192;4;196 +19191;Saint-Cernin-de-Larche;648;12;660 +19192;Saint-Chamant;486;6;492 +19193;Saint-Cirgues-la-Loutre;176;5;181 +19194;Saint-Clément;1323;35;1358 +19195;Saint-Cyprien;384;6;390 +19196;Saint-Cyr-la-Roche;505;8;513 +19198;Saint-Éloy-les-Tuileries;102;0;102 +19199;Saint-Étienne-aux-Clos;229;3;232 +19200;Saint-Étienne-la-Geneste;93;7;100 +19201;Saint-Exupéry-les-Roches;596;12;608 +19204;Saint-Fréjoux;291;6;297 +19205;Saint-Geniez-ô-Merle;90;2;92 +19206;Saint-Germain-Lavolps;87;1;88 +19207;Saint-Germain-les-Vergnes;1114;31;1145 +19208;Saint-Hilaire-Foissac;188;3;191 +19209;Saint-Hilaire-les-Courbes;158;2;160 +19210;Saint-Hilaire-Luc;70;0;70 +19211;Saint-Hilaire-Peyroux;978;20;998 +19212;Saint-Hilaire-Taurieux;103;6;109 +19213;Saint-Jal;629;17;646 +19214;Saint-Julien-aux-Bois;466;8;474 +19215;Saint-Julien-le-Pèlerin;129;3;132 +19216;Saint-Julien-le-Vendômois;249;3;252 +19217;Saint-Julien-Maumont;157;4;161 +19220;Saint-Martial-de-Gimel;487;7;494 +19221;Saint-Martial-Entraygues;84;2;86 +19222;Saint-Martin-la-Méanne;340;12;352 +19223;Saint-Martin-Sepert;274;2;276 +19225;Saint-Merd-de-Lapleau;174;2;176 +19226;Saint-Merd-les-Oussines;129;3;132 +19227;Saint-Mexant;1307;33;1340 +19228;Saint-Pantaléon-de-Lapleau;67;1;68 +19229;Saint-Pantaléon-de-Larche;4777;91;4868 +19230;Saint-Pardoux-Corbier;418;3;421 +19234;Saint-Pardoux-l'Ortigier;480;7;487 +19231;Saint-Pardoux-la-Croisille;177;2;179 +19232;Saint-Pardoux-le-Neuf;76;3;79 +19233;Saint-Pardoux-le-Vieux;297;12;309 +19235;Saint-Paul;221;6;227 +19236;Saint-Priest-de-Gimel;495;4;499 +19237;Saint-Privat;1075;21;1096 +19238;Saint-Rémy;227;6;233 +19239;Saint-Robert;301;8;309 +19240;Saint-Salvadour;300;12;312 +19241;Saint-Setiers;285;5;290 +19242;Saint-Solve;460;17;477 +19243;Saint-Sornin-Lavolps;858;17;875 +19244;Saint-Sulpice-les-Bois;84;0;84 +19245;Saint-Sylvain;135;5;140 +19246;Saint-Viance;1853;42;1895 +19247;Saint-Victour;186;9;195 +19248;Saint-Ybard;685;13;698 +19249;Saint-Yrieix-le-Déjalat;344;8;352 +19202;Sainte-Féréole;1941;40;1981 +19203;Sainte-Fortunade;1784;91;1875 +19219;Sainte-Marie-Lapanouze;59;1;60 +19250;Salon-la-Tour;658;5;663 +19251;Sarran;275;7;282 +19252;Sarroux - Saint Julien;851;17;868 +19253;Segonzac;222;2;224 +19254;Ségur-le-Château;174;4;178 +19255;Seilhac;1737;32;1769 +19256;Sérandon;349;5;354 +19257;Sérilhac;268;7;275 +19258;Servières-le-Château;613;9;622 +19259;Sexcles;234;5;239 +19260;Sioniac;220;6;226 +19261;Sornac;759;15;774 +19262;Soudaine-Lavinadière;176;18;194 +19263;Soudeilles;301;11;312 +19264;Soursac;505;3;508 +19265;Tarnac;339;8;347 +19266;Thalamy;97;4;101 +19268;Toy-Viam;37;0;37 +19269;Treignac;1361;67;1428 +19270;Troche;557;8;565 +19271;Tudeils;245;3;248 +19272;Tulle;14836;628;15464 +19273;Turenne;838;21;859 +19274;Ussac;4178;116;4294 +19275;Ussel;9736;388;10124 +19276;Uzerche;2806;64;2870 +19277;Valiergues;144;5;149 +19278;Varetz;2425;42;2467 +19279;Vars-sur-Roseix;374;6;380 +19280;Végennes;181;4;185 +19281;Veix;67;8;75 +19283;Veyrières;73;1;74 +19284;Viam;93;3;96 +19285;Vigeois;1195;27;1222 +19286;Vignols;550;9;559 +19287;Vitrac-sur-Montane;267;6;273 +19288;Voutezac;1259;151;1410 +19289;Yssandon;682;7;689 +2A001;Afa;3133;65;3198 +2A004;Ajaccio;70659;849;71508 +2A006;Alata;3244;85;3329 +2A008;Albitreccia;1705;25;1730 +2A011;Altagène;49;2;51 +2A014;Ambiegna;68;1;69 +2A017;Appietto;1825;40;1865 +2A018;Arbellara;156;2;158 +2A019;Arbori;54;0;54 +2A021;Argiusta-Moriccio;76;2;78 +2A022;Arro;83;1;84 +2A024;Aullène;187;2;189 +2A026;Azilone-Ampaza;184;3;187 +2A027;Azzana;54;0;54 +2A028;Balogna;137;5;142 +2A031;Bastelica;533;7;540 +2A032;Bastelicaccia;3983;108;4091 +2A035;Belvédère-Campomoro;165;2;167 +2A038;Bilia;46;5;51 +2A040;Bocognano;396;6;402 +2A041;Bonifacio;3118;55;3173 +2A048;Calcatoggio;523;3;526 +2A056;Campo;110;4;114 +2A060;Cannelle;65;1;66 +2A061;Carbini;103;2;105 +2A062;Carbuccia;393;10;403 +2A064;Cardo-Torgia;32;2;34 +2A065;Cargèse;1325;25;1350 +2A066;Cargiaca;55;0;55 +2A070;Casaglione;398;7;405 +2A071;Casalabriva;213;3;216 +2A085;Cauro;1444;37;1481 +2A089;Ciamannacce;133;2;135 +2A090;Coggia;695;16;711 +2A091;Cognocoli-Monticchi;169;0;169 +2A092;Conca;1100;21;1121 +2A094;Corrano;72;3;75 +2A098;Coti-Chiavari;728;8;736 +2A099;Cozzano;273;0;273 +2A100;Cristinacce;63;0;63 +2A103;Cuttoli-Corticchiato;2009;34;2043 +2A104;Eccica-Suarella;1179;45;1224 +2A108;Évisa;219;7;226 +2A114;Figari;1446;29;1475 +2A115;Foce;152;7;159 +2A117;Forciolo;81;0;81 +2A118;Fozzano;209;5;214 +2A119;Frasseto;122;4;126 +2A127;Giuncheto;86;2;88 +2A128;Granace;90;0;90 +2A129;Grossa;43;1;44 +2A130;Grosseto-Prugna;3124;53;3177 +2A131;Guagno;165;1;166 +2A132;Guargualé;145;1;146 +2A133;Guitera-les-Bains;148;5;153 +2A139;Lecci;1735;11;1746 +2A141;Letia;121;1;122 +2A142;Levie;687;14;701 +2A144;Lopigna;103;2;105 +2A146;Loreto-di-Tallano;53;0;53 +2A154;Marignana;110;3;113 +2A158;Mela;29;1;30 +2A160;Moca-Croce;252;4;256 +2A163;Monacia-d'Aullène;528;8;536 +2A174;Murzo;97;3;100 +2A181;Ocana;605;16;621 +2A186;Olivese;226;1;227 +2A189;Olmeto;1216;29;1245 +2A191;Olmiccia;122;3;125 +2A196;Orto;55;1;56 +2A197;Osani;97;1;98 +2A198;Ota;528;11;539 +2A200;Palneca;161;2;163 +2A203;Partinello;102;1;103 +2A204;Pastricciola;97;1;98 +2A209;Peri;1999;35;2034 +2A211;Petreto-Bicchisano;564;17;581 +2A212;Piana;482;4;486 +2A215;Pianottoli-Caldarello;912;7;919 +2A228;Pietrosella;1685;16;1701 +2A232;Pila-Canale;284;4;288 +2A240;Poggiolo;111;2;113 +2A247;Porto-Vecchio;12042;229;12271 +2A249;Propriano;3747;40;3787 +2A253;Quasquara;51;0;51 +2A254;Quenza;190;5;195 +2A258;Renno;59;3;62 +2A259;Rezza;54;1;55 +2A262;Rosazia;49;3;52 +2A308;Sainte-Lucie-de-Tallano;424;10;434 +2A266;Salice;91;4;95 +2A268;Sampolo;80;0;80 +2A300;San-Gavino-di-Carbini;1110;21;1131 +2A295;Sant'Andréa-d'Orcino;110;0;110 +2A310;Santa-Maria-Figaniella;100;0;100 +2A312;Santa-Maria-Siché;439;9;448 +2A270;Sari-d'Orcino;329;5;334 +2A269;Sari-Solenzara;1345;30;1375 +2A271;Sarrola-Carcopino;3267;62;3329 +2A272;Sartène;3259;132;3391 +2A276;Serra-di-Ferro;482;11;493 +2A278;Serra-di-Scopamène;89;2;91 +2A279;Serriera;127;0;127 +2A282;Soccia;146;4;150 +2A284;Sollacaro;363;5;368 +2A285;Sorbollano;78;0;78 +2A288;Sotta;1371;23;1394 +2A322;Tasso;110;0;110 +2A323;Tavaco;369;8;377 +2A324;Tavera;401;5;406 +2A326;Tolla;125;0;125 +2A330;Ucciani;501;4;505 +2A331;Urbalacone;65;0;65 +2A336;Valle-di-Mezzana;444;9;453 +2A345;Vero;579;3;582 +2A348;Vico;912;14;926 +2A349;Viggianello;814;17;831 +2A351;Villanova;362;10;372 +2A357;Zérubia;43;3;46 +2A358;Zévaco;59;2;61 +2A359;Zicavo;229;2;231 +2A360;Zigliara;130;7;137 +2A362;Zonza;2722;35;2757 +2A363;Zoza;54;0;54 +2B002;Aghione;241;4;245 +2B003;Aiti;30;0;30 +2B005;Alando;35;2;37 +2B007;Albertacce;200;1;201 +2B009;Aléria;2162;25;2187 +2B010;Algajola;358;7;365 +2B012;Altiani;48;0;48 +2B013;Alzi;26;0;26 +2B015;Ampriani;24;0;24 +2B016;Antisanti;546;0;546 +2B020;Aregno;598;16;614 +2B023;Asco;119;2;121 +2B025;Avapessa;82;3;85 +2B029;Barbaggio;303;3;306 +2B030;Barrettali;133;4;137 +2B033;Bastia;45715;719;46434 +2B034;Belgodère;623;9;632 +2B036;Bigorno;90;0;90 +2B037;Biguglia;7923;127;8050 +2B039;Bisinchi;220;2;222 +2B042;Borgo;8760;140;8900 +2B043;Brando;1630;40;1670 +2B045;Bustanico;64;1;65 +2B046;Cagnano;169;3;172 +2B047;Calacuccia;280;6;286 +2B049;Calenzana;2342;30;2372 +2B050;Calvi;5559;79;5638 +2B051;Cambia;80;0;80 +2B052;Campana;18;0;18 +2B053;Campi;20;2;22 +2B054;Campile;195;2;197 +2B055;Campitello;119;1;120 +2B057;Canale-di-Verde;321;10;331 +2B058;Canari;312;1;313 +2B059;Canavaggia;103;1;104 +2B063;Carcheto-Brustico;31;1;32 +2B067;Carpineto;33;0;33 +2B068;Carticasi;27;0;27 +2B069;Casabianca;84;2;86 +2B072;Casalta;53;0;53 +2B073;Casamaccioli;106;0;106 +2B074;Casanova;391;6;397 +2B075;Casevecchie;67;2;69 +2B077;Castellare-di-Casinca;666;6;672 +2B078;Castellare-di-Mercurio;31;1;32 +2B079;Castello-di-Rostino;471;5;476 +2B080;Castifao;152;1;153 +2B081;Castiglione;42;0;42 +2B082;Castineta;41;1;42 +2B083;Castirla;168;2;170 +2B084;Cateri;215;6;221 +2B086;Centuri;210;1;211 +2B087;Cervione;2189;26;2215 +2B088;Chiatra;222;5;227 +2B366;Chisa;100;2;102 +2B093;Corbara;907;32;939 +2B095;Corscia;129;3;132 +2B096;Corte;7446;117;7563 +2B097;Costa;62;1;63 +2B101;Croce;75;3;78 +2B102;Crocicchia;70;0;70 +2B105;Erbajolo;110;0;110 +2B106;Érone;11;0;11 +2B107;Ersa;154;1;155 +2B109;Farinole;228;1;229 +2B110;Favalello;76;3;79 +2B111;Felce;51;0;51 +2B112;Feliceto;225;4;229 +2B113;Ficaja;53;1;54 +2B116;Focicchia;26;1;27 +2B120;Furiani;5628;126;5754 +2B121;Galéria;338;9;347 +2B122;Gavignano;53;0;53 +2B123;Ghisonaccia;4225;66;4291 +2B124;Ghisoni;212;6;218 +2B125;Giocatojo;49;0;49 +2B126;Giuncaggio;62;0;62 +2B134;L' Île-Rousse;3043;78;3121 +2B135;Isolaccio-di-Fiumorbo;311;2;313 +2B136;Lama;151;2;153 +2B137;Lano;25;0;25 +2B138;Lavatoggio;150;3;153 +2B140;Lento;103;0;103 +2B143;Linguizzetta;1107;9;1116 +2B145;Loreto-di-Casinca;212;6;218 +2B147;Lozzi;118;2;120 +2B148;Lucciana;5780;49;5829 +2B149;Lugo-di-Nazza;78;3;81 +2B150;Lumio;1180;35;1215 +2B152;Luri;835;9;844 +2B153;Manso;114;2;116 +2B155;Matra;44;0;44 +2B156;Mausoléo;17;0;17 +2B157;Mazzola;28;0;28 +2B159;Meria;98;1;99 +2B161;Moïta;75;0;75 +2B162;Moltifao;682;11;693 +2B164;Monacia-d'Orezza;25;0;25 +2B165;Moncale;321;8;329 +2B166;Monte;607;5;612 +2B167;Montegrosso;426;5;431 +2B168;Monticello;1923;46;1969 +2B169;Morosaglia;1043;9;1052 +2B170;Morsiglia;119;2;121 +2B171;Muracciole;34;1;35 +2B172;Murato;600;15;615 +2B173;Muro;238;4;242 +2B175;Nessa;109;2;111 +2B176;Nocario;66;3;69 +2B177;Noceta;62;2;64 +2B178;Nonza;74;2;76 +2B179;Novale;62;0;62 +2B180;Novella;83;2;85 +2B182;Occhiatana;246;1;247 +2B183;Ogliastro;99;2;101 +2B184;Olcani;82;1;83 +2B185;Oletta;1696;13;1709 +2B187;Olmeta-di-Capocorso;142;1;143 +2B188;Olmeta-di-Tuda;488;9;497 +2B190;Olmi-Cappella;180;7;187 +2B192;Olmo;160;1;161 +2B193;Omessa;587;4;591 +2B194;Ortale;25;1;26 +2B195;Ortiporio;127;1;128 +2B199;Palasca;170;4;174 +2B201;Pancheraccia;187;3;190 +2B202;Parata;24;0;24 +2B205;Patrimonio;807;11;818 +2B206;Penta-Acquatella;34;0;34 +2B207;Penta-di-Casinca;3396;40;3436 +2B208;Perelli;110;0;110 +2B210;Pero-Casevecchie;123;1;124 +2B213;Pianello;70;0;70 +2B214;Piano;28;1;29 +2B216;Piazzali;17;0;17 +2B217;Piazzole;41;3;44 +2B222;Pie-d'Orezza;37;0;37 +2B218;Piedicorte-di-Gaggio;97;3;100 +2B219;Piedicroce;100;1;101 +2B220;Piedigriggio;138;2;140 +2B221;Piedipartino;17;0;17 +2B225;Pietra-di-Verde;102;6;108 +2B224;Pietracorbara;652;11;663 +2B223;Pietralba;504;3;507 +2B226;Pietraserena;72;1;73 +2B227;Pietricaggio;35;1;36 +2B229;Pietroso;289;0;289 +2B230;Piève;109;5;114 +2B231;Pigna;95;6;101 +2B233;Pino;164;2;166 +2B234;Piobetta;20;0;20 +2B235;Pioggiola;88;2;90 +2B239;Poggio-d'Oletta;213;6;219 +2B236;Poggio-di-Nazza;176;2;178 +2B238;Poggio-di-Venaco;214;2;216 +2B241;Poggio-Marinaccio;30;1;31 +2B242;Poggio-Mezzana;680;13;693 +2B243;Polveroso;42;0;42 +2B244;Popolasca;45;1;46 +2B245;Porri;43;1;44 +2B246;La Porta;193;1;194 +2B248;Prato-di-Giovellina;42;1;43 +2B250;Prunelli-di-Casacconi;150;0;150 +2B251;Prunelli-di-Fiumorbo;3660;40;3700 +2B252;Pruno;175;2;177 +2B255;Quercitello;44;0;44 +2B256;Rapaggio;25;0;25 +2B257;Rapale;151;0;151 +2B260;Riventosa;157;3;160 +2B261;Rogliano;563;11;574 +2B263;Rospigliani;71;5;76 +2B264;Rusio;71;1;72 +2B265;Rutali;377;6;383 +2B298;Saint-Florent;1655;36;1691 +2B267;Saliceto;50;3;53 +2B297;San-Damiano;58;0;58 +2B299;San-Gavino-d'Ampugnani;107;1;108 +2B365;San-Gavino-di-Fiumorbo;121;2;123 +2B301;San-Gavino-di-Tenda;66;1;67 +2B302;San-Giovanni-di-Moriani;94;2;96 +2B303;San-Giuliano;726;6;732 +2B304;San-Lorenzo;143;0;143 +2B305;San-Martino-di-Lota;2901;42;2943 +2B313;San-Nicolao;1987;22;2009 +2B292;Sant'Andréa-di-Bozio;72;2;74 +2B293;Sant'Andréa-di-Cotone;229;2;231 +2B296;Sant'Antonino;127;5;132 +2B306;Santa-Lucia-di-Mercurio;111;0;111 +2B307;Santa-Lucia-di-Moriani;1428;14;1442 +2B309;Santa-Maria-di-Lota;1722;53;1775 +2B311;Santa-Maria-Poggio;743;11;754 +2B316;Santa-Reparata-di-Balagna;1012;20;1032 +2B317;Santa-Reparata-di-Moriani;54;0;54 +2B314;Santo-Pietro-di-Tenda;361;4;365 +2B315;Santo-Pietro-di-Venaco;277;5;282 +2B273;Scata;46;5;51 +2B274;Scolca;101;1;102 +2B275;Sermano;63;2;65 +2B277;Serra-di-Fiumorbo;335;3;338 +2B280;Silvareccio;131;0;131 +2B281;Sisco;1169;9;1178 +2B283;Solaro;706;13;719 +2B286;Sorbo-Ocagnano;832;8;840 +2B287;Sorio;142;0;142 +2B289;Soveria;117;0;117 +2B290;Speloncato;276;4;280 +2B291;Stazzona;39;1;40 +2B318;Taglio-Isolaccio;572;12;584 +2B319;Talasani;772;7;779 +2B320;Tallone;315;2;317 +2B321;Tarrano;16;0;16 +2B327;Tomino;208;3;211 +2B328;Tox;96;0;96 +2B329;Tralonca;110;1;111 +2B332;Urtaca;230;3;233 +2B334;Valle-d'Alesani;109;1;110 +2B338;Valle-d'Orezza;43;0;43 +2B335;Valle-di-Campoloro;344;7;351 +2B337;Valle-di-Rostino;132;0;132 +2B333;Vallecalle;137;3;140 +2B339;Vallica;26;0;26 +2B340;Velone-Orneto;117;0;117 +2B341;Venaco;711;17;728 +2B342;Ventiseri;2481;46;2527 +2B343;Venzolasca;1796;14;1810 +2B344;Verdèse;37;2;39 +2B346;Vescovato;2836;31;2867 +2B347;Vezzani;265;1;266 +2B350;Vignale;160;1;161 +2B352;Ville-di-Paraso;213;4;217 +2B353;Ville-di-Pietrabugno;3323;85;3408 +2B354;Vivario;432;4;436 +2B355;Volpajola;390;7;397 +2B356;Zalana;141;1;142 +2B361;Zilia;286;5;291 +2B364;Zuani;30;0;30 +21001;Agencourt;460;53;513 +21002;Agey;278;3;281 +21003;Ahuy;1210;24;1234 +21004;Aignay-le-Duc;282;7;289 +21005;Aiserey;1400;13;1413 +21006;Aisey-sur-Seine;176;1;177 +21007;Aisy-sous-Thil;224;30;254 +21008;Alise-Sainte-Reine;579;7;586 +21009;Allerey;170;2;172 +21010;Aloxe-Corton;134;5;139 +21012;Ampilly-le-Sec;348;12;360 +21011;Ampilly-les-Bordes;84;0;84 +21013;Ancey;442;7;449 +21014;Antheuil;60;2;62 +21015;Antigny-la-Ville;102;0;102 +21021;Arc-sur-Tille;2670;59;2729 +21016;Arceau;897;17;914 +21017;Arcenant;507;19;526 +21018;Arcey;53;1;54 +21020;Arconcey;222;8;230 +21022;Argilly;513;12;525 +21023;Arnay-le-Duc;1425;39;1464 +21024;Arnay-sous-Vitteaux;111;0;111 +21025;Arrans;73;2;75 +21026;Asnières-en-Montagne;191;9;200 +21027;Asnières-lès-Dijon;1184;25;1209 +21028;Athée;781;10;791 +21029;Athie;75;1;76 +21030;Aubaine;95;3;98 +21031;Aubigny-en-Plaine;507;5;512 +21032;Aubigny-la-Ronce;167;4;171 +21033;Aubigny-lès-Sombernon;150;5;155 +21034;Autricourt;127;2;129 +21035;Auvillars-sur-Saône;331;5;336 +21036;Auxant;74;4;78 +21037;Auxey-Duresses;304;13;317 +21038;Auxonne;7622;86;7708 +21039;Avelanges;35;0;35 +21040;Avosnes;89;5;94 +21041;Avot;187;2;189 +21042;Bagnot;161;4;165 +21043;Baigneux-les-Juifs;242;46;288 +21044;Balot;90;1;91 +21045;Barbirey-sur-Ouche;216;9;225 +21046;Bard-le-Régulier;72;2;74 +21047;Bard-lès-Époisses;70;2;72 +21048;Barges;621;10;631 +21049;Barjon;41;2;43 +21050;Baubigny;202;6;208 +21051;Baulme-la-Roche;90;3;93 +21052;Beaulieu;27;4;31 +21053;Beaumont-sur-Vingeanne;199;4;203 +21054;Beaune;21031;716;21747 +21055;Beaunotte;19;0;19 +21056;Beire-le-Châtel;860;10;870 +21057;Beire-le-Fort;346;5;351 +21058;Belan-sur-Ource;252;5;257 +21059;Bellefond;866;17;883 +21060;Belleneuve;1618;17;1635 +21061;Bellenod-sur-Seine;76;2;78 +21062;Bellenot-sous-Pouilly;224;9;233 +21063;Beneuvre;91;5;96 +21064;Benoisey;109;0;109 +21065;Bessey-en-Chaume;145;5;150 +21066;Bessey-la-Cour;57;1;58 +21067;Bessey-lès-Cîteaux;696;7;703 +21068;Beurey-Bauguay;110;7;117 +21069;Beurizot;121;1;122 +21070;Bévy;139;4;143 +21071;Bèze;714;21;735 +21072;Bézouotte;202;3;205 +21074;Billey;264;4;268 +21075;Billy-lès-Chanceaux;61;1;62 +21076;Binges;790;11;801 +21077;Bissey-la-Côte;124;2;126 +21078;Bissey-la-Pierre;74;2;76 +21079;Blagny-sur-Vingeanne;132;0;132 +21080;Blaisy-Bas;669;11;680 +21081;Blaisy-Haut;131;1;132 +21082;Blancey;75;0;75 +21083;Blanot;127;1;128 +21085;Bligny-le-Sec;148;3;151 +21086;Bligny-lès-Beaune;1238;30;1268 +21087;Bligny-sur-Ouche;831;11;842 +21088;Boncourt-le-Bois;283;7;290 +21089;Bonnencontre;445;6;451 +21090;Boudreville;66;3;69 +21091;Bouhey;38;1;39 +21092;Bouilland;210;9;219 +21093;Bouix;156;4;160 +21094;Bourberain;394;4;398 +21095;Bousselange;51;2;53 +21096;Boussenois;118;1;119 +21097;Boussey;35;2;37 +21098;Boux-sous-Salmaise;125;4;129 +21099;Bouze-lès-Beaune;314;7;321 +21100;Brain;35;0;35 +21101;Braux;168;4;172 +21102;Brazey-en-Morvan;139;3;142 +21103;Brazey-en-Plaine;2379;43;2422 +21104;Brémur-et-Vaurois;49;3;52 +21105;Bressey-sur-Tille;1113;8;1121 +21106;Bretenière;913;13;926 +21107;Bretigny;904;24;928 +21108;Brianny;121;1;122 +21109;Brion-sur-Ource;238;7;245 +21110;Brochon;645;131;776 +21111;Brognon;307;3;310 +21112;Broin;429;10;439 +21113;Broindon;207;2;209 +21114;Buffon;176;1;177 +21115;Buncey;378;7;385 +21116;Bure-les-Templiers;134;0;134 +21117;Busseaut;48;2;50 +21118;Busserotte-et-Montenaille;24;4;28 +21120;La Bussière-sur-Ouche;159;2;161 +21119;Bussières;41;0;41 +21121;Bussy-la-Pesle;77;1;78 +21122;Bussy-le-Grand;316;8;324 +21123;Buxerolles;31;5;36 +21124;Censerey;171;2;173 +21125;Cérilly;231;8;239 +21126;Cessey-sur-Tille;622;7;629 +21127;Chaignay;517;8;525 +21128;Chailly-sur-Armançon;244;11;255 +21129;Chambain;27;0;27 +21130;Chambeire;386;4;390 +21131;Chamblanc;459;69;528 +21133;Chambolle-Musigny;295;7;302 +21132;Chambœuf;382;6;388 +21134;Chamesson;268;10;278 +21137;Champ-d'Oiseau;90;1;91 +21135;Champagne-sur-Vingeanne;315;1;316 +21136;Champagny;27;0;27 +21138;Champdôtre;606;8;614 +21139;Champeau-en-Morvan;228;5;233 +21140;Champignolles;76;1;77 +21141;Champrenault;34;1;35 +21142;Chanceaux;218;4;222 +21143;Channay;64;3;67 +21144;Charencey;33;0;33 +21145;Charigny;34;1;35 +21146;Charmes;135;3;138 +21147;Charny;34;0;34 +21148;Charrey-sur-Saône;351;1;352 +21149;Charrey-sur-Seine;145;8;153 +21150;Chassagne-Montrachet;305;11;316 +21151;Chassey;88;5;93 +21152;Châteauneuf;85;3;88 +21153;Châtellenot;151;6;157 +21154;Châtillon-sur-Seine;5373;349;5722 +21155;Chaudenay-la-Ville;44;7;51 +21156;Chaudenay-le-Château;49;0;49 +21157;Chaugey;17;0;17 +21159;La Chaume;102;2;104 +21158;Chaume-et-Courchamp;180;5;185 +21160;Chaume-lès-Baigneux;93;1;94 +21161;Chaumont-le-Bois;81;5;86 +21162;Chaux;485;9;494 +21163;Chazeuil;197;5;202 +21164;Chazilly;139;3;142 +21165;Chemin-d'Aisey;71;4;75 +21166;Chenôve;13910;196;14106 +21167;Cheuge;126;4;130 +21168;Chevannay;45;1;46 +21169;Chevannes;160;4;164 +21170;Chevigny-en-Valière;358;4;362 +21171;Chevigny-Saint-Sauveur;11326;213;11539 +21172;Chivres;299;5;304 +21173;Chorey-les-Beaune;633;17;650 +21175;Cirey-lès-Pontailler;206;2;208 +21176;Civry-en-Montagne;129;2;131 +21177;Clamerey;184;1;185 +21179;Clénay;855;10;865 +21180;Cléry;142;3;145 +21181;Clomot;137;2;139 +21182;Collonges-lès-Bévy;94;1;95 +21183;Collonges-lès-Premières;896;19;915 +21184;Colombier;64;0;64 +21185;Combertault;553;21;574 +21186;Comblanchien;637;17;654 +21187;Commarin;123;4;127 +21189;Corberon;449;7;456 +21190;Corcelles-les-Arts;462;18;480 +21191;Corcelles-lès-Cîteaux;811;14;825 +21192;Corcelles-les-Monts;640;10;650 +21193;Corgengoux;368;16;384 +21194;Corgoloin;906;12;918 +21195;Cormot-Vauchignon;210;4;214 +21196;Corpeau;968;15;983 +21197;Corpoyer-la-Chapelle;29;0;29 +21198;Corrombles;246;3;249 +21199;Corsaint;160;2;162 +21200;Couchey;1130;24;1154 +21201;Coulmier-le-Sec;260;6;266 +21202;Courban;168;1;169 +21203;Courcelles-Frémoy;124;2;126 +21204;Courcelles-lès-Montbard;80;1;81 +21205;Courcelles-lès-Semur;245;6;251 +21207;Courlon;81;4;85 +21208;Courtivron;168;3;171 +21209;Couternon;1889;39;1928 +21210;Créancey;528;6;534 +21211;Crécey-sur-Tille;142;2;144 +21212;Crépand;324;4;328 +21213;Crimolois;807;11;818 +21214;Crugey;175;5;180 +21215;Cuiserey;182;1;183 +21216;Culètre;99;2;101 +21217;Curley;135;4;139 +21218;Curtil-Saint-Seine;117;0;117 +21219;Curtil-Vergy;136;0;136 +21220;Cussey-les-Forges;138;3;141 +21221;Cussy-la-Colonne;42;2;44 +21222;Cussy-le-Châtel;109;3;112 +21223;Daix;1471;34;1505 +21224;Dampierre-en-Montagne;73;4;77 +21225;Dampierre-et-Flée;135;2;137 +21226;Darcey;338;11;349 +21227;Darois;493;7;500 +21228;Détain-et-Bruant;141;0;141 +21229;Diancey;84;4;88 +21230;Diénay;376;4;380 +21231;Dijon;156920;3284;160204 +21232;Dompierre-en-Morvan;211;5;216 +21233;Drambon;186;1;187 +21234;Drée;59;3;62 +21235;Duesme;53;1;54 +21236;Ébaty;256;8;264 +21237;Échalot;95;3;98 +21238;Échannay;128;2;130 +21239;Échenon;775;11;786 +21240;Échevannes;299;2;301 +21241;Échevronne;284;13;297 +21242;Échigey;288;3;291 +21243;Écutigny;79;5;84 +21244;Éguilly;62;0;62 +21245;Épagny;313;3;316 +21246;Épernay-sous-Gevrey;183;3;186 +21247;Époisses;796;14;810 +21248;Éringes;68;0;68 +21249;Esbarres;690;20;710 +21250;Essarois;91;2;93 +21251;Essey;275;27;302 +21252;Étais;85;2;87 +21253;Étalante;156;5;161 +21254;L' Étang-Vergy;213;12;225 +21255;Étaules;300;3;303 +21256;Étevaux;315;7;322 +21257;Étormay;67;5;72 +21258;Étrochey;226;3;229 +21259;Fain-lès-Montbard;300;6;306 +21260;Fain-lès-Moutiers;155;0;155 +21261;Fauverney;625;27;652 +21262;Faverolles-lès-Lucey;31;0;31 +21263;Fénay;1616;43;1659 +21264;Le Fête;48;0;48 +21265;Fixin;754;21;775 +21266;Flacey;185;1;186 +21267;Flagey-Echézeaux;473;13;486 +21268;Flagey-lès-Auxonne;194;3;197 +21269;Flammerans;428;9;437 +21270;Flavignerot;184;6;190 +21271;Flavigny-sur-Ozerain;302;7;309 +21273;Fleurey-sur-Ouche;1326;24;1350 +21274;Foissy;165;3;168 +21275;Foncegrive;135;3;138 +21277;Fontaine-Française;893;19;912 +21278;Fontaine-lès-Dijon;8888;184;9072 +21276;Fontaines-en-Duesmois;120;4;124 +21279;Fontaines-les-Sèches;26;1;27 +21280;Fontangy;139;6;145 +21281;Fontenelle;165;2;167 +21282;Forléans;103;2;105 +21283;Fraignot-et-Vesvrotte;62;1;63 +21284;Francheville;285;4;289 +21285;Franxault;476;6;482 +21286;Frénois;85;2;87 +21287;Fresnes;168;5;173 +21288;Frôlois;167;1;168 +21289;Fussey;118;7;125 +21290;Gemeaux;872;11;883 +21291;Genay;374;10;384 +21292;Genlis;5315;71;5386 +21293;Gergueil;117;0;117 +21294;Gerland;431;5;436 +21295;Gevrey-Chambertin;3087;40;3127 +21296;Gevrolles;178;1;179 +21297;Gilly-lès-Cîteaux;705;6;711 +21298;Gissey-le-Vieil;113;3;116 +21299;Gissey-sous-Flavigny;88;1;89 +21300;Gissey-sur-Ouche;354;9;363 +21301;Glanon;248;2;250 +21302;Gomméville;133;2;135 +21303;Les Goulles;12;0;12 +21304;Grancey-le-Château-Neuvelle;252;9;261 +21305;Grancey-sur-Ource;200;1;201 +21306;Grenant-lès-Sombernon;212;3;215 +21307;Grésigny-Sainte-Reine;142;2;144 +21308;Grignon;207;12;219 +21309;Griselles;89;3;92 +21310;Grosbois-en-Montagne;108;2;110 +21311;Grosbois-lès-Tichey;77;1;78 +21312;Gurgy-la-Ville;33;4;37 +21313;Gurgy-le-Château;44;0;44 +21314;Hauteroche;80;2;82 +21315;Hauteville-lès-Dijon;1219;16;1235 +21316;Heuilley-sur-Saône;333;5;338 +21317;Is-sur-Tille;4402;56;4458 +21319;Izeure;869;14;883 +21320;Izier;794;14;808 +21321;Jailly-les-Moulins;82;2;84 +21322;Jallanges;323;14;337 +21323;Jancigny;141;3;144 +21324;Jeux-lès-Bard;52;1;53 +21325;Jouey;185;2;187 +21326;Jours-lès-Baigneux;76;4;80 +21328;Juillenay;43;3;46 +21329;Juilly;47;3;50 +21330;Labergement-Foigney;368;12;380 +21331;Labergement-lès-Auxonne;328;3;331 +21332;Labergement-lès-Seurre;995;22;1017 +21333;Labruyère;227;5;232 +21334;Lacanche;561;10;571 +21335;Lacour-d'Arcenay;122;3;125 +21606;Ladoix-Serrigny;1834;31;1865 +21336;Laignes;692;20;712 +21337;Lamarche-sur-Saône;1341;13;1354 +21338;Lamargelle;158;3;161 +21339;Lantenay;510;16;526 +21340;Lanthes;264;4;268 +21341;Lantilly;109;3;112 +21342;Laperrière-sur-Saône;436;9;445 +21343;Larrey;92;2;94 +21344;Lechâtelet;225;5;230 +21345;Léry;196;3;199 +21346;Leuglay;306;3;309 +21347;Levernois;327;18;345 +21348;Licey-sur-Vingeanne;104;1;105 +21349;Liernais;514;27;541 +21350;Lignerolles;50;1;51 +21351;Longchamp;1168;121;1289 +21352;Longeault-Pluvault;1126;17;1143 +21353;Longecourt-en-Plaine;1228;25;1253 +21354;Longecourt-lès-Culêtre;50;2;52 +21355;Longvic;8604;135;8739 +21356;Losne;1606;36;1642 +21357;Louesme;106;3;109 +21358;Lucenay-le-Duc;187;3;190 +21359;Lucey;60;1;61 +21360;Lusigny-sur-Ouche;111;0;111 +21361;Lux;524;11;535 +21362;Maconge;132;3;135 +21363;Magnien;315;6;321 +21365;Magny-la-Ville;80;0;80 +21364;Magny-Lambert;86;6;92 +21366;Magny-lès-Aubigny;207;3;210 +21368;Magny-lès-Villers;243;12;255 +21367;Magny-Montarlot;265;2;267 +21369;Magny-Saint-Médard;311;4;315 +21370;Magny-sur-Tille;868;17;885 +21371;Les Maillys;820;19;839 +21372;Maisey-le-Duc;85;5;90 +21373;Mâlain;747;15;762 +21374;Maligny;212;7;219 +21375;Manlay;170;3;173 +21376;Marandeuil;113;1;114 +21377;Marcellois;49;0;49 +21378;Marcenay;98;2;100 +21379;Marcheseuil;156;1;157 +21380;Marcigny-sous-Thil;61;2;63 +21381;Marcilly-et-Dracy;99;4;103 +21382;Marcilly-Ogny;195;3;198 +21383;Marcilly-sur-Tille;1666;20;1686 +21384;Marey-lès-Fussey;56;5;61 +21385;Marey-sur-Tille;323;13;336 +21386;Marigny-le-Cahouët;319;12;331 +21387;Marigny-lès-Reullée;216;5;221 +21388;Marliens;595;3;598 +21389;Marmagne;212;1;213 +21390;Marsannay-la-Côte;5348;77;5425 +21391;Marsannay-le-Bois;840;10;850 +21392;Martrois;62;1;63 +21393;Massingy;152;9;161 +21394;Massingy-lès-Semur;163;4;167 +21395;Massingy-lès-Vitteaux;96;1;97 +21396;Mauvilly;68;2;70 +21397;Mavilly-Mandelot;178;3;181 +21398;Maxilly-sur-Saône;348;8;356 +21399;Meilly-sur-Rouvres;197;2;199 +21400;Le Meix;50;0;50 +21401;Meloisey;326;6;332 +21402;Menesble;10;0;10 +21403;Ménessaire;86;1;87 +21404;Ménétreux-le-Pitois;427;16;443 +21405;Merceuil;812;22;834 +21406;Mesmont;247;2;249 +21407;Messanges;236;11;247 +21408;Messigny-et-Vantoux;1660;30;1690 +21409;Meuilley;465;13;478 +21410;Meulson;33;0;33 +21411;Meursanges;557;20;577 +21412;Meursault;1425;47;1472 +21413;Millery;386;15;401 +21414;Mimeure;309;10;319 +21415;Minot;180;5;185 +21416;Mirebeau-sur-Bèze;2083;29;2112 +21417;Missery;105;0;105 +21418;Moitron;62;4;66 +21419;Molesme;265;4;269 +21420;Molinot;158;4;162 +21421;Moloy;233;3;236 +21422;Molphey;130;6;136 +21441;Mont-Saint-Jean;241;7;248 +21423;Montagny-lès-Beaune;682;18;700 +21424;Montagny-lès-Seurre;104;2;106 +21425;Montbard;5160;122;5282 +21426;Montberthault;211;3;214 +21427;Montceau-et-Écharnant;180;4;184 +21428;Monthelie;162;5;167 +21429;Montigny-Montfort;300;6;306 +21433;Montigny-Mornay-Villeneuve-sur-Vingeanne;394;4;398 +21430;Montigny-Saint-Barthélemy;86;2;88 +21431;Montigny-sur-Armançon;152;5;157 +21432;Montigny-sur-Aube;264;4;268 +21434;Montlay-en-Auxois;185;1;186 +21435;Montliot-et-Courcelles;303;6;309 +21436;Montmain;152;3;155 +21437;Montmançon;248;5;253 +21438;Montmoyen;78;3;81 +21439;Montoillot;80;0;80 +21440;Montot;197;6;203 +21442;Morey-Saint-Denis;666;12;678 +21444;Mosson;72;0;72 +21445;La Motte-Ternant;148;2;150 +21446;Moutiers-Saint-Jean;256;5;261 +21447;Musigny;83;0;83 +21448;Mussy-la-Fosse;86;1;87 +21449;Nan-sous-Thil;185;3;188 +21450;Nantoux;167;5;172 +21451;Nesle-et-Massoult;75;3;78 +21452;Neuilly-lès-Dijon;1857;17;1874 +21454;Nicey;110;0;110 +21455;Nod-sur-Seine;210;10;220 +21456;Nogent-lès-Montbard;155;8;163 +21457;Noidan;74;5;79 +21458;Noiron-sous-Gevrey;1106;13;1119 +21459;Noiron-sur-Bèze;238;5;243 +21460;Noiron-sur-Seine;72;1;73 +21461;Nolay;1465;21;1486 +21462;Norges-la-Ville;949;17;966 +21463;Normier;47;1;48 +21464;Nuits-Saint-Georges;5481;96;5577 +21465;Obtrée;76;3;79 +21466;Oigny;36;2;38 +21467;Oisilly;129;4;133 +21468;Orain;94;1;95 +21469;Orgeux;465;14;479 +21470;Origny;51;3;54 +21471;Orret;16;0;16 +21472;Orville;171;1;172 +21473;Ouges;1523;10;1533 +21474;Pagny-la-Ville;411;10;421 +21475;Pagny-le-Château;514;9;523 +21476;Painblanc;161;5;166 +21477;Panges;88;2;90 +21478;Pasques;289;5;294 +21479;Pellerey;105;0;105 +21480;Pernand-Vergelesses;244;9;253 +21481;Perrigny-lès-Dijon;1915;30;1945 +21482;Perrigny-sur-l'Ognon;646;13;659 +21483;Pichanges;293;5;298 +21484;Planay;67;5;72 +21485;Plombières-lès-Dijon;2556;46;2602 +21487;Pluvet;412;4;416 +21488;Poinçon-lès-Larrey;194;3;197 +21489;Poiseul-la-Grange;58;4;62 +21490;Poiseul-la-Ville-et-Laperrière;160;6;166 +21491;Poiseul-lès-Saulx;67;1;68 +21492;Pommard;500;13;513 +21493;Poncey-lès-Athée;581;7;588 +21494;Poncey-sur-l'Ignon;78;0;78 +21495;Pont;141;1;142 +21497;Pont-et-Massène;175;15;190 +21496;Pontailler-sur-Saône;1308;22;1330 +21498;Posanges;58;2;60 +21499;Pothières;207;4;211 +21500;Pouillenay;555;9;564 +21501;Pouilly-en-Auxois;1481;120;1601 +21502;Pouilly-sur-Saône;615;7;622 +21503;Pouilly-sur-Vingeanne;121;4;125 +21504;Prâlon;89;3;92 +21505;Précy-sous-Thil;714;10;724 +21506;Premeaux-Prissey;393;5;398 +21507;Premières;141;1;142 +21508;Prenois;419;8;427 +21510;Prusly-sur-Ource;159;1;160 +21511;Puits;122;5;127 +21512;Puligny-Montrachet;389;11;400 +21514;Quemigny-sur-Seine;98;3;101 +21515;Quetigny;9557;378;9935 +21516;Quincerot;76;4;80 +21517;Quincey;512;11;523 +21518;Quincy-le-Vicomte;211;5;216 +21519;Recey-sur-Ource;363;9;372 +21520;Remilly-en-Montagne;149;0;149 +21521;Remilly-sur-Tille;878;14;892 +21522;Renève;438;5;443 +21523;Reulle-Vergy;134;4;138 +21524;Riel-les-Eaux;94;2;96 +21525;La Roche-en-Brenil;869;11;880 +21528;La Roche-Vanneau;146;2;148 +21526;Rochefort-sur-Brévon;39;1;40 +21527;La Rochepot;291;8;299 +21529;Roilly;49;1;50 +21530;Rougemont;156;1;157 +21531;Rouvray;492;6;498 +21532;Rouvres-en-Plaine;1128;10;1138 +21533;Rouvres-sous-Meilly;89;3;92 +21534;Ruffey-lès-Beaune;714;49;763 +21535;Ruffey-lès-Echirey;1309;10;1319 +21536;Sacquenay;286;11;297 +21537;Saffres;115;2;117 +21538;Saint-Andeux;131;4;135 +21539;Saint-Anthot;59;1;60 +21540;Saint-Apollinaire;7463;104;7567 +21541;Saint-Aubin;223;8;231 +21542;Saint-Bernard;453;0;453 +21543;Saint-Broing-les-Moines;195;8;203 +21546;Saint-Didier;207;4;211 +21547;Saint-Euphrône;178;9;187 +21548;Saint-Germain-de-Modéon;172;3;175 +21549;Saint-Germain-le-Rocheux;80;4;84 +21550;Saint-Germain-lès-Senailly;125;5;130 +21552;Saint-Hélier;35;1;36 +21553;Saint-Jean-de-Bœuf;112;3;115 +21554;Saint-Jean-de-Losne;1092;6;1098 +21555;Saint-Julien;1477;20;1497 +21556;Saint-Léger-Triey;252;3;255 +21557;Saint-Marc-sur-Seine;107;3;110 +21560;Saint-Martin-de-la-Mer;296;2;298 +21561;Saint-Martin-du-Mont;435;9;444 +21562;Saint-Maurice-sur-Vingeanne;213;6;219 +21563;Saint-Mesmin;128;1;129 +21564;Saint-Nicolas-lès-Cîteaux;427;14;441 +21565;Saint-Philibert;473;8;481 +21566;Saint-Pierre-en-Vaux;148;2;150 +21567;Saint-Prix-lès-Arnay;227;6;233 +21568;Saint-Rémy;702;11;713 +21569;Saint-Romain;220;5;225 +21571;Saint-Sauveur;251;2;253 +21572;Saint-Seine-en-Bâche;408;6;414 +21573;Saint-Seine-l'Abbaye;375;3;378 +21574;Saint-Seine-sur-Vingeanne;393;14;407 +21575;Saint-Symphorien-sur-Saône;350;5;355 +21576;Saint-Thibault;164;1;165 +21577;Saint-Usage;1345;25;1370 +21578;Saint-Victor-sur-Ouche;303;4;307 +21544;Sainte-Colombe-en-Auxois;57;5;62 +21545;Sainte-Colombe-sur-Seine;943;15;958 +21558;Sainte-Marie-la-Blanche;882;31;913 +21559;Sainte-Marie-sur-Ouche;693;11;704 +21570;Sainte-Sabine;174;15;189 +21579;Salives;206;6;212 +21580;Salmaise;137;2;139 +21581;Samerey;155;2;157 +21582;Santenay;892;12;904 +21583;Santosse;51;2;53 +21584;Saulieu;2413;105;2518 +21585;Saulon-la-Chapelle;968;15;983 +21586;Saulon-la-Rue;703;10;713 +21587;Saulx-le-Duc;239;6;245 +21588;Saussey;72;2;74 +21589;Saussy;103;1;104 +21591;Savigny-le-Sec;844;14;858 +21590;Savigny-lès-Beaune;1305;41;1346 +21592;Savigny-sous-Mâlain;223;7;230 +21593;Savilly;80;3;83 +21594;Savoisy;200;3;203 +21595;Savolles;161;4;165 +21596;Savouges;376;6;382 +21597;Segrois;46;1;47 +21598;Seigny;172;2;174 +21599;Selongey;2403;33;2436 +21600;Semarey;122;1;123 +21601;Semezanges;92;4;96 +21602;Semond;23;0;23 +21603;Semur-en-Auxois;4139;353;4492 +21604;Senailly;139;4;143 +21605;Sennecey-lès-Dijon;2041;53;2094 +21607;Seurre;2353;23;2376 +21608;Sincey-lès-Rouvray;101;4;105 +21609;Soirans;485;7;492 +21610;Soissons-sur-Nacey;360;7;367 +21611;Sombernon;926;12;938 +21612;Souhey;91;0;91 +21084;Source-Seine;63;4;67 +21613;Soussey-sur-Brionne;153;8;161 +21614;Spoy;392;4;396 +21615;Sussey;248;8;256 +21616;Tailly;177;8;185 +21617;Talant;11689;235;11924 +21618;Talmay;576;6;582 +21619;Tanay;228;4;232 +21620;Tarsul;150;5;155 +21623;Tart;1588;32;1620 +21622;Tart-le-Bas;248;4;252 +21624;Tellecey;141;1;142 +21625;Ternant;83;5;88 +21626;Terrefondrée;62;2;64 +21627;Thenissey;105;10;115 +21628;Thoires;64;0;64 +21629;Thoisy-la-Berchère;309;5;314 +21630;Thoisy-le-Désert;207;1;208 +21631;Thomirey;50;0;50 +21632;Thorey-en-Plaine;1051;29;1080 +21633;Thorey-sous-Charny;179;1;180 +21634;Thorey-sur-Ouche;144;0;144 +21635;Thoste;108;6;114 +21636;Thury;275;8;283 +21637;Tichey;212;3;215 +21638;Til-Châtel;1110;7;1117 +21639;Tillenay;762;16;778 +21640;Torcy-et-Pouligny;204;5;209 +21641;Touillon;466;12;478 +21642;Toutry;442;8;450 +21643;Tréclun;470;3;473 +21644;Trochères;169;4;173 +21645;Trouhans;606;15;621 +21646;Trouhaut;117;3;120 +21647;Trugny;125;1;126 +21648;Turcey;183;1;184 +21649;Uncey-le-Franc;54;0;54 +21650;Urcy;153;1;154 +21272;Le Val-Larrey;264;4;268 +21327;Val-Mont;258;6;264 +21651;Val-Suzon;207;4;211 +21178;Valforêt;320;10;330 +21652;Vandenesse-en-Auxois;302;8;310 +21653;Vannaire;54;2;56 +21655;Vanvey;233;4;237 +21656;Varanges;716;11;727 +21657;Varois-et-Chaignot;1913;48;1961 +21659;Vaux-Saules;168;10;178 +21660;Veilly;41;0;41 +21661;Velars-sur-Ouche;1698;29;1727 +21662;Velogny;35;0;35 +21663;Venarey-les-Laumes;2884;37;2921 +21664;Verdonnet;83;4;87 +21665;Vernois-lès-Vesvres;175;0;175 +21666;Vernot;85;3;88 +21667;Véronnes;396;7;403 +21669;Verrey-sous-Drée;74;0;74 +21670;Verrey-sous-Salmaise;289;4;293 +21671;Vertault;56;1;57 +21672;Vesvres;27;2;29 +21673;Veuvey-sur-Ouche;209;2;211 +21674;Veuxhaulles-sur-Aube;207;3;210 +21675;Vianges;40;3;43 +21676;Vic-de-Chassenay;222;2;224 +21677;Vic-des-Prés;117;1;118 +21678;Vic-sous-Thil;189;3;192 +21679;Vieilmoulin;124;2;126 +21680;Vielverge;496;8;504 +21681;Vieux-Château;85;1;86 +21682;Viévigne;259;1;260 +21683;Viévy;357;4;361 +21684;Vignoles;977;30;1007 +21685;Villaines-en-Duesmois;252;6;258 +21686;Villaines-les-Prévôtes;141;2;143 +21687;Villargoix;143;5;148 +21689;Villars-et-Villenotte;174;7;181 +21688;Villars-Fontaine;118;4;122 +21690;Villeberny;91;2;93 +21691;Villebichot;393;6;399 +21692;Villecomte;253;4;257 +21693;Villedieu;69;2;71 +21694;Villeferry;30;0;30 +21695;La Villeneuve-les-Convers;52;1;53 +21696;Villeneuve-sous-Charigny;94;2;96 +21698;Villers-la-Faye;392;7;399 +21699;Villers-les-Pots;1134;13;1147 +21700;Villers-Patras;97;3;100 +21701;Villers-Rotin;128;5;133 +21702;Villey-sur-Tille;267;7;274 +21703;Villiers-en-Morvan;47;0;47 +21704;Villiers-le-Duc;87;0;87 +21705;Villotte-Saint-Seine;76;1;77 +21706;Villotte-sur-Ource;113;1;114 +21707;Villy-en-Auxois;218;4;222 +21708;Villy-le-Moutier;339;13;352 +21709;Viserny;178;2;180 +21710;Vitteaux;1074;18;1092 +21711;Vix;107;5;112 +21712;Volnay;241;9;250 +21713;Vonges;342;4;346 +21714;Vosne-Romanée;346;9;355 +21715;Voudenay;190;1;191 +21716;Vougeot;177;5;182 +21717;Voulaines-les-Templiers;288;10;298 +22001;Allineuc;604;8;612 +22002;Andel;1124;35;1159 +22003;Aucaleuc;943;80;1023 +22209;Beaussais-sur-Mer;3556;62;3618 +22004;Bégard;4808;78;4886 +22005;Belle-Isle-en-Terre;1031;19;1050 +22006;Berhet;257;8;265 +22055;Binic-Étables-sur-Mer;7068;158;7226 +22008;Bobital;1100;24;1124 +22009;Le Bodéo;162;0;162 +22107;Bon Repos sur Blavet;1271;39;1310 +22011;Boqueho;1078;20;1098 +22012;La Bouillie;860;18;878 +22013;Bourbriac;2271;50;2321 +22014;Bourseul;1141;29;1170 +22015;Bréhand;1647;37;1684 +22018;Brélidy;297;5;302 +22019;Bringolo;470;13;483 +22020;Broons;2886;49;2935 +22021;Brusvily;1196;13;1209 +22023;Bulat-Pestivien;432;9;441 +22024;Calanhel;217;1;218 +22025;Callac;2213;34;2247 +22026;Calorguen;728;9;737 +22027;Le Cambout;434;13;447 +22028;Camlez;888;26;914 +22029;Canihuel;355;13;368 +22030;Caouënnec-Lanvézéac;873;21;894 +22031;Carnoët;661;9;670 +22032;Caulnes;2488;152;2640 +22033;Caurel;360;11;371 +22034;Cavan;1564;27;1591 +22035;Les Champs-Géraux;1036;19;1055 +22036;La Chapelle-Blanche;206;7;213 +22037;La Chapelle-Neuve;388;4;392 +22206;Châtelaudren-Plouagat;3868;55;3923 +22039;La Chèze;563;28;591 +22040;Coadout;580;9;589 +22041;Coatascorn;262;3;265 +22042;Coatréven;495;15;510 +22043;Coëtlogon;213;5;218 +22044;Coëtmieux;1772;49;1821 +22045;Cohiniac;357;7;364 +22047;Corlay;957;15;972 +22048;Corseul;2184;47;2231 +22049;Créhen;1640;42;1682 +22050;Dinan;14166;575;14741 +22052;Duault;362;7;369 +22053;Éréac;682;8;690 +22054;Erquy;3910;94;4004 +22056;Évran;1712;35;1747 +22057;Le Faouët;396;9;405 +22179;Fréhel;1567;26;1593 +22059;Le Fœil;1429;39;1468 +22060;Gausson;616;21;637 +22061;Glomel;1380;42;1422 +22062;Gomené;546;11;557 +22063;Gommenec'h;558;15;573 +22064;Gouarec;925;32;957 +22065;Goudelin;1746;36;1782 +22068;Grâce-Uzel;432;9;441 +22067;Grâces;2528;58;2586 +22069;Guenroc;220;2;222 +22158;Guerlédan;2444;64;2508 +22070;Guingamp;6895;566;7461 +22071;Guitté;706;9;715 +22072;Gurunhuel;421;9;430 +22073;La Harmoye;377;14;391 +22074;Le Haut-Corlay;659;19;678 +22075;Hémonstoir;715;7;722 +22076;Hénanbihen;1314;36;1350 +22077;Hénansal;1173;15;1188 +22079;Hénon;2242;45;2287 +22081;Hillion;4137;98;4235 +22082;Le Hinglé;903;20;923 +22016;Île-de-Bréhat;361;7;368 +22083;Illifaut;690;16;706 +22084;Jugon-les-Lacs - Commune nouvelle;2493;51;2544 +22085;Kerbors;305;7;312 +22086;Kerfot;695;13;708 +22087;Kergrist-Moëlou;657;26;683 +22088;Kerien;254;4;258 +22090;Kermaria-Sulard;1049;20;1069 +22091;Kermoroc'h;456;10;466 +22092;Kerpert;270;10;280 +22093;Lamballe-Armor;16578;459;17037 +22094;Lancieux;1510;54;1564 +22095;Landebaëron;189;0;189 +22096;Landébia;481;3;484 +22097;La Landec;723;19;742 +22098;Landéhen;1415;36;1451 +22099;Lanfains;1091;18;1109 +22101;Langoat;1154;25;1179 +22103;Langrolay-sur-Rance;925;24;949 +22104;Languédias;515;29;544 +22105;Languenan;1155;23;1178 +22106;Langueux;7692;260;7952 +22108;Lanleff;121;5;126 +22109;Lanloup;222;5;227 +22110;Lanmérin;599;12;611 +22111;Lanmodez;417;7;424 +22112;Lannebert;443;5;448 +22113;Lannion;19880;972;20852 +22114;Lanrelas;837;16;853 +22115;Lanrivain;456;18;474 +22116;Lanrodec;1327;13;1340 +22117;Lantic;1672;33;1705 +22118;Lanvallay;4187;99;4286 +22119;Lanvellec;596;11;607 +22121;Lanvollon;1778;30;1808 +22122;Laurenan;736;14;750 +22124;Lescouët-Gouarec;223;3;226 +22126;Le Leslay;158;1;159 +22127;Lézardrieux;1474;38;1512 +22129;Loc-Envel;69;3;72 +22128;Locarn;407;16;423 +22131;Loguivy-Plougras;890;14;904 +22132;Lohuec;256;4;260 +22133;Loscouët-sur-Meu;629;16;645 +22134;Louannec;3068;115;3183 +22135;Louargat;2343;46;2389 +22136;Loudéac;9571;381;9952 +22137;Maël-Carhaix;1499;31;1530 +22138;Maël-Pestivien;378;5;383 +22139;Magoar;86;1;87 +22140;La Malhoure;594;15;609 +22141;Mantallot;230;6;236 +22143;Matignon;1662;23;1685 +22144;La Méaugon;1292;32;1324 +22145;Mégrit;818;11;829 +22146;Mellionnec;399;18;417 +22046;Le Mené;6417;122;6539 +22147;Merdrignac;2930;235;3165 +22148;Mérillac;233;4;237 +22149;Merléac;434;18;452 +22150;Le Merzer;959;27;986 +22152;Minihy-Tréguier;1267;38;1305 +22153;Moncontour;867;9;876 +22155;La Motte;2131;35;2166 +22156;Moustéru;660;15;675 +22157;Le Moustoir;666;17;683 +22160;Noyal;908;17;925 +22161;Pabu;2760;112;2872 +22162;Paimpol;7172;336;7508 +22163;Paule;707;24;731 +22164;Pédernec;1851;30;1881 +22165;Penguily;609;14;623 +22166;Penvénan;2538;65;2603 +22168;Perros-Guirec;7139;196;7335 +22169;Peumerit-Quintin;172;1;173 +22170;Plaine-Haute;1604;30;1634 +22171;Plaintel;4344;88;4432 +22172;Plancoët;3013;54;3067 +22174;Pléboulle;862;5;867 +22175;Plédéliac;1439;18;1457 +22176;Plédran;6666;111;6777 +22177;Pléguien;1325;28;1353 +22178;Pléhédel;1313;32;1345 +22180;Plélan-le-Petit;1910;29;1939 +22181;Plélauff;634;26;660 +22182;Plélo;3289;76;3365 +22183;Plémet;3649;128;3777 +22184;Plémy;1572;39;1611 +22185;Plénée-Jugon;2410;77;2487 +22186;Pléneuf-Val-André;4073;129;4202 +22187;Plérin;14062;483;14545 +22188;Plerneuf;1053;13;1066 +22189;Plésidy;613;13;626 +22190;Pleslin-Trigavou;3627;74;3701 +22193;Plestan;1598;26;1624 +22194;Plestin-les-Grèves;3591;89;3680 +22195;Pleubian;2322;42;2364 +22196;Pleudaniel;928;21;949 +22197;Pleudihen-sur-Rance;2909;77;2986 +22198;Pleumeur-Bodou;3925;166;4091 +22199;Pleumeur-Gautier;1217;20;1237 +22200;Pléven;582;6;588 +22201;Plévenon;781;14;795 +22202;Plévin;751;16;767 +22204;Ploëzal;1250;18;1268 +22205;Plorec-sur-Arguenon;414;2;416 +22207;Plouaret;2139;46;2185 +22208;Plouasne;1714;35;1749 +22210;Ploubazlanec;3014;125;3139 +22211;Ploubezre;3600;118;3718 +22212;Plouëc-du-Trieux;1134;28;1162 +22213;Plouër-sur-Rance;3531;107;3638 +22214;Plouézec;3182;57;3239 +22215;Ploufragan;11546;352;11898 +22216;Plougonver;733;11;744 +22217;Plougras;413;13;426 +22218;Plougrescant;1184;38;1222 +22219;Plouguenast-Langast;2487;84;2571 +22220;Plouguernével;1709;58;1767 +22221;Plouguiel;1760;38;1798 +22222;Plouha;4503;88;4591 +22223;Plouisy;1980;207;2187 +22224;Ploulec'h;1636;59;1695 +22225;Ploumagoar;5434;120;5554 +22226;Ploumilliau;2481;53;2534 +22227;Plounérin;747;11;758 +22228;Plounévez-Moëdec;1458;25;1483 +22229;Plounévez-Quintin;1091;25;1116 +22231;Plourac'h;319;4;323 +22232;Plourhan;1996;39;2035 +22233;Plourivo;2275;54;2329 +22234;Plouvara;1147;23;1170 +22235;Plouzélambre;234;4;238 +22236;Pludual;729;7;736 +22237;Pluduno;2193;65;2258 +22238;Plufur;534;12;546 +22239;Plumaudan;1288;39;1327 +22240;Plumaugat;1084;22;1106 +22241;Plumieux;1015;22;1037 +22242;Plurien;1519;22;1541 +22243;Plusquellec;527;15;542 +22244;Plussulien;487;23;510 +22245;Pluzunet;984;15;999 +22203;Plœuc-L'Hermitage;4062;77;4139 +22246;Pommeret;2075;34;2109 +22248;Pommerit-le-Vicomte;1760;50;1810 +22249;Pont-Melvez;603;19;622 +22250;Pontrieux;1028;25;1053 +22251;Pordic;7167;202;7369 +22254;Prat;1118;25;1143 +22255;La Prénessaye;887;21;908 +22256;Quemper-Guézennec;1094;26;1120 +22257;Quemperven;379;8;387 +22258;Quessoy;3786;233;4019 +22259;Quévert;3749;107;3856 +22260;Le Quillio;555;7;562 +22261;Quintenic;367;12;379 +22262;Quintin;2838;200;3038 +22263;Le Quiou;305;4;309 +22264;La Roche-Jaudy;2688;570;3258 +22265;Rospez;1758;54;1812 +22266;Rostrenen;3060;345;3405 +22267;Rouillac;395;2;397 +22268;Ruca;609;10;619 +22269;Runan;240;6;246 +22271;Saint-Adrien;353;8;361 +22272;Saint-Agathon;2273;53;2326 +22273;Saint-Alban;2154;31;2185 +22274;Saint-André-des-Eaux;339;9;348 +22275;Saint-Barnabé;1249;26;1275 +22276;Saint-Bihy;262;0;262 +22277;Saint-Brandan;2368;51;2419 +22278;Saint-Brieuc;44372;1634;46006 +22279;Saint-Caradec;1116;38;1154 +22280;Saint-Carné;998;28;1026 +22281;Saint-Carreuc;1509;28;1537 +22282;Saint-Cast-le-Guildo;3315;77;3392 +22283;Saint-Clet;875;23;898 +22284;Saint-Connan;297;6;303 +22285;Saint-Connec;255;7;262 +22286;Saint-Denoual;464;14;478 +22287;Saint-Donan;1457;35;1492 +22288;Saint-Étienne-du-Gué-de-l'Isle;356;6;362 +22289;Saint-Fiacre;212;3;215 +22291;Saint-Gildas;269;9;278 +22293;Saint-Gilles-les-Bois;432;5;437 +22294;Saint-Gilles-Pligeaux;295;6;301 +22295;Saint-Gilles-Vieux-Marché;354;8;362 +22296;Saint-Glen;621;11;632 +22299;Saint-Hélen;1481;37;1518 +22300;Saint-Hervé;400;9;409 +22334;Saint-Igeaux;135;5;140 +22302;Saint-Jacut-de-la-Mer;906;19;925 +22304;Saint-Jean-Kerdaniel;637;8;645 +22305;Saint-Jouan-de-l'Isle;496;5;501 +22306;Saint-Judoce;565;13;578 +22307;Saint-Julien;2050;50;2100 +22308;Saint-Juvat;653;20;673 +22309;Saint-Launeuc;200;4;204 +22310;Saint-Laurent;487;17;504 +22311;Saint-Lormel;860;17;877 +22312;Saint-Maden;231;9;240 +22313;Saint-Martin-des-Prés;315;10;325 +22314;Saint-Maudan;400;7;407 +22315;Saint-Maudez;284;11;295 +22316;Saint-Mayeux;470;15;485 +22317;Saint-Méloir-des-Bois;258;2;260 +22318;Saint-Michel-de-Plélan;321;8;329 +22319;Saint-Michel-en-Grève;456;13;469 +22320;Saint-Nicodème;168;3;171 +22321;Saint-Nicolas-du-Pélem;1666;43;1709 +22322;Saint-Péver;402;8;410 +22323;Saint-Pôtan;807;13;820 +22324;Saint-Quay-Perros;1303;56;1359 +22325;Saint-Quay-Portrieux;2997;220;3217 +22326;Saint-Rieul;550;5;555 +22327;Saint-Samson-sur-Rance;1607;26;1633 +22328;Saint-Servais;405;6;411 +22330;Saint-Thélo;420;6;426 +22332;Saint-Trimoël;544;6;550 +22333;Saint-Vran;759;30;789 +22331;Sainte-Tréphine;186;6;192 +22335;Senven-Léhart;234;0;234 +22337;Sévignac;1088;29;1117 +22338;Squiffiec;762;26;788 +22339;Taden;2467;76;2543 +22340;Tonquédec;1180;26;1206 +22341;Tramain;694;10;704 +22342;Trébédan;428;9;437 +22343;Trébeurden;3637;125;3762 +22344;Trébrivan;741;18;759 +22345;Trébry;798;19;817 +22346;Trédaniel;926;29;955 +22347;Trédarzec;1075;19;1094 +22348;Trédias;486;9;495 +22349;Trédrez-Locquémeau;1444;39;1483 +22350;Tréduder;195;4;199 +22351;Treffrin;548;13;561 +22352;Tréfumel;273;3;276 +22353;Trégastel;2465;71;2536 +22354;Tréglamus;1034;23;1057 +22356;Trégomeur;938;24;962 +22358;Trégonneau;576;7;583 +22359;Trégrom;426;4;430 +22360;Trégueux;8432;163;8595 +22361;Tréguidel;615;11;626 +22362;Tréguier;2419;276;2695 +22363;Trélévern;1249;32;1281 +22364;Trélivan;2782;73;2855 +22365;Trémargat;186;15;201 +22366;Trémel;411;6;417 +22368;Tréméreuc;744;28;772 +22369;Trémeur;764;19;783 +22370;Tréméven;341;8;349 +22371;Trémorel;1152;26;1178 +22372;Trémuson;2069;39;2108 +22373;Tréogan;100;4;104 +22375;Tressignaux;682;11;693 +22376;Trévé;1657;30;1687 +22377;Tréveneuc;794;25;819 +22378;Trévérec;214;7;221 +22379;Trévou-Tréguignec;1387;40;1427 +22380;Trévron;686;14;700 +22381;Trézény;356;8;364 +22383;Troguéry;249;6;255 +22384;Uzel;1046;25;1071 +22385;La Vicomté-sur-Rance;1057;14;1071 +22386;Le Vieux-Bourg;781;21;802 +22387;Le Vieux-Marché;1314;27;1341 +22388;Vildé-Guingalan;1241;21;1262 +22389;Yffiniac;5010;107;5117 +22390;Yvias;765;17;782 +22391;Yvignac-la-Tour;1166;19;1185 +23001;Ahun;1432;172;1604 +23002;Ajain;1138;26;1164 +23003;Alleyrat;143;0;143 +23004;Anzême;578;8;586 +23005;Arfeuille-Châtain;192;4;196 +23006;Arrènes;218;0;218 +23007;Ars;244;10;254 +23008;Aubusson;3366;185;3551 +23009;Auge;98;0;98 +23010;Augères;116;1;117 +23011;Aulon;154;2;156 +23012;Auriat;111;2;113 +23013;Auzances;1214;25;1239 +23014;Azat-Châtenet;115;3;118 +23015;Azerables;815;16;831 +23016;Banize;187;2;189 +23017;Basville;159;4;163 +23018;Bazelat;256;11;267 +23019;Beissat;25;0;25 +23020;Bellegarde-en-Marche;409;7;416 +23021;Bénévent-l'Abbaye;776;10;786 +23022;Bétête;365;8;373 +23023;Blaudeix;99;1;100 +23024;Blessac;533;12;545 +23025;Bonnat;1315;22;1337 +23026;Bord-Saint-Georges;353;11;364 +23027;Bosmoreau-les-Mines;244;7;251 +23028;Bosroger;110;2;112 +23029;Le Bourg-d'Hem;213;2;215 +23030;Bourganeuf;2572;215;2787 +23031;Boussac;1257;18;1275 +23032;Boussac-Bourg;717;12;729 +23033;La Brionne;440;7;447 +23034;Brousse;27;0;27 +23035;Budelière;717;10;727 +23036;Bussière-Dunoise;1038;15;1053 +23037;Bussière-Nouvelle;85;3;88 +23038;Bussière-Saint-Georges;256;3;259 +23039;La Celle-Dunoise;542;24;566 +23040;La Celle-sous-Gouzon;151;0;151 +23041;La Cellette;254;4;258 +23042;Ceyroux;127;1;128 +23043;Chamberaud;101;0;101 +23044;Chambon-Sainte-Croix;75;2;77 +23045;Chambon-sur-Voueize;892;12;904 +23046;Chambonchard;82;4;86 +23047;Chamborand;243;1;244 +23048;Champagnat;467;9;476 +23049;Champsanglard;248;6;254 +23050;La Chapelle-Baloue;135;1;136 +23051;La Chapelle-Saint-Martial;90;1;91 +23052;La Chapelle-Taillefert;424;12;436 +23053;Chard;211;2;213 +23054;Charron;232;10;242 +23055;Châtelard;32;0;32 +23056;Châtelus-le-Marcheix;314;8;322 +23057;Châtelus-Malvaleix;557;13;570 +23058;Le Chauchet;109;2;111 +23059;La Chaussade;107;6;113 +23060;Chavanat;143;3;146 +23061;Chénérailles;760;13;773 +23062;Chéniers;572;7;579 +23063;Clairavaux;156;1;157 +23064;Clugnat;645;6;651 +23065;Colondannes;265;8;273 +23066;Le Compas;212;12;224 +23067;La Courtine;769;8;777 +23068;Cressat;553;7;560 +23069;Crocq;411;6;417 +23070;Crozant;447;17;464 +23071;Croze;196;6;202 +23072;Domeyrot;225;3;228 +23073;Dontreix;415;8;423 +23074;Le Donzeil;188;4;192 +23075;Dun-le-Palestel;1116;21;1137 +23076;Évaux-les-Bains;1390;47;1437 +23077;Faux-la-Montagne;421;9;430 +23078;Faux-Mazuras;182;6;188 +23079;Felletin;1593;213;1806 +23080;Féniers;94;0;94 +23081;Flayat;309;5;314 +23082;Fleurat;309;6;315 +23083;Fontanières;249;1;250 +23084;La Forêt-du-Temple;143;1;144 +23086;Fransèches;242;4;246 +23087;Fresselines;498;13;511 +23192;Fursac;1511;23;1534 +23088;Gartempe;123;0;123 +23089;Genouillac;735;10;745 +23090;Gentioux-Pigerolles;405;3;408 +23091;Gioux;164;3;167 +23092;Glénic;666;12;678 +23093;Gouzon;1580;20;1600 +23095;Le Grand-Bourg;1220;44;1264 +23096;Guéret;13161;603;13764 +23097;Issoudun-Létrieix;299;3;302 +23098;Jalesches;90;4;94 +23099;Janaillat;330;5;335 +23100;Jarnages;452;11;463 +23101;Jouillat;401;12;413 +23102;Ladapeyre;346;3;349 +23103;Lafat;350;16;366 +23104;Lavaufranche;245;1;246 +23105;Lavaveix-les-Mines;666;5;671 +23106;Lépaud;363;4;367 +23107;Lépinas;139;5;144 +23108;Leyrat;146;1;147 +23109;Linard-Malval;210;5;215 +23110;Lioux-les-Monges;57;1;58 +23111;Lizières;268;4;272 +23112;Lourdoueix-Saint-Pierre;773;13;786 +23113;Lupersat;302;6;308 +23114;Lussat;426;7;433 +23115;Magnat-l'Étrange;242;2;244 +23116;Mainsat;564;13;577 +23117;Maison-Feyne;304;7;311 +23118;Maisonnisses;190;7;197 +23119;Malleret;44;0;44 +23120;Malleret-Boussac;193;4;197 +23122;Mansat-la-Courrière;83;2;85 +23123;Les Mars;195;2;197 +23124;Marsac;676;8;684 +23125;Le Mas-d'Artige;99;1;100 +23127;Mautes;210;6;216 +23128;Mazeirat;130;7;137 +23129;La Mazière-aux-Bons-Hommes;65;1;66 +23130;Méasnes;544;6;550 +23131;Mérinchal;720;11;731 +23132;Montaigut-le-Blanc;408;7;415 +23133;Montboucher;349;10;359 +23134;Le Monteil-au-Vicomte;201;48;249 +23136;Mortroux;285;9;294 +23137;Mourioux-Vieilleville;514;8;522 +23138;Moutier-d'Ahun;184;2;186 +23139;Moutier-Malcard;536;5;541 +23140;Moutier-Rozeille;427;9;436 +23141;Naillat;639;17;656 +23142;Néoux;287;3;290 +23143;Noth;499;11;510 +23144;La Nouaille;249;3;252 +23145;Nouhant;283;7;290 +23146;Nouzerines;248;5;253 +23147;Nouzerolles;99;2;101 +23148;Nouziers;240;1;241 +23149;Parsac-Rimondeix;701;14;715 +23150;Peyrabout;153;2;155 +23151;Peyrat-la-Nonière;426;9;435 +23152;Pierrefitte;70;0;70 +23154;Pionnat;758;11;769 +23155;Pontarion;365;8;373 +23156;Pontcharraud;79;1;80 +23157;La Pouge;90;0;90 +23158;Poussanges;155;0;155 +23159;Puy-Malsignat;159;3;162 +23160;Reterre;291;5;296 +23162;Roches;363;2;365 +23164;Rougnat;494;15;509 +23165;Royère-de-Vassivière;575;4;579 +23166;Sagnat;192;8;200 +23177;Saint-Agnant-de-Versillat;1094;29;1123 +23178;Saint-Agnant-près-Crocq;184;0;184 +23179;Saint-Alpinien;273;3;276 +23180;Saint-Amand;493;3;496 +23181;Saint-Amand-Jartoudeix;168;1;169 +23182;Saint-Avit-de-Tardes;173;2;175 +23183;Saint-Avit-le-Pauvre;78;2;80 +23184;Saint-Bard;103;3;106 +23185;Saint-Chabrais;294;4;298 +23186;Saint-Christophe;155;11;166 +23187;Saint-Dizier-la-Tour;212;3;215 +23188;Saint-Dizier-les-Domaines;195;4;199 +23189;Saint-Dizier-Masbaraud;1126;22;1148 +23190;Saint-Domet;176;4;180 +23191;Saint-Éloi;225;2;227 +23195;Saint-Fiel;1036;25;1061 +23196;Saint-Frion;254;4;258 +23197;Saint-Georges-la-Pouge;370;3;373 +23198;Saint-Georges-Nigremont;129;1;130 +23199;Saint-Germain-Beaupré;436;5;441 +23200;Saint-Goussaud;162;3;165 +23201;Saint-Hilaire-la-Plaine;210;4;214 +23202;Saint-Hilaire-le-Château;233;7;240 +23203;Saint-Julien-la-Genête;223;7;230 +23204;Saint-Julien-le-Châtel;143;3;146 +23205;Saint-Junien-la-Bregère;140;1;141 +23206;Saint-Laurent;691;13;704 +23207;Saint-Léger-Bridereix;198;3;201 +23208;Saint-Léger-le-Guérétois;429;10;439 +23209;Saint-Loup;182;1;183 +23210;Saint-Maixant;243;2;245 +23211;Saint-Marc-à-Frongier;425;9;434 +23212;Saint-Marc-à-Loubaud;136;2;138 +23213;Saint-Marien;185;1;186 +23214;Saint-Martial-le-Mont;261;5;266 +23215;Saint-Martial-le-Vieux;136;3;139 +23216;Saint-Martin-Château;144;6;150 +23217;Saint-Martin-Sainte-Catherine;343;5;348 +23219;Saint-Maurice-la-Souterraine;1223;29;1252 +23218;Saint-Maurice-près-Crocq;100;1;101 +23220;Saint-Médard-la-Rochette;583;12;595 +23221;Saint-Merd-la-Breuille;191;5;196 +23222;Saint-Michel-de-Veisse;162;4;166 +23223;Saint-Moreil;219;0;219 +23224;Saint-Oradoux-de-Chirouze;68;0;68 +23225;Saint-Oradoux-près-Crocq;97;4;101 +23226;Saint-Pardoux-d'Arnet;173;6;179 +23228;Saint-Pardoux-le-Neuf;192;5;197 +23229;Saint-Pardoux-les-Cards;287;3;290 +23227;Saint-Pardoux-Morterolles;206;5;211 +23232;Saint-Pierre-Bellevue;210;0;210 +23230;Saint-Pierre-Chérignat;168;4;172 +23233;Saint-Pierre-le-Bost;129;7;136 +23234;Saint-Priest;165;1;166 +23235;Saint-Priest-la-Feuille;771;12;783 +23236;Saint-Priest-la-Plaine;260;6;266 +23237;Saint-Priest-Palus;55;0;55 +23238;Saint-Quentin-la-Chabanne;404;10;414 +23239;Saint-Sébastien;647;13;660 +23240;Saint-Silvain-Bas-le-Roc;400;13;413 +23241;Saint-Silvain-Bellegarde;211;3;214 +23242;Saint-Silvain-Montaigut;213;2;215 +23243;Saint-Silvain-sous-Toulx;165;1;166 +23244;Saint-Sulpice-le-Dunois;607;12;619 +23245;Saint-Sulpice-le-Guérétois;1949;53;2002 +23246;Saint-Sulpice-les-Champs;355;6;361 +23247;Saint-Vaury;1753;118;1871 +23248;Saint-Victor-en-Marche;376;7;383 +23249;Saint-Yrieix-la-Montagne;224;8;232 +23250;Saint-Yrieix-les-Bois;286;5;291 +23193;Sainte-Feyre;2472;54;2526 +23194;Sainte-Feyre-la-Montagne;130;3;133 +23167;Sannat;344;8;352 +23168;Sardent;788;11;799 +23169;La Saunière;607;7;614 +23170;Savennes;214;9;223 +23171;Sermur;133;2;135 +23172;La Serre-Bussière-Vieille;122;1;123 +23173;Soubrebost;136;3;139 +23174;Soumans;601;7;608 +23175;Sous-Parsat;115;1;116 +23176;La Souterraine;5207;241;5448 +23251;Tardes;138;2;140 +23252;Tercillat;158;3;161 +23253;Thauron;174;7;181 +23254;Toulx-Sainte-Croix;263;3;266 +23255;Trois-Fonds;121;0;121 +23257;Vallière;723;20;743 +23258;Vareilles;311;9;320 +23259;Verneiges;114;1;115 +23260;Vidaillat;157;2;159 +23261;Viersat;303;2;305 +23262;Vigeville;164;2;166 +23263;Villard;366;6;372 +23264;La Villedieu;48;0;48 +23265;La Villeneuve;64;0;64 +23266;La Villetelle;169;1;170 +24001;Abjat-sur-Bandiat;620;7;627 +24002;Agonac;1761;23;1784 +24004;Ajat;317;3;320 +24006;Allas-les-Mines;204;10;214 +24007;Allemans;513;14;527 +24005;Alles-sur-Dordogne;385;9;394 +24008;Angoisse;588;10;598 +24009;Anlhiac;275;5;280 +24010;Annesse-et-Beaulieu;1436;49;1485 +24011;Antonne-et-Trigonant;1283;18;1301 +24012;Archignac;363;9;372 +24014;Aubas;609;19;628 +24015;Audrix;278;4;282 +24016;Augignac;814;18;832 +24018;Auriac-du-Périgord;383;10;393 +24019;Azerat;442;7;449 +24020;La Bachellerie;899;20;919 +24021;Badefols-d'Ans;404;9;413 +24022;Badefols-sur-Dordogne;212;5;217 +24023;Baneuil;347;12;359 +24024;Bardou;45;0;45 +24025;Bars;243;7;250 +24026;Bassillac et Auberoche;4498;82;4580 +24027;Bayac;351;1;352 +24028;Beaumontois en Périgord;1846;44;1890 +24029;Beaupouyet;492;7;499 +24030;Beauregard-de-Terrasson;703;16;719 +24031;Beauregard-et-Bassac;262;5;267 +24032;Beauronne;372;1;373 +24034;Beleymas;274;7;281 +24036;Berbiguières;182;4;186 +24037;Bergerac;26833;734;27567 +24038;Bertric-Burée;440;12;452 +24039;Besse;156;4;160 +24040;Beynac-et-Cazenac;547;9;556 +24042;Biras;664;7;671 +24043;Biron;162;10;172 +24045;Boisse;246;5;251 +24046;Boisseuilh;120;2;122 +24048;Bonneville-et-Saint-Avit-de-Fumadières;323;7;330 +24050;Borrèze;342;11;353 +24051;Bosset;215;6;221 +24052;Bouillac;122;2;124 +24053;Boulazac Isle Manoire;10635;297;10932 +24054;Bouniagues;587;19;606 +24055;Bourdeilles;743;15;758 +24056;Le Bourdeix;226;4;230 +24057;Bourg-des-Maisons;68;0;68 +24058;Bourg-du-Bost;225;3;228 +24059;Bourgnac;343;6;349 +24060;Bourniquel;69;1;70 +24061;Bourrou;128;7;135 +24062;Bouteilles-Saint-Sébastien;174;2;176 +24063;Bouzic;151;3;154 +24064;Brantôme en Périgord;3702;57;3759 +24066;Brouchaud;218;5;223 +24067;Le Bugue;2587;41;2628 +24068;Le Buisson-de-Cadouin;1954;58;2012 +24069;Bussac;397;2;399 +24070;Busserolles;503;9;512 +24071;Bussière-Badil;391;2;393 +24073;Calès;386;11;397 +24074;Calviac-en-Périgord;510;20;530 +24075;Campagnac-lès-Quercy;304;8;312 +24076;Campagne;380;10;390 +24077;Campsegret;389;7;396 +24080;Capdrot;502;4;506 +24081;Carlux;629;10;639 +24082;Carsac-Aillac;1578;29;1607 +24083;Carsac-de-Gurson;190;4;194 +24084;Carves;104;4;108 +24085;La Cassagne;151;1;152 +24086;Castelnaud-la-Chapelle;457;7;464 +24087;Castels et Bézenac;809;18;827 +24088;Cause-de-Clérans;345;7;352 +24089;Cazoulès;456;13;469 +24090;Celles;587;11;598 +24091;Cénac-et-Saint-Julien;1206;33;1239 +24094;Chalagnac;435;9;444 +24095;Chalais;404;9;413 +24096;Champagnac-de-Belair;752;14;766 +24097;Champagne-et-Fontaine;387;11;398 +24098;Champcevinel;2880;86;2966 +24100;Champniers-et-Reilhac;455;4;459 +24101;Champs-Romain;286;8;294 +24102;Chancelade;4262;82;4344 +24104;Chantérac;616;7;623 +24105;Chapdeuil;130;3;133 +24106;La Chapelle-Aubareil;541;13;554 +24107;La Chapelle-Faucher;414;6;420 +24108;La Chapelle-Gonaguet;1069;16;1085 +24109;La Chapelle-Grésignac;108;4;112 +24110;La Chapelle-Montabourlet;62;4;66 +24111;La Chapelle-Montmoreau;68;2;70 +24113;La Chapelle-Saint-Jean;91;1;92 +24114;Chassaignes;68;2;70 +24115;Château-l'Évêque;2170;36;2206 +24116;Châtres;194;1;195 +24119;Cherval;274;8;282 +24120;Cherveix-Cubas;569;12;581 +24121;Chourgnac;60;2;62 +24122;Cladech;105;1;106 +24124;Clermont-d'Excideuil;232;5;237 +24123;Clermont-de-Beauregard;105;1;106 +24126;Colombier;257;12;269 +24364;Coly-Saint-Amand;592;20;612 +24128;Comberanche-et-Épeluche;168;3;171 +24129;Condat-sur-Trincou;480;8;488 +24130;Condat-sur-Vézère;882;16;898 +24132;Conne-de-Labarde;246;4;250 +24131;Connezac;74;0;74 +24133;La Coquille;1324;17;1341 +24134;Corgnac-sur-l'Isle;835;13;848 +24135;Cornille;676;13;689 +24117;Les Coteaux Périgourdins;590;9;599 +24136;Coubjours;128;1;129 +24137;Coulaures;733;88;821 +24138;Coulounieix-Chamiers;7703;305;8008 +24140;Cours-de-Pile;1578;33;1611 +24139;Coursac;2149;44;2193 +24141;Coutures;185;1;186 +24142;Coux et Bigaroque-Mouzens;1220;40;1260 +24143;Couze-et-Saint-Front;716;10;726 +24144;Creyssac;99;0;99 +24145;Creysse;1740;32;1772 +24146;Creyssensac-et-Pissot;262;9;271 +24147;Cubjac-Auvézère-Val d'Ans;1083;9;1092 +24148;Cunèges;290;5;295 +24150;Daglan;538;19;557 +24151;Doissat;105;5;110 +24152;Domme;911;22;933 +24153;La Dornac;397;11;408 +24154;Douchapt;359;9;368 +24155;Douville;451;10;461 +24156;La Douze;1150;16;1166 +24157;Douzillac;795;12;807 +24158;Dussac;404;4;408 +24159;Échourgnac;392;7;399 +24161;Église-Neuve-d'Issac;140;3;143 +24160;Église-Neuve-de-Vergt;552;2;554 +24162;Escoire;418;9;427 +24163;Étouars;155;1;156 +24164;Excideuil;1177;41;1218 +24165;Eygurande-et-Gardedeuil;403;7;410 +24167;Eymet;2630;44;2674 +24259;Eyraud-Crempse-Maurens;1595;30;1625 +24171;Eyzerac;560;9;569 +24172;Les Eyzies;1100;16;1116 +24174;Fanlac;139;1;140 +24175;Les Farges;319;17;336 +24176;Faurilles;36;0;36 +24177;Faux;630;10;640 +24179;La Feuillade;732;21;753 +24180;Firbeix;307;9;316 +24182;Le Fleix;1485;52;1537 +24183;Fleurac;244;11;255 +24184;Florimont-Gaumier;142;2;144 +24186;Fonroque;326;2;328 +24222;La Force;2674;124;2798 +24188;Fossemagne;537;13;550 +24189;Fougueyrolles;479;17;496 +24190;Fouleix;248;8;256 +24191;Fraisse;172;1;173 +24192;Gabillou;94;3;97 +24193;Gageac-et-Rouillac;465;9;474 +24194;Gardonne;1592;25;1617 +24195;Gaugeac;112;1;113 +24196;Génis;478;4;482 +24197;Ginestet;729;14;743 +24199;Gout-Rossignol;379;7;386 +24200;Grand-Brassac;535;11;546 +24202;Granges-d'Ans;152;4;156 +24205;Grignols;672;10;682 +24206;Grives;120;4;124 +24207;Groléjac;654;16;670 +24208;Grun-Bordas;227;4;231 +24209;Hautefaye;136;1;137 +24210;Hautefort;928;16;944 +24211;Issac;445;5;450 +24212;Issigeac;757;10;767 +24213;Jaure;170;2;172 +24214;Javerlhac-et-la-Chapelle-Saint-Robert;846;10;856 +24215;Jayac;175;3;178 +24216;La Jemaye-Ponteyraud;154;3;157 +24217;Journiac;437;8;445 +24218;Jumilhac-le-Grand;1237;52;1289 +24220;Lacropte;651;13;664 +24223;Lalinde;2794;37;2831 +24224;Lamonzie-Montastruc;709;13;722 +24225;Lamonzie-Saint-Martin;2532;35;2567 +24226;Lamothe-Montravel;1330;21;1351 +24227;Lanouaille;1017;12;1029 +24228;Lanquais;496;14;510 +24229;Le Lardin-Saint-Lazare;1753;38;1791 +24230;Larzac;144;1;145 +24231;Lavalade;81;2;83 +24232;Lavaur;70;2;72 +24234;Les Lèches;368;2;370 +24236;Léguillac-de-l'Auche;994;14;1008 +24237;Lembras;1142;36;1178 +24238;Lempzours;134;5;139 +24240;Limeuil;336;12;348 +24241;Limeyrat;445;10;455 +24242;Liorac-sur-Louyre;245;1;246 +24243;Lisle;859;11;870 +24244;Lolme;197;2;199 +24245;Loubejac;264;3;267 +24246;Lunas;386;5;391 +24247;Lusignac;180;1;181 +24248;Lussas-et-Nontronneau;300;7;307 +24251;Manzac-sur-Vern;593;13;606 +24252;Marcillac-Saint-Quentin;792;19;811 +24253;Mareuil en Périgord;2342;48;2390 +24254;Marnac;188;1;189 +24255;Marquay;577;9;586 +24256;Marsac-sur-l'Isle;3104;74;3178 +24257;Marsalès;234;3;237 +24260;Mauzac-et-Grand-Castang;864;9;873 +24261;Mauzens-et-Miremont;301;11;312 +24262;Mayac;342;7;349 +24263;Mazeyrolles;305;11;316 +24264;Ménesplet;1817;15;1832 +24266;Mensignac;1521;26;1547 +24267;Mescoules;176;1;177 +24268;Meyrals;641;13;654 +24269;Mialet;613;9;622 +24271;Milhac-de-Nontron;505;13;518 +24272;Minzac;458;5;463 +24273;Molières;330;10;340 +24274;Monbazillac;829;90;919 +24276;Monestier;390;4;394 +24277;Monfaucon;294;4;298 +24278;Monmadalès;82;1;83 +24279;Monmarvès;64;0;64 +24280;Monpazier;473;6;479 +24293;Monplaisant;296;4;300 +24281;Monsac;192;7;199 +24282;Monsaguel;152;7;159 +24284;Montagnac-d'Auberoche;146;5;151 +24285;Montagnac-la-Crempse;392;13;405 +24286;Montagrier;516;10;526 +24287;Montaut;130;2;132 +24288;Montazeau;296;4;300 +24289;Montcaret;1455;20;1475 +24290;Montferrand-du-Périgord;157;4;161 +24291;Montignac;2770;53;2823 +24292;Montpeyroux;442;7;449 +24294;Montpon-Ménestérol;5498;80;5578 +24295;Montrem;1250;28;1278 +24296;Mouleydier;1132;18;1150 +24297;Moulin-Neuf;926;14;940 +24299;Mussidan;2710;54;2764 +24300;Nabirat;370;10;380 +24301;Nadaillac;376;4;380 +24302;Nailhac;333;2;335 +24303;Nanteuil-Auriac-de-Bourzac;224;3;227 +24304;Nantheuil;966;22;988 +24305;Nanthiat;239;2;241 +24306;Nastringues;117;4;121 +24307;Naussannes;253;5;258 +24308;Négrondes;815;10;825 +24309;Neuvic;3589;66;3655 +24311;Nontron;3050;110;3160 +24313;Orliac;60;2;62 +24314;Orliaguet;106;9;115 +24316;Parcoul-Chenaud;775;17;792 +24317;Paulin;259;4;263 +24318;Paunat;308;6;314 +24319;Paussac-et-Saint-Vivien;468;7;475 +24035;Pays de Belvès;1419;34;1453 +24320;Payzac;980;18;998 +24321;Pazayac;880;13;893 +24322;Périgueux;29966;1586;31552 +24323;Petit-Bersac;181;4;185 +24324;Peyrignac;580;9;589 +24325;Peyrillac-et-Millac;223;3;226 +24326;Peyzac-le-Moustier;174;3;177 +24327;Pezuls;122;3;125 +24328;Piégut-Pluviers;1166;34;1200 +24329;Le Pizou;1317;16;1333 +24168;Plaisance;423;12;435 +24330;Plazac;691;27;718 +24331;Pomport;739;23;762 +24334;Pontours;191;5;196 +24335;Port-Sainte-Foy-et-Ponchapt;2498;46;2544 +24336;Prats-de-Carlux;547;20;567 +24337;Prats-du-Périgord;147;2;149 +24338;Pressignac-Vicq;432;11;443 +24339;Preyssac-d'Excideuil;161;0;161 +24340;Prigonrieux;4157;78;4235 +24341;Proissans;1022;20;1042 +24345;Queyssac;466;14;480 +24346;Quinsac;362;8;370 +24347;Rampieux;150;0;150 +24348;Razac-d'Eymet;289;4;293 +24349;Razac-de-Saussignac;332;17;349 +24350;Razac-sur-l'Isle;2395;41;2436 +24351;Ribagnac;308;6;314 +24352;Ribérac;3861;147;4008 +24354;La Roche-Chalais;2999;53;3052 +24353;La Rochebeaucourt-et-Argentine;322;9;331 +24355;La Roque-Gageac;440;4;444 +24357;Rouffignac-de-Sigoulès;311;6;317 +24356;Rouffignac-Saint-Cernin-de-Reilhac;1603;35;1638 +24221;Rudeau-Ladosse;160;2;162 +24359;Sadillac;119;0;119 +24360;Sagelat;313;6;319 +24361;Saint-Agne;441;7;448 +24365;Saint-Amand-de-Vergt;243;8;251 +24366;Saint-André-d'Allas;833;19;852 +24367;Saint-André-de-Double;173;2;175 +24370;Saint-Antoine-de-Breuilh;1877;40;1917 +24371;Saint-Aquilin;479;3;482 +24372;Saint-Astier;5492;98;5590 +24373;Saint-Aubin-de-Cadelech;336;4;340 +24374;Saint-Aubin-de-Lanquais;343;4;347 +24375;Saint-Aubin-de-Nabirat;143;3;146 +24376;Saint Aulaye-Puymangou;1434;17;1451 +24377;Saint-Avit-de-Vialard;160;7;167 +24378;Saint-Avit-Rivière;78;4;82 +24379;Saint-Avit-Sénieur;439;4;443 +24380;Saint-Barthélemy-de-Bellegarde;505;2;507 +24381;Saint-Barthélemy-de-Bussière;214;8;222 +24383;Saint-Capraise-d'Eymet;156;2;158 +24382;Saint-Capraise-de-Lalinde;531;11;542 +24384;Saint-Cassien;34;2;36 +24386;Saint-Cernin-de-l'Herm;234;4;238 +24385;Saint-Cernin-de-Labarde;211;2;213 +24388;Saint-Chamassy;514;16;530 +24390;Saint-Crépin-d'Auberoche;356;5;361 +24392;Saint-Crépin-et-Carlucet;520;10;530 +24395;Saint-Cybranet;385;6;391 +24396;Saint-Cyprien;1561;34;1595 +24397;Saint-Cyr-les-Champagnes;244;7;251 +24398;Saint-Estèphe;613;19;632 +24399;Saint-Étienne-de-Puycorbier;106;4;110 +24403;Saint-Félix-de-Bourdeilles;62;0;62 +24404;Saint-Félix-de-Reillac-et-Mortemart;184;5;189 +24405;Saint-Félix-de-Villadeix;327;9;336 +24408;Saint-Front-d'Alemps;262;4;266 +24409;Saint-Front-de-Pradoux;1160;15;1175 +24410;Saint-Front-la-Rivière;518;8;526 +24411;Saint-Front-sur-Nizonne;157;2;159 +24412;Saint-Geniès;939;26;965 +24413;Saint-Georges-Blancaneix;252;0;252 +24414;Saint-Georges-de-Montclard;291;5;296 +24415;Saint-Géraud-de-Corps;243;2;245 +24416;Saint-Germain-de-Belvès;176;9;185 +24417;Saint-Germain-des-Prés;498;8;506 +24418;Saint-Germain-du-Salembre;941;7;948 +24419;Saint-Germain-et-Mons;829;18;847 +24420;Saint-Géry;236;2;238 +24421;Saint-Geyrac;198;6;204 +24422;Saint-Hilaire-d'Estissac;112;2;114 +24424;Saint-Jean-d'Ataux;128;3;131 +24426;Saint-Jean-d'Estissac;177;0;177 +24425;Saint-Jean-de-Côle;365;6;371 +24428;Saint-Jory-de-Chalais;584;38;622 +24429;Saint-Jory-las-Bloux;236;8;244 +24432;Saint-Julien-de-Lampon;626;18;644 +24423;Saint-Julien-Innocence-Eulalie;301;3;304 +24434;Saint-Just;136;2;138 +24436;Saint-Laurent-des-Hommes;1018;18;1036 +24437;Saint-Laurent-des-Vignes;886;13;899 +24438;Saint-Laurent-la-Vallée;247;9;256 +24441;Saint-Léon-d'Issigeac;126;4;130 +24442;Saint-Léon-sur-l'Isle;2027;23;2050 +24443;Saint-Léon-sur-Vézère;425;12;437 +24444;Saint-Louis-en-l'Isle;303;5;308 +24459;Saint-Maime-de-Péreyrol;283;8;291 +24445;Saint-Marcel-du-Périgord;147;2;149 +24446;Saint-Marcory;50;3;53 +24448;Saint-Martial-d'Albarède;464;7;471 +24449;Saint-Martial-d'Artenset;955;7;962 +24450;Saint-Martial-de-Nabirat;584;4;588 +24451;Saint-Martial-de-Valette;789;14;803 +24452;Saint-Martial-Viveyrol;195;2;197 +24453;Saint-Martin-de-Fressengeas;359;6;365 +24454;Saint-Martin-de-Gurson;666;8;674 +24455;Saint-Martin-de-Ribérac;716;10;726 +24456;Saint-Martin-des-Combes;186;8;194 +24457;Saint-Martin-l'Astier;138;1;139 +24458;Saint-Martin-le-Pin;271;7;278 +24460;Saint-Méard-de-Drône;497;6;503 +24461;Saint-Méard-de-Gurçon;813;18;831 +24463;Saint-Médard-d'Excideuil;546;16;562 +24462;Saint-Médard-de-Mussidan;1713;24;1737 +24464;Saint-Mesmin;318;5;323 +24465;Saint-Michel-de-Double;240;6;246 +24466;Saint-Michel-de-Montaigne;337;5;342 +24468;Saint-Michel-de-Villadeix;309;6;315 +24472;Saint-Nexans;967;18;985 +24474;Saint-Pancrace;187;0;187 +24476;Saint-Pantaly-d'Excideuil;150;3;153 +24477;Saint-Pardoux-de-Drône;198;5;203 +24478;Saint-Pardoux-et-Vielvic;211;0;211 +24479;Saint-Pardoux-la-Rivière;1179;13;1192 +24480;Saint-Paul-de-Serre;280;8;288 +24481;Saint-Paul-la-Roche;525;0;525 +24482;Saint-Paul-Lizonne;273;3;276 +24483;Saint-Perdoux;137;0;137 +24487;Saint-Pierre-d'Eyraud;1795;16;1811 +24484;Saint-Pierre-de-Chignac;871;17;888 +24485;Saint-Pierre-de-Côle;430;2;432 +24486;Saint-Pierre-de-Frugie;398;3;401 +24488;Saint-Pompont;372;6;378 +24489;Saint-Priest-les-Fougères;381;5;386 +24490;Saint Privat en Périgord;1121;30;1151 +24491;Saint-Rabier;585;9;594 +24493;Saint-Raphaël;94;3;97 +24494;Saint-Rémy;516;1;517 +24495;Saint-Romain-de-Monpazier;110;4;114 +24496;Saint-Romain-et-Saint-Clément;328;4;332 +24498;Saint-Saud-Lacoussière;832;14;846 +24499;Saint-Sauveur;847;21;868 +24500;Saint-Sauveur-Lalande;156;1;157 +24501;Saint-Seurin-de-Prats;494;8;502 +24502;Saint-Séverin-d'Estissac;100;0;100 +24505;Saint-Sulpice-d'Excideuil;344;3;347 +24504;Saint-Sulpice-de-Roumagnac;279;1;280 +24508;Saint-Victor;203;0;203 +24509;Saint-Vincent-de-Connezac;662;12;674 +24510;Saint-Vincent-de-Cosse;364;12;376 +24511;Saint-Vincent-Jalmoutiers;250;3;253 +24512;Saint-Vincent-le-Paluel;276;10;286 +24513;Saint-Vincent-sur-l'Isle;306;3;309 +24514;Saint-Vivien;250;7;257 +24393;Sainte-Croix;87;0;87 +24394;Sainte-Croix-de-Mareuil;150;6;156 +24401;Sainte-Eulalie-d'Ans;288;3;291 +24406;Sainte-Foy-de-Belvès;139;2;141 +24407;Sainte-Foy-de-Longas;237;7;244 +24470;Sainte-Mondane;260;5;265 +24471;Sainte-Nathalène;595;12;607 +24473;Sainte-Orse;358;6;364 +24492;Sainte-Radegonde;62;1;63 +24507;Sainte-Trie;110;2;112 +24515;Salagnac;769;4;773 +24516;Salignac-Eyvigues;1159;54;1213 +24517;Salles-de-Belvès;71;2;73 +24518;Salon;277;4;281 +24312;Sanilhac;4548;103;4651 +24519;Sarlande;432;0;432 +24520;Sarlat-la-Canéda;8869;434;9303 +24521;Sarliac-sur-l'Isle;1020;20;1040 +24522;Sarrazac;381;5;386 +24523;Saussignac;428;13;441 +24524;Savignac-de-Miremont;177;5;182 +24525;Savignac-de-Nontron;191;2;193 +24526;Savignac-Lédrier;717;9;726 +24527;Savignac-les-Églises;972;17;989 +24528;Sceau-Saint-Angel;124;2;126 +24529;Segonzac;205;3;208 +24531;Sergeac;216;3;219 +24532;Serres-et-Montguyard;237;3;240 +24533;Servanches;86;4;90 +24534;Sigoulès-et-Flaugeac;1225;236;1461 +24535;Simeyrols;258;3;261 +24536;Singleyrac;269;1;270 +24537;Siorac-de-Ribérac;251;4;255 +24538;Siorac-en-Périgord;1053;11;1064 +24540;Sorges et Ligueux en Périgord;1565;27;1592 +24541;Soudat;92;0;92 +24542;Soulaures;92;1;93 +24543;Sourzac;1107;14;1121 +24544;Tamniès;384;10;394 +24545;Teillots;102;1;103 +24546;Temple-Laguyon;41;1;42 +24547;Terrasson-Lavilledieu;6202;106;6308 +24548;Teyjat;275;5;280 +24549;Thénac;488;10;498 +24550;Thenon;1263;16;1279 +24551;Thiviers;2877;156;3033 +24552;Thonac;252;4;256 +24553;Tocane-Saint-Apre;1691;36;1727 +24554;La Tour-Blanche-Cercles;595;13;608 +24555;Tourtoirac;644;5;649 +24557;Trélissac;6658;223;6881 +24558;Trémolat;652;3;655 +24559;Tursac;339;10;349 +24560;Urval;114;7;121 +24362;Val de Louyre et Caudeau;1588;26;1614 +24562;Vallereuil;288;12;300 +24563;Valojoulx;271;8;279 +24564;Vanxains;700;88;788 +24565;Varaignes;403;9;412 +24566;Varennes;467;4;471 +24567;Vaunac;273;3;276 +24568;Vélines;1102;10;1112 +24569;Vendoire;134;2;136 +24570;Verdon;47;2;49 +24571;Vergt;1672;15;1687 +24572;Vergt-de-Biron;194;7;201 +24573;Verteillac;672;17;689 +24574;Veyrignac;335;8;343 +24575;Veyrines-de-Domme;230;22;252 +24576;Veyrines-de-Vergt;256;11;267 +24577;Vézac;587;11;598 +24580;Villac;266;2;268 +24581;Villamblard;886;19;905 +24582;Villars;463;9;472 +24584;Villefranche-de-Lonchat;973;18;991 +24585;Villefranche-du-Périgord;693;12;705 +24586;Villetoureix;906;21;927 +24587;Vitrac;800;30;830 +25001;Abbans-Dessous;263;6;269 +25002;Abbans-Dessus;304;5;309 +25003;Abbenans;342;6;348 +25004;Abbévillers;1040;20;1060 +25005;Accolans;96;1;97 +25006;Adam-lès-Passavant;89;2;91 +25007;Adam-lès-Vercel;103;3;106 +25008;Aibre;473;4;477 +25009;Aïssey;169;3;172 +25011;Allenjoie;735;16;751 +25012;Les Alliés;158;5;163 +25013;Allondans;253;3;256 +25014;Amagney;856;11;867 +25015;Amancey;687;20;707 +25016;Amathay-Vésigneux;163;4;167 +25017;Amondans;87;3;90 +25018;Anteuil;652;24;676 +25019;Appenans;376;10;386 +25020;Arbouans;945;9;954 +25021;Arc-et-Senans;1624;30;1654 +25025;Arc-sous-Cicon;665;13;678 +25026;Arc-sous-Montenot;195;9;204 +25022;Arcey;1441;48;1489 +25024;Arçon;841;15;856 +25029;Aubonne;240;3;243 +25030;Audeux;433;11;444 +25031;Audincourt;13387;182;13569 +25032;Autechaux;420;10;430 +25033;Autechaux-Roide;523;10;533 +25035;Les Auxons;2544;45;2589 +25036;Avanne-Aveney;2255;31;2286 +25038;Avilley;163;3;166 +25039;Avoudrey;909;15;924 +25040;Badevel;817;12;829 +25041;Bannans;369;10;379 +25042;Le Barboux;238;8;246 +25043;Bart;1980;53;2033 +25044;Bartherans;55;0;55 +25045;Battenans-les-Mines;54;1;55 +25046;Battenans-Varin;76;2;78 +25047;Baume-les-Dames;5063;163;5226 +25048;Bavans;3640;60;3700 +25049;Belfays;138;5;143 +25050;Le Bélieu;450;5;455 +25051;Belleherbe;625;11;636 +25052;Belmont;67;0;67 +25053;Belvoir;104;7;111 +25054;Berche;495;12;507 +25055;Berthelange;330;8;338 +25056;Besançon;115934;3315;119249 +25057;Bethoncourt;5647;78;5725 +25058;Beure;1349;11;1360 +25059;Beutal;277;5;282 +25060;Bians-les-Usiers;679;22;701 +25061;Bief;114;1;115 +25062;Le Bizot;309;8;317 +25063;Blamont;1221;26;1247 +25065;Blarians;57;4;61 +25066;Blussangeaux;84;1;85 +25067;Blussans;194;4;198 +25070;Bolandoz;372;15;387 +25071;Bondeval;472;11;483 +25072;Bonnal;29;2;31 +25073;Bonnay;837;6;843 +25074;Bonnétage;917;20;937 +25075;Bonnevaux;385;12;397 +25077;La Bosse;74;0;74 +25078;Bouclans;1073;23;1096 +25079;Boujailles;428;9;437 +25082;Bourguignon;914;23;937 +25083;Bournois;192;1;193 +25084;Boussières;1123;17;1140 +25085;Bouverans;364;7;371 +25086;Braillans;205;2;207 +25087;Branne;175;3;178 +25088;Breconchaux;93;5;98 +25089;Bremondans;86;2;88 +25090;Brères;62;0;62 +25091;Les Bréseux;477;8;485 +25092;La Bretenière;71;1;72 +25093;Bretigney;73;0;73 +25094;Bretigney-Notre-Dame;110;2;112 +25095;Bretonvillers;276;3;279 +25096;Brey-et-Maison-du-Bois;102;3;105 +25097;Brognard;481;12;493 +25098;Buffard;169;4;173 +25099;Bugny;217;6;223 +25100;Bulle;433;8;441 +25101;Burgille;565;5;570 +25102;Burnevillers;45;2;47 +25103;Busy;630;13;643 +25104;By;78;1;79 +25105;Byans-sur-Doubs;560;6;566 +25106;Cademène;71;0;71 +25107;Cendrey;191;0;191 +25108;Cernay-l'Église;302;9;311 +25109;Cessey;333;10;343 +25110;Chaffois;985;18;1003 +25111;Chalèze;370;12;382 +25112;Chalezeule;1292;18;1310 +25113;Chamesey;136;3;139 +25114;Chamesol;378;5;383 +25115;Champagney;286;3;289 +25116;Champlive;248;5;253 +25117;Champoux;91;0;91 +25119;Champvans-les-Moulins;340;10;350 +25120;Chantrans;405;14;419 +25122;Chapelle-d'Huin;514;7;521 +25121;Chapelle-des-Bois;253;16;269 +25124;Charmauvillers;250;6;256 +25125;Charmoille;330;5;335 +25126;Charnay;474;8;482 +25127;Charquemont;2668;50;2718 +25129;Chassagne-Saint-Denis;114;3;117 +25130;Châteauvieux-les-Fossés;13;0;13 +25131;Châtelblanc;120;5;125 +25132;Châtillon-Guyotte;129;3;132 +25133;Châtillon-le-Duc;2054;41;2095 +25134;Châtillon-sur-Lison;9;0;9 +25136;Chaucenne;511;13;524 +25139;La Chaux;558;9;567 +25141;Chaux-lès-Passavant;133;7;140 +25142;Chaux-Neuve;318;3;321 +25143;Chay;213;16;229 +25145;Chazot;120;1;121 +25147;Chemaudin et Vaux;1937;42;1979 +25148;La Chenalotte;499;5;504 +25149;Chenecey-Buillon;515;11;526 +25151;Chevigney-lès-Vercel;128;5;133 +25150;Chevigney-sur-l'Ognon;292;3;295 +25152;La Chevillotte;147;0;147 +25153;Chevroz;131;0;131 +25154;Chouzelot;269;9;278 +25155;Cléron;309;13;322 +25157;La Cluse-et-Mijoux;1307;28;1335 +25159;Colombier-Fontaine;1267;26;1293 +25160;Les Combes;737;26;763 +25161;Consolation-Maisonnettes;33;5;38 +25163;Corcelle-Mieslot;109;1;110 +25162;Corcelles-Ferrières;200;4;204 +25164;Corcondray;144;2;146 +25166;Côtebrune;80;6;86 +25173;Cour-Saint-Maurice;156;1;157 +25171;Courcelles;106;2;108 +25170;Courcelles-lès-Montbéliard;1277;40;1317 +25172;Courchapon;218;3;221 +25174;Courtefontaine;246;3;249 +25175;Courtetain-et-Salans;84;1;85 +25176;Courvières;315;4;319 +25177;Crosey-le-Grand;152;5;157 +25178;Crosey-le-Petit;135;3;138 +25179;Le Crouzet;59;1;60 +25180;Crouzet-Migette;116;6;122 +25181;Cubrial;136;4;140 +25182;Cubry;88;0;88 +25183;Cusance;69;1;70 +25184;Cuse-et-Adrisans;284;12;296 +25186;Cussey-sur-l'Ognon;1045;11;1056 +25185;Cussey-sur-Lison;65;5;70 +25187;Dambelin;495;6;501 +25188;Dambenois;754;22;776 +25189;Dammartin-les-Templiers;197;6;203 +25190;Dampierre-les-Bois;1635;27;1662 +25191;Dampierre-sur-le-Doubs;457;10;467 +25192;Dampjoux;172;4;176 +25193;Damprichard;1903;39;1942 +25194;Dannemarie;113;0;113 +25195;Dannemarie-sur-Crète;1473;292;1765 +25196;Dasle;1417;35;1452 +25197;Deluz;615;5;620 +25198;Désandans;734;15;749 +25199;Déservillers;339;10;349 +25200;Devecey;1451;28;1479 +25201;Dommartin;710;14;724 +25202;Dompierre-les-Tilleuls;267;4;271 +25203;Domprel;180;4;184 +25204;Doubs;3021;89;3110 +25207;Dung;637;17;654 +25208;Durnes;177;4;181 +25209;Échay;129;4;133 +25210;Échenans;155;6;161 +25211;Échevannes;89;0;89 +25212;École-Valentin;2609;48;2657 +25213;Les Écorces;718;22;740 +25214;Écot;503;10;513 +25215;L' Écouvotte;92;0;92 +25216;Écurcey;268;10;278 +25217;Émagny;594;10;604 +25218;Épenouse;151;3;154 +25219;Épenoy;630;16;646 +25220;Épeugney;586;15;601 +25221;Esnans;68;0;68 +25222;Étalans;1550;36;1586 +25223;Éternoz;338;7;345 +25224;Étouvans;825;13;838 +25225;Étrabonne;191;1;192 +25226;Étrappe;213;4;217 +25227;Étray;261;0;261 +25228;Étupes;3727;64;3791 +25229;Évillers;366;4;370 +25230;Exincourt;3222;50;3272 +25231;Eysson;116;2;118 +25232;Faimbe;107;2;109 +25233;Fallerans;284;8;292 +25234;Ferrières-le-Lac;172;7;179 +25235;Ferrières-les-Bois;320;3;323 +25236;Fertans;256;10;266 +25237;Fesches-le-Châtel;2189;33;2222 +25238;Fessevillers;158;2;160 +25239;Feule;180;1;181 +25240;Les Fins;3100;147;3247 +25241;Flagey;161;1;162 +25242;Flagey-Rigney;112;1;113 +25243;Flangebouche;779;18;797 +25244;Fleurey;85;3;88 +25245;Fontain;1301;27;1328 +25246;Fontaine-lès-Clerval;299;5;304 +25247;Fontenelle-Montby;92;3;95 +25248;Les Fontenelles;568;133;701 +25249;Fontenotte;62;2;64 +25251;Fourbanne;173;8;181 +25252;Fourcatier-et-Maison-Neuve;112;0;112 +25253;Fourg;380;4;384 +25254;Les Fourgs;1381;32;1413 +25255;Fournet-Blancheroche;357;13;370 +25288;Fournets-Luisans;699;18;717 +25256;Frambouhans;904;14;918 +25257;Franey;272;5;277 +25258;Franois;2340;40;2380 +25259;Frasne;1936;37;1973 +25261;Froidevaux;75;1;76 +25262;Fuans;483;24;507 +25263;Gellin;242;6;248 +25264;Gémonval;85;0;85 +25265;Geneuille;1331;20;1351 +25266;Geney;119;2;121 +25267;Gennes;681;20;701 +25268;Germéfontaine;122;2;124 +25269;Germondans;60;1;61 +25270;Gevresin;118;6;124 +25271;Gilley;1656;37;1693 +25273;Glamondans;217;4;221 +25274;Glay;340;2;342 +25275;Glère;225;1;226 +25277;Gondenans-les-Moulins;72;0;72 +25276;Gondenans-Montby;175;2;177 +25278;Gonsans;567;13;580 +25279;Gouhelans;118;1;119 +25280;Goumois;162;5;167 +25281;Goux-lès-Dambelin;285;0;285 +25282;Goux-les-Usiers;727;9;736 +25283;Goux-sous-Landet;71;1;72 +25284;Grand-Charmont;5699;73;5772 +25285;Grand'Combe-Châteleu;1489;26;1515 +25286;Grand'Combe-des-Bois;133;5;138 +25287;Grandfontaine;1647;39;1686 +25289;Grandfontaine-sur-Creuse;72;3;75 +25290;La Grange;94;3;97 +25293;Granges-Narboz;1226;42;1268 +25295;Les Grangettes;278;14;292 +25296;Les Gras;797;28;825 +25297;Le Gratteris;186;0;186 +25298;Grosbois;238;9;247 +25299;Guillon-les-Bains;109;1;110 +25300;Guyans-Durnes;280;5;285 +25301;Guyans-Vennes;829;25;854 +25303;Hauterive-la-Fresse;225;6;231 +25304;Hérimoncourt;3632;61;3693 +25305;L' Hôpital-du-Grosbois;598;11;609 +25306;L' Hôpital-Saint-Lieffroy;114;5;119 +25307;Les Hôpitaux-Neufs;921;11;932 +25308;Les Hôpitaux-Vieux;450;6;456 +25309;Houtaud;1094;36;1130 +25310;Huanne-Montmartin;87;1;88 +25311;Hyémondans;201;4;205 +25312;Hyèvre-Magny;71;1;72 +25313;Hyèvre-Paroisse;191;3;194 +25314;Indevillers;262;2;264 +25315;L' Isle-sur-le-Doubs;2997;73;3070 +25316;Issans;238;12;250 +25317;Jallerange;260;6;266 +25318;Jougne;1858;35;1893 +25320;Labergement-Sainte-Marie;1198;33;1231 +25322;Laire;400;12;412 +25323;Laissey;439;9;448 +25324;Lanans;167;6;173 +25325;Landresse;233;6;239 +25326;Lantenne-Vertière;534;13;547 +25327;Lanthenans;68;0;68 +25328;Larnod;773;11;784 +25329;Laval-le-Prieuré;35;1;36 +25330;Lavans-Quingey;191;3;194 +25331;Lavans-Vuillafans;238;5;243 +25332;Lavernay;576;9;585 +25333;Laviron;334;8;342 +25334;Levier;2183;226;2409 +25335;Liebvillers;164;5;169 +25336;Liesle;533;14;547 +25338;Lizine;92;1;93 +25339;Lods;219;2;221 +25340;Lombard;190;4;194 +25341;Lomont-sur-Crête;171;6;177 +25342;Longechaux;78;3;81 +25343;Longemaison;154;3;157 +25344;Longevelle-lès-Russey;46;0;46 +25345;Longevelle-sur-Doubs;682;14;696 +25346;Longeville;173;3;176 +25347;La Longeville;806;20;826 +25348;Longevilles-Mont-d'Or;581;15;596 +25349;Loray;521;14;535 +25350;Lougres;765;23;788 +25351;Le Luhier;222;1;223 +25354;Luxiol;161;0;161 +25355;Magny-Châtelard;61;0;61 +25356;Maîche;4286;110;4396 +25357;Maisons-du-Bois-Lièvremont;807;8;815 +25359;Malans;173;5;178 +25360;Malbrans;160;4;164 +25361;Malbuisson;855;25;880 +25362;Malpas;281;9;290 +25364;Mamirolle;1775;18;1793 +25365;Mancenans;308;5;313 +25366;Mancenans-Lizerne;192;6;198 +25367;Mandeure;4819;150;4969 +25368;Marchaux-Chaudefontaine;1464;21;1485 +25369;Marvelise;165;2;167 +25370;Mathay;2158;37;2195 +25371;Mazerolles-le-Salin;200;4;204 +25372;Médière;284;12;296 +25373;Le Mémont;44;2;46 +25374;Mercey-le-Grand;542;16;558 +25375;Mérey-sous-Montrond;430;10;440 +25376;Mérey-Vieilley;147;5;152 +25377;Mésandans;222;6;228 +25378;Meslières;361;8;369 +25379;Mesmay;71;3;74 +25380;Métabief;1196;23;1219 +25381;Miserey-Salines;2502;36;2538 +25382;Moncey;579;6;585 +25383;Moncley;280;6;286 +25384;Mondon;96;1;97 +25391;Mont-de-Laval;177;6;183 +25392;Mont-de-Vougney;186;5;191 +25385;Montagney-Servigney;132;3;135 +25386;Montancy;141;3;144 +25387;Montandon;405;4;409 +25388;Montbéliard;25395;585;25980 +25389;Montbéliardot;114;4;118 +25390;Montbenoît;396;12;408 +25393;Montécheroux;557;7;564 +25394;Montenois;1501;43;1544 +25395;Montfaucon;1550;49;1599 +25397;Montferrand-le-Château;2161;45;2206 +25398;Montflovin;107;4;111 +25400;Montgesoye;465;9;474 +25401;Montivernage;28;0;28 +25402;Montjoie-le-Château;27;1;28 +25403;Montlebon;2081;68;2149 +25404;Montmahoux;93;2;95 +25405;Montperreux;840;32;872 +25406;Montrond-le-Château;561;14;575 +25408;Montussaint;58;1;59 +25410;Morre;1361;79;1440 +25411;Morteau;6935;309;7244 +25413;Mouthe;1098;35;1133 +25414;Le Moutherot;127;2;129 +25415;Mouthier-Haute-Pierre;335;5;340 +25416;Myon;183;4;187 +25417;Naisey-les-Granges;796;20;816 +25418;Nancray;1260;29;1289 +25419;Nans;100;4;104 +25420;Nans-sous-Sainte-Anne;156;4;160 +25421;Narbief;69;4;73 +25422;Neuchâtel-Urtière;195;0;195 +25425;Noël-Cerneux;433;15;448 +25426;Noirefontaine;359;6;365 +25427;Noironte;386;4;390 +25428;Nommay;1638;37;1675 +25429;Novillars;1501;41;1542 +25430;Ollans;39;0;39 +25431;Onans;349;13;362 +25432;Orchamps-Vennes;2129;61;2190 +25433;Orgeans-Blanchefontaine;44;1;45 +25434;Ornans;4413;104;4517 +25435;Orsans;163;4;167 +25436;Orve;61;2;63 +25437;Osse;323;3;326 +25438;Osselle-Routelle;949;11;960 +25439;Ougney-Douvot;253;5;258 +25440;Ouhans;376;7;383 +25441;Ouvans;60;2;62 +25442;Oye-et-Pallet;726;12;738 +25443;Palantine;72;1;73 +25444;Palise;141;4;145 +25445;Paroy;126;2;128 +25446;Passavant;217;12;229 +25447;Passonfontaine;325;5;330 +25156;Pays-de-Clerval;1229;29;1258 +25448;Pelousey;1527;28;1555 +25449;Péseux;127;1;128 +25450;Pessans;87;3;90 +25451;Petite-Chaux;143;3;146 +25452;Pierrefontaine-lès-Blamont;468;12;480 +25453;Pierrefontaine-les-Varans;1421;25;1446 +25454;Pirey;2066;40;2106 +25455;Placey;198;4;202 +25456;Plaimbois-du-Miroir;246;8;254 +25457;Plaimbois-Vennes;102;0;102 +25458;Les Plains-et-Grands-Essarts;219;5;224 +25459;La Planée;296;8;304 +25461;Pompierre-sur-Doubs;307;2;309 +25463;Pont-de-Roide-Vermondans;4185;75;4260 +25465;Pont-les-Moulins;195;2;197 +25462;Pontarlier;17197;836;18033 +25464;Les Pontets;135;4;139 +25466;Pouilley-Français;833;19;852 +25467;Pouilley-les-Vignes;1965;39;2004 +25468;Pouligney-Lusans;850;11;861 +25424;Les Premiers Sapins;1555;31;1586 +25469;Présentevillers;455;12;467 +25470;La Prétière;156;5;161 +25471;Provenchère;135;3;138 +25472;Puessans;31;3;34 +25473;Pugey;742;20;762 +25474;Le Puy;112;3;115 +25475;Quingey;1430;14;1444 +25476;Rahon;126;0;126 +25477;Rancenay;352;6;358 +25478;Randevillers;122;2;124 +25479;Rang;418;5;423 +25481;Raynans;337;5;342 +25482;Recologne;653;3;656 +25483;Reculfoz;41;3;44 +25485;Rémondans-Vaivre;234;4;238 +25486;Remoray-Boujeons;428;11;439 +25487;Renédale;40;3;43 +25488;Rennes-sur-Loue;104;5;109 +25489;Reugney;305;29;334 +25490;Rigney;390;19;409 +25491;Rignosot;116;3;119 +25492;Rillans;93;3;96 +25493;La Rivière-Drugeon;902;26;928 +25496;Roche-lès-Clerval;110;0;110 +25495;Roche-lez-Beaupré;2111;26;2137 +25494;Rochejean;672;6;678 +25497;Roches-lès-Blamont;632;14;646 +25498;Rognon;48;0;48 +25499;Romain;128;2;130 +25500;Ronchaux;87;1;88 +25501;Rondefontaine;34;1;35 +25502;Roset-Fluans;520;3;523 +25503;Rosières-sur-Barbèche;122;4;126 +25504;Rosureux;78;1;79 +25505;Rougemont;1124;32;1156 +25506;Rougemontot;95;1;96 +25507;Rouhe;79;2;81 +25508;Roulans;1127;24;1151 +25510;Ruffey-le-Château;364;8;372 +25511;Rurey;340;6;346 +25512;Le Russey;2342;81;2423 +25514;Saint-Antoine;339;17;356 +25516;Saint-Georges-Armont;120;6;126 +25517;Saint-Gorgon-Main;283;3;286 +25518;Saint-Hilaire;160;9;169 +25519;Saint-Hippolyte;898;13;911 +25520;Saint-Juan;172;3;175 +25521;Saint-Julien-lès-Montbéliard;165;5;170 +25522;Saint-Julien-lès-Russey;180;3;183 +25524;Saint-Maurice-Colombier;907;26;933 +25525;Saint-Point-Lac;281;8;289 +25527;Saint-Vit;4874;71;4945 +25513;Sainte-Anne;42;0;42 +25515;Sainte-Colombe;409;7;416 +25523;Sainte-Marie;685;15;700 +25526;Sainte-Suzanne;1510;41;1551 +25528;Samson;86;0;86 +25529;Sancey;1332;27;1359 +25532;Saône;3375;58;3433 +25533;Saraz;11;2;13 +25534;Sarrageois;194;4;198 +25535;Saules;226;6;232 +25536;Sauvagney;185;4;189 +25537;Scey-Maisières;291;9;300 +25538;Séchin;113;1;114 +25539;Seloncourt;5775;144;5919 +25540;Semondans;302;6;308 +25541;Septfontaines;368;7;375 +25542;Serre-les-Sapins;1639;28;1667 +25544;Servin;202;9;211 +25545;Silley-Amancey;140;2;142 +25546;Silley-Bléfond;56;1;57 +25547;Sochaux;3949;40;3989 +25548;Solemont;150;7;157 +25549;Sombacour;641;6;647 +25550;La Sommette;236;3;239 +25551;Soulce-Cernay;127;1;128 +25552;Sourans;118;2;120 +25553;Soye;390;9;399 +25554;Surmont;121;3;124 +25555;Taillecourt;1104;24;1128 +25556;Tallans;47;3;50 +25557;Tallenay;414;8;422 +25558;Tarcenay-Foucherans;1495;23;1518 +25138;Les Terres-de-Chaux;135;5;140 +25559;Thiébouhans;256;6;262 +25560;Thise;3044;45;3089 +25561;Thoraise;362;4;366 +25562;Thulay;218;5;223 +25563;Thurey-le-Mont;129;3;132 +25564;Torpes;1021;15;1036 +25565;Touillon-et-Loutelet;269;13;282 +25566;La Tour-de-Sçay;297;4;301 +25567;Tournans;127;3;130 +25569;Trépot;532;11;543 +25570;Tressandans;23;2;25 +25571;Trévillers;484;11;495 +25572;Trouvans;104;5;109 +25573;Urtière;11;0;11 +25574;Uzelle;172;1;173 +25575;Vaire;810;17;827 +25460;Le Val;245;29;274 +25579;Val-de-Roulans;195;3;198 +25578;Valdahon;5595;97;5692 +25580;Valentigney;10714;175;10889 +25582;Valleroy;156;2;158 +25583;Valonne;244;3;247 +25584;Valoreille;127;4;131 +25586;Vandoncourt;830;32;862 +25588;Vaucluse;120;30;150 +25589;Vauclusotte;87;1;88 +25590;Vaudrivillers;91;0;91 +25591;Vaufrey;158;0;158 +25592;Vaux-et-Chantegrue;585;13;598 +25594;Velesmes-Essarts;348;4;352 +25595;Vellerot-lès-Belvoir;96;0;96 +25596;Vellerot-lès-Vercel;67;1;68 +25597;Vellevans;234;6;240 +25598;Venise;513;7;520 +25599;Vennans;259;8;267 +25600;Vennes;182;4;186 +25601;Vercel-Villedieu-le-Camp;1591;83;1674 +25602;Vergranne;108;4;112 +25604;Verne;127;4;131 +25605;Vernierfontaine;462;11;473 +25607;Vernois-lès-Belvoir;60;1;61 +25608;Le Vernoy;168;3;171 +25609;Verrières-de-Joux;450;11;461 +25611;La Vèze;455;7;462 +25612;Vieilley;699;19;718 +25613;Viéthorey;94;2;96 +25614;Vieux-Charmont;2744;54;2798 +25615;Villars-lès-Blamont;441;6;447 +25616;Villars-Saint-Georges;273;2;275 +25617;Villars-sous-Dampjoux;356;9;365 +25618;Villars-sous-Écot;352;8;360 +25620;Ville-du-Pont;315;7;322 +25619;Les Villedieu;207;3;210 +25621;Villeneuve-d'Amont;235;37;272 +25622;Villers-Buzon;259;1;260 +25623;Villers-Chief;123;1;124 +25624;Villers-Grélot;152;3;155 +25625;Villers-la-Combe;51;1;52 +25321;Villers-le-Lac;4985;111;5096 +25626;Villers-Saint-Martin;212;5;217 +25627;Villers-sous-Chalamont;296;3;299 +25628;Villers-sous-Montrond;210;3;213 +25629;Voillans;208;6;214 +25630;Voires;92;0;92 +25631;Vorges-les-Pins;602;11;613 +25632;Voujeaucourt;3175;84;3259 +25633;Vuillafans;757;13;770 +25634;Vuillecin;641;23;664 +25635;Vyt-lès-Belvoir;188;3;191 +26002;Albon;1937;36;1973 +26003;Aleyrac;47;0;47 +26004;Alixan;2509;75;2584 +26005;Allan;1727;49;1776 +26006;Allex;2515;78;2593 +26007;Ambonil;113;7;120 +26008;Ancône;1341;29;1370 +26009;Andancette;1339;36;1375 +26010;Anneyron;3999;92;4091 +26011;Aouste-sur-Sye;2524;41;2565 +26012;Arnayon;24;3;27 +26013;Arpavon;77;3;80 +26014;Arthémonay;588;8;596 +26015;Aubenasson;72;5;77 +26016;Aubres;421;16;437 +26017;Aucelon;16;0;16 +26018;Aulan;11;1;12 +26019;Aurel;245;3;248 +26021;Autichamp;121;4;125 +26022;Ballons;83;3;86 +26023;Barbières;1059;18;1077 +26024;Barcelonne;349;10;359 +26025;Barnave;198;11;209 +26026;Barret-de-Lioure;74;0;74 +26027;Barsac;138;3;141 +26028;Bathernay;254;8;262 +26030;La Bâtie-des-Fonds;4;0;4 +26031;La Bâtie-Rolland;1029;27;1056 +26032;La Baume-Cornillane;443;9;452 +26034;La Baume-d'Hostun;571;9;580 +26033;La Baume-de-Transit;881;16;897 +26035;Beaufort-sur-Gervanne;471;8;479 +26036;Beaumont-en-Diois;104;4;108 +26037;Beaumont-lès-Valence;3649;85;3734 +26038;Beaumont-Monteux;1317;17;1334 +26039;Beauregard-Baret;854;13;867 +26040;Beaurières;67;2;69 +26041;Beausemblant;1432;26;1458 +26042;Beauvallon;1591;27;1618 +26043;Beauvoisin;145;4;149 +26045;La Bégude-de-Mazenc;1656;47;1703 +26046;Bellecombe-Tarendol;75;3;78 +26047;Bellegarde-en-Diois;85;0;85 +26048;Bénivay-Ollon;66;1;67 +26049;Bésayes;1221;35;1256 +26050;Bésignan;82;2;84 +26051;Bézaudun-sur-Bîne;68;2;70 +26052;Bonlieu-sur-Roubion;469;12;481 +26054;Bouchet;1512;23;1535 +26055;Boulc;134;2;136 +26056;Bourdeaux;653;17;670 +26057;Bourg-de-Péage;10205;179;10384 +26058;Bourg-lès-Valence;19975;579;20554 +26059;Bouvante;226;3;229 +26060;Bouvières;146;6;152 +26061;Bren;563;9;572 +26062;Brette;40;0;40 +26063;Buis-les-Baronnies;2302;96;2398 +26064;Chabeuil;6875;178;7053 +26065;Chabrillan;721;8;729 +26066;Le Chaffal;39;0;39 +26067;Chalancon;53;1;54 +26068;Le Chalon;211;6;217 +26069;Chamaloc;131;3;134 +26070;Chamaret;546;11;557 +26071;Chanos-Curson;1078;33;1111 +26072;Chantemerle-les-Blés;1282;22;1304 +26073;Chantemerle-lès-Grignan;251;3;254 +26074;La Chapelle-en-Vercors;713;132;845 +26075;La Charce;34;0;34 +26076;Charens;28;0;28 +26077;Charmes-sur-l'Herbasse;927;23;950 +26078;Charols;918;14;932 +26079;Charpey;1417;36;1453 +26080;Chastel-Arnaud;40;0;40 +26081;Châteaudouble;578;24;602 +26082;Châteauneuf-de-Bordette;96;5;101 +26083;Châteauneuf-de-Galaure;1808;578;2386 +26085;Châteauneuf-du-Rhône;2725;55;2780 +26084;Châteauneuf-sur-Isère;3875;139;4014 +26086;Châtillon-en-Diois;666;13;679 +26087;Châtillon-Saint-Jean;1359;35;1394 +26088;Chatuzange-le-Goubet;5516;125;5641 +26089;Chaudebonne;56;1;57 +26090;La Chaudière;28;0;28 +26091;Chauvac-Laux-Montaux;42;0;42 +26092;Chavannes;710;11;721 +26093;Clansayes;529;13;542 +26094;Claveyson;865;23;888 +26095;Cléon-d'Andran;836;35;871 +26096;Clérieux;2017;36;2053 +26097;Cliousclat;638;16;654 +26098;Cobonne;161;4;165 +26099;Colonzelle;549;12;561 +26100;Combovin;422;14;436 +26101;Comps;156;10;166 +26102;Condillac;139;6;145 +26103;Condorcet;486;4;490 +26104;Cornillac;83;2;85 +26105;Cornillon-sur-l'Oule;69;6;75 +26106;La Coucourde;1071;19;1090 +26107;Crépol;563;1;564 +26108;Crest;8505;268;8773 +26110;Crozes-Hermitage;670;10;680 +26111;Crupies;100;1;101 +26112;Curnier;181;8;189 +26113;Die;4621;242;4863 +26114;Dieulefit;3159;138;3297 +26115;Divajeu;640;69;709 +26116;Donzère;5833;94;5927 +26117;Échevis;51;4;55 +26118;Épinouze;1521;20;1541 +26119;Érôme;811;9;820 +26121;Espeluche;1064;39;1103 +26122;Espenel;172;2;174 +26123;Establet;27;0;27 +26124;Étoile-sur-Rhône;5478;125;5603 +26125;Eurre;1334;32;1366 +26126;Eygalayes;86;0;86 +26127;Eygaliers;104;3;107 +26128;Eygluy-Escoulin;67;0;67 +26129;Eymeux;1024;22;1046 +26130;Eyroles;28;0;28 +26131;Eyzahut;147;1;148 +26133;Fay-le-Clos;163;4;167 +26134;Félines-sur-Rimandoule;79;1;80 +26135;Ferrassières;127;2;129 +26137;Francillon-sur-Roubion;190;5;195 +26138;La Garde-Adhémar;1107;34;1141 +26139;Génissieux;2282;55;2337 +26380;Gervans;554;10;564 +26140;Geyssans;717;28;745 +26141;Gigors-et-Lozeron;193;5;198 +26142;Glandage;113;1;114 +26143;Le Grand-Serre;912;51;963 +26144;Grane;1913;52;1965 +26145;Les Granges-Gontardes;643;19;662 +26379;Granges-les-Beaumont;927;10;937 +26146;Grignan;1551;41;1592 +26147;Gumiane;20;1;21 +26148;Hauterives;1895;56;1951 +26149;Hostun;983;8;991 +26150;Izon-la-Bruisse;10;0;10 +26381;Jaillans;892;12;904 +26152;Jonchères;28;0;28 +26153;Laborel;102;1;103 +26154;Lachau;232;5;237 +26155;Lapeyrouse-Mornay;1219;18;1237 +26156;Larnage;1078;30;1108 +26157;La Laupie;756;18;774 +26159;Laval-d'Aix;118;2;120 +26160;Laveyron;1187;17;1204 +26161;Lemps;50;0;50 +26162;Lens-Lestang;882;29;911 +26163;Léoncel;51;0;51 +26164;Lesches-en-Diois;53;1;54 +26165;Livron-sur-Drôme;9104;136;9240 +26166;Loriol-sur-Drôme;6593;87;6680 +26167;Luc-en-Diois;527;2;529 +26168;Lus-la-Croix-Haute;549;6;555 +26169;Malataverne;2012;38;2050 +26170;Malissard;3201;96;3297 +26171;Manas;194;10;204 +26172;Manthes;670;10;680 +26173;Marches;836;20;856 +26174;Margès;1159;21;1180 +26175;Marignac-en-Diois;214;9;223 +26176;Marsanne;1343;38;1381 +26177;Marsaz;761;25;786 +26178;Menglon;517;8;525 +26179;Mercurol-Veaunes;2664;55;2719 +26180;Mérindol-les-Oliviers;236;5;241 +26181;Mévouillon;238;7;245 +26182;Mirabel-aux-Baronnies;1620;28;1648 +26183;Mirabel-et-Blacons;1095;28;1123 +26185;Mirmande;585;13;598 +26186;Miscon;55;1;56 +26188;Mollans-sur-Ouvèze;1061;24;1085 +26189;Montauban-sur-l'Ouvèze;110;0;110 +26190;Montaulieu;83;4;87 +26191;Montboucher-sur-Jabron;2285;57;2342 +26192;Montbrison-sur-Lez;281;11;292 +26193;Montbrun-les-Bains;441;9;450 +26194;Montchenu;579;16;595 +26195;Montclar-sur-Gervanne;186;3;189 +26196;Montéléger;1806;140;1946 +26197;Montélier;4140;114;4254 +26198;Montélimar;39097;1130;40227 +26199;Montferrand-la-Fare;29;0;29 +26200;Montfroc;75;1;76 +26201;Montguers;45;6;51 +26202;Montjoux;332;11;343 +26203;Montjoyer;286;8;294 +26204;Montlaur-en-Diois;146;5;151 +26205;Montmaur-en-Diois;83;0;83 +26206;Montmeyran;2916;95;3011 +26207;Montmiral;671;17;688 +26208;Montoison;1925;52;1977 +26209;Montréal-les-Sources;23;0;23 +26211;Montségur-sur-Lauzon;1312;27;1339 +26212;Montvendre;1185;29;1214 +26213;Moras-en-Valloire;667;15;682 +26214;Mornans;72;0;72 +26215;La Motte-Chalancon;426;19;445 +26216;La Motte-de-Galaure;795;15;810 +26217;La Motte-Fanjas;193;0;193 +26218;Mours-Saint-Eusèbe;3153;54;3207 +26219;Mureils;465;8;473 +26220;Nyons;6793;187;6980 +26221;Omblèze;72;1;73 +26222;Orcinas;38;0;38 +26223;Oriol-en-Royans;532;6;538 +26224;Ourches;251;6;257 +26225;Parnans;697;21;718 +26226;Le Pègue;364;6;370 +26227;Pelonne;24;0;24 +26229;La Penne-sur-l'Ouvèze;96;1;97 +26228;Pennes-le-Sec;36;0;36 +26231;Peyrins;2751;71;2822 +26232;Peyrus;606;8;614 +26233;Piégon;260;10;270 +26234;Piégros-la-Clastre;843;35;878 +26235;Pierrelatte;13496;256;13752 +26236;Pierrelongue;217;4;221 +26238;Les Pilles;246;2;248 +26239;Plaisians;199;4;203 +26240;Plan-de-Baix;147;3;150 +26241;Le Poët-Célard;127;2;129 +26242;Le Poët-en-Percip;17;0;17 +26243;Le Poët-Laval;933;41;974 +26244;Le Poët-Sigillat;121;1;122 +26245;Pommerol;11;0;11 +26246;Ponet-et-Saint-Auban;125;4;129 +26247;Ponsas;527;8;535 +26249;Pont-de-Barret;670;17;687 +26250;Pont-de-l'Isère;3503;53;3556 +26248;Pontaix;168;1;169 +26251;Portes-en-Valdaine;399;12;411 +26252;Portes-lès-Valence;10610;148;10758 +26253;Poyols;70;1;71 +26254;Pradelle;18;0;18 +26255;Les Prés;24;0;24 +26256;Propiac;131;2;133 +26258;Puy-Saint-Martin;886;29;915 +26257;Puygiron;433;21;454 +26259;Ratières;270;12;282 +26261;Réauville;387;11;398 +26262;Recoubeau-Jansac;269;7;276 +26263;Reilhanette;144;2;146 +26264;Rémuzat;343;7;350 +26020;La Répara-Auriples;235;6;241 +26266;Rimon-et-Savel;27;2;29 +26267;Rioms;26;1;27 +26271;La Roche-de-Glun;3272;75;3347 +26276;Roche-Saint-Secret-Béconne;452;14;466 +26277;La Roche-sur-Grane;170;4;174 +26278;La Roche-sur-le-Buis;288;10;298 +26268;Rochebaudin;121;0;121 +26269;Rochebrune;61;0;61 +26270;Rochechinard;120;2;122 +26272;Rochefort-en-Valdaine;355;9;364 +26273;Rochefort-Samson;1007;20;1027 +26274;Rochefourchat;1;0;1 +26275;Rochegude;1579;45;1624 +26279;La Rochette-du-Buis;72;2;74 +26281;Romans-sur-Isère;33160;672;33832 +26282;Romeyer;197;8;205 +26283;Rottier;21;2;23 +26284;Roussas;365;9;374 +26285;Rousset-les-Vignes;289;9;298 +26286;Roussieux;23;1;24 +26287;Roynac;486;18;504 +26288;Sahune;313;6;319 +26289;Saillans;1278;19;1297 +26290;Saint-Agnan-en-Vercors;376;10;386 +26291;Saint-Andéol;83;1;84 +26292;Saint-Auban-sur-l'Ouvèze;213;4;217 +26293;Saint-Avit;306;8;314 +26294;Saint-Bardoux;622;19;641 +26295;Saint-Barthélemy-de-Vals;1869;31;1900 +26296;Saint-Benoit-en-Diois;27;1;28 +26298;Saint-Christophe-et-le-Laris;416;5;421 +26300;Saint-Dizier-en-Diois;48;0;48 +26301;Saint-Donat-sur-l'Herbasse;4195;91;4286 +26304;Saint-Ferréol-Trente-Pas;258;5;263 +26305;Saint-Gervais-sur-Roubion;1035;21;1056 +26307;Saint-Jean-en-Royans;2868;67;2935 +26308;Saint-Julien-en-Quint;153;1;154 +26309;Saint-Julien-en-Vercors;238;5;243 +26310;Saint-Laurent-d'Onay;154;4;158 +26311;Saint-Laurent-en-Royans;1419;49;1468 +26312;Saint-Marcel-lès-Sauzet;1244;44;1288 +26313;Saint-Marcel-lès-Valence;6236;127;6363 +26314;Saint-Martin-d'Août;383;16;399 +26315;Saint-Martin-en-Vercors;361;14;375 +26316;Saint-Martin-le-Colonel;192;6;198 +26317;Saint-Maurice-sur-Eygues;781;14;795 +26318;Saint-May;39;1;40 +26319;Saint-Michel-sur-Savasse;583;10;593 +26320;Saint-Nazaire-en-Royans;804;10;814 +26321;Saint-Nazaire-le-Désert;193;8;201 +26322;Saint-Pantaléon-les-Vignes;441;16;457 +26323;Saint-Paul-lès-Romans;1822;47;1869 +26324;Saint-Paul-Trois-Châteaux;8937;457;9394 +26325;Saint-Rambert-d'Albon;6530;65;6595 +26326;Saint-Restitut;1387;45;1432 +26327;Saint-Roman;201;3;204 +26328;Saint-Sauveur-en-Diois;55;1;56 +26329;Saint-Sauveur-Gouvernet;182;6;188 +26330;Saint-Sorlin-en-Valloire;2268;31;2299 +26331;Saint-Thomas-en-Royans;596;14;610 +26332;Saint-Uze;2046;22;2068 +26333;Saint-Vallier;3915;152;4067 +26382;Saint-Vincent-la-Commanderie;541;7;548 +26299;Sainte-Croix;106;3;109 +26302;Sainte-Eulalie-en-Royans;544;13;557 +26303;Sainte-Euphémie-sur-Ouvèze;70;3;73 +26306;Sainte-Jalle;308;6;314 +26334;Salettes;145;2;147 +26335;Salles-sous-Bois;191;3;194 +26336;Saou;571;23;594 +26337;Saulce-sur-Rhône;1855;32;1887 +26338;Sauzet;1840;57;1897 +26339;Savasse;1444;41;1485 +26340;Séderon;264;4;268 +26341;Serves-sur-Rhône;729;13;742 +26001;Solaure en Diois;444;8;452 +26342;Solérieux;335;7;342 +26343;Souspierre;97;2;99 +26344;Soyans;388;6;394 +26346;Suze;234;5;239 +26345;Suze-la-Rousse;2104;53;2157 +26347;Tain-l'Hermitage;6162;204;6366 +26348;Taulignan;1677;29;1706 +26349;Tersanne;357;5;362 +26350;Teyssières;88;0;88 +26351;Les Tonils;25;0;25 +26352;La Touche;253;7;260 +26353;Les Tourrettes;1030;13;1043 +26355;Triors;567;8;575 +26356;Truinas;119;4;123 +26357;Tulette;1989;39;2028 +26358;Upie;1520;45;1565 +26359;Vachères-en-Quint;32;0;32 +26136;Val-Maravel;55;0;55 +26360;Valaurie;593;16;609 +26361;Valdrôme;146;1;147 +26362;Valence;63714;1314;65028 +26210;Valherbasse;1010;23;1033 +26363;Valouse;36;0;36 +26364;Vassieux-en-Vercors;313;4;317 +26365;Vaunaveys-la-Rochette;584;11;595 +26367;Venterol;699;20;719 +26368;Vercheny;461;6;467 +26369;Verclause;59;1;60 +26370;Vercoiran;141;6;147 +26371;Véronne;46;2;48 +26372;Vers-sur-Méouge;42;1;43 +26373;Vesc;260;8;268 +26374;Villebois-les-Pins;16;0;16 +26375;Villefranche-le-Château;20;1;21 +26376;Villeperdrix;118;0;118 +26377;Vinsobres;1115;25;1140 +26378;Volvent;33;0;33 +27001;Aclou;324;9;333 +27002;Acon;468;8;476 +27003;Acquigny;1586;34;1620 +27004;Aigleville;409;8;417 +27005;Ailly;1159;17;1176 +27006;Aizier;137;2;139 +27008;Alizay;1544;17;1561 +27009;Ambenay;566;8;574 +27010;Amécourt;162;1;163 +27012;Amfreville-les-Champs;453;16;469 +27011;Amfreville-Saint-Amand;1204;14;1218 +27013;Amfreville-sous-les-Monts;494;11;505 +27014;Amfreville-sur-Iton;830;22;852 +27015;Andé;1288;31;1319 +27016;Les Andelys;8056;143;8199 +27017;Angerville-la-Campagne;1391;36;1427 +27018;Appeville-Annebault;1013;11;1024 +27019;Armentières-sur-Avre;170;7;177 +27020;Arnières-sur-Iton;1682;43;1725 +27021;Asnières;320;9;329 +27023;Aulnay-sur-Iton;709;21;730 +27025;Autheuil-Authouillet;958;19;977 +27026;Authevernes;400;8;408 +27027;Les Authieux;294;7;301 +27028;Authou;338;4;342 +27031;Aviron;1100;59;1159 +27033;Bacquepuis;313;7;320 +27034;Bacqueville;628;9;637 +27035;Bailleul-la-Vallée;114;1;115 +27036;Bâlines;567;8;575 +27037;Barc;1225;17;1242 +27038;Les Barils;269;6;275 +27039;Barneville-sur-Seine;511;38;549 +27277;La Baronnie;718;15;733 +27040;Barquet;449;6;455 +27042;Barville;71;0;71 +27043;Les Baux-de-Breteuil;664;20;684 +27044;Les Baux-Sainte-Croix;840;38;878 +27045;Bazincourt-sur-Epte;757;12;769 +27046;Bazoques;161;1;162 +27047;Beaubray;318;6;324 +27048;Beauficel-en-Lyons;188;3;191 +27051;Beaumont-le-Roger;2879;37;2916 +27050;Beaumontel;657;15;672 +27052;Le Bec-Hellouin;396;3;399 +27053;Le Bec-Thomas;219;5;224 +27054;Bémécourt;576;7;583 +27055;Bérengeville-la-Campagne;324;6;330 +27056;Bernay;10085;358;10443 +27057;Bernienville;288;6;294 +27059;Bernouville;303;3;306 +27061;Berthouville;312;5;317 +27063;Berville-la-Campagne;245;1;246 +27064;Berville-sur-Mer;709;9;718 +27065;Beuzeville;4608;59;4667 +27066;Bézu-la-Forêt;320;6;326 +27067;Bézu-Saint-Éloi;1505;28;1533 +27068;Bois-Anzeray;176;2;178 +27069;Bois-Arnault;700;16;716 +27071;Le Bois-Hellain;226;2;228 +27072;Bois-Jérôme-Saint-Ouen;749;23;772 +27073;Bois-le-Roi;1185;18;1203 +27075;Bois-Normand-près-Lyre;340;4;344 +27074;Boisney;283;8;291 +27076;Boisset-les-Prévanches;468;9;477 +27077;Boissey-le-Châtel;880;10;890 +27078;La Boissière;273;4;277 +27079;Boissy-Lamberville;350;5;355 +27081;Boncourt;186;6;192 +27083;Bonneville-Aptot;257;4;261 +27082;La Bonneville-sur-Iton;2131;50;2181 +27302;Le Bosc du Theil;1344;13;1357 +27091;Bosgouet;707;5;712 +27094;Bosquentin;123;1;124 +27095;Bosrobert;664;5;669 +27090;Bosroumois;3588;67;3655 +27096;Les Bottereaux;349;12;361 +27097;Bouafles;653;12;665 +27098;Bouchevilliers;81;3;84 +27099;Le Boulay-Morin;777;10;787 +27100;Boulleville;1148;21;1169 +27101;Bouquelon;512;9;521 +27102;Bouquetot;1060;22;1082 +27103;Bourg-Achard;3947;49;3996 +27104;Bourg-Beaudouin;708;10;718 +27106;Bournainville-Faverolles;483;5;488 +27107;Bourneville-Sainte-Croix;1291;24;1315 +27108;Bourth;1255;34;1289 +27109;Bray;398;4;402 +27110;Brestot;596;6;602 +27111;Bretagnolles;201;5;206 +27112;Breteuil;4424;120;4544 +27113;Brétigny;134;6;140 +27114;Breuilpont;1222;21;1243 +27115;Breux-sur-Avre;346;7;353 +27116;Brionne;4278;152;4430 +27117;Broglie;1057;21;1078 +27118;Brosville;633;10;643 +27119;Bueil;1621;29;1650 +27120;Burey;400;5;405 +27123;Caillouet-Orgeville;477;12;489 +27124;Cailly-sur-Eure;219;1;220 +27125;Calleville;669;11;680 +27126;Campigny;1201;10;1211 +27127;Canappeville;678;20;698 +27129;Caorches-Saint-Nicolas;592;15;607 +27130;Capelle-les-Grands;428;11;439 +27132;Caugé;866;24;890 +27133;Caumont;1058;10;1068 +27134;Cauverville-en-Roumois;226;0;226 +27135;Cesseville;489;5;494 +27136;Chaignes;277;12;289 +27137;Chaise-Dieu-du-Theil;216;5;221 +27138;Chamblac;391;13;404 +27032;Chambois;1376;31;1407 +27139;Chambord;163;6;169 +27140;Chambray;423;11;434 +27141;Champ-Dolent;66;0;66 +27142;Champenard;270;7;277 +27144;Champigny-la-Futelaye;289;3;292 +27146;La Chapelle-Bayvel;386;5;391 +27147;La Chapelle-du-Bois-des-Faulx;653;10;663 +27148;La Chapelle-Gauthier;398;6;404 +27149;La Chapelle-Hareng;100;3;103 +27554;La Chapelle-Longueville;3371;105;3476 +27151;Charleval;1789;21;1810 +27152;Château-sur-Epte;569;9;578 +27153;Chauvincourt-Provemont;365;6;371 +27154;Chavigny-Bailleul;593;16;609 +27155;Chennebrun;109;1;110 +27156;Chéronvilliers;505;17;522 +27158;Cierrey;743;27;770 +27161;Claville;1082;21;1103 +27191;Clef Vallée d'Eure;2533;47;2580 +27162;Collandres-Quincarnon;233;5;238 +27163;Colletot;202;1;203 +27164;Combon;813;8;821 +27165;Conches-en-Ouche;5030;65;5095 +27167;Condé-sur-Risle;639;6;645 +27168;Connelles;189;7;196 +27169;Conteville;999;10;1009 +27170;Cormeilles;1161;21;1182 +27171;Le Cormier;408;12;420 +27173;Corneville-la-Fouquetière;121;3;124 +27174;Corneville-sur-Risle;1357;25;1382 +27176;Coudray;218;5;223 +27177;Coudres;552;12;564 +27179;Courbépine;727;16;743 +27180;Courcelles-sur-Seine;2040;34;2074 +27181;Courdemanche;597;12;609 +27182;Courteilles;148;1;149 +27183;La Couture-Boussey;2314;45;2359 +27184;Crasville;126;3;129 +27185;Crestot;565;6;571 +27187;Criquebeuf-la-Campagne;310;4;314 +27188;Criquebeuf-sur-Seine;1449;15;1464 +27189;La Croisille;440;7;447 +27190;Croisy-sur-Eure;188;10;198 +27192;Crosville-la-Vieille;603;11;614 +27193;Croth;1348;16;1364 +27194;Cuverville;248;2;250 +27196;Les Damps;1389;8;1397 +27199;Dangu;573;12;585 +27200;Dardez;152;7;159 +27201;Daubeuf-la-Campagne;233;6;239 +27202;Daubeuf-près-Vatteville;468;8;476 +27203;Douains;513;14;527 +27204;Doudeauville-en-Vexin;302;9;311 +27205;Douville-sur-Andelle;446;3;449 +27206;Droisy;439;3;442 +27207;Drucourt;606;8;614 +27208;Duranville;153;3;156 +27209;Écaquelon;613;11;624 +27210;Écardenville-la-Campagne;473;12;485 +27212;Écauville;111;2;113 +27214;Écouis;816;14;830 +27215;Ecquetot;374;9;383 +27216;Émalleville;522;26;548 +27217;Émanville;572;9;581 +27218;Épaignes;1617;16;1633 +27219;Épégard;574;8;582 +27220;Épieds;354;3;357 +27222;Épreville-en-Lieuvin;195;3;198 +27224;Épreville-près-le-Neubourg;471;10;481 +27226;Étrépagny;3764;80;3844 +27227;Étréville;676;11;687 +27228;Éturqueraye;298;3;301 +27229;Évreux;47733;1299;49032 +27230;Ézy-sur-Eure;3670;52;3722 +27231;Fains;440;7;447 +27232;Farceaux;344;6;350 +27233;Fatouville-Grestain;746;11;757 +27234;Fauville;353;6;359 +27235;Faverolles-la-Campagne;159;3;162 +27237;Le Favril;170;2;172 +27240;La Ferrière-sur-Risle;221;3;224 +27238;Ferrières-Haut-Clocher;1166;27;1193 +27239;Ferrières-Saint-Hilaire;419;7;426 +27241;Feuguerolles;177;5;182 +27242;Le Fidelaire;1024;14;1038 +27243;Fiquefleur-Équainville;725;10;735 +27085;Flancourt-Crescy-en-Roumois;1455;20;1475 +27245;Fleury-la-Forêt;265;8;273 +27246;Fleury-sur-Andelle;1844;20;1864 +27247;Flipou;324;3;327 +27248;Folleville;199;4;203 +27249;Fontaine-Bellenger;1150;20;1170 +27251;Fontaine-l'Abbé;527;8;535 +27252;Fontaine-la-Louvet;332;7;339 +27254;Fontaine-sous-Jouy;873;24;897 +27256;La Forêt-du-Parc;597;9;606 +27258;Fort-Moville;500;7;507 +27259;Foucrainville;78;3;81 +27260;Foulbec;659;8;667 +27261;Fouqueville;460;5;465 +27266;Franqueville;332;6;338 +27070;Frenelles-en-Vexin;1689;36;1725 +27267;Freneuse-sur-Risle;360;4;364 +27269;Fresne-Cauverville;196;3;199 +27271;Fresney;346;6;352 +27273;Gadencourt;382;6;388 +27275;Gaillon;6924;98;7022 +27276;Gamaches-en-Vexin;291;8;299 +27278;Garennes-sur-Eure;1908;37;1945 +27279;Gasny;3089;50;3139 +27280;Gauciel;861;7;868 +27281;Gaudreville-la-Rivière;227;8;235 +27282;Gauville-la-Campagne;578;12;590 +27284;Gisors;11537;167;11704 +27285;Giverny;494;15;509 +27286;Giverville;400;5;405 +27287;Glisolles;847;17;864 +27288;Glos-sur-Risle;591;13;604 +27289;La Goulafrière;165;3;168 +27290;Goupil-Othon;1257;17;1274 +27291;Gournay-le-Guérin;132;11;143 +27105;Grand Bourgtheroulde;3802;72;3874 +27295;Grand-Camp;493;10;503 +27298;Graveron-Sémerville;303;6;309 +27299;Gravigny;3940;81;4021 +27300;Grosley-sur-Risle;523;4;527 +27301;Grossœuvre;1227;26;1253 +27304;Guerny;172;6;178 +27306;Guichainville;2757;56;2813 +27307;Guiseniers;461;8;469 +27309;L' Habit;506;7;513 +27310;Hacqueville;438;8;446 +27311;Harcourt;1068;6;1074 +27312;Hardencourt-Cocherel;259;13;272 +27313;La Harengère;595;5;600 +27315;Harquency;264;9;273 +27316;Hauville;1279;27;1306 +27317;La Haye-Aubrée;462;11;473 +27318;La Haye-de-Calleville;265;3;268 +27319;La Haye-de-Routot;305;5;310 +27320;La Haye-du-Theil;298;0;298 +27321;La Haye-le-Comte;135;5;140 +27322;La Haye-Malherbe;1403;19;1422 +27323;La Haye-Saint-Sylvestre;279;2;281 +27324;Hébécourt;586;13;599 +27325;Hecmanville;173;3;176 +27326;Hécourt;330;13;343 +27327;Hectomare;219;8;227 +27329;Hennezis;789;15;804 +27330;Herqueville;134;4;138 +27331;Heubécourt-Haricourt;464;10;474 +27332;Heudebouville;788;12;800 +27333;Heudicourt;684;7;691 +27334;Heudreville-en-Lieuvin;108;0;108 +27335;Heudreville-sur-Eure;1052;31;1083 +27336;La Heunière;367;4;371 +27337;Heuqueville;361;6;367 +27338;Les Hogues;642;8;650 +27339;Hondouville;798;15;813 +27340;Honguemare-Guenouville;696;7;703 +27341;L' Hosmes;68;3;71 +27342;Houetteville;205;6;211 +27343;Houlbec-Cocherel;1305;56;1361 +27345;La Houssaye;210;2;212 +27346;Houville-en-Vexin;233;1;234 +27347;Huest;799;14;813 +27348;Igoville;1746;20;1766 +27349;Illeville-sur-Montfort;874;22;896 +27350;Illiers-l'Évêque;999;17;1016 +27351;Incarville;1416;24;1440 +27353;Irreville;467;8;475 +27354;Iville;464;4;468 +27355;Ivry-la-Bataille;2724;29;2753 +27358;Jouy-sur-Eure;583;13;596 +27359;Juignettes;220;1;221 +27360;Jumelles;321;7;328 +27361;La Lande-Saint-Léger;368;4;372 +27363;Le Landin;209;5;214 +27364;Launay;200;3;203 +27365;Léry;2033;38;2071 +27565;Le Lesme;669;9;678 +27366;Letteguives;203;3;206 +27367;Lieurey;1451;16;1467 +27368;Lignerolles;327;10;337 +27369;Lilly;84;2;86 +27370;Lisors;350;6;356 +27371;Livet-sur-Authou;150;1;151 +27372;Longchamps;635;5;640 +27373;Lorleau;144;2;146 +27374;Louversey;538;14;552 +27375;Louviers;18648;421;19069 +27376;Louye;220;6;226 +27377;Lyons-la-Forêt;723;7;730 +27378;La Madeleine-de-Nonancourt;1146;23;1169 +27379;Mainneville;425;8;433 +27380;Malleville-sur-le-Bec;261;4;265 +27381;Malouy;160;0;160 +27382;Mandeville;318;9;327 +27383;Mandres;373;11;384 +27384;Manneville-la-Raoult;506;11;517 +27385;Manneville-sur-Risle;1531;21;1552 +27386;Le Manoir;1278;6;1284 +27388;Marais-Vernier;508;13;521 +27389;Marbeuf;461;17;478 +27157;Marbois;1387;20;1407 +27390;Marcilly-la-Campagne;1161;17;1178 +27391;Marcilly-sur-Eure;1580;31;1611 +27392;Martagny;152;4;156 +27393;Martainville;493;2;495 +27394;Martot;573;11;584 +27395;Mélicourt;83;1;84 +27396;Ménesqueville;465;8;473 +27397;Ménilles;1728;42;1770 +27398;Menneval;1430;94;1524 +27399;Mercey;50;1;51 +27400;Merey;348;5;353 +27049;Mesnil-en-Ouche;4684;128;4812 +27401;Le Mesnil-Fuguet;171;7;178 +27403;Le Mesnil-Jourdain;233;12;245 +27404;Mesnil-Rousset;93;1;94 +27541;Le Mesnil-Saint-Jean;209;6;215 +27405;Mesnil-sous-Vienne;110;5;115 +27406;Mesnil-sur-l'Estrée;904;22;926 +27407;Mesnil-Verclives;316;9;325 +27198;Mesnils-sur-Iton;6122;252;6374 +27408;Mézières-en-Vexin;613;18;631 +27410;Miserey;629;7;636 +27411;Moisville;238;1;239 +27413;Montfort-sur-Risle;761;11;772 +27414;Montreuil-l'Argillé;823;11;834 +27062;Les Monts du Roumois;1559;32;1591 +27415;Morainville-Jouveaux;372;3;375 +27417;Morgny;656;12;668 +27418;Morsan;108;0;108 +27419;Mouettes;786;5;791 +27420;Mouflaines;167;9;176 +27421;Mousseaux-Neuville;647;14;661 +27422;Muids;871;25;896 +27423;Muzy;805;19;824 +27424;Nagel-Séez-Mesnil;327;8;335 +27425;Nassandres sur Risle;2394;46;2440 +27427;Neaufles-Auvergny;423;8;431 +27426;Neaufles-Saint-Martin;1294;7;1301 +27428;Le Neubourg;4166;209;4375 +27429;Neuilly;178;0;178 +27430;La Neuve-Grange;330;3;333 +27431;La Neuve-Lyre;573;6;579 +27432;La Neuville-du-Bosc;652;7;659 +27433;Neuville-sur-Authou;194;2;196 +27434;Noards;54;0;54 +27435;La Noë-Poulain;272;3;275 +27436;Nogent-le-Sec;427;6;433 +27437;Nojeon-en-Vexin;339;6;345 +27438;Nonancourt;2282;46;2328 +27439;Normanville;1073;35;1108 +27441;Notre-Dame-d'Épine;81;0;81 +27440;Notre-Dame-de-l'Isle;671;21;692 +27442;Notre-Dame-du-Hamel;210;7;217 +27444;Le Noyer-en-Ouche;228;2;230 +27445;Noyers;264;4;268 +27446;Ormes;489;3;492 +27448;Pacy-sur-Eure;5090;124;5214 +27451;Parville;308;6;314 +27263;Le Perrey;1233;13;1246 +27453;Perriers-sur-Andelle;1809;19;1828 +27454;Perruel;469;3;472 +27455;Piencourt;155;3;158 +27456;Pinterville;745;10;755 +27457;Piseux;744;13;757 +27458;Pîtres;2519;25;2544 +27459;Les Places;78;1;79 +27460;Plainville;195;5;200 +27462;Le Planquay;157;2;159 +27463;Plasnes;713;9;722 +27464;Le Plessis-Grohan;870;18;888 +27465;Le Plessis-Hébert;400;13;413 +27466;Le Plessis-Sainte-Opportune;335;5;340 +27467;Pont-Audemer;10230;245;10475 +27468;Pont-Authou;632;8;640 +27469;Pont-de-l'Arche;4143;57;4200 +27470;Pont-Saint-Pierre;1151;22;1173 +27473;Port-Mort;931;26;957 +27471;Porte-de-Seine;207;7;214 +27472;Portes;271;3;274 +27474;Poses;1169;22;1191 +27475;La Poterie-Mathieu;169;1;170 +27476;Les Préaux;377;9;386 +27477;Pressagny-l'Orgueilleux;706;26;732 +27478;Prey;950;25;975 +27480;Puchay;626;7;633 +27481;Pullay;400;53;453 +27482;La Pyle;156;4;160 +27483;Quatremare;418;6;424 +27485;Quillebeuf-sur-Seine;870;9;879 +27486;Quittebeuf;663;11;674 +27487;Radepont;657;5;662 +27488;Renneville;197;3;200 +27489;Reuilly;525;12;537 +27490;Richeville;272;5;277 +27492;Romilly-la-Puthenaye;318;10;328 +27493;Romilly-sur-Andelle;3261;51;3312 +27495;La Roquette;238;2;240 +27496;Rosay-sur-Lieure;530;6;536 +27498;Rouge-Perriers;367;4;371 +27497;Rougemontiers;1058;9;1067 +27500;Routot;1600;52;1652 +27501;Rouvray;263;6;269 +27502;Rugles;2246;27;2273 +27504;Sacquenville;1231;36;1267 +27505;Saint-Agnan-de-Cernières;161;1;162 +27507;Saint-André-de-l'Eure;3988;65;4053 +27508;Saint-Antonin-de-Sommaire;183;5;188 +27511;Saint-Aubin-d'Écrosville;709;11;720 +27512;Saint-Aubin-de-Scellon;346;7;353 +27514;Saint-Aubin-du-Thenney;373;3;376 +27517;Saint-Aubin-sur-Gaillon;1989;44;2033 +27518;Saint-Aubin-sur-Quillebeuf;716;13;729 +27520;Saint-Benoît-des-Ombres;143;2;145 +27521;Saint-Christophe-sur-Avre;142;6;148 +27522;Saint-Christophe-sur-Condé;481;4;485 +27527;Saint-Cyr-de-Salerne;205;7;212 +27529;Saint-Cyr-la-Campagne;427;9;436 +27530;Saint-Denis-d'Augerons;85;4;89 +27531;Saint-Denis-des-Monts;211;2;213 +27533;Saint-Denis-le-Ferment;488;20;508 +27534;Saint-Didier-des-Bois;887;10;897 +27535;Saint-Élier;440;9;449 +27536;Saint-Éloi-de-Fourques;522;15;537 +27537;Saint-Étienne-du-Vauvray;882;14;896 +27538;Saint-Étienne-l'Allier;547;9;556 +27539;Saint-Étienne-sous-Bailleul;388;13;401 +27542;Saint-Georges-du-Vièvre;884;15;899 +27543;Saint-Georges-Motel;889;11;900 +27544;Saint-Germain-de-Fresney;206;5;211 +27545;Saint-Germain-de-Pasquier;126;5;131 +27546;Saint-Germain-des-Angles;173;2;175 +27547;Saint-Germain-la-Campagne;893;11;904 +27548;Saint-Germain-sur-Avre;1177;25;1202 +27550;Saint-Grégoire-du-Vièvre;318;7;325 +27552;Saint-Jean-du-Thenney;245;7;252 +27553;Saint-Julien-de-la-Liègue;413;3;416 +27555;Saint-Laurent-des-Bois;248;5;253 +27556;Saint-Laurent-du-Tencement;64;0;64 +27557;Saint-Léger-de-Rôtes;436;6;442 +27558;Saint-Léger-du-Gennetey;182;6;188 +27560;Saint-Luc;253;12;265 +27561;Saint-Maclou;627;12;639 +27562;Saint-Marcel;4493;136;4629 +27563;Saint-Mards-de-Blacarville;801;16;817 +27564;Saint-Mards-de-Fresne;334;6;340 +27569;Saint-Martin-du-Tilleul;240;4;244 +27570;Saint-Martin-la-Campagne;99;2;101 +27571;Saint-Martin-Saint-Firmin;329;10;339 +27572;Saint-Meslin-du-Bosc;284;4;288 +27579;Saint-Ouen-de-Pontcheuil;95;2;97 +27580;Saint-Ouen-de-Thouberville;2378;29;2407 +27582;Saint-Ouen-du-Tilleul;1653;18;1671 +27584;Saint-Paul-de-Fourques;294;9;303 +27586;Saint-Philbert-sur-Boissey;172;1;173 +27587;Saint-Philbert-sur-Risle;787;7;794 +27589;Saint-Pierre-de-Bailleul;955;37;992 +27590;Saint-Pierre-de-Cernières;225;3;228 +27591;Saint-Pierre-de-Cormeilles;609;12;621 +27592;Saint-Pierre-de-Salerne;248;3;251 +27593;Saint-Pierre-des-Fleurs;1562;21;1583 +27594;Saint-Pierre-des-Ifs;277;1;278 +27595;Saint-Pierre-du-Bosguérard;1032;13;1045 +27597;Saint-Pierre-du-Val;572;1;573 +27598;Saint-Pierre-du-Vauvray;1282;26;1308 +27599;Saint-Pierre-la-Garenne;912;10;922 +27601;Saint-Samson-de-la-Roque;436;4;440 +27602;Saint-Sébastien-de-Morsent;5697;170;5867 +27603;Saint-Siméon;317;6;323 +27604;Saint-Sulpice-de-Grimbouville;167;2;169 +27605;Saint-Sylvestre-de-Cormeilles;253;6;259 +27606;Saint-Symphorien;488;1;489 +27609;Saint-Victor-d'Épine;321;3;324 +27608;Saint-Victor-de-Chrétienville;456;9;465 +27610;Saint-Victor-sur-Avre;58;4;62 +27611;Saint-Vigor;330;4;334 +27612;Saint-Vincent-des-Bois;334;6;340 +27613;Saint-Vincent-du-Boulay;381;5;386 +27524;Sainte-Colombe-la-Commanderie;848;6;854 +27525;Sainte-Colombe-près-Vernon;309;19;328 +27540;Sainte-Geneviève-lès-Gasny;663;15;678 +27578;Sainte-Marie-d'Attez;599;14;613 +27567;Sainte-Marie-de-Vatimesnil;269;6;275 +27568;Sainte-Marthe;508;8;516 +27576;Sainte-Opportune-du-Bosc;648;15;663 +27577;Sainte-Opportune-la-Mare;440;11;451 +27614;Sancourt;155;4;159 +27615;Sassey;192;3;195 +27617;Saussay-la-Campagne;531;8;539 +27616;La Saussaye;1872;55;1927 +27618;Sébécourt;477;10;487 +27620;Selles;469;2;471 +27621;Serez;154;5;159 +27622;Serquigny;1987;47;2034 +27623;Surtauville;486;9;495 +27624;Surville;904;24;928 +27625;Suzay;351;2;353 +27693;Sylvains-Lès-Moulins;1295;33;1328 +27412;Terres de Bord;1484;35;1519 +27627;Le Theil-Nolent;250;12;262 +27089;Thénouville;1017;17;1034 +27629;Thiberville;1800;15;1815 +27630;Thibouville;312;55;367 +27631;Thierville;371;4;375 +27632;Le Thil;539;8;547 +27633;Les Thilliers-en-Vexin;494;6;500 +27635;Le Thuit;141;5;146 +27638;Le Thuit de l'Oison;3619;51;3670 +27640;Tilleul-Dame-Agnès;195;4;199 +27641;Le Tilleul-Lambert;251;5;256 +27643;Tillières-sur-Avre;1081;22;1103 +27644;Tilly;547;42;589 +27645;Tocqueville;155;2;157 +27646;Le Torpt;443;4;447 +27649;Touffreville;351;7;358 +27650;Tournedos-Bois-Hubert;476;4;480 +27652;Tourneville;319;8;327 +27654;Tourville-la-Campagne;1081;11;1092 +27655;Tourville-sur-Pont-Audemer;721;169;890 +27656;Toutainville;1344;26;1370 +27516;Treis-Sants-en-Ouche;1420;33;1453 +27658;Le Tremblay-Omonville;342;6;348 +27659;La Trinité;116;3;119 +27660;La Trinité-de-Réville;239;2;241 +27661;La Trinité-de-Thouberville;432;11;443 +27662;Triqueville;332;10;342 +27676;Les Trois Lacs;1784;34;1818 +27663;Le Troncq;173;4;177 +27664;Le Tronquay;511;8;519 +27665;Trouville-la-Haule;767;13;780 +27666;La Vacherie;568;19;587 +27022;Le Val d'Hazey;5556;72;5628 +27294;Val d'Orger;982;12;994 +27668;Le Val-David;723;18;741 +27701;Val-de-Reuil;13063;264;13327 +27447;Le Val-Doré;921;50;971 +27667;Valailles;384;10;394 +27669;Valletot;424;5;429 +27670;Vandrimare;959;18;977 +27671;Vannecrocq;153;6;159 +27672;Vascœuil;355;1;356 +27673;Vatteville;182;2;184 +27528;Le Vaudreuil;3722;84;3806 +27674;Vaux-sur-Eure;270;7;277 +27677;Venon;395;8;403 +27678;Les Ventes;1041;24;1065 +27679;Verneuil d'Avre et d'Iton;8170;403;8573 +27680;Verneusses;201;4;205 +27681;Vernon;23872;658;24530 +27682;Vesly;694;23;717 +27213;Vexin-sur-Epte;6065;137;6202 +27683;Vézillon;251;3;254 +27684;Le Vieil-Évreux;812;14;826 +27685;La Vieille-Lyre;651;10;661 +27686;Vieux-Port;46;0;46 +27689;Villegats;350;16;366 +27690;Villers-en-Vexin;318;1;319 +27691;Villers-sur-le-Roule;853;18;871 +27692;Villettes;170;6;176 +27694;Villez-sous-Bailleul;312;14;326 +27695;Villez-sur-le-Neubourg;284;6;290 +27696;Villiers-en-Désœuvre;937;18;955 +27697;Vironvay;332;5;337 +27698;Vitot;559;14;573 +27699;Voiscreville;124;4;128 +27700;Vraiville;691;5;696 +28001;Abondant;2372;54;2426 +28003;Allainville;136;7;143 +28004;Allonnes;313;3;316 +28005;Alluyes;760;89;849 +28006;Amilly;1842;47;1889 +28007;Anet;2733;99;2832 +28236;Arcisses;2204;59;2263 +28008;Ardelles;200;3;203 +28009;Ardelu;73;1;74 +28010;Argenvilliers;332;10;342 +28013;Aunay-sous-Auneau;1483;24;1507 +28014;Aunay-sous-Crécy;637;7;644 +28015;Auneau-Bleury-Saint-Symphorien;5916;84;6000 +28016;Les Autels-Villevillon;156;2;158 +28018;Authon-du-Perche;1511;17;1528 +28019;Baigneaux;225;5;230 +28023;Bailleau-Armenonville;1386;27;1413 +28022;Bailleau-l'Évêque;1162;32;1194 +28021;Bailleau-le-Pin;1563;30;1593 +28024;Barjouville;1712;59;1771 +28025;Barmainville;117;2;119 +28026;Baudreville;259;0;259 +28027;La Bazoche-Gouet;1224;20;1244 +28028;Bazoches-en-Dunois;258;5;263 +28029;Bazoches-les-Hautes;309;7;316 +28030;Beauche;274;9;283 +28031;Beaumont-les-Autels;394;111;505 +28032;Beauvilliers;335;4;339 +28033;Belhomert-Guéhouville;800;32;832 +28035;Berchères-les-Pierres;1000;23;1023 +28034;Berchères-Saint-Germain;845;11;856 +28036;Berchères-sur-Vesgre;849;20;869 +28037;Bérou-la-Mulotière;337;5;342 +28038;Béthonvilliers;118;5;123 +28039;Béville-le-Comte;1657;31;1688 +28040;Billancelles;324;8;332 +28041;Blandainville;273;3;276 +28045;Boissy-en-Drouais;210;6;216 +28046;Boissy-lès-Perche;498;12;510 +28047;Boisville-la-Saint-Père;712;15;727 +28049;Boncé;245;5;250 +28050;Boncourt;266;5;271 +28051;Bonneval;5055;103;5158 +28052;Bouglainval;767;14;781 +28053;Le Boullay-les-Deux-Églises;261;4;265 +28054;Le Boullay-Mivoye;486;10;496 +28055;Le Boullay-Thierry;553;5;558 +28048;La Bourdinière-Saint-Loup;725;15;740 +28056;Boutigny-Prouais;1745;39;1784 +28057;Bouville;588;8;596 +28058;Bréchamps;344;5;349 +28059;Brezolles;1816;25;1841 +28060;Briconville;249;5;254 +28061;Brou;3403;37;3440 +28062;Broué;888;15;903 +28064;Bû;1963;51;2014 +28065;Bullainville;108;5;113 +28067;Cernay;89;2;91 +28068;Challet;433;10;443 +28070;Champhol;3656;106;3762 +28071;Champrond-en-Gâtine;661;2;663 +28072;Champrond-en-Perchet;405;0;405 +28073;Champseru;333;1;334 +28074;La Chapelle-d'Aunainville;274;13;287 +28075;La Chapelle-du-Noyer;1032;181;1213 +28076;La Chapelle-Forainvilliers;201;3;204 +28077;La Chapelle-Fortin;189;5;194 +28078;Chapelle-Guillaume;185;5;190 +28079;Chapelle-Royale;307;5;312 +28080;Charbonnières;253;3;256 +28081;Charonville;315;5;320 +28082;Charpont;608;13;621 +28084;Chartainvilliers;727;9;736 +28085;Chartres;38578;1185;39763 +28086;Chassant;329;8;337 +28087;Châtaincourt;239;4;243 +28088;Châteaudun;13195;324;13519 +28089;Châteauneuf-en-Thymerais;2619;30;2649 +28090;Les Châtelets;99;4;103 +28091;Les Châtelliers-Notre-Dame;137;3;140 +28092;Châtenay;238;6;244 +28094;Chaudon;1685;25;1710 +28095;Chauffours;276;6;282 +28096;La Chaussée-d'Ivry;1156;17;1173 +28098;Cherisy;1866;27;1893 +28099;Chuisnes;1127;19;1146 +28100;Cintray;422;6;428 +28102;Clévilliers;707;9;716 +28103;Cloyes-les-Trois-Rivières;5662;126;5788 +28104;Coltainville;884;28;912 +28105;Combres;562;6;568 +28012;Commune nouvelle d'Arrou;3803;66;3869 +28106;Conie-Molitard;406;11;417 +28107;Corancez;378;9;387 +28108;Cormainville;237;8;245 +28109;Les Corvées-les-Yys;316;2;318 +28110;Le Coudray;4161;120;4281 +28111;Coudray-au-Perche;341;9;350 +28113;Coulombs;1353;18;1371 +28114;Courbehaye;137;0;137 +28116;Courville-sur-Eure;2867;44;2911 +28117;Crécy-Couvé;264;9;273 +28118;Croisilles;437;14;451 +28119;La Croix-du-Perche;163;4;167 +28120;Crucey-Villages;468;10;478 +28121;Dambron;102;0;102 +28122;Dammarie;1512;23;1535 +28123;Dampierre-sous-Brou;461;8;469 +28124;Dampierre-sur-Avre;742;18;760 +28126;Dancy;203;0;203 +28127;Dangeau;1274;20;1294 +28128;Dangers;432;7;439 +28129;Denonville;759;19;778 +28130;Digny;979;11;990 +28132;Donnemain-Saint-Mamès;684;17;701 +28134;Dreux;31044;561;31605 +28135;Droue-sur-Drouette;1241;58;1299 +28136;Écluzelles;166;5;171 +28137;Écrosnes;855;18;873 +28406;Éole-en-Beauce;1242;19;1261 +28139;Épeautrolles;186;2;188 +28140;Épernon;5551;66;5617 +28141;Ermenonville-la-Grande;319;11;330 +28142;Ermenonville-la-Petite;191;4;195 +28143;Escorpain;248;3;251 +28144;Les Étilleux;221;7;228 +28146;Faverolles;865;11;876 +28147;Favières;595;10;605 +28148;Le Favril;363;11;374 +28149;La Ferté-Vidame;700;19;719 +28151;Fessanvilliers-Mattanvilliers;176;5;181 +28153;Flacey;209;7;216 +28154;Fontaine-la-Guyon;1664;32;1696 +28155;Fontaine-les-Ribouts;208;3;211 +28156;Fontaine-Simon;924;16;940 +28157;Fontenay-sur-Conie;128;3;131 +28158;Fontenay-sur-Eure;1016;26;1042 +28159;La Framboisière;340;4;344 +28160;Francourville;833;8;841 +28161;Frazé;505;7;512 +28164;Fresnay-l'Évêque;741;10;751 +28162;Fresnay-le-Comte;326;9;335 +28163;Fresnay-le-Gilmert;202;3;205 +28166;Friaize;244;2;246 +28167;Fruncé;405;6;411 +28168;Gallardon;3669;58;3727 +28169;Garancières-en-Beauce;219;7;226 +28170;Garancières-en-Drouais;274;6;280 +28171;Garnay;876;13;889 +28172;Gas;792;16;808 +28173;Gasville-Oisème;1448;34;1482 +28175;La Gaudaine;175;4;179 +28176;Le Gault-Saint-Denis;674;12;686 +28177;Gellainville;670;12;682 +28178;Germainville;290;6;296 +28180;Gilles;522;20;542 +28182;Gohory;323;2;325 +28183;Gommerville;685;3;688 +28184;Gouillons;338;4;342 +28185;Goussainville;1292;18;1310 +28187;Guainville;655;12;667 +28188;Le Gué-de-Longroi;945;16;961 +28189;Guilleville;178;4;182 +28190;Guillonville;446;12;458 +28191;Hanches;2701;57;2758 +28192;Happonvilliers;307;4;311 +28193;Havelu;142;3;145 +28194;Houville-la-Branche;424;16;440 +28195;Houx;758;22;780 +28196;Illiers-Combray;3324;61;3385 +28197;Intréville;145;3;148 +28198;Jallans;809;31;840 +28199;Janville-en-Beauce;2567;50;2617 +28200;Jaudrais;406;5;411 +28201;Jouy;1939;41;1980 +28202;Lamblore;333;5;338 +28203;Landelles;640;6;646 +28206;Laons;687;13;700 +28207;Léthuin;229;4;233 +28208;Levainville;389;14;403 +28209;Lèves;5801;133;5934 +28210;Levesville-la-Chenard;218;2;220 +28211;Logron;585;8;593 +28212;Loigny-la-Bataille;206;8;214 +28213;Lormaye;661;9;670 +28214;La Loupe;3342;83;3425 +28215;Louville-la-Chenard;252;5;257 +28216;Louvilliers-en-Drouais;201;1;202 +28217;Louvilliers-lès-Perche;184;2;186 +28218;Lucé;15404;265;15669 +28219;Luigny;342;8;350 +28220;Luisant;6665;310;6975 +28221;Lumeau;149;8;157 +28222;Luplanté;386;8;394 +28223;Luray;1552;23;1575 +28225;Magny;653;12;665 +28226;Maillebois;922;16;938 +28227;Maintenon;4292;79;4371 +28229;Mainvilliers;11182;280;11462 +28230;Maisons;374;6;380 +28231;La Mancelière;187;3;190 +28232;Manou;597;29;626 +28233;Marboué;1147;28;1175 +28234;Marchéville;479;12;491 +28235;Marchezais;342;3;345 +28237;Marolles-les-Buis;212;4;216 +28239;Marville-Moutiers-Brûlé;976;20;996 +28240;Meaucé;543;8;551 +28242;Méréglise;100;3;103 +28243;Mérouville;218;4;222 +28245;Meslay-le-Grenet;345;6;351 +28246;Meslay-le-Vidame;522;9;531 +28247;Le Mesnil-Simon;580;15;595 +28248;Le Mesnil-Thomas;335;9;344 +28249;Mévoisins;624;18;642 +28251;Mézières-en-Drouais;1073;26;1099 +28252;Miermaigne;195;4;199 +28253;Mignières;1057;84;1141 +28254;Mittainvilliers-Vérigny;794;13;807 +28255;Moinville-la-Jeulin;170;0;170 +28256;Moléans;461;14;475 +28257;Mondonville-Saint-Jean;87;2;89 +28259;Montboissier;322;5;327 +28260;Montharville;98;5;103 +28261;Montigny-le-Chartif;615;12;627 +28263;Montigny-sur-Avre;258;6;264 +28264;Montireau;140;5;145 +28265;Montlandon;241;8;249 +28267;Montreuil;508;5;513 +28268;Morainville;22;2;24 +28269;Morancez;1836;37;1873 +28270;Moriers;224;4;228 +28271;Morvilliers;152;4;156 +28272;Mottereau;166;3;169 +28273;Moulhard;142;2;144 +28274;Moutiers;249;6;255 +28275;Néron;656;15;671 +28276;Neuvy-en-Beauce;212;8;220 +28277;Neuvy-en-Dunois;310;13;323 +28278;Nogent-le-Phaye;1472;34;1506 +28279;Nogent-le-Roi;4084;67;4151 +28280;Nogent-le-Rotrou;9715;441;10156 +28281;Nogent-sur-Eure;497;9;506 +28282;Nonvilliers-Grandhoux;427;11;438 +28283;Nottonville;304;6;310 +28284;Oinville-Saint-Liphard;276;9;285 +28285;Oinville-sous-Auneau;345;9;354 +28286;Ollé;612;15;627 +28287;Orgères-en-Beauce;1061;15;1076 +28289;Ormoy;235;5;240 +28290;Orrouer;301;10;311 +28291;Ouarville;524;16;540 +28292;Ouerre;733;15;748 +28293;Oulins;1205;27;1232 +28294;Oysonville;525;4;529 +28296;Péronville;268;4;272 +28298;Pierres;2783;56;2839 +28299;Les Pinthières;178;6;184 +28300;Poinville;142;3;145 +28301;Poisvilliers;443;6;449 +28302;Pontgouin;1096;334;1430 +28303;Poupry;112;1;113 +28304;Prasville;431;6;437 +28305;Pré-Saint-Évroult;298;5;303 +28306;Pré-Saint-Martin;199;6;205 +28308;Prudemanche;256;7;263 +28309;Prunay-le-Gillon;1075;17;1092 +28310;La Puisaye;278;6;284 +28312;Puiseux;136;2;138 +28313;Réclainville;190;1;191 +28314;Les Ressuintes;122;8;130 +28315;Revercourt;23;1;24 +28316;Rohaire;127;3;130 +28317;Roinville;561;3;564 +28319;Rouvray-Saint-Denis;434;6;440 +28321;Rouvres;823;14;837 +28322;Rueil-la-Gadelière;507;10;517 +28323;Saint-Ange-et-Torçay;287;1;288 +28324;Saint-Arnoult-des-Bois;888;23;911 +28325;Saint-Aubin-des-Bois;1016;25;1041 +28326;Saint-Avit-les-Guespières;362;4;366 +28327;Saint-Bomer;196;2;198 +28329;Saint-Christophe;159;2;161 +28333;Saint-Denis-des-Puits;139;2;141 +28334;Saint-Denis-Lanneray;2243;55;2298 +28335;Saint-Éliph;875;24;899 +28336;Saint-Éman;108;1;109 +28337;Saint-Georges-sur-Eure;2803;67;2870 +28339;Saint-Germain-le-Gaillard;345;11;356 +28341;Saint-Jean-de-Rebervilliers;241;5;246 +28342;Saint-Jean-Pierre-Fixte;259;9;268 +28343;Saint-Laurent-la-Gâtine;441;12;453 +28344;Saint-Léger-des-Aubées;266;10;276 +28346;Saint-Lubin-de-Cravant;58;3;61 +28347;Saint-Lubin-de-la-Haye;956;30;986 +28348;Saint-Lubin-des-Joncherets;3995;55;4050 +28349;Saint-Lucien;254;2;256 +28350;Saint-Luperce;896;20;916 +28351;Saint-Maixme-Hauterive;418;8;426 +28352;Saint-Martin-de-Nigelles;1560;42;1602 +28353;Saint-Maur-sur-le-Loir;413;5;418 +28354;Saint-Maurice-Saint-Germain;415;73;488 +28355;Saint-Ouen-Marchefroy;295;8;303 +28357;Saint-Piat;1050;30;1080 +28358;Saint-Prest;2031;73;2104 +28359;Saint-Rémy-sur-Avre;4010;42;4052 +28360;Saint-Sauveur-Marville;925;17;942 +28362;Saint-Victor-de-Buthon;511;13;524 +28332;Sainte-Gemme-Moronval;1093;22;1115 +28331;Saintigny;1020;20;1040 +28363;Sainville;1012;13;1025 +28364;Sancheville;806;13;819 +28365;Sandarville;408;9;417 +28366;Santeuil;320;1;321 +28367;Santilly;339;6;345 +28368;La Saucelle;194;3;197 +28369;Saulnières;709;9;718 +28370;Saumeray;491;11;502 +28371;Saussay;1092;19;1111 +28372;Senantes;582;12;594 +28373;Senonches;3087;45;3132 +28374;Serazereux;546;2;548 +28375;Serville;366;5;371 +28377;Sorel-Moussel;1804;35;1839 +28378;Souancé-au-Perche;532;11;543 +28379;Soulaires;454;10;464 +28380;Sours;1951;170;2121 +28382;Terminiers;903;15;918 +28383;Theuville;708;6;714 +28385;Le Thieulin;452;34;486 +28386;Thimert-Gâtelles;1256;22;1278 +28387;Thiron-Gardais;995;11;1006 +28388;Thivars;1059;33;1092 +28389;Thiville;342;4;346 +28390;Tillay-le-Péneux;324;6;330 +28391;Toury;2573;33;2606 +28392;Trancrainville;161;3;164 +28393;Tremblay-les-Villages;2271;65;2336 +28394;Tréon;1403;27;1430 +28395;Trizay-Coutretot-Saint-Serge;444;14;458 +28396;Trizay-lès-Bonneval;316;4;320 +28397;Umpeau;396;12;408 +28398;Unverre;1193;24;1217 +28400;Varize;196;8;204 +28401;Vaupillon;456;7;463 +28403;Ver-lès-Chartres;783;27;810 +28404;Vernouillet;12506;148;12654 +28405;Vert-en-Drouais;1091;21;1112 +28407;Vichères;304;8;312 +28408;Vierville;132;1;133 +28409;Vieuvicq;476;9;485 +28422;Les Villages Vovéens;3945;61;4006 +28410;Villampuy;306;4;310 +28411;Villars;175;1;176 +28414;Villebon;76;0;76 +28330;Villemaury;1392;34;1426 +28415;Villemeux-sur-Eure;1641;27;1668 +28417;Villiers-le-Morhier;1339;28;1367 +28418;Villiers-Saint-Orien;163;5;168 +28419;Vitray-en-Beauce;357;6;363 +28421;Voise;282;5;287 +28423;Yermenonville;597;7;604 +28424;Yèvres;1647;34;1681 +28425;Ymeray;612;12;624 +28426;Ymonville;498;9;507 +29001;Argol;991;17;1008 +29002;Arzano;1387;33;1420 +29003;Audierne;3692;65;3757 +29004;Bannalec;5659;158;5817 +29005;Baye;1149;34;1183 +29006;Bénodet;3568;65;3633 +29007;Berrien;919;31;950 +29008;Beuzec-Cap-Sizun;1001;20;1021 +29010;Bodilis;1609;35;1644 +29011;Bohars;3458;83;3541 +29012;Bolazec;205;1;206 +29013;Botmeur;215;6;221 +29014;Botsorhel;428;6;434 +29015;Bourg-Blanc;3568;53;3621 +29016;Brasparts;1024;11;1035 +29017;Brélès;875;27;902 +29018;Brennilis;444;5;449 +29019;Brest;140064;2684;142748 +29020;Briec;5630;112;5742 +29022;Camaret-sur-Mer;2543;57;2600 +29023;Carantec;3161;100;3261 +29024;Carhaix-Plouguer;7174;615;7789 +29025;Cast;1556;45;1601 +29026;Châteaulin;5214;456;5670 +29027;Châteauneuf-du-Faou;3673;102;3775 +29028;Cléden-Cap-Sizun;944;20;964 +29029;Cléden-Poher;1158;21;1179 +29030;Cléder;3779;105;3884 +29031;Clohars-Carnoët;4333;111;4444 +29032;Clohars-Fouesnant;2055;51;2106 +29033;Le Cloître-Pleyben;531;11;542 +29034;Le Cloître-Saint-Thégonnec;660;6;666 +29035;Coat-Méal;1100;19;1119 +29036;Collorec;611;7;618 +29037;Combrit;4092;133;4225 +29038;Commana;1036;27;1063 +29039;Concarneau;19050;825;19875 +29145;Confort-Meilars;879;28;907 +29040;Le Conquet;2713;59;2772 +29041;Coray;1896;30;1926 +29042;Crozon;7477;220;7697 +29043;Daoulas;1786;52;1838 +29044;Dinéault;2168;38;2206 +29045;Dirinon;2261;73;2334 +29046;Douarnenez;13902;363;14265 +29047;Le Drennec;1837;34;1871 +29048;Edern;2224;42;2266 +29049;Elliant;3271;141;3412 +29051;Ergué-Gabéric;8208;211;8419 +29053;Le Faou;1727;41;1768 +29054;La Feuillée;641;14;655 +29055;Le Folgoët;3187;77;3264 +29056;La Forest-Landerneau;1881;29;1910 +29057;La Forêt-Fouesnant;3366;119;3485 +29058;Fouesnant;9458;429;9887 +29059;Garlan;1052;33;1085 +29060;Gouesnach;2769;80;2849 +29061;Gouesnou;6116;130;6246 +29062;Gouézec;1100;34;1134 +29063;Goulien;433;7;440 +29064;Goulven;446;4;450 +29065;Gourlizon;896;16;912 +29066;Guengat;1782;29;1811 +29067;Guerlesquin;1329;41;1370 +29068;Guiclan;2490;52;2542 +29070;Guiler-sur-Goyen;529;10;539 +29069;Guilers;7981;155;8136 +29071;Guilligomarc'h;778;3;781 +29072;Guilvinec;2658;68;2726 +29073;Guimaëc;947;34;981 +29074;Guimiliau;1009;17;1026 +29075;Guipavas;14482;375;14857 +29077;Guissény;2009;42;2051 +29078;Hanvec;2025;46;2071 +29079;Henvic;1351;30;1381 +29080;Hôpital-Camfrout;2247;38;2285 +29081;Huelgoat;1449;28;1477 +29082;Île-de-Batz;457;18;475 +29083;Île-de-Sein;249;2;251 +29084;Île-Molène;141;5;146 +29085;Île-Tudy;741;17;758 +29086;Irvillac;1429;22;1451 +29087;Le Juch;713;17;730 +29089;Kergloff;880;23;903 +29090;Kerlaz;799;27;826 +29091;Kerlouan;2119;39;2158 +29093;Kernilis;1453;31;1484 +29094;Kernouës;685;14;699 +29095;Kersaint-Plabennec;1447;26;1473 +29097;Lampaul-Guimiliau;2058;51;2109 +29098;Lampaul-Plouarzel;2111;50;2161 +29099;Lampaul-Ploudalmézeau;838;22;860 +29100;Lanarvily;421;12;433 +29101;Landéda;3578;109;3687 +29102;Landeleau;937;12;949 +29103;Landerneau;15781;617;16398 +29104;Landévennec;337;6;343 +29105;Landivisiau;9132;322;9454 +29106;Landrévarzec;1841;39;1880 +29107;Landudal;877;13;890 +29108;Landudec;1436;39;1475 +29109;Landunvez;1475;36;1511 +29110;Langolen;876;18;894 +29111;Lanhouarneau;1308;24;1332 +29112;Lanildut;956;17;973 +29113;Lanmeur;2251;39;2290 +29114;Lannéanou;378;8;386 +29115;Lannédern;293;5;298 +29116;Lanneuffret;151;2;153 +29117;Lannilis;5592;114;5706 +29119;Lanrivoaré;1464;35;1499 +29120;Lanvéoc;2095;66;2161 +29122;Laz;661;15;676 +29123;Lennon;788;20;808 +29124;Lesneven;7311;228;7539 +29125;Leuhan;819;14;833 +29126;Loc-Brévalaire;202;6;208 +29128;Loc-Eguiner;402;7;409 +29130;Locmaria-Plouzané;5076;129;5205 +29131;Locmélar;471;14;485 +29132;Locquénolé;787;26;813 +29133;Locquirec;1456;42;1498 +29134;Locronan;795;27;822 +29135;Loctudy;4073;110;4183 +29136;Locunolé;1154;23;1177 +29137;Logonna-Daoulas;2124;52;2176 +29139;Lopérec;859;154;1013 +29140;Loperhet;3760;82;3842 +29141;Loqueffret;359;10;369 +29142;Lothey;459;4;463 +29143;Mahalon;957;20;977 +29144;La Martyre;751;9;760 +29146;Melgven;3356;51;3407 +29147;Mellac;3112;76;3188 +29148;Mespaul;966;17;983 +29076;Milizac-Guipronvel;4478;64;4542 +29150;Moëlan-sur-Mer;6781;140;6921 +29151;Morlaix;14559;469;15028 +29152;Motreff;703;14;717 +29153;Névez;2661;59;2720 +29155;Ouessant;835;19;854 +29156;Pencran;1970;31;2001 +29158;Penmarch;5247;114;5361 +29159;Peumerit;803;12;815 +29160;Plabennec;8436;160;8596 +29161;Pleuven;2987;79;3066 +29162;Pleyben;3627;263;3890 +29163;Pleyber-Christ;3139;77;3216 +29165;Plobannalec-Lesconil;3474;87;3561 +29166;Ploéven;518;17;535 +29167;Plogastel-Saint-Germain;1953;43;1996 +29168;Plogoff;1229;20;1249 +29169;Plogonnec;3156;74;3230 +29170;Plomelin;4171;167;4338 +29171;Plomeur;3774;81;3855 +29172;Plomodiern;2136;63;2199 +29173;Plonéis;2425;49;2474 +29174;Plonéour-Lanvern;6064;156;6220 +29175;Plonévez-du-Faou;2105;50;2155 +29176;Plonévez-Porzay;1758;44;1802 +29177;Plouarzel;3715;70;3785 +29178;Ploudalmézeau;6297;129;6426 +29179;Ploudaniel;3709;112;3821 +29180;Ploudiry;952;22;974 +29181;Plouédern;2813;67;2880 +29182;Plouégat-Guérand;1067;23;1090 +29183;Plouégat-Moysan;716;9;725 +29184;Plouénan;2510;59;2569 +29185;Plouescat;3446;82;3528 +29186;Plouezoc'h;1596;62;1658 +29187;Plougar;785;31;816 +29188;Plougasnou;2776;122;2898 +29189;Plougastel-Daoulas;13337;361;13698 +29190;Plougonvelin;4174;99;4273 +29191;Plougonven;3496;61;3557 +29192;Plougoulm;1759;45;1804 +29193;Plougourvest;1404;28;1432 +29195;Plouguerneau;6607;128;6735 +29196;Plouguin;2151;41;2192 +29197;Plouhinec;3975;118;4093 +29198;Plouider;1866;34;1900 +29199;Plouigneau;5083;182;5265 +29201;Ploumoguer;2063;37;2100 +29021;Plounéour-Brignogan-plages;1922;49;1971 +29202;Plounéour-Ménez;1246;39;1285 +29204;Plounéventer;2088;33;2121 +29206;Plounévez-Lochrist;2291;93;2384 +29205;Plounévézel;1227;26;1253 +29208;Plourin;1241;28;1269 +29207;Plourin-lès-Morlaix;4457;287;4744 +29209;Plouvien;3766;99;3865 +29210;Plouvorn;2870;73;2943 +29211;Plouyé;674;18;692 +29212;Plouzané;12822;269;13091 +29213;Plouzévédé;1766;40;1806 +29214;Plovan;682;27;709 +29215;Plozévet;2967;77;3044 +29216;Pluguffan;4109;99;4208 +29217;Pont-Aven;2801;58;2859 +29218;Pont-Croix;1580;30;1610 +29302;Pont-de-Buis-lès-Quimerch;3792;150;3942 +29220;Pont-l'Abbé;8250;399;8649 +29221;Porspoder;1810;38;1848 +29222;Port-Launay;391;7;398 +29224;Pouldergat;1211;25;1236 +29225;Pouldreuzic;2156;46;2202 +29226;Poullan-sur-Mer;1516;94;1610 +29227;Poullaouen;1500;32;1532 +29228;Primelin;702;17;719 +29229;Quéménéven;1117;34;1151 +29230;Querrien;1739;33;1772 +29232;Quimper;62985;2495;65480 +29233;Quimperlé;12057;453;12510 +29234;Rédené;2908;64;2972 +29235;Le Relecq-Kerhuon;11462;243;11705 +29236;Riec-sur-Bélon;4185;122;4307 +29237;La Roche-Maurice;1807;43;1850 +29238;Roscanvel;839;29;868 +29239;Roscoff;3404;84;3488 +29240;Rosnoën;955;26;981 +29241;Rosporden;7671;120;7791 +29243;Saint-Coulitz;437;10;447 +29244;Saint-Derrien;811;13;824 +29245;Saint-Divy;1537;21;1558 +29246;Saint-Eloy;214;5;219 +29247;Saint-Évarzec;3529;114;3643 +29248;Saint-Frégant;823;8;831 +29249;Saint-Goazec;706;9;715 +29250;Saint-Hernin;759;17;776 +29251;Saint-Jean-du-Doigt;641;12;653 +29252;Saint-Jean-Trolimon;962;27;989 +29254;Saint-Martin-des-Champs;4593;145;4738 +29255;Saint-Méen;917;19;936 +29256;Saint-Nic;773;21;794 +29257;Saint-Pabu;2074;34;2108 +29259;Saint-Pol-de-Léon;6596;234;6830 +29260;Saint-Renan;8110;189;8299 +29261;Saint-Rivoal;194;3;197 +29262;Saint-Sauveur;790;10;800 +29263;Saint-Ségal;1081;24;1105 +29264;Saint-Servais;782;12;794 +29266;Saint-Thégonnec Loc-Eguiner;3010;76;3086 +29267;Saint-Thois;716;18;734 +29268;Saint-Thonan;1821;35;1856 +29269;Saint-Thurien;1032;14;1046 +29270;Saint-Urbain;1633;35;1668 +29271;Saint-Vougay;904;18;922 +29272;Saint-Yvi;3155;68;3223 +29265;Sainte-Sève;1016;30;1046 +29273;Santec;2409;62;2471 +29274;Scaër;5380;122;5502 +29275;Scrignac;757;20;777 +29276;Sibiril;1208;27;1235 +29277;Sizun;2265;78;2343 +29278;Spézet;1808;44;1852 +29279;Taulé;2938;77;3015 +29280;Telgruc-sur-Mer;2085;59;2144 +29281;Tourch;1026;28;1054 +29282;Trébabu;352;9;361 +29284;Treffiagat;2399;100;2499 +29285;Tréflaouénan;510;7;517 +29286;Tréflévénez;243;9;252 +29287;Tréflez;958;22;980 +29288;Trégarantec;601;8;609 +29289;Trégarvan;119;6;125 +29290;Tréglonou;670;6;676 +29291;Trégourez;972;17;989 +29292;Tréguennec;318;7;325 +29293;Trégunc;7041;225;7266 +29294;Le Tréhou;633;14;647 +29295;Trémaouézan;575;9;584 +29296;Tréméoc;1346;39;1385 +29297;Tréméven;2324;43;2367 +29298;Tréogat;581;12;593 +29299;Tréouergat;341;5;346 +29300;Le Trévoux;1606;51;1657 +29301;Trézilidé;382;2;384 +30001;Aigaliers;507;13;520 +30002;Aigremont;791;13;804 +30003;Aigues-Mortes;8325;76;8401 +30004;Aigues-Vives;3337;48;3385 +30005;Aiguèze;214;3;217 +30006;Aimargues;5647;53;5700 +30007;Alès;40219;651;40870 +30008;Allègre-les-Fumades;902;16;918 +30009;Alzon;177;3;180 +30010;Anduze;3436;41;3477 +30011;Les Angles;8349;202;8551 +30012;Aramon;4238;73;4311 +30013;Argilliers;483;22;505 +30014;Arpaillargues-et-Aureillac;1009;28;1037 +30015;Arphy;171;4;175 +30016;Arre;287;10;297 +30017;Arrigas;211;2;213 +30018;Aspères;512;13;525 +30019;Aubais;2762;58;2820 +30020;Aubord;2375;44;2419 +30021;Aubussargues;323;4;327 +30022;Aujac;178;7;185 +30023;Aujargues;846;17;863 +30024;Aulas;477;7;484 +30025;Aumessas;228;3;231 +30026;Avèze;1080;32;1112 +30027;Bagard;2574;65;2639 +30028;Bagnols-sur-Cèze;18258;342;18600 +30029;Barjac;1596;24;1620 +30030;Baron;356;4;360 +30031;La Bastide-d'Engras;196;2;198 +30032;Beaucaire;15963;144;16107 +30033;Beauvoisin;4780;54;4834 +30034;Bellegarde;7129;81;7210 +30035;Belvézet;245;1;246 +30036;Bernis;3420;27;3447 +30037;Bessèges;2844;35;2879 +30038;Bez-et-Esparon;336;11;347 +30039;Bezouce;2299;32;2331 +30040;Blandas;135;2;137 +30041;Blauzac;1196;20;1216 +30042;Boisset-et-Gaujac;2545;45;2590 +30043;Boissières;565;11;576 +30044;Bonnevaux;88;0;88 +30045;Bordezac;393;4;397 +30046;Boucoiran-et-Nozières;947;14;961 +30047;Bouillargues;6328;131;6459 +30048;Bouquet;176;3;179 +30049;Bourdic;380;11;391 +30050;Bragassargues;175;5;180 +30051;Branoux-les-Taillades;1340;30;1370 +30052;Bréau-Mars;616;20;636 +30053;Brignon;771;12;783 +30055;Brouzet-lès-Alès;649;12;661 +30054;Brouzet-lès-Quissac;291;4;295 +30056;La Bruguière;328;7;335 +30057;Cabrières;1623;28;1651 +30058;La Cadière-et-Cambo;210;10;220 +30059;Le Cailar;2412;29;2441 +30060;Caissargues;4027;78;4105 +30061;La Calmette;2200;23;2223 +30062;Calvisson;5745;97;5842 +30064;Campestre-et-Luc;99;1;100 +30065;Canaules-et-Argentières;434;4;438 +30066;Cannes-et-Clairan;540;12;552 +30067;La Capelle-et-Masmolène;439;6;445 +30068;Cardet;871;21;892 +30069;Carnas;479;12;491 +30070;Carsan;685;23;708 +30071;Cassagnoles;403;2;405 +30072;Castelnau-Valence;454;10;464 +30073;Castillon-du-Gard;1684;79;1763 +30074;Causse-Bégon;20;0;20 +30075;Caveirac;4181;112;4293 +30076;Cavillargues;843;29;872 +30077;Cendras;1841;30;1871 +30079;Chambon;266;6;272 +30080;Chamborigaud;852;5;857 +30081;Chusclan;967;29;996 +30082;Clarensac;4263;98;4361 +30083;Codognan;2423;48;2471 +30084;Codolet;660;12;672 +30085;Collias;1090;15;1105 +30086;Collorgues;608;10;618 +30087;Colognac;221;6;227 +30088;Combas;628;14;642 +30089;Comps;1784;25;1809 +30090;Concoules;258;4;262 +30091;Congénies;1668;35;1703 +30092;Connaux;1674;34;1708 +30093;Conqueyrac;97;2;99 +30094;Corbès;154;1;155 +30095;Corconne;542;26;568 +30096;Cornillon;934;21;955 +30097;Courry;279;4;283 +30098;Crespian;423;4;427 +30099;Cros;249;8;257 +30100;Cruviers-Lascours;702;8;710 +30101;Deaux;648;16;664 +30102;Dions;584;11;595 +30103;Domazan;930;11;941 +30104;Domessargues;753;18;771 +30105;Dourbies;145;5;150 +30106;Durfort-et-Saint-Martin-de-Sossenac;685;18;703 +30107;Estézargues;579;12;591 +30108;L' Estréchure;161;5;166 +30109;Euzet;439;7;446 +30110;Flaux;375;9;384 +30111;Foissac;423;6;429 +30112;Fons;1506;14;1520 +30113;Fons-sur-Lussan;237;3;240 +30114;Fontanès;690;12;702 +30115;Fontarèches;263;5;268 +30116;Fournès;1085;13;1098 +30117;Fourques;2891;44;2935 +30119;Fressac;162;5;167 +30120;Gagnières;1121;14;1135 +30121;Gailhan;246;4;250 +30122;Gajan;668;22;690 +30123;Gallargues-le-Montueux;3708;75;3783 +30124;Le Garn;213;2;215 +30125;Garons;4895;49;4944 +30126;Garrigues-Sainte-Eulalie;731;20;751 +30127;Gaujac;1096;26;1122 +30128;Générac;4118;56;4174 +30129;Générargues;699;20;719 +30130;Génolhac;841;20;861 +30131;Goudargues;1100;23;1123 +30132;La Grand-Combe;5041;97;5138 +30133;Le Grau-du-Roi;8517;78;8595 +30134;Issirac;310;6;316 +30135;Jonquières-Saint-Vincent;3779;37;3816 +30136;Junas;1107;17;1124 +30137;Lamelouze;139;4;143 +30138;Langlade;2190;55;2245 +30139;Lanuéjols;357;23;380 +30140;Lasalle;1140;12;1152 +30141;Laudun-l'Ardoise;6292;117;6409 +30142;Laval-Pradel;1161;23;1184 +30143;Laval-Saint-Roman;217;5;222 +30144;Lecques;470;3;473 +30145;Lédenon;1556;24;1580 +30146;Lédignan;1462;24;1486 +30147;Lézan;1537;26;1563 +30148;Liouc;281;6;287 +30149;Lirac;904;20;924 +30150;Logrian-Florian;264;7;271 +30151;Lussan;486;7;493 +30152;Les Mages;2074;35;2109 +30153;Malons-et-Elze;125;0;125 +30154;Mandagout;401;7;408 +30155;Manduel;6814;95;6909 +30156;Marguerittes;8586;158;8744 +30158;Martignargues;424;9;433 +30159;Le Martinet;750;5;755 +30160;Maruéjols-lès-Gardon;243;4;247 +30161;Massanes;194;6;200 +30162;Massillargues-Attuech;662;16;678 +30163;Mauressargues;158;6;164 +30164;Méjannes-le-Clap;710;14;724 +30165;Méjannes-lès-Alès;1222;30;1252 +30166;Meynes;2456;152;2608 +30167;Meyrannes;825;17;842 +30168;Mialet;624;17;641 +30169;Milhaud;5636;134;5770 +30170;Molières-Cavaillac;938;33;971 +30171;Molières-sur-Cèze;1297;14;1311 +30172;Monoblet;728;13;741 +30173;Mons;1677;31;1708 +30354;Montagnac;208;4;212 +30174;Montaren-et-Saint-Médiers;1434;34;1468 +30175;Montclus;206;1;207 +30176;Montdardier;201;4;205 +30177;Monteils;656;10;666 +30178;Montfaucon;1492;37;1529 +30179;Montfrin;3189;54;3243 +30180;Montignargues;597;10;607 +30181;Montmirat;433;5;438 +30182;Montpezat;1234;19;1253 +30183;Moulézan;648;3;651 +30184;Moussac;1485;12;1497 +30185;Mus;1410;19;1429 +30186;Nages-et-Solorgues;1736;49;1785 +30187;Navacelles;325;8;333 +30188;Ners;702;13;715 +30189;Nîmes;150610;2342;152952 +30191;Orsan;1145;27;1172 +30192;Orthoux-Sérignac-Quilhan;416;7;423 +30193;Parignargues;678;4;682 +30194;Peyremale;285;2;287 +30195;Peyrolles;33;3;36 +30196;Le Pin;426;8;434 +30197;Les Plans;252;7;259 +30198;Les Plantiers;257;6;263 +30199;Pommiers;56;1;57 +30200;Pompignan;957;14;971 +30202;Pont-Saint-Esprit;10336;183;10519 +30201;Ponteils-et-Brésis;364;7;371 +30203;Portes;344;8;352 +30204;Potelières;373;9;382 +30205;Pougnadoresse;246;4;250 +30206;Poulx;3933;114;4047 +30207;Pouzilhac;713;6;719 +30208;Puechredon;40;0;40 +30209;Pujaut;4136;138;4274 +30210;Quissac;3216;35;3251 +30211;Redessan;4115;57;4172 +30212;Remoulins;2281;42;2323 +30213;Revens;21;0;21 +30214;Ribaute-les-Tavernes;2209;42;2251 +30215;Rivières;362;3;365 +30216;Robiac-Rochessadoule;840;15;855 +30217;Rochefort-du-Gard;7532;177;7709 +30218;Rochegude;252;3;255 +30356;Rodilhan;2878;197;3075 +30219;Rogues;107;2;109 +30222;La Roque-sur-Cèze;184;4;188 +30220;Roquedur;257;7;264 +30221;Roquemaure;5481;65;5546 +30223;Rousson;4106;71;4177 +30224;La Rouvière;598;14;612 +30225;Sabran;1674;51;1725 +30226;Saint-Alexandre;1232;25;1257 +30227;Saint-Ambroix;3162;39;3201 +30232;Saint-André-d'Olérargues;429;14;443 +30229;Saint-André-de-Majencoules;592;16;608 +30230;Saint-André-de-Roquepertuis;594;9;603 +30231;Saint-André-de-Valborgne;382;11;393 +30233;Saint-Bauzély;649;11;660 +30234;Saint-Bénézet;274;7;281 +30236;Saint-Bonnet-de-Salendrinque;120;3;123 +30235;Saint-Bonnet-du-Gard;835;11;846 +30237;Saint-Brès;652;12;664 +30238;Saint-Bresson;54;2;56 +30240;Saint-Césaire-de-Gauzignan;382;5;387 +30241;Saint-Chaptes;1865;29;1894 +30242;Saint-Christol-de-Rodières;160;2;162 +30243;Saint-Christol-lez-Alès;7030;189;7219 +30244;Saint-Clément;379;6;385 +30245;Saint-Côme-et-Maruéjols;790;14;804 +30247;Saint-Denis;294;9;303 +30248;Saint-Dézéry;450;4;454 +30249;Saint-Dionisy;1039;13;1052 +30250;Saint-Étienne-de-l'Olm;388;11;399 +30251;Saint-Étienne-des-Sorts;557;12;569 +30252;Saint-Félix-de-Pallières;252;7;259 +30253;Saint-Florent-sur-Auzonnet;1173;16;1189 +30254;Saint-Geniès-de-Comolas;1969;40;2009 +30255;Saint-Geniès-de-Malgoirès;3007;31;3038 +30256;Saint-Gervais;720;16;736 +30257;Saint-Gervasy;1899;27;1926 +30258;Saint-Gilles;13607;104;13711 +30260;Saint-Hilaire-d'Ozilhan;1069;21;1090 +30259;Saint-Hilaire-de-Brethmas;4313;106;4419 +30261;Saint-Hippolyte-de-Caton;213;4;217 +30262;Saint-Hippolyte-de-Montaigu;260;8;268 +30263;Saint-Hippolyte-du-Fort;3939;104;4043 +30264;Saint-Jean-de-Ceyrargues;164;1;165 +30265;Saint-Jean-de-Crieulon;246;2;248 +30266;Saint-Jean-de-Maruéjols-et-Avéjan;920;11;931 +30267;Saint-Jean-de-Serres;521;11;532 +30268;Saint-Jean-de-Valériscle;669;10;679 +30269;Saint-Jean-du-Gard;2433;171;2604 +30270;Saint-Jean-du-Pin;1511;39;1550 +30271;Saint-Julien-de-Cassagnas;698;15;713 +30272;Saint-Julien-de-la-Nef;141;6;147 +30273;Saint-Julien-de-Peyrolas;1402;26;1428 +30274;Saint-Julien-les-Rosiers;3348;62;3410 +30275;Saint-Just-et-Vacquières;302;2;304 +30276;Saint-Laurent-d'Aigouze;3474;42;3516 +30277;Saint-Laurent-de-Carnols;496;9;505 +30278;Saint-Laurent-des-Arbres;3072;36;3108 +30279;Saint-Laurent-la-Vernède;681;11;692 +30280;Saint-Laurent-le-Minier;341;11;352 +30281;Saint-Mamert-du-Gard;1634;21;1655 +30282;Saint-Marcel-de-Careiret;845;17;862 +30283;Saint-Martial;179;3;182 +30284;Saint-Martin-de-Valgalgues;4419;61;4480 +30285;Saint-Maurice-de-Cazevieille;727;8;735 +30286;Saint-Maximin;746;18;764 +30287;Saint-Michel-d'Euzet;636;12;648 +30288;Saint-Nazaire;1229;19;1248 +30289;Saint-Nazaire-des-Gardies;83;2;85 +30291;Saint-Paul-la-Coste;285;6;291 +30355;Saint-Paul-les-Fonts;1031;21;1052 +30290;Saint-Paulet-de-Caisson;1810;43;1853 +30292;Saint-Pons-la-Calm;438;10;448 +30293;Saint-Privat-de-Champclos;344;5;349 +30294;Saint-Privat-des-Vieux;5182;127;5309 +30295;Saint-Quentin-la-Poterie;3054;63;3117 +30296;Saint-Roman-de-Codières;157;15;172 +30297;Saint-Sauveur-Camprieu;245;14;259 +30298;Saint-Sébastien-d'Aigrefeuille;500;20;520 +30299;Saint-Siffret;1067;36;1103 +30300;Saint-Théodorit;532;6;538 +30303;Saint-Victor-de-Malcap;833;21;854 +30301;Saint-Victor-des-Oules;306;4;310 +30302;Saint-Victor-la-Coste;2073;42;2115 +30228;Sainte-Anastasie;1686;27;1713 +30239;Sainte-Cécile-d'Andorge;586;3;589 +30246;Sainte-Croix-de-Caderle;113;7;120 +30304;Salazac;184;3;187 +30305;Salindres;3494;41;3535 +30306;Salinelles;573;8;581 +30307;Les Salles-du-Gardon;2600;26;2626 +30308;Sanilhac-Sagriès;780;51;831 +30309;Sardan;300;1;301 +30310;Saumane;276;6;282 +30311;Sauve;1928;22;1950 +30312;Sauveterre;2036;48;2084 +30313;Sauzet;747;7;754 +30314;Savignargues;239;4;243 +30315;Saze;2037;39;2076 +30316;Sénéchas;247;8;255 +30317;Sernhac;1755;23;1778 +30318;Servas;209;4;213 +30319;Serviers-et-Labaume;604;23;627 +30320;Seynes;161;2;163 +30321;Sommières;4917;62;4979 +30322;Soudorgues;275;7;282 +30323;Soustelle;123;3;126 +30324;Souvignargues;871;15;886 +30325;Sumène;1549;42;1591 +30326;Tavel;1979;35;2014 +30327;Tharaux;56;2;58 +30328;Théziers;1039;18;1057 +30329;Thoiras;436;16;452 +30330;Tornac;904;26;930 +30331;Tresques;1806;50;1856 +30332;Trèves;128;1;129 +30333;Uchaud;4315;41;4356 +30334;Uzès;8454;359;8813 +30335;Vabres;121;4;125 +30339;Val-d'Aigoual;1431;20;1451 +30336;Vallabrègues;1392;19;1411 +30337;Vallabrix;432;5;437 +30338;Vallérargues;140;4;144 +30340;Valliguières;584;11;595 +30341;Vauvert;11608;134;11742 +30342;Vénéjan;1246;41;1287 +30343;Verfeuil;600;7;607 +30344;Vergèze;5188;79;5267 +30345;La Vernarède;336;2;338 +30346;Vers-Pont-du-Gard;1850;35;1885 +30347;Vestric-et-Candiac;1406;17;1423 +30348;Vézénobres;1774;97;1871 +30349;Vic-le-Fesq;522;4;526 +30350;Le Vigan;3820;124;3944 +30351;Villeneuve-lès-Avignon;11698;405;12103 +30352;Villevieille;1709;44;1753 +30353;Vissec;60;1;61 +31001;Agassac;118;3;121 +31002;Aignes;245;6;251 +31003;Aigrefeuille;1275;37;1312 +31005;Alan;305;8;313 +31006;Albiac;210;5;215 +31007;Ambax;67;0;67 +31008;Anan;243;7;250 +31009;Antichan-de-Frontignes;157;3;160 +31010;Antignac;116;5;121 +31011;Arbas;263;6;269 +31012;Arbon;102;1;103 +31013;Ardiège;364;11;375 +31014;Arguenos;72;1;73 +31015;Argut-Dessous;23;1;24 +31017;Arlos;100;1;101 +31018;Arnaud-Guilhem;231;3;234 +31019;Artigue;30;1;31 +31020;Aspet;879;72;951 +31021;Aspret-Sarrat;136;5;141 +31022;Aucamville;8408;69;8477 +31023;Aulon;309;10;319 +31024;Auragne;427;5;432 +31025;Aureville;899;14;913 +31026;Auriac-sur-Vendinelle;1035;13;1048 +31027;Auribail;204;5;209 +31028;Aurignac;1193;72;1265 +31029;Aurin;332;6;338 +31030;Ausseing;72;5;77 +31031;Ausson;586;15;601 +31032;Aussonne;6984;73;7057 +31033;Auterive;9752;98;9850 +31034;Auzas;239;10;249 +31035;Auzeville-Tolosane;4126;249;4375 +31036;Auzielle;1500;45;1545 +31037;Avignonet-Lauragais;1534;12;1546 +31004;Ayguesvives;2655;49;2704 +31038;Azas;664;16;680 +31039;Bachas;71;1;72 +31040;Bachos;38;1;39 +31041;Bagiry;112;2;114 +31042;Bagnères-de-Luchon;2312;143;2455 +31043;Balesta;148;6;154 +31044;Balma;16568;310;16878 +31045;Barbazan;490;10;500 +31046;Baren;12;0;12 +31047;Bax;89;1;90 +31048;Baziège;3346;57;3403 +31049;Bazus;553;15;568 +31050;Beauchalot;640;9;649 +31051;Beaufort;462;6;468 +31052;Beaumont-sur-Lèze;1557;31;1588 +31053;Beaupuy;1340;28;1368 +31054;Beauteville;175;1;176 +31055;Beauville;170;3;173 +31056;Beauzelle;6387;76;6463 +31057;Belberaud;1503;51;1554 +31058;Belbèze-de-Lauragais;123;1;124 +31059;Belbèze-en-Comminges;113;6;119 +31060;Bélesta-en-Lauragais;115;5;120 +31061;Bellegarde-Sainte-Marie;192;12;204 +31062;Bellesserre;110;3;113 +31063;Benque;162;2;164 +31064;Benque-Dessous-et-Dessus;25;0;25 +31065;Bérat;3016;59;3075 +31066;Bessières;4073;59;4132 +31067;Bezins-Garraux;44;0;44 +31068;Billière;22;0;22 +31590;Binos;43;0;43 +31069;Blagnac;24517;492;25009 +31070;Blajan;504;9;513 +31071;Bois-de-la-Pierre;429;3;432 +31072;Boissède;70;2;72 +31073;Bondigoux;537;12;549 +31074;Bonrepos-Riquet;293;7;300 +31075;Bonrepos-sur-Aussonnelle;1187;22;1209 +31076;Bordes-de-Rivière;483;12;495 +31077;Le Born;548;14;562 +31078;Boudrac;144;2;146 +31079;Bouloc;4659;84;4743 +31080;Boulogne-sur-Gesse;1612;48;1660 +31081;Bourg-d'Oueil;6;0;6 +31082;Bourg-Saint-Bernard;1038;19;1057 +31083;Boussan;239;2;241 +31084;Boussens;1074;23;1097 +31085;Boutx;244;3;247 +31086;Bouzin;96;4;100 +31087;Bragayrac;326;2;328 +31088;Brax;2811;101;2912 +31089;Bretx;663;6;669 +31090;Brignemont;387;5;392 +31091;Bruguières;5832;84;5916 +31092;Burgalays;123;6;129 +31093;Le Burgaud;979;8;987 +31094;Buzet-sur-Tarn;2767;49;2816 +31095;Cabanac-Cazaux;126;1;127 +31096;Cabanac-Séguenville;170;1;171 +31097;Le Cabanial;454;13;467 +31098;Cadours;1086;18;1104 +31099;Caignac;356;4;360 +31100;Calmont;2371;31;2402 +31101;Cambernard;466;4;470 +31102;Cambiac;215;3;218 +31103;Canens;60;0;60 +31104;Capens;662;13;675 +31105;Caragoudes;223;8;231 +31106;Caraman;2500;45;2545 +31107;Carbonne;5712;104;5816 +31108;Cardeilhac;267;2;269 +31109;Cassagnabère-Tournas;461;3;464 +31110;Cassagne;634;13;647 +31111;Castagnac;288;4;292 +31112;Castagnède;189;4;193 +31113;Castanet-Tolosan;13529;197;13726 +31114;Castelbiague;251;2;253 +31115;Castelgaillard;61;1;62 +31116;Castelginest;10467;115;10582 +31117;Castelmaurou;4273;96;4369 +31118;Castelnau-d'Estrétefonds;6334;64;6398 +31119;Castelnau-Picampeau;215;5;220 +31120;Le Castéra;736;18;754 +31121;Castéra-Vignoles;64;1;65 +31122;Casties-Labrande;117;2;119 +31123;Castillon-de-Larboust;63;1;64 +31124;Castillon-de-Saint-Martory;382;9;391 +31125;Cathervielle;36;0;36 +31126;Caubiac;382;10;392 +31127;Caubous;4;1;5 +31128;Caujac;837;12;849 +31593;Cazac;88;0;88 +31130;Cazaril-Tambourès;88;3;91 +31129;Cazarilh-Laspènes;24;6;30 +31131;Cazaunous;72;0;72 +31132;Cazaux-Layrisse;60;1;61 +31133;Cazeaux-de-Larboust;97;4;101 +31134;Cazeneuve-Montaut;74;0;74 +31135;Cazères;4889;65;4954 +31136;Cépet;1878;21;1899 +31137;Cessales;167;0;167 +31138;Charlas;242;6;248 +31139;Chaum;189;4;193 +31140;Chein-Dessus;182;7;189 +31141;Ciadoux;232;1;233 +31142;Cier-de-Luchon;248;7;255 +31143;Cier-de-Rivière;279;7;286 +31144;Cierp-Gaud;734;12;746 +31145;Cintegabelle;2904;65;2969 +31146;Cirès;13;0;13 +31147;Clarac;630;11;641 +31148;Clermont-le-Fort;506;27;533 +31149;Colomiers;38951;474;39425 +31150;Cornebarrieu;6592;93;6685 +31151;Corronsac;813;22;835 +31152;Coueilles;94;5;99 +31153;Couladère;425;12;437 +31155;Couret;239;2;241 +31156;Cox;341;1;342 +31157;Cugnaux;17974;223;18197 +31158;Cuguron;185;4;189 +31159;Le Cuing;465;5;470 +31160;Daux;2361;26;2387 +31161;Deyme;1192;21;1213 +31162;Donneville;1009;75;1084 +31163;Drémil-Lafage;2652;79;2731 +31164;Drudas;216;6;222 +31165;Eaunes;6162;94;6256 +31166;Empeaux;256;5;261 +31167;Encausse-les-Thermes;694;14;708 +31168;Eoux;119;0;119 +31169;Escalquens;6660;153;6813 +31170;Escanecrabe;246;10;256 +31591;Escoulis;80;0;80 +31171;Espanès;325;4;329 +31172;Esparron;57;2;59 +31173;Esperce;259;3;262 +31174;Estadens;528;4;532 +31175;Estancarbon;606;10;616 +31176;Esténos;187;5;192 +31177;Eup;133;2;135 +31178;Fabas;201;3;204 +31179;Le Faget;343;6;349 +31180;Falga;124;6;130 +31181;Le Fauga;2048;27;2075 +31182;Fenouillet;5161;58;5219 +31183;Figarol;305;9;314 +31184;Flourens;1963;38;2001 +31185;Folcarde;118;1;119 +31186;Fonbeauzard;2973;30;3003 +31187;Fonsorbes;11743;272;12015 +31188;Fontenilles;5935;124;6059 +31189;Forgues;212;4;216 +31190;Fos;237;0;237 +31191;Fougaron;95;2;97 +31192;Fourquevaux;771;21;792 +31193;Le Fousseret;1897;30;1927 +31194;Francarville;174;2;176 +31195;Francazal;29;0;29 +31196;Francon;243;3;246 +31197;Franquevielle;332;8;340 +31198;Le Fréchet;103;3;106 +31199;Fronsac;210;10;220 +31200;Frontignan-de-Comminges;77;4;81 +31201;Frontignan-Savès;70;0;70 +31202;Fronton;6079;143;6222 +31203;Frouzins;9022;155;9177 +31204;Fustignac;80;3;83 +31205;Gagnac-sur-Garonne;3110;27;3137 +31206;Gaillac-Toulza;1265;13;1278 +31207;Galié;82;6;88 +31208;Ganties;327;5;332 +31209;Garac;154;4;158 +31210;Gardouch;1268;23;1291 +31211;Gargas;685;9;694 +31212;Garidech;1768;12;1780 +31213;Garin;145;3;148 +31215;Gauré;494;16;510 +31216;Gémil;270;10;280 +31217;Génos;70;1;71 +31218;Gensac-de-Boulogne;125;4;129 +31219;Gensac-sur-Garonne;442;3;445 +31220;Gibel;361;6;367 +31221;Gouaux-de-Larboust;67;0;67 +31222;Gouaux-de-Luchon;46;0;46 +31223;Goudex;47;1;48 +31224;Gourdan-Polignan;1203;186;1389 +31225;Goutevernisse;187;3;190 +31226;Gouzens;81;10;91 +31227;Goyrans;843;36;879 +31228;Gragnague;1817;39;1856 +31229;Gratens;684;18;702 +31230;Gratentour;4158;92;4250 +31231;Grazac;587;8;595 +31232;Grenade;8847;99;8946 +31233;Grépiac;982;26;1008 +31234;Le Grès;433;8;441 +31235;Guran;44;1;45 +31236;Herran;75;1;76 +31237;His;223;30;253 +31238;Huos;489;11;500 +31239;L' Isle-en-Dodon;1631;23;1654 +31240;Issus;595;10;605 +31241;Izaut-de-l'Hôtel;314;5;319 +31242;Jurvielle;20;2;22 +31243;Juzes;85;5;90 +31245;Juzet-d'Izaut;188;5;193 +31244;Juzet-de-Luchon;369;16;385 +31246;Labarthe-Inard;852;13;865 +31247;Labarthe-Rivière;1332;29;1361 +31248;Labarthe-sur-Lèze;6178;101;6279 +31249;Labastide-Beauvoir;1272;26;1298 +31250;Labastide-Clermont;664;8;672 +31251;Labastide-Paumès;146;1;147 +31252;Labastide-Saint-Sernin;1909;21;1930 +31253;Labastidette;2563;33;2596 +31254;Labège;4044;147;4191 +31255;Labroquère;323;16;339 +31256;Labruyère-Dorsa;284;6;290 +31258;Lacaugne;218;5;223 +31259;Lacroix-Falgarde;2068;48;2116 +31260;Laffite-Toupière;103;1;104 +31261;Lafitte-Vigordane;1188;18;1206 +31262;Lagarde;409;11;420 +31263;Lagardelle-sur-Lèze;3045;45;3090 +31264;Lagrâce-Dieu;571;7;578 +31265;Lagraulet-Saint-Nicolas;251;4;255 +31266;Lahage;208;1;209 +31267;Lahitère;60;0;60 +31268;Lalouret-Laffiteau;134;3;137 +31269;Lamasquère;1462;14;1476 +31270;Landorthe;991;33;1024 +31271;Lanta;2070;40;2110 +31272;Lapeyrère;68;1;69 +31273;Lapeyrouse-Fossat;2821;58;2879 +31274;Larcan;177;4;181 +31275;Laréole;171;5;176 +31592;Larra;1891;30;1921 +31276;Larroque;292;5;297 +31277;Lasserre-Pradère;1522;42;1564 +31278;Latoue;323;5;328 +31279;Latour;77;1;78 +31280;Latrape;364;13;377 +31281;Launac;1382;34;1416 +31282;Launaguet;8880;108;8988 +31283;Lautignac;265;1;266 +31284;Lauzerville;1588;52;1640 +31285;Lavalette;738;13;751 +31286;Lavelanet-de-Comminges;625;8;633 +31287;Lavernose-Lacasse;3050;77;3127 +31288;Layrac-sur-Tarn;322;9;331 +31289;Lécussan;268;3;271 +31290;Lège;43;1;44 +31291;Léguevin;9196;248;9444 +31292;Lescuns;72;0;72 +31293;Lespinasse;2737;20;2757 +31294;Lespiteau;103;1;104 +31295;Lespugue;81;0;81 +31296;Lestelle-de-Saint-Martory;440;8;448 +31297;Lévignac;2113;39;2152 +31299;Lherm;3678;79;3757 +31300;Lieoux;126;0;126 +31301;Lilhac;130;1;131 +31302;Lodes;292;7;299 +31303;Longages;3082;34;3116 +31304;Loubens-Lauragais;461;10;471 +31305;Loudet;196;6;202 +31306;Lourde;92;0;92 +31308;Luscan;55;0;55 +31309;Lussan-Adeilhac;227;2;229 +31310;Lux;344;5;349 +31311;La Magdelaine-sur-Tarn;1171;21;1192 +31312;Mailholas;34;0;34 +31313;Malvezie;115;2;117 +31314;Mancioux;409;4;413 +31315;Mane;963;40;1003 +31316;Marignac;484;8;492 +31317;Marignac-Lasclares;478;19;497 +31318;Marignac-Laspeyres;218;6;224 +31319;Marliac;145;1;146 +31320;Marquefave;967;53;1020 +31321;Marsoulas;123;8;131 +31322;Martisserre;61;2;63 +31323;Martres-de-Rivière;357;11;368 +31324;Martres-Tolosane;2383;42;2425 +31325;Mascarville;179;12;191 +31326;Massabrac;89;0;89 +31327;Mauran;233;1;234 +31328;Mauremont;323;10;333 +31329;Maurens;206;2;208 +31330;Mauressac;518;5;523 +31331;Maureville;304;12;316 +31332;Mauvaisin;233;4;237 +31333;Mauvezin;93;2;95 +31334;Mauzac;1281;23;1304 +31335;Mayrègne;25;2;27 +31336;Mazères-sur-Salat;621;12;633 +31337;Melles;89;1;90 +31338;Menville;768;23;791 +31339;Mérenvielle;486;6;492 +31340;Mervilla;269;8;277 +31341;Merville;5615;95;5710 +31342;Milhas;177;0;177 +31343;Mirambeau;63;0;63 +31344;Miramont-de-Comminges;780;10;790 +31345;Miremont;2494;32;2526 +31346;Mirepoix-sur-Tarn;1014;13;1027 +31347;Molas;167;4;171 +31348;Moncaup;39;0;39 +31349;Mondavezan;905;18;923 +31350;Mondilhan;92;1;93 +31351;Mondonville;4546;63;4609 +31352;Mondouzil;235;6;241 +31353;Monès;96;1;97 +31354;Monestrol;62;0;62 +31355;Mons;1780;52;1832 +31369;Mont-de-Galié;42;1;43 +31356;Montaigut-sur-Save;1682;42;1724 +31357;Montastruc-de-Salies;288;2;290 +31358;Montastruc-la-Conseillère;3430;95;3525 +31359;Montastruc-Savès;77;1;78 +31360;Montauban-de-Luchon;496;7;503 +31361;Montaut;506;4;510 +31362;Montberaud;211;4;215 +31363;Montbernard;222;5;227 +31364;Montberon;2925;62;2987 +31365;Montbrun-Bocage;476;11;487 +31366;Montbrun-Lauragais;611;20;631 +31367;Montclar-de-Comminges;84;5;89 +31368;Montclar-Lauragais;246;3;249 +31370;Montégut-Bourjac;135;1;136 +31371;Montégut-Lauragais;442;15;457 +31372;Montespan;455;6;461 +31373;Montesquieu-Guittaut;176;2;178 +31374;Montesquieu-Lauragais;977;13;990 +31375;Montesquieu-Volvestre;3032;69;3101 +31376;Montgaillard-de-Salies;103;3;106 +31377;Montgaillard-Lauragais;743;18;761 +31378;Montgaillard-sur-Save;84;2;86 +31379;Montgazin;197;5;202 +31380;Montgeard;487;8;495 +31381;Montgiscard;2430;57;2487 +31382;Montgras;106;1;107 +31383;Montjoire;1274;25;1299 +31384;Montlaur;1576;32;1608 +31385;Montmaurin;210;6;216 +31386;Montoulieu-Saint-Bernard;213;6;219 +31387;Montoussin;132;0;132 +31388;Montpitol;387;12;399 +31389;Montrabé;4106;77;4183 +31390;Montréjeau;2796;31;2827 +31391;Montsaunès;445;31;476 +31392;Mourvilles-Basses;75;0;75 +31393;Mourvilles-Hautes;169;14;183 +31394;Moustajon;136;3;139 +31395;Muret;24945;543;25488 +31396;Nailloux;3873;43;3916 +31397;Nénigan;65;0;65 +31398;Nizan-Gesse;87;1;88 +31399;Noé;2897;64;2961 +31400;Nogaret;83;0;83 +31401;Noueilles;401;4;405 +31402;Odars;872;31;903 +31403;Ondes;733;129;862 +31404;Oô;92;4;96 +31405;Ore;101;1;102 +31406;Palaminy;808;11;819 +31407;Paulhac;1236;29;1265 +31408;Payssous;90;3;93 +31409;Péchabou;2330;64;2394 +31410;Pechbonnieu;4425;86;4511 +31411;Pechbusque;882;21;903 +31412;Péguilhan;286;10;296 +31413;Pelleport;515;12;527 +31414;Peyrissas;85;2;87 +31415;Peyrouzet;84;2;86 +31416;Peyssies;570;6;576 +31417;Pibrac;8459;253;8712 +31418;Pin-Balma;903;18;921 +31419;Le Pin-Murelet;176;4;180 +31421;Pins-Justaret;4410;71;4481 +31420;Pinsaguel;2771;37;2808 +31422;Plagne;97;0;97 +31423;Plagnole;305;3;308 +31424;Plaisance-du-Touch;18715;360;19075 +31425;Le Plan;447;7;454 +31426;Pointis-de-Rivière;840;11;851 +31427;Pointis-Inard;924;14;938 +31428;Polastron;54;2;56 +31429;Pompertuzat;2312;38;2350 +31430;Ponlat-Taillebourg;619;16;635 +31431;Portet-d'Aspet;64;1;65 +31432;Portet-de-Luchon;39;4;43 +31433;Portet-sur-Garonne;9721;120;9841 +31434;Poubeau;76;4;80 +31435;Poucharramet;880;13;893 +31436;Pouy-de-Touges;407;10;417 +31437;Pouze;88;4;92 +31439;Préserville;707;15;722 +31440;Proupiary;73;1;74 +31441;Prunet;150;2;152 +31442;Puydaniel;518;8;526 +31443;Puymaurin;296;3;299 +31444;Puysségur;147;0;147 +31445;Quint-Fonsegrives;5674;113;5787 +31446;Ramonville-Saint-Agne;14388;337;14725 +31447;Razecueillé;37;0;37 +31448;Rebigue;478;25;503 +31449;Régades;133;4;137 +31450;Renneville;550;12;562 +31451;Revel;9582;311;9893 +31452;Rieucazé;54;0;54 +31453;Rieumajou;136;2;138 +31454;Rieumes;3509;83;3592 +31455;Rieux-Volvestre;2583;52;2635 +31456;Riolas;48;1;49 +31457;Roquefort-sur-Garonne;794;12;806 +31458;Roques;4550;52;4602 +31459;Roquesérière;689;17;706 +31460;Roquettes;4049;61;4110 +31461;Rouède;292;3;295 +31462;Rouffiac-Tolosan;1944;42;1986 +31463;Roumens;242;6;248 +31464;Sabonnères;315;4;319 +31465;Saccourvielle;15;0;15 +31466;Saiguède;790;21;811 +31467;Saint-Alban;6150;50;6200 +31468;Saint-André;223;8;231 +31469;Saint-Araille;152;5;157 +31470;Saint-Aventin;80;4;84 +31471;Saint-Béat-Lez;382;8;390 +31472;Saint-Bertrand-de-Comminges;244;6;250 +31473;Saint-Cézert;434;1;435 +31474;Saint-Christaud;244;4;248 +31475;Saint-Clar-de-Rivière;1338;25;1363 +31476;Saint-Élix-le-Château;883;19;902 +31477;Saint-Élix-Séglan;42;0;42 +31478;Saint-Félix-Lauragais;1271;34;1305 +31479;Saint-Ferréol-de-Comminges;58;1;59 +31482;Saint-Frajou;215;4;219 +31483;Saint-Gaudens;11517;565;12082 +31484;Saint-Geniès-Bellevue;2466;62;2528 +31485;Saint-Germier;111;3;114 +31486;Saint-Hilaire;1219;18;1237 +31487;Saint-Ignan;226;5;231 +31488;Saint-Jean;10694;139;10833 +31489;Saint-Jean-Lherm;371;11;382 +31490;Saint-Jory;5797;60;5857 +31491;Saint-Julia;412;13;425 +31492;Saint-Julien-sur-Garonne;553;4;557 +31493;Saint-Lary-Boujean;141;2;143 +31494;Saint-Laurent;181;1;182 +31495;Saint-Léon;1268;13;1281 +31497;Saint-Loup-Cammas;2164;45;2209 +31498;Saint-Loup-en-Comminges;36;0;36 +31499;Saint-Lys;9470;151;9621 +31500;Saint-Mamet;557;19;576 +31501;Saint-Marcel-Paulel;404;6;410 +31502;Saint-Marcet;360;9;369 +31503;Saint-Martory;981;11;992 +31504;Saint-Médard;221;11;232 +31505;Saint-Michel;318;6;324 +31506;Saint-Orens-de-Gameville;11830;204;12034 +31508;Saint-Paul-d'Oueil;34;0;34 +31507;Saint-Paul-sur-Save;1625;24;1649 +31509;Saint-Pé-d'Ardet;148;1;149 +31510;Saint-Pé-Delbosc;134;0;134 +31511;Saint-Pierre;239;8;247 +31512;Saint-Pierre-de-Lages;886;18;904 +31513;Saint-Plancard;364;6;370 +31514;Saint-Rome;51;2;53 +31515;Saint-Rustice;460;9;469 +31516;Saint-Sauveur;1766;16;1782 +31517;Saint-Sulpice-sur-Lèze;2389;42;2431 +31518;Saint-Thomas;573;15;588 +31519;Saint-Vincent;192;8;200 +31480;Sainte-Foy-d'Aigrefeuille;2011;61;2072 +31481;Sainte-Foy-de-Peyrolières;2074;47;2121 +31496;Sainte-Livrade;271;13;284 +31520;Sajas;125;3;128 +31521;Saleich;341;8;349 +31522;Salerm;56;2;58 +31523;Salies-du-Salat;1788;103;1891 +31524;Salles-et-Pratviel;133;2;135 +31525;Salles-sur-Garonne;573;15;588 +31527;La Salvetat-Lauragais;143;3;146 +31526;La Salvetat-Saint-Gilles;8321;192;8513 +31528;Saman;130;4;134 +31529;Samouillan;124;2;126 +31530;Sana;258;5;263 +31531;Sarrecave;78;0;78 +31532;Sarremezan;97;3;100 +31533;Saubens;2225;52;2277 +31534;Saussens;209;0;209 +31535;Sauveterre-de-Comminges;634;8;642 +31536;Saux-et-Pomarède;272;9;281 +31537;Savarthès;173;5;178 +31538;Savères;218;4;222 +31539;Sédeilhac;61;2;63 +31540;Ségreville;297;7;304 +31541;Seilh;3268;75;3343 +31542;Seilhan;207;3;210 +31543;Sénarens;104;2;106 +31544;Sengouagnet;206;4;210 +31545;Sepx;224;4;228 +31546;Seyre;133;3;136 +31547;Seysses;9055;119;9174 +31548;Signac;48;0;48 +31549;Sode;18;0;18 +31550;Soueich;531;10;541 +31551;Tarabel;460;7;467 +31552;Terrebasse;137;4;141 +31553;Thil;1176;28;1204 +31554;Touille;246;1;247 +31555;Toulouse;479553;5256;484809 +31557;Tournefeuille;26962;567;27529 +31556;Les Tourreilles;384;9;393 +31558;Toutens;335;4;339 +31559;Trébons-de-Luchon;5;0;5 +31560;Trébons-sur-la-Grasse;450;8;458 +31561;L' Union;11715;185;11900 +31562;Urau;123;1;124 +31563;Vacquiers;1307;35;1342 +31564;Valcabrère;143;1;144 +31565;Valentine;877;15;892 +31566;Vallègue;524;4;528 +31567;Vallesvilles;418;6;424 +31568;Varennes;271;4;275 +31569;Vaudreuille;379;10;389 +31570;Vaux;295;5;300 +31571;Vendine;284;4;288 +31572;Venerque;2548;80;2628 +31573;Verfeil;3595;70;3665 +31574;Vernet;2871;32;2903 +31575;Vieille-Toulouse;1169;37;1206 +31576;Vieillevigne;339;7;346 +31577;Vignaux;135;0;135 +31578;Vigoulet-Auzil;904;30;934 +31579;Villariès;792;13;805 +31580;Villate;920;19;939 +31581;Villaudric;1545;27;1572 +31582;Villefranche-de-Lauragais;4519;61;4580 +31583;Villematier;1053;24;1077 +31584;Villemur-sur-Tarn;5888;105;5993 +31585;Villeneuve-de-Rivière;1794;42;1836 +31586;Villeneuve-Lécussan;556;4;560 +31587;Villeneuve-lès-Bouloc;1622;21;1643 +31588;Villeneuve-Tolosane;9720;118;9838 +31589;Villenouvelle;1391;18;1409 +32001;Aignan;734;71;805 +32002;Ansan;78;6;84 +32003;Antras;47;2;49 +32004;Arblade-le-Bas;147;2;149 +32005;Arblade-le-Haut;309;5;314 +32007;Ardizas;216;5;221 +32008;Armentieux;76;0;76 +32009;Armous-et-Cau;86;5;91 +32010;Arrouède;110;0;110 +32012;Aubiet;1083;34;1117 +32013;Auch;21935;1132;23067 +32014;Augnax;109;5;114 +32015;Aujan-Mournède;89;1;90 +32016;Auradé;671;16;687 +32017;Aurensan;134;5;139 +32018;Aurimont;205;2;207 +32468;Aussos;81;1;82 +32019;Auterive;520;17;537 +32020;Aux-Aussat;275;8;283 +32021;Avensac;77;1;78 +32022;Avéron-Bergelle;143;6;149 +32023;Avezan;107;3;110 +32024;Ayguetinte;161;3;164 +32025;Ayzieu;159;6;165 +32026;Bajonnette;106;0;106 +32027;Barcelonne-du-Gers;1372;38;1410 +32028;Barcugnan;107;6;113 +32029;Barran;673;20;693 +32030;Bars;135;4;139 +32031;Bascous;170;3;173 +32032;Bassoues;321;6;327 +32033;Bazian;112;0;112 +32034;Bazugues;57;3;60 +32035;Beaucaire;256;4;260 +32036;Beaumarchés;664;40;704 +32037;Beaumont;136;6;142 +32038;Beaupuy;188;7;195 +32039;Beccas;118;4;122 +32040;Bédéchan;152;1;153 +32041;Bellegarde;190;0;190 +32042;Belloc-Saint-Clamens;129;5;134 +32043;Belmont;150;4;154 +32044;Béraut;331;9;340 +32045;Berdoues;424;20;444 +32046;Bernède;204;1;205 +32047;Berrac;103;1;104 +32048;Betcave-Aguin;85;3;88 +32049;Bétous;88;3;91 +32050;Betplan;99;4;103 +32051;Bézéril;128;2;130 +32052;Bezolles;139;4;143 +32053;Bézues-Bajon;190;4;194 +32054;Biran;386;9;395 +32055;Bivès;133;2;135 +32056;Blanquefort;57;2;59 +32057;Blaziert;134;3;137 +32058;Blousson-Sérian;42;2;44 +32059;Bonas;133;2;135 +32060;Boucagnères;209;4;213 +32061;Boulaur;179;2;181 +32062;Bourrouillan;157;2;159 +32063;Bouzon-Gellenave;193;4;197 +32064;Bretagne-d'Armagnac;422;12;434 +32065;Le Brouilh-Monbert;228;3;231 +32066;Brugnens;256;11;267 +32067;Cabas-Loumassès;52;4;56 +32068;Cadeilhan;139;3;142 +32069;Cadeillan;61;3;64 +32070;Cahuzac-sur-Adour;223;3;226 +32071;Caillavet;204;10;214 +32072;Callian;47;1;48 +32073;Campagne-d'Armagnac;224;3;227 +32075;Cassaigne;221;5;226 +32076;Castelnau-Barbarens;528;10;538 +32077;Castelnau-d'Anglès;89;3;92 +32078;Castelnau-d'Arbieu;234;9;243 +32079;Castelnau d'Auzan Labarrère;1252;30;1282 +32080;Castelnau-sur-l'Auvignon;147;6;153 +32081;Castelnavet;130;2;132 +32082;Castéra-Lectourois;350;7;357 +32083;Castéra-Verduzan;988;19;1007 +32084;Castéron;52;3;55 +32085;Castet-Arrouy;186;7;193 +32086;Castex;86;2;88 +32087;Castex-d'Armagnac;112;4;116 +32088;Castillon-Debats;323;0;323 +32089;Castillon-Massas;246;6;252 +32090;Castillon-Savès;344;8;352 +32091;Castin;343;16;359 +32092;Catonvielle;97;4;101 +32093;Caumont;102;7;109 +32094;Caupenne-d'Armagnac;424;16;440 +32095;Caussens;619;13;632 +32096;Cazaubon;1629;34;1663 +32097;Cazaux-d'Anglès;119;2;121 +32098;Cazaux-Savès;315;5;320 +32099;Cazaux-Villecomtal;71;3;74 +32100;Cazeneuve;148;4;152 +32101;Céran;222;3;225 +32102;Cézan;223;2;225 +32103;Chélan;175;8;183 +32104;Clermont-Pouyguillès;159;3;162 +32105;Clermont-Savès;326;9;335 +32106;Cologne;914;66;980 +32107;Condom;6530;205;6735 +32108;Corneillan;146;10;156 +32109;Couloumé-Mondebat;194;5;199 +32110;Courrensan;403;7;410 +32111;Courties;56;0;56 +32112;Crastes;254;15;269 +32113;Cravencères;92;3;95 +32114;Cuélas;124;5;129 +32115;Dému;337;3;340 +32116;Duffort;141;4;145 +32117;Duran;870;29;899 +32118;Durban;154;5;159 +32119;Eauze;3918;74;3992 +32120;Encausse;427;9;436 +32121;Endoufielle;527;17;544 +32122;Esclassan-Labastide;358;10;368 +32123;Escornebœuf;565;11;576 +32124;Espaon;190;0;190 +32125;Espas;123;1;124 +32126;Estampes;159;1;160 +32127;Estang;638;13;651 +32128;Estipouy;208;14;222 +32129;Estramiac;142;0;142 +32130;Faget-Abbatial;218;1;219 +32131;Flamarens;150;2;152 +32132;Fleurance;6021;111;6132 +32133;Fourcès;260;2;262 +32134;Frégouville;346;6;352 +32135;Fustérouau;134;5;139 +32136;Galiax;161;5;166 +32138;Garravet;157;4;161 +32139;Gaudonville;111;1;112 +32140;Gaujac;66;0;66 +32141;Gaujan;118;1;119 +32142;Gavarret-sur-Aulouste;142;2;144 +32143;Gazaupouy;296;12;308 +32144;Gazax-et-Baccarisse;80;0;80 +32145;Gée-Rivière;46;2;48 +32146;Gimbrède;283;4;287 +32147;Gimont;3032;50;3082 +32148;Giscaro;100;0;100 +32149;Gondrin;1194;32;1226 +32150;Goutz;205;6;211 +32151;Goux;67;0;67 +32152;Haget;331;11;342 +32153;Haulies;165;1;166 +32154;Homps;104;1;105 +32155;Le Houga;1170;51;1221 +32156;Idrac-Respaillès;214;4;218 +32157;L' Isle-Arné;180;2;182 +32158;L' Isle-Bouzon;245;10;255 +32159;L' Isle-de-Noé;543;16;559 +32160;L' Isle-Jourdain;8851;218;9069 +32161;Izotges;105;4;109 +32162;Jegun;1144;49;1193 +32163;Jû-Belloc;296;9;305 +32164;Juillac;121;2;123 +32165;Juilles;220;6;226 +32166;Justian;118;1;119 +32167;Laas;298;6;304 +32169;Labarthe;153;4;157 +32170;Labarthète;140;5;145 +32171;Labastide-Savès;174;1;175 +32172;Labéjan;303;15;318 +32173;Labrihe;209;8;217 +32174;Ladevèze-Rivière;214;4;218 +32175;Ladevèze-Ville;236;7;243 +32176;Lagarde;119;5;124 +32177;Lagarde-Hachan;164;6;170 +32178;Lagardère;78;3;81 +32180;Lagraulet-du-Gers;575;10;585 +32181;Laguian-Mazous;241;3;244 +32182;Lahas;180;3;183 +32183;Lahitte;247;11;258 +32184;Lalanne;137;3;140 +32185;Lalanne-Arqué;156;4;160 +32186;Lamaguère;81;0;81 +32187;Lamazère;121;7;128 +32188;Lamothe-Goas;78;3;81 +32191;Lanne-Soubiran;141;1;142 +32189;Lannemaignan;109;3;112 +32190;Lannepax;494;6;500 +32192;Lannux;245;9;254 +32193;Larée;230;3;233 +32194;Larressingle;214;7;221 +32195;Larroque-Engalin;49;2;51 +32196;Larroque-Saint-Sernin;167;0;167 +32197;Larroque-sur-l'Osse;236;6;242 +32198;Lartigue;183;4;187 +32199;Lasserade;197;9;206 +32200;Lasséran;385;11;396 +32201;Lasseube-Propre;340;7;347 +32202;Laujuzan;279;15;294 +32203;Lauraët;252;3;255 +32204;Lavardens;385;11;396 +32205;Laveraët;108;1;109 +32206;Laymont;210;3;213 +32207;Leboulin;346;18;364 +32208;Lectoure;3664;363;4027 +32209;Lelin-Lapujolle;278;3;281 +32210;Lias;620;13;633 +32211;Lias-d'Armagnac;196;7;203 +32212;Ligardes;217;4;221 +32213;Lombez;2134;36;2170 +32214;Loubédat;107;3;110 +32215;Loubersan;152;11;163 +32216;Lourties-Monbrun;158;1;159 +32217;Louslitges;67;2;69 +32218;Loussous-Débat;62;0;62 +32219;Lupiac;300;14;314 +32220;Luppé-Violles;157;3;160 +32221;Lussan;228;4;232 +32222;Magnan;239;2;241 +32223;Magnas;59;31;90 +32224;Maignaut-Tauzia;260;2;262 +32225;Malabat;114;5;119 +32226;Manas-Bastanous;81;4;85 +32227;Manciet;805;26;831 +32228;Manent-Montané;92;1;93 +32229;Mansempuy;86;1;87 +32230;Mansencôme;46;4;50 +32231;Marambat;442;13;455 +32232;Maravat;43;0;43 +32233;Marciac;1224;86;1310 +32234;Marestaing;319;7;326 +32235;Margouët-Meymes;176;8;184 +32236;Marguestau;75;0;75 +32237;Marsan;471;11;482 +32238;Marseillan;90;3;93 +32239;Marsolan;458;11;469 +32241;Mas-d'Auvignon;171;6;177 +32240;Mascaras;64;4;68 +32242;Masseube;1520;451;1971 +32243;Mauléon-d'Armagnac;275;3;278 +32244;Maulichères;169;4;173 +32245;Maumusson-Laguian;145;7;152 +32246;Maupas;203;3;206 +32247;Maurens;311;7;318 +32248;Mauroux;135;4;139 +32249;Mauvezin;2179;48;2227 +32250;Meilhan;80;1;81 +32251;Mérens;64;0;64 +32252;Miélan;1139;23;1162 +32253;Miradoux;501;8;509 +32254;Miramont-d'Astarac;347;13;360 +32255;Miramont-Latour;163;3;166 +32256;Mirande;3468;326;3794 +32257;Mirannes;66;4;70 +32258;Mirepoix;225;4;229 +32260;Monbardon;83;4;87 +32261;Monblanc;351;8;359 +32262;Monbrun;385;12;397 +32263;Moncassin;134;3;137 +32264;Monclar;192;2;194 +32265;Monclar-sur-Losse;106;2;108 +32266;Moncorneil-Grazan;153;1;154 +32267;Monferran-Plavès;120;2;122 +32268;Monferran-Savès;803;29;832 +32269;Monfort;492;5;497 +32270;Mongausy;75;2;77 +32271;Monguilhem;309;13;322 +32272;Monlaur-Bernet;161;4;165 +32273;Monlezun;199;10;209 +32274;Monlezun-d'Armagnac;201;3;204 +32275;Monpardiac;45;1;46 +32280;Mont-d'Astarac;104;2;106 +32281;Mont-de-Marrast;111;5;116 +32276;Montadet;74;1;75 +32277;Montamat;136;2;138 +32278;Montaut;117;7;124 +32279;Montaut-les-Créneaux;708;20;728 +32282;Montégut;667;12;679 +32283;Montégut-Arros;293;6;299 +32284;Montégut-Savès;64;1;65 +32285;Montesquiou;581;22;603 +32286;Montestruc-sur-Gers;705;11;716 +32287;Monties;77;1;78 +32288;Montiron;140;3;143 +32289;Montpézat;242;3;245 +32290;Montréal;1168;35;1203 +32291;Mormès;121;2;123 +32292;Mouchan;406;14;420 +32293;Mouchès;75;4;79 +32294;Mourède;86;3;89 +32295;Nizas;149;9;158 +32296;Nogaro;2009;165;2174 +32297;Noilhan;375;11;386 +32298;Nougaroulet;375;12;387 +32299;Noulens;104;0;104 +32300;Orbessan;288;3;291 +32301;Ordan-Larroque;916;36;952 +32302;Ornézan;229;9;238 +32303;Pallanne;59;4;63 +32304;Panassac;288;9;297 +32305;Panjas;400;5;405 +32306;Pauilhac;618;49;667 +32307;Pavie;2486;116;2602 +32308;Pébées;103;2;105 +32309;Pellefigue;116;5;121 +32310;Perchède;118;1;119 +32311;Pergain-Taillac;302;4;306 +32312;Pessan;671;14;685 +32313;Pessoulens;142;4;146 +32314;Peyrecave;72;5;77 +32315;Peyrusse-Grande;164;5;169 +32316;Peyrusse-Massas;104;3;107 +32317;Peyrusse-Vieille;70;0;70 +32318;Pis;113;2;115 +32319;Plaisance;1461;28;1489 +32320;Plieux;134;6;140 +32321;Polastron;272;5;277 +32322;Pompiac;191;3;194 +32323;Ponsampère;126;6;132 +32324;Ponsan-Soubiran;90;4;94 +32327;Pouy-Loubrin;84;0;84 +32328;Pouy-Roquelaure;122;6;128 +32325;Pouydraguin;131;2;133 +32326;Pouylebon;139;5;144 +32329;Préchac;171;3;174 +32330;Préchac-sur-Adour;199;5;204 +32331;Preignan;1276;33;1309 +32332;Préneron;135;3;138 +32333;Projan;184;0;184 +32334;Pujaudran;1523;39;1562 +32335;Puycasquier;447;10;457 +32336;Puylausic;163;9;172 +32337;Puységur;75;1;76 +32338;Ramouzens;163;3;166 +32339;Razengues;239;9;248 +32340;Réans;293;5;298 +32341;Réjaumont;240;4;244 +32342;Ricourt;67;1;68 +32343;Riguepeu;204;7;211 +32344;Riscle;1830;100;1930 +32345;La Romieu;575;15;590 +32346;Roquebrune;213;4;217 +32347;Roquefort;296;5;301 +32348;Roquelaure;572;23;595 +32349;Roquelaure-Saint-Aubin;118;5;123 +32350;Roquepine;36;2;38 +32351;Roques;104;0;104 +32352;Rozès;124;2;126 +32353;Sabaillan;148;7;155 +32354;Sabazan;136;1;137 +32355;Sadeillan;87;2;89 +32356;Saint-André;123;1;124 +32358;Saint-Antoine;198;4;202 +32359;Saint-Antonin;159;5;164 +32360;Saint-Arailles;135;4;139 +32361;Saint-Arroman;137;7;144 +32362;Saint-Aunix-Lengros;142;3;145 +32364;Saint-Avit-Frandat;99;2;101 +32365;Saint-Blancard;341;6;347 +32366;Saint-Brès;76;3;79 +32467;Saint-Caprais;139;0;139 +32367;Saint-Christaud;65;2;67 +32370;Saint-Clar;1015;67;1082 +32371;Saint-Créac;83;1;84 +32372;Saint-Cricq;293;4;297 +32374;Saint-Élix-d'Astarac;189;6;195 +32375;Saint-Élix-Theux;106;0;106 +32377;Saint-Georges;180;2;182 +32378;Saint-Germé;500;6;506 +32379;Saint-Germier;210;7;217 +32380;Saint-Griède;140;10;150 +32381;Saint-Jean-le-Comtal;411;21;432 +32382;Saint-Jean-Poutge;322;14;336 +32383;Saint-Justin;130;6;136 +32384;Saint-Lary;279;6;285 +32385;Saint-Léonard;182;1;183 +32386;Saint-Lizier-du-Planté;138;1;139 +32387;Saint-Loube;96;2;98 +32389;Saint-Martin;459;21;480 +32390;Saint-Martin-d'Armagnac;247;7;254 +32391;Saint-Martin-de-Goyne;126;6;132 +32392;Saint-Martin-Gimois;91;1;92 +32393;Saint-Maur;142;5;147 +32394;Saint-Médard;327;5;332 +32396;Saint-Mézard;225;2;227 +32397;Saint-Michel;253;16;269 +32398;Saint-Mont;320;10;330 +32399;Saint-Orens;80;3;83 +32400;Saint-Orens-Pouy-Petit;193;7;200 +32401;Saint-Ost;87;2;89 +32402;Saint-Paul-de-Baïse;102;3;105 +32403;Saint-Pierre-d'Aubézies;67;1;68 +32404;Saint-Puy;600;14;614 +32406;Saint-Sauvy;340;6;346 +32407;Saint-Soulan;160;4;164 +32357;Sainte-Anne;117;1;118 +32363;Sainte-Aurence-Cazaux;101;1;102 +32368;Sainte-Christie;553;11;564 +32369;Sainte-Christie-d'Armagnac;373;13;386 +32373;Sainte-Dode;209;9;218 +32376;Sainte-Gemme;119;4;123 +32388;Sainte-Marie;429;8;437 +32395;Sainte-Mère;215;4;219 +32405;Sainte-Radegonde;182;4;186 +32408;Salles-d'Armagnac;131;4;135 +32409;Samaran;90;0;90 +32410;Samatan;2370;103;2473 +32411;Sansan;99;3;102 +32412;Saramon;825;16;841 +32413;Sarcos;75;2;77 +32414;Sarragachies;237;6;243 +32415;Sarraguzan;86;2;88 +32416;Sarrant;368;14;382 +32417;La Sauvetat;368;12;380 +32418;Sauveterre;265;63;328 +32419;Sauviac;108;3;111 +32420;Sauvimont;66;2;68 +32421;Savignac-Mona;138;1;139 +32422;Scieurac-et-Flourès;40;1;41 +32423;Séailles;45;1;46 +32424;Ségos;229;8;237 +32425;Ségoufielle;1138;27;1165 +32426;Seissan;1091;11;1102 +32427;Sembouès;60;1;61 +32428;Sémézies-Cachan;66;4;70 +32429;Sempesserre;294;5;299 +32430;Sère;77;0;77 +32431;Sérempuy;34;0;34 +32432;Seysses-Savès;239;2;241 +32433;Simorre;710;17;727 +32434;Sion;103;3;106 +32435;Sirac;169;9;178 +32436;Solomiac;481;10;491 +32437;Sorbets;226;6;232 +32438;Tachoires;98;0;98 +32439;Tarsac;168;2;170 +32440;Tasque;255;6;261 +32441;Taybosc;62;0;62 +32443;Termes-d'Armagnac;191;3;194 +32442;Terraube;372;4;376 +32444;Thoux;253;7;260 +32445;Tieste-Uragnoux;167;4;171 +32446;Tillac;281;7;288 +32447;Tirent-Pontéjac;89;1;90 +32448;Touget;512;17;529 +32449;Toujouse;248;2;250 +32450;Tourdun;117;4;121 +32451;Tournan;182;2;184 +32452;Tournecoupe;263;8;271 +32453;Tourrenquets;113;6;119 +32454;Traversères;71;3;74 +32455;Troncens;184;4;188 +32456;Tudelle;59;0;59 +32457;Urdens;292;5;297 +32458;Urgosse;239;3;242 +32459;Valence-sur-Baïse;1135;19;1154 +32460;Vergoignan;299;8;307 +32461;Verlus;105;3;108 +32462;Vic-Fezensac;3474;84;3558 +32463;Viella;511;12;523 +32464;Villecomtal-sur-Arros;853;19;872 +32465;Villefranche;128;5;133 +32466;Viozan;113;2;115 +33001;Abzac;1937;26;1963 +33002;Aillas;822;14;836 +33003;Ambarès-et-Lagrave;16344;136;16480 +33004;Ambès;3128;20;3148 +33005;Andernos-les-Bains;11645;252;11897 +33006;Anglade;947;11;958 +33007;Arbanats;1272;6;1278 +33009;Arcachon;11284;244;11528 +33010;Arcins;490;3;493 +33011;Arès;6308;123;6431 +33012;Arsac;3592;46;3638 +33014;Les Artigues-de-Lussac;1108;21;1129 +33013;Artigues-près-Bordeaux;8639;89;8728 +33015;Arveyres;1960;40;2000 +33016;Asques;460;9;469 +33017;Aubiac;272;11;283 +33019;Audenge;7993;112;8105 +33020;Auriolles;140;0;140 +33021;Auros;1020;14;1034 +33022;Avensan;2953;40;2993 +33023;Ayguemorte-les-Graves;1256;15;1271 +33024;Bagas;295;9;304 +33025;Baigneaux;438;4;442 +33026;Balizac;503;5;508 +33027;Barie;296;9;305 +33028;Baron;1153;16;1169 +33029;Le Barp;5506;81;5587 +33030;Barsac;2063;22;2085 +33031;Bassanne;120;5;125 +33032;Bassens;7278;58;7336 +33033;Baurech;871;6;877 +33034;Bayas;456;3;459 +33035;Bayon-sur-Gironde;704;2;706 +33036;Bazas;4772;264;5036 +33037;Beautiran;2267;38;2305 +33038;Bégadan;909;8;917 +33039;Bègles;28601;354;28955 +33040;Béguey;1187;13;1200 +33042;Belin-Béliet;5529;52;5581 +33043;Bellebat;257;1;258 +33044;Bellefond;225;6;231 +33045;Belvès-de-Castillon;333;8;341 +33046;Bernos-Beaulac;1104;23;1127 +33047;Berson;1795;31;1826 +33048;Berthez;263;7;270 +33049;Beychac-et-Caillau;2227;24;2251 +33050;Bieujac;620;8;628 +33051;Biganos;10706;117;10823 +33052;Les Billaux;1191;36;1227 +33053;Birac;231;1;232 +33054;Blaignac;287;5;292 +33055;Blaignan-Prignac;469;5;474 +33056;Blanquefort;15833;585;16418 +33057;Blasimon;906;19;925 +33058;Blaye;4835;112;4947 +33059;Blésignac;303;6;309 +33060;Bommes;465;67;532 +33061;Bonnetan;947;17;964 +33062;Bonzac;747;12;759 +33063;Bordeaux;254436;3368;257804 +33064;Bossugan;39;0;39 +33065;Bouliac;3631;70;3701 +33066;Bourdelles;93;1;94 +33067;Bourg;2243;42;2285 +33068;Bourideys;79;3;82 +33069;Le Bouscat;23824;266;24090 +33070;Brach;667;1;668 +33071;Branne;1288;17;1305 +33072;Brannens;239;4;243 +33073;Braud-et-Saint-Louis;1605;13;1618 +33213;La Brède;4280;486;4766 +33074;Brouqueyran;194;4;198 +33075;Bruges;17924;163;18087 +33076;Budos;787;14;801 +33077;Cabanac-et-Villagrains;2393;25;2418 +33078;Cabara;513;12;525 +33079;Cadarsac;357;6;363 +33080;Cadaujac;6097;62;6159 +33081;Cadillac;2789;28;2817 +33082;Cadillac-en-Fronsadais;1249;15;1264 +33083;Camarsac;1004;13;1017 +33084;Cambes;1625;17;1642 +33085;Camblanes-et-Meynac;2885;142;3027 +33086;Camiac-et-Saint-Denis;362;5;367 +33087;Camiran;412;5;417 +33088;Camps-sur-l'Isle;603;10;613 +33089;Campugnan;496;9;505 +33090;Canéjan;5539;66;5605 +33093;Capian;721;17;738 +33094;Caplong;225;7;232 +33095;Captieux;1281;22;1303 +33096;Carbon-Blanc;8091;81;8172 +33097;Carcans;2413;46;2459 +33098;Cardan;498;2;500 +33099;Carignan-de-Bordeaux;3859;40;3899 +33100;Cars;1187;21;1208 +33101;Cartelègue;1244;21;1265 +33102;Casseuil;398;4;402 +33103;Castelmoron-d'Albret;53;0;53 +33104;Castelnau-de-Médoc;4778;41;4819 +33105;Castelviel;219;12;231 +33106;Castets et Castillon;1452;18;1470 +33108;Castillon-la-Bataille;3166;36;3202 +33109;Castres-Gironde;2352;19;2371 +33111;Caudrot;1180;16;1196 +33112;Caumont;147;2;149 +33113;Cauvignac;169;4;173 +33114;Cavignac;2065;15;2080 +33115;Cazalis;236;1;237 +33116;Cazats;426;8;434 +33117;Cazaugitat;244;3;247 +33118;Cénac;1907;32;1939 +33119;Cenon;24729;246;24975 +33120;Cérons;2084;21;2105 +33121;Cessac;194;2;196 +33122;Cestas;16922;259;17181 +33123;Cézac;2571;33;2604 +33124;Chamadelle;733;4;737 +33125;Cissac-Médoc;2146;24;2170 +33126;Civrac-de-Blaye;857;20;877 +33128;Civrac-en-Médoc;692;6;698 +33127;Civrac-sur-Dordogne;223;5;228 +33129;Cleyrac;160;1;161 +33130;Coimères;1034;27;1061 +33131;Coirac;202;2;204 +33132;Comps;540;8;548 +33133;Coubeyrac;71;1;72 +33134;Couquèques;272;5;277 +33135;Courpiac;125;2;127 +33136;Cours-de-Monségur;284;4;288 +33137;Cours-les-Bains;222;4;226 +33138;Coutras;8606;156;8762 +33139;Coutures;96;4;100 +33140;Créon;4697;74;4771 +33141;Croignon;642;7;649 +33142;Cubnezais;1499;25;1524 +33143;Cubzac-les-Ponts;2466;25;2491 +33144;Cudos;802;163;965 +33145;Cursan;650;17;667 +33146;Cussac-Fort-Médoc;2240;27;2267 +33147;Daignac;476;6;482 +33148;Dardenac;85;3;88 +33149;Daubèze;153;1;154 +33150;Dieulivol;344;2;346 +33151;Donnezac;899;18;917 +33152;Donzac;118;5;123 +33153;Doulezon;265;4;269 +33154;Les Églisottes-et-Chalaures;2152;111;2263 +33155;Escaudes;153;3;156 +33156;Escoussans;299;8;307 +33157;Espiet;776;15;791 +33158;Les Esseintes;238;6;244 +33159;Étauliers;1493;15;1508 +33160;Eynesse;587;17;604 +33161;Eyrans;773;9;782 +33162;Eysines;23462;290;23752 +33163;Faleyras;424;6;430 +33164;Fargues;1652;33;1685 +33165;Fargues-Saint-Hilaire;2889;30;2919 +33166;Le Fieu;523;4;527 +33168;Flaujagues;591;9;600 +33167;Floirac;17463;91;17554 +33169;Floudès;108;3;111 +33170;Fontet;793;16;809 +33171;Fossès-et-Baleyssac;224;3;227 +33172;Fours;318;8;326 +33173;Francs;189;7;196 +33174;Fronsac;1153;34;1187 +33175;Frontenac;731;10;741 +33176;Gabarnac;365;4;369 +33177;Gaillan-en-Médoc;2323;25;2348 +33178;Gajac;380;4;384 +33179;Galgon;3014;51;3065 +33180;Gans;188;8;196 +33181;Gardegan-et-Tourtirac;281;12;293 +33182;Gauriac;748;16;764 +33183;Gauriaguet;1283;14;1297 +33184;Générac;541;11;552 +33185;Génissac;1948;34;1982 +33186;Gensac;771;10;781 +33187;Gironde-sur-Dropt;1261;24;1285 +33188;Giscos;180;3;183 +33189;Gornac;435;10;445 +33190;Goualade;91;1;92 +33191;Gours;571;3;574 +33192;Gradignan;25552;412;25964 +33193;Grayan-et-l'Hôpital;1371;19;1390 +33194;Grézillac;695;15;710 +33195;Grignols;1207;8;1215 +33196;Guillac;163;4;167 +33197;Guillos;450;6;456 +33198;Guîtres;1589;33;1622 +33199;Gujan-Mestras;21152;450;21602 +33200;Le Haillan;11018;179;11197 +33201;Haux;827;16;843 +33202;Hostens;1329;19;1348 +33203;Hourtin;3506;50;3556 +33204;Hure;513;8;521 +33205;Illats;1407;20;1427 +33206;Isle-Saint-Georges;522;3;525 +33207;Izon;5810;65;5875 +33208;Jau-Dignac-et-Loirac;973;10;983 +33209;Jugazan;298;4;302 +33210;Juillac;240;4;244 +33211;Labarde;591;2;593 +33212;Labescau;117;1;118 +33214;Lacanau;4914;71;4985 +33215;Ladaux;195;6;201 +33216;Lados;174;5;179 +33218;Lagorce;1667;16;1683 +33222;Lalande-de-Pomerol;655;15;670 +33220;Lamarque;1308;13;1321 +33221;Lamothe-Landerron;1226;40;1266 +33219;La Lande-de-Fronsac;2412;24;2436 +33223;Landerrouat;208;3;211 +33224;Landerrouet-sur-Ségur;97;0;97 +33225;Landiras;2227;37;2264 +33226;Langoiran;2152;31;2183 +33227;Langon;7375;156;7531 +33228;Lansac;739;7;746 +33229;Lanton;6912;131;7043 +33230;Lapouyade;498;10;508 +33231;Laroque;279;8;287 +33232;Lartigue;40;0;40 +33233;Laruscade;2765;20;2785 +33234;Latresne;3497;146;3643 +33235;Lavazan;227;2;229 +33236;Lège-Cap-Ferret;8409;175;8584 +33237;Léogeats;805;20;825 +33238;Léognan;10372;174;10546 +33239;Lerm-et-Musset;482;5;487 +33240;Lesparre-Médoc;5801;99;5900 +33241;Lestiac-sur-Garonne;580;8;588 +33242;Les Lèves-et-Thoumeyragues;557;10;567 +33243;Libourne;24845;555;25400 +33244;Lignan-de-Bazas;409;8;417 +33245;Lignan-de-Bordeaux;822;15;837 +33246;Ligueux;166;7;173 +33247;Listrac-de-Durèze;171;3;174 +33248;Listrac-Médoc;2764;38;2802 +33249;Lormont;23538;333;23871 +33250;Loubens;301;8;309 +33251;Louchats;724;9;733 +33252;Loupes;795;11;806 +33253;Loupiac;1112;11;1123 +33254;Loupiac-de-la-Réole;497;8;505 +33255;Lucmau;241;8;249 +33256;Ludon-Médoc;4771;41;4812 +33257;Lugaignac;479;6;485 +33258;Lugasson;295;7;302 +33259;Lugon-et-l'Île-du-Carnay;1281;23;1304 +33260;Lugos;927;20;947 +33261;Lussac;1261;38;1299 +33262;Macau;4225;24;4249 +33263;Madirac;245;4;249 +33264;Maransin;1016;10;1026 +33266;Marcenais;772;18;790 +33555;Marcheprime;4724;54;4778 +33268;Margaux-Cantenac;2965;43;3008 +33269;Margueron;397;4;401 +33270;Marimbault;186;8;194 +33271;Marions;208;2;210 +33272;Marsas;1204;22;1226 +33273;Martignas-sur-Jalle;7386;125;7511 +33274;Martillac;3067;37;3104 +33275;Martres;113;1;114 +33276;Masseilles;145;5;150 +33277;Massugas;227;6;233 +33278;Mauriac;244;5;249 +33279;Mazères;761;10;771 +33280;Mazion;525;4;529 +33281;Mérignac;70105;710;70815 +33282;Mérignas;341;4;345 +33283;Mesterrieux;222;3;225 +33284;Mios;9959;119;10078 +33285;Mombrier;423;8;431 +33287;Mongauzy;595;5;600 +33288;Monprimblanc;300;6;306 +33289;Monségur;1584;72;1656 +33290;Montagne;1524;139;1663 +33291;Montagoudin;181;4;185 +33292;Montignac;139;8;147 +33293;Montussan;3212;48;3260 +33294;Morizès;545;8;553 +33295;Mouillac;88;9;97 +33296;Mouliets-et-Villemartin;1061;15;1076 +33297;Moulis-en-Médoc;1830;33;1863 +33298;Moulon;999;18;1017 +33299;Mourens;385;8;393 +33300;Naujac-sur-Mer;1090;16;1106 +33301;Naujan-et-Postiac;580;7;587 +33302;Néac;386;12;398 +33303;Nérigean;839;15;854 +33304;Neuffons;150;4;154 +33305;Le Nizan;520;11;531 +33306;Noaillac;466;6;472 +33307;Noaillan;1679;37;1716 +33308;Omet;296;2;298 +33309;Ordonnac;510;7;517 +33310;Origne;182;2;184 +33311;Paillet;1213;25;1238 +33312;Parempuyre;8709;80;8789 +33314;Pauillac;4841;104;4945 +33315;Les Peintures;1583;19;1602 +33316;Pellegrue;1099;18;1117 +33317;Périssac;1198;17;1215 +33318;Pessac;63808;706;64514 +33319;Pessac-sur-Dordogne;449;9;458 +33320;Petit-Palais-et-Cornemps;723;11;734 +33321;Peujard;2173;27;2200 +33322;Le Pian-Médoc;6649;138;6787 +33323;Le Pian-sur-Garonne;852;17;869 +33324;Pineuilh;4394;114;4508 +33325;Plassac;885;21;906 +33326;Pleine-Selve;219;5;224 +33327;Podensac;3215;48;3263 +33328;Pomerol;607;13;620 +33329;Pompéjac;260;7;267 +33330;Pompignac;2980;51;3031 +33331;Pondaurat;470;14;484 +33332;Porchères;881;9;890 +33333;Le Porge;3185;47;3232 +33008;Porte-de-Benauge;505;8;513 +33334;Portets;2702;33;2735 +33335;Le Pout;603;7;610 +33336;Préchac;1010;11;1021 +33337;Preignac;2140;34;2174 +33339;Prignac-et-Marcamps;1379;29;1408 +33341;Pugnac;2288;31;2319 +33342;Puisseguin;856;22;878 +33344;Pujols;538;6;544 +33343;Pujols-sur-Ciron;780;15;795 +33345;Le Puy;403;4;407 +33346;Puybarban;423;6;429 +33347;Puynormand;302;7;309 +33348;Queyrac;1382;13;1395 +33349;Quinsac;2189;22;2211 +33350;Rauzan;1211;27;1238 +33351;Reignac;1599;31;1630 +33352;La Réole;4356;85;4441 +33353;Rimons;192;4;196 +33354;Riocaud;181;8;189 +33355;Rions;1556;20;1576 +33356;La Rivière;423;1;424 +33357;Roaillan;1700;29;1729 +33358;Romagne;460;16;476 +33359;Roquebrune;280;3;283 +33360;La Roquille;328;3;331 +33361;Ruch;600;10;610 +33362;Sablons;1314;16;1330 +33363;Sadirac;4244;36;4280 +33364;Saillans;403;4;407 +33365;Saint-Aignan;207;9;216 +33366;Saint-André-de-Cubzac;11464;163;11627 +33367;Saint-André-du-Bois;434;5;439 +33369;Saint-André-et-Appelles;686;12;698 +33370;Saint-Androny;551;8;559 +33372;Saint-Antoine-du-Queyret;59;2;61 +33373;Saint-Antoine-sur-l'Isle;585;7;592 +33374;Saint-Aubin-de-Blaye;821;18;839 +33375;Saint-Aubin-de-Branne;351;6;357 +33376;Saint-Aubin-de-Médoc;7362;171;7533 +33377;Saint-Avit-de-Soulège;78;3;81 +33378;Saint-Avit-Saint-Nazaire;1469;22;1491 +33379;Saint-Brice;316;7;323 +33381;Saint-Caprais-de-Bordeaux;3222;32;3254 +33382;Saint-Christoly-de-Blaye;1973;19;1992 +33383;Saint-Christoly-Médoc;283;3;286 +33385;Saint-Christophe-de-Double;732;8;740 +33384;Saint-Christophe-des-Bardes;442;7;449 +33386;Saint-Cibard;183;6;189 +33387;Saint-Ciers-d'Abzac;1446;25;1471 +33388;Saint-Ciers-de-Canesse;825;13;838 +33389;Saint-Ciers-sur-Gironde;3012;42;3054 +33391;Saint-Côme;320;4;324 +33393;Saint-Denis-de-Pile;5535;65;5600 +33394;Saint-Émilion;1874;48;1922 +33395;Saint-Estèphe;1615;51;1666 +33396;Saint-Étienne-de-Lisse;231;5;236 +33398;Saint-Exupéry;168;1;169 +33399;Saint-Félix-de-Foncaude;288;13;301 +33400;Saint-Ferme;349;5;354 +33405;Saint-Genès-de-Blaye;485;12;497 +33406;Saint-Genès-de-Castillon;393;4;397 +33407;Saint-Genès-de-Fronsac;794;8;802 +33408;Saint-Genès-de-Lombaud;391;17;408 +33409;Saint-Genis-du-Bois;89;1;90 +33412;Saint-Germain-d'Esteuil;1234;19;1253 +33411;Saint-Germain-de-Grave;166;3;169 +33414;Saint-Germain-de-la-Rivière;386;5;391 +33413;Saint-Germain-du-Puch;2156;36;2192 +33415;Saint-Gervais;1878;18;1896 +33416;Saint-Girons-d'Aiguevives;950;19;969 +33418;Saint-Hilaire-de-la-Noaille;381;7;388 +33419;Saint-Hilaire-du-Bois;78;0;78 +33420;Saint-Hippolyte;134;1;135 +33422;Saint-Jean-d'Illac;8377;153;8530 +33421;Saint-Jean-de-Blaignac;440;7;447 +33423;Saint-Julien-Beychevelle;595;1;596 +33425;Saint-Laurent-d'Arce;1449;25;1474 +33426;Saint-Laurent-des-Combes;260;1;261 +33427;Saint-Laurent-du-Bois;250;5;255 +33428;Saint-Laurent-du-Plan;92;0;92 +33424;Saint-Laurent-Médoc;4673;84;4757 +33429;Saint-Léger-de-Balson;337;5;342 +33431;Saint-Léon;339;4;343 +33432;Saint-Loubert;228;2;230 +33433;Saint-Loubès;9509;106;9615 +33434;Saint-Louis-de-Montferrand;2153;16;2169 +33435;Saint-Macaire;2076;94;2170 +33436;Saint-Magne;967;20;987 +33437;Saint-Magne-de-Castillon;1998;12;2010 +33438;Saint-Maixant;1919;49;1968 +33439;Saint-Mariens;1602;20;1622 +33440;Saint-Martial;242;5;247 +33442;Saint-Martin-de-Laye;544;5;549 +33443;Saint-Martin-de-Lerm;143;3;146 +33444;Saint-Martin-de-Sescas;589;10;599 +33445;Saint-Martin-du-Bois;862;14;876 +33446;Saint-Martin-du-Puy;183;1;184 +33441;Saint-Martin-Lacaussade;1118;100;1218 +33448;Saint-Médard-d'Eyrans;2971;33;3004 +33447;Saint-Médard-de-Guizières;2380;23;2403 +33449;Saint-Médard-en-Jalles;31145;516;31661 +33450;Saint-Michel-de-Castelnau;237;3;240 +33451;Saint-Michel-de-Fronsac;522;4;526 +33453;Saint-Michel-de-Lapujade;233;0;233 +33452;Saint-Michel-de-Rieufret;781;12;793 +33454;Saint-Morillon;1694;21;1715 +33456;Saint-Palais;505;11;516 +33457;Saint-Pardon-de-Conques;579;14;593 +33458;Saint-Paul;935;17;952 +33459;Saint-Pey-d'Armens;196;3;199 +33460;Saint-Pey-de-Castets;622;18;640 +33461;Saint-Philippe-d'Aiguille;374;5;379 +33462;Saint-Philippe-du-Seignal;476;3;479 +33463;Saint-Pierre-d'Aurillac;1321;19;1340 +33464;Saint-Pierre-de-Bat;308;6;314 +33465;Saint-Pierre-de-Mons;1198;20;1218 +33466;Saint-Quentin-de-Baron;2442;23;2465 +33467;Saint-Quentin-de-Caplong;243;4;247 +33470;Saint-Romain-la-Virvée;873;24;897 +33471;Saint-Sauveur;1312;17;1329 +33472;Saint-Sauveur-de-Puynormand;348;7;355 +33473;Saint-Savin;3208;37;3245 +33474;Saint-Selve;3026;37;3063 +33475;Saint-Seurin-de-Bourg;404;6;410 +33476;Saint-Seurin-de-Cadourne;710;12;722 +33477;Saint-Seurin-de-Cursac;774;17;791 +33478;Saint-Seurin-sur-l'Isle;3155;26;3181 +33479;Saint-Sève;254;2;256 +33480;Saint-Sulpice-de-Faleyrens;1348;30;1378 +33481;Saint-Sulpice-de-Guilleragues;229;3;232 +33482;Saint-Sulpice-de-Pommiers;225;3;228 +33483;Saint-Sulpice-et-Cameyrac;4614;67;4681 +33484;Saint-Symphorien;1837;33;1870 +33486;Saint-Trojan;342;9;351 +33487;Saint-Vincent-de-Paul;1007;10;1017 +33488;Saint-Vincent-de-Pertignas;385;7;392 +33489;Saint-Vivien-de-Blaye;356;5;361 +33490;Saint-Vivien-de-Médoc;1777;25;1802 +33491;Saint-Vivien-de-Monségur;366;6;372 +33492;Saint-Yzan-de-Soudiac;2380;23;2403 +33493;Saint-Yzans-de-Médoc;374;31;405 +33390;Sainte-Colombe;422;6;428 +33392;Sainte-Croix-du-Mont;899;13;912 +33397;Sainte-Eulalie;4631;53;4684 +33401;Sainte-Florence;149;2;151 +33402;Sainte-Foy-la-Grande;2554;30;2584 +33403;Sainte-Foy-la-Longue;122;0;122 +33404;Sainte-Gemme;186;7;193 +33417;Sainte-Hélène;2797;46;2843 +33468;Sainte-Radegonde;457;9;466 +33485;Sainte-Terre;1883;31;1914 +33494;Salaunes;1066;10;1076 +33496;Sallebœuf;2490;38;2528 +33498;Salles;7028;129;7157 +33499;Les Salles-de-Castillon;363;10;373 +33500;Samonac;426;9;435 +33501;Saucats;3056;47;3103 +33502;Saugon;475;5;480 +33503;Saumos;532;8;540 +33504;Sauternes;790;9;799 +33505;La Sauve;1483;70;1553 +33506;Sauveterre-de-Guyenne;1788;25;1813 +33507;Sauviac;327;11;338 +33508;Savignac;633;13;646 +33509;Savignac-de-l'Isle;504;9;513 +33510;Semens;206;1;207 +33511;Sendets;334;4;338 +33512;Sigalens;381;5;386 +33513;Sillas;118;2;120 +33514;Soulac-sur-Mer;2811;24;2835 +33515;Soulignac;432;8;440 +33516;Soussac;190;5;195 +33517;Soussans;1629;16;1645 +33518;Tabanac;1082;23;1105 +33519;Le Taillan-Médoc;10096;149;10245 +33520;Taillecavat;300;3;303 +33521;Talais;741;8;749 +33522;Talence;42606;968;43574 +33523;Targon;2077;24;2101 +33524;Tarnès;325;8;333 +33525;Tauriac;1289;22;1311 +33526;Tayac;133;3;136 +33527;Le Teich;7906;153;8059 +33528;Le Temple;615;5;620 +33529;La Teste-de-Buch;26078;360;26438 +33530;Teuillac;880;9;889 +33531;Tizac-de-Curton;330;5;335 +33532;Tizac-de-Lapouyade;474;9;483 +33533;Toulenne;2640;28;2668 +33534;Le Tourne;812;11;823 +33535;Tresses;4610;51;4661 +33536;Le Tuzan;278;6;284 +33537;Uzeste;430;10;440 +33380;Val-de-Livenne;1744;21;1765 +33018;Val de Virvée;3512;41;3553 +33538;Valeyrac;548;10;558 +33539;Vayres;3956;50;4006 +33540;Vendays-Montalivet;2445;39;2484 +33541;Vensac;986;18;1004 +33542;Vérac;923;14;937 +33543;Verdelais;1031;9;1040 +33544;Le Verdon-sur-Mer;1335;11;1346 +33545;Vertheuil;1286;21;1307 +33546;Vignonet;498;11;509 +33547;Villandraut;1059;25;1084 +33548;Villegouge;1263;23;1286 +33550;Villenave-d'Ornon;34090;200;34290 +33549;Villenave-de-Rions;317;3;320 +33551;Villeneuve;395;6;401 +33552;Virelade;1062;13;1075 +33553;Virsac;1112;5;1117 +33554;Yvrac;2812;24;2836 +34001;Abeilhan;1705;24;1729 +34002;Adissan;1212;26;1238 +34003;Agde;28609;414;29023 +34004;Agel;235;4;239 +34005;Agonès;265;6;271 +34006;Aigne;269;7;276 +34007;Aigues-Vives;469;7;476 +34008;Les Aires;608;12;620 +34009;Alignan-du-Vent;1737;28;1765 +34010;Aniane;2931;38;2969 +34011;Arboras;121;3;124 +34012;Argelliers;1012;25;1037 +34013;Aspiran;1648;28;1676 +34014;Assas;1520;44;1564 +34015;Assignan;162;3;165 +34016;Aumelas;526;17;543 +34017;Aumes;483;16;499 +34018;Autignac;911;15;926 +34019;Avène;287;8;295 +34020;Azillanet;365;12;377 +34021;Babeau-Bouldoux;296;6;302 +34022;Baillargues;7754;102;7856 +34024;Balaruc-le-Vieux;2628;38;2666 +34023;Balaruc-les-Bains;6751;107;6858 +34025;Bassan;2112;32;2144 +34026;Beaufort;219;4;223 +34027;Beaulieu;1946;44;1990 +34028;Bédarieux;5791;235;6026 +34029;Bélarga;632;9;641 +34030;Berlou;203;0;203 +34031;Bessan;5069;72;5141 +34032;Béziers;77177;1276;78453 +34033;Boisseron;1989;23;2012 +34034;Boisset;40;0;40 +34035;La Boissière;1021;19;1040 +34036;Le Bosc;1345;25;1370 +34037;Boujan-sur-Libron;3378;55;3433 +34038;Le Bousquet-d'Orb;1580;24;1604 +34039;Bouzigues;1655;24;1679 +34040;Brenas;53;0;53 +34041;Brignac;888;16;904 +34042;Brissac;613;14;627 +34043;Buzignargues;337;5;342 +34044;Cabrerolles;335;10;345 +34045;Cabrières;475;20;495 +34046;Cambon-et-Salvergues;48;0;48 +34047;Campagnan;674;10;684 +34048;Campagne;316;5;321 +34049;Camplong;234;3;237 +34050;Candillargues;1742;23;1765 +34051;Canet;3503;45;3548 +34052;Capestang;3233;58;3291 +34053;Carlencas-et-Levas;130;0;130 +34054;Cassagnoles;99;2;101 +34055;Castanet-le-Haut;206;3;209 +34056;Castelnau-de-Guers;1197;23;1220 +34057;Castelnau-le-Lez;20480;330;20810 +34058;Castries;6178;102;6280 +34059;La Caunette;306;6;312 +34060;Causse-de-la-Selle;392;5;397 +34061;Causses-et-Veyran;603;8;611 +34062;Caussiniojouls;130;1;131 +34063;Caux;2560;45;2605 +34064;Le Caylar;445;10;455 +34065;Cazedarnes;601;11;612 +34066;Cazevieille;185;2;187 +34067;Cazilhac;1517;40;1557 +34068;Cazouls-d'Hérault;406;11;417 +34069;Cazouls-lès-Béziers;4987;94;5081 +34070;Cébazan;616;11;627 +34071;Ceilhes-et-Rocozels;324;5;329 +34072;Celles;32;1;33 +34073;Cers;2566;41;2607 +34074;Cessenon-sur-Orb;2284;41;2325 +34075;Cesseras;392;19;411 +34076;Ceyras;1396;27;1423 +34077;Clapiers;5478;101;5579 +34078;Claret;1563;35;1598 +34079;Clermont-l'Hérault;8852;149;9001 +34080;Colombières-sur-Orb;479;14;493 +34081;Colombiers;2484;41;2525 +34082;Combaillaux;1487;41;1528 +34083;Combes;333;6;339 +34084;Corneilhan;1717;30;1747 +34085;Coulobres;360;4;364 +34086;Courniou;609;10;619 +34087;Cournonsec;3397;29;3426 +34088;Cournonterral;6110;72;6182 +34089;Creissan;1360;26;1386 +34090;Le Crès;9321;122;9443 +34091;Le Cros;55;0;55 +34092;Cruzy;988;17;1005 +34093;Dio-et-Valquières;149;5;154 +34246;Entre-Vignes;2136;44;2180 +34094;Espondeilhan;1033;30;1063 +34095;Fabrègues;7035;123;7158 +34096;Faugères;515;10;525 +34097;Félines-Minervois;478;6;484 +34098;Ferrals-les-Montagnes;170;4;174 +34099;Ferrières-les-Verreries;50;5;55 +34100;Ferrières-Poussarou;61;5;66 +34101;Florensac;5014;85;5099 +34102;Fontanès;348;9;357 +34103;Fontès;1015;18;1033 +34104;Fos;107;0;107 +34105;Fouzilhon;244;3;247 +34106;Fozières;167;10;177 +34107;Fraisse-sur-Agout;340;4;344 +34108;Frontignan;22762;184;22946 +34109;Gabian;841;19;860 +34110;Galargues;725;27;752 +34111;Ganges;4024;101;4125 +34112;Garrigues;177;4;181 +34113;Gigean;6426;80;6506 +34114;Gignac;6200;103;6303 +34115;Gorniès;127;3;130 +34116;Grabels;8430;95;8525 +34117;Graissessac;654;19;673 +34344;La Grande-Motte;8820;105;8925 +34118;Guzargues;510;12;522 +34119;Hérépian;1518;27;1545 +34120;Jacou;6791;102;6893 +34121;Joncels;313;4;317 +34122;Jonquières;476;12;488 +34123;Juvignac;11084;119;11203 +34124;Lacoste;325;11;336 +34125;Lagamas;111;4;115 +34126;Lamalou-les-Bains;2509;19;2528 +34127;Lansargues;3112;43;3155 +34128;Laroque;1624;31;1655 +34129;Lattes;16564;241;16805 +34130;Laurens;1702;29;1731 +34131;Lauret;599;18;617 +34132;Lauroux;200;2;202 +34133;Lavalette;62;0;62 +34134;Lavérune;3237;53;3290 +34135;Lespignan;3260;58;3318 +34136;Lézignan-la-Cèbe;1546;28;1574 +34137;Liausson;146;3;149 +34138;Lieuran-Cabrières;322;13;335 +34139;Lieuran-lès-Béziers;1396;26;1422 +34140;Lignan-sur-Orb;3199;84;3283 +34141;La Livinière;532;8;540 +34142;Lodève;7441;249;7690 +34143;Loupian;2160;37;2197 +34144;Lunas;668;14;682 +34145;Lunel;26239;260;26499 +34146;Lunel-Viel;3932;39;3971 +34147;Magalas;3349;51;3400 +34148;Maraussan;4414;82;4496 +34149;Margon;703;11;714 +34150;Marseillan;7778;110;7888 +34151;Marsillargues;6248;76;6324 +34152;Mas-de-Londres;671;5;676 +34153;Les Matelles;2003;41;2044 +34154;Mauguio;16919;180;17099 +34155;Maureilhan;2095;36;2131 +34156;Mérifons;43;3;46 +34157;Mèze;11587;161;11748 +34158;Minerve;121;0;121 +34159;Mireval;3283;49;3332 +34160;Mons;584;13;597 +34161;Montady;3935;72;4007 +34162;Montagnac;4336;47;4383 +34163;Montarnaud;3754;43;3797 +34164;Montaud;991;11;1002 +34165;Montbazin;2952;60;3012 +34166;Montblanc;2848;51;2899 +34167;Montels;252;4;256 +34168;Montesquieu;70;0;70 +34169;Montferrier-sur-Lez;3720;161;3881 +34170;Montouliers;212;5;217 +34171;Montoulieu;161;4;165 +34172;Montpellier;285121;3479;288600 +34173;Montpeyroux;1340;25;1365 +34174;Moulès-et-Baucels;877;26;903 +34175;Mourèze;197;5;202 +34176;Mudaison;2593;27;2620 +34177;Murles;308;10;318 +34178;Murviel-lès-Béziers;3075;53;3128 +34179;Murviel-lès-Montpellier;1883;30;1913 +34180;Nébian;1388;21;1409 +34181;Neffiès;1056;16;1072 +34182;Nézignan-l'Évêque;1820;29;1849 +34183;Nissan-lez-Enserune;3995;60;4055 +34184;Nizas;670;15;685 +34185;Notre-Dame-de-Londres;480;13;493 +34186;Octon;527;4;531 +34187;Olargues;679;14;693 +34188;Olmet-et-Villecun;180;4;184 +34189;Olonzac;1770;21;1791 +34190;Oupia;245;7;252 +34191;Pailhès;570;4;574 +34192;Palavas-les-Flots;5977;43;6020 +34193;Pardailhan;183;6;189 +34194;Paulhan;3937;49;3986 +34195;Pégairolles-de-Buèges;50;1;51 +34196;Pégairolles-de-l'Escalette;159;5;164 +34197;Péret;1020;18;1038 +34198;Pérols;8985;123;9108 +34199;Pézenas;8280;334;8614 +34200;Pézènes-les-Mines;241;6;247 +34201;Pierrerue;292;7;299 +34202;Pignan;7019;95;7114 +34203;Pinet;1745;37;1782 +34204;Plaissan;1196;16;1212 +34205;Les Plans;279;10;289 +34206;Poilhes;559;11;570 +34207;Pomérols;2293;45;2338 +34208;Popian;350;14;364 +34209;Portiragnes;3134;60;3194 +34210;Le Pouget;2054;46;2100 +34211;Le Poujol-sur-Orb;1083;20;1103 +34212;Poujols;164;1;165 +34213;Poussan;5972;79;6051 +34214;Pouzolles;1171;19;1190 +34215;Pouzols;967;21;988 +34216;Le Pradal;332;9;341 +34217;Prades-le-Lez;5467;104;5571 +34218;Prades-sur-Vernazobre;310;8;318 +34219;Prémian;518;7;525 +34220;Le Puech;242;5;247 +34221;Puéchabon;485;5;490 +34222;Puilacher;578;4;582 +34223;Puimisson;1077;22;1099 +34224;Puissalicon;1353;22;1375 +34225;Puisserguier;2912;52;2964 +34226;Quarante;1767;26;1793 +34227;Restinclières;1888;26;1914 +34228;Rieussec;66;2;68 +34229;Riols;767;23;790 +34230;Les Rives;144;4;148 +34231;Romiguières;23;2;25 +34232;Roquebrun;605;10;615 +34233;Roqueredonde;209;1;210 +34234;Roquessels;104;1;105 +34235;Rosis;287;5;292 +34236;Rouet;65;0;65 +34237;Roujan;2158;28;2186 +34238;Saint-André-de-Buèges;39;1;40 +34239;Saint-André-de-Sangonis;5927;86;6013 +34240;Saint-Aunès;3439;31;3470 +34241;Saint-Bauzille-de-la-Sylve;812;18;830 +34242;Saint-Bauzille-de-Montmel;1022;24;1046 +34243;Saint-Bauzille-de-Putois;1977;31;2008 +34244;Saint-Brès;2948;39;2987 +34245;Saint-Chinian;1677;36;1713 +34247;Saint-Clément-de-Rivière;4877;236;5113 +34249;Saint-Drézéry;2526;49;2575 +34250;Saint-Étienne-d'Albagnan;306;7;313 +34251;Saint-Étienne-de-Gourgas;494;16;510 +34252;Saint-Étienne-Estréchoux;260;5;265 +34253;Saint-Félix-de-l'Héras;34;1;35 +34254;Saint-Félix-de-Lodez;1169;32;1201 +34255;Saint-Gély-du-Fesc;9795;236;10031 +34258;Saint-Geniès-de-Fontedit;1593;29;1622 +34257;Saint-Geniès-de-Varensal;209;2;211 +34256;Saint-Geniès-des-Mourgues;1876;31;1907 +34259;Saint-Georges-d'Orques;5397;76;5473 +34260;Saint-Gervais-sur-Mare;858;17;875 +34261;Saint-Guilhem-le-Désert;253;9;262 +34262;Saint-Guiraud;221;0;221 +34263;Saint-Hilaire-de-Beauvoir;420;14;434 +34264;Saint-Jean-de-Buèges;197;0;197 +34265;Saint-Jean-de-Cornies;721;22;743 +34266;Saint-Jean-de-Cuculles;483;7;490 +34267;Saint-Jean-de-Fos;1696;32;1728 +34268;Saint-Jean-de-la-Blaquière;627;16;643 +34269;Saint-Jean-de-Minervois;148;6;154 +34270;Saint-Jean-de-Védas;10008;182;10190 +34271;Saint-Julien;220;3;223 +34272;Saint-Just;3255;43;3298 +34273;Saint-Martin-de-l'Arçon;139;5;144 +34274;Saint-Martin-de-Londres;2755;26;2781 +34276;Saint-Mathieu-de-Tréviers;4790;93;4883 +34277;Saint-Maurice-Navacelles;183;6;189 +34278;Saint-Michel;48;1;49 +34279;Saint-Nazaire-de-Ladarez;354;4;358 +34280;Saint-Nazaire-de-Pézan;626;7;633 +34281;Saint-Pargoire;2276;37;2313 +34282;Saint-Paul-et-Valmalle;1124;20;1144 +34283;Saint-Pierre-de-la-Fage;130;1;131 +34285;Saint-Pons-de-Mauchiens;659;11;670 +34284;Saint-Pons-de-Thomières;1885;175;2060 +34286;Saint-Privat;404;12;416 +34287;Saint-Saturnin-de-Lucian;276;7;283 +34288;Saint-Sériès;983;21;1004 +34289;Saint-Thibéry;2665;34;2699 +34291;Saint-Vincent-d'Olargues;357;23;380 +34290;Saint-Vincent-de-Barbeyrargues;666;9;675 +34248;Sainte-Croix-de-Quintillargues;902;16;918 +34292;Salasc;301;6;307 +34293;La Salvetat-sur-Agout;1141;21;1162 +34294;Saturargues;971;19;990 +34295;Saussan;1588;32;1620 +34296;Saussines;1033;22;1055 +34297;Sauteyrargues;410;8;418 +34298;Sauvian;5353;94;5447 +34299;Sérignan;6956;149;7105 +34300;Servian;4937;85;5022 +34301;Sète;43229;567;43796 +34302;Siran;733;8;741 +34303;Sorbs;35;0;35 +34304;Soubès;931;13;944 +34305;Le Soulié;130;0;130 +34306;Soumont;184;2;186 +34307;Sussargues;2751;55;2806 +34308;Taussac-la-Billière;446;11;457 +34309;Teyran;4586;106;4692 +34310;Thézan-lès-Béziers;2987;73;3060 +34312;La Tour-sur-Orb;1273;31;1304 +34311;Tourbes;1621;156;1777 +34313;Tressan;659;11;670 +34314;Le Triadou;462;16;478 +34315;Usclas-d'Hérault;418;5;423 +34316;Usclas-du-Bosc;218;2;220 +34317;La Vacquerie-et-Saint-Martin-de-Castries;190;7;197 +34318;Vacquières;651;11;662 +34319;Vailhan;158;5;163 +34320;Vailhauquès;2553;54;2607 +34321;Valergues;2071;28;2099 +34322;Valflaunès;763;24;787 +34323;Valmascle;40;1;41 +34324;Valras-Plage;4207;58;4265 +34325;Valros;1616;31;1647 +34326;Vélieux;86;0;86 +34327;Vendargues;6232;83;6315 +34328;Vendémian;1056;30;1086 +34329;Vendres;2702;79;2781 +34331;Verreries-de-Moussans;97;1;98 +34332;Vias;5719;67;5786 +34333;Vic-la-Gardiole;3261;35;3296 +34334;Vieussan;266;0;266 +34335;Villemagne-l'Argentière;433;12;445 +34336;Villeneuve-lès-Béziers;4207;53;4260 +34337;Villeneuve-lès-Maguelone;10012;120;10132 +34338;Villeneuvette;71;3;74 +34339;Villespassans;171;2;173 +34340;Villetelle;1433;41;1474 +34341;Villeveyrac;3795;67;3862 +34342;Viols-en-Laval;199;4;203 +34343;Viols-le-Fort;1211;28;1239 +35001;Acigné;6740;159;6899 +35002;Amanlis;1719;35;1754 +35003;Andouillé-Neuville;886;12;898 +35005;Arbrissel;306;12;318 +35006;Argentré-du-Plessis;4396;125;4521 +35007;Aubigné;474;2;476 +35008;Availles-sur-Seiche;684;18;702 +35009;Baguer-Morvan;1705;33;1738 +35010;Baguer-Pican;1681;13;1694 +35012;Bain-de-Bretagne;7331;165;7496 +35013;Bains-sur-Oust;3478;131;3609 +35014;Bais;2419;32;2451 +35015;Balazé;2228;48;2276 +35016;Baulon;2160;64;2224 +35017;La Baussaine;667;10;677 +35018;La Bazouge-du-Désert;1087;22;1109 +35019;Bazouges-la-Pérouse;1808;25;1833 +35021;Beaucé;1365;29;1394 +35022;Bécherel;669;11;680 +35023;Bédée;4308;71;4379 +35024;Betton;11735;292;12027 +35025;Billé;1052;14;1066 +35026;Bléruais;107;6;113 +35027;Boisgervilly;1664;33;1697 +35028;Boistrudan;710;14;724 +35029;Bonnemain;1566;20;1586 +35030;La Bosse-de-Bretagne;649;9;658 +35031;La Bouëxière;4447;112;4559 +35033;Bourg-des-Comptes;3264;68;3332 +35032;Bourgbarré;4132;56;4188 +35034;La Boussac;1181;23;1204 +35035;Bovel;605;10;615 +35037;Bréal-sous-Montfort;6131;79;6210 +35038;Bréal-sous-Vitré;646;9;655 +35039;Brécé;2106;43;2149 +35040;Breteil;3584;76;3660 +35041;Brie;950;16;966 +35042;Brielles;687;30;717 +35044;Broualan;373;9;382 +35045;Bruc-sur-Aff;863;22;885 +35046;Les Brulais;553;4;557 +35047;Bruz;18266;468;18734 +35049;Cancale;5121;90;5211 +35050;Cardroc;574;9;583 +35051;Cesson-Sévigné;17526;544;18070 +35052;Champeaux;504;16;520 +35054;Chanteloup;1815;43;1858 +35055;Chantepie;10435;218;10653 +35056;La Chapelle-aux-Filtzméens;815;19;834 +35057;La Chapelle-Bouëxic;1475;27;1502 +35058;La Chapelle-Chaussée;1271;15;1286 +35064;La Chapelle-de-Brain;969;23;992 +35059;La Chapelle-des-Fougeretz;4773;96;4869 +35060;La Chapelle du Lou du Lac;1003;19;1022 +35061;La Chapelle-Erbrée;698;17;715 +35062;La Chapelle-Janson;1450;27;1477 +35063;La Chapelle-Saint-Aubert;439;7;446 +35065;La Chapelle-Thouarault;2170;33;2203 +35066;Chartres-de-Bretagne;7800;126;7926 +35067;Chasné-sur-Illet;1537;27;1564 +35068;Châteaubourg;7064;146;7210 +35069;Châteaugiron;9966;253;10219 +35070;Châteauneuf-d'Ille-et-Vilaine;1722;30;1752 +35071;Le Châtellier;427;6;433 +35072;Châtillon-en-Vendelais;1679;35;1714 +35075;Chauvigné;845;20;865 +35076;Chavagne;4015;78;4093 +35077;Chelun;349;11;360 +35078;Cherrueix;1110;19;1129 +35079;Chevaigné;2265;67;2332 +35080;Cintré;2278;42;2320 +35081;Clayes;904;13;917 +35082;Coësmes;1474;34;1508 +35084;Comblessac;689;11;700 +35085;Combourg;5940;135;6075 +35086;Combourtillé;611;8;619 +35087;Cornillé;966;32;998 +35088;Corps-Nuds;3296;56;3352 +35089;La Couyère;479;12;491 +35090;Crevin;2828;39;2867 +35091;Le Crouais;574;7;581 +35092;Cuguen;839;10;849 +35093;Dinard;10027;545;10572 +35094;Dingé;1636;24;1660 +35095;Dol-de-Bretagne;5693;265;5958 +35096;Domagné;2305;42;2347 +35097;Domalain;2018;38;2056 +35098;La Dominelais;1377;26;1403 +35099;Domloup;3522;64;3586 +35101;Dourdain;1159;11;1170 +35102;Drouges;519;14;533 +35103;Eancé;403;9;412 +35104;Epiniac;1426;24;1450 +35105;Erbrée;1702;52;1754 +35106;Ercé-en-Lamée;1497;14;1511 +35107;Ercé-près-Liffré;1808;32;1840 +35108;Essé;1093;25;1118 +35109;Étrelles;2543;58;2601 +35110;Feins;977;19;996 +35111;Le Ferré;687;8;695 +35112;Fleurigné;974;26;1000 +35114;Forges-la-Forêt;265;6;271 +35115;Fougères;20418;680;21098 +35116;La Fresnais;2541;53;2594 +35117;Gaël;1634;25;1659 +35118;Gahard;1467;23;1490 +35119;Gennes-sur-Seiche;950;21;971 +35120;Gévezé;5301;102;5403 +35121;Gosné;1991;36;2027 +35122;La Gouesnière;1893;38;1931 +35123;Goven;4363;96;4459 +35124;Grand-Fougeray;2445;38;2483 +35125;La Guerche-de-Bretagne;4243;147;4390 +35126;Guichen;8568;198;8766 +35127;Guignen;3902;70;3972 +35128;Guipel;1696;38;1734 +35176;Guipry-Messac;6961;149;7110 +35130;Hédé-Bazouges;2247;53;2300 +35131;L' Hermitage;4437;80;4517 +35132;Hirel;1392;36;1428 +35133;Iffendic;4469;92;4561 +35134;Les Iffs;272;12;284 +35135;Irodouër;2262;27;2289 +35136;Janzé;8279;155;8434 +35137;Javené;2067;69;2136 +35138;Laignelet;1163;27;1190 +35139;Laillé;5026;143;5169 +35140;Lalleu;567;11;578 +35141;Landavran;692;21;713 +35142;Landéan;1205;20;1225 +35143;Landujan;934;31;965 +35144;Langan;979;19;998 +35145;Langon;1421;26;1447 +35146;Langouet;601;2;603 +35148;Lanrigan;152;0;152 +35149;Lassy;1702;38;1740 +35150;Lécousse;3233;103;3336 +35151;Lieuron;785;15;800 +35152;Liffré;7609;139;7748 +35153;Lillemer;358;10;368 +35154;Livré-sur-Changeon;1700;41;1741 +35155;Lohéac;649;15;664 +35156;Longaulnay;616;10;626 +35157;Le Loroux;653;15;668 +35159;Lourmais;326;2;328 +35160;Loutehel;258;5;263 +35161;Louvigné-de-Bais;1899;35;1934 +35162;Louvigné-du-Désert;3374;57;3431 +35163;Luitré-Dompierre;1851;30;1881 +35257;Maen Roch;4850;94;4944 +35164;Marcillé-Raoul;766;11;777 +35165;Marcillé-Robert;959;21;980 +35166;Marpiré;1053;17;1070 +35167;Martigné-Ferchaud;2603;65;2668 +35169;Maxent;1466;17;1483 +35170;Mecé;608;12;620 +35171;Médréac;1827;48;1875 +35172;Meillac;1848;29;1877 +35173;Melesse;6576;100;6676 +35174;Mellé;651;11;662 +35175;Mernel;1034;16;1050 +35308;Mesnil-Roc'h;4301;76;4377 +35177;La Mézière;4892;122;5014 +35178;Mézières-sur-Couesnon;1752;32;1784 +35179;Miniac-Morvan;3931;51;3982 +35180;Miniac-sous-Bécherel;774;16;790 +35181;Le Minihic-sur-Rance;1449;33;1482 +35183;Mondevert;819;21;840 +35186;Mont-Dol;1093;38;1131 +35184;Montauban-de-Bretagne;5840;242;6082 +35185;Montautour;264;6;270 +35187;Monterfil;1327;28;1355 +35188;Montfort-sur-Meu;6653;170;6823 +35189;Montgermont;3364;61;3425 +35190;Monthault;265;8;273 +35192;Montreuil-des-Landes;240;3;243 +35193;Montreuil-le-Gast;1936;43;1979 +35194;Montreuil-sous-Pérouse;1015;32;1047 +35195;Montreuil-sur-Ille;2383;35;2418 +35196;Mordelles;7363;139;7502 +35197;Mouazé;1586;18;1604 +35198;Moulins;716;24;740 +35199;Moussé;336;9;345 +35200;Moutiers;929;16;945 +35201;Muel;894;9;903 +35202;La Noë-Blanche;1002;9;1011 +35203;La Nouaye;357;5;362 +35204;Nouvoitou;3099;57;3156 +35206;Noyal-Châtillon-sur-Seiche;6919;125;7044 +35205;Noyal-sous-Bazouges;385;8;393 +35207;Noyal-sur-Vilaine;6008;146;6154 +35208;Orgères;4729;114;4843 +35210;Pacé;11739;297;12036 +35211;Paimpont;1711;38;1749 +35212;Pancé;1171;30;1201 +35214;Parcé;650;2;652 +35215;Parigné;1336;41;1377 +35216;Parthenay-de-Bretagne;1748;12;1760 +35217;Le Pertre;1389;30;1419 +35218;Le Petit-Fougeray;894;20;914 +35219;Pipriac;3745;55;3800 +35220;Piré-Chancé;2901;63;2964 +35221;Pléchâtel;2789;52;2841 +35222;Pleine-Fougères;1980;34;2014 +35223;Plélan-le-Grand;3949;73;4022 +35224;Plerguer;2722;49;2771 +35225;Plesder;790;16;806 +35226;Pleugueneuc;1903;25;1928 +35227;Pleumeleuc;3329;46;3375 +35228;Pleurtuit;6806;123;6929 +35229;Pocé-les-Bois;1293;51;1344 +35230;Poilley;378;4;382 +35231;Poligné;1201;31;1232 +35363;Pont-Péan;4463;129;4592 +35191;Les Portes du Coglais;2391;47;2438 +35232;Princé;380;5;385 +35233;Québriac;1579;37;1616 +35234;Quédillac;1186;21;1207 +35235;Rannée;1094;47;1141 +35236;Redon;9014;796;9810 +35237;Renac;1009;25;1034 +35238;Rennes;216815;4110;220925 +35239;Retiers;4357;94;4451 +35240;Le Rheu;8740;287;9027 +35241;La Richardais;2295;80;2375 +35242;Rimou;336;4;340 +35282;Rives-du-Couesnon;2858;53;2911 +35243;Romagné;2404;53;2457 +35244;Romazy;254;3;257 +35245;Romillé;3905;72;3977 +35246;Roz-Landrieux;1340;27;1367 +35247;Roz-sur-Couesnon;1003;12;1015 +35248;Sains;483;7;490 +35250;Saint-Armel;1981;35;2016 +35251;Saint-Aubin-d'Aubigné;3796;82;3878 +35252;Saint-Aubin-des-Landes;948;23;971 +35253;Saint-Aubin-du-Cormier;3837;161;3998 +35255;Saint-Benoît-des-Ondes;994;29;1023 +35256;Saint-Briac-sur-Mer;2070;62;2132 +35258;Saint-Brieuc-des-Iffs;340;9;349 +35259;Saint-Broladre;1132;22;1154 +35261;Saint-Christophe-de-Valains;225;2;227 +35260;Saint-Christophe-des-Bois;574;5;579 +35263;Saint-Coulomb;2707;84;2791 +35264;Saint-Didier;2052;27;2079 +35265;Saint-Domineuc;2532;49;2581 +35266;Saint-Erblon;3078;69;3147 +35268;Saint-Ganton;424;10;434 +35270;Saint-Georges-de-Gréhaigne;370;4;374 +35271;Saint-Georges-de-Reintembault;1498;25;1523 +35272;Saint-Germain-du-Pinel;915;15;930 +35273;Saint-Germain-en-Coglès;2051;30;2081 +35274;Saint-Germain-sur-Ille;925;14;939 +35275;Saint-Gilles;4984;82;5066 +35276;Saint-Gondran;537;11;548 +35277;Saint-Gonlay;354;5;359 +35278;Saint-Grégoire;9639;368;10007 +35279;Saint-Guinoux;1210;24;1234 +35280;Saint-Hilaire-des-Landes;1038;21;1059 +35281;Saint-Jacques-de-la-Lande;13087;152;13239 +35283;Saint-Jean-sur-Vilaine;1266;32;1298 +35284;Saint-Jouan-des-Guérets;2646;69;2715 +35285;Saint-Just;1065;26;1091 +35286;Saint-Léger-des-Prés;264;9;273 +35287;Saint-Lunaire;2356;83;2439 +35300;Saint-M'Hervé;1356;39;1395 +35288;Saint-Malo;46097;1265;47362 +35289;Saint-Malo-de-Phily;1084;19;1103 +35290;Saint-Malon-sur-Mel;576;12;588 +35292;Saint-Marc-le-Blanc;1689;24;1713 +35291;Saint-Marcan;448;9;457 +35295;Saint-Maugan;544;11;555 +35296;Saint-Médard-sur-Ille;1287;22;1309 +35297;Saint-Méen-le-Grand;4635;173;4808 +35299;Saint-Méloir-des-Ondes;4086;102;4188 +35302;Saint-Onen-la-Chapelle;1143;25;1168 +35304;Saint-Ouen-des-Alleux;1296;22;1318 +35305;Saint-Péran;410;8;418 +35306;Saint-Père-Marc-en-Poulet;2298;154;2452 +35307;Saint-Pern;1033;18;1051 +35309;Saint-Rémy-du-Plain;828;13;841 +35310;Saint-Sauveur-des-Landes;1511;26;1537 +35311;Saint-Séglin;566;6;572 +35312;Saint-Senoux;1840;48;1888 +35314;Saint-Suliac;907;29;936 +35316;Saint-Sulpice-des-Landes;809;9;818 +35315;Saint-Sulpice-la-Forêt;1332;38;1370 +35317;Saint-Symphorien;603;61;664 +35318;Saint-Thual;915;20;935 +35319;Saint-Thurial;2084;43;2127 +35320;Saint-Uniac;537;5;542 +35249;Sainte-Anne-sur-Vilaine;1018;14;1032 +35262;Sainte-Colombe;351;6;357 +35294;Sainte-Marie;2249;64;2313 +35321;Saulnières;773;10;783 +35322;Le Sel-de-Bretagne;1106;18;1124 +35324;La Selle-en-Luitré;613;16;629 +35325;La Selle-Guerchaise;154;7;161 +35326;Sens-de-Bretagne;2554;40;2594 +35327;Servon-sur-Vilaine;3676;85;3761 +35328;Sixt-sur-Aff;2129;44;2173 +35329;Sougéal;570;11;581 +35330;Taillis;1001;26;1027 +35331;Talensac;2488;54;2542 +35332;Teillay;1061;12;1073 +35333;Le Theil-de-Bretagne;1734;33;1767 +35334;Thorigné-Fouillard;8463;210;8673 +35335;Thourie;802;18;820 +35336;Le Tiercent;174;3;177 +35337;Tinténiac;3635;174;3809 +35338;Torcé;1187;25;1212 +35339;Trans-la-Forêt;583;4;587 +35340;Treffendel;1257;24;1281 +35342;Trémeheuc;343;12;355 +35343;Tresbœuf;1255;20;1275 +35345;Trévérien;884;23;907 +35346;Trimer;214;0;214 +35362;Le Tronchet;1161;8;1169 +35004;Val-Couesnon;4191;94;4285 +35168;Val d'Anast;3980;77;4057 +35347;Val-d'Izé;2590;58;2648 +35350;Vergéal;804;24;828 +35351;Le Verger;1445;24;1469 +35352;Vern-sur-Seiche;7911;195;8106 +35353;Vezin-le-Coquet;5727;102;5829 +35354;Vieux-Viel;315;2;317 +35355;Vieux-Vy-sur-Couesnon;1216;6;1222 +35356;Vignoc;1910;24;1934 +35357;Villamée;313;6;319 +35358;La Ville-ès-Nonais;1203;33;1236 +35359;Visseiche;823;17;840 +35360;Vitré;18037;539;18576 +35361;Le Vivier-sur-Mer;1039;10;1049 +36001;Aigurande;1428;29;1457 +36002;Aize;116;0;116 +36003;Ambrault;894;20;914 +36004;Anjouin;331;3;334 +36005;Ardentes;3860;85;3945 +36006;Argenton-sur-Creuse;4927;213;5140 +36007;Argy;603;8;611 +36008;Arpheuilles;223;9;232 +36009;Arthon;1250;46;1296 +36010;Azay-le-Ferron;862;19;881 +36158;Badecon-le-Pin;751;10;761 +36011;Bagneux;174;2;176 +36012;Baraize;351;1;352 +36013;Baudres;438;6;444 +36014;Bazaiges;205;6;211 +36015;Beaulieu;55;1;56 +36016;Bélâbre;968;21;989 +36017;La Berthenoux;397;5;402 +36018;Le Blanc;6389;222;6611 +36019;Bommiers;305;5;310 +36020;Bonneuil;79;1;80 +36021;Les Bordes;895;20;915 +36022;Bouesse;439;4;443 +36023;Bouges-le-Château;266;5;271 +36024;Bretagne;147;1;148 +36025;Briantes;605;11;616 +36026;Brion;572;8;580 +36027;Brives;258;2;260 +36028;La Buxerette;109;2;111 +36029;Buxeuil;222;3;225 +36030;Buxières-d'Aillac;256;4;260 +36031;Buzançais;4505;75;4580 +36032;Ceaulmont;727;20;747 +36033;Celon;407;4;411 +36034;Chabris;2750;43;2793 +36035;Chaillac;1095;13;1108 +36036;Chalais;140;6;146 +36037;La Champenoise;268;6;274 +36038;Champillet;153;2;155 +36040;La Chapelle-Orthemale;111;0;111 +36041;La Chapelle-Saint-Laurian;148;2;150 +36042;Chasseneuil;702;11;713 +36043;Chassignolles;568;23;591 +36044;Châteauroux;43741;1577;45318 +36045;Châtillon-sur-Indre;2567;55;2622 +36046;La Châtre;4109;120;4229 +36047;La Châtre-Langlin;521;8;529 +36048;Chavin;271;9;280 +36049;Chazelet;122;2;124 +36050;Chezelles;476;9;485 +36051;Chitray;182;5;187 +36052;Chouday;153;2;155 +36053;Ciron;572;11;583 +36054;Cléré-du-Bois;246;8;254 +36055;Clion;1023;21;1044 +36056;Cluis;996;15;1011 +36057;Coings;880;24;904 +36058;Concremiers;649;18;667 +36059;Condé;238;10;248 +36060;Crevant;718;14;732 +36061;Crozon-sur-Vauvre;340;11;351 +36062;Cuzion;441;6;447 +36063;Déols;7513;152;7665 +36064;Diors;785;22;807 +36065;Diou;256;5;261 +36066;Douadic;445;14;459 +36068;Dun-le-Poëlier;426;6;432 +36067;Dunet;101;3;104 +36069;Écueillé;1261;21;1282 +36070;Éguzon-Chantôme;1384;31;1415 +36071;Étrechet;1008;24;1032 +36073;Feusines;211;5;216 +36074;Fléré-la-Rivière;552;9;561 +36075;Fontenay;88;1;89 +36076;Fontgombault;249;3;252 +36077;Fontguenand;238;3;241 +36078;Fougerolles;350;6;356 +36079;Francillon;78;1;79 +36080;Frédille;71;2;73 +36081;Gargilesse-Dampierre;285;9;294 +36082;Gehée;255;0;255 +36083;Giroux;116;3;119 +36084;Gournay;290;2;292 +36085;Guilly;244;6;250 +36086;Heugnes;394;8;402 +36087;Ingrandes;317;5;322 +36088;Issoudun;11905;294;12199 +36089;Jeu-les-Bois;394;6;400 +36090;Jeu-Maloches;127;1;128 +36091;Lacs;653;19;672 +36092;Langé;285;8;293 +36093;Levroux;2947;36;2983 +36094;Lignac;459;7;466 +36095;Lignerolles;101;2;103 +36096;Lingé;229;3;232 +36097;Liniez;325;9;334 +36098;Lizeray;82;1;83 +36099;Lourdoueix-Saint-Michel;315;5;320 +36100;Lourouer-Saint-Laurent;270;6;276 +36101;Luant;1504;39;1543 +36104;Lurais;249;3;252 +36105;Lureuil;263;3;266 +36106;Luzeret;153;1;154 +36102;Luçay-le-Libre;99;6;105 +36103;Luçay-le-Mâle;1366;9;1375 +36107;Lye;740;13;753 +36108;Lys-Saint-Georges;221;2;223 +36109;Le Magny;1085;20;1105 +36110;Maillet;263;6;269 +36111;Malicornay;195;3;198 +36112;Mâron;762;18;780 +36113;Martizay;952;20;972 +36114;Mauvières;310;8;318 +36115;Menetou-sur-Nahon;118;2;120 +36116;Ménétréols-sous-Vatan;118;1;119 +36117;Le Menoux;430;7;437 +36118;Méobecq;374;2;376 +36119;Mérigny;537;13;550 +36120;Mers-sur-Indre;653;10;663 +36121;Meunet-Planches;174;6;180 +36122;Meunet-sur-Vatan;194;2;196 +36123;Mézières-en-Brenne;1001;20;1021 +36124;Migné;275;11;286 +36125;Migny;129;6;135 +36126;Montchevrier;451;5;456 +36127;Montgivray;1600;37;1637 +36128;Montierchaume;1643;166;1809 +36129;Montipouret;556;14;570 +36130;Montlevicq;115;1;116 +36131;Mosnay;474;7;481 +36132;La Motte-Feuilly;58;3;61 +36133;Mouhers;229;5;234 +36134;Mouhet;414;14;428 +36135;Moulins-sur-Céphons;293;6;299 +36136;Murs;127;3;130 +36137;Néons-sur-Creuse;381;16;397 +36138;Néret;191;7;198 +36139;Neuillay-les-Bois;659;16;675 +36140;Neuvy-Pailloux;1196;20;1216 +36141;Neuvy-Saint-Sépulchre;1653;38;1691 +36142;Niherne;1586;32;1618 +36143;Nohant-Vic;450;14;464 +36144;Nuret-le-Ferron;305;7;312 +36145;Obterre;191;3;194 +36146;Orsennes;758;9;767 +36147;Orville;138;3;141 +36148;Oulches;409;3;412 +36149;Palluau-sur-Indre;789;12;801 +36150;Parnac;501;13;514 +36152;Paudy;452;3;455 +36153;Paulnay;323;7;330 +36154;Le Pêchereau;1863;40;1903 +36155;Pellevoisin;758;58;816 +36156;Pérassay;362;2;364 +36157;La Pérouille;457;13;470 +36159;Le Poinçonnet;5851;170;6021 +36160;Pommiers;224;6;230 +36161;Le Pont-Chrétien-Chabenet;925;11;936 +36162;Poulaines;845;20;865 +36163;Pouligny-Notre-Dame;720;3;723 +36164;Pouligny-Saint-Martin;222;4;226 +36165;Pouligny-Saint-Pierre;1069;28;1097 +36166;Préaux;161;1;162 +36167;Preuilly-la-Ville;162;4;166 +36168;Prissac;613;15;628 +36169;Pruniers;515;10;525 +36170;Reboursin;109;1;110 +36171;Reuilly;2025;39;2064 +36172;Rivarennes;566;5;571 +36173;Rosnay;519;13;532 +36174;Roussines;360;11;371 +36175;Rouvres-les-Bois;286;3;289 +36176;Ruffec;589;8;597 +36177;Sacierges-Saint-Martin;318;6;324 +36178;Saint-Aigny;282;12;294 +36179;Saint-Aoustrille;227;0;227 +36180;Saint-Août;836;14;850 +36181;Saint-Aubin;180;4;184 +36182;Saint-Benoît-du-Sault;602;20;622 +36184;Saint-Chartier;510;8;518 +36185;Saint-Christophe-en-Bazelle;379;3;382 +36186;Saint-Christophe-en-Boucherie;257;3;260 +36187;Saint-Civran;140;2;142 +36188;Saint-Cyran-du-Jambot;216;149;365 +36189;Saint-Denis-de-Jouhet;971;12;983 +36191;Saint-Florentin;534;7;541 +36192;Saint-Gaultier;1833;23;1856 +36194;Saint-Genou;971;16;987 +36195;Saint-Georges-sur-Arnon;575;14;589 +36196;Saint-Gilles;110;1;111 +36197;Saint-Hilaire-sur-Benaize;302;8;310 +36198;Saint-Lactencin;423;14;437 +36200;Saint-Marcel;1585;19;1604 +36202;Saint-Maur;3642;75;3717 +36203;Saint-Médard;48;0;48 +36204;Saint-Michel-en-Brenne;323;7;330 +36205;Saint-Pierre-de-Jards;122;2;124 +36207;Saint-Plantaire;616;14;630 +36209;Saint-Valentin;279;11;290 +36190;Sainte-Fauste;274;1;275 +36193;Sainte-Gemme;262;8;270 +36199;Sainte-Lizaigne;1176;24;1200 +36208;Sainte-Sévère-sur-Indre;776;13;789 +36210;Sarzay;307;11;318 +36211;Sassierges-Saint-Germain;477;8;485 +36212;Saulnay;157;3;160 +36213;Sauzelles;245;4;249 +36214;Sazeray;302;10;312 +36215;Ségry;504;13;517 +36216;Selles-sur-Nahon;70;2;72 +36217;Sembleçay;101;3;104 +36218;Sougé;143;5;148 +36219;Tendu;648;7;655 +36220;Thenay;891;19;910 +36221;Thevet-Saint-Julien;389;8;397 +36222;Thizay;232;7;239 +36223;Tilly;137;4;141 +36224;Tournon-Saint-Martin;1159;25;1184 +36225;Le Tranger;176;1;177 +36226;Tranzault;352;1;353 +36227;Urciers;250;3;253 +36229;Val-Fouzon;996;10;1006 +36228;Valençay;2367;108;2475 +36230;Vatan;1988;41;2029 +36231;Velles;985;21;1006 +36232;Vendœuvres;1064;16;1080 +36233;La Vernelle;748;7;755 +36234;Verneuil-sur-Igneraie;309;9;318 +36235;Veuil;376;8;384 +36236;Vicq-Exemplet;319;4;323 +36237;Vicq-sur-Nahon;729;19;748 +36238;Vigoulant;102;3;105 +36239;Vigoux;461;5;466 +36240;Vijon;303;4;307 +36241;Villedieu-sur-Indre;2697;48;2745 +36242;Villegongis;113;1;114 +36243;Villegouin;331;5;336 +36244;Villentrois-Faverolles-en-Berry;892;7;899 +36246;Villiers;170;2;172 +36247;Vineuil;1228;22;1250 +36248;Vouillon;234;3;237 +37001;Abilly;1151;19;1170 +37002;Ambillou;1786;29;1815 +37003;Amboise;12610;371;12981 +37004;Anché;416;11;427 +37005;Antogny-le-Tillac;510;5;515 +37006;Artannes-sur-Indre;2628;41;2669 +37007;Assay;166;4;170 +37008;Athée-sur-Cher;2673;37;2710 +37009;Autrèche;427;4;431 +37010;Auzouer-en-Touraine;2216;69;2285 +37011;Avoine;1743;37;1780 +37012;Avon-les-Roches;548;3;551 +37013;Avrillé-les-Ponceaux;481;9;490 +37014;Azay-le-Rideau;3491;98;3589 +37015;Azay-sur-Cher;3082;68;3150 +37016;Azay-sur-Indre;385;12;397 +37018;Ballan-Miré;7975;134;8109 +37019;Barrou;470;10;480 +37020;Beaulieu-lès-Loches;1767;36;1803 +37022;Beaumont-en-Véron;2699;124;2823 +37021;Beaumont-Louestault;1684;18;1702 +37023;Beaumont-Village;259;4;263 +37024;Benais;922;30;952 +37025;Berthenay;708;6;714 +37026;Betz-le-Château;571;8;579 +37027;Bléré;5272;72;5344 +37028;Bossay-sur-Claise;758;22;780 +37029;Bossée;330;5;335 +37030;Le Boulay;793;7;800 +37031;Bourgueil;3923;76;3999 +37032;Bournan;272;7;279 +37033;Boussay;218;6;224 +37034;Braslou;306;7;313 +37035;Braye-sous-Faye;310;6;316 +37036;Braye-sur-Maulne;172;5;177 +37037;Brèches;248;4;252 +37038;Bréhémont;769;7;776 +37039;Bridoré;524;10;534 +37040;Brizay;280;10;290 +37041;Bueil-en-Touraine;319;9;328 +37042;Candes-Saint-Martin;199;3;202 +37043;Cangey;1062;24;1086 +37044;La Celle-Guenand;372;5;377 +37045;La Celle-Saint-Avant;1080;24;1104 +37046;Céré-la-Ronde;459;3;462 +37047;Cerelles;1198;26;1224 +37048;Chambon;321;5;326 +37049;Chambourg-sur-Indre;1291;25;1316 +37050;Chambray-lès-Tours;11578;270;11848 +37051;Champigny-sur-Veude;851;8;859 +37053;Chanceaux-près-Loches;129;8;137 +37054;Chanceaux-sur-Choisille;3515;48;3563 +37055;Channay-sur-Lathan;841;14;855 +37052;Chançay;1137;19;1156 +37056;La Chapelle-aux-Naux;571;8;579 +37057;La Chapelle-Blanche-Saint-Martin;685;14;699 +37058;La Chapelle-sur-Loire;1433;28;1461 +37059;Charentilly;1257;30;1287 +37060;Chargé;1304;26;1330 +37061;Charnizay;502;17;519 +37062;Château-la-Vallière;1780;16;1796 +37063;Château-Renault;5001;79;5080 +37064;Chaumussay;226;7;233 +37065;Chaveignes;552;5;557 +37066;Chédigny;558;6;564 +37067;Cheillé;1801;21;1822 +37068;Chemillé-sur-Dême;719;9;728 +37069;Chemillé-sur-Indrois;222;8;230 +37070;Chenonceaux;351;5;356 +37071;Chezelles;133;2;135 +37072;Chinon;8242;325;8567 +37073;Chisseaux;598;15;613 +37074;Chouzé-sur-Loire;2081;24;2105 +37075;Cigogné;434;5;439 +37076;Cinais;423;14;437 +37077;Cinq-Mars-la-Pile;3566;48;3614 +37078;Ciran;414;8;422 +37079;Civray-de-Touraine;1840;45;1885 +37080;Civray-sur-Esves;202;3;205 +37081;Cléré-les-Pins;1410;21;1431 +37082;Continvoir;412;6;418 +37083;Cormery;1780;25;1805 +37232;Coteaux-sur-Loire;1926;22;1948 +37084;Couesmes;501;6;507 +37086;Courcelles-de-Touraine;494;7;501 +37087;Courcoué;255;9;264 +37085;Courçay;807;21;828 +37088;Couziers;112;1;113 +37089;Cravant-les-Côteaux;672;18;690 +37090;Crissay-sur-Manse;99;2;101 +37091;La Croix-en-Touraine;2294;60;2354 +37092;Crotelles;691;6;697 +37093;Crouzilles;531;6;537 +37094;Cussay;570;17;587 +37095;Dame-Marie-les-Bois;352;7;359 +37115;Descartes;3489;65;3554 +37096;Dierre;608;10;618 +37097;Dolus-le-Sec;671;25;696 +37098;Draché;745;19;764 +37099;Druye;950;12;962 +37100;Épeigné-les-Bois;423;7;430 +37101;Épeigné-sur-Dême;159;2;161 +37103;Esves-le-Moutier;144;2;146 +37104;Esvres;6010;110;6120 +37105;Faye-la-Vineuse;253;5;258 +37106;La Ferrière;310;6;316 +37107;Ferrière-Larçon;247;5;252 +37108;Ferrière-sur-Beaulieu;734;18;752 +37109;Fondettes;10307;492;10799 +37110;Francueil;1377;33;1410 +37111;Genillé;1521;17;1538 +37112;Gizeux;390;6;396 +37113;Le Grand-Pressigny;916;19;935 +37114;La Guerche;180;1;181 +37116;Les Hermites;562;16;578 +37117;Hommes;886;8;894 +37118;Huismes;1475;37;1512 +37119;L' Île-Bouchard;1553;35;1588 +37121;Jaulnay;258;4;262 +37122;Joué-lès-Tours;37893;447;38340 +37123;Langeais;4666;52;4718 +37124;Larçay;2462;40;2502 +37125;Lémeré;518;2;520 +37126;Lerné;296;10;306 +37127;Le Liège;364;9;373 +37128;Lignières-de-Touraine;1308;19;1327 +37129;Ligré;1065;21;1086 +37130;Ligueil;2188;38;2226 +37131;Limeray;1308;24;1332 +37133;Loché-sur-Indrois;506;9;515 +37132;Loches;6277;560;6837 +37134;Louans;648;13;661 +37136;Le Louroux;531;3;534 +37137;Lublé;144;4;148 +37138;Lussault-sur-Loire;789;15;804 +37139;Luynes;5097;145;5242 +37140;Luzé;250;5;255 +37141;Luzillé;983;15;998 +37142;Maillé;578;5;583 +37143;Manthelan;1363;29;1392 +37145;Marcé-sur-Esves;242;1;243 +37146;Marcilly-sur-Maulne;230;5;235 +37147;Marcilly-sur-Vienne;554;10;564 +37148;Marigny-Marmande;595;6;601 +37149;Marray;471;7;478 +37144;Marçay;519;6;525 +37150;Mazières-de-Touraine;1331;14;1345 +37151;La Membrolle-sur-Choisille;3324;62;3386 +37152;Mettray;2068;75;2143 +37153;Monnaie;4439;50;4489 +37154;Montbazon;4313;86;4399 +37155;Monthodon;631;7;638 +37156;Montlouis-sur-Loire;10666;151;10817 +37157;Montrésor;341;5;346 +37158;Montreuil-en-Touraine;832;14;846 +37159;Monts;7794;141;7935 +37160;Morand;347;6;353 +37161;Mosnes;804;12;816 +37162;Mouzay;474;17;491 +37163;Nazelles-Négron;3532;58;3590 +37165;Neuil;440;5;445 +37166;Neuillé-le-Lierre;794;7;801 +37167;Neuillé-Pont-Pierre;2004;37;2041 +37168;Neuilly-le-Brignon;300;9;309 +37169;Neuville-sur-Brenne;899;27;926 +37170;Neuvy-le-Roi;1078;58;1136 +37171;Noizay;1139;19;1158 +37172;Notre-Dame-d'Oé;4125;80;4205 +37173;Nouans-les-Fontaines;750;9;759 +37174;Nouâtre;823;13;836 +37175;Nouzilly;1250;30;1280 +37176;Noyant-de-Touraine;1215;60;1275 +37177;Orbigny;732;15;747 +37178;Panzoult;595;4;599 +37179;Parçay-Meslay;2369;29;2398 +37180;Parçay-sur-Vienne;644;6;650 +37181;Paulmy;233;10;243 +37182;Pernay;1349;13;1362 +37183;Perrusson;1486;28;1514 +37184;Le Petit-Pressigny;336;7;343 +37185;Pocé-sur-Cisse;1639;73;1712 +37186;Pont-de-Ruan;1189;12;1201 +37187;Ports;359;7;366 +37188;Pouzay;878;7;885 +37189;Preuilly-sur-Claise;1003;22;1025 +37190;Pussigny;168;4;172 +37191;Razines;236;6;242 +37192;Reignac-sur-Indre;1238;18;1256 +37193;Restigné;1226;26;1252 +37194;Reugny;1690;33;1723 +37195;La Riche;10448;95;10543 +37196;Richelieu;1716;20;1736 +37197;Rigny-Ussé;501;13;514 +37198;Rillé;306;8;314 +37199;Rilly-sur-Vienne;489;9;498 +37200;Rivarennes;1004;12;1016 +37201;Rivière;696;17;713 +37202;La Roche-Clermault;518;11;529 +37203;Rochecorbon;3146;91;3237 +37204;Rouziers-de-Touraine;1317;22;1339 +37205;Saché;1392;19;1411 +37206;Saint-Antoine-du-Rocher;1720;37;1757 +37207;Saint-Aubin-le-Dépeint;315;2;317 +37208;Saint-Avertin;15025;315;15340 +37210;Saint-Benoît-la-Forêt;851;17;868 +37211;Saint-Branchs;2607;31;2638 +37213;Saint-Christophe-sur-le-Nais;1127;16;1143 +37214;Saint-Cyr-sur-Loire;15960;356;16316 +37216;Saint-Épain;1572;24;1596 +37217;Saint-Étienne-de-Chigny;1606;19;1625 +37218;Saint-Flovier;566;8;574 +37219;Saint-Genouph;1050;17;1067 +37220;Saint-Germain-sur-Vienne;375;4;379 +37221;Saint-Hippolyte;646;8;654 +37222;Saint-Jean-Saint-Germain;762;27;789 +37223;Saint-Laurent-de-Lin;322;1;323 +37224;Saint-Laurent-en-Gâtines;948;15;963 +37225;Saint-Martin-le-Beau;3156;58;3214 +37228;Saint-Nicolas-de-Bourgueil;1109;14;1123 +37229;Saint-Nicolas-des-Motets;261;7;268 +37230;Saint-Ouen-les-Vignes;1016;28;1044 +37231;Saint-Paterne-Racan;1665;28;1693 +37233;Saint-Pierre-des-Corps;15838;238;16076 +37234;Saint-Quentin-sur-Indrois;510;10;520 +37236;Saint-Règle;609;11;620 +37237;Saint-Roch;1255;18;1273 +37238;Saint-Senoch;570;6;576 +37212;Sainte-Catherine-de-Fierbois;761;11;772 +37226;Sainte-Maure-de-Touraine;4214;50;4264 +37240;Saunay;696;14;710 +37241;Savigné-sur-Lathan;1349;19;1368 +37242;Savigny-en-Véron;1542;30;1572 +37243;Savonnières;3152;76;3228 +37244;Sazilly;237;10;247 +37245;Semblançay;2171;45;2216 +37246;Sennevières;209;4;213 +37247;Sepmes;630;9;639 +37248;Seuilly;359;15;374 +37249;Sonzay;1387;19;1406 +37250;Sorigny;2643;75;2718 +37251;Souvigné;840;10;850 +37252;Souvigny-de-Touraine;391;4;395 +37253;Sublaines;191;6;197 +37254;Tauxigny-Saint-Bauld;1691;29;1720 +37255;Tavant;263;1;264 +37256;Theneuil;298;5;303 +37257;Thilouze;1721;23;1744 +37258;Thizay;281;4;285 +37260;La Tour-Saint-Gelin;523;8;531 +37259;Tournon-Saint-Pierre;459;11;470 +37261;Tours;135787;2829;138616 +37262;Trogues;310;4;314 +37263;Truyes;2433;41;2474 +37264;Vallères;1244;16;1260 +37265;Varennes;246;4;250 +37266;Veigné;6266;131;6397 +37267;Véretz;4496;79;4575 +37268;Verneuil-le-Château;126;0;126 +37269;Verneuil-sur-Indre;480;21;501 +37270;Vernou-sur-Brenne;2707;41;2748 +37271;Villaines-les-Rochers;1067;11;1078 +37272;Villandry;1114;36;1150 +37273;La Ville-aux-Dames;5487;75;5562 +37274;Villebourg;298;3;301 +37275;Villedômain;115;3;118 +37276;Villedômer;1359;31;1390 +37277;Villeloin-Coulangé;599;4;603 +37278;Villeperdue;1030;7;1037 +37279;Villiers-au-Bouin;756;6;762 +37280;Vou;199;9;208 +37281;Vouvray;3238;72;3310 +37282;Yzeures-sur-Creuse;1380;26;1406 +38001;Les Abrets en Dauphiné;6311;104;6415 +38002;Les Adrets;1006;23;1029 +38003;Agnin;1106;11;1117 +38004;L' Albenc;1244;22;1266 +38005;Allemond;971;18;989 +38006;Allevard;4102;108;4210 +38008;Ambel;28;0;28 +38009;Anjou;1013;23;1036 +38010;Annoisin-Chatelans;676;18;694 +38011;Anthon;1061;12;1073 +38012;Aoste;2878;54;2932 +38013;Apprieu;3313;88;3401 +38297;Arandon-Passins;1809;31;1840 +38015;Artas;1809;38;1847 +38017;Assieu;1472;21;1493 +38018;Auberives-en-Royans;376;11;387 +38019;Auberives-sur-Varèze;1484;29;1513 +38020;Auris;190;4;194 +38225;Autrans-Méaudre en Vercors;3000;116;3116 +38022;Les Avenières Veyrins-Thuellin;7739;157;7896 +38023;Avignonet;197;5;202 +38026;La Balme-les-Grottes;1060;12;1072 +38027;Barraux;1886;54;1940 +38029;La Bâtie-Montgascon;1919;42;1961 +38030;Beaucroissant;1682;30;1712 +38031;Beaufin;20;0;20 +38032;Beaufort;548;11;559 +38033;Beaulieu;638;19;657 +38034;Beaurepaire;4921;82;5003 +38035;Beauvoir-de-Marc;1121;15;1136 +38036;Beauvoir-en-Royans;92;2;94 +38037;Bellegarde-Poussieu;990;14;1004 +38038;Belmont;598;11;609 +38039;Bernin;3072;104;3176 +38040;Besse;126;4;130 +38041;Bessins;116;3;119 +38042;Bévenais;1008;20;1028 +38043;Bilieu;1544;42;1586 +38044;Biol;1419;40;1459 +38045;Biviers;2386;111;2497 +38046;Bizonnes;963;8;971 +38047;Blandin;145;3;148 +38048;Bonnefamille;1096;18;1114 +38049;Bossieu;294;7;301 +38050;Le Bouchage;623;9;632 +38051;Bougé-Chambalud;1375;21;1396 +38052;Le Bourg-d'Oisans;3278;102;3380 +38053;Bourgoin-Jallieu;28387;637;29024 +38054;Bouvesse-Quirieu;1512;21;1533 +38055;Brangues;626;8;634 +38056;Bressieux;93;2;95 +38057;Bresson;684;15;699 +38058;Brézins;2132;30;2162 +38059;Brié-et-Angonnes;2556;42;2598 +38060;Brion;144;5;149 +38061;La Buisse;3142;67;3209 +38062;La Buissière;669;19;688 +38063;Burcin;423;14;437 +38064;Cessieu;2984;75;3059 +38065;Châbons;2075;53;2128 +38066;Chalon;180;5;185 +38067;Chamagnieu;1674;37;1711 +38070;Le Champ-près-Froges;1197;14;1211 +38071;Champ-sur-Drac;3007;34;3041 +38068;Champagnier;1226;30;1256 +38069;Champier;1400;21;1421 +38567;Chamrousse;422;5;427 +38072;Chanas;2589;42;2631 +38073;Chantepérier;203;3;206 +38074;Chantesse;337;6;343 +38075;Chapareillan;3010;66;3076 +38076;La Chapelle-de-la-Tour;1807;65;1872 +38077;La Chapelle-de-Surieu;751;16;767 +38078;La Chapelle-du-Bard;571;7;578 +38080;Charancieu;774;20;794 +38081;Charantonnay;1911;42;1953 +38082;Charavines;1925;45;1970 +38083;Charette;459;15;474 +38084;Charnècles;1438;26;1464 +38085;Charvieu-Chavagneux;9661;79;9740 +38087;Chasse-sur-Rhône;6048;57;6105 +38086;Chasselay;406;8;414 +38089;Chassignieu;232;4;236 +38090;Château-Bernard;267;5;272 +38091;Châteauvilain;716;12;728 +38456;Châtel-en-Trièves;449;12;461 +38092;Châtelus;88;3;91 +38093;Châtenay;440;7;447 +38094;Châtonnay;2072;43;2115 +38095;Chatte;2512;209;2721 +38097;Chavanoz;4685;61;4746 +38098;Chélieu;676;14;690 +38099;Chevrières;708;23;731 +38100;Le Cheylas;2566;42;2608 +38101;Cheyssieu;1024;16;1040 +38102;Chèzeneuve;596;13;609 +38103;Chichilianne;305;2;307 +38104;Chimilin;1452;33;1485 +38105;Chirens;2337;44;2381 +38106;Cholonge;329;1;330 +38107;Chonas-l'Amballan;1668;52;1720 +38108;Choranche;121;0;121 +38109;Chozeau;1064;26;1090 +38110;Chuzelles;2181;46;2227 +38111;Claix;7932;197;8129 +38112;Clavans-en-Haut-Oisans;101;1;102 +38113;Clelles;543;6;549 +38114;Clonas-sur-Varèze;1458;32;1490 +38116;Cognet;42;0;42 +38117;Cognin-les-Gorges;635;11;646 +38118;Colombe;1574;43;1617 +38120;La Combe-de-Lancey;701;17;718 +38124;Corbelin;2235;47;2282 +38126;Corenc;4013;127;4140 +38127;Cornillon-en-Trièves;165;5;170 +38128;Corps;486;5;491 +38129;Corrençon-en-Vercors;354;18;372 +38130;La Côte-Saint-André;4811;286;5097 +38131;Les Côtes-d'Arey;2026;74;2100 +38132;Les Côtes-de-Corps;70;1;71 +38133;Coublevie;4836;395;5231 +38134;Cour-et-Buis;879;19;898 +38135;Courtenay;1276;21;1297 +38136;Crachier;508;15;523 +38137;Cras;438;13;451 +38138;Crémieu;3282;62;3344 +38439;Crêts en Belledonne;3339;53;3392 +38139;Creys-Mépieu;1503;19;1522 +38140;Crolles;8247;252;8499 +38141;Culin;745;14;759 +38253;Les Deux Alpes;1908;36;1944 +38144;Diémoz;2722;35;2757 +38146;Dizimieu;837;26;863 +38147;Doissin;881;25;906 +38148;Dolomieu;3167;71;3238 +38149;Domarin;1661;36;1697 +38150;Domène;6745;70;6815 +38151;Échirolles;36840;211;37051 +38152;Eclose-Badinières;1434;28;1462 +38153;Engins;465;10;475 +38154;Entraigues;230;2;232 +38155;Entre-deux-Guiers;1763;29;1792 +38156;Les Éparres;985;31;1016 +38157;Estrablin;3365;87;3452 +38158;Eybens;10185;117;10302 +38159;Eydoche;533;13;546 +38160;Eyzin-Pinet;2252;112;2364 +38161;Faramans;1038;6;1044 +38162;Faverges-de-la-Tour;1445;40;1485 +38166;La Flachère;490;14;504 +38167;Flachères;524;5;529 +38169;Fontaine;22523;267;22790 +38170;Fontanil-Cornillon;2710;39;2749 +38171;La Forteresse;322;4;326 +38172;Four;1494;30;1524 +38173;Le Freney-d'Oisans;252;6;258 +38174;La Frette;1094;23;1117 +38175;Froges;3331;61;3392 +38176;Frontonas;2069;53;2122 +38177;La Garde;98;0;98 +38179;Gières;6779;82;6861 +38180;Gillonnay;1012;28;1040 +38181;Goncelin;2425;36;2461 +38182;Le Grand-Lemps;3094;58;3152 +38183;Granieu;501;9;510 +38184;Grenay;1606;20;1626 +38185;Grenoble;158454;2171;160625 +38186;Gresse-en-Vercors;395;3;398 +38187;Le Gua;1779;25;1804 +38163;Le Haut-Bréda;398;11;409 +38188;Herbeys;1361;26;1387 +38189;Heyrieux;4731;64;4795 +38190;Hières-sur-Amby;1192;27;1219 +38191;Huez;1307;34;1341 +38192;Hurtières;168;6;174 +38193;L' Isle-d'Abeau;16124;281;16405 +38194;Izeaux;2147;34;2181 +38195;Izeron;726;9;735 +38197;Janneyrias;1829;16;1845 +38198;Jarcieu;1037;22;1059 +38199;Jardin;2207;57;2264 +38200;Jarrie;3746;68;3814 +38203;Laffrey;455;8;463 +38204;Lalley;193;6;199 +38205;Lans-en-Vercors;2651;125;2776 +38206;Laval;984;37;1021 +38207;Lavaldens;151;3;154 +38208;Lavars;148;3;151 +38209;Lentiol;222;7;229 +38210;Leyrieu;838;14;852 +38211;Lieudieu;341;5;346 +38212;Livet-et-Gavet;1315;10;1325 +38213;Longechenal;571;12;583 +38214;Lumbin;2136;72;2208 +38215;Luzinay;2302;43;2345 +38216;Malleval-en-Vercors;53;1;54 +38217;Marcieu;72;2;74 +38218;Marcilloles;1104;20;1124 +38219;Marcollin;670;10;680 +38221;Marnans;147;3;150 +38222;Massieu;747;17;764 +38223;Maubec;1745;61;1806 +38224;Mayres-Savel;97;4;101 +38226;Mens;1397;76;1473 +38228;Merlas;487;10;497 +38229;Meylan;17129;399;17528 +38230;Meyrié;995;40;1035 +38231;Meyrieu-les-Étangs;1015;40;1055 +38232;Meyssiez;637;8;645 +38235;Miribel-Lanchâtre;433;8;441 +38236;Miribel-les-Échelles;1721;38;1759 +38237;Mizoën;191;4;195 +38238;Moidieu-Détourbe;1889;35;1924 +38239;Moirans;7852;162;8014 +38240;Moissieu-sur-Dolon;707;14;721 +38241;Monestier-d'Ambel;21;0;21 +38242;Monestier-de-Clermont;1427;31;1458 +38243;Le Monestier-du-Percy;251;6;257 +38244;Monsteroux-Milieu;792;19;811 +38258;Mont-Saint-Martin;79;4;83 +38245;Montagne;266;6;272 +38246;Montagnieu;1084;17;1101 +38247;Montalieu-Vercieu;3368;51;3419 +38248;Montaud;543;22;565 +38249;Montbonnot-Saint-Martin;5134;558;5692 +38250;Montcarra;532;8;540 +38252;Montchaboud;339;9;348 +38254;Monteynard;487;12;499 +38255;Montfalcon;133;0;133 +38256;Montferrat;1786;23;1809 +38257;Montrevel;451;12;463 +38259;Montseveroux;961;16;977 +38260;Moras;511;18;529 +38261;Morestel;4469;99;4568 +38263;Morette;428;7;435 +38264;La Morte;132;0;132 +38265;La Motte-d'Aveillans;1712;22;1734 +38266;La Motte-Saint-Martin;444;9;453 +38267;Mottier;715;12;727 +38268;Le Moutaret;261;3;264 +38269;La Mure;4948;209;5157 +38270;La Murette;1884;65;1949 +38271;Murianette;882;11;893 +38272;Murinais;397;8;405 +38273;Nantes-en-Ratier;466;19;485 +38276;Nivolas-Vermelle;2649;53;2702 +38277;Notre-Dame-de-Commiers;518;6;524 +38278;Notre-Dame-de-l'Osier;492;9;501 +38279;Notre-Dame-de-Mésage;1147;12;1159 +38280;Notre-Dame-de-Vaulx;509;22;531 +38281;Noyarey;2223;76;2299 +38282;Optevoz;843;15;858 +38283;Oris-en-Rattier;114;4;118 +38284;Ornacieux-Balbins;844;26;870 +38285;Ornon;152;4;156 +38286;Oulles;7;0;7 +38287;Oyeu;1006;19;1025 +38288;Oytier-Saint-Oblas;1637;26;1663 +38289;Oz;235;4;239 +38290;Pact;841;15;856 +38291;Pajay;1146;18;1164 +38294;Panossas;666;16;682 +38295;Parmilieu;709;12;721 +38296;Le Passage;793;42;835 +38298;Le Péage-de-Roussillon;6680;76;6756 +38299;Pellafol;136;2;138 +38300;Penol;350;9;359 +38301;Percy;172;4;176 +38303;La Pierre;574;5;579 +38304;Pierre-Châtel;1496;36;1532 +38307;Pisieu;531;9;540 +38308;Plan;261;2;263 +38395;Plateau-des-Petites-Roches;2434;74;2508 +38309;Poisat;2168;28;2196 +38310;Poliénas;1188;16;1204 +38311;Pommier-de-Beaurepaire;704;15;719 +38313;Ponsonnas;291;15;306 +38315;Le Pont-de-Beauvoisin;3630;141;3771 +38316;Pont-de-Chéruy;5772;42;5814 +38317;Le Pont-de-Claix;10435;63;10498 +38319;Pont-en-Royans;774;33;807 +38318;Pont-Évêque;5210;49;5259 +38314;Pontcharra;7344;170;7514 +38320;Porcieu-Amblagnieu;1766;40;1806 +38479;Porte-des-Bonnevaux;2015;52;2067 +38321;Prébois;164;8;172 +38322;Presles;87;2;89 +38323;Pressins;1156;22;1178 +38324;Primarette;720;18;738 +38325;Proveysieux;507;9;516 +38326;Prunières;355;5;360 +38328;Quaix-en-Chartreuse;893;32;925 +38329;Quet-en-Beaumont;67;0;67 +38330;Quincieu;103;0;103 +38331;Réaumont;1021;32;1053 +38332;Renage;3507;54;3561 +38333;Rencurel;322;6;328 +38334;Revel;1314;40;1354 +38335;Revel-Tourdan;1053;39;1092 +38336;Reventin-Vaugris;1909;39;1948 +38337;Rives;6476;80;6556 +38338;La Rivière;747;9;756 +38339;Roche;2083;53;2136 +38340;Les Roches-de-Condrieu;1925;36;1961 +38341;Rochetoirin;1116;40;1156 +38342;Roissard;306;7;313 +38343;Romagnieu;1580;31;1611 +38344;Roussillon;8455;131;8586 +38345;Rovon;609;11;620 +38346;Royas;396;8;404 +38347;Roybon;1157;28;1185 +38348;Ruy-Montceau;4529;102;4631 +38349;Sablons;2309;22;2331 +38351;Saint-Agnin-sur-Bion;1043;21;1064 +38352;Saint-Alban-de-Roche;1982;56;2038 +38353;Saint-Alban-du-Rhône;842;18;860 +38354;Saint-Albin-de-Vaulserre;405;5;410 +38355;Saint-Andéol;122;6;128 +38356;Saint-André-en-Royans;315;18;333 +38357;Saint-André-le-Gaz;2793;152;2945 +38359;Saint Antoine l'Abbaye;1155;30;1185 +38360;Saint-Appolinard;409;8;417 +38361;Saint-Arey;84;5;89 +38362;Saint-Aupre;1137;52;1189 +38363;Saint-Barthélemy;941;38;979 +38364;Saint-Barthélemy-de-Séchilienne;433;4;437 +38365;Saint-Baudille-de-la-Tour;814;20;834 +38366;Saint-Baudille-et-Pipet;257;8;265 +38368;Saint-Blaise-du-Buis;1062;25;1087 +38370;Saint-Bonnet-de-Chavagne;634;18;652 +38372;Saint-Bueil;723;11;734 +38373;Saint-Cassien;1162;43;1205 +38374;Saint-Chef;3585;119;3704 +38375;Saint-Christophe-en-Oisans;107;0;107 +38376;Saint-Christophe-sur-Guiers;838;9;847 +38377;Saint-Clair-de-la-Tour;3424;59;3483 +38378;Saint-Clair-du-Rhône;3817;87;3904 +38379;Saint-Clair-sur-Galaure;282;4;286 +38380;Saint-Didier-de-Bizonnes;302;4;306 +38381;Saint-Didier-de-la-Tour;2045;51;2096 +38382;Saint-Égrève;15838;256;16094 +38383;Saint-Étienne-de-Crossey;2542;105;2647 +38384;Saint-Étienne-de-Saint-Geoirs;3225;44;3269 +38386;Saint-Geoire-en-Valdaine;2399;42;2441 +38387;Saint-Geoirs;516;13;529 +38389;Saint-Georges-d'Espéranche;3354;66;3420 +38388;Saint-Georges-de-Commiers;2276;30;2306 +38390;Saint-Gervais;549;9;558 +38391;Saint-Guillaume;258;5;263 +38392;Saint-Hilaire-de-Brens;636;17;653 +38393;Saint-Hilaire-de-la-Côte;1504;32;1536 +38394;Saint-Hilaire-du-Rosier;1886;30;1916 +38396;Saint-Honoré;814;27;841 +38397;Saint-Ismier;6966;322;7288 +38398;Saint-Jean-d'Avelanne;966;13;979 +38403;Saint-Jean-d'Hérans;288;7;295 +38399;Saint-Jean-de-Bournay;4594;105;4699 +38400;Saint-Jean-de-Moirans;3536;80;3616 +38401;Saint-Jean-de-Soudain;1585;30;1615 +38402;Saint-Jean-de-Vaulx;532;19;551 +38404;Saint-Jean-le-Vieux;292;4;296 +38405;Saint-Joseph-de-Rivière;1219;28;1247 +38406;Saint-Julien-de-l'Herms;149;5;154 +38408;Saint-Just-Chaleyssin;2568;58;2626 +38409;Saint-Just-de-Claix;1212;24;1236 +38410;Saint-Lattier;1338;23;1361 +38412;Saint-Laurent-du-Pont;4531;93;4624 +38413;Saint-Laurent-en-Beaumont;454;9;463 +38415;Saint-Marcel-Bel-Accueil;1393;38;1431 +38416;Saint-Marcellin;7903;199;8102 +38421;Saint-Martin-d'Hères;38487;268;38755 +38422;Saint-Martin-d'Uriage;5451;174;5625 +38419;Saint-Martin-de-Clelles;186;2;188 +38115;Saint-Martin-de-la-Cluze;717;17;734 +38420;Saint-Martin-de-Vaulserre;260;5;265 +38423;Saint-Martin-le-Vinoux;5778;61;5839 +38424;Saint-Maurice-en-Trièves;155;4;159 +38425;Saint-Maurice-l'Exil;6141;91;6232 +38426;Saint-Maximin;654;15;669 +38427;Saint-Michel-de-Saint-Geoirs;304;4;308 +38428;Saint-Michel-en-Beaumont;31;0;31 +38429;Saint-Michel-les-Portes;269;8;277 +38430;Saint-Mury-Monteymond;320;7;327 +38431;Saint-Nazaire-les-Eymes;2955;89;3044 +38432;Saint-Nicolas-de-Macherin;938;24;962 +38433;Saint-Nizier-du-Moucherotte;1098;31;1129 +38434;Saint-Ondras;640;6;646 +38437;Saint-Paul-d'Izeaux;295;6;301 +38436;Saint-Paul-de-Varces;2173;38;2211 +38438;Saint-Paul-lès-Monestier;267;1;268 +38446;Saint-Pierre-d'Entremont;571;14;585 +38440;Saint-Pierre-de-Bressieux;761;16;777 +38442;Saint-Pierre-de-Chartreuse;1015;28;1043 +38443;Saint-Pierre-de-Chérennes;464;12;476 +38444;Saint-Pierre-de-Méaroz;126;7;133 +38445;Saint-Pierre-de-Mésage;764;6;770 +38448;Saint-Prim;1372;30;1402 +38449;Saint-Quentin-Fallavier;6103;66;6169 +38450;Saint-Quentin-sur-Isère;1451;19;1470 +38451;Saint-Romain-de-Jalionas;3288;41;3329 +38452;Saint-Romain-de-Surieu;353;9;362 +38453;Saint-Romans;1778;41;1819 +38454;Saint-Sauveur;2098;48;2146 +38455;Saint-Savin;4076;80;4156 +38457;Saint-Siméon-de-Bressieux;2887;64;2951 +38458;Saint-Sorlin-de-Morestel;627;16;643 +38459;Saint-Sorlin-de-Vienne;878;7;885 +38460;Saint-Sulpice-des-Rivoires;430;8;438 +38462;Saint-Théoffrey;521;15;536 +38463;Saint-Vérand;1721;40;1761 +38464;Saint-Victor-de-Cessieu;2240;49;2289 +38465;Saint-Victor-de-Morestel;1092;22;1114 +38466;Saint-Vincent-de-Mercuze;1519;49;1568 +38350;Sainte-Agnès;563;18;581 +38358;Sainte-Anne-sur-Gervonde;692;10;702 +38369;Sainte-Blandine;977;36;1013 +38414;Sainte-Luce;43;0;43 +38417;Sainte-Marie-d'Alloix;478;17;495 +38418;Sainte-Marie-du-Mont;237;2;239 +38467;Salagnon;1420;38;1458 +38468;Salaise-sur-Sanne;4513;72;4585 +38469;La Salette-Fallavaux;65;1;66 +38470;La Salle-en-Beaumont;318;5;323 +38471;Le Sappey-en-Chartreuse;1121;30;1151 +38472;Sarcenas;189;8;197 +38473;Sardieu;1124;21;1145 +38474;Sassenage;11376;201;11577 +38475;Satolas-et-Bonce;2419;27;2446 +38476;Savas-Mépin;895;10;905 +38478;Séchilienne;1052;13;1065 +38480;Septème;2063;42;2105 +38481;Sérézin-de-la-Tour;1057;31;1088 +38483;Sermérieu;1668;39;1707 +38484;Serpaize;1939;25;1964 +38275;Serre-Nerpol;296;34;330 +38485;Seyssinet-Pariset;12013;158;12171 +38486;Seyssins;7685;106;7791 +38487;Seyssuel;2003;52;2055 +38488;Siccieu-Saint-Julien-et-Carisieu;583;16;599 +38489;Siévoz;136;2;138 +38490;Sillans;1909;46;1955 +38492;Sinard;692;23;715 +38494;Soleymieu;777;20;797 +38495;La Sône;584;4;588 +38496;Sonnay;1241;25;1266 +38497;Sousville;140;0;140 +38498;Succieu;735;21;756 +38407;La Sure en Chartreuse;984;37;1021 +38499;Susville;1272;32;1304 +38500;Têche;574;6;580 +38501;Tencin;2095;24;2119 +38503;La Terrasse;2539;122;2661 +38504;Theys;1961;74;2035 +38505;Thodure;743;14;757 +38507;Tignieu-Jameyzieu;7249;93;7342 +38508;Torchefelon;739;13;752 +38509;La Tour-du-Pin;8080;206;8286 +38511;Le Touvet;3229;102;3331 +38512;Tramolé;754;24;778 +38513;Treffort;292;7;299 +38514;Tréminis;178;1;179 +38515;Trept;2170;55;2225 +38516;La Tronche;6596;141;6737 +38517;Tullins;7680;121;7801 +38560;Val-de-Virieu;1539;19;1558 +38518;Valbonnais;495;8;503 +38519;Valencin;2799;48;2847 +38520;Valencogne;689;20;709 +38521;La Valette;71;3;74 +38522;Valjouffrey;135;2;137 +38523;Varacieux;854;21;875 +38524;Varces-Allières-et-Risset;8250;167;8417 +38525;Vasselin;474;5;479 +38526;Vatilieu;365;11;376 +38527;Vaujany;337;4;341 +38528;Vaulnaveys-le-Bas;1282;29;1311 +38529;Vaulnaveys-le-Haut;3867;60;3927 +38530;Vaulx-Milieu;2553;29;2582 +38531;Velanne;537;6;543 +38532;Vénérieu;846;9;855 +38533;Venon;729;16;745 +38535;Vernas;266;6;272 +38536;Vernioz;1294;26;1320 +38537;La Verpillière;7226;87;7313 +38538;Le Versoud;4818;56;4874 +38539;Vertrieu;639;19;658 +38540;Veurey-Voroize;1438;26;1464 +38542;Veyssilieu;336;8;344 +38543;Vézeronce-Curtin;2129;35;2164 +38544;Vienne;29306;377;29683 +38545;Vif;8532;124;8656 +38546;Vignieu;1015;95;1110 +38292;Villages du Lac de Paladru;2485;59;2544 +38547;Villard-Bonnot;7107;63;7170 +38548;Villard-de-Lans;4210;224;4434 +38549;Villard-Notre-Dame;27;3;30 +38550;Villard-Reculas;56;0;56 +38551;Villard-Reymond;43;1;44 +38552;Villard-Saint-Christophe;406;12;418 +38556;Ville-sous-Anjou;1173;25;1198 +38553;Villefontaine;18763;236;18999 +38554;Villemoirieu;1852;69;1921 +38555;Villeneuve-de-Marc;1147;18;1165 +38557;Villette-d'Anthon;4936;85;5021 +38558;Villette-de-Vienne;1872;30;1902 +38559;Vinay;4251;73;4324 +38561;Viriville;1630;22;1652 +38562;Vizille;7361;173;7534 +38563;Voiron;20108;495;20603 +38564;Voissant;226;10;236 +38565;Voreppe;9293;362;9655 +38566;Vourey;1705;39;1744 +39001;Abergement-la-Ronce;849;25;874 +39002;Abergement-le-Grand;58;1;59 +39003;Abergement-le-Petit;42;0;42 +39004;Abergement-lès-Thésy;60;3;63 +39006;Aiglepierre;436;16;452 +39007;Alièze;153;5;158 +39008;Amange;433;59;492 +39009;Andelot-en-Montagne;526;12;538 +39010;Andelot-Morval;95;2;97 +39011;Annoire;377;7;384 +39013;Arbois;3336;208;3544 +39014;Archelange;218;6;224 +39015;Ardon;115;2;117 +39586;Aresches;32;0;32 +39016;Arinthod;1114;32;1146 +39017;Arlay;1227;22;1249 +39018;Aromas;652;18;670 +39020;Arsure-Arsurette;101;2;103 +39019;Les Arsures;230;10;240 +39022;Asnans-Beauvoisin;731;11;742 +39024;Audelange;270;7;277 +39025;Augea;277;7;284 +39026;Augerans;178;1;179 +39027;Augisey;201;5;206 +39028;Aumont;468;8;476 +39029;Aumur;366;8;374 +39030;Authume;821;21;842 +39031;Auxange;201;4;205 +39032;Avignon-lès-Saint-Claude;383;18;401 +39034;Balaiseaux;309;8;317 +39035;Balanod;349;6;355 +39037;Bans;191;4;195 +39038;Barésia-sur-l'Ain;150;2;152 +39039;La Barre;232;6;238 +39040;Barretaine;178;2;180 +39041;Baume-les-Messieurs;162;6;168 +39042;Baverans;500;22;522 +39043;Beaufort-Orbagna;1351;16;1367 +39045;Beffia;77;3;80 +39046;Bellecombe;63;4;67 +39047;Bellefontaine;537;16;553 +39048;Belmont;262;8;270 +39049;Bersaillin;405;14;419 +39050;Besain;161;11;172 +39051;Biarne;407;5;412 +39052;Bief-des-Maisons;72;0;72 +39053;Bief-du-Fourg;203;5;208 +39054;Biefmorin;98;1;99 +39055;Billecul;47;1;48 +39056;Bletterans;1446;19;1465 +39057;Blois-sur-Seille;105;1;106 +39058;Blye;162;5;167 +39059;Bois-d'Amont;1655;42;1697 +39060;Bois-de-Gand;57;1;58 +39061;Boissia;118;5;123 +39062;La Boissière;68;0;68 +39063;Bonlieu;261;4;265 +39065;Bonnefontaine;104;0;104 +39066;Bornay;176;6;182 +39068;Les Bouchoux;317;9;326 +39070;Bourg-de-Sirod;94;2;96 +39072;Bracon;273;7;280 +39073;Brainans;171;6;177 +39074;Brans;216;8;224 +39076;La Bretenière;220;1;221 +39077;Bretenières;40;1;41 +39078;Brevans;669;14;683 +39079;Briod;204;9;213 +39080;Broissia;65;0;65 +39081;Buvilly;385;7;392 +39083;Censeau;301;6;307 +39084;Cernans;140;4;144 +39085;Cerniébaud;88;1;89 +39086;Cernon;251;3;254 +39088;Cesancey;392;11;403 +39021;La Chailleuse;602;13;615 +39090;Chaînée-des-Coupis;181;4;185 +39091;Les Chalesmes;96;1;97 +39092;Chambéria;175;1;176 +39093;Chamblay;424;10;434 +39094;Chamole;166;3;169 +39095;Champagne-sur-Loue;125;5;130 +39096;Champagney;480;8;488 +39097;Champagnole;7958;388;8346 +39099;Champdivers;429;17;446 +39100;Champrougier;101;3;104 +39101;Champvans;1414;43;1457 +39102;Chancia;226;4;230 +39103;La Chapelle-sur-Furieuse;315;1;316 +39104;Chapelle-Voland;602;7;609 +39105;Chapois;224;2;226 +39106;Charchilla;280;4;284 +39107;Charcier;129;3;132 +39108;Charency;55;1;56 +39109;Charézier;175;2;177 +39110;La Charme;68;0;68 +39111;Charnod;40;0;40 +39112;La Chassagne;119;2;121 +39339;Chassal-Molinges;1131;28;1159 +39114;Château-Chalon;146;6;152 +39118;Châtel-de-Joux;51;0;51 +39116;La Châtelaine;139;2;141 +39117;Chatelay;106;6;112 +39119;Le Chateley;87;3;90 +39120;Châtelneuf;138;6;144 +39121;Châtenois;389;7;396 +39122;Châtillon;112;7;119 +39124;Chaumergy;482;16;498 +39126;La Chaumusse;402;11;413 +39127;Chaussenans;100;1;101 +39128;Chaussin;1630;24;1654 +39133;Chaux-Champagny;71;2;73 +39129;Chaux-des-Crotenay;404;14;418 +39131;La Chaux-du-Dombief;544;13;557 +39132;La Chaux-en-Bresse;39;1;40 +39134;Chavéria;226;8;234 +39136;Chemenot;37;1;38 +39138;Chemin;343;10;353 +39139;Chêne-Bernard;64;0;64 +39140;Chêne-Sec;36;0;36 +39141;Chevigny;280;6;286 +39142;Chevreaux;122;1;123 +39143;Chevrotaine;32;0;32 +39145;Chille;293;19;312 +39146;Chilly-le-Vignoble;667;20;687 +39147;Chilly-sur-Salins;114;3;117 +39149;Chissey-sur-Loue;320;9;329 +39150;Choisey;1050;31;1081 +39151;Choux;119;4;123 +39153;Cize;788;28;816 +39154;Clairvaux-les-Lacs;1451;49;1500 +39155;Clucy;78;0;78 +39156;Cogna;252;15;267 +39157;Coiserette;52;3;55 +39159;Colonne;264;2;266 +39160;Commenailles;890;15;905 +39162;Condamine;272;6;278 +39163;Condes;109;7;116 +39164;Conliège;668;27;695 +39165;Conte;56;0;56 +39166;Cornod;218;7;225 +39167;Cosges;364;6;370 +39491;Coteaux du Lizon;2397;71;2468 +39168;Courbette;51;0;51 +39169;Courbouzon;590;14;604 +39170;Courlans;926;29;955 +39171;Courlaoux;1106;32;1138 +39172;Courtefontaine;249;16;265 +39173;Cousance;1308;23;1331 +39174;Coyrière;65;1;66 +39175;Coyron;73;7;80 +39176;Cramans;524;8;532 +39178;Crans;74;1;75 +39179;Crenans;239;5;244 +39180;Cressia;258;119;377 +39182;Crissey;653;25;678 +39183;Crotenay;640;89;729 +39184;Les Crozets;199;3;202 +39185;Cuisia;392;12;404 +39187;Cuvier;262;2;264 +39188;Dammartin-Marpain;342;6;348 +39189;Damparis;2694;80;2774 +39190;Dampierre;1278;27;1305 +39191;Darbonnay;92;2;94 +39192;Denezières;72;1;73 +39193;Le Deschaux;1021;8;1029 +39194;Desnes;481;6;487 +39196;Les Deux-Fays;106;1;107 +39197;Digna;350;12;362 +39198;Dole;23708;898;24606 +39199;Domblans;1232;32;1264 +39200;Dompierre-sur-Mont;230;7;237 +39201;Doucier;298;30;328 +39202;Dournon;140;1;141 +39203;Doye;101;2;103 +39204;Dramelay;29;3;32 +39205;Éclans-Nenon;387;5;392 +39206;Écleux;224;10;234 +39207;Écrille;83;3;86 +39208;Entre-deux-Monts;142;9;151 +39210;Équevillon;582;14;596 +39211;Les Essards-Taignevaux;260;4;264 +39214;Esserval-Tartre;119;4;123 +39216;Étival;308;10;318 +39217;L' Étoile;563;14;577 +39218;Étrepigney;430;6;436 +39219;Évans;644;12;656 +39220;Falletans;393;9;402 +39221;La Favière;28;1;29 +39222;Fay-en-Montagne;85;7;92 +39223;La Ferté;198;2;200 +39225;Le Fied;204;7;211 +39227;Foncine-le-Bas;192;7;199 +39228;Foncine-le-Haut;1063;27;1090 +39229;Fontainebrux;202;10;212 +39230;Fontenu;75;2;77 +39232;Fort-du-Plasne;443;10;453 +39233;Foucherans;2193;38;2231 +39234;Foulenay;84;0;84 +39235;Fraisans;1215;14;1229 +39236;Francheville;55;1;56 +39237;Fraroz;49;3;52 +39238;Frasne-les-Meulières;119;8;127 +39239;La Frasnée;39;2;41 +39240;Le Frasnois;160;4;164 +39241;Frébuans;373;8;381 +39244;Frontenay;172;5;177 +39245;Gatey;371;9;380 +39246;Gendrey;428;13;441 +39247;Genod;68;2;70 +39248;Geraise;42;0;42 +39249;Germigney;78;4;82 +39250;Geruge;169;7;176 +39251;Gevingey;451;96;547 +39252;Gevry;692;10;702 +39253;Gigny;281;7;288 +39254;Gillois;136;6;142 +39255;Gizia;236;3;239 +39258;Grande-Rivière Château;628;19;647 +39259;Grange-de-Vaivre;35;1;36 +39261;Graye-et-Charnay;139;2;141 +39262;Gredisans;136;1;137 +39263;Grozon;420;13;433 +39265;Hautecour;191;5;196 +39177;Hauteroche;951;25;976 +39368;Hauts de Bienne;5350;273;5623 +39266;Les Hays;331;2;333 +39267;Ivory;96;1;97 +39268;Ivrey;61;1;62 +39269;Jeurre;270;1;271 +39270;Jouhe;563;64;627 +39271;Lac-des-Rouges-Truites;394;17;411 +39272;Ladoye-sur-Seille;52;3;55 +39274;Lajoux;262;12;274 +39275;Lamoura;642;19;661 +39277;Le Larderet;74;3;77 +39278;Largillay-Marsonnay;153;2;155 +39279;Larnaud;603;13;616 +39280;Larrivoire;103;2;105 +39281;Le Latet;81;4;85 +39282;La Latette;73;2;75 +39283;Lavancia-Epercy;646;18;664 +39284;Lavangeot;138;2;140 +39285;Lavans-lès-Dole;324;8;332 +39286;Lavans-lès-Saint-Claude;2437;107;2544 +39288;Lavigny;378;4;382 +39289;Lect;354;6;360 +39291;Lemuy;238;5;243 +39292;Lent;150;4;154 +39293;Leschères;209;4;213 +39295;Loisia;166;1;167 +39296;Lombard;211;5;216 +39297;Longchaumois;1167;32;1199 +39298;Longcochon;63;1;64 +39299;Longwy-sur-le-Doubs;505;10;515 +39300;Lons-le-Saunier;17291;732;18023 +39301;Loulle;172;4;176 +39302;Louvatange;97;7;104 +39304;Le Louverot;211;12;223 +39305;La Loye;551;9;560 +39306;Macornay;974;35;1009 +39307;Maisod;329;12;341 +39308;Malange;321;6;327 +39310;Mantry;454;12;466 +39312;Marigna-sur-Valouse;116;4;120 +39313;Marigny;207;1;208 +39314;Marnézia;90;3;93 +39315;Marnoz;404;22;426 +39317;La Marre;338;14;352 +39318;Martigna;194;12;206 +39319;Mathenay;143;2;145 +39320;Maynal;338;2;340 +39321;Menétru-le-Vignoble;159;2;161 +39322;Menétrux-en-Joux;56;2;58 +39323;Menotey;306;15;321 +39324;Mérona;8;0;8 +39325;Mesnay;583;15;598 +39326;Mesnois;187;4;191 +39327;Messia-sur-Sorne;842;14;856 +39328;Meussia;420;6;426 +39329;Mièges;166;3;169 +39330;Miéry;152;5;157 +39331;Mignovillard;819;24;843 +39333;Moirans-en-Montagne;2099;107;2206 +39334;Moiron;130;5;135 +39335;Moissey;563;13;576 +39336;Molain;105;3;108 +39337;Molamboz;90;3;93 +39338;Molay;501;5;506 +39342;Monay;124;3;127 +39344;Monnet-la-Ville;343;13;356 +39343;Monnetay;14;1;15 +39345;Monnières;422;17;439 +39365;Mont-sous-Vaudrey;1265;22;1287 +39366;Mont-sur-Monnet;248;6;254 +39346;Montagna-le-Reconduit;119;0;119 +39348;Montaigu;437;52;489 +39349;Montain;509;24;533 +39350;Montbarrey;317;6;323 +39351;Montcusel;156;7;163 +39352;Monteplain;132;2;134 +39353;Montfleur;182;8;190 +39354;Montholier;359;3;362 +39355;Montigny-lès-Arsures;254;8;262 +39356;Montigny-sur-l'Ain;199;8;207 +39273;Montlainsia;246;7;253 +39359;Montmarlon;31;1;32 +39360;Montmirey-la-Ville;176;2;178 +39361;Montmirey-le-Château;197;5;202 +39362;Montmorot;3036;328;3364 +39363;Montrevel;90;1;91 +39364;Montrond;492;15;507 +39367;Morbier;2292;107;2399 +39370;Mouchard;1101;317;1418 +39372;Mournans-Charbonny;89;8;97 +39373;Les Moussières;167;4;171 +39375;Moutonne;132;0;132 +39376;Moutoux;72;2;74 +39377;Mutigney;171;3;174 +39379;Nance;519;11;530 +39130;Nanchez;806;22;828 +39380;Nancuise;46;2;48 +39381;Les Nans;91;3;94 +39385;Neublans-Abergement;545;5;550 +39386;Neuvilley;87;0;87 +39387;Nevy-lès-Dole;281;6;287 +39388;Nevy-sur-Seille;205;10;215 +39389;Ney;574;13;587 +39390;Nogna;295;12;307 +39391;Nozeroy;437;13;450 +39392;Offlanges;198;3;201 +39393;Onglières;65;2;67 +39394;Onoz;72;5;77 +39396;Orchamps;1121;18;1139 +39397;Orgelet;1596;44;1640 +39398;Ougney;375;3;378 +39399;Ounans;369;6;375 +39400;Our;140;2;142 +39401;Oussières;233;5;238 +39402;Pagney;324;7;331 +39403;Pagnoz;230;5;235 +39404;Pannessières;483;12;495 +39405;Parcey;974;20;994 +39406;Le Pasquier;251;8;259 +39407;Passenans;345;6;351 +39408;Patornay;140;6;146 +39409;Peintre;127;3;130 +39411;Perrigny;1523;48;1571 +39412;Peseux;320;2;322 +39413;La Pesse;343;7;350 +39415;Petit-Noir;1093;9;1102 +39418;Picarreau;101;3;104 +39419;Pillemoine;58;2;60 +39420;Pimorin;198;3;201 +39421;Le Pin;241;15;256 +39422;Plainoiseau;528;12;540 +39423;Plaisia;107;9;116 +39424;Les Planches-en-Montagne;164;2;166 +39425;Les Planches-près-Arbois;96;1;97 +39426;Plasne;218;11;229 +39427;Plénise;62;0;62 +39428;Plénisette;25;2;27 +39429;Pleure;429;3;432 +39430;Plumont;103;2;105 +39431;Poids-de-Fiole;333;4;337 +39432;Pointre;126;1;127 +39434;Poligny;4047;407;4454 +39436;Pont-d'Héry;234;8;242 +39435;Pont-de-Poitte;647;20;667 +39437;Pont-du-Navoy;275;5;280 +39439;Port-Lesney;526;13;539 +39441;Prémanon;1188;31;1219 +39443;Présilly;132;0;132 +39444;Pretin;61;1;62 +39445;Publy;285;9;294 +39446;Pupillin;237;8;245 +39447;Quintigny;248;6;254 +39448;Rahon;508;11;519 +39449;Rainans;269;4;273 +39451;Ranchot;495;4;499 +39452;Rans;535;7;542 +39453;Ravilloles;476;13;489 +39454;Recanoz;90;2;92 +39455;Reithouse;59;1;60 +39456;Relans;341;4;345 +39457;Les Repôts;52;0;52 +39458;Revigny;248;15;263 +39461;Rix;78;2;80 +39460;La Rixouse;193;9;202 +39462;Rochefort-sur-Nenon;679;5;684 +39463;Rogna;227;6;233 +39464;Romain;204;8;212 +39465;Romange;199;2;201 +39466;Rosay;125;0;125 +39467;Rotalier;161;6;167 +39468;Rothonay;135;4;139 +39469;Rouffange;104;2;106 +39470;Les Rousses;3630;97;3727 +39471;Ruffey-sur-Seille;734;15;749 +39472;Rye;218;5;223 +39473;Saffloz;102;2;104 +39475;Saint-Amour;2378;107;2485 +39476;Saint-Aubin;1800;43;1843 +39477;Saint-Baraing;261;5;266 +39478;Saint-Claude;9279;298;9577 +39479;Saint-Cyr-Montmalin;242;6;248 +39480;Saint-Didier;269;14;283 +39481;Saint-Germain-en-Montagne;407;10;417 +39137;Saint-Hymetière-sur-Valouse;437;17;454 +39486;Saint-Lamain;115;4;119 +39487;Saint-Laurent-en-Grandvaux;1807;37;1844 +39489;Saint-Lothain;471;9;480 +39490;Saint-Loup;272;7;279 +39492;Saint-Maur;233;3;236 +39493;Saint-Maurice-Crillat;242;2;244 +39494;Saint-Pierre;342;20;362 +39495;Saint-Thiébaud;58;0;58 +39474;Sainte-Agnès;355;10;365 +39497;Saizenay;95;2;97 +39498;Salans;591;12;603 +39499;Saligney;185;5;190 +39500;Salins-les-Bains;2586;150;2736 +39501;Sampans;1165;12;1177 +39502;Santans;297;7;304 +39503;Sapois;374;14;388 +39504;Sarrogna;230;10;240 +39505;Saugeot;66;1;67 +39507;Séligney;77;1;78 +39508;Sellières;744;9;753 +39510;Septmoncel les Molunes;829;24;853 +39511;Sergenaux;65;3;68 +39512;Sergenon;52;1;53 +39513;Sermange;249;2;251 +39514;Serre-les-Moulières;188;11;199 +39517;Sirod;524;20;544 +39518;Songeson;69;1;70 +39519;Soucia;187;5;192 +39520;Souvans;483;5;488 +39522;Supt;102;2;104 +39523;Syam;189;9;198 +39525;Tassenières;394;9;403 +39526;Tavaux;3918;94;4012 +39527;Taxenne;109;1;110 +39528;Thervay;385;10;395 +39529;Thésy;66;0;66 +39530;Thoirette-Coisia;868;25;893 +39531;Thoiria;192;4;196 +39532;Thoissia;36;1;37 +39533;Toulouse-le-Château;221;3;224 +39534;La Tour-du-Meix;231;4;235 +39535;Tourmont;473;19;492 +39537;Trenal;459;11;470 +39378;Les Trois Châteaux;774;19;793 +39538;Uxelles;55;1;56 +39539;Vadans;278;7;285 +39209;Val-d'Épy;343;7;350 +39576;Val-Sonnette;912;29;941 +39485;Val Suran;787;17;804 +39540;Valempoulières;193;11;204 +39290;Valzin en Petite Montagne;497;17;514 +39543;Vannoz;207;7;214 +39545;Le Vaudioux;175;6;181 +39546;Vaudrey;373;14;387 +39547;Vaux-lès-Saint-Claude;693;18;711 +39548;Vaux-sur-Poligny;77;4;81 +39550;Verges;191;5;196 +39551;Véria;117;4;121 +39552;Vernantois;328;11;339 +39553;Le Vernois;308;10;318 +39554;Vers-en-Montagne;234;5;239 +39555;Vers-sous-Sellières;238;2;240 +39556;Vertamboz;94;5;99 +39557;Vescles;193;3;196 +39558;Vevy;274;12;286 +39559;La Vieille-Loye;404;4;408 +39560;Villard-Saint-Sauveur;618;20;638 +39561;Villards-d'Héria;409;6;415 +39565;Villeneuve-d'Aval;87;1;88 +39567;Villeneuve-sous-Pymont;291;9;300 +39569;Villers-Farlay;666;11;677 +39570;Villers-les-Bois;212;1;213 +39571;Villers-Robert;231;2;233 +39568;Villerserine;51;1;52 +39572;Villette-lès-Arbois;386;7;393 +39573;Villette-lès-Dole;771;14;785 +39574;Villevieux;712;20;732 +39575;Le Villey;89;0;89 +39577;Vincent-Froideville;394;3;397 +39579;Viry;927;43;970 +39581;Vitreux;286;4;290 +39582;Voiteur;746;31;777 +39583;Vosbles-Valfin;185;12;197 +39584;Vriange;156;3;159 +39585;Vulvoz;20;0;20 +40001;Aire-sur-l'Adour;6129;552;6681 +40002;Amou;1540;22;1562 +40003;Angoumé;281;7;288 +40004;Angresse;2003;45;2048 +40005;Arboucave;201;4;205 +40006;Arengosse;683;9;692 +40007;Argelos;165;2;167 +40008;Argelouse;93;2;95 +40011;Arsague;340;3;343 +40012;Artassenx;250;1;251 +40013;Arthez-d'Armagnac;110;1;111 +40014;Arue;348;4;352 +40015;Arx;58;1;59 +40016;Aubagnan;250;3;253 +40017;Audignon;395;1;396 +40018;Audon;373;7;380 +40019;Aureilhan;1064;28;1092 +40020;Aurice;609;20;629 +40021;Azur;842;10;852 +40022;Bahus-Soubiran;409;15;424 +40023;Baigts;364;9;373 +40024;Banos;277;4;281 +40026;Bas-Mauco;360;10;370 +40025;Bascons;845;32;877 +40027;Bassercles;155;2;157 +40028;Bastennes;255;9;264 +40029;Bats;304;3;307 +40030;Baudignan;54;0;54 +40031;Bégaar;1167;16;1183 +40032;Belhade;198;6;204 +40033;Bélis;165;5;170 +40034;Bélus;602;10;612 +40035;Bénesse-lès-Dax;529;10;539 +40036;Bénesse-Maremne;3234;64;3298 +40037;Benquet;1732;45;1777 +40038;Bergouey;98;2;100 +40039;Betbezer-d'Armagnac;149;0;149 +40040;Beylongue;365;2;367 +40041;Beyries;128;2;130 +40042;Biarrotte;289;6;295 +40043;Bias;739;13;752 +40044;Biaudos;908;31;939 +40046;Biscarrosse;14182;379;14561 +40047;Bonnegarde;274;5;279 +40049;Bordères-et-Lamensans;369;6;375 +40050;Bostens;201;2;203 +40051;Bougue;774;23;797 +40052;Bourdalat;252;4;256 +40053;Bourriot-Bergonce;310;5;315 +40054;Brassempouy;267;6;273 +40055;Bretagne-de-Marsan;1544;28;1572 +40056;Brocas;789;22;811 +40057;Buanes;259;4;263 +40058;Cachen;226;3;229 +40059;Cagnotte;760;18;778 +40060;Callen;144;4;148 +40061;Campagne;998;28;1026 +40062;Campet-et-Lamolère;441;5;446 +40063;Candresse;807;27;834 +40064;Canenx-et-Réaut;158;3;161 +40065;Capbreton;8769;289;9058 +40066;Carcarès-Sainte-Croix;519;4;523 +40067;Carcen-Ponson;634;5;639 +40068;Cassen;578;16;594 +40069;Castaignos-Souslens;394;4;398 +40070;Castandet;398;17;415 +40074;Castel-Sarrazin;543;20;563 +40071;Castelnau-Chalosse;601;43;644 +40072;Castelnau-Tursan;193;2;195 +40073;Castelner;107;2;109 +40075;Castets;2388;26;2414 +40076;Cauna;444;7;451 +40077;Cauneille;799;14;813 +40078;Caupenne;404;8;412 +40079;Cazalis;134;4;138 +40080;Cazères-sur-l'Adour;1070;31;1101 +40081;Cère;411;6;417 +40082;Classun;271;6;277 +40083;Clèdes;128;7;135 +40084;Clermont;773;33;806 +40085;Commensacq;432;12;444 +40086;Coudures;451;9;460 +40087;Créon-d'Armagnac;362;7;369 +40088;Dax;20681;831;21512 +40089;Doazit;858;26;884 +40090;Donzacq;481;10;491 +40091;Duhort-Bachen;664;19;683 +40092;Dumes;236;6;242 +40093;Escalans;259;3;262 +40094;Escource;721;11;732 +40095;Estibeaux;699;15;714 +40096;Estigarde;121;2;123 +40097;Eugénie-les-Bains;446;10;456 +40098;Eyres-Moncube;365;13;378 +40099;Fargues;330;3;333 +40100;Le Frêche;400;2;402 +40101;Gaas;496;18;514 +40102;Gabarret;1295;246;1541 +40103;Gaillères;613;16;629 +40104;Gamarde-les-Bains;1319;31;1350 +40105;Garein;436;11;447 +40106;Garrey;205;6;211 +40108;Gastes;816;12;828 +40109;Gaujacq;435;10;445 +40110;Geaune;668;14;682 +40111;Geloux;704;16;720 +40112;Gibret;102;1;103 +40113;Goos;519;9;528 +40114;Gourbera;372;6;378 +40115;Gousse;312;11;323 +40116;Gouts;276;4;280 +40117;Grenade-sur-l'Adour;2487;84;2571 +40118;Habas;1503;26;1529 +40119;Hagetmau;4690;139;4829 +40120;Hastingues;579;16;595 +40121;Hauriet;278;5;283 +40122;Haut-Mauco;948;27;975 +40123;Herm;1129;43;1172 +40124;Herré;142;1;143 +40125;Heugas;1343;37;1380 +40126;Hinx;1883;41;1924 +40127;Hontanx;603;5;608 +40128;Horsarrieu;687;19;706 +40129;Josse;850;26;876 +40130;Labastide-Chalosse;150;4;154 +40131;Labastide-d'Armagnac;687;5;692 +40132;Labatut;1427;26;1453 +40133;Labenne;6616;112;6728 +40134;Labouheyre;2731;45;2776 +40135;Labrit;864;10;874 +40136;Lacajunte;153;4;157 +40137;Lacquy;280;5;285 +40138;Lacrabe;267;6;273 +40139;Laglorieuse;550;15;565 +40140;Lagrange;192;3;195 +40141;Lahosse;317;4;321 +40142;Laluque;1019;20;1039 +40143;Lamothe;312;4;316 +40144;Larbey;242;4;246 +40145;Larrivière-Saint-Savin;657;19;676 +40146;Latrille;156;3;159 +40147;Laurède;387;4;391 +40148;Lauret;85;3;88 +40149;Lencouacq;380;5;385 +40150;Léon;1940;51;1991 +40151;Lesgor;439;12;451 +40152;Lesperon;1043;27;1070 +40153;Le Leuy;251;2;253 +40154;Lévignacq;316;5;321 +40155;Linxe;1479;35;1514 +40156;Liposthey;534;5;539 +40157;Lit-et-Mixe;1606;31;1637 +40158;Losse;275;3;278 +40159;Louer;301;7;308 +40160;Lourquen;178;6;184 +40161;Lubbon;104;1;105 +40162;Lucbardez-et-Bargues;573;14;587 +40163;Lüe;562;10;572 +40165;Luglon;399;2;401 +40166;Lussagnet;73;1;74 +40167;Luxey;664;13;677 +40168;Magescq;2175;33;2208 +40169;Maillas;133;3;136 +40170;Maillères;243;4;247 +40171;Mano;125;3;128 +40172;Mant;271;4;275 +40173;Marpaps;139;5;144 +40174;Mauries;90;1;91 +40175;Maurrin;442;6;448 +40176;Mauvezin-d'Armagnac;93;1;94 +40177;Maylis;315;17;332 +40178;Mazerolles;633;27;660 +40179;Mées;1805;46;1851 +40180;Meilhan;1140;30;1170 +40181;Messanges;968;32;1000 +40182;Mézos;824;11;835 +40183;Mimbaste;1000;33;1033 +40184;Mimizan;7018;164;7182 +40185;Miramont-Sensacq;359;8;367 +40186;Misson;781;16;797 +40187;Moliets-et-Maa;1170;16;1186 +40188;Momuy;462;14;476 +40189;Monget;91;3;94 +40190;Monségur;391;11;402 +40192;Mont-de-Marsan;29554;1440;30994 +40191;Montaut;626;13;639 +40193;Montégut;71;2;73 +40194;Montfort-en-Chalosse;1177;28;1205 +40195;Montgaillard;631;13;644 +40196;Montsoué;570;11;581 +40197;Morcenx-la-Nouvelle;5052;178;5230 +40198;Morganx;173;9;182 +40199;Mouscardès;268;3;271 +40200;Moustey;695;10;705 +40201;Mugron;1382;109;1491 +40202;Narrosse;3210;73;3283 +40203;Nassiet;344;14;358 +40204;Nerbis;273;4;277 +40205;Nousse;244;8;252 +40206;Oeyregave;344;14;358 +40207;Oeyreluy;1508;230;1738 +40208;Onard;372;6;378 +40209;Ondres;5358;120;5478 +40210;Onesse-Laharie;1009;19;1028 +40211;Orist;722;18;740 +40212;Orthevielle;936;14;950 +40213;Orx;624;10;634 +40214;Ossages;504;19;523 +40215;Ousse-Suzan;277;8;285 +40216;Ozourt;203;2;205 +40217;Parentis-en-Born;6236;206;6442 +40218;Parleboscq;506;4;510 +40219;Payros-Cazautets;106;3;109 +40220;Pécorade;140;8;148 +40221;Perquie;350;14;364 +40222;Pey;676;22;698 +40223;Peyre;242;8;250 +40224;Peyrehorade;3695;175;3870 +40225;Philondenx;202;6;208 +40226;Pimbo;210;3;213 +40227;Pissos;1441;27;1468 +40228;Pomarez;1550;27;1577 +40229;Pontenx-les-Forges;1596;31;1627 +40230;Pontonx-sur-l'Adour;2810;115;2925 +40231;Port-de-Lanne;1076;21;1097 +40232;Poudenx;225;6;231 +40233;Pouillon;3072;81;3153 +40234;Pouydesseaux;916;27;943 +40235;Poyanne;688;10;698 +40236;Poyartin;833;21;854 +40237;Préchacq-les-Bains;733;6;739 +40238;Pujo-le-Plan;628;19;647 +40239;Puyol-Cazalet;108;3;111 +40240;Renung;537;11;548 +40164;Retjons;350;1;351 +40242;Rimbez-et-Baudiets;105;1;106 +40243;Rion-des-Landes;2986;43;3029 +40244;Rivière-Saas-et-Gourby;1217;28;1245 +40245;Roquefort;1892;49;1941 +40246;Sabres;1174;154;1328 +40247;Saint-Agnet;188;6;194 +40248;Saint-André-de-Seignanx;1766;26;1792 +40249;Saint-Aubin;503;13;516 +40250;Saint-Avit;672;21;693 +40251;Saint-Barthélemy;422;13;435 +40253;Saint-Cricq-Chalosse;641;11;652 +40254;Saint-Cricq-du-Gave;422;7;429 +40255;Saint-Cricq-Villeneuve;482;11;493 +40256;Saint-Étienne-d'Orthe;704;17;721 +40259;Saint-Gein;433;13;446 +40260;Saint-Geours-d'Auribat;413;8;421 +40261;Saint-Geours-de-Maremne;2673;48;2721 +40262;Saint-Gor;302;11;313 +40263;Saint-Jean-de-Lier;414;8;422 +40264;Saint-Jean-de-Marsacq;1614;23;1637 +40265;Saint-Julien-d'Armagnac;108;0;108 +40266;Saint-Julien-en-Born;1643;31;1674 +40267;Saint-Justin;974;13;987 +40268;Saint-Laurent-de-Gosse;657;21;678 +40269;Saint-Lon-les-Mines;1208;37;1245 +40270;Saint-Loubouer;443;8;451 +40274;Saint-Martin-d'Oney;1396;41;1437 +40272;Saint-Martin-de-Hinx;1480;36;1516 +40273;Saint-Martin-de-Seignanx;5488;125;5613 +40275;Saint-Maurice-sur-Adour;584;15;599 +40276;Saint-Michel-Escalus;305;8;313 +40277;Saint-Pandelon;715;53;768 +40278;Saint-Paul-en-Born;956;16;972 +40279;Saint-Paul-lès-Dax;13413;482;13895 +40280;Saint-Perdon;1726;32;1758 +40281;Saint-Pierre-du-Mont;9561;363;9924 +40282;Saint-Sever;4955;98;5053 +40283;Saint-Vincent-de-Paul;3126;221;3347 +40284;Saint-Vincent-de-Tyrosse;7593;233;7826 +40285;Saint-Yaguen;629;15;644 +40252;Sainte-Colombe;666;18;684 +40257;Sainte-Eulalie-en-Born;1265;20;1285 +40258;Sainte-Foy;253;3;256 +40271;Sainte-Marie-de-Gosse;1184;25;1209 +40286;Samadet;1152;22;1174 +40287;Sanguinet;4185;64;4249 +40288;Sarbazan;1176;23;1199 +40289;Sarraziet;240;1;241 +40290;Sarron;110;4;114 +40291;Saubion;1499;26;1525 +40292;Saubrigues;1415;79;1494 +40293;Saubusse;1120;22;1142 +40294;Saugnac-et-Cambran;1542;45;1587 +40295;Saugnacq-et-Muret;1035;18;1053 +40296;Seignosse;3872;96;3968 +40297;Le Sen;227;3;230 +40298;Serres-Gaston;394;12;406 +40299;Serreslous-et-Arribans;194;11;205 +40300;Seyresse;922;36;958 +40301;Siest;138;2;140 +40303;Solférino;324;2;326 +40304;Soorts-Hossegor;3580;90;3670 +40305;Sorbets;197;9;206 +40306;Sorde-l'Abbaye;631;13;644 +40307;Sore;1122;21;1143 +40308;Sort-en-Chalosse;945;31;976 +40309;Souprosse;1122;22;1144 +40310;Soustons;7877;191;8068 +40311;Taller;606;13;619 +40312;Tarnos;12264;316;12580 +40313;Tartas;3260;44;3304 +40314;Tercis-les-Bains;1203;38;1241 +40315;Téthieu;759;12;771 +40316;Tilh;813;19;832 +40317;Tosse;2927;74;3001 +40318;Toulouzette;322;6;328 +40319;Trensacq;245;4;249 +40320;Uchacq-et-Parentis;589;20;609 +40321;Urgons;252;8;260 +40322;Uza;195;1;196 +40323;Vert;270;4;274 +40324;Vicq-d'Auribat;262;10;272 +40326;Vielle-Saint-Girons;1305;31;1336 +40327;Vielle-Soubiran;229;5;234 +40325;Vielle-Tursan;257;8;265 +40328;Vieux-Boucau-les-Bains;1618;22;1640 +40329;Le Vignau;490;6;496 +40330;Villenave;326;4;330 +40331;Villeneuve-de-Marsan;2413;47;2460 +40332;Ychoux;2281;41;2322 +40333;Ygos-Saint-Saturnin;1322;14;1336 +40334;Yzosse;367;13;380 +41001;Ambloy;185;5;190 +41002;Angé;882;22;904 +41003;Areines;616;232;848 +41004;Artins;264;5;269 +41006;Autainville;444;8;452 +41007;Authon;721;13;734 +41008;Avaray;737;16;753 +41009;Averdon;697;14;711 +41010;Azé;1033;30;1063 +41012;Baillou;226;13;239 +41013;Bauzy;278;4;282 +41173;Beauce la Romaine;3484;67;3551 +41014;Beauchêne;173;2;175 +41016;Billy;1020;9;1029 +41017;Binas;686;17;703 +41018;Blois;46086;1629;47715 +41019;Boisseau;99;2;101 +41020;Bonneveau;467;7;474 +41022;Bouffry;134;1;135 +41024;Boursay;166;6;172 +41025;Bracieux;1305;19;1324 +41026;Brévainville;170;4;174 +41027;Briou;147;2;149 +41028;Busloup;439;6;445 +41029;Candé-sur-Beuvron;1497;27;1524 +41030;Cellé;225;3;228 +41031;Cellettes;2633;65;2698 +41032;Chailles;2680;81;2761 +41034;Chambord;93;0;93 +41035;Champigny-en-Beauce;604;17;621 +41036;Chaon;459;7;466 +41037;La Chapelle-Enchérie;211;4;215 +41038;La Chapelle-Montmartin;435;8;443 +41039;La Chapelle-Saint-Martin-en-Plaine;730;15;745 +41040;La Chapelle-Vendômoise;783;25;808 +41041;La Chapelle-Vicomtesse;169;3;172 +41042;Châteauvieux;538;4;542 +41043;Châtillon-sur-Cher;1722;32;1754 +41044;Châtres-sur-Cher;1097;10;1107 +41045;Chaumont-sur-Loire;1086;9;1095 +41046;Chaumont-sur-Tharonne;1074;14;1088 +41047;La Chaussée-Saint-Victor;4503;131;4634 +41048;Chauvigny-du-Perche;220;1;221 +41049;Chémery;971;12;983 +41050;Cheverny;956;40;996 +41051;Chissay-en-Touraine;1127;26;1153 +41052;Chitenay;1068;35;1103 +41053;Choue;529;5;534 +41054;Choussy;338;5;343 +41057;Conan;175;0;175 +41058;Concriers;176;5;181 +41059;Le Controis-en-Sologne;6866;148;7014 +41060;Cormenon;690;12;702 +41061;Cormeray;1560;26;1586 +41062;Couddes;546;7;553 +41248;Couëtron-au-Perche;1065;15;1080 +41063;Couffy;497;9;506 +41065;Coulommiers-la-Tour;557;16;573 +41067;Cour-Cheverny;2845;62;2907 +41069;Cour-sur-Loire;266;6;272 +41066;Courbouzon;435;10;445 +41068;Courmemin;509;8;517 +41071;Crouy-sur-Cosson;537;11;548 +41072;Crucheray;381;14;395 +41073;Danzé;694;17;711 +41074;Dhuizon;1233;16;1249 +41075;Droué;992;8;1000 +41077;Épiais;136;4;140 +41078;Épuisay;831;17;848 +41079;Les Essarts;108;0;108 +41080;Faverolles-sur-Cher;1386;29;1415 +41081;Faye;243;5;248 +41083;La Ferté-Beauharnais;525;4;529 +41084;La Ferté-Imbault;975;27;1002 +41085;La Ferté-Saint-Cyr;1056;12;1068 +41087;Fontaine-les-Coteaux;337;5;342 +41088;Fontaine-Raoul;225;6;231 +41086;Fontaines-en-Sologne;633;10;643 +41089;La Fontenelle;195;4;199 +41090;Fortan;269;7;276 +41091;Fossé;1308;18;1326 +41093;Françay;273;9;282 +41094;Fresnes;1145;37;1182 +41095;Fréteval;1083;22;1105 +41096;Le Gault-du-Perche;341;3;344 +41097;Gièvres;2396;31;2427 +41098;Gombergean;188;4;192 +41099;Gy-en-Sologne;499;13;512 +41100;Les Hayes;176;8;184 +41101;Herbault;1249;32;1281 +41102;Houssay;387;3;390 +41103;Huisseau-en-Beauce;423;8;431 +41104;Huisseau-sur-Cosson;2281;57;2338 +41105;Josnes;887;18;905 +41106;Lamotte-Beuvron;4724;64;4788 +41107;Lancé;473;7;480 +41108;Lancôme;122;3;125 +41109;Landes-le-Gaulois;750;21;771 +41110;Langon-sur-Cher;812;12;824 +41112;Lassay-sur-Croisne;249;9;258 +41113;Lavardin;183;7;190 +41114;Lestiou;290;7;297 +41115;Lignières;380;5;385 +41116;Lisle;195;3;198 +41118;Loreux;209;4;213 +41119;Lorges;352;6;358 +41120;Lunay;1267;33;1300 +41121;La Madeleine-Villefrouin;30;0;30 +41122;Maray;233;2;235 +41123;Marchenoir;659;10;669 +41124;Marcilly-en-Beauce;348;8;356 +41125;Marcilly-en-Gault;735;16;751 +41126;Mareuil-sur-Cher;1142;23;1165 +41127;La Marolle-en-Sologne;344;6;350 +41128;Marolles;725;18;743 +41129;Maslives;702;13;715 +41130;Maves;661;16;677 +41131;Mazangé;855;29;884 +41132;Méhers;338;7;345 +41134;Menars;626;22;648 +41135;Mennetou-sur-Cher;885;10;895 +41136;Mer;6238;108;6346 +41137;Mesland;565;23;588 +41138;Meslay;312;9;321 +41139;Meusnes;1097;13;1110 +41140;Millançay;780;20;800 +41141;Moisy;365;2;367 +41143;Mondoubleau;1335;54;1389 +41150;Mont-près-Chambord;3297;95;3392 +41144;Monteaux;768;24;792 +41145;Monthou-sur-Bièvre;811;21;832 +41146;Monthou-sur-Cher;964;14;978 +41147;Les Montils;1943;46;1989 +41148;Montlivault;1377;18;1395 +41149;Montoire-sur-le-Loir;3782;196;3978 +41151;Montrichard Val de Cher;3810;51;3861 +41152;Montrieux-en-Sologne;651;14;665 +41153;Montrouveau;154;3;157 +41154;Morée;1071;20;1091 +41155;Muides-sur-Loire;1259;36;1295 +41156;Mulsans;502;13;515 +41157;Mur-de-Sologne;1519;17;1536 +41158;Naveil;2361;68;2429 +41159;Neung-sur-Beuvron;1226;18;1244 +41160;Neuvy;319;4;323 +41161;Nouan-le-Fuzelier;2326;41;2367 +41163;Nourray;109;0;109 +41164;Noyers-sur-Cher;2728;37;2765 +41166;Oisly;377;5;382 +41168;Orçay;235;3;238 +41171;Oucques La Nouvelle;1724;27;1751 +41172;Ouzouer-le-Doyen;243;1;244 +41174;Périgny;177;7;184 +41175;Pezou;1119;19;1138 +41176;Pierrefitte-sur-Sauldre;789;14;803 +41177;Le Plessis-Dorin;167;0;167 +41178;Le Plessis-l'Échelle;70;2;72 +41179;Le Poislay;181;4;185 +41180;Pontlevoy;1524;167;1691 +41181;Pouillé;796;20;816 +41182;Pray;292;9;301 +41184;Prunay-Cassereau;612;7;619 +41185;Pruniers-en-Sologne;2388;59;2447 +41186;Rahart;325;6;331 +41187;Renay;171;4;175 +41188;Rhodon;123;3;126 +41189;Rilly-sur-Loire;474;6;480 +41190;Rocé;218;7;225 +41191;Roches;69;3;72 +41192;Les Roches-l'Évêque;279;3;282 +41193;Romilly;140;3;143 +41194;Romorantin-Lanthenay;17754;492;18246 +41195;Rougeou;159;0;159 +41196;Ruan-sur-Egvonne;94;0;94 +41198;Saint-Aignan;2849;75;2924 +41199;Saint-Amand-Longpré;1224;27;1251 +41201;Saint-Arnoult;321;3;324 +41203;Saint-Bohaire;497;21;518 +41204;Saint-Claude-de-Diray;1783;40;1823 +41205;Saint-Cyr-du-Gault;174;2;176 +41206;Saint-Denis-sur-Loire;837;28;865 +41207;Saint-Dyé-sur-Loire;1140;19;1159 +41208;Saint-Étienne-des-Guérets;111;3;114 +41209;Saint-Firmin-des-Prés;824;41;865 +41211;Saint-Georges-sur-Cher;2691;39;2730 +41212;Saint-Gervais-la-Forêt;3201;99;3300 +41213;Saint-Gourgon;113;4;117 +41214;Saint-Hilaire-la-Gravelle;717;4;721 +41215;Saint-Jacques-des-Guérets;91;2;93 +41216;Saint-Jean-Froidmentel;548;8;556 +41217;Saint-Julien-de-Chédon;756;17;773 +41218;Saint-Julien-sur-Cher;768;11;779 +41219;Saint-Laurent-des-Bois;287;12;299 +41220;Saint-Laurent-Nouan;4357;86;4443 +41221;Saint-Léonard-en-Beauce;644;17;661 +41222;Saint-Loup;375;9;384 +41223;Saint-Lubin-en-Vergonnois;718;10;728 +41224;Saint-Marc-du-Cor;183;4;187 +41225;Saint-Martin-des-Bois;579;11;590 +41226;Saint-Ouen;3189;94;3283 +41228;Saint-Rimay;291;3;294 +41229;Saint-Romain-sur-Cher;1478;34;1512 +41230;Saint-Sulpice-de-Pommeray;1855;56;1911 +41231;Saint-Viâtre;1196;29;1225 +41200;Sainte-Anne;459;14;473 +41232;Salbris;5166;102;5268 +41233;Sambin;940;14;954 +41234;Santenay;290;8;298 +41235;Sargé-sur-Braye;1041;22;1063 +41236;Sasnières;112;0;112 +41237;Sassay;1023;20;1043 +41238;Savigny-sur-Braye;2017;28;2045 +41239;Seigy;1055;24;1079 +41241;Selles-Saint-Denis;1337;29;1366 +41242;Selles-sur-Cher;4567;64;4631 +41243;Selommes;813;13;826 +41245;Séris;376;4;380 +41246;Seur;477;19;496 +41247;Soings-en-Sologne;1614;19;1633 +41249;Souesmes;1059;12;1071 +41250;Sougé;479;7;486 +41251;Souvigny-en-Sologne;524;9;533 +41252;Suèvres;1693;29;1722 +41253;Talcy;243;11;254 +41254;Le Temple;187;7;194 +41255;Ternay;336;7;343 +41256;Theillay;1260;19;1279 +41258;Thésée;1132;22;1154 +41259;Thoré-la-Rochette;885;17;902 +41260;Thoury;420;7;427 +41262;Tour-en-Sologne;1117;16;1133 +41261;Tourailles;134;3;137 +41265;Troo;297;9;306 +41266;Valaire;86;2;88 +41142;Valencisse;2398;93;2491 +41070;Vallée-de-Ronsard;523;8;531 +41267;Vallières-les-Grandes;937;19;956 +41055;Valloire-sur-Cisse;2438;58;2496 +41268;Veilleins;161;4;165 +41269;Vendôme;16569;643;17212 +41271;Vernou-en-Sologne;624;6;630 +41167;Veuzain-sur-Loire;3503;108;3611 +41273;Vievy-le-Rayé;453;7;460 +41274;Villavard;128;0;128 +41275;La Ville-aux-Clercs;1273;23;1296 +41276;Villebarou;2460;81;2541 +41277;Villebout;140;8;148 +41278;Villechauve;276;8;284 +41279;Villedieu-le-Château;414;4;418 +41280;Villefranche-sur-Cher;2667;68;2735 +41281;Villefrancœur;424;8;432 +41282;Villeherviers;471;7;478 +41283;Villemardy;277;4;281 +41284;Villeneuve-Frouville;61;2;63 +41285;Villeny;493;4;497 +41286;Villeporcher;153;5;158 +41287;Villerable;520;13;533 +41288;Villerbon;799;16;815 +41289;Villermain;398;12;410 +41290;Villeromain;240;0;240 +41291;Villetrun;322;4;326 +41292;Villexanton;201;1;202 +41294;Villiers-sur-Loir;1131;59;1190 +41293;Villiersfaux;255;5;260 +41295;Vineuil;7815;206;8021 +41296;Vouzon;1483;35;1518 +41297;Yvoy-le-Marron;728;8;736 +42001;Aboën;439;7;446 +42002;Ailleux;164;2;166 +42003;Ambierle;1915;56;1971 +42005;Andrézieux-Bouthéon;9790;163;9953 +42006;Apinac;416;8;424 +42007;Arcinges;212;12;224 +42008;Arcon;108;1;109 +42009;Arthun;542;5;547 +42010;Aveizieux;1647;21;1668 +42011;Balbigny;2965;57;3022 +42012;Bard;664;23;687 +42013;Bellegarde-en-Forez;2004;36;2040 +42014;Belleroche;312;9;321 +42015;Belmont-de-la-Loire;1491;27;1518 +42016;La Bénisson-Dieu;418;10;428 +42017;Le Bessat;446;8;454 +42018;Bessey;457;10;467 +42019;Boën-sur-Lignon;3309;43;3352 +42020;Boisset-lès-Montrond;1167;20;1187 +42021;Boisset-Saint-Priest;1223;10;1233 +42022;Bonson;3889;52;3941 +42023;Bourg-Argental;2922;57;2979 +42025;Boyer;199;7;206 +42026;Briennon;1692;38;1730 +42027;Bully;408;7;415 +42028;Burdignes;368;9;377 +42029;Bussières;1545;45;1590 +42030;Bussy-Albieux;537;16;553 +42031;Caloire;316;7;323 +42032;Cellieu;1697;23;1720 +42033;Le Cergne;642;25;667 +42034;Cervières;120;8;128 +42035;Cezay;219;7;226 +42036;Chagnon;490;16;506 +42037;Chalain-d'Uzore;557;21;578 +42038;Chalain-le-Comtal;705;14;719 +42039;Chalmazel-Jeansagnière;451;4;455 +42040;La Chamba;50;2;52 +42041;Chambéon;562;5;567 +42042;Chambles;1000;31;1031 +42044;Le Chambon-Feugerolles;12317;91;12408 +42045;La Chambonie;42;2;44 +42043;Chambœuf;1711;35;1746 +42046;Champdieu;1919;44;1963 +42047;Champoly;329;2;331 +42048;Chandon;1484;30;1514 +42049;Changy;637;10;647 +42050;La Chapelle-en-Lafaye;113;1;114 +42051;La Chapelle-Villars;530;14;544 +42052;Charlieu;3667;105;3772 +42053;Châteauneuf;1599;21;1620 +42054;Châtelneuf;335;8;343 +42055;Châtelus;137;8;145 +42339;Chausseterre;224;5;229 +42056;Chavanay;2885;50;2935 +42058;Chazelles-sur-Lavieu;272;6;278 +42059;Chazelles-sur-Lyon;5357;97;5454 +42060;Chenereilles;523;6;529 +42061;Cherier;559;16;575 +42062;Chevrières;1128;25;1153 +42063;Chirassimont;400;5;405 +42064;Chuyer;775;10;785 +42065;Civens;1359;51;1410 +42066;Cleppé;529;13;542 +42067;Colombier;305;2;307 +42068;Combre;439;5;444 +42069;Commelle-Vernay;2955;91;3046 +42070;Cordelle;916;21;937 +42072;La Côte-en-Couzan;68;0;68 +42071;Le Coteau;6872;181;7053 +42073;Cottance;719;9;728 +42074;Coutouvre;1101;27;1128 +42075;Craintilleux;1328;14;1342 +42076;Cremeaux;904;22;926 +42077;Croizet-sur-Gand;314;6;320 +42078;Le Crozet;272;12;284 +42079;Cuinzier;728;13;741 +42081;Cuzieu;1525;20;1545 +42083;Dargoire;521;4;525 +42084;Débats-Rivière-d'Orpra;156;2;158 +42085;Doizieux;831;16;847 +42086;Écoche;537;13;550 +42087;Écotay-l'Olme;1212;50;1262 +42088;Épercieux-Saint-Paul;738;18;756 +42089;Essertines-en-Châtelneuf;696;17;713 +42090;Essertines-en-Donzy;490;12;502 +42091;Estivareilles;686;12;698 +42092;L' Étrat;2531;84;2615 +42093;Farnay;1408;29;1437 +42094;Feurs;8173;191;8364 +42095;Firminy;17135;254;17389 +42096;Fontanès;678;13;691 +42097;La Fouillouse;4501;63;4564 +42098;Fourneaux;588;17;605 +42099;Fraisses;3723;52;3775 +42225;Genilac;3896;75;3971 +42100;La Gimond;277;6;283 +42101;Graix;146;1;147 +42102;Grammond;906;21;927 +42103;La Grand-Croix;5136;40;5176 +42104;La Gresle;842;20;862 +42105;Grézieux-le-Fromental;233;2;235 +42106;Grézolles;267;8;275 +42107;Gumières;322;10;332 +42108;L' Hôpital-le-Grand;1054;24;1078 +42109;L' Hôpital-sous-Rochefort;110;1;111 +42110;L' Horme;4790;42;4832 +42112;Jarnosse;435;8;443 +42113;Jas;222;13;235 +42115;Jonzieux;1170;15;1185 +42116;Juré;242;7;249 +42117;Lavieu;116;8;124 +42118;Lay;745;20;765 +42119;Leigneux;377;8;385 +42120;Lentigny;1736;51;1787 +42121;Lérigneux;143;2;145 +42122;Lézigneux;1695;61;1756 +42123;Lorette;4700;32;4732 +42124;Lupé;307;7;314 +42125;Luré;142;2;144 +42126;Luriecq;1311;17;1328 +42127;Mably;7605;119;7724 +42128;Machézal;382;5;387 +42129;Maclas;1804;52;1856 +42130;Magneux-Haute-Rive;578;8;586 +42131;Maizilly;337;3;340 +42132;Malleval;578;16;594 +42133;Marcenod;710;19;729 +42134;Marcilly-le-Châtel;1390;45;1435 +42135;Marclopt;503;17;520 +42136;Marcoux;735;23;758 +42137;Margerie-Chantagret;805;15;820 +42138;Maringes;666;12;678 +42139;Marlhes;1292;76;1368 +42140;Marols;416;4;420 +42141;Mars;560;12;572 +42142;Merle-Leignec;320;4;324 +42143;Mizérieux;453;4;457 +42145;Montagny;1049;22;1071 +42146;Montarcher;67;3;70 +42147;Montbrison;15641;602;16243 +42148;Montchal;492;10;502 +42149;Montrond-les-Bains;5302;80;5382 +42150;Montverdun;1381;28;1409 +42151;Mornand-en-Forez;407;79;486 +42152;Nandax;521;297;818 +42153;Neaux;480;12;492 +42154;Néronde;457;51;508 +42155;Nervieux;993;15;1008 +42156;Neulise;1366;17;1383 +42157;Noailly;802;14;816 +42158;Les Noës;208;4;212 +42159;Noirétable;1588;105;1693 +42160;Nollieux;197;6;203 +42161;Notre-Dame-de-Boisset;566;15;581 +42162;Ouches;1158;20;1178 +42163;La Pacaudière;1057;20;1077 +42164;Palogneux;78;1;79 +42165;Panissières;2929;87;3016 +42166;Parigny;609;16;625 +42167;Pavezin;354;3;357 +42168;Pélussin;3765;103;3868 +42169;Périgneux;1512;26;1538 +42170;Perreux;2114;179;2293 +42171;Pinay;284;7;291 +42172;Planfoy;1039;24;1063 +42173;Pommiers;359;11;370 +42174;Poncins;1097;25;1122 +42175;Pouilly-lès-Feurs;1239;35;1274 +42176;Pouilly-les-Nonains;2123;45;2168 +42177;Pouilly-sous-Charlieu;2471;45;2516 +42178;Pradines;803;10;813 +42179;Pralong;847;21;868 +42180;Précieux;1031;105;1136 +42181;Régny;1525;30;1555 +42182;Renaison;3143;106;3249 +42183;La Ricamarie;7906;49;7955 +42184;Riorges;10774;296;11070 +42185;Rivas;663;6;669 +42186;Rive-de-Gier;15184;115;15299 +42187;Roanne;34366;693;35059 +42188;Roche;254;4;258 +42189;Roche-la-Molière;9697;98;9795 +42191;Roisey;936;31;967 +42192;Rozier-Côtes-d'Aurec;447;7;454 +42193;Rozier-en-Donzy;1444;38;1482 +42194;Sail-les-Bains;200;6;206 +42195;Sail-sous-Couzan;941;7;948 +42198;Saint-Alban-les-Eaux;969;29;998 +42199;Saint-André-d'Apchon;1946;66;2012 +42200;Saint-André-le-Puy;1539;25;1564 +42201;Saint-Appolinard;678;9;687 +42202;Saint-Barthélemy-Lestra;684;15;699 +42203;Saint-Bonnet-des-Quarts;318;12;330 +42204;Saint-Bonnet-le-Château;1527;48;1575 +42205;Saint-Bonnet-le-Courreau;687;14;701 +42206;Saint-Bonnet-les-Oules;1638;40;1678 +42207;Saint-Chamond;34967;557;35524 +42208;Saint-Christo-en-Jarez;1891;28;1919 +42211;Saint-Cyprien;2485;30;2515 +42212;Saint-Cyr-de-Favières;917;27;944 +42213;Saint-Cyr-de-Valorges;304;12;316 +42214;Saint-Cyr-les-Vignes;1042;29;1071 +42215;Saint-Denis-de-Cabanne;1251;27;1278 +42216;Saint-Denis-sur-Coise;657;18;675 +42217;Saint-Didier-sur-Rochefort;417;7;424 +42218;Saint-Étienne;172565;1955;174520 +42219;Saint-Étienne-le-Molard;1019;23;1042 +42220;Saint-Forgeux-Lespinasse;646;13;659 +42222;Saint-Galmier;5722;142;5864 +42223;Saint-Genest-Lerpt;6131;70;6201 +42224;Saint-Genest-Malifaux;2861;143;3004 +42226;Saint-Georges-de-Baroille;419;3;422 +42227;Saint-Georges-en-Couzan;420;10;430 +42228;Saint-Georges-Haute-Ville;1440;25;1465 +42229;Saint-Germain-la-Montagne;240;7;247 +42230;Saint-Germain-Laval;1635;30;1665 +42231;Saint-Germain-Lespinasse;1251;85;1336 +42232;Saint-Haon-le-Châtel;638;12;650 +42233;Saint-Haon-le-Vieux;958;26;984 +42234;Saint-Héand;3592;70;3662 +42235;Saint-Hilaire-Cusson-la-Valmitte;335;5;340 +42236;Saint-Hilaire-sous-Charlieu;535;10;545 +42237;Saint-Jean-Bonnefonds;6638;69;6707 +42238;Saint-Jean-la-Vêtre;316;11;327 +42239;Saint-Jean-Saint-Maurice-sur-Loire;1148;28;1176 +42240;Saint-Jean-Soleymieux;860;12;872 +42241;Saint-Jodard;414;5;419 +42242;Saint-Joseph;1901;30;1931 +42243;Saint-Julien-d'Oddes;272;13;285 +42246;Saint-Julien-Molin-Molette;1147;27;1174 +42247;Saint-Just-en-Bas;289;8;297 +42248;Saint-Just-en-Chevalet;1141;42;1183 +42249;Saint-Just-la-Pendue;1642;35;1677 +42279;Saint-Just-Saint-Rambert;15083;270;15353 +42251;Saint-Laurent-la-Conche;608;13;621 +42252;Saint-Laurent-Rochefort;246;3;249 +42253;Saint-Léger-sur-Roanne;1145;42;1187 +42255;Saint-Marcel-d'Urfé;290;7;297 +42254;Saint-Marcel-de-Félines;809;17;826 +42256;Saint-Marcellin-en-Forez;4848;50;4898 +42257;Saint-Martin-d'Estréaux;839;16;855 +42259;Saint-Martin-la-Plaine;3755;74;3829 +42260;Saint-Martin-la-Sauveté;955;62;1017 +42261;Saint-Martin-Lestra;895;20;915 +42262;Saint-Maurice-en-Gourgois;1813;21;1834 +42264;Saint-Médard-en-Forez;1040;25;1065 +42265;Saint-Michel-sur-Rhône;826;25;851 +42266;Saint-Nizier-de-Fornas;666;12;678 +42267;Saint-Nizier-sous-Charlieu;1702;45;1747 +42269;Saint-Paul-d'Uzore;170;11;181 +42270;Saint-Paul-en-Cornillon;1364;27;1391 +42271;Saint-Paul-en-Jarez;4844;60;4904 +42272;Saint-Pierre-de-Bœuf;1726;39;1765 +42273;Saint-Pierre-la-Noaille;383;8;391 +42274;Saint-Polgues;259;8;267 +42275;Saint-Priest-en-Jarez;6120;93;6213 +42276;Saint-Priest-la-Prugne;433;5;438 +42277;Saint-Priest-la-Roche;350;1;351 +42278;Saint-Priest-la-Vêtre;148;1;149 +42280;Saint-Régis-du-Coin;387;8;395 +42281;Saint-Rirand;140;2;142 +42282;Saint-Romain-d'Urfé;260;5;265 +42283;Saint-Romain-en-Jarez;1226;13;1239 +42284;Saint-Romain-la-Motte;1434;62;1496 +42285;Saint-Romain-le-Puy;3998;60;4058 +42286;Saint-Romain-les-Atheux;960;15;975 +42287;Saint-Sauveur-en-Rue;1095;22;1117 +42288;Saint-Sixte;710;12;722 +42289;Saint-Symphorien-de-Lay;1887;36;1923 +42290;Saint-Thomas-la-Garde;595;22;617 +42293;Saint-Victor-sur-Rhins;1181;20;1201 +42294;Saint-Vincent-de-Boisset;966;28;994 +42196;Sainte-Agathe-en-Donzy;129;1;130 +42197;Sainte-Agathe-la-Bouteresse;1023;31;1054 +42209;Sainte-Colombe-sur-Gand;408;11;419 +42210;Sainte-Croix-en-Jarez;478;7;485 +42221;Sainte-Foy-Saint-Sulpice;512;13;525 +42295;Les Salles;541;7;548 +42296;Salt-en-Donzy;544;17;561 +42297;Salvizinet;589;19;608 +42298;Sauvain;380;5;385 +42299;Savigneux;3432;75;3507 +42300;Sevelinges;647;12;659 +42301;Soleymieux;654;15;669 +42302;Sorbiers;7933;170;8103 +42303;Souternon;288;7;295 +42304;Sury-le-Comtal;6552;270;6822 +42305;La Talaudière;6860;96;6956 +42306;Tarentaise;475;6;481 +42307;Tartaras;854;54;908 +42308;La Terrasse-sur-Dorlay;785;11;796 +42310;Thélis-la-Combe;158;5;163 +42311;La Tour-en-Jarez;1479;37;1516 +42312;La Tourette;584;16;600 +42313;Trelins;654;7;661 +42314;La Tuilière;289;8;297 +42315;Unias;433;15;448 +42316;Unieux;8597;86;8683 +42317;Urbise;130;6;136 +42318;Usson-en-Forez;1482;25;1507 +42319;Valeille;737;8;745 +42320;Valfleury;708;17;725 +42322;La Valla-en-Gier;1042;30;1072 +42321;La Valla-sur-Rochefort;104;1;105 +42323;Veauche;8984;104;9088 +42324;Veauchette;1180;17;1197 +42325;Vendranges;371;5;376 +42326;Véranne;835;27;862 +42327;Vérin;669;14;683 +42328;Verrières-en-Forez;705;73;778 +42329;La Versanne;373;5;378 +42245;Vêtre-sur-Anzon;550;5;555 +42268;Vézelin-sur-Loire;789;9;798 +42330;Villars;7970;158;8128 +42331;Villemontais;1017;33;1050 +42332;Villerest;4902;139;5041 +42333;Villers;585;11;596 +42334;Violay;1239;17;1256 +42335;Viricelles;457;21;478 +42336;Virigneux;631;19;650 +42337;Vivans;230;5;235 +42338;Vougy;1466;64;1530 +43001;Agnat;187;4;191 +43002;Aiguilhe;1511;64;1575 +43003;Allègre;907;18;925 +43004;Alleyrac;117;7;124 +43005;Alleyras;161;4;165 +43006;Ally;139;1;140 +43007;Araules;597;17;614 +43008;Arlempdes;138;6;144 +43009;Arlet;24;0;24 +43010;Arsac-en-Velay;1208;29;1237 +43011;Aubazat;178;5;183 +43012;Aurec-sur-Loire;6111;83;6194 +43014;Autrac;63;2;65 +43015;Auvers;54;0;54 +43016;Auzon;896;19;915 +43017;Azérat;273;6;279 +43018;Bains;1353;40;1393 +43019;Barges;96;2;98 +43020;Bas-en-Basset;4348;84;4432 +43021;Beaulieu;1029;20;1049 +43022;Beaumont;286;12;298 +43023;Beaune-sur-Arzon;221;3;224 +43024;Beaux;845;13;858 +43025;Beauzac;2936;65;3001 +43026;Bellevue-la-Montagne;419;14;433 +43027;Berbezit;47;0;47 +43028;Bessamorel;458;15;473 +43029;La Besseyre-Saint-Mary;100;0;100 +43030;Blanzac;402;10;412 +43031;Blassac;136;5;141 +43032;Blavozy;1656;31;1687 +43033;Blesle;637;8;645 +43034;Boisset;345;1;346 +43035;Bonneval;70;3;73 +43036;Borne;413;6;419 +43037;Le Bouchet-Saint-Nicolas;280;6;286 +43038;Bournoncle-Saint-Pierre;991;22;1013 +43039;Le Brignon;601;14;615 +43040;Brioude;6721;360;7081 +43041;Brives-Charensac;4085;235;4320 +43042;Cayres;729;8;737 +43043;Céaux-d'Allègre;474;8;482 +43044;Cerzat;209;4;213 +43045;Ceyssac;416;19;435 +43046;Chadrac;2516;70;2586 +43047;Chadron;292;8;300 +43048;La Chaise-Dieu;620;36;656 +43049;Chamalières-sur-Loire;491;9;500 +43050;Chambezon;116;0;116 +43051;Le Chambon-sur-Lignon;2470;57;2527 +43052;Champagnac-le-Vieux;206;8;214 +43053;Champclause;201;5;206 +43054;Chanaleilles;181;9;190 +43055;Chaniat;172;6;178 +43056;Chanteuges;441;13;454 +43057;La Chapelle-Bertin;48;3;51 +43058;La Chapelle-d'Aurec;1019;14;1033 +43059;La Chapelle-Geneste;110;1;111 +43060;Charraix;71;4;75 +43061;Chaspinhac;845;23;868 +43062;Chaspuzac;778;15;793 +43063;Chassagnes;157;2;159 +43064;Chassignolles;62;1;63 +43065;Chastel;129;4;133 +43066;Chaudeyrolles;107;4;111 +43067;Chavaniac-Lafayette;275;9;284 +43068;Chazelles;35;2;37 +43069;Chenereilles;325;7;332 +43070;Chilhac;181;2;183 +43071;Chomelix;475;7;482 +43072;La Chomette;154;6;160 +43073;Cistrières;140;2;142 +43074;Cohade;863;25;888 +43075;Collat;78;3;81 +43076;Connangles;146;1;147 +43077;Costaros;544;16;560 +43078;Coubon;3243;88;3331 +43079;Couteuges;301;11;312 +43080;Craponne-sur-Arzon;1982;41;2023 +43082;Cronce;75;1;76 +43083;Cubelles;152;2;154 +43084;Cussac-sur-Loire;1710;34;1744 +43085;Desges;59;1;60 +43086;Domeyrat;194;4;198 +43087;Dunières;2787;68;2855 +43088;Espalem;304;7;311 +43089;Espaly-Saint-Marcel;3513;175;3688 +43090;Esplantas-Vazeilles;126;4;130 +43091;Les Estables;333;11;344 +43092;Fay-sur-Lignon;363;8;371 +43093;Félines;318;7;325 +43094;Ferrussac;81;2;83 +43095;Fix-Saint-Geneys;123;6;129 +43096;Fontannes;952;228;1180 +43097;Freycenet-la-Cuche;106;1;107 +43098;Freycenet-la-Tour;104;5;109 +43099;Frugerès-les-Mines;557;6;563 +43100;Frugières-le-Pin;159;5;164 +43101;Goudet;60;6;66 +43102;Grazac;1063;22;1085 +43103;Grenier-Montgon;115;2;117 +43104;Grèzes;198;6;204 +43105;Javaugues;189;9;198 +43106;Jax;147;4;151 +43107;Josat;84;1;85 +43108;Jullianges;442;8;450 +43109;Lafarre;72;3;75 +43110;Lamothe;859;15;874 +43111;Landos;891;27;918 +43112;Langeac;3662;80;3742 +43113;Lantriac;1928;54;1982 +43114;Lapte;1715;38;1753 +43115;Laussonne;1010;19;1029 +43116;Laval-sur-Doulon;63;2;65 +43117;Lavaudieu;243;7;250 +43118;Lavoûte-Chilhac;281;4;285 +43119;Lavoûte-sur-Loire;840;18;858 +43120;Lempdes-sur-Allagnon;1342;25;1367 +43121;Léotoing;234;5;239 +43122;Lissac;275;5;280 +43123;Lorlanges;374;13;387 +43124;Loudes;918;24;942 +43125;Lubilhac;85;1;86 +43126;Malrevers;754;15;769 +43127;Malvalette;835;15;850 +43128;Malvières;135;2;137 +43129;Le Mas-de-Tence;168;7;175 +43131;Mazerat-Aurouze;200;2;202 +43130;Mazet-Saint-Voy;1109;28;1137 +43132;Mazeyrat-d'Allier;1480;45;1525 +43133;Mercœur;139;0;139 +43134;Mézères;158;4;162 +43135;Le Monastier-sur-Gazeille;1789;32;1821 +43136;Monistrol-d'Allier;202;2;204 +43137;Monistrol-sur-Loire;8718;420;9138 +43138;Monlet;420;12;432 +43139;Montclard;55;0;55 +43140;Le Monteil;670;23;693 +43141;Montfaucon-en-Velay;1202;26;1228 +43142;Montregard;596;10;606 +43143;Montusclat;138;0;138 +43144;Moudeyres;100;3;103 +43145;Ouides;57;0;57 +43147;Paulhac;636;22;658 +43148;Paulhaguet;876;18;894 +43149;Pébrac;114;2;116 +43150;Le Pertuis;455;12;467 +43151;Pinols;192;6;198 +43152;Polignac;2814;85;2899 +43153;Pont-Salomon;2019;31;2050 +43154;Pradelles;549;27;576 +43155;Prades;64;2;66 +43156;Présailles;116;6;122 +43157;Le Puy-en-Velay;18995;949;19944 +43158;Queyrières;305;17;322 +43159;Raucoules;923;23;946 +43160;Rauret;195;6;201 +43162;Retournac;2929;59;2988 +43163;Riotord;1174;17;1191 +43164;Roche-en-Régnier;500;7;507 +43165;Rosières;1528;32;1560 +43166;Saint-André-de-Chalencon;356;15;371 +43167;Saint-Arcons-d'Allier;189;4;193 +43168;Saint-Arcons-de-Barges;121;1;122 +43169;Saint-Austremoine;45;0;45 +43170;Saint-Beauzire;415;5;420 +43171;Saint-Bérain;90;3;93 +43172;Saint-Bonnet-le-Froid;244;2;246 +43173;Saint-Christophe-d'Allier;91;1;92 +43174;Saint-Christophe-sur-Dolaison;953;12;965 +43175;Saint-Cirgues;163;6;169 +43177;Saint-Didier-en-Velay;3403;51;3454 +43178;Saint-Didier-sur-Doulon;195;8;203 +43180;Saint-Étienne-du-Vigan;100;4;104 +43181;Saint-Étienne-Lardeyrol;759;20;779 +43182;Saint-Étienne-sur-Blesle;55;1;56 +43184;Saint-Ferréol-d'Auroure;2464;30;2494 +43186;Saint-Front;403;4;407 +43187;Saint-Geneys-près-Saint-Paulien;317;4;321 +43188;Saint-Georges-d'Aurac;466;6;472 +43189;Saint-Georges-Lagricol;527;13;540 +43190;Saint-Germain-Laprade;3634;82;3716 +43191;Saint-Géron;258;4;262 +43192;Saint-Haon;300;8;308 +43193;Saint-Hilaire;158;2;160 +43194;Saint-Hostien;755;18;773 +43195;Saint-Ilpize;189;5;194 +43196;Saint-Jean-d'Aubrigoux;177;2;179 +43197;Saint-Jean-de-Nay;355;5;360 +43198;Saint-Jean-Lachalm;289;8;297 +43199;Saint-Jeures;964;26;990 +43200;Saint-Julien-Chapteuil;1920;42;1962 +43201;Saint-Julien-d'Ance;247;8;255 +43202;Saint-Julien-des-Chazes;67;1;68 +43203;Saint-Julien-du-Pinet;471;13;484 +43204;Saint-Julien-Molhesabate;176;1;177 +43205;Saint-Just-Malmont;4194;76;4270 +43206;Saint-Just-près-Brioude;426;14;440 +43207;Saint-Laurent-Chabreuges;257;12;269 +43210;Saint-Martin-de-Fugères;219;5;224 +43211;Saint-Maurice-de-Lignon;2597;70;2667 +43212;Saint-Pal-de-Chalencon;1016;16;1032 +43213;Saint-Pal-de-Mons;2281;54;2335 +43214;Saint-Pal-de-Senouire;109;2;111 +43215;Saint-Paul-de-Tartas;194;7;201 +43216;Saint-Paulien;2416;54;2470 +43217;Saint-Pierre-du-Champ;530;12;542 +43218;Saint-Pierre-Eynac;1147;28;1175 +43219;Saint-Préjet-Armandon;107;3;110 +43220;Saint-Préjet-d'Allier;165;5;170 +43221;Saint-Privat-d'Allier;398;12;410 +43222;Saint-Privat-du-Dragon;157;3;160 +43223;Saint-Romain-Lachalm;1093;24;1117 +43225;Saint-Vénérand;52;0;52 +43226;Saint-Vert;112;3;115 +43227;Saint-Victor-Malescours;818;18;836 +43228;Saint-Victor-sur-Arlanc;89;2;91 +43229;Saint-Vidal;603;9;612 +43230;Saint-Vincent;1012;20;1032 +43183;Sainte-Eugénie-de-Villeneuve;107;2;109 +43185;Sainte-Florine;3154;67;3221 +43208;Sainte-Marguerite;43;2;45 +43224;Sainte-Sigolène;5959;99;6058 +43231;Salettes;136;4;140 +43232;Salzuit;362;7;369 +43233;Sanssac-l'Église;1116;41;1157 +43234;Saugues;1736;127;1863 +43236;La Séauve-sur-Semène;1470;19;1489 +43237;Sembadel;229;6;235 +43238;Séneujols;310;7;317 +43239;Siaugues-Sainte-Marie;799;16;815 +43240;Solignac-sous-Roche;243;7;250 +43241;Solignac-sur-Loire;1270;32;1302 +43242;Tailhac;72;3;75 +43244;Tence;3098;45;3143 +43245;Thoras;229;8;237 +43246;Tiranges;479;16;495 +43247;Torsiac;68;1;69 +43249;Valprivas;509;11;520 +43250;Vals-le-Chastel;44;3;47 +43251;Vals-près-le-Puy;3396;130;3526 +43252;Varennes-Saint-Honorat;24;2;26 +43253;Les Vastres;203;6;209 +43254;Vazeilles-Limandre;253;4;257 +43256;Venteuges;347;6;353 +43257;Vergezac;502;6;508 +43258;Vergongheon;1851;58;1909 +43259;Vernassal;355;11;366 +43260;Le Vernet;24;0;24 +43261;Vézézoux;593;6;599 +43262;Vieille-Brioude;1194;39;1233 +43263;Vielprat;55;1;56 +43264;Villeneuve-d'Allier;290;10;300 +43265;Les Villettes;1423;24;1447 +43013;Vissac-Auteyrac;327;12;339 +43267;Vorey;1447;15;1462 +43268;Yssingeaux;7202;465;7667 +44001;Abbaretz;2088;27;2115 +44002;Aigrefeuille-sur-Maine;3936;107;4043 +44003;Ancenis-Saint-Géréon;10802;382;11184 +44006;Assérac;1790;32;1822 +44007;Avessac;2476;54;2530 +44009;Basse-Goulaine;9036;232;9268 +44010;Batz-sur-Mer;2906;75;2981 +44055;La Baule-Escoublac;16132;526;16658 +44012;La Bernerie-en-Retz;2968;48;3016 +44013;Besné;3051;35;3086 +44014;Le Bignon;3770;69;3839 +44015;Blain;9793;170;9963 +44016;La Boissière-du-Doré;1045;19;1064 +44018;Bouaye;7844;153;7997 +44019;Bouée;991;14;1005 +44020;Bouguenais;19331;278;19609 +44022;Boussay;2621;35;2656 +44023;Bouvron;3115;46;3161 +44024;Brains;2840;58;2898 +44025;Campbon;3998;69;4067 +44026;Carquefou;19805;433;20238 +44027;Casson;2303;26;2329 +44028;Le Cellier;3793;99;3892 +44030;La Chapelle-des-Marais;4185;85;4270 +44031;La Chapelle-Glain;812;8;820 +44032;La Chapelle-Heulin;3263;45;3308 +44033;La Chapelle-Launay;3052;42;3094 +44035;La Chapelle-sur-Erdre;19609;435;20044 +44037;Château-Thébaud;3026;174;3200 +44036;Châteaubriant;11974;518;12492 +44005;Chaumes-en-Retz;6759;109;6868 +44038;Chauvé;2876;46;2922 +44039;Cheix-en-Retz;1067;8;1075 +44221;La Chevallerais;1549;20;1569 +44041;La Chevrolière;5589;81;5670 +44043;Clisson;7187;234;7421 +44044;Conquereuil;1116;18;1134 +44156;Corcoué-sur-Logne;2927;39;2966 +44045;Cordemais;3705;46;3751 +44046;Corsept;2667;54;2721 +44047;Couëron;21372;243;21615 +44048;Couffé;2563;51;2614 +44049;Le Croisic;4093;54;4147 +44050;Crossac;2952;28;2980 +44051;Derval;3489;427;3916 +44029;Divatte-sur-Loire;6844;99;6943 +44052;Donges;7961;92;8053 +44053;Drefféac;2228;33;2261 +44054;Erbray;3006;72;3078 +44056;Fay-de-Bretagne;3618;56;3674 +44057;Fégréac;2445;49;2494 +44058;Fercé;474;11;485 +44061;Frossay;3221;57;3278 +44062;Le Gâvre;1796;37;1833 +44223;Geneston;3641;47;3688 +44063;Gétigné;3669;65;3734 +44064;Gorges;4658;338;4996 +44065;Grand-Auverné;768;13;781 +44066;Grandchamps-des-Fontaines;6016;109;6125 +44224;La Grigonnais;1675;23;1698 +44067;Guémené-Penfao;5200;81;5281 +44068;Guenrouet;3349;56;3405 +44069;Guérande;15873;553;16426 +44070;La Haie-Fouassière;4659;110;4769 +44071;Haute-Goulaine;5764;122;5886 +44072;Herbignac;6822;124;6946 +44073;Héric;6049;82;6131 +44074;Indre;3969;44;4013 +44075;Issé;1833;39;1872 +44076;Jans;1370;23;1393 +44077;Joué-sur-Erdre;2482;34;2516 +44078;Juigné-des-Moutiers;345;3;348 +44079;Le Landreau;2995;296;3291 +44080;Lavau-sur-Loire;767;26;793 +44081;Legé;4514;112;4626 +44082;Ligné;5174;66;5240 +44083;La Limouzinière;2414;29;2443 +44213;Loireauxence;7522;137;7659 +44084;Le Loroux-Bottereau;8227;133;8360 +44085;Louisfert;1029;29;1058 +44086;Lusanger;1047;20;1067 +44087;Machecoul-Saint-Même;7473;243;7716 +44088;Maisdon-sur-Sèvre;2942;38;2980 +44089;Malville;3463;52;3515 +44090;La Marne;1503;17;1520 +44091;Marsac-sur-Don;1507;21;1528 +44092;Massérac;691;13;704 +44094;Mauves-sur-Loire;3215;44;3259 +44095;La Meilleraye-de-Bretagne;1527;24;1551 +44096;Mésanger;4687;75;4762 +44097;Mesquer;1941;41;1982 +44098;Missillac;5342;68;5410 +44099;Moisdon-la-Rivière;1951;59;2010 +44100;Monnières;2239;46;2285 +44101;La Montagne;6231;148;6379 +44102;Montbert;3125;55;3180 +44103;Montoir-de-Bretagne;7088;78;7166 +44104;Montrelais;852;11;863 +44105;Mouais;385;4;389 +44106;Les Moutiers-en-Retz;1640;24;1664 +44107;Mouzeil;1889;25;1914 +44108;Mouzillon;2830;52;2882 +44109;Nantes;309346;5157;314503 +44110;Nort-sur-Erdre;8763;186;8949 +44111;Notre-Dame-des-Landes;2184;24;2208 +44112;Noyal-sur-Brutz;592;11;603 +44113;Nozay;4150;45;4195 +44114;Orvault;26355;727;27082 +44115;Oudon;3805;65;3870 +44116;Paimbœuf;3090;110;3200 +44117;Le Pallet;3239;53;3292 +44118;Pannecé;1364;23;1387 +44119;Paulx;1981;27;2008 +44120;Le Pellerin;5100;159;5259 +44121;Petit-Auverné;428;4;432 +44122;Petit-Mars;3601;52;3653 +44123;Pierric;976;15;991 +44124;Le Pin;754;15;769 +44125;Piriac-sur-Mer;2245;51;2296 +44126;La Plaine-sur-Mer;4266;85;4351 +44127;La Planche;2640;32;2672 +44128;Plessé;5248;131;5379 +44130;Pont-Saint-Martin;6037;81;6118 +44129;Pontchâteau;10684;219;10903 +44131;Pornic;15018;389;15407 +44132;Pornichet;10669;293;10962 +44133;Port-Saint-Père;2913;42;2955 +44134;Pouillé-les-Côteaux;1051;25;1076 +44135;Le Pouliguen;4275;101;4376 +44136;Préfailles;1246;30;1276 +44137;Prinquiau;3459;65;3524 +44138;Puceul;1128;19;1147 +44139;Quilly;1380;11;1391 +44140;La Regrippière;1527;26;1553 +44141;La Remaudière;1285;13;1298 +44142;Remouillé;1903;35;1938 +44143;Rezé;41411;743;42154 +44144;Riaillé;2333;58;2391 +44222;La Roche-Blanche;1194;13;1207 +44145;Rouans;2956;37;2993 +44146;Rougé;2230;58;2288 +44148;Ruffigné;703;8;711 +44149;Saffré;3907;50;3957 +44150;Saint-Aignan-Grandlieu;3944;60;4004 +44151;Saint-André-des-Eaux;6473;170;6643 +44153;Saint-Aubin-des-Châteaux;1795;43;1838 +44154;Saint-Brevin-les-Pins;13802;302;14104 +44155;Saint-Colomban;3355;75;3430 +44157;Saint-Étienne-de-Mer-Morte;1733;20;1753 +44158;Saint-Étienne-de-Montluc;7129;183;7312 +44159;Saint-Fiacre-sur-Maine;1207;22;1229 +44161;Saint-Gildas-des-Bois;3774;69;3843 +44162;Saint-Herblain;46268;730;46998 +44164;Saint-Hilaire-de-Chaléons;2287;44;2331 +44165;Saint-Hilaire-de-Clisson;2285;44;2329 +44166;Saint-Jean-de-Boiseau;5827;109;5936 +44168;Saint-Joachim;4033;64;4097 +44169;Saint-Julien-de-Concelles;6917;98;7015 +44170;Saint-Julien-de-Vouvantes;984;15;999 +44171;Saint-Léger-les-Vignes;1844;33;1877 +44173;Saint-Lumine-de-Clisson;2103;45;2148 +44174;Saint-Lumine-de-Coutais;2162;39;2201 +44175;Saint-Lyphard;4760;96;4856 +44176;Saint-Malo-de-Guersac;3166;64;3230 +44178;Saint-Mars-de-Coutais;2610;43;2653 +44179;Saint-Mars-du-Désert;4899;80;4979 +44182;Saint-Michel-Chef-Chef;4993;85;5078 +44183;Saint-Molf;2622;57;2679 +44184;Saint-Nazaire;69993;1779;71772 +44185;Saint-Nicolas-de-Redon;3179;68;3247 +44187;Saint-Père-en-Retz;4564;156;4720 +44188;Saint-Philbert-de-Grand-Lieu;8921;192;9113 +44190;Saint-Sébastien-sur-Loire;26838;670;27508 +44192;Saint-Viaud;2510;42;2552 +44193;Saint-Vincent-des-Landes;1528;27;1555 +44152;Sainte-Anne-sur-Brivet;2967;52;3019 +44172;Sainte-Luce-sur-Loire;15360;256;15616 +44186;Sainte-Pazanne;6774;127;6901 +44189;Sainte-Reine-de-Bretagne;2374;29;2403 +44194;Sautron;8192;158;8350 +44195;Savenay;8679;177;8856 +44196;Sévérac;1627;22;1649 +44197;Sion-les-Mines;1583;40;1623 +44198;Les Sorinières;8541;128;8669 +44199;Soudan;1997;56;2053 +44200;Soulvache;350;4;354 +44201;Sucé-sur-Erdre;7023;197;7220 +44202;Teillé;1791;25;1816 +44203;Le Temple-de-Bretagne;1967;16;1983 +44204;Thouaré-sur-Loire;10025;187;10212 +44205;Les Touches;2474;31;2505 +44206;Touvois;1828;25;1853 +44207;Trans-sur-Erdre;1077;6;1083 +44208;Treffieux;883;11;894 +44209;Treillières;9219;238;9457 +44210;Trignac;7868;79;7947 +44211;La Turballe;4426;97;4523 +44163;Vair-sur-Loire;4671;101;4772 +44212;Vallet;9015;170;9185 +44180;Vallons-de-l'Erdre;6556;120;6676 +44214;Vay;2046;28;2074 +44215;Vertou;24219;649;24868 +44216;Vieillevigne;3959;72;4031 +44217;Vigneux-de-Bretagne;6030;127;6157 +44021;Villeneuve-en-Retz;4929;53;4982 +44218;Villepot;669;14;683 +44220;Vue;1638;26;1664 +45001;Adon;220;5;225 +45002;Aillant-sur-Milleron;398;8;406 +45004;Amilly;12977;600;13577 +45005;Andonville;246;6;252 +45006;Ardon;1117;28;1145 +45008;Artenay;1890;27;1917 +45009;Aschères-le-Marché;1145;30;1175 +45010;Ascoux;1164;21;1185 +45011;Attray;211;4;215 +45012;Audeville;190;2;192 +45013;Augerville-la-Rivière;232;3;235 +45014;Aulnay-la-Rivière;506;13;519 +45015;Autruy-sur-Juine;688;13;701 +45016;Autry-le-Châtel;961;27;988 +45017;Auvilliers-en-Gâtinais;360;3;363 +45018;Auxy;987;18;1005 +45019;Baccon;690;29;719 +45020;Le Bardon;1036;18;1054 +45021;Barville-en-Gâtinais;324;6;330 +45022;Batilly-en-Gâtinais;458;3;461 +45023;Batilly-en-Puisaye;116;2;118 +45024;Baule;2073;38;2111 +45025;Bazoches-les-Gallerandes;1538;21;1559 +45026;Bazoches-sur-le-Betz;946;18;964 +45027;Beauchamps-sur-Huillard;405;7;412 +45028;Beaugency;7298;185;7483 +45029;Beaulieu-sur-Loire;1815;21;1836 +45030;Beaune-la-Rolande;2008;128;2136 +45031;Bellegarde;1620;83;1703 +45032;Le Bignon-Mirabeau;323;8;331 +45033;Boësses;380;20;400 +45034;Boigny-sur-Bionne;2128;51;2179 +45035;Boiscommun;1140;23;1163 +45036;Boismorand;815;17;832 +45037;Boisseaux;497;10;507 +45038;Bondaroy;412;13;425 +45039;Bonnée;713;12;725 +45040;Bonny-sur-Loire;1952;27;1979 +45041;Bordeaux-en-Gâtinais;112;3;115 +45042;Les Bordes;1892;43;1935 +45043;Bou;958;23;981 +45044;Bougy-lez-Neuville;159;3;162 +45045;Bouilly-en-Gâtinais;319;15;334 +45046;Boulay-les-Barres;982;18;1000 +45047;Bouzonville-aux-Bois;428;14;442 +45049;Bouzy-la-Forêt;1221;29;1250 +45050;Boynes;1355;37;1392 +45051;Bray-Saint-Aignan;1746;34;1780 +45052;Breteau;90;0;90 +45053;Briare;5209;94;5303 +45054;Briarres-sur-Essonne;544;10;554 +45055;Bricy;554;15;569 +45056;Bromeilles;329;6;335 +45058;Bucy-le-Roi;171;1;172 +45059;Bucy-Saint-Liphard;191;1;192 +45060;La Bussière;805;18;823 +45061;Cepoy;2367;51;2418 +45062;Cercottes;1459;25;1484 +45063;Cerdon;942;19;961 +45064;Cernoy-en-Berry;451;10;461 +45065;Césarville-Dossainville;273;2;275 +45066;Chailly-en-Gâtinais;683;11;694 +45067;Chaingy;3663;124;3787 +45068;Châlette-sur-Loing;12576;259;12835 +45069;Chambon-la-Forêt;942;14;956 +45070;Champoulet;55;0;55 +45072;Chanteau;1470;21;1491 +45073;Chantecoq;494;8;502 +45074;La Chapelle-Onzerain;124;2;126 +45075;La Chapelle-Saint-Mesmin;10353;197;10550 +45076;La Chapelle-Saint-Sépulcre;241;6;247 +45077;La Chapelle-sur-Aveyron;636;6;642 +45078;Chapelon;257;0;257 +45079;Le Charme;151;0;151 +45080;Charmont-en-Beauce;367;9;376 +45081;Charsonville;616;18;634 +45083;Château-Renard;2187;33;2220 +45082;Châteauneuf-sur-Loire;8126;112;8238 +45084;Châtenoy;471;10;481 +45085;Châtillon-Coligny;1889;25;1914 +45086;Châtillon-le-Roi;276;8;284 +45087;Châtillon-sur-Loire;3144;52;3196 +45088;Chaussy;316;11;327 +45089;Chécy;8667;175;8842 +45091;Chevannes;320;13;333 +45092;Chevillon-sur-Huillard;1422;37;1459 +45093;Chevilly;2662;38;2700 +45094;Chevry-sous-le-Bignon;226;2;228 +45095;Chilleurs-aux-Bois;1992;33;2025 +45096;Les Choux;515;9;524 +45097;Chuelles;1196;13;1209 +45098;Cléry-Saint-André;3443;66;3509 +45099;Coinces;543;9;552 +45100;Combleux;498;22;520 +45101;Combreux;276;6;282 +45102;Conflans-sur-Loing;365;10;375 +45103;Corbeilles;1544;17;1561 +45104;Corquilleroy;2792;54;2846 +45105;Cortrat;76;2;78 +45107;Coudroy;322;0;322 +45108;Coullons;2370;37;2407 +45109;Coulmiers;536;12;548 +45112;La Cour-Marigny;350;11;361 +45110;Courcelles-le-Roi;309;2;311 +45111;Courcy-aux-Loges;442;2;444 +45113;Courtemaux;257;2;259 +45114;Courtempierre;235;3;238 +45115;Courtenay;4018;68;4086 +45116;Cravant;977;17;994 +45118;Crottes-en-Pithiverais;339;6;345 +45119;Dadonville;2433;64;2497 +45120;Dammarie-en-Puisaye;173;2;175 +45121;Dammarie-sur-Loing;489;9;498 +45122;Dampierre-en-Burly;1508;26;1534 +45123;Darvoy;1865;32;1897 +45124;Desmonts;170;3;173 +45125;Dimancheville;115;3;118 +45126;Donnery;2854;39;2893 +45127;Dordives;3313;37;3350 +45129;Douchy-Montcorbon;1385;26;1411 +45130;Dry;1391;33;1424 +45131;Échilleuses;396;8;404 +45132;Égry;360;5;365 +45133;Engenville;564;17;581 +45134;Épieds-en-Beauce;1435;27;1462 +45135;Erceville;307;5;312 +45136;Ervauville;546;6;552 +45137;Escrennes;732;17;749 +45138;Escrignelles;52;0;52 +45139;Estouy;514;18;532 +45141;Faverelles;154;1;155 +45142;Fay-aux-Loges;3756;67;3823 +45143;Feins-en-Gâtinais;35;1;36 +45144;Férolles;1153;83;1236 +45145;Ferrières-en-Gâtinais;3687;80;3767 +45146;La Ferté-Saint-Aubin;7454;123;7577 +45147;Fleury-les-Aubrais;21026;279;21305 +45148;Fontenay-sur-Loing;1720;14;1734 +45149;Foucherolles;278;2;280 +45150;Fréville-du-Gâtinais;180;4;184 +45151;Gaubertin;257;8;265 +45152;Gémigny;206;4;210 +45153;Germigny-des-Prés;722;24;746 +45154;Gidy;2009;33;2042 +45155;Gien;14007;423;14430 +45156;Girolles;619;20;639 +45157;Givraines;414;6;420 +45158;Gondreville;335;10;345 +45159;Grangermont;193;3;196 +45160;Greneville-en-Beauce;700;8;708 +45161;Griselles;792;19;811 +45162;Guigneville;529;14;543 +45164;Guilly;644;16;660 +45165;Gy-les-Nonains;628;9;637 +45166;Huêtre;283;5;288 +45167;Huisseau-sur-Mauves;1655;30;1685 +45168;Ingrannes;537;3;540 +45169;Ingré;9087;227;9314 +45170;Intville-la-Guétard;140;2;142 +45171;Isdes;556;12;568 +45173;Jargeau;4604;45;4649 +45174;Jouy-en-Pithiverais;272;0;272 +45175;Jouy-le-Potier;1350;30;1380 +45176;Juranville;442;4;446 +45177;Laas;236;4;240 +45178;Ladon;1389;18;1407 +45179;Lailly-en-Val;3112;45;3157 +45180;Langesse;79;0;79 +45181;Léouville;83;2;85 +45182;Ligny-le-Ribault;1236;29;1265 +45183;Lion-en-Beauce;140;1;141 +45184;Lion-en-Sullias;405;6;411 +45185;Lombreuil;303;10;313 +45186;Lorcy;560;8;568 +45187;Lorris;2943;50;2993 +45188;Loury;2452;59;2511 +45189;Louzouer;266;7;273 +45191;Le Malesherbois;8201;162;8363 +45193;Marcilly-en-Villette;2124;39;2163 +45194;Mardié;2816;52;2868 +45195;Mareau-aux-Bois;576;14;590 +45196;Mareau-aux-Prés;1351;23;1374 +45197;Marigny-les-Usages;1560;35;1595 +45198;Marsainvilliers;297;8;305 +45199;Melleroy;504;4;508 +45200;Ménestreau-en-Villette;1468;35;1503 +45201;Mérinville;185;3;188 +45202;Messas;923;14;937 +45203;Meung-sur-Loire;6440;93;6533 +45205;Mézières-en-Gâtinais;272;5;277 +45204;Mézières-lez-Cléry;824;21;845 +45206;Mignères;320;3;323 +45207;Mignerette;395;8;403 +45208;Montargis;14643;569;15212 +45209;Montbarrois;311;4;315 +45210;Montbouy;739;18;757 +45212;Montcresson;1281;26;1307 +45213;Montereau;608;14;622 +45214;Montigny;246;4;250 +45215;Montliard;235;3;238 +45216;Mormant-sur-Vernisson;120;2;122 +45217;Morville-en-Beauce;168;6;174 +45218;Le Moulinet-sur-Solin;119;1;120 +45219;Moulon;195;1;196 +45220;Nancray-sur-Rimarde;599;18;617 +45222;Nargis;1498;33;1531 +45223;Nesploy;368;7;375 +45224;Neuville-aux-Bois;4714;72;4786 +45225;La Neuville-sur-Essonne;386;14;400 +45226;Neuvy-en-Sullias;1362;26;1388 +45227;Nevoy;1171;23;1194 +45228;Nibelle;1177;11;1188 +45229;Nogent-sur-Vernisson;2556;33;2589 +45230;Noyers;756;4;760 +45231;Oison;130;9;139 +45232;Olivet;21951;523;22474 +45233;Ondreville-sur-Essonne;407;9;416 +45234;Orléans;116685;2400;119085 +45235;Ormes;4122;78;4200 +45237;Orville;119;1;120 +45238;Ousson-sur-Loire;752;9;761 +45239;Oussoy-en-Gâtinais;409;13;422 +45240;Outarville;1337;23;1360 +45241;Ouvrouer-les-Champs;558;11;569 +45242;Ouzouer-des-Champs;244;8;252 +45243;Ouzouer-sous-Bellegarde;313;6;319 +45244;Ouzouer-sur-Loire;2738;70;2808 +45245;Ouzouer-sur-Trézée;1131;21;1152 +45246;Pannecières;131;1;132 +45247;Pannes;3698;63;3761 +45248;Patay;2190;34;2224 +45249;Paucourt;904;24;928 +45250;Pers-en-Gâtinais;256;1;257 +45251;Pierrefitte-ès-Bois;309;4;313 +45252;Pithiviers;8981;148;9129 +45253;Pithiviers-le-Vieil;1813;47;1860 +45254;Poilly-lez-Gien;2406;62;2468 +45255;Préfontaines;452;9;461 +45256;Presnoy;246;6;252 +45257;Pressigny-les-Pins;498;7;505 +45258;Puiseaux;3416;58;3474 +45259;Quiers-sur-Bézonde;1152;22;1174 +45260;Ramoulu;251;9;260 +45261;Rebréchien;1324;17;1341 +45262;Rouvray-Sainte-Croix;142;0;142 +45263;Rouvres-Saint-Jean;281;8;289 +45264;Rozières-en-Beauce;194;5;199 +45265;Rozoy-le-Vieil;418;5;423 +45266;Ruan;205;1;206 +45268;Saint-Aignan-le-Jaillard;606;7;613 +45269;Saint-Ay;3454;68;3522 +45270;Saint-Benoît-sur-Loire;2030;44;2074 +45271;Saint-Brisson-sur-Loire;981;25;1006 +45272;Saint-Cyr-en-Val;3309;72;3381 +45273;Saint-Denis-de-l'Hôtel;3045;39;3084 +45274;Saint-Denis-en-Val;7517;177;7694 +45275;Saint-Firmin-des-Bois;462;4;466 +45276;Saint-Firmin-sur-Loire;521;5;526 +45277;Saint-Florent;457;11;468 +45279;Saint-Germain-des-Prés;1916;18;1934 +45280;Saint-Gondon;1109;19;1128 +45281;Saint-Hilaire-les-Andrésis;916;15;931 +45282;Saint-Hilaire-Saint-Mesmin;3040;83;3123 +45283;Saint-Hilaire-sur-Puiseaux;175;4;179 +45284;Saint-Jean-de-Braye;20751;598;21349 +45285;Saint-Jean-de-la-Ruelle;16273;306;16579 +45286;Saint-Jean-le-Blanc;8702;222;8924 +45287;Saint-Loup-de-Gonois;97;3;100 +45288;Saint-Loup-des-Vignes;398;10;408 +45289;Saint-Lyé-la-Forêt;1170;18;1188 +45290;Saint-Martin-d'Abbat;1769;28;1797 +45291;Saint-Martin-sur-Ocre;1240;37;1277 +45292;Saint-Maurice-sur-Aveyron;865;14;879 +45293;Saint-Maurice-sur-Fessard;1183;26;1209 +45294;Saint-Michel;123;0;123 +45296;Saint-Péravy-la-Colombe;759;15;774 +45297;Saint-Père-sur-Loire;1049;12;1061 +45298;Saint-Pryvé-Saint-Mesmin;5803;98;5901 +45299;Saint-Sigismond;262;4;266 +45278;Sainte-Geneviève-des-Bois;1083;34;1117 +45300;Sandillon;3971;87;4058 +45301;Santeau;420;3;423 +45302;Saran;16365;208;16573 +45303;Sceaux-du-Gâtinais;635;13;648 +45305;Seichebrières;207;1;208 +45306;La Selle-en-Hermoy;810;14;824 +45307;La Selle-sur-le-Bied;1012;20;1032 +45308;Semoy;3176;73;3249 +45309;Sennely;709;6;715 +45310;Sermaises;1646;23;1669 +45311;Sigloy;678;5;683 +45312;Solterre;469;7;476 +45313;Sougy;826;13;839 +45314;Sully-la-Chapelle;431;8;439 +45315;Sully-sur-Loire;5348;91;5439 +45316;Sury-aux-Bois;792;19;811 +45317;Tavers;1346;36;1382 +45320;Thignonville;400;11;411 +45321;Thimory;737;11;748 +45322;Thorailles;179;4;183 +45323;Thou;229;4;233 +45324;Tigy;2315;48;2363 +45325;Tivernon;285;4;289 +45326;Tournoisis;407;9;416 +45327;Traînou;3343;79;3422 +45328;Treilles-en-Gâtinais;287;5;292 +45329;Triguères;1293;25;1318 +45330;Trinay;225;4;229 +45331;Vannes-sur-Cosson;602;8;610 +45332;Varennes-Changy;1489;26;1515 +45333;Vennecy;1812;37;1849 +45334;Vieilles-Maisons-sur-Joudry;638;8;646 +45335;Vienne-en-Val;1942;29;1971 +45336;Viglain;871;7;878 +45337;Villamblain;285;8;293 +45338;Villemandeur;6815;349;7164 +45339;Villemoutiers;486;6;492 +45340;Villemurlin;585;3;588 +45341;Villeneuve-sur-Conie;206;7;213 +45342;Villereau;375;3;378 +45343;Villevoques;212;6;218 +45344;Villorceau;1132;22;1154 +45345;Vimory;1173;35;1208 +45346;Vitry-aux-Loges;2185;37;2222 +45347;Vrigny;823;24;847 +45348;Yèvre-la-Ville;702;17;719 +46001;Albas;525;13;538 +46002;Albiac;70;2;72 +46003;Alvignac;720;26;746 +46004;Anglars;214;2;216 +46005;Anglars-Juillac;326;8;334 +46006;Anglars-Nozac;365;4;369 +46007;Arcambal;994;24;1018 +46008;Les Arques;195;5;200 +46009;Assier;651;20;671 +46010;Aujols;364;10;374 +46011;Autoire;358;9;367 +46012;Aynac;550;10;560 +46013;Bach;178;2;180 +46015;Bagnac-sur-Célé;1475;38;1513 +46016;Baladou;399;16;415 +46017;Bannes;135;3;138 +46263;Barguelonne-en-Quercy;680;17;697 +46018;Le Bastit;143;3;146 +46020;Beauregard;233;12;245 +46021;Béduer;720;26;746 +46022;Bélaye;224;1;225 +46023;Belfort-du-Quercy;516;6;522 +46156;Bellefont-La Rauze;1230;24;1254 +46024;Belmont-Bretenoux;401;11;412 +46026;Belmont-Sainte-Foi;101;3;104 +46027;Berganty;116;2;118 +46338;Bessonies;81;2;83 +46028;Bétaille;1006;26;1032 +46029;Biars-sur-Cère;2139;52;2191 +46030;Bio;348;13;361 +46031;Blars;138;3;141 +46032;Boissières;397;5;402 +46034;Le Bourg;331;10;341 +46035;Boussac;185;8;193 +46036;Le Bouyssou;139;2;141 +46037;Bouziès;84;1;85 +46039;Brengues;211;5;216 +46038;Bretenoux;1356;26;1382 +46040;Cabrerets;229;8;237 +46041;Cadrieu;158;7;165 +46042;Cahors;19878;930;20808 +46043;Cahus;206;2;208 +46044;Caillac;599;21;620 +46045;Cajarc;1125;34;1159 +46046;Calamane;458;10;468 +46047;Calès;167;6;173 +46049;Calvignac;207;3;210 +46050;Cambayrac;154;5;159 +46051;Cambes;364;10;374 +46052;Camboulit;257;5;262 +46053;Camburat;421;13;434 +46054;Caniac-du-Causse;367;3;370 +46055;Capdenac;1105;26;1131 +46056;Carayac;101;5;106 +46057;Cardaillac;602;18;620 +46058;Carennac;408;15;423 +46059;Carlucet;220;9;229 +46060;Carnac-Rouffiac;219;1;220 +46061;Cassagnes;181;4;185 +46062;Castelfranc;426;8;434 +46063;Castelnau Montratier-Sainte Alauzie;1880;41;1921 +46064;Catus;860;15;875 +46065;Cavagnac;461;14;475 +46066;Cazals;625;15;640 +46068;Cénevières;172;3;175 +46069;Cézac;168;2;170 +46070;Cieurac;550;14;564 +46072;Concorès;313;7;320 +46073;Concots;423;17;440 +46074;Condat;414;8;422 +46075;Corn;227;5;232 +46076;Cornac;348;9;357 +46078;Couzou;92;2;94 +46079;Cras;103;2;105 +46080;Crayssac;770;13;783 +46081;Crégols;76;3;79 +46082;Cremps;361;9;370 +46083;Cressensac-Sarrazac;1136;23;1159 +46084;Creysse;305;8;313 +46085;Cuzac;241;6;247 +46086;Cuzance;607;13;620 +46138;Cœur de Causse;954;20;974 +46087;Dégagnac;667;18;685 +46088;Douelle;816;29;845 +46089;Duravel;965;7;972 +46090;Durbans;141;2;143 +46091;Escamps;209;5;214 +46092;Esclauzels;224;4;228 +46093;Espagnac-Sainte-Eulalie;91;3;94 +46094;Espédaillac;270;5;275 +46095;Espère;1044;26;1070 +46096;Espeyroux;97;2;99 +46097;Estal;109;6;115 +46098;Fajoles;288;6;294 +46100;Faycelles;659;26;685 +46101;Felzins;443;6;449 +46102;Figeac;9792;681;10473 +46104;Flaujac-Gare;99;6;105 +46105;Flaujac-Poujols;772;17;789 +46106;Floirac;258;7;265 +46107;Floressas;163;5;168 +46108;Fons;405;17;422 +46109;Fontanes;476;8;484 +46111;Fourmagnac;161;4;165 +46112;Francoulès;220;5;225 +46113;Frayssinet;304;7;311 +46114;Frayssinet-le-Gélat;358;7;365 +46115;Frayssinhes;167;6;173 +46116;Frontenac;69;6;75 +46117;Gagnac-sur-Cère;671;44;715 +46118;Gignac;666;13;679 +46119;Gigouzac;275;0;275 +46120;Gindou;321;4;325 +46121;Ginouillac;154;5;159 +46122;Gintrac;103;4;107 +46123;Girac;379;8;387 +46124;Glanes;308;11;319 +46125;Gorses;325;10;335 +46126;Goujounac;225;2;227 +46127;Gourdon;4094;128;4222 +46128;Gramat;3528;65;3593 +46129;Gréalou;282;9;291 +46130;Grézels;224;5;229 +46131;Grèzes;175;5;180 +46132;Issendolus;516;22;538 +46133;Issepts;241;4;245 +46134;Les Junies;269;5;274 +46135;Labastide-du-Haut-Mont;49;1;50 +46136;Labastide-du-Vert;269;7;276 +46137;Labastide-Marnhac;1226;22;1248 +46139;Labathude;209;6;215 +46140;Laburgade;353;14;367 +46142;Lacapelle-Cabanac;162;2;164 +46143;Lacapelle-Marival;1272;24;1296 +46144;Lacave;262;13;275 +46145;Lachapelle-Auzac;792;13;805 +46146;Ladirat;97;5;102 +46147;Lagardelle;124;0;124 +46148;Lalbenque;1684;45;1729 +46149;Lamagdelaine;698;21;719 +46151;Lamothe-Cassel;129;3;132 +46152;Lamothe-Fénelon;293;4;297 +46153;Lanzac;588;17;605 +46154;Laramière;348;12;360 +46155;Larnagol;137;1;138 +46157;Larroque-Toirac;133;5;138 +46159;Latouille-Lentillac;226;13;239 +46160;Latronquière;441;15;456 +46161;Lauresses;263;6;269 +46162;Lauzès;189;6;195 +46163;Laval-de-Cère;296;8;304 +46164;Lavercantière;244;12;256 +46165;Lavergne;446;17;463 +46262;Lendou-en-Quercy;642;15;657 +46167;Lentillac-du-Causse;99;0;99 +46168;Lentillac-Saint-Blaise;179;1;180 +46169;Léobard;210;7;217 +46170;Leyme;933;24;957 +46171;Lherm;229;2;231 +46172;Lhospitalet;496;17;513 +46173;Limogne-en-Quercy;762;19;781 +46174;Linac;223;1;224 +46175;Lissac-et-Mouret;918;32;950 +46176;Livernon;680;17;697 +46177;Loubressac;537;21;558 +46178;Loupiac;260;1;261 +46179;Lugagnac;127;5;132 +46180;Lunan;567;21;588 +46181;Lunegarde;100;3;103 +46182;Luzech;1815;30;1845 +46183;Marcilhac-sur-Célé;200;2;202 +46184;Marminiac;361;11;372 +46185;Martel;1597;50;1647 +46186;Masclat;361;7;368 +46187;Mauroux;526;11;537 +46188;Maxou;305;7;312 +46337;Mayrac;249;7;256 +46189;Mayrinhac-Lentour;511;13;524 +46190;Mechmont;125;3;128 +46191;Mercuès;1116;21;1137 +46192;Meyronne;278;7;285 +46193;Miers;455;13;468 +46194;Milhac;183;3;186 +46195;Molières;362;7;369 +46196;Montamel;108;3;111 +46197;Le Montat;1036;118;1154 +46198;Montbrun;99;1;100 +46199;Montcabrier;355;3;358 +46200;Montcléra;271;5;276 +46201;Montcuq-en-Quercy-Blanc;1706;55;1761 +46202;Montdoumerc;538;7;545 +46203;Montet-et-Bouxal;218;7;225 +46204;Montfaucon;592;9;601 +46205;Montgesty;339;3;342 +46206;Montlauzun;123;4;127 +46207;Montredon;297;5;302 +46208;Montvalent;286;11;297 +46209;Nadaillac-de-Rouge;159;8;167 +46210;Nadillac;61;2;63 +46211;Nuzéjouls;372;2;374 +46212;Orniac;72;3;75 +46213;Padirac;158;10;168 +46214;Parnac;377;9;386 +46215;Payrac;620;17;637 +46216;Payrignac;671;14;685 +46252;Les Pechs du Vers;310;8;318 +46217;Pern;449;10;459 +46218;Pescadoires;190;3;193 +46219;Peyrilles;354;13;367 +46220;Pinsac;774;24;798 +46221;Planioles;525;9;534 +46222;Pomarède;189;3;192 +46223;Pontcirq;158;0;158 +46033;Porte-du-Quercy;576;10;586 +46224;Pradines;3467;100;3567 +46225;Prayssac;2397;74;2471 +46226;Prendeignes;230;8;238 +46227;Promilhanes;226;3;229 +46228;Prudhomat;715;15;730 +46231;Puy-l'Évêque;1973;31;2004 +46229;Puybrun;1005;18;1023 +46230;Puyjourdes;89;2;91 +46233;Quissac;112;3;115 +46234;Rampoux;98;2;100 +46235;Reilhac;172;4;176 +46236;Reilhaguet;130;5;135 +46237;Reyrevignes;386;12;398 +46238;Rignac;266;14;280 +46239;Le Roc;220;6;226 +46240;Rocamadour;606;20;626 +46241;Rouffilhac;186;4;190 +46242;Rudelle;173;7;180 +46243;Rueyres;196;2;198 +46244;Sabadel-Latronquière;96;0;96 +46245;Sabadel-Lauzès;79;1;80 +46246;Saignes;78;1;79 +46247;Saillac;159;5;164 +46249;Saint-Bressou;114;3;117 +46250;Saint-Caprais;75;2;77 +46251;Saint-Céré;3462;167;3629 +46253;Saint-Chamarand;187;2;189 +46254;Saint-Chels;141;5;146 +46255;Saint-Cirgues;350;14;364 +46256;Saint-Cirq-Lapopie;203;2;205 +46257;Saint-Cirq-Madelon;128;3;131 +46258;Saint-Cirq-Souillaguet;159;1;160 +46259;Saint-Clair;145;2;147 +46264;Saint-Denis-Catus;181;6;187 +46265;Saint-Denis-lès-Martel;333;7;340 +46266;Saint-Félix;522;8;530 +46267;Saint-Germain-du-Bel-Air;562;12;574 +46268;Saint Géry-Vers;863;18;881 +46269;Saint-Hilaire;66;2;68 +46270;Saint-Jean-de-Laur;237;4;241 +46339;Saint-Jean-Lagineste;336;6;342 +46271;Saint-Jean-Lespinasse;393;17;410 +46272;Saint-Jean-Mirabel;240;4;244 +46273;Saint-Laurent-les-Tours;891;25;916 +46276;Saint-Martin-Labouval;186;6;192 +46277;Saint-Martin-le-Redon;210;12;222 +46279;Saint-Maurice-en-Quercy;218;4;222 +46280;Saint-Médard;177;6;183 +46281;Saint-Médard-de-Presque;202;7;209 +46282;Saint-Médard-Nicourby;93;0;93 +46283;Saint-Michel-de-Bannières;318;8;326 +46284;Saint-Michel-Loubéjou;401;15;416 +46286;Saint-Paul-de-Vern;181;4;185 +46103;Saint-Paul-Flaugnac;997;27;1024 +46288;Saint-Perdoux;211;9;220 +46340;Saint-Pierre-Lafeuille;367;12;379 +46289;Saint-Pierre-Toirac;153;0;153 +46290;Saint-Projet;342;8;350 +46292;Saint-Simon;172;2;174 +46293;Saint-Sozy;468;12;480 +46294;Saint-Sulpice;144;4;148 +46295;Saint-Vincent-du-Pendit;191;6;197 +46296;Saint-Vincent-Rive-d'Olt;443;15;458 +46260;Sainte-Colombe;208;2;210 +46297;Salviac;1211;26;1237 +46299;Sauliac-sur-Célé;121;3;124 +46301;Sauzet;515;5;520 +46302;Sénaillac-Latronquière;142;4;146 +46303;Sénaillac-Lauzès;128;3;131 +46304;Séniergues;131;1;132 +46305;Sérignac;300;1;301 +46306;Sonac;85;3;88 +46307;Soturac;637;5;642 +46308;Soucirac;101;1;102 +46309;Souillac;3284;392;3676 +46310;Soulomès;120;2;122 +46311;Sousceyrac-en-Quercy;1351;23;1374 +46312;Strenquels;271;2;273 +46313;Tauriac;418;8;426 +46314;Terrou;168;45;213 +46315;Teyssieu;173;4;177 +46316;Thédirac;296;5;301 +46317;Thégra;472;13;485 +46318;Thémines;218;3;221 +46319;Théminettes;169;6;175 +46320;Tour-de-Faure;323;14;337 +46321;Touzac;373;8;381 +46322;Trespoux-Rassiels;812;32;844 +46323;Ussel;95;2;97 +46324;Uzech;216;4;220 +46328;Varaire;314;6;320 +46329;Vaylats;323;4;327 +46330;Vayrac;1292;26;1318 +46332;Viazac;328;4;332 +46333;Vidaillac;171;4;175 +46334;Le Vigan;1603;37;1640 +46232;Le Vignon-en-Quercy;1014;25;1039 +46335;Villesèque;396;17;413 +46336;Vire-sur-Lot;350;31;381 +47001;Agen;33576;841;34417 +47002;Agmé;104;4;108 +47003;Agnac;422;7;429 +47004;Aiguillon;4387;141;4528 +47005;Allemans-du-Dropt;493;5;498 +47006;Allez-et-Cazeneuve;567;20;587 +47007;Allons;165;6;171 +47008;Ambrus;113;0;113 +47009;Andiran;222;8;230 +47010;Antagnac;231;3;234 +47011;Anthé;201;7;208 +47012;Anzex;313;2;315 +47013;Argenton;315;11;326 +47014;Armillac;198;7;205 +47015;Astaffort;2050;38;2088 +47016;Aubiac;1119;25;1144 +47017;Auradou;396;9;405 +47018;Auriac-sur-Dropt;177;6;183 +47019;Bajamont;978;19;997 +47020;Baleyssagues;176;5;181 +47021;Barbaste;1522;126;1648 +47022;Bazens;546;9;555 +47023;Beaugas;359;4;363 +47024;Beaupuy;1650;41;1691 +47025;Beauville;566;7;573 +47026;Beauziac;237;8;245 +47027;Bias;3031;66;3097 +47028;Birac-sur-Trec;843;18;861 +47029;Blanquefort-sur-Briolance;470;9;479 +47030;Blaymont;209;6;215 +47031;Boé;5593;92;5685 +47032;Bon-Encontre;6199;147;6346 +47033;Boudy-de-Beauregard;414;3;417 +47034;Bouglon;616;13;629 +47035;Bourgougnague;321;80;401 +47036;Bourlens;380;5;385 +47037;Bournel;246;4;250 +47038;Bourran;616;9;625 +47039;Boussès;37;0;37 +47040;Brax;2070;46;2116 +47041;Bruch;748;15;763 +47042;Brugnac;183;7;190 +47043;Buzet-sur-Baïse;1284;14;1298 +47044;Cahuzac;307;3;310 +47045;Calignac;478;5;483 +47046;Calonges;648;12;660 +47047;Cambes;180;5;185 +47048;Cancon;1340;20;1360 +47049;Casseneuil;2386;46;2432 +47050;Cassignas;125;1;126 +47051;Castelculier;2375;52;2427 +47052;Casteljaloux;4579;57;4636 +47053;Castella;367;7;374 +47054;Castelmoron-sur-Lot;1748;24;1772 +47056;Castelnau-sur-Gupie;890;32;922 +47055;Castelnaud-de-Gratecambe;508;7;515 +47057;Castillonnès;1417;21;1438 +47058;Caubeyres;253;1;254 +47059;Caubon-Saint-Sauveur;255;4;259 +47060;Caudecoste;1072;19;1091 +47061;Caumont-sur-Garonne;726;9;735 +47062;Cauzac;423;4;427 +47063;Cavarc;159;2;161 +47064;Cazideroque;230;7;237 +47065;Clairac;2622;194;2816 +47066;Clermont-Dessous;876;12;888 +47067;Clermont-Soubiran;382;8;390 +47068;Cocumont;1081;22;1103 +47069;Colayrac-Saint-Cirq;3074;48;3122 +47070;Condezaygues;854;24;878 +47071;Coulx;238;2;240 +47072;Courbiac;114;2;116 +47073;Cours;202;5;207 +47074;Couthures-sur-Garonne;339;2;341 +47075;La Croix-Blanche;1053;23;1076 +47076;Cuq;268;4;272 +47077;Cuzorn;849;17;866 +47078;Damazan;1354;46;1400 +47079;Dausse;510;18;528 +47080;Dévillac;133;3;136 +47081;Dolmayrac;712;15;727 +47082;Dondas;214;1;215 +47083;Doudrac;90;3;93 +47084;Douzains;269;5;274 +47085;Durance;293;3;296 +47086;Duras;1284;21;1305 +47087;Engayrac;169;3;172 +47088;Escassefort;600;9;609 +47089;Esclottes;151;2;153 +47090;Espiens;374;8;382 +47091;Estillac;2007;44;2051 +47092;Fals;378;4;382 +47093;Fargues-sur-Ourbise;344;9;353 +47094;Fauguerolles;790;8;798 +47095;Fauillet;848;16;864 +47096;Ferrensac;211;6;217 +47097;Feugarolles;993;21;1014 +47098;Fieux;351;9;360 +47099;Fongrave;625;16;641 +47100;Foulayronnes;5430;217;5647 +47101;Fourques-sur-Garonne;1318;28;1346 +47102;Francescas;747;11;758 +47103;Fréchou;229;4;233 +47104;Frégimont;259;4;263 +47105;Frespech;293;5;298 +47106;Fumel;4834;92;4926 +47107;Galapian;316;6;322 +47108;Gaujac;255;7;262 +47109;Gavaudun;284;5;289 +47110;Gontaud-de-Nogaret;1695;29;1724 +47111;Granges-sur-Lot;596;8;604 +47112;Grateloup-Saint-Gayrand;428;13;441 +47113;Grayssas;130;3;133 +47114;Grézet-Cavagnan;385;1;386 +47115;Guérin;249;7;256 +47117;Hautefage-la-Tour;993;17;1010 +47118;Hautesvignes;177;1;178 +47119;Houeillès;569;8;577 +47120;Jusix;116;3;119 +47121;Labastide-Castel-Amouroux;308;1;309 +47122;Labretonie;180;3;183 +47123;Lacapelle-Biron;423;5;428 +47124;Lacaussade;216;6;222 +47125;Lacépède;320;7;327 +47126;Lachapelle;84;1;85 +47127;Lafitte-sur-Lot;827;13;840 +47128;Lafox;1141;30;1171 +47129;Lagarrigue;276;6;282 +47130;Lagruère;324;6;330 +47131;Lagupie;713;15;728 +47132;Lalandusse;222;4;226 +47133;Lamontjoie;605;8;613 +47134;Lannes;369;9;378 +47135;Laparade;370;10;380 +47136;Laperche;127;4;131 +47137;Laplume;1390;33;1423 +47138;Laroque-Timbaut;1721;41;1762 +47139;Lasserre;76;3;79 +47140;Laugnac;667;15;682 +47141;Laussou;295;7;302 +47142;Lauzun;745;6;751 +47143;Lavardac;2260;60;2320 +47144;Lavergne;593;13;606 +47145;Layrac;3623;55;3678 +47146;Lédat;1398;36;1434 +47147;Lévignac-de-Guyenne;663;14;677 +47148;Leyritz-Moncassin;205;1;206 +47150;Longueville;366;7;373 +47151;Loubès-Bernac;415;3;418 +47152;Lougratte;402;10;412 +47154;Lusignan-Petit;362;4;366 +47155;Madaillan;651;15;666 +47156;Marcellus;863;8;871 +47157;Marmande;17691;589;18280 +47158;Marmont-Pachas;169;3;172 +47159;Le Mas-d'Agenais;1490;34;1524 +47160;Masquières;181;2;183 +47161;Massels;115;0;115 +47162;Massoulès;215;5;220 +47163;Mauvezin-sur-Gupie;593;8;601 +47164;Mazières-Naresse;127;4;131 +47165;Meilhan-sur-Garonne;1326;69;1395 +47167;Mézin;1554;27;1581 +47168;Miramont-de-Guyenne;3154;105;3259 +47169;Moirax;1156;41;1197 +47170;Monbahus;596;30;626 +47171;Monbalen;421;10;431 +47172;Moncaut;614;19;633 +47173;Monclar;871;13;884 +47174;Moncrabeau;733;18;751 +47175;Monflanquin;2313;55;2368 +47176;Mongaillard;180;7;187 +47177;Monheurt;192;3;195 +47178;Monségur;399;8;407 +47179;Monsempron-Libos;2091;29;2120 +47180;Montagnac-sur-Auvignon;615;14;629 +47181;Montagnac-sur-Lède;273;3;276 +47182;Montastruc;265;1;266 +47183;Montauriol;173;6;179 +47184;Montaut;251;3;254 +47185;Montayral;2680;66;2746 +47186;Montesquieu;783;12;795 +47187;Monteton;331;2;333 +47188;Montignac-de-Lauzun;286;4;290 +47189;Montignac-Toupinerie;149;0;149 +47190;Montpezat;559;46;605 +47191;Montpouillan;800;8;808 +47192;Monviel;79;1;80 +47193;Moulinet;198;4;202 +47194;Moustier;326;4;330 +47195;Nérac;6827;506;7333 +47196;Nicole;225;3;228 +47197;Nomdieu;255;8;263 +47198;Pailloles;339;6;345 +47199;Pardaillan;308;3;311 +47200;Parranquet;116;1;117 +47201;Le Passage;9561;171;9732 +47202;Paulhiac;308;7;315 +47203;Penne-d'Agenais;2346;49;2395 +47204;Peyrière;278;3;281 +47205;Pindères;209;8;217 +47206;Pinel-Hauterive;572;5;577 +47207;Pompiey;215;5;220 +47208;Pompogne;210;6;216 +47209;Pont-du-Casse;4212;121;4333 +47210;Port-Sainte-Marie;1931;32;1963 +47211;Poudenas;254;4;258 +47212;Poussignac;275;6;281 +47213;Prayssas;998;27;1025 +47214;Puch-d'Agenais;700;13;713 +47215;Pujols;3635;135;3770 +47216;Puymiclan;656;13;669 +47217;Puymirol;930;21;951 +47218;Puysserampion;245;4;249 +47219;Rayet;179;2;181 +47220;Razimet;305;6;311 +47221;Réaup-Lisse;606;18;624 +47222;La Réunion;488;9;497 +47223;Rives;221;8;229 +47224;Romestaing;166;6;172 +47225;Roquefort;1885;36;1921 +47226;Roumagne;542;10;552 +47227;Ruffiac;173;2;175 +47228;Saint-Antoine-de-Ficalba;722;11;733 +47229;Saint-Astier;222;5;227 +47230;Saint-Aubin;415;9;424 +47231;Saint-Avit;170;2;172 +47232;Saint-Barthélemy-d'Agenais;516;4;520 +47234;Saint-Caprais-de-Lerm;646;20;666 +47235;Saint-Colomb-de-Lauzun;478;4;482 +47239;Saint-Étienne-de-Fougères;829;13;842 +47240;Saint-Étienne-de-Villeréal;298;9;307 +47241;Saint-Eutrope-de-Born;680;18;698 +47242;Saint-Front-sur-Lémance;530;13;543 +47328;Saint-Georges;550;19;569 +47245;Saint-Géraud;95;2;97 +47246;Saint-Hilaire-de-Lusignan;1491;39;1530 +47247;Saint-Jean-de-Duras;245;9;254 +47248;Saint-Jean-de-Thurac;560;7;567 +47249;Saint-Laurent;525;4;529 +47250;Saint-Léger;133;4;137 +47251;Saint-Léon;322;5;327 +47254;Saint-Martin-Curton;313;8;321 +47255;Saint-Martin-de-Beauville;177;3;180 +47256;Saint-Martin-de-Villeréal;107;4;111 +47257;Saint-Martin-Petit;586;8;594 +47259;Saint-Maurice-de-Lestapel;106;4;110 +47260;Saint-Maurin;454;6;460 +47262;Saint-Nicolas-de-la-Balerme;408;4;412 +47263;Saint-Pardoux-du-Breuil;612;14;626 +47264;Saint-Pardoux-Isaac;1141;14;1155 +47265;Saint-Pastour;389;8;397 +47266;Saint-Pé-Saint-Simon;211;4;215 +47267;Saint-Pierre-de-Buzet;290;2;292 +47269;Saint-Pierre-de-Clairac;865;19;884 +47271;Saint-Pierre-sur-Dropt;338;3;341 +47272;Saint-Quentin-du-Dropt;195;7;202 +47273;Saint-Robert;184;6;190 +47274;Saint-Romain-le-Noble;418;6;424 +47275;Saint-Salvy;200;1;201 +47276;Saint-Sardos;295;7;302 +47277;Saint-Sauveur-de-Meilhan;333;1;334 +47278;Saint-Sernin;434;8;442 +47279;Saint-Sixte;358;5;363 +47280;Saint-Sylvestre-sur-Lot;2296;51;2347 +47281;Saint-Urcisse;236;1;237 +47282;Saint-Vincent-de-Lamontjoie;245;7;252 +47283;Saint-Vite;1170;25;1195 +47233;Sainte-Bazeille;3136;126;3262 +47236;Sainte-Colombe-de-Duras;105;1;106 +47237;Sainte-Colombe-de-Villeneuve;492;11;503 +47238;Sainte-Colombe-en-Bruilhois;1662;48;1710 +47244;Sainte-Gemme-Martaillac;411;5;416 +47252;Sainte-Livrade-sur-Lot;6459;177;6636 +47253;Sainte-Marthe;605;5;610 +47258;Sainte-Maure-de-Peyriac;332;11;343 +47284;Salles;293;7;300 +47285;Samazan;884;18;902 +47286;Sauméjan;107;0;107 +47287;Saumont;256;3;259 +47288;Sauvagnas;527;14;541 +47289;La Sauvetat-de-Savères;536;11;547 +47290;La Sauvetat-du-Dropt;535;10;545 +47291;La Sauvetat-sur-Lède;633;15;648 +47292;Sauveterre-la-Lémance;537;7;544 +47293;Sauveterre-Saint-Denis;387;17;404 +47294;Savignac-de-Duras;220;1;221 +47295;Savignac-sur-Leyze;302;6;308 +47296;Ségalas;156;5;161 +47297;Sembas;141;3;144 +47298;Sénestis;211;3;214 +47299;Sérignac-Péboudou;175;5;180 +47300;Sérignac-sur-Garonne;1172;21;1193 +47301;Seyches;1050;10;1060 +47302;Sos;664;7;671 +47303;Soumensac;231;9;240 +47304;Taillebourg;65;2;67 +47305;Tayrac;397;7;404 +47306;Le Temple-sur-Lot;1027;18;1045 +47307;Thézac;200;5;205 +47308;Thouars-sur-Garonne;218;3;221 +47309;Tombebœuf;460;4;464 +47310;Tonneins;9069;223;9292 +47311;Tourliac;135;7;142 +47312;Tournon-d'Agenais;761;13;774 +47313;Tourtrès;134;0;134 +47314;Trémons;392;10;402 +47315;Trentels;872;27;899 +47316;Varès;671;8;679 +47317;Verteuil-d'Agenais;607;11;618 +47318;Vianne;1016;15;1031 +47319;Villebramar;100;4;104 +47320;Villefranche-du-Queyran;390;1;391 +47321;Villeneuve-de-Duras;319;5;324 +47323;Villeneuve-sur-Lot;22064;705;22769 +47324;Villeréal;1279;40;1319 +47325;Villeton;456;6;462 +47326;Virazeil;1702;33;1735 +47327;Xaintrailles;418;3;421 +48001;Albaret-le-Comtal;174;5;179 +48002;Albaret-Sainte-Marie;568;24;592 +48003;Allenc;241;5;246 +48004;Altier;202;11;213 +48005;Antrenas;331;8;339 +48007;Arzenc-d'Apcher;50;0;50 +48008;Arzenc-de-Randon;200;8;208 +48010;Auroux;385;8;393 +48013;Badaroux;969;41;1010 +48016;Balsièges;549;19;568 +48017;Banassac-Canilhac;1044;33;1077 +48018;Barjac;751;17;768 +48019;Barre-des-Cévennes;202;7;209 +48020;Bassurels;61;0;61 +48021;La Bastide-Puylaurent;157;3;160 +48050;Bédouès-Cocurès;471;14;485 +48038;Bel-Air-Val-d'Ance;526;7;533 +48025;Les Bessons;440;28;468 +48026;Blavignac;258;1;259 +48028;Les Bondons;141;4;145 +48029;Le Born;147;0;147 +48099;Bourgs sur Colagne;2137;49;2186 +48030;Brenoux;382;9;391 +48031;Brion;79;1;80 +48032;Le Buisson;224;6;230 +48034;La Canourgue;2161;95;2256 +48166;Cans et Cévennes;284;11;295 +48036;Cassagnas;123;2;125 +48037;Chadenet;109;2;111 +48039;Chanac;1455;32;1487 +48041;Chastanier;78;0;78 +48042;Chastel-Nouvel;882;33;915 +48043;Châteauneuf-de-Randon;550;8;558 +48044;Chauchailles;90;2;92 +48045;Chaudeyrac;305;11;316 +48046;Chaulhac;70;1;71 +48048;Cheylard-l'Évêque;64;3;67 +48051;Le Collet-de-Dèze;748;48;796 +48053;Cubières;179;7;186 +48054;Cubiérettes;53;1;54 +48055;Cultures;165;4;169 +48056;Esclanèdes;392;9;401 +48058;La Fage-Montivernoux;155;5;160 +48059;La Fage-Saint-Julien;303;6;309 +48061;Florac Trois Rivières;2075;42;2117 +48063;Fontans;219;3;222 +48064;Fournels;367;8;375 +48065;Fraissinet-de-Fourques;79;0;79 +48067;Gabriac;100;3;103 +48068;Gabrias;152;5;157 +48069;Gatuzières;56;0;56 +48146;Gorges du Tarn Causses;953;31;984 +48070;Grandrieu;747;13;760 +48071;Grandvals;72;1;73 +48072;Grèzes;224;6;230 +48073;Les Hermaux;99;2;101 +48074;Hures-la-Parade;247;14;261 +48075;Ispagnac;890;20;910 +48077;Julianges;53;2;55 +48126;Lachamp-Ribennes;344;10;354 +48079;Lajo;106;3;109 +48080;Langogne;2891;194;3085 +48081;Lanuéjols;323;10;333 +48082;Laubert;97;4;101 +48083;Les Laubies;159;4;163 +48085;Laval-du-Tarn;96;4;100 +48086;Luc;216;5;221 +48088;La Malène;138;4;142 +48089;Le Malzieu-Forain;476;11;487 +48090;Le Malzieu-Ville;730;15;745 +48091;Marchastel;57;6;63 +48092;Marvejols;4722;241;4963 +48141;Mas-Saint-Chély;113;5;118 +48094;Massegros Causses Gorges;991;27;1018 +48095;Mende;12134;833;12967 +48096;Meyrueis;831;132;963 +48097;Moissac-Vallée-Française;218;9;227 +48098;Molezon;93;4;97 +48027;Mont Lozère et Goulet;1041;48;1089 +48100;Montbel;114;3;117 +48103;Montrodat;1236;79;1315 +48127;Monts-de-Randon;1301;20;1321 +48012;Les Monts-Verts;354;11;365 +48104;Nasbinals;528;29;557 +48105;Naussac-Fontanes;356;18;374 +48106;Noalhac;99;0;99 +48107;Palhers;182;7;189 +48108;La Panouse;77;2;79 +48110;Paulhac-en-Margeride;101;4;105 +48111;Pelouse;234;8;242 +48009;Peyre en Aubrac;2287;81;2368 +48015;Pied-de-Borne;180;12;192 +48112;Pierrefiche;163;5;168 +48115;Le Pompidou;160;7;167 +48116;Pont de Montvert - Sud Mont Lozère;584;24;608 +48117;Pourcharesses;120;2;122 +48119;Prévenchères;254;13;267 +48087;Prinsuéjols-Malbouzon;280;10;290 +48121;Prunières;256;17;273 +48123;Recoules-d'Aubrac;186;6;192 +48124;Recoules-de-Fumas;103;0;103 +48128;Rimeize;585;21;606 +48129;Rocles;233;6;239 +48130;Rousses;118;1;119 +48131;Le Rozier;132;6;138 +48132;Saint-Alban-sur-Limagnole;1349;31;1380 +48135;Saint-André-Capcèze;183;0;183 +48136;Saint-André-de-Lancize;134;2;136 +48137;Saint-Bauzile;621;25;646 +48138;Saint-Bonnet-de-Chirac;68;1;69 +48139;Saint Bonnet-Laval;253;2;255 +48140;Saint-Chély-d'Apcher;4164;582;4746 +48145;Saint-Denis-en-Margeride;171;7;178 +48147;Saint-Étienne-du-Valdonnez;647;40;687 +48148;Saint-Étienne-Vallée-Française;510;31;541 +48150;Saint-Flour-de-Mercoire;192;7;199 +48151;Saint-Frézal-d'Albuges;70;2;72 +48153;Saint-Gal;87;5;92 +48155;Saint-Germain-de-Calberte;448;6;454 +48156;Saint-Germain-du-Teil;889;12;901 +48158;Saint-Hilaire-de-Lavit;113;4;117 +48160;Saint-Jean-la-Fouillouse;158;7;165 +48161;Saint-Juéry;67;2;69 +48163;Saint-Julien-des-Points;109;1;110 +48165;Saint-Laurent-de-Muret;185;10;195 +48167;Saint-Laurent-de-Veyrès;37;1;38 +48168;Saint-Léger-de-Peyre;187;5;192 +48169;Saint-Léger-du-Malzieu;215;4;219 +48170;Saint-Martin-de-Boubaux;184;5;189 +48171;Saint-Martin-de-Lansuscle;188;5;193 +48173;Saint-Michel-de-Dèze;243;3;246 +48174;Saint-Paul-le-Froid;140;3;143 +48175;Saint-Pierre-de-Nogaret;180;5;185 +48176;Saint-Pierre-des-Tripiers;88;4;92 +48177;Saint-Pierre-le-Vieux;318;9;327 +48178;Saint-Privat-de-Vallongue;227;6;233 +48179;Saint-Privat-du-Fau;124;2;126 +48181;Saint-Saturnin;64;2;66 +48182;Saint-Sauveur-de-Ginestoux;57;2;59 +48144;Sainte-Croix-Vallée-Française;274;9;283 +48149;Sainte-Eulalie;37;2;39 +48157;Sainte-Hélène;101;4;105 +48187;Les Salces;97;1;98 +48185;Les Salelles;164;6;170 +48188;Serverette;257;5;262 +48190;Termes;210;8;218 +48191;La Tieule;91;3;94 +48192;Trélans;92;2;94 +48193;Vebron;204;1;205 +48152;Ventalon en Cévennes;237;6;243 +48194;Vialas;432;48;480 +48198;Villefort;548;12;560 +49002;Allonnes;3029;55;3084 +49007;Angers;152960;3077;156037 +49008;Angrie;949;13;962 +49009;Antoigné;465;4;469 +49010;Armaillé;314;5;319 +49011;Artannes-sur-Thouet;424;17;441 +49012;Aubigné-sur-Layon;366;11;377 +49015;Avrillé;13692;332;14024 +49017;Baracé;580;5;585 +49018;Baugé-en-Anjou;11892;250;12142 +49020;Beaucouzé;5156;100;5256 +49021;Beaufort-en-Anjou;7226;157;7383 +49022;Beaulieu-sur-Layon;1391;29;1420 +49023;Beaupréau-en-Mauges;23228;712;23940 +49026;Bécon-les-Granits;2803;114;2917 +49027;Bégrolles-en-Mauges;2068;40;2108 +49028;Béhuard;125;6;131 +49345;Bellevigne-en-Layon;5730;113;5843 +49060;Bellevigne-les-Châteaux;3520;81;3601 +49029;Blaison-Saint-Sulpice;1250;29;1279 +49030;Blou;994;21;1015 +49138;Les Bois d'Anjou;2653;56;2709 +49035;Bouchemaine;6774;138;6912 +49036;Bouillé-Ménard;750;20;770 +49038;Bourg-l'Évêque;251;4;255 +49041;Brain-sur-Allonnes;2003;32;2035 +49045;La Breille-les-Pins;602;13;615 +49048;Briollay;2967;39;3006 +49050;Brissac Loire Aubance;10807;278;11085 +49053;Brossay;364;4;368 +49054;Candé;2834;62;2896 +49055;Cantenay-Épinard;2303;36;2339 +49056;Carbay;260;6;266 +49057;Cernusson;354;6;360 +49058;Les Cerqueux;873;9;882 +49061;Challain-la-Potherie;808;19;827 +49063;Chalonnes-sur-Loire;6535;171;6706 +49064;Chambellay;403;10;413 +49068;Champtocé-sur-Loire;1868;30;1898 +49070;Chanteloup-les-Bois;700;10;710 +49076;La Chapelle-Saint-Laud;762;7;769 +49082;Chaudefonds-sur-Layon;952;15;967 +49089;Chazé-sur-Argos;1055;28;1083 +49090;Cheffes;974;12;986 +49092;Chemillé-en-Anjou;21392;590;21982 +49067;Chenillé-Champteussé;351;6;357 +49099;Cholet;53917;1870;55787 +49100;Cizay-la-Madeleine;464;4;468 +49102;Cléré-sur-Layon;341;6;347 +49107;Cornillé-les-Caves;470;16;486 +49109;Coron;1593;32;1625 +49110;Corzé;1841;15;1856 +49112;Le Coudray-Macouard;923;27;950 +49113;Courchamps;506;10;516 +49114;Courléon;147;4;151 +49120;Denée;1394;24;1418 +49121;Dénezé-sous-Doué;470;9;479 +49123;Distré;1713;57;1770 +49125;Doué-en-Anjou;11005;273;11278 +49127;Durtal;3387;72;3459 +49129;Écouflant;4159;55;4214 +49130;Écuillé;639;7;646 +49131;Épieds;761;13;774 +49367;Erdre-en-Anjou;5746;83;5829 +49132;Étriché;1549;17;1566 +49135;Feneu;2193;38;2231 +49140;Fontevraud-l'Abbaye;1536;26;1562 +49167;Les Garennes sur Loire;4508;121;4629 +49261;Gennes-Val-de-Loire;8724;165;8889 +49155;Grez-Neuville;1441;39;1480 +49080;Les Hauts-d'Anjou;8759;188;8947 +49174;Huillé-Lézigné;1322;18;1340 +49160;Ingrandes-Le Fresne sur Loire;2624;56;2680 +49161;La Jaille-Yvon;321;10;331 +49163;Jarzé Villages;2742;28;2770 +49170;Juvardeil;815;14;829 +49171;La Lande-Chasles;124;1;125 +49176;Le Lion-d'Angers;4924;72;4996 +49178;Loiré;864;28;892 +49307;Loire-Authion;15702;592;16294 +49180;Longué-Jumelles;6794;119;6913 +49200;Longuenée-en-Anjou;6331;168;6499 +49182;Louresse-Rochemenier;864;16;880 +49373;Lys-Haut-Layon;7880;186;8066 +49188;Marcé;841;14;855 +49244;Mauges-sur-Loire;18284;446;18730 +49192;Maulévrier;3176;77;3253 +49193;Le May-sur-Èvre;3805;70;3875 +49194;Mazé-Milon;5799;101;5900 +49195;Mazières-en-Mauges;1177;27;1204 +49201;La Ménitré;2072;34;2106 +49205;Miré;984;12;996 +49209;Montigné-lès-Rairies;423;3;426 +49211;Montilliers;1223;30;1253 +49215;Montreuil-Bellay;3822;249;4071 +49214;Montreuil-Juigné;7517;147;7664 +49216;Montreuil-sur-Loir;569;6;575 +49217;Montreuil-sur-Maine;759;11;770 +49218;Montrevault-sur-Èvre;15859;306;16165 +49219;Montsoreau;446;8;454 +49220;Morannes sur Sarthe-Daumeray;3664;55;3719 +49221;Mouliherne;849;23;872 +49222;Mozé-sur-Louet;1991;43;2034 +49223;Mûrs-Erigné;5522;98;5620 +49224;Neuillé;992;14;1006 +49228;Noyant-Villages;5633;170;5803 +49231;Nuaillé;1469;39;1508 +49248;Ombrée d'Anjou;8998;251;9249 +49069;Orée d'Anjou;16413;265;16678 +49235;Parnay;431;15;446 +49236;Passavant-sur-Layon;125;5;130 +49237;La Pellerine;139;2;141 +49240;La Plaine;1017;34;1051 +49241;Le Plessis-Grammoire;2381;57;2438 +49246;Les Ponts-de-Cé;12679;573;13252 +49247;La Possonnière;2437;41;2478 +49253;Le Puy-Notre-Dame;1192;21;1213 +49257;Les Rairies;1013;16;1029 +49377;Rives-du-Loir-en-Anjou;5560;90;5650 +49259;Rochefort-sur-Loire;2355;41;2396 +49260;La Romagne;1879;91;1970 +49262;Rou-Marson;664;9;673 +49266;Saint-Augustin-des-Bois;1218;28;1246 +49267;Saint-Barthélemy-d'Anjou;9195;238;9433 +49269;Saint-Christophe-du-Bois;2755;57;2812 +49271;Saint-Clément-de-la-Place;2131;27;2158 +49272;Saint-Clément-des-Levées;1106;20;1126 +49283;Saint-Georges-sur-Loire;3610;39;3649 +49284;Saint-Germain-des-Prés;1398;21;1419 +49288;Saint-Jean-de-la-Croix;229;6;235 +49291;Saint-Just-sur-Dive;389;5;394 +49294;Saint-Lambert-la-Potherie;2843;29;2872 +49298;Saint-Léger-de-Linières;3597;62;3659 +49299;Saint-Léger-sous-Cholet;2930;89;3019 +49302;Saint-Macaire-du-Bois;457;5;462 +49306;Saint-Martin-du-Fouilloux;1674;36;1710 +49308;Saint-Melaine-sur-Aubance;2063;56;2119 +49310;Saint-Paul-du-Bois;589;14;603 +49311;Saint-Philbert-du-Peuple;1309;27;1336 +49321;Saint-Sigismond;381;8;389 +49278;Sainte-Gemmes-sur-Loire;3406;261;3667 +49326;Sarrigné;817;19;836 +49328;Saumur;26734;967;27701 +49329;Savennières;1338;23;1361 +49330;Sceaux-d'Anjou;1195;14;1209 +49331;Segré-en-Anjou Bleu;17562;826;18388 +49332;La Séguinière;4150;78;4228 +49333;Seiches-sur-le-Loir;2978;42;3020 +49334;Sermaise;329;5;334 +49301;Sèvremoine;25414;569;25983 +49336;Somloire;889;16;905 +49338;Soulaines-sur-Aubance;1423;29;1452 +49339;Soulaire-et-Bourg;1495;31;1526 +49341;Souzay-Champigny;761;23;784 +49086;Terranjou;3967;83;4050 +49343;La Tessoualle;3198;71;3269 +49344;Thorigné-d'Anjou;1226;25;1251 +49347;Tiercé;4381;72;4453 +49352;Toutlemonde;1334;26;1360 +49353;Trélazé;14658;152;14810 +49355;Trémentines;3005;54;3059 +49003;Tuffalun;1772;38;1810 +49358;Turquant;576;14;590 +49359;Les Ulmes;579;15;594 +49183;Val d'Erdre-Auxence;4892;60;4952 +49292;Val-du-Layon;3402;51;3453 +49361;Varennes-sur-Loire;1839;40;1879 +49362;Varrains;1221;50;1271 +49364;Vaudelnay;1143;20;1163 +49368;Vernantes;1997;26;2023 +49369;Vernoil-le-Fourrier;1266;19;1285 +49370;Verrie;480;7;487 +49323;Verrières-en-Anjou;7153;292;7445 +49371;Vezins;1717;31;1748 +49374;Villebernier;1490;34;1524 +49378;Vivy;2582;36;2618 +49381;Yzernay;1841;30;1871 +50002;Agneaux;4027;509;4536 +50003;Agon-Coutainville;2791;95;2886 +50004;Airel;547;3;550 +50006;Amigny;147;5;152 +50008;Anctoville-sur-Boscq;450;26;476 +50013;Anneville-en-Saire;390;8;398 +50015;Annoville;672;11;683 +50016;Appeville;178;2;180 +50019;Aucey-la-Plaine;427;6;433 +50021;Audouville-la-Hubert;79;1;80 +50022;Aumeville-Lestre;114;3;117 +50023;Auvers;675;10;685 +50024;Auxais;174;3;177 +50025;Avranches;10155;556;10711 +50026;Azeville;85;1;86 +50027;Bacilly;935;25;960 +50028;La Baleine;91;1;92 +50029;Barenton;1172;65;1237 +50030;Barfleur;570;10;580 +50031;Barneville-Carteret;2231;57;2288 +50032;La Barre-de-Semilly;1000;39;1039 +50033;Baubigny;145;4;149 +50034;Baudre;539;18;557 +50036;Baupte;431;8;439 +50038;Beauchamps;408;11;419 +50039;Beaucoudray;132;3;135 +50040;Beauficel;135;6;141 +50042;Beauvoir;423;5;428 +50044;Belval;315;1;316 +50045;Benoîtville;617;23;640 +50046;Bérigny;425;6;431 +50048;Beslon;560;9;569 +50049;Besneville;665;15;680 +50050;Beuvrigny;138;0;138 +50052;Beuzeville-la-Bastille;144;2;146 +50054;Biéville;189;5;194 +50055;Biniville;114;2;116 +50058;Blainville-sur-Mer;1653;59;1712 +50059;Blosville;313;1;314 +50060;La Bloutière;428;8;436 +50062;Boisyvon;113;0;113 +50064;La Bonneville;186;7;193 +50069;Bourguenolles;344;12;356 +50546;Bourgvallées;3213;69;3282 +50070;Boutteville;73;5;78 +50072;Brainville;215;7;222 +50074;Brécey;2120;147;2267 +50076;Bréhal;3410;87;3497 +50077;Bretteville;1074;46;1120 +50078;Bretteville-sur-Ay;382;8;390 +50079;Breuville;422;6;428 +50081;Bréville-sur-Mer;778;29;807 +50082;Bricquebec-en-Cotentin;5899;154;6053 +50083;Bricquebosq;588;7;595 +50084;Bricqueville-la-Blouette;554;18;572 +50085;Bricqueville-sur-Mer;1212;40;1252 +50086;Brillevast;325;4;329 +50087;Brix;2131;52;2183 +50088;Brouains;136;2;138 +50090;Buais-Les-Monts;623;8;631 +50092;Cambernon;710;15;725 +50093;Cametours;423;6;429 +50094;Camprond;411;9;420 +50095;Canisy;1796;56;1852 +50096;Canteloup;208;8;216 +50097;Canville-la-Rocque;129;2;131 +50098;Carantilly;638;15;653 +50099;Carentan-les-Marais;10118;188;10306 +50101;Carneville;236;6;242 +50102;Carolles;744;19;763 +50105;Catteville;99;5;104 +50106;Cavigny;263;2;265 +50108;Céaux;422;14;436 +50109;Cérences;1819;40;1859 +50110;Cerisy-la-Forêt;1034;20;1054 +50111;Cerisy-la-Salle;1043;19;1062 +50112;La Chaise-Baudouin;471;8;479 +50117;Champeaux;360;12;372 +50118;Champrepus;337;7;344 +50120;Chanteloup;356;4;360 +50121;La Chapelle-Cécelin;248;4;252 +50124;La Chapelle-Urée;158;3;161 +50514;Chaulieu;295;1;296 +50126;Chavoy;128;7;135 +50129;Cherbourg-en-Cotentin;79200;2366;81566 +50130;Chérencé-le-Héron;409;6;415 +50135;Clitourps;208;3;211 +50137;La Colombe;631;14;645 +50138;Colomby;537;10;547 +50139;Condé-sur-Vire;4027;162;4189 +50143;Coudeville-sur-Mer;856;34;890 +50144;Coulouvray-Boisbenâtre;559;3;562 +50145;Courcy;596;13;609 +50146;Courtils;229;2;231 +50147;Coutances;8501;1204;9705 +50148;Couvains;507;4;511 +50149;Couville;1143;16;1159 +50150;Crasville;242;2;244 +50151;Créances;2137;29;2166 +50152;Les Cresnays;230;3;233 +50155;Crollon;302;8;310 +50156;Crosville-sur-Douve;63;0;63 +50158;Cuves;283;8;291 +50159;Dangy;672;15;687 +50161;Le Dézert;589;10;599 +50162;Digosville;1546;51;1597 +50164;Domjean;1038;28;1066 +50165;Donville-les-Bains;3166;90;3256 +50166;Doville;321;15;336 +50167;Dragey-Ronthon;824;18;842 +50168;Ducey-Les Chéris;2786;61;2847 +50169;Écausseville;102;1;103 +50172;Émondeville;352;11;363 +50174;Équilly;195;9;204 +50175;Éroudeville;222;9;231 +50176;L' Étang-Bertrand;341;14;355 +50177;Étienville;371;7;378 +50178;Fermanville;1281;23;1304 +50181;Feugères;333;8;341 +50182;La Feuillie;270;12;282 +50183;Fierville-les-Mines;339;6;345 +50184;Flamanville;1759;23;1782 +50185;Fleury;1035;24;1059 +50186;Flottemanville;196;7;203 +50188;Folligny;1089;28;1117 +50190;Fontenay-sur-Mer;178;3;181 +50192;Fourneaux;146;0;146 +50193;Le Fresne-Poret;216;2;218 +50194;Fresville;367;8;375 +50195;Gathemo;245;2;247 +50196;Gatteville-le-Phare;490;15;505 +50197;Gavray-sur-Sienne;1966;28;1994 +50198;Geffosses;440;5;445 +50199;Genêts;435;6;441 +50200;Ger;806;8;814 +50205;La Godefroy;275;7;282 +50207;Golleville;174;2;176 +50208;Gonfreville;151;2;153 +50209;Gonneville-Le Theil;1553;45;1598 +50210;Gorges;349;8;357 +50214;Gouvets;270;7;277 +50215;Gouville-sur-Mer;3173;84;3257 +50216;Graignes-Mesnil-Angot;802;104;906 +50217;Le Grand-Celland;586;10;596 +50391;Grandparigny;2682;88;2770 +50218;Granville;12580;665;13245 +50219;Gratot;656;12;668 +50221;Grimesnil;61;2;63 +50115;Le Grippon;370;11;381 +50222;Grosville;787;21;808 +50225;Le Guislain;135;1;136 +50041;La Hague;11634;364;11998 +50227;Le Ham;307;4;311 +50228;Hambye;1150;27;1177 +50229;Hamelin;92;1;93 +50230;Hardinvast;881;34;915 +50232;Hauteville-la-Guichard;469;18;487 +50231;Hauteville-sur-Mer;697;20;717 +50233;Hautteville-Bocage;155;5;160 +50236;La Haye;4006;118;4124 +50234;La Haye-Bellefond;83;0;83 +50235;La Haye-d'Ectot;257;5;262 +50237;La Haye-Pesnel;1330;26;1356 +50238;Héauville;468;6;474 +50240;Helleville;525;7;532 +50241;Hémevez;181;5;186 +50243;Heugueville-sur-Sienne;552;7;559 +50246;Hiesville;65;1;66 +50247;Hocquigny;184;5;189 +50251;Huberville;369;10;379 +50252;Hudimesnil;900;16;916 +50253;Huisnes-sur-Mer;185;9;194 +50256;Isigny-le-Buat;3319;83;3402 +50258;Joganville;109;3;112 +50259;Juilley;656;27;683 +50066;Jullouville;2312;71;2383 +50260;Juvigny les Vallées;1700;32;1732 +50261;Lamberville;174;1;175 +50262;La Lande-d'Airou;518;6;524 +50263;Lapenty;369;10;379 +50265;Laulne;189;2;191 +50266;Lengronne;423;10;433 +50267;Lessay;2245;39;2284 +50268;Lestre;248;5;253 +50269;Liesville-sur-Douve;204;6;210 +50270;Lieusaint;418;13;431 +50271;Lingeard;82;1;83 +50272;Lingreville;1011;21;1032 +50274;Les Loges-Marchis;992;158;1150 +50275;Les Loges-sur-Brécey;134;7;141 +50276;Lolif;566;19;585 +50277;Longueville;604;15;619 +50278;Le Loreur;275;6;281 +50279;Le Lorey;604;15;619 +50281;La Lucerne-d'Outremer;780;19;799 +50282;Le Luot;273;9;282 +50283;La Luzerne;76;1;77 +50285;Magneville;330;4;334 +50288;Marcey-les-Grèves;1284;29;1313 +50289;Marchésieux;716;12;728 +50290;Marcilly;328;10;338 +50291;Margueray;131;4;135 +50292;Marigny-Le-Lozon;2645;58;2703 +50294;Martinvast;1266;35;1301 +50295;Maupertuis;137;2;139 +50296;Maupertus-sur-Mer;220;9;229 +50297;La Meauffe;1040;30;1070 +50298;Méautis;656;12;668 +50299;Le Mesnil;219;7;226 +50300;Le Mesnil-Adelée;169;7;176 +50302;Le Mesnil-Amey;277;7;284 +50305;Le Mesnil-au-Val;728;18;746 +50304;Le Mesnil-Aubert;186;7;193 +50310;Le Mesnil-Eury;174;3;177 +50311;Le Mesnil-Garnier;228;8;236 +50312;Le Mesnil-Gilbert;136;3;139 +50317;Le Mesnil-Ozenne;268;3;271 +50321;Le Mesnil-Rouxelin;508;21;529 +50324;Le Mesnil-Véneron;123;2;125 +50326;Le Mesnil-Villeman;235;1;236 +50315;Le Mesnillard;260;7;267 +50327;La Meurdraquière;172;4;176 +50328;Millières;799;9;808 +50332;Les Moitiers-d'Allonne;690;15;705 +50353;Le Mont-Saint-Michel;30;0;30 +50334;Montabot;280;3;283 +50335;Montaigu-la-Brisette;510;15;525 +50336;Montaigu-les-Bois;226;3;229 +50338;Montbray;308;3;311 +50340;Montcuit;185;4;189 +50341;Montebourg;2096;102;2198 +50342;Montfarville;808;17;825 +50345;Monthuchon;680;32;712 +50347;Montjoie-Saint-Martin;243;4;247 +50349;Montmartin-sur-Mer;1337;45;1382 +50350;Montpinchon;529;9;538 +50351;Montrabot;85;2;87 +50352;Montreuil-sur-Lozon;330;7;337 +50273;Montsenelle;1407;20;1427 +50356;Moon-sur-Elle;842;12;854 +50357;Morigny;84;1;85 +50359;Mortain-Bocage;2942;266;3208 +50360;Morville;272;12;284 +50361;La Mouche;243;6;249 +50362;Moulines;291;5;296 +50363;Moyon Villages;1478;37;1515 +50364;Muneville-le-Bingard;693;8;701 +50365;Muneville-sur-Mer;475;11;486 +50368;Nay;70;2;72 +50369;Négreville;810;21;831 +50370;Néhou;626;11;637 +50371;Le Neufbourg;414;12;426 +50372;Neufmesnil;193;3;196 +50373;Neuville-au-Plain;90;4;94 +50374;Neuville-en-Beaumont;35;1;36 +50376;Nicorps;409;17;426 +50378;Notre-Dame-de-Cenilly;648;9;657 +50379;Notre-Dame-de-Livoye;147;3;150 +50382;Nouainville;603;17;620 +50384;Octeville-l'Avenel;218;3;221 +50387;Orglandes;371;0;371 +50388;Orval sur Sienne;1150;40;1190 +50389;Ouville;448;12;460 +50390;Ozeville;155;2;157 +50535;Le Parc;911;26;937 +50393;Percy-en-Normandie;2583;105;2688 +50394;Périers;2259;30;2289 +50395;La Pernelle;259;4;263 +50397;Perriers-en-Beauficel;216;3;219 +50398;Le Perron;207;2;209 +50399;Le Petit-Celland;189;4;193 +50400;Picauville;3278;39;3317 +50401;Pierreville;735;14;749 +50402;Les Pieux;3223;89;3312 +50403;Pirou;1438;36;1474 +50405;Le Plessis-Lastelle;236;8;244 +50407;Poilley;882;25;907 +50409;Pont-Hébert;1987;210;2197 +50408;Pontaubault;555;7;562 +50410;Pontorson;4342;78;4420 +50411;Ponts;655;16;671 +50412;Port-Bail-sur-Mer;2588;69;2657 +50413;Précey;550;6;556 +50417;Quettehou;1787;26;1813 +50419;Quettreville-sur-Sienne;3194;67;3261 +50420;Quibou;914;24;938 +50421;Quinéville;273;6;279 +50422;Raids;192;0;192 +50423;Rampan;204;6;210 +50425;Rauville-la-Bigot;1153;36;1189 +50426;Rauville-la-Place;376;6;382 +50428;Reffuveille;509;4;513 +50429;Regnéville-sur-Mer;736;34;770 +50430;Reigneville-Bocage;38;3;41 +50431;Remilly Les Marais;1103;13;1116 +50433;Réville;1038;16;1054 +50435;Rocheville;604;15;619 +50436;Romagny Fontenay;1318;44;1362 +50437;Roncey;804;11;815 +50442;Le Rozel;252;6;258 +50443;Sacey;516;10;526 +50444;Saint-Amand-Villages;2529;58;2587 +50445;Saint-André-de-Bohon;338;4;342 +50446;Saint-André-de-l'Épine;548;13;561 +50448;Saint-Aubin-de-Terregatte;683;15;698 +50447;Saint-Aubin-des-Préaux;438;13;451 +50450;Saint-Barthélemy;332;7;339 +50451;Saint-Brice;131;2;133 +50452;Saint-Brice-de-Landelles;687;23;710 +50454;Saint-Christophe-du-Foc;428;9;437 +50455;Saint-Clair-sur-l'Elle;953;20;973 +50456;Saint-Clément-Rancoudray;550;8;558 +50461;Saint-Cyr;181;12;193 +50462;Saint-Cyr-du-Bailleul;399;9;408 +50463;Saint-Denis-le-Gast;534;10;544 +50464;Saint-Denis-le-Vêtu;620;5;625 +50467;Saint-Floxel;491;13;504 +50468;Saint-Fromond;769;15;784 +50473;Saint-Georges-d'Elle;401;5;406 +50471;Saint-Georges-de-la-Rivière;278;11;289 +50472;Saint-Georges-de-Livoye;198;7;205 +50474;Saint-Georges-de-Rouelley;551;11;562 +50475;Saint-Georges-Montcocq;919;44;963 +50476;Saint-Germain-d'Elle;224;1;225 +50478;Saint-Germain-de-Tournebut;441;8;449 +50479;Saint-Germain-de-Varreville;113;4;117 +50480;Saint-Germain-le-Gaillard;748;22;770 +50481;Saint-Germain-sur-Ay;909;19;928 +50482;Saint-Germain-sur-Sèves;165;3;168 +50483;Saint-Gilles;923;35;958 +50484;Saint-Hilaire-du-Harcouët;6094;373;6467 +50486;Saint-Jacques-de-Néhou;608;11;619 +50487;Saint-James;4954;114;5068 +50492;Saint-Jean-d'Elle;2460;54;2514 +50488;Saint-Jean-de-Daye;629;6;635 +50489;Saint-Jean-de-la-Haize;521;14;535 +50490;Saint-Jean-de-la-Rivière;350;9;359 +50491;Saint-Jean-de-Savigny;446;6;452 +50493;Saint-Jean-des-Champs;1410;34;1444 +50495;Saint-Jean-du-Corail-des-Bois;71;5;76 +50496;Saint-Jean-le-Thomas;393;8;401 +50498;Saint-Joseph;792;28;820 +50499;Saint-Laurent-de-Cuves;483;7;490 +50500;Saint-Laurent-de-Terregatte;646;11;657 +50502;Saint-Lô;19116;883;19999 +50504;Saint-Louet-sur-Vire;205;1;206 +50505;Saint-Loup;708;36;744 +50506;Saint-Malo-de-la-Lande;479;5;484 +50507;Saint-Marcouf;341;6;347 +50510;Saint-Martin-d'Aubigny;595;4;599 +50511;Saint-Martin-d'Audouville;131;4;135 +50512;Saint-Martin-de-Bonfossé;529;9;538 +50513;Saint-Martin-de-Cenilly;182;3;185 +50517;Saint-Martin-de-Varreville;181;5;186 +50518;Saint-Martin-le-Bouillant;318;4;322 +50519;Saint-Martin-le-Gréard;515;7;522 +50521;Saint-Maur-des-Bois;151;4;155 +50522;Saint-Maurice-en-Cotentin;257;7;264 +50525;Saint-Michel-de-Montjoie;314;1;315 +50528;Saint-Nicolas-de-Pierrepont;306;12;318 +50529;Saint-Nicolas-des-Bois;86;2;88 +50531;Saint-Ovin;768;28;796 +50532;Saint-Pair-sur-Mer;4066;150;4216 +50533;Saint-Patrice-de-Claids;176;3;179 +50536;Saint-Pierre-d'Arthéglise;140;0;140 +50537;Saint-Pierre-de-Coutances;408;19;427 +50538;Saint-Pierre-de-Semilly;444;8;452 +50539;Saint-Pierre-Église;1803;25;1828 +50540;Saint-Pierre-Langers;601;19;620 +50541;Saint-Planchers;1350;39;1389 +50542;Saint-Pois;511;12;523 +50543;Saint-Quentin-sur-le-Homme;1296;30;1326 +50548;Saint-Sauveur-de-Pierrepont;128;2;130 +50549;Saint-Sauveur-la-Pommeraye;376;6;382 +50551;Saint-Sauveur-le-Vicomte;2132;41;2173 +50550;Saint-Sauveur-Villages;3588;147;3735 +50552;Saint-Sébastien-de-Raids;334;6;340 +50553;Saint-Senier-de-Beuvron;368;6;374 +50554;Saint-Senier-sous-Avranches;1417;88;1505 +50562;Saint-Vaast-la-Hougue;1730;33;1763 +50563;Saint-Vigor-des-Monts;285;9;294 +50453;Sainte-Cécile;816;19;835 +50457;Sainte-Colombe;210;5;215 +50469;Sainte-Geneviève;318;6;324 +50509;Sainte-Marie-du-Mont;720;17;737 +50523;Sainte-Mère-Église;3077;50;3127 +50556;Sainte-Suzanne-sur-Vire;685;10;695 +50565;Sartilly-Baie-Bocage;2812;56;2868 +50567;Saussemesnil;884;21;905 +50568;Saussey;467;15;482 +50569;Savigny;446;8;454 +50570;Savigny-le-Vieux;451;2;453 +50571;Sébeville;34;1;35 +50572;Sénoville;201;8;209 +50574;Servon;278;4;282 +50575;Sideville;744;13;757 +50576;Siouville-Hague;1033;34;1067 +50578;Sortosville;87;1;88 +50577;Sortosville-en-Beaumont;313;8;321 +50579;Sottevast;1385;29;1414 +50580;Sotteville;470;9;479 +50582;Sourdeval;3173;63;3236 +50584;Subligny;390;6;396 +50585;Surtainville;1180;28;1208 +50587;Taillepied;21;1;22 +50588;Tamerville;659;23;682 +50589;Tanis;293;12;305 +50590;Le Tanu;396;6;402 +50591;Le Teilleul;1683;28;1711 +50564;Terre-et-Marais;1295;28;1323 +50592;Tessy-Bocage;2357;50;2407 +50593;Teurthéville-Bocage;591;8;599 +50594;Teurthéville-Hague;1059;21;1080 +50239;Thèreval;1800;44;1844 +50596;Théville;330;12;342 +50597;Tirepied-sur-Sée;947;23;970 +50598;Tocqueville;278;5;283 +50599;Tollevast;1523;43;1566 +50601;Torigny-les-Villes;4352;56;4408 +50603;Tourville-sur-Sienne;785;24;809 +50604;Tréauville;735;13;748 +50606;Tribehou;533;5;538 +50607;La Trinité;395;6;401 +50609;Turqueville;138;3;141 +50610;Urville;210;6;216 +50612;Vains;722;67;789 +50616;Le Val-Saint-Père;2043;81;2124 +50613;Valcanville;416;10;426 +50615;Valognes;6803;267;7070 +50617;Varenguebec;323;2;325 +50618;Varouville;266;6;272 +50619;Le Vast;324;10;334 +50621;Vaudreville;73;0;73 +50624;La Vendelée;464;23;487 +50626;Ver;374;10;384 +50628;Vernix;158;4;162 +50629;Vesly;725;4;729 +50633;Le Vicel;121;0;121 +50142;Vicq-sur-Mer;1033;13;1046 +50634;Videcosville;81;1;82 +50637;Villebaudon;310;3;313 +50639;Villedieu-les-Poêles-Rouffigny;3878;82;3960 +50641;Villiers-Fossard;643;15;658 +50643;Virandeville;794;14;808 +50647;Yquelon;1091;42;1133 +50648;Yvetot-Bocage;1145;30;1175 +51001;Ablancourt;162;1;163 +51003;Aigny;275;5;280 +51004;Allemanche-Launay-et-Soyer;111;4;115 +51005;Allemant;164;3;167 +51006;Alliancelles;142;4;146 +51007;Ambonnay;970;25;995 +51008;Ambrières;226;11;237 +51009;Anglure;879;18;897 +51010;Angluzelles-et-Courcelles;146;4;150 +51012;Anthenay;70;1;71 +51013;Aougny;100;4;104 +51014;Arcis-le-Ponsart;313;9;322 +51015;Argers;117;1;118 +51016;Arrigny;244;4;248 +51017;Arzillières-Neuville;327;6;333 +51018;Athis;887;20;907 +51019;Aubérive;238;8;246 +51020;Aubilly;53;3;56 +51022;Aulnay-l'Aître;181;5;186 +51023;Aulnay-sur-Marne;259;6;265 +51025;Auménancourt;1048;8;1056 +51027;Auve;298;21;319 +51028;Avenay-Val-d'Or;1026;11;1037 +51029;Avize;1740;160;1900 +51030;Aÿ-Champagne;5592;92;5684 +51031;Baconnes;270;10;280 +51032;Bagneux;448;8;456 +51033;Le Baizil;253;3;256 +51034;Bannay;19;0;19 +51035;Bannes;273;3;276 +51036;Barbonne-Fayel;502;6;508 +51037;Baslieux-lès-Fismes;327;2;329 +51038;Baslieux-sous-Châtillon;191;6;197 +51039;Bassu;103;5;108 +51040;Bassuet;257;7;264 +51041;Baudement;110;5;115 +51042;Baye;410;8;418 +51043;Bazancourt;2212;26;2238 +51044;Beaumont-sur-Vesle;825;13;838 +51045;Beaunay;106;0;106 +51046;Beine-Nauroy;1010;15;1025 +51047;Belval-en-Argonne;47;3;50 +51048;Belval-sous-Châtillon;147;6;153 +51049;Bergères-lès-Vertus;615;4;619 +51050;Bergères-sous-Montmirail;123;2;125 +51051;Berméricourt;205;2;207 +51052;Berru;574;4;578 +51053;Berzieux;74;7;81 +51054;Bétheniville;1275;13;1288 +51055;Bétheny;6971;104;7075 +51056;Bethon;281;8;289 +51057;Bettancourt-la-Longue;78;2;80 +51058;Bezannes;2121;58;2179 +51059;Bignicourt-sur-Marne;343;12;355 +51060;Bignicourt-sur-Saulx;190;2;192 +51061;Billy-le-Grand;121;2;123 +51062;Binarville;99;3;102 +51063;Binson-et-Orquigny;169;2;171 +51065;Blacy;657;12;669 +51066;Blaise-sous-Arzillières;342;6;348 +51612;Blancs-Coteaux;3325;176;3501 +51068;Blesme;214;2;216 +51069;Bligny;122;1;123 +51070;Boissy-le-Repos;220;1;221 +51071;Bouchy-Saint-Genest;193;7;200 +51072;Bouilly;203;3;206 +51073;Bouleuse;212;3;215 +51074;Boult-sur-Suippe;1705;26;1731 +51075;Bourgogne-Fresne;1396;32;1428 +51076;Boursault;451;9;460 +51077;Bouvancourt;193;7;200 +51078;Bouy;567;13;580 +51079;Bouzy;921;25;946 +51080;Brandonvillers;184;1;185 +51081;Branscourt;309;5;314 +51083;Braux-Saint-Remy;86;1;87 +51082;Braux-Sainte-Cohière;96;6;102 +51084;Bréban;81;1;82 +51085;Le Breuil;387;4;391 +51086;Breuil-sur-Vesle;342;11;353 +51087;Breuvery-sur-Coole;217;8;225 +51088;Brimont;432;7;439 +51089;Brouillet;77;4;81 +51090;Broussy-le-Grand;312;12;324 +51091;Broussy-le-Petit;129;3;132 +51092;Broyes;361;4;365 +51093;Brugny-Vaudancourt;450;14;464 +51094;Brusson;184;7;191 +51095;Le Buisson;92;3;95 +51097;Bussy-le-Château;171;4;175 +51098;Bussy-le-Repos;135;4;139 +51099;Bussy-Lettrée;341;10;351 +51100;La Caure;103;2;105 +51101;Caurel;655;8;663 +51102;Cauroy-lès-Hermonville;491;8;499 +51103;La Celle-sous-Chantemerle;143;1;144 +51104;Cernay-en-Dormois;150;4;154 +51105;Cernay-lès-Reims;1426;23;1449 +51106;Cernon;128;5;133 +51107;Chaintrix-Bierges;329;3;332 +51108;Châlons-en-Champagne;44753;1244;45997 +51109;Châlons-sur-Vesle;192;2;194 +51110;Chaltrait;58;1;59 +51111;Chambrecy;148;8;156 +51112;Chamery;416;6;422 +51113;Champaubert;121;4;125 +51115;Champfleury;551;4;555 +51116;Champguyon;274;3;277 +51117;Champigneul-Champagne;314;5;319 +51118;Champigny;1493;22;1515 +51119;Champillon;505;8;513 +51120;Champlat-et-Boujacourt;165;0;165 +51121;Champvoisy;249;6;255 +51122;Changy;118;5;123 +51124;Chantemerle;44;5;49 +51125;Chapelaine;49;1;50 +51126;La Chapelle-Felcourt;50;4;54 +51127;La Chapelle-Lasson;85;2;87 +51128;La Chapelle-sous-Orbais;54;2;56 +51129;Charleville;238;9;247 +51130;Charmont;227;5;232 +51132;Les Charmontois;118;1;119 +51133;Le Châtelier;60;0;60 +51134;Châtelraould-Saint-Louvent;233;8;241 +51135;Châtillon-sur-Broué;77;0;77 +51136;Châtillon-sur-Marne;668;90;758 +51137;Châtillon-sur-Morin;217;3;220 +51138;Châtrices;34;2;36 +51139;Chaudefontaine;320;13;333 +51140;Chaumuzy;378;1;379 +51141;La Chaussée-sur-Marne;781;15;796 +51142;Chavot-Courcourt;343;11;354 +51143;Le Chemin;50;0;50 +51144;Cheminon;609;9;618 +51145;Chenay;227;6;233 +51146;Cheniers;107;4;111 +51147;La Cheppe;335;10;345 +51148;Cheppes-la-Prairie;177;1;178 +51149;Chepy;429;13;442 +51150;Cherville;81;1;82 +51151;Chichey;175;2;177 +51152;Chigny-les-Roses;556;14;570 +51153;Chouilly;1019;30;1049 +51154;Clamanges;206;10;216 +51155;Clesles;623;10;633 +51156;Cloyes-sur-Marne;129;1;130 +51157;Coizard-Joches;75;1;76 +51160;Compertrix;1490;47;1537 +51161;Condé-sur-Marne;805;16;821 +51162;Conflans-sur-Seine;641;7;648 +51163;Congy;262;2;264 +51164;Connantray-Vaurefroy;159;4;163 +51165;Connantre;1084;31;1115 +51166;Contault;66;2;68 +51167;Coole;145;1;146 +51168;Coolus;222;8;230 +51169;Corbeil;92;1;93 +51170;Corfélix;112;2;114 +51171;Cormicy;1476;26;1502 +51172;Cormontreuil;6524;90;6614 +51173;Cormoyeux;117;3;120 +51174;Corribert;60;0;60 +51175;Corrobert;205;7;212 +51176;Corroy;163;5;168 +51177;Coulommes-la-Montagne;208;4;212 +51178;Coupetz;78;2;80 +51179;Coupéville;161;1;162 +51181;Courcelles-Sapicourt;378;5;383 +51182;Courcemain;104;3;107 +51183;Courcy;1053;17;1070 +51184;Courdemanges;392;12;404 +51185;Courgivaux;328;10;338 +51186;Courjeonnet;46;0;46 +51187;Courlandon;288;4;292 +51188;Courmas;209;7;216 +51190;Courtagnon;63;0;63 +51191;Courtémont;61;1;62 +51192;Courthiézy;360;5;365 +51193;Courtisols;2425;94;2519 +51194;Courville;455;6;461 +51195;Couvrot;848;23;871 +51196;Cramant;894;13;907 +51197;La Croix-en-Champagne;78;2;80 +51198;Crugny;647;5;652 +51199;Cuchery;405;10;415 +51200;Cuis;386;13;399 +51201;Cuisles;133;4;137 +51202;Cumières;759;13;772 +51203;Cuperly;228;2;230 +51204;Damery;1438;26;1464 +51205;Dampierre-au-Temple;273;6;279 +51206;Dampierre-le-Château;106;2;108 +51208;Dampierre-sur-Moivre;113;2;115 +51210;Dizy;1524;37;1561 +51211;Dommartin-Dampierre;69;0;69 +51212;Dommartin-Lettrée;153;1;154 +51213;Dommartin-sous-Hans;57;2;59 +51214;Dommartin-Varimont;138;8;146 +51215;Dompremy;146;3;149 +51216;Dontrien;272;2;274 +51217;Dormans;2921;55;2976 +51219;Drosnay;216;1;217 +51220;Drouilly;135;1;136 +51222;Éclaires;96;4;100 +51223;Écollemont;53;0;53 +51224;Écriennes;174;2;176 +51225;Écueil;304;2;306 +51226;Écury-le-Repos;59;1;60 +51227;Écury-sur-Coole;501;14;515 +51228;Élise-Daucourt;96;0;96 +51229;Épense;124;6;130 +51230;Épernay;22671;449;23120 +51231;L' Épine;644;15;659 +51232;Époye;430;6;436 +51233;Escardes;78;3;81 +51234;Esclavolles-Lurey;589;19;608 +51236;Les Essarts-le-Vicomte;143;2;145 +51235;Les Essarts-lès-Sézanne;255;10;265 +51237;Esternay;1871;31;1902 +51238;Étoges;469;8;477 +51239;Étréchy;108;3;111 +51240;Étrepy;139;1;140 +51241;Euvy;83;1;84 +51242;Fagnières;4834;108;4942 +51243;Faux-Fresnay;318;8;326 +51244;Faux-Vésigneul;244;6;250 +51245;Faverolles-et-Coëmy;566;8;574 +51246;Favresse;224;6;230 +51248;Fère-Champenoise;2145;43;2188 +51247;Fèrebrianges;151;3;154 +51249;Festigny;399;5;404 +51250;Fismes;5487;49;5536 +51251;Flavigny;165;5;170 +51252;Fleury-la-Rivière;516;7;523 +51253;Florent-en-Argonne;235;5;240 +51254;Fontaine-Denis-Nuisy;234;1;235 +51255;Fontaine-en-Dormois;13;0;13 +51256;Fontaine-sur-Ay;343;8;351 +51258;La Forestière;217;14;231 +51259;Francheville;207;4;211 +51260;Le Fresne;77;0;77 +51262;Frignicourt;1876;38;1914 +51263;Fromentières;377;7;384 +51264;Le Gault-Soigny;529;15;544 +51265;Gaye;588;12;600 +51266;Germaine;514;15;529 +51267;Germigny;180;2;182 +51268;Germinon;174;4;178 +51269;Giffaumont-Champaubert;272;1;273 +51270;Gigny-Bussy;228;5;233 +51272;Givry-en-Argonne;448;5;453 +51273;Givry-lès-Loisy;72;4;76 +51274;Gizaucourt;115;3;118 +51275;Glannes;189;3;192 +51276;Gourgançon;149;7;156 +51278;Les Grandes-Loges;274;5;279 +51279;Granges-sur-Aube;184;1;185 +51280;Gratreuil;28;0;28 +51281;Grauves;619;13;632 +51282;Gueux;1687;51;1738 +51283;Hans;146;6;152 +51284;Haussignémont;286;1;287 +51285;Haussimont;140;5;145 +51286;Hauteville;241;8;249 +51287;Hautvillers;695;18;713 +51290;Heiltz-l'Évêque;301;5;306 +51288;Heiltz-le-Hutier;234;8;242 +51289;Heiltz-le-Maurupt;420;8;428 +51291;Hermonville;1417;31;1448 +51292;Herpont;136;5;141 +51293;Heutrégiville;444;6;450 +51294;Hourges;81;1;82 +51295;Huiron;302;2;304 +51296;Humbauville;79;1;80 +51298;Igny-Comblizy;412;3;415 +51300;Isle-sur-Marne;99;2;101 +51299;Isles-sur-Suippe;898;14;912 +51301;Isse;115;8;123 +51302;Les Istres-et-Bury;97;1;98 +51303;Jâlons;561;10;571 +51304;Janvilliers;167;4;171 +51305;Janvry;131;2;133 +51306;Joiselle;100;3;103 +51307;Jonchery-sur-Suippe;222;3;225 +51308;Jonchery-sur-Vesle;1860;50;1910 +51309;Jonquery;114;4;118 +51310;Jouy-lès-Reims;220;2;222 +51311;Jussecourt-Minecourt;208;2;210 +51312;Juvigny;925;28;953 +51313;Lachy;331;5;336 +51314;Lagery;217;3;220 +51315;Landricourt;148;2;150 +51316;Larzicourt;279;5;284 +51317;Laval-sur-Tourbe;58;0;58 +51318;Lavannes;592;16;608 +51319;Lenharrée;95;3;98 +51320;Leuvrigny;338;9;347 +51321;Lhéry;83;3;86 +51322;Lignon;127;0;127 +51323;Linthelles;108;6;114 +51324;Linthes;117;0;117 +51325;Lisse-en-Champagne;122;2;124 +51326;Livry-Louvercy;1102;14;1116 +51327;Loisy-en-Brie;200;2;202 +51328;Loisy-sur-Marne;1097;24;1121 +51329;Loivre;1283;17;1300 +51333;Ludes;640;7;647 +51334;Luxémont-et-Villotte;450;10;460 +51336;Maffrécourt;57;1;58 +51663;Magenta;1708;17;1725 +51337;Magneux;279;3;282 +51338;Mailly-Champagne;661;17;678 +51339;Mairy-sur-Marne;546;12;558 +51340;Maisons-en-Champagne;532;13;545 +51341;Malmy;33;2;35 +51342;Mancy;253;5;258 +51343;Marcilly-sur-Seine;639;15;654 +51344;Mardeuil;1501;22;1523 +51345;Mareuil-en-Brie;275;2;277 +51346;Mareuil-le-Port;1166;18;1184 +51348;Marfaux;123;1;124 +51349;Margerie-Hancourt;181;5;186 +51350;Margny;121;6;127 +51351;Marigny;107;1;108 +51352;Marolles;894;18;912 +51353;Marsangis;48;1;49 +51354;Marson;290;8;298 +51355;Massiges;49;0;49 +51356;Matignicourt-Goncourt;146;4;150 +51357;Matougues;591;15;606 +51358;Maurupt-le-Montois;582;10;592 +51359;Mécringes;204;3;207 +51360;Le Meix-Saint-Epoing;282;2;284 +51361;Le Meix-Tiercelin;175;1;176 +51362;Merfy;605;20;625 +51363;Merlaut;237;6;243 +51364;Méry-Prémecy;61;1;62 +51365;Les Mesneux;861;20;881 +51367;Le Mesnil-sur-Oger;1109;15;1124 +51368;Minaucourt-le-Mesnil-lès-Hurlus;50;3;53 +51370;Moiremont;199;10;209 +51371;Moivre;62;1;63 +51373;Moncetz-l'Abbaye;95;4;99 +51372;Moncetz-Longevas;535;9;544 +51374;Mondement-Montgivroux;29;0;29 +51382;Mont-sur-Courville;127;4;131 +51375;Montbré;278;4;282 +51377;Montépreux;45;0;45 +51376;Montgenost;154;3;157 +51378;Monthelon;353;6;359 +51379;Montigny-sur-Vesle;516;8;524 +51380;Montmirail;3598;50;3648 +51381;Montmort-Lucy;608;9;617 +51384;Morangis;389;7;396 +51386;Morsains;133;3;136 +51387;Moslins;308;3;311 +51388;Mourmelon-le-Grand;5085;47;5132 +51389;Mourmelon-le-Petit;813;13;826 +51390;Moussy;761;13;774 +51391;Muizon;2161;64;2225 +51392;Mutigny;188;5;193 +51369;Mœurs-Verdey;319;8;327 +51393;Nanteuil-la-Forêt;282;7;289 +51395;Nesle-la-Reposte;104;3;107 +51396;Nesle-le-Repons;150;3;153 +51399;La Neuville-au-Pont;546;11;557 +51397;La Neuville-aux-Bois;143;2;145 +51398;La Neuville-aux-Larris;170;2;172 +51402;Neuvy;255;7;262 +51403;Nogent-l'Abbesse;537;5;542 +51404;Noirlieu;106;6;112 +51406;Norrois;149;1;150 +51407;La Noue;407;5;412 +51409;Nuisement-sur-Coole;358;9;367 +51412;Ognes;63;2;65 +51413;Oiry;833;17;850 +51414;Olizy;160;5;165 +51415;Omey;211;0;211 +51416;Orbais-l'Abbaye;561;3;564 +51417;Orconte;384;5;389 +51418;Ormes;436;3;439 +51419;Outines;134;5;139 +51420;Outrepont;84;2;86 +51421;Oyes;86;3;89 +51422;Pargny-lès-Reims;462;10;472 +51423;Pargny-sur-Saulx;1855;21;1876 +51424;Passavant-en-Argonne;209;1;210 +51425;Passy-Grigny;380;14;394 +51426;Péas;67;3;70 +51428;Les Petites-Loges;482;7;489 +51429;Pévy;204;3;207 +51430;Pierre-Morains;91;2;93 +51431;Pierry;1181;26;1207 +51432;Pleurs;856;19;875 +51433;Plichancourt;244;3;247 +51434;Plivot;748;21;769 +51435;Pocancy;168;2;170 +51436;Pogny;916;18;934 +51437;Poilly;96;3;99 +51438;Poix;71;1;72 +51439;Pomacle;454;7;461 +51440;Pontfaverger-Moronvilliers;1753;18;1771 +51441;Ponthion;109;1;110 +51442;Possesse;159;0;159 +51443;Potangis;131;0;131 +51444;Pouillon;494;8;502 +51445;Pourcy;193;1;194 +51446;Pringy;417;8;425 +51447;Prosnes;490;2;492 +51448;Prouilly;560;4;564 +51449;Prunay;1032;26;1058 +51450;Puisieulx;415;8;423 +51451;Queudes;100;2;102 +51452;Rapsécourt;36;1;37 +51453;Recy;1031;30;1061 +51454;Reims;182460;3116;185576 +51455;Reims-la-Brûlée;228;3;231 +51456;Remicourt;57;1;58 +51457;Reuil;277;19;296 +51458;Reuves;71;0;71 +51459;Réveillon;106;1;107 +51460;Rieux;198;5;203 +51461;Rilly-la-Montagne;988;21;1009 +51463;Les Rivières-Henruel;180;3;183 +51464;Romain;315;18;333 +51465;Romery;157;2;159 +51466;Romigny;213;5;218 +51468;Rosnay;354;9;363 +51469;Rouffy;113;6;119 +51470;Rouvroy-Ripont;8;0;8 +51471;Sacy;371;3;374 +51472;Saint-Amand-sur-Fion;1024;17;1041 +51473;Saint-Bon;113;4;117 +51474;Saint-Brice-Courcelles;3522;51;3573 +51475;Saint-Chéron;60;3;63 +51476;Saint-Étienne-au-Temple;812;12;824 +51477;Saint-Étienne-sur-Suippe;316;4;320 +51478;Saint-Eulien;440;12;452 +51479;Saint-Euphraise-et-Clairizet;234;5;239 +51482;Saint-Germain-la-Ville;671;13;684 +51483;Saint-Gibrien;538;7;545 +51484;Saint-Gilles;293;4;297 +51485;Saint-Hilaire-au-Temple;342;6;348 +51486;Saint-Hilaire-le-Grand;363;4;367 +51487;Saint-Hilaire-le-Petit;339;7;346 +51488;Saint-Imoges;320;25;345 +51489;Saint-Jean-devant-Possesse;31;3;34 +51490;Saint-Jean-sur-Moivre;210;3;213 +51491;Saint-Jean-sur-Tourbe;92;3;95 +51492;Saint-Just-Sauvage;1461;39;1500 +51493;Saint-Léonard;106;3;109 +51495;Saint-Loup;87;1;88 +51496;Saint-Lumier-en-Champagne;263;5;268 +51497;Saint-Lumier-la-Populeuse;49;0;49 +51499;Saint-Mard-lès-Rouffy;163;7;170 +51498;Saint-Mard-sur-Auve;64;1;65 +51500;Saint-Mard-sur-le-Mont;118;0;118 +51502;Saint-Martin-aux-Champs;104;0;104 +51002;Saint-Martin-d'Ablois;1426;23;1449 +51503;Saint-Martin-l'Heureux;85;1;86 +51504;Saint-Martin-sur-le-Pré;797;32;829 +51505;Saint-Masmes;458;8;466 +51506;Saint-Memmie;5511;78;5589 +51508;Saint-Ouen-Domprot;205;6;211 +51509;Saint-Pierre;301;8;309 +51511;Saint-Quentin-le-Verger;121;2;123 +51510;Saint-Quentin-les-Marais;139;2;141 +51512;Saint-Quentin-sur-Coole;104;1;105 +51513;Saint-Remy-en-Bouzemont-Saint-Genest-et-Isson;518;6;524 +51514;Saint-Remy-sous-Broyes;105;2;107 +51515;Saint-Remy-sur-Bussy;343;8;351 +51516;Saint-Saturnin;59;0;59 +51517;Saint-Souplet-sur-Py;125;4;129 +51518;Saint-Thierry;627;23;650 +51519;Saint-Thomas-en-Argonne;40;2;42 +51520;Saint-Utin;79;1;80 +51521;Saint-Vrain;233;2;235 +51480;Sainte-Gemme;139;3;142 +51501;Sainte-Marie-à-Py;198;5;203 +51277;Sainte-Marie-du-Lac-Nuisement;268;2;270 +51507;Sainte-Menehould;4120;114;4234 +51522;Sapignicourt;410;4;414 +51523;Sarcy;254;4;258 +51524;Saron-sur-Aube;304;6;310 +51525;Sarry;2046;86;2132 +51526;Saudoy;369;10;379 +51527;Savigny-sur-Ardres;270;4;274 +51528;Scrupt;132;0;132 +51529;Selles;405;1;406 +51530;Sept-Saulx;615;11;626 +51531;Sermaize-les-Bains;1906;35;1941 +51532;Sermiers;561;14;575 +51533;Servon-Melzicourt;108;1;109 +51534;Serzy-et-Prin;207;4;211 +51535;Sézanne;4834;108;4942 +51536;Sillery;1724;37;1761 +51537;Sivry-Ante;182;5;187 +51538;Sogny-aux-Moulins;111;2;113 +51539;Sogny-en-l'Angle;62;0;62 +51542;Soizy-aux-Bois;184;1;185 +51543;Somme-Bionne;80;8;88 +51546;Somme-Suippe;475;164;639 +51547;Somme-Tourbe;143;3;146 +51548;Somme-Vesle;430;245;675 +51549;Somme-Yèvre;117;3;120 +51544;Sommepy-Tahure;623;16;639 +51545;Sommesous;533;14;547 +51550;Sompuis;291;12;303 +51551;Somsois;196;6;202 +51552;Songy;263;4;267 +51553;Souain-Perthes-lès-Hurlus;238;5;243 +51555;Soudé;183;0;183 +51556;Soudron;301;5;306 +51557;Soulanges;470;9;479 +51558;Soulières;142;1;143 +51559;Suippes;3913;47;3960 +51560;Suizy-le-Franc;107;3;110 +51562;Taissy;2199;36;2235 +51563;Talus-Saint-Prix;108;4;112 +51565;Thaas;99;0;99 +51566;Thibie;291;2;293 +51567;Thiéblemont-Farémont;541;6;547 +51568;Thil;296;4;300 +51569;Thillois;449;68;517 +51570;Le Thoult-Trosnay;103;2;105 +51572;Tilloy-et-Bellay;219;10;229 +51573;Tinqueux;10030;139;10169 +51574;Togny-aux-Bœufs;137;2;139 +51576;Tours-sur-Marne;1382;14;1396 +51577;Tramery;151;3;154 +51578;Trécon;82;1;83 +51579;Tréfols;168;3;171 +51580;Trépail;431;5;436 +51581;Treslon;242;1;243 +51582;Trigny;543;9;552 +51583;Trois-Fontaines-l'Abbaye;198;5;203 +51584;Trois-Puits;153;2;155 +51585;Troissy;829;93;922 +51586;Unchair;166;4;170 +51587;Vadenay;241;6;247 +51564;Val de Livre;633;17;650 +51571;Val-de-Vesle;912;10;922 +51218;Val-de-Vière;129;2;131 +51158;Val-des-Marais;567;11;578 +51588;Valmy;294;5;299 +51589;Vanault-le-Châtel;178;1;179 +51590;Vanault-les-Dames;363;8;371 +51591;Vandeuil;196;3;199 +51592;Vandières;307;6;313 +51594;Vassimont-et-Chapelaine;61;1;62 +51595;Vatry;158;2;160 +51596;Vauchamps;360;10;370 +51597;Vauciennes;332;7;339 +51598;Vauclerc;494;21;515 +51599;Vaudemange;309;5;314 +51600;Vaudesincourt;92;1;93 +51601;Vavray-le-Grand;161;3;164 +51602;Vavray-le-Petit;66;3;69 +51603;Vélye;196;2;198 +51604;Ventelay;259;6;265 +51605;Venteuil;529;10;539 +51607;Verdon;209;2;211 +51608;Vernancourt;88;4;92 +51609;Verneuil;840;20;860 +51610;Verrières;402;6;408 +51611;Vert-Toulon;291;4;295 +51613;Verzenay;1052;8;1060 +51614;Verzy;974;23;997 +51616;Vésigneul-sur-Marne;237;3;240 +51617;La Veuve;614;11;625 +51618;Le Vézier;191;3;194 +51619;Le Vieil-Dampierre;115;3;118 +51620;Vienne-la-Ville;173;7;180 +51621;Vienne-le-Château;520;7;527 +51622;Ville-Dommange;401;8;409 +51623;Ville-en-Selve;279;46;325 +51624;Ville-en-Tardenois;657;6;663 +51639;La Ville-sous-Orbais;49;1;50 +51640;Ville-sur-Tourbe;219;1;220 +51625;Villeneuve-la-Lionne;285;3;288 +51626;La Villeneuve-lès-Charleville;113;1;114 +51627;Villeneuve-Renneville-Chevigny;316;6;322 +51628;Villeneuve-Saint-Vistre-et-Villevotte;123;5;128 +51629;Villers-Allerand;885;18;903 +51630;Villers-aux-Bois;326;5;331 +51631;Villers-aux-Nœuds;188;4;192 +51632;Villers-en-Argonne;232;6;238 +51633;Villers-Franqueux;297;16;313 +51634;Villers-le-Château;254;8;262 +51635;Villers-le-Sec;117;1;118 +51636;Villers-Marmery;524;11;535 +51637;Villers-sous-Châtillon;215;0;215 +51638;Villeseneux;221;5;226 +51641;Villevenard;215;2;217 +51642;Villiers-aux-Corneilles;109;4;113 +51643;Vinay;589;5;594 +51644;Vincelles;290;3;293 +51645;Vindey;116;2;118 +51646;Virginy;84;3;87 +51647;Vitry-en-Perthois;828;24;852 +51648;Vitry-la-Ville;377;9;386 +51649;Vitry-le-François;12133;283;12416 +51650;Voilemont;44;5;49 +51652;Vouarces;60;0;60 +51654;Vouillers;258;6;264 +51655;Vouzy;293;5;298 +51656;Vraux;460;8;468 +51657;Vrigny;232;0;232 +51658;Vroil;104;0;104 +51659;Wargemoulin-Hurlus;46;1;47 +51660;Warmeriville;2468;26;2494 +51662;Witry-lès-Reims;5020;55;5075 +51410;Œuilly;648;10;658 +52001;Ageville;309;8;317 +52002;Aigremont;20;0;20 +52003;Aillianville;165;2;167 +52004;Aingoulaincourt;13;0;13 +52005;Aizanville;34;4;38 +52006;Allichamps;347;4;351 +52007;Ambonville;82;2;84 +52008;Andelot-Blancheville;870;10;880 +52009;Andilly-en-Bassigny;108;1;109 +52011;Annéville-la-Prairie;86;0;86 +52012;Annonville;32;1;33 +52013;Anrosey;121;5;126 +52014;Aprey;187;6;193 +52015;Arbigny-sous-Varennes;89;0;89 +52016;Arbot;70;2;72 +52017;Arc-en-Barrois;743;13;756 +52019;Arnancourt;91;4;95 +52021;Attancourt;260;4;264 +52022;Aubepierre-sur-Aube;188;3;191 +52023;Auberive;169;5;174 +52025;Audeloncourt;87;2;89 +52027;Aujeurres;83;2;85 +52028;Aulnoy-sur-Aube;51;0;51 +52029;Autigny-le-Grand;149;2;151 +52030;Autigny-le-Petit;63;2;65 +52031;Autreville-sur-la-Renne;382;9;391 +52033;Avrecourt;114;4;118 +52034;Bailly-aux-Forges;143;5;148 +52035;Baissey;193;3;196 +52037;Bannes;374;3;377 +52038;Bassoncourt;67;0;67 +52039;Baudrecourt;92;0;92 +52040;Bay-sur-Aube;52;1;53 +52265;Bayard-sur-Marne;1322;27;1349 +52042;Beauchemin;104;1;105 +52043;Belmont;57;1;58 +52045;Bettancourt-la-Ferrée;1697;37;1734 +52047;Beurville;104;0;104 +52050;Biesles;1352;31;1383 +52051;Bize;92;1;93 +52053;Blaisy;75;1;76 +52055;Blécourt;112;2;114 +52056;Blessonville;196;6;202 +52057;Blumeray;109;7;116 +52058;Bologne;1899;38;1937 +52059;Bonnecourt;135;0;135 +52060;Bourbonne-les-Bains;2073;54;2127 +52061;Bourdons-sur-Rognon;285;2;287 +52062;Bourg;156;5;161 +52063;Bourg-Sainte-Marie;101;1;102 +52064;Bourmont-entre-Meuse-et-Mouzon;803;30;833 +52065;Bouzancourt;65;1;66 +52066;Brachay;61;3;64 +52067;Brainville-sur-Meuse;78;0;78 +52069;Braux-le-Châtel;145;1;146 +52070;Brennes;133;3;136 +52072;Brethenay;368;10;378 +52074;Breuvannes-en-Bassigny;678;20;698 +52075;Briaucourt;181;6;187 +52076;Bricon;449;14;463 +52079;Brousseval;694;9;703 +52082;Bugnières;153;5;158 +52084;Busson;39;0;39 +52085;Buxières-lès-Clefmont;26;2;28 +52087;Buxières-lès-Villiers;195;20;215 +52088;Ceffonds;635;16;651 +52089;Celles-en-Bassigny;83;1;84 +52090;Celsoy;105;1;106 +52091;Cerisières;83;7;90 +52092;Chalancey;105;2;107 +52093;Chalindrey;2407;41;2448 +52095;Chalvraines;187;2;189 +52125;Chamarandes-Choignes;1034;172;1206 +52097;Chambroncourt;49;1;50 +52099;Chamouilley;806;10;816 +52101;Champigneulles-en-Bassigny;44;1;45 +52102;Champigny-lès-Langres;426;13;439 +52103;Champigny-sous-Varennes;115;2;117 +52083;Champsevraine;734;16;750 +52104;Chancenay;1087;27;1114 +52105;Changey;304;11;315 +52106;Chanoy;127;2;129 +52107;Chantraines;222;5;227 +52108;Charmes;146;4;150 +52109;Charmes-en-l'Angle;10;0;10 +52110;Charmes-la-Grande;156;6;162 +52113;Chassigny;253;2;255 +52114;Châteauvillain;1584;17;1601 +52400;Le Châtelet-sur-Meuse;150;0;150 +52115;Chatenay-Mâcheron;105;2;107 +52116;Chatenay-Vaudin;52;2;54 +52118;Chatonrupt-Sommermont;298;6;304 +52119;Chaudenay;345;7;352 +52120;Chauffourt;204;4;208 +52121;Chaumont;21945;1227;23172 +52122;Chaumont-la-Ville;116;1;117 +52123;Chevillon;1313;20;1333 +52124;Chézeaux;72;0;72 +52126;Choilley-Dardenay;162;4;166 +52127;Choiseul;78;4;82 +52128;Cirey-lès-Mareilles;140;3;143 +52129;Cirey-sur-Blaise;119;1;120 +52130;Cirfontaines-en-Azois;186;1;187 +52131;Cirfontaines-en-Ornois;77;1;78 +52132;Clefmont;176;3;179 +52133;Clinchamp;77;3;80 +52134;Cohons;233;5;238 +52135;Coiffy-le-Bas;92;0;92 +52136;Coiffy-le-Haut;116;0;116 +52137;Colmier-le-Bas;22;0;22 +52138;Colmier-le-Haut;59;1;60 +52140;Colombey les Deux Églises;714;22;736 +52141;Condes;304;6;310 +52142;Consigny;69;1;70 +52145;Coublanc;117;5;122 +52146;Coupray;146;2;148 +52151;Cour-l'Évêque;159;2;161 +52147;Courcelles-en-Montagne;90;0;90 +52149;Courcelles-sur-Blaise;98;1;99 +52155;Culmont;539;10;549 +52156;Curel;412;6;418 +52157;Curmont;12;1;13 +52158;Cusey;282;4;286 +52159;Cuves;25;1;26 +52160;Daillancourt;67;2;69 +52161;Daillecourt;74;0;74 +52162;Dammartin-sur-Meuse;198;2;200 +52163;Dampierre;387;4;391 +52164;Damrémont;197;4;201 +52165;Dancevoir;189;9;198 +52167;Darmannes;260;3;263 +52168;Dinteville;56;3;59 +52169;Domblain;80;2;82 +52170;Dommarien;161;7;168 +52171;Dommartin-le-Franc;248;2;250 +52172;Dommartin-le-Saint-Père;276;7;283 +52173;Domremy-Landéville;78;4;82 +52174;Doncourt-sur-Meuse;39;1;40 +52175;Donjeux;386;4;390 +52177;Doulaincourt-Saucourt;816;44;860 +52178;Doulevant-le-Château;363;13;376 +52179;Doulevant-le-Petit;26;3;29 +52181;Échenay;92;2;94 +52182;Éclaron-Braucourt-Sainte-Livière;2019;44;2063 +52183;Ecot-la-Combe;37;1;38 +52184;Effincourt;61;5;66 +52185;Enfonvelle;68;1;69 +52187;Épizon;168;4;172 +52190;Esnouveaux;296;5;301 +52193;Euffigneix;302;13;315 +52194;Eurville-Bienville;2065;32;2097 +52195;Farincourt;39;0;39 +52196;Faverolles;101;4;105 +52197;Fayl-Billot;1323;123;1446 +52198;Fays;73;3;76 +52199;Ferrière-et-Lafolie;50;2;52 +52200;Flagey;83;3;86 +52201;Flammerécourt;69;0;69 +52203;Fontaines-sur-Marne;148;2;150 +52204;Forcey;64;4;68 +52205;Foulain;697;17;714 +52206;Frampas;161;4;165 +52207;Frécourt;96;3;99 +52208;Fresnes-sur-Apance;148;2;150 +52211;Froncles;1521;24;1545 +52212;Fronville;323;3;326 +52213;Genevrières;132;5;137 +52214;La Genevroye;32;1;33 +52216;Germaines;41;1;42 +52217;Germainvilliers;89;4;93 +52218;Germay;45;2;47 +52219;Germisay;18;0;18 +52220;Giey-sur-Aujon;130;1;131 +52221;Gillancourt;120;3;123 +52222;Gillaumé;37;0;37 +52223;Gilley;67;3;70 +52227;Graffigny-Chemin;232;6;238 +52228;Grandchamp;74;1;75 +52229;Grenant;148;2;150 +52230;Gudmont-Villiers;291;5;296 +52231;Guindrecourt-aux-Ormes;93;2;95 +52232;Guindrecourt-sur-Blaise;59;0;59 +52233;Guyonvelle;107;1;108 +52234;Hâcourt;39;0;39 +52235;Hallignicourt;285;3;288 +52237;Harréville-les-Chanteurs;292;10;302 +52242;Haute-Amance;956;15;971 +52240;Heuilley-le-Grand;209;7;216 +52243;Huilliécourt;118;1;119 +52244;Humbécourt;780;10;790 +52245;Humberville;67;5;72 +52246;Humes-Jorquenay;570;15;585 +52247;Illoud;220;9;229 +52248;Is-en-Bassigny;542;13;555 +52249;Isômes;150;6;156 +52250;Joinville;3069;68;3137 +52251;Jonchery;1014;35;1049 +52253;Juzennecourt;213;3;216 +52254;Lachapelle-en-Blaisy;81;3;84 +52256;Lafauche;77;4;81 +52257;Laferté-sur-Amance;107;1;108 +52258;Laferté-sur-Aube;331;2;333 +52260;Lamancine;124;3;127 +52264;Laneuvelle;65;2;67 +52266;Laneuville-à-Rémy;66;0;66 +52267;Laneuville-au-Pont;209;3;212 +52269;Langres;7731;415;8146 +52271;Lanques-sur-Rognon;186;2;188 +52272;Lanty-sur-Aube;121;2;123 +52273;Larivière-Arnoncourt;117;1;118 +52274;Latrecey-Ormoy-sur-Aube;295;9;304 +52275;Lavernoy;76;0;76 +52276;Laville-aux-Bois;205;9;214 +52277;Lavilleneuve;60;1;61 +52278;Lavilleneuve-au-Roi;78;0;78 +52280;Lecey;210;3;213 +52282;Leffonds;349;9;358 +52284;Leschères-sur-le-Blaiseron;101;0;101 +52285;Leuchey;85;1;86 +52286;Leurville;84;0;84 +52287;Levécourt;87;1;88 +52288;Lezéville;125;0;125 +52289;Liffol-le-Petit;320;8;328 +52290;Les Loges;137;6;143 +52291;Longchamp;71;0;71 +52292;Longeau-Percey;743;19;762 +52294;Louvemont;701;10;711 +52295;Louvières;97;0;97 +52297;Luzy-sur-Marne;258;10;268 +52298;Maâtz;75;0;75 +52300;Magneux;167;2;169 +52301;Maisoncelles;58;1;59 +52302;Maizières;198;3;201 +52303;Maizières-sur-Amance;98;1;99 +52304;Malaincourt-sur-Meuse;57;1;58 +52305;Mandres-la-Côte;538;5;543 +52306;Manois;451;9;460 +52307;Marac;214;4;218 +52308;Maranville;410;4;414 +52310;Marbéville;98;2;100 +52311;Marcilly-en-Bassigny;218;4;222 +52312;Mardor;47;3;50 +52313;Mareilles;155;1;156 +52315;Marnay-sur-Marne;325;1;326 +52316;Mathons;65;2;67 +52318;Melay;258;6;264 +52319;Mennouveaux;70;1;71 +52320;Merrey;100;3;103 +52321;Mertrud;177;7;184 +52322;Meures;131;4;135 +52325;Millières;114;5;119 +52326;Mirbel;42;0;42 +52327;Moëslains;425;12;437 +52328;Montcharvot;33;1;34 +52330;Montheries;65;2;67 +52335;Montot-sur-Rognon;131;2;133 +52336;Montreuil-sur-Blaise;165;2;167 +52337;Montreuil-sur-Thonnance;62;0;62 +52405;Le Montsaugeonnais;1265;26;1291 +52341;Morancourt;134;2;136 +52342;Morionvilliers;29;0;29 +52344;Mouilleron;35;2;37 +52346;Mussey-sur-Marne;372;6;378 +52347;Narcy;247;5;252 +52348;Neuilly-l'Évêque;591;19;610 +52349;Neuilly-sur-Suize;311;9;320 +52350;Neuvelle-lès-Voisey;72;0;72 +52352;Ninville;79;5;84 +52353;Nogent;3752;63;3815 +52354;Noidant-Chatenoy;82;0;82 +52355;Noidant-le-Rocheux;160;4;164 +52356;Nomécourt;110;4;114 +52357;Noncourt-sur-le-Rongeant;176;2;178 +52358;Noyers;83;0;83 +52359;Nully;161;4;165 +52360;Occey;157;3;160 +52362;Orbigny-au-Mont;133;4;137 +52363;Orbigny-au-Val;96;7;103 +52364;Orcevaux;99;3;102 +52365;Orges;354;3;357 +52366;Ormancey;79;1;80 +52367;Ormoy-lès-Sexfontaines;43;1;44 +52369;Orquevaux;80;0;80 +52370;Osne-le-Val;257;6;263 +52371;Oudincourt;143;2;145 +52372;Outremécourt;90;6;96 +52373;Ozières;39;1;40 +52374;Le Pailly;284;5;289 +52375;Palaiseul;59;0;59 +52376;Pansey;97;3;100 +52377;Parnoy-en-Bassigny;299;8;307 +52378;Paroy-sur-Saulx;47;2;49 +52380;Peigney;376;2;378 +52383;Perrancey-les-Vieux-Moulins;293;7;300 +52384;Perrogney-les-Fontaines;114;0;114 +52385;Perrusse;31;2;33 +52386;Perthes;526;4;530 +52388;Pierremont-sur-Amance;143;0;143 +52390;Pisseloup;51;0;51 +52391;Planrupt;304;6;310 +52392;Plesnoy;115;2;117 +52393;Poinsenot;52;0;52 +52394;Poinson-lès-Fayl;222;9;231 +52395;Poinson-lès-Grancey;45;0;45 +52396;Poinson-lès-Nogent;143;3;146 +52397;Poiseul;71;1;72 +52398;Poissons;667;15;682 +52399;Pont-la-Ville;120;8;128 +52331;La Porte du Der;2278;65;2343 +52401;Poulangy;386;12;398 +52403;Praslay;74;1;75 +52406;Pressigny;200;5;205 +52407;Prez-sous-Lafauche;296;7;303 +52414;Rachecourt-sur-Marne;779;11;790 +52413;Rachecourt-Suzémont;105;2;107 +52416;Rangecourt;64;1;65 +52415;Rançonnières;106;1;107 +52419;Rennepont;136;5;141 +52420;Reynel;119;2;121 +52421;Riaucourt;473;9;482 +52422;Richebourg;274;5;279 +52423;Rimaucourt;671;8;679 +52411;Rives Dervoises;1371;53;1424 +52425;Rivière-les-Fosses;199;4;203 +52424;Rivières-le-Bois;73;0;73 +52426;Rizaucourt-Buchey;125;1;126 +52428;Rochefort-sur-la-Côte;64;1;65 +52044;Roches-Bettaincourt;570;13;583 +52429;Roches-sur-Marne;557;3;560 +52431;Rochetaillée;167;2;169 +52432;Rolampont;1478;30;1508 +52433;Romain-sur-Meuse;104;2;106 +52436;Rouécourt;47;3;50 +52437;Rouelles;25;0;25 +52438;Rougeux;110;2;112 +52439;Rouvres-sur-Aube;96;1;97 +52440;Rouvroy-sur-Marne;384;7;391 +52442;Rupt;338;6;344 +52443;Sailly;33;0;33 +52444;Saint-Blin;381;10;391 +52445;Saint-Broingt-le-Bois;71;2;73 +52446;Saint-Broingt-les-Fosses;232;4;236 +52447;Saint-Ciergues;189;2;191 +52448;Saint-Dizier;24012;558;24570 +52450;Saint-Loup-sur-Aujon;142;4;146 +52452;Saint-Martin-lès-Langres;111;4;115 +52453;Saint-Maurice;135;1;136 +52455;Saint-Thiébault;238;7;245 +52456;Saint-Urbain-Maconcourt;643;11;654 +52457;Saint-Vallier-sur-Marne;176;3;179 +52449;Saints-Geosmes;1129;33;1162 +52459;Sarcey;113;1;114 +52461;Sarrey;376;10;386 +52463;Saudron;46;1;47 +52464;Saulles;46;1;47 +52465;Saulxures;128;0;128 +52467;Savigny;59;2;61 +52468;Semilly;108;4;112 +52469;Semoutiers-Montsaon;769;15;784 +52470;Serqueux;413;13;426 +52472;Sexfontaines;133;0;133 +52473;Signéville;89;1;90 +52474;Silvarouvres;39;0;39 +52475;Sommancourt;68;1;69 +52476;Sommerécourt;78;4;82 +52479;Sommevoire;693;19;712 +52480;Soncourt-sur-Marne;371;8;379 +52482;Soulaucourt-sur-Mouzon;98;2;100 +52483;Soyers;62;1;63 +52484;Suzannecourt;370;14;384 +52486;Ternat;63;0;63 +52487;Thilleux;76;3;79 +52488;Thivet;272;0;272 +52489;Thol-lès-Millières;34;1;35 +52490;Thonnance-lès-Joinville;717;21;738 +52491;Thonnance-les-Moulins;114;5;119 +52492;Torcenay;551;15;566 +52493;Tornay;32;0;32 +52494;Treix;230;6;236 +52495;Trémilly;86;2;88 +52497;Troisfontaines-la-Ville;429;9;438 +52499;Vaillant;42;1;43 +52189;Le Val-d'Esnoms;389;11;400 +52332;Val-de-Meuse;1861;54;1915 +52500;Valcourt;621;9;630 +52502;Valleret;61;0;61 +52503;Valleroy;23;0;23 +52094;Vals-des-Tilles;167;1;168 +52504;Varennes-sur-Amance;269;4;273 +52505;Vaudrecourt;35;0;35 +52506;Vaudrémont;102;3;105 +52510;Vaux-sur-Blaise;376;7;383 +52511;Vaux-sur-Saint-Urbain;57;2;59 +52507;Vauxbons;60;0;60 +52512;Vecqueville;529;15;544 +52513;Velles;66;1;67 +52514;Verbiesles;332;10;342 +52515;Verseilles-le-Bas;102;4;106 +52516;Verseilles-le-Haut;48;1;49 +52517;Vesaignes-sous-Lafauche;128;1;129 +52518;Vesaignes-sur-Marne;104;2;106 +52519;Vesvres-sous-Chalancey;47;0;47 +52520;Vicq;151;6;157 +52522;Viéville;338;10;348 +52523;Vignes-la-Côte;64;4;68 +52524;Vignory;243;2;245 +52525;Villars-en-Azois;66;1;67 +52526;Villars-Santenoge;84;1;85 +52528;Ville-en-Blaisois;151;1;152 +52529;Villegusien-le-Lac;1002;17;1019 +52534;Villiers-en-Lieu;1529;33;1562 +52535;Villiers-le-Sec;711;11;722 +52536;Villiers-lès-Aprey;45;0;45 +52538;Villiers-sur-Suize;263;2;265 +52539;Violot;67;2;69 +52540;Vitry-en-Montagne;23;0;23 +52541;Vitry-lès-Nogent;186;4;190 +52542;Vivey;55;1;56 +52543;Voillecomte;532;10;542 +52544;Voisey;288;2;290 +52545;Voisines;101;2;103 +52546;Voncourt;16;0;16 +52547;Vouécourt;207;1;208 +52548;Vraincourt;92;2;94 +52549;Vroncourt-la-Côte;25;0;25 +52550;Wassy;2905;126;3031 +53001;Ahuillé;1806;35;1841 +53002;Alexain;601;9;610 +53003;Ambrières-les-Vallées;2739;70;2809 +53005;Andouillé;2300;49;2349 +53007;Argentré;2814;94;2908 +53008;Aron;1803;49;1852 +53009;Arquenay;638;17;655 +53010;Assé-le-Bérenger;450;13;463 +53011;Astillé;870;14;884 +53012;Athée;495;20;515 +53013;Averton;585;16;601 +53015;La Baconnière;1923;44;1967 +53016;Bais;1239;21;1260 +53018;Ballots;1281;31;1312 +53019;Bannes;120;3;123 +53021;La Bazoge-Montpinçon;1015;27;1042 +53022;La Bazouge-de-Chemeré;516;10;526 +53023;La Bazouge-des-Alleux;544;6;550 +53025;Bazougers;1106;13;1119 +53026;Beaulieu-sur-Oudon;519;9;528 +53027;Beaumont-Pied-de-Bœuf;190;3;193 +53028;Belgeard;616;8;624 +53029;Bierné-les-Villages;1249;28;1277 +53030;Le Bignon-du-Maine;336;8;344 +53031;La Bigottière;498;2;500 +53228;Blandouet-Saint Jean;605;19;624 +53033;La Boissière;117;5;122 +53034;Bonchamp-lès-Laval;6037;193;6230 +53035;Bouchamps-lès-Craon;564;9;573 +53036;Bouère;1090;20;1110 +53037;Bouessay;736;19;755 +53038;Boulay-les-Ifs;156;3;159 +53039;Le Bourgneuf-la-Forêt;1778;37;1815 +53040;Bourgon;640;10;650 +53041;Brains-sur-les-Marches;269;5;274 +53042;Brecé;824;13;837 +53043;Brée;535;6;541 +53045;La Brûlatte;697;18;715 +53046;Le Buret;309;3;312 +53047;Carelles;267;4;271 +53048;Chailland;1171;34;1205 +53049;Châlons-du-Maine;708;8;716 +53051;Champéon;585;6;591 +53052;Champfrémont;309;7;316 +53053;Champgenéteux;515;20;535 +53054;Changé;6020;191;6211 +53055;Chantrigné;618;21;639 +53056;La Chapelle-Anthenaise;1014;14;1028 +53057;La Chapelle-au-Riboul;501;10;511 +53058;La Chapelle-Craonnaise;352;8;360 +53059;La Chapelle-Rainsouin;412;6;418 +53061;Charchigné;481;6;487 +53062;Château-Gontier-sur-Mayenne;16776;648;17424 +53063;Châtelain;469;13;482 +53064;Châtillon-sur-Colmont;1024;25;1049 +53066;Chemazé;1361;32;1393 +53067;Chémeré-le-Roi;402;11;413 +53068;Chérancé;164;2;166 +53069;Chevaigné-du-Maine;173;7;180 +53071;Colombiers-du-Plessis;485;18;503 +53072;Commer;1201;26;1227 +53073;Congrier;896;25;921 +53074;Contest;840;33;873 +53075;Cosmes;282;7;289 +53076;Cossé-en-Champagne;323;10;333 +53077;Cossé-le-Vivien;3134;75;3209 +53078;Coudray;855;16;871 +53079;Couesmes-Vaucé;370;12;382 +53080;Couptrain;131;2;133 +53082;Courbeveille;640;5;645 +53083;Courcité;906;21;927 +53084;Craon;4507;178;4685 +53085;Crennes-sur-Fraubée;193;2;195 +53086;La Croixille;688;16;704 +53087;La Cropte;211;4;215 +53088;Cuillé;871;30;901 +53089;Daon;502;5;507 +53090;Denazé;162;5;167 +53091;Désertines;466;14;480 +53093;La Dorée;282;5;287 +53094;Entrammes;2256;42;2298 +53096;Ernée;5731;98;5829 +53097;Évron;8671;232;8903 +53098;Fontaine-Couverte;441;6;447 +53099;Forcé;1099;32;1131 +53100;Fougerolles-du-Plessis;1205;15;1220 +53101;Fromentières;831;11;842 +53102;Gastines;166;2;168 +53103;Le Genest-Saint-Isle;2135;57;2192 +53104;Gennes-Longuefuye;1327;24;1351 +53105;Gesnes;228;5;233 +53106;Gesvres;519;11;530 +53107;Gorron;2560;55;2615 +53108;La Gravelle;546;6;552 +53109;Grazay;615;18;633 +53110;Grez-en-Bouère;1011;19;1030 +53111;La Haie-Traversaine;472;13;485 +53112;Le Ham;395;8;403 +53113;Hambers;609;14;623 +53114;Hardanges;203;1;204 +53115;Hercé;312;12;324 +53116;Le Horps;744;20;764 +53117;Houssay;491;5;496 +53118;Le Housseau-Brétignolles;247;1;248 +53119;L' Huisserie;4244;153;4397 +53120;Izé;458;9;467 +53121;Javron-les-Chapelles;1378;29;1407 +53122;Jublains;734;16;750 +53123;Juvigné;1456;14;1470 +53125;Landivy;1149;22;1171 +53126;Larchamp;1110;17;1127 +53127;Lassay-les-Châteaux;2253;62;2315 +53128;Laubrières;356;4;360 +53129;Launay-Villiers;385;5;390 +53130;Laval;49728;2556;52284 +53131;Lesbois;194;2;196 +53132;Levaré;289;11;300 +53133;Lignières-Orgères;742;16;758 +53134;Livet;158;1;159 +53135;Livré-la-Touche;745;20;765 +53137;Loiron-Ruillé;2667;61;2728 +53139;Loupfougères;408;6;414 +53140;Louverné;4302;94;4396 +53141;Louvigné;1146;21;1167 +53142;Madré;293;6;299 +53143;Maisoncelles-du-Maine;517;10;527 +53144;Marcillé-la-Ville;798;24;822 +53145;Marigné-Peuton;548;14;562 +53146;Martigné-sur-Mayenne;1853;28;1881 +53147;Mayenne;12841;710;13551 +53148;Mée;226;1;227 +53150;Ménil;939;29;968 +53151;Méral;1098;15;1113 +53152;Meslay-du-Maine;2875;70;2945 +53153;Mézangers;657;13;670 +53154;Montaudin;908;15;923 +53155;Montenay;1361;24;1385 +53156;Montflours;253;8;261 +53157;Montigné-le-Brillant;1277;51;1328 +53158;Montjean;1036;20;1056 +53160;Montreuil-Poulay;371;11;382 +53161;Montsûrs;3227;61;3288 +53162;Moulay;963;17;980 +53163;Neau;774;3;777 +53164;Neuilly-le-Vendin;346;8;354 +53165;Niafles;350;7;357 +53168;Nuillé-sur-Vicoin;1210;26;1236 +53170;Oisseau;1184;25;1209 +53169;Olivet;417;10;427 +53172;Origné;423;5;428 +53173;La Pallu;193;6;199 +53174;Parigné-sur-Braye;847;18;865 +53175;Parné-sur-Roc;1348;29;1377 +53176;Le Pas;548;11;559 +53177;La Pellerine;340;5;345 +53178;Peuton;227;10;237 +53179;Placé;340;8;348 +53180;Pommerieux;652;28;680 +53181;Pontmain;825;13;838 +53182;Port-Brillet;1801;28;1829 +53185;Pré-en-Pail-Saint-Samson;2331;78;2409 +53184;Préaux;166;7;173 +53124;Prée-d'Anjou;1421;45;1466 +53186;Quelaines-Saint-Gault;2157;65;2222 +53187;Ravigny;233;12;245 +53188;Renazé;2541;33;2574 +53189;Rennes-en-Grenouilles;107;2;109 +53190;Le Ribay;460;10;470 +53136;La Roche-Neuville;1167;38;1205 +53191;La Roë;245;2;247 +53192;La Rouaudière;328;4;332 +53193;Ruillé-Froid-Fonds;569;12;581 +53195;Sacé;499;8;507 +53196;Saint-Aignan-de-Couptrain;374;10;384 +53197;Saint-Aignan-sur-Roë;894;24;918 +53198;Saint-Aubin-du-Désert;240;7;247 +53199;Saint-Aubin-Fosse-Louvain;217;6;223 +53200;Saint-Baudelle;1119;43;1162 +53201;Saint-Berthevin;7344;241;7585 +53202;Saint-Berthevin-la-Tannière;332;3;335 +53203;Saint-Brice;528;13;541 +53204;Saint-Calais-du-Désert;387;7;394 +53206;Saint-Charles-la-Forêt;203;10;213 +53208;Saint-Cyr-en-Pail;490;17;507 +53209;Saint-Cyr-le-Gravelais;544;14;558 +53210;Saint-Denis-d'Anjou;1558;29;1587 +53211;Saint-Denis-de-Gastines;1509;35;1544 +53212;Saint-Denis-du-Maine;428;9;437 +53213;Saint-Ellier-du-Maine;510;8;518 +53214;Saint-Erblon;172;4;176 +53216;Saint-Fraimbault-de-Prières;1001;26;1027 +53219;Saint-Georges-Buttavent;1443;39;1482 +53220;Saint-Georges-le-Fléchard;418;12;430 +53221;Saint-Georges-sur-Erve;385;10;395 +53222;Saint-Germain-d'Anxure;388;9;397 +53223;Saint-Germain-de-Coulamer;348;11;359 +53224;Saint-Germain-le-Fouilloux;1166;31;1197 +53225;Saint-Germain-le-Guillaume;495;10;505 +53226;Saint-Hilaire-du-Maine;863;24;887 +53229;Saint-Jean-sur-Mayenne;1653;49;1702 +53230;Saint-Julien-du-Terroux;235;9;244 +53232;Saint-Léger;308;3;311 +53233;Saint-Loup-du-Dorat;364;2;366 +53234;Saint-Loup-du-Gast;365;13;378 +53236;Saint-Mars-du-Désert;166;1;167 +53237;Saint-Mars-sur-Colmont;469;13;482 +53238;Saint-Mars-sur-la-Futaie;538;10;548 +53239;Saint-Martin-de-Connée;421;8;429 +53240;Saint-Martin-du-Limet;444;6;450 +53242;Saint-Michel-de-la-Roë;265;9;274 +53243;Saint-Ouën-des-Toits;1749;35;1784 +53245;Saint-Pierre-des-Landes;928;27;955 +53246;Saint-Pierre-des-Nids;1990;27;2017 +53247;Saint-Pierre-la-Cour;2170;43;2213 +53248;Saint-Pierre-sur-Erve;142;1;143 +53249;Saint-Pierre-sur-Orthe;463;10;473 +53250;Saint-Poix;405;6;411 +53251;Saint-Quentin-les-Anges;435;7;442 +53253;Saint-Saturnin-du-Limet;508;13;521 +53256;Saint-Thomas-de-Courceriers;185;4;189 +53218;Sainte-Gemmes-le-Robert;851;27;878 +53235;Sainte-Marie-du-Bois;217;4;221 +53255;Sainte-Suzanne-et-Chammes;1280;31;1311 +53257;Saulges;318;4;322 +53258;La Selle-Craonnaise;941;29;970 +53259;Senonnes;357;8;365 +53260;Simplé;452;4;456 +53261;Soucé;164;3;167 +53262;Soulgé-sur-Ouette;1084;31;1115 +53264;Thorigné-en-Charnie;195;3;198 +53263;Thubœuf;289;8;297 +53265;Torcé-Viviers-en-Charnie;756;15;771 +53266;Trans;232;4;236 +53267;Vaiges;1167;13;1180 +53017;Val-du-Maine;929;28;957 +53269;Vautorte;599;5;604 +53270;Vieuvy;118;8;126 +53271;Villaines-la-Juhel;2808;43;2851 +53272;Villepail;177;1;178 +53273;Villiers-Charlemagne;1122;23;1145 +53274;Vimarcé;237;1;238 +53276;Voutré;910;14;924 +54001;Abaucourt;299;4;303 +54002;Abbéville-lès-Conflans;226;4;230 +54003;Aboncourt;103;2;105 +54004;Affléville;179;2;181 +54005;Affracourt;110;1;111 +54006;Agincourt;438;7;445 +54007;Aingeray;543;4;547 +54008;Allain;478;14;492 +54009;Allamont;158;3;161 +54010;Allamps;510;14;524 +54011;Allondrelle-la-Malmaison;644;2;646 +54012;Amance;340;5;345 +54013;Amenoncourt;77;3;80 +54014;Ancerviller;282;15;297 +54015;Anderny;254;6;260 +54016;Andilly;286;7;293 +54017;Angomont;78;1;79 +54018;Anoux;265;8;273 +54019;Ansauville;82;1;83 +54020;Anthelupt;461;5;466 +54021;Armaucourt;225;2;227 +54022;Arnaville;565;7;572 +54023;Arracourt;246;2;248 +54024;Arraye-et-Han;359;7;366 +54025;Art-sur-Meurthe;1470;243;1713 +54026;Athienville;176;3;179 +54027;Atton;832;12;844 +54028;Auboué;2514;29;2543 +54029;Audun-le-Roman;2462;50;2512 +54030;Autrepierre;82;0;82 +54031;Autreville-sur-Moselle;277;5;282 +54032;Autrey;186;2;188 +54033;Avillers;123;0;123 +54034;Avrainville;219;10;229 +54035;Avricourt;386;3;389 +54036;Avril;1131;15;1146 +54037;Azelot;422;2;424 +54038;Azerailles;771;18;789 +54039;Baccarat;4330;62;4392 +54040;Badonviller;1551;31;1582 +54041;Bagneux;160;5;165 +54042;Bainville-aux-Miroirs;305;1;306 +54043;Bainville-sur-Madon;1396;13;1409 +54044;Barbas;191;2;193 +54045;Barbonville;437;7;444 +54046;Barisey-au-Plain;399;7;406 +54047;Barisey-la-Côte;226;3;229 +54048;Les Baroches;351;14;365 +54049;Baslieux;581;15;596 +54050;Bathelémont;64;1;65 +54051;Batilly;1261;19;1280 +54052;Battigny;142;2;144 +54053;Bauzemont;154;6;160 +54054;Bayon;1610;16;1626 +54055;Bayonville-sur-Mad;301;5;306 +54056;Bazailles;142;2;144 +54057;Beaumont;72;0;72 +54058;Béchamps;86;2;88 +54059;Belleau;746;9;755 +54060;Belleville;1441;17;1458 +54061;Bénaménil;583;11;594 +54062;Benney;650;11;661 +54063;Bernécourt;179;5;184 +54064;Bertrambois;308;6;314 +54065;Bertrichamps;1094;23;1117 +54066;Bettainvillers;391;2;393 +54067;Beuveille;760;11;771 +54068;Beuvezin;96;2;98 +54069;Beuvillers;424;8;432 +54070;Bey-sur-Seille;169;0;169 +54071;Bezange-la-Grande;158;1;159 +54072;Bezaumont;263;5;268 +54073;Bicqueley;902;16;918 +54074;Bienville-la-Petite;34;0;34 +54075;Bionville;116;4;120 +54076;Blainville-sur-l'Eau;4035;24;4059 +54077;Blâmont;1072;12;1084 +54078;Blémerey;63;1;64 +54079;Blénod-lès-Pont-à-Mousson;4601;47;4648 +54080;Blénod-lès-Toul;1078;20;1098 +54557;Bois-de-Haye;2257;102;2359 +54081;Boismont;415;6;421 +54082;Boncourt;174;3;177 +54083;Bonviller;183;3;186 +54085;Borville;97;2;99 +54086;Boucq;356;11;367 +54087;Bouillonville;156;3;159 +54088;Bouvron;241;1;242 +54089;Bouxières-aux-Chênes;1422;20;1442 +54090;Bouxières-aux-Dames;4216;39;4255 +54091;Bouxières-sous-Froidmont;369;4;373 +54092;Bouzanville;62;0;62 +54093;Brainville;160;2;162 +54094;Bralleville;174;3;177 +54095;Bratte;44;0;44 +54096;Bréhain-la-Ville;412;5;417 +54097;Bréménil;109;5;114 +54098;Brémoncourt;167;3;170 +54100;Brin-sur-Seille;783;11;794 +54101;Brouville;132;1;133 +54102;Bruley;610;6;616 +54103;Bruville;226;5;231 +54104;Buissoncourt;265;2;267 +54105;Bulligny;531;15;546 +54106;Bures;62;2;64 +54107;Buriville;74;3;77 +54108;Burthecourt-aux-Chênes;113;3;116 +54109;Ceintrey;925;9;934 +54110;Cerville;566;12;578 +54111;Chaligny;2858;23;2881 +54112;Chambley-Bussières;695;9;704 +54113;Champenoux;1415;16;1431 +54114;Champey-sur-Moselle;343;4;347 +54115;Champigneulles;6745;70;6815 +54116;Chanteheux;2143;42;2185 +54117;Chaouilley;112;1;113 +54118;Charency-Vezin;616;9;625 +54119;Charey;82;3;85 +54120;Charmes-la-Côte;335;8;343 +54121;Charmois;190;1;191 +54122;Chaudeney-sur-Moselle;709;17;726 +54123;Chavigny;1843;14;1857 +54124;Chazelles-sur-Albe;44;0;44 +54125;Chenevières;495;9;504 +54126;Chenicourt;227;1;228 +54127;Chenières;632;17;649 +54128;Choloy-Ménillot;736;10;746 +54129;Cirey-sur-Vezouze;1644;26;1670 +54130;Clayeures;187;1;188 +54131;Clémery;495;14;509 +54132;Clérey-sur-Brenon;67;2;69 +54133;Coincourt;128;4;132 +54134;Colmey;250;7;257 +54135;Colombey-les-Belles;1459;21;1480 +54136;Conflans-en-Jarnisy;2359;34;2393 +54137;Cons-la-Grandville;523;17;540 +54138;Cosnes-et-Romain;2690;55;2745 +54139;Courbesseaux;337;3;340 +54140;Courcelles;104;3;107 +54141;Coyviller;141;1;142 +54142;Crantenoy;152;2;154 +54143;Crépey;394;7;401 +54144;Crévéchamps;393;2;395 +54145;Crévic;913;12;925 +54146;Crézilles;282;3;285 +54147;Crion;96;0;96 +54148;Croismare;640;8;648 +54149;Crusnes;1579;12;1591 +54150;Custines;3079;26;3105 +54151;Cutry;1033;28;1061 +54152;Damelevières;3217;44;3261 +54153;Dampvitoux;58;0;58 +54154;Deneuvre;522;15;537 +54155;Deuxville;423;7;430 +54156;Diarville;539;5;544 +54157;Dieulouard;4763;44;4807 +54158;Dolcourt;129;2;131 +54159;Dombasle-sur-Meurthe;9734;192;9926 +54160;Domèvre-en-Haye;385;9;394 +54161;Domèvre-sur-Vezouze;296;10;306 +54162;Domgermain;1185;13;1198 +54163;Domjevin;256;2;258 +54164;Dommarie-Eulmont;87;2;89 +54165;Dommartemont;585;28;613 +54166;Dommartin-la-Chaussée;34;2;36 +54167;Dommartin-lès-Toul;1984;39;2023 +54168;Dommartin-sous-Amance;278;2;280 +54169;Domprix;87;3;90 +54170;Domptail-en-l'Air;71;1;72 +54171;Doncourt-lès-Conflans;1185;21;1206 +54172;Doncourt-lès-Longuyon;298;7;305 +54173;Drouville;205;4;209 +54174;Écrouves;4376;52;4428 +54175;Einvaux;363;3;366 +54176;Einville-au-Jard;1183;23;1206 +54177;Emberménil;260;3;263 +54178;Épiez-sur-Chiers;185;3;188 +54179;Éply;300;8;308 +54180;Erbéviller-sur-Amezule;76;2;78 +54181;Errouville;724;17;741 +54182;Essey-et-Maizerais;360;11;371 +54183;Essey-la-Côte;81;0;81 +54184;Essey-lès-Nancy;8823;160;8983 +54185;Étreval;61;1;62 +54186;Eulmont;1080;20;1100 +54187;Euvezin;111;1;112 +54188;Faulx;1344;10;1354 +54189;Favières;591;9;600 +54190;Fécocourt;109;2;111 +54191;Fenneviller;95;2;97 +54192;Ferrières;296;4;300 +54193;Fey-en-Haye;78;1;79 +54194;Fillières;510;8;518 +54195;Flainval;204;0;204 +54196;Flavigny-sur-Moselle;1743;130;1873 +54197;Fléville-devant-Nancy;2263;27;2290 +54198;Fléville-Lixières;320;3;323 +54199;Flin;378;11;389 +54200;Flirey;151;1;152 +54201;Fontenoy-la-Joûte;315;5;320 +54202;Fontenoy-sur-Moselle;374;5;379 +54203;Forcelles-Saint-Gorgon;143;3;146 +54204;Forcelles-sous-Gugney;94;2;96 +54205;Foug;2663;29;2692 +54206;Fraimbois;386;6;392 +54207;Fraisnes-en-Saintois;104;2;106 +54208;Francheville;281;2;283 +54209;Franconville;85;0;85 +54210;Fréménil;216;4;220 +54211;Frémonville;187;2;189 +54212;Fresnois-la-Montagne;409;14;423 +54213;Friauville;367;5;372 +54214;Frolois;708;8;716 +54215;Frouard;6563;74;6637 +54216;Froville;125;0;125 +54217;Gélacourt;167;2;169 +54218;Gélaucourt;68;0;68 +54219;Gellenoncourt;77;0;77 +54220;Gémonville;75;0;75 +54221;Gerbécourt-et-Haplemont;230;1;231 +54222;Gerbéviller;1342;26;1368 +54223;Germiny;219;7;226 +54224;Germonville;115;1;116 +54225;Gézoncourt;177;3;180 +54226;Gibeaumeix;164;3;167 +54227;Giraumont;1320;17;1337 +54228;Giriviller;70;0;70 +54229;Glonville;359;5;364 +54230;Gogney;46;1;47 +54231;Gondrecourt-Aix;177;3;180 +54232;Gondreville;2801;30;2831 +54233;Gondrexon;43;2;45 +54234;Gorcy;2763;43;2806 +54235;Goviller;425;9;434 +54236;Grand-Failly;334;8;342 +54237;Grimonviller;89;3;92 +54238;Gripport;285;1;286 +54239;Griscourt;132;2;134 +54240;Grosrouvres;63;0;63 +54241;Gugney;76;3;79 +54242;Gye;251;4;255 +54243;Hablainville;219;7;226 +54244;Hagéville;113;3;116 +54245;Haigneville;58;0;58 +54246;Halloville;71;6;77 +54247;Hammeville;177;4;181 +54248;Hamonville;96;1;97 +54602;Han-devant-Pierrepont;152;0;152 +54249;Hannonville-Suzémont;259;5;264 +54250;Haraucourt;734;4;738 +54251;Harbouey;118;1;119 +54252;Haroué;510;6;516 +54253;Hatrize;769;13;782 +54254;Haucourt-Moulaine;3241;42;3283 +54255;Haudonville;87;6;93 +54256;Haussonville;303;8;311 +54257;Heillecourt;5527;84;5611 +54258;Hénaménil;147;3;150 +54259;Herbéviller;236;2;238 +54260;Hériménil;956;18;974 +54261;Herserange;4390;47;4437 +54262;Hoéville;198;0;198 +54263;Homécourt;6176;54;6230 +54264;Houdelmont;212;1;213 +54265;Houdemont;2108;67;2175 +54266;Houdreville;425;10;435 +54268;Housséville;158;3;161 +54269;Hudiviller;356;5;361 +54270;Hussigny-Godbrange;3571;63;3634 +54271;Igney;124;6;130 +54272;Jaillon;478;6;484 +54273;Jarny;8283;185;8468 +54274;Jarville-la-Malgrange;9264;259;9523 +54275;Jaulny;203;6;209 +54276;Jeandelaincourt;811;6;817 +54277;Jeandelize;374;5;379 +54278;Jevoncourt;99;1;100 +54279;Jezainville;960;22;982 +54281;Jolivet;904;18;922 +54282;Joppécourt;160;6;166 +54283;Jouaville;298;9;307 +54284;Joudreville;1170;13;1183 +54285;Juvrecourt;58;1;59 +54280;Jœuf;6549;56;6605 +54286;Labry;1566;29;1595 +54287;Lachapelle;266;1;267 +54288;Lagney;506;5;511 +54289;Laître-sous-Amance;397;11;408 +54290;Laix;208;3;211 +54291;Lalœuf;291;3;294 +54292;Lamath;201;1;202 +54293;Landécourt;88;4;92 +54294;Landremont;146;1;147 +54295;Landres;974;110;1084 +54296;Laneuvelotte;437;4;441 +54297;Laneuveville-aux-Bois;319;3;322 +54298;Laneuveville-derrière-Foug;149;4;153 +54299;Laneuveville-devant-Bayon;226;6;232 +54300;Laneuveville-devant-Nancy;6541;110;6651 +54301;Lanfroicourt;130;1;131 +54302;Lantéfontaine;765;18;783 +54303;Laronxe;371;3;374 +54304;Laxou;14444;214;14658 +54305;Lay-Saint-Christophe;2441;68;2509 +54306;Lay-Saint-Remy;352;5;357 +54307;Lebeuville;175;4;179 +54308;Leintrey;142;3;145 +54309;Lemainville;374;4;378 +54310;Leménil-Mitry;3;0;3 +54311;Lenoncourt;592;9;601 +54312;Lesménils;494;10;504 +54313;Létricourt;235;1;236 +54314;Lexy;3725;66;3791 +54315;Leyr;916;6;922 +54316;Limey-Remenauville;285;5;290 +54317;Lironville;129;5;134 +54318;Liverdun;6087;61;6148 +54320;Loisy;325;4;329 +54321;Longlaville;2486;39;2525 +54322;Longuyon;5320;61;5381 +54323;Longwy;14378;291;14669 +54324;Lorey;99;0;99 +54325;Loromontzey;87;3;90 +54326;Lubey;228;4;232 +54327;Lucey;633;9;642 +54328;Ludres;6216;100;6316 +54329;Lunéville;18287;396;18683 +54330;Lupcourt;448;9;457 +54331;Magnières;286;6;292 +54332;Maidières;1547;24;1571 +54333;Mailly-sur-Seille;244;3;247 +54334;Mairy-Mainville;566;11;577 +54335;Maixe;413;4;417 +54336;Maizières;959;12;971 +54337;Malavillers;133;3;136 +54338;Malleloy;981;14;995 +54339;Malzéville;8125;268;8393 +54340;Mamey;339;5;344 +54343;Mandres-aux-Quatre-Tours;187;5;192 +54344;Mangonville;226;3;229 +54345;Manoncourt-en-Vermois;342;5;347 +54346;Manoncourt-en-Woëvre;245;4;249 +54348;Manonville;240;8;248 +54349;Manonviller;166;2;168 +54350;Marainviller;684;8;692 +54351;Marbache;1704;14;1718 +54352;Maron;831;10;841 +54353;Mars-la-Tour;965;18;983 +54354;Marthemont;42;0;42 +54355;Martincourt;96;2;98 +54356;Mattexey;67;2;69 +54357;Maxéville;9814;121;9935 +54358;Mazerulles;271;4;275 +54359;Méhoncourt;240;3;243 +54360;Ménil-la-Tour;336;2;338 +54362;Mercy-le-Bas;1278;6;1284 +54363;Mercy-le-Haut;273;6;279 +54364;Méréville;1345;20;1365 +54365;Merviller;337;9;346 +54366;Messein;1863;20;1883 +54367;Mexy;2283;50;2333 +54368;Mignéville;187;3;190 +54369;Millery;622;8;630 +54370;Minorville;230;1;231 +54371;Moineville;1083;15;1098 +54372;Moivrons;500;2;502 +54373;Moncel-lès-Lunéville;626;5;631 +54374;Moncel-sur-Seille;523;7;530 +54084;Mont-Bonvillers;948;14;962 +54379;Mont-l'Étroit;92;0;92 +54380;Mont-le-Vignoble;419;10;429 +54382;Mont-Saint-Martin;8807;110;8917 +54383;Mont-sur-Meurthe;1114;11;1125 +54375;Montauville;1056;16;1072 +54376;Montenoy;414;6;420 +54377;Montigny;155;0;155 +54378;Montigny-sur-Chiers;482;8;490 +54381;Montreux;62;2;64 +54385;Morfontaine;1092;25;1117 +54386;Moriviller;93;1;94 +54387;Morville-sur-Seille;147;0;147 +54388;Mouacourt;72;2;74 +54389;Mouaville;97;2;99 +54390;Mousson;104;3;107 +54391;Moutiers;1563;24;1587 +54392;Moutrot;303;2;305 +54393;Moyen;550;7;557 +54394;Murville;243;6;249 +54395;Nancy;104286;1457;105743 +54396;Neufmaisons;234;8;242 +54397;Neuves-Maisons;6729;66;6795 +54398;Neuviller-lès-Badonviller;94;2;96 +54399;Neuviller-sur-Moselle;235;1;236 +54400;Nomeny;1174;22;1196 +54401;Nonhigny;122;5;127 +54402;Norroy-le-Sec;417;12;429 +54403;Norroy-lès-Pont-à-Mousson;1194;15;1209 +54404;Noviant-aux-Prés;260;5;265 +54405;Ochey;518;4;522 +54406;Ogéviller;283;7;290 +54407;Ognéville;100;3;103 +54408;Olley;238;3;241 +54409;Omelmont;189;0;189 +54410;Onville;527;3;530 +54411;Ormes-et-Ville;227;2;229 +54412;Othe;33;3;36 +54413;Ozerailles;151;1;152 +54414;Pagney-derrière-Barine;631;8;639 +54415;Pagny-sur-Moselle;4140;53;4193 +54416;Pannes;177;4;181 +54417;Parey-Saint-Césaire;243;3;246 +54418;Parroy;166;1;167 +54419;Parux;71;0;71 +54420;Petit-Failly;86;1;87 +54421;Petitmont;321;4;325 +54422;Pettonville;67;0;67 +54423;Pexonne;365;2;367 +54424;Phlin;42;1;43 +54425;Piennes;2498;30;2528 +54426;Pierre-la-Treiche;492;2;494 +54427;Pierre-Percée;92;1;93 +54428;Pierrepont;870;10;880 +54429;Pierreville;308;2;310 +54430;Pompey;4884;54;4938 +54431;Pont-à-Mousson;14228;218;14446 +54432;Pont-Saint-Vincent;1903;43;1946 +54433;Port-sur-Seille;225;7;232 +54434;Praye;268;2;270 +54435;Prény;355;5;360 +54436;Preutin-Higny;134;1;135 +54437;Pulligny;1165;18;1183 +54438;Pulney;59;2;61 +54439;Pulnoy;4962;59;5021 +54440;Puxe;120;0;120 +54441;Puxieux;250;5;255 +54442;Quevilloncourt;95;2;97 +54443;Raon-lès-Leau;38;0;38 +54444;Raucourt;219;2;221 +54445;Raville-sur-Sânon;102;0;102 +54446;Réchicourt-la-Petite;62;2;64 +54447;Réclonville;76;1;77 +54449;Rehainviller;1044;15;1059 +54450;Reherrey;125;1;126 +54451;Réhon;3827;67;3894 +54452;Reillon;87;6;93 +54453;Rembercourt-sur-Mad;158;1;159 +54455;Remenoville;162;4;166 +54456;Réméréville;558;7;565 +54457;Remoncourt;47;1;48 +54458;Repaix;97;1;98 +54459;Richardménil;2355;25;2380 +54460;Rogéville;176;3;179 +54461;Romain;69;2;71 +54462;Rosières-aux-Salines;2858;30;2888 +54463;Rosières-en-Haye;232;2;234 +54464;Rouves;102;0;102 +54465;Roville-devant-Bayon;785;9;794 +54466;Royaumeix;368;4;372 +54467;Rozelieures;191;5;196 +54468;Saffais;116;0;116 +54469;Saint-Ail;424;5;429 +54470;Saint-Baussant;73;2;75 +54471;Saint-Boingt;71;3;74 +54472;Saint-Clément;861;17;878 +54473;Saint-Firmin;275;6;281 +54475;Saint-Germain;158;6;164 +54476;Saint-Jean-lès-Longuyon;421;11;432 +54477;Saint-Julien-lès-Gorze;161;2;163 +54478;Saint-Marcel;151;3;154 +54479;Saint-Mard;87;2;89 +54480;Saint-Martin;58;1;59 +54481;Saint-Maurice-aux-Forges;101;3;104 +54482;Saint-Max;9965;110;10075 +54483;Saint-Nicolas-de-Port;7520;75;7595 +54485;Saint-Pancré;316;6;322 +54486;Saint-Remimont;354;5;359 +54487;Saint-Rémy-aux-Bois;67;0;67 +54488;Saint-Sauveur;39;0;39 +54489;Saint-Supplet;139;9;148 +54474;Sainte-Geneviève;189;0;189 +54484;Sainte-Pôle;191;3;194 +54490;Saizerais;1503;22;1525 +54491;Sancy;318;7;325 +54492;Sanzey;144;2;146 +54493;Saulnes;2413;43;2456 +54494;Saulxerotte;107;1;108 +54495;Saulxures-lès-Nancy;4120;55;4175 +54496;Saulxures-lès-Vannes;373;5;378 +54497;Saxon-Sion;102;3;105 +54498;Seichamps;4952;61;5013 +54499;Seicheprey;113;4;117 +54500;Selaincourt;180;2;182 +54501;Seranville;100;0;100 +54502;Serres;247;1;248 +54504;Serrouville;683;16;699 +54505;Sexey-aux-Forges;705;8;713 +54507;Sionviller;103;2;105 +54508;Sivry;257;11;268 +54509;Sommerviller;990;4;994 +54510;Sornéville;328;6;334 +54511;Sponville;121;4;125 +54512;Tanconville;114;1;115 +54513;Tantonville;641;4;645 +54514;Tellancourt;560;10;570 +54515;Thélod;251;0;251 +54516;They-sous-Vaudemont;14;1;15 +54517;Thézey-Saint-Martin;203;2;205 +54518;Thiaucourt-Regniéville;1132;10;1142 +54519;Thiaville-sur-Meurthe;573;5;578 +54520;Thiébauménil;380;9;389 +54521;Thil;1877;28;1905 +54522;Thorey-Lyautey;143;3;146 +54523;Thuilley-aux-Groseilles;443;2;445 +54524;Thumeréville;72;1;73 +54525;Tiercelet;655;12;667 +54526;Tomblaine;8887;277;9164 +54527;Tonnoy;698;26;724 +54528;Toul;15832;281;16113 +54529;Tramont-Émy;29;0;29 +54530;Tramont-Lassus;87;2;89 +54531;Tramont-Saint-André;57;1;58 +54532;Tremblecourt;171;3;174 +54533;Trieux;2557;32;2589 +54534;Trondes;544;17;561 +54535;Tronville;201;2;203 +54536;Tucquegnieux;2469;28;2497 +54537;Ugny;715;30;745 +54538;Uruffe;401;2;403 +54539;Vacqueville;238;12;250 +54099;Val de Briey;8228;245;8473 +54540;Val-et-Châtillon;597;7;604 +54541;Valhey;170;2;172 +54542;Valleroy;2334;34;2368 +54543;Vallois;157;2;159 +54544;Vandelainville;140;2;142 +54545;Vandeléville;212;5;217 +54546;Vandières;925;8;933 +54547;Vandœuvre-lès-Nancy;30002;271;30273 +54548;Vannes-le-Châtel;569;8;577 +54549;Varangéville;3652;37;3689 +54550;Vathiménil;346;9;355 +54551;Vaucourt;63;2;65 +54552;Vaudémont;63;2;65 +54553;Vaudeville;157;2;159 +54554;Vaudigny;75;1;76 +54555;Vaxainville;99;0;99 +54556;Vého;100;3;103 +54558;Velaine-sous-Amance;280;5;285 +54559;Velle-sur-Moselle;283;6;289 +54560;Veney;50;0;50 +54561;Vennezey;50;1;51 +54562;Verdenal;156;7;163 +54563;Vézelise;1454;14;1468 +54564;Viéville-en-Haye;147;4;151 +54565;Vigneulles;242;2;244 +54566;Vilcey-sur-Trey;163;2;165 +54567;Villacourt;390;12;402 +54568;Ville-au-Montois;269;3;272 +54569;Ville-au-Val;197;4;201 +54571;Ville-en-Vermois;598;7;605 +54572;Ville-Houdlémont;662;5;667 +54581;Ville-sur-Yron;295;8;303 +54570;Villecey-sur-Mad;340;7;347 +54573;Villers-en-Haye;179;0;179 +54574;Villers-la-Chèvre;568;20;588 +54575;Villers-la-Montagne;1501;36;1537 +54576;Villers-le-Rond;107;1;108 +54577;Villers-lès-Moivrons;148;0;148 +54578;Villers-lès-Nancy;14415;315;14730 +54579;Villers-sous-Prény;346;7;353 +54580;Villerupt;9737;106;9843 +54582;Villette;183;1;184 +54583;Villey-le-Sec;405;11;416 +54584;Villey-Saint-Étienne;1061;23;1084 +54585;Virecourt;470;6;476 +54586;Viterne;733;7;740 +54587;Vitrey;203;4;207 +54588;Vitrimont;401;8;409 +54589;Vittonville;126;6;132 +54590;Viviers-sur-Chiers;663;20;683 +54591;Voinémont;331;11;342 +54592;Vroncourt;268;3;271 +54593;Waville;429;4;433 +54594;Xammes;153;1;154 +54595;Xermaménil;556;7;563 +54596;Xeuilley;934;6;940 +54597;Xirocourt;442;3;445 +54598;Xivry-Circourt;272;6;278 +54599;Xonville;127;0;127 +54600;Xousse;127;1;128 +54601;Xures;108;1;109 +55001;Abainville;301;5;306 +55002;Abaucourt-Hautecourt;107;3;110 +55004;Aincreville;69;1;70 +55005;Amanty;40;1;41 +55007;Ambly-sur-Meuse;245;2;247 +55008;Amel-sur-l'Étang;151;5;156 +55009;Ancemont;551;19;570 +55010;Ancerville;2752;64;2816 +55011;Andernay;258;3;261 +55012;Apremont-la-Forêt;397;9;406 +55013;Arrancy-sur-Crusne;491;7;498 +55014;Aubréville;374;7;381 +55015;Aulnois-en-Perthois;506;14;520 +55017;Autrécourt-sur-Aire;115;5;120 +55018;Autréville-Saint-Lambert;40;2;42 +55021;Avillers-Sainte-Croix;61;1;62 +55022;Avioth;144;4;148 +55023;Avocourt;108;2;110 +55024;Azannes-et-Soumazannes;165;3;168 +55025;Baâlon;290;3;293 +55026;Badonvilliers-Gérauvilliers;138;5;143 +55027;Bannoncourt;155;3;158 +55028;Bantheville;119;2;121 +55029;Bar-le-Duc;14985;600;15585 +55031;Baudonvilliers;378;11;389 +55032;Baudrémont;50;1;51 +55033;Baulny;16;1;17 +55034;Bazeilles-sur-Othain;116;3;119 +55035;Bazincourt-sur-Saulx;147;6;153 +55036;Beauclair;90;1;91 +55037;Beaufort-en-Argonne;144;1;145 +55038;Beaulieu-en-Argonne;36;2;38 +55039;Beaumont-en-Verdunois;0;0;0 +55040;Beausite;250;6;256 +55041;Behonne;609;26;635 +55042;Belleray;508;12;520 +55043;Belleville-sur-Meuse;3092;54;3146 +55044;Belrain;36;3;39 +55045;Belrupt-en-Verdunois;572;8;580 +55046;Beney-en-Woëvre;131;4;135 +55047;Béthelainville;171;6;177 +55048;Béthincourt;35;2;37 +55049;Beurey-sur-Saulx;417;0;417 +55050;Bezonvaux;0;0;0 +55051;Biencourt-sur-Orge;123;4;127 +55053;Billy-sous-Mangiennes;373;1;374 +55054;Bislée;61;5;66 +55055;Blanzée;16;1;17 +55057;Boinville-en-Woëvre;73;2;75 +55058;Boncourt-sur-Meuse;328;10;338 +55059;Bonnet;200;7;207 +55060;Bonzée;350;13;363 +55061;Le Bouchon-sur-Saulx;241;5;246 +55062;Bouconville-sur-Madt;111;1;112 +55063;Bouligny;2558;39;2597 +55064;Bouquemont;111;0;111 +55065;Boureuilles;120;0;120 +55066;Bovée-sur-Barboure;142;6;148 +55067;Boviolles;97;2;99 +55068;Brabant-en-Argonne;106;3;109 +55069;Brabant-le-Roi;230;4;234 +55070;Brabant-sur-Meuse;124;6;130 +55071;Brandeville;184;5;189 +55072;Braquis;119;1;120 +55073;Bras-sur-Meuse;698;49;747 +55075;Brauvilliers;171;3;174 +55076;Bréhéville;171;0;171 +55077;Breux;258;9;267 +55078;Brieulles-sur-Meuse;315;8;323 +55079;Brillon-en-Barrois;671;20;691 +55080;Brixey-aux-Chanoines;84;4;88 +55081;Brizeaux;58;1;59 +55082;Brocourt-en-Argonne;47;1;48 +55083;Brouennes;150;4;154 +55084;Broussey-en-Blois;59;1;60 +55085;Broussey-Raulecourt;283;4;287 +55087;Bure;84;7;91 +55088;Burey-en-Vaux;154;4;158 +55089;Burey-la-Côte;87;1;88 +55093;Buxières-sous-les-Côtes;287;3;290 +55094;Buzy-Darmont;559;11;570 +55095;Cesse;114;3;117 +55096;Chaillon;112;0;112 +55097;Chalaines;318;6;324 +55099;Champneuville;120;1;121 +55100;Champougny;83;8;91 +55358;Chanteraine;185;4;189 +55101;Chardogne;304;7;311 +55102;Charny-sur-Meuse;518;22;540 +55103;Charpentry;22;2;24 +55104;Chassey-Beaupré;88;3;91 +55105;Châtillon-sous-les-Côtes;175;4;179 +55106;Chattancourt;182;3;185 +55107;Chaumont-devant-Damvillers;48;1;49 +55108;Chaumont-sur-Aire;126;4;130 +55109;Chauvency-le-Château;248;3;251 +55110;Chauvency-Saint-Hubert;239;6;245 +55111;Chauvoncourt;452;20;472 +55113;Cheppy;149;1;150 +55114;Chonville-Malaumont;212;5;217 +55115;Cierges-sous-Montfaucon;52;0;52 +55116;Le Claon;60;0;60 +55117;Clermont-en-Argonne;1480;34;1514 +55118;Cléry-le-Grand;91;2;93 +55119;Cléry-le-Petit;186;1;187 +55120;Combles-en-Barrois;797;26;823 +55121;Combres-sous-les-Côtes;118;5;123 +55122;Commercy;5536;242;5778 +55124;Consenvoye;307;4;311 +55125;Contrisson;817;19;836 +55127;Courcelles-en-Barrois;38;0;38 +55128;Courcelles-sur-Aire;40;0;40 +55129;Courouvre;35;2;37 +55132;Cousances-les-Forges;1688;32;1720 +55518;Cousances-lès-Triconville;140;0;140 +55133;Couvertpuis;87;6;93 +55134;Couvonges;156;4;160 +55137;Cuisy;46;0;46 +55138;Culey;141;3;144 +55139;Cumières-le-Mort-Homme;0;0;0 +55140;Cunel;14;0;14 +55141;Dagonville;85;1;86 +55142;Dainville-Bertheléville;116;4;120 +55143;Damloup;131;8;139 +55144;Dammarie-sur-Saulx;422;15;437 +55145;Damvillers;651;59;710 +55146;Dannevoux;228;4;232 +55148;Delouze-Rosières;113;4;117 +55149;Delut;125;0;125 +55150;Demange-Baudignécourt;554;13;567 +55153;Dieppe-sous-Douaumont;189;2;191 +55154;Dieue-sur-Meuse;1446;33;1479 +55155;Dombasle-en-Argonne;407;7;414 +55156;Dombras;138;4;142 +55157;Dommartin-la-Montagne;51;0;51 +55158;Dommary-Baroncourt;737;8;745 +55159;Dompcevrin;309;2;311 +55160;Dompierre-aux-Bois;39;0;39 +55162;Domremy-la-Canne;36;0;36 +55163;Doncourt-aux-Templiers;60;3;63 +55537;Douaumont-Vaux;81;0;81 +55165;Doulcon;445;12;457 +55166;Dugny-sur-Meuse;1307;24;1331 +55167;Dun-sur-Meuse;661;8;669 +55168;Duzey;42;3;45 +55169;Écouviez;510;6;516 +55170;Écurey-en-Verdunois;124;0;124 +55171;Eix;249;4;253 +55172;Les Éparges;67;1;68 +55173;Épiez-sur-Meuse;41;1;42 +55174;Épinonville;72;0;72 +55175;Érize-la-Brûlée;188;6;194 +55177;Érize-la-Petite;55;2;57 +55178;Érize-Saint-Dizier;189;6;195 +55179;Erneville-aux-Bois;160;3;163 +55180;Esnes-en-Argonne;136;1;137 +55181;Étain;3580;70;3650 +55182;Éton;209;3;212 +55183;Étraye;39;1;40 +55184;Euville;1665;27;1692 +55185;Èvres;103;6;109 +55186;Fains-Véel;2140;61;2201 +55188;Flassigny;47;1;48 +55189;Fleury-devant-Douaumont;0;0;0 +55191;Foameix-Ornel;247;8;255 +55192;Fontaines-Saint-Clair;55;2;57 +55193;Forges-sur-Meuse;122;2;124 +55194;Foucaucourt-sur-Thabas;57;0;57 +55195;Fouchères-aux-Bois;134;4;138 +55196;Frémeréville-sous-les-Côtes;137;1;138 +55197;Fresnes-au-Mont;171;4;175 +55198;Fresnes-en-Woëvre;673;10;683 +55199;Froidos;98;2;100 +55200;Fromeréville-les-Vallons;209;4;213 +55201;Fromezey;53;0;53 +55202;Futeau;161;3;164 +55204;Génicourt-sur-Meuse;290;5;295 +55206;Gercourt-et-Drillancourt;106;4;110 +55207;Géry;55;1;56 +55208;Gesnes-en-Argonne;59;3;62 +55258;Geville;620;16;636 +55210;Gimécourt;39;0;39 +55211;Gincrey;64;1;65 +55212;Girauvoisin;77;0;77 +55214;Givrauval;290;23;313 +55215;Gondrecourt-le-Château;1085;15;1100 +55216;Gouraincourt;59;0;59 +55217;Goussaincourt;116;6;122 +55218;Gremilly;40;0;40 +55219;Grimaucourt-en-Woëvre;104;2;106 +55220;Grimaucourt-près-Sampigny;85;0;85 +55221;Guerpont;249;5;254 +55222;Gussainville;35;1;36 +55224;Haironville;595;13;608 +55225;Halles-sous-les-Côtes;151;7;158 +55226;Han-lès-Juvigny;121;1;122 +55229;Han-sur-Meuse;277;2;279 +55228;Hannonville-sous-les-Côtes;567;11;578 +55232;Harville;118;0;118 +55236;Haudainville;952;21;973 +55237;Haudiomont;217;4;221 +55239;Haumont-près-Samogneux;0;0;0 +55123;Les Hauts-de-Chée;728;13;741 +55241;Heippes;76;3;79 +55242;Hennemont;111;4;115 +55243;Herbeuville;180;5;185 +55244;Herméville-en-Woëvre;241;1;242 +55245;Heudicourt-sous-les-Côtes;166;8;174 +55246;Hévilliers;146;1;147 +55247;Horville-en-Ornois;57;2;59 +55248;Houdelaincourt;299;8;307 +55250;Inor;185;8;193 +55251;Ippécourt;97;3;100 +55252;Iré-le-Sec;154;2;156 +55296;L' Isle-en-Rigault;481;15;496 +55253;Les Islettes;747;14;761 +55255;Jametz;257;5;262 +55256;Jonville-en-Woëvre;149;0;149 +55257;Jouy-en-Argonne;47;0;47 +55260;Julvécourt;57;2;59 +55261;Juvigny-en-Perthois;137;2;139 +55262;Juvigny-sur-Loison;260;2;262 +55263;Kœur-la-Grande;164;4;168 +55264;Kœur-la-Petite;285;5;290 +55265;Labeuville;135;5;140 +55266;Lachalade;54;0;54 +55267;Lachaussée;271;9;280 +55268;Lacroix-sur-Meuse;720;18;738 +55269;Lahaymeix;74;0;74 +55270;Lahayville;27;1;28 +55271;Laheycourt;405;9;414 +55272;Laimont;461;17;478 +55274;Lamorville;288;6;294 +55275;Lamouilly;91;5;96 +55276;Landrecourt-Lempire;211;1;212 +55278;Laneuville-au-Rupt;198;3;201 +55279;Laneuville-sur-Meuse;436;9;445 +55280;Lanhères;61;0;61 +55281;Latour-en-Woëvre;95;0;95 +55282;Lavallée;92;3;95 +55284;Lavincourt;70;0;70 +55285;Lavoye;153;3;156 +55286;Lemmes;249;3;252 +55288;Lérouville;1433;16;1449 +55289;Levoncourt;57;1;58 +55290;Lignières-sur-Aire;53;1;54 +55291;Ligny-en-Barrois;4052;138;4190 +55292;Liny-devant-Dun;190;5;195 +55293;Lion-devant-Dun;170;4;174 +55295;Lisle-en-Barrois;35;1;36 +55297;Lissey;111;1;112 +55298;Loisey;300;9;309 +55299;Loison;119;3;122 +55301;Longchamps-sur-Aire;122;8;130 +55300;Longeaux;227;6;233 +55302;Longeville-en-Barrois;1160;29;1189 +55303;Loupmont;75;3;78 +55304;Louppy-le-Château;157;4;161 +55306;Louppy-sur-Loison;126;1;127 +55307;Louvemont-Côte-du-Poivre;0;0;0 +55310;Luzy-Saint-Martin;114;4;118 +55311;Maizeray;33;1;34 +55312;Maizey;165;6;171 +55313;Malancourt;64;2;66 +55315;Mandres-en-Barrois;118;4;122 +55316;Mangiennes;395;7;402 +55317;Manheulles;137;7;144 +55320;Marchéville-en-Woëvre;68;2;70 +55321;Marre;161;7;168 +55322;Marson-sur-Barboure;47;1;48 +55323;Martincourt-sur-Meuse;66;1;67 +55324;Marville;504;13;517 +55325;Maucourt-sur-Orne;57;1;58 +55326;Maulan;117;2;119 +55327;Mauvages;259;2;261 +55328;Maxey-sur-Vaise;293;5;298 +55329;Mécrin;224;2;226 +55330;Méligny-le-Grand;95;2;97 +55331;Méligny-le-Petit;80;0;80 +55332;Menaucourt;238;5;243 +55333;Ménil-aux-Bois;42;1;43 +55334;Ménil-la-Horgne;169;3;172 +55335;Ménil-sur-Saulx;256;9;265 +55336;Merles-sur-Loison;150;5;155 +55338;Milly-sur-Bradon;162;5;167 +55339;Mogeville;85;1;86 +55340;Mognéville;381;10;391 +55341;Moirey-Flabas-Crépion;129;2;131 +55345;Mont-devant-Sassey;95;3;98 +55343;Montblainville;61;2;63 +55344;Montbras;19;0;19 +55346;Montfaucon-d'Argonne;307;6;313 +55347;Les Monthairons;374;3;377 +55348;Montiers-sur-Saulx;380;3;383 +55349;Montigny-devant-Sassey;117;6;123 +55350;Montigny-lès-Vaucouleurs;68;0;68 +55351;Montmédy;2136;85;2221 +55352;Montplonne;141;17;158 +55353;Montsec;85;0;85 +55355;Montzéville;155;1;156 +55356;Moranville;108;1;109 +55357;Morgemoulin;111;3;114 +55359;Morley;205;3;208 +55360;Mouilly;113;1;114 +55361;Moulainville;124;6;130 +55362;Moulins-Saint-Hubert;176;3;179 +55363;Moulotte;101;0;101 +55364;Mouzay;692;30;722 +55365;Murvaux;141;3;144 +55367;Muzeray;134;4;138 +55368;Naives-en-Blois;151;10;161 +55369;Naives-Rosières;802;20;822 +55370;Naix-aux-Forges;221;2;223 +55373;Nant-le-Grand;79;5;84 +55374;Nant-le-Petit;78;1;79 +55375;Nantillois;63;1;64 +55376;Nantois;85;4;89 +55371;Nançois-le-Grand;73;4;77 +55372;Nançois-sur-Ornain;384;9;393 +55377;Nepvant;86;1;87 +55378;Nettancourt;252;3;255 +55379;Le Neufour;72;2;74 +55380;Neuville-en-Verdunois;58;2;60 +55381;Neuville-lès-Vaucouleurs;176;8;184 +55382;Neuville-sur-Ornain;362;11;373 +55383;Neuvilly-en-Argonne;216;2;218 +55384;Nicey-sur-Aire;123;4;127 +55385;Nixéville-Blercourt;494;16;510 +55386;Nonsard-Lamarche;210;5;215 +55387;Nouillonpont;238;4;242 +55388;Noyers-Auzécourt;281;7;288 +55389;Nubécourt;249;7;256 +55391;Olizy-sur-Chiers;192;6;198 +55394;Ornes;5;0;5 +55395;Osches;55;3;58 +55396;Ourches-sur-Meuse;221;4;225 +55397;Pagny-la-Blanche-Côte;237;4;241 +55398;Pagny-sur-Meuse;1023;16;1039 +55399;Pareid;119;0;119 +55400;Parfondrupt;45;0;45 +55401;Les Paroches;416;10;426 +55403;Peuvillers;55;2;57 +55404;Pierrefitte-sur-Aire;316;12;328 +55405;Pillon;264;2;266 +55406;Pintheville;110;4;114 +55407;Pont-sur-Meuse;133;6;139 +55408;Pouilly-sur-Meuse;178;5;183 +55409;Pretz-en-Argonne;72;2;74 +55410;Quincy-Landzécourt;140;6;146 +55442;Raival;254;4;258 +55411;Rambluzin-et-Benoite-Vaux;102;1;103 +55412;Rambucourt;189;6;195 +55414;Rancourt-sur-Ornain;191;1;192 +55415;Ranzières;82;1;83 +55416;Rarécourt;222;8;230 +55419;Récicourt;167;4;171 +55420;Récourt-le-Creux;77;0;77 +55421;Reffroy;73;4;77 +55422;Regnéville-sur-Meuse;51;0;51 +55423;Rembercourt-Sommaisne;353;9;362 +55424;Remennecourt;55;0;55 +55425;Remoiville;134;0;134 +55426;Resson;391;14;405 +55427;Revigny-sur-Ornain;2805;51;2856 +55428;Réville-aux-Bois;116;0;116 +55429;Riaville;43;2;45 +55430;Ribeaucourt;72;1;73 +55431;Richecourt;59;0;59 +55433;Rigny-la-Salle;365;12;377 +55434;Rigny-Saint-Martin;53;4;57 +55435;Robert-Espagne;823;24;847 +55436;Les Roises;30;0;30 +55437;Romagne-sous-les-Côtes;118;3;121 +55438;Romagne-sous-Montfaucon;184;4;188 +55439;Ronvaux;88;5;93 +55443;Rouvres-en-Woëvre;604;6;610 +55444;Rouvrois-sur-Meuse;207;1;208 +55445;Rouvrois-sur-Othain;194;8;202 +55446;Rumont;83;0;83 +55447;Rupt-aux-Nonains;371;6;377 +55448;Rupt-devant-Saint-Mihiel;56;0;56 +55449;Rupt-en-Woëvre;299;6;305 +55450;Rupt-sur-Othain;44;2;46 +55452;Saint-Amand-sur-Ornain;53;2;55 +55453;Saint-André-en-Barrois;66;1;67 +55454;Saint-Aubin-sur-Aire;171;1;172 +55456;Saint-Germain-sur-Meuse;257;9;266 +55457;Saint-Hilaire-en-Woëvre;174;6;180 +55458;Saint-Jean-lès-Buzy;370;0;370 +55459;Saint-Joire;239;3;242 +55460;Saint-Julien-sous-les-Côtes;140;2;142 +55461;Saint-Laurent-sur-Othain;506;10;516 +55462;Saint-Maurice-sous-les-Côtes;352;11;363 +55463;Saint-Mihiel;4112;75;4187 +55464;Saint-Pierrevillers;156;8;164 +55465;Saint-Remy-la-Calonne;103;0;103 +55466;Salmagne;301;5;306 +55468;Samogneux;95;0;95 +55467;Sampigny;706;13;719 +55469;Sassey-sur-Meuse;103;0;103 +55470;Saudrupt;198;2;200 +55471;Saulmory-Villefranche;87;0;87 +55472;Saulvaux;115;5;120 +55473;Saulx-lès-Champlon;118;11;129 +55474;Sauvigny;232;7;239 +55475;Sauvoy;62;2;64 +55476;Savonnières-devant-Bar;474;14;488 +55477;Savonnières-en-Perthois;409;10;419 +55479;Seigneulles;173;3;176 +55481;Senon;336;2;338 +55482;Senoncourt-les-Maujouy;95;2;97 +55484;Septsarges;47;1;48 +55485;Sepvigny;74;3;77 +55517;Seuil-d'Argonne;519;4;523 +55487;Seuzey;115;3;118 +55488;Silmont;159;1;160 +55489;Sivry-la-Perche;274;6;280 +55490;Sivry-sur-Meuse;337;11;348 +55492;Sommedieue;977;13;990 +55493;Sommeilles;204;1;205 +55494;Sommelonne;455;22;477 +55495;Sorbey;272;0;272 +55496;Sorcy-Saint-Martin;1105;22;1127 +55497;Les Souhesmes-Rampont;343;12;355 +55498;Souilly;446;5;451 +55500;Spincourt;841;13;854 +55501;Stainville;418;12;430 +55502;Stenay;2597;124;2721 +55503;Taillancourt;127;2;129 +55504;Tannois;403;10;413 +55505;Thierville-sur-Meuse;3118;97;3215 +55506;Thillombois;30;0;30 +55507;Thillot;232;2;234 +55508;Thonne-la-Long;333;2;335 +55509;Thonne-le-Thil;269;3;272 +55510;Thonne-les-Près;135;2;137 +55511;Thonnelle;134;3;137 +55512;Tilly-sur-Meuse;288;4;292 +55514;Trémont-sur-Saulx;607;9;616 +55515;Trésauvaux;70;1;71 +55516;Tréveray;572;9;581 +55254;Les Trois-Domaines;124;2;126 +55519;Tronville-en-Barrois;1438;30;1468 +55520;Troussey;464;11;475 +55521;Troyon;263;7;270 +55522;Ugny-sur-Meuse;109;3;112 +55523;Vacherauville;177;4;181 +55525;Vadelaincourt;80;0;80 +55526;Vadonville;260;5;265 +55366;Val-d'Ornain;988;34;1022 +55530;Valbois;93;1;94 +55527;Varennes-en-Argonne;655;12;667 +55528;Varnéville;54;0;54 +55531;Vassincourt;266;27;293 +55532;Vaubecourt;314;4;318 +55533;Vaucouleurs;1943;23;1966 +55534;Vaudeville-le-Haut;55;0;55 +55535;Vaudoncourt;89;0;89 +55536;Vauquois;17;3;20 +55540;Vaux-lès-Palameix;57;1;58 +55541;Vavincourt;514;10;524 +55543;Velaines;950;21;971 +55544;Velosnes;165;2;167 +55545;Verdun;17475;974;18449 +55546;Verneuil-Grand;203;7;210 +55547;Verneuil-Petit;123;4;127 +55549;Véry;90;1;91 +55552;Vigneul-sous-Montmédy;87;3;90 +55551;Vigneulles-lès-Hattonchâtel;1572;93;1665 +55553;Vignot;1309;33;1342 +55555;Ville-devant-Belrain;35;0;35 +55556;Ville-devant-Chaumont;50;1;51 +55557;Ville-en-Woëvre;123;2;125 +55567;Ville-sur-Cousances;140;2;142 +55568;Ville-sur-Saulx;287;11;298 +55554;Villécloye;265;15;280 +55559;Villeroy-sur-Méholle;37;2;39 +55560;Villers-aux-Vents;132;4;136 +55561;Villers-devant-Dun;52;5;57 +55562;Villers-le-Sec;125;2;127 +55563;Villers-lès-Mangiennes;81;4;85 +55565;Villers-sous-Pareid;79;3;82 +55566;Villers-sur-Meuse;307;2;309 +55569;Villotte-devant-Louppy;164;4;168 +55570;Villotte-sur-Aire;200;8;208 +55571;Vilosnes-Haraumont;221;8;229 +55572;Vittarville;78;1;79 +55573;Void-Vacon;1639;30;1669 +55574;Vouthon-Bas;49;2;51 +55575;Vouthon-Haut;84;0;84 +55577;Waly;60;2;62 +55578;Warcq;196;7;203 +55579;Watronville;105;0;105 +55580;Wavrille;50;3;53 +55581;Willeroncourt;107;4;111 +55582;Wiseppe;97;1;98 +55583;Woël;200;2;202 +55584;Woimbey;122;3;125 +55586;Xivray-et-Marvoisin;99;2;101 +56001;Allaire;3854;125;3979 +56002;Ambon;1817;46;1863 +56003;Arradon;5340;172;5512 +56004;Arzal;1656;31;1687 +56005;Arzon;2073;41;2114 +56006;Augan;1547;32;1579 +56007;Auray;13627;389;14016 +56008;Baden;4340;120;4460 +56009;Bangor;999;24;1023 +56010;Baud;6261;193;6454 +56011;Béganne;1404;27;1431 +56012;Beignon;1863;40;1903 +56013;Belz;3711;56;3767 +56014;Berné;1531;142;1673 +56015;Berric;1904;29;1933 +56017;Bignan;2791;61;2852 +56018;Billiers;959;26;985 +56019;Billio;353;10;363 +56020;Bohal;830;15;845 +56262;Bono;2466;42;2508 +56021;Brandérion;1429;26;1455 +56022;Brandivy;1280;25;1305 +56023;Brech;6637;275;6912 +56024;Bréhan;2305;41;2346 +56025;Brignac;186;4;190 +56026;Bubry;2374;37;2411 +56027;Buléon;534;10;544 +56028;Caden;1630;39;1669 +56029;Calan;1206;23;1229 +56030;Camoël;1007;15;1022 +56031;Camors;3030;61;3091 +56032;Campénéac;1903;54;1957 +56033;Carentoir;3165;60;3225 +56034;Carnac;4251;123;4374 +56035;Caro;1151;30;1181 +56036;Caudan;6838;197;7035 +56039;La Chapelle-Neuve;980;21;1001 +56040;Cléguer;3323;60;3383 +56041;Cléguérec;2906;94;3000 +56042;Colpo;2222;35;2257 +56043;Concoret;734;11;745 +56044;Cournon;761;23;784 +56045;Le Cours;670;10;680 +56046;Crach;3339;92;3431 +56047;Crédin;1559;30;1589 +56048;Le Croisty;709;18;727 +56050;La Croix-Helléan;891;31;922 +56049;Croixanvec;164;3;167 +56051;Cruguel;651;5;656 +56052;Damgan;1702;25;1727 +56053;Elven;6021;116;6137 +56054;Erdeven;3666;79;3745 +56055;Étel;1971;189;2160 +56144;Évellys;3482;64;3546 +56056;Évriguet;181;3;184 +56057;Le Faouët;2803;58;2861 +56058;Férel;3220;71;3291 +56102;Forges de Lanouée;2223;52;2275 +56060;Les Fougerêts;945;35;980 +56061;La Gacilly;3975;80;4055 +56062;Gâvres;675;19;694 +56063;Gestel;2684;83;2767 +56065;Gourhel;702;24;726 +56066;Gourin;3803;149;3952 +56067;Grand-Champ;5404;131;5535 +56068;La Grée-Saint-Laurent;336;9;345 +56069;Groix;2263;57;2320 +56070;Guégon;2287;50;2337 +56071;Guéhenno;796;12;808 +56072;Gueltas;512;13;525 +56073;Guémené-sur-Scorff;1061;15;1076 +56074;Guénin;1769;24;1793 +56075;Guer;6192;285;6477 +56076;Guern;1306;40;1346 +56077;Le Guerno;969;16;985 +56078;Guidel;11550;341;11891 +56079;Guillac;1357;38;1395 +56080;Guilliers;1313;142;1455 +56081;Guiscriff;2088;54;2142 +56082;Helléan;375;7;382 +56083;Hennebont;15678;363;16041 +56084;Le Hézo;813;13;826 +56085;Hœdic;99;6;105 +56087;Île-aux-Moines;606;15;621 +56088;Île-d'Arz;225;8;233 +56086;Île-d'Houat;231;6;237 +56089;Inguiniel;2158;53;2211 +56090;Inzinzac-Lochrist;6526;131;6657 +56091;Josselin;2495;95;2590 +56092;Kerfourn;838;16;854 +56093;Kergrist;723;15;738 +56264;Kernascléden;398;10;408 +56094;Kervignac;6596;204;6800 +56096;Landaul;2298;50;2348 +56097;Landévant;3810;68;3878 +56098;Lanester;22728;491;23219 +56099;Langoëlan;380;6;386 +56100;Langonnet;1757;59;1816 +56101;Languidic;7971;148;8119 +56103;Lantillac;306;4;310 +56104;Lanvaudan;798;10;808 +56105;Lanvénégen;1165;25;1190 +56106;Larmor-Baden;887;19;906 +56107;Larmor-Plage;8299;240;8539 +56108;Larré;1040;20;1060 +56109;Lauzach;1146;9;1155 +56110;Lignol;853;21;874 +56111;Limerzel;1336;22;1358 +56112;Lizio;735;15;750 +56113;Locmalo;904;21;925 +56114;Locmaria;868;27;895 +56115;Locmaria-Grand-Champ;1707;39;1746 +56116;Locmariaquer;1566;45;1611 +56117;Locminé;4332;221;4553 +56118;Locmiquélic;4046;114;4160 +56119;Locoal-Mendon;3416;65;3481 +56120;Locqueltas;1758;37;1795 +56121;Lorient;57149;1468;58617 +56122;Loyat;1624;41;1665 +56123;Malansac;2202;43;2245 +56124;Malestroit;2456;77;2533 +56125;Malguénac;1843;53;1896 +56126;Marzan;2308;26;2334 +56127;Mauron;3082;63;3145 +56128;Melrand;1516;26;1542 +56129;Ménéac;1578;45;1623 +56130;Merlevenez;3207;68;3275 +56131;Meslan;1424;32;1456 +56132;Meucon;2248;52;2300 +56133;Missiriac;1145;27;1172 +56134;Mohon;983;10;993 +56135;Molac;1569;28;1597 +56136;Monteneuf;756;15;771 +56137;Monterblanc;3275;76;3351 +56139;Montertelot;355;10;365 +56140;Moréac;3765;63;3828 +56141;Moustoir-Ac;1804;40;1844 +56143;Muzillac;5015;124;5139 +56145;Néant-sur-Yvel;1087;25;1112 +56146;Neulliac;1412;50;1462 +56147;Nivillac;4612;84;4696 +56148;Nostang;1545;31;1576 +56149;Noyal-Muzillac;2520;53;2573 +56151;Noyal-Pontivy;3639;118;3757 +56152;Le Palais;2571;58;2629 +56153;Péaule;2682;42;2724 +56154;Peillac;1858;51;1909 +56155;Pénestin;1946;24;1970 +56156;Persquen;346;6;352 +56157;Plaudren;1946;33;1979 +56158;Plescop;5854;168;6022 +56159;Pleucadeuc;1804;43;1847 +56160;Pleugriffet;1272;21;1293 +56161;Ploemel;2888;86;2974 +56162;Ploemeur;17853;683;18536 +56163;Ploërdut;1216;28;1244 +56164;Ploeren;6575;209;6784 +56165;Ploërmel;9837;583;10420 +56166;Plouay;5670;127;5797 +56167;Plougoumelen;2439;63;2502 +56168;Plouharnel;2160;48;2208 +56169;Plouhinec;5353;126;5479 +56170;Plouray;1121;33;1154 +56171;Pluherlin;1528;27;1555 +56172;Plumelec;2680;67;2747 +56173;Pluméliau-Bieuzy;4379;97;4476 +56174;Plumelin;2723;68;2791 +56175;Plumergat;4112;93;4205 +56176;Pluneret;5722;133;5855 +56177;Pluvigner;7543;138;7681 +56179;Pont-Scorff;3744;91;3835 +56178;Pontivy;14606;938;15544 +56180;Porcaro;722;16;738 +56181;Port-Louis;2618;81;2699 +56182;Priziac;976;180;1156 +56184;Questembert;7585;272;7857 +56185;Quéven;8676;219;8895 +56186;Quiberon;4741;93;4834 +56188;Quistinic;1431;23;1454 +56189;Radenac;1059;17;1076 +56190;Réguiny;1992;55;2047 +56191;Réminiac;384;7;391 +56193;Riantec;5622;139;5761 +56194;Rieux;2845;75;2920 +56195;La Roche-Bernard;692;11;703 +56196;Rochefort-en-Terre;632;13;645 +56198;Rohan;1636;48;1684 +56199;Roudouallec;710;13;723 +56200;Ruffiac;1410;34;1444 +56201;Le Saint;587;11;598 +56202;Saint-Abraham;536;15;551 +56203;Saint-Aignan;605;13;618 +56204;Saint-Allouestre;627;8;635 +56205;Saint-Armel;886;18;904 +56206;Saint-Avé;11642;303;11945 +56207;Saint-Barthélemy;1164;18;1182 +56208;Saint-Brieuc-de-Mauron;331;10;341 +56210;Saint-Caradec-Trégomel;480;6;486 +56211;Saint-Congard;764;16;780 +56212;Saint-Dolay;2487;39;2526 +56213;Saint-Gérand;1115;29;1144 +56214;Saint-Gildas-de-Rhuys;1576;24;1600 +56215;Saint-Gonnery;1090;24;1114 +56216;Saint-Gorgon;394;4;398 +56218;Saint-Gravé;730;5;735 +56219;Saint-Guyomard;1362;22;1384 +56221;Saint-Jacut-les-Pins;1733;107;1840 +56222;Saint-Jean-Brévelay;2789;131;2920 +56223;Saint-Jean-la-Poterie;1500;50;1550 +56224;Saint-Laurent-sur-Oust;366;8;374 +56225;Saint-Léry;189;7;196 +56226;Saint-Malo-de-Beignon;511;16;527 +56227;Saint-Malo-des-Trois-Fontaines;568;14;582 +56228;Saint-Marcel;1074;47;1121 +56229;Saint-Martin-sur-Oust;1305;19;1324 +56230;Saint-Nicolas-du-Tertre;468;11;479 +56231;Saint-Nolff;3779;120;3899 +56232;Saint-Perreux;1145;43;1188 +56233;Saint-Philibert;1496;42;1538 +56234;Saint-Pierre-Quiberon;2060;38;2098 +56236;Saint-Servant;811;19;830 +56237;Saint-Thuriau;1863;74;1937 +56238;Saint-Tugdual;370;5;375 +56239;Saint-Vincent-sur-Oust;1512;41;1553 +56263;Sainte-Anne-d'Auray;2708;94;2802 +56209;Sainte-Brigitte;177;7;184 +56220;Sainte-Hélène;1247;29;1276 +56240;Sarzeau;8182;163;8345 +56241;Sauzon;988;28;1016 +56242;Séglien;669;18;687 +56243;Séné;8947;252;9199 +56244;Sérent;3048;41;3089 +56245;Silfiac;434;7;441 +56246;Le Sourn;2107;44;2151 +56247;Sulniac;3674;68;3742 +56248;Surzur;4429;91;4520 +56249;Taupont;2198;87;2285 +56250;Théhillac;596;5;601 +56251;Theix-Noyalo;7966;197;8163 +56252;Le Tour-du-Parc;1231;8;1239 +56253;Tréal;640;25;665 +56254;Trédion;1273;17;1290 +56255;Treffléan;2324;55;2379 +56256;Tréhorenteuc;122;1;123 +56257;La Trinité-Porhoët;677;18;695 +56258;La Trinité-sur-Mer;1610;46;1656 +56259;La Trinité-Surzur;1611;21;1632 +56197;Val d'Oust;2705;75;2780 +56260;Vannes;53352;2070;55422 +56261;La Vraie-Croix;1471;30;1501 +57001;Aboncourt;351;3;354 +57002;Aboncourt-sur-Seille;72;2;74 +57003;Abreschviller;1427;22;1449 +57004;Achain;82;2;84 +57006;Achen;1011;28;1039 +57007;Adaincourt;125;1;126 +57008;Adelange;209;7;216 +57009;Ajoncourt;103;1;104 +57010;Alaincourt-la-Côte;149;2;151 +57011;Albestroff;634;23;657 +57012;Algrange;6144;56;6200 +57013;Alsting;2589;46;2635 +57014;Altrippe;382;7;389 +57015;Altviller;586;7;593 +57016;Alzing;392;8;400 +57017;Amanvillers;2161;23;2184 +57018;Amelécourt;154;10;164 +57019;Amnéville;10416;62;10478 +57020;Ancerville;302;2;304 +57021;Ancy-Dornot;1560;33;1593 +57022;Angevillers;1253;29;1282 +57024;Antilly;172;0;172 +57025;Anzeling;521;7;528 +57026;Apach;1032;17;1049 +57028;Argancy;1343;19;1362 +57027;Arraincourt;126;3;129 +57029;Arriance;212;2;214 +57030;Arry;554;4;558 +57031;Ars-Laquenexy;910;15;925 +57032;Ars-sur-Moselle;4723;46;4769 +57033;Arzviller;535;16;551 +57034;Aspach;34;1;35 +57035;Assenoncourt;116;3;119 +57036;Attilloncourt;105;0;105 +57037;Aube;268;5;273 +57038;Audun-le-Tiche;6846;62;6908 +57039;Augny;1996;30;2026 +57040;Aulnois-sur-Seille;278;2;280 +57041;Aumetz;2319;31;2350 +57042;Avricourt;612;8;620 +57043;Ay-sur-Moselle;1491;31;1522 +57044;Azoudange;118;5;123 +57045;Bacourt;109;2;111 +57046;Baerenthal;778;13;791 +57047;Bambiderstroff;1060;20;1080 +57049;Le Ban-Saint-Martin;4341;98;4439 +57048;Bannay;73;2;75 +57050;Barchain;110;2;112 +57051;Baronville;364;8;372 +57052;Barst;579;9;588 +57287;Basse-Ham;2237;51;2288 +57574;Basse-Rentgen;491;10;501 +57053;Bassing;119;5;124 +57054;Baudrecourt;186;1;187 +57055;Bazoncourt;540;2;542 +57056;Bébing;201;4;205 +57057;Béchy;630;5;635 +57058;Behren-lès-Forbach;6562;64;6626 +57059;Bellange;55;2;57 +57086;Belles-Forêts;245;5;250 +57060;Bénestroff;550;7;557 +57061;Béning-lès-Saint-Avold;1140;25;1165 +57062;Berg-sur-Moselle;430;15;445 +57063;Bérig-Vintrange;219;8;227 +57064;Berling;270;4;274 +57065;Bermering;225;6;231 +57066;Berthelming;511;9;520 +57067;Bertrange;2691;54;2745 +57069;Berviller-en-Moselle;471;7;478 +57070;Bettange;242;2;244 +57071;Bettborn;395;5;400 +57072;Bettelainville;625;8;633 +57073;Betting;882;16;898 +57074;Bettviller;831;17;848 +57075;Beux;274;3;277 +57076;Beyren-lès-Sierck;517;17;534 +57077;Bezange-la-Petite;92;3;95 +57079;Bibiche;452;9;461 +57080;Bickenholtz;81;0;81 +57081;Bidestroff;129;1;130 +57082;Biding;324;6;330 +57083;Bining;1173;25;1198 +57084;Bioncourt;307;2;309 +57085;Bionville-sur-Nied;381;9;390 +57087;Bisten-en-Lorraine;246;4;250 +57088;Bistroff;311;7;318 +57089;Bitche;5098;118;5216 +57090;Blanche-Église;113;2;115 +57092;Blies-Ébersing;646;8;654 +57093;Blies-Guersviller;644;12;656 +57091;Bliesbruck;1017;19;1036 +57095;Boucheporn;581;14;595 +57096;Boulange;2494;25;2519 +57097;Boulay-Moselle;5587;71;5658 +57099;Bourdonnay;229;5;234 +57098;Bourgaltroff;245;2;247 +57100;Bourscheid;179;4;183 +57101;Bousbach;1226;24;1250 +57102;Bousse;3174;48;3222 +57103;Bousseviller;125;4;129 +57104;Boust;1228;23;1251 +57105;Boustroff;149;2;151 +57106;Bouzonville;3947;80;4027 +57107;Bréhain;107;0;107 +57108;Breidenbach;328;12;340 +57109;Breistroff-la-Grande;698;15;713 +57110;Brettnach;441;4;445 +57111;Bronvaux;546;3;549 +57112;Brouck;84;1;85 +57113;Brouderdorff;966;23;989 +57114;Brouviller;427;15;442 +57115;Brulange;100;4;104 +57116;Buchy;99;1;100 +57117;Buding;588;5;593 +57118;Budling;176;6;182 +57119;Buhl-Lorraine;1214;31;1245 +57120;Burlioncourt;138;3;141 +57121;Burtoncourt;196;5;201 +57122;Cappel;701;12;713 +57123;Carling;3445;43;3488 +57124;Cattenom;2654;35;2689 +57125;Chailly-lès-Ennery;381;6;387 +57126;Chambrey;337;10;347 +57127;Chanville;133;0;133 +57128;Charleville-sous-Bois;320;3;323 +57129;Charly-Oradour;679;21;700 +57130;Château-Bréhain;76;1;77 +57131;Château-Rouge;292;11;303 +57132;Château-Salins;2464;237;2701 +57133;Château-Voué;101;0;101 +57134;Châtel-Saint-Germain;1873;153;2026 +57136;Chémery-les-Deux;565;6;571 +57137;Cheminot;775;13;788 +57138;Chenois;80;3;83 +57139;Chérisey;305;4;309 +57140;Chesny;594;10;604 +57141;Chicourt;96;2;98 +57142;Chieulles;417;7;424 +57143;Clouange;3495;37;3532 +57144;Cocheren;3478;42;3520 +57146;Coin-lès-Cuvry;726;16;742 +57147;Coin-sur-Seille;338;14;352 +57145;Coincy;313;5;318 +57148;Colligny-Maizery;577;12;589 +57149;Colmen;197;4;201 +57150;Condé-Northen;678;7;685 +57151;Conthil;165;3;168 +57152;Contz-les-Bains;508;10;518 +57153;Corny-sur-Moselle;2219;25;2244 +57154;Coume;662;9;671 +57155;Courcelles-Chaussy;3075;322;3397 +57156;Courcelles-sur-Nied;1190;11;1201 +57158;Craincourt;254;1;255 +57159;Créhange;3868;55;3923 +57160;Creutzwald;13095;235;13330 +57161;Cutting;139;0;139 +57162;Cuvry;847;15;862 +57163;Dabo;2522;41;2563 +57165;Dalem;646;9;655 +57166;Dalhain;110;2;112 +57167;Dalstein;361;6;367 +57168;Danne-et-Quatre-Vents;686;11;697 +57169;Dannelbourg;500;12;512 +57171;Delme;1124;9;1133 +57172;Denting;274;1;275 +57173;Desseling;103;3;106 +57174;Destry;94;1;95 +57175;Diane-Capelle;221;6;227 +57176;Diebling;1643;39;1682 +57765;Diesen;1057;15;1072 +57177;Dieuze;2903;234;3137 +57178;Diffembach-lès-Hellimer;354;6;360 +57179;Distroff;1773;31;1804 +57180;Dolving;352;6;358 +57181;Domnom-lès-Dieuze;81;1;82 +57182;Donjeux;95;3;98 +57183;Donnelay;190;2;192 +57186;Ébersviller;949;20;969 +57187;Éblange;374;6;380 +57188;Éguelshardt;426;80;506 +57189;Eincheville;220;2;222 +57190;Elvange;398;4;402 +57191;Elzange;721;8;729 +57192;Enchenberg;1239;32;1271 +57193;Ennery;2010;24;2034 +57194;Entrange;1241;37;1278 +57195;Epping;570;14;584 +57196;Erching;415;11;426 +57197;Ernestviller;503;5;508 +57198;Erstroff;194;3;197 +57199;Escherange;631;14;645 +57200;Les Étangs;401;10;411 +57201;Etting;747;14;761 +57202;Etzling;1184;17;1201 +57203;Évrange;240;3;243 +57204;Failly;511;10;521 +57205;Falck;2487;32;2519 +57206;Fameck;13931;125;14056 +57207;Farébersviller;5541;59;5600 +57208;Farschviller;1356;34;1390 +57209;Faulquemont;5306;88;5394 +57210;Fénétrange;723;13;736 +57211;Fèves;1118;19;1137 +57212;Féy;738;9;747 +57213;Filstroff;777;17;794 +57214;Fixem;418;7;425 +57215;Flastroff;326;4;330 +57216;Fleisheim;148;5;153 +57217;Flétrange;931;19;950 +57218;Fleury;1223;27;1250 +57219;Flévy;557;6;563 +57220;Flocourt;116;2;118 +57221;Florange;11951;103;12054 +57222;Folkling;1303;37;1340 +57224;Folschviller;3993;72;4065 +57225;Fonteny;143;0;143 +57226;Fontoy;3036;43;3079 +57227;Forbach;21552;306;21858 +57228;Fossieux;219;2;221 +57229;Foulcrey;170;4;174 +57230;Fouligny;195;2;197 +57231;Foville;98;0;98 +57232;Francaltroff;771;12;783 +57233;Fraquelfing;83;1;84 +57234;Frauenberg;591;8;599 +57235;Freistroff;1050;20;1070 +57236;Frémery;77;0;77 +57237;Frémestroff;301;6;307 +57238;Fresnes-en-Saulnois;183;6;189 +57239;Freybouse;432;6;438 +57240;Freyming-Merlebach;12818;142;12960 +57241;Fribourg;165;8;173 +57242;Gandrange;2907;36;2943 +57244;Garrebourg;496;11;507 +57245;Gavisse;569;9;578 +57246;Gelucourt;217;4;221 +57247;Gerbécourt;88;3;91 +57248;Givrycourt;88;1;89 +57249;Glatigny;256;7;263 +57250;Goetzenbruck;1531;41;1572 +57251;Goin;335;2;337 +57252;Gomelange;497;10;507 +57253;Gondrexange;491;4;495 +57254;Gorze;1167;10;1177 +57255;Gosselming;587;23;610 +57256;Gravelotte;830;4;834 +57257;Grémecey;105;0;105 +57258;Gréning;131;1;132 +57259;Grindorff-Bizing;317;7;324 +57261;Gros-Réderching;1333;40;1373 +57260;Grosbliederstroff;3303;53;3356 +57262;Grostenquin;631;6;637 +57263;Grundviller;658;19;677 +57264;Guebenhouse;426;6;432 +57265;Guébestroff;48;4;52 +57266;Guéblange-lès-Dieuze;156;4;160 +57268;Guébling;124;4;128 +57269;Guénange;7210;65;7275 +57271;Guenviller;645;22;667 +57272;Guermange;93;5;98 +57273;Guerstling;415;8;423 +57274;Guerting;854;20;874 +57275;Guessling-Hémering;919;13;932 +57276;Guinglange;329;5;334 +57277;Guinkirchen;152;8;160 +57278;Guinzeling;69;0;69 +57280;Guntzviller;385;13;398 +57281;Haboudange;267;4;271 +57282;Hagen;362;1;363 +57283;Hagondange;9242;97;9339 +57284;Hallering;113;5;118 +57286;Halstroff;313;9;322 +57288;Ham-sous-Varsberg;2825;40;2865 +57289;Hambach;2886;67;2953 +57290;Hampont;185;2;187 +57293;Han-sur-Nied;258;8;266 +57291;Hangviller;263;4;267 +57292;Hannocourt;21;1;22 +57294;Hanviller;208;8;216 +57295;Haraucourt-sur-Seille;103;1;104 +57296;Hargarten-aux-Mines;1107;20;1127 +57297;Harprich;173;6;179 +57298;Harreberg;395;7;402 +57299;Hartzviller;912;15;927 +57300;Haselbourg;315;7;322 +57301;Haspelschiedt;303;12;315 +57302;Hattigny;187;1;188 +57303;Hauconcourt;623;9;632 +57304;Haut-Clocher;348;11;359 +57371;Haute-Kontz;588;7;595 +57714;Haute-Vigneulles;416;9;425 +57305;Havange;448;8;456 +57306;Hayange;15811;161;15972 +57307;Hayes;232;6;238 +57308;Hazembourg;138;5;143 +57309;Heining-lès-Bouzonville;477;9;486 +57310;Hellering-lès-Fénétrange;187;1;188 +57311;Hellimer;548;9;557 +57312;Helstroff;535;16;551 +57313;Hémilly;143;3;146 +57314;Héming;498;2;500 +57315;Henridorff;701;14;715 +57316;Henriville;753;15;768 +57317;Hérange;108;4;112 +57318;Hermelange;224;5;229 +57319;Herny;508;5;513 +57320;Hertzing;190;2;192 +57321;Hesse;572;24;596 +57322;Hestroff;449;14;463 +57323;Hettange-Grande;7653;166;7819 +57324;Hilbesheim;607;21;628 +57325;Hilsprich;857;17;874 +57326;Hinckange;325;4;329 +57328;Holacourt;88;2;90 +57329;Holling;440;5;445 +57330;Holving;1290;11;1301 +57331;Hombourg-Budange;556;10;566 +57332;Hombourg-Haut;6433;66;6499 +57333;Hommarting;850;24;874 +57334;Hommert;337;10;347 +57335;Honskirch;224;4;228 +57336;L' Hôpital;5350;55;5405 +57337;Hoste;611;18;629 +57338;Hottviller;522;6;528 +57339;Hultehouse;364;5;369 +57340;Hundling;1350;20;1370 +57341;Hunting;721;18;739 +57342;Ibigny;97;1;98 +57343;Illange;1870;30;1900 +57344;Imling;724;9;733 +57345;Inglange;441;25;466 +57346;Insming;584;23;607 +57347;Insviller;177;3;180 +57348;Ippling;785;17;802 +57349;Jallaucourt;166;0;166 +57350;Jouy-aux-Arches;1472;22;1494 +57351;Jury;1036;22;1058 +57352;Jussy;443;17;460 +57353;Juvelize;71;1;72 +57354;Juville;119;5;124 +57355;Kalhausen;837;18;855 +57356;Kanfen;1174;21;1195 +57357;Kappelkinger;398;9;407 +57358;Kédange-sur-Canner;1087;22;1109 +57359;Kemplich;168;4;172 +57360;Kerbach;1189;32;1221 +57361;Kerling-lès-Sierck;578;17;595 +57362;Kerprich-aux-Bois;165;3;168 +57364;Kirsch-lès-Sierck;308;4;312 +57365;Kirschnaumen;481;6;487 +57366;Kirviller;141;2;143 +57367;Klang;239;3;242 +57368;Knutange;3203;58;3261 +57372;Kuntzig;1314;14;1328 +57370;Kœnigsmacker;2244;41;2285 +57373;Lachambre;914;27;941 +57374;Lafrimbolle;202;6;208 +57375;Lagarde;190;1;191 +57376;Lambach;508;6;514 +57377;Landange;242;3;245 +57379;Landroff;271;1;272 +57381;Laneuveville-en-Saulnois;303;3;306 +57380;Laneuveville-lès-Lorquin;102;3;105 +57382;Langatte;559;6;565 +57383;Languimberg;173;4;177 +57384;Laning;604;18;622 +57385;Laquenexy;1143;20;1163 +57386;Laudrefang;341;7;348 +57387;Laumesfeld;284;1;285 +57388;Launstroff;264;4;268 +57389;Lelling;472;12;484 +57390;Lemberg;1455;24;1479 +57391;Lemoncourt;70;1;71 +57392;Lemud;501;3;504 +57393;Lengelsheim;205;3;208 +57394;Léning;339;12;351 +57395;Lesse;206;4;210 +57396;Lessy;745;28;773 +57397;Ley;97;1;98 +57398;Leyviller;493;10;503 +57399;Lezey;100;4;104 +57410;Lhor;134;3;137 +57401;Lidrezing;86;1;87 +57402;Liederschiedt;122;4;126 +57403;Liéhon;114;2;116 +57404;Lindre-Basse;218;7;225 +57405;Lindre-Haute;50;1;51 +57406;Liocourt;136;7;143 +57407;Lixheim;579;6;585 +57408;Lixing-lès-Rouhling;937;19;956 +57409;Lixing-lès-Saint-Avold;682;17;699 +57411;Lommerange;301;1;302 +57412;Longeville-lès-Metz;4030;59;4089 +57413;Longeville-lès-Saint-Avold;3666;81;3747 +57414;Lorquin;1151;26;1177 +57415;Lorry-lès-Metz;1786;77;1863 +57416;Lorry-Mardigny;650;16;666 +57417;Lostroff;69;0;69 +57418;Loudrefing;322;4;326 +57419;Loupershouse;925;23;948 +57421;Loutzviller;150;3;153 +57422;Louvigny;899;11;910 +57423;Lubécourt;73;0;73 +57424;Lucy;228;2;230 +57425;Luppy;570;5;575 +57426;Luttange;892;8;900 +57427;Lutzelbourg;584;9;593 +57428;Macheren;2767;68;2835 +57430;Mainvillers;335;8;343 +57431;Maizeroy;390;3;393 +57433;Maizières-lès-Metz;11388;122;11510 +57434;Maizières-lès-Vic;496;9;505 +57436;Malaucourt-sur-Seille;123;4;127 +57437;Malling;630;14;644 +57438;Malroy;355;4;359 +57439;Manderen-Ritzing;586;13;599 +57440;Manhoué;142;3;145 +57441;Manom;2872;58;2930 +57442;Many;259;2;261 +57443;Marange-Silvange;6179;59;6238 +57444;Marange-Zondrange;341;2;343 +57445;Marieulles;703;8;711 +57446;Marimont-lès-Bénestroff;38;1;39 +57447;Marly;10104;238;10342 +57448;Marsal;282;3;285 +57449;Marsilly;579;6;585 +57451;Marthille;171;3;174 +57452;La Maxe;924;15;939 +57453;Maxstadt;316;11;327 +57454;Mécleuves;1156;23;1179 +57455;Mégange;160;1;161 +57456;Meisenthal;699;17;716 +57457;Menskirch;140;2;142 +57459;Merschweiller;248;1;249 +57460;Merten;1504;26;1530 +57461;Métairies-Saint-Quirin;266;4;270 +57462;Metting;399;7;406 +57463;Metz;116429;1824;118253 +57464;Metzeresche;949;21;970 +57465;Metzervisse;2271;53;2324 +57466;Metzing;645;11;656 +57467;Mey;267;5;272 +57468;Mittelbronn;688;10;698 +57469;Mittersheim;596;5;601 +57470;Molring;5;0;5 +57471;Momerstroff;285;3;288 +57472;Moncheux;149;2;151 +57473;Moncourt;70;2;72 +57474;Mondelange;5665;73;5738 +57475;Mondorff;518;14;532 +57476;Monneren;420;6;426 +57477;Montbronn;1630;46;1676 +57478;Montdidier;80;0;80 +57479;Montenach;458;12;470 +57480;Montigny-lès-Metz;21819;374;22193 +57481;Montois-la-Montagne;2710;19;2729 +57483;Morhange;3445;82;3527 +57484;Morsbach;2686;29;2715 +57485;Morville-lès-Vic;123;1;124 +57486;Morville-sur-Nied;119;1;120 +57487;Moulins-lès-Metz;5055;62;5117 +57488;Moussey;561;8;569 +57489;Mouterhouse;308;6;314 +57490;Moyenvic;364;4;368 +57491;Moyeuvre-Grande;7823;71;7894 +57492;Moyeuvre-Petite;462;2;464 +57493;Mulcey;211;1;212 +57494;Munster;249;0;249 +57495;Narbéfontaine;118;1;119 +57496;Nébing;345;5;350 +57497;Nelling;263;9;272 +57498;Neufchef;2580;53;2633 +57499;Neufgrange;1389;31;1420 +57500;Neufmoulins;43;0;43 +57501;Neufvillage;36;0;36 +57502;Neunkirchen-lès-Bouzonville;339;12;351 +57504;Niderhoff;285;2;287 +57505;Niderviller;1218;22;1240 +57506;Niederstinzel;257;1;258 +57507;Niedervisse;257;3;260 +57508;Nilvange;4725;42;4767 +57509;Nitting;464;3;467 +57510;Noisseville;1031;11;1042 +57511;Norroy-le-Veneur;1002;23;1025 +57512;Nouilly;723;7;730 +57513;Nousseviller-lès-Bitche;141;1;142 +57514;Nousseviller-Saint-Nabor;1210;31;1241 +57515;Novéant-sur-Moselle;1797;26;1823 +57516;Oberdorff;343;10;353 +57517;Obergailbach;304;3;307 +57518;Oberstinzel;340;9;349 +57519;Obervisse;159;3;162 +57520;Obreck;36;2;38 +57482;Ogy-Montoy-Flanville;1724;34;1758 +57524;Ommeray;127;2;129 +57525;Oriocourt;57;1;58 +57526;Ormersviller;390;2;392 +57527;Orny;358;4;362 +57528;Oron;94;1;95 +57529;Ottange;3043;65;3108 +57530;Ottonville;445;6;451 +57531;Oudrenne;740;14;754 +57532;Pagny-lès-Goin;238;4;242 +57533;Pange;871;22;893 +57534;Peltre;1856;120;1976 +57535;Petit-Réderching;1488;37;1525 +57536;Petit-Tenquin;229;5;234 +57537;Petite-Rosselle;6338;94;6432 +57538;Pettoncourt;291;2;293 +57539;Pévange;51;3;54 +57540;Phalsbourg;4728;258;4986 +57541;Philippsbourg;611;14;625 +57542;Piblange;1011;11;1022 +57543;Pierrevillers;1509;24;1533 +57544;Plaine-de-Walsch;630;16;646 +57545;Plappeville;1998;74;2072 +57546;Plesnois;826;29;855 +57547;Pommérieux;695;9;704 +57548;Pontoy;466;2;468 +57549;Pontpierre;724;14;738 +57550;Porcelette;2485;66;2551 +57551;Postroff;211;0;211 +57552;Pouilly;614;8;622 +57553;Pournoy-la-Chétive;637;6;643 +57554;Pournoy-la-Grasse;629;19;648 +57555;Prévocourt;110;0;110 +57556;Puttelange-aux-Lacs;3025;45;3070 +57557;Puttelange-lès-Thionville;974;23;997 +57558;Puttigny;85;0;85 +57559;Puzieux;187;5;192 +57560;Racrange;605;12;617 +57561;Rahling;766;20;786 +57562;Ranguevaux;832;18;850 +57563;Raville;268;2;270 +57564;Réchicourt-le-Château;541;8;549 +57565;Rédange;994;13;1007 +57566;Réding;2384;66;2450 +57567;Rémelfang;165;1;166 +57568;Rémelfing;1405;29;1434 +57569;Rémeling;308;6;314 +57570;Rémering;436;10;446 +57571;Rémering-lès-Puttelange;1087;30;1117 +57572;Rémilly;2016;103;2119 +57573;Réning;133;3;136 +57575;Retonfey;1384;15;1399 +57576;Rettel;764;65;829 +57577;Reyersviller;367;8;375 +57578;Rezonville-Vionville;503;6;509 +57579;Rhodes;122;1;123 +57580;Riche;188;3;191 +57581;Richeling;337;9;346 +57582;Richemont;2075;40;2115 +57583;Richeval;133;2;135 +57584;Rimling;650;16;666 +57586;Rochonvillers;188;2;190 +57587;Rodalbe;253;5;258 +57588;Rodemack;1240;31;1271 +57589;Rohrbach-lès-Bitche;2283;49;2332 +57590;Rolbing;249;5;254 +57591;Rombas;9882;111;9993 +57592;Romelfing;356;2;358 +57593;Roncourt;1003;10;1013 +57594;Roppeviller;105;3;108 +57595;Rorbach-lès-Dieuze;51;1;52 +57596;Rosbruck;764;11;775 +57597;Rosselange;2693;18;2711 +57598;Rouhling;2060;53;2113 +57599;Roupeldange;369;9;378 +57600;Roussy-le-Village;1369;24;1393 +57601;Rozérieulles;1383;43;1426 +57602;Rurange-lès-Thionville;2494;46;2540 +57603;Russange;1285;17;1302 +57604;Rustroff;612;5;617 +57605;Sailly-Achâtel;292;5;297 +57606;Saint-Avold;15483;377;15860 +57609;Saint-Epvre;177;0;177 +57610;Saint-François-Lacroix;302;6;308 +57611;Saint-Georges;198;5;203 +57612;Saint-Hubert;233;5;238 +57613;Saint-Jean-de-Bassel;350;3;353 +57614;Saint-Jean-Kourtzerode;714;4;718 +57615;Saint-Jean-Rohrbach;966;12;978 +57616;Saint-Julien-lès-Metz;3421;83;3504 +57617;Saint-Jure;295;6;301 +57618;Saint-Louis;665;20;685 +57619;Saint-Louis-lès-Bitche;490;10;500 +57621;Saint-Médard;100;1;101 +57622;Saint-Privat-la-Montagne;1839;18;1857 +57623;Saint-Quirin;722;45;767 +57607;Sainte-Barbe;745;10;755 +57620;Sainte-Marie-aux-Chênes;4216;59;4275 +57624;Sainte-Ruffine;563;28;591 +57625;Salonnes;189;2;191 +57626;Sanry-lès-Vigy;528;8;536 +57627;Sanry-sur-Nied;291;3;294 +57628;Sarralbe;4555;103;4658 +57629;Sarraltroff;748;8;756 +57630;Sarrebourg;12045;306;12351 +57631;Sarreguemines;20783;449;21232 +57633;Sarreinsming;1268;30;1298 +57634;Saulny;1428;35;1463 +57635;Schalbach;343;7;350 +57636;Schmittviller;322;12;334 +57637;Schneckenbusch;303;9;312 +57639;Schorbach;540;9;549 +57640;Schwerdorff;473;14;487 +57641;Schweyen;315;4;319 +57638;Schœneck;2570;41;2611 +57642;Scy-Chazelles;2676;49;2725 +57643;Secourt;196;5;201 +57644;Seingbouse;1822;43;1865 +57645;Semécourt;995;9;1004 +57647;Serémange-Erzange;4273;55;4328 +57648;Servigny-lès-Raville;484;4;488 +57649;Servigny-lès-Sainte-Barbe;466;4;470 +57650;Sierck-les-Bains;1755;14;1769 +57651;Siersthal;665;11;676 +57652;Sillegny;478;5;483 +57653;Silly-en-Saulnois;33;1;34 +57654;Silly-sur-Nied;693;12;705 +57655;Solgne;1109;64;1173 +57656;Sorbey;372;6;378 +57657;Sotzeling;20;0;20 +57658;Soucht;1049;18;1067 +57659;Spicheren;3224;57;3281 +57660;Stiring-Wendel;11618;124;11742 +57767;Stuckange;1073;27;1100 +57661;Sturzelbronn;176;3;179 +57662;Suisse;103;5;108 +57663;Talange;7707;172;7879 +57664;Tarquimpol;62;1;63 +57665;Tenteling;1077;39;1116 +57666;Terville;7025;91;7116 +57667;Téterchen;819;7;826 +57668;Teting-sur-Nied;1305;35;1340 +57669;Théding;2501;46;2547 +57670;Thicourt;142;2;144 +57671;Thimonville;155;0;155 +57672;Thionville;40701;787;41488 +57673;Thonville;47;0;47 +57674;Tincry;174;5;179 +57675;Torcheville;110;1;111 +57676;Tragny;97;2;99 +57677;Trémery;1063;19;1082 +57678;Tressange;2132;31;2163 +57679;Tritteling-Redlach;533;4;537 +57680;Troisfontaines;1272;27;1299 +57681;Tromborn;357;5;362 +57682;Turquestein-Blancrupt;14;0;14 +57683;Uckange;6818;45;6863 +57684;Vahl-Ebersing;514;10;524 +57685;Vahl-lès-Bénestroff;148;2;150 +57686;Vahl-lès-Faulquemont;256;4;260 +57270;Val-de-Bride;588;12;600 +57267;Le Val-de-Guéblange;856;19;875 +57687;Vallerange;209;4;213 +57689;Valmestroff;308;5;313 +57690;Valmont;3131;70;3201 +57691;Valmunster;94;4;98 +57692;Vannecourt;79;0;79 +57693;Vantoux;851;19;870 +57694;Vany;410;6;416 +57695;Varize-Vaudoncourt;552;9;561 +57696;Varsberg;951;26;977 +57697;Vasperviller;316;9;325 +57698;Vatimont;324;0;324 +57700;Vaudreching;532;8;540 +57701;Vaux;798;24;822 +57702;Vaxy;166;0;166 +57703;Veckersviller;231;5;236 +57704;Veckring;670;15;685 +57705;Velving;205;5;210 +57706;Vergaville;578;15;593 +57707;Vernéville;616;8;624 +57708;Verny;1950;90;2040 +57709;Vescheim;321;7;328 +57711;Vibersviller;454;7;461 +57712;Vic-sur-Seille;1295;105;1400 +57713;Vieux-Lixheim;256;8;264 +57715;Vigny;366;3;369 +57716;Vigy;1716;33;1749 +57717;Viller;201;4;205 +57718;Villers-Stoncourt;222;3;225 +57719;Villers-sur-Nied;73;1;74 +57720;Villing;494;11;505 +57721;Vilsberg;357;11;368 +57723;Virming;296;6;302 +57724;Vitry-sur-Orne;3019;34;3053 +57725;Vittersbourg;358;7;365 +57726;Vittoncourt;375;3;378 +57727;Viviers;123;1;124 +57728;Voimhaut;253;3;256 +57730;Volmerange-lès-Boulay;559;11;570 +57731;Volmerange-les-Mines;2189;48;2237 +57732;Volmunster;793;21;814 +57733;Volstroff;1965;28;1993 +57734;Voyer;452;11;463 +57736;Vry;595;9;604 +57737;Vulmont;30;1;31 +57749;Vœlfling-lès-Bouzonville;155;6;161 +57738;Waldhouse;401;6;407 +57739;Waldweistroff;494;2;496 +57740;Waldwisse;824;12;836 +57741;Walschbronn;497;16;513 +57742;Walscheid;1536;42;1578 +57743;Waltembourg;243;7;250 +57745;Wiesviller;968;21;989 +57746;Willerwald;1544;36;1580 +57747;Wintersbourg;265;7;272 +57748;Wittring;790;15;805 +57751;Woippy;14214;139;14353 +57752;Woustviller;3175;59;3234 +57753;Wuisse;63;4;67 +57750;Wœlfling-lès-Sarreguemines;739;26;765 +57754;Xanrey;116;0;116 +57755;Xocourt;93;1;94 +57756;Xouaxange;305;4;309 +57757;Yutz;16537;254;16791 +57759;Zarbeling;58;2;60 +57760;Zetting;825;24;849 +57761;Zilling;274;4;278 +57762;Zimming;712;6;718 +57763;Zommange;44;2;46 +57764;Zoufftgen;1222;14;1236 +57521;Œting;2679;52;2731 +58001;Achun;162;3;165 +58002;Alligny-Cosne;877;18;895 +58003;Alligny-en-Morvan;613;7;620 +58004;Alluy;386;8;394 +58005;Amazy;228;1;229 +58006;Anlezy;246;5;251 +58007;Annay;339;5;344 +58008;Anthien;177;5;182 +58009;Arbourse;127;1;128 +58010;Arleuf;746;11;757 +58011;Armes;283;6;289 +58012;Arquian;581;13;594 +58013;Arthel;95;1;96 +58014;Arzembouy;68;1;69 +58015;Asnan;125;2;127 +58016;Asnois;146;3;149 +58017;Aunay-en-Bazois;228;5;233 +58018;Authiou;44;0;44 +58019;Avrée;80;1;81 +58020;Avril-sur-Loire;268;4;272 +58021;Azy-le-Vif;206;6;212 +58023;Bazoches;177;3;180 +58024;Bazolles;279;6;285 +58025;Béard;172;8;180 +58026;Beaulieu;159;10;169 +58027;Beaumont-la-Ferrière;123;3;126 +58028;Beaumont-Sardolles;115;4;119 +58029;Beuvron;79;0;79 +58030;Biches;287;11;298 +58031;Billy-Chevannes;308;4;312 +58032;Billy-sur-Oisy;370;8;378 +58033;Bitry;305;8;313 +58034;Blismes;180;6;186 +58035;Bona;313;2;315 +58036;Bouhy;460;8;468 +58037;Brassy;611;36;647 +58038;Breugnon;169;5;174 +58039;Brèves;243;2;245 +58040;Brinay;144;4;148 +58041;Brinon-sur-Beuvron;181;5;186 +58042;Bulcy;129;5;134 +58043;Bussy-la-Pesle;56;0;56 +58044;La Celle-sur-Loire;830;11;841 +58045;La Celle-sur-Nièvre;160;0;160 +58046;Cercy-la-Tour;1746;26;1772 +58047;Cervon;650;14;664 +58048;Cessy-les-Bois;94;3;97 +58049;Chalaux;86;2;88 +58050;Challement;51;2;53 +58051;Challuy;1537;133;1670 +58052;Champallement;49;3;52 +58053;Champlemy;332;7;339 +58054;Champlin;39;1;40 +58055;Champvert;797;17;814 +58056;Champvoux;309;9;318 +58057;Chantenay-Saint-Imbert;1172;20;1192 +58058;La Chapelle-Saint-André;315;5;320 +58059;La Charité-sur-Loire;4901;71;4972 +58060;Charrin;609;9;618 +58061;Chasnay;116;3;119 +58063;Château-Chinon (Campagne);548;10;558 +58062;Château-Chinon (Ville);1964;390;2354 +58064;Châteauneuf-Val-de-Bargis;530;14;544 +58065;Châtillon-en-Bazois;897;17;914 +58066;Châtin;88;0;88 +58067;Chaulgnes;1505;23;1528 +58068;Chaumard;208;5;213 +58069;Chaumot;158;3;161 +58070;Chazeuil;59;2;61 +58071;Chevannes-Changy;132;6;138 +58072;Chevenon;590;11;601 +58073;Chevroches;125;5;130 +58074;Chiddes;334;5;339 +58075;Chitry-les-Mines;208;4;212 +58076;Chougny;76;1;77 +58077;Ciez;369;6;375 +58078;Cizely;61;0;61 +58079;Clamecy;3759;161;3920 +58080;La Collancelle;175;1;176 +58081;Colméry;321;6;327 +58082;Corancy;301;4;305 +58083;Corbigny;1482;108;1590 +58084;Corvol-d'Embernard;87;3;90 +58085;Corvol-l'Orgueilleux;800;8;808 +58086;Cosne-Cours-sur-Loire;9874;257;10131 +58087;Cossaye;718;8;726 +58088;Coulanges-lès-Nevers;3629;84;3713 +58089;Couloutre;191;7;198 +58090;Courcelles;217;3;220 +58092;Crux-la-Ville;405;9;414 +58093;Cuncy-lès-Varzy;127;2;129 +58094;Dampierre-sous-Bouhy;457;7;464 +58095;Decize;5393;190;5583 +58096;Devay;493;9;502 +58097;Diennes-Aubigny;94;1;95 +58098;Dirol;116;4;120 +58099;Dommartin;170;4;174 +58101;Dompierre-sur-Nièvre;191;2;193 +58102;Donzy;1583;27;1610 +58103;Dornecy;481;8;489 +58104;Dornes;1430;26;1456 +58105;Druy-Parigny;320;6;326 +58106;Dun-les-Places;351;4;355 +58107;Dun-sur-Grandry;156;2;158 +58108;Empury;83;1;84 +58109;Entrains-sur-Nohain;769;16;785 +58110;Epiry;238;2;240 +58111;Fâchin;110;1;111 +58112;La Fermeté;655;7;662 +58113;Fertrève;101;3;104 +58114;Fléty;103;6;109 +58115;Fleury-sur-Loire;229;5;234 +58116;Flez-Cuzy;134;2;136 +58117;Fourchambault;4229;58;4287 +58118;Fours;645;7;652 +58119;Frasnay-Reugny;88;4;92 +58120;Gâcogne;245;0;245 +58121;Garchizy;3726;45;3771 +58122;Garchy;427;8;435 +58123;Germenay;145;4;149 +58124;Germigny-sur-Loire;769;9;778 +58125;Gien-sur-Cure;96;2;98 +58126;Gimouille;459;7;466 +58127;Giry;195;2;197 +58128;Glux-en-Glenne;93;0;93 +58129;Gouloux;181;6;187 +58130;Grenois;97;2;99 +58131;Guérigny;2514;40;2554 +58132;Guipy;240;22;262 +58133;Héry;74;3;77 +58134;Imphy;3345;43;3388 +58135;Isenay;98;0;98 +58136;Jailly;64;2;66 +58137;Lamenay-sur-Loire;61;0;61 +58138;Langeron;366;10;376 +58139;Lanty;122;0;122 +58140;Larochemillay;231;4;235 +58141;Lavault-de-Frétoy;66;0;66 +58142;Limanton;240;4;244 +58143;Limon;148;5;153 +58144;Livry;700;9;709 +58145;Lormes;1288;29;1317 +58146;Lucenay-lès-Aix;982;18;1000 +58147;Lurcy-le-Bourg;287;5;292 +58148;Luthenay-Uxeloup;625;13;638 +58149;Luzy;1980;46;2026 +58150;Lys;109;6;115 +58151;La Machine;3343;52;3395 +58152;Magny-Cours;1393;28;1421 +58153;Magny-Lormes;74;2;76 +58154;La Maison-Dieu;121;1;122 +58155;La Marche;565;15;580 +58156;Marcy;153;4;157 +58157;Marigny-l'Église;293;17;310 +58159;Marigny-sur-Yonne;206;7;213 +58158;Mars-sur-Allier;303;7;310 +58160;Marzy;3672;198;3870 +58161;Maux;142;0;142 +58162;Menestreau;113;1;114 +58163;Menou;181;1;182 +58164;Mesves-sur-Loire;690;33;723 +58165;Metz-le-Comte;162;7;169 +58166;Mhère;230;1;231 +58168;Millay;446;6;452 +58169;Moissy-Moulinot;18;3;21 +58170;Monceaux-le-Comte;122;2;124 +58175;Mont-et-Marré;163;1;164 +58172;Montambert;123;2;125 +58171;Montapas;288;2;290 +58173;Montaron;161;2;163 +58174;Montenoison;121;1;122 +58176;Montigny-aux-Amognes;618;22;640 +58177;Montigny-en-Morvan;290;1;291 +58178;Montigny-sur-Canne;152;3;155 +58179;Montreuillon;261;7;268 +58180;Montsauche-les-Settons;522;3;525 +58181;Moraches;142;5;147 +58182;Moulins-Engilbert;1445;23;1468 +58183;Mouron-sur-Yonne;96;1;97 +58184;Moussy;106;0;106 +58185;Moux-en-Morvan;538;4;542 +58186;Murlin;92;2;94 +58187;Myennes;532;6;538 +58188;Nannay;117;3;120 +58189;Narcy;513;4;517 +58190;Neuffontaines;104;3;107 +58191;Neuilly;118;2;120 +58192;Neuville-lès-Decize;230;9;239 +58193;Neuvy-sur-Loire;1438;30;1468 +58194;Nevers;32990;1107;34097 +58195;La Nocle-Maulaix;279;2;281 +58196;Nolay;357;3;360 +58197;Nuars;156;1;157 +58198;Oisy;305;5;310 +58199;Onlay;148;3;151 +58200;Ouagne;153;1;154 +58201;Oudan;144;3;147 +58202;Ougny;25;0;25 +58203;Oulon;64;2;66 +58205;Ouroux-en-Morvan;617;8;625 +58206;Parigny-la-Rose;41;0;41 +58207;Parigny-les-Vaux;960;36;996 +58208;Pazy;305;10;315 +58209;Perroy;160;4;164 +58210;Planchez;301;4;305 +58211;Poil;138;2;140 +58212;Poiseux;334;4;338 +58213;Pougny;462;14;476 +58214;Pougues-les-Eaux;2388;53;2441 +58215;Pouilly-sur-Loire;1636;25;1661 +58216;Pouques-Lormes;160;3;163 +58217;Pousseaux;194;8;202 +58218;Prémery;1838;31;1869 +58219;Préporché;206;4;210 +58220;Raveau;673;12;685 +58221;Rémilly;152;2;154 +58222;Rix;159;1;160 +58223;Rouy;613;8;621 +58224;Ruages;93;4;97 +58225;Saincaize-Meauce;376;7;383 +58226;Saint-Agnan;137;2;139 +58227;Saint-Amand-en-Puisaye;1258;26;1284 +58228;Saint-Andelain;519;4;523 +58229;Saint-André-en-Morvan;310;5;315 +58230;Saint-Aubin-des-Chaumes;68;0;68 +58231;Saint-Aubin-les-Forges;402;7;409 +58232;Saint-Benin-d'Azy;1278;15;1293 +58233;Saint-Benin-des-Bois;168;7;175 +58234;Saint-Bonnot;138;1;139 +58235;Saint-Brisson;264;3;267 +58237;Saint-Didier;28;4;32 +58238;Saint-Éloi;2146;45;2191 +58239;Saint-Firmin;175;2;177 +58240;Saint-Franchy;74;3;77 +58241;Saint-Germain-Chassenay;323;5;328 +58242;Saint-Germain-des-Bois;120;0;120 +58243;Saint-Gratien-Savigny;113;4;117 +58244;Saint-Hilaire-en-Morvan;220;7;227 +58245;Saint-Hilaire-Fontaine;172;5;177 +58246;Saint-Honoré-les-Bains;744;14;758 +58247;Saint-Jean-aux-Amognes;492;7;499 +58248;Saint-Laurent-l'Abbaye;215;4;219 +58249;Saint-Léger-de-Fougeret;373;3;376 +58250;Saint-Léger-des-Vignes;1886;46;1932 +58251;Saint-Loup;468;7;475 +58252;Saint-Malo-en-Donziois;128;3;131 +58254;Saint-Martin-d'Heuille;596;13;609 +58255;Saint-Martin-du-Puy;276;5;281 +58256;Saint-Martin-sur-Nohain;371;18;389 +58257;Saint-Maurice;62;0;62 +58258;Saint-Ouen-sur-Loire;561;6;567 +58259;Saint-Parize-en-Viry;150;3;153 +58260;Saint-Parize-le-Châtel;1301;29;1330 +58261;Saint-Père;1097;21;1118 +58262;Saint-Péreuse;219;10;229 +58263;Saint-Pierre-du-Mont;190;4;194 +58264;Saint-Pierre-le-Moûtier;1956;21;1977 +58265;Saint-Quentin-sur-Nohain;100;3;103 +58266;Saint-Révérien;160;0;160 +58267;Saint-Saulge;738;80;818 +58268;Saint-Seine;207;5;212 +58269;Saint-Sulpice;399;7;406 +58270;Saint-Vérain;340;6;346 +58236;Sainte-Colombe-des-Bois;132;2;134 +58253;Sainte-Marie;80;4;84 +58271;Saizy;189;3;192 +58272;Sardy-lès-Épiry;113;4;117 +58273;Sauvigny-les-Bois;1458;40;1498 +58274;Savigny-Poil-Fol;124;2;126 +58275;Saxi-Bourdon;299;4;303 +58276;Sémelay;234;3;237 +58277;Sermages;188;8;196 +58278;Sermoise-sur-Loire;1514;71;1585 +58279;Sichamps;194;2;196 +58280;Sougy-sur-Loire;625;17;642 +58281;Suilly-la-Tour;600;14;614 +58282;Surgy;328;20;348 +58283;Taconnay;77;3;80 +58284;Talon;40;1;41 +58285;Tamnay-en-Bazois;167;5;172 +58286;Tannay;585;11;596 +58287;Tazilly;198;3;201 +58288;Teigny;103;2;105 +58289;Ternant;192;0;192 +58290;Thaix;50;1;51 +58291;Thianges;171;0;171 +58292;Tintury;183;0;183 +58293;Toury-Lurcy;430;8;438 +58294;Toury-sur-Jour;120;2;122 +58295;Tracy-sur-Loire;970;14;984 +58296;Tresnay;148;0;148 +58297;Trois-Vèvres;240;1;241 +58298;Tronsanges;395;9;404 +58299;Trucy-l'Orgueilleux;220;3;223 +58300;Urzy;1775;35;1810 +58301;Vandenesse;309;5;314 +58302;Varennes-lès-Narcy;955;5;960 +58303;Varennes-Vauzelles;9298;176;9474 +58304;Varzy;1215;197;1412 +58305;Vauclaix;134;2;136 +58204;Vaux d'Amognes;543;8;551 +58306;Verneuil;296;9;305 +58307;Vielmanay;183;3;186 +58308;Vignol;62;0;62 +58309;Villapourçon;415;8;423 +58311;Ville-Langy;252;5;257 +58310;Villiers-le-Sec;48;1;49 +58312;Villiers-sur-Yonne;274;9;283 +58313;Vitry-Laché;82;3;85 +59001;Abancourt;463;13;476 +59002;Abscon;4447;36;4483 +59003;Aibes;370;5;375 +59004;Aix-en-Pévèle;1220;14;1234 +59005;Allennes-les-Marais;3460;60;3520 +59006;Amfroipret;223;8;231 +59007;Anhiers;898;10;908 +59008;Aniche;10244;104;10348 +59010;Anneux;272;2;274 +59011;Annœullin;10428;106;10534 +59012;Anor;3220;47;3267 +59013;Anstaing;1469;16;1485 +59014;Anzin;13305;95;13400 +59015;Arleux;3219;25;3244 +59016;Armbouts-Cappel;2281;48;2329 +59017;Armentières;24882;359;25241 +59018;Arnèke;1617;16;1633 +59019;Artres;1057;12;1069 +59021;Assevent;1825;18;1843 +59022;Attiches;2275;32;2307 +59023;Aubencheul-au-Bac;535;7;542 +59024;Auberchicourt;4448;32;4480 +59025;Aubers;1651;21;1672 +59026;Aubigny-au-Bac;1178;18;1196 +59027;Aubry-du-Hainaut;1679;14;1693 +59028;Auby;7274;41;7315 +59029;Auchy-lez-Orchies;1521;21;1542 +59031;Audignies;366;4;370 +59032;Aulnoy-lez-Valenciennes;7341;67;7408 +59033;Aulnoye-Aymeries;8811;238;9049 +59034;Avelin;2690;34;2724 +59035;Avesnelles;2495;30;2525 +59038;Avesnes-le-Sec;1458;16;1474 +59037;Avesnes-les-Aubert;3640;34;3674 +59036;Avesnes-sur-Helpe;4495;147;4642 +59039;Awoingt;817;17;834 +59041;Bachant;2324;25;2349 +59042;Bachy;1702;23;1725 +59043;Bailleul;14769;270;15039 +59044;Baisieux;4765;48;4813 +59045;Baives;167;2;169 +59046;Bambecque;770;10;780 +59047;Banteux;344;2;346 +59048;Bantigny;510;11;521 +59049;Bantouzelle;426;6;432 +59050;Bas-Lieu;349;8;357 +59051;La Bassée;6402;53;6455 +59052;Bauvin;5180;43;5223 +59053;Bavay;3326;78;3404 +59054;Bavinchove;972;9;981 +59055;Bazuel;525;10;535 +59056;Beaucamps-Ligny;856;23;879 +59057;Beaudignies;564;14;578 +59058;Beaufort;1000;13;1013 +59059;Beaumont-en-Cambrésis;446;4;450 +59060;Beaurain;231;3;234 +59061;Beaurepaire-sur-Sambre;260;1;261 +59062;Beaurieux;165;0;165 +59063;Beauvois-en-Cambrésis;2072;25;2097 +59064;Bellaing;1239;12;1251 +59065;Bellignies;827;9;836 +59066;Bérelles;146;3;149 +59067;Bergues;3653;47;3700 +59068;Berlaimont;3130;36;3166 +59069;Bermerain;723;11;734 +59070;Bermeries;373;4;377 +59071;Bersée;2230;47;2277 +59072;Bersillies;252;6;258 +59073;Berthen;551;13;564 +59074;Bertry;2177;37;2214 +59075;Béthencourt;749;11;760 +59076;Bettignies;310;5;315 +59077;Bettrechies;252;4;256 +59078;Beugnies;635;6;641 +59079;Beuvrages;6740;34;6774 +59080;Beuvry-la-Forêt;2758;28;2786 +59081;Bévillers;562;5;567 +59082;Bierne;1831;31;1862 +59083;Bissezeele;247;2;249 +59084;Blaringhem;2069;31;2100 +59085;Blécourt;306;6;312 +59086;Boeschepe;2183;31;2214 +59087;Boëseghem;748;13;761 +59088;Bois-Grenier;1612;22;1634 +59089;Bollezeele;1435;30;1465 +59090;Bondues;10103;181;10284 +59091;Borre;591;12;603 +59092;Bouchain;3952;39;3991 +59093;Boulogne-sur-Helpe;339;4;343 +59094;Bourbourg;7097;54;7151 +59096;Bourghelles;1664;38;1702 +59097;Boursies;394;5;399 +59098;Bousbecque;4831;46;4877 +59099;Bousies;1738;13;1751 +59100;Bousignies;333;2;335 +59101;Bousignies-sur-Roc;402;2;404 +59102;Boussières-en-Cambrésis;422;4;426 +59103;Boussières-sur-Sambre;524;9;533 +59104;Boussois;3231;21;3252 +59105;Bouvignies;1535;26;1561 +59106;Bouvines;775;17;792 +59107;Bray-Dunes;4483;44;4527 +59108;Briastre;748;4;752 +59109;Brillon;738;9;747 +59110;Brouckerque;1375;28;1403 +59111;Broxeele;403;1;404 +59112;Bruay-sur-l'Escaut;11449;45;11494 +59113;Bruille-lez-Marchiennes;1345;7;1352 +59114;Bruille-Saint-Amand;1671;16;1687 +59115;Brunémont;711;4;715 +59116;Bry;417;12;429 +59117;Bugnicourt;1030;9;1039 +59118;Busigny;2482;29;2511 +59119;Buysscheure;583;9;592 +59120;Caëstre;1980;31;2011 +59121;Cagnoncles;611;7;618 +59122;Cambrai;32558;642;33200 +59123;Camphin-en-Carembault;1660;20;1680 +59124;Camphin-en-Pévèle;2452;42;2494 +59125;Cantaing-sur-Escaut;399;10;409 +59126;Cantin;1577;12;1589 +59127;Capelle;153;5;158 +59128;Capinghem;2495;29;2524 +59130;Cappelle-Brouck;1166;19;1185 +59129;Cappelle-en-Pévèle;2232;26;2258 +59131;Cappelle-la-Grande;7899;74;7973 +59132;Carnières;1073;14;1087 +59133;Carnin;1008;18;1026 +59134;Cartignies;1253;10;1263 +59135;Cassel;2289;101;2390 +59136;Le Cateau-Cambrésis;6933;138;7071 +59137;Catillon-sur-Sambre;840;7;847 +59138;Cattenières;670;14;684 +59139;Caudry;14591;148;14739 +59140;Caullery;454;11;465 +59141;Cauroir;570;15;585 +59142;Cerfontaine;688;4;692 +59143;La Chapelle-d'Armentières;8590;93;8683 +59144;Château-l'Abbaye;874;10;884 +59145;Chemy;768;12;780 +59146;Chéreng;2990;42;3032 +59147;Choisies;52;1;53 +59148;Clairfayts;371;1;372 +59149;Clary;1092;16;1108 +59150;Cobrieux;521;11;532 +59151;Colleret;1615;17;1632 +59152;Comines;12358;88;12446 +59153;Condé-sur-l'Escaut;9698;67;9765 +59155;Coudekerque-Branche;21134;294;21428 +59156;Courchelettes;2809;31;2840 +59157;Cousolre;2270;39;2309 +59158;Coutiches;3014;50;3064 +59159;Craywick;694;6;700 +59160;Crespin;4532;31;4563 +59161;Crèvecœur-sur-l'Escaut;744;45;789 +59162;Crochte;667;21;688 +59163;Croix;21041;276;21317 +59164;Croix-Caluyau;257;8;265 +59165;Cuincy;6435;100;6535 +59166;Curgies;1218;33;1251 +59167;Cuvillers;201;1;202 +59168;Cysoing;4968;73;5041 +59169;Damousies;193;0;193 +59170;Dechy;5324;38;5362 +59171;Dehéries;39;2;41 +59172;Denain;19825;96;19921 +59173;Deûlémont;1769;21;1790 +59174;Dimechaux;339;3;342 +59175;Dimont;314;8;322 +59176;Doignies;333;3;336 +59177;Dompierre-sur-Helpe;860;15;875 +59670;Don;1287;13;1300 +59178;Douai;39700;905;40605 +59179;Douchy-les-Mines;10558;40;10598 +59180;Le Doulieu;1478;22;1500 +59181;Dourlers;569;6;575 +59182;Drincham;250;7;257 +59183;Dunkerque;87353;1314;88667 +59184;Ebblinghem;673;10;683 +59185;Écaillon;1937;15;1952 +59186;Eccles;84;1;85 +59187;Éclaibes;292;5;297 +59188;Écuélin;140;4;144 +59189;Eecke;1219;22;1241 +59190;Élesmes;980;14;994 +59191;Élincourt;625;5;630 +59192;Émerchicourt;886;44;930 +59193;Emmerin;3172;23;3195 +59194;Englefontaine;1304;15;1319 +59195;Englos;609;9;618 +59196;Ennetières-en-Weppes;1311;20;1331 +59197;Ennevelin;2185;23;2208 +59198;Eppe-Sauvage;267;0;267 +59199;Erchin;692;12;704 +59200;Eringhem;479;6;485 +59201;Erquinghem-le-Sec;600;9;609 +59202;Erquinghem-Lys;5158;40;5198 +59203;Erre;1592;10;1602 +59204;Escarmain;470;4;474 +59205;Escaudain;9619;41;9660 +59206;Escaudœuvres;3257;29;3286 +59207;Escautpont;4192;28;4220 +59208;Escobecques;299;10;309 +59209;Esnes;679;8;687 +59210;Esquelbecq;2115;39;2154 +59211;Esquerchin;891;7;898 +59212;Estaires;6379;159;6538 +59213;Estourmel;461;7;468 +59214;Estrées;1112;21;1133 +59215;Estreux;956;19;975 +59219;Estrun;709;8;717 +59216;Eswars;352;8;360 +59217;Eth;340;7;347 +59218;Étrœungt;1319;15;1334 +59220;Faches-Thumesnil;17835;120;17955 +59221;Famars;2517;67;2584 +59222;Faumont;2172;56;2228 +59223;Le Favril;511;4;515 +59224;Féchain;1745;15;1760 +59225;Feignies;6881;97;6978 +59226;Felleries;1420;16;1436 +59227;Fenain;5385;48;5433 +59228;Férin;1455;18;1473 +59229;Féron;567;9;576 +59230;Ferrière-la-Grande;5301;49;5350 +59231;Ferrière-la-Petite;1066;13;1079 +59232;La Flamengrie;420;4;424 +59233;Flaumont-Waudrechies;382;9;391 +59234;Flers-en-Escrebieux;5856;40;5896 +59236;Flesquières;261;4;265 +59237;Flêtre;972;22;994 +59238;Flines-lès-Mortagne;1646;24;1670 +59239;Flines-lez-Raches;5570;89;5659 +59240;Floursies;128;1;129 +59241;Floyon;532;8;540 +59242;Fontaine-au-Bois;682;9;691 +59243;Fontaine-au-Pire;1215;18;1233 +59244;Fontaine-Notre-Dame;1780;32;1812 +59246;Forest-en-Cambrésis;565;4;569 +59247;Forest-sur-Marque;1457;19;1476 +59249;Fourmies;11727;205;11932 +59250;Fournes-en-Weppes;2220;115;2335 +59251;Frasnoy;378;4;382 +59252;Frelinghien;2415;20;2435 +59253;Fresnes-sur-Escaut;7565;43;7608 +59254;Fressain;877;12;889 +59255;Fressies;572;8;580 +59256;Fretin;3380;24;3404 +59257;Fromelles;958;14;972 +59258;Genech;2702;640;3342 +59259;Ghissignies;520;20;540 +59260;Ghyvelde;4193;61;4254 +59261;Glageon;1807;28;1835 +59262;Godewaersvelde;2051;38;2089 +59264;Gognies-Chaussée;752;10;762 +59265;Gommegnies;2301;35;2336 +59266;Gondecourt;4055;42;4097 +59267;Gonnelieu;309;4;313 +59268;La Gorgue;5635;53;5688 +59269;Gouzeaucourt;1511;28;1539 +59270;Grand-Fayt;505;7;512 +59272;Grand-Fort-Philippe;5048;47;5095 +59271;Grande-Synthe;22966;191;23157 +59273;Gravelines;11166;220;11386 +59274;La Groise;481;4;485 +59275;Gruson;1309;38;1347 +59276;Guesnain;4677;36;4713 +59277;Gussignies;334;4;338 +59263;Gœulzin;1026;25;1051 +59278;Hallennes-lez-Haubourdin;4436;35;4471 +59279;Halluin;20800;127;20927 +59280;Hamel;786;9;795 +59281;Hantay;1304;12;1316 +59282;Hardifort;381;10;391 +59283;Hargnies;607;10;617 +59284;Hasnon;3862;31;3893 +59285;Haspres;2739;23;2762 +59286;Haubourdin;14936;117;15053 +59287;Haucourt-en-Cambrésis;198;4;202 +59288;Haulchin;2306;29;2335 +59289;Haussy;1531;33;1564 +59290;Haut-Lieu;391;1;392 +59291;Hautmont;14574;101;14675 +59292;Haveluy;3174;6;3180 +59293;Haverskerque;1425;25;1450 +59294;Haynecourt;321;7;328 +59295;Hazebrouck;21441;558;21999 +59296;Hecq;360;10;370 +59297;Hélesmes;1975;8;1983 +59299;Hem;18617;166;18783 +59300;Hem-Lenglet;565;10;575 +59301;Hergnies;4437;33;4470 +59302;Hérin;4135;30;4165 +59303;Herlies;2399;27;2426 +59304;Herrin;421;6;427 +59305;Herzeele;1640;32;1672 +59306;Hestrud;294;4;298 +59307;Holque;896;5;901 +59310;Hon-Hergies;858;10;868 +59308;Hondeghem;951;25;976 +59309;Hondschoote;4083;84;4167 +59311;Honnechy;549;7;556 +59312;Honnecourt-sur-Escaut;794;12;806 +59313;Hordain;1396;5;1401 +59314;Hornaing;3553;23;3576 +59315;Houdain-lez-Bavay;875;9;884 +59316;Houplin-Ancoisne;3409;45;3454 +59317;Houplines;7805;94;7899 +59318;Houtkerque;994;8;1002 +59319;Hoymille;3214;203;3417 +59320;Illies;1624;11;1635 +59321;Inchy;741;5;746 +59322;Iwuy;3348;30;3378 +59323;Jenlain;1137;26;1163 +59324;Jeumont;10159;126;10285 +59325;Jolimetz;867;16;883 +59326;Killem;1116;20;1136 +59327;Lallaing;6231;43;6274 +59328;Lambersart;27649;402;28051 +59329;Lambres-lez-Douai;5125;101;5226 +59330;Landas;2399;42;2441 +59331;Landrecies;3483;107;3590 +59332;Lannoy;1773;7;1780 +59333;Larouillies;252;9;261 +59334;Lauwin-Planque;1679;24;1703 +59335;Lecelles;2810;54;2864 +59336;Lécluse;1372;15;1387 +59337;Lederzeele;676;15;691 +59338;Ledringhem;661;27;688 +59339;Leers;9473;79;9552 +59340;Leffrinckoucke;4262;96;4358 +59341;Lesdain;417;7;424 +59343;Lesquin;8259;73;8332 +59344;Leval;2455;10;2465 +59345;Lewarde;2425;22;2447 +59342;Lez-Fontaine;229;4;233 +59346;Lezennes;3104;24;3128 +59347;Liessies;533;16;549 +59348;Lieu-Saint-Amand;1349;11;1360 +59349;Ligny-en-Cambrésis;1894;29;1923 +59350;Lille;232787;2055;234842 +59351;Limont-Fontaine;563;6;569 +59352;Linselles;8371;98;8469 +59353;Locquignol;374;2;376 +59354;Loffre;729;14;743 +59356;Lompret;2299;53;2352 +59357;La Longueville;2097;32;2129 +59358;Looberghe;1178;22;1200 +59359;Loon-Plage;6193;76;6269 +59360;Loos;22233;255;22488 +59361;Lourches;3949;17;3966 +59363;Louvignies-Quesnoy;933;19;952 +59364;Louvil;826;16;842 +59365;Louvroil;6481;41;6522 +59366;Lynde;758;14;772 +59367;Lys-lez-Lannoy;13422;144;13566 +59368;La Madeleine;21173;181;21354 +59369;Maing;4112;41;4153 +59370;Mairieux;735;15;750 +59371;Le Maisnil;642;15;657 +59372;Malincourt;504;6;510 +59374;Marbaix;482;4;486 +59375;Marchiennes;4590;62;4652 +59377;Marcoing;1888;25;1913 +59378;Marcq-en-Barœul;38617;807;39424 +59379;Marcq-en-Ostrevent;736;3;739 +59381;Maresches;820;16;836 +59382;Maretz;1457;16;1473 +59383;Marly;11855;122;11977 +59384;Maroilles;1403;23;1426 +59385;Marpent;2748;31;2779 +59387;Marquette-en-Ostrevant;1873;12;1885 +59386;Marquette-lez-Lille;10376;69;10445 +59388;Marquillies;1997;23;2020 +59389;Masnières;2717;29;2746 +59390;Masny;4143;47;4190 +59391;Mastaing;865;5;870 +59392;Maubeuge;29944;314;30258 +59393;Maulde;1026;13;1039 +59394;Maurois;395;4;399 +59395;Mazinghien;304;4;308 +59396;Mecquignies;702;7;709 +59397;Merckeghem;593;12;605 +59398;Mérignies;3065;143;3208 +59399;Merris;1018;29;1047 +59400;Merville;9720;91;9811 +59401;Méteren;2314;37;2351 +59402;Millam;813;19;832 +59403;Millonfosse;715;12;727 +59406;Monceau-Saint-Waast;495;4;499 +59407;Monchaux-sur-Écaillon;541;9;550 +59408;Moncheaux;1536;18;1554 +59409;Monchecourt;2502;21;2523 +59410;Mons-en-Barœul;20782;161;20943 +59411;Mons-en-Pévèle;2134;39;2173 +59412;Montay;290;4;294 +59413;Montigny-en-Cambrésis;562;9;571 +59414;Montigny-en-Ostrevent;4801;37;4838 +59415;Montrécourt;224;1;225 +59416;Morbecque;2538;43;2581 +59418;Mortagne-du-Nord;1626;7;1633 +59419;Mouchin;1392;16;1408 +59420;Moustier-en-Fagne;59;1;60 +59421;Mouvaux;13151;188;13339 +59405;Mœuvres;465;3;468 +59422;Naves;636;9;645 +59423;Neuf-Berquin;1234;25;1259 +59424;Neuf-Mesnil;1330;5;1335 +59427;La Neuville;646;10;656 +59425;Neuville-en-Avesnois;304;8;312 +59426;Neuville-en-Ferrain;10284;66;10350 +59428;Neuville-Saint-Rémy;3803;41;3844 +59429;Neuville-sur-Escaut;2702;16;2718 +59430;Neuvilly;1113;12;1125 +59431;Nieppe;7476;83;7559 +59432;Niergnies;509;8;517 +59433;Nieurlet;937;13;950 +59434;Nivelle;1318;17;1335 +59435;Nomain;2521;35;2556 +59436;Noordpeene;788;10;798 +59437;Noyelles-lès-Seclin;873;13;886 +59438;Noyelles-sur-Escaut;803;12;815 +59439;Noyelles-sur-Sambre;278;5;283 +59440;Noyelles-sur-Selle;705;6;711 +59441;Obies;686;6;692 +59442;Obrechies;268;8;276 +59443;Ochtezeele;383;5;388 +59444;Odomez;936;12;948 +59445;Ohain;1199;17;1216 +59446;Oisy;614;8;622 +59447;Onnaing;8797;65;8862 +59448;Oost-Cappel;465;4;469 +59449;Orchies;8828;159;8987 +59450;Ors;643;8;651 +59451;Orsinval;548;3;551 +59452;Ostricourt;5372;27;5399 +59453;Oudezeele;686;9;695 +59454;Oxelaëre;519;4;523 +59455;Paillencourt;991;9;1000 +59456;Pecquencourt;6011;258;6269 +59457;Pérenchies;8424;42;8466 +59458;Péronne-en-Mélantois;908;19;927 +59461;Petit-Fayt;309;2;311 +59459;Petite-Forêt;4877;35;4912 +59462;Phalempin;4729;40;4769 +59463;Pitgam;966;12;978 +59464;Poix-du-Nord;2203;18;2221 +59465;Pommereuil;770;4;774 +59466;Pont-à-Marcq;2884;84;2968 +59467;Pont-sur-Sambre;2541;24;2565 +59468;Potelle;395;4;399 +59469;Pradelles;390;3;393 +59470;Prémesques;2130;23;2153 +59471;Préseau;1932;24;1956 +59472;Preux-au-Bois;844;9;853 +59473;Preux-au-Sart;314;7;321 +59474;Prisches;1081;22;1103 +59475;Prouvy;2282;39;2321 +59476;Proville;3163;75;3238 +59477;Provin;4234;29;4263 +59478;Quaëdypre;1095;25;1120 +59479;Quarouble;2992;28;3020 +59480;Quérénaing;886;20;906 +59481;Le Quesnoy;4934;131;5065 +59482;Quesnoy-sur-Deûle;6758;58;6816 +59483;Quiévelon;131;1;132 +59484;Quiévrechain;6366;28;6394 +59485;Quiévy;1783;20;1803 +59486;Râches;2740;32;2772 +59487;Radinghem-en-Weppes;1406;22;1428 +59488;Raillencourt-Sainte-Olle;2238;42;2280 +59489;Raimbeaucourt;4002;56;4058 +59490;Rainsars;182;2;184 +59491;Raismes;12587;75;12662 +59492;Ramillies;600;7;607 +59493;Ramousies;228;1;229 +59494;Raucourt-au-Bois;173;1;174 +59495;Recquignies;2413;22;2435 +59496;Rejet-de-Beaulieu;261;1;262 +59497;Renescure;2080;38;2118 +59498;Reumont;363;9;372 +59499;Rexpoëde;2001;33;2034 +59500;Ribécourt-la-Tour;373;5;378 +59501;Rieulay;1327;27;1354 +59502;Rieux-en-Cambrésis;1445;9;1454 +59503;Robersart;184;3;187 +59505;Rombies-et-Marchipont;760;4;764 +59506;Romeries;450;7;457 +59507;Ronchin;19220;129;19349 +59508;Roncq;13388;113;13501 +59509;Roost-Warendin;6141;51;6192 +59511;Rosult;1911;25;1936 +59512;Roubaix;96990;502;97492 +59513;Roucourt;454;7;461 +59514;Rousies;4016;55;4071 +59515;Rouvignies;655;6;661 +59516;Rubrouck;939;18;957 +59517;Les Rues-des-Vignes;801;18;819 +59518;Ruesnes;450;7;457 +59519;Rumegies;1797;17;1814 +59520;Rumilly-en-Cambrésis;1453;25;1478 +59504;Rœulx;3830;21;3851 +59521;Sailly-lez-Cambrai;471;8;479 +59522;Sailly-lez-Lannoy;1849;36;1885 +59523;Sainghin-en-Mélantois;2760;25;2785 +59524;Sainghin-en-Weppes;5586;51;5637 +59525;Sains-du-Nord;2892;26;2918 +59526;Saint-Amand-les-Eaux;15889;152;16041 +59527;Saint-André-lez-Lille;12608;99;12707 +59528;Saint-Aubert;1570;22;1592 +59529;Saint-Aubin;363;8;371 +59530;Saint-Aybert;379;5;384 +59531;Saint-Benin;340;3;343 +59532;Saint-Georges-sur-l'Aa;307;8;315 +59533;Saint-Hilaire-lez-Cambrai;1602;14;1616 +59534;Saint-Hilaire-sur-Helpe;823;31;854 +59535;Saint-Jans-Cappel;1722;49;1771 +59537;Saint-Martin-sur-Écaillon;515;9;524 +59538;Saint-Momelin;462;12;474 +59539;Saint-Pierre-Brouck;995;17;1012 +59541;Saint-Python;1016;8;1024 +59542;Saint-Remy-Chaussée;510;13;523 +59543;Saint-Remy-du-Nord;1115;11;1126 +59544;Saint-Saulve;11207;146;11353 +59545;Saint-Souplet;1230;18;1248 +59546;Saint-Sylvestre-Cappel;1180;9;1189 +59547;Saint-Vaast-en-Cambrésis;888;10;898 +59548;Saint-Waast;636;8;644 +59536;Sainte-Marie-Cappel;877;21;898 +59549;Salesches;303;2;305 +59550;Salomé;2969;22;2991 +59551;Saméon;1672;22;1694 +59552;Sancourt;197;6;203 +59553;Santes;5724;54;5778 +59554;Sars-et-Rosières;588;6;594 +59555;Sars-Poteries;1441;17;1458 +59556;Sassegnies;269;3;272 +59557;Saultain;2398;16;2414 +59558;Saulzoir;1753;22;1775 +59559;Sebourg;1969;32;2001 +59560;Seclin;12414;93;12507 +59562;Sémeries;546;6;552 +59563;Semousies;243;3;246 +59564;La Sentinelle;3136;16;3152 +59565;Sepmeries;663;11;674 +59566;Sequedin;4712;23;4735 +59567;Séranvillers-Forenville;411;1;412 +59568;Sercus;461;5;466 +59569;Sin-le-Noble;15682;117;15799 +59570;Socx;938;36;974 +59571;Solesmes;4338;103;4441 +59572;Solre-le-Château;1815;19;1834 +59573;Solrinnes;135;0;135 +59574;Somain;12151;81;12232 +59575;Sommaing;413;4;417 +59576;Spycker;1807;27;1834 +59577;Staple;658;5;663 +59578;Steenbecque;1690;30;1720 +59579;Steene;1354;25;1379 +59580;Steenvoorde;4368;84;4452 +59581;Steenwerck;3673;53;3726 +59582;Strazeele;945;23;968 +59583;Taisnières-en-Thiérache;466;1;467 +59584;Taisnières-sur-Hon;971;12;983 +59585;Templemars;3344;24;3368 +59586;Templeuve-en-Pévèle;6059;67;6126 +59587;Terdeghem;532;14;546 +59588;Téteghem-Coudekerque-Village;8341;251;8592 +59589;Thiant;2917;23;2940 +59590;Thiennes;908;15;923 +59591;Thivencelle;846;2;848 +59592;Thumeries;3900;31;3931 +59593;Thun-l'Évêque;754;11;765 +59594;Thun-Saint-Amand;1125;12;1137 +59595;Thun-Saint-Martin;518;8;526 +59597;Tilloy-lez-Cambrai;590;21;611 +59596;Tilloy-lez-Marchiennes;518;17;535 +59598;Toufflers;3905;19;3924 +59599;Tourcoing;97368;660;98028 +59600;Tourmignies;888;14;902 +59601;Trélon;2856;68;2924 +59602;Tressin;1408;32;1440 +59603;Trith-Saint-Léger;6215;90;6305 +59604;Troisvilles;841;9;850 +59605;Uxem;1411;23;1434 +59606;Valenciennes;43336;419;43755 +59607;Vendegies-au-Bois;487;5;492 +59608;Vendegies-sur-Écaillon;1068;20;1088 +59609;Vendeville;1606;21;1627 +59610;Verchain-Maugré;1013;9;1022 +59611;Verlinghem;2460;56;2516 +59612;Vertain;517;10;527 +59613;Vicq;1492;16;1508 +59614;Viesly;1506;21;1527 +59615;Vieux-Berquin;2507;40;2547 +59616;Vieux-Condé;10469;52;10521 +59617;Vieux-Mesnil;636;7;643 +59618;Vieux-Reng;848;14;862 +59009;Villeneuve-d'Ascq;63408;693;64101 +59619;Villereau;996;14;1010 +59620;Villers-au-Tertre;630;7;637 +59622;Villers-en-Cauchies;1248;17;1265 +59623;Villers-Guislain;696;4;700 +59624;Villers-Outréaux;2110;26;2136 +59625;Villers-Plouich;404;4;408 +59626;Villers-Pol;1276;21;1297 +59627;Villers-Sire-Nicole;978;11;989 +59628;Volckerinckhove;567;6;573 +59629;Vred;1375;19;1394 +59630;Wahagnies;2598;41;2639 +59631;Walincourt-Selvigny;2136;30;2166 +59632;Wallers;5526;39;5565 +59633;Wallers-en-Fagne;286;7;293 +59634;Wallon-Cappel;811;22;833 +59635;Wambaix;374;6;380 +59636;Wambrechies;10948;88;11036 +59637;Wandignies-Hamage;1302;16;1318 +59638;Wannehain;1272;14;1286 +59639;Wargnies-le-Grand;1101;23;1124 +59640;Wargnies-le-Petit;759;11;770 +59641;Warhem;2032;43;2075 +59642;Warlaing;579;17;596 +59643;Warneton;239;2;241 +59645;Wasnes-au-Bac;609;4;613 +59646;Wasquehal;20479;226;20705 +59647;Watten;2563;32;2595 +59648;Wattignies;14549;194;14743 +59649;Wattignies-la-Victoire;243;11;254 +59650;Wattrelos;40958;160;41118 +59651;Wavrechain-sous-Denain;1661;11;1672 +59652;Wavrechain-sous-Faulx;386;1;387 +59653;Wavrin;7676;68;7744 +59654;Waziers;7452;67;7519 +59655;Wemaers-Cappel;252;4;256 +59656;Wervicq-Sud;5413;49;5462 +59657;West-Cappel;628;7;635 +59658;Wicres;498;7;505 +59659;Wignehies;2903;31;2934 +59660;Willems;3021;40;3061 +59661;Willies;148;2;150 +59662;Winnezeele;1306;22;1328 +59663;Wormhout;5632;86;5718 +59664;Wulverdinghe;309;4;313 +59665;Wylder;291;10;301 +59666;Zegerscappel;1529;32;1561 +59667;Zermezeele;223;4;227 +59668;Zuydcoote;1677;59;1736 +59669;Zuytpeene;524;17;541 +60001;Abancourt;651;8;659 +60002;Abbecourt;787;23;810 +60003;Abbeville-Saint-Lucien;490;13;503 +60004;Achy;402;7;409 +60005;Acy-en-Multien;849;14;863 +60006;Les Ageux;1179;19;1198 +60007;Agnetz;3050;121;3171 +60008;Airion;399;154;553 +60009;Allonne;1572;29;1601 +60010;Amblainville;1740;21;1761 +60011;Amy;392;5;397 +60012;Andeville;3227;45;3272 +60013;Angicourt;1396;29;1425 +60014;Angivillers;185;5;190 +60015;Angy;1172;14;1186 +60016;Ansacq;276;4;280 +60017;Ansauvillers;1197;25;1222 +60019;Antheuil-Portes;409;6;415 +60020;Antilly;264;9;273 +60021;Appilly;542;8;550 +60022;Apremont;660;16;676 +60023;Armancourt;563;8;571 +60024;Arsy;770;8;778 +60025;Attichy;1880;41;1921 +60026;Auchy-la-Montagne;592;13;605 +60027;Auger-Saint-Vincent;518;13;531 +60028;Aumont-en-Halatte;476;25;501 +60029;Auneuil;2892;62;2954 +60030;Auteuil;554;9;563 +60031;Autheuil-en-Valois;272;6;278 +60032;Autrêches;733;15;748 +60033;Avilly-Saint-Léonard;887;40;927 +60034;Avrechy;1150;17;1167 +60035;Avricourt;260;2;262 +60036;Avrigny;373;7;380 +60037;Babœuf;520;7;527 +60039;Bacouël;492;8;500 +60040;Bailleul-le-Soc;642;11;653 +60041;Bailleul-sur-Thérain;2175;51;2226 +60042;Bailleval;1477;46;1523 +60043;Bailly;636;9;645 +60044;Balagny-sur-Thérain;1723;18;1741 +60045;Barbery;572;10;582 +60046;Bargny;332;7;339 +60047;Baron;760;16;776 +60048;Baugy;241;5;246 +60049;Bazancourt;129;9;138 +60050;Bazicourt;337;9;346 +60051;Beaudéduit;204;1;205 +60052;Beaugies-sous-Bois;101;3;104 +60053;Beaulieu-les-Fontaines;609;50;659 +60055;Beaurains-lès-Noyon;338;5;343 +60056;Beaurepaire;67;1;68 +60057;Beauvais;56254;1328;57582 +60058;Beauvoir;238;4;242 +60059;Béhéricourt;209;6;215 +60060;Belle-Église;609;9;618 +60061;Belloy;94;1;95 +60062;Berlancourt;331;5;336 +60063;Berneuil-en-Bray;788;36;824 +60064;Berneuil-sur-Aisne;1004;16;1020 +60065;Berthecourt;1633;30;1663 +60066;Béthancourt-en-Valois;218;10;228 +60067;Béthisy-Saint-Martin;1060;21;1081 +60068;Béthisy-Saint-Pierre;3078;55;3133 +60069;Betz;1161;39;1200 +60070;Bienville;442;10;452 +60071;Biermont;175;5;180 +60072;Bitry;317;5;322 +60073;Blacourt;602;5;607 +60074;Blaincourt-lès-Précy;1190;30;1220 +60075;Blancfossé;146;1;147 +60076;Blargies;533;7;540 +60077;Blicourt;349;9;358 +60078;Blincourt;93;0;93 +60079;Boissy-Fresnoy;999;13;1012 +60081;Bonlier;474;9;483 +60083;Bonneuil-en-Valois;1025;24;1049 +60082;Bonneuil-les-Eaux;805;16;821 +60084;Bonnières;169;1;170 +60085;Bonvillers;204;2;206 +60086;Boran-sur-Oise;2165;35;2200 +60087;Borest;334;18;352 +60088;Bornel;4817;69;4886 +60089;Boubiers;412;11;423 +60090;Bouconvillers;387;8;395 +60091;Bouillancy;382;11;393 +60092;Boullarre;223;5;228 +60093;Boulogne-la-Grasse;471;9;480 +60094;Boursonne;300;6;306 +60095;Boury-en-Vexin;341;7;348 +60097;Boutencourt;220;6;226 +60098;Bouvresse;160;1;161 +60099;Braisnes-sur-Aronde;169;2;171 +60100;Brasseuse;107;0;107 +60101;Brégy;636;14;650 +60102;Brenouille;2016;30;2046 +60103;Bresles;4147;44;4191 +60104;Breteuil;4340;114;4454 +60105;Brétigny;410;9;419 +60106;Breuil-le-Sec;2648;38;2686 +60107;Breuil-le-Vert;3087;129;3216 +60108;Briot;283;8;291 +60109;Brombos;256;4;260 +60110;Broquiers;242;0;242 +60111;Broyes;172;2;174 +60112;Brunvillers-la-Motte;344;1;345 +60113;Bucamps;188;3;191 +60114;Buicourt;145;0;145 +60115;Bulles;894;16;910 +60116;Bury;2971;37;3008 +60117;Bussy;323;8;331 +60118;Caisnes;511;9;520 +60120;Cambronne-lès-Clermont;1145;23;1168 +60119;Cambronne-lès-Ribécourt;1949;37;1986 +60121;Campagne;161;4;165 +60122;Campeaux;503;9;512 +60123;Campremy;490;0;490 +60124;Candor;297;4;301 +60125;Canly;782;19;801 +60126;Cannectancourt;510;6;516 +60127;Canny-sur-Matz;392;5;397 +60128;Canny-sur-Thérain;228;2;230 +60129;Carlepont;1514;20;1534 +60130;Catenoy;1041;23;1064 +60131;Catheux;109;1;110 +60132;Catigny;191;3;194 +60133;Catillon-Fumechon;536;5;541 +60134;Cauffry;2540;25;2565 +60135;Cauvigny;1662;36;1698 +60136;Cempuis;501;12;513 +60137;Cernoy;297;3;300 +60138;Chamant;910;29;939 +60139;Chambly;10174;131;10305 +60140;Chambors;315;4;319 +60141;Chantilly;10863;226;11089 +60142;La Chapelle-en-Serval;3141;84;3225 +60143;Chaumont-en-Vexin;3269;41;3310 +60144;Chavençon;172;3;175 +60145;Chelles;507;14;521 +60146;Chepoix;431;3;434 +60147;Chevincourt;869;22;891 +60148;Chèvreville;425;8;433 +60149;Chevrières;1993;67;2060 +60150;Chiry-Ourscamp;1199;17;1216 +60151;Choisy-au-Bac;3291;103;3394 +60152;Choisy-la-Victoire;236;1;237 +60153;Choqueuse-les-Bénards;103;0;103 +60154;Cinqueux;1556;44;1600 +60155;Cires-lès-Mello;3977;50;4027 +60156;Clairoix;2165;45;2210 +60157;Clermont;10147;215;10362 +60158;Coivrel;251;2;253 +60159;Compiègne;40199;1036;41235 +60160;Conchy-les-Pots;705;12;717 +60161;Conteville;73;0;73 +60162;Corbeil-Cerf;332;8;340 +60163;Cormeilles;421;6;427 +60209;La Corne en Vexin;529;13;542 +60164;Le Coudray-Saint-Germer;906;10;916 +60165;Le Coudray-sur-Thelle;544;19;563 +60166;Coudun;1062;32;1094 +60167;Couloisy;541;14;555 +60168;Courcelles-Epayelles;205;3;208 +60169;Courcelles-lès-Gisors;821;23;844 +60170;Courteuil;602;37;639 +60171;Courtieux;181;4;185 +60172;Coye-la-Forêt;3931;203;4134 +60173;Cramoisy;809;3;812 +60174;Crapeaumesnil;202;3;205 +60175;Creil;35657;227;35884 +60176;Crépy-en-Valois;15090;267;15357 +60177;Cressonsacq;448;8;456 +60178;Crèvecœur-le-Grand;3535;142;3677 +60179;Crèvecœur-le-Petit;147;2;149 +60180;Crillon;491;4;495 +60181;Crisolles;935;20;955 +60182;Le Crocq;182;1;183 +60183;Croissy-sur-Celle;266;2;268 +60184;Croutoy;207;6;213 +60185;Crouy-en-Thelle;1098;10;1108 +60186;Cuignières;248;4;252 +60187;Cuigy-en-Bray;943;13;956 +60188;Cuise-la-Motte;2192;107;2299 +60189;Cuts;975;21;996 +60190;Cuvergnon;291;7;298 +60191;Cuvilly;637;5;642 +60192;Cuy;219;5;224 +60193;Daméraucourt;222;1;223 +60194;Dargies;253;2;255 +60195;Delincourt;473;13;486 +60197;Dieudonné;818;18;836 +60198;Dives;401;6;407 +60199;Doméliers;248;8;256 +60200;Domfront;311;2;313 +60201;Dompierre;240;2;242 +60196;La Drenne;1001;14;1015 +60203;Duvy;445;8;453 +60204;Écuvilly;312;4;316 +60205;Élencourt;53;1;54 +60206;Élincourt-Sainte-Marguerite;862;12;874 +60207;Éméville;287;6;293 +60208;Énencourt-Léage;136;6;142 +60210;Épineuse;244;9;253 +60211;Éragny-sur-Epte;606;5;611 +60212;Ercuis;1609;27;1636 +60213;Ermenonville;1007;21;1028 +60214;Ernemont-Boutavent;207;3;210 +60215;Erquery;607;13;620 +60216;Erquinvillers;183;2;185 +60217;Escames;217;2;219 +60218;Esches;1573;14;1587 +60219;Escles-Saint-Pierre;165;3;168 +60220;Espaubourg;505;5;510 +60221;Esquennoy;720;7;727 +60222;Essuiles;560;16;576 +60223;Estrées-Saint-Denis;3752;53;3805 +60224;Étavigny;152;1;153 +60225;Étouy;774;40;814 +60226;Ève;421;2;423 +60227;Évricourt;224;2;226 +60228;Fay-les-Étangs;471;8;479 +60230;Le Fay-Saint-Quentin;522;8;530 +60229;Le Fayel;220;0;220 +60231;Feigneux;427;14;441 +60232;Ferrières;480;3;483 +60233;Feuquières;1404;20;1424 +60234;Fitz-James;2515;28;2543 +60235;Flavacourt;659;20;679 +60236;Flavy-le-Meldeux;213;0;213 +60237;Fléchy;95;1;96 +60238;Fleurines;1907;91;1998 +60239;Fleury;553;10;563 +60240;Fontaine-Bonneleau;244;3;247 +60241;Fontaine-Chaalis;347;16;363 +60242;Fontaine-Lavaganne;507;7;514 +60243;Fontaine-Saint-Lucien;168;6;174 +60244;Fontenay-Torcy;124;2;126 +60245;Formerie;2131;29;2160 +60247;Fouilleuse;140;2;142 +60248;Fouilloy;200;6;206 +60249;Foulangues;198;2;200 +60250;Fouquenies;430;12;442 +60251;Fouquerolles;281;5;286 +60252;Fournival;518;3;521 +60253;Francastel;479;1;480 +60254;Francières;547;16;563 +60255;Fréniches;349;4;353 +60257;Fresne-Léguillon;438;9;447 +60258;Fresnières;164;6;170 +60259;Fresnoy-en-Thelle;915;24;939 +60260;Fresnoy-la-Rivière;651;20;671 +60261;Fresnoy-le-Luat;503;12;515 +60262;Le Frestoy-Vaux;249;6;255 +60263;Frétoy-le-Château;256;3;259 +60264;Frocourt;523;15;538 +60265;Froissy;887;12;899 +60267;Le Gallet;173;5;178 +60268;Gannes;340;1;341 +60269;Gaudechart;361;5;366 +60270;Genvry;322;85;407 +60271;Gerberoy;90;2;92 +60272;Gilocourt;654;19;673 +60273;Giraumont;539;19;558 +60274;Glaignes;372;13;385 +60275;Glatigny;228;2;230 +60276;Godenvillers;228;3;231 +60277;Goincourt;1390;34;1424 +60278;Golancourt;391;3;394 +60279;Gondreville;206;5;211 +60280;Gourchelles;121;0;121 +60281;Gournay-sur-Aronde;573;17;590 +60282;Gouvieux;9069;402;9471 +60283;Gouy-les-Groseillers;27;0;27 +60284;Grandfresnoy;1773;59;1832 +60287;Grandrû;348;3;351 +60285;Grandvillers-aux-Bois;313;15;328 +60286;Grandvilliers;2940;84;3024 +60288;Grémévillers;458;5;463 +60289;Grez;270;4;274 +60290;Guignecourt;381;4;385 +60291;Guiscard;1803;23;1826 +60292;Gury;242;11;253 +60293;Hadancourt-le-Haut-Clocher;366;8;374 +60294;Hainvillers;80;1;81 +60295;Halloy;452;9;461 +60297;Le Hamel;183;2;185 +60296;Hannaches;141;1;142 +60298;Hanvoile;617;7;624 +60299;Hardivillers;540;7;547 +60301;Haucourt;138;5;143 +60302;Haudivillers;812;23;835 +60303;Hautbos;193;1;194 +60304;Haute-Épine;272;9;281 +60305;Hautefontaine;335;4;339 +60054;Les Hauts Talican;875;18;893 +60306;Hécourt;155;3;158 +60307;Heilles;623;10;633 +60308;Hémévillers;462;9;471 +60309;Hénonville;827;13;840 +60310;Herchies;642;27;669 +60311;La Hérelle;243;4;247 +60312;Héricourt-sur-Thérain;126;2;128 +60313;Hermes;2498;41;2539 +60314;Hétomesnil;312;5;317 +60315;Hodenc-en-Bray;490;10;500 +60316;Hodenc-l'Évêque;248;8;256 +60317;Hondainville;708;8;716 +60318;Houdancourt;671;11;682 +60319;La Houssoye;612;6;618 +60320;Ivors;259;3;262 +60321;Ivry-le-Temple;776;7;783 +60322;Jaméricourt;322;5;327 +60323;Janville;681;11;692 +60324;Jaulzy;903;11;914 +60325;Jaux;2411;67;2478 +60326;Jonquières;609;23;632 +60327;Jouy-sous-Thelle;1028;17;1045 +60328;Juvignies;322;10;332 +60329;Laberlière;197;6;203 +60330;Laboissière-en-Thelle;1347;25;1372 +60331;Labosse;443;6;449 +60332;Labruyère;691;10;701 +60333;Lachapelle-aux-Pots;1620;35;1655 +60334;Lachapelle-Saint-Pierre;919;21;940 +60335;Lachapelle-sous-Gerberoy;148;1;149 +60336;Lachaussée-du-Bois-d'Écu;203;3;206 +60337;Lachelle;651;23;674 +60338;Lacroix-Saint-Ouen;4708;152;4860 +60339;Lafraye;368;9;377 +60340;Lagny;527;15;542 +60341;Lagny-le-Sec;2062;54;2116 +60342;Laigneville;4719;53;4772 +60343;Lalande-en-Son;653;25;678 +60344;Lalandelle;480;9;489 +60345;Lamécourt;191;2;193 +60346;Lamorlaye;8881;236;9117 +60347;Lannoy-Cuillère;282;5;287 +60348;Larbroye;510;9;519 +60350;Lassigny;1399;24;1423 +60351;Lataule;117;2;119 +60352;Lattainville;150;1;151 +60353;Lavacquerie;207;1;208 +60354;Laverrière;38;1;39 +60355;Laversines;1168;52;1220 +60356;Lavilletertre;534;16;550 +60357;Léglantiers;551;5;556 +60358;Lévignen;972;23;995 +60359;Lhéraule;189;2;191 +60360;Liancourt;6880;61;6941 +60361;Liancourt-Saint-Pierre;595;20;615 +60362;Libermont;182;6;188 +60363;Lierville;227;1;228 +60364;Lieuvillers;709;8;717 +60365;Lihus;410;4;414 +60366;Litz;356;5;361 +60367;Loconville;336;8;344 +60368;Longueil-Annel;2622;60;2682 +60369;Longueil-Sainte-Marie;1919;35;1954 +60370;Lormaison;1306;15;1321 +60371;Loueuse;150;1;151 +60372;Luchy;642;15;657 +60373;Machemont;718;17;735 +60374;Maignelay-Montigny;2699;32;2731 +60375;Maimbeville;414;10;424 +60376;Maisoncelle-Saint-Pierre;161;1;162 +60377;Maisoncelle-Tuilerie;301;2;303 +60703;Aux Marais;847;16;863 +60378;Marest-sur-Matz;406;5;411 +60379;Mareuil-la-Motte;641;16;657 +60380;Mareuil-sur-Ourcq;1613;24;1637 +60381;Margny-aux-Cerises;261;1;262 +60382;Margny-lès-Compiègne;8370;174;8544 +60383;Margny-sur-Matz;536;12;548 +60385;Marolles;680;14;694 +60386;Marquéglise;491;9;500 +60387;Marseille-en-Beauvaisis;1482;9;1491 +60388;Martincourt;128;1;129 +60389;Maucourt;249;2;251 +60390;Maulers;316;6;322 +60391;Maysel;249;3;252 +60392;Mélicocq;740;16;756 +60393;Mello;638;18;656 +60394;Ménévillers;104;1;105 +60395;Méru;14614;186;14800 +60396;Méry-la-Bataille;629;5;634 +60397;Le Mesnil-Conteville;84;1;85 +60398;Le Mesnil-en-Thelle;2229;30;2259 +60399;Le Mesnil-Saint-Firmin;204;61;265 +60400;Le Mesnil-sur-Bulles;266;8;274 +60401;Le Mesnil-Théribus;794;48;842 +60402;Le Meux;2270;59;2329 +60403;Milly-sur-Thérain;1708;31;1739 +60404;Mogneville;1515;37;1552 +60405;Moliens;1158;16;1174 +60406;Monceaux;825;16;841 +60407;Monceaux-l'Abbaye;227;2;229 +60408;Monchy-Humières;769;13;782 +60409;Monchy-Saint-Éloi;2214;40;2254 +60410;Mondescourt;243;3;246 +60411;Monneville;823;12;835 +60421;Mont-l'Évêque;397;7;404 +60428;Le Mont-Saint-Adrien;647;27;674 +60412;Montagny-en-Vexin;669;12;681 +60413;Montagny-Sainte-Félicité;417;9;426 +60414;Montataire;13263;156;13419 +60256;Montchevreuil;1283;26;1309 +60415;Montépilloy;138;9;147 +60416;Montgérain;183;1;184 +60418;Montiers;427;8;435 +60420;Montjavoult;483;11;494 +60422;Montlognon;196;11;207 +60423;Montmacq;1082;24;1106 +60424;Montmartin;262;4;266 +60425;Montreuil-sur-Brêche;488;17;505 +60426;Montreuil-sur-Thérain;245;2;247 +60427;Monts;166;4;170 +60429;Morangles;392;13;405 +60430;Morienval;1078;13;1091 +60431;Morlincourt;538;11;549 +60432;Mortefontaine;854;29;883 +60433;Mortefontaine-en-Thelle;913;19;932 +60434;Mortemer;224;6;230 +60435;Morvillers;476;4;480 +60436;Mory-Montcrux;83;2;85 +60437;Mouchy-le-Châtel;82;0;82 +60438;Moulin-sous-Touvent;213;5;218 +60439;Mouy;5288;75;5363 +60440;Moyenneville;630;12;642 +60441;Moyvillers;679;7;686 +60442;Muidorge;141;2;143 +60443;Muirancourt;571;4;575 +60444;Mureaumont;153;4;157 +60445;Nampcel;317;3;320 +60446;Nanteuil-le-Haudouin;4296;38;4334 +60447;Néry;661;14;675 +60448;Neufchelles;377;6;383 +60449;Neufvy-sur-Aronde;279;4;283 +60450;Neuilly-en-Thelle;3655;42;3697 +60451;Neuilly-sous-Clermont;1673;30;1703 +60452;Neuville-Bosc;510;14;524 +60454;La Neuville-en-Hez;972;31;1003 +60456;La Neuville-Roy;952;15;967 +60457;La Neuville-Saint-Pierre;158;2;160 +60458;La Neuville-sur-Oudeuil;326;7;333 +60459;La Neuville-sur-Ressons;212;3;215 +60460;La Neuville-Vault;191;8;199 +60461;Nivillers;188;24;212 +60462;Noailles;2826;42;2868 +60463;Nogent-sur-Oise;20033;362;20395 +60464;Nointel;1029;15;1044 +60465;Noirémont;179;6;185 +60466;Noroy;234;3;237 +60468;Nourard-le-Franc;339;4;343 +60469;Novillers;364;9;373 +60470;Noyers-Saint-Martin;863;13;876 +60471;Noyon;13519;312;13831 +60472;Offoy;117;1;118 +60473;Ognes;294;1;295 +60474;Ognolles;287;6;293 +60476;Omécourt;198;8;206 +60477;Ons-en-Bray;1399;37;1436 +60478;Ormoy-le-Davien;343;8;351 +60479;Ormoy-Villers;644;10;654 +60480;Oroër;556;17;573 +60481;Orrouy;595;13;608 +60482;Orry-la-Ville;3345;89;3434 +60483;Orvillers-Sorel;519;59;578 +60484;Oudeuil;263;10;273 +60485;Oursel-Maison;240;5;245 +60486;Paillart;580;10;590 +60487;Parnes;341;13;354 +60488;Passel;282;6;288 +60489;Péroy-les-Gombries;1137;14;1151 +60490;Pierrefitte-en-Beauvaisis;365;12;377 +60491;Pierrefonds;1808;209;2017 +60492;Pimprez;868;19;887 +60493;Pisseleu;500;7;507 +60494;Plailly;1787;41;1828 +60495;Plainval;403;4;407 +60496;Plainville;161;1;162 +60497;Le Plessier-sur-Bulles;214;0;214 +60498;Le Plessier-sur-Saint-Just;514;3;517 +60500;Le Plessis-Belleville;3408;51;3459 +60501;Le Plessis-Brion;1365;32;1397 +60499;Plessis-de-Roye;233;5;238 +60502;Le Plessis-Patte-d'Oie;102;4;106 +60503;Le Ployron;113;1;114 +60504;Ponchon;1113;18;1131 +60506;Pont-l'Évêque;672;12;684 +60509;Pont-Sainte-Maxence;12209;113;12322 +60505;Pontarmé;817;20;837 +60507;Pontoise-lès-Noyon;459;10;469 +60508;Pontpoint;3268;67;3335 +60510;Porcheux;609;5;614 +60511;Porquéricourt;393;4;397 +60512;Pouilly;156;2;158 +60513;Précy-sur-Oise;3205;73;3278 +60514;Prévillers;232;0;232 +60515;Pronleroy;382;11;393 +60516;Puiseux-en-Bray;420;3;423 +60517;Puiseux-le-Hauberger;851;11;862 +60518;Puits-la-Vallée;203;4;207 +60519;Quesmy;181;4;185 +60520;Le Quesnel-Aubry;213;8;221 +60521;Quincampoix-Fleuzy;396;16;412 +60522;Quinquempoix;322;3;325 +60523;Rainvillers;927;24;951 +60524;Rantigny;2506;22;2528 +60525;Raray;144;6;150 +60526;Ravenel;1098;13;1111 +60527;Réez-Fosse-Martin;149;4;153 +60528;Reilly;126;2;128 +60529;Rémécourt;79;0;79 +60530;Rémérangles;216;9;225 +60531;Remy;1836;37;1873 +60533;Ressons-sur-Matz;1687;23;1710 +60534;Rethondes;656;24;680 +60535;Reuil-sur-Brêche;329;6;335 +60536;Rhuis;140;8;148 +60537;Ribécourt-Dreslincourt;3748;174;3922 +60538;Ricquebourg;285;4;289 +60539;Rieux;1567;21;1588 +60540;Rivecourt;595;14;609 +60541;Roberval;367;12;379 +60542;Rochy-Condé;990;16;1006 +60543;Rocquemont;121;2;123 +60544;Rocquencourt;197;1;198 +60545;Romescamps;547;8;555 +60546;Rosières;137;3;140 +60547;Rosoy;632;13;645 +60548;Rosoy-en-Multien;567;7;574 +60549;Rotangy;213;1;214 +60550;Rothois;226;0;226 +60551;Rousseloy;314;5;319 +60552;Rouville;254;9;263 +60553;Rouvillers;276;7;283 +60554;Rouvres-en-Multien;465;10;475 +60555;Rouvroy-les-Merles;54;0;54 +60557;Roy-Boissy;318;5;323 +60556;Royaucourt;209;3;212 +60558;Roye-sur-Matz;466;11;477 +60559;La Rue-Saint-Pierre;809;10;819 +60560;Rully;720;40;760 +60561;Russy-Bémont;200;6;206 +60562;Sacy-le-Grand;1542;27;1569 +60563;Sacy-le-Petit;552;7;559 +60564;Sains-Morainvillers;273;3;276 +60565;Saint-André-Farivillers;514;4;518 +60566;Saint-Arnoult;217;4;221 +60567;Saint-Aubin-en-Bray;1140;26;1166 +60568;Saint-Aubin-sous-Erquery;336;5;341 +60569;Saint-Crépin-aux-Bois;215;10;225 +60570;Saint-Crépin-Ibouvillers;1533;34;1567 +60571;Saint-Deniscourt;86;3;89 +60572;Saint-Étienne-Roilaye;310;9;319 +60574;Saint-Félix;631;7;638 +60576;Saint-Germain-la-Poterie;477;12;489 +60577;Saint-Germer-de-Fly;1712;35;1747 +60579;Saint-Jean-aux-Bois;315;14;329 +60581;Saint-Just-en-Chaussée;6013;46;6059 +60582;Saint-Léger-aux-Bois;795;16;811 +60583;Saint-Léger-en-Bray;349;12;361 +60584;Saint-Leu-d'Esserent;4688;100;4788 +60585;Saint-Martin-aux-Bois;287;5;292 +60586;Saint-Martin-le-Nœud;1040;22;1062 +60587;Saint-Martin-Longueau;1492;29;1521 +60588;Saint-Maur;383;5;388 +60589;Saint-Maximin;2938;111;3049 +60590;Saint-Omer-en-Chaussée;1249;25;1274 +60591;Saint-Paul;1531;61;1592 +60592;Saint-Pierre-es-Champs;712;8;720 +60593;Saint-Pierre-lès-Bitry;147;3;150 +60594;Saint-Quentin-des-Prés;283;6;289 +60595;Saint-Remy-en-l'Eau;416;3;419 +60596;Saint-Samson-la-Poterie;250;2;252 +60597;Saint-Sauveur;1734;30;1764 +60598;Saint-Sulpice;1020;100;1120 +60599;Saint-Thibault;298;5;303 +60600;Saint-Vaast-de-Longmont;647;7;654 +60601;Saint-Vaast-lès-Mello;1074;17;1091 +60602;Saint-Valery;65;1;66 +60573;Sainte-Eusoye;321;2;323 +60575;Sainte-Geneviève;3230;43;3273 +60578;Saintines;1077;17;1094 +60603;Salency;890;21;911 +60604;Sarcus;265;2;267 +60605;Sarnois;348;6;354 +60608;Le Saulchoy;100;1;101 +60609;Savignies;844;23;867 +60610;Sempigny;789;13;802 +60611;Senantes;621;18;639 +60612;Senlis;14277;601;14878 +60613;Senots;347;6;353 +60614;Serans;222;2;224 +60615;Sérévillers;136;3;139 +60616;Sérifontaine;2755;33;2788 +60617;Sermaize;257;4;261 +60618;Séry-Magneval;282;9;291 +60619;Silly-le-Long;1160;26;1186 +60620;Silly-Tillard;440;7;447 +60621;Solente;138;1;139 +60622;Sommereux;482;6;488 +60623;Songeons;1073;56;1129 +60624;Sully;170;4;174 +60625;Suzoy;568;12;580 +60626;Talmontiers;683;12;695 +60627;Tartigny;274;3;277 +60628;Therdonne;1063;23;1086 +60629;Thérines;202;9;211 +60630;Thibivillers;165;7;172 +60631;Thiers-sur-Thève;1059;23;1082 +60632;Thiescourt;754;16;770 +60633;Thieuloy-Saint-Antoine;410;2;412 +60634;Thieux;439;11;450 +60635;Thiverny;1065;10;1075 +60636;Thourotte;4558;74;4632 +60637;Thury-en-Valois;493;5;498 +60638;Thury-sous-Clermont;679;9;688 +60639;Tillé;1169;23;1192 +60640;Tourly;175;1;176 +60641;Tracy-le-Mont;1735;27;1762 +60642;Tracy-le-Val;1095;32;1127 +60643;Tricot;1422;15;1437 +60644;Trie-Château;1943;31;1974 +60645;Trie-la-Ville;310;5;315 +60646;Troissereux;1232;33;1265 +60647;Trosly-Breuil;2081;52;2133 +60648;Troussencourt;332;4;336 +60650;Trumilly;528;25;553 +60651;Ully-Saint-Georges;1869;30;1899 +60652;Valdampierre;936;11;947 +60653;Valescourt;291;2;293 +60654;Vandélicourt;276;5;281 +60655;Varesnes;368;10;378 +60656;Varinfroy;290;3;293 +60657;Vauchelles;265;5;270 +60658;Vauciennes;682;9;691 +60659;Vaudancourt;170;2;172 +60660;Le Vaumain;372;10;382 +60661;Vaumoise;985;84;1069 +60662;Le Vauroux;504;13;517 +60663;Velennes;241;3;244 +60664;Vendeuil-Caply;470;10;480 +60665;Venette;2857;60;2917 +60666;Ver-sur-Launette;1159;27;1186 +60667;Verberie;3848;52;3900 +60668;Verderel-lès-Sauqueuse;736;23;759 +60669;Verderonne;486;14;500 +60670;Verneuil-en-Halatte;4650;97;4747 +60671;Versigny;380;15;395 +60672;Vez;283;13;296 +60673;Viefvillers;193;1;194 +60674;Vieux-Moulin;644;43;687 +60675;Vignemont;434;6;440 +60676;Ville;762;16;778 +60677;Villembray;256;3;259 +60678;Villeneuve-les-Sablons;1188;16;1204 +60679;La Villeneuve-sous-Thury;164;5;169 +60680;Villeneuve-sur-Verberie;636;17;653 +60681;Villers-Saint-Barthélemy;480;18;498 +60682;Villers Saint Frambourg-Ognon;714;38;752 +60683;Villers-Saint-Genest;389;16;405 +60684;Villers-Saint-Paul;6422;67;6489 +60685;Villers-Saint-Sépulcre;1002;9;1011 +60686;Villers-sous-Saint-Leu;2335;57;2392 +60687;Villers-sur-Auchy;374;9;383 +60688;Villers-sur-Bonnières;164;1;165 +60689;Villers-sur-Coudun;1407;58;1465 +60691;Villers-Vermont;124;5;129 +60692;Villers-Vicomte;151;2;153 +60693;Villeselve;421;4;425 +60695;Vineuil-Saint-Firmin;1413;46;1459 +60697;Vrocourt;33;1;34 +60698;Wacquemoulin;300;10;310 +60699;Wambez;164;5;169 +60700;Warluis;1157;32;1189 +60701;Wavignies;1212;12;1224 +60702;Welles-Pérennes;255;3;258 +61214;L' Aigle;8090;208;8298 +61001;Alençon;25848;744;26592 +61002;Almenêches;716;7;723 +61005;Appenai-sous-Bellême;276;6;282 +61006;Argentan;13823;385;14208 +61422;Les Aspres;631;14;645 +61007;Athis-Val de Rouvre;4256;87;4343 +61008;Aube;1298;37;1335 +61010;Aubry-le-Panthou;115;6;121 +61011;Aubusson;431;20;451 +61012;Auguaise;207;6;213 +61013;Aunay-les-Bois;145;0;145 +61014;Aunou-le-Faucon;246;9;255 +61015;Aunou-sur-Orne;266;7;273 +61017;Les Authieux-du-Puits;73;0;73 +61018;Avernes-Saint-Gourgon;56;5;61 +61020;Avoine;218;7;225 +61021;Avrilly;107;3;110 +61483;Bagnoles de l'Orne Normandie;2693;51;2744 +61023;Bailleul;608;17;625 +61024;Banvou;615;14;629 +61026;Barville;191;9;200 +61028;Bazoches-au-Houlme;468;11;479 +61029;Bazoches-sur-Hoëne;861;23;884 +61030;La Bazoque;265;4;269 +61032;Beaufai;342;8;350 +61034;Beaulieu;211;8;219 +61035;Beauvain;271;2;273 +61036;Belfonds;205;0;205 +61196;Belforêt-en-Perche;1678;43;1721 +61037;Bellavilliers;139;3;142 +61038;Bellême;1464;19;1483 +61039;La Bellière;125;1;126 +61040;Bellou-en-Houlme;1117;29;1146 +61041;Bellou-le-Trichard;214;3;217 +61043;Berd'huis;1111;31;1142 +61044;Berjou;461;16;477 +61046;Bizou;130;3;133 +61048;Boëcé;124;5;129 +61375;Boischampré;1199;36;1235 +61049;Boissei-la-Lande;124;2;126 +61051;Boitron;354;6;360 +61052;Bonnefoi;185;5;190 +61053;Bonsmoulins;240;8;248 +61054;Le Bosc-Renoult;249;4;253 +61055;Boucé;615;12;627 +61056;Le Bouillon;171;1;172 +61060;Brethel;164;1;165 +61061;Bretoncelles;1487;30;1517 +61062;Brieux;90;2;92 +61063;Briouze;1534;71;1605 +61064;Brullemail;95;3;98 +61066;Buré;111;1;112 +61067;Bures;165;5;170 +61068;Bursard;214;3;217 +61069;Cahan;181;3;184 +61070;Caligny;827;26;853 +61071;Camembert;187;5;192 +61072;Canapville;206;4;210 +61074;Carrouges;672;12;684 +61075;Ceaucé;1182;27;1209 +61076;Le Cercueil;137;6;143 +61077;Cerisé;863;23;886 +61078;Cerisy-Belle-Étoile;724;47;771 +61079;Ceton;1785;25;1810 +61080;Chahains;86;2;88 +61081;Chailloué;897;26;923 +61082;Le Chalange;98;4;102 +61085;Le Champ-de-la-Pierre;41;0;41 +61088;Champ-Haut;50;0;50 +61084;Champcerie;160;7;167 +61086;Les Champeaux;116;0;116 +61087;Champeaux-sur-Sarthe;167;5;172 +61089;Champosoult;97;0;97 +61091;Champsecret;895;19;914 +61092;Chandai;664;7;671 +61093;Chanu;1257;17;1274 +61094;La Chapelle-au-Moine;587;17;604 +61095;La Chapelle-Biche;527;8;535 +61097;La Chapelle-Montligeon;520;15;535 +61098;La Chapelle-près-Sées;449;31;480 +61099;La Chapelle-Souëf;255;8;263 +61100;La Chapelle-Viel;272;9;281 +61429;Charencey;797;32;829 +61101;Le Château-d'Almenêches;205;9;214 +61102;Le Châtellier;411;8;419 +61103;Chaumont;177;1;178 +61104;La Chaux;53;1;54 +61105;Chemilli;200;1;201 +61107;Ciral;394;11;405 +61108;Cisai-Saint-Aubin;153;5;158 +61111;Colombiers;335;13;348 +61113;Comblot;64;1;65 +61114;Commeaux;154;4;158 +61117;Condé-sur-Sarthe;2507;46;2553 +61118;Corbon;137;6;143 +61120;Coudehard;78;0;78 +61121;Coulimer;293;8;301 +61122;Coulmer;85;1;86 +61123;Coulonces;224;5;229 +61124;La Coulonche;493;19;512 +61126;Coulonges-sur-Sarthe;543;9;552 +61050;Cour-Maugis sur Huisne;610;24;634 +61129;Courgeon;372;11;383 +61130;Courgeoût;451;13;464 +61133;Courtomer;702;16;718 +61137;Craménil;148;5;153 +61138;Croisilles;207;4;211 +61139;Crouttes;306;11;317 +61140;Crulai;858;15;873 +61141;Cuissai;418;18;436 +61142;Dame-Marie;144;4;148 +61143;Damigny;2568;65;2633 +61145;Domfront en Poiraie;4243;127;4370 +61146;Dompierre;406;3;409 +61148;Durcet;312;5;317 +61149;Échalou;389;9;398 +61150;Échauffour;742;12;754 +61151;Écorcei;390;12;402 +61152;Écorches;89;0;89 +61153;Écouché-les-Vallées;2169;53;2222 +61341;Écouves;1703;55;1758 +61156;Essay;531;14;545 +61158;Faverolles;146;2;148 +61159;Fay;71;2;73 +61160;Feings;191;5;196 +61162;La Ferrière-au-Doyen;169;3;172 +61163;La Ferrière-aux-Étangs;1518;22;1540 +61164;La Ferrière-Béchet;242;2;244 +61165;La Ferrière-Bochard;742;14;756 +61166;Ferrières-la-Verrerie;149;3;152 +61167;La Ferté-en-Ouche;3217;49;3266 +61168;La Ferté Macé;5237;403;5640 +61169;Flers;14734;359;15093 +61170;Fleuré;207;3;210 +61171;Fontaine-les-Bassets;105;1;106 +61176;Francheville;150;4;154 +61178;La Fresnaie-Fayel;54;2;56 +61180;Fresnay-le-Samson;87;1;88 +61181;Gacé;1861;61;1922 +61182;Gandelain;411;6;417 +61183;Gâprée;134;5;139 +61187;Les Genettes;193;7;200 +61188;La Genevraie;98;5;103 +61189;Giel-Courteilles;430;248;678 +61190;Ginai;85;1;86 +61192;Godisson;111;0;111 +61193;La Gonfrière;302;3;305 +61474;Gouffern en Auge;3729;80;3809 +61195;Le Grais;197;4;201 +61197;Guêprei;138;4;142 +61198;Guerquesalles;135;0;135 +61199;Habloville;323;5;328 +61202;Hauterive;473;11;484 +61203;Héloup;917;26;943 +61206;L' Hôme-Chamondot;257;4;261 +61207;Igé;630;24;654 +61208;Irai;613;15;628 +61209;Joué-du-Bois;422;2;424 +61210;Joué-du-Plain;255;10;265 +61212;Juvigny-sur-Orne;119;4;123 +61211;Juvigny Val d'Andaine;2193;55;2248 +61213;Lalacelle;284;4;288 +61215;Laleu;360;7;367 +61216;La Lande-de-Goult;192;3;195 +61217;La Lande-de-Lougé;49;1;50 +61218;La Lande-Patry;1791;53;1844 +61219;La Lande-Saint-Siméon;151;1;152 +61221;Landigou;440;8;448 +61222;Landisacq;749;20;769 +61224;Larré;435;7;442 +61225;Lignères;28;0;28 +61227;Lignou;150;3;153 +61229;Loisail;126;4;130 +61230;Longny les Villages;3008;51;3059 +61232;Lonlay-l'Abbaye;1128;35;1163 +61233;Lonlay-le-Tesson;222;5;227 +61234;Lonrai;1134;37;1171 +61237;Lougé-sur-Maire;315;12;327 +61238;Louvières-en-Auge;76;1;77 +61240;Macé;409;5;414 +61241;La Madeleine-Bouvet;408;10;418 +61242;Le Mage;231;10;241 +61243;Magny-le-Désert;1400;42;1442 +61244;Mahéru;266;11;277 +61248;Mantilly;535;6;541 +61251;Marchemaisons;152;6;158 +61252;Mardilly;136;4;140 +61255;Mauves-sur-Huisne;544;13;557 +61256;Médavy;154;9;163 +61257;Méhoudin;123;2;125 +61258;Le Mêle-sur-Sarthe;686;13;699 +61259;Le Ménil-Bérard;75;0;75 +61261;Le Ménil-Broût;169;3;172 +61262;Le Ménil-Ciboult;121;1;122 +61260;Le Ménil-de-Briouze;562;10;572 +61263;Ménil-Erreux;219;7;226 +61264;Ménil-Froger;55;1;56 +61265;Ménil-Gondouin;172;6;178 +61266;Le Ménil-Guyon;77;0;77 +61267;Ménil-Hermei;203;5;208 +61268;Ménil-Hubert-en-Exmes;111;5;116 +61269;Ménil-Hubert-sur-Orne;482;8;490 +61271;Le Ménil-Scelleur;91;0;91 +61272;Le Ménil-Vicomte;24;1;25 +61273;Ménil-Vin;53;3;56 +61274;Les Menus;237;6;243 +61275;Le Merlerault;809;17;826 +61276;Merri;163;6;169 +61277;La Mesnière;286;6;292 +61278;Messei;1908;58;1966 +61279;Mieuxcé;624;15;639 +61281;Moncy;251;7;258 +61289;Mont-Ormel;53;0;53 +61283;Montabard;286;10;296 +61284;Montchevrel;234;2;236 +61286;Montgaudry;79;0;79 +61287;Montilly-sur-Noireau;724;19;743 +61288;Montmerrei;515;7;522 +61290;Montreuil-au-Houlme;134;4;138 +61291;Montreuil-la-Cambe;70;0;70 +61463;Les Monts d'Andaine;1779;34;1813 +61194;Monts-sur-Orne;909;14;923 +61292;Montsecret-Clairefougère;665;9;674 +61293;Mortagne-au-Perche;3818;295;4113 +61294;Mortrée;1175;29;1204 +61295;La Motte-Fouquet;161;2;163 +61297;Moulins-la-Marche;732;11;743 +61298;Moulins-sur-Orne;311;9;320 +61300;Moutiers-au-Perche;390;8;398 +61301;Neauphe-sous-Essai;211;1;212 +61302;Neauphe-sur-Dive;136;8;144 +61303;Nécy;519;11;530 +61304;Neuilly-le-Bisson;303;5;308 +61307;Neuville-sur-Touques;226;2;228 +61308;Neuvy-au-Houlme;208;4;212 +61310;Nonant-le-Pin;498;39;537 +61314;Occagnes;655;17;672 +61316;Ommoy;124;3;127 +61228;L' Orée-d'Écouves;737;15;752 +61317;Orgères;165;5;170 +61319;Origny-le-Roux;266;7;273 +61321;Pacé;389;6;395 +61322;Parfondeval;111;2;113 +61323;Le Pas-Saint-l'Homer;133;2;135 +61324;Passais Villages;1191;15;1206 +61309;Perche en Nocé;2066;64;2130 +61326;Perrou;295;6;301 +61327;Pervenchères;344;11;355 +61328;Le Pin-au-Haras;276;5;281 +61329;Le Pin-la-Garenne;653;11;664 +61330;Planches;189;3;192 +61331;Le Plantis;147;2;149 +61332;Pointel;330;59;389 +61333;Pontchardon;180;4;184 +61336;Pouvrai;107;7;114 +61339;Putanges-le-Lac;2181;34;2215 +61342;Rai;1425;27;1452 +61344;Rânes;1045;13;1058 +61345;Rémalard en Perche;1950;43;1993 +61346;Le Renouard;202;6;208 +61347;Résenlieu;171;3;174 +61348;Réveillon;374;6;380 +61349;Ri;167;4;171 +61096;Rives d'Andaine;3054;112;3166 +61350;La Roche-Mabile;157;8;165 +61351;Roiville;131;3;134 +61352;Rônai;171;5;176 +61357;Rouperroux;188;3;191 +61116;Sablons sur Huisne;2142;29;2171 +61358;Sai;222;6;228 +61360;Saint-Agnan-sur-Sarthe;104;2;106 +61361;Saint-André-de-Briouze;179;6;185 +61362;Saint-André-de-Messei;572;15;587 +61363;Saint-Aquilin-de-Corbion;67;3;70 +61365;Saint-Aubin-d'Appenai;403;11;414 +61366;Saint-Aubin-de-Bonneval;135;3;138 +61367;Saint-Aubin-de-Courteraie;132;1;133 +61369;Saint-Bômer-les-Forges;1040;35;1075 +61370;Saint-Brice;153;2;155 +61371;Saint-Brice-sous-Rânes;136;2;138 +61372;Saint-Céneri-le-Gérei;120;8;128 +61374;Saint-Christophe-de-Chaulieu;97;4;101 +61376;Saint-Clair-de-Halouze;863;18;881 +61379;Saint-Cyr-la-Rosière;232;4;236 +61381;Saint-Denis-sur-Huisne;56;5;61 +61382;Saint-Denis-sur-Sarthon;1122;21;1143 +61384;Saint-Ellier-les-Bois;248;2;250 +61385;Saint-Evroult-de-Montfort;340;8;348 +61386;Saint-Evroult-Notre-Dame-du-Bois;454;32;486 +61387;Saint-Fraimbault;539;18;557 +61388;Saint-Fulgent-des-Ormes;162;2;164 +61390;Saint-Georges-d'Annebecq;147;1;148 +61391;Saint-Georges-des-Groseillers;3196;115;3311 +61392;Saint-Germain-d'Aunay;146;4;150 +61393;Saint-Germain-de-Clairefeuille;146;5;151 +61394;Saint-Germain-de-la-Coudre;755;27;782 +61396;Saint-Germain-de-Martigny;76;5;81 +61395;Saint-Germain-des-Grois;238;7;245 +61397;Saint-Germain-du-Corbéis;3798;132;3930 +61398;Saint-Germain-le-Vieux;59;1;60 +61399;Saint-Gervais-des-Sablons;72;3;75 +61400;Saint-Gervais-du-Perron;372;7;379 +61401;Saint-Gilles-des-Marais;111;0;111 +61402;Saint-Hilaire-de-Briouze;313;8;321 +61404;Saint-Hilaire-le-Châtel;641;29;670 +61405;Saint-Hilaire-sur-Erre;529;11;540 +61406;Saint-Hilaire-sur-Risle;316;4;320 +61411;Saint-Jouin-de-Blavou;282;9;291 +61412;Saint-Julien-sur-Sarthe;677;15;692 +61413;Saint-Lambert-sur-Dive;149;4;153 +61414;Saint-Langis-lès-Mortagne;911;19;930 +61415;Saint-Léger-sur-Sarthe;346;6;352 +61416;Saint-Léonard-des-Parcs;75;1;76 +61418;Saint-Mard-de-Réno;429;11;440 +61421;Saint-Mars-d'Égrenne;677;23;700 +61423;Saint-Martin-d'Écublei;651;20;671 +61424;Saint-Martin-des-Landes;216;6;222 +61425;Saint-Martin-des-Pézerits;138;2;140 +61426;Saint-Martin-du-Vieux-Bellême;577;17;594 +61427;Saint-Martin-l'Aiguillon;195;4;199 +61432;Saint-Michel-Tubœuf;642;19;661 +61435;Saint-Nicolas-de-Sommaire;270;4;274 +61433;Saint-Nicolas-des-Bois;285;8;293 +61438;Saint-Ouen-de-Sécherouvre;175;5;180 +61439;Saint-Ouen-le-Brisoult;123;4;127 +61440;Saint-Ouen-sur-Iton;825;31;856 +61442;Saint-Patrice-du-Désert;199;4;203 +61443;Saint-Paul;680;15;695 +61444;Saint-Philbert-sur-Orne;114;3;117 +61445;Saint-Pierre-d'Entremont;687;10;697 +61446;Saint-Pierre-des-Loges;156;5;161 +61447;Saint-Pierre-du-Regard;1422;19;1441 +61448;Saint-Pierre-la-Bruyère;438;6;444 +61450;Saint-Quentin-de-Blavou;71;1;72 +61451;Saint-Quentin-les-Chardonnets;337;7;344 +61452;Saint-Roch-sur-Égrenne;178;0;178 +61453;Saint-Sauveur-de-Carrouges;247;7;254 +61456;Saint-Sulpice-sur-Risle;1672;47;1719 +61457;Saint-Symphorien-des-Bruyères;493;8;501 +61373;Sainte-Céronne-lès-Mortagne;249;8;257 +61389;Sainte-Gauburge-Sainte-Colombe;1077;25;1102 +61407;Sainte-Honorine-la-Chardonne;725;13;738 +61408;Sainte-Honorine-la-Guillaume;334;9;343 +61419;Sainte-Marguerite-de-Carrouges;224;7;231 +61420;Sainte-Marie-la-Robert;85;0;85 +61436;Sainte-Opportune;244;2;246 +61454;Sainte-Scolasse-sur-Sarthe;623;15;638 +61459;Saires-la-Verrerie;305;6;311 +61461;Le Sap-André;118;3;121 +61460;Sap-en-Auge;968;10;978 +61462;Sarceaux;1050;34;1084 +61464;Sées;4179;446;4625 +61466;La Selle-la-Forge;1466;38;1504 +61467;Semallé;352;11;363 +61472;Sévigny;308;12;320 +61473;Sevrai;256;5;261 +61475;Soligny-la-Trappe;674;14;688 +61476;Suré;280;8;288 +61479;Tanques;157;5;162 +61480;Tanville;228;5;233 +61481;Tellières-le-Plessis;75;3;78 +61482;Tessé-Froulay;389;9;398 +61485;Ticheville;205;7;212 +61486;Tinchebray-Bocage;4933;91;5024 +61487;Torchamp;295;3;298 +61488;Touquettes;91;2;93 +61490;Tournai-sur-Dive;307;1;308 +61491;Tourouvre au Perche;3127;55;3182 +61492;Trémont;120;4;124 +61493;La Trinité-des-Laitiers;66;6;72 +61494;Trun;1245;66;1311 +61484;Val-au-Perche;3620;76;3696 +61497;Valframbert;1779;29;1808 +61498;Vaunoise;101;4;105 +61499;Les Ventes-de-Bourse;154;3;157 +61500;La Ventrouze;126;4;130 +61501;Verrières;423;5;428 +61502;Vidai;96;0;96 +61503;Vieux-Pont;198;4;202 +61505;Villedieu-lès-Bailleul;215;6;221 +61507;Villiers-sous-Mortagne;284;5;289 +61508;Vimoutiers;3332;96;3428 +61510;Vitrai-sous-Laigle;232;4;236 +61512;Les Yveteaux;103;3;106 +62001;Ablain-Saint-Nazaire;1772;32;1804 +62002;Ablainzevelle;222;4;226 +62003;Acheville;627;23;650 +62004;Achicourt;7799;104;7903 +62005;Achiet-le-Grand;988;5;993 +62006;Achiet-le-Petit;303;4;307 +62007;Acq;769;5;774 +62008;Acquin-Westbécourt;833;5;838 +62009;Adinfer;259;5;264 +62010;Affringues;239;0;239 +62011;Agnez-lès-Duisans;653;16;669 +62012;Agnières;249;4;253 +62013;Agny;1929;29;1958 +62014;Aire-sur-la-Lys;9871;257;10128 +62015;Airon-Notre-Dame;223;2;225 +62016;Airon-Saint-Vaast;186;5;191 +62017;Aix-en-Ergny;189;1;190 +62018;Aix-en-Issart;263;5;268 +62019;Aix-Noulette;3906;43;3949 +62020;Alembon;630;11;641 +62021;Alette;386;1;387 +62022;Alincthun;330;4;334 +62023;Allouagne;2925;30;2955 +62024;Alquines;999;12;1011 +62025;Ambleteuse;1843;39;1882 +62026;Ambricourt;112;2;114 +62027;Ambrines;239;0;239 +62028;Ames;636;8;644 +62029;Amettes;475;1;476 +62030;Amplier;302;4;306 +62031;Andres;1564;9;1573 +62032;Angres;4526;57;4583 +62033;Annay;4337;27;4364 +62034;Annequin;2201;14;2215 +62035;Annezin;5898;46;5944 +62036;Anvin;772;24;796 +62037;Anzin-Saint-Aubin;2742;86;2828 +62038;Ardres;4405;70;4475 +62039;Arleux-en-Gohelle;856;17;873 +62040;Arques;9753;129;9882 +62041;Arras;41019;794;41813 +62042;Athies;1014;13;1027 +62043;Les Attaques;1978;26;2004 +62044;Attin;729;9;738 +62045;Aubigny-en-Artois;1459;26;1485 +62046;Aubin-Saint-Vaast;759;13;772 +62047;Aubrometz;152;1;153 +62048;Auchel;10291;53;10344 +62049;Auchy-au-Bois;504;2;506 +62050;Auchy-lès-Hesdin;1571;16;1587 +62051;Auchy-les-Mines;4726;39;4765 +62052;Audembert;432;12;444 +62053;Audincthun;664;6;670 +62054;Audinghen;582;7;589 +62055;Audrehem;562;12;574 +62056;Audresselles;649;5;654 +62057;Audruicq;5412;53;5465 +62058;Aumerval;198;5;203 +62059;Autingues;291;8;299 +62060;Auxi-le-Château;2639;24;2663 +62061;Averdoingt;293;7;300 +62062;Avesnes;52;1;53 +62063;Avesnes-le-Comte;1902;30;1932 +62064;Avesnes-lès-Bapaume;162;2;164 +62065;Avion;17622;140;17762 +62066;Avondance;38;2;40 +62067;Avroult;607;4;611 +62068;Ayette;324;7;331 +62069;Azincourt;307;4;311 +62070;Bailleul-aux-Cornailles;263;5;268 +62071;Bailleul-lès-Pernes;422;7;429 +62073;Bailleul-Sir-Berthoult;1412;17;1429 +62072;Bailleulmont;240;2;242 +62074;Bailleulval;240;8;248 +62075;Baincthun;1291;30;1321 +62076;Bainghen;227;1;228 +62077;Bajus;365;6;371 +62078;Balinghem;1169;10;1179 +62079;Bancourt;87;0;87 +62080;Bapaume;3887;315;4202 +62081;Baralle;480;11;491 +62082;Barastre;307;4;311 +62083;Barlin;7661;43;7704 +62084;Barly;221;5;226 +62085;Basseux;137;5;142 +62086;Bavincourt;378;7;385 +62087;Bayenghem-lès-Éperlecques;1009;22;1031 +62088;Bayenghem-lès-Seninghem;324;6;330 +62089;Bazinghen;393;13;406 +62090;Béalencourt;130;5;135 +62091;Beaudricourt;90;1;91 +62092;Beaufort-Blavincourt;397;7;404 +62093;Beaulencourt;235;0;235 +62094;Beaumerie-Saint-Martin;397;4;401 +62095;Beaumetz-lès-Aire;239;1;240 +62096;Beaumetz-lès-Cambrai;581;4;585 +62097;Beaumetz-lès-Loges;999;15;1014 +62099;Beaurains;5662;67;5729 +62100;Beaurainville;2095;28;2123 +62881;Beauvoir-Wavans;380;10;390 +62101;Beauvois;142;1;143 +62102;Bécourt;272;3;275 +62103;Béhagnies;126;2;128 +62105;Belle-et-Houllefort;560;18;578 +62104;Bellebrune;400;7;407 +62471;Bellinghem;1070;23;1093 +62106;Bellonne;211;7;218 +62107;Bénifontaine;356;9;365 +62108;Berck;14189;330;14519 +62109;Bergueneuse;218;1;219 +62111;Berlencourt-le-Cauroy;275;81;356 +62112;Berles-au-Bois;515;8;523 +62113;Berles-Monchel;488;14;502 +62114;Bermicourt;165;4;169 +62115;Berneville;480;18;498 +62116;Bernieulles;184;1;185 +62117;Bertincourt;918;15;933 +62118;Béthonsart;147;4;151 +62119;Béthune;24895;333;25228 +62120;Beugin;471;7;478 +62121;Beugnâtre;170;3;173 +62122;Beugny;376;4;380 +62123;Beussent;548;3;551 +62124;Beutin;466;11;477 +62125;Beuvrequen;457;13;470 +62126;Beuvry;9442;175;9617 +62127;Bezinghem;363;10;373 +62128;Biache-Saint-Vaast;4083;32;4115 +62129;Biefvillers-lès-Bapaume;94;2;96 +62130;Bienvillers-au-Bois;643;13;656 +62131;Bihucourt;351;3;354 +62132;Billy-Berclau;4624;37;4661 +62133;Billy-Montigny;8150;42;8192 +62134;Bimont;114;2;116 +62135;Blairville;314;3;317 +62137;Blangerval-Blangermont;106;1;107 +62138;Blangy-sur-Ternoise;720;13;733 +62139;Blendecques;5002;133;5135 +62140;Bléquin;519;4;523 +62141;Blessy;870;13;883 +62142;Blingel;166;1;167 +62143;Boffles;50;1;51 +62144;Boiry-Becquerelle;447;8;455 +62145;Boiry-Notre-Dame;454;6;460 +62146;Boiry-Saint-Martin;277;0;277 +62147;Boiry-Sainte-Rictrude;406;4;410 +62148;Bois-Bernard;827;9;836 +62149;Boisdinghem;249;8;257 +62150;Boisjean;505;7;512 +62151;Boisleux-au-Mont;517;10;527 +62152;Boisleux-Saint-Marc;251;3;254 +62153;Bomy;631;7;638 +62154;Bonnières;674;14;688 +62155;Bonningues-lès-Ardres;656;14;670 +62156;Bonningues-lès-Calais;565;13;578 +62157;Boubers-lès-Hesmond;88;3;91 +62158;Boubers-sur-Canche;589;13;602 +62661;Bouin-Plumoison;494;9;503 +62160;Boulogne-sur-Mer;40874;446;41320 +62161;Bouquehault;765;4;769 +62162;Bourecq;639;2;641 +62163;Bouret-sur-Canche;256;3;259 +62164;Bourlon;1156;18;1174 +62165;Bournonville;240;5;245 +62166;Bours;617;7;624 +62167;Boursin;255;4;259 +62168;Bourthes;853;12;865 +62169;Bouvelinghem;219;5;224 +62170;Bouvigny-Boyeffles;2403;90;2493 +62171;Boyaval;133;2;135 +62172;Boyelles;358;3;361 +62173;Brebières;5023;60;5083 +62174;Brêmes;1290;13;1303 +62175;Brévillers;158;5;163 +62176;Bréxent-Énocq;681;12;693 +62180;Brias;294;6;300 +62177;Brimeux;847;21;868 +62178;Bruay-la-Buissière;21831;436;22267 +62179;Brunembert;418;7;425 +62181;Bucquoy;1461;91;1552 +62182;Buire-au-Bois;230;7;237 +62183;Buire-le-Sec;777;10;787 +62184;Buissy;263;3;266 +62185;Bullecourt;236;1;237 +62186;Bully-les-Mines;12163;71;12234 +62187;Buneville;180;2;182 +62188;Burbure;2865;30;2895 +62189;Bus;126;2;128 +62190;Busnes;1290;23;1313 +62191;Caffiers;749;3;752 +62192;Cagnicourt;432;7;439 +62193;Calais;73911;670;74581 +62194;Calonne-Ricouart;5454;33;5487 +62195;Calonne-sur-la-Lys;1545;19;1564 +62196;La Calotterie;643;7;650 +62197;Camblain-Châtelain;1764;17;1781 +62199;Camblain-l'Abbé;650;129;779 +62198;Cambligneul;337;10;347 +62200;Cambrin;1244;15;1259 +62201;Camiers;2717;43;2760 +62202;Campagne-lès-Boulonnais;634;97;731 +62203;Campagne-lès-Guines;445;11;456 +62204;Campagne-lès-Hesdin;1920;36;1956 +62205;Campagne-lès-Wardrecques;1243;36;1279 +62206;Campigneulles-les-Grandes;299;18;317 +62207;Campigneulles-les-Petites;552;21;573 +62208;Canettemont;70;1;71 +62209;Canlers;159;10;169 +62211;Capelle-Fermont;217;4;221 +62908;La Capelle-lès-Boulogne;1629;38;1667 +62212;Capelle-lès-Hesdin;485;11;496 +62213;Carency;750;10;760 +62214;Carly;551;10;561 +62215;Carvin;17124;111;17235 +62216;La Cauchie;211;2;213 +62217;Cauchy-à-la-Tour;2814;15;2829 +62218;Caucourt;346;7;353 +62219;Caumont;162;4;166 +62220;Cavron-Saint-Martin;457;6;463 +62221;Chelers;259;7;266 +62222;Chériennes;155;2;157 +62223;Chérisy;293;7;300 +62224;Chocques;2881;27;2908 +62225;Clairmarais;624;11;635 +62227;Clenleu;195;3;198 +62228;Clerques;327;3;330 +62229;Cléty;772;16;788 +62230;Colembert;942;13;955 +62231;Colline-Beaumont;137;5;142 +62232;La Comté;935;16;951 +62233;Conchil-le-Temple;1135;14;1149 +62234;Conchy-sur-Canche;216;4;220 +62235;Condette;2506;91;2597 +62236;Contes;331;8;339 +62238;Conteville-en-Ternois;91;1;92 +62237;Conteville-lès-Boulogne;478;14;492 +62239;Coquelles;2611;37;2648 +62240;Corbehem;2366;18;2384 +62241;Cormont;319;5;324 +62242;Couin;113;1;114 +62243;Coullemont;122;3;125 +62244;Coulogne;5372;209;5581 +62245;Coulomby;737;7;744 +62246;Coupelle-Neuve;161;0;161 +62247;Coupelle-Vieille;601;11;612 +62248;Courcelles-le-Comte;461;7;468 +62249;Courcelles-lès-Lens;7774;39;7813 +62250;Courrières;10512;98;10610 +62251;Courset;515;191;706 +62252;La Couture;2764;72;2836 +62253;Couturelle;65;2;67 +62254;Coyecques;606;16;622 +62255;Crémarest;786;4;790 +62256;Crépy;149;3;152 +62257;Créquy;485;8;493 +62258;Croisette;278;5;283 +62259;Croisilles;1929;26;1955 +62260;Croix-en-Ternois;322;3;325 +62261;Cucq;5121;90;5211 +62262;Cuinchy;1741;16;1757 +62263;Dainville;5646;107;5753 +62264;Dannes;1316;5;1321 +62265;Delettes;1178;16;1194 +62266;Denier;86;1;87 +62267;Dennebrœucq;389;6;395 +62268;Desvres;4985;39;5024 +62269;Diéval;750;6;756 +62270;Divion;6978;39;7017 +62271;Dohem;828;17;845 +62272;Douchy-lès-Ayette;308;2;310 +62273;Doudeauville;600;10;610 +62274;Dourges;5891;40;5931 +62275;Douriez;326;7;333 +62276;Douvrin;5407;42;5449 +62277;Drocourt;2936;12;2948 +62278;Drouvin-le-Marais;594;17;611 +62279;Duisans;1309;124;1433 +62280;Dury;350;5;355 +62281;Echinghen;390;6;396 +62282;Éclimeux;176;0;176 +62283;Écoivres;131;0;131 +62284;Écourt-Saint-Quentin;1672;16;1688 +62285;Écoust-Saint-Mein;491;8;499 +62286;Ecquedecques;513;3;516 +62288;Ecques;2139;47;2186 +62289;Écuires;717;21;738 +62290;Écurie;386;6;392 +62291;Éleu-dit-Leauwette;2920;33;2953 +62292;Elnes;914;15;929 +62293;Embry;239;5;244 +62295;Enquin-lez-Guinegatte;1616;26;1642 +62296;Enquin-sur-Baillons;280;1;281 +62297;Éperlecques;3640;44;3684 +62298;Épinoy;546;10;556 +62299;Eps;250;5;255 +62300;Équihen-Plage;2738;35;2773 +62301;Équirre;76;1;77 +62302;Ergny;233;2;235 +62303;Érin;234;5;239 +62304;Erny-Saint-Julien;325;4;329 +62306;Ervillers;399;3;402 +62307;Escalles;228;9;237 +62308;Escœuilles;479;10;489 +62309;Esquerdes;1629;20;1649 +62310;Essars;1725;19;1744 +62311;Estevelles;2044;11;2055 +62312;Estrée;290;6;296 +62313;Estrée-Blanche;951;6;957 +62314;Estrée-Cauchy;373;2;375 +62316;Estrée-Wamin;172;3;175 +62315;Estréelles;352;9;361 +62317;Étaing;450;3;453 +62318;Étaples;10865;98;10963 +62319;Éterpigny;258;3;261 +62320;Étrun;314;8;322 +62321;Évin-Malmaison;4551;17;4568 +62322;Famechon;120;3;123 +62323;Fampoux;1181;21;1202 +62324;Farbus;557;14;571 +62325;Fauquembergues;984;15;999 +62326;Favreuil;237;5;242 +62327;Febvin-Palfart;600;4;604 +62328;Ferfay;912;11;923 +62329;Ferques;1802;14;1816 +62330;Festubert;1313;20;1333 +62331;Feuchy;1028;20;1048 +62332;Ficheux;523;4;527 +62333;Fiefs;385;6;391 +62334;Fiennes;891;8;899 +62335;Fillièvres;509;5;514 +62336;Fléchin;479;7;486 +62337;Flers;225;5;230 +62338;Fleurbaix;2732;55;2787 +62339;Fleury;122;1;123 +62340;Floringhem;898;7;905 +62341;Foncquevillers;435;9;444 +62345;Fontaine-l'Étalon;102;0;102 +62342;Fontaine-lès-Boulans;100;1;101 +62343;Fontaine-lès-Croisilles;278;2;280 +62344;Fontaine-lès-Hermans;108;3;111 +62346;Fortel-en-Artois;211;2;213 +62347;Fosseux;136;3;139 +62348;Foufflin-Ricametz;160;2;162 +62349;Fouquereuil;1570;12;1582 +62350;Fouquières-lès-Béthune;1060;20;1080 +62351;Fouquières-lès-Lens;6362;38;6400 +62352;Framecourt;105;2;107 +62353;Frémicourt;244;6;250 +62354;Frencq;843;18;861 +62355;Fresnes-lès-Montauban;572;7;579 +62356;Fresnicourt-le-Dolmen;772;8;780 +62357;Fresnoy;69;1;70 +62358;Fresnoy-en-Gohelle;214;5;219 +62359;Fressin;575;10;585 +62360;Fréthun;1322;14;1336 +62361;Frévent;3570;58;3628 +62362;Frévillers;239;3;242 +62363;Frévin-Capelle;380;9;389 +62364;Fruges;2371;240;2611 +62365;Galametz;199;0;199 +62366;Gauchin-Légal;321;10;331 +62367;Gauchin-Verloingt;838;35;873 +62368;Gaudiempré;199;0;199 +62369;Gavrelle;627;14;641 +62370;Gennes-Ivergny;128;1;129 +62371;Givenchy-en-Gohelle;1947;43;1990 +62372;Givenchy-le-Noble;150;3;153 +62373;Givenchy-lès-la-Bassée;1012;11;1023 +62374;Gomiécourt;156;8;164 +62375;Gommecourt;96;1;97 +62376;Gonnehem;2536;36;2572 +62377;Gosnay;951;7;958 +62378;Gouves;197;4;201 +62379;Gouy-en-Artois;330;8;338 +62381;Gouy-en-Ternois;133;2;135 +62382;Gouy-Saint-André;643;13;656 +62380;Gouy-Servins;344;2;346 +62383;Gouy-sous-Bellonne;1368;19;1387 +62384;Graincourt-lès-Havrincourt;638;8;646 +62385;Grand-Rullecourt;410;5;415 +62386;Grenay;6932;40;6972 +62387;Grévillers;365;10;375 +62388;Grigny;296;1;297 +62389;Grincourt-lès-Pas;30;2;32 +62390;Groffliers;1508;46;1554 +62391;Guarbecque;1425;14;1439 +62392;Guémappe;336;8;344 +62393;Guemps;1092;21;1113 +62395;Guigny;139;4;143 +62396;Guinecourt;17;1;18 +62397;Guînes;5626;77;5703 +62398;Guisy;270;12;282 +62399;Habarcq;676;14;690 +62400;Haillicourt;4886;37;4923 +62401;Haisnes;4337;26;4363 +62402;Halinghen;325;6;331 +62403;Hallines;1195;20;1215 +62404;Halloy;217;2;219 +62407;Ham-en-Artois;992;13;1005 +62405;Hamblain-les-Prés;504;4;508 +62406;Hamelincourt;255;5;260 +62408;Hames-Boucres;1469;18;1487 +62409;Hannescamps;196;3;199 +62410;Haplincourt;184;6;190 +62411;Haravesnes;50;0;50 +62412;Hardinghen;1210;6;1216 +62413;Harnes;12354;96;12450 +62414;Haucourt;238;2;240 +62419;Haut-Loquin;185;1;186 +62415;Haute-Avesnes;445;9;454 +62416;Hautecloque;218;1;219 +62418;Hauteville;316;8;324 +62421;Havrincourt;403;11;414 +62422;Hébuterne;524;6;530 +62423;Helfaut;1697;30;1727 +62424;Hendecourt-lès-Cagnicourt;312;11;323 +62425;Hendecourt-lès-Ransart;135;4;139 +62427;Hénin-Beaumont;26022;363;26385 +62428;Hénin-sur-Cojeul;527;7;534 +62426;Héninel;177;5;182 +62429;Henneveux;300;6;306 +62430;Hénu;164;2;166 +62432;Herbinghen;378;8;386 +62433;Héricourt;95;3;98 +62434;La Herlière;149;5;154 +62436;Herlin-le-Sec;171;3;174 +62435;Herlincourt;104;8;112 +62437;Herly;313;7;320 +62438;Hermaville;540;8;548 +62439;Hermelinghen;422;3;425 +62440;Hermies;1180;21;1201 +62441;Hermin;213;2;215 +62442;Hernicourt;567;5;572 +62443;Hersin-Coupigny;6245;42;6287 +62444;Hervelinghen;232;6;238 +62445;Hesdigneul-lès-Béthune;822;17;839 +62446;Hesdigneul-lès-Boulogne;677;23;700 +62447;Hesdin;2225;12;2237 +62448;Hesdin-l'Abbé;1863;26;1889 +62449;Hesmond;165;6;171 +62450;Hestrus;243;1;244 +62451;Heuchin;529;11;540 +62452;Heuringhem;1339;33;1372 +62453;Hézecques;122;0;122 +62454;Hinges;2452;49;2501 +62455;Hocquinghen;112;1;113 +62456;Houchin;718;12;730 +62457;Houdain;7246;61;7307 +62458;Houlle;1127;12;1139 +62459;Houvin-Houvigneul;232;4;236 +62460;Hubersent;269;7;276 +62461;Huby-Saint-Leu;886;10;896 +62462;Huclier;137;5;142 +62463;Hucqueliers;464;37;501 +62464;Hulluch;3448;31;3479 +62465;Humbercamps;218;0;218 +62466;Humbert;232;1;233 +62467;Humerœuille;176;0;176 +62468;Humières;229;2;231 +62469;Inchy-en-Artois;624;9;633 +62470;Incourt;86;2;88 +62472;Inxent;162;6;168 +62473;Isbergues;8845;78;8923 +62474;Isques;1153;22;1175 +62475;Ivergny;259;2;261 +62476;Izel-lès-Équerchin;1011;10;1021 +62477;Izel-lès-Hameau;727;15;742 +62478;Journy;287;5;292 +62479;Labeuvrière;1645;14;1659 +62480;Labourse;2847;22;2869 +62481;Labroye;165;3;168 +62483;Lacres;247;2;249 +62484;Lagnicourt-Marcel;331;4;335 +62485;Laires;364;1;365 +62486;Lambres;1061;14;1075 +62487;Landrethun-le-Nord;1299;10;1309 +62488;Landrethun-lès-Ardres;753;20;773 +62489;Lapugnoy;3459;30;3489 +62490;Lattre-Saint-Quentin;267;3;270 +62491;Laventie;4994;81;5075 +62492;Lebiez;250;2;252 +62493;Lebucquière;234;3;237 +62494;Léchelle;49;1;50 +62495;Ledinghem;338;1;339 +62496;Lefaux;238;6;244 +62497;Leforest;7167;48;7215 +62498;Lens;31415;199;31614 +62499;Lépine;273;8;281 +62500;Lespesses;405;3;408 +62501;Lespinoy;222;2;224 +62502;Lestrem;4532;69;4601 +62503;Leubringhen;295;8;303 +62504;Leulinghem;252;6;258 +62505;Leulinghen-Bernes;470;5;475 +62907;Libercourt;8355;43;8398 +62506;Licques;1631;19;1650 +62507;Liencourt;291;2;293 +62508;Lières;380;10;390 +62509;Liettres;327;4;331 +62510;Liévin;30785;369;31154 +62511;Lignereuil;137;1;138 +62512;Ligny-lès-Aire;598;15;613 +62514;Ligny-Saint-Flochel;258;3;261 +62513;Ligny-sur-Canche;194;6;200 +62515;Ligny-Thilloy;532;17;549 +62516;Lillers;9931;83;10014 +62517;Linghem;205;6;211 +62518;Linzeux;153;3;156 +62519;Lisbourg;591;8;599 +62520;Locon;2465;36;2501 +62521;La Loge;201;4;205 +62523;Loison-sous-Lens;5410;47;5457 +62522;Loison-sur-Créquoise;266;2;268 +62524;Longfossé;1452;16;1468 +62525;Longuenesse;11023;540;11563 +62526;Longueville;138;2;140 +62527;Longvilliers;247;6;253 +62528;Loos-en-Gohelle;6751;57;6808 +62529;Lorgies;1586;18;1604 +62530;Lottinghen;545;9;554 +62531;Louches;960;14;974 +62532;Lozinghem;1262;14;1276 +62533;Lugy;147;3;150 +62534;Lumbres;3626;75;3701 +62535;La Madelaine-sous-Montreuil;161;8;169 +62536;Magnicourt-en-Comte;649;10;659 +62537;Magnicourt-sur-Canche;117;4;121 +62538;Maintenay;426;8;434 +62539;Maisnil;242;3;245 +62540;Maisnil-lès-Ruitz;1680;14;1694 +62541;Maisoncelle;125;4;129 +62542;Maizières;193;4;197 +62543;Mametz;1997;31;2028 +62544;Manin;185;1;186 +62545;Maninghem;151;0;151 +62546;Maninghen-Henne;314;15;329 +62547;Marant;66;1;67 +62548;Marck;10676;143;10819 +62549;Marconne;1093;63;1156 +62550;Marconnelle;1134;22;1156 +62551;Marenla;243;2;245 +62552;Maresquel-Ecquemicourt;986;8;994 +62553;Marest;285;6;291 +62554;Maresville;102;0;102 +62555;Marles-les-Mines;5579;29;5608 +62556;Marles-sur-Canche;299;4;303 +62558;Marquay;179;1;180 +62559;Marquion;976;14;990 +62560;Marquise;5088;60;5148 +62561;Martinpuich;196;1;197 +62557;Marœuil;2464;63;2527 +62562;Matringhem;185;2;187 +62563;Mazingarbe;8053;50;8103 +62564;Mazinghem;474;8;482 +62565;Mencas;77;0;77 +62566;Menneville;700;19;719 +62567;Mentque-Nortbécourt;651;9;660 +62568;Mercatel;697;7;704 +62569;Merck-Saint-Liévin;656;6;662 +62570;Méricourt;11363;75;11438 +62571;Merlimont;3348;66;3414 +62572;Metz-en-Couture;664;11;675 +62573;Meurchin;3786;24;3810 +62574;Mingoval;230;5;235 +62576;Moncheaux-lès-Frévent;139;0;139 +62577;Monchel-sur-Canche;90;0;90 +62578;Monchiet;96;2;98 +62579;Monchy-au-Bois;561;15;576 +62580;Monchy-Breton;476;11;487 +62581;Monchy-Cayeux;300;3;303 +62582;Monchy-le-Preux;651;36;687 +62583;Mondicourt;592;9;601 +62584;Mont-Bernanchon;1359;22;1381 +62589;Mont-Saint-Éloi;1023;20;1043 +62585;Montcavrel;413;5;418 +62586;Montenescourt;460;6;466 +62587;Montigny-en-Gohelle;10198;60;10258 +62588;Montreuil;2014;130;2144 +62590;Monts-en-Ternois;63;0;63 +62591;Morchies;210;3;213 +62592;Moringhem;558;8;566 +62593;Morval;94;2;96 +62594;Mory;309;3;312 +62595;Moulle;1117;28;1145 +62596;Mouriez;249;5;254 +62597;Moyenneville;272;3;275 +62598;Muncq-Nieurlet;734;7;741 +62599;Nabringhen;212;6;218 +62600;Nédon;153;3;156 +62601;Nédonchel;282;5;287 +62602;Nempont-Saint-Firmin;198;2;200 +62603;Nesles;953;18;971 +62604;Neufchâtel-Hardelot;3746;74;3820 +62605;Neulette;28;0;28 +62606;Neuve-Chapelle;1440;12;1452 +62607;Neuville-au-Cornet;71;2;73 +62608;Neuville-Bourjonval;168;1;169 +62609;Neuville-Saint-Vaast;1526;29;1555 +62610;Neuville-sous-Montreuil;650;9;659 +62611;Neuville-Vitasse;505;8;513 +62612;Neuvireuil;574;12;586 +62614;Nielles-lès-Ardres;557;14;571 +62613;Nielles-lès-Bléquin;847;9;856 +62615;Nielles-lès-Calais;281;5;286 +62618;Nordausques;1273;14;1287 +62619;Noreuil;160;2;162 +62620;Norrent-Fontes;1398;23;1421 +62622;Nort-Leulinghem;234;3;237 +62621;Nortkerque;1613;25;1638 +62623;Nouvelle-Église;679;8;687 +62630;Noyelle-Vion;294;5;299 +62624;Noyelles-Godault;5973;34;6007 +62625;Noyelles-lès-Humières;53;2;55 +62626;Noyelles-lès-Vermelles;2401;15;2416 +62627;Noyelles-sous-Bellonne;812;17;829 +62628;Noyelles-sous-Lens;6561;46;6607 +62629;Noyellette;173;1;174 +62631;Nuncq-Hautecôte;476;7;483 +62616;Nœux-lès-Auxi;179;2;181 +62617;Nœux-les-Mines;12074;72;12146 +62632;Oblinghem;379;2;381 +62634;Offekerque;1167;19;1186 +62635;Offin;207;2;209 +62636;Offrethun;264;13;277 +62637;Oignies;9767;50;9817 +62638;Oisy-le-Verger;1217;14;1231 +62639;Oppy;399;9;408 +62640;Orville;402;8;410 +62641;Ostreville;239;3;242 +62642;Ourton;769;9;778 +62643;Outreau;13422;174;13596 +62644;Ouve-Wirquin;506;7;513 +62645;Oye-Plage;5373;82;5455 +62646;Palluel;563;3;566 +62647;Le Parcq;776;16;792 +62648;Parenty;520;10;530 +62649;Pas-en-Artois;762;10;772 +62650;Pelves;740;7;747 +62651;Penin;474;4;478 +62652;Pernes;1686;28;1714 +62653;Pernes-lès-Boulogne;421;19;440 +62654;Peuplingues;777;10;787 +62655;Pierremont;292;7;299 +62656;Pihem;948;24;972 +62657;Pihen-lès-Guînes;499;7;506 +62658;Pittefaux;124;13;137 +62659;Planques;81;1;82 +62660;Plouvain;454;7;461 +62662;Polincove;853;15;868 +62663;Pommera;306;4;310 +62664;Pommier;232;4;236 +62665;Le Ponchel;207;6;213 +62666;Pont-à-Vendin;3187;17;3204 +62667;Le Portel;9240;103;9343 +62668;Prédefin;190;2;192 +62669;Pressy;317;5;322 +62670;Preures;605;7;612 +62671;Pronville-en-Artois;324;4;328 +62672;Puisieux;661;5;666 +62673;Quéant;657;10;667 +62674;Quelmes;576;10;586 +62675;Quercamps;269;2;271 +62676;Quernes;458;7;465 +62677;Le Quesnoy-en-Artois;347;5;352 +62678;Quesques;676;3;679 +62679;Questrecques;307;9;316 +62680;Quiéry-la-Motte;737;13;750 +62681;Quiestède;614;22;636 +62682;Quilen;60;0;60 +62683;Quœux-Haut-Maînil;257;1;258 +62684;Racquinghem;2276;34;2310 +62685;Radinghem;275;163;438 +62686;Ramecourt;382;11;393 +62688;Rang-du-Fliers;4171;118;4289 +62689;Ransart;404;2;406 +62690;Raye-sur-Authie;250;4;254 +62692;Rebergues;375;4;379 +62693;Rebreuve-Ranchicourt;1074;22;1096 +62694;Rebreuve-sur-Canche;194;0;194 +62695;Rebreuviette;268;3;271 +62696;Reclinghem;241;2;243 +62697;Récourt;211;0;211 +62698;Recques-sur-Course;279;5;284 +62699;Recques-sur-Hem;631;14;645 +62700;Regnauville;213;1;214 +62701;Rely;454;2;456 +62702;Remilly-Wirquin;349;6;355 +62703;Rémy;395;6;401 +62704;Renty;624;20;644 +62705;Rety;2096;16;2112 +62706;Richebourg;2622;56;2678 +62708;Riencourt-lès-Bapaume;35;1;36 +62709;Riencourt-lès-Cagnicourt;262;5;267 +62710;Rimboval;142;0;142 +62711;Rinxent;3001;30;3031 +62712;Rivière;1123;27;1150 +62713;Robecq;1359;23;1382 +62714;Roclincourt;782;19;801 +62715;Rocquigny;285;0;285 +62716;Rodelinghem;528;6;534 +62717;Roëllecourt;538;10;548 +62719;Rollancourt;307;39;346 +62720;Rombly;46;2;48 +62721;Roquetoire;1944;49;1993 +62722;Rougefay;86;3;89 +62723;Roussent;241;0;241 +62724;Rouvroy;8738;37;8775 +62725;Royon;135;0;135 +62726;Ruisseauville;199;5;204 +62727;Ruitz;1583;34;1617 +62728;Rumaucourt;685;12;697 +62729;Rumilly;254;5;259 +62730;Ruminghem;1650;23;1673 +62731;Ruyaulcourt;294;3;297 +62718;Rœux;1446;20;1466 +62732;Sachin;345;5;350 +62733;Sailly-au-Bois;309;1;310 +62734;Sailly-en-Ostrevent;722;11;733 +62735;Sailly-Labourse;2336;17;2353 +62736;Sailly-sur-la-Lys;3982;72;4054 +62737;Sains-en-Gohelle;6145;38;6183 +62738;Sains-lès-Fressin;162;4;166 +62739;Sains-lès-Marquion;322;3;325 +62740;Sains-lès-Pernes;292;9;301 +62741;Saint-Amand;122;3;125 +62742;Saint-Aubin;264;6;270 +62691;Saint-Augustin;805;13;818 +62745;Saint-Denœux;160;0;160 +62746;Saint-Étienne-au-Mont;5076;64;5140 +62747;Saint-Floris;592;15;607 +62748;Saint-Folquin;2248;39;2287 +62749;Saint-Georges;326;6;332 +62750;Saint-Hilaire-Cottes;807;9;816 +62751;Saint-Inglevert;783;9;792 +62752;Saint-Josse;1136;26;1162 +62753;Saint-Laurent-Blangy;6606;64;6670 +62754;Saint-Léger;450;4;454 +62755;Saint-Léonard;3452;53;3505 +62758;Saint-Martin-Boulogne;11204;186;11390 +62759;Saint-Martin-Choquel;482;8;490 +62760;Saint-Martin-d'Hardinghem;286;3;289 +62757;Saint-Martin-lez-Tatinghem;5906;136;6042 +62761;Saint-Martin-sur-Cojeul;210;4;214 +62762;Saint-Michel-sous-Bois;119;5;124 +62763;Saint-Michel-sur-Ternoise;878;15;893 +62764;Saint-Nicolas;4738;50;4788 +62765;Saint-Omer;14782;688;15470 +62766;Saint-Omer-Capelle;1095;12;1107 +62767;Saint-Pol-sur-Ternoise;4971;174;5145 +62768;Saint-Rémy-au-Bois;101;2;103 +62769;Saint-Tricat;760;14;774 +62770;Saint-Venant;3027;85;3112 +62743;Sainte-Austreberthe;401;9;410 +62744;Sainte-Catherine;3511;56;3567 +62756;Sainte-Marie-Kerque;1648;30;1678 +62771;Sallaumines;9715;37;9752 +62772;Salperwick;486;25;511 +62773;Samer;4496;143;4639 +62774;Sangatte;4820;126;4946 +62775;Sanghen;329;2;331 +62776;Sapignies;196;4;200 +62777;Le Sars;180;1;181 +62778;Sars-le-Bois;82;1;83 +62779;Sarton;183;0;183 +62780;Sauchy-Cauchy;364;4;368 +62781;Sauchy-Lestrée;455;3;458 +62782;Saudemont;449;8;457 +62783;Saulchoy;317;1;318 +62784;Saulty;765;12;777 +62785;Savy-Berlette;916;183;1099 +62786;Selles;333;3;336 +62787;Sempy;325;3;328 +62788;Seninghem;722;17;739 +62789;Senlecques;269;1;270 +62790;Senlis;163;4;167 +62791;Séricourt;54;0;54 +62792;Serques;1148;32;1180 +62793;Servins;1093;12;1105 +62794;Setques;608;6;614 +62795;Sibiville;111;2;113 +62796;Simencourt;557;12;569 +62797;Siracourt;269;3;272 +62798;Sombrin;240;7;247 +62799;Sorrus;817;13;830 +62800;Souastre;379;3;382 +62801;Souchez;2496;35;2531 +62802;Le Souich;154;1;155 +62803;Surques;640;5;645 +62804;Sus-Saint-Léger;376;2;378 +62805;Tangry;252;1;253 +62806;Tardinghen;151;4;155 +62808;Teneur;260;0;260 +62809;Ternas;137;3;140 +62810;Thélus;1204;36;1240 +62811;Thérouanne;1115;24;1139 +62812;Thiembronne;834;7;841 +62813;La Thieuloye;493;2;495 +62814;Thièvres;123;1;124 +62815;Tigny-Noyelle;174;0;174 +62816;Tilloy-lès-Hermaville;223;5;228 +62817;Tilloy-lès-Mofflaines;1434;116;1550 +62818;Tilly-Capelle;159;1;160 +62819;Tilques;1099;30;1129 +62820;Tincques;825;16;841 +62821;Tingry;290;7;297 +62822;Tollent;91;3;94 +62823;Torcy;165;5;170 +62824;Tortefontaine;222;5;227 +62825;Tortequesne;826;8;834 +62826;Le Touquet-Paris-Plage;4223;239;4462 +62827;Tournehem-sur-la-Hem;1436;17;1453 +62828;Tramecourt;60;0;60 +62829;Le Transloy;411;3;414 +62830;Trescault;178;2;180 +62831;Troisvaux;279;7;286 +62832;Tubersent;538;3;541 +62833;Vacquerie-le-Boucq;84;2;86 +62834;Vacqueriette-Erquières;253;4;257 +62835;Valhuon;569;19;588 +62836;Vaudricourt;971;26;997 +62837;Vaudringhem;532;8;540 +62838;Vaulx;90;3;93 +62839;Vaulx-Vraucourt;1018;9;1027 +62840;Vélu;135;0;135 +62842;Vendin-le-Vieil;8608;42;8650 +62841;Vendin-lès-Béthune;2443;24;2467 +62843;Verchin;241;5;246 +62844;Verchocq;645;14;659 +62845;Verlincthun;444;5;449 +62846;Vermelles;4726;39;4765 +62847;Verquigneul;1929;23;1952 +62848;Verquin;3452;34;3486 +62849;Verton;2425;56;2481 +62850;Vieil-Hesdin;356;6;362 +62853;Vieil-Moutier;386;10;396 +62851;Vieille-Chapelle;778;16;794 +62852;Vieille-Église;1382;14;1396 +62854;Villers-au-Bois;568;11;579 +62855;Villers-au-Flos;272;2;274 +62856;Villers-Brûlin;365;4;369 +62857;Villers-Châtel;135;11;146 +62859;Villers-l'Hôpital;265;4;269 +62858;Villers-lès-Cagnicourt;264;5;269 +62860;Villers-Sir-Simon;118;3;121 +62861;Vimy;4265;77;4342 +62862;Vincly;158;3;161 +62863;Violaines;3667;30;3697 +62864;Vis-en-Artois;654;15;669 +62865;Vitry-en-Artois;4677;49;4726 +62866;Waben;431;15;446 +62867;Wacquinghen;262;7;269 +62868;Wail;262;6;268 +62869;Wailly;1099;32;1131 +62870;Wailly-Beaucamp;1004;19;1023 +62871;Wambercourt;245;5;250 +62872;Wamin;237;5;242 +62873;Wancourt;649;10;659 +62874;Wanquetin;719;15;734 +62875;Wardrecques;1333;23;1356 +62876;Warlencourt-Eaucourt;138;2;140 +62877;Warlincourt-lès-Pas;174;5;179 +62878;Warlus;377;7;384 +62879;Warluzel;232;3;235 +62880;Le Wast;206;3;209 +62882;Wavrans-sur-l'Aa;1270;35;1305 +62883;Wavrans-sur-Ternoise;201;0;201 +62885;Westrehem;244;1;245 +62886;Wicquinghem;252;3;255 +62887;Widehem;244;1;245 +62888;Wierre-au-Bois;226;0;226 +62889;Wierre-Effroy;857;19;876 +62890;Willeman;188;1;189 +62891;Willencourt;134;2;136 +62892;Willerval;651;20;671 +62893;Wimereux;6575;168;6743 +62894;Wimille;4083;80;4163 +62895;Wingles;8770;60;8830 +62896;Wirwignes;746;21;767 +62897;Wismes;491;9;500 +62898;Wisques;226;9;235 +62899;Wissant;939;18;957 +62900;Witternesse;587;16;603 +62901;Wittes;961;12;973 +62902;Wizernes;3344;53;3397 +62909;Ytres;435;5;440 +62903;Zoteux;615;4;619 +62904;Zouafques;609;10;619 +62905;Zudausques;915;45;960 +62906;Zutkerque;1753;21;1774 +62633;Œuf-en-Ternois;249;3;252 +63001;Aigueperse;2732;31;2763 +63002;Aix-la-Fayette;93;0;93 +63003;Ambert;6671;252;6923 +63004;Les Ancizes-Comps;1610;29;1639 +63005;Antoingt;397;4;401 +63006;Anzat-le-Luguet;178;2;180 +63007;Apchat;166;3;169 +63008;Arconsat;604;12;616 +63009;Ardes;561;6;567 +63010;Arlanc;1892;40;1932 +63011;Ars-les-Favets;225;6;231 +63012;Artonne;898;17;915 +63013;Aubiat;890;12;902 +63014;Aubière;10061;150;10211 +63015;Aubusson-d'Auvergne;261;4;265 +63016;Augerolles;888;19;907 +63017;Augnat;172;1;173 +63160;Aulhat-Flat;911;31;942 +63019;Aulnat;4046;39;4085 +63020;Aurières;331;11;342 +63021;Authezat;679;8;687 +63022;Auzat-la-Combelle;2076;34;2110 +63023;Auzelles;364;9;373 +63024;Avèze;178;4;182 +63025;Ayat-sur-Sioule;145;4;149 +63026;Aydat;2373;41;2414 +63027;Baffie;112;1;113 +63028;Bagnols;440;8;448 +63029;Bansat;253;3;256 +63030;Bas-et-Lezat;333;6;339 +63031;Beaulieu;461;4;465 +63032;Beaumont;10787;236;11023 +63033;Beaumont-lès-Randan;295;2;297 +63034;Beauregard-l'Évêque;1518;28;1546 +63035;Beauregard-Vendon;1194;18;1212 +63036;Bergonne;339;4;343 +63037;Bertignat;455;14;469 +63038;Besse-et-Saint-Anastaise;1504;67;1571 +63039;Beurières;297;10;307 +63040;Billom;4741;84;4825 +63041;Biollet;329;6;335 +63042;Blanzat;3749;55;3804 +63043;Blot-l'Église;421;3;424 +63044;Bongheat;427;4;431 +63045;Bort-l'Étang;657;4;661 +63046;Boudes;287;4;291 +63047;La Bourboule;1789;49;1838 +63048;Bourg-Lastic;877;26;903 +63049;Bouzel;727;7;734 +63050;Brassac-les-Mines;3311;119;3430 +63051;Brenat;622;13;635 +63052;Le Breuil-sur-Couze;1046;93;1139 +63053;Briffons;269;12;281 +63054;Le Broc;679;16;695 +63055;Bromont-Lamothe;976;16;992 +63056;Brousse;339;4;343 +63057;Le Brugeron;245;6;251 +63058;Bulhon;530;9;539 +63059;Busséol;218;5;223 +63060;Bussières;92;0;92 +63061;Bussières-et-Pruns;450;7;457 +63062;Buxières-sous-Montaigut;237;3;240 +63063;Cébazat;8604;107;8711 +63065;Ceilloux;177;5;182 +63064;La Celle;84;0;84 +63066;Celles-sur-Durolle;1738;23;1761 +63067;La Cellette;169;2;171 +63069;Le Cendre;5426;57;5483 +63070;Ceyrat;6416;134;6550 +63071;Ceyssat;693;11;704 +63072;Chabreloche;1220;19;1239 +63073;Chadeleuf;428;12;440 +63074;Chalus;178;0;178 +63075;Chamalières;17173;653;17826 +63244;Chambaron sur Morge;1749;24;1773 +63076;Chambon-sur-Dolore;161;8;169 +63077;Chambon-sur-Lac;417;3;420 +63079;Champagnat-le-Jeune;149;2;151 +63080;Champeix;1360;22;1382 +63081;Champétières;272;6;278 +63082;Champs;399;8;407 +63083;Chanat-la-Mouteyre;941;28;969 +63084;Chanonat;1685;39;1724 +63085;Chapdes-Beaufort;1100;8;1108 +63086;La Chapelle-Agnon;346;12;358 +63087;La Chapelle-Marcousse;63;0;63 +63088;La Chapelle-sur-Usson;74;0;74 +63089;Chappes;1655;27;1682 +63090;Chaptuzat;491;8;499 +63091;Charbonnier-les-Mines;898;15;913 +63092;Charbonnières-les-Varennes;1728;26;1754 +63093;Charbonnières-les-Vieilles;1075;20;1095 +63094;Charensat;506;4;510 +63095;Charnat;210;3;213 +63096;Chas;379;7;386 +63097;Chassagne;73;0;73 +63098;Chastreix;226;8;234 +63101;Château-sur-Cher;74;1;75 +63099;Châteaugay;3135;55;3190 +63100;Châteauneuf-les-Bains;316;4;320 +63103;Châtel-Guyon;6152;146;6298 +63102;Châteldon;773;12;785 +63104;La Chaulme;115;5;120 +63105;Chaumont-le-Bourg;231;6;237 +63106;Chauriat;1677;18;1695 +63107;Chavaroux;477;9;486 +63108;Le Cheix;663;14;677 +63109;Chidrac;523;12;535 +63110;Cisternes-la-Forêt;461;5;466 +63111;Clémensat;118;4;122 +63112;Clerlande;564;7;571 +63113;Clermont-Ferrand;143886;2746;146632 +63114;Collanges;158;1;159 +63115;Combrailles;218;4;222 +63116;Combronde;2206;34;2240 +63117;Compains;126;3;129 +63118;Condat-en-Combraille;422;7;429 +63119;Condat-lès-Montboissier;226;3;229 +63120;Corent;747;9;756 +63121;Coudes;1249;12;1261 +63122;Courgoul;66;1;67 +63123;Cournols;242;5;247 +63124;Cournon-d'Auvergne;20043;397;20440 +63125;Courpière;4050;144;4194 +63126;Le Crest;1267;27;1294 +63128;Crevant-Laveine;967;14;981 +63129;Cros;175;1;176 +63130;La Crouzille;262;11;273 +63131;Culhat;1130;18;1148 +63132;Cunlhat;1248;38;1286 +63134;Dauzat-sur-Vodable;80;2;82 +63135;Davayat;610;6;616 +63136;Domaize;389;8;397 +63137;Doranges;159;4;163 +63138;Dorat;705;7;712 +63139;Dore-l'Église;634;8;642 +63140;Durmignat;205;5;210 +63141;Durtol;2015;47;2062 +63142;Échandelys;258;8;266 +63143;Effiat;1119;18;1137 +63144;Égliseneuve-d'Entraigues;352;8;360 +63145;Égliseneuve-des-Liards;143;7;150 +63146;Égliseneuve-près-Billom;799;63;862 +63147;Églisolles;261;3;264 +63148;Ennezat;2484;52;2536 +63149;Entraigues;661;9;670 +63150;Enval;1486;29;1515 +63151;Escoutoux;1348;40;1388 +63152;Espinasse;294;4;298 +63153;Espinchal;104;2;106 +63154;Espirat;408;5;413 +63155;Estandeuil;452;7;459 +63156;Esteil;63;1;64 +63157;Fayet-le-Château;357;11;368 +63158;Fayet-Ronaye;106;6;112 +63159;Fernoël;131;2;133 +63161;La Forie;321;11;332 +63162;Fournols;317;9;326 +63163;Gelles;977;48;1025 +63164;Gerzat;10365;88;10453 +63165;Giat;816;39;855 +63166;Gignat;239;5;244 +63167;Gimeaux;401;5;406 +63168;Glaine-Montaigut;572;13;585 +63169;La Godivelle;14;0;14 +63170;La Goutelle;626;22;648 +63171;Gouttières;342;11;353 +63172;Grandeyrolles;53;1;54 +63173;Grandrif;186;6;192 +63174;Grandval;116;3;119 +63175;Herment;245;8;253 +63176;Heume-l'Église;105;3;108 +63177;Isserteaux;414;10;424 +63178;Issoire;14822;404;15226 +63179;Job;1018;28;1046 +63180;Joze;1101;18;1119 +63181;Jozerand;554;14;568 +63182;Jumeaux;635;13;648 +63183;Labessette;62;0;62 +63184;Lachaux;280;3;283 +63185;Lamontgie;649;8;657 +63186;Landogne;238;4;242 +63187;Lapeyrouse;551;12;563 +63188;Laps;594;14;608 +63189;Laqueuille;369;4;373 +63190;Larodde;265;7;272 +63191;Lastic;109;2;111 +63448;Le Vernet-Chaméane;808;64;872 +63193;Lempdes;8409;423;8832 +63194;Lempty;389;7;396 +63195;Lezoux;6152;73;6225 +63196;Limons;754;13;767 +63197;Lisseuil;122;1;123 +63198;Loubeyrat;1342;20;1362 +63199;Ludesse;489;6;495 +63200;Lussat;917;17;934 +63201;Luzillat;1131;18;1149 +63202;Madriat;109;3;112 +63203;Malauzat;1145;17;1162 +63204;Malintrat;1132;22;1154 +63205;Manglieu;468;4;472 +63206;Manzat;1371;20;1391 +63207;Marat;816;12;828 +63208;Marcillat;284;5;289 +63209;Mareugheol;198;6;204 +63210;Maringues;3154;26;3180 +63211;Marsac-en-Livradois;1458;45;1503 +63212;Marsat;1360;37;1397 +63213;Les Martres-d'Artière;2156;22;2178 +63214;Les Martres-de-Veyre;3976;56;4032 +63215;Martres-sur-Morge;670;8;678 +63216;Mauzun;115;4;119 +63218;Mayres;200;5;205 +63219;Mazaye;723;11;734 +63220;Mazoires;98;3;101 +63221;Medeyrolles;118;0;118 +63222;Meilhaud;496;9;505 +63223;Menat;547;12;559 +63224;Ménétrol;1635;25;1660 +63225;Messeix;1045;40;1085 +63227;Mirefleurs;2436;45;2481 +63228;Miremont;298;9;307 +63229;Moissat;1225;22;1247 +63230;Le Monestier;210;3;213 +63231;La Monnerie-le-Montel;1722;32;1754 +63232;Mons;538;13;551 +63236;Mont-Dore;1278;18;1296 +63233;Montaigut;987;8;995 +63234;Montaigut-le-Blanc;864;14;878 +63235;Montcel;504;7;511 +63237;Montel-de-Gelat;438;8;446 +63238;Montfermy;228;1;229 +63239;Montmorin;722;22;744 +63240;Montpensier;447;9;456 +63241;Montpeyroux;335;15;350 +63242;Moriat;366;9;375 +63243;Moureuille;363;5;368 +63245;Mozac;3878;64;3942 +63226;Mur-sur-Allier;3412;74;3486 +63246;Murat-le-Quaire;472;16;488 +63247;Murol;588;10;598 +63248;Nébouzat;836;14;850 +63249;Néronde-sur-Dore;514;8;522 +63250;Neschers;834;18;852 +63251;Neuf-Église;291;7;298 +63252;Neuville;382;7;389 +63253;Noalhat;247;5;252 +63254;Nohanent;2225;36;2261 +63255;Nonette-Orsonnette;575;14;589 +63256;Novacelles;145;2;147 +63257;Olby;795;10;805 +63258;Olliergues;752;20;772 +63259;Olloix;315;9;324 +63260;Olmet;165;5;170 +63261;Orbeil;841;28;869 +63262;Orcet;2669;38;2707 +63263;Orcines;3388;87;3475 +63264;Orcival;243;1;244 +63265;Orléat;2157;42;2199 +63267;Palladuc;549;13;562 +63268;Pardines;279;5;284 +63269;Parent;859;16;875 +63270;Parentignat;523;19;542 +63271;Paslières;1513;36;1549 +63272;Pérignat-lès-Sarliève;2680;68;2748 +63273;Pérignat-sur-Allier;1509;30;1539 +63274;Perpezat;432;6;438 +63275;Perrier;888;19;907 +63276;Peschadoires;2132;64;2196 +63277;Peslières;66;0;66 +63278;Pessat-Villeneuve;667;5;672 +63279;Picherande;347;6;353 +63280;Pignols;338;6;344 +63281;Pionsat;1087;21;1108 +63282;Plauzat;1667;21;1688 +63284;Pont-du-Château;11441;295;11736 +63283;Pontaumur;645;114;759 +63285;Pontgibaud;756;17;773 +63286;Pouzol;276;12;288 +63287;Les Pradeaux;337;7;344 +63288;Prompsat;429;13;442 +63289;Prondines;260;9;269 +63290;Pulvérières;406;8;414 +63291;Puy-Guillaume;2752;44;2796 +63292;Puy-Saint-Gulmier;159;4;163 +63293;Le Quartier;214;7;221 +63294;Queuille;276;6;282 +63295;Randan;1573;16;1589 +63296;Ravel;727;14;741 +63297;Reignat;389;1;390 +63298;La Renaudie;123;4;127 +63299;Rentières;113;0;113 +63300;Riom;19180;819;19999 +63301;Ris;765;8;773 +63302;La Roche-Blanche;3422;67;3489 +63303;Roche-Charles-la-Mayrand;40;0;40 +63304;Roche-d'Agoux;105;1;106 +63306;La Roche-Noire;618;9;627 +63305;Rochefort-Montagne;859;144;1003 +63307;Romagnat;7705;177;7882 +63308;Royat;4651;126;4777 +63309;Saillant;288;1;289 +63311;Saint-Agoulin;334;2;336 +63312;Saint-Alyre-d'Arlanc;170;4;174 +63313;Saint-Alyre-ès-Montagne;126;5;131 +63314;Saint-Amant-Roche-Savine;508;28;536 +63315;Saint-Amant-Tallende;1743;37;1780 +63317;Saint-André-le-Coq;526;3;529 +63318;Saint-Angel;427;9;436 +63319;Saint-Anthème;698;22;720 +63320;Saint-Avit;234;5;239 +63321;Saint-Babel;944;15;959 +63322;Saint-Beauzire;2180;31;2211 +63323;Saint-Bonnet-le-Bourg;163;3;166 +63324;Saint-Bonnet-le-Chastel;208;7;215 +63325;Saint-Bonnet-lès-Allier;427;6;433 +63326;Saint-Bonnet-près-Orcival;487;8;495 +63327;Saint-Bonnet-près-Riom;2114;40;2154 +63330;Saint-Cirgues-sur-Couze;351;5;356 +63332;Saint-Clément-de-Régnat;557;6;563 +63331;Saint-Clément-de-Valorgue;231;5;236 +63333;Saint-Denis-Combarnazat;223;8;231 +63334;Saint-Dier-d'Auvergne;519;22;541 +63335;Saint-Diéry;498;11;509 +63336;Saint-Donat;206;4;210 +63337;Saint-Éloy-la-Glacière;56;0;56 +63338;Saint-Éloy-les-Mines;3709;172;3881 +63339;Saint-Étienne-des-Champs;142;1;143 +63340;Saint-Étienne-sur-Usson;276;3;279 +63341;Saint-Ferréol-des-Côtes;544;17;561 +63342;Saint-Floret;251;7;258 +63343;Saint-Flour;285;3;288 +63344;Saint-Gal-sur-Sioule;135;4;139 +63345;Saint-Genès-Champanelle;3612;105;3717 +63346;Saint-Genès-Champespe;219;7;226 +63347;Saint-Genès-du-Retz;483;19;502 +63348;Saint-Genès-la-Tourette;180;1;181 +63349;Saint-Georges-de-Mons;1955;48;2003 +63350;Saint-Georges-sur-Allier;1250;16;1266 +63353;Saint-Germain-l'Herm;487;27;514 +63352;Saint-Germain-Lembron;1980;37;2017 +63351;Saint-Germain-près-Herment;84;1;85 +63354;Saint-Gervais-d'Auvergne;1340;120;1460 +63355;Saint-Gervais-sous-Meymont;235;6;241 +63356;Saint-Gervazy;329;12;341 +63357;Saint-Hérent;114;2;116 +63360;Saint-Hilaire;161;5;166 +63358;Saint-Hilaire-la-Croix;348;3;351 +63359;Saint-Hilaire-les-Monges;91;1;92 +63362;Saint-Ignat;903;16;919 +63363;Saint-Jacques-d'Ambur;276;6;282 +63364;Saint-Jean-d'Heurs;659;6;665 +63365;Saint-Jean-des-Ollières;451;11;462 +63366;Saint-Jean-en-Val;354;3;357 +63367;Saint-Jean-Saint-Gervais;124;1;125 +63368;Saint-Julien-de-Coppel;1276;25;1301 +63369;Saint-Julien-la-Geneste;121;3;124 +63370;Saint-Julien-Puy-Lavèze;359;4;363 +63371;Saint-Just;157;1;158 +63372;Saint-Laure;653;5;658 +63373;Saint-Maigner;190;3;193 +63376;Saint-Martin-d'Ollières;150;7;157 +63374;Saint-Martin-des-Olmes;287;7;294 +63375;Saint-Martin-des-Plains;155;1;156 +63378;Saint-Maurice;869;8;877 +63377;Saint-Maurice-près-Pionsat;371;5;376 +63379;Saint-Myon;485;6;491 +63380;Saint-Nectaire;741;3;744 +63381;Saint-Ours;1670;23;1693 +63382;Saint-Pardoux;404;14;418 +63383;Saint-Pierre-Colamine;249;5;254 +63384;Saint-Pierre-la-Bourlhonne;128;3;131 +63385;Saint-Pierre-le-Chastel;434;9;443 +63386;Saint-Pierre-Roche;463;4;467 +63387;Saint-Priest-Bramefant;865;17;882 +63388;Saint-Priest-des-Champs;702;14;716 +63389;Saint-Quentin-sur-Sauxillanges;112;0;112 +63390;Saint-Quintin-sur-Sioule;381;12;393 +63391;Saint-Rémy-de-Blot;230;4;234 +63392;Saint-Rémy-de-Chargnat;572;9;581 +63393;Saint-Rémy-sur-Durolle;1741;28;1769 +63394;Saint-Romain;212;6;218 +63395;Saint-Sandoux;955;18;973 +63396;Saint-Saturnin;1172;96;1268 +63397;Saint-Sauves-d'Auvergne;1133;20;1153 +63398;Saint-Sauveur-la-Sagne;95;1;96 +63399;Saint-Sulpice;87;6;93 +63400;Saint-Sylvestre-Pragoulin;1085;19;1104 +63401;Saint-Victor-la-Rivière;247;6;253 +63402;Saint-Victor-Montvianeix;249;6;255 +63403;Saint-Vincent;411;10;421 +63404;Saint-Yvoine;595;11;606 +63310;Sainte-Agathe;180;2;182 +63328;Sainte-Catherine;52;2;54 +63329;Sainte-Christine;126;3;129 +63405;Sallèdes;588;13;601 +63406;Sardon;314;2;316 +63407;Saulzet-le-Froid;272;7;279 +63408;Sauret-Besserve;164;3;167 +63409;Saurier;270;2;272 +63410;Sauvagnat;129;2;131 +63411;Sauvagnat-Sainte-Marthe;481;9;490 +63412;Sauvessanges;527;6;533 +63413;La Sauvetat;720;8;728 +63414;Sauviat;542;10;552 +63415;Sauxillanges;1255;13;1268 +63416;Savennes;94;8;102 +63417;Sayat;2344;32;2376 +63418;Sermentizon;576;8;584 +63419;Servant;531;11;542 +63420;Seychalles;785;11;796 +63421;Singles;167;5;172 +63422;Solignat;497;9;506 +63423;Sugères;605;9;614 +63424;Surat;567;12;579 +63425;Tallende;1521;42;1563 +63426;Tauves;780;16;796 +63427;Teilhède;457;13;470 +63428;Teilhet;289;2;291 +63429;Ternant-les-Eaux;37;2;39 +63430;Thiers;11847;322;12169 +63431;Thiolières;161;1;162 +63432;Thuret;921;49;970 +63433;Tortebesse;69;3;72 +63192;La Tour-d'Auvergne;640;30;670 +63434;Tours-sur-Meymont;516;23;539 +63435;Tourzel-Ronzières;246;1;247 +63436;Tralaigues;78;0;78 +63437;Trémouille-Saint-Loup;147;4;151 +63438;Trézioux;476;6;482 +63439;Usson;286;2;288 +63440;Valbeleix;127;0;127 +63441;Valcivières;209;3;212 +63442;Valz-sous-Châteauneuf;51;2;53 +63443;Varennes-sur-Morge;404;7;411 +63444;Varennes-sur-Usson;285;4;289 +63445;Vassel;289;5;294 +63446;Vensat;505;4;509 +63447;Vergheas;62;1;63 +63449;Le Vernet-Sainte-Marguerite;298;6;304 +63450;Verneugheol;241;11;252 +63451;Vernines;420;28;448 +63452;Verrières;71;2;73 +63453;Vertaizon;3187;31;3218 +63454;Vertolaye;535;11;546 +63455;Veyre-Monton;3542;58;3600 +63457;Vic-le-Comte;5197;107;5304 +63456;Vichel;352;10;362 +63458;Villeneuve;161;0;161 +63459;Villeneuve-les-Cerfs;532;4;536 +63460;Villosanges;349;9;358 +63461;Vinzelles;351;4;355 +63462;Virlet;272;4;276 +63463;Viscomtat;530;9;539 +63464;Vitrac;349;12;361 +63465;Viverols;408;9;417 +63466;Vodable;196;3;199 +63467;Voingt;33;1;34 +63468;Vollore-Montagne;305;8;313 +63469;Vollore-Ville;743;14;757 +63470;Volvic;4487;69;4556 +63471;Youx;915;19;934 +63472;Yronde-et-Buron;648;18;666 +63473;Yssac-la-Tourette;384;7;391 +64001;Aast;181;7;188 +64002;Abère;162;1;163 +64003;Abidos;226;7;233 +64004;Abitain;102;1;103 +64005;Abos;542;14;556 +64006;Accous;461;13;474 +64007;Agnos;1019;25;1044 +64008;Ahaxe-Alciette-Bascassan;274;13;287 +64009;Ahetze;2158;41;2199 +64010;Aïcirits-Camou-Suhast;670;16;686 +64011;Aincille;112;6;118 +64012;Ainharp;141;1;142 +64013;Ainhice-Mongelos;173;0;173 +64014;Ainhoa;672;7;679 +64016;Aldudes;322;6;328 +64017;Alos-Sibas-Abense;319;6;325 +64015;Alçay-Alçabéhéty-Sunharette;226;7;233 +64018;Amendeuix-Oneix;448;9;457 +64019;Amorots-Succos;232;1;233 +64225;Ance Féas;612;15;627 +64021;Andoins;637;12;649 +64022;Andrein;131;1;132 +64023;Angaïs;889;23;912 +64024;Anglet;38929;1229;40158 +64025;Angous;102;0;102 +64026;Anhaux;387;10;397 +64027;Anos;192;3;195 +64028;Anoye;144;2;146 +64029;Aramits;669;16;685 +64031;Arancou;162;3;165 +64032;Araujuzon;194;8;202 +64033;Araux;142;1;143 +64034;Arbérats-Sillègue;257;7;264 +64035;Arbonne;2223;59;2282 +64036;Arbouet-Sussaute;322;3;325 +64037;Arbus;1205;22;1227 +64038;Arcangues;3160;80;3240 +64039;Aren;246;1;247 +64041;Aressy;712;10;722 +64040;Arette;1057;31;1088 +64042;Argagnon;702;23;725 +64043;Argelos;282;4;286 +64044;Arget;78;1;79 +64045;Arhansus;74;1;75 +64046;Armendarits;405;4;409 +64047;Arnéguy;238;3;241 +64048;Arnos;113;1;114 +64049;Aroue-Ithorots-Olhaïby;240;8;248 +64050;Arrast-Larrebieu;95;3;98 +64051;Arraute-Charritte;385;6;391 +64052;Arricau-Bordes;108;0;108 +64053;Arrien;185;3;188 +64054;Arros-de-Nay;783;22;805 +64056;Arrosès;139;2;141 +64058;Arthez-d'Asson;491;10;501 +64057;Arthez-de-Béarn;1862;43;1905 +64059;Artigueloutan;1090;29;1119 +64060;Artiguelouve;1621;45;1666 +64061;Artix;3428;60;3488 +64062;Arudy;2229;46;2275 +64063;Arzacq-Arraziguet;1089;22;1111 +64064;Asasp-Arros;461;9;470 +64065;Ascain;4194;111;4305 +64066;Ascarat;321;9;330 +64067;Assat;1828;42;1870 +64068;Asson;2031;51;2082 +64069;Aste-Béon;237;6;243 +64070;Astis;306;1;307 +64071;Athos-Aspis;211;5;216 +64072;Aubertin;656;14;670 +64073;Aubin;239;5;244 +64074;Aubous;48;0;48 +64075;Audaux;164;73;237 +64077;Auga;153;3;156 +64078;Auriac;238;6;244 +64079;Aurions-Idernes;104;3;107 +64080;Aussevielle;785;24;809 +64081;Aussurucq;245;2;247 +64082;Auterrive;130;1;131 +64083;Autevielle-Saint-Martin-Bideren;205;3;208 +64084;Aydie;140;2;142 +64085;Aydius;114;1;115 +64086;Ayherre;1042;27;1069 +64087;Baigts-de-Béarn;876;22;898 +64088;Balansun;287;7;294 +64089;Baleix;143;0;143 +64090;Baliracq-Maumusson;122;1;123 +64091;Baliros;475;5;480 +64092;Banca;346;7;353 +64093;Barcus;642;6;648 +64094;Bardos;1828;50;1878 +64095;Barinque;606;12;618 +64096;Barraute-Camu;174;1;175 +64097;Barzun;591;7;598 +64098;Bassillon-Vauzé;66;2;68 +64100;Bassussarry;3126;93;3219 +64099;Bastanès;99;4;103 +64289;La Bastide-Clairence;979;34;1013 +64101;Baudreix;611;117;728 +64102;Bayonne;51228;1170;52398 +64103;Bédeille;207;3;210 +64104;Bedous;597;15;612 +64105;Béguios;252;11;263 +64106;Béhasque-Lapiste;507;9;516 +64107;Béhorléguy;74;3;77 +64108;Bellocq;906;12;918 +64109;Bénéjacq;1942;44;1986 +64111;Bentayou-Sérée;109;1;110 +64110;Béost;217;3;220 +64112;Bérenx;435;4;439 +64113;Bergouey-Viellenave;116;2;118 +64114;Bernadets;577;9;586 +64115;Berrogain-Laruns;161;69;230 +64116;Bescat;255;5;260 +64117;Bésingrand;141;5;146 +64118;Bétracq;51;0;51 +64119;Beuste;637;20;657 +64121;Beyrie-en-Béarn;193;2;195 +64120;Beyrie-sur-Joyeuse;510;11;521 +64122;Biarritz;25404;704;26108 +64123;Bidache;1370;35;1405 +64124;Bidarray;677;15;692 +64125;Bidart;6811;134;6945 +64126;Bidos;1133;28;1161 +64127;Bielle;390;17;407 +64128;Bilhères;160;4;164 +64129;Billère;12804;229;13033 +64130;Biriatou;1222;21;1243 +64131;Biron;679;9;688 +64132;Bizanos;4626;126;4752 +64133;Boeil-Bezing;1287;25;1312 +64134;Bonloc;366;6;372 +64135;Bonnut;774;13;787 +64136;Borce;134;5;139 +64137;Bordères;646;19;665 +64138;Bordes;2884;40;2924 +64139;Bosdarros;1013;28;1041 +64140;Boucau;8350;149;8499 +64141;Boueilh-Boueilho-Lasque;348;8;356 +64142;Bougarber;852;27;879 +64143;Bouillon;157;5;162 +64144;Boumourt;158;2;160 +64145;Bourdettes;515;8;523 +64146;Bournos;331;4;335 +64147;Briscous;2806;44;2850 +64148;Bruges-Capbis-Mifaget;887;22;909 +64149;Bugnein;238;6;244 +64150;Bunus;127;0;127 +64151;Burgaronne;99;4;103 +64152;Buros;1883;52;1935 +64153;Burosse-Mendousse;66;1;67 +64154;Bussunarits-Sarrasquette;205;1;206 +64155;Bustince-Iriberry;96;1;97 +64156;Buziet;484;14;498 +64157;Buzy;974;22;996 +64158;Cabidos;180;7;187 +64159;Cadillon;110;4;114 +64160;Cambo-les-Bains;6551;109;6660 +64161;Came;978;19;997 +64162;Camou-Cihigue;101;4;105 +64165;Cardesse;296;1;297 +64166;Caro;204;5;209 +64167;Carrère;216;5;221 +64168;Carresse-Cassaber;676;10;686 +64170;Castagnède;207;2;209 +64171;Casteide-Cami;241;2;243 +64172;Casteide-Candau;290;3;293 +64173;Casteide-Doat;159;1;160 +64174;Castéra-Loubix;52;1;53 +64175;Castet;157;4;161 +64176;Castetbon;181;8;189 +64177;Castétis;618;25;643 +64178;Castetnau-Camblong;457;15;472 +64179;Castetner;134;6;140 +64180;Castetpugon;217;3;220 +64181;Castillon (Canton d'Arthez-de-Béarn);315;4;319 +64182;Castillon (Canton de Lembeye);69;1;70 +64183;Caubios-Loos;563;17;580 +64184;Cescau;598;17;615 +64185;Cette-Eygun;68;1;69 +64186;Charre;213;3;216 +64187;Charritte-de-Bas;268;9;277 +64188;Chéraute;1089;154;1243 +64189;Ciboure;6251;179;6430 +64190;Claracq;227;3;230 +64191;Coarraze;2176;141;2317 +64192;Conchez-de-Béarn;120;1;121 +64193;Corbère-Abères;108;2;110 +64194;Coslédaà-Lube-Boast;392;1;393 +64195;Coublucq;102;2;104 +64196;Crouseilles;125;0;125 +64197;Cuqueron;189;5;194 +64198;Denguin;1747;40;1787 +64199;Diusse;143;4;147 +64200;Doazon;186;3;189 +64201;Dognen;220;9;229 +64202;Domezain-Berraute;505;27;532 +64203;Doumy;305;7;312 +64204;Eaux-Bonnes;243;4;247 +64205;Escos;236;4;240 +64206;Escot;127;1;128 +64207;Escou;414;15;429 +64208;Escoubès;411;8;419 +64209;Escout;438;8;446 +64210;Escurès;148;1;149 +64211;Eslourenties-Daban;332;4;336 +64212;Espéchède;142;2;144 +64213;Espelette;2024;49;2073 +64214;Espès-Undurein;495;17;512 +64215;Espiute;108;3;111 +64216;Espoey;1169;45;1214 +64217;Esquiule;537;12;549 +64218;Estérençuby;345;1;346 +64219;Estialescq;267;6;273 +64220;Estos;526;15;541 +64221;Etcharry;130;19;149 +64222;Etchebar;73;1;74 +64223;Etsaut;69;2;71 +64224;Eysus;645;17;662 +64226;Fichous-Riumayou;179;1;180 +64227;Gabaston;662;13;675 +64228;Gabat;256;2;258 +64229;Gamarthe;126;5;131 +64230;Gan;5510;105;5615 +64231;Garindein;500;9;509 +64232;Garlède-Mondebat;222;2;224 +64233;Garlin;1387;24;1411 +64234;Garos;257;9;266 +64235;Garris;282;8;290 +64236;Gayon;55;1;56 +64237;Gelos;3543;169;3712 +64238;Ger;1899;48;1947 +64239;Gerderest;137;1;138 +64240;Gère-Bélesten;190;7;197 +64241;Géronce;455;7;462 +64242;Gestas;70;0;70 +64243;Géus-d'Arzacq;200;2;202 +64244;Geüs-d'Oloron;252;9;261 +64245;Goès;624;17;641 +64246;Gomer;314;7;321 +64247;Gotein-Libarrenx;477;17;494 +64249;Guéthary;1320;36;1356 +64250;Guiche;970;31;1001 +64251;Guinarthe-Parenties;224;8;232 +64252;Gurmençon;884;27;911 +64253;Gurs;419;10;429 +64254;Hagetaubin;578;18;596 +64255;Halsou;595;5;600 +64256;Hasparren;6879;273;7152 +64257;Haut-de-Bosdarros;335;1;336 +64258;Haux;82;1;83 +64259;Hélette;717;11;728 +64260;Hendaye;16484;397;16881 +64261;Herrère;387;2;389 +64262;Higuères-Souye;274;9;283 +64263;L' Hôpital-d'Orion;138;3;141 +64264;L' Hôpital-Saint-Blaise;69;2;71 +64265;Hosta;80;0;80 +64266;Hours;268;3;271 +64267;Ibarrolle;82;1;83 +64268;Idaux-Mendy;270;4;274 +64269;Idron;4846;157;5003 +64270;Igon;968;59;1027 +64271;Iholdy;549;8;557 +64272;Ilharre;152;1;153 +64273;Irissarry;886;13;899 +64274;Irouléguy;363;3;366 +64275;Ispoure;673;13;686 +64276;Issor;236;6;242 +64277;Isturits;518;12;530 +64279;Itxassou;2133;64;2197 +64280;Izeste;425;3;428 +64281;Jasses;138;4;142 +64282;Jatxou;1154;29;1183 +64283;Jaxu;202;0;202 +64284;Jurançon;7094;247;7341 +64285;Juxue;209;6;215 +64286;Laà-Mondrans;429;13;442 +64287;Laàs;136;3;139 +64288;Labastide-Cézéracq;555;8;563 +64290;Labastide-Monréjeau;589;17;606 +64291;Labastide-Villefranche;335;4;339 +64292;Labatmale;254;2;256 +64293;Labatut;175;2;177 +64294;Labets-Biscay;160;3;163 +64295;Labeyrie;123;5;128 +64296;Lacadée;155;4;159 +64297;Lacarre;174;4;178 +64298;Lacarry-Arhan-Charritte-de-Haut;130;0;130 +64299;Lacommande;214;4;218 +64300;Lacq;732;11;743 +64301;Lagor;1194;20;1214 +64302;Lagos;468;12;480 +64303;Laguinge-Restoue;158;8;166 +64304;Lahonce;2418;53;2471 +64305;Lahontan;514;10;524 +64306;Lahourcade;698;21;719 +64307;Lalongue;212;3;215 +64308;Lalonquette;274;5;279 +64309;Lamayou;201;5;206 +64310;Lanne-en-Barétous;494;6;500 +64311;Lannecaube;159;2;161 +64312;Lanneplaà;306;6;312 +64313;Lantabat;284;5;289 +64314;Larceveau-Arros-Cibits;413;3;416 +64315;Laroin;1076;26;1102 +64316;Larrau;197;4;201 +64317;Larressore;2053;30;2083 +64318;Larreule;183;5;188 +64319;Larribar-Sorhapuru;188;0;188 +64320;Laruns;1194;23;1217 +64321;Lasclaveries;244;5;249 +64322;Lasse;333;6;339 +64323;Lasserre;89;5;94 +64324;Lasseube;1736;41;1777 +64325;Lasseubetat;207;4;211 +64326;Lay-Lamidou;118;4;122 +64327;Lecumberry;172;4;176 +64328;Ledeuix;1032;29;1061 +64329;Lée;1270;58;1328 +64330;Lées-Athas;265;12;277 +64331;Lembeye;773;16;789 +64332;Lème;166;1;167 +64334;Léren;220;3;223 +64335;Lescar;9804;421;10225 +64336;Lescun;172;1;173 +64337;Lespielle;155;3;158 +64338;Lespourcy;192;6;198 +64339;Lestelle-Bétharram;831;81;912 +64340;Lichans-Sunhar;81;1;82 +64341;Lichos;135;1;136 +64342;Licq-Athérey;207;6;213 +64343;Limendous;706;8;714 +64344;Livron;405;16;421 +64345;Lohitzun-Oyhercq;203;1;204 +64346;Lombia;207;1;208 +64348;Lons;13374;249;13623 +64347;Lonçon;199;3;202 +64349;Loubieng;516;5;521 +64350;Louhossoa;887;18;905 +64351;Lourdios-Ichère;141;9;150 +64352;Lourenties;362;4;366 +64353;Louvie-Juzon;1058;29;1087 +64354;Louvie-Soubiron;119;1;120 +64355;Louvigny;140;2;142 +64356;Luc-Armau;113;0;113 +64357;Lucarré;59;0;59 +64358;Lucgarier;251;1;252 +64359;Lucq-de-Béarn;934;20;954 +64360;Lurbe-Saint-Christau;195;6;201 +64361;Lussagnet-Lusson;172;6;178 +64362;Luxe-Sumberraute;404;24;428 +64363;Lys;334;4;338 +64364;Macaye;587;10;597 +64365;Malaussanne;428;7;435 +64366;Mascaraàs-Haron;127;0;127 +64367;Maslacq;890;23;913 +64368;Masparraute;234;7;241 +64369;Maspie-Lalonquère-Juillacq;261;4;265 +64370;Maucor;534;15;549 +64371;Mauléon-Licharre;2954;231;3185 +64372;Maure;104;1;105 +64373;Mazères-Lezons;1833;44;1877 +64374;Mazerolles;1115;18;1133 +64375;Méharin;273;4;277 +64376;Meillon;916;16;932 +64377;Mendionde;844;24;868 +64378;Menditte;200;129;329 +64379;Mendive;164;4;168 +64380;Méracq;229;5;234 +64381;Méritein;288;9;297 +64382;Mesplède;365;13;378 +64383;Mialos;126;0;126 +64385;Miossens-Lanusse;267;2;269 +64386;Mirepeix;1278;37;1315 +64387;Momas;577;12;589 +64388;Momy;127;1;128 +64389;Monassut-Audiracq;359;3;362 +64390;Moncaup;156;12;168 +64391;Moncayolle-Larrory-Mendibieu;314;7;321 +64392;Moncla;91;2;93 +64393;Monein;4438;107;4545 +64394;Monpezat;83;1;84 +64395;Monségur;129;0;129 +64396;Mont;1124;93;1217 +64401;Mont-Disse;72;4;76 +64397;Montagut;116;2;118 +64398;Montaner;432;8;440 +64399;Montardon;2300;278;2578 +64400;Montaut;1110;46;1156 +64403;Montfort;181;3;184 +64404;Montory;306;13;319 +64405;Morlaàs;4282;256;4538 +64406;Morlanne;591;15;606 +64407;Mouguerre;5108;140;5248 +64408;Mouhous;57;0;57 +64409;Moumour;841;22;863 +64410;Mourenx;6485;175;6660 +64411;Musculdy;236;3;239 +64412;Nabas;107;2;109 +64413;Narcastet;754;12;766 +64414;Narp;113;2;115 +64415;Navailles-Angos;1521;22;1543 +64416;Navarrenx;1051;14;1065 +64417;Nay;3288;236;3524 +64418;Noguères;140;3;143 +64419;Nousty;1608;30;1638 +64420;Ogenne-Camptort;245;6;251 +64421;Ogeu-les-Bains;1289;29;1318 +64422;Oloron-Sainte-Marie;10684;621;11305 +64423;Oraàs;176;3;179 +64424;Ordiarp;527;5;532 +64425;Orègue;485;9;494 +64426;Orin;241;9;250 +64427;Orion;144;9;153 +64428;Orriule;132;2;134 +64429;Orsanco;110;4;114 +64430;Orthez;10449;657;11106 +64431;Os-Marsillon;533;9;542 +64432;Ossas-Suhare;84;2;86 +64433;Osse-en-Aspe;325;15;340 +64434;Ossenx;52;1;53 +64435;Osserain-Rivareyte;212;9;221 +64436;Ossès;835;23;858 +64437;Ostabat-Asme;194;2;196 +64438;Ouillon;552;13;565 +64439;Ousse;1661;50;1711 +64440;Ozenx-Montestrucq;382;17;399 +64441;Pagolle;261;5;266 +64442;Parbayse;319;10;329 +64443;Pardies;849;22;871 +64444;Pardies-Piétat;448;11;459 +64445;Pau;77130;1405;78535 +64446;Peyrelongue-Abos;150;2;152 +64447;Piets-Plasence-Moustrou;139;1;140 +64449;Poey-d'Oloron;166;4;170 +64448;Poey-de-Lescar;1655;46;1701 +64450;Pomps;290;6;296 +64451;Ponson-Debat-Pouts;95;3;98 +64452;Ponson-Dessus;258;7;265 +64453;Pontacq;2936;45;2981 +64454;Pontiacq-Viellepinte;184;2;186 +64455;Portet;169;3;172 +64456;Pouliacq;54;3;57 +64457;Poursiugues-Boucoue;190;4;194 +64458;Préchacq-Josbaig;293;7;300 +64459;Préchacq-Navarrenx;165;2;167 +64460;Précilhon;401;9;410 +64461;Puyoô;1133;16;1149 +64462;Ramous;495;6;501 +64463;Rébénacq;682;11;693 +64464;Ribarrouy;83;1;84 +64465;Riupeyrous;214;3;217 +64466;Rivehaute;262;18;280 +64467;Rontignon;833;16;849 +64468;Roquiague;119;2;121 +64469;Saint-Abit;317;8;325 +64470;Saint-Armou;636;22;658 +64471;Saint-Boès;367;12;379 +64472;Saint-Castin;888;18;906 +64474;Saint-Dos;160;1;161 +64476;Saint-Esteben;411;6;417 +64477;Saint-Étienne-de-Baïgorry;1477;39;1516 +64478;Saint-Faust;746;26;772 +64479;Saint-Girons-en-Béarn;157;4;161 +64480;Saint-Gladie-Arrive-Munein;200;4;204 +64481;Saint-Goin;230;4;234 +64482;Saint-Jammes;628;8;636 +64483;Saint-Jean-de-Luz;14093;454;14547 +64484;Saint-Jean-le-Vieux;849;17;866 +64485;Saint-Jean-Pied-de-Port;1587;263;1850 +64486;Saint-Jean-Poudge;73;0;73 +64487;Saint-Just-Ibarre;223;5;228 +64488;Saint-Laurent-Bretagne;434;12;446 +64489;Saint-Martin-d'Arberoue;315;10;325 +64490;Saint-Martin-d'Arrossa;537;15;552 +64491;Saint-Médard;211;4;215 +64492;Saint-Michel;295;3;298 +64493;Saint-Palais;1838;68;1906 +64494;Saint-Pé-de-Léren;258;6;264 +64495;Saint-Pée-sur-Nivelle;6849;150;6999 +64496;Saint-Pierre-d'Irube;4844;106;4950 +64498;Saint-Vincent;398;10;408 +64473;Sainte-Colome;356;4;360 +64475;Sainte-Engrâce;193;3;196 +64499;Salies-de-Béarn;4638;132;4770 +64500;Salles-Mongiscard;308;5;313 +64501;Sallespisse;577;8;585 +64502;Sames;699;6;705 +64503;Samsons-Lion;88;1;89 +64504;Sare;2651;27;2678 +64505;Sarpourenx;338;6;344 +64506;Sarrance;165;4;169 +64507;Saubole;137;3;140 +64508;Saucède;126;2;128 +64509;Sauguis-Saint-Étienne;165;5;170 +64510;Sault-de-Navailles;898;16;914 +64511;Sauvagnon;3313;96;3409 +64512;Sauvelade;271;4;275 +64513;Sauveterre-de-Béarn;1375;105;1480 +64514;Séby;195;7;202 +64515;Sedze-Maubecq;275;5;280 +64516;Sedzère;390;3;393 +64517;Séméacq-Blachon;167;8;175 +64518;Sendets;1007;20;1027 +64519;Serres-Castet;4261;116;4377 +64520;Serres-Morlaàs;783;31;814 +64521;Serres-Sainte-Marie;562;17;579 +64523;Sévignacq;749;14;763 +64522;Sévignacq-Meyracq;538;15;553 +64524;Simacourbe;404;2;406 +64525;Siros;752;14;766 +64526;Soumoulou;1584;23;1607 +64527;Souraïde;1400;27;1427 +64528;Suhescun;173;8;181 +64529;Sus;375;11;386 +64530;Susmiou;357;7;364 +64531;Tabaille-Usquain;44;2;46 +64532;Tadousse-Ussau;67;0;67 +64533;Tardets-Sorholus;541;11;552 +64534;Taron-Sadirac-Viellenave;192;0;192 +64535;Tarsacq;521;6;527 +64536;Thèze;836;16;852 +64537;Trois-Villes;131;3;134 +64538;Uhart-Cize;806;16;822 +64539;Uhart-Mixe;210;5;215 +64540;Urcuit;2492;62;2554 +64541;Urdès;305;3;308 +64542;Urdos;64;2;66 +64543;Urepel;284;7;291 +64544;Urost;76;2;78 +64545;Urrugne;10317;191;10508 +64546;Urt;2301;34;2335 +64547;Ustaritz;6822;266;7088 +64548;Uzan;176;4;180 +64549;Uzein;1232;23;1255 +64550;Uzos;742;29;771 +64551;Verdets;270;4;274 +64552;Vialer;188;3;191 +64554;Viellenave-d'Arthez;205;3;208 +64555;Viellenave-de-Navarrenx;161;3;164 +64556;Vielleségure;375;10;385 +64557;Vignes;441;21;462 +64558;Villefranque;2671;73;2744 +64559;Viodos-Abense-de-Bas;712;20;732 +64560;Viven;187;0;187 +65001;Adast;292;7;299 +65002;Adé;802;10;812 +65003;Adervielle-Pouchergues;132;1;133 +65004;Agos-Vidalos;416;10;426 +65005;Allier;411;10;421 +65006;Ancizan;271;7;278 +65007;Andrest;1396;28;1424 +65009;Anères;174;3;177 +65011;Les Angles;126;3;129 +65010;Angos;223;4;227 +65012;Anla;91;2;93 +65013;Ansost;57;2;59 +65014;Antichan;35;0;35 +65015;Antin;106;7;113 +65016;Antist;181;3;184 +65017;Aragnouet;248;2;250 +65018;Arbéost;85;1;86 +65019;Arcizac-Adour;534;11;545 +65020;Arcizac-ez-Angles;259;5;264 +65021;Arcizans-Avant;394;15;409 +65022;Arcizans-Dessus;125;1;126 +65023;Ardengost;13;0;13 +65024;Argelès-Bagnères;110;3;113 +65025;Argelès-Gazost;2901;169;3070 +65026;Aries-Espénan;71;0;71 +65028;Arné;213;5;218 +65029;Arras-en-Lavedan;489;11;500 +65247;Arrayou-Lahitte;107;0;107 +65031;Arreau;773;26;799 +65032;Arrens-Marsous;727;10;737 +65034;Arrodets;20;0;20 +65033;Arrodets-ez-Angles;110;2;112 +65035;Artagnan;512;12;524 +65036;Artalens-Souin;133;3;136 +65037;Artiguemy;92;1;93 +65038;Artigues;16;1;17 +65039;Aspin-Aure;45;0;45 +65040;Aspin-en-Lavedan;334;3;337 +65041;Asque;118;7;125 +65042;Asté;559;11;570 +65043;Astugue;258;9;267 +65044;Aubarède;297;6;303 +65045;Aucun;237;9;246 +65046;Aulon;84;5;89 +65047;Aureilhan;7745;222;7967 +65048;Aurensan;789;10;799 +65049;Auriébat;246;3;249 +65050;Avajan;78;1;79 +65051;Aventignan;205;7;212 +65052;Averan;68;0;68 +65053;Aveux;41;1;42 +65054;Avezac-Prat-Lahitte;602;8;610 +65055;Ayros-Arbouix;314;3;317 +65056;Ayzac-Ost;450;13;463 +65057;Azereix;986;16;1002 +65058;Azet;148;2;150 +65059;Bagnères-de-Bigorre;7253;263;7516 +65060;Banios;53;3;56 +65061;Barbachen;53;0;53 +65062;Barbazan-Debat;3463;75;3538 +65063;Barbazan-Dessus;165;3;168 +65481;Barèges;163;5;168 +65064;Bareilles;47;0;47 +65065;Barlest;290;8;298 +65066;Barrancoueu;33;0;33 +65067;Barry;125;9;134 +65068;Barthe;18;1;19 +65069;La Barthe-de-Neste;1227;30;1257 +65070;Bartrès;514;17;531 +65071;Batsère;36;0;36 +65072;Bazet;1748;15;1763 +65073;Bazillac;347;4;351 +65074;Bazordan;113;1;114 +65075;Bazus-Aure;131;7;138 +65076;Bazus-Neste;59;2;61 +65077;Beaucens;409;17;426 +65078;Beaudéan;395;10;405 +65079;Bégole;203;4;207 +65080;Bénac;548;9;557 +65081;Benqué-Molère;126;3;129 +65082;Berbérust-Lias;50;0;50 +65083;Bernac-Debat;683;16;699 +65084;Bernac-Dessus;294;4;298 +65085;Bernadets-Debat;112;1;113 +65086;Bernadets-Dessus;155;0;155 +65087;Bertren;174;5;179 +65088;Betbèze;45;1;46 +65089;Betpouey;87;3;90 +65090;Betpouy;78;3;81 +65091;Bettes;51;0;51 +65092;Beyrède-Jumet-Camous;217;2;219 +65093;Bize;215;8;223 +65094;Bizous;110;2;112 +65095;Bonnefont;339;11;350 +65096;Bonnemazon;64;2;66 +65097;Bonrepos;187;5;192 +65098;Boô-Silhen;310;7;317 +65099;Bordères-Louron;155;3;158 +65100;Bordères-sur-l'Échez;5227;112;5339 +65101;Bordes;762;18;780 +65102;Bouilh-Devant;21;2;23 +65103;Bouilh-Péreuilh;94;1;95 +65104;Boulin;288;9;297 +65105;Bourg-de-Bigorre;197;3;200 +65106;Bourisp;163;4;167 +65107;Bourréac;108;2;110 +65108;Bours;829;17;846 +65109;Bramevaque;34;1;35 +65110;Bugard;89;0;89 +65111;Bulan;61;0;61 +65112;Bun;146;5;151 +65113;Burg;275;11;286 +65114;Buzon;78;4;82 +65115;Cabanac;290;10;300 +65116;Cadéac;305;5;310 +65117;Cadeilhan-Trachère;39;1;40 +65118;Caharet;37;1;38 +65119;Caixon;375;4;379 +65120;Calavanté;335;6;341 +65121;Camalès;384;9;393 +65123;Campan;1332;53;1385 +65124;Camparan;55;2;57 +65125;Campistrous;316;7;323 +65126;Campuzan;157;5;162 +65482;Cantaous;443;11;454 +65127;Capvern;1285;26;1311 +65128;Castelbajac;135;3;138 +65129;Castelnau-Magnoac;798;21;819 +65130;Castelnau-Rivière-Basse;627;13;640 +65131;Castelvieilh;245;2;247 +65132;Castéra-Lanusse;44;0;44 +65133;Castéra-Lou;231;4;235 +65134;Casterets;13;0;13 +65135;Castillon;83;0;83 +65136;Caubous;39;0;39 +65137;Caussade-Rivière;97;3;100 +65138;Cauterets;908;19;927 +65139;Cazarilh;53;1;54 +65140;Cazaux-Debat;32;1;33 +65141;Cazaux-Fréchet-Anéran-Camors;48;2;50 +65142;Chelle-Debat;210;4;214 +65143;Chelle-Spou;119;0;119 +65144;Cheust;86;2;88 +65145;Chèze;48;0;48 +65146;Chis;315;1;316 +65147;Cieutat;600;11;611 +65148;Cizos;127;1;128 +65149;Clarac;180;5;185 +65150;Clarens;507;23;530 +65151;Collongues;148;4;152 +65153;Coussan;122;5;127 +65154;Créchets;56;0;56 +65155;Devèze;59;2;61 +65156;Dours;223;5;228 +65157;Ens;24;2;26 +65158;Esbareich;82;0;82 +65159;Escala;376;12;388 +65160;Escaunets;126;3;129 +65161;Escondeaux;281;5;286 +65162;Esconnets;35;1;36 +65163;Escots;34;1;35 +65164;Escoubès-Pouts;106;2;108 +65165;Esparros;183;1;184 +65166;Espèche;53;0;53 +65167;Espieilh;26;1;27 +65168;Esquièze-Sère;401;12;413 +65169;Estaing;83;1;84 +65170;Estampures;78;2;80 +65171;Estarvielle;37;0;37 +65172;Estensan;40;0;40 +65173;Esterre;191;7;198 +65174;Estirac;103;4;107 +65175;Ferrère;42;2;44 +65176;Ferrières;90;0;90 +65177;Fontrailles;151;3;154 +65178;Fréchède;50;0;50 +65179;Fréchendets;29;0;29 +65180;Fréchet-Aure;12;0;12 +65181;Fréchou-Fréchet;163;3;166 +65182;Gaillagos;128;1;129 +65183;Galan;714;14;728 +65184;Galez;182;2;184 +65185;Gardères;443;11;454 +65186;Gaudent;39;1;40 +65187;Gaussan;111;4;115 +65192;Gavarnie-Gèdre;345;9;354 +65189;Gayan;277;2;279 +65190;Gazave;67;0;67 +65191;Gazost;126;2;128 +65193;Gembrie;77;3;80 +65194;Générest;101;1;102 +65195;Génos;137;0;137 +65196;Gensac;98;2;100 +65197;Ger;156;9;165 +65198;Gerde;1136;34;1170 +65199;Germ;36;0;36 +65200;Germs-sur-l'Oussouet;110;3;113 +65201;Geu;173;4;177 +65202;Gez;327;13;340 +65203;Gez-ez-Angles;27;1;28 +65204;Gonez;28;0;28 +65205;Gouaux;55;1;56 +65206;Goudon;231;6;237 +65207;Gourgue;62;0;62 +65208;Grailhen;22;2;24 +65209;Grézian;81;0;81 +65210;Grust;37;1;38 +65211;Guchan;140;5;145 +65212;Guchen;343;11;354 +65213;Guizerix;123;3;126 +65214;Hachan;43;0;43 +65215;Hagedet;46;2;48 +65216;Hauban;111;2;113 +65217;Hautaget;54;2;56 +65218;Hèches;616;13;629 +65219;Hères;124;2;126 +65220;Hibarette;246;1;247 +65221;Hiis;251;5;256 +65222;Hitte;163;1;164 +65223;Horgues;1198;37;1235 +65224;Houeydets;267;6;273 +65225;Hourc;109;1;110 +65226;Ibos;2895;137;3032 +65228;Ilhet;118;0;118 +65229;Ilheu;38;0;38 +65230;Izaourt;257;6;263 +65231;Izaux;202;9;211 +65232;Jacque;74;1;75 +65233;Jarret;320;4;324 +65234;Jézeau;97;3;100 +65235;Juillan;4106;97;4203 +65236;Julos;405;11;416 +65237;Juncalas;166;5;171 +65238;Labassère;235;9;244 +65239;Labastide;157;5;162 +65240;Labatut-Rivière;397;5;402 +65241;Laborde;84;1;85 +65242;Lacassagne;232;2;234 +65243;Lafitole;477;12;489 +65244;Lagarde;524;7;531 +65245;Lagrange;227;7;234 +65248;Lahitte-Toupière;261;9;270 +65249;Lalanne;98;6;104 +65250;Lalanne-Trie;115;1;116 +65251;Laloubère;1883;57;1940 +65252;Lamarque-Pontacq;852;14;866 +65253;Lamarque-Rustaing;53;0;53 +65254;Laméac;147;4;151 +65256;Lanespède;150;2;152 +65257;Lanne;588;9;597 +65258;Lannemezan;5837;159;5996 +65259;Lansac;177;4;181 +65255;Lançon;32;0;32 +65260;Lapeyre;101;5;106 +65261;Laran;48;1;49 +65262;Larreule;410;14;424 +65263;Larroque;99;3;102 +65264;Lascazères;311;27;338 +65265;Laslades;340;10;350 +65266;Lassales;33;1;34 +65267;Lau-Balagnas;524;16;540 +65268;Layrisse;185;0;185 +65269;Lescurry;171;3;174 +65270;Lespouey;209;9;218 +65271;Lézignan;350;8;358 +65272;Lhez;77;0;77 +65273;Liac;196;1;197 +65274;Libaros;136;1;137 +65275;Lies;71;2;73 +65276;Lizos;117;1;118 +65277;Lombrès;100;3;103 +65278;Lomné;31;0;31 +65279;Lortet;213;8;221 +65280;Loubajac;403;8;411 +65281;Loucrup;228;4;232 +65282;Loudenvielle;301;5;306 +65283;Loudervielle;54;1;55 +65284;Louey;990;26;1016 +65285;Louit;196;3;199 +65286;Lourdes;13389;303;13692 +65287;Loures-Barousse;626;13;639 +65288;Lubret-Saint-Luc;55;0;55 +65289;Luby-Betmont;107;1;108 +65290;Luc;213;3;216 +65291;Lugagnan;136;3;139 +65292;Luquet;397;3;400 +65293;Lustar;118;3;121 +65294;Lutilhous;223;3;226 +65295;Luz-Saint-Sauveur;966;16;982 +65296;Madiran;418;10;428 +65297;Mansan;42;5;47 +65298;Marquerie;80;0;80 +65299;Marsac;224;4;228 +65300;Marsas;69;5;74 +65301;Marseillan;255;4;259 +65303;Mascaras;353;4;357 +65304;Maubourguet;2377;31;2408 +65305;Mauléon-Barousse;95;0;95 +65306;Mauvezin;234;4;238 +65307;Mazères-de-Neste;330;6;336 +65308;Mazerolles;106;4;110 +65309;Mazouau;16;3;19 +65310;Mérilheu;253;4;257 +65311;Mingot;99;0;99 +65313;Momères;759;19;778 +65314;Monfaucon;210;6;216 +65315;Monléon-Magnoac;439;241;680 +65316;Monlong;102;4;106 +65317;Mont;42;2;44 +65318;Montastruc;233;6;239 +65319;Montégut;135;2;137 +65320;Montgaillard;850;17;867 +65321;Montignac;138;2;140 +65322;Montoussé;250;7;257 +65323;Montsérié;80;0;80 +65324;Moulédous;211;7;218 +65325;Moumoulous;42;0;42 +65326;Mun;101;2;103 +65327;Nestier;156;2;158 +65328;Neuilh;98;4;102 +65329;Nistos;215;5;220 +65330;Nouilhan;200;4;204 +65331;Odos;3242;97;3339 +65332;Oléac-Debat;170;1;171 +65333;Oléac-Dessus;120;1;121 +65334;Omex;227;3;230 +65335;Ordizan;544;21;565 +65336;Organ;44;0;44 +65337;Orieux;115;3;118 +65338;Orignac;255;3;258 +65339;Orincles;330;7;337 +65340;Orleix;2127;33;2160 +65341;Oroix;120;2;122 +65342;Osmets;90;2;92 +65343;Ossen;233;4;237 +65344;Ossun;2368;49;2417 +65345;Ossun-ez-Angles;50;1;51 +65346;Oueilloux;179;5;184 +65347;Ourde;40;0;40 +65348;Ourdis-Cotdoussan;48;2;50 +65349;Ourdon;7;0;7 +65350;Oursbelille;1179;40;1219 +65351;Ousté;26;2;28 +65352;Ouzous;212;9;221 +65353;Ozon;279;5;284 +65354;Pailhac;69;2;71 +65355;Paréac;63;0;63 +65356;Péré;55;2;57 +65357;Peyraube;161;4;165 +65358;Peyret-Saint-André;54;2;56 +65359;Peyriguère;27;0;27 +65360;Peyrouse;276;7;283 +65361;Peyrun;84;1;85 +65362;Pierrefitte-Nestalas;1139;25;1164 +65363;Pinas;446;9;455 +65364;Pintac;22;3;25 +65366;Poueyferré;849;17;866 +65367;Poumarous;156;3;159 +65368;Pouy;46;1;47 +65369;Pouyastruc;675;22;697 +65370;Pouzac;1112;38;1150 +65371;Préchac;230;10;240 +65372;Pujo;636;13;649 +65373;Puntous;181;4;185 +65374;Puydarrieux;223;1;224 +65375;Rabastens-de-Bigorre;1453;26;1479 +65376;Recurt;204;8;212 +65377;Réjaumont;164;4;168 +65378;Ricaud;66;2;68 +65379;Ris;16;0;16 +65380;Sabalos;147;1;148 +65381;Sabarros;34;0;34 +65382;Sacoué;62;2;64 +65383;Sadournin;183;2;185 +65384;Sailhan;161;1;162 +65385;Saint-Arroman;87;5;92 +65386;Saint-Créac;97;0;97 +65387;Saint-Lanne;141;2;143 +65388;Saint-Lary-Soulan;835;25;860 +65389;Saint-Laurent-de-Neste;927;38;965 +65390;Saint-Lézer;426;14;440 +65392;Saint-Martin;452;12;464 +65393;Saint-Pastous;135;5;140 +65394;Saint-Paul;315;3;318 +65395;Saint-Pé-de-Bigorre;1162;16;1178 +65396;Saint-Savin;373;7;380 +65397;Saint-Sever-de-Rustan;173;2;175 +65391;Sainte-Marie;65;0;65 +65398;Saléchan;272;4;276 +65399;Saligos;107;3;110 +65400;Salles;233;7;240 +65401;Salles-Adour;594;7;601 +65402;Samuran;26;0;26 +65403;Sanous;98;2;100 +65404;Sariac-Magnoac;153;3;156 +65405;Sarlabous;68;4;72 +65406;Sarniguet;255;5;260 +65407;Sarp;108;2;110 +65408;Sarrancolin;563;13;576 +65409;Sarriac-Bigorre;303;5;308 +65410;Sarrouilles;529;17;546 +65411;Sassis;80;6;86 +65412;Sauveterre;169;4;173 +65413;Sazos;129;4;133 +65414;Ségalas;81;4;85 +65415;Ségus;235;1;236 +65416;Seich;89;3;92 +65417;Séméac;4926;135;5061 +65418;Sénac;296;7;303 +65419;Sentous;69;0;69 +65420;Sère-en-Lavedan;74;2;76 +65421;Sère-Lanso;52;2;54 +65423;Sère-Rustaing;127;0;127 +65422;Séron;327;3;330 +65424;Sers;114;2;116 +65425;Siarrouy;436;7;443 +65426;Sinzos;140;6;146 +65427;Siradan;284;5;289 +65428;Sireix;64;1;65 +65429;Sombrun;207;8;215 +65430;Soréac;47;1;48 +65431;Sost;92;4;96 +65432;Soublecause;187;3;190 +65433;Soues;3061;58;3119 +65435;Soulom;256;8;264 +65436;Souyeaux;306;7;313 +65437;Tajan;134;3;137 +65438;Talazac;76;1;77 +65439;Tarasteix;266;3;269 +65440;Tarbes;41518;1072;42590 +65441;Thèbe;76;3;79 +65442;Thermes-Magnoac;212;1;213 +65443;Thuy;19;0;19 +65444;Tibiran-Jaunac;312;4;316 +65445;Tilhouse;221;2;223 +65446;Tostat;535;8;543 +65447;Tournay;1209;20;1229 +65448;Tournous-Darré;87;4;91 +65449;Tournous-Devant;105;6;111 +65450;Tramezaïgues;34;1;35 +65451;Trébons;760;14;774 +65452;Trie-sur-Baïse;1043;25;1068 +65453;Troubat;74;1;75 +65454;Trouley-Labarthe;99;1;100 +65455;Tuzaguet;453;9;462 +65456;Uglas;287;11;298 +65457;Ugnouas;79;1;80 +65458;Uz;33;1;34 +65459;Uzer;105;4;109 +65460;Vic-en-Bigorre;4897;275;5172 +65461;Vidou;106;1;107 +65462;Vidouze;241;9;250 +65463;Viella;88;3;91 +65464;Vielle-Adour;509;10;519 +65465;Vielle-Aure;330;9;339 +65466;Vielle-Louron;94;0;94 +65467;Vier-Bordes;102;6;108 +65468;Vieuzos;44;1;45 +65469;Viey;32;2;34 +65470;Viger;140;3;143 +65471;Vignec;222;8;230 +65472;Villefranque;79;3;82 +65473;Villelongue;399;15;414 +65474;Villembits;115;2;117 +65475;Villemur;59;1;60 +65476;Villenave-près-Béarn;59;4;63 +65477;Villenave-près-Marsac;90;2;92 +65478;Viscos;35;2;37 +65479;Visker;340;10;350 +66001;L' Albère;80;1;81 +66002;Alénya;3601;59;3660 +66003;Amélie-les-Bains-Palalda;3460;32;3492 +66004;Les Angles;547;8;555 +66005;Angoustrine-Villeneuve-des-Escaldes;608;38;646 +66006;Ansignan;166;2;168 +66007;Arboussols;118;2;120 +66008;Argelès-sur-Mer;10383;240;10623 +66009;Arles-sur-Tech;2705;37;2742 +66010;Ayguatébia-Talau;38;0;38 +66011;Bages;4174;53;4227 +66012;Baho;3217;59;3276 +66013;Baillestavy;115;2;117 +66014;Baixas;2573;51;2624 +66015;Banyuls-dels-Aspres;1259;21;1280 +66016;Banyuls-sur-Mer;4761;77;4838 +66017;Le Barcarès;5915;40;5955 +66018;La Bastide;72;2;74 +66019;Bélesta;221;4;225 +66020;Bolquère;808;26;834 +66021;Bompas;7254;102;7356 +66022;Boule-d'Amont;55;0;55 +66023;Bouleternère;935;8;943 +66024;Le Boulou;5514;56;5570 +66025;Bourg-Madame;1224;82;1306 +66026;Brouilla;1437;15;1452 +66027;La Cabanasse;669;13;682 +66028;Cabestany;10106;215;10321 +66029;Caixas;142;1;143 +66030;Calce;210;2;212 +66032;Calmeilles;59;0;59 +66033;Camélas;464;7;471 +66034;Campôme;111;4;115 +66035;Campoussy;37;1;38 +66036;Canaveilles;26;0;26 +66037;Canet-en-Roussillon;12130;246;12376 +66038;Canohès;6097;109;6206 +66039;Caramany;150;3;153 +66040;Casefabre;40;1;41 +66041;Cases-de-Pène;926;22;948 +66042;Cassagnes;267;6;273 +66043;Casteil;136;2;138 +66044;Castelnou;315;5;320 +66045;Catllar;771;15;786 +66047;Caudiès-de-Conflent;17;2;19 +66046;Caudiès-de-Fenouillèdes;618;12;630 +66048;Cerbère;1355;17;1372 +66049;Céret;7798;228;8026 +66050;Claira;4181;53;4234 +66051;Clara-Villerach;256;6;262 +66063;Les Cluses;242;3;245 +66052;Codalet;386;12;398 +66053;Collioure;2427;29;2456 +66054;Conat;61;3;64 +66055;Corbère;733;22;755 +66056;Corbère-les-Cabanes;1070;15;1085 +66057;Corneilla-de-Conflent;490;4;494 +66059;Corneilla-del-Vercol;2293;28;2321 +66058;Corneilla-la-Rivière;1991;36;2027 +66060;Corsavy;218;19;237 +66061;Coustouges;98;0;98 +66062;Dorres;169;7;176 +66064;Égat;438;11;449 +66065;Elne;8941;108;9049 +66066;Enveitg;641;22;663 +66067;Err;673;22;695 +66068;Escaro;106;1;107 +66070;Espira-de-Conflent;168;3;171 +66069;Espira-de-l'Agly;3455;149;3604 +66071;Estagel;2016;18;2034 +66072;Estavar;472;17;489 +66073;Estoher;145;1;146 +66074;Eus;388;4;392 +66075;Eyne;130;8;138 +66076;Felluns;70;0;70 +66077;Fenouillet;89;1;90 +66078;Fillols;185;7;192 +66079;Finestret;176;7;183 +66124;Font-Romeu-Odeillo-Via;1928;216;2144 +66080;Fontpédrouse;123;2;125 +66081;Fontrabiouse;127;3;130 +66082;Formiguères;479;4;483 +66083;Fosse;40;0;40 +66084;Fourques;1280;19;1299 +66085;Fuilla;448;24;472 +66086;Glorianes;25;0;25 +66088;Ille-sur-Têt;5446;61;5507 +66089;Joch;265;8;273 +66090;Jujols;44;2;46 +66091;Lamanère;46;1;47 +66092;Lansac;89;0;89 +66093;Laroque-des-Albères;2112;41;2153 +66094;Latour-Bas-Elne;2797;41;2838 +66095;Latour-de-Carol;424;4;428 +66096;Latour-de-France;1026;14;1040 +66097;Lesquerde;133;3;136 +66098;La Llagonne;219;10;229 +66099;Llauro;317;2;319 +66100;Llo;172;3;175 +66101;Llupia;1943;41;1984 +66102;Mantet;30;1;31 +66103;Marquixanes;555;7;562 +66104;Los Masos;966;12;978 +66105;Matemale;267;5;272 +66106;Maureillas-las-Illas;2544;47;2591 +66107;Maury;785;5;790 +66108;Millas;4279;48;4327 +66109;Molitg-les-Bains;233;4;237 +66117;Mont-Louis;152;9;161 +66111;Montalba-le-Château;149;2;151 +66112;Montauriol;247;5;252 +66113;Montbolo;180;2;182 +66114;Montescot;1712;39;1751 +66115;Montesquieu-des-Albères;1224;23;1247 +66116;Montferrer;188;4;192 +66118;Montner;348;7;355 +66119;Mosset;308;7;315 +66120;Nahuja;76;3;79 +66121;Néfiach;1280;35;1315 +66122;Nohèdes;63;2;65 +66123;Nyer;148;2;150 +66125;Olette;364;5;369 +66126;Oms;333;4;337 +66127;Opoul-Périllos;1199;8;1207 +66128;Oreilla;23;0;23 +66129;Ortaffa;1481;19;1500 +66130;Osséja;1330;64;1394 +66132;Palau-de-Cerdagne;408;10;418 +66133;Palau-del-Vidre;3142;45;3187 +66134;Passa;820;9;829 +66136;Perpignan;120158;1523;121681 +66137;Le Perthus;574;3;577 +66138;Peyrestortes;1427;24;1451 +66139;Pézilla-de-Conflent;46;0;46 +66140;Pézilla-la-Rivière;3662;53;3715 +66141;Pia;9035;87;9122 +66142;Planès;53;2;55 +66143;Planèzes;99;2;101 +66144;Pollestres;4887;80;4967 +66145;Ponteilla;2738;42;2780 +66148;Port-Vendres;4129;75;4204 +66146;Porta;116;7;123 +66147;Porté-Puymorens;101;8;109 +66149;Prades;6124;341;6465 +66150;Prats-de-Mollo-la-Preste;1163;19;1182 +66151;Prats-de-Sournia;78;4;82 +66152;Prugnanes;104;0;104 +66153;Prunet-et-Belpuig;49;0;49 +66154;Puyvalador;72;1;73 +66155;Py;88;0;88 +66156;Rabouillet;103;1;104 +66157;Railleu;32;1;33 +66158;Rasiguères;152;3;155 +66159;Réal;66;0;66 +66160;Reynès;1328;20;1348 +66161;Ria-Sirach;1325;30;1355 +66162;Rigarda;641;3;644 +66164;Rivesaltes;8610;163;8773 +66165;Rodès;619;6;625 +66166;Sahorre;382;6;388 +66167;Saillagouse;1089;25;1114 +66168;Saint-André;3443;42;3485 +66169;Saint-Arnac;115;1;116 +66171;Saint-Cyprien;10511;166;10677 +66172;Saint-Estève;11658;176;11834 +66173;Saint-Féliu-d'Amont;1133;17;1150 +66174;Saint-Féliu-d'Avall;2797;38;2835 +66175;Saint-Génis-des-Fontaines;2826;26;2852 +66176;Saint-Hippolyte;3052;29;3081 +66177;Saint-Jean-Lasseille;1540;18;1558 +66178;Saint-Jean-Pla-de-Corts;2218;45;2263 +66179;Saint-Laurent-de-Cerdans;1098;10;1108 +66180;Saint-Laurent-de-la-Salanque;10246;107;10353 +66183;Saint-Marsal;71;0;71 +66184;Saint-Martin-de-Fenouillet;55;4;59 +66185;Saint-Michel-de-Llotes;348;12;360 +66186;Saint-Nazaire;2688;40;2728 +66187;Saint-Paul-de-Fenouillet;1812;13;1825 +66188;Saint-Pierre-dels-Forcats;267;9;276 +66170;Sainte-Colombe-de-la-Commanderie;153;2;155 +66181;Sainte-Léocadie;127;1;128 +66182;Sainte-Marie-la-Mer;4773;61;4834 +66189;Saleilles;5282;97;5379 +66190;Salses-le-Château;3501;13;3514 +66191;Sansa;22;0;22 +66192;Sauto;91;1;92 +66193;Serdinya;246;10;256 +66194;Serralongue;226;2;228 +66195;Le Soler;7710;112;7822 +66196;Sorède;3267;47;3314 +66197;Souanyas;37;0;37 +66198;Sournia;498;5;503 +66199;Taillet;105;1;106 +66201;Tarerach;46;1;47 +66202;Targassonne;184;5;189 +66203;Taulis;52;0;52 +66204;Taurinya;336;11;347 +66205;Tautavel;866;19;885 +66206;Le Tech;95;0;95 +66207;Terrats;640;14;654 +66208;Théza;2040;97;2137 +66209;Thuès-Entre-Valls;37;2;39 +66210;Thuir;7635;130;7765 +66211;Tordères;165;7;172 +66212;Torreilles;3812;53;3865 +66213;Toulouges;6881;119;7000 +66214;Tresserre;1066;13;1079 +66215;Trévillach;157;0;157 +66216;Trilla;74;2;76 +66217;Trouillas;2067;23;2090 +66218;Ur;363;11;374 +66219;Urbanya;55;1;56 +66220;Valcebollère;42;2;44 +66221;Valmanya;34;0;34 +66222;Vernet-les-Bains;1387;38;1425 +66223;Villefranche-de-Conflent;213;5;218 +66224;Villelongue-de-la-Salanque;3254;35;3289 +66225;Villelongue-dels-Monts;1706;67;1773 +66226;Villemolaque;1370;22;1392 +66227;Villeneuve-de-la-Raho;3926;65;3991 +66228;Villeneuve-la-Rivière;1316;24;1340 +66231;Vingrau;606;11;617 +66230;Vinça;2075;25;2100 +66232;Vira;26;0;26 +66233;Vivès;176;4;180 +66234;Le Vivier;75;0;75 +67001;Achenheim;2123;29;2152 +67002;Adamswiller;377;14;391 +67003;Albé;446;15;461 +67005;Alteckendorf;868;19;887 +67006;Altenheim;212;1;213 +67008;Altorf;1293;18;1311 +67009;Altwiller;395;13;408 +67010;Andlau;1739;78;1817 +67011;Artolsheim;996;9;1005 +67012;Aschbach;682;20;702 +67013;Asswiller;276;3;279 +67016;Avolsheim;713;14;727 +67017;Baerendorf;302;5;307 +67018;Balbronn;656;10;666 +67019;Baldenheim;1169;18;1187 +67020;Barembach;874;7;881 +67021;Barr;7238;160;7398 +67022;Bassemberg;249;6;255 +67023;Batzendorf;988;20;1008 +67025;Beinheim;1875;23;1898 +67026;Bellefosse;150;0;150 +67027;Belmont;167;0;167 +67028;Benfeld;5753;96;5849 +67029;Berg;365;4;369 +67030;Bergbieten;704;7;711 +67031;Bernardswiller;1455;44;1499 +67032;Bernardvillé;231;2;233 +67033;Bernolsheim;602;7;609 +67034;Berstett;2437;41;2478 +67035;Berstheim;437;14;451 +67339;Betschdorf;4161;46;4207 +67036;Bettwiller;308;7;315 +67037;Biblisheim;358;5;363 +67038;Bietlenheim;277;3;280 +67039;Bilwisheim;467;1;468 +67040;Bindernheim;1032;10;1042 +67043;Bischheim;17093;202;17295 +67044;Bischholtz;273;0;273 +67045;Bischoffsheim;3330;58;3388 +67046;Bischwiller;12538;125;12663 +67047;Bissert;155;3;158 +67048;Bitschhoffen;459;15;474 +67049;Blaesheim;1316;19;1335 +67050;Blancherupt;38;3;41 +67051;Blienschwiller;321;10;331 +67054;Bolsenheim;531;5;536 +67055;Boofzheim;1381;17;1398 +67056;Bootzheim;728;6;734 +67057;Bosselshausen;166;7;173 +67058;Bossendorf;399;8;407 +67059;Bourg-Bruche;468;9;477 +67060;Bourgheim;640;10;650 +67061;Bouxwiller;3963;90;4053 +67062;Breitenau;313;6;319 +67063;Breitenbach;665;16;681 +67065;Breuschwickersheim;1253;20;1273 +67066;La Broque;2663;87;2750 +67067;Brumath;9986;103;10089 +67069;Buhl;524;1;525 +67070;Burbach;274;3;277 +67071;Bust;463;11;474 +67068;Buswiller;274;2;276 +67072;Butten;669;21;690 +67052;Bœrsch;2437;66;2503 +67053;Bœsenbiesen;321;11;332 +67073;Châtenois;4188;87;4275 +67074;Cleebourg;720;7;727 +67075;Climbach;440;6;446 +67076;Colroy-la-Roche;488;9;497 +67077;Cosswiller;574;13;587 +67078;Crastatt;270;1;271 +67079;Crœttwiller;176;3;179 +67080;Dachstein;1802;21;1823 +67081;Dahlenheim;765;12;777 +67082;Dalhunden;1171;8;1179 +67083;Dambach;736;13;749 +67084;Dambach-la-Ville;2201;41;2242 +67085;Dangolsheim;723;11;734 +67086;Daubensand;401;8;409 +67087;Dauendorf;1440;15;1455 +67088;Dehlingen;360;7;367 +67089;Dettwiller;2612;26;2638 +67090;Diebolsheim;694;44;738 +67091;Diedendorf;330;12;342 +67092;Dieffenbach-au-Val;627;14;641 +67093;Dieffenbach-lès-Wœrth;350;5;355 +67094;Dieffenthal;256;2;258 +67095;Diemeringen;1600;37;1637 +67096;Dimbsthal;311;13;324 +67097;Dingsheim;1275;19;1294 +67098;Dinsheim-sur-Bruche;1476;19;1495 +67099;Domfessel;286;4;290 +67100;Donnenheim;349;1;350 +67101;Dorlisheim;2647;31;2678 +67102;Dossenheim-Kochersberg;294;5;299 +67103;Dossenheim-sur-Zinsel;1058;26;1084 +67104;Drachenbronn-Birlenbach;762;17;779 +67105;Drulingen;1460;27;1487 +67106;Drusenheim;5154;42;5196 +67107;Duntzenheim;643;5;648 +67108;Duppigheim;1597;18;1615 +67109;Durningen;651;17;668 +67110;Durrenbach;1079;18;1097 +67111;Durstel;412;11;423 +67112;Duttlenheim;2890;29;2919 +67113;Eberbach-Seltz;422;7;429 +67115;Ebersheim;2239;24;2263 +67116;Ebersmunster;521;25;546 +67117;Eckartswiller;431;12;443 +67118;Eckbolsheim;6857;61;6918 +67119;Eckwersheim;1328;18;1346 +67120;Eichhoffen;527;12;539 +67121;Elsenheim;813;10;823 +67123;Engwiller;501;1;502 +67124;Entzheim;2390;13;2403 +67125;Epfig;2267;75;2342 +67126;Erckartswiller;299;2;301 +67127;Ergersheim;1358;13;1371 +67128;Ernolsheim-Bruche;1875;18;1893 +67129;Ernolsheim-lès-Saverne;594;9;603 +67130;Erstein;10630;124;10754 +67131;Eschau;5303;51;5354 +67132;Eschbach;931;11;942 +67133;Eschbourg;484;7;491 +67134;Eschwiller;183;0;183 +67135;Ettendorf;771;5;776 +67136;Eywiller;280;5;285 +67137;Fegersheim;5737;65;5802 +67138;Fessenheim-le-Bas;561;8;569 +67139;Flexbourg;457;10;467 +67140;Forstfeld;737;4;741 +67141;Forstheim;584;5;589 +67142;Fort-Louis;296;1;297 +67143;Fouchy;656;18;674 +67144;Fouday;341;2;343 +67145;Friedolsheim;235;1;236 +67146;Friesenheim;627;4;631 +67148;Frohmuhl;181;4;185 +67147;Frœschwiller;503;4;507 +67149;Furchhausen;415;8;423 +67150;Furdenheim;1315;22;1337 +67151;Gambsheim;4883;40;4923 +67152;Geispolsheim;7540;76;7616 +67153;Geiswiller-Zœbersdorf;408;6;414 +67154;Gerstheim;3448;24;3472 +67155;Gertwiller;1250;21;1271 +67156;Geudertheim;2530;29;2559 +67161;Gottenhouse;384;11;395 +67162;Gottesheim;346;8;354 +67163;Gougenheim;548;13;561 +67164;Goxwiller;845;20;865 +67165;Grandfontaine;396;7;403 +67166;Grassendorf;250;4;254 +67167;Grendelbruch;1201;13;1214 +67168;Gresswiller;1696;18;1714 +67169;Gries;2864;42;2906 +67172;Griesheim-près-Molsheim;2188;39;2227 +67173;Griesheim-sur-Souffel;1125;18;1143 +67174;Gumbrechtshoffen;1175;7;1182 +67176;Gundershoffen;3679;56;3735 +67178;Gungwiller;279;5;284 +67177;Gunstett;655;12;667 +67159;Gœrlingen;227;6;233 +67160;Gœrsdorf;1072;25;1097 +67179;Haegen;677;9;686 +67180;Haguenau;34504;546;35050 +67181;Handschuheim;268;8;276 +67182;Hangenbieten;1554;23;1577 +67183;Harskirchen;860;20;880 +67184;Hatten;1928;30;1958 +67185;Hattmatt;691;4;695 +67186;Hegeney;424;7;431 +67187;Heidolsheim;523;8;531 +67188;Heiligenberg;676;10;686 +67189;Heiligenstein;965;20;985 +67190;Hengwiller;190;1;191 +67191;Herbitzheim;1839;47;1886 +67192;Herbsheim;925;10;935 +67194;Herrlisheim;4861;51;4912 +67195;Hessenheim;620;10;630 +67196;Hilsenheim;2633;28;2661 +67197;Hindisheim;1502;21;1523 +67198;Hinsbourg;112;3;115 +67199;Hinsingen;87;1;88 +67200;Hipsheim;1010;8;1018 +67201;Hirschland;324;7;331 +67202;Hochfelden;3987;38;4025 +67203;Hochstett;373;5;378 +67206;Hoffen;1125;18;1143 +67208;Hohengœft;536;8;544 +67209;Hohfrankenheim;265;2;267 +67210;Le Hohwald;505;13;518 +67212;Holtzheim;3656;28;3684 +67213;Hunspach;637;16;653 +67214;Hurtigheim;834;7;841 +67215;Huttendorf;505;3;508 +67216;Huttenheim;2701;35;2736 +67204;Hœnheim;11215;80;11295 +67205;Hœrdt;4370;58;4428 +67217;Ichtratzheim;327;4;331 +67218;Illkirch-Graffenstaden;26780;666;27446 +67220;Ingenheim;333;2;335 +67221;Ingolsheim;319;5;324 +67222;Ingwiller;4064;37;4101 +67223;Innenheim;1188;6;1194 +67225;Issenhausen;111;2;113 +67226;Ittenheim;2111;24;2135 +67227;Itterswiller;242;4;246 +67229;Jetterswiller;193;2;195 +67230;Kaltenhouse;2333;18;2351 +67231;Kauffenheim;215;2;217 +67232;Keffenach;193;7;200 +67233;Kertzfeld;1221;20;1241 +67234;Keskastel;1520;26;1546 +67235;Kesseldorf;404;7;411 +67236;Kienheim;553;9;562 +67237;Kilstett;2510;32;2542 +67238;Kindwiller;637;7;644 +67239;Kintzheim;1639;31;1670 +67240;Kirchheim;706;3;709 +67241;Kirrberg;157;4;161 +67242;Kirrwiller;540;5;545 +67244;Kleingœft;156;3;159 +67245;Knœrsheim;222;2;224 +67246;Kogenheim;1265;16;1281 +67247;Kolbsheim;948;19;967 +67248;Krautergersheim;1680;26;1706 +67249;Krautwiller;255;6;261 +67250;Kriegsheim;781;17;798 +67252;Kurtzenhouse;1053;12;1065 +67253;Kuttolsheim;622;11;633 +67254;Kutzenhausen;915;16;931 +67255;Lalaye;471;8;479 +67256;Lampertheim;3272;61;3333 +67257;Lampertsloch;722;14;736 +67258;Landersheim;199;3;202 +67259;Langensoultzbach;936;13;949 +67260;Laubach;320;5;325 +67261;Lauterbourg;2304;26;2330 +67263;Lembach;1540;45;1585 +67264;Leutenheim;837;12;849 +67265;Lichtenberg;557;6;563 +67266;Limersheim;654;8;662 +67267;Lingolsheim;18324;172;18496 +67268;Lipsheim;2600;30;2630 +67269;Littenheim;286;4;290 +67270;Lixhausen;380;1;381 +67271;Lobsann;640;6;646 +67272;Lochwiller;417;7;424 +67273;Lohr;498;6;504 +67274;Lorentzen;241;2;243 +67275;Lupstein;794;20;814 +67276;Lutzelhouse;1899;28;1927 +67277;Mackenheim;765;4;769 +67278;Mackwiller;575;13;588 +67279;Maennolsheim;231;2;233 +67280;Maisonsgoutte;804;18;822 +67281;Marckolsheim;4151;64;4215 +67282;Marlenheim;4250;65;4315 +67283;Marmoutier;2726;46;2772 +67285;Matzenheim;1429;107;1536 +67286;Meistratzheim;1485;17;1502 +67287;Melsheim;591;6;597 +67288;Memmelshoffen;332;5;337 +67289;Menchhoffen;613;10;623 +67290;Merkwiller-Pechelbronn;915;14;929 +67291;Mertzwiller;3355;40;3395 +67292;Mietesheim;670;12;682 +67293;Minversheim;661;11;672 +67295;Mittelbergheim;650;18;668 +67296;Mittelhausbergen;1984;23;2007 +67298;Mittelschaeffolsheim;576;8;584 +67299;Mollkirch;923;26;949 +67300;Molsheim;9312;214;9526 +67301;Mommenheim;1897;20;1917 +67302;Monswiller;2077;39;2116 +67303;Morsbronn-les-Bains;695;6;701 +67304;Morschwiller;587;12;599 +67305;Mothern;2006;22;2028 +67306;Muhlbach-sur-Bruche;641;54;695 +67307;Mulhausen;488;4;492 +67308;Munchhausen;763;9;772 +67309;Mundolsheim;4731;61;4792 +67310;Mussig;1138;33;1171 +67311;Muttersholtz;2013;38;2051 +67312;Mutzenhouse;456;8;464 +67313;Mutzig;6011;50;6061 +67314;Natzwiller;542;8;550 +67315;Neewiller-près-Lauterbourg;656;14;670 +67317;Neubois;698;14;712 +67228;Neugartheim-Ittlenheim;799;17;816 +67319;Neuhaeusel;351;4;355 +67320;Neuve-Église;629;10;639 +67321;Neuviller-la-Roche;341;8;349 +67322;Neuwiller-lès-Saverne;1113;13;1126 +67324;Niederbronn-les-Bains;4404;84;4488 +67325;Niederhaslach;1405;14;1419 +67326;Niederhausbergen;1590;12;1602 +67327;Niederlauterbach;965;21;986 +67328;Niedermodern;913;7;920 +67329;Niedernai;1270;22;1292 +67330;Niederrœdern;931;9;940 +67331;Niederschaeffolsheim;1374;12;1386 +67333;Niedersoultzbach;276;5;281 +67334;Niedersteinbach;122;1;123 +67335;Nordheim;887;15;902 +67336;Nordhouse;1734;30;1764 +67337;Nothalten;456;16;472 +67338;Obenheim;1359;22;1381 +67340;Oberbronn;1570;26;1596 +67341;Oberdorf-Spachbach;363;8;371 +67342;Oberhaslach;1780;28;1808 +67343;Oberhausbergen;5381;54;5435 +67344;Oberhoffen-lès-Wissembourg;324;5;329 +67345;Oberhoffen-sur-Moder;3486;28;3514 +67346;Oberlauterbach;540;11;551 +67347;Obermodern-Zutzendorf;1681;21;1702 +67348;Obernai;11279;459;11738 +67349;Oberrœdern;525;10;535 +67350;Oberschaeffolsheim;2301;24;2325 +67352;Obersoultzbach;433;2;435 +67353;Obersteinbach;227;2;229 +67354;Odratzheim;499;11;510 +67355;Oermingen;1250;15;1265 +67356;Offendorf;2476;20;2496 +67358;Offwiller;796;17;813 +67359;Ohlungen;1308;20;1328 +67360;Ohnenheim;1032;13;1045 +67361;Olwisheim;498;6;504 +67362;Orschwiller;603;5;608 +67363;Osthoffen;825;17;842 +67364;Osthouse;924;17;941 +67365;Ostwald;12604;120;12724 +67366;Ottersthal;713;18;731 +67367;Otterswiller;1339;33;1372 +67368;Ottrott;1546;31;1577 +67369;Ottwiller;260;5;265 +67370;Petersbach;647;12;659 +67371;La Petite-Pierre;618;4;622 +67373;Pfalzweyer;321;4;325 +67375;Pfulgriesheim;1311;17;1328 +67377;Plaine;993;11;1004 +67378;Plobsheim;4443;39;4482 +67379;Preuschdorf;891;5;896 +67380;Printzheim;202;4;206 +67381;Puberg;353;5;358 +67382;Quatzenheim;781;18;799 +67383;Rangen;198;6;204 +67384;Ranrupt;329;4;333 +67385;Ratzwiller;254;3;257 +67386;Rauwiller;209;2;211 +67387;Reichsfeld;296;9;305 +67388;Reichshoffen;5396;84;5480 +67389;Reichstett;4418;40;4458 +67391;Reinhardsmunster;448;7;455 +67392;Reipertswiller;858;6;864 +67394;Retschwiller;285;6;291 +67395;Reutenbourg;419;11;430 +67396;Rexingen;203;1;204 +67397;Rhinau;2698;30;2728 +67398;Richtolsheim;343;2;345 +67400;Riedseltz;1087;33;1120 +67401;Rimsdorf;308;9;317 +67403;Ringendorf;437;10;447 +67404;Rittershoffen;911;14;925 +67406;Rohr;311;3;314 +67407;Rohrwiller;1634;11;1645 +67408;Romanswiller;1239;17;1256 +67409;Roppenheim;1003;15;1018 +67410;Rosenwiller;686;15;701 +67411;Rosheim;5149;109;5258 +67412;Rossfeld;1002;10;1012 +67413;Rosteig;537;10;547 +67414;Rothau;1591;18;1609 +67415;Rothbach;468;6;474 +67416;Rott;472;10;482 +67417;Rottelsheim;307;10;317 +67418;Rountzenheim-Auenheim;1937;29;1966 +67420;Russ;1254;16;1270 +67405;Rœschwoog;2285;47;2332 +67421;Saales;837;12;849 +67422;Saasenheim;600;10;610 +67423;Saessolsheim;570;8;578 +67424;Saint-Blaise-la-Roche;228;0;228 +67425;Saint-Jean-Saverne;560;13;573 +67426;Saint-Martin;352;1;353 +67427;Saint-Maurice;367;15;382 +67428;Saint-Nabor;485;13;498 +67429;Saint-Pierre;648;9;657 +67430;Saint-Pierre-Bois;771;26;797 +67432;Salmbach;578;12;590 +67433;Sand;1283;10;1293 +67434;Sarre-Union;2823;44;2867 +67435;Sarrewerden;848;19;867 +67436;Saulxures;512;12;524 +67437;Saverne;11239;309;11548 +67438;Schaeffersheim;835;13;848 +67440;Schaffhouse-près-Seltz;558;12;570 +67441;Schalkendorf;330;5;335 +67442;Scharrachbergheim-Irmstett;1215;60;1275 +67443;Scheibenhard;822;19;841 +67444;Scherlenheim;126;0;126 +67445;Scherwiller;3195;53;3248 +67446;Schillersdorf;430;11;441 +67447;Schiltigheim;31894;176;32070 +67448;Schirmeck;2183;49;2232 +67449;Schirrhein;2227;18;2245 +67450;Schirrhoffen;694;17;711 +67451;Schleithal;1428;32;1460 +67452;Schnersheim;1613;31;1644 +67456;Schopperten;445;10;455 +67458;Schweighouse-sur-Moder;4939;60;4999 +67459;Schwenheim;760;17;777 +67460;Schwindratzheim;1675;20;1695 +67461;Schwobsheim;323;7;330 +67453;Schœnau;602;8;610 +67454;Schœnbourg;428;8;436 +67455;Schœnenbourg;688;11;699 +67351;Seebach;1672;39;1711 +67462;Sélestat;19252;288;19540 +67463;Seltz;3235;35;3270 +67464;Sermersheim;930;13;943 +67465;Sessenheim;2315;33;2348 +67466;Siegen;508;9;517 +67467;Siewiller;386;5;391 +67468;Siltzheim;636;16;652 +67470;Solbach;104;1;105 +67004;Sommerau;1524;28;1552 +67471;Souffelweyersheim;8001;62;8063 +67472;Soufflenheim;4889;64;4953 +67473;Soultz-les-Bains;947;18;965 +67474;Soultz-sous-Forêts;3177;35;3212 +67475;Sparsbach;240;3;243 +67476;Stattmatten;707;7;714 +67477;Steige;609;17;626 +67478;Steinbourg;1991;30;2021 +67479;Steinseltz;596;22;618 +67480;Still;1809;27;1836 +67481;Stotzheim;1064;16;1080 +67482;Strasbourg;280966;2779;283745 +67483;Struth;252;2;254 +67484;Stundwiller;491;9;500 +67485;Stutzheim-Offenheim;1455;26;1481 +67486;Sundhouse;1823;23;1846 +67487;Surbourg;1699;23;1722 +67488;Thal-Drulingen;184;4;188 +67489;Thal-Marmoutier;777;23;800 +67490;Thanvillé;594;19;613 +67491;Tieffenbach;261;0;261 +67492;Traenheim;648;15;663 +67493;Triembach-au-Val;463;11;474 +67494;Trimbach;574;11;585 +67495;Truchtersheim;4029;81;4110 +67497;Uhlwiller;688;15;703 +67498;Uhrwiller;706;5;711 +67499;Urbeis;322;14;336 +67500;Urmatt;1478;35;1513 +67501;Uttenheim;552;4;556 +67502;Uttenhoffen;204;2;206 +67503;Uttwiller;161;2;163 +67372;Val-de-Moder;5096;65;5161 +67504;Valff;1318;13;1331 +67505;La Vancelle;402;22;424 +67506;Vendenheim;5664;65;5729 +67507;Villé;1834;33;1867 +67509;Volksberg;354;8;362 +67508;Vœllerdingen;398;18;416 +67510;Wahlenheim;478;2;480 +67511;Walbourg;917;274;1191 +67513;Waldersbach;131;1;132 +67514;Waldhambach;626;10;636 +67515;Waldolwisheim;574;9;583 +67516;Waltenheim-sur-Zorn;664;7;671 +67517;Wangen;698;11;709 +67122;Wangenbourg-Engenthal;1354;17;1371 +67519;La Wantzenau;5841;107;5948 +67520;Wasselonne;5652;63;5715 +67521;Weinbourg;432;6;438 +67522;Weislingen;535;8;543 +67523;Weitbruch;2832;38;2870 +67524;Weiterswiller;521;13;534 +67525;Westhoffen;1651;26;1677 +67526;Westhouse;1515;26;1541 +67527;Westhouse-Marmoutier;306;3;309 +67528;Weyer;576;11;587 +67529;Weyersheim;3356;36;3392 +67530;Wickersheim-Wilshausen;392;6;398 +67531;Wildersbach;291;6;297 +67532;Willgottheim;1085;18;1103 +67534;Wilwisheim;725;6;731 +67535;Wimmenau;1081;21;1102 +67536;Windstein;164;1;165 +67537;Wingen;453;6;459 +67538;Wingen-sur-Moder;1626;23;1649 +67539;Wingersheim les Quatre Bans;2292;44;2336 +67540;Wintershouse;894;12;906 +67541;Wintzenbach;544;2;546 +67542;Wintzenheim-Kochersberg;425;3;428 +67543;Wisches;2105;29;2134 +67544;Wissembourg;7537;213;7750 +67545;Witternheim;507;5;512 +67546;Wittersheim;661;5;666 +67547;Wittisheim;2054;24;2078 +67548;Wiwersheim;880;13;893 +67551;Wolfisheim;4157;56;4213 +67552;Wolfskirchen;344;10;354 +67553;Wolschheim;320;5;325 +67554;Wolxheim;963;13;976 +67550;Wœrth;1745;24;1769 +67555;Zehnacker;246;3;249 +67556;Zeinheim;201;3;204 +67557;Zellwiller;794;13;807 +67558;Zinswiller;769;11;780 +67559;Zittersheim;250;2;252 +68001;Algolsheim;1141;13;1154 +68002;Altenach;393;4;397 +68004;Altkirch;5737;133;5870 +68005;Ammerschwihr;1779;47;1826 +68007;Andolsheim;2162;64;2226 +68008;Appenwihr;579;11;590 +68009;Artzenheim;846;11;857 +68010;Aspach;1128;20;1148 +68011;Aspach-le-Bas;1321;28;1349 +68012;Aspach-Michelbach;1788;42;1830 +68013;Attenschwiller;973;23;996 +68014;Aubure;360;9;369 +68015;Baldersheim;2616;47;2663 +68016;Balgau;969;18;987 +68017;Ballersdorf;824;14;838 +68018;Balschwiller;757;17;774 +68019;Baltzenheim;574;5;579 +68020;Bantzenheim;1608;34;1642 +68021;Bartenheim;3837;52;3889 +68022;Battenheim;1587;14;1601 +68023;Beblenheim;941;24;965 +68024;Bellemagny;190;4;194 +68025;Bendorf;216;3;219 +68026;Bennwihr;1335;26;1361 +68027;Berentzwiller;324;9;333 +68028;Bergheim;2121;49;2170 +68029;Bergholtz;1078;33;1111 +68030;Bergholtzzell;433;15;448 +68006;Bernwiller;1180;24;1204 +68032;Berrwiller;1192;37;1229 +68033;Bettendorf;450;8;458 +68034;Bettlach;311;16;327 +68035;Biederthal;317;13;330 +68036;Biesheim;2571;32;2603 +68037;Biltzheim;444;11;455 +68038;Bischwihr;1039;24;1063 +68039;Bisel;544;16;560 +68040;Bitschwiller-lès-Thann;1960;23;1983 +68041;Blodelsheim;1957;27;1984 +68042;Blotzheim;4526;114;4640 +68043;Bollwiller;4027;55;4082 +68044;Le Bonhomme;752;29;781 +68045;Bourbach-le-Bas;560;19;579 +68046;Bourbach-le-Haut;420;10;430 +68049;Bouxwiller;459;9;468 +68050;Bréchaumont;412;11;423 +68051;Breitenbach-Haut-Rhin;828;16;844 +68052;Bretten;181;3;184 +68054;Brinckheim;405;8;413 +68055;Bruebach;1061;24;1085 +68056;Brunstatt-Didenheim;8012;208;8220 +68057;Buethwiller;277;4;281 +68058;Buhl;3310;41;3351 +68059;Burnhaupt-le-Bas;1878;40;1918 +68060;Burnhaupt-le-Haut;1802;45;1847 +68061;Buschwiller;1040;17;1057 +68062;Carspach;2044;103;2147 +68063;Cernay;11565;224;11789 +68064;Chalampé;950;19;969 +68065;Chavannes-sur-l'Étang;693;9;702 +68066;Colmar;69105;1053;70158 +68067;Courtavon;368;2;370 +68068;Dannemarie;2255;29;2284 +68069;Dessenheim;1420;30;1450 +68071;Diefmatten;290;6;296 +68072;Dietwiller;1447;28;1475 +68073;Dolleren;475;11;486 +68074;Durlinsdorf;566;7;573 +68075;Durmenach;841;16;857 +68076;Durrenentzen;907;10;917 +68077;Eglingen;365;9;374 +68078;Eguisheim;1726;42;1768 +68079;Elbach;259;0;259 +68080;Emlingen;287;3;290 +68082;Ensisheim;7508;70;7578 +68083;Eschbach-au-Val;362;14;376 +68084;Eschentzwiller;1473;46;1519 +68085;Eteimbes;380;5;385 +68086;Falkwiller;191;9;200 +68087;Feldbach;444;13;457 +68088;Feldkirch;990;20;1010 +68089;Fellering;1606;32;1638 +68090;Ferrette;729;14;743 +68091;Fessenheim;2353;48;2401 +68092;Fislis;418;6;424 +68093;Flaxlanden;1448;47;1495 +68094;Folgensbourg;918;14;932 +68095;Fortschwihr;1157;40;1197 +68096;Franken;349;4;353 +68097;Fréland;1343;32;1375 +68098;Friesen;644;8;652 +68099;Frœningen;739;19;758 +68100;Fulleren;342;14;356 +68101;Galfingue;805;17;822 +68102;Geishouse;441;10;451 +68103;Geispitzen;449;8;457 +68104;Geiswasser;306;5;311 +68105;Gildwiller;271;12;283 +68106;Goldbach-Altenbach;286;6;292 +68107;Gommersdorf;361;8;369 +68109;Griesbach-au-Val;714;14;728 +68110;Grussenheim;830;13;843 +68111;Gueberschwihr;837;24;861 +68112;Guebwiller;11094;320;11414 +68113;Guémar;1384;28;1412 +68114;Guevenatten;140;2;142 +68115;Guewenheim;1302;25;1327 +68116;Gundolsheim;699;29;728 +68117;Gunsbach;907;15;922 +68118;Habsheim;4894;97;4991 +68119;Hagenbach;706;16;722 +68120;Hagenthal-le-Bas;1220;29;1249 +68121;Hagenthal-le-Haut;664;18;682 +68122;Hartmannswiller;638;11;649 +68123;Hattstatt;785;25;810 +68124;Hausgauen;383;9;392 +68219;Le Haut Soultzbach;914;24;938 +68125;Hecken;497;7;504 +68126;Hégenheim;3420;73;3493 +68127;Heidwiller;624;13;637 +68128;Heimersdorf;660;15;675 +68129;Heimsbrunn;1325;49;1374 +68130;Heiteren;1040;19;1059 +68131;Heiwiller;169;1;170 +68132;Helfrantzkirch;692;17;709 +68134;Herrlisheim-près-Colmar;1818;24;1842 +68135;Hésingue;2719;54;2773 +68136;Hettenschlag;331;11;342 +68137;Hindlingen;636;10;646 +68138;Hirsingue;2121;39;2160 +68139;Hirtzbach;1442;20;1462 +68140;Hirtzfelden;1261;15;1276 +68141;Hochstatt;2143;55;2198 +68142;Hohrod;365;12;377 +68144;Hombourg;1334;26;1360 +68145;Horbourg-Wihr;5967;114;6081 +68146;Houssen;2249;22;2271 +68147;Hunawihr;602;8;610 +68148;Hundsbach;346;5;351 +68149;Huningue;7238;88;7326 +68150;Husseren-les-Châteaux;514;13;527 +68151;Husseren-Wesserling;1048;12;1060 +68152;Illfurth;2474;39;2513 +68153;Illhaeusern;702;13;715 +68240;Illtal;1420;24;1444 +68154;Illzach;14691;171;14862 +68155;Ingersheim;4678;74;4752 +68156;Issenheim;3416;46;3462 +68157;Jebsheim;1403;18;1421 +68158;Jettingen;502;15;517 +68159;Jungholtz;898;22;920 +68160;Kappelen;587;15;602 +68161;Katzenthal;528;22;550 +68162;Kaysersberg Vignoble;4523;95;4618 +68163;Kembs;5257;73;5330 +68165;Kiffis;249;3;252 +68166;Kingersheim;13055;146;13201 +68167;Kirchberg;762;21;783 +68168;Knœringue;381;11;392 +68171;Kruth;941;14;955 +68172;Kunheim;1763;29;1792 +68169;Kœstlach;506;9;515 +68170;Kœtzingue;600;24;624 +68173;Labaroche;2165;77;2242 +68174;Landser;1601;24;1625 +68175;Lapoutroie;1908;40;1948 +68176;Largitzen;314;5;319 +68177;Lautenbach;1511;37;1548 +68178;Lautenbachzell;955;15;970 +68179;Lauw;915;16;931 +68180;Leimbach;888;28;916 +68181;Levoncourt;240;3;243 +68182;Leymen;1208;27;1235 +68183;Liebenswiller;194;4;198 +68184;Liebsdorf;307;10;317 +68185;Lièpvre;1724;28;1752 +68186;Ligsdorf;311;9;320 +68187;Linsdorf;321;12;333 +68188;Linthal;599;19;618 +68189;Logelheim;818;21;839 +68190;Lucelle;34;0;34 +68191;Luemschwiller;777;15;792 +68193;Luttenbach-près-Munster;742;9;751 +68194;Lutter;279;5;284 +68195;Lutterbach;6310;94;6404 +68196;Magny;308;5;313 +68197;Magstatt-le-Bas;475;9;484 +68198;Magstatt-le-Haut;283;8;291 +68199;Malmerspach;504;2;506 +68200;Manspach;560;13;573 +68201;Masevaux-Niederbruck;3797;63;3860 +68202;Mertzen;209;5;214 +68203;Merxheim;1261;25;1286 +68204;Metzeral;1060;15;1075 +68205;Meyenheim;1480;9;1489 +68207;Michelbach-le-Bas;697;8;705 +68208;Michelbach-le-Haut;597;11;608 +68209;Mittelwihr;832;16;848 +68210;Mittlach;335;1;336 +68211;Mitzach;390;8;398 +68213;Mollau;349;7;356 +68214;Montreux-Jeune;370;9;379 +68215;Montreux-Vieux;899;8;907 +68217;Moosch;1677;23;1700 +68216;Mooslargue;417;6;423 +68218;Morschwiller-le-Bas;3766;83;3849 +68221;Muespach;899;13;912 +68222;Muespach-le-Haut;1065;20;1085 +68223;Muhlbach-sur-Munster;767;14;781 +68224;Mulhouse;109443;1169;110612 +68225;Munchhouse;1519;25;1544 +68226;Munster;4606;82;4688 +68227;Muntzenheim;1257;33;1290 +68228;Munwiller;475;16;491 +68229;Murbach;159;3;162 +68212;Mœrnach;529;11;540 +68230;Nambsheim;586;7;593 +68231;Neuf-Brisach;1931;13;1944 +68232;Neuwiller;463;14;477 +68234;Niederentzen;715;10;725 +68235;Niederhergheim;1129;15;1144 +68237;Niedermorschwihr;539;14;553 +68238;Niffer;946;25;971 +68239;Oberbruck;393;14;407 +68241;Oberentzen;637;10;647 +68242;Oberhergheim;1202;12;1214 +68243;Oberlarg;138;1;139 +68244;Obermorschwihr;359;6;365 +68245;Obermorschwiller;407;15;422 +68246;Obersaasheim;1033;13;1046 +68247;Oderen;1268;15;1283 +68248;Oltingue;686;22;708 +68249;Orbey;3552;67;3619 +68250;Orschwihr;1043;18;1061 +68251;Osenbach;890;19;909 +68252;Ostheim;1612;29;1641 +68253;Ottmarsheim;1885;30;1915 +68254;Petit-Landau;828;21;849 +68255;Pfaffenheim;1457;21;1478 +68256;Pfastatt;9579;128;9707 +68257;Pfetterhouse;980;23;1003 +68143;Porte du Ried;1782;51;1833 +68258;Pulversheim;2960;76;3036 +68259;Raedersdorf;513;7;520 +68260;Raedersheim;1108;24;1132 +68261;Rammersmatt;223;6;229 +68262;Ranspach;819;16;835 +68263;Ranspach-le-Bas;646;8;654 +68264;Ranspach-le-Haut;628;11;639 +68265;Rantzwiller;795;23;818 +68266;Réguisheim;1895;28;1923 +68267;Reiningue;1981;24;2005 +68268;Retzwiller;709;8;717 +68269;Ribeauvillé;4729;164;4893 +68270;Richwiller;3689;61;3750 +68271;Riedisheim;12645;353;12998 +68273;Riespach;643;40;683 +68274;Rimbach-près-Guebwiller;187;1;188 +68275;Rimbach-près-Masevaux;464;17;481 +68276;Rimbachzell;198;2;200 +68277;Riquewihr;1077;19;1096 +68278;Rixheim;13902;212;14114 +68279;Roderen;887;26;913 +68280;Rodern;362;6;368 +68281;Roggenhouse;469;6;475 +68282;Romagny;263;4;267 +68283;Rombach-le-Franc;780;22;802 +68284;Roppentzwiller;698;10;708 +68285;Rorschwihr;372;8;380 +68286;Rosenau;2374;51;2425 +68287;Rouffach;4518;266;4784 +68288;Ruederbach;399;4;403 +68289;Ruelisheim;2297;39;2336 +68291;Rumersheim-le-Haut;1079;26;1105 +68290;Rustenhart;859;15;874 +68292;Saint-Amarin;2262;41;2303 +68081;Saint-Bernard;571;9;580 +68293;Saint-Cosme;91;1;92 +68296;Saint-Hippolyte;966;15;981 +68297;Saint-Louis;21177;280;21457 +68299;Saint-Ulrich;308;0;308 +68294;Sainte-Croix-aux-Mines;1922;28;1950 +68295;Sainte-Croix-en-Plaine;2978;65;3043 +68298;Sainte-Marie-aux-Mines;5095;125;5220 +68300;Sausheim;5501;121;5622 +68301;Schlierbach;1227;24;1251 +68302;Schweighouse-Thann;767;27;794 +68303;Schwoben;228;8;236 +68304;Sentheim;1577;30;1607 +68305;Seppois-le-Bas;1378;25;1403 +68306;Seppois-le-Haut;511;7;518 +68307;Sewen;501;7;508 +68308;Sickert;327;13;340 +68309;Sierentz;3696;73;3769 +68311;Sondernach;615;12;627 +68312;Sondersdorf;335;6;341 +68313;Soppe-le-Bas;763;12;775 +68315;Soultz-Haut-Rhin;7072;132;7204 +68316;Soultzbach-les-Bains;735;22;757 +68317;Soultzeren;1121;19;1140 +68318;Soultzmatt;2411;52;2463 +68320;Spechbach;1334;44;1378 +68321;Staffelfelden;3959;64;4023 +68322;Steinbach;1360;25;1385 +68323;Steinbrunn-le-Bas;757;23;780 +68324;Steinbrunn-le-Haut;583;16;599 +68325;Steinsoultz;769;9;778 +68326;Sternenberg;155;7;162 +68327;Stetten;351;6;357 +68328;Storckensohn;207;1;208 +68329;Stosswihr;1352;34;1386 +68330;Strueth;331;8;339 +68331;Sundhoffen;1938;57;1995 +68332;Tagolsheim;928;13;941 +68333;Tagsdorf;294;6;300 +68334;Thann;7780;141;7921 +68335;Thannenkirch;463;6;469 +68336;Traubach-le-Bas;478;6;484 +68337;Traubach-le-Haut;604;9;613 +68338;Turckheim;3776;79;3855 +68340;Ueberstrass;375;14;389 +68341;Uffheim;885;27;912 +68342;Uffholtz;1795;34;1829 +68343;Ungersheim;2341;31;2372 +68344;Urbès;435;9;444 +68345;Urschenheim;735;25;760 +68192;Valdieu-Lutran;421;4;425 +68347;Vieux-Ferrette;688;20;708 +68348;Vieux-Thann;2843;46;2889 +68349;Village-Neuf;4284;82;4366 +68351;Vogelgrun;649;13;662 +68352;Volgelsheim;2668;26;2694 +68350;Vœgtlinshoffen;489;15;504 +68353;Wahlbach;497;17;514 +68354;Walbach;904;36;940 +68355;Waldighofen;1540;27;1567 +68356;Walheim;896;20;916 +68357;Waltenheim;532;16;548 +68358;Wasserbourg;463;12;475 +68359;Wattwiller;1634;47;1681 +68360;Weckolsheim;665;4;669 +68361;Wegscheid;322;6;328 +68362;Wentzwiller;756;15;771 +68363;Werentzhouse;544;14;558 +68364;Westhalten;988;15;1003 +68365;Wettolsheim;1733;62;1795 +68366;Wickerschwihr;732;31;763 +68367;Widensolen;1177;21;1198 +68368;Wihr-au-Val;1263;41;1304 +68370;Wildenstein;180;4;184 +68371;Willer;308;9;317 +68372;Willer-sur-Thur;1825;41;1866 +68373;Winkel;304;12;316 +68374;Wintzenheim;7594;402;7996 +68375;Wittelsheim;10355;162;10517 +68376;Wittenheim;14317;113;14430 +68377;Wittersdorf;806;18;824 +68378;Wolfersdorf;372;3;375 +68379;Wolfgantzen;1048;21;1069 +68380;Wolschwiller;453;11;464 +68381;Wuenheim;799;19;818 +68382;Zaessingue;378;4;382 +68383;Zellenberg;322;5;327 +68384;Zillisheim;2572;64;2636 +68385;Zimmerbach;843;25;868 +68386;Zimmersheim;1016;42;1058 +69001;Affoux;369;3;372 +69002;Aigueperse;248;1;249 +69003;Albigny-sur-Saône;2880;39;2919 +69004;Alix;763;23;786 +69005;Ambérieux;578;9;587 +69006;Amplepuis;4976;121;5097 +69007;Ampuis;2713;43;2756 +69008;Ancy;640;15;655 +69009;Anse;7178;154;7332 +69010;L' Arbresle;6398;196;6594 +69012;Les Ardillats;622;15;637 +69013;Arnas;3778;78;3856 +69014;Aveize;1127;22;1149 +69016;Azolette;120;0;120 +69017;Bagnols;731;21;752 +69018;Beaujeu;2157;33;2190 +69179;Beauvallon;4013;73;4086 +69019;Belleville-en-Beaujolais;12971;269;13240 +69020;Belmont-d'Azergues;631;17;648 +69021;Bessenay;2293;80;2373 +69022;Bibost;575;14;589 +69023;Blacé;1631;25;1656 +69026;Le Breuil;530;10;540 +69027;Brignais;11434;176;11610 +69028;Brindas;6174;106;6280 +69029;Bron;41543;477;42020 +69030;Brullioles;816;15;831 +69031;Brussieu;1376;93;1469 +69032;Bully;1982;37;2019 +69033;Cailloux-sur-Fontaines;2722;70;2792 +69034;Caluire-et-Cuire;43187;629;43816 +69035;Cenves;391;7;398 +69036;Cercié;1128;22;1150 +69228;Chabanière;4183;93;4276 +69037;Chambost-Allières;839;6;845 +69038;Chambost-Longessaigne;938;25;963 +69039;Chamelet;682;10;692 +69040;Champagne-au-Mont-d'Or;5526;53;5579 +69042;La Chapelle-sur-Coise;573;15;588 +69270;Chaponnay;4273;65;4338 +69043;Chaponost;8717;171;8888 +69044;Charbonnières-les-Bains;5067;141;5208 +69045;Charentay;1240;68;1308 +69046;Charly;4541;138;4679 +69047;Charnay;1057;23;1080 +69049;Chasselay;2784;65;2849 +69271;Chassieu;10359;146;10505 +69050;Châtillon;2137;47;2184 +69051;Chaussan;1116;29;1145 +69052;Chazay-d'Azergues;4130;115;4245 +69053;Chénas;545;13;558 +69054;Chénelette;321;6;327 +69055;Les Chères;1453;26;1479 +69056;Chessy;2063;48;2111 +69057;Chevinay;557;12;569 +69058;Chiroubles;391;10;401 +69059;Civrieux-d'Azergues;1515;28;1543 +69060;Claveisolles;635;95;730 +69061;Cogny;1167;34;1201 +69062;Coise;769;22;791 +69063;Collonges-au-Mont-d'Or;4052;83;4135 +69299;Colombier-Saugnieu;2613;30;2643 +69272;Communay;4197;84;4281 +69064;Condrieu;3897;80;3977 +69273;Corbas;11050;60;11110 +69065;Corcelles-en-Beaujolais;942;15;957 +69066;Cours;4449;80;4529 +69067;Courzieu;1118;20;1138 +69068;Couzon-au-Mont-d'Or;2516;48;2564 +69069;Craponne;11067;186;11253 +69070;Cublize;1266;28;1294 +69071;Curis-au-Mont-d'Or;1172;31;1203 +69072;Dardilly;8600;556;9156 +69275;Décines-Charpieu;28602;128;28730 +69074;Denicé;1513;48;1561 +69135;Deux-Grosnes;1905;41;1946 +69075;Dième;186;2;188 +69076;Dommartin;2576;98;2674 +69077;Dracé;956;13;969 +69078;Duerne;829;16;845 +69080;Échalas;1799;15;1814 +69081;Écully;18517;348;18865 +69082;Émeringes;259;7;266 +69083;Éveux;1169;29;1198 +69276;Feyzin;9857;53;9910 +69084;Fleurie;1265;21;1286 +69085;Fleurieu-sur-Saône;1449;40;1489 +69086;Fleurieux-sur-l'Arbresle;2334;64;2398 +69087;Fontaines-Saint-Martin;3052;74;3126 +69088;Fontaines-sur-Saône;7069;75;7144 +69089;Francheville;14198;266;14464 +69090;Frontenas;815;24;839 +69277;Genas;12734;207;12941 +69278;Genay;5470;104;5574 +69091;Givors;19975;114;20089 +69092;Gleizé;7472;339;7811 +69093;Grandris;1181;20;1201 +69094;Grézieu-la-Varenne;5734;112;5846 +69095;Grézieu-le-Marché;815;17;832 +69096;Grigny;9662;72;9734 +69097;Les Haies;785;20;805 +69098;Les Halles;492;7;499 +69099;Haute-Rivoire;1444;28;1472 +69100;Irigny;8641;99;8740 +69279;Jonage;5903;75;5978 +69280;Jons;1487;12;1499 +69102;Joux;691;22;713 +69103;Juliénas;909;21;930 +69104;Jullié;435;9;444 +69105;Lacenas;972;34;1006 +69106;Lachassagne;1118;22;1140 +69107;Lamure-sur-Azergues;1048;66;1114 +69108;Lancié;1021;23;1044 +69109;Lantignié;880;30;910 +69110;Larajasse;1853;30;1883 +69111;Légny;667;17;684 +69112;Lentilly;5793;137;5930 +69113;Létra;922;28;950 +69115;Limas;4803;102;4905 +69116;Limonest;3664;101;3765 +69117;Lissieu;3122;74;3196 +69118;Loire-sur-Rhône;2559;31;2590 +69119;Longes;977;9;986 +69120;Longessaigne;595;16;611 +69121;Lozanne;2626;41;2667 +69122;Lucenay;1808;35;1843 +69381;Lyon 1er Arrondissement;29352;790;30142 +69382;Lyon 2e Arrondissement;30520;378;30898 +69383;Lyon 3e Arrondissement;101744;1008;102752 +69384;Lyon 4e Arrondissement;35949;420;36369 +69385;Lyon 5e Arrondissement;49409;1064;50473 +69386;Lyon 6e Arrondissement;51777;791;52568 +69387;Lyon 7e Arrondissement;81566;539;82105 +69388;Lyon 8e Arrondissement;85088;1022;86110 +69389;Lyon 9e Arrondissement;50687;575;51262 +69124;Marchampt;462;9;471 +69125;Marcilly-d'Azergues;875;14;889 +69126;Marcy;726;27;753 +69127;Marcy-l'Étoile;3657;57;3714 +69281;Marennes;1688;20;1708 +69130;Meaux-la-Montagne;237;3;240 +69131;Messimy;3381;84;3465 +69132;Meys;850;15;865 +69282;Meyzieu;33477;248;33725 +69133;Millery;4331;83;4414 +69283;Mions;13542;119;13661 +69134;Moiré;210;9;219 +69136;Montagny;2959;41;3000 +69284;Montanay;3142;113;3255 +69137;Montmelas-Saint-Sorlin;502;7;509 +69138;Montromant;456;9;465 +69139;Montrottier;1385;78;1463 +69140;Morancé;1970;45;2015 +69141;Mornant;5938;202;6140 +69142;La Mulatière;6334;89;6423 +69143;Neuville-sur-Saône;7514;95;7609 +69145;Odenas;927;25;952 +69148;Orliénas;2444;65;2509 +69149;Oullins;26273;292;26565 +69151;Le Perréon;1587;39;1626 +69152;Pierre-Bénite;10390;63;10453 +69153;Poleymieux-au-Mont-d'Or;1332;44;1376 +69154;Pollionnay;2637;49;2686 +69155;Pomeys;1145;31;1176 +69156;Pommiers;2637;78;2715 +69159;Porte des Pierres Dorées;3753;92;3845 +69160;Poule-les-Écharmeaux;1102;25;1127 +69161;Propières;468;30;498 +69285;Pusignan;4114;37;4151 +69162;Quincié-en-Beaujolais;1325;34;1359 +69163;Quincieux;3467;51;3518 +69164;Ranchal;319;10;329 +69165;Régnié-Durette;1119;25;1144 +69286;Rillieux-la-Pape;30012;354;30366 +69166;Riverie;322;2;324 +69167;Rivolet;579;11;590 +69168;Rochetaillée-sur-Saône;1528;23;1551 +69169;Ronno;636;23;659 +69170;Rontalon;1162;18;1180 +69171;Sain-Bel;2316;24;2340 +69180;Saint-André-la-Côte;284;9;293 +69181;Saint-Appolinaire;213;1;214 +69287;Saint-Bonnet-de-Mure;6800;79;6879 +69182;Saint-Bonnet-des-Bruyères;356;2;358 +69183;Saint-Bonnet-le-Troncy;313;3;316 +69186;Saint-Clément-de-Vers;226;2;228 +69187;Saint-Clément-les-Places;640;21;661 +69188;Saint-Clément-sur-Valsonne;909;9;918 +69191;Saint-Cyr-au-Mont-d'Or;5576;136;5712 +69192;Saint-Cyr-le-Chatoux;145;7;152 +69193;Saint-Cyr-sur-le-Rhône;1306;33;1339 +69194;Saint-Didier-au-Mont-d'Or;6785;154;6939 +69196;Saint-Didier-sur-Beaujeu;616;10;626 +69197;Saint-Étienne-des-Oullières;2207;39;2246 +69198;Saint-Étienne-la-Varenne;741;7;748 +69199;Saint-Fons;18802;57;18859 +69200;Saint-Forgeux;1486;33;1519 +69203;Saint-Genis-l'Argentière;1041;17;1058 +69204;Saint-Genis-Laval;21217;478;21695 +69205;Saint-Genis-les-Ollières;4984;88;5072 +69206;Saint-Georges-de-Reneins;4378;90;4468 +69207;Saint-Germain-au-Mont-d'Or;3085;48;3133 +69208;Saint-Germain-Nuelles;2265;61;2326 +69209;Saint-Igny-de-Vers;582;16;598 +69212;Saint-Jean-des-Vignes;432;10;442 +69214;Saint-Jean-la-Bussière;1214;28;1242 +69215;Saint-Julien;854;19;873 +69216;Saint-Julien-sur-Bibost;562;12;574 +69217;Saint-Just-d'Avray;747;28;775 +69218;Saint-Lager;1040;17;1057 +69219;Saint-Laurent-d'Agny;2139;57;2196 +69220;Saint-Laurent-de-Chamousset;1827;113;1940 +69288;Saint-Laurent-de-Mure;5377;65;5442 +69225;Saint-Marcel-l'Éclairé;524;14;538 +69227;Saint-Martin-en-Haut;3865;189;4054 +69229;Saint-Nizier-d'Azergues;790;14;804 +69289;Saint-Pierre-de-Chandieu;4520;58;4578 +69231;Saint-Pierre-la-Palud;2635;42;2677 +69290;Saint-Priest;46207;290;46497 +69233;Saint-Romain-au-Mont-d'Or;1211;59;1270 +69234;Saint-Romain-de-Popey;1560;71;1631 +69235;Saint-Romain-en-Gal;1889;112;2001 +69236;Saint-Romain-en-Gier;579;5;584 +69291;Saint-Symphorien-d'Ozon;5735;56;5791 +69238;Saint-Symphorien-sur-Coise;3682;94;3776 +69239;Saint-Vérand;1192;23;1215 +69240;Saint-Vincent-de-Reins;630;6;636 +69184;Sainte-Catherine;980;20;1000 +69189;Sainte-Colombe;1909;29;1938 +69190;Sainte-Consorce;1939;91;2030 +69201;Sainte-Foy-l'Argentière;1281;25;1306 +69202;Sainte-Foy-lès-Lyon;22012;371;22383 +69230;Sainte-Paule;324;7;331 +69172;Salles-Arbuissonnas-en-Beaujolais;791;28;819 +69173;Sarcey;1002;25;1027 +69292;Sathonay-Camp;5934;59;5993 +69293;Sathonay-Village;2360;48;2408 +69174;Les Sauvages;612;13;625 +69175;Savigny;2009;57;2066 +69294;Sérézin-du-Rhône;2664;36;2700 +69295;Simandres;1812;9;1821 +69296;Solaize;2922;32;2954 +69176;Soucieu-en-Jarrest;4515;83;4598 +69177;Sourcieux-les-Mines;2029;45;2074 +69178;Souzy;813;20;833 +69241;Taluyers;2539;62;2601 +69242;Taponas;976;16;992 +69243;Tarare;10582;281;10863 +69244;Tassin-la-Demi-Lune;22297;394;22691 +69245;Ternand;684;26;710 +69297;Ternay;5514;61;5575 +69246;Theizé;1247;38;1285 +69248;Thizy-les-Bourgs;6031;127;6158 +69249;Thurins;3050;62;3112 +69250;La Tour-de-Salvagny;4050;96;4146 +69298;Toussieu;3080;26;3106 +69252;Trèves;737;9;746 +69253;Tupin-et-Semons;617;10;627 +69024;Val d'Oingt;4037;112;4149 +69254;Valsonne;952;12;964 +69255;Vaugneray;5734;108;5842 +69256;Vaulx-en-Velin;49658;270;49928 +69257;Vaux-en-Beaujolais;1087;19;1106 +69258;Vauxrenard;321;7;328 +69259;Vénissieux;65894;308;66202 +69260;Vernaison;4998;54;5052 +69261;Vernay;101;1;102 +69265;Ville-sur-Jarnioux;806;33;839 +69263;Villechenève;883;20;903 +69264;Villefranche-sur-Saône;36857;446;37303 +69266;Villeurbanne;147712;1042;148754 +69267;Villié-Morgon;2111;120;2231 +69157;Vindry-sur-Turdine;5133;93;5226 +69268;Vourles;3411;90;3501 +69269;Yzeron;1022;24;1046 +70001;Abelcourt;354;5;359 +70002;Aboncourt-Gesincourt;214;7;221 +70003;Achey;70;0;70 +70004;Adelans-et-le-Val-de-Bithaine;301;7;308 +70005;Aillevans;148;1;149 +70006;Aillevillers-et-Lyaumont;1551;110;1661 +70007;Ailloncourt;302;5;307 +70008;Ainvelle;148;2;150 +70009;Aisey-et-Richecourt;107;0;107 +70010;Alaincourt;112;2;114 +70011;Amage;338;4;342 +70012;Amance;652;15;667 +70013;Ambiévillers;73;0;73 +70014;Amblans-et-Velotte;396;5;401 +70015;Amoncourt;286;7;293 +70016;Amont-et-Effreney;164;3;167 +70017;Anchenoncourt-et-Chazel;241;2;243 +70018;Ancier;502;5;507 +70019;Andelarre;134;4;138 +70020;Andelarrot;237;2;239 +70021;Andornay;203;5;208 +70022;Angirey;140;3;143 +70023;Anjeux;144;4;148 +70024;Apremont;460;14;474 +70025;Arbecey;259;6;265 +70026;Arc-lès-Gray;2540;27;2567 +70027;Argillières;75;1;76 +70028;Aroz;148;3;151 +70029;Arpenans;245;2;247 +70030;Arsans;48;2;50 +70031;Athesans-Étroitefontaine;654;13;667 +70032;Attricourt;44;0;44 +70035;Augicourt;177;4;181 +70036;Aulx-lès-Cromary;167;2;169 +70037;Autet;262;26;288 +70038;Authoison;320;11;331 +70039;Autoreille;337;4;341 +70042;Autrey-le-Vay;92;1;93 +70040;Autrey-lès-Cerre;234;1;235 +70041;Autrey-lès-Gray;374;9;383 +70043;Auvet-et-la-Chapelotte;238;8;246 +70044;Auxon;419;19;438 +70045;Avrigney-Virey;420;7;427 +70046;Les Aynans;351;7;358 +70047;Baignes;104;1;105 +70048;Bard-lès-Pesmes;145;1;146 +70049;Barges;94;2;96 +70050;La Barre;101;0;101 +70051;La Basse-Vaivre;37;0;37 +70052;Bassigney;127;3;130 +70053;Les Bâties;79;1;80 +70054;Battrans;237;3;240 +70055;Baudoncourt;533;10;543 +70056;Baulay;297;6;303 +70057;Bay;142;1;143 +70058;Beaujeu-Saint-Vallier-Pierrejux-et-Quitteur;934;15;949 +70059;Beaumotte-Aubertans;458;9;467 +70060;Beaumotte-lès-Pin;307;4;311 +70061;Belfahy;81;3;84 +70062;Belmont;137;5;142 +70063;Belonchamp;204;4;208 +70064;Belverne;145;3;148 +70065;Besnans;79;1;80 +70066;Betaucourt;170;1;171 +70067;Betoncourt-lès-Brotte;122;0;122 +70069;Betoncourt-Saint-Pancras;50;2;52 +70070;Betoncourt-sur-Mance;29;2;31 +70071;Beulotte-Saint-Laurent;58;0;58 +70072;Beveuge;83;2;85 +70074;Blondefontaine;269;3;272 +70075;Bonboillon;199;2;201 +70076;Bonnevent-Velloreille;378;8;386 +70077;Borey;230;4;234 +70078;Bougey;93;2;95 +70079;Bougnon;545;11;556 +70080;Bouhans-et-Feurg;239;7;246 +70081;Bouhans-lès-Lure;323;6;329 +70082;Bouhans-lès-Montbozon;142;3;145 +70083;Bouligney;410;10;420 +70084;Boulot;690;6;696 +70085;Boult;623;12;635 +70086;Bourbévelle;78;1;79 +70087;Bourguignon-lès-Conflans;141;3;144 +70088;Bourguignon-lès-la-Charité;116;2;118 +70089;Bourguignon-lès-Morey;47;3;50 +70090;Boursières;57;1;58 +70091;Bousseraucourt;49;1;50 +70092;Bresilley;188;3;191 +70093;Breuches;688;11;699 +70094;Breuchotte;300;6;306 +70095;Breurey-lès-Faverney;635;10;645 +70096;Brevilliers;634;17;651 +70097;Briaucourt;239;10;249 +70098;Brotte-lès-Luxeuil;208;2;210 +70099;Brotte-lès-Ray;75;1;76 +70101;Broye-Aubigney-Montseugny;486;6;492 +70100;Broye-les-Loups-et-Verfontaine;127;0;127 +70102;Brussey;276;10;286 +70103;La Bruyère;218;3;221 +70104;Bucey-lès-Gy;592;14;606 +70105;Bucey-lès-Traves;123;1;124 +70106;Buffignécourt;116;4;120 +70107;Bussières;425;4;429 +70109;Buthiers;308;2;310 +70111;Calmoutier;266;4;270 +70112;Cemboing;180;5;185 +70113;Cenans;125;3;128 +70114;Cendrecourt;207;2;209 +70115;Cerre-lès-Noroy;233;6;239 +70116;Chagey;634;12;646 +70117;Châlonvillars;1248;34;1282 +70118;Chambornay-lès-Bellevaux;185;3;188 +70119;Chambornay-lès-Pin;361;12;373 +70120;Champagney;3788;76;3864 +70121;Champey;875;16;891 +70122;Champlitte;1639;34;1673 +70124;Champtonnay;101;1;102 +70125;Champvans;180;2;182 +70126;Chancey;200;6;206 +70127;Chantes;119;9;128 +70128;La Chapelle-lès-Luxeuil;382;9;391 +70129;La Chapelle-Saint-Quillain;154;3;157 +70130;Charcenne;336;9;345 +70132;Chargey-lès-Gray;694;68;762 +70133;Chargey-lès-Port;237;7;244 +70134;Chariez;207;2;209 +70135;Charmes-Saint-Valbert;38;1;39 +70136;Charmoille;484;11;495 +70137;Chassey-lès-Montbozon;217;9;226 +70138;Chassey-lès-Scey;131;3;134 +70140;Châteney;64;1;65 +70141;Châtenois;118;2;120 +70142;Chaumercenne;187;3;190 +70143;Chauvirey-le-Châtel;123;4;127 +70144;Chauvirey-le-Vieil;34;1;35 +70145;Chaux-la-Lotière;454;10;464 +70146;Chaux-lès-Port;159;4;163 +70147;Chavanne;239;2;241 +70148;Chemilly;88;1;89 +70149;Chenebier;695;17;712 +70150;Chenevrey-et-Morogne;308;2;310 +70151;Chevigney;36;0;36 +70152;Choye;453;37;490 +70153;Cintrey;94;1;95 +70154;Cirey;368;6;374 +70155;Citers;778;14;792 +70156;Citey;103;1;104 +70157;Clairegoutte;379;4;383 +70158;Clans;106;2;108 +70159;Cognières;92;0;92 +70160;Coisevaux;327;20;347 +70162;Colombe-lès-Vesoul;460;14;474 +70163;Colombier;452;5;457 +70164;Colombotte;85;1;86 +70165;Combeaufontaine;542;46;588 +70166;Comberjon;161;6;167 +70167;Conflandey;360;13;373 +70168;Conflans-sur-Lanterne;623;18;641 +70169;Confracourt;216;5;221 +70170;Contréglise;118;2;120 +70171;Corbenay;1282;30;1312 +70172;La Corbière;106;1;107 +70174;Cordonnet;142;2;144 +70175;Cornot;139;4;143 +70176;Corravillers;190;3;193 +70177;Corre;596;18;614 +70178;La Côte;519;12;531 +70179;Coulevon;173;3;176 +70180;Courchaton;449;10;459 +70181;Courcuire;128;2;130 +70182;Courmont;136;0;136 +70183;Courtesoult-et-Gatey;61;0;61 +70184;Couthenans;730;21;751 +70185;Cresancey;181;9;190 +70186;La Creuse;74;1;75 +70187;Crevans-et-la-Chapelle-lès-Granges;264;3;267 +70188;Creveney;57;1;58 +70189;Cromary;245;4;249 +70190;Cubry-lès-Faverney;178;3;181 +70192;Cugney;205;2;207 +70193;Cult;233;5;238 +70194;Cuve;141;9;150 +70195;Dambenoît-lès-Colombe;277;4;281 +70196;Dampierre-lès-Conflans;260;9;269 +70197;Dampierre-sur-Linotte;802;16;818 +70198;Dampierre-sur-Salon;1263;26;1289 +70199;Dampvalley-lès-Colombe;113;0;113 +70200;Dampvalley-Saint-Pancras;32;1;33 +70201;Delain;219;1;220 +70202;Demangevelle;278;7;285 +70203;La Demie;142;3;145 +70204;Denèvre;165;4;169 +70205;Échavanne;205;2;207 +70206;Échenans-sous-Mont-Vaudois;522;7;529 +70207;Échenoz-la-Méline;3231;75;3306 +70208;Échenoz-le-Sec;298;5;303 +70210;Écromagny;158;5;163 +70211;Écuelle;70;2;72 +70213;Éhuns;234;4;238 +70214;Équevilley;123;6;129 +70215;Errevet;248;11;259 +70216;Esboz-Brest;428;23;451 +70217;Esmoulières;97;1;98 +70218;Esmoulins;136;1;137 +70219;Esprels;733;16;749 +70220;Essertenne-et-Cecey;411;6;417 +70221;Étobon;288;5;293 +70222;Étrelles-et-la-Montbleuse;77;1;78 +70224;Étuz;666;14;680 +70225;Fahy-lès-Autrey;112;6;118 +70226;Fallon;313;4;317 +70227;Faucogney-et-la-Mer;530;15;545 +70228;Faverney;961;14;975 +70229;Faymont;262;7;269 +70230;Fédry;97;4;101 +70231;Ferrières-lès-Ray;33;2;35 +70232;Ferrières-lès-Scey;124;5;129 +70233;Les Fessey;136;2;138 +70234;Filain;235;5;240 +70235;Flagy;156;2;158 +70236;Fleurey-lès-Faverney;466;9;475 +70237;Fleurey-lès-Lavoncourt;99;0;99 +70238;Fleurey-lès-Saint-Loup;134;4;138 +70239;Fondremand;198;6;204 +70240;Fontaine-lès-Luxeuil;1351;29;1380 +70242;Fontenois-la-Ville;135;0;135 +70243;Fontenois-lès-Montbozon;328;10;338 +70244;Fouchécourt;110;0;110 +70245;Fougerolles-Saint-Valbert;3803;128;3931 +70247;Fouvent-Saint-Andoche;214;3;217 +70248;Frahier-et-Chatebier;1378;25;1403 +70252;Framont;176;3;179 +70249;Francalmont;120;3;123 +70250;Franchevelle;428;7;435 +70251;Francourt;101;4;105 +70253;Frasne-le-Château;292;28;320 +70254;Frédéric-Fontaine;258;8;266 +70255;Fresne-Saint-Mamès;505;4;509 +70256;Fresse;721;13;734 +70257;Fretigney-et-Velloreille;735;7;742 +70258;Froideconche;1980;47;2027 +70259;Froideterre;371;12;383 +70260;Frotey-lès-Lure;691;21;712 +70261;Frotey-lès-Vesoul;1411;34;1445 +70262;Genevreuille;165;4;169 +70263;Genevrey;243;2;245 +70264;Georfans;59;0;59 +70265;Germigney;161;5;166 +70267;Gevigney-et-Mercey;482;7;489 +70268;Gézier-et-Fontenelay;211;3;214 +70269;Girefontaine;37;0;37 +70271;Gouhenans;388;10;398 +70272;Gourgeon;208;13;221 +70273;Grammont;66;1;67 +70443;La Grande-Résie;86;1;87 +70274;Grandecourt;48;0;48 +70275;Grandvelle-et-le-Perrenot;371;5;376 +70276;Granges-la-Ville;185;8;193 +70277;Granges-le-Bourg;387;10;397 +70278;Grattery;213;4;217 +70279;Gray;5512;404;5916 +70280;Gray-la-Ville;955;37;992 +70282;Gy;1049;21;1070 +70283;Haut-du-Them-Château-Lambert;434;9;443 +70284;Hautevelle;267;9;276 +70285;Héricourt;10601;280;10881 +70286;Hugier;128;3;131 +70287;Hurecourt;40;2;42 +70288;Hyet;124;0;124 +70289;Igny;200;2;202 +70290;Jasney;233;10;243 +70291;Jonvelle;126;2;128 +70292;Jussey;1613;43;1656 +70293;Lambrey;83;2;85 +70294;Lantenot;353;5;358 +70295;La Lanterne-et-les-Armonts;215;5;220 +70296;Larians-et-Munans;260;2;262 +70297;Larret;60;3;63 +70298;Lavigney;121;0;121 +70299;Lavoncourt;309;4;313 +70301;Lieffrans;62;0;62 +70302;Lieucourt;77;1;78 +70303;Liévans;148;2;150 +70304;Linexert;128;1;129 +70306;Lomont;443;4;447 +70307;Longevelle;125;7;132 +70308;La Longine;226;7;233 +70309;Loulans-Verchamp;453;15;468 +70310;Lure;8207;202;8409 +70311;Luxeuil-les-Bains;6722;286;7008 +70312;Luze;707;22;729 +70313;Lyoffans;375;5;380 +70305;Lœuilley;104;2;106 +70314;Magnivray;168;8;176 +70315;Magnoncourt;418;13;431 +70316;Le Magnoray;89;4;93 +70317;Les Magny;139;4;143 +70318;Magny-Danigon;439;15;454 +70319;Magny-Jobert;110;1;111 +70320;Magny-lès-Jussey;103;0;103 +70321;Magny-Vernois;1376;31;1407 +70322;Mailleroncourt-Charette;279;6;285 +70323;Mailleroncourt-Saint-Pancras;192;1;193 +70324;Mailley-et-Chazelot;649;14;663 +70325;Maizières;363;29;392 +70326;La Malachère;307;4;311 +70327;Malans;134;4;138 +70328;Malbouhans;335;4;339 +70329;Malvillers;63;4;67 +70330;Mandrevillars;242;7;249 +70331;Mantoche;448;20;468 +70332;Marast;55;1;56 +70334;Marnay;1481;22;1503 +70335;Maussans;67;1;68 +70336;Mélecey;144;3;147 +70337;Melin;58;2;60 +70338;Melincourt;237;3;240 +70339;Mélisey;1681;36;1717 +70340;Membrey;217;31;248 +70341;Menoux;301;5;306 +70342;Mercey-sur-Saône;133;2;135 +70343;Mersuay;289;5;294 +70344;Meurcourt;330;10;340 +70347;Mignavillers;339;5;344 +70348;Moffans-et-Vacheresse;625;12;637 +70349;Moimay;236;3;239 +70350;Molay;67;0;67 +70351;Mollans;234;3;237 +70367;Mont-le-Vernois;171;3;174 +70369;Mont-Saint-Léger;51;0;51 +70352;La Montagne;37;0;37 +70353;Montagney;514;8;522 +70355;Montarlot-lès-Rioz;285;7;292 +70356;Montboillon;270;6;276 +70357;Montbozon;562;94;656 +70358;Montcey;276;4;280 +70359;Montcourt;55;0;55 +70360;Montdoré;73;1;74 +70361;Montessaux;162;6;168 +70362;Montigny-lès-Cherlieu;157;6;163 +70363;Montigny-lès-Vesoul;660;19;679 +70364;Montjustin-et-Velotte;121;4;125 +70368;Montot;132;3;135 +70371;Montureux-et-Prantigny;208;1;209 +70372;Montureux-lès-Baulay;156;4;160 +70374;Motey-Besuche;103;2;105 +70376;Nantilly;481;10;491 +70378;Navenne;1660;57;1717 +70380;Neurey-en-Vaux;176;6;182 +70381;Neurey-lès-la-Demie;328;11;339 +70383;Neuvelle-lès-Cromary;403;5;408 +70384;Neuvelle-lès-la-Charité;225;5;230 +70385;La Neuvelle-lès-Lure;333;9;342 +70386;La Neuvelle-lès-Scey;187;7;194 +70387;Noidans-le-Ferroux;687;10;697 +70388;Noidans-lès-Vesoul;1992;68;2060 +70389;Noiron;57;1;58 +70390;Noroy-le-Bourg;497;11;508 +70392;Oigney;41;2;43 +70393;Oiselay-et-Grachaux;422;6;428 +70394;Onay;60;4;64 +70395;Oppenans;53;1;54 +70396;Oricourt;38;1;39 +70397;Ormenans;77;0;77 +70398;Ormoiche;65;4;69 +70399;Ormoy;215;7;222 +70400;Ouge;102;3;105 +70401;Ovanches;133;1;134 +70402;Oyrières;381;11;392 +70403;Palante;239;4;243 +70404;Passavant-la-Rochère;603;19;622 +70405;Pennesières;193;4;197 +70406;Percey-le-Grand;83;1;84 +70407;Perrouse;267;6;273 +70408;Pesmes;1084;29;1113 +70409;Pierrecourt;113;2;115 +70410;Pin;700;4;704 +70411;La Pisseure;37;0;37 +70412;Plainemont;68;0;68 +70413;Plancher-Bas;1965;36;2001 +70414;Plancher-les-Mines;975;15;990 +70415;Polaincourt-et-Clairefontaine;734;9;743 +70416;Pomoy;210;7;217 +70419;Pont-du-Bois;108;5;113 +70420;Pont-sur-l'Ognon;67;0;67 +70417;Pontcey;324;9;333 +70421;Port-sur-Saône;2971;57;3028 +70422;Poyans;146;1;147 +70423;Preigney;108;1;109 +70425;La Proiselière-et-Langle;146;6;152 +70426;Provenchère;260;7;267 +70427;Purgerot;342;9;351 +70428;Pusey;1474;50;1524 +70429;Pusy-et-Épenoux;552;12;564 +70430;La Quarte;66;1;67 +70431;Quenoche;249;3;252 +70432;Quers;345;7;352 +70433;Quincey;1399;39;1438 +70435;Raddon-et-Chapendu;861;23;884 +70436;Raincourt;121;0;121 +70437;Ranzevelle;17;0;17 +70438;Ray-sur-Saône;210;3;213 +70439;Raze;352;7;359 +70440;Recologne;32;2;34 +70441;Recologne-lès-Rioz;249;3;252 +70442;Renaucourt;105;4;109 +70444;La Résie-Saint-Martin;158;2;160 +70445;Rignovelle;112;0;112 +70446;Rigny;595;10;605 +70447;Rioz;2270;90;2360 +70448;Roche-et-Raucourt;160;2;162 +70373;La Roche-Morey;281;4;285 +70449;Roche-sur-Linotte-et-Sorans-les-Cordiers;66;0;66 +70450;La Rochelle;39;0;39 +70418;La Romaine;511;4;515 +70451;Ronchamp;2757;31;2788 +70452;Rosey;268;3;271 +70453;La Rosière;80;3;83 +70454;Rosières-sur-Mance;49;2;51 +70455;Roye;1553;29;1582 +70456;Ruhans;155;5;160 +70457;Rupt-sur-Saône;111;5;116 +70459;Saint-Barthélemy;1115;29;1144 +70460;Saint-Bresson;439;10;449 +70461;Saint-Broing;115;3;118 +70462;Saint-Ferjeux;78;2;80 +70463;Saint-Gand;137;1;138 +70464;Saint-Germain;1344;25;1369 +70466;Saint-Loup-Nantouard;122;3;125 +70467;Saint-Loup-sur-Semouse;3221;80;3301 +70468;Saint-Marcel;93;1;94 +70472;Saint-Rémy-en-Comté;571;5;576 +70473;Saint-Sauveur;1920;43;1963 +70474;Saint-Sulpice;131;2;133 +70469;Sainte-Marie-en-Chanois;216;5;221 +70470;Sainte-Marie-en-Chaux;161;3;164 +70471;Sainte-Reine;31;1;32 +70476;Saponcourt;64;1;65 +70477;Saulnot;752;13;765 +70478;Saulx;898;16;914 +70479;Sauvigney-lès-Gray;102;4;106 +70480;Sauvigney-lès-Pesmes;139;7;146 +70481;Savoyeux;210;4;214 +70482;Scey-sur-Saône-et-Saint-Albin;1545;26;1571 +70483;Scye;135;4;139 +70484;Secenans;178;3;181 +70485;Selles;204;7;211 +70486;Semmadon;116;3;119 +70487;Senargent-Mignafans;295;3;298 +70488;Senoncourt;196;1;197 +70489;Servance-Miellin;816;32;848 +70490;Servigney;122;0;122 +70491;Seveux-Motey;488;6;494 +70492;Soing-Cubry-Charentenay;570;10;580 +70493;Sorans-lès-Breurey;441;7;448 +70494;Sornay;337;6;343 +70496;Tartécourt;27;1;28 +70498;Ternuay-Melay-et-Saint-Hilaire;487;14;501 +70499;Theuley;104;2;106 +70500;Thieffrans;173;11;184 +70501;Thiénans;93;3;96 +70502;Tincey-et-Pontrebeau;86;1;87 +70503;Traitiéfontaine;162;2;164 +70504;Traves;362;13;375 +70505;Le Tremblois;176;9;185 +70506;Trémoins;386;13;399 +70507;Trésilley;221;7;228 +70509;Tromarey;101;1;102 +70510;Vadans;134;3;137 +70511;Vaite;218;4;222 +70512;La Vaivre;216;5;221 +70513;Vaivre-et-Montoille;2417;60;2477 +70515;Le Val-de-Gouhenans;66;1;67 +70518;Le Val-Saint-Éloi;100;2;102 +70514;Valay;693;11;704 +70516;Vallerois-le-Bois;256;4;260 +70517;Vallerois-Lorioz;370;18;388 +70519;Vandelans;111;0;111 +70520;Vanne;103;3;106 +70521;Vantoux-et-Longevelle;181;4;185 +70522;Varogne;146;4;150 +70523;Vars;203;3;206 +70524;Vauchoux;111;3;114 +70525;Vauconcourt-Nervezain;215;3;218 +70526;Vauvillers;660;15;675 +70527;Vaux-le-Moncelot;70;0;70 +70528;Velesmes-Échevanne;485;10;495 +70529;Velet;393;15;408 +70536;Velle-le-Châtel;132;2;134 +70530;Vellechevreux-et-Courbenans;128;0;128 +70531;Velleclaire;109;2;111 +70532;Vellefaux;499;7;506 +70533;Vellefrey-et-Vellefrange;121;0;121 +70534;Vellefrie;127;1;128 +70535;Velleguindry-et-Levrecey;156;1;157 +70537;Velleminfroy;298;6;304 +70538;Vellemoz;82;0;82 +70539;Vellexon-Queutrey-et-Vaudey;453;13;466 +70540;Velloreille-lès-Choye;78;4;82 +70541;Velorcey;209;4;213 +70542;Venère;218;5;223 +70545;Venisey;136;3;139 +70546;Vereux;227;23;250 +70544;La Vergenne;118;2;120 +70547;Verlans;174;3;177 +70548;Vernois-sur-Mance;146;1;147 +70549;La Vernotte;76;1;77 +70550;Vesoul;14916;812;15728 +70552;Villafans;211;4;215 +70553;Villargent;120;2;122 +70554;Villars-le-Pautel;193;2;195 +70555;La Villedieu-en-Fontenette;176;2;178 +70557;Villefrancon;140;2;142 +70558;La Villeneuve-Bellenoye-et-la-Maize;139;2;141 +70559;Villeparois;206;5;211 +70560;Villers-Bouton;162;2;164 +70366;Villers-Chemin-et-Mont-lès-Étrelles;123;0;123 +70562;Villers-la-Ville;146;3;149 +70563;Villers-le-Sec;531;13;544 +70564;Villers-lès-Luxeuil;303;11;314 +70565;Villers-Pater;51;2;53 +70566;Villers-sur-Port;208;5;213 +70567;Villers-sur-Saulnot;133;0;133 +70568;Villers-Vaudey;58;4;62 +70561;Villersexel;1441;106;1547 +70569;Vilory;65;1;66 +70571;Visoncourt;40;2;42 +70572;Vitrey-sur-Mance;277;7;284 +70573;La Voivre;146;3;149 +70574;Volon;60;0;60 +70575;Voray-sur-l'Ognon;827;16;843 +70576;Vougécourt;149;1;150 +70577;Vouhenans;371;9;380 +70578;Vregille;174;2;176 +70580;Vy-le-Ferroux;156;5;161 +70583;Vy-lès-Filain;126;1;127 +70581;Vy-lès-Lure;676;18;694 +70582;Vy-lès-Rupt;90;0;90 +70579;Vyans-le-Val;453;17;470 +71001;L' Abergement-de-Cuisery;797;15;812 +71002;L' Abergement-Sainte-Colombe;1224;20;1244 +71003;Allerey-sur-Saône;802;6;808 +71004;Allériot;1145;25;1170 +71005;Aluze;251;10;261 +71006;Amanzé;176;8;184 +71007;Ameugny;172;4;176 +71008;Anglure-sous-Dun;156;7;163 +71009;Anost;730;14;744 +71010;Antully;854;10;864 +71011;Anzy-le-Duc;472;87;559 +71012;Artaix;327;14;341 +71013;Authumes;252;5;257 +71014;Autun;13290;1091;14381 +71015;Auxy;934;29;963 +71016;Azé;1046;27;1073 +71017;Ballore;92;4;96 +71018;Bantanges;549;10;559 +71019;Barizey;144;7;151 +71020;Barnay;100;2;102 +71021;Baron;292;22;314 +71022;Baudemont;640;9;649 +71023;Baudrières;947;25;972 +71024;Baugy;503;17;520 +71025;Beaubery;367;8;375 +71026;Beaumont-sur-Grosne;347;8;355 +71027;Beaurepaire-en-Bresse;696;5;701 +71028;Beauvernois;115;3;118 +71029;Bellevesvre;282;4;286 +71030;Bergesserin;205;4;209 +71032;Berzé-la-Ville;676;15;691 +71031;Berzé-le-Châtel;59;2;61 +71033;Bey;845;15;860 +71034;Bissey-sous-Cruchaud;341;7;348 +71035;Bissy-la-Mâconnaise;205;3;208 +71036;Bissy-sous-Uxelles;68;2;70 +71037;Bissy-sur-Fley;89;6;95 +71038;Les Bizots;465;12;477 +71039;Blanot;177;1;178 +71040;Blanzy;6146;140;6286 +71041;Bois-Sainte-Marie;197;2;199 +71042;Bonnay;325;7;332 +71043;Les Bordes;85;3;88 +71044;Bosjean;308;6;314 +71045;Bouhans;175;6;181 +71046;La Boulaye;100;1;101 +71047;Bourbon-Lancy;4927;73;5000 +71048;Bourg-le-Comte;181;2;183 +71050;Bourgvilain;331;7;338 +71051;Bouzeron;137;8;145 +71052;Boyer;719;11;730 +71054;Bragny-sur-Saône;652;13;665 +71056;Branges;2357;34;2391 +71057;Bray;122;1;123 +71058;Bresse-sur-Grosne;186;11;197 +71059;Le Breuil;3573;69;3642 +71060;Briant;224;2;226 +71061;Brienne;468;11;479 +71062;Brion;299;8;307 +71063;Broye;762;14;776 +71064;Bruailles;990;14;1004 +71065;Buffières;275;8;283 +71066;Burgy;124;0;124 +71067;Burnand;129;7;136 +71068;Burzy;60;2;62 +71069;Bussières;567;26;593 +71070;Buxy;2136;85;2221 +71509;La Celle-en-Morvan;481;6;487 +71071;Céron;260;9;269 +71072;Cersot;139;2;141 +71073;Chagny;5543;73;5616 +71074;Chaintré;584;16;600 +71075;Chalmoux;636;11;647 +71076;Chalon-sur-Saône;45096;1507;46603 +71077;Chambilly;511;4;515 +71078;Chamilly;158;3;161 +71079;Champagnat;450;13;463 +71080;Champagny-sous-Uxelles;97;0;97 +71081;Champforgeuil;2534;54;2588 +71082;Champlecy;223;3;226 +71084;Chânes;538;11;549 +71085;Change;219;11;230 +71086;Changy;467;9;476 +71087;Chapaize;157;1;158 +71088;La Chapelle-au-Mans;227;10;237 +71089;La Chapelle-de-Bragny;248;2;250 +71090;La Chapelle-de-Guinchay;4121;52;4173 +71091;La Chapelle-du-Mont-de-France;187;2;189 +71092;La Chapelle-Naude;531;11;542 +71093;La Chapelle-Saint-Sauveur;681;22;703 +71094;La Chapelle-sous-Brancion;133;2;135 +71095;La Chapelle-sous-Dun;448;9;457 +71096;La Chapelle-sous-Uchon;188;2;190 +71097;La Chapelle-Thècle;466;13;479 +71098;Charbonnat;248;5;253 +71099;Charbonnières;328;14;342 +71100;Chardonnay;197;0;197 +71101;Charette-Varennes;456;8;464 +71102;La Charmée;695;24;719 +71103;Charmoy;257;6;263 +71104;Charnay-lès-Chalon;187;6;193 +71105;Charnay-lès-Mâcon;7376;287;7663 +71106;Charolles;2785;435;3220 +71107;Charrecey;321;10;331 +71108;Chasselas;170;5;175 +71109;Chassey-le-Camp;344;2;346 +71110;Chassigny-sous-Dun;572;11;583 +71111;Chassy;313;11;324 +71112;Château;219;10;229 +71113;Châteauneuf;109;0;109 +71115;Châtel-Moron;102;1;103 +71116;Châtenay;165;2;167 +71117;Châtenoy-en-Bresse;1109;31;1140 +71118;Châtenoy-le-Royal;6177;139;6316 +71119;Chaudenay;1112;24;1136 +71120;Chauffailles;3708;69;3777 +71121;La Chaux;302;9;311 +71122;Cheilly-lès-Maranges;550;14;564 +71123;Chenay-le-Châtel;382;4;386 +71124;Chenôves;208;7;215 +71125;Chérizet;20;0;20 +71126;Chevagny-les-Chevrières;592;23;615 +71127;Chevagny-sur-Guye;74;1;75 +71128;Chiddes;93;5;98 +71129;Chissey-en-Morvan;275;7;282 +71130;Chissey-lès-Mâcon;237;6;243 +71131;Ciel;769;12;781 +71132;Ciry-le-Noble;2275;32;2307 +71133;La Clayette;1656;72;1728 +71135;Clessé;869;20;889 +71136;Clessy;251;7;258 +71137;Cluny;4830;268;5098 +71578;Clux-Villeneuve;324;11;335 +71139;Collonge-en-Charollais;141;1;142 +71140;Collonge-la-Madeleine;47;0;47 +71141;Colombier-en-Brionnais;308;5;313 +71142;La Comelle;225;5;230 +71143;Condal;441;8;449 +71144;Cordesse;190;5;195 +71145;Cormatin;557;9;566 +71146;Cortambert;232;7;239 +71147;Cortevaix;252;6;258 +71148;Coublanc;834;15;849 +71149;Couches;1351;30;1381 +71150;Crêches-sur-Saône;2986;77;3063 +71151;Créot;81;3;84 +71152;Cressy-sur-Somme;186;9;195 +71153;Le Creusot;21630;305;21935 +71154;Crissey;2480;63;2543 +71155;Cronat;535;15;550 +71156;Cruzille;263;65;328 +71157;Cuiseaux;1829;29;1858 +71158;Cuisery;1538;25;1563 +71159;Culles-les-Roches;197;8;205 +71160;Curbigny;319;13;332 +71161;Curdin;316;6;322 +71162;Curgy;1145;44;1189 +71163;Curtil-sous-Buffières;90;1;91 +71164;Curtil-sous-Burnand;133;3;136 +71165;Cussy-en-Morvan;388;9;397 +71166;Cuzy;119;2;121 +71167;Damerey;558;19;577 +71168;Dampierre-en-Bresse;171;1;172 +71169;Davayé;694;108;802 +71170;Demigny;1794;40;1834 +71171;Dennevy;306;9;315 +71172;Dettey;80;1;81 +71173;Devrouze;311;4;315 +71174;Dezize-lès-Maranges;174;4;178 +71175;Diconne;343;3;346 +71176;Digoin;7817;243;8060 +71177;Dommartin-lès-Cuiseaux;794;12;806 +71178;Dompierre-les-Ormes;907;32;939 +71179;Dompierre-sous-Sanvignes;79;1;80 +71181;Donzy-le-Pertuis;167;4;171 +71182;Dracy-le-Fort;1333;53;1386 +71183;Dracy-lès-Couches;153;4;157 +71184;Dracy-Saint-Loup;570;22;592 +71185;Dyo;340;14;354 +71186;Écuelles;273;5;278 +71187;Écuisses;1583;33;1616 +71188;Épertully;61;1;62 +71189;Épervans;1613;51;1664 +71190;Épinac;2217;25;2242 +71191;Essertenne;475;9;484 +71192;Étang-sur-Arroux;1858;151;2009 +71193;Étrigny;474;12;486 +71194;Farges-lès-Chalon;779;14;793 +71195;Farges-lès-Mâcon;219;6;225 +71196;Le Fay;639;8;647 +71198;Flacey-en-Bresse;400;7;407 +71199;Flagy;169;8;177 +71591;Fleurville;519;8;527 +71200;Fleury-la-Montagne;691;17;708 +71201;Fley;211;8;219 +71202;Fontaines;1948;363;2311 +71203;Fontenay;45;1;46 +71204;Fragnes-La Loyère;1496;41;1537 +71205;Frangy-en-Bresse;621;10;631 +71206;La Frette;241;4;245 +71207;Fretterans;287;11;298 +71208;Frontenard;223;3;226 +71209;Frontenaud;729;13;742 +71210;Fuissé;381;19;400 +71212;Génelard;1372;32;1404 +71213;La Genête;572;13;585 +71214;Genouilly;427;13;440 +71215;Gergy;2545;70;2615 +71216;Germagny;202;7;209 +71217;Germolles-sur-Grosne;127;5;132 +71218;Gibles;590;21;611 +71219;Gigny-sur-Saône;528;14;542 +71220;Gilly-sur-Loire;487;3;490 +71221;Givry;3705;155;3860 +71222;Gourdon;904;26;930 +71223;La Grande-Verrière;563;9;572 +71224;Grandvaux;76;8;84 +71225;Granges;528;13;541 +71226;Grevilly;34;0;34 +71227;Grury;535;9;544 +71228;Guerfand;206;0;206 +71229;Les Guerreaux;236;1;237 +71230;Gueugnon;6992;204;7196 +71231;La Guiche;623;12;635 +71232;Hautefond;206;14;220 +71233;L' Hôpital-le-Mercier;303;7;310 +71234;Huilly-sur-Seille;334;6;340 +71235;Hurigny;1983;107;2090 +71236;Igé;871;21;892 +71237;Igornay;539;10;549 +71238;Iguerande;996;19;1015 +71239;Issy-l'Évêque;706;10;716 +71240;Jalogny;359;13;372 +71241;Jambles;490;18;508 +71242;Joncy;530;8;538 +71243;Joudes;379;4;383 +71244;Jouvençon;429;2;431 +71245;Jugy;322;6;328 +71246;Juif;259;4;263 +71247;Jully-lès-Buxy;366;10;376 +71248;Lacrost;729;16;745 +71249;Laives;1020;37;1057 +71250;Laizé;1087;50;1137 +71251;Laizy;579;17;596 +71252;Lalheue;395;15;410 +71253;Lans;924;24;948 +71254;Lays-sur-le-Doubs;143;0;143 +71255;Lesme;187;2;189 +71256;Lessard-en-Bresse;542;13;555 +71257;Lessard-le-National;644;26;670 +71258;Leynes;517;15;532 +71259;Ligny-en-Brionnais;340;7;347 +71261;Loisy;651;15;666 +71262;Longepierre;168;4;172 +71263;Louhans;6365;204;6569 +71264;Lournand;331;9;340 +71266;Lucenay-l'Évêque;319;3;322 +71267;Lugny;875;85;960 +71268;Lugny-lès-Charolles;350;10;360 +71269;Lux;2011;33;2044 +71270;Mâcon;33638;779;34417 +71271;Mailly;155;10;165 +71272;Malay;206;9;215 +71273;Maltat;283;6;289 +71274;Mancey;387;10;397 +71275;Marcigny;1780;33;1813 +71276;Marcilly-la-Gueurce;120;6;126 +71277;Marcilly-lès-Buxy;691;19;710 +71278;Marigny;154;5;159 +71280;Marly-sous-Issy;88;2;90 +71281;Marly-sur-Arroux;323;14;337 +71282;Marmagne;1242;33;1275 +71283;Marnay;558;5;563 +71284;Martailly-lès-Brancion;142;7;149 +71285;Martigny-le-Comte;417;7;424 +71286;Mary;245;3;248 +71287;Massilly;356;7;363 +71289;Matour;1119;21;1140 +71290;Mazille;384;68;452 +71291;Melay;994;13;1007 +71292;Mellecey;1299;45;1344 +71293;Ménetreuil;410;8;418 +71294;Mercurey;1193;169;1362 +71295;Mervans;1494;24;1518 +71296;Messey-sur-Grosne;753;19;772 +71297;Mesvres;760;27;787 +71299;Milly-Lamartine;330;8;338 +71300;Le Miroir;609;8;617 +71301;Mont;186;2;188 +71315;Mont-lès-Seurre;180;2;182 +71320;Mont-Saint-Vincent;327;3;330 +71302;Montagny-lès-Buxy;218;9;227 +71303;Montagny-près-Louhans;454;6;460 +71305;Montbellet;800;18;818 +71306;Montceau-les-Mines;18398;391;18789 +71307;Montceaux-l'Étoile;290;7;297 +71308;Montceaux-Ragny;31;0;31 +71309;Montcenis;2095;64;2159 +71310;Montchanin;5030;88;5118 +71311;Montcony;266;4;270 +71312;Montcoy;251;1;252 +71313;Monthelon;384;15;399 +71314;Montjay;202;0;202 +71316;Montmelard;356;6;362 +71317;Montmort;177;3;180 +71318;Montpont-en-Bresse;1099;14;1113 +71319;Montret;801;19;820 +71321;Morey;199;4;203 +71322;Morlet;62;1;63 +71323;Mornay;132;0;132 +71324;Moroges;569;17;586 +71325;La Motte-Saint-Jean;1217;31;1248 +71326;Mouthier-en-Bresse;426;7;433 +71327;Mussy-sous-Dun;349;8;357 +71328;Nanton;634;12;646 +71329;Navilly;423;9;432 +71134;Navour-sur-Grosne;653;21;674 +71330;Neuvy-Grandchamp;762;25;787 +71331;Nochize;115;1;116 +71332;Ormes;477;5;482 +71333;Oslon;1230;41;1271 +71334;Oudry;387;9;396 +71335;Ouroux-sous-le-Bois-Sainte-Marie;67;0;67 +71336;Ouroux-sur-Saône;3072;79;3151 +71337;Oyé;302;8;310 +71338;Ozenay;219;2;221 +71339;Ozolles;418;9;427 +71340;Palinges;1513;32;1545 +71341;Palleau;246;2;248 +71342;Paray-le-Monial;9189;450;9639 +71343;Paris-l'Hôpital;306;4;310 +71344;Passy;64;2;66 +71345;Péronne;652;11;663 +71346;Perrecy-les-Forges;1627;30;1657 +71347;Perreuil;549;15;564 +71348;Perrigny-sur-Loire;135;3;138 +71349;La Petite-Verrière;52;1;53 +71351;Pierre-de-Bresse;1946;31;1977 +71350;Pierreclos;904;22;926 +71352;Le Planois;93;3;96 +71353;Plottes;534;6;540 +71354;Poisson;567;21;588 +71355;Pontoux;275;7;282 +71356;Pouilloux;992;18;1010 +71357;Pourlans;210;2;212 +71358;Pressy-sous-Dondin;99;3;102 +71359;Préty;544;17;561 +71360;Prissé;1994;49;2043 +71361;Prizy;64;5;69 +71362;Pruzilly;337;5;342 +71363;Le Puley;97;2;99 +71364;La Racineuse;174;1;175 +71365;Rancy;561;8;569 +71366;Ratenelle;389;6;395 +71367;Ratte;361;10;371 +71368;Reclesne;320;17;337 +71369;Remigny;433;8;441 +71370;Rigny-sur-Arroux;642;11;653 +71371;La Roche-Vineuse;1557;41;1598 +71372;Romanèche-Thorins;2006;33;2039 +71373;Romenay;1674;20;1694 +71374;Rosey;166;2;168 +71279;Le Rousset-Marizy;653;20;673 +71376;Roussillon-en-Morvan;270;8;278 +71377;Royer;131;2;133 +71378;Rully;1554;35;1589 +71379;Sagy;1235;18;1253 +71380;Saillenard;785;16;801 +71381;Sailly;85;0;85 +71382;Saint-Agnan;705;15;720 +71383;Saint-Albain;513;5;518 +71384;Saint-Ambreuil;506;8;514 +71385;Saint-Amour-Bellevue;558;21;579 +71386;Saint-André-en-Bresse;98;0;98 +71387;Saint-André-le-Désert;251;5;256 +71388;Saint-Aubin-en-Charollais;472;20;492 +71389;Saint-Aubin-sur-Loire;292;5;297 +71390;Saint-Berain-sous-Sanvignes;1093;22;1115 +71391;Saint-Bérain-sur-Dheune;553;9;562 +71392;Saint-Boil;491;10;501 +71393;Saint-Bonnet-de-Cray;485;12;497 +71394;Saint-Bonnet-de-Joux;758;20;778 +71395;Saint-Bonnet-de-Vieille-Vigne;200;2;202 +71396;Saint-Bonnet-en-Bresse;483;4;487 +71398;Saint-Christophe-en-Bresse;1087;31;1118 +71399;Saint-Christophe-en-Brionnais;527;16;543 +71400;Saint-Clément-sur-Guye;131;3;134 +71402;Saint-Cyr;729;20;749 +71403;Saint-Denis-de-Vaux;263;10;273 +71404;Saint-Désert;881;28;909 +71405;Saint-Didier-en-Bresse;188;0;188 +71406;Saint-Didier-en-Brionnais;134;10;144 +71407;Saint-Didier-sur-Arroux;232;4;236 +71408;Saint-Edmond;404;9;413 +71409;Saint-Émiland;343;10;353 +71410;Saint-Étienne-en-Bresse;799;14;813 +71411;Saint-Eugène;151;8;159 +71412;Saint-Eusèbe;1191;24;1215 +71413;Saint-Firmin;889;19;908 +71414;Saint-Forgeot;468;18;486 +71416;Saint-Gengoux-de-Scissé;608;3;611 +71417;Saint-Gengoux-le-National;1046;8;1054 +71419;Saint-Germain-du-Bois;1899;40;1939 +71420;Saint-Germain-du-Plain;2290;49;2339 +71421;Saint-Germain-en-Brionnais;190;7;197 +71422;Saint-Germain-lès-Buxy;268;9;277 +71423;Saint-Gervais-en-Vallière;438;10;448 +71424;Saint-Gervais-sur-Couches;202;1;203 +71425;Saint-Gilles;270;10;280 +71427;Saint-Huruge;53;1;54 +71428;Saint-Igny-de-Roche;766;15;781 +71431;Saint-Jean-de-Trézy;368;13;381 +71430;Saint-Jean-de-Vaux;407;13;420 +71433;Saint-Julien-de-Civry;487;14;501 +71434;Saint-Julien-de-Jonzy;345;7;352 +71435;Saint-Julien-sur-Dheune;239;2;241 +71436;Saint-Laurent-d'Andenay;1019;15;1034 +71437;Saint-Laurent-en-Brionnais;326;11;337 +71438;Saint-Léger-du-Bois;537;10;547 +71439;Saint-Léger-lès-Paray;730;20;750 +71440;Saint-Léger-sous-Beuvray;380;10;390 +71441;Saint-Léger-sous-la-Bussière;271;4;275 +71442;Saint-Léger-sur-Dheune;1567;20;1587 +71444;Saint-Loup-de-Varennes;1161;28;1189 +71443;Saint-Loup-Géanges;1631;45;1676 +71445;Saint-Marcel;6049;173;6222 +71446;Saint-Marcelin-de-Cray;186;6;192 +71447;Saint-Mard-de-Vaux;275;13;288 +71448;Saint-Martin-Belle-Roche;1392;26;1418 +71449;Saint-Martin-d'Auxy;111;6;117 +71450;Saint-Martin-de-Commune;106;6;112 +71451;Saint-Martin-de-Lixy;92;0;92 +71452;Saint-Martin-de-Salencey;99;1;100 +71453;Saint-Martin-du-Lac;242;11;253 +71454;Saint-Martin-du-Mont;202;4;206 +71455;Saint-Martin-du-Tartre;159;4;163 +71456;Saint-Martin-en-Bresse;1921;77;1998 +71457;Saint-Martin-en-Gâtinois;123;1;124 +71458;Saint-Martin-la-Patrouille;62;0;62 +71459;Saint-Martin-sous-Montaigu;353;17;370 +71460;Saint-Maurice-de-Satonnay;486;23;509 +71461;Saint-Maurice-des-Champs;62;1;63 +71462;Saint-Maurice-en-Rivière;554;11;565 +71463;Saint-Maurice-lès-Châteauneuf;569;12;581 +71464;Saint-Maurice-lès-Couches;191;8;199 +71465;Saint-Micaud;273;10;283 +71466;Saint-Nizier-sur-Arroux;125;4;129 +71468;Saint-Pierre-de-Varennes;849;16;865 +71469;Saint-Pierre-le-Vieux;355;10;365 +71470;Saint-Point;328;14;342 +71471;Saint-Privé;82;1;83 +71472;Saint-Prix;217;10;227 +71473;Saint-Racho;171;1;172 +71475;Saint-Rémy;6639;157;6796 +71477;Saint-Romain-sous-Gourdon;479;9;488 +71478;Saint-Romain-sous-Versigny;85;2;87 +71479;Saint-Sernin-du-Bois;1812;37;1849 +71480;Saint-Sernin-du-Plain;581;13;594 +71481;Saint-Symphorien-d'Ancelles;1187;17;1204 +71482;Saint-Symphorien-de-Marmagne;846;11;857 +71483;Saint-Symphorien-des-Bois;438;12;450 +71484;Saint-Usuge;1345;19;1364 +71485;Saint-Vallerin;263;13;276 +71486;Saint-Vallier;8654;177;8831 +71487;Saint-Vérand;165;2;167 +71490;Saint-Vincent-Bragny;997;17;1014 +71488;Saint-Vincent-des-Prés;109;3;112 +71489;Saint-Vincent-en-Bresse;573;9;582 +71491;Saint-Yan;1169;24;1193 +71492;Saint-Ythaire;125;3;128 +71397;Sainte-Cécile;288;8;296 +71401;Sainte-Croix;635;14;649 +71415;Sainte-Foy;139;2;141 +71426;Sainte-Hélène;523;10;533 +71474;Sainte-Radegonde;154;2;156 +71493;Saisy;334;12;346 +71494;La Salle;545;11;556 +71495;Salornay-sur-Guye;864;12;876 +71496;Sampigny-lès-Maranges;143;10;153 +71497;Sancé;2033;50;2083 +71498;Santilly;133;6;139 +71499;Sanvignes-les-Mines;4317;85;4402 +71500;Sarry;104;3;107 +71501;Sassangy;147;3;150 +71502;Sassenay;1587;44;1631 +71503;Saules;128;3;131 +71504;Saunières;81;2;83 +71505;Savianges;74;0;74 +71506;Savigny-en-Revermont;1156;17;1173 +71507;Savigny-sur-Grosne;170;1;171 +71508;Savigny-sur-Seille;423;9;432 +71510;Semur-en-Brionnais;623;19;642 +71512;Sennecey-le-Grand;3149;51;3200 +71513;Senozan;1125;16;1141 +71514;Sens-sur-Seille;411;5;416 +71515;Sercy;97;7;104 +71516;Serley;608;7;615 +71517;Sermesse;237;3;240 +71518;Serrières;275;9;284 +71519;Serrigny-en-Bresse;200;4;204 +71520;Sevrey;1226;25;1251 +71521;Sigy-le-Châtel;103;2;105 +71522;Simandre;1728;21;1749 +71523;Simard;1208;12;1220 +71524;Sivignon;166;6;172 +71525;Sologny;591;11;602 +71526;Solutré-Pouilly;358;7;365 +71527;Sommant;211;4;215 +71528;Sornay;2030;44;2074 +71529;Suin;266;7;273 +71530;Sully;496;18;514 +71531;La Tagnière;230;1;231 +71532;Taizé;178;3;181 +71533;Tancon;542;17;559 +71534;Le Tartre;114;1;115 +71535;Tavernay;495;11;506 +71537;Thil-sur-Arroux;133;0;133 +71538;Thurey;456;5;461 +71539;Tintry;78;2;80 +71540;Torcy;2960;40;3000 +71541;Torpes;372;4;376 +71542;Toulon-sur-Arroux;1585;39;1624 +71543;Tournus;5545;340;5885 +71544;Toutenant;190;5;195 +71545;Tramayes;1056;20;1076 +71546;Trambly;399;10;409 +71547;Trivy;274;5;279 +71548;Tronchy;257;1;258 +71549;La Truchère;226;2;228 +71550;Uchizy;843;14;857 +71551;Uchon;98;5;103 +71552;Uxeau;519;15;534 +71553;Vareilles;268;5;273 +71554;Varenne-l'Arconce;117;3;120 +71557;Varenne-Saint-Germain;713;18;731 +71555;Varennes-le-Grand;2298;48;2346 +71556;Varennes-lès-Mâcon;548;8;556 +71558;Varennes-Saint-Sauveur;1133;26;1159 +71559;Varennes-sous-Dun;573;15;588 +71561;Vauban;223;9;232 +71562;Vaudebarrier;221;33;254 +71563;Vaux-en-Pré;79;1;80 +71564;Vendenesse-lès-Charolles;743;20;763 +71565;Vendenesse-sur-Arroux;582;15;597 +71566;Verdun-sur-le-Doubs;1083;8;1091 +71567;Vergisson;255;7;262 +71568;Vérissey;55;0;55 +71570;Verjux;528;12;540 +71571;Verosvres;448;59;507 +71572;Vers;231;6;237 +71573;Versaugues;193;14;207 +71574;Verzé;787;26;813 +71576;Le Villars;285;4;289 +71577;Villegaudin;212;4;216 +71579;Villeneuve-en-Montagne;163;0;163 +71580;Vincelles;424;10;434 +71581;Vindecy;254;5;259 +71582;La Vineuse sur Fregande;655;18;673 +71583;Vinzelles;702;21;723 +71584;Viré;1181;27;1208 +71585;Virey-le-Grand;1342;73;1415 +71586;Viry;255;4;259 +71588;Vitry-en-Charollais;1098;24;1122 +71589;Vitry-sur-Loire;432;7;439 +71590;Volesvres;607;24;631 +72001;Aigné;1659;36;1695 +72002;Aillières-Beauvoir;217;6;223 +72003;Allonnes;11098;108;11206 +72004;Amné;566;3;569 +72005;Ancinnes;949;21;970 +72007;Ardenay-sur-Mérize;486;5;491 +72008;Arnage;5311;121;5432 +72009;Arthezé;392;9;401 +72006;Arçonnay;1844;229;2073 +72010;Asnières-sur-Vègre;406;11;417 +72011;Assé-le-Boisne;913;17;930 +72012;Assé-le-Riboul;518;10;528 +72013;Aubigné-Racan;2120;28;2148 +72015;Les Aulneaux;117;0;117 +72016;Auvers-le-Hamon;1473;36;1509 +72017;Auvers-sous-Montfaucon;244;3;247 +72018;Avesnes-en-Saosnois;89;1;90 +72019;Avessé;375;11;386 +72020;Avezé;726;19;745 +72021;Avoise;612;7;619 +72022;Le Bailleul;1234;17;1251 +72023;Ballon-Saint Mars;2230;32;2262 +72024;La Bazoge;3641;59;3700 +72025;Bazouges Cré sur Loir;2048;57;2105 +72026;Beaufay;1491;15;1506 +72028;Beaumont-Pied-de-Bœuf;488;13;501 +72027;Beaumont-sur-Dême;331;8;339 +72029;Beaumont-sur-Sarthe;1960;26;1986 +72031;Beillé;528;3;531 +72032;Berfay;328;12;340 +72219;Bernay-Neuvy-en-Champagne;862;58;920 +72034;Bérus;447;12;459 +72035;Bessé-sur-Braye;2212;36;2248 +72036;Béthon;327;4;331 +72037;Blèves;105;1;106 +72038;Boëssé-le-Sec;632;13;645 +72039;Bonnétable;3856;59;3915 +72040;La Bosse;137;0;137 +72041;Bouër;333;2;335 +72042;Bouloire;2082;36;2118 +72043;Bourg-le-Roi;320;8;328 +72044;Bousse;443;5;448 +72045;Brains-sur-Gée;820;13;833 +72046;Le Breil-sur-Mérize;1542;27;1569 +72047;Brette-les-Pins;2153;115;2268 +72048;Briosne-lès-Sables;542;4;546 +72049;La Bruère-sur-Loir;244;2;246 +72050;Brûlon;1580;31;1611 +72051;Cérans-Foulletourte;3375;35;3410 +72052;Chahaignes;693;13;706 +72053;Challes;1221;14;1235 +72054;Champagné;3876;71;3947 +72056;Champfleur;1358;24;1382 +72057;Champrond;70;3;73 +72058;Changé;6519;194;6713 +72059;Chantenay-Villedieu;865;18;883 +72060;La Chapelle-aux-Choux;266;3;269 +72061;La Chapelle-d'Aligné;1694;25;1719 +72062;La Chapelle-du-Bois;868;25;893 +72064;La Chapelle-Huon;547;15;562 +72065;La Chapelle-Saint-Aubin;2360;67;2427 +72066;La Chapelle-Saint-Fray;441;7;448 +72067;La Chapelle-Saint-Rémy;976;15;991 +72068;La Chartre-sur-le-Loir;1425;17;1442 +72070;Chassillé;240;6;246 +72072;Château-l'Hermitage;254;2;256 +72073;Chaufour-Notre-Dame;1067;22;1089 +72074;Chemiré-en-Charnie;209;6;215 +72075;Chemiré-le-Gaudin;979;26;1005 +72076;Chenay;231;2;233 +72077;Chenu;429;6;435 +72078;Chérancé;360;3;363 +72079;Chérisay;309;3;312 +72080;Cherré-Au;2698;79;2777 +72083;Chevillé;411;5;416 +72084;Clermont-Créans;1264;35;1299 +72085;Cogners;188;2;190 +72086;Commerveil;137;2;139 +72087;Conflans-sur-Anille;512;15;527 +72088;Congé-sur-Orne;343;4;347 +72089;Conlie;1899;34;1933 +72090;Connerré;2902;58;2960 +72091;Contilly;139;2;141 +72093;Cormes;907;14;921 +72094;Coudrecieux;616;9;625 +72095;Coulaines;7423;125;7548 +72096;Coulans-sur-Gée;1650;81;1731 +72098;Coulongé;519;6;525 +72099;Courcebœufs;638;7;645 +72100;Courcelles-la-Forêt;410;5;415 +72101;Courcemont;679;15;694 +72102;Courcival;96;1;97 +72103;Courdemanche;609;9;618 +72104;Courgains;579;14;593 +72105;Courgenard;495;5;500 +72106;Courtillers;922;27;949 +72107;Crannes-en-Champagne;352;6;358 +72109;Crissé;587;5;592 +72110;Crosmières;1044;21;1065 +72111;Cures;485;15;500 +72112;Dangeul;473;1;474 +72113;Degré;784;12;796 +72114;Dehault;270;6;276 +72115;Dissay-sous-Courcillon;932;24;956 +72118;Dollon;1488;29;1517 +72119;Domfront-en-Champagne;1034;18;1052 +72120;Doucelles;250;3;253 +72121;Douillet;328;11;339 +72122;Duneau;1045;21;1066 +72123;Dureil;71;0;71 +72124;Écommoy;4677;71;4748 +72125;Écorpain;296;9;305 +72126;Épineu-le-Chevreuil;295;9;304 +72127;Étival-lès-le-Mans;1939;36;1975 +72129;Fatines;845;16;861 +72130;Fay;668;13;681 +72131;Fercé-sur-Sarthe;593;8;601 +72132;La Ferté-Bernard;8820;335;9155 +72133;Fillé;1494;24;1518 +72154;La Flèche;14956;1000;15956 +72134;Flée;539;14;553 +72135;La Fontaine-Saint-Martin;619;7;626 +72136;Fontenay-sur-Vègre;324;8;332 +72138;Fresnay-sur-Sarthe;2970;45;3015 +72139;Fyé;992;44;1036 +72141;Gesnes-le-Gandelin;963;22;985 +72143;Le Grand-Lucé;1923;27;1950 +72142;Grandchamp;156;8;164 +72144;Gréez-sur-Roc;332;4;336 +72145;Le Grez;397;10;407 +72146;Guécélard;3019;52;3071 +72147;La Guierche;1103;23;1126 +72148;Jauzé;84;1;85 +72149;Joué-en-Charnie;654;5;659 +72150;Joué-l'Abbé;1279;23;1302 +72151;Juigné-sur-Sarthe;1147;26;1173 +72152;Juillé;474;13;487 +72153;Jupilles;566;12;578 +72155;Laigné-en-Belin;2353;30;2383 +72156;Lamnay;957;23;980 +72157;Lavardin;735;9;744 +72158;Lavaré;856;11;867 +72160;Lavernat;599;7;606 +72161;Lhomme;902;14;916 +72163;Ligron;504;9;513 +72164;Livet-en-Saosnois;70;0;70 +72262;Loir en Vallée;2173;175;2348 +72165;Lombron;1909;23;1932 +72166;Longnes;325;10;335 +72167;Louailles;727;10;737 +72168;Loué;2135;40;2175 +72169;Louplande;1462;24;1486 +72170;Louvigny;176;7;183 +72171;Louzes;101;1;102 +72172;Le Luart;1439;12;1451 +72174;Lucé-sous-Ballon;105;2;107 +72173;Luceau;1226;27;1253 +72175;Luché-Pringé;1562;15;1577 +72176;Le Lude;4255;73;4328 +72177;Maigné;353;4;357 +72178;Maisoncelles;193;1;194 +72179;Malicorne-sur-Sarthe;1905;33;1938 +72180;Mamers;5299;161;5460 +72181;Le Mans;142946;2830;145776 +72182;Mansigné;1553;31;1584 +72184;Mareil-en-Champagne;382;6;388 +72185;Mareil-sur-Loir;663;10;673 +72186;Maresché;886;10;896 +72187;Marigné-Laillé;1636;23;1659 +72189;Marolles-les-Braults;2205;32;2237 +72190;Marolles-lès-Saint-Calais;276;4;280 +72188;Marollette;150;2;152 +72183;Marçon;1060;18;1078 +72191;Mayet;3138;37;3175 +72192;Les Mées;100;2;102 +72193;Melleray;432;7;439 +72194;Meurcé;269;3;272 +72195;Mézeray;1917;24;1941 +72197;Mézières-sous-Lavardin;695;5;700 +72196;Mézières-sur-Ponthouin;706;7;713 +72198;La Milesse;2640;43;2683 +72199;Moitron-sur-Sarthe;262;1;263 +72200;Moncé-en-Belin;3670;50;3720 +72201;Moncé-en-Saosnois;259;3;262 +72202;Monhoudou;207;8;215 +72211;Mont-Saint-Jean;640;17;657 +72204;Montaillé;543;12;555 +72205;Montbizot;1803;27;1830 +72241;Montfort-le-Gesnois;2973;48;3021 +72208;Montmirail;389;9;398 +72209;Montreuil-le-Chétif;302;0;302 +72210;Montreuil-le-Henri;308;4;312 +72071;Montval-sur-Loir;6124;249;6373 +72212;Moulins-le-Carbonnel;697;12;709 +72213;Mulsanne;5238;63;5301 +72214;Nauvay;11;2;13 +72215;Neufchâtel-en-Saosnois;1026;11;1037 +72216;Neuvillalais;590;12;602 +72217;Neuville-sur-Sarthe;2421;48;2469 +72218;Neuvillette-en-Charnie;293;3;296 +72220;Nogent-le-Bernard;914;37;951 +72221;Nogent-sur-Loir;380;3;383 +72232;Notre-Dame-du-Pé;634;10;644 +72222;Nouans;286;5;291 +72223;Noyen-sur-Sarthe;2611;33;2644 +72224;Nuillé-le-Jalais;542;6;548 +72225;Oisseau-le-Petit;662;13;675 +72226;Oizé;1323;17;1340 +72227;Panon;44;0;44 +72228;Parcé-sur-Sarthe;2100;51;2151 +72229;Parennes;508;7;515 +72231;Parigné-l'Évêque;5086;78;5164 +72230;Parigné-le-Pôlin;1082;55;1137 +72233;Peray;62;0;62 +72234;Pezé-le-Robert;370;11;381 +72235;Piacé;383;7;390 +72236;Pincé;193;8;201 +72237;Pirmil;513;8;521 +72238;Pizieux;74;0;74 +72239;Poillé-sur-Vègre;617;20;637 +72243;Pontvallain;1675;25;1700 +72244;Précigné;2973;64;3037 +72245;Préval;687;15;702 +72246;Prévelles;218;2;220 +72248;Pruillé-l'Éguillé;824;24;848 +72247;Pruillé-le-Chétif;1359;37;1396 +72249;La Quinte;777;13;790 +72250;Rahay;158;9;167 +72251;René;379;5;384 +72252;Requeil;1184;11;1195 +72253;Roézé-sur-Sarthe;2626;69;2695 +72254;Rouessé-Fontaine;276;5;281 +72255;Rouessé-Vassé;813;17;830 +72256;Rouez;771;8;779 +72257;Rouillon;2259;315;2574 +72259;Rouperroux-le-Coquet;290;6;296 +72260;Ruaudin;3418;67;3485 +72261;Ruillé-en-Champagne;322;12;334 +72264;Sablé-sur-Sarthe;12220;499;12719 +72265;Saint-Aignan;251;1;252 +72266;Saint-Aubin-de-Locquenay;690;16;706 +72267;Saint-Aubin-des-Coudrais;926;21;947 +72268;Saint-Biez-en-Belin;714;11;725 +72269;Saint-Calais;3236;195;3431 +72270;Saint-Calez-en-Saosnois;187;1;188 +72271;Saint-Célerin;905;15;920 +72273;Saint-Christophe-du-Jambet;233;4;237 +72274;Saint-Christophe-en-Champagne;209;6;215 +72275;Saint-Corneille;1431;14;1445 +72276;Saint-Cosme-en-Vairais;1970;51;2021 +72278;Saint-Denis-d'Orques;799;11;810 +72277;Saint-Denis-des-Coudrais;114;1;115 +72279;Saint-Georges-de-la-Couée;159;3;162 +72280;Saint-Georges-du-Bois;2121;36;2157 +72281;Saint-Georges-du-Rosay;435;3;438 +72282;Saint-Georges-le-Gaultier;531;5;536 +72283;Saint-Germain-d'Arcé;335;5;340 +72286;Saint-Gervais-de-Vic;395;7;402 +72287;Saint-Gervais-en-Belin;2076;44;2120 +72290;Saint-Jean-d'Assé;1759;15;1774 +72291;Saint-Jean-de-la-Motte;968;22;990 +72292;Saint-Jean-des-Échelles;253;8;261 +72293;Saint-Jean-du-Bois;626;8;634 +72294;Saint-Léonard-des-Bois;472;13;485 +72295;Saint-Longis;503;8;511 +72296;Saint-Maixent;740;19;759 +72297;Saint-Marceau;560;6;566 +72299;Saint-Mars-d'Outillé;2418;36;2454 +72298;Saint-Mars-de-Locquenay;570;10;580 +72300;Saint-Mars-la-Brière;2688;29;2717 +72302;Saint-Martin-des-Monts;179;4;183 +72303;Saint-Michel-de-Chavaignes;737;11;748 +72305;Saint-Ouen-de-Mimbré;1029;11;1040 +72306;Saint-Ouen-en-Belin;1303;23;1326 +72307;Saint-Ouen-en-Champagne;244;2;246 +72308;Saint-Paterne - Le Chevain;2120;209;2329 +72309;Saint-Paul-le-Gaultier;288;8;296 +72310;Saint-Pavace;1925;58;1983 +72311;Saint-Pierre-de-Chevillé;364;2;366 +72312;Saint-Pierre-des-Bois;235;3;238 +72313;Saint-Pierre-des-Ormes;226;6;232 +72314;Saint-Pierre-du-Lorouër;377;9;386 +72315;Saint-Rémy-de-Sillé;831;14;845 +72316;Saint-Rémy-des-Monts;686;20;706 +72317;Saint-Rémy-du-Val;512;17;529 +72320;Saint-Saturnin;2529;82;2611 +72321;Saint-Symphorien;562;12;574 +72322;Saint-Ulphace;225;4;229 +72323;Saint-Victeur;456;3;459 +72324;Saint-Vincent-des-Prés;513;3;516 +72325;Saint-Vincent-du-Lorouër;855;17;872 +72272;Sainte-Cérotte;316;6;322 +72289;Sainte-Jamme-sur-Sarthe;2051;32;2083 +72319;Sainte-Sabine-sur-Longève;763;18;781 +72326;Saosnes;211;5;216 +72327;Sarcé;299;4;303 +72328;Sargé-lès-le-Mans;3614;135;3749 +72329;Savigné-l'Évêque;3998;83;4081 +72330;Savigné-sous-le-Lude;429;13;442 +72331;Sceaux-sur-Huisne;570;11;581 +72332;Ségrie;605;7;612 +72333;Semur-en-Vallon;447;9;456 +72334;Sillé-le-Guillaume;2305;86;2391 +72335;Sillé-le-Philippe;1078;14;1092 +72336;Solesmes;1198;38;1236 +72337;Sougé-le-Ganelon;901;18;919 +72338;Souillé;690;9;699 +72339;Souligné-Flacé;686;8;694 +72340;Souligné-sous-Ballon;1202;21;1223 +72341;Soulitré;631;12;643 +72342;Souvigné-sur-Même;174;7;181 +72343;Souvigné-sur-Sarthe;629;12;641 +72344;Spay;2890;48;2938 +72345;Surfonds;340;6;346 +72346;La Suze-sur-Sarthe;4463;56;4519 +72347;Tassé;314;5;319 +72348;Tassillé;134;1;135 +72349;Teillé;480;2;482 +72350;Teloché;3056;80;3136 +72351;Tennie;1057;20;1077 +72352;Terrehault;135;0;135 +72353;Théligny;213;5;218 +72354;Thoigné;164;4;168 +72355;Thoiré-sous-Contensor;92;0;92 +72356;Thoiré-sur-Dinan;439;5;444 +72357;Thorée-les-Pins;724;11;735 +72358;Thorigné-sur-Dué;1607;35;1642 +72359;Torcé-en-Vallée;1409;11;1420 +72360;Trangé;1415;30;1445 +72361;Tresson;466;8;474 +72362;Le Tronchet;163;1;164 +72363;Tuffé Val de la Chéronne;1650;40;1690 +72364;Vaas;1510;20;1530 +72128;Val d'Étangson;528;5;533 +72366;Valennes;318;4;322 +72367;Vallon-sur-Gée;805;11;816 +72368;Vancé;324;6;330 +72369;Verneil-le-Chétif;613;108;721 +72370;Vernie;333;7;340 +72372;Vezot;76;1;77 +72373;Vibraye;2553;56;2609 +72374;Villaines-la-Carelle;152;5;157 +72375;Villaines-la-Gonais;558;16;574 +72376;Villaines-sous-Lucé;711;21;732 +72377;Villaines-sous-Malicorne;1025;12;1037 +72137;Villeneuve-en-Perseigne;2196;42;2238 +72378;Vion;1448;33;1481 +72379;Viré-en-Champagne;200;6;206 +72380;Vivoin;948;22;970 +72381;Voivres-lès-le-Mans;1377;11;1388 +72382;Volnay;919;11;930 +72383;Vouvray-sur-Huisne;128;4;132 +72386;Yvré-l'Évêque;4228;133;4361 +72385;Yvré-le-Pôlin;1768;24;1792 +73001;Aiguebelette-le-Lac;235;9;244 +73004;Aillon-le-Jeune;434;16;450 +73005;Aillon-le-Vieux;179;4;183 +73006;Aime-la-Plagne;4443;111;4554 +73007;Aiton;1667;22;1689 +73008;Aix-les-Bains;29794;579;30373 +73011;Albertville;18899;554;19453 +73012;Albiez-le-Jeune;146;2;148 +73013;Albiez-Montrond;376;11;387 +73014;Allondaz;275;2;277 +73015;Les Allues;1841;43;1884 +73017;Apremont;1013;21;1034 +73018;Arbin;777;21;798 +73019;Argentine;954;23;977 +73020;Arith;442;11;453 +73021;Arvillard;854;15;869 +73022;Attignat-Oncin;538;15;553 +73023;Aussois;679;22;701 +73024;Les Avanchers-Valmorel;784;22;806 +73025;Avressieux;522;11;533 +73026;Avrieux;388;14;402 +73027;Ayn;376;5;381 +73028;La Balme;320;3;323 +73029;Barberaz;4717;126;4843 +73030;Barby;3414;39;3453 +73031;Bassens;4466;121;4587 +73032;La Bâthie;2194;42;2236 +73033;La Bauche;505;5;510 +73034;Beaufort;2040;91;2131 +73036;Bellecombe-en-Bauges;668;18;686 +73257;Les Belleville;3494;117;3611 +73039;Belmont-Tramonet;561;13;574 +73040;Bessans;353;8;361 +73041;Betton-Bettonet;313;8;321 +73042;Billième;269;6;275 +73043;La Biolle;2578;32;2610 +73047;Bonneval-sur-Arc;261;8;269 +73048;Bonvillard;359;9;368 +73049;Bonvillaret;143;0;143 +73050;Bourdeau;555;20;575 +73054;Bourg-Saint-Maurice;7302;400;7702 +73051;Le Bourget-du-Lac;4866;98;4964 +73052;Bourget-en-Huile;147;6;153 +73053;Bourgneuf;682;10;692 +73055;Bozel;1841;57;1898 +73057;Brides-les-Bains;506;12;518 +73058;La Bridoire;1272;19;1291 +73059;Brison-Saint-Innocent;2131;71;2202 +73061;Césarches;427;15;442 +73063;Cevins;743;15;758 +73064;Challes-les-Eaux;5590;274;5864 +73065;Chambéry;58919;1562;60481 +73067;La Chambre;1164;23;1187 +73068;Chamousset;587;21;608 +73069;Chamoux-sur-Gelon;940;18;958 +73072;Champ-Laurent;36;2;38 +73070;Champagneux;688;8;696 +73071;Champagny-en-Vanoise;579;22;601 +73073;Chanaz;512;11;523 +73074;La Chapelle;331;4;335 +73075;La Chapelle-Blanche;561;15;576 +73076;La Chapelle-du-Mont-du-Chat;257;4;261 +73078;La Chapelle-Saint-Martin;148;6;154 +73077;Les Chapelles;561;9;570 +73079;Châteauneuf;894;16;910 +73081;Le Châtelard;670;44;714 +73082;La Chavanne;685;34;719 +73083;Les Chavannes-en-Maurienne;246;3;249 +73084;Chignin;862;28;890 +73085;Chindrieux;1361;21;1382 +73086;Cléry;404;12;416 +73087;Cognin;6204;177;6381 +73088;Cohennoz;161;8;169 +73089;Coise-Saint-Jean-Pied-Gauthier;1243;21;1264 +73090;La Compôte;257;6;263 +73091;Conjux;201;1;202 +73092;Corbel;157;4;161 +73227;Courchevel;2361;59;2420 +73094;Crest-Voland;341;14;355 +73095;La Croix-de-la-Rochette;365;8;373 +73096;Cruet;1038;19;1057 +73097;Curienne;682;21;703 +73098;Les Déserts;795;22;817 +73099;Détrier;427;4;431 +73100;Domessin;1855;41;1896 +73101;Doucy-en-Bauges;95;3;98 +73103;Drumettaz-Clarafond;2807;79;2886 +73104;Dullin;444;5;449 +73105;Les Échelles;1223;16;1239 +73106;École;291;6;297 +73010;Entrelacs;6268;131;6399 +73107;Entremont-le-Vieux;649;8;657 +73109;Épierre;759;10;769 +73110;Esserts-Blay;809;14;823 +73113;Feissons-sur-Salins;182;3;185 +73114;Flumet;810;29;839 +73116;Fontcouverte-la-Toussuire;510;14;524 +73117;Fourneaux;676;9;685 +73119;Freney;103;3;106 +73120;Fréterive;576;17;593 +73121;Frontenex;1898;41;1939 +73122;Gerbaix;401;15;416 +73123;La Giettaz;403;16;419 +73124;Gilly-sur-Isère;3013;76;3089 +73003;Grand-Aigueblanche;3850;112;3962 +73128;Grésy-sur-Aix;4545;101;4646 +73129;Grésy-sur-Isère;1242;31;1273 +73130;Grignon;2119;38;2157 +73131;Hautecour;307;13;320 +73132;Hauteluce;757;20;777 +73133;Hauteville;352;8;360 +73137;Jacob-Bellecombette;3984;77;4061 +73138;Jarrier;503;13;516 +73139;Jarsy;267;12;279 +73140;Jongieux;293;8;301 +73141;Laissaud;671;14;685 +73142;Landry;825;20;845 +73187;La Léchère;2586;55;2641 +73145;Lépin-le-Lac;454;6;460 +73146;Lescheraines;764;15;779 +73147;Loisieux;205;0;205 +73149;Lucey;318;11;329 +73152;Marcieux;190;5;195 +73153;Marthod;1367;31;1398 +73154;Mercury;3088;86;3174 +73155;Méry;1803;38;1841 +73156;Meyrieux-Trouet;311;6;317 +73157;Modane;3097;138;3235 +73159;Les Mollettes;816;12;828 +73160;Montagnole;887;22;909 +73161;Montagny;661;26;687 +73162;Montailleur;679;23;702 +73164;Montcel;999;60;1059 +73166;Montendry;58;2;60 +73168;Montgilbert;123;1;124 +73170;Monthion;550;11;561 +73171;Montmélian;4123;77;4200 +73173;Montricher-Albanne;471;10;481 +73175;Montsapey;63;0;63 +73176;Montvalezan;686;21;707 +73177;Montvernier;230;9;239 +73178;La Motte-en-Bauges;498;11;509 +73179;La Motte-Servolex;11826;564;12390 +73180;Motz;437;6;443 +73181;Moûtiers;3501;457;3958 +73182;Mouxy;2234;50;2284 +73183;Myans;1236;33;1269 +73184;Nances;490;10;500 +73186;Notre-Dame-de-Bellecombe;479;14;493 +73188;Notre-Dame-des-Millières;1031;23;1054 +73189;Notre-Dame-du-Cruet;226;3;229 +73190;Notre-Dame-du-Pré;249;5;254 +73191;Novalaise;2071;60;2131 +73192;Le Noyer;214;5;219 +73193;Ontex;105;3;108 +73194;Orelle;349;12;361 +73196;Pallud;780;19;799 +73197;Peisey-Nancroix;642;25;667 +73150;La Plagne Tarentaise;3638;96;3734 +73200;Planaise;545;7;552 +73201;Planay;428;12;440 +73202;Plancherine;439;10;449 +73204;Le Pont-de-Beauvoisin;2074;32;2106 +73205;Le Pontet;122;5;127 +73151;Porte-de-Savoie;3680;85;3765 +73206;Pralognan-la-Vanoise;724;23;747 +73207;Presle;418;12;430 +73208;Pugny-Chatenod;951;40;991 +73210;Puygros;385;5;390 +73211;Queige;805;26;831 +73213;La Ravoire;8457;588;9045 +73214;Rochefort;232;10;242 +73216;Rognaix;478;8;486 +73217;Rotherens;367;3;370 +73218;Ruffieux;837;16;853 +73220;Saint-Alban-d'Hurtières;356;10;366 +73219;Saint-Alban-de-Montbel;643;16;659 +73221;Saint-Alban-des-Villards;100;3;103 +73222;Saint-Alban-Leysse;6007;206;6213 +73223;Saint-André;457;6;463 +73224;Saint-Avre;868;10;878 +73225;Saint-Baldoph;2809;93;2902 +73226;Saint-Béron;1671;21;1692 +73228;Saint-Cassin;838;22;860 +73229;Saint-Christophe;531;13;544 +73230;Saint-Colomban-des-Villards;135;1;136 +73231;Saint-Étienne-de-Cuines;1195;23;1218 +73233;Saint-Franc;167;16;183 +73234;Saint-François-de-Sales;150;4;154 +73235;Saint François Longchamp;517;6;523 +73236;Saint-Genix-les-Villages;2944;65;3009 +73237;Saint-Georges-d'Hurtières;339;3;342 +73242;Saint-Jean-d'Arves;266;9;275 +73243;Saint-Jean-d'Arvey;1697;56;1753 +73245;Saint-Jean-de-Chevelu;813;17;830 +73246;Saint-Jean-de-Couz;291;8;299 +73247;Saint-Jean-de-la-Porte;937;76;1013 +73248;Saint-Jean-de-Maurienne;7746;400;8146 +73249;Saint-Jeoire-Prieuré;1704;41;1745 +73250;Saint-Julien-Mont-Denis;1618;45;1663 +73252;Saint-Léger;224;5;229 +73253;Saint-Marcel;607;8;615 +73256;Saint-Martin-d'Arc;361;5;366 +73258;Saint-Martin-de-la-Porte;679;18;697 +73259;Saint-Martin-sur-la-Chambre;552;14;566 +73261;Saint-Michel-de-Maurienne;2461;270;2731 +73262;Saint-Nicolas-la-Chapelle;454;30;484 +73263;Saint-Offenge;1104;21;1125 +73265;Saint-Ours;677;18;695 +73267;Saint-Pancrace;290;11;301 +73269;Saint-Paul;686;12;698 +73268;Saint-Paul-sur-Isère;524;66;590 +73270;Saint-Pierre-d'Albigny;3943;95;4038 +73271;Saint-Pierre-d'Alvey;292;9;301 +73274;Saint-Pierre-d'Entremont;457;15;472 +73272;Saint-Pierre-de-Belleville;171;4;175 +73273;Saint-Pierre-de-Curtille;491;5;496 +73275;Saint-Pierre-de-Genebroz;334;9;343 +73276;Saint-Pierre-de-Soucy;437;20;457 +73278;Saint-Rémy-de-Maurienne;1253;22;1275 +73280;Saint-Sorlin-d'Arves;331;8;339 +73281;Saint-Sulpice;760;19;779 +73282;Saint-Thibaud-de-Couz;1060;20;1080 +73283;Saint-Vital;694;13;707 +73232;Sainte-Foy-Tarentaise;768;15;783 +73240;Sainte-Hélène-du-Lac;779;20;799 +73241;Sainte-Hélène-sur-Isère;1183;20;1203 +73254;Sainte-Marie-d'Alvey;117;2;119 +73255;Sainte-Marie-de-Cuines;803;20;823 +73277;Sainte-Reine;159;6;165 +73284;Salins-Fontaine;1011;19;1030 +73285;Séez;2355;74;2429 +73286;Serrières-en-Chautagne;1208;22;1230 +73288;Sonnaz;1857;36;1893 +73289;La Table;448;8;456 +73292;Thénésol;310;7;317 +73293;Thoiry;457;11;468 +73294;La Thuile;330;7;337 +73296;Tignes;2196;45;2241 +73135;La Tour-en-Maurienne;1074;30;1104 +73297;Tournon;611;20;631 +73298;Tours-en-Savoie;959;11;970 +73299;Traize;318;6;324 +73300;Tresserve;3014;105;3119 +73301;Trévignin;776;20;796 +73302;La Trinité;345;2;347 +73303;Ugine;7039;293;7332 +73290;Val-Cenis;2088;38;2126 +73212;Val-d'Arc;2008;33;2041 +73304;Val-d'Isère;1555;27;1582 +73215;Valgelon-La Rochette;4111;104;4215 +73306;Valloire;1083;27;1110 +73307;Valmeinier;515;3;518 +73308;Venthon;621;20;641 +73309;Verel-de-Montbel;303;6;309 +73310;Verel-Pragondran;476;12;488 +73311;Le Verneil;102;1;103 +73312;Verrens-Arvey;900;30;930 +73313;Verthemex;229;1;230 +73314;Villard-d'Héry;268;8;276 +73315;Villard-Léger;473;8;481 +73316;Villard-Sallet;290;5;295 +73317;Villard-sur-Doron;712;28;740 +73318;Villarembert;247;9;256 +73320;Villargondran;862;25;887 +73322;Villarodin-Bourget;529;11;540 +73323;Villaroger;366;15;381 +73324;Villaroux;203;9;212 +73326;Vimines;2028;38;2066 +73327;Vions;403;6;409 +73328;Viviers-du-Lac;2235;44;2279 +73329;Voglans;1897;36;1933 +73330;Yenne;2978;34;3012 +74001;Abondance;1439;116;1555 +74002;Alby-sur-Chéran;2579;54;2633 +74003;Alex;1072;33;1105 +74004;Allèves;411;8;419 +74005;Allinges;4459;118;4577 +74006;Allonzier-la-Caille;2071;28;2099 +74007;Amancy;2665;54;2719 +74008;Ambilly;6385;85;6470 +74009;Andilly;900;19;919 +74010;Annecy;126924;3251;130175 +74012;Annemasse;35712;393;36105 +74013;Anthy-sur-Léman;2171;89;2260 +74014;Arâches-la-Frasse;1910;46;1956 +74015;Arbusigny;1115;23;1138 +74016;Archamps;2556;36;2592 +74018;Arenthon;1741;44;1785 +74019;Argonay;3025;250;3275 +74020;Armoy;1295;54;1349 +74021;Arthaz-Pont-Notre-Dame;1577;30;1607 +74024;Ayse;2145;59;2204 +74025;Ballaison;1470;20;1490 +74026;La Balme-de-Sillingy;5037;162;5199 +74027;La Balme-de-Thuy;462;5;467 +74029;Bassy;413;14;427 +74030;La Baume;309;2;311 +74031;Beaumont;2838;67;2905 +74032;Bellevaux;1294;40;1334 +74033;Bernex;1352;28;1380 +74034;Le Biot;572;14;586 +74035;Bloye;609;25;634 +74036;Bluffy;391;12;403 +74037;Boëge;1765;57;1822 +74038;Bogève;1111;26;1137 +74040;Bonne;3218;146;3364 +74041;Bonnevaux;277;7;284 +74042;Bonneville;12608;402;13010 +74043;Bons-en-Chablais;5631;105;5736 +74044;Bossey;1018;14;1032 +74045;Le Bouchet-Mont-Charvin;242;3;245 +74046;Boussy;505;12;517 +74048;Brenthonne;1037;20;1057 +74049;Brizon;485;2;487 +74050;Burdignin;628;15;643 +74051;Cercier;678;11;689 +74052;Cernex;1010;16;1026 +74053;Cervens;1205;21;1226 +74054;Chainaz-les-Frasses;728;27;755 +74055;Challonges;536;13;549 +74056;Chamonix-Mont-Blanc;8611;385;8996 +74057;Champanges;1015;28;1043 +74061;Chapeiry;812;31;843 +74058;La Chapelle-d'Abondance;911;17;928 +74059;La Chapelle-Rambaud;256;6;262 +74060;La Chapelle-Saint-Maurice;119;0;119 +74062;Charvonnex;1356;25;1381 +74063;Châtel;1246;41;1287 +74064;Châtillon-sur-Cluses;1245;46;1291 +74065;Chaumont;492;14;506 +74066;Chavannaz;236;2;238 +74067;Chavanod;2643;167;2810 +74068;Chêne-en-Semine;496;8;504 +74069;Chênex;828;9;837 +74070;Chens-sur-Léman;2776;34;2810 +74071;Chessenaz;214;7;221 +74072;Chevaline;203;7;210 +74073;Chevenoz;607;11;618 +74074;Chevrier;545;6;551 +74075;Chilly;1382;21;1403 +74076;Choisy;1604;29;1633 +74077;Clarafond-Arcine;1033;26;1059 +74079;Les Clefs;659;6;665 +74078;Clermont;409;6;415 +74080;La Clusaz;1734;55;1789 +74081;Cluses;17059;395;17454 +74082;Collonges-sous-Salève;3979;117;4096 +74083;Combloux;2106;113;2219 +74086;Contamine-Sarzin;704;13;717 +74087;Contamine-sur-Arve;2083;149;2232 +74085;Les Contamines-Montjoie;1167;49;1216 +74088;Copponex;1154;22;1176 +74089;Cordon;973;26;999 +74090;Cornier;1333;19;1352 +74091;La Côte-d'Arbroz;339;2;341 +74094;Cranves-Sales;6793;167;6960 +74095;Crempigny-Bonneguête;316;2;318 +74096;Cruseilles;4431;291;4722 +74097;Cusy;1850;55;1905 +74098;Cuvat;1391;48;1439 +74099;Demi-Quartier;909;33;942 +74100;Desingy;806;16;822 +74101;Dingy-en-Vuache;682;21;703 +74102;Dingy-Saint-Clair;1433;41;1474 +74103;Domancy;2113;73;2186 +74104;Doussard;3592;87;3679 +74105;Douvaine;5948;71;6019 +74106;Draillant;859;30;889 +74107;Droisy;159;5;164 +74108;Duingt;972;20;992 +74109;Éloise;864;18;882 +74111;Entrevernes;214;3;217 +74112;Epagny Metz-Tessy;7824;189;8013 +74114;Essert-Romand;513;6;519 +74116;Etaux;1979;68;2047 +74117;Étercy;813;20;833 +74118;Étrembières;2453;25;2478 +74119;Évian-les-Bains;9098;257;9355 +74121;Excenevex;1104;16;1120 +74122;Faucigny;628;16;644 +74123;Faverges-Seythenex;7606;250;7856 +74124;Feigères;1682;33;1715 +74126;Fessy;923;26;949 +74127;Féternes;1418;43;1461 +74282;Fillière;9255;233;9488 +74128;Fillinges;3413;86;3499 +74129;La Forclaz;233;4;237 +74130;Franclens;533;43;576 +74131;Frangy;2119;40;2159 +74133;Gaillard;10619;112;10731 +74134;Les Gets;1239;27;1266 +74135;Giez;541;8;549 +74212;Glières-Val-de-Borne;1798;33;1831 +74136;Le Grand-Bornand;2118;49;2167 +74137;Groisy;3629;140;3769 +74138;Gruffy;1567;64;1631 +74139;Habère-Lullin;1010;30;1040 +74140;Habère-Poche;1465;25;1490 +74141;Hauteville-sur-Fier;958;24;982 +74142;Héry-sur-Alby;975;31;1006 +74143;Les Houches;2943;77;3020 +74144;Jonzier-Épagny;798;20;818 +74145;Juvigny;639;14;653 +74146;Larringes;1424;43;1467 +74147;Lathuile;1016;25;1041 +74148;Leschaux;274;7;281 +74150;Loisin;1551;28;1579 +74151;Lornay;560;10;570 +74152;Lovagny;1286;43;1329 +74153;Lucinges;1625;65;1690 +74154;Lugrin;2435;50;2485 +74155;Lullin;799;21;820 +74156;Lully;701;13;714 +74157;Lyaud;1729;35;1764 +74158;Machilly;1086;20;1106 +74159;Magland;3279;68;3347 +74160;Manigod;1004;22;1026 +74162;Marcellaz;1018;18;1036 +74161;Marcellaz-Albanais;1906;41;1947 +74163;Margencel;2145;77;2222 +74164;Marignier;6445;172;6617 +74165;Marigny-Saint-Marcel;685;9;694 +74166;Marin;1789;51;1840 +74168;Marlioz;1012;12;1024 +74169;Marnaz;5521;116;5637 +74170;Massingy;875;19;894 +74171;Massongy;1494;33;1527 +74172;Maxilly-sur-Léman;1414;34;1448 +74173;Megève;3036;128;3164 +74174;Mégevette;581;24;605 +74175;Meillerie;317;5;322 +74176;Menthon-Saint-Bernard;1889;70;1959 +74177;Menthonnex-en-Bornes;1076;19;1095 +74178;Menthonnex-sous-Clermont;715;13;728 +74179;Mésigny;753;17;770 +74180;Messery;2134;47;2181 +74183;Mieussy;2340;59;2399 +74184;Minzier;1023;19;1042 +74185;Monnetier-Mornex;2295;34;2329 +74189;Mont-Saxonnex;1668;50;1718 +74186;Montagny-les-Lanches;705;20;725 +74188;Montriond;905;24;929 +74190;Morillon;662;14;676 +74191;Morzine;2785;75;2860 +74192;Moye;1018;38;1056 +74193;La Muraz;1063;11;1074 +74194;Mûres;784;22;806 +74195;Musièges;416;7;423 +74196;Nancy-sur-Cluses;460;15;475 +74197;Nangy;1618;35;1653 +74198;Nâves-Parmelan;969;38;1007 +74199;Nernier;380;7;387 +74200;Neuvecelle;3048;92;3140 +74201;Neydens;1915;44;1959 +74202;Nonglard;654;7;661 +74203;Novel;48;0;48 +74205;Onnion;1293;29;1322 +74206;Orcier;981;17;998 +74208;Passy;10902;417;11319 +74209;Peillonnex;1400;42;1442 +74210;Perrignier;1845;37;1882 +74211;Pers-Jussy;3052;90;3142 +74213;Poisy;8124;357;8481 +74215;Praz-sur-Arly;1228;36;1264 +74216;Présilly;960;19;979 +74218;Publier;7148;208;7356 +74219;Quintal;1238;51;1289 +74220;Reignier-Ésery;7994;209;8203 +74221;Le Reposoir;522;22;544 +74222;Reyvroz;510;8;518 +74223;La Rivière-Enverse;468;7;475 +74224;La Roche-sur-Foron;11339;344;11683 +74225;Rumilly;15379;362;15741 +74226;Saint-André-de-Boëge;542;16;558 +74228;Saint-Blaise;350;12;362 +74229;Saint-Cergues;3613;72;3685 +74231;Saint-Eusèbe;547;13;560 +74232;Saint-Eustache;513;26;539 +74233;Saint-Félix;2421;29;2450 +74234;Saint-Ferréol;867;22;889 +74235;Saint-Germain-sur-Rhône;526;13;539 +74236;Saint-Gervais-les-Bains;5573;129;5702 +74237;Saint-Gingolph;840;4;844 +74238;Saint-Jean-d'Aulps;1440;24;1464 +74239;Saint-Jean-de-Sixt;1453;32;1485 +74240;Saint-Jean-de-Tholome;990;29;1019 +74241;Saint-Jeoire;3282;115;3397 +74242;Saint-Jorioz;5738;189;5927 +74243;Saint-Julien-en-Genevois;14258;218;14476 +74244;Saint-Laurent;836;22;858 +74249;Saint-Paul-en-Chablais;2412;78;2490 +74250;Saint-Pierre-en-Faucigny;6573;131;6704 +74252;Saint-Sigismond;589;32;621 +74253;Saint-Sixt;1021;32;1053 +74254;Saint-Sylvestre;607;16;623 +74255;Sales;1978;49;2027 +74256;Sallanches;16088;515;16603 +74257;Sallenôves;703;20;723 +74258;Samoëns;2458;61;2519 +74259;Le Sappey;409;10;419 +74260;Savigny;893;20;913 +74261;Saxel;484;8;492 +74262;Scientrier;1159;22;1181 +74263;Sciez;6033;135;6168 +74264;Scionzier;8683;111;8794 +74265;Serraval;700;72;772 +74266;Servoz;999;34;1033 +74267;Sevrier;4161;181;4342 +74269;Seyssel;2325;74;2399 +74271;Seytroux;513;13;526 +74272;Sillingy;5245;126;5371 +74273;Sixt-Fer-à-Cheval;769;18;787 +74275;Talloires-Montmin;1996;64;2060 +74276;Taninges;3443;74;3517 +74279;Thollon-les-Mémises;793;24;817 +74280;Thônes;6576;321;6897 +74281;Thonon-les-Bains;34756;1107;35863 +74283;Thusy;1101;20;1121 +74278;Thyez;6198;148;6346 +74284;La Tour;1275;24;1299 +74285;Usinens;402;10;412 +74286;Vacheresse;855;17;872 +74287;Vailly;910;20;930 +74167;Val de Chaise;1363;25;1388 +74288;Valleiry;4697;60;4757 +74289;Vallières-sur-Fier;2503;58;2561 +74290;Vallorcine;400;13;413 +74291;Vanzy;329;8;337 +74292;Vaulx;978;26;1004 +74293;Veigy-Foncenex;3685;41;3726 +74294;Verchaix;752;21;773 +74295;La Vernaz;337;5;342 +74296;Vers;893;19;912 +74297;Versonnex;612;24;636 +74298;Vétraz-Monthoux;8900;267;9167 +74299;Veyrier-du-Lac;2251;81;2332 +74301;Villard;812;17;829 +74302;Les Villards-sur-Thônes;1068;37;1105 +74303;Villaz;3427;124;3551 +74304;Ville-en-Sallaz;905;10;915 +74305;Ville-la-Grand;8802;117;8919 +74306;Villy-le-Bouveret;597;17;614 +74307;Villy-le-Pelloux;938;15;953 +74308;Vinzier;821;22;843 +74309;Viry;5182;82;5264 +74311;Viuz-en-Sallaz;4374;81;4455 +74310;Viuz-la-Chiésaz;1324;32;1356 +74312;Vougy;1561;28;1589 +74313;Vovray-en-Bornes;524;10;534 +74314;Vulbens;1588;68;1656 +74315;Yvoire;993;18;1011 +75101;Paris 1er Arrondissement;16266;129;16395 +75102;Paris 2e Arrondissement;20900;142;21042 +75103;Paris 3e Arrondissement;34115;274;34389 +75104;Paris 4e Arrondissement;28088;282;28370 +75105;Paris 5e Arrondissement;58850;781;59631 +75106;Paris 6e Arrondissement;41100;876;41976 +75107;Paris 7e Arrondissement;51367;826;52193 +75108;Paris 8e Arrondissement;36808;560;37368 +75109;Paris 9e Arrondissement;59555;516;60071 +75110;Paris 10e Arrondissement;90372;464;90836 +75111;Paris 11e Arrondissement;146643;827;147470 +75112;Paris 12e Arrondissement;140296;991;141287 +75113;Paris 13e Arrondissement;182099;1300;183399 +75114;Paris 14e Arrondissement;135964;977;136941 +75115;Paris 15e Arrondissement;233392;1786;235178 +75116;Paris 16e Arrondissement;166361;2193;168554 +75117;Paris 17e Arrondissement;167288;1449;168737 +75118;Paris 18e Arrondissement;195233;898;196131 +75119;Paris 19e Arrondissement;187015;1051;188066 +75120;Paris 20e Arrondissement;195814;925;196739 +76001;Allouville-Bellefosse;1157;19;1176 +76002;Alvimare;615;9;624 +76004;Ambrumesnil;472;14;486 +76005;Amfreville-la-Mi-Voie;3273;29;3302 +76006;Amfreville-les-Champs;171;4;175 +76007;Anceaumeville;647;12;659 +76008;Ancourt;653;11;664 +76009;Ancourteville-sur-Héricourt;333;6;339 +76010;Ancretiéville-Saint-Victor;381;6;387 +76011;Ancretteville-sur-Mer;170;4;174 +76012;Angerville-Bailleul;191;3;194 +76014;Angerville-l'Orcher;1426;16;1442 +76013;Angerville-la-Martel;1060;29;1089 +76015;Angiens;516;11;527 +76017;Anglesqueville-l'Esneval;598;7;605 +76016;Anglesqueville-la-Bras-Long;117;2;119 +76020;Anneville-Ambourville;1190;22;1212 +76019;Anneville-sur-Scie;432;10;442 +76021;Annouville-Vilmesnil;477;7;484 +76022;Anquetierville;341;14;355 +76023;Anvéville;295;5;300 +76024;Ardouval;162;4;166 +76401;Arelaune-en-Seine;2576;46;2622 +76025;Argueil;341;8;349 +76026;Arques-la-Bataille;2583;53;2636 +76028;Aubéguimont;197;1;198 +76029;Aubermesnil-aux-Érables;203;4;207 +76030;Aubermesnil-Beaumais;468;4;472 +76032;Auberville-la-Manuel;130;1;131 +76033;Auberville-la-Renault;462;7;469 +76035;Aumale;2024;52;2076 +76036;Auppegard;716;19;735 +76038;Authieux-Ratiéville;405;3;408 +76039;Les Authieux-sur-le-Port-Saint-Ouen;1265;26;1291 +76040;Autigny;313;0;313 +76042;Auvilliers;101;0;101 +76043;Auzebosc;1123;338;1461 +76045;Auzouville-l'Esneval;358;8;366 +76046;Auzouville-sur-Ry;733;6;739 +76047;Auzouville-sur-Saâne;152;1;153 +76048;Avesnes-en-Bray;301;6;307 +76049;Avesnes-en-Val;279;6;285 +76050;Avremesnil;1016;18;1034 +76051;Bacqueville-en-Caux;1901;38;1939 +76052;Bailleul-Neuville;216;3;219 +76053;Baillolet;106;1;107 +76054;Bailly-en-Rivière;526;5;531 +76055;Baons-le-Comte;349;17;366 +76056;Bardouville;639;5;644 +76057;Barentin;11822;212;12034 +76058;Baromesnil;228;5;233 +76059;Bazinval;415;11;426 +76060;Beaubec-la-Rosière;498;13;511 +76062;Beaumont-le-Hareng;265;3;268 +76064;Beaurepaire;497;13;510 +76065;Beaussault;411;4;415 +76066;Beautot;147;4;151 +76063;Beauval-en-Caux;491;15;506 +76067;Beauvoir-en-Lyons;617;14;631 +76068;Bec-de-Mortagne;661;17;678 +76069;Belbeuf;2201;50;2251 +76070;Bellencombre;680;7;687 +76071;Bellengreville;476;7;483 +76072;Belleville-en-Caux;711;12;723 +76074;La Bellière;57;1;58 +76075;Belmesnil;457;2;459 +76076;Bénarville;265;5;270 +76077;Bénesville;195;4;199 +76079;Bénouville;179;1;180 +76082;Bernières;641;6;647 +76083;Bertheauville;106;1;107 +76084;Bertreville;120;1;121 +76085;Bertreville-Saint-Ouen;345;10;355 +76086;Bertrimont;219;6;225 +76087;Berville-en-Caux;649;9;658 +76088;Berville-sur-Seine;559;7;566 +76090;Beuzeville-la-Grenier;1227;16;1243 +76091;Beuzeville-la-Guérard;225;2;227 +76092;Beuzevillette;647;10;657 +76093;Bézancourt;352;9;361 +76094;Bierville;317;3;320 +76095;Bihorel;8398;184;8582 +76096;Biville-la-Baignarde;656;12;668 +76097;Biville-la-Rivière;106;0;106 +76099;Blacqueville;707;9;716 +76100;Blainville-Crevon;1209;17;1226 +76101;Blangy-sur-Bresle;2972;52;3024 +76104;Blosseville;254;14;268 +76105;Le Bocasse;666;8;674 +76106;Bois-d'Ennebourg;563;8;571 +76107;Bois-Guilbert;315;3;318 +76108;Bois-Guillaume;13796;375;14171 +76109;Bois-Héroult;200;5;205 +76110;Bois-Himont;460;5;465 +76111;Bois-l'Évêque;554;9;563 +76112;Le Bois-Robert;351;8;359 +76113;Boissay;406;6;412 +76114;Bolbec;11417;136;11553 +76115;Bolleville;580;3;583 +76103;Bonsecours;6462;104;6566 +76116;Boos;3810;45;3855 +76117;Bordeaux-Saint-Clair;666;14;680 +76118;Bornambusc;260;8;268 +76119;Bosc-Bérenger;190;2;192 +76120;Bosc-Bordel;452;10;462 +76121;Bosc-Édeline;360;3;363 +76123;Bosc-Guérard-Saint-Adrien;948;25;973 +76124;Bosc-Hyons;419;8;427 +76125;Bosc-le-Hard;1462;20;1482 +76126;Bosc-Mesnil;312;6;318 +76128;Bosville;579;15;594 +76129;Boudeville;210;6;216 +76130;Bouelles;276;4;280 +76131;La Bouille;753;11;764 +76132;Bourdainville;463;2;465 +76133;Le Bourg-Dun;431;9;440 +76134;Bourville;297;4;301 +76135;Bouville;982;14;996 +76136;Brachy;768;7;775 +76138;Bracquetuit;336;5;341 +76139;Bradiancourt;217;3;220 +76140;Brametot;206;1;207 +76141;Bréauté;1340;13;1353 +76142;Brémontier-Merval;459;124;583 +76143;Bretteville-du-Grand-Caux;1345;22;1367 +76144;Bretteville-Saint-Laurent;159;2;161 +76146;Buchy;2757;97;2854 +76147;Bully;916;21;937 +76148;Bures-en-Bray;323;5;328 +76149;Butot;281;4;285 +76732;Butot-Vénesville;247;4;251 +76151;Cailleville;264;10;274 +76152;Cailly;790;3;793 +76122;Callengeville;511;5;516 +76153;Calleville-les-Deux-Églises;332;3;335 +76154;Campneuseville;476;11;487 +76155;Canehan;364;2;366 +76156;Canouville;335;9;344 +76157;Canteleu;14181;448;14629 +76158;Canville-les-Deux-Églises;328;2;330 +76159;Cany-Barville;3052;53;3105 +76160;Carville-la-Folletière;425;8;433 +76161;Carville-Pot-de-Fer;106;3;109 +76162;Le Catelier;261;5;266 +76163;Catenay;678;9;687 +76165;Caudebec-lès-Elbeuf;10335;78;10413 +76166;Le Caule-Sainte-Beuve;487;5;492 +76167;Cauville-sur-Mer;1547;26;1573 +76168;Les Cent-Acres;64;1;65 +76169;La Cerlangue;1289;111;1400 +76170;La Chapelle-du-Bourgay;130;0;130 +76171;La Chapelle-Saint-Ouen;130;3;133 +76172;La Chapelle-sur-Dun;160;3;163 +76173;La Chaussée;549;6;555 +76174;Cideville;386;5;391 +76175;Clais;259;7;266 +76176;Clasville;326;7;333 +76177;Claville-Motteville;279;6;285 +76178;Cléon;4994;32;5026 +76179;Clères;1369;16;1385 +76180;Cleuville;194;8;202 +76181;Cléville;159;2;161 +76182;Cliponville;277;6;283 +76183;Colleville;759;17;776 +76184;Colmesnil-Manneville;107;2;109 +76185;Compainville;180;4;184 +76186;Conteville;491;7;498 +76187;Contremoulins;155;9;164 +76188;Cottévrard;470;4;474 +76189;Crasville-la-Mallet;154;6;160 +76190;Crasville-la-Rocquefort;214;4;218 +76192;Criel-sur-Mer;2680;54;2734 +76193;La Crique;350;5;355 +76194;Criquebeuf-en-Caux;404;3;407 +76196;Criquetot-l'Esneval;2567;83;2650 +76195;Criquetot-le-Mauconduit;176;1;177 +76197;Criquetot-sur-Longueville;228;1;229 +76198;Criquetot-sur-Ouville;811;18;829 +76199;Criquiers;651;10;661 +76200;Critot;465;12;477 +76201;Croisy-sur-Andelle;554;4;558 +76203;Croix-Mare;803;7;810 +76202;Croixdalle;307;4;311 +76204;Cropus;249;1;250 +76205;Crosville-sur-Scie;248;2;250 +76206;Cuverville;351;5;356 +76207;Cuverville-sur-Yères;199;6;205 +76208;Cuy-Saint-Fiacre;659;17;676 +76209;Dampierre-en-Bray;453;8;461 +76210;Dampierre-Saint-Nicolas;472;2;474 +76211;Dancourt;229;2;231 +76212;Darnétal;9707;80;9787 +76213;Daubeuf-Serville;393;8;401 +76214;Dénestanville;266;1;267 +76216;Déville-lès-Rouen;10492;96;10588 +76217;Dieppe;29080;558;29638 +76218;Doudeauville;87;1;88 +76219;Doudeville;2484;41;2525 +76220;Douvrend;522;11;533 +76221;Drosay;198;7;205 +76222;Duclair;4198;47;4245 +76223;Écalles-Alix;533;6;539 +76224;Écrainville;1022;21;1043 +76225;Écretteville-lès-Baons;387;13;400 +76226;Écretteville-sur-Mer;159;2;161 +76227;Ectot-l'Auber;677;11;688 +76228;Ectot-lès-Baons;394;7;401 +76231;Elbeuf;16166;142;16308 +76229;Elbeuf-en-Bray;415;13;428 +76230;Elbeuf-sur-Andelle;473;6;479 +76232;Életot;645;9;654 +76233;Ellecourt;147;5;152 +76234;Émanville;707;11;718 +76235;Envermeu;2097;162;2259 +76236;Envronville;343;1;344 +76237;Épinay-sur-Duclair;529;9;538 +76238;Épouville;2686;45;2731 +76239;Épretot;735;14;749 +76240;Épreville;1022;13;1035 +76241;Ermenouville;140;6;146 +76242;Ernemont-la-Villette;180;1;181 +76243;Ernemont-sur-Buchy;299;4;303 +76244;Esclavelles;378;6;384 +76245;Eslettes;1567;16;1583 +76247;Esteville;495;4;499 +76249;Étaimpuis;805;11;816 +76250;Étainhus;1160;25;1185 +76251;Étalleville;454;3;457 +76252;Étalondes;1057;28;1085 +76253;Étoutteville;807;14;821 +76254;Étretat;1291;7;1298 +76255;Eu;6883;193;7076 +76257;Fallencourt;188;2;190 +76259;Fécamp;18641;314;18955 +76260;Ferrières-en-Bray;1674;19;1693 +76261;La Ferté-Saint-Samson;466;11;477 +76262;Fesques;119;0;119 +76263;La Feuillie;1296;22;1318 +76264;Flamanville;492;12;504 +76265;Flamets-Frétils;162;7;169 +76266;Flocques;711;15;726 +76268;Fongueusemare;189;5;194 +76269;Fontaine-en-Bray;176;3;179 +76270;Fontaine-la-Mallet;2626;61;2687 +76271;Fontaine-le-Bourg;1759;18;1777 +76272;Fontaine-le-Dun;903;17;920 +76273;Fontaine-sous-Préaux;508;15;523 +76274;La Fontelaye;31;0;31 +76275;Fontenay;1240;20;1260 +76276;Forges-les-Eaux;3805;191;3996 +76278;Foucarmont;817;15;832 +76279;Foucart;354;10;364 +76475;Franqueville-Saint-Pierre;6123;188;6311 +76280;Fréauville;132;1;133 +76281;La Frénaye;2134;46;2180 +76282;Freneuse;932;13;945 +76283;Fresles;236;4;240 +76284;Fresnay-le-Long;331;5;336 +76285;Fresne-le-Plan;609;8;617 +76286;Fresnoy-Folny;699;7;706 +76287;Fresquiennes;997;14;1011 +76288;Freulleville;364;5;369 +76290;Frichemesnil;412;11;423 +76291;Froberville;1245;19;1264 +76292;Fry;148;3;151 +76293;Fultot;220;0;220 +76294;La Gaillarde;386;8;394 +76295;Gaillefontaine;1225;9;1234 +76296;Gainneville;2582;31;2613 +76297;Gancourt-Saint-Étienne;228;7;235 +76298;Ganzeville;477;6;483 +76299;Gerponville;398;4;402 +76300;Gerville;424;4;428 +76302;Goderville;2851;40;2891 +76303;Gommerville;738;12;750 +76304;Gonfreville-Caillot;359;1;360 +76305;Gonfreville-l'Orcher;9057;58;9115 +76306;Gonnetot;197;2;199 +76307;Gonneville-la-Mallet;1334;22;1356 +76308;Gonneville-sur-Scie;465;4;469 +76309;Gonzeville;115;2;117 +76311;Goupillières;417;5;422 +76312;Gournay-en-Bray;6072;97;6169 +76313;Gouy;869;25;894 +76314;Graimbouville;615;9;624 +76315;Grainville-la-Teinturière;1078;21;1099 +76316;Grainville-sur-Ry;446;4;450 +76317;Grainville-Ymauville;439;12;451 +76318;Grand-Camp;708;26;734 +76319;Grand-Couronne;9648;194;9842 +76322;Le Grand-Quevilly;25698;247;25945 +76320;Grandcourt;341;5;346 +76321;Les Grandes-Ventes;1821;27;1848 +76323;Graval;155;2;157 +76324;Grèges;838;21;859 +76325;Grémonville;433;4;437 +76327;Greuville;379;5;384 +76328;Grigneuseville;368;6;374 +76329;Gruchet-le-Valasse;3160;38;3198 +76330;Gruchet-Saint-Siméon;687;13;700 +76331;Grugny;1011;7;1018 +76332;Grumesnil;441;2;443 +76333;Guerville;473;6;479 +76334;Gueures;535;20;555 +76335;Gueutteville;85;0;85 +76336;Gueutteville-les-Grès;370;11;381 +76338;La Hallotière;221;1;222 +76339;Le Hanouard;249;5;254 +76340;Harcanville;510;7;517 +76341;Harfleur;8449;65;8514 +76342;Hattenville;724;17;741 +76343;Haucourt;207;4;211 +76344;Haudricourt;416;11;427 +76345;Haussez;278;2;280 +76346;Hautot-l'Auvray;329;8;337 +76347;Hautot-le-Vatois;354;6;360 +76348;Hautot-Saint-Sulpice;678;8;686 +76349;Hautot-sur-Mer;1914;71;1985 +76350;Hautot-sur-Seine;413;7;420 +76041;Les Hauts-de-Caux;1384;34;1418 +76351;Le Havre;170147;1920;172067 +76352;La Haye;381;1;382 +76353;Héberville;116;5;121 +76354;Hénouville;1302;14;1316 +76355;Héricourt-en-Caux;955;13;968 +76356;Hermanville;116;2;118 +76357;Hermeville;366;16;382 +76358;Le Héron;252;2;254 +76359;Héronchelles;139;2;141 +76360;Heugleville-sur-Scie;637;7;644 +76361;Heuqueville;718;8;726 +76362;Heurteauville;310;2;312 +76363;Hodeng-au-Bosc;575;8;583 +76364;Hodeng-Hodenger;279;3;282 +76365;Houdetot;180;0;180 +76366;Le Houlme;4050;29;4079 +76367;Houppeville;2784;46;2830 +76368;Houquetot;353;6;359 +76369;La Houssaye-Béranger;534;7;541 +76370;Hugleville-en-Caux;428;3;431 +76371;Les Ifs;75;0;75 +76372;Illois;407;3;410 +76373;Imbleville;307;6;313 +76374;Incheville;1247;14;1261 +76375;Ingouville;270;14;284 +76377;Isneauville;3158;64;3222 +76378;Jumièges;1719;33;1752 +76379;Lamberville;192;2;194 +76380;Lammerville;335;8;343 +76381;Landes-Vieilles-et-Neuves;137;1;138 +76382;Lanquetot;1147;13;1160 +76383;Lestanville;95;0;95 +76384;Lillebonne;8894;152;9046 +76385;Limésy;1523;42;1565 +76386;Limpiville;370;6;376 +76387;Lindebeuf;399;7;406 +76388;Lintot;449;3;452 +76389;Lintot-les-Bois;181;7;188 +76390;Les Loges;1157;22;1179 +76391;La Londe;2334;67;2401 +76392;Londinières;1263;13;1276 +76393;Longmesnil;52;0;52 +76394;Longroy;634;5;639 +76395;Longueil;561;11;572 +76396;Longuerue;327;3;330 +76397;Longueville-sur-Scie;980;26;1006 +76398;Louvetot;738;6;744 +76399;Lucy;189;1;190 +76400;Luneray;2211;37;2248 +76402;Malaunay;6110;45;6155 +76403;Malleville-les-Grès;202;1;203 +76404;Manéglise;1261;21;1282 +76405;Manéhouville;226;1;227 +76406;Maniquerville;411;6;417 +76407;Manneville-ès-Plains;280;7;287 +76408;Manneville-la-Goupil;1021;14;1035 +76409;Mannevillette;868;12;880 +76410;Maromme;10908;137;11045 +76411;Marques;232;1;233 +76412;Martainville-Épreville;697;11;708 +76413;Martigny;439;10;449 +76414;Martin-Église;1587;51;1638 +76415;Massy;343;5;348 +76416;Mathonville;319;6;325 +76417;Maucomble;415;3;418 +76418;Maulévrier-Sainte-Gertrude;987;20;1007 +76419;Mauny;172;6;178 +76420;Mauquenchy;352;5;357 +76421;Mélamare;889;13;902 +76422;Melleville;264;8;272 +76423;Ménerval;173;2;175 +76424;Ménonval;221;4;225 +76425;Mentheville;301;5;306 +76426;Mésangueville;164;1;165 +76427;Mesnières-en-Bray;927;248;1175 +76428;Le Mesnil-Durdent;18;3;21 +76429;Le Mesnil-Esnard;7967;351;8318 +76430;Mesnil-Follemprise;128;4;132 +76431;Le Mesnil-Lieubray;99;3;102 +76432;Mesnil-Mauger;247;4;251 +76433;Mesnil-Panneville;719;7;726 +76434;Mesnil-Raoul;1024;7;1031 +76435;Le Mesnil-Réaume;793;16;809 +76436;Le Mesnil-sous-Jumièges;639;3;642 +76437;Meulers;563;5;568 +76438;Millebosc;247;5;252 +76439;Mirville;335;9;344 +76440;Molagnies;167;4;171 +76441;Monchaux-Soreng;654;15;669 +76442;Monchy-sur-Eu;587;9;596 +76443;Mont-Cauvaire;741;14;755 +76451;Mont-Saint-Aignan;18850;369;19219 +76445;Montérolier;596;7;603 +76446;Montigny;1240;17;1257 +76447;Montivilliers;15612;250;15862 +76448;Montmain;1314;23;1337 +76449;Montreuil-en-Caux;507;8;515 +76450;Montroty;273;26;299 +76452;Montville;4760;54;4814 +76453;Morgny-la-Pommeraye;1023;21;1044 +76606;Morienne;179;26;205 +76454;Mortemer;83;0;83 +76455;Morville-sur-Andelle;345;4;349 +76456;Motteville;791;11;802 +76457;Moulineaux;944;15;959 +76458;Muchedent;131;3;134 +76459;Nesle-Hodeng;349;5;354 +76460;Nesle-Normandeuse;546;8;554 +76463;Neuf-Marché;667;22;689 +76461;Neufbosc;403;5;408 +76462;Neufchâtel-en-Bray;4737;206;4943 +76464;La Neuville-Chant-d'Oisel;2240;33;2273 +76465;Neuville-Ferrières;579;5;584 +76467;Néville;1306;20;1326 +76468;Nointot;1346;33;1379 +76469;Nolléval;447;4;451 +76470;Normanville;669;25;694 +76471;Norville;987;26;1013 +76472;Notre-Dame-d'Aliermont;771;2;773 +76473;Notre-Dame-de-Bliquetuit;754;12;766 +76474;Notre-Dame-de-Bondeville;7015;104;7119 +76477;Notre-Dame-du-Bec;452;7;459 +76478;Notre-Dame-du-Parc;172;1;173 +76479;Nullemont;135;1;136 +76480;Ocqueville;449;11;460 +76481;Octeville-sur-Mer;5918;118;6036 +76482;Offranville;3119;237;3356 +76483;Oherville;228;2;230 +76484;Oissel;11895;86;11981 +76485;Omonville;262;55;317 +76486;Orival;913;4;917 +76487;Osmoy-Saint-Valery;324;6;330 +76488;Ouainville;527;16;543 +76489;Oudalle;440;11;451 +76490;Ourville-en-Caux;1146;13;1159 +76491;Ouville-l'Abbaye;672;7;679 +76492;Ouville-la-Rivière;495;17;512 +76493;Paluel;432;13;445 +76494;Parc-d'Anxtot;567;7;574 +76495;Pavilly;6308;56;6364 +76618;Petit-Caux;9553;202;9755 +76497;Petit-Couronne;8619;190;8809 +76498;Le Petit-Quevilly;21995;265;22260 +76499;Petiville;1125;30;1155 +76500;Pierrecourt;476;5;481 +76501;Pierrefiques;135;7;142 +76502;Pierreval;555;9;564 +76503;Pissy-Pôville;1264;19;1283 +76504;Pleine-Sève;133;2;135 +76505;Pommereux;96;1;97 +76506;Pommeréval;463;5;468 +76507;Ponts-et-Marais;799;13;812 +76476;Port-Jérôme-sur-Seine;10030;180;10210 +76508;La Poterie-Cap-d'Antifer;453;6;459 +76509;Préaux;1812;31;1843 +76510;Prétot-Vicquemare;224;3;227 +76511;Preuseville;137;1;138 +76512;Puisenval;25;0;25 +76513;Quevillon;598;14;612 +76514;Quévreville-la-Poterie;992;13;1005 +76515;Quiberville;552;8;560 +76516;Quièvrecourt;448;8;456 +76517;Quincampoix;2994;84;3078 +76518;Raffetot;503;9;512 +76519;Rainfreville;69;3;72 +76520;Réalcamp;627;13;640 +76521;Rebets;147;1;148 +76522;La Remuée;1284;26;1310 +76523;Rétonval;195;4;199 +76524;Reuville;123;1;124 +76526;Ricarville-du-Val;169;4;173 +76527;Richemont;453;2;455 +76528;Rieux;632;12;644 +76164;Rives-en-Seine;4259;77;4336 +76529;Riville;293;12;305 +76530;Robertot;215;5;220 +76531;Rocquefort;315;8;323 +76532;Rocquemont;802;16;818 +76533;Rogerville;1416;16;1432 +76534;Rolleville;1195;18;1213 +76535;Roncherolles-en-Bray;479;8;487 +76536;Roncherolles-sur-le-Vivier;1114;20;1134 +76537;Ronchois;175;6;181 +76538;Rosay;267;5;272 +76540;Rouen;110145;1615;111760 +76541;Roumare;1508;26;1534 +76542;Routes;273;7;280 +76543;Rouville;617;12;629 +76544;Rouvray-Catillon;228;6;234 +76545;Rouxmesnil-Bouteilles;1847;43;1890 +76546;Royville;282;8;290 +76547;La Rue-Saint-Pierre;785;10;795 +76548;Ry;712;8;720 +76549;Saâne-Saint-Just;159;3;162 +76550;Sahurs;1226;23;1249 +76551;Sainneville;846;11;857 +76554;Saint-Aignan-sur-Ry;348;2;350 +76555;Saint-André-sur-Cailly;857;15;872 +76556;Saint-Antoine-la-Forêt;1079;21;1100 +76557;Saint-Arnoult;1384;20;1404 +76558;Saint-Aubin-Celloville;1057;5;1062 +76559;Saint-Aubin-de-Crétot;522;8;530 +76560;Saint-Aubin-Épinay;1033;16;1049 +76562;Saint-Aubin-le-Cauf;853;18;871 +76561;Saint-Aubin-lès-Elbeuf;8309;84;8393 +76563;Saint-Aubin-Routot;1900;14;1914 +76564;Saint-Aubin-sur-Mer;170;3;173 +76565;Saint-Aubin-sur-Scie;1085;71;1156 +76568;Saint-Clair-sur-les-Monts;591;21;612 +76570;Saint-Crespin;295;4;299 +76572;Saint-Denis-d'Aclon;132;5;137 +76573;Saint-Denis-le-Thiboult;504;14;518 +76574;Saint-Denis-sur-Scie;674;4;678 +76575;Saint-Étienne-du-Rouvray;28641;280;28921 +76576;Saint-Eustache-la-Forêt;1146;16;1162 +76580;Saint-Georges-sur-Fontaine;911;18;929 +76582;Saint-Germain-d'Étables;263;1;264 +76581;Saint-Germain-des-Essourts;406;6;412 +76583;Saint-Germain-sous-Cailly;344;5;349 +76584;Saint-Germain-sur-Eaulne;207;5;212 +76585;Saint-Gilles-de-Crétot;434;11;445 +76586;Saint-Gilles-de-la-Neuville;645;6;651 +76588;Saint-Hellier;459;5;464 +76589;Saint-Honoré;208;3;211 +76590;Saint-Jacques-d'Aliermont;349;2;351 +76591;Saint-Jacques-sur-Darnétal;2835;42;2877 +76592;Saint-Jean-de-Folleville;827;20;847 +76593;Saint-Jean-de-la-Neuville;587;11;598 +76594;Saint-Jean-du-Cardonnay;1377;23;1400 +76595;Saint-Jouin-Bruneval;1869;38;1907 +76596;Saint-Laurent-de-Brèvedent;1467;37;1504 +76597;Saint-Laurent-en-Caux;771;10;781 +76598;Saint-Léger-aux-Bois;497;7;504 +76599;Saint-Léger-du-Bourg-Denis;3450;49;3499 +76600;Saint-Léonard;1724;32;1756 +76601;Saint-Lucien;245;3;248 +76602;Saint-Maclou-de-Folleville;632;12;644 +76603;Saint-Maclou-la-Brière;477;6;483 +76604;Saint-Mards;194;6;200 +76612;Saint-Martin-au-Bosc;251;5;256 +76611;Saint-Martin-aux-Arbres;324;9;333 +76613;Saint-Martin-aux-Buneaux;660;19;679 +76614;Saint-Martin-de-Boscherville;1521;32;1553 +76289;Saint Martin de l'If;1699;26;1725 +76615;Saint-Martin-du-Bec;609;24;633 +76616;Saint-Martin-du-Manoir;1512;33;1545 +76617;Saint-Martin-du-Vivier;1629;64;1693 +76620;Saint-Martin-l'Hortier;278;7;285 +76619;Saint-Martin-le-Gaillard;298;6;304 +76621;Saint-Martin-Osmonville;1171;22;1193 +76622;Saint-Maurice-d'Ételan;305;10;315 +76623;Saint-Michel-d'Halescourt;122;5;127 +76624;Saint-Nicolas-d'Aliermont;3705;59;3764 +76626;Saint-Nicolas-de-la-Haie;413;6;419 +76627;Saint-Nicolas-de-la-Taille;1572;18;1590 +76628;Saint-Ouen-du-Breuil;778;14;792 +76629;Saint-Ouen-le-Mauger;302;6;308 +76630;Saint-Ouen-sous-Bailly;220;6;226 +76631;Saint-Paër;1346;15;1361 +76632;Saint-Pierre-Bénouville;379;3;382 +76634;Saint-Pierre-de-Manneville;921;8;929 +76636;Saint-Pierre-de-Varengeville;2338;23;2361 +76635;Saint-Pierre-des-Jonquières;74;0;74 +76637;Saint-Pierre-en-Port;831;11;842 +76638;Saint-Pierre-en-Val;1100;20;1120 +76641;Saint-Pierre-le-Vieux;192;5;197 +76642;Saint-Pierre-le-Viger;257;3;260 +76640;Saint-Pierre-lès-Elbeuf;8202;77;8279 +76644;Saint-Rémy-Boscrocourt;803;16;819 +76645;Saint-Riquier-en-Rivière;148;5;153 +76646;Saint-Riquier-ès-Plains;585;21;606 +76647;Saint-Romain-de-Colbosc;4132;40;4172 +76648;Saint-Saëns;2391;23;2414 +76649;Saint-Saire;611;11;622 +76650;Saint-Sauveur-d'Émalleville;1214;26;1240 +76651;Saint-Sylvain;179;2;181 +76652;Saint-Vaast-d'Équiqueville;750;5;755 +76653;Saint-Vaast-Dieppedalle;368;3;371 +76654;Saint-Vaast-du-Val;471;8;479 +76655;Saint-Valery-en-Caux;4006;161;4167 +76656;Saint-Victor-l'Abbaye;771;8;779 +76657;Saint-Vigor-d'Ymonville;1130;27;1157 +76658;Saint-Vincent-Cramesnil;655;20;675 +76552;Sainte-Adresse;7389;260;7649 +76553;Sainte-Agathe-d'Aliermont;310;5;315 +76566;Sainte-Austreberthe;612;5;617 +76567;Sainte-Beuve-en-Rivière;183;5;188 +76569;Sainte-Colombe;215;4;219 +76571;Sainte-Croix-sur-Buchy;697;4;701 +76577;Sainte-Foy;593;12;605 +76578;Sainte-Geneviève;270;3;273 +76587;Sainte-Hélène-Bondeville;709;10;719 +76608;Sainte-Marguerite-sur-Duclair;2028;41;2069 +76605;Sainte-Marguerite-sur-Mer;477;11;488 +76609;Sainte-Marie-au-Bosc;367;12;379 +76610;Sainte-Marie-des-Champs;1582;13;1595 +76660;Sandouville;801;8;809 +76662;Sassetot-le-Malgardé;116;0;116 +76663;Sassetot-le-Mauconduit;1100;18;1118 +76664;Sasseville;273;5;278 +76665;Sauchay;415;5;420 +76666;Saumont-la-Poterie;412;2;414 +76667;Sauqueville;345;6;351 +76668;Saussay;376;7;383 +76669;Sausseuzemare-en-Caux;435;7;442 +76670;Senneville-sur-Fécamp;882;11;893 +76671;Sept-Meules;193;2;195 +76672;Serqueux;991;21;1012 +76673;Servaville-Salmonville;1133;15;1148 +76675;Sierville;1039;11;1050 +76676;Sigy-en-Bray;515;12;527 +76677;Smermesnil;407;8;415 +76678;Sommery;809;8;817 +76679;Sommesnil;103;1;104 +76680;Sorquainville;185;4;189 +76681;Sotteville-lès-Rouen;28965;444;29409 +76682;Sotteville-sous-le-Val;791;4;795 +76683;Sotteville-sur-Mer;390;10;400 +76684;Tancarville;1284;20;1304 +76258;Terres-de-Caux;4142;110;4252 +76685;Thérouldeville;664;3;667 +76686;Theuville-aux-Maillots;554;6;560 +76688;Thiergeville;406;12;418 +76689;Thiétreville;371;38;409 +76690;Thil-Manneville;608;11;619 +76691;Le Thil-Riberpré;219;8;227 +76692;Thiouville;309;6;315 +76693;Le Tilleul;695;7;702 +76694;Tocqueville-en-Caux;121;3;124 +76695;Tocqueville-les-Murs;278;1;279 +76697;Torcy-le-Grand;773;24;797 +76698;Torcy-le-Petit;485;8;493 +76699;Le Torp-Mesnil;441;4;445 +76700;Tôtes;1559;31;1590 +76702;Touffreville-la-Corbeline;826;15;841 +76703;Touffreville-sur-Eu;209;4;213 +76705;Tourville-la-Rivière;2501;21;2522 +76706;Tourville-les-Ifs;613;7;620 +76707;Tourville-sur-Arques;1234;39;1273 +76708;Toussaint;717;11;728 +76709;Le Trait;4942;45;4987 +76710;Trémauville;106;2;108 +76711;Le Tréport;4870;94;4964 +76712;La Trinité-du-Mont;798;26;824 +76714;Les Trois-Pierres;751;14;765 +76715;Trouville;632;8;640 +76716;Turretot;1469;24;1493 +76717;Val-de-la-Haye;710;4;714 +76018;Val-de-Saâne;1504;19;1523 +76034;Val-de-Scie;2555;24;2579 +76718;Valliquerville;1418;34;1452 +76719;Valmont;847;12;859 +76720;Varengeville-sur-Mer;957;33;990 +76721;Varneville-Bretteville;324;9;333 +76723;Vassonville;455;5;460 +76724;Vatierville;133;2;135 +76725;Vattetot-sous-Beaumont;576;5;581 +76726;Vattetot-sur-Mer;319;6;325 +76727;Vatteville-la-Rue;1140;27;1167 +76728;La Vaupalière;1057;19;1076 +76730;Veauville-lès-Quelles;130;2;132 +76731;Vénestanville;205;2;207 +76733;Ventes-Saint-Rémy;226;4;230 +76734;Vergetot;442;12;454 +76735;Veules-les-Roses;605;10;615 +76736;Veulettes-sur-Mer;275;6;281 +76737;Vibeuf;608;20;628 +76738;Vieux-Manoir;736;16;752 +76739;Vieux-Rouen-sur-Bresle;564;7;571 +76740;La Vieux-Rue;571;10;581 +76741;Villainville;294;12;306 +76743;Villers-Écalles;1768;19;1787 +76744;Villers-sous-Foucarmont;193;2;195 +76745;Villy-sur-Yères;194;1;195 +76746;Vinnemerville;216;2;218 +76747;Virville;357;8;365 +76748;Vittefleur;655;7;662 +76749;Wanchy-Capval;356;2;358 +76750;Yainville;1050;13;1063 +76751;Yébleron;1284;18;1302 +76752;Yerville;2418;19;2437 +76753;Ymare;1154;22;1176 +76754;Yport;798;16;814 +76755;Ypreville-Biville;573;8;581 +76756;Yquebeuf;238;8;246 +76757;Yvecrique;644;7;651 +76758;Yvetot;11859;264;12123 +76759;Yville-sur-Seine;451;5;456 +77001;Achères-la-Forêt;1125;19;1144 +77002;Amillis;825;6;831 +77003;Amponville;351;15;366 +77004;Andrezel;284;4;288 +77005;Annet-sur-Marne;3278;44;3322 +77006;Arbonne-la-Forêt;995;21;1016 +77007;Argentières;376;8;384 +77008;Armentières-en-Brie;1242;24;1266 +77009;Arville;125;0;125 +77010;Aubepierre-Ozouer-le-Repos;917;10;927 +77011;Aufferville;514;11;525 +77012;Augers-en-Brie;300;7;307 +77013;Aulnoy;356;8;364 +77014;Avon;13886;240;14126 +77015;Baby;95;2;97 +77016;Bagneaux-sur-Loing;1666;16;1682 +77018;Bailly-Romainvilliers;7521;61;7582 +77019;Balloy;327;3;330 +77020;Bannost-Villegagnon;658;11;669 +77021;Barbey;148;2;150 +77022;Barbizon;1135;32;1167 +77023;Barcy;304;7;311 +77024;Bassevelle;364;3;367 +77025;Bazoches-lès-Bray;861;8;869 +77026;Beauchery-Saint-Martin;368;15;383 +77027;Beaumont-du-Gâtinais;1180;15;1195 +77433;Beautheil-Saints;2015;34;2049 +77029;Beauvoir;205;3;208 +77030;Bellot;774;5;779 +77031;Bernay-Vilbert;827;7;834 +77032;Beton-Bazoches;906;16;922 +77033;Bezalles;241;8;249 +77034;Blandy;739;7;746 +77035;Blennes;559;6;565 +77037;Bois-le-Roi;5876;149;6025 +77036;Boisdon;140;3;143 +77038;Boissettes;401;5;406 +77039;Boissise-la-Bertrand;1150;11;1161 +77040;Boissise-le-Roi;3775;41;3816 +77041;Boissy-aux-Cailles;290;5;295 +77042;Boissy-le-Châtel;3151;53;3204 +77043;Boitron;373;4;377 +77044;Bombon;961;8;969 +77045;Bougligny;725;9;734 +77046;Boulancourt;347;11;358 +77047;Bouleurs;1645;17;1662 +77048;Bourron-Marlotte;2772;82;2854 +77049;Boutigny;862;14;876 +77050;Bransles;568;6;574 +77051;Bray-sur-Seine;2243;18;2261 +77052;Bréau;327;5;332 +77053;Brie-Comte-Robert;17817;316;18133 +77054;La Brosse-Montceaux;773;12;785 +77055;Brou-sur-Chantereine;4382;11;4393 +77056;Burcy;154;6;160 +77057;Bussières;524;3;527 +77058;Bussy-Saint-Georges;27379;335;27714 +77059;Bussy-Saint-Martin;676;15;691 +77060;Buthiers;730;16;746 +77061;Cannes-Écluse;2466;37;2503 +77062;Carnetin;454;9;463 +77063;La Celle-sur-Morin;1313;13;1326 +77065;Cély;1183;23;1206 +77066;Cerneux;323;8;331 +77067;Cesson;10418;140;10558 +77068;Cessoy-en-Montois;214;4;218 +77069;Chailly-en-Bière;2037;27;2064 +77070;Chailly-en-Brie;1394;103;1497 +77071;Chaintreaux;909;14;923 +77072;Chalautre-la-Grande;703;11;714 +77073;Chalautre-la-Petite;572;17;589 +77075;Chalifert;1266;15;1281 +77076;Chalmaison;752;53;805 +77077;Chambry;979;12;991 +77078;Chamigny;1356;54;1410 +77079;Champagne-sur-Seine;6233;134;6367 +77080;Champcenest;208;1;209 +77081;Champdeuil;726;8;734 +77082;Champeaux;823;12;835 +77083;Champs-sur-Marne;25041;154;25195 +77084;Changis-sur-Marne;1261;12;1273 +77085;Chanteloup-en-Brie;3953;26;3979 +77086;La Chapelle-Gauthier;1454;5;1459 +77087;La Chapelle-Iger;169;0;169 +77088;La Chapelle-la-Reine;2418;30;2448 +77093;La Chapelle-Moutils;443;3;446 +77089;La Chapelle-Rablais;946;6;952 +77090;La Chapelle-Saint-Sulpice;243;4;247 +77091;Les Chapelles-Bourbon;470;3;473 +77094;Charmentray;289;1;290 +77095;Charny;1313;15;1328 +77096;Chartrettes;2554;57;2611 +77097;Chartronges;296;2;298 +77099;Château-Landon;2952;61;3013 +77098;Châteaubleau;361;2;363 +77100;Le Châtelet-en-Brie;4454;87;4541 +77101;Châtenay-sur-Seine;1024;11;1035 +77102;Châtenoy;168;2;170 +77103;Châtillon-la-Borde;216;2;218 +77104;Châtres;678;7;685 +77335;Chauconin-Neufmontiers;3289;26;3315 +77106;Chauffry;1022;15;1037 +77107;Chaumes-en-Brie;3242;26;3268 +77108;Chelles;54917;278;55195 +77109;Chenoise-Cucharmoy;1623;26;1649 +77110;Chenou;327;2;329 +77111;Chessy;5633;50;5683 +77112;Chevrainvilliers;242;4;246 +77113;Chevru;1105;13;1118 +77114;Chevry-Cossigny;3952;40;3992 +77115;Chevry-en-Sereine;522;11;533 +77116;Choisy-en-Brie;1349;18;1367 +77117;Citry;917;9;926 +77118;Claye-Souilly;12486;145;12631 +77119;Clos-Fontaine;263;3;266 +77120;Cocherel;635;4;639 +77121;Collégien;3400;26;3426 +77122;Combs-la-Ville;22383;173;22556 +77123;Compans;808;1;809 +77124;Conches-sur-Gondoire;1746;28;1774 +77125;Condé-Sainte-Libiaire;1417;17;1434 +77126;Congis-sur-Thérouanne;1768;193;1961 +77127;Coubert;1934;14;1948 +77128;Couilly-Pont-aux-Dames;2154;30;2184 +77129;Coulombs-en-Valois;571;9;580 +77130;Coulommes;430;6;436 +77131;Coulommiers;14838;238;15076 +77132;Coupvray;2864;28;2892 +77133;Courcelles-en-Bassée;206;3;209 +77134;Courchamp;150;3;153 +77135;Courpalay;1323;14;1337 +77136;Courquetaine;195;7;202 +77137;Courtacon;242;10;252 +77138;Courtomer;532;6;538 +77139;Courtry;6492;48;6540 +77140;Coutençon;300;5;305 +77141;Coutevroult;1108;12;1120 +77142;Crécy-la-Chapelle;4531;61;4592 +77143;Crégy-lès-Meaux;4749;46;4795 +77144;Crèvecœur-en-Brie;406;1;407 +77145;Crisenoy;659;13;672 +77146;Croissy-Beaubourg;1987;21;2008 +77147;La Croix-en-Brie;671;8;679 +77148;Crouy-sur-Ourcq;1914;24;1938 +77150;Cuisy;441;2;443 +77151;Dagny;294;4;298 +77152;Dammarie-les-Lys;21835;152;21987 +77153;Dammartin-en-Goële;9920;86;10006 +77154;Dammartin-sur-Tigeaux;1068;14;1082 +77155;Dampmart;3375;37;3412 +77156;Darvault;875;15;890 +77157;Dhuisy;300;6;306 +77158;Diant;197;2;199 +77159;Donnemarie-Dontilly;2832;48;2880 +77161;Dormelles;806;18;824 +77162;Doue;1019;8;1027 +77163;Douy-la-Ramée;325;5;330 +77164;Échouboulains;557;6;563 +77165;Les Écrennes;604;6;610 +77167;Égligny;331;6;337 +77168;Égreville;2150;39;2189 +77169;Émerainville;7720;32;7752 +77171;Esbly;6220;44;6264 +77172;Esmans;899;9;908 +77173;Étrépilly;889;10;899 +77174;Everly;590;15;605 +77175;Évry-Grégy-sur-Yerre;2866;30;2896 +77176;Faremoutiers;2822;26;2848 +77177;Favières;1109;14;1123 +77178;Faÿ-lès-Nemours;487;11;498 +77179;Féricy;579;20;599 +77180;Férolles-Attilly;1237;28;1265 +77181;Ferrières-en-Brie;3433;31;3464 +77182;La Ferté-Gaucher;4860;48;4908 +77183;La Ferté-sous-Jouarre;9619;84;9703 +77184;Flagy;649;16;665 +77185;Fleury-en-Bière;656;17;673 +77187;Fontaine-Fourches;602;3;605 +77188;Fontaine-le-Port;1001;18;1019 +77186;Fontainebleau;14886;437;15323 +77190;Fontains;247;5;252 +77191;Fontenailles;1066;13;1079 +77192;Fontenay-Trésigny;5574;55;5629 +77193;Forfry;218;0;218 +77194;Forges;418;67;485 +77195;Fouju;575;11;586 +77196;Fresnes-sur-Marne;931;3;934 +77197;Frétoy;167;5;172 +77198;Fromont;239;4;243 +77199;Fublaines;1366;12;1378 +77200;Garentreville;114;1;115 +77201;Gastins;689;4;693 +77202;La Genevraye;784;11;795 +77203;Germigny-l'Évêque;1306;19;1325 +77204;Germigny-sous-Coulombs;209;3;212 +77205;Gesvres-le-Chapitre;151;1;152 +77206;Giremoutiers;172;4;176 +77207;Gironville;155;5;160 +77208;Gouaix;1479;34;1513 +77209;Gouvernes;1176;18;1194 +77210;La Grande-Paroisse;2786;35;2821 +77211;Grandpuits-Bailly-Carrois;1028;9;1037 +77212;Gravon;165;3;168 +77214;Gressy;840;13;853 +77215;Gretz-Armainvilliers;8657;62;8719 +77216;Grez-sur-Loing;1414;37;1451 +77217;Grisy-Suisnes;2451;30;2481 +77218;Grisy-sur-Seine;109;1;110 +77219;Guérard;2480;32;2512 +77220;Guercheville;269;4;273 +77221;Guermantes;1147;24;1171 +77222;Guignes;4095;30;4125 +77223;Gurcy-le-Châtel;573;6;579 +77225;La Haute-Maison;300;9;309 +77224;Hautefeuille;255;2;257 +77226;Héricy;2604;106;2710 +77227;Hermé;642;17;659 +77228;Hondevilliers;254;4;258 +77229;La Houssaye-en-Brie;1629;17;1646 +77230;Ichy;166;2;168 +77231;Isles-les-Meldeuses;806;2;808 +77232;Isles-lès-Villenoy;1014;15;1029 +77233;Iverny;588;3;591 +77234;Jablines;686;7;693 +77235;Jaignes;308;5;313 +77236;Jaulnes;362;4;366 +77237;Jossigny;687;2;689 +77238;Jouarre;4337;42;4379 +77239;Jouy-le-Châtel;1527;20;1547 +77240;Jouy-sur-Morin;2096;27;2123 +77241;Juilly;1963;11;1974 +77242;Jutigny;551;7;558 +77243;Lagny-sur-Marne;21356;245;21601 +77244;Larchant;696;43;739 +77245;Laval-en-Brie;448;4;452 +77246;Léchelle;596;12;608 +77247;Lescherolles;463;11;474 +77248;Lesches;743;8;751 +77249;Lésigny;7214;120;7334 +77250;Leudon-en-Brie;164;7;171 +77251;Lieusaint;13291;75;13366 +77252;Limoges-Fourches;490;5;495 +77253;Lissy;230;1;231 +77254;Liverdy-en-Brie;1316;20;1336 +77255;Livry-sur-Seine;2076;35;2111 +77256;Lizines;185;1;186 +77257;Lizy-sur-Ourcq;3566;21;3587 +77258;Lognes;14000;63;14063 +77259;Longperrier;2368;11;2379 +77260;Longueville;1796;25;1821 +77261;Lorrez-le-Bocage-Préaux;1230;20;1250 +77262;Louan-Villegruis-Fontaine;477;9;486 +77263;Luisetaines;243;5;248 +77264;Lumigny-Nesles-Ormeaux;1527;15;1542 +77265;Luzancy;1110;48;1158 +77266;Machault;783;12;795 +77267;La Madeleine-sur-Loing;355;4;359 +77268;Magny-le-Hongre;8645;142;8787 +77269;Maincy;1732;48;1780 +77272;Maison-Rouge;879;8;887 +77270;Maisoncelles-en-Brie;900;11;911 +77271;Maisoncelles-en-Gâtinais;133;1;134 +77273;Marchémoret;564;4;568 +77274;Marcilly;473;2;475 +77275;Les Marêts;149;4;153 +77276;Mareuil-lès-Meaux;3108;49;3157 +77277;Marles-en-Brie;1679;21;1700 +77278;Marolles-en-Brie;401;3;404 +77279;Marolles-sur-Seine;1748;33;1781 +77280;Mary-sur-Marne;1159;12;1171 +77281;Mauperthuis;483;3;486 +77282;Mauregard;353;0;353 +77283;May-en-Multien;912;3;915 +77284;Meaux;54991;470;55461 +77285;Le Mée-sur-Seine;20816;139;20955 +77286;Meigneux;232;6;238 +77287;Meilleray;501;11;512 +77288;Melun;40032;316;40348 +77289;Melz-sur-Seine;352;3;355 +77290;Méry-sur-Marne;670;46;716 +77291;Le Mesnil-Amelot;1014;5;1019 +77292;Messy;1161;11;1172 +77293;Misy-sur-Yonne;978;11;989 +77294;Mitry-Mory;19931;79;20010 +77295;Moisenay;1380;14;1394 +77296;Moissy-Cramayel;17713;126;17839 +77297;Mondreville;337;4;341 +77298;Mons-en-Montois;452;10;462 +77300;Montceaux-lès-Meaux;594;12;606 +77301;Montceaux-lès-Provins;330;1;331 +77302;Montcourt-Fromonville;1982;35;2017 +77303;Montdauphin;246;3;249 +77304;Montenils;26;0;26 +77305;Montereau-Fault-Yonne;20206;194;20400 +77306;Montereau-sur-le-Jard;516;6;522 +77307;Montévrain;11563;106;11669 +77308;Montgé-en-Goële;772;6;778 +77309;Monthyon;1707;11;1718 +77310;Montigny-le-Guesdier;301;6;307 +77311;Montigny-Lencoup;1386;14;1400 +77312;Montigny-sur-Loing;2701;76;2777 +77313;Montmachoux;246;2;248 +77314;Montolivet;238;2;240 +77315;Montry;3631;30;3661 +77316;Moret-Loing-et-Orvanne;12214;338;12552 +77317;Mormant;4834;22;4856 +77318;Mortcerf;1445;15;1460 +77319;Mortery;149;3;152 +77320;Mouroux;5491;58;5549 +77321;Mousseaux-lès-Bray;701;6;707 +77322;Moussy-le-Neuf;3054;20;3074 +77323;Moussy-le-Vieux;1428;5;1433 +77325;Mouy-sur-Seine;357;4;361 +77326;Nandy;6042;65;6107 +77327;Nangis;8710;83;8793 +77328;Nanteau-sur-Essonne;435;8;443 +77329;Nanteau-sur-Lunain;695;4;699 +77330;Nanteuil-lès-Meaux;6160;72;6232 +77331;Nanteuil-sur-Marne;430;5;435 +77332;Nantouillet;277;1;278 +77333;Nemours;13081;134;13215 +77336;Neufmoutiers-en-Brie;1091;20;1111 +77337;Noisiel;15230;103;15333 +77338;Noisy-Rudignon;610;8;618 +77339;Noisy-sur-École;1832;57;1889 +77340;Nonville;618;12;630 +77341;Noyen-sur-Seine;371;10;381 +77342;Obsonville;112;1;113 +77343;Ocquerre;429;24;453 +77344;Oissery;2276;22;2298 +77345;Orly-sur-Morin;677;11;688 +77347;Les Ormes-sur-Voulzie;858;10;868 +77348;Ormesson;243;6;249 +77349;Othis;6680;77;6757 +77350;Ozoir-la-Ferrière;20331;169;20500 +77352;Ozouer-le-Voulgis;1904;21;1925 +77353;Paley;421;7;428 +77354;Pamfou;942;9;951 +77355;Paroy;167;1;168 +77356;Passy-sur-Seine;47;1;48 +77357;Pécy;863;7;870 +77358;Penchard;1083;13;1096 +77359;Perthes;1995;24;2019 +77360;Pézarches;392;4;396 +77361;Pierre-Levée;470;7;477 +77363;Le Pin;1467;10;1477 +77364;Le Plessis-aux-Bois;280;2;282 +77365;Le Plessis-Feu-Aussoux;591;6;597 +77366;Le Plessis-l'Évêque;297;4;301 +77367;Le Plessis-Placy;268;4;272 +77368;Poigny;528;8;536 +77369;Poincy;692;12;704 +77370;Poligny;798;12;810 +77371;Pommeuse;2925;24;2949 +77372;Pomponne;4034;37;4071 +77373;Pontault-Combault;37747;247;37994 +77374;Pontcarré;2251;16;2267 +77376;Précy-sur-Marne;803;3;806 +77377;Presles-en-Brie;2312;31;2343 +77378;Pringy;2924;19;2943 +77379;Provins;11844;281;12125 +77380;Puisieux;319;5;324 +77381;Quiers;668;5;673 +77382;Quincy-Voisins;5435;54;5489 +77383;Rampillon;825;6;831 +77384;Réau;1834;4;1838 +77385;Rebais;2288;25;2313 +77386;Recloses;635;24;659 +77387;Remauville;459;10;469 +77388;Reuil-en-Brie;834;5;839 +77389;La Rochette;3412;98;3510 +77390;Roissy-en-Brie;22994;106;23100 +77391;Rouilly;486;6;492 +77392;Rouvres;899;9;908 +77393;Rozay-en-Brie;2826;36;2862 +77394;Rubelles;2355;19;2374 +77395;Rumont;123;5;128 +77396;Rupéreux;101;0;101 +77397;Saâcy-sur-Marne;1813;36;1849 +77398;Sablonnières;721;8;729 +77400;Saint-Augustin;1738;29;1767 +77402;Saint-Barthélemy;329;5;334 +77403;Saint-Brice;781;17;798 +77405;Saint-Cyr-sur-Morin;1952;44;1996 +77406;Saint-Denis-lès-Rebais;975;19;994 +77407;Saint-Fargeau-Ponthierry;14206;128;14334 +77408;Saint-Fiacre;402;2;404 +77409;Saint-Germain-Laval;2762;101;2863 +77410;Saint-Germain-Laxis;743;18;761 +77411;Saint-Germain-sous-Doue;537;11;548 +77412;Saint-Germain-sur-École;366;5;371 +77413;Saint-Germain-sur-Morin;3664;49;3713 +77414;Saint-Hilliers;473;8;481 +77415;Saint-Jean-les-Deux-Jumeaux;1272;12;1284 +77416;Saint-Just-en-Brie;240;5;245 +77417;Saint-Léger;261;1;262 +77418;Saint-Loup-de-Naud;882;11;893 +77419;Saint-Mammès;3347;119;3466 +77420;Saint-Mard;3857;28;3885 +77421;Saint-Mars-Vieux-Maisons;283;2;285 +77423;Saint-Martin-des-Champs;650;11;661 +77424;Saint-Martin-du-Boschet;287;4;291 +77425;Saint-Martin-en-Bière;751;17;768 +77426;Saint-Méry;344;9;353 +77427;Saint-Mesmes;613;6;619 +77428;Saint-Ouen-en-Brie;836;12;848 +77429;Saint-Ouen-sur-Morin;536;5;541 +77430;Saint-Pathus;6055;51;6106 +77431;Saint-Pierre-lès-Nemours;5483;90;5573 +77432;Saint-Rémy-la-Vanne;983;9;992 +77434;Saint-Sauveur-lès-Bray;359;5;364 +77435;Saint-Sauveur-sur-École;1122;22;1144 +77436;Saint-Siméon;896;5;901 +77437;Saint-Soupplets;3243;30;3273 +77438;Saint-Thibault-des-Vignes;6447;75;6522 +77401;Sainte-Aulde;680;7;687 +77404;Sainte-Colombe;1822;31;1853 +77439;Salins;1102;21;1123 +77440;Sammeron;1125;15;1140 +77441;Samois-sur-Seine;2053;49;2102 +77442;Samoreau;2308;65;2373 +77443;Sancy;383;8;391 +77444;Sancy-lès-Provins;321;3;324 +77445;Savigny-le-Temple;29984;238;30222 +77446;Savins;606;9;615 +77447;Seine-Port;1888;42;1930 +77448;Sept-Sorts;500;8;508 +77449;Serris;9040;87;9127 +77450;Servon;3251;52;3303 +77451;Signy-Signets;584;6;590 +77452;Sigy;57;0;57 +77453;Sivry-Courtry;1214;15;1229 +77454;Sognolles-en-Montois;394;6;400 +77455;Soignolles-en-Brie;1957;11;1968 +77456;Soisy-Bouy;820;19;839 +77457;Solers;1211;22;1233 +77458;Souppes-sur-Loing;5390;108;5498 +77459;Sourdun;1484;405;1889 +77460;Tancrou;357;4;361 +77461;Thénisy;291;6;297 +77462;Thieux;913;3;916 +77463;Thomery;3467;118;3585 +77464;Thorigny-sur-Marne;10154;112;10266 +77465;Thoury-Férottes;673;10;683 +77466;Tigeaux;381;3;384 +77467;La Tombe;224;0;224 +77468;Torcy;22568;125;22693 +77469;Touquin;1206;13;1219 +77470;Tournan-en-Brie;8718;134;8852 +77471;Tousson;391;8;399 +77472;La Trétoire;493;10;503 +77473;Treuzy-Levelay;425;7;432 +77474;Trilbardou;662;4;666 +77475;Trilport;5033;30;5063 +77476;Trocy-en-Multien;239;2;241 +77477;Ury;847;30;877 +77478;Ussy-sur-Marne;1067;10;1077 +77479;Vaires-sur-Marne;13327;140;13467 +77480;Valence-en-Brie;966;8;974 +77481;Vanvillé;183;2;185 +77482;Varennes-sur-Seine;3469;63;3532 +77483;Varreddes;2004;22;2026 +77484;Vaucourtois;256;6;262 +77485;Le Vaudoué;739;14;753 +77486;Vaudoy-en-Brie;902;8;910 +77487;Vaux-le-Pénil;11062;158;11220 +77489;Vaux-sur-Lunain;226;2;228 +77490;Vendrest;730;10;740 +77492;Verdelot;690;7;697 +77493;Verneuil-l'Étang;3237;19;3256 +77494;Vernou-la-Celle-sur-Seine;2673;40;2713 +77495;Vert-Saint-Denis;7610;79;7689 +77496;Vieux-Champagne;190;2;192 +77498;Vignely;309;0;309 +77516;Ville-Saint-Jacques;814;25;839 +77500;Villebéon;479;9;488 +77501;Villecerf;719;17;736 +77504;Villemaréchal;1110;17;1127 +77505;Villemareuil;405;5;410 +77506;Villemer;742;11;753 +77507;Villenauxe-la-Petite;426;7;433 +77508;Villeneuve-le-Comte;1850;36;1886 +77509;Villeneuve-les-Bordes;612;7;619 +77510;Villeneuve-Saint-Denis;924;4;928 +77511;Villeneuve-sous-Dammartin;641;1;642 +77512;Villeneuve-sur-Bellot;1131;11;1142 +77513;Villenoy;4903;32;4935 +77514;Villeparisis;26322;107;26429 +77515;Villeroy;721;5;726 +77517;Villevaudé;2122;12;2134 +77518;Villiers-en-Bière;211;3;214 +77519;Villiers-Saint-Georges;1231;21;1252 +77520;Villiers-sous-Grez;681;21;702 +77521;Villiers-sur-Morin;1926;24;1950 +77522;Villiers-sur-Seine;300;6;306 +77523;Villuis;265;3;268 +77524;Vimpelles;521;10;531 +77525;Vinantes;379;2;381 +77526;Vincy-Manœuvre;289;5;294 +77527;Voinsles;596;18;614 +77528;Voisenon;1133;16;1149 +77529;Voulangis;1522;30;1552 +77530;Voulton;317;12;329 +77531;Voulx;1729;23;1752 +77532;Vulaines-lès-Provins;64;0;64 +77533;Vulaines-sur-Seine;2722;62;2784 +77534;Yèbles;960;3;963 +78003;Ablis;3439;48;3487 +78005;Achères;21017;138;21155 +78006;Adainville;731;18;749 +78007;Aigremont;1084;49;1133 +78009;Allainville;306;5;311 +78010;Les Alluets-le-Roi;1201;36;1237 +78013;Andelu;476;4;480 +78015;Andrésy;13324;118;13442 +78020;Arnouville-lès-Mantes;938;12;950 +78029;Aubergenville;11817;64;11881 +78030;Auffargis;1982;45;2027 +78031;Auffreville-Brasseuil;650;10;660 +78033;Aulnay-sur-Mauldre;1140;24;1164 +78034;Auteuil;955;19;974 +78036;Autouillet;509;6;515 +78043;Bailly;3721;142;3863 +78048;Bazainville;1454;41;1495 +78049;Bazemont;1582;41;1623 +78050;Bazoches-sur-Guyonne;621;9;630 +78053;Béhoust;460;8;468 +78057;Bennecourt;1897;22;1919 +78062;Beynes;7662;112;7774 +78068;Blaru;889;21;910 +78070;Boinville-en-Mantois;292;2;294 +78071;Boinville-le-Gaillard;608;8;616 +78072;Boinvilliers;291;2;293 +78073;Bois-d'Arcy;15142;131;15273 +78076;Boissets;266;4;270 +78077;La Boissière-École;765;73;838 +78082;Boissy-Mauvoisin;614;11;625 +78084;Boissy-sans-Avoir;646;11;657 +78087;Bonnelles;1963;49;2012 +78089;Bonnières-sur-Seine;4612;40;4652 +78090;Bouafle;2156;27;2183 +78092;Bougival;8699;142;8841 +78096;Bourdonné;496;8;504 +78104;Breuil-Bois-Robert;735;12;747 +78107;Bréval;1820;26;1846 +78108;Les Bréviaires;1244;29;1273 +78113;Brueil-en-Vexin;691;12;703 +78117;Buc;5821;159;5980 +78118;Buchelay;3133;21;3154 +78120;Bullion;1914;62;1976 +78123;Carrières-sous-Poissy;16212;145;16357 +78124;Carrières-sur-Seine;14967;193;15160 +78125;La Celle-les-Bordes;834;30;864 +78126;La Celle-Saint-Cloud;20966;412;21378 +78128;Cernay-la-Ville;1577;37;1614 +78133;Chambourcy;5634;143;5777 +78138;Chanteloup-les-Vignes;10374;81;10455 +78140;Chapet;1314;24;1338 +78143;Châteaufort;1394;40;1434 +78146;Chatou;30253;501;30754 +78147;Chaufour-lès-Bonnières;471;7;478 +78152;Chavenay;1815;74;1889 +78158;Le Chesnay-Rocquencourt;31164;616;31780 +78160;Chevreuse;5678;132;5810 +78162;Choisel;556;15;571 +78163;Civry-la-Forêt;335;4;339 +78164;Clairefontaine-en-Yvelines;827;64;891 +78165;Les Clayes-sous-Bois;17636;206;17842 +78168;Coignières;4394;26;4420 +78171;Condé-sur-Vesgre;1205;31;1236 +78172;Conflans-Sainte-Honorine;35846;439;36285 +78185;Courgent;374;11;385 +78188;Cravent;438;6;444 +78189;Crespières;1612;67;1679 +78190;Croissy-sur-Seine;9701;400;10101 +78192;Dammartin-en-Serve;1264;15;1279 +78193;Dampierre-en-Yvelines;1037;15;1052 +78194;Dannemarie;194;5;199 +78196;Davron;304;15;319 +78202;Drocourt;562;11;573 +78206;Ecquevilly;4259;45;4304 +78208;Élancourt;25400;260;25660 +78209;Émancé;880;13;893 +78217;Épône;6503;88;6591 +78220;Les Essarts-le-Roi;6708;134;6842 +78224;L' Étang-la-Ville;4437;183;4620 +78227;Évecquemont;787;14;801 +78230;La Falaise;586;8;594 +78231;Favrieux;143;5;148 +78233;Feucherolles;2874;136;3010 +78234;Flacourt;166;0;166 +78236;Flexanville;590;15;605 +78237;Flins-Neuve-Église;156;2;158 +78238;Flins-sur-Seine;2410;29;2439 +78239;Follainville-Dennemont;2139;29;2168 +78242;Fontenay-le-Fleury;13503;119;13622 +78245;Fontenay-Mauvoisin;362;13;375 +78246;Fontenay-Saint-Père;982;19;1001 +78255;Freneuse;4411;57;4468 +78261;Gaillon-sur-Montcient;677;14;691 +78262;Galluis;1212;16;1228 +78263;Gambais;2463;61;2524 +78264;Gambaiseuil;62;1;63 +78265;Garancières;2348;50;2398 +78267;Gargenville;7467;65;7532 +78269;Gazeran;1280;21;1301 +78276;Gommecourt;674;6;680 +78278;Goupillières;511;9;520 +78281;Goussonville;622;10;632 +78283;Grandchamp;325;7;332 +78285;Gressey;545;14;559 +78289;Grosrouvre;915;30;945 +78290;Guernes;1084;15;1099 +78291;Guerville;2144;36;2180 +78296;Guitrancourt;615;6;621 +78297;Guyancourt;28633;432;29065 +78299;Hardricourt;2289;19;2308 +78300;Hargeville;446;5;451 +78302;La Hauteville;174;5;179 +78305;Herbeville;247;6;253 +78307;Hermeray;956;25;981 +78310;Houdan;3640;42;3682 +78311;Houilles;32151;329;32480 +78314;Issou;4100;48;4148 +78317;Jambville;835;14;849 +78321;Jouars-Pontchartrain;5658;115;5773 +78322;Jouy-en-Josas;8191;163;8354 +78324;Jouy-Mauvoisin;555;10;565 +78325;Jumeauville;609;7;616 +78327;Juziers;3820;44;3864 +78329;Lainville-en-Vexin;788;13;801 +78334;Lévis-Saint-Nom;1604;46;1650 +78335;Limay;16820;112;16932 +78337;Limetz-Villez;1942;31;1973 +78343;Les Loges-en-Josas;1564;56;1620 +78344;Lommoye;671;8;679 +78346;Longnes;1448;22;1470 +78349;Longvilliers;502;12;514 +78350;Louveciennes;7099;160;7259 +78354;Magnanville;6030;133;6163 +78356;Magny-les-Hameaux;9327;164;9491 +78358;Maisons-Laffitte;23669;498;24167 +78361;Mantes-la-Jolie;44299;229;44528 +78362;Mantes-la-Ville;20452;140;20592 +78364;Marcq;762;9;771 +78366;Mareil-le-Guyon;377;12;389 +78367;Mareil-Marly;3448;157;3605 +78368;Mareil-sur-Mauldre;1706;37;1743 +78372;Marly-le-Roi;16192;486;16678 +78380;Maule;5854;221;6075 +78381;Maulette;972;6;978 +78382;Maurecourt;4358;53;4411 +78383;Maurepas;18281;262;18543 +78384;Médan;1375;44;1419 +78385;Ménerville;210;1;211 +78389;Méré;1677;53;1730 +78391;Méricourt;422;5;427 +78396;Le Mesnil-le-Roi;6292;149;6441 +78397;Le Mesnil-Saint-Denis;6789;114;6903 +78398;Les Mesnuls;857;22;879 +78401;Meulan-en-Yvelines;8990;75;9065 +78402;Mézières-sur-Seine;3676;40;3716 +78403;Mézy-sur-Seine;2197;33;2230 +78404;Millemont;258;4;262 +78406;Milon-la-Chapelle;289;12;301 +78407;Mittainville;607;15;622 +78410;Moisson;977;7;984 +78413;Mondreville;406;3;409 +78415;Montainville;506;20;526 +78416;Montalet-le-Bois;315;5;320 +78417;Montchauvet;285;7;292 +78418;Montesson;15019;270;15289 +78420;Montfort-l'Amaury;2940;75;3015 +78423;Montigny-le-Bretonneux;32929;467;33396 +78431;Morainvilliers;2930;79;3009 +78437;Mousseaux-sur-Seine;682;9;691 +78439;Mulcent;110;1;111 +78440;Les Mureaux;32792;181;32973 +78442;Neauphle-le-Château;3373;55;3428 +78443;Neauphle-le-Vieux;936;19;955 +78444;Neauphlette;826;15;841 +78451;Nézel;1042;15;1057 +78455;Noisy-le-Roi;7550;262;7812 +78320;Notre-Dame-de-la-Mer;652;10;662 +78460;Oinville-sur-Montcient;1076;20;1096 +78464;Orcemont;1004;22;1026 +78465;Orgerus;2370;65;2435 +78466;Orgeval;6263;138;6401 +78470;Orphin;898;26;924 +78472;Orsonville;334;8;342 +78474;Orvilliers;876;9;885 +78475;Osmoy;364;8;372 +78478;Paray-Douaville;259;3;262 +78481;Le Pecq;16072;363;16435 +78484;Perdreauville;632;16;648 +78486;Le Perray-en-Yvelines;6724;115;6839 +78490;Plaisir;31419;389;31808 +78497;Poigny-la-Forêt;931;40;971 +78498;Poissy;37388;295;37683 +78499;Ponthévrard;636;18;654 +78501;Porcheville;3203;20;3223 +78502;Le Port-Marly;5532;57;5589 +78506;Prunay-en-Yvelines;870;10;880 +78505;Prunay-le-Temple;419;17;436 +78513;La Queue-les-Yvelines;2180;31;2211 +78516;Raizeux;952;15;967 +78517;Rambouillet;26736;513;27249 +78518;Rennemoulin;107;0;107 +78520;Richebourg;1452;25;1477 +78522;Rochefort-en-Yvelines;906;38;944 +78528;Rolleboise;391;3;394 +78530;Rosay;368;2;370 +78531;Rosny-sur-Seine;6433;42;6475 +78536;Sailly;378;11;389 +78537;Saint-Arnoult-en-Yvelines;6001;138;6139 +78545;Saint-Cyr-l'École;18795;612;19407 +78548;Saint-Forget;518;10;528 +78550;Saint-Germain-de-la-Grange;1869;38;1907 +78551;Saint-Germain-en-Laye;44753;1817;46570 +78557;Saint-Hilarion;920;17;937 +78558;Saint-Illiers-la-Ville;395;8;403 +78559;Saint-Illiers-le-Bois;427;5;432 +78561;Saint-Lambert;452;39;491 +78562;Saint-Léger-en-Yvelines;1378;32;1410 +78564;Saint-Martin-de-Bréthencourt;642;11;653 +78565;Saint-Martin-des-Champs;306;9;315 +78567;Saint-Martin-la-Garenne;975;12;987 +78571;Saint-Nom-la-Bretèche;4911;209;5120 +78576;Saint-Rémy-l'Honoré;1568;29;1597 +78575;Saint-Rémy-lès-Chevreuse;7862;156;8018 +78569;Sainte-Mesme;939;20;959 +78586;Sartrouville;51967;466;52433 +78588;Saulx-Marchais;937;26;963 +78590;Senlisse;491;11;502 +78591;Septeuil;2348;24;2372 +78597;Soindres;678;8;686 +78601;Sonchamp;1641;66;1707 +78605;Tacoignières;1034;17;1051 +78606;Le Tartre-Gaudran;35;1;36 +78608;Le Tertre-Saint-Denis;124;1;125 +78609;Tessancourt-sur-Aubette;1024;6;1030 +78615;Thiverval-Grignon;1058;18;1076 +78616;Thoiry;1415;23;1438 +78618;Tilly;529;7;536 +78620;Toussus-le-Noble;1170;32;1202 +78621;Trappes;32584;130;32714 +78623;Le Tremblay-sur-Mauldre;930;123;1053 +78624;Triel-sur-Seine;11892;216;12108 +78638;Vaux-sur-Seine;4927;66;4993 +78640;Vélizy-Villacoublay;22036;211;22247 +78642;Verneuil-sur-Seine;15577;405;15982 +78643;Vernouillet;10048;185;10233 +78644;La Verrière;6715;105;6820 +78646;Versailles;85862;2038;87900 +78647;Vert;831;12;843 +78650;Le Vésinet;15889;585;16474 +78653;Vicq;398;3;401 +78655;Vieille-Église-en-Yvelines;682;28;710 +78668;La Villeneuve-en-Chevrie;640;9;649 +78672;Villennes-sur-Seine;5282;166;5448 +78674;Villepreux;10947;204;11151 +78677;Villette;523;17;540 +78681;Villiers-le-Mahieu;794;17;811 +78683;Villiers-Saint-Frédéric;2838;159;2997 +78686;Viroflay;16129;307;16436 +78688;Voisins-le-Bretonneux;11088;338;11426 +79001;L' Absie;979;14;993 +79002;Adilly;305;5;310 +79003;Aiffres;5506;203;5709 +79185;Aigondigné;4747;144;4891 +79005;Airvault;3281;47;3328 +79136;Alloinay;869;16;885 +79007;Allonne;665;18;683 +79008;Amailloux;827;7;834 +79009;Amuré;428;12;440 +79012;Ardin;1243;33;1276 +79013;Argentonnay;3185;86;3271 +79010;Arçais;613;6;619 +79015;Asnières-en-Poitou;204;7;211 +79016;Assais-les-Jumeaux;774;12;786 +79018;Aubigné;210;2;212 +79019;Aubigny;169;1;170 +79020;Augé;910;19;929 +79022;Availles-Thouarsais;198;2;200 +79023;Avon;67;0;67 +79024;Azay-le-Brûlé;1951;93;2044 +79025;Azay-sur-Thouet;1148;22;1170 +79029;Beaulieu-sous-Parthenay;674;15;689 +79030;Beaussais-Vitré;977;56;1033 +79031;Beauvoir-sur-Niort;1752;29;1781 +79032;Béceleuf;757;14;771 +79034;Bessines;1675;63;1738 +79077;Beugnon-Thireuil;726;10;736 +79038;Boismé;1200;28;1228 +79040;La Boissière-en-Gâtine;246;2;248 +79042;Bougon;177;6;183 +79046;Le Bourdet;584;6;590 +79047;Boussais;457;10;467 +79049;Bressuire;19519;1014;20533 +79050;Bretignolles;600;16;616 +79055;Brieuil-sur-Chizé;123;3;126 +79056;Brion-près-Thouet;740;11;751 +79057;Brioux-sur-Boutonne;1474;50;1524 +79058;Brûlain;757;17;774 +79059;Le Busseau;732;4;736 +79060;Caunay;181;1;182 +79061;Celles-sur-Belle;3907;57;3964 +79062;Cerizay;4768;72;4840 +79066;Champdeniers;1666;37;1703 +79069;Chanteloup;1009;23;1032 +79070;La Chapelle-Bâton;398;10;408 +79071;La Chapelle-Bertrand;478;14;492 +79074;La Chapelle-Pouilloux;183;5;188 +79076;La Chapelle-Saint-Laurent;2002;24;2026 +79105;Les Châteliers;484;9;493 +79080;Châtillon-sur-Thouet;2685;53;2738 +79081;Chauray;7006;201;7207 +79083;Chef-Boutonne;2563;132;2695 +79084;Chenay;454;3;457 +79085;Chérigné;147;5;152 +79086;Cherveux;1905;42;1947 +79087;Chey;567;10;577 +79088;Chiché;1690;45;1735 +79089;Le Chillou;167;1;168 +79090;Chizé;863;23;886 +79091;Cirières;945;24;969 +79092;Clavé;363;5;368 +79094;Clessé;954;10;964 +79095;Clussais-la-Pommeraie;590;12;602 +79096;Combrand;1161;34;1195 +79100;Coulon;2263;55;2318 +79101;Coulonges-sur-l'Autize;2350;48;2398 +79102;Coulonges-Thouarsais;432;5;437 +79103;Courlay;2436;49;2485 +79104;Cours;554;13;567 +79106;Couture-d'Argenson;379;2;381 +79048;La Crèche;5635;129;5764 +79108;Doux;229;1;230 +79109;Échiré;3371;97;3468 +79111;Ensigné;286;4;290 +79112;Épannes;867;20;887 +79114;Exireuil;1583;32;1615 +79115;Exoudun;576;10;586 +79116;Faye-l'Abbesse;1066;16;1082 +79117;Faye-sur-Ardin;631;8;639 +79118;Fénery;292;5;297 +79119;Fenioux;644;11;655 +79120;La Ferrière-en-Parthenay;786;11;797 +79121;Fomperron;420;8;428 +79122;Fontenille-Saint-Martin-d'Entraigues;547;5;552 +79064;Fontivillié;861;25;886 +79123;La Forêt-sur-Sèvre;2365;33;2398 +79124;Les Forges;129;6;135 +79125;Fors;1795;56;1851 +79126;Les Fosses;448;10;458 +79127;La Foye-Monjault;846;7;853 +79128;François;954;26;980 +79129;Fressines;1673;30;1703 +79130;Frontenay-Rohan-Rohan;2862;97;2959 +79131;Geay;314;5;319 +79132;Genneton;325;6;331 +79133;Germond-Rouvre;1174;22;1196 +79134;Glénay;569;13;582 +79135;Gourgé;967;23;990 +79137;Granzay-Gript;904;22;926 +79139;Les Groseillers;58;2;60 +79141;Irais;207;4;211 +79142;Juillé;99;2;101 +79144;Juscorps;361;6;367 +79145;Lageon;359;5;364 +79147;Largeasse;747;9;756 +79148;Lezay;1999;27;2026 +79149;Lhoumois;147;2;149 +79150;Limalonges;834;17;851 +79014;Loretz-d'Argenton;2655;37;2692 +79152;Lorigné;300;6;306 +79153;Loubigné;161;4;165 +79154;Loubillé;392;6;398 +79156;Louin;684;25;709 +79157;Louzy;1358;23;1381 +79158;Luché-sur-Brioux;142;5;147 +79159;Luché-Thouarsais;509;4;513 +79160;Lusseray;157;3;160 +79161;Luzay;635;12;647 +79162;Magné;2671;66;2737 +79163;Mairé-Levescault;532;10;542 +79164;Maisonnay;256;4;260 +79165;Maisontiers;154;5;159 +79251;Marcillé;760;30;790 +79166;Marigny;877;13;890 +79167;Marnes;258;11;269 +79079;Mauléon;8519;224;8743 +79170;Mauzé-sur-le-Mignon;2818;55;2873 +79172;Mazières-en-Gâtine;1011;24;1035 +79174;Melle;6213;327;6540 +79175;Melleran;507;10;517 +79176;Ménigoute;859;23;882 +79177;Messé;188;4;192 +79179;Moncoutant-sur-Sèvre;5046;168;5214 +79180;Montalembert;302;3;305 +79183;Montravers;382;6;388 +79184;La Mothe-Saint-Héray;1692;39;1731 +79189;Nanteuil;1713;31;1744 +79190;Neuvy-Bouin;513;7;520 +79191;Niort;58707;1799;60506 +79195;Nueil-les-Aubiers;5541;120;5661 +79197;Oroux;95;1;96 +79198;Paizay-le-Chapt;261;3;264 +79200;Pamplie;273;3;276 +79201;Pamproux;1747;15;1762 +79202;Parthenay;10267;385;10652 +79203;Pas-de-Jeu;369;8;377 +79204;Périgné;1006;38;1044 +79205;Pers;74;3;77 +79207;La Petite-Boissière;634;17;651 +79208;La Peyratte;1171;49;1220 +79209;Pierrefitte;327;7;334 +79210;Le Pin;1052;23;1075 +79078;Plaine-d'Argenson;966;15;981 +79196;Plaine-et-Vallées;2405;55;2460 +79212;Pliboux;206;3;209 +79213;Pompaire;2001;56;2057 +79215;Pougne-Hérisson;370;7;377 +79216;Prahecq;2179;38;2217 +79217;Prailles-La Couarde;949;18;967 +79218;Pressigny;185;6;191 +79220;Prin-Deyrançon;606;18;624 +79223;Puihardy;61;0;61 +79225;Reffannes;368;6;374 +79226;Le Retail;278;4;282 +79229;La Rochénard;583;6;589 +79230;Rom;860;13;873 +79231;Romans;708;14;722 +79235;Saint-Amand-sur-Sèvre;1409;35;1444 +79236;Saint-André-sur-Sèvre;649;13;662 +79238;Saint-Aubin-du-Plain;550;21;571 +79239;Saint-Aubin-le-Cloud;1771;105;1876 +79241;Saint-Christophe-sur-Roc;558;11;569 +79243;Saint-Coutant;283;0;283 +79244;Saint-Cyr-la-Lande;358;4;362 +79249;Saint-Gelais;2091;63;2154 +79252;Saint-Généroux;362;13;375 +79253;Saint-Georges-de-Noisné;700;14;714 +79254;Saint-Georges-de-Rex;441;14;455 +79255;Saint-Germain-de-Longue-Chaume;403;3;406 +79256;Saint-Germier;226;6;232 +79257;Saint-Hilaire-la-Palud;1540;22;1562 +79258;Saint-Jacques-de-Thouars;438;13;451 +79259;Saint-Jean-de-Thouars;1358;35;1393 +79263;Saint-Laurs;568;8;576 +79265;Saint-Léger-de-Montbrun;1264;24;1288 +79267;Saint-Lin;331;6;337 +79268;Saint-Loup-Lamairé;986;41;1027 +79269;Saint-Maixent-de-Beugné;404;8;412 +79270;Saint-Maixent-l'École;6982;147;7129 +79271;Saint-Marc-la-Lande;363;3;366 +79273;Saint-Martin-de-Bernegoue;782;17;799 +79274;Saint-Martin-de-Mâcon;306;6;312 +79276;Saint-Martin-de-Saint-Maixent;1105;31;1136 +79277;Saint-Martin-de-Sanzay;1085;17;1102 +79278;Saint-Martin-du-Fouilloux;236;4;240 +79280;Saint Maurice Étusson;876;11;887 +79281;Saint-Maxire;1302;43;1345 +79285;Saint-Pardoux-Soutiers;1876;36;1912 +79286;Saint-Paul-en-Gâtine;448;7;455 +79289;Saint-Pierre-des-Échaubrognes;1411;25;1436 +79290;Saint-Pompain;943;12;955 +79293;Saint-Rémy;1100;23;1123 +79294;Saint-Romans-des-Champs;173;4;177 +79295;Saint-Romans-lès-Melle;718;18;736 +79298;Saint-Symphorien;1922;53;1975 +79299;Saint-Varent;2445;40;2485 +79301;Saint-Vincent-la-Châtre;641;21;662 +79246;Sainte-Eanne;613;13;626 +79250;Sainte-Gemme;400;3;403 +79283;Sainte-Néomaye;1320;38;1358 +79284;Sainte-Ouenne;805;12;817 +79297;Sainte-Soline;358;14;372 +79300;Sainte-Verge;1395;30;1425 +79302;Saivres;1461;21;1482 +79303;Salles;329;12;341 +79304;Sansais;753;51;804 +79306;Saurais;189;2;191 +79307;Sauzé-Vaussais;1596;26;1622 +79308;Sciecq;638;10;648 +79309;Scillé;355;7;362 +79310;Secondigné-sur-Belle;510;16;526 +79311;Secondigny;1843;81;1924 +79312;Séligné;115;3;118 +79313;Sepvret;616;16;632 +79316;Soudan;430;4;434 +79319;Souvigné;902;28;930 +79320;Surin;657;12;669 +79322;Le Tallud;2021;48;2069 +79326;Thénezay;1403;29;1432 +79329;Thouars;13990;351;14341 +79331;Tourtenay;117;4;121 +79332;Trayes;122;4;126 +79334;Val-du-Mignon;1095;20;1115 +79063;Val en Vignes;2047;86;2133 +79140;Valdelaume;852;9;861 +79335;Vallans;787;21;808 +79337;Le Vanneau-Irleau;872;26;898 +79338;Vanzay;237;0;237 +79336;Vançais;220;6;226 +79339;Vasles;1662;24;1686 +79340;Vausseroux;326;6;332 +79341;Vautebis;114;1;115 +79342;Vernoux-en-Gâtine;571;13;584 +79343;Vernoux-sur-Boutonne;215;2;217 +79345;Verruyes;904;34;938 +79346;Le Vert;128;3;131 +79347;Viennay;1104;21;1125 +79348;Villefollet;216;5;221 +79349;Villemain;150;2;152 +79350;Villiers-en-Bois;123;3;126 +79351;Villiers-en-Plaine;1774;31;1805 +79352;Villiers-sur-Chizé;160;6;166 +79354;Vouhé;385;11;396 +79355;Vouillé;3292;99;3391 +79242;Voulmentin;1110;29;1139 +79357;Xaintray;223;4;227 +80001;Abbeville;22946;412;23358 +80002;Ablaincourt-Pressoir;266;5;271 +80003;Acheux-en-Amiénois;593;11;604 +80004;Acheux-en-Vimeu;528;5;533 +80005;Agenville;91;2;93 +80006;Agenvillers;228;4;232 +80008;Aigneville;890;19;909 +80009;Ailly-le-Haut-Clocher;966;23;989 +80010;Ailly-sur-Noye;2838;32;2870 +80011;Ailly-sur-Somme;2967;26;2993 +80013;Airaines;2378;32;2410 +80014;Aizecourt-le-Bas;54;0;54 +80015;Aizecourt-le-Haut;67;3;70 +80016;Albert;9928;174;10102 +80017;Allaines;466;10;476 +80018;Allenay;250;5;255 +80019;Allery;793;14;807 +80020;Allonville;738;17;755 +80021;Amiens;134057;2697;136754 +80022;Andainville;254;3;257 +80023;Andechy;269;4;273 +80025;Argoules;326;3;329 +80026;Arguel;29;0;29 +80024;Argœuves;542;6;548 +80027;Armancourt;33;0;33 +80028;Arquèves;165;3;168 +80029;Arrest;869;26;895 +80030;Arry;212;8;220 +80031;Arvillers;778;8;786 +80032;Assainvillers;108;0;108 +80033;Assevillers;296;4;300 +80034;Athies;594;6;600 +80035;Aubercourt;81;1;82 +80036;Aubigny;505;4;509 +80037;Aubvillers;142;2;144 +80038;Auchonvillers;143;3;146 +80039;Ault;1464;18;1482 +80040;Aumâtre;180;5;185 +80041;Aumont;145;4;149 +80042;Autheux;120;2;122 +80043;Authie;286;10;296 +80044;Authieule;409;6;415 +80045;Authuille;165;2;167 +80046;Avelesges;57;0;57 +80047;Aveluy;522;4;526 +80048;Avesnes-Chaussoy;64;3;67 +80049;Ayencourt;192;13;205 +80050;Bacouel-sur-Selle;501;10;511 +80051;Bailleul;266;3;269 +80052;Baizieux;207;5;212 +80053;Balâtre;72;1;73 +80054;Barleux;230;5;235 +80055;Barly;177;3;180 +80056;Bavelincourt;106;1;107 +80057;Bayencourt;79;3;82 +80058;Bayonvillers;340;4;344 +80059;Bazentin;79;1;80 +80060;Béalcourt;104;0;104 +80061;Beaucamps-le-Jeune;202;3;205 +80062;Beaucamps-le-Vieux;1421;19;1440 +80063;Beauchamps;996;21;1017 +80064;Beaucourt-en-Santerre;176;3;179 +80065;Beaucourt-sur-l'Ancre;95;2;97 +80066;Beaucourt-sur-l'Hallue;298;7;305 +80067;Beaufort-en-Santerre;204;4;208 +80068;Beaumetz;226;1;227 +80069;Beaumont-Hamel;215;0;215 +80070;Beauquesne;1339;54;1393 +80071;Beauval;2095;28;2123 +80073;Bécordel-Bécourt;160;2;162 +80074;Becquigny;131;1;132 +80076;Béhen;509;4;513 +80077;Béhencourt;333;3;336 +80078;Bellancourt;513;9;522 +80079;Belleuse;357;0;357 +80080;Belloy-en-Santerre;149;2;151 +80081;Belloy-Saint-Léonard;92;2;94 +80082;Belloy-sur-Somme;752;8;760 +80083;Bergicourt;145;4;149 +80084;Bermesnil;222;2;224 +80085;Bernâtre;32;2;34 +80086;Bernaville;1070;17;1087 +80087;Bernay-en-Ponthieu;231;6;237 +80088;Bernes;352;2;354 +80089;Berneuil;257;1;258 +80090;Berny-en-Santerre;154;3;157 +80092;Bertangles;627;6;633 +80093;Berteaucourt-les-Dames;1162;8;1170 +80094;Berteaucourt-lès-Thennes;437;10;447 +80095;Bertrancourt;223;3;226 +80096;Béthencourt-sur-Mer;968;9;977 +80097;Béthencourt-sur-Somme;129;3;132 +80098;Bettembos;102;3;105 +80099;Bettencourt-Rivière;230;5;235 +80100;Bettencourt-Saint-Ouen;619;5;624 +80101;Beuvraignes;860;5;865 +80102;Biaches;384;7;391 +80103;Biarre;67;0;67 +80104;Biencourt;133;4;137 +80105;Billancourt;173;2;175 +80106;Blangy-sous-Poix;181;3;184 +80107;Blangy-Tronville;563;10;573 +80108;Boisbergues;78;1;79 +80109;Le Boisle;363;2;365 +80110;Boismont;475;17;492 +80112;Bonnay;237;1;238 +80113;Bonneville;331;7;338 +80114;Bosquel;334;6;340 +80115;Bouchavesnes-Bergen;291;4;295 +80116;Bouchoir;293;3;296 +80117;Bouchon;155;1;156 +80118;Boufflers;122;1;123 +80119;Bougainville;448;7;455 +80120;Bouillancourt-en-Séry;550;10;560 +80121;Bouillancourt-la-Bataille;155;0;155 +80122;Bouquemaison;503;15;518 +80123;Bourdon;385;8;393 +80124;Bourseville;699;14;713 +80125;Boussicourt;87;0;87 +80126;Bouttencourt;931;21;952 +80127;Bouvaincourt-sur-Bresle;868;11;879 +80128;Bouvincourt-en-Vermandois;151;4;155 +80129;Bouzincourt;550;13;563 +80130;Bovelles;434;6;440 +80131;Boves;3192;34;3226 +80132;Braches;263;3;266 +80133;Brailly-Cornehotte;241;1;242 +80134;Brassy;74;0;74 +80135;Bray-lès-Mareuil;240;4;244 +80136;Bray-sur-Somme;1276;7;1283 +80137;Breilly;685;4;689 +80138;Bresle;128;1;129 +80139;Breuil;46;0;46 +80140;Brévillers;108;3;111 +80141;Brie;331;1;332 +80142;Briquemesnil-Floxicourt;269;5;274 +80143;Brocourt;98;1;99 +80144;Brouchy;512;9;521 +80145;Brucamps;139;0;139 +80146;Brutelles;207;5;212 +80147;Buigny-l'Abbé;311;9;320 +80148;Buigny-lès-Gamaches;414;5;419 +80149;Buigny-Saint-Maclou;517;12;529 +80150;Buire-Courcelles;234;7;241 +80151;Buire-sur-l'Ancre;310;4;314 +80152;Bus-la-Mésière;167;1;168 +80153;Bus-lès-Artois;134;0;134 +80154;Bussu;213;7;220 +80155;Bussus-Bussuel;297;8;305 +80156;Bussy-lès-Daours;381;3;384 +80157;Bussy-lès-Poix;101;2;103 +80158;Buverchy;49;0;49 +80159;Cachy;282;4;286 +80160;Cagny;1204;21;1225 +80161;Cahon;199;4;203 +80162;Caix;740;12;752 +80163;Cambron;724;11;735 +80164;Camon;4432;54;4486 +80165;Camps-en-Amiénois;188;1;189 +80166;Canaples;706;7;713 +80167;Canchy;322;4;326 +80168;Candas;1100;9;1109 +80169;Cannessières;70;0;70 +80170;Cantigny;114;1;115 +80171;Caours;603;19;622 +80172;Cappy;535;7;542 +80173;Cardonnette;518;7;525 +80174;Le Cardonnois;83;3;86 +80505;Carnoy-Mametz;285;4;289 +80176;Carrépuis;272;4;276 +80177;Cartigny;745;24;769 +80179;Caulières;206;4;210 +80180;Cavillon;103;1;104 +80181;Cayeux-en-Santerre;121;0;121 +80182;Cayeux-sur-Mer;2477;32;2509 +80184;Cerisy;531;5;536 +80183;Cerisy-Buleux;266;6;272 +80185;Champien;276;10;286 +80186;Chaulnes;2083;30;2113 +80187;La Chaussée-Tirancourt;659;11;670 +80188;Chaussoy-Epagny;581;6;587 +80189;La Chavatte;73;1;74 +80190;Chépy;1252;17;1269 +80191;Chilly;183;5;188 +80192;Chipilly;171;2;173 +80193;Chirmont;119;1;120 +80194;Chuignes;134;1;135 +80195;Chuignolles;152;3;155 +80196;Citerne;238;4;242 +80197;Cizancourt;34;0;34 +80198;Clairy-Saulchoix;370;4;374 +80199;Cléry-sur-Somme;546;11;557 +80200;Cocquerel;229;2;231 +80201;Coigneux;49;2;51 +80202;Coisy;340;3;343 +80203;Colincamps;88;2;90 +80204;Combles;765;12;777 +80205;Condé-Folie;916;10;926 +80206;Contalmaison;118;0;118 +80207;Contay;364;1;365 +80208;Conteville;211;4;215 +80210;Contre;153;7;160 +80211;Conty;1735;48;1783 +80212;Corbie;6283;80;6363 +80213;Cottenchy;576;172;748 +80214;Coullemelle;332;1;333 +80215;Coulonvillers;231;8;239 +80216;Courcelette;154;1;155 +80217;Courcelles-au-Bois;82;0;82 +80218;Courcelles-sous-Moyencourt;139;3;142 +80219;Courcelles-sous-Thoix;69;0;69 +80220;Courtemanche;102;2;104 +80221;Cramont;303;5;308 +80222;Crécy-en-Ponthieu;1436;30;1466 +80223;Crémery;121;0;121 +80224;Cressy-Omencourt;123;1;124 +80225;Creuse;190;4;194 +80226;Croix-Moligneaux;278;5;283 +80227;Croixrault;434;10;444 +80228;Le Crotoy;2012;33;2045 +80229;Crouy-Saint-Pierre;346;2;348 +80230;Curchy;298;9;307 +80231;Curlu;168;2;170 +80232;Damery;235;5;240 +80233;Dancourt-Popincourt;155;1;156 +80234;Daours;797;16;813 +80235;Dargnies;1246;18;1264 +80236;Davenescourt;563;4;567 +80237;Démuin;493;10;503 +80238;Dernancourt;540;9;549 +80239;Devise;50;3;53 +80240;Doingt;1427;36;1463 +80241;Domart-en-Ponthieu;1094;12;1106 +80242;Domart-sur-la-Luce;419;9;428 +80243;Domesmont;45;0;45 +80244;Dominois;177;5;182 +80245;Domléger-Longvillers;302;3;305 +80246;Dommartin;350;3;353 +80247;Dompierre-Becquincourt;706;8;714 +80248;Dompierre-sur-Authie;401;5;406 +80249;Domqueur;311;7;318 +80250;Domvast;350;4;354 +80251;Doudelainville;339;8;347 +80252;Douilly;240;1;241 +80253;Doullens;6106;306;6412 +80256;Dreuil-lès-Amiens;1653;11;1664 +80258;Driencourt;92;3;95 +80259;Dromesnil;94;1;95 +80260;Drucat;921;25;946 +80261;Dury;1430;61;1491 +80262;Eaucourt-sur-Somme;424;7;431 +80263;L' Échelle-Saint-Aurin;53;0;53 +80264;Éclusier-Vaux;81;39;120 +80265;Embreville;557;7;564 +80266;Englebelmer;299;0;299 +80267;Ennemain;262;2;264 +80268;Épagne-Épagnette;544;15;559 +80269;Épaumesnil;133;0;133 +80270;Épécamps;5;0;5 +80271;Épehy;1145;14;1159 +80272;Épénancourt;123;1;124 +80273;Éplessier;361;9;370 +80274;Eppeville;1816;18;1834 +80275;Équancourt;298;3;301 +80276;Équennes-Éramecourt;296;7;303 +80278;Erches;187;3;190 +80279;Ercheu;785;12;797 +80280;Ercourt;122;2;124 +80281;Ergnies;180;1;181 +80282;Érondelle;511;5;516 +80283;Esclainvillers;167;0;167 +80284;Esmery-Hallon;767;37;804 +80285;Essertaux;262;3;265 +80287;Estrébœuf;243;4;247 +80288;Estrées-Deniécourt;330;10;340 +80290;Estrées-lès-Crécy;391;7;398 +80557;Estrées-Mons;606;5;611 +80291;Estrées-sur-Noye;270;3;273 +80292;Étalon;136;1;137 +80293;Ételfay;378;6;384 +80294;Éterpigny;168;3;171 +80295;Étinehem-Méricourt;592;7;599 +80296;L' Étoile;1194;8;1202 +80297;Étréjust;44;1;45 +80298;Étricourt-Manancourt;531;4;535 +80299;La Faloise;231;1;232 +80300;Falvy;150;3;153 +80301;Famechon;266;3;269 +80302;Faverolles;161;3;164 +80303;Favières;462;8;470 +80304;Fay;103;2;105 +80305;Ferrières;477;4;481 +80306;Fescamps;138;5;143 +80307;Feuillères;147;1;148 +80308;Feuquières-en-Vimeu;2570;43;2613 +80566;Fieffes-Montrelet;327;8;335 +80310;Fienvillers;686;12;698 +80311;Fignières;154;2;156 +80312;Fins;277;2;279 +80313;Flaucourt;291;5;296 +80314;Flers;195;3;198 +80315;Flers-sur-Noye;506;10;516 +80316;Flesselles;2063;24;2087 +80317;Fleury;223;3;226 +80318;Flixecourt;3173;76;3249 +80319;Fluy;332;0;332 +80320;Folies;146;1;147 +80321;Folleville;146;2;148 +80322;Fonches-Fonchette;164;0;164 +80324;Fontaine-le-Sec;154;4;158 +80325;Fontaine-lès-Cappy;51;1;52 +80326;Fontaine-sous-Montdidier;108;2;110 +80327;Fontaine-sur-Maye;161;5;166 +80328;Fontaine-sur-Somme;518;5;523 +80329;Forceville;175;0;175 +80330;Forceville-en-Vimeu;238;6;244 +80331;Forest-l'Abbaye;301;12;313 +80332;Forest-Montiers;399;9;408 +80333;Fort-Mahon-Plage;1259;13;1272 +80334;Fossemanant;93;5;98 +80335;Foucaucourt-en-Santerre;268;3;271 +80336;Foucaucourt-Hors-Nesle;80;1;81 +80337;Fouencamps;208;3;211 +80338;Fouilloy;1837;18;1855 +80339;Fouquescourt;158;4;162 +80340;Fourcigny;193;2;195 +80341;Fourdrinoy;417;9;426 +80342;Framerville-Rainecourt;461;3;464 +80343;Framicourt;176;2;178 +80344;Francières;194;8;202 +80345;Franleu;552;7;559 +80346;Franqueville;177;1;178 +80347;Fransart;151;5;156 +80348;Fransu;176;0;176 +80349;Fransures;133;1;134 +80350;Franvillers;513;7;520 +80351;Fréchencourt;263;2;265 +80352;Frémontiers;154;1;155 +80353;Fresnes-Mazancourt;139;0;139 +80354;Fresnes-Tilloloy;203;4;207 +80355;Fresneville;105;2;107 +80356;Fresnoy-Andainville;86;6;92 +80357;Fresnoy-au-Val;243;3;246 +80358;Fresnoy-en-Chaussée;148;1;149 +80359;Fresnoy-lès-Roye;293;9;302 +80360;Fressenneville;2207;43;2250 +80361;Frettecuisse;74;0;74 +80362;Frettemeule;324;5;329 +80364;Friaucourt;742;11;753 +80365;Fricamps;176;0;176 +80366;Fricourt;490;4;494 +80367;Frise;183;6;189 +80368;Friville-Escarbotin;4569;103;4672 +80369;Frohen-sur-Authie;233;5;238 +80371;Froyelles;105;4;109 +80372;Frucourt;132;6;138 +80373;Gamaches;2548;86;2634 +80374;Gapennes;281;3;284 +80375;Gauville;346;7;353 +80376;Gentelles;640;4;644 +80377;Gézaincourt;428;6;434 +80378;Ginchy;61;0;61 +80379;Glisy;771;1;772 +80380;Gorenflos;254;6;260 +80381;Gorges;40;1;41 +80383;Goyencourt;94;0;94 +80385;Grand-Laviers;433;27;460 +80384;Grandcourt;176;3;179 +80386;Gratibus;182;3;185 +80387;Grattepanche;318;1;319 +80388;Grébault-Mesnil;220;2;222 +80390;Grivesnes;407;6;413 +80391;Grivillers;86;0;86 +80392;Grouches-Luchuel;586;13;599 +80393;Gruny;324;1;325 +80395;Guerbigny;293;5;298 +80396;Gueschart;335;4;339 +80397;Gueudecourt;94;4;98 +80399;Guignemicourt;360;4;364 +80400;Guillaucourt;440;8;448 +80401;Guillemont;137;2;139 +80402;Guizancourt;127;1;128 +80404;Guyencourt-Saulcourt;140;3;143 +80403;Guyencourt-sur-Noye;177;3;180 +80405;Hailles;422;2;424 +80406;Hallencourt;1325;21;1346 +80407;Hallivillers;149;6;155 +80408;Halloy-lès-Pernois;343;3;346 +80409;Hallu;177;5;182 +80410;Ham;4611;97;4708 +80411;Le Hamel;501;6;507 +80412;Hamelet;630;6;636 +80413;Hancourt;92;1;93 +80414;Hangard;124;2;126 +80415;Hangest-en-Santerre;1016;8;1024 +80416;Hangest-sur-Somme;775;3;778 +80417;Harbonnières;1641;12;1653 +80418;Hardecourt-aux-Bois;84;0;84 +80420;Harponville;180;1;181 +80421;Hattencourt;291;4;295 +80422;Hautvillers-Ouville;580;10;590 +80423;Havernas;394;5;399 +80424;Hébécourt;538;18;556 +80425;Hédauville;126;1;127 +80426;Heilly;424;8;432 +80427;Hem-Hardinval;363;4;367 +80428;Hem-Monacu;128;2;130 +80429;Hénencourt;195;1;196 +80430;Herbécourt;224;4;228 +80431;Hérissart;614;9;623 +80432;Herleville;183;1;184 +80433;Herly;45;0;45 +80434;Hervilly;189;4;193 +80435;Hesbécourt;57;0;57 +80436;Hescamps;516;5;521 +80437;Heucourt-Croquoison;117;4;121 +80438;Heudicourt;507;6;513 +80439;Heuzecourt;169;1;170 +80440;Hiermont;150;3;153 +80442;Hombleux;1180;10;1190 +80443;Hornoy-le-Bourg;1679;25;1704 +80444;Huchenneville;665;13;678 +80445;Humbercourt;268;2;270 +80446;Huppy;785;20;805 +80621;Hypercourt;731;17;748 +80449;Ignaucourt;76;1;77 +80450;Inval-Boiron;113;1;114 +80451;Irles;113;0;113 +80452;Jumel;518;4;522 +80453;Laboissière-en-Santerre;150;0;150 +80455;Lachapelle;85;2;87 +80456;Lafresguimont-Saint-Martin;550;6;556 +80458;Lahoussoye;471;10;481 +80459;Laleu;117;6;123 +80460;Lamaronde;65;0;65 +80461;Lamotte-Brebière;222;4;226 +80462;Lamotte-Buleux;352;11;363 +80463;Lamotte-Warfusée;703;10;713 +80464;Lanchères;915;13;928 +80466;Lanches-Saint-Hilaire;131;1;132 +80465;Languevoisin-Quiquery;195;5;200 +80467;Laucourt;203;1;204 +80468;Laviéville;171;3;174 +80469;Lawarde-Mauger-l'Hortoy;173;1;174 +80470;Léalvillers;167;2;169 +80472;Lesbœufs;182;5;187 +80473;Liancourt-Fosse;301;4;305 +80474;Licourt;400;3;403 +80475;Liéramont;227;7;234 +80476;Liercourt;359;5;364 +80477;Ligescourt;219;5;224 +80478;Lignières;137;2;139 +80479;Lignières-Châtelain;385;2;387 +80480;Lignières-en-Vimeu;111;2;113 +80481;Lihons;442;5;447 +80482;Limeux;141;2;143 +80484;Liomer;397;6;403 +80486;Long;621;8;629 +80487;Longavesnes;86;2;88 +80488;Longpré-les-Corps-Saints;1660;25;1685 +80489;Longueau;5621;44;5665 +80490;Longueval;271;9;280 +80491;Longuevillette;77;1;78 +80493;Louvencourt;281;4;285 +80494;Louvrechy;200;3;203 +80495;Lucheux;534;8;542 +80496;Machiel;156;1;157 +80497;Machy;127;5;132 +80498;Mailly-Maillet;624;5;629 +80499;Mailly-Raineval;299;6;305 +80500;Maisnières;516;6;522 +80501;Maison-Ponthieu;274;3;277 +80502;Maison-Roland;106;3;109 +80503;Maizicourt;192;2;194 +80504;Malpart;78;0;78 +80507;Marcelcave;1239;17;1256 +80508;Marché-Allouarde;53;0;53 +80509;Marchélepot-Misery;599;6;605 +80511;Marestmontiers;113;1;114 +80512;Mareuil-Caubert;825;12;837 +80513;Maricourt;178;3;181 +80514;Marieux;122;1;123 +80515;Marlers;141;0;141 +80516;Marquaix;200;1;201 +80517;Marquivillers;188;3;191 +80518;Martainneville;422;3;425 +80519;Matigny;503;6;509 +80520;Maucourt;180;3;183 +80521;Maurepas;197;0;197 +80522;Le Mazis;106;1;107 +80523;Méaulte;1254;16;1270 +80524;Méharicourt;589;6;595 +80525;Meigneux;175;4;179 +80526;Le Meillard;154;3;157 +80527;Méneslies;310;7;317 +80528;Méréaucourt;6;1;7 +80529;Mérélessart;197;5;202 +80531;Méricourt-en-Vimeu;103;0;103 +80530;Méricourt-l'Abbé;604;4;608 +80533;Mers-les-Bains;2825;33;2858 +80535;Le Mesge;176;3;179 +80536;Mesnil-Bruntel;288;6;294 +80537;Mesnil-Domqueur;88;0;88 +80538;Mesnil-en-Arrouaise;126;0;126 +80540;Mesnil-Martinsart;238;4;242 +80541;Mesnil-Saint-Georges;188;3;191 +80542;Mesnil-Saint-Nicaise;561;7;568 +80543;Métigny;118;3;121 +80544;Mézerolles;188;3;191 +80545;Mézières-en-Santerre;589;0;589 +80546;Miannay;564;7;571 +80547;Millencourt;211;4;215 +80548;Millencourt-en-Ponthieu;359;2;361 +80549;Miraumont;664;12;676 +80550;Mirvaux;144;4;148 +80552;Moislains;1201;14;1215 +80553;Molliens-au-Bois;322;10;332 +80554;Molliens-Dreuil;958;11;969 +80555;Monchy-Lagache;643;20;663 +80556;Mons-Boubert;558;6;564 +80558;Monsures;227;2;229 +80559;Montagne-Fayel;145;3;148 +80560;Montauban-de-Picardie;214;1;215 +80561;Montdidier;6255;104;6359 +80563;Montigny-les-Jongleurs;95;1;96 +80562;Montigny-sur-l'Hallue;205;2;207 +80565;Montonvillers;82;2;84 +80568;Morchain;352;4;356 +80569;Morcourt;312;3;315 +80570;Moreuil;3980;28;4008 +80571;Morisel;518;2;520 +80572;Morlancourt;371;2;373 +80573;Morvillers-Saint-Saturnin;406;5;411 +80574;Mouflers;93;1;94 +80575;Mouflières;86;9;95 +80576;Moyencourt;317;0;317 +80577;Moyencourt-lès-Poix;181;1;182 +80578;Moyenneville;716;11;727 +80579;Muille-Villette;831;12;843 +80580;Nampont;248;3;251 +80582;Namps-Maisnil;987;13;1000 +80583;Nampty;289;8;297 +80584;Naours;1080;10;1090 +80585;Nesle;2339;30;2369 +80586;Nesle-l'Hôpital;156;1;157 +80587;Neslette;81;0;81 +80588;Neufmoulin;361;7;368 +80590;Neuilly-l'Hôpital;323;12;335 +80589;Neuilly-le-Dien;96;0;96 +80591;Neuville-au-Bois;153;1;154 +80592;Neuville-Coppegueule;521;6;527 +80593;La Neuville-lès-Bray;266;2;268 +80595;La Neuville-Sire-Bernard;285;1;286 +80596;Neuvillette;222;6;228 +80597;Nibas;853;15;868 +80598;Nouvion;1316;26;1342 +80599;Noyelles-en-Chaussée;243;3;246 +80600;Noyelles-sur-Mer;730;11;741 +80601;Nurlu;387;4;391 +80485;Ô-de-Selle;1205;9;1214 +80602;Occoches;127;3;130 +80603;Ochancourt;317;1;318 +80604;Offignies;74;3;77 +80605;Offoy;217;2;219 +80606;Oisemont;1171;49;1220 +80607;Oissy;221;3;224 +80609;Oneux;389;6;395 +80611;Oresmaux;930;13;943 +80613;Oust-Marest;630;11;641 +80614;Outrebois;312;6;318 +80615;Ovillers-la-Boisselle;446;6;452 +80616;Pargny;205;1;206 +80617;Parvillers-le-Quesnoy;233;3;236 +80618;Pendé;1069;14;1083 +80619;Pernois;735;8;743 +80620;Péronne;7579;206;7785 +80622;Picquigny;1337;16;1353 +80623;Piennes-Onvillers;363;4;367 +80624;Pierregot;280;5;285 +80626;Pissy;281;2;283 +80627;Plachy-Buyon;878;21;899 +80628;Le Plessier-Rozainvillers;755;4;759 +80630;Poix-de-Picardie;2408;32;2440 +80631;Ponches-Estruval;101;3;104 +80632;Pont-de-Metz;2467;38;2505 +80634;Pont-Noyelles;840;17;857 +80635;Pont-Remy;1469;22;1491 +80633;Ponthoile;615;10;625 +80637;Port-le-Grand;283;1;284 +80638;Potte;103;2;105 +80639;Poulainville;1211;23;1234 +80640;Pozières;266;3;269 +80642;Prouville;314;2;316 +80643;Prouzel;552;7;559 +80644;Proyart;695;10;705 +80645;Puchevillers;555;3;558 +80646;Punchy;87;4;91 +80647;Puzeaux;298;3;301 +80648;Pys;120;1;121 +80629;Pœuilly;121;2;123 +80649;Quend;1396;18;1414 +80650;Querrieu;648;18;666 +80651;Le Quesne;267;2;269 +80652;Le Quesnel;792;9;801 +80654;Quesnoy-le-Montant;564;19;583 +80655;Quesnoy-sur-Airaines;441;6;447 +80656;Quevauvillers;1102;9;1111 +80657;Quiry-le-Sec;325;2;327 +80658;Quivières;142;3;145 +80659;Raincheval;282;6;288 +80661;Rainneville;997;7;1004 +80662;Ramburelles;280;2;282 +80663;Rambures;343;7;350 +80664;Rancourt;198;3;201 +80665;Regnière-Écluse;126;3;129 +80666;Remaisnil;29;0;29 +80667;Remaugies;132;0;132 +80668;Remiencourt;175;3;178 +80669;Rethonvillers;366;4;370 +80670;Revelles;515;6;521 +80671;Ribeaucourt;250;7;257 +80672;Ribemont-sur-Ancre;679;2;681 +80673;Riencourt;178;7;185 +80674;Rivery;3552;40;3592 +80675;Rogy;126;2;128 +80676;Roiglise;155;7;162 +80677;Roisel;1613;21;1634 +80678;Rollot;751;19;770 +80679;Ronssoy;587;6;593 +80680;Rosières-en-Santerre;3008;26;3034 +80681;Rouvrel;306;5;311 +80682;Rouvroy-en-Santerre;212;3;215 +80683;Rouy-le-Grand;107;3;110 +80684;Rouy-le-Petit;112;4;116 +80685;Roye;5786;62;5848 +80686;Rubempré;726;10;736 +80687;Rubescourt;134;2;136 +80688;Rue;3101;103;3204 +80690;Rumigny;611;9;620 +80691;Saigneville;393;14;407 +80692;Sailly-Flibeaucourt;1037;18;1055 +80693;Sailly-Laurette;314;1;315 +80694;Sailly-le-Sec;352;6;358 +80695;Sailly-Saillisel;477;8;485 +80696;Sains-en-Amiénois;1205;32;1237 +80697;Saint-Acheul;27;0;27 +80698;Saint-Aubin-Montenoy;225;4;229 +80699;Saint-Aubin-Rivière;111;0;111 +80700;Saint-Blimont;878;10;888 +80701;Saint-Christ-Briost;437;10;447 +80702;Saint-Fuscien;1170;24;1194 +80703;Saint-Germain-sur-Bresle;206;3;209 +80704;Saint-Gratien;377;6;383 +80705;Saint-Léger-lès-Authie;89;1;90 +80706;Saint-Léger-lès-Domart;1855;17;1872 +80707;Saint-Léger-sur-Bresle;81;4;85 +80708;Saint-Mard;165;3;168 +80709;Saint-Maulvis;267;7;274 +80710;Saint-Maxent;392;4;396 +80711;Saint-Ouen;1907;11;1918 +80713;Saint-Quentin-en-Tourmont;282;4;286 +80714;Saint-Quentin-la-Motte-Croix-au-Bailly;1291;21;1312 +80716;Saint-Riquier;1258;30;1288 +80717;Saint-Sauflieu;995;10;1005 +80718;Saint-Sauveur;1376;16;1392 +80722;Saint-Vaast-en-Chaussée;495;7;502 +80721;Saint-Valery-sur-Somme;2510;40;2550 +80719;Sainte-Segrée;57;5;62 +80723;Saisseval;239;1;240 +80724;Saleux;2846;33;2879 +80725;Salouël;3979;53;4032 +80726;Sancourt;267;6;273 +80728;Saulchoy-sous-Poix;71;0;71 +80729;Sauvillers-Mongival;175;0;175 +80730;Saveuse;932;8;940 +80732;Senarpont;647;15;662 +80733;Senlis-le-Sec;294;8;302 +80734;Sentelie;208;3;211 +80735;Seux;168;2;170 +80737;Sorel;162;0;162 +80736;Sorel-en-Vimeu;213;4;217 +80738;Soues;125;4;129 +80740;Sourdon;325;2;327 +80741;Soyécourt;182;4;186 +80742;Surcamps;64;2;66 +80743;Suzanne;186;4;190 +80744;Tailly;59;2;61 +80746;Talmas;1067;12;1079 +80747;Templeux-la-Fosse;140;3;143 +80748;Templeux-le-Guérard;172;1;173 +80749;Terramesnil;310;3;313 +80750;Tertry;156;1;157 +80751;Thennes;563;6;569 +80752;Thézy-Glimont;662;8;670 +80753;Thiepval;129;1;130 +80754;Thieulloy-l'Abbaye;372;3;375 +80755;Thieulloy-la-Ville;144;4;148 +80756;Thièvres;62;0;62 +80757;Thoix;144;2;146 +80758;Thory;195;0;195 +80759;Tilloloy;353;9;362 +80760;Tilloy-Floriville;393;4;397 +80762;Tincourt-Boucly;356;10;366 +80763;Le Titre;358;8;366 +80765;Tours-en-Vimeu;818;10;828 +80766;Toutencourt;461;6;467 +80767;Le Translay;248;5;253 +80769;Treux;249;4;253 +80625;Trois-Rivières;1504;10;1514 +80770;Tully;548;9;557 +80764;Tœufles;299;7;306 +80771;Ugny-l'Équipée;40;1;41 +80773;Vadencourt;100;0;100 +80774;Vaire-sous-Corbie;288;3;291 +80775;Valines;636;6;642 +80776;Varennes;220;1;221 +80777;Vauchelles-lès-Authie;151;1;152 +80778;Vauchelles-lès-Domart;125;0;125 +80779;Vauchelles-les-Quesnoy;851;19;870 +80780;Vaudricourt;395;5;400 +80781;Vauvillers;246;5;251 +80782;Vaux-en-Amiénois;406;12;418 +80783;Vaux-Marquenneville;87;3;90 +80784;Vaux-sur-Somme;308;6;314 +80785;Vecquemont;540;9;549 +80786;Velennes;149;0;149 +80787;Vercourt;93;1;94 +80788;Vergies;163;3;166 +80789;Vermandovillers;150;0;150 +80790;Verpillières;165;3;168 +80791;Vers-sur-Selle;735;7;742 +80792;La Vicogne;252;1;253 +80793;Vignacourt;2368;30;2398 +80795;Ville-le-Marclet;473;33;506 +80807;Ville-sur-Ancre;271;3;274 +80794;Villecourt;58;1;59 +80796;Villeroy;190;5;195 +80797;Villers-aux-Érables;127;3;130 +80798;Villers-Bocage;1422;54;1476 +80799;Villers-Bretonneux;4464;54;4518 +80800;Villers-Campsart;152;1;153 +80801;Villers-Carbonnel;366;3;369 +80802;Villers-Faucon;588;9;597 +80803;Villers-lès-Roye;274;0;274 +80804;Villers-sous-Ailly;181;5;186 +80806;Villers-sur-Authie;474;7;481 +80805;Villers-Tournelle;155;6;161 +80808;Vironchaux;491;9;500 +80809;Vismes;483;12;495 +80810;Vitz-sur-Authie;127;1;128 +80811;Voyennes;603;7;610 +80812;Vraignes-en-Vermandois;142;3;145 +80813;Vraignes-lès-Hornoy;96;3;99 +80814;Vrély;437;9;446 +80815;Vron;837;26;863 +80819;Wargnies;89;3;92 +80820;Warloy-Baillon;758;6;764 +80821;Warlus;222;6;228 +80822;Warsy;143;2;145 +80823;Warvillers;150;5;155 +80824;Wiencourt-l'Équipée;263;2;265 +80825;Wiry-au-Mont;121;0;121 +80826;Woignarue;816;16;832 +80827;Woincourt;1268;15;1283 +80828;Woirel;60;0;60 +80829;Y;92;2;94 +80830;Yaucourt-Bussus;244;8;252 +80836;Yonval;227;7;234 +80832;Yvrench;304;4;308 +80833;Yvrencheux;127;2;129 +80834;Yzengremer;514;53;567 +80835;Yzeux;267;3;270 +81001;Aguts;223;10;233 +81002;Aiguefonde;2517;56;2573 +81003;Alban;938;42;980 +81004;Albi;48970;1789;50759 +81005;Albine;509;4;513 +81006;Algans;203;3;206 +81008;Almayrac;293;4;297 +81007;Alos;93;2;95 +81009;Amarens;68;0;68 +81010;Ambialet;459;6;465 +81011;Ambres;980;25;1005 +81012;Andillac;123;1;124 +81013;Andouque;406;8;414 +81014;Anglès;508;7;515 +81015;Appelle;72;1;73 +81016;Arfons;168;7;175 +81017;Arifat;164;1;165 +81018;Arthès;2498;53;2551 +81019;Assac;144;1;145 +81020;Aussac;263;12;275 +81021;Aussillon;5892;134;6026 +81022;Bannières;206;7;213 +81023;Barre;207;2;209 +81024;Beauvais-sur-Tescou;362;9;371 +81025;Belcastel;237;9;246 +81026;Bellegarde-Marsal;712;7;719 +81027;Belleserre;162;2;164 +81028;Berlats;105;1;106 +81029;Bernac;186;5;191 +81030;Bertre;118;1;119 +81031;Le Bez;831;18;849 +81032;Blan;1125;19;1144 +81033;Blaye-les-Mines;2987;204;3191 +81034;Boissezon;397;7;404 +81035;Bournazel;192;6;198 +81036;Bout-du-Pont-de-Larn;1261;22;1283 +81037;Brassac;1290;33;1323 +81038;Brens;2305;63;2368 +81039;Briatexte;2016;30;2046 +81040;Brousse;419;11;430 +81041;Broze;119;1;120 +81042;Burlats;2131;51;2182 +81043;Busque;745;13;758 +81044;Cabanès;289;4;293 +81045;Les Cabannes;369;9;378 +81046;Cadalen;1530;31;1561 +81047;Cadix;228;9;237 +81048;Cagnac-les-Mines;2601;32;2633 +81049;Cahuzac;375;3;378 +81051;Cahuzac-sur-Vère;1157;20;1177 +81052;Cambon;2121;55;2176 +81050;Cambon-lès-Lavaur;333;8;341 +81053;Cambounès;331;11;342 +81054;Cambounet-sur-le-Sor;932;19;951 +81055;Les Cammazes;340;1;341 +81056;Campagnac;152;2;154 +81058;Carbes;225;8;233 +81059;Carlus;678;16;694 +81060;Carmaux;9500;159;9659 +81061;Castanet;199;2;201 +81063;Castelnau-de-Lévis;1594;38;1632 +81064;Castelnau-de-Montmiral;1033;24;1057 +81065;Castres;41636;1446;43082 +81066;Caucalières;286;6;292 +81067;Cestayrols;466;9;475 +81068;Combefa;155;6;161 +81069;Cordes-sur-Ciel;869;41;910 +81070;Coufouleux;2874;51;2925 +81071;Courris;80;4;84 +81072;Crespin;131;3;134 +81073;Crespinet;174;1;175 +81074;Cunac;1558;60;1618 +81075;Cuq;495;10;505 +81076;Cuq-Toulza;699;20;719 +81077;Curvalle;398;10;408 +81078;Damiatte;1025;17;1042 +81079;Dénat;792;16;808 +81080;Donnazac;80;1;81 +81081;Dourgne;1315;44;1359 +81082;Le Dourn;114;1;115 +81083;Durfort;249;1;250 +81084;Escoussens;601;24;625 +81085;Escroux;49;1;50 +81086;Espérausses;172;3;175 +81088;Fauch;536;13;549 +81089;Faussergues;141;6;147 +81087;Fayssac;347;10;357 +81090;Fénols;245;6;251 +81092;Fiac;925;15;940 +81093;Florentin;680;46;726 +81062;Fontrieu;947;18;965 +81094;Fraissines;93;3;96 +81095;Frausseilles;85;1;86 +81096;Le Fraysse;392;3;395 +81097;Fréjairolles;1323;36;1359 +81098;Fréjeville;667;20;687 +81099;Gaillac;15294;327;15621 +81100;Garrevaques;398;10;408 +81101;Le Garric;1252;18;1270 +81102;Garrigues;252;13;265 +81103;Gijounet;129;7;136 +81104;Giroussens;1484;35;1519 +81105;Graulhet;12618;238;12856 +81106;Grazac;604;17;621 +81132;Guitalens-L'Albarède;866;13;879 +81108;Itzac;152;6;158 +81109;Jonquières;447;6;453 +81110;Jouqueviel;96;3;99 +81111;Labarthe-Bleys;75;0;75 +81112;Labastide-de-Lévis;909;20;929 +81114;Labastide-Gabausse;512;12;524 +81115;Labastide-Rouairoux;1410;25;1435 +81116;Labastide-Saint-Georges;1929;45;1974 +81117;Labessière-Candeil;749;21;770 +81118;Laboulbène;144;4;148 +81119;Laboutarie;489;6;495 +81120;Labruguière;6535;123;6658 +81121;Lacabarède;310;6;316 +81122;Lacapelle-Pinet;77;2;79 +81123;Lacapelle-Ségalar;99;2;101 +81124;Lacaune;2492;88;2580 +81125;Lacaze;298;8;306 +81126;Lacougotte-Cadoul;171;5;176 +81127;Lacroisille;114;6;120 +81128;Lacrouzette;1689;45;1734 +81129;Lagardiolle;238;5;243 +81130;Lagarrigue;1823;37;1860 +81131;Lagrave;2140;39;2179 +81133;Lamillarié;513;5;518 +81134;Lamontélarié;68;0;68 +81135;Laparrouquial;101;0;101 +81136;Larroque;158;3;161 +81137;Lasfaillades;81;1;82 +81138;Lasgraisses;519;9;528 +81139;Lautrec;1783;27;1810 +81140;Lavaur;10811;418;11229 +81141;Lédas-et-Penthiès;140;4;144 +81142;Lempaut;868;15;883 +81143;Lescout;711;13;724 +81144;Lescure-d'Albigeois;4577;93;4670 +81145;Lisle-sur-Tarn;4694;84;4778 +81146;Livers-Cazelles;216;10;226 +81147;Lombers;1141;14;1155 +81148;Loubers;78;6;84 +81149;Loupiac;408;20;428 +81150;Lugan;421;13;434 +81151;Magrin;130;5;135 +81152;Mailhoc;300;3;303 +81154;Marnaves;77;1;78 +81156;Marssac-sur-Tarn;3200;74;3274 +81157;Marzens;298;11;309 +81158;Le Masnau-Massuguiès;270;6;276 +81159;Massac-Séran;386;17;403 +81160;Massaguel;405;8;413 +81161;Massals;100;3;103 +81162;Maurens-Scopont;187;2;189 +81163;Mazamet;10013;450;10463 +81164;Mézens;490;11;501 +81165;Milhars;239;3;242 +81166;Milhavet;86;3;89 +81167;Miolles;106;1;107 +81168;Mirandol-Bourgnounac;1042;22;1064 +81169;Missècle;97;1;98 +81170;Monestiés;1367;13;1380 +81183;Mont-Roc;190;6;196 +81171;Montans;1431;31;1462 +81172;Montauriol;52;0;52 +81173;Montcabrier;304;7;311 +81174;Montdragon;622;5;627 +81175;Montdurausse;425;6;431 +81176;Montels;103;2;105 +81177;Montfa;488;6;494 +81178;Montgaillard;375;13;388 +81179;Montgey;290;7;297 +81180;Montirat;249;9;258 +81181;Montpinier;190;4;194 +81182;Montredon-Labessonnié;2004;42;2046 +81184;Montrosier;33;0;33 +81185;Montvalen;237;3;240 +81186;Moularès;273;5;278 +81187;Moulayrès;208;3;211 +81188;Moulin-Mage;313;3;316 +81189;Mouzens;125;2;127 +81191;Mouzieys-Panens;236;1;237 +81190;Mouzieys-Teulet;514;9;523 +81192;Murat-sur-Vèbre;846;15;861 +81193;Nages;333;4;337 +81195;Navès;687;22;709 +81196;Noailhac;853;20;873 +81197;Noailles;215;6;221 +81198;Orban;333;4;337 +81199;Padiès;191;3;194 +81200;Palleville;435;52;487 +81201;Pampelonne;851;19;870 +81202;Parisot;959;18;977 +81203;Paulinet;547;10;557 +81204;Payrin-Augmontel;2168;37;2205 +81205;Péchaudier;188;9;197 +81206;Penne;579;19;598 +81207;Peyregoux;80;35;115 +81208;Peyrole;580;11;591 +81209;Pont-de-Larn;2832;83;2915 +81210;Poudis;259;7;266 +81211;Poulan-Pouzols;498;7;505 +81212;Prades;130;4;134 +81213;Pratviel;87;2;89 +81214;Puéchoursi;99;1;100 +81215;Puybegon;645;9;654 +81216;Puycalvel;221;2;223 +81217;Puycelsi;449;11;460 +81218;Puygouzon;3461;83;3544 +81219;Puylaurens;3236;74;3310 +81220;Rabastens;5620;144;5764 +81221;Rayssac;242;1;243 +81222;Réalmont;3418;58;3476 +81223;Le Rialet;55;0;55 +81224;Le Riols;103;2;105 +81225;Rivières;1048;20;1068 +81227;Roquecourbe;2206;47;2253 +81228;Roquemaure;450;10;460 +81229;Roquevidal;135;4;139 +81230;Rosières;744;18;762 +81231;Rouairoux;367;12;379 +81232;Rouffiac;622;12;634 +81234;Roussayrolles;80;3;83 +81235;Saint-Affrique-les-Montagnes;729;28;757 +81236;Saint-Agnan;229;7;236 +81237;Saint-Amancet;189;3;192 +81238;Saint-Amans-Soult;1577;118;1695 +81239;Saint-Amans-Valtoret;902;12;914 +81240;Saint-André;100;4;104 +81242;Saint-Avit;265;3;268 +81243;Saint-Beauzile;129;2;131 +81244;Saint-Benoît-de-Carmaux;2165;37;2202 +81245;Saint-Christophe;125;6;131 +81247;Saint-Cirgue;210;4;214 +81248;Saint-Gauzens;855;19;874 +81250;Saint-Genest-de-Contest;289;9;298 +81251;Saint-Germain-des-Prés;915;18;933 +81252;Saint-Germier;160;1;161 +81253;Saint-Grégoire;462;7;469 +81254;Saint-Jean-de-Marcel;368;7;375 +81255;Saint-Jean-de-Rives;497;12;509 +81256;Saint-Jean-de-Vals;75;1;76 +81257;Saint-Juéry;6818;114;6932 +81258;Saint-Julien-du-Puy;431;17;448 +81259;Saint-Julien-Gaulène;215;1;216 +81261;Saint-Lieux-lès-Lavaur;1046;18;1064 +81262;Saint-Marcel-Campes;210;2;212 +81263;Saint-Martin-Laguépie;395;11;406 +81265;Saint-Michel-de-Vax;71;1;72 +81264;Saint-Michel-Labadié;94;2;96 +81266;Saint-Paul-Cap-de-Joux;1117;19;1136 +81267;Saint-Pierre-de-Trivisy;621;12;633 +81268;Saint-Salvi-de-Carcavès;72;4;76 +81269;Saint-Salvy-de-la-Balme;522;8;530 +81270;Saint-Sernin-lès-Lavaur;166;3;169 +81271;Saint-Sulpice-la-Pointe;9117;272;9389 +81272;Saint-Urcisse;212;1;213 +81246;Sainte-Cécile-du-Cayrou;113;2;115 +81326;Sainte-Croix;378;12;390 +81249;Sainte-Gemme;902;13;915 +81273;Saïx;3548;74;3622 +81274;Saliès;824;18;842 +81275;Salles;186;2;188 +81276;Salvagnac;1184;8;1192 +81277;Saussenac;587;9;596 +81278;Sauveterre;167;2;169 +81279;La Sauzière-Saint-Jean;267;7;274 +81280;Le Ségur;258;7;265 +81281;Sémalens;2013;53;2066 +81282;Senaux;33;0;33 +81283;Senouillac;1109;33;1142 +81284;Le Sequestre;1809;28;1837 +81285;Sérénac;487;2;489 +81286;Serviès;637;9;646 +81287;Sieurac;266;2;268 +81288;Sorèze;2836;63;2899 +81289;Soual;2549;40;2589 +81290;Souel;165;2;167 +81291;Taïx;468;6;474 +81292;Tanus;533;17;550 +81293;Tauriac;339;3;342 +81294;Técou;976;17;993 +81295;Teillet;443;5;448 +81233;Terre-de-Bancalié;1710;27;1737 +81297;Terssac;1193;28;1221 +81298;Teulat;496;12;508 +81299;Teyssode;372;15;387 +81300;Tonnac;108;2;110 +81302;Tréban;45;0;45 +81303;Trébas;409;7;416 +81304;Trévien;184;4;188 +81305;Vabre;774;20;794 +81306;Valderiès;852;12;864 +81307;Valdurenque;835;18;853 +81308;Valence-d'Albigeois;1316;28;1344 +81309;Vaour;317;15;332 +81310;Veilhes;144;3;147 +81311;Vénès;813;22;835 +81312;Verdalle;992;175;1167 +81313;Le Verdier;224;6;230 +81314;Viane;534;40;574 +81315;Vielmur-sur-Agout;1464;51;1515 +81316;Vieux;224;5;229 +81317;Villefranche-d'Albigeois;1256;29;1285 +81318;Villeneuve-lès-Lavaur;148;2;150 +81319;Villeneuve-sur-Vère;494;14;508 +81320;Vindrac-Alayrac;150;4;154 +81321;Le Vintrou;85;1;86 +81322;Virac;234;6;240 +81323;Viterbe;361;6;367 +81324;Viviers-lès-Lavaur;221;4;225 +81325;Viviers-lès-Montagnes;1930;36;1966 +82001;Albefeuille-Lagarde;633;18;651 +82002;Albias;3246;55;3301 +82003;Angeville;242;5;247 +82004;Asques;132;2;134 +82005;Aucamville;1446;19;1465 +82006;Auterive;79;3;82 +82007;Auty;145;1;146 +82008;Auvillar;918;42;960 +82009;Balignac;41;2;43 +82010;Bardigues;296;1;297 +82011;Barry-d'Islemade;935;14;949 +82012;Les Barthes;567;8;575 +82013;Beaumont-de-Lomagne;3758;175;3933 +82014;Beaupuy;265;6;271 +82015;Belbèze-en-Lomagne;128;0;128 +82016;Belvèze;209;2;211 +82017;Bessens;1506;7;1513 +82018;Bioule;1113;31;1144 +82019;Boudou;731;16;747 +82020;Bouillac;629;15;644 +82021;Bouloc-en-Quercy;189;3;192 +82022;Bourg-de-Visa;382;10;392 +82023;Bourret;924;11;935 +82024;Brassac;248;3;251 +82025;Bressols;3697;104;3801 +82026;Bruniquel;608;9;617 +82027;Campsas;1368;22;1390 +82028;Canals;764;10;774 +82029;Castanet;289;1;290 +82030;Castelferrus;473;3;476 +82031;Castelmayran;1210;16;1226 +82032;Castelsagrat;569;14;583 +82033;Castelsarrasin;13944;323;14267 +82034;Castéra-Bouzet;109;3;112 +82035;Caumont;318;5;323 +82036;Le Causé;137;2;139 +82037;Caussade;6863;241;7104 +82038;Caylus;1446;12;1458 +82039;Cayrac;549;22;571 +82040;Cayriech;277;9;286 +82041;Cazals;225;3;228 +82042;Cazes-Mondenard;1185;21;1206 +82043;Comberouger;280;10;290 +82044;Corbarieu;1654;52;1706 +82045;Cordes-Tolosannes;353;6;359 +82046;Coutures;107;0;107 +82047;Cumont;52;0;52 +82048;Dieupentale;1700;18;1718 +82049;Donzac;1045;13;1058 +82050;Dunes;1200;24;1224 +82051;Durfort-Lacapelette;847;91;938 +82052;Escatalens;1097;91;1188 +82053;Escazeaux;289;3;292 +82054;Espalais;388;7;395 +82055;Esparsac;250;8;258 +82056;Espinas;174;4;178 +82057;Fabas;621;14;635 +82058;Fajolles;98;2;100 +82059;Faudoas;289;10;299 +82060;Fauroux;225;5;230 +82061;Féneyrols;147;2;149 +82062;Finhan;1525;19;1544 +82063;Garganvillar;677;13;690 +82064;Gariès;114;1;115 +82065;Gasques;412;9;421 +82066;Génébrières;633;13;646 +82067;Gensac;114;1;115 +82068;Gimat;230;8;238 +82069;Ginals;207;6;213 +82070;Glatens;74;2;76 +82071;Goas;37;2;39 +82072;Golfech;985;25;1010 +82073;Goudourville;955;32;987 +82074;Gramont;141;5;146 +82075;Grisolles;4115;54;4169 +82076;L' Honor-de-Cos;1577;35;1612 +82077;Labarthe;394;5;399 +82078;Labastide-de-Penne;129;0;129 +82080;Labastide-du-Temple;1125;27;1152 +82079;Labastide-Saint-Pierre;3742;96;3838 +82081;Labourgade;183;3;186 +82082;Lacapelle-Livron;200;6;206 +82083;Lachapelle;118;1;119 +82084;Lacour;171;5;176 +82085;Lacourt-Saint-Pierre;1201;11;1212 +82086;Lafitte;228;3;231 +82087;Lafrançaise;2850;66;2916 +82088;Laguépie;608;13;621 +82089;Lamagistère;1154;18;1172 +82090;Lamothe-Capdeville;1073;30;1103 +82091;Lamothe-Cumont;123;3;126 +82092;Lapenche;276;3;279 +82093;Larrazet;687;8;695 +82094;Lauzerte;1454;17;1471 +82095;Lavaurette;218;7;225 +82097;Lavit;1589;18;1607 +82098;Léojac;1284;40;1324 +82099;Lizac;510;11;521 +82100;Loze;144;3;147 +82101;Malause;1158;26;1184 +82102;Mansonville;288;4;292 +82103;Marignac;111;6;117 +82104;Marsac;176;5;181 +82105;Mas-Grenier;1322;18;1340 +82106;Maubec;135;1;136 +82107;Maumusson;48;1;49 +82108;Meauzac;1338;27;1365 +82109;Merles;202;13;215 +82110;Mirabel;1036;18;1054 +82111;Miramont-de-Quercy;323;9;332 +82112;Moissac;13039;339;13378 +82113;Molières;1174;24;1198 +82114;Monbéqui;634;7;641 +82115;Monclar-de-Quercy;1993;18;2011 +82116;Montagudet;197;1;198 +82117;Montaigu-de-Quercy;1323;25;1348 +82118;Montaïn;105;1;106 +82119;Montalzat;658;19;677 +82120;Montastruc;311;5;316 +82121;Montauban;60810;1480;62290 +82122;Montbarla;179;3;182 +82123;Montbartier;1331;21;1352 +82124;Montbeton;4279;80;4359 +82125;Montech;6349;120;6469 +82126;Monteils;1361;68;1429 +82127;Montesquieu;759;18;777 +82128;Montfermier;105;3;108 +82129;Montgaillard;144;4;148 +82130;Montjoi;165;1;166 +82131;Montpezat-de-Quercy;1567;35;1602 +82132;Montricoux;1207;11;1218 +82133;Mouillac;98;1;99 +82134;Nègrepelisse;5628;79;5707 +82135;Nohic;1369;28;1397 +82136;Orgueil;1658;32;1690 +82137;Parisot;600;7;607 +82138;Perville;143;1;144 +82139;Le Pin;123;3;126 +82140;Piquecos;434;3;437 +82141;Pommevic;547;4;551 +82142;Pompignan;1465;19;1484 +82143;Poupas;82;0;82 +82144;Puycornet;731;11;742 +82146;Puygaillard-de-Lomagne;69;2;71 +82145;Puygaillard-de-Quercy;391;4;395 +82147;Puylagarde;334;8;342 +82148;Puylaroque;698;25;723 +82149;Réalville;1910;42;1952 +82150;Reyniès;860;28;888 +82151;Roquecor;408;10;418 +82152;Saint-Aignan;405;11;416 +82154;Saint-Amans-de-Pellagal;215;5;220 +82153;Saint-Amans-du-Pech;216;1;217 +82155;Saint-Antonin-Noble-Val;1852;45;1897 +82156;Saint-Arroumex;152;3;155 +82157;Saint-Beauzeil;98;2;100 +82158;Saint-Cirice;155;5;160 +82159;Saint-Cirq;548;17;565 +82160;Saint-Clair;273;8;281 +82161;Saint-Étienne-de-Tulmont;3788;74;3862 +82162;Saint-Georges;261;7;268 +82163;Saint-Jean-du-Bouzet;52;0;52 +82165;Saint-Loup;520;4;524 +82166;Saint-Michel;255;3;258 +82167;Saint-Nauphary;1843;40;1883 +82168;Saint-Nazaire-de-Valentane;351;3;354 +82169;Saint-Nicolas-de-la-Grave;2260;29;2289 +82170;Saint-Paul-d'Espis;578;16;594 +82171;Saint-Porquier;1404;23;1427 +82172;Saint-Projet;283;9;292 +82173;Saint-Sardos;1143;14;1157 +82174;Saint-Vincent-d'Autéjac;285;2;287 +82175;Saint-Vincent-Lespinasse;258;3;261 +82164;Sainte-Juliette;132;3;135 +82176;La Salvetat-Belmontet;818;12;830 +82177;Sauveterre;170;3;173 +82178;Savenès;803;17;820 +82179;Septfonds;2212;49;2261 +82180;Sérignac;539;4;543 +82181;Sistels;211;3;214 +82182;Touffailles;346;3;349 +82183;Tréjouls;242;10;252 +82184;Vaïssac;870;10;880 +82185;Valeilles;248;6;254 +82186;Valence;5221;156;5377 +82187;Varen;654;15;669 +82188;Varennes;591;15;606 +82189;Vazerac;722;13;735 +82190;Verdun-sur-Garonne;4764;65;4829 +82191;Verfeil;395;3;398 +82192;Verlhac-Tescou;519;14;533 +82193;Vigueron;134;3;137 +82096;La Ville-Dieu-du-Temple;3191;43;3234 +82194;Villebrumier;1387;19;1406 +82195;Villemade;744;25;769 +83001;Les Adrets-de-l'Estérel;2750;65;2815 +83002;Aiguines;276;2;278 +83003;Ampus;934;24;958 +83004;Les Arcs;7064;173;7237 +83005;Artignosc-sur-Verdon;314;8;322 +83006;Artigues;260;7;267 +83007;Aups;2228;35;2263 +83008;Bagnols-en-Forêt;2788;56;2844 +83009;Bandol;8409;145;8554 +83010;Bargème;217;1;218 +83011;Bargemon;1365;22;1387 +83012;Barjols;2979;41;3020 +83013;La Bastide;205;1;206 +83014;Baudinard-sur-Verdon;224;4;228 +83015;Bauduen;318;4;322 +83016;Le Beausset;9736;171;9907 +83017;Belgentier;2429;32;2461 +83018;Besse-sur-Issole;3039;46;3085 +83019;Bormes-les-Mimosas;8102;116;8218 +83020;Le Bourguet;35;1;36 +83021;Bras;2698;53;2751 +83022;Brenon;29;0;29 +83023;Brignoles;17179;353;17532 +83025;Brue-Auriac;1376;25;1401 +83026;Cabasse;1947;37;1984 +83027;La Cadière-d'Azur;5550;98;5648 +83028;Callas;1909;36;1945 +83029;Callian;3206;60;3266 +83030;Camps-la-Source;1906;38;1944 +83031;Le Cannet-des-Maures;4300;59;4359 +83032;Carcès;3447;82;3529 +83033;Carnoules;3448;34;3482 +83034;Carqueiranne;9700;168;9868 +83035;Le Castellet;3886;41;3927 +83036;Cavalaire-sur-Mer;7385;84;7469 +83037;La Celle;1477;56;1533 +83038;Châteaudouble;473;12;485 +83039;Châteauvert;145;37;182 +83040;Châteauvieux;83;1;84 +83041;Claviers;692;13;705 +83042;Cogolin;11736;256;11992 +83043;Collobrières;1908;89;1997 +83044;Comps-sur-Artuby;364;5;369 +83045;Correns;903;8;911 +83046;Cotignac;2163;40;2203 +83047;La Crau;18288;418;18706 +83048;La Croix-Valmer;3780;121;3901 +83049;Cuers;11425;132;11557 +83050;Draguignan;39340;894;40234 +83051;Entrecasteaux;1123;25;1148 +83052;Esparron;356;5;361 +83053;Évenos;2405;51;2456 +83054;La Farlède;9083;112;9195 +83055;Fayence;5792;89;5881 +83056;Figanières;2605;54;2659 +83057;Flassans-sur-Issole;3533;66;3599 +83058;Flayosc;4294;102;4396 +83059;Forcalqueiret;2990;47;3037 +83060;Fox-Amphoux;459;4;463 +83061;Fréjus;52672;840;53512 +83062;La Garde;25126;354;25480 +83063;La Garde-Freinet;1887;33;1920 +83064;Garéoult;5330;99;5429 +83065;Gassin;2560;63;2623 +83066;Ginasservis;1799;35;1834 +83067;Gonfaron;4318;62;4380 +83068;Grimaud;4541;60;4601 +83069;Hyères;55588;983;56571 +83070;Le Lavandou;5985;62;6047 +83071;La Londe-les-Maures;10297;132;10429 +83072;Lorgues;8990;288;9278 +83073;Le Luc;11067;109;11176 +83074;La Martre;211;5;216 +83075;Les Mayons;644;12;656 +83076;Mazaugues;889;13;902 +83077;Méounes-lès-Montrieux;2184;20;2204 +83078;Moissac-Bellevue;291;7;298 +83079;La Môle;1432;25;1457 +83080;Mons;817;17;834 +83081;Montauroux;6411;128;6539 +83082;Montferrat;1536;23;1559 +83083;Montfort-sur-Argens;1349;17;1366 +83084;Montmeyan;551;3;554 +83085;La Motte;2845;51;2896 +83086;Le Muy;9134;246;9380 +83087;Nans-les-Pins;4627;82;4709 +83088;Néoules;2712;54;2766 +83089;Ollières;646;22;668 +83090;Ollioules;13702;270;13972 +83091;Pierrefeu-du-Var;6045;104;6149 +83092;Pignans;4201;45;4246 +83093;Plan-d'Aups-Sainte-Baume;2158;26;2184 +83094;Le Plan-de-la-Tour;2827;48;2875 +83095;Pontevès;748;18;766 +83096;Pourcieux;1564;22;1586 +83097;Pourrières;5155;89;5244 +83098;Le Pradet;10249;166;10415 +83099;Puget-sur-Argens;8097;121;8218 +83100;Puget-Ville;4280;50;4330 +83101;Ramatuelle;2070;46;2116 +83152;Rayol-Canadel-sur-Mer;711;12;723 +83102;Régusse;2613;14;2627 +83103;Le Revest-les-Eaux;3865;88;3953 +83104;Rians;4232;62;4294 +83105;Riboux;46;0;46 +83106;Rocbaron;5033;63;5096 +83109;La Roque-Esclapon;267;0;267 +83107;Roquebrune-sur-Argens;14251;208;14459 +83108;La Roquebrussanne;2455;45;2500 +83110;Rougiers;1656;30;1686 +83154;Saint-Antonin-du-Var;741;13;754 +83112;Saint-Cyr-sur-Mer;11761;195;11956 +83113;Saint-Julien;2409;41;2450 +83153;Saint-Mandrier-sur-Mer;5862;69;5931 +83114;Saint-Martin-de-Pallières;244;4;248 +83116;Saint-Maximin-la-Sainte-Baume;16433;455;16888 +83117;Saint-Paul-en-Forêt;1730;43;1773 +83118;Saint-Raphaël;35042;571;35613 +83119;Saint-Tropez;4352;87;4439 +83120;Saint-Zacharie;5604;78;5682 +83111;Sainte-Anastasie-sur-Issole;1973;24;1997 +83115;Sainte-Maxime;13968;215;14183 +83121;Salernes;3840;78;3918 +83122;Les Salles-sur-Verdon;245;4;249 +83123;Sanary-sur-Mer;16605;238;16843 +83124;Seillans;2669;31;2700 +83125;Seillons-Source-d'Argens;2468;37;2505 +83126;La Seyne-sur-Mer;63936;781;64717 +83127;Signes;2844;44;2888 +83128;Sillans-la-Cascade;752;55;807 +83129;Six-Fours-les-Plages;32829;593;33422 +83130;Solliès-Pont;11149;161;11310 +83131;Solliès-Toucas;5719;108;5827 +83132;Solliès-Ville;2450;44;2494 +83133;Tanneron;1666;33;1699 +83134;Taradeau;1803;34;1837 +83135;Tavernes;1399;15;1414 +83136;Le Thoronet;2462;37;2499 +83137;Toulon;171953;1807;173760 +83138;Tourrettes;2884;51;2935 +83139;Tourtour;581;14;595 +83140;Tourves;5025;72;5097 +83141;Trans-en-Provence;5847;136;5983 +83142;Trigance;191;3;194 +83143;Le Val;4295;96;4391 +83144;La Valette-du-Var;23884;247;24131 +83145;Varages;1178;15;1193 +83146;La Verdière;1601;14;1615 +83147;Vérignon;10;1;11 +83148;Vidauban;11907;104;12011 +83149;Villecroze;1463;28;1491 +83150;Vinon-sur-Verdon;4233;88;4321 +83151;Vins-sur-Caramy;1014;18;1032 +84001;Althen-des-Paluds;2823;45;2868 +84002;Ansouis;1023;47;1070 +84003;Apt;11425;237;11662 +84004;Aubignan;5661;91;5752 +84005;Aurel;206;2;208 +84006;Auribeau;71;4;75 +84007;Avignon;91921;1750;93671 +84008;Le Barroux;629;52;681 +84009;La Bastide-des-Jourdans;1566;93;1659 +84010;La Bastidonne;817;21;838 +84011;Le Beaucet;351;9;360 +84012;Beaumes-de-Venise;2409;27;2436 +84013;Beaumettes;255;3;258 +84014;Beaumont-de-Pertuis;1137;15;1152 +84015;Beaumont-du-Ventoux;280;3;283 +84016;Bédarrides;5171;74;5245 +84017;Bédoin;3099;69;3168 +84018;Blauvac;511;8;519 +84019;Bollène;13504;240;13744 +84020;Bonnieux;1315;25;1340 +84021;Brantes;86;3;89 +84022;Buisson;298;9;307 +84023;Buoux;68;5;73 +84024;Cabrières-d'Aigues;955;21;976 +84025;Cabrières-d'Avignon;1816;37;1853 +84026;Cadenet;4190;76;4266 +84027;Caderousse;2667;48;2715 +84028;Cairanne;1072;13;1085 +84029;Camaret-sur-Aigues;4543;112;4655 +84030;Caromb;3348;58;3406 +84031;Carpentras;28309;835;29144 +84032;Caseneuve;489;8;497 +84033;Castellet-en-Luberon;131;4;135 +84034;Caumont-sur-Durance;4885;99;4984 +84035;Cavaillon;26641;434;27075 +84036;Châteauneuf-de-Gadagne;3311;73;3384 +84037;Châteauneuf-du-Pape;2116;31;2147 +84038;Cheval-Blanc;4276;75;4351 +84039;Courthézon;5639;73;5712 +84040;Crestet;412;17;429 +84041;Crillon-le-Brave;470;18;488 +84042;Cucuron;1766;33;1799 +84043;Entraigues-sur-la-Sorgue;8472;120;8592 +84044;Entrechaux;1112;33;1145 +84045;Faucon;433;8;441 +84046;Flassan;465;13;478 +84139;Fontaine-de-Vaucluse;604;16;620 +84047;Gargas;3039;48;3087 +84048;Gignac;68;4;72 +84049;Gigondas;501;12;513 +84050;Gordes;1773;36;1809 +84051;Goult;1099;27;1126 +84052;Grambois;1251;30;1281 +84053;Grillon;1750;31;1781 +84054;L' Isle-sur-la-Sorgue;19421;470;19891 +84055;Jonquerettes;1507;29;1536 +84056;Jonquières;5399;63;5462 +84057;Joucas;338;5;343 +84058;Lacoste;409;7;416 +84059;Lafare;116;1;117 +84060;Lagarde-d'Apt;36;0;36 +84061;Lagarde-Paréol;330;15;345 +84062;Lagnes;1635;32;1667 +84063;Lamotte-du-Rhône;398;1;399 +84064;Lapalud;3805;68;3873 +84065;Lauris;3856;67;3923 +84066;Lioux;288;4;292 +84067;Loriol-du-Comtat;2603;48;2651 +84068;Lourmarin;1076;23;1099 +84069;Malaucène;2903;52;2955 +84070;Malemort-du-Comtat;1782;22;1804 +84071;Maubec;1930;48;1978 +84072;Mazan;6036;153;6189 +84073;Ménerbes;990;17;1007 +84074;Mérindol;2097;23;2120 +84075;Méthamis;436;3;439 +84076;Mirabeau;1288;38;1326 +84077;Modène;453;7;460 +84078;Mondragon;3792;64;3856 +84079;Monieux;317;5;322 +84080;Monteux;12909;222;13131 +84081;Morières-lès-Avignon;8317;123;8440 +84082;Mormoiron;1873;49;1922 +84083;Mornas;2407;46;2453 +84084;La Motte-d'Aigues;1334;40;1374 +84085;Murs;419;6;425 +84086;Oppède;1332;28;1360 +84087;Orange;28919;647;29566 +84088;Pernes-les-Fontaines;9620;263;9883 +84089;Pertuis;20380;350;20730 +84090;Peypin-d'Aigues;674;17;691 +84091;Piolenc;5253;104;5357 +84092;Le Pontet;17530;155;17685 +84093;Puget;769;21;790 +84094;Puyméras;595;12;607 +84095;Puyvert;817;14;831 +84096;Rasteau;846;22;868 +84097;Richerenches;619;82;701 +84098;Roaix;644;9;653 +84099;Robion;4531;72;4603 +84100;La Roque-Alric;51;0;51 +84101;La Roque-sur-Pernes;415;11;426 +84102;Roussillon;1305;31;1336 +84103;Rustrel;688;20;708 +84104;Sablet;1284;31;1315 +84105;Saignon;980;21;1001 +84107;Saint-Christol;1345;4;1349 +84108;Saint-Didier;2144;44;2188 +84109;Saint-Hippolyte-le-Graveyron;178;9;187 +84110;Saint-Léger-du-Ventoux;34;0;34 +84111;Saint-Marcellin-lès-Vaison;312;11;323 +84112;Saint-Martin-de-Castillon;781;16;797 +84113;Saint-Martin-de-la-Brasque;840;17;857 +84114;Saint-Pantaléon;200;3;203 +84115;Saint-Pierre-de-Vassols;525;12;537 +84116;Saint-Romain-en-Viennois;802;19;821 +84117;Saint-Roman-de-Malegarde;325;5;330 +84118;Saint-Saturnin-lès-Apt;2811;67;2878 +84119;Saint-Saturnin-lès-Avignon;4846;110;4956 +84120;Saint-Trinit;121;1;122 +84106;Sainte-Cécile-les-Vignes;2505;54;2559 +84121;Sannes;240;7;247 +84122;Sarrians;6065;74;6139 +84123;Sault;1381;23;1404 +84124;Saumane-de-Vaucluse;948;16;964 +84125;Savoillan;63;0;63 +84126;Séguret;844;24;868 +84127;Sérignan-du-Comtat;2676;75;2751 +84128;Sivergues;43;1;44 +84129;Sorgues;18680;244;18924 +84130;Suzette;119;3;122 +84131;Taillades;1909;40;1949 +84132;Le Thor;9071;151;9222 +84133;La Tour-d'Aigues;4287;142;4429 +84134;Travaillan;722;14;736 +84135;Uchaux;1649;55;1704 +84136;Vacqueyras;1308;30;1338 +84137;Vaison-la-Romaine;5999;138;6137 +84138;Valréas;9422;230;9652 +84140;Vaugines;568;20;588 +84141;Vedène;11259;370;11629 +84142;Velleron;2960;53;3013 +84143;Venasque;1012;17;1029 +84144;Viens;636;18;654 +84145;Villars;776;15;791 +84146;Villedieu;504;16;520 +84147;Villelaure;3477;71;3548 +84148;Villes-sur-Auzon;1287;34;1321 +84149;Violès;1677;33;1710 +84150;Visan;1983;57;2040 +84151;Vitrolles-en-Lubéron;164;4;168 +85152;Les Achards;5063;103;5166 +85001;L' Aiguillon-sur-Mer;2081;35;2116 +85002;L' Aiguillon-sur-Vie;1965;23;1988 +85003;Aizenay;9510;155;9665 +85004;Angles;2816;36;2852 +85005;Antigny;1059;20;1079 +85006;Apremont;1814;18;1832 +85008;Aubigny-Les Clouzeaux;6571;100;6671 +85009;Auchay-sur-Vendée;1151;24;1175 +85010;Avrillé;1420;8;1428 +85011;Barbâtre;1724;48;1772 +85012;La Barre-de-Monts;2199;48;2247 +85013;Bazoges-en-Paillers;1419;17;1436 +85014;Bazoges-en-Pareds;1153;27;1180 +85015;Beaufou;1508;20;1528 +85016;Beaulieu-sous-la-Roche;2212;29;2241 +85017;Beaurepaire;2401;48;2449 +85018;Beauvoir-sur-Mer;3904;60;3964 +85019;Bellevigny;6005;119;6124 +85020;Benet;4011;75;4086 +85022;Le Bernard;1216;17;1233 +85021;La Bernardière;1815;33;1848 +85023;Bessay;426;9;435 +85024;Bois-de-Céné;2001;34;2035 +85025;La Boissière-de-Montaigu;2251;51;2302 +85026;La Boissière-des-Landes;1388;18;1406 +85028;Bouillé-Courdault;599;8;607 +85029;Bouin;2156;35;2191 +85031;Le Boupère;3150;42;3192 +85033;Bourneau;734;19;753 +85034;Bournezeau;3373;99;3472 +85243;Brem-sur-Mer;2720;47;2767 +85035;Bretignolles-sur-Mer;4669;81;4750 +85036;La Bretonnière-la-Claye;575;8;583 +85037;Breuil-Barret;630;17;647 +85038;Les Brouzils;2799;43;2842 +85039;La Bruffière;3943;60;4003 +85040;La Caillère-Saint-Hilaire;1111;23;1134 +85041;Cezais;300;11;311 +85042;Chaillé-les-Marais;1896;25;1921 +85045;La Chaize-Giraud;1068;14;1082 +85046;La Chaize-le-Vicomte;3770;58;3828 +85047;Challans;20622;696;21318 +85050;Le Champ-Saint-Père;1837;23;1860 +85049;Champagné-les-Marais;1772;16;1788 +85051;Chantonnay;8318;414;8732 +85302;Chanverrie;5517;133;5650 +85053;La Chapelle-aux-Lys;253;3;256 +85054;La Chapelle-Hermier;898;9;907 +85055;La Chapelle-Palluau;946;18;964 +85056;La Chapelle-Thémer;385;9;394 +85058;Chasnais;728;20;748 +85059;La Châtaigneraie;2544;35;2579 +85061;Château-Guibert;1521;32;1553 +85062;Châteauneuf;1056;19;1075 +85064;Chauché;2470;33;2503 +85065;Chavagnes-en-Paillers;3536;102;3638 +85066;Chavagnes-les-Redoux;828;18;846 +85067;Cheffois;977;17;994 +85070;Coëx;3176;53;3229 +85071;Commequiers;3505;48;3553 +85072;La Copechagnière;999;11;1010 +85073;Corpe;1033;16;1049 +85074;La Couture;218;3;221 +85076;Cugand;3498;92;3590 +85077;Curzon;513;8;521 +85078;Damvix;747;16;763 +85080;Doix lès Fontaines;1714;33;1747 +85081;Dompierre-sur-Yon;4244;79;4323 +85082;Les Epesses;2853;54;2907 +85083;L' Épine;1641;31;1672 +85084;Essarts en Bocage;8931;161;9092 +85086;Falleron;1598;15;1613 +85307;La Faute-sur-Mer;660;9;669 +85087;Faymoreau;202;4;206 +85088;Le Fenouiller;4711;127;4838 +85089;La Ferrière;5255;153;5408 +85092;Fontenay-le-Comte;13226;680;13906 +85093;Fougeré;1204;20;1224 +85094;Foussais-Payré;1130;30;1160 +85095;Froidfond;1876;21;1897 +85096;La Garnache;4995;98;5093 +85097;La Gaubretière;3060;67;3127 +85098;La Genétouze;1931;37;1968 +85099;Le Girouard;1050;19;1069 +85100;Givrand;2176;52;2228 +85101;Le Givre;508;5;513 +85102;Grand'Landes;670;9;679 +85103;Grosbreuil;2177;31;2208 +85104;Grues;851;14;865 +85105;Le Gué-de-Velluire;544;12;556 +85106;La Guérinière;1347;32;1379 +85108;L' Herbergement;3175;108;3283 +85109;Les Herbiers;15958;463;16421 +85110;L' Hermenault;913;15;928 +85111;L' Île-d'Elle;1520;19;1539 +85112;L' Île-d'Olonne;2694;57;2751 +85113;L' Île-d'Yeu;4809;100;4909 +85114;Jard-sur-Mer;2653;30;2683 +85115;La Jaudonnière;606;10;616 +85116;La Jonchère;450;6;456 +85117;Lairoux;619;19;638 +85118;Landeronde;2279;47;2326 +85119;Les Landes-Genusson;2387;42;2429 +85120;Landevieille;1389;30;1419 +85121;Le Langon;1028;32;1060 +85123;Liez;278;4;282 +85125;Loge-Fougereuse;387;4;391 +85126;Longèves;1323;49;1372 +85127;Longeville-sur-Mer;2466;26;2492 +85129;Les Lucs-sur-Boulogne;3463;71;3534 +85128;Luçon;9540;388;9928 +85130;Maché;1545;20;1565 +85131;Les Magnils-Reigniers;1576;42;1618 +85132;Maillé;760;14;774 +85133;Maillezais;939;24;963 +85134;Mallièvre;252;10;262 +85135;Mareuil-sur-Lay-Dissais;2813;125;2938 +85136;Marillet;115;1;116 +85137;Marsais-Sainte-Radégonde;489;14;503 +85138;Martinet;1136;12;1148 +85139;Le Mazeau;452;14;466 +85140;La Meilleraie-Tillay;1515;43;1558 +85141;Menomblet;664;11;675 +85142;La Merlatière;1000;23;1023 +85143;Mervent;1050;20;1070 +85144;Mesnard-la-Barotière;1440;25;1465 +85145;Monsireigne;972;16;988 +85146;Montaigu-Vendée;20126;618;20744 +85147;Montournais;1663;54;1717 +85148;Montreuil;798;25;823 +85197;Montréverd;3700;36;3736 +85149;Moreilles;422;5;427 +85151;Mortagne-sur-Sèvre;5930;167;6097 +85153;Mouchamps;2886;44;2930 +85155;Mouilleron-le-Captif;4928;104;5032 +85154;Mouilleron-Saint-Germain;1845;90;1935 +85156;Moutiers-les-Mauxfaits;2128;32;2160 +85157;Moutiers-sur-le-Lay;753;12;765 +85158;Mouzeuil-Saint-Martin;1216;25;1241 +85159;Nalliers;2315;47;2362 +85160;Nesmy;2883;44;2927 +85161;Nieul-le-Dolent;2487;25;2512 +85163;Noirmoutier-en-l'Île;4668;88;4756 +85164;Notre-Dame-de-Monts;2105;45;2150 +85189;Notre-Dame-de-Riez;2099;45;2144 +85167;L' Orbrie;797;18;815 +85169;Palluau;1102;8;1110 +85171;Péault;610;23;633 +85172;Le Perrier;2023;32;2055 +85174;Petosse;706;17;723 +85175;Les Pineaux;632;3;635 +85176;Pissotte;1143;35;1178 +85178;Le Poiré-sur-Vie;8509;217;8726 +85179;Poiroux;1090;16;1106 +85181;Pouillé;629;17;646 +85182;Pouzauges;5514;181;5695 +85184;Puy-de-Serre;318;7;325 +85185;Puyravault;663;6;669 +85186;La Rabatelière;989;15;1004 +85187;Réaumur;864;8;872 +85188;La Réorthe;1093;22;1115 +85162;Rives-d'Autise;2118;50;2168 +85213;Rives de l'Yon;4160;175;4335 +85191;La Roche-sur-Yon;54372;2994;57366 +85190;Rocheservière;3322;47;3369 +85192;Rochetrejoux;950;9;959 +85193;Rosnay;627;15;642 +85194;Les Sables-d'Olonne;44017;1428;45445 +85196;Saint-André-Goule-d'Oie;1832;15;1847 +85198;Saint-Aubin-des-Ormeaux;1335;16;1351 +85199;Saint-Aubin-la-Plaine;535;6;541 +85200;Saint-Avaugourd-des-Landes;1067;21;1088 +85201;Saint-Benoist-sur-Mer;474;6;480 +85204;Saint-Christophe-du-Ligneron;2554;42;2596 +85205;Saint-Cyr-des-Gâts;534;8;542 +85206;Saint-Cyr-en-Talmondais;379;4;383 +85207;Saint-Denis-du-Payré;385;9;394 +85208;Saint-Denis-la-Chevasse;2290;36;2326 +85209;Saint-Étienne-de-Brillouet;615;8;623 +85210;Saint-Étienne-du-Bois;2101;25;2126 +85215;Saint-Fulgent;3792;131;3923 +85218;Saint-Georges-de-Pointindoux;1668;15;1683 +85220;Saint-Germain-de-Prinçay;1535;26;1561 +85221;Saint-Gervais;2669;37;2706 +85222;Saint-Gilles-Croix-de-Vie;7655;224;7879 +85226;Saint-Hilaire-de-Riez;11169;212;11381 +85229;Saint-Hilaire-de-Voust;594;13;607 +85227;Saint-Hilaire-des-Loges;1950;54;2004 +85231;Saint-Hilaire-la-Forêt;802;14;816 +85232;Saint-Hilaire-le-Vouhis;1060;21;1081 +85233;Saint-Jean-de-Beugné;594;9;603 +85234;Saint-Jean-de-Monts;8634;209;8843 +85235;Saint-Juire-Champgillon;408;13;421 +85236;Saint-Julien-des-Landes;1773;20;1793 +85237;Saint-Laurent-de-la-Salle;357;11;368 +85238;Saint-Laurent-sur-Sèvre;3617;439;4056 +85239;Saint-Maixent-sur-Vie;1078;6;1084 +85240;Saint-Malô-du-Bois;1603;48;1651 +85242;Saint-Mars-la-Réorthe;978;13;991 +85244;Saint-Martin-de-Fraigneau;820;59;879 +85245;Saint-Martin-des-Fontaines;172;2;174 +85246;Saint-Martin-des-Noyers;2372;38;2410 +85247;Saint-Martin-des-Tilleuls;1069;18;1087 +85248;Saint-Martin-Lars-en-Sainte-Hermine;408;9;417 +85250;Saint-Mathurin;2270;35;2305 +85251;Saint-Maurice-des-Noues;648;18;666 +85252;Saint-Maurice-le-Girard;588;14;602 +85254;Saint-Mesmin;1766;26;1792 +85255;Saint-Michel-en-l'Herm;2352;78;2430 +85256;Saint-Michel-le-Cloucq;1289;32;1321 +85259;Saint-Paul-en-Pareds;1336;28;1364 +85260;Saint-Paul-Mont-Penit;811;11;822 +85262;Saint-Philbert-de-Bouaine;3424;37;3461 +85264;Saint-Pierre-du-Chemin;1336;20;1356 +85265;Saint-Pierre-le-Vieux;961;23;984 +85266;Saint-Prouant;1618;28;1646 +85268;Saint-Révérend;1430;17;1447 +85269;Saint-Sigismond;406;7;413 +85271;Saint-Sulpice-en-Pareds;430;12;442 +85273;Saint-Urbain;1818;35;1853 +85274;Saint-Valérien;526;13;539 +85276;Saint-Vincent-Sterlanges;789;13;802 +85277;Saint-Vincent-sur-Graon;1485;23;1508 +85278;Saint-Vincent-sur-Jard;1298;21;1319 +85202;Sainte-Cécile;1621;106;1727 +85211;Sainte-Flaive-des-Loups;2395;24;2419 +85214;Sainte-Foy;2215;43;2258 +85216;Sainte-Gemme-la-Plaine;2044;213;2257 +85223;Sainte-Hermine;2925;39;2964 +85261;Sainte-Pexine;257;11;268 +85267;Sainte-Radégonde-des-Noyers;916;18;934 +85280;Sallertaine;3099;70;3169 +85281;Sérigné;974;29;1003 +85090;Sèvremont;6486;217;6703 +85282;Sigournais;896;15;911 +85284;Soullans;4221;91;4312 +85285;Le Tablier;746;13;759 +85286;La Taillée;581;9;590 +85287;Tallud-Sainte-Gemme;470;4;474 +85288;Talmont-Saint-Hilaire;7657;179;7836 +85289;La Tardière;1312;26;1338 +85290;Thiré;570;12;582 +85291;Thorigny;1230;20;1250 +85292;Thouarsais-Bouildroux;770;10;780 +85293;Tiffauges;1588;40;1628 +85294;La Tranche-sur-Mer;2905;64;2969 +85295;Treize-Septiers;3209;81;3290 +85296;Treize-Vents;1259;25;1284 +85297;Triaize;1010;15;1025 +85298;Vairé;1665;29;1694 +85177;Les Velluire-sur-Vendée;1381;18;1399 +85300;Venansault;4644;163;4807 +85301;Vendrennes;1721;20;1741 +85303;Vix;1788;20;1808 +85304;Vouillé-les-Marais;755;10;765 +85305;Vouvant;867;48;915 +85306;Xanton-Chassenon;729;13;742 +86001;Adriers;719;8;727 +86002;Amberre;576;21;597 +86003;Anché;340;7;347 +86004;Angles-sur-l'Anglin;357;14;371 +86005;Angliers;629;22;651 +86006;Antigny;549;20;569 +86007;Antran;1192;32;1224 +86009;Archigny;1092;17;1109 +86008;Arçay;355;7;362 +86010;Aslonnes;1109;19;1128 +86011;Asnières-sur-Blour;182;4;186 +86012;Asnois;163;7;170 +86013;Aulnay;98;3;101 +86014;Availles-en-Châtellerault;1757;40;1797 +86015;Availles-Limouzine;1272;26;1298 +86016;Avanton;2175;29;2204 +86017;Ayron;1138;19;1157 +86018;Basses;323;2;325 +86019;Beaumont Saint-Cyr;3035;41;3076 +86020;Bellefonds;254;4;258 +86022;Berrie;263;4;267 +86023;Berthegon;306;4;310 +86024;Béruges;1469;25;1494 +86025;Béthines;473;5;478 +86026;Beuxes;553;4;557 +86027;Biard;1751;59;1810 +86028;Bignoux;1054;18;1072 +86029;Blanzay;787;26;813 +86123;Boivre-la-Vallée;3083;46;3129 +86031;Bonnes;1729;21;1750 +86032;Bonneuil-Matours;2104;60;2164 +86034;Bouresse;584;17;601 +86035;Bourg-Archambault;188;7;195 +86036;Bournand;878;19;897 +86037;Brigueil-le-Chantre;513;7;520 +86038;Brion;226;8;234 +86039;Brux;716;10;726 +86040;La Bussière;323;10;333 +86041;Buxerolles;10023;142;10165 +86042;Buxeuil;939;14;953 +86044;Ceaux-en-Loudun;553;12;565 +86045;Celle-Lévescault;1356;17;1373 +86046;Cenon-sur-Vienne;1778;30;1808 +86047;Cernay;477;13;490 +86048;Chabournay;1073;10;1083 +86049;Chalais;513;16;529 +86050;Chalandray;841;11;852 +86051;Champagné-le-Sec;200;4;204 +86052;Champagné-Saint-Hilaire;1010;20;1030 +86053;Champigny en Rochereau;1925;35;1960 +86054;Champniers;351;5;356 +86055;La Chapelle-Bâton;357;9;366 +86058;La Chapelle-Moulière;705;20;725 +86059;Chapelle-Viviers;561;4;565 +86061;Charroux;1136;29;1165 +86062;Chasseneuil-du-Poitou;4704;49;4753 +86063;Chatain;250;3;253 +86064;Château-Garnier;614;10;624 +86065;Château-Larcher;1025;17;1042 +86066;Châtellerault;31840;764;32604 +86068;Chaunay;1212;20;1232 +86069;La Chaussée;182;4;186 +86070;Chauvigny;7049;115;7164 +86072;Chenevelles;469;7;476 +86073;Cherves;572;10;582 +86074;Chiré-en-Montreuil;912;14;926 +86075;Chouppes;750;16;766 +86076;Cissé;2785;49;2834 +86077;Civaux;1203;16;1219 +86078;Civray;2658;130;2788 +86080;Cloué;496;5;501 +86081;Colombiers;1501;31;1532 +86083;Coulombiers;1164;12;1176 +86084;Coulonges;236;6;242 +86085;Coussay;251;4;255 +86086;Coussay-les-Bois;1003;14;1017 +86087;Craon;186;3;189 +86088;Croutelle;851;23;874 +86089;Cuhon;398;7;405 +86091;Curzay-sur-Vonne;410;5;415 +86090;Curçay-sur-Dive;213;1;214 +86092;Dangé-Saint-Romain;2981;41;3022 +86093;Dercé;155;3;158 +86094;Dienné;561;12;573 +86095;Dissay;3233;49;3282 +86096;Doussay;653;8;661 +86097;La Ferrière-Airoux;321;13;334 +86098;Fleix;136;1;137 +86099;Fleuré;1050;8;1058 +86100;Fontaine-le-Comte;3853;73;3926 +86102;Frozes;559;9;568 +86104;Genouillé;512;4;516 +86103;Gençay;1737;63;1800 +86105;Gizay;377;1;378 +86106;Glénouze;105;2;107 +86107;Gouex;491;8;499 +86108;La Grimaudière;397;12;409 +86109;Guesnes;222;7;229 +86110;Haims;225;4;229 +86111;Ingrandes;1750;37;1787 +86112;L' Isle-Jourdain;1163;14;1177 +86113;Iteuil;2940;47;2987 +86114;Jardres;1273;24;1297 +86115;Jaunay-Marigny;7530;236;7766 +86116;Jazeneuil;804;17;821 +86117;Jouhet;527;7;534 +86118;Journet;369;8;377 +86119;Joussé;303;4;307 +86120;Lathus-Saint-Rémy;1217;21;1238 +86121;Latillé;1440;26;1466 +86122;Lauthiers;68;3;71 +86124;Lavoux;1180;19;1199 +86125;Leigné-les-Bois;592;12;604 +86127;Leigné-sur-Usseau;475;3;478 +86126;Leignes-sur-Fontaine;637;13;650 +86128;Lencloître;2456;30;2486 +86129;Lésigny;537;2;539 +86130;Leugny;407;4;411 +86131;Lhommaizé;859;23;882 +86132;Liglet;312;3;315 +86133;Ligugé;3349;61;3410 +86134;Linazay;225;5;230 +86135;Liniers;561;11;572 +86136;Lizant;404;8;412 +86137;Loudun;6747;344;7091 +86138;Luchapt;249;2;251 +86139;Lusignan;2649;37;2686 +86140;Lussac-les-Châteaux;2318;45;2363 +86141;Magné;675;15;690 +86142;Maillé;668;9;677 +86143;Mairé;158;7;165 +86144;Maisonneuve;339;8;347 +86147;Marigny-Chemereau;601;12;613 +86148;Marnay;700;12;712 +86149;Martaizé;380;9;389 +86145;Marçay;1185;15;1200 +86150;Massognes;287;5;292 +86151;Maulay;182;7;189 +86152;Mauprévoir;603;15;618 +86153;Mazerolles;851;13;864 +86154;Mazeuil;253;5;258 +86156;Messemé;239;6;245 +86157;Mignaloux-Beauvoir;4577;174;4751 +86158;Migné-Auxances;6071;112;6183 +86159;Millac;553;15;568 +86160;Mirebeau;2218;33;2251 +86161;Moncontour;986;20;1006 +86162;Mondion;106;3;109 +86163;Montamisé;3630;58;3688 +86164;Monthoiron;662;9;671 +86165;Montmorillon;5954;462;6416 +86167;Monts-sur-Guesnes;895;5;900 +86169;Morton;346;5;351 +86170;Moulismes;373;11;384 +86171;Moussac;442;14;456 +86173;Mouterre-Silly;663;12;675 +86172;Mouterre-sur-Blourde;166;4;170 +86174;Naintré;5911;120;6031 +86175;Nalliers;320;10;330 +86176;Nérignac;123;4;127 +86177;Neuville-de-Poitou;5324;85;5409 +86178;Nieuil-l'Espoir;2718;37;2755 +86180;Nouaillé-Maupertuis;2751;73;2824 +86181;Nueil-sous-Faye;213;5;218 +86182;Orches;410;4;414 +86183;Les Ormes;1631;22;1653 +86184;Ouzilly;919;12;931 +86186;Oyré;973;25;998 +86187;Paizay-le-Sec;463;14;477 +86189;Payroux;490;12;502 +86190;Persac;770;19;789 +86191;Pindray;254;7;261 +86192;Plaisance;166;3;169 +86193;Pleumartin;1246;18;1264 +86194;Poitiers;88291;2412;90703 +86195;Port-de-Piles;566;12;578 +86197;Pouant;413;8;421 +86196;Pouançay;234;4;238 +86198;Pouillé;657;10;667 +86200;Pressac;576;4;580 +86201;Prinçay;217;2;219 +86202;La Puye;606;10;616 +86203;Queaux;524;13;537 +86204;Quinçay;2215;44;2259 +86205;Ranton;193;3;196 +86206;Raslay;132;5;137 +86207;La Roche-Posay;1561;30;1591 +86079;La Roche-Rigault;556;36;592 +86209;Roches-Prémarie-Andillé;2021;33;2054 +86210;Roiffé;759;11;770 +86211;Romagne;887;92;979 +86213;Rouillé;2468;203;2671 +86214;Saint-Benoît;7233;243;7476 +86217;Saint-Christophe;302;12;314 +86218;Saint-Clair;196;7;203 +86220;Saint-Gaudent;310;7;317 +86221;Saint-Genest-d'Ambière;1248;23;1271 +86222;Saint-Georges-lès-Baillargeaux;4168;65;4233 +86223;Saint-Germain;928;25;953 +86224;Saint-Gervais-les-Trois-Clochers;1314;25;1339 +86225;Saint-Jean-de-Sauves;1389;28;1417 +86226;Saint-Julien-l'Ars;2660;47;2707 +86227;Saint-Laon;126;4;130 +86228;Saint-Laurent-de-Jourdes;200;3;203 +86229;Saint-Léger-de-Montbrillais;349;5;354 +86230;Saint-Léomer;183;3;186 +86231;Saint-Macoux;474;17;491 +86234;Saint-Martin-l'Ars;386;4;390 +86281;Saint-Martin-la-Pallu;5546;96;5642 +86235;Saint-Maurice-la-Clouère;1312;35;1347 +86237;Saint-Pierre-d'Exideuil;754;18;772 +86236;Saint-Pierre-de-Maillé;881;16;897 +86241;Saint-Rémy-sur-Creuse;392;6;398 +86242;Saint-Romain;396;9;405 +86244;Saint-Sauvant;1258;25;1283 +86246;Saint-Savin;846;16;862 +86247;Saint-Saviol;532;8;540 +86248;Saint-Secondin;546;15;561 +86239;Sainte-Radégonde;169;0;169 +86249;Saires;132;6;138 +86250;Saix;290;5;295 +86252;Sammarçolles;642;13;655 +86253;Sanxay;548;11;559 +86254;Saulgé;1013;12;1025 +86255;Savigné;1336;29;1365 +86256;Savigny-Lévescault;1168;26;1194 +86257;Savigny-sous-Faye;383;5;388 +86258;Scorbé-Clairvaux;2259;31;2290 +86245;Senillé-Saint-Sauveur;1877;42;1919 +86260;Sérigny;312;1;313 +86261;Sèvres-Anxaumont;2181;79;2260 +86262;Sillars;611;14;625 +86263;Smarves;2810;41;2851 +86264;Sommières-du-Clain;788;17;805 +86265;Sossais;438;3;441 +86266;Surin;133;2;135 +86268;Tercé;1116;16;1132 +86269;Ternay;184;3;187 +86270;Thollet;156;3;159 +86271;Thurageau;814;14;828 +86272;Thuré;2878;152;3030 +86273;La Trimouille;889;23;912 +86274;Les Trois-Moutiers;1074;22;1096 +86275;Usseau;607;9;616 +86276;Usson-du-Poitou;1260;21;1281 +86233;Valdivienne;2747;42;2789 +86082;Valence-en-Poitou;4474;117;4591 +86279;Vaux-sur-Vienne;546;6;552 +86280;Vellèches;363;5;368 +86284;Vernon;704;20;724 +86285;Verrières;1004;30;1034 +86286;Verrue;391;2;393 +86287;Vézières;357;6;363 +86288;Vicq-sur-Gartempe;615;7;622 +86289;Le Vigeant;699;27;726 +86290;La Villedieu-du-Clain;1592;30;1622 +86291;Villemort;103;7;110 +86292;Villiers;893;17;910 +86293;Vivonne;4345;78;4423 +86294;Vouillé;3701;54;3755 +86295;Voulême;378;4;382 +86296;Voulon;467;7;474 +86297;Vouneuil-sous-Biard;5896;132;6028 +86298;Vouneuil-sur-Vienne;2198;31;2229 +86299;Vouzailles;600;7;607 +86300;Yversay;529;4;533 +87001;Aixe-sur-Vienne;5836;80;5916 +87002;Ambazac;5667;74;5741 +87003;Arnac-la-Poste;951;26;977 +87004;Augne;108;2;110 +87005;Aureil;1004;20;1024 +87006;Azat-le-Ris;257;2;259 +87007;Balledent;197;6;203 +87008;La Bazeuge;140;2;142 +87009;Beaumont-du-Lac;143;5;148 +87011;Bellac;3808;147;3955 +87012;Berneuil;426;5;431 +87013;Bersac-sur-Rivalier;631;18;649 +87014;Bessines-sur-Gartempe;2836;45;2881 +87015;Beynac;693;73;766 +87016;Les Billanges;288;6;294 +87017;Blanzac;495;12;507 +87018;Blond;693;24;717 +87019;Boisseuil;2928;54;2982 +87020;Bonnac-la-Côte;1701;29;1730 +87021;Bosmie-l'Aiguille;2579;35;2614 +87022;Breuilaufa;129;1;130 +87023;Le Buis;189;4;193 +87024;Bujaleuf;833;9;842 +87025;Burgnac;841;11;852 +87027;Bussière-Galant;1308;17;1325 +87029;Les Cars;632;11;643 +87030;Chaillac-sur-Vienne;1235;22;1257 +87031;Le Chalard;312;4;316 +87032;Châlus;1621;28;1649 +87033;Chamboret;789;10;799 +87034;Champagnac-la-Rivière;577;8;585 +87035;Champnétery;550;1;551 +87036;Champsac;671;11;682 +87037;La Chapelle-Montbrandeix;256;2;258 +87038;Chaptelat;2121;18;2139 +87039;Château-Chervix;799;13;812 +87040;Châteauneuf-la-Forêt;1524;20;1544 +87041;Châteauponsac;2035;24;2059 +87042;Le Châtenet-en-Dognon;393;7;400 +87043;Cheissoux;177;2;179 +87044;Chéronnac;336;4;340 +87045;Cieux;989;13;1002 +87046;Cognac-la-Forêt;1185;9;1194 +87047;Compreignac;1838;16;1854 +87048;Condat-sur-Vienne;5150;79;5229 +87049;Coussac-Bonneval;1317;34;1351 +87050;Couzeix;9268;158;9426 +87051;La Croisille-sur-Briance;641;13;654 +87052;La Croix-sur-Gartempe;188;1;189 +87053;Cromac;246;2;248 +87054;Cussac;1235;24;1259 +87056;Dinsac;271;6;277 +87057;Dompierre-les-Églises;367;5;372 +87058;Domps;118;1;119 +87059;Le Dorat;1683;68;1751 +87060;Dournazac;657;9;666 +87061;Droux;350;6;356 +87062;Eybouleuf;436;8;444 +87063;Eyjeaux;1321;28;1349 +87064;Eymoutiers;2062;22;2084 +87065;Feytiat;6123;85;6208 +87066;Flavignac;1061;12;1073 +87067;Folles;486;9;495 +87068;Fromental;540;17;557 +87069;Gajoubert;145;1;146 +87070;La Geneytouse;958;15;973 +87071;Glandon;781;18;799 +87072;Glanges;512;10;522 +87073;Gorre;401;9;410 +87074;Les Grands-Chézeaux;246;2;248 +87075;Isle;7696;146;7842 +87076;Jabreilles-les-Bordes;239;2;241 +87077;Janailhac;536;9;545 +87078;Javerdat;717;5;722 +87079;La Jonchère-Saint-Maurice;824;11;835 +87080;Jouac;181;4;185 +87081;Jourgnac;1110;20;1130 +87082;Ladignac-le-Long;1168;12;1180 +87083;Laurière;568;4;572 +87084;Lavignac;153;4;157 +87085;Limoges;132175;2285;134460 +87086;Linards;1057;17;1074 +87087;Lussac-les-Églises;532;11;543 +87088;Magnac-Bourg;1089;12;1101 +87089;Magnac-Laval;1744;150;1894 +87090;Mailhac-sur-Benaize;270;5;275 +87091;Maisonnais-sur-Tardoire;390;7;397 +87092;Marval;540;6;546 +87093;Masléon;284;2;286 +87094;Meilhac;529;5;534 +87095;Meuzac;731;14;745 +87096;La Meyze;828;20;848 +87099;Moissannes;360;16;376 +87100;Montrol-Sénard;278;7;285 +87101;Mortemart;112;1;113 +87103;Nantiat;1598;24;1622 +87104;Nedde;464;5;469 +87105;Neuvic-Entier;929;17;946 +87106;Nexon;2539;46;2585 +87107;Nieul;1647;18;1665 +87108;Nouic;467;6;473 +87109;Oradour-Saint-Genest;333;35;368 +87110;Oradour-sur-Glane;2473;22;2495 +87111;Oradour-sur-Vayres;1500;20;1520 +87112;Pageas;580;13;593 +87113;Le Palais-sur-Vienne;6042;65;6107 +87114;Panazol;10972;208;11180 +87115;Pensol;180;2;182 +87116;Peyrat-de-Bellac;1065;24;1089 +87117;Peyrat-le-Château;1013;17;1030 +87118;Peyrilhac;1270;13;1283 +87119;Pierre-Buffière;1157;11;1168 +87120;La Porcherie;514;11;525 +87121;Rancon;494;11;505 +87122;Razès;1173;13;1186 +87123;Rempnat;149;4;153 +87124;Rilhac-Lastours;371;3;374 +87125;Rilhac-Rancon;4573;69;4642 +87127;La Roche-l'Abeille;618;10;628 +87126;Rochechouart;3778;49;3827 +87129;Royères;915;6;921 +87130;Roziers-Saint-Georges;180;1;181 +87131;Saillat-sur-Vienne;832;12;844 +87132;Saint-Amand-le-Petit;108;4;112 +87133;Saint-Amand-Magnazeix;523;8;531 +87135;Saint-Auvent;962;18;980 +87137;Saint-Bazile;112;1;113 +87138;Saint-Bonnet-Briance;574;14;588 +87139;Saint-Bonnet-de-Bellac;484;8;492 +87140;Saint-Brice-sur-Vienne;1669;17;1686 +87141;Saint-Cyr;693;8;701 +87142;Saint-Denis-des-Murs;529;7;536 +87143;Saint-Gence;2134;27;2161 +87144;Saint-Genest-sur-Roselle;520;5;525 +87145;Saint-Georges-les-Landes;239;1;240 +87146;Saint-Germain-les-Belles;1169;13;1182 +87147;Saint-Gilles-les-Forêts;43;2;45 +87148;Saint-Hilaire-Bonneval;988;12;1000 +87149;Saint-Hilaire-la-Treille;381;9;390 +87150;Saint-Hilaire-les-Places;870;14;884 +87151;Saint-Jean-Ligoure;515;9;524 +87152;Saint-Jouvent;1659;23;1682 +87153;Saint-Julien-le-Petit;288;0;288 +87154;Saint-Junien;11202;273;11475 +87155;Saint-Junien-les-Combes;174;7;181 +87156;Saint-Just-le-Martel;2677;46;2723 +87157;Saint-Laurent-les-Églises;865;37;902 +87158;Saint-Laurent-sur-Gorre;1500;20;1520 +87159;Saint-Léger-la-Montagne;348;5;353 +87160;Saint-Léger-Magnazeix;490;7;497 +87161;Saint-Léonard-de-Noblat;4554;112;4666 +87163;Saint-Martial-sur-Isop;136;4;140 +87164;Saint-Martin-de-Jussac;565;9;574 +87165;Saint-Martin-le-Mault;130;0;130 +87166;Saint-Martin-le-Vieux;922;16;938 +87167;Saint-Martin-Terressus;557;5;562 +87168;Saint-Mathieu;1080;15;1095 +87169;Saint-Maurice-les-Brousses;1060;7;1067 +87170;Saint-Méard;357;7;364 +87172;Saint-Ouen-sur-Gartempe;214;4;218 +87128;Saint-Pardoux-le-Lac;1322;16;1338 +87174;Saint-Paul;1236;23;1259 +87176;Saint-Priest-Ligoure;668;12;680 +87177;Saint-Priest-sous-Aixe;1746;20;1766 +87178;Saint-Priest-Taurion;2881;33;2914 +87179;Saint-Sornin-la-Marche;258;2;260 +87180;Saint-Sornin-Leulac;634;8;642 +87181;Saint-Sulpice-Laurière;837;20;857 +87182;Saint-Sulpice-les-Feuilles;1240;22;1262 +87183;Saint-Sylvestre;924;10;934 +87185;Saint-Victurnien;1755;29;1784 +87186;Saint-Vitte-sur-Briance;330;4;334 +87187;Saint-Yrieix-la-Perche;6766;433;7199 +87188;Saint-Yrieix-sous-Aixe;421;3;424 +87134;Sainte-Anne-Saint-Priest;168;2;170 +87162;Sainte-Marie-de-Vaux;209;3;212 +87189;Les Salles-Lavauguyon;144;1;145 +87190;Sauviat-sur-Vige;889;7;896 +87191;Séreilhac;1992;22;2014 +87192;Solignac;1579;23;1602 +87193;Surdoux;44;3;47 +87194;Sussac;351;3;354 +87195;Tersannes;138;2;140 +87197;Thouron;532;9;541 +87097;Val d'Issoire;1068;12;1080 +87028;Val-d'Oire-et-Gartempe;1671;35;1706 +87198;Vaulry;409;5;414 +87199;Vayres;750;16;766 +87200;Verneuil-Moustiers;128;0;128 +87201;Verneuil-sur-Vienne;4889;215;5104 +87202;Veyrac;2071;34;2105 +87203;Vicq-sur-Breuilh;1324;25;1349 +87204;Videix;211;3;214 +87205;Le Vigen;2171;41;2212 +87206;Villefavard;158;1;159 +88001;Les Ableuvenettes;62;0;62 +88002;Ahéville;69;0;69 +88003;Aingeville;61;2;63 +88004;Ainvelle;142;6;148 +88005;Allarmont;211;4;215 +88006;Ambacourt;297;8;305 +88007;Ameuvelle;49;0;49 +88008;Anglemont;167;3;170 +88009;Anould;3369;68;3437 +88010;Aouze;191;1;192 +88011;Arches;1638;53;1691 +88012;Archettes;1085;13;1098 +88013;Aroffe;80;0;80 +88014;Arrentès-de-Corcieux;179;5;184 +88015;Attignéville;217;3;220 +88016;Attigny;230;6;236 +88017;Aulnois;161;6;167 +88019;Autigny-la-Tour;159;3;162 +88020;Autreville;183;5;188 +88021;Autrey;286;10;296 +88022;Auzainvilliers;228;6;234 +88023;Avillers;84;2;86 +88024;Avrainville;111;0;111 +88025;Avranville;70;4;74 +88026;Aydoilles;1028;49;1077 +88027;Badménil-aux-Bois;154;6;160 +88028;La Baffe;634;95;729 +88030;Bainville-aux-Saules;137;0;137 +88031;Balléville;102;4;106 +88032;Ban-de-Laveline;1211;33;1244 +88033;Ban-de-Sapt;348;11;359 +88106;Ban-sur-Meurthe-Clefcy;949;28;977 +88035;Barbey-Seroux;148;4;152 +88036;Barville;91;1;92 +88037;Basse-sur-le-Rupt;864;27;891 +88038;Battexey;34;0;34 +88039;Baudricourt;328;6;334 +88040;Bayecourt;255;5;260 +88041;Bazegney;113;2;115 +88042;Bazien;78;1;79 +88043;Bazoilles-et-Ménil;114;4;118 +88044;Bazoilles-sur-Meuse;598;16;614 +88045;Beaufremont;90;0;90 +88046;Beauménil;125;4;129 +88047;Begnécourt;157;7;164 +88048;Bellefontaine;992;10;1002 +88049;Belmont-lès-Darney;112;2;114 +88050;Belmont-sur-Buttant;302;5;307 +88051;Belmont-sur-Vair;128;1;129 +88052;Belrupt;102;5;107 +88053;Belval;156;2;158 +88054;Bertrimoutier;310;10;320 +88055;Bettegney-Saint-Brice;169;2;171 +88056;Bettoncourt;96;1;97 +88057;Le Beulay;97;6;103 +88058;Biécourt;103;2;105 +88059;Biffontaine;408;12;420 +88060;Blémerey;28;1;29 +88061;Bleurville;308;12;320 +88062;Blevaincourt;108;1;109 +88063;Bocquegney;134;4;138 +88064;Bois-de-Champ;111;1;112 +88065;Bonvillet;300;5;305 +88066;Boulaincourt;71;3;74 +88068;La Bourgonce;896;21;917 +88069;Bouxières-aux-Bois;139;6;145 +88070;Bouxurulles;170;1;171 +88071;Bouzemont;52;1;53 +88073;Brantigny;211;4;215 +88074;Brechainville;61;0;61 +88075;La Bresse;4154;150;4304 +88076;Brouvelieures;446;8;454 +88077;Brû;562;13;575 +88078;Bruyères;3064;53;3117 +88079;Bulgnéville;1549;87;1636 +88080;Bult;308;2;310 +88081;Bussang;1383;23;1406 +88465;Capavenir Vosges;8862;239;9101 +88082;Celles-sur-Plaine;821;16;837 +88083;Certilleux;208;12;220 +88084;Chamagne;465;8;473 +88086;Champ-le-Duc;544;18;562 +88085;Champdray;179;0;179 +88087;Chantraine;3212;81;3293 +88088;La Chapelle-aux-Bois;668;8;676 +88089;La Chapelle-devant-Bruyères;576;13;589 +88090;Charmes;4689;53;4742 +88091;Charmois-devant-Bruyères;393;7;400 +88092;Charmois-l'Orgueilleux;587;8;595 +88093;Châtas;50;2;52 +88094;Châtel-sur-Moselle;1702;50;1752 +88095;Châtenois;1706;43;1749 +88096;Châtillon-sur-Saône;131;9;140 +88097;Chauffecourt;42;1;43 +88098;Chaumousey;908;26;934 +88099;Chavelot;1391;31;1422 +88100;Chef-Haut;46;2;48 +88101;Cheniménil;1219;23;1242 +88102;Chermisey;96;1;97 +88103;Circourt;88;2;90 +88104;Circourt-sur-Mouzon;189;10;199 +88105;Claudon;216;4;220 +88107;Clérey-la-Côte;32;0;32 +88108;Le Clerjus;568;16;584 +88109;Cleurie;651;13;664 +88110;Clézentaine;214;5;219 +88111;Coinches;360;3;363 +88113;Combrimont;134;5;139 +88114;Contrexéville;3202;222;3424 +88115;Corcieux;1538;14;1552 +88116;Cornimont;3208;62;3270 +88117;Courcelles-sous-Châtenois;79;1;80 +88118;Coussey;723;20;743 +88119;Crainvilliers;171;2;173 +88120;La Croix-aux-Mines;503;9;512 +88121;Damas-aux-Bois;268;6;274 +88122;Damas-et-Bettegney;366;7;373 +88123;Damblain;254;7;261 +88124;Darney;1092;54;1146 +88125;Darney-aux-Chênes;63;1;64 +88126;Darnieulles;1407;30;1437 +88127;Deinvillers;61;2;63 +88128;Denipaire;247;5;252 +88129;Derbamont;111;3;114 +88130;Destord;256;5;261 +88131;Deycimont;309;8;317 +88132;Deyvillers;1418;39;1457 +88133;Dignonville;190;9;199 +88134;Dinozé;604;13;617 +88135;Docelles;879;18;897 +88136;Dogneville;1486;27;1513 +88137;Dolaincourt;99;0;99 +88138;Dombasle-devant-Darney;81;2;83 +88139;Dombasle-en-Xaintois;124;2;126 +88140;Dombrot-le-Sec;376;14;390 +88141;Dombrot-sur-Vair;245;3;248 +88144;Domèvre-sous-Montfort;57;0;57 +88142;Domèvre-sur-Avière;402;8;410 +88143;Domèvre-sur-Durbion;267;14;281 +88145;Domfaing;216;3;219 +88146;Domjulien;177;2;179 +88147;Dommartin-aux-Bois;394;5;399 +88148;Dommartin-lès-Remiremont;1894;52;1946 +88149;Dommartin-lès-Vallois;55;0;55 +88150;Dommartin-sur-Vraine;307;8;315 +88151;Dompaire;1148;28;1176 +88152;Dompierre;257;13;270 +88153;Domptail;357;1;358 +88154;Domrémy-la-Pucelle;104;2;106 +88155;Domvallier;105;7;112 +88156;Doncières;137;2;139 +88157;Dounoux;855;18;873 +88158;Éloyes;3180;61;3241 +88159;Entre-deux-Eaux;503;8;511 +88160;Épinal;31740;1408;33148 +88161;Escles;436;12;448 +88162;Esley;190;5;195 +88163;Essegney;754;9;763 +88164;Estrennes;89;2;91 +88165;Étival-Clairefontaine;2616;52;2668 +88166;Évaux-et-Ménil;357;3;360 +88167;Faucompierre;240;5;245 +88168;Fauconcourt;132;2;134 +88169;Fays;223;9;232 +88170;Ferdrupt;721;17;738 +88171;Fignévelle;45;1;46 +88172;Fiménil;227;4;231 +88173;Florémont;449;11;460 +88174;Fomerey;158;6;164 +88175;Fontenay;468;21;489 +88176;Fontenoy-le-Château;532;36;568 +88177;La Forge;529;11;540 +88178;Les Forges;1868;70;1938 +88179;Fouchécourt;45;1;46 +88180;Frain;129;7;136 +88181;Fraize;2871;47;2918 +88182;Frapelle;190;5;195 +88183;Frebécourt;313;7;320 +88184;Fremifontaine;469;11;480 +88185;Frenelle-la-Grande;108;4;112 +88186;Frenelle-la-Petite;45;3;48 +88187;Frénois;51;0;51 +88188;Fresse-sur-Moselle;1738;48;1786 +88189;Fréville;145;4;149 +88190;Frizon;515;7;522 +88192;Gelvécourt-et-Adompt;110;1;111 +88193;Gemaingoutte;139;1;140 +88194;Gemmelaincourt;149;12;161 +88195;Gendreville;106;1;107 +88196;Gérardmer;7967;631;8598 +88197;Gerbamont;362;11;373 +88198;Gerbépal;589;12;601 +88199;Gignéville;79;3;82 +88200;Gigney;46;2;48 +88201;Girancourt;896;15;911 +88202;Gircourt-lès-Viéville;184;3;187 +88203;Girecourt-sur-Durbion;342;11;353 +88205;Girmont-Val-d'Ajol;251;16;267 +88206;Gironcourt-sur-Vraine;927;18;945 +88208;Godoncourt;124;4;128 +88209;Golbey;8623;134;8757 +88210;Gorhey;178;6;184 +88212;Grand;360;10;370 +88213;La Grande-Fosse;129;0;129 +88215;Grandrupt;77;2;79 +88214;Grandrupt-de-Bains;81;4;85 +88216;Grandvillers;753;12;765 +88218;Granges-Aumontzey;2665;59;2724 +88219;Greux;157;6;163 +88220;Grignoncourt;40;1;41 +88221;Gruey-lès-Surance;262;8;270 +88222;Gugnécourt;238;19;257 +88223;Gugney-aux-Aulx;161;7;168 +88224;Hadigny-les-Verrières;405;5;410 +88225;Hadol;2368;106;2474 +88226;Hagécourt;120;4;124 +88227;Hagnéville-et-Roncourt;87;1;88 +88228;Haillainville;167;4;171 +88229;Harchéchamp;74;4;78 +88230;Hardancourt;41;0;41 +88231;Haréville;480;18;498 +88232;Harmonville;229;4;233 +88233;Harol;628;57;685 +88236;La Haye;115;0;115 +88237;Hennecourt;361;7;368 +88238;Hennezel;402;7;409 +88239;Hergugney;135;3;138 +88240;Herpelmont;282;2;284 +88241;Houécourt;440;12;452 +88242;Houéville;50;1;51 +88243;Housseras;489;7;496 +88244;La Houssière;587;17;604 +88245;Hurbache;320;14;334 +88246;Hymont;476;14;490 +88247;Igney;1168;25;1193 +88248;Isches;164;4;168 +88249;Jainvillotte;79;3;82 +88250;Jarménil;474;4;478 +88251;Jeanménil;1113;34;1147 +88252;Jésonville;127;7;134 +88253;Jeuxey;687;16;703 +88254;Jorxey;83;1;84 +88255;Jubainville;91;1;92 +88256;Jussarupt;274;4;278 +88257;Juvaincourt;184;3;187 +88258;Lamarche;901;16;917 +88259;Landaville;298;9;307 +88260;Langley;161;2;163 +88261;Laval-sur-Vologne;631;11;642 +88262;Laveline-devant-Bruyères;610;12;622 +88263;Laveline-du-Houx;214;6;220 +88264;Légéville-et-Bonfays;49;3;52 +88265;Lemmecourt;30;0;30 +88266;Lépanges-sur-Vologne;850;19;869 +88267;Lerrain;460;16;476 +88268;Lesseux;151;8;159 +88269;Liézey;286;7;293 +88270;Liffol-le-Grand;2144;56;2200 +88271;Lignéville;315;6;321 +88272;Lironcourt;71;0;71 +88273;Longchamp;456;11;467 +88274;Longchamp-sous-Châtenois;66;5;71 +88275;Lubine;228;2;230 +88276;Lusse;434;3;437 +88277;Luvigny;112;3;115 +88278;Maconcourt;75;1;76 +88279;Madecourt;52;1;53 +88280;Madegney;128;0;128 +88281;Madonne-et-Lamerey;401;12;413 +88283;Malaincourt;85;1;86 +88284;Mandray;589;12;601 +88285;Mandres-sur-Vair;458;121;579 +88286;Marainville-sur-Madon;95;0;95 +88287;Marey;69;1;70 +88288;Maroncourt;9;0;9 +88289;Martigny-les-Bains;803;73;876 +88290;Martigny-les-Gerbonvaux;108;2;110 +88291;Martinvelle;122;3;125 +88292;Mattaincourt;821;19;840 +88293;Maxey-sur-Meuse;227;4;231 +88294;Mazeley;267;3;270 +88295;Mazirot;224;7;231 +88296;Médonville;100;0;100 +88297;Méménil;151;5;156 +88298;Ménarmont;76;0;76 +88302;Le Ménil;1069;24;1093 +88300;Ménil-de-Senones;138;2;140 +88299;Ménil-en-Xaintois;150;1;151 +88301;Ménil-sur-Belvitte;294;11;305 +88303;Midrevaux;222;5;227 +88304;Mirecourt;5246;482;5728 +88305;Moncel-sur-Vair;201;5;206 +88306;Le Mont;51;0;51 +88307;Mont-lès-Lamarche;98;2;100 +88308;Mont-lès-Neufchâteau;300;5;305 +88309;Monthureux-le-Sec;159;9;168 +88310;Monthureux-sur-Saône;879;18;897 +88311;Montmotier;45;1;46 +88312;Morelmaison;207;5;212 +88313;Moriville;433;8;441 +88314;Morizécourt;107;4;111 +88315;Mortagne;170;2;172 +88316;Morville;49;2;51 +88317;Moussey;614;5;619 +88318;Moyemont;223;5;228 +88319;Moyenmoutier;3186;66;3252 +88320;Nayemont-les-Fosses;798;39;837 +88321;Neufchâteau;6664;287;6951 +88322;La Neuveville-devant-Lépanges;499;12;511 +88324;La Neuveville-sous-Châtenois;377;10;387 +88325;La Neuveville-sous-Montfort;180;7;187 +88326;Neuvillers-sur-Fave;339;8;347 +88327;Nomexy;2097;29;2126 +88328;Nompatelize;541;23;564 +88330;Nonville;200;2;202 +88331;Nonzeville;51;2;53 +88332;Norroy;222;6;228 +88333;Nossoncourt;117;1;118 +88334;Oëlleville;306;5;311 +88335;Offroicourt;152;4;156 +88336;Ollainville;67;1;68 +88338;Ortoncourt;89;0;89 +88340;Padoux;514;7;521 +88341;Pair-et-Grandrupt;511;10;521 +88342;Pallegney;170;3;173 +88343;Parey-sous-Montfort;149;4;153 +88344;Pargny-sous-Mureau;182;5;187 +88345;La Petite-Fosse;78;3;81 +88346;La Petite-Raon;751;10;761 +88347;Pierrefitte;123;1;124 +88348;Pierrepont-sur-l'Arentèle;136;2;138 +88349;Plainfaing;1676;27;1703 +88350;Pleuvezain;76;3;79 +88351;Plombières-les-Bains;1678;26;1704 +88352;Pompierre;219;5;224 +88353;Pont-lès-Bonfays;102;3;105 +88354;Pont-sur-Madon;178;0;178 +88355;Portieux;1258;21;1279 +88356;Les Poulières;241;1;242 +88357;Poussay;689;20;709 +88358;Pouxeux;1992;37;2029 +88359;Prey;93;3;96 +88361;Provenchères-et-Colroy;1372;86;1458 +88360;Provenchères-lès-Darney;159;8;167 +88362;Le Puid;102;1;103 +88363;Punerot;157;5;162 +88364;Puzieux;148;3;151 +88365;Racécourt;171;3;174 +88366;Rainville;278;12;290 +88367;Rambervillers;5170;134;5304 +88368;Ramecourt;189;4;193 +88369;Ramonchamp;1978;139;2117 +88370;Rancourt;60;1;61 +88371;Raon-aux-Bois;1237;19;1256 +88372;Raon-l'Étape;6388;146;6534 +88373;Raon-sur-Plaine;146;2;148 +88374;Rapey;23;0;23 +88375;Raves;468;7;475 +88376;Rebeuville;283;7;290 +88377;Regnévelle;125;2;127 +88378;Regney;88;2;90 +88379;Rehaincourt;363;6;369 +88380;Rehaupal;211;6;217 +88381;Relanges;209;12;221 +88382;Remicourt;66;1;67 +88383;Remiremont;7714;299;8013 +88386;Remomeix;479;3;482 +88385;Remoncourt;594;10;604 +88387;Removille;214;4;218 +88388;Renauvoid;118;3;121 +88389;Repel;84;0;84 +88390;Robécourt;108;3;111 +88391;Rochesson;699;17;716 +88393;Rollainville;306;9;315 +88394;Romain-aux-Bois;48;0;48 +88395;Romont;391;9;400 +88398;Les Rouges-Eaux;88;3;91 +88399;Le Roulier;195;2;197 +88400;Rouvres-en-Xaintois;277;3;280 +88401;Rouvres-la-Chétive;450;9;459 +88402;Roville-aux-Chênes;369;161;530 +88403;Rozerotte;192;2;194 +88404;Rozières-sur-Mouzon;63;1;64 +88406;Rugney;141;3;144 +88407;Ruppes;140;2;142 +88408;Rupt-sur-Moselle;3525;67;3592 +88409;Saint-Amé;2154;40;2194 +88411;Saint-Baslemont;80;1;81 +88412;Saint-Benoît-la-Chipotte;417;9;426 +88413;Saint-Dié-des-Vosges;19607;530;20137 +88415;Saint-Étienne-lès-Remiremont;3840;82;3922 +88416;Saint-Genest;136;2;138 +88417;Saint-Gorgon;391;9;400 +88419;Saint-Jean-d'Ormont;122;0;122 +88421;Saint-Julien;110;2;112 +88423;Saint-Léonard;1355;22;1377 +88425;Saint-Maurice-sur-Mortagne;181;5;186 +88426;Saint-Maurice-sur-Moselle;1404;37;1441 +88427;Saint-Menge;126;1;127 +88428;Saint-Michel-sur-Meurthe;1864;58;1922 +88429;Saint-Nabord;4052;245;4297 +88430;Saint-Ouen-lès-Parey;495;13;508 +88431;Saint-Paul;156;3;159 +88432;Saint-Pierremont;153;3;156 +88433;Saint-Prancher;83;1;84 +88434;Saint-Remimont;224;6;230 +88435;Saint-Remy;519;12;531 +88436;Saint-Stail;73;1;74 +88437;Saint-Vallier;98;1;99 +88410;Sainte-Barbe;278;4;282 +88418;Sainte-Hélène;466;4;470 +88424;Sainte-Marguerite;2319;71;2390 +88438;La Salle;394;5;399 +88439;Sanchey;939;36;975 +88440;Sandaucourt;174;4;178 +88441;Sans-Vallois;133;2;135 +88442;Sapois;641;17;658 +88443;Sartes;99;2;101 +88444;Le Saulcy;327;11;338 +88445;Saulcy-sur-Meurthe;2330;55;2385 +88446;Saulxures-lès-Bulgnéville;252;2;254 +88447;Saulxures-sur-Moselotte;2588;86;2674 +88448;Sauville;183;7;190 +88449;Savigny;184;0;184 +88450;Senaide;181;1;182 +88451;Senones;2464;40;2504 +88452;Senonges;128;0;128 +88453;Seraumont;43;1;44 +88454;Sercœur;240;6;246 +88455;Serécourt;100;6;106 +88456;Serocourt;90;3;93 +88457;Sionne;140;1;141 +88458;Socourt;270;3;273 +88459;Soncourt;44;1;45 +88460;Soulosse-sous-Saint-Élophe;646;12;658 +88461;Suriauville;214;0;214 +88462;Le Syndicat;1898;41;1939 +88463;Taintrux;1543;42;1585 +88464;Tendon;516;8;524 +88466;They-sous-Montfort;127;5;132 +88467;Thiéfosse;593;15;608 +88468;Le Thillot;3438;56;3494 +88469;Thiraucourt;99;4;103 +88470;Le Tholy;1573;44;1617 +88471;Les Thons;105;1;106 +88472;Thuillières;120;3;123 +88473;Tignécourt;105;4;109 +88474;Tilleux;58;0;58 +88475;Tollaincourt;127;0;127 +88476;Totainville;121;1;122 +88477;Trampot;92;2;94 +88478;Tranqueville-Graux;103;1;104 +88479;Trémonzey;255;4;259 +88480;Ubexy;175;0;175 +88481;Uriménil;1355;23;1378 +88482;Urville;57;0;57 +88483;Uxegney;2294;66;2360 +88484;Uzemain;1055;30;1085 +88485;La Vacheresse-et-la-Rouillie;125;0;125 +88486;Vagney;3925;110;4035 +88487;Le Val-d'Ajol;3871;100;3971 +88488;Valfroicourt;241;5;246 +88489;Valleroy-aux-Saules;260;8;268 +88490;Valleroy-le-Sec;167;6;173 +88491;Les Vallois;118;4;122 +88492;Le Valtin;74;2;76 +88493;Varmonzey;28;1;29 +88494;Vaubexy;126;2;128 +88495;Vaudéville;162;6;168 +88496;Vaudoncourt;157;3;160 +88497;Vaxoncourt;452;8;460 +88498;Vecoux;870;21;891 +88499;Velotte-et-Tatignécourt;158;3;161 +88500;Ventron;838;14;852 +88501;Le Vermont;70;0;70 +88502;Vervezelle;132;5;137 +88503;Vexaincourt;157;3;160 +88504;Vicherey;195;4;199 +88505;Vienville;125;2;127 +88506;Vieux-Moulin;320;6;326 +88508;Ville-sur-Illon;558;12;570 +88507;Villers;209;7;216 +88509;Villoncourt;110;2;112 +88510;Villotte;153;0;153 +88511;Villouxel;82;2;84 +88512;Viménil;245;3;248 +88513;Vincey;2181;26;2207 +88514;Viocourt;156;5;161 +88515;Vioménil;145;2;147 +88516;Vittel;5071;145;5216 +88517;Viviers-le-Gras;199;3;202 +88518;Viviers-lès-Offroicourt;36;0;36 +88029;La Vôge-les-Bains;1624;123;1747 +88519;La Voivre;686;22;708 +88520;Les Voivres;310;9;319 +88521;Vomécourt;275;4;279 +88522;Vomécourt-sur-Madon;70;3;73 +88523;Vouxey;138;8;146 +88524;Vrécourt;370;4;374 +88525;Vroville;133;3;136 +88526;Wisembach;409;10;419 +88527;Xaffévillers;153;3;156 +88528;Xamontarupt;155;3;158 +88529;Xaronval;106;4;110 +88530;Xertigny;2611;49;2660 +88531;Xonrupt-Longemer;1522;49;1571 +88532;Zincourt;83;4;87 +89002;Aigremont;78;3;81 +89004;Aisy-sur-Armançon;245;11;256 +89005;Ancy-le-Franc;908;24;932 +89006;Ancy-le-Libre;183;5;188 +89007;Andryes;399;12;411 +89008;Angely;158;7;165 +89009;Annay-la-Côte;348;16;364 +89010;Annay-sur-Serein;219;3;222 +89011;Annéot;128;10;138 +89012;Annoux;86;3;89 +89013;Appoigny;3167;52;3219 +89014;Arces-Dilo;605;8;613 +89015;Arcy-sur-Cure;484;12;496 +89016;Argentenay;81;3;84 +89017;Argenteuil-sur-Armançon;213;2;215 +89018;Armeau;770;8;778 +89019;Arthonnay;152;1;153 +89020;Asnières-sous-Bois;126;2;128 +89021;Asquins;294;13;307 +89022;Athie;137;2;139 +89023;Augy;1059;41;1100 +89024;Auxerre;34634;1282;35916 +89025;Avallon;6572;219;6791 +89027;Bagneaux;209;5;214 +89028;Baon;75;6;81 +89029;Bassou;873;20;893 +89030;Bazarnes;424;9;433 +89031;Beaumont;630;12;642 +89032;Beauvilliers;76;3;79 +89033;Beauvoir;392;8;400 +89034;Beine;482;12;494 +89035;Bellechaume;441;14;455 +89036;La Belliole;252;5;257 +89037;Béon;510;5;515 +89038;Bernouil;108;0;108 +89039;Béru;76;1;77 +89040;Bessy-sur-Cure;190;3;193 +89041;Beugnon;307;14;321 +89042;Bierry-les-Belles-Fontaines;190;5;195 +89043;Blacy;103;1;104 +89044;Blannay;114;1;115 +89045;Bleigny-le-Carreau;295;7;302 +89046;Bléneau;1289;18;1307 +89049;Bois-d'Arcy;24;2;26 +89050;Bonnard;881;11;892 +89051;Les Bordes;551;8;559 +89053;Branches;451;10;461 +89054;Brannay;786;8;794 +89055;Brienon-sur-Armançon;3176;71;3247 +89056;Brion;629;14;643 +89057;Brosses;302;4;306 +89058;Bussières;125;2;127 +89059;Bussy-en-Othe;730;11;741 +89060;Bussy-le-Repos;452;11;463 +89061;Butteaux;255;4;259 +89048;Bœurs-en-Othe;343;7;350 +89062;Carisey;355;5;360 +89063;La Celle-Saint-Cyr;810;20;830 +89064;Censy;56;1;57 +89065;Cérilly;40;1;41 +89066;Cerisiers;984;25;1009 +89067;Cézy;1118;17;1135 +89068;Chablis;2274;44;2318 +89069;Chailley;540;13;553 +89071;Chamoux;101;0;101 +89072;Champcevrais;310;3;313 +89073;Champignelles;994;42;1036 +89074;Champigny;2204;40;2244 +89075;Champlay;721;11;732 +89076;Champlost;790;11;801 +89077;Champs-sur-Yonne;1574;92;1666 +89079;Chamvres;657;23;680 +89080;La Chapelle-sur-Oreuse;624;5;629 +89081;La Chapelle-Vaupelteigne;89;0;89 +89083;Charbuy;1865;47;1912 +89084;Charentenay;297;5;302 +89085;Charmoy;1150;22;1172 +89086;Charny Orée de Puisaye;4877;74;4951 +89087;Chassignelles;313;9;322 +89088;Chassy;460;12;472 +89089;Chastellux-sur-Cure;136;6;142 +89091;Châtel-Censoir;643;13;656 +89092;Châtel-Gérard;215;11;226 +89093;Chaumont;656;10;666 +89094;Chaumot;760;15;775 +89095;Chemilly-sur-Serein;148;7;155 +89096;Chemilly-sur-Yonne;910;21;931 +89098;Cheney;232;5;237 +89099;Cheny;2487;47;2534 +89100;Chéroy;1655;15;1670 +89101;Chéu;558;11;569 +89102;Chevannes;2178;62;2240 +89104;Chichée;311;11;322 +89105;Chichery;481;16;497 +89108;Chitry;353;9;362 +89111;Les Clérimois;297;7;304 +89112;Collan;172;6;178 +89113;Collemiers;660;16;676 +89115;Compigny;194;2;196 +89116;Cornant;357;5;362 +89117;Coulangeron;214;1;215 +89118;Coulanges-la-Vineuse;826;18;844 +89119;Coulanges-sur-Yonne;551;10;561 +89120;Coulours;133;3;136 +89122;Courgenay;565;8;573 +89123;Courgis;257;6;263 +89124;Courlon-sur-Yonne;1192;23;1215 +89125;Courson-les-Carrières;942;20;962 +89126;Courtoin;38;1;39 +89127;Courtois-sur-Yonne;769;24;793 +89128;Coutarnoux;141;4;145 +89129;Crain;399;9;408 +89131;Cruzy-le-Châtel;242;4;246 +89132;Cry;170;6;176 +89133;Cudot;345;4;349 +89134;Cussy-les-Forges;338;7;345 +89136;Cuy;862;13;875 +89137;Dannemoine;474;10;484 +89130;Deux Rivières;1260;29;1289 +89139;Diges;1141;37;1178 +89141;Dissangis;120;7;127 +89142;Dixmont;914;26;940 +89143;Dollot;322;2;324 +89144;Domats;819;15;834 +89145;Domecy-sur-Cure;388;12;400 +89146;Domecy-sur-le-Vault;88;3;91 +89147;Dracy;216;5;221 +89148;Druyes-les-Belles-Fontaines;279;5;284 +89149;Dyé;210;6;216 +89150;Égleny;448;9;457 +89151;Égriselles-le-Bocage;1295;39;1334 +89152;Épineau-les-Voves;742;15;757 +89153;Épineuil;597;15;612 +89154;Escamps;888;22;910 +89155;Escolives-Sainte-Camille;702;12;714 +89156;Esnon;392;7;399 +89158;Étais-la-Sauvin;629;26;655 +89159;Étaule;369;10;379 +89160;Étigny;752;24;776 +89161;Étivey;197;5;202 +89162;Évry;386;4;390 +89163;La Ferté-Loupière;532;9;541 +89164;Festigny;89;0;89 +89165;Flacy;111;2;113 +89167;Fleury-la-Vallée;1102;35;1137 +89168;Fleys;180;3;183 +89169;Flogny-la-Chapelle;1029;20;1049 +89170;Foissy-lès-Vézelay;128;2;130 +89171;Foissy-sur-Vanne;325;3;328 +89172;Fontaine-la-Gaillarde;509;25;534 +89173;Fontaines;475;4;479 +89175;Fontenay-près-Chablis;143;7;150 +89176;Fontenay-près-Vézelay;136;3;139 +89177;Fontenay-sous-Fouronnes;73;0;73 +89179;Fontenoy;296;8;304 +89180;Fouchères;469;9;478 +89181;Fournaudin;121;2;123 +89182;Fouronnes;164;2;166 +89183;Fresnes;66;0;66 +89184;Fulvy;131;3;134 +89186;Germigny;547;19;566 +89187;Gigny;99;2;101 +89188;Girolles;169;7;176 +89189;Gisy-les-Nobles;575;19;594 +89190;Givry;174;8;182 +89191;Gland;42;2;44 +89194;Grimault;120;5;125 +89195;Gron;1238;75;1313 +89197;Guillon-Terre-Plaine;760;8;768 +89198;Gurgy;1716;38;1754 +89199;Gy-l'Évêque;454;10;464 +89200;Hauterive;390;16;406 +89405;Les Hauts de Forterre;509;7;516 +89201;Héry;1809;54;1863 +89202;Irancy;279;6;285 +89203;Island;182;11;193 +89204;L' Isle-sur-Serein;662;13;675 +89205;Jaulges;550;5;555 +89206;Joigny;9580;346;9926 +89207;Jouancy;24;0;24 +89208;Joux-la-Ville;1181;19;1200 +89209;Jouy;524;15;539 +89210;Jully;147;7;154 +89211;Junay;76;0;76 +89212;Jussy;384;15;399 +89214;Lailly;192;5;197 +89215;Lain;182;4;186 +89216;Lainsecq;326;10;336 +89217;Lalande;136;2;138 +89218;Laroche-Saint-Cydroine;1252;23;1275 +89219;Lasson;146;1;147 +89220;Lavau;464;8;472 +89221;Leugny;341;12;353 +89222;Levis;225;6;231 +89223;Lézinnes;669;18;687 +89224;Lichères-près-Aigremont;161;4;165 +89225;Lichères-sur-Yonne;51;0;51 +89226;Lignorelles;192;9;201 +89227;Ligny-le-Châtel;1280;16;1296 +89228;Lindry;1387;42;1429 +89229;Lixy;450;10;460 +89230;Looze;446;17;463 +89232;Lucy-le-Bois;298;15;313 +89233;Lucy-sur-Cure;203;5;208 +89234;Lucy-sur-Yonne;134;2;136 +89235;Magny;866;22;888 +89236;Maillot;1166;31;1197 +89237;Mailly-la-Ville;511;12;523 +89238;Mailly-le-Château;554;6;560 +89239;Malay-le-Grand;1533;43;1576 +89240;Malay-le-Petit;339;11;350 +89242;Maligny;802;20;822 +89244;Marmeaux;93;2;95 +89245;Marsangy;849;19;868 +89246;Massangis;360;4;364 +89247;Mélisey;254;2;256 +89248;Menades;55;2;57 +89249;Mercy;81;1;82 +89250;Méré;197;2;199 +89251;Merry-la-Vallée;376;9;385 +89252;Merry-Sec;175;4;179 +89253;Merry-sur-Yonne;200;1;201 +89254;Mézilles;547;7;554 +89255;Michery;1048;21;1069 +89256;Migé;423;3;426 +89257;Migennes;7240;114;7354 +89259;Môlay;91;2;93 +89261;Molinons;277;7;284 +89262;Molosmes;175;8;183 +89263;Monéteau;3985;79;4064 +89268;Mont-Saint-Sulpice;795;15;810 +89264;Montacher-Villegardin;766;12;778 +89003;Montholon;2866;60;2926 +89265;Montigny-la-Resle;588;21;609 +89266;Montillot;274;6;280 +89267;Montréal;182;7;189 +89270;Mouffy;128;2;130 +89271;Moulins-en-Tonnerrois;103;2;105 +89272;Moulins-sur-Ouanne;298;3;301 +89273;Moutiers-en-Puisaye;289;3;292 +89274;Nailly;1299;36;1335 +89276;Neuvy-Sautour;914;34;948 +89277;Nitry;369;6;375 +89278;Noé;555;7;562 +89279;Noyers;580;14;594 +89280;Nuits;399;9;408 +89281;Les Ormes;346;2;348 +89282;Ormoy;681;12;693 +89283;Ouanne;606;16;622 +89284;Pacy-sur-Armançon;191;4;195 +89285;Pailly;306;3;309 +89286;Parly;819;14;833 +89287;Paron;4853;122;4975 +89288;Paroy-en-Othe;185;3;188 +89289;Paroy-sur-Tholon;284;12;296 +89290;Pasilly;46;2;48 +89291;Passy;342;10;352 +89469;Perceneige;950;22;972 +89292;Percey;252;4;256 +89295;Perrigny;1272;32;1304 +89296;Perrigny-sur-Armançon;131;1;132 +89297;Pierre-Perthuis;122;0;122 +89298;Piffonds;639;18;657 +89299;Pimelles;62;1;63 +89300;Pisy;76;1;77 +89302;Plessis-Saint-Jean;216;5;221 +89303;Poilly-sur-Serein;272;5;277 +89304;Poilly-sur-Tholon;688;17;705 +89308;Pont-sur-Vanne;194;8;202 +89309;Pont-sur-Yonne;3334;61;3395 +89306;Pontaubert;385;12;397 +89307;Pontigny;752;10;762 +89310;La Postolle;143;3;146 +89311;Pourrain;1403;34;1437 +89312;Précy-le-Sec;253;10;263 +89313;Précy-sur-Vrin;438;14;452 +89314;Prégilbert;181;1;182 +89315;Préhy;150;1;151 +89316;Provency;243;8;251 +89318;Quarré-les-Tombes;645;12;657 +89319;Quenne;472;15;487 +89320;Quincerot;60;2;62 +89321;Ravières;736;16;752 +89323;Roffey;141;4;145 +89324;Rogny-les-Sept-Écluses;675;19;694 +89325;Ronchères;96;1;97 +89326;Rosoy;1122;28;1150 +89327;Rousson;407;9;416 +89328;Rouvray;381;10;391 +89329;Rugny;78;1;79 +89331;Sainpuits;315;12;327 +89332;Saint-Agnan;951;25;976 +89333;Saint-André-en-Terre-Plaine;159;4;163 +89335;Saint-Aubin-sur-Yonne;411;6;417 +89336;Saint-Brancher;290;8;298 +89337;Saint-Bris-le-Vineux;1024;25;1049 +89338;Saint-Clément;2756;74;2830 +89341;Saint-Cyr-les-Colons;447;4;451 +89342;Saint-Denis-lès-Sens;723;30;753 +89344;Saint-Fargeau;1589;16;1605 +89345;Saint-Florentin;4362;65;4427 +89346;Saint-Georges-sur-Baulche;3230;144;3374 +89347;Saint-Germain-des-Champs;360;10;370 +89348;Saint-Julien-du-Sault;2348;55;2403 +89349;Saint-Léger-Vauban;360;8;368 +89350;Saint-Loup-d'Ordon;256;5;261 +89353;Saint-Martin-d'Ordon;413;4;417 +89352;Saint-Martin-des-Champs;282;7;289 +89354;Saint-Martin-du-Tertre;1567;45;1612 +89355;Saint-Martin-sur-Armançon;141;6;147 +89359;Saint-Maurice-aux-Riches-Hommes;420;5;425 +89360;Saint-Maurice-le-Vieil;373;6;379 +89361;Saint-Maurice-Thizouaille;263;2;265 +89362;Saint-Moré;178;5;183 +89364;Saint-Père;310;4;314 +89365;Saint-Privé;521;15;536 +89368;Saint-Sauveur-en-Puisaye;885;17;902 +89369;Saint-Sérotin;557;8;565 +89370;Saint-Valérien;1681;30;1711 +89339;Sainte-Colombe;200;6;206 +89351;Sainte-Magnance;477;7;484 +89363;Sainte-Pallaye;109;0;109 +89371;Sainte-Vertu;90;0;90 +89367;Saints-en-Puisaye;561;10;571 +89373;Saligny;668;10;678 +89374;Sambourg;78;3;81 +89375;Santigny;97;3;100 +89376;Sarry;161;4;165 +89377;Sauvigny-le-Beuréal;73;0;73 +89378;Sauvigny-le-Bois;708;25;733 +89379;Savigny-en-Terre-Plaine;153;3;156 +89380;Savigny-sur-Clairis;459;7;466 +89382;Seignelay;1522;38;1560 +89383;Sementron;110;3;113 +89384;Senan;700;24;724 +89385;Sennevoy-le-Bas;86;3;89 +89386;Sennevoy-le-Haut;118;1;119 +89387;Sens;25935;584;26519 +89388;Sépeaux-Saint Romain;559;15;574 +89390;Serbonnes;626;10;636 +89391;Sergines;1287;27;1314 +89392;Sermizelles;256;8;264 +89393;Serrigny;113;2;115 +89394;Sery;91;1;92 +89395;Les Sièges;414;8;422 +89397;Sommecaise;369;6;375 +89398;Sormery;349;5;354 +89399;Soucy;1589;45;1634 +89400;Sougères-en-Puisaye;318;5;323 +89402;Soumaintrain;218;4;222 +89403;Stigny;94;10;104 +89404;Subligny;510;8;518 +89406;Talcy;74;2;76 +89407;Tanlay;998;33;1031 +89408;Tannerre-en-Puisaye;283;8;291 +89409;Tharoiseau;62;1;63 +89410;Tharot;93;5;98 +89412;Thizy;197;9;206 +89413;Thorey;29;0;29 +89414;Thorigny-sur-Oreuse;1456;31;1487 +89415;Thory;203;3;206 +89416;Thury;439;8;447 +89417;Tissey;102;2;104 +89418;Tonnerre;4575;186;4761 +89419;Toucy;2662;140;2802 +89420;Treigny-Perreuse-Sainte-Colombe;994;20;1014 +89422;Trichey;42;2;44 +89423;Tronchoy;127;0;127 +89424;Trucy-sur-Yonne;139;6;145 +89425;Turny;681;20;701 +89334;Le Val d'Ocre;566;7;573 +89426;Val-de-Mercy;391;12;403 +89427;Vallan;680;19;699 +89411;Les Vallées de la Vanne;1078;25;1103 +89428;Vallery;556;3;559 +89196;Valravillon;1762;45;1807 +89430;Varennes;323;8;331 +89431;Vassy-sous-Pisy;71;1;72 +89432;Vaudeurs;476;9;485 +89433;Vault-de-Lugny;292;5;297 +89434;Vaumort;364;4;368 +89436;Venizy;902;15;917 +89437;Venouse;303;10;313 +89438;Venoy;1800;191;1991 +89439;Vergigny;1549;23;1572 +89440;Verlin;425;3;428 +89441;Vermenton;1289;27;1316 +89442;Vernoy;245;4;249 +89443;Véron;1955;38;1993 +89445;Vézannes;49;2;51 +89446;Vézelay;428;4;432 +89447;Vézinnes;159;5;164 +89449;Villeblevin;1865;31;1896 +89450;Villebougis;630;21;651 +89451;Villechétive;241;4;245 +89452;Villecien;405;6;411 +89453;Villefargeau;1107;29;1136 +89456;Villemanoche;670;9;679 +89458;Villenavotte;176;7;183 +89461;Villeneuve-l'Archevêque;1131;22;1153 +89459;Villeneuve-la-Dondagre;301;0;301 +89460;Villeneuve-la-Guyard;3465;48;3513 +89462;Villeneuve-les-Genêts;281;3;284 +89463;Villeneuve-Saint-Salves;253;4;257 +89464;Villeneuve-sur-Yonne;5219;83;5302 +89465;Villeperrot;323;1;324 +89466;Villeroy;390;10;400 +89467;Villethierry;838;15;853 +89468;Villevallier;424;50;474 +89470;Villiers-les-Hauts;125;7;132 +89471;Villiers-Louis;457;15;472 +89472;Villiers-Saint-Benoît;476;9;485 +89474;Villiers-Vineux;282;4;286 +89475;Villon;110;4;114 +89477;Villy;107;2;109 +89478;Vincelles;930;20;950 +89479;Vincelottes;279;6;285 +89480;Vinneuf;1548;22;1570 +89481;Vireaux;131;6;137 +89482;Viviers;127;1;128 +89483;Voisines;498;16;514 +89485;Voutenay-sur-Cure;214;4;218 +89486;Yrouerre;159;5;164 +90001;Andelnans;1199;22;1221 +90002;Angeot;345;8;353 +90003;Anjoutey;603;22;625 +90004;Argiésans;461;13;474 +90082;Autrechêne;280;9;289 +90005;Auxelles-Bas;463;14;477 +90006;Auxelles-Haut;289;8;297 +90007;Banvillars;282;5;287 +90008;Bavilliers;4726;110;4836 +90009;Beaucourt;5007;63;5070 +90010;Belfort;47656;767;48423 +90011;Bermont;391;9;400 +90012;Bessoncourt;1245;31;1276 +90013;Bethonvilliers;248;11;259 +90014;Boron;480;8;488 +90015;Botans;242;9;251 +90016;Bourg-sous-Châtelet;118;2;120 +90017;Bourogne;1896;25;1921 +90018;Brebotte;385;7;392 +90019;Bretagne;265;6;271 +90020;Buc;283;9;292 +90021;Charmois;340;4;344 +90022;Châtenois-les-Forges;2750;56;2806 +90023;Chaux;1147;30;1177 +90024;Chavanatte;154;3;157 +90025;Chavannes-les-Grands;338;4;342 +90026;Chèvremont;1600;40;1640 +90027;Courcelles;120;0;120 +90028;Courtelevant;419;7;426 +90029;Cravanche;1957;55;2012 +90030;Croix;165;3;168 +90031;Cunelières;355;14;369 +90032;Danjoutin;3715;64;3779 +90033;Delle;5690;87;5777 +90034;Denney;762;26;788 +90035;Dorans;751;9;760 +90036;Eguenigue;274;9;283 +90037;Éloie;948;26;974 +90039;Essert;3306;98;3404 +90041;Étueffont;1491;47;1538 +90042;Évette-Salbert;2055;67;2122 +90043;Faverois;574;8;582 +90045;Fêche-l'Église;768;13;781 +90044;Felon;244;5;249 +90046;Florimont;446;6;452 +90047;Fontaine;603;14;617 +90048;Fontenelle;127;3;130 +90049;Foussemagne;921;18;939 +90050;Frais;219;6;225 +90051;Froidefontaine;456;8;464 +90052;Giromagny;3064;85;3149 +90053;Grandvillars;2974;61;3035 +90054;Grosmagny;524;7;531 +90055;Grosne;329;2;331 +90056;Joncherey;1353;27;1380 +90057;Lachapelle-sous-Chaux;741;26;767 +90058;Lachapelle-sous-Rougemont;580;6;586 +90059;Lacollonge;228;7;235 +90060;Lagrange;129;3;132 +90061;Lamadeleine-Val-des-Anges;40;2;42 +90062;Larivière;301;10;311 +90063;Lebetain;421;9;430 +90065;Lepuix;1154;20;1174 +90064;Lepuix-Neuf;298;4;302 +90066;Leval;241;1;242 +90067;Menoncourt;390;17;407 +90068;Meroux-Moval;1307;30;1337 +90069;Méziré;1334;25;1359 +90070;Montbouton;405;10;415 +90071;Montreux-Château;1181;14;1195 +90072;Morvillars;1078;22;1100 +90074;Novillard;299;4;303 +90075;Offemont;4108;96;4204 +90076;Pérouse;1169;30;1199 +90077;Petit-Croix;299;7;306 +90078;Petitefontaine;190;5;195 +90079;Petitmagny;298;6;304 +90080;Phaffans;451;12;463 +90081;Réchésy;786;14;800 +90083;Recouvrance;108;1;109 +90084;Reppe;342;10;352 +90085;Riervescemont;100;2;102 +90086;Romagny-sous-Rougemont;218;6;224 +90087;Roppe;1045;18;1063 +90088;Rougegoutte;976;25;1001 +90089;Rougemont-le-Château;1479;64;1543 +90090;Saint-Dizier-l'Évêque;428;11;439 +90091;Saint-Germain-le-Châtelet;644;24;668 +90093;Sermamagny;860;19;879 +90094;Sevenans;701;17;718 +90095;Suarce;436;3;439 +90096;Thiancourt;290;8;298 +90097;Trévenans;1248;32;1280 +90098;Urcerey;233;10;243 +90099;Valdoie;5300;235;5535 +90100;Vauthiermont;210;12;222 +90101;Vellescot;255;6;261 +90102;Vescemont;746;24;770 +90103;Vétrigne;638;22;660 +90104;Vézelois;953;17;970 +90105;Villars-le-Sec;181;2;183 +91001;Abbéville-la-Rivière;303;7;310 +91016;Angerville;4270;67;4337 +91017;Angervilliers;1673;24;1697 +91021;Arpajon;10378;89;10467 +91022;Arrancourt;152;4;156 +91027;Athis-Mons;34347;377;34724 +91035;Authon-la-Plaine;373;6;379 +91037;Auvernaux;324;1;325 +91038;Auvers-Saint-Georges;1283;21;1304 +91041;Avrainville;985;7;992 +91044;Ballainvilliers;4581;43;4624 +91045;Ballancourt-sur-Essonne;7597;99;7696 +91047;Baulne;1315;14;1329 +91064;Bièvres;4639;111;4750 +91067;Blandy;120;2;122 +91069;Boigneville;389;10;399 +91075;Bois-Herpin;77;1;78 +91079;Boissy-la-Rivière;526;7;533 +91080;Boissy-le-Cutté;1319;13;1332 +91081;Boissy-le-Sec;683;11;694 +91085;Boissy-sous-Saint-Yon;3868;47;3915 +91086;Bondoufle;9538;135;9673 +91093;Boullay-les-Troux;643;21;664 +91095;Bouray-sur-Juine;2184;27;2211 +91097;Boussy-Saint-Antoine;7552;72;7624 +91098;Boutervilliers;425;6;431 +91099;Boutigny-sur-Essonne;2998;41;3039 +91100;Bouville;648;16;664 +91103;Brétigny-sur-Orge;26528;313;26841 +91105;Breuillet;8394;119;8513 +91106;Breux-Jouy;1245;11;1256 +91109;Brières-les-Scellés;1250;8;1258 +91111;Briis-sous-Forges;3408;38;3446 +91112;Brouy;133;4;137 +91114;Brunoy;25669;427;26096 +91115;Bruyères-le-Châtel;3302;36;3338 +91121;Buno-Bonnevaux;442;7;449 +91122;Bures-sur-Yvette;9804;193;9997 +91129;Cerny;3336;163;3499 +91130;Chalo-Saint-Mars;1054;28;1082 +91131;Chalou-Moulineux;431;3;434 +91132;Chamarande;1147;14;1161 +91135;Champcueil;2867;57;2924 +91136;Champlan;2761;18;2779 +91137;Champmotteux;368;6;374 +91145;Chatignonville;64;1;65 +91148;Chauffour-lès-Étréchy;134;0;134 +91156;Cheptainville;2055;29;2084 +91159;Chevannes;1621;28;1649 +91161;Chilly-Mazarin;20181;139;20320 +91613;Congerville-Thionville;221;7;228 +91174;Corbeil-Essonnes;51292;280;51572 +91175;Corbreuse;1741;30;1771 +91179;Le Coudray-Montceaux;4865;45;4910 +91180;Courances;342;10;352 +91184;Courdimanche-sur-Essonne;267;7;274 +91186;Courson-Monteloup;572;8;580 +91191;Crosne;9231;58;9289 +91198;D'Huison-Longueville;1508;25;1533 +91195;Dannemois;822;6;828 +91200;Dourdan;10806;184;10990 +91201;Draveil;28833;242;29075 +91204;Écharcon;786;17;803 +91207;Égly;5865;46;5911 +91215;Épinay-sous-Sénart;12446;85;12531 +91216;Épinay-sur-Orge;11270;125;11395 +91223;Étampes;25092;165;25257 +91225;Étiolles;3161;152;3313 +91226;Étréchy;6541;93;6634 +91228;Évry-Courcouronnes;67967;526;68493 +91232;La Ferté-Alais;3800;57;3857 +91235;Fleury-Mérogis;12673;16;12689 +91240;Fontaine-la-Rivière;212;4;216 +91244;Fontenay-le-Vicomte;1540;24;1564 +91243;Fontenay-lès-Briis;2149;26;2175 +91247;La Forêt-le-Roi;524;5;529 +91248;La Forêt-Sainte-Croix;162;1;163 +91249;Forges-les-Bains;3851;75;3926 +91272;Gif-sur-Yvette;21379;615;21994 +91273;Gironville-sur-Essonne;763;18;781 +91274;Gometz-la-Ville;1483;24;1507 +91275;Gometz-le-Châtel;2752;35;2787 +91284;Les Granges-le-Roi;1198;24;1222 +91286;Grigny;28737;125;28862 +91292;Guibeville;707;12;719 +91293;Guigneville-sur-Essonne;930;17;947 +91294;Guillerval;819;11;830 +91312;Igny;10052;353;10405 +91315;Itteville;6585;61;6646 +91318;Janville-sur-Juine;1962;47;2009 +91319;Janvry;636;10;646 +91326;Juvisy-sur-Orge;16667;128;16795 +91330;Lardy;5526;74;5600 +91332;Leudeville;1463;25;1488 +91333;Leuville-sur-Orge;4471;57;4528 +91338;Limours;6625;125;6750 +91339;Linas;6785;54;6839 +91340;Lisses;7445;59;7504 +91345;Longjumeau;21221;169;21390 +91347;Longpont-sur-Orge;6338;51;6389 +91359;Maisse;2719;32;2751 +91363;Marcoussis;8139;161;8300 +91374;Marolles-en-Beauce;233;3;236 +91376;Marolles-en-Hurepoix;5388;52;5440 +91377;Massy;50833;309;51142 +91378;Mauchamps;275;2;277 +91386;Mennecy;14319;332;14651 +91390;Le Mérévillois;3347;43;3390 +91393;Mérobert;614;9;623 +91399;Mespuits;211;4;215 +91405;Milly-la-Forêt;4609;88;4697 +91408;Moigny-sur-École;1253;16;1269 +91411;Les Molières;1914;48;1962 +91412;Mondeville;727;14;741 +91414;Monnerville;382;5;387 +91421;Montgeron;23775;290;24065 +91425;Montlhéry;7593;236;7829 +91432;Morangis;13729;73;13802 +91433;Morigny-Champigny;4346;106;4452 +91434;Morsang-sur-Orge;20909;174;21083 +91435;Morsang-sur-Seine;526;39;565 +91441;Nainville-les-Roches;470;11;481 +91457;La Norville;4097;42;4139 +91458;Nozay;4642;73;4715 +91461;Ollainville;4722;59;4781 +91463;Oncy-sur-École;1038;22;1060 +91468;Ormoy;2046;20;2066 +91469;Ormoy-la-Rivière;921;60;981 +91471;Orsay;16421;332;16753 +91473;Orveau;193;7;200 +91477;Palaiseau;35514;367;35881 +91479;Paray-Vieille-Poste;7457;55;7512 +91482;Pecqueuse;549;17;566 +91494;Le Plessis-Pâté;4103;59;4162 +91495;Plessis-Saint-Benoist;330;2;332 +91507;Prunay-sur-Essonne;295;5;300 +91508;Puiselet-le-Marais;266;4;270 +91511;Pussay;2200;31;2231 +91514;Quincy-sous-Sénart;9021;43;9064 +91519;Richarville;397;6;403 +91521;Ris-Orangis;29225;193;29418 +91525;Roinville;1393;23;1416 +91526;Roinvilliers;107;1;108 +91533;Saclas;1806;24;1830 +91534;Saclay;4029;54;4083 +91538;Saint-Aubin;703;21;724 +91540;Saint-Chéron;5072;77;5149 +91544;Saint-Cyr-la-Rivière;517;9;526 +91546;Saint-Cyr-sous-Dourdan;978;23;1001 +91547;Saint-Escobille;562;3;565 +91552;Saint-Germain-lès-Arpajon;10707;72;10779 +91553;Saint-Germain-lès-Corbeil;7493;99;7592 +91556;Saint-Hilaire;408;9;417 +91560;Saint-Jean-de-Beauregard;441;6;447 +91568;Saint-Maurice-Montcouronne;1564;36;1600 +91570;Saint-Michel-sur-Orge;19758;144;19902 +91573;Saint-Pierre-du-Perray;10835;109;10944 +91578;Saint-Sulpice-de-Favières;294;5;299 +91579;Saint-Vrain;3059;52;3111 +91581;Saint-Yon;894;10;904 +91549;Sainte-Geneviève-des-Bois;36207;320;36527 +91577;Saintry-sur-Seine;5720;54;5774 +91587;Saulx-les-Chartreux;5886;41;5927 +91589;Savigny-sur-Orge;36533;284;36817 +91593;Sermaise;1622;39;1661 +91599;Soisy-sur-École;1269;21;1290 +91600;Soisy-sur-Seine;7154;133;7287 +91602;Souzy-la-Briche;428;8;436 +91617;Tigery;4017;73;4090 +91619;Torfou;272;10;282 +91692;Les Ulis;25208;153;25361 +91630;Le Val-Saint-Germain;1475;31;1506 +91629;Valpuiseaux;612;11;623 +91631;Varennes-Jarcy;2310;30;2340 +91634;Vaugrigneuse;1287;17;1304 +91635;Vauhallan;2059;32;2091 +91639;Vayres-sur-Essonne;929;67;996 +91645;Verrières-le-Buisson;15242;336;15578 +91648;Vert-le-Grand;2322;28;2350 +91649;Vert-le-Petit;2790;37;2827 +91654;Videlles;600;17;617 +91657;Vigneux-sur-Seine;31574;178;31752 +91659;Villabé;5438;40;5478 +91665;La Ville-du-Bois;7753;62;7815 +91661;Villebon-sur-Yvette;10489;168;10657 +91662;Villeconin;724;22;746 +91666;Villejust;2385;16;2401 +91667;Villemoisson-sur-Orge;6996;88;7084 +91671;Villeneuve-sur-Auvers;617;13;630 +91679;Villiers-le-Bâcle;1237;16;1253 +91685;Villiers-sur-Orge;4548;37;4585 +91687;Viry-Châtillon;31093;224;31317 +91689;Wissous;7470;74;7544 +91691;Yerres;29029;234;29263 +92002;Antony;62570;749;63319 +92004;Asnières-sur-Seine;85191;684;85875 +92007;Bagneux;40918;193;41111 +92009;Bois-Colombes;28239;237;28476 +92012;Boulogne-Billancourt;120071;1178;121249 +92014;Bourg-la-Reine;20667;342;21009 +92019;Châtenay-Malabry;33286;378;33664 +92020;Châtillon;37355;341;37696 +92022;Chaville;20520;325;20845 +92023;Clamart;52971;538;53509 +92024;Clichy;61070;309;61379 +92025;Colombes;85177;598;85775 +92026;Courbevoie;81719;608;82327 +92032;Fontenay-aux-Roses;24564;245;24809 +92033;Garches;17869;415;18284 +92035;La Garenne-Colombes;29169;245;29414 +92036;Gennevilliers;46907;262;47169 +92040;Issy-les-Moulineaux;68451;826;69277 +92044;Levallois-Perret;64379;543;64922 +92046;Malakoff;30720;212;30932 +92047;Marnes-la-Coquette;1810;52;1862 +92048;Meudon;45352;657;46009 +92049;Montrouge;50260;221;50481 +92050;Nanterre;95105;634;95739 +92051;Neuilly-sur-Seine;60361;935;61296 +92060;Le Plessis-Robinson;29100;149;29249 +92062;Puteaux;44645;260;44905 +92063;Rueil-Malmaison;78152;1593;79745 +92064;Saint-Cloud;29973;609;30582 +92071;Sceaux;19344;368;19712 +92072;Sèvres;23507;403;23910 +92073;Suresnes;48264;472;48736 +92075;Vanves;27729;277;28006 +92076;Vaucresson;8667;326;8993 +92077;Ville-d'Avray;11453;317;11770 +92078;Villeneuve-la-Garenne;23771;110;23881 +93001;Aubervilliers;86375;222;86597 +93005;Aulnay-sous-Bois;85740;440;86180 +93006;Bagnolet;35674;123;35797 +93007;Le Blanc-Mesnil;56783;246;57029 +93008;Bobigny;53640;174;53814 +93010;Bondy;53353;187;53540 +93013;Le Bourget;16594;49;16643 +93014;Clichy-sous-Bois;29348;85;29433 +93015;Coubron;4833;30;4863 +93027;La Courneuve;43054;149;43203 +93029;Drancy;71318;287;71605 +93030;Dugny;10732;40;10772 +93031;Épinay-sur-Seine;55084;153;55237 +93032;Gagny;39358;177;39535 +93033;Gournay-sur-Marne;6869;64;6933 +93039;L' Île-Saint-Denis;7981;35;8016 +93045;Les Lilas;23045;123;23168 +93046;Livry-Gargan;44437;224;44661 +93047;Montfermeil;26783;106;26889 +93048;Montreuil;109897;577;110474 +93049;Neuilly-Plaisance;21150;118;21268 +93050;Neuilly-sur-Marne;34993;119;35112 +93051;Noisy-le-Grand;68183;332;68515 +93053;Noisy-le-Sec;44136;138;44274 +93055;Pantin;57482;186;57668 +93057;Les Pavillons-sous-Bois;23962;98;24060 +93059;Pierrefitte-sur-Seine;30306;81;30387 +93061;Le Pré-Saint-Gervais;17950;90;18040 +93062;Le Raincy;14648;228;14876 +93063;Romainville;27567;88;27655 +93064;Rosny-sous-Bois;46207;188;46395 +93066;Saint-Denis;111135;813;111948 +93070;Saint-Ouen-sur-Seine;51108;160;51268 +93071;Sevran;51016;185;51201 +93072;Stains;38720;103;38823 +93073;Tremblay-en-France;36180;165;36345 +93074;Vaujours;7030;87;7117 +93077;Villemomble;29964;188;30152 +93078;Villepinte;36830;104;36934 +93079;Villetaneuse;13646;60;13706 +94001;Ablon-sur-Seine;5785;26;5811 +94002;Alfortville;43881;182;44063 +94003;Arcueil;21501;131;21632 +94004;Boissy-Saint-Léger;16345;81;16426 +94011;Bonneuil-sur-Marne;17950;89;18039 +94015;Bry-sur-Marne;16624;181;16805 +94016;Cachan;31069;473;31542 +94017;Champigny-sur-Marne;77630;362;77992 +94018;Charenton-le-Pont;30374;194;30568 +94019;Chennevières-sur-Marne;18321;123;18444 +94021;Chevilly-Larue;19491;87;19578 +94022;Choisy-le-Roi;45331;221;45552 +94028;Créteil;90605;515;91120 +94033;Fontenay-sous-Bois;52939;479;53418 +94034;Fresnes;27802;103;27905 +94037;Gentilly;18605;102;18707 +94038;L' Haÿ-les-Roses;31204;160;31364 +94041;Ivry-sur-Seine;62052;242;62294 +94042;Joinville-le-Pont;19133;149;19282 +94043;Le Kremlin-Bicêtre;25334;134;25468 +94044;Limeil-Brévannes;27228;108;27336 +94046;Maisons-Alfort;55655;333;55988 +94047;Mandres-les-Roses;4755;39;4794 +94048;Marolles-en-Brie;4847;101;4948 +94052;Nogent-sur-Marne;32851;227;33078 +94053;Noiseau;4651;43;4694 +94054;Orly;23801;201;24002 +94055;Ormesson-sur-Marne;10305;101;10406 +94056;Périgny;2668;24;2692 +94058;Le Perreux-sur-Marne;33879;282;34161 +94059;Le Plessis-Trévise;20130;85;20215 +94060;La Queue-en-Brie;11931;130;12061 +94065;Rungis;5611;66;5677 +94067;Saint-Mandé;22619;216;22835 +94068;Saint-Maur-des-Fossés;74859;900;75759 +94069;Saint-Maurice;14056;97;14153 +94070;Santeny;3775;57;3832 +94071;Sucy-en-Brie;26472;237;26709 +94073;Thiais;29017;230;29247 +94074;Valenton;14796;69;14865 +94075;Villecresnes;10458;58;10516 +94076;Villejuif;54753;294;55047 +94077;Villeneuve-le-Roi;21384;97;21481 +94078;Villeneuve-Saint-Georges;33545;91;33636 +94079;Villiers-sur-Marne;28456;111;28567 +94080;Vincennes;49891;376;50267 +94081;Vitry-sur-Seine;93557;502;94059 +95002;Ableiges;1161;8;1169 +95008;Aincourt;916;14;930 +95011;Ambleville;372;10;382 +95012;Amenucourt;210;6;216 +95014;Andilly;2590;55;2645 +95018;Argenteuil;110210;629;110839 +95019;Arnouville;14227;86;14313 +95023;Arronville;656;3;659 +95024;Arthies;278;5;283 +95026;Asnières-sur-Oise;2650;36;2686 +95028;Attainville;1702;8;1710 +95039;Auvers-sur-Oise;6908;107;7015 +95040;Avernes;852;22;874 +95042;Baillet-en-France;1957;16;1973 +95046;Banthelu;154;2;156 +95051;Beauchamp;8683;92;8775 +95052;Beaumont-sur-Oise;9576;93;9669 +95054;Le Bellay-en-Vexin;234;5;239 +95055;Bellefontaine;485;7;492 +95056;Belloy-en-France;2189;8;2197 +95058;Bernes-sur-Oise;2708;27;2735 +95059;Berville;352;3;355 +95060;Bessancourt;7318;55;7373 +95061;Béthemont-la-Forêt;414;3;417 +95063;Bezons;29383;125;29508 +95074;Boisemont;745;16;761 +95078;Boissy-l'Aillerie;1816;32;1848 +95088;Bonneuil-en-France;1076;3;1079 +95091;Bouffémont;6327;56;6383 +95094;Bouqueval;306;2;308 +95101;Bray-et-Lû;957;13;970 +95102;Bréançon;373;8;381 +95110;Brignancourt;206;3;209 +95116;Bruyères-sur-Oise;4323;28;4351 +95119;Buhy;325;2;327 +95120;Butry-sur-Oise;2272;24;2296 +95127;Cergy;65177;470;65647 +95134;Champagne-sur-Oise;5018;41;5059 +95139;La Chapelle-en-Vexin;333;5;338 +95141;Charmont;36;0;36 +95142;Chars;2110;17;2127 +95144;Châtenay-en-France;74;1;75 +95149;Chaumontel;3261;55;3316 +95150;Chaussy;591;15;606 +95151;Chauvry;299;5;304 +95154;Chennevières-lès-Louvres;306;3;309 +95157;Chérence;138;4;142 +95166;Cléry-en-Vexin;459;7;466 +95169;Commeny;483;3;486 +95170;Condécourt;556;1;557 +95176;Cormeilles-en-Parisis;24161;193;24354 +95177;Cormeilles-en-Vexin;1402;14;1416 +95181;Courcelles-sur-Viosne;268;6;274 +95183;Courdimanche;6681;110;6791 +95197;Deuil-la-Barre;22306;191;22497 +95199;Domont;15514;204;15718 +95203;Eaubonne;25097;333;25430 +95205;Écouen;7188;48;7236 +95210;Enghien-les-Bains;11228;141;11369 +95211;Ennery;2430;26;2456 +95212;Épiais-lès-Louvres;107;0;107 +95213;Épiais-Rhus;615;16;631 +95214;Épinay-Champlâtreux;68;0;68 +95218;Éragny;17354;111;17465 +95219;Ermont;29108;240;29348 +95229;Ézanville;9775;61;9836 +95241;Fontenay-en-Parisis;1980;15;1995 +95250;Fosses;9679;65;9744 +95252;Franconville;36762;210;36972 +95253;Frémainville;499;10;509 +95254;Frémécourt;572;8;580 +95256;Frépillon;3337;32;3369 +95257;La Frette-sur-Seine;4686;40;4726 +95258;Frouville;358;8;366 +95268;Garges-lès-Gonesse;42728;125;42853 +95270;Genainville;543;19;562 +95271;Génicourt;528;8;536 +95277;Gonesse;25999;133;26132 +95280;Goussainville;30637;150;30787 +95282;Gouzangrez;165;1;166 +95287;Grisy-les-Plâtres;696;12;708 +95288;Groslay;8778;82;8860 +95295;Guiry-en-Vexin;155;3;158 +95298;Haravilliers;550;6;556 +95301;Haute-Isle;278;5;283 +95303;Le Heaulme;211;1;212 +95304;Hédouville;282;8;290 +95306;Herblay-sur-Seine;29342;229;29571 +95308;Hérouville-en-Vexin;605;13;618 +95309;Hodent;214;3;217 +95313;L' Isle-Adam;12057;212;12269 +95316;Jagny-sous-Bois;258;2;260 +95323;Jouy-le-Moutier;16035;122;16157 +95328;Labbeville;626;7;633 +95331;Lassy;176;3;179 +95341;Livilliers;385;9;394 +95348;Longuesse;542;6;548 +95351;Louvres;10337;79;10416 +95352;Luzarches;4551;69;4620 +95353;Maffliers;1843;17;1860 +95355;Magny-en-Vexin;5653;62;5715 +95365;Mareil-en-France;698;9;707 +95369;Margency;2887;51;2938 +95370;Marines;3481;62;3543 +95371;Marly-la-Ville;5677;44;5721 +95379;Maudétour-en-Vexin;189;2;191 +95387;Menouville;60;0;60 +95388;Menucourt;5771;53;5824 +95392;Mériel;5083;43;5126 +95394;Méry-sur-Oise;9892;100;9992 +95395;Le Mesnil-Aubry;921;9;930 +95409;Moisselles;1347;3;1350 +95422;Montgeroult;369;3;372 +95424;Montigny-lès-Cormeilles;21601;117;21718 +95426;Montlignon;2978;90;3068 +95427;Montmagny;14173;65;14238 +95428;Montmorency;21461;271;21732 +95429;Montreuil-sur-Epte;417;10;427 +95430;Montsoult;3482;34;3516 +95436;Mours;1609;11;1620 +95438;Moussy;130;2;132 +95445;Nerville-la-Forêt;663;3;666 +95446;Nesles-la-Vallée;1843;33;1876 +95447;Neuilly-en-Vexin;208;4;212 +95450;Neuville-sur-Oise;2048;27;2075 +95452;Nointel;816;7;823 +95456;Noisy-sur-Oise;665;4;669 +95459;Nucourt;712;15;727 +95462;Omerville;319;8;327 +95476;Osny;16910;225;17135 +95480;Parmain;5549;93;5642 +95483;Le Perchay;541;4;545 +95487;Persan;12695;40;12735 +95488;Pierrelaye;8393;38;8431 +95489;Piscop;676;69;745 +95491;Le Plessis-Bouchard;8408;69;8477 +95492;Le Plessis-Gassot;71;0;71 +95493;Le Plessis-Luzarches;136;1;137 +95500;Pontoise;30767;667;31434 +95504;Presles;3904;52;3956 +95509;Puiseux-en-France;3523;40;3563 +95510;Puiseux-Pontoise;603;12;615 +95523;La Roche-Guyon;478;37;515 +95527;Roissy-en-France;2883;25;2908 +95529;Ronquerolles;872;7;879 +95535;Sagy;1114;26;1140 +95539;Saint-Brice-sous-Forêt;14883;79;14962 +95541;Saint-Clair-sur-Epte;996;14;1010 +95543;Saint-Cyr-en-Arthies;244;1;245 +95554;Saint-Gervais;920;19;939 +95555;Saint-Gratien;20682;177;20859 +95563;Saint-Leu-la-Forêt;15798;168;15966 +95566;Saint-Martin-du-Tertre;2778;13;2791 +95572;Saint-Ouen-l'Aumône;23741;112;23853 +95574;Saint-Prix;7158;106;7264 +95580;Saint-Witz;2383;105;2488 +95582;Sannois;26662;358;27020 +95584;Santeuil;672;6;678 +95585;Sarcelles;58587;262;58849 +95592;Seraincourt;1299;14;1313 +95594;Seugy;999;14;1013 +95598;Soisy-sous-Montmorency;18155;186;18341 +95604;Survilliers;4171;25;4196 +95607;Taverny;26441;189;26630 +95610;Théméricourt;297;6;303 +95611;Theuville;45;0;45 +95612;Le Thillay;4557;21;4578 +95625;Us;1322;12;1334 +95627;Vallangoujard;612;14;626 +95628;Valmondois;1195;21;1216 +95633;Vaudherland;92;0;92 +95637;Vauréal;16464;213;16677 +95641;Vémars;2471;23;2494 +95651;Vétheuil;857;20;877 +95652;Viarmes;5175;65;5240 +95656;Vienne-en-Arthies;416;7;423 +95658;Vigny;1089;23;1112 +95660;Villaines-sous-Bois;776;7;783 +95675;Villeron;1001;9;1010 +95676;Villers-en-Arthies;503;10;513 +95678;Villiers-Adam;859;11;870 +95680;Villiers-le-Bel;27676;132;27808 +95682;Villiers-le-Sec;185;3;188 +95690;Wy-dit-Joli-Village;333;7;340 +97101;Les Abymes;53491;558;54049 +97102;Anse-Bertrand;4275;68;4343 +97103;Baie-Mahault;30929;475;31404 +97104;Baillif;5605;98;5703 +97105;Basse-Terre;10058;247;10305 +97106;Bouillante;7024;111;7135 +97107;Capesterre-Belle-Eau;18270;147;18417 +97108;Capesterre-de-Marie-Galante;3301;44;3345 +97111;Deshaies;4081;64;4145 +97110;La Désirade;1448;34;1482 +97113;Le Gosier;26783;313;27096 +97109;Gourbeyre;7795;184;7979 +97114;Goyave;7555;136;7691 +97112;Grand-Bourg;5012;135;5147 +97115;Lamentin;16573;318;16891 +97116;Morne-à-l'Eau;17434;203;17637 +97117;Le Moule;22150;239;22389 +97118;Petit-Bourg;24277;511;24788 +97119;Petit-Canal;8220;150;8370 +97120;Pointe-à-Pitre;15923;125;16048 +97121;Pointe-Noire;6107;133;6240 +97122;Port-Louis;5704;61;5765 +97124;Saint-Claude;10381;242;10623 +97125;Saint-François;12816;173;12989 +97126;Saint-Louis;2447;54;2501 +97128;Sainte-Anne;23675;276;23951 +97129;Sainte-Rose;19162;340;19502 +97130;Terre-de-Bas;1046;21;1067 +97131;Terre-de-Haut;1532;39;1571 +97132;Trois-Rivières;8124;182;8306 +97133;Vieux-Fort;1845;31;1876 +97134;Vieux-Habitants;7210;188;7398 +97201;L' Ajoupa-Bouillon;1874;33;1907 +97202;Les Anses-d'Arlet;3587;53;3640 +97203;Basse-Pointe;3026;45;3071 +97234;Bellefontaine;1721;107;1828 +97204;Le Carbet;3535;48;3583 +97205;Case-Pilote;4454;69;4523 +97206;Le Diamant;5642;74;5716 +97207;Ducos;17367;290;17657 +97208;Fonds-Saint-Denis;730;12;742 +97209;Fort-de-France;80041;965;81006 +97210;Le François;16949;313;17262 +97211;Grand'Rivière;721;10;731 +97212;Gros-Morne;9869;79;9948 +97213;Le Lamentin;39809;662;40471 +97214;Le Lorrain;6878;77;6955 +97215;Macouba;1074;9;1083 +97216;Le Marigot;3196;33;3229 +97217;Le Marin;8791;146;8937 +97218;Le Morne-Rouge;5114;60;5174 +97233;Le Morne-Vert;1834;26;1860 +97219;Le Prêcheur;1304;24;1328 +97220;Rivière-Pilote;11935;132;12067 +97221;Rivière-Salée;12168;219;12387 +97222;Le Robert;22719;209;22928 +97223;Saint-Esprit;9432;88;9520 +97224;Saint-Joseph;16232;228;16460 +97225;Saint-Pierre;4123;55;4178 +97226;Sainte-Anne;4298;58;4356 +97227;Sainte-Luce;9816;221;10037 +97228;Sainte-Marie;15932;150;16082 +97229;Schœlcher;19997;225;20222 +97230;La Trinité;12243;173;12416 +97231;Les Trois-Îlets;7339;127;7466 +97232;Le Vauclin;8844;97;8941 +97360;Apatou;9241;4;9245 +97361;Awala-Yalimapo;1411;12;1423 +97356;Camopi;1805;23;1828 +97302;Cayenne;61268;377;61645 +97357;Grand-Santi;7918;33;7951 +97303;Iracoubo;1799;20;1819 +97304;Kourou;25685;228;25913 +97305;Macouria;14202;153;14355 +97306;Mana;10894;165;11059 +97353;Maripasoula;13227;124;13351 +97307;Matoury;31956;277;32233 +97313;Montsinéry-Tonnegrande;2589;20;2609 +97314;Ouanary;200;1;201 +97362;Papaichton;6668;21;6689 +97301;Régina;876;25;901 +97309;Remire-Montjoly;25122;416;25538 +97310;Roura;3783;59;3842 +97358;Saint-Élie;242;1;243 +97308;Saint-Georges;4131;89;4220 +97311;Saint-Laurent-du-Maroni;42612;324;42936 +97352;Saül;152;8;160 +97312;Sinnamary;2919;44;2963 +97401;Les Avirons;11345;166;11511 +97402;Bras-Panon;12811;181;12992 +97424;Cilaos;5456;81;5537 +97403;Entre-Deux;6902;67;6969 +97404;L' Étang-Salé;13894;209;14103 +97405;Petite-Île;12162;111;12273 +97406;La Plaine-des-Palmistes;6565;94;6659 +97407;Le Port;34128;310;34438 +97408;La Possession;33020;354;33374 +97409;Saint-André;56268;421;56689 +97410;Saint-Benoît;37759;254;38013 +97411;Saint-Denis;147931;1382;149313 +97412;Saint-Joseph;37644;522;38166 +97413;Saint-Leu;33576;454;34030 +97414;Saint-Louis;53365;591;53956 +97415;Saint-Paul;104519;1368;105887 +97417;Saint-Philippe;5260;53;5313 +97416;Saint-Pierre;84212;871;85083 +97418;Sainte-Marie;33839;391;34230 +97419;Sainte-Rose;6418;79;6497 +97420;Sainte-Suzanne;23505;199;23704 +97421;Salazie;7312;75;7387 +97422;Le Tampon;78629;1076;79705 +97423;Les Trois-Bassins;7139;95;7234 diff --git a/source/manipulation/polars/data/departement2021.csv b/source/manipulation/polars/data/departement2021.csv new file mode 100644 index 00000000..fe9fd697 --- /dev/null +++ b/source/manipulation/polars/data/departement2021.csv @@ -0,0 +1,102 @@ +DEP,REG,CHEFLIEU,TNCC,NCC,NCCENR,LIBELLE +01,84,01053,5,AIN,Ain,Ain +02,32,02408,5,AISNE,Aisne,Aisne +03,84,03190,5,ALLIER,Allier,Allier +04,93,04070,4,ALPES DE HAUTE PROVENCE,Alpes-de-Haute-Provence,Alpes-de-Haute-Provence +05,93,05061,4,HAUTES ALPES,Hautes-Alpes,Hautes-Alpes +06,93,06088,4,ALPES MARITIMES,Alpes-Maritimes,Alpes-Maritimes +07,84,07186,5,ARDECHE,Ardèche,Ardèche +08,44,08105,4,ARDENNES,Ardennes,Ardennes +09,76,09122,5,ARIEGE,Ariège,Ariège +10,44,10387,5,AUBE,Aube,Aube +11,76,11069,5,AUDE,Aude,Aude +12,76,12202,5,AVEYRON,Aveyron,Aveyron +13,93,13055,4,BOUCHES DU RHONE,Bouches-du-Rhône,Bouches-du-Rhône +14,28,14118,2,CALVADOS,Calvados,Calvados +15,84,15014,2,CANTAL,Cantal,Cantal +16,75,16015,3,CHARENTE,Charente,Charente +17,75,17300,3,CHARENTE MARITIME,Charente-Maritime,Charente-Maritime +18,24,18033,2,CHER,Cher,Cher +19,75,19272,3,CORREZE,Corrèze,Corrèze +21,27,21231,3,COTE D OR,Côte-d'Or,Côte-d'Or +22,53,22278,4,COTES D ARMOR,Côtes-d'Armor,Côtes-d'Armor +23,75,23096,3,CREUSE,Creuse,Creuse +24,75,24322,3,DORDOGNE,Dordogne,Dordogne +25,27,25056,2,DOUBS,Doubs,Doubs +26,84,26362,3,DROME,Drôme,Drôme +27,28,27229,5,EURE,Eure,Eure +28,24,28085,1,EURE ET LOIR,Eure-et-Loir,Eure-et-Loir +29,53,29232,2,FINISTERE,Finistère,Finistère +2A,94,2A004,3,CORSE DU SUD,Corse-du-Sud,Corse-du-Sud +2B,94,2B033,3,HAUTE CORSE,Haute-Corse,Haute-Corse +30,76,30189,2,GARD,Gard,Gard +31,76,31555,3,HAUTE GARONNE,Haute-Garonne,Haute-Garonne +32,76,32013,2,GERS,Gers,Gers +33,75,33063,3,GIRONDE,Gironde,Gironde +34,76,34172,5,HERAULT,Hérault,Hérault +35,53,35238,1,ILLE ET VILAINE,Ille-et-Vilaine,Ille-et-Vilaine +36,24,36044,5,INDRE,Indre,Indre +37,24,37261,1,INDRE ET LOIRE,Indre-et-Loire,Indre-et-Loire +38,84,38185,5,ISERE,Isère,Isère +39,27,39300,2,JURA,Jura,Jura +40,75,40192,4,LANDES,Landes,Landes +41,24,41018,2,LOIR ET CHER,Loir-et-Cher,Loir-et-Cher +42,84,42218,3,LOIRE,Loire,Loire +43,84,43157,3,HAUTE LOIRE,Haute-Loire,Haute-Loire +44,52,44109,3,LOIRE ATLANTIQUE,Loire-Atlantique,Loire-Atlantique +45,24,45234,2,LOIRET,Loiret,Loiret +46,76,46042,2,LOT,Lot,Lot +47,75,47001,2,LOT ET GARONNE,Lot-et-Garonne,Lot-et-Garonne +48,76,48095,3,LOZERE,Lozère,Lozère +49,52,49007,0,MAINE ET LOIRE,Maine-et-Loire,Maine-et-Loire +50,28,50502,3,MANCHE,Manche,Manche +51,44,51108,3,MARNE,Marne,Marne +52,44,52121,3,HAUTE MARNE,Haute-Marne,Haute-Marne +53,52,53130,3,MAYENNE,Mayenne,Mayenne +54,44,54395,0,MEURTHE ET MOSELLE,Meurthe-et-Moselle,Meurthe-et-Moselle +55,44,55029,3,MEUSE,Meuse,Meuse +56,53,56260,2,MORBIHAN,Morbihan,Morbihan +57,44,57463,3,MOSELLE,Moselle,Moselle +58,27,58194,3,NIEVRE,Nièvre,Nièvre +59,32,59350,2,NORD,Nord,Nord +60,32,60057,5,OISE,Oise,Oise +61,28,61001,5,ORNE,Orne,Orne +62,32,62041,2,PAS DE CALAIS,Pas-de-Calais,Pas-de-Calais +63,84,63113,2,PUY DE DOME,Puy-de-Dôme,Puy-de-Dôme +64,75,64445,4,PYRENEES ATLANTIQUES,Pyrénées-Atlantiques,Pyrénées-Atlantiques +65,76,65440,4,HAUTES PYRENEES,Hautes-Pyrénées,Hautes-Pyrénées +66,76,66136,4,PYRENEES ORIENTALES,Pyrénées-Orientales,Pyrénées-Orientales +67,44,67482,2,BAS RHIN,Bas-Rhin,Bas-Rhin +68,44,68066,2,HAUT RHIN,Haut-Rhin,Haut-Rhin +69,84,69123,2,RHONE,Rhône,Rhône +70,27,70550,3,HAUTE SAONE,Haute-Saône,Haute-Saône +71,27,71270,0,SAONE ET LOIRE,Saône-et-Loire,Saône-et-Loire +72,52,72181,3,SARTHE,Sarthe,Sarthe +73,84,73065,3,SAVOIE,Savoie,Savoie +74,84,74010,3,HAUTE SAVOIE,Haute-Savoie,Haute-Savoie +75,11,75056,0,PARIS,Paris,Paris +76,28,76540,3,SEINE MARITIME,Seine-Maritime,Seine-Maritime +77,11,77288,0,SEINE ET MARNE,Seine-et-Marne,Seine-et-Marne +78,11,78646,4,YVELINES,Yvelines,Yvelines +79,75,79191,4,DEUX SEVRES,Deux-Sèvres,Deux-Sèvres +80,32,80021,3,SOMME,Somme,Somme +81,76,81004,2,TARN,Tarn,Tarn +82,76,82121,2,TARN ET GARONNE,Tarn-et-Garonne,Tarn-et-Garonne +83,93,83137,2,VAR,Var,Var +84,93,84007,2,VAUCLUSE,Vaucluse,Vaucluse +85,52,85191,3,VENDEE,Vendée,Vendée +86,75,86194,3,VIENNE,Vienne,Vienne +87,75,87085,3,HAUTE VIENNE,Haute-Vienne,Haute-Vienne +88,44,88160,4,VOSGES,Vosges,Vosges +89,27,89024,5,YONNE,Yonne,Yonne +90,27,90010,2,TERRITOIRE DE BELFORT,Territoire de Belfort,Territoire de Belfort +91,11,91228,5,ESSONNE,Essonne,Essonne +92,11,92050,4,HAUTS DE SEINE,Hauts-de-Seine,Hauts-de-Seine +93,11,93008,3,SEINE SAINT DENIS,Seine-Saint-Denis,Seine-Saint-Denis +94,11,94028,2,VAL DE MARNE,Val-de-Marne,Val-de-Marne +95,11,95500,2,VAL D OISE,Val-d'Oise,Val-d'Oise +971,01,97105,3,GUADELOUPE,Guadeloupe,Guadeloupe +972,02,97209,3,MARTINIQUE,Martinique,Martinique +973,03,97302,3,GUYANE,Guyane,Guyane +974,04,97411,0,LA REUNION,La Réunion,La Réunion +976,06,97608,0,MAYOTTE,Mayotte,Mayotte diff --git a/source/manipulation/polars/data/departement2021.parquet b/source/manipulation/polars/data/departement2021.parquet new file mode 100644 index 0000000000000000000000000000000000000000..a511fc27c76d41cdfe550ad259c6d6cb4edf3369 GIT binary patch literal 9640 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

93__b*eilrSVT^&F^GCHmu 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%0D`*i=n)D=_x`5c_u4L#?^;uEk`^Xs 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�B^?=k$hb+wTeY#;+HZC` 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 literal 0 HcmV?d00001 diff --git a/source/manipulation/polars/output/.gitignore b/source/manipulation/polars/output/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/source/manipulation/polars/output/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd new file mode 100644 index 00000000..417d8285 --- /dev/null +++ b/source/manipulation/polars/tutorial.qmd @@ -0,0 +1,4173 @@ +::: {.content-visible when-profile="fr"} +# Traiter des données tabulaires avec Polars + +L'analyse statistique a généralement pour base des **données tabulaires**, dans lesquelles chaque ligne représente une observation et chaque colonne une variable. Pour traiter ce type de données et y appliquer facilement les méthodes d'analyse de données standards, des objets dédiés ont été conçus : les `DataFrames`. Les utilisateurs de `R` connaissent bien cette structure de données, qui est native à ce langage orienté statistique. En `Python`, langage généraliste, cet objet n'existe pas nativement. Heureusement, une librairie très complete et bien pratique, pensée comme une surcouche à `NumPy`, introduit en `Python` l'objet `DataFrame` et permet la manipulation et l'analyse de données de manière simple et intuitive : `Pandas`. + +::: {.callout-note} +Pandas étant l'élément central de l'éco-système data science en Python, il offre des possibilités de traitement de la donnée quasi-infinies. En plus de ça, il existe généralement de multiples manières de réaliser une même opération en Pandas. En conséquence, ce chapitre est particulièrement long et dense en nouvelles fonctionnalités. L'objectif n'est pas de retenir toutes les méthodes présentées tout au long de ce chapitre, mais plutôt d'avoir une vision générale de ce qu'il est possible de faire afin de pouvoir mobiliser les bons outils dans les projets. En particulier, les exercices de fin de chapitre et les mini-projets de fin de formation seront l'occasion d'appliquer ces nouvelles connaissances à des problématiques concrètes. +::: + +On commence par importer la librairie `Pandas`. L'usage est courant est de lui attribuer l'alias `pd` afin de simplifier les futurs appels aux objets et fonctions du package. On importe également `NumPy` car on va comparer les objets fondamentaux des deux packages. + +```{python} +import pandas as pd +import numpy as np +``` + + + + + +## Structures de données + +Pour bien comprendre le fonctionnement de `Pandas`, il faut s'intéresser à ses objets fondamentaux. On va donc d'abord étudier les `Series`, dont la concaténation permet de construire un `DataFrame`. + +### La `Series` + +Une Series est un conteneur de données unidimensionnel pouvant accueillir n'importe quel type de données (entiers, *strings*, objets Python...). Une Series est néanmoins d'un type donné : une Series ne contenant que des entiers sera de type `int`, et une Series contenant des objets de différente nature sera de type `object`. Construisons notre première Series à partir d'une liste pour vérifier ce comportement. + +```{python} +l = [1, "X", 3] +s = pd.Series(l) +print(s) +``` + +On peut notamment accéder aux données d'une Series par position, comme pour une liste ou un array. + +```{python} +print(s[1]) +``` + +A priori, on ne voit pas beaucoup de différence entre une Series et un *array* `NumPy` à 1 dimension. Pourtant, il existe une différence de taille qui est la présence d'un index : les observations ont un label associé. Lorsqu'on crée une Series sans rien spécifier, l'index est automatiquement fixé aux entiers de 0 à n-1 (avec n le nombre d'éléments de la Series). Mais il est possible de passer un index spécifique (ex : des dates, des noms de communes, etc.). + +```{python} +s = pd.Series(l, index=["a", "b", "c"]) +print(s) +``` + +Ce qui permet d'accéder aux données par label : + +```{python} +s["b"] +``` + +Cette différence apparaît secondaire à première vue, mais deviendra essentielle pour la construction du DataFrame. Pour le reste, les Series se comportent de manière très proche des arrays NumPy : les calculs sont vectorisés, on peut directement faire la somme de deux Series, etc. D'ailleurs, on peut très facilement convertir une Series en array via l'attribut `values`. Ce qui, naturellement, fait perdre l'index... + +```{python} +s = pd.Series(l, index=["a", "b", "c"]) +s.values +``` + +### Le `DataFrame` + +Fondamentalement, un DataFrame consiste en une collection de Series, alignées par les index. Cette concaténation construit donc une table de données, dont les Series correspondent aux colonnes, et dont l'index identifie les lignes. La figure suivante ([source](https://www.geeksforgeeks.org/creating-a-pandas-dataframe/)) permet de bien comprendre cette structure de données. + +![](img/structure_df.png){fig-align="center" width="800"} + +Un DataFrame peut être construit de multiples manières. En pratique, on construit généralement un DataFrame directement à partir de fichiers de données tabulaires (ex : CSV, excel), rarement à la main. On illustrera donc seulement la méthode de construction manuelle la plus usuelle : à partir d'un dictionnaire de données. + +```{python} +df = pd.DataFrame( + data = { + "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var2": np.random.randint(-10, 10, 6), + "experiment": ["test", "train", "test", "train", "train", "validation"], + "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-01-05", "2022-01-06"], + "sample": "sample1" + } +) + +df +``` + +Un DataFrame Pandas dispose d'un ensemble d'attributs utiles que nous allons découvrir tout au long de ce tutoriel. Pour l'instant, intéressons-nous aux plus basiques : l'index et le nom des colonnes. Par défaut, l'index est initialisé comme pour les Series à la liste des positions des observations. On aurait pu spécifier un index alternatif lors de la construction du DataFrame en spécifiant l'argument `index` de la fonction `pd.DataFrame`. + +```{python} +df.index +``` + +```{python} +df.columns +``` + +Souvent, plutôt que de spécifier un index à la main lors de la construction du DataFrame, on va vouloir utiliser une certaine colonne du DataFrame comme index. On utilise pour cela la méthode `set_index` associée aux DataFrames. + +```{python} +df = df.set_index("date") +df +``` + +L'attribut index a naturellement changé : + +```{python} +df.index +``` + + + + + +## Sélectionner des données + +Lors de la manipulation des données tabulaires, il est fréquent de vouloir extraire des colonnes spécifiques d'un `DataFrame`. Cette extraction est simple avec `Pandas` grâce à l'utilisation des crochets. + +### Sélectionner des colonnes + +#### Sélectionner une seule colonne + +Pour extraire une seule colonne, on peut utiliser la syntaxe suivante : + +```{python} +selected_column = df["var1"] +selected_column +``` + +L'objet `selected_column` renvoie ici la colonne nommée `var1` du `DataFrame` `df`. Mais de quel type est cet objet ? Pour répondre à cette question, on utilise la fonction `type()` : + +```{python} +type(selected_column) +``` + +Comme on peut le voir, le résultat est une `Series`, qui est un objet unidimensionnel dans `Pandas`. + +Un autre attribut utile à connaître est `shape`. Il permet de connaître la dimension de l'objet. Pour une `Series`, `shape` retournera un tuple dont le premier élément indique le nombre de lignes. +```{python} +selected_column.shape +``` + +#### Sélectionner plusieurs colonnes + +Pour extraire plusieurs colonnes, il suffit de passer une liste des noms des colonnes souhaitées : + +```{python} +selected_columns = df[["var1", "var2", "experiment"]] +selected_columns +``` + +Cet extrait montre les colonnes `var1`, `var2` et `experiment` du `DataFrame` `df`. Vérifions maintenant son type : + +```{python} +type(selected_columns) +``` + +Le résultat est un `DataFrame`, car il s'agit d'un objet bidimensionnel. On peut aussi vérifier sa forme avec l'attribut `shape`. Dans ce cas, le tuple renvoyé par `shape` contiendra deux éléments : le nombre de lignes et le nombre de colonnes. + +```{python} +selected_columns.shape +``` + +### Sélectionner des lignes + +#### Utilisation de `loc` et `iloc` + +Lorsqu'on veut sélectionner des lignes spécifiques dans un DataFrame, on peut se servir des deux principales méthodes : `loc` et `iloc`. + + +- `iloc` permet de sélectionner des lignes et des colonnes par leur position, c'est-à-dire par des indices numériques. + +Exemple, sélection des 3 premières lignes : +```{python} +df.iloc[0:3, :] +``` + + +- `loc` quant à lui, fonctionne avec des labels. Si les index du DataFrame sont des numéros, ils ressemblent aux positions, mais ce n'est pas forcément le cas. Il est crucial de noter que, contrairement à `iloc`, avec `loc`, l'index de fin est inclus dans la sélection. + +```{python} +df.loc["2022-01-01":"2022-01-03", :] +``` + +#### Filtrage des données selon des conditions + +En pratique, plutôt que de sélectionner des lignes basées sur des positions ou des labels, on souhaite souvent filtrer un DataFrame selon certaines conditions. Dans ce cas, on se sert principalement de filtres booléens. + + +- **Inégalités** : On peut vouloir garder seulement les lignes qui respectent une certaine condition. + +Exemple, filtrer les lignes où la valeur de la colonne `var2` est supérieure à 0 : +```{python} +df[df['var2'] >= 0] +``` + + +- **Appartenance avec `isin`** : Si on veut filtrer les données basées sur une liste de valeurs possibles, la méthode `isin` est très utile. + +Exemple, pour garder uniquement les lignes où la colonne `experiment` a des valeurs 'test' ou 'validation' : +```{python} +df[df['experiment'].isin(['train', 'validation'])] +``` + +Ces méthodes peuvent être combinées pour créer des conditions plus complexes. Il est aussi possible d'utiliser les opérateurs logiques (`&` pour "et", `|` pour "ou") pour combiner plusieurs conditions. Attention, il faut bien prendre soin d'encadrer chaque condition par des parenthèses lors de la combinaison. + +Exemple, sélectionner les lignes où `var2` est supérieur à 0 et `experiment` est égal à 'test' ou 'validation': +```{python} +df[(df['var2'] >= 0) & (df['experiment'].isin(['train', 'validation']))] +``` + + + + + +## Explorer des données tabulaires + +En statistique publique, le point de départ n'est généralement pas la génération manuelle de données, mais plutôt des fichiers tabulaires préexistants. Ces fichiers, qu'ils soient issus d'enquêtes, de bases administratives ou d'autres sources, constituent la matière première pour toute analyse ultérieure. Pandas offre des outils puissants pour importer ces fichiers tabulaires et les explorer en vue de manipulations plus poussées. + +### Importer et exporter des données + +#### Importer un fichier CSV + +Comme nous l'avons vu dans un précédent TP, le format CSV est l'un des formats les plus courants pour stocker des données tabulaires. Nous avons précédemment utilisé la librairie `csv` pour les manipuler comme des fichiers texte, mais ce n'était pas très pratique. Pour rappel, la syntaxe pour lire un fichier CSV et afficher les premières lignes était la suivante : + +```{python} +import csv + +rows = [] + +with open("data/departement2021.csv") as file_in: + csv_reader = csv.reader(file_in) + for row in csv_reader: + rows.append(row) + +rows[:5] +``` + +Avec Pandas, il suffit d'utiliser la fonction `read_csv()` pour importer le fichier comme un DataFrame, puis la fonction `head()`. + +```{python} +df_departements = pd.read_csv('data/departement2021.csv') +df_departements.head() +``` + +Il est également possible d'importer un fichier CSV directement à partir d'une URL. C'est particulièrement pratique lorsque les données sont régulièrement mises à jour sur un site web et que l'on souhaite accéder à la version la plus récente sans avoir à télécharger manuellement le fichier à chaque fois. Prenons l'exemple d'un fichier CSV disponible sur le site de l'INSEE : le fichier des prénoms, issu des données de l'état civil. On note au passage une autre fonctionnalité bien pratique : le fichier CSV est compressé (format `zip`), mais Pandas est capable de le reconnaître et de le décompresser avant de l'importer. + +```{python} +# Importer un fichier CSV depuis une URL +url = "https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip" +df_prenoms_url = pd.read_csv(url, sep=";") +df_prenoms_url.head() +``` + +Lorsqu'on travaille avec des fichiers CSV, il y a de nombreux arguments optionnels disponibles dans la fonction `read_csv()` qui permettent d'ajuster le processus d'importation en fonction des spécificités du fichier. Ces arguments peuvent notamment permettre de définir un délimiteur spécifique (comme ci-dessus pour le fichier des prénoms), de sauter certaines lignes en début de fichier, ou encore de définir les types de données pour chaque colonne, et bien d'autres. Tous ces paramètres et leur utilisation sont détaillés dans la [documentation officielle](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html). + +#### Exporter au format CSV + +Une fois que les données ont été traitées et modifiées au sein de Pandas, il est courant de vouloir exporter le résultat sous forme de fichier CSV pour le partager, l'archiver ou l'utiliser dans d'autres outils. Pandas offre une méthode simple pour cette opération : `to_csv()`. Supposons par exemple que l'on souhaite exporter les données du DataFrame `df_departements` spécifiques aux cinq départements d'outre-mer. + +```{python} +df_departements_dom = df_departements[df_departements["DEP"].isin(["971", "972", "973", "974", "975"])] +df_departements_dom.to_csv('output/departements2021_dom.csv') +``` + +Un des arguments clés de la méthode `to_csv()` est `index`. Par défaut, `index=True`, ce qui signifie que l'index du DataFrame sera également écrit dans le fichier CSV. On peut le vérifier en imprimant les premières lignes de notre fichier CSV : Pandas a ajouté une colonne non-nommée, qui contient l'index des lignes retenues. + +```{python} +with open("output/departements2021_dom.csv") as file_in: + for i in range(5): + row = next(file_in).strip() + print(row) +``` + +Dans certains cas, notamment lorsque l'index n'apporte pas d'information utile ou est simplement généré automatiquement par Pandas, on pourrait vouloir l'exclure du fichier exporté. Pour ce faire, on peut définir `index=False`. + +```{python} +df_departements_dom.to_csv('output/departements2021_dom_noindex.csv', index=False) +``` + +#### Importer un fichier Parquet + +Le format Parquet est un autre format pour le stockage de données tabulaires, de plus en plus fréquemment utilisé. Sans entrer dans les détails techniques, le format Parquet présente différentes caractéristiques qui en font un choix privilégié pour le stockage et le traitement de gros volumes de données. En raison de ces avantages, ce format est de plus en plus utilisé pour la mise à disposition de données à l'Insee. Il est donc essentiel de savoir importer et requêter des fichiers Parquet avec Pandas. + +Importer un fichier Parquet dans un DataFrame Pandas se fait tout aussi facilement que pour un fichier CSV. La fonction se nomme `read_parquet()`. + +```{python} +df_departements = pd.read_parquet('data/departement2021.parquet') +df_departements.head() +``` + +#### Exporter au format Parquet + +Là encore, tout se passe comme dans le monde des CSV : on utilise la méthode `to_parquet()` pour exporter un DataFrame dans un fichier Parquet. De même, on peut choisir d'exporter ou non l'index, à l'aide du paramètre `index` (qui vaut `True` par défaut). + +```{python} +df_departements_dom = df_departements[df_departements["DEP"].isin(["971", "972", "973", "974", "975"])] +df_departements_dom.to_parquet('output/departements2021_dom.parquet', index=False) +``` + +Une des grandes forces du format Parquet, en comparaison des formats texte comme le CSV, est sa capacité à stocker des méta-données, i.e. des données permettant de mieux comprendre les données contenues dans le fichier. En particulier, un fichier Parquet inclut dans ses méta-données le schéma des données (noms des variables, types des variables, etc.), ce qui en fait un format très adapté à la diffusion de données. Vérifions ce comportement en reprenant le DataFrame que nous avons défini précédemment. + +```{python} +df = pd.DataFrame( + data = { + "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var2": np.random.randint(-10, 10, 6), + "experiment": ["test", "train", "test", "train", "train", "validation"], + "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-01-05", "2022-01-06"], + "sample": "sample1" + } +) + +df = df.assign( + experiment=pd.Categorical(df["experiment"]), + date=pd.to_datetime(df["date"]) +) +``` + +On utilise cette fois deux types de données spécifiques, pour les données catégorielles (`category`) et pour les données temporelles (`datetime`). On verra plus loin dans le tutoriel comment utiliser ces types. Pour l'instant, notons simplement que Pandas stocke ces types dans le schéma des données. + +```{python} +df.info() +``` + +Vérifions à présent que l'export et le ré-import de ces données en Parquet préserve le schéma. + +```{python} +df.to_parquet("output/df_test_schema.parquet", index=False) +df_test_schema_parquet = pd.read_parquet('output/df_test_schema.parquet') + +df_test_schema_parquet.info() +``` + +A l'inverse, un fichier CSV ne contenant par définition que du texte, ne permet pas de préserver ces données. Les variables dont nous avons spécifié le type sont importées comme des strings (type `object` en Pandas). + +```{python} +df.to_csv("output/df_test_schema.csv", index=False) +df_test_schema_csv = pd.read_csv('output/df_test_schema.csv') + +df_test_schema_csv.info() +``` + +### Visualiser un échantillon des données + +Lorsqu'on travaille avec des jeux de données volumineux, il est souvent utile de visualiser rapidement un échantillon des données pour avoir une idée de leur structure, de leur format ou encore pour détecter d'éventuels problèmes. Pandas offre plusieurs méthodes pour cela. + +La méthode `head()` permet d'afficher les premières lignes du DataFrame. Par défaut, elle retourne les 5 premières lignes, mais on peut spécifier un autre nombre en argument si nécessaire. + +```{python} +df_departements.head() +``` + +```{python} +df_departements.head(10) +``` + +À l'inverse, la méthode `tail()` donne un aperçu des dernières lignes du DataFrame. + +```{python} +df_departements.tail() +``` + +L'affichage des premières ou dernières lignes peut parfois ne pas être représentatif de l'ensemble du jeu de données, lorsque les données sont triées par exemple. Afin de minimiser le risque d'obtenir un aperçu biaisé des données, on peut utiliser la méthode `sample()`, qui sélectionne un un échantillon aléatoire de lignes. Par défaut, elle retourne une seule ligne, mais on peut demander un nombre spécifique de lignes en utilisant l'argument `n`. + +```{python} +df_departements.sample(n=5) +``` + +### Obtenir une vue d'ensemble des données + +L'une des premières étapes lors de l'exploration de nouvelles données est de comprendre la structure générale du jeu de données. La méthode `info()` de Pandas offre une vue d'ensemble rapide des données, notamment en termes de types de données, de présence de valeurs manquantes et de mémoire utilisée. + +```{python} +df.info() +``` + +Plusieurs éléments d'information clés peuvent être extraits de ce résultat : + +- **index** : le DataFrame a un `RangeIndex`, ce qui signifie que l'index est constitué d'une suite numérique simple. Ici, l'index va de 0 à 5, soit 6 entrées au total. + +- **schéma** : la liste des colonnes est affichée avec des informations très utiles sur le schéma des données : + + - **Non-Null Count** : le nombre de valeurs **non-manquantes** (non `nan`) dans la colonne. Si ce nombre est inférieur au nombre total d'entrées (dans notre cas, 6), cela signifie que la colonne contient des valeurs manquantes. Attention à l'ambiguité possible sur "null" : cela signifie bien les valeurs manquantes, pas les valeurs égales à 0. Ainsi, dans notre cas, le nombre de valeurs "non-null" pour la variable `var1` est 3. + + - **Dtype** : Le type de données de la colonne, qui permet de comprendre la nature des informations stockées dans chaque colonne. Par exemple, `float64` (nombres réels), `int32` (nombres entiers), `category` (variable catégorielle), `datetime64[ns]` (information temporelle) et `object` (données textuelles ou mixtes). + +L'utilisation de `info()` est un moyen rapide et efficace d'obtenir une vue d'ensemble d'un DataFrame, d'identifier rapidement les colonnes contenant des valeurs manquantes et de comprendre la structure des données. + +### Calculer des statistiques descriptives + +En complément des informations renvoyées par la méthode `info()`, on peut vouloir obtenir des statistiques descriptives simples afin de visualiser rapidement les distributions des variables. La méthode `describe()` permet d'avoir une vue synthétique de la distribution des données dans chaque colonne. + +```{python} +df.describe() +``` + +Il est à noter que `describe()` ne renvoie des statistiques que pour les colonnes numériques par défaut. Si l'on souhaite inclure des colonnes d'autres types, il est nécessaire de le préciser via l'argument `include`. Par exemple, `df.describe(include='all')` renverra des statistiques pour toutes les colonnes, y compris des métriques comme le nombre unique, la valeur la plus fréquente et la fréquence de la valeur la plus fréquente pour les colonnes non numériques. + +```{python} +df.describe(include='all') +``` + +Notons que, là encore, la variable `count` renvoie le nombre de valeurs **non-manquantes** dans chaque variable. + + + + + +## Principales manipulations de données + +### Transformer les données + +Les opérations de transformation sur les données sont essentielles pour façonner, nettoyer et préparer les données en vue de leur analyse. Les transformations peuvent concerner l'ensemble du DataFrame, des colonnes spécifiques ou encore des lignes spécifiques. + +#### Transformer un DataFrame + +Pour transformer un DataFrame complet (ou un sous-DataFrame), il est possible d'utiliser des fonctions vectorisées, qui permettent d'appliquer rapidement une opération à l'ensemble des éléments du DataFrame. Cela inclut un certain nombre de méthodes disponibles pour les `Series`, mais aussi les fonctions mathématiques de `NumPy`, etc. + +Par exemple, passer chaque valeur numérique d'un DataFrame à la puissance 2 : + +```{python} +df = pd.DataFrame( + data = { + "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var2": np.random.randint(-10, 10, 6), + } +) + +df ** 2 +``` + +ou les passer en valeur absolue : + +```{python} +np.abs(df) +``` + +Certaines méthodes, disponibles pour les `Series`, peuvent aussi être utilisées pour transformer un DataFrame complet. Par exemple, la bien utile méthode [replace()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.replace.html), qui permet de remplacer toutes les occurences d'une valeur donnée par une autre valeur. Par exemple, supposons que la valeur 0 dans la colonne `var1` indique en fait une erreur de mesure. Il serait préférable de la remplacer par une valeur manquante. + +```{python} +df.replace(0, np.nan) +``` + +::: {.callout-warning title="Assignation ou méthodes *in place* (en place) ?"} +Dans l'exemple précédent, l'application de la méthode [replace()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.replace.html) ne modifie pas directement le DataFrame. Pour que la modifiction soit persistente, une première possibilité est d'assigner le résultat à un objet : + +```{python} +df = df.replace(0, np.nan) +``` + +Une seconde possibilité est, lorsque les méthodes le proposent, d'utiliser l'argument `inplace`. Lorsque `inplace=True`, l'opération est effectuée "en place", et le DataFrame est donc modifié directement. + +```{python} +df.replace(0, np.nan, inplace=True) +``` + +En pratique, il est préférable de limiter les opérations `inplace`. Elles ne favorisent pas la reproductibilité des analyses, dans la mesure où la ré-exécution d'une même cellule va donner à chaque fois des résultats différents. +::: + +#### Transformer les colonnes + +Dans certains cas, on ne va pas vouloir appliquer les transformations à l'ensemble des données, mais à des variables spécifiques. Les transformations qui sont possibles à l'échelle du DataFrame (fonctions vectorisées, méthodes comme [replace()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.replace.html), etc.) restent naturellement possibles à l'échelle d'une colonne. + +```{python} +df = pd.DataFrame( + data = { + "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var2": np.random.randint(-10, 10, 6), + } +) + +np.abs(df["var2"]) +``` + +```{python} +df["var1"].replace(0, np.nan) +``` + +Mais il existe d'autres transformations que l'on applique généralement au niveau d'une ou de quelques colonnes. Par exemple, lorsque le schéma n'a pas été bien reconnu à l'import, il peut arriver que des variables numériques soient définies comme des string (type `object` en Pandas). + +```{python} +df = pd.DataFrame( + data = { + "var1": [1.3, 5.6, np.nan], + "var2": ["1", "5", "18"], + } +) + +df.info() +``` + +Dans ce cas, on peut utiliser la méthode `astype` pour convertir la colonne dans le type souhaité. + +```{python} +df['var2'] = df['var2'].astype(int) + +df.info() +``` + +Une autre opération fréquente est le renommage d'une ou plusieurs colonnes. Pour cela, on peut utiliser la méthode [rename()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.rename.html), à laquelle on passe un dictionnaire qui contient autant de couples clé-valeur que de variables à renommer, et dans lequel chaque couple clé-valeur est de la forme `'ancien_nom': 'nouveau_nom'`. + +```{python} +df.rename(columns={'var2': 'age'}) +``` + +Enfin, on peut souhaiter supprimer du DataFrame des colonnes qui ne sont pas ou plus utiles à l'analyse. Pour cela, on utilise la méthode [drop()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.drop.html), à laquelle on passe soit un string (nom d'une colonne si l'on souhaite n'en supprimer qu'une seule) ou une liste de noms de colonne à supprimer. + +```{python} +df.drop(columns=['var1']) +``` + +#### Transformer les lignes + +En statistiques, on applique généralement des tranformations faisant intervenir une ou plusieurs colonnes. Néanmoins, dans certains cas, il est nécessaire d'appliquer des transformations au niveau des lignes. Pour cela, on peut utiliser la méthode [apply()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.apply.html) de Pandas, appliquée à l'axe des lignes (`axis=1`). Illustrons son fonctionnement avec un cas simple. Pour cela, on génère d'abord des données. + +```{python} +df = pd.DataFrame( + data = { + "var1": [1, 5, 9, 13], + "var2": [3, 7, 11, 15], + "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04"], + } +) + +df.head() +``` + +On applique maintenant la fonction `apply()` au DataFrame afin de calculer une nouvelle variable qui est la somme des deux existantes. + +```{python} +df['sum_row'] = df.apply(lambda row: row['var1'] + row['var2'], axis=1) + +df.head() +``` + +::: {.callout-tip title="Les fonctions lambda"} +Une fonction `lambda` est une petite fonction anonyme. Elle peut prendre n'importe quel nombre d'arguments, mais ne peut avoir qu'une seule expression. Dans l'exemple ci-dessus, la fonction `lambda` prend une ligne en argument et renvoie la somme des colonnes `var1` et `var2` pour cette ligne. + +Les fonctions `lambda` permettent de définir simplement des fonctions "à la volée", sans devoir leur donner un nom. Dans notre exemple, cela aurait été parfaitement équivalent au code suivant : + +```{python} +def sum_row(row): + return row['var1'] + row['var2'] + +df['sum_row'] = df.apply(sum_row, axis=1) +``` + +::: + +Bien que `apply()` offre une grande flexibilité, elle n'est pas la méthode la plus efficiente, notamment pour de grands jeux de données. Les opérations vectorisées sont toujours préférables car elles traitent les données en bloc plutôt que ligne par ligne. Dans notre cas, il aurait été bien entendu préférable de créer notre variable en utilisant des opérations sur les colonnes. + +```{python} +df['sum_row_vect'] = df['var1'] + df['var2'] + +df.head() +``` + +Néanmoins, on peut se retrouver dans certains (rares) cas où une opération ne peut pas être facilement vectorisée ou où la logique est complexe. Supposons par exemple que l'on souhaite combiner les valeurs de plusieurs colonnes en fonction de certaines conditions. + +```{python} +def combine_columns(row): + if row['var1'] > 6: + return str(row['var2']) + else: + return str(row['var2']) + "_" + row['date'] + +df['combined_column'] = df.apply(combine_columns, axis=1) + +df +``` + +### Trier les valeurs + +Le tri des données est particulièrement utile pour l'exploration et la visualisation de données. Avec Pandas, on utilise la méthode [sort_values()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.sort_values.html) pour trier les valeurs d'un DataFrame selon une ou plusieurs colonnes. + +```{python} +df = pd.DataFrame( + data = { + "var1": [1, 5, 9, 13], + "var2": [3, 7, 11, 15], + "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04"], + } +) + +df +``` + +Pour trier les valeurs selon une seule colonne, il suffit de passer le nom de la colonne en paramètre. + +```{python} +df.sort_values(by='var1') +``` + +Par défaut, le tri est effectué dans l'ordre croissant. Pour trier les valeurs dans un ordre décroissant, il suffit de paramétrer `ascending=False`. + +```{python} +df.sort_values(by='var1', ascending=False) +``` + +Si on souhaite trier le DataFrame sur plusieurs colonnes, on peut fournir une liste de noms de colonnes. On peut également choisir de trier de manière croissante pour certaines colonnes et décroissante pour d'autres. + + + +### Agréger des données + +L'agrégation des données est un processus dans lequel les données vont être ventilées en groupes selon certains critères, puis agrégées selon une fonction d'agrégation appliquée indépendamment à chaque groupe. Cette opération est courante lors de l'analyse exploratoire ou lors du prétraitement des données pour la visualisation ou la modélisation statistique. + +```{python} +df = pd.DataFrame( + data = { + "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var2": np.random.randint(-10, 10, 6), + "experiment": ["test", "train", "test", "train", "train", "validation"], + "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-01-05", "2022-01-06"], + "sample": "sample1" + } +) + +df.head() +``` + +#### L'opération `groupBy` + +La méthode `groupBy` de Pandas permet de diviser le DataFrame en sous-ensembles selon les valeurs d'une ou plusieurs colonnes, puis d'appliquer une fonction d'agrégation à chaque sous-ensemble. Elle renvoie un objet de type `DataFrameGroupBy` qui ne présente pas de grand intérêt en soi, mais constitue l'étape intermédiaire indispensable pour pouvoir ensuite appliquer une ou plusieurs fonction(s) d'agrégation aux différents groupes. + +```{python} +df.groupby('experiment') +``` + +#### Fonctions d'agrégation + +Une fois les données groupées, on peut appliquer des fonctions d'agrégation pour obtenir un résumé statistique. Pandas intègre un certain nombre de ces fonctions, dont la liste complète est détaillée dans la [documentation](https://pandas.pydata.org/docs/user_guide/groupby.html#built-in-aggregation-methods). Voici quelques exemples d'utilisation de ces méthodes. + +Par exemple, compter le nombre d'occurrences dans chaque groupe. + +```{python} +df.groupby('experiment').size() +``` + +Calculer la somme d'une variable par groupe. + +```{python} +df.groupby('experiment')['var1'].sum() +``` + +Ou encore compter le nombre de valeurs unique d'une variable par groupe. Les possibilités sont nombreuses. + +```{python} +# Pour le nombre de valeurs uniques de 'var2' dans chaque groupe +df.groupby('experiment')['var2'].nunique() +``` + +Lorsqu'on souhaite appliquer plusieurs fonctions d'agrégation à la fois ou des fonctions personnalisées, on utilise la méthode `agg`. Cette méthode accepte une liste de fonctions ou un dictionnaire qui associe les noms des colonnes aux fonctions à appliquer. Cela permet d'appliquer plus finement les fonctions d'agrégation. + +```{python} +df.groupby('experiment').agg({'var1': 'mean', 'var2': 'count'}) +``` + +::: {.callout-note title="Le chaînage de méthodes"} +Les exemples précédents illustrent un concept important en Pandas : le chaînage de méthodes. Ce terme désigne la possibilité d'enchaîner les transformations appliquées à un DataFrame en lui appliquant à la chaîne des méthodes. A chaque méthode appliquée, un DataFrame intermédiaire est créé (mais non assigné à une variable), qui devient l'input de la méthode suivante. + +Le chaînage de méthodes permet de combiner plusieurs opérations en une seule expression de code. Cela peut améliorer l'efficacité en évitant les assignations intermédiaires et en rendant le code plus fluide et plus facile à lire. +Cela favorise également un style de programmation fonctionnel où les données passent à travers une chaîne de transformations de manière fluide. +::: + +#### Effets sur l'index + +Il est intéressant de noter les effets du processus d'agrégation sur l'index du DataFrame. Le dernier exemple ci-dessus l'illustre bien : les groupes, i.e. les modalités de la variable utilisée pour effectuer l'agrégation, deviennent les valeurs de l'index. + +On peut vouloir réutiliser cette information dans des analyses ultérieures, et donc la vouloir comme une colonne. Il suffit pour cela de réinitialiser l'index avec la méthode `reset_index()`. + +```{python} +df_agg = df.groupby('experiment').agg({'var1': 'mean', 'var2': 'count'}) +df_agg.reset_index() +``` + +### Traiter les valeurs manquantes + +Les valeurs manquantes sont une réalité courante dans le traitement des données réelles et peuvent survenir pour diverses raisons, telles que des non-réponses à un questionnaire, des erreurs de saisie, des pertes de données lors de la transmission ou simplement parce que l'information n'est pas applicable. Pandas offre plusieurs outils pour gérer les valeurs manquantes. + +#### Représentation des valeurs manquantes + +Dans Pandas, les valeurs manquantes sont généralement représentées par `np.nan`, qui est un marqueur spécial fourni par la bibliothèque `NumPy`. S'il est préférable d'utiliser cet objet pour dénoter les valeurs manquantes, notons que l'objet `None` de `Python` est également compris comme une valeur manquante par `Pandas`. + +Vérifions cette propriété. Pour identifier où se trouvent les valeurs manquantes, on utilise la fonction `isna()` qui retourne un DataFrame booléen indiquant `True` là où les valeurs sont `NaN`. + +```{python} +df = pd.DataFrame( + data = { + "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var2": np.random.randint(-10, 10, 6), + "experiment": ["test", "train", "test", None, "train", "validation"], + "sample": "sample1" + } +) + +df.isna() +``` + +#### Calculs sur des colonnes contenant des valeurs manquantes + +Lors de calculs statistiques, les valeurs manquantes sont généralement ignorées. Par exemple, la méthode `.mean()` calcule la moyenne des valeurs non manquantes. + +```{python} +df['var1'].mean() +``` + +En revanche, les calculs faisant intervenir plusieurs colonnes n'ignorent pas toujours les valeurs manquantes et peuvent souvent donner des résultats en `NaN`. + +```{python} +df['var3'] = df['var1'] + df['var2'] + +df +``` + +#### Suppression des valeurs manquantes + +La méthode `dropna()` permet de supprimer les lignes (`axis=0`) ou les colonnes (`axis=1`) contenant des valeurs manquantes. Par défaut, toute ligne contenant au moins une valeur manquante est supprimée. + +```{python} +df.dropna() +``` + +En modifiant le paramètre `axis`, on peut demander à ce que toute colonne contenant au moins une valeur manquante soit supprimée. + +```{python} +df.dropna(axis=1) +``` + +Enfin, le paramètre `how` définit la modalité de supression. Par défaut, une ligne ou colonne est supprimée lorsqu'au moins une valeur est manquante (`how=any`), mais il est possible de ne supprimer la ligne/colonne que lorsque toutes les valeurs sont manquantes (`how=all`). + +#### Remplacement des valeurs manquantes + +Pour gérer les valeurs manquantes dans un DataFrame, une approche commune est l'imputation, qui consiste à remplacer les valeurs manquantes par d'autres valeurs. La méthode `fillna()` permet d'effectuer cette opération de différentes manières. Une première possibilité est le remplacement par une valeur constante. + +```{python} +df['var1'].fillna(value=0) +``` + +::: {.callout-warning title="Changement de représentation des valeurs manquantes"} +Il peut parfois être tentant de changer la manifestation d'une valeur manquante pour des raisons de visibilité, par exemple en la remplaçant par une chaîne de caractères : + +```{python} +df['var1'].fillna(value="MISSING") +``` + +En pratique, cette façon de faire n'est pas recommandée. Il est en effet préférable de conserver la convention standard de `Pandas` (l'utilisation des `np.nan`), d'abord pour des questions de standardisation des pratiques qui facilitent la lecture et la maintenance du code, mais également parce que la convention standard est optimisée pour la performance et les calculs à partir de données contenant des valeurs manquantes. +::: + +Une autre méthode d'imputation fréquente est d'utiliser une valeur statistique, comme la moyenne ou la médiane de la variable. + +```{python} +df['var1'].fillna(value=df['var1'].mean()) +``` + +::: {.callout-warning title="Biais d'imputation"} +Remplacer les valeurs manquantes par une valeur constante, telle que zéro, la moyenne ou la médiane, peut être problématique. Si les données ne sont pas manquantes au hasard (*Missing Not At Random* - *MNAR*), cela peut introduire un biais dans l'analyse. Les variables *MNAR* sont des variables dont la probabilité d'être manquantes est liée à leur propre valeur ou à d'autres variables dans les données. Dans de tels cas, une imputation plus sophistiquée peut être nécessaire pour minimiser les distorsions. Nous en verrons un exemple en exercice de fin de tutoriel. +::: + +### Traiter les données de types spécifiques + +#### Données textuelles + +Les données textuelles nécessitent souvent un nettoyage et une préparation avant l'analyse. Pandas fournit via la librairie de méthodes `str` un ensemble d'opérations vectorisées qui rendent la préparation des données textuelles à la fois simple et très efficace. Là encore, les possibilités sont multiples et détaillées dans la [documentation](https://pandas.pydata.org/docs/user_guide/text.html). Nous présentons ici les méthodes les plus fréquemment utilisées dans l'analyse de données. + +```{python} +df = pd.DataFrame( + data = { + "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var2": np.random.randint(-10, 10, 6), + "experiment": ["test", "train", "test", "test", "train", "validation"], + "sample": [" sample1", "sample1", "sample2", " sample2 ", "sample2 ", "sample1"] + } +) + +df +``` + +Une première opération fréquente consiste à extraire certains caractères d'une chaîne. On utilise pour cela la fonction (à la syntaxe un peu particulière) `str[n:]` Par exemple, si l'on veut extraire le dernier caractère de la variable `sample` afin de ne retenir que le chiffre de l'échantillon. + +```{python} +df["sample_n"] = df["sample"].str[-1:] + +df +``` + +Le principe était le bon, mais la présence d'espaces superflus dans nos données textuelles (qui ne se voyaient pas à la visualisation du DataFrame !) a rendu l'opération plus difficile que prévue. C'est l'occasion d'introduire la famille de méthode `strip` (`.str.strip()`, `.str.lstrip()` et `.str.rstrip()`) qui respectivement retirent les espaces superflus des deux côtés ou d'un seul. + +```{python} +df["sample"] = df["sample"].str.strip() +df["sample_n"] = df["sample"].str[-1:] + +df +``` + +On peut également vouloir filtrer un DataFrame en fonction de la présence ou non d'une certaine chaîne (ou sous-chaîne) de caractères. On utilise pour cela la méthode `.str.contains()`. + +```{python} +df[df['experiment'].str.contains('test')] +``` + +Enfin, on peut vouloir remplacer une chaîne (ou sous-chaîne) de caractères par une autre, ce que permet la méthode `str.replace()`. + +```{python} +df['experiment'] = df['experiment'].str.replace('validation', 'val') + +df +``` + +#### Données catégorielles + +Les données catégorielles sont des variables qui contiennent un nombre restreint de modalités. A l'instar de `R` avec la notion de `factor`, Pandas a un type de données spécial, `category`, qui est utile pour représenter des données catégorielles de manière plus efficace et plus informative. Les données catégorielles sont en effet optimisées pour certains types de données et peuvent accélérer les opérations comme le groupement et le tri. Elles sont également utiles pour la visualisation, car elles permettent d'assurer que les catégories sont affichées dans un ordre cohérent et logique. + +Pour convertir une variable au format `category`, on utilise la méthode `astype()`. + +```{python} +df = pd.DataFrame( + data = { + "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var2": np.random.randint(-10, 10, 6), + "experiment": ["test", "train", "test", None, "train", "validation"], + } +) +print(df.dtypes) +``` + +```{python} +df['experiment'] = df['experiment'].astype('category') + +print(df.dtypes) +``` + +Cette conversion nous donne accès à quelques méthodes bien pratiques, spécifiques au traitement des variables catégorielles. Il peut par exemple être utile de renommer les catégories pour des raisons de clarté ou de standardisation. + +```{python} +df['experiment'] = df['experiment'].cat.rename_categories({'test': 'Test', 'train': 'Train', 'validation': 'Validation'}) +df +``` + +Parfois, l'ordre des catégories est significatif, et on peut vouloir le modifier. En particulier dans le cadre de la visualisation, car les modalités seront par défaut affichées dans l'ordre spécifié. + +```{python} +df_cat = df['experiment'].cat.reorder_categories(['Test', 'Train', 'Validation'], ordered=True) +df.groupby("experiment").mean().plot(kind='bar') +``` + +#### Données temporelles + +Les données temporelles sont souvent présentes dans les données tabulaires afin d'identifier temporellement les observations recueillies. Pandas offre des fonctionnalités pour manipuler ces types de données, notamment grâce au type `datetime64` qui permet une manipulation précise des dates et des heures. + +```{python} +df = pd.DataFrame( + data = { + "var1": [1, 5, 9, 13], + "var2": [3, 7, 11, 15], + "date": ["2022-01-01", "2022-01-02", "2023-01-01", "2023-01-02"], + "sample": ["sample1", "sample1", "sample2", "sample2"] + } +) + +df.dtypes +``` + +Pour manipuler les données temporelles, il est nécessaire de convertir les chaînes de caractères en objets `datetime`. Pandas le fait via la fonction `to_datetime()`. + +```{python} +df['date'] = pd.to_datetime(df['date']) + +df.dtypes +``` + +Une fois converties, les dates peuvent être formatées, comparées et utilisées dans des calculs. En particulier, Pandas comprend à présent l'"ordre" des dates présentes dans les données, et permet donc le filtrage sur des périodes données. + +```{python} +df[(df['date'] >= "2022-01-01") & (df['date'] < "2022-01-03")] +``` + +On peut également vouloir réaliser des filtrages moins précis, faisant intervenir l'année ou le mois. Pandas permet d'extraire facilement des composants spécifiques de la date, comme l'année, le mois, le jour, l'heure, etc. + +```{python} +df['year'] = df['date'].dt.year +df['month'] = df['date'].dt.month +df['day'] = df['date'].dt.day + +df[df['year'] == 2023] +``` + +Enfin, les calculs faisant intervenir des dates deviennent possible. On peut ajouter ou soustraire des périodes temporelles à des dates, et les comparer entre elles. Les fonctions utilisées sont issues de `Pandas`, mais sont très semblables dans leur fonctionnement à celles du module [time](https://docs.python.org/fr/3/library/time.html) de Python. + +On peut par exemple ajouter des intervalles de temps, ou bien calculer des écarts à une date de référence. + +```{python} +df['date_plus_one'] = df['date'] + pd.Timedelta(days=1) +df['date_diff'] = df['date'] - pd.to_datetime('2022-01-01') + +df +``` + +### Joindre des tables + +Dans le cadre d'une analyse de données, il est courant de vouloir combiner différentes sources de données. Cette combinaison peut se faire verticalement (un DataFrame par dessus l'autre), par exemple lorsque l'on souhaite combiner deux millésimes d'une même enquête afin de les analyser conjointement. La combinaison peut également se faire horizontalement (côte à côte) selon une ou plusieurs clé(s) de jointure, souvent dans le but d'enrichir une source de données à partir d'une autre source portant sur les mêmes unités statistiques. + +#### Concaténer des tables + +La concaténation verticale de tables se fait à l'aide de la fonction `concat()` de Pandas. + +```{python} +df1 = pd.DataFrame( + data = { + "var1": [1, 5], + "var2": [3, 7], + "date": ["2022-01-01", "2022-01-02"], + "sample": ["sample1", "sample1"] + } +) + +df2 = pd.DataFrame( + data = { + "var1": [9, 13], + "date": ["2023-01-01", "2023-01-02"], + "var2": [11, 15], + "sample": ["sample2", "sample2"] + } +) + +df_concat = pd.concat([df1, df2]) + +df_concat +``` + +Notons que l'ordre des variables dans les deux DataFrames n'est pas important. Pandas ne juxtapose pas "bêtement" les deux DataFrames, il fait une correspondance des schémas pour faire correspondre les variables par nom. Si deux variables ont le même nom mais pas le même type - par exemple dans le cas où une variable numérique aurait été interprétée comme des strings - Pandas va résoudre le problème en prenant le dénominateur commun, c'est à dire en général convertir en strings (type `object`). + +Par contre, la concaténation précédente laisse apparaître un problème de répétition au niveau de l'index. C'est logique : on n'a pas spécifié d'index pour nos deux DataFrames initiaux, qui ont donc le même index de position ([0, 1]). Dans ce cas (où l'index n'est pas important), on peut passer le paramètre `ignore_index=True` pour reconstruire de zéro l'index final. + +```{python} +df_concat = pd.concat([df1, df2], ignore_index=True) + +df_concat +``` + +::: {.callout-warning title="Construction itérative d'un DataFrame"} +On pourrait avoir l'idée d'utiliser `pd.concat()` pour construire un DataFrame de manière itérative, en ajoutant à chaque itération d'une boucle une nouvelle ligne au DataFrame existant. Ce n'est néanmoins pas une bonne idée : comme nous l'avons vu, un DataFrame est représenté dans la mémoire commme une juxtaposition de Series. Ainsi, ajouter une colonne à un DataFrame est peu coûteux, mais ajouter une ligne implique de modifier chaque élément constituant du DataFrame. Pour construire un DataFrame, il est donc plutôt conseillé de stocker les lignes dans une liste de listes (une par colonne) ou un dictionnaire, puis d'appeler `pd.DataFrame()` pour construire le DataFrame, comme nous l'avons fait au début de ce tutoriel. +::: + +#### Fusionner des tables + +La fusion de tables est une opération qui permet d'associer des lignes de deux DataFrames différents en se basant sur une ou plusieurs clés communes, similaire aux jointures dans les bases de données SQL. Différents types de jointure sont possible selon les données que l'on souhaite conserver, dont les principaux sont représentés sur le graphique suivant. + +![](img/joins.png) + +Source : [lien](https://medium.com/swlh/merging-dataframes-with-pandas-pd-merge-7764c7e2d46d) + +En Pandas, les jointures se font avec la fonction [merge()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.merge.html). Pour réaliser une jointure, on doit spécifier (au minimum) deux informations : + +- le type de jointure : par défaut, Pandas effectue une jointure de type `inner`. Le paramètre `how` permet de spécifier d'autres types de jointure ; + +- la clé de jointure. Par défaut, Pandas essaie de joindre les deux DataFrames à partir de leurs index. En pratique, on spécifie souvent une variable présente dans le DataFrames comme clé de jointure (paramètre `on` si la variable porte le même nom dans les deux DataFrame, ou `left_on` et `right_on` sinon). + +Analysons la différence entre les différents types de jointure à travers des exemples. + +```{python} +df_a = pd.DataFrame({ + 'key': ['K0', 'K1', 'K2', 'K3', 'K4'], + 'A': ['A0', 'A1', 'A2', 'A3', 'A4'], + 'B': ['B0', 'B1', 'B2', 'B3', 'A4'] +}) + +df_b = pd.DataFrame({ + 'key': ['K0', 'K1', 'K2', 'K5', 'K6'], + 'C': ['C0', 'C1', 'C2', 'C5', 'C6'], + 'D': ['D0', 'D1', 'D2', 'D5', 'D6'] +}) + +display(df_a) +display(df_b) +``` + +La jointure de type `inner` conserve les observations dont la clé est présente dans les deux DataFrame. + +```{python} +df_merged_inner = pd.merge(df_a, df_b, on='key') +df_merged_inner +``` + +::: {.callout-warning title="Jointures inner"} +La jointure de type `inner` est la plus intuitive : elle ne crée généralement pas de valeurs manquantes et permet donc de travailler directement sur la table fusionnée. Mais attention : si beaucoup de clés ne sont pas présentes dans les deux DataFrames à la fois, une jointure `inner` peut aboutit à des pertes importantes de données, et donc à des résultats finaux biaisés. Dans ce cas, il vaut mieux choisir une jointure à gauche ou à droite, selon la source que l'on cherche à enrichir et pour laquelle il est donc le plus important de limiter les pertes de données. +::: + +Une jointure de type `left` conserve toutes les observations contenues dans le DataFrame de gauche (premier DataFrame spécifié dans `pd.merge()`). Par conséquent, si des clés sont présentes dans le DataFrame de gauche mais pas dans celui de droite, le DataFrame final contient des valeurs manquantes au niveau de ces observations (pour les variables du DataFrame de droite). + +```{python} +df_merged_left = pd.merge(df_a, df_b, how="left", on='key') +df_merged_left +``` + +La jointure de type `outer` contient toutes les observations et variables contenues dans les deux DataFrame. Ainsi, l'information retenue est maximale, mais en contrepartie les valeurs manquantes peuvent être assez nombreuses. Il sera donc nécessaire de bien traiter les valeurs manquantes avant de procéder aux analyses. + +```{python} +df_merged_outer = pd.merge(df_a, df_b, how="outer", on='key') +df_merged_outer +``` + +## Exercices + +### Questions de compréhension + + +- 1/ Qu'est-ce qu'un DataFrame dans le contexte de Pandas et à quel type de structure de données peut-on le comparer dans le langage Python ? + +- 2/ Quelle est la différence fondamentale entre un array Numpy et une Pandas Series ? + +- 3/ Quel est le lien entre Series et DataFrame dans Pandas ? + +- 4/ Comment sont structurées les données dans un DataFrame Pandas ? + +- 5/ Quel est le rôle de l'index dans un DataFrame Pandas et comment peut-il être utilisé lors de la manipulation des données ? + +- 6/ Quelles méthodes pouvez-vous utiliser pour explorer un DataFrame inconnu et en apprendre davantage sur son contenu et sa structure ? + +- 7/ Dans Pandas, quelle est la différence entre assigner le résultat d'une opération à une nouvelle variable et utiliser une méthode avec l'argument `inplace=True` ? + +- 8/ Comment s'applique le principe de la vectorisation dans Pandas et pourquoi est-ce avantageux pour manipuler les données ? + +- 9/ Comment Pandas représente-t-il les valeurs manquantes et quel impact cela a-t-il sur les calculs et les transformations de données ? + +- 10/ Quelle est la différence entre concaténer deux DataFrames et les joindre via une jointure, et quand utiliseriez-vous l'une plutôt que l'autre ? + + +::: {.cell .markdown} + +

+Afficher la solution + +- 1/ Un DataFrame dans Pandas est une structure de données bidimensionnelle, comparable à un tableau ou une feuille de calcul Excel. Dans le contexte Python, on peut le comparer à un dictionnaire d'arrays NumPy, où les clés sont les noms des colonnes et les valeurs sont les colonnes elles-mêmes. + +- 2/ La différence principale entre un array NumPy et une Series Pandas est que la Series peut contenir des données étiquetées, c'est-à-dire qu'elle a un index qui lui est associé, permettant des accès et des manipulations par label. + +- 3/ Un DataFrame est essentiellement une collection de Series. Chaque colonne d'un DataFrame est une Series, et toutes ces Series partagent le même index, qui correspond aux étiquettes des lignes du DataFrame. + +- 4/ Les données dans un DataFrame Pandas sont structurées en colonnes et en lignes. Chaque colonne peut contenir un type de données différent (numérique, chaîne de caractères, booléen, etc.), et chaque ligne représente une observation. + +- 5/ L'index dans un DataFrame Pandas sert à identifier de manière unique chaque ligne du DataFrame. Il permet d'accéder rapidement aux lignes, de réaliser des jointures, de trier les données et de faciliter les opérations de regroupement. + +- 6/ Pour explorer un DataFrame inconnu, on peut utiliser df.head() pour voir les premières lignes, df.tail() pour les dernières, df.info() pour obtenir un résumé des types de données et des valeurs manquantes, et df.describe() pour des statistiques descriptives. + +- 7/ Assigner le résultat d'une opération à une nouvelle variable crée une copie du DataFrame avec les modifications appliquées. Utiliser une méthode avec inplace=True modifie le DataFrame original sans créer de copie, ce qui peut être plus efficace en termes de mémoire. + +- 8/ Pandas représente les valeurs manquantes avec l'objet `nan` (Not a Number) de `Numpy` pour les données numériques et avec None ou pd.NaT pour les dates/temps. Ces valeurs manquantes sont généralement ignorées dans les calculs de fonctions statistiques, ce qui peut affecter les résultats si elles ne sont pas traitées correctement. + +- 9/ Concaténer consiste à assembler des DataFrames en les empilant verticalement ou en les alignant horizontalement, principalement utilisé lorsque les DataFrames ont le même schéma ou lorsque vous souhaitez empiler les données. Les jointures, inspirées des opérations JOIN en SQL, combinent les DataFrames sur la base de valeurs de clés communes et sont utilisées pour enrichir un ensemble de données avec des informations d'un autre ensemble. + +
+ +::: + +### Plusieurs manières de créer un DataFrame + +Dans la cellule suivante, nous avons récupéré des données de caisses sur les ventes de différentes enseignes. Les données sont cependant présentées de deux manières différentes, dans un cas sous forme d'observations (chaque liste contient les données d'une ligne), dans l'autre sous forme de variables (chaque liste contient les données d'une colonne). + +```{python} +data_list1 = [ + ['Carrefour', '01.1.1', 3, 1.50], + ['Casino', '02.1.1', 2, 2.30], + ['Lidl', '01.1.1', 7, 0.99], + ['Carrefour', '03.1.1', 5, 5.00], + ['Casino', '01.1.1', 10, 1.20], + ['Lidl', '02.1.1', 1, 3.10] +] + +data_list2 = [ + ['Carrefour', 'Casino', 'Lidl', 'Carrefour', 'Casino', 'Lidl'], + ['01.1.1', '02.1.1', '01.1.1', '03.1.1', '01.1.1', '02.1.1'], + [3, 2, 7, 5, 10, 1], + [1.50, 2.30, 0.99, 5.00, 1.20, 3.10] +] +``` + +L'objectif est de construire dans les deux cas un même DataFrame qui contient chacune des 6 observations et des 4 variables, avec les mêmes noms dans les deux DataFrame. A chaque cas va correspondre une structure de données plus adaptée en entrée, dictionnaire ou liste de listes... faîtes le bon choix ! On vérifiera que les deux DataFrames sont identiques à l'aide de la méthode [equals()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.equals.html). + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +data_list1 = [ + ['Carrefour', 'Casino', 'Lidl', 'Carrefour', 'Casino', 'Lidl'], + ['01.1.1', '02.1.1', '01.1.1', '03.1.1', '01.1.1', '02.1.1'], + [3, 2, 7, 5, 10, 1], + [1.50, 2.30, 0.99, 5.00, 1.20, 3.10] +] + +data_list2 = [ + ['Carrefour', '01.1.1', 3, 1.50], + ['Casino', '02.1.1', 2, 2.30], + ['Lidl', '01.1.1', 7, 0.99], + ['Carrefour', '03.1.1', 5, 5.00], + ['Casino', '01.1.1', 10, 1.20], + ['Lidl', '02.1.1', 1, 3.10] +] + +# Si les données sont sous forme de colonnes : à partir d'un dictionnaire +data_dict = { + 'enseigne': data_list1[0], + 'produit': data_list1[1], + 'quantite': data_list1[2], + 'prix': data_list1[3] +} + +df_from_dict = pd.DataFrame(data_dict) + +# Si les données sont sous forme de lignes : à partir d'une liste de listes +columns = ['enseigne', 'produit', 'quantite', 'prix'] +df_from_list = pd.DataFrame(data_list2, columns=columns) + +# Vérification +df_from_dict.equals(df_from_list) +``` + +
+ +::: + +### Sélection de données dans un DataFrame + +Un DataFrame Pandas est créé avec des données de caisse (mêmes données que l'exercice précédent). + +```{python} +data = { + 'enseigne': ['Carrefour', 'Casino', 'Lidl', 'Carrefour', 'Casino', 'Lidl'], + 'produit': ['01.1.1', '02.1.1', '01.1.1', '03.1.1', '01.1.1', '02.1.1'], + 'quantite': [3, 2, 7, 5, 10, 1], + 'prix': [1.50, 2.30, 0.99, 5.00, 1.20, 3.10], + 'date_heure': pd.to_datetime(["2022-01-01 14:05", "2022-01-02 09:30", + "2022-01-03 17:45", "2022-01-04 08:20", + "2022-01-05 19:00", "2022-01-06 16:30"]) +} + +df = pd.DataFrame(data) +``` + +Utilisez les méthodes `loc` et `iloc` pour sélectionner des données spécifiques : + +- Sélectionner les données de la première ligne. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +print(df.iloc[0]) +``` + +
+ +::: + +- Sélectionner toutes les données de la colonne "prix". + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +print(df.loc[:, 'prix']) +``` + +
+ +::: + +- Sélectionner les lignes correspondant à l'enseigne "Carrefour" uniquement. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +print(df.loc[df['enseigne'] == 'Carrefour']) +``` + +
+ +::: + +- Sélectionner les quantités achetées pour les produits classifiés "01.1.1" (Pain). + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +print(df.loc[df['produit'] == '01.1.1', 'quantite']) +``` + +
+ +::: + +- Sélectionner les données des colonnes "enseigne" et "prix" pour toutes les lignes. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +print(df.loc[:, ['enseigne', 'prix']]) +``` + +
+ +::: + +- Sélectionner les lignes où la quantité achetée est supérieure à 5. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +print(df.loc[df['quantite'] > 5]) +``` + +
+ +::: + +- Filtrer pour sélectionner toutes les transactions qui ont eu lieu après 15h. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +print(df.loc[df['date_heure'].dt.hour > 15]) +``` + +
+ +::: + +- Sélectionner les transactions qui ont eu lieu le "2022-01-03". + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +print(df.loc[df['date_heure'].dt.date == pd.to_datetime('2022-01-03').date()]) +``` + +
+ +::: + +### Exploration du fichier des prénoms + +Le fichier des prénoms contient des données sur les prénoms attribués aux enfants nés en France entre 1900 et 2021. Ces données sont disponibles au niveau France, par département et par région, à l'adresse suivante : [https://www.insee.fr/fr/statistiques/2540004?sommaire=4767262](https://www.insee.fr/fr/statistiques/2540004?sommaire=4767262). L'objectif de ce tutoriel est de proposer une analyse de ce fichier, du nettoyage des données au statistiques sur les prénoms. + +#### Partie 1 : Import et exploration des données + + +- Importez les données dans un DataFrame en utilisant cette [URL](https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip). +- Visualisez un échantillon des données. Repérez-vous d'éventuelles anomalies ? +- Affichez les principales informations du DataFrame. Repérez d'éventuelles variables dont le type serait incorrect, ou bien d'éventuelles valeurs manquantes. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +url = "https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip" +df_prenoms = pd.read_csv(url, sep=";") + +df_prenoms.head(10) +df_prenoms.sample(n=50) + +df_prenoms.info() +``` + +
+ +::: + +#### Partie 2 : Nettoyage des données + + +- L'output de la méthode `info()` suggère des valeurs manquantes dans la colonne des prénoms. Affichez ces lignes. Vérifiez que ces valeurs manquantes sont correctement spécifiées. +- L'output de méthode `head()` montre une modalité récurrente "_PRENOMS_RARES" dans la colonne des prénoms. Quelle proportion des individus de la base cela concerne-t-il ? Convertir ces valeurs en `np.nan`. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +print(df_prenoms[df_prenoms["preusuel"].isna()]) +prop_rares = df_prenoms.groupby("preusuel")["nombre"].sum()["_PRENOMS_RARES"] / df_prenoms["nombre"].sum() +print(prop_rares) # ~ 2 % de la base +df_prenoms = df_prenoms.replace('_PRENOMS_RARES', np.nan) +``` + +
+ +::: + +- On remarque que les prénoms de personnes dont l'année de naissance n'est pas connue sont regroupés sous la modalité `XXXX`. Quelle proportion des individus de la base cela concerne-t-il ? Convertir ces valeurs en `np.nan`. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +prop_xxxx = df_prenoms.groupby("annais")["nombre"].sum()["XXXX"] / df_prenoms["nombre"].sum() +print(prop_xxxx) # ~ 1 % de la base +df_prenoms = df_prenoms.replace('XXXX', np.nan) +``` + +
+ +::: + +- Supprimer les lignes contenant des valeurs manquantes de l'échantillon. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +df_prenoms = df_prenoms.dropna() +``` + +
+ +::: + +- Convertissez la colonne `annais` en type numérique et la colonne `sexe` en type catégoriel. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +df_prenoms['annais'] = pd.to_numeric(df_prenoms['annais']) +df_prenoms['sexe'] = df_prenoms['sexe'].astype('category') +``` + +
+ +::: + +- Vérifiez avec la méthode `info()` que le nettoyage a été correctement appliqué. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +df_prenoms.info() +``` + +
+ +::: + +#### Partie 3 : Statistiques descriptives sur les naissances + + +- La [documentation](https://www.insee.fr/fr/statistiques/2540004?sommaire=4767262#documentation) du fichier nous informe qu'on peut considérer les données comme quasi-exhaustives à partir de 1946. Pour cette partie seulement, filtrer les données pour ne conserver que les données ultérieures. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +df_prenoms_post_1946 = df_prenoms[df_prenoms["annais"] >= 1946] +``` + +
+ +::: + +- Calculez le nombre total de naissances par sexe. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +births_per_sex = df_prenoms_post_1946.groupby('sexe')['nombre'].sum() +print(births_per_sex) +``` + +
+ +::: + +- Identifiez les cinq années ayant le plus grand nombre de naissances. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +top5_years = df_prenoms_post_1946.groupby('annais')['nombre'].sum().nlargest(5) +print(top5_years) +``` + +
+ +::: + +#### Partie 4 : Analyse des prénoms + + +- Identifiez le nombre total de prénoms uniques dans le DataFrame. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +total_unique_names = df_prenoms['preusuel'].nunique() +print(total_unique_names) +``` + +
+ +::: + +- Compter le nombre de personnes possédant un prénom d'une seule lettre. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +single_letter_names = df_prenoms[df_prenoms['preusuel'].str.len() == 1]['nombre'].sum() +print(single_letter_names) +``` + +
+ +::: + +- Créez une "fonction de popularité" qui, pour un prénom donné, affiche l'année où il a été le plus donné ainsi que le nombre de fois où il a été donné cette année-là. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +def popularite_par_annee(df, prenom): + # Filtrer le DataFrame pour ne garder que les lignes correspondant au prénom donné + df_prenom = df[df['preusuel'] == prenom] + + # Grouper par année, sommer les naissances et identifier l'année avec le maximum de naissances + df_agg = df_prenom.groupby('annais')['nombre'].sum() + annee_max = df_agg.idxmax() + n_max = df_agg[annee_max] + + print(f"Le prénom '{prenom}' a été le plus donné en {annee_max}, avec {n_max} naissances.") + +# Test de la fonction avec un exemple +popularite_par_annee(df_prenoms, 'ALFRED') +``` + +
+ +::: + +- Créez une fonction qui, pour un sexe donné, renvoie un DataFrame contenant le prénom le plus donné pour chaque décennie. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +def popularite_par_decennie(df, sexe): + # Filtrage sur le sexe + df_sub = df[df["sexe"] == sexe] + + # Calcul de la variable décennie + df_sub["decennie"] = (df_sub["annais"] // 10) * 10 + + # Calculer la somme des naissances pour chaque prénom et chaque décennie + df_counts_decennie = df_sub.groupby(["preusuel", "decennie"])["nombre"].sum().reset_index() + + # Trouver l'indice du prénom le plus fréquent pour chaque décennie + idx = df_counts_decennie.groupby("decennie")["nombre"].idxmax() + + # Utiliser l'indice pour obtenir les lignes correspondantes du DataFrame df_counts_decennie + df_popularite_decennie = df_counts_decennie.loc[idx].set_index("decennie") + + return df_popularite_decennie + +# Test de la fonction avec un exemple +popularite_par_decennie(df_prenoms, sexe=2) +``` + +
+ +::: + +### Calcul d'une empreinte carbone par habitant au niveau communal + +L'objectif de cet exercice est de calculer une empreinte carbone par habitant au niveau communal. Pour cela, il va falloir combiner deux sources de données : + +- les populations légales au niveau des communes, issues du recensement de la population ([source](https://www.insee.fr/fr/statistiques/6683037)) + +- les émissions de gaz à effet de serre estimées au niveau communal par l’ADEME ([source](https://www.data.gouv.fr/fr/datasets/inventaire-de-gaz-a-effet-de-serre-territorialise/#_)) + +Cet exercice constitue une version simplifiée d'un [TP complet pour la pratique de Pandas](https://pythonds.linogaliana.fr/content/manipulation/02b_pandas_TP.html#importer-les-donn%C3%A9es) proposé par Lino Galiana dans son [cours à l'ENSAE](https://pythonds.linogaliana.fr/). + +#### Partie 1 : Exploration des données sur les populations légales communales + +- Importez le fichier CSV `communes.csv`. +- Utilisez les méthodes `.sample()`, `.info()` et `.describe()` pour obtenir un aperçu des données. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +df_pop_communes = pd.read_csv("data/communes.csv", sep=";") + +df_pop_communes.sample(10) +df_pop_communes.info() +df_pop_communes.describe() +``` + +
+ +::: + +- Identifiez et retirez les lignes correspondant aux communes sans population. +- Supprimez les colonnes "PMUN" et "PCAP", non pertinentes pour l'analyse. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +n_communes_0_pop = df_pop_communes[df_pop_communes["PTOT"] == 0].shape[0] +print(n_communes_0_pop) +df_pop_communes = df_pop_communes[df_pop_communes["PTOT"] > 0] + +df_pop_communes = df_pop_communes.drop(columns=["PMUN", "PCAP"]) +``` + +
+ +::: + +Les communes qui ont les noms les plus longs sont-elles aussi les communes les moins peuplées ? Pour le savoir : +- Créez une nouvelle variable qui contient le nombre de caractères de chaque commune à l'aide de la méthode [str.len()](https://pandas.pydata.org/docs/reference/api/pandas.Series.str.len.html) +- Calculez la corrélation entre cette variable et la population totale avec la méthode [corr()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.corr.html) + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +df_pop_communes_stats = df_pop_communes.copy() +df_pop_communes_stats['longueur'] = df_pop_communes_stats['COM'].str.len() +df_pop_communes_stats['longueur'].corr(df_pop_communes_stats['PTOT']) +``` + +
+ +::: + +#### Partie 2 : Exploration des données sur les émissions communales + +- Importez les données d'émission depuis cette [URL](https://data.ademe.fr/data-fair/api/v1/datasets/igt-pouvoir-de-rechauffement-global/data-files/IGT%20-%20Pouvoir%20de%20r%C3%A9chauffement%20global.csv) +- Utilisez les méthodes `.sample()`, `.info()` et `.describe()` pour obtenir un aperçu des données. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +url_ademe = "https://data.ademe.fr/data-fair/api/v1/datasets/igt-pouvoir-de-rechauffement-global/data-files/IGT%20-%20Pouvoir%20de%20r%C3%A9chauffement%20global.csv" +df_emissions = pd.read_csv(url_ademe) + +df_emissions.sample(10) +df_emissions.info() +df_emissions.describe() +``` + +
+ +::: + +- Y a-t-il des lignes avec des valeurs manquantes pour toutes les colonnes d'émission ? Vérifiez-le à l'aide des méthodes [isnull()](https://pandas.pydata.org/docs/reference/api/pandas.isnull.html) et [all()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.all.html). + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +df_emissions_num = df_emissions.select_dtypes(['number']) +only_nan = df_emissions_num[df_emissions_num.isnull().all(axis=1)] +only_nan.shape[0] +``` + +
+ +::: + +- Créez une nouvelle colonne qui donne les émissions totales par commune +- Afficher les 10 communes les plus émettrices. Qu'observez-vous dans les résultats ? + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +df_emissions['emissions_totales'] = df_emissions.sum(axis = 1, numeric_only = True) + +df_emissions.sort_values(by="emissions_totales", ascending=False).head(10) +``` + +
+ +::: + +- Il semble que les postes majeurs d'émissions soient "Industrie hors-énergie" et "Autres transports international". Pour vérifier si cette conjecture tient, calculer la corrélation entre les émissions totales et les postes sectoriels d'émissions à l'aide de la méthode [corrwith()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.corrwith.html). + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +df_emissions.corrwith(df_emissions["emissions_totales"], numeric_only=True) +``` + +
+ +::: + +- Extraire du code commune le numéro de département dans une nouvelle variable +- Calculer les émissions totales par département +- Afficher les 10 principaux départements émetteurs. Les résultats sont-ils logiques par rapport à l'analyse au niveau communal ? + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +df_emissions["dep"] = df_emissions["INSEE commune"].str[:2] +df_emissions.groupby("dep").agg({"emissions_totales": "sum"}).sort_values(by="emissions_totales", ascending=False).head(10) +``` + +
+ +::: + +#### Partie 3 : Vérifications préalables pour la jointure des sources de données + +Pour effectuer une jointure, il est toujours préférable d'avoir une clé de jointure, i.e. une colonne commune aux deux sources, qui identifie uniquement les unités statistiques. L'objet de cette partie est de trouver la clé de jointure pertinente. + +- Vérifiez si la variable contenant les noms de commune contient des doublons + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +doublons = df_pop_communes.groupby('COM').count()['DEPCOM'] +doublons = doublons[doublons>1] +doublons = doublons.reset_index() +doublons +``` + +
+ +::: + +- Filtrez dans le DataFrame initial les communes dont le nom est dupliqué, et triez-le par code commune. Les doublons semblent-ils problématiques ? + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +df_pop_communes_doublons = df_pop_communes[df_pop_communes["COM"].isin(doublons["COM"])] +df_pop_communes_doublons.sort_values('COM') +``` + +
+ +::: + +- Vérifiez que les codes commune identifient de manière unique la commune associée + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +(df_pop_communes_doublons.groupby("DEPCOM")["COM"].nunique() != 1).sum() +``` + +
+ +::: + +- Affichez les communes présentes dans les données communales mais pas dans les données d'émissions, et inversement. Qu'en concluez-vous ? + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +## Observations qui sont dans les pop légales mais pas dans les données d'émissions +df_pop_communes[~df_pop_communes["DEPCOM"].isin(df_emissions["INSEE commune"])] + +## Observations qui sont dans les données d'émissions mais pas dans les pop légales +df_emissions[~df_emissions["INSEE commune"].isin(df_pop_communes["DEPCOM"])] +``` + +
+ +::: + +#### Partie 4 : Calcul d'une empreinte carbone par habitant pour chaque commune + +- Joindre les deux DataFrames à l'aide de la fonction à partir du code commune. Attention : les variables ne s'appellent pas de la même manière des deux côtés ! + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +df_emissions_pop = pd.merge(df_pop_communes, df_emissions, how="inner", left_on="DEPCOM", right_on="INSEE commune") +df_emissions_pop +``` + +
+ +::: + +- Calculer une empreinte carbone pour chaque commune, correspondant aux émissions totales de la commune divisées par sa population totale. +- Affichez les 10 communes avec les empreintes carbones les plus élevées. +- Les résultats sont-ils identiques à ceux avec les émissions totales ? Qu'en concluez-vous ? + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +df_emissions_pop["empreinte_carbone"] = df_emissions_pop["emissions_totales"] / df_emissions_pop["PTOT"] +df_emissions_pop.sort_values("empreinte_carbone", ascending=False).head(10) +``` + +
+ +::: + +### Analyse de l'évolution d'un indice de production + +Vous avez à disposition dans le dossier `data/` deux jeux de données CSV : + +- `serie_glaces_valeurs.csv` contient les valeurs mensuelles de l'indice de prix de production de l'industrie française des glaces et sorbets +- `serie_glaces_metadonnees.csv` contient les métadonnées associées, notamment les codes indiquant le statut des données. + +L'objectif est d'utiliser `Pandas` pour calculer : + +- l'évolution de l'indice entre chaque période (mois) +- l'évolution de l'indice en glissement annuel (entre un mois donné et le même mois l'année suivante). + +#### Partie 1 : Import des données + +- Importez les deux fichiers CSV dans des DataFrames. Attention, dans les deux cas, il y a des lignes superflues avant les données, qu'il faudra sauter à l'aide du paramètre `skiprows` de la fonction [read_csv()](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html). +- Donnez des noms simples et pertinents aux différentes variables. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +df_valeurs = pd.read_csv('data/serie_glaces_valeurs.csv', delimiter=';', + skiprows=4, names=["periode", "indice", "code"]) +df_metadata = pd.read_csv('data/serie_glaces_metadonnees.csv', delimiter=';', + skiprows=5, names=["code", "signification"]) +``` + +
+ +::: + +#### Partie 2 : Filtrage des données pertinentes + +- Fusionner les deux DataFrames afin de récupérer la signification des codes présents dans les données. +- Filtrer les données de sorte à ne conserver que les données de type "Valeur normale". +- Supprimer les colonnes liées aux codes, dont nous n'avons plus besoin pour la suite. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +df_merged = pd.merge(df_valeurs, df_metadata, how='left', on='code') + +df_clean = df_merged[df_merged['code'] == "A"] +df_clean = df_clean[["periode", "indice"]] +``` + +
+ +::: + +#### Partie 3 : Pré-traitement des données + +Vérifiez si les types des variables sont pertinents selon leur nature. Sinon, convertissez-les avec les fonctions idoines. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +df_clean.info() +df_clean['periode'] = pd.to_datetime(df_clean['periode']) +df_clean['indice'] = pd.to_numeric(df_clean['indice']) +df_clean.info() +``` + +
+ +::: + +#### Partie 4 : Calcul de l'évolution périodique + +- Utilisez la méthode [shift()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.shift.html) pour créer une nouvelle colonne qui contiendra l'indice du trimestre précédent +- Calculez la différence entre l'indice actuel et l'indice décalé pour obtenir l'évolution (en pourcentage) d'un trimestre à l'autre + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +df_clean['indice_prec'] = df_clean['indice'].shift(1) +df_clean['evo'] = ((df_clean['indice'] - df_clean['indice_prec']) / df_clean['indice_prec']) * 100 + +## Méthode alternative +df_clean['evo_alt'] = df_clean['indice'].pct_change(periods=1) * 100 +``` + +
+ +::: + +#### Partie 5 : Calcul de l'évolution glissante sur 12 mois + +Comme vous avez pu le voir dans la solution de l'exercice précédent, la méthode [pct_change()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.pct_change.html) permet précisément de calculer une évolution entre deux périodes. Utiliser cette méthode pour calculer une évolution (en pourcentage) en glissement annuel pour chaque mois. + +```{python} +# Testez votre réponse dans cette cellule + +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} +df_clean["evo_glissement_annuel"] = df_clean['indice'].pct_change(periods=12) * 100 +df_clean.head(20) +``` + +
+ +::: + +::: + + + + + + + + + + + + + +::: {.content-visible when-profile="en"} + +# Working with tabular data using Pandas + +Statistical analysis is generally based on **tabular data**, where each row represents an observation and each column a variable. To handle this type of data and easily apply standard data analysis methods, dedicated objects have been designed: `DataFrames`. Users of `R` are well acquainted with this data structure, which is native to this statistics-oriented language. In `Python`, a general-purpose language, this object does not exist natively. Fortunately, a very comprehensive and convenient library, designed as an overlay to `NumPy`, introduces the `DataFrame` object in `Python` and allows for simple and intuitive data manipulation and analysis: `Pandas`. + +::: {.callout-note} +Pandas is the central element of the data science ecosystem in Python, offering virtually infinite data processing capabilities. Moreover, there are generally multiple ways to perform the same operation in Pandas. Consequently, this chapter is particularly long and dense with new features. The goal is not to memorize all the methods presented throughout this chapter, but rather to have a general overview of what is possible in order to use the right tools in projects. In particular, the end-of-chapter exercises and the mini-projects at the end of the course will provide an opportunity to apply this new knowledge to concrete problems. +::: + +Let's start by importing the `Pandas` library. The common usage is to give it the alias `pd` to simplify future calls to the package's objects and functions. We also import `NumPy` as we will compare the fundamental objects of the two packages. + +```{python} +import pandas as pd +import numpy as np +``` + +## Data structures + +To fully understand how `Pandas` works, it is important to focus on its fundamental objects. We will therefore first study the `Series`, whose concatenation allows us to build a `DataFrame`. + +### The `Series` + +A Series is a one-dimensional data container that can hold any type of data (integers, strings, Python objects...). However, a Series is of a given type: a Series containing only integers will be of type `int`, and a Series containing objects of different natures will be of type `object`. Let's build our first Series from a list to check this behavior. + +```{python} +l = [1, "X", 3] +s = pd.Series(l) +print(s) +``` + +In particular, we can access the data of a Series by position, as for a list or an array. + +```{python} +print(s[1]) +``` + +At first glance, we do not see much difference between a Series and a one-dimensional `NumPy` array. However, there is a significant difference: the presence of an index. The observations have an associated label. When we create a Series without specifying anything, the index is automatically set to the integers from 0 to n-1 (with n being the number of elements in the Series). But it is possible to pass a specific index (e.g., dates, town names, etc.). + +```{python} +s = pd.Series(l, index=["a", "b", "c"]) +print(s) +``` + +This allows us to access the data by label: + +```{python} +s["b"] +``` + +This difference may seem minor at first, but it becomes essential for constructing the DataFrame. For the rest, Series behave very similarly to NumPy arrays: calculations are vectorized, we can directly sum two Series, etc. Moreover, we can easily convert a Series into an array via the `values` attribute. This naturally loses the index... + +```{python} +s = pd.Series(l, index=["a", "b", "c"]) +s.values +``` + +### The `DataFrame` + +Fundamentally, a DataFrame consists of a collection of Series, aligned by their indexes. This concatenation thus constructs a data table, with Series corresponding to columns, and the index identifying the rows. The following figure ([source](https://www.geeksforgeeks.org/creating-a-pandas-dataframe/)) helps to understand this data structure. + +![](img/structure_df.png){fig-align="center" width="800"} + +A DataFrame can be constructed in multiple ways. In practice, we generally build a DataFrame directly from tabular data files (e.g., CSV, Excel), rarely by hand. So, we will only illustrate the most common manual construction method: from a data dictionary. + +```{python} +df = pd.DataFrame( + data = { + "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var2": np.random.randint(-10, 10, 6), + "experiment": ["test", "train", "test", "train", "train", "validation"], + "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-01-05", "2022-01-06"], + "sample": "sample1" + } +) + +df +``` + +A Pandas DataFrame has a set of useful attributes that we will discover throughout this tutorial. For now, let's focus on the most basic ones: the index and the column names. By default, the index is initialized, as for Series, to the list of positions of the observations. We could have specified an alternative index when constructing the DataFrame by specifying the `index` argument of the `pd.DataFrame` function. + +```{python} +df.index +``` + +```{python} +df.columns +``` + +Often, rather than specifying an index manually during the construction of the DataFrame, we will want to use a certain column of the DataFrame as an index. We use the `set_index` method associated with DataFrames for this. + +```{python} +df = df.set_index("date") +df +``` + +The index attribute has naturally changed: + +```{python} +df.index +``` + +## Selecting data + +When manipulating tabular data, it is common to want to extract specific columns from a `DataFrame`. This extraction is simple with `Pandas` using square brackets. + +### Selecting columns + +#### Selecting a single column + +To extract a single column, we can use the following syntax: + +```{python} +selected_column = df["var1"] +selected_column +``` + +The `selected_column` object here returns the column named `var1` from the `DataFrame` `df`. But what type is this object? To answer this question, we use the `type()` function: + +```{python} +type(selected_column) +``` + +As we can see, the result is a `Series`, which is a one-dimensional object in `Pandas`. + +Another useful attribute to know is `shape`. It allows us to know the dimension of the object. For a `Series`, `shape` will return a tuple whose first element indicates the number of rows. + +```{python} +selected_column.shape +``` + +#### Selecting multiple columns + +To extract multiple columns, just pass a list of the desired column names: + +```{python} +selected_columns = df[["var1", "var2", "experiment"]] +selected_columns +``` + +This snippet shows the columns `var1`, `var2`, and `experiment` from the `DataFrame` `df`. Let's now check its type: + +```{python} +type(selected_columns) +``` + +The result is a `DataFrame` because it is a two-dimensional object. We can also check its shape with the `shape` attribute. In this case, the tuple returned by `shape` will contain two elements: the number of rows and the number of columns. + +```{python} +selected_columns.shape +``` + +### Selecting rows + +#### Using `loc` and `iloc` + +When we want to select specific rows in a DataFrame, we can use two main methods: `loc` and `iloc`. + +- `iloc` allows selecting rows and columns by their position, i.e., by numeric indices. + +Example, selecting the first 3 rows: + +```{python} +df.iloc[0:3, :] +``` + +- `loc` works with labels. If the DataFrame's indexes are numbers, they resemble positions, but this is not necessarily the case. It is crucial to note that, unlike `iloc`, with `loc`, the end index is included in the selection. + +```{python} +df.loc["2022-01-01":"2022-01-03", :] +``` + +#### Filtering data based on conditions + +In practice, rather than selecting rows based on positions or labels, we often want to filter a DataFrame based on certain conditions. In this case, we primarily use boolean filters. + +- **Inequalities**: We might want to keep only the rows that meet a certain condition. + +Example, filtering rows where the value of the `var2` column is greater than 0: + +```{python} +df[df['var2'] >= 0] +``` + +- **Membership with `isin`**: If we want to filter data based on a list of possible values, the `isin` method is very useful. + +Example, to keep only the rows where the `experiment` column has values 'test' or 'validation': + +```{python} +df[df['experiment'].isin(['train', 'validation'])] +``` + +These methods can be combined to create more complex conditions. It is also possible to use logical operators (`&` for "and", `|` for "or") to combine multiple conditions. Be careful to enclose each condition in parentheses when combining them. + +Example, selecting rows where `var2` is greater than 0 and `experiment` is equal to 'test' or 'validation': + +```{python} +df[(df['var2'] >= 0) & (df['experiment'].isin(['train', 'validation']))] +``` + +## Exploring tabular data + +In public statistics, the starting point is generally not the manual generation of data but rather pre-existing tab + +ular files. These files, whether from surveys, administrative databases, or other sources, constitute the raw material for any subsequent analysis. Pandas offers powerful tools to import these tabular files and explore them for further manipulations. + +### Importing and exporting data + +#### Importing a CSV file + +As we saw in a previous lab, the CSV format is one of the most common formats for storing tabular data. We previously used the `csv` library to handle them as text files, but it was not very convenient. To recall, the syntax for reading a CSV file and displaying the first lines was as follows: + +```{python} +import csv + +rows = [] + +with open("data/departement2021.csv") as file_in: + csv_reader = csv.reader(file_in) + for row in csv_reader: + rows.append(row) + +rows[:5] +``` + +With Pandas, just use the `read_csv()` function to import the file as a DataFrame, then the `head()` function. + +```{python} +df_departements = pd.read_csv('data/departement2021.csv') +df_departements.head() +``` + +It is also possible to import a CSV file directly from a URL. This is particularly convenient when the data is regularly updated on a website, and we want to access the latest version without manually downloading the file each time. Let's take the example of a CSV file available on the INSEE website: the file of given names, from civil status data. We also note another handy feature: the CSV file is compressed (in `zip` format), but Pandas can recognize and decompress it before importing. + +```{python} +# Importing a CSV file from a URL +url = "https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip" +df_prenoms_url = pd.read_csv(url, sep=";") +df_prenoms_url.head() +``` + +When working with CSV files, there are many optional arguments available in the `read_csv()` function that allow us to adjust the import process according to the specifics of the file. These arguments can, for example, define a specific delimiter (as above for the given names file), skip certain lines at the beginning of the file, or define data types for each column, and many others. All these parameters and their usage are detailed in the [official documentation](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html). + +#### Exporting to CSV format + +Once the data has been processed and modified within Pandas, it is common to want to export the result as a CSV file for sharing, archiving, or use in other tools. Pandas offers a simple method for this operation: `to_csv()`. Suppose we want to export the data from the `df_departements` DataFrame specific to the five overseas departments. + +```{python} +df_departements_dom = df_departements[df_departements["DEP"].isin(["971", "972", "973", "974", "975"])] +df_departements_dom.to_csv('output/departements2021_dom.csv') +``` + +One of the key arguments of the `to_csv()` method is `index`. By default, `index=True`, which means that the DataFrame's index will also be written in the CSV file. We can verify this by printing the first lines of our CSV file: Pandas has added an unnamed column, which contains the index of the retained rows. + +```{python} +with open("output/departements2021_dom.csv") as file_in: + for i in range(5): + row = next(file_in).strip() + print(row) +``` + +In some cases, notably when the index does not provide useful information or is simply automatically generated by Pandas, we might want to exclude it from the exported file. To do this, we can set `index=False`. + +```{python} +df_departements_dom.to_csv('output/departements2021_dom_noindex.csv', index=False) +``` + +#### Importing a Parquet file + +The Parquet format is another format for storing tabular data, increasingly used. Without going into technical details, the Parquet format has various characteristics that make it a preferred choice for storing and processing large volumes of data. Due to these advantages, this format is increasingly used for data dissemination at INSEE. It is therefore essential to know how to import and query Parquet files with Pandas. + +Importing a Parquet file into a Pandas DataFrame is as easy as for a CSV file. The function is called `read_parquet()`. + +```{python} +df_departements = pd.read_parquet('data/departement2021.parquet') +df_departements.head() +``` + +#### Exporting to Parquet format + +Again, everything works as in the CSV world: we use the `to_parquet()` method to export a DataFrame to a Parquet file. Similarly, we can choose to export or not the index, using the `index` parameter (which defaults to `True`). + +```{python} +df_departements_dom = df_departements[df_departements["DEP"].isin(["971", "972", "973", "974", "975"])] +df_departements_dom.to_parquet('output/departements2021_dom.parquet', index=False) +``` + +One of the major strengths of the Parquet format, compared to text formats like CSV, is its ability to store metadata, i.e., data that helps better understand the data contained in the file. In particular, a Parquet file includes in its metadata the data schema (variable names, variable types, etc.), making it a very suitable format for data dissemination. Let's verify this behavior by revisiting the DataFrame we defined earlier. + +```{python} +df = pd.DataFrame( + data = { + "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var2": np.random.randint(-10, 10, 6), + "experiment": ["test", "train", "test", "train", "train", "validation"], + "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-01-05", "2022-01-06"], + "sample": "sample1" + } +) + +df = df.assign( + experiment=pd.Categorical(df["experiment"]), + date=pd.to_datetime(df["date"]) +) +``` + +This time, we use two specific data types, for categorical data (`category`) and for temporal data (`datetime`). We will see later in the tutorial how to use these types. For now, let's simply note that Pandas stores these types in the data schema. + +```{python} +df.info() +``` + +Let's now verify that exporting and re-importing this data in Parquet preserves the schema. + +```{python} +df.to_parquet("output/df_test_schema.parquet", index=False) +df_test_schema_parquet = pd.read_parquet('output/df_test_schema.parquet') + +df_test_schema_parquet.info() +``` + +Conversely, a CSV file, which by definition only contains text, does not preserve this data. The variables for which we specified the type are imported as strings (type `object` in Pandas). + +```{python} +df.to_csv("output/df_test_schema.csv", index=False) +df_test_schema_csv = pd.read_csv('output/df_test_schema.csv') + +df_test_schema_csv.info() +``` + +### Viewing a sample of data + +When working with large datasets, it is often useful to quickly view a sample of the data to get an idea of its structure, format, or even to detect potential problems. Pandas offers several methods for this. + +The `head()` method displays the first rows of the DataFrame. By default, it returns the first 5 rows, but we can specify another number as an argument if necessary. + +```{python} +df_departements.head() +``` + +```{python} +df_departements.head(10) +``` + +Conversely, the `tail()` method gives a preview of the last rows of the DataFrame. + +```{python} +df_departements.tail() +``` + +Displaying the first or last rows may sometimes not be representative of the entire dataset, especially when the data is sorted. To minimize the risk of obtaining a biased overview of the data, we can use the `sample()` method, which selects a random sample of rows. By default, it returns a single row, but we can request a specific number of rows using the `n` argument. + +```{python} +df_departements.sample(n=5) +``` + +### Getting an overview of the data + +One of the first steps when exploring new data is to understand the general structure of the dataset. The `info()` method in Pandas provides a quick overview of the data, including data types, the presence of missing values, and memory usage. + +```{python} +df.info() +``` + +Several key pieces of information can be extracted from this result: + +- **index**: The DataFrame has a `RangeIndex`, which means the index is a simple numeric sequence. Here, the index ranges from 0 to 5, for a total of 6 entries. + +- **schema**: The list of columns is displayed with very useful information about the data schema: + + - **Non-Null Count**: The number of **non-missing** (non-`nan`) values in the column. If this number is less than the total number of entries (in our case, 6), it means the column contains missing values. Note the possible ambiguity on "null": this indeed means missing values, not values equal to 0. Thus, in our case, the number of "non-null" values for the `var1` variable is 5. + + - **Dtype**: The data type of the column, which helps understand the nature of the information stored in each column. For example, `float64` + + (real numbers), `int32` (integers), `category` (categorical variable), `datetime64[ns]` (temporal information), and `object` (text or mixed data). + +Using `info()` is a quick and effective way to get an overview of a DataFrame, quickly identify columns containing missing values, and understand the data structure. + +### Calculating descriptive statistics + +In addition to the information returned by the `info()` method, we might want to obtain simple descriptive statistics to quickly visualize the distributions of variables. The `describe()` method provides a synthetic view of the distribution of data in each column. + +```{python} +df.describe() +``` + +It should be noted that `describe()` only returns statistics for numeric columns by default. If we want to include columns of other types, we need to specify this via the `include` argument. For example, `df.describe(include='all')` will return statistics for all columns, including metrics such as the unique count, the most frequent value, and the frequency of the most frequent value for non-numeric columns. + +```{python} +df.describe(include='all') +``` + +Note again that the `count` variable returns the number of **non-missing** values in each variable. + +## Main data manipulations + +### Transforming data + +Data transformation operations are essential for shaping, cleaning, and preparing data for analysis. Transformations can apply to the entire DataFrame, specific columns, or specific rows. + +#### Transforming a DataFrame + +To transform an entire DataFrame (or a sub-DataFrame), it is possible to use vectorized functions, which allow quickly applying an operation to all elements of the DataFrame. This includes a number of methods available for `Series`, as well as NumPy mathematical functions, etc. + +For example, raising each numeric value in a DataFrame to the power of 2: + +```{python} +df = pd.DataFrame( + data = { + "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var2": np.random.randint(-10, 10, 6), + } +) + +df ** 2 +``` + +or taking the absolute value: + +```{python} +np.abs(df) +``` + +Some methods available for `Series` can also be used to transform an entire DataFrame. For example, the very useful [replace()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.replace.html) method, which allows replacing all occurrences of a given value with another value. For example, suppose the value 0 in the `var1` column actually indicates a measurement error. It would be preferable to replace it with a missing value. + +```{python} +df.replace(0, np.nan) +``` + +::: {.callout-warning title="Assignment or in-place methods?"} +In the previous example, applying the [replace()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.replace.html) method does not directly modify the DataFrame. To make the modification persistent, one possibility is to assign the result to an object: + +```{python} +df = df.replace(0, np.nan) +``` + +A second possibility is, when methods offer it, to use the `inplace` argument. When `inplace=True`, the operation is performed "in place", and the DataFrame is therefore directly modified. + +```{python} +df.replace(0, np.nan, inplace=True) +``` + +In practice, it is better to limit `inplace` operations. They do not favor the reproducibility of analyses, as the re-execution of the same cell will give different results each time. +::: + +#### Transforming columns + +In some cases, we will not want to apply transformations to the entire data but to specific variables. Transformations possible at the DataFrame level (vectorized functions, methods like [replace()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.replace.html), etc.) naturally remain possible at the column level. + +```{python} +df = pd.DataFrame( + data = { + "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var2": np.random.randint(-10, 10, 6), + } +) + +np.abs(df["var2"]) +``` + +```{python} +df["var1"].replace(0, np.nan) +``` + +But there are other transformations that are generally applied at the level of one or a few columns. For example, when the schema has not been properly recognized upon import, it may happen that numeric variables are defined as strings (type `object` in Pandas). + +```{python} +df = pd.DataFrame( + data = { + "var1": [1.3, 5.6, np.nan], + "var2": ["1", "5", "18"], + } +) + +df.info() +``` + +In this case, we can use the `astype` method to convert the column to the desired type. + +```{python} +df['var2'] = df['var2'].astype(int) + +df.info() +``` + +Another frequent operation is renaming one or more columns. To do this, we can use the [rename()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.rename.html) method, passing a dictionary containing as many key-value pairs as variables to be renamed, where each key-value pair is of the form `'old_name': 'new_name'`. + +```{python} +df.rename(columns={'var2': 'age'}) +``` + +Finally, we might want to remove columns from the DataFrame that are not or no longer useful for analysis. For this, we use the [drop()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.drop.html) method, to which we pass either a string (name of a column if we want to remove only one) or a list of column names to remove. + +```{python} +df.drop(columns=['var1']) +``` + +#### Transforming rows + +In statistics, we generally apply transformations involving one or more columns. However, in some cases, it is necessary to apply transformations at the row level. For this, we can use the [apply()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.apply.html) method of Pandas, applied to the row axis (`axis=1`). Let's illustrate its operation with a simple case. First, we generate data. + +```{python} +df = pd.DataFrame( + data = { + "var1": [1, 5, 9, 13], + "var2": [3, 7, 11, 15], + "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04"], + } +) + +df.head() +``` + +We now apply the `apply()` function to the DataFrame to calculate a new variable that is the sum of the two existing ones. + +```{python} +df['sum_row'] = df.apply(lambda row: row['var1'] + row['var2'], axis=1) + +df.head() +``` + +::: {.callout-tip title="Lambda functions"} +A `lambda` function is a small anonymous function. It can take any number of arguments but can have only one expression. In the example above, the `lambda` function takes a row as an argument and returns the sum of the `var1` and `var2` columns for that row. + +Lambda functions allow defining simple functions "on the fly" without having to give them a name. In our example, this would have been perfectly equivalent to the following code: + +```{python} +def sum_row(row): + return row['var1'] + row['var2'] + +df['sum_row'] = df.apply(sum_row, axis=1) +``` + +::: + +Although `apply()` offers great flexibility, it is not the most efficient method, especially for large datasets. Vectorized operations are always preferable as they process data in blocks rather than row by row. In our case, it would have been preferable to create our variable using column operations. + +```{python} +df['sum_row_vect'] = df['var1'] + df['var2'] + +df.head() +``` + +However, we might find ourselves in certain (rare) cases where an operation cannot be easily vectorized or where the logic is complex. Suppose, for example, we want to combine the values of several columns based on certain conditions. + +```{python} +def combine_columns(row): + if row['var1'] > 6: + return str(row['var2']) + else: + return str(row['var2']) + "_" + row['date'] + +df['combined_column'] = df.apply(combine_columns, axis=1) + +df +``` + +### Sorting values + +Sorting data is particularly useful for exploring and visualizing data. With Pandas, we use the [sort_values()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.sort_values.html) method to sort the values of a DataFrame based on one or more columns. + +```{python} +df = pd.DataFrame( + data = { + "var1": [1, 5, 9, 13], + "var2": [3, 7, 11, 15], + "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04"], + } +) + +df +``` + +To sort the values based on a single column, just pass the column name as a parameter. + +```{python} +df.sort_values(by='var1') +``` + +By default, the sorting is done in ascending + + order. To sort the values in descending order, just set `ascending=False`. + +```{python} +df.sort_values(by='var1', ascending=False) +``` + +If we want to sort the DataFrame on multiple columns, we can provide a list of column names. We can also choose to sort in ascending order for some columns and descending order for others. + +### Aggregating data + +Aggregating data is a process where the data is broken down into groups based on certain criteria and then aggregated using an aggregation function applied independently to each group. This operation is common in exploratory analysis or when preprocessing data for visualization or statistical modeling. + +```{python} +df = pd.DataFrame( + data = { + "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var2": np.random.randint(-10, 10, 6), + "experiment": ["test", "train", "test", "train", "train", "validation"], + "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-01-05", "2022-01-06"], + "sample": "sample1" + } +) + +df.head() +``` + +#### The `groupBy` operation + +The `groupBy` method in Pandas allows dividing the DataFrame into subsets based on the values of one or more columns, and then applying an aggregation function to each subset. It returns a `DataFrameGroupBy` object that is not very useful by itself but is an essential intermediate step to then apply one or more aggregation function(s) to the different groups. + +```{python} +df.groupby('experiment') +``` + +#### Aggregation functions + +Once the data is grouped, we can apply aggregation functions to obtain a statistical summary. Pandas includes a number of these functions, the complete list of which is detailed in the [documentation](https://pandas.pydata.org/docs/user_guide/groupby.html#built-in-aggregation-methods). Here are some examples of using these methods. + +For example, count the number of occurrences in each group. + +```{python} +df.groupby('experiment').size() +``` + +Calculate the sum of a variable by group. + +```{python} +df.groupby('experiment')['var1'].sum() +``` + +Or count the number of unique values of a variable by group. The possibilities are numerous. + +```{python} +# For the number of unique values of 'var2' in each group +df.groupby('experiment')['var2'].nunique() +``` + +When we want to apply multiple aggregation functions at once or custom functions, we use the `agg` method. This method accepts a list of functions or a dictionary that associates column names with functions to apply. This allows for finer application of aggregation functions. + +```{python} +df.groupby('experiment').agg({'var1': 'mean', 'var2': 'count'}) +``` + +::: {.callout-note title="Method chaining"} +The previous examples illustrate an important concept in Pandas: method chaining. This term refers to the possibility of chaining transformations applied to a DataFrame by applying methods to it in a chain. At each applied method, an intermediate DataFrame is created (but not assigned to a variable), which becomes the input of the next method. + +Method chaining allows combining several operations into a single code expression. This can improve efficiency by avoiding intermediate assignments and making the code more fluid and readable. It also favors a functional programming style where data flows smoothly through a chain of transformations. +::: + +#### Effects on the index + +It is interesting to note the effects of the aggregation process on the DataFrame's index. The last example above illustrates this well: the groups, i.e., the modalities of the variable used for aggregation, become the values of the index. + +We might want to reuse this information in subsequent analyses and therefore want it as a column. For this, just reset the index with the `reset_index()` method. + +```{python} +df_agg = df.groupby('experiment').agg({'var1': 'mean', 'var2': 'count'}) +df_agg.reset_index() +``` + +### Handling missing values + +Missing values are a common reality in real-world data processing and can occur for various reasons, such as non-responses to a questionnaire, data entry errors, data loss during transmission, or simply because the information is not applicable. Pandas offers several tools to handle missing values. + +#### Representation of missing values + +In Pandas, missing values are generally represented by `np.nan`, a special marker provided by the `NumPy` library. While it is preferable to use this object to denote missing values, note that the `None` object in `Python` is also understood as a missing value by `Pandas`. + +Let's verify this property. To identify where the missing values are, we use the `isna()` function, which returns a boolean DataFrame indicating `True` where the values are `NaN`. + +```{python} +df = pd.DataFrame( + data = { + "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var2": np.random.randint(-10, 10, 6), + "experiment": ["test", "train", "test", None, "train", "validation"], + "sample": "sample1" + } +) + +df.isna() +``` + +#### Calculations on columns containing missing values + +During statistical calculations, missing values are generally ignored. For example, the `.mean()` method calculates the mean of non-missing values. + +```{python} +df['var1'].mean() +``` + +However, calculations involving multiple columns do not always ignore missing values and can often result in `NaN`. + +```{python} +df['var3'] = df['var1'] + df['var2'] + +df +``` + +#### Removing missing values + +The `dropna()` method allows us to remove rows (`axis=0`) or columns (`axis=1`) containing missing values. By default, any row containing at least one missing value is removed. + +```{python} +df.dropna() +``` + +By changing the `axis` parameter, we can request that any column containing at least one missing value be removed. + +```{python} +df.dropna(axis=1) +``` + +Finally, the `how` parameter defines the deletion mode. By default, a row or column is removed when at least one value is missing (`how=any`), but it is possible to remove the row/column only when all values are missing (`how=all`). + +#### Replacing missing values + +To handle missing values in a DataFrame, a common approach is imputation, which involves replacing the missing values with other values. The `fillna()` method allows us to perform this operation in various ways. One possibility is replacement by a constant value. + +```{python} +df['var1'].fillna(value=0) +``` + +::: {.callout-warning title="Changing the representation of missing values"} +It can sometimes be tempting to change the manifestation of a missing value for visibility reasons, for example by replacing it with a string: + +```{python} +df['var1'].fillna(value="MISSING") +``` + +In practice, this is not recommended. It is indeed preferable to stick to Pandas' standard convention (using `np.nan`), firstly for standardization purposes that facilitate reading and maintaining the code, but also because the standard convention is optimized for performance and calculations from data containing missing values. +::: + +Another frequent imputation method is to use a statistical value, such as the mean or median of the variable. + +```{python} +df['var1'].fillna(value=df['var1'].mean()) +``` + +::: {.callout-warning title="Imputation bias"} +Replacing missing values with a constant value, such as zero, the mean, or the median, can be problematic. If the data is not missing at random (MNAR), this can introduce bias into the analysis. MNAR variables are variables whose probability of being missing is related to their own value or other variables in the data. In such cases, more sophisticated imputation may be necessary to minimize distortions. We will see an example in the end-of-tutorial exercise. +::: + +### Handling data of specific types + +#### Text data + +Text data often requires cleaning and preparation before analysis. Pandas provides an array of vectorized operations via the `str` library that make preparing text data both simple and very efficient. Again, the possibilities are numerous and detailed in the [documentation](https://pandas.pydata.org/docs/user_guide/text.html). Here we present the most frequently used methods in data analysis. + +```{python} +df = pd.DataFrame( + data = { + "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var2": np.random.randint(-10, 10, 6), + "experiment": ["test", "train", "test", "test", "train", "validation"], + "sample": [" sample1", "sample1", "sample2", " sample2 ", "sample2 ", "sample1"] + } +) + +df +``` + +A first frequent operation is to extract certain characters from a string. We use the `str[n:]` function (with a somewhat peculiar syntax) for this. For example, if we want to extract the last character of the `sample` variable to retain only the sample number. + +```{python} +df["sample_n"] = df["sample"].str[-1:] + +df +``` + +The principle was correct, but the presence of extraneous spaces in our text data (which were not visible when viewing the DataFrame!) made the operation more difficult than expected. This is an opportunity to introduce the `strip` family of methods (`.str.strip()`, `.str.lstrip()`, and `.str.rstrip()`) that respectively remove extr + +aneous spaces from both sides or one side. + +```{python} +df["sample"] = df["sample"].str.strip() +df["sample_n"] = df["sample"].str[-1:] + +df +``` + +We might also want to filter a DataFrame based on the presence or absence of a certain string (or substring) of characters. For this, we use the `.str.contains()` method. + +```{python} +df[df['experiment'].str.contains('test')] +``` + +Finally, we might want to replace a string (or substring) of characters with another, which the `str.replace()` method allows. + +```{python} +df['experiment'] = df['experiment'].str.replace('validation', 'val') + +df +``` + +#### Categorical data + +Categorical data is variables that contain a limited number of categories. Similar to `R` with the notion of `factor`, Pandas has a special data type, `category`, which is useful for representing categorical data more efficiently and informatively. Categorical data is indeed optimized for certain types of data and can speed up operations like grouping and sorting. It is also useful for visualization, ensuring that categories are displayed in a coherent and logical order. + +To convert a variable to the `category` format, we use the `astype()` method. + +```{python} +df = pd.DataFrame( + data = { + "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var2": np.random.randint(-10, 10, 6), + "experiment": ["test", "train", "test", None, "train", "validation"], + } +) +print(df.dtypes) +``` + +```{python} +df['experiment'] = df['experiment'].astype('category') + +print(df.dtypes) +``` + +This conversion gives us access to some very useful methods, specific to handling categorical variables. For example, it can be useful to rename categories for clarity or standardization. + +```{python} +df['experiment'] = df['experiment'].cat.rename_categories({'test': 'Test', 'train': 'Train', 'validation': 'Validation'}) +df +``` + +Sometimes, the order of categories is significant, and we might want to modify it. This is particularly important for visualization, as the categories will by default be displayed in the specified order. + +```{python} +df_cat = df['experiment'].cat.reorder_categories(['Test', 'Train', 'Validation'], ordered=True) +df.groupby("experiment").mean().plot(kind='bar') +``` + +#### Temporal data + +Temporal data is often present in tabular data to temporally identify the observations collected. Pandas offers functionalities for handling these types of data, particularly through the `datetime64` type, which allows precise manipulation of dates and times. + +```{python} +df = pd.DataFrame( + data = { + "var1": [1, 5, 9, 13], + "var2": [3, 7, 11, 15], + "date": ["2022-01-01", "2022-01-02", "2023-01-01", "2023-01-02"], + "sample": ["sample1", "sample1", "sample2", "sample2"] + } +) + +df.dtypes +``` + +To handle temporal data, it is necessary to convert the strings into `datetime` objects. Pandas does this via the `to_datetime()` function. + +```{python} +df['date'] = pd.to_datetime(df['date']) + +df.dtypes +``` + +Once converted, dates can be formatted, compared, and used in calculations. In particular, Pandas now understands the "order" of the dates present in the data, allowing for filtering over given periods. + +```{python} +df[(df['date'] >= "2022-01-01") & (df['date'] < "2022-01-03")] +``` + +We might also want to perform less precise filtering, involving the year or month. Pandas allows us to easily extract specific components of the date, such as the year, month, day, hour, etc. + +```{python} +df['year'] = df['date'].dt.year +df['month'] = df['date'].dt.month +df['day'] = df['date'].dt.day + +df[df['year'] == 2023] +``` + +Finally, calculations involving dates become possible. We can add or subtract time periods from dates and compare them with each other. The functions used come from `Pandas` but are very similar in operation to those of the [time](https://docs.python.org/fr/3/library/time.html) module in Python. + +For example, we can add time intervals or calculate differences from a reference date. + +```{python} +df['date_plus_one'] = df['date'] + pd.Timedelta(days=1) +df['date_diff'] = df['date'] - pd.to_datetime('2022-01-01') + +df +``` + +### Joining tables + +In data analysis, it is common to want to combine different data sources. This combination can be done vertically (one DataFrame on top of another), for example, when combining two years of the same survey for joint analysis. The combination can also be done horizontally (side by side) based on one or more join keys, often to enrich one data source with information from another source covering the same statistical units. + +#### Concatenating tables + +The vertical concatenation of tables is done using the `concat()` function in Pandas. + +```{python} +df1 = pd.DataFrame( + data = { + "var1": [1, 5], + "var2": [3, 7], + "date": ["2022-01-01", "2022-01-02"], + "sample": ["sample1", "sample1"] + } +) + +df2 = pd.DataFrame( + data = { + "var1": [9, 13], + "date": ["2023-01-01", "2023-01-02"], + "var2": [11, 15], + "sample": ["sample2", "sample2"] + } +) + +df_concat = pd.concat([df1, df2]) + +df_concat +``` + +Note that the order of variables in the two DataFrames is not important. Pandas does not "dumbly" juxtapose the two DataFrames; it matches the schemas to align the variables by name. If two variables have the same name but not the same type - for example, if a numeric variable has been interpreted as strings - Pandas will resolve the issue by taking the common denominator, usually converting to strings (type `object`). + +However, the previous concatenation reveals an issue of repetition at the index level. This is logical: we did not specify an index for our initial two DataFrames, which therefore have the same position index ([0, 1]). In this case (where the index is not important), we can pass the `ignore_index=True` parameter to rebuild the final index from scratch. + +```{python} +df_concat = pd.concat([df1, df2], ignore_index=True) + +df_concat +``` + +::: {.callout-warning title="Iterative construction of a DataFrame"} +One might have the idea of using `pd.concat()` to iteratively construct a DataFrame by adding a new row to the existing DataFrame in each iteration of a loop. However, this is not a good idea: as we have seen, a DataFrame is represented in memory as a juxtaposition of Series. Thus, adding a column to a DataFrame is not costly, but adding a row involves modifying each element constituting the DataFrame. To construct a DataFrame, it is therefore advisable to store the rows in a list of lists (one per column) or a dictionary, then call `pd.DataFrame()` to build the DataFrame, as we did at the beginning of this tutorial. +::: + +#### Merging tables + +Merging tables is an operation that allows us to associate rows from two different DataFrames based on one or more common keys, similar to joins in SQL databases. Different types of joins are possible depending on the data we want to keep, the main ones being represented in the following diagram. + +![](img/joins.png) + +Source: [link](https://medium.com/swlh/merging-dataframes-with-pandas-pd-merge-7764c7e2d46d) + +In Pandas, joins are done with the [merge()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.merge.html) function. To perform a join, we must specify (at a minimum) two pieces of information: + +- the type of join: by default, Pandas performs an `inner` join. The `how` parameter allows specifying other types of joins; + +- the join key. By default, Pandas tries to join the two DataFrames based on their indexes. In practice, we often specify a variable present in the DataFrames as the join key (the `on` parameter if the variable has the same name in both DataFrames, or `left_on` and `right_on` otherwise). + +Let's analyze the difference between the different types of joins through examples. + +```{python} +df_a = pd.DataFrame({ + 'key': ['K0', 'K1', 'K2', 'K3', 'K4'], + 'A': ['A0', 'A1', 'A2', 'A3', 'A4'], + 'B': ['B0', 'B1', 'B2', 'B3', 'A4'] +}) + +df_b = pd.DataFrame({ + 'key': ['K0', 'K1', 'K2', 'K5', 'K6'], + 'C': ['C0', 'C1', 'C2', 'C5', 'C6'], + 'D': ['D0', 'D1', 'D2', 'D5', 'D6'] +}) + +display(df_a) +display(df_b) +``` + +The `inner` join keeps the observations whose key is present in both DataFrames. + +```{python} +df_merged_inner = pd.merge(df_a, df_b, on='key') +df_merged_inner +``` + +::: {.callout-warning title="Inner joins"} +The `inner` join is the most intuitive: it generally does not create missing values and therefore allows working directly on the merged table. But beware: if many keys are not present in both DataFrames, an `inner` join can result in significant data loss, leading to biased final results. In this case, it is better to choose a left or right join, depending on the source we want to enrich and for which it is most important to minimize data loss. +::: + +A `left` join keeps all observations in the left DataFrame (the first DataFrame specified in `pd.merge()`). As a result, if keys are present in the left DataFrame but not in the right one, the final DataFrame contains missing values at those observations (for the right DataFrame's variables). + +```{python} +df_merged_left = pd.merge(df_a, df_b, how="left", on='key') +df_merged_left +``` + +The `outer` join contains all observations and variables in both DataFrames. Thus, the retained information is maximal, but on the other hand, missing values can be quite numerous. It will therefore be necessary to handle missing values well before proceeding with analyses. + +```{python} +df_merged_outer = pd.merge(df_a, df_b, how="outer", on='key') +df_merged_outer +``` + +## Exercises + +### Comprehension questions + +1. What is a DataFrame in the context of Pandas, and what type of data structure can it be compared to in Python? +2. What is the fundamental difference between a NumPy array and a Pandas Series? +3. What is the relationship between Series and DataFrame in Pandas? +4. How are data structured in a Pandas DataFrame? +5. What is the role of the index in a Pandas DataFrame, and how can it be used when manipulating data? +6. What methods can you use to explore an unknown DataFrame and learn more about its content and structure? +7. In Pandas, what is the difference between assigning the result of an operation to a new variable and using a method with the `inplace=True` argument? +8. How does the principle of vectorization apply in Pandas, and why is it advantageous for manipulating data? +9. How does Pandas represent missing values, and what impact does this have on calculations and data transformations? +10. What is the difference between concatenating two DataFrames and joining them via a merge, and when would you use one over the other? + +::: {.cell .markdown} + +
+Show solution + +1. A DataFrame in Pandas is a two-dimensional data structure, comparable to a table or an Excel spreadsheet. In the Python context, it can be compared to a dictionary of NumPy arrays, where the keys are column names, and the values are the columns themselves. + +2. The main difference between a NumPy array and a Pandas Series is that the Series can contain labeled data, meaning it has an associated index that allows access and manipulation by label. + +3. A DataFrame is essentially a collection of Series. Each column of a DataFrame is a Series, and all these Series share the same index, which corresponds to the row labels of the DataFrame. + +4. Data in a Pandas DataFrame are structured in columns and rows. Each column can contain a different type of data (numeric, string, boolean, etc.), and each row represents an observation. + +5. The index in a Pandas DataFrame serves to uniquely identify each row in the DataFrame. It allows quick access to rows, performing joins, sorting data, and facilitating grouping operations. + +6. To explore an unknown DataFrame, you can use `df.head()` to see the first rows, `df.tail()` for the last rows, `df.info()` to get a summary of data types and missing values, and `df.describe()` for descriptive statistics. + +7. Assigning the result of an operation to a new variable creates a copy of the DataFrame with the applied modifications. Using a method with `inplace=True` modifies the original DataFrame without creating a copy, which can be more memory-efficient. + +8. Pandas represents missing values with the `nan` (Not a Number) object from `NumPy` for numeric data and with `None` or `pd.NaT` for date/time data. These missing values are generally ignored in statistical calculations, which can affect the results if they are not handled properly. + +9. Concatenating consists of stacking DataFrames vertically or aligning them horizontally, primarily used when the DataFrames have the same schema or when you want to stack the data. Merging, inspired by SQL JOIN operations, combines DataFrames based on common key values and is used to enrich one dataset with information from another. + +
+ +::: + +### Multiple ways to create a DataFrame + +In the following cell, we have retrieved cash register data on sales from different stores. The data is presented in two different ways: one as observations (each list contains data from a row), and the other as variables (each list contains data from a column). + +```{python} +data_list1 = [ + ['Carrefour', '01.1.1', 3, 1.50], + ['Casino', '02.1.1', 2, 2.30], + ['Lidl', '01.1.1', 7, 0.99], + ['Carrefour', '03.1.1', 5, 5.00], + ['Casino', '01.1.1', 10, 1.20], + ['Lidl', '02.1.1', 1, 3.10] +] + +data_list2 = [ + ['Carrefour', 'Casino', 'Lidl', 'Carrefour', 'Casino', 'Lidl'], + ['01.1.1', '02.1.1', '01.1.1', '03.1.1', '01.1.1', '02.1.1'], + [3, 2, 7, 5, 10, 1], + [1.50, 2.30, 0.99, 5.00, 1.20, 3.10] +] +``` + +The goal is to build in both cases the same DataFrame containing each of the 6 observations and 4 variables, with the same names in both DataFrames. Each case will correspond to a more suitable input data structure, dictionary, or list of lists... make the right choice! We will verify that the two DataFrames are identical using the [equals()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.equals.html) method. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +data_list1 = [ + ['Carrefour', 'Casino', 'Lidl', 'Carrefour', 'Casino', 'Lidl'], + ['01.1.1', '02.1.1', '01.1.1', '03.1.1', '01.1.1', '02.1.1'], + [3, 2, 7, 5, 10, 1], + [1.50, 2.30, 0.99, 5.00, 1.20, 3.10] +] + +data_list2 = [ + ['Carrefour', '01.1.1', 3, 1.50], + ['Casino', '02.1.1', 2, 2.30], + ['Lidl', '01.1.1', 7, 0.99], + ['Carrefour', '03.1.1', 5, 5.00], + ['Casino', '01.1.1', 10, 1.20], + ['Lidl', '02.1.1', 1, 3.10] +] + +# If the data is in column form: from a dictionary +data_dict = { + 'store': data_list1[0], + 'product': data_list1[1], + 'quantity': data_list1[2], + 'price': data_list1[3] +} + +df_from_dict = pd.DataFrame(data_dict) + +# If the data is in row form: from a list of lists +columns = ['store', 'product', 'quantity', 'price'] +df_from_list = pd.DataFrame(data_list2, columns=columns) + +# Verification +df_from_dict.equals(df_from_list) +``` + +
+ +::: + +### Data selection in a DataFrame + +A Pandas DataFrame is created with cash register data (same data as the previous exercise). + +```{python} +data = { + 'store': ['Carrefour', 'Casino', 'Lidl', 'Carrefour', 'Casino', 'Lidl'], + 'product': ['01.1.1', '02.1.1', '01.1.1', '03.1.1', '01.1.1', '02.1.1'], + 'quantity': [3, 2, 7, 5, 10, 1], + 'price': [1.50, 2.30, 0.99, 5.00, 1.20, 3.10], + 'date_time': pd.to_datetime(["2022-01-01 14:05", "2022-01-02 09:30", + "2022-01-03 17:45", "2022-01-04 08:20", + "2022-01-05 19:00", "2022-01-06 16:30"]) +} + +df = pd.DataFrame(data) +``` + +Use the `loc` and `iloc` methods to select specific data: + +- Select the data from the first row. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +print(df.iloc[0]) +``` + +
+ +::: + +- Select all data from the "price" column. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +print(df.loc[:, 'price']) +``` + +
+ +::: + +- Select the rows corresponding to the store "Carrefour" only. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +print(df.loc[df['store'] == 'Carrefour']) +``` + +
+ +::: + +- Select the quantities purchased for products classified "01.1.1" (Bread). + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +print(df.loc[df['product'] == '01.1.1', 'quantity']) +``` + +
+ +::: + +- Select the data from the "store" and "price" columns for all rows. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +print(df.loc[:, ['store', 'price']]) +``` + +
+ +::: + +- Select the rows where the purchased quantity is greater than 5. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +print(df.loc[df['quantity'] > 5]) +``` + +
+ +::: + +- Filter to select all transactions that occurred after 3 PM. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +print(df.loc[df['date_time'].dt.hour > 15]) +``` + +
+ +::: + +- Select the transactions that took place on "2022-01-03". + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +print(df.loc[df['date_time'].dt.date == pd.to_datetime('2022-01-03').date()]) +``` + +
+ +::: + +### Exploring the first names file + +The first names file contains data on the first names given to children born in France between 1900 and 2021. This data is available at the national, department, and regional levels at the following address: [https://www.insee.fr/fr/statistiques/2540004?sommaire=4767262](https://www.insee.fr/fr/statistiques/2540004?sommaire=4767262). The goal of this tutorial is to propose an analysis of this file, from data cleaning to first name statistics. + +#### Part 1: Import and data exploration + +- Import the data into a DataFrame using this [URL](https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip). +- View a sample of the data. Do you notice any anomalies? +- Display the main information about the DataFrame. Identify any variables with incorrect types or any missing values. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +url = "https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip" +df_first_names = pd.read_csv(url, sep=";") + +df_first_names.head(10) +df_first_names.sample(n=50) + +df_first_names.info() +``` + +
+ +::: + +#### Part 2: Data cleaning + +- The output of the `info()` method suggests missing values in the first names column. Display these rows. Verify that these missing values are correctly specified. +- The output of the `head()` method shows a recurring "_PRENOMS_RARES" modality in the first names column. What proportion of the individuals in the database does this represent? Convert these values to `np.nan`. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +print(df_first_names[df_first_names["preusuel"].isna()]) +prop_rares = df_first_names.groupby("preusuel")["nombre"].sum()["_PRENOMS_RARES"] / df_first_names["nombre"].sum() +print(prop_rares) # ~ 2% of the database +df_first_names = df_first_names.replace('_PRENOMS_RARES', np.nan) +``` + +
+ +::: + +- We notice that the first names of people whose year of birth is unknown are grouped under the "XXXX" modality. What proportion of the individuals in the database does this represent? Convert these values to `np.nan`. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +prop_xxxx = df_first_names.groupby("annais")["nombre"].sum()["XXXX"] / df_first_names["nombre"].sum() +print(prop_xxxx) # ~ 1% of the database +df_first_names = df_first_names.replace('XXXX', np.nan) +``` + +
+ +::: + +- Remove the rows containing missing values from the sample. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +df_first_names = df_first_names.dropna() +``` + +
+ +::: + +- Convert the `annais` column to numeric type and the `sexe` column to categorical type. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +df_first_names['annais'] = pd.to_numeric(df_first_names['annais']) +df_first_names['sexe'] = df_first_names['sexe'].astype('category') +``` + +
+ +::: + +- Verify with the `info()` method that the cleaning has been correctly applied. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +df_first_names.info() +``` + +
+ +::: + +#### Part 3: Descriptive statistics on births + +- The [documentation](https://www.insee.fr/fr/statistiques/2540004?sommaire=4767262#documentation) of the file informs us that the data can be considered quasi-exhaustive from 1946 onwards. For this part only, filter the data to keep only data from 1946 onwards. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +df_first_names_post_1946 = df_first_names[df_first_names["annais"] >= 1946] +``` + +
+ +::: + +- Calculate the total number of births by sex. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +births_per_sex = df_first_names_post_1946.groupby('sexe')['nombre'].sum() +print(births_per_sex) +``` + +
+ +::: + +- Identify the five years with the highest number of births. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +top5_years = df_first_names_post_1946.groupby('annais')['nombre'].sum().nlargest(5) +print(top5_years) +``` + +
+ +::: + +#### Part 4: First name analysis + +- Identify the total number of unique first names in the DataFrame. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +total_unique_names = df_first_names['preusuel'].nunique() +print(total_unique_names) +``` + +
+ +::: + +- Count the number of people with a single-letter first name. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +single_letter_names = df_first_names[df_first_names['preusuel'].str.len() == 1]['nombre'].sum() +print(single_letter_names) +``` + +
+ +::: + +- Create a "popularity function" that, for a given first name, displays the year it was most given and the number of times it was given that year. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +def popularity_by_year(df, first_name): + # Filter the DataFrame to keep only the rows corresponding to the given first name + df_first_name = df[df['preusuel'] == first_name] + + # Group by year, sum the births, and identify the year with the maximum births + df_agg = df_first_name.groupby('annais')['nombre'].sum() + max_year = df_agg.idxmax() + max_n = df_agg[max_year] + + print(f"The first name '{first_name}' was most given in {max_year}, with {max_n} births.") + +# Test the function with an example +popularity_by_year(df_first_names, 'ALFRED') +``` + +
+ +::: + +- Create a function that, for a given sex, returns a DataFrame containing the most given first name for each decade. + +```{python} +# Test + + your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +def popularity_by_decade(df, sex): + # Filter by sex + df_sub = df[df["sexe"] == sex] + + # Calculate the decade variable + df_sub["decade"] = (df_sub["annais"] // 10) * 10 + + # Calculate the sum of births for each first name and each decade + df_counts_decade = df_sub.groupby(["preusuel", "decade"])["nombre"].sum().reset_index() + + # Find the index of the most frequent first name for each decade + idx = df_counts_decade.groupby("decade")["nombre"].idxmax() + + # Use the index to obtain the corresponding rows from the df_counts_decade DataFrame + df_popularity_decade = df_counts_decade.loc[idx].set_index("decade") + + return df_popularity_decade + +# Test the function with an example +popularity_by_decade(df_first_names, sex=2) +``` + +
+ +::: + +### Calculation of a carbon footprint per inhabitant at the municipal level + +The goal of this exercise is to calculate a carbon footprint per inhabitant at the municipal level. To do this, we will need to combine two data sources: + +- Legal populations at the municipal level from the population census ([source](https://www.insee.fr/fr/statistiques/6683037)) + +- Greenhouse gas emissions estimated at the municipal level by ADEME ([source](https://www.data.gouv.fr/fr/datasets/inventaire-de-gaz-a-effet-de-serre-territorialise/#_)) + +This exercise constitutes a simplified version of a [complete practical exercise on Pandas](https://pythonds.linogaliana.fr/content/manipulation/02b_pandas_TP.html#importer-les-donn%C3%A9es) proposed by Lino Galiana in his [course at ENSAE](https://pythonds.linogaliana.fr/). + +#### Part 1: Exploring the legal municipal populations data + +- Import the CSV file `communes.csv`. +- Use the `.sample()`, `.info()`, and `.describe()` methods to get an overview of the data. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +df_pop_communes = pd.read_csv("data/communes.csv", sep=";") + +df_pop_communes.sample(10) +df_pop_communes.info() +df_pop_communes.describe() +``` + +
+ +::: + +- Identify and remove rows corresponding to municipalities without population. +- Remove the "PMUN" and "PCAP" columns, which are irrelevant for the analysis. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +n_communes_0_pop = df_pop_communes[df_pop_communes["PTOT"] == 0].shape[0] +print(n_communes_0_pop) +df_pop_communes = df_pop_communes[df_pop_communes["PTOT"] > 0] + +df_pop_communes = df_pop_communes.drop(columns=["PMUN", "PCAP"]) +``` + +
+ +::: + +Do the municipalities with the longest names also have the smallest populations? To find out: +- Create a new variable that contains the number of characters of each municipality using the [str.len()](https://pandas.pydata.org/docs/reference/api/pandas.Series.str.len.html) method. +- Calculate the correlation between this variable and the total population using the [corr()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.corr.html) method. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +df_pop_communes_stats = df_pop_communes.copy() +df_pop_communes_stats['length'] = df_pop_communes_stats['COM'].str.len() +df_pop_communes_stats['length'].corr(df_pop_communes_stats['PTOT']) +``` + +
+ +::: + +#### Part 2: Exploring the municipal emissions data + +- Import the emissions data from this [URL](https://data.ademe.fr/data-fair/api/v1/datasets/igt-pouvoir-de-rechauffement-global/data-files/IGT%20-%20Pouvoir%20de%20r%C3%A9chauffement%20global.csv). +- Use the `.sample()`, `.info()`, and `.describe()` methods to get an overview of the data. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +url_ademe = "https://data.ademe.fr/data-fair/api/v1/datasets/igt-pouvoir-de-rechauffement-global/data-files/IGT%20-%20Pouvoir%20de%20r%C3%A9chauffement%20global.csv" +df_emissions = pd.read_csv(url_ademe) + +df_emissions.sample(10) +df_emissions.info() +df_emissions.describe() +``` + +
+ +::: + +- Are there rows with missing values for all emission columns? Check using the [isnull()](https://pandas.pydata.org/docs/reference/api/pandas.isnull.html) and [all()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.all.html) methods. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +df_emissions_num = df_emissions.select_dtypes(['number']) +only_nan = df_emissions_num[df_emissions_num.isnull().all(axis=1)] +only_nan.shape[0] +``` + +
+ +::: + +- Create a new column that gives the total emissions per municipality. +- Display the 10 most emitting municipalities. What do you observe in the results? + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +df_emissions['total_emissions'] = df_emissions.sum(axis=1, numeric_only=True) + +df_emissions.sort_values(by="total_emissions", ascending=False).head(10) +``` + +
+ +::: + +- It seems that the major emission sectors are "Industry excluding energy" and "Other international transport." To verify if this conjecture holds, calculate the correlation between total emissions and the sectoral emission items using the [corrwith()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.corrwith.html) method. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +df_emissions.corrwith(df_emissions["total_emissions"], numeric_only=True) +``` + +
+ +::: + +- Extract the department number from the municipality code into a new variable. +- Calculate the total emissions by department. +- Display the top 10 emitting departments. Are the results logical compared to the analysis at the municipal level? + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +df_emissions["dep"] = df_emissions["INSEE commune"].str[:2] +df_emissions.groupby("dep").agg({"total_emissions": "sum"}).sort_values(by="total_emissions", ascending=False).head(10) +``` + +
+ +::: + +#### Part 3: Preliminary checks for merging data sources + +To perform a merge, it is always preferable to have a join key, i.e., a column common to both sources that uniquely identifies the statistical units. The purpose of this part is to find the relevant join key. + +- Check if the variable containing the municipality names contains duplicates. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +duplicates = df_pop_communes.groupby('COM').count()['DEPCOM'] +duplicates = duplicates[duplicates > 1] +duplicates = duplicates.reset_index() +duplicates +``` + +
+ +::: + +- Filter in the initial DataFrame the municipalities with duplicated names and sort it by municipality code. Do the duplicates seem problematic? + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +df_pop_communes_duplicates = df_pop_communes[df_pop_communes["COM"].isin(duplicates["COM"])] +df_pop_communes_duplicates.sort_values('COM') +``` + +
+ +::: + +- Verify that the municipality codes uniquely identify the associated municipality. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +(df_pop_communes_duplicates.groupby("DEPCOM")["COM"].nunique() != 1).sum() +``` + +
+ +::: + +- Display the municipalities present in the population data but not in the emissions data, and vice versa. What do you conclude? + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +# Observations in the population data but not in the emissions data +df_pop_communes[~df_pop_communes["DEPCOM"].isin(df_emissions["INSEE commune"])] + +# Observations in the emissions data but not in the population data +df_emissions[~df_emissions["INSEE commune"].isin(df_pop_communes["DEPCOM"])] +``` + +
+ +::: + +#### Part 4: Calculating a carbon footprint per inhabitant for each municipality + +- Merge the two DataFrames using the municipality code as the join key. Note: the variables are not named the same on both sides! + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +df_emissions_pop = pd.merge(df_pop_communes, df_emissions, how="inner", left_on="DEPCOM", right_on="INSEE commune") +df_emissions_pop +``` + +
+ +::: + +- Calculate a carbon footprint for each municipality, corresponding to the total emissions of the municipality divided by its total population. +- Display the top 10 municipalities with the highest carbon footprints. +- Are the results the same as those with total emissions? What do you conclude? + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +df_emissions_pop["carbon_footprint"] = df_emissions_pop["total_emissions"] / df_emissions_pop["PTOT"] +df_emissions_pop.sort_values("carbon_footprint", ascending=False).head(10) +``` + +
+ +::: + +### Analysis of the evolution of a production index + +You have two CSV data sets available in the `data/` folder: + +- `serie_glaces_valeurs.csv` contains the monthly values of the production price index of the French ice cream and sorbet industry. +- `serie_glaces_metadonnees.csv` contains the associated metadata, including the codes indicating the data status. + +The goal is to use `Pandas` to calculate: + +- the evolution of the index between each period (month) +- the evolution of the index on a year-over-year basis (between a given month and the same month the following year). + +#### Part 1: Importing data + +- Import the two CSV files into DataFrames. Note: in both cases, there are extraneous rows before the data that need to be skipped using the `skiprows` parameter of the [read_csv()](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html) function. +- Give simple and relevant names to the various variables. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +df_values = pd.read_csv('data/serie_glaces_valeurs.csv', delimiter=';', + skiprows=4, names=["period", "index", "code"]) +df_metadata = pd.read_csv('data/serie_glaces_metadonnees.csv', delimiter=';', + skiprows=5, names=["code", "meaning"]) +``` + +
+ +::: + +#### Part 2: Filtering relevant data + +- Merge the two DataFrames to retrieve the meanings of the codes present in the data. +- Filter the data to keep only the "Normal Value" data. +- Remove the columns related to the codes, which we no longer need for the rest. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +df_merged = pd.merge(df_values, df_metadata, how='left', on='code') + +df_clean = df_merged[df_merged['code'] == "A"] +df_clean = df_clean[["period", "index"]] +``` + +
+ +::: + +#### Part 3: Data preprocessing + +Verify if the types of variables are relevant according to their nature. If not, convert them with the appropriate functions. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +df_clean.info() +df_clean['period'] = pd.to_datetime(df_clean['period']) +df_clean['index'] = pd.to_numeric(df_clean['index']) +df_clean.info() +``` + +
+ +::: + +#### Part 4: Calculating periodic evolution + +- Use the [shift()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.shift.html) method to create a new column containing the previous month's index. +- Calculate the difference between the current index and the shifted index to obtain the (percentage) evolution from one month to the next. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +df_clean['previous_index'] = df_clean['index'].shift(1) +df_clean['evolution'] = ((df_clean['index'] - df_clean['previous_index']) / df_clean['previous_index']) * 100 + +# Alternative method +df_clean['alternative_evolution'] = df_clean['index'].pct_change(periods=1) * 100 +``` + +
+ +::: + +#### Part 5: Calculating year-over-year evolution + +As you saw in the previous exercise's solution, the [pct_change()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.pct_change.html) method allows you to calculate an evolution between two periods. Use this method to calculate a year-over-year evolution for each month. + +```{python} +# Test your answer in this cell +``` + +::: {.cell .markdown} + +
+Show solution + +```{python} +df_clean["year_over_year_evolution"] = df_clean['index'].pct_change(periods=12) * 100 +df_clean.head(20) +``` + +
+ +::: + + +::: From 3d7bbccab466d433165ac11d3aa5d1c59715a2a9 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Mon, 5 Jan 2026 11:29:42 +0000 Subject: [PATCH 05/92] add polars to site structure --- _quarto-en.yaml | 8 +++++--- _quarto-fr.yaml | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/_quarto-en.yaml b/_quarto-en.yaml index 1610dd35..8bc3cdca 100644 --- a/_quarto-en.yaml +++ b/_quarto-en.yaml @@ -7,7 +7,7 @@ website: style: 'docked' contents: - section: "Fundamentals" - contents: + contents: - text: "Basic types and variables" href: source/fundamentals/types-variables/tutorial.qmd - text: "Data structures 1: lists and tuples" @@ -23,7 +23,7 @@ website: - text: "Introduction to object-oriented programming" href: source/fundamentals/oop/tutorial.qmd - section: "Data handling" - contents: + contents: - text: "File manipulation" href: source/manipulation/modules-files/tutorial.qmd - text: "Working with CSV and JSON files" @@ -32,10 +32,12 @@ website: href: source/manipulation/numpy/tutorial.qmd - text: "Processing tabular data with Pandas" href: source/manipulation/pandas/tutorial.qmd + - text: "Processing tabular data with Polars" + href: source/manipulation/polars/tutorial.qmd - text: "Introduction to data visualization" href: source/manipulation/dataviz/tutorial.qmd - section: "Projects" - contents: + contents: - text: "Project 1 - Connect 4" href: source/projects/puissance4/tutorial.qmd - text: "Project 2 - Wheather forecast" diff --git a/_quarto-fr.yaml b/_quarto-fr.yaml index b96c6d83..11f5b9eb 100644 --- a/_quarto-fr.yaml +++ b/_quarto-fr.yaml @@ -4,7 +4,7 @@ website: style: 'docked' contents: - section: "Fondamentaux du langage" - contents: + contents: - text: "Types de base et variables" href: source/fundamentals/types-variables/tutorial.qmd - text: "Structures de données 1 : listes et tuples" @@ -20,7 +20,7 @@ website: - text: "Notions de programmation orientée objet" href: source/fundamentals/oop/tutorial.qmd - section: "Manipulation de données" - contents: + contents: - text: "Manipulation de fichiers" href: source/manipulation/modules-files/tutorial.qmd - text: "Travailler avec des fichiers CSV et JSON" @@ -29,10 +29,12 @@ website: href: source/manipulation/numpy/tutorial.qmd - text: "Traiter des données tabulaires avec Pandas" href: source/manipulation/pandas/tutorial.qmd + - text: "Traiter des données tabulaires avec Polars" + href: source/manipulation/polars/tutorial.qmd - text: "Introduction à la visualisation de données" href: source/manipulation/dataviz/tutorial.qmd - section: "Projets" - contents: + contents: - text: "Projet 1 - Puissance 4" href: source/projects/puissance4/tutorial.qmd - text: "Projet 2 - Prédictions météorologiques" From 4d49d811a08be2232b1101f9b663958f5fd9d284 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Mon, 5 Jan 2026 21:18:35 +0000 Subject: [PATCH 06/92] move to uv --- pyproject.toml | 20 ++ requirements.txt | 9 - uv.lock | 876 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 896 insertions(+), 9 deletions(-) create mode 100644 pyproject.toml delete mode 100644 requirements.txt create mode 100644 uv.lock diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..aabc9bb0 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,20 @@ +[project] +name = "" +version = "0.0.1" +requires-python = ">=3.13" +dependencies = [ + "geopandas", + "matplotlib", + "numpy", + "pandas", + "pyarrow", + "requests", + "seaborn", + "scikit-learn", + "xlrd", + "polars>=1.36.1", + "tidypolars>=0.3.2", +] + +[tool.uv] +package = false diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 41089979..00000000 --- a/requirements.txt +++ /dev/null @@ -1,9 +0,0 @@ -geopandas -matplotlib -numpy -pandas -pyarrow -requests -seaborn -scikit-learn -xlrd \ No newline at end of file diff --git a/uv.lock b/uv.lock new file mode 100644 index 00000000..b1e016ce --- /dev/null +++ b/uv.lock @@ -0,0 +1,876 @@ +version = 1 +revision = 3 +requires-python = ">=3.13" + +[[package]] +name = "" +version = "0.0.1" +source = { virtual = "." } +dependencies = [ + { name = "geopandas" }, + { name = "matplotlib" }, + { name = "numpy" }, + { name = "pandas" }, + { name = "polars" }, + { name = "pyarrow" }, + { name = "requests" }, + { name = "scikit-learn" }, + { name = "seaborn" }, + { name = "tidypolars" }, + { name = "xlrd" }, +] + +[package.metadata] +requires-dist = [ + { name = "geopandas" }, + { name = "matplotlib" }, + { name = "numpy" }, + { name = "pandas" }, + { name = "polars", specifier = ">=1.36.1" }, + { name = "pyarrow" }, + { name = "requests" }, + { name = "scikit-learn" }, + { name = "seaborn" }, + { name = "tidypolars", specifier = ">=0.3.2" }, + { name = "xlrd" }, +] + +[[package]] +name = "certifi" +version = "2026.1.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/2d/a891ca51311197f6ad14a7ef42e2399f36cf2f9bd44752b3dc4eab60fdc5/certifi-2026.1.4.tar.gz", hash = "sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120", size = 154268, upload-time = "2026-01-04T02:42:41.825Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c", size = 152900, upload-time = "2026-01-04T02:42:40.15Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, + { url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, + { url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, + { url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, + { url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, + { url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, + { url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, + { url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, + { url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, + { url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, + { url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, + { url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, + { url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, + { url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, + { url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" }, + { url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" }, + { url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" }, + { url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" }, + { url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" }, + { url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" }, + { url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" }, + { url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" }, + { url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" }, + { url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" }, + { url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" }, + { url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" }, + { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" }, + { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" }, + { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, +] + +[[package]] +name = "contourpy" +version = "1.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/58/01/1253e6698a07380cd31a736d248a3f2a50a7c88779a1813da27503cadc2a/contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880", size = 13466174, upload-time = "2025-07-26T12:03:12.549Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/68/35/0167aad910bbdb9599272bd96d01a9ec6852f36b9455cf2ca67bd4cc2d23/contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:177fb367556747a686509d6fef71d221a4b198a3905fe824430e5ea0fda54eb5", size = 293257, upload-time = "2025-07-26T12:01:39.367Z" }, + { url = "https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1", size = 274034, upload-time = "2025-07-26T12:01:40.645Z" }, + { url = "https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286", size = 334672, upload-time = "2025-07-26T12:01:41.942Z" }, + { url = "https://files.pythonhosted.org/packages/ed/93/b43d8acbe67392e659e1d984700e79eb67e2acb2bd7f62012b583a7f1b55/contourpy-1.3.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:655456777ff65c2c548b7c454af9c6f33f16c8884f11083244b5819cc214f1b5", size = 381234, upload-time = "2025-07-26T12:01:43.499Z" }, + { url = "https://files.pythonhosted.org/packages/46/3b/bec82a3ea06f66711520f75a40c8fc0b113b2a75edb36aa633eb11c4f50f/contourpy-1.3.3-cp313-cp313-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:644a6853d15b2512d67881586bd03f462c7ab755db95f16f14d7e238f2852c67", size = 385169, upload-time = "2025-07-26T12:01:45.219Z" }, + { url = "https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9", size = 362859, upload-time = "2025-07-26T12:01:46.519Z" }, + { url = "https://files.pythonhosted.org/packages/33/71/e2a7945b7de4e58af42d708a219f3b2f4cff7386e6b6ab0a0fa0033c49a9/contourpy-1.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a15459b0f4615b00bbd1e91f1b9e19b7e63aea7483d03d804186f278c0af2659", size = 1332062, upload-time = "2025-07-26T12:01:48.964Z" }, + { url = "https://files.pythonhosted.org/packages/12/fc/4e87ac754220ccc0e807284f88e943d6d43b43843614f0a8afa469801db0/contourpy-1.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca0fdcd73925568ca027e0b17ab07aad764be4706d0a925b89227e447d9737b7", size = 1403932, upload-time = "2025-07-26T12:01:51.979Z" }, + { url = "https://files.pythonhosted.org/packages/a6/2e/adc197a37443f934594112222ac1aa7dc9a98faf9c3842884df9a9d8751d/contourpy-1.3.3-cp313-cp313-win32.whl", hash = "sha256:b20c7c9a3bf701366556e1b1984ed2d0cedf999903c51311417cf5f591d8c78d", size = 185024, upload-time = "2025-07-26T12:01:53.245Z" }, + { url = "https://files.pythonhosted.org/packages/18/0b/0098c214843213759692cc638fce7de5c289200a830e5035d1791d7a2338/contourpy-1.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:1cadd8b8969f060ba45ed7c1b714fe69185812ab43bd6b86a9123fe8f99c3263", size = 226578, upload-time = "2025-07-26T12:01:54.422Z" }, + { url = "https://files.pythonhosted.org/packages/8a/9a/2f6024a0c5995243cd63afdeb3651c984f0d2bc727fd98066d40e141ad73/contourpy-1.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:fd914713266421b7536de2bfa8181aa8c699432b6763a0ea64195ebe28bff6a9", size = 193524, upload-time = "2025-07-26T12:01:55.73Z" }, + { url = "https://files.pythonhosted.org/packages/c0/b3/f8a1a86bd3298513f500e5b1f5fd92b69896449f6cab6a146a5d52715479/contourpy-1.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:88df9880d507169449d434c293467418b9f6cbe82edd19284aa0409e7fdb933d", size = 306730, upload-time = "2025-07-26T12:01:57.051Z" }, + { url = "https://files.pythonhosted.org/packages/3f/11/4780db94ae62fc0c2053909b65dc3246bd7cecfc4f8a20d957ad43aa4ad8/contourpy-1.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d06bb1f751ba5d417047db62bca3c8fde202b8c11fb50742ab3ab962c81e8216", size = 287897, upload-time = "2025-07-26T12:01:58.663Z" }, + { url = "https://files.pythonhosted.org/packages/ae/15/e59f5f3ffdd6f3d4daa3e47114c53daabcb18574a26c21f03dc9e4e42ff0/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4e6b05a45525357e382909a4c1600444e2a45b4795163d3b22669285591c1ae", size = 326751, upload-time = "2025-07-26T12:02:00.343Z" }, + { url = "https://files.pythonhosted.org/packages/0f/81/03b45cfad088e4770b1dcf72ea78d3802d04200009fb364d18a493857210/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab3074b48c4e2cf1a960e6bbeb7f04566bf36b1861d5c9d4d8ac04b82e38ba20", size = 375486, upload-time = "2025-07-26T12:02:02.128Z" }, + { url = "https://files.pythonhosted.org/packages/0c/ba/49923366492ffbdd4486e970d421b289a670ae8cf539c1ea9a09822b371a/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c3d53c796f8647d6deb1abe867daeb66dcc8a97e8455efa729516b997b8ed99", size = 388106, upload-time = "2025-07-26T12:02:03.615Z" }, + { url = "https://files.pythonhosted.org/packages/9f/52/5b00ea89525f8f143651f9f03a0df371d3cbd2fccd21ca9b768c7a6500c2/contourpy-1.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50ed930df7289ff2a8d7afeb9603f8289e5704755c7e5c3bbd929c90c817164b", size = 352548, upload-time = "2025-07-26T12:02:05.165Z" }, + { url = "https://files.pythonhosted.org/packages/32/1d/a209ec1a3a3452d490f6b14dd92e72280c99ae3d1e73da74f8277d4ee08f/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4feffb6537d64b84877da813a5c30f1422ea5739566abf0bd18065ac040e120a", size = 1322297, upload-time = "2025-07-26T12:02:07.379Z" }, + { url = "https://files.pythonhosted.org/packages/bc/9e/46f0e8ebdd884ca0e8877e46a3f4e633f6c9c8c4f3f6e72be3fe075994aa/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2b7e9480ffe2b0cd2e787e4df64270e3a0440d9db8dc823312e2c940c167df7e", size = 1391023, upload-time = "2025-07-26T12:02:10.171Z" }, + { url = "https://files.pythonhosted.org/packages/b9/70/f308384a3ae9cd2209e0849f33c913f658d3326900d0ff5d378d6a1422d2/contourpy-1.3.3-cp313-cp313t-win32.whl", hash = "sha256:283edd842a01e3dcd435b1c5116798d661378d83d36d337b8dde1d16a5fc9ba3", size = 196157, upload-time = "2025-07-26T12:02:11.488Z" }, + { url = "https://files.pythonhosted.org/packages/b2/dd/880f890a6663b84d9e34a6f88cded89d78f0091e0045a284427cb6b18521/contourpy-1.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:87acf5963fc2b34825e5b6b048f40e3635dd547f590b04d2ab317c2619ef7ae8", size = 240570, upload-time = "2025-07-26T12:02:12.754Z" }, + { url = "https://files.pythonhosted.org/packages/80/99/2adc7d8ffead633234817ef8e9a87115c8a11927a94478f6bb3d3f4d4f7d/contourpy-1.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:3c30273eb2a55024ff31ba7d052dde990d7d8e5450f4bbb6e913558b3d6c2301", size = 199713, upload-time = "2025-07-26T12:02:14.4Z" }, + { url = "https://files.pythonhosted.org/packages/72/8b/4546f3ab60f78c514ffb7d01a0bd743f90de36f0019d1be84d0a708a580a/contourpy-1.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fde6c716d51c04b1c25d0b90364d0be954624a0ee9d60e23e850e8d48353d07a", size = 292189, upload-time = "2025-07-26T12:02:16.095Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77", size = 273251, upload-time = "2025-07-26T12:02:17.524Z" }, + { url = "https://files.pythonhosted.org/packages/b1/71/f93e1e9471d189f79d0ce2497007731c1e6bf9ef6d1d61b911430c3db4e5/contourpy-1.3.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22e9b1bd7a9b1d652cd77388465dc358dafcd2e217d35552424aa4f996f524f5", size = 335810, upload-time = "2025-07-26T12:02:18.9Z" }, + { url = "https://files.pythonhosted.org/packages/91/f9/e35f4c1c93f9275d4e38681a80506b5510e9327350c51f8d4a5a724d178c/contourpy-1.3.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a22738912262aa3e254e4f3cb079a95a67132fc5a063890e224393596902f5a4", size = 382871, upload-time = "2025-07-26T12:02:20.418Z" }, + { url = "https://files.pythonhosted.org/packages/b5/71/47b512f936f66a0a900d81c396a7e60d73419868fba959c61efed7a8ab46/contourpy-1.3.3-cp314-cp314-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:afe5a512f31ee6bd7d0dda52ec9864c984ca3d66664444f2d72e0dc4eb832e36", size = 386264, upload-time = "2025-07-26T12:02:21.916Z" }, + { url = "https://files.pythonhosted.org/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3", size = 363819, upload-time = "2025-07-26T12:02:23.759Z" }, + { url = "https://files.pythonhosted.org/packages/3e/a6/0b185d4cc480ee494945cde102cb0149ae830b5fa17bf855b95f2e70ad13/contourpy-1.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1fd43c3be4c8e5fd6e4f2baeae35ae18176cf2e5cced681cca908addf1cdd53b", size = 1333650, upload-time = "2025-07-26T12:02:26.181Z" }, + { url = "https://files.pythonhosted.org/packages/43/d7/afdc95580ca56f30fbcd3060250f66cedbde69b4547028863abd8aa3b47e/contourpy-1.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6afc576f7b33cf00996e5c1102dc2a8f7cc89e39c0b55df93a0b78c1bd992b36", size = 1404833, upload-time = "2025-07-26T12:02:28.782Z" }, + { url = "https://files.pythonhosted.org/packages/e2/e2/366af18a6d386f41132a48f033cbd2102e9b0cf6345d35ff0826cd984566/contourpy-1.3.3-cp314-cp314-win32.whl", hash = "sha256:66c8a43a4f7b8df8b71ee1840e4211a3c8d93b214b213f590e18a1beca458f7d", size = 189692, upload-time = "2025-07-26T12:02:30.128Z" }, + { url = "https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd", size = 232424, upload-time = "2025-07-26T12:02:31.395Z" }, + { url = "https://files.pythonhosted.org/packages/18/79/a9416650df9b525737ab521aa181ccc42d56016d2123ddcb7b58e926a42c/contourpy-1.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:95b181891b4c71de4bb404c6621e7e2390745f887f2a026b2d99e92c17892339", size = 198300, upload-time = "2025-07-26T12:02:32.956Z" }, + { url = "https://files.pythonhosted.org/packages/1f/42/38c159a7d0f2b7b9c04c64ab317042bb6952b713ba875c1681529a2932fe/contourpy-1.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:33c82d0138c0a062380332c861387650c82e4cf1747aaa6938b9b6516762e772", size = 306769, upload-time = "2025-07-26T12:02:34.2Z" }, + { url = "https://files.pythonhosted.org/packages/c3/6c/26a8205f24bca10974e77460de68d3d7c63e282e23782f1239f226fcae6f/contourpy-1.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ea37e7b45949df430fe649e5de8351c423430046a2af20b1c1961cae3afcda77", size = 287892, upload-time = "2025-07-26T12:02:35.807Z" }, + { url = "https://files.pythonhosted.org/packages/66/06/8a475c8ab718ebfd7925661747dbb3c3ee9c82ac834ccb3570be49d129f4/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d304906ecc71672e9c89e87c4675dc5c2645e1f4269a5063b99b0bb29f232d13", size = 326748, upload-time = "2025-07-26T12:02:37.193Z" }, + { url = "https://files.pythonhosted.org/packages/b4/a3/c5ca9f010a44c223f098fccd8b158bb1cb287378a31ac141f04730dc49be/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca658cd1a680a5c9ea96dc61cdbae1e85c8f25849843aa799dfd3cb370ad4fbe", size = 375554, upload-time = "2025-07-26T12:02:38.894Z" }, + { url = "https://files.pythonhosted.org/packages/80/5b/68bd33ae63fac658a4145088c1e894405e07584a316738710b636c6d0333/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ab2fd90904c503739a75b7c8c5c01160130ba67944a7b77bbf36ef8054576e7f", size = 388118, upload-time = "2025-07-26T12:02:40.642Z" }, + { url = "https://files.pythonhosted.org/packages/40/52/4c285a6435940ae25d7410a6c36bda5145839bc3f0beb20c707cda18b9d2/contourpy-1.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7301b89040075c30e5768810bc96a8e8d78085b47d8be6e4c3f5a0b4ed478a0", size = 352555, upload-time = "2025-07-26T12:02:42.25Z" }, + { url = "https://files.pythonhosted.org/packages/24/ee/3e81e1dd174f5c7fefe50e85d0892de05ca4e26ef1c9a59c2a57e43b865a/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2a2a8b627d5cc6b7c41a4beff6c5ad5eb848c88255fda4a8745f7e901b32d8e4", size = 1322295, upload-time = "2025-07-26T12:02:44.668Z" }, + { url = "https://files.pythonhosted.org/packages/3c/b2/6d913d4d04e14379de429057cd169e5e00f6c2af3bb13e1710bcbdb5da12/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fd6ec6be509c787f1caf6b247f0b1ca598bef13f4ddeaa126b7658215529ba0f", size = 1391027, upload-time = "2025-07-26T12:02:47.09Z" }, + { url = "https://files.pythonhosted.org/packages/93/8a/68a4ec5c55a2971213d29a9374913f7e9f18581945a7a31d1a39b5d2dfe5/contourpy-1.3.3-cp314-cp314t-win32.whl", hash = "sha256:e74a9a0f5e3fff48fb5a7f2fd2b9b70a3fe014a67522f79b7cca4c0c7e43c9ae", size = 202428, upload-time = "2025-07-26T12:02:48.691Z" }, + { url = "https://files.pythonhosted.org/packages/fa/96/fd9f641ffedc4fa3ace923af73b9d07e869496c9cc7a459103e6e978992f/contourpy-1.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:13b68d6a62db8eafaebb8039218921399baf6e47bf85006fd8529f2a08ef33fc", size = 250331, upload-time = "2025-07-26T12:02:50.137Z" }, + { url = "https://files.pythonhosted.org/packages/ae/8c/469afb6465b853afff216f9528ffda78a915ff880ed58813ba4faf4ba0b6/contourpy-1.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b7448cb5a725bb1e35ce88771b86fba35ef418952474492cf7c764059933ff8b", size = 203831, upload-time = "2025-07-26T12:02:51.449Z" }, +] + +[[package]] +name = "cycler" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615, upload-time = "2023-10-07T05:32:18.335Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" }, +] + +[[package]] +name = "fonttools" +version = "4.61.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/ca/cf17b88a8df95691275a3d77dc0a5ad9907f328ae53acbe6795da1b2f5ed/fonttools-4.61.1.tar.gz", hash = "sha256:6675329885c44657f826ef01d9e4fb33b9158e9d93c537d84ad8399539bc6f69", size = 3565756, upload-time = "2025-12-12T17:31:24.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/cf/00ba28b0990982530addb8dc3e9e6f2fa9cb5c20df2abdda7baa755e8fe1/fonttools-4.61.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8c56c488ab471628ff3bfa80964372fc13504ece601e0d97a78ee74126b2045c", size = 2846454, upload-time = "2025-12-12T17:30:24.938Z" }, + { url = "https://files.pythonhosted.org/packages/5a/ca/468c9a8446a2103ae645d14fee3f610567b7042aba85031c1c65e3ef7471/fonttools-4.61.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dc492779501fa723b04d0ab1f5be046797fee17d27700476edc7ee9ae535a61e", size = 2398191, upload-time = "2025-12-12T17:30:27.343Z" }, + { url = "https://files.pythonhosted.org/packages/a3/4b/d67eedaed19def5967fade3297fed8161b25ba94699efc124b14fb68cdbc/fonttools-4.61.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:64102ca87e84261419c3747a0d20f396eb024bdbeb04c2bfb37e2891f5fadcb5", size = 4928410, upload-time = "2025-12-12T17:30:29.771Z" }, + { url = "https://files.pythonhosted.org/packages/b0/8d/6fb3494dfe61a46258cd93d979cf4725ded4eb46c2a4ca35e4490d84daea/fonttools-4.61.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c1b526c8d3f615a7b1867f38a9410849c8f4aef078535742198e942fba0e9bd", size = 4984460, upload-time = "2025-12-12T17:30:32.073Z" }, + { url = "https://files.pythonhosted.org/packages/f7/f1/a47f1d30b3dc00d75e7af762652d4cbc3dff5c2697a0dbd5203c81afd9c3/fonttools-4.61.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:41ed4b5ec103bd306bb68f81dc166e77409e5209443e5773cb4ed837bcc9b0d3", size = 4925800, upload-time = "2025-12-12T17:30:34.339Z" }, + { url = "https://files.pythonhosted.org/packages/a7/01/e6ae64a0981076e8a66906fab01539799546181e32a37a0257b77e4aa88b/fonttools-4.61.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b501c862d4901792adaec7c25b1ecc749e2662543f68bb194c42ba18d6eec98d", size = 5067859, upload-time = "2025-12-12T17:30:36.593Z" }, + { url = "https://files.pythonhosted.org/packages/73/aa/28e40b8d6809a9b5075350a86779163f074d2b617c15d22343fce81918db/fonttools-4.61.1-cp313-cp313-win32.whl", hash = "sha256:4d7092bb38c53bbc78e9255a59158b150bcdc115a1e3b3ce0b5f267dc35dd63c", size = 2267821, upload-time = "2025-12-12T17:30:38.478Z" }, + { url = "https://files.pythonhosted.org/packages/1a/59/453c06d1d83dc0951b69ef692d6b9f1846680342927df54e9a1ca91c6f90/fonttools-4.61.1-cp313-cp313-win_amd64.whl", hash = "sha256:21e7c8d76f62ab13c9472ccf74515ca5b9a761d1bde3265152a6dc58700d895b", size = 2318169, upload-time = "2025-12-12T17:30:40.951Z" }, + { url = "https://files.pythonhosted.org/packages/32/8f/4e7bf82c0cbb738d3c2206c920ca34ca74ef9dabde779030145d28665104/fonttools-4.61.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fff4f534200a04b4a36e7ae3cb74493afe807b517a09e99cb4faa89a34ed6ecd", size = 2846094, upload-time = "2025-12-12T17:30:43.511Z" }, + { url = "https://files.pythonhosted.org/packages/71/09/d44e45d0a4f3a651f23a1e9d42de43bc643cce2971b19e784cc67d823676/fonttools-4.61.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d9203500f7c63545b4ce3799319fe4d9feb1a1b89b28d3cb5abd11b9dd64147e", size = 2396589, upload-time = "2025-12-12T17:30:45.681Z" }, + { url = "https://files.pythonhosted.org/packages/89/18/58c64cafcf8eb677a99ef593121f719e6dcbdb7d1c594ae5a10d4997ca8a/fonttools-4.61.1-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fa646ecec9528bef693415c79a86e733c70a4965dd938e9a226b0fc64c9d2e6c", size = 4877892, upload-time = "2025-12-12T17:30:47.709Z" }, + { url = "https://files.pythonhosted.org/packages/8a/ec/9e6b38c7ba1e09eb51db849d5450f4c05b7e78481f662c3b79dbde6f3d04/fonttools-4.61.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11f35ad7805edba3aac1a3710d104592df59f4b957e30108ae0ba6c10b11dd75", size = 4972884, upload-time = "2025-12-12T17:30:49.656Z" }, + { url = "https://files.pythonhosted.org/packages/5e/87/b5339da8e0256734ba0dbbf5b6cdebb1dd79b01dc8c270989b7bcd465541/fonttools-4.61.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b931ae8f62db78861b0ff1ac017851764602288575d65b8e8ff1963fed419063", size = 4924405, upload-time = "2025-12-12T17:30:51.735Z" }, + { url = "https://files.pythonhosted.org/packages/0b/47/e3409f1e1e69c073a3a6fd8cb886eb18c0bae0ee13db2c8d5e7f8495e8b7/fonttools-4.61.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b148b56f5de675ee16d45e769e69f87623a4944f7443850bf9a9376e628a89d2", size = 5035553, upload-time = "2025-12-12T17:30:54.823Z" }, + { url = "https://files.pythonhosted.org/packages/bf/b6/1f6600161b1073a984294c6c031e1a56ebf95b6164249eecf30012bb2e38/fonttools-4.61.1-cp314-cp314-win32.whl", hash = "sha256:9b666a475a65f4e839d3d10473fad6d47e0a9db14a2f4a224029c5bfde58ad2c", size = 2271915, upload-time = "2025-12-12T17:30:57.913Z" }, + { url = "https://files.pythonhosted.org/packages/52/7b/91e7b01e37cc8eb0e1f770d08305b3655e4f002fc160fb82b3390eabacf5/fonttools-4.61.1-cp314-cp314-win_amd64.whl", hash = "sha256:4f5686e1fe5fce75d82d93c47a438a25bf0d1319d2843a926f741140b2b16e0c", size = 2323487, upload-time = "2025-12-12T17:30:59.804Z" }, + { url = "https://files.pythonhosted.org/packages/39/5c/908ad78e46c61c3e3ed70c3b58ff82ab48437faf84ec84f109592cabbd9f/fonttools-4.61.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:e76ce097e3c57c4bcb67c5aa24a0ecdbd9f74ea9219997a707a4061fbe2707aa", size = 2929571, upload-time = "2025-12-12T17:31:02.574Z" }, + { url = "https://files.pythonhosted.org/packages/bd/41/975804132c6dea64cdbfbaa59f3518a21c137a10cccf962805b301ac6ab2/fonttools-4.61.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9cfef3ab326780c04d6646f68d4b4742aae222e8b8ea1d627c74e38afcbc9d91", size = 2435317, upload-time = "2025-12-12T17:31:04.974Z" }, + { url = "https://files.pythonhosted.org/packages/b0/5a/aef2a0a8daf1ebaae4cfd83f84186d4a72ee08fd6a8451289fcd03ffa8a4/fonttools-4.61.1-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a75c301f96db737e1c5ed5fd7d77d9c34466de16095a266509e13da09751bd19", size = 4882124, upload-time = "2025-12-12T17:31:07.456Z" }, + { url = "https://files.pythonhosted.org/packages/80/33/d6db3485b645b81cea538c9d1c9219d5805f0877fda18777add4671c5240/fonttools-4.61.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:91669ccac46bbc1d09e9273546181919064e8df73488ea087dcac3e2968df9ba", size = 5100391, upload-time = "2025-12-12T17:31:09.732Z" }, + { url = "https://files.pythonhosted.org/packages/6c/d6/675ba631454043c75fcf76f0ca5463eac8eb0666ea1d7badae5fea001155/fonttools-4.61.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c33ab3ca9d3ccd581d58e989d67554e42d8d4ded94ab3ade3508455fe70e65f7", size = 4978800, upload-time = "2025-12-12T17:31:11.681Z" }, + { url = "https://files.pythonhosted.org/packages/7f/33/d3ec753d547a8d2bdaedd390d4a814e8d5b45a093d558f025c6b990b554c/fonttools-4.61.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:664c5a68ec406f6b1547946683008576ef8b38275608e1cee6c061828171c118", size = 5006426, upload-time = "2025-12-12T17:31:13.764Z" }, + { url = "https://files.pythonhosted.org/packages/b4/40/cc11f378b561a67bea850ab50063366a0d1dd3f6d0a30ce0f874b0ad5664/fonttools-4.61.1-cp314-cp314t-win32.whl", hash = "sha256:aed04cabe26f30c1647ef0e8fbb207516fd40fe9472e9439695f5c6998e60ac5", size = 2335377, upload-time = "2025-12-12T17:31:16.49Z" }, + { url = "https://files.pythonhosted.org/packages/e4/ff/c9a2b66b39f8628531ea58b320d66d951267c98c6a38684daa8f50fb02f8/fonttools-4.61.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2180f14c141d2f0f3da43f3a81bc8aa4684860f6b0e6f9e165a4831f24e6a23b", size = 2400613, upload-time = "2025-12-12T17:31:18.769Z" }, + { url = "https://files.pythonhosted.org/packages/c7/4e/ce75a57ff3aebf6fc1f4e9d508b8e5810618a33d900ad6c19eb30b290b97/fonttools-4.61.1-py3-none-any.whl", hash = "sha256:17d2bf5d541add43822bcf0c43d7d847b160c9bb01d15d5007d84e2217aaa371", size = 1148996, upload-time = "2025-12-12T17:31:21.03Z" }, +] + +[[package]] +name = "geopandas" +version = "1.1.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, + { name = "packaging" }, + { name = "pandas" }, + { name = "pyogrio" }, + { name = "pyproj" }, + { name = "shapely" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8d/24/5eb5685d7bf89d64218919379f882d19a60f8219d66d833c83b1cf264c95/geopandas-1.1.2.tar.gz", hash = "sha256:33f7b33565c46a45b8459a2ab699ec943fdbb5716e58e251b3c413cf7783106c", size = 336037, upload-time = "2025-12-22T21:06:13.749Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/e4/fac19dc34cb686c96011388b813ff7b858a70681e5ce6ce7698e5021b0f4/geopandas-1.1.2-py3-none-any.whl", hash = "sha256:2bb0b1052cb47378addb4ba54c47f8d4642dcbda9b61375638274f49d9f0bb0d", size = 341734, upload-time = "2025-12-22T21:06:12.498Z" }, +] + +[[package]] +name = "idna" +version = "3.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, +] + +[[package]] +name = "joblib" +version = "1.5.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/41/f2/d34e8b3a08a9cc79a50b2208a93dce981fe615b64d5a4d4abee421d898df/joblib-1.5.3.tar.gz", hash = "sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3", size = 331603, upload-time = "2025-12-15T08:41:46.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713", size = 309071, upload-time = "2025-12-15T08:41:44.973Z" }, +] + +[[package]] +name = "kiwisolver" +version = "1.4.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5c/3c/85844f1b0feb11ee581ac23fe5fce65cd049a200c1446708cc1b7f922875/kiwisolver-1.4.9.tar.gz", hash = "sha256:c3b22c26c6fd6811b0ae8363b95ca8ce4ea3c202d3d0975b2914310ceb1bcc4d", size = 97564, upload-time = "2025-08-10T21:27:49.279Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/c1/c2686cda909742ab66c7388e9a1a8521a59eb89f8bcfbee28fc980d07e24/kiwisolver-1.4.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5d0432ccf1c7ab14f9949eec60c5d1f924f17c037e9f8b33352fa05799359b8", size = 123681, upload-time = "2025-08-10T21:26:26.725Z" }, + { url = "https://files.pythonhosted.org/packages/ca/f0/f44f50c9f5b1a1860261092e3bc91ecdc9acda848a8b8c6abfda4a24dd5c/kiwisolver-1.4.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efb3a45b35622bb6c16dbfab491a8f5a391fe0e9d45ef32f4df85658232ca0e2", size = 66464, upload-time = "2025-08-10T21:26:27.733Z" }, + { url = "https://files.pythonhosted.org/packages/2d/7a/9d90a151f558e29c3936b8a47ac770235f436f2120aca41a6d5f3d62ae8d/kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1a12cf6398e8a0a001a059747a1cbf24705e18fe413bc22de7b3d15c67cffe3f", size = 64961, upload-time = "2025-08-10T21:26:28.729Z" }, + { url = "https://files.pythonhosted.org/packages/e9/e9/f218a2cb3a9ffbe324ca29a9e399fa2d2866d7f348ec3a88df87fc248fc5/kiwisolver-1.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b67e6efbf68e077dd71d1a6b37e43e1a99d0bff1a3d51867d45ee8908b931098", size = 1474607, upload-time = "2025-08-10T21:26:29.798Z" }, + { url = "https://files.pythonhosted.org/packages/d9/28/aac26d4c882f14de59041636292bc838db8961373825df23b8eeb807e198/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5656aa670507437af0207645273ccdfee4f14bacd7f7c67a4306d0dcaeaf6eed", size = 1276546, upload-time = "2025-08-10T21:26:31.401Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ad/8bfc1c93d4cc565e5069162f610ba2f48ff39b7de4b5b8d93f69f30c4bed/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bfc08add558155345129c7803b3671cf195e6a56e7a12f3dde7c57d9b417f525", size = 1294482, upload-time = "2025-08-10T21:26:32.721Z" }, + { url = "https://files.pythonhosted.org/packages/da/f1/6aca55ff798901d8ce403206d00e033191f63d82dd708a186e0ed2067e9c/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:40092754720b174e6ccf9e845d0d8c7d8e12c3d71e7fc35f55f3813e96376f78", size = 1343720, upload-time = "2025-08-10T21:26:34.032Z" }, + { url = "https://files.pythonhosted.org/packages/d1/91/eed031876c595c81d90d0f6fc681ece250e14bf6998c3d7c419466b523b7/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:497d05f29a1300d14e02e6441cf0f5ee81c1ff5a304b0d9fb77423974684e08b", size = 2224907, upload-time = "2025-08-10T21:26:35.824Z" }, + { url = "https://files.pythonhosted.org/packages/e9/ec/4d1925f2e49617b9cca9c34bfa11adefad49d00db038e692a559454dfb2e/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:bdd1a81a1860476eb41ac4bc1e07b3f07259e6d55bbf739b79c8aaedcf512799", size = 2321334, upload-time = "2025-08-10T21:26:37.534Z" }, + { url = "https://files.pythonhosted.org/packages/43/cb/450cd4499356f68802750c6ddc18647b8ea01ffa28f50d20598e0befe6e9/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e6b93f13371d341afee3be9f7c5964e3fe61d5fa30f6a30eb49856935dfe4fc3", size = 2488313, upload-time = "2025-08-10T21:26:39.191Z" }, + { url = "https://files.pythonhosted.org/packages/71/67/fc76242bd99f885651128a5d4fa6083e5524694b7c88b489b1b55fdc491d/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d75aa530ccfaa593da12834b86a0724f58bff12706659baa9227c2ccaa06264c", size = 2291970, upload-time = "2025-08-10T21:26:40.828Z" }, + { url = "https://files.pythonhosted.org/packages/75/bd/f1a5d894000941739f2ae1b65a32892349423ad49c2e6d0771d0bad3fae4/kiwisolver-1.4.9-cp313-cp313-win_amd64.whl", hash = "sha256:dd0a578400839256df88c16abddf9ba14813ec5f21362e1fe65022e00c883d4d", size = 73894, upload-time = "2025-08-10T21:26:42.33Z" }, + { url = "https://files.pythonhosted.org/packages/95/38/dce480814d25b99a391abbddadc78f7c117c6da34be68ca8b02d5848b424/kiwisolver-1.4.9-cp313-cp313-win_arm64.whl", hash = "sha256:d4188e73af84ca82468f09cadc5ac4db578109e52acb4518d8154698d3a87ca2", size = 64995, upload-time = "2025-08-10T21:26:43.889Z" }, + { url = "https://files.pythonhosted.org/packages/e2/37/7d218ce5d92dadc5ebdd9070d903e0c7cf7edfe03f179433ac4d13ce659c/kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:5a0f2724dfd4e3b3ac5a82436a8e6fd16baa7d507117e4279b660fe8ca38a3a1", size = 126510, upload-time = "2025-08-10T21:26:44.915Z" }, + { url = "https://files.pythonhosted.org/packages/23/b0/e85a2b48233daef4b648fb657ebbb6f8367696a2d9548a00b4ee0eb67803/kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1b11d6a633e4ed84fc0ddafd4ebfd8ea49b3f25082c04ad12b8315c11d504dc1", size = 67903, upload-time = "2025-08-10T21:26:45.934Z" }, + { url = "https://files.pythonhosted.org/packages/44/98/f2425bc0113ad7de24da6bb4dae1343476e95e1d738be7c04d31a5d037fd/kiwisolver-1.4.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61874cdb0a36016354853593cffc38e56fc9ca5aa97d2c05d3dcf6922cd55a11", size = 66402, upload-time = "2025-08-10T21:26:47.101Z" }, + { url = "https://files.pythonhosted.org/packages/98/d8/594657886df9f34c4177cc353cc28ca7e6e5eb562d37ccc233bff43bbe2a/kiwisolver-1.4.9-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:60c439763a969a6af93b4881db0eed8fadf93ee98e18cbc35bc8da868d0c4f0c", size = 1582135, upload-time = "2025-08-10T21:26:48.665Z" }, + { url = "https://files.pythonhosted.org/packages/5c/c6/38a115b7170f8b306fc929e166340c24958347308ea3012c2b44e7e295db/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92a2f997387a1b79a75e7803aa7ded2cfbe2823852ccf1ba3bcf613b62ae3197", size = 1389409, upload-time = "2025-08-10T21:26:50.335Z" }, + { url = "https://files.pythonhosted.org/packages/bf/3b/e04883dace81f24a568bcee6eb3001da4ba05114afa622ec9b6fafdc1f5e/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a31d512c812daea6d8b3be3b2bfcbeb091dbb09177706569bcfc6240dcf8b41c", size = 1401763, upload-time = "2025-08-10T21:26:51.867Z" }, + { url = "https://files.pythonhosted.org/packages/9f/80/20ace48e33408947af49d7d15c341eaee69e4e0304aab4b7660e234d6288/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:52a15b0f35dad39862d376df10c5230155243a2c1a436e39eb55623ccbd68185", size = 1453643, upload-time = "2025-08-10T21:26:53.592Z" }, + { url = "https://files.pythonhosted.org/packages/64/31/6ce4380a4cd1f515bdda976a1e90e547ccd47b67a1546d63884463c92ca9/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a30fd6fdef1430fd9e1ba7b3398b5ee4e2887783917a687d86ba69985fb08748", size = 2330818, upload-time = "2025-08-10T21:26:55.051Z" }, + { url = "https://files.pythonhosted.org/packages/fa/e9/3f3fcba3bcc7432c795b82646306e822f3fd74df0ee81f0fa067a1f95668/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cc9617b46837c6468197b5945e196ee9ca43057bb7d9d1ae688101e4e1dddf64", size = 2419963, upload-time = "2025-08-10T21:26:56.421Z" }, + { url = "https://files.pythonhosted.org/packages/99/43/7320c50e4133575c66e9f7dadead35ab22d7c012a3b09bb35647792b2a6d/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:0ab74e19f6a2b027ea4f845a78827969af45ce790e6cb3e1ebab71bdf9f215ff", size = 2594639, upload-time = "2025-08-10T21:26:57.882Z" }, + { url = "https://files.pythonhosted.org/packages/65/d6/17ae4a270d4a987ef8a385b906d2bdfc9fce502d6dc0d3aea865b47f548c/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dba5ee5d3981160c28d5490f0d1b7ed730c22470ff7f6cc26cfcfaacb9896a07", size = 2391741, upload-time = "2025-08-10T21:26:59.237Z" }, + { url = "https://files.pythonhosted.org/packages/2a/8f/8f6f491d595a9e5912971f3f863d81baddccc8a4d0c3749d6a0dd9ffc9df/kiwisolver-1.4.9-cp313-cp313t-win_arm64.whl", hash = "sha256:0749fd8f4218ad2e851e11cc4dc05c7cbc0cbc4267bdfdb31782e65aace4ee9c", size = 68646, upload-time = "2025-08-10T21:27:00.52Z" }, + { url = "https://files.pythonhosted.org/packages/6b/32/6cc0fbc9c54d06c2969faa9c1d29f5751a2e51809dd55c69055e62d9b426/kiwisolver-1.4.9-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:9928fe1eb816d11ae170885a74d074f57af3a0d65777ca47e9aeb854a1fba386", size = 123806, upload-time = "2025-08-10T21:27:01.537Z" }, + { url = "https://files.pythonhosted.org/packages/b2/dd/2bfb1d4a4823d92e8cbb420fe024b8d2167f72079b3bb941207c42570bdf/kiwisolver-1.4.9-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d0005b053977e7b43388ddec89fa567f43d4f6d5c2c0affe57de5ebf290dc552", size = 66605, upload-time = "2025-08-10T21:27:03.335Z" }, + { url = "https://files.pythonhosted.org/packages/f7/69/00aafdb4e4509c2ca6064646cba9cd4b37933898f426756adb2cb92ebbed/kiwisolver-1.4.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2635d352d67458b66fd0667c14cb1d4145e9560d503219034a18a87e971ce4f3", size = 64925, upload-time = "2025-08-10T21:27:04.339Z" }, + { url = "https://files.pythonhosted.org/packages/43/dc/51acc6791aa14e5cb6d8a2e28cefb0dc2886d8862795449d021334c0df20/kiwisolver-1.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:767c23ad1c58c9e827b649a9ab7809fd5fd9db266a9cf02b0e926ddc2c680d58", size = 1472414, upload-time = "2025-08-10T21:27:05.437Z" }, + { url = "https://files.pythonhosted.org/packages/3d/bb/93fa64a81db304ac8a246f834d5094fae4b13baf53c839d6bb6e81177129/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72d0eb9fba308b8311685c2268cf7d0a0639a6cd027d8128659f72bdd8a024b4", size = 1281272, upload-time = "2025-08-10T21:27:07.063Z" }, + { url = "https://files.pythonhosted.org/packages/70/e6/6df102916960fb8d05069d4bd92d6d9a8202d5a3e2444494e7cd50f65b7a/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f68e4f3eeca8fb22cc3d731f9715a13b652795ef657a13df1ad0c7dc0e9731df", size = 1298578, upload-time = "2025-08-10T21:27:08.452Z" }, + { url = "https://files.pythonhosted.org/packages/7c/47/e142aaa612f5343736b087864dbaebc53ea8831453fb47e7521fa8658f30/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d84cd4061ae292d8ac367b2c3fa3aad11cb8625a95d135fe93f286f914f3f5a6", size = 1345607, upload-time = "2025-08-10T21:27:10.125Z" }, + { url = "https://files.pythonhosted.org/packages/54/89/d641a746194a0f4d1a3670fb900d0dbaa786fb98341056814bc3f058fa52/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a60ea74330b91bd22a29638940d115df9dc00af5035a9a2a6ad9399ffb4ceca5", size = 2230150, upload-time = "2025-08-10T21:27:11.484Z" }, + { url = "https://files.pythonhosted.org/packages/aa/6b/5ee1207198febdf16ac11f78c5ae40861b809cbe0e6d2a8d5b0b3044b199/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ce6a3a4e106cf35c2d9c4fa17c05ce0b180db622736845d4315519397a77beaf", size = 2325979, upload-time = "2025-08-10T21:27:12.917Z" }, + { url = "https://files.pythonhosted.org/packages/fc/ff/b269eefd90f4ae14dcc74973d5a0f6d28d3b9bb1afd8c0340513afe6b39a/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:77937e5e2a38a7b48eef0585114fe7930346993a88060d0bf886086d2aa49ef5", size = 2491456, upload-time = "2025-08-10T21:27:14.353Z" }, + { url = "https://files.pythonhosted.org/packages/fc/d4/10303190bd4d30de547534601e259a4fbf014eed94aae3e5521129215086/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:24c175051354f4a28c5d6a31c93906dc653e2bf234e8a4bbfb964892078898ce", size = 2294621, upload-time = "2025-08-10T21:27:15.808Z" }, + { url = "https://files.pythonhosted.org/packages/28/e0/a9a90416fce5c0be25742729c2ea52105d62eda6c4be4d803c2a7be1fa50/kiwisolver-1.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:0763515d4df10edf6d06a3c19734e2566368980d21ebec439f33f9eb936c07b7", size = 75417, upload-time = "2025-08-10T21:27:17.436Z" }, + { url = "https://files.pythonhosted.org/packages/1f/10/6949958215b7a9a264299a7db195564e87900f709db9245e4ebdd3c70779/kiwisolver-1.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:0e4e2bf29574a6a7b7f6cb5fa69293b9f96c928949ac4a53ba3f525dffb87f9c", size = 66582, upload-time = "2025-08-10T21:27:18.436Z" }, + { url = "https://files.pythonhosted.org/packages/ec/79/60e53067903d3bc5469b369fe0dfc6b3482e2133e85dae9daa9527535991/kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d976bbb382b202f71c67f77b0ac11244021cfa3f7dfd9e562eefcea2df711548", size = 126514, upload-time = "2025-08-10T21:27:19.465Z" }, + { url = "https://files.pythonhosted.org/packages/25/d1/4843d3e8d46b072c12a38c97c57fab4608d36e13fe47d47ee96b4d61ba6f/kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2489e4e5d7ef9a1c300a5e0196e43d9c739f066ef23270607d45aba368b91f2d", size = 67905, upload-time = "2025-08-10T21:27:20.51Z" }, + { url = "https://files.pythonhosted.org/packages/8c/ae/29ffcbd239aea8b93108de1278271ae764dfc0d803a5693914975f200596/kiwisolver-1.4.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e2ea9f7ab7fbf18fffb1b5434ce7c69a07582f7acc7717720f1d69f3e806f90c", size = 66399, upload-time = "2025-08-10T21:27:21.496Z" }, + { url = "https://files.pythonhosted.org/packages/a1/ae/d7ba902aa604152c2ceba5d352d7b62106bedbccc8e95c3934d94472bfa3/kiwisolver-1.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b34e51affded8faee0dfdb705416153819d8ea9250bbbf7ea1b249bdeb5f1122", size = 1582197, upload-time = "2025-08-10T21:27:22.604Z" }, + { url = "https://files.pythonhosted.org/packages/f2/41/27c70d427eddb8bc7e4f16420a20fefc6f480312122a59a959fdfe0445ad/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8aacd3d4b33b772542b2e01beb50187536967b514b00003bdda7589722d2a64", size = 1390125, upload-time = "2025-08-10T21:27:24.036Z" }, + { url = "https://files.pythonhosted.org/packages/41/42/b3799a12bafc76d962ad69083f8b43b12bf4fe78b097b12e105d75c9b8f1/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7cf974dd4e35fa315563ac99d6287a1024e4dc2077b8a7d7cd3d2fb65d283134", size = 1402612, upload-time = "2025-08-10T21:27:25.773Z" }, + { url = "https://files.pythonhosted.org/packages/d2/b5/a210ea073ea1cfaca1bb5c55a62307d8252f531beb364e18aa1e0888b5a0/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:85bd218b5ecfbee8c8a82e121802dcb519a86044c9c3b2e4aef02fa05c6da370", size = 1453990, upload-time = "2025-08-10T21:27:27.089Z" }, + { url = "https://files.pythonhosted.org/packages/5f/ce/a829eb8c033e977d7ea03ed32fb3c1781b4fa0433fbadfff29e39c676f32/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0856e241c2d3df4efef7c04a1e46b1936b6120c9bcf36dd216e3acd84bc4fb21", size = 2331601, upload-time = "2025-08-10T21:27:29.343Z" }, + { url = "https://files.pythonhosted.org/packages/e0/4b/b5e97eb142eb9cd0072dacfcdcd31b1c66dc7352b0f7c7255d339c0edf00/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9af39d6551f97d31a4deebeac6f45b156f9755ddc59c07b402c148f5dbb6482a", size = 2422041, upload-time = "2025-08-10T21:27:30.754Z" }, + { url = "https://files.pythonhosted.org/packages/40/be/8eb4cd53e1b85ba4edc3a9321666f12b83113a178845593307a3e7891f44/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:bb4ae2b57fc1d8cbd1cf7b1d9913803681ffa903e7488012be5b76dedf49297f", size = 2594897, upload-time = "2025-08-10T21:27:32.803Z" }, + { url = "https://files.pythonhosted.org/packages/99/dd/841e9a66c4715477ea0abc78da039832fbb09dac5c35c58dc4c41a407b8a/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:aedff62918805fb62d43a4aa2ecd4482c380dc76cd31bd7c8878588a61bd0369", size = 2391835, upload-time = "2025-08-10T21:27:34.23Z" }, + { url = "https://files.pythonhosted.org/packages/0c/28/4b2e5c47a0da96896fdfdb006340ade064afa1e63675d01ea5ac222b6d52/kiwisolver-1.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:1fa333e8b2ce4d9660f2cda9c0e1b6bafcfb2457a9d259faa82289e73ec24891", size = 79988, upload-time = "2025-08-10T21:27:35.587Z" }, + { url = "https://files.pythonhosted.org/packages/80/be/3578e8afd18c88cdf9cb4cffde75a96d2be38c5a903f1ed0ceec061bd09e/kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32", size = 70260, upload-time = "2025-08-10T21:27:36.606Z" }, +] + +[[package]] +name = "matplotlib" +version = "3.10.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "contourpy" }, + { name = "cycler" }, + { name = "fonttools" }, + { name = "kiwisolver" }, + { name = "numpy" }, + { name = "packaging" }, + { name = "pillow" }, + { name = "pyparsing" }, + { name = "python-dateutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8a/76/d3c6e3a13fe484ebe7718d14e269c9569c4eb0020a968a327acb3b9a8fe6/matplotlib-3.10.8.tar.gz", hash = "sha256:2299372c19d56bcd35cf05a2738308758d32b9eaed2371898d8f5bd33f084aa3", size = 34806269, upload-time = "2025-12-10T22:56:51.155Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/b9/15fd5541ef4f5b9a17eefd379356cf12175fe577424e7b1d80676516031a/matplotlib-3.10.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3f2e409836d7f5ac2f1c013110a4d50b9f7edc26328c108915f9075d7d7a91b6", size = 8261076, upload-time = "2025-12-10T22:55:44.648Z" }, + { url = "https://files.pythonhosted.org/packages/8d/a0/2ba3473c1b66b9c74dc7107c67e9008cb1782edbe896d4c899d39ae9cf78/matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56271f3dac49a88d7fca5060f004d9d22b865f743a12a23b1e937a0be4818ee1", size = 8148794, upload-time = "2025-12-10T22:55:46.252Z" }, + { url = "https://files.pythonhosted.org/packages/75/97/a471f1c3eb1fd6f6c24a31a5858f443891d5127e63a7788678d14e249aea/matplotlib-3.10.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a0a7f52498f72f13d4a25ea70f35f4cb60642b466cbb0a9be951b5bc3f45a486", size = 8718474, upload-time = "2025-12-10T22:55:47.864Z" }, + { url = "https://files.pythonhosted.org/packages/01/be/cd478f4b66f48256f42927d0acbcd63a26a893136456cd079c0cc24fbabf/matplotlib-3.10.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:646d95230efb9ca614a7a594d4fcacde0ac61d25e37dd51710b36477594963ce", size = 9549637, upload-time = "2025-12-10T22:55:50.048Z" }, + { url = "https://files.pythonhosted.org/packages/5d/7c/8dc289776eae5109e268c4fb92baf870678dc048a25d4ac903683b86d5bf/matplotlib-3.10.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f89c151aab2e2e23cb3fe0acad1e8b82841fd265379c4cecd0f3fcb34c15e0f6", size = 9613678, upload-time = "2025-12-10T22:55:52.21Z" }, + { url = "https://files.pythonhosted.org/packages/64/40/37612487cc8a437d4dd261b32ca21fe2d79510fe74af74e1f42becb1bdb8/matplotlib-3.10.8-cp313-cp313-win_amd64.whl", hash = "sha256:e8ea3e2d4066083e264e75c829078f9e149fa119d27e19acd503de65e0b13149", size = 8142686, upload-time = "2025-12-10T22:55:54.253Z" }, + { url = "https://files.pythonhosted.org/packages/66/52/8d8a8730e968185514680c2a6625943f70269509c3dcfc0dcf7d75928cb8/matplotlib-3.10.8-cp313-cp313-win_arm64.whl", hash = "sha256:c108a1d6fa78a50646029cb6d49808ff0fc1330fda87fa6f6250c6b5369b6645", size = 8012917, upload-time = "2025-12-10T22:55:56.268Z" }, + { url = "https://files.pythonhosted.org/packages/b5/27/51fe26e1062f298af5ef66343d8ef460e090a27fea73036c76c35821df04/matplotlib-3.10.8-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ad3d9833a64cf48cc4300f2b406c3d0f4f4724a91c0bd5640678a6ba7c102077", size = 8305679, upload-time = "2025-12-10T22:55:57.856Z" }, + { url = "https://files.pythonhosted.org/packages/2c/1e/4de865bc591ac8e3062e835f42dd7fe7a93168d519557837f0e37513f629/matplotlib-3.10.8-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:eb3823f11823deade26ce3b9f40dcb4a213da7a670013929f31d5f5ed1055b22", size = 8198336, upload-time = "2025-12-10T22:55:59.371Z" }, + { url = "https://files.pythonhosted.org/packages/c6/cb/2f7b6e75fb4dce87ef91f60cac4f6e34f4c145ab036a22318ec837971300/matplotlib-3.10.8-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d9050fee89a89ed57b4fb2c1bfac9a3d0c57a0d55aed95949eedbc42070fea39", size = 8731653, upload-time = "2025-12-10T22:56:01.032Z" }, + { url = "https://files.pythonhosted.org/packages/46/b3/bd9c57d6ba670a37ab31fb87ec3e8691b947134b201f881665b28cc039ff/matplotlib-3.10.8-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b44d07310e404ba95f8c25aa5536f154c0a8ec473303535949e52eb71d0a1565", size = 9561356, upload-time = "2025-12-10T22:56:02.95Z" }, + { url = "https://files.pythonhosted.org/packages/c0/3d/8b94a481456dfc9dfe6e39e93b5ab376e50998cddfd23f4ae3b431708f16/matplotlib-3.10.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0a33deb84c15ede243aead39f77e990469fff93ad1521163305095b77b72ce4a", size = 9614000, upload-time = "2025-12-10T22:56:05.411Z" }, + { url = "https://files.pythonhosted.org/packages/bd/cd/bc06149fe5585ba800b189a6a654a75f1f127e8aab02fd2be10df7fa500c/matplotlib-3.10.8-cp313-cp313t-win_amd64.whl", hash = "sha256:3a48a78d2786784cc2413e57397981fb45c79e968d99656706018d6e62e57958", size = 8220043, upload-time = "2025-12-10T22:56:07.551Z" }, + { url = "https://files.pythonhosted.org/packages/e3/de/b22cf255abec916562cc04eef457c13e58a1990048de0c0c3604d082355e/matplotlib-3.10.8-cp313-cp313t-win_arm64.whl", hash = "sha256:15d30132718972c2c074cd14638c7f4592bd98719e2308bccea40e0538bc0cb5", size = 8062075, upload-time = "2025-12-10T22:56:09.178Z" }, + { url = "https://files.pythonhosted.org/packages/3c/43/9c0ff7a2f11615e516c3b058e1e6e8f9614ddeca53faca06da267c48345d/matplotlib-3.10.8-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b53285e65d4fa4c86399979e956235deb900be5baa7fc1218ea67fbfaeaadd6f", size = 8262481, upload-time = "2025-12-10T22:56:10.885Z" }, + { url = "https://files.pythonhosted.org/packages/6f/ca/e8ae28649fcdf039fda5ef554b40a95f50592a3c47e6f7270c9561c12b07/matplotlib-3.10.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32f8dce744be5569bebe789e46727946041199030db8aeb2954d26013a0eb26b", size = 8151473, upload-time = "2025-12-10T22:56:12.377Z" }, + { url = "https://files.pythonhosted.org/packages/f1/6f/009d129ae70b75e88cbe7e503a12a4c0670e08ed748a902c2568909e9eb5/matplotlib-3.10.8-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4cf267add95b1c88300d96ca837833d4112756045364f5c734a2276038dae27d", size = 9553896, upload-time = "2025-12-10T22:56:14.432Z" }, + { url = "https://files.pythonhosted.org/packages/f5/26/4221a741eb97967bc1fd5e4c52b9aa5a91b2f4ec05b59f6def4d820f9df9/matplotlib-3.10.8-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2cf5bd12cecf46908f286d7838b2abc6c91cda506c0445b8223a7c19a00df008", size = 9824193, upload-time = "2025-12-10T22:56:16.29Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f3/3abf75f38605772cf48a9daf5821cd4f563472f38b4b828c6fba6fa6d06e/matplotlib-3.10.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:41703cc95688f2516b480f7f339d8851a6035f18e100ee6a32bc0b8536a12a9c", size = 9615444, upload-time = "2025-12-10T22:56:18.155Z" }, + { url = "https://files.pythonhosted.org/packages/93/a5/de89ac80f10b8dc615807ee1133cd99ac74082581196d4d9590bea10690d/matplotlib-3.10.8-cp314-cp314-win_amd64.whl", hash = "sha256:83d282364ea9f3e52363da262ce32a09dfe241e4080dcedda3c0db059d3c1f11", size = 8272719, upload-time = "2025-12-10T22:56:20.366Z" }, + { url = "https://files.pythonhosted.org/packages/69/ce/b006495c19ccc0a137b48083168a37bd056392dee02f87dba0472f2797fe/matplotlib-3.10.8-cp314-cp314-win_arm64.whl", hash = "sha256:2c1998e92cd5999e295a731bcb2911c75f597d937341f3030cc24ef2733d78a8", size = 8144205, upload-time = "2025-12-10T22:56:22.239Z" }, + { url = "https://files.pythonhosted.org/packages/68/d9/b31116a3a855bd313c6fcdb7226926d59b041f26061c6c5b1be66a08c826/matplotlib-3.10.8-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:b5a2b97dbdc7d4f353ebf343744f1d1f1cca8aa8bfddb4262fcf4306c3761d50", size = 8305785, upload-time = "2025-12-10T22:56:24.218Z" }, + { url = "https://files.pythonhosted.org/packages/1e/90/6effe8103f0272685767ba5f094f453784057072f49b393e3ea178fe70a5/matplotlib-3.10.8-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3f5c3e4da343bba819f0234186b9004faba952cc420fbc522dc4e103c1985908", size = 8198361, upload-time = "2025-12-10T22:56:26.787Z" }, + { url = "https://files.pythonhosted.org/packages/d7/65/a73188711bea603615fc0baecca1061429ac16940e2385433cc778a9d8e7/matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f62550b9a30afde8c1c3ae450e5eb547d579dd69b25c2fc7a1c67f934c1717a", size = 9561357, upload-time = "2025-12-10T22:56:28.953Z" }, + { url = "https://files.pythonhosted.org/packages/f4/3d/b5c5d5d5be8ce63292567f0e2c43dde9953d3ed86ac2de0a72e93c8f07a1/matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:495672de149445ec1b772ff2c9ede9b769e3cb4f0d0aa7fa730d7f59e2d4e1c1", size = 9823610, upload-time = "2025-12-10T22:56:31.455Z" }, + { url = "https://files.pythonhosted.org/packages/4d/4b/e7beb6bbd49f6bae727a12b270a2654d13c397576d25bd6786e47033300f/matplotlib-3.10.8-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:595ba4d8fe983b88f0eec8c26a241e16d6376fe1979086232f481f8f3f67494c", size = 9614011, upload-time = "2025-12-10T22:56:33.85Z" }, + { url = "https://files.pythonhosted.org/packages/7c/e6/76f2813d31f032e65f6f797e3f2f6e4aab95b65015924b1c51370395c28a/matplotlib-3.10.8-cp314-cp314t-win_amd64.whl", hash = "sha256:25d380fe8b1dc32cf8f0b1b448470a77afb195438bafdf1d858bfb876f3edf7b", size = 8362801, upload-time = "2025-12-10T22:56:36.107Z" }, + { url = "https://files.pythonhosted.org/packages/5d/49/d651878698a0b67f23aa28e17f45a6d6dd3d3f933fa29087fa4ce5947b5a/matplotlib-3.10.8-cp314-cp314t-win_arm64.whl", hash = "sha256:113bb52413ea508ce954a02c10ffd0d565f9c3bc7f2eddc27dfe1731e71c7b5f", size = 8192560, upload-time = "2025-12-10T22:56:38.008Z" }, +] + +[[package]] +name = "numpy" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a4/7a/6a3d14e205d292b738db449d0de649b373a59edb0d0b4493821d0a3e8718/numpy-2.4.0.tar.gz", hash = "sha256:6e504f7b16118198f138ef31ba24d985b124c2c469fe8467007cf30fd992f934", size = 20685720, upload-time = "2025-12-20T16:18:19.023Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/0d/853fd96372eda07c824d24adf02e8bc92bb3731b43a9b2a39161c3667cc4/numpy-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a152d86a3ae00ba5f47b3acf3b827509fd0b6cb7d3259665e63dafbad22a75ea", size = 16649088, upload-time = "2025-12-20T16:16:31.421Z" }, + { url = "https://files.pythonhosted.org/packages/e3/37/cc636f1f2a9f585434e20a3e6e63422f70bfe4f7f6698e941db52ea1ac9a/numpy-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:39b19251dec4de8ff8496cd0806cbe27bf0684f765abb1f4809554de93785f2d", size = 12364065, upload-time = "2025-12-20T16:16:33.491Z" }, + { url = "https://files.pythonhosted.org/packages/ed/69/0b78f37ca3690969beee54103ce5f6021709134e8020767e93ba691a72f1/numpy-2.4.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:009bd0ea12d3c784b6639a8457537016ce5172109e585338e11334f6a7bb88ee", size = 5192640, upload-time = "2025-12-20T16:16:35.636Z" }, + { url = "https://files.pythonhosted.org/packages/1d/2a/08569f8252abf590294dbb09a430543ec8f8cc710383abfb3e75cc73aeda/numpy-2.4.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:5fe44e277225fd3dff6882d86d3d447205d43532c3627313d17e754fb3905a0e", size = 6541556, upload-time = "2025-12-20T16:16:37.276Z" }, + { url = "https://files.pythonhosted.org/packages/93/e9/a949885a4e177493d61519377952186b6cbfdf1d6002764c664ba28349b5/numpy-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f935c4493eda9069851058fa0d9e39dbf6286be690066509305e52912714dbb2", size = 14396562, upload-time = "2025-12-20T16:16:38.953Z" }, + { url = "https://files.pythonhosted.org/packages/99/98/9d4ad53b0e9ef901c2ef1d550d2136f5ac42d3fd2988390a6def32e23e48/numpy-2.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8cfa5f29a695cb7438965e6c3e8d06e0416060cf0d709c1b1c1653a939bf5c2a", size = 16351719, upload-time = "2025-12-20T16:16:41.503Z" }, + { url = "https://files.pythonhosted.org/packages/28/de/5f3711a38341d6e8dd619f6353251a0cdd07f3d6d101a8fd46f4ef87f895/numpy-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ba0cb30acd3ef11c94dc27fbfba68940652492bc107075e7ffe23057f9425681", size = 16176053, upload-time = "2025-12-20T16:16:44.552Z" }, + { url = "https://files.pythonhosted.org/packages/2a/5b/2a3753dc43916501b4183532e7ace862e13211042bceafa253afb5c71272/numpy-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:60e8c196cd82cbbd4f130b5290007e13e6de3eca79f0d4d38014769d96a7c475", size = 18277859, upload-time = "2025-12-20T16:16:47.174Z" }, + { url = "https://files.pythonhosted.org/packages/2c/c5/a18bcdd07a941db3076ef489d036ab16d2bfc2eae0cf27e5a26e29189434/numpy-2.4.0-cp313-cp313-win32.whl", hash = "sha256:5f48cb3e88fbc294dc90e215d86fbaf1c852c63dbdb6c3a3e63f45c4b57f7344", size = 5953849, upload-time = "2025-12-20T16:16:49.554Z" }, + { url = "https://files.pythonhosted.org/packages/4f/f1/719010ff8061da6e8a26e1980cf090412d4f5f8060b31f0c45d77dd67a01/numpy-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:a899699294f28f7be8992853c0c60741f16ff199205e2e6cdca155762cbaa59d", size = 12302840, upload-time = "2025-12-20T16:16:51.227Z" }, + { url = "https://files.pythonhosted.org/packages/f5/5a/b3d259083ed8b4d335270c76966cb6cf14a5d1b69e1a608994ac57a659e6/numpy-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:9198f447e1dc5647d07c9a6bbe2063cc0132728cc7175b39dbc796da5b54920d", size = 10308509, upload-time = "2025-12-20T16:16:53.313Z" }, + { url = "https://files.pythonhosted.org/packages/31/01/95edcffd1bb6c0633df4e808130545c4f07383ab629ac7e316fb44fff677/numpy-2.4.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74623f2ab5cc3f7c886add4f735d1031a1d2be4a4ae63c0546cfd74e7a31ddf6", size = 12491815, upload-time = "2025-12-20T16:16:55.496Z" }, + { url = "https://files.pythonhosted.org/packages/59/ea/5644b8baa92cc1c7163b4b4458c8679852733fa74ca49c942cfa82ded4e0/numpy-2.4.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:0804a8e4ab070d1d35496e65ffd3cf8114c136a2b81f61dfab0de4b218aacfd5", size = 5320321, upload-time = "2025-12-20T16:16:57.468Z" }, + { url = "https://files.pythonhosted.org/packages/26/4e/e10938106d70bc21319bd6a86ae726da37edc802ce35a3a71ecdf1fdfe7f/numpy-2.4.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:02a2038eb27f9443a8b266a66911e926566b5a6ffd1a689b588f7f35b81e7dc3", size = 6641635, upload-time = "2025-12-20T16:16:59.379Z" }, + { url = "https://files.pythonhosted.org/packages/b3/8d/a8828e3eaf5c0b4ab116924df82f24ce3416fa38d0674d8f708ddc6c8aac/numpy-2.4.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1889b3a3f47a7b5bee16bc25a2145bd7cb91897f815ce3499db64c7458b6d91d", size = 14456053, upload-time = "2025-12-20T16:17:01.768Z" }, + { url = "https://files.pythonhosted.org/packages/68/a1/17d97609d87d4520aa5ae2dcfb32305654550ac6a35effb946d303e594ce/numpy-2.4.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85eef4cb5625c47ee6425c58a3502555e10f45ee973da878ac8248ad58c136f3", size = 16401702, upload-time = "2025-12-20T16:17:04.235Z" }, + { url = "https://files.pythonhosted.org/packages/18/32/0f13c1b2d22bea1118356b8b963195446f3af124ed7a5adfa8fdecb1b6ca/numpy-2.4.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6dc8b7e2f4eb184b37655195f421836cfae6f58197b67e3ffc501f1333d993fa", size = 16242493, upload-time = "2025-12-20T16:17:06.856Z" }, + { url = "https://files.pythonhosted.org/packages/ae/23/48f21e3d309fbc137c068a1475358cbd3a901b3987dcfc97a029ab3068e2/numpy-2.4.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:44aba2f0cafd287871a495fb3163408b0bd25bbce135c6f621534a07f4f7875c", size = 18324222, upload-time = "2025-12-20T16:17:09.392Z" }, + { url = "https://files.pythonhosted.org/packages/ac/52/41f3d71296a3dcaa4f456aaa3c6fc8e745b43d0552b6bde56571bb4b4a0f/numpy-2.4.0-cp313-cp313t-win32.whl", hash = "sha256:20c115517513831860c573996e395707aa9fb691eb179200125c250e895fcd93", size = 6076216, upload-time = "2025-12-20T16:17:11.437Z" }, + { url = "https://files.pythonhosted.org/packages/35/ff/46fbfe60ab0710d2a2b16995f708750307d30eccbb4c38371ea9e986866e/numpy-2.4.0-cp313-cp313t-win_amd64.whl", hash = "sha256:b48e35f4ab6f6a7597c46e301126ceba4c44cd3280e3750f85db48b082624fa4", size = 12444263, upload-time = "2025-12-20T16:17:13.182Z" }, + { url = "https://files.pythonhosted.org/packages/a3/e3/9189ab319c01d2ed556c932ccf55064c5d75bb5850d1df7a482ce0badead/numpy-2.4.0-cp313-cp313t-win_arm64.whl", hash = "sha256:4d1cfce39e511069b11e67cd0bd78ceff31443b7c9e5c04db73c7a19f572967c", size = 10378265, upload-time = "2025-12-20T16:17:15.211Z" }, + { url = "https://files.pythonhosted.org/packages/ab/ed/52eac27de39d5e5a6c9aadabe672bc06f55e24a3d9010cd1183948055d76/numpy-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:c95eb6db2884917d86cde0b4d4cf31adf485c8ec36bf8696dd66fa70de96f36b", size = 16647476, upload-time = "2025-12-20T16:17:17.671Z" }, + { url = "https://files.pythonhosted.org/packages/77/c0/990ce1b7fcd4e09aeaa574e2a0a839589e4b08b2ca68070f1acb1fea6736/numpy-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:65167da969cd1ec3a1df31cb221ca3a19a8aaa25370ecb17d428415e93c1935e", size = 12374563, upload-time = "2025-12-20T16:17:20.216Z" }, + { url = "https://files.pythonhosted.org/packages/37/7c/8c5e389c6ae8f5fd2277a988600d79e9625db3fff011a2d87ac80b881a4c/numpy-2.4.0-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:3de19cfecd1465d0dcf8a5b5ea8b3155b42ed0b639dba4b71e323d74f2a3be5e", size = 5203107, upload-time = "2025-12-20T16:17:22.47Z" }, + { url = "https://files.pythonhosted.org/packages/e6/94/ca5b3bd6a8a70a5eec9a0b8dd7f980c1eff4b8a54970a9a7fef248ef564f/numpy-2.4.0-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:6c05483c3136ac4c91b4e81903cb53a8707d316f488124d0398499a4f8e8ef51", size = 6538067, upload-time = "2025-12-20T16:17:24.001Z" }, + { url = "https://files.pythonhosted.org/packages/79/43/993eb7bb5be6761dde2b3a3a594d689cec83398e3f58f4758010f3b85727/numpy-2.4.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36667db4d6c1cea79c8930ab72fadfb4060feb4bfe724141cd4bd064d2e5f8ce", size = 14411926, upload-time = "2025-12-20T16:17:25.822Z" }, + { url = "https://files.pythonhosted.org/packages/03/75/d4c43b61de473912496317a854dac54f1efec3eeb158438da6884b70bb90/numpy-2.4.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9a818668b674047fd88c4cddada7ab8f1c298812783e8328e956b78dc4807f9f", size = 16354295, upload-time = "2025-12-20T16:17:28.308Z" }, + { url = "https://files.pythonhosted.org/packages/b8/0a/b54615b47ee8736a6461a4bb6749128dd3435c5a759d5663f11f0e9af4ac/numpy-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1ee32359fb7543b7b7bd0b2f46294db27e29e7bbdf70541e81b190836cd83ded", size = 16190242, upload-time = "2025-12-20T16:17:30.993Z" }, + { url = "https://files.pythonhosted.org/packages/98/ce/ea207769aacad6246525ec6c6bbd66a2bf56c72443dc10e2f90feed29290/numpy-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e493962256a38f58283de033d8af176c5c91c084ea30f15834f7545451c42059", size = 18280875, upload-time = "2025-12-20T16:17:33.327Z" }, + { url = "https://files.pythonhosted.org/packages/17/ef/ec409437aa962ea372ed601c519a2b141701683ff028f894b7466f0ab42b/numpy-2.4.0-cp314-cp314-win32.whl", hash = "sha256:6bbaebf0d11567fa8926215ae731e1d58e6ec28a8a25235b8a47405d301332db", size = 6002530, upload-time = "2025-12-20T16:17:35.729Z" }, + { url = "https://files.pythonhosted.org/packages/5f/4a/5cb94c787a3ed1ac65e1271b968686521169a7b3ec0b6544bb3ca32960b0/numpy-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:3d857f55e7fdf7c38ab96c4558c95b97d1c685be6b05c249f5fdafcbd6f9899e", size = 12435890, upload-time = "2025-12-20T16:17:37.599Z" }, + { url = "https://files.pythonhosted.org/packages/48/a0/04b89db963af9de1104975e2544f30de89adbf75b9e75f7dd2599be12c79/numpy-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:bb50ce5fb202a26fd5404620e7ef820ad1ab3558b444cb0b55beb7ef66cd2d63", size = 10591892, upload-time = "2025-12-20T16:17:39.649Z" }, + { url = "https://files.pythonhosted.org/packages/53/e5/d74b5ccf6712c06c7a545025a6a71bfa03bdc7e0568b405b0d655232fd92/numpy-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:355354388cba60f2132df297e2d53053d4063f79077b67b481d21276d61fc4df", size = 12494312, upload-time = "2025-12-20T16:17:41.714Z" }, + { url = "https://files.pythonhosted.org/packages/c2/08/3ca9cc2ddf54dfee7ae9a6479c071092a228c68aef08252aa08dac2af002/numpy-2.4.0-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:1d8f9fde5f6dc1b6fc34df8162f3b3079365468703fee7f31d4e0cc8c63baed9", size = 5322862, upload-time = "2025-12-20T16:17:44.145Z" }, + { url = "https://files.pythonhosted.org/packages/87/74/0bb63a68394c0c1e52670cfff2e309afa41edbe11b3327d9af29e4383f34/numpy-2.4.0-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:e0434aa22c821f44eeb4c650b81c7fbdd8c0122c6c4b5a576a76d5a35625ecd9", size = 6644986, upload-time = "2025-12-20T16:17:46.203Z" }, + { url = "https://files.pythonhosted.org/packages/06/8f/9264d9bdbcf8236af2823623fe2f3981d740fc3461e2787e231d97c38c28/numpy-2.4.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:40483b2f2d3ba7aad426443767ff5632ec3156ef09742b96913787d13c336471", size = 14457958, upload-time = "2025-12-20T16:17:48.017Z" }, + { url = "https://files.pythonhosted.org/packages/8c/d9/f9a69ae564bbc7236a35aa883319364ef5fd41f72aa320cc1cbe66148fe2/numpy-2.4.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6a7664ddd9746e20b7325351fe1a8408d0a2bf9c63b5e898290ddc8f09544", size = 16398394, upload-time = "2025-12-20T16:17:50.409Z" }, + { url = "https://files.pythonhosted.org/packages/34/c7/39241501408dde7f885d241a98caba5421061a2c6d2b2197ac5e3aa842d8/numpy-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ecb0019d44f4cdb50b676c5d0cb4b1eae8e15d1ed3d3e6639f986fc92b2ec52c", size = 16241044, upload-time = "2025-12-20T16:17:52.661Z" }, + { url = "https://files.pythonhosted.org/packages/7c/95/cae7effd90e065a95e59fe710eeee05d7328ed169776dfdd9f789e032125/numpy-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d0ffd9e2e4441c96a9c91ec1783285d80bf835b677853fc2770a89d50c1e48ac", size = 18321772, upload-time = "2025-12-20T16:17:54.947Z" }, + { url = "https://files.pythonhosted.org/packages/96/df/3c6c279accd2bfb968a76298e5b276310bd55d243df4fa8ac5816d79347d/numpy-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:77f0d13fa87036d7553bf81f0e1fe3ce68d14c9976c9851744e4d3e91127e95f", size = 6148320, upload-time = "2025-12-20T16:17:57.249Z" }, + { url = "https://files.pythonhosted.org/packages/92/8d/f23033cce252e7a75cae853d17f582e86534c46404dea1c8ee094a9d6d84/numpy-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b1f5b45829ac1848893f0ddf5cb326110604d6df96cdc255b0bf9edd154104d4", size = 12623460, upload-time = "2025-12-20T16:17:58.963Z" }, + { url = "https://files.pythonhosted.org/packages/a4/4f/1f8475907d1a7c4ef9020edf7f39ea2422ec896849245f00688e4b268a71/numpy-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:23a3e9d1a6f360267e8fbb38ba5db355a6a7e9be71d7fce7ab3125e88bb646c8", size = 10661799, upload-time = "2025-12-20T16:18:01.078Z" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + +[[package]] +name = "pandas" +version = "2.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, + { name = "python-dateutil" }, + { name = "pytz" }, + { name = "tzdata" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/33/01/d40b85317f86cf08d853a4f495195c73815fdf205eef3993821720274518/pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b", size = 4495223, upload-time = "2025-09-29T23:34:51.853Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cd/4b/18b035ee18f97c1040d94debd8f2e737000ad70ccc8f5513f4eefad75f4b/pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713", size = 11544671, upload-time = "2025-09-29T23:21:05.024Z" }, + { url = "https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8", size = 10680807, upload-time = "2025-09-29T23:21:15.979Z" }, + { url = "https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d", size = 11709872, upload-time = "2025-09-29T23:21:27.165Z" }, + { url = "https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac", size = 12306371, upload-time = "2025-09-29T23:21:40.532Z" }, + { url = "https://files.pythonhosted.org/packages/33/81/a3afc88fca4aa925804a27d2676d22dcd2031c2ebe08aabd0ae55b9ff282/pandas-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c", size = 12765333, upload-time = "2025-09-29T23:21:55.77Z" }, + { url = "https://files.pythonhosted.org/packages/8d/0f/b4d4ae743a83742f1153464cf1a8ecfafc3ac59722a0b5c8602310cb7158/pandas-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493", size = 13418120, upload-time = "2025-09-29T23:22:10.109Z" }, + { url = "https://files.pythonhosted.org/packages/4f/c7/e54682c96a895d0c808453269e0b5928a07a127a15704fedb643e9b0a4c8/pandas-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee", size = 10993991, upload-time = "2025-09-29T23:25:04.889Z" }, + { url = "https://files.pythonhosted.org/packages/f9/ca/3f8d4f49740799189e1395812f3bf23b5e8fc7c190827d55a610da72ce55/pandas-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5", size = 12048227, upload-time = "2025-09-29T23:22:24.343Z" }, + { url = "https://files.pythonhosted.org/packages/0e/5a/f43efec3e8c0cc92c4663ccad372dbdff72b60bdb56b2749f04aa1d07d7e/pandas-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21", size = 11411056, upload-time = "2025-09-29T23:22:37.762Z" }, + { url = "https://files.pythonhosted.org/packages/46/b1/85331edfc591208c9d1a63a06baa67b21d332e63b7a591a5ba42a10bb507/pandas-2.3.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78", size = 11645189, upload-time = "2025-09-29T23:22:51.688Z" }, + { url = "https://files.pythonhosted.org/packages/44/23/78d645adc35d94d1ac4f2a3c4112ab6f5b8999f4898b8cdf01252f8df4a9/pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110", size = 12121912, upload-time = "2025-09-29T23:23:05.042Z" }, + { url = "https://files.pythonhosted.org/packages/53/da/d10013df5e6aaef6b425aa0c32e1fc1f3e431e4bcabd420517dceadce354/pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86", size = 12712160, upload-time = "2025-09-29T23:23:28.57Z" }, + { url = "https://files.pythonhosted.org/packages/bd/17/e756653095a083d8a37cbd816cb87148debcfcd920129b25f99dd8d04271/pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc", size = 13199233, upload-time = "2025-09-29T23:24:24.876Z" }, + { url = "https://files.pythonhosted.org/packages/04/fd/74903979833db8390b73b3a8a7d30d146d710bd32703724dd9083950386f/pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0", size = 11540635, upload-time = "2025-09-29T23:25:52.486Z" }, + { url = "https://files.pythonhosted.org/packages/21/00/266d6b357ad5e6d3ad55093a7e8efc7dd245f5a842b584db9f30b0f0a287/pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593", size = 10759079, upload-time = "2025-09-29T23:26:33.204Z" }, + { url = "https://files.pythonhosted.org/packages/ca/05/d01ef80a7a3a12b2f8bbf16daba1e17c98a2f039cbc8e2f77a2c5a63d382/pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c", size = 11814049, upload-time = "2025-09-29T23:27:15.384Z" }, + { url = "https://files.pythonhosted.org/packages/15/b2/0e62f78c0c5ba7e3d2c5945a82456f4fac76c480940f805e0b97fcbc2f65/pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b", size = 12332638, upload-time = "2025-09-29T23:27:51.625Z" }, + { url = "https://files.pythonhosted.org/packages/c5/33/dd70400631b62b9b29c3c93d2feee1d0964dc2bae2e5ad7a6c73a7f25325/pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6", size = 12886834, upload-time = "2025-09-29T23:28:21.289Z" }, + { url = "https://files.pythonhosted.org/packages/d3/18/b5d48f55821228d0d2692b34fd5034bb185e854bdb592e9c640f6290e012/pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3", size = 13409925, upload-time = "2025-09-29T23:28:58.261Z" }, + { url = "https://files.pythonhosted.org/packages/a6/3d/124ac75fcd0ecc09b8fdccb0246ef65e35b012030defb0e0eba2cbbbe948/pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5", size = 11109071, upload-time = "2025-09-29T23:32:27.484Z" }, + { url = "https://files.pythonhosted.org/packages/89/9c/0e21c895c38a157e0faa1fb64587a9226d6dd46452cac4532d80c3c4a244/pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec", size = 12048504, upload-time = "2025-09-29T23:29:31.47Z" }, + { url = "https://files.pythonhosted.org/packages/d7/82/b69a1c95df796858777b68fbe6a81d37443a33319761d7c652ce77797475/pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7", size = 11410702, upload-time = "2025-09-29T23:29:54.591Z" }, + { url = "https://files.pythonhosted.org/packages/f9/88/702bde3ba0a94b8c73a0181e05144b10f13f29ebfc2150c3a79062a8195d/pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450", size = 11634535, upload-time = "2025-09-29T23:30:21.003Z" }, + { url = "https://files.pythonhosted.org/packages/a4/1e/1bac1a839d12e6a82ec6cb40cda2edde64a2013a66963293696bbf31fbbb/pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5", size = 12121582, upload-time = "2025-09-29T23:30:43.391Z" }, + { url = "https://files.pythonhosted.org/packages/44/91/483de934193e12a3b1d6ae7c8645d083ff88dec75f46e827562f1e4b4da6/pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788", size = 12699963, upload-time = "2025-09-29T23:31:10.009Z" }, + { url = "https://files.pythonhosted.org/packages/70/44/5191d2e4026f86a2a109053e194d3ba7a31a2d10a9c2348368c63ed4e85a/pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87", size = 13202175, upload-time = "2025-09-29T23:31:59.173Z" }, +] + +[[package]] +name = "pillow" +version = "12.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/02/d52c733a2452ef1ffcc123b68e6606d07276b0e358db70eabad7e40042b7/pillow-12.1.0.tar.gz", hash = "sha256:5c5ae0a06e9ea030ab786b0251b32c7e4ce10e58d983c0d5c56029455180b5b9", size = 46977283, upload-time = "2026-01-02T09:13:29.892Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dd/c7/2530a4aa28248623e9d7f27316b42e27c32ec410f695929696f2e0e4a778/pillow-12.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:7b5dd7cbae20285cdb597b10eb5a2c13aa9de6cde9bb64a3c1317427b1db1ae1", size = 4062543, upload-time = "2026-01-02T09:11:31.566Z" }, + { url = "https://files.pythonhosted.org/packages/8f/1f/40b8eae823dc1519b87d53c30ed9ef085506b05281d313031755c1705f73/pillow-12.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:29a4cef9cb672363926f0470afc516dbf7305a14d8c54f7abbb5c199cd8f8179", size = 4138373, upload-time = "2026-01-02T09:11:33.367Z" }, + { url = "https://files.pythonhosted.org/packages/d4/77/6fa60634cf06e52139fd0e89e5bbf055e8166c691c42fb162818b7fda31d/pillow-12.1.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:681088909d7e8fa9e31b9799aaa59ba5234c58e5e4f1951b4c4d1082a2e980e0", size = 3601241, upload-time = "2026-01-02T09:11:35.011Z" }, + { url = "https://files.pythonhosted.org/packages/4f/bf/28ab865de622e14b747f0cd7877510848252d950e43002e224fb1c9ababf/pillow-12.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:983976c2ab753166dc66d36af6e8ec15bb511e4a25856e2227e5f7e00a160587", size = 5262410, upload-time = "2026-01-02T09:11:36.682Z" }, + { url = "https://files.pythonhosted.org/packages/1c/34/583420a1b55e715937a85bd48c5c0991598247a1fd2eb5423188e765ea02/pillow-12.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:db44d5c160a90df2d24a24760bbd37607d53da0b34fb546c4c232af7192298ac", size = 4657312, upload-time = "2026-01-02T09:11:38.535Z" }, + { url = "https://files.pythonhosted.org/packages/1d/fd/f5a0896839762885b3376ff04878f86ab2b097c2f9a9cdccf4eda8ba8dc0/pillow-12.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6b7a9d1db5dad90e2991645874f708e87d9a3c370c243c2d7684d28f7e133e6b", size = 6232605, upload-time = "2026-01-02T09:11:40.602Z" }, + { url = "https://files.pythonhosted.org/packages/98/aa/938a09d127ac1e70e6ed467bd03834350b33ef646b31edb7452d5de43792/pillow-12.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6258f3260986990ba2fa8a874f8b6e808cf5abb51a94015ca3dc3c68aa4f30ea", size = 8041617, upload-time = "2026-01-02T09:11:42.721Z" }, + { url = "https://files.pythonhosted.org/packages/17/e8/538b24cb426ac0186e03f80f78bc8dc7246c667f58b540bdd57c71c9f79d/pillow-12.1.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e115c15e3bc727b1ca3e641a909f77f8ca72a64fff150f666fcc85e57701c26c", size = 6346509, upload-time = "2026-01-02T09:11:44.955Z" }, + { url = "https://files.pythonhosted.org/packages/01/9a/632e58ec89a32738cabfd9ec418f0e9898a2b4719afc581f07c04a05e3c9/pillow-12.1.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6741e6f3074a35e47c77b23a4e4f2d90db3ed905cb1c5e6e0d49bff2045632bc", size = 7038117, upload-time = "2026-01-02T09:11:46.736Z" }, + { url = "https://files.pythonhosted.org/packages/c7/a2/d40308cf86eada842ca1f3ffa45d0ca0df7e4ab33c83f81e73f5eaed136d/pillow-12.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:935b9d1aed48fcfb3f838caac506f38e29621b44ccc4f8a64d575cb1b2a88644", size = 6460151, upload-time = "2026-01-02T09:11:48.625Z" }, + { url = "https://files.pythonhosted.org/packages/f1/88/f5b058ad6453a085c5266660a1417bdad590199da1b32fb4efcff9d33b05/pillow-12.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5fee4c04aad8932da9f8f710af2c1a15a83582cfb884152a9caa79d4efcdbf9c", size = 7164534, upload-time = "2026-01-02T09:11:50.445Z" }, + { url = "https://files.pythonhosted.org/packages/19/ce/c17334caea1db789163b5d855a5735e47995b0b5dc8745e9a3605d5f24c0/pillow-12.1.0-cp313-cp313-win32.whl", hash = "sha256:a786bf667724d84aa29b5db1c61b7bfdde380202aaca12c3461afd6b71743171", size = 6332551, upload-time = "2026-01-02T09:11:52.234Z" }, + { url = "https://files.pythonhosted.org/packages/e5/07/74a9d941fa45c90a0d9465098fe1ec85de3e2afbdc15cc4766622d516056/pillow-12.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:461f9dfdafa394c59cd6d818bdfdbab4028b83b02caadaff0ffd433faf4c9a7a", size = 7040087, upload-time = "2026-01-02T09:11:54.822Z" }, + { url = "https://files.pythonhosted.org/packages/88/09/c99950c075a0e9053d8e880595926302575bc742b1b47fe1bbcc8d388d50/pillow-12.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:9212d6b86917a2300669511ed094a9406888362e085f2431a7da985a6b124f45", size = 2452470, upload-time = "2026-01-02T09:11:56.522Z" }, + { url = "https://files.pythonhosted.org/packages/b5/ba/970b7d85ba01f348dee4d65412476321d40ee04dcb51cd3735b9dc94eb58/pillow-12.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:00162e9ca6d22b7c3ee8e61faa3c3253cd19b6a37f126cad04f2f88b306f557d", size = 5264816, upload-time = "2026-01-02T09:11:58.227Z" }, + { url = "https://files.pythonhosted.org/packages/10/60/650f2fb55fdba7a510d836202aa52f0baac633e50ab1cf18415d332188fb/pillow-12.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:7d6daa89a00b58c37cb1747ec9fb7ac3bc5ffd5949f5888657dfddde6d1312e0", size = 4660472, upload-time = "2026-01-02T09:12:00.798Z" }, + { url = "https://files.pythonhosted.org/packages/2b/c0/5273a99478956a099d533c4f46cbaa19fd69d606624f4334b85e50987a08/pillow-12.1.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e2479c7f02f9d505682dc47df8c0ea1fc5e264c4d1629a5d63fe3e2334b89554", size = 6268974, upload-time = "2026-01-02T09:12:02.572Z" }, + { url = "https://files.pythonhosted.org/packages/b4/26/0bf714bc2e73d5267887d47931d53c4ceeceea6978148ed2ab2a4e6463c4/pillow-12.1.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f188d580bd870cda1e15183790d1cc2fa78f666e76077d103edf048eed9c356e", size = 8073070, upload-time = "2026-01-02T09:12:04.75Z" }, + { url = "https://files.pythonhosted.org/packages/43/cf/1ea826200de111a9d65724c54f927f3111dc5ae297f294b370a670c17786/pillow-12.1.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0fde7ec5538ab5095cc02df38ee99b0443ff0e1c847a045554cf5f9af1f4aa82", size = 6380176, upload-time = "2026-01-02T09:12:06.626Z" }, + { url = "https://files.pythonhosted.org/packages/03/e0/7938dd2b2013373fd85d96e0f38d62b7a5a262af21ac274250c7ca7847c9/pillow-12.1.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ed07dca4a8464bada6139ab38f5382f83e5f111698caf3191cb8dbf27d908b4", size = 7067061, upload-time = "2026-01-02T09:12:08.624Z" }, + { url = "https://files.pythonhosted.org/packages/86/ad/a2aa97d37272a929a98437a8c0ac37b3cf012f4f8721e1bd5154699b2518/pillow-12.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f45bd71d1fa5e5749587613037b172e0b3b23159d1c00ef2fc920da6f470e6f0", size = 6491824, upload-time = "2026-01-02T09:12:10.488Z" }, + { url = "https://files.pythonhosted.org/packages/a4/44/80e46611b288d51b115826f136fb3465653c28f491068a72d3da49b54cd4/pillow-12.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:277518bf4fe74aa91489e1b20577473b19ee70fb97c374aa50830b279f25841b", size = 7190911, upload-time = "2026-01-02T09:12:12.772Z" }, + { url = "https://files.pythonhosted.org/packages/86/77/eacc62356b4cf81abe99ff9dbc7402750044aed02cfd6a503f7c6fc11f3e/pillow-12.1.0-cp313-cp313t-win32.whl", hash = "sha256:7315f9137087c4e0ee73a761b163fc9aa3b19f5f606a7fc08d83fd3e4379af65", size = 6336445, upload-time = "2026-01-02T09:12:14.775Z" }, + { url = "https://files.pythonhosted.org/packages/e7/3c/57d81d0b74d218706dafccb87a87ea44262c43eef98eb3b164fd000e0491/pillow-12.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:0ddedfaa8b5f0b4ffbc2fa87b556dc59f6bb4ecb14a53b33f9189713ae8053c0", size = 7045354, upload-time = "2026-01-02T09:12:16.599Z" }, + { url = "https://files.pythonhosted.org/packages/ac/82/8b9b97bba2e3576a340f93b044a3a3a09841170ab4c1eb0d5c93469fd32f/pillow-12.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:80941e6d573197a0c28f394753de529bb436b1ca990ed6e765cf42426abc39f8", size = 2454547, upload-time = "2026-01-02T09:12:18.704Z" }, + { url = "https://files.pythonhosted.org/packages/8c/87/bdf971d8bbcf80a348cc3bacfcb239f5882100fe80534b0ce67a784181d8/pillow-12.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:5cb7bc1966d031aec37ddb9dcf15c2da5b2e9f7cc3ca7c54473a20a927e1eb91", size = 4062533, upload-time = "2026-01-02T09:12:20.791Z" }, + { url = "https://files.pythonhosted.org/packages/ff/4f/5eb37a681c68d605eb7034c004875c81f86ec9ef51f5be4a63eadd58859a/pillow-12.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:97e9993d5ed946aba26baf9c1e8cf18adbab584b99f452ee72f7ee8acb882796", size = 4138546, upload-time = "2026-01-02T09:12:23.664Z" }, + { url = "https://files.pythonhosted.org/packages/11/6d/19a95acb2edbace40dcd582d077b991646b7083c41b98da4ed7555b59733/pillow-12.1.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:414b9a78e14ffeb98128863314e62c3f24b8a86081066625700b7985b3f529bd", size = 3601163, upload-time = "2026-01-02T09:12:26.338Z" }, + { url = "https://files.pythonhosted.org/packages/fc/36/2b8138e51cb42e4cc39c3297713455548be855a50558c3ac2beebdc251dd/pillow-12.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e6bdb408f7c9dd2a5ff2b14a3b0bb6d4deb29fb9961e6eb3ae2031ae9a5cec13", size = 5266086, upload-time = "2026-01-02T09:12:28.782Z" }, + { url = "https://files.pythonhosted.org/packages/53/4b/649056e4d22e1caa90816bf99cef0884aed607ed38075bd75f091a607a38/pillow-12.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3413c2ae377550f5487991d444428f1a8ae92784aac79caa8b1e3b89b175f77e", size = 4657344, upload-time = "2026-01-02T09:12:31.117Z" }, + { url = "https://files.pythonhosted.org/packages/6c/6b/c5742cea0f1ade0cd61485dc3d81f05261fc2276f537fbdc00802de56779/pillow-12.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e5dcbe95016e88437ecf33544ba5db21ef1b8dd6e1b434a2cb2a3d605299e643", size = 6232114, upload-time = "2026-01-02T09:12:32.936Z" }, + { url = "https://files.pythonhosted.org/packages/bf/8f/9f521268ce22d63991601aafd3d48d5ff7280a246a1ef62d626d67b44064/pillow-12.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d0a7735df32ccbcc98b98a1ac785cc4b19b580be1bdf0aeb5c03223220ea09d5", size = 8042708, upload-time = "2026-01-02T09:12:34.78Z" }, + { url = "https://files.pythonhosted.org/packages/1a/eb/257f38542893f021502a1bbe0c2e883c90b5cff26cc33b1584a841a06d30/pillow-12.1.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c27407a2d1b96774cbc4a7594129cc027339fd800cd081e44497722ea1179de", size = 6347762, upload-time = "2026-01-02T09:12:36.748Z" }, + { url = "https://files.pythonhosted.org/packages/c4/5a/8ba375025701c09b309e8d5163c5a4ce0102fa86bbf8800eb0d7ac87bc51/pillow-12.1.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15c794d74303828eaa957ff8070846d0efe8c630901a1c753fdc63850e19ecd9", size = 7039265, upload-time = "2026-01-02T09:12:39.082Z" }, + { url = "https://files.pythonhosted.org/packages/cf/dc/cf5e4cdb3db533f539e88a7bbf9f190c64ab8a08a9bc7a4ccf55067872e4/pillow-12.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c990547452ee2800d8506c4150280757f88532f3de2a58e3022e9b179107862a", size = 6462341, upload-time = "2026-01-02T09:12:40.946Z" }, + { url = "https://files.pythonhosted.org/packages/d0/47/0291a25ac9550677e22eda48510cfc4fa4b2ef0396448b7fbdc0a6946309/pillow-12.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b63e13dd27da389ed9475b3d28510f0f954bca0041e8e551b2a4eb1eab56a39a", size = 7165395, upload-time = "2026-01-02T09:12:42.706Z" }, + { url = "https://files.pythonhosted.org/packages/4f/4c/e005a59393ec4d9416be06e6b45820403bb946a778e39ecec62f5b2b991e/pillow-12.1.0-cp314-cp314-win32.whl", hash = "sha256:1a949604f73eb07a8adab38c4fe50791f9919344398bdc8ac6b307f755fc7030", size = 6431413, upload-time = "2026-01-02T09:12:44.944Z" }, + { url = "https://files.pythonhosted.org/packages/1c/af/f23697f587ac5f9095d67e31b81c95c0249cd461a9798a061ed6709b09b5/pillow-12.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:4f9f6a650743f0ddee5593ac9e954ba1bdbc5e150bc066586d4f26127853ab94", size = 7176779, upload-time = "2026-01-02T09:12:46.727Z" }, + { url = "https://files.pythonhosted.org/packages/b3/36/6a51abf8599232f3e9afbd16d52829376a68909fe14efe29084445db4b73/pillow-12.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:808b99604f7873c800c4840f55ff389936ef1948e4e87645eaf3fccbc8477ac4", size = 2543105, upload-time = "2026-01-02T09:12:49.243Z" }, + { url = "https://files.pythonhosted.org/packages/82/54/2e1dd20c8749ff225080d6ba465a0cab4387f5db0d1c5fb1439e2d99923f/pillow-12.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:bc11908616c8a283cf7d664f77411a5ed2a02009b0097ff8abbba5e79128ccf2", size = 5268571, upload-time = "2026-01-02T09:12:51.11Z" }, + { url = "https://files.pythonhosted.org/packages/57/61/571163a5ef86ec0cf30d265ac2a70ae6fc9e28413d1dc94fa37fae6bda89/pillow-12.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:896866d2d436563fa2a43a9d72f417874f16b5545955c54a64941e87c1376c61", size = 4660426, upload-time = "2026-01-02T09:12:52.865Z" }, + { url = "https://files.pythonhosted.org/packages/5e/e1/53ee5163f794aef1bf84243f755ee6897a92c708505350dd1923f4afec48/pillow-12.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8e178e3e99d3c0ea8fc64b88447f7cac8ccf058af422a6cedc690d0eadd98c51", size = 6269908, upload-time = "2026-01-02T09:12:54.884Z" }, + { url = "https://files.pythonhosted.org/packages/bc/0b/b4b4106ff0ee1afa1dc599fde6ab230417f800279745124f6c50bcffed8e/pillow-12.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:079af2fb0c599c2ec144ba2c02766d1b55498e373b3ac64687e43849fbbef5bc", size = 8074733, upload-time = "2026-01-02T09:12:56.802Z" }, + { url = "https://files.pythonhosted.org/packages/19/9f/80b411cbac4a732439e629a26ad3ef11907a8c7fc5377b7602f04f6fe4e7/pillow-12.1.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bdec5e43377761c5dbca620efb69a77f6855c5a379e32ac5b158f54c84212b14", size = 6381431, upload-time = "2026-01-02T09:12:58.823Z" }, + { url = "https://files.pythonhosted.org/packages/8f/b7/d65c45db463b66ecb6abc17c6ba6917a911202a07662247e1355ce1789e7/pillow-12.1.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:565c986f4b45c020f5421a4cea13ef294dde9509a8577f29b2fc5edc7587fff8", size = 7068529, upload-time = "2026-01-02T09:13:00.885Z" }, + { url = "https://files.pythonhosted.org/packages/50/96/dfd4cd726b4a45ae6e3c669fc9e49deb2241312605d33aba50499e9d9bd1/pillow-12.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:43aca0a55ce1eefc0aefa6253661cb54571857b1a7b2964bd8a1e3ef4b729924", size = 6492981, upload-time = "2026-01-02T09:13:03.314Z" }, + { url = "https://files.pythonhosted.org/packages/4d/1c/b5dc52cf713ae46033359c5ca920444f18a6359ce1020dd3e9c553ea5bc6/pillow-12.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0deedf2ea233722476b3a81e8cdfbad786f7adbed5d848469fa59fe52396e4ef", size = 7191878, upload-time = "2026-01-02T09:13:05.276Z" }, + { url = "https://files.pythonhosted.org/packages/53/26/c4188248bd5edaf543864fe4834aebe9c9cb4968b6f573ce014cc42d0720/pillow-12.1.0-cp314-cp314t-win32.whl", hash = "sha256:b17fbdbe01c196e7e159aacb889e091f28e61020a8abeac07b68079b6e626988", size = 6438703, upload-time = "2026-01-02T09:13:07.491Z" }, + { url = "https://files.pythonhosted.org/packages/b8/0e/69ed296de8ea05cb03ee139cee600f424ca166e632567b2d66727f08c7ed/pillow-12.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27b9baecb428899db6c0de572d6d305cfaf38ca1596b5c0542a5182e3e74e8c6", size = 7182927, upload-time = "2026-01-02T09:13:09.841Z" }, + { url = "https://files.pythonhosted.org/packages/fc/f5/68334c015eed9b5cff77814258717dec591ded209ab5b6fb70e2ae873d1d/pillow-12.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:f61333d817698bdcdd0f9d7793e365ac3d2a21c1f1eb02b32ad6aefb8d8ea831", size = 2545104, upload-time = "2026-01-02T09:13:12.068Z" }, +] + +[[package]] +name = "polars" +version = "1.36.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "polars-runtime-32" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/dc/56f2a90c79a2cb13f9e956eab6385effe54216ae7a2068b3a6406bae4345/polars-1.36.1.tar.gz", hash = "sha256:12c7616a2305559144711ab73eaa18814f7aa898c522e7645014b68f1432d54c", size = 711993, upload-time = "2025-12-10T01:14:53.033Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f6/c6/36a1b874036b49893ecae0ac44a2f63d1a76e6212631a5b2f50a86e0e8af/polars-1.36.1-py3-none-any.whl", hash = "sha256:853c1bbb237add6a5f6d133c15094a9b727d66dd6a4eb91dbb07cdb056b2b8ef", size = 802429, upload-time = "2025-12-10T01:13:53.838Z" }, +] + +[[package]] +name = "polars-runtime-32" +version = "1.36.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/31/df/597c0ef5eb8d761a16d72327846599b57c5d40d7f9e74306fc154aba8c37/polars_runtime_32-1.36.1.tar.gz", hash = "sha256:201c2cfd80ceb5d5cd7b63085b5fd08d6ae6554f922bcb941035e39638528a09", size = 2788751, upload-time = "2025-12-10T01:14:54.172Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/ea/871129a2d296966c0925b078a9a93c6c5e7facb1c5eebfcd3d5811aeddc1/polars_runtime_32-1.36.1-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:327b621ca82594f277751f7e23d4b939ebd1be18d54b4cdf7a2f8406cecc18b2", size = 43494311, upload-time = "2025-12-10T01:13:56.096Z" }, + { url = "https://files.pythonhosted.org/packages/d8/76/0038210ad1e526ce5bb2933b13760d6b986b3045eccc1338e661bd656f77/polars_runtime_32-1.36.1-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ab0d1f23084afee2b97de8c37aa3e02ec3569749ae39571bd89e7a8b11ae9e83", size = 39300602, upload-time = "2025-12-10T01:13:59.366Z" }, + { url = "https://files.pythonhosted.org/packages/54/1e/2707bee75a780a953a77a2c59829ee90ef55708f02fc4add761c579bf76e/polars_runtime_32-1.36.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:899b9ad2e47ceb31eb157f27a09dbc2047efbf4969a923a6b1ba7f0412c3e64c", size = 44511780, upload-time = "2025-12-10T01:14:02.285Z" }, + { url = "https://files.pythonhosted.org/packages/11/b2/3fede95feee441be64b4bcb32444679a8fbb7a453a10251583053f6efe52/polars_runtime_32-1.36.1-cp39-abi3-manylinux_2_24_aarch64.whl", hash = "sha256:d9d077bb9df711bc635a86540df48242bb91975b353e53ef261c6fae6cb0948f", size = 40688448, upload-time = "2025-12-10T01:14:05.131Z" }, + { url = "https://files.pythonhosted.org/packages/05/0f/e629713a72999939b7b4bfdbf030a32794db588b04fdf3dc977dd8ea6c53/polars_runtime_32-1.36.1-cp39-abi3-win_amd64.whl", hash = "sha256:cc17101f28c9a169ff8b5b8d4977a3683cd403621841623825525f440b564cf0", size = 44464898, upload-time = "2025-12-10T01:14:08.296Z" }, + { url = "https://files.pythonhosted.org/packages/d1/d8/a12e6aa14f63784cead437083319ec7cece0d5bb9a5bfe7678cc6578b52a/polars_runtime_32-1.36.1-cp39-abi3-win_arm64.whl", hash = "sha256:809e73857be71250141225ddd5d2b30c97e6340aeaa0d445f930e01bef6888dc", size = 39798896, upload-time = "2025-12-10T01:14:11.568Z" }, +] + +[[package]] +name = "pyarrow" +version = "22.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/53/04a7fdc63e6056116c9ddc8b43bc28c12cdd181b85cbeadb79278475f3ae/pyarrow-22.0.0.tar.gz", hash = "sha256:3d600dc583260d845c7d8a6db540339dd883081925da2bd1c5cb808f720b3cd9", size = 1151151, upload-time = "2025-10-24T12:30:00.762Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a6/d6/d0fac16a2963002fc22c8fa75180a838737203d558f0ed3b564c4a54eef5/pyarrow-22.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:e6e95176209257803a8b3d0394f21604e796dadb643d2f7ca21b66c9c0b30c9a", size = 34204629, upload-time = "2025-10-24T10:06:20.274Z" }, + { url = "https://files.pythonhosted.org/packages/c6/9c/1d6357347fbae062ad3f17082f9ebc29cc733321e892c0d2085f42a2212b/pyarrow-22.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:001ea83a58024818826a9e3f89bf9310a114f7e26dfe404a4c32686f97bd7901", size = 35985783, upload-time = "2025-10-24T10:06:27.301Z" }, + { url = "https://files.pythonhosted.org/packages/ff/c0/782344c2ce58afbea010150df07e3a2f5fdad299cd631697ae7bd3bac6e3/pyarrow-22.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:ce20fe000754f477c8a9125543f1936ea5b8867c5406757c224d745ed033e691", size = 45020999, upload-time = "2025-10-24T10:06:35.387Z" }, + { url = "https://files.pythonhosted.org/packages/1b/8b/5362443737a5307a7b67c1017c42cd104213189b4970bf607e05faf9c525/pyarrow-22.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e0a15757fccb38c410947df156f9749ae4a3c89b2393741a50521f39a8cf202a", size = 47724601, upload-time = "2025-10-24T10:06:43.551Z" }, + { url = "https://files.pythonhosted.org/packages/69/4d/76e567a4fc2e190ee6072967cb4672b7d9249ac59ae65af2d7e3047afa3b/pyarrow-22.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cedb9dd9358e4ea1d9bce3665ce0797f6adf97ff142c8e25b46ba9cdd508e9b6", size = 48001050, upload-time = "2025-10-24T10:06:52.284Z" }, + { url = "https://files.pythonhosted.org/packages/01/5e/5653f0535d2a1aef8223cee9d92944cb6bccfee5cf1cd3f462d7cb022790/pyarrow-22.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:252be4a05f9d9185bb8c18e83764ebcfea7185076c07a7a662253af3a8c07941", size = 50307877, upload-time = "2025-10-24T10:07:02.405Z" }, + { url = "https://files.pythonhosted.org/packages/2d/f8/1d0bd75bf9328a3b826e24a16e5517cd7f9fbf8d34a3184a4566ef5a7f29/pyarrow-22.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:a4893d31e5ef780b6edcaf63122df0f8d321088bb0dee4c8c06eccb1ca28d145", size = 27977099, upload-time = "2025-10-24T10:08:07.259Z" }, + { url = "https://files.pythonhosted.org/packages/90/81/db56870c997805bf2b0f6eeeb2d68458bf4654652dccdcf1bf7a42d80903/pyarrow-22.0.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:f7fe3dbe871294ba70d789be16b6e7e52b418311e166e0e3cba9522f0f437fb1", size = 34336685, upload-time = "2025-10-24T10:07:11.47Z" }, + { url = "https://files.pythonhosted.org/packages/1c/98/0727947f199aba8a120f47dfc229eeb05df15bcd7a6f1b669e9f882afc58/pyarrow-22.0.0-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:ba95112d15fd4f1105fb2402c4eab9068f0554435e9b7085924bcfaac2cc306f", size = 36032158, upload-time = "2025-10-24T10:07:18.626Z" }, + { url = "https://files.pythonhosted.org/packages/96/b4/9babdef9c01720a0785945c7cf550e4acd0ebcd7bdd2e6f0aa7981fa85e2/pyarrow-22.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:c064e28361c05d72eed8e744c9605cbd6d2bb7481a511c74071fd9b24bc65d7d", size = 44892060, upload-time = "2025-10-24T10:07:26.002Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ca/2f8804edd6279f78a37062d813de3f16f29183874447ef6d1aadbb4efa0f/pyarrow-22.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:6f9762274496c244d951c819348afbcf212714902742225f649cf02823a6a10f", size = 47504395, upload-time = "2025-10-24T10:07:34.09Z" }, + { url = "https://files.pythonhosted.org/packages/b9/f0/77aa5198fd3943682b2e4faaf179a674f0edea0d55d326d83cb2277d9363/pyarrow-22.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a9d9ffdc2ab696f6b15b4d1f7cec6658e1d788124418cb30030afbae31c64746", size = 48066216, upload-time = "2025-10-24T10:07:43.528Z" }, + { url = "https://files.pythonhosted.org/packages/79/87/a1937b6e78b2aff18b706d738c9e46ade5bfcf11b294e39c87706a0089ac/pyarrow-22.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ec1a15968a9d80da01e1d30349b2b0d7cc91e96588ee324ce1b5228175043e95", size = 50288552, upload-time = "2025-10-24T10:07:53.519Z" }, + { url = "https://files.pythonhosted.org/packages/60/ae/b5a5811e11f25788ccfdaa8f26b6791c9807119dffcf80514505527c384c/pyarrow-22.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:bba208d9c7decf9961998edf5c65e3ea4355d5818dd6cd0f6809bec1afb951cc", size = 28262504, upload-time = "2025-10-24T10:08:00.932Z" }, + { url = "https://files.pythonhosted.org/packages/bd/b0/0fa4d28a8edb42b0a7144edd20befd04173ac79819547216f8a9f36f9e50/pyarrow-22.0.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:9bddc2cade6561f6820d4cd73f99a0243532ad506bc510a75a5a65a522b2d74d", size = 34224062, upload-time = "2025-10-24T10:08:14.101Z" }, + { url = "https://files.pythonhosted.org/packages/0f/a8/7a719076b3c1be0acef56a07220c586f25cd24de0e3f3102b438d18ae5df/pyarrow-22.0.0-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:e70ff90c64419709d38c8932ea9fe1cc98415c4f87ea8da81719e43f02534bc9", size = 35990057, upload-time = "2025-10-24T10:08:21.842Z" }, + { url = "https://files.pythonhosted.org/packages/89/3c/359ed54c93b47fb6fe30ed16cdf50e3f0e8b9ccfb11b86218c3619ae50a8/pyarrow-22.0.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:92843c305330aa94a36e706c16209cd4df274693e777ca47112617db7d0ef3d7", size = 45068002, upload-time = "2025-10-24T10:08:29.034Z" }, + { url = "https://files.pythonhosted.org/packages/55/fc/4945896cc8638536ee787a3bd6ce7cec8ec9acf452d78ec39ab328efa0a1/pyarrow-22.0.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:6dda1ddac033d27421c20d7a7943eec60be44e0db4e079f33cc5af3b8280ccde", size = 47737765, upload-time = "2025-10-24T10:08:38.559Z" }, + { url = "https://files.pythonhosted.org/packages/cd/5e/7cb7edeb2abfaa1f79b5d5eb89432356155c8426f75d3753cbcb9592c0fd/pyarrow-22.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:84378110dd9a6c06323b41b56e129c504d157d1a983ce8f5443761eb5256bafc", size = 48048139, upload-time = "2025-10-24T10:08:46.784Z" }, + { url = "https://files.pythonhosted.org/packages/88/c6/546baa7c48185f5e9d6e59277c4b19f30f48c94d9dd938c2a80d4d6b067c/pyarrow-22.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:854794239111d2b88b40b6ef92aa478024d1e5074f364033e73e21e3f76b25e0", size = 50314244, upload-time = "2025-10-24T10:08:55.771Z" }, + { url = "https://files.pythonhosted.org/packages/3c/79/755ff2d145aafec8d347bf18f95e4e81c00127f06d080135dfc86aea417c/pyarrow-22.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:b883fe6fd85adad7932b3271c38ac289c65b7337c2c132e9569f9d3940620730", size = 28757501, upload-time = "2025-10-24T10:09:59.891Z" }, + { url = "https://files.pythonhosted.org/packages/0e/d2/237d75ac28ced3147912954e3c1a174df43a95f4f88e467809118a8165e0/pyarrow-22.0.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:7a820d8ae11facf32585507c11f04e3f38343c1e784c9b5a8b1da5c930547fe2", size = 34355506, upload-time = "2025-10-24T10:09:02.953Z" }, + { url = "https://files.pythonhosted.org/packages/1e/2c/733dfffe6d3069740f98e57ff81007809067d68626c5faef293434d11bd6/pyarrow-22.0.0-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:c6ec3675d98915bf1ec8b3c7986422682f7232ea76cad276f4c8abd5b7319b70", size = 36047312, upload-time = "2025-10-24T10:09:10.334Z" }, + { url = "https://files.pythonhosted.org/packages/7c/2b/29d6e3782dc1f299727462c1543af357a0f2c1d3c160ce199950d9ca51eb/pyarrow-22.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:3e739edd001b04f654b166204fc7a9de896cf6007eaff33409ee9e50ceaff754", size = 45081609, upload-time = "2025-10-24T10:09:18.61Z" }, + { url = "https://files.pythonhosted.org/packages/8d/42/aa9355ecc05997915af1b7b947a7f66c02dcaa927f3203b87871c114ba10/pyarrow-22.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:7388ac685cab5b279a41dfe0a6ccd99e4dbf322edfb63e02fc0443bf24134e91", size = 47703663, upload-time = "2025-10-24T10:09:27.369Z" }, + { url = "https://files.pythonhosted.org/packages/ee/62/45abedde480168e83a1de005b7b7043fd553321c1e8c5a9a114425f64842/pyarrow-22.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f633074f36dbc33d5c05b5dc75371e5660f1dbf9c8b1d95669def05e5425989c", size = 48066543, upload-time = "2025-10-24T10:09:34.908Z" }, + { url = "https://files.pythonhosted.org/packages/84/e9/7878940a5b072e4f3bf998770acafeae13b267f9893af5f6d4ab3904b67e/pyarrow-22.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4c19236ae2402a8663a2c8f21f1870a03cc57f0bef7e4b6eb3238cc82944de80", size = 50288838, upload-time = "2025-10-24T10:09:44.394Z" }, + { url = "https://files.pythonhosted.org/packages/7b/03/f335d6c52b4a4761bcc83499789a1e2e16d9d201a58c327a9b5cc9a41bd9/pyarrow-22.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0c34fe18094686194f204a3b1787a27456897d8a2d62caf84b61e8dfbc0252ae", size = 29185594, upload-time = "2025-10-24T10:09:53.111Z" }, +] + +[[package]] +name = "pyogrio" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "numpy" }, + { name = "packaging" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/49/d4/12f86b1ed09721363da4c09622464b604c851a9223fc0c6b393fb2012208/pyogrio-0.12.1.tar.gz", hash = "sha256:e548ab705bb3e5383693717de1e6c76da97f3762ab92522cb310f93128a75ff1", size = 303289, upload-time = "2025-11-28T19:04:53.341Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/be/56/f56e79f71b84aa9bea25fdde39fab3846841bd7926be96f623eb7253b7e1/pyogrio-0.12.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:ec0e47a5a704e575092b2fd5c83fa0472a1d421e590f94093eb837bb0a11125d", size = 23658483, upload-time = "2025-11-28T19:03:43.567Z" }, + { url = "https://files.pythonhosted.org/packages/66/ac/5559f8a35d58a16cbb2dd7602dd11936ff8796d8c9bf789f14da88764ec3/pyogrio-0.12.1-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:b4c888fc08f388be4dd99dfca5e84a5cdc5994deeec0230cc45144d3460e2b21", size = 25232737, upload-time = "2025-11-28T19:03:45.92Z" }, + { url = "https://files.pythonhosted.org/packages/59/58/925f1c129ddd7cbba8dea4e7609797cea7a76dbc863ac9afd318a679c4b9/pyogrio-0.12.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:73a88436f9962750d782853727897ac2722cac5900d920e39fab3e56d7a6a7f1", size = 31377986, upload-time = "2025-11-28T19:03:48.495Z" }, + { url = "https://files.pythonhosted.org/packages/18/5f/c87034e92847b1844d0e8492a6a8e3301147d32c5e57909397ce64dbedf5/pyogrio-0.12.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:b5d248a0d59fe9bbf9a35690b70004c67830ee0ebe7d4f7bb8ffd8659f684b3a", size = 30915791, upload-time = "2025-11-28T19:03:51.267Z" }, + { url = "https://files.pythonhosted.org/packages/46/35/b874f79d03e9f900012cf609f7fff97b77164f2e14ee5aac282f8a999c1b/pyogrio-0.12.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:0622bc1a186421547660271083079b38d42e6f868802936d8538c0b379f1ab6b", size = 32499754, upload-time = "2025-11-28T19:03:58.776Z" }, + { url = "https://files.pythonhosted.org/packages/c3/c4/705678c9c4200130290b3a104b45c0cc10aaa48fcef3b2585b34e34ab3e1/pyogrio-0.12.1-cp313-cp313-win_amd64.whl", hash = "sha256:207bd60c7ffbcea84584596e3637653aa7095e9ee20fa408f90c7f9460392613", size = 22933945, upload-time = "2025-11-28T19:04:01.551Z" }, + { url = "https://files.pythonhosted.org/packages/f9/e0/d92d4944001330bc87742d43f112d63d12fc89378b6187e62ff3fc1e8e85/pyogrio-0.12.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:1511b39a283fa27cda906cd187a791578942a87a40b6a06697d9b43bb8ac80b0", size = 23692697, upload-time = "2025-11-28T19:04:04.208Z" }, + { url = "https://files.pythonhosted.org/packages/e5/d7/40acbe06d1b1140e3bb27b79e9163776469c1dc785f1be7d9a7fc7b95c87/pyogrio-0.12.1-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:e486cd6aa9ea8a15394a5f84e019d61ec18f257eeeb642348bd68c3d1e57280b", size = 25258083, upload-time = "2025-11-28T19:04:07.121Z" }, + { url = "https://files.pythonhosted.org/packages/87/a1/39fefd9cddd95986700524f43d3093b4350f6e4fc200623c3838424a5080/pyogrio-0.12.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d3f1a19f63bfd1d3042e45f37ad1d6598123a5a604b6c4ba3f38b419273486cd", size = 31368995, upload-time = "2025-11-28T19:04:09.88Z" }, + { url = "https://files.pythonhosted.org/packages/18/d7/da88c566e67d741a03851eb8d01358949d52e0b0fc2cd953582dc6d89ff8/pyogrio-0.12.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:f3dcc59b3316b8a0f59346bcc638a4d69997864a4d21da839192f50c4c92369a", size = 31035589, upload-time = "2025-11-28T19:04:12.993Z" }, + { url = "https://files.pythonhosted.org/packages/11/ac/8f0199f0d31b8ddbc4b4ea1918df8070fdf3e0a63100b898633ec9396224/pyogrio-0.12.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:a0643e041dee3e8e038fce69f52a915ecb486e6d7b674c0f9919f3c9e9629689", size = 32487973, upload-time = "2025-11-28T19:04:16.103Z" }, + { url = "https://files.pythonhosted.org/packages/bd/64/8541a27e9635a335835d234dfaeb19d6c26097fd88224eda7791f83ca98d/pyogrio-0.12.1-cp313-cp313t-win_amd64.whl", hash = "sha256:5881017f29e110d3613819667657844d8e961b747f2d35cf92f273c27af6d068", size = 22987374, upload-time = "2025-11-28T19:04:18.91Z" }, + { url = "https://files.pythonhosted.org/packages/f4/6f/b4d5e285e08c0c60bcc23b50d73038ddc7335d8de79cc25678cd486a3db0/pyogrio-0.12.1-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:5a1b0453d1c9e7b03715dd57296c8f3790acb8b50d7e3b5844b3074a18f50709", size = 23660673, upload-time = "2025-11-28T19:04:21.662Z" }, + { url = "https://files.pythonhosted.org/packages/8d/75/4b29e71489c5551aa1a1c5ca8c5160a60203c94f2f68c87c0e3614d58965/pyogrio-0.12.1-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:e7ee560422239dd09ca7f8284cc8483a8919c30d25f3049bb0249bff4c38dec4", size = 25232194, upload-time = "2025-11-28T19:04:23.975Z" }, + { url = "https://files.pythonhosted.org/packages/89/6e/e9929d2261a07c36301983de2767bcde90d441ab5bf1d767ce56dd07f8b4/pyogrio-0.12.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:648c6f7f5f214d30e6cf493b4af1d59782907ac068af9119ca35f18153d6865a", size = 31336936, upload-time = "2025-11-28T19:04:26.594Z" }, + { url = "https://files.pythonhosted.org/packages/1d/9e/c59941d734ed936d4e5c89b4b99cb5541307cc42b3fd466ee78a1850c177/pyogrio-0.12.1-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:58042584f3fd4cabb0f55d26c1405053f656be8a5c266c38140316a1e981aca0", size = 30902210, upload-time = "2025-11-28T19:04:29.143Z" }, + { url = "https://files.pythonhosted.org/packages/d1/68/cc07320a63f9c2586e60bf11d148b00e12d0e707673bffe609bbdcb7e754/pyogrio-0.12.1-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:b438e38e4ccbaedaa5cb5824ff5de5539315d9b2fde6547c1e816576924ee8ca", size = 32461674, upload-time = "2025-11-28T19:04:31.792Z" }, + { url = "https://files.pythonhosted.org/packages/13/bc/e4522f429c45a3b6ad28185849dd76e5c8718b780883c4795e7ee41841ae/pyogrio-0.12.1-cp314-cp314-win_amd64.whl", hash = "sha256:f1d8d8a2fea3781dc2a05982c050259261ebc0f6c5e03732d6d79d582adf9363", size = 23550575, upload-time = "2025-11-28T19:04:34.556Z" }, + { url = "https://files.pythonhosted.org/packages/bd/ac/34f0664d0e391994a7b68529ae07a96432b2b4926dbac173ddc4ec94d310/pyogrio-0.12.1-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:9fe7286946f35a73e6370dc5855bc7a5e8e7babf9e4a8bad7a3279a1d94c7ea9", size = 23694285, upload-time = "2025-11-28T19:04:37.833Z" }, + { url = "https://files.pythonhosted.org/packages/8a/93/873255529faff1da09d0b27287e85ec805a318c60c0c74fd7df77f94e557/pyogrio-0.12.1-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:2c50345b382f1be801d654ec22c70ee974d6057d4ba7afe984b55f2192bc94ee", size = 25259825, upload-time = "2025-11-28T19:04:40.125Z" }, + { url = "https://files.pythonhosted.org/packages/27/95/4d4c3644695d99c6fa0b0b42f0d6266ae9dfaf64478a3371eaac950bdd02/pyogrio-0.12.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f0db95765ac0ca935c7fe579e29451294e3ab19c317b0c59c31fbe92a69155e0", size = 31371995, upload-time = "2025-11-28T19:04:42.736Z" }, + { url = "https://files.pythonhosted.org/packages/4c/6f/71f6bcca8754c8bf55a4b7153c61c91f8ac5ba992568e9fa3e54a0ee76fd/pyogrio-0.12.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:fc882779075982b93064b3bf3d8642514a6df00d9dd752493b104817072cfb01", size = 31035498, upload-time = "2025-11-28T19:04:45.79Z" }, + { url = "https://files.pythonhosted.org/packages/fd/47/75c1aa165a988347317afab9b938a01ad25dbca559b582ea34473703dc38/pyogrio-0.12.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:806f620e0c54b54dbdd65e9b6368d24f344cda84c9343364b40a57eb3e1c4dca", size = 32496390, upload-time = "2025-11-28T19:04:48.786Z" }, + { url = "https://files.pythonhosted.org/packages/31/93/4641dc5d952f6bdb71dabad2c50e3f8a5d58396cdea6ff8f8a08bfd4f4a6/pyogrio-0.12.1-cp314-cp314t-win_amd64.whl", hash = "sha256:5399f66730978d8852ef5f44dbafa0f738e7f28f4f784349f36830b69a9d2134", size = 23620996, upload-time = "2025-11-28T19:04:51.132Z" }, +] + +[[package]] +name = "pyparsing" +version = "3.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/33/c1/1d9de9aeaa1b89b0186e5fe23294ff6517fce1bc69149185577cd31016b2/pyparsing-3.3.1.tar.gz", hash = "sha256:47fad0f17ac1e2cad3de3b458570fbc9b03560aa029ed5e16ee5554da9a2251c", size = 1550512, upload-time = "2025-12-23T03:14:04.391Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl", hash = "sha256:023b5e7e5520ad96642e2c6db4cb683d3970bd640cdf7115049a6e9c3682df82", size = 121793, upload-time = "2025-12-23T03:14:02.103Z" }, +] + +[[package]] +name = "pyproj" +version = "3.7.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/90/67bd7260b4ea9b8b20b4f58afef6c223ecb3abf368eb4ec5bc2cdef81b49/pyproj-3.7.2.tar.gz", hash = "sha256:39a0cf1ecc7e282d1d30f36594ebd55c9fae1fda8a2622cee5d100430628f88c", size = 226279, upload-time = "2025-08-14T12:05:42.18Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/be/14/faf1b90d267cea68d7e70662e7f88cefdb1bc890bd596c74b959e0517a72/pyproj-3.7.2-cp313-cp313-macosx_13_0_x86_64.whl", hash = "sha256:19466e529b1b15eeefdf8ff26b06fa745856c044f2f77bf0edbae94078c1dfa1", size = 6214580, upload-time = "2025-08-14T12:04:28.804Z" }, + { url = "https://files.pythonhosted.org/packages/35/48/da9a45b184d375f62667f62eba0ca68569b0bd980a0bb7ffcc1d50440520/pyproj-3.7.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:c79b9b84c4a626c5dc324c0d666be0bfcebd99f7538d66e8898c2444221b3da7", size = 4615388, upload-time = "2025-08-14T12:04:30.553Z" }, + { url = "https://files.pythonhosted.org/packages/5e/e7/d2b459a4a64bca328b712c1b544e109df88e5c800f7c143cfbc404d39bfb/pyproj-3.7.2-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:ceecf374cacca317bc09e165db38ac548ee3cad07c3609442bd70311c59c21aa", size = 9628455, upload-time = "2025-08-14T12:04:32.435Z" }, + { url = "https://files.pythonhosted.org/packages/f8/85/c2b1706e51942de19076eff082f8495e57d5151364e78b5bef4af4a1d94a/pyproj-3.7.2-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:5141a538ffdbe4bfd157421828bb2e07123a90a7a2d6f30fa1462abcfb5ce681", size = 9514269, upload-time = "2025-08-14T12:04:34.599Z" }, + { url = "https://files.pythonhosted.org/packages/34/38/07a9b89ae7467872f9a476883a5bad9e4f4d1219d31060f0f2b282276cbe/pyproj-3.7.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f000841e98ea99acbb7b8ca168d67773b0191de95187228a16110245c5d954d5", size = 10808437, upload-time = "2025-08-14T12:04:36.485Z" }, + { url = "https://files.pythonhosted.org/packages/12/56/fda1daeabbd39dec5b07f67233d09f31facb762587b498e6fc4572be9837/pyproj-3.7.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8115faf2597f281a42ab608ceac346b4eb1383d3b45ab474fd37341c4bf82a67", size = 10745540, upload-time = "2025-08-14T12:04:38.568Z" }, + { url = "https://files.pythonhosted.org/packages/0d/90/c793182cbba65a39a11db2ac6b479fe76c59e6509ae75e5744c344a0da9d/pyproj-3.7.2-cp313-cp313-win32.whl", hash = "sha256:f18c0579dd6be00b970cb1a6719197fceecc407515bab37da0066f0184aafdf3", size = 5896506, upload-time = "2025-08-14T12:04:41.059Z" }, + { url = "https://files.pythonhosted.org/packages/be/0f/747974129cf0d800906f81cd25efd098c96509026e454d4b66868779ab04/pyproj-3.7.2-cp313-cp313-win_amd64.whl", hash = "sha256:bb41c29d5f60854b1075853fe80c58950b398d4ebb404eb532536ac8d2834ed7", size = 6310195, upload-time = "2025-08-14T12:04:42.974Z" }, + { url = "https://files.pythonhosted.org/packages/82/64/fc7598a53172c4931ec6edf5228280663063150625d3f6423b4c20f9daff/pyproj-3.7.2-cp313-cp313-win_arm64.whl", hash = "sha256:2b617d573be4118c11cd96b8891a0b7f65778fa7733ed8ecdb297a447d439100", size = 6230748, upload-time = "2025-08-14T12:04:44.491Z" }, + { url = "https://files.pythonhosted.org/packages/aa/f0/611dd5cddb0d277f94b7af12981f56e1441bf8d22695065d4f0df5218498/pyproj-3.7.2-cp313-cp313t-macosx_13_0_x86_64.whl", hash = "sha256:d27b48f0e81beeaa2b4d60c516c3a1cfbb0c7ff6ef71256d8e9c07792f735279", size = 6241729, upload-time = "2025-08-14T12:04:46.274Z" }, + { url = "https://files.pythonhosted.org/packages/15/93/40bd4a6c523ff9965e480870611aed7eda5aa2c6128c6537345a2b77b542/pyproj-3.7.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:55a3610d75023c7b1c6e583e48ef8f62918e85a2ae81300569d9f104d6684bb6", size = 4652497, upload-time = "2025-08-14T12:04:48.203Z" }, + { url = "https://files.pythonhosted.org/packages/1b/ae/7150ead53c117880b35e0d37960d3138fe640a235feb9605cb9386f50bb0/pyproj-3.7.2-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:8d7349182fa622696787cc9e195508d2a41a64765da9b8a6bee846702b9e6220", size = 9942610, upload-time = "2025-08-14T12:04:49.652Z" }, + { url = "https://files.pythonhosted.org/packages/d8/17/7a4a7eafecf2b46ab64e5c08176c20ceb5844b503eaa551bf12ccac77322/pyproj-3.7.2-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:d230b186eb876ed4f29a7c5ee310144c3a0e44e89e55f65fb3607e13f6db337c", size = 9692390, upload-time = "2025-08-14T12:04:51.731Z" }, + { url = "https://files.pythonhosted.org/packages/c3/55/ae18f040f6410f0ea547a21ada7ef3e26e6c82befa125b303b02759c0e9d/pyproj-3.7.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:237499c7862c578d0369e2b8ac56eec550e391a025ff70e2af8417139dabb41c", size = 11047596, upload-time = "2025-08-14T12:04:53.748Z" }, + { url = "https://files.pythonhosted.org/packages/e6/2e/d3fff4d2909473f26ae799f9dda04caa322c417a51ff3b25763f7d03b233/pyproj-3.7.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8c225f5978abd506fd9a78eaaf794435e823c9156091cabaab5374efb29d7f69", size = 10896975, upload-time = "2025-08-14T12:04:55.875Z" }, + { url = "https://files.pythonhosted.org/packages/f2/bc/8fc7d3963d87057b7b51ebe68c1e7c51c23129eee5072ba6b86558544a46/pyproj-3.7.2-cp313-cp313t-win32.whl", hash = "sha256:2da731876d27639ff9d2d81c151f6ab90a1546455fabd93368e753047be344a2", size = 5953057, upload-time = "2025-08-14T12:04:58.466Z" }, + { url = "https://files.pythonhosted.org/packages/cc/27/ea9809966cc47d2d51e6d5ae631ea895f7c7c7b9b3c29718f900a8f7d197/pyproj-3.7.2-cp313-cp313t-win_amd64.whl", hash = "sha256:f54d91ae18dd23b6c0ab48126d446820e725419da10617d86a1b69ada6d881d3", size = 6375414, upload-time = "2025-08-14T12:04:59.861Z" }, + { url = "https://files.pythonhosted.org/packages/5b/f8/1ef0129fba9a555c658e22af68989f35e7ba7b9136f25758809efec0cd6e/pyproj-3.7.2-cp313-cp313t-win_arm64.whl", hash = "sha256:fc52ba896cfc3214dc9f9ca3c0677a623e8fdd096b257c14a31e719d21ff3fdd", size = 6262501, upload-time = "2025-08-14T12:05:01.39Z" }, + { url = "https://files.pythonhosted.org/packages/42/17/c2b050d3f5b71b6edd0d96ae16c990fdc42a5f1366464a5c2772146de33a/pyproj-3.7.2-cp314-cp314-macosx_13_0_x86_64.whl", hash = "sha256:2aaa328605ace41db050d06bac1adc11f01b71fe95c18661497763116c3a0f02", size = 6214541, upload-time = "2025-08-14T12:05:03.166Z" }, + { url = "https://files.pythonhosted.org/packages/03/68/68ada9c8aea96ded09a66cfd9bf87aa6db8c2edebe93f5bf9b66b0143fbc/pyproj-3.7.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:35dccbce8201313c596a970fde90e33605248b66272595c061b511c8100ccc08", size = 4617456, upload-time = "2025-08-14T12:05:04.563Z" }, + { url = "https://files.pythonhosted.org/packages/81/e4/4c50ceca7d0e937977866b02cb64e6ccf4df979a5871e521f9e255df6073/pyproj-3.7.2-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:25b0b7cb0042444c29a164b993c45c1b8013d6c48baa61dc1160d834a277e83b", size = 9615590, upload-time = "2025-08-14T12:05:06.094Z" }, + { url = "https://files.pythonhosted.org/packages/05/1e/ada6fb15a1d75b5bd9b554355a69a798c55a7dcc93b8d41596265c1772e3/pyproj-3.7.2-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:85def3a6388e9ba51f964619aa002a9d2098e77c6454ff47773bb68871024281", size = 9474960, upload-time = "2025-08-14T12:05:07.973Z" }, + { url = "https://files.pythonhosted.org/packages/51/07/9d48ad0a8db36e16f842f2c8a694c1d9d7dcf9137264846bef77585a71f3/pyproj-3.7.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b1bccefec3875ab81eabf49059e2b2ea77362c178b66fd3528c3e4df242f1516", size = 10799478, upload-time = "2025-08-14T12:05:14.102Z" }, + { url = "https://files.pythonhosted.org/packages/85/cf/2f812b529079f72f51ff2d6456b7fef06c01735e5cfd62d54ffb2b548028/pyproj-3.7.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d5371ca114d6990b675247355a801925814eca53e6c4b2f1b5c0a956336ee36e", size = 10710030, upload-time = "2025-08-14T12:05:16.317Z" }, + { url = "https://files.pythonhosted.org/packages/99/9b/4626a19e1f03eba4c0e77b91a6cf0f73aa9cb5d51a22ee385c22812bcc2c/pyproj-3.7.2-cp314-cp314-win32.whl", hash = "sha256:77f066626030f41be543274f5ac79f2a511fe89860ecd0914f22131b40a0ec25", size = 5991181, upload-time = "2025-08-14T12:05:19.492Z" }, + { url = "https://files.pythonhosted.org/packages/04/b2/5a6610554306a83a563080c2cf2c57565563eadd280e15388efa00fb5b33/pyproj-3.7.2-cp314-cp314-win_amd64.whl", hash = "sha256:5a964da1696b8522806f4276ab04ccfff8f9eb95133a92a25900697609d40112", size = 6434721, upload-time = "2025-08-14T12:05:21.022Z" }, + { url = "https://files.pythonhosted.org/packages/ae/ce/6c910ea2e1c74ef673c5d48c482564b8a7824a44c4e35cca2e765b68cfcc/pyproj-3.7.2-cp314-cp314-win_arm64.whl", hash = "sha256:e258ab4dbd3cf627809067c0ba8f9884ea76c8e5999d039fb37a1619c6c3e1f6", size = 6363821, upload-time = "2025-08-14T12:05:22.627Z" }, + { url = "https://files.pythonhosted.org/packages/e4/e4/5532f6f7491812ba782a2177fe9de73fd8e2912b59f46a1d056b84b9b8f2/pyproj-3.7.2-cp314-cp314t-macosx_13_0_x86_64.whl", hash = "sha256:bbbac2f930c6d266f70ec75df35ef851d96fdb3701c674f42fd23a9314573b37", size = 6241773, upload-time = "2025-08-14T12:05:24.577Z" }, + { url = "https://files.pythonhosted.org/packages/20/1f/0938c3f2bbbef1789132d1726d9b0e662f10cfc22522743937f421ad664e/pyproj-3.7.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:b7544e0a3d6339dc9151e9c8f3ea62a936ab7cc446a806ec448bbe86aebb979b", size = 4652537, upload-time = "2025-08-14T12:05:26.391Z" }, + { url = "https://files.pythonhosted.org/packages/c7/a8/488b1ed47d25972f33874f91f09ca8f2227902f05f63a2b80dc73e7b1c97/pyproj-3.7.2-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:f7f5133dca4c703e8acadf6f30bc567d39a42c6af321e7f81975c2518f3ed357", size = 9940864, upload-time = "2025-08-14T12:05:27.985Z" }, + { url = "https://files.pythonhosted.org/packages/c7/cc/7f4c895d0cb98e47b6a85a6d79eaca03eb266129eed2f845125c09cf31ff/pyproj-3.7.2-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:5aff3343038d7426aa5076f07feb88065f50e0502d1b0d7c22ddfdd2c75a3f81", size = 9688868, upload-time = "2025-08-14T12:05:30.425Z" }, + { url = "https://files.pythonhosted.org/packages/b2/b7/c7e306b8bb0f071d9825b753ee4920f066c40fbfcce9372c4f3cfb2fc4ed/pyproj-3.7.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:b0552178c61f2ac1c820d087e8ba6e62b29442debddbb09d51c4bf8acc84d888", size = 11045910, upload-time = "2025-08-14T12:05:32.507Z" }, + { url = "https://files.pythonhosted.org/packages/42/fb/538a4d2df695980e2dde5c04d965fbdd1fe8c20a3194dc4aaa3952a4d1be/pyproj-3.7.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:47d87db2d2c436c5fd0409b34d70bb6cdb875cca2ebe7a9d1c442367b0ab8d59", size = 10895724, upload-time = "2025-08-14T12:05:35.465Z" }, + { url = "https://files.pythonhosted.org/packages/e8/8b/a3f0618b03957de9db5489a04558a8826f43906628bb0b766033aa3b5548/pyproj-3.7.2-cp314-cp314t-win32.whl", hash = "sha256:c9b6f1d8ad3e80a0ee0903a778b6ece7dca1d1d40f6d114ae01bc8ddbad971aa", size = 6056848, upload-time = "2025-08-14T12:05:37.553Z" }, + { url = "https://files.pythonhosted.org/packages/bc/56/413240dd5149dd3291eda55aa55a659da4431244a2fd1319d0ae89407cfb/pyproj-3.7.2-cp314-cp314t-win_amd64.whl", hash = "sha256:1914e29e27933ba6f9822663ee0600f169014a2859f851c054c88cf5ea8a333c", size = 6517676, upload-time = "2025-08-14T12:05:39.126Z" }, + { url = "https://files.pythonhosted.org/packages/15/73/a7141a1a0559bf1a7aa42a11c879ceb19f02f5c6c371c6d57fd86cefd4d1/pyproj-3.7.2-cp314-cp314t-win_arm64.whl", hash = "sha256:d9d25bae416a24397e0d85739f84d323b55f6511e45a522dd7d7eae70d10c7e4", size = 6391844, upload-time = "2025-08-14T12:05:40.745Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "pytz" +version = "2025.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/bf/abbd3cdfb8fbc7fb3d4d38d320f2441b1e7cbe29be4f23797b4a2b5d8aac/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", size = 320884, upload-time = "2025-03-25T02:25:00.538Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" }, +] + +[[package]] +name = "requests" +version = "2.32.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, +] + +[[package]] +name = "scikit-learn" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "joblib" }, + { name = "numpy" }, + { name = "scipy" }, + { name = "threadpoolctl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0e/d4/40988bf3b8e34feec1d0e6a051446b1f66225f8529b9309becaeef62b6c4/scikit_learn-1.8.0.tar.gz", hash = "sha256:9bccbb3b40e3de10351f8f5068e105d0f4083b1a65fa07b6634fbc401a6287fd", size = 7335585, upload-time = "2025-12-10T07:08:53.618Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/03/aa/e22e0768512ce9255eba34775be2e85c2048da73da1193e841707f8f039c/scikit_learn-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0d6ae97234d5d7079dc0040990a6f7aeb97cb7fa7e8945f1999a429b23569e0a", size = 8513770, upload-time = "2025-12-10T07:08:03.251Z" }, + { url = "https://files.pythonhosted.org/packages/58/37/31b83b2594105f61a381fc74ca19e8780ee923be2d496fcd8d2e1147bd99/scikit_learn-1.8.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:edec98c5e7c128328124a029bceb09eda2d526997780fef8d65e9a69eead963e", size = 8044458, upload-time = "2025-12-10T07:08:05.336Z" }, + { url = "https://files.pythonhosted.org/packages/2d/5a/3f1caed8765f33eabb723596666da4ebbf43d11e96550fb18bdec42b467b/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:74b66d8689d52ed04c271e1329f0c61635bcaf5b926db9b12d58914cdc01fe57", size = 8610341, upload-time = "2025-12-10T07:08:07.732Z" }, + { url = "https://files.pythonhosted.org/packages/38/cf/06896db3f71c75902a8e9943b444a56e727418f6b4b4a90c98c934f51ed4/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8fdf95767f989b0cfedb85f7ed8ca215d4be728031f56ff5a519ee1e3276dc2e", size = 8900022, upload-time = "2025-12-10T07:08:09.862Z" }, + { url = "https://files.pythonhosted.org/packages/1c/f9/9b7563caf3ec8873e17a31401858efab6b39a882daf6c1bfa88879c0aa11/scikit_learn-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:2de443b9373b3b615aec1bb57f9baa6bb3a9bd093f1269ba95c17d870422b271", size = 7989409, upload-time = "2025-12-10T07:08:12.028Z" }, + { url = "https://files.pythonhosted.org/packages/49/bd/1f4001503650e72c4f6009ac0c4413cb17d2d601cef6f71c0453da2732fc/scikit_learn-1.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:eddde82a035681427cbedded4e6eff5e57fa59216c2e3e90b10b19ab1d0a65c3", size = 7619760, upload-time = "2025-12-10T07:08:13.688Z" }, + { url = "https://files.pythonhosted.org/packages/d2/7d/a630359fc9dcc95496588c8d8e3245cc8fd81980251079bc09c70d41d951/scikit_learn-1.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7cc267b6108f0a1499a734167282c00c4ebf61328566b55ef262d48e9849c735", size = 8826045, upload-time = "2025-12-10T07:08:15.215Z" }, + { url = "https://files.pythonhosted.org/packages/cc/56/a0c86f6930cfcd1c7054a2bc417e26960bb88d32444fe7f71d5c2cfae891/scikit_learn-1.8.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:fe1c011a640a9f0791146011dfd3c7d9669785f9fed2b2a5f9e207536cf5c2fd", size = 8420324, upload-time = "2025-12-10T07:08:17.561Z" }, + { url = "https://files.pythonhosted.org/packages/46/1e/05962ea1cebc1cf3876667ecb14c283ef755bf409993c5946ade3b77e303/scikit_learn-1.8.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72358cce49465d140cc4e7792015bb1f0296a9742d5622c67e31399b75468b9e", size = 8680651, upload-time = "2025-12-10T07:08:19.952Z" }, + { url = "https://files.pythonhosted.org/packages/fe/56/a85473cd75f200c9759e3a5f0bcab2d116c92a8a02ee08ccd73b870f8bb4/scikit_learn-1.8.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:80832434a6cc114f5219211eec13dcbc16c2bac0e31ef64c6d346cde3cf054cb", size = 8925045, upload-time = "2025-12-10T07:08:22.11Z" }, + { url = "https://files.pythonhosted.org/packages/cc/b7/64d8cfa896c64435ae57f4917a548d7ac7a44762ff9802f75a79b77cb633/scikit_learn-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ee787491dbfe082d9c3013f01f5991658b0f38aa8177e4cd4bf434c58f551702", size = 8507994, upload-time = "2025-12-10T07:08:23.943Z" }, + { url = "https://files.pythonhosted.org/packages/5e/37/e192ea709551799379958b4c4771ec507347027bb7c942662c7fbeba31cb/scikit_learn-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf97c10a3f5a7543f9b88cbf488d33d175e9146115a451ae34568597ba33dcde", size = 7869518, upload-time = "2025-12-10T07:08:25.71Z" }, + { url = "https://files.pythonhosted.org/packages/24/05/1af2c186174cc92dcab2233f327336058c077d38f6fe2aceb08e6ab4d509/scikit_learn-1.8.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:c22a2da7a198c28dd1a6e1136f19c830beab7fdca5b3e5c8bba8394f8a5c45b3", size = 8528667, upload-time = "2025-12-10T07:08:27.541Z" }, + { url = "https://files.pythonhosted.org/packages/a8/25/01c0af38fe969473fb292bba9dc2b8f9b451f3112ff242c647fee3d0dfe7/scikit_learn-1.8.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:6b595b07a03069a2b1740dc08c2299993850ea81cce4fe19b2421e0c970de6b7", size = 8066524, upload-time = "2025-12-10T07:08:29.822Z" }, + { url = "https://files.pythonhosted.org/packages/be/ce/a0623350aa0b68647333940ee46fe45086c6060ec604874e38e9ab7d8e6c/scikit_learn-1.8.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:29ffc74089f3d5e87dfca4c2c8450f88bdc61b0fc6ed5d267f3988f19a1309f6", size = 8657133, upload-time = "2025-12-10T07:08:31.865Z" }, + { url = "https://files.pythonhosted.org/packages/b8/cb/861b41341d6f1245e6ca80b1c1a8c4dfce43255b03df034429089ca2a2c5/scikit_learn-1.8.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fb65db5d7531bccf3a4f6bec3462223bea71384e2cda41da0f10b7c292b9e7c4", size = 8923223, upload-time = "2025-12-10T07:08:34.166Z" }, + { url = "https://files.pythonhosted.org/packages/76/18/a8def8f91b18cd1ba6e05dbe02540168cb24d47e8dcf69e8d00b7da42a08/scikit_learn-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:56079a99c20d230e873ea40753102102734c5953366972a71d5cb39a32bc40c6", size = 8096518, upload-time = "2025-12-10T07:08:36.339Z" }, + { url = "https://files.pythonhosted.org/packages/d1/77/482076a678458307f0deb44e29891d6022617b2a64c840c725495bee343f/scikit_learn-1.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:3bad7565bc9cf37ce19a7c0d107742b320c1285df7aab1a6e2d28780df167242", size = 7754546, upload-time = "2025-12-10T07:08:38.128Z" }, + { url = "https://files.pythonhosted.org/packages/2d/d1/ef294ca754826daa043b2a104e59960abfab4cf653891037d19dd5b6f3cf/scikit_learn-1.8.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:4511be56637e46c25721e83d1a9cea9614e7badc7040c4d573d75fbe257d6fd7", size = 8848305, upload-time = "2025-12-10T07:08:41.013Z" }, + { url = "https://files.pythonhosted.org/packages/5b/e2/b1f8b05138ee813b8e1a4149f2f0d289547e60851fd1bb268886915adbda/scikit_learn-1.8.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:a69525355a641bf8ef136a7fa447672fb54fe8d60cab5538d9eb7c6438543fb9", size = 8432257, upload-time = "2025-12-10T07:08:42.873Z" }, + { url = "https://files.pythonhosted.org/packages/26/11/c32b2138a85dcb0c99f6afd13a70a951bfdff8a6ab42d8160522542fb647/scikit_learn-1.8.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c2656924ec73e5939c76ac4c8b026fc203b83d8900362eb2599d8aee80e4880f", size = 8678673, upload-time = "2025-12-10T07:08:45.362Z" }, + { url = "https://files.pythonhosted.org/packages/c7/57/51f2384575bdec454f4fe4e7a919d696c9ebce914590abf3e52d47607ab8/scikit_learn-1.8.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15fc3b5d19cc2be65404786857f2e13c70c83dd4782676dd6814e3b89dc8f5b9", size = 8922467, upload-time = "2025-12-10T07:08:47.408Z" }, + { url = "https://files.pythonhosted.org/packages/35/4d/748c9e2872637a57981a04adc038dacaa16ba8ca887b23e34953f0b3f742/scikit_learn-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:00d6f1d66fbcf4eba6e356e1420d33cc06c70a45bb1363cd6f6a8e4ebbbdece2", size = 8774395, upload-time = "2025-12-10T07:08:49.337Z" }, + { url = "https://files.pythonhosted.org/packages/60/22/d7b2ebe4704a5e50790ba089d5c2ae308ab6bb852719e6c3bd4f04c3a363/scikit_learn-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:f28dd15c6bb0b66ba09728cf09fd8736c304be29409bd8445a080c1280619e8c", size = 8002647, upload-time = "2025-12-10T07:08:51.601Z" }, +] + +[[package]] +name = "scipy" +version = "1.16.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0a/ca/d8ace4f98322d01abcd52d381134344bf7b431eba7ed8b42bdea5a3c2ac9/scipy-1.16.3.tar.gz", hash = "sha256:01e87659402762f43bd2fee13370553a17ada367d42e7487800bf2916535aecb", size = 30597883, upload-time = "2025-10-28T17:38:54.068Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/72/f1/57e8327ab1508272029e27eeef34f2302ffc156b69e7e233e906c2a5c379/scipy-1.16.3-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:d2ec56337675e61b312179a1ad124f5f570c00f920cc75e1000025451b88241c", size = 36617856, upload-time = "2025-10-28T17:33:31.375Z" }, + { url = "https://files.pythonhosted.org/packages/44/13/7e63cfba8a7452eb756306aa2fd9b37a29a323b672b964b4fdeded9a3f21/scipy-1.16.3-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:16b8bc35a4cc24db80a0ec836a9286d0e31b2503cb2fd7ff7fb0e0374a97081d", size = 28874306, upload-time = "2025-10-28T17:33:36.516Z" }, + { url = "https://files.pythonhosted.org/packages/15/65/3a9400efd0228a176e6ec3454b1fa998fbbb5a8defa1672c3f65706987db/scipy-1.16.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:5803c5fadd29de0cf27fa08ccbfe7a9e5d741bf63e4ab1085437266f12460ff9", size = 20865371, upload-time = "2025-10-28T17:33:42.094Z" }, + { url = "https://files.pythonhosted.org/packages/33/d7/eda09adf009a9fb81827194d4dd02d2e4bc752cef16737cc4ef065234031/scipy-1.16.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:b81c27fc41954319a943d43b20e07c40bdcd3ff7cf013f4fb86286faefe546c4", size = 23524877, upload-time = "2025-10-28T17:33:48.483Z" }, + { url = "https://files.pythonhosted.org/packages/7d/6b/3f911e1ebc364cb81320223a3422aab7d26c9c7973109a9cd0f27c64c6c0/scipy-1.16.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0c3b4dd3d9b08dbce0f3440032c52e9e2ab9f96ade2d3943313dfe51a7056959", size = 33342103, upload-time = "2025-10-28T17:33:56.495Z" }, + { url = "https://files.pythonhosted.org/packages/21/f6/4bfb5695d8941e5c570a04d9fcd0d36bce7511b7d78e6e75c8f9791f82d0/scipy-1.16.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7dc1360c06535ea6116a2220f760ae572db9f661aba2d88074fe30ec2aa1ff88", size = 35697297, upload-time = "2025-10-28T17:34:04.722Z" }, + { url = "https://files.pythonhosted.org/packages/04/e1/6496dadbc80d8d896ff72511ecfe2316b50313bfc3ebf07a3f580f08bd8c/scipy-1.16.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:663b8d66a8748051c3ee9c96465fb417509315b99c71550fda2591d7dd634234", size = 36021756, upload-time = "2025-10-28T17:34:13.482Z" }, + { url = "https://files.pythonhosted.org/packages/fe/bd/a8c7799e0136b987bda3e1b23d155bcb31aec68a4a472554df5f0937eef7/scipy-1.16.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eab43fae33a0c39006a88096cd7b4f4ef545ea0447d250d5ac18202d40b6611d", size = 38696566, upload-time = "2025-10-28T17:34:22.384Z" }, + { url = "https://files.pythonhosted.org/packages/cd/01/1204382461fcbfeb05b6161b594f4007e78b6eba9b375382f79153172b4d/scipy-1.16.3-cp313-cp313-win_amd64.whl", hash = "sha256:062246acacbe9f8210de8e751b16fc37458213f124bef161a5a02c7a39284304", size = 38529877, upload-time = "2025-10-28T17:35:51.076Z" }, + { url = "https://files.pythonhosted.org/packages/7f/14/9d9fbcaa1260a94f4bb5b64ba9213ceb5d03cd88841fe9fd1ffd47a45b73/scipy-1.16.3-cp313-cp313-win_arm64.whl", hash = "sha256:50a3dbf286dbc7d84f176f9a1574c705f277cb6565069f88f60db9eafdbe3ee2", size = 25455366, upload-time = "2025-10-28T17:35:59.014Z" }, + { url = "https://files.pythonhosted.org/packages/e2/a3/9ec205bd49f42d45d77f1730dbad9ccf146244c1647605cf834b3a8c4f36/scipy-1.16.3-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:fb4b29f4cf8cc5a8d628bc8d8e26d12d7278cd1f219f22698a378c3d67db5e4b", size = 37027931, upload-time = "2025-10-28T17:34:31.451Z" }, + { url = "https://files.pythonhosted.org/packages/25/06/ca9fd1f3a4589cbd825b1447e5db3a8ebb969c1eaf22c8579bd286f51b6d/scipy-1.16.3-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:8d09d72dc92742988b0e7750bddb8060b0c7079606c0d24a8cc8e9c9c11f9079", size = 29400081, upload-time = "2025-10-28T17:34:39.087Z" }, + { url = "https://files.pythonhosted.org/packages/6a/56/933e68210d92657d93fb0e381683bc0e53a965048d7358ff5fbf9e6a1b17/scipy-1.16.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:03192a35e661470197556de24e7cb1330d84b35b94ead65c46ad6f16f6b28f2a", size = 21391244, upload-time = "2025-10-28T17:34:45.234Z" }, + { url = "https://files.pythonhosted.org/packages/a8/7e/779845db03dc1418e215726329674b40576879b91814568757ff0014ad65/scipy-1.16.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:57d01cb6f85e34f0946b33caa66e892aae072b64b034183f3d87c4025802a119", size = 23929753, upload-time = "2025-10-28T17:34:51.793Z" }, + { url = "https://files.pythonhosted.org/packages/4c/4b/f756cf8161d5365dcdef9e5f460ab226c068211030a175d2fc7f3f41ca64/scipy-1.16.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:96491a6a54e995f00a28a3c3badfff58fd093bf26cd5fb34a2188c8c756a3a2c", size = 33496912, upload-time = "2025-10-28T17:34:59.8Z" }, + { url = "https://files.pythonhosted.org/packages/09/b5/222b1e49a58668f23839ca1542a6322bb095ab8d6590d4f71723869a6c2c/scipy-1.16.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cd13e354df9938598af2be05822c323e97132d5e6306b83a3b4ee6724c6e522e", size = 35802371, upload-time = "2025-10-28T17:35:08.173Z" }, + { url = "https://files.pythonhosted.org/packages/c1/8d/5964ef68bb31829bde27611f8c9deeac13764589fe74a75390242b64ca44/scipy-1.16.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:63d3cdacb8a824a295191a723ee5e4ea7768ca5ca5f2838532d9f2e2b3ce2135", size = 36190477, upload-time = "2025-10-28T17:35:16.7Z" }, + { url = "https://files.pythonhosted.org/packages/ab/f2/b31d75cb9b5fa4dd39a0a931ee9b33e7f6f36f23be5ef560bf72e0f92f32/scipy-1.16.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e7efa2681ea410b10dde31a52b18b0154d66f2485328830e45fdf183af5aefc6", size = 38796678, upload-time = "2025-10-28T17:35:26.354Z" }, + { url = "https://files.pythonhosted.org/packages/b4/1e/b3723d8ff64ab548c38d87055483714fefe6ee20e0189b62352b5e015bb1/scipy-1.16.3-cp313-cp313t-win_amd64.whl", hash = "sha256:2d1ae2cf0c350e7705168ff2429962a89ad90c2d49d1dd300686d8b2a5af22fc", size = 38640178, upload-time = "2025-10-28T17:35:35.304Z" }, + { url = "https://files.pythonhosted.org/packages/8e/f3/d854ff38789aca9b0cc23008d607ced9de4f7ab14fa1ca4329f86b3758ca/scipy-1.16.3-cp313-cp313t-win_arm64.whl", hash = "sha256:0c623a54f7b79dd88ef56da19bc2873afec9673a48f3b85b18e4d402bdd29a5a", size = 25803246, upload-time = "2025-10-28T17:35:42.155Z" }, + { url = "https://files.pythonhosted.org/packages/99/f6/99b10fd70f2d864c1e29a28bbcaa0c6340f9d8518396542d9ea3b4aaae15/scipy-1.16.3-cp314-cp314-macosx_10_14_x86_64.whl", hash = "sha256:875555ce62743e1d54f06cdf22c1e0bc47b91130ac40fe5d783b6dfa114beeb6", size = 36606469, upload-time = "2025-10-28T17:36:08.741Z" }, + { url = "https://files.pythonhosted.org/packages/4d/74/043b54f2319f48ea940dd025779fa28ee360e6b95acb7cd188fad4391c6b/scipy-1.16.3-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:bb61878c18a470021fb515a843dc7a76961a8daceaaaa8bad1332f1bf4b54657", size = 28872043, upload-time = "2025-10-28T17:36:16.599Z" }, + { url = "https://files.pythonhosted.org/packages/4d/e1/24b7e50cc1c4ee6ffbcb1f27fe9f4c8b40e7911675f6d2d20955f41c6348/scipy-1.16.3-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:f2622206f5559784fa5c4b53a950c3c7c1cf3e84ca1b9c4b6c03f062f289ca26", size = 20862952, upload-time = "2025-10-28T17:36:22.966Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3a/3e8c01a4d742b730df368e063787c6808597ccb38636ed821d10b39ca51b/scipy-1.16.3-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:7f68154688c515cdb541a31ef8eb66d8cd1050605be9dcd74199cbd22ac739bc", size = 23508512, upload-time = "2025-10-28T17:36:29.731Z" }, + { url = "https://files.pythonhosted.org/packages/1f/60/c45a12b98ad591536bfe5330cb3cfe1850d7570259303563b1721564d458/scipy-1.16.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8b3c820ddb80029fe9f43d61b81d8b488d3ef8ca010d15122b152db77dc94c22", size = 33413639, upload-time = "2025-10-28T17:36:37.982Z" }, + { url = "https://files.pythonhosted.org/packages/71/bc/35957d88645476307e4839712642896689df442f3e53b0fa016ecf8a3357/scipy-1.16.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d3837938ae715fc0fe3c39c0202de3a8853aff22ca66781ddc2ade7554b7e2cc", size = 35704729, upload-time = "2025-10-28T17:36:46.547Z" }, + { url = "https://files.pythonhosted.org/packages/3b/15/89105e659041b1ca11c386e9995aefacd513a78493656e57789f9d9eab61/scipy-1.16.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:aadd23f98f9cb069b3bd64ddc900c4d277778242e961751f77a8cb5c4b946fb0", size = 36086251, upload-time = "2025-10-28T17:36:55.161Z" }, + { url = "https://files.pythonhosted.org/packages/1a/87/c0ea673ac9c6cc50b3da2196d860273bc7389aa69b64efa8493bdd25b093/scipy-1.16.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b7c5f1bda1354d6a19bc6af73a649f8285ca63ac6b52e64e658a5a11d4d69800", size = 38716681, upload-time = "2025-10-28T17:37:04.1Z" }, + { url = "https://files.pythonhosted.org/packages/91/06/837893227b043fb9b0d13e4bd7586982d8136cb249ffb3492930dab905b8/scipy-1.16.3-cp314-cp314-win_amd64.whl", hash = "sha256:e5d42a9472e7579e473879a1990327830493a7047506d58d73fc429b84c1d49d", size = 39358423, upload-time = "2025-10-28T17:38:20.005Z" }, + { url = "https://files.pythonhosted.org/packages/95/03/28bce0355e4d34a7c034727505a02d19548549e190bedd13a721e35380b7/scipy-1.16.3-cp314-cp314-win_arm64.whl", hash = "sha256:6020470b9d00245926f2d5bb93b119ca0340f0d564eb6fbaad843eaebf9d690f", size = 26135027, upload-time = "2025-10-28T17:38:24.966Z" }, + { url = "https://files.pythonhosted.org/packages/b2/6f/69f1e2b682efe9de8fe9f91040f0cd32f13cfccba690512ba4c582b0bc29/scipy-1.16.3-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:e1d27cbcb4602680a49d787d90664fa4974063ac9d4134813332a8c53dbe667c", size = 37028379, upload-time = "2025-10-28T17:37:14.061Z" }, + { url = "https://files.pythonhosted.org/packages/7c/2d/e826f31624a5ebbab1cd93d30fd74349914753076ed0593e1d56a98c4fb4/scipy-1.16.3-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:9b9c9c07b6d56a35777a1b4cc8966118fb16cfd8daf6743867d17d36cfad2d40", size = 29400052, upload-time = "2025-10-28T17:37:21.709Z" }, + { url = "https://files.pythonhosted.org/packages/69/27/d24feb80155f41fd1f156bf144e7e049b4e2b9dd06261a242905e3bc7a03/scipy-1.16.3-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:3a4c460301fb2cffb7f88528f30b3127742cff583603aa7dc964a52c463b385d", size = 21391183, upload-time = "2025-10-28T17:37:29.559Z" }, + { url = "https://files.pythonhosted.org/packages/f8/d3/1b229e433074c5738a24277eca520a2319aac7465eea7310ea6ae0e98ae2/scipy-1.16.3-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:f667a4542cc8917af1db06366d3f78a5c8e83badd56409f94d1eac8d8d9133fa", size = 23930174, upload-time = "2025-10-28T17:37:36.306Z" }, + { url = "https://files.pythonhosted.org/packages/16/9d/d9e148b0ec680c0f042581a2be79a28a7ab66c0c4946697f9e7553ead337/scipy-1.16.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f379b54b77a597aa7ee5e697df0d66903e41b9c85a6dd7946159e356319158e8", size = 33497852, upload-time = "2025-10-28T17:37:42.228Z" }, + { url = "https://files.pythonhosted.org/packages/2f/22/4e5f7561e4f98b7bea63cf3fd7934bff1e3182e9f1626b089a679914d5c8/scipy-1.16.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4aff59800a3b7f786b70bfd6ab551001cb553244988d7d6b8299cb1ea653b353", size = 35798595, upload-time = "2025-10-28T17:37:48.102Z" }, + { url = "https://files.pythonhosted.org/packages/83/42/6644d714c179429fc7196857866f219fef25238319b650bb32dde7bf7a48/scipy-1.16.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:da7763f55885045036fabcebd80144b757d3db06ab0861415d1c3b7c69042146", size = 36186269, upload-time = "2025-10-28T17:37:53.72Z" }, + { url = "https://files.pythonhosted.org/packages/ac/70/64b4d7ca92f9cf2e6fc6aaa2eecf80bb9b6b985043a9583f32f8177ea122/scipy-1.16.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ffa6eea95283b2b8079b821dc11f50a17d0571c92b43e2b5b12764dc5f9b285d", size = 38802779, upload-time = "2025-10-28T17:37:59.393Z" }, + { url = "https://files.pythonhosted.org/packages/61/82/8d0e39f62764cce5ffd5284131e109f07cf8955aef9ab8ed4e3aa5e30539/scipy-1.16.3-cp314-cp314t-win_amd64.whl", hash = "sha256:d9f48cafc7ce94cf9b15c6bffdc443a81a27bf7075cf2dcd5c8b40f85d10c4e7", size = 39471128, upload-time = "2025-10-28T17:38:05.259Z" }, + { url = "https://files.pythonhosted.org/packages/64/47/a494741db7280eae6dc033510c319e34d42dd41b7ac0c7ead39354d1a2b5/scipy-1.16.3-cp314-cp314t-win_arm64.whl", hash = "sha256:21d9d6b197227a12dcbf9633320a4e34c6b0e51c57268df255a0942983bac562", size = 26464127, upload-time = "2025-10-28T17:38:11.34Z" }, +] + +[[package]] +name = "seaborn" +version = "0.13.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "matplotlib" }, + { name = "numpy" }, + { name = "pandas" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/86/59/a451d7420a77ab0b98f7affa3a1d78a313d2f7281a57afb1a34bae8ab412/seaborn-0.13.2.tar.gz", hash = "sha256:93e60a40988f4d65e9f4885df477e2fdaff6b73a9ded434c1ab356dd57eefff7", size = 1457696, upload-time = "2024-01-25T13:21:52.551Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/11/00d3c3dfc25ad54e731d91449895a79e4bf2384dc3ac01809010ba88f6d5/seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987", size = 294914, upload-time = "2024-01-25T13:21:49.598Z" }, +] + +[[package]] +name = "shapely" +version = "2.1.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4d/bc/0989043118a27cccb4e906a46b7565ce36ca7b57f5a18b78f4f1b0f72d9d/shapely-2.1.2.tar.gz", hash = "sha256:2ed4ecb28320a433db18a5bf029986aa8afcfd740745e78847e330d5d94922a9", size = 315489, upload-time = "2025-09-24T13:51:41.432Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c3/90/98ef257c23c46425dc4d1d31005ad7c8d649fe423a38b917db02c30f1f5a/shapely-2.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b510dda1a3672d6879beb319bc7c5fd302c6c354584690973c838f46ec3e0fa8", size = 1832644, upload-time = "2025-09-24T13:50:44.886Z" }, + { url = "https://files.pythonhosted.org/packages/6d/ab/0bee5a830d209adcd3a01f2d4b70e587cdd9fd7380d5198c064091005af8/shapely-2.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8cff473e81017594d20ec55d86b54bc635544897e13a7cfc12e36909c5309a2a", size = 1642887, upload-time = "2025-09-24T13:50:46.735Z" }, + { url = "https://files.pythonhosted.org/packages/2d/5e/7d7f54ba960c13302584c73704d8c4d15404a51024631adb60b126a4ae88/shapely-2.1.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fe7b77dc63d707c09726b7908f575fc04ff1d1ad0f3fb92aec212396bc6cfe5e", size = 2970931, upload-time = "2025-09-24T13:50:48.374Z" }, + { url = "https://files.pythonhosted.org/packages/f2/a2/83fc37e2a58090e3d2ff79175a95493c664bcd0b653dd75cb9134645a4e5/shapely-2.1.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7ed1a5bbfb386ee8332713bf7508bc24e32d24b74fc9a7b9f8529a55db9f4ee6", size = 3082855, upload-time = "2025-09-24T13:50:50.037Z" }, + { url = "https://files.pythonhosted.org/packages/44/2b/578faf235a5b09f16b5f02833c53822294d7f21b242f8e2d0cf03fb64321/shapely-2.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a84e0582858d841d54355246ddfcbd1fce3179f185da7470f41ce39d001ee1af", size = 3979960, upload-time = "2025-09-24T13:50:51.74Z" }, + { url = "https://files.pythonhosted.org/packages/4d/04/167f096386120f692cc4ca02f75a17b961858997a95e67a3cb6a7bbd6b53/shapely-2.1.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dc3487447a43d42adcdf52d7ac73804f2312cbfa5d433a7d2c506dcab0033dfd", size = 4142851, upload-time = "2025-09-24T13:50:53.49Z" }, + { url = "https://files.pythonhosted.org/packages/48/74/fb402c5a6235d1c65a97348b48cdedb75fb19eca2b1d66d04969fc1c6091/shapely-2.1.2-cp313-cp313-win32.whl", hash = "sha256:9c3a3c648aedc9f99c09263b39f2d8252f199cb3ac154fadc173283d7d111350", size = 1541890, upload-time = "2025-09-24T13:50:55.337Z" }, + { url = "https://files.pythonhosted.org/packages/41/47/3647fe7ad990af60ad98b889657a976042c9988c2807cf322a9d6685f462/shapely-2.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:ca2591bff6645c216695bdf1614fca9c82ea1144d4a7591a466fef64f28f0715", size = 1722151, upload-time = "2025-09-24T13:50:57.153Z" }, + { url = "https://files.pythonhosted.org/packages/3c/49/63953754faa51ffe7d8189bfbe9ca34def29f8c0e34c67cbe2a2795f269d/shapely-2.1.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2d93d23bdd2ed9dc157b46bc2f19b7da143ca8714464249bef6771c679d5ff40", size = 1834130, upload-time = "2025-09-24T13:50:58.49Z" }, + { url = "https://files.pythonhosted.org/packages/7f/ee/dce001c1984052970ff60eb4727164892fb2d08052c575042a47f5a9e88f/shapely-2.1.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:01d0d304b25634d60bd7cf291828119ab55a3bab87dc4af1e44b07fb225f188b", size = 1642802, upload-time = "2025-09-24T13:50:59.871Z" }, + { url = "https://files.pythonhosted.org/packages/da/e7/fc4e9a19929522877fa602f705706b96e78376afb7fad09cad5b9af1553c/shapely-2.1.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8d8382dd120d64b03698b7298b89611a6ea6f55ada9d39942838b79c9bc89801", size = 3018460, upload-time = "2025-09-24T13:51:02.08Z" }, + { url = "https://files.pythonhosted.org/packages/a1/18/7519a25db21847b525696883ddc8e6a0ecaa36159ea88e0fef11466384d0/shapely-2.1.2-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:19efa3611eef966e776183e338b2d7ea43569ae99ab34f8d17c2c054d3205cc0", size = 3095223, upload-time = "2025-09-24T13:51:04.472Z" }, + { url = "https://files.pythonhosted.org/packages/48/de/b59a620b1f3a129c3fecc2737104a0a7e04e79335bd3b0a1f1609744cf17/shapely-2.1.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:346ec0c1a0fcd32f57f00e4134d1200e14bf3f5ae12af87ba83ca275c502498c", size = 4030760, upload-time = "2025-09-24T13:51:06.455Z" }, + { url = "https://files.pythonhosted.org/packages/96/b3/c6655ee7232b417562bae192ae0d3ceaadb1cc0ffc2088a2ddf415456cc2/shapely-2.1.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6305993a35989391bd3476ee538a5c9a845861462327efe00dd11a5c8c709a99", size = 4170078, upload-time = "2025-09-24T13:51:08.584Z" }, + { url = "https://files.pythonhosted.org/packages/a0/8e/605c76808d73503c9333af8f6cbe7e1354d2d238bda5f88eea36bfe0f42a/shapely-2.1.2-cp313-cp313t-win32.whl", hash = "sha256:c8876673449f3401f278c86eb33224c5764582f72b653a415d0e6672fde887bf", size = 1559178, upload-time = "2025-09-24T13:51:10.73Z" }, + { url = "https://files.pythonhosted.org/packages/36/f7/d317eb232352a1f1444d11002d477e54514a4a6045536d49d0c59783c0da/shapely-2.1.2-cp313-cp313t-win_amd64.whl", hash = "sha256:4a44bc62a10d84c11a7a3d7c1c4fe857f7477c3506e24c9062da0db0ae0c449c", size = 1739756, upload-time = "2025-09-24T13:51:12.105Z" }, + { url = "https://files.pythonhosted.org/packages/fc/c4/3ce4c2d9b6aabd27d26ec988f08cb877ba9e6e96086eff81bfea93e688c7/shapely-2.1.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:9a522f460d28e2bf4e12396240a5fc1518788b2fcd73535166d748399ef0c223", size = 1831290, upload-time = "2025-09-24T13:51:13.56Z" }, + { url = "https://files.pythonhosted.org/packages/17/b9/f6ab8918fc15429f79cb04afa9f9913546212d7fb5e5196132a2af46676b/shapely-2.1.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1ff629e00818033b8d71139565527ced7d776c269a49bd78c9df84e8f852190c", size = 1641463, upload-time = "2025-09-24T13:51:14.972Z" }, + { url = "https://files.pythonhosted.org/packages/a5/57/91d59ae525ca641e7ac5551c04c9503aee6f29b92b392f31790fcb1a4358/shapely-2.1.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f67b34271dedc3c653eba4e3d7111aa421d5be9b4c4c7d38d30907f796cb30df", size = 2970145, upload-time = "2025-09-24T13:51:16.961Z" }, + { url = "https://files.pythonhosted.org/packages/8a/cb/4948be52ee1da6927831ab59e10d4c29baa2a714f599f1f0d1bc747f5777/shapely-2.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:21952dc00df38a2c28375659b07a3979d22641aeb104751e769c3ee825aadecf", size = 3073806, upload-time = "2025-09-24T13:51:18.712Z" }, + { url = "https://files.pythonhosted.org/packages/03/83/f768a54af775eb41ef2e7bec8a0a0dbe7d2431c3e78c0a8bdba7ab17e446/shapely-2.1.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1f2f33f486777456586948e333a56ae21f35ae273be99255a191f5c1fa302eb4", size = 3980803, upload-time = "2025-09-24T13:51:20.37Z" }, + { url = "https://files.pythonhosted.org/packages/9f/cb/559c7c195807c91c79d38a1f6901384a2878a76fbdf3f1048893a9b7534d/shapely-2.1.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cf831a13e0d5a7eb519e96f58ec26e049b1fad411fc6fc23b162a7ce04d9cffc", size = 4133301, upload-time = "2025-09-24T13:51:21.887Z" }, + { url = "https://files.pythonhosted.org/packages/80/cd/60d5ae203241c53ef3abd2ef27c6800e21afd6c94e39db5315ea0cbafb4a/shapely-2.1.2-cp314-cp314-win32.whl", hash = "sha256:61edcd8d0d17dd99075d320a1dd39c0cb9616f7572f10ef91b4b5b00c4aeb566", size = 1583247, upload-time = "2025-09-24T13:51:23.401Z" }, + { url = "https://files.pythonhosted.org/packages/74/d4/135684f342e909330e50d31d441ace06bf83c7dc0777e11043f99167b123/shapely-2.1.2-cp314-cp314-win_amd64.whl", hash = "sha256:a444e7afccdb0999e203b976adb37ea633725333e5b119ad40b1ca291ecf311c", size = 1773019, upload-time = "2025-09-24T13:51:24.873Z" }, + { url = "https://files.pythonhosted.org/packages/a3/05/a44f3f9f695fa3ada22786dc9da33c933da1cbc4bfe876fe3a100bafe263/shapely-2.1.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:5ebe3f84c6112ad3d4632b1fd2290665aa75d4cef5f6c5d77c4c95b324527c6a", size = 1834137, upload-time = "2025-09-24T13:51:26.665Z" }, + { url = "https://files.pythonhosted.org/packages/52/7e/4d57db45bf314573427b0a70dfca15d912d108e6023f623947fa69f39b72/shapely-2.1.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5860eb9f00a1d49ebb14e881f5caf6c2cf472c7fd38bd7f253bbd34f934eb076", size = 1642884, upload-time = "2025-09-24T13:51:28.029Z" }, + { url = "https://files.pythonhosted.org/packages/5a/27/4e29c0a55d6d14ad7422bf86995d7ff3f54af0eba59617eb95caf84b9680/shapely-2.1.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b705c99c76695702656327b819c9660768ec33f5ce01fa32b2af62b56ba400a1", size = 3018320, upload-time = "2025-09-24T13:51:29.903Z" }, + { url = "https://files.pythonhosted.org/packages/9f/bb/992e6a3c463f4d29d4cd6ab8963b75b1b1040199edbd72beada4af46bde5/shapely-2.1.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a1fd0ea855b2cf7c9cddaf25543e914dd75af9de08785f20ca3085f2c9ca60b0", size = 3094931, upload-time = "2025-09-24T13:51:32.699Z" }, + { url = "https://files.pythonhosted.org/packages/9c/16/82e65e21070e473f0ed6451224ed9fa0be85033d17e0c6e7213a12f59d12/shapely-2.1.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:df90e2db118c3671a0754f38e36802db75fe0920d211a27481daf50a711fdf26", size = 4030406, upload-time = "2025-09-24T13:51:34.189Z" }, + { url = "https://files.pythonhosted.org/packages/7c/75/c24ed871c576d7e2b64b04b1fe3d075157f6eb54e59670d3f5ffb36e25c7/shapely-2.1.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:361b6d45030b4ac64ddd0a26046906c8202eb60d0f9f53085f5179f1d23021a0", size = 4169511, upload-time = "2025-09-24T13:51:36.297Z" }, + { url = "https://files.pythonhosted.org/packages/b1/f7/b3d1d6d18ebf55236eec1c681ce5e665742aab3c0b7b232720a7d43df7b6/shapely-2.1.2-cp314-cp314t-win32.whl", hash = "sha256:b54df60f1fbdecc8ebc2c5b11870461a6417b3d617f555e5033f1505d36e5735", size = 1602607, upload-time = "2025-09-24T13:51:37.757Z" }, + { url = "https://files.pythonhosted.org/packages/9a/f6/f09272a71976dfc138129b8faf435d064a811ae2f708cb147dccdf7aacdb/shapely-2.1.2-cp314-cp314t-win_amd64.whl", hash = "sha256:0036ac886e0923417932c2e6369b6c52e38e0ff5d9120b90eef5cd9a5fc5cae9", size = 1796682, upload-time = "2025-09-24T13:51:39.233Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "threadpoolctl" +version = "3.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b7/4d/08c89e34946fce2aec4fbb45c9016efd5f4d7f24af8e5d93296e935631d8/threadpoolctl-3.6.0.tar.gz", hash = "sha256:8ab8b4aa3491d812b623328249fab5302a68d2d71745c8a4c719a2fcaba9f44e", size = 21274, upload-time = "2025-03-13T13:49:23.031Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638, upload-time = "2025-03-13T13:49:21.846Z" }, +] + +[[package]] +name = "tidypolars" +version = "0.3.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, + { name = "polars" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/b4/98c9f4f6c87d0630c4745777140c889d3b1a70db5a292204020839f0deae/tidypolars-0.3.2.tar.gz", hash = "sha256:009cb92d3211fb20a375adbfcf043703b04411aa22c05351addd13addff84f67", size = 17836, upload-time = "2024-11-02T14:49:21.012Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/c5/fe58f5ff266d15d22c3eb214c04d035c606febd317ea51cac85e212e74de/tidypolars-0.3.2-py3-none-any.whl", hash = "sha256:73ca614730c38abc63e30db832e599b098e95ea7094d9cff60fe24733b0a5293", size = 18731, upload-time = "2024-11-02T14:49:19.513Z" }, +] + +[[package]] +name = "tzdata" +version = "2025.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/a7/c202b344c5ca7daf398f3b8a477eeb205cf3b6f32e7ec3a6bac0629ca975/tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7", size = 196772, upload-time = "2025-12-13T17:45:35.667Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, +] + +[[package]] +name = "urllib3" +version = "2.6.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1e/24/a2a2ed9addd907787d7aa0355ba36a6cadf1768b934c652ea78acbd59dcd/urllib3-2.6.2.tar.gz", hash = "sha256:016f9c98bb7e98085cb2b4b17b87d2c702975664e4f060c6532e64d1c1a5e797", size = 432930, upload-time = "2025-12-11T15:56:40.252Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl", hash = "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd", size = 131182, upload-time = "2025-12-11T15:56:38.584Z" }, +] + +[[package]] +name = "xlrd" +version = "2.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/07/5a/377161c2d3538d1990d7af382c79f3b2372e880b65de21b01b1a2b78691e/xlrd-2.0.2.tar.gz", hash = "sha256:08b5e25de58f21ce71dc7db3b3b8106c1fa776f3024c54e45b45b374e89234c9", size = 100167, upload-time = "2025-06-14T08:46:39.039Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1a/62/c8d562e7766786ba6587d09c5a8ba9f718ed3fa8af7f4553e8f91c36f302/xlrd-2.0.2-py2.py3-none-any.whl", hash = "sha256:ea762c3d29f4cca48d82df517b6d89fbce4db3107f9d78713e48cd321d5c9aa9", size = 96555, upload-time = "2025-06-14T08:46:37.766Z" }, +] From f1fca47b700ec4f4165b224189475b84085ef62a Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Mon, 5 Jan 2026 21:19:12 +0000 Subject: [PATCH 07/92] polars tutorial skeleton --- source/manipulation/polars/tutorial.qmd | 140 +++++++----------------- 1 file changed, 40 insertions(+), 100 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 417d8285..194f9e26 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -1,62 +1,48 @@ ::: {.content-visible when-profile="fr"} # Traiter des données tabulaires avec Polars -L'analyse statistique a généralement pour base des **données tabulaires**, dans lesquelles chaque ligne représente une observation et chaque colonne une variable. Pour traiter ce type de données et y appliquer facilement les méthodes d'analyse de données standards, des objets dédiés ont été conçus : les `DataFrames`. Les utilisateurs de `R` connaissent bien cette structure de données, qui est native à ce langage orienté statistique. En `Python`, langage généraliste, cet objet n'existe pas nativement. Heureusement, une librairie très complete et bien pratique, pensée comme une surcouche à `NumPy`, introduit en `Python` l'objet `DataFrame` et permet la manipulation et l'analyse de données de manière simple et intuitive : `Pandas`. +L'analyse statistique a généralement pour base des **données tabulaires**, dans lesquelles chaque ligne représente une observation et chaque colonne une variable. Pour traiter ce type de données et y appliquer facilement les méthodes d'analyse de données standards, des objets dédiés ont été conçus : les `DataFrames`. Les utilisateurs de `R` connaissent bien cette structure de données, qui est native à ce langage orienté statistique. En `Python`, langage généraliste, cet objet n'existe pas nativement. -::: {.callout-note} -Pandas étant l'élément central de l'éco-système data science en Python, il offre des possibilités de traitement de la donnée quasi-infinies. En plus de ça, il existe généralement de multiples manières de réaliser une même opération en Pandas. En conséquence, ce chapitre est particulièrement long et dense en nouvelles fonctionnalités. L'objectif n'est pas de retenir toutes les méthodes présentées tout au long de ce chapitre, mais plutôt d'avoir une vision générale de ce qu'il est possible de faire afin de pouvoir mobiliser les bons outils dans les projets. En particulier, les exercices de fin de chapitre et les mini-projets de fin de formation seront l'occasion d'appliquer ces nouvelles connaissances à des problématiques concrètes. -::: +On commence par importer la librairie `Polars`. L'usage est courant est de lui attribuer l'alias `pl` afin de simplifier les futurs appels aux objets et fonctions du package. -On commence par importer la librairie `Pandas`. L'usage est courant est de lui attribuer l'alias `pd` afin de simplifier les futurs appels aux objets et fonctions du package. On importe également `NumPy` car on va comparer les objets fondamentaux des deux packages. +Intro, reprendre de -```{python} -import pandas as pd -import numpy as np -``` +- [Lien réparé vers le notebook Polars](https://datalab.sspcloud.fr/launcher/ide/jupyter-python?name=Tutoriel%20Polars&version=2.3.28&s3=region-79669f20&init.personalInit=«https%3A%2F%2Fraw.githubusercontent.com%2Fntoulemonde%2Ftest%2Frefs%2Fheads%2Fmain%2Finit.sh»&autoLaunch=true) +Polars plus proche de l'univers du tidyverse pour des personnes venant de R. +beaucoup plus rapide que pandas +plus jeune (et donc pas (encore?) intégré partout ? panda) +moins répandu que Pandas +très strict sur les types des colonnes -## Structures de données - -Pour bien comprendre le fonctionnement de `Pandas`, il faut s'intéresser à ses objets fondamentaux. On va donc d'abord étudier les `Series`, dont la concaténation permet de construire un `DataFrame`. +Parler de : +- types +- colonnes sont associées à des string. +- pas d'index. +- polars selectors +- pipe +- lazy eval -### La `Series` +Ressources : +https://ddotta.github.io/awesome-polars/ -Une Series est un conteneur de données unidimensionnel pouvant accueillir n'importe quel type de données (entiers, *strings*, objets Python...). Une Series est néanmoins d'un type donné : une Series ne contenant que des entiers sera de type `int`, et une Series contenant des objets de différente nature sera de type `object`. Construisons notre première Series à partir d'une liste pour vérifier ce comportement. +tidypolars : https://tidypolars.readthedocs.io/en/latest/ ```{python} -l = [1, "X", 3] -s = pd.Series(l) -print(s) -``` - -On peut notamment accéder aux données d'une Series par position, comme pour une liste ou un array. - -```{python} -print(s[1]) -``` - -A priori, on ne voit pas beaucoup de différence entre une Series et un *array* `NumPy` à 1 dimension. Pourtant, il existe une différence de taille qui est la présence d'un index : les observations ont un label associé. Lorsqu'on crée une Series sans rien spécifier, l'index est automatiquement fixé aux entiers de 0 à n-1 (avec n le nombre d'éléments de la Series). Mais il est possible de passer un index spécifique (ex : des dates, des noms de communes, etc.). - -```{python} -s = pd.Series(l, index=["a", "b", "c"]) -print(s) +import tidypolars as tp +df = tp.tibble(name = ['apple', 'banana', 'pear', 'grape']) +print(df.mutate(x = tp.str_extract(tp.col('name'), 'e'))) ``` -Ce qui permet d'accéder aux données par label : - ```{python} -s["b"] +import polars as pl ``` -Cette différence apparaît secondaire à première vue, mais deviendra essentielle pour la construction du DataFrame. Pour le reste, les Series se comportent de manière très proche des arrays NumPy : les calculs sont vectorisés, on peut directement faire la somme de deux Series, etc. D'ailleurs, on peut très facilement convertir une Series en array via l'attribut `values`. Ce qui, naturellement, fait perdre l'index... -```{python} -s = pd.Series(l, index=["a", "b", "c"]) -s.values -``` +## Structures de données ### Le `DataFrame` @@ -67,45 +53,31 @@ Fondamentalement, un DataFrame consiste en une collection de Series, alignées p Un DataFrame peut être construit de multiples manières. En pratique, on construit généralement un DataFrame directement à partir de fichiers de données tabulaires (ex : CSV, excel), rarement à la main. On illustrera donc seulement la méthode de construction manuelle la plus usuelle : à partir d'un dictionnaire de données. ```{python} -df = pd.DataFrame( +df = pl.DataFrame( data = { - "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], - "var2": np.random.randint(-10, 10, 6), + "var1": [1.3, 5.6, None, None, 0, None], "experiment": ["test", "train", "test", "train", "train", "validation"], "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-01-05", "2022-01-06"], "sample": "sample1" - } + }, strict=False ) df ``` -Un DataFrame Pandas dispose d'un ensemble d'attributs utiles que nous allons découvrir tout au long de ce tutoriel. Pour l'instant, intéressons-nous aux plus basiques : l'index et le nom des colonnes. Par défaut, l'index est initialisé comme pour les Series à la liste des positions des observations. On aurait pu spécifier un index alternatif lors de la construction du DataFrame en spécifiant l'argument `index` de la fonction `pd.DataFrame`. +from_dicts +from_dict -```{python} -df.index -``` -```{python} -df.columns -``` +A noter qu'une valeur manquante est indiquée par None en Polars. Elle sera ensuite traduite en type Null interne à Polars. -Souvent, plutôt que de spécifier un index à la main lors de la construction du DataFrame, on va vouloir utiliser une certaine colonne du DataFrame comme index. On utilise pour cela la méthode `set_index` associée aux DataFrames. +Un DataFrame Pandas dispose d'un ensemble d'attributs utiles que nous allons découvrir tout au long de ce tutoriel. Pour l'instant, intéressons-nous aux plus basiques : le nom des colonnes. ```{python} -df = df.set_index("date") -df -``` - -L'attribut index a naturellement changé : - -```{python} -df.index +df.columns ``` - - - +Autres attributs ? ## Sélectionner des données @@ -158,29 +130,6 @@ selected_columns.shape ### Sélectionner des lignes -#### Utilisation de `loc` et `iloc` - -Lorsqu'on veut sélectionner des lignes spécifiques dans un DataFrame, on peut se servir des deux principales méthodes : `loc` et `iloc`. - - -- `iloc` permet de sélectionner des lignes et des colonnes par leur position, c'est-à-dire par des indices numériques. - -Exemple, sélection des 3 premières lignes : -```{python} -df.iloc[0:3, :] -``` - - -- `loc` quant à lui, fonctionne avec des labels. Si les index du DataFrame sont des numéros, ils ressemblent aux positions, mais ce n'est pas forcément le cas. Il est crucial de noter que, contrairement à `iloc`, avec `loc`, l'index de fin est inclus dans la sélection. - -```{python} -df.loc["2022-01-01":"2022-01-03", :] -``` - -#### Filtrage des données selon des conditions - -En pratique, plutôt que de sélectionner des lignes basées sur des positions ou des labels, on souhaite souvent filtrer un DataFrame selon certaines conditions. Dans ce cas, on se sert principalement de filtres booléens. - - **Inégalités** : On peut vouloir garder seulement les lignes qui respectent une certaine condition. @@ -238,6 +187,8 @@ df_departements = pd.read_csv('data/departement2021.csv') df_departements.head() ``` +Pas possible de faire directement avec un url, pour cela il faut aller chercher le fichier et le lire + Il est également possible d'importer un fichier CSV directement à partir d'une URL. C'est particulièrement pratique lorsque les données sont régulièrement mises à jour sur un site web et que l'on souhaite accéder à la version la plus récente sans avoir à télécharger manuellement le fichier à chaque fois. Prenons l'exemple d'un fichier CSV disponible sur le site de l'INSEE : le fichier des prénoms, issu des données de l'état civil. On note au passage une autre fonctionnalité bien pratique : le fichier CSV est compressé (format `zip`), mais Pandas est capable de le reconnaître et de le décompresser avant de l'importer. ```{python} @@ -258,20 +209,6 @@ df_departements_dom = df_departements[df_departements["DEP"].isin(["971", "972", df_departements_dom.to_csv('output/departements2021_dom.csv') ``` -Un des arguments clés de la méthode `to_csv()` est `index`. Par défaut, `index=True`, ce qui signifie que l'index du DataFrame sera également écrit dans le fichier CSV. On peut le vérifier en imprimant les premières lignes de notre fichier CSV : Pandas a ajouté une colonne non-nommée, qui contient l'index des lignes retenues. - -```{python} -with open("output/departements2021_dom.csv") as file_in: - for i in range(5): - row = next(file_in).strip() - print(row) -``` - -Dans certains cas, notamment lorsque l'index n'apporte pas d'information utile ou est simplement généré automatiquement par Pandas, on pourrait vouloir l'exclure du fichier exporté. Pour ce faire, on peut définir `index=False`. - -```{python} -df_departements_dom.to_csv('output/departements2021_dom_noindex.csv', index=False) -``` #### Importer un fichier Parquet @@ -366,14 +303,17 @@ df_departements.sample(n=5) L'une des premières étapes lors de l'exploration de nouvelles données est de comprendre la structure générale du jeu de données. La méthode `info()` de Pandas offre une vue d'ensemble rapide des données, notamment en termes de types de données, de présence de valeurs manquantes et de mémoire utilisée. +df.glimpse() + +Par défaut imprime les 5 premières et dernière lignes quand on fait +df + ```{python} df.info() ``` Plusieurs éléments d'information clés peuvent être extraits de ce résultat : -- **index** : le DataFrame a un `RangeIndex`, ce qui signifie que l'index est constitué d'une suite numérique simple. Ici, l'index va de 0 à 5, soit 6 entrées au total. - - **schéma** : la liste des colonnes est affichée avec des informations très utiles sur le schéma des données : - **Non-Null Count** : le nombre de valeurs **non-manquantes** (non `nan`) dans la colonne. Si ce nombre est inférieur au nombre total d'entrées (dans notre cas, 6), cela signifie que la colonne contient des valeurs manquantes. Attention à l'ambiguité possible sur "null" : cela signifie bien les valeurs manquantes, pas les valeurs égales à 0. Ainsi, dans notre cas, le nombre de valeurs "non-null" pour la variable `var1` est 3. From 35af977a04b74878801565fa13283412cc1e8d20 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 6 Jan 2026 11:20:09 +0000 Subject: [PATCH 08/92] wtih select and csv --- source/manipulation/polars/tutorial.qmd | 123 ++++++++++++++++++------ 1 file changed, 96 insertions(+), 27 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 194f9e26..12b91b52 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -25,6 +25,10 @@ Parler de : - polars selectors - pipe - lazy eval +- unnest + +pour aller plus loin : +- interconnection avec duckDB pour des requêtes en SQL Ressources : https://ddotta.github.io/awesome-polars/ @@ -46,7 +50,7 @@ import polars as pl ### Le `DataFrame` -Fondamentalement, un DataFrame consiste en une collection de Series, alignées par les index. Cette concaténation construit donc une table de données, dont les Series correspondent aux colonnes, et dont l'index identifie les lignes. La figure suivante ([source](https://www.geeksforgeeks.org/creating-a-pandas-dataframe/)) permet de bien comprendre cette structure de données. +Fondamentalement, un DataFrame consiste en une collection de Series. Cette concaténation construit donc une table de données, dont les Series correspondent aux colonnes. La figure suivante ([source](https://www.geeksforgeeks.org/creating-a-pandas-dataframe/)) permet de bien comprendre cette structure de données. ![](img/structure_df.png){fig-align="center" width="800"} @@ -65,13 +69,10 @@ df = pl.DataFrame( df ``` -from_dicts -from_dict - -A noter qu'une valeur manquante est indiquée par None en Polars. Elle sera ensuite traduite en type Null interne à Polars. +A noter qu'une valeur manquante est indiquée par `None` en Polars. Elle sera ensuite traduite en type Null interne à Polars. -Un DataFrame Pandas dispose d'un ensemble d'attributs utiles que nous allons découvrir tout au long de ce tutoriel. Pour l'instant, intéressons-nous aux plus basiques : le nom des colonnes. +Un DataFrame Polars dispose d'un ensemble d'attributs utiles que nous allons découvrir tout au long de ce tutoriel. Pour l'instant, intéressons-nous aux plus basiques : le nom des colonnes. ```{python} df.columns @@ -81,39 +82,46 @@ Autres attributs ? ## Sélectionner des données -Lors de la manipulation des données tabulaires, il est fréquent de vouloir extraire des colonnes spécifiques d'un `DataFrame`. Cette extraction est simple avec `Pandas` grâce à l'utilisation des crochets. +Lors de la manipulation des données tabulaires, il est fréquent de vouloir extraire des colonnes spécifiques d'un `DataFrame`. +Cette extraction suit la même logique que le tidyverse avec `Polars`. +La méthode `select` permet de sélectionner sur les colonnes quand `filter` filtre les lignes. ### Sélectionner des colonnes -#### Sélectionner une seule colonne +Que l'on veuille sélectionner une ou deux colonnes en `Polars`, la logique est similaire. Pour extraire une seule colonne, on peut utiliser la syntaxe suivante : ```{python} -selected_column = df["var1"] +selected_column = df.select("var1") selected_column ``` -L'objet `selected_column` renvoie ici la colonne nommée `var1` du `DataFrame` `df`. Mais de quel type est cet objet ? Pour répondre à cette question, on utilise la fonction `type()` : +L'objet `selected_column` renvoie ici la colonne nommée `var1` du `DataFrame` `df`. Contrairement à Pandas, ici on ne garde qu'une seule colonne du dataframe, on ne l'extrait pas. L'objet `selected_columns` reste donc un dataframe de 1 colonne, et n'est pas une Polars Series. En effet, si on sélectionnait 2 colonnes, cela serait toujours un dataframe. + +::: {.callout-tip} +Si vous voulez transformer un dataframe en une série Polars, il faut utiliser la méthode `to_series()` ou reprendre la syntaxe de Pandas qui marche aussi en Polars : ```{python} -type(selected_column) -``` +print(f'En passant par select.to_series(), la table \n {df.select('var1').to_series()} \n est de type {type(df.select('var1').to_series())}') +print(f'En passant par df[var1], la table \n {df['var1']} \n est aussi de type {type(df['var1'])}') -Comme on peut le voir, le résultat est une `Series`, qui est un objet unidimensionnel dans `Pandas`. +``` +::: Un autre attribut utile à connaître est `shape`. Il permet de connaître la dimension de l'objet. Pour une `Series`, `shape` retournera un tuple dont le premier élément indique le nombre de lignes. ```{python} -selected_column.shape +df.shape ``` #### Sélectionner plusieurs colonnes -Pour extraire plusieurs colonnes, il suffit de passer une liste des noms des colonnes souhaitées : +Pour extraire plusieurs colonnes, il suffit de passer une liste des noms des colonnes souhaitées +ou sans passer par une liste, comme dans le tidyverse. ```{python} -selected_columns = df[["var1", "var2", "experiment"]] -selected_columns +print(df.select("var1", "experiment")) +print(df.select(["var1", "experiment"])) ``` Cet extrait montre les colonnes `var1`, `var2` et `experiment` du `DataFrame` `df`. Vérifions maintenant son type : @@ -122,11 +130,7 @@ Cet extrait montre les colonnes `var1`, `var2` et `experiment` du `DataFrame` `d type(selected_columns) ``` -Le résultat est un `DataFrame`, car il s'agit d'un objet bidimensionnel. On peut aussi vérifier sa forme avec l'attribut `shape`. Dans ce cas, le tuple renvoyé par `shape` contiendra deux éléments : le nombre de lignes et le nombre de colonnes. -```{python} -selected_columns.shape -``` ### Sélectionner des lignes @@ -163,6 +167,22 @@ En statistique publique, le point de départ n'est généralement pas la génér ### Importer et exporter des données +Polars est très sensible au type des données, l'import peut donc parfois être un peu long quand il n'arrive pas à déterminer le type de données de la colonne. +En effet, Polars va traiter chaque colonne comme une série d'un des types qu'il connait. +Les types de données sont détaillés dans la [documentation de Polars](https://docs.pola.rs/api/python/stable/reference/datatypes.html). +Ils comprennent principalement: + +| Type de données | Type en Polars | Remarques | +| -- | -- | -- | +| Caractères | - `pl.String`
- `pl.Utf8` | les données catégorielles (`pl.Categorical`) sont encore peu matures dans Polars.
Il peut donc mieux valoir les traiter simplement comme des caractères usuels. | +| Nombres | | | +| - entiers | - `pl.Int8`
- `pl.Int16`
- `pl.Int32` ... | | +| - numérique | - `pl.Float16`
- `pl.Float32`
- `pl.Float64` | | +| Temporelles | - `pl.Date`
- `pl.Datetime`
- `pl.Duration` ... | | +| Structures imbriquées | | - les `pl.Struc` très pratique pour lire des formats imbriqués comme des JSON)| + +A noter que pour Polars, null et nan sont différents. + #### Importer un fichier CSV Comme nous l'avons vu dans un précédent TP, le format CSV est l'un des formats les plus courants pour stocker des données tabulaires. Nous avons précédemment utilisé la librairie `csv` pour les manipuler comme des fichiers texte, mais ce n'était pas très pratique. Pour rappel, la syntaxe pour lire un fichier CSV et afficher les premières lignes était la suivante : @@ -183,22 +203,71 @@ rows[:5] Avec Pandas, il suffit d'utiliser la fonction `read_csv()` pour importer le fichier comme un DataFrame, puis la fonction `head()`. ```{python} -df_departements = pd.read_csv('data/departement2021.csv') +df_departements = pl.read_csv('data/departement2021.csv') df_departements.head() ``` Pas possible de faire directement avec un url, pour cela il faut aller chercher le fichier et le lire -Il est également possible d'importer un fichier CSV directement à partir d'une URL. C'est particulièrement pratique lorsque les données sont régulièrement mises à jour sur un site web et que l'on souhaite accéder à la version la plus récente sans avoir à télécharger manuellement le fichier à chaque fois. Prenons l'exemple d'un fichier CSV disponible sur le site de l'INSEE : le fichier des prénoms, issu des données de l'état civil. On note au passage une autre fonctionnalité bien pratique : le fichier CSV est compressé (format `zip`), mais Pandas est capable de le reconnaître et de le décompresser avant de l'importer. +Il est également possible d'importer un fichier CSV directement à partir d'une URL. C'est particulièrement pratique lorsque les données sont régulièrement mises à jour sur un site web et que l'on souhaite accéder à la version la plus récente sans avoir à télécharger manuellement le fichier à chaque fois. Prenons l'exemple d'un fichier CSV disponible sur le site de l'INSEE : le fichier des prénoms, issu des données de l'état civil. +A la différence de Pandas et à la date d'écriture de ce tutoriel, Polars ne dézippe pas encore automatiquement le fichier csv(_cf._ [discussion de cette problématique sur Github](https://github.com/pola-rs/polars/issues/19447)). +Il faut donc faire les petites étapes avant soi-même pour le moment. ```{python} -# Importer un fichier CSV depuis une URL +# Téléchargement et stockage du nom du fichier url = "https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip" -df_prenoms_url = pd.read_csv(url, sep=";") -df_prenoms_url.head() +file_Path = url.split('/')[-1] + +response = requests.get(url) +if response.status_code == 200: + with open(file_Path, 'wb') as file: + file.write(response.content) + +# zipfile permet de dézipper les fichiers +from zipfile import ZipFile + +# on charge le fichier télécharger et extraction dans un dossier temp/ +with ZipFile(file_Path, 'r') as zObject: + + # Extracting all the members of the zip + # into a specific location. + zObject.extractall( + path="temp/") + +``` + +For example, here Polars will throw back an error because of data types. It thinks the anais column is an int but then finds a 'XXXX' value +```{python} +df_prenoms_url = pl.read_csv('temp/'+os.listdir('temp')[0], separator=";") +``` +You can set infer_schema=False to cast all columns as string + +```{python} +df_prenoms_url = pl.read_csv('temp/'+os.listdir('temp')[0], separator=";", infer_schema=False) +df_prenoms_url ``` -Lorsqu'on travaille avec des fichiers CSV, il y a de nombreux arguments optionnels disponibles dans la fonction `read_csv()` qui permettent d'ajuster le processus d'importation en fonction des spécificités du fichier. Ces arguments peuvent notamment permettre de définir un délimiteur spécifique (comme ci-dessus pour le fichier des prénoms), de sauter certaines lignes en début de fichier, ou encore de définir les types de données pour chaque colonne, et bien d'autres. Tous ces paramètres et leur utilisation sont détaillés dans la [documentation officielle](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html). +You can also tell Polars to treat the `XXXX` modality as null. +Polars will then infer the types of each columns +```{python} +df_prenoms_url = pl.read_csv('temp/'+os.listdir('temp')[0], separator=";", null_values=['XXXX']) +df_prenoms_url +``` + +```{python} +!rm $file_Path +!rm temp -rf +``` + +Lorsqu'on travaille avec des fichiers CSV, il y a de nombreux arguments optionnels disponibles dans la fonction `read_csv()` qui permettent d'ajuster le processus d'importation en fonction des spécificités du fichier. Ces arguments peuvent notamment permettre de définir un délimiteur spécifique (comme ci-dessus pour le fichier des prénoms), de sauter certaines lignes en début de fichier, ou encore de définir les types de données pour chaque colonne, et bien d'autres. Tous ces paramètres et leur utilisation sont détaillés dans la [documentation officielle](https://docs.pola.rs/api/python/stable/reference/api/polars.read_csv.html#polars.read_csv). + +#### Importer depuis un dictionnaire + +Comme illustré dans la partie JSON, on peut aussi créer un dataFrame Polars à partir d'un dictionnaire. +Cela est très utile par exemple quand on récupère les données d'une API. + +from_dicts +from_dict #### Exporter au format CSV From 1cc68086e9b271b21c43f06f2160030fb58739ab Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 6 Jan 2026 12:19:45 +0000 Subject: [PATCH 09/92] filter and select --- source/manipulation/polars/tutorial.qmd | 143 ++++++++++++++++-------- 1 file changed, 99 insertions(+), 44 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 12b91b52..98dc4f0f 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -19,7 +19,7 @@ très strict sur les types des colonnes Parler de : -- types +- types : FAIT - colonnes sont associées à des string. - pas d'index. - polars selectors @@ -78,7 +78,13 @@ Un DataFrame Polars dispose d'un ensemble d'attributs utiles que nous allons dé df.columns ``` -Autres attributs ? +Les principaux autres attributs d'un dataframe sont : +- liés à la taille du data frame : + - le nombre de ligne (df.height) et de colonnes (df.width) + - la forme globale (df.shape), qui reprend le nombre de lignes et de colonnes +- liés aux formats des colonnes: + - le schéma du dataframe (df.schema) + - les formats des colonnes (df.dtypes) ## Sélectionner des données @@ -97,7 +103,10 @@ selected_column = df.select("var1") selected_column ``` -L'objet `selected_column` renvoie ici la colonne nommée `var1` du `DataFrame` `df`. Contrairement à Pandas, ici on ne garde qu'une seule colonne du dataframe, on ne l'extrait pas. L'objet `selected_columns` reste donc un dataframe de 1 colonne, et n'est pas une Polars Series. En effet, si on sélectionnait 2 colonnes, cela serait toujours un dataframe. +L'objet `selected_column` renvoie ici la colonne nommée `var1` du `DataFrame` `df`. +Contrairement à Pandas, ici on ne garde qu'une seule colonne du dataframe, on ne l'extrait pas. +L'objet `selected_columns` reste donc un dataframe de 1 colonne, et n'est pas une Polars Series. +En effet, si on sélectionnait 2 colonnes, cela serait aussi dataframe. ::: {.callout-tip} Si vous voulez transformer un dataframe en une série Polars, il faut utiliser la méthode `to_series()` ou reprendre la syntaxe de Pandas qui marche aussi en Polars : @@ -109,80 +118,121 @@ print(f'En passant par df[var1], la table \n {df['var1']} \n est aussi de type { ``` ::: -Un autre attribut utile à connaître est `shape`. Il permet de connaître la dimension de l'objet. Pour une `Series`, `shape` retournera un tuple dont le premier élément indique le nombre de lignes. -```{python} -df.shape -``` - -#### Sélectionner plusieurs colonnes Pour extraire plusieurs colonnes, il suffit de passer une liste des noms des colonnes souhaitées ou sans passer par une liste, comme dans le tidyverse. +Cet extrait montre les colonnes `var1` et `experiment` du `DataFrame` `df`. + ```{python} print(df.select("var1", "experiment")) print(df.select(["var1", "experiment"])) ``` -Cet extrait montre les colonnes `var1`, `var2` et `experiment` du `DataFrame` `df`. Vérifions maintenant son type : -```{python} -type(selected_columns) -``` +### Sélectionner des lignes +En pratique, on souhaite souvent filtrer un DataFrame selon certaines conditions. +Dans ce cas, on se sert principalement de filtres booléens selon une logique similaire au tidyverse. +La principale différence tient au nommage des colonnes. +En effet, le nom de chaque colonne doit être entourée d'un sélecteur `pl.col`. +Quand en R on écrirait +```r +df |> + filter(var1>=0) +``` -### Sélectionner des lignes +en Polars, on va l'écrire +```{python} +print(df.filter(pl.col('var1')>=0)) +print(df.filter(pl.col.var1 >= 0)) +``` + +Il y a deux manières de sélectionner une colonne : avec `pl.col('colname')` ou `pl.col.colname`. +Ce sera selon votre goût :) - **Inégalités** : On peut vouloir garder seulement les lignes qui respectent une certaine condition. -Exemple, filtrer les lignes où la valeur de la colonne `var2` est supérieure à 0 : +Exemple, filtrer les lignes où la valeur de la colonne `var1` est supérieure à 0 : ```{python} -df[df['var2'] >= 0] +df.filter(pl.col('var1') >= 0) ``` -- **Appartenance avec `isin`** : Si on veut filtrer les données basées sur une liste de valeurs possibles, la méthode `isin` est très utile. +- **Appartenance avec `is_in`** : Si on veut filtrer les données basées sur une liste de valeurs possibles, la méthode `is_in` est très utile. Exemple, pour garder uniquement les lignes où la colonne `experiment` a des valeurs 'test' ou 'validation' : ```{python} -df[df['experiment'].isin(['train', 'validation'])] +df.filter(pl.col('experiment').is_in(['train', 'validation'])) ``` -Ces méthodes peuvent être combinées pour créer des conditions plus complexes. Il est aussi possible d'utiliser les opérateurs logiques (`&` pour "et", `|` pour "ou") pour combiner plusieurs conditions. Attention, il faut bien prendre soin d'encadrer chaque condition par des parenthèses lors de la combinaison. +Ces méthodes peuvent être combinées pour créer des conditions plus complexes. +Il est aussi possible d'utiliser les opérateurs logiques (`&` pour "et", `|` pour "ou") pour combiner plusieurs conditions. +Par défaut, les filtres sont considérés comme des "et" : filter(condA, condB) renverra quand condA et condB sont vraies. +**Attention à ne pas oublier les parenthèses pour délimiter les conditions !** -Exemple, sélectionner les lignes où `var2` est supérieur à 0 et `experiment` est égal à 'test' ou 'validation': +Exemple : +- sélectionner les lignes où `var1` est supérieur à 0 **et** `experiment` est égal à 'test' ou 'validation': ```{python} -df[(df['var2'] >= 0) & (df['experiment'].isin(['train', 'validation']))] +df.filter((pl.col("var1") >= 0) & pl.col("experiment").is_in(['train', 'validation'])) +# équivalent à +df.filter(pl.col("var1") >= 0, pl.col("experiment").is_in(['train', 'validation'])) ``` - - - +- sélectionner les lignes où `var1` est supérieur à 0 **ou** `experiment` est égal à 'test' ou 'validation': +```{python} +df.filter((pl.col("var1") >= 0) | pl.col("experiment").is_in(['train', 'validation'])) +``` ## Explorer des données tabulaires -En statistique publique, le point de départ n'est généralement pas la génération manuelle de données, mais plutôt des fichiers tabulaires préexistants. Ces fichiers, qu'ils soient issus d'enquêtes, de bases administratives ou d'autres sources, constituent la matière première pour toute analyse ultérieure. Pandas offre des outils puissants pour importer ces fichiers tabulaires et les explorer en vue de manipulations plus poussées. +En statistique publique, le point de départ n'est généralement pas la génération manuelle de données, mais plutôt des fichiers tabulaires préexistants. +Ces fichiers, qu'ils soient issus d'enquêtes, de bases administratives ou d'autres sources, constituent la matière première pour toute analyse ultérieure. +Polars offre des outils puissants et très rapides pour importer ces fichiers tabulaires et les explorer en vue de manipulations plus poussées. ### Importer et exporter des données -Polars est très sensible au type des données, l'import peut donc parfois être un peu long quand il n'arrive pas à déterminer le type de données de la colonne. -En effet, Polars va traiter chaque colonne comme une série d'un des types qu'il connait. -Les types de données sont détaillés dans la [documentation de Polars](https://docs.pola.rs/api/python/stable/reference/datatypes.html). +Polars est très sensible au format des données, l'import peut donc parfois être un peu long à débuger quand il n'arrive pas à déterminer le format de données de la colonne. +En effet, Polars va traiter chaque colonne comme une série d'un des formats qu'il connaît. +Les formats de données sont détaillés dans la [documentation de Polars](https://docs.pola.rs/api/python/stable/reference/datatypes.html). Ils comprennent principalement: -| Type de données | Type en Polars | Remarques | +| Famille de format | Format Polars | Remarques | | -- | -- | -- | | Caractères | - `pl.String`
- `pl.Utf8` | les données catégorielles (`pl.Categorical`) sont encore peu matures dans Polars.
Il peut donc mieux valoir les traiter simplement comme des caractères usuels. | | Nombres | | | | - entiers | - `pl.Int8`
- `pl.Int16`
- `pl.Int32` ... | | | - numérique | - `pl.Float16`
- `pl.Float32`
- `pl.Float64` | | | Temporelles | - `pl.Date`
- `pl.Datetime`
- `pl.Duration` ... | | -| Structures imbriquées | | - les `pl.Struc` très pratique pour lire des formats imbriqués comme des JSON)| +| Structures imbriquées | | - le format `pl.Struc` très pratique pour lire des formats imbriqués comme des JSON | +| Valeurs manquantes | | Polars traite les valeurs manquantes à part. | + +::: {.callout-caution} +A noter que pour Polars, les types `null` et `nan` sont différents. +`null` est une valeur manquante, quelque soit le type de valeur (caractère, numérique, temporelle, +imbriquée ...). On le déclare avec un `None`. +`NaN`, qui signifie _Not a Number_, est une valeur manquante **numérique** (et non pour les entiers). +Cela signifie que Polars le traite comme un nombre particulier. +On déclare un `NaN` soit en utilisant Numpy `np.nan`, soit une syntaxe de Polars : `float("nan")`. + +Plus de détail sur la [documentation](https://docs.pola.rs/user-guide/expressions/missing-data/#null-and-nan-values). +::: -A noter que pour Polars, null et nan sont différents. +On peut convertir une colonne d'un type à l'autre avec la méthode `cast` en indiquant +dans un dictionnaire le nom de la colonne et le format Polars souhaité. +Par exemple, dans la table `df` définie ci-dessus, Polars a assigné les formats suivants : +```{python} +df.schema +``` +On peut convertir `var1` en caractère et `date` en un format temporel par exemple : + +```{python} +df.cast({"var1":pl.String, "date":pl.Date}) +``` +  #### Importer un fichier CSV Comme nous l'avons vu dans un précédent TP, le format CSV est l'un des formats les plus courants pour stocker des données tabulaires. Nous avons précédemment utilisé la librairie `csv` pour les manipuler comme des fichiers texte, mais ce n'était pas très pratique. Pour rappel, la syntaxe pour lire un fichier CSV et afficher les premières lignes était la suivante : @@ -200,18 +250,16 @@ with open("data/departement2021.csv") as file_in: rows[:5] ``` -Avec Pandas, il suffit d'utiliser la fonction `read_csv()` pour importer le fichier comme un DataFrame, puis la fonction `head()`. +Avec Polars, il suffit d'utiliser la fonction `read_csv()` pour importer le fichier comme un DataFrame, puis la fonction `head()`. ```{python} df_departements = pl.read_csv('data/departement2021.csv') df_departements.head() ``` -Pas possible de faire directement avec un url, pour cela il faut aller chercher le fichier et le lire - -Il est également possible d'importer un fichier CSV directement à partir d'une URL. C'est particulièrement pratique lorsque les données sont régulièrement mises à jour sur un site web et que l'on souhaite accéder à la version la plus récente sans avoir à télécharger manuellement le fichier à chaque fois. Prenons l'exemple d'un fichier CSV disponible sur le site de l'INSEE : le fichier des prénoms, issu des données de l'état civil. -A la différence de Pandas et à la date d'écriture de ce tutoriel, Polars ne dézippe pas encore automatiquement le fichier csv(_cf._ [discussion de cette problématique sur Github](https://github.com/pola-rs/polars/issues/19447)). -Il faut donc faire les petites étapes avant soi-même pour le moment. +A la différence de Pandas et à la date d'écriture de ce tutoriel, Polars ne charge pas directement depuis une URL et ne dézippe pas encore automatiquement le fichier csv (_cf._ [discussion de cette problématique sur Github](https://github.com/pola-rs/polars/issues/19447)). +Il faut donc faire ces étapes soi-même pour le moment grâce aux packages `requests`et `zipfile`. +Prenons l'exemple d'un fichier CSV disponible sur le site de l'INSEE : le fichier des prénoms, issu des données de l'état civil. ```{python} # Téléchargement et stockage du nom du fichier @@ -236,31 +284,38 @@ with ZipFile(file_Path, 'r') as zObject: ``` -For example, here Polars will throw back an error because of data types. It thinks the anais column is an int but then finds a 'XXXX' value +Par exemple, une erreur sera causée ici à cause de types de données incohérentes détectées par Polars. +En regardant le message d'erreur, Polars traite la colonne `anais` comme un entier. +Mais la lecture de la valeur `XXXX` cause une erreur et n'est pas convertible en entier par Polars. + ```{python} df_prenoms_url = pl.read_csv('temp/'+os.listdir('temp')[0], separator=";") ``` -You can set infer_schema=False to cast all columns as string + +Dans ce cas, deux solutions existent : +- On peut dire à Polars de traiter toutes les colonnes comme des caractères avec infer_schema=False ```{python} df_prenoms_url = pl.read_csv('temp/'+os.listdir('temp')[0], separator=";", infer_schema=False) df_prenoms_url ``` -You can also tell Polars to treat the `XXXX` modality as null. -Polars will then infer the types of each columns +- On peut aussi lui dire de traiter la valeur `XXXX` comme une valeur manquante. +Polars va alors assigner des types à chaque colonne qui ne seront pas toutes des caractères. + ```{python} df_prenoms_url = pl.read_csv('temp/'+os.listdir('temp')[0], separator=";", null_values=['XXXX']) df_prenoms_url ``` +Lorsqu'on travaille avec des fichiers CSV, il y a de nombreux arguments optionnels disponibles dans la fonction `read_csv()` qui permettent d'ajuster le processus d'importation en fonction des spécificités du fichier. Ces arguments peuvent notamment permettre de définir un délimiteur spécifique (comme ci-dessus pour le fichier des prénoms), de sauter certaines lignes en début de fichier, ou encore de définir les types de données pour chaque colonne, et bien d'autres. Tous ces paramètres et leur utilisation sont détaillés dans la [documentation officielle](https://docs.pola.rs/api/python/stable/reference/api/polars.read_csv.html#polars.read_csv). + + ```{python} +# Pour nettoyer les fichiers !rm $file_Path !rm temp -rf ``` - -Lorsqu'on travaille avec des fichiers CSV, il y a de nombreux arguments optionnels disponibles dans la fonction `read_csv()` qui permettent d'ajuster le processus d'importation en fonction des spécificités du fichier. Ces arguments peuvent notamment permettre de définir un délimiteur spécifique (comme ci-dessus pour le fichier des prénoms), de sauter certaines lignes en début de fichier, ou encore de définir les types de données pour chaque colonne, et bien d'autres. Tous ces paramètres et leur utilisation sont détaillés dans la [documentation officielle](https://docs.pola.rs/api/python/stable/reference/api/polars.read_csv.html#polars.read_csv). - #### Importer depuis un dictionnaire Comme illustré dans la partie JSON, on peut aussi créer un dataFrame Polars à partir d'un dictionnaire. From fcec38148fa44059a7ebdd9dc45d2a705b422345 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 6 Jan 2026 15:01:04 +0000 Subject: [PATCH 10/92] tidypolars --- source/manipulation/polars/tutorial.qmd | 55 ++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 98dc4f0f..128ca506 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -33,18 +33,42 @@ pour aller plus loin : Ressources : https://ddotta.github.io/awesome-polars/ -tidypolars : https://tidypolars.readthedocs.io/en/latest/ + +::: {.panel-tabset group="polars_vs_tidypolars"}} + +## Polars ```{python} -import tidypolars as tp -df = tp.tibble(name = ['apple', 'banana', 'pear', 'grape']) -print(df.mutate(x = tp.str_extract(tp.col('name'), 'e'))) +import polars as pl ``` +## Tidypolars +Pour celles et ceux qui veulent utiliser des fonctions pressqu'identiques à celles du tidyverse, +il y a le package [tidypolars](https://tidypolars.readthedocs.io/en/latest/). + +Les noms des fonctions dans tidypolars sont presque tous identiques à ceux du tidyverse: +- un DataFrame de Polars devient un tibble chez tidypolars; +- la structure de la création d'un tibble est la même que dans R; +- les méthodes filter, select de Polars restent les mêmes; +- la méthode with_columns de Polars devient mutate ... + +Tidypolars reprend ainsi exactement la syntaxe des principales fonctions de dplyr, tidyr, stringr, lubridate, tidyselect directement dans Python! +La liste complète des fonctions reprises est disponible dans la [documentation](https://tidypolars.readthedocs.io/en/latest/reference.html). + +La seule différence notable entre tidypolars et R est liée aux colonnes, qui sont accessibles par pl.col/tp.col dans polars/tidypolars quand dans R leur nom seul suffit. + +Pour la simplicité du tutoriel, le tutoriel présente le début avec tidypolars mais ensuite utilise uniquement Polars. +Pour plus de détail, allez voir la [documentation](https://tidypolars.readthedocs.io/en/latest/reference.html) ! + ```{python} import polars as pl +import tidypolars as tp + +from tidypolars import col ``` +::: + ## Structures de données @@ -56,6 +80,10 @@ Fondamentalement, un DataFrame consiste en une collection de Series. Cette conca Un DataFrame peut être construit de multiples manières. En pratique, on construit généralement un DataFrame directement à partir de fichiers de données tabulaires (ex : CSV, excel), rarement à la main. On illustrera donc seulement la méthode de construction manuelle la plus usuelle : à partir d'un dictionnaire de données. +::: {.panel-tabset group="polars_vs_tidypolars"} + +## Polars + ```{python} df = pl.DataFrame( data = { @@ -69,6 +97,23 @@ df = pl.DataFrame( df ``` +## Tidypolars + +```{python} + +df = tp.tibble( + var1 = [1.3, 5.6, None, None, 0, None], + experiment = ["test", "train", "test", "train", "train", "validation"], + date = ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-01-05", "2022-01-06"], + sample = "sample1" +) + +df + +``` + +::: + A noter qu'une valeur manquante est indiquée par `None` en Polars. Elle sera ensuite traduite en type Null interne à Polars. @@ -310,12 +355,12 @@ df_prenoms_url Lorsqu'on travaille avec des fichiers CSV, il y a de nombreux arguments optionnels disponibles dans la fonction `read_csv()` qui permettent d'ajuster le processus d'importation en fonction des spécificités du fichier. Ces arguments peuvent notamment permettre de définir un délimiteur spécifique (comme ci-dessus pour le fichier des prénoms), de sauter certaines lignes en début de fichier, ou encore de définir les types de données pour chaque colonne, et bien d'autres. Tous ces paramètres et leur utilisation sont détaillés dans la [documentation officielle](https://docs.pola.rs/api/python/stable/reference/api/polars.read_csv.html#polars.read_csv). - ```{python} # Pour nettoyer les fichiers !rm $file_Path !rm temp -rf ``` + #### Importer depuis un dictionnaire Comme illustré dans la partie JSON, on peut aussi créer un dataFrame Polars à partir d'un dictionnaire. From 39503cfbf14ca49aaea652a2c0d88b1cbd202c3d Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 6 Jan 2026 15:16:03 +0000 Subject: [PATCH 11/92] parquet section --- source/manipulation/polars/tutorial.qmd | 69 +++++++++++++++---------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 128ca506..3d445e68 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -40,6 +40,7 @@ https://ddotta.github.io/awesome-polars/ ## Polars ```{python} import polars as pl +import numpy as np ``` ## Tidypolars @@ -353,7 +354,9 @@ df_prenoms_url = pl.read_csv('temp/'+os.listdir('temp')[0], separator=";", null_ df_prenoms_url ``` -Lorsqu'on travaille avec des fichiers CSV, il y a de nombreux arguments optionnels disponibles dans la fonction `read_csv()` qui permettent d'ajuster le processus d'importation en fonction des spécificités du fichier. Ces arguments peuvent notamment permettre de définir un délimiteur spécifique (comme ci-dessus pour le fichier des prénoms), de sauter certaines lignes en début de fichier, ou encore de définir les types de données pour chaque colonne, et bien d'autres. Tous ces paramètres et leur utilisation sont détaillés dans la [documentation officielle](https://docs.pola.rs/api/python/stable/reference/api/polars.read_csv.html#polars.read_csv). +Lorsqu'on travaille avec des fichiers CSV, il y a de nombreux arguments optionnels disponibles dans la fonction `read_csv()` qui permettent d'ajuster le processus d'importation en fonction des spécificités du fichier. +Ces arguments peuvent notamment permettre de définir un délimiteur spécifique (comme ci-dessus pour le fichier des prénoms), de sauter certaines lignes en début de fichier, ou encore de définir les types de données pour chaque colonne, et bien d'autres. +Tous ces paramètres et leur utilisation sont détaillés dans la [documentation officielle](https://docs.pola.rs/api/python/stable/reference/api/polars.read_csv.html#polars.read_csv). ```{python} # Pour nettoyer les fichiers @@ -371,75 +374,87 @@ from_dict #### Exporter au format CSV -Une fois que les données ont été traitées et modifiées au sein de Pandas, il est courant de vouloir exporter le résultat sous forme de fichier CSV pour le partager, l'archiver ou l'utiliser dans d'autres outils. Pandas offre une méthode simple pour cette opération : `to_csv()`. Supposons par exemple que l'on souhaite exporter les données du DataFrame `df_departements` spécifiques aux cinq départements d'outre-mer. +Une fois que les données ont été traitées et modifiées au sein de Polars, il est courant de vouloir exporter le résultat sous forme de fichier CSV pour le partager, l'archiver ou l'utiliser dans d'autres outils. +Polars offre une méthode simple pour cette opération : `write_csv()`. +Supposons par exemple que l'on souhaite exporter les données du DataFrame `df_departements` spécifiques aux cinq départements d'outre-mer. ```{python} -df_departements_dom = df_departements[df_departements["DEP"].isin(["971", "972", "973", "974", "975"])] -df_departements_dom.to_csv('output/departements2021_dom.csv') +df_departements_dom = df_departements.filter(pl.col("DEP").is_in(["971", "972", "973", "974", "975"])) +df_departements_dom.write_csv('output/departements2021_dom.csv', separator=";") ``` #### Importer un fichier Parquet -Le format Parquet est un autre format pour le stockage de données tabulaires, de plus en plus fréquemment utilisé. Sans entrer dans les détails techniques, le format Parquet présente différentes caractéristiques qui en font un choix privilégié pour le stockage et le traitement de gros volumes de données. En raison de ces avantages, ce format est de plus en plus utilisé pour la mise à disposition de données à l'Insee. Il est donc essentiel de savoir importer et requêter des fichiers Parquet avec Pandas. +Le format Parquet est un autre format pour le stockage de données tabulaires, de plus en plus fréquemment utilisé. +Sans entrer dans les détails techniques, le format Parquet présente différentes caractéristiques qui en font un choix privilégié pour le stockage et le traitement de gros volumes de données. +En raison de ces avantages, ce format est de plus en plus utilisé pour la mise à disposition de données à l'Insee. +Il est donc essentiel de savoir importer et requêter des fichiers Parquet avec Polars. -Importer un fichier Parquet dans un DataFrame Pandas se fait tout aussi facilement que pour un fichier CSV. La fonction se nomme `read_parquet()`. +Importer un fichier Parquet dans un DataFrame Pandas se fait tout aussi facilement que pour un fichier CSV. +La fonction se nomme `read_parquet()`. ```{python} -df_departements = pd.read_parquet('data/departement2021.parquet') +df_departements = pl.read_parquet('data/departement2021.parquet') df_departements.head() ``` #### Exporter au format Parquet -Là encore, tout se passe comme dans le monde des CSV : on utilise la méthode `to_parquet()` pour exporter un DataFrame dans un fichier Parquet. De même, on peut choisir d'exporter ou non l'index, à l'aide du paramètre `index` (qui vaut `True` par défaut). +Là encore, tout se passe comme dans le monde des CSV : on utilise la méthode `write_parquet()` pour exporter un DataFrame dans un fichier Parquet. ```{python} -df_departements_dom = df_departements[df_departements["DEP"].isin(["971", "972", "973", "974", "975"])] -df_departements_dom.to_parquet('output/departements2021_dom.parquet', index=False) +df_departements_dom = df_departements.filter(pl.col("DEP").is_in(["971", "972", "973", "974", "975"])) +df_departements_dom.write_parquet('output/departements2021_dom.parquet') ``` -Une des grandes forces du format Parquet, en comparaison des formats texte comme le CSV, est sa capacité à stocker des méta-données, i.e. des données permettant de mieux comprendre les données contenues dans le fichier. En particulier, un fichier Parquet inclut dans ses méta-données le schéma des données (noms des variables, types des variables, etc.), ce qui en fait un format très adapté à la diffusion de données. Vérifions ce comportement en reprenant le DataFrame que nous avons défini précédemment. +Une des grandes forces du format Parquet, en comparaison des formats texte comme le CSV, est sa capacité à stocker des méta-données, i.e. des données permettant de mieux comprendre les données contenues dans le fichier. +En particulier, un fichier Parquet inclut dans ses méta-données le schéma des données (noms des variables, types des variables, etc.), ce qui en fait un format très adapté à la diffusion de données. +Vérifions ce comportement en reprenant le DataFrame que nous avons défini précédemment. ```{python} -df = pd.DataFrame( +df = pl.DataFrame( data = { - "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var1": [1.3, 5.6, float("nan"), float("nan"), 0, float("nan")], "var2": np.random.randint(-10, 10, 6), "experiment": ["test", "train", "test", "train", "train", "validation"], "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-01-05", "2022-01-06"], "sample": "sample1" - } + }, + schema_overrides={ + "experiment": pl.Categorical, + "date": pl.Date + } ) -df = df.assign( - experiment=pd.Categorical(df["experiment"]), - date=pd.to_datetime(df["date"]) -) ``` -On utilise cette fois deux types de données spécifiques, pour les données catégorielles (`category`) et pour les données temporelles (`datetime`). On verra plus loin dans le tutoriel comment utiliser ces types. Pour l'instant, notons simplement que Pandas stocke ces types dans le schéma des données. +On utilise cette fois deux types de données spécifiques, pour les données catégorielles (`categorical`) et pour les données temporelles (`date`), comme présenté précédemment. +Le format des données est imprimé par Polars dans la sortie : on voit maintenant en +dessous du nom des colonnes que le format des colonnes `experiment` et `date` ont changé. +On verra plus loin dans le tutoriel comment utiliser ces types. ```{python} -df.info() +df ``` Vérifions à présent que l'export et le ré-import de ces données en Parquet préserve le schéma. ```{python} -df.to_parquet("output/df_test_schema.parquet", index=False) -df_test_schema_parquet = pd.read_parquet('output/df_test_schema.parquet') +df.write_parquet("output/df_test_schema.parquet") +df_test_schema_parquet = pl.read_parquet('output/df_test_schema.parquet') -df_test_schema_parquet.info() +df_test_schema_parquet ``` -A l'inverse, un fichier CSV ne contenant par définition que du texte, ne permet pas de préserver ces données. Les variables dont nous avons spécifié le type sont importées comme des strings (type `object` en Pandas). +A l'inverse, un fichier CSV ne contenant par définition que du texte, ne permet pas de préserver ces données. +Les variables dont nous avons spécifié le type sont importées comme des strings (type `object` en Polars). ```{python} -df.to_csv("output/df_test_schema.csv", index=False) -df_test_schema_csv = pd.read_csv('output/df_test_schema.csv') +df.write_csv("output/df_test_schema.csv") +df_test_schema_csv = pl.read_csv('output/df_test_schema.csv') -df_test_schema_csv.info() +df_test_schema_csv ``` ### Visualiser un échantillon des données From 0ca557b3bcc4e46c05ecae0de6a70810cec69e16 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 6 Jan 2026 15:58:15 +0000 Subject: [PATCH 12/92] export/import dictionnaire --- source/manipulation/polars/tutorial.qmd | 64 ++++++++++++++++++++----- 1 file changed, 52 insertions(+), 12 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 3d445e68..b8064213 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -322,11 +322,7 @@ from zipfile import ZipFile # on charge le fichier télécharger et extraction dans un dossier temp/ with ZipFile(file_Path, 'r') as zObject: - - # Extracting all the members of the zip - # into a specific location. - zObject.extractall( - path="temp/") + zObject.extractall(path="temp/") ``` @@ -364,13 +360,6 @@ Tous ces paramètres et leur utilisation sont détaillés dans la [documentation !rm temp -rf ``` -#### Importer depuis un dictionnaire - -Comme illustré dans la partie JSON, on peut aussi créer un dataFrame Polars à partir d'un dictionnaire. -Cela est très utile par exemple quand on récupère les données d'une API. - -from_dicts -from_dict #### Exporter au format CSV @@ -457,6 +446,57 @@ df_test_schema_csv = pl.read_csv('output/df_test_schema.csv') df_test_schema_csv ``` +#### Importer depuis un dictionnaire + +Comme illustré dans le tutoriel [Travailler avec des fichiers CSV et JSON](../csv-json-files/tutorial.qmd), on peut aussi créer un dataFrame Polars à partir d'un dictionnaire. +Cela sera très utile par exemple quand on récupère les données d'une API (_cf._ cours de +[Python pour la data-science](https://pythonds.linogaliana.fr/) et la partie sur les API). + +Les méthodes `from_dict` et `from_dicts` permettent de créer des DataFrames à partir de dictionnaires. + +- `from_dict` prend comme argument un **dictionnaire des colonnes**, de manière similaire à `pl.DataFrame` : +on va écrire par exemple `pl.from_dict({"a": [1, 2], "b": [3, 4]})` +- `from_dicts` par contre prend comme argument une **liste des lignes** : on va écrire par exemple `pl.from_dicts([{"a": 1, "b": 4}, {"a": 2, "b": 5}, {"a": 3, "b": 6}])` + +```{python} +import requests +import json + +response = requests.get("https://data.geopf.fr/geocodage/search?q=comedie&type=street") +``` +Le résultat de la requête est un dictionnaire avec 3 clés, dont la deuxième, 'features', stocke les résultats sous forme d'une liste. +Pour importer directement ce fichier en Polars, on peut utiliser la méthode from_dict ou from_dicts. + +```{python} +df = pl.from_dicts(json.loads(response.text)) +df.head(2) +``` + +On retrouve dans le DataFrame les trois colonnes dont la clé représente le nom de la colonne et la valeur dans le dictionnaire la valeur dans la colonne. +La première et dernière colonnes sont des valeurs constantes au format `pl.String` et les résultats sont stockés dans la colonne `features`. +Cette dernière est au format `pl.Struct`, qui fonctionne de manière similaire à un dictionnaire. + +On peut facilement récupérer le détail des résultats grâce à la méthode `unnest` : + +```{python} +df.select("features").unnest("features") +``` + +#### Autres exports et imports + +- Exporter vers un dictionnaire: + +De manière similaire, Polars permet d'exporter un DataFrame vers un dictionnaire. + + - La méthode `to_dict` permet d'exporter un DataFrame "en format colonne". + L'export sera un seul dictionnaire dont les clés sont les noms des colonnes et + les valeurs les listes des valeurs prises par colonne `{'a':[1, 2, 3], 'b': [3, 2, 1]}`. + - La méthode `to_dicts`permet d'exporter le DataFrame "en format ligne". + L'export sera une liste dont les termes seront les lignes du DataFrame, + représentées à chaque fois par un dictionnaire : `[{'a': 1, 'b': 3}, {'a': 2, 'b': 2}, {'a': 3, 'b': 1}]` + + + ### Visualiser un échantillon des données Lorsqu'on travaille avec des jeux de données volumineux, il est souvent utile de visualiser rapidement un échantillon des données pour avoir une idée de leur structure, de leur format ou encore pour détecter d'éventuels problèmes. Pandas offre plusieurs méthodes pour cela. From 417f81ea5bea76e1ef495e69d063bc0f553a2881 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 6 Jan 2026 16:01:25 +0000 Subject: [PATCH 13/92] depuis/vers pandas --- source/manipulation/polars/tutorial.qmd | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index b8064213..a91bf2e3 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -484,7 +484,7 @@ df.select("features").unnest("features") #### Autres exports et imports -- Exporter vers un dictionnaire: +- **Exporter vers un dictionnaire**: De manière similaire, Polars permet d'exporter un DataFrame vers un dictionnaire. @@ -495,7 +495,10 @@ De manière similaire, Polars permet d'exporter un DataFrame vers un dictionnair L'export sera une liste dont les termes seront les lignes du DataFrame, représentées à chaque fois par un dictionnaire : `[{'a': 1, 'b': 3}, {'a': 2, 'b': 2}, {'a': 3, 'b': 1}]` - +- **Depuis/vers Pandas**: +Polars permet aussi facilement d'exporter et d'importer des DataFrame au format Pandas. +Cela permet de travailler avec Polars et de convertir un DataFrame en Pandas quand un package n'autorise pas l'import depuis Polars. +Il suffit d'utiliser la fonction `pl.from_pandas(df)` et la méthode `df.to_pandas()`. ### Visualiser un échantillon des données From 200b4cb23bd34da88fd004fd0ccdfa8e98a63d03 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 6 Jan 2026 16:19:15 +0000 Subject: [PATCH 14/92] preview --- source/manipulation/polars/tutorial.qmd | 39 ++++++++++++++++--------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index a91bf2e3..fbf8c471 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -479,7 +479,8 @@ Cette dernière est au format `pl.Struct`, qui fonctionne de manière similaire On peut facilement récupérer le détail des résultats grâce à la méthode `unnest` : ```{python} -df.select("features").unnest("features") +df = df.select("features").unnest("features") +df ``` #### Autres exports et imports @@ -497,14 +498,23 @@ De manière similaire, Polars permet d'exporter un DataFrame vers un dictionnair - **Depuis/vers Pandas**: Polars permet aussi facilement d'exporter et d'importer des DataFrame au format Pandas. -Cela permet de travailler avec Polars et de convertir un DataFrame en Pandas quand un package n'autorise pas l'import depuis Polars. +Cela permet de travailler avec Polars et de convertir un DataFrame en Pandas quand un package n'autorise pas l'import depuis Polars. Il suffit d'utiliser la fonction `pl.from_pandas(df)` et la méthode `df.to_pandas()`. ### Visualiser un échantillon des données -Lorsqu'on travaille avec des jeux de données volumineux, il est souvent utile de visualiser rapidement un échantillon des données pour avoir une idée de leur structure, de leur format ou encore pour détecter d'éventuels problèmes. Pandas offre plusieurs méthodes pour cela. +Lorsqu'on travaille avec des jeux de données volumineux, il est souvent utile de visualiser rapidement un échantillon +des données pour avoir une idée de leur structure, de leur format ou encore pour détecter d'éventuels problèmes. +Polars offre plusieurs méthodes pour cela. + +Par défaut, Polars indique les cinq premières et cinq dernières lignes d'un DataFrame et indique la forme (_shape_). + +```{python} +df_departements +``` -La méthode `head()` permet d'afficher les premières lignes du DataFrame. Par défaut, elle retourne les 5 premières lignes, mais on peut spécifier un autre nombre en argument si nécessaire. +La méthode `head()` permet d'afficher les premières lignes du DataFrame. +Par défaut, elle retourne les 5 premières lignes, mais on peut spécifier un autre nombre en argument si nécessaire. ```{python} df_departements.head() @@ -528,26 +538,27 @@ df_departements.sample(n=5) ### Obtenir une vue d'ensemble des données -L'une des premières étapes lors de l'exploration de nouvelles données est de comprendre la structure générale du jeu de données. La méthode `info()` de Pandas offre une vue d'ensemble rapide des données, notamment en termes de types de données, de présence de valeurs manquantes et de mémoire utilisée. - -df.glimpse() - -Par défaut imprime les 5 premières et dernière lignes quand on fait -df +L'une des premières étapes lors de l'exploration de nouvelles données est de comprendre la structure générale du jeu de données. +La méthode `glimpse()` de Polars offre une vue d'ensemble rapide des données, notamment en termes de types de données et affiche les données. ```{python} -df.info() +df.glimpse() ``` Plusieurs éléments d'information clés peuvent être extraits de ce résultat : +- **Taille de la table** : le nombre de ligne et de colonnes sont indiquées + - **schéma** : la liste des colonnes est affichée avec des informations très utiles sur le schéma des données : - - **Non-Null Count** : le nombre de valeurs **non-manquantes** (non `nan`) dans la colonne. Si ce nombre est inférieur au nombre total d'entrées (dans notre cas, 6), cela signifie que la colonne contient des valeurs manquantes. Attention à l'ambiguité possible sur "null" : cela signifie bien les valeurs manquantes, pas les valeurs égales à 0. Ainsi, dans notre cas, le nombre de valeurs "non-null" pour la variable `var1` est 3. + - **Format** : Le format Polars de données de la colonne, par exemple ``pour un format caractère (ou `pl.String`). + Ceka permet de comprendre la nature des informations stockées dans chaque colonne. - - **Dtype** : Le type de données de la colonne, qui permet de comprendre la nature des informations stockées dans chaque colonne. Par exemple, `float64` (nombres réels), `int32` (nombres entiers), `category` (variable catégorielle), `datetime64[ns]` (information temporelle) et `object` (données textuelles ou mixtes). + - **les premières valeurs** : après chaque colonne sont indiquées, à l'horizontale, les premières valeurs de la colonne. + Cela permet de mieux comprendre le schéma du DataFrame. -L'utilisation de `info()` est un moyen rapide et efficace d'obtenir une vue d'ensemble d'un DataFrame, d'identifier rapidement les colonnes contenant des valeurs manquantes et de comprendre la structure des données. +Contrairement à Pandas, cette méthode n'affiche pas les valeurs manquantes. +Pour cela, il faut utiliser les statistiques descriptives. ### Calculer des statistiques descriptives From 9a03290aecccea8d1b2e15c1c1094d49aba572d9 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 6 Jan 2026 16:45:07 +0000 Subject: [PATCH 15/92] missing values --- source/manipulation/polars/tutorial.qmd | 156 ++++++------------------ 1 file changed, 35 insertions(+), 121 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index fbf8c471..7fa884f0 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -562,78 +562,39 @@ Pour cela, il faut utiliser les statistiques descriptives. ### Calculer des statistiques descriptives -En complément des informations renvoyées par la méthode `info()`, on peut vouloir obtenir des statistiques descriptives simples afin de visualiser rapidement les distributions des variables. La méthode `describe()` permet d'avoir une vue synthétique de la distribution des données dans chaque colonne. +En complément des informations renvoyées par la méthode `glimpse()`, on peut vouloir obtenir des +statistiques descriptives simples afin de visualiser rapidement les distributions des variables. +La méthode `describe()` permet d'avoir une vue synthétique de la distribution des données dans chaque colonne. ```{python} df.describe() ``` -Il est à noter que `describe()` ne renvoie des statistiques que pour les colonnes numériques par défaut. Si l'on souhaite inclure des colonnes d'autres types, il est nécessaire de le préciser via l'argument `include`. Par exemple, `df.describe(include='all')` renverra des statistiques pour toutes les colonnes, y compris des métriques comme le nombre unique, la valeur la plus fréquente et la fréquence de la valeur la plus fréquente pour les colonnes non numériques. - -```{python} -df.describe(include='all') -``` - Notons que, là encore, la variable `count` renvoie le nombre de valeurs **non-manquantes** dans chaque variable. - - ## Principales manipulations de données ### Transformer les données -Les opérations de transformation sur les données sont essentielles pour façonner, nettoyer et préparer les données en vue de leur analyse. Les transformations peuvent concerner l'ensemble du DataFrame, des colonnes spécifiques ou encore des lignes spécifiques. - -#### Transformer un DataFrame - -Pour transformer un DataFrame complet (ou un sous-DataFrame), il est possible d'utiliser des fonctions vectorisées, qui permettent d'appliquer rapidement une opération à l'ensemble des éléments du DataFrame. Cela inclut un certain nombre de méthodes disponibles pour les `Series`, mais aussi les fonctions mathématiques de `NumPy`, etc. - -Par exemple, passer chaque valeur numérique d'un DataFrame à la puissance 2 : - -```{python} -df = pd.DataFrame( - data = { - "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], - "var2": np.random.randint(-10, 10, 6), - } -) - -df ** 2 -``` - -ou les passer en valeur absolue : - -```{python} -np.abs(df) -``` +Les opérations de transformation sur les données sont essentielles pour façonner, nettoyer et préparer les données en vue de leur analyse. +Les transformations peuvent concerner l'ensemble du DataFrame, des colonnes spécifiques ou encore des lignes spécifiques. -Certaines méthodes, disponibles pour les `Series`, peuvent aussi être utilisées pour transformer un DataFrame complet. Par exemple, la bien utile méthode [replace()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.replace.html), qui permet de remplacer toutes les occurences d'une valeur donnée par une autre valeur. Par exemple, supposons que la valeur 0 dans la colonne `var1` indique en fait une erreur de mesure. Il serait préférable de la remplacer par une valeur manquante. +#### Transformer les colonnes -```{python} -df.replace(0, np.nan) -``` +En équivalent de mutate du tidyverse ou du replace de pandas, Polars utilise with_columns. +Le fonctionnement est similaire au mutate du tidyverse. +Il permet ainsi de modifier des valeurs de colonne, d'effectuer des opérations etc. -::: {.callout-warning title="Assignation ou méthodes *in place* (en place) ?"} -Dans l'exemple précédent, l'application de la méthode [replace()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.replace.html) ne modifie pas directement le DataFrame. Pour que la modifiction soit persistente, une première possibilité est d'assigner le résultat à un objet : +La structure pl.when(pl.col.foo > 2).then(1).otherwise(1 + pl.col.bar).alias("val") -```{python} -df = df.replace(0, np.nan) -``` +Deux types d'expression différents : +- avec alias +- plus similaire au tidyverse, avec assignation. -Une seconde possibilité est, lorsque les méthodes le proposent, d'utiliser l'argument `inplace`. Lorsque `inplace=True`, l'opération est effectuée "en place", et le DataFrame est donc modifié directement. - -```{python} -df.replace(0, np.nan, inplace=True) -``` - -En pratique, il est préférable de limiter les opérations `inplace`. Elles ne favorisent pas la reproductibilité des analyses, dans la mesure où la ré-exécution d'une même cellule va donner à chaque fois des résultats différents. -::: - -#### Transformer les colonnes - -Dans certains cas, on ne va pas vouloir appliquer les transformations à l'ensemble des données, mais à des variables spécifiques. Les transformations qui sont possibles à l'échelle du DataFrame (fonctions vectorisées, méthodes comme [replace()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.replace.html), etc.) restent naturellement possibles à l'échelle d'une colonne. +Attention, les caractères simple sont assimilés aux valeurs des colonnes. +Pour insérer un caractère, utiliser pl.lit. ```{python} df = pd.DataFrame( @@ -671,64 +632,18 @@ df['var2'] = df['var2'].astype(int) df.info() ``` +#### Renommer des colonnes + Une autre opération fréquente est le renommage d'une ou plusieurs colonnes. Pour cela, on peut utiliser la méthode [rename()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.rename.html), à laquelle on passe un dictionnaire qui contient autant de couples clé-valeur que de variables à renommer, et dans lequel chaque couple clé-valeur est de la forme `'ancien_nom': 'nouveau_nom'`. ```{python} df.rename(columns={'var2': 'age'}) ``` -Enfin, on peut souhaiter supprimer du DataFrame des colonnes qui ne sont pas ou plus utiles à l'analyse. Pour cela, on utilise la méthode [drop()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.drop.html), à laquelle on passe soit un string (nom d'une colonne si l'on souhaite n'en supprimer qu'une seule) ou une liste de noms de colonne à supprimer. - -```{python} -df.drop(columns=['var1']) -``` - -#### Transformer les lignes -En statistiques, on applique généralement des tranformations faisant intervenir une ou plusieurs colonnes. Néanmoins, dans certains cas, il est nécessaire d'appliquer des transformations au niveau des lignes. Pour cela, on peut utiliser la méthode [apply()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.apply.html) de Pandas, appliquée à l'axe des lignes (`axis=1`). Illustrons son fonctionnement avec un cas simple. Pour cela, on génère d'abord des données. - -```{python} -df = pd.DataFrame( - data = { - "var1": [1, 5, 9, 13], - "var2": [3, 7, 11, 15], - "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04"], - } -) - -df.head() -``` - -On applique maintenant la fonction `apply()` au DataFrame afin de calculer une nouvelle variable qui est la somme des deux existantes. - -```{python} -df['sum_row'] = df.apply(lambda row: row['var1'] + row['var2'], axis=1) - -df.head() -``` - -::: {.callout-tip title="Les fonctions lambda"} -Une fonction `lambda` est une petite fonction anonyme. Elle peut prendre n'importe quel nombre d'arguments, mais ne peut avoir qu'une seule expression. Dans l'exemple ci-dessus, la fonction `lambda` prend une ligne en argument et renvoie la somme des colonnes `var1` et `var2` pour cette ligne. - -Les fonctions `lambda` permettent de définir simplement des fonctions "à la volée", sans devoir leur donner un nom. Dans notre exemple, cela aurait été parfaitement équivalent au code suivant : - -```{python} -def sum_row(row): - return row['var1'] + row['var2'] - -df['sum_row'] = df.apply(sum_row, axis=1) -``` - -::: - -Bien que `apply()` offre une grande flexibilité, elle n'est pas la méthode la plus efficiente, notamment pour de grands jeux de données. Les opérations vectorisées sont toujours préférables car elles traitent les données en bloc plutôt que ligne par ligne. Dans notre cas, il aurait été bien entendu préférable de créer notre variable en utilisant des opérations sur les colonnes. - -```{python} -df['sum_row_vect'] = df['var1'] + df['var2'] - -df.head() -``` +#### Fonctions complexes +map_element Néanmoins, on peut se retrouver dans certains (rares) cas où une opération ne peut pas être facilement vectorisée ou où la logique est complexe. Supposons par exemple que l'on souhaite combiner les valeurs de plusieurs colonnes en fonction de certaines conditions. ```{python} @@ -837,38 +752,37 @@ Le chaînage de méthodes permet de combiner plusieurs opérations en une seule Cela favorise également un style de programmation fonctionnel où les données passent à travers une chaîne de transformations de manière fluide. ::: -#### Effets sur l'index - -Il est intéressant de noter les effets du processus d'agrégation sur l'index du DataFrame. Le dernier exemple ci-dessus l'illustre bien : les groupes, i.e. les modalités de la variable utilisée pour effectuer l'agrégation, deviennent les valeurs de l'index. - -On peut vouloir réutiliser cette information dans des analyses ultérieures, et donc la vouloir comme une colonne. Il suffit pour cela de réinitialiser l'index avec la méthode `reset_index()`. - -```{python} -df_agg = df.groupby('experiment').agg({'var1': 'mean', 'var2': 'count'}) -df_agg.reset_index() -``` - ### Traiter les valeurs manquantes Les valeurs manquantes sont une réalité courante dans le traitement des données réelles et peuvent survenir pour diverses raisons, telles que des non-réponses à un questionnaire, des erreurs de saisie, des pertes de données lors de la transmission ou simplement parce que l'information n'est pas applicable. Pandas offre plusieurs outils pour gérer les valeurs manquantes. #### Représentation des valeurs manquantes -Dans Pandas, les valeurs manquantes sont généralement représentées par `np.nan`, qui est un marqueur spécial fourni par la bibliothèque `NumPy`. S'il est préférable d'utiliser cet objet pour dénoter les valeurs manquantes, notons que l'objet `None` de `Python` est également compris comme une valeur manquante par `Pandas`. - -Vérifions cette propriété. Pour identifier où se trouvent les valeurs manquantes, on utilise la fonction `isna()` qui retourne un DataFrame booléen indiquant `True` là où les valeurs sont `NaN`. +On peut tout d'abord traiter les valeurs manquantes avec les méthodes associées. +Pour rappel, en Polars, les valeurs `NaN` et `null` sont différentes, alors qu'en Pandas elles sont traitées de manière similaire. +Seule `Null` est considéré par défaut comme une valeur manquante. +Vérifions cette propriété. +Pour identifier où se trouvent les valeurs manquantes, on utilise la fonction `is_null()` ou `is_nan()` appliquée à une colonne. ```{python} -df = pd.DataFrame( +df = pl.DataFrame( data = { - "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var1": [1.3, 5.6, np.nan, 1.4, None, np.nan], "var2": np.random.randint(-10, 10, 6), "experiment": ["test", "train", "test", None, "train", "validation"], "sample": "sample1" } ) +df.with_columns( + var1_na=pl.col("var1").is_nan(), + var1_null=pl.col("var1").is_null() +) +``` -df.isna() +On peut à l'inverse éliminer les lignes qui comportent une valeur manquante ou un `NaN` : +```{python} +print(df.drop_nans()) +print(df.drop_nulls()) ``` #### Calculs sur des colonnes contenant des valeurs manquantes From 3b6d554320820c605fdedb5bad22c2e4f1606168 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 20 Jan 2026 15:56:58 +0000 Subject: [PATCH 16/92] with_columns --- source/manipulation/polars/tutorial.qmd | 57 ++++++++++++++++++++----- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 7fa884f0..fbb4e905 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -304,7 +304,14 @@ df_departements.head() ``` A la différence de Pandas et à la date d'écriture de ce tutoriel, Polars ne charge pas directement depuis une URL et ne dézippe pas encore automatiquement le fichier csv (_cf._ [discussion de cette problématique sur Github](https://github.com/pola-rs/polars/issues/19447)). -Il faut donc faire ces étapes soi-même pour le moment grâce aux packages `requests`et `zipfile`. +Soit on utilise la fonction idoine de `pandas` et après on transforme le dataframe en `polars` facilement grâce à la fonction `pl.from_pandas`. + +```{python} +url = "https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip" +pl.from_pandas(pd.read_csv(url, delimiter=";")) +``` + +Si l'on veut éviter une dépendance à `pandas` juste pour cette opération, il faut donc faire ces étapes soi-même pour le moment grâce aux packages `requests`et `zipfile`. Prenons l'exemple d'un fichier CSV disponible sur le site de l'INSEE : le fichier des prénoms, issu des données de l'état civil. ```{python} @@ -464,6 +471,7 @@ import json response = requests.get("https://data.geopf.fr/geocodage/search?q=comedie&type=street") ``` + Le résultat de la requête est un dictionnaire avec 3 clés, dont la deuxième, 'features', stocke les résultats sous forme d'une liste. Pour importer directement ce fichier en Polars, on peut utiliser la méthode from_dict ou from_dicts. @@ -552,7 +560,7 @@ Plusieurs éléments d'information clés peuvent être extraits de ce résultat - **schéma** : la liste des colonnes est affichée avec des informations très utiles sur le schéma des données : - **Format** : Le format Polars de données de la colonne, par exemple ``pour un format caractère (ou `pl.String`). - Ceka permet de comprendre la nature des informations stockées dans chaque colonne. + Cela permet de comprendre la nature des informations stockées dans chaque colonne. - **les premières valeurs** : après chaque colonne sont indiquées, à l'horizontale, les premières valeurs de la colonne. Cela permet de mieux comprendre le schéma du DataFrame. @@ -583,23 +591,52 @@ Les transformations peuvent concerner l'ensemble du DataFrame, des colonnes spé #### Transformer les colonnes -En équivalent de mutate du tidyverse ou du replace de pandas, Polars utilise with_columns. -Le fonctionnement est similaire au mutate du tidyverse. +En équivalent de `mutate` du tidyverse ou du `replace` de pandas, Polars utilise `with_columns`. +Le fonctionnement est similaire au `mutate` du tidyverse. Il permet ainsi de modifier des valeurs de colonne, d'effectuer des opérations etc. -La structure pl.when(pl.col.foo > 2).then(1).otherwise(1 + pl.col.bar).alias("val") -Deux types d'expression différents : -- avec alias -- plus similaire au tidyverse, avec assignation. -Attention, les caractères simple sont assimilés aux valeurs des colonnes. +La fonction with_columns fonctionne de deux manières différentes : + + 1. en utilisant une syntaxe plus proche du SQL et de Python, grâce à la méthode `.alias()`. + Par exemple, si l'on veut définir la colonne `b` comme la colonne `a` divisée par 2 , on va utiliser la formule suivante : df.with_columns((pl.col("a")/2).alias("b") + 2. plus similaire au tidyverse, en assignant les variables selon la structure : b=pl.col("a")/2 +1. +::: {.callout-tip} +La structure pl.when est très pratique et équivaut à la structure ifelse en R. + +Par exemple, si je veux définir la colonne val à partir de la colonne foo selon le schéma : si foo > 2 : val = 1, sinon val = 1 + bar, cela s'écrite en polars : + + +```{python} +df = pl.DataFrame({'foo':np.random.randint(-10, 10, 6), 'bar': np.random.randint(5, 15, 6)}) +df.with_columns( + pl.when(pl.col('foo') > 2).then(1).otherwise(1 + pl.col('bar')).alias("val") +) +``` + +::: + +::: {.callout-warning} + +Attention, en Polars, les caractères simples sont assimilés aux colonnes. Pour insérer un caractère, utiliser pl.lit. +```{python} +df = pl.DataFrame({'foo':np.random.randint(-10, 10, 6), 'bar': np.random.randint(5, 15, 6)}) +df.with_columns( + val="foo", + this_is_foo=pl.lit("foo") +) +``` + +::: + ```{python} df = pd.DataFrame( data = { - "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var1": [1.3, 5.6, 7.8, np.nan, 0, np.nan], "var2": np.random.randint(-10, 10, 6), } ) From 64a4607bfe2ed4b5430ba9966f7974da99af8002 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 20 Jan 2026 16:44:24 +0000 Subject: [PATCH 17/92] with cast and data transformation --- source/manipulation/polars/tutorial.qmd | 63 +++++++++++++++---------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index fbb4e905..9018b65e 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -160,8 +160,8 @@ Si vous voulez transformer un dataframe en une série Polars, il faut utiliser l ```{python} print(f'En passant par select.to_series(), la table \n {df.select('var1').to_series()} \n est de type {type(df.select('var1').to_series())}') print(f'En passant par df[var1], la table \n {df['var1']} \n est aussi de type {type(df['var1'])}') - ``` + ::: @@ -184,6 +184,7 @@ La principale différence tient au nommage des colonnes. En effet, le nom de chaque colonne doit être entourée d'un sélecteur `pl.col`. Quand en R on écrirait + ```r df |> filter(var1>=0) @@ -202,6 +203,7 @@ Ce sera selon votre goût :) - **Inégalités** : On peut vouloir garder seulement les lignes qui respectent une certaine condition. Exemple, filtrer les lignes où la valeur de la colonne `var1` est supérieure à 0 : + ```{python} df.filter(pl.col('var1') >= 0) ``` @@ -210,6 +212,7 @@ df.filter(pl.col('var1') >= 0) - **Appartenance avec `is_in`** : Si on veut filtrer les données basées sur une liste de valeurs possibles, la méthode `is_in` est très utile. Exemple, pour garder uniquement les lignes où la colonne `experiment` a des valeurs 'test' ou 'validation' : + ```{python} df.filter(pl.col('experiment').is_in(['train', 'validation'])) ``` @@ -221,6 +224,7 @@ Par défaut, les filtres sont considérés comme des "et" : filter(condA, condB) Exemple : - sélectionner les lignes où `var1` est supérieur à 0 **et** `experiment` est égal à 'test' ou 'validation': + ```{python} df.filter((pl.col("var1") >= 0) & pl.col("experiment").is_in(['train', 'validation'])) # équivalent à @@ -228,6 +232,7 @@ df.filter(pl.col("var1") >= 0, pl.col("experiment").is_in(['train', 'validation' ``` - sélectionner les lignes où `var1` est supérieur à 0 **ou** `experiment` est égal à 'test' ou 'validation': + ```{python} df.filter((pl.col("var1") >= 0) | pl.col("experiment").is_in(['train', 'validation'])) ``` @@ -270,15 +275,17 @@ On peut convertir une colonne d'un type à l'autre avec la méthode `cast` en in dans un dictionnaire le nom de la colonne et le format Polars souhaité. Par exemple, dans la table `df` définie ci-dessus, Polars a assigné les formats suivants : + ```{python} df.schema ``` + On peut convertir `var1` en caractère et `date` en un format temporel par exemple : ```{python} df.cast({"var1":pl.String, "date":pl.Date}) ``` -  + #### Importer un fichier CSV Comme nous l'avons vu dans un précédent TP, le format CSV est l'un des formats les plus courants pour stocker des données tabulaires. Nous avons précédemment utilisé la librairie `csv` pour les manipuler comme des fichiers texte, mais ce n'était pas très pratique. Pour rappel, la syntaxe pour lire un fichier CSV et afficher les premières lignes était la suivante : @@ -600,11 +607,27 @@ Il permet ainsi de modifier des valeurs de colonne, d'effectuer des opérations La fonction with_columns fonctionne de deux manières différentes : 1. en utilisant une syntaxe plus proche du SQL et de Python, grâce à la méthode `.alias()`. - Par exemple, si l'on veut définir la colonne `b` comme la colonne `a` divisée par 2 , on va utiliser la formule suivante : df.with_columns((pl.col("a")/2).alias("b") - 2. plus similaire au tidyverse, en assignant les variables selon la structure : b=pl.col("a")/2 -1. + 2. plus similaire au tidyverse, en assignant les variables avec une équation + +Par exemple, si l'on veut définir la colonne `b` comme la colonne `a` divisée par 2 , on va utiliser la formule suivante : + +```{python} +df = pl.DataFrame({'a':np.random.randint(-10, 10, 6), 'b': np.random.randint(5, 15, 6)}) + +df.with_columns( + # Première méthode : + (pl.col("a")/2).alias("b"), + (np.abs(pl.col("a"))).alias("abs_a"), + # Ou l'autre méthode : + b2=pl.col("a")/2, + abs_a2=np.abs(pl.col("a")) +) + +``` + + ::: {.callout-tip} -La structure pl.when est très pratique et équivaut à la structure ifelse en R. +La structure `pl.when` est très pratique et équivaut à la structure `ifelse` en R. Par exemple, si je veux définir la colonne val à partir de la colonne foo selon le schéma : si foo > 2 : val = 1, sinon val = 1 + bar, cela s'écrite en polars : @@ -633,40 +656,32 @@ df.with_columns( ::: -```{python} -df = pd.DataFrame( - data = { - "var1": [1.3, 5.6, 7.8, np.nan, 0, np.nan], - "var2": np.random.randint(-10, 10, 6), - } -) - -np.abs(df["var2"]) -``` +La méthodes fill_null permet de remplacer les valeurs manquante ```{python} -df["var1"].replace(0, np.nan) +df.fill_null(strategy='zero') ``` -Mais il existe d'autres transformations que l'on applique généralement au niveau d'une ou de quelques colonnes. Par exemple, lorsque le schéma n'a pas été bien reconnu à l'import, il peut arriver que des variables numériques soient définies comme des string (type `object` en Pandas). + +Mais il existe d'autres transformations que l'on applique généralement au niveau d'une ou de quelques colonnes. Par exemple, lorsque le schéma n'a pas été bien reconnu à l'import, il peut arriver que des variables numériques soient définies comme des string. ```{python} -df = pd.DataFrame( +df = pl.DataFrame( data = { - "var1": [1.3, 5.6, np.nan], + "var1": [1.3, 5.6, None], "var2": ["1", "5", "18"], } ) -df.info() +df.glimpse() ``` -Dans ce cas, on peut utiliser la méthode `astype` pour convertir la colonne dans le type souhaité. +Dans ce cas, on peut utiliser la méthode `cast` pour convertir la colonne dans le type souhaité en spécifiant avec un format de dictionnaire les colonnes à modifier . La clé LE dictionnaire est écrit sous le `{'nom de la colonne':'type Polars à appliquer'}`. Les types sont décrits plus haut et dans la [documentation de Polars](https://docs.pola.rs/api/python/stable/reference/datatypes.html). ```{python} -df['var2'] = df['var2'].astype(int) +df = df.cast({'var2':pl.Int32}) -df.info() +df.glimpse() ``` #### Renommer des colonnes From fcc565ae2b3cef5dd82e0260817d6faf7e541fe2 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 20 Jan 2026 16:47:33 +0000 Subject: [PATCH 18/92] with rename --- source/manipulation/polars/tutorial.qmd | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 9018b65e..fc630294 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -686,16 +686,15 @@ df.glimpse() #### Renommer des colonnes -Une autre opération fréquente est le renommage d'une ou plusieurs colonnes. Pour cela, on peut utiliser la méthode [rename()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.rename.html), à laquelle on passe un dictionnaire qui contient autant de couples clé-valeur que de variables à renommer, et dans lequel chaque couple clé-valeur est de la forme `'ancien_nom': 'nouveau_nom'`. +Une autre opération fréquente est le renommage d'une ou plusieurs colonnes. Pour cela, on peut utiliser la méthode [rename()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.rename.html#polars.DataFrame.rename), à laquelle on passe un dictionnaire qui contient autant de couples clé-valeur que de variables à renommer, et dans lequel chaque couple clé-valeur est de la forme `'ancien_nom': 'nouveau_nom'`. ```{python} -df.rename(columns={'var2': 'age'}) +df.rename({'var2': 'age'}) ``` #### Fonctions complexes -map_element Néanmoins, on peut se retrouver dans certains (rares) cas où une opération ne peut pas être facilement vectorisée ou où la logique est complexe. Supposons par exemple que l'on souhaite combiner les valeurs de plusieurs colonnes en fonction de certaines conditions. ```{python} From f396233af9ef33c47b7d11860031ed5c033ec461 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 21 Jan 2026 09:40:08 +0000 Subject: [PATCH 19/92] update renaming --- source/manipulation/polars/tutorial.qmd | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index fc630294..8ed89901 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -676,7 +676,9 @@ df = pl.DataFrame( df.glimpse() ``` -Dans ce cas, on peut utiliser la méthode `cast` pour convertir la colonne dans le type souhaité en spécifiant avec un format de dictionnaire les colonnes à modifier . La clé LE dictionnaire est écrit sous le `{'nom de la colonne':'type Polars à appliquer'}`. Les types sont décrits plus haut et dans la [documentation de Polars](https://docs.pola.rs/api/python/stable/reference/datatypes.html). +Dans ce cas, on peut utiliser la méthode `cast` pour convertir la colonne dans le type souhaité en spécifiant avec un dictionnaire les colonnes à modifier. +Le dictionnaire est écrit sous le format `{'nom de la colonne 1':'type Polars à appliquer', 'nom de la colonne 2':'type Polars à appliquer'}`. +Les types sont décrits plus haut et dans la [documentation de Polars](https://docs.pola.rs/api/python/stable/reference/datatypes.html). ```{python} df = df.cast({'var2':pl.Int32}) From 9dd963b5d6f14d30e8066130c4b32cc9dde40d5e Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 21 Jan 2026 10:22:34 +0000 Subject: [PATCH 20/92] complex functions and sorting --- source/manipulation/polars/tutorial.qmd | 48 ++++++++++++++++--------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 8ed89901..9679126a 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -697,30 +697,41 @@ df.rename({'var2': 'age'}) #### Fonctions complexes -Néanmoins, on peut se retrouver dans certains (rares) cas où une opération ne peut pas être facilement vectorisée ou où la logique est complexe. Supposons par exemple que l'on souhaite combiner les valeurs de plusieurs colonnes en fonction de certaines conditions. +Néanmoins, on peut se retrouver dans certains (rares) cas où une opération ne peut pas être facilement vectorisée ou où la logique est complexe. +Supposons par exemple que l'on souhaite calculer la variation annuelle du PIB par pays dans une table comportant les pays et les années. ```{python} -def combine_columns(row): - if row['var1'] > 6: - return str(row['var2']) - else: - return str(row['var2']) + "_" + row['date'] +# Données fictives de PIB par pays +df = pl.DataFrame({ + 'country': ['France', 'France', 'France', 'Germany', 'Germany', 'Germany', 'UK', 'UK', 'UK'], + 'year': [2019, 2020, 2021, 2019, 2020, 2021, 2019, 2020, 2021], + 'gdp': [21.43, 20.21, 22.54, 1.73, 1.66, 1.78, 2.83, 2.71, 2.99] +}) -df['combined_column'] = df.apply(combine_columns, axis=1) +# On définit une fonction dite User-defined-function (UDF) pour calculer la croissance par pays +def calculate_percentage_change(group): + group = group.sort('year') + group = group.with_columns( + ((pl.col('gdp') - pl.col('gdp').shift(1)) / pl.col('gdp').shift(1) * 100).alias('percentage_change') + ) + return group + +# On applique la fonction en utilisant map_groups +print(df.group_by('country').map_groups(calculate_percentage_change)) -df ``` + ### Trier les valeurs -Le tri des données est particulièrement utile pour l'exploration et la visualisation de données. Avec Pandas, on utilise la méthode [sort_values()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.sort_values.html) pour trier les valeurs d'un DataFrame selon une ou plusieurs colonnes. +Le tri des données est particulièrement utile pour l'exploration et la visualisation de données. Avec Polars, on utilise la méthode [sort()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.sort.html#polars.DataFrame.sort) pour trier les valeurs d'un DataFrame selon une ou plusieurs colonnes. ```{python} -df = pd.DataFrame( +df = pl.DataFrame( data = { - "var1": [1, 5, 9, 13], - "var2": [3, 7, 11, 15], - "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04"], + "var1": [1, 9, 9, 14, 13], + "var2": [3, 7, 11, 15, 4], + "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-04-02"], } ) @@ -730,17 +741,20 @@ df Pour trier les valeurs selon une seule colonne, il suffit de passer le nom de la colonne en paramètre. ```{python} -df.sort_values(by='var1') +df.sort(by='var1') ``` -Par défaut, le tri est effectué dans l'ordre croissant. Pour trier les valeurs dans un ordre décroissant, il suffit de paramétrer `ascending=False`. +Par défaut, le tri est effectué dans l'ordre croissant. Pour trier les valeurs dans un ordre décroissant, il suffit de paramétrer `descending=True`. ```{python} -df.sort_values(by='var1', ascending=False) +df.sort(by='var1', descending=True) ``` -Si on souhaite trier le DataFrame sur plusieurs colonnes, on peut fournir une liste de noms de colonnes. On peut également choisir de trier de manière croissante pour certaines colonnes et décroissante pour d'autres. +Si on souhaite trier le DataFrame sur plusieurs colonnes, on peut fournir une liste de noms de colonnes. On peut également choisir de trier de manière croissante pour certaines colonnes et décroissante pour d'autres en spécifiant les booléns dans une liste. +```{python} +df.sort(by=['var1', 'var2'], descending=[True, True]) +``` ### Agréger des données From 1730fc601074fc0d191f89732b54fd1c6e99e6c7 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 21 Jan 2026 10:26:44 +0000 Subject: [PATCH 21/92] nans en None --- source/manipulation/polars/tutorial.qmd | 38 ++++++++++++------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 9679126a..1ccacaa9 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -762,9 +762,9 @@ df.sort(by=['var1', 'var2'], descending=[True, True]) L'agrégation des données est un processus dans lequel les données vont être ventilées en groupes selon certains critères, puis agrégées selon une fonction d'agrégation appliquée indépendamment à chaque groupe. Cette opération est courante lors de l'analyse exploratoire ou lors du prétraitement des données pour la visualisation ou la modélisation statistique. ```{python} -df = pd.DataFrame( +df = pl.DataFrame( data = { - "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var1": [1.3, 5.6, None, None, 0, None], "var2": np.random.randint(-10, 10, 6), "experiment": ["test", "train", "test", "train", "train", "validation"], "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-01-05", "2022-01-06"], @@ -775,12 +775,12 @@ df = pd.DataFrame( df.head() ``` -#### L'opération `groupBy` +#### L'opération `group_by` -La méthode `groupBy` de Pandas permet de diviser le DataFrame en sous-ensembles selon les valeurs d'une ou plusieurs colonnes, puis d'appliquer une fonction d'agrégation à chaque sous-ensemble. Elle renvoie un objet de type `DataFrameGroupBy` qui ne présente pas de grand intérêt en soi, mais constitue l'étape intermédiaire indispensable pour pouvoir ensuite appliquer une ou plusieurs fonction(s) d'agrégation aux différents groupes. +La méthode `group_by` de Polars permet de diviser le DataFrame en sous-ensembles selon les valeurs d'une ou plusieurs colonnes, puis d'appliquer une fonction d'agrégation à chaque sous-ensemble. Elle renvoie un objet de type `DataFrameGroupBy` qui ne présente pas de grand intérêt en soi, mais constitue l'étape intermédiaire indispensable pour pouvoir ensuite appliquer une ou plusieurs fonction(s) d'agrégation aux différents groupes. ```{python} -df.groupby('experiment') +df.group_by('experiment') ``` #### Fonctions d'agrégation @@ -921,7 +921,7 @@ Les données textuelles nécessitent souvent un nettoyage et une préparation av ```{python} df = pd.DataFrame( data = { - "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var1": [1.3, 5.6, None, None, 0, None], "var2": np.random.randint(-10, 10, 6), "experiment": ["test", "train", "test", "test", "train", "validation"], "sample": [" sample1", "sample1", "sample2", " sample2 ", "sample2 ", "sample1"] @@ -971,7 +971,7 @@ Pour convertir une variable au format `category`, on utilise la méthode `astype ```{python} df = pd.DataFrame( data = { - "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var1": [1.3, 5.6, None, None, 0, None], "var2": np.random.randint(-10, 10, 6), "experiment": ["test", "train", "test", None, "train", "validation"], } @@ -1516,7 +1516,7 @@ df_prenoms.info() print(df_prenoms[df_prenoms["preusuel"].isna()]) prop_rares = df_prenoms.groupby("preusuel")["nombre"].sum()["_PRENOMS_RARES"] / df_prenoms["nombre"].sum() print(prop_rares) # ~ 2 % de la base -df_prenoms = df_prenoms.replace('_PRENOMS_RARES', np.nan) +df_prenoms = df_prenoms.replace('_PRENOMS_RARES', None) ``` @@ -1538,7 +1538,7 @@ df_prenoms = df_prenoms.replace('_PRENOMS_RARES', np.nan) ```{python} prop_xxxx = df_prenoms.groupby("annais")["nombre"].sum()["XXXX"] / df_prenoms["nombre"].sum() print(prop_xxxx) # ~ 1 % de la base -df_prenoms = df_prenoms.replace('XXXX', np.nan) +df_prenoms = df_prenoms.replace('XXXX', None) ``` @@ -2349,7 +2349,7 @@ A DataFrame can be constructed in multiple ways. In practice, we generally build ```{python} df = pd.DataFrame( data = { - "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var1": [1.3, 5.6, None, np.nan, 0, np.nan], "var2": np.random.randint(-10, 10, 6), "experiment": ["test", "train", "test", "train", "train", "validation"], "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-01-05", "2022-01-06"], @@ -2573,7 +2573,7 @@ One of the major strengths of the Parquet format, compared to text formats like ```{python} df = pd.DataFrame( data = { - "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var1": [1.3, 5.6, None, None, 0, None], "var2": np.random.randint(-10, 10, 6), "experiment": ["test", "train", "test", "train", "train", "validation"], "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-01-05", "2022-01-06"], @@ -2690,7 +2690,7 @@ For example, raising each numeric value in a DataFrame to the power of 2: ```{python} df = pd.DataFrame( data = { - "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var1": [1.3, 5.6, None, None, 0, None], "var2": np.random.randint(-10, 10, 6), } ) @@ -2707,20 +2707,20 @@ np.abs(df) Some methods available for `Series` can also be used to transform an entire DataFrame. For example, the very useful [replace()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.replace.html) method, which allows replacing all occurrences of a given value with another value. For example, suppose the value 0 in the `var1` column actually indicates a measurement error. It would be preferable to replace it with a missing value. ```{python} -df.replace(0, np.nan) +df.replace(0, None) ``` ::: {.callout-warning title="Assignment or in-place methods?"} In the previous example, applying the [replace()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.replace.html) method does not directly modify the DataFrame. To make the modification persistent, one possibility is to assign the result to an object: ```{python} -df = df.replace(0, np.nan) +df = df.replace(0, None) ``` A second possibility is, when methods offer it, to use the `inplace` argument. When `inplace=True`, the operation is performed "in place", and the DataFrame is therefore directly modified. ```{python} -df.replace(0, np.nan, inplace=True) +df.replace(0, None, inplace=True) ``` In practice, it is better to limit `inplace` operations. They do not favor the reproducibility of analyses, as the re-execution of the same cell will give different results each time. @@ -2733,7 +2733,7 @@ In some cases, we will not want to apply transformations to the entire data but ```{python} df = pd.DataFrame( data = { - "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var1": [1.3, 5.6, None, None, 0, None], "var2": np.random.randint(-10, 10, 6), } ) @@ -2742,7 +2742,7 @@ np.abs(df["var2"]) ``` ```{python} -df["var1"].replace(0, np.nan) +df["var1"].replace(0, None) ``` But there are other transformations that are generally applied at the level of one or a few columns. For example, when the schema has not been properly recognized upon import, it may happen that numeric variables are defined as strings (type `object` in Pandas). @@ -2750,7 +2750,7 @@ But there are other transformations that are generally applied at the level of o ```{python} df = pd.DataFrame( data = { - "var1": [1.3, 5.6, np.nan], + "var1": [1.3, 5.6, None], "var2": ["1", "5", "18"], } ) @@ -2877,7 +2877,7 @@ Aggregating data is a process where the data is broken down into groups based on ```{python} df = pd.DataFrame( data = { - "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], + "var1": [1.3, 5.6, None, None, 0, None], "var2": np.random.randint(-10, 10, 6), "experiment": ["test", "train", "test", "train", "train", "validation"], "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-01-05", "2022-01-06"], From b138858d5a8511e581385d817481694ea42dc358 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 21 Jan 2026 12:41:55 +0000 Subject: [PATCH 22/92] aggregation --- source/manipulation/polars/tutorial.qmd | 66 ++++++++++++++++++++----- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 1ccacaa9..ea821516 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -777,7 +777,7 @@ df.head() #### L'opération `group_by` -La méthode `group_by` de Polars permet de diviser le DataFrame en sous-ensembles selon les valeurs d'une ou plusieurs colonnes, puis d'appliquer une fonction d'agrégation à chaque sous-ensemble. Elle renvoie un objet de type `DataFrameGroupBy` qui ne présente pas de grand intérêt en soi, mais constitue l'étape intermédiaire indispensable pour pouvoir ensuite appliquer une ou plusieurs fonction(s) d'agrégation aux différents groupes. +La méthode `group_by` de Polars permet de diviser le DataFrame en sous-ensembles selon les valeurs d'une ou plusieurs colonnes, puis d'appliquer une fonction d'agrégation à chaque sous-ensemble. Elle renvoie un objet de type `dataframe.group_by` qui ne présente pas de grand intérêt en soi, mais constitue l'étape intermédiaire indispensable pour pouvoir ensuite appliquer une ou plusieurs fonction(s) d'agrégation aux différents groupes. ```{python} df.group_by('experiment') @@ -785,38 +785,80 @@ df.group_by('experiment') #### Fonctions d'agrégation -Une fois les données groupées, on peut appliquer des fonctions d'agrégation pour obtenir un résumé statistique. Pandas intègre un certain nombre de ces fonctions, dont la liste complète est détaillée dans la [documentation](https://pandas.pydata.org/docs/user_guide/groupby.html#built-in-aggregation-methods). Voici quelques exemples d'utilisation de ces méthodes. +Une fois les données groupées, on peut appliquer des fonctions d'agrégation pour obtenir un résumé statistique. Polars intègre un certain nombre de ces fonctions qui fonctionnent sur la table de donnée entière, *cf.* [liste complète dans la documentation](https://docs.pola.rs/api/python/stable/reference/dataframe/aggregation.html) ou sur des sous-ensembles de la table, en utilisant `group_by`, *cf.* [liste complète dans la documentation](https://docs.pola.rs/api/python/stable/reference/dataframe/group_by.html). -Par exemple, compter le nombre d'occurrences dans chaque groupe. + +Voici quelques exemples d'utilisation de ces méthodes avec `group_by`. + +Par défaut, Polars appliquera les fonctions usuelles à l'ensemble des colonnes. +Pour spécifier une colonne, il faut utiliser la fonction `agg`, détaillée plus bas. + +- Par exemple, compter le nombre d'occurrences dans chaque groupe. ```{python} -df.groupby('experiment').size() +df.group_by('experiment').count() ``` -Calculer la somme d'une variable par groupe. +- Calculer la somme d'une variable par groupe. ```{python} -df.groupby('experiment')['var1'].sum() +df.group_by('experiment').agg(pl.col('var2').sum()) ``` -Ou encore compter le nombre de valeurs unique d'une variable par groupe. Les possibilités sont nombreuses. +::: {.callout-tip} +Polars a aussi introduit des wrappers utiles pour les fonctions principales d'aggregation sum, std, count, quantile, cum_count, cum_sum, max, min, median, sqrt. + +Pour ces fonctions, on peut les appeler directement en faisant `pl.sum('var2')` et non `pl.col('var2').sum()`. + +Par exemple : +```{.python} +df.group_by('experiment').agg(pl.sum('var2')) +``` + +est identique à : +```{.python} +df.group_by('experiment').agg(pl.col('var2').sum()) +``` + +::: + +- Ou encore compter le nombre de valeurs unique d'une variable par groupe. Les possibilités sont nombreuses. ```{python} -# Pour le nombre de valeurs uniques de 'var2' dans chaque groupe -df.groupby('experiment')['var2'].nunique() +# Pour le nombre de valeurs uniques dans chaque groupe +df.group_by('experiment').agg(pl.col('var2').n_unique()) ``` -Lorsqu'on souhaite appliquer plusieurs fonctions d'agrégation à la fois ou des fonctions personnalisées, on utilise la méthode `agg`. Cette méthode accepte une liste de fonctions ou un dictionnaire qui associe les noms des colonnes aux fonctions à appliquer. Cela permet d'appliquer plus finement les fonctions d'agrégation. +Lorsqu'on souhaite appliquer plusieurs fonctions d'agrégation à la fois ou des fonctions personnalisées, on utilise la méthode `agg`. Cette méthode fonctionne selon une structure similaire à `with_columns`. Elle permet de définir plus finement les fonctions d'agrégation. ```{python} -df.groupby('experiment').agg({'var1': 'mean', 'var2': 'count'}) +df.group_by('experiment').agg( + pl.col('var1').mean().alias('mean_var1'), + pl.col('var2').count().alias('count_var2') +) ``` +::: {.callout-tip} +Au lieu d'utiliser la méthode alias, on peut utiliser l'attribut `name` de Polars qui renvoie le nom de la colonne et les fonctions associées. Plus de détails sont présentés dans la [documentation officielle](https://docs.pola.rs/api/python/stable/reference/expressions/name.html). + +Par exemple, définir `.alias('mean_var1')` est l'équivalent de `.name.prefix('mean_')` +::: + ::: {.callout-note title="Le chaînage de méthodes"} -Les exemples précédents illustrent un concept important en Pandas : le chaînage de méthodes. Ce terme désigne la possibilité d'enchaîner les transformations appliquées à un DataFrame en lui appliquant à la chaîne des méthodes. A chaque méthode appliquée, un DataFrame intermédiaire est créé (mais non assigné à une variable), qui devient l'input de la méthode suivante. +Les exemples précédents illustrent un concept important en Polars : le chaînage de méthodes. Ce terme désigne la possibilité d'enchaîner les transformations appliquées à un DataFrame en lui appliquant à la chaîne des méthodes, comme le `pipe` du tidyverse. A chaque méthode appliquée, un DataFrame intermédiaire est créé (mais non assigné à une variable), qui devient l'input de la méthode suivante. Le chaînage de méthodes permet de combiner plusieurs opérations en une seule expression de code. Cela peut améliorer l'efficacité en évitant les assignations intermédiaires et en rendant le code plus fluide et plus facile à lire. Cela favorise également un style de programmation fonctionnel où les données passent à travers une chaîne de transformations de manière fluide. + +```{.python} +subset_df = ( + df + .filter(pl.col('sample') == "sample1", pl.col("date") >= '2022-01-02') + .drop('sample') + .glimpse() +) +``` + ::: ### Traiter les valeurs manquantes From 9bca87e205fd2d4dc973935eb4363df7deb7e6cc Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 21 Jan 2026 13:18:19 +0000 Subject: [PATCH 23/92] missing values and NaNs --- source/manipulation/polars/tutorial.qmd | 34 +++++++++++++++---------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index ea821516..622f424d 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -869,15 +869,22 @@ Les valeurs manquantes sont une réalité courante dans le traitement des donné On peut tout d'abord traiter les valeurs manquantes avec les méthodes associées. Pour rappel, en Polars, les valeurs `NaN` et `null` sont différentes, alors qu'en Pandas elles sont traitées de manière similaire. -Seule `Null` est considéré par défaut comme une valeur manquante. + +| | **Type `null`** | **Type `NaN`** | +|--|--|--| +| **Signification** | Seule `Null` est considéré par défaut comme une valeur manquante et est l'unique type de valeur manquante dans Polars (que le type original soit temporel, numérique, un charactère ...). | `NaN` représente à l'inverse des valeurs numériques erronées, comme le résultat d'une division par 0. | +| **Comment les créer ?** | Les valeurs manquantes peuvent être crées simplement avec `None`. | Pour créer une valeur `NaN`, valable uniquement pour les types numériques, on peut utiliser `np.nan` de NumPy ou `float("nan")` de Polars. | +| Comportement dans Polars | Ces valeurs sont en général **ignorées**. | Ces valeurs **se propagent**. | + Vérifions cette propriété. Pour identifier où se trouvent les valeurs manquantes, on utilise la fonction `is_null()` ou `is_nan()` appliquée à une colonne. + ```{python} df = pl.DataFrame( data = { - "var1": [1.3, 5.6, np.nan, 1.4, None, np.nan], - "var2": np.random.randint(-10, 10, 6), + "var1": [1.3, 5.6, 2.2, 1.4, None, 1.7], + "var2": np.append(np.random.randint(-10, 10, 5), np.nan), "experiment": ["test", "train", "test", None, "train", "validation"], "sample": "sample1" } @@ -889,6 +896,7 @@ df.with_columns( ``` On peut à l'inverse éliminer les lignes qui comportent une valeur manquante ou un `NaN` : + ```{python} print(df.drop_nans()) print(df.drop_nulls()) @@ -896,36 +904,34 @@ print(df.drop_nulls()) #### Calculs sur des colonnes contenant des valeurs manquantes -Lors de calculs statistiques, les valeurs manquantes sont généralement ignorées. Par exemple, la méthode `.mean()` calcule la moyenne des valeurs non manquantes. +Lors de calculs statistiques, les valeurs nulles sont généralement ignorées en Polars. Par exemple, la méthode `.mean()` calcule la moyenne des valeurs non manquantes. ```{python} df['var1'].mean() ``` -En revanche, les calculs faisant intervenir plusieurs colonnes n'ignorent pas toujours les valeurs manquantes et peuvent souvent donner des résultats en `NaN`. +En revanche, les valeurs 'Not a Number', ou `NaN`, ont plutôt tendance à se propager. ```{python} -df['var3'] = df['var1'] + df['var2'] - -df +df['var2'].mean() ``` #### Suppression des valeurs manquantes -La méthode `dropna()` permet de supprimer les lignes (`axis=0`) ou les colonnes (`axis=1`) contenant des valeurs manquantes. Par défaut, toute ligne contenant au moins une valeur manquante est supprimée. +Les méthodes `drop_nulls()` et `drop_nans()` permettent de supprimer les lignes contenant des valeurs manquantes ou des NaN. + +Par défaut, toute ligne contenant au moins une valeur manquante ou NaN est supprimée. ```{python} -df.dropna() +df.drop_nans() ``` -En modifiant le paramètre `axis`, on peut demander à ce que toute colonne contenant au moins une valeur manquante soit supprimée. +Si l'on spécifie une liste de colonnes, seules les lignes comportant une valeur manquante ou NaN de cette colonne seront supprimées. ```{python} -df.dropna(axis=1) +df.drop_nulls(['var1']) ``` -Enfin, le paramètre `how` définit la modalité de supression. Par défaut, une ligne ou colonne est supprimée lorsqu'au moins une valeur est manquante (`how=any`), mais il est possible de ne supprimer la ligne/colonne que lorsque toutes les valeurs sont manquantes (`how=all`). - #### Remplacement des valeurs manquantes Pour gérer les valeurs manquantes dans un DataFrame, une approche commune est l'imputation, qui consiste à remplacer les valeurs manquantes par d'autres valeurs. La méthode `fillna()` permet d'effectuer cette opération de différentes manières. Une première possibilité est le remplacement par une valeur constante. From cc9a836edac2d1d82be927d131be8f9759520b2f Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 21 Jan 2026 13:34:34 +0000 Subject: [PATCH 24/92] fill_null and fill_nan --- source/manipulation/polars/tutorial.qmd | 26 +++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 622f424d..9294bdef 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -934,32 +934,46 @@ df.drop_nulls(['var1']) #### Remplacement des valeurs manquantes -Pour gérer les valeurs manquantes dans un DataFrame, une approche commune est l'imputation, qui consiste à remplacer les valeurs manquantes par d'autres valeurs. La méthode `fillna()` permet d'effectuer cette opération de différentes manières. Une première possibilité est le remplacement par une valeur constante. +Pour gérer les valeurs manquantes dans un DataFrame, une approche commune est l'imputation, qui consiste à remplacer les valeurs manquantes par d'autres valeurs. La méthode [`fill_null()`](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.fill_null.html) permet d'effectuer cette opération de différentes manières dans toute la table de donnée. + +- Une première possibilité est le remplacement par une valeur constante. ```{python} -df['var1'].fillna(value=0) +df.fill_null(value=0) ``` ::: {.callout-warning title="Changement de représentation des valeurs manquantes"} Il peut parfois être tentant de changer la manifestation d'une valeur manquante pour des raisons de visibilité, par exemple en la remplaçant par une chaîne de caractères : ```{python} -df['var1'].fillna(value="MISSING") +df.fill_null(value="MISSING") ``` -En pratique, cette façon de faire n'est pas recommandée. Il est en effet préférable de conserver la convention standard de `Pandas` (l'utilisation des `np.nan`), d'abord pour des questions de standardisation des pratiques qui facilitent la lecture et la maintenance du code, mais également parce que la convention standard est optimisée pour la performance et les calculs à partir de données contenant des valeurs manquantes. +En pratique, cette façon de faire n'est pas recommandée. Il est en effet préférable de conserver la convention standard de `Polars` (l'utilisation des `null`), d'abord pour des questions de standardisation des pratiques qui facilitent la lecture et la maintenance du code, mais également parce que la convention standard est optimisée pour la performance et les calculs à partir de données contenant des valeurs manquantes. ::: -Une autre méthode d'imputation fréquente est d'utiliser une valeur statistique, comme la moyenne ou la médiane de la variable. +La méthide `fill_null()` de Polars propose 4 méthodes pré-définies pour remplacer les valeurs manquantes par l'argument `strategy`: +- toute valeur constante indiquée (`strategy=None`, argument par défaut); +- soit des 0, soit des 1 (`strategy="zero"`, `strategy="one"` :); +- en reportant la valeur précédente (`strategy=‘forward’`) ou la valeur suivante (`strategy=‘backward’`) de la colonne ; +- en indiquant le minimum, le maximum ou la médiane de la colonne (`strategy=‘min’`, `strategy=‘max’`, `strategy=‘mean’`). + +Si l'on veut remplacer uniquement les valeurs manquantantes d'une colonne en Polars, il est plus utile d'utiliser la méthode `with_columns()` en utilisant l'agilité des sélecteurs de Polars. ```{python} -df['var1'].fillna(value=df['var1'].mean()) +df.with_columns( + pl.col(pl.NUMERIC_DTYPES).fill_null(strategy="mean") +) ``` +"TO DO" les sélecteurs dans Polars + ::: {.callout-warning title="Biais d'imputation"} Remplacer les valeurs manquantes par une valeur constante, telle que zéro, la moyenne ou la médiane, peut être problématique. Si les données ne sont pas manquantes au hasard (*Missing Not At Random* - *MNAR*), cela peut introduire un biais dans l'analyse. Les variables *MNAR* sont des variables dont la probabilité d'être manquantes est liée à leur propre valeur ou à d'autres variables dans les données. Dans de tels cas, une imputation plus sophistiquée peut être nécessaire pour minimiser les distorsions. Nous en verrons un exemple en exercice de fin de tutoriel. ::: +De manière similaire, la méthode `fill_nan()` permet de remplacer les valeurs numériques NaN par toute valeur indiquée. + ### Traiter les données de types spécifiques #### Données textuelles From 3718aebfdb7548f4e84a14df311157b011440143 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 21 Jan 2026 14:01:44 +0000 Subject: [PATCH 25/92] string operations --- source/manipulation/polars/tutorial.qmd | 55 ++++++++++++++++++------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 9294bdef..a7403601 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -27,6 +27,9 @@ Parler de : - lazy eval - unnest +"TO DO" - Polars Séries +"TO DO" les sélecteurs dans Polars + pour aller plus loin : - interconnection avec duckDB pour des requêtes en SQL @@ -966,7 +969,6 @@ df.with_columns( ) ``` -"TO DO" les sélecteurs dans Polars ::: {.callout-warning title="Biais d'imputation"} Remplacer les valeurs manquantes par une valeur constante, telle que zéro, la moyenne ou la médiane, peut être problématique. Si les données ne sont pas manquantes au hasard (*Missing Not At Random* - *MNAR*), cela peut introduire un biais dans l'analyse. Les variables *MNAR* sont des variables dont la probabilité d'être manquantes est liée à leur propre valeur ou à d'autres variables dans les données. Dans de tels cas, une imputation plus sophistiquée peut être nécessaire pour minimiser les distorsions. Nous en verrons un exemple en exercice de fin de tutoriel. @@ -978,50 +980,71 @@ De manière similaire, la méthode `fill_nan()` permet de remplacer les valeurs #### Données textuelles -Les données textuelles nécessitent souvent un nettoyage et une préparation avant l'analyse. Pandas fournit via la librairie de méthodes `str` un ensemble d'opérations vectorisées qui rendent la préparation des données textuelles à la fois simple et très efficace. Là encore, les possibilités sont multiples et détaillées dans la [documentation](https://pandas.pydata.org/docs/user_guide/text.html). Nous présentons ici les méthodes les plus fréquemment utilisées dans l'analyse de données. +Les données textuelles nécessitent souvent un nettoyage et une préparation avant l'analyse. +Polars fournit via la librairie de méthodes `str` un ensemble d'opérations vectorisées qui rendent la préparation des données textuelles à la fois simple et très efficace. +La méthode `str` s'applique aux séries Polars. +Là encore, les possibilités sont multiples et détaillées dans la [documentation](https://docs.pola.rs/api/python/stable/reference/series/string.html). +Nous présentons ici les méthodes les plus fréquemment utilisées dans l'analyse de données. ```{python} -df = pd.DataFrame( +df = pl.DataFrame( data = { "var1": [1.3, 5.6, None, None, 0, None], "var2": np.random.randint(-10, 10, 6), "experiment": ["test", "train", "test", "test", "train", "validation"], - "sample": [" sample1", "sample1", "sample2", " sample2 ", "sample2 ", "sample1"] + "sample": [" sample1", "sample1 ", " sample2 ", " sample2 ", "sample2 ", "sample1"] } ) df ``` -Une première opération fréquente consiste à extraire certains caractères d'une chaîne. On utilise pour cela la fonction (à la syntaxe un peu particulière) `str[n:]` Par exemple, si l'on veut extraire le dernier caractère de la variable `sample` afin de ne retenir que le chiffre de l'échantillon. +Une première opération fréquente consiste à extraire certains caractères d'une chaîne. +Par exemple, si l'on veut extraire le dernier caractère de la variable `sample` afin de ne retenir que le chiffre de l'échantillon. +Un petit tour par la [documentation](https://docs.pola.rs/api/python/stable/reference/series/string.html) montre que la méthode `tail()` est notre gagnant. ```{python} -df["sample_n"] = df["sample"].str[-1:] +df.with_columns( + sample_n = pl.col('sample').str.tail(1) +) -df ``` -Le principe était le bon, mais la présence d'espaces superflus dans nos données textuelles (qui ne se voyaient pas à la visualisation du DataFrame !) a rendu l'opération plus difficile que prévue. C'est l'occasion d'introduire la famille de méthode `strip` (`.str.strip()`, `.str.lstrip()` et `.str.rstrip()`) qui respectivement retirent les espaces superflus des deux côtés ou d'un seul. +Le principe était le bon, mais la présence d'espaces superflus dans nos données textuelles (qui ne se voyaient pas à la visualisation du DataFrame !) a rendu l'opération plus difficile que prévue. +C'est l'occasion d'introduire la famille de méthode `strip` (`.str.strip_chars()`, `.str.strip_chars_start()` et `.str.strip_chars_end()`) qui respectivement retirent les espaces superflus (ou tout caractère indiqué) des deux côtés ou d'un seul. ```{python} -df["sample"] = df["sample"].str.strip() -df["sample_n"] = df["sample"].str[-1:] - -df +( + df + .with_columns( + sample = pl.col('sample').str.strip_chars() + ) + .with_columns( + sample_n = pl.col('sample').str.tail(1) + ) +) ``` -On peut également vouloir filtrer un DataFrame en fonction de la présence ou non d'une certaine chaîne (ou sous-chaîne) de caractères. On utilise pour cela la méthode `.str.contains()`. +::: {.callout-note} +Remarquez la présence de deux `with_columns()` et non d'un seul. +C'est parce que Polars étant optimisé, il effectue les opérations sur `with_columns` en parallèle. +Ainsi, si l'on ne le fait pas de manière séquentielle, il ne prend pas en compte le fait qu'on enlève les espace superflus dans 'sample' à la première ligne avant d'en extraire le dernier caractère. +::: + +On peut également vouloir filtrer un DataFrame en fonction de la présence ou non d'une certaine chaîne (ou sous-chaîne) de caractères. +On utilise pour cela la méthode `.str.contains()`. ```{python} -df[df['experiment'].str.contains('test')] +df.filter(pl.col('experiment').str.contains('test')) ``` Enfin, on peut vouloir remplacer une chaîne (ou sous-chaîne) de caractères par une autre, ce que permet la méthode `str.replace()`. ```{python} -df['experiment'] = df['experiment'].str.replace('validation', 'val') +df.with_columns( + experiment = pl.col('experiment').str.replace('validation', 'val') +) -df ``` #### Données catégorielles From 420a73ccb14756e1fe89d8c33252ea9a76830aac Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 21 Jan 2026 14:36:41 +0000 Subject: [PATCH 26/92] with categories --- source/manipulation/polars/tutorial.qmd | 29 +++++++++++++------------ 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index a7403601..05dda6f9 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -1049,12 +1049,19 @@ df.with_columns( #### Données catégorielles -Les données catégorielles sont des variables qui contiennent un nombre restreint de modalités. A l'instar de `R` avec la notion de `factor`, Pandas a un type de données spécial, `category`, qui est utile pour représenter des données catégorielles de manière plus efficace et plus informative. Les données catégorielles sont en effet optimisées pour certains types de données et peuvent accélérer les opérations comme le groupement et le tri. Elles sont également utiles pour la visualisation, car elles permettent d'assurer que les catégories sont affichées dans un ordre cohérent et logique. +Les données catégorielles sont des variables qui contiennent un nombre restreint de modalités. +A l'instar de `R` avec la notion de `factor`, Polars a un type de données spécial, `Categorical`, qui peut être utilisé pour représenter des données catégorielles. + +Ce type de données est cependant délicat à gérer en Polars et, en général, on préfèrera travailler avec des données de type caractère. + +En effet, les méthodes usuelles pour renommer des catégories, dissocier son nom et sa représentation, réarranger l'ordre dans laquelle les catégories sont visualisées sont encore très largement perfectibles (voire inexistantes :o). + +Si l'on veut quand même avoir la base, on peut convertir une variable au format `Categorical`, on peut directement utiliser la méthode `cast()`. +Polars va alors inférer le schéma de la catégorie et le stocker dans un objet de type `Categories`. -Pour convertir une variable au format `category`, on utilise la méthode `astype()`. ```{python} -df = pd.DataFrame( +df = pl.DataFrame( data = { "var1": [1.3, 5.6, None, None, 0, None], "var2": np.random.randint(-10, 10, 6), @@ -1065,25 +1072,19 @@ print(df.dtypes) ``` ```{python} -df['experiment'] = df['experiment'].astype('category') - +df = df.with_columns(pl.col("experiment").cast(pl.Categorical)) print(df.dtypes) ``` -Cette conversion nous donne accès à quelques méthodes bien pratiques, spécifiques au traitement des variables catégorielles. Il peut par exemple être utile de renommer les catégories pour des raisons de clarté ou de standardisation. +Les `Categories` ont un certain nombre de méthodes, tout comme les données textuelles, présentées dans la [documentation](https://docs.pola.rs/api/python/stable/reference/series/categories.html). -```{python} -df['experiment'] = df['experiment'].cat.rename_categories({'test': 'Test', 'train': 'Train', 'validation': 'Validation'}) -df -``` - -Parfois, l'ordre des catégories est significatif, et on peut vouloir le modifier. En particulier dans le cadre de la visualisation, car les modalités seront par défaut affichées dans l'ordre spécifié. +On pourra alors par exemple accéder aux catégories avec la méthode `Series.cat.get_categories()` ```{python} -df_cat = df['experiment'].cat.reorder_categories(['Test', 'Train', 'Validation'], ordered=True) -df.groupby("experiment").mean().plot(kind='bar') +df['experiment'].cat.get_categories() ``` + #### Données temporelles Les données temporelles sont souvent présentes dans les données tabulaires afin d'identifier temporellement les observations recueillies. Pandas offre des fonctionnalités pour manipuler ces types de données, notamment grâce au type `datetime64` qui permet une manipulation précise des dates et des heures. From 0544639b4162c7fbbf8c167c49ff8b539e06e766 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 21 Jan 2026 15:25:16 +0000 Subject: [PATCH 27/92] with temporal column --- source/manipulation/polars/tutorial.qmd | 71 ++++++++++++++++++------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 05dda6f9..1ef34d33 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -1087,14 +1087,15 @@ df['experiment'].cat.get_categories() #### Données temporelles -Les données temporelles sont souvent présentes dans les données tabulaires afin d'identifier temporellement les observations recueillies. Pandas offre des fonctionnalités pour manipuler ces types de données, notamment grâce au type `datetime64` qui permet une manipulation précise des dates et des heures. +Les données temporelles sont souvent présentes dans les données tabulaires afin d'identifier temporellement les observations recueillies. +Polars offre des fonctionnalités pour manipuler ces types de données, notamment grâce au type `pl.Datetime` qui permet une manipulation précise des dates et des heures. ```{python} -df = pd.DataFrame( +df = pl.DataFrame( data = { "var1": [1, 5, 9, 13], "var2": [3, 7, 11, 15], - "date": ["2022-01-01", "2022-01-02", "2023-01-01", "2023-01-02"], + "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04"], "sample": ["sample1", "sample1", "sample2", "sample2"] } ) @@ -1102,39 +1103,72 @@ df = pd.DataFrame( df.dtypes ``` -Pour manipuler les données temporelles, il est nécessaire de convertir les chaînes de caractères en objets `datetime`. Pandas le fait via la fonction `to_datetime()`. +Pour manipuler les données temporelles, il est nécessaire de convertir les chaînes de caractères en colonne de type temporel sous Polars. +Il existe 4 types temporels de colonnes en Polars, comme rappelé dans la [documentation](https://docs.pola.rs/api/python/stable/reference/datatypes.html): -```{python} -df['date'] = pd.to_datetime(df['date']) +- le type [`pl.Datetime`](https://docs.pola.rs/api/python/stable/reference/api/polars.datatypes.Date.html#polars.datatypes.Datetime) pour un format date et heure ; +- le type [`pl.Date`](https://docs.pola.rs/api/python/stable/reference/api/polars.datatypes.Date.html#polars.datatypes.Date) pour un format Date seul ; +- le type [`pl.Duration`](https://docs.pola.rs/api/python/stable/reference/api/polars.datatypes.Date.html#polars.datatypes.Duration) pour une durée ; +- le type [`pl.Time`](https://docs.pola.rs/api/python/stable/reference/api/polars.datatypes.Date.html#polars.datatypes.Time) pour une heure. + +Polars transforme des données textuelles en données temporelles fait via les méthodes [`str.to_date()`](https://docs.pola.rs/api/python/stable/reference/series/api/polars.Series.str.to_datetime.html#polars.Series.str.to_date), [`str.to_datetime()`](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.Expr.str.to_datetime.html), [`str.to_time()`](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.Expr.str.to_time.html), [`str.strptime()`](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.Expr.str.strptime.html). + +Au cas d'espèce, la méthode `str.to_date()` remplit parfaitement notre besoin. +```{python} +df = df.with_columns( + date = pl.col('date').str.to_date("%Y-%m-%d") +) df.dtypes ``` -Une fois converties, les dates peuvent être formatées, comparées et utilisées dans des calculs. En particulier, Pandas comprend à présent l'"ordre" des dates présentes dans les données, et permet donc le filtrage sur des périodes données. +Une fois converties, les dates peuvent être formatées, comparées et utilisées dans des calculs. +Il faudra cependant bien penser à traduire les dates d'un format textuel à un format temporel. +Par exemple, pour filter des données, on devra spécifier les bornes en appelant les fonctions dédiées de Polars ou du module `datetime`. ```{python} -df[(df['date'] >= "2022-01-01") & (df['date'] < "2022-01-03")] +df.filter(pl.col('date') >= pl.date(2022, 1, 1), pl.col('date') < pl.date(2022, 1, 3)) +``` + +```{python} +from datetime import datetime +df.filter(pl.col('date') >= datetime.strptime("2022-01-01", "%Y-%m-%d"), pl.col('date') < datetime.strptime("2022-01-03", "%Y-%m-%d")) ``` -On peut également vouloir réaliser des filtrages moins précis, faisant intervenir l'année ou le mois. Pandas permet d'extraire facilement des composants spécifiques de la date, comme l'année, le mois, le jour, l'heure, etc. +On peut également vouloir réaliser des filtrages moins précis, faisant intervenir l'année ou le mois. +Polars comprend toute une série de méthode sur les données temporelles, présentées dans la [documentation](https://docs.pola.rs/api/python/stable/reference/series/temporal.html). +Elles permettent d'extraire facilement des composants spécifiques de la date, comme l'année, le mois, le jour, l'heure, etc. ```{python} -df['year'] = df['date'].dt.year -df['month'] = df['date'].dt.month -df['day'] = df['date'].dt.day +df = df.with_columns( + year = pl.col('date').dt.year(), + month = pl.col('date').dt.month(), + day = pl.col('date').dt.day() +) + +df.filter(pl.col('year')==2022) -df[df['year'] == 2023] ``` -Enfin, les calculs faisant intervenir des dates deviennent possible. On peut ajouter ou soustraire des périodes temporelles à des dates, et les comparer entre elles. Les fonctions utilisées sont issues de `Pandas`, mais sont très semblables dans leur fonctionnement à celles du module [time](https://docs.python.org/fr/3/library/time.html) de Python. +Dans ce cas précis, on peut utiliser plus finement les propriétés de la méthode `filter()` et avoir le même résultat en faisant directement `df.filter(pl.col('date').dt.year() == 2022)`. + +Enfin, les calculs faisant intervenir des dates deviennent possible. +On peut ajouter ou soustraire des périodes temporelles à des dates, et les comparer entre elles. +Les fonctions utilisées sont issues de `Polars`, mais sont très semblables dans leur fonctionnement à celles du module [datetime](https://docs.python.org/fr/3/library/datetime.html#module-datetime) de Python. On peut par exemple ajouter des intervalles de temps, ou bien calculer des écarts à une date de référence. -```{python} -df['date_plus_one'] = df['date'] + pd.Timedelta(days=1) -df['date_diff'] = df['date'] - pd.to_datetime('2022-01-01') +::: {.callout-note} +Par défaut, les différences de temps sont indiquées dans une unité temporelle. +Si l'on veut transformer une durée en un nombre, il faut utiliser les méthodes `Series.dt.total_...`. -df +::: + +```{python} +df.with_columns( + date = pl.col("date") + pl.duration(days=1), + date_diff = (pl.col('date') - pl.date(2022, 1, 1)).dt.total_days() +) ``` ### Joindre des tables @@ -1146,6 +1180,7 @@ Dans le cadre d'une analyse de données, il est courant de vouloir combiner diff La concaténation verticale de tables se fait à l'aide de la fonction `concat()` de Pandas. ```{python} + df1 = pd.DataFrame( data = { "var1": [1, 5], From 69222c6bcc9491827c14697bcd9e6877a50f1750 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 21 Jan 2026 16:05:30 +0000 Subject: [PATCH 28/92] with joining dataframes --- source/manipulation/polars/tutorial.qmd | 94 ++++++++++++++++--------- 1 file changed, 62 insertions(+), 32 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 1ef34d33..a1b18e2b 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -1173,15 +1173,17 @@ df.with_columns( ### Joindre des tables -Dans le cadre d'une analyse de données, il est courant de vouloir combiner différentes sources de données. Cette combinaison peut se faire verticalement (un DataFrame par dessus l'autre), par exemple lorsque l'on souhaite combiner deux millésimes d'une même enquête afin de les analyser conjointement. La combinaison peut également se faire horizontalement (côte à côte) selon une ou plusieurs clé(s) de jointure, souvent dans le but d'enrichir une source de données à partir d'une autre source portant sur les mêmes unités statistiques. +Dans le cadre d'une analyse de données, il est courant de vouloir combiner différentes sources de données. +Cette combinaison peut se faire verticalement (un DataFrame par dessus l'autre), par exemple lorsque l'on souhaite combiner deux millésimes d'une même enquête afin de les analyser conjointement. +La combinaison peut également se faire horizontalement (côte à côte) selon une ou plusieurs clé(s) de jointure, souvent dans le but d'enrichir une source de données à partir d'une autre source portant sur les mêmes unités statistiques. #### Concaténer des tables -La concaténation verticale de tables se fait à l'aide de la fonction `concat()` de Pandas. +La concaténation verticale de tables se fait à l'aide de la fonction [`concat()`](https://docs.pola.rs/api/python/stable/reference/api/polars.concat.html#polars.concat) de Polars. ```{python} -df1 = pd.DataFrame( +df1 = pl.DataFrame( data = { "var1": [1, 5], "var2": [3, 7], @@ -1190,90 +1192,118 @@ df1 = pd.DataFrame( } ) -df2 = pd.DataFrame( +df2 = pl.DataFrame( data = { "var1": [9, 13], - "date": ["2023-01-01", "2023-01-02"], "var2": [11, 15], + "date": ["2023-01-01", "2023-01-02"], "sample": ["sample2", "sample2"] } ) -df_concat = pd.concat([df1, df2]) +pl.concat([df1, df2]) -df_concat ``` -Notons que l'ordre des variables dans les deux DataFrames n'est pas important. Pandas ne juxtapose pas "bêtement" les deux DataFrames, il fait une correspondance des schémas pour faire correspondre les variables par nom. Si deux variables ont le même nom mais pas le même type - par exemple dans le cas où une variable numérique aurait été interprétée comme des strings - Pandas va résoudre le problème en prenant le dénominateur commun, c'est à dire en général convertir en strings (type `object`). +A la grande différence de `Pandas`, **l'ordre des variables dans les deux DataFrames importe**. -Par contre, la concaténation précédente laisse apparaître un problème de répétition au niveau de l'index. C'est logique : on n'a pas spécifié d'index pour nos deux DataFrames initiaux, qui ont donc le même index de position ([0, 1]). Dans ce cas (où l'index n'est pas important), on peut passer le paramètre `ignore_index=True` pour reconstruire de zéro l'index final. +Ainsi, le même code avec `df2` défini comme ci-après va renvoyer une erreur. +```{.python} -```{python} -df_concat = pd.concat([df1, df2], ignore_index=True) +df2 = pl.DataFrame( + data = { + "var1": [9, 13], + "date": ["2023-01-01", "2023-01-02"], + "var2": [11, 15], + "sample": ["sample2", "sample2"] + } +) -df_concat ``` -::: {.callout-warning title="Construction itérative d'un DataFrame"} -On pourrait avoir l'idée d'utiliser `pd.concat()` pour construire un DataFrame de manière itérative, en ajoutant à chaque itération d'une boucle une nouvelle ligne au DataFrame existant. Ce n'est néanmoins pas une bonne idée : comme nous l'avons vu, un DataFrame est représenté dans la mémoire commme une juxtaposition de Series. Ainsi, ajouter une colonne à un DataFrame est peu coûteux, mais ajouter une ligne implique de modifier chaque élément constituant du DataFrame. Pour construire un DataFrame, il est donc plutôt conseillé de stocker les lignes dans une liste de listes (une par colonne) ou un dictionnaire, puis d'appeler `pd.DataFrame()` pour construire le DataFrame, comme nous l'avons fait au début de ce tutoriel. -::: +Pour contourner ce problème, il suffit de préférer une méthode de type `join` avec `df1.join(df2, on=df1.columns, how="full", coalesce=True)` (*cf.* ci-après). + #### Fusionner des tables -La fusion de tables est une opération qui permet d'associer des lignes de deux DataFrames différents en se basant sur une ou plusieurs clés communes, similaire aux jointures dans les bases de données SQL. Différents types de jointure sont possible selon les données que l'on souhaite conserver, dont les principaux sont représentés sur le graphique suivant. +La fusion de tables est une opération qui permet d'associer des lignes de deux DataFrames différents en se basant sur une ou plusieurs clés communes, similaire aux jointures dans les bases de données SQL. +Différents types de jointure sont possible selon les données que l'on souhaite conserver, dont les principaux sont représentés sur le graphique suivant. ![](img/joins.png) Source : [lien](https://medium.com/swlh/merging-dataframes-with-pandas-pd-merge-7764c7e2d46d) -En Pandas, les jointures se font avec la fonction [merge()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.merge.html). Pour réaliser une jointure, on doit spécifier (au minimum) deux informations : +En Polars, les jointures se font avec la fonction [`join()`](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.join.html#polars.DataFrame.join). +Pour réaliser une jointure, on doit spécifier (au minimum) deux informations : -- le type de jointure : par défaut, Pandas effectue une jointure de type `inner`. Le paramètre `how` permet de spécifier d'autres types de jointure ; +- le type de jointure : par défaut, Polars effectue une jointure de type `inner`. +Le paramètre `how` permet de spécifier d'autres types de jointure ; + +- la clé de jointure. +On spécifie souvent une colonne présente dans le DataFrame comme clé de jointure (paramètre `on` si la colonne porte le même nom dans les deux DataFrame, ou `left_on` et `right_on` sinon). + + +Par défaut, les colonnes présentes dans les deux colonnes seront conservées avec des suffixes '_right' ou '_left'. +Pour éviter ce comportement, il faut préciser l'argument `coalesce`. +On peut aussi spécifier l'ordre dans lequel les colonnes apparaissent avec l'argument `maintain_order`. + +::: {.callout-note} +On peut aussi tout à fait joindre selon des critères différents que l'égalité : par exemple, joint cette ligne avec toute ligne dont la date est antérieure. +Les méthodes utilisées sont [`join_asof()`](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.join_asof.html) et [`join_where()`](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.join_where.html)` +::: -- la clé de jointure. Par défaut, Pandas essaie de joindre les deux DataFrames à partir de leurs index. En pratique, on spécifie souvent une variable présente dans le DataFrames comme clé de jointure (paramètre `on` si la variable porte le même nom dans les deux DataFrame, ou `left_on` et `right_on` sinon). Analysons la différence entre les différents types de jointure à travers des exemples. ```{python} -df_a = pd.DataFrame({ +df_a = pl.DataFrame({ 'key': ['K0', 'K1', 'K2', 'K3', 'K4'], 'A': ['A0', 'A1', 'A2', 'A3', 'A4'], 'B': ['B0', 'B1', 'B2', 'B3', 'A4'] }) -df_b = pd.DataFrame({ +df_b = pl.DataFrame({ 'key': ['K0', 'K1', 'K2', 'K5', 'K6'], 'C': ['C0', 'C1', 'C2', 'C5', 'C6'], 'D': ['D0', 'D1', 'D2', 'D5', 'D6'] }) -display(df_a) -display(df_b) +print(df_a) +print(df_b) ``` +- **Inner Join** La jointure de type `inner` conserve les observations dont la clé est présente dans les deux DataFrame. ```{python} -df_merged_inner = pd.merge(df_a, df_b, on='key') -df_merged_inner +df_a.join(df_b, on='key') ``` ::: {.callout-warning title="Jointures inner"} -La jointure de type `inner` est la plus intuitive : elle ne crée généralement pas de valeurs manquantes et permet donc de travailler directement sur la table fusionnée. Mais attention : si beaucoup de clés ne sont pas présentes dans les deux DataFrames à la fois, une jointure `inner` peut aboutit à des pertes importantes de données, et donc à des résultats finaux biaisés. Dans ce cas, il vaut mieux choisir une jointure à gauche ou à droite, selon la source que l'on cherche à enrichir et pour laquelle il est donc le plus important de limiter les pertes de données. +La jointure de type `inner` est la plus intuitive : elle ne crée généralement pas de valeurs manquantes et permet donc de travailler directement sur la table fusionnée. +Mais attention : si beaucoup de clés ne sont pas présentes dans les deux DataFrames à la fois, une jointure `inner` peut aboutit à des pertes importantes de données, et donc à des résultats finaux biaisés. +Dans ce cas, il vaut mieux choisir une jointure à gauche ou à droite, selon la source que l'on cherche à enrichir et pour laquelle il est donc le plus important de limiter les pertes de données. ::: -Une jointure de type `left` conserve toutes les observations contenues dans le DataFrame de gauche (premier DataFrame spécifié dans `pd.merge()`). Par conséquent, si des clés sont présentes dans le DataFrame de gauche mais pas dans celui de droite, le DataFrame final contient des valeurs manquantes au niveau de ces observations (pour les variables du DataFrame de droite). +- **Left join** +Une jointure de type `left` conserve toutes les observations contenues dans le DataFrame de gauche (le DataFrame à qui on applique la méthode `.join()`). +Par conséquent, si des clés sont présentes dans le DataFrame de gauche mais pas dans celui de droite, le DataFrame final contient des valeurs manquantes au niveau de ces observations (pour les variables du DataFrame de droite). ```{python} -df_merged_left = pd.merge(df_a, df_b, how="left", on='key') -df_merged_left +df_a.join(df_b, how="left", on='key') ``` -La jointure de type `outer` contient toutes les observations et variables contenues dans les deux DataFrame. Ainsi, l'information retenue est maximale, mais en contrepartie les valeurs manquantes peuvent être assez nombreuses. Il sera donc nécessaire de bien traiter les valeurs manquantes avant de procéder aux analyses. +- **Full join** +La jointure de type `full` contient toutes les observations et variables contenues dans les deux DataFrame. +Ainsi, l'information retenue est maximale, mais en contrepartie les valeurs manquantes peuvent être assez nombreuses. +Il sera donc nécessaire de bien traiter les valeurs manquantes avant de procéder aux analyses. ```{python} -df_merged_outer = pd.merge(df_a, df_b, how="outer", on='key') -df_merged_outer +df_a.join(df_b, how="full", on='key') +``` + +```{python} +df_a.join(df_b, how="full", on='key', coalesce=True) ``` ## Exercices From 739d8c544f2749eeb4af7b352f24f289479dcbb6 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 21 Jan 2026 16:39:00 +0000 Subject: [PATCH 29/92] with intro --- .../polars/img/polars-benchmark-short.png | Bin 0 -> 59140 bytes .../polars-split-parallel-apply-combine.svg | 2526 +++++++++++++++++ .../manipulation/polars/img/structure_df.png | Bin 164895 -> 0 bytes source/manipulation/polars/tutorial.qmd | 165 +- 4 files changed, 2672 insertions(+), 19 deletions(-) create mode 100644 source/manipulation/polars/img/polars-benchmark-short.png create mode 100644 source/manipulation/polars/img/polars-split-parallel-apply-combine.svg delete mode 100644 source/manipulation/polars/img/structure_df.png diff --git a/source/manipulation/polars/img/polars-benchmark-short.png b/source/manipulation/polars/img/polars-benchmark-short.png new file mode 100644 index 0000000000000000000000000000000000000000..e8bb3312d7464a0e15dd766f9c2809f578d32e75 GIT binary patch literal 59140 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
-Show solution - -1. A DataFrame in Pandas is a two-dimensional data structure, comparable to a table or an Excel spreadsheet. In the Python context, it can be compared to a dictionary of NumPy arrays, where the keys are column names, and the values are the columns themselves. - -2. The main difference between a NumPy array and a Pandas Series is that the Series can contain labeled data, meaning it has an associated index that allows access and manipulation by label. - -3. A DataFrame is essentially a collection of Series. Each column of a DataFrame is a Series, and all these Series share the same index, which corresponds to the row labels of the DataFrame. - -4. Data in a Pandas DataFrame are structured in columns and rows. Each column can contain a different type of data (numeric, string, boolean, etc.), and each row represents an observation. - -5. The index in a Pandas DataFrame serves to uniquely identify each row in the DataFrame. It allows quick access to rows, performing joins, sorting data, and facilitating grouping operations. - -6. To explore an unknown DataFrame, you can use `df.head()` to see the first rows, `df.tail()` for the last rows, `df.info()` to get a summary of data types and missing values, and `df.describe()` for descriptive statistics. - -7. Assigning the result of an operation to a new variable creates a copy of the DataFrame with the applied modifications. Using a method with `inplace=True` modifies the original DataFrame without creating a copy, which can be more memory-efficient. - -8. Pandas represents missing values with the `nan` (Not a Number) object from `NumPy` for numeric data and with `None` or `pd.NaT` for date/time data. These missing values are generally ignored in statistical calculations, which can affect the results if they are not handled properly. - -9. Concatenating consists of stacking DataFrames vertically or aligning them horizontally, primarily used when the DataFrames have the same schema or when you want to stack the data. Merging, inspired by SQL JOIN operations, combines DataFrames based on common key values and is used to enrich one dataset with information from another. - -
- -::: - -### Multiple ways to create a DataFrame - -In the following cell, we have retrieved cash register data on sales from different stores. The data is presented in two different ways: one as observations (each list contains data from a row), and the other as variables (each list contains data from a column). - -```{python} -data_list1 = [ - ['Carrefour', '01.1.1', 3, 1.50], - ['Casino', '02.1.1', 2, 2.30], - ['Lidl', '01.1.1', 7, 0.99], - ['Carrefour', '03.1.1', 5, 5.00], - ['Casino', '01.1.1', 10, 1.20], - ['Lidl', '02.1.1', 1, 3.10] -] - -data_list2 = [ - ['Carrefour', 'Casino', 'Lidl', 'Carrefour', 'Casino', 'Lidl'], - ['01.1.1', '02.1.1', '01.1.1', '03.1.1', '01.1.1', '02.1.1'], - [3, 2, 7, 5, 10, 1], - [1.50, 2.30, 0.99, 5.00, 1.20, 3.10] -] -``` - -The goal is to build in both cases the same DataFrame containing each of the 6 observations and 4 variables, with the same names in both DataFrames. Each case will correspond to a more suitable input data structure, dictionary, or list of lists... make the right choice! We will verify that the two DataFrames are identical using the [equals()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.equals.html) method. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -data_list1 = [ - ['Carrefour', 'Casino', 'Lidl', 'Carrefour', 'Casino', 'Lidl'], - ['01.1.1', '02.1.1', '01.1.1', '03.1.1', '01.1.1', '02.1.1'], - [3, 2, 7, 5, 10, 1], - [1.50, 2.30, 0.99, 5.00, 1.20, 3.10] -] - -data_list2 = [ - ['Carrefour', '01.1.1', 3, 1.50], - ['Casino', '02.1.1', 2, 2.30], - ['Lidl', '01.1.1', 7, 0.99], - ['Carrefour', '03.1.1', 5, 5.00], - ['Casino', '01.1.1', 10, 1.20], - ['Lidl', '02.1.1', 1, 3.10] -] - -# If the data is in column form: from a dictionary -data_dict = { - 'store': data_list1[0], - 'product': data_list1[1], - 'quantity': data_list1[2], - 'price': data_list1[3] -} - -df_from_dict = pd.DataFrame(data_dict) - -# If the data is in row form: from a list of lists -columns = ['store', 'product', 'quantity', 'price'] -df_from_list = pd.DataFrame(data_list2, columns=columns) - -# Verification -df_from_dict.equals(df_from_list) -``` - -
- -::: - -### Data selection in a DataFrame - -A Pandas DataFrame is created with cash register data (same data as the previous exercise). - -```{python} -data = { - 'store': ['Carrefour', 'Casino', 'Lidl', 'Carrefour', 'Casino', 'Lidl'], - 'product': ['01.1.1', '02.1.1', '01.1.1', '03.1.1', '01.1.1', '02.1.1'], - 'quantity': [3, 2, 7, 5, 10, 1], - 'price': [1.50, 2.30, 0.99, 5.00, 1.20, 3.10], - 'date_time': pd.to_datetime(["2022-01-01 14:05", "2022-01-02 09:30", - "2022-01-03 17:45", "2022-01-04 08:20", - "2022-01-05 19:00", "2022-01-06 16:30"]) -} - -df = pd.DataFrame(data) -``` - -Use the `loc` and `iloc` methods to select specific data: - -- Select the data from the first row. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -print(df.iloc[0]) -``` - -
- -::: - -- Select all data from the "price" column. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -print(df.loc[:, 'price']) -``` - -
- -::: - -- Select the rows corresponding to the store "Carrefour" only. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -print(df.loc[df['store'] == 'Carrefour']) -``` - -
- -::: - -- Select the quantities purchased for products classified "01.1.1" (Bread). - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -print(df.loc[df['product'] == '01.1.1', 'quantity']) -``` - -
- -::: - -- Select the data from the "store" and "price" columns for all rows. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -print(df.loc[:, ['store', 'price']]) -``` - -
- -::: - -- Select the rows where the purchased quantity is greater than 5. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -print(df.loc[df['quantity'] > 5]) -``` - -
- -::: - -- Filter to select all transactions that occurred after 3 PM. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -print(df.loc[df['date_time'].dt.hour > 15]) -``` - -
- -::: - -- Select the transactions that took place on "2022-01-03". - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -print(df.loc[df['date_time'].dt.date == pd.to_datetime('2022-01-03').date()]) -``` - -
- -::: - -### Exploring the first names file - -The first names file contains data on the first names given to children born in France between 1900 and 2021. This data is available at the national, department, and regional levels at the following address: [https://www.insee.fr/fr/statistiques/2540004?sommaire=4767262](https://www.insee.fr/fr/statistiques/2540004?sommaire=4767262). The goal of this tutorial is to propose an analysis of this file, from data cleaning to first name statistics. - -#### Part 1: Import and data exploration - -- Import the data into a DataFrame using this [URL](https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip). -- View a sample of the data. Do you notice any anomalies? -- Display the main information about the DataFrame. Identify any variables with incorrect types or any missing values. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -url = "https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip" -df_first_names = pd.read_csv(url, sep=";") - -df_first_names.head(10) -df_first_names.sample(n=50) - -df_first_names.info() -``` - -
- -::: - -#### Part 2: Data cleaning - -- The output of the `info()` method suggests missing values in the first names column. Display these rows. Verify that these missing values are correctly specified. -- The output of the `head()` method shows a recurring "_PRENOMS_RARES" modality in the first names column. What proportion of the individuals in the database does this represent? Convert these values to `np.nan`. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -print(df_first_names[df_first_names["preusuel"].isna()]) -prop_rares = df_first_names.groupby("preusuel")["nombre"].sum()["_PRENOMS_RARES"] / df_first_names["nombre"].sum() -print(prop_rares) # ~ 2% of the database -df_first_names = df_first_names.replace('_PRENOMS_RARES', np.nan) -``` - -
- -::: - -- We notice that the first names of people whose year of birth is unknown are grouped under the "XXXX" modality. What proportion of the individuals in the database does this represent? Convert these values to `np.nan`. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -prop_xxxx = df_first_names.groupby("annais")["nombre"].sum()["XXXX"] / df_first_names["nombre"].sum() -print(prop_xxxx) # ~ 1% of the database -df_first_names = df_first_names.replace('XXXX', np.nan) -``` - -
- -::: - -- Remove the rows containing missing values from the sample. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -df_first_names = df_first_names.dropna() -``` - -
- -::: - -- Convert the `annais` column to numeric type and the `sexe` column to categorical type. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -df_first_names['annais'] = pd.to_numeric(df_first_names['annais']) -df_first_names['sexe'] = df_first_names['sexe'].astype('category') -``` - -
- -::: - -- Verify with the `info()` method that the cleaning has been correctly applied. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -df_first_names.info() -``` - -
- -::: - -#### Part 3: Descriptive statistics on births - -- The [documentation](https://www.insee.fr/fr/statistiques/2540004?sommaire=4767262#documentation) of the file informs us that the data can be considered quasi-exhaustive from 1946 onwards. For this part only, filter the data to keep only data from 1946 onwards. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -df_first_names_post_1946 = df_first_names[df_first_names["annais"] >= 1946] -``` - -
- -::: - -- Calculate the total number of births by sex. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -births_per_sex = df_first_names_post_1946.groupby('sexe')['nombre'].sum() -print(births_per_sex) -``` - -
- -::: - -- Identify the five years with the highest number of births. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -top5_years = df_first_names_post_1946.groupby('annais')['nombre'].sum().nlargest(5) -print(top5_years) -``` - -
- -::: - -#### Part 4: First name analysis - -- Identify the total number of unique first names in the DataFrame. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -total_unique_names = df_first_names['preusuel'].nunique() -print(total_unique_names) -``` - -
- -::: - -- Count the number of people with a single-letter first name. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -single_letter_names = df_first_names[df_first_names['preusuel'].str.len() == 1]['nombre'].sum() -print(single_letter_names) -``` - -
- -::: - -- Create a "popularity function" that, for a given first name, displays the year it was most given and the number of times it was given that year. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -def popularity_by_year(df, first_name): - # Filter the DataFrame to keep only the rows corresponding to the given first name - df_first_name = df[df['preusuel'] == first_name] - - # Group by year, sum the births, and identify the year with the maximum births - df_agg = df_first_name.groupby('annais')['nombre'].sum() - max_year = df_agg.idxmax() - max_n = df_agg[max_year] - - print(f"The first name '{first_name}' was most given in {max_year}, with {max_n} births.") - -# Test the function with an example -popularity_by_year(df_first_names, 'ALFRED') -``` - -
- -::: - -- Create a function that, for a given sex, returns a DataFrame containing the most given first name for each decade. - -```{python} -# Test - - your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -def popularity_by_decade(df, sex): - # Filter by sex - df_sub = df[df["sexe"] == sex] - - # Calculate the decade variable - df_sub["decade"] = (df_sub["annais"] // 10) * 10 - - # Calculate the sum of births for each first name and each decade - df_counts_decade = df_sub.groupby(["preusuel", "decade"])["nombre"].sum().reset_index() - - # Find the index of the most frequent first name for each decade - idx = df_counts_decade.groupby("decade")["nombre"].idxmax() - - # Use the index to obtain the corresponding rows from the df_counts_decade DataFrame - df_popularity_decade = df_counts_decade.loc[idx].set_index("decade") - - return df_popularity_decade - -# Test the function with an example -popularity_by_decade(df_first_names, sex=2) -``` - -
- -::: - -### Calculation of a carbon footprint per inhabitant at the municipal level - -The goal of this exercise is to calculate a carbon footprint per inhabitant at the municipal level. To do this, we will need to combine two data sources: - -- Legal populations at the municipal level from the population census ([source](https://www.insee.fr/fr/statistiques/6683037)) - -- Greenhouse gas emissions estimated at the municipal level by ADEME ([source](https://www.data.gouv.fr/fr/datasets/inventaire-de-gaz-a-effet-de-serre-territorialise/#_)) - -This exercise constitutes a simplified version of a [complete practical exercise on Pandas](https://pythonds.linogaliana.fr/content/manipulation/02b_pandas_TP.html#importer-les-donn%C3%A9es) proposed by Lino Galiana in his [course at ENSAE](https://pythonds.linogaliana.fr/). - -#### Part 1: Exploring the legal municipal populations data - -- Import the CSV file `communes.csv`. -- Use the `.sample()`, `.info()`, and `.describe()` methods to get an overview of the data. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -df_pop_communes = pd.read_csv("data/communes.csv", sep=";") - -df_pop_communes.sample(10) -df_pop_communes.info() -df_pop_communes.describe() -``` - -
- -::: - -- Identify and remove rows corresponding to municipalities without population. -- Remove the "PMUN" and "PCAP" columns, which are irrelevant for the analysis. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -n_communes_0_pop = df_pop_communes[df_pop_communes["PTOT"] == 0].shape[0] -print(n_communes_0_pop) -df_pop_communes = df_pop_communes[df_pop_communes["PTOT"] > 0] - -df_pop_communes = df_pop_communes.drop(columns=["PMUN", "PCAP"]) -``` - -
- -::: - -Do the municipalities with the longest names also have the smallest populations? To find out: -- Create a new variable that contains the number of characters of each municipality using the [str.len()](https://pandas.pydata.org/docs/reference/api/pandas.Series.str.len.html) method. -- Calculate the correlation between this variable and the total population using the [corr()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.corr.html) method. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -df_pop_communes_stats = df_pop_communes.copy() -df_pop_communes_stats['length'] = df_pop_communes_stats['COM'].str.len() -df_pop_communes_stats['length'].corr(df_pop_communes_stats['PTOT']) -``` - -
- -::: - -#### Part 2: Exploring the municipal emissions data - -- Import the emissions data from this [URL](https://data.ademe.fr/data-fair/api/v1/datasets/igt-pouvoir-de-rechauffement-global/data-files/IGT%20-%20Pouvoir%20de%20r%C3%A9chauffement%20global.csv). -- Use the `.sample()`, `.info()`, and `.describe()` methods to get an overview of the data. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -url_ademe = "https://data.ademe.fr/data-fair/api/v1/datasets/igt-pouvoir-de-rechauffement-global/data-files/IGT%20-%20Pouvoir%20de%20r%C3%A9chauffement%20global.csv" -df_emissions = pd.read_csv(url_ademe) - -df_emissions.sample(10) -df_emissions.info() -df_emissions.describe() -``` - -
- -::: - -- Are there rows with missing values for all emission columns? Check using the [isnull()](https://pandas.pydata.org/docs/reference/api/pandas.isnull.html) and [all()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.all.html) methods. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -df_emissions_num = df_emissions.select_dtypes(['number']) -only_nan = df_emissions_num[df_emissions_num.isnull().all(axis=1)] -only_nan.shape[0] -``` - -
- -::: - -- Create a new column that gives the total emissions per municipality. -- Display the 10 most emitting municipalities. What do you observe in the results? - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -df_emissions['total_emissions'] = df_emissions.sum(axis=1, numeric_only=True) - -df_emissions.sort_values(by="total_emissions", ascending=False).head(10) -``` - -
- -::: - -- It seems that the major emission sectors are "Industry excluding energy" and "Other international transport." To verify if this conjecture holds, calculate the correlation between total emissions and the sectoral emission items using the [corrwith()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.corrwith.html) method. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -df_emissions.corrwith(df_emissions["total_emissions"], numeric_only=True) -``` - -
- -::: - -- Extract the department number from the municipality code into a new variable. -- Calculate the total emissions by department. -- Display the top 10 emitting departments. Are the results logical compared to the analysis at the municipal level? - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -df_emissions["dep"] = df_emissions["INSEE commune"].str[:2] -df_emissions.groupby("dep").agg({"total_emissions": "sum"}).sort_values(by="total_emissions", ascending=False).head(10) -``` - -
- -::: - -#### Part 3: Preliminary checks for merging data sources - -To perform a merge, it is always preferable to have a join key, i.e., a column common to both sources that uniquely identifies the statistical units. The purpose of this part is to find the relevant join key. - -- Check if the variable containing the municipality names contains duplicates. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -duplicates = df_pop_communes.groupby('COM').count()['DEPCOM'] -duplicates = duplicates[duplicates > 1] -duplicates = duplicates.reset_index() -duplicates -``` - -
- -::: - -- Filter in the initial DataFrame the municipalities with duplicated names and sort it by municipality code. Do the duplicates seem problematic? - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -df_pop_communes_duplicates = df_pop_communes[df_pop_communes["COM"].isin(duplicates["COM"])] -df_pop_communes_duplicates.sort_values('COM') -``` - -
- -::: - -- Verify that the municipality codes uniquely identify the associated municipality. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -(df_pop_communes_duplicates.groupby("DEPCOM")["COM"].nunique() != 1).sum() -``` - -
- -::: - -- Display the municipalities present in the population data but not in the emissions data, and vice versa. What do you conclude? - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -# Observations in the population data but not in the emissions data -df_pop_communes[~df_pop_communes["DEPCOM"].isin(df_emissions["INSEE commune"])] - -# Observations in the emissions data but not in the population data -df_emissions[~df_emissions["INSEE commune"].isin(df_pop_communes["DEPCOM"])] -``` - -
- -::: - -#### Part 4: Calculating a carbon footprint per inhabitant for each municipality - -- Merge the two DataFrames using the municipality code as the join key. Note: the variables are not named the same on both sides! - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -df_emissions_pop = pd.merge(df_pop_communes, df_emissions, how="inner", left_on="DEPCOM", right_on="INSEE commune") -df_emissions_pop -``` - -
- -::: - -- Calculate a carbon footprint for each municipality, corresponding to the total emissions of the municipality divided by its total population. -- Display the top 10 municipalities with the highest carbon footprints. -- Are the results the same as those with total emissions? What do you conclude? - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -df_emissions_pop["carbon_footprint"] = df_emissions_pop["total_emissions"] / df_emissions_pop["PTOT"] -df_emissions_pop.sort_values("carbon_footprint", ascending=False).head(10) -``` - -
- -::: - -### Analysis of the evolution of a production index - -You have two CSV data sets available in the `data/` folder: - -- `serie_glaces_valeurs.csv` contains the monthly values of the production price index of the French ice cream and sorbet industry. -- `serie_glaces_metadonnees.csv` contains the associated metadata, including the codes indicating the data status. - -The goal is to use `Pandas` to calculate: - -- the evolution of the index between each period (month) -- the evolution of the index on a year-over-year basis (between a given month and the same month the following year). - -#### Part 1: Importing data - -- Import the two CSV files into DataFrames. Note: in both cases, there are extraneous rows before the data that need to be skipped using the `skiprows` parameter of the [read_csv()](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html) function. -- Give simple and relevant names to the various variables. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -df_values = pd.read_csv('data/serie_glaces_valeurs.csv', delimiter=';', - skiprows=4, names=["period", "index", "code"]) -df_metadata = pd.read_csv('data/serie_glaces_metadonnees.csv', delimiter=';', - skiprows=5, names=["code", "meaning"]) -``` - -
- -::: - -#### Part 2: Filtering relevant data - -- Merge the two DataFrames to retrieve the meanings of the codes present in the data. -- Filter the data to keep only the "Normal Value" data. -- Remove the columns related to the codes, which we no longer need for the rest. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -df_merged = pd.merge(df_values, df_metadata, how='left', on='code') - -df_clean = df_merged[df_merged['code'] == "A"] -df_clean = df_clean[["period", "index"]] -``` - -
- -::: - -#### Part 3: Data preprocessing - -Verify if the types of variables are relevant according to their nature. If not, convert them with the appropriate functions. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -df_clean.info() -df_clean['period'] = pd.to_datetime(df_clean['period']) -df_clean['index'] = pd.to_numeric(df_clean['index']) -df_clean.info() -``` - -
- -::: - -#### Part 4: Calculating periodic evolution - -- Use the [shift()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.shift.html) method to create a new column containing the previous month's index. -- Calculate the difference between the current index and the shifted index to obtain the (percentage) evolution from one month to the next. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -df_clean['previous_index'] = df_clean['index'].shift(1) -df_clean['evolution'] = ((df_clean['index'] - df_clean['previous_index']) / df_clean['previous_index']) * 100 - -# Alternative method -df_clean['alternative_evolution'] = df_clean['index'].pct_change(periods=1) * 100 -``` - -
- -::: - -#### Part 5: Calculating year-over-year evolution - -As you saw in the previous exercise's solution, the [pct_change()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.pct_change.html) method allows you to calculate an evolution between two periods. Use this method to calculate a year-over-year evolution for each month. - -```{python} -# Test your answer in this cell -``` - -::: {.cell .markdown} - -
-Show solution - -```{python} -df_clean["year_over_year_evolution"] = df_clean['index'].pct_change(periods=12) * 100 -df_clean.head(20) -``` - -
- -::: - - -::: From f850eb20c1c3428e068673cc58c55f0b0b5010c2 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 21 Jan 2026 17:01:33 +0000 Subject: [PATCH 31/92] with the right title levels --- .gitignore | 2 + pyproject.toml | 1 + source/manipulation/polars/tutorial.qmd | 142 +-- uv.lock | 1344 +++++++++++++++++++++++ 4 files changed, 1420 insertions(+), 69 deletions(-) diff --git a/.gitignore b/.gitignore index b4a895ad..4a940cae 100644 --- a/.gitignore +++ b/.gitignore @@ -153,3 +153,5 @@ dmypy.json .pyre/ /.quarto/ + +**/*.quarto_ipynb diff --git a/pyproject.toml b/pyproject.toml index aabc9bb0..cd6f9769 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,7 @@ dependencies = [ "xlrd", "polars>=1.36.1", "tidypolars>=0.3.2", + "jupyter>=1.1.1", ] [tool.uv] diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 3b97de3a..851b519d 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -115,7 +115,7 @@ df = q.collect(streaming=True) De plus, `Polars` lit nativement les fichiers `Parquet` qui par ses propriétés permet d'aller beaucoup plus vite que le CSV ! -# Une API fluide +### Une API fluide C'est un reproche régulièrement fait à `Pandas` : la syntaxe de manipulations des données est parfois complexe ou peu lisible, et les choix d'écriture ne sont pas transparents du point de vue des performances. @@ -136,12 +136,12 @@ df.lazy() .collect() ``` -# Un pipe natif +### Un pipe natif On retrouve une sémantique d'opérations de haut niveau qui s'enchaînent à la manière de [ce que l'on peut faire en `dplyr`](https://www.book.utilitr.org/03_fiches_thematiques/fiche_tidyverse#comment-utiliser-lop%C3%A9rateur-pipe-avec-le-tidyverse). - +## Intro - TO DO On commence par importer la librairie `Polars`. L'usage est courant est de lui attribuer l'alias `pl` afin de simplifier les futurs appels aux objets et fonctions du package. @@ -153,6 +153,7 @@ très strict sur les types des colonnes Parler de : + - colonnes sont associées à des string. - pas d'index. - polars selectors @@ -162,14 +163,16 @@ Parler de : "TO DO" - Polars Séries pour aller plus loin : + - interconnection avec duckDB pour des requêtes en SQL Ressources : + - [Blog Awesome Polars](https://ddotta.github.io/awesome-polars/), par Damien D - [Notebook Polars](https://datalab.sspcloud.fr/launcher/ide/jupyter-python?name=Tutoriel%20Polars&version=2.3.28&s3=region-79669f20&init.personalInit=«https%3A%2F%2Fraw.githubusercontent.com%2Fntoulemonde%2Ftest%2Frefs%2Fheads%2Fmain%2Finit.sh»&autoLaunch=true) -::: {.panel-tabset group="polars_vs_tidypolars"}} +::: {.panel-tabset group="polars_vs_tidypolars" name="Pour commencer"} ## Polars ```{python} @@ -178,19 +181,20 @@ import numpy as np ``` ## Tidypolars -Pour celles et ceux qui veulent utiliser des fonctions pressqu'identiques à celles du tidyverse, +Pour celles et ceux qui veulent utiliser des fonctions presqu'identiques à celles du tidyverse, il y a le package [tidypolars](https://tidypolars.readthedocs.io/en/latest/). Les noms des fonctions dans tidypolars sont presque tous identiques à ceux du tidyverse: -- un DataFrame de Polars devient un tibble chez tidypolars; -- la structure de la création d'un tibble est la même que dans R; -- les méthodes filter, select de Polars restent les mêmes; -- la méthode with_columns de Polars devient mutate ... + +- un `DataFrame` de Polars devient un `tibble` chez tidypolars; +- la structure de la création d'un `tibble` est la même que dans R; +- les méthodes `filter`, `select` de Polars restent les mêmes; +- la méthode `with_columns` de Polars devient `mutate` ... Tidypolars reprend ainsi exactement la syntaxe des principales fonctions de dplyr, tidyr, stringr, lubridate, tidyselect directement dans Python! La liste complète des fonctions reprises est disponible dans la [documentation](https://tidypolars.readthedocs.io/en/latest/reference.html). -La seule différence notable entre tidypolars et R est liée aux colonnes, qui sont accessibles par pl.col/tp.col dans polars/tidypolars quand dans R leur nom seul suffit. +La seule différence notable entre tidypolars et R est liée aux colonnes, qui sont accessibles par `pl.col/tp.col` dans `polars/tidypolars` quand dans R leur nom seul suffit. Pour la simplicité du tutoriel, le tutoriel présente le début avec tidypolars mais ensuite utilise uniquement Polars. Pour plus de détail, allez voir la [documentation](https://tidypolars.readthedocs.io/en/latest/reference.html) ! @@ -205,9 +209,9 @@ from tidypolars import col ::: -## Structures de données +# C'est parti avec la structure des données -### Le `DataFrame` +## Le `DataFrame` Fondamentalement, un DataFrame consiste en une collection de Series. Cette concaténation construit donc une table de données, dont les Series correspondent aux colonnes. La figure suivante ([source](https://www.geeksforgeeks.org/creating-a-pandas-dataframe/)) permet de bien comprendre cette structure de données. @@ -266,13 +270,13 @@ Les principaux autres attributs d'un dataframe sont : - le schéma du dataframe (df.schema) - les formats des colonnes (df.dtypes) -## Sélectionner des données +# Sélectionner des données Lors de la manipulation des données tabulaires, il est fréquent de vouloir extraire des colonnes spécifiques d'un `DataFrame`. Cette extraction suit la même logique que le tidyverse avec `Polars`. La méthode `select` permet de sélectionner sur les colonnes quand `filter` filtre les lignes. -### Sélectionner des colonnes +## Sélectionner des colonnes Que l'on veuille sélectionner une ou deux colonnes en `Polars`, la logique est similaire. @@ -285,8 +289,8 @@ selected_column L'objet `selected_column` renvoie ici la colonne nommée `var1` du `DataFrame` `df`. Contrairement à Pandas, ici on ne garde qu'une seule colonne du dataframe, on ne l'extrait pas. -L'objet `selected_columns` reste donc un dataframe de 1 colonne, et n'est pas une Polars Series. -En effet, si on sélectionnait 2 colonnes, cela serait aussi dataframe. +L'objet `selected_columns` reste donc un dataframe de 1 colonne, et n'est pas une série Polars. +Si on sélectionnait 2 colonnes, cela serait ainsi aussi un dataframe. ::: {.callout-tip} Si vous voulez transformer un dataframe en une série Polars, il faut utiliser la méthode `to_series()` ou reprendre la syntaxe de Pandas qui marche aussi en Polars : @@ -310,7 +314,7 @@ print(df.select(["var1", "experiment"])) ``` -### Sélectionner des lignes +## Sélectionner des lignes En pratique, on souhaite souvent filtrer un DataFrame selon certaines conditions. Dans ce cas, on se sert principalement de filtres booléens selon une logique similaire au tidyverse. @@ -371,13 +375,13 @@ df.filter(pl.col("var1") >= 0, pl.col("experiment").is_in(['train', 'validation' df.filter((pl.col("var1") >= 0) | pl.col("experiment").is_in(['train', 'validation'])) ``` -## Explorer des données tabulaires +# Explorer des données tabulaires En statistique publique, le point de départ n'est généralement pas la génération manuelle de données, mais plutôt des fichiers tabulaires préexistants. Ces fichiers, qu'ils soient issus d'enquêtes, de bases administratives ou d'autres sources, constituent la matière première pour toute analyse ultérieure. Polars offre des outils puissants et très rapides pour importer ces fichiers tabulaires et les explorer en vue de manipulations plus poussées. -### Importer et exporter des données +## Importer et exporter des données Polars est très sensible au format des données, l'import peut donc parfois être un peu long à débuger quand il n'arrive pas à déterminer le format de données de la colonne. En effet, Polars va traiter chaque colonne comme une série d'un des formats qu'il connaît. @@ -420,7 +424,7 @@ On peut convertir `var1` en caractère et `date` en un format temporel par exemp df.cast({"var1":pl.String, "date":pl.Date}) ``` -#### Importer un fichier CSV +### Importer un fichier CSV Comme nous l'avons vu dans un précédent TP, le format CSV est l'un des formats les plus courants pour stocker des données tabulaires. Nous avons précédemment utilisé la librairie `csv` pour les manipuler comme des fichiers texte, mais ce n'était pas très pratique. Pour rappel, la syntaxe pour lire un fichier CSV et afficher les premières lignes était la suivante : @@ -509,7 +513,7 @@ Tous ces paramètres et leur utilisation sont détaillés dans la [documentation ``` -#### Exporter au format CSV +### Exporter au format CSV Une fois que les données ont été traitées et modifiées au sein de Polars, il est courant de vouloir exporter le résultat sous forme de fichier CSV pour le partager, l'archiver ou l'utiliser dans d'autres outils. Polars offre une méthode simple pour cette opération : `write_csv()`. @@ -521,7 +525,7 @@ df_departements_dom.write_csv('output/departements2021_dom.csv', separator=";") ``` -#### Importer un fichier Parquet +### Importer un fichier Parquet Le format Parquet est un autre format pour le stockage de données tabulaires, de plus en plus fréquemment utilisé. Sans entrer dans les détails techniques, le format Parquet présente différentes caractéristiques qui en font un choix privilégié pour le stockage et le traitement de gros volumes de données. @@ -536,7 +540,7 @@ df_departements = pl.read_parquet('data/departement2021.parquet') df_departements.head() ``` -#### Exporter au format Parquet +### Exporter au format Parquet Là encore, tout se passe comme dans le monde des CSV : on utilise la méthode `write_parquet()` pour exporter un DataFrame dans un fichier Parquet. @@ -594,7 +598,7 @@ df_test_schema_csv = pl.read_csv('output/df_test_schema.csv') df_test_schema_csv ``` -#### Importer depuis un dictionnaire +### Importer depuis un dictionnaire Comme illustré dans le tutoriel [Travailler avec des fichiers CSV et JSON](../csv-json-files/tutorial.qmd), on peut aussi créer un dataFrame Polars à partir d'un dictionnaire. Cela sera très utile par exemple quand on récupère les données d'une API (_cf._ cours de @@ -632,7 +636,7 @@ df = df.select("features").unnest("features") df ``` -#### Autres exports et imports +### Autres exports et imports - **Exporter vers un dictionnaire**: @@ -650,7 +654,7 @@ Polars permet aussi facilement d'exporter et d'importer des DataFrame au format Cela permet de travailler avec Polars et de convertir un DataFrame en Pandas quand un package n'autorise pas l'import depuis Polars. Il suffit d'utiliser la fonction `pl.from_pandas(df)` et la méthode `df.to_pandas()`. -### Visualiser un échantillon des données +# Visualiser un échantillon des données Lorsqu'on travaille avec des jeux de données volumineux, il est souvent utile de visualiser rapidement un échantillon des données pour avoir une idée de leur structure, de leur format ou encore pour détecter d'éventuels problèmes. @@ -685,7 +689,7 @@ L'affichage des premières ou dernières lignes peut parfois ne pas être repré df_departements.sample(n=5) ``` -### Obtenir une vue d'ensemble des données +## Obtenir une vue d'ensemble des données L'une des premières étapes lors de l'exploration de nouvelles données est de comprendre la structure générale du jeu de données. La méthode `glimpse()` de Polars offre une vue d'ensemble rapide des données, notamment en termes de types de données et affiche les données. @@ -709,7 +713,7 @@ Plusieurs éléments d'information clés peuvent être extraits de ce résultat Contrairement à Pandas, cette méthode n'affiche pas les valeurs manquantes. Pour cela, il faut utiliser les statistiques descriptives. -### Calculer des statistiques descriptives +## Calculer des statistiques descriptives En complément des informations renvoyées par la méthode `glimpse()`, on peut vouloir obtenir des statistiques descriptives simples afin de visualiser rapidement les distributions des variables. @@ -723,14 +727,14 @@ Notons que, là encore, la variable `count` renvoie le nombre de valeurs **non-m -## Principales manipulations de données +# Principales manipulations de données -### Transformer les données +## Transformer les données Les opérations de transformation sur les données sont essentielles pour façonner, nettoyer et préparer les données en vue de leur analyse. Les transformations peuvent concerner l'ensemble du DataFrame, des colonnes spécifiques ou encore des lignes spécifiques. -#### Transformer les colonnes +### Transformer les colonnes En équivalent de `mutate` du tidyverse ou du `replace` de pandas, Polars utilise `with_columns`. Le fonctionnement est similaire au `mutate` du tidyverse. @@ -820,7 +824,7 @@ df = df.cast({'var2':pl.Int32}) df.glimpse() ``` -#### Renommer des colonnes +### Renommer des colonnes Une autre opération fréquente est le renommage d'une ou plusieurs colonnes. Pour cela, on peut utiliser la méthode [rename()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.rename.html#polars.DataFrame.rename), à laquelle on passe un dictionnaire qui contient autant de couples clé-valeur que de variables à renommer, et dans lequel chaque couple clé-valeur est de la forme `'ancien_nom': 'nouveau_nom'`. @@ -829,7 +833,7 @@ df.rename({'var2': 'age'}) ``` -#### Fonctions complexes +### Fonctions complexes Néanmoins, on peut se retrouver dans certains (rares) cas où une opération ne peut pas être facilement vectorisée ou où la logique est complexe. Supposons par exemple que l'on souhaite calculer la variation annuelle du PIB par pays dans une table comportant les pays et les années. @@ -856,7 +860,7 @@ print(df.group_by('country').map_groups(calculate_percentage_change)) ``` -### Trier les valeurs +## Trier les valeurs Le tri des données est particulièrement utile pour l'exploration et la visualisation de données. Avec Polars, on utilise la méthode [sort()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.sort.html#polars.DataFrame.sort) pour trier les valeurs d'un DataFrame selon une ou plusieurs colonnes. @@ -891,7 +895,7 @@ df.sort(by=['var1', 'var2'], descending=[True, True]) ``` -### Agréger des données +## Agréger des données L'agrégation des données est un processus dans lequel les données vont être ventilées en groupes selon certains critères, puis agrégées selon une fonction d'agrégation appliquée indépendamment à chaque groupe. Cette opération est courante lors de l'analyse exploratoire ou lors du prétraitement des données pour la visualisation ou la modélisation statistique. @@ -909,7 +913,7 @@ df = pl.DataFrame( df.head() ``` -#### L'opération `group_by` +### L'opération `group_by` La méthode `group_by` de Polars permet de diviser le DataFrame en sous-ensembles selon les valeurs d'une ou plusieurs colonnes, puis d'appliquer une fonction d'agrégation à chaque sous-ensemble. Elle renvoie un objet de type `dataframe.group_by` qui ne présente pas de grand intérêt en soi, mais constitue l'étape intermédiaire indispensable pour pouvoir ensuite appliquer une ou plusieurs fonction(s) d'agrégation aux différents groupes. @@ -917,7 +921,7 @@ La méthode `group_by` de Polars permet de diviser le DataFrame en sous-ensemble df.group_by('experiment') ``` -#### Fonctions d'agrégation +### Fonctions d'agrégation Une fois les données groupées, on peut appliquer des fonctions d'agrégation pour obtenir un résumé statistique. Polars intègre un certain nombre de ces fonctions qui fonctionnent sur la table de donnée entière, *cf.* [liste complète dans la documentation](https://docs.pola.rs/api/python/stable/reference/dataframe/aggregation.html) ou sur des sous-ensembles de la table, en utilisant `group_by`, *cf.* [liste complète dans la documentation](https://docs.pola.rs/api/python/stable/reference/dataframe/group_by.html). @@ -995,11 +999,11 @@ subset_df = ( ::: -### Traiter les valeurs manquantes +## Traiter les valeurs manquantes Les valeurs manquantes sont une réalité courante dans le traitement des données réelles et peuvent survenir pour diverses raisons, telles que des non-réponses à un questionnaire, des erreurs de saisie, des pertes de données lors de la transmission ou simplement parce que l'information n'est pas applicable. Pandas offre plusieurs outils pour gérer les valeurs manquantes. -#### Représentation des valeurs manquantes +### Représentation des valeurs manquantes On peut tout d'abord traiter les valeurs manquantes avec les méthodes associées. Pour rappel, en Polars, les valeurs `NaN` et `null` sont différentes, alors qu'en Pandas elles sont traitées de manière similaire. @@ -1036,7 +1040,7 @@ print(df.drop_nans()) print(df.drop_nulls()) ``` -#### Calculs sur des colonnes contenant des valeurs manquantes +### Calculs sur des colonnes contenant des valeurs manquantes Lors de calculs statistiques, les valeurs nulles sont généralement ignorées en Polars. Par exemple, la méthode `.mean()` calcule la moyenne des valeurs non manquantes. @@ -1050,7 +1054,7 @@ En revanche, les valeurs 'Not a Number', ou `NaN`, ont plutôt tendance à se pr df['var2'].mean() ``` -#### Suppression des valeurs manquantes +### Suppression des valeurs manquantes Les méthodes `drop_nulls()` et `drop_nans()` permettent de supprimer les lignes contenant des valeurs manquantes ou des NaN. @@ -1066,7 +1070,7 @@ Si l'on spécifie une liste de colonnes, seules les lignes comportant une valeur df.drop_nulls(['var1']) ``` -#### Remplacement des valeurs manquantes +### Remplacement des valeurs manquantes Pour gérer les valeurs manquantes dans un DataFrame, une approche commune est l'imputation, qui consiste à remplacer les valeurs manquantes par d'autres valeurs. La méthode [`fill_null()`](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.fill_null.html) permet d'effectuer cette opération de différentes manières dans toute la table de donnée. @@ -1107,9 +1111,9 @@ Remplacer les valeurs manquantes par une valeur constante, telle que zéro, la m De manière similaire, la méthode `fill_nan()` permet de remplacer les valeurs numériques NaN par toute valeur indiquée. -### Traiter les données de types spécifiques +# Traiter les données de types spécifiques -#### Données textuelles +## Données textuelles Les données textuelles nécessitent souvent un nettoyage et une préparation avant l'analyse. Polars fournit via la librairie de méthodes `str` un ensemble d'opérations vectorisées qui rendent la préparation des données textuelles à la fois simple et très efficace. @@ -1178,7 +1182,7 @@ df.with_columns( ``` -#### Données catégorielles +## Données catégorielles Les données catégorielles sont des variables qui contiennent un nombre restreint de modalités. A l'instar de `R` avec la notion de `factor`, Polars a un type de données spécial, `Categorical`, qui peut être utilisé pour représenter des données catégorielles. @@ -1216,7 +1220,7 @@ df['experiment'].cat.get_categories() ``` -#### Données temporelles +## Données temporelles Les données temporelles sont souvent présentes dans les données tabulaires afin d'identifier temporellement les observations recueillies. Polars offre des fonctionnalités pour manipuler ces types de données, notamment grâce au type `pl.Datetime` qui permet une manipulation précise des dates et des heures. @@ -1302,13 +1306,13 @@ df.with_columns( ) ``` -### Joindre des tables +# Joindre des tables Dans le cadre d'une analyse de données, il est courant de vouloir combiner différentes sources de données. Cette combinaison peut se faire verticalement (un DataFrame par dessus l'autre), par exemple lorsque l'on souhaite combiner deux millésimes d'une même enquête afin de les analyser conjointement. La combinaison peut également se faire horizontalement (côte à côte) selon une ou plusieurs clé(s) de jointure, souvent dans le but d'enrichir une source de données à partir d'une autre source portant sur les mêmes unités statistiques. -#### Concaténer des tables +## Concaténer des tables La concaténation verticale de tables se fait à l'aide de la fonction [`concat()`](https://docs.pola.rs/api/python/stable/reference/api/polars.concat.html#polars.concat) de Polars. @@ -1355,7 +1359,7 @@ df2 = pl.DataFrame( Pour contourner ce problème, il suffit de préférer une méthode de type `join` avec `df1.join(df2, on=df1.columns, how="full", coalesce=True)` (*cf.* ci-après). -#### Fusionner des tables +## Fusionner des tables La fusion de tables est une opération qui permet d'associer des lignes de deux DataFrames différents en se basant sur une ou plusieurs clés communes, similaire aux jointures dans les bases de données SQL. Différents types de jointure sont possible selon les données que l'on souhaite conserver, dont les principaux sont représentés sur le graphique suivant. @@ -1437,9 +1441,9 @@ df_a.join(df_b, how="full", on='key') df_a.join(df_b, how="full", on='key', coalesce=True) ``` -## Exercices +# Exercices -### Questions de compréhension +## Questions de compréhension - 1/ Qu'est-ce qu'un DataFrame dans le contexte de Polars et à quel type de structure de données peut-on le comparer dans le langage Python ? @@ -1486,7 +1490,7 @@ df_a.join(df_b, how="full", on='key', coalesce=True) ::: -### Plusieurs manières de créer un DataFrame +## Plusieurs manières de créer un DataFrame Dans la cellule suivante, nous avons récupéré des données de caisses sur les ventes de différentes enseignes. Les données sont cependant présentées de deux manières différentes, dans un cas sous forme d'observations (chaque liste contient les données d'une ligne), dans l'autre sous forme de variables (chaque liste contient les données d'une colonne). @@ -1559,7 +1563,7 @@ df_from_dict.equals(df_from_list) ::: -### Sélection de données dans un DataFrame +## Sélection de données dans un DataFrame Un DataFrame Pandas est créé avec des données de caisse (mêmes données que l'exercice précédent). @@ -1739,11 +1743,11 @@ print(df.loc[df['date_heure'].dt.date == pd.to_datetime('2022-01-03').date()]) ::: -### Exploration du fichier des prénoms +## Exploration du fichier des prénoms Le fichier des prénoms contient des données sur les prénoms attribués aux enfants nés en France entre 1900 et 2021. Ces données sont disponibles au niveau France, par département et par région, à l'adresse suivante : [https://www.insee.fr/fr/statistiques/2540004?sommaire=4767262](https://www.insee.fr/fr/statistiques/2540004?sommaire=4767262). L'objectif de ce tutoriel est de proposer une analyse de ce fichier, du nettoyage des données au statistiques sur les prénoms. -#### Partie 1 : Import et exploration des données +### Partie 1 : Import et exploration des données - Importez les données dans un DataFrame en utilisant cette [URL](https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip). @@ -1774,7 +1778,7 @@ df_prenoms.info() ::: -#### Partie 2 : Nettoyage des données +### Partie 2 : Nettoyage des données - L'output de la méthode `info()` suggère des valeurs manquantes dans la colonne des prénoms. Affichez ces lignes. Vérifiez que ces valeurs manquantes sont correctement spécifiées. @@ -1884,7 +1888,7 @@ df_prenoms.info() ::: -#### Partie 3 : Statistiques descriptives sur les naissances +### Partie 3 : Statistiques descriptives sur les naissances - La [documentation](https://www.insee.fr/fr/statistiques/2540004?sommaire=4767262#documentation) du fichier nous informe qu'on peut considérer les données comme quasi-exhaustives à partir de 1946. Pour cette partie seulement, filtrer les données pour ne conserver que les données ultérieures. @@ -1949,7 +1953,7 @@ print(top5_years) ::: -#### Partie 4 : Analyse des prénoms +### Partie 4 : Analyse des prénoms - Identifiez le nombre total de prénoms uniques dans le DataFrame. @@ -2065,7 +2069,7 @@ popularite_par_decennie(df_prenoms, sexe=2) ::: -### Calcul d'une empreinte carbone par habitant au niveau communal +## Calcul d'une empreinte carbone par habitant au niveau communal L'objectif de cet exercice est de calculer une empreinte carbone par habitant au niveau communal. Pour cela, il va falloir combiner deux sources de données : @@ -2075,7 +2079,7 @@ L'objectif de cet exercice est de calculer une empreinte carbone par habitant au Cet exercice constitue une version simplifiée d'un [TP complet pour la pratique de Pandas](https://pythonds.linogaliana.fr/content/manipulation/02b_pandas_TP.html#importer-les-donn%C3%A9es) proposé par Lino Galiana dans son [cours à l'ENSAE](https://pythonds.linogaliana.fr/). -#### Partie 1 : Exploration des données sur les populations légales communales +### Partie 1 : Exploration des données sur les populations légales communales - Importez le fichier CSV `communes.csv`. - Utilisez les méthodes `.sample()`, `.info()` et `.describe()` pour obtenir un aperçu des données. @@ -2151,7 +2155,7 @@ df_pop_communes_stats['longueur'].corr(df_pop_communes_stats['PTOT']) ::: -#### Partie 2 : Exploration des données sur les émissions communales +### Partie 2 : Exploration des données sur les émissions communales - Importez les données d'émission depuis cette [URL](https://data.ademe.fr/data-fair/api/v1/datasets/igt-pouvoir-de-rechauffement-global/data-files/IGT%20-%20Pouvoir%20de%20r%C3%A9chauffement%20global.csv) - Utilisez les méthodes `.sample()`, `.info()` et `.describe()` pour obtenir un aperçu des données. @@ -2267,7 +2271,7 @@ df_emissions.groupby("dep").agg({"emissions_totales": "sum"}).sort_values(by="em ::: -#### Partie 3 : Vérifications préalables pour la jointure des sources de données +### Partie 3 : Vérifications préalables pour la jointure des sources de données Pour effectuer une jointure, il est toujours préférable d'avoir une clé de jointure, i.e. une colonne commune aux deux sources, qui identifie uniquement les unités statistiques. L'objet de cette partie est de trouver la clé de jointure pertinente. @@ -2359,7 +2363,7 @@ df_emissions[~df_emissions["INSEE commune"].isin(df_pop_communes["DEPCOM"])] ::: -#### Partie 4 : Calcul d'une empreinte carbone par habitant pour chaque commune +### Partie 4 : Calcul d'une empreinte carbone par habitant pour chaque commune - Joindre les deux DataFrames à l'aide de la fonction à partir du code commune. Attention : les variables ne s'appellent pas de la même manière des deux côtés ! @@ -2405,7 +2409,7 @@ df_emissions_pop.sort_values("empreinte_carbone", ascending=False).head(10) ::: -### Analyse de l'évolution d'un indice de production +## Analyse de l'évolution d'un indice de production Vous avez à disposition dans le dossier `data/` deux jeux de données CSV : @@ -2417,7 +2421,7 @@ L'objectif est d'utiliser `Pandas` pour calculer : - l'évolution de l'indice entre chaque période (mois) - l'évolution de l'indice en glissement annuel (entre un mois donné et le même mois l'année suivante). -#### Partie 1 : Import des données +### Partie 1 : Import des données - Importez les deux fichiers CSV dans des DataFrames. Attention, dans les deux cas, il y a des lignes superflues avant les données, qu'il faudra sauter à l'aide du paramètre `skiprows` de la fonction [read_csv()](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html). - Donnez des noms simples et pertinents aux différentes variables. @@ -2443,7 +2447,7 @@ df_metadata = pd.read_csv('data/serie_glaces_metadonnees.csv', delimiter=';', ::: -#### Partie 2 : Filtrage des données pertinentes +### Partie 2 : Filtrage des données pertinentes - Fusionner les deux DataFrames afin de récupérer la signification des codes présents dans les données. - Filtrer les données de sorte à ne conserver que les données de type "Valeur normale". @@ -2470,7 +2474,7 @@ df_clean = df_clean[["periode", "indice"]] ::: -#### Partie 3 : Pré-traitement des données +### Partie 3 : Pré-traitement des données Vérifiez si les types des variables sont pertinents selon leur nature. Sinon, convertissez-les avec les fonctions idoines. @@ -2495,7 +2499,7 @@ df_clean.info() ::: -#### Partie 4 : Calcul de l'évolution périodique +### Partie 4 : Calcul de l'évolution périodique - Utilisez la méthode [shift()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.shift.html) pour créer une nouvelle colonne qui contiendra l'indice du trimestre précédent - Calculez la différence entre l'indice actuel et l'indice décalé pour obtenir l'évolution (en pourcentage) d'un trimestre à l'autre @@ -2522,7 +2526,7 @@ df_clean['evo_alt'] = df_clean['indice'].pct_change(periods=1) * 100 ::: -#### Partie 5 : Calcul de l'évolution glissante sur 12 mois +### Partie 5 : Calcul de l'évolution glissante sur 12 mois Comme vous avez pu le voir dans la solution de l'exercice précédent, la méthode [pct_change()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.pct_change.html) permet précisément de calculer une évolution entre deux périodes. Utiliser cette méthode pour calculer une évolution (en pourcentage) en glissement annuel pour chaque mois. diff --git a/uv.lock b/uv.lock index b1e016ce..ef3786f1 100644 --- a/uv.lock +++ b/uv.lock @@ -1,6 +1,10 @@ version = 1 revision = 3 requires-python = ">=3.13" +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version < '3.14'", +] [[package]] name = "" @@ -8,6 +12,7 @@ version = "0.0.1" source = { virtual = "." } dependencies = [ { name = "geopandas" }, + { name = "jupyter" }, { name = "matplotlib" }, { name = "numpy" }, { name = "pandas" }, @@ -23,6 +28,7 @@ dependencies = [ [package.metadata] requires-dist = [ { name = "geopandas" }, + { name = "jupyter", specifier = ">=1.1.1" }, { name = "matplotlib" }, { name = "numpy" }, { name = "pandas" }, @@ -35,6 +41,149 @@ requires-dist = [ { name = "xlrd" }, ] +[[package]] +name = "anyio" +version = "4.12.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/96/f0/5eb65b2bb0d09ac6776f2eb54adee6abe8228ea05b20a5ad0e4945de8aac/anyio-4.12.1.tar.gz", hash = "sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703", size = 228685, upload-time = "2026-01-06T11:45:21.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c", size = 113592, upload-time = "2026-01-06T11:45:19.497Z" }, +] + +[[package]] +name = "appnope" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/35/5d/752690df9ef5b76e169e68d6a129fa6d08a7100ca7f754c89495db3c6019/appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee", size = 4170, upload-time = "2024-02-06T09:43:11.258Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c", size = 4321, upload-time = "2024-02-06T09:43:09.663Z" }, +] + +[[package]] +name = "argon2-cffi" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "argon2-cffi-bindings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0e/89/ce5af8a7d472a67cc819d5d998aa8c82c5d860608c4db9f46f1162d7dab9/argon2_cffi-25.1.0.tar.gz", hash = "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1", size = 45706, upload-time = "2025-06-03T06:55:32.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl", hash = "sha256:fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741", size = 14657, upload-time = "2025-06-03T06:55:30.804Z" }, +] + +[[package]] +name = "argon2-cffi-bindings" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5c/2d/db8af0df73c1cf454f71b2bbe5e356b8c1f8041c979f505b3d3186e520a9/argon2_cffi_bindings-25.1.0.tar.gz", hash = "sha256:b957f3e6ea4d55d820e40ff76f450952807013d361a65d7f28acc0acbf29229d", size = 1783441, upload-time = "2025-07-30T10:02:05.147Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/97/3c0a35f46e52108d4707c44b95cfe2afcafc50800b5450c197454569b776/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:3d3f05610594151994ca9ccb3c771115bdb4daef161976a266f0dd8aa9996b8f", size = 54393, upload-time = "2025-07-30T10:01:40.97Z" }, + { url = "https://files.pythonhosted.org/packages/9d/f4/98bbd6ee89febd4f212696f13c03ca302b8552e7dbf9c8efa11ea4a388c3/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8b8efee945193e667a396cbc7b4fb7d357297d6234d30a489905d96caabde56b", size = 29328, upload-time = "2025-07-30T10:01:41.916Z" }, + { url = "https://files.pythonhosted.org/packages/43/24/90a01c0ef12ac91a6be05969f29944643bc1e5e461155ae6559befa8f00b/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3c6702abc36bf3ccba3f802b799505def420a1b7039862014a65db3205967f5a", size = 31269, upload-time = "2025-07-30T10:01:42.716Z" }, + { url = "https://files.pythonhosted.org/packages/d4/d3/942aa10782b2697eee7af5e12eeff5ebb325ccfb86dd8abda54174e377e4/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1c70058c6ab1e352304ac7e3b52554daadacd8d453c1752e547c76e9c99ac44", size = 86558, upload-time = "2025-07-30T10:01:43.943Z" }, + { url = "https://files.pythonhosted.org/packages/0d/82/b484f702fec5536e71836fc2dbc8c5267b3f6e78d2d539b4eaa6f0db8bf8/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e2fd3bfbff3c5d74fef31a722f729bf93500910db650c925c2d6ef879a7e51cb", size = 92364, upload-time = "2025-07-30T10:01:44.887Z" }, + { url = "https://files.pythonhosted.org/packages/c9/c1/a606ff83b3f1735f3759ad0f2cd9e038a0ad11a3de3b6c673aa41c24bb7b/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4f9665de60b1b0e99bcd6be4f17d90339698ce954cfd8d9cf4f91c995165a92", size = 85637, upload-time = "2025-07-30T10:01:46.225Z" }, + { url = "https://files.pythonhosted.org/packages/44/b4/678503f12aceb0262f84fa201f6027ed77d71c5019ae03b399b97caa2f19/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ba92837e4a9aa6a508c8d2d7883ed5a8f6c308c89a4790e1e447a220deb79a85", size = 91934, upload-time = "2025-07-30T10:01:47.203Z" }, + { url = "https://files.pythonhosted.org/packages/f0/c7/f36bd08ef9bd9f0a9cff9428406651f5937ce27b6c5b07b92d41f91ae541/argon2_cffi_bindings-25.1.0-cp314-cp314t-win32.whl", hash = "sha256:84a461d4d84ae1295871329b346a97f68eade8c53b6ed9a7ca2d7467f3c8ff6f", size = 28158, upload-time = "2025-07-30T10:01:48.341Z" }, + { url = "https://files.pythonhosted.org/packages/b3/80/0106a7448abb24a2c467bf7d527fe5413b7fdfa4ad6d6a96a43a62ef3988/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b55aec3565b65f56455eebc9b9f34130440404f27fe21c3b375bf1ea4d8fbae6", size = 32597, upload-time = "2025-07-30T10:01:49.112Z" }, + { url = "https://files.pythonhosted.org/packages/05/b8/d663c9caea07e9180b2cb662772865230715cbd573ba3b5e81793d580316/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:87c33a52407e4c41f3b70a9c2d3f6056d88b10dad7695be708c5021673f55623", size = 28231, upload-time = "2025-07-30T10:01:49.92Z" }, + { url = "https://files.pythonhosted.org/packages/1d/57/96b8b9f93166147826da5f90376e784a10582dd39a393c99bb62cfcf52f0/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:aecba1723ae35330a008418a91ea6cfcedf6d31e5fbaa056a166462ff066d500", size = 54121, upload-time = "2025-07-30T10:01:50.815Z" }, + { url = "https://files.pythonhosted.org/packages/0a/08/a9bebdb2e0e602dde230bdde8021b29f71f7841bd54801bcfd514acb5dcf/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2630b6240b495dfab90aebe159ff784d08ea999aa4b0d17efa734055a07d2f44", size = 29177, upload-time = "2025-07-30T10:01:51.681Z" }, + { url = "https://files.pythonhosted.org/packages/b6/02/d297943bcacf05e4f2a94ab6f462831dc20158614e5d067c35d4e63b9acb/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:7aef0c91e2c0fbca6fc68e7555aa60ef7008a739cbe045541e438373bc54d2b0", size = 31090, upload-time = "2025-07-30T10:01:53.184Z" }, + { url = "https://files.pythonhosted.org/packages/c1/93/44365f3d75053e53893ec6d733e4a5e3147502663554b4d864587c7828a7/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e021e87faa76ae0d413b619fe2b65ab9a037f24c60a1e6cc43457ae20de6dc6", size = 81246, upload-time = "2025-07-30T10:01:54.145Z" }, + { url = "https://files.pythonhosted.org/packages/09/52/94108adfdd6e2ddf58be64f959a0b9c7d4ef2fa71086c38356d22dc501ea/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e924cfc503018a714f94a49a149fdc0b644eaead5d1f089330399134fa028a", size = 87126, upload-time = "2025-07-30T10:01:55.074Z" }, + { url = "https://files.pythonhosted.org/packages/72/70/7a2993a12b0ffa2a9271259b79cc616e2389ed1a4d93842fac5a1f923ffd/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87b72589133f0346a1cb8d5ecca4b933e3c9b64656c9d175270a000e73b288d", size = 80343, upload-time = "2025-07-30T10:01:56.007Z" }, + { url = "https://files.pythonhosted.org/packages/78/9a/4e5157d893ffc712b74dbd868c7f62365618266982b64accab26bab01edc/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1db89609c06afa1a214a69a462ea741cf735b29a57530478c06eb81dd403de99", size = 86777, upload-time = "2025-07-30T10:01:56.943Z" }, + { url = "https://files.pythonhosted.org/packages/74/cd/15777dfde1c29d96de7f18edf4cc94c385646852e7c7b0320aa91ccca583/argon2_cffi_bindings-25.1.0-cp39-abi3-win32.whl", hash = "sha256:473bcb5f82924b1becbb637b63303ec8d10e84c8d241119419897a26116515d2", size = 27180, upload-time = "2025-07-30T10:01:57.759Z" }, + { url = "https://files.pythonhosted.org/packages/e2/c6/a759ece8f1829d1f162261226fbfd2c6832b3ff7657384045286d2afa384/argon2_cffi_bindings-25.1.0-cp39-abi3-win_amd64.whl", hash = "sha256:a98cd7d17e9f7ce244c0803cad3c23a7d379c301ba618a5fa76a67d116618b98", size = 31715, upload-time = "2025-07-30T10:01:58.56Z" }, + { url = "https://files.pythonhosted.org/packages/42/b9/f8d6fa329ab25128b7e98fd83a3cb34d9db5b059a9847eddb840a0af45dd/argon2_cffi_bindings-25.1.0-cp39-abi3-win_arm64.whl", hash = "sha256:b0fdbcf513833809c882823f98dc2f931cf659d9a1429616ac3adebb49f5db94", size = 27149, upload-time = "2025-07-30T10:01:59.329Z" }, +] + +[[package]] +name = "arrow" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, + { name = "tzdata" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/33/032cdc44182491aa708d06a68b62434140d8c50820a087fac7af37703357/arrow-1.4.0.tar.gz", hash = "sha256:ed0cc050e98001b8779e84d461b0098c4ac597e88704a655582b21d116e526d7", size = 152931, upload-time = "2025-10-18T17:46:46.761Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl", hash = "sha256:749f0769958ebdc79c173ff0b0670d59051a535fa26e8eba02953dc19eb43205", size = 68797, upload-time = "2025-10-18T17:46:45.663Z" }, +] + +[[package]] +name = "asttokens" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/be/a5/8e3f9b6771b0b408517c82d97aed8f2036509bc247d46114925e32fe33f0/asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7", size = 62308, upload-time = "2025-11-15T16:43:48.578Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", size = 27047, upload-time = "2025-11-15T16:43:16.109Z" }, +] + +[[package]] +name = "async-lru" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ef/c3/bbf34f15ea88dfb649ab2c40f9d75081784a50573a9ea431563cab64adb8/async_lru-2.1.0.tar.gz", hash = "sha256:9eeb2fecd3fe42cc8a787fc32ead53a3a7158cc43d039c3c55ab3e4e5b2a80ed", size = 12041, upload-time = "2026-01-17T22:52:18.931Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2e/e9/eb6a5db5ac505d5d45715388e92bced7a5bb556facc4d0865d192823f2d2/async_lru-2.1.0-py3-none-any.whl", hash = "sha256:fa12dcf99a42ac1280bc16c634bbaf06883809790f6304d85cdab3f666f33a7e", size = 6933, upload-time = "2026-01-17T22:52:17.389Z" }, +] + +[[package]] +name = "attrs" +version = "25.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, +] + +[[package]] +name = "babel" +version = "2.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852, upload-time = "2025-02-01T15:17:41.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537, upload-time = "2025-02-01T15:17:37.39Z" }, +] + +[[package]] +name = "beautifulsoup4" +version = "4.14.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "soupsieve" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c3/b0/1c6a16426d389813b48d95e26898aff79abbde42ad353958ad95cc8c9b21/beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86", size = 627737, upload-time = "2025-11-30T15:08:26.084Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" }, +] + +[[package]] +name = "bleach" +version = "6.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "webencodings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/07/18/3c8523962314be6bf4c8989c79ad9531c825210dd13a8669f6b84336e8bd/bleach-6.3.0.tar.gz", hash = "sha256:6f3b91b1c0a02bb9a78b5a454c92506aa0fdf197e1d5e114d2e00c6f64306d22", size = 203533, upload-time = "2025-10-27T17:57:39.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl", hash = "sha256:fe10ec77c93ddf3d13a73b035abaac7a9f5e436513864ccdad516693213c65d6", size = 164437, upload-time = "2025-10-27T17:57:37.538Z" }, +] + +[package.optional-dependencies] +css = [ + { name = "tinycss2" }, +] + [[package]] name = "certifi" version = "2026.1.4" @@ -44,6 +193,51 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c", size = 152900, upload-time = "2026-01-04T02:42:40.15Z" }, ] +[[package]] +name = "cffi" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, + { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, + { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, + { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, + { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, + { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, + { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, + { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, + { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, + { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, + { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, + { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, + { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" }, + { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" }, + { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, + { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, + { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, + { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, + { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, + { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" }, + { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" }, + { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" }, + { url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" }, + { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, + { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, + { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, + { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, + { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, + { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, +] + [[package]] name = "charset-normalizer" version = "3.4.4" @@ -85,6 +279,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, ] +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "comm" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/13/7d740c5849255756bc17888787313b61fd38a0a8304fc4f073dfc46122aa/comm-0.2.3.tar.gz", hash = "sha256:2dc8048c10962d55d7ad693be1e7045d891b7ce8d999c97963a5e3e99c055971", size = 6319, upload-time = "2025-07-25T14:02:04.452Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl", hash = "sha256:c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417", size = 7294, upload-time = "2025-07-25T14:02:02.896Z" }, +] + [[package]] name = "contourpy" version = "1.3.3" @@ -149,6 +361,59 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" }, ] +[[package]] +name = "debugpy" +version = "1.8.19" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/73/75/9e12d4d42349b817cd545b89247696c67917aab907012ae5b64bbfea3199/debugpy-1.8.19.tar.gz", hash = "sha256:eea7e5987445ab0b5ed258093722d5ecb8bb72217c5c9b1e21f64efe23ddebdb", size = 1644590, upload-time = "2025-12-15T21:53:28.044Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/3d/388035a31a59c26f1ecc8d86af607d0c42e20ef80074147cd07b180c4349/debugpy-1.8.19-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:91e35db2672a0abaf325f4868fcac9c1674a0d9ad9bb8a8c849c03a5ebba3e6d", size = 2538859, upload-time = "2025-12-15T21:53:50.478Z" }, + { url = "https://files.pythonhosted.org/packages/4a/19/c93a0772d0962294f083dbdb113af1a7427bb632d36e5314297068f55db7/debugpy-1.8.19-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:85016a73ab84dea1c1f1dcd88ec692993bcbe4532d1b49ecb5f3c688ae50c606", size = 4292575, upload-time = "2025-12-15T21:53:51.821Z" }, + { url = "https://files.pythonhosted.org/packages/5c/56/09e48ab796b0a77e3d7dc250f95251832b8bf6838c9632f6100c98bdf426/debugpy-1.8.19-cp313-cp313-win32.whl", hash = "sha256:b605f17e89ba0ecee994391194285fada89cee111cfcd29d6f2ee11cbdc40976", size = 5286209, upload-time = "2025-12-15T21:53:53.602Z" }, + { url = "https://files.pythonhosted.org/packages/fb/4e/931480b9552c7d0feebe40c73725dd7703dcc578ba9efc14fe0e6d31cfd1/debugpy-1.8.19-cp313-cp313-win_amd64.whl", hash = "sha256:c30639998a9f9cd9699b4b621942c0179a6527f083c72351f95c6ab1728d5b73", size = 5328206, upload-time = "2025-12-15T21:53:55.433Z" }, + { url = "https://files.pythonhosted.org/packages/f6/b9/cbec520c3a00508327476c7fce26fbafef98f412707e511eb9d19a2ef467/debugpy-1.8.19-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:1e8c4d1bd230067bf1bbcdbd6032e5a57068638eb28b9153d008ecde288152af", size = 2537372, upload-time = "2025-12-15T21:53:57.318Z" }, + { url = "https://files.pythonhosted.org/packages/88/5e/cf4e4dc712a141e10d58405c58c8268554aec3c35c09cdcda7535ff13f76/debugpy-1.8.19-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:d40c016c1f538dbf1762936e3aeb43a89b965069d9f60f9e39d35d9d25e6b809", size = 4268729, upload-time = "2025-12-15T21:53:58.712Z" }, + { url = "https://files.pythonhosted.org/packages/82/a3/c91a087ab21f1047db328c1d3eb5d1ff0e52de9e74f9f6f6fa14cdd93d58/debugpy-1.8.19-cp314-cp314-win32.whl", hash = "sha256:0601708223fe1cd0e27c6cce67a899d92c7d68e73690211e6788a4b0e1903f5b", size = 5286388, upload-time = "2025-12-15T21:54:00.687Z" }, + { url = "https://files.pythonhosted.org/packages/17/b8/bfdc30b6e94f1eff09f2dc9cc1f9cd1c6cde3d996bcbd36ce2d9a4956e99/debugpy-1.8.19-cp314-cp314-win_amd64.whl", hash = "sha256:8e19a725f5d486f20e53a1dde2ab8bb2c9607c40c00a42ab646def962b41125f", size = 5327741, upload-time = "2025-12-15T21:54:02.148Z" }, + { url = "https://files.pythonhosted.org/packages/25/3e/e27078370414ef35fafad2c06d182110073daaeb5d3bf734b0b1eeefe452/debugpy-1.8.19-py2.py3-none-any.whl", hash = "sha256:360ffd231a780abbc414ba0f005dad409e71c78637efe8f2bd75837132a41d38", size = 5292321, upload-time = "2025-12-15T21:54:16.024Z" }, +] + +[[package]] +name = "decorator" +version = "5.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", size = 56711, upload-time = "2025-02-24T04:41:34.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190, upload-time = "2025-02-24T04:41:32.565Z" }, +] + +[[package]] +name = "defusedxml" +version = "0.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520, upload-time = "2021-03-08T10:59:26.269Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" }, +] + +[[package]] +name = "executing" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, +] + +[[package]] +name = "fastjsonschema" +version = "2.21.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/b5/23b216d9d985a956623b6bd12d4086b60f0059b27799f23016af04a74ea1/fastjsonschema-2.21.2.tar.gz", hash = "sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de", size = 374130, upload-time = "2025-08-14T18:49:36.666Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl", hash = "sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463", size = 24024, upload-time = "2025-08-14T18:49:34.776Z" }, +] + [[package]] name = "fonttools" version = "4.61.1" @@ -182,6 +447,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/4e/ce75a57ff3aebf6fc1f4e9d508b8e5810618a33d900ad6c19eb30b290b97/fonttools-4.61.1-py3-none-any.whl", hash = "sha256:17d2bf5d541add43822bcf0c43d7d847b160c9bb01d15d5007d84e2217aaa371", size = 1148996, upload-time = "2025-12-12T17:31:21.03Z" }, ] +[[package]] +name = "fqdn" +version = "1.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/3e/a80a8c077fd798951169626cde3e239adeba7dab75deb3555716415bd9b0/fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f", size = 6015, upload-time = "2021-03-11T07:16:29.08Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014", size = 9121, upload-time = "2021-03-11T07:16:28.351Z" }, +] + [[package]] name = "geopandas" version = "1.1.2" @@ -199,6 +473,43 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/54/e4/fac19dc34cb686c96011388b813ff7b858a70681e5ce6ce7698e5021b0f4/geopandas-1.1.2-py3-none-any.whl", hash = "sha256:2bb0b1052cb47378addb4ba54c47f8d4642dcbda9b61375638274f49d9f0bb0d", size = 341734, upload-time = "2025-12-22T21:06:12.498Z" }, ] +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + [[package]] name = "idna" version = "3.11" @@ -208,6 +519,115 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, ] +[[package]] +name = "ipykernel" +version = "7.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "appnope", marker = "sys_platform == 'darwin'" }, + { name = "comm" }, + { name = "debugpy" }, + { name = "ipython" }, + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "matplotlib-inline" }, + { name = "nest-asyncio" }, + { name = "packaging" }, + { name = "psutil" }, + { name = "pyzmq" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/a4/4948be6eb88628505b83a1f2f40d90254cab66abf2043b3c40fa07dfce0f/ipykernel-7.1.0.tar.gz", hash = "sha256:58a3fc88533d5930c3546dc7eac66c6d288acde4f801e2001e65edc5dc9cf0db", size = 174579, upload-time = "2025-10-27T09:46:39.471Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/17/20c2552266728ceba271967b87919664ecc0e33efca29c3efc6baf88c5f9/ipykernel-7.1.0-py3-none-any.whl", hash = "sha256:763b5ec6c5b7776f6a8d7ce09b267693b4e5ce75cb50ae696aaefb3c85e1ea4c", size = 117968, upload-time = "2025-10-27T09:46:37.805Z" }, +] + +[[package]] +name = "ipython" +version = "9.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "decorator" }, + { name = "ipython-pygments-lexers" }, + { name = "jedi" }, + { name = "matplotlib-inline" }, + { name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "prompt-toolkit" }, + { name = "pygments" }, + { name = "stack-data" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/46/dd/fb08d22ec0c27e73c8bc8f71810709870d51cadaf27b7ddd3f011236c100/ipython-9.9.0.tar.gz", hash = "sha256:48fbed1b2de5e2c7177eefa144aba7fcb82dac514f09b57e2ac9da34ddb54220", size = 4425043, upload-time = "2026-01-05T12:36:46.233Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/86/92/162cfaee4ccf370465c5af1ce36a9eacec1becb552f2033bb3584e6f640a/ipython-9.9.0-py3-none-any.whl", hash = "sha256:b457fe9165df2b84e8ec909a97abcf2ed88f565970efba16b1f7229c283d252b", size = 621431, upload-time = "2026-01-05T12:36:44.669Z" }, +] + +[[package]] +name = "ipython-pygments-lexers" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393, upload-time = "2025-01-17T11:24:34.505Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" }, +] + +[[package]] +name = "ipywidgets" +version = "8.1.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "comm" }, + { name = "ipython" }, + { name = "jupyterlab-widgets" }, + { name = "traitlets" }, + { name = "widgetsnbextension" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4c/ae/c5ce1edc1afe042eadb445e95b0671b03cee61895264357956e61c0d2ac0/ipywidgets-8.1.8.tar.gz", hash = "sha256:61f969306b95f85fba6b6986b7fe45d73124d1d9e3023a8068710d47a22ea668", size = 116739, upload-time = "2025-11-01T21:18:12.393Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl", hash = "sha256:ecaca67aed704a338f88f67b1181b58f821ab5dc89c1f0f5ef99db43c1c2921e", size = 139808, upload-time = "2025-11-01T21:18:10.956Z" }, +] + +[[package]] +name = "isoduration" +version = "20.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "arrow" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7c/1a/3c8edc664e06e6bd06cce40c6b22da5f1429aa4224d0c590f3be21c91ead/isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9", size = 11649, upload-time = "2020-11-01T11:00:00.312Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042", size = 11321, upload-time = "2020-11-01T10:59:58.02Z" }, +] + +[[package]] +name = "jedi" +version = "0.19.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "parso" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/72/3a/79a912fbd4d8dd6fbb02bf69afd3bb72cf0c729bb3063c6f4498603db17a/jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0", size = 1231287, upload-time = "2024-11-11T01:41:42.873Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9", size = 1572278, upload-time = "2024-11-11T01:41:40.175Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + [[package]] name = "joblib" version = "1.5.3" @@ -217,6 +637,262 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713", size = 309071, upload-time = "2025-12-15T08:41:44.973Z" }, ] +[[package]] +name = "json5" +version = "0.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/77/e8/a3f261a66e4663f22700bc8a17c08cb83e91fbf086726e7a228398968981/json5-0.13.0.tar.gz", hash = "sha256:b1edf8d487721c0bf64d83c28e91280781f6e21f4a797d3261c7c828d4c165bf", size = 52441, upload-time = "2026-01-01T19:42:14.99Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d7/9e/038522f50ceb7e74f1f991bf1b699f24b0c2bbe7c390dd36ad69f4582258/json5-0.13.0-py3-none-any.whl", hash = "sha256:9a08e1dd65f6a4d4c6fa82d216cf2477349ec2346a38fd70cc11d2557499fbcc", size = 36163, upload-time = "2026-01-01T19:42:13.962Z" }, +] + +[[package]] +name = "jsonpointer" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6a/0a/eebeb1fa92507ea94016a2a790b93c2ae41a7e18778f85471dc54475ed25/jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef", size = 9114, upload-time = "2024-06-10T19:24:42.462Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942", size = 7595, upload-time = "2024-06-10T19:24:40.698Z" }, +] + +[[package]] +name = "jsonschema" +version = "4.26.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" }, +] + +[package.optional-dependencies] +format-nongpl = [ + { name = "fqdn" }, + { name = "idna" }, + { name = "isoduration" }, + { name = "jsonpointer" }, + { name = "rfc3339-validator" }, + { name = "rfc3986-validator" }, + { name = "rfc3987-syntax" }, + { name = "uri-template" }, + { name = "webcolors" }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2025.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, +] + +[[package]] +name = "jupyter" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ipykernel" }, + { name = "ipywidgets" }, + { name = "jupyter-console" }, + { name = "jupyterlab" }, + { name = "nbconvert" }, + { name = "notebook" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/58/f3/af28ea964ab8bc1e472dba2e82627d36d470c51f5cd38c37502eeffaa25e/jupyter-1.1.1.tar.gz", hash = "sha256:d55467bceabdea49d7e3624af7e33d59c37fff53ed3a350e1ac957bed731de7a", size = 5714959, upload-time = "2024-08-30T07:15:48.299Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/64/285f20a31679bf547b75602702f7800e74dbabae36ef324f716c02804753/jupyter-1.1.1-py2.py3-none-any.whl", hash = "sha256:7a59533c22af65439b24bbe60373a4e95af8f16ac65a6c00820ad378e3f7cc83", size = 2657, upload-time = "2024-08-30T07:15:47.045Z" }, +] + +[[package]] +name = "jupyter-client" +version = "8.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-core" }, + { name = "python-dateutil" }, + { name = "pyzmq" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/05/e4/ba649102a3bc3fbca54e7239fb924fd434c766f855693d86de0b1f2bec81/jupyter_client-8.8.0.tar.gz", hash = "sha256:d556811419a4f2d96c869af34e854e3f059b7cc2d6d01a9cd9c85c267691be3e", size = 348020, upload-time = "2026-01-08T13:55:47.938Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl", hash = "sha256:f93a5b99c5e23a507b773d3a1136bd6e16c67883ccdbd9a829b0bbdb98cd7d7a", size = 107371, upload-time = "2026-01-08T13:55:45.562Z" }, +] + +[[package]] +name = "jupyter-console" +version = "6.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ipykernel" }, + { name = "ipython" }, + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "prompt-toolkit" }, + { name = "pygments" }, + { name = "pyzmq" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bd/2d/e2fd31e2fc41c14e2bcb6c976ab732597e907523f6b2420305f9fc7fdbdb/jupyter_console-6.6.3.tar.gz", hash = "sha256:566a4bf31c87adbfadf22cdf846e3069b59a71ed5da71d6ba4d8aaad14a53539", size = 34363, upload-time = "2023-03-06T14:13:31.02Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ca/77/71d78d58f15c22db16328a476426f7ac4a60d3a5a7ba3b9627ee2f7903d4/jupyter_console-6.6.3-py3-none-any.whl", hash = "sha256:309d33409fcc92ffdad25f0bcdf9a4a9daa61b6f341177570fdac03de5352485", size = 24510, upload-time = "2023-03-06T14:13:28.229Z" }, +] + +[[package]] +name = "jupyter-core" +version = "5.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "platformdirs" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/49/9d1284d0dc65e2c757b74c6687b6d319b02f822ad039e5c512df9194d9dd/jupyter_core-5.9.1.tar.gz", hash = "sha256:4d09aaff303b9566c3ce657f580bd089ff5c91f5f89cf7d8846c3cdf465b5508", size = 89814, upload-time = "2025-10-16T19:19:18.444Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl", hash = "sha256:ebf87fdc6073d142e114c72c9e29a9d7ca03fad818c5d300ce2adc1fb0743407", size = 29032, upload-time = "2025-10-16T19:19:16.783Z" }, +] + +[[package]] +name = "jupyter-events" +version = "0.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jsonschema", extra = ["format-nongpl"] }, + { name = "packaging" }, + { name = "python-json-logger" }, + { name = "pyyaml" }, + { name = "referencing" }, + { name = "rfc3339-validator" }, + { name = "rfc3986-validator" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9d/c3/306d090461e4cf3cd91eceaff84bede12a8e52cd821c2d20c9a4fd728385/jupyter_events-0.12.0.tar.gz", hash = "sha256:fc3fce98865f6784c9cd0a56a20644fc6098f21c8c33834a8d9fe383c17e554b", size = 62196, upload-time = "2025-02-03T17:23:41.485Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/48/577993f1f99c552f18a0428731a755e06171f9902fa118c379eb7c04ea22/jupyter_events-0.12.0-py3-none-any.whl", hash = "sha256:6464b2fa5ad10451c3d35fabc75eab39556ae1e2853ad0c0cc31b656731a97fb", size = 19430, upload-time = "2025-02-03T17:23:38.643Z" }, +] + +[[package]] +name = "jupyter-lsp" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-server" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/5a/9066c9f8e94ee517133cd98dba393459a16cd48bba71a82f16a65415206c/jupyter_lsp-2.3.0.tar.gz", hash = "sha256:458aa59339dc868fb784d73364f17dbce8836e906cd75fd471a325cba02e0245", size = 54823, upload-time = "2025-08-27T17:47:34.671Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1a/60/1f6cee0c46263de1173894f0fafcb3475ded276c472c14d25e0280c18d6d/jupyter_lsp-2.3.0-py3-none-any.whl", hash = "sha256:e914a3cb2addf48b1c7710914771aaf1819d46b2e5a79b0f917b5478ec93f34f", size = 76687, upload-time = "2025-08-27T17:47:33.15Z" }, +] + +[[package]] +name = "jupyter-server" +version = "2.17.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "argon2-cffi" }, + { name = "jinja2" }, + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "jupyter-events" }, + { name = "jupyter-server-terminals" }, + { name = "nbconvert" }, + { name = "nbformat" }, + { name = "packaging" }, + { name = "prometheus-client" }, + { name = "pywinpty", marker = "os_name == 'nt'" }, + { name = "pyzmq" }, + { name = "send2trash" }, + { name = "terminado" }, + { name = "tornado" }, + { name = "traitlets" }, + { name = "websocket-client" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/ac/e040ec363d7b6b1f11304cc9f209dac4517ece5d5e01821366b924a64a50/jupyter_server-2.17.0.tar.gz", hash = "sha256:c38ea898566964c888b4772ae1ed58eca84592e88251d2cfc4d171f81f7e99d5", size = 731949, upload-time = "2025-08-21T14:42:54.042Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/80/a24767e6ca280f5a49525d987bf3e4d7552bf67c8be07e8ccf20271f8568/jupyter_server-2.17.0-py3-none-any.whl", hash = "sha256:e8cb9c7db4251f51ed307e329b81b72ccf2056ff82d50524debde1ee1870e13f", size = 388221, upload-time = "2025-08-21T14:42:52.034Z" }, +] + +[[package]] +name = "jupyter-server-terminals" +version = "0.5.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pywinpty", marker = "os_name == 'nt'" }, + { name = "terminado" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f4/a7/bcd0a9b0cbba88986fe944aaaf91bfda603e5a50bda8ed15123f381a3b2f/jupyter_server_terminals-0.5.4.tar.gz", hash = "sha256:bbda128ed41d0be9020349f9f1f2a4ab9952a73ed5f5ac9f1419794761fb87f5", size = 31770, upload-time = "2026-01-14T16:53:20.213Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl", hash = "sha256:55be353fc74a80bc7f3b20e6be50a55a61cd525626f578dcb66a5708e2007d14", size = 13704, upload-time = "2026-01-14T16:53:18.738Z" }, +] + +[[package]] +name = "jupyterlab" +version = "4.5.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "async-lru" }, + { name = "httpx" }, + { name = "ipykernel" }, + { name = "jinja2" }, + { name = "jupyter-core" }, + { name = "jupyter-lsp" }, + { name = "jupyter-server" }, + { name = "jupyterlab-server" }, + { name = "notebook-shim" }, + { name = "packaging" }, + { name = "setuptools" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/93/dc/2c8c4ff1aee27ac999ba04c373c5d0d7c6c181b391640d7b916b884d5985/jupyterlab-4.5.2.tar.gz", hash = "sha256:c80a6b9f6dace96a566d590c65ee2785f61e7cd4aac5b4d453dcc7d0d5e069b7", size = 23990371, upload-time = "2026-01-12T12:27:08.493Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a4/78/7e455920f104ef2aa94a4c0d2b40e5b44334ee7057eae1aa1fb97b9631ad/jupyterlab-4.5.2-py3-none-any.whl", hash = "sha256:76466ebcfdb7a9bb7e2fbd6459c0e2c032ccf75be673634a84bee4b3e6b13ab6", size = 12385807, upload-time = "2026-01-12T12:27:03.923Z" }, +] + +[[package]] +name = "jupyterlab-pygments" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/90/51/9187be60d989df97f5f0aba133fa54e7300f17616e065d1ada7d7646b6d6/jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d", size = 512900, upload-time = "2023-11-23T09:26:37.44Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780", size = 15884, upload-time = "2023-11-23T09:26:34.325Z" }, +] + +[[package]] +name = "jupyterlab-server" +version = "2.28.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "babel" }, + { name = "jinja2" }, + { name = "json5" }, + { name = "jsonschema" }, + { name = "jupyter-server" }, + { name = "packaging" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d6/2c/90153f189e421e93c4bb4f9e3f59802a1f01abd2ac5cf40b152d7f735232/jupyterlab_server-2.28.0.tar.gz", hash = "sha256:35baa81898b15f93573e2deca50d11ac0ae407ebb688299d3a5213265033712c", size = 76996, upload-time = "2025-10-22T13:59:18.37Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl", hash = "sha256:e4355b148fdcf34d312bbbc80f22467d6d20460e8b8736bf235577dd18506968", size = 59830, upload-time = "2025-10-22T13:59:16.767Z" }, +] + +[[package]] +name = "jupyterlab-widgets" +version = "3.0.16" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/26/2d/ef58fed122b268c69c0aa099da20bc67657cdfb2e222688d5731bd5b971d/jupyterlab_widgets-3.0.16.tar.gz", hash = "sha256:423da05071d55cf27a9e602216d35a3a65a3e41cdf9c5d3b643b814ce38c19e0", size = 897423, upload-time = "2025-11-01T21:11:29.724Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl", hash = "sha256:45fa36d9c6422cf2559198e4db481aa243c7a32d9926b500781c830c80f7ecf8", size = 914926, upload-time = "2025-11-01T21:11:28.008Z" }, +] + [[package]] name = "kiwisolver" version = "1.4.9" @@ -276,6 +952,67 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/80/be/3578e8afd18c88cdf9cb4cffde75a96d2be38c5a903f1ed0ceec061bd09e/kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32", size = 70260, upload-time = "2025-08-10T21:27:36.606Z" }, ] +[[package]] +name = "lark" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/34/28fff3ab31ccff1fd4f6c7c7b0ceb2b6968d8ea4950663eadcb5720591a0/lark-1.3.1.tar.gz", hash = "sha256:b426a7a6d6d53189d318f2b6236ab5d6429eaf09259f1ca33eb716eed10d2905", size = 382732, upload-time = "2025-10-27T18:25:56.653Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/3d/14ce75ef66813643812f3093ab17e46d3a206942ce7376d31ec2d36229e7/lark-1.3.1-py3-none-any.whl", hash = "sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12", size = 113151, upload-time = "2025-10-27T18:25:54.882Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, + { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, + { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, + { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, + { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, + { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, + { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, + { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, + { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, + { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, + { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, + { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, + { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, + { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, + { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, + { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, + { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, + { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, + { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, + { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, + { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, + { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, + { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, + { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, + { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, + { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, + { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, + { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, + { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, + { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, + { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, + { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, +] + [[package]] name = "matplotlib" version = "3.10.8" @@ -323,6 +1060,119 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5d/49/d651878698a0b67f23aa28e17f45a6d6dd3d3f933fa29087fa4ce5947b5a/matplotlib-3.10.8-cp314-cp314t-win_arm64.whl", hash = "sha256:113bb52413ea508ce954a02c10ffd0d565f9c3bc7f2eddc27dfe1731e71c7b5f", size = 8192560, upload-time = "2025-12-10T22:56:38.008Z" }, ] +[[package]] +name = "matplotlib-inline" +version = "0.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c7/74/97e72a36efd4ae2bccb3463284300f8953f199b5ffbc04cbbb0ec78f74b1/matplotlib_inline-0.2.1.tar.gz", hash = "sha256:e1ee949c340d771fc39e241ea75683deb94762c8fa5f2927ec57c83c4dffa9fe", size = 8110, upload-time = "2025-10-23T09:00:22.126Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76", size = 9516, upload-time = "2025-10-23T09:00:20.675Z" }, +] + +[[package]] +name = "mistune" +version = "3.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9d/55/d01f0c4b45ade6536c51170b9043db8b2ec6ddf4a35c7ea3f5f559ac935b/mistune-3.2.0.tar.gz", hash = "sha256:708487c8a8cdd99c9d90eb3ed4c3ed961246ff78ac82f03418f5183ab70e398a", size = 95467, upload-time = "2025-12-23T11:36:34.994Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl", hash = "sha256:febdc629a3c78616b94393c6580551e0e34cc289987ec6c35ed3f4be42d0eee1", size = 53598, upload-time = "2025-12-23T11:36:33.211Z" }, +] + +[[package]] +name = "nbclient" +version = "0.10.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "nbformat" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/56/91/1c1d5a4b9a9ebba2b4e32b8c852c2975c872aec1fe42ab5e516b2cecd193/nbclient-0.10.4.tar.gz", hash = "sha256:1e54091b16e6da39e297b0ece3e10f6f29f4ac4e8ee515d29f8a7099bd6553c9", size = 62554, upload-time = "2025-12-23T07:45:46.369Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl", hash = "sha256:9162df5a7373d70d606527300a95a975a47c137776cd942e52d9c7e29ff83440", size = 25465, upload-time = "2025-12-23T07:45:44.51Z" }, +] + +[[package]] +name = "nbconvert" +version = "7.16.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beautifulsoup4" }, + { name = "bleach", extra = ["css"] }, + { name = "defusedxml" }, + { name = "jinja2" }, + { name = "jupyter-core" }, + { name = "jupyterlab-pygments" }, + { name = "markupsafe" }, + { name = "mistune" }, + { name = "nbclient" }, + { name = "nbformat" }, + { name = "packaging" }, + { name = "pandocfilters" }, + { name = "pygments" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a3/59/f28e15fc47ffb73af68a8d9b47367a8630d76e97ae85ad18271b9db96fdf/nbconvert-7.16.6.tar.gz", hash = "sha256:576a7e37c6480da7b8465eefa66c17844243816ce1ccc372633c6b71c3c0f582", size = 857715, upload-time = "2025-01-28T09:29:14.724Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/9a/cd673b2f773a12c992f41309ef81b99da1690426bd2f96957a7ade0d3ed7/nbconvert-7.16.6-py3-none-any.whl", hash = "sha256:1375a7b67e0c2883678c48e506dc320febb57685e5ee67faa51b18a90f3a712b", size = 258525, upload-time = "2025-01-28T09:29:12.551Z" }, +] + +[[package]] +name = "nbformat" +version = "5.10.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fastjsonschema" }, + { name = "jsonschema" }, + { name = "jupyter-core" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6d/fd/91545e604bc3dad7dca9ed03284086039b294c6b3d75c0d2fa45f9e9caf3/nbformat-5.10.4.tar.gz", hash = "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a", size = 142749, upload-time = "2024-04-04T11:20:37.371Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b", size = 78454, upload-time = "2024-04-04T11:20:34.895Z" }, +] + +[[package]] +name = "nest-asyncio" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/83/f8/51569ac65d696c8ecbee95938f89d4abf00f47d58d48f6fbabfe8f0baefe/nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", size = 7418, upload-time = "2024-01-21T14:25:19.227Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195, upload-time = "2024-01-21T14:25:17.223Z" }, +] + +[[package]] +name = "notebook" +version = "7.5.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-server" }, + { name = "jupyterlab" }, + { name = "jupyterlab-server" }, + { name = "notebook-shim" }, + { name = "tornado" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3b/b6/6b2c653570b02e4ec2a94c0646a4a25132be0749617776d0b72a2bcedb9b/notebook-7.5.2.tar.gz", hash = "sha256:83e82f93c199ca730313bea1bb24bc279ea96f74816d038a92d26b6b9d5f3e4a", size = 14059605, upload-time = "2026-01-12T14:56:53.483Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/55/b754cd51c6011d90ef03e3f06136f1ebd44658b9529dbcf0c15fc0d6a0b7/notebook-7.5.2-py3-none-any.whl", hash = "sha256:17d078a98603d70d62b6b4b3fcb67e87d7a68c398a7ae9b447eb2d7d9aec9979", size = 14468915, upload-time = "2026-01-12T14:56:47.87Z" }, +] + +[[package]] +name = "notebook-shim" +version = "0.2.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-server" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/54/d2/92fa3243712b9a3e8bafaf60aac366da1cada3639ca767ff4b5b3654ec28/notebook_shim-0.2.4.tar.gz", hash = "sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb", size = 13167, upload-time = "2024-02-14T23:35:18.353Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/33/bd5b9137445ea4b680023eb0469b2bb969d61303dedb2aac6560ff3d14a1/notebook_shim-0.2.4-py3-none-any.whl", hash = "sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef", size = 13307, upload-time = "2024-02-14T23:35:16.286Z" }, +] + [[package]] name = "numpy" version = "2.4.0" @@ -422,6 +1272,36 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/70/44/5191d2e4026f86a2a109053e194d3ba7a31a2d10a9c2348368c63ed4e85a/pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87", size = 13202175, upload-time = "2025-09-29T23:31:59.173Z" }, ] +[[package]] +name = "pandocfilters" +version = "1.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/70/6f/3dd4940bbe001c06a65f88e36bad298bc7a0de5036115639926b0c5c0458/pandocfilters-1.5.1.tar.gz", hash = "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e", size = 8454, upload-time = "2024-01-18T20:08:13.726Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/af/4fbc8cab944db5d21b7e2a5b8e9211a03a79852b1157e2c102fcc61ac440/pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc", size = 8663, upload-time = "2024-01-18T20:08:11.28Z" }, +] + +[[package]] +name = "parso" +version = "0.8.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d4/de/53e0bcf53d13e005bd8c92e7855142494f41171b34c2536b86187474184d/parso-0.8.5.tar.gz", hash = "sha256:034d7354a9a018bdce352f48b2a8a450f05e9d6ee85db84764e9b6bd96dafe5a", size = 401205, upload-time = "2025-08-23T15:15:28.028Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/16/32/f8e3c85d1d5250232a5d3477a2a28cc291968ff175caeadaf3cc19ce0e4a/parso-0.8.5-py2.py3-none-any.whl", hash = "sha256:646204b5ee239c396d040b90f9e272e9a8017c630092bf59980beb62fd033887", size = 106668, upload-time = "2025-08-23T15:15:25.663Z" }, +] + +[[package]] +name = "pexpect" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ptyprocess" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" }, +] + [[package]] name = "pillow" version = "12.1.0" @@ -480,6 +1360,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fc/f5/68334c015eed9b5cff77814258717dec591ded209ab5b6fb70e2ae873d1d/pillow-12.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:f61333d817698bdcdd0f9d7793e365ac3d2a21c1f1eb02b32ad6aefb8d8ea831", size = 2545104, upload-time = "2026-01-02T09:13:12.068Z" }, ] +[[package]] +name = "platformdirs" +version = "4.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cf/86/0248f086a84f01b37aaec0fa567b397df1a119f73c16f6c7a9aac73ea309/platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda", size = 21715, upload-time = "2025-12-05T13:52:58.638Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31", size = 18731, upload-time = "2025-12-05T13:52:56.823Z" }, +] + [[package]] name = "polars" version = "1.36.1" @@ -506,6 +1395,73 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d8/a12e6aa14f63784cead437083319ec7cece0d5bb9a5bfe7678cc6578b52a/polars_runtime_32-1.36.1-cp39-abi3-win_arm64.whl", hash = "sha256:809e73857be71250141225ddd5d2b30c97e6340aeaa0d445f930e01bef6888dc", size = 39798896, upload-time = "2025-12-10T01:14:11.568Z" }, ] +[[package]] +name = "prometheus-client" +version = "0.24.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f0/58/a794d23feb6b00fc0c72787d7e87d872a6730dd9ed7c7b3e954637d8f280/prometheus_client-0.24.1.tar.gz", hash = "sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9", size = 85616, upload-time = "2026-01-14T15:26:26.965Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl", hash = "sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055", size = 64057, upload-time = "2026-01-14T15:26:24.42Z" }, +] + +[[package]] +name = "prompt-toolkit" +version = "3.0.52" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, +] + +[[package]] +name = "psutil" +version = "7.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/73/cb/09e5184fb5fc0358d110fc3ca7f6b1d033800734d34cac10f4136cfac10e/psutil-7.2.1.tar.gz", hash = "sha256:f7583aec590485b43ca601dd9cea0dcd65bd7bb21d30ef4ddbf4ea6b5ed1bdd3", size = 490253, upload-time = "2025-12-29T08:26:00.169Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/8e/f0c242053a368c2aa89584ecd1b054a18683f13d6e5a318fc9ec36582c94/psutil-7.2.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ba9f33bb525b14c3ea563b2fd521a84d2fa214ec59e3e6a2858f78d0844dd60d", size = 129624, upload-time = "2025-12-29T08:26:04.255Z" }, + { url = "https://files.pythonhosted.org/packages/26/97/a58a4968f8990617decee234258a2b4fc7cd9e35668387646c1963e69f26/psutil-7.2.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:81442dac7abfc2f4f4385ea9e12ddf5a796721c0f6133260687fec5c3780fa49", size = 130132, upload-time = "2025-12-29T08:26:06.228Z" }, + { url = "https://files.pythonhosted.org/packages/db/6d/ed44901e830739af5f72a85fa7ec5ff1edea7f81bfbf4875e409007149bd/psutil-7.2.1-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ea46c0d060491051d39f0d2cff4f98d5c72b288289f57a21556cc7d504db37fc", size = 180612, upload-time = "2025-12-29T08:26:08.276Z" }, + { url = "https://files.pythonhosted.org/packages/c7/65/b628f8459bca4efbfae50d4bf3feaab803de9a160b9d5f3bd9295a33f0c2/psutil-7.2.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:35630d5af80d5d0d49cfc4d64c1c13838baf6717a13effb35869a5919b854cdf", size = 183201, upload-time = "2025-12-29T08:26:10.622Z" }, + { url = "https://files.pythonhosted.org/packages/fb/23/851cadc9764edcc18f0effe7d0bf69f727d4cf2442deb4a9f78d4e4f30f2/psutil-7.2.1-cp313-cp313t-win_amd64.whl", hash = "sha256:923f8653416604e356073e6e0bccbe7c09990acef442def2f5640dd0faa9689f", size = 139081, upload-time = "2025-12-29T08:26:12.483Z" }, + { url = "https://files.pythonhosted.org/packages/59/82/d63e8494ec5758029f31c6cb06d7d161175d8281e91d011a4a441c8a43b5/psutil-7.2.1-cp313-cp313t-win_arm64.whl", hash = "sha256:cfbe6b40ca48019a51827f20d830887b3107a74a79b01ceb8cc8de4ccb17b672", size = 134767, upload-time = "2025-12-29T08:26:14.528Z" }, + { url = "https://files.pythonhosted.org/packages/05/c2/5fb764bd61e40e1fe756a44bd4c21827228394c17414ade348e28f83cd79/psutil-7.2.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:494c513ccc53225ae23eec7fe6e1482f1b8a44674241b54561f755a898650679", size = 129716, upload-time = "2025-12-29T08:26:16.017Z" }, + { url = "https://files.pythonhosted.org/packages/c9/d2/935039c20e06f615d9ca6ca0ab756cf8408a19d298ffaa08666bc18dc805/psutil-7.2.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3fce5f92c22b00cdefd1645aa58ab4877a01679e901555067b1bd77039aa589f", size = 130133, upload-time = "2025-12-29T08:26:18.009Z" }, + { url = "https://files.pythonhosted.org/packages/77/69/19f1eb0e01d24c2b3eacbc2f78d3b5add8a89bf0bb69465bc8d563cc33de/psutil-7.2.1-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93f3f7b0bb07711b49626e7940d6fe52aa9940ad86e8f7e74842e73189712129", size = 181518, upload-time = "2025-12-29T08:26:20.241Z" }, + { url = "https://files.pythonhosted.org/packages/e1/6d/7e18b1b4fa13ad370787626c95887b027656ad4829c156bb6569d02f3262/psutil-7.2.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d34d2ca888208eea2b5c68186841336a7f5e0b990edec929be909353a202768a", size = 184348, upload-time = "2025-12-29T08:26:22.215Z" }, + { url = "https://files.pythonhosted.org/packages/98/60/1672114392dd879586d60dd97896325df47d9a130ac7401318005aab28ec/psutil-7.2.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2ceae842a78d1603753561132d5ad1b2f8a7979cb0c283f5b52fb4e6e14b1a79", size = 140400, upload-time = "2025-12-29T08:26:23.993Z" }, + { url = "https://files.pythonhosted.org/packages/fb/7b/d0e9d4513c46e46897b46bcfc410d51fc65735837ea57a25170f298326e6/psutil-7.2.1-cp314-cp314t-win_arm64.whl", hash = "sha256:08a2f175e48a898c8eb8eace45ce01777f4785bc744c90aa2cc7f2fa5462a266", size = 135430, upload-time = "2025-12-29T08:26:25.999Z" }, + { url = "https://files.pythonhosted.org/packages/c5/cf/5180eb8c8bdf6a503c6919f1da28328bd1e6b3b1b5b9d5b01ae64f019616/psutil-7.2.1-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b2e953fcfaedcfbc952b44744f22d16575d3aa78eb4f51ae74165b4e96e55f42", size = 128137, upload-time = "2025-12-29T08:26:27.759Z" }, + { url = "https://files.pythonhosted.org/packages/c5/2c/78e4a789306a92ade5000da4f5de3255202c534acdadc3aac7b5458fadef/psutil-7.2.1-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:05cc68dbb8c174828624062e73078e7e35406f4ca2d0866c272c2410d8ef06d1", size = 128947, upload-time = "2025-12-29T08:26:29.548Z" }, + { url = "https://files.pythonhosted.org/packages/29/f8/40e01c350ad9a2b3cb4e6adbcc8a83b17ee50dd5792102b6142385937db5/psutil-7.2.1-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e38404ca2bb30ed7267a46c02f06ff842e92da3bb8c5bfdadbd35a5722314d8", size = 154694, upload-time = "2025-12-29T08:26:32.147Z" }, + { url = "https://files.pythonhosted.org/packages/06/e4/b751cdf839c011a9714a783f120e6a86b7494eb70044d7d81a25a5cd295f/psutil-7.2.1-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab2b98c9fc19f13f59628d94df5cc4cc4844bc572467d113a8b517d634e362c6", size = 156136, upload-time = "2025-12-29T08:26:34.079Z" }, + { url = "https://files.pythonhosted.org/packages/44/ad/bbf6595a8134ee1e94a4487af3f132cef7fce43aef4a93b49912a48c3af7/psutil-7.2.1-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f78baafb38436d5a128f837fab2d92c276dfb48af01a240b861ae02b2413ada8", size = 148108, upload-time = "2025-12-29T08:26:36.225Z" }, + { url = "https://files.pythonhosted.org/packages/1c/15/dd6fd869753ce82ff64dcbc18356093471a5a5adf4f77ed1f805d473d859/psutil-7.2.1-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:99a4cd17a5fdd1f3d014396502daa70b5ec21bf4ffe38393e152f8e449757d67", size = 147402, upload-time = "2025-12-29T08:26:39.21Z" }, + { url = "https://files.pythonhosted.org/packages/34/68/d9317542e3f2b180c4306e3f45d3c922d7e86d8ce39f941bb9e2e9d8599e/psutil-7.2.1-cp37-abi3-win_amd64.whl", hash = "sha256:b1b0671619343aa71c20ff9767eced0483e4fc9e1f489d50923738caf6a03c17", size = 136938, upload-time = "2025-12-29T08:26:41.036Z" }, + { url = "https://files.pythonhosted.org/packages/3e/73/2ce007f4198c80fcf2cb24c169884f833fe93fbc03d55d302627b094ee91/psutil-7.2.1-cp37-abi3-win_arm64.whl", hash = "sha256:0d67c1822c355aa6f7314d92018fb4268a76668a536f133599b91edd48759442", size = 133836, upload-time = "2025-12-29T08:26:43.086Z" }, +] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762, upload-time = "2020-12-28T15:15:30.155Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993, upload-time = "2020-12-28T15:15:28.35Z" }, +] + +[[package]] +name = "pure-eval" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752, upload-time = "2024-07-21T12:58:21.801Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" }, +] + [[package]] name = "pyarrow" version = "22.0.0" @@ -542,6 +1498,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7b/03/f335d6c52b4a4761bcc83499789a1e2e16d9d201a58c327a9b5cc9a41bd9/pyarrow-22.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0c34fe18094686194f204a3b1787a27456897d8a2d62caf84b61e8dfbc0252ae", size = 29185594, upload-time = "2025-10-24T10:09:53.111Z" }, ] +[[package]] +name = "pycparser" +version = "3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + [[package]] name = "pyogrio" version = "0.12.1" @@ -647,6 +1621,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, ] +[[package]] +name = "python-json-logger" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/29/bf/eca6a3d43db1dae7070f70e160ab20b807627ba953663ba07928cdd3dc58/python_json_logger-4.0.0.tar.gz", hash = "sha256:f58e68eb46e1faed27e0f574a55a0455eecd7b8a5b88b85a784519ba3cff047f", size = 17683, upload-time = "2025-10-06T04:15:18.984Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl", hash = "sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2", size = 15548, upload-time = "2025-10-06T04:15:17.553Z" }, +] + [[package]] name = "pytz" version = "2025.2" @@ -656,6 +1639,110 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" }, ] +[[package]] +name = "pywinpty" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/bb/a7cc2967c5c4eceb6cc49cfe39447d4bfc56e6c865e7c2249b6eb978935f/pywinpty-3.0.2.tar.gz", hash = "sha256:1505cc4cb248af42cb6285a65c9c2086ee9e7e574078ee60933d5d7fa86fb004", size = 30669, upload-time = "2025-10-03T21:16:29.205Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fc/19/b757fe28008236a4a713e813283721b8a40aa60cd7d3f83549f2e25a3155/pywinpty-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:18f78b81e4cfee6aabe7ea8688441d30247b73e52cd9657138015c5f4ee13a51", size = 2050057, upload-time = "2025-10-03T21:19:26.732Z" }, + { url = "https://files.pythonhosted.org/packages/cb/44/cbae12ecf6f4fa4129c36871fd09c6bef4f98d5f625ecefb5e2449765508/pywinpty-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:663383ecfab7fc382cc97ea5c4f7f0bb32c2f889259855df6ea34e5df42d305b", size = 2049874, upload-time = "2025-10-03T21:18:53.923Z" }, + { url = "https://files.pythonhosted.org/packages/ca/15/f12c6055e2d7a617d4d5820e8ac4ceaff849da4cb124640ef5116a230771/pywinpty-3.0.2-cp314-cp314-win_amd64.whl", hash = "sha256:28297cecc37bee9f24d8889e47231972d6e9e84f7b668909de54f36ca785029a", size = 2050386, upload-time = "2025-10-03T21:18:50.477Z" }, + { url = "https://files.pythonhosted.org/packages/de/24/c6907c5bb06043df98ad6a0a0ff5db2e0affcecbc3b15c42404393a3f72a/pywinpty-3.0.2-cp314-cp314t-win_amd64.whl", hash = "sha256:34b55ae9a1b671fe3eae071d86618110538e8eaad18fcb1531c0830b91a82767", size = 2049834, upload-time = "2025-10-03T21:19:25.688Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] + +[[package]] +name = "pyzmq" +version = "27.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "implementation_name == 'pypy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/0b/3c9baedbdf613ecaa7aa07027780b8867f57b6293b6ee50de316c9f3222b/pyzmq-27.1.0.tar.gz", hash = "sha256:ac0765e3d44455adb6ddbf4417dcce460fc40a05978c08efdf2948072f6db540", size = 281750, upload-time = "2025-09-08T23:10:18.157Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:452631b640340c928fa343801b0d07eb0c3789a5ffa843f6e1a9cee0ba4eb4fc", size = 1306279, upload-time = "2025-09-08T23:08:03.807Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5e/c3c49fdd0f535ef45eefcc16934648e9e59dace4a37ee88fc53f6cd8e641/pyzmq-27.1.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1c179799b118e554b66da67d88ed66cd37a169f1f23b5d9f0a231b4e8d44a113", size = 895645, upload-time = "2025-09-08T23:08:05.301Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e5/b0b2504cb4e903a74dcf1ebae157f9e20ebb6ea76095f6cfffea28c42ecd/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3837439b7f99e60312f0c926a6ad437b067356dc2bc2ec96eb395fd0fe804233", size = 652574, upload-time = "2025-09-08T23:08:06.828Z" }, + { url = "https://files.pythonhosted.org/packages/f8/9b/c108cdb55560eaf253f0cbdb61b29971e9fb34d9c3499b0e96e4e60ed8a5/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43ad9a73e3da1fab5b0e7e13402f0b2fb934ae1c876c51d0afff0e7c052eca31", size = 840995, upload-time = "2025-09-08T23:08:08.396Z" }, + { url = "https://files.pythonhosted.org/packages/c2/bb/b79798ca177b9eb0825b4c9998c6af8cd2a7f15a6a1a4272c1d1a21d382f/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0de3028d69d4cdc475bfe47a6128eb38d8bc0e8f4d69646adfbcd840facbac28", size = 1642070, upload-time = "2025-09-08T23:08:09.989Z" }, + { url = "https://files.pythonhosted.org/packages/9c/80/2df2e7977c4ede24c79ae39dcef3899bfc5f34d1ca7a5b24f182c9b7a9ca/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:cf44a7763aea9298c0aa7dbf859f87ed7012de8bda0f3977b6fb1d96745df856", size = 2021121, upload-time = "2025-09-08T23:08:11.907Z" }, + { url = "https://files.pythonhosted.org/packages/46/bd/2d45ad24f5f5ae7e8d01525eb76786fa7557136555cac7d929880519e33a/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f30f395a9e6fbca195400ce833c731e7b64c3919aa481af4d88c3759e0cb7496", size = 1878550, upload-time = "2025-09-08T23:08:13.513Z" }, + { url = "https://files.pythonhosted.org/packages/e6/2f/104c0a3c778d7c2ab8190e9db4f62f0b6957b53c9d87db77c284b69f33ea/pyzmq-27.1.0-cp312-abi3-win32.whl", hash = "sha256:250e5436a4ba13885494412b3da5d518cd0d3a278a1ae640e113c073a5f88edd", size = 559184, upload-time = "2025-09-08T23:08:15.163Z" }, + { url = "https://files.pythonhosted.org/packages/fc/7f/a21b20d577e4100c6a41795842028235998a643b1ad406a6d4163ea8f53e/pyzmq-27.1.0-cp312-abi3-win_amd64.whl", hash = "sha256:9ce490cf1d2ca2ad84733aa1d69ce6855372cb5ce9223802450c9b2a7cba0ccf", size = 619480, upload-time = "2025-09-08T23:08:17.192Z" }, + { url = "https://files.pythonhosted.org/packages/78/c2/c012beae5f76b72f007a9e91ee9401cb88c51d0f83c6257a03e785c81cc2/pyzmq-27.1.0-cp312-abi3-win_arm64.whl", hash = "sha256:75a2f36223f0d535a0c919e23615fc85a1e23b71f40c7eb43d7b1dedb4d8f15f", size = 552993, upload-time = "2025-09-08T23:08:18.926Z" }, + { url = "https://files.pythonhosted.org/packages/60/cb/84a13459c51da6cec1b7b1dc1a47e6db6da50b77ad7fd9c145842750a011/pyzmq-27.1.0-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:93ad4b0855a664229559e45c8d23797ceac03183c7b6f5b4428152a6b06684a5", size = 1122436, upload-time = "2025-09-08T23:08:20.801Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b6/94414759a69a26c3dd674570a81813c46a078767d931a6c70ad29fc585cb/pyzmq-27.1.0-cp313-cp313-android_24_x86_64.whl", hash = "sha256:fbb4f2400bfda24f12f009cba62ad5734148569ff4949b1b6ec3b519444342e6", size = 1156301, upload-time = "2025-09-08T23:08:22.47Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ad/15906493fd40c316377fd8a8f6b1f93104f97a752667763c9b9c1b71d42d/pyzmq-27.1.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:e343d067f7b151cfe4eb3bb796a7752c9d369eed007b91231e817071d2c2fec7", size = 1341197, upload-time = "2025-09-08T23:08:24.286Z" }, + { url = "https://files.pythonhosted.org/packages/14/1d/d343f3ce13db53a54cb8946594e567410b2125394dafcc0268d8dda027e0/pyzmq-27.1.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:08363b2011dec81c354d694bdecaef4770e0ae96b9afea70b3f47b973655cc05", size = 897275, upload-time = "2025-09-08T23:08:26.063Z" }, + { url = "https://files.pythonhosted.org/packages/69/2d/d83dd6d7ca929a2fc67d2c3005415cdf322af7751d773524809f9e585129/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d54530c8c8b5b8ddb3318f481297441af102517602b569146185fa10b63f4fa9", size = 660469, upload-time = "2025-09-08T23:08:27.623Z" }, + { url = "https://files.pythonhosted.org/packages/3e/cd/9822a7af117f4bc0f1952dbe9ef8358eb50a24928efd5edf54210b850259/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f3afa12c392f0a44a2414056d730eebc33ec0926aae92b5ad5cf26ebb6cc128", size = 847961, upload-time = "2025-09-08T23:08:29.672Z" }, + { url = "https://files.pythonhosted.org/packages/9a/12/f003e824a19ed73be15542f172fd0ec4ad0b60cf37436652c93b9df7c585/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c65047adafe573ff023b3187bb93faa583151627bc9c51fc4fb2c561ed689d39", size = 1650282, upload-time = "2025-09-08T23:08:31.349Z" }, + { url = "https://files.pythonhosted.org/packages/d5/4a/e82d788ed58e9a23995cee70dbc20c9aded3d13a92d30d57ec2291f1e8a3/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:90e6e9441c946a8b0a667356f7078d96411391a3b8f80980315455574177ec97", size = 2024468, upload-time = "2025-09-08T23:08:33.543Z" }, + { url = "https://files.pythonhosted.org/packages/d9/94/2da0a60841f757481e402b34bf4c8bf57fa54a5466b965de791b1e6f747d/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:add071b2d25f84e8189aaf0882d39a285b42fa3853016ebab234a5e78c7a43db", size = 1885394, upload-time = "2025-09-08T23:08:35.51Z" }, + { url = "https://files.pythonhosted.org/packages/4f/6f/55c10e2e49ad52d080dc24e37adb215e5b0d64990b57598abc2e3f01725b/pyzmq-27.1.0-cp313-cp313t-win32.whl", hash = "sha256:7ccc0700cfdf7bd487bea8d850ec38f204478681ea02a582a8da8171b7f90a1c", size = 574964, upload-time = "2025-09-08T23:08:37.178Z" }, + { url = "https://files.pythonhosted.org/packages/87/4d/2534970ba63dd7c522d8ca80fb92777f362c0f321900667c615e2067cb29/pyzmq-27.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:8085a9fba668216b9b4323be338ee5437a235fe275b9d1610e422ccc279733e2", size = 641029, upload-time = "2025-09-08T23:08:40.595Z" }, + { url = "https://files.pythonhosted.org/packages/f6/fa/f8aea7a28b0641f31d40dea42d7ef003fded31e184ef47db696bc74cd610/pyzmq-27.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:6bb54ca21bcfe361e445256c15eedf083f153811c37be87e0514934d6913061e", size = 561541, upload-time = "2025-09-08T23:08:42.668Z" }, + { url = "https://files.pythonhosted.org/packages/87/45/19efbb3000956e82d0331bafca5d9ac19ea2857722fa2caacefb6042f39d/pyzmq-27.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:ce980af330231615756acd5154f29813d553ea555485ae712c491cd483df6b7a", size = 1341197, upload-time = "2025-09-08T23:08:44.973Z" }, + { url = "https://files.pythonhosted.org/packages/48/43/d72ccdbf0d73d1343936296665826350cb1e825f92f2db9db3e61c2162a2/pyzmq-27.1.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1779be8c549e54a1c38f805e56d2a2e5c009d26de10921d7d51cfd1c8d4632ea", size = 897175, upload-time = "2025-09-08T23:08:46.601Z" }, + { url = "https://files.pythonhosted.org/packages/2f/2e/a483f73a10b65a9ef0161e817321d39a770b2acf8bcf3004a28d90d14a94/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7200bb0f03345515df50d99d3db206a0a6bee1955fbb8c453c76f5bf0e08fb96", size = 660427, upload-time = "2025-09-08T23:08:48.187Z" }, + { url = "https://files.pythonhosted.org/packages/f5/d2/5f36552c2d3e5685abe60dfa56f91169f7a2d99bbaf67c5271022ab40863/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01c0e07d558b06a60773744ea6251f769cd79a41a97d11b8bf4ab8f034b0424d", size = 847929, upload-time = "2025-09-08T23:08:49.76Z" }, + { url = "https://files.pythonhosted.org/packages/c4/2a/404b331f2b7bf3198e9945f75c4c521f0c6a3a23b51f7a4a401b94a13833/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:80d834abee71f65253c91540445d37c4c561e293ba6e741b992f20a105d69146", size = 1650193, upload-time = "2025-09-08T23:08:51.7Z" }, + { url = "https://files.pythonhosted.org/packages/1c/0b/f4107e33f62a5acf60e3ded67ed33d79b4ce18de432625ce2fc5093d6388/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:544b4e3b7198dde4a62b8ff6685e9802a9a1ebf47e77478a5eb88eca2a82f2fd", size = 2024388, upload-time = "2025-09-08T23:08:53.393Z" }, + { url = "https://files.pythonhosted.org/packages/0d/01/add31fe76512642fd6e40e3a3bd21f4b47e242c8ba33efb6809e37076d9b/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cedc4c68178e59a4046f97eca31b148ddcf51e88677de1ef4e78cf06c5376c9a", size = 1885316, upload-time = "2025-09-08T23:08:55.702Z" }, + { url = "https://files.pythonhosted.org/packages/c4/59/a5f38970f9bf07cee96128de79590bb354917914a9be11272cfc7ff26af0/pyzmq-27.1.0-cp314-cp314t-win32.whl", hash = "sha256:1f0b2a577fd770aa6f053211a55d1c47901f4d537389a034c690291485e5fe92", size = 587472, upload-time = "2025-09-08T23:08:58.18Z" }, + { url = "https://files.pythonhosted.org/packages/70/d8/78b1bad170f93fcf5e3536e70e8fadac55030002275c9a29e8f5719185de/pyzmq-27.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:19c9468ae0437f8074af379e986c5d3d7d7bfe033506af442e8c879732bedbe0", size = 661401, upload-time = "2025-09-08T23:08:59.802Z" }, + { url = "https://files.pythonhosted.org/packages/81/d6/4bfbb40c9a0b42fc53c7cf442f6385db70b40f74a783130c5d0a5aa62228/pyzmq-27.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dc5dbf68a7857b59473f7df42650c621d7e8923fb03fa74a526890f4d33cc4d7", size = 575170, upload-time = "2025-09-08T23:09:01.418Z" }, +] + +[[package]] +name = "referencing" +version = "0.37.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" }, +] + [[package]] name = "requests" version = "2.32.5" @@ -671,6 +1758,105 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, ] +[[package]] +name = "rfc3339-validator" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/ea/a9387748e2d111c3c2b275ba970b735e04e15cdb1eb30693b6b5708c4dbd/rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b", size = 5513, upload-time = "2021-05-12T16:37:54.178Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa", size = 3490, upload-time = "2021-05-12T16:37:52.536Z" }, +] + +[[package]] +name = "rfc3986-validator" +version = "0.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/88/f270de456dd7d11dcc808abfa291ecdd3f45ff44e3b549ffa01b126464d0/rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055", size = 6760, upload-time = "2019-10-28T16:00:19.144Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9", size = 4242, upload-time = "2019-10-28T16:00:13.976Z" }, +] + +[[package]] +name = "rfc3987-syntax" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "lark" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2c/06/37c1a5557acf449e8e406a830a05bf885ac47d33270aec454ef78675008d/rfc3987_syntax-1.1.0.tar.gz", hash = "sha256:717a62cbf33cffdd16dfa3a497d81ce48a660ea691b1ddd7be710c22f00b4a0d", size = 14239, upload-time = "2025-07-18T01:05:05.015Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl", hash = "sha256:6c3d97604e4c5ce9f714898e05401a0445a641cfa276432b0a648c80856f6a3f", size = 8046, upload-time = "2025-07-18T01:05:03.843Z" }, +] + +[[package]] +name = "rpds-py" +version = "0.30.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469, upload-time = "2025-11-30T20:24:38.837Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ed/dc/d61221eb88ff410de3c49143407f6f3147acf2538c86f2ab7ce65ae7d5f9/rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2", size = 374887, upload-time = "2025-11-30T20:22:41.812Z" }, + { url = "https://files.pythonhosted.org/packages/fd/32/55fb50ae104061dbc564ef15cc43c013dc4a9f4527a1f4d99baddf56fe5f/rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8", size = 358904, upload-time = "2025-11-30T20:22:43.479Z" }, + { url = "https://files.pythonhosted.org/packages/58/70/faed8186300e3b9bdd138d0273109784eea2396c68458ed580f885dfe7ad/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4", size = 389945, upload-time = "2025-11-30T20:22:44.819Z" }, + { url = "https://files.pythonhosted.org/packages/bd/a8/073cac3ed2c6387df38f71296d002ab43496a96b92c823e76f46b8af0543/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136", size = 407783, upload-time = "2025-11-30T20:22:46.103Z" }, + { url = "https://files.pythonhosted.org/packages/77/57/5999eb8c58671f1c11eba084115e77a8899d6e694d2a18f69f0ba471ec8b/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7", size = 515021, upload-time = "2025-11-30T20:22:47.458Z" }, + { url = "https://files.pythonhosted.org/packages/e0/af/5ab4833eadc36c0a8ed2bc5c0de0493c04f6c06de223170bd0798ff98ced/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2", size = 414589, upload-time = "2025-11-30T20:22:48.872Z" }, + { url = "https://files.pythonhosted.org/packages/b7/de/f7192e12b21b9e9a68a6d0f249b4af3fdcdff8418be0767a627564afa1f1/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6", size = 394025, upload-time = "2025-11-30T20:22:50.196Z" }, + { url = "https://files.pythonhosted.org/packages/91/c4/fc70cd0249496493500e7cc2de87504f5aa6509de1e88623431fec76d4b6/rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e", size = 408895, upload-time = "2025-11-30T20:22:51.87Z" }, + { url = "https://files.pythonhosted.org/packages/58/95/d9275b05ab96556fefff73a385813eb66032e4c99f411d0795372d9abcea/rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d", size = 422799, upload-time = "2025-11-30T20:22:53.341Z" }, + { url = "https://files.pythonhosted.org/packages/06/c1/3088fc04b6624eb12a57eb814f0d4997a44b0d208d6cace713033ff1a6ba/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7", size = 572731, upload-time = "2025-11-30T20:22:54.778Z" }, + { url = "https://files.pythonhosted.org/packages/d8/42/c612a833183b39774e8ac8fecae81263a68b9583ee343db33ab571a7ce55/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31", size = 599027, upload-time = "2025-11-30T20:22:56.212Z" }, + { url = "https://files.pythonhosted.org/packages/5f/60/525a50f45b01d70005403ae0e25f43c0384369ad24ffe46e8d9068b50086/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95", size = 563020, upload-time = "2025-11-30T20:22:58.2Z" }, + { url = "https://files.pythonhosted.org/packages/0b/5d/47c4655e9bcd5ca907148535c10e7d489044243cc9941c16ed7cd53be91d/rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d", size = 223139, upload-time = "2025-11-30T20:23:00.209Z" }, + { url = "https://files.pythonhosted.org/packages/f2/e1/485132437d20aa4d3e1d8b3fb5a5e65aa8139f1e097080c2a8443201742c/rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15", size = 240224, upload-time = "2025-11-30T20:23:02.008Z" }, + { url = "https://files.pythonhosted.org/packages/24/95/ffd128ed1146a153d928617b0ef673960130be0009c77d8fbf0abe306713/rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1", size = 230645, upload-time = "2025-11-30T20:23:03.43Z" }, + { url = "https://files.pythonhosted.org/packages/ff/1b/b10de890a0def2a319a2626334a7f0ae388215eb60914dbac8a3bae54435/rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a", size = 364443, upload-time = "2025-11-30T20:23:04.878Z" }, + { url = "https://files.pythonhosted.org/packages/0d/bf/27e39f5971dc4f305a4fb9c672ca06f290f7c4e261c568f3dea16a410d47/rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e", size = 353375, upload-time = "2025-11-30T20:23:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/40/58/442ada3bba6e8e6615fc00483135c14a7538d2ffac30e2d933ccf6852232/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000", size = 383850, upload-time = "2025-11-30T20:23:07.825Z" }, + { url = "https://files.pythonhosted.org/packages/14/14/f59b0127409a33c6ef6f5c1ebd5ad8e32d7861c9c7adfa9a624fc3889f6c/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db", size = 392812, upload-time = "2025-11-30T20:23:09.228Z" }, + { url = "https://files.pythonhosted.org/packages/b3/66/e0be3e162ac299b3a22527e8913767d869e6cc75c46bd844aa43fb81ab62/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2", size = 517841, upload-time = "2025-11-30T20:23:11.186Z" }, + { url = "https://files.pythonhosted.org/packages/3d/55/fa3b9cf31d0c963ecf1ba777f7cf4b2a2c976795ac430d24a1f43d25a6ba/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa", size = 408149, upload-time = "2025-11-30T20:23:12.864Z" }, + { url = "https://files.pythonhosted.org/packages/60/ca/780cf3b1a32b18c0f05c441958d3758f02544f1d613abf9488cd78876378/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083", size = 383843, upload-time = "2025-11-30T20:23:14.638Z" }, + { url = "https://files.pythonhosted.org/packages/82/86/d5f2e04f2aa6247c613da0c1dd87fcd08fa17107e858193566048a1e2f0a/rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9", size = 396507, upload-time = "2025-11-30T20:23:16.105Z" }, + { url = "https://files.pythonhosted.org/packages/4b/9a/453255d2f769fe44e07ea9785c8347edaf867f7026872e76c1ad9f7bed92/rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0", size = 414949, upload-time = "2025-11-30T20:23:17.539Z" }, + { url = "https://files.pythonhosted.org/packages/a3/31/622a86cdc0c45d6df0e9ccb6becdba5074735e7033c20e401a6d9d0e2ca0/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94", size = 565790, upload-time = "2025-11-30T20:23:19.029Z" }, + { url = "https://files.pythonhosted.org/packages/1c/5d/15bbf0fb4a3f58a3b1c67855ec1efcc4ceaef4e86644665fff03e1b66d8d/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08", size = 590217, upload-time = "2025-11-30T20:23:20.885Z" }, + { url = "https://files.pythonhosted.org/packages/6d/61/21b8c41f68e60c8cc3b2e25644f0e3681926020f11d06ab0b78e3c6bbff1/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27", size = 555806, upload-time = "2025-11-30T20:23:22.488Z" }, + { url = "https://files.pythonhosted.org/packages/f9/39/7e067bb06c31de48de3eb200f9fc7c58982a4d3db44b07e73963e10d3be9/rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6", size = 211341, upload-time = "2025-11-30T20:23:24.449Z" }, + { url = "https://files.pythonhosted.org/packages/0a/4d/222ef0b46443cf4cf46764d9c630f3fe4abaa7245be9417e56e9f52b8f65/rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d", size = 225768, upload-time = "2025-11-30T20:23:25.908Z" }, + { url = "https://files.pythonhosted.org/packages/86/81/dad16382ebbd3d0e0328776d8fd7ca94220e4fa0798d1dc5e7da48cb3201/rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0", size = 362099, upload-time = "2025-11-30T20:23:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/2b/60/19f7884db5d5603edf3c6bce35408f45ad3e97e10007df0e17dd57af18f8/rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be", size = 353192, upload-time = "2025-11-30T20:23:29.151Z" }, + { url = "https://files.pythonhosted.org/packages/bf/c4/76eb0e1e72d1a9c4703c69607cec123c29028bff28ce41588792417098ac/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f", size = 384080, upload-time = "2025-11-30T20:23:30.785Z" }, + { url = "https://files.pythonhosted.org/packages/72/87/87ea665e92f3298d1b26d78814721dc39ed8d2c74b86e83348d6b48a6f31/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f", size = 394841, upload-time = "2025-11-30T20:23:32.209Z" }, + { url = "https://files.pythonhosted.org/packages/77/ad/7783a89ca0587c15dcbf139b4a8364a872a25f861bdb88ed99f9b0dec985/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87", size = 516670, upload-time = "2025-11-30T20:23:33.742Z" }, + { url = "https://files.pythonhosted.org/packages/5b/3c/2882bdac942bd2172f3da574eab16f309ae10a3925644e969536553cb4ee/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18", size = 408005, upload-time = "2025-11-30T20:23:35.253Z" }, + { url = "https://files.pythonhosted.org/packages/ce/81/9a91c0111ce1758c92516a3e44776920b579d9a7c09b2b06b642d4de3f0f/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad", size = 382112, upload-time = "2025-11-30T20:23:36.842Z" }, + { url = "https://files.pythonhosted.org/packages/cf/8e/1da49d4a107027e5fbc64daeab96a0706361a2918da10cb41769244b805d/rpds_py-0.30.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07", size = 399049, upload-time = "2025-11-30T20:23:38.343Z" }, + { url = "https://files.pythonhosted.org/packages/df/5a/7ee239b1aa48a127570ec03becbb29c9d5a9eb092febbd1699d567cae859/rpds_py-0.30.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f", size = 415661, upload-time = "2025-11-30T20:23:40.263Z" }, + { url = "https://files.pythonhosted.org/packages/70/ea/caa143cf6b772f823bc7929a45da1fa83569ee49b11d18d0ada7f5ee6fd6/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65", size = 565606, upload-time = "2025-11-30T20:23:42.186Z" }, + { url = "https://files.pythonhosted.org/packages/64/91/ac20ba2d69303f961ad8cf55bf7dbdb4763f627291ba3d0d7d67333cced9/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f", size = 591126, upload-time = "2025-11-30T20:23:44.086Z" }, + { url = "https://files.pythonhosted.org/packages/21/20/7ff5f3c8b00c8a95f75985128c26ba44503fb35b8e0259d812766ea966c7/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53", size = 553371, upload-time = "2025-11-30T20:23:46.004Z" }, + { url = "https://files.pythonhosted.org/packages/72/c7/81dadd7b27c8ee391c132a6b192111ca58d866577ce2d9b0ca157552cce0/rpds_py-0.30.0-cp314-cp314-win32.whl", hash = "sha256:ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed", size = 215298, upload-time = "2025-11-30T20:23:47.696Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d2/1aaac33287e8cfb07aab2e6b8ac1deca62f6f65411344f1433c55e6f3eb8/rpds_py-0.30.0-cp314-cp314-win_amd64.whl", hash = "sha256:95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950", size = 228604, upload-time = "2025-11-30T20:23:49.501Z" }, + { url = "https://files.pythonhosted.org/packages/e8/95/ab005315818cc519ad074cb7784dae60d939163108bd2b394e60dc7b5461/rpds_py-0.30.0-cp314-cp314-win_arm64.whl", hash = "sha256:613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6", size = 222391, upload-time = "2025-11-30T20:23:50.96Z" }, + { url = "https://files.pythonhosted.org/packages/9e/68/154fe0194d83b973cdedcdcc88947a2752411165930182ae41d983dcefa6/rpds_py-0.30.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb", size = 364868, upload-time = "2025-11-30T20:23:52.494Z" }, + { url = "https://files.pythonhosted.org/packages/83/69/8bbc8b07ec854d92a8b75668c24d2abcb1719ebf890f5604c61c9369a16f/rpds_py-0.30.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8", size = 353747, upload-time = "2025-11-30T20:23:54.036Z" }, + { url = "https://files.pythonhosted.org/packages/ab/00/ba2e50183dbd9abcce9497fa5149c62b4ff3e22d338a30d690f9af970561/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7", size = 383795, upload-time = "2025-11-30T20:23:55.556Z" }, + { url = "https://files.pythonhosted.org/packages/05/6f/86f0272b84926bcb0e4c972262f54223e8ecc556b3224d281e6598fc9268/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898", size = 393330, upload-time = "2025-11-30T20:23:57.033Z" }, + { url = "https://files.pythonhosted.org/packages/cb/e9/0e02bb2e6dc63d212641da45df2b0bf29699d01715913e0d0f017ee29438/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e", size = 518194, upload-time = "2025-11-30T20:23:58.637Z" }, + { url = "https://files.pythonhosted.org/packages/ee/ca/be7bca14cf21513bdf9c0606aba17d1f389ea2b6987035eb4f62bd923f25/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419", size = 408340, upload-time = "2025-11-30T20:24:00.2Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c7/736e00ebf39ed81d75544c0da6ef7b0998f8201b369acf842f9a90dc8fce/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551", size = 383765, upload-time = "2025-11-30T20:24:01.759Z" }, + { url = "https://files.pythonhosted.org/packages/4a/3f/da50dfde9956aaf365c4adc9533b100008ed31aea635f2b8d7b627e25b49/rpds_py-0.30.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8", size = 396834, upload-time = "2025-11-30T20:24:03.687Z" }, + { url = "https://files.pythonhosted.org/packages/4e/00/34bcc2565b6020eab2623349efbdec810676ad571995911f1abdae62a3a0/rpds_py-0.30.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5", size = 415470, upload-time = "2025-11-30T20:24:05.232Z" }, + { url = "https://files.pythonhosted.org/packages/8c/28/882e72b5b3e6f718d5453bd4d0d9cf8df36fddeb4ddbbab17869d5868616/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404", size = 565630, upload-time = "2025-11-30T20:24:06.878Z" }, + { url = "https://files.pythonhosted.org/packages/3b/97/04a65539c17692de5b85c6e293520fd01317fd878ea1995f0367d4532fb1/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856", size = 591148, upload-time = "2025-11-30T20:24:08.445Z" }, + { url = "https://files.pythonhosted.org/packages/85/70/92482ccffb96f5441aab93e26c4d66489eb599efdcf96fad90c14bbfb976/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40", size = 556030, upload-time = "2025-11-30T20:24:10.956Z" }, + { url = "https://files.pythonhosted.org/packages/20/53/7c7e784abfa500a2b6b583b147ee4bb5a2b3747a9166bab52fec4b5b5e7d/rpds_py-0.30.0-cp314-cp314t-win32.whl", hash = "sha256:dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0", size = 211570, upload-time = "2025-11-30T20:24:12.735Z" }, + { url = "https://files.pythonhosted.org/packages/d0/02/fa464cdfbe6b26e0600b62c528b72d8608f5cc49f96b8d6e38c95d60c676/rpds_py-0.30.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3", size = 226532, upload-time = "2025-11-30T20:24:14.634Z" }, +] + [[package]] name = "scikit-learn" version = "1.8.0" @@ -774,6 +1960,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/83/11/00d3c3dfc25ad54e731d91449895a79e4bf2384dc3ac01809010ba88f6d5/seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987", size = 294914, upload-time = "2024-01-25T13:21:49.598Z" }, ] +[[package]] +name = "send2trash" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c5/f0/184b4b5f8d00f2a92cf96eec8967a3d550b52cf94362dad1100df9e48d57/send2trash-2.1.0.tar.gz", hash = "sha256:1c72b39f09457db3c05ce1d19158c2cbef4c32b8bedd02c155e49282b7ea7459", size = 17255, upload-time = "2026-01-14T06:27:36.056Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1c/78/504fdd027da3b84ff1aecd9f6957e65f35134534ccc6da8628eb71e76d3f/send2trash-2.1.0-py3-none-any.whl", hash = "sha256:0da2f112e6d6bb22de6aa6daa7e144831a4febf2a87261451c4ad849fe9a873c", size = 17610, upload-time = "2026-01-14T06:27:35.218Z" }, +] + +[[package]] +name = "setuptools" +version = "80.10.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/86/ff/f75651350db3cf2ef767371307eb163f3cc1ac03e16fdf3ac347607f7edb/setuptools-80.10.1.tar.gz", hash = "sha256:bf2e513eb8144c3298a3bd28ab1a5edb739131ec5c22e045ff93cd7f5319703a", size = 1229650, upload-time = "2026-01-21T09:42:03.061Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/76/f963c61683a39084aa575f98089253e1e852a4417cb8a3a8a422923a5246/setuptools-80.10.1-py3-none-any.whl", hash = "sha256:fc30c51cbcb8199a219c12cc9c281b5925a4978d212f84229c909636d9f6984e", size = 1099859, upload-time = "2026-01-21T09:42:00.688Z" }, +] + [[package]] name = "shapely" version = "2.1.2" @@ -826,6 +2030,43 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, ] +[[package]] +name = "soupsieve" +version = "2.8.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/ae/2d9c981590ed9999a0d91755b47fc74f74de286b0f5cee14c9269041e6c4/soupsieve-2.8.3.tar.gz", hash = "sha256:3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349", size = 118627, upload-time = "2026-01-20T04:27:02.457Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl", hash = "sha256:ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95", size = 37016, upload-time = "2026-01-20T04:27:01.012Z" }, +] + +[[package]] +name = "stack-data" +version = "0.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asttokens" }, + { name = "executing" }, + { name = "pure-eval" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707, upload-time = "2023-09-30T13:58:05.479Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" }, +] + +[[package]] +name = "terminado" +version = "0.18.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ptyprocess", marker = "os_name != 'nt'" }, + { name = "pywinpty", marker = "os_name == 'nt'" }, + { name = "tornado" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8a/11/965c6fd8e5cc254f1fe142d547387da17a8ebfd75a3455f637c663fb38a0/terminado-0.18.1.tar.gz", hash = "sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e", size = 32701, upload-time = "2024-03-12T14:34:39.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl", hash = "sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0", size = 14154, upload-time = "2024-03-12T14:34:36.569Z" }, +] + [[package]] name = "threadpoolctl" version = "3.6.0" @@ -848,6 +2089,55 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4b/c5/fe58f5ff266d15d22c3eb214c04d035c606febd317ea51cac85e212e74de/tidypolars-0.3.2-py3-none-any.whl", hash = "sha256:73ca614730c38abc63e30db832e599b098e95ea7094d9cff60fe24733b0a5293", size = 18731, upload-time = "2024-11-02T14:49:19.513Z" }, ] +[[package]] +name = "tinycss2" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "webencodings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7a/fd/7a5ee21fd08ff70d3d33a5781c255cbe779659bd03278feb98b19ee550f4/tinycss2-1.4.0.tar.gz", hash = "sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7", size = 87085, upload-time = "2024-10-24T14:58:29.895Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289", size = 26610, upload-time = "2024-10-24T14:58:28.029Z" }, +] + +[[package]] +name = "tornado" +version = "6.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/37/1d/0a336abf618272d53f62ebe274f712e213f5a03c0b2339575430b8362ef2/tornado-6.5.4.tar.gz", hash = "sha256:a22fa9047405d03260b483980635f0b041989d8bcc9a313f8fe18b411d84b1d7", size = 513632, upload-time = "2025-12-15T19:21:03.836Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/a9/e94a9d5224107d7ce3cc1fab8d5dc97f5ea351ccc6322ee4fb661da94e35/tornado-6.5.4-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:d6241c1a16b1c9e4cc28148b1cda97dd1c6cb4fb7068ac1bedc610768dff0ba9", size = 443909, upload-time = "2025-12-15T19:20:48.382Z" }, + { url = "https://files.pythonhosted.org/packages/db/7e/f7b8d8c4453f305a51f80dbb49014257bb7d28ccb4bbb8dd328ea995ecad/tornado-6.5.4-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2d50f63dda1d2cac3ae1fa23d254e16b5e38153758470e9956cbc3d813d40843", size = 442163, upload-time = "2025-12-15T19:20:49.791Z" }, + { url = "https://files.pythonhosted.org/packages/ba/b5/206f82d51e1bfa940ba366a8d2f83904b15942c45a78dd978b599870ab44/tornado-6.5.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1cf66105dc6acb5af613c054955b8137e34a03698aa53272dbda4afe252be17", size = 445746, upload-time = "2025-12-15T19:20:51.491Z" }, + { url = "https://files.pythonhosted.org/packages/8e/9d/1a3338e0bd30ada6ad4356c13a0a6c35fbc859063fa7eddb309183364ac1/tornado-6.5.4-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50ff0a58b0dc97939d29da29cd624da010e7f804746621c78d14b80238669335", size = 445083, upload-time = "2025-12-15T19:20:52.778Z" }, + { url = "https://files.pythonhosted.org/packages/50/d4/e51d52047e7eb9a582da59f32125d17c0482d065afd5d3bc435ff2120dc5/tornado-6.5.4-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5fb5e04efa54cf0baabdd10061eb4148e0be137166146fff835745f59ab9f7f", size = 445315, upload-time = "2025-12-15T19:20:53.996Z" }, + { url = "https://files.pythonhosted.org/packages/27/07/2273972f69ca63dbc139694a3fc4684edec3ea3f9efabf77ed32483b875c/tornado-6.5.4-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9c86b1643b33a4cd415f8d0fe53045f913bf07b4a3ef646b735a6a86047dda84", size = 446003, upload-time = "2025-12-15T19:20:56.101Z" }, + { url = "https://files.pythonhosted.org/packages/d1/83/41c52e47502bf7260044413b6770d1a48dda2f0246f95ee1384a3cd9c44a/tornado-6.5.4-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:6eb82872335a53dd063a4f10917b3efd28270b56a33db69009606a0312660a6f", size = 445412, upload-time = "2025-12-15T19:20:57.398Z" }, + { url = "https://files.pythonhosted.org/packages/10/c7/bc96917f06cbee182d44735d4ecde9c432e25b84f4c2086143013e7b9e52/tornado-6.5.4-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6076d5dda368c9328ff41ab5d9dd3608e695e8225d1cd0fd1e006f05da3635a8", size = 445392, upload-time = "2025-12-15T19:20:58.692Z" }, + { url = "https://files.pythonhosted.org/packages/0c/1a/d7592328d037d36f2d2462f4bc1fbb383eec9278bc786c1b111cbbd44cfa/tornado-6.5.4-cp39-abi3-win32.whl", hash = "sha256:1768110f2411d5cd281bac0a090f707223ce77fd110424361092859e089b38d1", size = 446481, upload-time = "2025-12-15T19:21:00.008Z" }, + { url = "https://files.pythonhosted.org/packages/d6/6d/c69be695a0a64fd37a97db12355a035a6d90f79067a3cf936ec2b1dc38cd/tornado-6.5.4-cp39-abi3-win_amd64.whl", hash = "sha256:fa07d31e0cd85c60713f2b995da613588aa03e1303d75705dca6af8babc18ddc", size = 446886, upload-time = "2025-12-15T19:21:01.287Z" }, + { url = "https://files.pythonhosted.org/packages/50/49/8dc3fd90902f70084bd2cd059d576ddb4f8bb44c2c7c0e33a11422acb17e/tornado-6.5.4-cp39-abi3-win_arm64.whl", hash = "sha256:053e6e16701eb6cbe641f308f4c1a9541f91b6261991160391bfc342e8a551a1", size = 445910, upload-time = "2025-12-15T19:21:02.571Z" }, +] + +[[package]] +name = "traitlets" +version = "5.14.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/eb/79/72064e6a701c2183016abbbfedaba506d81e30e232a68c9f0d6f6fcd1574/traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", size = 161621, upload-time = "2024-04-19T11:11:49.746Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f", size = 85359, upload-time = "2024-04-19T11:11:46.763Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] + [[package]] name = "tzdata" version = "2025.3" @@ -857,6 +2147,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, ] +[[package]] +name = "uri-template" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/31/c7/0336f2bd0bcbada6ccef7aaa25e443c118a704f828a0620c6fa0207c1b64/uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7", size = 21678, upload-time = "2023-06-21T01:49:05.374Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363", size = 11140, upload-time = "2023-06-21T01:49:03.467Z" }, +] + [[package]] name = "urllib3" version = "2.6.2" @@ -866,6 +2165,51 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl", hash = "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd", size = 131182, upload-time = "2025-12-11T15:56:38.584Z" }, ] +[[package]] +name = "wcwidth" +version = "0.2.14" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/24/30/6b0809f4510673dc723187aeaf24c7f5459922d01e2f794277a3dfb90345/wcwidth-0.2.14.tar.gz", hash = "sha256:4d478375d31bc5395a3c55c40ccdf3354688364cd61c4f6adacaa9215d0b3605", size = 102293, upload-time = "2025-09-22T16:29:53.023Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl", hash = "sha256:a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1", size = 37286, upload-time = "2025-09-22T16:29:51.641Z" }, +] + +[[package]] +name = "webcolors" +version = "25.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/7a/eb316761ec35664ea5174709a68bbd3389de60d4a1ebab8808bfc264ed67/webcolors-25.10.0.tar.gz", hash = "sha256:62abae86504f66d0f6364c2a8520de4a0c47b80c03fc3a5f1815fedbef7c19bf", size = 53491, upload-time = "2025-10-31T07:51:03.977Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl", hash = "sha256:032c727334856fc0b968f63daa252a1ac93d33db2f5267756623c210e57a4f1d", size = 14905, upload-time = "2025-10-31T07:51:01.778Z" }, +] + +[[package]] +name = "webencodings" +version = "0.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923", size = 9721, upload-time = "2017-04-05T20:21:34.189Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774, upload-time = "2017-04-05T20:21:32.581Z" }, +] + +[[package]] +name = "websocket-client" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2c/41/aa4bf9664e4cda14c3b39865b12251e8e7d239f4cd0e3cc1b6c2ccde25c1/websocket_client-1.9.0.tar.gz", hash = "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", size = 70576, upload-time = "2025-10-07T21:16:36.495Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/34/db/b10e48aa8fff7407e67470363eac595018441cf32d5e1001567a7aeba5d2/websocket_client-1.9.0-py3-none-any.whl", hash = "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef", size = 82616, upload-time = "2025-10-07T21:16:34.951Z" }, +] + +[[package]] +name = "widgetsnbextension" +version = "4.0.15" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/f4/c67440c7fb409a71b7404b7aefcd7569a9c0d6bd071299bf4198ae7a5d95/widgetsnbextension-4.0.15.tar.gz", hash = "sha256:de8610639996f1567952d763a5a41af8af37f2575a41f9852a38f947eb82a3b9", size = 1097402, upload-time = "2025-11-01T21:15:55.178Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl", hash = "sha256:8156704e4346a571d9ce73b84bee86a29906c9abfd7223b7228a28899ccf3366", size = 2196503, upload-time = "2025-11-01T21:15:53.565Z" }, +] + [[package]] name = "xlrd" version = "2.0.2" From ea060fac74820bc6b67e37d428fbf726cfdd17f4 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 28 Jan 2026 17:24:39 +0000 Subject: [PATCH 32/92] with typos and unnest --- source/manipulation/polars/tutorial.qmd | 42 +++++++++++++++++-------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 851b519d..f2811f74 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -158,7 +158,6 @@ Parler de : - pas d'index. - polars selectors - lazy eval -- unnest "TO DO" - Polars Séries @@ -259,6 +258,15 @@ A noter qu'une valeur manquante est indiquée par `None` en Polars. Elle sera en Un DataFrame Polars dispose d'un ensemble d'attributs utiles que nous allons découvrir tout au long de ce tutoriel. Pour l'instant, intéressons-nous aux plus basiques : le nom des colonnes. ```{python} +df = pl.DataFrame( + data = { + "var1": [1.3, 5.6, None, None, 0, None], + "experiment": ["test", "train", "test", "train", "train", "validation"], + "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-01-05", "2022-01-06"], + "sample": "sample1" + }, strict=False +) + df.columns ``` @@ -452,6 +460,7 @@ A la différence de Pandas et à la date d'écriture de ce tutoriel, Polars ne c Soit on utilise la fonction idoine de `pandas` et après on transforme le dataframe en `polars` facilement grâce à la fonction `pl.from_pandas`. ```{python} +import pandas as pd url = "https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip" pl.from_pandas(pd.read_csv(url, delimiter=";")) ``` @@ -460,6 +469,8 @@ Si l'on veut éviter une dépendance à `pandas` juste pour cette opération, il Prenons l'exemple d'un fichier CSV disponible sur le site de l'INSEE : le fichier des prénoms, issu des données de l'état civil. ```{python} +import requests + # Téléchargement et stockage du nom du fichier url = "https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip" file_Path = url.split('/')[-1] @@ -483,14 +494,15 @@ En regardant le message d'erreur, Polars traite la colonne `anais` comme un enti Mais la lecture de la valeur `XXXX` cause une erreur et n'est pas convertible en entier par Polars. ```{python} -df_prenoms_url = pl.read_csv('temp/'+os.listdir('temp')[0], separator=";") +import os +df_prenoms_url = pl.read_csv('temp/' + os.listdir('temp')[0], separator=";") ``` Dans ce cas, deux solutions existent : - On peut dire à Polars de traiter toutes les colonnes comme des caractères avec infer_schema=False ```{python} -df_prenoms_url = pl.read_csv('temp/'+os.listdir('temp')[0], separator=";", infer_schema=False) +df_prenoms_url = pl.read_csv('temp/' + os.listdir('temp')[0], separator=";", infer_schema=False) df_prenoms_url ``` @@ -629,25 +641,29 @@ On retrouve dans le DataFrame les trois colonnes dont la clé représente le nom La première et dernière colonnes sont des valeurs constantes au format `pl.String` et les résultats sont stockés dans la colonne `features`. Cette dernière est au format `pl.Struct`, qui fonctionne de manière similaire à un dictionnaire. -On peut facilement récupérer le détail des résultats grâce à la méthode `unnest` : +::: {.callout-tip} +La méthode `unnest` est **très pratique** en travaillant avec des formats JSON. +Elle permet facilement de passer d'un format structuré à un format plus standard (numérique ou textuel). +Ainsi, pour récupérer le détail des résultats de l'appel à l'API, il suffit d'utiliser la méthode `unnest`. +On l'applique à plusieurs reprises et on veille à supprimer les colonnes intermédiaires qui ont des noms identiques pour *applatir* le data frame: ```{python} -df = df.select("features").unnest("features") -df +df = df.select("features").unnest("features").drop('type').unnest('geometry').drop('type').unnest('properties') ``` +::: + ### Autres exports et imports - **Exporter vers un dictionnaire**: - De manière similaire, Polars permet d'exporter un DataFrame vers un dictionnaire. - - La méthode `to_dict` permet d'exporter un DataFrame "en format colonne". - L'export sera un seul dictionnaire dont les clés sont les noms des colonnes et - les valeurs les listes des valeurs prises par colonne `{'a':[1, 2, 3], 'b': [3, 2, 1]}`. - - La méthode `to_dicts`permet d'exporter le DataFrame "en format ligne". - L'export sera une liste dont les termes seront les lignes du DataFrame, - représentées à chaque fois par un dictionnaire : `[{'a': 1, 'b': 3}, {'a': 2, 'b': 2}, {'a': 3, 'b': 1}]` + - La méthode `to_dict` permet d'exporter un DataFrame "en format colonne". +L'export sera un seul dictionnaire dont les clés sont les noms des colonnes et +les valeurs les listes des valeurs prises par colonne `{'a':[1, 2, 3], 'b': [3, 2, 1]}`. + - La méthode `to_dicts`permet d'exporter le DataFrame "en format ligne". +L'export sera une liste dont les termes seront les lignes du DataFrame, +représentées à chaque fois par un dictionnaire : `[{'a': 1, 'b': 3}, {'a': 2, 'b': 2}, {'a': 3, 'b': 1}]` - **Depuis/vers Pandas**: Polars permet aussi facilement d'exporter et d'importer des DataFrame au format Pandas. From abb20f6365cfe61f4cdae11ca3ca5265ce9e3191 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 24 Feb 2026 13:39:01 +0000 Subject: [PATCH 33/92] uv for rendering notebooks --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index cdd25cd9..88c6782a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Formation - Initiation à Python -*Auteur : Romain Avouac* +_Auteur : Romain Avouac_ -*Contributeurs : Yves-Laurent Bénichou, Olivier Chateau, Thomas Faria, Antoine Palazzolo* +_Contributeurs : Yves-Laurent Bénichou, Olivier Chateau, Thomas Faria, Antoine Palazzolo_ ## Site associé @@ -15,6 +15,7 @@ Ce projet contient les supports de cours de l'auto-formation d'initiation à Pyt ## Génération des notebooks Afin de favoriser la reproductibilité de la formation, les sources des supports de cours sont disponibles au format `.qmd` ([Quarto](https://quarto.org/)) dans les différents sous-dossiers du dossier `source/`. Les notebooks `Jupyter` (format `.ipynb`) exécutables associés peuvent être générés en suivant les étapes suivantes : + - [installer Quarto](https://quarto.org/docs/get-started/) - cloner le dépôt de la formation : @@ -26,13 +27,13 @@ cd formation-python-initiation - installer les packages `Python` nécessaires : ```bash -pip install -r requirements.txt +uv sync ``` - générer les notebooks : ```bash -quarto render --profile notebooks +uv run quarto render --profile notebooks ``` -Une fois l'étape de *rendering* terminée, les notebooks générés au format `.ipynb` sont disponibles dans les différents sous-dossiers du dossier `source/`. +Une fois l'étape de _rendering_ terminée, les notebooks générés au format `.ipynb` sont disponibles dans les différents sous-dossiers du dossier `source/`. From 1f21ff670952cabd8a36591aa059e7f16b7f6446 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 24 Feb 2026 14:52:44 +0000 Subject: [PATCH 34/92] intro polars --- source/manipulation/polars/tutorial.qmd | 197 ++++++++---------------- 1 file changed, 63 insertions(+), 134 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index f2811f74..276143cd 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -1,173 +1,102 @@ ::: {.content-visible when-profile="fr"} -# Traiter des données tabulaires avec Polars +# Introduction - traiter des données tabulaires avec Polars L'analyse statistique a généralement pour base des **données tabulaires**, dans lesquelles chaque ligne représente une observation et chaque colonne une variable. Pour traiter ce type de données et y appliquer facilement les méthodes d'analyse de données standards, des objets dédiés ont été conçus : les `DataFrames`. Les utilisateurs de `R` connaissent bien cette structure de données, qui est native à ce langage orienté statistique. En `Python`, langage généraliste, cet objet n'existe pas nativement. -Plusieurs packages viennent ainsi combler ce manque, comme `pandas`, XX. +Plusieurs packages viennent ainsi combler ce manque, comme `pandas` ou `polars`. -## Les atouts de Polars +## Pourquoi `polars`? -Les _benchmarks_ disponibles [sont clairs](https://h2oai.github.io/db-benchmark/) : `Polars` est -un ours qui court vite ! +Comment choisir entre les deux ? Cela va dépendre de vos goûts et de vos besoins. +Mais voici en attendant quelques éléments pour savoir si `polars` est utile. -Le benchmark suivant, [effectué par H2O](https://h2oai.github.io/db-benchmark/), propose -un comparatif de la vitesse des principaux frameworks de manipulation de données -pour effectuer une agrégation par groupe avec un jeu de données de 50GB: +- Polars est rapide et permet de traiter des données volumineuses : Selon un benchmark [effectué par H2O](https://h2oai.github.io/db-benchmark/), +Polars permet de traiter des données que d'autres librairies ne pourraient pas () +et les traite aussi rapidement que le package `R` `data.table`. et 3 à 4 fois plus vite que d'autres librairies. -![Benchmark H2O](img/polars-benchmark-short.png) - -`Polars` devance des solutions connues pour leur efficacité sur ce type d'opérations, -comme le package `R` `data.table`. L'utilisateur habituel de `Pandas` -ne pourrait même pas traiter ces données, qui excèdent les capacités computationnelles -de sa machine. - -### L'évaluation _lazy_ - -Plusieurs éléments expliquent cette rapidité. - -En premier lieu, `Polars` est conçu pour optimiser les requêtes : -grâce au mode _lazy_ (_"paresseux"_), -on laisse la possibilité au moteur d'analyser ce qu'on souhaite faire -pour proposer une exécution optimale (pour la lecture comme pour la transformation des jeux de données). -La _lazy evaluation_ est une méthode assez commune pour améliorer la vitesse -des traitements et est utilisée, entre autres, par `Spark`. +- Polars permet de traiter des données _out of memory_ : `Polars` présente aussi l'avantage +de lire naturellement des jeux de données hors des limites de la mémoire de l'ordinateur grâce à [sa capacité de lire en flux](https://www.youtube.com/watch?v=3-C0Afs5TXQ) (méthode qu'on appelle le _streaming_). -Du fait de -la _lazy evaluation_ il est ainsi possible, par exemple, -si un filtre sur les lignes arrive -tardivement, de le remonter dans l'ordre des opérations effectuées par `Python` -afin que -les opérations ultérieures ne soient effectuées que sur -l'ensemble optimal de données. +- Polars permet une évaluation paresseuse (*lazy evaluation*) : ce mode de calcul +permet d'optimiser vos traitements pour proposer une exécution plus rapide +(pour la lecture comme pour la transformation des jeux de données). +Elle peut permettre d'avancer un `select` ou un `filter` si les opérations ultérieures +ne sont pas impactées. Ces optimisations sont détaillées dans la [documentation officielle](https://pola-rs.github.io/polars-book/user-guide/optimizations/intro.html). +- Une API fluide -### Lecture optimisée des fichiers - -L'utilisateur `Pandas` est habitué à lire du CSV avec `pd.read_csv`. -Avec `Polars`, il existe deux manières, très ressemblantes -de le faire. - -```python -import polars as pl - -# Création d'une requête -q = ( - pl.scan_csv("iris.csv") # Lecture lazy - .filter(pl.col("sepal_length") > 5) - .groupby("species") - .agg(pl.all().sum()) -) - -# Exécution de la requête -df = q.collect() -``` - -Avec cette syntaxe, les connaisseurs de `Pyspark` retrouveront facilement leurs petits (ours 🐻). - -On peut toujours lire de manière plus directe -(en mode _eager_, _"impatient"_) en utilisant la fonction `read_csv`, -et ensuite appliquer des transformations optimisables en glissant habilement `lazy` : - -```python -df = pl.read_csv("iris.csv") - -df_res = df.lazy() # ← ici :) - .filter(pl.col("sepal_length") > 5) - .groupby("species") - .agg(pl.all().sum()) - .collect() -``` - -`Polars` fonctionne également très bien avec le format `Parquet`, comme illustré dans -le _notebook_ qui accompagne ce _post_. - +C'est un reproche régulièrement fait à `pandas` : +la syntaxe de manipulations des données est parfois complexe ou peu lisible, et les choix d'écriture ne sont pas transparents du point de vue des performances. -### Parallélisation +L'API proposée par Polars est à la fois expressive et transparente. +Voici un exemple d'exploitation de la BPE, issu du _notebook_ accompagnant +ce _post_ : -`Polars` parallélise les traitements dès que cela est possible, notamment dans le cas d'agrégation. -Chaque coeur se charge d'une partie de l'agrégation et envoie des données plus légères à `Python` -qui va finaliser l'agrégation. +### Un pipe natif +On retrouve une sémantique d'opérations de haut niveau qui s'enchaînent à la manière de [ce que l'on peut faire en `dplyr`](https://www.book.utilitr.org/03_fiches_thematiques/fiche_tidyverse#comment-utiliser-lop%C3%A9rateur-pipe-avec-le-tidyverse). -![Parallélisation](img/polars-split-parallel-apply-combine.svg) -_Illustration du principe de la parallélisation_ +### Quelques fonctionnalités encore instables +Les catégories de Polars ne sont pas encore très bien. +On a tendance à traiter ces variable catégorielles comme des caractères. -Sur les systèmes proposant de nombreux coeurs, cela peut faire gagner beaucoup de temps. +### Pas (encore) de `geopolars` +A l'inverse, Polars est encore relativement récent. +Tout l'écosystème autour de `pandas` n'a ainsi pas forcément (encore) d'équivalent en polars. +Pour les données géolocalisées par exemple, geopolars n'existe pas encore. -### Des couches basses à la pointe +### `Polars` reste moins répandu que `pandas` +Polars étant plus récent, il est en général moins bien interfacé avec les autres +librairies de data science, même si certaines commencent à accepter des données +`polars` en entrée. +La rapidité et simplicité de Polars permet cependant facilement de repasser à un +dataframe pandas pour les librairies qui n'accepteraient pas encore de dataframe +polars en entrée. -Enfin, le choix d'utiliser à la fois le format de représentation en mémoire [Arrow](https://arrow.apache.org/) et le langage [Rust](https://www.rust-lang.org/fr) pour le coeur de la bibliothèque n'est pas étranger à cette performance. -### Calculs _out of memory_ +## Caractéristiques de polars pour commencer +Polars présente plusieurs caractéristiques à garder en tête. -`Polars` travaille vite mais présente aussi l'avantage -de lire naturellement des jeux de données hors des limites de la mémoire de l'ordinateur grâce à [sa capacité de lire en flux](https://www.youtube.com/watch?v=3-C0Afs5TXQ) (méthode qu'on appelle le _streaming_). +### Petits conseils pour commencer +- Import plus délicat +Polars est très strict sur les types des colonnes quand on importe des données. +Il est courant de passer du temps à débugger cette étape. +Pour optimiser ce temps là, +- Colonnes sont associées à des string +En Polars, les caractères simples `""` -```python -# La même requête que tout à l'heure va lire le fichier "en flux" -df = q.collect(streaming=True) -``` +- l'index de pandas est mort <3 -De plus, `Polars` lit nativement les fichiers `Parquet` qui par ses propriétés -permet d'aller beaucoup plus vite que le CSV ! +- les `polars selectors` sont très pratiques pour sélectionner des colonnes. +Ils permettent de sélectionner des colonnes avec des regex sur leurs noms ou bien +en fonction de leur type de données. +Plus d'exemples sont disponibles dans la [documentation officielle](https://docs.pola.rs/api/python/stable/reference/selectors.html). -### Une API fluide -C'est un reproche régulièrement fait à `Pandas` : -la syntaxe de manipulations des données est parfois complexe ou peu lisible, et les choix d'écriture ne sont pas transparents du point de vue des performances. +## Allons-y ! -L'API proposée par Polars est à la fois expressive et transparente. -Voici un exemple d'exploitation de la BPE, issu du _notebook_ accompagnant -ce _post_ : +On commence par importer la librairie `Polars`. +L'usage est courant est de lui attribuer l'alias `pl` afin de simplifier les +futurs appels aux objets et fonctions du package. -```python -df.lazy() - .filter( - pl.col("TYPEQU") == "B316" - ) - .groupby("DEP") - .agg( - pl.count().alias("NB_STATION_SERVICE") - ) - .collect() +```{python} +import polars as pl +import polars.selectors as cs ``` -### Un pipe natif -On retrouve une sémantique d'opérations de haut niveau qui s'enchaînent à la manière de [ce que l'on peut faire en `dplyr`](https://www.book.utilitr.org/03_fiches_thematiques/fiche_tidyverse#comment-utiliser-lop%C3%A9rateur-pipe-avec-le-tidyverse). - - - -## Intro - TO DO - -On commence par importer la librairie `Polars`. L'usage est courant est de lui attribuer l'alias `pl` afin de simplifier les futurs appels aux objets et fonctions du package. - -Polars plus proche de l'univers du tidyverse pour des personnes venant de R. -beaucoup plus rapide que pandas -plus jeune (et donc pas (encore?) intégré partout ? panda) -moins répandu que Pandas -très strict sur les types des colonnes - - -Parler de : - -- colonnes sont associées à des string. -- pas d'index. -- polars selectors -- lazy eval - "TO DO" - Polars Séries -pour aller plus loin : - -- interconnection avec duckDB pour des requêtes en SQL +## pour aller plus loin -Ressources : +Voici un ensemble de ressources si vous voulez aller plus loin sur l'écosystème +de Polars : - [Blog Awesome Polars](https://ddotta.github.io/awesome-polars/), par Damien D +- [Blog sur Polars sur le site du SSPHub](https://ssphub.netlify.app/post/polars/) - [Notebook Polars](https://datalab.sspcloud.fr/launcher/ide/jupyter-python?name=Tutoriel%20Polars&version=2.3.28&s3=region-79669f20&init.personalInit=«https%3A%2F%2Fraw.githubusercontent.com%2Fntoulemonde%2Ftest%2Frefs%2Fheads%2Fmain%2Finit.sh»&autoLaunch=true) @@ -214,7 +143,7 @@ from tidypolars import col Fondamentalement, un DataFrame consiste en une collection de Series. Cette concaténation construit donc une table de données, dont les Series correspondent aux colonnes. La figure suivante ([source](https://www.geeksforgeeks.org/creating-a-pandas-dataframe/)) permet de bien comprendre cette structure de données. -![](img/structure_df.png){fig-align="center" width="800"} +![](../pandas/img/structure_df.png){fig-align="center" width="800"} Un DataFrame peut être construit de multiples manières. En pratique, on construit généralement un DataFrame directement à partir de fichiers de données tabulaires (ex : CSV, excel), rarement à la main. On illustrera donc seulement la méthode de construction manuelle la plus usuelle : à partir d'un dictionnaire de données. From 91e39a035122c0999c504f827bb6811d85934b7c Mon Sep 17 00:00:00 2001 From: Nicole <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 24 Feb 2026 18:58:42 +0100 Subject: [PATCH 35/92] intro --- source/manipulation/polars/tutorial.qmd | 58 +++++++++++-------------- 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 276143cd..05565b3e 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -12,44 +12,36 @@ Plusieurs packages viennent ainsi combler ce manque, comme `pandas` ou `polars`. Comment choisir entre les deux ? Cela va dépendre de vos goûts et de vos besoins. Mais voici en attendant quelques éléments pour savoir si `polars` est utile. -- Polars est rapide et permet de traiter des données volumineuses : Selon un benchmark [effectué par H2O](https://h2oai.github.io/db-benchmark/), +Du côté des atouts de Polars : + +- Polars est **rapide** et permet de traiter des **données volumineuses** : Selon un benchmark [effectué par H2O](https://h2oai.github.io/db-benchmark/), Polars permet de traiter des données que d'autres librairies ne pourraient pas () et les traite aussi rapidement que le package `R` `data.table`. et 3 à 4 fois plus vite que d'autres librairies. -- Polars permet de traiter des données _out of memory_ : `Polars` présente aussi l'avantage +- Polars permet même de traiter des **données _out of memory_ :** `Polars` présente aussi l'avantage de lire naturellement des jeux de données hors des limites de la mémoire de l'ordinateur grâce à [sa capacité de lire en flux](https://www.youtube.com/watch?v=3-C0Afs5TXQ) (méthode qu'on appelle le _streaming_). -- Polars permet une évaluation paresseuse (*lazy evaluation*) : ce mode de calcul +- Polars permet une **évaluation paresseuse** (*lazy evaluation*) : ce mode de calcul permet d'optimiser vos traitements pour proposer une exécution plus rapide (pour la lecture comme pour la transformation des jeux de données). Elle peut permettre d'avancer un `select` ou un `filter` si les opérations ultérieures ne sont pas impactées. Ces optimisations sont détaillées dans la [documentation officielle](https://pola-rs.github.io/polars-book/user-guide/optimizations/intro.html). -- Une API fluide - -C'est un reproche régulièrement fait à `pandas` : -la syntaxe de manipulations des données est parfois complexe ou peu lisible, et les choix d'écriture ne sont pas transparents du point de vue des performances. - -L'API proposée par Polars est à la fois expressive et transparente. -Voici un exemple d'exploitation de la BPE, issu du _notebook_ accompagnant -ce _post_ : +- Une **API fluide** : L'API proposée par Polars est à la fois expressive et transparente. Ceci répond notamment aux commentaires sur `pandas`, où la syntaxe de manipulations des données est parfois complexe ou peu lisible et les choix d'écriture ne sont pas transparents du point de vue des performances. -### Un pipe natif -On retrouve une sémantique d'opérations de haut niveau qui s'enchaînent à la manière de [ce que l'on peut faire en `dplyr`](https://www.book.utilitr.org/03_fiches_thematiques/fiche_tidyverse#comment-utiliser-lop%C3%A9rateur-pipe-avec-le-tidyverse). +- Un **pipe natif** : On retrouve une sémantique d'opérations de haut niveau qui s'enchaînent à la manière de [ce que l'on peut faire en `dplyr`](https://www.book.utilitr.org/03_fiches_thematiques/fiche_tidyverse#comment-utiliser-lop%C3%A9rateur-pipe-avec-le-tidyverse). +Polars présente quand même aussi quelques **inconvénients**, notamment lié à sa plus grande jeunesse. -### Quelques fonctionnalités encore instables -Les catégories de Polars ne sont pas encore très bien. -On a tendance à traiter ces variable catégorielles comme des caractères. +- ainsi, le **traitement de données catégorielles** est encore instable, notamment en comparaison à pandas et +au tidyverse. +Dans Polars pour contourner ces problèmes, on a tendance à traiter ces variable catégorielles comme des caractères. -### Pas (encore) de `geopolars` -A l'inverse, Polars est encore relativement récent. -Tout l'écosystème autour de `pandas` n'a ainsi pas forcément (encore) d'équivalent en polars. -Pour les données géolocalisées par exemple, geopolars n'existe pas encore. +- **Pas (encore) de `geopolars`** : Tout l'écosystème autour de `pandas` n'a ainsi pas forcément (encore) d'équivalent en polars. +Pour les données géolocalisées par exemple, geopolars n'existe pas encore. -### `Polars` reste moins répandu que `pandas` -Polars étant plus récent, il est en général moins bien interfacé avec les autres +- plus généralement, **`Polars` reste moins répandu que `pandas`** : Polars étant plus récent, il est en général moins bien interfacé avec les autres librairies de data science, même si certaines commencent à accepter des données `polars` en entrée. La rapidité et simplicité de Polars permet cependant facilement de repasser à un @@ -57,19 +49,22 @@ dataframe pandas pour les librairies qui n'accepteraient pas encore de dataframe polars en entrée. -## Caractéristiques de polars pour commencer -Polars présente plusieurs caractéristiques à garder en tête. +## Petits conseils pour commencer +Avant de commencer à utiliser Polars, voici quelques conseils à garder en tête : -### Petits conseils pour commencer -- Import plus délicat +- L'import de données est **plus délicat** : Polars est très strict sur les types des colonnes quand on importe des données. -Il est courant de passer du temps à débugger cette étape. -Pour optimiser ce temps là, +Il est courant de passer du temps à débugger cette étape, notamment pour s'assurer +que le code soit résistant à de légères variations dans le format des données d'entrée. +Pour optimiser ce temps là, on peut spécifier directement les types en entrée. -- Colonnes sont associées à des string -En Polars, les caractères simples `""` +- Les **chaines de caractères sont par défaut associées à des colonnes** : +En Polars, les caractères simples `"myvar"` sont par défaut considéré comme des noms de +colonne. Il faut penser à utiliser `pl.lit("myvar")` pour signaler qu'il ne s'agit +pas d'un nom de colonne. -- l'index de pandas est mort <3 +- **l'index de pandas** est mort <3 : comme dans le tidyverse, polars +n'utilise pas d'index, et c'est très bien comme cela ! - les `polars selectors` sont très pratiques pour sélectionner des colonnes. Ils permettent de sélectionner des colonnes avec des regex sur leurs noms ou bien @@ -88,7 +83,6 @@ import polars as pl import polars.selectors as cs ``` -"TO DO" - Polars Séries ## pour aller plus loin From bbc72fc636ed20eff6b7c551c48946d87ec36e89 Mon Sep 17 00:00:00 2001 From: Nicole <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 24 Feb 2026 19:41:14 +0100 Subject: [PATCH 36/92] review --- source/manipulation/polars/tutorial.qmd | 26 +++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 05565b3e..8f0d1322 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -306,6 +306,14 @@ df.filter(pl.col("var1") >= 0, pl.col("experiment").is_in(['train', 'validation' df.filter((pl.col("var1") >= 0) | pl.col("experiment").is_in(['train', 'validation'])) ``` +:::::: {.callout-note} +La méthode `filter` marche aussi sur des calculs à base des colonnes. Par exemple, si l'on veut sélectionner les observations faites le 2 du mois, on peut effectuer cela en une ligne (on verra plus tard le travail sur les données temporelles): + +```{python} +df.filter(pl.col('date').str.to_date("%Y-%m-%d").dt.day()==2) +``` +::: + # Explorer des données tabulaires En statistique publique, le point de départ n'est généralement pas la génération manuelle de données, mais plutôt des fichiers tabulaires préexistants. @@ -417,7 +425,7 @@ En regardant le message d'erreur, Polars traite la colonne `anais` comme un enti Mais la lecture de la valeur `XXXX` cause une erreur et n'est pas convertible en entier par Polars. ```{python} -import os +#| eval: false df_prenoms_url = pl.read_csv('temp/' + os.listdir('temp')[0], separator=";") ``` @@ -1091,7 +1099,8 @@ C'est l'occasion d'introduire la famille de méthode `strip` (`.str.strip_chars( ( df .with_columns( - sample = pl.col('sample').str.strip_chars() + sample=pl.col('sample').str.strip_chars() # remarque : on peut omettre ici le 'sample=' + # et avoir le meme résultat ) .with_columns( sample_n = pl.col('sample').str.tail(1) @@ -1198,13 +1207,13 @@ df.dtypes Une fois converties, les dates peuvent être formatées, comparées et utilisées dans des calculs. Il faudra cependant bien penser à traduire les dates d'un format textuel à un format temporel. -Par exemple, pour filter des données, on devra spécifier les bornes en appelant les fonctions dédiées de Polars ou du module `datetime`. +Par exemple, pour filtrer des données, on devra spécifier les bornes en appelant les fonctions dédiées de Polars ou du module `datetime`. ```{python} df.filter(pl.col('date') >= pl.date(2022, 1, 1), pl.col('date') < pl.date(2022, 1, 3)) -``` -```{python} +# équivalent à + from datetime import datetime df.filter(pl.col('date') >= datetime.strptime("2022-01-01", "%Y-%m-%d"), pl.col('date') < datetime.strptime("2022-01-03", "%Y-%m-%d")) ``` @@ -1235,7 +1244,6 @@ On peut par exemple ajouter des intervalles de temps, ou bien calculer des écar ::: {.callout-note} Par défaut, les différences de temps sont indiquées dans une unité temporelle. Si l'on veut transformer une durée en un nombre, il faut utiliser les méthodes `Series.dt.total_...`. - ::: ```{python} @@ -1282,7 +1290,8 @@ pl.concat([df1, df2]) A la grande différence de `Pandas`, **l'ordre des variables dans les deux DataFrames importe**. Ainsi, le même code avec `df2` défini comme ci-après va renvoyer une erreur. -```{.python} +```{python} +#| eval: false df2 = pl.DataFrame( data = { @@ -1293,9 +1302,10 @@ df2 = pl.DataFrame( } ) +pl.concat([df1, df2]) ``` -Pour contourner ce problème, il suffit de préférer une méthode de type `join` avec `df1.join(df2, on=df1.columns, how="full", coalesce=True)` (*cf.* ci-après). +Pour contourner ce problème, il suffit de préférer une méthode de type `join` avec `df1.join(df2, on=df1.columns, how="full", coalesce=True)` (*cf.* ci-après) ou de réordonner les colonnes avec `pl.concat([df1, df2.select(df1.columns)])`. ## Fusionner des tables From 4ebefae5d1153c594961b5611ed7e347799f949a Mon Sep 17 00:00:00 2001 From: Nicole <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 24 Feb 2026 20:02:28 +0100 Subject: [PATCH 37/92] with answer exo1 --- source/manipulation/polars/tutorial.qmd | 36 ++++++++++++++----------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 8f0d1322..865c1176 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -1461,7 +1461,7 @@ data_list2 = [ ] ``` -L'objectif est de construire dans les deux cas un même DataFrame qui contient chacune des 6 observations et des 4 variables, avec les mêmes noms dans les deux DataFrame. A chaque cas va correspondre une structure de données plus adaptée en entrée, dictionnaire ou liste de listes... faîtes le bon choix ! On vérifiera que les deux DataFrames sont identiques à l'aide de la méthode [equals()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.equals.html). +L'objectif est de construire dans les deux cas un même DataFrame qui contient chacune des 6 observations et des 4 variables, avec les mêmes noms dans les deux DataFrame. A chaque cas va correspondre une structure de données plus adaptée en entrée, dictionnaire ou liste de listes... faîtes le bon choix ! On vérifiera que les deux DataFrames sont identiques à l'aide de la méthode [equals()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.equals.html#polars.DataFrame.equals). ```{python} # Testez votre réponse dans cette cellule @@ -1498,11 +1498,11 @@ data_dict = { 'prix': data_list1[3] } -df_from_dict = pd.DataFrame(data_dict) +df_from_dict = pl.DataFrame(data_dict) # Si les données sont sous forme de lignes : à partir d'une liste de listes columns = ['enseigne', 'produit', 'quantite', 'prix'] -df_from_list = pd.DataFrame(data_list2, columns=columns) +df_from_list = pl.DataFrame(data_list2, schema=columns, orient='row') # Vérification df_from_dict.equals(df_from_list) @@ -1514,7 +1514,7 @@ df_from_dict.equals(df_from_list) ## Sélection de données dans un DataFrame -Un DataFrame Pandas est créé avec des données de caisse (mêmes données que l'exercice précédent). +Un DataFrame Polars est créé avec des données de caisse (mêmes données que l'exercice précédent). ```{python} data = { @@ -1522,15 +1522,15 @@ data = { 'produit': ['01.1.1', '02.1.1', '01.1.1', '03.1.1', '01.1.1', '02.1.1'], 'quantite': [3, 2, 7, 5, 10, 1], 'prix': [1.50, 2.30, 0.99, 5.00, 1.20, 3.10], - 'date_heure': pd.to_datetime(["2022-01-01 14:05", "2022-01-02 09:30", + 'date_heure': pl.Series(["2022-01-01 14:05", "2022-01-02 09:30", "2022-01-03 17:45", "2022-01-04 08:20", - "2022-01-05 19:00", "2022-01-06 16:30"]) + "2022-01-05 19:00", "2022-01-06 16:30"]).str.to_datetime() } -df = pd.DataFrame(data) +df = pl.DataFrame(data) ``` -Utilisez les méthodes `loc` et `iloc` pour sélectionner des données spécifiques : +Utilisez les méthodes appropriées parmi `filter`, `select`, `head` pour sélectionner des données spécifiques : - Sélectionner les données de la première ligne. @@ -1545,7 +1545,7 @@ Utilisez les méthodes `loc` et `iloc` pour sélectionner des données spécifiq Afficher la solution ```{python} -print(df.iloc[0]) +print(df.head(1)) ``` @@ -1565,7 +1565,7 @@ print(df.iloc[0]) Afficher la solution ```{python} -print(df.loc[:, 'prix']) +print(df.select("prix")) ``` @@ -1585,7 +1585,7 @@ print(df.loc[:, 'prix']) Afficher la solution ```{python} -print(df.loc[df['enseigne'] == 'Carrefour']) +print(df.filter(pl.col("enseigne") == 'Carrefour')) ``` @@ -1605,7 +1605,11 @@ print(df.loc[df['enseigne'] == 'Carrefour']) Afficher la solution ```{python} -print(df.loc[df['produit'] == '01.1.1', 'quantite']) +print( + df + .filter(pl.col("produit") == '01.1.1') + .select('quantite') +) ``` @@ -1625,7 +1629,7 @@ print(df.loc[df['produit'] == '01.1.1', 'quantite']) Afficher la solution ```{python} -print(df.loc[:, ['enseigne', 'prix']]) +print(df.select(('enseigne', 'prix')) ``` @@ -1645,7 +1649,7 @@ print(df.loc[:, ['enseigne', 'prix']]) Afficher la solution ```{python} -print(df.loc[df['quantite'] > 5]) +print(df.filter(pl.col("quantite") > 5)) ``` @@ -1665,7 +1669,7 @@ print(df.loc[df['quantite'] > 5]) Afficher la solution ```{python} -print(df.loc[df['date_heure'].dt.hour > 15]) +print(df.filter(pl.col("date_heure").dt.hour() > 15)) ``` @@ -1685,7 +1689,7 @@ print(df.loc[df['date_heure'].dt.hour > 15]) Afficher la solution ```{python} -print(df.loc[df['date_heure'].dt.date == pd.to_datetime('2022-01-03').date()]) +print(df.filter(pl.col('date_heure').dt.date() == pl.Series(['2022-01-03']).str.to_date())) ``` From ee161255afc62d828c1778a8a7371808cc1755bf Mon Sep 17 00:00:00 2001 From: Nicole <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 24 Feb 2026 20:56:09 +0100 Subject: [PATCH 38/92] with exo prenoms --- source/manipulation/polars/tutorial.qmd | 48 +++++++++++++++++++------ 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 865c1176..ed69404c 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -426,6 +426,7 @@ Mais la lecture de la valeur `XXXX` cause une erreur et n'est pas convertible en ```{python} #| eval: false +import os df_prenoms_url = pl.read_csv('temp/' + os.listdir('temp')[0], separator=";") ``` @@ -433,6 +434,7 @@ Dans ce cas, deux solutions existent : - On peut dire à Polars de traiter toutes les colonnes comme des caractères avec infer_schema=False ```{python} +import os df_prenoms_url = pl.read_csv('temp/' + os.listdir('temp')[0], separator=";", infer_schema=False) df_prenoms_url ``` @@ -1718,13 +1720,14 @@ Le fichier des prénoms contient des données sur les prénoms attribués aux en Afficher la solution ```{python} +import pandas as pd url = "https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip" -df_prenoms = pd.read_csv(url, sep=";") +df_prenoms = pl.from_pandas(pd.read_csv(url, sep=";")) df_prenoms.head(10) df_prenoms.sample(n=50) -df_prenoms.info() +print(df_prenoms.describe()) ``` @@ -1734,8 +1737,8 @@ df_prenoms.info() ### Partie 2 : Nettoyage des données -- L'output de la méthode `info()` suggère des valeurs manquantes dans la colonne des prénoms. Affichez ces lignes. Vérifiez que ces valeurs manquantes sont correctement spécifiées. -- L'output de méthode `head()` montre une modalité récurrente "_PRENOMS_RARES" dans la colonne des prénoms. Quelle proportion des individus de la base cela concerne-t-il ? Convertir ces valeurs en `np.nan`. +- L'output des recherches précédentes suggère des valeurs manquantes dans la colonne des prénoms. Affichez ces lignes. Vérifiez que ces valeurs manquantes sont correctement spécifiées. +- L'output de méthode `head()` montre une modalité récurrente "_PRENOMS_RARES" dans la colonne des prénoms. Quelle proportion des individus de la base cela concerne-t-il ? Vous pouvez vous aider de la méthode `over` détaillée dans la documentation. Convertir ces valeurs en valeurs manquantes. ```{python} # Testez votre réponse dans cette cellule @@ -1748,10 +1751,28 @@ df_prenoms.info() Afficher la solution ```{python} -print(df_prenoms[df_prenoms["preusuel"].isna()]) -prop_rares = df_prenoms.groupby("preusuel")["nombre"].sum()["_PRENOMS_RARES"] / df_prenoms["nombre"].sum() -print(prop_rares) # ~ 2 % de la base -df_prenoms = df_prenoms.replace('_PRENOMS_RARES', None) +print(df_prenoms.filter(pl.col("preusuel").is_null())) +prop_rares1 = ( + df_prenoms + .with_columns( + tot_rel=pl.sum("nombre").over("preusuel") / pl.sum("nombre") + ) + .filter(pl.col("preusuel")=="_PRENOMS_RARES") + .item(0, "tot_rel") +) +print(prop_rares1) # ~ 2 % de la base +# equivalent à +prop_rares2 = ( + df_prenoms + .group_by("preusuel") + .agg(pl.col("nombre").sum()) + .with_columns(tot=pl.sum("nombre")) + .with_columns(tot_rel=pl.col("nombre")/pl.col("tot")) + .filter(pl.col("preusuel")=="_PRENOMS_RARES") + .item(0, "tot_rel") +) +print(prop_rares2) # ~ 2 % de la base +df_prenoms = df_prenoms.with_columns(pl.col("preusuel").str.replace('_PRENOMS_RARES', None)) ``` @@ -1771,9 +1792,16 @@ df_prenoms = df_prenoms.replace('_PRENOMS_RARES', None) Afficher la solution ```{python} -prop_xxxx = df_prenoms.groupby("annais")["nombre"].sum()["XXXX"] / df_prenoms["nombre"].sum() +prop_xxxx = ( + df_prenoms + .with_columns( + tot_rel=pl.col("nombre").sum().over("annais")/ pl.col("nombre").sum() + ) + .filter(pl.col("annais")=="XXXX") + .item(0, "tot_rel") +) print(prop_xxxx) # ~ 1 % de la base -df_prenoms = df_prenoms.replace('XXXX', None) +df_prenoms = df_prenoms.with_columns(pl.col("annais").str.replace("XXXX", None)) ``` From a29cbbbf972c551f7493065481cd856b64fba430 Mon Sep 17 00:00:00 2001 From: Nicole <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 24 Feb 2026 21:08:23 +0100 Subject: [PATCH 39/92] with exo prenoms - end --- source/manipulation/polars/tutorial.qmd | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index ed69404c..0dc388ba 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -1772,14 +1772,14 @@ prop_rares2 = ( .item(0, "tot_rel") ) print(prop_rares2) # ~ 2 % de la base -df_prenoms = df_prenoms.with_columns(pl.col("preusuel").str.replace('_PRENOMS_RARES', None)) +df_prenoms = df_prenoms.with_columns(preusuel=pl.when(pl.col("preusuel")=="_PRENOMS_RARES").then(None).otherwise(pl.col("preusuel"))) ``` ::: -- On remarque que les prénoms de personnes dont l'année de naissance n'est pas connue sont regroupés sous la modalité `XXXX`. Quelle proportion des individus de la base cela concerne-t-il ? Convertir ces valeurs en `np.nan`. +- On remarque que les prénoms de personnes dont l'année de naissance n'est pas connue sont regroupés sous la modalité `XXXX`. Quelle proportion des individus de la base cela concerne-t-il ? Convertir ces valeurs en valeurs manquantes. Vous pouvez utiliser la syntaxe de [`pl.when`](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.when.html) ```{python} # Testez votre réponse dans cette cellule @@ -1801,7 +1801,7 @@ prop_xxxx = ( .item(0, "tot_rel") ) print(prop_xxxx) # ~ 1 % de la base -df_prenoms = df_prenoms.with_columns(pl.col("annais").str.replace("XXXX", None)) +df_prenoms = df_prenoms.with_columns(annais=pl.when(pl.col("annais")=="XXXX").then(None).otherwise(pl.col("annais"))) ``` @@ -1821,7 +1821,7 @@ df_prenoms = df_prenoms.with_columns(pl.col("annais").str.replace("XXXX", None)) Afficher la solution ```{python} -df_prenoms = df_prenoms.dropna() +df_prenoms = df_prenoms.drop_nulls() ``` @@ -1841,15 +1841,14 @@ df_prenoms = df_prenoms.dropna() Afficher la solution ```{python} -df_prenoms['annais'] = pd.to_numeric(df_prenoms['annais']) -df_prenoms['sexe'] = df_prenoms['sexe'].astype('category') +df_prenoms = df_prenoms.cast({'annais':pl.Int32, 'sexe':pl.Categorical}) ``` ::: -- Vérifiez avec la méthode `info()` que le nettoyage a été correctement appliqué. +- Vérifiez avec la méthode `describe()` que le nettoyage a été correctement appliqué. ```{python} # Testez votre réponse dans cette cellule @@ -1862,7 +1861,7 @@ df_prenoms['sexe'] = df_prenoms['sexe'].astype('category') Afficher la solution ```{python} -df_prenoms.info() +df_prenoms.describe() ``` From b52ef3054cb836a7edb4d0d49987ff15fd0db6b7 Mon Sep 17 00:00:00 2001 From: Nicole <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 24 Feb 2026 21:08:23 +0100 Subject: [PATCH 40/92] with exo prenom -end --- source/manipulation/polars/tutorial.qmd | 50 ++++++++++++------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index ed69404c..77b21e68 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -1772,14 +1772,14 @@ prop_rares2 = ( .item(0, "tot_rel") ) print(prop_rares2) # ~ 2 % de la base -df_prenoms = df_prenoms.with_columns(pl.col("preusuel").str.replace('_PRENOMS_RARES', None)) +df_prenoms = df_prenoms.with_columns(preusuel=pl.when(pl.col("preusuel")=="_PRENOMS_RARES").then(None).otherwise(pl.col("preusuel"))) ``` ::: -- On remarque que les prénoms de personnes dont l'année de naissance n'est pas connue sont regroupés sous la modalité `XXXX`. Quelle proportion des individus de la base cela concerne-t-il ? Convertir ces valeurs en `np.nan`. +- On remarque que les prénoms de personnes dont l'année de naissance n'est pas connue sont regroupés sous la modalité `XXXX`. Quelle proportion des individus de la base cela concerne-t-il ? Convertir ces valeurs en valeurs manquantes. Vous pouvez utiliser la syntaxe de [`pl.when`](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.when.html) ```{python} # Testez votre réponse dans cette cellule @@ -1801,7 +1801,7 @@ prop_xxxx = ( .item(0, "tot_rel") ) print(prop_xxxx) # ~ 1 % de la base -df_prenoms = df_prenoms.with_columns(pl.col("annais").str.replace("XXXX", None)) +df_prenoms = df_prenoms.with_columns(annais=pl.when(pl.col("annais")=="XXXX").then(None).otherwise(pl.col("annais"))) ``` @@ -1821,7 +1821,7 @@ df_prenoms = df_prenoms.with_columns(pl.col("annais").str.replace("XXXX", None)) Afficher la solution ```{python} -df_prenoms = df_prenoms.dropna() +df_prenoms = df_prenoms.drop_nulls() ``` @@ -1841,15 +1841,14 @@ df_prenoms = df_prenoms.dropna() Afficher la solution ```{python} -df_prenoms['annais'] = pd.to_numeric(df_prenoms['annais']) -df_prenoms['sexe'] = df_prenoms['sexe'].astype('category') +df_prenoms = df_prenoms.cast({'annais':pl.Int32, 'sexe':pl.Categorical}) ``` ::: -- Vérifiez avec la méthode `info()` que le nettoyage a été correctement appliqué. +- Vérifiez avec la méthode `describe()` que le nettoyage a été correctement appliqué. ```{python} # Testez votre réponse dans cette cellule @@ -1862,7 +1861,7 @@ df_prenoms['sexe'] = df_prenoms['sexe'].astype('category') Afficher la solution ```{python} -df_prenoms.info() +df_prenoms.describe() ``` @@ -1885,7 +1884,7 @@ df_prenoms.info() Afficher la solution ```{python} -df_prenoms_post_1946 = df_prenoms[df_prenoms["annais"] >= 1946] +df_prenoms_post_1946 = df_prenoms.filter(pl.col("annais") >= 1946) ``` @@ -1905,7 +1904,7 @@ df_prenoms_post_1946 = df_prenoms[df_prenoms["annais"] >= 1946] Afficher la solution ```{python} -births_per_sex = df_prenoms_post_1946.groupby('sexe')['nombre'].sum() +births_per_sex = df_prenoms_post_1946.group_by('sexe').agg(pl.sum('nombre')) print(births_per_sex) ``` @@ -1926,7 +1925,7 @@ print(births_per_sex) Afficher la solution ```{python} -top5_years = df_prenoms_post_1946.groupby('annais')['nombre'].sum().nlargest(5) +top5_years = df_prenoms_post_1946.group_by(pl.col("annais")).agg(pl.sum("nombre")).sort("nombre").tail(5) print(top5_years) ``` @@ -1950,7 +1949,7 @@ print(top5_years) Afficher la solution ```{python} -total_unique_names = df_prenoms['preusuel'].nunique() +total_unique_names = df_prenoms.n_unique("preusuel") print(total_unique_names) ``` @@ -1971,7 +1970,7 @@ print(total_unique_names) Afficher la solution ```{python} -single_letter_names = df_prenoms[df_prenoms['preusuel'].str.len() == 1]['nombre'].sum() +single_letter_names = df_prenoms.filter(pl.col("preusuel").str.len_chars() == 1).select("nombre").sum() print(single_letter_names) ``` @@ -1994,12 +1993,12 @@ print(single_letter_names) ```{python} def popularite_par_annee(df, prenom): # Filtrer le DataFrame pour ne garder que les lignes correspondant au prénom donné - df_prenom = df[df['preusuel'] == prenom] + df_prenom = df.filter(pl.col("preusuel") == "ALFRED") # Grouper par année, sommer les naissances et identifier l'année avec le maximum de naissances - df_agg = df_prenom.groupby('annais')['nombre'].sum() - annee_max = df_agg.idxmax() - n_max = df_agg[annee_max] + df_agg = df_prenom.group_by("annais").agg(pl.sum('nombre')).sort("nombre", descending=True) + annee_max = df_agg.item(0, "annais") + n_max = df_agg.item(0, "nombre") print(f"Le prénom '{prenom}' a été le plus donné en {annee_max}, avec {n_max} naissances.") @@ -2026,24 +2025,23 @@ popularite_par_annee(df_prenoms, 'ALFRED') ```{python} def popularite_par_decennie(df, sexe): # Filtrage sur le sexe - df_sub = df[df["sexe"] == sexe] + df_sub = df.filter(pl.col("sexe") == sexe) # Calcul de la variable décennie - df_sub["decennie"] = (df_sub["annais"] // 10) * 10 + df_sub = df_sub.with_columns( + decennie = (pl.col("annais") // 10) * 10 + ) # Calculer la somme des naissances pour chaque prénom et chaque décennie - df_counts_decennie = df_sub.groupby(["preusuel", "decennie"])["nombre"].sum().reset_index() - - # Trouver l'indice du prénom le plus fréquent pour chaque décennie - idx = df_counts_decennie.groupby("decennie")["nombre"].idxmax() + df_counts_decennie = df_sub.group_by(["preusuel", "decennie"]).agg(pl.sum("nombre")) - # Utiliser l'indice pour obtenir les lignes correspondantes du DataFrame df_counts_decennie - df_popularite_decennie = df_counts_decennie.loc[idx].set_index("decennie") + # Filtrer le prénom le plus fréquent pour chaque décennie par over + df_popularite_decennie = df_counts_decennie.filter(pl.col("nombre")==pl.max("nombre").over("decennie")) return df_popularite_decennie # Test de la fonction avec un exemple -popularite_par_decennie(df_prenoms, sexe=2) +popularite_par_decennie(df_prenoms, sexe="2") ``` From 5889334f7c809bada53f981d9c5d5599370b66a6 Mon Sep 17 00:00:00 2001 From: Nicole <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 24 Feb 2026 22:44:01 +0100 Subject: [PATCH 41/92] with exo empreinte carbone - 1 --- source/manipulation/polars/tutorial.qmd | 46 +++++++++++++++---------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 77b21e68..e8885378 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -2074,10 +2074,9 @@ Cet exercice constitue une version simplifiée d'un [TP complet pour la pratique Afficher la solution ```{python} -df_pop_communes = pd.read_csv("data/communes.csv", sep=";") +df_pop_communes = pl.read_csv("data/communes.csv", separator=";", infer_schema_length=None) df_pop_communes.sample(10) -df_pop_communes.info() df_pop_communes.describe() ``` @@ -2099,11 +2098,11 @@ df_pop_communes.describe() Afficher la solution ```{python} -n_communes_0_pop = df_pop_communes[df_pop_communes["PTOT"] == 0].shape[0] +n_communes_0_pop = df_pop_communes.filter(pl.col("PTOT") == 0).height print(n_communes_0_pop) -df_pop_communes = df_pop_communes[df_pop_communes["PTOT"] > 0] +df_pop_communes = df_pop_communes.filter(pl.col("PTOT") > 0) -df_pop_communes = df_pop_communes.drop(columns=["PMUN", "PCAP"]) +df_pop_communes = df_pop_communes.drop(["PMUN", "PCAP"]) ``` @@ -2111,8 +2110,8 @@ df_pop_communes = df_pop_communes.drop(columns=["PMUN", "PCAP"]) ::: Les communes qui ont les noms les plus longs sont-elles aussi les communes les moins peuplées ? Pour le savoir : -- Créez une nouvelle variable qui contient le nombre de caractères de chaque commune à l'aide de la méthode [str.len()](https://pandas.pydata.org/docs/reference/api/pandas.Series.str.len.html) -- Calculez la corrélation entre cette variable et la population totale avec la méthode [corr()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.corr.html) +- Créez une nouvelle variable qui contient le nombre de caractères de chaque commune à l'aide de la méthode [str.len_chars()](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.Expr.str.len_chars.html#polars.Expr.str.len_chars) +- Calculez la corrélation entre cette variable et la population totale avec la méthode [corr()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.corr.html#polars.DataFrame.corr) ```{python} # Testez votre réponse dans cette cellule @@ -2125,9 +2124,13 @@ Les communes qui ont les noms les plus longs sont-elles aussi les communes les m Afficher la solution ```{python} -df_pop_communes_stats = df_pop_communes.copy() -df_pop_communes_stats['longueur'] = df_pop_communes_stats['COM'].str.len() -df_pop_communes_stats['longueur'].corr(df_pop_communes_stats['PTOT']) +df_pop_communes_stats = df_pop_communes +df_pop_communes_stats = (df_pop_communes_stats.with_columns( + longueur=pl.col('COM').str.len_chars() + ) + .select(["longueur", "PTOT"]) +) +df_pop_communes_stats.corr() ``` @@ -2151,10 +2154,9 @@ df_pop_communes_stats['longueur'].corr(df_pop_communes_stats['PTOT']) ```{python} url_ademe = "https://data.ademe.fr/data-fair/api/v1/datasets/igt-pouvoir-de-rechauffement-global/data-files/IGT%20-%20Pouvoir%20de%20r%C3%A9chauffement%20global.csv" -df_emissions = pd.read_csv(url_ademe) +df_emissions = pl.from_pandas(pd.read_csv(url_ademe)) df_emissions.sample(10) -df_emissions.info() df_emissions.describe() ``` @@ -2162,7 +2164,7 @@ df_emissions.describe() ::: -- Y a-t-il des lignes avec des valeurs manquantes pour toutes les colonnes d'émission ? Vérifiez-le à l'aide des méthodes [isnull()](https://pandas.pydata.org/docs/reference/api/pandas.isnull.html) et [all()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.all.html). +- Y a-t-il des lignes avec des valeurs manquantes pour toutes les colonnes d'émission ? Vérifiez-le à l'aide des méthodes [is_null()](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.Expr.is_null.html#polars.Expr.is_null) et [all_horizontal()](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.all_horizontal.html#polars.all_horizontal). ```{python} # Testez votre réponse dans cette cellule @@ -2175,9 +2177,10 @@ df_emissions.describe() Afficher la solution ```{python} -df_emissions_num = df_emissions.select_dtypes(['number']) -only_nan = df_emissions_num[df_emissions_num.isnull().all(axis=1)] -only_nan.shape[0] +import polars.selectors as cs +df_emissions_num = df_emissions.select(cs.numeric()) +only_nan = df_emissions_num.filter(pl.all_horizontal(pl.all().is_null())) +only_nan.height ``` @@ -2198,9 +2201,14 @@ only_nan.shape[0] Afficher la solution ```{python} -df_emissions['emissions_totales'] = df_emissions.sum(axis = 1, numeric_only = True) - -df_emissions.sort_values(by="emissions_totales", ascending=False).head(10) +( + df_emissions + .unpivot(on=cs.numeric(), index="INSEE commune") + .with_columns(emissions_totales=pl.sum("value").over("INSEE commune")) + .pivot(on_columns="variable", index=["INSEE commune", "emissions_totales"]) + .sort(["emissions_totales", "value"], descending=[True, True]) + .head(120) +) ``` From 7333c22056b28d97862aa4550920251a3c55f096 Mon Sep 17 00:00:00 2001 From: Nicole <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 24 Feb 2026 22:50:16 +0100 Subject: [PATCH 42/92] with exo empreinte carbone - pivot partial --- source/manipulation/polars/tutorial.qmd | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index e8885378..8d729f4e 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -2201,13 +2201,16 @@ only_nan.height Afficher la solution ```{python} -( +df_emissions_top10 = ( df_emissions .unpivot(on=cs.numeric(), index="INSEE commune") .with_columns(emissions_totales=pl.sum("value").over("INSEE commune")) - .pivot(on_columns="variable", index=["INSEE commune", "emissions_totales"]) - .sort(["emissions_totales", "value"], descending=[True, True]) - .head(120) + .pivot(on="variable", index=["INSEE commune", "emissions_totales"]) + .sort("emissions_totales", descending=True) + .head(10) +) +df_emissions_top10.with_columns( + pl.col(cs.exclude("emissions_totales"))/pl.col("emissions_totales") ) ``` From f14c5bcb3d9cd8eaaef30cab6d2d2b5bf757b265 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 25 Feb 2026 10:27:20 +0000 Subject: [PATCH 43/92] with selectors --- source/manipulation/polars/tutorial.qmd | 91 ++++++++++++++----------- 1 file changed, 53 insertions(+), 38 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 8d729f4e..6c812f84 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -12,7 +12,7 @@ Plusieurs packages viennent ainsi combler ce manque, comme `pandas` ou `polars`. Comment choisir entre les deux ? Cela va dépendre de vos goûts et de vos besoins. Mais voici en attendant quelques éléments pour savoir si `polars` est utile. -Du côté des atouts de Polars : +Du côté des atouts de Polars : - Polars est **rapide** et permet de traiter des **données volumineuses** : Selon un benchmark [effectué par H2O](https://h2oai.github.io/db-benchmark/), Polars permet de traiter des données que d'autres librairies ne pourraient pas () @@ -34,12 +34,11 @@ Ces optimisations sont détaillées dans la [documentation officielle](https://p Polars présente quand même aussi quelques **inconvénients**, notamment lié à sa plus grande jeunesse. -- ainsi, le **traitement de données catégorielles** est encore instable, notamment en comparaison à pandas et -au tidyverse. +- ainsi, le **traitement de données catégorielles** est encore instable, notamment en comparaison à pandas et au tidyverse. Dans Polars pour contourner ces problèmes, on a tendance à traiter ces variable catégorielles comme des caractères. - **Pas (encore) de `geopolars`** : Tout l'écosystème autour de `pandas` n'a ainsi pas forcément (encore) d'équivalent en polars. -Pour les données géolocalisées par exemple, geopolars n'existe pas encore. +Pour les données géolocalisées par exemple, geopolars n'existe pas encore. - plus généralement, **`Polars` reste moins répandu que `pandas`** : Polars étant plus récent, il est en général moins bien interfacé avec les autres librairies de data science, même si certaines commencent à accepter des données @@ -50,20 +49,20 @@ polars en entrée. ## Petits conseils pour commencer -Avant de commencer à utiliser Polars, voici quelques conseils à garder en tête : +Avant de commencer à utiliser Polars, voici quelques conseils à garder en tête : -- L'import de données est **plus délicat** : +- L'import de données est **plus délicat** : Polars est très strict sur les types des colonnes quand on importe des données. Il est courant de passer du temps à débugger cette étape, notamment pour s'assurer que le code soit résistant à de légères variations dans le format des données d'entrée. -Pour optimiser ce temps là, on peut spécifier directement les types en entrée. +Pour optimiser ce temps là, on peut spécifier directement les types en entrée. -- Les **chaines de caractères sont par défaut associées à des colonnes** : -En Polars, les caractères simples `"myvar"` sont par défaut considéré comme des noms de -colonne. Il faut penser à utiliser `pl.lit("myvar")` pour signaler qu'il ne s'agit -pas d'un nom de colonne. +- Les **chaines de caractères sont par défaut associées à des colonnes** : +En Polars, les caractères simples `"myvar"` sont par défaut considéré comme des noms de +colonne. Il faut penser à utiliser `pl.lit("myvar")` pour signaler qu'il ne s'agit +pas d'un nom de colonne. -- **l'index de pandas** est mort <3 : comme dans le tidyverse, polars +- **l'index de pandas** est mort <3 : comme dans le tidyverse, polars n'utilise pas d'index, et c'est très bien comme cela ! - les `polars selectors` sont très pratiques pour sélectionner des colonnes. @@ -245,6 +244,24 @@ print(df.select(["var1", "experiment"])) ``` +Polars propose tout une série de méthodes, appelées `selectors`, très pratique pour effectuer des opérations sur des colonnes (sélection, mutation etc) en fonction de leur nom ou de leur type. +Par exemple, on peut sélectionner des colonnes suivant : +- leur nom (colonnes commençant par, finissant par, avec des regex) ; +- leur type ; +- exlcure des colonnes des résultats avec l'opération `-` (et plus généralement effectuer des opérations logiques). + +L'habitude est d'importer les selectors avec `import polars.selectors as cs`. + +Par exemple : + +- pour sélectionner toutes les colonnes numériques, on va utiliser `cs.numeric()` : +`df.select(cs.numeric())` ; +- pour sélectionner toutes les colonnes de caractères, on va utiliser `cs.string()` : +`df.select(cs.string())`. + +Des explications détaillées sont disponibles dans la [documentation officielle](https://docs.pola.rs/api/python/stable/reference/selectors.html). + + ## Sélectionner des lignes En pratique, on souhaite souvent filtrer un DataFrame selon certaines conditions. @@ -307,7 +324,7 @@ df.filter((pl.col("var1") >= 0) | pl.col("experiment").is_in(['train', 'validati ``` :::::: {.callout-note} -La méthode `filter` marche aussi sur des calculs à base des colonnes. Par exemple, si l'on veut sélectionner les observations faites le 2 du mois, on peut effectuer cela en une ligne (on verra plus tard le travail sur les données temporelles): +La méthode `filter` marche aussi sur des calculs à base des colonnes. Par exemple, si l'on veut sélectionner les observations faites le 2 du mois, on peut effectuer cela en une ligne (on verra plus tard le travail sur les données temporelles): ```{python} df.filter(pl.col('date').str.to_date("%Y-%m-%d").dt.day()==2) @@ -773,6 +790,20 @@ df = df.cast({'var2':pl.Int32}) df.glimpse() ``` + +On peut aussi utiliser les `selectors` de Polars pour faire des opérations groupées sur un ensemble +de colonnes. +Il suffit de remplacer le `pl.col("mycol")` par le sélecteur recherché. +Pour modifier les noms en série, on peut utiliser les fonctions liées aux méthodes `Expr.name`, *cf.* [documentation officielle](https://docs.pola.rs/api/python/stable/reference/expressions/name.html). + +Par exemple, si l'on veut normaliser à 1 toutes les colonnes numériques, on peut le faire en une ligne en spécifiant uniquement la colonne de référence : + +```{python} +df.with_columns( + (cs.numeric() / pl.col("var2")).name.suffix("_norm") +) +``` + ### Renommer des colonnes Une autre opération fréquente est le renommage d'une ou plusieurs colonnes. Pour cela, on peut utiliser la méthode [rename()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.rename.html#polars.DataFrame.rename), à laquelle on passe un dictionnaire qui contient autant de couples clé-valeur que de variables à renommer, et dans lequel chaque couple clé-valeur est de la forme `'ancien_nom': 'nouveau_nom'`. @@ -1214,7 +1245,7 @@ Par exemple, pour filtrer des données, on devra spécifier les bornes en appela ```{python} df.filter(pl.col('date') >= pl.date(2022, 1, 1), pl.col('date') < pl.date(2022, 1, 3)) -# équivalent à +# équivalent à from datetime import datetime df.filter(pl.col('date') >= datetime.strptime("2022-01-01", "%Y-%m-%d"), pl.col('date') < datetime.strptime("2022-01-03", "%Y-%m-%d")) @@ -1631,7 +1662,7 @@ print( Afficher la solution ```{python} -print(df.select(('enseigne', 'prix')) +print(df.select('enseigne', 'prix')) ``` @@ -1761,7 +1792,7 @@ prop_rares1 = ( .item(0, "tot_rel") ) print(prop_rares1) # ~ 2 % de la base -# equivalent à +# equivalent à prop_rares2 = ( df_prenoms .group_by("preusuel") @@ -2155,29 +2186,10 @@ df_pop_communes_stats.corr() ```{python} url_ademe = "https://data.ademe.fr/data-fair/api/v1/datasets/igt-pouvoir-de-rechauffement-global/data-files/IGT%20-%20Pouvoir%20de%20r%C3%A9chauffement%20global.csv" df_emissions = pl.from_pandas(pd.read_csv(url_ademe)) - -df_emissions.sample(10) -df_emissions.describe() -``` - - -::: - -- Y a-t-il des lignes avec des valeurs manquantes pour toutes les colonnes d'émission ? Vérifiez-le à l'aide des méthodes [is_null()](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.Expr.is_null.html#polars.Expr.is_null) et [all_horizontal()](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.all_horizontal.html#polars.all_horizontal). - ```{python} # Testez votre réponse dans cette cellule -``` - -::: {.cell .markdown} - -
-Afficher la solution - -```{python} -import polars.selectors as cs df_emissions_num = df_emissions.select(cs.numeric()) only_nan = df_emissions_num.filter(pl.all_horizontal(pl.all().is_null())) only_nan.height @@ -2190,6 +2202,7 @@ only_nan.height - Créez une nouvelle colonne qui donne les émissions totales par commune - Afficher les 10 communes les plus émettrices. Qu'observez-vous dans les résultats ? + ```{python} # Testez votre réponse dans cette cellule @@ -2208,10 +2221,12 @@ df_emissions_top10 = ( .pivot(on="variable", index=["INSEE commune", "emissions_totales"]) .sort("emissions_totales", descending=True) .head(10) + .with_columns( + (cs.numeric() / pl.col("emissions_totales")).name.suffix("_normalized") + ) ) -df_emissions_top10.with_columns( - pl.col(cs.exclude("emissions_totales"))/pl.col("emissions_totales") -) + +df_emissions_top10 ```
From 0cd93c6f66c39efa2e964e10d53420ec0ba65147 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 25 Feb 2026 10:59:07 +0000 Subject: [PATCH 44/92] fix typo --- source/manipulation/polars/tutorial.qmd | 31 ++++++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 6c812f84..c53fdc34 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -2092,7 +2092,7 @@ Cet exercice constitue une version simplifiée d'un [TP complet pour la pratique ### Partie 1 : Exploration des données sur les populations légales communales - Importez le fichier CSV `communes.csv`. -- Utilisez les méthodes `.sample()`, `.info()` et `.describe()` pour obtenir un aperçu des données. +- Utilisez les méthodes `.sample()` et `.describe()` pour obtenir un aperçu des données. ```{python} # Testez votre réponse dans cette cellule @@ -2171,13 +2171,14 @@ df_pop_communes_stats.corr() ### Partie 2 : Exploration des données sur les émissions communales - Importez les données d'émission depuis cette [URL](https://data.ademe.fr/data-fair/api/v1/datasets/igt-pouvoir-de-rechauffement-global/data-files/IGT%20-%20Pouvoir%20de%20r%C3%A9chauffement%20global.csv) -- Utilisez les méthodes `.sample()`, `.info()` et `.describe()` pour obtenir un aperçu des données. +- Utilisez les méthodes `.sample()` et `.describe()` pour obtenir un aperçu des données. ```{python} # Testez votre réponse dans cette cellule ``` + ::: {.cell .markdown}
@@ -2186,13 +2187,31 @@ df_pop_communes_stats.corr() ```{python} url_ademe = "https://data.ademe.fr/data-fair/api/v1/datasets/igt-pouvoir-de-rechauffement-global/data-files/IGT%20-%20Pouvoir%20de%20r%C3%A9chauffement%20global.csv" df_emissions = pl.from_pandas(pd.read_csv(url_ademe)) + +df_emissions.sample(10) +df_emissions.describe() +``` +
+ +::: + +- Y a-t-il des lignes avec des valeurs manquantes pour toutes les colonnes d'émission ? Vérifiez-le à l'aide des méthodes [is_null()](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.Expr.is_null.html#polars.Expr.is_null) et [all_horizontal()](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.all_horizontal.html#polars.all_horizontal). + ```{python} # Testez votre réponse dans cette cellule +``` + +::: {.cell .markdown} + +
+Afficher la solution + +```{python} df_emissions_num = df_emissions.select(cs.numeric()) -only_nan = df_emissions_num.filter(pl.all_horizontal(pl.all().is_null())) -only_nan.height +only_nulls = df_emissions_num.filter(pl.all_horizontal(pl.all().is_null())) +only_nulls.height ```
@@ -2233,7 +2252,7 @@ df_emissions_top10 ::: -- Il semble que les postes majeurs d'émissions soient "Industrie hors-énergie" et "Autres transports international". Pour vérifier si cette conjecture tient, calculer la corrélation entre les émissions totales et les postes sectoriels d'émissions à l'aide de la méthode [corrwith()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.corrwith.html). +- Il semble que les postes majeurs d'émissions soient "Industrie hors-énergie" et "Autres transports international". Pour vérifier si cette conjecture tient, calculer la corrélation entre les émissions totales et les postes sectoriels d'émissions à l'aide de la méthode [corr()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.corr.html#polars.DataFrame.corr). ```{python} # Testez votre réponse dans cette cellule @@ -2246,7 +2265,7 @@ df_emissions_top10 Afficher la solution ```{python} -df_emissions.corrwith(df_emissions["emissions_totales"], numeric_only=True) +df_emissions.select(cs.numeric()).corr() ``` From 994d55f2921bacfbfdbefbc5705d8849ccca183a Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 25 Feb 2026 11:07:08 +0000 Subject: [PATCH 45/92] with corr --- source/manipulation/polars/tutorial.qmd | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index c53fdc34..c9ede6ad 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -2233,12 +2233,16 @@ only_nulls.height Afficher la solution ```{python} -df_emissions_top10 = ( +df_emissions = ( df_emissions .unpivot(on=cs.numeric(), index="INSEE commune") .with_columns(emissions_totales=pl.sum("value").over("INSEE commune")) .pivot(on="variable", index=["INSEE commune", "emissions_totales"]) .sort("emissions_totales", descending=True) +) + +df_emissions_top10 = ( + df_emissions .head(10) .with_columns( (cs.numeric() / pl.col("emissions_totales")).name.suffix("_normalized") @@ -2265,7 +2269,13 @@ df_emissions_top10 Afficher la solution ```{python} -df_emissions.select(cs.numeric()).corr() +pl.concat( + [df_emissions.drop_nulls().select(cs.numeric()).corr().select("emissions_totales"), + pl.DataFrame({ + 'autre_col':df_emissions.select(cs.numeric()).columns + })], + how='horizontal' + ).sort("emissions_totales") ``` From ad1bd2b6bebc0c4d147c529efb08e6c4a3aad3d0 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 25 Feb 2026 12:13:37 +0000 Subject: [PATCH 46/92] with exo empreinte carbone - 2 --- source/manipulation/polars/tutorial.qmd | 29 ++++++++++++++++++------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index c9ede6ad..efdd5c3a 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -2269,13 +2269,18 @@ df_emissions_top10 Afficher la solution ```{python} -pl.concat( - [df_emissions.drop_nulls().select(cs.numeric()).corr().select("emissions_totales"), - pl.DataFrame({ - 'autre_col':df_emissions.select(cs.numeric()).columns - })], +( + pl.concat( + [ + df_emissions.drop_nulls().select(cs.numeric()).corr().select("emissions_totales"), + pl.DataFrame({ + 'autre_col':df_emissions.select(cs.numeric()).columns + }) + ], how='horizontal' - ).sort("emissions_totales") + ) + .sort("emissions_totales") +) ``` @@ -2297,8 +2302,16 @@ pl.concat( Afficher la solution ```{python} -df_emissions["dep"] = df_emissions["INSEE commune"].str[:2] -df_emissions.groupby("dep").agg({"emissions_totales": "sum"}).sort_values(by="emissions_totales", ascending=False).head(10) +( + df_emissions + .with_columns( + dep = pl.col("INSEE commune").str.head(2) + ) + .group_by("dep") + .agg(pl.sum("emissions_totales")) + .sort("emissions_totales") + .tail(10) +) ``` From cda6c2b2e118cfda59bf0ab794380e70c059a5d0 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 25 Feb 2026 12:59:32 +0000 Subject: [PATCH 47/92] with exo empreinte carbone - end --- source/manipulation/polars/tutorial.qmd | 36 ++++++++++++++++--------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index efdd5c3a..0f147c0f 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -2320,9 +2320,10 @@ df_emissions_top10 ### Partie 3 : Vérifications préalables pour la jointure des sources de données -Pour effectuer une jointure, il est toujours préférable d'avoir une clé de jointure, i.e. une colonne commune aux deux sources, qui identifie uniquement les unités statistiques. L'objet de cette partie est de trouver la clé de jointure pertinente. +Pour effectuer une jointure, il est toujours préférable d'avoir une clé de jointure, i.e. une colonne commune aux deux sources, qui identifie uniquement les unités statistiques. +L'objet de cette partie est de trouver la clé de jointure pertinente. -- Vérifiez si la variable contenant les noms de commune contient des doublons +- Vérifiez si la variable contenant les noms de commune de la table population contient des doublons ```{python} # Testez votre réponse dans cette cellule @@ -2335,9 +2336,7 @@ Pour effectuer une jointure, il est toujours préférable d'avoir une clé de jo Afficher la solution ```{python} -doublons = df_pop_communes.groupby('COM').count()['DEPCOM'] -doublons = doublons[doublons>1] -doublons = doublons.reset_index() +doublons = df_pop_communes.select(pl.col("COM").value_counts(name="nb_occurences")).unnest("COM").filter(pl.col("nb_occurences")>1) doublons ``` @@ -2358,8 +2357,8 @@ doublons Afficher la solution ```{python} -df_pop_communes_doublons = df_pop_communes[df_pop_communes["COM"].isin(doublons["COM"])] -df_pop_communes_doublons.sort_values('COM') +df_pop_communes_doublons = df_pop_communes.filter(pl.col("COM").is_in(doublons["COM"])).drop(pl.col("PTOT")) +df_pop_communes_doublons.sort('COM') ``` @@ -2379,7 +2378,7 @@ df_pop_communes_doublons.sort_values('COM') Afficher la solution ```{python} -(df_pop_communes_doublons.groupby("DEPCOM")["COM"].nunique() != 1).sum() +df_pop_communes_doublons.group_by("DEPCOM").n_unique().filter(pl.col("COM")>1).select(pl.sum("COM")) ``` @@ -2400,10 +2399,14 @@ df_pop_communes_doublons.sort_values('COM') ```{python} ## Observations qui sont dans les pop légales mais pas dans les données d'émissions -df_pop_communes[~df_pop_communes["DEPCOM"].isin(df_emissions["INSEE commune"])] +df_pop_communes.filter( + ~pl.col("DEPCOM").is_in(df_emissions["INSEE commune"]) + ) ## Observations qui sont dans les données d'émissions mais pas dans les pop légales -df_emissions[~df_emissions["INSEE commune"].isin(df_pop_communes["DEPCOM"])] +df_emissions.filter( + ~pl.col("INSEE commune").is_in(df_pop_communes["DEPCOM"]) + )["INSEE commune"] ``` @@ -2425,7 +2428,7 @@ df_emissions[~df_emissions["INSEE commune"].isin(df_pop_communes["DEPCOM"])] Afficher la solution ```{python} -df_emissions_pop = pd.merge(df_pop_communes, df_emissions, how="inner", left_on="DEPCOM", right_on="INSEE commune") +df_emissions_pop = df_pop_communes.join(df_emissions, how="inner", left_on="DEPCOM", right_on="INSEE commune") df_emissions_pop ``` @@ -2448,8 +2451,15 @@ df_emissions_pop Afficher la solution ```{python} -df_emissions_pop["empreinte_carbone"] = df_emissions_pop["emissions_totales"] / df_emissions_pop["PTOT"] -df_emissions_pop.sort_values("empreinte_carbone", ascending=False).head(10) +df_emissions_pop = ( + df_emissions_pop + .with_columns( + empreinte_carbone=pl.col("emissions_totales") / pl.col("PTOT") + ) + .sort("empreinte_carbone") +) + +df_emissions_pop.tail(10) ``` From 9f272255868c3f556d75a5873ae8b845241fbdf6 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 25 Feb 2026 13:06:29 +0000 Subject: [PATCH 48/92] indice - part 1 --- source/manipulation/polars/tutorial.qmd | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 0f147c0f..03fe6895 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -2480,7 +2480,7 @@ L'objectif est d'utiliser `Pandas` pour calculer : ### Partie 1 : Import des données -- Importez les deux fichiers CSV dans des DataFrames. Attention, dans les deux cas, il y a des lignes superflues avant les données, qu'il faudra sauter à l'aide du paramètre `skiprows` de la fonction [read_csv()](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html). +- Importez les deux fichiers CSV dans des DataFrames. Attention, dans les deux cas, il y a des lignes superflues avant les données, qu'il faudra sauter à l'aide du paramètre `skip_rows` de la fonction [read_csv()](https://docs.pola.rs/api/python/stable/reference/api/polars.read_csv.html#polars.read_csv). - Donnez des noms simples et pertinents aux différentes variables. ```{python} @@ -2494,10 +2494,10 @@ L'objectif est d'utiliser `Pandas` pour calculer : Afficher la solution ```{python} -df_valeurs = pd.read_csv('data/serie_glaces_valeurs.csv', delimiter=';', - skiprows=4, names=["periode", "indice", "code"]) -df_metadata = pd.read_csv('data/serie_glaces_metadonnees.csv', delimiter=';', - skiprows=5, names=["code", "signification"]) +df_valeurs = pl.read_csv('data/serie_glaces_valeurs.csv', separator=';', + skip_rows=4, has_header=False, new_columns=["periode", "indice", "code"]) +df_metadata = pl.read_csv('data/serie_glaces_metadonnees.csv', separator=';', + skip_rows=5, has_header=False, new_columns=["code", "signification"]) ``` From 96e508765303a4e172462caa70baf938715b689b Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 25 Feb 2026 13:23:28 +0000 Subject: [PATCH 49/92] indice - end --- source/manipulation/polars/tutorial.qmd | 35 ++++++++++++++++--------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 03fe6895..9dce9e1e 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -2521,10 +2521,10 @@ df_metadata = pl.read_csv('data/serie_glaces_metadonnees.csv', separator=';', Afficher la solution ```{python} -df_merged = pd.merge(df_valeurs, df_metadata, how='left', on='code') +df_merged = df_valeurs.join(df_metadata, how='left', on='code') -df_clean = df_merged[df_merged['code'] == "A"] -df_clean = df_clean[["periode", "indice"]] +df_clean = df_merged.filter(pl.col("code") == "A") +df_clean = df_clean.select("periode", "indice") ``` @@ -2546,10 +2546,12 @@ Vérifiez si les types des variables sont pertinents selon leur nature. Sinon, c Afficher la solution ```{python} -df_clean.info() -df_clean['periode'] = pd.to_datetime(df_clean['periode']) -df_clean['indice'] = pd.to_numeric(df_clean['indice']) -df_clean.info() +df_clean.describe() +df_clean = df_clean.with_columns( + periode = pl.col("periode").str.to_date("%Y-%m"), + indice = pl.col("indice").cast(pl.Float64) +) +df_clean.glimpse() ``` @@ -2558,7 +2560,7 @@ df_clean.info() ### Partie 4 : Calcul de l'évolution périodique -- Utilisez la méthode [shift()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.shift.html) pour créer une nouvelle colonne qui contiendra l'indice du trimestre précédent +- Utilisez la méthode [shift()](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.Expr.shift.html#polars.Expr.shift) pour créer une nouvelle colonne qui contiendra l'indice du trimestre précédent - Calculez la différence entre l'indice actuel et l'indice décalé pour obtenir l'évolution (en pourcentage) d'un trimestre à l'autre ```{python} @@ -2572,11 +2574,16 @@ df_clean.info() Afficher la solution ```{python} -df_clean['indice_prec'] = df_clean['indice'].shift(1) -df_clean['evo'] = ((df_clean['indice'] - df_clean['indice_prec']) / df_clean['indice_prec']) * 100 +df_clean = ( + df_clean + .sort("periode") + .with_columns( + evo = ((pl.col("indice") - pl.col("indice").shift(1)) / pl.col("indice").shift(1))*100 + ) +) ## Méthode alternative -df_clean['evo_alt'] = df_clean['indice'].pct_change(periods=1) * 100 +df_clean.with_columns(evo_alt = pl.col("indice").pct_change(n=1) * 100) ``` @@ -2585,7 +2592,8 @@ df_clean['evo_alt'] = df_clean['indice'].pct_change(periods=1) * 100 ### Partie 5 : Calcul de l'évolution glissante sur 12 mois -Comme vous avez pu le voir dans la solution de l'exercice précédent, la méthode [pct_change()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.pct_change.html) permet précisément de calculer une évolution entre deux périodes. Utiliser cette méthode pour calculer une évolution (en pourcentage) en glissement annuel pour chaque mois. +Comme vous avez pu le voir dans la solution de l'exercice précédent, la méthode [pct_change()](https://docs.pola.rs/api/python/stable/reference/series/api/polars.Series.pct_change.html#polars.Series.pct_change) permet précisément de calculer une évolution entre deux périodes. +Utiliser cette méthode pour calculer une évolution (en pourcentage) en glissement annuel pour chaque mois. ```{python} # Testez votre réponse dans cette cellule @@ -2598,7 +2606,8 @@ Comme vous avez pu le voir dans la solution de l'exercice précédent, la métho Afficher la solution ```{python} -df_clean["evo_glissement_annuel"] = df_clean['indice'].pct_change(periods=12) * 100 +df_clean = df_clean.with_columns(evo_glissement_annuel=pl.col("indice").pct_change(n=12) * 100) + df_clean.head(20) ``` From 85945f15a40de490ec65a02bc5bc021f91c4f08a Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 25 Feb 2026 13:25:01 +0000 Subject: [PATCH 50/92] typo --- source/manipulation/polars/tutorial.qmd | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 9dce9e1e..3cb35d39 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -1751,7 +1751,6 @@ Le fichier des prénoms contient des données sur les prénoms attribués aux en Afficher la solution ```{python} -import pandas as pd url = "https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip" df_prenoms = pl.from_pandas(pd.read_csv(url, sep=";")) @@ -2087,7 +2086,7 @@ L'objectif de cet exercice est de calculer une empreinte carbone par habitant au - les émissions de gaz à effet de serre estimées au niveau communal par l’ADEME ([source](https://www.data.gouv.fr/fr/datasets/inventaire-de-gaz-a-effet-de-serre-territorialise/#_)) -Cet exercice constitue une version simplifiée d'un [TP complet pour la pratique de Pandas](https://pythonds.linogaliana.fr/content/manipulation/02b_pandas_TP.html#importer-les-donn%C3%A9es) proposé par Lino Galiana dans son [cours à l'ENSAE](https://pythonds.linogaliana.fr/). +Cet exercice constitue une version simplifiée d'un [TP complet pour la pratique de Pandas](https://pythonds.linogaliana.fr/content/manipulation/02b_pandas_TP.html#importer-les-donn%C3%A9es) proposé par Lino Galiana dans son [cours à l'ENSAE](https://pythonds.linogaliana.fr/) et traduit en Polars. ### Partie 1 : Exploration des données sur les populations légales communales @@ -2473,7 +2472,7 @@ Vous avez à disposition dans le dossier `data/` deux jeux de données CSV : - `serie_glaces_valeurs.csv` contient les valeurs mensuelles de l'indice de prix de production de l'industrie française des glaces et sorbets - `serie_glaces_metadonnees.csv` contient les métadonnées associées, notamment les codes indiquant le statut des données. -L'objectif est d'utiliser `Pandas` pour calculer : +L'objectif est d'utiliser `Polars` pour calculer : - l'évolution de l'indice entre chaque période (mois) - l'évolution de l'indice en glissement annuel (entre un mois donné et le même mois l'année suivante). From 26703d6ecb7b0df9a62932fb722e38fd4b8f6586 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 25 Feb 2026 13:48:35 +0000 Subject: [PATCH 51/92] harmonization --- source/manipulation/polars/tutorial.qmd | 209 ++++++++++++------------ 1 file changed, 105 insertions(+), 104 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 3cb35d39..7d16a961 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -1,5 +1,5 @@ ::: {.content-visible when-profile="fr"} -# Introduction - traiter des données tabulaires avec Polars +# Introduction - traiter des données tabulaires avec `polars` L'analyse statistique a généralement pour base des **données tabulaires**, dans lesquelles chaque ligne représente une observation et chaque colonne une variable. Pour traiter ce type de données et y appliquer facilement les méthodes d'analyse de données standards, des objets dédiés ont été conçus : les `DataFrames`. @@ -12,44 +12,44 @@ Plusieurs packages viennent ainsi combler ce manque, comme `pandas` ou `polars`. Comment choisir entre les deux ? Cela va dépendre de vos goûts et de vos besoins. Mais voici en attendant quelques éléments pour savoir si `polars` est utile. -Du côté des atouts de Polars : +Du côté des atouts de `polars` : -- Polars est **rapide** et permet de traiter des **données volumineuses** : Selon un benchmark [effectué par H2O](https://h2oai.github.io/db-benchmark/), +- `polars` est **rapide** et permet de traiter des **données volumineuses** : Selon un benchmark [effectué par H2O](https://h2oai.github.io/db-benchmark/), Polars permet de traiter des données que d'autres librairies ne pourraient pas () et les traite aussi rapidement que le package `R` `data.table`. et 3 à 4 fois plus vite que d'autres librairies. -- Polars permet même de traiter des **données _out of memory_ :** `Polars` présente aussi l'avantage +- `polars` permet même de traiter des **données _out of memory_ :** `Polars` présente aussi l'avantage de lire naturellement des jeux de données hors des limites de la mémoire de l'ordinateur grâce à [sa capacité de lire en flux](https://www.youtube.com/watch?v=3-C0Afs5TXQ) (méthode qu'on appelle le _streaming_). -- Polars permet une **évaluation paresseuse** (*lazy evaluation*) : ce mode de calcul +- `polars` permet une **évaluation paresseuse** (*lazy evaluation*) : ce mode de calcul permet d'optimiser vos traitements pour proposer une exécution plus rapide (pour la lecture comme pour la transformation des jeux de données). Elle peut permettre d'avancer un `select` ou un `filter` si les opérations ultérieures ne sont pas impactées. Ces optimisations sont détaillées dans la [documentation officielle](https://pola-rs.github.io/polars-book/user-guide/optimizations/intro.html). -- Une **API fluide** : L'API proposée par Polars est à la fois expressive et transparente. Ceci répond notamment aux commentaires sur `pandas`, où la syntaxe de manipulations des données est parfois complexe ou peu lisible et les choix d'écriture ne sont pas transparents du point de vue des performances. +- Une **API fluide** : L'API proposée par `polars` est à la fois expressive et transparente. Ceci répond notamment aux commentaires sur `pandas`, où la syntaxe de manipulations des données est parfois complexe ou peu lisible et les choix d'écriture ne sont pas transparents du point de vue des performances. - Un **pipe natif** : On retrouve une sémantique d'opérations de haut niveau qui s'enchaînent à la manière de [ce que l'on peut faire en `dplyr`](https://www.book.utilitr.org/03_fiches_thematiques/fiche_tidyverse#comment-utiliser-lop%C3%A9rateur-pipe-avec-le-tidyverse). Polars présente quand même aussi quelques **inconvénients**, notamment lié à sa plus grande jeunesse. -- ainsi, le **traitement de données catégorielles** est encore instable, notamment en comparaison à pandas et au tidyverse. -Dans Polars pour contourner ces problèmes, on a tendance à traiter ces variable catégorielles comme des caractères. +- ainsi, le **traitement de données catégorielles** est encore instable, notamment en comparaison à `pandas` et au tidyverse. +Dans `polars` pour contourner ces problèmes, on a tendance à traiter ces variable catégorielles comme des caractères. -- **Pas (encore) de `geopolars`** : Tout l'écosystème autour de `pandas` n'a ainsi pas forcément (encore) d'équivalent en polars. +- **Pas (encore) de `geopolars`** : Tout l'écosystème autour de `pandas` n'a ainsi pas forcément (encore) d'équivalent en `polars`. Pour les données géolocalisées par exemple, geopolars n'existe pas encore. -- plus généralement, **`Polars` reste moins répandu que `pandas`** : Polars étant plus récent, il est en général moins bien interfacé avec les autres +- plus généralement, **`Polars` reste moins répandu que `pandas`** : `polars` étant plus récent, il est en général moins bien interfacé avec les autres librairies de data science, même si certaines commencent à accepter des données `polars` en entrée. -La rapidité et simplicité de Polars permet cependant facilement de repasser à un -dataframe pandas pour les librairies qui n'accepteraient pas encore de dataframe +La rapidité et simplicité de `polars` permet cependant facilement de repasser à un +dataframe `pandas` pour les librairies qui n'accepteraient pas encore de dataframe polars en entrée. ## Petits conseils pour commencer -Avant de commencer à utiliser Polars, voici quelques conseils à garder en tête : +Avant de commencer à utiliser `polars`, voici quelques conseils à garder en tête : - L'import de données est **plus délicat** : Polars est très strict sur les types des colonnes quand on importe des données. @@ -58,11 +58,11 @@ que le code soit résistant à de légères variations dans le format des donné Pour optimiser ce temps là, on peut spécifier directement les types en entrée. - Les **chaines de caractères sont par défaut associées à des colonnes** : -En Polars, les caractères simples `"myvar"` sont par défaut considéré comme des noms de +En `polars`, les caractères simples `"myvar"` sont par défaut considéré comme des noms de colonne. Il faut penser à utiliser `pl.lit("myvar")` pour signaler qu'il ne s'agit pas d'un nom de colonne. -- **l'index de pandas** est mort <3 : comme dans le tidyverse, polars +- **l'index de `pandas`** est mort <3 : comme dans le tidyverse, `polars` n'utilise pas d'index, et c'est très bien comme cela ! - les `polars selectors` sont très pratiques pour sélectionner des colonnes. @@ -86,11 +86,11 @@ import polars.selectors as cs ## pour aller plus loin Voici un ensemble de ressources si vous voulez aller plus loin sur l'écosystème -de Polars : +de `polars` : -- [Blog Awesome Polars](https://ddotta.github.io/awesome-polars/), par Damien D -- [Blog sur Polars sur le site du SSPHub](https://ssphub.netlify.app/post/polars/) -- [Notebook Polars](https://datalab.sspcloud.fr/launcher/ide/jupyter-python?name=Tutoriel%20Polars&version=2.3.28&s3=region-79669f20&init.personalInit=«https%3A%2F%2Fraw.githubusercontent.com%2Fntoulemonde%2Ftest%2Frefs%2Fheads%2Fmain%2Finit.sh»&autoLaunch=true) +- [Blog Awesome `polars`](https://ddotta.github.io/awesome-polars/), par Damien D +- [Blog sur `polars` sur le site du SSPHub](https://ssphub.netlify.app/post/polars/) +- [Notebook `polars`](https://datalab.sspcloud.fr/launcher/ide/jupyter-python?name=Tutoriel%20Polars&version=2.3.28&s3=region-79669f20&init.personalInit=«https%3A%2F%2Fraw.githubusercontent.com%2Fntoulemonde%2Ftest%2Frefs%2Fheads%2Fmain%2Finit.sh»&autoLaunch=true) ::: {.panel-tabset group="polars_vs_tidypolars" name="Pour commencer"} @@ -107,17 +107,17 @@ il y a le package [tidypolars](https://tidypolars.readthedocs.io/en/latest/). Les noms des fonctions dans tidypolars sont presque tous identiques à ceux du tidyverse: -- un `DataFrame` de Polars devient un `tibble` chez tidypolars; +- un `DataFrame` de `polars` devient un `tibble` chez tidypolars; - la structure de la création d'un `tibble` est la même que dans R; -- les méthodes `filter`, `select` de Polars restent les mêmes; -- la méthode `with_columns` de Polars devient `mutate` ... +- les méthodes `filter`, `select` de `polars` restent les mêmes; +- la méthode `with_columns` de `polars` devient `mutate` ... Tidypolars reprend ainsi exactement la syntaxe des principales fonctions de dplyr, tidyr, stringr, lubridate, tidyselect directement dans Python! La liste complète des fonctions reprises est disponible dans la [documentation](https://tidypolars.readthedocs.io/en/latest/reference.html). La seule différence notable entre tidypolars et R est liée aux colonnes, qui sont accessibles par `pl.col/tp.col` dans `polars/tidypolars` quand dans R leur nom seul suffit. -Pour la simplicité du tutoriel, le tutoriel présente le début avec tidypolars mais ensuite utilise uniquement Polars. +Pour la simplicité du tutoriel, le tutoriel présente le début avec tidypolars mais ensuite utilise uniquement `polars`. Pour plus de détail, allez voir la [documentation](https://tidypolars.readthedocs.io/en/latest/reference.html) ! ```{python} @@ -175,9 +175,9 @@ df ::: -A noter qu'une valeur manquante est indiquée par `None` en Polars. Elle sera ensuite traduite en type Null interne à Polars. +A noter qu'une valeur manquante est indiquée par `None` en `polars`. Elle sera ensuite traduite en type Null interne à `polars`. -Un DataFrame Polars dispose d'un ensemble d'attributs utiles que nous allons découvrir tout au long de ce tutoriel. Pour l'instant, intéressons-nous aux plus basiques : le nom des colonnes. +Un DataFrame `polars` dispose d'un ensemble d'attributs utiles que nous allons découvrir tout au long de ce tutoriel. Pour l'instant, intéressons-nous aux plus basiques : le nom des colonnes. ```{python} df = pl.DataFrame( @@ -218,12 +218,12 @@ selected_column ``` L'objet `selected_column` renvoie ici la colonne nommée `var1` du `DataFrame` `df`. -Contrairement à Pandas, ici on ne garde qu'une seule colonne du dataframe, on ne l'extrait pas. -L'objet `selected_columns` reste donc un dataframe de 1 colonne, et n'est pas une série Polars. +Contrairement à `pandas`, ici on ne garde qu'une seule colonne du dataframe, on ne l'extrait pas. +L'objet `selected_columns` reste donc un dataframe de 1 colonne, et n'est pas une série `polars`. Si on sélectionnait 2 colonnes, cela serait ainsi aussi un dataframe. ::: {.callout-tip} -Si vous voulez transformer un dataframe en une série Polars, il faut utiliser la méthode `to_series()` ou reprendre la syntaxe de Pandas qui marche aussi en Polars : +Si vous voulez transformer un dataframe en une série `polars`, il faut utiliser la méthode `to_series()` ou reprendre la syntaxe de `pandas` qui marche aussi en `polars` : ```{python} print(f'En passant par select.to_series(), la table \n {df.select('var1').to_series()} \n est de type {type(df.select('var1').to_series())}') @@ -276,7 +276,7 @@ df |> filter(var1>=0) ``` -en Polars, on va l'écrire +en `polars`, on va l'écrire ```{python} print(df.filter(pl.col('var1')>=0)) @@ -340,35 +340,35 @@ Polars offre des outils puissants et très rapides pour importer ces fichiers ta ## Importer et exporter des données Polars est très sensible au format des données, l'import peut donc parfois être un peu long à débuger quand il n'arrive pas à déterminer le format de données de la colonne. -En effet, Polars va traiter chaque colonne comme une série d'un des formats qu'il connaît. -Les formats de données sont détaillés dans la [documentation de Polars](https://docs.pola.rs/api/python/stable/reference/datatypes.html). +En effet, `polars` va traiter chaque colonne comme une série d'un des formats qu'il connaît. +Les formats de données sont détaillés dans la [documentation de `polars`](https://docs.pola.rs/api/python/stable/reference/datatypes.html). Ils comprennent principalement: -| Famille de format | Format Polars | Remarques | +| Famille de format | Format `polars` | Remarques | | -- | -- | -- | -| Caractères | - `pl.String`
- `pl.Utf8` | les données catégorielles (`pl.Categorical`) sont encore peu matures dans Polars.
Il peut donc mieux valoir les traiter simplement comme des caractères usuels. | +| Caractères | - `pl.String`
- `pl.Utf8` | les données catégorielles (`pl.Categorical`) sont encore peu matures dans `polars`.
Il peut donc mieux valoir les traiter simplement comme des caractères usuels. | | Nombres | | | | - entiers | - `pl.Int8`
- `pl.Int16`
- `pl.Int32` ... | | | - numérique | - `pl.Float16`
- `pl.Float32`
- `pl.Float64` | | | Temporelles | - `pl.Date`
- `pl.Datetime`
- `pl.Duration` ... | | | Structures imbriquées | | - le format `pl.Struc` très pratique pour lire des formats imbriqués comme des JSON | -| Valeurs manquantes | | Polars traite les valeurs manquantes à part. | +| Valeurs manquantes | | `polars` traite les valeurs manquantes à part. | ::: {.callout-caution} -A noter que pour Polars, les types `null` et `nan` sont différents. +A noter que pour `polars`, les types `null` et `nan` sont différents. `null` est une valeur manquante, quelque soit le type de valeur (caractère, numérique, temporelle, imbriquée ...). On le déclare avec un `None`. `NaN`, qui signifie _Not a Number_, est une valeur manquante **numérique** (et non pour les entiers). -Cela signifie que Polars le traite comme un nombre particulier. -On déclare un `NaN` soit en utilisant Numpy `np.nan`, soit une syntaxe de Polars : `float("nan")`. +Cela signifie que `polars` le traite comme un nombre particulier. +On déclare un `NaN` soit en utilisant Numpy `np.nan`, soit une syntaxe de `polars` : `float("nan")`. Plus de détail sur la [documentation](https://docs.pola.rs/user-guide/expressions/missing-data/#null-and-nan-values). ::: On peut convertir une colonne d'un type à l'autre avec la méthode `cast` en indiquant -dans un dictionnaire le nom de la colonne et le format Polars souhaité. +dans un dictionnaire le nom de la colonne et le format `polars` souhaité. -Par exemple, dans la table `df` définie ci-dessus, Polars a assigné les formats suivants : +Par exemple, dans la table `df` définie ci-dessus, `polars` a assigné les formats suivants : ```{python} df.schema @@ -397,14 +397,14 @@ with open("data/departement2021.csv") as file_in: rows[:5] ``` -Avec Polars, il suffit d'utiliser la fonction `read_csv()` pour importer le fichier comme un DataFrame, puis la fonction `head()`. +Avec `polars`, il suffit d'utiliser la fonction `read_csv()` pour importer le fichier comme un DataFrame, puis la fonction `head()`. ```{python} df_departements = pl.read_csv('data/departement2021.csv') df_departements.head() ``` -A la différence de Pandas et à la date d'écriture de ce tutoriel, Polars ne charge pas directement depuis une URL et ne dézippe pas encore automatiquement le fichier csv (_cf._ [discussion de cette problématique sur Github](https://github.com/pola-rs/polars/issues/19447)). +A la différence de `pandas` et à la date d'écriture de ce tutoriel, `polars` ne charge pas directement depuis une URL et ne dézippe pas encore automatiquement le fichier csv (_cf._ [discussion de cette problématique sur Github](https://github.com/pola-rs/polars/issues/19447)). Soit on utilise la fonction idoine de `pandas` et après on transforme le dataframe en `polars` facilement grâce à la fonction `pl.from_pandas`. ```{python} @@ -437,9 +437,9 @@ with ZipFile(file_Path, 'r') as zObject: ``` -Par exemple, une erreur sera causée ici à cause de types de données incohérentes détectées par Polars. -En regardant le message d'erreur, Polars traite la colonne `anais` comme un entier. -Mais la lecture de la valeur `XXXX` cause une erreur et n'est pas convertible en entier par Polars. +Par exemple, une erreur sera causée ici à cause de types de données incohérentes détectées par `polars`. +En regardant le message d'erreur, `polars` traite la colonne `annais` comme un entier. +Mais la lecture de la valeur `XXXX` cause une erreur et n'est pas convertible en entier par `polars`. ```{python} #| eval: false @@ -448,7 +448,7 @@ df_prenoms_url = pl.read_csv('temp/' + os.listdir('temp')[0], separator=";") ``` Dans ce cas, deux solutions existent : -- On peut dire à Polars de traiter toutes les colonnes comme des caractères avec infer_schema=False +- On peut dire à `polars` de traiter toutes les colonnes comme des caractères avec infer_schema=False ```{python} import os @@ -477,7 +477,7 @@ Tous ces paramètres et leur utilisation sont détaillés dans la [documentation ### Exporter au format CSV -Une fois que les données ont été traitées et modifiées au sein de Polars, il est courant de vouloir exporter le résultat sous forme de fichier CSV pour le partager, l'archiver ou l'utiliser dans d'autres outils. +Une fois que les données ont été traitées et modifiées au sein de `polars`, il est courant de vouloir exporter le résultat sous forme de fichier CSV pour le partager, l'archiver ou l'utiliser dans d'autres outils. Polars offre une méthode simple pour cette opération : `write_csv()`. Supposons par exemple que l'on souhaite exporter les données du DataFrame `df_departements` spécifiques aux cinq départements d'outre-mer. @@ -492,9 +492,9 @@ df_departements_dom.write_csv('output/departements2021_dom.csv', separator=";") Le format Parquet est un autre format pour le stockage de données tabulaires, de plus en plus fréquemment utilisé. Sans entrer dans les détails techniques, le format Parquet présente différentes caractéristiques qui en font un choix privilégié pour le stockage et le traitement de gros volumes de données. En raison de ces avantages, ce format est de plus en plus utilisé pour la mise à disposition de données à l'Insee. -Il est donc essentiel de savoir importer et requêter des fichiers Parquet avec Polars. +Il est donc essentiel de savoir importer et requêter des fichiers Parquet avec `polars`. -Importer un fichier Parquet dans un DataFrame Pandas se fait tout aussi facilement que pour un fichier CSV. +Importer un fichier Parquet dans un DataFrame `pandas` se fait tout aussi facilement que pour un fichier CSV. La fonction se nomme `read_parquet()`. ```{python} @@ -533,7 +533,7 @@ df = pl.DataFrame( ``` On utilise cette fois deux types de données spécifiques, pour les données catégorielles (`categorical`) et pour les données temporelles (`date`), comme présenté précédemment. -Le format des données est imprimé par Polars dans la sortie : on voit maintenant en +Le format des données est imprimé par `polars` dans la sortie : on voit maintenant en dessous du nom des colonnes que le format des colonnes `experiment` et `date` ont changé. On verra plus loin dans le tutoriel comment utiliser ces types. @@ -551,7 +551,7 @@ df_test_schema_parquet ``` A l'inverse, un fichier CSV ne contenant par définition que du texte, ne permet pas de préserver ces données. -Les variables dont nous avons spécifié le type sont importées comme des strings (type `object` en Polars). +Les variables dont nous avons spécifié le type sont importées comme des strings (type `object` en `polars`). ```{python} df.write_csv("output/df_test_schema.csv") @@ -562,7 +562,7 @@ df_test_schema_csv ### Importer depuis un dictionnaire -Comme illustré dans le tutoriel [Travailler avec des fichiers CSV et JSON](../csv-json-files/tutorial.qmd), on peut aussi créer un dataFrame Polars à partir d'un dictionnaire. +Comme illustré dans le tutoriel [Travailler avec des fichiers CSV et JSON](../csv-json-files/tutorial.qmd), on peut aussi créer un dataFrame `polars` à partir d'un dictionnaire. Cela sera très utile par exemple quand on récupère les données d'une API (_cf._ cours de [Python pour la data-science](https://pythonds.linogaliana.fr/) et la partie sur les API). @@ -580,7 +580,7 @@ response = requests.get("https://data.geopf.fr/geocodage/search?q=comedie&type=s ``` Le résultat de la requête est un dictionnaire avec 3 clés, dont la deuxième, 'features', stocke les résultats sous forme d'une liste. -Pour importer directement ce fichier en Polars, on peut utiliser la méthode from_dict ou from_dicts. +Pour importer directement ce fichier en `polars`, on peut utiliser la méthode from_dict ou from_dicts. ```{python} df = pl.from_dicts(json.loads(response.text)) @@ -606,7 +606,7 @@ df = df.select("features").unnest("features").drop('type').unnest('geometry').dr ### Autres exports et imports - **Exporter vers un dictionnaire**: -De manière similaire, Polars permet d'exporter un DataFrame vers un dictionnaire. +De manière similaire, `polars` permet d'exporter un DataFrame vers un dictionnaire. - La méthode `to_dict` permet d'exporter un DataFrame "en format colonne". L'export sera un seul dictionnaire dont les clés sont les noms des colonnes et @@ -615,10 +615,11 @@ les valeurs les listes des valeurs prises par colonne `{'a':[1, 2, 3], 'b': [3, L'export sera une liste dont les termes seront les lignes du DataFrame, représentées à chaque fois par un dictionnaire : `[{'a': 1, 'b': 3}, {'a': 2, 'b': 2}, {'a': 3, 'b': 1}]` -- **Depuis/vers Pandas**: -Polars permet aussi facilement d'exporter et d'importer des DataFrame au format Pandas. -Cela permet de travailler avec Polars et de convertir un DataFrame en Pandas quand un package n'autorise pas l'import depuis Polars. -Il suffit d'utiliser la fonction `pl.from_pandas(df)` et la méthode `df.to_pandas()`. +- **Depuis/vers `pandas`**: +Polars permet aussi facilement d'exporter et d'importer des DataFrame au format `pandas`. +Cela permet de travailler avec `polars` et de convertir un DataFrame en `pandas` quand un package n'autorise pas l'import depuis `polars`. +Il suffit d'utiliser la fonction `pl.from_pandas(df)` pour importer un dataframe `pandas` en `polars`. +La méthode `df.to_pandas()` permettra d'exporter un `polars` dataframe vers `pandas`. # Visualiser un échantillon des données @@ -626,7 +627,7 @@ Lorsqu'on travaille avec des jeux de données volumineux, il est souvent utile d des données pour avoir une idée de leur structure, de leur format ou encore pour détecter d'éventuels problèmes. Polars offre plusieurs méthodes pour cela. -Par défaut, Polars indique les cinq premières et cinq dernières lignes d'un DataFrame et indique la forme (_shape_). +Par défaut, `polars` indique les cinq premières et cinq dernières lignes d'un DataFrame et indique la forme (_shape_). ```{python} df_departements @@ -658,7 +659,7 @@ df_departements.sample(n=5) ## Obtenir une vue d'ensemble des données L'une des premières étapes lors de l'exploration de nouvelles données est de comprendre la structure générale du jeu de données. -La méthode `glimpse()` de Polars offre une vue d'ensemble rapide des données, notamment en termes de types de données et affiche les données. +La méthode `glimpse()` de `polars` offre une vue d'ensemble rapide des données, notamment en termes de types de données et affiche les données. ```{python} df.glimpse() @@ -670,13 +671,13 @@ Plusieurs éléments d'information clés peuvent être extraits de ce résultat - **schéma** : la liste des colonnes est affichée avec des informations très utiles sur le schéma des données : - - **Format** : Le format Polars de données de la colonne, par exemple ``pour un format caractère (ou `pl.String`). + - **Format** : Le format `polars` de données de la colonne, par exemple ``pour un format caractère (ou `pl.String`). Cela permet de comprendre la nature des informations stockées dans chaque colonne. - **les premières valeurs** : après chaque colonne sont indiquées, à l'horizontale, les premières valeurs de la colonne. Cela permet de mieux comprendre le schéma du DataFrame. -Contrairement à Pandas, cette méthode n'affiche pas les valeurs manquantes. +Contrairement à `pandas`, cette méthode n'affiche pas les valeurs manquantes. Pour cela, il faut utiliser les statistiques descriptives. ## Calculer des statistiques descriptives @@ -702,7 +703,7 @@ Les transformations peuvent concerner l'ensemble du DataFrame, des colonnes spé ### Transformer les colonnes -En équivalent de `mutate` du tidyverse ou du `replace` de pandas, Polars utilise `with_columns`. +En équivalent de `mutate` du tidyverse ou du `replace` de `pandas`, `polars` utilise `with_columns`. Le fonctionnement est similaire au `mutate` du tidyverse. Il permet ainsi de modifier des valeurs de colonne, d'effectuer des opérations etc. @@ -733,7 +734,7 @@ df.with_columns( ::: {.callout-tip} La structure `pl.when` est très pratique et équivaut à la structure `ifelse` en R. -Par exemple, si je veux définir la colonne val à partir de la colonne foo selon le schéma : si foo > 2 : val = 1, sinon val = 1 + bar, cela s'écrite en polars : +Par exemple, si je veux définir la colonne val à partir de la colonne foo selon le schéma : si foo > 2 : val = 1, sinon val = 1 + bar, cela s'écrite en `polars` : ```{python} @@ -747,7 +748,7 @@ df.with_columns( ::: {.callout-warning} -Attention, en Polars, les caractères simples sont assimilés aux colonnes. +Attention, en `polars`, les caractères simples sont assimilés aux colonnes. Pour insérer un caractère, utiliser pl.lit. ```{python} @@ -782,7 +783,7 @@ df.glimpse() Dans ce cas, on peut utiliser la méthode `cast` pour convertir la colonne dans le type souhaité en spécifiant avec un dictionnaire les colonnes à modifier. Le dictionnaire est écrit sous le format `{'nom de la colonne 1':'type Polars à appliquer', 'nom de la colonne 2':'type Polars à appliquer'}`. -Les types sont décrits plus haut et dans la [documentation de Polars](https://docs.pola.rs/api/python/stable/reference/datatypes.html). +Les types sont décrits plus haut et dans la [documentation de `polars`](https://docs.pola.rs/api/python/stable/reference/datatypes.html). ```{python} df = df.cast({'var2':pl.Int32}) @@ -791,7 +792,7 @@ df.glimpse() ``` -On peut aussi utiliser les `selectors` de Polars pour faire des opérations groupées sur un ensemble +On peut aussi utiliser les `selectors` de `polars` pour faire des opérations groupées sur un ensemble de colonnes. Il suffit de remplacer le `pl.col("mycol")` par le sélecteur recherché. Pour modifier les noms en série, on peut utiliser les fonctions liées aux méthodes `Expr.name`, *cf.* [documentation officielle](https://docs.pola.rs/api/python/stable/reference/expressions/name.html). @@ -842,7 +843,7 @@ print(df.group_by('country').map_groups(calculate_percentage_change)) ## Trier les valeurs -Le tri des données est particulièrement utile pour l'exploration et la visualisation de données. Avec Polars, on utilise la méthode [sort()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.sort.html#polars.DataFrame.sort) pour trier les valeurs d'un DataFrame selon une ou plusieurs colonnes. +Le tri des données est particulièrement utile pour l'exploration et la visualisation de données. Avec `polars`, on utilise la méthode [sort()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.sort.html#polars.DataFrame.sort) pour trier les valeurs d'un DataFrame selon une ou plusieurs colonnes. ```{python} df = pl.DataFrame( @@ -895,7 +896,7 @@ df.head() ### L'opération `group_by` -La méthode `group_by` de Polars permet de diviser le DataFrame en sous-ensembles selon les valeurs d'une ou plusieurs colonnes, puis d'appliquer une fonction d'agrégation à chaque sous-ensemble. Elle renvoie un objet de type `dataframe.group_by` qui ne présente pas de grand intérêt en soi, mais constitue l'étape intermédiaire indispensable pour pouvoir ensuite appliquer une ou plusieurs fonction(s) d'agrégation aux différents groupes. +La méthode `group_by` de `polars` permet de diviser le DataFrame en sous-ensembles selon les valeurs d'une ou plusieurs colonnes, puis d'appliquer une fonction d'agrégation à chaque sous-ensemble. Elle renvoie un objet de type `dataframe.group_by` qui ne présente pas de grand intérêt en soi, mais constitue l'étape intermédiaire indispensable pour pouvoir ensuite appliquer une ou plusieurs fonction(s) d'agrégation aux différents groupes. ```{python} df.group_by('experiment') @@ -903,12 +904,12 @@ df.group_by('experiment') ### Fonctions d'agrégation -Une fois les données groupées, on peut appliquer des fonctions d'agrégation pour obtenir un résumé statistique. Polars intègre un certain nombre de ces fonctions qui fonctionnent sur la table de donnée entière, *cf.* [liste complète dans la documentation](https://docs.pola.rs/api/python/stable/reference/dataframe/aggregation.html) ou sur des sous-ensembles de la table, en utilisant `group_by`, *cf.* [liste complète dans la documentation](https://docs.pola.rs/api/python/stable/reference/dataframe/group_by.html). +Une fois les données groupées, on peut appliquer des fonctions d'agrégation pour obtenir un résumé statistique. `polars` intègre un certain nombre de ces fonctions qui fonctionnent sur la table de donnée entière, *cf.* [liste complète dans la documentation](https://docs.pola.rs/api/python/stable/reference/dataframe/aggregation.html) ou sur des sous-ensembles de la table, en utilisant `group_by`, *cf.* [liste complète dans la documentation](https://docs.pola.rs/api/python/stable/reference/dataframe/group_by.html). Voici quelques exemples d'utilisation de ces méthodes avec `group_by`. -Par défaut, Polars appliquera les fonctions usuelles à l'ensemble des colonnes. +Par défaut, `polars` appliquera les fonctions usuelles à l'ensemble des colonnes. Pour spécifier une colonne, il faut utiliser la fonction `agg`, détaillée plus bas. - Par exemple, compter le nombre d'occurrences dans chaque groupe. @@ -957,13 +958,13 @@ df.group_by('experiment').agg( ``` ::: {.callout-tip} -Au lieu d'utiliser la méthode alias, on peut utiliser l'attribut `name` de Polars qui renvoie le nom de la colonne et les fonctions associées. Plus de détails sont présentés dans la [documentation officielle](https://docs.pola.rs/api/python/stable/reference/expressions/name.html). +Au lieu d'utiliser la méthode alias, on peut utiliser l'attribut `name` de `polars` qui renvoie le nom de la colonne et les fonctions associées. Plus de détails sont présentés dans la [documentation officielle](https://docs.pola.rs/api/python/stable/reference/expressions/name.html). Par exemple, définir `.alias('mean_var1')` est l'équivalent de `.name.prefix('mean_')` ::: ::: {.callout-note title="Le chaînage de méthodes"} -Les exemples précédents illustrent un concept important en Polars : le chaînage de méthodes. Ce terme désigne la possibilité d'enchaîner les transformations appliquées à un DataFrame en lui appliquant à la chaîne des méthodes, comme le `pipe` du tidyverse. A chaque méthode appliquée, un DataFrame intermédiaire est créé (mais non assigné à une variable), qui devient l'input de la méthode suivante. +Les exemples précédents illustrent un concept important en `polars` : le chaînage de méthodes. Ce terme désigne la possibilité d'enchaîner les transformations appliquées à un DataFrame en lui appliquant à la chaîne des méthodes, comme le `pipe` du tidyverse. A chaque méthode appliquée, un DataFrame intermédiaire est créé (mais non assigné à une variable), qui devient l'input de la méthode suivante. Le chaînage de méthodes permet de combiner plusieurs opérations en une seule expression de code. Cela peut améliorer l'efficacité en évitant les assignations intermédiaires et en rendant le code plus fluide et plus facile à lire. Cela favorise également un style de programmation fonctionnel où les données passent à travers une chaîne de transformations de manière fluide. @@ -981,18 +982,18 @@ subset_df = ( ## Traiter les valeurs manquantes -Les valeurs manquantes sont une réalité courante dans le traitement des données réelles et peuvent survenir pour diverses raisons, telles que des non-réponses à un questionnaire, des erreurs de saisie, des pertes de données lors de la transmission ou simplement parce que l'information n'est pas applicable. Pandas offre plusieurs outils pour gérer les valeurs manquantes. +Les valeurs manquantes sont une réalité courante dans le traitement des données réelles et peuvent survenir pour diverses raisons, telles que des non-réponses à un questionnaire, des erreurs de saisie, des pertes de données lors de la transmission ou simplement parce que l'information n'est pas applicable. `pandas` offre plusieurs outils pour gérer les valeurs manquantes. ### Représentation des valeurs manquantes On peut tout d'abord traiter les valeurs manquantes avec les méthodes associées. -Pour rappel, en Polars, les valeurs `NaN` et `null` sont différentes, alors qu'en Pandas elles sont traitées de manière similaire. +Pour rappel, en `polars`, les valeurs `NaN` et `null` sont différentes, alors qu'en `pandas` elles sont traitées de manière similaire. | | **Type `null`** | **Type `NaN`** | |--|--|--| -| **Signification** | Seule `Null` est considéré par défaut comme une valeur manquante et est l'unique type de valeur manquante dans Polars (que le type original soit temporel, numérique, un charactère ...). | `NaN` représente à l'inverse des valeurs numériques erronées, comme le résultat d'une division par 0. | -| **Comment les créer ?** | Les valeurs manquantes peuvent être crées simplement avec `None`. | Pour créer une valeur `NaN`, valable uniquement pour les types numériques, on peut utiliser `np.nan` de NumPy ou `float("nan")` de Polars. | -| Comportement dans Polars | Ces valeurs sont en général **ignorées**. | Ces valeurs **se propagent**. | +| **Signification** | Seule `Null` est considéré par défaut comme une valeur manquante et est l'unique type de valeur manquante dans `polars` (que le type original soit temporel, numérique, un charactère ...). | `NaN` représente à l'inverse des valeurs numériques erronées, comme le résultat d'une division par 0. | +| **Comment les créer ?** | Les valeurs manquantes peuvent être crées simplement avec `None`. | Pour créer une valeur `NaN`, valable uniquement pour les types numériques, on peut utiliser `np.nan` de NumPy ou `float("nan")` de `polars`. | +| Comportement dans `polars` | Ces valeurs sont en général **ignorées**. | Ces valeurs **se propagent**. | Vérifions cette propriété. @@ -1022,7 +1023,7 @@ print(df.drop_nulls()) ### Calculs sur des colonnes contenant des valeurs manquantes -Lors de calculs statistiques, les valeurs nulles sont généralement ignorées en Polars. Par exemple, la méthode `.mean()` calcule la moyenne des valeurs non manquantes. +Lors de calculs statistiques, les valeurs nulles sont généralement ignorées en `polars`. Par exemple, la méthode `.mean()` calcule la moyenne des valeurs non manquantes. ```{python} df['var1'].mean() @@ -1070,13 +1071,13 @@ df.fill_null(value="MISSING") En pratique, cette façon de faire n'est pas recommandée. Il est en effet préférable de conserver la convention standard de `Polars` (l'utilisation des `null`), d'abord pour des questions de standardisation des pratiques qui facilitent la lecture et la maintenance du code, mais également parce que la convention standard est optimisée pour la performance et les calculs à partir de données contenant des valeurs manquantes. ::: -La méthide `fill_null()` de Polars propose 4 méthodes pré-définies pour remplacer les valeurs manquantes par l'argument `strategy`: +La méthide `fill_null()` de `polars` propose 4 méthodes pré-définies pour remplacer les valeurs manquantes par l'argument `strategy`: - toute valeur constante indiquée (`strategy=None`, argument par défaut); - soit des 0, soit des 1 (`strategy="zero"`, `strategy="one"` :); - en reportant la valeur précédente (`strategy=‘forward’`) ou la valeur suivante (`strategy=‘backward’`) de la colonne ; - en indiquant le minimum, le maximum ou la médiane de la colonne (`strategy=‘min’`, `strategy=‘max’`, `strategy=‘mean’`). -Si l'on veut remplacer uniquement les valeurs manquantantes d'une colonne en Polars, il est plus utile d'utiliser la méthode `with_columns()` en utilisant l'agilité des sélecteurs de Polars. +Si l'on veut remplacer uniquement les valeurs manquantantes d'une colonne en `polars`, il est plus utile d'utiliser la méthode `with_columns()` en utilisant l'agilité des sélecteurs de `polars`. ```{python} df.with_columns( @@ -1097,7 +1098,7 @@ De manière similaire, la méthode `fill_nan()` permet de remplacer les valeurs Les données textuelles nécessitent souvent un nettoyage et une préparation avant l'analyse. Polars fournit via la librairie de méthodes `str` un ensemble d'opérations vectorisées qui rendent la préparation des données textuelles à la fois simple et très efficace. -La méthode `str` s'applique aux séries Polars. +La méthode `str` s'applique aux séries `polars`. Là encore, les possibilités sont multiples et détaillées dans la [documentation](https://docs.pola.rs/api/python/stable/reference/series/string.html). Nous présentons ici les méthodes les plus fréquemment utilisées dans l'analyse de données. @@ -1143,7 +1144,7 @@ C'est l'occasion d'introduire la famille de méthode `strip` (`.str.strip_chars( ::: {.callout-note} Remarquez la présence de deux `with_columns()` et non d'un seul. -C'est parce que Polars étant optimisé, il effectue les opérations sur `with_columns` en parallèle. +C'est parce que `polars` étant optimisé, il effectue les opérations sur `with_columns` en parallèle. Ainsi, si l'on ne le fait pas de manière séquentielle, il ne prend pas en compte le fait qu'on enlève les espace superflus dans 'sample' à la première ligne avant d'en extraire le dernier caractère. ::: @@ -1166,9 +1167,9 @@ df.with_columns( ## Données catégorielles Les données catégorielles sont des variables qui contiennent un nombre restreint de modalités. -A l'instar de `R` avec la notion de `factor`, Polars a un type de données spécial, `Categorical`, qui peut être utilisé pour représenter des données catégorielles. +A l'instar de `R` avec la notion de `factor`, `polars` a un type de données spécial, `Categorical`, qui peut être utilisé pour représenter des données catégorielles. -Ce type de données est cependant délicat à gérer en Polars et, en général, on préfèrera travailler avec des données de type caractère. +Ce type de données est cependant délicat à gérer en `polars` et, en général, on préfèrera travailler avec des données de type caractère. En effet, les méthodes usuelles pour renommer des catégories, dissocier son nom et sa représentation, réarranger l'ordre dans laquelle les catégories sont visualisées sont encore très largement perfectibles (voire inexistantes :o). @@ -1219,8 +1220,8 @@ df = pl.DataFrame( df.dtypes ``` -Pour manipuler les données temporelles, il est nécessaire de convertir les chaînes de caractères en colonne de type temporel sous Polars. -Il existe 4 types temporels de colonnes en Polars, comme rappelé dans la [documentation](https://docs.pola.rs/api/python/stable/reference/datatypes.html): +Pour manipuler les données temporelles, il est nécessaire de convertir les chaînes de caractères en colonne de type temporel sous `polars`. +Il existe 4 types temporels de colonnes en `polars`, comme rappelé dans la [documentation](https://docs.pola.rs/api/python/stable/reference/datatypes.html): - le type [`pl.Datetime`](https://docs.pola.rs/api/python/stable/reference/api/polars.datatypes.Date.html#polars.datatypes.Datetime) pour un format date et heure ; - le type [`pl.Date`](https://docs.pola.rs/api/python/stable/reference/api/polars.datatypes.Date.html#polars.datatypes.Date) pour un format Date seul ; @@ -1240,7 +1241,7 @@ df.dtypes Une fois converties, les dates peuvent être formatées, comparées et utilisées dans des calculs. Il faudra cependant bien penser à traduire les dates d'un format textuel à un format temporel. -Par exemple, pour filtrer des données, on devra spécifier les bornes en appelant les fonctions dédiées de Polars ou du module `datetime`. +Par exemple, pour filtrer des données, on devra spécifier les bornes en appelant les fonctions dédiées de `polars` ou du module `datetime`. ```{python} df.filter(pl.col('date') >= pl.date(2022, 1, 1), pl.col('date') < pl.date(2022, 1, 3)) @@ -1294,7 +1295,7 @@ La combinaison peut également se faire horizontalement (côte à côte) selon u ## Concaténer des tables -La concaténation verticale de tables se fait à l'aide de la fonction [`concat()`](https://docs.pola.rs/api/python/stable/reference/api/polars.concat.html#polars.concat) de Polars. +La concaténation verticale de tables se fait à l'aide de la fonction [`concat()`](https://docs.pola.rs/api/python/stable/reference/api/polars.concat.html#polars.concat) de `polars`. ```{python} @@ -1320,7 +1321,7 @@ pl.concat([df1, df2]) ``` -A la grande différence de `Pandas`, **l'ordre des variables dans les deux DataFrames importe**. +A la grande différence de `pandas`, **l'ordre des variables dans les deux DataFrames importe**. Ainsi, le même code avec `df2` défini comme ci-après va renvoyer une erreur. ```{python} @@ -1350,10 +1351,10 @@ Différents types de jointure sont possible selon les données que l'on souhaite Source : [lien](https://medium.com/swlh/merging-dataframes-with-pandas-pd-merge-7764c7e2d46d) -En Polars, les jointures se font avec la fonction [`join()`](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.join.html#polars.DataFrame.join). +En `polars`, les jointures se font avec la fonction [`join()`](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.join.html#polars.DataFrame.join). Pour réaliser une jointure, on doit spécifier (au minimum) deux informations : -- le type de jointure : par défaut, Polars effectue une jointure de type `inner`. +- le type de jointure : par défaut, `polars` effectue une jointure de type `inner`. Le paramètre `how` permet de spécifier d'autres types de jointure ; - la clé de jointure. @@ -1428,19 +1429,19 @@ df_a.join(df_b, how="full", on='key', coalesce=True) ## Questions de compréhension -- 1/ Qu'est-ce qu'un DataFrame dans le contexte de Polars et à quel type de structure de données peut-on le comparer dans le langage Python ? +- 1/ Qu'est-ce qu'un DataFrame dans le contexte de `polars` et à quel type de structure de données peut-on le comparer dans le langage Python ? -- 2/ Quels sont les avantages de Polars ? +- 2/ Quels sont les avantages de `polars` ? -- 3/ Quel est le lien entre Series et DataFrame dans Polars ? +- 3/ Quel est le lien entre Series et DataFrame dans `polars` ? -- 4/ Comment sont structurées les données dans un DataFrame Polars ? +- 4/ Comment sont structurées les données dans un DataFrame `polars` ? - 6/ Quelles méthodes pouvez-vous utiliser pour explorer un DataFrame inconnu et en apprendre davantage sur son contenu et sa structure ? -- 8/ Comment s'applique le principe d'évaluation paresseuse dans Polars et pourquoi est-ce avantageux pour manipuler les données ? +- 8/ Comment s'applique le principe d'évaluation paresseuse dans `polars` et pourquoi est-ce avantageux pour manipuler les données ? -- 9/ Comment Polars représente-t-il les valeurs manquantes et quel impact cela a-t-il sur les calculs et les transformations de données ? +- 9/ Comment `polars` représente-t-il les valeurs manquantes et quel impact cela a-t-il sur les calculs et les transformations de données ? - 10/ Quelle est la différence entre concaténer deux DataFrames et les joindre via une jointure, et quand utiliseriez-vous l'une plutôt que l'autre ? @@ -1450,21 +1451,21 @@ df_a.join(df_b, how="full", on='key', coalesce=True)
Afficher la solution -- 1/ Un DataFrame dans Pandas est une structure de données bidimensionnelle, comparable à un tableau ou une feuille de calcul Excel. Dans le contexte Python, on peut le comparer à un dictionnaire d'arrays NumPy, où les clés sont les noms des colonnes et les valeurs sont les colonnes elles-mêmes. +- 1/ Un DataFrame dans `pandas` est une structure de données bidimensionnelle, comparable à un tableau ou une feuille de calcul Excel. Dans le contexte Python, on peut le comparer à un dictionnaire d'arrays NumPy, où les clés sont les noms des colonnes et les valeurs sont les colonnes elles-mêmes. -- 2/ La différence principale entre un array NumPy et une Series Pandas est que la Series peut contenir des données étiquetées, c'est-à-dire qu'elle a un index qui lui est associé, permettant des accès et des manipulations par label. +- 2/ La différence principale entre un array NumPy et une Series `pandas` est que la Series peut contenir des données étiquetées, c'est-à-dire qu'elle a un index qui lui est associé, permettant des accès et des manipulations par label. - 3/ Un DataFrame est essentiellement une collection de Series. Chaque colonne d'un DataFrame est une Series, et toutes ces Series partagent le même index, qui correspond aux étiquettes des lignes du DataFrame. -- 4/ Les données dans un DataFrame Pandas sont structurées en colonnes et en lignes. Chaque colonne peut contenir un type de données différent (numérique, chaîne de caractères, booléen, etc.), et chaque ligne représente une observation. +- 4/ Les données dans un DataFrame `pandas` sont structurées en colonnes et en lignes. Chaque colonne peut contenir un type de données différent (numérique, chaîne de caractères, booléen, etc.), et chaque ligne représente une observation. -- 5/ L'index dans un DataFrame Pandas sert à identifier de manière unique chaque ligne du DataFrame. Il permet d'accéder rapidement aux lignes, de réaliser des jointures, de trier les données et de faciliter les opérations de regroupement. +- 5/ L'index dans un DataFrame `pandas` sert à identifier de manière unique chaque ligne du DataFrame. Il permet d'accéder rapidement aux lignes, de réaliser des jointures, de trier les données et de faciliter les opérations de regroupement. - 6/ Pour explorer un DataFrame inconnu, on peut utiliser df.head() pour voir les premières lignes, df.tail() pour les dernières, df.info() pour obtenir un résumé des types de données et des valeurs manquantes, et df.describe() pour des statistiques descriptives. - 7/ Assigner le résultat d'une opération à une nouvelle variable crée une copie du DataFrame avec les modifications appliquées. Utiliser une méthode avec inplace=True modifie le DataFrame original sans créer de copie, ce qui peut être plus efficace en termes de mémoire. -- 8/ Pandas représente les valeurs manquantes avec l'objet `nan` (Not a Number) de `Numpy` pour les données numériques et avec None ou pd.NaT pour les dates/temps. Ces valeurs manquantes sont généralement ignorées dans les calculs de fonctions statistiques, ce qui peut affecter les résultats si elles ne sont pas traitées correctement. +- 8/ `pandas` représente les valeurs manquantes avec l'objet `nan` (Not a Number) de `Numpy` pour les données numériques et avec None ou pd.NaT pour les dates/temps. Ces valeurs manquantes sont généralement ignorées dans les calculs de fonctions statistiques, ce qui peut affecter les résultats si elles ne sont pas traitées correctement. - 9/ Concaténer consiste à assembler des DataFrames en les empilant verticalement ou en les alignant horizontalement, principalement utilisé lorsque les DataFrames ont le même schéma ou lorsque vous souhaitez empiler les données. Les jointures, inspirées des opérations JOIN en SQL, combinent les DataFrames sur la base de valeurs de clés communes et sont utilisées pour enrichir un ensemble de données avec des informations d'un autre ensemble. @@ -1547,7 +1548,7 @@ df_from_dict.equals(df_from_list) ## Sélection de données dans un DataFrame -Un DataFrame Polars est créé avec des données de caisse (mêmes données que l'exercice précédent). +Un DataFrame `polars` est créé avec des données de caisse (mêmes données que l'exercice précédent). ```{python} data = { @@ -2086,7 +2087,7 @@ L'objectif de cet exercice est de calculer une empreinte carbone par habitant au - les émissions de gaz à effet de serre estimées au niveau communal par l’ADEME ([source](https://www.data.gouv.fr/fr/datasets/inventaire-de-gaz-a-effet-de-serre-territorialise/#_)) -Cet exercice constitue une version simplifiée d'un [TP complet pour la pratique de Pandas](https://pythonds.linogaliana.fr/content/manipulation/02b_pandas_TP.html#importer-les-donn%C3%A9es) proposé par Lino Galiana dans son [cours à l'ENSAE](https://pythonds.linogaliana.fr/) et traduit en Polars. +Cet exercice constitue une version simplifiée d'un [TP complet pour la pratique de `pandas`](https://pythonds.linogaliana.fr/content/manipulation/02b_pandas_TP.html#importer-les-donn%C3%A9es) proposé par Lino Galiana dans son [cours à l'ENSAE](https://pythonds.linogaliana.fr/) et traduit en `polars`. ### Partie 1 : Exploration des données sur les populations légales communales From 7103b7f96df25b67d8ca562934c2bfb7b969fcd6 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 25 Feb 2026 14:02:55 +0000 Subject: [PATCH 52/92] with correction questions --- source/manipulation/polars/tutorial.qmd | 58 +++++++++++++++++++------ 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 7d16a961..0027511c 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -1437,13 +1437,13 @@ df_a.join(df_b, how="full", on='key', coalesce=True) - 4/ Comment sont structurées les données dans un DataFrame `polars` ? -- 6/ Quelles méthodes pouvez-vous utiliser pour explorer un DataFrame inconnu et en apprendre davantage sur son contenu et sa structure ? +- 5/ Quelles méthodes pouvez-vous utiliser pour explorer un DataFrame inconnu et en apprendre davantage sur son contenu et sa structure ? -- 8/ Comment s'applique le principe d'évaluation paresseuse dans `polars` et pourquoi est-ce avantageux pour manipuler les données ? +- 6/ Comment s'applique le principe d'évaluation paresseuse dans `polars` et pourquoi est-ce avantageux pour manipuler les données ? -- 9/ Comment `polars` représente-t-il les valeurs manquantes et quel impact cela a-t-il sur les calculs et les transformations de données ? +- 7/ Comment `polars` représente-t-il les valeurs manquantes et quel impact cela a-t-il sur les calculs et les transformations de données ? -- 10/ Quelle est la différence entre concaténer deux DataFrames et les joindre via une jointure, et quand utiliseriez-vous l'une plutôt que l'autre ? +- 8/ Quelle est la différence entre concaténer deux DataFrames et les joindre via une jointure, et quand utiliseriez-vous l'une plutôt que l'autre ? ::: {.cell .markdown} @@ -1451,23 +1451,55 @@ df_a.join(df_b, how="full", on='key', coalesce=True)
Afficher la solution -- 1/ Un DataFrame dans `pandas` est une structure de données bidimensionnelle, comparable à un tableau ou une feuille de calcul Excel. Dans le contexte Python, on peut le comparer à un dictionnaire d'arrays NumPy, où les clés sont les noms des colonnes et les valeurs sont les colonnes elles-mêmes. +- 1/ Un DataFrame dans `polars` est une **structure de données tabulaire bidimensionnelle**, optimisée pour la performance et la manipulation de données volumineuses. Contrairement à pandas, il n’utilise pas d’index nommé par défaut. +On peut le comparer à un **dictionnaire de listes ou d’arrays NumPy**, où chaque clé du dictionnaire représente une colonne, et les valeurs sont les données de cette colonne. Polars utilise des Series pour représenter chaque colonne, mais contrairement à pandas, ces Series ne partagent pas d’index global. -- 2/ La différence principale entre un array NumPy et une Series `pandas` est que la Series peut contenir des données étiquetées, c'est-à-dire qu'elle a un index qui lui est associé, permettant des accès et des manipulations par label. +- 2/ Les avantages de `polars` sont globalement : + - **Rapidité** : Polars est optimisé pour traiter des données volumineuses, souvent plus rapidement que pandas, grâce à son implémentation en Rust et son utilisation de la parallélisation. + - **Évaluation paresseuse (lazy evaluation)** : Permet d’optimiser les requêtes avant leur exécution, améliorant les performances sur les gros jeux de données. + - **Streaming** : Capacité à traiter des données qui ne tiennent pas en mémoire (out-of-memory). + - **API expressive** : Syntaxe claire et intuitive, inspirée de SQL et du tidyverse (R). + - **Pas d’index** : Contrairement à pandas, Polars n’utilise pas d’index, ce qui simplifie les opérations et améliore les performances. + - **Gestion des types stricte **: Polars est très strict sur les types de données, ce qui réduit les erreurs et améliore la robustesse. + - **Sélecteurs avancés** : Permet de sélectionner des colonnes par nom, type ou motif (regex). -- 3/ Un DataFrame est essentiellement une collection de Series. Chaque colonne d'un DataFrame est une Series, et toutes ces Series partagent le même index, qui correspond aux étiquettes des lignes du DataFrame. -- 4/ Les données dans un DataFrame `pandas` sont structurées en colonnes et en lignes. Chaque colonne peut contenir un type de données différent (numérique, chaîne de caractères, booléen, etc.), et chaque ligne représente une observation. +- 3/ Un DataFrame est une **collection de Series**, où chaque Series représente une colonne. Contrairement à `pandas`, les Series de `polars` ne partagent pas d’index global. Chaque Series est indépendante et peut être manipulée individuellement. +Un DataFrame est donc une table composée de colonnes (Series) alignées par leur position (et non par un index). -- 5/ L'index dans un DataFrame `pandas` sert à identifier de manière unique chaque ligne du DataFrame. Il permet d'accéder rapidement aux lignes, de réaliser des jointures, de trier les données et de faciliter les opérations de regroupement. +- 4/ Les données sont organisées en **colonnes (Series) et en lignes (observations)**. + - Chaque colonne est une Series avec un type de données homogène (ex : pl.Int64, pl.String, pl.Date). + - Les lignes n’ont pas d’index nommé par défaut, mais peuvent être référencées par leur position. + - Les colonnes peuvent être de types différents (numériques, chaînes, dates, etc.). -- 6/ Pour explorer un DataFrame inconnu, on peut utiliser df.head() pour voir les premières lignes, df.tail() pour les dernières, df.info() pour obtenir un résumé des types de données et des valeurs manquantes, et df.describe() pour des statistiques descriptives. -- 7/ Assigner le résultat d'une opération à une nouvelle variable crée une copie du DataFrame avec les modifications appliquées. Utiliser une méthode avec inplace=True modifie le DataFrame original sans créer de copie, ce qui peut être plus efficace en termes de mémoire. +- 5/ Pour explorer un DataFrame inconnu, on peut utiliser : + - df.head(n) : Affiche les n premières lignes. + - df.tail(n) : Affiche les n dernières lignes. + - df.sample(n) : Affiche un échantillon aléatoire de n lignes. + - df.glimpse() : Affiche un résumé du schéma (noms des colonnes, types de données) et les premières - valeurs. + - df.describe() : Fournit des statistiques descriptives (moyenne, écart-type, valeurs min/max, etc.) - pour chaque colonne. + - df.schema : Affiche les types de données de chaque colonne. + - df.shape : Retourne le nombre de lignes et de colonnes. + - df.columns : Liste les noms des colonnes. -- 8/ `pandas` représente les valeurs manquantes avec l'objet `nan` (Not a Number) de `Numpy` pour les données numériques et avec None ou pd.NaT pour les dates/temps. Ces valeurs manquantes sont généralement ignorées dans les calculs de fonctions statistiques, ce qui peut affecter les résultats si elles ne sont pas traitées correctement. +- 6/ L’évaluation paresseuse (lazy evaluation) permet de **planifier une série d’opérations** (filtres, agrégations, jointures) sans les exécuter immédiatement. Polars optimise alors le plan d’exécution (par exemple, en appliquant les filtres avant les agrégations) avant de charger ou transformer les données. +Cela permet notamment de réduire la consommation mémoire, d'augmenter le temps d'exécution et d'optimiser +le traitement de requêtes complexes. + + +- 7/ `polars` distingue **deux types de valeurs manquantes** : + - null : Valeur manquante générique (pour tous les types de données). + - NaN : Valeur manquante spécifique aux données numériques (équivalent à np.nan). +Les valeurs null et NaN sont ignorées par défaut dans les calculs statistiques (moyenne, somme, etc.). +Les opérations logiques (filter, is_in, etc.) traitent null comme une valeur inconnue (ex : null == null retourne null, pas True). +Les méthodes comme .drop_nulls() ou .fill_null() permettent de gérer explicitement ces valeurs. + +- 8/ La différence entre concaténer et joindre deux tables est : + - **Concaténer**, avec `pl.concat`, permet d'empiler deux DataFrames verticalement (ajoute des lignes) ou horizontalement (ajoute des colonnes). On l'utilise lorsque les DataFrames ont la même structure (mêmes colonnes pour un empilement vertical, mêmes lignes pour un empilement horizontal). + - La **jointure**, avec `df.join()`, permet de **combiner deux DataFrames sur une clé commune** (comme une opération SQL JOIN). Elle est utilisée pour enrichir un DataFrame avec des données d’un autre, en fonction de valeurs partagées (ex : df1.join(df2, on="id", how="inner")). Il existe quatre types principaux de jointures : inner, left, outer, cross. + - On **préfère** concaténer pour fusionner des données de même structure (ex : ajouter des observations supplémentaires) et joindre deux tables pour combiner des données liées par une clé (ex : lier des tables "clients" et "commandes"). -- 9/ Concaténer consiste à assembler des DataFrames en les empilant verticalement ou en les alignant horizontalement, principalement utilisé lorsque les DataFrames ont le même schéma ou lorsque vous souhaitez empiler les données. Les jointures, inspirées des opérations JOIN en SQL, combinent les DataFrames sur la base de valeurs de clés communes et sont utilisées pour enrichir un ensemble de données avec des informations d'un autre ensemble.
From 52a7765fa7065ea402dcf2f76250cc2f528f6bb5 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 25 Feb 2026 15:33:56 +0000 Subject: [PATCH 53/92] review and harmonization --- source/manipulation/polars/tutorial.qmd | 568 ++++++++++++------------ 1 file changed, 291 insertions(+), 277 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 0027511c..e2d31c76 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -1,55 +1,56 @@ ::: {.content-visible when-profile="fr"} -# Introduction - traiter des données tabulaires avec `polars` +# Introduction - traiter des données tabulaires avec polars L'analyse statistique a généralement pour base des **données tabulaires**, dans lesquelles chaque ligne représente une observation et chaque colonne une variable. Pour traiter ce type de données et y appliquer facilement les méthodes d'analyse de données standards, des objets dédiés ont été conçus : les `DataFrames`. Les utilisateurs de `R` connaissent bien cette structure de données, qui est native à ce langage orienté statistique. En `Python`, langage généraliste, cet objet n'existe pas nativement. -Plusieurs packages viennent ainsi combler ce manque, comme `pandas` ou `polars`. +Plusieurs packages viennent ainsi combler ce manque, comme pandas ou polars. -## Pourquoi `polars`? +## Pourquoi polars? Comment choisir entre les deux ? Cela va dépendre de vos goûts et de vos besoins. -Mais voici en attendant quelques éléments pour savoir si `polars` est utile. +Mais voici en attendant quelques éléments pour savoir si polars est utile. -Du côté des atouts de `polars` : +Du côté des atouts de polars : -- `polars` est **rapide** et permet de traiter des **données volumineuses** : Selon un benchmark [effectué par H2O](https://h2oai.github.io/db-benchmark/), -Polars permet de traiter des données que d'autres librairies ne pourraient pas () +- polars est **rapide** et permet de traiter des **données volumineuses** : Selon un benchmark [effectué par H2O](https://h2oai.github.io/db-benchmark/), +Polars permet de traiter des données que d'autres librairies ne pourraient pas et les traite aussi rapidement que le package `R` `data.table`. et 3 à 4 fois plus vite que d'autres librairies. -- `polars` permet même de traiter des **données _out of memory_ :** `Polars` présente aussi l'avantage +- polars permet même de traiter des **données _out of memory_ :** polars présente aussi l'avantage de lire naturellement des jeux de données hors des limites de la mémoire de l'ordinateur grâce à [sa capacité de lire en flux](https://www.youtube.com/watch?v=3-C0Afs5TXQ) (méthode qu'on appelle le _streaming_). -- `polars` permet une **évaluation paresseuse** (*lazy evaluation*) : ce mode de calcul +- polars permet une **évaluation paresseuse** (*lazy evaluation*) : ce mode de calcul permet d'optimiser vos traitements pour proposer une exécution plus rapide (pour la lecture comme pour la transformation des jeux de données). Elle peut permettre d'avancer un `select` ou un `filter` si les opérations ultérieures ne sont pas impactées. Ces optimisations sont détaillées dans la [documentation officielle](https://pola-rs.github.io/polars-book/user-guide/optimizations/intro.html). -- Une **API fluide** : L'API proposée par `polars` est à la fois expressive et transparente. Ceci répond notamment aux commentaires sur `pandas`, où la syntaxe de manipulations des données est parfois complexe ou peu lisible et les choix d'écriture ne sont pas transparents du point de vue des performances. +- Une **API fluide** : L'API proposée par polars est à la fois expressive et transparente. Ceci répond notamment aux commentaires sur pandas, où la syntaxe de manipulations des données est parfois complexe ou peu lisible et les choix d'écriture ne sont pas transparents du point de vue des performances. - Un **pipe natif** : On retrouve une sémantique d'opérations de haut niveau qui s'enchaînent à la manière de [ce que l'on peut faire en `dplyr`](https://www.book.utilitr.org/03_fiches_thematiques/fiche_tidyverse#comment-utiliser-lop%C3%A9rateur-pipe-avec-le-tidyverse). Polars présente quand même aussi quelques **inconvénients**, notamment lié à sa plus grande jeunesse. +Ces inconvénients restent relativement marginaux et l'avenir semble quand même plutôt souffler dans le sens de polars. -- ainsi, le **traitement de données catégorielles** est encore instable, notamment en comparaison à `pandas` et au tidyverse. -Dans `polars` pour contourner ces problèmes, on a tendance à traiter ces variable catégorielles comme des caractères. +- ainsi, le **traitement de données catégorielles** est encore instable, notamment en comparaison à pandas et au tidyverse. +Dans polars pour contourner ces problèmes, on a tendance à traiter ces variable catégorielles comme des caractères. -- **Pas (encore) de `geopolars`** : Tout l'écosystème autour de `pandas` n'a ainsi pas forcément (encore) d'équivalent en `polars`. -Pour les données géolocalisées par exemple, geopolars n'existe pas encore. +- **Pas (encore) de `geopolars`** : Tout l'écosystème autour de pandas n'a ainsi pas forcément (encore) d'équivalent en polars. +Pour les données géolocalisées par exemple, [geopolars](https://github.com/pola-rs/geopolars) est en développement. -- plus généralement, **`Polars` reste moins répandu que `pandas`** : `polars` étant plus récent, il est en général moins bien interfacé avec les autres -librairies de data science, même si certaines commencent à accepter des données -`polars` en entrée. -La rapidité et simplicité de `polars` permet cependant facilement de repasser à un -dataframe `pandas` pour les librairies qui n'accepteraient pas encore de dataframe +- plus généralement, **polars reste moins répandu que pandas** : polars étant plus récent, il est en général moins bien interfacé avec les autres +librairies de data science, même si un certain nombre commence à accepter des données +polars en entrée. +Polars permet cependant facilement de repasser à un +dataframe pandas pour les librairies qui n'accepteraient pas encore de dataframe polars en entrée. ## Petits conseils pour commencer -Avant de commencer à utiliser `polars`, voici quelques conseils à garder en tête : +Avant de commencer à utiliser polars, voici quelques conseils à garder en tête : - L'import de données est **plus délicat** : Polars est très strict sur les types des colonnes quand on importe des données. @@ -57,12 +58,7 @@ Il est courant de passer du temps à débugger cette étape, notamment pour s'as que le code soit résistant à de légères variations dans le format des données d'entrée. Pour optimiser ce temps là, on peut spécifier directement les types en entrée. -- Les **chaines de caractères sont par défaut associées à des colonnes** : -En `polars`, les caractères simples `"myvar"` sont par défaut considéré comme des noms de -colonne. Il faut penser à utiliser `pl.lit("myvar")` pour signaler qu'il ne s'agit -pas d'un nom de colonne. - -- **l'index de `pandas`** est mort <3 : comme dans le tidyverse, `polars` +- **l'index de pandas** est mort <3 : comme dans le tidyverse, polars n'utilise pas d'index, et c'est très bien comme cela ! - les `polars selectors` sont très pratiques pour sélectionner des colonnes. @@ -70,79 +66,76 @@ Ils permettent de sélectionner des colonnes avec des regex sur leurs noms ou bi en fonction de leur type de données. Plus d'exemples sont disponibles dans la [documentation officielle](https://docs.pola.rs/api/python/stable/reference/selectors.html). +- Les **chaines de caractères sont par défaut associées à des colonnes** : +En polars, les caractères simples `"myvar"` sont par défaut considéré comme des noms de +colonne. Il faut penser à utiliser `pl.lit("myvar")` pour signaler qu'il ne s'agit +pas d'un nom de colonne. + +## Pour aller plus loin + +Voici un ensemble de ressources si vous voulez aller plus loin sur l'écosystème +de polars : + +- [Blog Awesome polars](https://ddotta.github.io/awesome-polars/), par Damien D : une liste de +ressources liées à Polars, que ce soit en R ou en Python ; +- [Blog sur polars sur le site du SSPHub](https://ssphub.netlify.app/post/polars/) : un article de blog +détaille plus précisément certains usages de polars ; +- [Notebook polars](https://datalab.sspcloud.fr/launcher/ide/jupyter-python?version=1.13.22&autoLaunch=true&init.personalInit=%C2%ABhttps%3A%2F%2Fraw.githubusercontent.com%2FInseeFrLab%2Fssphub%2Fmain%2Fpost%2Fpolars%2Finit.sh%C2%BB&init.personalInitArgs=%C2%ABpolars-tuto%C2%BB&onyxia.friendlyName=%C2%ABTutoriel%20Polars%C2%BB) : notebook +lié au post de blog et qui présente polars et ses fonctionnalités, de manière similaire à ce cours. + ## Allons-y ! -On commence par importer la librairie `Polars`. +On commence par importer la librairie polars. L'usage est courant est de lui attribuer l'alias `pl` afin de simplifier les futurs appels aux objets et fonctions du package. ```{python} import polars as pl import polars.selectors as cs +import numpy as np # Numpy reste nécessaire pour certaines fonctionnalités utiles ``` -## pour aller plus loin - -Voici un ensemble de ressources si vous voulez aller plus loin sur l'écosystème -de `polars` : - -- [Blog Awesome `polars`](https://ddotta.github.io/awesome-polars/), par Damien D -- [Blog sur `polars` sur le site du SSPHub](https://ssphub.netlify.app/post/polars/) -- [Notebook `polars`](https://datalab.sspcloud.fr/launcher/ide/jupyter-python?name=Tutoriel%20Polars&version=2.3.28&s3=region-79669f20&init.personalInit=«https%3A%2F%2Fraw.githubusercontent.com%2Fntoulemonde%2Ftest%2Frefs%2Fheads%2Fmain%2Finit.sh»&autoLaunch=true) +::: {.callout-note} -::: {.panel-tabset group="polars_vs_tidypolars" name="Pour commencer"} - -## Polars -```{python} -import polars as pl -import numpy as np -``` +## Tidypolars, pour polars avec une syntaxe du tidyverse -## Tidypolars -Pour celles et ceux qui veulent utiliser des fonctions presqu'identiques à celles du tidyverse, +Pour celles et ceux qui voudraient garder le **confort des chaussons du tidyverse,** il y a le package [tidypolars](https://tidypolars.readthedocs.io/en/latest/). +Il reprend les fonctions de polars et les traduit à ceux du tidyverse pour revenir sur nos les habitudes : -Les noms des fonctions dans tidypolars sont presque tous identiques à ceux du tidyverse: - -- un `DataFrame` de `polars` devient un `tibble` chez tidypolars; +- un dataframe de polars devient un `tibble` chez `tidypolars`; - la structure de la création d'un `tibble` est la même que dans R; -- les méthodes `filter`, `select` de `polars` restent les mêmes; -- la méthode `with_columns` de `polars` devient `mutate` ... +- les méthodes `filter`, `select` de polars restent les mêmes; +- la méthode `with_columns` de polars devient `mutate` ... -Tidypolars reprend ainsi exactement la syntaxe des principales fonctions de dplyr, tidyr, stringr, lubridate, tidyselect directement dans Python! -La liste complète des fonctions reprises est disponible dans la [documentation](https://tidypolars.readthedocs.io/en/latest/reference.html). +`Tidypolars` reprend ainsi exactement la syntaxe des principales fonctions de dplyr, tidyr, stringr, lubridate, tidyselect directement dans Python! -La seule différence notable entre tidypolars et R est liée aux colonnes, qui sont accessibles par `pl.col/tp.col` dans `polars/tidypolars` quand dans R leur nom seul suffit. +La **seule différence notable** entre `tidypolars` et R est liée aux colonnes, qui sont accessibles par `pl.col/tp.col` dans `polars/tidypolars` quand dans R leur nom seul suffit. -Pour la simplicité du tutoriel, le tutoriel présente le début avec tidypolars mais ensuite utilise uniquement `polars`. -Pour plus de détail, allez voir la [documentation](https://tidypolars.readthedocs.io/en/latest/reference.html) ! +Pour la simplicité du tutoriel, le tutoriel utilise uniquement polars. +Mais si vous voulez vous lancer dans `tidypolars`, allez voir leur [documentation](https://tidypolars.readthedocs.io/en/latest/reference.html) ! La liste complète des fonctions reprises y est notamment disponible. -```{python} -import polars as pl -import tidypolars as tp - -from tidypolars import col -``` ::: # C'est parti avec la structure des données -## Le `DataFrame` +## Le dataframe -Fondamentalement, un DataFrame consiste en une collection de Series. Cette concaténation construit donc une table de données, dont les Series correspondent aux colonnes. La figure suivante ([source](https://www.geeksforgeeks.org/creating-a-pandas-dataframe/)) permet de bien comprendre cette structure de données. +Fondamentalement, un dataframe consiste en une **collection de Series**. +Cette concaténation construit donc une table de données, dont les Series correspondent aux colonnes. +La figure suivante ([source](https://www.geeksforgeeks.org/creating-a-pandas-dataframe/)) permet de bien comprendre cette structure de données. ![](../pandas/img/structure_df.png){fig-align="center" width="800"} -Un DataFrame peut être construit de multiples manières. En pratique, on construit généralement un DataFrame directement à partir de fichiers de données tabulaires (ex : CSV, excel), rarement à la main. On illustrera donc seulement la méthode de construction manuelle la plus usuelle : à partir d'un dictionnaire de données. - -::: {.panel-tabset group="polars_vs_tidypolars"} +Un dataframe peut être construit de multiples manières. +En pratique, on construit généralement un dataframe directement à partir de fichiers de données tabulaires (ex : CSV, excel), rarement à la main. +On illustrera donc seulement la méthode de construction manuelle la plus usuelle : à partir d'un dictionnaire de données. -## Polars ```{python} df = pl.DataFrame( @@ -157,27 +150,15 @@ df = pl.DataFrame( df ``` -## Tidypolars -```{python} -df = tp.tibble( - var1 = [1.3, 5.6, None, None, 0, None], - experiment = ["test", "train", "test", "train", "train", "validation"], - date = ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-01-05", "2022-01-06"], - sample = "sample1" -) - -df - -``` - -::: +A noter qu'une valeur manquante est indiquée par `None` en polars. +Elle sera ensuite traduite en type `Null` interne à polars. +## Les attributs d'un dataframe -A noter qu'une valeur manquante est indiquée par `None` en `polars`. Elle sera ensuite traduite en type Null interne à `polars`. - -Un DataFrame `polars` dispose d'un ensemble d'attributs utiles que nous allons découvrir tout au long de ce tutoriel. Pour l'instant, intéressons-nous aux plus basiques : le nom des colonnes. +Un dataframe polars dispose d'un ensemble d'attributs utiles que nous allons découvrir tout au long de ce tutoriel. +Pour l'instant, intéressons-nous aux plus basiques : le **nom des colonnes**. ```{python} df = pl.DataFrame( @@ -193,64 +174,76 @@ df.columns ``` Les principaux autres attributs d'un dataframe sont : -- liés à la taille du data frame : - - le nombre de ligne (df.height) et de colonnes (df.width) - - la forme globale (df.shape), qui reprend le nombre de lignes et de colonnes -- liés aux formats des colonnes: - - le schéma du dataframe (df.schema) - - les formats des colonnes (df.dtypes) + +- liés à la **taille du data frame** : + - le nombre de ligne `df.height` et de colonnes `df.width` ; + - la forme globale `df.shape`, qui reprend le nombre de lignes et de colonnes ; +- liés aux **formats des colonnes**: + - le schéma du dataframe `df.schema` ; + - les formats des colonnes `df.dtypes` (pour *data types*). # Sélectionner des données -Lors de la manipulation des données tabulaires, il est fréquent de vouloir extraire des colonnes spécifiques d'un `DataFrame`. -Cette extraction suit la même logique que le tidyverse avec `Polars`. -La méthode `select` permet de sélectionner sur les colonnes quand `filter` filtre les lignes. +Lors de la manipulation des données tabulaires, il est fréquent de vouloir **extraire des colonnes** spécifiques d'un dataframe. +Cette extraction suit la même logique avec polars qu'avec le tidyverse : +la méthode `select` permet de sélectionner sur les colonnes quand `filter` filtre les lignes. ## Sélectionner des colonnes -Que l'on veuille sélectionner une ou deux colonnes en `Polars`, la logique est similaire. +Que l'on veuille sélectionner une ou deux colonnes en polars, la logique est similaire et retourne un dataframe dans les deux cas. -Pour extraire une seule colonne, on peut utiliser la syntaxe suivante : +### Avec les noms des colonnes +Si l'on connaît les noms des colonnes, pour extraire une seule colonne, on peut utiliser la syntaxe suivante : ```{python} selected_column = df.select("var1") selected_column ``` -L'objet `selected_column` renvoie ici la colonne nommée `var1` du `DataFrame` `df`. -Contrairement à `pandas`, ici on ne garde qu'une seule colonne du dataframe, on ne l'extrait pas. -L'objet `selected_columns` reste donc un dataframe de 1 colonne, et n'est pas une série `polars`. +L'objet `selected_column` renvoie ici la colonne nommée `var1` du dataframe `df`. +Contrairement à pandas, ici on ne garde qu'une seule colonne du dataframe, on ne l'extrait pas. +L'objet `selected_columns` reste donc un dataframe de 1 colonne, et n'est pas une série polars. Si on sélectionnait 2 colonnes, cela serait ainsi aussi un dataframe. +Concrètement, cela veut dire que vous pouvez appliquer à ce **résultat les méthodes d'un dataframe** +et non celles d'une série. + ::: {.callout-tip} -Si vous voulez transformer un dataframe en une série `polars`, il faut utiliser la méthode `to_series()` ou reprendre la syntaxe de `pandas` qui marche aussi en `polars` : + +## Transformer un dataframe en série +Si vous voulez transformer un dataframe en une série polars, il faut utiliser la méthode `to_series()` +ou reprendre la syntaxe de pandas `df["mycol"]` qui renvoie aussi une série polars : ```{python} -print(f'En passant par select.to_series(), la table \n {df.select('var1').to_series()} \n est de type {type(df.select('var1').to_series())}') -print(f'En passant par df[var1], la table \n {df['var1']} \n est aussi de type {type(df['var1'])}') +df.select("var1").to_series() # équivalent +df['var1'] ``` ::: -Pour extraire plusieurs colonnes, il suffit de passer une liste des noms des colonnes souhaitées -ou sans passer par une liste, comme dans le tidyverse. +Pour **extraire plusieurs colonnes**, il faut passer une liste des noms des colonnes souhaités +ou, sans passer par une liste, une énumération des colonnes, comme dans le tidyverse. -Cet extrait montre les colonnes `var1` et `experiment` du `DataFrame` `df`. +Cet extrait montre les colonnes `var1` et `experiment` du dataframe `df`. ```{python} -print(df.select("var1", "experiment")) +print(df.select("var1", "experiment")) # équivalent print(df.select(["var1", "experiment"])) ``` +### Grâce aux sélecteurs de polars -Polars propose tout une série de méthodes, appelées `selectors`, très pratique pour effectuer des opérations sur des colonnes (sélection, mutation etc) en fonction de leur nom ou de leur type. +Polars propose tout une série de méthodes, appelées `selectors`, très pratique pour effectuer des +opérations sur des colonnes (sélection, mutation etc) en fonction de leur nom ou de leur type. Par exemple, on peut sélectionner des colonnes suivant : + - leur nom (colonnes commençant par, finissant par, avec des regex) ; - leur type ; - exlcure des colonnes des résultats avec l'opération `-` (et plus généralement effectuer des opérations logiques). -L'habitude est d'importer les selectors avec `import polars.selectors as cs`. +L'habitude est d'importer les sélecteurs polars avec `import polars.selectors as cs`. + Par exemple : @@ -259,12 +252,13 @@ Par exemple : - pour sélectionner toutes les colonnes de caractères, on va utiliser `cs.string()` : `df.select(cs.string())`. -Des explications détaillées sont disponibles dans la [documentation officielle](https://docs.pola.rs/api/python/stable/reference/selectors.html). +On verra des détails ci-dessous. +Les explications détaillées sont disponibles dans la [documentation officielle](https://docs.pola.rs/api/python/stable/reference/selectors.html). ## Sélectionner des lignes -En pratique, on souhaite souvent filtrer un DataFrame selon certaines conditions. +En pratique, on souhaite souvent filtrer un dataframe selon certaines conditions. Dans ce cas, on se sert principalement de filtres booléens selon une logique similaire au tidyverse. La principale différence tient au nommage des colonnes. En effet, le nom de chaque colonne doit être entourée d'un sélecteur `pl.col`. @@ -276,22 +270,39 @@ df |> filter(var1>=0) ``` -en `polars`, on va l'écrire +en polars, on va l'écrire ```{python} -print(df.filter(pl.col('var1')>=0)) +print(df.filter(pl.col("var1")>=0)) # équivalent à print(df.filter(pl.col.var1 >= 0)) ``` -Il y a deux manières de sélectionner une colonne : avec `pl.col('colname')` ou `pl.col.colname`. +Il y a deux manières de sélectionner une colonne : avec `pl.col("colname")` ou `pl.col.colname`. Ce sera selon votre goût :) +::: {.callout-tip} + +## Raccourcis de saisie + +On tape beaucoup `pl.col()` en polars. +Un moyen de simplifier cela que l'on retrouve dans d'autres packages est d'importer la fonction col directement. + +```{python} +from polars import col # pour éviter d'avoir à taper pl.col + +df.filter(pl.col("var1")>=0) # équivaut alors à + +df.filter(col("var1") >= 0) + +``` +::: + - **Inégalités** : On peut vouloir garder seulement les lignes qui respectent une certaine condition. Exemple, filtrer les lignes où la valeur de la colonne `var1` est supérieure à 0 : ```{python} -df.filter(pl.col('var1') >= 0) +df.filter(pl.col("var1") >= 0) ``` @@ -300,7 +311,7 @@ df.filter(pl.col('var1') >= 0) Exemple, pour garder uniquement les lignes où la colonne `experiment` a des valeurs 'test' ou 'validation' : ```{python} -df.filter(pl.col('experiment').is_in(['train', 'validation'])) +df.filter(pl.col("experiment").is_in(['train', 'validation'])) ``` Ces méthodes peuvent être combinées pour créer des conditions plus complexes. @@ -327,7 +338,7 @@ df.filter((pl.col("var1") >= 0) | pl.col("experiment").is_in(['train', 'validati La méthode `filter` marche aussi sur des calculs à base des colonnes. Par exemple, si l'on veut sélectionner les observations faites le 2 du mois, on peut effectuer cela en une ligne (on verra plus tard le travail sur les données temporelles): ```{python} -df.filter(pl.col('date').str.to_date("%Y-%m-%d").dt.day()==2) +df.filter(pl.col("date").str.to_date("%Y-%m-%d").dt.day()==2) ``` ::: @@ -340,35 +351,35 @@ Polars offre des outils puissants et très rapides pour importer ces fichiers ta ## Importer et exporter des données Polars est très sensible au format des données, l'import peut donc parfois être un peu long à débuger quand il n'arrive pas à déterminer le format de données de la colonne. -En effet, `polars` va traiter chaque colonne comme une série d'un des formats qu'il connaît. -Les formats de données sont détaillés dans la [documentation de `polars`](https://docs.pola.rs/api/python/stable/reference/datatypes.html). +En effet, polars va traiter chaque colonne comme une série d'un des formats qu'il connaît. +Les formats de données sont détaillés dans la [documentation de polars](https://docs.pola.rs/api/python/stable/reference/datatypes.html). Ils comprennent principalement: -| Famille de format | Format `polars` | Remarques | +| Famille de format | Format polars | Remarques | | -- | -- | -- | -| Caractères | - `pl.String`
- `pl.Utf8` | les données catégorielles (`pl.Categorical`) sont encore peu matures dans `polars`.
Il peut donc mieux valoir les traiter simplement comme des caractères usuels. | +| Caractères | - `pl.String`
- `pl.Utf8` | les données catégorielles (`pl.Categorical`) sont encore peu matures dans polars.
Il peut donc mieux valoir les traiter simplement comme des caractères usuels. | | Nombres | | | | - entiers | - `pl.Int8`
- `pl.Int16`
- `pl.Int32` ... | | | - numérique | - `pl.Float16`
- `pl.Float32`
- `pl.Float64` | | | Temporelles | - `pl.Date`
- `pl.Datetime`
- `pl.Duration` ... | | | Structures imbriquées | | - le format `pl.Struc` très pratique pour lire des formats imbriqués comme des JSON | -| Valeurs manquantes | | `polars` traite les valeurs manquantes à part. | +| Valeurs manquantes | | polars traite les valeurs manquantes à part. | ::: {.callout-caution} -A noter que pour `polars`, les types `null` et `nan` sont différents. +A noter que pour polars, les types `null` et `nan` sont différents. `null` est une valeur manquante, quelque soit le type de valeur (caractère, numérique, temporelle, imbriquée ...). On le déclare avec un `None`. `NaN`, qui signifie _Not a Number_, est une valeur manquante **numérique** (et non pour les entiers). -Cela signifie que `polars` le traite comme un nombre particulier. -On déclare un `NaN` soit en utilisant Numpy `np.nan`, soit une syntaxe de `polars` : `float("nan")`. +Cela signifie que polars le traite comme un nombre particulier. +On déclare un `NaN` soit en utilisant Numpy `np.nan`, soit une syntaxe de polars : `float("nan")`. Plus de détail sur la [documentation](https://docs.pola.rs/user-guide/expressions/missing-data/#null-and-nan-values). ::: On peut convertir une colonne d'un type à l'autre avec la méthode `cast` en indiquant -dans un dictionnaire le nom de la colonne et le format `polars` souhaité. +dans un dictionnaire le nom de la colonne et le format polars souhaité. -Par exemple, dans la table `df` définie ci-dessus, `polars` a assigné les formats suivants : +Par exemple, dans la table `df` définie ci-dessus, polars a assigné les formats suivants : ```{python} df.schema @@ -397,15 +408,15 @@ with open("data/departement2021.csv") as file_in: rows[:5] ``` -Avec `polars`, il suffit d'utiliser la fonction `read_csv()` pour importer le fichier comme un DataFrame, puis la fonction `head()`. +Avec polars, il suffit d'utiliser la fonction `read_csv()` pour importer le fichier comme un dataframe, puis la fonction `head()`. ```{python} df_departements = pl.read_csv('data/departement2021.csv') df_departements.head() ``` -A la différence de `pandas` et à la date d'écriture de ce tutoriel, `polars` ne charge pas directement depuis une URL et ne dézippe pas encore automatiquement le fichier csv (_cf._ [discussion de cette problématique sur Github](https://github.com/pola-rs/polars/issues/19447)). -Soit on utilise la fonction idoine de `pandas` et après on transforme le dataframe en `polars` facilement grâce à la fonction `pl.from_pandas`. +A la différence de pandas et à la date d'écriture de ce tutoriel, polars ne charge pas directement depuis une URL et ne dézippe pas encore automatiquement le fichier csv (_cf._ [discussion de cette problématique sur Github](https://github.com/pola-rs/polars/issues/19447)). +Soit on utilise la fonction idoine de pandas et après on transforme le dataframe en polars facilement grâce à la fonction `pl.from_pandas`. ```{python} import pandas as pd @@ -413,10 +424,11 @@ url = "https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip" pl.from_pandas(pd.read_csv(url, delimiter=";")) ``` -Si l'on veut éviter une dépendance à `pandas` juste pour cette opération, il faut donc faire ces étapes soi-même pour le moment grâce aux packages `requests`et `zipfile`. +Si l'on veut éviter une dépendance à pandas juste pour cette opération, il faut donc faire ces étapes soi-même pour le moment grâce aux packages `requests`et `zipfile`. Prenons l'exemple d'un fichier CSV disponible sur le site de l'INSEE : le fichier des prénoms, issu des données de l'état civil. ```{python} +#| eval: false import requests # Téléchargement et stockage du nom du fichier @@ -437,9 +449,9 @@ with ZipFile(file_Path, 'r') as zObject: ``` -Par exemple, une erreur sera causée ici à cause de types de données incohérentes détectées par `polars`. -En regardant le message d'erreur, `polars` traite la colonne `annais` comme un entier. -Mais la lecture de la valeur `XXXX` cause une erreur et n'est pas convertible en entier par `polars`. +Par exemple, une erreur sera causée ici à cause de types de données incohérentes détectées par polars. +En regardant le message d'erreur, polars traite la colonne `annais` comme un entier. +Mais la lecture de la valeur `XXXX` cause une erreur et n'est pas convertible en entier par polars. ```{python} #| eval: false @@ -448,7 +460,7 @@ df_prenoms_url = pl.read_csv('temp/' + os.listdir('temp')[0], separator=";") ``` Dans ce cas, deux solutions existent : -- On peut dire à `polars` de traiter toutes les colonnes comme des caractères avec infer_schema=False +- On peut dire à polars de traiter toutes les colonnes comme des caractères avec infer_schema=False ```{python} import os @@ -460,6 +472,7 @@ df_prenoms_url Polars va alors assigner des types à chaque colonne qui ne seront pas toutes des caractères. ```{python} +#| eval: false df_prenoms_url = pl.read_csv('temp/'+os.listdir('temp')[0], separator=";", null_values=['XXXX']) df_prenoms_url ``` @@ -469,6 +482,7 @@ Ces arguments peuvent notamment permettre de définir un délimiteur spécifique Tous ces paramètres et leur utilisation sont détaillés dans la [documentation officielle](https://docs.pola.rs/api/python/stable/reference/api/polars.read_csv.html#polars.read_csv). ```{python} +#| eval: false # Pour nettoyer les fichiers !rm $file_Path !rm temp -rf @@ -477,9 +491,9 @@ Tous ces paramètres et leur utilisation sont détaillés dans la [documentation ### Exporter au format CSV -Une fois que les données ont été traitées et modifiées au sein de `polars`, il est courant de vouloir exporter le résultat sous forme de fichier CSV pour le partager, l'archiver ou l'utiliser dans d'autres outils. +Une fois que les données ont été traitées et modifiées au sein de polars, il est courant de vouloir exporter le résultat sous forme de fichier CSV pour le partager, l'archiver ou l'utiliser dans d'autres outils. Polars offre une méthode simple pour cette opération : `write_csv()`. -Supposons par exemple que l'on souhaite exporter les données du DataFrame `df_departements` spécifiques aux cinq départements d'outre-mer. +Supposons par exemple que l'on souhaite exporter les données du dataframe `df_departements` spécifiques aux cinq départements d'outre-mer. ```{python} df_departements_dom = df_departements.filter(pl.col("DEP").is_in(["971", "972", "973", "974", "975"])) @@ -492,9 +506,9 @@ df_departements_dom.write_csv('output/departements2021_dom.csv', separator=";") Le format Parquet est un autre format pour le stockage de données tabulaires, de plus en plus fréquemment utilisé. Sans entrer dans les détails techniques, le format Parquet présente différentes caractéristiques qui en font un choix privilégié pour le stockage et le traitement de gros volumes de données. En raison de ces avantages, ce format est de plus en plus utilisé pour la mise à disposition de données à l'Insee. -Il est donc essentiel de savoir importer et requêter des fichiers Parquet avec `polars`. +Il est donc essentiel de savoir importer et requêter des fichiers Parquet avec polars. -Importer un fichier Parquet dans un DataFrame `pandas` se fait tout aussi facilement que pour un fichier CSV. +Importer un fichier Parquet dans un dataframe pandas se fait tout aussi facilement que pour un fichier CSV. La fonction se nomme `read_parquet()`. ```{python} @@ -504,7 +518,7 @@ df_departements.head() ### Exporter au format Parquet -Là encore, tout se passe comme dans le monde des CSV : on utilise la méthode `write_parquet()` pour exporter un DataFrame dans un fichier Parquet. +Là encore, tout se passe comme dans le monde des CSV : on utilise la méthode `write_parquet()` pour exporter un dataframe dans un fichier Parquet. ```{python} df_departements_dom = df_departements.filter(pl.col("DEP").is_in(["971", "972", "973", "974", "975"])) @@ -513,7 +527,7 @@ df_departements_dom.write_parquet('output/departements2021_dom.parquet') Une des grandes forces du format Parquet, en comparaison des formats texte comme le CSV, est sa capacité à stocker des méta-données, i.e. des données permettant de mieux comprendre les données contenues dans le fichier. En particulier, un fichier Parquet inclut dans ses méta-données le schéma des données (noms des variables, types des variables, etc.), ce qui en fait un format très adapté à la diffusion de données. -Vérifions ce comportement en reprenant le DataFrame que nous avons défini précédemment. +Vérifions ce comportement en reprenant le dataframe que nous avons défini précédemment. ```{python} df = pl.DataFrame( @@ -533,7 +547,7 @@ df = pl.DataFrame( ``` On utilise cette fois deux types de données spécifiques, pour les données catégorielles (`categorical`) et pour les données temporelles (`date`), comme présenté précédemment. -Le format des données est imprimé par `polars` dans la sortie : on voit maintenant en +Le format des données est imprimé par polars dans la sortie : on voit maintenant en dessous du nom des colonnes que le format des colonnes `experiment` et `date` ont changé. On verra plus loin dans le tutoriel comment utiliser ces types. @@ -551,7 +565,7 @@ df_test_schema_parquet ``` A l'inverse, un fichier CSV ne contenant par définition que du texte, ne permet pas de préserver ces données. -Les variables dont nous avons spécifié le type sont importées comme des strings (type `object` en `polars`). +Les variables dont nous avons spécifié le type sont importées comme des strings (type `object` en polars). ```{python} df.write_csv("output/df_test_schema.csv") @@ -562,11 +576,11 @@ df_test_schema_csv ### Importer depuis un dictionnaire -Comme illustré dans le tutoriel [Travailler avec des fichiers CSV et JSON](../csv-json-files/tutorial.qmd), on peut aussi créer un dataFrame `polars` à partir d'un dictionnaire. +Comme illustré dans le tutoriel [Travailler avec des fichiers CSV et JSON](../csv-json-files/tutorial.qmd), on peut aussi créer un dataFrame polars à partir d'un dictionnaire. Cela sera très utile par exemple quand on récupère les données d'une API (_cf._ cours de [Python pour la data-science](https://pythonds.linogaliana.fr/) et la partie sur les API). -Les méthodes `from_dict` et `from_dicts` permettent de créer des DataFrames à partir de dictionnaires. +Les méthodes `from_dict` et `from_dicts` permettent de créer des dataframes à partir de dictionnaires. - `from_dict` prend comme argument un **dictionnaire des colonnes**, de manière similaire à `pl.DataFrame` : on va écrire par exemple `pl.from_dict({"a": [1, 2], "b": [3, 4]})` @@ -580,14 +594,14 @@ response = requests.get("https://data.geopf.fr/geocodage/search?q=comedie&type=s ``` Le résultat de la requête est un dictionnaire avec 3 clés, dont la deuxième, 'features', stocke les résultats sous forme d'une liste. -Pour importer directement ce fichier en `polars`, on peut utiliser la méthode from_dict ou from_dicts. +Pour importer directement ce fichier en polars, on peut utiliser la méthode from_dict ou from_dicts. ```{python} df = pl.from_dicts(json.loads(response.text)) df.head(2) ``` -On retrouve dans le DataFrame les trois colonnes dont la clé représente le nom de la colonne et la valeur dans le dictionnaire la valeur dans la colonne. +On retrouve dans le dataframe les trois colonnes dont la clé représente le nom de la colonne et la valeur dans le dictionnaire la valeur dans la colonne. La première et dernière colonnes sont des valeurs constantes au format `pl.String` et les résultats sont stockés dans la colonne `features`. Cette dernière est au format `pl.Struct`, qui fonctionne de manière similaire à un dictionnaire. @@ -598,7 +612,7 @@ Ainsi, pour récupérer le détail des résultats de l'appel à l'API, il suffit On l'applique à plusieurs reprises et on veille à supprimer les colonnes intermédiaires qui ont des noms identiques pour *applatir* le data frame: ```{python} -df = df.select("features").unnest("features").drop('type').unnest('geometry').drop('type').unnest('properties') +df = df.select("features").unnest("features").drop("type").unnest("geometry").drop("type").unnest("properties") ``` ::: @@ -606,20 +620,20 @@ df = df.select("features").unnest("features").drop('type').unnest('geometry').dr ### Autres exports et imports - **Exporter vers un dictionnaire**: -De manière similaire, `polars` permet d'exporter un DataFrame vers un dictionnaire. +De manière similaire, polars permet d'exporter un dataframe vers un dictionnaire. - - La méthode `to_dict` permet d'exporter un DataFrame "en format colonne". + - La méthode `to_dict` permet d'exporter un dataframe "en format colonne". L'export sera un seul dictionnaire dont les clés sont les noms des colonnes et les valeurs les listes des valeurs prises par colonne `{'a':[1, 2, 3], 'b': [3, 2, 1]}`. - - La méthode `to_dicts`permet d'exporter le DataFrame "en format ligne". -L'export sera une liste dont les termes seront les lignes du DataFrame, + - La méthode `to_dicts`permet d'exporter le dataframe "en format ligne". +L'export sera une liste dont les termes seront les lignes du dataframe, représentées à chaque fois par un dictionnaire : `[{'a': 1, 'b': 3}, {'a': 2, 'b': 2}, {'a': 3, 'b': 1}]` -- **Depuis/vers `pandas`**: -Polars permet aussi facilement d'exporter et d'importer des DataFrame au format `pandas`. -Cela permet de travailler avec `polars` et de convertir un DataFrame en `pandas` quand un package n'autorise pas l'import depuis `polars`. -Il suffit d'utiliser la fonction `pl.from_pandas(df)` pour importer un dataframe `pandas` en `polars`. -La méthode `df.to_pandas()` permettra d'exporter un `polars` dataframe vers `pandas`. +- **Depuis/vers pandas**: +Polars permet aussi facilement d'exporter et d'importer des dataframe au format pandas. +Cela permet de travailler avec polars et de convertir un dataframe en pandas quand un package n'autorise pas l'import depuis polars. +Il suffit d'utiliser la fonction `pl.from_pandas(df)` pour importer un dataframe pandas en polars. +La méthode `df.to_pandas()` permettra d'exporter un polars dataframe vers pandas. # Visualiser un échantillon des données @@ -627,13 +641,13 @@ Lorsqu'on travaille avec des jeux de données volumineux, il est souvent utile d des données pour avoir une idée de leur structure, de leur format ou encore pour détecter d'éventuels problèmes. Polars offre plusieurs méthodes pour cela. -Par défaut, `polars` indique les cinq premières et cinq dernières lignes d'un DataFrame et indique la forme (_shape_). +Par défaut, polars indique les cinq premières et cinq dernières lignes d'un dataframe et indique la forme (_shape_). ```{python} df_departements ``` -La méthode `head()` permet d'afficher les premières lignes du DataFrame. +La méthode `head()` permet d'afficher les premières lignes du dataframe. Par défaut, elle retourne les 5 premières lignes, mais on peut spécifier un autre nombre en argument si nécessaire. ```{python} @@ -644,7 +658,7 @@ df_departements.head() df_departements.head(10) ``` -À l'inverse, la méthode `tail()` donne un aperçu des dernières lignes du DataFrame. +À l'inverse, la méthode `tail()` donne un aperçu des dernières lignes du dataframe. ```{python} df_departements.tail() @@ -659,7 +673,7 @@ df_departements.sample(n=5) ## Obtenir une vue d'ensemble des données L'une des premières étapes lors de l'exploration de nouvelles données est de comprendre la structure générale du jeu de données. -La méthode `glimpse()` de `polars` offre une vue d'ensemble rapide des données, notamment en termes de types de données et affiche les données. +La méthode `glimpse()` de polars offre une vue d'ensemble rapide des données, notamment en termes de types de données et affiche les données. ```{python} df.glimpse() @@ -671,13 +685,13 @@ Plusieurs éléments d'information clés peuvent être extraits de ce résultat - **schéma** : la liste des colonnes est affichée avec des informations très utiles sur le schéma des données : - - **Format** : Le format `polars` de données de la colonne, par exemple ``pour un format caractère (ou `pl.String`). + - **Format** : Le format polars de données de la colonne, par exemple ``pour un format caractère (ou `pl.String`). Cela permet de comprendre la nature des informations stockées dans chaque colonne. - **les premières valeurs** : après chaque colonne sont indiquées, à l'horizontale, les premières valeurs de la colonne. - Cela permet de mieux comprendre le schéma du DataFrame. + Cela permet de mieux comprendre le schéma du dataframe. -Contrairement à `pandas`, cette méthode n'affiche pas les valeurs manquantes. +Contrairement à pandas, cette méthode n'affiche pas les valeurs manquantes. Pour cela, il faut utiliser les statistiques descriptives. ## Calculer des statistiques descriptives @@ -699,11 +713,11 @@ Notons que, là encore, la variable `count` renvoie le nombre de valeurs **non-m ## Transformer les données Les opérations de transformation sur les données sont essentielles pour façonner, nettoyer et préparer les données en vue de leur analyse. -Les transformations peuvent concerner l'ensemble du DataFrame, des colonnes spécifiques ou encore des lignes spécifiques. +Les transformations peuvent concerner l'ensemble du dataframe, des colonnes spécifiques ou encore des lignes spécifiques. ### Transformer les colonnes -En équivalent de `mutate` du tidyverse ou du `replace` de `pandas`, `polars` utilise `with_columns`. +En équivalent de `mutate` du tidyverse ou du `replace` de pandas, polars utilise `with_columns`. Le fonctionnement est similaire au `mutate` du tidyverse. Il permet ainsi de modifier des valeurs de colonne, d'effectuer des opérations etc. @@ -734,13 +748,13 @@ df.with_columns( ::: {.callout-tip} La structure `pl.when` est très pratique et équivaut à la structure `ifelse` en R. -Par exemple, si je veux définir la colonne val à partir de la colonne foo selon le schéma : si foo > 2 : val = 1, sinon val = 1 + bar, cela s'écrite en `polars` : +Par exemple, si je veux définir la colonne val à partir de la colonne foo selon le schéma : si foo > 2 : val = 1, sinon val = 1 + bar, cela s'écrite en polars : ```{python} df = pl.DataFrame({'foo':np.random.randint(-10, 10, 6), 'bar': np.random.randint(5, 15, 6)}) df.with_columns( - pl.when(pl.col('foo') > 2).then(1).otherwise(1 + pl.col('bar')).alias("val") + pl.when(pl.col("foo") > 2).then(1).otherwise(1 + pl.col("bar")).alias("val") ) ``` @@ -748,7 +762,7 @@ df.with_columns( ::: {.callout-warning} -Attention, en `polars`, les caractères simples sont assimilés aux colonnes. +Attention, en polars, les caractères simples sont assimilés aux colonnes. Pour insérer un caractère, utiliser pl.lit. ```{python} @@ -783,7 +797,7 @@ df.glimpse() Dans ce cas, on peut utiliser la méthode `cast` pour convertir la colonne dans le type souhaité en spécifiant avec un dictionnaire les colonnes à modifier. Le dictionnaire est écrit sous le format `{'nom de la colonne 1':'type Polars à appliquer', 'nom de la colonne 2':'type Polars à appliquer'}`. -Les types sont décrits plus haut et dans la [documentation de `polars`](https://docs.pola.rs/api/python/stable/reference/datatypes.html). +Les types sont décrits plus haut et dans la [documentation de polars](https://docs.pola.rs/api/python/stable/reference/datatypes.html). ```{python} df = df.cast({'var2':pl.Int32}) @@ -792,7 +806,7 @@ df.glimpse() ``` -On peut aussi utiliser les `selectors` de `polars` pour faire des opérations groupées sur un ensemble +On peut aussi utiliser les `selectors` de polars pour faire des opérations groupées sur un ensemble de colonnes. Il suffit de remplacer le `pl.col("mycol")` par le sélecteur recherché. Pour modifier les noms en série, on peut utiliser les fonctions liées aux méthodes `Expr.name`, *cf.* [documentation officielle](https://docs.pola.rs/api/python/stable/reference/expressions/name.html). @@ -829,21 +843,21 @@ df = pl.DataFrame({ # On définit une fonction dite User-defined-function (UDF) pour calculer la croissance par pays def calculate_percentage_change(group): - group = group.sort('year') + group = group.sort("year") group = group.with_columns( - ((pl.col('gdp') - pl.col('gdp').shift(1)) / pl.col('gdp').shift(1) * 100).alias('percentage_change') + ((pl.col("gdp") - pl.col("gdp").shift(1)) / pl.col("gdp").shift(1) * 100).alias("percentage_change") ) return group # On applique la fonction en utilisant map_groups -print(df.group_by('country').map_groups(calculate_percentage_change)) +print(df.group_by("country").map_groups(calculate_percentage_change)) ``` ## Trier les valeurs -Le tri des données est particulièrement utile pour l'exploration et la visualisation de données. Avec `polars`, on utilise la méthode [sort()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.sort.html#polars.DataFrame.sort) pour trier les valeurs d'un DataFrame selon une ou plusieurs colonnes. +Le tri des données est particulièrement utile pour l'exploration et la visualisation de données. Avec polars, on utilise la méthode [sort()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.sort.html#polars.DataFrame.sort) pour trier les valeurs d'un dataframe selon une ou plusieurs colonnes. ```{python} df = pl.DataFrame( @@ -860,7 +874,7 @@ df Pour trier les valeurs selon une seule colonne, il suffit de passer le nom de la colonne en paramètre. ```{python} -df.sort(by='var1') +df.sort(by='var1") ``` Par défaut, le tri est effectué dans l'ordre croissant. Pour trier les valeurs dans un ordre décroissant, il suffit de paramétrer `descending=True`. @@ -869,7 +883,7 @@ Par défaut, le tri est effectué dans l'ordre croissant. Pour trier les valeurs df.sort(by='var1', descending=True) ``` -Si on souhaite trier le DataFrame sur plusieurs colonnes, on peut fournir une liste de noms de colonnes. On peut également choisir de trier de manière croissante pour certaines colonnes et décroissante pour d'autres en spécifiant les booléns dans une liste. +Si on souhaite trier le dataframe sur plusieurs colonnes, on peut fournir une liste de noms de colonnes. On peut également choisir de trier de manière croissante pour certaines colonnes et décroissante pour d'autres en spécifiant les booléns dans une liste. ```{python} df.sort(by=['var1', 'var2'], descending=[True, True]) @@ -896,47 +910,47 @@ df.head() ### L'opération `group_by` -La méthode `group_by` de `polars` permet de diviser le DataFrame en sous-ensembles selon les valeurs d'une ou plusieurs colonnes, puis d'appliquer une fonction d'agrégation à chaque sous-ensemble. Elle renvoie un objet de type `dataframe.group_by` qui ne présente pas de grand intérêt en soi, mais constitue l'étape intermédiaire indispensable pour pouvoir ensuite appliquer une ou plusieurs fonction(s) d'agrégation aux différents groupes. +La méthode `group_by` de polars permet de diviser le dataframe en sous-ensembles selon les valeurs d'une ou plusieurs colonnes, puis d'appliquer une fonction d'agrégation à chaque sous-ensemble. Elle renvoie un objet de type `dataframe.group_by` qui ne présente pas de grand intérêt en soi, mais constitue l'étape intermédiaire indispensable pour pouvoir ensuite appliquer une ou plusieurs fonction(s) d'agrégation aux différents groupes. ```{python} -df.group_by('experiment') +df.group_by("experiment") ``` ### Fonctions d'agrégation -Une fois les données groupées, on peut appliquer des fonctions d'agrégation pour obtenir un résumé statistique. `polars` intègre un certain nombre de ces fonctions qui fonctionnent sur la table de donnée entière, *cf.* [liste complète dans la documentation](https://docs.pola.rs/api/python/stable/reference/dataframe/aggregation.html) ou sur des sous-ensembles de la table, en utilisant `group_by`, *cf.* [liste complète dans la documentation](https://docs.pola.rs/api/python/stable/reference/dataframe/group_by.html). +Une fois les données groupées, on peut appliquer des fonctions d'agrégation pour obtenir un résumé statistique. polars intègre un certain nombre de ces fonctions qui fonctionnent sur la table de donnée entière, *cf.* [liste complète dans la documentation](https://docs.pola.rs/api/python/stable/reference/dataframe/aggregation.html) ou sur des sous-ensembles de la table, en utilisant `group_by`, *cf.* [liste complète dans la documentation](https://docs.pola.rs/api/python/stable/reference/dataframe/group_by.html). Voici quelques exemples d'utilisation de ces méthodes avec `group_by`. -Par défaut, `polars` appliquera les fonctions usuelles à l'ensemble des colonnes. +Par défaut, polars appliquera les fonctions usuelles à l'ensemble des colonnes. Pour spécifier une colonne, il faut utiliser la fonction `agg`, détaillée plus bas. - Par exemple, compter le nombre d'occurrences dans chaque groupe. ```{python} -df.group_by('experiment').count() +df.group_by("experiment").count() ``` - Calculer la somme d'une variable par groupe. ```{python} -df.group_by('experiment').agg(pl.col('var2').sum()) +df.group_by("experiment").agg(pl.col("var2").sum()) ``` ::: {.callout-tip} Polars a aussi introduit des wrappers utiles pour les fonctions principales d'aggregation sum, std, count, quantile, cum_count, cum_sum, max, min, median, sqrt. -Pour ces fonctions, on peut les appeler directement en faisant `pl.sum('var2')` et non `pl.col('var2').sum()`. +Pour ces fonctions, on peut les appeler directement en faisant `pl.sum("var2")` et non `pl.col("var2").sum()`. Par exemple : ```{.python} -df.group_by('experiment').agg(pl.sum('var2')) +df.group_by("experiment").agg(pl.sum("var2")) ``` est identique à : ```{.python} -df.group_by('experiment').agg(pl.col('var2').sum()) +df.group_by("experiment").agg(pl.col("var2").sum()) ``` ::: @@ -945,26 +959,26 @@ df.group_by('experiment').agg(pl.col('var2').sum()) ```{python} # Pour le nombre de valeurs uniques dans chaque groupe -df.group_by('experiment').agg(pl.col('var2').n_unique()) +df.group_by("experiment").agg(pl.col("var2").n_unique()) ``` Lorsqu'on souhaite appliquer plusieurs fonctions d'agrégation à la fois ou des fonctions personnalisées, on utilise la méthode `agg`. Cette méthode fonctionne selon une structure similaire à `with_columns`. Elle permet de définir plus finement les fonctions d'agrégation. ```{python} -df.group_by('experiment').agg( - pl.col('var1').mean().alias('mean_var1'), - pl.col('var2').count().alias('count_var2') +df.group_by("experiment").agg( + pl.col("var1").mean().alias('mean_var1"), + pl.col("var2").count().alias('count_var2") ) ``` ::: {.callout-tip} -Au lieu d'utiliser la méthode alias, on peut utiliser l'attribut `name` de `polars` qui renvoie le nom de la colonne et les fonctions associées. Plus de détails sont présentés dans la [documentation officielle](https://docs.pola.rs/api/python/stable/reference/expressions/name.html). +Au lieu d'utiliser la méthode alias, on peut utiliser l'attribut `name` de polars qui renvoie le nom de la colonne et les fonctions associées. Plus de détails sont présentés dans la [documentation officielle](https://docs.pola.rs/api/python/stable/reference/expressions/name.html). -Par exemple, définir `.alias('mean_var1')` est l'équivalent de `.name.prefix('mean_')` +Par exemple, définir `.alias('mean_var1")` est l'équivalent de `.name.prefix('mean_")` ::: ::: {.callout-note title="Le chaînage de méthodes"} -Les exemples précédents illustrent un concept important en `polars` : le chaînage de méthodes. Ce terme désigne la possibilité d'enchaîner les transformations appliquées à un DataFrame en lui appliquant à la chaîne des méthodes, comme le `pipe` du tidyverse. A chaque méthode appliquée, un DataFrame intermédiaire est créé (mais non assigné à une variable), qui devient l'input de la méthode suivante. +Les exemples précédents illustrent un concept important en polars : le chaînage de méthodes. Ce terme désigne la possibilité d'enchaîner les transformations appliquées à un dataframe en lui appliquant à la chaîne des méthodes, comme le `pipe` du tidyverse. A chaque méthode appliquée, un dataframe intermédiaire est créé (mais non assigné à une variable), qui devient l'input de la méthode suivante. Le chaînage de méthodes permet de combiner plusieurs opérations en une seule expression de code. Cela peut améliorer l'efficacité en évitant les assignations intermédiaires et en rendant le code plus fluide et plus facile à lire. Cela favorise également un style de programmation fonctionnel où les données passent à travers une chaîne de transformations de manière fluide. @@ -972,8 +986,8 @@ Cela favorise également un style de programmation fonctionnel où les données ```{.python} subset_df = ( df - .filter(pl.col('sample') == "sample1", pl.col("date") >= '2022-01-02') - .drop('sample') + .filter(pl.col("sample") == "sample1", pl.col("date") >= '2022-01-02') + .drop('sample") .glimpse() ) ``` @@ -982,18 +996,18 @@ subset_df = ( ## Traiter les valeurs manquantes -Les valeurs manquantes sont une réalité courante dans le traitement des données réelles et peuvent survenir pour diverses raisons, telles que des non-réponses à un questionnaire, des erreurs de saisie, des pertes de données lors de la transmission ou simplement parce que l'information n'est pas applicable. `pandas` offre plusieurs outils pour gérer les valeurs manquantes. +Les valeurs manquantes sont une réalité courante dans le traitement des données réelles et peuvent survenir pour diverses raisons, telles que des non-réponses à un questionnaire, des erreurs de saisie, des pertes de données lors de la transmission ou simplement parce que l'information n'est pas applicable. pandas offre plusieurs outils pour gérer les valeurs manquantes. ### Représentation des valeurs manquantes On peut tout d'abord traiter les valeurs manquantes avec les méthodes associées. -Pour rappel, en `polars`, les valeurs `NaN` et `null` sont différentes, alors qu'en `pandas` elles sont traitées de manière similaire. +Pour rappel, en polars, les valeurs `NaN` et `null` sont différentes, alors qu'en pandas elles sont traitées de manière similaire. | | **Type `null`** | **Type `NaN`** | |--|--|--| -| **Signification** | Seule `Null` est considéré par défaut comme une valeur manquante et est l'unique type de valeur manquante dans `polars` (que le type original soit temporel, numérique, un charactère ...). | `NaN` représente à l'inverse des valeurs numériques erronées, comme le résultat d'une division par 0. | -| **Comment les créer ?** | Les valeurs manquantes peuvent être crées simplement avec `None`. | Pour créer une valeur `NaN`, valable uniquement pour les types numériques, on peut utiliser `np.nan` de NumPy ou `float("nan")` de `polars`. | -| Comportement dans `polars` | Ces valeurs sont en général **ignorées**. | Ces valeurs **se propagent**. | +| **Signification** | Seule `Null` est considéré par défaut comme une valeur manquante et est l'unique type de valeur manquante dans polars (que le type original soit temporel, numérique, un charactère ...). | `NaN` représente à l'inverse des valeurs numériques erronées, comme le résultat d'une division par 0. | +| **Comment les créer ?** | Les valeurs manquantes peuvent être crées simplement avec `None`. | Pour créer une valeur `NaN`, valable uniquement pour les types numériques, on peut utiliser `np.nan` de NumPy ou `float("nan")` de polars. | +| Comportement dans polars | Ces valeurs sont en général **ignorées**. | Ces valeurs **se propagent**. | Vérifions cette propriété. @@ -1023,7 +1037,7 @@ print(df.drop_nulls()) ### Calculs sur des colonnes contenant des valeurs manquantes -Lors de calculs statistiques, les valeurs nulles sont généralement ignorées en `polars`. Par exemple, la méthode `.mean()` calcule la moyenne des valeurs non manquantes. +Lors de calculs statistiques, les valeurs nulles sont généralement ignorées en polars. Par exemple, la méthode `.mean()` calcule la moyenne des valeurs non manquantes. ```{python} df['var1'].mean() @@ -1053,7 +1067,7 @@ df.drop_nulls(['var1']) ### Remplacement des valeurs manquantes -Pour gérer les valeurs manquantes dans un DataFrame, une approche commune est l'imputation, qui consiste à remplacer les valeurs manquantes par d'autres valeurs. La méthode [`fill_null()`](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.fill_null.html) permet d'effectuer cette opération de différentes manières dans toute la table de donnée. +Pour gérer les valeurs manquantes dans un dataframe, une approche commune est l'imputation, qui consiste à remplacer les valeurs manquantes par d'autres valeurs. La méthode [`fill_null()`](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.fill_null.html) permet d'effectuer cette opération de différentes manières dans toute la table de donnée. - Une première possibilité est le remplacement par une valeur constante. @@ -1068,16 +1082,16 @@ Il peut parfois être tentant de changer la manifestation d'une valeur manquante df.fill_null(value="MISSING") ``` -En pratique, cette façon de faire n'est pas recommandée. Il est en effet préférable de conserver la convention standard de `Polars` (l'utilisation des `null`), d'abord pour des questions de standardisation des pratiques qui facilitent la lecture et la maintenance du code, mais également parce que la convention standard est optimisée pour la performance et les calculs à partir de données contenant des valeurs manquantes. +En pratique, cette façon de faire n'est pas recommandée. Il est en effet préférable de conserver la convention standard de polars (l'utilisation des `null`), d'abord pour des questions de standardisation des pratiques qui facilitent la lecture et la maintenance du code, mais également parce que la convention standard est optimisée pour la performance et les calculs à partir de données contenant des valeurs manquantes. ::: -La méthide `fill_null()` de `polars` propose 4 méthodes pré-définies pour remplacer les valeurs manquantes par l'argument `strategy`: +La méthide `fill_null()` de polars propose 4 méthodes pré-définies pour remplacer les valeurs manquantes par l'argument `strategy`: - toute valeur constante indiquée (`strategy=None`, argument par défaut); - soit des 0, soit des 1 (`strategy="zero"`, `strategy="one"` :); - en reportant la valeur précédente (`strategy=‘forward’`) ou la valeur suivante (`strategy=‘backward’`) de la colonne ; - en indiquant le minimum, le maximum ou la médiane de la colonne (`strategy=‘min’`, `strategy=‘max’`, `strategy=‘mean’`). -Si l'on veut remplacer uniquement les valeurs manquantantes d'une colonne en `polars`, il est plus utile d'utiliser la méthode `with_columns()` en utilisant l'agilité des sélecteurs de `polars`. +Si l'on veut remplacer uniquement les valeurs manquantantes d'une colonne en polars, il est plus utile d'utiliser la méthode `with_columns()` en utilisant l'agilité des sélecteurs de polars. ```{python} df.with_columns( @@ -1098,7 +1112,7 @@ De manière similaire, la méthode `fill_nan()` permet de remplacer les valeurs Les données textuelles nécessitent souvent un nettoyage et une préparation avant l'analyse. Polars fournit via la librairie de méthodes `str` un ensemble d'opérations vectorisées qui rendent la préparation des données textuelles à la fois simple et très efficace. -La méthode `str` s'applique aux séries `polars`. +La méthode `str` s'applique aux séries polars. Là encore, les possibilités sont multiples et détaillées dans la [documentation](https://docs.pola.rs/api/python/stable/reference/series/string.html). Nous présentons ici les méthodes les plus fréquemment utilisées dans l'analyse de données. @@ -1121,45 +1135,45 @@ Un petit tour par la [documentation](https://docs.pola.rs/api/python/stable/refe ```{python} df.with_columns( - sample_n = pl.col('sample').str.tail(1) + sample_n = pl.col("sample").str.tail(1) ) ``` -Le principe était le bon, mais la présence d'espaces superflus dans nos données textuelles (qui ne se voyaient pas à la visualisation du DataFrame !) a rendu l'opération plus difficile que prévue. +Le principe était le bon, mais la présence d'espaces superflus dans nos données textuelles (qui ne se voyaient pas à la visualisation du dataframe !) a rendu l'opération plus difficile que prévue. C'est l'occasion d'introduire la famille de méthode `strip` (`.str.strip_chars()`, `.str.strip_chars_start()` et `.str.strip_chars_end()`) qui respectivement retirent les espaces superflus (ou tout caractère indiqué) des deux côtés ou d'un seul. ```{python} ( df .with_columns( - sample=pl.col('sample').str.strip_chars() # remarque : on peut omettre ici le 'sample=' + sample=pl.col("sample").str.strip_chars() # remarque : on peut omettre ici le 'sample=' # et avoir le meme résultat ) .with_columns( - sample_n = pl.col('sample').str.tail(1) + sample_n = pl.col("sample").str.tail(1) ) ) ``` ::: {.callout-note} Remarquez la présence de deux `with_columns()` et non d'un seul. -C'est parce que `polars` étant optimisé, il effectue les opérations sur `with_columns` en parallèle. +C'est parce que polars étant optimisé, il effectue les opérations sur `with_columns` en parallèle. Ainsi, si l'on ne le fait pas de manière séquentielle, il ne prend pas en compte le fait qu'on enlève les espace superflus dans 'sample' à la première ligne avant d'en extraire le dernier caractère. ::: -On peut également vouloir filtrer un DataFrame en fonction de la présence ou non d'une certaine chaîne (ou sous-chaîne) de caractères. +On peut également vouloir filtrer un dataframe en fonction de la présence ou non d'une certaine chaîne (ou sous-chaîne) de caractères. On utilise pour cela la méthode `.str.contains()`. ```{python} -df.filter(pl.col('experiment').str.contains('test')) +df.filter(pl.col("experiment").str.contains("test")) ``` Enfin, on peut vouloir remplacer une chaîne (ou sous-chaîne) de caractères par une autre, ce que permet la méthode `str.replace()`. ```{python} df.with_columns( - experiment = pl.col('experiment').str.replace('validation', 'val') + experiment = pl.col("experiment").str.replace("validation", "val") ) ``` @@ -1167,9 +1181,9 @@ df.with_columns( ## Données catégorielles Les données catégorielles sont des variables qui contiennent un nombre restreint de modalités. -A l'instar de `R` avec la notion de `factor`, `polars` a un type de données spécial, `Categorical`, qui peut être utilisé pour représenter des données catégorielles. +A l'instar de `R` avec la notion de `factor`, polars a un type de données spécial, `Categorical`, qui peut être utilisé pour représenter des données catégorielles. -Ce type de données est cependant délicat à gérer en `polars` et, en général, on préfèrera travailler avec des données de type caractère. +Ce type de données est cependant délicat à gérer en polars et, en général, on préfèrera travailler avec des données de type caractère. En effet, les méthodes usuelles pour renommer des catégories, dissocier son nom et sa représentation, réarranger l'ordre dans laquelle les catégories sont visualisées sont encore très largement perfectibles (voire inexistantes :o). @@ -1220,8 +1234,8 @@ df = pl.DataFrame( df.dtypes ``` -Pour manipuler les données temporelles, il est nécessaire de convertir les chaînes de caractères en colonne de type temporel sous `polars`. -Il existe 4 types temporels de colonnes en `polars`, comme rappelé dans la [documentation](https://docs.pola.rs/api/python/stable/reference/datatypes.html): +Pour manipuler les données temporelles, il est nécessaire de convertir les chaînes de caractères en colonne de type temporel sous polars. +Il existe 4 types temporels de colonnes en polars, comme rappelé dans la [documentation](https://docs.pola.rs/api/python/stable/reference/datatypes.html): - le type [`pl.Datetime`](https://docs.pola.rs/api/python/stable/reference/api/polars.datatypes.Date.html#polars.datatypes.Datetime) pour un format date et heure ; - le type [`pl.Date`](https://docs.pola.rs/api/python/stable/reference/api/polars.datatypes.Date.html#polars.datatypes.Date) pour un format Date seul ; @@ -1234,22 +1248,22 @@ Au cas d'espèce, la méthode `str.to_date()` remplit parfaitement notre besoin. ```{python} df = df.with_columns( - date = pl.col('date').str.to_date("%Y-%m-%d") + date = pl.col("date").str.to_date("%Y-%m-%d") ) df.dtypes ``` Une fois converties, les dates peuvent être formatées, comparées et utilisées dans des calculs. Il faudra cependant bien penser à traduire les dates d'un format textuel à un format temporel. -Par exemple, pour filtrer des données, on devra spécifier les bornes en appelant les fonctions dédiées de `polars` ou du module `datetime`. +Par exemple, pour filtrer des données, on devra spécifier les bornes en appelant les fonctions dédiées de polars ou du module `datetime`. ```{python} -df.filter(pl.col('date') >= pl.date(2022, 1, 1), pl.col('date') < pl.date(2022, 1, 3)) +df.filter(pl.col("date") >= pl.date(2022, 1, 1), pl.col("date") < pl.date(2022, 1, 3)) # équivalent à from datetime import datetime -df.filter(pl.col('date') >= datetime.strptime("2022-01-01", "%Y-%m-%d"), pl.col('date') < datetime.strptime("2022-01-03", "%Y-%m-%d")) +df.filter(pl.col("date") >= datetime.strptime("2022-01-01", "%Y-%m-%d"), pl.col("date") < datetime.strptime("2022-01-03", "%Y-%m-%d")) ``` On peut également vouloir réaliser des filtrages moins précis, faisant intervenir l'année ou le mois. @@ -1258,20 +1272,20 @@ Elles permettent d'extraire facilement des composants spécifiques de la date, c ```{python} df = df.with_columns( - year = pl.col('date').dt.year(), - month = pl.col('date').dt.month(), - day = pl.col('date').dt.day() + year = pl.col("date").dt.year(), + month = pl.col("date").dt.month(), + day = pl.col("date").dt.day() ) -df.filter(pl.col('year')==2022) +df.filter(pl.col("year")==2022) ``` -Dans ce cas précis, on peut utiliser plus finement les propriétés de la méthode `filter()` et avoir le même résultat en faisant directement `df.filter(pl.col('date').dt.year() == 2022)`. +Dans ce cas précis, on peut utiliser plus finement les propriétés de la méthode `filter()` et avoir le même résultat en faisant directement `df.filter(pl.col("date").dt.year() == 2022)`. Enfin, les calculs faisant intervenir des dates deviennent possible. On peut ajouter ou soustraire des périodes temporelles à des dates, et les comparer entre elles. -Les fonctions utilisées sont issues de `Polars`, mais sont très semblables dans leur fonctionnement à celles du module [datetime](https://docs.python.org/fr/3/library/datetime.html#module-datetime) de Python. +Les fonctions utilisées sont issues de polars, mais sont très semblables dans leur fonctionnement à celles du module [datetime](https://docs.python.org/fr/3/library/datetime.html#module-datetime) de Python. On peut par exemple ajouter des intervalles de temps, ou bien calculer des écarts à une date de référence. @@ -1283,19 +1297,19 @@ Si l'on veut transformer une durée en un nombre, il faut utiliser les méthodes ```{python} df.with_columns( date = pl.col("date") + pl.duration(days=1), - date_diff = (pl.col('date') - pl.date(2022, 1, 1)).dt.total_days() + date_diff = (pl.col("date") - pl.date(2022, 1, 1)).dt.total_days() ) ``` # Joindre des tables Dans le cadre d'une analyse de données, il est courant de vouloir combiner différentes sources de données. -Cette combinaison peut se faire verticalement (un DataFrame par dessus l'autre), par exemple lorsque l'on souhaite combiner deux millésimes d'une même enquête afin de les analyser conjointement. +Cette combinaison peut se faire verticalement (un dataframe par dessus l'autre), par exemple lorsque l'on souhaite combiner deux millésimes d'une même enquête afin de les analyser conjointement. La combinaison peut également se faire horizontalement (côte à côte) selon une ou plusieurs clé(s) de jointure, souvent dans le but d'enrichir une source de données à partir d'une autre source portant sur les mêmes unités statistiques. ## Concaténer des tables -La concaténation verticale de tables se fait à l'aide de la fonction [`concat()`](https://docs.pola.rs/api/python/stable/reference/api/polars.concat.html#polars.concat) de `polars`. +La concaténation verticale de tables se fait à l'aide de la fonction [`concat()`](https://docs.pola.rs/api/python/stable/reference/api/polars.concat.html#polars.concat) de polars. ```{python} @@ -1321,7 +1335,7 @@ pl.concat([df1, df2]) ``` -A la grande différence de `pandas`, **l'ordre des variables dans les deux DataFrames importe**. +A la grande différence de pandas, **l'ordre des variables dans les deux dataframes importe**. Ainsi, le même code avec `df2` défini comme ci-après va renvoyer une erreur. ```{python} @@ -1344,21 +1358,21 @@ Pour contourner ce problème, il suffit de préférer une méthode de type `join ## Fusionner des tables -La fusion de tables est une opération qui permet d'associer des lignes de deux DataFrames différents en se basant sur une ou plusieurs clés communes, similaire aux jointures dans les bases de données SQL. +La fusion de tables est une opération qui permet d'associer des lignes de deux dataframes différents en se basant sur une ou plusieurs clés communes, similaire aux jointures dans les bases de données SQL. Différents types de jointure sont possible selon les données que l'on souhaite conserver, dont les principaux sont représentés sur le graphique suivant. ![](img/joins.png) Source : [lien](https://medium.com/swlh/merging-dataframes-with-pandas-pd-merge-7764c7e2d46d) -En `polars`, les jointures se font avec la fonction [`join()`](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.join.html#polars.DataFrame.join). +En polars, les jointures se font avec la fonction [`join()`](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.join.html#polars.DataFrame.join). Pour réaliser une jointure, on doit spécifier (au minimum) deux informations : -- le type de jointure : par défaut, `polars` effectue une jointure de type `inner`. +- le type de jointure : par défaut, polars effectue une jointure de type `inner`. Le paramètre `how` permet de spécifier d'autres types de jointure ; - la clé de jointure. -On spécifie souvent une colonne présente dans le DataFrame comme clé de jointure (paramètre `on` si la colonne porte le même nom dans les deux DataFrame, ou `left_on` et `right_on` sinon). +On spécifie souvent une colonne présente dans le dataframe comme clé de jointure (paramètre `on` si la colonne porte le même nom dans les deux dataframes, ou `left_on` et `right_on` sinon). Par défaut, les colonnes présentes dans les deux colonnes seront conservées avec des suffixes '_right' ou '_left'. @@ -1391,7 +1405,7 @@ print(df_b) ``` - **Inner Join** -La jointure de type `inner` conserve les observations dont la clé est présente dans les deux DataFrame. +La jointure de type `inner` conserve les observations dont la clé est présente dans les deux dataframes. ```{python} df_a.join(df_b, on='key') @@ -1399,20 +1413,20 @@ df_a.join(df_b, on='key') ::: {.callout-warning title="Jointures inner"} La jointure de type `inner` est la plus intuitive : elle ne crée généralement pas de valeurs manquantes et permet donc de travailler directement sur la table fusionnée. -Mais attention : si beaucoup de clés ne sont pas présentes dans les deux DataFrames à la fois, une jointure `inner` peut aboutit à des pertes importantes de données, et donc à des résultats finaux biaisés. +Mais attention : si beaucoup de clés ne sont pas présentes dans les deux dataframes à la fois, une jointure `inner` peut aboutit à des pertes importantes de données, et donc à des résultats finaux biaisés. Dans ce cas, il vaut mieux choisir une jointure à gauche ou à droite, selon la source que l'on cherche à enrichir et pour laquelle il est donc le plus important de limiter les pertes de données. ::: - **Left join** -Une jointure de type `left` conserve toutes les observations contenues dans le DataFrame de gauche (le DataFrame à qui on applique la méthode `.join()`). -Par conséquent, si des clés sont présentes dans le DataFrame de gauche mais pas dans celui de droite, le DataFrame final contient des valeurs manquantes au niveau de ces observations (pour les variables du DataFrame de droite). +Une jointure de type `left` conserve toutes les observations contenues dans le dataframe de gauche (le dataframe à qui on applique la méthode `.join()`). +Par conséquent, si des clés sont présentes dans le dataframe de gauche mais pas dans celui de droite, le dataframe final contient des valeurs manquantes au niveau de ces observations (pour les variables du dataframe de droite). ```{python} df_a.join(df_b, how="left", on='key') ``` - **Full join** -La jointure de type `full` contient toutes les observations et variables contenues dans les deux DataFrame. +La jointure de type `full` contient toutes les observations et variables contenues dans les deux dataframes. Ainsi, l'information retenue est maximale, mais en contrepartie les valeurs manquantes peuvent être assez nombreuses. Il sera donc nécessaire de bien traiter les valeurs manquantes avant de procéder aux analyses. @@ -1429,21 +1443,21 @@ df_a.join(df_b, how="full", on='key', coalesce=True) ## Questions de compréhension -- 1/ Qu'est-ce qu'un DataFrame dans le contexte de `polars` et à quel type de structure de données peut-on le comparer dans le langage Python ? +- 1/ Qu'est-ce qu'un dataframe dans le contexte de polars et à quel type de structure de données peut-on le comparer dans le langage Python ? -- 2/ Quels sont les avantages de `polars` ? +- 2/ Quels sont les avantages de polars ? -- 3/ Quel est le lien entre Series et DataFrame dans `polars` ? +- 3/ Quel est le lien entre Series et dataframe dans polars ? -- 4/ Comment sont structurées les données dans un DataFrame `polars` ? +- 4/ Comment sont structurées les données dans un dataframe polars ? -- 5/ Quelles méthodes pouvez-vous utiliser pour explorer un DataFrame inconnu et en apprendre davantage sur son contenu et sa structure ? +- 5/ Quelles méthodes pouvez-vous utiliser pour explorer un dataframe inconnu et en apprendre davantage sur son contenu et sa structure ? -- 6/ Comment s'applique le principe d'évaluation paresseuse dans `polars` et pourquoi est-ce avantageux pour manipuler les données ? +- 6/ Comment s'applique le principe d'évaluation paresseuse dans polars et pourquoi est-ce avantageux pour manipuler les données ? -- 7/ Comment `polars` représente-t-il les valeurs manquantes et quel impact cela a-t-il sur les calculs et les transformations de données ? +- 7/ Comment polars représente-t-il les valeurs manquantes et quel impact cela a-t-il sur les calculs et les transformations de données ? -- 8/ Quelle est la différence entre concaténer deux DataFrames et les joindre via une jointure, et quand utiliseriez-vous l'une plutôt que l'autre ? +- 8/ Quelle est la différence entre concaténer deux dataframes et les joindre via une jointure, et quand utiliseriez-vous l'une plutôt que l'autre ? ::: {.cell .markdown} @@ -1451,10 +1465,10 @@ df_a.join(df_b, how="full", on='key', coalesce=True)
Afficher la solution -- 1/ Un DataFrame dans `polars` est une **structure de données tabulaire bidimensionnelle**, optimisée pour la performance et la manipulation de données volumineuses. Contrairement à pandas, il n’utilise pas d’index nommé par défaut. +- 1/ Un dataframe dans polars est une **structure de données tabulaire bidimensionnelle**, optimisée pour la performance et la manipulation de données volumineuses. Contrairement à pandas, il n’utilise pas d’index nommé par défaut. On peut le comparer à un **dictionnaire de listes ou d’arrays NumPy**, où chaque clé du dictionnaire représente une colonne, et les valeurs sont les données de cette colonne. Polars utilise des Series pour représenter chaque colonne, mais contrairement à pandas, ces Series ne partagent pas d’index global. -- 2/ Les avantages de `polars` sont globalement : +- 2/ Les avantages de polars sont globalement : - **Rapidité** : Polars est optimisé pour traiter des données volumineuses, souvent plus rapidement que pandas, grâce à son implémentation en Rust et son utilisation de la parallélisation. - **Évaluation paresseuse (lazy evaluation)** : Permet d’optimiser les requêtes avant leur exécution, améliorant les performances sur les gros jeux de données. - **Streaming** : Capacité à traiter des données qui ne tiennent pas en mémoire (out-of-memory). @@ -1464,8 +1478,8 @@ On peut le comparer à un **dictionnaire de listes ou d’arrays NumPy**, où ch - **Sélecteurs avancés** : Permet de sélectionner des colonnes par nom, type ou motif (regex). -- 3/ Un DataFrame est une **collection de Series**, où chaque Series représente une colonne. Contrairement à `pandas`, les Series de `polars` ne partagent pas d’index global. Chaque Series est indépendante et peut être manipulée individuellement. -Un DataFrame est donc une table composée de colonnes (Series) alignées par leur position (et non par un index). +- 3/ Un dataframe est une **collection de Series**, où chaque Series représente une colonne. Contrairement à pandas, les Series de polars ne partagent pas d’index global. Chaque Series est indépendante et peut être manipulée individuellement. +Un dataframe est donc une table composée de colonnes (Series) alignées par leur position (et non par un index). - 4/ Les données sont organisées en **colonnes (Series) et en lignes (observations)**. - Chaque colonne est une Series avec un type de données homogène (ex : pl.Int64, pl.String, pl.Date). @@ -1473,7 +1487,7 @@ Un DataFrame est donc une table composée de colonnes (Series) alignées par leu - Les colonnes peuvent être de types différents (numériques, chaînes, dates, etc.). -- 5/ Pour explorer un DataFrame inconnu, on peut utiliser : +- 5/ Pour explorer un dataframe inconnu, on peut utiliser : - df.head(n) : Affiche les n premières lignes. - df.tail(n) : Affiche les n dernières lignes. - df.sample(n) : Affiche un échantillon aléatoire de n lignes. @@ -1488,16 +1502,16 @@ Cela permet notamment de réduire la consommation mémoire, d'augmenter le temps le traitement de requêtes complexes. -- 7/ `polars` distingue **deux types de valeurs manquantes** : +- 7/ polars distingue **deux types de valeurs manquantes** : - null : Valeur manquante générique (pour tous les types de données). - NaN : Valeur manquante spécifique aux données numériques (équivalent à np.nan). Les valeurs null et NaN sont ignorées par défaut dans les calculs statistiques (moyenne, somme, etc.). Les opérations logiques (filter, is_in, etc.) traitent null comme une valeur inconnue (ex : null == null retourne null, pas True). -Les méthodes comme .drop_nulls() ou .fill_null() permettent de gérer explicitement ces valeurs. +Les méthodes comme `df.drop_nulls()` ou `df.fill_null()` permettent de gérer explicitement ces valeurs. - 8/ La différence entre concaténer et joindre deux tables est : - - **Concaténer**, avec `pl.concat`, permet d'empiler deux DataFrames verticalement (ajoute des lignes) ou horizontalement (ajoute des colonnes). On l'utilise lorsque les DataFrames ont la même structure (mêmes colonnes pour un empilement vertical, mêmes lignes pour un empilement horizontal). - - La **jointure**, avec `df.join()`, permet de **combiner deux DataFrames sur une clé commune** (comme une opération SQL JOIN). Elle est utilisée pour enrichir un DataFrame avec des données d’un autre, en fonction de valeurs partagées (ex : df1.join(df2, on="id", how="inner")). Il existe quatre types principaux de jointures : inner, left, outer, cross. + - **Concaténer**, avec `pl.concat`, permet d'empiler deux dataframes verticalement (ajoute des lignes) ou horizontalement (ajoute des colonnes). On l'utilise lorsque les dataframes ont la même structure (mêmes colonnes pour un empilement vertical, mêmes lignes pour un empilement horizontal). + - La **jointure**, avec `df.join()`, permet de **combiner deux dataframes sur une clé commune** (comme une opération SQL JOIN). Elle est utilisée pour enrichir un dataframe avec des données d’un autre, en fonction de valeurs partagées (ex : df1.join(df2, on="id", how="inner")). Il existe quatre types principaux de jointures : inner, left, outer, cross. - On **préfère** concaténer pour fusionner des données de même structure (ex : ajouter des observations supplémentaires) et joindre deux tables pour combiner des données liées par une clé (ex : lier des tables "clients" et "commandes"). @@ -1505,7 +1519,7 @@ Les méthodes comme .drop_nulls() ou .fill_null() permettent de gérer explicite ::: -## Plusieurs manières de créer un DataFrame +## Plusieurs manières de créer un dataframe Dans la cellule suivante, nous avons récupéré des données de caisses sur les ventes de différentes enseignes. Les données sont cependant présentées de deux manières différentes, dans un cas sous forme d'observations (chaque liste contient les données d'une ligne), dans l'autre sous forme de variables (chaque liste contient les données d'une colonne). @@ -1527,7 +1541,7 @@ data_list2 = [ ] ``` -L'objectif est de construire dans les deux cas un même DataFrame qui contient chacune des 6 observations et des 4 variables, avec les mêmes noms dans les deux DataFrame. A chaque cas va correspondre une structure de données plus adaptée en entrée, dictionnaire ou liste de listes... faîtes le bon choix ! On vérifiera que les deux DataFrames sont identiques à l'aide de la méthode [equals()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.equals.html#polars.DataFrame.equals). +L'objectif est de construire dans les deux cas un même dataframe qui contient chacune des 6 observations et des 4 variables, avec les mêmes noms dans les deux dataframes. A chaque cas va correspondre une structure de données plus adaptée en entrée, dictionnaire ou liste de listes... faîtes le bon choix ! On vérifiera que les deux dataframes sont identiques à l'aide de la méthode [equals()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.equals.html#polars.DataFrame.equals). ```{python} # Testez votre réponse dans cette cellule @@ -1578,9 +1592,9 @@ df_from_dict.equals(df_from_list) ::: -## Sélection de données dans un DataFrame +## Sélection de données dans un dataframe -Un DataFrame `polars` est créé avec des données de caisse (mêmes données que l'exercice précédent). +Un dataframe polars est créé avec des données de caisse (mêmes données que l'exercice précédent). ```{python} data = { @@ -1674,7 +1688,7 @@ print(df.filter(pl.col("enseigne") == 'Carrefour')) print( df .filter(pl.col("produit") == '01.1.1') - .select('quantite') + .select("quantite") ) ``` @@ -1695,7 +1709,7 @@ print( Afficher la solution ```{python} -print(df.select('enseigne', 'prix')) +print(df.select("enseigne", "prix")) ```
@@ -1755,7 +1769,7 @@ print(df.filter(pl.col("date_heure").dt.hour() > 15)) Afficher la solution ```{python} -print(df.filter(pl.col('date_heure').dt.date() == pl.Series(['2022-01-03']).str.to_date())) +print(df.filter(pl.col("date_heure").dt.date() == pl.Series(['2022-01-03']).str.to_date())) ```
@@ -1769,9 +1783,9 @@ Le fichier des prénoms contient des données sur les prénoms attribués aux en ### Partie 1 : Import et exploration des données -- Importez les données dans un DataFrame en utilisant cette [URL](https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip). +- Importez les données dans un dataframe en utilisant cette [URL](https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip). - Visualisez un échantillon des données. Repérez-vous d'éventuelles anomalies ? -- Affichez les principales informations du DataFrame. Repérez d'éventuelles variables dont le type serait incorrect, ou bien d'éventuelles valeurs manquantes. +- Affichez les principales informations du dataframe. Repérez d'éventuelles variables dont le type serait incorrect, ou bien d'éventuelles valeurs manquantes. ```{python} # Testez votre réponse dans cette cellule @@ -1967,7 +1981,7 @@ df_prenoms_post_1946 = df_prenoms.filter(pl.col("annais") >= 1946) Afficher la solution ```{python} -births_per_sex = df_prenoms_post_1946.group_by('sexe').agg(pl.sum('nombre')) +births_per_sex = df_prenoms_post_1946.group_by("sexe").agg(pl.sum("nombre")) print(births_per_sex) ``` @@ -1999,7 +2013,7 @@ print(top5_years) ### Partie 4 : Analyse des prénoms -- Identifiez le nombre total de prénoms uniques dans le DataFrame. +- Identifiez le nombre total de prénoms uniques dans le dataframe. ```{python} # Testez votre réponse dans cette cellule @@ -2055,11 +2069,11 @@ print(single_letter_names) ```{python} def popularite_par_annee(df, prenom): - # Filtrer le DataFrame pour ne garder que les lignes correspondant au prénom donné + # Filtrer le dataframe pour ne garder que les lignes correspondant au prénom donné df_prenom = df.filter(pl.col("preusuel") == "ALFRED") # Grouper par année, sommer les naissances et identifier l'année avec le maximum de naissances - df_agg = df_prenom.group_by("annais").agg(pl.sum('nombre')).sort("nombre", descending=True) + df_agg = df_prenom.group_by("annais").agg(pl.sum("nombre")).sort("nombre", descending=True) annee_max = df_agg.item(0, "annais") n_max = df_agg.item(0, "nombre") @@ -2073,7 +2087,7 @@ popularite_par_annee(df_prenoms, 'ALFRED') ::: -- Créez une fonction qui, pour un sexe donné, renvoie un DataFrame contenant le prénom le plus donné pour chaque décennie. +- Créez une fonction qui, pour un sexe donné, renvoie un dataframe contenant le prénom le plus donné pour chaque décennie. ```{python} # Testez votre réponse dans cette cellule @@ -2119,7 +2133,7 @@ L'objectif de cet exercice est de calculer une empreinte carbone par habitant au - les émissions de gaz à effet de serre estimées au niveau communal par l’ADEME ([source](https://www.data.gouv.fr/fr/datasets/inventaire-de-gaz-a-effet-de-serre-territorialise/#_)) -Cet exercice constitue une version simplifiée d'un [TP complet pour la pratique de `pandas`](https://pythonds.linogaliana.fr/content/manipulation/02b_pandas_TP.html#importer-les-donn%C3%A9es) proposé par Lino Galiana dans son [cours à l'ENSAE](https://pythonds.linogaliana.fr/) et traduit en `polars`. +Cet exercice constitue une version simplifiée d'un [TP complet pour la pratique de pandas](https://pythonds.linogaliana.fr/content/manipulation/02b_pandas_TP.html#importer-les-donn%C3%A9es) proposé par Lino Galiana dans son [cours à l'ENSAE](https://pythonds.linogaliana.fr/) et traduit en polars. ### Partie 1 : Exploration des données sur les populations légales communales @@ -2189,7 +2203,7 @@ Les communes qui ont les noms les plus longs sont-elles aussi les communes les m ```{python} df_pop_communes_stats = df_pop_communes df_pop_communes_stats = (df_pop_communes_stats.with_columns( - longueur=pl.col('COM').str.len_chars() + longueur=pl.col("COM").str.len_chars() ) .select(["longueur", "PTOT"]) ) @@ -2376,7 +2390,7 @@ doublons ::: -- Filtrez dans le DataFrame initial les communes dont le nom est dupliqué, et triez-le par code commune. Les doublons semblent-ils problématiques ? +- Filtrez dans le dataframe initial les communes dont le nom est dupliqué, et triez-le par code commune. Les doublons semblent-ils problématiques ? ```{python} # Testez votre réponse dans cette cellule @@ -2390,7 +2404,7 @@ doublons ```{python} df_pop_communes_doublons = df_pop_communes.filter(pl.col("COM").is_in(doublons["COM"])).drop(pl.col("PTOT")) -df_pop_communes_doublons.sort('COM') +df_pop_communes_doublons.sort("COM") ``` @@ -2447,7 +2461,7 @@ df_emissions.filter( ### Partie 4 : Calcul d'une empreinte carbone par habitant pour chaque commune -- Joindre les deux DataFrames à l'aide de la fonction à partir du code commune. Attention : les variables ne s'appellent pas de la même manière des deux côtés ! +- Joindre les deux dataframes à l'aide de la fonction à partir du code commune. Attention : les variables ne s'appellent pas de la même manière des deux côtés ! ```{python} # Testez votre réponse dans cette cellule @@ -2505,14 +2519,14 @@ Vous avez à disposition dans le dossier `data/` deux jeux de données CSV : - `serie_glaces_valeurs.csv` contient les valeurs mensuelles de l'indice de prix de production de l'industrie française des glaces et sorbets - `serie_glaces_metadonnees.csv` contient les métadonnées associées, notamment les codes indiquant le statut des données. -L'objectif est d'utiliser `Polars` pour calculer : +L'objectif est d'utiliser polars pour calculer : - l'évolution de l'indice entre chaque période (mois) - l'évolution de l'indice en glissement annuel (entre un mois donné et le même mois l'année suivante). ### Partie 1 : Import des données -- Importez les deux fichiers CSV dans des DataFrames. Attention, dans les deux cas, il y a des lignes superflues avant les données, qu'il faudra sauter à l'aide du paramètre `skip_rows` de la fonction [read_csv()](https://docs.pola.rs/api/python/stable/reference/api/polars.read_csv.html#polars.read_csv). +- Importez les deux fichiers CSV dans des dataframes. Attention, dans les deux cas, il y a des lignes superflues avant les données, qu'il faudra sauter à l'aide du paramètre `skip_rows` de la fonction [read_csv()](https://docs.pola.rs/api/python/stable/reference/api/polars.read_csv.html#polars.read_csv). - Donnez des noms simples et pertinents aux différentes variables. ```{python} @@ -2538,7 +2552,7 @@ df_metadata = pl.read_csv('data/serie_glaces_metadonnees.csv', separator=';', ### Partie 2 : Filtrage des données pertinentes -- Fusionner les deux DataFrames afin de récupérer la signification des codes présents dans les données. +- Fusionner les deux dataframes afin de récupérer la signification des codes présents dans les données. - Filtrer les données de sorte à ne conserver que les données de type "Valeur normale". - Supprimer les colonnes liées aux codes, dont nous n'avons plus besoin pour la suite. From ff36c29d6e9b5fae5aaebae11d67a196d3f71e78 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 25 Feb 2026 16:59:29 +0000 Subject: [PATCH 54/92] review - aggregate --- source/manipulation/polars/tutorial.qmd | 354 ++++++++++++++---------- 1 file changed, 202 insertions(+), 152 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index e2d31c76..a917e549 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -228,8 +228,8 @@ ou, sans passer par une liste, une énumération des colonnes, comme dans le tid Cet extrait montre les colonnes `var1` et `experiment` du dataframe `df`. ```{python} -print(df.select("var1", "experiment")) # équivalent -print(df.select(["var1", "experiment"])) +df.select("var1", "experiment") # équivalent +df.select(["var1", "experiment"]) ``` ### Grâce aux sélecteurs de polars @@ -273,8 +273,8 @@ df |> en polars, on va l'écrire ```{python} -print(df.filter(pl.col("var1")>=0)) # équivalent à -print(df.filter(pl.col.var1 >= 0)) +df.filter(pl.col("var1")>=0) # équivalent à +df.filter(pl.col.var1 >= 0) ``` Il y a deux manières de sélectionner une colonne : avec `pl.col("colname")` ou `pl.col.colname`. @@ -314,24 +314,42 @@ Exemple, pour garder uniquement les lignes où la colonne `experiment` a des val df.filter(pl.col("experiment").is_in(['train', 'validation'])) ``` +::: {.callout-important title="is_in recherche dans des séries ou des listes, pas dans des dataframes"} + +Si l'on veut filtrer avec `is_in` basée sur une série d'un dataframe, il faut que celui-ci soit au format séries. + +Il faut donc utiliser la syntaxe `df.filter(pl.col("experiment").is_in(other_df["experiment"]))` +et non `df.filter(pl.col("experiment").is_in(other_df.select("experiment")))`. +::: + Ces méthodes peuvent être combinées pour créer des conditions plus complexes. Il est aussi possible d'utiliser les opérateurs logiques (`&` pour "et", `|` pour "ou") pour combiner plusieurs conditions. Par défaut, les filtres sont considérés comme des "et" : filter(condA, condB) renverra quand condA et condB sont vraies. **Attention à ne pas oublier les parenthèses pour délimiter les conditions !** Exemple : + - sélectionner les lignes où `var1` est supérieur à 0 **et** `experiment` est égal à 'test' ou 'validation': ```{python} -df.filter((pl.col("var1") >= 0) & pl.col("experiment").is_in(['train', 'validation'])) +df.filter( + (pl.col("var1") >= 0) & + pl.col("experiment").is_in(['train', 'validation']) + ) # équivalent à -df.filter(pl.col("var1") >= 0, pl.col("experiment").is_in(['train', 'validation'])) +df.filter( + pl.col("var1") >= 0, + pl.col("experiment").is_in(['train', 'validation']) + ) ``` - sélectionner les lignes où `var1` est supérieur à 0 **ou** `experiment` est égal à 'test' ou 'validation': ```{python} -df.filter((pl.col("var1") >= 0) | pl.col("experiment").is_in(['train', 'validation'])) +df.filter( + (pl.col("var1") >= 0) | + pl.col("experiment").is_in(['train', 'validation']) + ) ``` :::::: {.callout-note} @@ -342,20 +360,24 @@ df.filter(pl.col("date").str.to_date("%Y-%m-%d").dt.day()==2) ``` ::: -# Explorer des données tabulaires + +# Importer et exporter des données En statistique publique, le point de départ n'est généralement pas la génération manuelle de données, mais plutôt des fichiers tabulaires préexistants. Ces fichiers, qu'ils soient issus d'enquêtes, de bases administratives ou d'autres sources, constituent la matière première pour toute analyse ultérieure. -Polars offre des outils puissants et très rapides pour importer ces fichiers tabulaires et les explorer en vue de manipulations plus poussées. +Polars offre des **outils puissants et très rapides** pour importer ces fichiers tabulaires et les explorer en vue de manipulations plus poussées. -## Importer et exporter des données +## Les types de données + +Polars est **très sensible au format des données**, l'import peut donc parfois être un peu long à débuger +quand il n'arrive pas à déterminer le format de données de la colonne. -Polars est très sensible au format des données, l'import peut donc parfois être un peu long à débuger quand il n'arrive pas à déterminer le format de données de la colonne. En effet, polars va traiter chaque colonne comme une série d'un des formats qu'il connaît. -Les formats de données sont détaillés dans la [documentation de polars](https://docs.pola.rs/api/python/stable/reference/datatypes.html). +Les **formats de données** sont détaillés dans la [documentation de polars](https://docs.pola.rs/api/python/stable/reference/datatypes.html). Ils comprennent principalement: -| Famille de format | Format polars | Remarques | + +| **Famille de format** | **Format polars** | **Remarques** | | -- | -- | -- | | Caractères | - `pl.String`
- `pl.Utf8` | les données catégorielles (`pl.Categorical`) sont encore peu matures dans polars.
Il peut donc mieux valoir les traiter simplement comme des caractères usuels. | | Nombres | | | @@ -363,21 +385,29 @@ Ils comprennent principalement: | - numérique | - `pl.Float16`
- `pl.Float32`
- `pl.Float64` | | | Temporelles | - `pl.Date`
- `pl.Datetime`
- `pl.Duration` ... | | | Structures imbriquées | | - le format `pl.Struc` très pratique pour lire des formats imbriqués comme des JSON | -| Valeurs manquantes | | polars traite les valeurs manquantes à part. | +| Valeurs manquantes | | polars traite les valeurs manquantes à part | + + +::: {.callout-caution title="Deux types de valeurs particulières"} -::: {.callout-caution} A noter que pour polars, les types `null` et `nan` sont différents. -`null` est une valeur manquante, quelque soit le type de valeur (caractère, numérique, temporelle, + +- `null` est une **valeur manquante**, quelque soit le type de valeur (caractère, numérique, temporelle, imbriquée ...). On le déclare avec un `None`. -`NaN`, qui signifie _Not a Number_, est une valeur manquante **numérique** (et non pour les entiers). +- `NaN`, qui signifie **_Not a Number_**, est une **valeur numérique particulière**, similaire au résultat +d'une opération mathématique interdite comme diviser par 0. +Elle existe **uniquement pour les données de type `float`** et non pour les entiers. Cela signifie que polars le traite comme un nombre particulier. On déclare un `NaN` soit en utilisant Numpy `np.nan`, soit une syntaxe de polars : `float("nan")`. Plus de détail sur la [documentation](https://docs.pola.rs/user-guide/expressions/missing-data/#null-and-nan-values). ::: -On peut convertir une colonne d'un type à l'autre avec la méthode `cast` en indiquant +## Convertir les données d'un type à l'autre + +On peut convertir une colonne d'un type à l'autre avec la **méthode `cast`** en indiquant dans un dictionnaire le nom de la colonne et le format polars souhaité. +Le dictionnaire est écrit sous le format `{'nom de la colonne 1':'type Polars à appliquer', 'nom de la colonne 2':'type Polars à appliquer'}`. Par exemple, dans la table `df` définie ci-dessus, polars a assigné les formats suivants : @@ -388,12 +418,20 @@ df.schema On peut convertir `var1` en caractère et `date` en un format temporel par exemple : ```{python} -df.cast({"var1":pl.String, "date":pl.Date}) +df.cast({"var1":pl.String, "date":pl.Date}) # équivalent à +df.with_columns( # on verra la méthode with_columns plus bas + pl.col("var1").cast(pl.String), + pl.col("date").cast(pl.Date) +) ``` -### Importer un fichier CSV -Comme nous l'avons vu dans un précédent TP, le format CSV est l'un des formats les plus courants pour stocker des données tabulaires. Nous avons précédemment utilisé la librairie `csv` pour les manipuler comme des fichiers texte, mais ce n'était pas très pratique. Pour rappel, la syntaxe pour lire un fichier CSV et afficher les premières lignes était la suivante : +## Importer un fichier CSV + +Comme nous l'avons vu dans un précédent TP, le **format CSV est l'un des formats les plus courants** pour stocker des données tabulaires. +Nous avons précédemment utilisé la librairie `csv` pour les manipuler comme des fichiers texte, +mais ce n'était pas très pratique. +Pour rappel, la syntaxe pour lire un fichier CSV et afficher les premières lignes était la suivante : ```{python} import csv @@ -408,27 +446,31 @@ with open("data/departement2021.csv") as file_in: rows[:5] ``` -Avec polars, il suffit d'utiliser la fonction `read_csv()` pour importer le fichier comme un dataframe, puis la fonction `head()`. +Avec polars, il suffit d'utiliser la fonction `read_csv()` pour importer le fichier comme un dataframe, +puis la méthode `head()`. ```{python} df_departements = pl.read_csv('data/departement2021.csv') df_departements.head() ``` -A la différence de pandas et à la date d'écriture de ce tutoriel, polars ne charge pas directement depuis une URL et ne dézippe pas encore automatiquement le fichier csv (_cf._ [discussion de cette problématique sur Github](https://github.com/pola-rs/polars/issues/19447)). -Soit on utilise la fonction idoine de pandas et après on transforme le dataframe en polars facilement grâce à la fonction `pl.from_pandas`. +A la différence de pandas et à la date d'écriture de ce tutoriel, polars ne charge pas directement +depuis une URL et ne dézippe pas encore automatiquement le fichier csv (_cf._ [discussion de cette problématique sur Github](https://github.com/pola-rs/polars/issues/19447)). +On peut utiliser la fonction idoine de pandas et après transformer en polars dataframe facilement grâce à la fonction `pl.from_pandas`. ```{python} import pandas as pd url = "https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip" -pl.from_pandas(pd.read_csv(url, delimiter=";")) +df_prenoms_url = pl.from_pandas(pd.read_csv(url, delimiter=";")) ``` + +::: {.callout-tip title="Eviter pandas"} + Si l'on veut éviter une dépendance à pandas juste pour cette opération, il faut donc faire ces étapes soi-même pour le moment grâce aux packages `requests`et `zipfile`. Prenons l'exemple d'un fichier CSV disponible sur le site de l'INSEE : le fichier des prénoms, issu des données de l'état civil. ```{python} -#| eval: false import requests # Téléchargement et stockage du nom du fichier @@ -449,8 +491,10 @@ with ZipFile(file_Path, 'r') as zObject: ``` -Par exemple, une erreur sera causée ici à cause de types de données incohérentes détectées par polars. -En regardant le message d'erreur, polars traite la colonne `annais` comme un entier. +::: + +Par exemple, une erreur sera causée ici à cause d'un type de données incohérentes détecté par polars. +En regardant le message d'erreur, polars traite en effet la colonne `annais` comme un entier. Mais la lecture de la valeur `XXXX` cause une erreur et n'est pas convertible en entier par polars. ```{python} @@ -460,10 +504,11 @@ df_prenoms_url = pl.read_csv('temp/' + os.listdir('temp')[0], separator=";") ``` Dans ce cas, deux solutions existent : -- On peut dire à polars de traiter toutes les colonnes comme des caractères avec infer_schema=False + +- On peut dire à polars de traiter toutes les colonnes comme des caractères avec `infer_schema=False`. +On voit bien alors dans la deuxième ligne que **toutes les colonnes sont des caractères**. ```{python} -import os df_prenoms_url = pl.read_csv('temp/' + os.listdir('temp')[0], separator=";", infer_schema=False) df_prenoms_url ``` @@ -477,21 +522,23 @@ df_prenoms_url = pl.read_csv('temp/'+os.listdir('temp')[0], separator=";", null_ df_prenoms_url ``` -Lorsqu'on travaille avec des fichiers CSV, il y a de nombreux arguments optionnels disponibles dans la fonction `read_csv()` qui permettent d'ajuster le processus d'importation en fonction des spécificités du fichier. -Ces arguments peuvent notamment permettre de définir un délimiteur spécifique (comme ci-dessus pour le fichier des prénoms), de sauter certaines lignes en début de fichier, ou encore de définir les types de données pour chaque colonne, et bien d'autres. +Lorsqu'on travaille avec des fichiers CSV, il y a de **nombreux arguments optionnels disponibles dans la fonction `read_csv()`** +qui permettent d'ajuster le processus d'importation en fonction des spécificités du fichier. +Ces arguments peuvent notamment permettre de définir un délimiteur spécifique (comme ci-dessus pour le fichier des prénoms), +de sauter certaines lignes en début de fichier, ou encore de définir les types de données pour chaque colonne, et bien d'autres. Tous ces paramètres et leur utilisation sont détaillés dans la [documentation officielle](https://docs.pola.rs/api/python/stable/reference/api/polars.read_csv.html#polars.read_csv). ```{python} -#| eval: false +#| echo: false # Pour nettoyer les fichiers !rm $file_Path !rm temp -rf ``` -### Exporter au format CSV +## Exporter au format CSV -Une fois que les données ont été traitées et modifiées au sein de polars, il est courant de vouloir exporter le résultat sous forme de fichier CSV pour le partager, l'archiver ou l'utiliser dans d'autres outils. +Une fois que les données ont été traitées et modifiées au sein de polars, il est courant de vouloir **exporter le résultat sous forme de fichier CSV** pour le partager, l'archiver ou l'utiliser dans d'autres outils. Polars offre une méthode simple pour cette opération : `write_csv()`. Supposons par exemple que l'on souhaite exporter les données du dataframe `df_departements` spécifiques aux cinq départements d'outre-mer. @@ -501,22 +548,21 @@ df_departements_dom.write_csv('output/departements2021_dom.csv', separator=";") ``` -### Importer un fichier Parquet +## Importer un fichier Parquet Le format Parquet est un autre format pour le stockage de données tabulaires, de plus en plus fréquemment utilisé. Sans entrer dans les détails techniques, le format Parquet présente différentes caractéristiques qui en font un choix privilégié pour le stockage et le traitement de gros volumes de données. En raison de ces avantages, ce format est de plus en plus utilisé pour la mise à disposition de données à l'Insee. Il est donc essentiel de savoir importer et requêter des fichiers Parquet avec polars. -Importer un fichier Parquet dans un dataframe pandas se fait tout aussi facilement que pour un fichier CSV. -La fonction se nomme `read_parquet()`. +Importer un fichier Parquet dans un dataframe polars se fait tout aussi facilement que pour un fichier CSV grâce à la **fonction `read_parquet()`**. ```{python} df_departements = pl.read_parquet('data/departement2021.parquet') df_departements.head() ``` -### Exporter au format Parquet +## Exporter au format Parquet Là encore, tout se passe comme dans le monde des CSV : on utilise la méthode `write_parquet()` pour exporter un dataframe dans un fichier Parquet. @@ -525,8 +571,8 @@ df_departements_dom = df_departements.filter(pl.col("DEP").is_in(["971", "972", df_departements_dom.write_parquet('output/departements2021_dom.parquet') ``` -Une des grandes forces du format Parquet, en comparaison des formats texte comme le CSV, est sa capacité à stocker des méta-données, i.e. des données permettant de mieux comprendre les données contenues dans le fichier. -En particulier, un fichier Parquet inclut dans ses méta-données le schéma des données (noms des variables, types des variables, etc.), ce qui en fait un format très adapté à la diffusion de données. +Une des grandes forces du format Parquet, en comparaison des formats texte comme le CSV, est sa capacité à **stocker des méta-données**, i.e. des données permettant de mieux comprendre les données contenues dans le fichier. +En particulier, un fichier Parquet inclut dans ses méta-données le **schéma des données** (noms des variables, types des variables, etc.), ce qui en fait un format très adapté à la diffusion de données. Vérifions ce comportement en reprenant le dataframe que nous avons défini précédemment. ```{python} @@ -555,7 +601,7 @@ On verra plus loin dans le tutoriel comment utiliser ces types. df ``` -Vérifions à présent que l'export et le ré-import de ces données en Parquet préserve le schéma. +Vérifions à présent que **l'export et le ré-import de ces données en Parquet** préserve le schéma. ```{python} df.write_parquet("output/df_test_schema.parquet") @@ -564,8 +610,8 @@ df_test_schema_parquet = pl.read_parquet('output/df_test_schema.parquet') df_test_schema_parquet ``` -A l'inverse, un fichier CSV ne contenant par définition que du texte, ne permet pas de préserver ces données. -Les variables dont nous avons spécifié le type sont importées comme des strings (type `object` en polars). +A l'inverse, **un fichier CSV ne contenant par définition que du texte, ne permet pas de préserver ces données**. +Les variables dont nous avons spécifié le type sont importées comme des caractères (type `object` en polars). ```{python} df.write_csv("output/df_test_schema.csv") @@ -574,9 +620,9 @@ df_test_schema_csv = pl.read_csv('output/df_test_schema.csv') df_test_schema_csv ``` -### Importer depuis un dictionnaire +## Importer depuis un dictionnaire -Comme illustré dans le tutoriel [Travailler avec des fichiers CSV et JSON](../csv-json-files/tutorial.qmd), on peut aussi créer un dataFrame polars à partir d'un dictionnaire. +Comme illustré dans le tutoriel [Travailler avec des fichiers CSV et JSON](../csv-json-files/tutorial.qmd), on peut aussi créer un dataframe polars à partir d'un dictionnaire. Cela sera très utile par exemple quand on récupère les données d'une API (_cf._ cours de [Python pour la data-science](https://pythonds.linogaliana.fr/) et la partie sur les API). @@ -584,32 +630,35 @@ Les méthodes `from_dict` et `from_dicts` permettent de créer des dataframes à - `from_dict` prend comme argument un **dictionnaire des colonnes**, de manière similaire à `pl.DataFrame` : on va écrire par exemple `pl.from_dict({"a": [1, 2], "b": [3, 4]})` -- `from_dicts` par contre prend comme argument une **liste des lignes** : on va écrire par exemple `pl.from_dicts([{"a": 1, "b": 4}, {"a": 2, "b": 5}, {"a": 3, "b": 6}])` +- `from_dicts` par contre prend comme argument une **liste des lignes** définies chacune comme un dictionnaire: on va écrire par exemple `pl.from_dicts([{"a": 1, "b": 4}, {"a": 2, "b": 5}, {"a": 3, "b": 6}])` + +Par exemple, ```{python} -import requests import json response = requests.get("https://data.geopf.fr/geocodage/search?q=comedie&type=street") ``` -Le résultat de la requête est un dictionnaire avec 3 clés, dont la deuxième, 'features', stocke les résultats sous forme d'une liste. -Pour importer directement ce fichier en polars, on peut utiliser la méthode from_dict ou from_dicts. +Si l'on clique sur le [lien de la requête](https://data.geopf.fr/geocodage/search?q=comedie&type=street), on voit que le résultat de la requête est **un dictionnaire avec 3 clés** : type, features et query. La deuxième clé, 'features', stocke les résultats sous forme d'une liste de 10 éléments. +Pour importer directement ce fichier en polars, on peut utiliser l'une ou l'autre des méthodes `from_dict` ou `from_dicts`. ```{python} df = pl.from_dicts(json.loads(response.text)) -df.head(2) +df.head(1) ``` -On retrouve dans le dataframe les trois colonnes dont la clé représente le nom de la colonne et la valeur dans le dictionnaire la valeur dans la colonne. +On retrouve dans le dataframe les **trois colonnes** dont la clé représente le nom de la colonne et la valeur dans le dictionnaire la valeur dans la colonne. La première et dernière colonnes sont des valeurs constantes au format `pl.String` et les résultats sont stockés dans la colonne `features`. -Cette dernière est au format `pl.Struct`, qui fonctionne de manière similaire à un dictionnaire. +Cette dernière est au **format `pl.Struct`**, qui fonctionne de manière similaire à un dictionnaire. -::: {.callout-tip} +::: {.callout-tip title="Travailler avec des JSON facilement grâce à unnest()"} La méthode `unnest` est **très pratique** en travaillant avec des formats JSON. Elle permet facilement de passer d'un format structuré à un format plus standard (numérique ou textuel). -Ainsi, pour récupérer le détail des résultats de l'appel à l'API, il suffit d'utiliser la méthode `unnest`. -On l'applique à plusieurs reprises et on veille à supprimer les colonnes intermédiaires qui ont des noms identiques pour *applatir* le data frame: + +Ainsi, pour récupérer le détail des résultats de l'appel à l'API, il suffit de l'appliquer à plusieurs reprises. +On veille à supprimer les colonnes intermédiaires qui ont des noms identiques. +On obtient ainsi facilement un dataframe plat: ```{python} df = df.select("features").unnest("features").drop("type").unnest("geometry").drop("type").unnest("properties") @@ -617,7 +666,7 @@ df = df.select("features").unnest("features").drop("type").unnest("geometry").dr ::: -### Autres exports et imports +## Autres exports et imports - **Exporter vers un dictionnaire**: De manière similaire, polars permet d'exporter un dataframe vers un dictionnaire. @@ -631,7 +680,7 @@ représentées à chaque fois par un dictionnaire : `[{'a': 1, 'b': 3}, {'a': 2, - **Depuis/vers pandas**: Polars permet aussi facilement d'exporter et d'importer des dataframe au format pandas. -Cela permet de travailler avec polars et de convertir un dataframe en pandas quand un package n'autorise pas l'import depuis polars. +Cela permet de travailler avec polars et de convertir le résultat en un dataframe pandas quand un package n'autorise pas l'import depuis polars. Il suffit d'utiliser la fonction `pl.from_pandas(df)` pour importer un dataframe pandas en polars. La méthode `df.to_pandas()` permettra d'exporter un polars dataframe vers pandas. @@ -641,13 +690,13 @@ Lorsqu'on travaille avec des jeux de données volumineux, il est souvent utile d des données pour avoir une idée de leur structure, de leur format ou encore pour détecter d'éventuels problèmes. Polars offre plusieurs méthodes pour cela. -Par défaut, polars indique les cinq premières et cinq dernières lignes d'un dataframe et indique la forme (_shape_). +Par défaut, **polars indique les cinq premières et cinq dernières lignes d'un dataframe, indique la forme (_shape_) et le type des colonnes**. ```{python} df_departements ``` -La méthode `head()` permet d'afficher les premières lignes du dataframe. +La méthode `head()` permet d'**afficher les premières lignes** du dataframe. Par défaut, elle retourne les 5 premières lignes, mais on peut spécifier un autre nombre en argument si nécessaire. ```{python} @@ -658,13 +707,14 @@ df_departements.head() df_departements.head(10) ``` -À l'inverse, la méthode `tail()` donne un aperçu des dernières lignes du dataframe. +À l'inverse, la méthode **`tail()` donne un aperçu des dernières lignes** du dataframe. ```{python} df_departements.tail() ``` -L'affichage des premières ou dernières lignes peut parfois ne pas être représentatif de l'ensemble du jeu de données, lorsque les données sont triées par exemple. Afin de minimiser le risque d'obtenir un aperçu biaisé des données, on peut utiliser la méthode `sample()`, qui sélectionne un un échantillon aléatoire de lignes. Par défaut, elle retourne une seule ligne, mais on peut demander un nombre spécifique de lignes en utilisant l'argument `n`. +L'affichage des premières ou dernières lignes peut parfois ne pas être représentatif de l'ensemble du jeu de données, lorsque les données sont triées par exemple. +Afin de minimiser le risque d'obtenir un aperçu biaisé des données, on peut utiliser la méthode `sample()`, qui **sélectionne un un échantillon aléatoire de lignes**. Par défaut, elle retourne une seule ligne, mais on peut demander un nombre spécifique de lignes en utilisant l'argument `n` ou une proportion du dataframe. ```{python} df_departements.sample(n=5) @@ -672,7 +722,7 @@ df_departements.sample(n=5) ## Obtenir une vue d'ensemble des données -L'une des premières étapes lors de l'exploration de nouvelles données est de comprendre la structure générale du jeu de données. +L'une des premières étapes lors de l'exploration de nouvelles données est de comprendre la **structure générale du jeu de données**. La méthode `glimpse()` de polars offre une vue d'ensemble rapide des données, notamment en termes de types de données et affiche les données. ```{python} @@ -691,14 +741,14 @@ Plusieurs éléments d'information clés peuvent être extraits de ce résultat - **les premières valeurs** : après chaque colonne sont indiquées, à l'horizontale, les premières valeurs de la colonne. Cela permet de mieux comprendre le schéma du dataframe. -Contrairement à pandas, cette méthode n'affiche pas les valeurs manquantes. +Contrairement à pandas, cette méthode **n'affiche pas les valeurs manquantes**. Pour cela, il faut utiliser les statistiques descriptives. ## Calculer des statistiques descriptives En complément des informations renvoyées par la méthode `glimpse()`, on peut vouloir obtenir des statistiques descriptives simples afin de visualiser rapidement les distributions des variables. -La méthode `describe()` permet d'avoir une vue synthétique de la distribution des données dans chaque colonne. +La **méthode `describe()` permet d'avoir une vue synthétique de la distribution** des données dans chaque colonne et des valeurs manquantes. ```{python} df.describe() @@ -718,15 +768,14 @@ Les transformations peuvent concerner l'ensemble du dataframe, des colonnes spé ### Transformer les colonnes En équivalent de `mutate` du tidyverse ou du `replace` de pandas, polars utilise `with_columns`. -Le fonctionnement est similaire au `mutate` du tidyverse. +Le fonctionnement est cependant plus similaire au `mutate` du tidyverse. Il permet ainsi de modifier des valeurs de colonne, d'effectuer des opérations etc. +La méthode `with_columns()` fonctionne de deux manières différentes : -La fonction with_columns fonctionne de deux manières différentes : - - 1. en utilisant une syntaxe plus proche du SQL et de Python, grâce à la méthode `.alias()`. - 2. plus similaire au tidyverse, en assignant les variables avec une équation +- en utilisant une syntaxe plus proche du SQL et de Python, grâce à la méthode `.alias()` ; +- plus similaire au tidyverse, en assignant les variables avec une équation. Par exemple, si l'on veut définir la colonne `b` comme la colonne `a` divisée par 2 , on va utiliser la formule suivante : @@ -745,10 +794,10 @@ df.with_columns( ``` -::: {.callout-tip} -La structure `pl.when` est très pratique et équivaut à la structure `ifelse` en R. +::: {.callout-tip title="Equivalent de if/else"} +La fonction `pl.when` est très pratique et équivaut à la structure `ifelse` en R. -Par exemple, si je veux définir la colonne val à partir de la colonne foo selon le schéma : si foo > 2 : val = 1, sinon val = 1 + bar, cela s'écrite en polars : +Par exemple, si je veux définir la colonne val à partir de la colonne foo, cela s'écrit en polars : ```{python} @@ -760,68 +809,51 @@ df.with_columns( ::: -::: {.callout-warning} +::: {.callout-warning title="Les caractères sont des colonnes"} Attention, en polars, les caractères simples sont assimilés aux colonnes. -Pour insérer un caractère, utiliser pl.lit. +Pour insérer un caractère, utiliser `pl.lit`. ```{python} df = pl.DataFrame({'foo':np.random.randint(-10, 10, 6), 'bar': np.random.randint(5, 15, 6)}) df.with_columns( - val="foo", - this_is_foo=pl.lit("foo") + val="foo", # les colonnes val et foo seront identiques + this_is_foo=pl.lit("foo") # la colonne this_is_foo sera un mot "foo" ) ``` ::: -La méthodes fill_null permet de remplacer les valeurs manquante -```{python} -df.fill_null(strategy='zero') -``` +On peut aussi utiliser les `selectors` de polars pour faire des opérations groupées sur un ensemble de colonnes. +Il suffit de remplacer le `pl.col("mycol")` par le sélecteur recherché. +Pour modifier les noms des colonnes, on peut utiliser les fonctions liées aux méthodes `Expr.name`, *cf.* [documentation officielle](https://docs.pola.rs/api/python/stable/reference/expressions/name.html). -Mais il existe d'autres transformations que l'on applique généralement au niveau d'une ou de quelques colonnes. Par exemple, lorsque le schéma n'a pas été bien reconnu à l'import, il peut arriver que des variables numériques soient définies comme des string. +Par exemple, si l'on veut normaliser toutes les colonnes numériques, on peut le faire en une ligne en spécifiant uniquement la colonne de référence : ```{python} + df = pl.DataFrame( data = { "var1": [1.3, 5.6, None], - "var2": ["1", "5", "18"], + "var2": [1, 5, 18], } ) -df.glimpse() -``` - -Dans ce cas, on peut utiliser la méthode `cast` pour convertir la colonne dans le type souhaité en spécifiant avec un dictionnaire les colonnes à modifier. -Le dictionnaire est écrit sous le format `{'nom de la colonne 1':'type Polars à appliquer', 'nom de la colonne 2':'type Polars à appliquer'}`. -Les types sont décrits plus haut et dans la [documentation de polars](https://docs.pola.rs/api/python/stable/reference/datatypes.html). - -```{python} -df = df.cast({'var2':pl.Int32}) - -df.glimpse() -``` - - -On peut aussi utiliser les `selectors` de polars pour faire des opérations groupées sur un ensemble -de colonnes. -Il suffit de remplacer le `pl.col("mycol")` par le sélecteur recherché. -Pour modifier les noms en série, on peut utiliser les fonctions liées aux méthodes `Expr.name`, *cf.* [documentation officielle](https://docs.pola.rs/api/python/stable/reference/expressions/name.html). - -Par exemple, si l'on veut normaliser à 1 toutes les colonnes numériques, on peut le faire en une ligne en spécifiant uniquement la colonne de référence : +df.with_columns( + (cs.numeric() / pl.col("var2")) # va remplacer var1 et var2 par var1 et var2 normalisés par var2 +) -```{python} df.with_columns( - (cs.numeric() / pl.col("var2")).name.suffix("_norm") + (cs.numeric() / pl.col("var2")).name.suffix("_norm") # va normaliser les colonnes var1 et var2 en var1_norm et var2_norm ) ``` ### Renommer des colonnes -Une autre opération fréquente est le renommage d'une ou plusieurs colonnes. Pour cela, on peut utiliser la méthode [rename()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.rename.html#polars.DataFrame.rename), à laquelle on passe un dictionnaire qui contient autant de couples clé-valeur que de variables à renommer, et dans lequel chaque couple clé-valeur est de la forme `'ancien_nom': 'nouveau_nom'`. +Une autre opération fréquente est le renommage d'une ou plusieurs colonnes. +Pour cela, on peut utiliser la **méthode** [**rename()**](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.rename.html#polars.DataFrame.rename), à laquelle on passe un dictionnaire qui contient autant de couples clé-valeur que de variables à renommer, et dans lequel chaque couple clé-valeur est de la forme `{'ancien_nom': 'nouveau_nom'}`. ```{python} df.rename({'var2': 'age'}) @@ -830,8 +862,10 @@ df.rename({'var2': 'age'}) ### Fonctions complexes -Néanmoins, on peut se retrouver dans certains (rares) cas où une opération ne peut pas être facilement vectorisée ou où la logique est complexe. -Supposons par exemple que l'on souhaite calculer la variation annuelle du PIB par pays dans une table comportant les pays et les années. +Néanmoins, on peut se retrouver dans certains (rares) cas où une opération ne peut pas être facilement vectorisée. +On peut alors appliquer une fonction définie par l'utilisateur (UDF) grâce à `map_groups()`. + +Supposons par exemple que l'on souhaite calculer **la variation annuelle du PIB par pays** dans une table comportant les pays et les années. ```{python} # Données fictives de PIB par pays @@ -854,10 +888,21 @@ print(df.group_by("country").map_groups(calculate_percentage_change)) ``` +::: {.callout-note title="Exemple fictif"} + +Cet exemple est facilement vectorisable en fait avec les méthodes `pct_change()` et `over()` de polars : + +```{.python} +df.sort("year").with_columns( + pl.col("gdp").pct_change(1).alias("pct_change").over("country") + ) +``` +::: ## Trier les valeurs -Le tri des données est particulièrement utile pour l'exploration et la visualisation de données. Avec polars, on utilise la méthode [sort()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.sort.html#polars.DataFrame.sort) pour trier les valeurs d'un dataframe selon une ou plusieurs colonnes. +Le tri des données est particulièrement utile pour l'exploration et la visualisation de données. +Avec polars, on utilise la **méthode [sort()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.sort.html#polars.DataFrame.sort)** pour trier les valeurs d'un dataframe selon une ou plusieurs colonnes. ```{python} df = pl.DataFrame( @@ -877,13 +922,15 @@ Pour trier les valeurs selon une seule colonne, il suffit de passer le nom de la df.sort(by='var1") ``` -Par défaut, le tri est effectué dans l'ordre croissant. Pour trier les valeurs dans un ordre décroissant, il suffit de paramétrer `descending=True`. +Par défaut, le tri est effectué dans **l'ordre croissant**. +Pour trier les valeurs dans un ordre décroissant, il suffit de paramétrer `descending=True`. ```{python} df.sort(by='var1', descending=True) ``` -Si on souhaite trier le dataframe sur plusieurs colonnes, on peut fournir une liste de noms de colonnes. On peut également choisir de trier de manière croissante pour certaines colonnes et décroissante pour d'autres en spécifiant les booléns dans une liste. +Si on souhaite trier le dataframe sur **plusieurs colonnes**, on peut fournir une liste de noms de colonnes. +On peut également choisir de trier de manière croissante pour certaines colonnes et décroissante pour d'autres en spécifiant les booléns dans une liste. ```{python} df.sort(by=['var1', 'var2'], descending=[True, True]) @@ -892,7 +939,8 @@ df.sort(by=['var1', 'var2'], descending=[True, True]) ## Agréger des données -L'agrégation des données est un processus dans lequel les données vont être ventilées en groupes selon certains critères, puis agrégées selon une fonction d'agrégation appliquée indépendamment à chaque groupe. Cette opération est courante lors de l'analyse exploratoire ou lors du prétraitement des données pour la visualisation ou la modélisation statistique. +L'agrégation des données est un processus dans lequel les données vont être ventilées en groupes selon certains critères, puis agrégées selon une fonction d'agrégation appliquée indépendamment à chaque groupe. +Cette opération est courante lors de l'analyse exploratoire ou lors du prétraitement des données pour la visualisation ou la modélisation statistique. ```{python} df = pl.DataFrame( @@ -910,7 +958,10 @@ df.head() ### L'opération `group_by` -La méthode `group_by` de polars permet de diviser le dataframe en sous-ensembles selon les valeurs d'une ou plusieurs colonnes, puis d'appliquer une fonction d'agrégation à chaque sous-ensemble. Elle renvoie un objet de type `dataframe.group_by` qui ne présente pas de grand intérêt en soi, mais constitue l'étape intermédiaire indispensable pour pouvoir ensuite appliquer une ou plusieurs fonction(s) d'agrégation aux différents groupes. +La méthode `group_by` permet de diviser le dataframe en sous-ensembles selon les valeurs d'une ou plusieurs colonnes, puis d'appliquer une fonction d'agrégation à chaque sous-ensemble. +Elle renvoie un objet de type `dataframe.group_by` qui ne présente pas de grand intérêt en soi, mais constitue l'étape intermédiaire indispensable pour pouvoir ensuite appliquer une ou plusieurs fonction(s) d'agrégation aux différents groupes. +L'objet renvoyé n'est ainsi pas un dataframe polars classique : cela veut dire qu'on ne pourra pas lui appliquer +les mêmes méthodes. ```{python} df.group_by("experiment") @@ -918,69 +969,67 @@ df.group_by("experiment") ### Fonctions d'agrégation -Une fois les données groupées, on peut appliquer des fonctions d'agrégation pour obtenir un résumé statistique. polars intègre un certain nombre de ces fonctions qui fonctionnent sur la table de donnée entière, *cf.* [liste complète dans la documentation](https://docs.pola.rs/api/python/stable/reference/dataframe/aggregation.html) ou sur des sous-ensembles de la table, en utilisant `group_by`, *cf.* [liste complète dans la documentation](https://docs.pola.rs/api/python/stable/reference/dataframe/group_by.html). +Une fois les données groupées, on peut appliquer des fonctions d'agrégation pour obtenir un résumé statistique. +Polars intègre un certain nombre de ces fonctions qui fonctionnent sur la table de donnée entière, *cf.* [liste complète dans la documentation](https://docs.pola.rs/api/python/stable/reference/dataframe/aggregation.html) ou sur des sous-ensembles de la table, en utilisant `group_by`, *cf.* [liste complète dans la documentation](https://docs.pola.rs/api/python/stable/reference/dataframe/group_by.html). Voici quelques exemples d'utilisation de ces méthodes avec `group_by`. -Par défaut, polars appliquera les fonctions usuelles à l'ensemble des colonnes. -Pour spécifier une colonne, il faut utiliser la fonction `agg`, détaillée plus bas. +Polars peut appliquer certaines méthodes usuelles à l'ensemble des colonnes par défaut. - Par exemple, compter le nombre d'occurrences dans chaque groupe. ```{python} -df.group_by("experiment").count() +df.group_by("experiment").len() ``` -- Calculer la somme d'une variable par groupe. - -```{python} -df.group_by("experiment").agg(pl.col("var2").sum()) -``` +- Les autres méthodes appliquées directement à un datagrame groupé sont listées dans la [documentation](https://docs.pola.rs/api/python/stable/reference/dataframe/group_by.html) mais comprennent les min, max, median, first, last, n_unique ... -::: {.callout-tip} -Polars a aussi introduit des wrappers utiles pour les fonctions principales d'aggregation sum, std, count, quantile, cum_count, cum_sum, max, min, median, sqrt. -Pour ces fonctions, on peut les appeler directement en faisant `pl.sum("var2")` et non `pl.col("var2").sum()`. +Pour d'autres méthodes, appliquer plusieurs fonctions d'agrégation à la fois, ou pour spécifier une colonne, il faut utiliser la méthode `agg`. +Cette méthode fonctionne selon une structure similaire à `with_columns`. Par exemple : -```{.python} -df.group_by("experiment").agg(pl.sum("var2")) -``` -est identique à : -```{.python} +- pour calculer la somme d'une variable par groupe on va : + +```{python} df.group_by("experiment").agg(pl.col("var2").sum()) ``` -::: - -- Ou encore compter le nombre de valeurs unique d'une variable par groupe. Les possibilités sont nombreuses. - +- Pour calculer le nombre de valeurs uniques de "var2" par type d'expérience : ```{python} # Pour le nombre de valeurs uniques dans chaque groupe df.group_by("experiment").agg(pl.col("var2").n_unique()) ``` -Lorsqu'on souhaite appliquer plusieurs fonctions d'agrégation à la fois ou des fonctions personnalisées, on utilise la méthode `agg`. Cette méthode fonctionne selon une structure similaire à `with_columns`. Elle permet de définir plus finement les fonctions d'agrégation. - +- Pour calculer par type d'expérience le nombre de valeurs de "var2" et la moyenne de "var1" : ```{python} df.group_by("experiment").agg( pl.col("var1").mean().alias('mean_var1"), - pl.col("var2").count().alias('count_var2") + pl.col("var2").len().alias('count_var2") ) ``` -::: {.callout-tip} -Au lieu d'utiliser la méthode alias, on peut utiliser l'attribut `name` de polars qui renvoie le nom de la colonne et les fonctions associées. Plus de détails sont présentés dans la [documentation officielle](https://docs.pola.rs/api/python/stable/reference/expressions/name.html). +::: {.callout-tip title="Wrapper pour aggréger"} +Polars a introduit des wrappers utiles pour les fonctions principales d'aggrégation sum, std, len, quantile, cum_count, cum_sum, max, min, median, sqrt. + +Pour ces fonctions, on peut les appeler directement en faisant `pl.median("var2")` et non `pl.col("var2").median()`. -Par exemple, définir `.alias('mean_var1")` est l'équivalent de `.name.prefix('mean_")` +```{python} +df.group_by("experiment").agg(pl.col("var2").sum()) # équivalent à +df.group_by("experiment").agg(pl.sum("var2")) +``` ::: + ::: {.callout-note title="Le chaînage de méthodes"} -Les exemples précédents illustrent un concept important en polars : le chaînage de méthodes. Ce terme désigne la possibilité d'enchaîner les transformations appliquées à un dataframe en lui appliquant à la chaîne des méthodes, comme le `pipe` du tidyverse. A chaque méthode appliquée, un dataframe intermédiaire est créé (mais non assigné à une variable), qui devient l'input de la méthode suivante. +Les exemples précédents illustrent un concept important en polars : le chaînage de méthodes. +Ce terme désigne la possibilité d'enchaîner les transformations appliquées à un dataframe en lui appliquant à la chaîne des méthodes, comme le `pipe` du tidyverse. +A chaque méthode appliquée, un dataframe intermédiaire est créé (mais non assigné à une variable), qui devient l'input de la méthode suivante. -Le chaînage de méthodes permet de combiner plusieurs opérations en une seule expression de code. Cela peut améliorer l'efficacité en évitant les assignations intermédiaires et en rendant le code plus fluide et plus facile à lire. +Le chaînage de méthodes permet de combiner plusieurs opérations en une seule expression de code. +Cela peut améliorer l'efficacité en évitant les assignations intermédiaires et en rendant le code plus fluide et plus facile à lire. Cela favorise également un style de programmation fonctionnel où les données passent à travers une chaîne de transformations de manière fluide. ```{.python} @@ -1199,12 +1248,12 @@ df = pl.DataFrame( "experiment": ["test", "train", "test", None, "train", "validation"], } ) -print(df.dtypes) +df.dtypes ``` ```{python} df = df.with_columns(pl.col("experiment").cast(pl.Categorical)) -print(df.dtypes) +df.dtypes ``` Les `Categories` ont un certain nombre de méthodes, tout comme les données textuelles, présentées dans la [documentation](https://docs.pola.rs/api/python/stable/reference/series/categories.html). @@ -1625,7 +1674,7 @@ Utilisez les méthodes appropriées parmi `filter`, `select`, `head` pour sélec Afficher la solution ```{python} -print(df.head(1)) +df.head(1) ``` @@ -1645,7 +1694,7 @@ print(df.head(1)) Afficher la solution ```{python} -print(df.select("prix")) +df.select("prix") ``` @@ -1665,7 +1714,7 @@ print(df.select("prix")) Afficher la solution ```{python} -print(df.filter(pl.col("enseigne") == 'Carrefour')) +df.filter(pl.col("enseigne") == 'Carrefour') ``` @@ -1709,7 +1758,7 @@ print( Afficher la solution ```{python} -print(df.select("enseigne", "prix")) +df.select("enseigne", "prix") ``` @@ -1729,7 +1778,7 @@ print(df.select("enseigne", "prix")) Afficher la solution ```{python} -print(df.filter(pl.col("quantite") > 5)) +df.filter(pl.col("quantite") > 5) ``` @@ -1749,7 +1798,7 @@ print(df.filter(pl.col("quantite") > 5)) Afficher la solution ```{python} -print(df.filter(pl.col("date_heure").dt.hour() > 15)) +df.filter(pl.col("date_heure").dt.hour() > 15) ``` @@ -1769,7 +1818,7 @@ print(df.filter(pl.col("date_heure").dt.hour() > 15)) Afficher la solution ```{python} -print(df.filter(pl.col("date_heure").dt.date() == pl.Series(['2022-01-03']).str.to_date())) +df.filter(pl.col("date_heure").dt.date() == pl.Series(['2022-01-03']).str.to_date()) ``` @@ -1804,7 +1853,7 @@ df_prenoms = pl.from_pandas(pd.read_csv(url, sep=";")) df_prenoms.head(10) df_prenoms.sample(n=50) -print(df_prenoms.describe()) +df_prenoms.describe() ``` @@ -1838,6 +1887,7 @@ prop_rares1 = ( .item(0, "tot_rel") ) print(prop_rares1) # ~ 2 % de la base + # equivalent à prop_rares2 = ( df_prenoms From 2a06f33a171867c7caf21dbfa3014a026a5da0b5 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 25 Feb 2026 17:28:18 +0000 Subject: [PATCH 55/92] transfer import at first cell --- source/manipulation/polars/tutorial.qmd | 46 ++++++++++++++----------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index a917e549..1854b77e 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -96,6 +96,13 @@ import polars.selectors as cs import numpy as np # Numpy reste nécessaire pour certaines fonctionnalités utiles ``` +```{python} +#| echo: false +import os +import requests +import json +from zipfile import ZipFile # zipfile permet de dézipper les fichiers +``` ::: {.callout-note} @@ -352,7 +359,7 @@ df.filter( ) ``` -:::::: {.callout-note} +:::::: {.callout-note title="Filtrer avec une condition calculée"} La méthode `filter` marche aussi sur des calculs à base des colonnes. Par exemple, si l'on veut sélectionner les observations faites le 2 du mois, on peut effectuer cela en une ligne (on verra plus tard le travail sur les données temporelles): ```{python} @@ -378,19 +385,21 @@ Ils comprennent principalement: | **Famille de format** | **Format polars** | **Remarques** | -| -- | -- | -- | -| Caractères | - `pl.String`
- `pl.Utf8` | les données catégorielles (`pl.Categorical`) sont encore peu matures dans polars.
Il peut donc mieux valoir les traiter simplement comme des caractères usuels. | -| Nombres | | | -| - entiers | - `pl.Int8`
- `pl.Int16`
- `pl.Int32` ... | | -| - numérique | - `pl.Float16`
- `pl.Float32`
- `pl.Float64` | | -| Temporelles | - `pl.Date`
- `pl.Datetime`
- `pl.Duration` ... | | -| Structures imbriquées | | - le format `pl.Struc` très pratique pour lire des formats imbriqués comme des JSON | -| Valeurs manquantes | | polars traite les valeurs manquantes à part | - +|:----|:---|:---------| +| **Caractères** | - `pl.String`
- `pl.Utf8` | Type le plus courant | +| **Catégories** | - `pl.Category` | Encore peu matures. Il peut donc mieux valoir les traiter simplement comme des caractères usuels. | +| **Nombres** | | | +| - *entiers* | - `pl.Int8`
- `pl.Int16`
- `pl.Int32` ... | Type le plus courant | +| - *numérique* | - `pl.Float16`
- `pl.Float32`
- `pl.Float64` | Type le plus courant | +| **Temporelles** | - `pl.Date`
- `pl.Datetime`
- `pl.Duration` ... | Type le plus courant, inspiré de `datetime` | +| **Structures imbriquées** | - `pl.Struc`
- `pl.List` | le format `pl.Struc` très pratique pour lire des formats imbriqués comme des JSON | +| **Valeurs manquantes** | `Null` ou `NaN` | polars traite les valeurs manquantes à part | + +: Type de données dans polars ::: {.callout-caution title="Deux types de valeurs particulières"} -A noter que pour polars, les types `null` et `nan` sont différents. +Pour polars, les types `null` et `nan` sont différents. - `null` est une **valeur manquante**, quelque soit le type de valeur (caractère, numérique, temporelle, imbriquée ...). On le déclare avec un `None`. @@ -459,6 +468,7 @@ depuis une URL et ne dézippe pas encore automatiquement le fichier csv (_cf._ [ On peut utiliser la fonction idoine de pandas et après transformer en polars dataframe facilement grâce à la fonction `pl.from_pandas`. ```{python} +#| eval: false import pandas as pd url = "https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip" df_prenoms_url = pl.from_pandas(pd.read_csv(url, delimiter=";")) @@ -471,8 +481,7 @@ Si l'on veut éviter une dépendance à pandas juste pour cette opération, il f Prenons l'exemple d'un fichier CSV disponible sur le site de l'INSEE : le fichier des prénoms, issu des données de l'état civil. ```{python} -import requests - +#| eval: false # Téléchargement et stockage du nom du fichier url = "https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip" file_Path = url.split('/')[-1] @@ -482,8 +491,6 @@ if response.status_code == 200: with open(file_Path, 'wb') as file: file.write(response.content) -# zipfile permet de dézipper les fichiers -from zipfile import ZipFile # on charge le fichier télécharger et extraction dans un dossier temp/ with ZipFile(file_Path, 'r') as zObject: @@ -499,7 +506,6 @@ Mais la lecture de la valeur `XXXX` cause une erreur et n'est pas convertible en ```{python} #| eval: false -import os df_prenoms_url = pl.read_csv('temp/' + os.listdir('temp')[0], separator=";") ``` @@ -530,6 +536,7 @@ Tous ces paramètres et leur utilisation sont détaillés dans la [documentation ```{python} #| echo: false +#| eval: false # Pour nettoyer les fichiers !rm $file_Path !rm temp -rf @@ -635,7 +642,6 @@ on va écrire par exemple `pl.from_dict({"a": [1, 2], "b": [3, 4]})` Par exemple, ```{python} -import json response = requests.get("https://data.geopf.fr/geocodage/search?q=comedie&type=street") ``` @@ -1045,12 +1051,13 @@ subset_df = ( ## Traiter les valeurs manquantes -Les valeurs manquantes sont une réalité courante dans le traitement des données réelles et peuvent survenir pour diverses raisons, telles que des non-réponses à un questionnaire, des erreurs de saisie, des pertes de données lors de la transmission ou simplement parce que l'information n'est pas applicable. pandas offre plusieurs outils pour gérer les valeurs manquantes. +Les valeurs manquantes sont une réalité courante dans le traitement des données réelles et peuvent survenir pour diverses raisons, telles que des non-réponses à un questionnaire, des erreurs de saisie, des pertes de données lors de la transmission ou simplement parce que l'information n'est pas applicable. +Polars offre plusieurs outils pour gérer les valeurs manquantes. ### Représentation des valeurs manquantes On peut tout d'abord traiter les valeurs manquantes avec les méthodes associées. -Pour rappel, en polars, les valeurs `NaN` et `null` sont différentes, alors qu'en pandas elles sont traitées de manière similaire. +En polars, les valeurs `NaN` et `null` sont différentes, alors qu'en pandas elles sont traitées de manière similaire. | | **Type `null`** | **Type `NaN`** | |--|--|--| @@ -1310,7 +1317,6 @@ Par exemple, pour filtrer des données, on devra spécifier les bornes en appela df.filter(pl.col("date") >= pl.date(2022, 1, 1), pl.col("date") < pl.date(2022, 1, 3)) # équivalent à - from datetime import datetime df.filter(pl.col("date") >= datetime.strptime("2022-01-01", "%Y-%m-%d"), pl.col("date") < datetime.strptime("2022-01-03", "%Y-%m-%d")) ``` From 7bc1f22bd9a8cd1eab713d3b1aadde52fe5b068e Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 25 Feb 2026 17:37:51 +0000 Subject: [PATCH 56/92] review missing --- source/manipulation/polars/tutorial.qmd | 40 ++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 1854b77e..1ad08150 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -778,7 +778,7 @@ Le fonctionnement est cependant plus similaire au `mutate` du tidyverse. Il permet ainsi de modifier des valeurs de colonne, d'effectuer des opérations etc. -La méthode `with_columns()` fonctionne de deux manières différentes : +La méthode `with_columns()` fonctionne avec deux syntaxes différentes : - en utilisant une syntaxe plus proche du SQL et de Python, grâce à la méthode `.alias()` ; - plus similaire au tidyverse, en assignant les variables avec une équation. @@ -789,10 +789,10 @@ Par exemple, si l'on veut définir la colonne `b` comme la colonne `a` divisée df = pl.DataFrame({'a':np.random.randint(-10, 10, 6), 'b': np.random.randint(5, 15, 6)}) df.with_columns( - # Première méthode : + # Première méthode plus proche de Python et du SQL: (pl.col("a")/2).alias("b"), (np.abs(pl.col("a"))).alias("abs_a"), - # Ou l'autre méthode : + # Ou l'autre méthode plus proche du tidyverse: b2=pl.col("a")/2, abs_a2=np.abs(pl.col("a")) ) @@ -1063,11 +1063,11 @@ En polars, les valeurs `NaN` et `null` sont différentes, alors qu'en pandas ell |--|--|--| | **Signification** | Seule `Null` est considéré par défaut comme une valeur manquante et est l'unique type de valeur manquante dans polars (que le type original soit temporel, numérique, un charactère ...). | `NaN` représente à l'inverse des valeurs numériques erronées, comme le résultat d'une division par 0. | | **Comment les créer ?** | Les valeurs manquantes peuvent être crées simplement avec `None`. | Pour créer une valeur `NaN`, valable uniquement pour les types numériques, on peut utiliser `np.nan` de NumPy ou `float("nan")` de polars. | -| Comportement dans polars | Ces valeurs sont en général **ignorées**. | Ces valeurs **se propagent**. | +| **Comportement dans polars** | Ces valeurs sont en général **ignorées**. | Ces valeurs **se propagent**. | +: Valeurs particulières en polars -Vérifions cette propriété. -Pour identifier où se trouvent les valeurs manquantes, on utilise la fonction `is_null()` ou `is_nan()` appliquée à une colonne. +Pour identifier où se trouvent les valeurs manquantes, on utilise les méthodes `is_null()` ou `is_nan()` appliquées à une colonne. ```{python} df = pl.DataFrame( @@ -1084,16 +1084,11 @@ df.with_columns( ) ``` -On peut à l'inverse éliminer les lignes qui comportent une valeur manquante ou un `NaN` : - -```{python} -print(df.drop_nans()) -print(df.drop_nulls()) -``` ### Calculs sur des colonnes contenant des valeurs manquantes -Lors de calculs statistiques, les valeurs nulles sont généralement ignorées en polars. Par exemple, la méthode `.mean()` calcule la moyenne des valeurs non manquantes. +Lors de calculs statistiques, les valeurs nulles sont généralement ignorées en polars. +Par exemple, la méthode `.mean()` calcule la moyenne des valeurs non manquantes. ```{python} df['var1'].mean() @@ -1107,15 +1102,15 @@ df['var2'].mean() ### Suppression des valeurs manquantes -Les méthodes `drop_nulls()` et `drop_nans()` permettent de supprimer les lignes contenant des valeurs manquantes ou des NaN. +Les méthodes `drop_nulls()` et `drop_nans()` permettent de supprimer les lignes contenant des valeurs manquantes ou des `NaN`. -Par défaut, toute ligne contenant au moins une valeur manquante ou NaN est supprimée. +Par défaut, toute ligne contenant au moins une valeur manquante ou `NaN` est supprimée. ```{python} df.drop_nans() ``` -Si l'on spécifie une liste de colonnes, seules les lignes comportant une valeur manquante ou NaN de cette colonne seront supprimées. +Si l'on spécifie une liste de colonnes, seules les lignes comportant une valeur manquante ou `NaN` de cette colonne seront supprimées. ```{python} df.drop_nulls(['var1']) @@ -1123,7 +1118,8 @@ df.drop_nulls(['var1']) ### Remplacement des valeurs manquantes -Pour gérer les valeurs manquantes dans un dataframe, une approche commune est l'imputation, qui consiste à remplacer les valeurs manquantes par d'autres valeurs. La méthode [`fill_null()`](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.fill_null.html) permet d'effectuer cette opération de différentes manières dans toute la table de donnée. +Pour gérer les valeurs manquantes dans un dataframe, une approche commune est l'imputation, qui consiste à remplacer les valeurs manquantes par d'autres valeurs. +La méthode [`fill_null()`](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.fill_null.html) permet d'effectuer cette opération de différentes manières dans toute la table de donnée. - Une première possibilité est le remplacement par une valeur constante. @@ -1138,7 +1134,8 @@ Il peut parfois être tentant de changer la manifestation d'une valeur manquante df.fill_null(value="MISSING") ``` -En pratique, cette façon de faire n'est pas recommandée. Il est en effet préférable de conserver la convention standard de polars (l'utilisation des `null`), d'abord pour des questions de standardisation des pratiques qui facilitent la lecture et la maintenance du code, mais également parce que la convention standard est optimisée pour la performance et les calculs à partir de données contenant des valeurs manquantes. +En pratique, cette façon de faire n'est pas recommandée. +Il est en effet préférable de conserver la convention standard de polars (l'utilisation des `null`), d'abord pour des questions de standardisation des pratiques qui facilitent la lecture et la maintenance du code, mais également parce que la convention standard est optimisée pour la performance et les calculs à partir de données contenant des valeurs manquantes. ::: La méthide `fill_null()` de polars propose 4 méthodes pré-définies pour remplacer les valeurs manquantes par l'argument `strategy`: @@ -1151,13 +1148,16 @@ Si l'on veut remplacer uniquement les valeurs manquantantes d'une colonne en pol ```{python} df.with_columns( - pl.col(pl.NUMERIC_DTYPES).fill_null(strategy="mean") + cs.numeric().fill_null(strategy="mean") ) ``` ::: {.callout-warning title="Biais d'imputation"} -Remplacer les valeurs manquantes par une valeur constante, telle que zéro, la moyenne ou la médiane, peut être problématique. Si les données ne sont pas manquantes au hasard (*Missing Not At Random* - *MNAR*), cela peut introduire un biais dans l'analyse. Les variables *MNAR* sont des variables dont la probabilité d'être manquantes est liée à leur propre valeur ou à d'autres variables dans les données. Dans de tels cas, une imputation plus sophistiquée peut être nécessaire pour minimiser les distorsions. Nous en verrons un exemple en exercice de fin de tutoriel. +Remplacer les valeurs manquantes par une valeur constante, telle que zéro, la moyenne ou la médiane, peut être problématique. +Si les données ne sont pas manquantes au hasard (*Missing Not At Random* - *MNAR*), cela peut introduire un biais dans l'analyse. +Les variables *MNAR* sont des variables dont la probabilité d'être manquantes est liée à leur propre valeur ou à d'autres variables dans les données. +Dans de tels cas, une imputation plus sophistiquée peut être nécessaire pour minimiser les distorsions. ::: De manière similaire, la méthode `fill_nan()` permet de remplacer les valeurs numériques NaN par toute valeur indiquée. From b753b258634c796bd7fba92835ef4cc4379091f1 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 25 Feb 2026 17:56:07 +0000 Subject: [PATCH 57/92] review until merge --- source/manipulation/polars/tutorial.qmd | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 1ad08150..0b98bd68 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -397,6 +397,9 @@ Ils comprennent principalement: : Type de données dans polars +À chaque type de données polars sont associées des méthodes différentes pour les manipuler. +Elles sont détaillées dans la documentation et les principales seront vues à la suite. + ::: {.callout-caution title="Deux types de valeurs particulières"} Pour polars, les types `null` et `nan` sont différents. @@ -481,7 +484,6 @@ Si l'on veut éviter une dépendance à pandas juste pour cette opération, il f Prenons l'exemple d'un fichier CSV disponible sur le site de l'INSEE : le fichier des prénoms, issu des données de l'état civil. ```{python} -#| eval: false # Téléchargement et stockage du nom du fichier url = "https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip" file_Path = url.split('/')[-1] @@ -536,7 +538,6 @@ Tous ces paramètres et leur utilisation sont détaillés dans la [documentation ```{python} #| echo: false -#| eval: false # Pour nettoyer les fichiers !rm $file_Path !rm temp -rf @@ -780,7 +781,9 @@ Il permet ainsi de modifier des valeurs de colonne, d'effectuer des opérations La méthode `with_columns()` fonctionne avec deux syntaxes différentes : -- en utilisant une syntaxe plus proche du SQL et de Python, grâce à la méthode `.alias()` ; +- en utilisant une syntaxe plus proche du SQL et de Python, grâce à la méthode `.alias()`. +Dans cette syntaxe, on définit le nom de la variable en appliquant 'alias' à la définition. +Attention, si `alias()` n'est pas défini, polars n'affecte pas le résultat ; - plus similaire au tidyverse, en assignant les variables avec une équation. Par exemple, si l'on veut définir la colonne `b` comme la colonne `a` divisée par 2 , on va utiliser la formule suivante : @@ -1164,10 +1167,17 @@ De manière similaire, la méthode `fill_nan()` permet de remplacer les valeurs # Traiter les données de types spécifiques +Comme rappelé précédemment, polars associe à chaque type de données des méthodes spécifiques. +Par exemple : + +- à toute série de type caractère identifiée par exemple par `pl.col("myvar")`, on peut passer des méthodes pratiques après avoir appelé l'attribut `.str` de la série. +- à toute série de type temporelle identifiée par exemple par `pl.col("mydate")`, on peut passer des méthodes pratiques après avoir appelé l'attribut `.dt` de la série. + + ## Données textuelles Les données textuelles nécessitent souvent un nettoyage et une préparation avant l'analyse. -Polars fournit via la librairie de méthodes `str` un ensemble d'opérations vectorisées qui rendent la préparation des données textuelles à la fois simple et très efficace. +Polars associe à l'attribut `str` des méthodes vectorisées qui rendent la préparation des données textuelles à la fois simple et très efficace. La méthode `str` s'applique aux séries polars. Là encore, les possibilités sont multiples et détaillées dans la [documentation](https://docs.pola.rs/api/python/stable/reference/series/string.html). Nous présentons ici les méthodes les plus fréquemment utilisées dans l'analyse de données. @@ -1203,8 +1213,7 @@ C'est l'occasion d'introduire la famille de méthode `strip` (`.str.strip_chars( ( df .with_columns( - sample=pl.col("sample").str.strip_chars() # remarque : on peut omettre ici le 'sample=' - # et avoir le meme résultat + sample=pl.col("sample").str.strip_chars() ) .with_columns( sample_n = pl.col("sample").str.tail(1) @@ -1212,7 +1221,7 @@ C'est l'occasion d'introduire la famille de méthode `strip` (`.str.strip_chars( ) ``` -::: {.callout-note} +::: {.callout-note title="with_columns ne permet pas de travailler sur une variable nouvellement créée"} Remarquez la présence de deux `with_columns()` et non d'un seul. C'est parce que polars étant optimisé, il effectue les opérations sur `with_columns` en parallèle. Ainsi, si l'on ne le fait pas de manière séquentielle, il ne prend pas en compte le fait qu'on enlève les espace superflus dans 'sample' à la première ligne avant d'en extraire le dernier caractère. From 0c1d73b9b2948fe38978ee716400e1ff63e3107e Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 09:01:41 +0000 Subject: [PATCH 58/92] review merge --- source/manipulation/polars/tutorial.qmd | 29 ++++++++++++++++--------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 0b98bd68..e734c551 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -1368,12 +1368,14 @@ df.with_columns( # Joindre des tables Dans le cadre d'une analyse de données, il est courant de vouloir combiner différentes sources de données. + Cette combinaison peut se faire verticalement (un dataframe par dessus l'autre), par exemple lorsque l'on souhaite combiner deux millésimes d'une même enquête afin de les analyser conjointement. + La combinaison peut également se faire horizontalement (côte à côte) selon une ou plusieurs clé(s) de jointure, souvent dans le but d'enrichir une source de données à partir d'une autre source portant sur les mêmes unités statistiques. ## Concaténer des tables -La concaténation verticale de tables se fait à l'aide de la fonction [`concat()`](https://docs.pola.rs/api/python/stable/reference/api/polars.concat.html#polars.concat) de polars. +La concaténation verticale de tables se fait à l'aide de la fonction [`concat()`](https://docs.pola.rs/api/python/stable/reference/api/polars.concat.html#polars.concat). ```{python} @@ -1425,9 +1427,9 @@ Pour contourner ce problème, il suffit de préférer une méthode de type `join La fusion de tables est une opération qui permet d'associer des lignes de deux dataframes différents en se basant sur une ou plusieurs clés communes, similaire aux jointures dans les bases de données SQL. Différents types de jointure sont possible selon les données que l'on souhaite conserver, dont les principaux sont représentés sur le graphique suivant. -![](img/joins.png) +![*Source : [lien](https://medium.com/swlh/merging-dataframes-with-pandas-pd-merge-7764c7e2d46d) +*](img/joins.png) -Source : [lien](https://medium.com/swlh/merging-dataframes-with-pandas-pd-merge-7764c7e2d46d) En polars, les jointures se font avec la fonction [`join()`](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.join.html#polars.DataFrame.join). Pour réaliser une jointure, on doit spécifier (au minimum) deux informations : @@ -1435,16 +1437,16 @@ Pour réaliser une jointure, on doit spécifier (au minimum) deux informations : - le type de jointure : par défaut, polars effectue une jointure de type `inner`. Le paramètre `how` permet de spécifier d'autres types de jointure ; -- la clé de jointure. -On spécifie souvent une colonne présente dans le dataframe comme clé de jointure (paramètre `on` si la colonne porte le même nom dans les deux dataframes, ou `left_on` et `right_on` sinon). +- la clé de jointure : on spécifie souvent une colonne présente dans le dataframe comme clé de jointure (paramètre `on` si la colonne porte le même nom dans les deux dataframes, ou `left_on` et `right_on` sinon). + +Par défaut, les colonnes présentes dans les deux dataframe seront fusionnées sauf pour un full join. +Pour éviter ce comportement, il faut préciser `coalesce=False`. -Par défaut, les colonnes présentes dans les deux colonnes seront conservées avec des suffixes '_right' ou '_left'. -Pour éviter ce comportement, il faut préciser l'argument `coalesce`. On peut aussi spécifier l'ordre dans lequel les colonnes apparaissent avec l'argument `maintain_order`. -::: {.callout-note} -On peut aussi tout à fait joindre selon des critères différents que l'égalité : par exemple, joint cette ligne avec toute ligne dont la date est antérieure. +::: {.callout-note title="Jointure complexe"} +On peut aussi tout à fait joindre selon des critères différents que l'égalité : par exemple, joint cette ligne avec toute ligne dont la date est la plus proche avant. Les méthodes utilisées sont [`join_asof()`](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.join_asof.html) et [`join_where()`](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.join_where.html)` ::: @@ -1477,7 +1479,9 @@ df_a.join(df_b, on='key') ::: {.callout-warning title="Jointures inner"} La jointure de type `inner` est la plus intuitive : elle ne crée généralement pas de valeurs manquantes et permet donc de travailler directement sur la table fusionnée. + Mais attention : si beaucoup de clés ne sont pas présentes dans les deux dataframes à la fois, une jointure `inner` peut aboutit à des pertes importantes de données, et donc à des résultats finaux biaisés. + Dans ce cas, il vaut mieux choisir une jointure à gauche ou à droite, selon la source que l'on cherche à enrichir et pour laquelle il est donc le plus important de limiter les pertes de données. ::: @@ -1502,12 +1506,17 @@ df_a.join(df_b, how="full", on='key') df_a.join(df_b, how="full", on='key', coalesce=True) ``` +::: {.callout-tip title="Validation des clés"} + +La fonction `join()` comprend l'option `validate: {‘m:m’, ‘m:1’, ‘1:m’, ‘1:1’}` qui permet de valider si la multiplicité des clés de jointure. + +::: # Exercices ## Questions de compréhension -- 1/ Qu'est-ce qu'un dataframe dans le contexte de polars et à quel type de structure de données peut-on le comparer dans le langage Python ? +- 1/ Qu'est-ce qu'un dataframe dans polars et à quel type de structure de données peut-on le comparer dans le langage Python ? - 2/ Quels sont les avantages de polars ? From 628db63a030d2d8c3ef800d97334ff3d1b65b40a Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 09:07:19 +0000 Subject: [PATCH 59/92] review exo1 --- source/manipulation/polars/tutorial.qmd | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index e734c551..6ca8fd2a 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -1594,7 +1594,8 @@ Les méthodes comme `df.drop_nulls()` ou `df.fill_null()` permettent de gérer e ## Plusieurs manières de créer un dataframe -Dans la cellule suivante, nous avons récupéré des données de caisses sur les ventes de différentes enseignes. Les données sont cependant présentées de deux manières différentes, dans un cas sous forme d'observations (chaque liste contient les données d'une ligne), dans l'autre sous forme de variables (chaque liste contient les données d'une colonne). +Dans la cellule suivante, nous avons récupéré des données de caisses sur les ventes de différentes enseignes. +Les données sont cependant présentées de deux manières différentes, dans un cas sous forme d'observations (chaque liste contient les données d'une ligne), dans l'autre sous forme de variables (chaque liste contient les données d'une colonne). ```{python} data_list1 = [ @@ -1614,7 +1615,9 @@ data_list2 = [ ] ``` -L'objectif est de construire dans les deux cas un même dataframe qui contient chacune des 6 observations et des 4 variables, avec les mêmes noms dans les deux dataframes. A chaque cas va correspondre une structure de données plus adaptée en entrée, dictionnaire ou liste de listes... faîtes le bon choix ! On vérifiera que les deux dataframes sont identiques à l'aide de la méthode [equals()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.equals.html#polars.DataFrame.equals). +L'objectif est de construire dans les deux cas un même dataframe qui contient chacune des 6 observations et des 4 variables, avec les mêmes noms dans les deux dataframes. +A chaque cas va correspondre une structure de données plus adaptée en entrée, dictionnaire ou liste de listes... faîtes le bon choix ! +On vérifiera que les deux dataframes sont identiques à l'aide de la méthode [equals()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.equals.html#polars.DataFrame.equals). ```{python} # Testez votre réponse dans cette cellule @@ -1675,9 +1678,11 @@ data = { 'produit': ['01.1.1', '02.1.1', '01.1.1', '03.1.1', '01.1.1', '02.1.1'], 'quantite': [3, 2, 7, 5, 10, 1], 'prix': [1.50, 2.30, 0.99, 5.00, 1.20, 3.10], - 'date_heure': pl.Series(["2022-01-01 14:05", "2022-01-02 09:30", - "2022-01-03 17:45", "2022-01-04 08:20", - "2022-01-05 19:00", "2022-01-06 16:30"]).str.to_datetime() + 'date_heure': pl.Series( + ["2022-01-01 14:05", "2022-01-02 09:30", + "2022-01-03 17:45", "2022-01-04 08:20", + "2022-01-05 19:00", "2022-01-06 16:30"] + ).str.to_datetime() } df = pl.DataFrame(data) @@ -1758,7 +1763,7 @@ df.filter(pl.col("enseigne") == 'Carrefour') Afficher la solution ```{python} -print( +( df .filter(pl.col("produit") == '01.1.1') .select("quantite") From 5c2512e57881ac64d32ff3897854962a58de38ca Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 09:29:06 +0000 Subject: [PATCH 60/92] review exo2 prenoms --- source/manipulation/polars/tutorial.qmd | 58 ++++++++++++++++++------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 6ca8fd2a..244d8576 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -1856,7 +1856,9 @@ df.filter(pl.col("date_heure").dt.date() == pl.Series(['2022-01-03']).str.to_dat ## Exploration du fichier des prénoms -Le fichier des prénoms contient des données sur les prénoms attribués aux enfants nés en France entre 1900 et 2021. Ces données sont disponibles au niveau France, par département et par région, à l'adresse suivante : [https://www.insee.fr/fr/statistiques/2540004?sommaire=4767262](https://www.insee.fr/fr/statistiques/2540004?sommaire=4767262). L'objectif de ce tutoriel est de proposer une analyse de ce fichier, du nettoyage des données au statistiques sur les prénoms. +Le fichier des prénoms contient des données sur les prénoms attribués aux enfants nés en France entre 1900 et 2021. +Ces données sont disponibles au niveau France, par département et par région, à l'adresse suivante : [https://www.insee.fr/fr/statistiques/2540004?sommaire=4767262](https://www.insee.fr/fr/statistiques/2540004?sommaire=4767262). +L'objectif de ce tutoriel est de proposer une analyse de ce fichier, du nettoyage des données au statistiques sur les prénoms. ### Partie 1 : Import et exploration des données @@ -1892,8 +1894,24 @@ df_prenoms.describe() ### Partie 2 : Nettoyage des données -- L'output des recherches précédentes suggère des valeurs manquantes dans la colonne des prénoms. Affichez ces lignes. Vérifiez que ces valeurs manquantes sont correctement spécifiées. -- L'output de méthode `head()` montre une modalité récurrente "_PRENOMS_RARES" dans la colonne des prénoms. Quelle proportion des individus de la base cela concerne-t-il ? Vous pouvez vous aider de la méthode `over` détaillée dans la documentation. Convertir ces valeurs en valeurs manquantes. +- L'output des recherches précédentes suggère des valeurs manquantes dans la colonne des prénoms. +Affichez ces lignes. +Vérifiez que ces valeurs manquantes sont correctement spécifiées. +- L'output de méthode `head()` montre une modalité récurrente "_PRENOMS_RARES" dans la colonne des prénoms. +Quelle proportion des individus de la base cela concerne-t-il ? +Convertir ces valeurs en valeurs manquantes. + +::: {.callout-tip title="Indices"} + +Ces méthides peuvent aider : + +- [`over`](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.Expr.over.html#polars.Expr.over) ; +- la syntaxe de [`pl.when`](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.when.html) ; +- [`dataframe.item`](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.iter_rows.html) : pour accéder à un élément d'un dataframe et le retourner en format Python classique + +::: + + ```{python} # Testez votre réponse dans cette cellule @@ -1921,21 +1939,24 @@ print(prop_rares1) # ~ 2 % de la base prop_rares2 = ( df_prenoms .group_by("preusuel") - .agg(pl.col("nombre").sum()) + .agg(pl.sum("nombre")) .with_columns(tot=pl.sum("nombre")) .with_columns(tot_rel=pl.col("nombre")/pl.col("tot")) .filter(pl.col("preusuel")=="_PRENOMS_RARES") .item(0, "tot_rel") ) print(prop_rares2) # ~ 2 % de la base -df_prenoms = df_prenoms.with_columns(preusuel=pl.when(pl.col("preusuel")=="_PRENOMS_RARES").then(None).otherwise(pl.col("preusuel"))) +df_prenoms = df_prenoms.with_columns( + preusuel=pl.when(pl.col("preusuel")=="_PRENOMS_RARES").then(None).otherwise(pl.col("preusuel"))) ``` ::: -- On remarque que les prénoms de personnes dont l'année de naissance n'est pas connue sont regroupés sous la modalité `XXXX`. Quelle proportion des individus de la base cela concerne-t-il ? Convertir ces valeurs en valeurs manquantes. Vous pouvez utiliser la syntaxe de [`pl.when`](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.when.html) +- On remarque que les prénoms de personnes dont l'année de naissance n'est pas connue sont regroupés sous la modalité `XXXX`. +Quelle proportion des individus de la base cela concerne-t-il ? +Convertir ces valeurs en valeurs manquantes. ```{python} # Testez votre réponse dans cette cellule @@ -1951,7 +1972,7 @@ df_prenoms = df_prenoms.with_columns(preusuel=pl.when(pl.col("preusuel")=="_PREN prop_xxxx = ( df_prenoms .with_columns( - tot_rel=pl.col("nombre").sum().over("annais")/ pl.col("nombre").sum() + tot_rel=pl.sum("nombre").over("annais")/ pl.sum("nombre") ) .filter(pl.col("annais")=="XXXX") .item(0, "tot_rel") @@ -1984,7 +2005,7 @@ df_prenoms = df_prenoms.drop_nulls() ::: -- Convertissez la colonne `annais` en type numérique et la colonne `sexe` en type catégoriel. +- Convertissez la colonne `annais` en type numérique et la colonne `sexe` en type caractère (ou en catégorie, mais attention au résultat!). ```{python} # Testez votre réponse dans cette cellule @@ -1997,7 +2018,11 @@ df_prenoms = df_prenoms.drop_nulls() Afficher la solution ```{python} -df_prenoms = df_prenoms.cast({'annais':pl.Int32, 'sexe':pl.Categorical}) +df_prenoms = df_prenoms.cast({'annais':pl.Int32, 'sexe':pl.Utf8}) + +# Pour une catégorie, il faut ensuite le transformer en catégorie. +# Le changement de pl.Int => pl.Categorical ne marche pas directement sinon et renvoie des null +df_prenoms.cast({'sexe':pl.Categorical}) ``` @@ -2027,7 +2052,8 @@ df_prenoms.describe() ### Partie 3 : Statistiques descriptives sur les naissances -- La [documentation](https://www.insee.fr/fr/statistiques/2540004?sommaire=4767262#documentation) du fichier nous informe qu'on peut considérer les données comme quasi-exhaustives à partir de 1946. Pour cette partie seulement, filtrer les données pour ne conserver que les données ultérieures. +- La [documentation](https://www.insee.fr/fr/statistiques/2540004?sommaire=4767262#documentation) du fichier nous informe qu'on peut considérer les données comme quasi-exhaustives à partir de 1946. +Pour cette partie seulement, filtrer les données pour ne conserver que les données ultérieures. ```{python} # Testez votre réponse dans cette cellule @@ -2061,7 +2087,7 @@ df_prenoms_post_1946 = df_prenoms.filter(pl.col("annais") >= 1946) ```{python} births_per_sex = df_prenoms_post_1946.group_by("sexe").agg(pl.sum("nombre")) -print(births_per_sex) +births_per_sex ``` @@ -2082,7 +2108,7 @@ print(births_per_sex) ```{python} top5_years = df_prenoms_post_1946.group_by(pl.col("annais")).agg(pl.sum("nombre")).sort("nombre").tail(5) -print(top5_years) +top5_years ``` @@ -2106,7 +2132,7 @@ print(top5_years) ```{python} total_unique_names = df_prenoms.n_unique("preusuel") -print(total_unique_names) +total_unique_names ``` @@ -2126,8 +2152,8 @@ print(total_unique_names) Afficher la solution ```{python} -single_letter_names = df_prenoms.filter(pl.col("preusuel").str.len_chars() == 1).select("nombre").sum() -print(single_letter_names) +single_letter_names = df_prenoms.filter(pl.col("preusuel").str.len_chars() == 1).select(pl.sum("nombre")) +single_letter_names ``` @@ -2194,7 +2220,7 @@ def popularite_par_decennie(df, sexe): # Filtrer le prénom le plus fréquent pour chaque décennie par over df_popularite_decennie = df_counts_decennie.filter(pl.col("nombre")==pl.max("nombre").over("decennie")) - return df_popularite_decennie + return df_popularite_decennie.sort("decennie") # Test de la fonction avec un exemple popularite_par_decennie(df_prenoms, sexe="2") From ea744525392e026c3e038fc8ce8c1a2e34b53414 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 09:33:34 +0000 Subject: [PATCH 61/92] with select to transform --- source/manipulation/polars/tutorial.qmd | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 244d8576..c90159a7 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -859,6 +859,19 @@ df.with_columns( ) ``` +### Sélectionner et transformer des colonnes + +La méthode `select()`, déjà abordée plus haut, permet aussi de transformer les colonnes. +Si l'on veut sélectionner et transformer les colonnes en une commande, +cela est donc possible grâce à cette méthode. + +Par exemple, pour normaliser les colonnes dans l'exemple ci-dessus, on peut remplacer `with_columns()` par un `select()`. + +```{python} +df.select( + (cs.numeric() / pl.col("var2")).name.suffix("_norm") # va normaliser les colonnes et sélectionner les colonnes listées +) +``` ### Renommer des colonnes Une autre opération fréquente est le renommage d'une ou plusieurs colonnes. From 8f2f594b88b635bef5387f7f203839b7a2d57808 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 10:14:33 +0000 Subject: [PATCH 62/92] review exo3 empreinte --- source/manipulation/polars/tutorial.qmd | 70 ++++++++++++++++++------- 1 file changed, 50 insertions(+), 20 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index c90159a7..74677045 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -2154,6 +2154,10 @@ total_unique_names - Compter le nombre de personnes possédant un prénom d'une seule lettre. +::: {.callout-tip title="Indicee"} +La méthode [str.len_chars()](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.Expr.str.len_chars.html#polars.Expr.str.len_chars) vous aidera. +::: + ```{python} # Testez votre réponse dans cette cellule @@ -2245,11 +2249,12 @@ popularite_par_decennie(df_prenoms, sexe="2") ## Calcul d'une empreinte carbone par habitant au niveau communal -L'objectif de cet exercice est de calculer une empreinte carbone par habitant au niveau communal. Pour cela, il va falloir combiner deux sources de données : +L'objectif de cet exercice est de calculer une empreinte carbone par habitant au niveau communal. +Pour cela, il va falloir combiner deux sources de données : -- les populations légales au niveau des communes, issues du recensement de la population ([source](https://www.insee.fr/fr/statistiques/6683037)) +- les populations légales au niveau des communes, issues du recensement de la population ([source](https://www.insee.fr/fr/statistiques/6683037)) ; -- les émissions de gaz à effet de serre estimées au niveau communal par l’ADEME ([source](https://www.data.gouv.fr/fr/datasets/inventaire-de-gaz-a-effet-de-serre-territorialise/#_)) +- les émissions de gaz à effet de serre estimées au niveau communal par l’ADEME ([source](https://www.data.gouv.fr/fr/datasets/inventaire-de-gaz-a-effet-de-serre-territorialise/#_)). Cet exercice constitue une version simplifiée d'un [TP complet pour la pratique de pandas](https://pythonds.linogaliana.fr/content/manipulation/02b_pandas_TP.html#importer-les-donn%C3%A9es) proposé par Lino Galiana dans son [cours à l'ENSAE](https://pythonds.linogaliana.fr/) et traduit en polars. @@ -2305,7 +2310,7 @@ df_pop_communes = df_pop_communes.drop(["PMUN", "PCAP"]) ::: Les communes qui ont les noms les plus longs sont-elles aussi les communes les moins peuplées ? Pour le savoir : -- Créez une nouvelle variable qui contient le nombre de caractères de chaque commune à l'aide de la méthode [str.len_chars()](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.Expr.str.len_chars.html#polars.Expr.str.len_chars) +- Créez une nouvelle variable qui contient le nombre de caractères de chaque commune - Calculez la corrélation entre cette variable et la population totale avec la méthode [corr()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.corr.html#polars.DataFrame.corr) ```{python} @@ -2360,7 +2365,15 @@ df_emissions.describe() ::: -- Y a-t-il des lignes avec des valeurs manquantes pour toutes les colonnes d'émission ? Vérifiez-le à l'aide des méthodes [is_null()](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.Expr.is_null.html#polars.Expr.is_null) et [all_horizontal()](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.all_horizontal.html#polars.all_horizontal). +- Y a-t-il des lignes avec des valeurs manquantes pour toutes les colonnes d'émission ? + +::: {.callout-tip title="Indices"} + +- les sélecteurs vous permettront de choisir les colonnes numériques ; +- [`pl.all()`](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.all.html#polars.all) s'applique à toutes les colonnes ; +- la méthode [`is_null()`](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.Expr.is_null.html#polars.Expr.is_null) permet d'identifier les valeurs manquantes ; +- la méthode [`all_horizontal()`](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.all_horizontal.html#polars.all_horizontal) permet de vérifier une condition sur toutes les colonnes. +::: ```{python} # Testez votre réponse dans cette cellule @@ -2374,7 +2387,10 @@ df_emissions.describe() ```{python} df_emissions_num = df_emissions.select(cs.numeric()) -only_nulls = df_emissions_num.filter(pl.all_horizontal(pl.all().is_null())) +# List of columns with nulls values +cols_with_nulls = [col for col in df_emissions_num.columns if df_emissions_num.describe().item(1, col)>0] # item(1, col) will get the number of nulls + +only_nulls = df_emissions_num.select(cols_with_nulls).filter(pl.all_horizontal(pl.all().is_null())) only_nulls.height ``` @@ -2385,6 +2401,13 @@ only_nulls.height - Créez une nouvelle colonne qui donne les émissions totales par commune - Afficher les 10 communes les plus émettrices. Qu'observez-vous dans les résultats ? +::: {.callout-tip title="Indice"} + +Comme dans le tidyverse, vous pouvez jouer sur les formes de dataframe +avec `pivot` et `unpivot` (ou `melt` en pandas). + +::: + ```{python} # Testez votre réponse dans cette cellule @@ -2420,7 +2443,8 @@ df_emissions_top10 ::: -- Il semble que les postes majeurs d'émissions soient "Industrie hors-énergie" et "Autres transports international". Pour vérifier si cette conjecture tient, calculer la corrélation entre les émissions totales et les postes sectoriels d'émissions à l'aide de la méthode [corr()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.corr.html#polars.DataFrame.corr). +- Il semble que les postes majeurs d'émissions soient "Industrie hors-énergie" et "Autres transports international". +Pour vérifier si cette conjecture tient, calculer la corrélation entre les émissions totales et les postes sectoriels d'émissions à l'aide de la méthode [corr()](https://docs.pola.rs/api/python/stable/reference/dataframe/api/polars.DataFrame.corr.html#polars.DataFrame.corr). ```{python} # Testez votre réponse dans cette cellule @@ -2433,17 +2457,19 @@ df_emissions_top10 Afficher la solution ```{python} +# Calculating the corr table +emissions_corr = df_emissions.drop_nulls().select(cs.numeric()).corr() + +# For readability, selecting the column and sorting the correlation ( - pl.concat( - [ - df_emissions.drop_nulls().select(cs.numeric()).corr().select("emissions_totales"), - pl.DataFrame({ - 'autre_col':df_emissions.select(cs.numeric()).columns - }) - ], - how='horizontal' + emissions_corr + .head(1) + .transpose( + include_header=True, + header_name="sector", + column_names=["corr_emissions_tot"] ) - .sort("emissions_totales") + .sort("corr_emissions_tot") ) ``` @@ -2453,7 +2479,8 @@ df_emissions_top10 - Extraire du code commune le numéro de département dans une nouvelle variable - Calculer les émissions totales par département -- Afficher les 10 principaux départements émetteurs. Les résultats sont-ils logiques par rapport à l'analyse au niveau communal ? +- Afficher les 10 principaux départements émetteurs. +Les résultats sont-ils logiques par rapport à l'analyse au niveau communal ? ```{python} # Testez votre réponse dans cette cellule @@ -2508,7 +2535,8 @@ doublons ::: -- Filtrez dans le dataframe initial les communes dont le nom est dupliqué, et triez-le par code commune. Les doublons semblent-ils problématiques ? +- Filtrez dans le dataframe initial les communes dont le nom est dupliqué, et triez-le par code commune. +Les doublons semblent-ils problématiques ? ```{python} # Testez votre réponse dans cette cellule @@ -2549,7 +2577,8 @@ df_pop_communes_doublons.group_by("DEPCOM").n_unique().filter(pl.col("COM")>1).s ::: -- Affichez les communes présentes dans les données communales mais pas dans les données d'émissions, et inversement. Qu'en concluez-vous ? +- Affichez les communes présentes dans les données communales mais pas dans les données d'émissions, et inversement. +Qu'en concluez-vous ? ```{python} # Testez votre réponse dans cette cellule @@ -2579,7 +2608,8 @@ df_emissions.filter( ### Partie 4 : Calcul d'une empreinte carbone par habitant pour chaque commune -- Joindre les deux dataframes à l'aide de la fonction à partir du code commune. Attention : les variables ne s'appellent pas de la même manière des deux côtés ! +- Joindre les deux dataframes à l'aide de la fonction à partir du code commune. +Attention : les variables ne s'appellent pas de la même manière des deux côtés ! ```{python} # Testez votre réponse dans cette cellule From 439428a6eeae70a0e7035a485e2b42e31a93868f Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 10:25:25 +0000 Subject: [PATCH 63/92] typos --- source/manipulation/polars/tutorial.qmd | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 74677045..536a3ee1 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -941,21 +941,21 @@ df Pour trier les valeurs selon une seule colonne, il suffit de passer le nom de la colonne en paramètre. ```{python} -df.sort(by='var1") +df.sort(by="var1") ``` Par défaut, le tri est effectué dans **l'ordre croissant**. Pour trier les valeurs dans un ordre décroissant, il suffit de paramétrer `descending=True`. ```{python} -df.sort(by='var1', descending=True) +df.sort(by="var1", descending=True) ``` Si on souhaite trier le dataframe sur **plusieurs colonnes**, on peut fournir une liste de noms de colonnes. On peut également choisir de trier de manière croissante pour certaines colonnes et décroissante pour d'autres en spécifiant les booléns dans une liste. ```{python} -df.sort(by=['var1', 'var2'], descending=[True, True]) +df.sort(by=["var1", "var2"], descending=[True, True]) ``` @@ -1028,8 +1028,8 @@ df.group_by("experiment").agg(pl.col("var2").n_unique()) - Pour calculer par type d'expérience le nombre de valeurs de "var2" et la moyenne de "var1" : ```{python} df.group_by("experiment").agg( - pl.col("var1").mean().alias('mean_var1"), - pl.col("var2").len().alias('count_var2") + pl.col("var1").mean().alias("mean_var1"), + pl.col("var2").len().alias("count_var2") ) ``` @@ -1058,7 +1058,7 @@ Cela favorise également un style de programmation fonctionnel où les données subset_df = ( df .filter(pl.col("sample") == "sample1", pl.col("date") >= '2022-01-02') - .drop('sample") + .drop("sample") .glimpse() ) ``` @@ -1107,13 +1107,13 @@ Lors de calculs statistiques, les valeurs nulles sont généralement ignorées e Par exemple, la méthode `.mean()` calcule la moyenne des valeurs non manquantes. ```{python} -df['var1'].mean() +df["var1"].mean() ``` En revanche, les valeurs 'Not a Number', ou `NaN`, ont plutôt tendance à se propager. ```{python} -df['var2'].mean() +df["var2"].mean() ``` ### Suppression des valeurs manquantes @@ -1129,7 +1129,7 @@ df.drop_nans() Si l'on spécifie une liste de colonnes, seules les lignes comportant une valeur manquante ou `NaN` de cette colonne seront supprimées. ```{python} -df.drop_nulls(['var1']) +df.drop_nulls(["var1"]) ``` ### Remplacement des valeurs manquantes @@ -1140,6 +1140,8 @@ La méthode [`fill_null()`](https://docs.pola.rs/api/python/stable/reference/dat - Une première possibilité est le remplacement par une valeur constante. ```{python} +#| eval: false + df.fill_null(value=0) ``` @@ -1147,6 +1149,8 @@ df.fill_null(value=0) Il peut parfois être tentant de changer la manifestation d'une valeur manquante pour des raisons de visibilité, par exemple en la remplaçant par une chaîne de caractères : ```{python} +#| eval: false + df.fill_null(value="MISSING") ``` @@ -1163,6 +1167,7 @@ La méthide `fill_null()` de polars propose 4 méthodes pré-définies pour remp Si l'on veut remplacer uniquement les valeurs manquantantes d'une colonne en polars, il est plus utile d'utiliser la méthode `with_columns()` en utilisant l'agilité des sélecteurs de polars. ```{python} +#| eval: false df.with_columns( cs.numeric().fill_null(strategy="mean") ) From f03b6861b70a907b2013f95f4bc2a71f3886f34d Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 11:30:13 +0000 Subject: [PATCH 64/92] review exo3 empreinte - end --- source/manipulation/polars/tutorial.qmd | 31 ++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 536a3ee1..3e3c8ee0 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -2307,7 +2307,7 @@ n_communes_0_pop = df_pop_communes.filter(pl.col("PTOT") == 0).height print(n_communes_0_pop) df_pop_communes = df_pop_communes.filter(pl.col("PTOT") > 0) -df_pop_communes = df_pop_communes.drop(["PMUN", "PCAP"]) +df_pop_communes = df_pop_communes.drop("PMUN", "PCAP") ``` @@ -2444,6 +2444,35 @@ df_emissions_top10 = ( df_emissions_top10 ``` +Pour une meilleure représentation, on peut regarder cela sous forme graphique (*cf.* partie suivante) : + +```{python} +# Liste des secteurs et dataframe pandas +sectors = df_emissions_top10.columns[2:12] +df = df_emissions_top10.select(sectors + ["INSEE commune", "emissions_totales"]).to_pandas() + +# Graphique empilé +ax = df[sectors+ ["INSEE commune"]].plot(kind='bar', stacked=True, x="INSEE commune", y=sub_components) + +# Ajouter la ligne pour emissions_totales +ax.plot( + df["INSEE commune"], + df["emissions_totales"], + color="black", + marker="x", + label="Emissions Totales", +) + +# Personnalisation +ax.set_xlabel("Code Insee Commune") +ax.set_ylabel("Emissions") +plt.xticks(rotation=45) # Rotation des étiquettes pour une meilleure lisibilité +plt.title("Décomposition des émissions par commune") + +# Affichage +plt.show() + +``` ::: From eefc10515d257f7c9e3150eeaca8a7d4c8518d13 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 11:55:22 +0000 Subject: [PATCH 65/92] with modified intro --- source/manipulation/polars/tutorial.qmd | 40 +++++++++++++++---------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 3e3c8ee0..48aef970 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -58,18 +58,21 @@ Il est courant de passer du temps à débugger cette étape, notamment pour s'as que le code soit résistant à de légères variations dans le format des données d'entrée. Pour optimiser ce temps là, on peut spécifier directement les types en entrée. -- **l'index de pandas** est mort <3 : comme dans le tidyverse, polars -n'utilise pas d'index, et c'est très bien comme cela ! +- ce qui est mort de **pandas**: + - **l'index de pandas** est mort <3 : comme dans le tidyverse, polars + n'utilise pas d'index, et c'est très bien comme cela ! + - **plus de `inplace=True`**, en polars les méthodes ne remplacent pas les dataframe. + Il faut à chaque fois affecter le résultat pour modifier le dataframe, comme en + R. + - la logique entre ce qui relève d'un attribut, d'une méthode est bien **plus claire** qu'avec + pandas. En gros, toutes les fonctions utilisées en polars sont des méthodes de dataframe, + de Séries ou d'expressions polars. Cela facilite le chainage et la logique de code. - les `polars selectors` sont très pratiques pour sélectionner des colonnes. Ils permettent de sélectionner des colonnes avec des regex sur leurs noms ou bien en fonction de leur type de données. Plus d'exemples sont disponibles dans la [documentation officielle](https://docs.pola.rs/api/python/stable/reference/selectors.html). -- Les **chaines de caractères sont par défaut associées à des colonnes** : -En polars, les caractères simples `"myvar"` sont par défaut considéré comme des noms de -colonne. Il faut penser à utiliser `pl.lit("myvar")` pour signaler qu'il ne s'agit -pas d'un nom de colonne. ## Pour aller plus loin @@ -102,6 +105,7 @@ import os import requests import json from zipfile import ZipFile # zipfile permet de dézipper les fichiers +import pandas as pd ``` @@ -472,7 +476,6 @@ On peut utiliser la fonction idoine de pandas et après transformer en polars da ```{python} #| eval: false -import pandas as pd url = "https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip" df_prenoms_url = pl.from_pandas(pd.read_csv(url, delimiter=";")) ``` @@ -647,7 +650,7 @@ Par exemple, response = requests.get("https://data.geopf.fr/geocodage/search?q=comedie&type=street") ``` -Si l'on clique sur le [lien de la requête](https://data.geopf.fr/geocodage/search?q=comedie&type=street), on voit que le résultat de la requête est **un dictionnaire avec 3 clés** : type, features et query. La deuxième clé, 'features', stocke les résultats sous forme d'une liste de 10 éléments. +Si l'on clique sur le [lien de la requête](https://data.geopf.fr/geocodage/search?q=comedie&type=street), on voit que le résultat de la requête est **un dictionnaire avec 3 clés** : *type*, *features* et *query*. La deuxième clé, *features*, stocke les résultats sous forme d'une liste de 10 éléments. Pour importer directement ce fichier en polars, on peut utiliser l'une ou l'autre des méthodes `from_dict` ou `from_dicts`. ```{python} @@ -669,6 +672,7 @@ On obtient ainsi facilement un dataframe plat: ```{python} df = df.select("features").unnest("features").drop("type").unnest("geometry").drop("type").unnest("properties") +df ``` ::: @@ -1610,7 +1614,7 @@ Les méthodes comme `df.drop_nulls()` ou `df.fill_null()` permettent de gérer e ::: -## Plusieurs manières de créer un dataframe +## Ex 1 - Plusieurs manières de créer un dataframe (facile) Dans la cellule suivante, nous avons récupéré des données de caisses sur les ventes de différentes enseignes. Les données sont cependant présentées de deux manières différentes, dans un cas sous forme d'observations (chaque liste contient les données d'une ligne), dans l'autre sous forme de variables (chaque liste contient les données d'une colonne). @@ -1686,7 +1690,7 @@ df_from_dict.equals(df_from_list) ::: -## Sélection de données dans un dataframe +## Ex 2 - Sélection de données dans un dataframe (facile) Un dataframe polars est créé avec des données de caisse (mêmes données que l'exercice précédent). @@ -1872,7 +1876,7 @@ df.filter(pl.col("date_heure").dt.date() == pl.Series(['2022-01-03']).str.to_dat ::: -## Exploration du fichier des prénoms +## Ex 3 - Exploration du fichier des prénoms (moyen) Le fichier des prénoms contient des données sur les prénoms attribués aux enfants nés en France entre 1900 et 2021. Ces données sont disponibles au niveau France, par département et par région, à l'adresse suivante : [https://www.insee.fr/fr/statistiques/2540004?sommaire=4767262](https://www.insee.fr/fr/statistiques/2540004?sommaire=4767262). @@ -2159,7 +2163,7 @@ total_unique_names - Compter le nombre de personnes possédant un prénom d'une seule lettre. -::: {.callout-tip title="Indicee"} +::: {.callout-tip title="Indice"} La méthode [str.len_chars()](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.Expr.str.len_chars.html#polars.Expr.str.len_chars) vous aidera. ::: @@ -2252,7 +2256,7 @@ popularite_par_decennie(df_prenoms, sexe="2") ::: -## Calcul d'une empreinte carbone par habitant au niveau communal +## Ex 4 - Calcul d'une empreinte carbone par habitant au niveau communal (difficile) L'objectif de cet exercice est de calculer une empreinte carbone par habitant au niveau communal. Pour cela, il va falloir combiner deux sources de données : @@ -2452,7 +2456,7 @@ sectors = df_emissions_top10.columns[2:12] df = df_emissions_top10.select(sectors + ["INSEE commune", "emissions_totales"]).to_pandas() # Graphique empilé -ax = df[sectors+ ["INSEE commune"]].plot(kind='bar', stacked=True, x="INSEE commune", y=sub_components) +ax = df[sectors+ ["INSEE commune"]].plot(kind='bar', stacked=True, x="INSEE commune", y=sectors) # Ajouter la ligne pour emissions_totales ax.plot( @@ -2694,7 +2698,7 @@ df_emissions_pop.tail(10) ::: -## Analyse de l'évolution d'un indice de production +## Ex 5 - Analyse de l'évolution d'un indice de production (moyen) Vous avez à disposition dans le dossier `data/` deux jeux de données CSV : @@ -2788,9 +2792,13 @@ df_clean.glimpse() ### Partie 4 : Calcul de l'évolution périodique -- Utilisez la méthode [shift()](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.Expr.shift.html#polars.Expr.shift) pour créer une nouvelle colonne qui contiendra l'indice du trimestre précédent - Calculez la différence entre l'indice actuel et l'indice décalé pour obtenir l'évolution (en pourcentage) d'un trimestre à l'autre +::: {.callout-tip title="Indice"} + +Utilisez la méthode [shift()](https://docs.pola.rs/api/python/stable/reference/expressions/api/polars.Expr.shift.html#polars.Expr.shift) pour créer une nouvelle colonne qui contiendra l'indice du trimestre précédent + +::: ```{python} # Testez votre réponse dans cette cellule From 8d0c1209ec0a6c80f95d71fdad6983aa0230870e Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 13:43:17 +0000 Subject: [PATCH 66/92] add remark to return statement #26 --- source/fundamentals/oop/tutorial.qmd | 38 ++++++++++++++-------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/source/fundamentals/oop/tutorial.qmd b/source/fundamentals/oop/tutorial.qmd index 4972fc6c..14ca4800 100644 --- a/source/fundamentals/oop/tutorial.qmd +++ b/source/fundamentals/oop/tutorial.qmd @@ -24,7 +24,7 @@ print(type({})) def f(x): print(x) - + print(type(f)) ``` @@ -43,10 +43,10 @@ class Citron: self.saveur = "acide" self.couleur = couleur self.jus = qte_jus - + def recup_qte_jus(self): print("Il reste " + str(self.jus) + " mL de jus dans le citron.") - + def extraire_jus(self, quantite): if quantite > self.jus: print("Il n'y a pas assez de jus dans le citron pour la quantité demandée.") @@ -64,7 +64,7 @@ Analysons la syntaxe de construction d'une classe d'objets : - le constructeur a un paramètre obligatoire : `self`. C'est une référence aux **instances** qui vont être créées à partir de cette classe. Notons la syntaxe qui définit un attribut : `self.attribut = valeur`. -- les autres méthodes sont définies par l'utilisateur. Elles prennent également le `self` en paramètre, ce qui leur permet d'effectuer des opérations sur / à partir des attributs. Comme ce sont des fonctions, elles peuvent également admettre d'autres paramètres. Ainsi, la fonction `extraire_jus` prend un paramètre `quantite` qui définit quelle quantité de jus on extrait du citron lorsqu'on le presse. +- les autres méthodes sont définies par l'utilisateur. Elles prennent également le `self` en paramètre, ce qui leur permet d'effectuer des opérations sur / à partir des attributs. Comme ce sont des fonctions, elles peuvent également admettre d'autres paramètres. Ainsi, la fonction `extraire_jus` prend un paramètre `quantite` qui définit quelle quantité de jus on extrait du citron lorsqu'on le presse. On peut remarquer que les méthodes ne prennent pas de déclaration `return`, contrairement aux fonctions. ## La classe et ses instances @@ -202,7 +202,7 @@ Les trois exécutions donnent des résultats différents, alors que le code exé - 3/ A quoi sert le constructeur `__init__` ? -- 4/ A quoi sert le `self` ? +- 4/ A quoi sert le `self` ? - 5/ Quelle est la différence entre une classe et une instance ? @@ -268,10 +268,10 @@ class Citron: self.saveur = "acide" self.couleur = couleur self.jus = qte_jus - + def recup_qte_jus(self): print("Il reste " + str(self.jus) + " mL de jus dans le citron.") - + def extraire_jus(self, quantite): if quantite > self.jus: print("Il n'y a pas assez de jus dans le citron pour la quantité demandée.") @@ -297,19 +297,19 @@ class Citron: self.couleur = couleur self.masse = masse self.jus = masse / 4 - + def recup_masse(self): print("La masse du citron est " + str(self.masse) + " grammes.") - + def recup_qte_jus(self): print("Il reste " + str(self.jus) + " mL de jus dans le citron.") - + def extraire_jus(self, quantite): if quantite > self.jus: print("Il n'y a pas assez de jus dans le citron pour la quantité demandée.") else: self.jus = max(0, self.jus - quantite) # évite toute valeur négative de `jus` - + citron = Citron("jaune", 500) citron.recup_masse() @@ -333,7 +333,7 @@ Implémenter une classe `Compte` avec : - une méthode `depot` qui admet un paramètre `montant`. Lorsqu'un dépôt est effectué, le solde du compte est incrémenté du montant du dépôt. -- une méthode `retrait` qui admet un paramètre `montant`. Lorsqu'un retrait est effectué : +- une méthode `retrait` qui admet un paramètre `montant`. Lorsqu'un retrait est effectué : - si le montant est inférieur au solde : le solde est décrémenté du montant, est on affiche "Retrait accepté.". @@ -344,7 +344,7 @@ Implémenter une classe `Compte` avec : - si le montant est inférieur au solde de client1 : le solde de client1 est décrémenté du montant, le solde de client2 est incrémenté du montant. - si le montant est supérieur au solde de client1 : on affiche "Transfert refusé : fonds insuffisants." et les soldes des deux clients restent inchangés. - + Créer deux clients et tester que les différentes fonctionnalités à implémenter marchent comme prévu. ```{python} @@ -362,27 +362,27 @@ class Compte: def __init__(self, titulaire, solde): self.titulaire = titulaire self.solde = solde - + def affiche_solde(self): print("Le solde du compte de " + self.titulaire + " est " + str(self.solde) + " euros.") - + def depot(self, montant): self.solde += montant - + def retrait(self, montant): if self.solde >= montant: self.solde -= montant print("Retrait accepté.") else: print("Retrait refusé : fonds insuffisants.") - + def transfert(self, destinataire, montant): if self.solde >= montant: destinataire.solde += montant self.solde -= montant else: print("Transfert refusé : fonds insuffisants.") - + client1 = Compte("Bernard", 2000) client2 = Compte("Bianca", 5000) @@ -830,4 +830,4 @@ client1.show_balance() # + 2000 ::: -::: \ No newline at end of file +::: From 34638eae383f545fd1d07200be051163d308dbf8 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Fri, 19 Dec 2025 15:02:34 +0000 Subject: [PATCH 67/92] meteo app : API issue #31 --- applis_nt/solutions_meteo.py | 47 ++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 applis_nt/solutions_meteo.py diff --git a/applis_nt/solutions_meteo.py b/applis_nt/solutions_meteo.py new file mode 100644 index 00000000..2921a088 --- /dev/null +++ b/applis_nt/solutions_meteo.py @@ -0,0 +1,47 @@ +import polars as pl +import requests +import seaborn as sns +import matplotlib.pyplot as plt + +# import solutions + +def build_request_nominatim(country, city): + url_request = f"https://nominatim.openstreetmap.org/search?country={country}&city={city}&format=json" + return url_request + +requests.get(build_request_nominatim('France', 'Montrouge')) + +def get_lat_long(query): + response = requests.get(query) + code = response.status_code + if code == 200: + json_data = response.json() + latitude = float(json_data[0]["lat"]) + longitude = float(json_data[0]["lon"]) + return latitude, longitude + else: + print(f"Error code : {code}") + return None + + +def build_request_open_meteo(latitude, longitude): + url_request = f"https://api.open-meteo.com/v1/forecast?latitude={latitude}&longitude={longitude}&hourly=relativehumidity_2m,windspeed_10m" + return url_request + + +response_json = requests.get(build_request_open_meteo(48.8188544, 2.3194375)).json() +pl.DataFrame(response_json).select('hourly').unnest('hourly') +pl.DataFrame(response_json).unnest('hourly') +( + pl.DataFrame(response_json)\ + .select('hourly') + .unnest('hourly') + .explode('time', 'relativehumidity_2m', 'windspeed_10m') + .cast({'time':pl.Datetime}) + .rename({'time': 'date_time', 'relativehumidity_2m': 'humidity', 'windspeed_10m': 'wind_speed'}) + .with_columns( + date=pl.col('date_time').dt.date(), + time=pl.col('date_time').dt.time(), + bhi=pl.col.humidity*pl.col.wind_speed + ) +) \ No newline at end of file From 41cc082b4935cc4934b299f5487a97d93a944189 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Fri, 19 Dec 2025 16:17:09 +0000 Subject: [PATCH 68/92] solution with polars --- applis_nt/solutions_meteo.py | 96 +++++++++++++++++++++++++++++------- 1 file changed, 77 insertions(+), 19 deletions(-) diff --git a/applis_nt/solutions_meteo.py b/applis_nt/solutions_meteo.py index 2921a088..92e7017d 100644 --- a/applis_nt/solutions_meteo.py +++ b/applis_nt/solutions_meteo.py @@ -1,15 +1,12 @@ import polars as pl import requests -import seaborn as sns -import matplotlib.pyplot as plt +from plotnine import ggplot, aes, geom_line, theme_matplotlib, labs # import solutions - def build_request_nominatim(country, city): url_request = f"https://nominatim.openstreetmap.org/search?country={country}&city={city}&format=json" return url_request -requests.get(build_request_nominatim('France', 'Montrouge')) def get_lat_long(query): response = requests.get(query) @@ -29,19 +26,80 @@ def build_request_open_meteo(latitude, longitude): return url_request -response_json = requests.get(build_request_open_meteo(48.8188544, 2.3194375)).json() -pl.DataFrame(response_json).select('hourly').unnest('hourly') -pl.DataFrame(response_json).unnest('hourly') -( - pl.DataFrame(response_json)\ - .select('hourly') - .unnest('hourly') - .explode('time', 'relativehumidity_2m', 'windspeed_10m') - .cast({'time':pl.Datetime}) - .rename({'time': 'date_time', 'relativehumidity_2m': 'humidity', 'windspeed_10m': 'wind_speed'}) - .with_columns( - date=pl.col('date_time').dt.date(), - time=pl.col('date_time').dt.time(), - bhi=pl.col.humidity*pl.col.wind_speed +def get_meteo_data(query): + response = requests.get(query) + code = response.status_code + if code == 200: + data = response.json() + return data + else: + print(f"Error code : {code}") + return None + +# %% +def preprocess_predictions(predictions): + + df = ( + pl.DataFrame(predictions) + .select('hourly') + .unnest('hourly') + .explode('time', 'relativehumidity_2m', 'windspeed_10m') + .cast({'time': pl.Datetime}) + .rename({'time': 'date_time', 'relativehumidity_2m': 'humidity', 'windspeed_10m': 'wind_speed'}) + .with_columns( + day=pl.col('date_time').dt.date(), + hour=pl.col('date_time').dt.hour(), + bad_hair_index=pl.col.humidity*pl.col.wind_speed + ) + ) + + return df + +# %% +def plot_agg_avg_bhi(df_preds, agg_var="day"): + plot = ( + ggplot(df_preds.group_by(agg_var).agg(pl.mean('bad_hair_index')), aes(x=agg_var, y='bad_hair_index')) + + geom_line() + + theme_matplotlib() + ) + if agg_var == "day": + plot = ( + plot + + labs( + title="Evolution of the average BHI on 7 days", + x='Hour', + y='Average Bad Hair Index') + ) + elif agg_var == "hour": + plot = ( + plot + + labs( + title="Average BHI by hour on the next 7 days", + x='Day', + y='Average Bad Hair Index') ) -) \ No newline at end of file + + return plot + + +# %% +def main(country, city, agg_var="day"): +# def main(agg_var="day"): + # Get lat, long from Nominatim API + url_request_nominatim = build_request_nominatim(country, city) + lat, long = get_lat_long(query=url_request_nominatim) + # lat, long = (48.8188544, 2.3194375) + + # Get wheather predictions + url_request_open_meteo = build_request_open_meteo(latitude=lat, longitude=long) + predictions = get_meteo_data(url_request_open_meteo) + df_preds = preprocess_predictions(predictions) + + # Graphical representation + return plot_agg_avg_bhi(df_preds, agg_var) + +# %% +main('France', 'Montrouge', 'day') + +# %% +main('France', 'Montrouge', 'hour') \ No newline at end of file From 15a48b34bc8d80b2df4da7f400a35caa9398e17f Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Fri, 19 Dec 2025 16:33:58 +0000 Subject: [PATCH 69/92] add error handling case --- applis_nt/solutions_meteo.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/applis_nt/solutions_meteo.py b/applis_nt/solutions_meteo.py index 92e7017d..d2141cbd 100644 --- a/applis_nt/solutions_meteo.py +++ b/applis_nt/solutions_meteo.py @@ -57,6 +57,9 @@ def preprocess_predictions(predictions): # %% def plot_agg_avg_bhi(df_preds, agg_var="day"): + if agg_var not in ['day', 'hour']: + raise ValueError('Not the right aggregation variable') + plot = ( ggplot(df_preds.group_by(agg_var).agg(pl.mean('bad_hair_index')), aes(x=agg_var, y='bad_hair_index')) + geom_line() From f8a8a96d96382e079045a78372dce0e606472e09 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 23 Dec 2025 16:14:49 +0000 Subject: [PATCH 70/92] RP with polars with functions to load one year and the whole dataset #31 --- applis_nt/solutions_rp.py | 59 +++ pyproject.toml | 17 +- uv.lock | 762 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 830 insertions(+), 8 deletions(-) create mode 100644 applis_nt/solutions_rp.py diff --git a/applis_nt/solutions_rp.py b/applis_nt/solutions_rp.py new file mode 100644 index 00000000..a3f7afb2 --- /dev/null +++ b/applis_nt/solutions_rp.py @@ -0,0 +1,59 @@ +# import copy +import polars as pl +import plotnine as p9 +import geopandas as gpd +# import seaborn as sns +# import fastexcel +# import solutions + +def load_data(): + data = pl.read_excel( + 'https://www.insee.fr/fr/statistiques/fichier/1893198/estim-pop-dep-sexe-aq-1975-2023.xls', + sheet_name=[str(i) for i in range(1975,2024,1)], + read_options={ "header_row": 3}) + + return data + + +def reshape_table_by_year(df, year): + # Merging columns to Genre__Age + temp_colnames_list = df.columns + for index, colname in enumerate(temp_colnames_list): + if colname[:11] == '__UNNAMED__': + if df[0, colname] is not None: + temp_colnames_list[index] = temp_colnames_list[index-1].split("_")[0] + "__" + df[0, colname] + else: + temp_colnames_list[index] = temp_colnames_list[index-1].split("_")[0] + "__00" + df_new = df.rename(dict(zip(df.columns, temp_colnames_list))) + + # Reshaping data + df_new = ( + df_new.drop_nulls(pl.col('Départements__00')) + .unpivot(index=['Départements', 'Départements__00'], value_name="population") + .with_columns( + variablelist=pl.col.variable.str.split('__') + ) + .with_columns( + genre=pl.col.variablelist.list.get(0, null_on_oob=True), + age=pl.col.variablelist.list.get(1, null_on_oob=True), + population=pl.col.population.cast(pl.Int64), + annee=pl.lit(year) + ) + .rename({'Départements':'dep_code','Départements__00':'dep'}) + .select({'genre', 'age', 'population', 'dep_code', 'dep', 'annee'}) + ) + + return df_new + + +def reshape_data(data): + df = pl.DataFrame(schema= + ['dep', 'population', 'dep_code', 'annee', 'age', 'genre'] + ) + for annee_dic, annee_df in data.items(): + df=pl.concat([df, reshape_table_by_year(annee_df, annee_dic)], strict=False, how='vertical_relaxed') + + return df + + +reshape_data(load_data()) diff --git a/pyproject.toml b/pyproject.toml index cd6f9769..a3acce44 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,9 +1,10 @@ [project] -name = "" -version = "0.0.1" +name = "formation-python-initiation" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" requires-python = ">=3.13" dependencies = [ - "geopandas", "matplotlib", "numpy", "pandas", @@ -11,11 +12,11 @@ dependencies = [ "requests", "seaborn", "scikit-learn", - "xlrd", - "polars>=1.36.1", "tidypolars>=0.3.2", "jupyter>=1.1.1", + "fastexcel>=0.18.0", + "geopandas>=1.1.1", + "plotnine>=0.15.2", + "polars>=1.36.1", + "xlrd>=2.0.2", ] - -[tool.uv] -package = false diff --git a/uv.lock b/uv.lock index ef3786f1..9a6ba890 100644 --- a/uv.lock +++ b/uv.lock @@ -1,6 +1,768 @@ version = 1 revision = 3 requires-python = ">=3.13" + +[[package]] +name = "certifi" +version = "2025.11.12" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/8c/58f469717fa48465e4a50c014a0400602d3c437d7c0c468e17ada824da3a/certifi-2025.11.12.tar.gz", hash = "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316", size = 160538, upload-time = "2025-11-12T02:54:51.517Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", size = 159438, upload-time = "2025-11-12T02:54:49.735Z" }, +] + +[[package]] +name = "contourpy" +version = "1.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/58/01/1253e6698a07380cd31a736d248a3f2a50a7c88779a1813da27503cadc2a/contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880", size = 13466174, upload-time = "2025-07-26T12:03:12.549Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/68/35/0167aad910bbdb9599272bd96d01a9ec6852f36b9455cf2ca67bd4cc2d23/contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:177fb367556747a686509d6fef71d221a4b198a3905fe824430e5ea0fda54eb5", size = 293257, upload-time = "2025-07-26T12:01:39.367Z" }, + { url = "https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1", size = 274034, upload-time = "2025-07-26T12:01:40.645Z" }, + { url = "https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286", size = 334672, upload-time = "2025-07-26T12:01:41.942Z" }, + { url = "https://files.pythonhosted.org/packages/ed/93/b43d8acbe67392e659e1d984700e79eb67e2acb2bd7f62012b583a7f1b55/contourpy-1.3.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:655456777ff65c2c548b7c454af9c6f33f16c8884f11083244b5819cc214f1b5", size = 381234, upload-time = "2025-07-26T12:01:43.499Z" }, + { url = "https://files.pythonhosted.org/packages/46/3b/bec82a3ea06f66711520f75a40c8fc0b113b2a75edb36aa633eb11c4f50f/contourpy-1.3.3-cp313-cp313-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:644a6853d15b2512d67881586bd03f462c7ab755db95f16f14d7e238f2852c67", size = 385169, upload-time = "2025-07-26T12:01:45.219Z" }, + { url = "https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9", size = 362859, upload-time = "2025-07-26T12:01:46.519Z" }, + { url = "https://files.pythonhosted.org/packages/33/71/e2a7945b7de4e58af42d708a219f3b2f4cff7386e6b6ab0a0fa0033c49a9/contourpy-1.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a15459b0f4615b00bbd1e91f1b9e19b7e63aea7483d03d804186f278c0af2659", size = 1332062, upload-time = "2025-07-26T12:01:48.964Z" }, + { url = "https://files.pythonhosted.org/packages/12/fc/4e87ac754220ccc0e807284f88e943d6d43b43843614f0a8afa469801db0/contourpy-1.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca0fdcd73925568ca027e0b17ab07aad764be4706d0a925b89227e447d9737b7", size = 1403932, upload-time = "2025-07-26T12:01:51.979Z" }, + { url = "https://files.pythonhosted.org/packages/a6/2e/adc197a37443f934594112222ac1aa7dc9a98faf9c3842884df9a9d8751d/contourpy-1.3.3-cp313-cp313-win32.whl", hash = "sha256:b20c7c9a3bf701366556e1b1984ed2d0cedf999903c51311417cf5f591d8c78d", size = 185024, upload-time = "2025-07-26T12:01:53.245Z" }, + { url = "https://files.pythonhosted.org/packages/18/0b/0098c214843213759692cc638fce7de5c289200a830e5035d1791d7a2338/contourpy-1.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:1cadd8b8969f060ba45ed7c1b714fe69185812ab43bd6b86a9123fe8f99c3263", size = 226578, upload-time = "2025-07-26T12:01:54.422Z" }, + { url = "https://files.pythonhosted.org/packages/8a/9a/2f6024a0c5995243cd63afdeb3651c984f0d2bc727fd98066d40e141ad73/contourpy-1.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:fd914713266421b7536de2bfa8181aa8c699432b6763a0ea64195ebe28bff6a9", size = 193524, upload-time = "2025-07-26T12:01:55.73Z" }, + { url = "https://files.pythonhosted.org/packages/c0/b3/f8a1a86bd3298513f500e5b1f5fd92b69896449f6cab6a146a5d52715479/contourpy-1.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:88df9880d507169449d434c293467418b9f6cbe82edd19284aa0409e7fdb933d", size = 306730, upload-time = "2025-07-26T12:01:57.051Z" }, + { url = "https://files.pythonhosted.org/packages/3f/11/4780db94ae62fc0c2053909b65dc3246bd7cecfc4f8a20d957ad43aa4ad8/contourpy-1.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d06bb1f751ba5d417047db62bca3c8fde202b8c11fb50742ab3ab962c81e8216", size = 287897, upload-time = "2025-07-26T12:01:58.663Z" }, + { url = "https://files.pythonhosted.org/packages/ae/15/e59f5f3ffdd6f3d4daa3e47114c53daabcb18574a26c21f03dc9e4e42ff0/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4e6b05a45525357e382909a4c1600444e2a45b4795163d3b22669285591c1ae", size = 326751, upload-time = "2025-07-26T12:02:00.343Z" }, + { url = "https://files.pythonhosted.org/packages/0f/81/03b45cfad088e4770b1dcf72ea78d3802d04200009fb364d18a493857210/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab3074b48c4e2cf1a960e6bbeb7f04566bf36b1861d5c9d4d8ac04b82e38ba20", size = 375486, upload-time = "2025-07-26T12:02:02.128Z" }, + { url = "https://files.pythonhosted.org/packages/0c/ba/49923366492ffbdd4486e970d421b289a670ae8cf539c1ea9a09822b371a/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c3d53c796f8647d6deb1abe867daeb66dcc8a97e8455efa729516b997b8ed99", size = 388106, upload-time = "2025-07-26T12:02:03.615Z" }, + { url = "https://files.pythonhosted.org/packages/9f/52/5b00ea89525f8f143651f9f03a0df371d3cbd2fccd21ca9b768c7a6500c2/contourpy-1.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50ed930df7289ff2a8d7afeb9603f8289e5704755c7e5c3bbd929c90c817164b", size = 352548, upload-time = "2025-07-26T12:02:05.165Z" }, + { url = "https://files.pythonhosted.org/packages/32/1d/a209ec1a3a3452d490f6b14dd92e72280c99ae3d1e73da74f8277d4ee08f/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4feffb6537d64b84877da813a5c30f1422ea5739566abf0bd18065ac040e120a", size = 1322297, upload-time = "2025-07-26T12:02:07.379Z" }, + { url = "https://files.pythonhosted.org/packages/bc/9e/46f0e8ebdd884ca0e8877e46a3f4e633f6c9c8c4f3f6e72be3fe075994aa/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2b7e9480ffe2b0cd2e787e4df64270e3a0440d9db8dc823312e2c940c167df7e", size = 1391023, upload-time = "2025-07-26T12:02:10.171Z" }, + { url = "https://files.pythonhosted.org/packages/b9/70/f308384a3ae9cd2209e0849f33c913f658d3326900d0ff5d378d6a1422d2/contourpy-1.3.3-cp313-cp313t-win32.whl", hash = "sha256:283edd842a01e3dcd435b1c5116798d661378d83d36d337b8dde1d16a5fc9ba3", size = 196157, upload-time = "2025-07-26T12:02:11.488Z" }, + { url = "https://files.pythonhosted.org/packages/b2/dd/880f890a6663b84d9e34a6f88cded89d78f0091e0045a284427cb6b18521/contourpy-1.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:87acf5963fc2b34825e5b6b048f40e3635dd547f590b04d2ab317c2619ef7ae8", size = 240570, upload-time = "2025-07-26T12:02:12.754Z" }, + { url = "https://files.pythonhosted.org/packages/80/99/2adc7d8ffead633234817ef8e9a87115c8a11927a94478f6bb3d3f4d4f7d/contourpy-1.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:3c30273eb2a55024ff31ba7d052dde990d7d8e5450f4bbb6e913558b3d6c2301", size = 199713, upload-time = "2025-07-26T12:02:14.4Z" }, + { url = "https://files.pythonhosted.org/packages/72/8b/4546f3ab60f78c514ffb7d01a0bd743f90de36f0019d1be84d0a708a580a/contourpy-1.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fde6c716d51c04b1c25d0b90364d0be954624a0ee9d60e23e850e8d48353d07a", size = 292189, upload-time = "2025-07-26T12:02:16.095Z" }, + { url = "https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77", size = 273251, upload-time = "2025-07-26T12:02:17.524Z" }, + { url = "https://files.pythonhosted.org/packages/b1/71/f93e1e9471d189f79d0ce2497007731c1e6bf9ef6d1d61b911430c3db4e5/contourpy-1.3.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22e9b1bd7a9b1d652cd77388465dc358dafcd2e217d35552424aa4f996f524f5", size = 335810, upload-time = "2025-07-26T12:02:18.9Z" }, + { url = "https://files.pythonhosted.org/packages/91/f9/e35f4c1c93f9275d4e38681a80506b5510e9327350c51f8d4a5a724d178c/contourpy-1.3.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a22738912262aa3e254e4f3cb079a95a67132fc5a063890e224393596902f5a4", size = 382871, upload-time = "2025-07-26T12:02:20.418Z" }, + { url = "https://files.pythonhosted.org/packages/b5/71/47b512f936f66a0a900d81c396a7e60d73419868fba959c61efed7a8ab46/contourpy-1.3.3-cp314-cp314-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:afe5a512f31ee6bd7d0dda52ec9864c984ca3d66664444f2d72e0dc4eb832e36", size = 386264, upload-time = "2025-07-26T12:02:21.916Z" }, + { url = "https://files.pythonhosted.org/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3", size = 363819, upload-time = "2025-07-26T12:02:23.759Z" }, + { url = "https://files.pythonhosted.org/packages/3e/a6/0b185d4cc480ee494945cde102cb0149ae830b5fa17bf855b95f2e70ad13/contourpy-1.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1fd43c3be4c8e5fd6e4f2baeae35ae18176cf2e5cced681cca908addf1cdd53b", size = 1333650, upload-time = "2025-07-26T12:02:26.181Z" }, + { url = "https://files.pythonhosted.org/packages/43/d7/afdc95580ca56f30fbcd3060250f66cedbde69b4547028863abd8aa3b47e/contourpy-1.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6afc576f7b33cf00996e5c1102dc2a8f7cc89e39c0b55df93a0b78c1bd992b36", size = 1404833, upload-time = "2025-07-26T12:02:28.782Z" }, + { url = "https://files.pythonhosted.org/packages/e2/e2/366af18a6d386f41132a48f033cbd2102e9b0cf6345d35ff0826cd984566/contourpy-1.3.3-cp314-cp314-win32.whl", hash = "sha256:66c8a43a4f7b8df8b71ee1840e4211a3c8d93b214b213f590e18a1beca458f7d", size = 189692, upload-time = "2025-07-26T12:02:30.128Z" }, + { url = "https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd", size = 232424, upload-time = "2025-07-26T12:02:31.395Z" }, + { url = "https://files.pythonhosted.org/packages/18/79/a9416650df9b525737ab521aa181ccc42d56016d2123ddcb7b58e926a42c/contourpy-1.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:95b181891b4c71de4bb404c6621e7e2390745f887f2a026b2d99e92c17892339", size = 198300, upload-time = "2025-07-26T12:02:32.956Z" }, + { url = "https://files.pythonhosted.org/packages/1f/42/38c159a7d0f2b7b9c04c64ab317042bb6952b713ba875c1681529a2932fe/contourpy-1.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:33c82d0138c0a062380332c861387650c82e4cf1747aaa6938b9b6516762e772", size = 306769, upload-time = "2025-07-26T12:02:34.2Z" }, + { url = "https://files.pythonhosted.org/packages/c3/6c/26a8205f24bca10974e77460de68d3d7c63e282e23782f1239f226fcae6f/contourpy-1.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ea37e7b45949df430fe649e5de8351c423430046a2af20b1c1961cae3afcda77", size = 287892, upload-time = "2025-07-26T12:02:35.807Z" }, + { url = "https://files.pythonhosted.org/packages/66/06/8a475c8ab718ebfd7925661747dbb3c3ee9c82ac834ccb3570be49d129f4/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d304906ecc71672e9c89e87c4675dc5c2645e1f4269a5063b99b0bb29f232d13", size = 326748, upload-time = "2025-07-26T12:02:37.193Z" }, + { url = "https://files.pythonhosted.org/packages/b4/a3/c5ca9f010a44c223f098fccd8b158bb1cb287378a31ac141f04730dc49be/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca658cd1a680a5c9ea96dc61cdbae1e85c8f25849843aa799dfd3cb370ad4fbe", size = 375554, upload-time = "2025-07-26T12:02:38.894Z" }, + { url = "https://files.pythonhosted.org/packages/80/5b/68bd33ae63fac658a4145088c1e894405e07584a316738710b636c6d0333/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ab2fd90904c503739a75b7c8c5c01160130ba67944a7b77bbf36ef8054576e7f", size = 388118, upload-time = "2025-07-26T12:02:40.642Z" }, + { url = "https://files.pythonhosted.org/packages/40/52/4c285a6435940ae25d7410a6c36bda5145839bc3f0beb20c707cda18b9d2/contourpy-1.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7301b89040075c30e5768810bc96a8e8d78085b47d8be6e4c3f5a0b4ed478a0", size = 352555, upload-time = "2025-07-26T12:02:42.25Z" }, + { url = "https://files.pythonhosted.org/packages/24/ee/3e81e1dd174f5c7fefe50e85d0892de05ca4e26ef1c9a59c2a57e43b865a/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2a2a8b627d5cc6b7c41a4beff6c5ad5eb848c88255fda4a8745f7e901b32d8e4", size = 1322295, upload-time = "2025-07-26T12:02:44.668Z" }, + { url = "https://files.pythonhosted.org/packages/3c/b2/6d913d4d04e14379de429057cd169e5e00f6c2af3bb13e1710bcbdb5da12/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fd6ec6be509c787f1caf6b247f0b1ca598bef13f4ddeaa126b7658215529ba0f", size = 1391027, upload-time = "2025-07-26T12:02:47.09Z" }, + { url = "https://files.pythonhosted.org/packages/93/8a/68a4ec5c55a2971213d29a9374913f7e9f18581945a7a31d1a39b5d2dfe5/contourpy-1.3.3-cp314-cp314t-win32.whl", hash = "sha256:e74a9a0f5e3fff48fb5a7f2fd2b9b70a3fe014a67522f79b7cca4c0c7e43c9ae", size = 202428, upload-time = "2025-07-26T12:02:48.691Z" }, + { url = "https://files.pythonhosted.org/packages/fa/96/fd9f641ffedc4fa3ace923af73b9d07e869496c9cc7a459103e6e978992f/contourpy-1.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:13b68d6a62db8eafaebb8039218921399baf6e47bf85006fd8529f2a08ef33fc", size = 250331, upload-time = "2025-07-26T12:02:50.137Z" }, + { url = "https://files.pythonhosted.org/packages/ae/8c/469afb6465b853afff216f9528ffda78a915ff880ed58813ba4faf4ba0b6/contourpy-1.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b7448cb5a725bb1e35ce88771b86fba35ef418952474492cf7c764059933ff8b", size = 203831, upload-time = "2025-07-26T12:02:51.449Z" }, +] + +[[package]] +name = "cycler" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615, upload-time = "2023-10-07T05:32:18.335Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" }, +] + +[[package]] +name = "fastexcel" +version = "0.18.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8a/bd/29c2e1689587ca5fa23f2e422e1a845cb6c3b6e19197f56d8ac8360f9889/fastexcel-0.18.0.tar.gz", hash = "sha256:00d82b787ca6dd0fae9c5d75e6c7b0a2c489236ac93e63cba70571e6d3e87568", size = 59027, upload-time = "2025-11-24T11:07:52.799Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c9/af/86df57906c473d0072785360f1951b222ba6d33b2ff1e0bea86ff6070503/fastexcel-0.18.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:6ec6e53de42519b8a080dcaf1ec8e8eca99c5e6a19d30022d168f488b1f0ec12", size = 3065735, upload-time = "2025-11-24T11:07:41.223Z" }, + { url = "https://files.pythonhosted.org/packages/81/74/ce74f5d5a7fd36e3384499fe43bb5db23cf16c98b7f95b0f3a2456361cb3/fastexcel-0.18.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:b7fadce17c6649819709bd06f5acb66bae3ce38112237d80b4816ab791693b73", size = 2857635, upload-time = "2025-11-24T11:07:43.6Z" }, + { url = "https://files.pythonhosted.org/packages/1c/05/68f6145b7230a4e75b8c08a592ce4dcac88567420967aca190b7feee73e3/fastexcel-0.18.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f8edb3e38aa458a110dffd3fb6aabb64ef8e10b8c5cede2d2346e5c04e5e1ef", size = 3185991, upload-time = "2025-11-24T11:07:33.102Z" }, + { url = "https://files.pythonhosted.org/packages/81/c5/d2833ce05892e78979450c0a439a0298bddbb5613244d5d43406341cc217/fastexcel-0.18.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eaebd921d4d89d02293e94739d92965f58873433e77a44a187ed1947769592c", size = 3359228, upload-time = "2025-11-24T11:07:35.07Z" }, + { url = "https://files.pythonhosted.org/packages/d8/71/61572e6c59029a1edfe99ec05722cb1fcdf4825adc49c5c9308fa7e83c24/fastexcel-0.18.0-cp310-abi3-win_amd64.whl", hash = "sha256:259d29c1f40828e4665d64762232dd6680fec2344192ea850ba9fe4f4fddd6de", size = 2890696, upload-time = "2025-11-24T11:07:49.238Z" }, + { url = "https://files.pythonhosted.org/packages/26/f7/30bfe0a608bb26606b76db3ce9493501f2d3d5b0efc29de75175b9b847ca/fastexcel-0.18.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:cb9be21a5b5e28cd77081f37e0a972833c8fb8f1b646986b56f893313672df0a", size = 3057524, upload-time = "2025-11-24T11:07:45.607Z" }, + { url = "https://files.pythonhosted.org/packages/df/1f/e4e91eed5cc9ee7327176483204bf16611884315c11bca273f9e3fecf503/fastexcel-0.18.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:102dfe32348519be7e8055f010f6fad1857201f768d94e418c563c6fde439410", size = 2847009, upload-time = "2025-11-24T11:07:47.352Z" }, + { url = "https://files.pythonhosted.org/packages/c9/c7/8fab170bf0fe48d0179e2bcbbdc797c8f577d7edbb7858fc23483cec2620/fastexcel-0.18.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cf22c4753c9895fe273835e160b52e64edaef89d84585a90f8b82ef1e9adc6a", size = 3185911, upload-time = "2025-11-24T11:07:36.879Z" }, + { url = "https://files.pythonhosted.org/packages/58/a6/0957473ed388e8315d18c7c6e054b37b9f278b27a70afb50f6e3684528df/fastexcel-0.18.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:178cf27b44a8b16be23dc165081c144463322a91b6b4043e60d6cc1b9415233b", size = 3354475, upload-time = "2025-11-24T11:07:39.095Z" }, + { url = "https://files.pythonhosted.org/packages/6f/ff/7c1f5af4b3339910f11a9b621b72e1345b8016c6dff99737e9df1388e911/fastexcel-0.18.0-cp314-cp314t-win_amd64.whl", hash = "sha256:79bb347d1ea573f6ed7de01cec0a3fc850ddaade0096f9500a07692b32541af4", size = 2890781, upload-time = "2025-11-24T11:07:51.133Z" }, +] + +[[package]] +name = "fonttools" +version = "4.61.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/ca/cf17b88a8df95691275a3d77dc0a5ad9907f328ae53acbe6795da1b2f5ed/fonttools-4.61.1.tar.gz", hash = "sha256:6675329885c44657f826ef01d9e4fb33b9158e9d93c537d84ad8399539bc6f69", size = 3565756, upload-time = "2025-12-12T17:31:24.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/cf/00ba28b0990982530addb8dc3e9e6f2fa9cb5c20df2abdda7baa755e8fe1/fonttools-4.61.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8c56c488ab471628ff3bfa80964372fc13504ece601e0d97a78ee74126b2045c", size = 2846454, upload-time = "2025-12-12T17:30:24.938Z" }, + { url = "https://files.pythonhosted.org/packages/5a/ca/468c9a8446a2103ae645d14fee3f610567b7042aba85031c1c65e3ef7471/fonttools-4.61.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dc492779501fa723b04d0ab1f5be046797fee17d27700476edc7ee9ae535a61e", size = 2398191, upload-time = "2025-12-12T17:30:27.343Z" }, + { url = "https://files.pythonhosted.org/packages/a3/4b/d67eedaed19def5967fade3297fed8161b25ba94699efc124b14fb68cdbc/fonttools-4.61.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:64102ca87e84261419c3747a0d20f396eb024bdbeb04c2bfb37e2891f5fadcb5", size = 4928410, upload-time = "2025-12-12T17:30:29.771Z" }, + { url = "https://files.pythonhosted.org/packages/b0/8d/6fb3494dfe61a46258cd93d979cf4725ded4eb46c2a4ca35e4490d84daea/fonttools-4.61.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c1b526c8d3f615a7b1867f38a9410849c8f4aef078535742198e942fba0e9bd", size = 4984460, upload-time = "2025-12-12T17:30:32.073Z" }, + { url = "https://files.pythonhosted.org/packages/f7/f1/a47f1d30b3dc00d75e7af762652d4cbc3dff5c2697a0dbd5203c81afd9c3/fonttools-4.61.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:41ed4b5ec103bd306bb68f81dc166e77409e5209443e5773cb4ed837bcc9b0d3", size = 4925800, upload-time = "2025-12-12T17:30:34.339Z" }, + { url = "https://files.pythonhosted.org/packages/a7/01/e6ae64a0981076e8a66906fab01539799546181e32a37a0257b77e4aa88b/fonttools-4.61.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b501c862d4901792adaec7c25b1ecc749e2662543f68bb194c42ba18d6eec98d", size = 5067859, upload-time = "2025-12-12T17:30:36.593Z" }, + { url = "https://files.pythonhosted.org/packages/73/aa/28e40b8d6809a9b5075350a86779163f074d2b617c15d22343fce81918db/fonttools-4.61.1-cp313-cp313-win32.whl", hash = "sha256:4d7092bb38c53bbc78e9255a59158b150bcdc115a1e3b3ce0b5f267dc35dd63c", size = 2267821, upload-time = "2025-12-12T17:30:38.478Z" }, + { url = "https://files.pythonhosted.org/packages/1a/59/453c06d1d83dc0951b69ef692d6b9f1846680342927df54e9a1ca91c6f90/fonttools-4.61.1-cp313-cp313-win_amd64.whl", hash = "sha256:21e7c8d76f62ab13c9472ccf74515ca5b9a761d1bde3265152a6dc58700d895b", size = 2318169, upload-time = "2025-12-12T17:30:40.951Z" }, + { url = "https://files.pythonhosted.org/packages/32/8f/4e7bf82c0cbb738d3c2206c920ca34ca74ef9dabde779030145d28665104/fonttools-4.61.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fff4f534200a04b4a36e7ae3cb74493afe807b517a09e99cb4faa89a34ed6ecd", size = 2846094, upload-time = "2025-12-12T17:30:43.511Z" }, + { url = "https://files.pythonhosted.org/packages/71/09/d44e45d0a4f3a651f23a1e9d42de43bc643cce2971b19e784cc67d823676/fonttools-4.61.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d9203500f7c63545b4ce3799319fe4d9feb1a1b89b28d3cb5abd11b9dd64147e", size = 2396589, upload-time = "2025-12-12T17:30:45.681Z" }, + { url = "https://files.pythonhosted.org/packages/89/18/58c64cafcf8eb677a99ef593121f719e6dcbdb7d1c594ae5a10d4997ca8a/fonttools-4.61.1-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fa646ecec9528bef693415c79a86e733c70a4965dd938e9a226b0fc64c9d2e6c", size = 4877892, upload-time = "2025-12-12T17:30:47.709Z" }, + { url = "https://files.pythonhosted.org/packages/8a/ec/9e6b38c7ba1e09eb51db849d5450f4c05b7e78481f662c3b79dbde6f3d04/fonttools-4.61.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11f35ad7805edba3aac1a3710d104592df59f4b957e30108ae0ba6c10b11dd75", size = 4972884, upload-time = "2025-12-12T17:30:49.656Z" }, + { url = "https://files.pythonhosted.org/packages/5e/87/b5339da8e0256734ba0dbbf5b6cdebb1dd79b01dc8c270989b7bcd465541/fonttools-4.61.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b931ae8f62db78861b0ff1ac017851764602288575d65b8e8ff1963fed419063", size = 4924405, upload-time = "2025-12-12T17:30:51.735Z" }, + { url = "https://files.pythonhosted.org/packages/0b/47/e3409f1e1e69c073a3a6fd8cb886eb18c0bae0ee13db2c8d5e7f8495e8b7/fonttools-4.61.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b148b56f5de675ee16d45e769e69f87623a4944f7443850bf9a9376e628a89d2", size = 5035553, upload-time = "2025-12-12T17:30:54.823Z" }, + { url = "https://files.pythonhosted.org/packages/bf/b6/1f6600161b1073a984294c6c031e1a56ebf95b6164249eecf30012bb2e38/fonttools-4.61.1-cp314-cp314-win32.whl", hash = "sha256:9b666a475a65f4e839d3d10473fad6d47e0a9db14a2f4a224029c5bfde58ad2c", size = 2271915, upload-time = "2025-12-12T17:30:57.913Z" }, + { url = "https://files.pythonhosted.org/packages/52/7b/91e7b01e37cc8eb0e1f770d08305b3655e4f002fc160fb82b3390eabacf5/fonttools-4.61.1-cp314-cp314-win_amd64.whl", hash = "sha256:4f5686e1fe5fce75d82d93c47a438a25bf0d1319d2843a926f741140b2b16e0c", size = 2323487, upload-time = "2025-12-12T17:30:59.804Z" }, + { url = "https://files.pythonhosted.org/packages/39/5c/908ad78e46c61c3e3ed70c3b58ff82ab48437faf84ec84f109592cabbd9f/fonttools-4.61.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:e76ce097e3c57c4bcb67c5aa24a0ecdbd9f74ea9219997a707a4061fbe2707aa", size = 2929571, upload-time = "2025-12-12T17:31:02.574Z" }, + { url = "https://files.pythonhosted.org/packages/bd/41/975804132c6dea64cdbfbaa59f3518a21c137a10cccf962805b301ac6ab2/fonttools-4.61.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9cfef3ab326780c04d6646f68d4b4742aae222e8b8ea1d627c74e38afcbc9d91", size = 2435317, upload-time = "2025-12-12T17:31:04.974Z" }, + { url = "https://files.pythonhosted.org/packages/b0/5a/aef2a0a8daf1ebaae4cfd83f84186d4a72ee08fd6a8451289fcd03ffa8a4/fonttools-4.61.1-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a75c301f96db737e1c5ed5fd7d77d9c34466de16095a266509e13da09751bd19", size = 4882124, upload-time = "2025-12-12T17:31:07.456Z" }, + { url = "https://files.pythonhosted.org/packages/80/33/d6db3485b645b81cea538c9d1c9219d5805f0877fda18777add4671c5240/fonttools-4.61.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:91669ccac46bbc1d09e9273546181919064e8df73488ea087dcac3e2968df9ba", size = 5100391, upload-time = "2025-12-12T17:31:09.732Z" }, + { url = "https://files.pythonhosted.org/packages/6c/d6/675ba631454043c75fcf76f0ca5463eac8eb0666ea1d7badae5fea001155/fonttools-4.61.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c33ab3ca9d3ccd581d58e989d67554e42d8d4ded94ab3ade3508455fe70e65f7", size = 4978800, upload-time = "2025-12-12T17:31:11.681Z" }, + { url = "https://files.pythonhosted.org/packages/7f/33/d3ec753d547a8d2bdaedd390d4a814e8d5b45a093d558f025c6b990b554c/fonttools-4.61.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:664c5a68ec406f6b1547946683008576ef8b38275608e1cee6c061828171c118", size = 5006426, upload-time = "2025-12-12T17:31:13.764Z" }, + { url = "https://files.pythonhosted.org/packages/b4/40/cc11f378b561a67bea850ab50063366a0d1dd3f6d0a30ce0f874b0ad5664/fonttools-4.61.1-cp314-cp314t-win32.whl", hash = "sha256:aed04cabe26f30c1647ef0e8fbb207516fd40fe9472e9439695f5c6998e60ac5", size = 2335377, upload-time = "2025-12-12T17:31:16.49Z" }, + { url = "https://files.pythonhosted.org/packages/e4/ff/c9a2b66b39f8628531ea58b320d66d951267c98c6a38684daa8f50fb02f8/fonttools-4.61.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2180f14c141d2f0f3da43f3a81bc8aa4684860f6b0e6f9e165a4831f24e6a23b", size = 2400613, upload-time = "2025-12-12T17:31:18.769Z" }, + { url = "https://files.pythonhosted.org/packages/c7/4e/ce75a57ff3aebf6fc1f4e9d508b8e5810618a33d900ad6c19eb30b290b97/fonttools-4.61.1-py3-none-any.whl", hash = "sha256:17d2bf5d541add43822bcf0c43d7d847b160c9bb01d15d5007d84e2217aaa371", size = 1148996, upload-time = "2025-12-12T17:31:21.03Z" }, +] + +[[package]] +name = "formation-python-initiation" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "fastexcel" }, + { name = "geopandas" }, + { name = "plotnine" }, + { name = "polars" }, + { name = "xlrd" }, +] + +[package.metadata] +requires-dist = [ + { name = "fastexcel", specifier = ">=0.18.0" }, + { name = "geopandas", specifier = ">=1.1.1" }, + { name = "plotnine", specifier = ">=0.15.2" }, + { name = "polars", specifier = ">=1.36.1" }, + { name = "xlrd", specifier = ">=2.0.2" }, +] + +[[package]] +name = "geopandas" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, + { name = "packaging" }, + { name = "pandas" }, + { name = "pyogrio" }, + { name = "pyproj" }, + { name = "shapely" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8c/76/e1960ba846f153ab109575242abf89dc98f8e057faa32f3decf4cce9247a/geopandas-1.1.1.tar.gz", hash = "sha256:1745713f64d095c43e72e08e753dbd271678254b24f2e01db8cdb8debe1d293d", size = 332655, upload-time = "2025-06-26T21:04:56.57Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0b/70/d5cd0696eff08e62fdbdebe5b46527facb4e7220eabe0ac6225efab50168/geopandas-1.1.1-py3-none-any.whl", hash = "sha256:589e61aaf39b19828843df16cb90234e72897e2579be236f10eee0d052ad98e8", size = 338365, upload-time = "2025-06-26T21:04:55.139Z" }, +] + +[[package]] +name = "kiwisolver" +version = "1.4.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5c/3c/85844f1b0feb11ee581ac23fe5fce65cd049a200c1446708cc1b7f922875/kiwisolver-1.4.9.tar.gz", hash = "sha256:c3b22c26c6fd6811b0ae8363b95ca8ce4ea3c202d3d0975b2914310ceb1bcc4d", size = 97564, upload-time = "2025-08-10T21:27:49.279Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/c1/c2686cda909742ab66c7388e9a1a8521a59eb89f8bcfbee28fc980d07e24/kiwisolver-1.4.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5d0432ccf1c7ab14f9949eec60c5d1f924f17c037e9f8b33352fa05799359b8", size = 123681, upload-time = "2025-08-10T21:26:26.725Z" }, + { url = "https://files.pythonhosted.org/packages/ca/f0/f44f50c9f5b1a1860261092e3bc91ecdc9acda848a8b8c6abfda4a24dd5c/kiwisolver-1.4.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efb3a45b35622bb6c16dbfab491a8f5a391fe0e9d45ef32f4df85658232ca0e2", size = 66464, upload-time = "2025-08-10T21:26:27.733Z" }, + { url = "https://files.pythonhosted.org/packages/2d/7a/9d90a151f558e29c3936b8a47ac770235f436f2120aca41a6d5f3d62ae8d/kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1a12cf6398e8a0a001a059747a1cbf24705e18fe413bc22de7b3d15c67cffe3f", size = 64961, upload-time = "2025-08-10T21:26:28.729Z" }, + { url = "https://files.pythonhosted.org/packages/e9/e9/f218a2cb3a9ffbe324ca29a9e399fa2d2866d7f348ec3a88df87fc248fc5/kiwisolver-1.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b67e6efbf68e077dd71d1a6b37e43e1a99d0bff1a3d51867d45ee8908b931098", size = 1474607, upload-time = "2025-08-10T21:26:29.798Z" }, + { url = "https://files.pythonhosted.org/packages/d9/28/aac26d4c882f14de59041636292bc838db8961373825df23b8eeb807e198/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5656aa670507437af0207645273ccdfee4f14bacd7f7c67a4306d0dcaeaf6eed", size = 1276546, upload-time = "2025-08-10T21:26:31.401Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ad/8bfc1c93d4cc565e5069162f610ba2f48ff39b7de4b5b8d93f69f30c4bed/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bfc08add558155345129c7803b3671cf195e6a56e7a12f3dde7c57d9b417f525", size = 1294482, upload-time = "2025-08-10T21:26:32.721Z" }, + { url = "https://files.pythonhosted.org/packages/da/f1/6aca55ff798901d8ce403206d00e033191f63d82dd708a186e0ed2067e9c/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:40092754720b174e6ccf9e845d0d8c7d8e12c3d71e7fc35f55f3813e96376f78", size = 1343720, upload-time = "2025-08-10T21:26:34.032Z" }, + { url = "https://files.pythonhosted.org/packages/d1/91/eed031876c595c81d90d0f6fc681ece250e14bf6998c3d7c419466b523b7/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:497d05f29a1300d14e02e6441cf0f5ee81c1ff5a304b0d9fb77423974684e08b", size = 2224907, upload-time = "2025-08-10T21:26:35.824Z" }, + { url = "https://files.pythonhosted.org/packages/e9/ec/4d1925f2e49617b9cca9c34bfa11adefad49d00db038e692a559454dfb2e/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:bdd1a81a1860476eb41ac4bc1e07b3f07259e6d55bbf739b79c8aaedcf512799", size = 2321334, upload-time = "2025-08-10T21:26:37.534Z" }, + { url = "https://files.pythonhosted.org/packages/43/cb/450cd4499356f68802750c6ddc18647b8ea01ffa28f50d20598e0befe6e9/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e6b93f13371d341afee3be9f7c5964e3fe61d5fa30f6a30eb49856935dfe4fc3", size = 2488313, upload-time = "2025-08-10T21:26:39.191Z" }, + { url = "https://files.pythonhosted.org/packages/71/67/fc76242bd99f885651128a5d4fa6083e5524694b7c88b489b1b55fdc491d/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d75aa530ccfaa593da12834b86a0724f58bff12706659baa9227c2ccaa06264c", size = 2291970, upload-time = "2025-08-10T21:26:40.828Z" }, + { url = "https://files.pythonhosted.org/packages/75/bd/f1a5d894000941739f2ae1b65a32892349423ad49c2e6d0771d0bad3fae4/kiwisolver-1.4.9-cp313-cp313-win_amd64.whl", hash = "sha256:dd0a578400839256df88c16abddf9ba14813ec5f21362e1fe65022e00c883d4d", size = 73894, upload-time = "2025-08-10T21:26:42.33Z" }, + { url = "https://files.pythonhosted.org/packages/95/38/dce480814d25b99a391abbddadc78f7c117c6da34be68ca8b02d5848b424/kiwisolver-1.4.9-cp313-cp313-win_arm64.whl", hash = "sha256:d4188e73af84ca82468f09cadc5ac4db578109e52acb4518d8154698d3a87ca2", size = 64995, upload-time = "2025-08-10T21:26:43.889Z" }, + { url = "https://files.pythonhosted.org/packages/e2/37/7d218ce5d92dadc5ebdd9070d903e0c7cf7edfe03f179433ac4d13ce659c/kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:5a0f2724dfd4e3b3ac5a82436a8e6fd16baa7d507117e4279b660fe8ca38a3a1", size = 126510, upload-time = "2025-08-10T21:26:44.915Z" }, + { url = "https://files.pythonhosted.org/packages/23/b0/e85a2b48233daef4b648fb657ebbb6f8367696a2d9548a00b4ee0eb67803/kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1b11d6a633e4ed84fc0ddafd4ebfd8ea49b3f25082c04ad12b8315c11d504dc1", size = 67903, upload-time = "2025-08-10T21:26:45.934Z" }, + { url = "https://files.pythonhosted.org/packages/44/98/f2425bc0113ad7de24da6bb4dae1343476e95e1d738be7c04d31a5d037fd/kiwisolver-1.4.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61874cdb0a36016354853593cffc38e56fc9ca5aa97d2c05d3dcf6922cd55a11", size = 66402, upload-time = "2025-08-10T21:26:47.101Z" }, + { url = "https://files.pythonhosted.org/packages/98/d8/594657886df9f34c4177cc353cc28ca7e6e5eb562d37ccc233bff43bbe2a/kiwisolver-1.4.9-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:60c439763a969a6af93b4881db0eed8fadf93ee98e18cbc35bc8da868d0c4f0c", size = 1582135, upload-time = "2025-08-10T21:26:48.665Z" }, + { url = "https://files.pythonhosted.org/packages/5c/c6/38a115b7170f8b306fc929e166340c24958347308ea3012c2b44e7e295db/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92a2f997387a1b79a75e7803aa7ded2cfbe2823852ccf1ba3bcf613b62ae3197", size = 1389409, upload-time = "2025-08-10T21:26:50.335Z" }, + { url = "https://files.pythonhosted.org/packages/bf/3b/e04883dace81f24a568bcee6eb3001da4ba05114afa622ec9b6fafdc1f5e/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a31d512c812daea6d8b3be3b2bfcbeb091dbb09177706569bcfc6240dcf8b41c", size = 1401763, upload-time = "2025-08-10T21:26:51.867Z" }, + { url = "https://files.pythonhosted.org/packages/9f/80/20ace48e33408947af49d7d15c341eaee69e4e0304aab4b7660e234d6288/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:52a15b0f35dad39862d376df10c5230155243a2c1a436e39eb55623ccbd68185", size = 1453643, upload-time = "2025-08-10T21:26:53.592Z" }, + { url = "https://files.pythonhosted.org/packages/64/31/6ce4380a4cd1f515bdda976a1e90e547ccd47b67a1546d63884463c92ca9/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a30fd6fdef1430fd9e1ba7b3398b5ee4e2887783917a687d86ba69985fb08748", size = 2330818, upload-time = "2025-08-10T21:26:55.051Z" }, + { url = "https://files.pythonhosted.org/packages/fa/e9/3f3fcba3bcc7432c795b82646306e822f3fd74df0ee81f0fa067a1f95668/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cc9617b46837c6468197b5945e196ee9ca43057bb7d9d1ae688101e4e1dddf64", size = 2419963, upload-time = "2025-08-10T21:26:56.421Z" }, + { url = "https://files.pythonhosted.org/packages/99/43/7320c50e4133575c66e9f7dadead35ab22d7c012a3b09bb35647792b2a6d/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:0ab74e19f6a2b027ea4f845a78827969af45ce790e6cb3e1ebab71bdf9f215ff", size = 2594639, upload-time = "2025-08-10T21:26:57.882Z" }, + { url = "https://files.pythonhosted.org/packages/65/d6/17ae4a270d4a987ef8a385b906d2bdfc9fce502d6dc0d3aea865b47f548c/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dba5ee5d3981160c28d5490f0d1b7ed730c22470ff7f6cc26cfcfaacb9896a07", size = 2391741, upload-time = "2025-08-10T21:26:59.237Z" }, + { url = "https://files.pythonhosted.org/packages/2a/8f/8f6f491d595a9e5912971f3f863d81baddccc8a4d0c3749d6a0dd9ffc9df/kiwisolver-1.4.9-cp313-cp313t-win_arm64.whl", hash = "sha256:0749fd8f4218ad2e851e11cc4dc05c7cbc0cbc4267bdfdb31782e65aace4ee9c", size = 68646, upload-time = "2025-08-10T21:27:00.52Z" }, + { url = "https://files.pythonhosted.org/packages/6b/32/6cc0fbc9c54d06c2969faa9c1d29f5751a2e51809dd55c69055e62d9b426/kiwisolver-1.4.9-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:9928fe1eb816d11ae170885a74d074f57af3a0d65777ca47e9aeb854a1fba386", size = 123806, upload-time = "2025-08-10T21:27:01.537Z" }, + { url = "https://files.pythonhosted.org/packages/b2/dd/2bfb1d4a4823d92e8cbb420fe024b8d2167f72079b3bb941207c42570bdf/kiwisolver-1.4.9-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d0005b053977e7b43388ddec89fa567f43d4f6d5c2c0affe57de5ebf290dc552", size = 66605, upload-time = "2025-08-10T21:27:03.335Z" }, + { url = "https://files.pythonhosted.org/packages/f7/69/00aafdb4e4509c2ca6064646cba9cd4b37933898f426756adb2cb92ebbed/kiwisolver-1.4.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2635d352d67458b66fd0667c14cb1d4145e9560d503219034a18a87e971ce4f3", size = 64925, upload-time = "2025-08-10T21:27:04.339Z" }, + { url = "https://files.pythonhosted.org/packages/43/dc/51acc6791aa14e5cb6d8a2e28cefb0dc2886d8862795449d021334c0df20/kiwisolver-1.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:767c23ad1c58c9e827b649a9ab7809fd5fd9db266a9cf02b0e926ddc2c680d58", size = 1472414, upload-time = "2025-08-10T21:27:05.437Z" }, + { url = "https://files.pythonhosted.org/packages/3d/bb/93fa64a81db304ac8a246f834d5094fae4b13baf53c839d6bb6e81177129/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72d0eb9fba308b8311685c2268cf7d0a0639a6cd027d8128659f72bdd8a024b4", size = 1281272, upload-time = "2025-08-10T21:27:07.063Z" }, + { url = "https://files.pythonhosted.org/packages/70/e6/6df102916960fb8d05069d4bd92d6d9a8202d5a3e2444494e7cd50f65b7a/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f68e4f3eeca8fb22cc3d731f9715a13b652795ef657a13df1ad0c7dc0e9731df", size = 1298578, upload-time = "2025-08-10T21:27:08.452Z" }, + { url = "https://files.pythonhosted.org/packages/7c/47/e142aaa612f5343736b087864dbaebc53ea8831453fb47e7521fa8658f30/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d84cd4061ae292d8ac367b2c3fa3aad11cb8625a95d135fe93f286f914f3f5a6", size = 1345607, upload-time = "2025-08-10T21:27:10.125Z" }, + { url = "https://files.pythonhosted.org/packages/54/89/d641a746194a0f4d1a3670fb900d0dbaa786fb98341056814bc3f058fa52/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a60ea74330b91bd22a29638940d115df9dc00af5035a9a2a6ad9399ffb4ceca5", size = 2230150, upload-time = "2025-08-10T21:27:11.484Z" }, + { url = "https://files.pythonhosted.org/packages/aa/6b/5ee1207198febdf16ac11f78c5ae40861b809cbe0e6d2a8d5b0b3044b199/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ce6a3a4e106cf35c2d9c4fa17c05ce0b180db622736845d4315519397a77beaf", size = 2325979, upload-time = "2025-08-10T21:27:12.917Z" }, + { url = "https://files.pythonhosted.org/packages/fc/ff/b269eefd90f4ae14dcc74973d5a0f6d28d3b9bb1afd8c0340513afe6b39a/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:77937e5e2a38a7b48eef0585114fe7930346993a88060d0bf886086d2aa49ef5", size = 2491456, upload-time = "2025-08-10T21:27:14.353Z" }, + { url = "https://files.pythonhosted.org/packages/fc/d4/10303190bd4d30de547534601e259a4fbf014eed94aae3e5521129215086/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:24c175051354f4a28c5d6a31c93906dc653e2bf234e8a4bbfb964892078898ce", size = 2294621, upload-time = "2025-08-10T21:27:15.808Z" }, + { url = "https://files.pythonhosted.org/packages/28/e0/a9a90416fce5c0be25742729c2ea52105d62eda6c4be4d803c2a7be1fa50/kiwisolver-1.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:0763515d4df10edf6d06a3c19734e2566368980d21ebec439f33f9eb936c07b7", size = 75417, upload-time = "2025-08-10T21:27:17.436Z" }, + { url = "https://files.pythonhosted.org/packages/1f/10/6949958215b7a9a264299a7db195564e87900f709db9245e4ebdd3c70779/kiwisolver-1.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:0e4e2bf29574a6a7b7f6cb5fa69293b9f96c928949ac4a53ba3f525dffb87f9c", size = 66582, upload-time = "2025-08-10T21:27:18.436Z" }, + { url = "https://files.pythonhosted.org/packages/ec/79/60e53067903d3bc5469b369fe0dfc6b3482e2133e85dae9daa9527535991/kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d976bbb382b202f71c67f77b0ac11244021cfa3f7dfd9e562eefcea2df711548", size = 126514, upload-time = "2025-08-10T21:27:19.465Z" }, + { url = "https://files.pythonhosted.org/packages/25/d1/4843d3e8d46b072c12a38c97c57fab4608d36e13fe47d47ee96b4d61ba6f/kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2489e4e5d7ef9a1c300a5e0196e43d9c739f066ef23270607d45aba368b91f2d", size = 67905, upload-time = "2025-08-10T21:27:20.51Z" }, + { url = "https://files.pythonhosted.org/packages/8c/ae/29ffcbd239aea8b93108de1278271ae764dfc0d803a5693914975f200596/kiwisolver-1.4.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e2ea9f7ab7fbf18fffb1b5434ce7c69a07582f7acc7717720f1d69f3e806f90c", size = 66399, upload-time = "2025-08-10T21:27:21.496Z" }, + { url = "https://files.pythonhosted.org/packages/a1/ae/d7ba902aa604152c2ceba5d352d7b62106bedbccc8e95c3934d94472bfa3/kiwisolver-1.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b34e51affded8faee0dfdb705416153819d8ea9250bbbf7ea1b249bdeb5f1122", size = 1582197, upload-time = "2025-08-10T21:27:22.604Z" }, + { url = "https://files.pythonhosted.org/packages/f2/41/27c70d427eddb8bc7e4f16420a20fefc6f480312122a59a959fdfe0445ad/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8aacd3d4b33b772542b2e01beb50187536967b514b00003bdda7589722d2a64", size = 1390125, upload-time = "2025-08-10T21:27:24.036Z" }, + { url = "https://files.pythonhosted.org/packages/41/42/b3799a12bafc76d962ad69083f8b43b12bf4fe78b097b12e105d75c9b8f1/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7cf974dd4e35fa315563ac99d6287a1024e4dc2077b8a7d7cd3d2fb65d283134", size = 1402612, upload-time = "2025-08-10T21:27:25.773Z" }, + { url = "https://files.pythonhosted.org/packages/d2/b5/a210ea073ea1cfaca1bb5c55a62307d8252f531beb364e18aa1e0888b5a0/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:85bd218b5ecfbee8c8a82e121802dcb519a86044c9c3b2e4aef02fa05c6da370", size = 1453990, upload-time = "2025-08-10T21:27:27.089Z" }, + { url = "https://files.pythonhosted.org/packages/5f/ce/a829eb8c033e977d7ea03ed32fb3c1781b4fa0433fbadfff29e39c676f32/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0856e241c2d3df4efef7c04a1e46b1936b6120c9bcf36dd216e3acd84bc4fb21", size = 2331601, upload-time = "2025-08-10T21:27:29.343Z" }, + { url = "https://files.pythonhosted.org/packages/e0/4b/b5e97eb142eb9cd0072dacfcdcd31b1c66dc7352b0f7c7255d339c0edf00/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9af39d6551f97d31a4deebeac6f45b156f9755ddc59c07b402c148f5dbb6482a", size = 2422041, upload-time = "2025-08-10T21:27:30.754Z" }, + { url = "https://files.pythonhosted.org/packages/40/be/8eb4cd53e1b85ba4edc3a9321666f12b83113a178845593307a3e7891f44/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:bb4ae2b57fc1d8cbd1cf7b1d9913803681ffa903e7488012be5b76dedf49297f", size = 2594897, upload-time = "2025-08-10T21:27:32.803Z" }, + { url = "https://files.pythonhosted.org/packages/99/dd/841e9a66c4715477ea0abc78da039832fbb09dac5c35c58dc4c41a407b8a/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:aedff62918805fb62d43a4aa2ecd4482c380dc76cd31bd7c8878588a61bd0369", size = 2391835, upload-time = "2025-08-10T21:27:34.23Z" }, + { url = "https://files.pythonhosted.org/packages/0c/28/4b2e5c47a0da96896fdfdb006340ade064afa1e63675d01ea5ac222b6d52/kiwisolver-1.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:1fa333e8b2ce4d9660f2cda9c0e1b6bafcfb2457a9d259faa82289e73ec24891", size = 79988, upload-time = "2025-08-10T21:27:35.587Z" }, + { url = "https://files.pythonhosted.org/packages/80/be/3578e8afd18c88cdf9cb4cffde75a96d2be38c5a903f1ed0ceec061bd09e/kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32", size = 70260, upload-time = "2025-08-10T21:27:36.606Z" }, +] + +[[package]] +name = "matplotlib" +version = "3.10.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "contourpy" }, + { name = "cycler" }, + { name = "fonttools" }, + { name = "kiwisolver" }, + { name = "numpy" }, + { name = "packaging" }, + { name = "pillow" }, + { name = "pyparsing" }, + { name = "python-dateutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8a/76/d3c6e3a13fe484ebe7718d14e269c9569c4eb0020a968a327acb3b9a8fe6/matplotlib-3.10.8.tar.gz", hash = "sha256:2299372c19d56bcd35cf05a2738308758d32b9eaed2371898d8f5bd33f084aa3", size = 34806269, upload-time = "2025-12-10T22:56:51.155Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/b9/15fd5541ef4f5b9a17eefd379356cf12175fe577424e7b1d80676516031a/matplotlib-3.10.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3f2e409836d7f5ac2f1c013110a4d50b9f7edc26328c108915f9075d7d7a91b6", size = 8261076, upload-time = "2025-12-10T22:55:44.648Z" }, + { url = "https://files.pythonhosted.org/packages/8d/a0/2ba3473c1b66b9c74dc7107c67e9008cb1782edbe896d4c899d39ae9cf78/matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56271f3dac49a88d7fca5060f004d9d22b865f743a12a23b1e937a0be4818ee1", size = 8148794, upload-time = "2025-12-10T22:55:46.252Z" }, + { url = "https://files.pythonhosted.org/packages/75/97/a471f1c3eb1fd6f6c24a31a5858f443891d5127e63a7788678d14e249aea/matplotlib-3.10.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a0a7f52498f72f13d4a25ea70f35f4cb60642b466cbb0a9be951b5bc3f45a486", size = 8718474, upload-time = "2025-12-10T22:55:47.864Z" }, + { url = "https://files.pythonhosted.org/packages/01/be/cd478f4b66f48256f42927d0acbcd63a26a893136456cd079c0cc24fbabf/matplotlib-3.10.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:646d95230efb9ca614a7a594d4fcacde0ac61d25e37dd51710b36477594963ce", size = 9549637, upload-time = "2025-12-10T22:55:50.048Z" }, + { url = "https://files.pythonhosted.org/packages/5d/7c/8dc289776eae5109e268c4fb92baf870678dc048a25d4ac903683b86d5bf/matplotlib-3.10.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f89c151aab2e2e23cb3fe0acad1e8b82841fd265379c4cecd0f3fcb34c15e0f6", size = 9613678, upload-time = "2025-12-10T22:55:52.21Z" }, + { url = "https://files.pythonhosted.org/packages/64/40/37612487cc8a437d4dd261b32ca21fe2d79510fe74af74e1f42becb1bdb8/matplotlib-3.10.8-cp313-cp313-win_amd64.whl", hash = "sha256:e8ea3e2d4066083e264e75c829078f9e149fa119d27e19acd503de65e0b13149", size = 8142686, upload-time = "2025-12-10T22:55:54.253Z" }, + { url = "https://files.pythonhosted.org/packages/66/52/8d8a8730e968185514680c2a6625943f70269509c3dcfc0dcf7d75928cb8/matplotlib-3.10.8-cp313-cp313-win_arm64.whl", hash = "sha256:c108a1d6fa78a50646029cb6d49808ff0fc1330fda87fa6f6250c6b5369b6645", size = 8012917, upload-time = "2025-12-10T22:55:56.268Z" }, + { url = "https://files.pythonhosted.org/packages/b5/27/51fe26e1062f298af5ef66343d8ef460e090a27fea73036c76c35821df04/matplotlib-3.10.8-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ad3d9833a64cf48cc4300f2b406c3d0f4f4724a91c0bd5640678a6ba7c102077", size = 8305679, upload-time = "2025-12-10T22:55:57.856Z" }, + { url = "https://files.pythonhosted.org/packages/2c/1e/4de865bc591ac8e3062e835f42dd7fe7a93168d519557837f0e37513f629/matplotlib-3.10.8-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:eb3823f11823deade26ce3b9f40dcb4a213da7a670013929f31d5f5ed1055b22", size = 8198336, upload-time = "2025-12-10T22:55:59.371Z" }, + { url = "https://files.pythonhosted.org/packages/c6/cb/2f7b6e75fb4dce87ef91f60cac4f6e34f4c145ab036a22318ec837971300/matplotlib-3.10.8-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d9050fee89a89ed57b4fb2c1bfac9a3d0c57a0d55aed95949eedbc42070fea39", size = 8731653, upload-time = "2025-12-10T22:56:01.032Z" }, + { url = "https://files.pythonhosted.org/packages/46/b3/bd9c57d6ba670a37ab31fb87ec3e8691b947134b201f881665b28cc039ff/matplotlib-3.10.8-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b44d07310e404ba95f8c25aa5536f154c0a8ec473303535949e52eb71d0a1565", size = 9561356, upload-time = "2025-12-10T22:56:02.95Z" }, + { url = "https://files.pythonhosted.org/packages/c0/3d/8b94a481456dfc9dfe6e39e93b5ab376e50998cddfd23f4ae3b431708f16/matplotlib-3.10.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0a33deb84c15ede243aead39f77e990469fff93ad1521163305095b77b72ce4a", size = 9614000, upload-time = "2025-12-10T22:56:05.411Z" }, + { url = "https://files.pythonhosted.org/packages/bd/cd/bc06149fe5585ba800b189a6a654a75f1f127e8aab02fd2be10df7fa500c/matplotlib-3.10.8-cp313-cp313t-win_amd64.whl", hash = "sha256:3a48a78d2786784cc2413e57397981fb45c79e968d99656706018d6e62e57958", size = 8220043, upload-time = "2025-12-10T22:56:07.551Z" }, + { url = "https://files.pythonhosted.org/packages/e3/de/b22cf255abec916562cc04eef457c13e58a1990048de0c0c3604d082355e/matplotlib-3.10.8-cp313-cp313t-win_arm64.whl", hash = "sha256:15d30132718972c2c074cd14638c7f4592bd98719e2308bccea40e0538bc0cb5", size = 8062075, upload-time = "2025-12-10T22:56:09.178Z" }, + { url = "https://files.pythonhosted.org/packages/3c/43/9c0ff7a2f11615e516c3b058e1e6e8f9614ddeca53faca06da267c48345d/matplotlib-3.10.8-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b53285e65d4fa4c86399979e956235deb900be5baa7fc1218ea67fbfaeaadd6f", size = 8262481, upload-time = "2025-12-10T22:56:10.885Z" }, + { url = "https://files.pythonhosted.org/packages/6f/ca/e8ae28649fcdf039fda5ef554b40a95f50592a3c47e6f7270c9561c12b07/matplotlib-3.10.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32f8dce744be5569bebe789e46727946041199030db8aeb2954d26013a0eb26b", size = 8151473, upload-time = "2025-12-10T22:56:12.377Z" }, + { url = "https://files.pythonhosted.org/packages/f1/6f/009d129ae70b75e88cbe7e503a12a4c0670e08ed748a902c2568909e9eb5/matplotlib-3.10.8-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4cf267add95b1c88300d96ca837833d4112756045364f5c734a2276038dae27d", size = 9553896, upload-time = "2025-12-10T22:56:14.432Z" }, + { url = "https://files.pythonhosted.org/packages/f5/26/4221a741eb97967bc1fd5e4c52b9aa5a91b2f4ec05b59f6def4d820f9df9/matplotlib-3.10.8-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2cf5bd12cecf46908f286d7838b2abc6c91cda506c0445b8223a7c19a00df008", size = 9824193, upload-time = "2025-12-10T22:56:16.29Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f3/3abf75f38605772cf48a9daf5821cd4f563472f38b4b828c6fba6fa6d06e/matplotlib-3.10.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:41703cc95688f2516b480f7f339d8851a6035f18e100ee6a32bc0b8536a12a9c", size = 9615444, upload-time = "2025-12-10T22:56:18.155Z" }, + { url = "https://files.pythonhosted.org/packages/93/a5/de89ac80f10b8dc615807ee1133cd99ac74082581196d4d9590bea10690d/matplotlib-3.10.8-cp314-cp314-win_amd64.whl", hash = "sha256:83d282364ea9f3e52363da262ce32a09dfe241e4080dcedda3c0db059d3c1f11", size = 8272719, upload-time = "2025-12-10T22:56:20.366Z" }, + { url = "https://files.pythonhosted.org/packages/69/ce/b006495c19ccc0a137b48083168a37bd056392dee02f87dba0472f2797fe/matplotlib-3.10.8-cp314-cp314-win_arm64.whl", hash = "sha256:2c1998e92cd5999e295a731bcb2911c75f597d937341f3030cc24ef2733d78a8", size = 8144205, upload-time = "2025-12-10T22:56:22.239Z" }, + { url = "https://files.pythonhosted.org/packages/68/d9/b31116a3a855bd313c6fcdb7226926d59b041f26061c6c5b1be66a08c826/matplotlib-3.10.8-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:b5a2b97dbdc7d4f353ebf343744f1d1f1cca8aa8bfddb4262fcf4306c3761d50", size = 8305785, upload-time = "2025-12-10T22:56:24.218Z" }, + { url = "https://files.pythonhosted.org/packages/1e/90/6effe8103f0272685767ba5f094f453784057072f49b393e3ea178fe70a5/matplotlib-3.10.8-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3f5c3e4da343bba819f0234186b9004faba952cc420fbc522dc4e103c1985908", size = 8198361, upload-time = "2025-12-10T22:56:26.787Z" }, + { url = "https://files.pythonhosted.org/packages/d7/65/a73188711bea603615fc0baecca1061429ac16940e2385433cc778a9d8e7/matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f62550b9a30afde8c1c3ae450e5eb547d579dd69b25c2fc7a1c67f934c1717a", size = 9561357, upload-time = "2025-12-10T22:56:28.953Z" }, + { url = "https://files.pythonhosted.org/packages/f4/3d/b5c5d5d5be8ce63292567f0e2c43dde9953d3ed86ac2de0a72e93c8f07a1/matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:495672de149445ec1b772ff2c9ede9b769e3cb4f0d0aa7fa730d7f59e2d4e1c1", size = 9823610, upload-time = "2025-12-10T22:56:31.455Z" }, + { url = "https://files.pythonhosted.org/packages/4d/4b/e7beb6bbd49f6bae727a12b270a2654d13c397576d25bd6786e47033300f/matplotlib-3.10.8-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:595ba4d8fe983b88f0eec8c26a241e16d6376fe1979086232f481f8f3f67494c", size = 9614011, upload-time = "2025-12-10T22:56:33.85Z" }, + { url = "https://files.pythonhosted.org/packages/7c/e6/76f2813d31f032e65f6f797e3f2f6e4aab95b65015924b1c51370395c28a/matplotlib-3.10.8-cp314-cp314t-win_amd64.whl", hash = "sha256:25d380fe8b1dc32cf8f0b1b448470a77afb195438bafdf1d858bfb876f3edf7b", size = 8362801, upload-time = "2025-12-10T22:56:36.107Z" }, + { url = "https://files.pythonhosted.org/packages/5d/49/d651878698a0b67f23aa28e17f45a6d6dd3d3f933fa29087fa4ce5947b5a/matplotlib-3.10.8-cp314-cp314t-win_arm64.whl", hash = "sha256:113bb52413ea508ce954a02c10ffd0d565f9c3bc7f2eddc27dfe1731e71c7b5f", size = 8192560, upload-time = "2025-12-10T22:56:38.008Z" }, +] + +[[package]] +name = "mizani" +version = "0.14.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, + { name = "pandas" }, + { name = "scipy" }, + { name = "tzdata", marker = "sys_platform == 'emscripten' or sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6d/19/98f2bd61e5441b687e0a5d3b36041981cc032451f2d11472021b040d27fd/mizani-0.14.3.tar.gz", hash = "sha256:c2fb886b3c9e8109be5b8fd21e1130fba1f0a20230a987146240221209fc0ddd", size = 772470, upload-time = "2025-10-30T20:16:53.268Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5c/d2/4ffcaa27c8a4b4f9ad456da4821c76dfbdfada23e8210cd4d80e1eb3236a/mizani-0.14.3-py3-none-any.whl", hash = "sha256:6d2ca9b1b8366ff85668f0cc1b6095f1e702e26e66f132c4f02a949efa32a688", size = 133433, upload-time = "2025-10-30T20:16:51.218Z" }, +] + +[[package]] +name = "numpy" +version = "2.3.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/76/65/21b3bc86aac7b8f2862db1e808f1ea22b028e30a225a34a5ede9bf8678f2/numpy-2.3.5.tar.gz", hash = "sha256:784db1dcdab56bf0517743e746dfb0f885fc68d948aba86eeec2cba234bdf1c0", size = 20584950, upload-time = "2025-11-16T22:52:42.067Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/69/9cde09f36da4b5a505341180a3f2e6fadc352fd4d2b7096ce9778db83f1a/numpy-2.3.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d0f23b44f57077c1ede8c5f26b30f706498b4862d3ff0a7298b8411dd2f043ff", size = 16728251, upload-time = "2025-11-16T22:50:19.013Z" }, + { url = "https://files.pythonhosted.org/packages/79/fb/f505c95ceddd7027347b067689db71ca80bd5ecc926f913f1a23e65cf09b/numpy-2.3.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa5bc7c5d59d831d9773d1170acac7893ce3a5e130540605770ade83280e7188", size = 12254652, upload-time = "2025-11-16T22:50:21.487Z" }, + { url = "https://files.pythonhosted.org/packages/78/da/8c7738060ca9c31b30e9301ee0cf6c5ffdbf889d9593285a1cead337f9a5/numpy-2.3.5-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:ccc933afd4d20aad3c00bcef049cb40049f7f196e0397f1109dba6fed63267b0", size = 5083172, upload-time = "2025-11-16T22:50:24.562Z" }, + { url = "https://files.pythonhosted.org/packages/a4/b4/ee5bb2537fb9430fd2ef30a616c3672b991a4129bb1c7dcc42aa0abbe5d7/numpy-2.3.5-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:afaffc4393205524af9dfa400fa250143a6c3bc646c08c9f5e25a9f4b4d6a903", size = 6622990, upload-time = "2025-11-16T22:50:26.47Z" }, + { url = "https://files.pythonhosted.org/packages/95/03/dc0723a013c7d7c19de5ef29e932c3081df1c14ba582b8b86b5de9db7f0f/numpy-2.3.5-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c75442b2209b8470d6d5d8b1c25714270686f14c749028d2199c54e29f20b4d", size = 14248902, upload-time = "2025-11-16T22:50:28.861Z" }, + { url = "https://files.pythonhosted.org/packages/f5/10/ca162f45a102738958dcec8023062dad0cbc17d1ab99d68c4e4a6c45fb2b/numpy-2.3.5-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11e06aa0af8c0f05104d56450d6093ee639e15f24ecf62d417329d06e522e017", size = 16597430, upload-time = "2025-11-16T22:50:31.56Z" }, + { url = "https://files.pythonhosted.org/packages/2a/51/c1e29be863588db58175175f057286900b4b3327a1351e706d5e0f8dd679/numpy-2.3.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ed89927b86296067b4f81f108a2271d8926467a8868e554eaf370fc27fa3ccaf", size = 16024551, upload-time = "2025-11-16T22:50:34.242Z" }, + { url = "https://files.pythonhosted.org/packages/83/68/8236589d4dbb87253d28259d04d9b814ec0ecce7cb1c7fed29729f4c3a78/numpy-2.3.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51c55fe3451421f3a6ef9a9c1439e82101c57a2c9eab9feb196a62b1a10b58ce", size = 18533275, upload-time = "2025-11-16T22:50:37.651Z" }, + { url = "https://files.pythonhosted.org/packages/40/56/2932d75b6f13465239e3b7b7e511be27f1b8161ca2510854f0b6e521c395/numpy-2.3.5-cp313-cp313-win32.whl", hash = "sha256:1978155dd49972084bd6ef388d66ab70f0c323ddee6f693d539376498720fb7e", size = 6277637, upload-time = "2025-11-16T22:50:40.11Z" }, + { url = "https://files.pythonhosted.org/packages/0c/88/e2eaa6cffb115b85ed7c7c87775cb8bcf0816816bc98ca8dbfa2ee33fe6e/numpy-2.3.5-cp313-cp313-win_amd64.whl", hash = "sha256:00dc4e846108a382c5869e77c6ed514394bdeb3403461d25a829711041217d5b", size = 12779090, upload-time = "2025-11-16T22:50:42.503Z" }, + { url = "https://files.pythonhosted.org/packages/8f/88/3f41e13a44ebd4034ee17baa384acac29ba6a4fcc2aca95f6f08ca0447d1/numpy-2.3.5-cp313-cp313-win_arm64.whl", hash = "sha256:0472f11f6ec23a74a906a00b48a4dcf3849209696dff7c189714511268d103ae", size = 10194710, upload-time = "2025-11-16T22:50:44.971Z" }, + { url = "https://files.pythonhosted.org/packages/13/cb/71744144e13389d577f867f745b7df2d8489463654a918eea2eeb166dfc9/numpy-2.3.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:414802f3b97f3c1eef41e530aaba3b3c1620649871d8cb38c6eaff034c2e16bd", size = 16827292, upload-time = "2025-11-16T22:50:47.715Z" }, + { url = "https://files.pythonhosted.org/packages/71/80/ba9dc6f2a4398e7f42b708a7fdc841bb638d353be255655498edbf9a15a8/numpy-2.3.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5ee6609ac3604fa7780e30a03e5e241a7956f8e2fcfe547d51e3afa5247ac47f", size = 12378897, upload-time = "2025-11-16T22:50:51.327Z" }, + { url = "https://files.pythonhosted.org/packages/2e/6d/db2151b9f64264bcceccd51741aa39b50150de9b602d98ecfe7e0c4bff39/numpy-2.3.5-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:86d835afea1eaa143012a2d7a3f45a3adce2d7adc8b4961f0b362214d800846a", size = 5207391, upload-time = "2025-11-16T22:50:54.542Z" }, + { url = "https://files.pythonhosted.org/packages/80/ae/429bacace5ccad48a14c4ae5332f6aa8ab9f69524193511d60ccdfdc65fa/numpy-2.3.5-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:30bc11310e8153ca664b14c5f1b73e94bd0503681fcf136a163de856f3a50139", size = 6721275, upload-time = "2025-11-16T22:50:56.794Z" }, + { url = "https://files.pythonhosted.org/packages/74/5b/1919abf32d8722646a38cd527bc3771eb229a32724ee6ba340ead9b92249/numpy-2.3.5-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1062fde1dcf469571705945b0f221b73928f34a20c904ffb45db101907c3454e", size = 14306855, upload-time = "2025-11-16T22:50:59.208Z" }, + { url = "https://files.pythonhosted.org/packages/a5/87/6831980559434973bebc30cd9c1f21e541a0f2b0c280d43d3afd909b66d0/numpy-2.3.5-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ce581db493ea1a96c0556360ede6607496e8bf9b3a8efa66e06477267bc831e9", size = 16657359, upload-time = "2025-11-16T22:51:01.991Z" }, + { url = "https://files.pythonhosted.org/packages/dd/91/c797f544491ee99fd00495f12ebb7802c440c1915811d72ac5b4479a3356/numpy-2.3.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:cc8920d2ec5fa99875b670bb86ddeb21e295cb07aa331810d9e486e0b969d946", size = 16093374, upload-time = "2025-11-16T22:51:05.291Z" }, + { url = "https://files.pythonhosted.org/packages/74/a6/54da03253afcbe7a72785ec4da9c69fb7a17710141ff9ac5fcb2e32dbe64/numpy-2.3.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:9ee2197ef8c4f0dfe405d835f3b6a14f5fee7782b5de51ba06fb65fc9b36e9f1", size = 18594587, upload-time = "2025-11-16T22:51:08.585Z" }, + { url = "https://files.pythonhosted.org/packages/80/e9/aff53abbdd41b0ecca94285f325aff42357c6b5abc482a3fcb4994290b18/numpy-2.3.5-cp313-cp313t-win32.whl", hash = "sha256:70b37199913c1bd300ff6e2693316c6f869c7ee16378faf10e4f5e3275b299c3", size = 6405940, upload-time = "2025-11-16T22:51:11.541Z" }, + { url = "https://files.pythonhosted.org/packages/d5/81/50613fec9d4de5480de18d4f8ef59ad7e344d497edbef3cfd80f24f98461/numpy-2.3.5-cp313-cp313t-win_amd64.whl", hash = "sha256:b501b5fa195cc9e24fe102f21ec0a44dffc231d2af79950b451e0d99cea02234", size = 12920341, upload-time = "2025-11-16T22:51:14.312Z" }, + { url = "https://files.pythonhosted.org/packages/bb/ab/08fd63b9a74303947f34f0bd7c5903b9c5532c2d287bead5bdf4c556c486/numpy-2.3.5-cp313-cp313t-win_arm64.whl", hash = "sha256:a80afd79f45f3c4a7d341f13acbe058d1ca8ac017c165d3fa0d3de6bc1a079d7", size = 10262507, upload-time = "2025-11-16T22:51:16.846Z" }, + { url = "https://files.pythonhosted.org/packages/ba/97/1a914559c19e32d6b2e233cf9a6a114e67c856d35b1d6babca571a3e880f/numpy-2.3.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:bf06bc2af43fa8d32d30fae16ad965663e966b1a3202ed407b84c989c3221e82", size = 16735706, upload-time = "2025-11-16T22:51:19.558Z" }, + { url = "https://files.pythonhosted.org/packages/57/d4/51233b1c1b13ecd796311216ae417796b88b0616cfd8a33ae4536330748a/numpy-2.3.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:052e8c42e0c49d2575621c158934920524f6c5da05a1d3b9bab5d8e259e045f0", size = 12264507, upload-time = "2025-11-16T22:51:22.492Z" }, + { url = "https://files.pythonhosted.org/packages/45/98/2fe46c5c2675b8306d0b4a3ec3494273e93e1226a490f766e84298576956/numpy-2.3.5-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:1ed1ec893cff7040a02c8aa1c8611b94d395590d553f6b53629a4461dc7f7b63", size = 5093049, upload-time = "2025-11-16T22:51:25.171Z" }, + { url = "https://files.pythonhosted.org/packages/ce/0e/0698378989bb0ac5f1660c81c78ab1fe5476c1a521ca9ee9d0710ce54099/numpy-2.3.5-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:2dcd0808a421a482a080f89859a18beb0b3d1e905b81e617a188bd80422d62e9", size = 6626603, upload-time = "2025-11-16T22:51:27Z" }, + { url = "https://files.pythonhosted.org/packages/5e/a6/9ca0eecc489640615642a6cbc0ca9e10df70df38c4d43f5a928ff18d8827/numpy-2.3.5-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:727fd05b57df37dc0bcf1a27767a3d9a78cbbc92822445f32cc3436ba797337b", size = 14262696, upload-time = "2025-11-16T22:51:29.402Z" }, + { url = "https://files.pythonhosted.org/packages/c8/f6/07ec185b90ec9d7217a00eeeed7383b73d7e709dae2a9a021b051542a708/numpy-2.3.5-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fffe29a1ef00883599d1dc2c51aa2e5d80afe49523c261a74933df395c15c520", size = 16597350, upload-time = "2025-11-16T22:51:32.167Z" }, + { url = "https://files.pythonhosted.org/packages/75/37/164071d1dde6a1a84c9b8e5b414fa127981bad47adf3a6b7e23917e52190/numpy-2.3.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8f7f0e05112916223d3f438f293abf0727e1181b5983f413dfa2fefc4098245c", size = 16040190, upload-time = "2025-11-16T22:51:35.403Z" }, + { url = "https://files.pythonhosted.org/packages/08/3c/f18b82a406b04859eb026d204e4e1773eb41c5be58410f41ffa511d114ae/numpy-2.3.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2e2eb32ddb9ccb817d620ac1d8dae7c3f641c1e5f55f531a33e8ab97960a75b8", size = 18536749, upload-time = "2025-11-16T22:51:39.698Z" }, + { url = "https://files.pythonhosted.org/packages/40/79/f82f572bf44cf0023a2fe8588768e23e1592585020d638999f15158609e1/numpy-2.3.5-cp314-cp314-win32.whl", hash = "sha256:66f85ce62c70b843bab1fb14a05d5737741e74e28c7b8b5a064de10142fad248", size = 6335432, upload-time = "2025-11-16T22:51:42.476Z" }, + { url = "https://files.pythonhosted.org/packages/a3/2e/235b4d96619931192c91660805e5e49242389742a7a82c27665021db690c/numpy-2.3.5-cp314-cp314-win_amd64.whl", hash = "sha256:e6a0bc88393d65807d751a614207b7129a310ca4fe76a74e5c7da5fa5671417e", size = 12919388, upload-time = "2025-11-16T22:51:45.275Z" }, + { url = "https://files.pythonhosted.org/packages/07/2b/29fd75ce45d22a39c61aad74f3d718e7ab67ccf839ca8b60866054eb15f8/numpy-2.3.5-cp314-cp314-win_arm64.whl", hash = "sha256:aeffcab3d4b43712bb7a60b65f6044d444e75e563ff6180af8f98dd4b905dfd2", size = 10476651, upload-time = "2025-11-16T22:51:47.749Z" }, + { url = "https://files.pythonhosted.org/packages/17/e1/f6a721234ebd4d87084cfa68d081bcba2f5cfe1974f7de4e0e8b9b2a2ba1/numpy-2.3.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:17531366a2e3a9e30762c000f2c43a9aaa05728712e25c11ce1dbe700c53ad41", size = 16834503, upload-time = "2025-11-16T22:51:50.443Z" }, + { url = "https://files.pythonhosted.org/packages/5c/1c/baf7ffdc3af9c356e1c135e57ab7cf8d247931b9554f55c467efe2c69eff/numpy-2.3.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d21644de1b609825ede2f48be98dfde4656aefc713654eeee280e37cadc4e0ad", size = 12381612, upload-time = "2025-11-16T22:51:53.609Z" }, + { url = "https://files.pythonhosted.org/packages/74/91/f7f0295151407ddc9ba34e699013c32c3c91944f9b35fcf9281163dc1468/numpy-2.3.5-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:c804e3a5aba5460c73955c955bdbd5c08c354954e9270a2c1565f62e866bdc39", size = 5210042, upload-time = "2025-11-16T22:51:56.213Z" }, + { url = "https://files.pythonhosted.org/packages/2e/3b/78aebf345104ec50dd50a4d06ddeb46a9ff5261c33bcc58b1c4f12f85ec2/numpy-2.3.5-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:cc0a57f895b96ec78969c34f682c602bf8da1a0270b09bc65673df2e7638ec20", size = 6724502, upload-time = "2025-11-16T22:51:58.584Z" }, + { url = "https://files.pythonhosted.org/packages/02/c6/7c34b528740512e57ef1b7c8337ab0b4f0bddf34c723b8996c675bc2bc91/numpy-2.3.5-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:900218e456384ea676e24ea6a0417f030a3b07306d29d7ad843957b40a9d8d52", size = 14308962, upload-time = "2025-11-16T22:52:01.698Z" }, + { url = "https://files.pythonhosted.org/packages/80/35/09d433c5262bc32d725bafc619e095b6a6651caf94027a03da624146f655/numpy-2.3.5-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:09a1bea522b25109bf8e6f3027bd810f7c1085c64a0c7ce050c1676ad0ba010b", size = 16655054, upload-time = "2025-11-16T22:52:04.267Z" }, + { url = "https://files.pythonhosted.org/packages/7a/ab/6a7b259703c09a88804fa2430b43d6457b692378f6b74b356155283566ac/numpy-2.3.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:04822c00b5fd0323c8166d66c701dc31b7fbd252c100acd708c48f763968d6a3", size = 16091613, upload-time = "2025-11-16T22:52:08.651Z" }, + { url = "https://files.pythonhosted.org/packages/c2/88/330da2071e8771e60d1038166ff9d73f29da37b01ec3eb43cb1427464e10/numpy-2.3.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d6889ec4ec662a1a37eb4b4fb26b6100841804dac55bd9df579e326cdc146227", size = 18591147, upload-time = "2025-11-16T22:52:11.453Z" }, + { url = "https://files.pythonhosted.org/packages/51/41/851c4b4082402d9ea860c3626db5d5df47164a712cb23b54be028b184c1c/numpy-2.3.5-cp314-cp314t-win32.whl", hash = "sha256:93eebbcf1aafdf7e2ddd44c2923e2672e1010bddc014138b229e49725b4d6be5", size = 6479806, upload-time = "2025-11-16T22:52:14.641Z" }, + { url = "https://files.pythonhosted.org/packages/90/30/d48bde1dfd93332fa557cff1972fbc039e055a52021fbef4c2c4b1eefd17/numpy-2.3.5-cp314-cp314t-win_amd64.whl", hash = "sha256:c8a9958e88b65c3b27e22ca2a076311636850b612d6bbfb76e8d156aacde2aaf", size = 13105760, upload-time = "2025-11-16T22:52:17.975Z" }, + { url = "https://files.pythonhosted.org/packages/2d/fd/4b5eb0b3e888d86aee4d198c23acec7d214baaf17ea93c1adec94c9518b9/numpy-2.3.5-cp314-cp314t-win_arm64.whl", hash = "sha256:6203fdf9f3dc5bdaed7319ad8698e685c7a3be10819f41d32a0723e611733b42", size = 10545459, upload-time = "2025-11-16T22:52:20.55Z" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + +[[package]] +name = "pandas" +version = "2.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, + { name = "python-dateutil" }, + { name = "pytz" }, + { name = "tzdata" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/33/01/d40b85317f86cf08d853a4f495195c73815fdf205eef3993821720274518/pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b", size = 4495223, upload-time = "2025-09-29T23:34:51.853Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cd/4b/18b035ee18f97c1040d94debd8f2e737000ad70ccc8f5513f4eefad75f4b/pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713", size = 11544671, upload-time = "2025-09-29T23:21:05.024Z" }, + { url = "https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8", size = 10680807, upload-time = "2025-09-29T23:21:15.979Z" }, + { url = "https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d", size = 11709872, upload-time = "2025-09-29T23:21:27.165Z" }, + { url = "https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac", size = 12306371, upload-time = "2025-09-29T23:21:40.532Z" }, + { url = "https://files.pythonhosted.org/packages/33/81/a3afc88fca4aa925804a27d2676d22dcd2031c2ebe08aabd0ae55b9ff282/pandas-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c", size = 12765333, upload-time = "2025-09-29T23:21:55.77Z" }, + { url = "https://files.pythonhosted.org/packages/8d/0f/b4d4ae743a83742f1153464cf1a8ecfafc3ac59722a0b5c8602310cb7158/pandas-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493", size = 13418120, upload-time = "2025-09-29T23:22:10.109Z" }, + { url = "https://files.pythonhosted.org/packages/4f/c7/e54682c96a895d0c808453269e0b5928a07a127a15704fedb643e9b0a4c8/pandas-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee", size = 10993991, upload-time = "2025-09-29T23:25:04.889Z" }, + { url = "https://files.pythonhosted.org/packages/f9/ca/3f8d4f49740799189e1395812f3bf23b5e8fc7c190827d55a610da72ce55/pandas-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5", size = 12048227, upload-time = "2025-09-29T23:22:24.343Z" }, + { url = "https://files.pythonhosted.org/packages/0e/5a/f43efec3e8c0cc92c4663ccad372dbdff72b60bdb56b2749f04aa1d07d7e/pandas-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21", size = 11411056, upload-time = "2025-09-29T23:22:37.762Z" }, + { url = "https://files.pythonhosted.org/packages/46/b1/85331edfc591208c9d1a63a06baa67b21d332e63b7a591a5ba42a10bb507/pandas-2.3.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78", size = 11645189, upload-time = "2025-09-29T23:22:51.688Z" }, + { url = "https://files.pythonhosted.org/packages/44/23/78d645adc35d94d1ac4f2a3c4112ab6f5b8999f4898b8cdf01252f8df4a9/pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110", size = 12121912, upload-time = "2025-09-29T23:23:05.042Z" }, + { url = "https://files.pythonhosted.org/packages/53/da/d10013df5e6aaef6b425aa0c32e1fc1f3e431e4bcabd420517dceadce354/pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86", size = 12712160, upload-time = "2025-09-29T23:23:28.57Z" }, + { url = "https://files.pythonhosted.org/packages/bd/17/e756653095a083d8a37cbd816cb87148debcfcd920129b25f99dd8d04271/pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc", size = 13199233, upload-time = "2025-09-29T23:24:24.876Z" }, + { url = "https://files.pythonhosted.org/packages/04/fd/74903979833db8390b73b3a8a7d30d146d710bd32703724dd9083950386f/pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0", size = 11540635, upload-time = "2025-09-29T23:25:52.486Z" }, + { url = "https://files.pythonhosted.org/packages/21/00/266d6b357ad5e6d3ad55093a7e8efc7dd245f5a842b584db9f30b0f0a287/pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593", size = 10759079, upload-time = "2025-09-29T23:26:33.204Z" }, + { url = "https://files.pythonhosted.org/packages/ca/05/d01ef80a7a3a12b2f8bbf16daba1e17c98a2f039cbc8e2f77a2c5a63d382/pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c", size = 11814049, upload-time = "2025-09-29T23:27:15.384Z" }, + { url = "https://files.pythonhosted.org/packages/15/b2/0e62f78c0c5ba7e3d2c5945a82456f4fac76c480940f805e0b97fcbc2f65/pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b", size = 12332638, upload-time = "2025-09-29T23:27:51.625Z" }, + { url = "https://files.pythonhosted.org/packages/c5/33/dd70400631b62b9b29c3c93d2feee1d0964dc2bae2e5ad7a6c73a7f25325/pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6", size = 12886834, upload-time = "2025-09-29T23:28:21.289Z" }, + { url = "https://files.pythonhosted.org/packages/d3/18/b5d48f55821228d0d2692b34fd5034bb185e854bdb592e9c640f6290e012/pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3", size = 13409925, upload-time = "2025-09-29T23:28:58.261Z" }, + { url = "https://files.pythonhosted.org/packages/a6/3d/124ac75fcd0ecc09b8fdccb0246ef65e35b012030defb0e0eba2cbbbe948/pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5", size = 11109071, upload-time = "2025-09-29T23:32:27.484Z" }, + { url = "https://files.pythonhosted.org/packages/89/9c/0e21c895c38a157e0faa1fb64587a9226d6dd46452cac4532d80c3c4a244/pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec", size = 12048504, upload-time = "2025-09-29T23:29:31.47Z" }, + { url = "https://files.pythonhosted.org/packages/d7/82/b69a1c95df796858777b68fbe6a81d37443a33319761d7c652ce77797475/pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7", size = 11410702, upload-time = "2025-09-29T23:29:54.591Z" }, + { url = "https://files.pythonhosted.org/packages/f9/88/702bde3ba0a94b8c73a0181e05144b10f13f29ebfc2150c3a79062a8195d/pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450", size = 11634535, upload-time = "2025-09-29T23:30:21.003Z" }, + { url = "https://files.pythonhosted.org/packages/a4/1e/1bac1a839d12e6a82ec6cb40cda2edde64a2013a66963293696bbf31fbbb/pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5", size = 12121582, upload-time = "2025-09-29T23:30:43.391Z" }, + { url = "https://files.pythonhosted.org/packages/44/91/483de934193e12a3b1d6ae7c8645d083ff88dec75f46e827562f1e4b4da6/pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788", size = 12699963, upload-time = "2025-09-29T23:31:10.009Z" }, + { url = "https://files.pythonhosted.org/packages/70/44/5191d2e4026f86a2a109053e194d3ba7a31a2d10a9c2348368c63ed4e85a/pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87", size = 13202175, upload-time = "2025-09-29T23:31:59.173Z" }, +] + +[[package]] +name = "patsy" +version = "1.0.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/be/44/ed13eccdd0519eff265f44b670d46fbb0ec813e2274932dc1c0e48520f7d/patsy-1.0.2.tar.gz", hash = "sha256:cdc995455f6233e90e22de72c37fcadb344e7586fb83f06696f54d92f8ce74c0", size = 399942, upload-time = "2025-10-20T16:17:37.535Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl", hash = "sha256:37bfddbc58fcf0362febb5f54f10743f8b21dd2aa73dec7e7ef59d1b02ae668a", size = 233301, upload-time = "2025-10-20T16:17:36.563Z" }, +] + +[[package]] +name = "pillow" +version = "12.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5a/b0/cace85a1b0c9775a9f8f5d5423c8261c858760e2466c79b2dd184638b056/pillow-12.0.0.tar.gz", hash = "sha256:87d4f8125c9988bfbed67af47dd7a953e2fc7b0cc1e7800ec6d2080d490bb353", size = 47008828, upload-time = "2025-10-15T18:24:14.008Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/f2/de993bb2d21b33a98d031ecf6a978e4b61da207bef02f7b43093774c480d/pillow-12.0.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:0869154a2d0546545cde61d1789a6524319fc1897d9ee31218eae7a60ccc5643", size = 4045493, upload-time = "2025-10-15T18:22:25.758Z" }, + { url = "https://files.pythonhosted.org/packages/0e/b6/bc8d0c4c9f6f111a783d045310945deb769b806d7574764234ffd50bc5ea/pillow-12.0.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a7921c5a6d31b3d756ec980f2f47c0cfdbce0fc48c22a39347a895f41f4a6ea4", size = 4120461, upload-time = "2025-10-15T18:22:27.286Z" }, + { url = "https://files.pythonhosted.org/packages/5d/57/d60d343709366a353dc56adb4ee1e7d8a2cc34e3fbc22905f4167cfec119/pillow-12.0.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:1ee80a59f6ce048ae13cda1abf7fbd2a34ab9ee7d401c46be3ca685d1999a399", size = 3576912, upload-time = "2025-10-15T18:22:28.751Z" }, + { url = "https://files.pythonhosted.org/packages/a4/a4/a0a31467e3f83b94d37568294b01d22b43ae3c5d85f2811769b9c66389dd/pillow-12.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c50f36a62a22d350c96e49ad02d0da41dbd17ddc2e29750dbdba4323f85eb4a5", size = 5249132, upload-time = "2025-10-15T18:22:30.641Z" }, + { url = "https://files.pythonhosted.org/packages/83/06/48eab21dd561de2914242711434c0c0eb992ed08ff3f6107a5f44527f5e9/pillow-12.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5193fde9a5f23c331ea26d0cf171fbf67e3f247585f50c08b3e205c7aeb4589b", size = 4650099, upload-time = "2025-10-15T18:22:32.73Z" }, + { url = "https://files.pythonhosted.org/packages/fc/bd/69ed99fd46a8dba7c1887156d3572fe4484e3f031405fcc5a92e31c04035/pillow-12.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bde737cff1a975b70652b62d626f7785e0480918dece11e8fef3c0cf057351c3", size = 6230808, upload-time = "2025-10-15T18:22:34.337Z" }, + { url = "https://files.pythonhosted.org/packages/ea/94/8fad659bcdbf86ed70099cb60ae40be6acca434bbc8c4c0d4ef356d7e0de/pillow-12.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a6597ff2b61d121172f5844b53f21467f7082f5fb385a9a29c01414463f93b07", size = 8037804, upload-time = "2025-10-15T18:22:36.402Z" }, + { url = "https://files.pythonhosted.org/packages/20/39/c685d05c06deecfd4e2d1950e9a908aa2ca8bc4e6c3b12d93b9cafbd7837/pillow-12.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0b817e7035ea7f6b942c13aa03bb554fc44fea70838ea21f8eb31c638326584e", size = 6345553, upload-time = "2025-10-15T18:22:38.066Z" }, + { url = "https://files.pythonhosted.org/packages/38/57/755dbd06530a27a5ed74f8cb0a7a44a21722ebf318edbe67ddbd7fb28f88/pillow-12.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f4f1231b7dec408e8670264ce63e9c71409d9583dd21d32c163e25213ee2a344", size = 7037729, upload-time = "2025-10-15T18:22:39.769Z" }, + { url = "https://files.pythonhosted.org/packages/ca/b6/7e94f4c41d238615674d06ed677c14883103dce1c52e4af16f000338cfd7/pillow-12.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e51b71417049ad6ab14c49608b4a24d8fb3fe605e5dfabfe523b58064dc3d27", size = 6459789, upload-time = "2025-10-15T18:22:41.437Z" }, + { url = "https://files.pythonhosted.org/packages/9c/14/4448bb0b5e0f22dd865290536d20ec8a23b64e2d04280b89139f09a36bb6/pillow-12.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d120c38a42c234dc9a8c5de7ceaaf899cf33561956acb4941653f8bdc657aa79", size = 7130917, upload-time = "2025-10-15T18:22:43.152Z" }, + { url = "https://files.pythonhosted.org/packages/dd/ca/16c6926cc1c015845745d5c16c9358e24282f1e588237a4c36d2b30f182f/pillow-12.0.0-cp313-cp313-win32.whl", hash = "sha256:4cc6b3b2efff105c6a1656cfe59da4fdde2cda9af1c5e0b58529b24525d0a098", size = 6302391, upload-time = "2025-10-15T18:22:44.753Z" }, + { url = "https://files.pythonhosted.org/packages/6d/2a/dd43dcfd6dae9b6a49ee28a8eedb98c7d5ff2de94a5d834565164667b97b/pillow-12.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:4cf7fed4b4580601c4345ceb5d4cbf5a980d030fd5ad07c4d2ec589f95f09905", size = 7007477, upload-time = "2025-10-15T18:22:46.838Z" }, + { url = "https://files.pythonhosted.org/packages/77/f0/72ea067f4b5ae5ead653053212af05ce3705807906ba3f3e8f58ddf617e6/pillow-12.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:9f0b04c6b8584c2c193babcccc908b38ed29524b29dd464bc8801bf10d746a3a", size = 2435918, upload-time = "2025-10-15T18:22:48.399Z" }, + { url = "https://files.pythonhosted.org/packages/f5/5e/9046b423735c21f0487ea6cb5b10f89ea8f8dfbe32576fe052b5ba9d4e5b/pillow-12.0.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7fa22993bac7b77b78cae22bad1e2a987ddf0d9015c63358032f84a53f23cdc3", size = 5251406, upload-time = "2025-10-15T18:22:49.905Z" }, + { url = "https://files.pythonhosted.org/packages/12/66/982ceebcdb13c97270ef7a56c3969635b4ee7cd45227fa707c94719229c5/pillow-12.0.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f135c702ac42262573fe9714dfe99c944b4ba307af5eb507abef1667e2cbbced", size = 4653218, upload-time = "2025-10-15T18:22:51.587Z" }, + { url = "https://files.pythonhosted.org/packages/16/b3/81e625524688c31859450119bf12674619429cab3119eec0e30a7a1029cb/pillow-12.0.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c85de1136429c524e55cfa4e033b4a7940ac5c8ee4d9401cc2d1bf48154bbc7b", size = 6266564, upload-time = "2025-10-15T18:22:53.215Z" }, + { url = "https://files.pythonhosted.org/packages/98/59/dfb38f2a41240d2408096e1a76c671d0a105a4a8471b1871c6902719450c/pillow-12.0.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:38df9b4bfd3db902c9c2bd369bcacaf9d935b2fff73709429d95cc41554f7b3d", size = 8069260, upload-time = "2025-10-15T18:22:54.933Z" }, + { url = "https://files.pythonhosted.org/packages/dc/3d/378dbea5cd1874b94c312425ca77b0f47776c78e0df2df751b820c8c1d6c/pillow-12.0.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7d87ef5795da03d742bf49439f9ca4d027cde49c82c5371ba52464aee266699a", size = 6379248, upload-time = "2025-10-15T18:22:56.605Z" }, + { url = "https://files.pythonhosted.org/packages/84/b0/d525ef47d71590f1621510327acec75ae58c721dc071b17d8d652ca494d8/pillow-12.0.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aff9e4d82d082ff9513bdd6acd4f5bd359f5b2c870907d2b0a9c5e10d40c88fe", size = 7066043, upload-time = "2025-10-15T18:22:58.53Z" }, + { url = "https://files.pythonhosted.org/packages/61/2c/aced60e9cf9d0cde341d54bf7932c9ffc33ddb4a1595798b3a5150c7ec4e/pillow-12.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:8d8ca2b210ada074d57fcee40c30446c9562e542fc46aedc19baf758a93532ee", size = 6490915, upload-time = "2025-10-15T18:23:00.582Z" }, + { url = "https://files.pythonhosted.org/packages/ef/26/69dcb9b91f4e59f8f34b2332a4a0a951b44f547c4ed39d3e4dcfcff48f89/pillow-12.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:99a7f72fb6249302aa62245680754862a44179b545ded638cf1fef59befb57ef", size = 7157998, upload-time = "2025-10-15T18:23:02.627Z" }, + { url = "https://files.pythonhosted.org/packages/61/2b/726235842220ca95fa441ddf55dd2382b52ab5b8d9c0596fe6b3f23dafe8/pillow-12.0.0-cp313-cp313t-win32.whl", hash = "sha256:4078242472387600b2ce8d93ade8899c12bf33fa89e55ec89fe126e9d6d5d9e9", size = 6306201, upload-time = "2025-10-15T18:23:04.709Z" }, + { url = "https://files.pythonhosted.org/packages/c0/3d/2afaf4e840b2df71344ababf2f8edd75a705ce500e5dc1e7227808312ae1/pillow-12.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2c54c1a783d6d60595d3514f0efe9b37c8808746a66920315bfd34a938d7994b", size = 7013165, upload-time = "2025-10-15T18:23:06.46Z" }, + { url = "https://files.pythonhosted.org/packages/6f/75/3fa09aa5cf6ed04bee3fa575798ddf1ce0bace8edb47249c798077a81f7f/pillow-12.0.0-cp313-cp313t-win_arm64.whl", hash = "sha256:26d9f7d2b604cd23aba3e9faf795787456ac25634d82cd060556998e39c6fa47", size = 2437834, upload-time = "2025-10-15T18:23:08.194Z" }, + { url = "https://files.pythonhosted.org/packages/54/2a/9a8c6ba2c2c07b71bec92cf63e03370ca5e5f5c5b119b742bcc0cde3f9c5/pillow-12.0.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:beeae3f27f62308f1ddbcfb0690bf44b10732f2ef43758f169d5e9303165d3f9", size = 4045531, upload-time = "2025-10-15T18:23:10.121Z" }, + { url = "https://files.pythonhosted.org/packages/84/54/836fdbf1bfb3d66a59f0189ff0b9f5f666cee09c6188309300df04ad71fa/pillow-12.0.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:d4827615da15cd59784ce39d3388275ec093ae3ee8d7f0c089b76fa87af756c2", size = 4120554, upload-time = "2025-10-15T18:23:12.14Z" }, + { url = "https://files.pythonhosted.org/packages/0d/cd/16aec9f0da4793e98e6b54778a5fbce4f375c6646fe662e80600b8797379/pillow-12.0.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:3e42edad50b6909089750e65c91aa09aaf1e0a71310d383f11321b27c224ed8a", size = 3576812, upload-time = "2025-10-15T18:23:13.962Z" }, + { url = "https://files.pythonhosted.org/packages/f6/b7/13957fda356dc46339298b351cae0d327704986337c3c69bb54628c88155/pillow-12.0.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e5d8efac84c9afcb40914ab49ba063d94f5dbdf5066db4482c66a992f47a3a3b", size = 5252689, upload-time = "2025-10-15T18:23:15.562Z" }, + { url = "https://files.pythonhosted.org/packages/fc/f5/eae31a306341d8f331f43edb2e9122c7661b975433de5e447939ae61c5da/pillow-12.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:266cd5f2b63ff316d5a1bba46268e603c9caf5606d44f38c2873c380950576ad", size = 4650186, upload-time = "2025-10-15T18:23:17.379Z" }, + { url = "https://files.pythonhosted.org/packages/86/62/2a88339aa40c4c77e79108facbd307d6091e2c0eb5b8d3cf4977cfca2fe6/pillow-12.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:58eea5ebe51504057dd95c5b77d21700b77615ab0243d8152793dc00eb4faf01", size = 6230308, upload-time = "2025-10-15T18:23:18.971Z" }, + { url = "https://files.pythonhosted.org/packages/c7/33/5425a8992bcb32d1cb9fa3dd39a89e613d09a22f2c8083b7bf43c455f760/pillow-12.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f13711b1a5ba512d647a0e4ba79280d3a9a045aaf7e0cc6fbe96b91d4cdf6b0c", size = 8039222, upload-time = "2025-10-15T18:23:20.909Z" }, + { url = "https://files.pythonhosted.org/packages/d8/61/3f5d3b35c5728f37953d3eec5b5f3e77111949523bd2dd7f31a851e50690/pillow-12.0.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6846bd2d116ff42cba6b646edf5bf61d37e5cbd256425fa089fee4ff5c07a99e", size = 6346657, upload-time = "2025-10-15T18:23:23.077Z" }, + { url = "https://files.pythonhosted.org/packages/3a/be/ee90a3d79271227e0f0a33c453531efd6ed14b2e708596ba5dd9be948da3/pillow-12.0.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c98fa880d695de164b4135a52fd2e9cd7b7c90a9d8ac5e9e443a24a95ef9248e", size = 7038482, upload-time = "2025-10-15T18:23:25.005Z" }, + { url = "https://files.pythonhosted.org/packages/44/34/a16b6a4d1ad727de390e9bd9f19f5f669e079e5826ec0f329010ddea492f/pillow-12.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa3ed2a29a9e9d2d488b4da81dcb54720ac3104a20bf0bd273f1e4648aff5af9", size = 6461416, upload-time = "2025-10-15T18:23:27.009Z" }, + { url = "https://files.pythonhosted.org/packages/b6/39/1aa5850d2ade7d7ba9f54e4e4c17077244ff7a2d9e25998c38a29749eb3f/pillow-12.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d034140032870024e6b9892c692fe2968493790dd57208b2c37e3fb35f6df3ab", size = 7131584, upload-time = "2025-10-15T18:23:29.752Z" }, + { url = "https://files.pythonhosted.org/packages/bf/db/4fae862f8fad0167073a7733973bfa955f47e2cac3dc3e3e6257d10fab4a/pillow-12.0.0-cp314-cp314-win32.whl", hash = "sha256:1b1b133e6e16105f524a8dec491e0586d072948ce15c9b914e41cdadd209052b", size = 6400621, upload-time = "2025-10-15T18:23:32.06Z" }, + { url = "https://files.pythonhosted.org/packages/2b/24/b350c31543fb0107ab2599464d7e28e6f856027aadda995022e695313d94/pillow-12.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:8dc232e39d409036af549c86f24aed8273a40ffa459981146829a324e0848b4b", size = 7142916, upload-time = "2025-10-15T18:23:34.71Z" }, + { url = "https://files.pythonhosted.org/packages/0f/9b/0ba5a6fd9351793996ef7487c4fdbde8d3f5f75dbedc093bb598648fddf0/pillow-12.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:d52610d51e265a51518692045e372a4c363056130d922a7351429ac9f27e70b0", size = 2523836, upload-time = "2025-10-15T18:23:36.967Z" }, + { url = "https://files.pythonhosted.org/packages/f5/7a/ceee0840aebc579af529b523d530840338ecf63992395842e54edc805987/pillow-12.0.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1979f4566bb96c1e50a62d9831e2ea2d1211761e5662afc545fa766f996632f6", size = 5255092, upload-time = "2025-10-15T18:23:38.573Z" }, + { url = "https://files.pythonhosted.org/packages/44/76/20776057b4bfd1aef4eeca992ebde0f53a4dce874f3ae693d0ec90a4f79b/pillow-12.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b2e4b27a6e15b04832fe9bf292b94b5ca156016bbc1ea9c2c20098a0320d6cf6", size = 4653158, upload-time = "2025-10-15T18:23:40.238Z" }, + { url = "https://files.pythonhosted.org/packages/82/3f/d9ff92ace07be8836b4e7e87e6a4c7a8318d47c2f1463ffcf121fc57d9cb/pillow-12.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fb3096c30df99fd01c7bf8e544f392103d0795b9f98ba71a8054bcbf56b255f1", size = 6267882, upload-time = "2025-10-15T18:23:42.434Z" }, + { url = "https://files.pythonhosted.org/packages/9f/7a/4f7ff87f00d3ad33ba21af78bfcd2f032107710baf8280e3722ceec28cda/pillow-12.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7438839e9e053ef79f7112c881cef684013855016f928b168b81ed5835f3e75e", size = 8071001, upload-time = "2025-10-15T18:23:44.29Z" }, + { url = "https://files.pythonhosted.org/packages/75/87/fcea108944a52dad8cca0715ae6247e271eb80459364a98518f1e4f480c1/pillow-12.0.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d5c411a8eaa2299322b647cd932586b1427367fd3184ffbb8f7a219ea2041ca", size = 6380146, upload-time = "2025-10-15T18:23:46.065Z" }, + { url = "https://files.pythonhosted.org/packages/91/52/0d31b5e571ef5fd111d2978b84603fce26aba1b6092f28e941cb46570745/pillow-12.0.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7e091d464ac59d2c7ad8e7e08105eaf9dafbc3883fd7265ffccc2baad6ac925", size = 7067344, upload-time = "2025-10-15T18:23:47.898Z" }, + { url = "https://files.pythonhosted.org/packages/7b/f4/2dd3d721f875f928d48e83bb30a434dee75a2531bca839bb996bb0aa5a91/pillow-12.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:792a2c0be4dcc18af9d4a2dfd8a11a17d5e25274a1062b0ec1c2d79c76f3e7f8", size = 6491864, upload-time = "2025-10-15T18:23:49.607Z" }, + { url = "https://files.pythonhosted.org/packages/30/4b/667dfcf3d61fc309ba5a15b141845cece5915e39b99c1ceab0f34bf1d124/pillow-12.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:afbefa430092f71a9593a99ab6a4e7538bc9eabbf7bf94f91510d3503943edc4", size = 7158911, upload-time = "2025-10-15T18:23:51.351Z" }, + { url = "https://files.pythonhosted.org/packages/a2/2f/16cabcc6426c32218ace36bf0d55955e813f2958afddbf1d391849fee9d1/pillow-12.0.0-cp314-cp314t-win32.whl", hash = "sha256:3830c769decf88f1289680a59d4f4c46c72573446352e2befec9a8512104fa52", size = 6408045, upload-time = "2025-10-15T18:23:53.177Z" }, + { url = "https://files.pythonhosted.org/packages/35/73/e29aa0c9c666cf787628d3f0dcf379f4791fba79f4936d02f8b37165bdf8/pillow-12.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:905b0365b210c73afb0ebe9101a32572152dfd1c144c7e28968a331b9217b94a", size = 7148282, upload-time = "2025-10-15T18:23:55.316Z" }, + { url = "https://files.pythonhosted.org/packages/c1/70/6b41bdcddf541b437bbb9f47f94d2db5d9ddef6c37ccab8c9107743748a4/pillow-12.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:99353a06902c2e43b43e8ff74ee65a7d90307d82370604746738a1e0661ccca7", size = 2525630, upload-time = "2025-10-15T18:23:57.149Z" }, +] + +[[package]] +name = "plotnine" +version = "0.15.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "matplotlib" }, + { name = "mizani" }, + { name = "numpy" }, + { name = "pandas" }, + { name = "scipy" }, + { name = "statsmodels" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/11/14/3adedabe6b8710caee34e4ac9f4edc48218a381594ee1980c323b8866577/plotnine-0.15.2.tar.gz", hash = "sha256:ec2e4cdf2d022eb0dab63ef4aa0017ce0d84c60bd99d55093e72637fddf757e6", size = 6787690, upload-time = "2025-12-12T10:41:37.249Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/58/27/4e6ffe2f095fbfd6285343aa6114903a4cf011564b4f1f2bb706341472df/plotnine-0.15.2-py3-none-any.whl", hash = "sha256:7dc508bc51625b9b9f945e274d8ee4463cf30b280749190a5b707e6828003fa6", size = 1332822, upload-time = "2025-12-12T10:41:34.203Z" }, +] + +[[package]] +name = "polars" +version = "1.36.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "polars-runtime-32" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9f/dc/56f2a90c79a2cb13f9e956eab6385effe54216ae7a2068b3a6406bae4345/polars-1.36.1.tar.gz", hash = "sha256:12c7616a2305559144711ab73eaa18814f7aa898c522e7645014b68f1432d54c", size = 711993, upload-time = "2025-12-10T01:14:53.033Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f6/c6/36a1b874036b49893ecae0ac44a2f63d1a76e6212631a5b2f50a86e0e8af/polars-1.36.1-py3-none-any.whl", hash = "sha256:853c1bbb237add6a5f6d133c15094a9b727d66dd6a4eb91dbb07cdb056b2b8ef", size = 802429, upload-time = "2025-12-10T01:13:53.838Z" }, +] + +[[package]] +name = "polars-runtime-32" +version = "1.36.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/31/df/597c0ef5eb8d761a16d72327846599b57c5d40d7f9e74306fc154aba8c37/polars_runtime_32-1.36.1.tar.gz", hash = "sha256:201c2cfd80ceb5d5cd7b63085b5fd08d6ae6554f922bcb941035e39638528a09", size = 2788751, upload-time = "2025-12-10T01:14:54.172Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/ea/871129a2d296966c0925b078a9a93c6c5e7facb1c5eebfcd3d5811aeddc1/polars_runtime_32-1.36.1-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:327b621ca82594f277751f7e23d4b939ebd1be18d54b4cdf7a2f8406cecc18b2", size = 43494311, upload-time = "2025-12-10T01:13:56.096Z" }, + { url = "https://files.pythonhosted.org/packages/d8/76/0038210ad1e526ce5bb2933b13760d6b986b3045eccc1338e661bd656f77/polars_runtime_32-1.36.1-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ab0d1f23084afee2b97de8c37aa3e02ec3569749ae39571bd89e7a8b11ae9e83", size = 39300602, upload-time = "2025-12-10T01:13:59.366Z" }, + { url = "https://files.pythonhosted.org/packages/54/1e/2707bee75a780a953a77a2c59829ee90ef55708f02fc4add761c579bf76e/polars_runtime_32-1.36.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:899b9ad2e47ceb31eb157f27a09dbc2047efbf4969a923a6b1ba7f0412c3e64c", size = 44511780, upload-time = "2025-12-10T01:14:02.285Z" }, + { url = "https://files.pythonhosted.org/packages/11/b2/3fede95feee441be64b4bcb32444679a8fbb7a453a10251583053f6efe52/polars_runtime_32-1.36.1-cp39-abi3-manylinux_2_24_aarch64.whl", hash = "sha256:d9d077bb9df711bc635a86540df48242bb91975b353e53ef261c6fae6cb0948f", size = 40688448, upload-time = "2025-12-10T01:14:05.131Z" }, + { url = "https://files.pythonhosted.org/packages/05/0f/e629713a72999939b7b4bfdbf030a32794db588b04fdf3dc977dd8ea6c53/polars_runtime_32-1.36.1-cp39-abi3-win_amd64.whl", hash = "sha256:cc17101f28c9a169ff8b5b8d4977a3683cd403621841623825525f440b564cf0", size = 44464898, upload-time = "2025-12-10T01:14:08.296Z" }, + { url = "https://files.pythonhosted.org/packages/d1/d8/a12e6aa14f63784cead437083319ec7cece0d5bb9a5bfe7678cc6578b52a/polars_runtime_32-1.36.1-cp39-abi3-win_arm64.whl", hash = "sha256:809e73857be71250141225ddd5d2b30c97e6340aeaa0d445f930e01bef6888dc", size = 39798896, upload-time = "2025-12-10T01:14:11.568Z" }, +] + +[[package]] +name = "pyogrio" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "numpy" }, + { name = "packaging" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/49/d4/12f86b1ed09721363da4c09622464b604c851a9223fc0c6b393fb2012208/pyogrio-0.12.1.tar.gz", hash = "sha256:e548ab705bb3e5383693717de1e6c76da97f3762ab92522cb310f93128a75ff1", size = 303289, upload-time = "2025-11-28T19:04:53.341Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/be/56/f56e79f71b84aa9bea25fdde39fab3846841bd7926be96f623eb7253b7e1/pyogrio-0.12.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:ec0e47a5a704e575092b2fd5c83fa0472a1d421e590f94093eb837bb0a11125d", size = 23658483, upload-time = "2025-11-28T19:03:43.567Z" }, + { url = "https://files.pythonhosted.org/packages/66/ac/5559f8a35d58a16cbb2dd7602dd11936ff8796d8c9bf789f14da88764ec3/pyogrio-0.12.1-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:b4c888fc08f388be4dd99dfca5e84a5cdc5994deeec0230cc45144d3460e2b21", size = 25232737, upload-time = "2025-11-28T19:03:45.92Z" }, + { url = "https://files.pythonhosted.org/packages/59/58/925f1c129ddd7cbba8dea4e7609797cea7a76dbc863ac9afd318a679c4b9/pyogrio-0.12.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:73a88436f9962750d782853727897ac2722cac5900d920e39fab3e56d7a6a7f1", size = 31377986, upload-time = "2025-11-28T19:03:48.495Z" }, + { url = "https://files.pythonhosted.org/packages/18/5f/c87034e92847b1844d0e8492a6a8e3301147d32c5e57909397ce64dbedf5/pyogrio-0.12.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:b5d248a0d59fe9bbf9a35690b70004c67830ee0ebe7d4f7bb8ffd8659f684b3a", size = 30915791, upload-time = "2025-11-28T19:03:51.267Z" }, + { url = "https://files.pythonhosted.org/packages/46/35/b874f79d03e9f900012cf609f7fff97b77164f2e14ee5aac282f8a999c1b/pyogrio-0.12.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:0622bc1a186421547660271083079b38d42e6f868802936d8538c0b379f1ab6b", size = 32499754, upload-time = "2025-11-28T19:03:58.776Z" }, + { url = "https://files.pythonhosted.org/packages/c3/c4/705678c9c4200130290b3a104b45c0cc10aaa48fcef3b2585b34e34ab3e1/pyogrio-0.12.1-cp313-cp313-win_amd64.whl", hash = "sha256:207bd60c7ffbcea84584596e3637653aa7095e9ee20fa408f90c7f9460392613", size = 22933945, upload-time = "2025-11-28T19:04:01.551Z" }, + { url = "https://files.pythonhosted.org/packages/f9/e0/d92d4944001330bc87742d43f112d63d12fc89378b6187e62ff3fc1e8e85/pyogrio-0.12.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:1511b39a283fa27cda906cd187a791578942a87a40b6a06697d9b43bb8ac80b0", size = 23692697, upload-time = "2025-11-28T19:04:04.208Z" }, + { url = "https://files.pythonhosted.org/packages/e5/d7/40acbe06d1b1140e3bb27b79e9163776469c1dc785f1be7d9a7fc7b95c87/pyogrio-0.12.1-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:e486cd6aa9ea8a15394a5f84e019d61ec18f257eeeb642348bd68c3d1e57280b", size = 25258083, upload-time = "2025-11-28T19:04:07.121Z" }, + { url = "https://files.pythonhosted.org/packages/87/a1/39fefd9cddd95986700524f43d3093b4350f6e4fc200623c3838424a5080/pyogrio-0.12.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d3f1a19f63bfd1d3042e45f37ad1d6598123a5a604b6c4ba3f38b419273486cd", size = 31368995, upload-time = "2025-11-28T19:04:09.88Z" }, + { url = "https://files.pythonhosted.org/packages/18/d7/da88c566e67d741a03851eb8d01358949d52e0b0fc2cd953582dc6d89ff8/pyogrio-0.12.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:f3dcc59b3316b8a0f59346bcc638a4d69997864a4d21da839192f50c4c92369a", size = 31035589, upload-time = "2025-11-28T19:04:12.993Z" }, + { url = "https://files.pythonhosted.org/packages/11/ac/8f0199f0d31b8ddbc4b4ea1918df8070fdf3e0a63100b898633ec9396224/pyogrio-0.12.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:a0643e041dee3e8e038fce69f52a915ecb486e6d7b674c0f9919f3c9e9629689", size = 32487973, upload-time = "2025-11-28T19:04:16.103Z" }, + { url = "https://files.pythonhosted.org/packages/bd/64/8541a27e9635a335835d234dfaeb19d6c26097fd88224eda7791f83ca98d/pyogrio-0.12.1-cp313-cp313t-win_amd64.whl", hash = "sha256:5881017f29e110d3613819667657844d8e961b747f2d35cf92f273c27af6d068", size = 22987374, upload-time = "2025-11-28T19:04:18.91Z" }, + { url = "https://files.pythonhosted.org/packages/f4/6f/b4d5e285e08c0c60bcc23b50d73038ddc7335d8de79cc25678cd486a3db0/pyogrio-0.12.1-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:5a1b0453d1c9e7b03715dd57296c8f3790acb8b50d7e3b5844b3074a18f50709", size = 23660673, upload-time = "2025-11-28T19:04:21.662Z" }, + { url = "https://files.pythonhosted.org/packages/8d/75/4b29e71489c5551aa1a1c5ca8c5160a60203c94f2f68c87c0e3614d58965/pyogrio-0.12.1-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:e7ee560422239dd09ca7f8284cc8483a8919c30d25f3049bb0249bff4c38dec4", size = 25232194, upload-time = "2025-11-28T19:04:23.975Z" }, + { url = "https://files.pythonhosted.org/packages/89/6e/e9929d2261a07c36301983de2767bcde90d441ab5bf1d767ce56dd07f8b4/pyogrio-0.12.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:648c6f7f5f214d30e6cf493b4af1d59782907ac068af9119ca35f18153d6865a", size = 31336936, upload-time = "2025-11-28T19:04:26.594Z" }, + { url = "https://files.pythonhosted.org/packages/1d/9e/c59941d734ed936d4e5c89b4b99cb5541307cc42b3fd466ee78a1850c177/pyogrio-0.12.1-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:58042584f3fd4cabb0f55d26c1405053f656be8a5c266c38140316a1e981aca0", size = 30902210, upload-time = "2025-11-28T19:04:29.143Z" }, + { url = "https://files.pythonhosted.org/packages/d1/68/cc07320a63f9c2586e60bf11d148b00e12d0e707673bffe609bbdcb7e754/pyogrio-0.12.1-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:b438e38e4ccbaedaa5cb5824ff5de5539315d9b2fde6547c1e816576924ee8ca", size = 32461674, upload-time = "2025-11-28T19:04:31.792Z" }, + { url = "https://files.pythonhosted.org/packages/13/bc/e4522f429c45a3b6ad28185849dd76e5c8718b780883c4795e7ee41841ae/pyogrio-0.12.1-cp314-cp314-win_amd64.whl", hash = "sha256:f1d8d8a2fea3781dc2a05982c050259261ebc0f6c5e03732d6d79d582adf9363", size = 23550575, upload-time = "2025-11-28T19:04:34.556Z" }, + { url = "https://files.pythonhosted.org/packages/bd/ac/34f0664d0e391994a7b68529ae07a96432b2b4926dbac173ddc4ec94d310/pyogrio-0.12.1-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:9fe7286946f35a73e6370dc5855bc7a5e8e7babf9e4a8bad7a3279a1d94c7ea9", size = 23694285, upload-time = "2025-11-28T19:04:37.833Z" }, + { url = "https://files.pythonhosted.org/packages/8a/93/873255529faff1da09d0b27287e85ec805a318c60c0c74fd7df77f94e557/pyogrio-0.12.1-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:2c50345b382f1be801d654ec22c70ee974d6057d4ba7afe984b55f2192bc94ee", size = 25259825, upload-time = "2025-11-28T19:04:40.125Z" }, + { url = "https://files.pythonhosted.org/packages/27/95/4d4c3644695d99c6fa0b0b42f0d6266ae9dfaf64478a3371eaac950bdd02/pyogrio-0.12.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f0db95765ac0ca935c7fe579e29451294e3ab19c317b0c59c31fbe92a69155e0", size = 31371995, upload-time = "2025-11-28T19:04:42.736Z" }, + { url = "https://files.pythonhosted.org/packages/4c/6f/71f6bcca8754c8bf55a4b7153c61c91f8ac5ba992568e9fa3e54a0ee76fd/pyogrio-0.12.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:fc882779075982b93064b3bf3d8642514a6df00d9dd752493b104817072cfb01", size = 31035498, upload-time = "2025-11-28T19:04:45.79Z" }, + { url = "https://files.pythonhosted.org/packages/fd/47/75c1aa165a988347317afab9b938a01ad25dbca559b582ea34473703dc38/pyogrio-0.12.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:806f620e0c54b54dbdd65e9b6368d24f344cda84c9343364b40a57eb3e1c4dca", size = 32496390, upload-time = "2025-11-28T19:04:48.786Z" }, + { url = "https://files.pythonhosted.org/packages/31/93/4641dc5d952f6bdb71dabad2c50e3f8a5d58396cdea6ff8f8a08bfd4f4a6/pyogrio-0.12.1-cp314-cp314t-win_amd64.whl", hash = "sha256:5399f66730978d8852ef5f44dbafa0f738e7f28f4f784349f36830b69a9d2134", size = 23620996, upload-time = "2025-11-28T19:04:51.132Z" }, +] + +[[package]] +name = "pyparsing" +version = "3.2.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/a5/181488fc2b9d093e3972d2a472855aae8a03f000592dbfce716a512b3359/pyparsing-3.2.5.tar.gz", hash = "sha256:2df8d5b7b2802ef88e8d016a2eb9c7aeaa923529cd251ed0fe4608275d4105b6", size = 1099274, upload-time = "2025-09-21T04:11:06.277Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/5e/1aa9a93198c6b64513c9d7752de7422c06402de6600a8767da1524f9570b/pyparsing-3.2.5-py3-none-any.whl", hash = "sha256:e38a4f02064cf41fe6593d328d0512495ad1f3d8a91c4f73fc401b3079a59a5e", size = 113890, upload-time = "2025-09-21T04:11:04.117Z" }, +] + +[[package]] +name = "pyproj" +version = "3.7.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/90/67bd7260b4ea9b8b20b4f58afef6c223ecb3abf368eb4ec5bc2cdef81b49/pyproj-3.7.2.tar.gz", hash = "sha256:39a0cf1ecc7e282d1d30f36594ebd55c9fae1fda8a2622cee5d100430628f88c", size = 226279, upload-time = "2025-08-14T12:05:42.18Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/be/14/faf1b90d267cea68d7e70662e7f88cefdb1bc890bd596c74b959e0517a72/pyproj-3.7.2-cp313-cp313-macosx_13_0_x86_64.whl", hash = "sha256:19466e529b1b15eeefdf8ff26b06fa745856c044f2f77bf0edbae94078c1dfa1", size = 6214580, upload-time = "2025-08-14T12:04:28.804Z" }, + { url = "https://files.pythonhosted.org/packages/35/48/da9a45b184d375f62667f62eba0ca68569b0bd980a0bb7ffcc1d50440520/pyproj-3.7.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:c79b9b84c4a626c5dc324c0d666be0bfcebd99f7538d66e8898c2444221b3da7", size = 4615388, upload-time = "2025-08-14T12:04:30.553Z" }, + { url = "https://files.pythonhosted.org/packages/5e/e7/d2b459a4a64bca328b712c1b544e109df88e5c800f7c143cfbc404d39bfb/pyproj-3.7.2-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:ceecf374cacca317bc09e165db38ac548ee3cad07c3609442bd70311c59c21aa", size = 9628455, upload-time = "2025-08-14T12:04:32.435Z" }, + { url = "https://files.pythonhosted.org/packages/f8/85/c2b1706e51942de19076eff082f8495e57d5151364e78b5bef4af4a1d94a/pyproj-3.7.2-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:5141a538ffdbe4bfd157421828bb2e07123a90a7a2d6f30fa1462abcfb5ce681", size = 9514269, upload-time = "2025-08-14T12:04:34.599Z" }, + { url = "https://files.pythonhosted.org/packages/34/38/07a9b89ae7467872f9a476883a5bad9e4f4d1219d31060f0f2b282276cbe/pyproj-3.7.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f000841e98ea99acbb7b8ca168d67773b0191de95187228a16110245c5d954d5", size = 10808437, upload-time = "2025-08-14T12:04:36.485Z" }, + { url = "https://files.pythonhosted.org/packages/12/56/fda1daeabbd39dec5b07f67233d09f31facb762587b498e6fc4572be9837/pyproj-3.7.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8115faf2597f281a42ab608ceac346b4eb1383d3b45ab474fd37341c4bf82a67", size = 10745540, upload-time = "2025-08-14T12:04:38.568Z" }, + { url = "https://files.pythonhosted.org/packages/0d/90/c793182cbba65a39a11db2ac6b479fe76c59e6509ae75e5744c344a0da9d/pyproj-3.7.2-cp313-cp313-win32.whl", hash = "sha256:f18c0579dd6be00b970cb1a6719197fceecc407515bab37da0066f0184aafdf3", size = 5896506, upload-time = "2025-08-14T12:04:41.059Z" }, + { url = "https://files.pythonhosted.org/packages/be/0f/747974129cf0d800906f81cd25efd098c96509026e454d4b66868779ab04/pyproj-3.7.2-cp313-cp313-win_amd64.whl", hash = "sha256:bb41c29d5f60854b1075853fe80c58950b398d4ebb404eb532536ac8d2834ed7", size = 6310195, upload-time = "2025-08-14T12:04:42.974Z" }, + { url = "https://files.pythonhosted.org/packages/82/64/fc7598a53172c4931ec6edf5228280663063150625d3f6423b4c20f9daff/pyproj-3.7.2-cp313-cp313-win_arm64.whl", hash = "sha256:2b617d573be4118c11cd96b8891a0b7f65778fa7733ed8ecdb297a447d439100", size = 6230748, upload-time = "2025-08-14T12:04:44.491Z" }, + { url = "https://files.pythonhosted.org/packages/aa/f0/611dd5cddb0d277f94b7af12981f56e1441bf8d22695065d4f0df5218498/pyproj-3.7.2-cp313-cp313t-macosx_13_0_x86_64.whl", hash = "sha256:d27b48f0e81beeaa2b4d60c516c3a1cfbb0c7ff6ef71256d8e9c07792f735279", size = 6241729, upload-time = "2025-08-14T12:04:46.274Z" }, + { url = "https://files.pythonhosted.org/packages/15/93/40bd4a6c523ff9965e480870611aed7eda5aa2c6128c6537345a2b77b542/pyproj-3.7.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:55a3610d75023c7b1c6e583e48ef8f62918e85a2ae81300569d9f104d6684bb6", size = 4652497, upload-time = "2025-08-14T12:04:48.203Z" }, + { url = "https://files.pythonhosted.org/packages/1b/ae/7150ead53c117880b35e0d37960d3138fe640a235feb9605cb9386f50bb0/pyproj-3.7.2-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:8d7349182fa622696787cc9e195508d2a41a64765da9b8a6bee846702b9e6220", size = 9942610, upload-time = "2025-08-14T12:04:49.652Z" }, + { url = "https://files.pythonhosted.org/packages/d8/17/7a4a7eafecf2b46ab64e5c08176c20ceb5844b503eaa551bf12ccac77322/pyproj-3.7.2-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:d230b186eb876ed4f29a7c5ee310144c3a0e44e89e55f65fb3607e13f6db337c", size = 9692390, upload-time = "2025-08-14T12:04:51.731Z" }, + { url = "https://files.pythonhosted.org/packages/c3/55/ae18f040f6410f0ea547a21ada7ef3e26e6c82befa125b303b02759c0e9d/pyproj-3.7.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:237499c7862c578d0369e2b8ac56eec550e391a025ff70e2af8417139dabb41c", size = 11047596, upload-time = "2025-08-14T12:04:53.748Z" }, + { url = "https://files.pythonhosted.org/packages/e6/2e/d3fff4d2909473f26ae799f9dda04caa322c417a51ff3b25763f7d03b233/pyproj-3.7.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8c225f5978abd506fd9a78eaaf794435e823c9156091cabaab5374efb29d7f69", size = 10896975, upload-time = "2025-08-14T12:04:55.875Z" }, + { url = "https://files.pythonhosted.org/packages/f2/bc/8fc7d3963d87057b7b51ebe68c1e7c51c23129eee5072ba6b86558544a46/pyproj-3.7.2-cp313-cp313t-win32.whl", hash = "sha256:2da731876d27639ff9d2d81c151f6ab90a1546455fabd93368e753047be344a2", size = 5953057, upload-time = "2025-08-14T12:04:58.466Z" }, + { url = "https://files.pythonhosted.org/packages/cc/27/ea9809966cc47d2d51e6d5ae631ea895f7c7c7b9b3c29718f900a8f7d197/pyproj-3.7.2-cp313-cp313t-win_amd64.whl", hash = "sha256:f54d91ae18dd23b6c0ab48126d446820e725419da10617d86a1b69ada6d881d3", size = 6375414, upload-time = "2025-08-14T12:04:59.861Z" }, + { url = "https://files.pythonhosted.org/packages/5b/f8/1ef0129fba9a555c658e22af68989f35e7ba7b9136f25758809efec0cd6e/pyproj-3.7.2-cp313-cp313t-win_arm64.whl", hash = "sha256:fc52ba896cfc3214dc9f9ca3c0677a623e8fdd096b257c14a31e719d21ff3fdd", size = 6262501, upload-time = "2025-08-14T12:05:01.39Z" }, + { url = "https://files.pythonhosted.org/packages/42/17/c2b050d3f5b71b6edd0d96ae16c990fdc42a5f1366464a5c2772146de33a/pyproj-3.7.2-cp314-cp314-macosx_13_0_x86_64.whl", hash = "sha256:2aaa328605ace41db050d06bac1adc11f01b71fe95c18661497763116c3a0f02", size = 6214541, upload-time = "2025-08-14T12:05:03.166Z" }, + { url = "https://files.pythonhosted.org/packages/03/68/68ada9c8aea96ded09a66cfd9bf87aa6db8c2edebe93f5bf9b66b0143fbc/pyproj-3.7.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:35dccbce8201313c596a970fde90e33605248b66272595c061b511c8100ccc08", size = 4617456, upload-time = "2025-08-14T12:05:04.563Z" }, + { url = "https://files.pythonhosted.org/packages/81/e4/4c50ceca7d0e937977866b02cb64e6ccf4df979a5871e521f9e255df6073/pyproj-3.7.2-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:25b0b7cb0042444c29a164b993c45c1b8013d6c48baa61dc1160d834a277e83b", size = 9615590, upload-time = "2025-08-14T12:05:06.094Z" }, + { url = "https://files.pythonhosted.org/packages/05/1e/ada6fb15a1d75b5bd9b554355a69a798c55a7dcc93b8d41596265c1772e3/pyproj-3.7.2-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:85def3a6388e9ba51f964619aa002a9d2098e77c6454ff47773bb68871024281", size = 9474960, upload-time = "2025-08-14T12:05:07.973Z" }, + { url = "https://files.pythonhosted.org/packages/51/07/9d48ad0a8db36e16f842f2c8a694c1d9d7dcf9137264846bef77585a71f3/pyproj-3.7.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b1bccefec3875ab81eabf49059e2b2ea77362c178b66fd3528c3e4df242f1516", size = 10799478, upload-time = "2025-08-14T12:05:14.102Z" }, + { url = "https://files.pythonhosted.org/packages/85/cf/2f812b529079f72f51ff2d6456b7fef06c01735e5cfd62d54ffb2b548028/pyproj-3.7.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d5371ca114d6990b675247355a801925814eca53e6c4b2f1b5c0a956336ee36e", size = 10710030, upload-time = "2025-08-14T12:05:16.317Z" }, + { url = "https://files.pythonhosted.org/packages/99/9b/4626a19e1f03eba4c0e77b91a6cf0f73aa9cb5d51a22ee385c22812bcc2c/pyproj-3.7.2-cp314-cp314-win32.whl", hash = "sha256:77f066626030f41be543274f5ac79f2a511fe89860ecd0914f22131b40a0ec25", size = 5991181, upload-time = "2025-08-14T12:05:19.492Z" }, + { url = "https://files.pythonhosted.org/packages/04/b2/5a6610554306a83a563080c2cf2c57565563eadd280e15388efa00fb5b33/pyproj-3.7.2-cp314-cp314-win_amd64.whl", hash = "sha256:5a964da1696b8522806f4276ab04ccfff8f9eb95133a92a25900697609d40112", size = 6434721, upload-time = "2025-08-14T12:05:21.022Z" }, + { url = "https://files.pythonhosted.org/packages/ae/ce/6c910ea2e1c74ef673c5d48c482564b8a7824a44c4e35cca2e765b68cfcc/pyproj-3.7.2-cp314-cp314-win_arm64.whl", hash = "sha256:e258ab4dbd3cf627809067c0ba8f9884ea76c8e5999d039fb37a1619c6c3e1f6", size = 6363821, upload-time = "2025-08-14T12:05:22.627Z" }, + { url = "https://files.pythonhosted.org/packages/e4/e4/5532f6f7491812ba782a2177fe9de73fd8e2912b59f46a1d056b84b9b8f2/pyproj-3.7.2-cp314-cp314t-macosx_13_0_x86_64.whl", hash = "sha256:bbbac2f930c6d266f70ec75df35ef851d96fdb3701c674f42fd23a9314573b37", size = 6241773, upload-time = "2025-08-14T12:05:24.577Z" }, + { url = "https://files.pythonhosted.org/packages/20/1f/0938c3f2bbbef1789132d1726d9b0e662f10cfc22522743937f421ad664e/pyproj-3.7.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:b7544e0a3d6339dc9151e9c8f3ea62a936ab7cc446a806ec448bbe86aebb979b", size = 4652537, upload-time = "2025-08-14T12:05:26.391Z" }, + { url = "https://files.pythonhosted.org/packages/c7/a8/488b1ed47d25972f33874f91f09ca8f2227902f05f63a2b80dc73e7b1c97/pyproj-3.7.2-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:f7f5133dca4c703e8acadf6f30bc567d39a42c6af321e7f81975c2518f3ed357", size = 9940864, upload-time = "2025-08-14T12:05:27.985Z" }, + { url = "https://files.pythonhosted.org/packages/c7/cc/7f4c895d0cb98e47b6a85a6d79eaca03eb266129eed2f845125c09cf31ff/pyproj-3.7.2-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:5aff3343038d7426aa5076f07feb88065f50e0502d1b0d7c22ddfdd2c75a3f81", size = 9688868, upload-time = "2025-08-14T12:05:30.425Z" }, + { url = "https://files.pythonhosted.org/packages/b2/b7/c7e306b8bb0f071d9825b753ee4920f066c40fbfcce9372c4f3cfb2fc4ed/pyproj-3.7.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:b0552178c61f2ac1c820d087e8ba6e62b29442debddbb09d51c4bf8acc84d888", size = 11045910, upload-time = "2025-08-14T12:05:32.507Z" }, + { url = "https://files.pythonhosted.org/packages/42/fb/538a4d2df695980e2dde5c04d965fbdd1fe8c20a3194dc4aaa3952a4d1be/pyproj-3.7.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:47d87db2d2c436c5fd0409b34d70bb6cdb875cca2ebe7a9d1c442367b0ab8d59", size = 10895724, upload-time = "2025-08-14T12:05:35.465Z" }, + { url = "https://files.pythonhosted.org/packages/e8/8b/a3f0618b03957de9db5489a04558a8826f43906628bb0b766033aa3b5548/pyproj-3.7.2-cp314-cp314t-win32.whl", hash = "sha256:c9b6f1d8ad3e80a0ee0903a778b6ece7dca1d1d40f6d114ae01bc8ddbad971aa", size = 6056848, upload-time = "2025-08-14T12:05:37.553Z" }, + { url = "https://files.pythonhosted.org/packages/bc/56/413240dd5149dd3291eda55aa55a659da4431244a2fd1319d0ae89407cfb/pyproj-3.7.2-cp314-cp314t-win_amd64.whl", hash = "sha256:1914e29e27933ba6f9822663ee0600f169014a2859f851c054c88cf5ea8a333c", size = 6517676, upload-time = "2025-08-14T12:05:39.126Z" }, + { url = "https://files.pythonhosted.org/packages/15/73/a7141a1a0559bf1a7aa42a11c879ceb19f02f5c6c371c6d57fd86cefd4d1/pyproj-3.7.2-cp314-cp314t-win_arm64.whl", hash = "sha256:d9d25bae416a24397e0d85739f84d323b55f6511e45a522dd7d7eae70d10c7e4", size = 6391844, upload-time = "2025-08-14T12:05:40.745Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "pytz" +version = "2025.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/bf/abbd3cdfb8fbc7fb3d4d38d320f2441b1e7cbe29be4f23797b4a2b5d8aac/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", size = 320884, upload-time = "2025-03-25T02:25:00.538Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" }, +] + +[[package]] +name = "scipy" +version = "1.16.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0a/ca/d8ace4f98322d01abcd52d381134344bf7b431eba7ed8b42bdea5a3c2ac9/scipy-1.16.3.tar.gz", hash = "sha256:01e87659402762f43bd2fee13370553a17ada367d42e7487800bf2916535aecb", size = 30597883, upload-time = "2025-10-28T17:38:54.068Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/72/f1/57e8327ab1508272029e27eeef34f2302ffc156b69e7e233e906c2a5c379/scipy-1.16.3-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:d2ec56337675e61b312179a1ad124f5f570c00f920cc75e1000025451b88241c", size = 36617856, upload-time = "2025-10-28T17:33:31.375Z" }, + { url = "https://files.pythonhosted.org/packages/44/13/7e63cfba8a7452eb756306aa2fd9b37a29a323b672b964b4fdeded9a3f21/scipy-1.16.3-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:16b8bc35a4cc24db80a0ec836a9286d0e31b2503cb2fd7ff7fb0e0374a97081d", size = 28874306, upload-time = "2025-10-28T17:33:36.516Z" }, + { url = "https://files.pythonhosted.org/packages/15/65/3a9400efd0228a176e6ec3454b1fa998fbbb5a8defa1672c3f65706987db/scipy-1.16.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:5803c5fadd29de0cf27fa08ccbfe7a9e5d741bf63e4ab1085437266f12460ff9", size = 20865371, upload-time = "2025-10-28T17:33:42.094Z" }, + { url = "https://files.pythonhosted.org/packages/33/d7/eda09adf009a9fb81827194d4dd02d2e4bc752cef16737cc4ef065234031/scipy-1.16.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:b81c27fc41954319a943d43b20e07c40bdcd3ff7cf013f4fb86286faefe546c4", size = 23524877, upload-time = "2025-10-28T17:33:48.483Z" }, + { url = "https://files.pythonhosted.org/packages/7d/6b/3f911e1ebc364cb81320223a3422aab7d26c9c7973109a9cd0f27c64c6c0/scipy-1.16.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0c3b4dd3d9b08dbce0f3440032c52e9e2ab9f96ade2d3943313dfe51a7056959", size = 33342103, upload-time = "2025-10-28T17:33:56.495Z" }, + { url = "https://files.pythonhosted.org/packages/21/f6/4bfb5695d8941e5c570a04d9fcd0d36bce7511b7d78e6e75c8f9791f82d0/scipy-1.16.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7dc1360c06535ea6116a2220f760ae572db9f661aba2d88074fe30ec2aa1ff88", size = 35697297, upload-time = "2025-10-28T17:34:04.722Z" }, + { url = "https://files.pythonhosted.org/packages/04/e1/6496dadbc80d8d896ff72511ecfe2316b50313bfc3ebf07a3f580f08bd8c/scipy-1.16.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:663b8d66a8748051c3ee9c96465fb417509315b99c71550fda2591d7dd634234", size = 36021756, upload-time = "2025-10-28T17:34:13.482Z" }, + { url = "https://files.pythonhosted.org/packages/fe/bd/a8c7799e0136b987bda3e1b23d155bcb31aec68a4a472554df5f0937eef7/scipy-1.16.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eab43fae33a0c39006a88096cd7b4f4ef545ea0447d250d5ac18202d40b6611d", size = 38696566, upload-time = "2025-10-28T17:34:22.384Z" }, + { url = "https://files.pythonhosted.org/packages/cd/01/1204382461fcbfeb05b6161b594f4007e78b6eba9b375382f79153172b4d/scipy-1.16.3-cp313-cp313-win_amd64.whl", hash = "sha256:062246acacbe9f8210de8e751b16fc37458213f124bef161a5a02c7a39284304", size = 38529877, upload-time = "2025-10-28T17:35:51.076Z" }, + { url = "https://files.pythonhosted.org/packages/7f/14/9d9fbcaa1260a94f4bb5b64ba9213ceb5d03cd88841fe9fd1ffd47a45b73/scipy-1.16.3-cp313-cp313-win_arm64.whl", hash = "sha256:50a3dbf286dbc7d84f176f9a1574c705f277cb6565069f88f60db9eafdbe3ee2", size = 25455366, upload-time = "2025-10-28T17:35:59.014Z" }, + { url = "https://files.pythonhosted.org/packages/e2/a3/9ec205bd49f42d45d77f1730dbad9ccf146244c1647605cf834b3a8c4f36/scipy-1.16.3-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:fb4b29f4cf8cc5a8d628bc8d8e26d12d7278cd1f219f22698a378c3d67db5e4b", size = 37027931, upload-time = "2025-10-28T17:34:31.451Z" }, + { url = "https://files.pythonhosted.org/packages/25/06/ca9fd1f3a4589cbd825b1447e5db3a8ebb969c1eaf22c8579bd286f51b6d/scipy-1.16.3-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:8d09d72dc92742988b0e7750bddb8060b0c7079606c0d24a8cc8e9c9c11f9079", size = 29400081, upload-time = "2025-10-28T17:34:39.087Z" }, + { url = "https://files.pythonhosted.org/packages/6a/56/933e68210d92657d93fb0e381683bc0e53a965048d7358ff5fbf9e6a1b17/scipy-1.16.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:03192a35e661470197556de24e7cb1330d84b35b94ead65c46ad6f16f6b28f2a", size = 21391244, upload-time = "2025-10-28T17:34:45.234Z" }, + { url = "https://files.pythonhosted.org/packages/a8/7e/779845db03dc1418e215726329674b40576879b91814568757ff0014ad65/scipy-1.16.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:57d01cb6f85e34f0946b33caa66e892aae072b64b034183f3d87c4025802a119", size = 23929753, upload-time = "2025-10-28T17:34:51.793Z" }, + { url = "https://files.pythonhosted.org/packages/4c/4b/f756cf8161d5365dcdef9e5f460ab226c068211030a175d2fc7f3f41ca64/scipy-1.16.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:96491a6a54e995f00a28a3c3badfff58fd093bf26cd5fb34a2188c8c756a3a2c", size = 33496912, upload-time = "2025-10-28T17:34:59.8Z" }, + { url = "https://files.pythonhosted.org/packages/09/b5/222b1e49a58668f23839ca1542a6322bb095ab8d6590d4f71723869a6c2c/scipy-1.16.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cd13e354df9938598af2be05822c323e97132d5e6306b83a3b4ee6724c6e522e", size = 35802371, upload-time = "2025-10-28T17:35:08.173Z" }, + { url = "https://files.pythonhosted.org/packages/c1/8d/5964ef68bb31829bde27611f8c9deeac13764589fe74a75390242b64ca44/scipy-1.16.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:63d3cdacb8a824a295191a723ee5e4ea7768ca5ca5f2838532d9f2e2b3ce2135", size = 36190477, upload-time = "2025-10-28T17:35:16.7Z" }, + { url = "https://files.pythonhosted.org/packages/ab/f2/b31d75cb9b5fa4dd39a0a931ee9b33e7f6f36f23be5ef560bf72e0f92f32/scipy-1.16.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e7efa2681ea410b10dde31a52b18b0154d66f2485328830e45fdf183af5aefc6", size = 38796678, upload-time = "2025-10-28T17:35:26.354Z" }, + { url = "https://files.pythonhosted.org/packages/b4/1e/b3723d8ff64ab548c38d87055483714fefe6ee20e0189b62352b5e015bb1/scipy-1.16.3-cp313-cp313t-win_amd64.whl", hash = "sha256:2d1ae2cf0c350e7705168ff2429962a89ad90c2d49d1dd300686d8b2a5af22fc", size = 38640178, upload-time = "2025-10-28T17:35:35.304Z" }, + { url = "https://files.pythonhosted.org/packages/8e/f3/d854ff38789aca9b0cc23008d607ced9de4f7ab14fa1ca4329f86b3758ca/scipy-1.16.3-cp313-cp313t-win_arm64.whl", hash = "sha256:0c623a54f7b79dd88ef56da19bc2873afec9673a48f3b85b18e4d402bdd29a5a", size = 25803246, upload-time = "2025-10-28T17:35:42.155Z" }, + { url = "https://files.pythonhosted.org/packages/99/f6/99b10fd70f2d864c1e29a28bbcaa0c6340f9d8518396542d9ea3b4aaae15/scipy-1.16.3-cp314-cp314-macosx_10_14_x86_64.whl", hash = "sha256:875555ce62743e1d54f06cdf22c1e0bc47b91130ac40fe5d783b6dfa114beeb6", size = 36606469, upload-time = "2025-10-28T17:36:08.741Z" }, + { url = "https://files.pythonhosted.org/packages/4d/74/043b54f2319f48ea940dd025779fa28ee360e6b95acb7cd188fad4391c6b/scipy-1.16.3-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:bb61878c18a470021fb515a843dc7a76961a8daceaaaa8bad1332f1bf4b54657", size = 28872043, upload-time = "2025-10-28T17:36:16.599Z" }, + { url = "https://files.pythonhosted.org/packages/4d/e1/24b7e50cc1c4ee6ffbcb1f27fe9f4c8b40e7911675f6d2d20955f41c6348/scipy-1.16.3-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:f2622206f5559784fa5c4b53a950c3c7c1cf3e84ca1b9c4b6c03f062f289ca26", size = 20862952, upload-time = "2025-10-28T17:36:22.966Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3a/3e8c01a4d742b730df368e063787c6808597ccb38636ed821d10b39ca51b/scipy-1.16.3-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:7f68154688c515cdb541a31ef8eb66d8cd1050605be9dcd74199cbd22ac739bc", size = 23508512, upload-time = "2025-10-28T17:36:29.731Z" }, + { url = "https://files.pythonhosted.org/packages/1f/60/c45a12b98ad591536bfe5330cb3cfe1850d7570259303563b1721564d458/scipy-1.16.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8b3c820ddb80029fe9f43d61b81d8b488d3ef8ca010d15122b152db77dc94c22", size = 33413639, upload-time = "2025-10-28T17:36:37.982Z" }, + { url = "https://files.pythonhosted.org/packages/71/bc/35957d88645476307e4839712642896689df442f3e53b0fa016ecf8a3357/scipy-1.16.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d3837938ae715fc0fe3c39c0202de3a8853aff22ca66781ddc2ade7554b7e2cc", size = 35704729, upload-time = "2025-10-28T17:36:46.547Z" }, + { url = "https://files.pythonhosted.org/packages/3b/15/89105e659041b1ca11c386e9995aefacd513a78493656e57789f9d9eab61/scipy-1.16.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:aadd23f98f9cb069b3bd64ddc900c4d277778242e961751f77a8cb5c4b946fb0", size = 36086251, upload-time = "2025-10-28T17:36:55.161Z" }, + { url = "https://files.pythonhosted.org/packages/1a/87/c0ea673ac9c6cc50b3da2196d860273bc7389aa69b64efa8493bdd25b093/scipy-1.16.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b7c5f1bda1354d6a19bc6af73a649f8285ca63ac6b52e64e658a5a11d4d69800", size = 38716681, upload-time = "2025-10-28T17:37:04.1Z" }, + { url = "https://files.pythonhosted.org/packages/91/06/837893227b043fb9b0d13e4bd7586982d8136cb249ffb3492930dab905b8/scipy-1.16.3-cp314-cp314-win_amd64.whl", hash = "sha256:e5d42a9472e7579e473879a1990327830493a7047506d58d73fc429b84c1d49d", size = 39358423, upload-time = "2025-10-28T17:38:20.005Z" }, + { url = "https://files.pythonhosted.org/packages/95/03/28bce0355e4d34a7c034727505a02d19548549e190bedd13a721e35380b7/scipy-1.16.3-cp314-cp314-win_arm64.whl", hash = "sha256:6020470b9d00245926f2d5bb93b119ca0340f0d564eb6fbaad843eaebf9d690f", size = 26135027, upload-time = "2025-10-28T17:38:24.966Z" }, + { url = "https://files.pythonhosted.org/packages/b2/6f/69f1e2b682efe9de8fe9f91040f0cd32f13cfccba690512ba4c582b0bc29/scipy-1.16.3-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:e1d27cbcb4602680a49d787d90664fa4974063ac9d4134813332a8c53dbe667c", size = 37028379, upload-time = "2025-10-28T17:37:14.061Z" }, + { url = "https://files.pythonhosted.org/packages/7c/2d/e826f31624a5ebbab1cd93d30fd74349914753076ed0593e1d56a98c4fb4/scipy-1.16.3-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:9b9c9c07b6d56a35777a1b4cc8966118fb16cfd8daf6743867d17d36cfad2d40", size = 29400052, upload-time = "2025-10-28T17:37:21.709Z" }, + { url = "https://files.pythonhosted.org/packages/69/27/d24feb80155f41fd1f156bf144e7e049b4e2b9dd06261a242905e3bc7a03/scipy-1.16.3-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:3a4c460301fb2cffb7f88528f30b3127742cff583603aa7dc964a52c463b385d", size = 21391183, upload-time = "2025-10-28T17:37:29.559Z" }, + { url = "https://files.pythonhosted.org/packages/f8/d3/1b229e433074c5738a24277eca520a2319aac7465eea7310ea6ae0e98ae2/scipy-1.16.3-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:f667a4542cc8917af1db06366d3f78a5c8e83badd56409f94d1eac8d8d9133fa", size = 23930174, upload-time = "2025-10-28T17:37:36.306Z" }, + { url = "https://files.pythonhosted.org/packages/16/9d/d9e148b0ec680c0f042581a2be79a28a7ab66c0c4946697f9e7553ead337/scipy-1.16.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f379b54b77a597aa7ee5e697df0d66903e41b9c85a6dd7946159e356319158e8", size = 33497852, upload-time = "2025-10-28T17:37:42.228Z" }, + { url = "https://files.pythonhosted.org/packages/2f/22/4e5f7561e4f98b7bea63cf3fd7934bff1e3182e9f1626b089a679914d5c8/scipy-1.16.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4aff59800a3b7f786b70bfd6ab551001cb553244988d7d6b8299cb1ea653b353", size = 35798595, upload-time = "2025-10-28T17:37:48.102Z" }, + { url = "https://files.pythonhosted.org/packages/83/42/6644d714c179429fc7196857866f219fef25238319b650bb32dde7bf7a48/scipy-1.16.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:da7763f55885045036fabcebd80144b757d3db06ab0861415d1c3b7c69042146", size = 36186269, upload-time = "2025-10-28T17:37:53.72Z" }, + { url = "https://files.pythonhosted.org/packages/ac/70/64b4d7ca92f9cf2e6fc6aaa2eecf80bb9b6b985043a9583f32f8177ea122/scipy-1.16.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ffa6eea95283b2b8079b821dc11f50a17d0571c92b43e2b5b12764dc5f9b285d", size = 38802779, upload-time = "2025-10-28T17:37:59.393Z" }, + { url = "https://files.pythonhosted.org/packages/61/82/8d0e39f62764cce5ffd5284131e109f07cf8955aef9ab8ed4e3aa5e30539/scipy-1.16.3-cp314-cp314t-win_amd64.whl", hash = "sha256:d9f48cafc7ce94cf9b15c6bffdc443a81a27bf7075cf2dcd5c8b40f85d10c4e7", size = 39471128, upload-time = "2025-10-28T17:38:05.259Z" }, + { url = "https://files.pythonhosted.org/packages/64/47/a494741db7280eae6dc033510c319e34d42dd41b7ac0c7ead39354d1a2b5/scipy-1.16.3-cp314-cp314t-win_arm64.whl", hash = "sha256:21d9d6b197227a12dcbf9633320a4e34c6b0e51c57268df255a0942983bac562", size = 26464127, upload-time = "2025-10-28T17:38:11.34Z" }, +] + +[[package]] +name = "shapely" +version = "2.1.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4d/bc/0989043118a27cccb4e906a46b7565ce36ca7b57f5a18b78f4f1b0f72d9d/shapely-2.1.2.tar.gz", hash = "sha256:2ed4ecb28320a433db18a5bf029986aa8afcfd740745e78847e330d5d94922a9", size = 315489, upload-time = "2025-09-24T13:51:41.432Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c3/90/98ef257c23c46425dc4d1d31005ad7c8d649fe423a38b917db02c30f1f5a/shapely-2.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b510dda1a3672d6879beb319bc7c5fd302c6c354584690973c838f46ec3e0fa8", size = 1832644, upload-time = "2025-09-24T13:50:44.886Z" }, + { url = "https://files.pythonhosted.org/packages/6d/ab/0bee5a830d209adcd3a01f2d4b70e587cdd9fd7380d5198c064091005af8/shapely-2.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8cff473e81017594d20ec55d86b54bc635544897e13a7cfc12e36909c5309a2a", size = 1642887, upload-time = "2025-09-24T13:50:46.735Z" }, + { url = "https://files.pythonhosted.org/packages/2d/5e/7d7f54ba960c13302584c73704d8c4d15404a51024631adb60b126a4ae88/shapely-2.1.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fe7b77dc63d707c09726b7908f575fc04ff1d1ad0f3fb92aec212396bc6cfe5e", size = 2970931, upload-time = "2025-09-24T13:50:48.374Z" }, + { url = "https://files.pythonhosted.org/packages/f2/a2/83fc37e2a58090e3d2ff79175a95493c664bcd0b653dd75cb9134645a4e5/shapely-2.1.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7ed1a5bbfb386ee8332713bf7508bc24e32d24b74fc9a7b9f8529a55db9f4ee6", size = 3082855, upload-time = "2025-09-24T13:50:50.037Z" }, + { url = "https://files.pythonhosted.org/packages/44/2b/578faf235a5b09f16b5f02833c53822294d7f21b242f8e2d0cf03fb64321/shapely-2.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a84e0582858d841d54355246ddfcbd1fce3179f185da7470f41ce39d001ee1af", size = 3979960, upload-time = "2025-09-24T13:50:51.74Z" }, + { url = "https://files.pythonhosted.org/packages/4d/04/167f096386120f692cc4ca02f75a17b961858997a95e67a3cb6a7bbd6b53/shapely-2.1.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dc3487447a43d42adcdf52d7ac73804f2312cbfa5d433a7d2c506dcab0033dfd", size = 4142851, upload-time = "2025-09-24T13:50:53.49Z" }, + { url = "https://files.pythonhosted.org/packages/48/74/fb402c5a6235d1c65a97348b48cdedb75fb19eca2b1d66d04969fc1c6091/shapely-2.1.2-cp313-cp313-win32.whl", hash = "sha256:9c3a3c648aedc9f99c09263b39f2d8252f199cb3ac154fadc173283d7d111350", size = 1541890, upload-time = "2025-09-24T13:50:55.337Z" }, + { url = "https://files.pythonhosted.org/packages/41/47/3647fe7ad990af60ad98b889657a976042c9988c2807cf322a9d6685f462/shapely-2.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:ca2591bff6645c216695bdf1614fca9c82ea1144d4a7591a466fef64f28f0715", size = 1722151, upload-time = "2025-09-24T13:50:57.153Z" }, + { url = "https://files.pythonhosted.org/packages/3c/49/63953754faa51ffe7d8189bfbe9ca34def29f8c0e34c67cbe2a2795f269d/shapely-2.1.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2d93d23bdd2ed9dc157b46bc2f19b7da143ca8714464249bef6771c679d5ff40", size = 1834130, upload-time = "2025-09-24T13:50:58.49Z" }, + { url = "https://files.pythonhosted.org/packages/7f/ee/dce001c1984052970ff60eb4727164892fb2d08052c575042a47f5a9e88f/shapely-2.1.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:01d0d304b25634d60bd7cf291828119ab55a3bab87dc4af1e44b07fb225f188b", size = 1642802, upload-time = "2025-09-24T13:50:59.871Z" }, + { url = "https://files.pythonhosted.org/packages/da/e7/fc4e9a19929522877fa602f705706b96e78376afb7fad09cad5b9af1553c/shapely-2.1.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8d8382dd120d64b03698b7298b89611a6ea6f55ada9d39942838b79c9bc89801", size = 3018460, upload-time = "2025-09-24T13:51:02.08Z" }, + { url = "https://files.pythonhosted.org/packages/a1/18/7519a25db21847b525696883ddc8e6a0ecaa36159ea88e0fef11466384d0/shapely-2.1.2-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:19efa3611eef966e776183e338b2d7ea43569ae99ab34f8d17c2c054d3205cc0", size = 3095223, upload-time = "2025-09-24T13:51:04.472Z" }, + { url = "https://files.pythonhosted.org/packages/48/de/b59a620b1f3a129c3fecc2737104a0a7e04e79335bd3b0a1f1609744cf17/shapely-2.1.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:346ec0c1a0fcd32f57f00e4134d1200e14bf3f5ae12af87ba83ca275c502498c", size = 4030760, upload-time = "2025-09-24T13:51:06.455Z" }, + { url = "https://files.pythonhosted.org/packages/96/b3/c6655ee7232b417562bae192ae0d3ceaadb1cc0ffc2088a2ddf415456cc2/shapely-2.1.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6305993a35989391bd3476ee538a5c9a845861462327efe00dd11a5c8c709a99", size = 4170078, upload-time = "2025-09-24T13:51:08.584Z" }, + { url = "https://files.pythonhosted.org/packages/a0/8e/605c76808d73503c9333af8f6cbe7e1354d2d238bda5f88eea36bfe0f42a/shapely-2.1.2-cp313-cp313t-win32.whl", hash = "sha256:c8876673449f3401f278c86eb33224c5764582f72b653a415d0e6672fde887bf", size = 1559178, upload-time = "2025-09-24T13:51:10.73Z" }, + { url = "https://files.pythonhosted.org/packages/36/f7/d317eb232352a1f1444d11002d477e54514a4a6045536d49d0c59783c0da/shapely-2.1.2-cp313-cp313t-win_amd64.whl", hash = "sha256:4a44bc62a10d84c11a7a3d7c1c4fe857f7477c3506e24c9062da0db0ae0c449c", size = 1739756, upload-time = "2025-09-24T13:51:12.105Z" }, + { url = "https://files.pythonhosted.org/packages/fc/c4/3ce4c2d9b6aabd27d26ec988f08cb877ba9e6e96086eff81bfea93e688c7/shapely-2.1.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:9a522f460d28e2bf4e12396240a5fc1518788b2fcd73535166d748399ef0c223", size = 1831290, upload-time = "2025-09-24T13:51:13.56Z" }, + { url = "https://files.pythonhosted.org/packages/17/b9/f6ab8918fc15429f79cb04afa9f9913546212d7fb5e5196132a2af46676b/shapely-2.1.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1ff629e00818033b8d71139565527ced7d776c269a49bd78c9df84e8f852190c", size = 1641463, upload-time = "2025-09-24T13:51:14.972Z" }, + { url = "https://files.pythonhosted.org/packages/a5/57/91d59ae525ca641e7ac5551c04c9503aee6f29b92b392f31790fcb1a4358/shapely-2.1.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f67b34271dedc3c653eba4e3d7111aa421d5be9b4c4c7d38d30907f796cb30df", size = 2970145, upload-time = "2025-09-24T13:51:16.961Z" }, + { url = "https://files.pythonhosted.org/packages/8a/cb/4948be52ee1da6927831ab59e10d4c29baa2a714f599f1f0d1bc747f5777/shapely-2.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:21952dc00df38a2c28375659b07a3979d22641aeb104751e769c3ee825aadecf", size = 3073806, upload-time = "2025-09-24T13:51:18.712Z" }, + { url = "https://files.pythonhosted.org/packages/03/83/f768a54af775eb41ef2e7bec8a0a0dbe7d2431c3e78c0a8bdba7ab17e446/shapely-2.1.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1f2f33f486777456586948e333a56ae21f35ae273be99255a191f5c1fa302eb4", size = 3980803, upload-time = "2025-09-24T13:51:20.37Z" }, + { url = "https://files.pythonhosted.org/packages/9f/cb/559c7c195807c91c79d38a1f6901384a2878a76fbdf3f1048893a9b7534d/shapely-2.1.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cf831a13e0d5a7eb519e96f58ec26e049b1fad411fc6fc23b162a7ce04d9cffc", size = 4133301, upload-time = "2025-09-24T13:51:21.887Z" }, + { url = "https://files.pythonhosted.org/packages/80/cd/60d5ae203241c53ef3abd2ef27c6800e21afd6c94e39db5315ea0cbafb4a/shapely-2.1.2-cp314-cp314-win32.whl", hash = "sha256:61edcd8d0d17dd99075d320a1dd39c0cb9616f7572f10ef91b4b5b00c4aeb566", size = 1583247, upload-time = "2025-09-24T13:51:23.401Z" }, + { url = "https://files.pythonhosted.org/packages/74/d4/135684f342e909330e50d31d441ace06bf83c7dc0777e11043f99167b123/shapely-2.1.2-cp314-cp314-win_amd64.whl", hash = "sha256:a444e7afccdb0999e203b976adb37ea633725333e5b119ad40b1ca291ecf311c", size = 1773019, upload-time = "2025-09-24T13:51:24.873Z" }, + { url = "https://files.pythonhosted.org/packages/a3/05/a44f3f9f695fa3ada22786dc9da33c933da1cbc4bfe876fe3a100bafe263/shapely-2.1.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:5ebe3f84c6112ad3d4632b1fd2290665aa75d4cef5f6c5d77c4c95b324527c6a", size = 1834137, upload-time = "2025-09-24T13:51:26.665Z" }, + { url = "https://files.pythonhosted.org/packages/52/7e/4d57db45bf314573427b0a70dfca15d912d108e6023f623947fa69f39b72/shapely-2.1.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5860eb9f00a1d49ebb14e881f5caf6c2cf472c7fd38bd7f253bbd34f934eb076", size = 1642884, upload-time = "2025-09-24T13:51:28.029Z" }, + { url = "https://files.pythonhosted.org/packages/5a/27/4e29c0a55d6d14ad7422bf86995d7ff3f54af0eba59617eb95caf84b9680/shapely-2.1.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b705c99c76695702656327b819c9660768ec33f5ce01fa32b2af62b56ba400a1", size = 3018320, upload-time = "2025-09-24T13:51:29.903Z" }, + { url = "https://files.pythonhosted.org/packages/9f/bb/992e6a3c463f4d29d4cd6ab8963b75b1b1040199edbd72beada4af46bde5/shapely-2.1.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a1fd0ea855b2cf7c9cddaf25543e914dd75af9de08785f20ca3085f2c9ca60b0", size = 3094931, upload-time = "2025-09-24T13:51:32.699Z" }, + { url = "https://files.pythonhosted.org/packages/9c/16/82e65e21070e473f0ed6451224ed9fa0be85033d17e0c6e7213a12f59d12/shapely-2.1.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:df90e2db118c3671a0754f38e36802db75fe0920d211a27481daf50a711fdf26", size = 4030406, upload-time = "2025-09-24T13:51:34.189Z" }, + { url = "https://files.pythonhosted.org/packages/7c/75/c24ed871c576d7e2b64b04b1fe3d075157f6eb54e59670d3f5ffb36e25c7/shapely-2.1.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:361b6d45030b4ac64ddd0a26046906c8202eb60d0f9f53085f5179f1d23021a0", size = 4169511, upload-time = "2025-09-24T13:51:36.297Z" }, + { url = "https://files.pythonhosted.org/packages/b1/f7/b3d1d6d18ebf55236eec1c681ce5e665742aab3c0b7b232720a7d43df7b6/shapely-2.1.2-cp314-cp314t-win32.whl", hash = "sha256:b54df60f1fbdecc8ebc2c5b11870461a6417b3d617f555e5033f1505d36e5735", size = 1602607, upload-time = "2025-09-24T13:51:37.757Z" }, + { url = "https://files.pythonhosted.org/packages/9a/f6/f09272a71976dfc138129b8faf435d064a811ae2f708cb147dccdf7aacdb/shapely-2.1.2-cp314-cp314t-win_amd64.whl", hash = "sha256:0036ac886e0923417932c2e6369b6c52e38e0ff5d9120b90eef5cd9a5fc5cae9", size = 1796682, upload-time = "2025-09-24T13:51:39.233Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "statsmodels" +version = "0.14.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, + { name = "packaging" }, + { name = "pandas" }, + { name = "patsy" }, + { name = "scipy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0d/81/e8d74b34f85285f7335d30c5e3c2d7c0346997af9f3debf9a0a9a63de184/statsmodels-0.14.6.tar.gz", hash = "sha256:4d17873d3e607d398b85126cd4ed7aad89e4e9d89fc744cdab1af3189a996c2a", size = 20689085, upload-time = "2025-12-05T23:08:39.522Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/59/a5aad5b0cc266f5be013db8cde563ac5d2a025e7efc0c328d83b50c72992/statsmodels-0.14.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:47ee7af083623d2091954fa71c7549b8443168f41b7c5dce66510274c50fd73e", size = 10072009, upload-time = "2025-12-05T23:11:14.021Z" }, + { url = "https://files.pythonhosted.org/packages/53/dd/d8cfa7922fc6dc3c56fa6c59b348ea7de829a94cd73208c6f8202dd33f17/statsmodels-0.14.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa60d82e29fcd0a736e86feb63a11d2380322d77a9369a54be8b0965a3985f71", size = 9980018, upload-time = "2025-12-05T23:11:30.907Z" }, + { url = "https://files.pythonhosted.org/packages/ee/77/0ec96803eba444efd75dba32f2ef88765ae3e8f567d276805391ec2c98c6/statsmodels-0.14.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:89ee7d595f5939cc20bf946faedcb5137d975f03ae080f300ebb4398f16a5bd4", size = 10060269, upload-time = "2025-12-05T23:11:46.338Z" }, + { url = "https://files.pythonhosted.org/packages/10/b9/fd41f1f6af13a1a1212a06bb377b17762feaa6d656947bf666f76300fc05/statsmodels-0.14.6-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:730f3297b26749b216a06e4327fe0be59b8d05f7d594fb6caff4287b69654589", size = 10324155, upload-time = "2025-12-05T23:12:01.805Z" }, + { url = "https://files.pythonhosted.org/packages/ee/0f/a6900e220abd2c69cd0a07e3ad26c71984be6061415a60e0f17b152ecf08/statsmodels-0.14.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f1c08befa85e93acc992b72a390ddb7bd876190f1360e61d10cf43833463bc9c", size = 10349765, upload-time = "2025-12-05T23:12:18.018Z" }, + { url = "https://files.pythonhosted.org/packages/98/08/b79f0c614f38e566eebbdcff90c0bcacf3c6ba7a5bbb12183c09c29ca400/statsmodels-0.14.6-cp313-cp313-win_amd64.whl", hash = "sha256:8021271a79f35b842c02a1794465a651a9d06ec2080f76ebc3b7adce77d08233", size = 9540043, upload-time = "2025-12-05T23:12:33.887Z" }, + { url = "https://files.pythonhosted.org/packages/71/de/09540e870318e0c7b58316561d417be45eff731263b4234fdd2eee3511a8/statsmodels-0.14.6-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:00781869991f8f02ad3610da6627fd26ebe262210287beb59761982a8fa88cae", size = 10069403, upload-time = "2025-12-05T23:12:48.424Z" }, + { url = "https://files.pythonhosted.org/packages/ab/f0/63c1bfda75dc53cee858006e1f46bd6d6f883853bea1b97949d0087766ca/statsmodels-0.14.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:73f305fbf31607b35ce919fae636ab8b80d175328ed38fdc6f354e813b86ee37", size = 9989253, upload-time = "2025-12-05T23:13:05.274Z" }, + { url = "https://files.pythonhosted.org/packages/c1/98/b0dfb4f542b2033a3341aa5f1bdd97024230a4ad3670c5b0839d54e3dcab/statsmodels-0.14.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e443e7077a6e2d3faeea72f5a92c9f12c63722686eb80bb40a0f04e4a7e267ad", size = 10090802, upload-time = "2025-12-05T23:13:20.653Z" }, + { url = "https://files.pythonhosted.org/packages/34/0e/2408735aca9e764643196212f9069912100151414dd617d39ffc72d77eee/statsmodels-0.14.6-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3414e40c073d725007a6603a18247ab7af3467e1af4a5e5a24e4c27bc26673b4", size = 10337587, upload-time = "2025-12-05T23:13:37.597Z" }, + { url = "https://files.pythonhosted.org/packages/0f/36/4d44f7035ab3c0b2b6a4c4ebb98dedf36246ccbc1b3e2f51ebcd7ac83abb/statsmodels-0.14.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a518d3f9889ef920116f9fa56d0338069e110f823926356946dae83bc9e33e19", size = 10363350, upload-time = "2025-12-05T23:13:53.08Z" }, + { url = "https://files.pythonhosted.org/packages/26/33/f1652d0c59fa51de18492ee2345b65372550501ad061daa38f950be390b6/statsmodels-0.14.6-cp314-cp314-win_amd64.whl", hash = "sha256:151b73e29f01fe619dbce7f66d61a356e9d1fe5e906529b78807df9189c37721", size = 9588010, upload-time = "2025-12-05T23:14:07.28Z" }, +] + +[[package]] +name = "tzdata" +version = "2025.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/a7/c202b344c5ca7daf398f3b8a477eeb205cf3b6f32e7ec3a6bac0629ca975/tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7", size = 196772, upload-time = "2025-12-13T17:45:35.667Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, +] + +[[package]] +name = "xlrd" +version = "2.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/07/5a/377161c2d3538d1990d7af382c79f3b2372e880b65de21b01b1a2b78691e/xlrd-2.0.2.tar.gz", hash = "sha256:08b5e25de58f21ce71dc7db3b3b8106c1fa776f3024c54e45b45b374e89234c9", size = 100167, upload-time = "2025-06-14T08:46:39.039Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1a/62/c8d562e7766786ba6587d09c5a8ba9f718ed3fa8af7f4553e8f91c36f302/xlrd-2.0.2-py2.py3-none-any.whl", hash = "sha256:ea762c3d29f4cca48d82df517b6d89fbce4db3107f9d78713e48cd321d5c9aa9", size = 96555, upload-time = "2025-06-14T08:46:37.766Z" }, +] +version = 1 +revision = 3 +requires-python = ">=3.13" resolution-markers = [ "python_full_version >= '3.14'", "python_full_version < '3.14'", From ab8e101b86e642955998b56b526e96ed61d065ac Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Tue, 23 Dec 2025 16:20:48 +0000 Subject: [PATCH 71/92] with year as int --- applis_nt/solutions_rp.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/applis_nt/solutions_rp.py b/applis_nt/solutions_rp.py index a3f7afb2..87df7fab 100644 --- a/applis_nt/solutions_rp.py +++ b/applis_nt/solutions_rp.py @@ -37,10 +37,10 @@ def reshape_table_by_year(df, year): genre=pl.col.variablelist.list.get(0, null_on_oob=True), age=pl.col.variablelist.list.get(1, null_on_oob=True), population=pl.col.population.cast(pl.Int64), - annee=pl.lit(year) + annee=pl.lit(year).cast(pl.Int64) ) .rename({'Départements':'dep_code','Départements__00':'dep'}) - .select({'genre', 'age', 'population', 'dep_code', 'dep', 'annee'}) + .select(['dep_code', 'dep', 'annee', 'genre', 'age', 'population']) ) return df_new @@ -48,7 +48,7 @@ def reshape_table_by_year(df, year): def reshape_data(data): df = pl.DataFrame(schema= - ['dep', 'population', 'dep_code', 'annee', 'age', 'genre'] + ['dep_code', 'dep', 'annee', 'genre', 'age', 'population'] ) for annee_dic, annee_df in data.items(): df=pl.concat([df, reshape_table_by_year(annee_df, annee_dic)], strict=False, how='vertical_relaxed') @@ -56,4 +56,5 @@ def reshape_data(data): return df +# reshape_table_by_year(load_data()['1977'], '1977') reshape_data(load_data()) From 9a030f69afab6023fb656b70a05ef37691b26947 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 24 Dec 2025 09:39:10 +0000 Subject: [PATCH 72/92] fix column renaming for null cases --- applis_nt/solutions_rp.py | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/applis_nt/solutions_rp.py b/applis_nt/solutions_rp.py index 87df7fab..1bded934 100644 --- a/applis_nt/solutions_rp.py +++ b/applis_nt/solutions_rp.py @@ -19,17 +19,21 @@ def reshape_table_by_year(df, year): # Merging columns to Genre__Age temp_colnames_list = df.columns for index, colname in enumerate(temp_colnames_list): - if colname[:11] == '__UNNAMED__': - if df[0, colname] is not None: + if df[0, colname] is not None: + if colname[:11] == '__UNNAMED__': temp_colnames_list[index] = temp_colnames_list[index-1].split("_")[0] + "__" + df[0, colname] else: - temp_colnames_list[index] = temp_colnames_list[index-1].split("_")[0] + "__00" + temp_colnames_list[index] = temp_colnames_list[index] + "__" + df[0, colname] + else: + temp_colnames_list[index] = temp_colnames_list[index-1].split("_")[0] + "__00" + temp_colnames_list[0]="dep_code" + temp_colnames_list[1]="dep" df_new = df.rename(dict(zip(df.columns, temp_colnames_list))) # Reshaping data df_new = ( - df_new.drop_nulls(pl.col('Départements__00')) - .unpivot(index=['Départements', 'Départements__00'], value_name="population") + df_new.drop_nulls(pl.col('dep_code')) + .unpivot(index=['dep_code', 'dep'], value_name="population") .with_columns( variablelist=pl.col.variable.str.split('__') ) @@ -39,7 +43,6 @@ def reshape_table_by_year(df, year): population=pl.col.population.cast(pl.Int64), annee=pl.lit(year).cast(pl.Int64) ) - .rename({'Départements':'dep_code','Départements__00':'dep'}) .select(['dep_code', 'dep', 'annee', 'genre', 'age', 'population']) ) @@ -57,4 +60,22 @@ def reshape_data(data): # reshape_table_by_year(load_data()['1977'], '1977') -reshape_data(load_data()) +data = reshape_data(load_data()) + + +with pl.Config(tbl_rows=1000): + data.filter(pl.col.dep_code=="01", pl.col.annee==2022) + +# .group_by("age") +# .agg(pl.col('population').sum()) +# ) +# p9.ggplot(aes(x="annee", y="population")) +# + p9.geom_line() +# ) + + +def plot_population_by_gender_per_department(data, department_code): + # Votre code ici + 1 + + From f0978048f532818b91385d1efc6c844367195633 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 24 Dec 2025 10:37:16 +0000 Subject: [PATCH 73/92] RP: with plot function - Q3 --- applis_nt/{ => rp}/solutions_rp.py | 51 ++++++++++++++++++++-------- pyproject.toml | 2 ++ uv.lock | 54 ++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 14 deletions(-) rename applis_nt/{ => rp}/solutions_rp.py (65%) diff --git a/applis_nt/solutions_rp.py b/applis_nt/rp/solutions_rp.py similarity index 65% rename from applis_nt/solutions_rp.py rename to applis_nt/rp/solutions_rp.py index 1bded934..cd553269 100644 --- a/applis_nt/solutions_rp.py +++ b/applis_nt/rp/solutions_rp.py @@ -1,10 +1,12 @@ +# %% # import copy import polars as pl import plotnine as p9 import geopandas as gpd # import seaborn as sns # import fastexcel -# import solutions +import solutions +import matplotlib.pyplot as plt def load_data(): data = pl.read_excel( @@ -59,23 +61,44 @@ def reshape_data(data): return df -# reshape_table_by_year(load_data()['1977'], '1977') -data = reshape_data(load_data()) +df = reshape_data(load_data()) +# %% +def plot_population_by_gender_per_department(data, department_code): + + df_plot = (data\ + .filter( + pl.col.dep_code.is_in([department_code]), + pl.col.genre!="Ensemble", + pl.col.age=="Total" + ) + .with_columns(pl.col.population/1e6) + ) -with pl.Config(tbl_rows=1000): - data.filter(pl.col.dep_code=="01", pl.col.annee==2022) + plot = ( + p9.ggplot(df_plot, + p9.aes(x="annee", y="population", group="genre", colour="genre")) + + p9.geom_line(size=1) + + p9.theme_matplotlib() + + p9.labs( + title=f"Évolution de la population entre {df_plot.min()[0, "annee"]} et {df_plot.max()[0, "annee"]} dans le {df_plot.min()[0, "dep_code"]} ({df_plot.min()[0, "dep"]})", + x="Année", + y="Population (M)" + ) + ) -# .group_by("age") -# .agg(pl.col('population').sum()) -# ) -# p9.ggplot(aes(x="annee", y="population")) -# + p9.geom_line() -# ) + return plot +# %% +plot_population_by_gender_per_department(df, '31') -def plot_population_by_gender_per_department(data, department_code): - # Votre code ici - 1 +# %% +solutions.plot_population_by_gender_per_department(df.to_pandas(), "31") + +# %% +fig,(ax1,ax2) = plt.subplots(1,2,figsize=(15,6)) +solutions.plot_age_pyramid(df.to_pandas(), 1975, ax=ax1) +solutions.plot_age_pyramid(df.to_pandas(), 2022, ax=ax2) +# %% diff --git a/pyproject.toml b/pyproject.toml index a3acce44..dc2ad128 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,5 +18,7 @@ dependencies = [ "geopandas>=1.1.1", "plotnine>=0.15.2", "polars>=1.36.1", + "pyarrow>=22.0.0", + "seaborn>=0.13.2", "xlrd>=2.0.2", ] diff --git a/uv.lock b/uv.lock index 9a6ba890..9e3adae6 100644 --- a/uv.lock +++ b/uv.lock @@ -135,6 +135,8 @@ dependencies = [ { name = "geopandas" }, { name = "plotnine" }, { name = "polars" }, + { name = "pyarrow" }, + { name = "seaborn" }, { name = "xlrd" }, ] @@ -144,6 +146,8 @@ requires-dist = [ { name = "geopandas", specifier = ">=1.1.1" }, { name = "plotnine", specifier = ">=0.15.2" }, { name = "polars", specifier = ">=1.36.1" }, + { name = "pyarrow", specifier = ">=22.0.0" }, + { name = "seaborn", specifier = ">=0.13.2" }, { name = "xlrd", specifier = ">=2.0.2" }, ] @@ -499,6 +503,42 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d8/a12e6aa14f63784cead437083319ec7cece0d5bb9a5bfe7678cc6578b52a/polars_runtime_32-1.36.1-cp39-abi3-win_arm64.whl", hash = "sha256:809e73857be71250141225ddd5d2b30c97e6340aeaa0d445f930e01bef6888dc", size = 39798896, upload-time = "2025-12-10T01:14:11.568Z" }, ] +[[package]] +name = "pyarrow" +version = "22.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/53/04a7fdc63e6056116c9ddc8b43bc28c12cdd181b85cbeadb79278475f3ae/pyarrow-22.0.0.tar.gz", hash = "sha256:3d600dc583260d845c7d8a6db540339dd883081925da2bd1c5cb808f720b3cd9", size = 1151151, upload-time = "2025-10-24T12:30:00.762Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a6/d6/d0fac16a2963002fc22c8fa75180a838737203d558f0ed3b564c4a54eef5/pyarrow-22.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:e6e95176209257803a8b3d0394f21604e796dadb643d2f7ca21b66c9c0b30c9a", size = 34204629, upload-time = "2025-10-24T10:06:20.274Z" }, + { url = "https://files.pythonhosted.org/packages/c6/9c/1d6357347fbae062ad3f17082f9ebc29cc733321e892c0d2085f42a2212b/pyarrow-22.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:001ea83a58024818826a9e3f89bf9310a114f7e26dfe404a4c32686f97bd7901", size = 35985783, upload-time = "2025-10-24T10:06:27.301Z" }, + { url = "https://files.pythonhosted.org/packages/ff/c0/782344c2ce58afbea010150df07e3a2f5fdad299cd631697ae7bd3bac6e3/pyarrow-22.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:ce20fe000754f477c8a9125543f1936ea5b8867c5406757c224d745ed033e691", size = 45020999, upload-time = "2025-10-24T10:06:35.387Z" }, + { url = "https://files.pythonhosted.org/packages/1b/8b/5362443737a5307a7b67c1017c42cd104213189b4970bf607e05faf9c525/pyarrow-22.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e0a15757fccb38c410947df156f9749ae4a3c89b2393741a50521f39a8cf202a", size = 47724601, upload-time = "2025-10-24T10:06:43.551Z" }, + { url = "https://files.pythonhosted.org/packages/69/4d/76e567a4fc2e190ee6072967cb4672b7d9249ac59ae65af2d7e3047afa3b/pyarrow-22.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cedb9dd9358e4ea1d9bce3665ce0797f6adf97ff142c8e25b46ba9cdd508e9b6", size = 48001050, upload-time = "2025-10-24T10:06:52.284Z" }, + { url = "https://files.pythonhosted.org/packages/01/5e/5653f0535d2a1aef8223cee9d92944cb6bccfee5cf1cd3f462d7cb022790/pyarrow-22.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:252be4a05f9d9185bb8c18e83764ebcfea7185076c07a7a662253af3a8c07941", size = 50307877, upload-time = "2025-10-24T10:07:02.405Z" }, + { url = "https://files.pythonhosted.org/packages/2d/f8/1d0bd75bf9328a3b826e24a16e5517cd7f9fbf8d34a3184a4566ef5a7f29/pyarrow-22.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:a4893d31e5ef780b6edcaf63122df0f8d321088bb0dee4c8c06eccb1ca28d145", size = 27977099, upload-time = "2025-10-24T10:08:07.259Z" }, + { url = "https://files.pythonhosted.org/packages/90/81/db56870c997805bf2b0f6eeeb2d68458bf4654652dccdcf1bf7a42d80903/pyarrow-22.0.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:f7fe3dbe871294ba70d789be16b6e7e52b418311e166e0e3cba9522f0f437fb1", size = 34336685, upload-time = "2025-10-24T10:07:11.47Z" }, + { url = "https://files.pythonhosted.org/packages/1c/98/0727947f199aba8a120f47dfc229eeb05df15bcd7a6f1b669e9f882afc58/pyarrow-22.0.0-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:ba95112d15fd4f1105fb2402c4eab9068f0554435e9b7085924bcfaac2cc306f", size = 36032158, upload-time = "2025-10-24T10:07:18.626Z" }, + { url = "https://files.pythonhosted.org/packages/96/b4/9babdef9c01720a0785945c7cf550e4acd0ebcd7bdd2e6f0aa7981fa85e2/pyarrow-22.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:c064e28361c05d72eed8e744c9605cbd6d2bb7481a511c74071fd9b24bc65d7d", size = 44892060, upload-time = "2025-10-24T10:07:26.002Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ca/2f8804edd6279f78a37062d813de3f16f29183874447ef6d1aadbb4efa0f/pyarrow-22.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:6f9762274496c244d951c819348afbcf212714902742225f649cf02823a6a10f", size = 47504395, upload-time = "2025-10-24T10:07:34.09Z" }, + { url = "https://files.pythonhosted.org/packages/b9/f0/77aa5198fd3943682b2e4faaf179a674f0edea0d55d326d83cb2277d9363/pyarrow-22.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a9d9ffdc2ab696f6b15b4d1f7cec6658e1d788124418cb30030afbae31c64746", size = 48066216, upload-time = "2025-10-24T10:07:43.528Z" }, + { url = "https://files.pythonhosted.org/packages/79/87/a1937b6e78b2aff18b706d738c9e46ade5bfcf11b294e39c87706a0089ac/pyarrow-22.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ec1a15968a9d80da01e1d30349b2b0d7cc91e96588ee324ce1b5228175043e95", size = 50288552, upload-time = "2025-10-24T10:07:53.519Z" }, + { url = "https://files.pythonhosted.org/packages/60/ae/b5a5811e11f25788ccfdaa8f26b6791c9807119dffcf80514505527c384c/pyarrow-22.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:bba208d9c7decf9961998edf5c65e3ea4355d5818dd6cd0f6809bec1afb951cc", size = 28262504, upload-time = "2025-10-24T10:08:00.932Z" }, + { url = "https://files.pythonhosted.org/packages/bd/b0/0fa4d28a8edb42b0a7144edd20befd04173ac79819547216f8a9f36f9e50/pyarrow-22.0.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:9bddc2cade6561f6820d4cd73f99a0243532ad506bc510a75a5a65a522b2d74d", size = 34224062, upload-time = "2025-10-24T10:08:14.101Z" }, + { url = "https://files.pythonhosted.org/packages/0f/a8/7a719076b3c1be0acef56a07220c586f25cd24de0e3f3102b438d18ae5df/pyarrow-22.0.0-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:e70ff90c64419709d38c8932ea9fe1cc98415c4f87ea8da81719e43f02534bc9", size = 35990057, upload-time = "2025-10-24T10:08:21.842Z" }, + { url = "https://files.pythonhosted.org/packages/89/3c/359ed54c93b47fb6fe30ed16cdf50e3f0e8b9ccfb11b86218c3619ae50a8/pyarrow-22.0.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:92843c305330aa94a36e706c16209cd4df274693e777ca47112617db7d0ef3d7", size = 45068002, upload-time = "2025-10-24T10:08:29.034Z" }, + { url = "https://files.pythonhosted.org/packages/55/fc/4945896cc8638536ee787a3bd6ce7cec8ec9acf452d78ec39ab328efa0a1/pyarrow-22.0.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:6dda1ddac033d27421c20d7a7943eec60be44e0db4e079f33cc5af3b8280ccde", size = 47737765, upload-time = "2025-10-24T10:08:38.559Z" }, + { url = "https://files.pythonhosted.org/packages/cd/5e/7cb7edeb2abfaa1f79b5d5eb89432356155c8426f75d3753cbcb9592c0fd/pyarrow-22.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:84378110dd9a6c06323b41b56e129c504d157d1a983ce8f5443761eb5256bafc", size = 48048139, upload-time = "2025-10-24T10:08:46.784Z" }, + { url = "https://files.pythonhosted.org/packages/88/c6/546baa7c48185f5e9d6e59277c4b19f30f48c94d9dd938c2a80d4d6b067c/pyarrow-22.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:854794239111d2b88b40b6ef92aa478024d1e5074f364033e73e21e3f76b25e0", size = 50314244, upload-time = "2025-10-24T10:08:55.771Z" }, + { url = "https://files.pythonhosted.org/packages/3c/79/755ff2d145aafec8d347bf18f95e4e81c00127f06d080135dfc86aea417c/pyarrow-22.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:b883fe6fd85adad7932b3271c38ac289c65b7337c2c132e9569f9d3940620730", size = 28757501, upload-time = "2025-10-24T10:09:59.891Z" }, + { url = "https://files.pythonhosted.org/packages/0e/d2/237d75ac28ced3147912954e3c1a174df43a95f4f88e467809118a8165e0/pyarrow-22.0.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:7a820d8ae11facf32585507c11f04e3f38343c1e784c9b5a8b1da5c930547fe2", size = 34355506, upload-time = "2025-10-24T10:09:02.953Z" }, + { url = "https://files.pythonhosted.org/packages/1e/2c/733dfffe6d3069740f98e57ff81007809067d68626c5faef293434d11bd6/pyarrow-22.0.0-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:c6ec3675d98915bf1ec8b3c7986422682f7232ea76cad276f4c8abd5b7319b70", size = 36047312, upload-time = "2025-10-24T10:09:10.334Z" }, + { url = "https://files.pythonhosted.org/packages/7c/2b/29d6e3782dc1f299727462c1543af357a0f2c1d3c160ce199950d9ca51eb/pyarrow-22.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:3e739edd001b04f654b166204fc7a9de896cf6007eaff33409ee9e50ceaff754", size = 45081609, upload-time = "2025-10-24T10:09:18.61Z" }, + { url = "https://files.pythonhosted.org/packages/8d/42/aa9355ecc05997915af1b7b947a7f66c02dcaa927f3203b87871c114ba10/pyarrow-22.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:7388ac685cab5b279a41dfe0a6ccd99e4dbf322edfb63e02fc0443bf24134e91", size = 47703663, upload-time = "2025-10-24T10:09:27.369Z" }, + { url = "https://files.pythonhosted.org/packages/ee/62/45abedde480168e83a1de005b7b7043fd553321c1e8c5a9a114425f64842/pyarrow-22.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f633074f36dbc33d5c05b5dc75371e5660f1dbf9c8b1d95669def05e5425989c", size = 48066543, upload-time = "2025-10-24T10:09:34.908Z" }, + { url = "https://files.pythonhosted.org/packages/84/e9/7878940a5b072e4f3bf998770acafeae13b267f9893af5f6d4ab3904b67e/pyarrow-22.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4c19236ae2402a8663a2c8f21f1870a03cc57f0bef7e4b6eb3238cc82944de80", size = 50288838, upload-time = "2025-10-24T10:09:44.394Z" }, + { url = "https://files.pythonhosted.org/packages/7b/03/f335d6c52b4a4761bcc83499789a1e2e16d9d201a58c327a9b5cc9a41bd9/pyarrow-22.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0c34fe18094686194f204a3b1787a27456897d8a2d62caf84b61e8dfbc0252ae", size = 29185594, upload-time = "2025-10-24T10:09:53.111Z" }, +] + [[package]] name = "pyogrio" version = "0.12.1" @@ -664,6 +704,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/64/47/a494741db7280eae6dc033510c319e34d42dd41b7ac0c7ead39354d1a2b5/scipy-1.16.3-cp314-cp314t-win_arm64.whl", hash = "sha256:21d9d6b197227a12dcbf9633320a4e34c6b0e51c57268df255a0942983bac562", size = 26464127, upload-time = "2025-10-28T17:38:11.34Z" }, ] +[[package]] +name = "seaborn" +version = "0.13.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "matplotlib" }, + { name = "numpy" }, + { name = "pandas" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/86/59/a451d7420a77ab0b98f7affa3a1d78a313d2f7281a57afb1a34bae8ab412/seaborn-0.13.2.tar.gz", hash = "sha256:93e60a40988f4d65e9f4885df477e2fdaff6b73a9ded434c1ab356dd57eefff7", size = 1457696, upload-time = "2024-01-25T13:21:52.551Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/11/00d3c3dfc25ad54e731d91449895a79e4bf2384dc3ac01809010ba88f6d5/seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987", size = 294914, upload-time = "2024-01-25T13:21:49.598Z" }, +] + [[package]] name = "shapely" version = "2.1.2" From 2bfff13c63fbcd3f6f24560ae861d6a53814bb6e Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 24 Dec 2025 13:47:36 +0000 Subject: [PATCH 74/92] with pyramide data and plot age pyramide --- applis_nt/rp/solutions_rp.py | 79 ++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 3 deletions(-) diff --git a/applis_nt/rp/solutions_rp.py b/applis_nt/rp/solutions_rp.py index cd553269..8025edab 100644 --- a/applis_nt/rp/solutions_rp.py +++ b/applis_nt/rp/solutions_rp.py @@ -34,7 +34,7 @@ def reshape_table_by_year(df, year): # Reshaping data df_new = ( - df_new.drop_nulls(pl.col('dep_code')) + df_new.drop_nulls(pl.col('dep')) .unpivot(index=['dep_code', 'dep'], value_name="population") .with_columns( variablelist=pl.col.variable.str.split('__') @@ -69,8 +69,8 @@ def plot_population_by_gender_per_department(data, department_code): df_plot = (data\ .filter( pl.col.dep_code.is_in([department_code]), - pl.col.genre!="Ensemble", - pl.col.age=="Total" + pl.col.genre !="Ensemble", + pl.col.age == "Total" ) .with_columns(pl.col.population/1e6) ) @@ -95,10 +95,83 @@ def plot_population_by_gender_per_department(data, department_code): # %% solutions.plot_population_by_gender_per_department(df.to_pandas(), "31") +# %% +pyramide_data = solutions.get_age_pyramid_data(df.to_pandas(), 2022) +pyramide_data + +# %% +def get_age_pyramid_data(df, years): + pyramide_data = df\ + .filter( + pl.col.annee.is_in([1975, 2022]), + pl.col.age != "Total" + )\ + .group_by( + ["annee", "genre", "age"] + )\ + .agg( + pl.col.population.sum() + )\ + .pivot(on="genre", values="population", index=["annee", "age"])\ + .sort("age")\ + .with_columns(Hommes=-pl.col.Hommes) + + return pyramide_data + + +# Function to turn labels of ge pyramid to absolute values +def abs_list(list): + return [abs(xi) if isinstance(xi, (int, float)) else xi for xi in list] + + +def tr_age_sorted_plot(list): + return [tr_age_sorted[5:] for tr_age_sorted in list] + + +# %% +def plot_age_pyramid(years): + df_plot = get_age_pyramid_data(df, years)\ + .unpivot(index=["annee", "age"])\ + .filter(pl.col.variable != "Ensemble")\ + .with_columns(pl.col.value/1e6) + + # Otherwise the categorie 5 to 9 is plotted betwwen 45 to 49 and 50 to 55 + age_categories_sorted = df_plot.select("age").unique().with_columns(pl.col.age.str.len_chars().alias("length")).sort("length", "age").select("age").to_series().to_list() + + df_plot = df_plot.join( + pl.DataFrame({ + "age": age_categories_sorted, + "age_sorted" : [f'{age_tr_i+1:02} - {age_categories_sorted[age_tr_i]}' for age_tr_i in range(len(age_categories_sorted))] + }), + on="age", + how="left" + ) + + plot = ( df_plot + >> p9.ggplot() + + p9.geom_bar(p9.aes("age_sorted", "value", fill="variable"),stat="identity") + + p9.theme_matplotlib() + + p9.facet_wrap("~ annee") + + p9.coord_flip() + + p9.scale_x_discrete(labels=tr_age_sorted_plot) + + p9.scale_y_continuous(labels=abs_list) + + p9.labs( + title=f"Évolution de la structure de la population entre {df_plot.min()[0, "annee"]} et {df_plot.max()[0, "annee"]})", + x="Tranche d'âge", + y="Population (M)" + ) + ) + + return plot + +# %% +plot_age_pyramid([1975, 2023]) # %% fig,(ax1,ax2) = plt.subplots(1,2,figsize=(15,6)) solutions.plot_age_pyramid(df.to_pandas(), 1975, ax=ax1) solutions.plot_age_pyramid(df.to_pandas(), 2022, ax=ax2) + +fig # %% From f37391c2ad288b5a421e8c47e76841017e97eb14 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 24 Dec 2025 13:52:51 +0000 Subject: [PATCH 75/92] change var name for graph legend --- applis_nt/rp/solutions_rp.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/applis_nt/rp/solutions_rp.py b/applis_nt/rp/solutions_rp.py index 8025edab..39fbd345 100644 --- a/applis_nt/rp/solutions_rp.py +++ b/applis_nt/rp/solutions_rp.py @@ -131,8 +131,8 @@ def tr_age_sorted_plot(list): # %% def plot_age_pyramid(years): df_plot = get_age_pyramid_data(df, years)\ - .unpivot(index=["annee", "age"])\ - .filter(pl.col.variable != "Ensemble")\ + .unpivot(index=["annee", "age"], variable_name="genre")\ + .filter(pl.col.genre != "Ensemble")\ .with_columns(pl.col.value/1e6) # Otherwise the categorie 5 to 9 is plotted betwwen 45 to 49 and 50 to 55 @@ -149,7 +149,7 @@ def plot_age_pyramid(years): plot = ( df_plot >> p9.ggplot() - + p9.geom_bar(p9.aes("age_sorted", "value", fill="variable"),stat="identity") + + p9.geom_bar(p9.aes("age_sorted", "value", fill="genre"),stat="identity") + p9.theme_matplotlib() + p9.facet_wrap("~ annee") + p9.coord_flip() From 41823e943122c5fa4f16e8ff7ac9aaa8b2c3fc89 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 24 Dec 2025 14:51:14 +0000 Subject: [PATCH 76/92] with regions and departements --- applis_nt/rp/solutions_rp.py | 45 +- pyproject.toml | 4 +- uv.lock | 2274 ---------------------------------- 3 files changed, 46 insertions(+), 2277 deletions(-) diff --git a/applis_nt/rp/solutions_rp.py b/applis_nt/rp/solutions_rp.py index 39fbd345..2299573b 100644 --- a/applis_nt/rp/solutions_rp.py +++ b/applis_nt/rp/solutions_rp.py @@ -60,7 +60,7 @@ def reshape_data(data): return df - +# %% df = reshape_data(load_data()) # %% @@ -175,3 +175,46 @@ def plot_age_pyramid(years): fig # %% +df_matching = solutions.load_departements_regions("https://static.data.gouv.fr/resources/departements-et-leurs-regions/20190815-175403/departements-region.json") +df_matching + +# %% +def load_departements_regions(url): + return pl.from_dicts(requests.get(url).json()) + + +# %% +url = "https://static.data.gouv.fr/resources/departements-et-leurs-regions/20190815-175403/departements-region.json" +reg_details = load_departements_regions(url) +reg_details +# %% +df_regions = solutions.match_department_regions(df.to_pandas(), df_matching) +df_regions + +# %% +def match_department_regions(df, df_matching): + df_regions = df.join( + df_matching, + how="left", + left_on="dep_code", + right_on="num_dep" + ) + return df_regions + +# %% +df_regions = match_department_regions(df, reg_details) +df_regions + +# %% +geo = solutions.load_geo_data("https://minio.lab.sspcloud.fr/projet-cartiflette/diffusion/shapefiles-test1/year=2022/administrative_level=REGION/crs=4326/FRANCE_ENTIERE=metropole/vectorfile_format='geojson'/provider='IGN'/source='EXPRESS-COG-CARTO-TERRITOIRE'/raw.geojson") +geo + +# %% +def load_geo_data(url): + geodata = gpd.read_file(url) + geodata = geodata[[NOM', 'geometry']] + return +# %% +url = "https://minio.lab.sspcloud.fr/projet-cartiflette/diffusion/shapefiles-test1/year=2022/administrative_level=REGION/crs=4326/FRANCE_ENTIERE=metropole/vectorfile_format='geojson'/provider='IGN'/source='EXPRESS-COG-CARTO-TERRITOIRE'/raw.geojson" + +load_geo_data(url) \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index dc2ad128..0f47637e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,16 +9,16 @@ dependencies = [ "numpy", "pandas", "pyarrow", - "requests", - "seaborn", "scikit-learn", "tidypolars>=0.3.2", "jupyter>=1.1.1", + "cartiflette>=0.1.9", "fastexcel>=0.18.0", "geopandas>=1.1.1", "plotnine>=0.15.2", "polars>=1.36.1", "pyarrow>=22.0.0", + "requests>=2.32.5", "seaborn>=0.13.2", "xlrd>=2.0.2", ] diff --git a/uv.lock b/uv.lock index 9e3adae6..a41f569e 100644 --- a/uv.lock +++ b/uv.lock @@ -135,8 +135,6 @@ dependencies = [ { name = "geopandas" }, { name = "plotnine" }, { name = "polars" }, - { name = "pyarrow" }, - { name = "seaborn" }, { name = "xlrd" }, ] @@ -146,8 +144,6 @@ requires-dist = [ { name = "geopandas", specifier = ">=1.1.1" }, { name = "plotnine", specifier = ">=0.15.2" }, { name = "polars", specifier = ">=1.36.1" }, - { name = "pyarrow", specifier = ">=22.0.0" }, - { name = "seaborn", specifier = ">=0.13.2" }, { name = "xlrd", specifier = ">=2.0.2" }, ] @@ -503,42 +499,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d8/a12e6aa14f63784cead437083319ec7cece0d5bb9a5bfe7678cc6578b52a/polars_runtime_32-1.36.1-cp39-abi3-win_arm64.whl", hash = "sha256:809e73857be71250141225ddd5d2b30c97e6340aeaa0d445f930e01bef6888dc", size = 39798896, upload-time = "2025-12-10T01:14:11.568Z" }, ] -[[package]] -name = "pyarrow" -version = "22.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/30/53/04a7fdc63e6056116c9ddc8b43bc28c12cdd181b85cbeadb79278475f3ae/pyarrow-22.0.0.tar.gz", hash = "sha256:3d600dc583260d845c7d8a6db540339dd883081925da2bd1c5cb808f720b3cd9", size = 1151151, upload-time = "2025-10-24T12:30:00.762Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a6/d6/d0fac16a2963002fc22c8fa75180a838737203d558f0ed3b564c4a54eef5/pyarrow-22.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:e6e95176209257803a8b3d0394f21604e796dadb643d2f7ca21b66c9c0b30c9a", size = 34204629, upload-time = "2025-10-24T10:06:20.274Z" }, - { url = "https://files.pythonhosted.org/packages/c6/9c/1d6357347fbae062ad3f17082f9ebc29cc733321e892c0d2085f42a2212b/pyarrow-22.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:001ea83a58024818826a9e3f89bf9310a114f7e26dfe404a4c32686f97bd7901", size = 35985783, upload-time = "2025-10-24T10:06:27.301Z" }, - { url = "https://files.pythonhosted.org/packages/ff/c0/782344c2ce58afbea010150df07e3a2f5fdad299cd631697ae7bd3bac6e3/pyarrow-22.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:ce20fe000754f477c8a9125543f1936ea5b8867c5406757c224d745ed033e691", size = 45020999, upload-time = "2025-10-24T10:06:35.387Z" }, - { url = "https://files.pythonhosted.org/packages/1b/8b/5362443737a5307a7b67c1017c42cd104213189b4970bf607e05faf9c525/pyarrow-22.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e0a15757fccb38c410947df156f9749ae4a3c89b2393741a50521f39a8cf202a", size = 47724601, upload-time = "2025-10-24T10:06:43.551Z" }, - { url = "https://files.pythonhosted.org/packages/69/4d/76e567a4fc2e190ee6072967cb4672b7d9249ac59ae65af2d7e3047afa3b/pyarrow-22.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cedb9dd9358e4ea1d9bce3665ce0797f6adf97ff142c8e25b46ba9cdd508e9b6", size = 48001050, upload-time = "2025-10-24T10:06:52.284Z" }, - { url = "https://files.pythonhosted.org/packages/01/5e/5653f0535d2a1aef8223cee9d92944cb6bccfee5cf1cd3f462d7cb022790/pyarrow-22.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:252be4a05f9d9185bb8c18e83764ebcfea7185076c07a7a662253af3a8c07941", size = 50307877, upload-time = "2025-10-24T10:07:02.405Z" }, - { url = "https://files.pythonhosted.org/packages/2d/f8/1d0bd75bf9328a3b826e24a16e5517cd7f9fbf8d34a3184a4566ef5a7f29/pyarrow-22.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:a4893d31e5ef780b6edcaf63122df0f8d321088bb0dee4c8c06eccb1ca28d145", size = 27977099, upload-time = "2025-10-24T10:08:07.259Z" }, - { url = "https://files.pythonhosted.org/packages/90/81/db56870c997805bf2b0f6eeeb2d68458bf4654652dccdcf1bf7a42d80903/pyarrow-22.0.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:f7fe3dbe871294ba70d789be16b6e7e52b418311e166e0e3cba9522f0f437fb1", size = 34336685, upload-time = "2025-10-24T10:07:11.47Z" }, - { url = "https://files.pythonhosted.org/packages/1c/98/0727947f199aba8a120f47dfc229eeb05df15bcd7a6f1b669e9f882afc58/pyarrow-22.0.0-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:ba95112d15fd4f1105fb2402c4eab9068f0554435e9b7085924bcfaac2cc306f", size = 36032158, upload-time = "2025-10-24T10:07:18.626Z" }, - { url = "https://files.pythonhosted.org/packages/96/b4/9babdef9c01720a0785945c7cf550e4acd0ebcd7bdd2e6f0aa7981fa85e2/pyarrow-22.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:c064e28361c05d72eed8e744c9605cbd6d2bb7481a511c74071fd9b24bc65d7d", size = 44892060, upload-time = "2025-10-24T10:07:26.002Z" }, - { url = "https://files.pythonhosted.org/packages/f8/ca/2f8804edd6279f78a37062d813de3f16f29183874447ef6d1aadbb4efa0f/pyarrow-22.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:6f9762274496c244d951c819348afbcf212714902742225f649cf02823a6a10f", size = 47504395, upload-time = "2025-10-24T10:07:34.09Z" }, - { url = "https://files.pythonhosted.org/packages/b9/f0/77aa5198fd3943682b2e4faaf179a674f0edea0d55d326d83cb2277d9363/pyarrow-22.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a9d9ffdc2ab696f6b15b4d1f7cec6658e1d788124418cb30030afbae31c64746", size = 48066216, upload-time = "2025-10-24T10:07:43.528Z" }, - { url = "https://files.pythonhosted.org/packages/79/87/a1937b6e78b2aff18b706d738c9e46ade5bfcf11b294e39c87706a0089ac/pyarrow-22.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ec1a15968a9d80da01e1d30349b2b0d7cc91e96588ee324ce1b5228175043e95", size = 50288552, upload-time = "2025-10-24T10:07:53.519Z" }, - { url = "https://files.pythonhosted.org/packages/60/ae/b5a5811e11f25788ccfdaa8f26b6791c9807119dffcf80514505527c384c/pyarrow-22.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:bba208d9c7decf9961998edf5c65e3ea4355d5818dd6cd0f6809bec1afb951cc", size = 28262504, upload-time = "2025-10-24T10:08:00.932Z" }, - { url = "https://files.pythonhosted.org/packages/bd/b0/0fa4d28a8edb42b0a7144edd20befd04173ac79819547216f8a9f36f9e50/pyarrow-22.0.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:9bddc2cade6561f6820d4cd73f99a0243532ad506bc510a75a5a65a522b2d74d", size = 34224062, upload-time = "2025-10-24T10:08:14.101Z" }, - { url = "https://files.pythonhosted.org/packages/0f/a8/7a719076b3c1be0acef56a07220c586f25cd24de0e3f3102b438d18ae5df/pyarrow-22.0.0-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:e70ff90c64419709d38c8932ea9fe1cc98415c4f87ea8da81719e43f02534bc9", size = 35990057, upload-time = "2025-10-24T10:08:21.842Z" }, - { url = "https://files.pythonhosted.org/packages/89/3c/359ed54c93b47fb6fe30ed16cdf50e3f0e8b9ccfb11b86218c3619ae50a8/pyarrow-22.0.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:92843c305330aa94a36e706c16209cd4df274693e777ca47112617db7d0ef3d7", size = 45068002, upload-time = "2025-10-24T10:08:29.034Z" }, - { url = "https://files.pythonhosted.org/packages/55/fc/4945896cc8638536ee787a3bd6ce7cec8ec9acf452d78ec39ab328efa0a1/pyarrow-22.0.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:6dda1ddac033d27421c20d7a7943eec60be44e0db4e079f33cc5af3b8280ccde", size = 47737765, upload-time = "2025-10-24T10:08:38.559Z" }, - { url = "https://files.pythonhosted.org/packages/cd/5e/7cb7edeb2abfaa1f79b5d5eb89432356155c8426f75d3753cbcb9592c0fd/pyarrow-22.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:84378110dd9a6c06323b41b56e129c504d157d1a983ce8f5443761eb5256bafc", size = 48048139, upload-time = "2025-10-24T10:08:46.784Z" }, - { url = "https://files.pythonhosted.org/packages/88/c6/546baa7c48185f5e9d6e59277c4b19f30f48c94d9dd938c2a80d4d6b067c/pyarrow-22.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:854794239111d2b88b40b6ef92aa478024d1e5074f364033e73e21e3f76b25e0", size = 50314244, upload-time = "2025-10-24T10:08:55.771Z" }, - { url = "https://files.pythonhosted.org/packages/3c/79/755ff2d145aafec8d347bf18f95e4e81c00127f06d080135dfc86aea417c/pyarrow-22.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:b883fe6fd85adad7932b3271c38ac289c65b7337c2c132e9569f9d3940620730", size = 28757501, upload-time = "2025-10-24T10:09:59.891Z" }, - { url = "https://files.pythonhosted.org/packages/0e/d2/237d75ac28ced3147912954e3c1a174df43a95f4f88e467809118a8165e0/pyarrow-22.0.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:7a820d8ae11facf32585507c11f04e3f38343c1e784c9b5a8b1da5c930547fe2", size = 34355506, upload-time = "2025-10-24T10:09:02.953Z" }, - { url = "https://files.pythonhosted.org/packages/1e/2c/733dfffe6d3069740f98e57ff81007809067d68626c5faef293434d11bd6/pyarrow-22.0.0-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:c6ec3675d98915bf1ec8b3c7986422682f7232ea76cad276f4c8abd5b7319b70", size = 36047312, upload-time = "2025-10-24T10:09:10.334Z" }, - { url = "https://files.pythonhosted.org/packages/7c/2b/29d6e3782dc1f299727462c1543af357a0f2c1d3c160ce199950d9ca51eb/pyarrow-22.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:3e739edd001b04f654b166204fc7a9de896cf6007eaff33409ee9e50ceaff754", size = 45081609, upload-time = "2025-10-24T10:09:18.61Z" }, - { url = "https://files.pythonhosted.org/packages/8d/42/aa9355ecc05997915af1b7b947a7f66c02dcaa927f3203b87871c114ba10/pyarrow-22.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:7388ac685cab5b279a41dfe0a6ccd99e4dbf322edfb63e02fc0443bf24134e91", size = 47703663, upload-time = "2025-10-24T10:09:27.369Z" }, - { url = "https://files.pythonhosted.org/packages/ee/62/45abedde480168e83a1de005b7b7043fd553321c1e8c5a9a114425f64842/pyarrow-22.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f633074f36dbc33d5c05b5dc75371e5660f1dbf9c8b1d95669def05e5425989c", size = 48066543, upload-time = "2025-10-24T10:09:34.908Z" }, - { url = "https://files.pythonhosted.org/packages/84/e9/7878940a5b072e4f3bf998770acafeae13b267f9893af5f6d4ab3904b67e/pyarrow-22.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4c19236ae2402a8663a2c8f21f1870a03cc57f0bef7e4b6eb3238cc82944de80", size = 50288838, upload-time = "2025-10-24T10:09:44.394Z" }, - { url = "https://files.pythonhosted.org/packages/7b/03/f335d6c52b4a4761bcc83499789a1e2e16d9d201a58c327a9b5cc9a41bd9/pyarrow-22.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0c34fe18094686194f204a3b1787a27456897d8a2d62caf84b61e8dfbc0252ae", size = 29185594, upload-time = "2025-10-24T10:09:53.111Z" }, -] - [[package]] name = "pyogrio" version = "0.12.1" @@ -704,20 +664,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/64/47/a494741db7280eae6dc033510c319e34d42dd41b7ac0c7ead39354d1a2b5/scipy-1.16.3-cp314-cp314t-win_arm64.whl", hash = "sha256:21d9d6b197227a12dcbf9633320a4e34c6b0e51c57268df255a0942983bac562", size = 26464127, upload-time = "2025-10-28T17:38:11.34Z" }, ] -[[package]] -name = "seaborn" -version = "0.13.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "matplotlib" }, - { name = "numpy" }, - { name = "pandas" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/86/59/a451d7420a77ab0b98f7affa3a1d78a313d2f7281a57afb1a34bae8ab412/seaborn-0.13.2.tar.gz", hash = "sha256:93e60a40988f4d65e9f4885df477e2fdaff6b73a9ded434c1ab356dd57eefff7", size = 1457696, upload-time = "2024-01-25T13:21:52.551Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/83/11/00d3c3dfc25ad54e731d91449895a79e4bf2384dc3ac01809010ba88f6d5/seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987", size = 294914, upload-time = "2024-01-25T13:21:49.598Z" }, -] - [[package]] name = "shapely" version = "2.1.2" @@ -814,2223 +760,3 @@ sdist = { url = "https://files.pythonhosted.org/packages/07/5a/377161c2d3538d199 wheels = [ { url = "https://files.pythonhosted.org/packages/1a/62/c8d562e7766786ba6587d09c5a8ba9f718ed3fa8af7f4553e8f91c36f302/xlrd-2.0.2-py2.py3-none-any.whl", hash = "sha256:ea762c3d29f4cca48d82df517b6d89fbce4db3107f9d78713e48cd321d5c9aa9", size = 96555, upload-time = "2025-06-14T08:46:37.766Z" }, ] -version = 1 -revision = 3 -requires-python = ">=3.13" -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version < '3.14'", -] - -[[package]] -name = "" -version = "0.0.1" -source = { virtual = "." } -dependencies = [ - { name = "geopandas" }, - { name = "jupyter" }, - { name = "matplotlib" }, - { name = "numpy" }, - { name = "pandas" }, - { name = "polars" }, - { name = "pyarrow" }, - { name = "requests" }, - { name = "scikit-learn" }, - { name = "seaborn" }, - { name = "tidypolars" }, - { name = "xlrd" }, -] - -[package.metadata] -requires-dist = [ - { name = "geopandas" }, - { name = "jupyter", specifier = ">=1.1.1" }, - { name = "matplotlib" }, - { name = "numpy" }, - { name = "pandas" }, - { name = "polars", specifier = ">=1.36.1" }, - { name = "pyarrow" }, - { name = "requests" }, - { name = "scikit-learn" }, - { name = "seaborn" }, - { name = "tidypolars", specifier = ">=0.3.2" }, - { name = "xlrd" }, -] - -[[package]] -name = "anyio" -version = "4.12.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "idna" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/96/f0/5eb65b2bb0d09ac6776f2eb54adee6abe8228ea05b20a5ad0e4945de8aac/anyio-4.12.1.tar.gz", hash = "sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703", size = 228685, upload-time = "2026-01-06T11:45:21.246Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c", size = 113592, upload-time = "2026-01-06T11:45:19.497Z" }, -] - -[[package]] -name = "appnope" -version = "0.1.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/35/5d/752690df9ef5b76e169e68d6a129fa6d08a7100ca7f754c89495db3c6019/appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee", size = 4170, upload-time = "2024-02-06T09:43:11.258Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c", size = 4321, upload-time = "2024-02-06T09:43:09.663Z" }, -] - -[[package]] -name = "argon2-cffi" -version = "25.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "argon2-cffi-bindings" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/0e/89/ce5af8a7d472a67cc819d5d998aa8c82c5d860608c4db9f46f1162d7dab9/argon2_cffi-25.1.0.tar.gz", hash = "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1", size = 45706, upload-time = "2025-06-03T06:55:32.073Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl", hash = "sha256:fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741", size = 14657, upload-time = "2025-06-03T06:55:30.804Z" }, -] - -[[package]] -name = "argon2-cffi-bindings" -version = "25.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cffi" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/5c/2d/db8af0df73c1cf454f71b2bbe5e356b8c1f8041c979f505b3d3186e520a9/argon2_cffi_bindings-25.1.0.tar.gz", hash = "sha256:b957f3e6ea4d55d820e40ff76f450952807013d361a65d7f28acc0acbf29229d", size = 1783441, upload-time = "2025-07-30T10:02:05.147Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/60/97/3c0a35f46e52108d4707c44b95cfe2afcafc50800b5450c197454569b776/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:3d3f05610594151994ca9ccb3c771115bdb4daef161976a266f0dd8aa9996b8f", size = 54393, upload-time = "2025-07-30T10:01:40.97Z" }, - { url = "https://files.pythonhosted.org/packages/9d/f4/98bbd6ee89febd4f212696f13c03ca302b8552e7dbf9c8efa11ea4a388c3/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8b8efee945193e667a396cbc7b4fb7d357297d6234d30a489905d96caabde56b", size = 29328, upload-time = "2025-07-30T10:01:41.916Z" }, - { url = "https://files.pythonhosted.org/packages/43/24/90a01c0ef12ac91a6be05969f29944643bc1e5e461155ae6559befa8f00b/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3c6702abc36bf3ccba3f802b799505def420a1b7039862014a65db3205967f5a", size = 31269, upload-time = "2025-07-30T10:01:42.716Z" }, - { url = "https://files.pythonhosted.org/packages/d4/d3/942aa10782b2697eee7af5e12eeff5ebb325ccfb86dd8abda54174e377e4/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1c70058c6ab1e352304ac7e3b52554daadacd8d453c1752e547c76e9c99ac44", size = 86558, upload-time = "2025-07-30T10:01:43.943Z" }, - { url = "https://files.pythonhosted.org/packages/0d/82/b484f702fec5536e71836fc2dbc8c5267b3f6e78d2d539b4eaa6f0db8bf8/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e2fd3bfbff3c5d74fef31a722f729bf93500910db650c925c2d6ef879a7e51cb", size = 92364, upload-time = "2025-07-30T10:01:44.887Z" }, - { url = "https://files.pythonhosted.org/packages/c9/c1/a606ff83b3f1735f3759ad0f2cd9e038a0ad11a3de3b6c673aa41c24bb7b/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4f9665de60b1b0e99bcd6be4f17d90339698ce954cfd8d9cf4f91c995165a92", size = 85637, upload-time = "2025-07-30T10:01:46.225Z" }, - { url = "https://files.pythonhosted.org/packages/44/b4/678503f12aceb0262f84fa201f6027ed77d71c5019ae03b399b97caa2f19/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ba92837e4a9aa6a508c8d2d7883ed5a8f6c308c89a4790e1e447a220deb79a85", size = 91934, upload-time = "2025-07-30T10:01:47.203Z" }, - { url = "https://files.pythonhosted.org/packages/f0/c7/f36bd08ef9bd9f0a9cff9428406651f5937ce27b6c5b07b92d41f91ae541/argon2_cffi_bindings-25.1.0-cp314-cp314t-win32.whl", hash = "sha256:84a461d4d84ae1295871329b346a97f68eade8c53b6ed9a7ca2d7467f3c8ff6f", size = 28158, upload-time = "2025-07-30T10:01:48.341Z" }, - { url = "https://files.pythonhosted.org/packages/b3/80/0106a7448abb24a2c467bf7d527fe5413b7fdfa4ad6d6a96a43a62ef3988/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b55aec3565b65f56455eebc9b9f34130440404f27fe21c3b375bf1ea4d8fbae6", size = 32597, upload-time = "2025-07-30T10:01:49.112Z" }, - { url = "https://files.pythonhosted.org/packages/05/b8/d663c9caea07e9180b2cb662772865230715cbd573ba3b5e81793d580316/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:87c33a52407e4c41f3b70a9c2d3f6056d88b10dad7695be708c5021673f55623", size = 28231, upload-time = "2025-07-30T10:01:49.92Z" }, - { url = "https://files.pythonhosted.org/packages/1d/57/96b8b9f93166147826da5f90376e784a10582dd39a393c99bb62cfcf52f0/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:aecba1723ae35330a008418a91ea6cfcedf6d31e5fbaa056a166462ff066d500", size = 54121, upload-time = "2025-07-30T10:01:50.815Z" }, - { url = "https://files.pythonhosted.org/packages/0a/08/a9bebdb2e0e602dde230bdde8021b29f71f7841bd54801bcfd514acb5dcf/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2630b6240b495dfab90aebe159ff784d08ea999aa4b0d17efa734055a07d2f44", size = 29177, upload-time = "2025-07-30T10:01:51.681Z" }, - { url = "https://files.pythonhosted.org/packages/b6/02/d297943bcacf05e4f2a94ab6f462831dc20158614e5d067c35d4e63b9acb/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:7aef0c91e2c0fbca6fc68e7555aa60ef7008a739cbe045541e438373bc54d2b0", size = 31090, upload-time = "2025-07-30T10:01:53.184Z" }, - { url = "https://files.pythonhosted.org/packages/c1/93/44365f3d75053e53893ec6d733e4a5e3147502663554b4d864587c7828a7/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e021e87faa76ae0d413b619fe2b65ab9a037f24c60a1e6cc43457ae20de6dc6", size = 81246, upload-time = "2025-07-30T10:01:54.145Z" }, - { url = "https://files.pythonhosted.org/packages/09/52/94108adfdd6e2ddf58be64f959a0b9c7d4ef2fa71086c38356d22dc501ea/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e924cfc503018a714f94a49a149fdc0b644eaead5d1f089330399134fa028a", size = 87126, upload-time = "2025-07-30T10:01:55.074Z" }, - { url = "https://files.pythonhosted.org/packages/72/70/7a2993a12b0ffa2a9271259b79cc616e2389ed1a4d93842fac5a1f923ffd/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87b72589133f0346a1cb8d5ecca4b933e3c9b64656c9d175270a000e73b288d", size = 80343, upload-time = "2025-07-30T10:01:56.007Z" }, - { url = "https://files.pythonhosted.org/packages/78/9a/4e5157d893ffc712b74dbd868c7f62365618266982b64accab26bab01edc/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1db89609c06afa1a214a69a462ea741cf735b29a57530478c06eb81dd403de99", size = 86777, upload-time = "2025-07-30T10:01:56.943Z" }, - { url = "https://files.pythonhosted.org/packages/74/cd/15777dfde1c29d96de7f18edf4cc94c385646852e7c7b0320aa91ccca583/argon2_cffi_bindings-25.1.0-cp39-abi3-win32.whl", hash = "sha256:473bcb5f82924b1becbb637b63303ec8d10e84c8d241119419897a26116515d2", size = 27180, upload-time = "2025-07-30T10:01:57.759Z" }, - { url = "https://files.pythonhosted.org/packages/e2/c6/a759ece8f1829d1f162261226fbfd2c6832b3ff7657384045286d2afa384/argon2_cffi_bindings-25.1.0-cp39-abi3-win_amd64.whl", hash = "sha256:a98cd7d17e9f7ce244c0803cad3c23a7d379c301ba618a5fa76a67d116618b98", size = 31715, upload-time = "2025-07-30T10:01:58.56Z" }, - { url = "https://files.pythonhosted.org/packages/42/b9/f8d6fa329ab25128b7e98fd83a3cb34d9db5b059a9847eddb840a0af45dd/argon2_cffi_bindings-25.1.0-cp39-abi3-win_arm64.whl", hash = "sha256:b0fdbcf513833809c882823f98dc2f931cf659d9a1429616ac3adebb49f5db94", size = 27149, upload-time = "2025-07-30T10:01:59.329Z" }, -] - -[[package]] -name = "arrow" -version = "1.4.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "python-dateutil" }, - { name = "tzdata" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b9/33/032cdc44182491aa708d06a68b62434140d8c50820a087fac7af37703357/arrow-1.4.0.tar.gz", hash = "sha256:ed0cc050e98001b8779e84d461b0098c4ac597e88704a655582b21d116e526d7", size = 152931, upload-time = "2025-10-18T17:46:46.761Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl", hash = "sha256:749f0769958ebdc79c173ff0b0670d59051a535fa26e8eba02953dc19eb43205", size = 68797, upload-time = "2025-10-18T17:46:45.663Z" }, -] - -[[package]] -name = "asttokens" -version = "3.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/be/a5/8e3f9b6771b0b408517c82d97aed8f2036509bc247d46114925e32fe33f0/asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7", size = 62308, upload-time = "2025-11-15T16:43:48.578Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", size = 27047, upload-time = "2025-11-15T16:43:16.109Z" }, -] - -[[package]] -name = "async-lru" -version = "2.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ef/c3/bbf34f15ea88dfb649ab2c40f9d75081784a50573a9ea431563cab64adb8/async_lru-2.1.0.tar.gz", hash = "sha256:9eeb2fecd3fe42cc8a787fc32ead53a3a7158cc43d039c3c55ab3e4e5b2a80ed", size = 12041, upload-time = "2026-01-17T22:52:18.931Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2e/e9/eb6a5db5ac505d5d45715388e92bced7a5bb556facc4d0865d192823f2d2/async_lru-2.1.0-py3-none-any.whl", hash = "sha256:fa12dcf99a42ac1280bc16c634bbaf06883809790f6304d85cdab3f666f33a7e", size = 6933, upload-time = "2026-01-17T22:52:17.389Z" }, -] - -[[package]] -name = "attrs" -version = "25.4.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, -] - -[[package]] -name = "babel" -version = "2.17.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7d/6b/d52e42361e1aa00709585ecc30b3f9684b3ab62530771402248b1b1d6240/babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", size = 9951852, upload-time = "2025-02-01T15:17:41.026Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/b8/3fe70c75fe32afc4bb507f75563d39bc5642255d1d94f1f23604725780bf/babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2", size = 10182537, upload-time = "2025-02-01T15:17:37.39Z" }, -] - -[[package]] -name = "beautifulsoup4" -version = "4.14.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "soupsieve" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c3/b0/1c6a16426d389813b48d95e26898aff79abbde42ad353958ad95cc8c9b21/beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86", size = 627737, upload-time = "2025-11-30T15:08:26.084Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" }, -] - -[[package]] -name = "bleach" -version = "6.3.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "webencodings" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/07/18/3c8523962314be6bf4c8989c79ad9531c825210dd13a8669f6b84336e8bd/bleach-6.3.0.tar.gz", hash = "sha256:6f3b91b1c0a02bb9a78b5a454c92506aa0fdf197e1d5e114d2e00c6f64306d22", size = 203533, upload-time = "2025-10-27T17:57:39.211Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl", hash = "sha256:fe10ec77c93ddf3d13a73b035abaac7a9f5e436513864ccdad516693213c65d6", size = 164437, upload-time = "2025-10-27T17:57:37.538Z" }, -] - -[package.optional-dependencies] -css = [ - { name = "tinycss2" }, -] - -[[package]] -name = "certifi" -version = "2026.1.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e0/2d/a891ca51311197f6ad14a7ef42e2399f36cf2f9bd44752b3dc4eab60fdc5/certifi-2026.1.4.tar.gz", hash = "sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120", size = 154268, upload-time = "2026-01-04T02:42:41.825Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c", size = 152900, upload-time = "2026-01-04T02:42:40.15Z" }, -] - -[[package]] -name = "cffi" -version = "2.0.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pycparser", marker = "implementation_name != 'PyPy'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, - { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, - { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, - { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, - { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, - { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, - { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, - { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, - { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, - { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, - { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, - { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, - { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" }, - { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" }, - { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, - { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, - { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, - { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, - { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, - { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, - { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" }, - { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" }, - { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" }, - { url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" }, - { url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" }, - { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, - { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, - { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, - { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, - { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, - { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, - { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, - { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, - { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, -] - -[[package]] -name = "charset-normalizer" -version = "3.4.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, - { url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, - { url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, - { url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, - { url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, - { url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, - { url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, - { url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, - { url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, - { url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, - { url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, - { url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, - { url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, - { url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, - { url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, - { url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, - { url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" }, - { url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" }, - { url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" }, - { url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" }, - { url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" }, - { url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" }, - { url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" }, - { url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" }, - { url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" }, - { url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" }, - { url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" }, - { url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" }, - { url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" }, - { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" }, - { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" }, - { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" }, - { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, -] - -[[package]] -name = "colorama" -version = "0.4.6" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, -] - -[[package]] -name = "comm" -version = "0.2.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4c/13/7d740c5849255756bc17888787313b61fd38a0a8304fc4f073dfc46122aa/comm-0.2.3.tar.gz", hash = "sha256:2dc8048c10962d55d7ad693be1e7045d891b7ce8d999c97963a5e3e99c055971", size = 6319, upload-time = "2025-07-25T14:02:04.452Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl", hash = "sha256:c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417", size = 7294, upload-time = "2025-07-25T14:02:02.896Z" }, -] - -[[package]] -name = "contourpy" -version = "1.3.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "numpy" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/58/01/1253e6698a07380cd31a736d248a3f2a50a7c88779a1813da27503cadc2a/contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880", size = 13466174, upload-time = "2025-07-26T12:03:12.549Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/68/35/0167aad910bbdb9599272bd96d01a9ec6852f36b9455cf2ca67bd4cc2d23/contourpy-1.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:177fb367556747a686509d6fef71d221a4b198a3905fe824430e5ea0fda54eb5", size = 293257, upload-time = "2025-07-26T12:01:39.367Z" }, - { url = "https://files.pythonhosted.org/packages/96/e4/7adcd9c8362745b2210728f209bfbcf7d91ba868a2c5f40d8b58f54c509b/contourpy-1.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d002b6f00d73d69333dac9d0b8d5e84d9724ff9ef044fd63c5986e62b7c9e1b1", size = 274034, upload-time = "2025-07-26T12:01:40.645Z" }, - { url = "https://files.pythonhosted.org/packages/73/23/90e31ceeed1de63058a02cb04b12f2de4b40e3bef5e082a7c18d9c8ae281/contourpy-1.3.3-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:348ac1f5d4f1d66d3322420f01d42e43122f43616e0f194fc1c9f5d830c5b286", size = 334672, upload-time = "2025-07-26T12:01:41.942Z" }, - { url = "https://files.pythonhosted.org/packages/ed/93/b43d8acbe67392e659e1d984700e79eb67e2acb2bd7f62012b583a7f1b55/contourpy-1.3.3-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:655456777ff65c2c548b7c454af9c6f33f16c8884f11083244b5819cc214f1b5", size = 381234, upload-time = "2025-07-26T12:01:43.499Z" }, - { url = "https://files.pythonhosted.org/packages/46/3b/bec82a3ea06f66711520f75a40c8fc0b113b2a75edb36aa633eb11c4f50f/contourpy-1.3.3-cp313-cp313-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:644a6853d15b2512d67881586bd03f462c7ab755db95f16f14d7e238f2852c67", size = 385169, upload-time = "2025-07-26T12:01:45.219Z" }, - { url = "https://files.pythonhosted.org/packages/4b/32/e0f13a1c5b0f8572d0ec6ae2f6c677b7991fafd95da523159c19eff0696a/contourpy-1.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4debd64f124ca62069f313a9cb86656ff087786016d76927ae2cf37846b006c9", size = 362859, upload-time = "2025-07-26T12:01:46.519Z" }, - { url = "https://files.pythonhosted.org/packages/33/71/e2a7945b7de4e58af42d708a219f3b2f4cff7386e6b6ab0a0fa0033c49a9/contourpy-1.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a15459b0f4615b00bbd1e91f1b9e19b7e63aea7483d03d804186f278c0af2659", size = 1332062, upload-time = "2025-07-26T12:01:48.964Z" }, - { url = "https://files.pythonhosted.org/packages/12/fc/4e87ac754220ccc0e807284f88e943d6d43b43843614f0a8afa469801db0/contourpy-1.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca0fdcd73925568ca027e0b17ab07aad764be4706d0a925b89227e447d9737b7", size = 1403932, upload-time = "2025-07-26T12:01:51.979Z" }, - { url = "https://files.pythonhosted.org/packages/a6/2e/adc197a37443f934594112222ac1aa7dc9a98faf9c3842884df9a9d8751d/contourpy-1.3.3-cp313-cp313-win32.whl", hash = "sha256:b20c7c9a3bf701366556e1b1984ed2d0cedf999903c51311417cf5f591d8c78d", size = 185024, upload-time = "2025-07-26T12:01:53.245Z" }, - { url = "https://files.pythonhosted.org/packages/18/0b/0098c214843213759692cc638fce7de5c289200a830e5035d1791d7a2338/contourpy-1.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:1cadd8b8969f060ba45ed7c1b714fe69185812ab43bd6b86a9123fe8f99c3263", size = 226578, upload-time = "2025-07-26T12:01:54.422Z" }, - { url = "https://files.pythonhosted.org/packages/8a/9a/2f6024a0c5995243cd63afdeb3651c984f0d2bc727fd98066d40e141ad73/contourpy-1.3.3-cp313-cp313-win_arm64.whl", hash = "sha256:fd914713266421b7536de2bfa8181aa8c699432b6763a0ea64195ebe28bff6a9", size = 193524, upload-time = "2025-07-26T12:01:55.73Z" }, - { url = "https://files.pythonhosted.org/packages/c0/b3/f8a1a86bd3298513f500e5b1f5fd92b69896449f6cab6a146a5d52715479/contourpy-1.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:88df9880d507169449d434c293467418b9f6cbe82edd19284aa0409e7fdb933d", size = 306730, upload-time = "2025-07-26T12:01:57.051Z" }, - { url = "https://files.pythonhosted.org/packages/3f/11/4780db94ae62fc0c2053909b65dc3246bd7cecfc4f8a20d957ad43aa4ad8/contourpy-1.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d06bb1f751ba5d417047db62bca3c8fde202b8c11fb50742ab3ab962c81e8216", size = 287897, upload-time = "2025-07-26T12:01:58.663Z" }, - { url = "https://files.pythonhosted.org/packages/ae/15/e59f5f3ffdd6f3d4daa3e47114c53daabcb18574a26c21f03dc9e4e42ff0/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e4e6b05a45525357e382909a4c1600444e2a45b4795163d3b22669285591c1ae", size = 326751, upload-time = "2025-07-26T12:02:00.343Z" }, - { url = "https://files.pythonhosted.org/packages/0f/81/03b45cfad088e4770b1dcf72ea78d3802d04200009fb364d18a493857210/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab3074b48c4e2cf1a960e6bbeb7f04566bf36b1861d5c9d4d8ac04b82e38ba20", size = 375486, upload-time = "2025-07-26T12:02:02.128Z" }, - { url = "https://files.pythonhosted.org/packages/0c/ba/49923366492ffbdd4486e970d421b289a670ae8cf539c1ea9a09822b371a/contourpy-1.3.3-cp313-cp313t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:6c3d53c796f8647d6deb1abe867daeb66dcc8a97e8455efa729516b997b8ed99", size = 388106, upload-time = "2025-07-26T12:02:03.615Z" }, - { url = "https://files.pythonhosted.org/packages/9f/52/5b00ea89525f8f143651f9f03a0df371d3cbd2fccd21ca9b768c7a6500c2/contourpy-1.3.3-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:50ed930df7289ff2a8d7afeb9603f8289e5704755c7e5c3bbd929c90c817164b", size = 352548, upload-time = "2025-07-26T12:02:05.165Z" }, - { url = "https://files.pythonhosted.org/packages/32/1d/a209ec1a3a3452d490f6b14dd92e72280c99ae3d1e73da74f8277d4ee08f/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4feffb6537d64b84877da813a5c30f1422ea5739566abf0bd18065ac040e120a", size = 1322297, upload-time = "2025-07-26T12:02:07.379Z" }, - { url = "https://files.pythonhosted.org/packages/bc/9e/46f0e8ebdd884ca0e8877e46a3f4e633f6c9c8c4f3f6e72be3fe075994aa/contourpy-1.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2b7e9480ffe2b0cd2e787e4df64270e3a0440d9db8dc823312e2c940c167df7e", size = 1391023, upload-time = "2025-07-26T12:02:10.171Z" }, - { url = "https://files.pythonhosted.org/packages/b9/70/f308384a3ae9cd2209e0849f33c913f658d3326900d0ff5d378d6a1422d2/contourpy-1.3.3-cp313-cp313t-win32.whl", hash = "sha256:283edd842a01e3dcd435b1c5116798d661378d83d36d337b8dde1d16a5fc9ba3", size = 196157, upload-time = "2025-07-26T12:02:11.488Z" }, - { url = "https://files.pythonhosted.org/packages/b2/dd/880f890a6663b84d9e34a6f88cded89d78f0091e0045a284427cb6b18521/contourpy-1.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:87acf5963fc2b34825e5b6b048f40e3635dd547f590b04d2ab317c2619ef7ae8", size = 240570, upload-time = "2025-07-26T12:02:12.754Z" }, - { url = "https://files.pythonhosted.org/packages/80/99/2adc7d8ffead633234817ef8e9a87115c8a11927a94478f6bb3d3f4d4f7d/contourpy-1.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:3c30273eb2a55024ff31ba7d052dde990d7d8e5450f4bbb6e913558b3d6c2301", size = 199713, upload-time = "2025-07-26T12:02:14.4Z" }, - { url = "https://files.pythonhosted.org/packages/72/8b/4546f3ab60f78c514ffb7d01a0bd743f90de36f0019d1be84d0a708a580a/contourpy-1.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fde6c716d51c04b1c25d0b90364d0be954624a0ee9d60e23e850e8d48353d07a", size = 292189, upload-time = "2025-07-26T12:02:16.095Z" }, - { url = "https://files.pythonhosted.org/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77", size = 273251, upload-time = "2025-07-26T12:02:17.524Z" }, - { url = "https://files.pythonhosted.org/packages/b1/71/f93e1e9471d189f79d0ce2497007731c1e6bf9ef6d1d61b911430c3db4e5/contourpy-1.3.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22e9b1bd7a9b1d652cd77388465dc358dafcd2e217d35552424aa4f996f524f5", size = 335810, upload-time = "2025-07-26T12:02:18.9Z" }, - { url = "https://files.pythonhosted.org/packages/91/f9/e35f4c1c93f9275d4e38681a80506b5510e9327350c51f8d4a5a724d178c/contourpy-1.3.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a22738912262aa3e254e4f3cb079a95a67132fc5a063890e224393596902f5a4", size = 382871, upload-time = "2025-07-26T12:02:20.418Z" }, - { url = "https://files.pythonhosted.org/packages/b5/71/47b512f936f66a0a900d81c396a7e60d73419868fba959c61efed7a8ab46/contourpy-1.3.3-cp314-cp314-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:afe5a512f31ee6bd7d0dda52ec9864c984ca3d66664444f2d72e0dc4eb832e36", size = 386264, upload-time = "2025-07-26T12:02:21.916Z" }, - { url = "https://files.pythonhosted.org/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3", size = 363819, upload-time = "2025-07-26T12:02:23.759Z" }, - { url = "https://files.pythonhosted.org/packages/3e/a6/0b185d4cc480ee494945cde102cb0149ae830b5fa17bf855b95f2e70ad13/contourpy-1.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1fd43c3be4c8e5fd6e4f2baeae35ae18176cf2e5cced681cca908addf1cdd53b", size = 1333650, upload-time = "2025-07-26T12:02:26.181Z" }, - { url = "https://files.pythonhosted.org/packages/43/d7/afdc95580ca56f30fbcd3060250f66cedbde69b4547028863abd8aa3b47e/contourpy-1.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6afc576f7b33cf00996e5c1102dc2a8f7cc89e39c0b55df93a0b78c1bd992b36", size = 1404833, upload-time = "2025-07-26T12:02:28.782Z" }, - { url = "https://files.pythonhosted.org/packages/e2/e2/366af18a6d386f41132a48f033cbd2102e9b0cf6345d35ff0826cd984566/contourpy-1.3.3-cp314-cp314-win32.whl", hash = "sha256:66c8a43a4f7b8df8b71ee1840e4211a3c8d93b214b213f590e18a1beca458f7d", size = 189692, upload-time = "2025-07-26T12:02:30.128Z" }, - { url = "https://files.pythonhosted.org/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd", size = 232424, upload-time = "2025-07-26T12:02:31.395Z" }, - { url = "https://files.pythonhosted.org/packages/18/79/a9416650df9b525737ab521aa181ccc42d56016d2123ddcb7b58e926a42c/contourpy-1.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:95b181891b4c71de4bb404c6621e7e2390745f887f2a026b2d99e92c17892339", size = 198300, upload-time = "2025-07-26T12:02:32.956Z" }, - { url = "https://files.pythonhosted.org/packages/1f/42/38c159a7d0f2b7b9c04c64ab317042bb6952b713ba875c1681529a2932fe/contourpy-1.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:33c82d0138c0a062380332c861387650c82e4cf1747aaa6938b9b6516762e772", size = 306769, upload-time = "2025-07-26T12:02:34.2Z" }, - { url = "https://files.pythonhosted.org/packages/c3/6c/26a8205f24bca10974e77460de68d3d7c63e282e23782f1239f226fcae6f/contourpy-1.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ea37e7b45949df430fe649e5de8351c423430046a2af20b1c1961cae3afcda77", size = 287892, upload-time = "2025-07-26T12:02:35.807Z" }, - { url = "https://files.pythonhosted.org/packages/66/06/8a475c8ab718ebfd7925661747dbb3c3ee9c82ac834ccb3570be49d129f4/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d304906ecc71672e9c89e87c4675dc5c2645e1f4269a5063b99b0bb29f232d13", size = 326748, upload-time = "2025-07-26T12:02:37.193Z" }, - { url = "https://files.pythonhosted.org/packages/b4/a3/c5ca9f010a44c223f098fccd8b158bb1cb287378a31ac141f04730dc49be/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca658cd1a680a5c9ea96dc61cdbae1e85c8f25849843aa799dfd3cb370ad4fbe", size = 375554, upload-time = "2025-07-26T12:02:38.894Z" }, - { url = "https://files.pythonhosted.org/packages/80/5b/68bd33ae63fac658a4145088c1e894405e07584a316738710b636c6d0333/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ab2fd90904c503739a75b7c8c5c01160130ba67944a7b77bbf36ef8054576e7f", size = 388118, upload-time = "2025-07-26T12:02:40.642Z" }, - { url = "https://files.pythonhosted.org/packages/40/52/4c285a6435940ae25d7410a6c36bda5145839bc3f0beb20c707cda18b9d2/contourpy-1.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7301b89040075c30e5768810bc96a8e8d78085b47d8be6e4c3f5a0b4ed478a0", size = 352555, upload-time = "2025-07-26T12:02:42.25Z" }, - { url = "https://files.pythonhosted.org/packages/24/ee/3e81e1dd174f5c7fefe50e85d0892de05ca4e26ef1c9a59c2a57e43b865a/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2a2a8b627d5cc6b7c41a4beff6c5ad5eb848c88255fda4a8745f7e901b32d8e4", size = 1322295, upload-time = "2025-07-26T12:02:44.668Z" }, - { url = "https://files.pythonhosted.org/packages/3c/b2/6d913d4d04e14379de429057cd169e5e00f6c2af3bb13e1710bcbdb5da12/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fd6ec6be509c787f1caf6b247f0b1ca598bef13f4ddeaa126b7658215529ba0f", size = 1391027, upload-time = "2025-07-26T12:02:47.09Z" }, - { url = "https://files.pythonhosted.org/packages/93/8a/68a4ec5c55a2971213d29a9374913f7e9f18581945a7a31d1a39b5d2dfe5/contourpy-1.3.3-cp314-cp314t-win32.whl", hash = "sha256:e74a9a0f5e3fff48fb5a7f2fd2b9b70a3fe014a67522f79b7cca4c0c7e43c9ae", size = 202428, upload-time = "2025-07-26T12:02:48.691Z" }, - { url = "https://files.pythonhosted.org/packages/fa/96/fd9f641ffedc4fa3ace923af73b9d07e869496c9cc7a459103e6e978992f/contourpy-1.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:13b68d6a62db8eafaebb8039218921399baf6e47bf85006fd8529f2a08ef33fc", size = 250331, upload-time = "2025-07-26T12:02:50.137Z" }, - { url = "https://files.pythonhosted.org/packages/ae/8c/469afb6465b853afff216f9528ffda78a915ff880ed58813ba4faf4ba0b6/contourpy-1.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b7448cb5a725bb1e35ce88771b86fba35ef418952474492cf7c764059933ff8b", size = 203831, upload-time = "2025-07-26T12:02:51.449Z" }, -] - -[[package]] -name = "cycler" -version = "0.12.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615, upload-time = "2023-10-07T05:32:18.335Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" }, -] - -[[package]] -name = "debugpy" -version = "1.8.19" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/73/75/9e12d4d42349b817cd545b89247696c67917aab907012ae5b64bbfea3199/debugpy-1.8.19.tar.gz", hash = "sha256:eea7e5987445ab0b5ed258093722d5ecb8bb72217c5c9b1e21f64efe23ddebdb", size = 1644590, upload-time = "2025-12-15T21:53:28.044Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/71/3d/388035a31a59c26f1ecc8d86af607d0c42e20ef80074147cd07b180c4349/debugpy-1.8.19-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:91e35db2672a0abaf325f4868fcac9c1674a0d9ad9bb8a8c849c03a5ebba3e6d", size = 2538859, upload-time = "2025-12-15T21:53:50.478Z" }, - { url = "https://files.pythonhosted.org/packages/4a/19/c93a0772d0962294f083dbdb113af1a7427bb632d36e5314297068f55db7/debugpy-1.8.19-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:85016a73ab84dea1c1f1dcd88ec692993bcbe4532d1b49ecb5f3c688ae50c606", size = 4292575, upload-time = "2025-12-15T21:53:51.821Z" }, - { url = "https://files.pythonhosted.org/packages/5c/56/09e48ab796b0a77e3d7dc250f95251832b8bf6838c9632f6100c98bdf426/debugpy-1.8.19-cp313-cp313-win32.whl", hash = "sha256:b605f17e89ba0ecee994391194285fada89cee111cfcd29d6f2ee11cbdc40976", size = 5286209, upload-time = "2025-12-15T21:53:53.602Z" }, - { url = "https://files.pythonhosted.org/packages/fb/4e/931480b9552c7d0feebe40c73725dd7703dcc578ba9efc14fe0e6d31cfd1/debugpy-1.8.19-cp313-cp313-win_amd64.whl", hash = "sha256:c30639998a9f9cd9699b4b621942c0179a6527f083c72351f95c6ab1728d5b73", size = 5328206, upload-time = "2025-12-15T21:53:55.433Z" }, - { url = "https://files.pythonhosted.org/packages/f6/b9/cbec520c3a00508327476c7fce26fbafef98f412707e511eb9d19a2ef467/debugpy-1.8.19-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:1e8c4d1bd230067bf1bbcdbd6032e5a57068638eb28b9153d008ecde288152af", size = 2537372, upload-time = "2025-12-15T21:53:57.318Z" }, - { url = "https://files.pythonhosted.org/packages/88/5e/cf4e4dc712a141e10d58405c58c8268554aec3c35c09cdcda7535ff13f76/debugpy-1.8.19-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:d40c016c1f538dbf1762936e3aeb43a89b965069d9f60f9e39d35d9d25e6b809", size = 4268729, upload-time = "2025-12-15T21:53:58.712Z" }, - { url = "https://files.pythonhosted.org/packages/82/a3/c91a087ab21f1047db328c1d3eb5d1ff0e52de9e74f9f6f6fa14cdd93d58/debugpy-1.8.19-cp314-cp314-win32.whl", hash = "sha256:0601708223fe1cd0e27c6cce67a899d92c7d68e73690211e6788a4b0e1903f5b", size = 5286388, upload-time = "2025-12-15T21:54:00.687Z" }, - { url = "https://files.pythonhosted.org/packages/17/b8/bfdc30b6e94f1eff09f2dc9cc1f9cd1c6cde3d996bcbd36ce2d9a4956e99/debugpy-1.8.19-cp314-cp314-win_amd64.whl", hash = "sha256:8e19a725f5d486f20e53a1dde2ab8bb2c9607c40c00a42ab646def962b41125f", size = 5327741, upload-time = "2025-12-15T21:54:02.148Z" }, - { url = "https://files.pythonhosted.org/packages/25/3e/e27078370414ef35fafad2c06d182110073daaeb5d3bf734b0b1eeefe452/debugpy-1.8.19-py2.py3-none-any.whl", hash = "sha256:360ffd231a780abbc414ba0f005dad409e71c78637efe8f2bd75837132a41d38", size = 5292321, upload-time = "2025-12-15T21:54:16.024Z" }, -] - -[[package]] -name = "decorator" -version = "5.2.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", size = 56711, upload-time = "2025-02-24T04:41:34.073Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190, upload-time = "2025-02-24T04:41:32.565Z" }, -] - -[[package]] -name = "defusedxml" -version = "0.7.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520, upload-time = "2021-03-08T10:59:26.269Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" }, -] - -[[package]] -name = "executing" -version = "2.2.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, -] - -[[package]] -name = "fastjsonschema" -version = "2.21.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/20/b5/23b216d9d985a956623b6bd12d4086b60f0059b27799f23016af04a74ea1/fastjsonschema-2.21.2.tar.gz", hash = "sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de", size = 374130, upload-time = "2025-08-14T18:49:36.666Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl", hash = "sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463", size = 24024, upload-time = "2025-08-14T18:49:34.776Z" }, -] - -[[package]] -name = "fonttools" -version = "4.61.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ec/ca/cf17b88a8df95691275a3d77dc0a5ad9907f328ae53acbe6795da1b2f5ed/fonttools-4.61.1.tar.gz", hash = "sha256:6675329885c44657f826ef01d9e4fb33b9158e9d93c537d84ad8399539bc6f69", size = 3565756, upload-time = "2025-12-12T17:31:24.246Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4b/cf/00ba28b0990982530addb8dc3e9e6f2fa9cb5c20df2abdda7baa755e8fe1/fonttools-4.61.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8c56c488ab471628ff3bfa80964372fc13504ece601e0d97a78ee74126b2045c", size = 2846454, upload-time = "2025-12-12T17:30:24.938Z" }, - { url = "https://files.pythonhosted.org/packages/5a/ca/468c9a8446a2103ae645d14fee3f610567b7042aba85031c1c65e3ef7471/fonttools-4.61.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dc492779501fa723b04d0ab1f5be046797fee17d27700476edc7ee9ae535a61e", size = 2398191, upload-time = "2025-12-12T17:30:27.343Z" }, - { url = "https://files.pythonhosted.org/packages/a3/4b/d67eedaed19def5967fade3297fed8161b25ba94699efc124b14fb68cdbc/fonttools-4.61.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:64102ca87e84261419c3747a0d20f396eb024bdbeb04c2bfb37e2891f5fadcb5", size = 4928410, upload-time = "2025-12-12T17:30:29.771Z" }, - { url = "https://files.pythonhosted.org/packages/b0/8d/6fb3494dfe61a46258cd93d979cf4725ded4eb46c2a4ca35e4490d84daea/fonttools-4.61.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c1b526c8d3f615a7b1867f38a9410849c8f4aef078535742198e942fba0e9bd", size = 4984460, upload-time = "2025-12-12T17:30:32.073Z" }, - { url = "https://files.pythonhosted.org/packages/f7/f1/a47f1d30b3dc00d75e7af762652d4cbc3dff5c2697a0dbd5203c81afd9c3/fonttools-4.61.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:41ed4b5ec103bd306bb68f81dc166e77409e5209443e5773cb4ed837bcc9b0d3", size = 4925800, upload-time = "2025-12-12T17:30:34.339Z" }, - { url = "https://files.pythonhosted.org/packages/a7/01/e6ae64a0981076e8a66906fab01539799546181e32a37a0257b77e4aa88b/fonttools-4.61.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b501c862d4901792adaec7c25b1ecc749e2662543f68bb194c42ba18d6eec98d", size = 5067859, upload-time = "2025-12-12T17:30:36.593Z" }, - { url = "https://files.pythonhosted.org/packages/73/aa/28e40b8d6809a9b5075350a86779163f074d2b617c15d22343fce81918db/fonttools-4.61.1-cp313-cp313-win32.whl", hash = "sha256:4d7092bb38c53bbc78e9255a59158b150bcdc115a1e3b3ce0b5f267dc35dd63c", size = 2267821, upload-time = "2025-12-12T17:30:38.478Z" }, - { url = "https://files.pythonhosted.org/packages/1a/59/453c06d1d83dc0951b69ef692d6b9f1846680342927df54e9a1ca91c6f90/fonttools-4.61.1-cp313-cp313-win_amd64.whl", hash = "sha256:21e7c8d76f62ab13c9472ccf74515ca5b9a761d1bde3265152a6dc58700d895b", size = 2318169, upload-time = "2025-12-12T17:30:40.951Z" }, - { url = "https://files.pythonhosted.org/packages/32/8f/4e7bf82c0cbb738d3c2206c920ca34ca74ef9dabde779030145d28665104/fonttools-4.61.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fff4f534200a04b4a36e7ae3cb74493afe807b517a09e99cb4faa89a34ed6ecd", size = 2846094, upload-time = "2025-12-12T17:30:43.511Z" }, - { url = "https://files.pythonhosted.org/packages/71/09/d44e45d0a4f3a651f23a1e9d42de43bc643cce2971b19e784cc67d823676/fonttools-4.61.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d9203500f7c63545b4ce3799319fe4d9feb1a1b89b28d3cb5abd11b9dd64147e", size = 2396589, upload-time = "2025-12-12T17:30:45.681Z" }, - { url = "https://files.pythonhosted.org/packages/89/18/58c64cafcf8eb677a99ef593121f719e6dcbdb7d1c594ae5a10d4997ca8a/fonttools-4.61.1-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fa646ecec9528bef693415c79a86e733c70a4965dd938e9a226b0fc64c9d2e6c", size = 4877892, upload-time = "2025-12-12T17:30:47.709Z" }, - { url = "https://files.pythonhosted.org/packages/8a/ec/9e6b38c7ba1e09eb51db849d5450f4c05b7e78481f662c3b79dbde6f3d04/fonttools-4.61.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11f35ad7805edba3aac1a3710d104592df59f4b957e30108ae0ba6c10b11dd75", size = 4972884, upload-time = "2025-12-12T17:30:49.656Z" }, - { url = "https://files.pythonhosted.org/packages/5e/87/b5339da8e0256734ba0dbbf5b6cdebb1dd79b01dc8c270989b7bcd465541/fonttools-4.61.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b931ae8f62db78861b0ff1ac017851764602288575d65b8e8ff1963fed419063", size = 4924405, upload-time = "2025-12-12T17:30:51.735Z" }, - { url = "https://files.pythonhosted.org/packages/0b/47/e3409f1e1e69c073a3a6fd8cb886eb18c0bae0ee13db2c8d5e7f8495e8b7/fonttools-4.61.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b148b56f5de675ee16d45e769e69f87623a4944f7443850bf9a9376e628a89d2", size = 5035553, upload-time = "2025-12-12T17:30:54.823Z" }, - { url = "https://files.pythonhosted.org/packages/bf/b6/1f6600161b1073a984294c6c031e1a56ebf95b6164249eecf30012bb2e38/fonttools-4.61.1-cp314-cp314-win32.whl", hash = "sha256:9b666a475a65f4e839d3d10473fad6d47e0a9db14a2f4a224029c5bfde58ad2c", size = 2271915, upload-time = "2025-12-12T17:30:57.913Z" }, - { url = "https://files.pythonhosted.org/packages/52/7b/91e7b01e37cc8eb0e1f770d08305b3655e4f002fc160fb82b3390eabacf5/fonttools-4.61.1-cp314-cp314-win_amd64.whl", hash = "sha256:4f5686e1fe5fce75d82d93c47a438a25bf0d1319d2843a926f741140b2b16e0c", size = 2323487, upload-time = "2025-12-12T17:30:59.804Z" }, - { url = "https://files.pythonhosted.org/packages/39/5c/908ad78e46c61c3e3ed70c3b58ff82ab48437faf84ec84f109592cabbd9f/fonttools-4.61.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:e76ce097e3c57c4bcb67c5aa24a0ecdbd9f74ea9219997a707a4061fbe2707aa", size = 2929571, upload-time = "2025-12-12T17:31:02.574Z" }, - { url = "https://files.pythonhosted.org/packages/bd/41/975804132c6dea64cdbfbaa59f3518a21c137a10cccf962805b301ac6ab2/fonttools-4.61.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9cfef3ab326780c04d6646f68d4b4742aae222e8b8ea1d627c74e38afcbc9d91", size = 2435317, upload-time = "2025-12-12T17:31:04.974Z" }, - { url = "https://files.pythonhosted.org/packages/b0/5a/aef2a0a8daf1ebaae4cfd83f84186d4a72ee08fd6a8451289fcd03ffa8a4/fonttools-4.61.1-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a75c301f96db737e1c5ed5fd7d77d9c34466de16095a266509e13da09751bd19", size = 4882124, upload-time = "2025-12-12T17:31:07.456Z" }, - { url = "https://files.pythonhosted.org/packages/80/33/d6db3485b645b81cea538c9d1c9219d5805f0877fda18777add4671c5240/fonttools-4.61.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:91669ccac46bbc1d09e9273546181919064e8df73488ea087dcac3e2968df9ba", size = 5100391, upload-time = "2025-12-12T17:31:09.732Z" }, - { url = "https://files.pythonhosted.org/packages/6c/d6/675ba631454043c75fcf76f0ca5463eac8eb0666ea1d7badae5fea001155/fonttools-4.61.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c33ab3ca9d3ccd581d58e989d67554e42d8d4ded94ab3ade3508455fe70e65f7", size = 4978800, upload-time = "2025-12-12T17:31:11.681Z" }, - { url = "https://files.pythonhosted.org/packages/7f/33/d3ec753d547a8d2bdaedd390d4a814e8d5b45a093d558f025c6b990b554c/fonttools-4.61.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:664c5a68ec406f6b1547946683008576ef8b38275608e1cee6c061828171c118", size = 5006426, upload-time = "2025-12-12T17:31:13.764Z" }, - { url = "https://files.pythonhosted.org/packages/b4/40/cc11f378b561a67bea850ab50063366a0d1dd3f6d0a30ce0f874b0ad5664/fonttools-4.61.1-cp314-cp314t-win32.whl", hash = "sha256:aed04cabe26f30c1647ef0e8fbb207516fd40fe9472e9439695f5c6998e60ac5", size = 2335377, upload-time = "2025-12-12T17:31:16.49Z" }, - { url = "https://files.pythonhosted.org/packages/e4/ff/c9a2b66b39f8628531ea58b320d66d951267c98c6a38684daa8f50fb02f8/fonttools-4.61.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2180f14c141d2f0f3da43f3a81bc8aa4684860f6b0e6f9e165a4831f24e6a23b", size = 2400613, upload-time = "2025-12-12T17:31:18.769Z" }, - { url = "https://files.pythonhosted.org/packages/c7/4e/ce75a57ff3aebf6fc1f4e9d508b8e5810618a33d900ad6c19eb30b290b97/fonttools-4.61.1-py3-none-any.whl", hash = "sha256:17d2bf5d541add43822bcf0c43d7d847b160c9bb01d15d5007d84e2217aaa371", size = 1148996, upload-time = "2025-12-12T17:31:21.03Z" }, -] - -[[package]] -name = "fqdn" -version = "1.5.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/30/3e/a80a8c077fd798951169626cde3e239adeba7dab75deb3555716415bd9b0/fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f", size = 6015, upload-time = "2021-03-11T07:16:29.08Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014", size = 9121, upload-time = "2021-03-11T07:16:28.351Z" }, -] - -[[package]] -name = "geopandas" -version = "1.1.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "numpy" }, - { name = "packaging" }, - { name = "pandas" }, - { name = "pyogrio" }, - { name = "pyproj" }, - { name = "shapely" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/8d/24/5eb5685d7bf89d64218919379f882d19a60f8219d66d833c83b1cf264c95/geopandas-1.1.2.tar.gz", hash = "sha256:33f7b33565c46a45b8459a2ab699ec943fdbb5716e58e251b3c413cf7783106c", size = 336037, upload-time = "2025-12-22T21:06:13.749Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/54/e4/fac19dc34cb686c96011388b813ff7b858a70681e5ce6ce7698e5021b0f4/geopandas-1.1.2-py3-none-any.whl", hash = "sha256:2bb0b1052cb47378addb4ba54c47f8d4642dcbda9b61375638274f49d9f0bb0d", size = 341734, upload-time = "2025-12-22T21:06:12.498Z" }, -] - -[[package]] -name = "h11" -version = "0.16.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, -] - -[[package]] -name = "httpcore" -version = "1.0.9" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "certifi" }, - { name = "h11" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, -] - -[[package]] -name = "httpx" -version = "0.28.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "anyio" }, - { name = "certifi" }, - { name = "httpcore" }, - { name = "idna" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, -] - -[[package]] -name = "idna" -version = "3.11" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, -] - -[[package]] -name = "ipykernel" -version = "7.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "appnope", marker = "sys_platform == 'darwin'" }, - { name = "comm" }, - { name = "debugpy" }, - { name = "ipython" }, - { name = "jupyter-client" }, - { name = "jupyter-core" }, - { name = "matplotlib-inline" }, - { name = "nest-asyncio" }, - { name = "packaging" }, - { name = "psutil" }, - { name = "pyzmq" }, - { name = "tornado" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b9/a4/4948be6eb88628505b83a1f2f40d90254cab66abf2043b3c40fa07dfce0f/ipykernel-7.1.0.tar.gz", hash = "sha256:58a3fc88533d5930c3546dc7eac66c6d288acde4f801e2001e65edc5dc9cf0db", size = 174579, upload-time = "2025-10-27T09:46:39.471Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a3/17/20c2552266728ceba271967b87919664ecc0e33efca29c3efc6baf88c5f9/ipykernel-7.1.0-py3-none-any.whl", hash = "sha256:763b5ec6c5b7776f6a8d7ce09b267693b4e5ce75cb50ae696aaefb3c85e1ea4c", size = 117968, upload-time = "2025-10-27T09:46:37.805Z" }, -] - -[[package]] -name = "ipython" -version = "9.9.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "decorator" }, - { name = "ipython-pygments-lexers" }, - { name = "jedi" }, - { name = "matplotlib-inline" }, - { name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, - { name = "prompt-toolkit" }, - { name = "pygments" }, - { name = "stack-data" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/46/dd/fb08d22ec0c27e73c8bc8f71810709870d51cadaf27b7ddd3f011236c100/ipython-9.9.0.tar.gz", hash = "sha256:48fbed1b2de5e2c7177eefa144aba7fcb82dac514f09b57e2ac9da34ddb54220", size = 4425043, upload-time = "2026-01-05T12:36:46.233Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/86/92/162cfaee4ccf370465c5af1ce36a9eacec1becb552f2033bb3584e6f640a/ipython-9.9.0-py3-none-any.whl", hash = "sha256:b457fe9165df2b84e8ec909a97abcf2ed88f565970efba16b1f7229c283d252b", size = 621431, upload-time = "2026-01-05T12:36:44.669Z" }, -] - -[[package]] -name = "ipython-pygments-lexers" -version = "1.1.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pygments" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393, upload-time = "2025-01-17T11:24:34.505Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" }, -] - -[[package]] -name = "ipywidgets" -version = "8.1.8" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "comm" }, - { name = "ipython" }, - { name = "jupyterlab-widgets" }, - { name = "traitlets" }, - { name = "widgetsnbextension" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/4c/ae/c5ce1edc1afe042eadb445e95b0671b03cee61895264357956e61c0d2ac0/ipywidgets-8.1.8.tar.gz", hash = "sha256:61f969306b95f85fba6b6986b7fe45d73124d1d9e3023a8068710d47a22ea668", size = 116739, upload-time = "2025-11-01T21:18:12.393Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl", hash = "sha256:ecaca67aed704a338f88f67b1181b58f821ab5dc89c1f0f5ef99db43c1c2921e", size = 139808, upload-time = "2025-11-01T21:18:10.956Z" }, -] - -[[package]] -name = "isoduration" -version = "20.11.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "arrow" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/7c/1a/3c8edc664e06e6bd06cce40c6b22da5f1429aa4224d0c590f3be21c91ead/isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9", size = 11649, upload-time = "2020-11-01T11:00:00.312Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042", size = 11321, upload-time = "2020-11-01T10:59:58.02Z" }, -] - -[[package]] -name = "jedi" -version = "0.19.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "parso" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/72/3a/79a912fbd4d8dd6fbb02bf69afd3bb72cf0c729bb3063c6f4498603db17a/jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0", size = 1231287, upload-time = "2024-11-11T01:41:42.873Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9", size = 1572278, upload-time = "2024-11-11T01:41:40.175Z" }, -] - -[[package]] -name = "jinja2" -version = "3.1.6" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "markupsafe" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, -] - -[[package]] -name = "joblib" -version = "1.5.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/41/f2/d34e8b3a08a9cc79a50b2208a93dce981fe615b64d5a4d4abee421d898df/joblib-1.5.3.tar.gz", hash = "sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3", size = 331603, upload-time = "2025-12-15T08:41:46.427Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713", size = 309071, upload-time = "2025-12-15T08:41:44.973Z" }, -] - -[[package]] -name = "json5" -version = "0.13.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/77/e8/a3f261a66e4663f22700bc8a17c08cb83e91fbf086726e7a228398968981/json5-0.13.0.tar.gz", hash = "sha256:b1edf8d487721c0bf64d83c28e91280781f6e21f4a797d3261c7c828d4c165bf", size = 52441, upload-time = "2026-01-01T19:42:14.99Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d7/9e/038522f50ceb7e74f1f991bf1b699f24b0c2bbe7c390dd36ad69f4582258/json5-0.13.0-py3-none-any.whl", hash = "sha256:9a08e1dd65f6a4d4c6fa82d216cf2477349ec2346a38fd70cc11d2557499fbcc", size = 36163, upload-time = "2026-01-01T19:42:13.962Z" }, -] - -[[package]] -name = "jsonpointer" -version = "3.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6a/0a/eebeb1fa92507ea94016a2a790b93c2ae41a7e18778f85471dc54475ed25/jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef", size = 9114, upload-time = "2024-06-10T19:24:42.462Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942", size = 7595, upload-time = "2024-06-10T19:24:40.698Z" }, -] - -[[package]] -name = "jsonschema" -version = "4.26.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "attrs" }, - { name = "jsonschema-specifications" }, - { name = "referencing" }, - { name = "rpds-py" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" }, -] - -[package.optional-dependencies] -format-nongpl = [ - { name = "fqdn" }, - { name = "idna" }, - { name = "isoduration" }, - { name = "jsonpointer" }, - { name = "rfc3339-validator" }, - { name = "rfc3986-validator" }, - { name = "rfc3987-syntax" }, - { name = "uri-template" }, - { name = "webcolors" }, -] - -[[package]] -name = "jsonschema-specifications" -version = "2025.9.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "referencing" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, -] - -[[package]] -name = "jupyter" -version = "1.1.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "ipykernel" }, - { name = "ipywidgets" }, - { name = "jupyter-console" }, - { name = "jupyterlab" }, - { name = "nbconvert" }, - { name = "notebook" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/58/f3/af28ea964ab8bc1e472dba2e82627d36d470c51f5cd38c37502eeffaa25e/jupyter-1.1.1.tar.gz", hash = "sha256:d55467bceabdea49d7e3624af7e33d59c37fff53ed3a350e1ac957bed731de7a", size = 5714959, upload-time = "2024-08-30T07:15:48.299Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/38/64/285f20a31679bf547b75602702f7800e74dbabae36ef324f716c02804753/jupyter-1.1.1-py2.py3-none-any.whl", hash = "sha256:7a59533c22af65439b24bbe60373a4e95af8f16ac65a6c00820ad378e3f7cc83", size = 2657, upload-time = "2024-08-30T07:15:47.045Z" }, -] - -[[package]] -name = "jupyter-client" -version = "8.8.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jupyter-core" }, - { name = "python-dateutil" }, - { name = "pyzmq" }, - { name = "tornado" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/05/e4/ba649102a3bc3fbca54e7239fb924fd434c766f855693d86de0b1f2bec81/jupyter_client-8.8.0.tar.gz", hash = "sha256:d556811419a4f2d96c869af34e854e3f059b7cc2d6d01a9cd9c85c267691be3e", size = 348020, upload-time = "2026-01-08T13:55:47.938Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl", hash = "sha256:f93a5b99c5e23a507b773d3a1136bd6e16c67883ccdbd9a829b0bbdb98cd7d7a", size = 107371, upload-time = "2026-01-08T13:55:45.562Z" }, -] - -[[package]] -name = "jupyter-console" -version = "6.6.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "ipykernel" }, - { name = "ipython" }, - { name = "jupyter-client" }, - { name = "jupyter-core" }, - { name = "prompt-toolkit" }, - { name = "pygments" }, - { name = "pyzmq" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/bd/2d/e2fd31e2fc41c14e2bcb6c976ab732597e907523f6b2420305f9fc7fdbdb/jupyter_console-6.6.3.tar.gz", hash = "sha256:566a4bf31c87adbfadf22cdf846e3069b59a71ed5da71d6ba4d8aaad14a53539", size = 34363, upload-time = "2023-03-06T14:13:31.02Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ca/77/71d78d58f15c22db16328a476426f7ac4a60d3a5a7ba3b9627ee2f7903d4/jupyter_console-6.6.3-py3-none-any.whl", hash = "sha256:309d33409fcc92ffdad25f0bcdf9a4a9daa61b6f341177570fdac03de5352485", size = 24510, upload-time = "2023-03-06T14:13:28.229Z" }, -] - -[[package]] -name = "jupyter-core" -version = "5.9.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "platformdirs" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/02/49/9d1284d0dc65e2c757b74c6687b6d319b02f822ad039e5c512df9194d9dd/jupyter_core-5.9.1.tar.gz", hash = "sha256:4d09aaff303b9566c3ce657f580bd089ff5c91f5f89cf7d8846c3cdf465b5508", size = 89814, upload-time = "2025-10-16T19:19:18.444Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl", hash = "sha256:ebf87fdc6073d142e114c72c9e29a9d7ca03fad818c5d300ce2adc1fb0743407", size = 29032, upload-time = "2025-10-16T19:19:16.783Z" }, -] - -[[package]] -name = "jupyter-events" -version = "0.12.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jsonschema", extra = ["format-nongpl"] }, - { name = "packaging" }, - { name = "python-json-logger" }, - { name = "pyyaml" }, - { name = "referencing" }, - { name = "rfc3339-validator" }, - { name = "rfc3986-validator" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/9d/c3/306d090461e4cf3cd91eceaff84bede12a8e52cd821c2d20c9a4fd728385/jupyter_events-0.12.0.tar.gz", hash = "sha256:fc3fce98865f6784c9cd0a56a20644fc6098f21c8c33834a8d9fe383c17e554b", size = 62196, upload-time = "2025-02-03T17:23:41.485Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e2/48/577993f1f99c552f18a0428731a755e06171f9902fa118c379eb7c04ea22/jupyter_events-0.12.0-py3-none-any.whl", hash = "sha256:6464b2fa5ad10451c3d35fabc75eab39556ae1e2853ad0c0cc31b656731a97fb", size = 19430, upload-time = "2025-02-03T17:23:38.643Z" }, -] - -[[package]] -name = "jupyter-lsp" -version = "2.3.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jupyter-server" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/eb/5a/9066c9f8e94ee517133cd98dba393459a16cd48bba71a82f16a65415206c/jupyter_lsp-2.3.0.tar.gz", hash = "sha256:458aa59339dc868fb784d73364f17dbce8836e906cd75fd471a325cba02e0245", size = 54823, upload-time = "2025-08-27T17:47:34.671Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1a/60/1f6cee0c46263de1173894f0fafcb3475ded276c472c14d25e0280c18d6d/jupyter_lsp-2.3.0-py3-none-any.whl", hash = "sha256:e914a3cb2addf48b1c7710914771aaf1819d46b2e5a79b0f917b5478ec93f34f", size = 76687, upload-time = "2025-08-27T17:47:33.15Z" }, -] - -[[package]] -name = "jupyter-server" -version = "2.17.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "anyio" }, - { name = "argon2-cffi" }, - { name = "jinja2" }, - { name = "jupyter-client" }, - { name = "jupyter-core" }, - { name = "jupyter-events" }, - { name = "jupyter-server-terminals" }, - { name = "nbconvert" }, - { name = "nbformat" }, - { name = "packaging" }, - { name = "prometheus-client" }, - { name = "pywinpty", marker = "os_name == 'nt'" }, - { name = "pyzmq" }, - { name = "send2trash" }, - { name = "terminado" }, - { name = "tornado" }, - { name = "traitlets" }, - { name = "websocket-client" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/5b/ac/e040ec363d7b6b1f11304cc9f209dac4517ece5d5e01821366b924a64a50/jupyter_server-2.17.0.tar.gz", hash = "sha256:c38ea898566964c888b4772ae1ed58eca84592e88251d2cfc4d171f81f7e99d5", size = 731949, upload-time = "2025-08-21T14:42:54.042Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/92/80/a24767e6ca280f5a49525d987bf3e4d7552bf67c8be07e8ccf20271f8568/jupyter_server-2.17.0-py3-none-any.whl", hash = "sha256:e8cb9c7db4251f51ed307e329b81b72ccf2056ff82d50524debde1ee1870e13f", size = 388221, upload-time = "2025-08-21T14:42:52.034Z" }, -] - -[[package]] -name = "jupyter-server-terminals" -version = "0.5.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pywinpty", marker = "os_name == 'nt'" }, - { name = "terminado" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f4/a7/bcd0a9b0cbba88986fe944aaaf91bfda603e5a50bda8ed15123f381a3b2f/jupyter_server_terminals-0.5.4.tar.gz", hash = "sha256:bbda128ed41d0be9020349f9f1f2a4ab9952a73ed5f5ac9f1419794761fb87f5", size = 31770, upload-time = "2026-01-14T16:53:20.213Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl", hash = "sha256:55be353fc74a80bc7f3b20e6be50a55a61cd525626f578dcb66a5708e2007d14", size = 13704, upload-time = "2026-01-14T16:53:18.738Z" }, -] - -[[package]] -name = "jupyterlab" -version = "4.5.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "async-lru" }, - { name = "httpx" }, - { name = "ipykernel" }, - { name = "jinja2" }, - { name = "jupyter-core" }, - { name = "jupyter-lsp" }, - { name = "jupyter-server" }, - { name = "jupyterlab-server" }, - { name = "notebook-shim" }, - { name = "packaging" }, - { name = "setuptools" }, - { name = "tornado" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/93/dc/2c8c4ff1aee27ac999ba04c373c5d0d7c6c181b391640d7b916b884d5985/jupyterlab-4.5.2.tar.gz", hash = "sha256:c80a6b9f6dace96a566d590c65ee2785f61e7cd4aac5b4d453dcc7d0d5e069b7", size = 23990371, upload-time = "2026-01-12T12:27:08.493Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a4/78/7e455920f104ef2aa94a4c0d2b40e5b44334ee7057eae1aa1fb97b9631ad/jupyterlab-4.5.2-py3-none-any.whl", hash = "sha256:76466ebcfdb7a9bb7e2fbd6459c0e2c032ccf75be673634a84bee4b3e6b13ab6", size = 12385807, upload-time = "2026-01-12T12:27:03.923Z" }, -] - -[[package]] -name = "jupyterlab-pygments" -version = "0.3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/90/51/9187be60d989df97f5f0aba133fa54e7300f17616e065d1ada7d7646b6d6/jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d", size = 512900, upload-time = "2023-11-23T09:26:37.44Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780", size = 15884, upload-time = "2023-11-23T09:26:34.325Z" }, -] - -[[package]] -name = "jupyterlab-server" -version = "2.28.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "babel" }, - { name = "jinja2" }, - { name = "json5" }, - { name = "jsonschema" }, - { name = "jupyter-server" }, - { name = "packaging" }, - { name = "requests" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/d6/2c/90153f189e421e93c4bb4f9e3f59802a1f01abd2ac5cf40b152d7f735232/jupyterlab_server-2.28.0.tar.gz", hash = "sha256:35baa81898b15f93573e2deca50d11ac0ae407ebb688299d3a5213265033712c", size = 76996, upload-time = "2025-10-22T13:59:18.37Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl", hash = "sha256:e4355b148fdcf34d312bbbc80f22467d6d20460e8b8736bf235577dd18506968", size = 59830, upload-time = "2025-10-22T13:59:16.767Z" }, -] - -[[package]] -name = "jupyterlab-widgets" -version = "3.0.16" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/26/2d/ef58fed122b268c69c0aa099da20bc67657cdfb2e222688d5731bd5b971d/jupyterlab_widgets-3.0.16.tar.gz", hash = "sha256:423da05071d55cf27a9e602216d35a3a65a3e41cdf9c5d3b643b814ce38c19e0", size = 897423, upload-time = "2025-11-01T21:11:29.724Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl", hash = "sha256:45fa36d9c6422cf2559198e4db481aa243c7a32d9926b500781c830c80f7ecf8", size = 914926, upload-time = "2025-11-01T21:11:28.008Z" }, -] - -[[package]] -name = "kiwisolver" -version = "1.4.9" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5c/3c/85844f1b0feb11ee581ac23fe5fce65cd049a200c1446708cc1b7f922875/kiwisolver-1.4.9.tar.gz", hash = "sha256:c3b22c26c6fd6811b0ae8363b95ca8ce4ea3c202d3d0975b2914310ceb1bcc4d", size = 97564, upload-time = "2025-08-10T21:27:49.279Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/31/c1/c2686cda909742ab66c7388e9a1a8521a59eb89f8bcfbee28fc980d07e24/kiwisolver-1.4.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a5d0432ccf1c7ab14f9949eec60c5d1f924f17c037e9f8b33352fa05799359b8", size = 123681, upload-time = "2025-08-10T21:26:26.725Z" }, - { url = "https://files.pythonhosted.org/packages/ca/f0/f44f50c9f5b1a1860261092e3bc91ecdc9acda848a8b8c6abfda4a24dd5c/kiwisolver-1.4.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efb3a45b35622bb6c16dbfab491a8f5a391fe0e9d45ef32f4df85658232ca0e2", size = 66464, upload-time = "2025-08-10T21:26:27.733Z" }, - { url = "https://files.pythonhosted.org/packages/2d/7a/9d90a151f558e29c3936b8a47ac770235f436f2120aca41a6d5f3d62ae8d/kiwisolver-1.4.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1a12cf6398e8a0a001a059747a1cbf24705e18fe413bc22de7b3d15c67cffe3f", size = 64961, upload-time = "2025-08-10T21:26:28.729Z" }, - { url = "https://files.pythonhosted.org/packages/e9/e9/f218a2cb3a9ffbe324ca29a9e399fa2d2866d7f348ec3a88df87fc248fc5/kiwisolver-1.4.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b67e6efbf68e077dd71d1a6b37e43e1a99d0bff1a3d51867d45ee8908b931098", size = 1474607, upload-time = "2025-08-10T21:26:29.798Z" }, - { url = "https://files.pythonhosted.org/packages/d9/28/aac26d4c882f14de59041636292bc838db8961373825df23b8eeb807e198/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5656aa670507437af0207645273ccdfee4f14bacd7f7c67a4306d0dcaeaf6eed", size = 1276546, upload-time = "2025-08-10T21:26:31.401Z" }, - { url = "https://files.pythonhosted.org/packages/8b/ad/8bfc1c93d4cc565e5069162f610ba2f48ff39b7de4b5b8d93f69f30c4bed/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:bfc08add558155345129c7803b3671cf195e6a56e7a12f3dde7c57d9b417f525", size = 1294482, upload-time = "2025-08-10T21:26:32.721Z" }, - { url = "https://files.pythonhosted.org/packages/da/f1/6aca55ff798901d8ce403206d00e033191f63d82dd708a186e0ed2067e9c/kiwisolver-1.4.9-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:40092754720b174e6ccf9e845d0d8c7d8e12c3d71e7fc35f55f3813e96376f78", size = 1343720, upload-time = "2025-08-10T21:26:34.032Z" }, - { url = "https://files.pythonhosted.org/packages/d1/91/eed031876c595c81d90d0f6fc681ece250e14bf6998c3d7c419466b523b7/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:497d05f29a1300d14e02e6441cf0f5ee81c1ff5a304b0d9fb77423974684e08b", size = 2224907, upload-time = "2025-08-10T21:26:35.824Z" }, - { url = "https://files.pythonhosted.org/packages/e9/ec/4d1925f2e49617b9cca9c34bfa11adefad49d00db038e692a559454dfb2e/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:bdd1a81a1860476eb41ac4bc1e07b3f07259e6d55bbf739b79c8aaedcf512799", size = 2321334, upload-time = "2025-08-10T21:26:37.534Z" }, - { url = "https://files.pythonhosted.org/packages/43/cb/450cd4499356f68802750c6ddc18647b8ea01ffa28f50d20598e0befe6e9/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e6b93f13371d341afee3be9f7c5964e3fe61d5fa30f6a30eb49856935dfe4fc3", size = 2488313, upload-time = "2025-08-10T21:26:39.191Z" }, - { url = "https://files.pythonhosted.org/packages/71/67/fc76242bd99f885651128a5d4fa6083e5524694b7c88b489b1b55fdc491d/kiwisolver-1.4.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d75aa530ccfaa593da12834b86a0724f58bff12706659baa9227c2ccaa06264c", size = 2291970, upload-time = "2025-08-10T21:26:40.828Z" }, - { url = "https://files.pythonhosted.org/packages/75/bd/f1a5d894000941739f2ae1b65a32892349423ad49c2e6d0771d0bad3fae4/kiwisolver-1.4.9-cp313-cp313-win_amd64.whl", hash = "sha256:dd0a578400839256df88c16abddf9ba14813ec5f21362e1fe65022e00c883d4d", size = 73894, upload-time = "2025-08-10T21:26:42.33Z" }, - { url = "https://files.pythonhosted.org/packages/95/38/dce480814d25b99a391abbddadc78f7c117c6da34be68ca8b02d5848b424/kiwisolver-1.4.9-cp313-cp313-win_arm64.whl", hash = "sha256:d4188e73af84ca82468f09cadc5ac4db578109e52acb4518d8154698d3a87ca2", size = 64995, upload-time = "2025-08-10T21:26:43.889Z" }, - { url = "https://files.pythonhosted.org/packages/e2/37/7d218ce5d92dadc5ebdd9070d903e0c7cf7edfe03f179433ac4d13ce659c/kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:5a0f2724dfd4e3b3ac5a82436a8e6fd16baa7d507117e4279b660fe8ca38a3a1", size = 126510, upload-time = "2025-08-10T21:26:44.915Z" }, - { url = "https://files.pythonhosted.org/packages/23/b0/e85a2b48233daef4b648fb657ebbb6f8367696a2d9548a00b4ee0eb67803/kiwisolver-1.4.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1b11d6a633e4ed84fc0ddafd4ebfd8ea49b3f25082c04ad12b8315c11d504dc1", size = 67903, upload-time = "2025-08-10T21:26:45.934Z" }, - { url = "https://files.pythonhosted.org/packages/44/98/f2425bc0113ad7de24da6bb4dae1343476e95e1d738be7c04d31a5d037fd/kiwisolver-1.4.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61874cdb0a36016354853593cffc38e56fc9ca5aa97d2c05d3dcf6922cd55a11", size = 66402, upload-time = "2025-08-10T21:26:47.101Z" }, - { url = "https://files.pythonhosted.org/packages/98/d8/594657886df9f34c4177cc353cc28ca7e6e5eb562d37ccc233bff43bbe2a/kiwisolver-1.4.9-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:60c439763a969a6af93b4881db0eed8fadf93ee98e18cbc35bc8da868d0c4f0c", size = 1582135, upload-time = "2025-08-10T21:26:48.665Z" }, - { url = "https://files.pythonhosted.org/packages/5c/c6/38a115b7170f8b306fc929e166340c24958347308ea3012c2b44e7e295db/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92a2f997387a1b79a75e7803aa7ded2cfbe2823852ccf1ba3bcf613b62ae3197", size = 1389409, upload-time = "2025-08-10T21:26:50.335Z" }, - { url = "https://files.pythonhosted.org/packages/bf/3b/e04883dace81f24a568bcee6eb3001da4ba05114afa622ec9b6fafdc1f5e/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a31d512c812daea6d8b3be3b2bfcbeb091dbb09177706569bcfc6240dcf8b41c", size = 1401763, upload-time = "2025-08-10T21:26:51.867Z" }, - { url = "https://files.pythonhosted.org/packages/9f/80/20ace48e33408947af49d7d15c341eaee69e4e0304aab4b7660e234d6288/kiwisolver-1.4.9-cp313-cp313t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:52a15b0f35dad39862d376df10c5230155243a2c1a436e39eb55623ccbd68185", size = 1453643, upload-time = "2025-08-10T21:26:53.592Z" }, - { url = "https://files.pythonhosted.org/packages/64/31/6ce4380a4cd1f515bdda976a1e90e547ccd47b67a1546d63884463c92ca9/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a30fd6fdef1430fd9e1ba7b3398b5ee4e2887783917a687d86ba69985fb08748", size = 2330818, upload-time = "2025-08-10T21:26:55.051Z" }, - { url = "https://files.pythonhosted.org/packages/fa/e9/3f3fcba3bcc7432c795b82646306e822f3fd74df0ee81f0fa067a1f95668/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:cc9617b46837c6468197b5945e196ee9ca43057bb7d9d1ae688101e4e1dddf64", size = 2419963, upload-time = "2025-08-10T21:26:56.421Z" }, - { url = "https://files.pythonhosted.org/packages/99/43/7320c50e4133575c66e9f7dadead35ab22d7c012a3b09bb35647792b2a6d/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:0ab74e19f6a2b027ea4f845a78827969af45ce790e6cb3e1ebab71bdf9f215ff", size = 2594639, upload-time = "2025-08-10T21:26:57.882Z" }, - { url = "https://files.pythonhosted.org/packages/65/d6/17ae4a270d4a987ef8a385b906d2bdfc9fce502d6dc0d3aea865b47f548c/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dba5ee5d3981160c28d5490f0d1b7ed730c22470ff7f6cc26cfcfaacb9896a07", size = 2391741, upload-time = "2025-08-10T21:26:59.237Z" }, - { url = "https://files.pythonhosted.org/packages/2a/8f/8f6f491d595a9e5912971f3f863d81baddccc8a4d0c3749d6a0dd9ffc9df/kiwisolver-1.4.9-cp313-cp313t-win_arm64.whl", hash = "sha256:0749fd8f4218ad2e851e11cc4dc05c7cbc0cbc4267bdfdb31782e65aace4ee9c", size = 68646, upload-time = "2025-08-10T21:27:00.52Z" }, - { url = "https://files.pythonhosted.org/packages/6b/32/6cc0fbc9c54d06c2969faa9c1d29f5751a2e51809dd55c69055e62d9b426/kiwisolver-1.4.9-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:9928fe1eb816d11ae170885a74d074f57af3a0d65777ca47e9aeb854a1fba386", size = 123806, upload-time = "2025-08-10T21:27:01.537Z" }, - { url = "https://files.pythonhosted.org/packages/b2/dd/2bfb1d4a4823d92e8cbb420fe024b8d2167f72079b3bb941207c42570bdf/kiwisolver-1.4.9-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d0005b053977e7b43388ddec89fa567f43d4f6d5c2c0affe57de5ebf290dc552", size = 66605, upload-time = "2025-08-10T21:27:03.335Z" }, - { url = "https://files.pythonhosted.org/packages/f7/69/00aafdb4e4509c2ca6064646cba9cd4b37933898f426756adb2cb92ebbed/kiwisolver-1.4.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2635d352d67458b66fd0667c14cb1d4145e9560d503219034a18a87e971ce4f3", size = 64925, upload-time = "2025-08-10T21:27:04.339Z" }, - { url = "https://files.pythonhosted.org/packages/43/dc/51acc6791aa14e5cb6d8a2e28cefb0dc2886d8862795449d021334c0df20/kiwisolver-1.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:767c23ad1c58c9e827b649a9ab7809fd5fd9db266a9cf02b0e926ddc2c680d58", size = 1472414, upload-time = "2025-08-10T21:27:05.437Z" }, - { url = "https://files.pythonhosted.org/packages/3d/bb/93fa64a81db304ac8a246f834d5094fae4b13baf53c839d6bb6e81177129/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72d0eb9fba308b8311685c2268cf7d0a0639a6cd027d8128659f72bdd8a024b4", size = 1281272, upload-time = "2025-08-10T21:27:07.063Z" }, - { url = "https://files.pythonhosted.org/packages/70/e6/6df102916960fb8d05069d4bd92d6d9a8202d5a3e2444494e7cd50f65b7a/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f68e4f3eeca8fb22cc3d731f9715a13b652795ef657a13df1ad0c7dc0e9731df", size = 1298578, upload-time = "2025-08-10T21:27:08.452Z" }, - { url = "https://files.pythonhosted.org/packages/7c/47/e142aaa612f5343736b087864dbaebc53ea8831453fb47e7521fa8658f30/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d84cd4061ae292d8ac367b2c3fa3aad11cb8625a95d135fe93f286f914f3f5a6", size = 1345607, upload-time = "2025-08-10T21:27:10.125Z" }, - { url = "https://files.pythonhosted.org/packages/54/89/d641a746194a0f4d1a3670fb900d0dbaa786fb98341056814bc3f058fa52/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a60ea74330b91bd22a29638940d115df9dc00af5035a9a2a6ad9399ffb4ceca5", size = 2230150, upload-time = "2025-08-10T21:27:11.484Z" }, - { url = "https://files.pythonhosted.org/packages/aa/6b/5ee1207198febdf16ac11f78c5ae40861b809cbe0e6d2a8d5b0b3044b199/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ce6a3a4e106cf35c2d9c4fa17c05ce0b180db622736845d4315519397a77beaf", size = 2325979, upload-time = "2025-08-10T21:27:12.917Z" }, - { url = "https://files.pythonhosted.org/packages/fc/ff/b269eefd90f4ae14dcc74973d5a0f6d28d3b9bb1afd8c0340513afe6b39a/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:77937e5e2a38a7b48eef0585114fe7930346993a88060d0bf886086d2aa49ef5", size = 2491456, upload-time = "2025-08-10T21:27:14.353Z" }, - { url = "https://files.pythonhosted.org/packages/fc/d4/10303190bd4d30de547534601e259a4fbf014eed94aae3e5521129215086/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:24c175051354f4a28c5d6a31c93906dc653e2bf234e8a4bbfb964892078898ce", size = 2294621, upload-time = "2025-08-10T21:27:15.808Z" }, - { url = "https://files.pythonhosted.org/packages/28/e0/a9a90416fce5c0be25742729c2ea52105d62eda6c4be4d803c2a7be1fa50/kiwisolver-1.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:0763515d4df10edf6d06a3c19734e2566368980d21ebec439f33f9eb936c07b7", size = 75417, upload-time = "2025-08-10T21:27:17.436Z" }, - { url = "https://files.pythonhosted.org/packages/1f/10/6949958215b7a9a264299a7db195564e87900f709db9245e4ebdd3c70779/kiwisolver-1.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:0e4e2bf29574a6a7b7f6cb5fa69293b9f96c928949ac4a53ba3f525dffb87f9c", size = 66582, upload-time = "2025-08-10T21:27:18.436Z" }, - { url = "https://files.pythonhosted.org/packages/ec/79/60e53067903d3bc5469b369fe0dfc6b3482e2133e85dae9daa9527535991/kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d976bbb382b202f71c67f77b0ac11244021cfa3f7dfd9e562eefcea2df711548", size = 126514, upload-time = "2025-08-10T21:27:19.465Z" }, - { url = "https://files.pythonhosted.org/packages/25/d1/4843d3e8d46b072c12a38c97c57fab4608d36e13fe47d47ee96b4d61ba6f/kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2489e4e5d7ef9a1c300a5e0196e43d9c739f066ef23270607d45aba368b91f2d", size = 67905, upload-time = "2025-08-10T21:27:20.51Z" }, - { url = "https://files.pythonhosted.org/packages/8c/ae/29ffcbd239aea8b93108de1278271ae764dfc0d803a5693914975f200596/kiwisolver-1.4.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e2ea9f7ab7fbf18fffb1b5434ce7c69a07582f7acc7717720f1d69f3e806f90c", size = 66399, upload-time = "2025-08-10T21:27:21.496Z" }, - { url = "https://files.pythonhosted.org/packages/a1/ae/d7ba902aa604152c2ceba5d352d7b62106bedbccc8e95c3934d94472bfa3/kiwisolver-1.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b34e51affded8faee0dfdb705416153819d8ea9250bbbf7ea1b249bdeb5f1122", size = 1582197, upload-time = "2025-08-10T21:27:22.604Z" }, - { url = "https://files.pythonhosted.org/packages/f2/41/27c70d427eddb8bc7e4f16420a20fefc6f480312122a59a959fdfe0445ad/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8aacd3d4b33b772542b2e01beb50187536967b514b00003bdda7589722d2a64", size = 1390125, upload-time = "2025-08-10T21:27:24.036Z" }, - { url = "https://files.pythonhosted.org/packages/41/42/b3799a12bafc76d962ad69083f8b43b12bf4fe78b097b12e105d75c9b8f1/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7cf974dd4e35fa315563ac99d6287a1024e4dc2077b8a7d7cd3d2fb65d283134", size = 1402612, upload-time = "2025-08-10T21:27:25.773Z" }, - { url = "https://files.pythonhosted.org/packages/d2/b5/a210ea073ea1cfaca1bb5c55a62307d8252f531beb364e18aa1e0888b5a0/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:85bd218b5ecfbee8c8a82e121802dcb519a86044c9c3b2e4aef02fa05c6da370", size = 1453990, upload-time = "2025-08-10T21:27:27.089Z" }, - { url = "https://files.pythonhosted.org/packages/5f/ce/a829eb8c033e977d7ea03ed32fb3c1781b4fa0433fbadfff29e39c676f32/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0856e241c2d3df4efef7c04a1e46b1936b6120c9bcf36dd216e3acd84bc4fb21", size = 2331601, upload-time = "2025-08-10T21:27:29.343Z" }, - { url = "https://files.pythonhosted.org/packages/e0/4b/b5e97eb142eb9cd0072dacfcdcd31b1c66dc7352b0f7c7255d339c0edf00/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9af39d6551f97d31a4deebeac6f45b156f9755ddc59c07b402c148f5dbb6482a", size = 2422041, upload-time = "2025-08-10T21:27:30.754Z" }, - { url = "https://files.pythonhosted.org/packages/40/be/8eb4cd53e1b85ba4edc3a9321666f12b83113a178845593307a3e7891f44/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:bb4ae2b57fc1d8cbd1cf7b1d9913803681ffa903e7488012be5b76dedf49297f", size = 2594897, upload-time = "2025-08-10T21:27:32.803Z" }, - { url = "https://files.pythonhosted.org/packages/99/dd/841e9a66c4715477ea0abc78da039832fbb09dac5c35c58dc4c41a407b8a/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:aedff62918805fb62d43a4aa2ecd4482c380dc76cd31bd7c8878588a61bd0369", size = 2391835, upload-time = "2025-08-10T21:27:34.23Z" }, - { url = "https://files.pythonhosted.org/packages/0c/28/4b2e5c47a0da96896fdfdb006340ade064afa1e63675d01ea5ac222b6d52/kiwisolver-1.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:1fa333e8b2ce4d9660f2cda9c0e1b6bafcfb2457a9d259faa82289e73ec24891", size = 79988, upload-time = "2025-08-10T21:27:35.587Z" }, - { url = "https://files.pythonhosted.org/packages/80/be/3578e8afd18c88cdf9cb4cffde75a96d2be38c5a903f1ed0ceec061bd09e/kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32", size = 70260, upload-time = "2025-08-10T21:27:36.606Z" }, -] - -[[package]] -name = "lark" -version = "1.3.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/da/34/28fff3ab31ccff1fd4f6c7c7b0ceb2b6968d8ea4950663eadcb5720591a0/lark-1.3.1.tar.gz", hash = "sha256:b426a7a6d6d53189d318f2b6236ab5d6429eaf09259f1ca33eb716eed10d2905", size = 382732, upload-time = "2025-10-27T18:25:56.653Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/82/3d/14ce75ef66813643812f3093ab17e46d3a206942ce7376d31ec2d36229e7/lark-1.3.1-py3-none-any.whl", hash = "sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12", size = 113151, upload-time = "2025-10-27T18:25:54.882Z" }, -] - -[[package]] -name = "markupsafe" -version = "3.0.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, - { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, - { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, - { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, - { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, - { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, - { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, - { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, - { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, - { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, - { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, - { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, - { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, - { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, - { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, - { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, - { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, - { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, - { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, - { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, - { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, - { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, - { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, - { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, - { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, - { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, - { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, - { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, - { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, - { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, - { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, - { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, - { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, - { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, - { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, - { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, - { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, - { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, - { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, - { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, - { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, - { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, - { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, - { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, -] - -[[package]] -name = "matplotlib" -version = "3.10.8" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "contourpy" }, - { name = "cycler" }, - { name = "fonttools" }, - { name = "kiwisolver" }, - { name = "numpy" }, - { name = "packaging" }, - { name = "pillow" }, - { name = "pyparsing" }, - { name = "python-dateutil" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/8a/76/d3c6e3a13fe484ebe7718d14e269c9569c4eb0020a968a327acb3b9a8fe6/matplotlib-3.10.8.tar.gz", hash = "sha256:2299372c19d56bcd35cf05a2738308758d32b9eaed2371898d8f5bd33f084aa3", size = 34806269, upload-time = "2025-12-10T22:56:51.155Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3d/b9/15fd5541ef4f5b9a17eefd379356cf12175fe577424e7b1d80676516031a/matplotlib-3.10.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3f2e409836d7f5ac2f1c013110a4d50b9f7edc26328c108915f9075d7d7a91b6", size = 8261076, upload-time = "2025-12-10T22:55:44.648Z" }, - { url = "https://files.pythonhosted.org/packages/8d/a0/2ba3473c1b66b9c74dc7107c67e9008cb1782edbe896d4c899d39ae9cf78/matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56271f3dac49a88d7fca5060f004d9d22b865f743a12a23b1e937a0be4818ee1", size = 8148794, upload-time = "2025-12-10T22:55:46.252Z" }, - { url = "https://files.pythonhosted.org/packages/75/97/a471f1c3eb1fd6f6c24a31a5858f443891d5127e63a7788678d14e249aea/matplotlib-3.10.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a0a7f52498f72f13d4a25ea70f35f4cb60642b466cbb0a9be951b5bc3f45a486", size = 8718474, upload-time = "2025-12-10T22:55:47.864Z" }, - { url = "https://files.pythonhosted.org/packages/01/be/cd478f4b66f48256f42927d0acbcd63a26a893136456cd079c0cc24fbabf/matplotlib-3.10.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:646d95230efb9ca614a7a594d4fcacde0ac61d25e37dd51710b36477594963ce", size = 9549637, upload-time = "2025-12-10T22:55:50.048Z" }, - { url = "https://files.pythonhosted.org/packages/5d/7c/8dc289776eae5109e268c4fb92baf870678dc048a25d4ac903683b86d5bf/matplotlib-3.10.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f89c151aab2e2e23cb3fe0acad1e8b82841fd265379c4cecd0f3fcb34c15e0f6", size = 9613678, upload-time = "2025-12-10T22:55:52.21Z" }, - { url = "https://files.pythonhosted.org/packages/64/40/37612487cc8a437d4dd261b32ca21fe2d79510fe74af74e1f42becb1bdb8/matplotlib-3.10.8-cp313-cp313-win_amd64.whl", hash = "sha256:e8ea3e2d4066083e264e75c829078f9e149fa119d27e19acd503de65e0b13149", size = 8142686, upload-time = "2025-12-10T22:55:54.253Z" }, - { url = "https://files.pythonhosted.org/packages/66/52/8d8a8730e968185514680c2a6625943f70269509c3dcfc0dcf7d75928cb8/matplotlib-3.10.8-cp313-cp313-win_arm64.whl", hash = "sha256:c108a1d6fa78a50646029cb6d49808ff0fc1330fda87fa6f6250c6b5369b6645", size = 8012917, upload-time = "2025-12-10T22:55:56.268Z" }, - { url = "https://files.pythonhosted.org/packages/b5/27/51fe26e1062f298af5ef66343d8ef460e090a27fea73036c76c35821df04/matplotlib-3.10.8-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ad3d9833a64cf48cc4300f2b406c3d0f4f4724a91c0bd5640678a6ba7c102077", size = 8305679, upload-time = "2025-12-10T22:55:57.856Z" }, - { url = "https://files.pythonhosted.org/packages/2c/1e/4de865bc591ac8e3062e835f42dd7fe7a93168d519557837f0e37513f629/matplotlib-3.10.8-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:eb3823f11823deade26ce3b9f40dcb4a213da7a670013929f31d5f5ed1055b22", size = 8198336, upload-time = "2025-12-10T22:55:59.371Z" }, - { url = "https://files.pythonhosted.org/packages/c6/cb/2f7b6e75fb4dce87ef91f60cac4f6e34f4c145ab036a22318ec837971300/matplotlib-3.10.8-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d9050fee89a89ed57b4fb2c1bfac9a3d0c57a0d55aed95949eedbc42070fea39", size = 8731653, upload-time = "2025-12-10T22:56:01.032Z" }, - { url = "https://files.pythonhosted.org/packages/46/b3/bd9c57d6ba670a37ab31fb87ec3e8691b947134b201f881665b28cc039ff/matplotlib-3.10.8-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b44d07310e404ba95f8c25aa5536f154c0a8ec473303535949e52eb71d0a1565", size = 9561356, upload-time = "2025-12-10T22:56:02.95Z" }, - { url = "https://files.pythonhosted.org/packages/c0/3d/8b94a481456dfc9dfe6e39e93b5ab376e50998cddfd23f4ae3b431708f16/matplotlib-3.10.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0a33deb84c15ede243aead39f77e990469fff93ad1521163305095b77b72ce4a", size = 9614000, upload-time = "2025-12-10T22:56:05.411Z" }, - { url = "https://files.pythonhosted.org/packages/bd/cd/bc06149fe5585ba800b189a6a654a75f1f127e8aab02fd2be10df7fa500c/matplotlib-3.10.8-cp313-cp313t-win_amd64.whl", hash = "sha256:3a48a78d2786784cc2413e57397981fb45c79e968d99656706018d6e62e57958", size = 8220043, upload-time = "2025-12-10T22:56:07.551Z" }, - { url = "https://files.pythonhosted.org/packages/e3/de/b22cf255abec916562cc04eef457c13e58a1990048de0c0c3604d082355e/matplotlib-3.10.8-cp313-cp313t-win_arm64.whl", hash = "sha256:15d30132718972c2c074cd14638c7f4592bd98719e2308bccea40e0538bc0cb5", size = 8062075, upload-time = "2025-12-10T22:56:09.178Z" }, - { url = "https://files.pythonhosted.org/packages/3c/43/9c0ff7a2f11615e516c3b058e1e6e8f9614ddeca53faca06da267c48345d/matplotlib-3.10.8-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b53285e65d4fa4c86399979e956235deb900be5baa7fc1218ea67fbfaeaadd6f", size = 8262481, upload-time = "2025-12-10T22:56:10.885Z" }, - { url = "https://files.pythonhosted.org/packages/6f/ca/e8ae28649fcdf039fda5ef554b40a95f50592a3c47e6f7270c9561c12b07/matplotlib-3.10.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32f8dce744be5569bebe789e46727946041199030db8aeb2954d26013a0eb26b", size = 8151473, upload-time = "2025-12-10T22:56:12.377Z" }, - { url = "https://files.pythonhosted.org/packages/f1/6f/009d129ae70b75e88cbe7e503a12a4c0670e08ed748a902c2568909e9eb5/matplotlib-3.10.8-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4cf267add95b1c88300d96ca837833d4112756045364f5c734a2276038dae27d", size = 9553896, upload-time = "2025-12-10T22:56:14.432Z" }, - { url = "https://files.pythonhosted.org/packages/f5/26/4221a741eb97967bc1fd5e4c52b9aa5a91b2f4ec05b59f6def4d820f9df9/matplotlib-3.10.8-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2cf5bd12cecf46908f286d7838b2abc6c91cda506c0445b8223a7c19a00df008", size = 9824193, upload-time = "2025-12-10T22:56:16.29Z" }, - { url = "https://files.pythonhosted.org/packages/1f/f3/3abf75f38605772cf48a9daf5821cd4f563472f38b4b828c6fba6fa6d06e/matplotlib-3.10.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:41703cc95688f2516b480f7f339d8851a6035f18e100ee6a32bc0b8536a12a9c", size = 9615444, upload-time = "2025-12-10T22:56:18.155Z" }, - { url = "https://files.pythonhosted.org/packages/93/a5/de89ac80f10b8dc615807ee1133cd99ac74082581196d4d9590bea10690d/matplotlib-3.10.8-cp314-cp314-win_amd64.whl", hash = "sha256:83d282364ea9f3e52363da262ce32a09dfe241e4080dcedda3c0db059d3c1f11", size = 8272719, upload-time = "2025-12-10T22:56:20.366Z" }, - { url = "https://files.pythonhosted.org/packages/69/ce/b006495c19ccc0a137b48083168a37bd056392dee02f87dba0472f2797fe/matplotlib-3.10.8-cp314-cp314-win_arm64.whl", hash = "sha256:2c1998e92cd5999e295a731bcb2911c75f597d937341f3030cc24ef2733d78a8", size = 8144205, upload-time = "2025-12-10T22:56:22.239Z" }, - { url = "https://files.pythonhosted.org/packages/68/d9/b31116a3a855bd313c6fcdb7226926d59b041f26061c6c5b1be66a08c826/matplotlib-3.10.8-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:b5a2b97dbdc7d4f353ebf343744f1d1f1cca8aa8bfddb4262fcf4306c3761d50", size = 8305785, upload-time = "2025-12-10T22:56:24.218Z" }, - { url = "https://files.pythonhosted.org/packages/1e/90/6effe8103f0272685767ba5f094f453784057072f49b393e3ea178fe70a5/matplotlib-3.10.8-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3f5c3e4da343bba819f0234186b9004faba952cc420fbc522dc4e103c1985908", size = 8198361, upload-time = "2025-12-10T22:56:26.787Z" }, - { url = "https://files.pythonhosted.org/packages/d7/65/a73188711bea603615fc0baecca1061429ac16940e2385433cc778a9d8e7/matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f62550b9a30afde8c1c3ae450e5eb547d579dd69b25c2fc7a1c67f934c1717a", size = 9561357, upload-time = "2025-12-10T22:56:28.953Z" }, - { url = "https://files.pythonhosted.org/packages/f4/3d/b5c5d5d5be8ce63292567f0e2c43dde9953d3ed86ac2de0a72e93c8f07a1/matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:495672de149445ec1b772ff2c9ede9b769e3cb4f0d0aa7fa730d7f59e2d4e1c1", size = 9823610, upload-time = "2025-12-10T22:56:31.455Z" }, - { url = "https://files.pythonhosted.org/packages/4d/4b/e7beb6bbd49f6bae727a12b270a2654d13c397576d25bd6786e47033300f/matplotlib-3.10.8-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:595ba4d8fe983b88f0eec8c26a241e16d6376fe1979086232f481f8f3f67494c", size = 9614011, upload-time = "2025-12-10T22:56:33.85Z" }, - { url = "https://files.pythonhosted.org/packages/7c/e6/76f2813d31f032e65f6f797e3f2f6e4aab95b65015924b1c51370395c28a/matplotlib-3.10.8-cp314-cp314t-win_amd64.whl", hash = "sha256:25d380fe8b1dc32cf8f0b1b448470a77afb195438bafdf1d858bfb876f3edf7b", size = 8362801, upload-time = "2025-12-10T22:56:36.107Z" }, - { url = "https://files.pythonhosted.org/packages/5d/49/d651878698a0b67f23aa28e17f45a6d6dd3d3f933fa29087fa4ce5947b5a/matplotlib-3.10.8-cp314-cp314t-win_arm64.whl", hash = "sha256:113bb52413ea508ce954a02c10ffd0d565f9c3bc7f2eddc27dfe1731e71c7b5f", size = 8192560, upload-time = "2025-12-10T22:56:38.008Z" }, -] - -[[package]] -name = "matplotlib-inline" -version = "0.2.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c7/74/97e72a36efd4ae2bccb3463284300f8953f199b5ffbc04cbbb0ec78f74b1/matplotlib_inline-0.2.1.tar.gz", hash = "sha256:e1ee949c340d771fc39e241ea75683deb94762c8fa5f2927ec57c83c4dffa9fe", size = 8110, upload-time = "2025-10-23T09:00:22.126Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76", size = 9516, upload-time = "2025-10-23T09:00:20.675Z" }, -] - -[[package]] -name = "mistune" -version = "3.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9d/55/d01f0c4b45ade6536c51170b9043db8b2ec6ddf4a35c7ea3f5f559ac935b/mistune-3.2.0.tar.gz", hash = "sha256:708487c8a8cdd99c9d90eb3ed4c3ed961246ff78ac82f03418f5183ab70e398a", size = 95467, upload-time = "2025-12-23T11:36:34.994Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl", hash = "sha256:febdc629a3c78616b94393c6580551e0e34cc289987ec6c35ed3f4be42d0eee1", size = 53598, upload-time = "2025-12-23T11:36:33.211Z" }, -] - -[[package]] -name = "nbclient" -version = "0.10.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jupyter-client" }, - { name = "jupyter-core" }, - { name = "nbformat" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/56/91/1c1d5a4b9a9ebba2b4e32b8c852c2975c872aec1fe42ab5e516b2cecd193/nbclient-0.10.4.tar.gz", hash = "sha256:1e54091b16e6da39e297b0ece3e10f6f29f4ac4e8ee515d29f8a7099bd6553c9", size = 62554, upload-time = "2025-12-23T07:45:46.369Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl", hash = "sha256:9162df5a7373d70d606527300a95a975a47c137776cd942e52d9c7e29ff83440", size = 25465, upload-time = "2025-12-23T07:45:44.51Z" }, -] - -[[package]] -name = "nbconvert" -version = "7.16.6" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "beautifulsoup4" }, - { name = "bleach", extra = ["css"] }, - { name = "defusedxml" }, - { name = "jinja2" }, - { name = "jupyter-core" }, - { name = "jupyterlab-pygments" }, - { name = "markupsafe" }, - { name = "mistune" }, - { name = "nbclient" }, - { name = "nbformat" }, - { name = "packaging" }, - { name = "pandocfilters" }, - { name = "pygments" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/a3/59/f28e15fc47ffb73af68a8d9b47367a8630d76e97ae85ad18271b9db96fdf/nbconvert-7.16.6.tar.gz", hash = "sha256:576a7e37c6480da7b8465eefa66c17844243816ce1ccc372633c6b71c3c0f582", size = 857715, upload-time = "2025-01-28T09:29:14.724Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/9a/cd673b2f773a12c992f41309ef81b99da1690426bd2f96957a7ade0d3ed7/nbconvert-7.16.6-py3-none-any.whl", hash = "sha256:1375a7b67e0c2883678c48e506dc320febb57685e5ee67faa51b18a90f3a712b", size = 258525, upload-time = "2025-01-28T09:29:12.551Z" }, -] - -[[package]] -name = "nbformat" -version = "5.10.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "fastjsonschema" }, - { name = "jsonschema" }, - { name = "jupyter-core" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/6d/fd/91545e604bc3dad7dca9ed03284086039b294c6b3d75c0d2fa45f9e9caf3/nbformat-5.10.4.tar.gz", hash = "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a", size = 142749, upload-time = "2024-04-04T11:20:37.371Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b", size = 78454, upload-time = "2024-04-04T11:20:34.895Z" }, -] - -[[package]] -name = "nest-asyncio" -version = "1.6.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/83/f8/51569ac65d696c8ecbee95938f89d4abf00f47d58d48f6fbabfe8f0baefe/nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", size = 7418, upload-time = "2024-01-21T14:25:19.227Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195, upload-time = "2024-01-21T14:25:17.223Z" }, -] - -[[package]] -name = "notebook" -version = "7.5.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jupyter-server" }, - { name = "jupyterlab" }, - { name = "jupyterlab-server" }, - { name = "notebook-shim" }, - { name = "tornado" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/3b/b6/6b2c653570b02e4ec2a94c0646a4a25132be0749617776d0b72a2bcedb9b/notebook-7.5.2.tar.gz", hash = "sha256:83e82f93c199ca730313bea1bb24bc279ea96f74816d038a92d26b6b9d5f3e4a", size = 14059605, upload-time = "2026-01-12T14:56:53.483Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/32/55/b754cd51c6011d90ef03e3f06136f1ebd44658b9529dbcf0c15fc0d6a0b7/notebook-7.5.2-py3-none-any.whl", hash = "sha256:17d078a98603d70d62b6b4b3fcb67e87d7a68c398a7ae9b447eb2d7d9aec9979", size = 14468915, upload-time = "2026-01-12T14:56:47.87Z" }, -] - -[[package]] -name = "notebook-shim" -version = "0.2.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jupyter-server" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/54/d2/92fa3243712b9a3e8bafaf60aac366da1cada3639ca767ff4b5b3654ec28/notebook_shim-0.2.4.tar.gz", hash = "sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb", size = 13167, upload-time = "2024-02-14T23:35:18.353Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f9/33/bd5b9137445ea4b680023eb0469b2bb969d61303dedb2aac6560ff3d14a1/notebook_shim-0.2.4-py3-none-any.whl", hash = "sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef", size = 13307, upload-time = "2024-02-14T23:35:16.286Z" }, -] - -[[package]] -name = "numpy" -version = "2.4.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a4/7a/6a3d14e205d292b738db449d0de649b373a59edb0d0b4493821d0a3e8718/numpy-2.4.0.tar.gz", hash = "sha256:6e504f7b16118198f138ef31ba24d985b124c2c469fe8467007cf30fd992f934", size = 20685720, upload-time = "2025-12-20T16:18:19.023Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/0d/853fd96372eda07c824d24adf02e8bc92bb3731b43a9b2a39161c3667cc4/numpy-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a152d86a3ae00ba5f47b3acf3b827509fd0b6cb7d3259665e63dafbad22a75ea", size = 16649088, upload-time = "2025-12-20T16:16:31.421Z" }, - { url = "https://files.pythonhosted.org/packages/e3/37/cc636f1f2a9f585434e20a3e6e63422f70bfe4f7f6698e941db52ea1ac9a/numpy-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:39b19251dec4de8ff8496cd0806cbe27bf0684f765abb1f4809554de93785f2d", size = 12364065, upload-time = "2025-12-20T16:16:33.491Z" }, - { url = "https://files.pythonhosted.org/packages/ed/69/0b78f37ca3690969beee54103ce5f6021709134e8020767e93ba691a72f1/numpy-2.4.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:009bd0ea12d3c784b6639a8457537016ce5172109e585338e11334f6a7bb88ee", size = 5192640, upload-time = "2025-12-20T16:16:35.636Z" }, - { url = "https://files.pythonhosted.org/packages/1d/2a/08569f8252abf590294dbb09a430543ec8f8cc710383abfb3e75cc73aeda/numpy-2.4.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:5fe44e277225fd3dff6882d86d3d447205d43532c3627313d17e754fb3905a0e", size = 6541556, upload-time = "2025-12-20T16:16:37.276Z" }, - { url = "https://files.pythonhosted.org/packages/93/e9/a949885a4e177493d61519377952186b6cbfdf1d6002764c664ba28349b5/numpy-2.4.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f935c4493eda9069851058fa0d9e39dbf6286be690066509305e52912714dbb2", size = 14396562, upload-time = "2025-12-20T16:16:38.953Z" }, - { url = "https://files.pythonhosted.org/packages/99/98/9d4ad53b0e9ef901c2ef1d550d2136f5ac42d3fd2988390a6def32e23e48/numpy-2.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8cfa5f29a695cb7438965e6c3e8d06e0416060cf0d709c1b1c1653a939bf5c2a", size = 16351719, upload-time = "2025-12-20T16:16:41.503Z" }, - { url = "https://files.pythonhosted.org/packages/28/de/5f3711a38341d6e8dd619f6353251a0cdd07f3d6d101a8fd46f4ef87f895/numpy-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ba0cb30acd3ef11c94dc27fbfba68940652492bc107075e7ffe23057f9425681", size = 16176053, upload-time = "2025-12-20T16:16:44.552Z" }, - { url = "https://files.pythonhosted.org/packages/2a/5b/2a3753dc43916501b4183532e7ace862e13211042bceafa253afb5c71272/numpy-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:60e8c196cd82cbbd4f130b5290007e13e6de3eca79f0d4d38014769d96a7c475", size = 18277859, upload-time = "2025-12-20T16:16:47.174Z" }, - { url = "https://files.pythonhosted.org/packages/2c/c5/a18bcdd07a941db3076ef489d036ab16d2bfc2eae0cf27e5a26e29189434/numpy-2.4.0-cp313-cp313-win32.whl", hash = "sha256:5f48cb3e88fbc294dc90e215d86fbaf1c852c63dbdb6c3a3e63f45c4b57f7344", size = 5953849, upload-time = "2025-12-20T16:16:49.554Z" }, - { url = "https://files.pythonhosted.org/packages/4f/f1/719010ff8061da6e8a26e1980cf090412d4f5f8060b31f0c45d77dd67a01/numpy-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:a899699294f28f7be8992853c0c60741f16ff199205e2e6cdca155762cbaa59d", size = 12302840, upload-time = "2025-12-20T16:16:51.227Z" }, - { url = "https://files.pythonhosted.org/packages/f5/5a/b3d259083ed8b4d335270c76966cb6cf14a5d1b69e1a608994ac57a659e6/numpy-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:9198f447e1dc5647d07c9a6bbe2063cc0132728cc7175b39dbc796da5b54920d", size = 10308509, upload-time = "2025-12-20T16:16:53.313Z" }, - { url = "https://files.pythonhosted.org/packages/31/01/95edcffd1bb6c0633df4e808130545c4f07383ab629ac7e316fb44fff677/numpy-2.4.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74623f2ab5cc3f7c886add4f735d1031a1d2be4a4ae63c0546cfd74e7a31ddf6", size = 12491815, upload-time = "2025-12-20T16:16:55.496Z" }, - { url = "https://files.pythonhosted.org/packages/59/ea/5644b8baa92cc1c7163b4b4458c8679852733fa74ca49c942cfa82ded4e0/numpy-2.4.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:0804a8e4ab070d1d35496e65ffd3cf8114c136a2b81f61dfab0de4b218aacfd5", size = 5320321, upload-time = "2025-12-20T16:16:57.468Z" }, - { url = "https://files.pythonhosted.org/packages/26/4e/e10938106d70bc21319bd6a86ae726da37edc802ce35a3a71ecdf1fdfe7f/numpy-2.4.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:02a2038eb27f9443a8b266a66911e926566b5a6ffd1a689b588f7f35b81e7dc3", size = 6641635, upload-time = "2025-12-20T16:16:59.379Z" }, - { url = "https://files.pythonhosted.org/packages/b3/8d/a8828e3eaf5c0b4ab116924df82f24ce3416fa38d0674d8f708ddc6c8aac/numpy-2.4.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1889b3a3f47a7b5bee16bc25a2145bd7cb91897f815ce3499db64c7458b6d91d", size = 14456053, upload-time = "2025-12-20T16:17:01.768Z" }, - { url = "https://files.pythonhosted.org/packages/68/a1/17d97609d87d4520aa5ae2dcfb32305654550ac6a35effb946d303e594ce/numpy-2.4.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85eef4cb5625c47ee6425c58a3502555e10f45ee973da878ac8248ad58c136f3", size = 16401702, upload-time = "2025-12-20T16:17:04.235Z" }, - { url = "https://files.pythonhosted.org/packages/18/32/0f13c1b2d22bea1118356b8b963195446f3af124ed7a5adfa8fdecb1b6ca/numpy-2.4.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6dc8b7e2f4eb184b37655195f421836cfae6f58197b67e3ffc501f1333d993fa", size = 16242493, upload-time = "2025-12-20T16:17:06.856Z" }, - { url = "https://files.pythonhosted.org/packages/ae/23/48f21e3d309fbc137c068a1475358cbd3a901b3987dcfc97a029ab3068e2/numpy-2.4.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:44aba2f0cafd287871a495fb3163408b0bd25bbce135c6f621534a07f4f7875c", size = 18324222, upload-time = "2025-12-20T16:17:09.392Z" }, - { url = "https://files.pythonhosted.org/packages/ac/52/41f3d71296a3dcaa4f456aaa3c6fc8e745b43d0552b6bde56571bb4b4a0f/numpy-2.4.0-cp313-cp313t-win32.whl", hash = "sha256:20c115517513831860c573996e395707aa9fb691eb179200125c250e895fcd93", size = 6076216, upload-time = "2025-12-20T16:17:11.437Z" }, - { url = "https://files.pythonhosted.org/packages/35/ff/46fbfe60ab0710d2a2b16995f708750307d30eccbb4c38371ea9e986866e/numpy-2.4.0-cp313-cp313t-win_amd64.whl", hash = "sha256:b48e35f4ab6f6a7597c46e301126ceba4c44cd3280e3750f85db48b082624fa4", size = 12444263, upload-time = "2025-12-20T16:17:13.182Z" }, - { url = "https://files.pythonhosted.org/packages/a3/e3/9189ab319c01d2ed556c932ccf55064c5d75bb5850d1df7a482ce0badead/numpy-2.4.0-cp313-cp313t-win_arm64.whl", hash = "sha256:4d1cfce39e511069b11e67cd0bd78ceff31443b7c9e5c04db73c7a19f572967c", size = 10378265, upload-time = "2025-12-20T16:17:15.211Z" }, - { url = "https://files.pythonhosted.org/packages/ab/ed/52eac27de39d5e5a6c9aadabe672bc06f55e24a3d9010cd1183948055d76/numpy-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:c95eb6db2884917d86cde0b4d4cf31adf485c8ec36bf8696dd66fa70de96f36b", size = 16647476, upload-time = "2025-12-20T16:17:17.671Z" }, - { url = "https://files.pythonhosted.org/packages/77/c0/990ce1b7fcd4e09aeaa574e2a0a839589e4b08b2ca68070f1acb1fea6736/numpy-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:65167da969cd1ec3a1df31cb221ca3a19a8aaa25370ecb17d428415e93c1935e", size = 12374563, upload-time = "2025-12-20T16:17:20.216Z" }, - { url = "https://files.pythonhosted.org/packages/37/7c/8c5e389c6ae8f5fd2277a988600d79e9625db3fff011a2d87ac80b881a4c/numpy-2.4.0-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:3de19cfecd1465d0dcf8a5b5ea8b3155b42ed0b639dba4b71e323d74f2a3be5e", size = 5203107, upload-time = "2025-12-20T16:17:22.47Z" }, - { url = "https://files.pythonhosted.org/packages/e6/94/ca5b3bd6a8a70a5eec9a0b8dd7f980c1eff4b8a54970a9a7fef248ef564f/numpy-2.4.0-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:6c05483c3136ac4c91b4e81903cb53a8707d316f488124d0398499a4f8e8ef51", size = 6538067, upload-time = "2025-12-20T16:17:24.001Z" }, - { url = "https://files.pythonhosted.org/packages/79/43/993eb7bb5be6761dde2b3a3a594d689cec83398e3f58f4758010f3b85727/numpy-2.4.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36667db4d6c1cea79c8930ab72fadfb4060feb4bfe724141cd4bd064d2e5f8ce", size = 14411926, upload-time = "2025-12-20T16:17:25.822Z" }, - { url = "https://files.pythonhosted.org/packages/03/75/d4c43b61de473912496317a854dac54f1efec3eeb158438da6884b70bb90/numpy-2.4.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9a818668b674047fd88c4cddada7ab8f1c298812783e8328e956b78dc4807f9f", size = 16354295, upload-time = "2025-12-20T16:17:28.308Z" }, - { url = "https://files.pythonhosted.org/packages/b8/0a/b54615b47ee8736a6461a4bb6749128dd3435c5a759d5663f11f0e9af4ac/numpy-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1ee32359fb7543b7b7bd0b2f46294db27e29e7bbdf70541e81b190836cd83ded", size = 16190242, upload-time = "2025-12-20T16:17:30.993Z" }, - { url = "https://files.pythonhosted.org/packages/98/ce/ea207769aacad6246525ec6c6bbd66a2bf56c72443dc10e2f90feed29290/numpy-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e493962256a38f58283de033d8af176c5c91c084ea30f15834f7545451c42059", size = 18280875, upload-time = "2025-12-20T16:17:33.327Z" }, - { url = "https://files.pythonhosted.org/packages/17/ef/ec409437aa962ea372ed601c519a2b141701683ff028f894b7466f0ab42b/numpy-2.4.0-cp314-cp314-win32.whl", hash = "sha256:6bbaebf0d11567fa8926215ae731e1d58e6ec28a8a25235b8a47405d301332db", size = 6002530, upload-time = "2025-12-20T16:17:35.729Z" }, - { url = "https://files.pythonhosted.org/packages/5f/4a/5cb94c787a3ed1ac65e1271b968686521169a7b3ec0b6544bb3ca32960b0/numpy-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:3d857f55e7fdf7c38ab96c4558c95b97d1c685be6b05c249f5fdafcbd6f9899e", size = 12435890, upload-time = "2025-12-20T16:17:37.599Z" }, - { url = "https://files.pythonhosted.org/packages/48/a0/04b89db963af9de1104975e2544f30de89adbf75b9e75f7dd2599be12c79/numpy-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:bb50ce5fb202a26fd5404620e7ef820ad1ab3558b444cb0b55beb7ef66cd2d63", size = 10591892, upload-time = "2025-12-20T16:17:39.649Z" }, - { url = "https://files.pythonhosted.org/packages/53/e5/d74b5ccf6712c06c7a545025a6a71bfa03bdc7e0568b405b0d655232fd92/numpy-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:355354388cba60f2132df297e2d53053d4063f79077b67b481d21276d61fc4df", size = 12494312, upload-time = "2025-12-20T16:17:41.714Z" }, - { url = "https://files.pythonhosted.org/packages/c2/08/3ca9cc2ddf54dfee7ae9a6479c071092a228c68aef08252aa08dac2af002/numpy-2.4.0-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:1d8f9fde5f6dc1b6fc34df8162f3b3079365468703fee7f31d4e0cc8c63baed9", size = 5322862, upload-time = "2025-12-20T16:17:44.145Z" }, - { url = "https://files.pythonhosted.org/packages/87/74/0bb63a68394c0c1e52670cfff2e309afa41edbe11b3327d9af29e4383f34/numpy-2.4.0-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:e0434aa22c821f44eeb4c650b81c7fbdd8c0122c6c4b5a576a76d5a35625ecd9", size = 6644986, upload-time = "2025-12-20T16:17:46.203Z" }, - { url = "https://files.pythonhosted.org/packages/06/8f/9264d9bdbcf8236af2823623fe2f3981d740fc3461e2787e231d97c38c28/numpy-2.4.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:40483b2f2d3ba7aad426443767ff5632ec3156ef09742b96913787d13c336471", size = 14457958, upload-time = "2025-12-20T16:17:48.017Z" }, - { url = "https://files.pythonhosted.org/packages/8c/d9/f9a69ae564bbc7236a35aa883319364ef5fd41f72aa320cc1cbe66148fe2/numpy-2.4.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6a7664ddd9746e20b7325351fe1a8408d0a2bf9c63b5e898290ddc8f09544", size = 16398394, upload-time = "2025-12-20T16:17:50.409Z" }, - { url = "https://files.pythonhosted.org/packages/34/c7/39241501408dde7f885d241a98caba5421061a2c6d2b2197ac5e3aa842d8/numpy-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ecb0019d44f4cdb50b676c5d0cb4b1eae8e15d1ed3d3e6639f986fc92b2ec52c", size = 16241044, upload-time = "2025-12-20T16:17:52.661Z" }, - { url = "https://files.pythonhosted.org/packages/7c/95/cae7effd90e065a95e59fe710eeee05d7328ed169776dfdd9f789e032125/numpy-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d0ffd9e2e4441c96a9c91ec1783285d80bf835b677853fc2770a89d50c1e48ac", size = 18321772, upload-time = "2025-12-20T16:17:54.947Z" }, - { url = "https://files.pythonhosted.org/packages/96/df/3c6c279accd2bfb968a76298e5b276310bd55d243df4fa8ac5816d79347d/numpy-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:77f0d13fa87036d7553bf81f0e1fe3ce68d14c9976c9851744e4d3e91127e95f", size = 6148320, upload-time = "2025-12-20T16:17:57.249Z" }, - { url = "https://files.pythonhosted.org/packages/92/8d/f23033cce252e7a75cae853d17f582e86534c46404dea1c8ee094a9d6d84/numpy-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b1f5b45829ac1848893f0ddf5cb326110604d6df96cdc255b0bf9edd154104d4", size = 12623460, upload-time = "2025-12-20T16:17:58.963Z" }, - { url = "https://files.pythonhosted.org/packages/a4/4f/1f8475907d1a7c4ef9020edf7f39ea2422ec896849245f00688e4b268a71/numpy-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:23a3e9d1a6f360267e8fbb38ba5db355a6a7e9be71d7fce7ab3125e88bb646c8", size = 10661799, upload-time = "2025-12-20T16:18:01.078Z" }, -] - -[[package]] -name = "packaging" -version = "25.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, -] - -[[package]] -name = "pandas" -version = "2.3.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "numpy" }, - { name = "python-dateutil" }, - { name = "pytz" }, - { name = "tzdata" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/33/01/d40b85317f86cf08d853a4f495195c73815fdf205eef3993821720274518/pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b", size = 4495223, upload-time = "2025-09-29T23:34:51.853Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cd/4b/18b035ee18f97c1040d94debd8f2e737000ad70ccc8f5513f4eefad75f4b/pandas-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56851a737e3470de7fa88e6131f41281ed440d29a9268dcbf0002da5ac366713", size = 11544671, upload-time = "2025-09-29T23:21:05.024Z" }, - { url = "https://files.pythonhosted.org/packages/31/94/72fac03573102779920099bcac1c3b05975c2cb5f01eac609faf34bed1ca/pandas-2.3.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdcd9d1167f4885211e401b3036c0c8d9e274eee67ea8d0758a256d60704cfe8", size = 10680807, upload-time = "2025-09-29T23:21:15.979Z" }, - { url = "https://files.pythonhosted.org/packages/16/87/9472cf4a487d848476865321de18cc8c920b8cab98453ab79dbbc98db63a/pandas-2.3.3-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32e7cc9af0f1cc15548288a51a3b681cc2a219faa838e995f7dc53dbab1062d", size = 11709872, upload-time = "2025-09-29T23:21:27.165Z" }, - { url = "https://files.pythonhosted.org/packages/15/07/284f757f63f8a8d69ed4472bfd85122bd086e637bf4ed09de572d575a693/pandas-2.3.3-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318d77e0e42a628c04dc56bcef4b40de67918f7041c2b061af1da41dcff670ac", size = 12306371, upload-time = "2025-09-29T23:21:40.532Z" }, - { url = "https://files.pythonhosted.org/packages/33/81/a3afc88fca4aa925804a27d2676d22dcd2031c2ebe08aabd0ae55b9ff282/pandas-2.3.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e0a175408804d566144e170d0476b15d78458795bb18f1304fb94160cabf40c", size = 12765333, upload-time = "2025-09-29T23:21:55.77Z" }, - { url = "https://files.pythonhosted.org/packages/8d/0f/b4d4ae743a83742f1153464cf1a8ecfafc3ac59722a0b5c8602310cb7158/pandas-2.3.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:93c2d9ab0fc11822b5eece72ec9587e172f63cff87c00b062f6e37448ced4493", size = 13418120, upload-time = "2025-09-29T23:22:10.109Z" }, - { url = "https://files.pythonhosted.org/packages/4f/c7/e54682c96a895d0c808453269e0b5928a07a127a15704fedb643e9b0a4c8/pandas-2.3.3-cp313-cp313-win_amd64.whl", hash = "sha256:f8bfc0e12dc78f777f323f55c58649591b2cd0c43534e8355c51d3fede5f4dee", size = 10993991, upload-time = "2025-09-29T23:25:04.889Z" }, - { url = "https://files.pythonhosted.org/packages/f9/ca/3f8d4f49740799189e1395812f3bf23b5e8fc7c190827d55a610da72ce55/pandas-2.3.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:75ea25f9529fdec2d2e93a42c523962261e567d250b0013b16210e1d40d7c2e5", size = 12048227, upload-time = "2025-09-29T23:22:24.343Z" }, - { url = "https://files.pythonhosted.org/packages/0e/5a/f43efec3e8c0cc92c4663ccad372dbdff72b60bdb56b2749f04aa1d07d7e/pandas-2.3.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:74ecdf1d301e812db96a465a525952f4dde225fdb6d8e5a521d47e1f42041e21", size = 11411056, upload-time = "2025-09-29T23:22:37.762Z" }, - { url = "https://files.pythonhosted.org/packages/46/b1/85331edfc591208c9d1a63a06baa67b21d332e63b7a591a5ba42a10bb507/pandas-2.3.3-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6435cb949cb34ec11cc9860246ccb2fdc9ecd742c12d3304989017d53f039a78", size = 11645189, upload-time = "2025-09-29T23:22:51.688Z" }, - { url = "https://files.pythonhosted.org/packages/44/23/78d645adc35d94d1ac4f2a3c4112ab6f5b8999f4898b8cdf01252f8df4a9/pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110", size = 12121912, upload-time = "2025-09-29T23:23:05.042Z" }, - { url = "https://files.pythonhosted.org/packages/53/da/d10013df5e6aaef6b425aa0c32e1fc1f3e431e4bcabd420517dceadce354/pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86", size = 12712160, upload-time = "2025-09-29T23:23:28.57Z" }, - { url = "https://files.pythonhosted.org/packages/bd/17/e756653095a083d8a37cbd816cb87148debcfcd920129b25f99dd8d04271/pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc", size = 13199233, upload-time = "2025-09-29T23:24:24.876Z" }, - { url = "https://files.pythonhosted.org/packages/04/fd/74903979833db8390b73b3a8a7d30d146d710bd32703724dd9083950386f/pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0", size = 11540635, upload-time = "2025-09-29T23:25:52.486Z" }, - { url = "https://files.pythonhosted.org/packages/21/00/266d6b357ad5e6d3ad55093a7e8efc7dd245f5a842b584db9f30b0f0a287/pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593", size = 10759079, upload-time = "2025-09-29T23:26:33.204Z" }, - { url = "https://files.pythonhosted.org/packages/ca/05/d01ef80a7a3a12b2f8bbf16daba1e17c98a2f039cbc8e2f77a2c5a63d382/pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c", size = 11814049, upload-time = "2025-09-29T23:27:15.384Z" }, - { url = "https://files.pythonhosted.org/packages/15/b2/0e62f78c0c5ba7e3d2c5945a82456f4fac76c480940f805e0b97fcbc2f65/pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b", size = 12332638, upload-time = "2025-09-29T23:27:51.625Z" }, - { url = "https://files.pythonhosted.org/packages/c5/33/dd70400631b62b9b29c3c93d2feee1d0964dc2bae2e5ad7a6c73a7f25325/pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6", size = 12886834, upload-time = "2025-09-29T23:28:21.289Z" }, - { url = "https://files.pythonhosted.org/packages/d3/18/b5d48f55821228d0d2692b34fd5034bb185e854bdb592e9c640f6290e012/pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3", size = 13409925, upload-time = "2025-09-29T23:28:58.261Z" }, - { url = "https://files.pythonhosted.org/packages/a6/3d/124ac75fcd0ecc09b8fdccb0246ef65e35b012030defb0e0eba2cbbbe948/pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5", size = 11109071, upload-time = "2025-09-29T23:32:27.484Z" }, - { url = "https://files.pythonhosted.org/packages/89/9c/0e21c895c38a157e0faa1fb64587a9226d6dd46452cac4532d80c3c4a244/pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec", size = 12048504, upload-time = "2025-09-29T23:29:31.47Z" }, - { url = "https://files.pythonhosted.org/packages/d7/82/b69a1c95df796858777b68fbe6a81d37443a33319761d7c652ce77797475/pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7", size = 11410702, upload-time = "2025-09-29T23:29:54.591Z" }, - { url = "https://files.pythonhosted.org/packages/f9/88/702bde3ba0a94b8c73a0181e05144b10f13f29ebfc2150c3a79062a8195d/pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450", size = 11634535, upload-time = "2025-09-29T23:30:21.003Z" }, - { url = "https://files.pythonhosted.org/packages/a4/1e/1bac1a839d12e6a82ec6cb40cda2edde64a2013a66963293696bbf31fbbb/pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5", size = 12121582, upload-time = "2025-09-29T23:30:43.391Z" }, - { url = "https://files.pythonhosted.org/packages/44/91/483de934193e12a3b1d6ae7c8645d083ff88dec75f46e827562f1e4b4da6/pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788", size = 12699963, upload-time = "2025-09-29T23:31:10.009Z" }, - { url = "https://files.pythonhosted.org/packages/70/44/5191d2e4026f86a2a109053e194d3ba7a31a2d10a9c2348368c63ed4e85a/pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87", size = 13202175, upload-time = "2025-09-29T23:31:59.173Z" }, -] - -[[package]] -name = "pandocfilters" -version = "1.5.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/70/6f/3dd4940bbe001c06a65f88e36bad298bc7a0de5036115639926b0c5c0458/pandocfilters-1.5.1.tar.gz", hash = "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e", size = 8454, upload-time = "2024-01-18T20:08:13.726Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ef/af/4fbc8cab944db5d21b7e2a5b8e9211a03a79852b1157e2c102fcc61ac440/pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc", size = 8663, upload-time = "2024-01-18T20:08:11.28Z" }, -] - -[[package]] -name = "parso" -version = "0.8.5" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d4/de/53e0bcf53d13e005bd8c92e7855142494f41171b34c2536b86187474184d/parso-0.8.5.tar.gz", hash = "sha256:034d7354a9a018bdce352f48b2a8a450f05e9d6ee85db84764e9b6bd96dafe5a", size = 401205, upload-time = "2025-08-23T15:15:28.028Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/16/32/f8e3c85d1d5250232a5d3477a2a28cc291968ff175caeadaf3cc19ce0e4a/parso-0.8.5-py2.py3-none-any.whl", hash = "sha256:646204b5ee239c396d040b90f9e272e9a8017c630092bf59980beb62fd033887", size = 106668, upload-time = "2025-08-23T15:15:25.663Z" }, -] - -[[package]] -name = "pexpect" -version = "4.9.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "ptyprocess" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" }, -] - -[[package]] -name = "pillow" -version = "12.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d0/02/d52c733a2452ef1ffcc123b68e6606d07276b0e358db70eabad7e40042b7/pillow-12.1.0.tar.gz", hash = "sha256:5c5ae0a06e9ea030ab786b0251b32c7e4ce10e58d983c0d5c56029455180b5b9", size = 46977283, upload-time = "2026-01-02T09:13:29.892Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/dd/c7/2530a4aa28248623e9d7f27316b42e27c32ec410f695929696f2e0e4a778/pillow-12.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:7b5dd7cbae20285cdb597b10eb5a2c13aa9de6cde9bb64a3c1317427b1db1ae1", size = 4062543, upload-time = "2026-01-02T09:11:31.566Z" }, - { url = "https://files.pythonhosted.org/packages/8f/1f/40b8eae823dc1519b87d53c30ed9ef085506b05281d313031755c1705f73/pillow-12.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:29a4cef9cb672363926f0470afc516dbf7305a14d8c54f7abbb5c199cd8f8179", size = 4138373, upload-time = "2026-01-02T09:11:33.367Z" }, - { url = "https://files.pythonhosted.org/packages/d4/77/6fa60634cf06e52139fd0e89e5bbf055e8166c691c42fb162818b7fda31d/pillow-12.1.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:681088909d7e8fa9e31b9799aaa59ba5234c58e5e4f1951b4c4d1082a2e980e0", size = 3601241, upload-time = "2026-01-02T09:11:35.011Z" }, - { url = "https://files.pythonhosted.org/packages/4f/bf/28ab865de622e14b747f0cd7877510848252d950e43002e224fb1c9ababf/pillow-12.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:983976c2ab753166dc66d36af6e8ec15bb511e4a25856e2227e5f7e00a160587", size = 5262410, upload-time = "2026-01-02T09:11:36.682Z" }, - { url = "https://files.pythonhosted.org/packages/1c/34/583420a1b55e715937a85bd48c5c0991598247a1fd2eb5423188e765ea02/pillow-12.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:db44d5c160a90df2d24a24760bbd37607d53da0b34fb546c4c232af7192298ac", size = 4657312, upload-time = "2026-01-02T09:11:38.535Z" }, - { url = "https://files.pythonhosted.org/packages/1d/fd/f5a0896839762885b3376ff04878f86ab2b097c2f9a9cdccf4eda8ba8dc0/pillow-12.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6b7a9d1db5dad90e2991645874f708e87d9a3c370c243c2d7684d28f7e133e6b", size = 6232605, upload-time = "2026-01-02T09:11:40.602Z" }, - { url = "https://files.pythonhosted.org/packages/98/aa/938a09d127ac1e70e6ed467bd03834350b33ef646b31edb7452d5de43792/pillow-12.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6258f3260986990ba2fa8a874f8b6e808cf5abb51a94015ca3dc3c68aa4f30ea", size = 8041617, upload-time = "2026-01-02T09:11:42.721Z" }, - { url = "https://files.pythonhosted.org/packages/17/e8/538b24cb426ac0186e03f80f78bc8dc7246c667f58b540bdd57c71c9f79d/pillow-12.1.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e115c15e3bc727b1ca3e641a909f77f8ca72a64fff150f666fcc85e57701c26c", size = 6346509, upload-time = "2026-01-02T09:11:44.955Z" }, - { url = "https://files.pythonhosted.org/packages/01/9a/632e58ec89a32738cabfd9ec418f0e9898a2b4719afc581f07c04a05e3c9/pillow-12.1.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6741e6f3074a35e47c77b23a4e4f2d90db3ed905cb1c5e6e0d49bff2045632bc", size = 7038117, upload-time = "2026-01-02T09:11:46.736Z" }, - { url = "https://files.pythonhosted.org/packages/c7/a2/d40308cf86eada842ca1f3ffa45d0ca0df7e4ab33c83f81e73f5eaed136d/pillow-12.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:935b9d1aed48fcfb3f838caac506f38e29621b44ccc4f8a64d575cb1b2a88644", size = 6460151, upload-time = "2026-01-02T09:11:48.625Z" }, - { url = "https://files.pythonhosted.org/packages/f1/88/f5b058ad6453a085c5266660a1417bdad590199da1b32fb4efcff9d33b05/pillow-12.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5fee4c04aad8932da9f8f710af2c1a15a83582cfb884152a9caa79d4efcdbf9c", size = 7164534, upload-time = "2026-01-02T09:11:50.445Z" }, - { url = "https://files.pythonhosted.org/packages/19/ce/c17334caea1db789163b5d855a5735e47995b0b5dc8745e9a3605d5f24c0/pillow-12.1.0-cp313-cp313-win32.whl", hash = "sha256:a786bf667724d84aa29b5db1c61b7bfdde380202aaca12c3461afd6b71743171", size = 6332551, upload-time = "2026-01-02T09:11:52.234Z" }, - { url = "https://files.pythonhosted.org/packages/e5/07/74a9d941fa45c90a0d9465098fe1ec85de3e2afbdc15cc4766622d516056/pillow-12.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:461f9dfdafa394c59cd6d818bdfdbab4028b83b02caadaff0ffd433faf4c9a7a", size = 7040087, upload-time = "2026-01-02T09:11:54.822Z" }, - { url = "https://files.pythonhosted.org/packages/88/09/c99950c075a0e9053d8e880595926302575bc742b1b47fe1bbcc8d388d50/pillow-12.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:9212d6b86917a2300669511ed094a9406888362e085f2431a7da985a6b124f45", size = 2452470, upload-time = "2026-01-02T09:11:56.522Z" }, - { url = "https://files.pythonhosted.org/packages/b5/ba/970b7d85ba01f348dee4d65412476321d40ee04dcb51cd3735b9dc94eb58/pillow-12.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:00162e9ca6d22b7c3ee8e61faa3c3253cd19b6a37f126cad04f2f88b306f557d", size = 5264816, upload-time = "2026-01-02T09:11:58.227Z" }, - { url = "https://files.pythonhosted.org/packages/10/60/650f2fb55fdba7a510d836202aa52f0baac633e50ab1cf18415d332188fb/pillow-12.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:7d6daa89a00b58c37cb1747ec9fb7ac3bc5ffd5949f5888657dfddde6d1312e0", size = 4660472, upload-time = "2026-01-02T09:12:00.798Z" }, - { url = "https://files.pythonhosted.org/packages/2b/c0/5273a99478956a099d533c4f46cbaa19fd69d606624f4334b85e50987a08/pillow-12.1.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e2479c7f02f9d505682dc47df8c0ea1fc5e264c4d1629a5d63fe3e2334b89554", size = 6268974, upload-time = "2026-01-02T09:12:02.572Z" }, - { url = "https://files.pythonhosted.org/packages/b4/26/0bf714bc2e73d5267887d47931d53c4ceeceea6978148ed2ab2a4e6463c4/pillow-12.1.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f188d580bd870cda1e15183790d1cc2fa78f666e76077d103edf048eed9c356e", size = 8073070, upload-time = "2026-01-02T09:12:04.75Z" }, - { url = "https://files.pythonhosted.org/packages/43/cf/1ea826200de111a9d65724c54f927f3111dc5ae297f294b370a670c17786/pillow-12.1.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0fde7ec5538ab5095cc02df38ee99b0443ff0e1c847a045554cf5f9af1f4aa82", size = 6380176, upload-time = "2026-01-02T09:12:06.626Z" }, - { url = "https://files.pythonhosted.org/packages/03/e0/7938dd2b2013373fd85d96e0f38d62b7a5a262af21ac274250c7ca7847c9/pillow-12.1.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ed07dca4a8464bada6139ab38f5382f83e5f111698caf3191cb8dbf27d908b4", size = 7067061, upload-time = "2026-01-02T09:12:08.624Z" }, - { url = "https://files.pythonhosted.org/packages/86/ad/a2aa97d37272a929a98437a8c0ac37b3cf012f4f8721e1bd5154699b2518/pillow-12.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f45bd71d1fa5e5749587613037b172e0b3b23159d1c00ef2fc920da6f470e6f0", size = 6491824, upload-time = "2026-01-02T09:12:10.488Z" }, - { url = "https://files.pythonhosted.org/packages/a4/44/80e46611b288d51b115826f136fb3465653c28f491068a72d3da49b54cd4/pillow-12.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:277518bf4fe74aa91489e1b20577473b19ee70fb97c374aa50830b279f25841b", size = 7190911, upload-time = "2026-01-02T09:12:12.772Z" }, - { url = "https://files.pythonhosted.org/packages/86/77/eacc62356b4cf81abe99ff9dbc7402750044aed02cfd6a503f7c6fc11f3e/pillow-12.1.0-cp313-cp313t-win32.whl", hash = "sha256:7315f9137087c4e0ee73a761b163fc9aa3b19f5f606a7fc08d83fd3e4379af65", size = 6336445, upload-time = "2026-01-02T09:12:14.775Z" }, - { url = "https://files.pythonhosted.org/packages/e7/3c/57d81d0b74d218706dafccb87a87ea44262c43eef98eb3b164fd000e0491/pillow-12.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:0ddedfaa8b5f0b4ffbc2fa87b556dc59f6bb4ecb14a53b33f9189713ae8053c0", size = 7045354, upload-time = "2026-01-02T09:12:16.599Z" }, - { url = "https://files.pythonhosted.org/packages/ac/82/8b9b97bba2e3576a340f93b044a3a3a09841170ab4c1eb0d5c93469fd32f/pillow-12.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:80941e6d573197a0c28f394753de529bb436b1ca990ed6e765cf42426abc39f8", size = 2454547, upload-time = "2026-01-02T09:12:18.704Z" }, - { url = "https://files.pythonhosted.org/packages/8c/87/bdf971d8bbcf80a348cc3bacfcb239f5882100fe80534b0ce67a784181d8/pillow-12.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:5cb7bc1966d031aec37ddb9dcf15c2da5b2e9f7cc3ca7c54473a20a927e1eb91", size = 4062533, upload-time = "2026-01-02T09:12:20.791Z" }, - { url = "https://files.pythonhosted.org/packages/ff/4f/5eb37a681c68d605eb7034c004875c81f86ec9ef51f5be4a63eadd58859a/pillow-12.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:97e9993d5ed946aba26baf9c1e8cf18adbab584b99f452ee72f7ee8acb882796", size = 4138546, upload-time = "2026-01-02T09:12:23.664Z" }, - { url = "https://files.pythonhosted.org/packages/11/6d/19a95acb2edbace40dcd582d077b991646b7083c41b98da4ed7555b59733/pillow-12.1.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:414b9a78e14ffeb98128863314e62c3f24b8a86081066625700b7985b3f529bd", size = 3601163, upload-time = "2026-01-02T09:12:26.338Z" }, - { url = "https://files.pythonhosted.org/packages/fc/36/2b8138e51cb42e4cc39c3297713455548be855a50558c3ac2beebdc251dd/pillow-12.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e6bdb408f7c9dd2a5ff2b14a3b0bb6d4deb29fb9961e6eb3ae2031ae9a5cec13", size = 5266086, upload-time = "2026-01-02T09:12:28.782Z" }, - { url = "https://files.pythonhosted.org/packages/53/4b/649056e4d22e1caa90816bf99cef0884aed607ed38075bd75f091a607a38/pillow-12.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3413c2ae377550f5487991d444428f1a8ae92784aac79caa8b1e3b89b175f77e", size = 4657344, upload-time = "2026-01-02T09:12:31.117Z" }, - { url = "https://files.pythonhosted.org/packages/6c/6b/c5742cea0f1ade0cd61485dc3d81f05261fc2276f537fbdc00802de56779/pillow-12.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e5dcbe95016e88437ecf33544ba5db21ef1b8dd6e1b434a2cb2a3d605299e643", size = 6232114, upload-time = "2026-01-02T09:12:32.936Z" }, - { url = "https://files.pythonhosted.org/packages/bf/8f/9f521268ce22d63991601aafd3d48d5ff7280a246a1ef62d626d67b44064/pillow-12.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d0a7735df32ccbcc98b98a1ac785cc4b19b580be1bdf0aeb5c03223220ea09d5", size = 8042708, upload-time = "2026-01-02T09:12:34.78Z" }, - { url = "https://files.pythonhosted.org/packages/1a/eb/257f38542893f021502a1bbe0c2e883c90b5cff26cc33b1584a841a06d30/pillow-12.1.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c27407a2d1b96774cbc4a7594129cc027339fd800cd081e44497722ea1179de", size = 6347762, upload-time = "2026-01-02T09:12:36.748Z" }, - { url = "https://files.pythonhosted.org/packages/c4/5a/8ba375025701c09b309e8d5163c5a4ce0102fa86bbf8800eb0d7ac87bc51/pillow-12.1.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15c794d74303828eaa957ff8070846d0efe8c630901a1c753fdc63850e19ecd9", size = 7039265, upload-time = "2026-01-02T09:12:39.082Z" }, - { url = "https://files.pythonhosted.org/packages/cf/dc/cf5e4cdb3db533f539e88a7bbf9f190c64ab8a08a9bc7a4ccf55067872e4/pillow-12.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c990547452ee2800d8506c4150280757f88532f3de2a58e3022e9b179107862a", size = 6462341, upload-time = "2026-01-02T09:12:40.946Z" }, - { url = "https://files.pythonhosted.org/packages/d0/47/0291a25ac9550677e22eda48510cfc4fa4b2ef0396448b7fbdc0a6946309/pillow-12.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b63e13dd27da389ed9475b3d28510f0f954bca0041e8e551b2a4eb1eab56a39a", size = 7165395, upload-time = "2026-01-02T09:12:42.706Z" }, - { url = "https://files.pythonhosted.org/packages/4f/4c/e005a59393ec4d9416be06e6b45820403bb946a778e39ecec62f5b2b991e/pillow-12.1.0-cp314-cp314-win32.whl", hash = "sha256:1a949604f73eb07a8adab38c4fe50791f9919344398bdc8ac6b307f755fc7030", size = 6431413, upload-time = "2026-01-02T09:12:44.944Z" }, - { url = "https://files.pythonhosted.org/packages/1c/af/f23697f587ac5f9095d67e31b81c95c0249cd461a9798a061ed6709b09b5/pillow-12.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:4f9f6a650743f0ddee5593ac9e954ba1bdbc5e150bc066586d4f26127853ab94", size = 7176779, upload-time = "2026-01-02T09:12:46.727Z" }, - { url = "https://files.pythonhosted.org/packages/b3/36/6a51abf8599232f3e9afbd16d52829376a68909fe14efe29084445db4b73/pillow-12.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:808b99604f7873c800c4840f55ff389936ef1948e4e87645eaf3fccbc8477ac4", size = 2543105, upload-time = "2026-01-02T09:12:49.243Z" }, - { url = "https://files.pythonhosted.org/packages/82/54/2e1dd20c8749ff225080d6ba465a0cab4387f5db0d1c5fb1439e2d99923f/pillow-12.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:bc11908616c8a283cf7d664f77411a5ed2a02009b0097ff8abbba5e79128ccf2", size = 5268571, upload-time = "2026-01-02T09:12:51.11Z" }, - { url = "https://files.pythonhosted.org/packages/57/61/571163a5ef86ec0cf30d265ac2a70ae6fc9e28413d1dc94fa37fae6bda89/pillow-12.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:896866d2d436563fa2a43a9d72f417874f16b5545955c54a64941e87c1376c61", size = 4660426, upload-time = "2026-01-02T09:12:52.865Z" }, - { url = "https://files.pythonhosted.org/packages/5e/e1/53ee5163f794aef1bf84243f755ee6897a92c708505350dd1923f4afec48/pillow-12.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8e178e3e99d3c0ea8fc64b88447f7cac8ccf058af422a6cedc690d0eadd98c51", size = 6269908, upload-time = "2026-01-02T09:12:54.884Z" }, - { url = "https://files.pythonhosted.org/packages/bc/0b/b4b4106ff0ee1afa1dc599fde6ab230417f800279745124f6c50bcffed8e/pillow-12.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:079af2fb0c599c2ec144ba2c02766d1b55498e373b3ac64687e43849fbbef5bc", size = 8074733, upload-time = "2026-01-02T09:12:56.802Z" }, - { url = "https://files.pythonhosted.org/packages/19/9f/80b411cbac4a732439e629a26ad3ef11907a8c7fc5377b7602f04f6fe4e7/pillow-12.1.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bdec5e43377761c5dbca620efb69a77f6855c5a379e32ac5b158f54c84212b14", size = 6381431, upload-time = "2026-01-02T09:12:58.823Z" }, - { url = "https://files.pythonhosted.org/packages/8f/b7/d65c45db463b66ecb6abc17c6ba6917a911202a07662247e1355ce1789e7/pillow-12.1.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:565c986f4b45c020f5421a4cea13ef294dde9509a8577f29b2fc5edc7587fff8", size = 7068529, upload-time = "2026-01-02T09:13:00.885Z" }, - { url = "https://files.pythonhosted.org/packages/50/96/dfd4cd726b4a45ae6e3c669fc9e49deb2241312605d33aba50499e9d9bd1/pillow-12.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:43aca0a55ce1eefc0aefa6253661cb54571857b1a7b2964bd8a1e3ef4b729924", size = 6492981, upload-time = "2026-01-02T09:13:03.314Z" }, - { url = "https://files.pythonhosted.org/packages/4d/1c/b5dc52cf713ae46033359c5ca920444f18a6359ce1020dd3e9c553ea5bc6/pillow-12.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0deedf2ea233722476b3a81e8cdfbad786f7adbed5d848469fa59fe52396e4ef", size = 7191878, upload-time = "2026-01-02T09:13:05.276Z" }, - { url = "https://files.pythonhosted.org/packages/53/26/c4188248bd5edaf543864fe4834aebe9c9cb4968b6f573ce014cc42d0720/pillow-12.1.0-cp314-cp314t-win32.whl", hash = "sha256:b17fbdbe01c196e7e159aacb889e091f28e61020a8abeac07b68079b6e626988", size = 6438703, upload-time = "2026-01-02T09:13:07.491Z" }, - { url = "https://files.pythonhosted.org/packages/b8/0e/69ed296de8ea05cb03ee139cee600f424ca166e632567b2d66727f08c7ed/pillow-12.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27b9baecb428899db6c0de572d6d305cfaf38ca1596b5c0542a5182e3e74e8c6", size = 7182927, upload-time = "2026-01-02T09:13:09.841Z" }, - { url = "https://files.pythonhosted.org/packages/fc/f5/68334c015eed9b5cff77814258717dec591ded209ab5b6fb70e2ae873d1d/pillow-12.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:f61333d817698bdcdd0f9d7793e365ac3d2a21c1f1eb02b32ad6aefb8d8ea831", size = 2545104, upload-time = "2026-01-02T09:13:12.068Z" }, -] - -[[package]] -name = "platformdirs" -version = "4.5.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cf/86/0248f086a84f01b37aaec0fa567b397df1a119f73c16f6c7a9aac73ea309/platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda", size = 21715, upload-time = "2025-12-05T13:52:58.638Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/28/3bfe2fa5a7b9c46fe7e13c97bda14c895fb10fa2ebf1d0abb90e0cea7ee1/platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31", size = 18731, upload-time = "2025-12-05T13:52:56.823Z" }, -] - -[[package]] -name = "polars" -version = "1.36.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "polars-runtime-32" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/9f/dc/56f2a90c79a2cb13f9e956eab6385effe54216ae7a2068b3a6406bae4345/polars-1.36.1.tar.gz", hash = "sha256:12c7616a2305559144711ab73eaa18814f7aa898c522e7645014b68f1432d54c", size = 711993, upload-time = "2025-12-10T01:14:53.033Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f6/c6/36a1b874036b49893ecae0ac44a2f63d1a76e6212631a5b2f50a86e0e8af/polars-1.36.1-py3-none-any.whl", hash = "sha256:853c1bbb237add6a5f6d133c15094a9b727d66dd6a4eb91dbb07cdb056b2b8ef", size = 802429, upload-time = "2025-12-10T01:13:53.838Z" }, -] - -[[package]] -name = "polars-runtime-32" -version = "1.36.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/31/df/597c0ef5eb8d761a16d72327846599b57c5d40d7f9e74306fc154aba8c37/polars_runtime_32-1.36.1.tar.gz", hash = "sha256:201c2cfd80ceb5d5cd7b63085b5fd08d6ae6554f922bcb941035e39638528a09", size = 2788751, upload-time = "2025-12-10T01:14:54.172Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e1/ea/871129a2d296966c0925b078a9a93c6c5e7facb1c5eebfcd3d5811aeddc1/polars_runtime_32-1.36.1-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:327b621ca82594f277751f7e23d4b939ebd1be18d54b4cdf7a2f8406cecc18b2", size = 43494311, upload-time = "2025-12-10T01:13:56.096Z" }, - { url = "https://files.pythonhosted.org/packages/d8/76/0038210ad1e526ce5bb2933b13760d6b986b3045eccc1338e661bd656f77/polars_runtime_32-1.36.1-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ab0d1f23084afee2b97de8c37aa3e02ec3569749ae39571bd89e7a8b11ae9e83", size = 39300602, upload-time = "2025-12-10T01:13:59.366Z" }, - { url = "https://files.pythonhosted.org/packages/54/1e/2707bee75a780a953a77a2c59829ee90ef55708f02fc4add761c579bf76e/polars_runtime_32-1.36.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:899b9ad2e47ceb31eb157f27a09dbc2047efbf4969a923a6b1ba7f0412c3e64c", size = 44511780, upload-time = "2025-12-10T01:14:02.285Z" }, - { url = "https://files.pythonhosted.org/packages/11/b2/3fede95feee441be64b4bcb32444679a8fbb7a453a10251583053f6efe52/polars_runtime_32-1.36.1-cp39-abi3-manylinux_2_24_aarch64.whl", hash = "sha256:d9d077bb9df711bc635a86540df48242bb91975b353e53ef261c6fae6cb0948f", size = 40688448, upload-time = "2025-12-10T01:14:05.131Z" }, - { url = "https://files.pythonhosted.org/packages/05/0f/e629713a72999939b7b4bfdbf030a32794db588b04fdf3dc977dd8ea6c53/polars_runtime_32-1.36.1-cp39-abi3-win_amd64.whl", hash = "sha256:cc17101f28c9a169ff8b5b8d4977a3683cd403621841623825525f440b564cf0", size = 44464898, upload-time = "2025-12-10T01:14:08.296Z" }, - { url = "https://files.pythonhosted.org/packages/d1/d8/a12e6aa14f63784cead437083319ec7cece0d5bb9a5bfe7678cc6578b52a/polars_runtime_32-1.36.1-cp39-abi3-win_arm64.whl", hash = "sha256:809e73857be71250141225ddd5d2b30c97e6340aeaa0d445f930e01bef6888dc", size = 39798896, upload-time = "2025-12-10T01:14:11.568Z" }, -] - -[[package]] -name = "prometheus-client" -version = "0.24.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f0/58/a794d23feb6b00fc0c72787d7e87d872a6730dd9ed7c7b3e954637d8f280/prometheus_client-0.24.1.tar.gz", hash = "sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9", size = 85616, upload-time = "2026-01-14T15:26:26.965Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl", hash = "sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055", size = 64057, upload-time = "2026-01-14T15:26:24.42Z" }, -] - -[[package]] -name = "prompt-toolkit" -version = "3.0.52" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "wcwidth" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, -] - -[[package]] -name = "psutil" -version = "7.2.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/73/cb/09e5184fb5fc0358d110fc3ca7f6b1d033800734d34cac10f4136cfac10e/psutil-7.2.1.tar.gz", hash = "sha256:f7583aec590485b43ca601dd9cea0dcd65bd7bb21d30ef4ddbf4ea6b5ed1bdd3", size = 490253, upload-time = "2025-12-29T08:26:00.169Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/77/8e/f0c242053a368c2aa89584ecd1b054a18683f13d6e5a318fc9ec36582c94/psutil-7.2.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ba9f33bb525b14c3ea563b2fd521a84d2fa214ec59e3e6a2858f78d0844dd60d", size = 129624, upload-time = "2025-12-29T08:26:04.255Z" }, - { url = "https://files.pythonhosted.org/packages/26/97/a58a4968f8990617decee234258a2b4fc7cd9e35668387646c1963e69f26/psutil-7.2.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:81442dac7abfc2f4f4385ea9e12ddf5a796721c0f6133260687fec5c3780fa49", size = 130132, upload-time = "2025-12-29T08:26:06.228Z" }, - { url = "https://files.pythonhosted.org/packages/db/6d/ed44901e830739af5f72a85fa7ec5ff1edea7f81bfbf4875e409007149bd/psutil-7.2.1-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ea46c0d060491051d39f0d2cff4f98d5c72b288289f57a21556cc7d504db37fc", size = 180612, upload-time = "2025-12-29T08:26:08.276Z" }, - { url = "https://files.pythonhosted.org/packages/c7/65/b628f8459bca4efbfae50d4bf3feaab803de9a160b9d5f3bd9295a33f0c2/psutil-7.2.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:35630d5af80d5d0d49cfc4d64c1c13838baf6717a13effb35869a5919b854cdf", size = 183201, upload-time = "2025-12-29T08:26:10.622Z" }, - { url = "https://files.pythonhosted.org/packages/fb/23/851cadc9764edcc18f0effe7d0bf69f727d4cf2442deb4a9f78d4e4f30f2/psutil-7.2.1-cp313-cp313t-win_amd64.whl", hash = "sha256:923f8653416604e356073e6e0bccbe7c09990acef442def2f5640dd0faa9689f", size = 139081, upload-time = "2025-12-29T08:26:12.483Z" }, - { url = "https://files.pythonhosted.org/packages/59/82/d63e8494ec5758029f31c6cb06d7d161175d8281e91d011a4a441c8a43b5/psutil-7.2.1-cp313-cp313t-win_arm64.whl", hash = "sha256:cfbe6b40ca48019a51827f20d830887b3107a74a79b01ceb8cc8de4ccb17b672", size = 134767, upload-time = "2025-12-29T08:26:14.528Z" }, - { url = "https://files.pythonhosted.org/packages/05/c2/5fb764bd61e40e1fe756a44bd4c21827228394c17414ade348e28f83cd79/psutil-7.2.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:494c513ccc53225ae23eec7fe6e1482f1b8a44674241b54561f755a898650679", size = 129716, upload-time = "2025-12-29T08:26:16.017Z" }, - { url = "https://files.pythonhosted.org/packages/c9/d2/935039c20e06f615d9ca6ca0ab756cf8408a19d298ffaa08666bc18dc805/psutil-7.2.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3fce5f92c22b00cdefd1645aa58ab4877a01679e901555067b1bd77039aa589f", size = 130133, upload-time = "2025-12-29T08:26:18.009Z" }, - { url = "https://files.pythonhosted.org/packages/77/69/19f1eb0e01d24c2b3eacbc2f78d3b5add8a89bf0bb69465bc8d563cc33de/psutil-7.2.1-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93f3f7b0bb07711b49626e7940d6fe52aa9940ad86e8f7e74842e73189712129", size = 181518, upload-time = "2025-12-29T08:26:20.241Z" }, - { url = "https://files.pythonhosted.org/packages/e1/6d/7e18b1b4fa13ad370787626c95887b027656ad4829c156bb6569d02f3262/psutil-7.2.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d34d2ca888208eea2b5c68186841336a7f5e0b990edec929be909353a202768a", size = 184348, upload-time = "2025-12-29T08:26:22.215Z" }, - { url = "https://files.pythonhosted.org/packages/98/60/1672114392dd879586d60dd97896325df47d9a130ac7401318005aab28ec/psutil-7.2.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2ceae842a78d1603753561132d5ad1b2f8a7979cb0c283f5b52fb4e6e14b1a79", size = 140400, upload-time = "2025-12-29T08:26:23.993Z" }, - { url = "https://files.pythonhosted.org/packages/fb/7b/d0e9d4513c46e46897b46bcfc410d51fc65735837ea57a25170f298326e6/psutil-7.2.1-cp314-cp314t-win_arm64.whl", hash = "sha256:08a2f175e48a898c8eb8eace45ce01777f4785bc744c90aa2cc7f2fa5462a266", size = 135430, upload-time = "2025-12-29T08:26:25.999Z" }, - { url = "https://files.pythonhosted.org/packages/c5/cf/5180eb8c8bdf6a503c6919f1da28328bd1e6b3b1b5b9d5b01ae64f019616/psutil-7.2.1-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b2e953fcfaedcfbc952b44744f22d16575d3aa78eb4f51ae74165b4e96e55f42", size = 128137, upload-time = "2025-12-29T08:26:27.759Z" }, - { url = "https://files.pythonhosted.org/packages/c5/2c/78e4a789306a92ade5000da4f5de3255202c534acdadc3aac7b5458fadef/psutil-7.2.1-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:05cc68dbb8c174828624062e73078e7e35406f4ca2d0866c272c2410d8ef06d1", size = 128947, upload-time = "2025-12-29T08:26:29.548Z" }, - { url = "https://files.pythonhosted.org/packages/29/f8/40e01c350ad9a2b3cb4e6adbcc8a83b17ee50dd5792102b6142385937db5/psutil-7.2.1-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e38404ca2bb30ed7267a46c02f06ff842e92da3bb8c5bfdadbd35a5722314d8", size = 154694, upload-time = "2025-12-29T08:26:32.147Z" }, - { url = "https://files.pythonhosted.org/packages/06/e4/b751cdf839c011a9714a783f120e6a86b7494eb70044d7d81a25a5cd295f/psutil-7.2.1-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab2b98c9fc19f13f59628d94df5cc4cc4844bc572467d113a8b517d634e362c6", size = 156136, upload-time = "2025-12-29T08:26:34.079Z" }, - { url = "https://files.pythonhosted.org/packages/44/ad/bbf6595a8134ee1e94a4487af3f132cef7fce43aef4a93b49912a48c3af7/psutil-7.2.1-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f78baafb38436d5a128f837fab2d92c276dfb48af01a240b861ae02b2413ada8", size = 148108, upload-time = "2025-12-29T08:26:36.225Z" }, - { url = "https://files.pythonhosted.org/packages/1c/15/dd6fd869753ce82ff64dcbc18356093471a5a5adf4f77ed1f805d473d859/psutil-7.2.1-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:99a4cd17a5fdd1f3d014396502daa70b5ec21bf4ffe38393e152f8e449757d67", size = 147402, upload-time = "2025-12-29T08:26:39.21Z" }, - { url = "https://files.pythonhosted.org/packages/34/68/d9317542e3f2b180c4306e3f45d3c922d7e86d8ce39f941bb9e2e9d8599e/psutil-7.2.1-cp37-abi3-win_amd64.whl", hash = "sha256:b1b0671619343aa71c20ff9767eced0483e4fc9e1f489d50923738caf6a03c17", size = 136938, upload-time = "2025-12-29T08:26:41.036Z" }, - { url = "https://files.pythonhosted.org/packages/3e/73/2ce007f4198c80fcf2cb24c169884f833fe93fbc03d55d302627b094ee91/psutil-7.2.1-cp37-abi3-win_arm64.whl", hash = "sha256:0d67c1822c355aa6f7314d92018fb4268a76668a536f133599b91edd48759442", size = 133836, upload-time = "2025-12-29T08:26:43.086Z" }, -] - -[[package]] -name = "ptyprocess" -version = "0.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762, upload-time = "2020-12-28T15:15:30.155Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993, upload-time = "2020-12-28T15:15:28.35Z" }, -] - -[[package]] -name = "pure-eval" -version = "0.2.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752, upload-time = "2024-07-21T12:58:21.801Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" }, -] - -[[package]] -name = "pyarrow" -version = "22.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/30/53/04a7fdc63e6056116c9ddc8b43bc28c12cdd181b85cbeadb79278475f3ae/pyarrow-22.0.0.tar.gz", hash = "sha256:3d600dc583260d845c7d8a6db540339dd883081925da2bd1c5cb808f720b3cd9", size = 1151151, upload-time = "2025-10-24T12:30:00.762Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a6/d6/d0fac16a2963002fc22c8fa75180a838737203d558f0ed3b564c4a54eef5/pyarrow-22.0.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:e6e95176209257803a8b3d0394f21604e796dadb643d2f7ca21b66c9c0b30c9a", size = 34204629, upload-time = "2025-10-24T10:06:20.274Z" }, - { url = "https://files.pythonhosted.org/packages/c6/9c/1d6357347fbae062ad3f17082f9ebc29cc733321e892c0d2085f42a2212b/pyarrow-22.0.0-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:001ea83a58024818826a9e3f89bf9310a114f7e26dfe404a4c32686f97bd7901", size = 35985783, upload-time = "2025-10-24T10:06:27.301Z" }, - { url = "https://files.pythonhosted.org/packages/ff/c0/782344c2ce58afbea010150df07e3a2f5fdad299cd631697ae7bd3bac6e3/pyarrow-22.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:ce20fe000754f477c8a9125543f1936ea5b8867c5406757c224d745ed033e691", size = 45020999, upload-time = "2025-10-24T10:06:35.387Z" }, - { url = "https://files.pythonhosted.org/packages/1b/8b/5362443737a5307a7b67c1017c42cd104213189b4970bf607e05faf9c525/pyarrow-22.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e0a15757fccb38c410947df156f9749ae4a3c89b2393741a50521f39a8cf202a", size = 47724601, upload-time = "2025-10-24T10:06:43.551Z" }, - { url = "https://files.pythonhosted.org/packages/69/4d/76e567a4fc2e190ee6072967cb4672b7d9249ac59ae65af2d7e3047afa3b/pyarrow-22.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cedb9dd9358e4ea1d9bce3665ce0797f6adf97ff142c8e25b46ba9cdd508e9b6", size = 48001050, upload-time = "2025-10-24T10:06:52.284Z" }, - { url = "https://files.pythonhosted.org/packages/01/5e/5653f0535d2a1aef8223cee9d92944cb6bccfee5cf1cd3f462d7cb022790/pyarrow-22.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:252be4a05f9d9185bb8c18e83764ebcfea7185076c07a7a662253af3a8c07941", size = 50307877, upload-time = "2025-10-24T10:07:02.405Z" }, - { url = "https://files.pythonhosted.org/packages/2d/f8/1d0bd75bf9328a3b826e24a16e5517cd7f9fbf8d34a3184a4566ef5a7f29/pyarrow-22.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:a4893d31e5ef780b6edcaf63122df0f8d321088bb0dee4c8c06eccb1ca28d145", size = 27977099, upload-time = "2025-10-24T10:08:07.259Z" }, - { url = "https://files.pythonhosted.org/packages/90/81/db56870c997805bf2b0f6eeeb2d68458bf4654652dccdcf1bf7a42d80903/pyarrow-22.0.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:f7fe3dbe871294ba70d789be16b6e7e52b418311e166e0e3cba9522f0f437fb1", size = 34336685, upload-time = "2025-10-24T10:07:11.47Z" }, - { url = "https://files.pythonhosted.org/packages/1c/98/0727947f199aba8a120f47dfc229eeb05df15bcd7a6f1b669e9f882afc58/pyarrow-22.0.0-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:ba95112d15fd4f1105fb2402c4eab9068f0554435e9b7085924bcfaac2cc306f", size = 36032158, upload-time = "2025-10-24T10:07:18.626Z" }, - { url = "https://files.pythonhosted.org/packages/96/b4/9babdef9c01720a0785945c7cf550e4acd0ebcd7bdd2e6f0aa7981fa85e2/pyarrow-22.0.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:c064e28361c05d72eed8e744c9605cbd6d2bb7481a511c74071fd9b24bc65d7d", size = 44892060, upload-time = "2025-10-24T10:07:26.002Z" }, - { url = "https://files.pythonhosted.org/packages/f8/ca/2f8804edd6279f78a37062d813de3f16f29183874447ef6d1aadbb4efa0f/pyarrow-22.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:6f9762274496c244d951c819348afbcf212714902742225f649cf02823a6a10f", size = 47504395, upload-time = "2025-10-24T10:07:34.09Z" }, - { url = "https://files.pythonhosted.org/packages/b9/f0/77aa5198fd3943682b2e4faaf179a674f0edea0d55d326d83cb2277d9363/pyarrow-22.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a9d9ffdc2ab696f6b15b4d1f7cec6658e1d788124418cb30030afbae31c64746", size = 48066216, upload-time = "2025-10-24T10:07:43.528Z" }, - { url = "https://files.pythonhosted.org/packages/79/87/a1937b6e78b2aff18b706d738c9e46ade5bfcf11b294e39c87706a0089ac/pyarrow-22.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ec1a15968a9d80da01e1d30349b2b0d7cc91e96588ee324ce1b5228175043e95", size = 50288552, upload-time = "2025-10-24T10:07:53.519Z" }, - { url = "https://files.pythonhosted.org/packages/60/ae/b5a5811e11f25788ccfdaa8f26b6791c9807119dffcf80514505527c384c/pyarrow-22.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:bba208d9c7decf9961998edf5c65e3ea4355d5818dd6cd0f6809bec1afb951cc", size = 28262504, upload-time = "2025-10-24T10:08:00.932Z" }, - { url = "https://files.pythonhosted.org/packages/bd/b0/0fa4d28a8edb42b0a7144edd20befd04173ac79819547216f8a9f36f9e50/pyarrow-22.0.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:9bddc2cade6561f6820d4cd73f99a0243532ad506bc510a75a5a65a522b2d74d", size = 34224062, upload-time = "2025-10-24T10:08:14.101Z" }, - { url = "https://files.pythonhosted.org/packages/0f/a8/7a719076b3c1be0acef56a07220c586f25cd24de0e3f3102b438d18ae5df/pyarrow-22.0.0-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:e70ff90c64419709d38c8932ea9fe1cc98415c4f87ea8da81719e43f02534bc9", size = 35990057, upload-time = "2025-10-24T10:08:21.842Z" }, - { url = "https://files.pythonhosted.org/packages/89/3c/359ed54c93b47fb6fe30ed16cdf50e3f0e8b9ccfb11b86218c3619ae50a8/pyarrow-22.0.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:92843c305330aa94a36e706c16209cd4df274693e777ca47112617db7d0ef3d7", size = 45068002, upload-time = "2025-10-24T10:08:29.034Z" }, - { url = "https://files.pythonhosted.org/packages/55/fc/4945896cc8638536ee787a3bd6ce7cec8ec9acf452d78ec39ab328efa0a1/pyarrow-22.0.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:6dda1ddac033d27421c20d7a7943eec60be44e0db4e079f33cc5af3b8280ccde", size = 47737765, upload-time = "2025-10-24T10:08:38.559Z" }, - { url = "https://files.pythonhosted.org/packages/cd/5e/7cb7edeb2abfaa1f79b5d5eb89432356155c8426f75d3753cbcb9592c0fd/pyarrow-22.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:84378110dd9a6c06323b41b56e129c504d157d1a983ce8f5443761eb5256bafc", size = 48048139, upload-time = "2025-10-24T10:08:46.784Z" }, - { url = "https://files.pythonhosted.org/packages/88/c6/546baa7c48185f5e9d6e59277c4b19f30f48c94d9dd938c2a80d4d6b067c/pyarrow-22.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:854794239111d2b88b40b6ef92aa478024d1e5074f364033e73e21e3f76b25e0", size = 50314244, upload-time = "2025-10-24T10:08:55.771Z" }, - { url = "https://files.pythonhosted.org/packages/3c/79/755ff2d145aafec8d347bf18f95e4e81c00127f06d080135dfc86aea417c/pyarrow-22.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:b883fe6fd85adad7932b3271c38ac289c65b7337c2c132e9569f9d3940620730", size = 28757501, upload-time = "2025-10-24T10:09:59.891Z" }, - { url = "https://files.pythonhosted.org/packages/0e/d2/237d75ac28ced3147912954e3c1a174df43a95f4f88e467809118a8165e0/pyarrow-22.0.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:7a820d8ae11facf32585507c11f04e3f38343c1e784c9b5a8b1da5c930547fe2", size = 34355506, upload-time = "2025-10-24T10:09:02.953Z" }, - { url = "https://files.pythonhosted.org/packages/1e/2c/733dfffe6d3069740f98e57ff81007809067d68626c5faef293434d11bd6/pyarrow-22.0.0-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:c6ec3675d98915bf1ec8b3c7986422682f7232ea76cad276f4c8abd5b7319b70", size = 36047312, upload-time = "2025-10-24T10:09:10.334Z" }, - { url = "https://files.pythonhosted.org/packages/7c/2b/29d6e3782dc1f299727462c1543af357a0f2c1d3c160ce199950d9ca51eb/pyarrow-22.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:3e739edd001b04f654b166204fc7a9de896cf6007eaff33409ee9e50ceaff754", size = 45081609, upload-time = "2025-10-24T10:09:18.61Z" }, - { url = "https://files.pythonhosted.org/packages/8d/42/aa9355ecc05997915af1b7b947a7f66c02dcaa927f3203b87871c114ba10/pyarrow-22.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:7388ac685cab5b279a41dfe0a6ccd99e4dbf322edfb63e02fc0443bf24134e91", size = 47703663, upload-time = "2025-10-24T10:09:27.369Z" }, - { url = "https://files.pythonhosted.org/packages/ee/62/45abedde480168e83a1de005b7b7043fd553321c1e8c5a9a114425f64842/pyarrow-22.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f633074f36dbc33d5c05b5dc75371e5660f1dbf9c8b1d95669def05e5425989c", size = 48066543, upload-time = "2025-10-24T10:09:34.908Z" }, - { url = "https://files.pythonhosted.org/packages/84/e9/7878940a5b072e4f3bf998770acafeae13b267f9893af5f6d4ab3904b67e/pyarrow-22.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4c19236ae2402a8663a2c8f21f1870a03cc57f0bef7e4b6eb3238cc82944de80", size = 50288838, upload-time = "2025-10-24T10:09:44.394Z" }, - { url = "https://files.pythonhosted.org/packages/7b/03/f335d6c52b4a4761bcc83499789a1e2e16d9d201a58c327a9b5cc9a41bd9/pyarrow-22.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:0c34fe18094686194f204a3b1787a27456897d8a2d62caf84b61e8dfbc0252ae", size = 29185594, upload-time = "2025-10-24T10:09:53.111Z" }, -] - -[[package]] -name = "pycparser" -version = "3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, -] - -[[package]] -name = "pygments" -version = "2.19.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, -] - -[[package]] -name = "pyogrio" -version = "0.12.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "certifi" }, - { name = "numpy" }, - { name = "packaging" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/49/d4/12f86b1ed09721363da4c09622464b604c851a9223fc0c6b393fb2012208/pyogrio-0.12.1.tar.gz", hash = "sha256:e548ab705bb3e5383693717de1e6c76da97f3762ab92522cb310f93128a75ff1", size = 303289, upload-time = "2025-11-28T19:04:53.341Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/be/56/f56e79f71b84aa9bea25fdde39fab3846841bd7926be96f623eb7253b7e1/pyogrio-0.12.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:ec0e47a5a704e575092b2fd5c83fa0472a1d421e590f94093eb837bb0a11125d", size = 23658483, upload-time = "2025-11-28T19:03:43.567Z" }, - { url = "https://files.pythonhosted.org/packages/66/ac/5559f8a35d58a16cbb2dd7602dd11936ff8796d8c9bf789f14da88764ec3/pyogrio-0.12.1-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:b4c888fc08f388be4dd99dfca5e84a5cdc5994deeec0230cc45144d3460e2b21", size = 25232737, upload-time = "2025-11-28T19:03:45.92Z" }, - { url = "https://files.pythonhosted.org/packages/59/58/925f1c129ddd7cbba8dea4e7609797cea7a76dbc863ac9afd318a679c4b9/pyogrio-0.12.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:73a88436f9962750d782853727897ac2722cac5900d920e39fab3e56d7a6a7f1", size = 31377986, upload-time = "2025-11-28T19:03:48.495Z" }, - { url = "https://files.pythonhosted.org/packages/18/5f/c87034e92847b1844d0e8492a6a8e3301147d32c5e57909397ce64dbedf5/pyogrio-0.12.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:b5d248a0d59fe9bbf9a35690b70004c67830ee0ebe7d4f7bb8ffd8659f684b3a", size = 30915791, upload-time = "2025-11-28T19:03:51.267Z" }, - { url = "https://files.pythonhosted.org/packages/46/35/b874f79d03e9f900012cf609f7fff97b77164f2e14ee5aac282f8a999c1b/pyogrio-0.12.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:0622bc1a186421547660271083079b38d42e6f868802936d8538c0b379f1ab6b", size = 32499754, upload-time = "2025-11-28T19:03:58.776Z" }, - { url = "https://files.pythonhosted.org/packages/c3/c4/705678c9c4200130290b3a104b45c0cc10aaa48fcef3b2585b34e34ab3e1/pyogrio-0.12.1-cp313-cp313-win_amd64.whl", hash = "sha256:207bd60c7ffbcea84584596e3637653aa7095e9ee20fa408f90c7f9460392613", size = 22933945, upload-time = "2025-11-28T19:04:01.551Z" }, - { url = "https://files.pythonhosted.org/packages/f9/e0/d92d4944001330bc87742d43f112d63d12fc89378b6187e62ff3fc1e8e85/pyogrio-0.12.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:1511b39a283fa27cda906cd187a791578942a87a40b6a06697d9b43bb8ac80b0", size = 23692697, upload-time = "2025-11-28T19:04:04.208Z" }, - { url = "https://files.pythonhosted.org/packages/e5/d7/40acbe06d1b1140e3bb27b79e9163776469c1dc785f1be7d9a7fc7b95c87/pyogrio-0.12.1-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:e486cd6aa9ea8a15394a5f84e019d61ec18f257eeeb642348bd68c3d1e57280b", size = 25258083, upload-time = "2025-11-28T19:04:07.121Z" }, - { url = "https://files.pythonhosted.org/packages/87/a1/39fefd9cddd95986700524f43d3093b4350f6e4fc200623c3838424a5080/pyogrio-0.12.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d3f1a19f63bfd1d3042e45f37ad1d6598123a5a604b6c4ba3f38b419273486cd", size = 31368995, upload-time = "2025-11-28T19:04:09.88Z" }, - { url = "https://files.pythonhosted.org/packages/18/d7/da88c566e67d741a03851eb8d01358949d52e0b0fc2cd953582dc6d89ff8/pyogrio-0.12.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:f3dcc59b3316b8a0f59346bcc638a4d69997864a4d21da839192f50c4c92369a", size = 31035589, upload-time = "2025-11-28T19:04:12.993Z" }, - { url = "https://files.pythonhosted.org/packages/11/ac/8f0199f0d31b8ddbc4b4ea1918df8070fdf3e0a63100b898633ec9396224/pyogrio-0.12.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:a0643e041dee3e8e038fce69f52a915ecb486e6d7b674c0f9919f3c9e9629689", size = 32487973, upload-time = "2025-11-28T19:04:16.103Z" }, - { url = "https://files.pythonhosted.org/packages/bd/64/8541a27e9635a335835d234dfaeb19d6c26097fd88224eda7791f83ca98d/pyogrio-0.12.1-cp313-cp313t-win_amd64.whl", hash = "sha256:5881017f29e110d3613819667657844d8e961b747f2d35cf92f273c27af6d068", size = 22987374, upload-time = "2025-11-28T19:04:18.91Z" }, - { url = "https://files.pythonhosted.org/packages/f4/6f/b4d5e285e08c0c60bcc23b50d73038ddc7335d8de79cc25678cd486a3db0/pyogrio-0.12.1-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:5a1b0453d1c9e7b03715dd57296c8f3790acb8b50d7e3b5844b3074a18f50709", size = 23660673, upload-time = "2025-11-28T19:04:21.662Z" }, - { url = "https://files.pythonhosted.org/packages/8d/75/4b29e71489c5551aa1a1c5ca8c5160a60203c94f2f68c87c0e3614d58965/pyogrio-0.12.1-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:e7ee560422239dd09ca7f8284cc8483a8919c30d25f3049bb0249bff4c38dec4", size = 25232194, upload-time = "2025-11-28T19:04:23.975Z" }, - { url = "https://files.pythonhosted.org/packages/89/6e/e9929d2261a07c36301983de2767bcde90d441ab5bf1d767ce56dd07f8b4/pyogrio-0.12.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:648c6f7f5f214d30e6cf493b4af1d59782907ac068af9119ca35f18153d6865a", size = 31336936, upload-time = "2025-11-28T19:04:26.594Z" }, - { url = "https://files.pythonhosted.org/packages/1d/9e/c59941d734ed936d4e5c89b4b99cb5541307cc42b3fd466ee78a1850c177/pyogrio-0.12.1-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:58042584f3fd4cabb0f55d26c1405053f656be8a5c266c38140316a1e981aca0", size = 30902210, upload-time = "2025-11-28T19:04:29.143Z" }, - { url = "https://files.pythonhosted.org/packages/d1/68/cc07320a63f9c2586e60bf11d148b00e12d0e707673bffe609bbdcb7e754/pyogrio-0.12.1-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:b438e38e4ccbaedaa5cb5824ff5de5539315d9b2fde6547c1e816576924ee8ca", size = 32461674, upload-time = "2025-11-28T19:04:31.792Z" }, - { url = "https://files.pythonhosted.org/packages/13/bc/e4522f429c45a3b6ad28185849dd76e5c8718b780883c4795e7ee41841ae/pyogrio-0.12.1-cp314-cp314-win_amd64.whl", hash = "sha256:f1d8d8a2fea3781dc2a05982c050259261ebc0f6c5e03732d6d79d582adf9363", size = 23550575, upload-time = "2025-11-28T19:04:34.556Z" }, - { url = "https://files.pythonhosted.org/packages/bd/ac/34f0664d0e391994a7b68529ae07a96432b2b4926dbac173ddc4ec94d310/pyogrio-0.12.1-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:9fe7286946f35a73e6370dc5855bc7a5e8e7babf9e4a8bad7a3279a1d94c7ea9", size = 23694285, upload-time = "2025-11-28T19:04:37.833Z" }, - { url = "https://files.pythonhosted.org/packages/8a/93/873255529faff1da09d0b27287e85ec805a318c60c0c74fd7df77f94e557/pyogrio-0.12.1-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:2c50345b382f1be801d654ec22c70ee974d6057d4ba7afe984b55f2192bc94ee", size = 25259825, upload-time = "2025-11-28T19:04:40.125Z" }, - { url = "https://files.pythonhosted.org/packages/27/95/4d4c3644695d99c6fa0b0b42f0d6266ae9dfaf64478a3371eaac950bdd02/pyogrio-0.12.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f0db95765ac0ca935c7fe579e29451294e3ab19c317b0c59c31fbe92a69155e0", size = 31371995, upload-time = "2025-11-28T19:04:42.736Z" }, - { url = "https://files.pythonhosted.org/packages/4c/6f/71f6bcca8754c8bf55a4b7153c61c91f8ac5ba992568e9fa3e54a0ee76fd/pyogrio-0.12.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:fc882779075982b93064b3bf3d8642514a6df00d9dd752493b104817072cfb01", size = 31035498, upload-time = "2025-11-28T19:04:45.79Z" }, - { url = "https://files.pythonhosted.org/packages/fd/47/75c1aa165a988347317afab9b938a01ad25dbca559b582ea34473703dc38/pyogrio-0.12.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:806f620e0c54b54dbdd65e9b6368d24f344cda84c9343364b40a57eb3e1c4dca", size = 32496390, upload-time = "2025-11-28T19:04:48.786Z" }, - { url = "https://files.pythonhosted.org/packages/31/93/4641dc5d952f6bdb71dabad2c50e3f8a5d58396cdea6ff8f8a08bfd4f4a6/pyogrio-0.12.1-cp314-cp314t-win_amd64.whl", hash = "sha256:5399f66730978d8852ef5f44dbafa0f738e7f28f4f784349f36830b69a9d2134", size = 23620996, upload-time = "2025-11-28T19:04:51.132Z" }, -] - -[[package]] -name = "pyparsing" -version = "3.3.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/33/c1/1d9de9aeaa1b89b0186e5fe23294ff6517fce1bc69149185577cd31016b2/pyparsing-3.3.1.tar.gz", hash = "sha256:47fad0f17ac1e2cad3de3b458570fbc9b03560aa029ed5e16ee5554da9a2251c", size = 1550512, upload-time = "2025-12-23T03:14:04.391Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/40/2614036cdd416452f5bf98ec037f38a1afb17f327cb8e6b652d4729e0af8/pyparsing-3.3.1-py3-none-any.whl", hash = "sha256:023b5e7e5520ad96642e2c6db4cb683d3970bd640cdf7115049a6e9c3682df82", size = 121793, upload-time = "2025-12-23T03:14:02.103Z" }, -] - -[[package]] -name = "pyproj" -version = "3.7.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "certifi" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/04/90/67bd7260b4ea9b8b20b4f58afef6c223ecb3abf368eb4ec5bc2cdef81b49/pyproj-3.7.2.tar.gz", hash = "sha256:39a0cf1ecc7e282d1d30f36594ebd55c9fae1fda8a2622cee5d100430628f88c", size = 226279, upload-time = "2025-08-14T12:05:42.18Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/be/14/faf1b90d267cea68d7e70662e7f88cefdb1bc890bd596c74b959e0517a72/pyproj-3.7.2-cp313-cp313-macosx_13_0_x86_64.whl", hash = "sha256:19466e529b1b15eeefdf8ff26b06fa745856c044f2f77bf0edbae94078c1dfa1", size = 6214580, upload-time = "2025-08-14T12:04:28.804Z" }, - { url = "https://files.pythonhosted.org/packages/35/48/da9a45b184d375f62667f62eba0ca68569b0bd980a0bb7ffcc1d50440520/pyproj-3.7.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:c79b9b84c4a626c5dc324c0d666be0bfcebd99f7538d66e8898c2444221b3da7", size = 4615388, upload-time = "2025-08-14T12:04:30.553Z" }, - { url = "https://files.pythonhosted.org/packages/5e/e7/d2b459a4a64bca328b712c1b544e109df88e5c800f7c143cfbc404d39bfb/pyproj-3.7.2-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:ceecf374cacca317bc09e165db38ac548ee3cad07c3609442bd70311c59c21aa", size = 9628455, upload-time = "2025-08-14T12:04:32.435Z" }, - { url = "https://files.pythonhosted.org/packages/f8/85/c2b1706e51942de19076eff082f8495e57d5151364e78b5bef4af4a1d94a/pyproj-3.7.2-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:5141a538ffdbe4bfd157421828bb2e07123a90a7a2d6f30fa1462abcfb5ce681", size = 9514269, upload-time = "2025-08-14T12:04:34.599Z" }, - { url = "https://files.pythonhosted.org/packages/34/38/07a9b89ae7467872f9a476883a5bad9e4f4d1219d31060f0f2b282276cbe/pyproj-3.7.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f000841e98ea99acbb7b8ca168d67773b0191de95187228a16110245c5d954d5", size = 10808437, upload-time = "2025-08-14T12:04:36.485Z" }, - { url = "https://files.pythonhosted.org/packages/12/56/fda1daeabbd39dec5b07f67233d09f31facb762587b498e6fc4572be9837/pyproj-3.7.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8115faf2597f281a42ab608ceac346b4eb1383d3b45ab474fd37341c4bf82a67", size = 10745540, upload-time = "2025-08-14T12:04:38.568Z" }, - { url = "https://files.pythonhosted.org/packages/0d/90/c793182cbba65a39a11db2ac6b479fe76c59e6509ae75e5744c344a0da9d/pyproj-3.7.2-cp313-cp313-win32.whl", hash = "sha256:f18c0579dd6be00b970cb1a6719197fceecc407515bab37da0066f0184aafdf3", size = 5896506, upload-time = "2025-08-14T12:04:41.059Z" }, - { url = "https://files.pythonhosted.org/packages/be/0f/747974129cf0d800906f81cd25efd098c96509026e454d4b66868779ab04/pyproj-3.7.2-cp313-cp313-win_amd64.whl", hash = "sha256:bb41c29d5f60854b1075853fe80c58950b398d4ebb404eb532536ac8d2834ed7", size = 6310195, upload-time = "2025-08-14T12:04:42.974Z" }, - { url = "https://files.pythonhosted.org/packages/82/64/fc7598a53172c4931ec6edf5228280663063150625d3f6423b4c20f9daff/pyproj-3.7.2-cp313-cp313-win_arm64.whl", hash = "sha256:2b617d573be4118c11cd96b8891a0b7f65778fa7733ed8ecdb297a447d439100", size = 6230748, upload-time = "2025-08-14T12:04:44.491Z" }, - { url = "https://files.pythonhosted.org/packages/aa/f0/611dd5cddb0d277f94b7af12981f56e1441bf8d22695065d4f0df5218498/pyproj-3.7.2-cp313-cp313t-macosx_13_0_x86_64.whl", hash = "sha256:d27b48f0e81beeaa2b4d60c516c3a1cfbb0c7ff6ef71256d8e9c07792f735279", size = 6241729, upload-time = "2025-08-14T12:04:46.274Z" }, - { url = "https://files.pythonhosted.org/packages/15/93/40bd4a6c523ff9965e480870611aed7eda5aa2c6128c6537345a2b77b542/pyproj-3.7.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:55a3610d75023c7b1c6e583e48ef8f62918e85a2ae81300569d9f104d6684bb6", size = 4652497, upload-time = "2025-08-14T12:04:48.203Z" }, - { url = "https://files.pythonhosted.org/packages/1b/ae/7150ead53c117880b35e0d37960d3138fe640a235feb9605cb9386f50bb0/pyproj-3.7.2-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:8d7349182fa622696787cc9e195508d2a41a64765da9b8a6bee846702b9e6220", size = 9942610, upload-time = "2025-08-14T12:04:49.652Z" }, - { url = "https://files.pythonhosted.org/packages/d8/17/7a4a7eafecf2b46ab64e5c08176c20ceb5844b503eaa551bf12ccac77322/pyproj-3.7.2-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:d230b186eb876ed4f29a7c5ee310144c3a0e44e89e55f65fb3607e13f6db337c", size = 9692390, upload-time = "2025-08-14T12:04:51.731Z" }, - { url = "https://files.pythonhosted.org/packages/c3/55/ae18f040f6410f0ea547a21ada7ef3e26e6c82befa125b303b02759c0e9d/pyproj-3.7.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:237499c7862c578d0369e2b8ac56eec550e391a025ff70e2af8417139dabb41c", size = 11047596, upload-time = "2025-08-14T12:04:53.748Z" }, - { url = "https://files.pythonhosted.org/packages/e6/2e/d3fff4d2909473f26ae799f9dda04caa322c417a51ff3b25763f7d03b233/pyproj-3.7.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8c225f5978abd506fd9a78eaaf794435e823c9156091cabaab5374efb29d7f69", size = 10896975, upload-time = "2025-08-14T12:04:55.875Z" }, - { url = "https://files.pythonhosted.org/packages/f2/bc/8fc7d3963d87057b7b51ebe68c1e7c51c23129eee5072ba6b86558544a46/pyproj-3.7.2-cp313-cp313t-win32.whl", hash = "sha256:2da731876d27639ff9d2d81c151f6ab90a1546455fabd93368e753047be344a2", size = 5953057, upload-time = "2025-08-14T12:04:58.466Z" }, - { url = "https://files.pythonhosted.org/packages/cc/27/ea9809966cc47d2d51e6d5ae631ea895f7c7c7b9b3c29718f900a8f7d197/pyproj-3.7.2-cp313-cp313t-win_amd64.whl", hash = "sha256:f54d91ae18dd23b6c0ab48126d446820e725419da10617d86a1b69ada6d881d3", size = 6375414, upload-time = "2025-08-14T12:04:59.861Z" }, - { url = "https://files.pythonhosted.org/packages/5b/f8/1ef0129fba9a555c658e22af68989f35e7ba7b9136f25758809efec0cd6e/pyproj-3.7.2-cp313-cp313t-win_arm64.whl", hash = "sha256:fc52ba896cfc3214dc9f9ca3c0677a623e8fdd096b257c14a31e719d21ff3fdd", size = 6262501, upload-time = "2025-08-14T12:05:01.39Z" }, - { url = "https://files.pythonhosted.org/packages/42/17/c2b050d3f5b71b6edd0d96ae16c990fdc42a5f1366464a5c2772146de33a/pyproj-3.7.2-cp314-cp314-macosx_13_0_x86_64.whl", hash = "sha256:2aaa328605ace41db050d06bac1adc11f01b71fe95c18661497763116c3a0f02", size = 6214541, upload-time = "2025-08-14T12:05:03.166Z" }, - { url = "https://files.pythonhosted.org/packages/03/68/68ada9c8aea96ded09a66cfd9bf87aa6db8c2edebe93f5bf9b66b0143fbc/pyproj-3.7.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:35dccbce8201313c596a970fde90e33605248b66272595c061b511c8100ccc08", size = 4617456, upload-time = "2025-08-14T12:05:04.563Z" }, - { url = "https://files.pythonhosted.org/packages/81/e4/4c50ceca7d0e937977866b02cb64e6ccf4df979a5871e521f9e255df6073/pyproj-3.7.2-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:25b0b7cb0042444c29a164b993c45c1b8013d6c48baa61dc1160d834a277e83b", size = 9615590, upload-time = "2025-08-14T12:05:06.094Z" }, - { url = "https://files.pythonhosted.org/packages/05/1e/ada6fb15a1d75b5bd9b554355a69a798c55a7dcc93b8d41596265c1772e3/pyproj-3.7.2-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:85def3a6388e9ba51f964619aa002a9d2098e77c6454ff47773bb68871024281", size = 9474960, upload-time = "2025-08-14T12:05:07.973Z" }, - { url = "https://files.pythonhosted.org/packages/51/07/9d48ad0a8db36e16f842f2c8a694c1d9d7dcf9137264846bef77585a71f3/pyproj-3.7.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b1bccefec3875ab81eabf49059e2b2ea77362c178b66fd3528c3e4df242f1516", size = 10799478, upload-time = "2025-08-14T12:05:14.102Z" }, - { url = "https://files.pythonhosted.org/packages/85/cf/2f812b529079f72f51ff2d6456b7fef06c01735e5cfd62d54ffb2b548028/pyproj-3.7.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d5371ca114d6990b675247355a801925814eca53e6c4b2f1b5c0a956336ee36e", size = 10710030, upload-time = "2025-08-14T12:05:16.317Z" }, - { url = "https://files.pythonhosted.org/packages/99/9b/4626a19e1f03eba4c0e77b91a6cf0f73aa9cb5d51a22ee385c22812bcc2c/pyproj-3.7.2-cp314-cp314-win32.whl", hash = "sha256:77f066626030f41be543274f5ac79f2a511fe89860ecd0914f22131b40a0ec25", size = 5991181, upload-time = "2025-08-14T12:05:19.492Z" }, - { url = "https://files.pythonhosted.org/packages/04/b2/5a6610554306a83a563080c2cf2c57565563eadd280e15388efa00fb5b33/pyproj-3.7.2-cp314-cp314-win_amd64.whl", hash = "sha256:5a964da1696b8522806f4276ab04ccfff8f9eb95133a92a25900697609d40112", size = 6434721, upload-time = "2025-08-14T12:05:21.022Z" }, - { url = "https://files.pythonhosted.org/packages/ae/ce/6c910ea2e1c74ef673c5d48c482564b8a7824a44c4e35cca2e765b68cfcc/pyproj-3.7.2-cp314-cp314-win_arm64.whl", hash = "sha256:e258ab4dbd3cf627809067c0ba8f9884ea76c8e5999d039fb37a1619c6c3e1f6", size = 6363821, upload-time = "2025-08-14T12:05:22.627Z" }, - { url = "https://files.pythonhosted.org/packages/e4/e4/5532f6f7491812ba782a2177fe9de73fd8e2912b59f46a1d056b84b9b8f2/pyproj-3.7.2-cp314-cp314t-macosx_13_0_x86_64.whl", hash = "sha256:bbbac2f930c6d266f70ec75df35ef851d96fdb3701c674f42fd23a9314573b37", size = 6241773, upload-time = "2025-08-14T12:05:24.577Z" }, - { url = "https://files.pythonhosted.org/packages/20/1f/0938c3f2bbbef1789132d1726d9b0e662f10cfc22522743937f421ad664e/pyproj-3.7.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:b7544e0a3d6339dc9151e9c8f3ea62a936ab7cc446a806ec448bbe86aebb979b", size = 4652537, upload-time = "2025-08-14T12:05:26.391Z" }, - { url = "https://files.pythonhosted.org/packages/c7/a8/488b1ed47d25972f33874f91f09ca8f2227902f05f63a2b80dc73e7b1c97/pyproj-3.7.2-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:f7f5133dca4c703e8acadf6f30bc567d39a42c6af321e7f81975c2518f3ed357", size = 9940864, upload-time = "2025-08-14T12:05:27.985Z" }, - { url = "https://files.pythonhosted.org/packages/c7/cc/7f4c895d0cb98e47b6a85a6d79eaca03eb266129eed2f845125c09cf31ff/pyproj-3.7.2-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:5aff3343038d7426aa5076f07feb88065f50e0502d1b0d7c22ddfdd2c75a3f81", size = 9688868, upload-time = "2025-08-14T12:05:30.425Z" }, - { url = "https://files.pythonhosted.org/packages/b2/b7/c7e306b8bb0f071d9825b753ee4920f066c40fbfcce9372c4f3cfb2fc4ed/pyproj-3.7.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:b0552178c61f2ac1c820d087e8ba6e62b29442debddbb09d51c4bf8acc84d888", size = 11045910, upload-time = "2025-08-14T12:05:32.507Z" }, - { url = "https://files.pythonhosted.org/packages/42/fb/538a4d2df695980e2dde5c04d965fbdd1fe8c20a3194dc4aaa3952a4d1be/pyproj-3.7.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:47d87db2d2c436c5fd0409b34d70bb6cdb875cca2ebe7a9d1c442367b0ab8d59", size = 10895724, upload-time = "2025-08-14T12:05:35.465Z" }, - { url = "https://files.pythonhosted.org/packages/e8/8b/a3f0618b03957de9db5489a04558a8826f43906628bb0b766033aa3b5548/pyproj-3.7.2-cp314-cp314t-win32.whl", hash = "sha256:c9b6f1d8ad3e80a0ee0903a778b6ece7dca1d1d40f6d114ae01bc8ddbad971aa", size = 6056848, upload-time = "2025-08-14T12:05:37.553Z" }, - { url = "https://files.pythonhosted.org/packages/bc/56/413240dd5149dd3291eda55aa55a659da4431244a2fd1319d0ae89407cfb/pyproj-3.7.2-cp314-cp314t-win_amd64.whl", hash = "sha256:1914e29e27933ba6f9822663ee0600f169014a2859f851c054c88cf5ea8a333c", size = 6517676, upload-time = "2025-08-14T12:05:39.126Z" }, - { url = "https://files.pythonhosted.org/packages/15/73/a7141a1a0559bf1a7aa42a11c879ceb19f02f5c6c371c6d57fd86cefd4d1/pyproj-3.7.2-cp314-cp314t-win_arm64.whl", hash = "sha256:d9d25bae416a24397e0d85739f84d323b55f6511e45a522dd7d7eae70d10c7e4", size = 6391844, upload-time = "2025-08-14T12:05:40.745Z" }, -] - -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "six" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, -] - -[[package]] -name = "python-json-logger" -version = "4.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/29/bf/eca6a3d43db1dae7070f70e160ab20b807627ba953663ba07928cdd3dc58/python_json_logger-4.0.0.tar.gz", hash = "sha256:f58e68eb46e1faed27e0f574a55a0455eecd7b8a5b88b85a784519ba3cff047f", size = 17683, upload-time = "2025-10-06T04:15:18.984Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl", hash = "sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2", size = 15548, upload-time = "2025-10-06T04:15:17.553Z" }, -] - -[[package]] -name = "pytz" -version = "2025.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f8/bf/abbd3cdfb8fbc7fb3d4d38d320f2441b1e7cbe29be4f23797b4a2b5d8aac/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", size = 320884, upload-time = "2025-03-25T02:25:00.538Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" }, -] - -[[package]] -name = "pywinpty" -version = "3.0.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f3/bb/a7cc2967c5c4eceb6cc49cfe39447d4bfc56e6c865e7c2249b6eb978935f/pywinpty-3.0.2.tar.gz", hash = "sha256:1505cc4cb248af42cb6285a65c9c2086ee9e7e574078ee60933d5d7fa86fb004", size = 30669, upload-time = "2025-10-03T21:16:29.205Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/fc/19/b757fe28008236a4a713e813283721b8a40aa60cd7d3f83549f2e25a3155/pywinpty-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:18f78b81e4cfee6aabe7ea8688441d30247b73e52cd9657138015c5f4ee13a51", size = 2050057, upload-time = "2025-10-03T21:19:26.732Z" }, - { url = "https://files.pythonhosted.org/packages/cb/44/cbae12ecf6f4fa4129c36871fd09c6bef4f98d5f625ecefb5e2449765508/pywinpty-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:663383ecfab7fc382cc97ea5c4f7f0bb32c2f889259855df6ea34e5df42d305b", size = 2049874, upload-time = "2025-10-03T21:18:53.923Z" }, - { url = "https://files.pythonhosted.org/packages/ca/15/f12c6055e2d7a617d4d5820e8ac4ceaff849da4cb124640ef5116a230771/pywinpty-3.0.2-cp314-cp314-win_amd64.whl", hash = "sha256:28297cecc37bee9f24d8889e47231972d6e9e84f7b668909de54f36ca785029a", size = 2050386, upload-time = "2025-10-03T21:18:50.477Z" }, - { url = "https://files.pythonhosted.org/packages/de/24/c6907c5bb06043df98ad6a0a0ff5db2e0affcecbc3b15c42404393a3f72a/pywinpty-3.0.2-cp314-cp314t-win_amd64.whl", hash = "sha256:34b55ae9a1b671fe3eae071d86618110538e8eaad18fcb1531c0830b91a82767", size = 2049834, upload-time = "2025-10-03T21:19:25.688Z" }, -] - -[[package]] -name = "pyyaml" -version = "6.0.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, - { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, - { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, - { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, - { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, - { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, - { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, - { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, - { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, - { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, - { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, - { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, - { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, - { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, - { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, - { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, - { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, - { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, - { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, - { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, - { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, - { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, - { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, - { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, - { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, - { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, - { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, - { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, -] - -[[package]] -name = "pyzmq" -version = "27.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cffi", marker = "implementation_name == 'pypy'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/04/0b/3c9baedbdf613ecaa7aa07027780b8867f57b6293b6ee50de316c9f3222b/pyzmq-27.1.0.tar.gz", hash = "sha256:ac0765e3d44455adb6ddbf4417dcce460fc40a05978c08efdf2948072f6db540", size = 281750, upload-time = "2025-09-08T23:10:18.157Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:452631b640340c928fa343801b0d07eb0c3789a5ffa843f6e1a9cee0ba4eb4fc", size = 1306279, upload-time = "2025-09-08T23:08:03.807Z" }, - { url = "https://files.pythonhosted.org/packages/e8/5e/c3c49fdd0f535ef45eefcc16934648e9e59dace4a37ee88fc53f6cd8e641/pyzmq-27.1.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1c179799b118e554b66da67d88ed66cd37a169f1f23b5d9f0a231b4e8d44a113", size = 895645, upload-time = "2025-09-08T23:08:05.301Z" }, - { url = "https://files.pythonhosted.org/packages/f8/e5/b0b2504cb4e903a74dcf1ebae157f9e20ebb6ea76095f6cfffea28c42ecd/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3837439b7f99e60312f0c926a6ad437b067356dc2bc2ec96eb395fd0fe804233", size = 652574, upload-time = "2025-09-08T23:08:06.828Z" }, - { url = "https://files.pythonhosted.org/packages/f8/9b/c108cdb55560eaf253f0cbdb61b29971e9fb34d9c3499b0e96e4e60ed8a5/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43ad9a73e3da1fab5b0e7e13402f0b2fb934ae1c876c51d0afff0e7c052eca31", size = 840995, upload-time = "2025-09-08T23:08:08.396Z" }, - { url = "https://files.pythonhosted.org/packages/c2/bb/b79798ca177b9eb0825b4c9998c6af8cd2a7f15a6a1a4272c1d1a21d382f/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0de3028d69d4cdc475bfe47a6128eb38d8bc0e8f4d69646adfbcd840facbac28", size = 1642070, upload-time = "2025-09-08T23:08:09.989Z" }, - { url = "https://files.pythonhosted.org/packages/9c/80/2df2e7977c4ede24c79ae39dcef3899bfc5f34d1ca7a5b24f182c9b7a9ca/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:cf44a7763aea9298c0aa7dbf859f87ed7012de8bda0f3977b6fb1d96745df856", size = 2021121, upload-time = "2025-09-08T23:08:11.907Z" }, - { url = "https://files.pythonhosted.org/packages/46/bd/2d45ad24f5f5ae7e8d01525eb76786fa7557136555cac7d929880519e33a/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f30f395a9e6fbca195400ce833c731e7b64c3919aa481af4d88c3759e0cb7496", size = 1878550, upload-time = "2025-09-08T23:08:13.513Z" }, - { url = "https://files.pythonhosted.org/packages/e6/2f/104c0a3c778d7c2ab8190e9db4f62f0b6957b53c9d87db77c284b69f33ea/pyzmq-27.1.0-cp312-abi3-win32.whl", hash = "sha256:250e5436a4ba13885494412b3da5d518cd0d3a278a1ae640e113c073a5f88edd", size = 559184, upload-time = "2025-09-08T23:08:15.163Z" }, - { url = "https://files.pythonhosted.org/packages/fc/7f/a21b20d577e4100c6a41795842028235998a643b1ad406a6d4163ea8f53e/pyzmq-27.1.0-cp312-abi3-win_amd64.whl", hash = "sha256:9ce490cf1d2ca2ad84733aa1d69ce6855372cb5ce9223802450c9b2a7cba0ccf", size = 619480, upload-time = "2025-09-08T23:08:17.192Z" }, - { url = "https://files.pythonhosted.org/packages/78/c2/c012beae5f76b72f007a9e91ee9401cb88c51d0f83c6257a03e785c81cc2/pyzmq-27.1.0-cp312-abi3-win_arm64.whl", hash = "sha256:75a2f36223f0d535a0c919e23615fc85a1e23b71f40c7eb43d7b1dedb4d8f15f", size = 552993, upload-time = "2025-09-08T23:08:18.926Z" }, - { url = "https://files.pythonhosted.org/packages/60/cb/84a13459c51da6cec1b7b1dc1a47e6db6da50b77ad7fd9c145842750a011/pyzmq-27.1.0-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:93ad4b0855a664229559e45c8d23797ceac03183c7b6f5b4428152a6b06684a5", size = 1122436, upload-time = "2025-09-08T23:08:20.801Z" }, - { url = "https://files.pythonhosted.org/packages/dc/b6/94414759a69a26c3dd674570a81813c46a078767d931a6c70ad29fc585cb/pyzmq-27.1.0-cp313-cp313-android_24_x86_64.whl", hash = "sha256:fbb4f2400bfda24f12f009cba62ad5734148569ff4949b1b6ec3b519444342e6", size = 1156301, upload-time = "2025-09-08T23:08:22.47Z" }, - { url = "https://files.pythonhosted.org/packages/a5/ad/15906493fd40c316377fd8a8f6b1f93104f97a752667763c9b9c1b71d42d/pyzmq-27.1.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:e343d067f7b151cfe4eb3bb796a7752c9d369eed007b91231e817071d2c2fec7", size = 1341197, upload-time = "2025-09-08T23:08:24.286Z" }, - { url = "https://files.pythonhosted.org/packages/14/1d/d343f3ce13db53a54cb8946594e567410b2125394dafcc0268d8dda027e0/pyzmq-27.1.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:08363b2011dec81c354d694bdecaef4770e0ae96b9afea70b3f47b973655cc05", size = 897275, upload-time = "2025-09-08T23:08:26.063Z" }, - { url = "https://files.pythonhosted.org/packages/69/2d/d83dd6d7ca929a2fc67d2c3005415cdf322af7751d773524809f9e585129/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d54530c8c8b5b8ddb3318f481297441af102517602b569146185fa10b63f4fa9", size = 660469, upload-time = "2025-09-08T23:08:27.623Z" }, - { url = "https://files.pythonhosted.org/packages/3e/cd/9822a7af117f4bc0f1952dbe9ef8358eb50a24928efd5edf54210b850259/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f3afa12c392f0a44a2414056d730eebc33ec0926aae92b5ad5cf26ebb6cc128", size = 847961, upload-time = "2025-09-08T23:08:29.672Z" }, - { url = "https://files.pythonhosted.org/packages/9a/12/f003e824a19ed73be15542f172fd0ec4ad0b60cf37436652c93b9df7c585/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c65047adafe573ff023b3187bb93faa583151627bc9c51fc4fb2c561ed689d39", size = 1650282, upload-time = "2025-09-08T23:08:31.349Z" }, - { url = "https://files.pythonhosted.org/packages/d5/4a/e82d788ed58e9a23995cee70dbc20c9aded3d13a92d30d57ec2291f1e8a3/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:90e6e9441c946a8b0a667356f7078d96411391a3b8f80980315455574177ec97", size = 2024468, upload-time = "2025-09-08T23:08:33.543Z" }, - { url = "https://files.pythonhosted.org/packages/d9/94/2da0a60841f757481e402b34bf4c8bf57fa54a5466b965de791b1e6f747d/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:add071b2d25f84e8189aaf0882d39a285b42fa3853016ebab234a5e78c7a43db", size = 1885394, upload-time = "2025-09-08T23:08:35.51Z" }, - { url = "https://files.pythonhosted.org/packages/4f/6f/55c10e2e49ad52d080dc24e37adb215e5b0d64990b57598abc2e3f01725b/pyzmq-27.1.0-cp313-cp313t-win32.whl", hash = "sha256:7ccc0700cfdf7bd487bea8d850ec38f204478681ea02a582a8da8171b7f90a1c", size = 574964, upload-time = "2025-09-08T23:08:37.178Z" }, - { url = "https://files.pythonhosted.org/packages/87/4d/2534970ba63dd7c522d8ca80fb92777f362c0f321900667c615e2067cb29/pyzmq-27.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:8085a9fba668216b9b4323be338ee5437a235fe275b9d1610e422ccc279733e2", size = 641029, upload-time = "2025-09-08T23:08:40.595Z" }, - { url = "https://files.pythonhosted.org/packages/f6/fa/f8aea7a28b0641f31d40dea42d7ef003fded31e184ef47db696bc74cd610/pyzmq-27.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:6bb54ca21bcfe361e445256c15eedf083f153811c37be87e0514934d6913061e", size = 561541, upload-time = "2025-09-08T23:08:42.668Z" }, - { url = "https://files.pythonhosted.org/packages/87/45/19efbb3000956e82d0331bafca5d9ac19ea2857722fa2caacefb6042f39d/pyzmq-27.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:ce980af330231615756acd5154f29813d553ea555485ae712c491cd483df6b7a", size = 1341197, upload-time = "2025-09-08T23:08:44.973Z" }, - { url = "https://files.pythonhosted.org/packages/48/43/d72ccdbf0d73d1343936296665826350cb1e825f92f2db9db3e61c2162a2/pyzmq-27.1.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1779be8c549e54a1c38f805e56d2a2e5c009d26de10921d7d51cfd1c8d4632ea", size = 897175, upload-time = "2025-09-08T23:08:46.601Z" }, - { url = "https://files.pythonhosted.org/packages/2f/2e/a483f73a10b65a9ef0161e817321d39a770b2acf8bcf3004a28d90d14a94/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7200bb0f03345515df50d99d3db206a0a6bee1955fbb8c453c76f5bf0e08fb96", size = 660427, upload-time = "2025-09-08T23:08:48.187Z" }, - { url = "https://files.pythonhosted.org/packages/f5/d2/5f36552c2d3e5685abe60dfa56f91169f7a2d99bbaf67c5271022ab40863/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01c0e07d558b06a60773744ea6251f769cd79a41a97d11b8bf4ab8f034b0424d", size = 847929, upload-time = "2025-09-08T23:08:49.76Z" }, - { url = "https://files.pythonhosted.org/packages/c4/2a/404b331f2b7bf3198e9945f75c4c521f0c6a3a23b51f7a4a401b94a13833/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:80d834abee71f65253c91540445d37c4c561e293ba6e741b992f20a105d69146", size = 1650193, upload-time = "2025-09-08T23:08:51.7Z" }, - { url = "https://files.pythonhosted.org/packages/1c/0b/f4107e33f62a5acf60e3ded67ed33d79b4ce18de432625ce2fc5093d6388/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:544b4e3b7198dde4a62b8ff6685e9802a9a1ebf47e77478a5eb88eca2a82f2fd", size = 2024388, upload-time = "2025-09-08T23:08:53.393Z" }, - { url = "https://files.pythonhosted.org/packages/0d/01/add31fe76512642fd6e40e3a3bd21f4b47e242c8ba33efb6809e37076d9b/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cedc4c68178e59a4046f97eca31b148ddcf51e88677de1ef4e78cf06c5376c9a", size = 1885316, upload-time = "2025-09-08T23:08:55.702Z" }, - { url = "https://files.pythonhosted.org/packages/c4/59/a5f38970f9bf07cee96128de79590bb354917914a9be11272cfc7ff26af0/pyzmq-27.1.0-cp314-cp314t-win32.whl", hash = "sha256:1f0b2a577fd770aa6f053211a55d1c47901f4d537389a034c690291485e5fe92", size = 587472, upload-time = "2025-09-08T23:08:58.18Z" }, - { url = "https://files.pythonhosted.org/packages/70/d8/78b1bad170f93fcf5e3536e70e8fadac55030002275c9a29e8f5719185de/pyzmq-27.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:19c9468ae0437f8074af379e986c5d3d7d7bfe033506af442e8c879732bedbe0", size = 661401, upload-time = "2025-09-08T23:08:59.802Z" }, - { url = "https://files.pythonhosted.org/packages/81/d6/4bfbb40c9a0b42fc53c7cf442f6385db70b40f74a783130c5d0a5aa62228/pyzmq-27.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dc5dbf68a7857b59473f7df42650c621d7e8923fb03fa74a526890f4d33cc4d7", size = 575170, upload-time = "2025-09-08T23:09:01.418Z" }, -] - -[[package]] -name = "referencing" -version = "0.37.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "attrs" }, - { name = "rpds-py" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" }, -] - -[[package]] -name = "requests" -version = "2.32.5" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "certifi" }, - { name = "charset-normalizer" }, - { name = "idna" }, - { name = "urllib3" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, -] - -[[package]] -name = "rfc3339-validator" -version = "0.1.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "six" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/28/ea/a9387748e2d111c3c2b275ba970b735e04e15cdb1eb30693b6b5708c4dbd/rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b", size = 5513, upload-time = "2021-05-12T16:37:54.178Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa", size = 3490, upload-time = "2021-05-12T16:37:52.536Z" }, -] - -[[package]] -name = "rfc3986-validator" -version = "0.1.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/da/88/f270de456dd7d11dcc808abfa291ecdd3f45ff44e3b549ffa01b126464d0/rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055", size = 6760, upload-time = "2019-10-28T16:00:19.144Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9", size = 4242, upload-time = "2019-10-28T16:00:13.976Z" }, -] - -[[package]] -name = "rfc3987-syntax" -version = "1.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "lark" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/2c/06/37c1a5557acf449e8e406a830a05bf885ac47d33270aec454ef78675008d/rfc3987_syntax-1.1.0.tar.gz", hash = "sha256:717a62cbf33cffdd16dfa3a497d81ce48a660ea691b1ddd7be710c22f00b4a0d", size = 14239, upload-time = "2025-07-18T01:05:05.015Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl", hash = "sha256:6c3d97604e4c5ce9f714898e05401a0445a641cfa276432b0a648c80856f6a3f", size = 8046, upload-time = "2025-07-18T01:05:03.843Z" }, -] - -[[package]] -name = "rpds-py" -version = "0.30.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469, upload-time = "2025-11-30T20:24:38.837Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/dc/d61221eb88ff410de3c49143407f6f3147acf2538c86f2ab7ce65ae7d5f9/rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2", size = 374887, upload-time = "2025-11-30T20:22:41.812Z" }, - { url = "https://files.pythonhosted.org/packages/fd/32/55fb50ae104061dbc564ef15cc43c013dc4a9f4527a1f4d99baddf56fe5f/rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8", size = 358904, upload-time = "2025-11-30T20:22:43.479Z" }, - { url = "https://files.pythonhosted.org/packages/58/70/faed8186300e3b9bdd138d0273109784eea2396c68458ed580f885dfe7ad/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4", size = 389945, upload-time = "2025-11-30T20:22:44.819Z" }, - { url = "https://files.pythonhosted.org/packages/bd/a8/073cac3ed2c6387df38f71296d002ab43496a96b92c823e76f46b8af0543/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136", size = 407783, upload-time = "2025-11-30T20:22:46.103Z" }, - { url = "https://files.pythonhosted.org/packages/77/57/5999eb8c58671f1c11eba084115e77a8899d6e694d2a18f69f0ba471ec8b/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7", size = 515021, upload-time = "2025-11-30T20:22:47.458Z" }, - { url = "https://files.pythonhosted.org/packages/e0/af/5ab4833eadc36c0a8ed2bc5c0de0493c04f6c06de223170bd0798ff98ced/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2", size = 414589, upload-time = "2025-11-30T20:22:48.872Z" }, - { url = "https://files.pythonhosted.org/packages/b7/de/f7192e12b21b9e9a68a6d0f249b4af3fdcdff8418be0767a627564afa1f1/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6", size = 394025, upload-time = "2025-11-30T20:22:50.196Z" }, - { url = "https://files.pythonhosted.org/packages/91/c4/fc70cd0249496493500e7cc2de87504f5aa6509de1e88623431fec76d4b6/rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e", size = 408895, upload-time = "2025-11-30T20:22:51.87Z" }, - { url = "https://files.pythonhosted.org/packages/58/95/d9275b05ab96556fefff73a385813eb66032e4c99f411d0795372d9abcea/rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d", size = 422799, upload-time = "2025-11-30T20:22:53.341Z" }, - { url = "https://files.pythonhosted.org/packages/06/c1/3088fc04b6624eb12a57eb814f0d4997a44b0d208d6cace713033ff1a6ba/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7", size = 572731, upload-time = "2025-11-30T20:22:54.778Z" }, - { url = "https://files.pythonhosted.org/packages/d8/42/c612a833183b39774e8ac8fecae81263a68b9583ee343db33ab571a7ce55/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31", size = 599027, upload-time = "2025-11-30T20:22:56.212Z" }, - { url = "https://files.pythonhosted.org/packages/5f/60/525a50f45b01d70005403ae0e25f43c0384369ad24ffe46e8d9068b50086/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95", size = 563020, upload-time = "2025-11-30T20:22:58.2Z" }, - { url = "https://files.pythonhosted.org/packages/0b/5d/47c4655e9bcd5ca907148535c10e7d489044243cc9941c16ed7cd53be91d/rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d", size = 223139, upload-time = "2025-11-30T20:23:00.209Z" }, - { url = "https://files.pythonhosted.org/packages/f2/e1/485132437d20aa4d3e1d8b3fb5a5e65aa8139f1e097080c2a8443201742c/rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15", size = 240224, upload-time = "2025-11-30T20:23:02.008Z" }, - { url = "https://files.pythonhosted.org/packages/24/95/ffd128ed1146a153d928617b0ef673960130be0009c77d8fbf0abe306713/rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1", size = 230645, upload-time = "2025-11-30T20:23:03.43Z" }, - { url = "https://files.pythonhosted.org/packages/ff/1b/b10de890a0def2a319a2626334a7f0ae388215eb60914dbac8a3bae54435/rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a", size = 364443, upload-time = "2025-11-30T20:23:04.878Z" }, - { url = "https://files.pythonhosted.org/packages/0d/bf/27e39f5971dc4f305a4fb9c672ca06f290f7c4e261c568f3dea16a410d47/rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e", size = 353375, upload-time = "2025-11-30T20:23:06.342Z" }, - { url = "https://files.pythonhosted.org/packages/40/58/442ada3bba6e8e6615fc00483135c14a7538d2ffac30e2d933ccf6852232/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000", size = 383850, upload-time = "2025-11-30T20:23:07.825Z" }, - { url = "https://files.pythonhosted.org/packages/14/14/f59b0127409a33c6ef6f5c1ebd5ad8e32d7861c9c7adfa9a624fc3889f6c/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db", size = 392812, upload-time = "2025-11-30T20:23:09.228Z" }, - { url = "https://files.pythonhosted.org/packages/b3/66/e0be3e162ac299b3a22527e8913767d869e6cc75c46bd844aa43fb81ab62/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2", size = 517841, upload-time = "2025-11-30T20:23:11.186Z" }, - { url = "https://files.pythonhosted.org/packages/3d/55/fa3b9cf31d0c963ecf1ba777f7cf4b2a2c976795ac430d24a1f43d25a6ba/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa", size = 408149, upload-time = "2025-11-30T20:23:12.864Z" }, - { url = "https://files.pythonhosted.org/packages/60/ca/780cf3b1a32b18c0f05c441958d3758f02544f1d613abf9488cd78876378/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083", size = 383843, upload-time = "2025-11-30T20:23:14.638Z" }, - { url = "https://files.pythonhosted.org/packages/82/86/d5f2e04f2aa6247c613da0c1dd87fcd08fa17107e858193566048a1e2f0a/rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9", size = 396507, upload-time = "2025-11-30T20:23:16.105Z" }, - { url = "https://files.pythonhosted.org/packages/4b/9a/453255d2f769fe44e07ea9785c8347edaf867f7026872e76c1ad9f7bed92/rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0", size = 414949, upload-time = "2025-11-30T20:23:17.539Z" }, - { url = "https://files.pythonhosted.org/packages/a3/31/622a86cdc0c45d6df0e9ccb6becdba5074735e7033c20e401a6d9d0e2ca0/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94", size = 565790, upload-time = "2025-11-30T20:23:19.029Z" }, - { url = "https://files.pythonhosted.org/packages/1c/5d/15bbf0fb4a3f58a3b1c67855ec1efcc4ceaef4e86644665fff03e1b66d8d/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08", size = 590217, upload-time = "2025-11-30T20:23:20.885Z" }, - { url = "https://files.pythonhosted.org/packages/6d/61/21b8c41f68e60c8cc3b2e25644f0e3681926020f11d06ab0b78e3c6bbff1/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27", size = 555806, upload-time = "2025-11-30T20:23:22.488Z" }, - { url = "https://files.pythonhosted.org/packages/f9/39/7e067bb06c31de48de3eb200f9fc7c58982a4d3db44b07e73963e10d3be9/rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6", size = 211341, upload-time = "2025-11-30T20:23:24.449Z" }, - { url = "https://files.pythonhosted.org/packages/0a/4d/222ef0b46443cf4cf46764d9c630f3fe4abaa7245be9417e56e9f52b8f65/rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d", size = 225768, upload-time = "2025-11-30T20:23:25.908Z" }, - { url = "https://files.pythonhosted.org/packages/86/81/dad16382ebbd3d0e0328776d8fd7ca94220e4fa0798d1dc5e7da48cb3201/rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0", size = 362099, upload-time = "2025-11-30T20:23:27.316Z" }, - { url = "https://files.pythonhosted.org/packages/2b/60/19f7884db5d5603edf3c6bce35408f45ad3e97e10007df0e17dd57af18f8/rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be", size = 353192, upload-time = "2025-11-30T20:23:29.151Z" }, - { url = "https://files.pythonhosted.org/packages/bf/c4/76eb0e1e72d1a9c4703c69607cec123c29028bff28ce41588792417098ac/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f", size = 384080, upload-time = "2025-11-30T20:23:30.785Z" }, - { url = "https://files.pythonhosted.org/packages/72/87/87ea665e92f3298d1b26d78814721dc39ed8d2c74b86e83348d6b48a6f31/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f", size = 394841, upload-time = "2025-11-30T20:23:32.209Z" }, - { url = "https://files.pythonhosted.org/packages/77/ad/7783a89ca0587c15dcbf139b4a8364a872a25f861bdb88ed99f9b0dec985/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87", size = 516670, upload-time = "2025-11-30T20:23:33.742Z" }, - { url = "https://files.pythonhosted.org/packages/5b/3c/2882bdac942bd2172f3da574eab16f309ae10a3925644e969536553cb4ee/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18", size = 408005, upload-time = "2025-11-30T20:23:35.253Z" }, - { url = "https://files.pythonhosted.org/packages/ce/81/9a91c0111ce1758c92516a3e44776920b579d9a7c09b2b06b642d4de3f0f/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad", size = 382112, upload-time = "2025-11-30T20:23:36.842Z" }, - { url = "https://files.pythonhosted.org/packages/cf/8e/1da49d4a107027e5fbc64daeab96a0706361a2918da10cb41769244b805d/rpds_py-0.30.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07", size = 399049, upload-time = "2025-11-30T20:23:38.343Z" }, - { url = "https://files.pythonhosted.org/packages/df/5a/7ee239b1aa48a127570ec03becbb29c9d5a9eb092febbd1699d567cae859/rpds_py-0.30.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f", size = 415661, upload-time = "2025-11-30T20:23:40.263Z" }, - { url = "https://files.pythonhosted.org/packages/70/ea/caa143cf6b772f823bc7929a45da1fa83569ee49b11d18d0ada7f5ee6fd6/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65", size = 565606, upload-time = "2025-11-30T20:23:42.186Z" }, - { url = "https://files.pythonhosted.org/packages/64/91/ac20ba2d69303f961ad8cf55bf7dbdb4763f627291ba3d0d7d67333cced9/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f", size = 591126, upload-time = "2025-11-30T20:23:44.086Z" }, - { url = "https://files.pythonhosted.org/packages/21/20/7ff5f3c8b00c8a95f75985128c26ba44503fb35b8e0259d812766ea966c7/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53", size = 553371, upload-time = "2025-11-30T20:23:46.004Z" }, - { url = "https://files.pythonhosted.org/packages/72/c7/81dadd7b27c8ee391c132a6b192111ca58d866577ce2d9b0ca157552cce0/rpds_py-0.30.0-cp314-cp314-win32.whl", hash = "sha256:ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed", size = 215298, upload-time = "2025-11-30T20:23:47.696Z" }, - { url = "https://files.pythonhosted.org/packages/3e/d2/1aaac33287e8cfb07aab2e6b8ac1deca62f6f65411344f1433c55e6f3eb8/rpds_py-0.30.0-cp314-cp314-win_amd64.whl", hash = "sha256:95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950", size = 228604, upload-time = "2025-11-30T20:23:49.501Z" }, - { url = "https://files.pythonhosted.org/packages/e8/95/ab005315818cc519ad074cb7784dae60d939163108bd2b394e60dc7b5461/rpds_py-0.30.0-cp314-cp314-win_arm64.whl", hash = "sha256:613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6", size = 222391, upload-time = "2025-11-30T20:23:50.96Z" }, - { url = "https://files.pythonhosted.org/packages/9e/68/154fe0194d83b973cdedcdcc88947a2752411165930182ae41d983dcefa6/rpds_py-0.30.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb", size = 364868, upload-time = "2025-11-30T20:23:52.494Z" }, - { url = "https://files.pythonhosted.org/packages/83/69/8bbc8b07ec854d92a8b75668c24d2abcb1719ebf890f5604c61c9369a16f/rpds_py-0.30.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8", size = 353747, upload-time = "2025-11-30T20:23:54.036Z" }, - { url = "https://files.pythonhosted.org/packages/ab/00/ba2e50183dbd9abcce9497fa5149c62b4ff3e22d338a30d690f9af970561/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7", size = 383795, upload-time = "2025-11-30T20:23:55.556Z" }, - { url = "https://files.pythonhosted.org/packages/05/6f/86f0272b84926bcb0e4c972262f54223e8ecc556b3224d281e6598fc9268/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898", size = 393330, upload-time = "2025-11-30T20:23:57.033Z" }, - { url = "https://files.pythonhosted.org/packages/cb/e9/0e02bb2e6dc63d212641da45df2b0bf29699d01715913e0d0f017ee29438/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e", size = 518194, upload-time = "2025-11-30T20:23:58.637Z" }, - { url = "https://files.pythonhosted.org/packages/ee/ca/be7bca14cf21513bdf9c0606aba17d1f389ea2b6987035eb4f62bd923f25/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419", size = 408340, upload-time = "2025-11-30T20:24:00.2Z" }, - { url = "https://files.pythonhosted.org/packages/c2/c7/736e00ebf39ed81d75544c0da6ef7b0998f8201b369acf842f9a90dc8fce/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551", size = 383765, upload-time = "2025-11-30T20:24:01.759Z" }, - { url = "https://files.pythonhosted.org/packages/4a/3f/da50dfde9956aaf365c4adc9533b100008ed31aea635f2b8d7b627e25b49/rpds_py-0.30.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8", size = 396834, upload-time = "2025-11-30T20:24:03.687Z" }, - { url = "https://files.pythonhosted.org/packages/4e/00/34bcc2565b6020eab2623349efbdec810676ad571995911f1abdae62a3a0/rpds_py-0.30.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5", size = 415470, upload-time = "2025-11-30T20:24:05.232Z" }, - { url = "https://files.pythonhosted.org/packages/8c/28/882e72b5b3e6f718d5453bd4d0d9cf8df36fddeb4ddbbab17869d5868616/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404", size = 565630, upload-time = "2025-11-30T20:24:06.878Z" }, - { url = "https://files.pythonhosted.org/packages/3b/97/04a65539c17692de5b85c6e293520fd01317fd878ea1995f0367d4532fb1/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856", size = 591148, upload-time = "2025-11-30T20:24:08.445Z" }, - { url = "https://files.pythonhosted.org/packages/85/70/92482ccffb96f5441aab93e26c4d66489eb599efdcf96fad90c14bbfb976/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40", size = 556030, upload-time = "2025-11-30T20:24:10.956Z" }, - { url = "https://files.pythonhosted.org/packages/20/53/7c7e784abfa500a2b6b583b147ee4bb5a2b3747a9166bab52fec4b5b5e7d/rpds_py-0.30.0-cp314-cp314t-win32.whl", hash = "sha256:dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0", size = 211570, upload-time = "2025-11-30T20:24:12.735Z" }, - { url = "https://files.pythonhosted.org/packages/d0/02/fa464cdfbe6b26e0600b62c528b72d8608f5cc49f96b8d6e38c95d60c676/rpds_py-0.30.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3", size = 226532, upload-time = "2025-11-30T20:24:14.634Z" }, -] - -[[package]] -name = "scikit-learn" -version = "1.8.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "joblib" }, - { name = "numpy" }, - { name = "scipy" }, - { name = "threadpoolctl" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/0e/d4/40988bf3b8e34feec1d0e6a051446b1f66225f8529b9309becaeef62b6c4/scikit_learn-1.8.0.tar.gz", hash = "sha256:9bccbb3b40e3de10351f8f5068e105d0f4083b1a65fa07b6634fbc401a6287fd", size = 7335585, upload-time = "2025-12-10T07:08:53.618Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/03/aa/e22e0768512ce9255eba34775be2e85c2048da73da1193e841707f8f039c/scikit_learn-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0d6ae97234d5d7079dc0040990a6f7aeb97cb7fa7e8945f1999a429b23569e0a", size = 8513770, upload-time = "2025-12-10T07:08:03.251Z" }, - { url = "https://files.pythonhosted.org/packages/58/37/31b83b2594105f61a381fc74ca19e8780ee923be2d496fcd8d2e1147bd99/scikit_learn-1.8.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:edec98c5e7c128328124a029bceb09eda2d526997780fef8d65e9a69eead963e", size = 8044458, upload-time = "2025-12-10T07:08:05.336Z" }, - { url = "https://files.pythonhosted.org/packages/2d/5a/3f1caed8765f33eabb723596666da4ebbf43d11e96550fb18bdec42b467b/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:74b66d8689d52ed04c271e1329f0c61635bcaf5b926db9b12d58914cdc01fe57", size = 8610341, upload-time = "2025-12-10T07:08:07.732Z" }, - { url = "https://files.pythonhosted.org/packages/38/cf/06896db3f71c75902a8e9943b444a56e727418f6b4b4a90c98c934f51ed4/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8fdf95767f989b0cfedb85f7ed8ca215d4be728031f56ff5a519ee1e3276dc2e", size = 8900022, upload-time = "2025-12-10T07:08:09.862Z" }, - { url = "https://files.pythonhosted.org/packages/1c/f9/9b7563caf3ec8873e17a31401858efab6b39a882daf6c1bfa88879c0aa11/scikit_learn-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:2de443b9373b3b615aec1bb57f9baa6bb3a9bd093f1269ba95c17d870422b271", size = 7989409, upload-time = "2025-12-10T07:08:12.028Z" }, - { url = "https://files.pythonhosted.org/packages/49/bd/1f4001503650e72c4f6009ac0c4413cb17d2d601cef6f71c0453da2732fc/scikit_learn-1.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:eddde82a035681427cbedded4e6eff5e57fa59216c2e3e90b10b19ab1d0a65c3", size = 7619760, upload-time = "2025-12-10T07:08:13.688Z" }, - { url = "https://files.pythonhosted.org/packages/d2/7d/a630359fc9dcc95496588c8d8e3245cc8fd81980251079bc09c70d41d951/scikit_learn-1.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7cc267b6108f0a1499a734167282c00c4ebf61328566b55ef262d48e9849c735", size = 8826045, upload-time = "2025-12-10T07:08:15.215Z" }, - { url = "https://files.pythonhosted.org/packages/cc/56/a0c86f6930cfcd1c7054a2bc417e26960bb88d32444fe7f71d5c2cfae891/scikit_learn-1.8.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:fe1c011a640a9f0791146011dfd3c7d9669785f9fed2b2a5f9e207536cf5c2fd", size = 8420324, upload-time = "2025-12-10T07:08:17.561Z" }, - { url = "https://files.pythonhosted.org/packages/46/1e/05962ea1cebc1cf3876667ecb14c283ef755bf409993c5946ade3b77e303/scikit_learn-1.8.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72358cce49465d140cc4e7792015bb1f0296a9742d5622c67e31399b75468b9e", size = 8680651, upload-time = "2025-12-10T07:08:19.952Z" }, - { url = "https://files.pythonhosted.org/packages/fe/56/a85473cd75f200c9759e3a5f0bcab2d116c92a8a02ee08ccd73b870f8bb4/scikit_learn-1.8.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:80832434a6cc114f5219211eec13dcbc16c2bac0e31ef64c6d346cde3cf054cb", size = 8925045, upload-time = "2025-12-10T07:08:22.11Z" }, - { url = "https://files.pythonhosted.org/packages/cc/b7/64d8cfa896c64435ae57f4917a548d7ac7a44762ff9802f75a79b77cb633/scikit_learn-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ee787491dbfe082d9c3013f01f5991658b0f38aa8177e4cd4bf434c58f551702", size = 8507994, upload-time = "2025-12-10T07:08:23.943Z" }, - { url = "https://files.pythonhosted.org/packages/5e/37/e192ea709551799379958b4c4771ec507347027bb7c942662c7fbeba31cb/scikit_learn-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf97c10a3f5a7543f9b88cbf488d33d175e9146115a451ae34568597ba33dcde", size = 7869518, upload-time = "2025-12-10T07:08:25.71Z" }, - { url = "https://files.pythonhosted.org/packages/24/05/1af2c186174cc92dcab2233f327336058c077d38f6fe2aceb08e6ab4d509/scikit_learn-1.8.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:c22a2da7a198c28dd1a6e1136f19c830beab7fdca5b3e5c8bba8394f8a5c45b3", size = 8528667, upload-time = "2025-12-10T07:08:27.541Z" }, - { url = "https://files.pythonhosted.org/packages/a8/25/01c0af38fe969473fb292bba9dc2b8f9b451f3112ff242c647fee3d0dfe7/scikit_learn-1.8.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:6b595b07a03069a2b1740dc08c2299993850ea81cce4fe19b2421e0c970de6b7", size = 8066524, upload-time = "2025-12-10T07:08:29.822Z" }, - { url = "https://files.pythonhosted.org/packages/be/ce/a0623350aa0b68647333940ee46fe45086c6060ec604874e38e9ab7d8e6c/scikit_learn-1.8.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:29ffc74089f3d5e87dfca4c2c8450f88bdc61b0fc6ed5d267f3988f19a1309f6", size = 8657133, upload-time = "2025-12-10T07:08:31.865Z" }, - { url = "https://files.pythonhosted.org/packages/b8/cb/861b41341d6f1245e6ca80b1c1a8c4dfce43255b03df034429089ca2a2c5/scikit_learn-1.8.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fb65db5d7531bccf3a4f6bec3462223bea71384e2cda41da0f10b7c292b9e7c4", size = 8923223, upload-time = "2025-12-10T07:08:34.166Z" }, - { url = "https://files.pythonhosted.org/packages/76/18/a8def8f91b18cd1ba6e05dbe02540168cb24d47e8dcf69e8d00b7da42a08/scikit_learn-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:56079a99c20d230e873ea40753102102734c5953366972a71d5cb39a32bc40c6", size = 8096518, upload-time = "2025-12-10T07:08:36.339Z" }, - { url = "https://files.pythonhosted.org/packages/d1/77/482076a678458307f0deb44e29891d6022617b2a64c840c725495bee343f/scikit_learn-1.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:3bad7565bc9cf37ce19a7c0d107742b320c1285df7aab1a6e2d28780df167242", size = 7754546, upload-time = "2025-12-10T07:08:38.128Z" }, - { url = "https://files.pythonhosted.org/packages/2d/d1/ef294ca754826daa043b2a104e59960abfab4cf653891037d19dd5b6f3cf/scikit_learn-1.8.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:4511be56637e46c25721e83d1a9cea9614e7badc7040c4d573d75fbe257d6fd7", size = 8848305, upload-time = "2025-12-10T07:08:41.013Z" }, - { url = "https://files.pythonhosted.org/packages/5b/e2/b1f8b05138ee813b8e1a4149f2f0d289547e60851fd1bb268886915adbda/scikit_learn-1.8.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:a69525355a641bf8ef136a7fa447672fb54fe8d60cab5538d9eb7c6438543fb9", size = 8432257, upload-time = "2025-12-10T07:08:42.873Z" }, - { url = "https://files.pythonhosted.org/packages/26/11/c32b2138a85dcb0c99f6afd13a70a951bfdff8a6ab42d8160522542fb647/scikit_learn-1.8.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c2656924ec73e5939c76ac4c8b026fc203b83d8900362eb2599d8aee80e4880f", size = 8678673, upload-time = "2025-12-10T07:08:45.362Z" }, - { url = "https://files.pythonhosted.org/packages/c7/57/51f2384575bdec454f4fe4e7a919d696c9ebce914590abf3e52d47607ab8/scikit_learn-1.8.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15fc3b5d19cc2be65404786857f2e13c70c83dd4782676dd6814e3b89dc8f5b9", size = 8922467, upload-time = "2025-12-10T07:08:47.408Z" }, - { url = "https://files.pythonhosted.org/packages/35/4d/748c9e2872637a57981a04adc038dacaa16ba8ca887b23e34953f0b3f742/scikit_learn-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:00d6f1d66fbcf4eba6e356e1420d33cc06c70a45bb1363cd6f6a8e4ebbbdece2", size = 8774395, upload-time = "2025-12-10T07:08:49.337Z" }, - { url = "https://files.pythonhosted.org/packages/60/22/d7b2ebe4704a5e50790ba089d5c2ae308ab6bb852719e6c3bd4f04c3a363/scikit_learn-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:f28dd15c6bb0b66ba09728cf09fd8736c304be29409bd8445a080c1280619e8c", size = 8002647, upload-time = "2025-12-10T07:08:51.601Z" }, -] - -[[package]] -name = "scipy" -version = "1.16.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "numpy" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/0a/ca/d8ace4f98322d01abcd52d381134344bf7b431eba7ed8b42bdea5a3c2ac9/scipy-1.16.3.tar.gz", hash = "sha256:01e87659402762f43bd2fee13370553a17ada367d42e7487800bf2916535aecb", size = 30597883, upload-time = "2025-10-28T17:38:54.068Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/72/f1/57e8327ab1508272029e27eeef34f2302ffc156b69e7e233e906c2a5c379/scipy-1.16.3-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:d2ec56337675e61b312179a1ad124f5f570c00f920cc75e1000025451b88241c", size = 36617856, upload-time = "2025-10-28T17:33:31.375Z" }, - { url = "https://files.pythonhosted.org/packages/44/13/7e63cfba8a7452eb756306aa2fd9b37a29a323b672b964b4fdeded9a3f21/scipy-1.16.3-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:16b8bc35a4cc24db80a0ec836a9286d0e31b2503cb2fd7ff7fb0e0374a97081d", size = 28874306, upload-time = "2025-10-28T17:33:36.516Z" }, - { url = "https://files.pythonhosted.org/packages/15/65/3a9400efd0228a176e6ec3454b1fa998fbbb5a8defa1672c3f65706987db/scipy-1.16.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:5803c5fadd29de0cf27fa08ccbfe7a9e5d741bf63e4ab1085437266f12460ff9", size = 20865371, upload-time = "2025-10-28T17:33:42.094Z" }, - { url = "https://files.pythonhosted.org/packages/33/d7/eda09adf009a9fb81827194d4dd02d2e4bc752cef16737cc4ef065234031/scipy-1.16.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:b81c27fc41954319a943d43b20e07c40bdcd3ff7cf013f4fb86286faefe546c4", size = 23524877, upload-time = "2025-10-28T17:33:48.483Z" }, - { url = "https://files.pythonhosted.org/packages/7d/6b/3f911e1ebc364cb81320223a3422aab7d26c9c7973109a9cd0f27c64c6c0/scipy-1.16.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0c3b4dd3d9b08dbce0f3440032c52e9e2ab9f96ade2d3943313dfe51a7056959", size = 33342103, upload-time = "2025-10-28T17:33:56.495Z" }, - { url = "https://files.pythonhosted.org/packages/21/f6/4bfb5695d8941e5c570a04d9fcd0d36bce7511b7d78e6e75c8f9791f82d0/scipy-1.16.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7dc1360c06535ea6116a2220f760ae572db9f661aba2d88074fe30ec2aa1ff88", size = 35697297, upload-time = "2025-10-28T17:34:04.722Z" }, - { url = "https://files.pythonhosted.org/packages/04/e1/6496dadbc80d8d896ff72511ecfe2316b50313bfc3ebf07a3f580f08bd8c/scipy-1.16.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:663b8d66a8748051c3ee9c96465fb417509315b99c71550fda2591d7dd634234", size = 36021756, upload-time = "2025-10-28T17:34:13.482Z" }, - { url = "https://files.pythonhosted.org/packages/fe/bd/a8c7799e0136b987bda3e1b23d155bcb31aec68a4a472554df5f0937eef7/scipy-1.16.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eab43fae33a0c39006a88096cd7b4f4ef545ea0447d250d5ac18202d40b6611d", size = 38696566, upload-time = "2025-10-28T17:34:22.384Z" }, - { url = "https://files.pythonhosted.org/packages/cd/01/1204382461fcbfeb05b6161b594f4007e78b6eba9b375382f79153172b4d/scipy-1.16.3-cp313-cp313-win_amd64.whl", hash = "sha256:062246acacbe9f8210de8e751b16fc37458213f124bef161a5a02c7a39284304", size = 38529877, upload-time = "2025-10-28T17:35:51.076Z" }, - { url = "https://files.pythonhosted.org/packages/7f/14/9d9fbcaa1260a94f4bb5b64ba9213ceb5d03cd88841fe9fd1ffd47a45b73/scipy-1.16.3-cp313-cp313-win_arm64.whl", hash = "sha256:50a3dbf286dbc7d84f176f9a1574c705f277cb6565069f88f60db9eafdbe3ee2", size = 25455366, upload-time = "2025-10-28T17:35:59.014Z" }, - { url = "https://files.pythonhosted.org/packages/e2/a3/9ec205bd49f42d45d77f1730dbad9ccf146244c1647605cf834b3a8c4f36/scipy-1.16.3-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:fb4b29f4cf8cc5a8d628bc8d8e26d12d7278cd1f219f22698a378c3d67db5e4b", size = 37027931, upload-time = "2025-10-28T17:34:31.451Z" }, - { url = "https://files.pythonhosted.org/packages/25/06/ca9fd1f3a4589cbd825b1447e5db3a8ebb969c1eaf22c8579bd286f51b6d/scipy-1.16.3-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:8d09d72dc92742988b0e7750bddb8060b0c7079606c0d24a8cc8e9c9c11f9079", size = 29400081, upload-time = "2025-10-28T17:34:39.087Z" }, - { url = "https://files.pythonhosted.org/packages/6a/56/933e68210d92657d93fb0e381683bc0e53a965048d7358ff5fbf9e6a1b17/scipy-1.16.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:03192a35e661470197556de24e7cb1330d84b35b94ead65c46ad6f16f6b28f2a", size = 21391244, upload-time = "2025-10-28T17:34:45.234Z" }, - { url = "https://files.pythonhosted.org/packages/a8/7e/779845db03dc1418e215726329674b40576879b91814568757ff0014ad65/scipy-1.16.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:57d01cb6f85e34f0946b33caa66e892aae072b64b034183f3d87c4025802a119", size = 23929753, upload-time = "2025-10-28T17:34:51.793Z" }, - { url = "https://files.pythonhosted.org/packages/4c/4b/f756cf8161d5365dcdef9e5f460ab226c068211030a175d2fc7f3f41ca64/scipy-1.16.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:96491a6a54e995f00a28a3c3badfff58fd093bf26cd5fb34a2188c8c756a3a2c", size = 33496912, upload-time = "2025-10-28T17:34:59.8Z" }, - { url = "https://files.pythonhosted.org/packages/09/b5/222b1e49a58668f23839ca1542a6322bb095ab8d6590d4f71723869a6c2c/scipy-1.16.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cd13e354df9938598af2be05822c323e97132d5e6306b83a3b4ee6724c6e522e", size = 35802371, upload-time = "2025-10-28T17:35:08.173Z" }, - { url = "https://files.pythonhosted.org/packages/c1/8d/5964ef68bb31829bde27611f8c9deeac13764589fe74a75390242b64ca44/scipy-1.16.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:63d3cdacb8a824a295191a723ee5e4ea7768ca5ca5f2838532d9f2e2b3ce2135", size = 36190477, upload-time = "2025-10-28T17:35:16.7Z" }, - { url = "https://files.pythonhosted.org/packages/ab/f2/b31d75cb9b5fa4dd39a0a931ee9b33e7f6f36f23be5ef560bf72e0f92f32/scipy-1.16.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e7efa2681ea410b10dde31a52b18b0154d66f2485328830e45fdf183af5aefc6", size = 38796678, upload-time = "2025-10-28T17:35:26.354Z" }, - { url = "https://files.pythonhosted.org/packages/b4/1e/b3723d8ff64ab548c38d87055483714fefe6ee20e0189b62352b5e015bb1/scipy-1.16.3-cp313-cp313t-win_amd64.whl", hash = "sha256:2d1ae2cf0c350e7705168ff2429962a89ad90c2d49d1dd300686d8b2a5af22fc", size = 38640178, upload-time = "2025-10-28T17:35:35.304Z" }, - { url = "https://files.pythonhosted.org/packages/8e/f3/d854ff38789aca9b0cc23008d607ced9de4f7ab14fa1ca4329f86b3758ca/scipy-1.16.3-cp313-cp313t-win_arm64.whl", hash = "sha256:0c623a54f7b79dd88ef56da19bc2873afec9673a48f3b85b18e4d402bdd29a5a", size = 25803246, upload-time = "2025-10-28T17:35:42.155Z" }, - { url = "https://files.pythonhosted.org/packages/99/f6/99b10fd70f2d864c1e29a28bbcaa0c6340f9d8518396542d9ea3b4aaae15/scipy-1.16.3-cp314-cp314-macosx_10_14_x86_64.whl", hash = "sha256:875555ce62743e1d54f06cdf22c1e0bc47b91130ac40fe5d783b6dfa114beeb6", size = 36606469, upload-time = "2025-10-28T17:36:08.741Z" }, - { url = "https://files.pythonhosted.org/packages/4d/74/043b54f2319f48ea940dd025779fa28ee360e6b95acb7cd188fad4391c6b/scipy-1.16.3-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:bb61878c18a470021fb515a843dc7a76961a8daceaaaa8bad1332f1bf4b54657", size = 28872043, upload-time = "2025-10-28T17:36:16.599Z" }, - { url = "https://files.pythonhosted.org/packages/4d/e1/24b7e50cc1c4ee6ffbcb1f27fe9f4c8b40e7911675f6d2d20955f41c6348/scipy-1.16.3-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:f2622206f5559784fa5c4b53a950c3c7c1cf3e84ca1b9c4b6c03f062f289ca26", size = 20862952, upload-time = "2025-10-28T17:36:22.966Z" }, - { url = "https://files.pythonhosted.org/packages/dd/3a/3e8c01a4d742b730df368e063787c6808597ccb38636ed821d10b39ca51b/scipy-1.16.3-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:7f68154688c515cdb541a31ef8eb66d8cd1050605be9dcd74199cbd22ac739bc", size = 23508512, upload-time = "2025-10-28T17:36:29.731Z" }, - { url = "https://files.pythonhosted.org/packages/1f/60/c45a12b98ad591536bfe5330cb3cfe1850d7570259303563b1721564d458/scipy-1.16.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8b3c820ddb80029fe9f43d61b81d8b488d3ef8ca010d15122b152db77dc94c22", size = 33413639, upload-time = "2025-10-28T17:36:37.982Z" }, - { url = "https://files.pythonhosted.org/packages/71/bc/35957d88645476307e4839712642896689df442f3e53b0fa016ecf8a3357/scipy-1.16.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d3837938ae715fc0fe3c39c0202de3a8853aff22ca66781ddc2ade7554b7e2cc", size = 35704729, upload-time = "2025-10-28T17:36:46.547Z" }, - { url = "https://files.pythonhosted.org/packages/3b/15/89105e659041b1ca11c386e9995aefacd513a78493656e57789f9d9eab61/scipy-1.16.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:aadd23f98f9cb069b3bd64ddc900c4d277778242e961751f77a8cb5c4b946fb0", size = 36086251, upload-time = "2025-10-28T17:36:55.161Z" }, - { url = "https://files.pythonhosted.org/packages/1a/87/c0ea673ac9c6cc50b3da2196d860273bc7389aa69b64efa8493bdd25b093/scipy-1.16.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b7c5f1bda1354d6a19bc6af73a649f8285ca63ac6b52e64e658a5a11d4d69800", size = 38716681, upload-time = "2025-10-28T17:37:04.1Z" }, - { url = "https://files.pythonhosted.org/packages/91/06/837893227b043fb9b0d13e4bd7586982d8136cb249ffb3492930dab905b8/scipy-1.16.3-cp314-cp314-win_amd64.whl", hash = "sha256:e5d42a9472e7579e473879a1990327830493a7047506d58d73fc429b84c1d49d", size = 39358423, upload-time = "2025-10-28T17:38:20.005Z" }, - { url = "https://files.pythonhosted.org/packages/95/03/28bce0355e4d34a7c034727505a02d19548549e190bedd13a721e35380b7/scipy-1.16.3-cp314-cp314-win_arm64.whl", hash = "sha256:6020470b9d00245926f2d5bb93b119ca0340f0d564eb6fbaad843eaebf9d690f", size = 26135027, upload-time = "2025-10-28T17:38:24.966Z" }, - { url = "https://files.pythonhosted.org/packages/b2/6f/69f1e2b682efe9de8fe9f91040f0cd32f13cfccba690512ba4c582b0bc29/scipy-1.16.3-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:e1d27cbcb4602680a49d787d90664fa4974063ac9d4134813332a8c53dbe667c", size = 37028379, upload-time = "2025-10-28T17:37:14.061Z" }, - { url = "https://files.pythonhosted.org/packages/7c/2d/e826f31624a5ebbab1cd93d30fd74349914753076ed0593e1d56a98c4fb4/scipy-1.16.3-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:9b9c9c07b6d56a35777a1b4cc8966118fb16cfd8daf6743867d17d36cfad2d40", size = 29400052, upload-time = "2025-10-28T17:37:21.709Z" }, - { url = "https://files.pythonhosted.org/packages/69/27/d24feb80155f41fd1f156bf144e7e049b4e2b9dd06261a242905e3bc7a03/scipy-1.16.3-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:3a4c460301fb2cffb7f88528f30b3127742cff583603aa7dc964a52c463b385d", size = 21391183, upload-time = "2025-10-28T17:37:29.559Z" }, - { url = "https://files.pythonhosted.org/packages/f8/d3/1b229e433074c5738a24277eca520a2319aac7465eea7310ea6ae0e98ae2/scipy-1.16.3-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:f667a4542cc8917af1db06366d3f78a5c8e83badd56409f94d1eac8d8d9133fa", size = 23930174, upload-time = "2025-10-28T17:37:36.306Z" }, - { url = "https://files.pythonhosted.org/packages/16/9d/d9e148b0ec680c0f042581a2be79a28a7ab66c0c4946697f9e7553ead337/scipy-1.16.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f379b54b77a597aa7ee5e697df0d66903e41b9c85a6dd7946159e356319158e8", size = 33497852, upload-time = "2025-10-28T17:37:42.228Z" }, - { url = "https://files.pythonhosted.org/packages/2f/22/4e5f7561e4f98b7bea63cf3fd7934bff1e3182e9f1626b089a679914d5c8/scipy-1.16.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4aff59800a3b7f786b70bfd6ab551001cb553244988d7d6b8299cb1ea653b353", size = 35798595, upload-time = "2025-10-28T17:37:48.102Z" }, - { url = "https://files.pythonhosted.org/packages/83/42/6644d714c179429fc7196857866f219fef25238319b650bb32dde7bf7a48/scipy-1.16.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:da7763f55885045036fabcebd80144b757d3db06ab0861415d1c3b7c69042146", size = 36186269, upload-time = "2025-10-28T17:37:53.72Z" }, - { url = "https://files.pythonhosted.org/packages/ac/70/64b4d7ca92f9cf2e6fc6aaa2eecf80bb9b6b985043a9583f32f8177ea122/scipy-1.16.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ffa6eea95283b2b8079b821dc11f50a17d0571c92b43e2b5b12764dc5f9b285d", size = 38802779, upload-time = "2025-10-28T17:37:59.393Z" }, - { url = "https://files.pythonhosted.org/packages/61/82/8d0e39f62764cce5ffd5284131e109f07cf8955aef9ab8ed4e3aa5e30539/scipy-1.16.3-cp314-cp314t-win_amd64.whl", hash = "sha256:d9f48cafc7ce94cf9b15c6bffdc443a81a27bf7075cf2dcd5c8b40f85d10c4e7", size = 39471128, upload-time = "2025-10-28T17:38:05.259Z" }, - { url = "https://files.pythonhosted.org/packages/64/47/a494741db7280eae6dc033510c319e34d42dd41b7ac0c7ead39354d1a2b5/scipy-1.16.3-cp314-cp314t-win_arm64.whl", hash = "sha256:21d9d6b197227a12dcbf9633320a4e34c6b0e51c57268df255a0942983bac562", size = 26464127, upload-time = "2025-10-28T17:38:11.34Z" }, -] - -[[package]] -name = "seaborn" -version = "0.13.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "matplotlib" }, - { name = "numpy" }, - { name = "pandas" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/86/59/a451d7420a77ab0b98f7affa3a1d78a313d2f7281a57afb1a34bae8ab412/seaborn-0.13.2.tar.gz", hash = "sha256:93e60a40988f4d65e9f4885df477e2fdaff6b73a9ded434c1ab356dd57eefff7", size = 1457696, upload-time = "2024-01-25T13:21:52.551Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/83/11/00d3c3dfc25ad54e731d91449895a79e4bf2384dc3ac01809010ba88f6d5/seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987", size = 294914, upload-time = "2024-01-25T13:21:49.598Z" }, -] - -[[package]] -name = "send2trash" -version = "2.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c5/f0/184b4b5f8d00f2a92cf96eec8967a3d550b52cf94362dad1100df9e48d57/send2trash-2.1.0.tar.gz", hash = "sha256:1c72b39f09457db3c05ce1d19158c2cbef4c32b8bedd02c155e49282b7ea7459", size = 17255, upload-time = "2026-01-14T06:27:36.056Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1c/78/504fdd027da3b84ff1aecd9f6957e65f35134534ccc6da8628eb71e76d3f/send2trash-2.1.0-py3-none-any.whl", hash = "sha256:0da2f112e6d6bb22de6aa6daa7e144831a4febf2a87261451c4ad849fe9a873c", size = 17610, upload-time = "2026-01-14T06:27:35.218Z" }, -] - -[[package]] -name = "setuptools" -version = "80.10.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/86/ff/f75651350db3cf2ef767371307eb163f3cc1ac03e16fdf3ac347607f7edb/setuptools-80.10.1.tar.gz", hash = "sha256:bf2e513eb8144c3298a3bd28ab1a5edb739131ec5c22e045ff93cd7f5319703a", size = 1229650, upload-time = "2026-01-21T09:42:03.061Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e0/76/f963c61683a39084aa575f98089253e1e852a4417cb8a3a8a422923a5246/setuptools-80.10.1-py3-none-any.whl", hash = "sha256:fc30c51cbcb8199a219c12cc9c281b5925a4978d212f84229c909636d9f6984e", size = 1099859, upload-time = "2026-01-21T09:42:00.688Z" }, -] - -[[package]] -name = "shapely" -version = "2.1.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "numpy" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/4d/bc/0989043118a27cccb4e906a46b7565ce36ca7b57f5a18b78f4f1b0f72d9d/shapely-2.1.2.tar.gz", hash = "sha256:2ed4ecb28320a433db18a5bf029986aa8afcfd740745e78847e330d5d94922a9", size = 315489, upload-time = "2025-09-24T13:51:41.432Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c3/90/98ef257c23c46425dc4d1d31005ad7c8d649fe423a38b917db02c30f1f5a/shapely-2.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b510dda1a3672d6879beb319bc7c5fd302c6c354584690973c838f46ec3e0fa8", size = 1832644, upload-time = "2025-09-24T13:50:44.886Z" }, - { url = "https://files.pythonhosted.org/packages/6d/ab/0bee5a830d209adcd3a01f2d4b70e587cdd9fd7380d5198c064091005af8/shapely-2.1.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8cff473e81017594d20ec55d86b54bc635544897e13a7cfc12e36909c5309a2a", size = 1642887, upload-time = "2025-09-24T13:50:46.735Z" }, - { url = "https://files.pythonhosted.org/packages/2d/5e/7d7f54ba960c13302584c73704d8c4d15404a51024631adb60b126a4ae88/shapely-2.1.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fe7b77dc63d707c09726b7908f575fc04ff1d1ad0f3fb92aec212396bc6cfe5e", size = 2970931, upload-time = "2025-09-24T13:50:48.374Z" }, - { url = "https://files.pythonhosted.org/packages/f2/a2/83fc37e2a58090e3d2ff79175a95493c664bcd0b653dd75cb9134645a4e5/shapely-2.1.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7ed1a5bbfb386ee8332713bf7508bc24e32d24b74fc9a7b9f8529a55db9f4ee6", size = 3082855, upload-time = "2025-09-24T13:50:50.037Z" }, - { url = "https://files.pythonhosted.org/packages/44/2b/578faf235a5b09f16b5f02833c53822294d7f21b242f8e2d0cf03fb64321/shapely-2.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a84e0582858d841d54355246ddfcbd1fce3179f185da7470f41ce39d001ee1af", size = 3979960, upload-time = "2025-09-24T13:50:51.74Z" }, - { url = "https://files.pythonhosted.org/packages/4d/04/167f096386120f692cc4ca02f75a17b961858997a95e67a3cb6a7bbd6b53/shapely-2.1.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dc3487447a43d42adcdf52d7ac73804f2312cbfa5d433a7d2c506dcab0033dfd", size = 4142851, upload-time = "2025-09-24T13:50:53.49Z" }, - { url = "https://files.pythonhosted.org/packages/48/74/fb402c5a6235d1c65a97348b48cdedb75fb19eca2b1d66d04969fc1c6091/shapely-2.1.2-cp313-cp313-win32.whl", hash = "sha256:9c3a3c648aedc9f99c09263b39f2d8252f199cb3ac154fadc173283d7d111350", size = 1541890, upload-time = "2025-09-24T13:50:55.337Z" }, - { url = "https://files.pythonhosted.org/packages/41/47/3647fe7ad990af60ad98b889657a976042c9988c2807cf322a9d6685f462/shapely-2.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:ca2591bff6645c216695bdf1614fca9c82ea1144d4a7591a466fef64f28f0715", size = 1722151, upload-time = "2025-09-24T13:50:57.153Z" }, - { url = "https://files.pythonhosted.org/packages/3c/49/63953754faa51ffe7d8189bfbe9ca34def29f8c0e34c67cbe2a2795f269d/shapely-2.1.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2d93d23bdd2ed9dc157b46bc2f19b7da143ca8714464249bef6771c679d5ff40", size = 1834130, upload-time = "2025-09-24T13:50:58.49Z" }, - { url = "https://files.pythonhosted.org/packages/7f/ee/dce001c1984052970ff60eb4727164892fb2d08052c575042a47f5a9e88f/shapely-2.1.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:01d0d304b25634d60bd7cf291828119ab55a3bab87dc4af1e44b07fb225f188b", size = 1642802, upload-time = "2025-09-24T13:50:59.871Z" }, - { url = "https://files.pythonhosted.org/packages/da/e7/fc4e9a19929522877fa602f705706b96e78376afb7fad09cad5b9af1553c/shapely-2.1.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8d8382dd120d64b03698b7298b89611a6ea6f55ada9d39942838b79c9bc89801", size = 3018460, upload-time = "2025-09-24T13:51:02.08Z" }, - { url = "https://files.pythonhosted.org/packages/a1/18/7519a25db21847b525696883ddc8e6a0ecaa36159ea88e0fef11466384d0/shapely-2.1.2-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:19efa3611eef966e776183e338b2d7ea43569ae99ab34f8d17c2c054d3205cc0", size = 3095223, upload-time = "2025-09-24T13:51:04.472Z" }, - { url = "https://files.pythonhosted.org/packages/48/de/b59a620b1f3a129c3fecc2737104a0a7e04e79335bd3b0a1f1609744cf17/shapely-2.1.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:346ec0c1a0fcd32f57f00e4134d1200e14bf3f5ae12af87ba83ca275c502498c", size = 4030760, upload-time = "2025-09-24T13:51:06.455Z" }, - { url = "https://files.pythonhosted.org/packages/96/b3/c6655ee7232b417562bae192ae0d3ceaadb1cc0ffc2088a2ddf415456cc2/shapely-2.1.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6305993a35989391bd3476ee538a5c9a845861462327efe00dd11a5c8c709a99", size = 4170078, upload-time = "2025-09-24T13:51:08.584Z" }, - { url = "https://files.pythonhosted.org/packages/a0/8e/605c76808d73503c9333af8f6cbe7e1354d2d238bda5f88eea36bfe0f42a/shapely-2.1.2-cp313-cp313t-win32.whl", hash = "sha256:c8876673449f3401f278c86eb33224c5764582f72b653a415d0e6672fde887bf", size = 1559178, upload-time = "2025-09-24T13:51:10.73Z" }, - { url = "https://files.pythonhosted.org/packages/36/f7/d317eb232352a1f1444d11002d477e54514a4a6045536d49d0c59783c0da/shapely-2.1.2-cp313-cp313t-win_amd64.whl", hash = "sha256:4a44bc62a10d84c11a7a3d7c1c4fe857f7477c3506e24c9062da0db0ae0c449c", size = 1739756, upload-time = "2025-09-24T13:51:12.105Z" }, - { url = "https://files.pythonhosted.org/packages/fc/c4/3ce4c2d9b6aabd27d26ec988f08cb877ba9e6e96086eff81bfea93e688c7/shapely-2.1.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:9a522f460d28e2bf4e12396240a5fc1518788b2fcd73535166d748399ef0c223", size = 1831290, upload-time = "2025-09-24T13:51:13.56Z" }, - { url = "https://files.pythonhosted.org/packages/17/b9/f6ab8918fc15429f79cb04afa9f9913546212d7fb5e5196132a2af46676b/shapely-2.1.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1ff629e00818033b8d71139565527ced7d776c269a49bd78c9df84e8f852190c", size = 1641463, upload-time = "2025-09-24T13:51:14.972Z" }, - { url = "https://files.pythonhosted.org/packages/a5/57/91d59ae525ca641e7ac5551c04c9503aee6f29b92b392f31790fcb1a4358/shapely-2.1.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f67b34271dedc3c653eba4e3d7111aa421d5be9b4c4c7d38d30907f796cb30df", size = 2970145, upload-time = "2025-09-24T13:51:16.961Z" }, - { url = "https://files.pythonhosted.org/packages/8a/cb/4948be52ee1da6927831ab59e10d4c29baa2a714f599f1f0d1bc747f5777/shapely-2.1.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:21952dc00df38a2c28375659b07a3979d22641aeb104751e769c3ee825aadecf", size = 3073806, upload-time = "2025-09-24T13:51:18.712Z" }, - { url = "https://files.pythonhosted.org/packages/03/83/f768a54af775eb41ef2e7bec8a0a0dbe7d2431c3e78c0a8bdba7ab17e446/shapely-2.1.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1f2f33f486777456586948e333a56ae21f35ae273be99255a191f5c1fa302eb4", size = 3980803, upload-time = "2025-09-24T13:51:20.37Z" }, - { url = "https://files.pythonhosted.org/packages/9f/cb/559c7c195807c91c79d38a1f6901384a2878a76fbdf3f1048893a9b7534d/shapely-2.1.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:cf831a13e0d5a7eb519e96f58ec26e049b1fad411fc6fc23b162a7ce04d9cffc", size = 4133301, upload-time = "2025-09-24T13:51:21.887Z" }, - { url = "https://files.pythonhosted.org/packages/80/cd/60d5ae203241c53ef3abd2ef27c6800e21afd6c94e39db5315ea0cbafb4a/shapely-2.1.2-cp314-cp314-win32.whl", hash = "sha256:61edcd8d0d17dd99075d320a1dd39c0cb9616f7572f10ef91b4b5b00c4aeb566", size = 1583247, upload-time = "2025-09-24T13:51:23.401Z" }, - { url = "https://files.pythonhosted.org/packages/74/d4/135684f342e909330e50d31d441ace06bf83c7dc0777e11043f99167b123/shapely-2.1.2-cp314-cp314-win_amd64.whl", hash = "sha256:a444e7afccdb0999e203b976adb37ea633725333e5b119ad40b1ca291ecf311c", size = 1773019, upload-time = "2025-09-24T13:51:24.873Z" }, - { url = "https://files.pythonhosted.org/packages/a3/05/a44f3f9f695fa3ada22786dc9da33c933da1cbc4bfe876fe3a100bafe263/shapely-2.1.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:5ebe3f84c6112ad3d4632b1fd2290665aa75d4cef5f6c5d77c4c95b324527c6a", size = 1834137, upload-time = "2025-09-24T13:51:26.665Z" }, - { url = "https://files.pythonhosted.org/packages/52/7e/4d57db45bf314573427b0a70dfca15d912d108e6023f623947fa69f39b72/shapely-2.1.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5860eb9f00a1d49ebb14e881f5caf6c2cf472c7fd38bd7f253bbd34f934eb076", size = 1642884, upload-time = "2025-09-24T13:51:28.029Z" }, - { url = "https://files.pythonhosted.org/packages/5a/27/4e29c0a55d6d14ad7422bf86995d7ff3f54af0eba59617eb95caf84b9680/shapely-2.1.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b705c99c76695702656327b819c9660768ec33f5ce01fa32b2af62b56ba400a1", size = 3018320, upload-time = "2025-09-24T13:51:29.903Z" }, - { url = "https://files.pythonhosted.org/packages/9f/bb/992e6a3c463f4d29d4cd6ab8963b75b1b1040199edbd72beada4af46bde5/shapely-2.1.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a1fd0ea855b2cf7c9cddaf25543e914dd75af9de08785f20ca3085f2c9ca60b0", size = 3094931, upload-time = "2025-09-24T13:51:32.699Z" }, - { url = "https://files.pythonhosted.org/packages/9c/16/82e65e21070e473f0ed6451224ed9fa0be85033d17e0c6e7213a12f59d12/shapely-2.1.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:df90e2db118c3671a0754f38e36802db75fe0920d211a27481daf50a711fdf26", size = 4030406, upload-time = "2025-09-24T13:51:34.189Z" }, - { url = "https://files.pythonhosted.org/packages/7c/75/c24ed871c576d7e2b64b04b1fe3d075157f6eb54e59670d3f5ffb36e25c7/shapely-2.1.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:361b6d45030b4ac64ddd0a26046906c8202eb60d0f9f53085f5179f1d23021a0", size = 4169511, upload-time = "2025-09-24T13:51:36.297Z" }, - { url = "https://files.pythonhosted.org/packages/b1/f7/b3d1d6d18ebf55236eec1c681ce5e665742aab3c0b7b232720a7d43df7b6/shapely-2.1.2-cp314-cp314t-win32.whl", hash = "sha256:b54df60f1fbdecc8ebc2c5b11870461a6417b3d617f555e5033f1505d36e5735", size = 1602607, upload-time = "2025-09-24T13:51:37.757Z" }, - { url = "https://files.pythonhosted.org/packages/9a/f6/f09272a71976dfc138129b8faf435d064a811ae2f708cb147dccdf7aacdb/shapely-2.1.2-cp314-cp314t-win_amd64.whl", hash = "sha256:0036ac886e0923417932c2e6369b6c52e38e0ff5d9120b90eef5cd9a5fc5cae9", size = 1796682, upload-time = "2025-09-24T13:51:39.233Z" }, -] - -[[package]] -name = "six" -version = "1.17.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, -] - -[[package]] -name = "soupsieve" -version = "2.8.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7b/ae/2d9c981590ed9999a0d91755b47fc74f74de286b0f5cee14c9269041e6c4/soupsieve-2.8.3.tar.gz", hash = "sha256:3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349", size = 118627, upload-time = "2026-01-20T04:27:02.457Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl", hash = "sha256:ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95", size = 37016, upload-time = "2026-01-20T04:27:01.012Z" }, -] - -[[package]] -name = "stack-data" -version = "0.6.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "asttokens" }, - { name = "executing" }, - { name = "pure-eval" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707, upload-time = "2023-09-30T13:58:05.479Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" }, -] - -[[package]] -name = "terminado" -version = "0.18.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "ptyprocess", marker = "os_name != 'nt'" }, - { name = "pywinpty", marker = "os_name == 'nt'" }, - { name = "tornado" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/8a/11/965c6fd8e5cc254f1fe142d547387da17a8ebfd75a3455f637c663fb38a0/terminado-0.18.1.tar.gz", hash = "sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e", size = 32701, upload-time = "2024-03-12T14:34:39.026Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl", hash = "sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0", size = 14154, upload-time = "2024-03-12T14:34:36.569Z" }, -] - -[[package]] -name = "threadpoolctl" -version = "3.6.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b7/4d/08c89e34946fce2aec4fbb45c9016efd5f4d7f24af8e5d93296e935631d8/threadpoolctl-3.6.0.tar.gz", hash = "sha256:8ab8b4aa3491d812b623328249fab5302a68d2d71745c8a4c719a2fcaba9f44e", size = 21274, upload-time = "2025-03-13T13:49:23.031Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638, upload-time = "2025-03-13T13:49:21.846Z" }, -] - -[[package]] -name = "tidypolars" -version = "0.3.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "numpy" }, - { name = "polars" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/06/b4/98c9f4f6c87d0630c4745777140c889d3b1a70db5a292204020839f0deae/tidypolars-0.3.2.tar.gz", hash = "sha256:009cb92d3211fb20a375adbfcf043703b04411aa22c05351addd13addff84f67", size = 17836, upload-time = "2024-11-02T14:49:21.012Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4b/c5/fe58f5ff266d15d22c3eb214c04d035c606febd317ea51cac85e212e74de/tidypolars-0.3.2-py3-none-any.whl", hash = "sha256:73ca614730c38abc63e30db832e599b098e95ea7094d9cff60fe24733b0a5293", size = 18731, upload-time = "2024-11-02T14:49:19.513Z" }, -] - -[[package]] -name = "tinycss2" -version = "1.4.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "webencodings" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/7a/fd/7a5ee21fd08ff70d3d33a5781c255cbe779659bd03278feb98b19ee550f4/tinycss2-1.4.0.tar.gz", hash = "sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7", size = 87085, upload-time = "2024-10-24T14:58:29.895Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289", size = 26610, upload-time = "2024-10-24T14:58:28.029Z" }, -] - -[[package]] -name = "tornado" -version = "6.5.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/37/1d/0a336abf618272d53f62ebe274f712e213f5a03c0b2339575430b8362ef2/tornado-6.5.4.tar.gz", hash = "sha256:a22fa9047405d03260b483980635f0b041989d8bcc9a313f8fe18b411d84b1d7", size = 513632, upload-time = "2025-12-15T19:21:03.836Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ab/a9/e94a9d5224107d7ce3cc1fab8d5dc97f5ea351ccc6322ee4fb661da94e35/tornado-6.5.4-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:d6241c1a16b1c9e4cc28148b1cda97dd1c6cb4fb7068ac1bedc610768dff0ba9", size = 443909, upload-time = "2025-12-15T19:20:48.382Z" }, - { url = "https://files.pythonhosted.org/packages/db/7e/f7b8d8c4453f305a51f80dbb49014257bb7d28ccb4bbb8dd328ea995ecad/tornado-6.5.4-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2d50f63dda1d2cac3ae1fa23d254e16b5e38153758470e9956cbc3d813d40843", size = 442163, upload-time = "2025-12-15T19:20:49.791Z" }, - { url = "https://files.pythonhosted.org/packages/ba/b5/206f82d51e1bfa940ba366a8d2f83904b15942c45a78dd978b599870ab44/tornado-6.5.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1cf66105dc6acb5af613c054955b8137e34a03698aa53272dbda4afe252be17", size = 445746, upload-time = "2025-12-15T19:20:51.491Z" }, - { url = "https://files.pythonhosted.org/packages/8e/9d/1a3338e0bd30ada6ad4356c13a0a6c35fbc859063fa7eddb309183364ac1/tornado-6.5.4-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50ff0a58b0dc97939d29da29cd624da010e7f804746621c78d14b80238669335", size = 445083, upload-time = "2025-12-15T19:20:52.778Z" }, - { url = "https://files.pythonhosted.org/packages/50/d4/e51d52047e7eb9a582da59f32125d17c0482d065afd5d3bc435ff2120dc5/tornado-6.5.4-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5fb5e04efa54cf0baabdd10061eb4148e0be137166146fff835745f59ab9f7f", size = 445315, upload-time = "2025-12-15T19:20:53.996Z" }, - { url = "https://files.pythonhosted.org/packages/27/07/2273972f69ca63dbc139694a3fc4684edec3ea3f9efabf77ed32483b875c/tornado-6.5.4-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9c86b1643b33a4cd415f8d0fe53045f913bf07b4a3ef646b735a6a86047dda84", size = 446003, upload-time = "2025-12-15T19:20:56.101Z" }, - { url = "https://files.pythonhosted.org/packages/d1/83/41c52e47502bf7260044413b6770d1a48dda2f0246f95ee1384a3cd9c44a/tornado-6.5.4-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:6eb82872335a53dd063a4f10917b3efd28270b56a33db69009606a0312660a6f", size = 445412, upload-time = "2025-12-15T19:20:57.398Z" }, - { url = "https://files.pythonhosted.org/packages/10/c7/bc96917f06cbee182d44735d4ecde9c432e25b84f4c2086143013e7b9e52/tornado-6.5.4-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6076d5dda368c9328ff41ab5d9dd3608e695e8225d1cd0fd1e006f05da3635a8", size = 445392, upload-time = "2025-12-15T19:20:58.692Z" }, - { url = "https://files.pythonhosted.org/packages/0c/1a/d7592328d037d36f2d2462f4bc1fbb383eec9278bc786c1b111cbbd44cfa/tornado-6.5.4-cp39-abi3-win32.whl", hash = "sha256:1768110f2411d5cd281bac0a090f707223ce77fd110424361092859e089b38d1", size = 446481, upload-time = "2025-12-15T19:21:00.008Z" }, - { url = "https://files.pythonhosted.org/packages/d6/6d/c69be695a0a64fd37a97db12355a035a6d90f79067a3cf936ec2b1dc38cd/tornado-6.5.4-cp39-abi3-win_amd64.whl", hash = "sha256:fa07d31e0cd85c60713f2b995da613588aa03e1303d75705dca6af8babc18ddc", size = 446886, upload-time = "2025-12-15T19:21:01.287Z" }, - { url = "https://files.pythonhosted.org/packages/50/49/8dc3fd90902f70084bd2cd059d576ddb4f8bb44c2c7c0e33a11422acb17e/tornado-6.5.4-cp39-abi3-win_arm64.whl", hash = "sha256:053e6e16701eb6cbe641f308f4c1a9541f91b6261991160391bfc342e8a551a1", size = 445910, upload-time = "2025-12-15T19:21:02.571Z" }, -] - -[[package]] -name = "traitlets" -version = "5.14.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/eb/79/72064e6a701c2183016abbbfedaba506d81e30e232a68c9f0d6f6fcd1574/traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", size = 161621, upload-time = "2024-04-19T11:11:49.746Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f", size = 85359, upload-time = "2024-04-19T11:11:46.763Z" }, -] - -[[package]] -name = "typing-extensions" -version = "4.15.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, -] - -[[package]] -name = "tzdata" -version = "2025.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5e/a7/c202b344c5ca7daf398f3b8a477eeb205cf3b6f32e7ec3a6bac0629ca975/tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7", size = 196772, upload-time = "2025-12-13T17:45:35.667Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, -] - -[[package]] -name = "uri-template" -version = "1.3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/31/c7/0336f2bd0bcbada6ccef7aaa25e443c118a704f828a0620c6fa0207c1b64/uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7", size = 21678, upload-time = "2023-06-21T01:49:05.374Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363", size = 11140, upload-time = "2023-06-21T01:49:03.467Z" }, -] - -[[package]] -name = "urllib3" -version = "2.6.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1e/24/a2a2ed9addd907787d7aa0355ba36a6cadf1768b934c652ea78acbd59dcd/urllib3-2.6.2.tar.gz", hash = "sha256:016f9c98bb7e98085cb2b4b17b87d2c702975664e4f060c6532e64d1c1a5e797", size = 432930, upload-time = "2025-12-11T15:56:40.252Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6d/b9/4095b668ea3678bf6a0af005527f39de12fb026516fb3df17495a733b7f8/urllib3-2.6.2-py3-none-any.whl", hash = "sha256:ec21cddfe7724fc7cb4ba4bea7aa8e2ef36f607a4bab81aa6ce42a13dc3f03dd", size = 131182, upload-time = "2025-12-11T15:56:38.584Z" }, -] - -[[package]] -name = "wcwidth" -version = "0.2.14" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/24/30/6b0809f4510673dc723187aeaf24c7f5459922d01e2f794277a3dfb90345/wcwidth-0.2.14.tar.gz", hash = "sha256:4d478375d31bc5395a3c55c40ccdf3354688364cd61c4f6adacaa9215d0b3605", size = 102293, upload-time = "2025-09-22T16:29:53.023Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl", hash = "sha256:a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1", size = 37286, upload-time = "2025-09-22T16:29:51.641Z" }, -] - -[[package]] -name = "webcolors" -version = "25.10.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1d/7a/eb316761ec35664ea5174709a68bbd3389de60d4a1ebab8808bfc264ed67/webcolors-25.10.0.tar.gz", hash = "sha256:62abae86504f66d0f6364c2a8520de4a0c47b80c03fc3a5f1815fedbef7c19bf", size = 53491, upload-time = "2025-10-31T07:51:03.977Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl", hash = "sha256:032c727334856fc0b968f63daa252a1ac93d33db2f5267756623c210e57a4f1d", size = 14905, upload-time = "2025-10-31T07:51:01.778Z" }, -] - -[[package]] -name = "webencodings" -version = "0.5.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923", size = 9721, upload-time = "2017-04-05T20:21:34.189Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774, upload-time = "2017-04-05T20:21:32.581Z" }, -] - -[[package]] -name = "websocket-client" -version = "1.9.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2c/41/aa4bf9664e4cda14c3b39865b12251e8e7d239f4cd0e3cc1b6c2ccde25c1/websocket_client-1.9.0.tar.gz", hash = "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", size = 70576, upload-time = "2025-10-07T21:16:36.495Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/34/db/b10e48aa8fff7407e67470363eac595018441cf32d5e1001567a7aeba5d2/websocket_client-1.9.0-py3-none-any.whl", hash = "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef", size = 82616, upload-time = "2025-10-07T21:16:34.951Z" }, -] - -[[package]] -name = "widgetsnbextension" -version = "4.0.15" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bd/f4/c67440c7fb409a71b7404b7aefcd7569a9c0d6bd071299bf4198ae7a5d95/widgetsnbextension-4.0.15.tar.gz", hash = "sha256:de8610639996f1567952d763a5a41af8af37f2575a41f9852a38f947eb82a3b9", size = 1097402, upload-time = "2025-11-01T21:15:55.178Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl", hash = "sha256:8156704e4346a571d9ce73b84bee86a29906c9abfd7223b7228a28899ccf3366", size = 2196503, upload-time = "2025-11-01T21:15:53.565Z" }, -] - -[[package]] -name = "xlrd" -version = "2.0.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/07/5a/377161c2d3538d1990d7af382c79f3b2372e880b65de21b01b1a2b78691e/xlrd-2.0.2.tar.gz", hash = "sha256:08b5e25de58f21ce71dc7db3b3b8106c1fa776f3024c54e45b45b374e89234c9", size = 100167, upload-time = "2025-06-14T08:46:39.039Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1a/62/c8d562e7766786ba6587d09c5a8ba9f718ed3fa8af7f4553e8f91c36f302/xlrd-2.0.2-py2.py3-none-any.whl", hash = "sha256:ea762c3d29f4cca48d82df517b6d89fbce4db3107f9d78713e48cd321d5c9aa9", size = 96555, upload-time = "2025-06-14T08:46:37.766Z" }, -] From 247bc57684df9137f280f3adda02673f9d5e0a1c Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 24 Dec 2025 16:09:36 +0000 Subject: [PATCH 77/92] with plot pop per region --- applis_nt/rp/solutions_rp.py | 75 +++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 23 deletions(-) diff --git a/applis_nt/rp/solutions_rp.py b/applis_nt/rp/solutions_rp.py index 2299573b..3e0d56e4 100644 --- a/applis_nt/rp/solutions_rp.py +++ b/applis_nt/rp/solutions_rp.py @@ -7,12 +7,15 @@ # import fastexcel import solutions import matplotlib.pyplot as plt +import requests + def load_data(): data = pl.read_excel( - 'https://www.insee.fr/fr/statistiques/fichier/1893198/estim-pop-dep-sexe-aq-1975-2023.xls', - sheet_name=[str(i) for i in range(1975,2024,1)], - read_options={ "header_row": 3}) + 'https://www.insee.fr/fr/statistiques/fichier/1893198/estim-pop-dep-sexe-aq-1975-2023.xls', + sheet_name=[str(i) for i in range(1975, 2024, 1)], + read_options={"header_row": 3} + ) return data @@ -28,24 +31,24 @@ def reshape_table_by_year(df, year): temp_colnames_list[index] = temp_colnames_list[index] + "__" + df[0, colname] else: temp_colnames_list[index] = temp_colnames_list[index-1].split("_")[0] + "__00" - temp_colnames_list[0]="dep_code" - temp_colnames_list[1]="dep" + temp_colnames_list[0] = "dep_code" + temp_colnames_list[1] = "dep" df_new = df.rename(dict(zip(df.columns, temp_colnames_list))) # Reshaping data - df_new = ( - df_new.drop_nulls(pl.col('dep')) - .unpivot(index=['dep_code', 'dep'], value_name="population") - .with_columns( - variablelist=pl.col.variable.str.split('__') - ) - .with_columns( - genre=pl.col.variablelist.list.get(0, null_on_oob=True), - age=pl.col.variablelist.list.get(1, null_on_oob=True), - population=pl.col.population.cast(pl.Int64), - annee=pl.lit(year).cast(pl.Int64) - ) - .select(['dep_code', 'dep', 'annee', 'genre', 'age', 'population']) + df_new = (df_new\ + .drop_nulls(pl.col('dep')) + .unpivot(index=['dep_code', 'dep'], value_name="population") + .with_columns( + variablelist=pl.col.variable.str.split('__') + ) + .with_columns( + genre=pl.col.variablelist.list.get(0, null_on_oob=True), + age=pl.col.variablelist.list.get(1, null_on_oob=True), + population=pl.col.population.cast(pl.Int64), + annee=pl.lit(year).cast(pl.Int64) + ) + .select(['dep_code', 'dep', 'annee', 'genre', 'age', 'population']) ) return df_new @@ -129,7 +132,7 @@ def tr_age_sorted_plot(list): # %% -def plot_age_pyramid(years): +def plot_age_pyramid(df, years): df_plot = get_age_pyramid_data(df, years)\ .unpivot(index=["annee", "age"], variable_name="genre")\ .filter(pl.col.genre != "Ensemble")\ @@ -165,7 +168,7 @@ def plot_age_pyramid(years): return plot # %% -plot_age_pyramid([1975, 2023]) +plot_age_pyramid(df, [1975, 2023]) # %% fig,(ax1,ax2) = plt.subplots(1,2,figsize=(15,6)) @@ -212,9 +215,35 @@ def match_department_regions(df, df_matching): # %% def load_geo_data(url): geodata = gpd.read_file(url) - geodata = geodata[[NOM', 'geometry']] - return + geodata = geodata[['NOM', 'geometry']] + return geodata # %% url = "https://minio.lab.sspcloud.fr/projet-cartiflette/diffusion/shapefiles-test1/year=2022/administrative_level=REGION/crs=4326/FRANCE_ENTIERE=metropole/vectorfile_format='geojson'/provider='IGN'/source='EXPRESS-COG-CARTO-TERRITOIRE'/raw.geojson" -load_geo_data(url) \ No newline at end of file +geo = load_geo_data(url) +# %% +solutions.plot_population_by_regions(df_regions.to_pandas(), geo, 2022) + +# %% + +(df_regions\ + .filter(pl.col.annee==2022, pl.col.genre=="Ensemble", pl.col.age=="Total") + .group_by('region_name') + .agg(pl.col.population.sum()) + .to_pandas() + .merge( + geo, + left_on="region_name", + right_on="NOM", + how="left" + ) + >> p9.ggplot(p9.aes(fill="population")) + + p9.geom_map() + + p9.theme_matplotlib() +) + +# list(set(list(geo['NOM'].unique())) & set(df_regions.select("region_name").unique().to_series().to_list())) +# %% +solutions.plot_growth_population_by_regions(df_regions.to_pandas(), geo, 2015, 2022) + +# %% From 68995c746a5aaffe799f6b45abe9dccb71cef74f Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 14:40:51 +0000 Subject: [PATCH 78/92] clean up post rebase --- .../projects/RP/solutions_polars.py | 0 .../projects/meteo/solutions_polars.py | 0 uv.lock | 1630 +++++++++++++++++ 3 files changed, 1630 insertions(+) rename applis_nt/rp/solutions_rp.py => source/projects/RP/solutions_polars.py (100%) rename applis_nt/solutions_meteo.py => source/projects/meteo/solutions_polars.py (100%) diff --git a/applis_nt/rp/solutions_rp.py b/source/projects/RP/solutions_polars.py similarity index 100% rename from applis_nt/rp/solutions_rp.py rename to source/projects/RP/solutions_polars.py diff --git a/applis_nt/solutions_meteo.py b/source/projects/meteo/solutions_polars.py similarity index 100% rename from applis_nt/solutions_meteo.py rename to source/projects/meteo/solutions_polars.py diff --git a/uv.lock b/uv.lock index a41f569e..8b9896f0 100644 --- a/uv.lock +++ b/uv.lock @@ -1,6 +1,182 @@ version = 1 revision = 3 requires-python = ">=3.13" +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version < '3.14'", +] + +[[package]] +name = "anyio" +version = "4.12.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/96/f0/5eb65b2bb0d09ac6776f2eb54adee6abe8228ea05b20a5ad0e4945de8aac/anyio-4.12.1.tar.gz", hash = "sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703", size = 228685, upload-time = "2026-01-06T11:45:21.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c", size = 113592, upload-time = "2026-01-06T11:45:19.497Z" }, +] + +[[package]] +name = "appnope" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/35/5d/752690df9ef5b76e169e68d6a129fa6d08a7100ca7f754c89495db3c6019/appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee", size = 4170, upload-time = "2024-02-06T09:43:11.258Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c", size = 4321, upload-time = "2024-02-06T09:43:09.663Z" }, +] + +[[package]] +name = "argon2-cffi" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "argon2-cffi-bindings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0e/89/ce5af8a7d472a67cc819d5d998aa8c82c5d860608c4db9f46f1162d7dab9/argon2_cffi-25.1.0.tar.gz", hash = "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1", size = 45706, upload-time = "2025-06-03T06:55:32.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl", hash = "sha256:fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741", size = 14657, upload-time = "2025-06-03T06:55:30.804Z" }, +] + +[[package]] +name = "argon2-cffi-bindings" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5c/2d/db8af0df73c1cf454f71b2bbe5e356b8c1f8041c979f505b3d3186e520a9/argon2_cffi_bindings-25.1.0.tar.gz", hash = "sha256:b957f3e6ea4d55d820e40ff76f450952807013d361a65d7f28acc0acbf29229d", size = 1783441, upload-time = "2025-07-30T10:02:05.147Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/97/3c0a35f46e52108d4707c44b95cfe2afcafc50800b5450c197454569b776/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:3d3f05610594151994ca9ccb3c771115bdb4daef161976a266f0dd8aa9996b8f", size = 54393, upload-time = "2025-07-30T10:01:40.97Z" }, + { url = "https://files.pythonhosted.org/packages/9d/f4/98bbd6ee89febd4f212696f13c03ca302b8552e7dbf9c8efa11ea4a388c3/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8b8efee945193e667a396cbc7b4fb7d357297d6234d30a489905d96caabde56b", size = 29328, upload-time = "2025-07-30T10:01:41.916Z" }, + { url = "https://files.pythonhosted.org/packages/43/24/90a01c0ef12ac91a6be05969f29944643bc1e5e461155ae6559befa8f00b/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3c6702abc36bf3ccba3f802b799505def420a1b7039862014a65db3205967f5a", size = 31269, upload-time = "2025-07-30T10:01:42.716Z" }, + { url = "https://files.pythonhosted.org/packages/d4/d3/942aa10782b2697eee7af5e12eeff5ebb325ccfb86dd8abda54174e377e4/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1c70058c6ab1e352304ac7e3b52554daadacd8d453c1752e547c76e9c99ac44", size = 86558, upload-time = "2025-07-30T10:01:43.943Z" }, + { url = "https://files.pythonhosted.org/packages/0d/82/b484f702fec5536e71836fc2dbc8c5267b3f6e78d2d539b4eaa6f0db8bf8/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e2fd3bfbff3c5d74fef31a722f729bf93500910db650c925c2d6ef879a7e51cb", size = 92364, upload-time = "2025-07-30T10:01:44.887Z" }, + { url = "https://files.pythonhosted.org/packages/c9/c1/a606ff83b3f1735f3759ad0f2cd9e038a0ad11a3de3b6c673aa41c24bb7b/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4f9665de60b1b0e99bcd6be4f17d90339698ce954cfd8d9cf4f91c995165a92", size = 85637, upload-time = "2025-07-30T10:01:46.225Z" }, + { url = "https://files.pythonhosted.org/packages/44/b4/678503f12aceb0262f84fa201f6027ed77d71c5019ae03b399b97caa2f19/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ba92837e4a9aa6a508c8d2d7883ed5a8f6c308c89a4790e1e447a220deb79a85", size = 91934, upload-time = "2025-07-30T10:01:47.203Z" }, + { url = "https://files.pythonhosted.org/packages/f0/c7/f36bd08ef9bd9f0a9cff9428406651f5937ce27b6c5b07b92d41f91ae541/argon2_cffi_bindings-25.1.0-cp314-cp314t-win32.whl", hash = "sha256:84a461d4d84ae1295871329b346a97f68eade8c53b6ed9a7ca2d7467f3c8ff6f", size = 28158, upload-time = "2025-07-30T10:01:48.341Z" }, + { url = "https://files.pythonhosted.org/packages/b3/80/0106a7448abb24a2c467bf7d527fe5413b7fdfa4ad6d6a96a43a62ef3988/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b55aec3565b65f56455eebc9b9f34130440404f27fe21c3b375bf1ea4d8fbae6", size = 32597, upload-time = "2025-07-30T10:01:49.112Z" }, + { url = "https://files.pythonhosted.org/packages/05/b8/d663c9caea07e9180b2cb662772865230715cbd573ba3b5e81793d580316/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:87c33a52407e4c41f3b70a9c2d3f6056d88b10dad7695be708c5021673f55623", size = 28231, upload-time = "2025-07-30T10:01:49.92Z" }, + { url = "https://files.pythonhosted.org/packages/1d/57/96b8b9f93166147826da5f90376e784a10582dd39a393c99bb62cfcf52f0/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:aecba1723ae35330a008418a91ea6cfcedf6d31e5fbaa056a166462ff066d500", size = 54121, upload-time = "2025-07-30T10:01:50.815Z" }, + { url = "https://files.pythonhosted.org/packages/0a/08/a9bebdb2e0e602dde230bdde8021b29f71f7841bd54801bcfd514acb5dcf/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2630b6240b495dfab90aebe159ff784d08ea999aa4b0d17efa734055a07d2f44", size = 29177, upload-time = "2025-07-30T10:01:51.681Z" }, + { url = "https://files.pythonhosted.org/packages/b6/02/d297943bcacf05e4f2a94ab6f462831dc20158614e5d067c35d4e63b9acb/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:7aef0c91e2c0fbca6fc68e7555aa60ef7008a739cbe045541e438373bc54d2b0", size = 31090, upload-time = "2025-07-30T10:01:53.184Z" }, + { url = "https://files.pythonhosted.org/packages/c1/93/44365f3d75053e53893ec6d733e4a5e3147502663554b4d864587c7828a7/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e021e87faa76ae0d413b619fe2b65ab9a037f24c60a1e6cc43457ae20de6dc6", size = 81246, upload-time = "2025-07-30T10:01:54.145Z" }, + { url = "https://files.pythonhosted.org/packages/09/52/94108adfdd6e2ddf58be64f959a0b9c7d4ef2fa71086c38356d22dc501ea/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e924cfc503018a714f94a49a149fdc0b644eaead5d1f089330399134fa028a", size = 87126, upload-time = "2025-07-30T10:01:55.074Z" }, + { url = "https://files.pythonhosted.org/packages/72/70/7a2993a12b0ffa2a9271259b79cc616e2389ed1a4d93842fac5a1f923ffd/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87b72589133f0346a1cb8d5ecca4b933e3c9b64656c9d175270a000e73b288d", size = 80343, upload-time = "2025-07-30T10:01:56.007Z" }, + { url = "https://files.pythonhosted.org/packages/78/9a/4e5157d893ffc712b74dbd868c7f62365618266982b64accab26bab01edc/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1db89609c06afa1a214a69a462ea741cf735b29a57530478c06eb81dd403de99", size = 86777, upload-time = "2025-07-30T10:01:56.943Z" }, + { url = "https://files.pythonhosted.org/packages/74/cd/15777dfde1c29d96de7f18edf4cc94c385646852e7c7b0320aa91ccca583/argon2_cffi_bindings-25.1.0-cp39-abi3-win32.whl", hash = "sha256:473bcb5f82924b1becbb637b63303ec8d10e84c8d241119419897a26116515d2", size = 27180, upload-time = "2025-07-30T10:01:57.759Z" }, + { url = "https://files.pythonhosted.org/packages/e2/c6/a759ece8f1829d1f162261226fbfd2c6832b3ff7657384045286d2afa384/argon2_cffi_bindings-25.1.0-cp39-abi3-win_amd64.whl", hash = "sha256:a98cd7d17e9f7ce244c0803cad3c23a7d379c301ba618a5fa76a67d116618b98", size = 31715, upload-time = "2025-07-30T10:01:58.56Z" }, + { url = "https://files.pythonhosted.org/packages/42/b9/f8d6fa329ab25128b7e98fd83a3cb34d9db5b059a9847eddb840a0af45dd/argon2_cffi_bindings-25.1.0-cp39-abi3-win_arm64.whl", hash = "sha256:b0fdbcf513833809c882823f98dc2f931cf659d9a1429616ac3adebb49f5db94", size = 27149, upload-time = "2025-07-30T10:01:59.329Z" }, +] + +[[package]] +name = "arrow" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, + { name = "tzdata" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/33/032cdc44182491aa708d06a68b62434140d8c50820a087fac7af37703357/arrow-1.4.0.tar.gz", hash = "sha256:ed0cc050e98001b8779e84d461b0098c4ac597e88704a655582b21d116e526d7", size = 152931, upload-time = "2025-10-18T17:46:46.761Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl", hash = "sha256:749f0769958ebdc79c173ff0b0670d59051a535fa26e8eba02953dc19eb43205", size = 68797, upload-time = "2025-10-18T17:46:45.663Z" }, +] + +[[package]] +name = "asttokens" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/be/a5/8e3f9b6771b0b408517c82d97aed8f2036509bc247d46114925e32fe33f0/asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7", size = 62308, upload-time = "2025-11-15T16:43:48.578Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", size = 27047, upload-time = "2025-11-15T16:43:16.109Z" }, +] + +[[package]] +name = "async-lru" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8a/ca724066c32a53fa75f59e0f21aa822fdaa8a0dffa112d223634e3caabf9/async_lru-2.2.0.tar.gz", hash = "sha256:80abae2a237dbc6c60861d621619af39f0d920aea306de34cb992c879e01370c", size = 14654, upload-time = "2026-02-20T19:11:43.848Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/5c/af990f019b8dd11c5492a6371fe74a5b0276357370030b67254a87329944/async_lru-2.2.0-py3-none-any.whl", hash = "sha256:e2c1cf731eba202b59c5feedaef14ffd9d02ad0037fcda64938699f2c380eafe", size = 7890, upload-time = "2026-02-20T19:11:42.273Z" }, +] + +[[package]] +name = "attrs" +version = "25.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6b/5c/685e6633917e101e5dcb62b9dd76946cbb57c26e133bae9e0cd36033c0a9/attrs-25.4.0.tar.gz", hash = "sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11", size = 934251, upload-time = "2025-10-06T13:54:44.725Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, +] + +[[package]] +name = "babel" +version = "2.18.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/b2/51899539b6ceeeb420d40ed3cd4b7a40519404f9baf3d4ac99dc413a834b/babel-2.18.0.tar.gz", hash = "sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d", size = 9959554, upload-time = "2026-02-01T12:30:56.078Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl", hash = "sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35", size = 10196845, upload-time = "2026-02-01T12:30:53.445Z" }, +] + +[[package]] +name = "beautifulsoup4" +version = "4.14.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "soupsieve" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c3/b0/1c6a16426d389813b48d95e26898aff79abbde42ad353958ad95cc8c9b21/beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86", size = 627737, upload-time = "2025-11-30T15:08:26.084Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" }, +] + +[[package]] +name = "bleach" +version = "6.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "webencodings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/07/18/3c8523962314be6bf4c8989c79ad9531c825210dd13a8669f6b84336e8bd/bleach-6.3.0.tar.gz", hash = "sha256:6f3b91b1c0a02bb9a78b5a454c92506aa0fdf197e1d5e114d2e00c6f64306d22", size = 203533, upload-time = "2025-10-27T17:57:39.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl", hash = "sha256:fe10ec77c93ddf3d13a73b035abaac7a9f5e436513864ccdad516693213c65d6", size = 164437, upload-time = "2025-10-27T17:57:37.538Z" }, +] + +[package.optional-dependencies] +css = [ + { name = "tinycss2" }, +] + +[[package]] +name = "cartiflette" +version = "0.1.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "geopandas" }, + { name = "platformdirs" }, + { name = "requests" }, + { name = "requests-cache" }, + { name = "tqdm" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c3/2a/d3e419bd087cf99c234ad91a83ca1622775c9d25b1bcb3c3431275ed3683/cartiflette-0.1.9.tar.gz", hash = "sha256:e5a0676dc8eb47a6854f27e3863e4263b6882a31339dd156ac3dea647a05bd28", size = 103685, upload-time = "2025-05-25T10:56:42.471Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/35/984034116552257ff3d96e7be4cd27b5bddb05052fb8e6509a4123a685bd/cartiflette-0.1.9-py3-none-any.whl", hash = "sha256:87c9e1a6fc13b75f710418667cd5b4a25485e7bba022221027edcbe61bd08964", size = 6813, upload-time = "2025-05-25T10:56:41.231Z" }, +] + +[[package]] +name = "cattrs" +version = "26.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a0/ec/ba18945e7d6e55a58364d9fb2e46049c1c2998b3d805f19b703f14e81057/cattrs-26.1.0.tar.gz", hash = "sha256:fa239e0f0ec0715ba34852ce813986dfed1e12117e209b816ab87401271cdd40", size = 495672, upload-time = "2026-02-18T22:15:19.406Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/80/56/60547f7801b97c67e97491dc3d9ade9fbccbd0325058fd3dfcb2f5d98d90/cattrs-26.1.0-py3-none-any.whl", hash = "sha256:d1e0804c42639494d469d08d4f26d6b9de9b8ab26b446db7b5f8c2e97f7c3096", size = 73054, upload-time = "2026-02-18T22:15:17.958Z" }, +] [[package]] name = "certifi" @@ -11,6 +187,110 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", size = 159438, upload-time = "2025-11-12T02:54:49.735Z" }, ] +[[package]] +name = "cffi" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, + { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, + { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, + { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, + { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, + { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, + { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, + { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, + { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, + { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, + { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, + { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, + { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" }, + { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" }, + { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, + { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, + { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, + { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, + { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, + { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" }, + { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" }, + { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" }, + { url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" }, + { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, + { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, + { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, + { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, + { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, + { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, + { url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, + { url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, + { url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, + { url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, + { url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, + { url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, + { url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, + { url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, + { url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, + { url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, + { url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, + { url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, + { url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, + { url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, + { url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" }, + { url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" }, + { url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" }, + { url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" }, + { url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" }, + { url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" }, + { url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" }, + { url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" }, + { url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" }, + { url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" }, + { url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" }, + { url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" }, + { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" }, + { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" }, + { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" }, + { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "comm" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/13/7d740c5849255756bc17888787313b61fd38a0a8304fc4f073dfc46122aa/comm-0.2.3.tar.gz", hash = "sha256:2dc8048c10962d55d7ad693be1e7045d891b7ce8d999c97963a5e3e99c055971", size = 6319, upload-time = "2025-07-25T14:02:04.452Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl", hash = "sha256:c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417", size = 7294, upload-time = "2025-07-25T14:02:02.896Z" }, +] + [[package]] name = "contourpy" version = "1.3.3" @@ -75,6 +355,50 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" }, ] +[[package]] +name = "debugpy" +version = "1.8.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/b7/cd8080344452e4874aae67c40d8940e2b4d47b01601a8fd9f44786c757c7/debugpy-1.8.20.tar.gz", hash = "sha256:55bc8701714969f1ab89a6d5f2f3d40c36f91b2cbe2f65d98bf8196f6a6a2c33", size = 1645207, upload-time = "2026-01-29T23:03:28.199Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/e2/fc500524cc6f104a9d049abc85a0a8b3f0d14c0a39b9c140511c61e5b40b/debugpy-1.8.20-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:5dff4bb27027821fdfcc9e8f87309a28988231165147c31730128b1c983e282a", size = 2539560, upload-time = "2026-01-29T23:03:48.738Z" }, + { url = "https://files.pythonhosted.org/packages/90/83/fb33dcea789ed6018f8da20c5a9bc9d82adc65c0c990faed43f7c955da46/debugpy-1.8.20-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:84562982dd7cf5ebebfdea667ca20a064e096099997b175fe204e86817f64eaf", size = 4293272, upload-time = "2026-01-29T23:03:50.169Z" }, + { url = "https://files.pythonhosted.org/packages/a6/25/b1e4a01bfb824d79a6af24b99ef291e24189080c93576dfd9b1a2815cd0f/debugpy-1.8.20-cp313-cp313-win32.whl", hash = "sha256:da11dea6447b2cadbf8ce2bec59ecea87cc18d2c574980f643f2d2dfe4862393", size = 5331208, upload-time = "2026-01-29T23:03:51.547Z" }, + { url = "https://files.pythonhosted.org/packages/13/f7/a0b368ce54ffff9e9028c098bd2d28cfc5b54f9f6c186929083d4c60ba58/debugpy-1.8.20-cp313-cp313-win_amd64.whl", hash = "sha256:eb506e45943cab2efb7c6eafdd65b842f3ae779f020c82221f55aca9de135ed7", size = 5372930, upload-time = "2026-01-29T23:03:53.585Z" }, + { url = "https://files.pythonhosted.org/packages/33/2e/f6cb9a8a13f5058f0a20fe09711a7b726232cd5a78c6a7c05b2ec726cff9/debugpy-1.8.20-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:9c74df62fc064cd5e5eaca1353a3ef5a5d50da5eb8058fcef63106f7bebe6173", size = 2538066, upload-time = "2026-01-29T23:03:54.999Z" }, + { url = "https://files.pythonhosted.org/packages/c5/56/6ddca50b53624e1ca3ce1d1e49ff22db46c47ea5fb4c0cc5c9b90a616364/debugpy-1.8.20-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:077a7447589ee9bc1ff0cdf443566d0ecf540ac8aa7333b775ebcb8ce9f4ecad", size = 4269425, upload-time = "2026-01-29T23:03:56.518Z" }, + { url = "https://files.pythonhosted.org/packages/c5/d9/d64199c14a0d4c476df46c82470a3ce45c8d183a6796cfb5e66533b3663c/debugpy-1.8.20-cp314-cp314-win32.whl", hash = "sha256:352036a99dd35053b37b7803f748efc456076f929c6a895556932eaf2d23b07f", size = 5331407, upload-time = "2026-01-29T23:03:58.481Z" }, + { url = "https://files.pythonhosted.org/packages/e0/d9/1f07395b54413432624d61524dfd98c1a7c7827d2abfdb8829ac92638205/debugpy-1.8.20-cp314-cp314-win_amd64.whl", hash = "sha256:a98eec61135465b062846112e5ecf2eebb855305acc1dfbae43b72903b8ab5be", size = 5372521, upload-time = "2026-01-29T23:03:59.864Z" }, + { url = "https://files.pythonhosted.org/packages/e0/c3/7f67dea8ccf8fdcb9c99033bbe3e90b9e7395415843accb81428c441be2d/debugpy-1.8.20-py2.py3-none-any.whl", hash = "sha256:5be9bed9ae3be00665a06acaa48f8329d2b9632f15fd09f6a9a8c8d9907e54d7", size = 5337658, upload-time = "2026-01-29T23:04:17.404Z" }, +] + +[[package]] +name = "decorator" +version = "5.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", size = 56711, upload-time = "2025-02-24T04:41:34.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190, upload-time = "2025-02-24T04:41:32.565Z" }, +] + +[[package]] +name = "defusedxml" +version = "0.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520, upload-time = "2021-03-08T10:59:26.269Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" }, +] + +[[package]] +name = "executing" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, +] + [[package]] name = "fastexcel" version = "0.18.0" @@ -93,6 +417,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6f/ff/7c1f5af4b3339910f11a9b621b72e1345b8016c6dff99737e9df1388e911/fastexcel-0.18.0-cp314-cp314t-win_amd64.whl", hash = "sha256:79bb347d1ea573f6ed7de01cec0a3fc850ddaade0096f9500a07692b32541af4", size = 2890781, upload-time = "2025-11-24T11:07:51.133Z" }, ] +[[package]] +name = "fastjsonschema" +version = "2.21.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/b5/23b216d9d985a956623b6bd12d4086b60f0059b27799f23016af04a74ea1/fastjsonschema-2.21.2.tar.gz", hash = "sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de", size = 374130, upload-time = "2025-08-14T18:49:36.666Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl", hash = "sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463", size = 24024, upload-time = "2025-08-14T18:49:34.776Z" }, +] + [[package]] name = "fonttools" version = "4.61.1" @@ -131,22 +464,52 @@ name = "formation-python-initiation" version = "0.1.0" source = { virtual = "." } dependencies = [ + { name = "cartiflette" }, { name = "fastexcel" }, { name = "geopandas" }, + { name = "jupyter" }, + { name = "matplotlib" }, + { name = "numpy" }, + { name = "pandas" }, { name = "plotnine" }, { name = "polars" }, + { name = "pyarrow" }, + { name = "requests" }, + { name = "scikit-learn" }, + { name = "seaborn" }, + { name = "tidypolars" }, { name = "xlrd" }, ] [package.metadata] requires-dist = [ + { name = "cartiflette", specifier = ">=0.1.9" }, { name = "fastexcel", specifier = ">=0.18.0" }, { name = "geopandas", specifier = ">=1.1.1" }, + { name = "jupyter", specifier = ">=1.1.1" }, + { name = "matplotlib" }, + { name = "numpy" }, + { name = "pandas" }, { name = "plotnine", specifier = ">=0.15.2" }, { name = "polars", specifier = ">=1.36.1" }, + { name = "pyarrow" }, + { name = "pyarrow", specifier = ">=22.0.0" }, + { name = "requests", specifier = ">=2.32.5" }, + { name = "scikit-learn" }, + { name = "seaborn", specifier = ">=0.13.2" }, + { name = "tidypolars", specifier = ">=0.3.2" }, { name = "xlrd", specifier = ">=2.0.2" }, ] +[[package]] +name = "fqdn" +version = "1.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/3e/a80a8c077fd798951169626cde3e239adeba7dab75deb3555716415bd9b0/fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f", size = 6015, upload-time = "2021-03-11T07:16:29.08Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014", size = 9121, upload-time = "2021-03-11T07:16:28.351Z" }, +] + [[package]] name = "geopandas" version = "1.1.1" @@ -164,6 +527,426 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0b/70/d5cd0696eff08e62fdbdebe5b46527facb4e7220eabe0ac6225efab50168/geopandas-1.1.1-py3-none-any.whl", hash = "sha256:589e61aaf39b19828843df16cb90234e72897e2579be236f10eee0d052ad98e8", size = 338365, upload-time = "2025-06-26T21:04:55.139Z" }, ] +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + +[[package]] +name = "idna" +version = "3.11" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, +] + +[[package]] +name = "ipykernel" +version = "7.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "appnope", marker = "sys_platform == 'darwin'" }, + { name = "comm" }, + { name = "debugpy" }, + { name = "ipython" }, + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "matplotlib-inline" }, + { name = "nest-asyncio" }, + { name = "packaging" }, + { name = "psutil" }, + { name = "pyzmq" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ca/8d/b68b728e2d06b9e0051019640a40a9eb7a88fcd82c2e1b5ce70bef5ff044/ipykernel-7.2.0.tar.gz", hash = "sha256:18ed160b6dee2cbb16e5f3575858bc19d8f1fe6046a9a680c708494ce31d909e", size = 176046, upload-time = "2026-02-06T16:43:27.403Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl", hash = "sha256:3bbd4420d2b3cc105cbdf3756bfc04500b1e52f090a90716851f3916c62e1661", size = 118788, upload-time = "2026-02-06T16:43:25.149Z" }, +] + +[[package]] +name = "ipython" +version = "9.10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "decorator" }, + { name = "ipython-pygments-lexers" }, + { name = "jedi" }, + { name = "matplotlib-inline" }, + { name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "prompt-toolkit" }, + { name = "pygments" }, + { name = "stack-data" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a6/60/2111715ea11f39b1535bed6024b7dec7918b71e5e5d30855a5b503056b50/ipython-9.10.0.tar.gz", hash = "sha256:cd9e656be97618a0676d058134cd44e6dc7012c0e5cb36a9ce96a8c904adaf77", size = 4426526, upload-time = "2026-02-02T10:00:33.594Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/aa/898dec789a05731cd5a9f50605b7b44a72bd198fd0d4528e11fc610177cc/ipython-9.10.0-py3-none-any.whl", hash = "sha256:c6ab68cc23bba8c7e18e9b932797014cc61ea7fd6f19de180ab9ba73e65ee58d", size = 622774, upload-time = "2026-02-02T10:00:31.503Z" }, +] + +[[package]] +name = "ipython-pygments-lexers" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393, upload-time = "2025-01-17T11:24:34.505Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" }, +] + +[[package]] +name = "ipywidgets" +version = "8.1.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "comm" }, + { name = "ipython" }, + { name = "jupyterlab-widgets" }, + { name = "traitlets" }, + { name = "widgetsnbextension" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4c/ae/c5ce1edc1afe042eadb445e95b0671b03cee61895264357956e61c0d2ac0/ipywidgets-8.1.8.tar.gz", hash = "sha256:61f969306b95f85fba6b6986b7fe45d73124d1d9e3023a8068710d47a22ea668", size = 116739, upload-time = "2025-11-01T21:18:12.393Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl", hash = "sha256:ecaca67aed704a338f88f67b1181b58f821ab5dc89c1f0f5ef99db43c1c2921e", size = 139808, upload-time = "2025-11-01T21:18:10.956Z" }, +] + +[[package]] +name = "isoduration" +version = "20.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "arrow" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7c/1a/3c8edc664e06e6bd06cce40c6b22da5f1429aa4224d0c590f3be21c91ead/isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9", size = 11649, upload-time = "2020-11-01T11:00:00.312Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042", size = 11321, upload-time = "2020-11-01T10:59:58.02Z" }, +] + +[[package]] +name = "jedi" +version = "0.19.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "parso" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/72/3a/79a912fbd4d8dd6fbb02bf69afd3bb72cf0c729bb3063c6f4498603db17a/jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0", size = 1231287, upload-time = "2024-11-11T01:41:42.873Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9", size = 1572278, upload-time = "2024-11-11T01:41:40.175Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "joblib" +version = "1.5.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/41/f2/d34e8b3a08a9cc79a50b2208a93dce981fe615b64d5a4d4abee421d898df/joblib-1.5.3.tar.gz", hash = "sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3", size = 331603, upload-time = "2025-12-15T08:41:46.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713", size = 309071, upload-time = "2025-12-15T08:41:44.973Z" }, +] + +[[package]] +name = "json5" +version = "0.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/77/e8/a3f261a66e4663f22700bc8a17c08cb83e91fbf086726e7a228398968981/json5-0.13.0.tar.gz", hash = "sha256:b1edf8d487721c0bf64d83c28e91280781f6e21f4a797d3261c7c828d4c165bf", size = 52441, upload-time = "2026-01-01T19:42:14.99Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d7/9e/038522f50ceb7e74f1f991bf1b699f24b0c2bbe7c390dd36ad69f4582258/json5-0.13.0-py3-none-any.whl", hash = "sha256:9a08e1dd65f6a4d4c6fa82d216cf2477349ec2346a38fd70cc11d2557499fbcc", size = 36163, upload-time = "2026-01-01T19:42:13.962Z" }, +] + +[[package]] +name = "jsonpointer" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6a/0a/eebeb1fa92507ea94016a2a790b93c2ae41a7e18778f85471dc54475ed25/jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef", size = 9114, upload-time = "2024-06-10T19:24:42.462Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942", size = 7595, upload-time = "2024-06-10T19:24:40.698Z" }, +] + +[[package]] +name = "jsonschema" +version = "4.26.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" }, +] + +[package.optional-dependencies] +format-nongpl = [ + { name = "fqdn" }, + { name = "idna" }, + { name = "isoduration" }, + { name = "jsonpointer" }, + { name = "rfc3339-validator" }, + { name = "rfc3986-validator" }, + { name = "rfc3987-syntax" }, + { name = "uri-template" }, + { name = "webcolors" }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2025.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, +] + +[[package]] +name = "jupyter" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ipykernel" }, + { name = "ipywidgets" }, + { name = "jupyter-console" }, + { name = "jupyterlab" }, + { name = "nbconvert" }, + { name = "notebook" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/58/f3/af28ea964ab8bc1e472dba2e82627d36d470c51f5cd38c37502eeffaa25e/jupyter-1.1.1.tar.gz", hash = "sha256:d55467bceabdea49d7e3624af7e33d59c37fff53ed3a350e1ac957bed731de7a", size = 5714959, upload-time = "2024-08-30T07:15:48.299Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/64/285f20a31679bf547b75602702f7800e74dbabae36ef324f716c02804753/jupyter-1.1.1-py2.py3-none-any.whl", hash = "sha256:7a59533c22af65439b24bbe60373a4e95af8f16ac65a6c00820ad378e3f7cc83", size = 2657, upload-time = "2024-08-30T07:15:47.045Z" }, +] + +[[package]] +name = "jupyter-client" +version = "8.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-core" }, + { name = "python-dateutil" }, + { name = "pyzmq" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/05/e4/ba649102a3bc3fbca54e7239fb924fd434c766f855693d86de0b1f2bec81/jupyter_client-8.8.0.tar.gz", hash = "sha256:d556811419a4f2d96c869af34e854e3f059b7cc2d6d01a9cd9c85c267691be3e", size = 348020, upload-time = "2026-01-08T13:55:47.938Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl", hash = "sha256:f93a5b99c5e23a507b773d3a1136bd6e16c67883ccdbd9a829b0bbdb98cd7d7a", size = 107371, upload-time = "2026-01-08T13:55:45.562Z" }, +] + +[[package]] +name = "jupyter-console" +version = "6.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ipykernel" }, + { name = "ipython" }, + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "prompt-toolkit" }, + { name = "pygments" }, + { name = "pyzmq" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bd/2d/e2fd31e2fc41c14e2bcb6c976ab732597e907523f6b2420305f9fc7fdbdb/jupyter_console-6.6.3.tar.gz", hash = "sha256:566a4bf31c87adbfadf22cdf846e3069b59a71ed5da71d6ba4d8aaad14a53539", size = 34363, upload-time = "2023-03-06T14:13:31.02Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ca/77/71d78d58f15c22db16328a476426f7ac4a60d3a5a7ba3b9627ee2f7903d4/jupyter_console-6.6.3-py3-none-any.whl", hash = "sha256:309d33409fcc92ffdad25f0bcdf9a4a9daa61b6f341177570fdac03de5352485", size = 24510, upload-time = "2023-03-06T14:13:28.229Z" }, +] + +[[package]] +name = "jupyter-core" +version = "5.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "platformdirs" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/49/9d1284d0dc65e2c757b74c6687b6d319b02f822ad039e5c512df9194d9dd/jupyter_core-5.9.1.tar.gz", hash = "sha256:4d09aaff303b9566c3ce657f580bd089ff5c91f5f89cf7d8846c3cdf465b5508", size = 89814, upload-time = "2025-10-16T19:19:18.444Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl", hash = "sha256:ebf87fdc6073d142e114c72c9e29a9d7ca03fad818c5d300ce2adc1fb0743407", size = 29032, upload-time = "2025-10-16T19:19:16.783Z" }, +] + +[[package]] +name = "jupyter-events" +version = "0.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jsonschema", extra = ["format-nongpl"] }, + { name = "packaging" }, + { name = "python-json-logger" }, + { name = "pyyaml" }, + { name = "referencing" }, + { name = "rfc3339-validator" }, + { name = "rfc3986-validator" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9d/c3/306d090461e4cf3cd91eceaff84bede12a8e52cd821c2d20c9a4fd728385/jupyter_events-0.12.0.tar.gz", hash = "sha256:fc3fce98865f6784c9cd0a56a20644fc6098f21c8c33834a8d9fe383c17e554b", size = 62196, upload-time = "2025-02-03T17:23:41.485Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/48/577993f1f99c552f18a0428731a755e06171f9902fa118c379eb7c04ea22/jupyter_events-0.12.0-py3-none-any.whl", hash = "sha256:6464b2fa5ad10451c3d35fabc75eab39556ae1e2853ad0c0cc31b656731a97fb", size = 19430, upload-time = "2025-02-03T17:23:38.643Z" }, +] + +[[package]] +name = "jupyter-lsp" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-server" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/5a/9066c9f8e94ee517133cd98dba393459a16cd48bba71a82f16a65415206c/jupyter_lsp-2.3.0.tar.gz", hash = "sha256:458aa59339dc868fb784d73364f17dbce8836e906cd75fd471a325cba02e0245", size = 54823, upload-time = "2025-08-27T17:47:34.671Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1a/60/1f6cee0c46263de1173894f0fafcb3475ded276c472c14d25e0280c18d6d/jupyter_lsp-2.3.0-py3-none-any.whl", hash = "sha256:e914a3cb2addf48b1c7710914771aaf1819d46b2e5a79b0f917b5478ec93f34f", size = 76687, upload-time = "2025-08-27T17:47:33.15Z" }, +] + +[[package]] +name = "jupyter-server" +version = "2.17.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "argon2-cffi" }, + { name = "jinja2" }, + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "jupyter-events" }, + { name = "jupyter-server-terminals" }, + { name = "nbconvert" }, + { name = "nbformat" }, + { name = "packaging" }, + { name = "prometheus-client" }, + { name = "pywinpty", marker = "os_name == 'nt'" }, + { name = "pyzmq" }, + { name = "send2trash" }, + { name = "terminado" }, + { name = "tornado" }, + { name = "traitlets" }, + { name = "websocket-client" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/ac/e040ec363d7b6b1f11304cc9f209dac4517ece5d5e01821366b924a64a50/jupyter_server-2.17.0.tar.gz", hash = "sha256:c38ea898566964c888b4772ae1ed58eca84592e88251d2cfc4d171f81f7e99d5", size = 731949, upload-time = "2025-08-21T14:42:54.042Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/80/a24767e6ca280f5a49525d987bf3e4d7552bf67c8be07e8ccf20271f8568/jupyter_server-2.17.0-py3-none-any.whl", hash = "sha256:e8cb9c7db4251f51ed307e329b81b72ccf2056ff82d50524debde1ee1870e13f", size = 388221, upload-time = "2025-08-21T14:42:52.034Z" }, +] + +[[package]] +name = "jupyter-server-terminals" +version = "0.5.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pywinpty", marker = "os_name == 'nt'" }, + { name = "terminado" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f4/a7/bcd0a9b0cbba88986fe944aaaf91bfda603e5a50bda8ed15123f381a3b2f/jupyter_server_terminals-0.5.4.tar.gz", hash = "sha256:bbda128ed41d0be9020349f9f1f2a4ab9952a73ed5f5ac9f1419794761fb87f5", size = 31770, upload-time = "2026-01-14T16:53:20.213Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl", hash = "sha256:55be353fc74a80bc7f3b20e6be50a55a61cd525626f578dcb66a5708e2007d14", size = 13704, upload-time = "2026-01-14T16:53:18.738Z" }, +] + +[[package]] +name = "jupyterlab" +version = "4.5.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "async-lru" }, + { name = "httpx" }, + { name = "ipykernel" }, + { name = "jinja2" }, + { name = "jupyter-core" }, + { name = "jupyter-lsp" }, + { name = "jupyter-server" }, + { name = "jupyterlab-server" }, + { name = "notebook-shim" }, + { name = "packaging" }, + { name = "setuptools" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6e/2d/953a5612a34a3c799a62566a548e711d103f631672fd49650e0f2de80870/jupyterlab-4.5.5.tar.gz", hash = "sha256:eac620698c59eb810e1729909be418d9373d18137cac66637141abba613b3fda", size = 23968441, upload-time = "2026-02-23T18:57:34.339Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/52/372d3494766d690dfdd286871bf5f7fb9a6c61f7566ccaa7153a163dd1df/jupyterlab-4.5.5-py3-none-any.whl", hash = "sha256:a35694a40a8e7f2e82f387472af24e61b22adcce87b5a8ab97a5d9c486202a6d", size = 12446824, upload-time = "2026-02-23T18:57:30.398Z" }, +] + +[[package]] +name = "jupyterlab-pygments" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/90/51/9187be60d989df97f5f0aba133fa54e7300f17616e065d1ada7d7646b6d6/jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d", size = 512900, upload-time = "2023-11-23T09:26:37.44Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780", size = 15884, upload-time = "2023-11-23T09:26:34.325Z" }, +] + +[[package]] +name = "jupyterlab-server" +version = "2.28.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "babel" }, + { name = "jinja2" }, + { name = "json5" }, + { name = "jsonschema" }, + { name = "jupyter-server" }, + { name = "packaging" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d6/2c/90153f189e421e93c4bb4f9e3f59802a1f01abd2ac5cf40b152d7f735232/jupyterlab_server-2.28.0.tar.gz", hash = "sha256:35baa81898b15f93573e2deca50d11ac0ae407ebb688299d3a5213265033712c", size = 76996, upload-time = "2025-10-22T13:59:18.37Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl", hash = "sha256:e4355b148fdcf34d312bbbc80f22467d6d20460e8b8736bf235577dd18506968", size = 59830, upload-time = "2025-10-22T13:59:16.767Z" }, +] + +[[package]] +name = "jupyterlab-widgets" +version = "3.0.16" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/26/2d/ef58fed122b268c69c0aa099da20bc67657cdfb2e222688d5731bd5b971d/jupyterlab_widgets-3.0.16.tar.gz", hash = "sha256:423da05071d55cf27a9e602216d35a3a65a3e41cdf9c5d3b643b814ce38c19e0", size = 897423, upload-time = "2025-11-01T21:11:29.724Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl", hash = "sha256:45fa36d9c6422cf2559198e4db481aa243c7a32d9926b500781c830c80f7ecf8", size = 914926, upload-time = "2025-11-01T21:11:28.008Z" }, +] + [[package]] name = "kiwisolver" version = "1.4.9" @@ -223,6 +1006,67 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/80/be/3578e8afd18c88cdf9cb4cffde75a96d2be38c5a903f1ed0ceec061bd09e/kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32", size = 70260, upload-time = "2025-08-10T21:27:36.606Z" }, ] +[[package]] +name = "lark" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/34/28fff3ab31ccff1fd4f6c7c7b0ceb2b6968d8ea4950663eadcb5720591a0/lark-1.3.1.tar.gz", hash = "sha256:b426a7a6d6d53189d318f2b6236ab5d6429eaf09259f1ca33eb716eed10d2905", size = 382732, upload-time = "2025-10-27T18:25:56.653Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/3d/14ce75ef66813643812f3093ab17e46d3a206942ce7376d31ec2d36229e7/lark-1.3.1-py3-none-any.whl", hash = "sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12", size = 113151, upload-time = "2025-10-27T18:25:54.882Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, + { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, + { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, + { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, + { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, + { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, + { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, + { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, + { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, + { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, + { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, + { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, + { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, + { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, + { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, + { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, + { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, + { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, + { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, + { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, + { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, + { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, + { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, + { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, + { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, + { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, + { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, + { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, + { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, + { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, + { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, + { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, +] + [[package]] name = "matplotlib" version = "3.10.8" @@ -270,6 +1114,27 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5d/49/d651878698a0b67f23aa28e17f45a6d6dd3d3f933fa29087fa4ce5947b5a/matplotlib-3.10.8-cp314-cp314t-win_arm64.whl", hash = "sha256:113bb52413ea508ce954a02c10ffd0d565f9c3bc7f2eddc27dfe1731e71c7b5f", size = 8192560, upload-time = "2025-12-10T22:56:38.008Z" }, ] +[[package]] +name = "matplotlib-inline" +version = "0.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c7/74/97e72a36efd4ae2bccb3463284300f8953f199b5ffbc04cbbb0ec78f74b1/matplotlib_inline-0.2.1.tar.gz", hash = "sha256:e1ee949c340d771fc39e241ea75683deb94762c8fa5f2927ec57c83c4dffa9fe", size = 8110, upload-time = "2025-10-23T09:00:22.126Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76", size = 9516, upload-time = "2025-10-23T09:00:20.675Z" }, +] + +[[package]] +name = "mistune" +version = "3.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9d/55/d01f0c4b45ade6536c51170b9043db8b2ec6ddf4a35c7ea3f5f559ac935b/mistune-3.2.0.tar.gz", hash = "sha256:708487c8a8cdd99c9d90eb3ed4c3ed961246ff78ac82f03418f5183ab70e398a", size = 95467, upload-time = "2025-12-23T11:36:34.994Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl", hash = "sha256:febdc629a3c78616b94393c6580551e0e34cc289987ec6c35ed3f4be42d0eee1", size = 53598, upload-time = "2025-12-23T11:36:33.211Z" }, +] + [[package]] name = "mizani" version = "0.14.3" @@ -285,6 +1150,98 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5c/d2/4ffcaa27c8a4b4f9ad456da4821c76dfbdfada23e8210cd4d80e1eb3236a/mizani-0.14.3-py3-none-any.whl", hash = "sha256:6d2ca9b1b8366ff85668f0cc1b6095f1e702e26e66f132c4f02a949efa32a688", size = 133433, upload-time = "2025-10-30T20:16:51.218Z" }, ] +[[package]] +name = "nbclient" +version = "0.10.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "nbformat" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/56/91/1c1d5a4b9a9ebba2b4e32b8c852c2975c872aec1fe42ab5e516b2cecd193/nbclient-0.10.4.tar.gz", hash = "sha256:1e54091b16e6da39e297b0ece3e10f6f29f4ac4e8ee515d29f8a7099bd6553c9", size = 62554, upload-time = "2025-12-23T07:45:46.369Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl", hash = "sha256:9162df5a7373d70d606527300a95a975a47c137776cd942e52d9c7e29ff83440", size = 25465, upload-time = "2025-12-23T07:45:44.51Z" }, +] + +[[package]] +name = "nbconvert" +version = "7.17.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beautifulsoup4" }, + { name = "bleach", extra = ["css"] }, + { name = "defusedxml" }, + { name = "jinja2" }, + { name = "jupyter-core" }, + { name = "jupyterlab-pygments" }, + { name = "markupsafe" }, + { name = "mistune" }, + { name = "nbclient" }, + { name = "nbformat" }, + { name = "packaging" }, + { name = "pandocfilters" }, + { name = "pygments" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/38/47/81f886b699450d0569f7bc551df2b1673d18df7ff25cc0c21ca36ed8a5ff/nbconvert-7.17.0.tar.gz", hash = "sha256:1b2696f1b5be12309f6c7d707c24af604b87dfaf6d950794c7b07acab96dda78", size = 862855, upload-time = "2026-01-29T16:37:48.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/4b/8d5f796a792f8a25f6925a96032f098789f448571eb92011df1ae59e8ea8/nbconvert-7.17.0-py3-none-any.whl", hash = "sha256:4f99a63b337b9a23504347afdab24a11faa7d86b405e5c8f9881cd313336d518", size = 261510, upload-time = "2026-01-29T16:37:46.322Z" }, +] + +[[package]] +name = "nbformat" +version = "5.10.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fastjsonschema" }, + { name = "jsonschema" }, + { name = "jupyter-core" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6d/fd/91545e604bc3dad7dca9ed03284086039b294c6b3d75c0d2fa45f9e9caf3/nbformat-5.10.4.tar.gz", hash = "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a", size = 142749, upload-time = "2024-04-04T11:20:37.371Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b", size = 78454, upload-time = "2024-04-04T11:20:34.895Z" }, +] + +[[package]] +name = "nest-asyncio" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/83/f8/51569ac65d696c8ecbee95938f89d4abf00f47d58d48f6fbabfe8f0baefe/nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", size = 7418, upload-time = "2024-01-21T14:25:19.227Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195, upload-time = "2024-01-21T14:25:17.223Z" }, +] + +[[package]] +name = "notebook" +version = "7.5.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-server" }, + { name = "jupyterlab" }, + { name = "jupyterlab-server" }, + { name = "notebook-shim" }, + { name = "tornado" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/78/08/9d446fbb49f95de316ea6d7f25d0a4bc95117dd574e35f405895ac706f29/notebook-7.5.4.tar.gz", hash = "sha256:b928b2ba22cb63aa83df2e0e76fe3697950a0c1c4a41b84ebccf1972b1bb5771", size = 14167892, upload-time = "2026-02-24T14:13:56.116Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/59/01/05e5387b53e0f549212d5eff58845886f3827617b5c9409c966ddc07cb6d/notebook-7.5.4-py3-none-any.whl", hash = "sha256:860e31782b3d3a25ca0819ff039f5cf77845d1bf30c78ef9528b88b25e0a9850", size = 14578014, upload-time = "2026-02-24T14:13:52.274Z" }, +] + +[[package]] +name = "notebook-shim" +version = "0.2.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-server" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/54/d2/92fa3243712b9a3e8bafaf60aac366da1cada3639ca767ff4b5b3654ec28/notebook_shim-0.2.4.tar.gz", hash = "sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb", size = 13167, upload-time = "2024-02-14T23:35:18.353Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/33/bd5b9137445ea4b680023eb0469b2bb969d61303dedb2aac6560ff3d14a1/notebook_shim-0.2.4-py3-none-any.whl", hash = "sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef", size = 13307, upload-time = "2024-02-14T23:35:16.286Z" }, +] + [[package]] name = "numpy" version = "2.3.5" @@ -386,6 +1343,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/70/44/5191d2e4026f86a2a109053e194d3ba7a31a2d10a9c2348368c63ed4e85a/pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87", size = 13202175, upload-time = "2025-09-29T23:31:59.173Z" }, ] +[[package]] +name = "pandocfilters" +version = "1.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/70/6f/3dd4940bbe001c06a65f88e36bad298bc7a0de5036115639926b0c5c0458/pandocfilters-1.5.1.tar.gz", hash = "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e", size = 8454, upload-time = "2024-01-18T20:08:13.726Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/af/4fbc8cab944db5d21b7e2a5b8e9211a03a79852b1157e2c102fcc61ac440/pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc", size = 8663, upload-time = "2024-01-18T20:08:11.28Z" }, +] + +[[package]] +name = "parso" +version = "0.8.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/81/76/a1e769043c0c0c9fe391b702539d594731a4362334cdf4dc25d0c09761e7/parso-0.8.6.tar.gz", hash = "sha256:2b9a0332696df97d454fa67b81618fd69c35a7b90327cbe6ba5c92d2c68a7bfd", size = 401621, upload-time = "2026-02-09T15:45:24.425Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b6/61/fae042894f4296ec49e3f193aff5d7c18440da9e48102c3315e1bc4519a7/parso-0.8.6-py2.py3-none-any.whl", hash = "sha256:2c549f800b70a5c4952197248825584cb00f033b29c692671d3bf08bf380baff", size = 106894, upload-time = "2026-02-09T15:45:21.391Z" }, +] + [[package]] name = "patsy" version = "1.0.2" @@ -398,6 +1373,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl", hash = "sha256:37bfddbc58fcf0362febb5f54f10743f8b21dd2aa73dec7e7ef59d1b02ae668a", size = 233301, upload-time = "2025-10-20T16:17:36.563Z" }, ] +[[package]] +name = "pexpect" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ptyprocess" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" }, +] + [[package]] name = "pillow" version = "12.0.0" @@ -456,6 +1443,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c1/70/6b41bdcddf541b437bbb9f47f94d2db5d9ddef6c37ccab8c9107743748a4/pillow-12.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:99353a06902c2e43b43e8ff74ee65a7d90307d82370604746738a1e0661ccca7", size = 2525630, upload-time = "2025-10-15T18:23:57.149Z" }, ] +[[package]] +name = "platformdirs" +version = "4.9.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/04/fea538adf7dbbd6d186f551d595961e564a3b6715bdf276b477460858672/platformdirs-4.9.2.tar.gz", hash = "sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291", size = 28394, upload-time = "2026-02-16T03:56:10.574Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/48/31/05e764397056194206169869b50cf2fee4dbbbc71b344705b9c0d878d4d8/platformdirs-4.9.2-py3-none-any.whl", hash = "sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd", size = 21168, upload-time = "2026-02-16T03:56:08.891Z" }, +] + [[package]] name = "plotnine" version = "0.15.2" @@ -499,6 +1495,127 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d8/a12e6aa14f63784cead437083319ec7cece0d5bb9a5bfe7678cc6578b52a/polars_runtime_32-1.36.1-cp39-abi3-win_arm64.whl", hash = "sha256:809e73857be71250141225ddd5d2b30c97e6340aeaa0d445f930e01bef6888dc", size = 39798896, upload-time = "2025-12-10T01:14:11.568Z" }, ] +[[package]] +name = "prometheus-client" +version = "0.24.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f0/58/a794d23feb6b00fc0c72787d7e87d872a6730dd9ed7c7b3e954637d8f280/prometheus_client-0.24.1.tar.gz", hash = "sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9", size = 85616, upload-time = "2026-01-14T15:26:26.965Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl", hash = "sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055", size = 64057, upload-time = "2026-01-14T15:26:24.42Z" }, +] + +[[package]] +name = "prompt-toolkit" +version = "3.0.52" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, +] + +[[package]] +name = "psutil" +version = "7.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/c6/d1ddf4abb55e93cebc4f2ed8b5d6dbad109ecb8d63748dd2b20ab5e57ebe/psutil-7.2.2.tar.gz", hash = "sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372", size = 493740, upload-time = "2026-01-28T18:14:54.428Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/08/510cbdb69c25a96f4ae523f733cdc963ae654904e8db864c07585ef99875/psutil-7.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2edccc433cbfa046b980b0df0171cd25bcaeb3a68fe9022db0979e7aa74a826b", size = 130595, upload-time = "2026-01-28T18:14:57.293Z" }, + { url = "https://files.pythonhosted.org/packages/d6/f5/97baea3fe7a5a9af7436301f85490905379b1c6f2dd51fe3ecf24b4c5fbf/psutil-7.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78c8603dcd9a04c7364f1a3e670cea95d51ee865e4efb3556a3a63adef958ea", size = 131082, upload-time = "2026-01-28T18:14:59.732Z" }, + { url = "https://files.pythonhosted.org/packages/37/d6/246513fbf9fa174af531f28412297dd05241d97a75911ac8febefa1a53c6/psutil-7.2.2-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a571f2330c966c62aeda00dd24620425d4b0cc86881c89861fbc04549e5dc63", size = 181476, upload-time = "2026-01-28T18:15:01.884Z" }, + { url = "https://files.pythonhosted.org/packages/b8/b5/9182c9af3836cca61696dabe4fd1304e17bc56cb62f17439e1154f225dd3/psutil-7.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:917e891983ca3c1887b4ef36447b1e0873e70c933afc831c6b6da078ba474312", size = 184062, upload-time = "2026-01-28T18:15:04.436Z" }, + { url = "https://files.pythonhosted.org/packages/16/ba/0756dca669f5a9300d0cbcbfae9a4c30e446dfc7440ffe43ded5724bfd93/psutil-7.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:ab486563df44c17f5173621c7b198955bd6b613fb87c71c161f827d3fb149a9b", size = 139893, upload-time = "2026-01-28T18:15:06.378Z" }, + { url = "https://files.pythonhosted.org/packages/1c/61/8fa0e26f33623b49949346de05ec1ddaad02ed8ba64af45f40a147dbfa97/psutil-7.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:ae0aefdd8796a7737eccea863f80f81e468a1e4cf14d926bd9b6f5f2d5f90ca9", size = 135589, upload-time = "2026-01-28T18:15:08.03Z" }, + { url = "https://files.pythonhosted.org/packages/81/69/ef179ab5ca24f32acc1dac0c247fd6a13b501fd5534dbae0e05a1c48b66d/psutil-7.2.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00", size = 130664, upload-time = "2026-01-28T18:15:09.469Z" }, + { url = "https://files.pythonhosted.org/packages/7b/64/665248b557a236d3fa9efc378d60d95ef56dd0a490c2cd37dafc7660d4a9/psutil-7.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7b6d09433a10592ce39b13d7be5a54fbac1d1228ed29abc880fb23df7cb694c9", size = 131087, upload-time = "2026-01-28T18:15:11.724Z" }, + { url = "https://files.pythonhosted.org/packages/d5/2e/e6782744700d6759ebce3043dcfa661fb61e2fb752b91cdeae9af12c2178/psutil-7.2.2-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fa4ecf83bcdf6e6c8f4449aff98eefb5d0604bf88cb883d7da3d8d2d909546a", size = 182383, upload-time = "2026-01-28T18:15:13.445Z" }, + { url = "https://files.pythonhosted.org/packages/57/49/0a41cefd10cb7505cdc04dab3eacf24c0c2cb158a998b8c7b1d27ee2c1f5/psutil-7.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e452c464a02e7dc7822a05d25db4cde564444a67e58539a00f929c51eddda0cf", size = 185210, upload-time = "2026-01-28T18:15:16.002Z" }, + { url = "https://files.pythonhosted.org/packages/dd/2c/ff9bfb544f283ba5f83ba725a3c5fec6d6b10b8f27ac1dc641c473dc390d/psutil-7.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c7663d4e37f13e884d13994247449e9f8f574bc4655d509c3b95e9ec9e2b9dc1", size = 141228, upload-time = "2026-01-28T18:15:18.385Z" }, + { url = "https://files.pythonhosted.org/packages/f2/fc/f8d9c31db14fcec13748d373e668bc3bed94d9077dbc17fb0eebc073233c/psutil-7.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:11fe5a4f613759764e79c65cf11ebdf26e33d6dd34336f8a337aa2996d71c841", size = 136284, upload-time = "2026-01-28T18:15:19.912Z" }, + { url = "https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486", size = 129090, upload-time = "2026-01-28T18:15:22.168Z" }, + { url = "https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979", size = 129859, upload-time = "2026-01-28T18:15:23.795Z" }, + { url = "https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9", size = 155560, upload-time = "2026-01-28T18:15:25.976Z" }, + { url = "https://files.pythonhosted.org/packages/63/65/37648c0c158dc222aba51c089eb3bdfa238e621674dc42d48706e639204f/psutil-7.2.2-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b0726cecd84f9474419d67252add4ac0cd9811b04d61123054b9fb6f57df6e9e", size = 156997, upload-time = "2026-01-28T18:15:27.794Z" }, + { url = "https://files.pythonhosted.org/packages/8e/13/125093eadae863ce03c6ffdbae9929430d116a246ef69866dad94da3bfbc/psutil-7.2.2-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8", size = 148972, upload-time = "2026-01-28T18:15:29.342Z" }, + { url = "https://files.pythonhosted.org/packages/04/78/0acd37ca84ce3ddffaa92ef0f571e073faa6d8ff1f0559ab1272188ea2be/psutil-7.2.2-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b58fabe35e80b264a4e3bb23e6b96f9e45a3df7fb7eed419ac0e5947c61e47cc", size = 148266, upload-time = "2026-01-28T18:15:31.597Z" }, + { url = "https://files.pythonhosted.org/packages/b4/90/e2159492b5426be0c1fef7acba807a03511f97c5f86b3caeda6ad92351a7/psutil-7.2.2-cp37-abi3-win_amd64.whl", hash = "sha256:eb7e81434c8d223ec4a219b5fc1c47d0417b12be7ea866e24fb5ad6e84b3d988", size = 137737, upload-time = "2026-01-28T18:15:33.849Z" }, + { url = "https://files.pythonhosted.org/packages/8c/c7/7bb2e321574b10df20cbde462a94e2b71d05f9bbda251ef27d104668306a/psutil-7.2.2-cp37-abi3-win_arm64.whl", hash = "sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee", size = 134617, upload-time = "2026-01-28T18:15:36.514Z" }, +] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762, upload-time = "2020-12-28T15:15:30.155Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993, upload-time = "2020-12-28T15:15:28.35Z" }, +] + +[[package]] +name = "pure-eval" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752, upload-time = "2024-07-21T12:58:21.801Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" }, +] + +[[package]] +name = "pyarrow" +version = "23.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/88/22/134986a4cc224d593c1afde5494d18ff629393d74cc2eddb176669f234a4/pyarrow-23.0.1.tar.gz", hash = "sha256:b8c5873e33440b2bc2f4a79d2b47017a89c5a24116c055625e6f2ee50523f019", size = 1167336, upload-time = "2026-02-16T10:14:12.39Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/10/2cbe4c6f0fb83d2de37249567373d64327a5e4d8db72f486db42875b08f6/pyarrow-23.0.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:6b8fda694640b00e8af3c824f99f789e836720aa8c9379fb435d4c4953a756b8", size = 34210066, upload-time = "2026-02-16T10:10:45.487Z" }, + { url = "https://files.pythonhosted.org/packages/cb/4f/679fa7e84dadbaca7a65f7cdba8d6c83febbd93ca12fa4adf40ba3b6362b/pyarrow-23.0.1-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:8ff51b1addc469b9444b7c6f3548e19dc931b172ab234e995a60aea9f6e6025f", size = 35825526, upload-time = "2026-02-16T10:10:52.266Z" }, + { url = "https://files.pythonhosted.org/packages/f9/63/d2747d930882c9d661e9398eefc54f15696547b8983aaaf11d4a2e8b5426/pyarrow-23.0.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:71c5be5cbf1e1cb6169d2a0980850bccb558ddc9b747b6206435313c47c37677", size = 44473279, upload-time = "2026-02-16T10:11:01.557Z" }, + { url = "https://files.pythonhosted.org/packages/b3/93/10a48b5e238de6d562a411af6467e71e7aedbc9b87f8d3a35f1560ae30fb/pyarrow-23.0.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:9b6f4f17b43bc39d56fec96e53fe89d94bac3eb134137964371b45352d40d0c2", size = 47585798, upload-time = "2026-02-16T10:11:09.401Z" }, + { url = "https://files.pythonhosted.org/packages/5c/20/476943001c54ef078dbf9542280e22741219a184a0632862bca4feccd666/pyarrow-23.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fc13fc6c403d1337acab46a2c4346ca6c9dec5780c3c697cf8abfd5e19b6b37", size = 48179446, upload-time = "2026-02-16T10:11:17.781Z" }, + { url = "https://files.pythonhosted.org/packages/4b/b6/5dd0c47b335fcd8edba9bfab78ad961bd0fd55ebe53468cc393f45e0be60/pyarrow-23.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5c16ed4f53247fa3ffb12a14d236de4213a4415d127fe9cebed33d51671113e2", size = 50623972, upload-time = "2026-02-16T10:11:26.185Z" }, + { url = "https://files.pythonhosted.org/packages/d5/09/a532297c9591a727d67760e2e756b83905dd89adb365a7f6e9c72578bcc1/pyarrow-23.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:cecfb12ef629cf6be0b1887f9f86463b0dd3dc3195ae6224e74006be4736035a", size = 27540749, upload-time = "2026-02-16T10:12:23.297Z" }, + { url = "https://files.pythonhosted.org/packages/a5/8e/38749c4b1303e6ae76b3c80618f84861ae0c55dd3c2273842ea6f8258233/pyarrow-23.0.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:29f7f7419a0e30264ea261fdc0e5fe63ce5a6095003db2945d7cd78df391a7e1", size = 34471544, upload-time = "2026-02-16T10:11:32.535Z" }, + { url = "https://files.pythonhosted.org/packages/a3/73/f237b2bc8c669212f842bcfd842b04fc8d936bfc9d471630569132dc920d/pyarrow-23.0.1-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:33d648dc25b51fd8055c19e4261e813dfc4d2427f068bcecc8b53d01b81b0500", size = 35949911, upload-time = "2026-02-16T10:11:39.813Z" }, + { url = "https://files.pythonhosted.org/packages/0c/86/b912195eee0903b5611bf596833def7d146ab2d301afeb4b722c57ffc966/pyarrow-23.0.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:cd395abf8f91c673dd3589cadc8cc1ee4e8674fa61b2e923c8dd215d9c7d1f41", size = 44520337, upload-time = "2026-02-16T10:11:47.764Z" }, + { url = "https://files.pythonhosted.org/packages/69/c2/f2a717fb824f62d0be952ea724b4f6f9372a17eed6f704b5c9526f12f2f1/pyarrow-23.0.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:00be9576d970c31defb5c32eb72ef585bf600ef6d0a82d5eccaae96639cf9d07", size = 47548944, upload-time = "2026-02-16T10:11:56.607Z" }, + { url = "https://files.pythonhosted.org/packages/84/a7/90007d476b9f0dc308e3bc57b832d004f848fd6c0da601375d20d92d1519/pyarrow-23.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c2139549494445609f35a5cda4eb94e2c9e4d704ce60a095b342f82460c73a83", size = 48236269, upload-time = "2026-02-16T10:12:04.47Z" }, + { url = "https://files.pythonhosted.org/packages/b0/3f/b16fab3e77709856eb6ac328ce35f57a6d4a18462c7ca5186ef31b45e0e0/pyarrow-23.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:7044b442f184d84e2351e5084600f0d7343d6117aabcbc1ac78eb1ae11eb4125", size = 50604794, upload-time = "2026-02-16T10:12:11.797Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a1/22df0620a9fac31d68397a75465c344e83c3dfe521f7612aea33e27ab6c0/pyarrow-23.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:a35581e856a2fafa12f3f54fce4331862b1cfb0bef5758347a858a4aa9d6bae8", size = 27660642, upload-time = "2026-02-16T10:12:17.746Z" }, + { url = "https://files.pythonhosted.org/packages/8d/1b/6da9a89583ce7b23ac611f183ae4843cd3a6cf54f079549b0e8c14031e73/pyarrow-23.0.1-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:5df1161da23636a70838099d4aaa65142777185cc0cdba4037a18cee7d8db9ca", size = 34238755, upload-time = "2026-02-16T10:12:32.819Z" }, + { url = "https://files.pythonhosted.org/packages/ae/b5/d58a241fbe324dbaeb8df07be6af8752c846192d78d2272e551098f74e88/pyarrow-23.0.1-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:fa8e51cb04b9f8c9c5ace6bab63af9a1f88d35c0d6cbf53e8c17c098552285e1", size = 35847826, upload-time = "2026-02-16T10:12:38.949Z" }, + { url = "https://files.pythonhosted.org/packages/54/a5/8cbc83f04aba433ca7b331b38f39e000efd9f0c7ce47128670e737542996/pyarrow-23.0.1-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:0b95a3994f015be13c63148fef8832e8a23938128c185ee951c98908a696e0eb", size = 44536859, upload-time = "2026-02-16T10:12:45.467Z" }, + { url = "https://files.pythonhosted.org/packages/36/2e/c0f017c405fcdc252dbccafbe05e36b0d0eb1ea9a958f081e01c6972927f/pyarrow-23.0.1-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:4982d71350b1a6e5cfe1af742c53dfb759b11ce14141870d05d9e540d13bc5d1", size = 47614443, upload-time = "2026-02-16T10:12:55.525Z" }, + { url = "https://files.pythonhosted.org/packages/af/6b/2314a78057912f5627afa13ba43809d9d653e6630859618b0fd81a4e0759/pyarrow-23.0.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c250248f1fe266db627921c89b47b7c06fee0489ad95b04d50353537d74d6886", size = 48232991, upload-time = "2026-02-16T10:13:04.729Z" }, + { url = "https://files.pythonhosted.org/packages/40/f2/1bcb1d3be3460832ef3370d621142216e15a2c7c62602a4ea19ec240dd64/pyarrow-23.0.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5f4763b83c11c16e5f4c15601ba6dfa849e20723b46aa2617cb4bffe8768479f", size = 50645077, upload-time = "2026-02-16T10:13:14.147Z" }, + { url = "https://files.pythonhosted.org/packages/eb/3f/b1da7b61cd66566a4d4c8383d376c606d1c34a906c3f1cb35c479f59d1aa/pyarrow-23.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:3a4c85ef66c134161987c17b147d6bffdca4566f9a4c1d81a0a01cdf08414ea5", size = 28234271, upload-time = "2026-02-16T10:14:09.397Z" }, + { url = "https://files.pythonhosted.org/packages/b5/78/07f67434e910a0f7323269be7bfbf58699bd0c1d080b18a1ab49ba943fe8/pyarrow-23.0.1-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:17cd28e906c18af486a499422740298c52d7c6795344ea5002a7720b4eadf16d", size = 34488692, upload-time = "2026-02-16T10:13:21.541Z" }, + { url = "https://files.pythonhosted.org/packages/50/76/34cf7ae93ece1f740a04910d9f7e80ba166b9b4ab9596a953e9e62b90fe1/pyarrow-23.0.1-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:76e823d0e86b4fb5e1cf4a58d293036e678b5a4b03539be933d3b31f9406859f", size = 35964383, upload-time = "2026-02-16T10:13:28.63Z" }, + { url = "https://files.pythonhosted.org/packages/46/90/459b827238936d4244214be7c684e1b366a63f8c78c380807ae25ed92199/pyarrow-23.0.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:a62e1899e3078bf65943078b3ad2a6ddcacf2373bc06379aac61b1e548a75814", size = 44538119, upload-time = "2026-02-16T10:13:35.506Z" }, + { url = "https://files.pythonhosted.org/packages/28/a1/93a71ae5881e99d1f9de1d4554a87be37da11cd6b152239fb5bd924fdc64/pyarrow-23.0.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:df088e8f640c9fae3b1f495b3c64755c4e719091caf250f3a74d095ddf3c836d", size = 47571199, upload-time = "2026-02-16T10:13:42.504Z" }, + { url = "https://files.pythonhosted.org/packages/88/a3/d2c462d4ef313521eaf2eff04d204ac60775263f1fb08c374b543f79f610/pyarrow-23.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:46718a220d64677c93bc243af1d44b55998255427588e400677d7192671845c7", size = 48259435, upload-time = "2026-02-16T10:13:49.226Z" }, + { url = "https://files.pythonhosted.org/packages/cc/f1/11a544b8c3d38a759eb3fbb022039117fd633e9a7b19e4841cc3da091915/pyarrow-23.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a09f3876e87f48bc2f13583ab551f0379e5dfb83210391e68ace404181a20690", size = 50629149, upload-time = "2026-02-16T10:13:57.238Z" }, + { url = "https://files.pythonhosted.org/packages/50/f2/c0e76a0b451ffdf0cf788932e182758eb7558953f4f27f1aff8e2518b653/pyarrow-23.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:527e8d899f14bd15b740cd5a54ad56b7f98044955373a17179d5956ddb93d9ce", size = 28365807, upload-time = "2026-02-16T10:14:03.892Z" }, +] + +[[package]] +name = "pycparser" +version = "3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + [[package]] name = "pyogrio" version = "0.12.1" @@ -604,6 +1721,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, ] +[[package]] +name = "python-json-logger" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/29/bf/eca6a3d43db1dae7070f70e160ab20b807627ba953663ba07928cdd3dc58/python_json_logger-4.0.0.tar.gz", hash = "sha256:f58e68eb46e1faed27e0f574a55a0455eecd7b8a5b88b85a784519ba3cff047f", size = 17683, upload-time = "2025-10-06T04:15:18.984Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl", hash = "sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2", size = 15548, upload-time = "2025-10-06T04:15:17.553Z" }, +] + [[package]] name = "pytz" version = "2025.2" @@ -613,6 +1739,283 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" }, ] +[[package]] +name = "pywinpty" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f7/54/37c7370ba91f579235049dc26cd2c5e657d2a943e01820844ffc81f32176/pywinpty-3.0.3.tar.gz", hash = "sha256:523441dc34d231fb361b4b00f8c99d3f16de02f5005fd544a0183112bcc22412", size = 31309, upload-time = "2026-02-04T21:51:09.524Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/cb/58d6ed3fd429c96a90ef01ac9a617af10a6d41469219c25e7dc162abbb71/pywinpty-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9c91dbb026050c77bdcef964e63a4f10f01a639113c4d3658332614544c467ab", size = 2112686, upload-time = "2026-02-04T21:52:03.035Z" }, + { url = "https://files.pythonhosted.org/packages/fd/50/724ed5c38c504d4e58a88a072776a1e880d970789deaeb2b9f7bd9a5141a/pywinpty-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:fe1f7911805127c94cf51f89ab14096c6f91ffdcacf993d2da6082b2142a2523", size = 234591, upload-time = "2026-02-04T21:52:29.821Z" }, + { url = "https://files.pythonhosted.org/packages/f7/ad/90a110538696b12b39fd8758a06d70ded899308198ad2305ac68e361126e/pywinpty-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:3f07a6cf1c1d470d284e614733c3d0f726d2c85e78508ea10a403140c3c0c18a", size = 2112360, upload-time = "2026-02-04T21:55:33.397Z" }, + { url = "https://files.pythonhosted.org/packages/44/0f/7ffa221757a220402bc79fda44044c3f2cc57338d878ab7d622add6f4581/pywinpty-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:15c7c0b6f8e9d87aabbaff76468dabf6e6121332c40fc1d83548d02a9d6a3759", size = 233107, upload-time = "2026-02-04T21:51:45.455Z" }, + { url = "https://files.pythonhosted.org/packages/28/88/2ff917caff61e55f38bcdb27de06ee30597881b2cae44fbba7627be015c4/pywinpty-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:d4b6b7b0fe0cdcd02e956bd57cfe9f4e5a06514eecf3b5ae174da4f951b58be9", size = 2113282, upload-time = "2026-02-04T21:52:08.188Z" }, + { url = "https://files.pythonhosted.org/packages/63/32/40a775343ace542cc43ece3f1d1fce454021521ecac41c4c4573081c2336/pywinpty-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:34789d685fc0d547ce0c8a65e5a70e56f77d732fa6e03c8f74fefb8cbb252019", size = 234207, upload-time = "2026-02-04T21:51:58.687Z" }, + { url = "https://files.pythonhosted.org/packages/8d/54/5d5e52f4cb75028104ca6faf36c10f9692389b1986d34471663b4ebebd6d/pywinpty-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:0c37e224a47a971d1a6e08649a1714dac4f63c11920780977829ed5c8cadead1", size = 2112910, upload-time = "2026-02-04T21:52:30.976Z" }, + { url = "https://files.pythonhosted.org/packages/0a/44/dcd184824e21d4620b06c7db9fbb15c3ad0a0f1fa2e6de79969fb82647ec/pywinpty-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:c4e9c3dff7d86ba81937438d5819f19f385a39d8f592d4e8af67148ceb4f6ab5", size = 233425, upload-time = "2026-02-04T21:51:56.754Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] + +[[package]] +name = "pyzmq" +version = "27.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "implementation_name == 'pypy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/0b/3c9baedbdf613ecaa7aa07027780b8867f57b6293b6ee50de316c9f3222b/pyzmq-27.1.0.tar.gz", hash = "sha256:ac0765e3d44455adb6ddbf4417dcce460fc40a05978c08efdf2948072f6db540", size = 281750, upload-time = "2025-09-08T23:10:18.157Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:452631b640340c928fa343801b0d07eb0c3789a5ffa843f6e1a9cee0ba4eb4fc", size = 1306279, upload-time = "2025-09-08T23:08:03.807Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5e/c3c49fdd0f535ef45eefcc16934648e9e59dace4a37ee88fc53f6cd8e641/pyzmq-27.1.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1c179799b118e554b66da67d88ed66cd37a169f1f23b5d9f0a231b4e8d44a113", size = 895645, upload-time = "2025-09-08T23:08:05.301Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e5/b0b2504cb4e903a74dcf1ebae157f9e20ebb6ea76095f6cfffea28c42ecd/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3837439b7f99e60312f0c926a6ad437b067356dc2bc2ec96eb395fd0fe804233", size = 652574, upload-time = "2025-09-08T23:08:06.828Z" }, + { url = "https://files.pythonhosted.org/packages/f8/9b/c108cdb55560eaf253f0cbdb61b29971e9fb34d9c3499b0e96e4e60ed8a5/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43ad9a73e3da1fab5b0e7e13402f0b2fb934ae1c876c51d0afff0e7c052eca31", size = 840995, upload-time = "2025-09-08T23:08:08.396Z" }, + { url = "https://files.pythonhosted.org/packages/c2/bb/b79798ca177b9eb0825b4c9998c6af8cd2a7f15a6a1a4272c1d1a21d382f/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0de3028d69d4cdc475bfe47a6128eb38d8bc0e8f4d69646adfbcd840facbac28", size = 1642070, upload-time = "2025-09-08T23:08:09.989Z" }, + { url = "https://files.pythonhosted.org/packages/9c/80/2df2e7977c4ede24c79ae39dcef3899bfc5f34d1ca7a5b24f182c9b7a9ca/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:cf44a7763aea9298c0aa7dbf859f87ed7012de8bda0f3977b6fb1d96745df856", size = 2021121, upload-time = "2025-09-08T23:08:11.907Z" }, + { url = "https://files.pythonhosted.org/packages/46/bd/2d45ad24f5f5ae7e8d01525eb76786fa7557136555cac7d929880519e33a/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f30f395a9e6fbca195400ce833c731e7b64c3919aa481af4d88c3759e0cb7496", size = 1878550, upload-time = "2025-09-08T23:08:13.513Z" }, + { url = "https://files.pythonhosted.org/packages/e6/2f/104c0a3c778d7c2ab8190e9db4f62f0b6957b53c9d87db77c284b69f33ea/pyzmq-27.1.0-cp312-abi3-win32.whl", hash = "sha256:250e5436a4ba13885494412b3da5d518cd0d3a278a1ae640e113c073a5f88edd", size = 559184, upload-time = "2025-09-08T23:08:15.163Z" }, + { url = "https://files.pythonhosted.org/packages/fc/7f/a21b20d577e4100c6a41795842028235998a643b1ad406a6d4163ea8f53e/pyzmq-27.1.0-cp312-abi3-win_amd64.whl", hash = "sha256:9ce490cf1d2ca2ad84733aa1d69ce6855372cb5ce9223802450c9b2a7cba0ccf", size = 619480, upload-time = "2025-09-08T23:08:17.192Z" }, + { url = "https://files.pythonhosted.org/packages/78/c2/c012beae5f76b72f007a9e91ee9401cb88c51d0f83c6257a03e785c81cc2/pyzmq-27.1.0-cp312-abi3-win_arm64.whl", hash = "sha256:75a2f36223f0d535a0c919e23615fc85a1e23b71f40c7eb43d7b1dedb4d8f15f", size = 552993, upload-time = "2025-09-08T23:08:18.926Z" }, + { url = "https://files.pythonhosted.org/packages/60/cb/84a13459c51da6cec1b7b1dc1a47e6db6da50b77ad7fd9c145842750a011/pyzmq-27.1.0-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:93ad4b0855a664229559e45c8d23797ceac03183c7b6f5b4428152a6b06684a5", size = 1122436, upload-time = "2025-09-08T23:08:20.801Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b6/94414759a69a26c3dd674570a81813c46a078767d931a6c70ad29fc585cb/pyzmq-27.1.0-cp313-cp313-android_24_x86_64.whl", hash = "sha256:fbb4f2400bfda24f12f009cba62ad5734148569ff4949b1b6ec3b519444342e6", size = 1156301, upload-time = "2025-09-08T23:08:22.47Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ad/15906493fd40c316377fd8a8f6b1f93104f97a752667763c9b9c1b71d42d/pyzmq-27.1.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:e343d067f7b151cfe4eb3bb796a7752c9d369eed007b91231e817071d2c2fec7", size = 1341197, upload-time = "2025-09-08T23:08:24.286Z" }, + { url = "https://files.pythonhosted.org/packages/14/1d/d343f3ce13db53a54cb8946594e567410b2125394dafcc0268d8dda027e0/pyzmq-27.1.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:08363b2011dec81c354d694bdecaef4770e0ae96b9afea70b3f47b973655cc05", size = 897275, upload-time = "2025-09-08T23:08:26.063Z" }, + { url = "https://files.pythonhosted.org/packages/69/2d/d83dd6d7ca929a2fc67d2c3005415cdf322af7751d773524809f9e585129/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d54530c8c8b5b8ddb3318f481297441af102517602b569146185fa10b63f4fa9", size = 660469, upload-time = "2025-09-08T23:08:27.623Z" }, + { url = "https://files.pythonhosted.org/packages/3e/cd/9822a7af117f4bc0f1952dbe9ef8358eb50a24928efd5edf54210b850259/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f3afa12c392f0a44a2414056d730eebc33ec0926aae92b5ad5cf26ebb6cc128", size = 847961, upload-time = "2025-09-08T23:08:29.672Z" }, + { url = "https://files.pythonhosted.org/packages/9a/12/f003e824a19ed73be15542f172fd0ec4ad0b60cf37436652c93b9df7c585/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c65047adafe573ff023b3187bb93faa583151627bc9c51fc4fb2c561ed689d39", size = 1650282, upload-time = "2025-09-08T23:08:31.349Z" }, + { url = "https://files.pythonhosted.org/packages/d5/4a/e82d788ed58e9a23995cee70dbc20c9aded3d13a92d30d57ec2291f1e8a3/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:90e6e9441c946a8b0a667356f7078d96411391a3b8f80980315455574177ec97", size = 2024468, upload-time = "2025-09-08T23:08:33.543Z" }, + { url = "https://files.pythonhosted.org/packages/d9/94/2da0a60841f757481e402b34bf4c8bf57fa54a5466b965de791b1e6f747d/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:add071b2d25f84e8189aaf0882d39a285b42fa3853016ebab234a5e78c7a43db", size = 1885394, upload-time = "2025-09-08T23:08:35.51Z" }, + { url = "https://files.pythonhosted.org/packages/4f/6f/55c10e2e49ad52d080dc24e37adb215e5b0d64990b57598abc2e3f01725b/pyzmq-27.1.0-cp313-cp313t-win32.whl", hash = "sha256:7ccc0700cfdf7bd487bea8d850ec38f204478681ea02a582a8da8171b7f90a1c", size = 574964, upload-time = "2025-09-08T23:08:37.178Z" }, + { url = "https://files.pythonhosted.org/packages/87/4d/2534970ba63dd7c522d8ca80fb92777f362c0f321900667c615e2067cb29/pyzmq-27.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:8085a9fba668216b9b4323be338ee5437a235fe275b9d1610e422ccc279733e2", size = 641029, upload-time = "2025-09-08T23:08:40.595Z" }, + { url = "https://files.pythonhosted.org/packages/f6/fa/f8aea7a28b0641f31d40dea42d7ef003fded31e184ef47db696bc74cd610/pyzmq-27.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:6bb54ca21bcfe361e445256c15eedf083f153811c37be87e0514934d6913061e", size = 561541, upload-time = "2025-09-08T23:08:42.668Z" }, + { url = "https://files.pythonhosted.org/packages/87/45/19efbb3000956e82d0331bafca5d9ac19ea2857722fa2caacefb6042f39d/pyzmq-27.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:ce980af330231615756acd5154f29813d553ea555485ae712c491cd483df6b7a", size = 1341197, upload-time = "2025-09-08T23:08:44.973Z" }, + { url = "https://files.pythonhosted.org/packages/48/43/d72ccdbf0d73d1343936296665826350cb1e825f92f2db9db3e61c2162a2/pyzmq-27.1.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1779be8c549e54a1c38f805e56d2a2e5c009d26de10921d7d51cfd1c8d4632ea", size = 897175, upload-time = "2025-09-08T23:08:46.601Z" }, + { url = "https://files.pythonhosted.org/packages/2f/2e/a483f73a10b65a9ef0161e817321d39a770b2acf8bcf3004a28d90d14a94/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7200bb0f03345515df50d99d3db206a0a6bee1955fbb8c453c76f5bf0e08fb96", size = 660427, upload-time = "2025-09-08T23:08:48.187Z" }, + { url = "https://files.pythonhosted.org/packages/f5/d2/5f36552c2d3e5685abe60dfa56f91169f7a2d99bbaf67c5271022ab40863/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01c0e07d558b06a60773744ea6251f769cd79a41a97d11b8bf4ab8f034b0424d", size = 847929, upload-time = "2025-09-08T23:08:49.76Z" }, + { url = "https://files.pythonhosted.org/packages/c4/2a/404b331f2b7bf3198e9945f75c4c521f0c6a3a23b51f7a4a401b94a13833/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:80d834abee71f65253c91540445d37c4c561e293ba6e741b992f20a105d69146", size = 1650193, upload-time = "2025-09-08T23:08:51.7Z" }, + { url = "https://files.pythonhosted.org/packages/1c/0b/f4107e33f62a5acf60e3ded67ed33d79b4ce18de432625ce2fc5093d6388/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:544b4e3b7198dde4a62b8ff6685e9802a9a1ebf47e77478a5eb88eca2a82f2fd", size = 2024388, upload-time = "2025-09-08T23:08:53.393Z" }, + { url = "https://files.pythonhosted.org/packages/0d/01/add31fe76512642fd6e40e3a3bd21f4b47e242c8ba33efb6809e37076d9b/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cedc4c68178e59a4046f97eca31b148ddcf51e88677de1ef4e78cf06c5376c9a", size = 1885316, upload-time = "2025-09-08T23:08:55.702Z" }, + { url = "https://files.pythonhosted.org/packages/c4/59/a5f38970f9bf07cee96128de79590bb354917914a9be11272cfc7ff26af0/pyzmq-27.1.0-cp314-cp314t-win32.whl", hash = "sha256:1f0b2a577fd770aa6f053211a55d1c47901f4d537389a034c690291485e5fe92", size = 587472, upload-time = "2025-09-08T23:08:58.18Z" }, + { url = "https://files.pythonhosted.org/packages/70/d8/78b1bad170f93fcf5e3536e70e8fadac55030002275c9a29e8f5719185de/pyzmq-27.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:19c9468ae0437f8074af379e986c5d3d7d7bfe033506af442e8c879732bedbe0", size = 661401, upload-time = "2025-09-08T23:08:59.802Z" }, + { url = "https://files.pythonhosted.org/packages/81/d6/4bfbb40c9a0b42fc53c7cf442f6385db70b40f74a783130c5d0a5aa62228/pyzmq-27.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dc5dbf68a7857b59473f7df42650c621d7e8923fb03fa74a526890f4d33cc4d7", size = 575170, upload-time = "2025-09-08T23:09:01.418Z" }, +] + +[[package]] +name = "referencing" +version = "0.37.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" }, +] + +[[package]] +name = "requests" +version = "2.32.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, +] + +[[package]] +name = "requests-cache" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "cattrs" }, + { name = "platformdirs" }, + { name = "requests" }, + { name = "url-normalize" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a4/6c/deaf1a9462ce8b6a9ac0ee3603d9ba32917be8e48c8f6799770d5418c3cb/requests_cache-1.3.0.tar.gz", hash = "sha256:070e357ccef11a300ccef4294a85de1ab265833c5d9c9538b26cd7ba4085d54a", size = 97720, upload-time = "2026-02-02T23:17:33.245Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/68/3f/dfa42bb16be96d53351aa151cb1e39fcaafe6cda01389c530a2ec809ef8a/requests_cache-1.3.0-py3-none-any.whl", hash = "sha256:f09f27bbf100c250886acf13a9db35b53cf2852fddd71977b47c71ea7d90dbba", size = 69626, upload-time = "2026-02-02T23:17:31.718Z" }, +] + +[[package]] +name = "rfc3339-validator" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/ea/a9387748e2d111c3c2b275ba970b735e04e15cdb1eb30693b6b5708c4dbd/rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b", size = 5513, upload-time = "2021-05-12T16:37:54.178Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa", size = 3490, upload-time = "2021-05-12T16:37:52.536Z" }, +] + +[[package]] +name = "rfc3986-validator" +version = "0.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/88/f270de456dd7d11dcc808abfa291ecdd3f45ff44e3b549ffa01b126464d0/rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055", size = 6760, upload-time = "2019-10-28T16:00:19.144Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9", size = 4242, upload-time = "2019-10-28T16:00:13.976Z" }, +] + +[[package]] +name = "rfc3987-syntax" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "lark" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2c/06/37c1a5557acf449e8e406a830a05bf885ac47d33270aec454ef78675008d/rfc3987_syntax-1.1.0.tar.gz", hash = "sha256:717a62cbf33cffdd16dfa3a497d81ce48a660ea691b1ddd7be710c22f00b4a0d", size = 14239, upload-time = "2025-07-18T01:05:05.015Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl", hash = "sha256:6c3d97604e4c5ce9f714898e05401a0445a641cfa276432b0a648c80856f6a3f", size = 8046, upload-time = "2025-07-18T01:05:03.843Z" }, +] + +[[package]] +name = "rpds-py" +version = "0.30.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469, upload-time = "2025-11-30T20:24:38.837Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ed/dc/d61221eb88ff410de3c49143407f6f3147acf2538c86f2ab7ce65ae7d5f9/rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2", size = 374887, upload-time = "2025-11-30T20:22:41.812Z" }, + { url = "https://files.pythonhosted.org/packages/fd/32/55fb50ae104061dbc564ef15cc43c013dc4a9f4527a1f4d99baddf56fe5f/rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8", size = 358904, upload-time = "2025-11-30T20:22:43.479Z" }, + { url = "https://files.pythonhosted.org/packages/58/70/faed8186300e3b9bdd138d0273109784eea2396c68458ed580f885dfe7ad/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4", size = 389945, upload-time = "2025-11-30T20:22:44.819Z" }, + { url = "https://files.pythonhosted.org/packages/bd/a8/073cac3ed2c6387df38f71296d002ab43496a96b92c823e76f46b8af0543/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136", size = 407783, upload-time = "2025-11-30T20:22:46.103Z" }, + { url = "https://files.pythonhosted.org/packages/77/57/5999eb8c58671f1c11eba084115e77a8899d6e694d2a18f69f0ba471ec8b/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7", size = 515021, upload-time = "2025-11-30T20:22:47.458Z" }, + { url = "https://files.pythonhosted.org/packages/e0/af/5ab4833eadc36c0a8ed2bc5c0de0493c04f6c06de223170bd0798ff98ced/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2", size = 414589, upload-time = "2025-11-30T20:22:48.872Z" }, + { url = "https://files.pythonhosted.org/packages/b7/de/f7192e12b21b9e9a68a6d0f249b4af3fdcdff8418be0767a627564afa1f1/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6", size = 394025, upload-time = "2025-11-30T20:22:50.196Z" }, + { url = "https://files.pythonhosted.org/packages/91/c4/fc70cd0249496493500e7cc2de87504f5aa6509de1e88623431fec76d4b6/rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e", size = 408895, upload-time = "2025-11-30T20:22:51.87Z" }, + { url = "https://files.pythonhosted.org/packages/58/95/d9275b05ab96556fefff73a385813eb66032e4c99f411d0795372d9abcea/rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d", size = 422799, upload-time = "2025-11-30T20:22:53.341Z" }, + { url = "https://files.pythonhosted.org/packages/06/c1/3088fc04b6624eb12a57eb814f0d4997a44b0d208d6cace713033ff1a6ba/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7", size = 572731, upload-time = "2025-11-30T20:22:54.778Z" }, + { url = "https://files.pythonhosted.org/packages/d8/42/c612a833183b39774e8ac8fecae81263a68b9583ee343db33ab571a7ce55/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31", size = 599027, upload-time = "2025-11-30T20:22:56.212Z" }, + { url = "https://files.pythonhosted.org/packages/5f/60/525a50f45b01d70005403ae0e25f43c0384369ad24ffe46e8d9068b50086/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95", size = 563020, upload-time = "2025-11-30T20:22:58.2Z" }, + { url = "https://files.pythonhosted.org/packages/0b/5d/47c4655e9bcd5ca907148535c10e7d489044243cc9941c16ed7cd53be91d/rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d", size = 223139, upload-time = "2025-11-30T20:23:00.209Z" }, + { url = "https://files.pythonhosted.org/packages/f2/e1/485132437d20aa4d3e1d8b3fb5a5e65aa8139f1e097080c2a8443201742c/rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15", size = 240224, upload-time = "2025-11-30T20:23:02.008Z" }, + { url = "https://files.pythonhosted.org/packages/24/95/ffd128ed1146a153d928617b0ef673960130be0009c77d8fbf0abe306713/rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1", size = 230645, upload-time = "2025-11-30T20:23:03.43Z" }, + { url = "https://files.pythonhosted.org/packages/ff/1b/b10de890a0def2a319a2626334a7f0ae388215eb60914dbac8a3bae54435/rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a", size = 364443, upload-time = "2025-11-30T20:23:04.878Z" }, + { url = "https://files.pythonhosted.org/packages/0d/bf/27e39f5971dc4f305a4fb9c672ca06f290f7c4e261c568f3dea16a410d47/rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e", size = 353375, upload-time = "2025-11-30T20:23:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/40/58/442ada3bba6e8e6615fc00483135c14a7538d2ffac30e2d933ccf6852232/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000", size = 383850, upload-time = "2025-11-30T20:23:07.825Z" }, + { url = "https://files.pythonhosted.org/packages/14/14/f59b0127409a33c6ef6f5c1ebd5ad8e32d7861c9c7adfa9a624fc3889f6c/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db", size = 392812, upload-time = "2025-11-30T20:23:09.228Z" }, + { url = "https://files.pythonhosted.org/packages/b3/66/e0be3e162ac299b3a22527e8913767d869e6cc75c46bd844aa43fb81ab62/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2", size = 517841, upload-time = "2025-11-30T20:23:11.186Z" }, + { url = "https://files.pythonhosted.org/packages/3d/55/fa3b9cf31d0c963ecf1ba777f7cf4b2a2c976795ac430d24a1f43d25a6ba/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa", size = 408149, upload-time = "2025-11-30T20:23:12.864Z" }, + { url = "https://files.pythonhosted.org/packages/60/ca/780cf3b1a32b18c0f05c441958d3758f02544f1d613abf9488cd78876378/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083", size = 383843, upload-time = "2025-11-30T20:23:14.638Z" }, + { url = "https://files.pythonhosted.org/packages/82/86/d5f2e04f2aa6247c613da0c1dd87fcd08fa17107e858193566048a1e2f0a/rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9", size = 396507, upload-time = "2025-11-30T20:23:16.105Z" }, + { url = "https://files.pythonhosted.org/packages/4b/9a/453255d2f769fe44e07ea9785c8347edaf867f7026872e76c1ad9f7bed92/rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0", size = 414949, upload-time = "2025-11-30T20:23:17.539Z" }, + { url = "https://files.pythonhosted.org/packages/a3/31/622a86cdc0c45d6df0e9ccb6becdba5074735e7033c20e401a6d9d0e2ca0/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94", size = 565790, upload-time = "2025-11-30T20:23:19.029Z" }, + { url = "https://files.pythonhosted.org/packages/1c/5d/15bbf0fb4a3f58a3b1c67855ec1efcc4ceaef4e86644665fff03e1b66d8d/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08", size = 590217, upload-time = "2025-11-30T20:23:20.885Z" }, + { url = "https://files.pythonhosted.org/packages/6d/61/21b8c41f68e60c8cc3b2e25644f0e3681926020f11d06ab0b78e3c6bbff1/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27", size = 555806, upload-time = "2025-11-30T20:23:22.488Z" }, + { url = "https://files.pythonhosted.org/packages/f9/39/7e067bb06c31de48de3eb200f9fc7c58982a4d3db44b07e73963e10d3be9/rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6", size = 211341, upload-time = "2025-11-30T20:23:24.449Z" }, + { url = "https://files.pythonhosted.org/packages/0a/4d/222ef0b46443cf4cf46764d9c630f3fe4abaa7245be9417e56e9f52b8f65/rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d", size = 225768, upload-time = "2025-11-30T20:23:25.908Z" }, + { url = "https://files.pythonhosted.org/packages/86/81/dad16382ebbd3d0e0328776d8fd7ca94220e4fa0798d1dc5e7da48cb3201/rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0", size = 362099, upload-time = "2025-11-30T20:23:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/2b/60/19f7884db5d5603edf3c6bce35408f45ad3e97e10007df0e17dd57af18f8/rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be", size = 353192, upload-time = "2025-11-30T20:23:29.151Z" }, + { url = "https://files.pythonhosted.org/packages/bf/c4/76eb0e1e72d1a9c4703c69607cec123c29028bff28ce41588792417098ac/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f", size = 384080, upload-time = "2025-11-30T20:23:30.785Z" }, + { url = "https://files.pythonhosted.org/packages/72/87/87ea665e92f3298d1b26d78814721dc39ed8d2c74b86e83348d6b48a6f31/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f", size = 394841, upload-time = "2025-11-30T20:23:32.209Z" }, + { url = "https://files.pythonhosted.org/packages/77/ad/7783a89ca0587c15dcbf139b4a8364a872a25f861bdb88ed99f9b0dec985/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87", size = 516670, upload-time = "2025-11-30T20:23:33.742Z" }, + { url = "https://files.pythonhosted.org/packages/5b/3c/2882bdac942bd2172f3da574eab16f309ae10a3925644e969536553cb4ee/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18", size = 408005, upload-time = "2025-11-30T20:23:35.253Z" }, + { url = "https://files.pythonhosted.org/packages/ce/81/9a91c0111ce1758c92516a3e44776920b579d9a7c09b2b06b642d4de3f0f/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad", size = 382112, upload-time = "2025-11-30T20:23:36.842Z" }, + { url = "https://files.pythonhosted.org/packages/cf/8e/1da49d4a107027e5fbc64daeab96a0706361a2918da10cb41769244b805d/rpds_py-0.30.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07", size = 399049, upload-time = "2025-11-30T20:23:38.343Z" }, + { url = "https://files.pythonhosted.org/packages/df/5a/7ee239b1aa48a127570ec03becbb29c9d5a9eb092febbd1699d567cae859/rpds_py-0.30.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f", size = 415661, upload-time = "2025-11-30T20:23:40.263Z" }, + { url = "https://files.pythonhosted.org/packages/70/ea/caa143cf6b772f823bc7929a45da1fa83569ee49b11d18d0ada7f5ee6fd6/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65", size = 565606, upload-time = "2025-11-30T20:23:42.186Z" }, + { url = "https://files.pythonhosted.org/packages/64/91/ac20ba2d69303f961ad8cf55bf7dbdb4763f627291ba3d0d7d67333cced9/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f", size = 591126, upload-time = "2025-11-30T20:23:44.086Z" }, + { url = "https://files.pythonhosted.org/packages/21/20/7ff5f3c8b00c8a95f75985128c26ba44503fb35b8e0259d812766ea966c7/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53", size = 553371, upload-time = "2025-11-30T20:23:46.004Z" }, + { url = "https://files.pythonhosted.org/packages/72/c7/81dadd7b27c8ee391c132a6b192111ca58d866577ce2d9b0ca157552cce0/rpds_py-0.30.0-cp314-cp314-win32.whl", hash = "sha256:ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed", size = 215298, upload-time = "2025-11-30T20:23:47.696Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d2/1aaac33287e8cfb07aab2e6b8ac1deca62f6f65411344f1433c55e6f3eb8/rpds_py-0.30.0-cp314-cp314-win_amd64.whl", hash = "sha256:95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950", size = 228604, upload-time = "2025-11-30T20:23:49.501Z" }, + { url = "https://files.pythonhosted.org/packages/e8/95/ab005315818cc519ad074cb7784dae60d939163108bd2b394e60dc7b5461/rpds_py-0.30.0-cp314-cp314-win_arm64.whl", hash = "sha256:613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6", size = 222391, upload-time = "2025-11-30T20:23:50.96Z" }, + { url = "https://files.pythonhosted.org/packages/9e/68/154fe0194d83b973cdedcdcc88947a2752411165930182ae41d983dcefa6/rpds_py-0.30.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb", size = 364868, upload-time = "2025-11-30T20:23:52.494Z" }, + { url = "https://files.pythonhosted.org/packages/83/69/8bbc8b07ec854d92a8b75668c24d2abcb1719ebf890f5604c61c9369a16f/rpds_py-0.30.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8", size = 353747, upload-time = "2025-11-30T20:23:54.036Z" }, + { url = "https://files.pythonhosted.org/packages/ab/00/ba2e50183dbd9abcce9497fa5149c62b4ff3e22d338a30d690f9af970561/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7", size = 383795, upload-time = "2025-11-30T20:23:55.556Z" }, + { url = "https://files.pythonhosted.org/packages/05/6f/86f0272b84926bcb0e4c972262f54223e8ecc556b3224d281e6598fc9268/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898", size = 393330, upload-time = "2025-11-30T20:23:57.033Z" }, + { url = "https://files.pythonhosted.org/packages/cb/e9/0e02bb2e6dc63d212641da45df2b0bf29699d01715913e0d0f017ee29438/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e", size = 518194, upload-time = "2025-11-30T20:23:58.637Z" }, + { url = "https://files.pythonhosted.org/packages/ee/ca/be7bca14cf21513bdf9c0606aba17d1f389ea2b6987035eb4f62bd923f25/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419", size = 408340, upload-time = "2025-11-30T20:24:00.2Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c7/736e00ebf39ed81d75544c0da6ef7b0998f8201b369acf842f9a90dc8fce/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551", size = 383765, upload-time = "2025-11-30T20:24:01.759Z" }, + { url = "https://files.pythonhosted.org/packages/4a/3f/da50dfde9956aaf365c4adc9533b100008ed31aea635f2b8d7b627e25b49/rpds_py-0.30.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8", size = 396834, upload-time = "2025-11-30T20:24:03.687Z" }, + { url = "https://files.pythonhosted.org/packages/4e/00/34bcc2565b6020eab2623349efbdec810676ad571995911f1abdae62a3a0/rpds_py-0.30.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5", size = 415470, upload-time = "2025-11-30T20:24:05.232Z" }, + { url = "https://files.pythonhosted.org/packages/8c/28/882e72b5b3e6f718d5453bd4d0d9cf8df36fddeb4ddbbab17869d5868616/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404", size = 565630, upload-time = "2025-11-30T20:24:06.878Z" }, + { url = "https://files.pythonhosted.org/packages/3b/97/04a65539c17692de5b85c6e293520fd01317fd878ea1995f0367d4532fb1/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856", size = 591148, upload-time = "2025-11-30T20:24:08.445Z" }, + { url = "https://files.pythonhosted.org/packages/85/70/92482ccffb96f5441aab93e26c4d66489eb599efdcf96fad90c14bbfb976/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40", size = 556030, upload-time = "2025-11-30T20:24:10.956Z" }, + { url = "https://files.pythonhosted.org/packages/20/53/7c7e784abfa500a2b6b583b147ee4bb5a2b3747a9166bab52fec4b5b5e7d/rpds_py-0.30.0-cp314-cp314t-win32.whl", hash = "sha256:dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0", size = 211570, upload-time = "2025-11-30T20:24:12.735Z" }, + { url = "https://files.pythonhosted.org/packages/d0/02/fa464cdfbe6b26e0600b62c528b72d8608f5cc49f96b8d6e38c95d60c676/rpds_py-0.30.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3", size = 226532, upload-time = "2025-11-30T20:24:14.634Z" }, +] + +[[package]] +name = "scikit-learn" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "joblib" }, + { name = "numpy" }, + { name = "scipy" }, + { name = "threadpoolctl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0e/d4/40988bf3b8e34feec1d0e6a051446b1f66225f8529b9309becaeef62b6c4/scikit_learn-1.8.0.tar.gz", hash = "sha256:9bccbb3b40e3de10351f8f5068e105d0f4083b1a65fa07b6634fbc401a6287fd", size = 7335585, upload-time = "2025-12-10T07:08:53.618Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/03/aa/e22e0768512ce9255eba34775be2e85c2048da73da1193e841707f8f039c/scikit_learn-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0d6ae97234d5d7079dc0040990a6f7aeb97cb7fa7e8945f1999a429b23569e0a", size = 8513770, upload-time = "2025-12-10T07:08:03.251Z" }, + { url = "https://files.pythonhosted.org/packages/58/37/31b83b2594105f61a381fc74ca19e8780ee923be2d496fcd8d2e1147bd99/scikit_learn-1.8.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:edec98c5e7c128328124a029bceb09eda2d526997780fef8d65e9a69eead963e", size = 8044458, upload-time = "2025-12-10T07:08:05.336Z" }, + { url = "https://files.pythonhosted.org/packages/2d/5a/3f1caed8765f33eabb723596666da4ebbf43d11e96550fb18bdec42b467b/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:74b66d8689d52ed04c271e1329f0c61635bcaf5b926db9b12d58914cdc01fe57", size = 8610341, upload-time = "2025-12-10T07:08:07.732Z" }, + { url = "https://files.pythonhosted.org/packages/38/cf/06896db3f71c75902a8e9943b444a56e727418f6b4b4a90c98c934f51ed4/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8fdf95767f989b0cfedb85f7ed8ca215d4be728031f56ff5a519ee1e3276dc2e", size = 8900022, upload-time = "2025-12-10T07:08:09.862Z" }, + { url = "https://files.pythonhosted.org/packages/1c/f9/9b7563caf3ec8873e17a31401858efab6b39a882daf6c1bfa88879c0aa11/scikit_learn-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:2de443b9373b3b615aec1bb57f9baa6bb3a9bd093f1269ba95c17d870422b271", size = 7989409, upload-time = "2025-12-10T07:08:12.028Z" }, + { url = "https://files.pythonhosted.org/packages/49/bd/1f4001503650e72c4f6009ac0c4413cb17d2d601cef6f71c0453da2732fc/scikit_learn-1.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:eddde82a035681427cbedded4e6eff5e57fa59216c2e3e90b10b19ab1d0a65c3", size = 7619760, upload-time = "2025-12-10T07:08:13.688Z" }, + { url = "https://files.pythonhosted.org/packages/d2/7d/a630359fc9dcc95496588c8d8e3245cc8fd81980251079bc09c70d41d951/scikit_learn-1.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7cc267b6108f0a1499a734167282c00c4ebf61328566b55ef262d48e9849c735", size = 8826045, upload-time = "2025-12-10T07:08:15.215Z" }, + { url = "https://files.pythonhosted.org/packages/cc/56/a0c86f6930cfcd1c7054a2bc417e26960bb88d32444fe7f71d5c2cfae891/scikit_learn-1.8.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:fe1c011a640a9f0791146011dfd3c7d9669785f9fed2b2a5f9e207536cf5c2fd", size = 8420324, upload-time = "2025-12-10T07:08:17.561Z" }, + { url = "https://files.pythonhosted.org/packages/46/1e/05962ea1cebc1cf3876667ecb14c283ef755bf409993c5946ade3b77e303/scikit_learn-1.8.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72358cce49465d140cc4e7792015bb1f0296a9742d5622c67e31399b75468b9e", size = 8680651, upload-time = "2025-12-10T07:08:19.952Z" }, + { url = "https://files.pythonhosted.org/packages/fe/56/a85473cd75f200c9759e3a5f0bcab2d116c92a8a02ee08ccd73b870f8bb4/scikit_learn-1.8.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:80832434a6cc114f5219211eec13dcbc16c2bac0e31ef64c6d346cde3cf054cb", size = 8925045, upload-time = "2025-12-10T07:08:22.11Z" }, + { url = "https://files.pythonhosted.org/packages/cc/b7/64d8cfa896c64435ae57f4917a548d7ac7a44762ff9802f75a79b77cb633/scikit_learn-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ee787491dbfe082d9c3013f01f5991658b0f38aa8177e4cd4bf434c58f551702", size = 8507994, upload-time = "2025-12-10T07:08:23.943Z" }, + { url = "https://files.pythonhosted.org/packages/5e/37/e192ea709551799379958b4c4771ec507347027bb7c942662c7fbeba31cb/scikit_learn-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf97c10a3f5a7543f9b88cbf488d33d175e9146115a451ae34568597ba33dcde", size = 7869518, upload-time = "2025-12-10T07:08:25.71Z" }, + { url = "https://files.pythonhosted.org/packages/24/05/1af2c186174cc92dcab2233f327336058c077d38f6fe2aceb08e6ab4d509/scikit_learn-1.8.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:c22a2da7a198c28dd1a6e1136f19c830beab7fdca5b3e5c8bba8394f8a5c45b3", size = 8528667, upload-time = "2025-12-10T07:08:27.541Z" }, + { url = "https://files.pythonhosted.org/packages/a8/25/01c0af38fe969473fb292bba9dc2b8f9b451f3112ff242c647fee3d0dfe7/scikit_learn-1.8.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:6b595b07a03069a2b1740dc08c2299993850ea81cce4fe19b2421e0c970de6b7", size = 8066524, upload-time = "2025-12-10T07:08:29.822Z" }, + { url = "https://files.pythonhosted.org/packages/be/ce/a0623350aa0b68647333940ee46fe45086c6060ec604874e38e9ab7d8e6c/scikit_learn-1.8.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:29ffc74089f3d5e87dfca4c2c8450f88bdc61b0fc6ed5d267f3988f19a1309f6", size = 8657133, upload-time = "2025-12-10T07:08:31.865Z" }, + { url = "https://files.pythonhosted.org/packages/b8/cb/861b41341d6f1245e6ca80b1c1a8c4dfce43255b03df034429089ca2a2c5/scikit_learn-1.8.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fb65db5d7531bccf3a4f6bec3462223bea71384e2cda41da0f10b7c292b9e7c4", size = 8923223, upload-time = "2025-12-10T07:08:34.166Z" }, + { url = "https://files.pythonhosted.org/packages/76/18/a8def8f91b18cd1ba6e05dbe02540168cb24d47e8dcf69e8d00b7da42a08/scikit_learn-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:56079a99c20d230e873ea40753102102734c5953366972a71d5cb39a32bc40c6", size = 8096518, upload-time = "2025-12-10T07:08:36.339Z" }, + { url = "https://files.pythonhosted.org/packages/d1/77/482076a678458307f0deb44e29891d6022617b2a64c840c725495bee343f/scikit_learn-1.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:3bad7565bc9cf37ce19a7c0d107742b320c1285df7aab1a6e2d28780df167242", size = 7754546, upload-time = "2025-12-10T07:08:38.128Z" }, + { url = "https://files.pythonhosted.org/packages/2d/d1/ef294ca754826daa043b2a104e59960abfab4cf653891037d19dd5b6f3cf/scikit_learn-1.8.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:4511be56637e46c25721e83d1a9cea9614e7badc7040c4d573d75fbe257d6fd7", size = 8848305, upload-time = "2025-12-10T07:08:41.013Z" }, + { url = "https://files.pythonhosted.org/packages/5b/e2/b1f8b05138ee813b8e1a4149f2f0d289547e60851fd1bb268886915adbda/scikit_learn-1.8.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:a69525355a641bf8ef136a7fa447672fb54fe8d60cab5538d9eb7c6438543fb9", size = 8432257, upload-time = "2025-12-10T07:08:42.873Z" }, + { url = "https://files.pythonhosted.org/packages/26/11/c32b2138a85dcb0c99f6afd13a70a951bfdff8a6ab42d8160522542fb647/scikit_learn-1.8.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c2656924ec73e5939c76ac4c8b026fc203b83d8900362eb2599d8aee80e4880f", size = 8678673, upload-time = "2025-12-10T07:08:45.362Z" }, + { url = "https://files.pythonhosted.org/packages/c7/57/51f2384575bdec454f4fe4e7a919d696c9ebce914590abf3e52d47607ab8/scikit_learn-1.8.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15fc3b5d19cc2be65404786857f2e13c70c83dd4782676dd6814e3b89dc8f5b9", size = 8922467, upload-time = "2025-12-10T07:08:47.408Z" }, + { url = "https://files.pythonhosted.org/packages/35/4d/748c9e2872637a57981a04adc038dacaa16ba8ca887b23e34953f0b3f742/scikit_learn-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:00d6f1d66fbcf4eba6e356e1420d33cc06c70a45bb1363cd6f6a8e4ebbbdece2", size = 8774395, upload-time = "2025-12-10T07:08:49.337Z" }, + { url = "https://files.pythonhosted.org/packages/60/22/d7b2ebe4704a5e50790ba089d5c2ae308ab6bb852719e6c3bd4f04c3a363/scikit_learn-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:f28dd15c6bb0b66ba09728cf09fd8736c304be29409bd8445a080c1280619e8c", size = 8002647, upload-time = "2025-12-10T07:08:51.601Z" }, +] + [[package]] name = "scipy" version = "1.16.3" @@ -664,6 +2067,38 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/64/47/a494741db7280eae6dc033510c319e34d42dd41b7ac0c7ead39354d1a2b5/scipy-1.16.3-cp314-cp314t-win_arm64.whl", hash = "sha256:21d9d6b197227a12dcbf9633320a4e34c6b0e51c57268df255a0942983bac562", size = 26464127, upload-time = "2025-10-28T17:38:11.34Z" }, ] +[[package]] +name = "seaborn" +version = "0.13.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "matplotlib" }, + { name = "numpy" }, + { name = "pandas" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/86/59/a451d7420a77ab0b98f7affa3a1d78a313d2f7281a57afb1a34bae8ab412/seaborn-0.13.2.tar.gz", hash = "sha256:93e60a40988f4d65e9f4885df477e2fdaff6b73a9ded434c1ab356dd57eefff7", size = 1457696, upload-time = "2024-01-25T13:21:52.551Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/11/00d3c3dfc25ad54e731d91449895a79e4bf2384dc3ac01809010ba88f6d5/seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987", size = 294914, upload-time = "2024-01-25T13:21:49.598Z" }, +] + +[[package]] +name = "send2trash" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c5/f0/184b4b5f8d00f2a92cf96eec8967a3d550b52cf94362dad1100df9e48d57/send2trash-2.1.0.tar.gz", hash = "sha256:1c72b39f09457db3c05ce1d19158c2cbef4c32b8bedd02c155e49282b7ea7459", size = 17255, upload-time = "2026-01-14T06:27:36.056Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1c/78/504fdd027da3b84ff1aecd9f6957e65f35134534ccc6da8628eb71e76d3f/send2trash-2.1.0-py3-none-any.whl", hash = "sha256:0da2f112e6d6bb22de6aa6daa7e144831a4febf2a87261451c4ad849fe9a873c", size = 17610, upload-time = "2026-01-14T06:27:35.218Z" }, +] + +[[package]] +name = "setuptools" +version = "82.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/f3/748f4d6f65d1756b9ae577f329c951cda23fb900e4de9f70900ced962085/setuptools-82.0.0.tar.gz", hash = "sha256:22e0a2d69474c6ae4feb01951cb69d515ed23728cf96d05513d36e42b62b37cb", size = 1144893, upload-time = "2026-02-08T15:08:40.206Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/c6/76dc613121b793286a3f91621d7b75a2b493e0390ddca50f11993eadf192/setuptools-82.0.0-py3-none-any.whl", hash = "sha256:70b18734b607bd1da571d097d236cfcfacaf01de45717d59e6e04b96877532e0", size = 1003468, upload-time = "2026-02-08T15:08:38.723Z" }, +] + [[package]] name = "shapely" version = "2.1.2" @@ -716,6 +2151,29 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, ] +[[package]] +name = "soupsieve" +version = "2.8.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/ae/2d9c981590ed9999a0d91755b47fc74f74de286b0f5cee14c9269041e6c4/soupsieve-2.8.3.tar.gz", hash = "sha256:3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349", size = 118627, upload-time = "2026-01-20T04:27:02.457Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl", hash = "sha256:ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95", size = 37016, upload-time = "2026-01-20T04:27:01.012Z" }, +] + +[[package]] +name = "stack-data" +version = "0.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asttokens" }, + { name = "executing" }, + { name = "pure-eval" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707, upload-time = "2023-09-30T13:58:05.479Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" }, +] + [[package]] name = "statsmodels" version = "0.14.6" @@ -743,6 +2201,103 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/26/33/f1652d0c59fa51de18492ee2345b65372550501ad061daa38f950be390b6/statsmodels-0.14.6-cp314-cp314-win_amd64.whl", hash = "sha256:151b73e29f01fe619dbce7f66d61a356e9d1fe5e906529b78807df9189c37721", size = 9588010, upload-time = "2025-12-05T23:14:07.28Z" }, ] +[[package]] +name = "terminado" +version = "0.18.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ptyprocess", marker = "os_name != 'nt'" }, + { name = "pywinpty", marker = "os_name == 'nt'" }, + { name = "tornado" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8a/11/965c6fd8e5cc254f1fe142d547387da17a8ebfd75a3455f637c663fb38a0/terminado-0.18.1.tar.gz", hash = "sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e", size = 32701, upload-time = "2024-03-12T14:34:39.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl", hash = "sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0", size = 14154, upload-time = "2024-03-12T14:34:36.569Z" }, +] + +[[package]] +name = "threadpoolctl" +version = "3.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b7/4d/08c89e34946fce2aec4fbb45c9016efd5f4d7f24af8e5d93296e935631d8/threadpoolctl-3.6.0.tar.gz", hash = "sha256:8ab8b4aa3491d812b623328249fab5302a68d2d71745c8a4c719a2fcaba9f44e", size = 21274, upload-time = "2025-03-13T13:49:23.031Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638, upload-time = "2025-03-13T13:49:21.846Z" }, +] + +[[package]] +name = "tidypolars" +version = "0.3.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, + { name = "polars" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/b4/98c9f4f6c87d0630c4745777140c889d3b1a70db5a292204020839f0deae/tidypolars-0.3.2.tar.gz", hash = "sha256:009cb92d3211fb20a375adbfcf043703b04411aa22c05351addd13addff84f67", size = 17836, upload-time = "2024-11-02T14:49:21.012Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/c5/fe58f5ff266d15d22c3eb214c04d035c606febd317ea51cac85e212e74de/tidypolars-0.3.2-py3-none-any.whl", hash = "sha256:73ca614730c38abc63e30db832e599b098e95ea7094d9cff60fe24733b0a5293", size = 18731, upload-time = "2024-11-02T14:49:19.513Z" }, +] + +[[package]] +name = "tinycss2" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "webencodings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7a/fd/7a5ee21fd08ff70d3d33a5781c255cbe779659bd03278feb98b19ee550f4/tinycss2-1.4.0.tar.gz", hash = "sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7", size = 87085, upload-time = "2024-10-24T14:58:29.895Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289", size = 26610, upload-time = "2024-10-24T14:58:28.029Z" }, +] + +[[package]] +name = "tornado" +version = "6.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/37/1d/0a336abf618272d53f62ebe274f712e213f5a03c0b2339575430b8362ef2/tornado-6.5.4.tar.gz", hash = "sha256:a22fa9047405d03260b483980635f0b041989d8bcc9a313f8fe18b411d84b1d7", size = 513632, upload-time = "2025-12-15T19:21:03.836Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/a9/e94a9d5224107d7ce3cc1fab8d5dc97f5ea351ccc6322ee4fb661da94e35/tornado-6.5.4-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:d6241c1a16b1c9e4cc28148b1cda97dd1c6cb4fb7068ac1bedc610768dff0ba9", size = 443909, upload-time = "2025-12-15T19:20:48.382Z" }, + { url = "https://files.pythonhosted.org/packages/db/7e/f7b8d8c4453f305a51f80dbb49014257bb7d28ccb4bbb8dd328ea995ecad/tornado-6.5.4-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2d50f63dda1d2cac3ae1fa23d254e16b5e38153758470e9956cbc3d813d40843", size = 442163, upload-time = "2025-12-15T19:20:49.791Z" }, + { url = "https://files.pythonhosted.org/packages/ba/b5/206f82d51e1bfa940ba366a8d2f83904b15942c45a78dd978b599870ab44/tornado-6.5.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1cf66105dc6acb5af613c054955b8137e34a03698aa53272dbda4afe252be17", size = 445746, upload-time = "2025-12-15T19:20:51.491Z" }, + { url = "https://files.pythonhosted.org/packages/8e/9d/1a3338e0bd30ada6ad4356c13a0a6c35fbc859063fa7eddb309183364ac1/tornado-6.5.4-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50ff0a58b0dc97939d29da29cd624da010e7f804746621c78d14b80238669335", size = 445083, upload-time = "2025-12-15T19:20:52.778Z" }, + { url = "https://files.pythonhosted.org/packages/50/d4/e51d52047e7eb9a582da59f32125d17c0482d065afd5d3bc435ff2120dc5/tornado-6.5.4-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5fb5e04efa54cf0baabdd10061eb4148e0be137166146fff835745f59ab9f7f", size = 445315, upload-time = "2025-12-15T19:20:53.996Z" }, + { url = "https://files.pythonhosted.org/packages/27/07/2273972f69ca63dbc139694a3fc4684edec3ea3f9efabf77ed32483b875c/tornado-6.5.4-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9c86b1643b33a4cd415f8d0fe53045f913bf07b4a3ef646b735a6a86047dda84", size = 446003, upload-time = "2025-12-15T19:20:56.101Z" }, + { url = "https://files.pythonhosted.org/packages/d1/83/41c52e47502bf7260044413b6770d1a48dda2f0246f95ee1384a3cd9c44a/tornado-6.5.4-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:6eb82872335a53dd063a4f10917b3efd28270b56a33db69009606a0312660a6f", size = 445412, upload-time = "2025-12-15T19:20:57.398Z" }, + { url = "https://files.pythonhosted.org/packages/10/c7/bc96917f06cbee182d44735d4ecde9c432e25b84f4c2086143013e7b9e52/tornado-6.5.4-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6076d5dda368c9328ff41ab5d9dd3608e695e8225d1cd0fd1e006f05da3635a8", size = 445392, upload-time = "2025-12-15T19:20:58.692Z" }, + { url = "https://files.pythonhosted.org/packages/0c/1a/d7592328d037d36f2d2462f4bc1fbb383eec9278bc786c1b111cbbd44cfa/tornado-6.5.4-cp39-abi3-win32.whl", hash = "sha256:1768110f2411d5cd281bac0a090f707223ce77fd110424361092859e089b38d1", size = 446481, upload-time = "2025-12-15T19:21:00.008Z" }, + { url = "https://files.pythonhosted.org/packages/d6/6d/c69be695a0a64fd37a97db12355a035a6d90f79067a3cf936ec2b1dc38cd/tornado-6.5.4-cp39-abi3-win_amd64.whl", hash = "sha256:fa07d31e0cd85c60713f2b995da613588aa03e1303d75705dca6af8babc18ddc", size = 446886, upload-time = "2025-12-15T19:21:01.287Z" }, + { url = "https://files.pythonhosted.org/packages/50/49/8dc3fd90902f70084bd2cd059d576ddb4f8bb44c2c7c0e33a11422acb17e/tornado-6.5.4-cp39-abi3-win_arm64.whl", hash = "sha256:053e6e16701eb6cbe641f308f4c1a9541f91b6261991160391bfc342e8a551a1", size = 445910, upload-time = "2025-12-15T19:21:02.571Z" }, +] + +[[package]] +name = "tqdm" +version = "4.67.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/09/a9/6ba95a270c6f1fbcd8dac228323f2777d886cb206987444e4bce66338dd4/tqdm-4.67.3.tar.gz", hash = "sha256:7d825f03f89244ef73f1d4ce193cb1774a8179fd96f31d7e1dcde62092b960bb", size = 169598, upload-time = "2026-02-03T17:35:53.048Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf", size = 78374, upload-time = "2026-02-03T17:35:50.982Z" }, +] + +[[package]] +name = "traitlets" +version = "5.14.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/eb/79/72064e6a701c2183016abbbfedaba506d81e30e232a68c9f0d6f6fcd1574/traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", size = 161621, upload-time = "2024-04-19T11:11:49.746Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f", size = 85359, upload-time = "2024-04-19T11:11:46.763Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] + [[package]] name = "tzdata" version = "2025.3" @@ -752,6 +2307,81 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, ] +[[package]] +name = "uri-template" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/31/c7/0336f2bd0bcbada6ccef7aaa25e443c118a704f828a0620c6fa0207c1b64/uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7", size = 21678, upload-time = "2023-06-21T01:49:05.374Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363", size = 11140, upload-time = "2023-06-21T01:49:03.467Z" }, +] + +[[package]] +name = "url-normalize" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/80/31/febb777441e5fcdaacb4522316bf2a527c44551430a4873b052d545e3279/url_normalize-2.2.1.tar.gz", hash = "sha256:74a540a3b6eba1d95bdc610c24f2c0141639f3ba903501e61a52a8730247ff37", size = 18846, upload-time = "2025-04-26T20:37:58.553Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/d9/5ec15501b675f7bc07c5d16aa70d8d778b12375686b6efd47656efdc67cd/url_normalize-2.2.1-py3-none-any.whl", hash = "sha256:3deb687587dc91f7b25c9ae5162ffc0f057ae85d22b1e15cf5698311247f567b", size = 14728, upload-time = "2025-04-26T20:37:57.217Z" }, +] + +[[package]] +name = "urllib3" +version = "2.6.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/24/5f1b3bdffd70275f6661c76461e25f024d5a38a46f04aaca912426a2b1d3/urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", size = 435556, upload-time = "2026-01-07T16:24:43.925Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" }, +] + +[[package]] +name = "wcwidth" +version = "0.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/35/a2/8e3becb46433538a38726c948d3399905a4c7cabd0df578ede5dc51f0ec2/wcwidth-0.6.0.tar.gz", hash = "sha256:cdc4e4262d6ef9a1a57e018384cbeb1208d8abbc64176027e2c2455c81313159", size = 159684, upload-time = "2026-02-06T19:19:40.919Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/68/5a/199c59e0a824a3db2b89c5d2dade7ab5f9624dbf6448dc291b46d5ec94d3/wcwidth-0.6.0-py3-none-any.whl", hash = "sha256:1a3a1e510b553315f8e146c54764f4fb6264ffad731b3d78088cdb1478ffbdad", size = 94189, upload-time = "2026-02-06T19:19:39.646Z" }, +] + +[[package]] +name = "webcolors" +version = "25.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/7a/eb316761ec35664ea5174709a68bbd3389de60d4a1ebab8808bfc264ed67/webcolors-25.10.0.tar.gz", hash = "sha256:62abae86504f66d0f6364c2a8520de4a0c47b80c03fc3a5f1815fedbef7c19bf", size = 53491, upload-time = "2025-10-31T07:51:03.977Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl", hash = "sha256:032c727334856fc0b968f63daa252a1ac93d33db2f5267756623c210e57a4f1d", size = 14905, upload-time = "2025-10-31T07:51:01.778Z" }, +] + +[[package]] +name = "webencodings" +version = "0.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923", size = 9721, upload-time = "2017-04-05T20:21:34.189Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774, upload-time = "2017-04-05T20:21:32.581Z" }, +] + +[[package]] +name = "websocket-client" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2c/41/aa4bf9664e4cda14c3b39865b12251e8e7d239f4cd0e3cc1b6c2ccde25c1/websocket_client-1.9.0.tar.gz", hash = "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", size = 70576, upload-time = "2025-10-07T21:16:36.495Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/34/db/b10e48aa8fff7407e67470363eac595018441cf32d5e1001567a7aeba5d2/websocket_client-1.9.0-py3-none-any.whl", hash = "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef", size = 82616, upload-time = "2025-10-07T21:16:34.951Z" }, +] + +[[package]] +name = "widgetsnbextension" +version = "4.0.15" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/f4/c67440c7fb409a71b7404b7aefcd7569a9c0d6bd071299bf4198ae7a5d95/widgetsnbextension-4.0.15.tar.gz", hash = "sha256:de8610639996f1567952d763a5a41af8af37f2575a41f9852a38f947eb82a3b9", size = 1097402, upload-time = "2025-11-01T21:15:55.178Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl", hash = "sha256:8156704e4346a571d9ce73b84bee86a29906c9abfd7223b7228a28899ccf3366", size = 2196503, upload-time = "2025-11-01T21:15:53.565Z" }, +] + [[package]] name = "xlrd" version = "2.0.2" From 21da98d49e360014043055eb736795f8f672a696 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 14:47:22 +0000 Subject: [PATCH 79/92] review - RP - 1 --- source/projects/RP/solutions_polars.py | 221 ++++++++++++------------- 1 file changed, 109 insertions(+), 112 deletions(-) diff --git a/source/projects/RP/solutions_polars.py b/source/projects/RP/solutions_polars.py index 3e0d56e4..47270187 100644 --- a/source/projects/RP/solutions_polars.py +++ b/source/projects/RP/solutions_polars.py @@ -1,20 +1,17 @@ # %% -# import copy -import polars as pl -import plotnine as p9 import geopandas as gpd -# import seaborn as sns -# import fastexcel -import solutions import matplotlib.pyplot as plt +import plotnine as p9 +import polars as pl import requests +import solutions def load_data(): data = pl.read_excel( - 'https://www.insee.fr/fr/statistiques/fichier/1893198/estim-pop-dep-sexe-aq-1975-2023.xls', + "https://www.insee.fr/fr/statistiques/fichier/1893198/estim-pop-dep-sexe-aq-1975-2023.xls", sheet_name=[str(i) for i in range(1975, 2024, 1)], - read_options={"header_row": 3} + read_options={"header_row": 3}, ) return data @@ -25,99 +22,84 @@ def reshape_table_by_year(df, year): temp_colnames_list = df.columns for index, colname in enumerate(temp_colnames_list): if df[0, colname] is not None: - if colname[:11] == '__UNNAMED__': - temp_colnames_list[index] = temp_colnames_list[index-1].split("_")[0] + "__" + df[0, colname] + if colname[:11] == "__UNNAMED__": + temp_colnames_list[index] = ( + temp_colnames_list[index - 1].split("_")[0] + "__" + df[0, colname] + ) else: - temp_colnames_list[index] = temp_colnames_list[index] + "__" + df[0, colname] + temp_colnames_list[index] = ( + temp_colnames_list[index] + "__" + df[0, colname] + ) else: - temp_colnames_list[index] = temp_colnames_list[index-1].split("_")[0] + "__00" + temp_colnames_list[index] = ( + temp_colnames_list[index - 1].split("_")[0] + "__00" + ) temp_colnames_list[0] = "dep_code" temp_colnames_list[1] = "dep" df_new = df.rename(dict(zip(df.columns, temp_colnames_list))) # Reshaping data - df_new = (df_new\ - .drop_nulls(pl.col('dep')) - .unpivot(index=['dep_code', 'dep'], value_name="population") - .with_columns( - variablelist=pl.col.variable.str.split('__') - ) + df_new = ( + df_new.drop_nulls(pl.col("dep")) + .unpivot(index=["dep_code", "dep"], value_name="population") + .with_columns(variablelist=pl.col.variable.str.split("__")) .with_columns( - genre=pl.col.variablelist.list.get(0, null_on_oob=True), - age=pl.col.variablelist.list.get(1, null_on_oob=True), - population=pl.col.population.cast(pl.Int64), - annee=pl.lit(year).cast(pl.Int64) + genre=pl.col.variablelist.list.get(0, null_on_oob=True), + age=pl.col.variablelist.list.get(1, null_on_oob=True), + population=pl.col.population.cast(pl.Int64), + annee=pl.lit(year).cast(pl.Int64), ) - .select(['dep_code', 'dep', 'annee', 'genre', 'age', 'population']) + .select(["dep_code", "dep", "annee", "genre", "age", "population"]) ) return df_new def reshape_data(data): - df = pl.DataFrame(schema= - ['dep_code', 'dep', 'annee', 'genre', 'age', 'population'] - ) + df = pl.DataFrame(schema=["dep_code", "dep", "annee", "genre", "age", "population"]) for annee_dic, annee_df in data.items(): - df=pl.concat([df, reshape_table_by_year(annee_df, annee_dic)], strict=False, how='vertical_relaxed') + df = pl.concat( + [df, reshape_table_by_year(annee_df, annee_dic)], + strict=False, + how="vertical_relaxed", + ) return df -# %% -df = reshape_data(load_data()) -# %% def plot_population_by_gender_per_department(data, department_code): - - df_plot = (data\ - .filter( - pl.col.dep_code.is_in([department_code]), - pl.col.genre !="Ensemble", - pl.col.age == "Total" - ) - .with_columns(pl.col.population/1e6) - ) + df_plot = data.filter( + pl.col.dep_code.is_in([department_code]), + pl.col.genre != "Ensemble", + pl.col.age == "Total", + ).with_columns(pl.col.population / 1e6) plot = ( - p9.ggplot(df_plot, - p9.aes(x="annee", y="population", group="genre", colour="genre")) + p9.ggplot( + df_plot, p9.aes(x="annee", y="population", group="genre", colour="genre") + ) + p9.geom_line(size=1) + p9.theme_matplotlib() + p9.labs( - title=f"Évolution de la population entre {df_plot.min()[0, "annee"]} et {df_plot.max()[0, "annee"]} dans le {df_plot.min()[0, "dep_code"]} ({df_plot.min()[0, "dep"]})", - x="Année", - y="Population (M)" + title=f"Évolution de la population entre {df_plot.min()[0, 'annee']} et {df_plot.max()[0, 'annee']} dans le {df_plot.min()[0, 'dep_code']} ({df_plot.min()[0, 'dep']})", + x="Année", + y="Population (M)", ) ) return plot -# %% -plot_population_by_gender_per_department(df, '31') - -# %% -solutions.plot_population_by_gender_per_department(df.to_pandas(), "31") - -# %% -pyramide_data = solutions.get_age_pyramid_data(df.to_pandas(), 2022) -pyramide_data # %% def get_age_pyramid_data(df, years): - pyramide_data = df\ - .filter( - pl.col.annee.is_in([1975, 2022]), - pl.col.age != "Total" - )\ - .group_by( - ["annee", "genre", "age"] - )\ - .agg( - pl.col.population.sum() - )\ - .pivot(on="genre", values="population", index=["annee", "age"])\ - .sort("age")\ + pyramide_data = ( + df.filter(pl.col.annee.is_in(years), pl.col.age != "Total") + .group_by(["annee", "genre", "age"]) + .agg(pl.col.population.sum()) + .pivot(on="genre", values="population", index=["annee", "age"]) + .sort("age") .with_columns(Hommes=-pl.col.Hommes) + ) return pyramide_data @@ -133,54 +115,70 @@ def tr_age_sorted_plot(list): # %% def plot_age_pyramid(df, years): - df_plot = get_age_pyramid_data(df, years)\ - .unpivot(index=["annee", "age"], variable_name="genre")\ - .filter(pl.col.genre != "Ensemble")\ - .with_columns(pl.col.value/1e6) + df_plot = ( + get_age_pyramid_data(df, years) + .unpivot(index=["annee", "age"], variable_name="genre") + .filter(pl.col.genre != "Ensemble") + .with_columns(pl.col.value / 1e6) + ) # Otherwise the categorie 5 to 9 is plotted betwwen 45 to 49 and 50 to 55 - age_categories_sorted = df_plot.select("age").unique().with_columns(pl.col.age.str.len_chars().alias("length")).sort("length", "age").select("age").to_series().to_list() + age_categories_sorted = ( + df_plot.select("age") + .unique() + .with_columns(pl.col.age.str.len_chars().alias("length")) + .sort("length", "age") + .select("age") + .to_series() + .to_list() + ) df_plot = df_plot.join( - pl.DataFrame({ - "age": age_categories_sorted, - "age_sorted" : [f'{age_tr_i+1:02} - {age_categories_sorted[age_tr_i]}' for age_tr_i in range(len(age_categories_sorted))] - }), - on="age", - how="left" - ) + pl.DataFrame( + { + "age": age_categories_sorted, + "age_sorted": [ + f"{age_tr_i + 1:02} - {age_categories_sorted[age_tr_i]}" + for age_tr_i in range(len(age_categories_sorted)) + ], + } + ), + on="age", + how="left", + ) - plot = ( df_plot - >> p9.ggplot() - + p9.geom_bar(p9.aes("age_sorted", "value", fill="genre"),stat="identity") - + p9.theme_matplotlib() - + p9.facet_wrap("~ annee") - + p9.coord_flip() - + p9.scale_x_discrete(labels=tr_age_sorted_plot) - + p9.scale_y_continuous(labels=abs_list) - + p9.labs( - title=f"Évolution de la structure de la population entre {df_plot.min()[0, "annee"]} et {df_plot.max()[0, "annee"]})", - x="Tranche d'âge", - y="Population (M)" - ) + plot = df_plot >> p9.ggplot() + p9.geom_bar( + p9.aes("age_sorted", "value", fill="genre"), stat="identity" + ) + p9.theme_matplotlib() + p9.facet_wrap( + "~ annee" + ) + p9.coord_flip() + p9.scale_x_discrete( + labels=tr_age_sorted_plot + ) + p9.scale_y_continuous(labels=abs_list) + p9.labs( + title=f"Évolution de la structure de la population entre {df_plot.min()[0, 'annee']} et {df_plot.max()[0, 'annee']})", + x="Tranche d'âge", + y="Population (M)", ) return plot -# %% + +# %% plot_age_pyramid(df, [1975, 2023]) # %% -fig,(ax1,ax2) = plt.subplots(1,2,figsize=(15,6)) +fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6)) solutions.plot_age_pyramid(df.to_pandas(), 1975, ax=ax1) solutions.plot_age_pyramid(df.to_pandas(), 2022, ax=ax2) fig # %% -df_matching = solutions.load_departements_regions("https://static.data.gouv.fr/resources/departements-et-leurs-regions/20190815-175403/departements-region.json") +df_matching = solutions.load_departements_regions( + "https://static.data.gouv.fr/resources/departements-et-leurs-regions/20190815-175403/departements-region.json" +) df_matching + # %% def load_departements_regions(url): return pl.from_dicts(requests.get(url).json()) @@ -194,29 +192,33 @@ def load_departements_regions(url): df_regions = solutions.match_department_regions(df.to_pandas(), df_matching) df_regions + # %% def match_department_regions(df, df_matching): df_regions = df.join( - df_matching, - how="left", - left_on="dep_code", - right_on="num_dep" + df_matching, how="left", left_on="dep_code", right_on="num_dep" ) return df_regions + # %% df_regions = match_department_regions(df, reg_details) df_regions # %% -geo = solutions.load_geo_data("https://minio.lab.sspcloud.fr/projet-cartiflette/diffusion/shapefiles-test1/year=2022/administrative_level=REGION/crs=4326/FRANCE_ENTIERE=metropole/vectorfile_format='geojson'/provider='IGN'/source='EXPRESS-COG-CARTO-TERRITOIRE'/raw.geojson") +geo = solutions.load_geo_data( + "https://minio.lab.sspcloud.fr/projet-cartiflette/diffusion/shapefiles-test1/year=2022/administrative_level=REGION/crs=4326/FRANCE_ENTIERE=metropole/vectorfile_format='geojson'/provider='IGN'/source='EXPRESS-COG-CARTO-TERRITOIRE'/raw.geojson" +) geo + # %% def load_geo_data(url): geodata = gpd.read_file(url) - geodata = geodata[['NOM', 'geometry']] + geodata = geodata[["NOM", "geometry"]] return geodata + + # %% url = "https://minio.lab.sspcloud.fr/projet-cartiflette/diffusion/shapefiles-test1/year=2022/administrative_level=REGION/crs=4326/FRANCE_ENTIERE=metropole/vectorfile_format='geojson'/provider='IGN'/source='EXPRESS-COG-CARTO-TERRITOIRE'/raw.geojson" @@ -226,20 +228,15 @@ def load_geo_data(url): # %% -(df_regions\ - .filter(pl.col.annee==2022, pl.col.genre=="Ensemble", pl.col.age=="Total") - .group_by('region_name') +( + df_regions.filter( + pl.col.annee == 2022, pl.col.genre == "Ensemble", pl.col.age == "Total" + ) + .group_by("region_name") .agg(pl.col.population.sum()) .to_pandas() - .merge( - geo, - left_on="region_name", - right_on="NOM", - how="left" - ) - >> p9.ggplot(p9.aes(fill="population")) - + p9.geom_map() - + p9.theme_matplotlib() + .merge(geo, left_on="region_name", right_on="NOM", how="left") + >> p9.ggplot(p9.aes(fill="population")) + p9.geom_map() + p9.theme_matplotlib() ) # list(set(list(geo['NOM'].unique())) & set(df_regions.select("region_name").unique().to_series().to_list())) From ef2de3fccb8c188b725fb54c9040a4b8018ac7da Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 14:48:59 +0000 Subject: [PATCH 80/92] review - RP - 2 --- source/projects/RP/solutions_polars.py | 28 -------------------------- 1 file changed, 28 deletions(-) diff --git a/source/projects/RP/solutions_polars.py b/source/projects/RP/solutions_polars.py index 47270187..071d543d 100644 --- a/source/projects/RP/solutions_polars.py +++ b/source/projects/RP/solutions_polars.py @@ -1,6 +1,5 @@ # %% import geopandas as gpd -import matplotlib.pyplot as plt import plotnine as p9 import polars as pl import requests @@ -162,37 +161,10 @@ def plot_age_pyramid(df, years): return plot -# %% -plot_age_pyramid(df, [1975, 2023]) -# %% - -fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 6)) - -solutions.plot_age_pyramid(df.to_pandas(), 1975, ax=ax1) -solutions.plot_age_pyramid(df.to_pandas(), 2022, ax=ax2) - -fig -# %% -df_matching = solutions.load_departements_regions( - "https://static.data.gouv.fr/resources/departements-et-leurs-regions/20190815-175403/departements-region.json" -) -df_matching - - -# %% def load_departements_regions(url): return pl.from_dicts(requests.get(url).json()) -# %% -url = "https://static.data.gouv.fr/resources/departements-et-leurs-regions/20190815-175403/departements-region.json" -reg_details = load_departements_regions(url) -reg_details -# %% -df_regions = solutions.match_department_regions(df.to_pandas(), df_matching) -df_regions - - # %% def match_department_regions(df, df_matching): df_regions = df.join( From dc8b6d70e3370825df78b2d8ba6c9f9a0859fb87 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 14:55:44 +0000 Subject: [PATCH 81/92] review - RP - 3 --- source/projects/RP/solutions_polars.py | 44 +++++++------------------- 1 file changed, 12 insertions(+), 32 deletions(-) diff --git a/source/projects/RP/solutions_polars.py b/source/projects/RP/solutions_polars.py index 071d543d..b0c8dfd2 100644 --- a/source/projects/RP/solutions_polars.py +++ b/source/projects/RP/solutions_polars.py @@ -165,7 +165,6 @@ def load_departements_regions(url): return pl.from_dicts(requests.get(url).json()) -# %% def match_department_regions(df, df_matching): df_regions = df.join( df_matching, how="left", left_on="dep_code", right_on="num_dep" @@ -173,43 +172,24 @@ def match_department_regions(df, df_matching): return df_regions -# %% -df_regions = match_department_regions(df, reg_details) -df_regions - -# %% -geo = solutions.load_geo_data( - "https://minio.lab.sspcloud.fr/projet-cartiflette/diffusion/shapefiles-test1/year=2022/administrative_level=REGION/crs=4326/FRANCE_ENTIERE=metropole/vectorfile_format='geojson'/provider='IGN'/source='EXPRESS-COG-CARTO-TERRITOIRE'/raw.geojson" -) -geo - - -# %% def load_geo_data(url): geodata = gpd.read_file(url) - geodata = geodata[["NOM", "geometry"]] return geodata -# %% -url = "https://minio.lab.sspcloud.fr/projet-cartiflette/diffusion/shapefiles-test1/year=2022/administrative_level=REGION/crs=4326/FRANCE_ENTIERE=metropole/vectorfile_format='geojson'/provider='IGN'/source='EXPRESS-COG-CARTO-TERRITOIRE'/raw.geojson" - -geo = load_geo_data(url) -# %% -solutions.plot_population_by_regions(df_regions.to_pandas(), geo, 2022) - -# %% - -( - df_regions.filter( - pl.col.annee == 2022, pl.col.genre == "Ensemble", pl.col.age == "Total" +def plot_population_by_regions(df, geo, year): + plot = ( + df_regions.filter( + pl.col.annee == year, pl.col.genre == "Ensemble", pl.col.age == "Total" + ) + .group_by("region_name") + .agg(pl.sum("population")) + .to_pandas() + .merge(geo, left_on="region_name", right_on="NOM", how="left") + >> p9.ggplot(p9.aes(fill="population")) + p9.geom_map() + p9.theme_matplotlib() ) - .group_by("region_name") - .agg(pl.col.population.sum()) - .to_pandas() - .merge(geo, left_on="region_name", right_on="NOM", how="left") - >> p9.ggplot(p9.aes(fill="population")) + p9.geom_map() + p9.theme_matplotlib() -) + return plot + # list(set(list(geo['NOM'].unique())) & set(df_regions.select("region_name").unique().to_series().to_list())) # %% From 5149479b2b702b57241647923f74bcfac045cc04 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 15:13:54 +0000 Subject: [PATCH 82/92] review - RP - with compute population_growth_per_region --- source/projects/RP/solutions_polars.py | 32 +++++++++++++++++++++----- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/source/projects/RP/solutions_polars.py b/source/projects/RP/solutions_polars.py index b0c8dfd2..83a2575f 100644 --- a/source/projects/RP/solutions_polars.py +++ b/source/projects/RP/solutions_polars.py @@ -3,7 +3,6 @@ import plotnine as p9 import polars as pl import requests -import solutions def load_data(): @@ -89,7 +88,6 @@ def plot_population_by_gender_per_department(data, department_code): return plot -# %% def get_age_pyramid_data(df, years): pyramide_data = ( df.filter(pl.col.annee.is_in(years), pl.col.age != "Total") @@ -112,7 +110,6 @@ def tr_age_sorted_plot(list): return [tr_age_sorted[5:] for tr_age_sorted in list] -# %% def plot_age_pyramid(df, years): df_plot = ( get_age_pyramid_data(df, years) @@ -191,8 +188,31 @@ def plot_population_by_regions(df, geo, year): return plot -# list(set(list(geo['NOM'].unique())) & set(df_regions.select("region_name").unique().to_series().to_list())) -# %% -solutions.plot_growth_population_by_regions(df_regions.to_pandas(), geo, 2015, 2022) +def compute_population_growth_per_region(df): + """ + This function takes a DataFrame as input and returns the population growth as a percentage + for each region, grouped by year. + + Parameters: + df (polars.DataFrame): DataFrame containing population data. + + Returns: + polars.DataFrame: DataFrame containing population growth as a percentage for each region, + grouped by year. + """ + df_croissance = ( + df.filter(pl.col("genre") == "Ensemble", pl.col("age") == "Total") + .group_by("region_name", "annee") + .agg(pl.sum("population")) + .sort("annee") + .with_columns( + pct_change=pl.col("population").pct_change(1).over("region_name") * 100 + ) + .drop("population") + .pivot(on="region_name", index="annee", values="pct_change", sort_columns=True) + ) + + return df_croissance + # %% From 87a62202c8a97dd2dce77eda536799500ba3bf24 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 15:21:44 +0000 Subject: [PATCH 83/92] review - RP - with compute_mean_population_growth_per_region --- source/projects/RP/solutions_polars.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/source/projects/RP/solutions_polars.py b/source/projects/RP/solutions_polars.py index 83a2575f..cf9cb88e 100644 --- a/source/projects/RP/solutions_polars.py +++ b/source/projects/RP/solutions_polars.py @@ -215,4 +215,23 @@ def compute_population_growth_per_region(df): return df_croissance -# %% +def compute_mean_population_growth_per_region(df, min_year, max_year): + """ + This function takes a DataFrame as input, and returns the mean population growth as a percentage + for each region, between a given range of years. + + Parameters: + df (polars.DataFrame): DataFrame containing population data. + min_year (int): the minimum year of the range to consider + max_year (int): the maximum year of the range to consider + + Returns: + polars.DataFrame: DataFrame containing mean population growth as a percentage for each region, + between the given range of years + """ + df = compute_population_growth_per_region(df) + df_croissance = df.filter( + pl.col("annee") >= min_year, pl.col("annee") <= max_year + ).mean() + + return df_croissance From ed85df663f1e445d52deebaab48a941a817ac42d Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 15:32:12 +0000 Subject: [PATCH 84/92] review - RP - with plot_growth_population_by_regions - final #31 --- source/projects/RP/solutions_polars.py | 39 +++++++++++++++++--------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/source/projects/RP/solutions_polars.py b/source/projects/RP/solutions_polars.py index cf9cb88e..06a39380 100644 --- a/source/projects/RP/solutions_polars.py +++ b/source/projects/RP/solutions_polars.py @@ -1,4 +1,3 @@ -# %% import geopandas as gpd import plotnine as p9 import polars as pl @@ -175,15 +174,14 @@ def load_geo_data(url): def plot_population_by_regions(df, geo, year): - plot = ( - df_regions.filter( - pl.col.annee == year, pl.col.genre == "Ensemble", pl.col.age == "Total" - ) - .group_by("region_name") - .agg(pl.sum("population")) - .to_pandas() - .merge(geo, left_on="region_name", right_on="NOM", how="left") - >> p9.ggplot(p9.aes(fill="population")) + p9.geom_map() + p9.theme_matplotlib() + plot = df_regions.filter( + pl.col.annee == year, pl.col.genre == "Ensemble", pl.col.age == "Total" + ).group_by("region_name").agg(pl.sum("population")).to_pandas().merge( + geo, left_on="region_name", right_on="NOM", how="left" + ) >> p9.ggplot( + p9.aes(fill="population") + ) + p9.geom_map() + p9.theme_matplotlib() + p9.labs( + title="Population des différentes régions de France" ) return plot @@ -230,8 +228,23 @@ def compute_mean_population_growth_per_region(df, min_year, max_year): between the given range of years """ df = compute_population_growth_per_region(df) - df_croissance = df.filter( - pl.col("annee") >= min_year, pl.col("annee") <= max_year - ).mean() + df_croissance = ( + df.filter(pl.col("annee") >= min_year, pl.col("annee") <= max_year) + .mean() + .unpivot(index="annee", variable_name="region", value_name="croissance_pop") + ) return df_croissance + + +def plot_growth_population_by_regions(df, geo, min_year, max_year): + df = compute_mean_population_growth_per_region(df, min_year, max_year) + df_geo = geo.merge(df.to_pandas(), right_on=["region"], left_on=["NOM"]) + + plot = df_geo >> p9.ggplot( + p9.aes(fill="croissance_pop") + ) + p9.geom_map() + p9.theme_matplotlib() + p9.labs( + title="Croissance de la population des différentes régions de France (en %)" + ) + + return plot From d18a2184c938f08b1d4618da6bf36f9596e93c5e Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 15:43:19 +0000 Subject: [PATCH 85/92] tutorial RP with polars #31 --- source/projects/RP/tutorial.qmd | 35 ++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/source/projects/RP/tutorial.qmd b/source/projects/RP/tutorial.qmd index 64461463..4dddc75f 100644 --- a/source/projects/RP/tutorial.qmd +++ b/source/projects/RP/tutorial.qmd @@ -6,7 +6,10 @@ execute: ::: {.content-visible when-profile="fr"} # Projet 3 - Estimations de population à partir du recensement -Le but de ce projet est de réaliser une analyse statistique rapide d'un jeu de données dont le format n'est pas directement optimisé pour une analyse en python. Nous allons utiliser exclusivement la librairie `pandas` pour l'analyse de données. Pour reproduire au mieux une situation à laquelle vous pouvez être confrontés, nous vous invitons vivement à consulter la documentation de la librairie ([docs](https://pandas.pydata.org/docs/user_guide/index.html#user-guide)). +Le but de ce projet est de réaliser une analyse statistique rapide d'un jeu de données dont le format n'est pas directement optimisé pour une analyse en python. +Vous avez le choix entre utiliser la librairie `pandas` ou `polars` pour l'analyse de données. Pour reproduire au mieux une situation à laquelle vous pouvez être confrontés, nous vous invitons vivement à consulter la documentation de la librairie que vous aurez choisie ([pandas](https://pandas.pydata.org/docs/user_guide/index.html#user-guide) ou [polars](https://docs.pola.rs/api/python/stable/reference/index.html)). + +Vous n'avez plus qu'à importer les solutions au format que vous aurez choisi en commentant les lignes idoines. Nous allons nous intéresser à l’estimation de la population au 1er janvier de chaque année, cette estimation étant effectuée à partir des recensements et des modèles d’évolution de la population. Les données sont accessibles sur le site de l'Insee à l'adresse suivante : [https://www.insee.fr/fr/statistiques/1893198](https://www.insee.fr/fr/statistiques/1893198). @@ -20,14 +23,16 @@ import matplotlib.pyplot as plt import geopandas as gpd import seaborn as sns -import solutions +# Choisissez entre pandas/seaborn/matplotlib et polars/plotnine +import solutions # pandas and seaborn/matplotlib +# import solutions_polars as solutions # polars and plotnine ``` ## Partie 1 : Téléchargement et mise en forme des données Avant d'effectuer le téléchargement des données avec python il est nécessaire de connaître le format de nos données. Dans notre cas, il s'agit du format Excel (`.xlsx`). De plus, il peut être utile de regarder à quoi ressemble les données que l'on souhaite importer, notamment lorsque leur format n'est pas standard. Ainsi, avant de commencer, prenez le temps de jeter un œil aux données. -### Question 0 +### Question 0 Téléchargez les données en cliquant sur ce [lien](https://www.insee.fr/fr/statistiques/fichier/1893198/estim-pop-dep-sexe-aq-1975-2023.xls) et ouvrez-le avec votre logiciel tableur préféré. Analysez la structure des données. @@ -52,9 +57,9 @@ def load_data(): return data ``` -### Question 2 +### Question 2 -Maintenant que les données sont importées nous allons les mettre sous la forme d'un seul `DataFrame` dont les colonnes sont : +Maintenant que les données sont importées nous allons les mettre sous la forme d'un seul `DataFrame` dont les colonnes sont : - `genre` ; @@ -68,7 +73,7 @@ Maintenant que les données sont importées nous allons les mettre sous la forme - `annee`. -2.1 - Pour ce faire créez une fonction `reshape_data_by_year(df, year)` qui prend en argument un DataFrame issu de votre Dict `data` et une année donnée. +2.1 - Pour ce faire créez une fonction `reshape_data_by_year(df, year)` qui prend en argument un DataFrame issu de votre Dict `data` et une année donnée. #### Résultat attendu @@ -161,16 +166,22 @@ def get_age_pyramid_data(df, year): ```{python} #| eval: false +# For pandas and matplotlib fig,(ax1,ax2) = plt.subplots(1,2,figsize=(15,6)) solutions.plot_age_pyramid(df, 1975, ax=ax1) solutions.plot_age_pyramid(df, 2022, ax=ax2) + +# For polars and plotnine +# solutions.plot_age_pyramid(df, 1975) +# solutions.plot_age_pyramid(df, 2022) ``` #### À vous de jouer ! ```{python} #| eval: false +# For pandas and matplotlib def plot_age_pyramid(df, year, ax=None): if ax is None: ax = plt.gca() @@ -182,11 +193,11 @@ def plot_age_pyramid(df, year, ax=None): Les données géographiques sont très utiles car elles permettent de visualiser et d'analyser des informations liées à des emplacements spécifiques sur la terre. Les données géographiques peuvent être utilisées pour créer des cartes, des visualisations en 3D et des analyses spatiales pour comprendre les tendances, les modèles et les relations dans les données. En utilisant des bibliothèques Python telles que `Geopandas` ou `Folium`, vous pouvez facilement manipuler et visualiser des données géographiques pour répondre à vos besoins analytiques. -Afin de représenter graphiquement des données géographiques il est nécessaire d'obtenir les données des contours (*shapefile*) des zones que l'on souhaite représenter. L'objectif de cette partie est de créer une carte choropleth des régions en fonction de leur population respective. +Afin de représenter graphiquement des données géographiques il est nécessaire d'obtenir les données des contours (*shapefile*) des zones que l'on souhaite représenter. L'objectif de cette partie est de créer une carte choropleth des régions en fonction de leur population respective. -Les données que nous avons actuellement contiennent les informations par département et non par région. Avant toute chose il est nécessaire d'affecter à chaque département sa région correspondante. Pour cela, vous pourrez utiliser le fichier `.json` disponible à l'adresse suivante : [https://static.data.gouv.fr/resources/departements-et-leurs-regions/20190815-175403/departements-region.json](https://static.data.gouv.fr/resources/departements-et-leurs-regions/20190815-175403/departements-region.json). +Les données que nous avons actuellement contiennent les informations par département et non par région. Avant toute chose il est nécessaire d'affecter à chaque département sa région correspondante. Pour cela, vous pourrez utiliser le fichier `.json` disponible à l'adresse suivante : [https://static.data.gouv.fr/resources/departements-et-leurs-regions/20190815-175403/departements-region.json](https://static.data.gouv.fr/resources/departements-et-leurs-regions/20190815-175403/departements-region.json). -### Question 5 +### Question 5 Créez un DataFrame à partir du fichier `.json` des départements et régions de France précédemment mentionné. Assurez-vous que les colonnes soient au bon format. @@ -252,7 +263,7 @@ def load_geo_data(url): ### Question 8 -Produire une carte choropleth de la population en 2022 des régions de France. Vous pouvez consulter la documentation de `geopandas` [ici](https://geopandas.org/en/stable/docs/user_guide/mapping.html). +Produire une carte choropleth de la population en 2022 des régions de France. Vous pouvez consulter la documentation de `geopandas` [ici](https://geopandas.org/en/stable/docs/user_guide/mapping.html). #### Résultat attendu @@ -271,7 +282,7 @@ def plot_population_by_regions(df, geo, year): ### Question 9 -La population totale d'une région n'est pas suffisante pour analyser la démographie d'une région. Il peut être intéressant de s'intéresser à la croissance démographique. +La population totale d'une région n'est pas suffisante pour analyser la démographie d'une région. Il peut être intéressant de s'intéresser à la croissance démographique. 9.1- Ecrire une fonction `compute_population_growth_per_region(df)` qui calcule la croissance de la population en pourcentage par an pour chaque région. @@ -662,4 +673,4 @@ def plot_growth_population_by_regions(df, geo, min_year, max_year): ``` -::: \ No newline at end of file +::: From bdc1af8c4ffdda61ec0c6fba2e89deaf6671bf82 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 15:43:26 +0000 Subject: [PATCH 86/92] typo --- source/projects/RP/solutions_polars.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/projects/RP/solutions_polars.py b/source/projects/RP/solutions_polars.py index 06a39380..74c6457b 100644 --- a/source/projects/RP/solutions_polars.py +++ b/source/projects/RP/solutions_polars.py @@ -174,7 +174,7 @@ def load_geo_data(url): def plot_population_by_regions(df, geo, year): - plot = df_regions.filter( + plot = df.filter( pl.col.annee == year, pl.col.genre == "Ensemble", pl.col.age == "Total" ).group_by("region_name").agg(pl.sum("population")).to_pandas().merge( geo, left_on="region_name", right_on="NOM", how="left" From 1f00558b2d147591f52c9e67d9df653ccb794541 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:00:01 +0000 Subject: [PATCH 87/92] tutorial meteo with polars #31 --- source/projects/meteo/tutorial.qmd | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/source/projects/meteo/tutorial.qmd b/source/projects/meteo/tutorial.qmd index f5fbdb74..a45e3a0b 100644 --- a/source/projects/meteo/tutorial.qmd +++ b/source/projects/meteo/tutorial.qmd @@ -3,7 +3,7 @@ ## Contexte du projet -Il y a certains jours où l'on serait bien resté en télétravail.. Parmi ceux-là, ces jours à la fois humides et venteux où il est impossible de maintenir une coiffure décente, malgré tous ses efforts. Pourrait-on utiliser `Python` pour prédire ce que les anglo-saxons nomment des *bad hair day* ("mauvais jour de cheveux") ? +Il y a certains jours où l'on serait bien resté en télétravail. Parmi ceux-là, ces jours à la fois humides et venteux où il est impossible de maintenir une coiffure décente, malgré tous ses efforts. Pourrait-on utiliser `Python` pour prédire ce que les anglo-saxons nomment des *bad hair day* ("mauvais jour de cheveux") ? L'objectif du projet est de construire un *bad hair index* ("indice de mauvais jour de cheveux") à partir des données météorologiques et de représenter graphiquement l'évolution de cette indice afin de déterminer à l'avance les jours où l'on ferait mieux de rester bien au chaud. Afin d'obtenir les données adéquates, nous allons requêter des APIs. @@ -12,18 +12,20 @@ Une API (Interface de Programmation d'Application) est un ensemble de règles et Les APIs que nous allons utiliser sont : - [Nominatim](https://nominatim.org/release-docs/latest/api/Overview/) : une API de géocodage proposée par **OpenStreetMap** qui nous permet de convertir un nom de lieu en coordonnées géographiques. -- [Open-Meteo Weather Forecast](https://open-meteo.com/en/docs) : une API qui fournit des prévisions météorologiques détaillées. +- [Open-Meteo Weather Forecast](https://open-meteo.com/en/docs) : une API qui fournit des prévisions météorologiques détaillées. Commençons par importer les packages dont nous aurons besoin au cours de ce projet. ```{python} #| eval: false import requests -import pandas -import seaborn as sns -import matplotlib.pyplot as plt +# Choississez entre pandas et polars +# for pandas and seaborn/matplotlib import solutions + +# for polars and plotnine +# import solutions_polars as solutions ``` ## Partie 1 : récupération des coordonnées géographiques pour une localisation donnée @@ -37,7 +39,7 @@ Lorsque l'on travaille à partir d'une API, la première étape est toujours de La première caractéristique essentielle d'une API est le *endpoint*, c'est à dire l'URL à laquelle on va envoyer des requêtes. Dans notre cas, on va utiliser le *endpoint* `/search` dans la mesure où l'on veut trouver un objet géographique (des coordonnées) à partir d'un nom de localisation. La [page de documentation](https://nominatim.org/release-docs/develop/api/Search/) associée à ce *endpoint* nous donne toutes les informations dont nous avons besoin : - le format d'une requête est `https://nominatim.openstreetmap.org/search?` où `` doit être remplacé par les paramètres de la requête, séparés par le symbole `&` -- dans la section [Structured Query](https://nominatim.org/release-docs/develop/api/Search/#structured-query), on voit que l'API admet comme paramètres `country` (pays) et `city` (ville), que l'on va utiliser pour paramétrer notre requête. +- dans la section [Structured Query](https://nominatim.org/release-docs/develop/api/Search/#structured-query), on voit que l'API admet comme paramètres `country` (pays) et `city` (ville), que l'on va utiliser pour paramétrer notre requête. Définissez une fonction `build_request_nominatim` qui construit le lien de la requête pour un pays et une ville donnée. @@ -67,7 +69,7 @@ url_request_nominatim ### Question 2 -La prochaine étape est d'envoyer notre requête paramétrisée à l'API. Pour la tester au préalable, on peut simplement mettre l'adresse dans un navigateur et voir ce que nous renvoie l'API. Si les résultats ont l'air cohérent, on peut continuer. Si l'API nous renvoie un code d'erreur, il y a sûrement une erreur à trouver dans la requête. +La prochaine étape est d'envoyer notre requête paramétrisée à l'API. Pour la tester au préalable, on peut simplement mettre l'adresse dans un navigateur et voir ce que nous renvoie l'API. Si les résultats ont l'air cohérent, on peut continuer. Si l'API nous renvoie un code d'erreur, il y a sûrement une erreur à trouver dans la requête. Pour effectuer cette requête à partir de `Python` afin d'en récupérer les résultats, on utilise la fonction `requests.get()` à laquelle on fournit comme seul paramètre l'URL de la requête. On obtient en retour un objet "réponse", dont on peut extraire le contenu `JSON` sous forme d'un dictionnaire `Python` en lui appliquant la méthode `.json()`. Il faut alors parcourir le dictionnaire pour en extraire les informations pertinentes ; dans notre cas : la latitude et la longitude. @@ -370,11 +372,13 @@ Let's start by importing the packages we will need throughout this project. ```{python} #| eval: false import requests -import pandas -import seaborn as sns -import matplotlib.pyplot as plt +# Choose between using pandas or polars +# for pandas and seaborn/matplotlib import solutions + +# for polars and plotnine +# import solutions_polars as solutions ``` ## Part 1: Retrieving geographic coordinates for a given location @@ -686,4 +690,4 @@ main(country="Germany", city="Berlin", agg_var="hour") ``` -::: \ No newline at end of file +::: From 7fd32867b3ea5b59b4e8760b95e211ba4e0d1812 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:00:18 +0000 Subject: [PATCH 88/92] cleaning solutions_polars meteo #31 --- source/projects/meteo/solutions_polars.py | 81 +++++++++++------------ 1 file changed, 39 insertions(+), 42 deletions(-) diff --git a/source/projects/meteo/solutions_polars.py b/source/projects/meteo/solutions_polars.py index d2141cbd..840e4ed3 100644 --- a/source/projects/meteo/solutions_polars.py +++ b/source/projects/meteo/solutions_polars.py @@ -1,8 +1,8 @@ +import plotnine as p9 import polars as pl import requests -from plotnine import ggplot, aes, geom_line, theme_matplotlib, labs -# import solutions + def build_request_nominatim(country, city): url_request = f"https://nominatim.openstreetmap.org/search?country={country}&city={city}&format=json" return url_request @@ -36,58 +36,61 @@ def get_meteo_data(query): print(f"Error code : {code}") return None -# %% -def preprocess_predictions(predictions): +def preprocess_predictions(predictions): df = ( pl.DataFrame(predictions) - .select('hourly') - .unnest('hourly') - .explode('time', 'relativehumidity_2m', 'windspeed_10m') - .cast({'time': pl.Datetime}) - .rename({'time': 'date_time', 'relativehumidity_2m': 'humidity', 'windspeed_10m': 'wind_speed'}) - .with_columns( - day=pl.col('date_time').dt.date(), - hour=pl.col('date_time').dt.hour(), - bad_hair_index=pl.col.humidity*pl.col.wind_speed - ) + .select("hourly") + .unnest("hourly") + .explode("time", "relativehumidity_2m", "windspeed_10m") + .cast({"time": pl.Datetime}) + .rename( + { + "time": "date_time", + "relativehumidity_2m": "humidity", + "windspeed_10m": "wind_speed", + } + ) + .with_columns( + day=pl.col("date_time").dt.date(), + hour=pl.col("date_time").dt.hour(), + bad_hair_index=pl.col.humidity * pl.col.wind_speed, + ) ) return df -# %% + def plot_agg_avg_bhi(df_preds, agg_var="day"): - if agg_var not in ['day', 'hour']: - raise ValueError('Not the right aggregation variable') - + if agg_var not in ["day", "hour"]: + raise ValueError("Not the right aggregation variable") + plot = ( - ggplot(df_preds.group_by(agg_var).agg(pl.mean('bad_hair_index')), aes(x=agg_var, y='bad_hair_index')) - + geom_line() - + theme_matplotlib() + p9.ggplot( + df_preds.group_by(agg_var).agg(pl.mean("bad_hair_index")), + p9.aes(x=agg_var, y="bad_hair_index"), + ) + + p9.geom_line() + + p9.theme_matplotlib() ) if agg_var == "day": - plot = ( - plot - + labs( - title="Evolution of the average BHI on 7 days", - x='Hour', - y='Average Bad Hair Index') + plot = plot + p9.labs( + title="Evolution of the average BHI on 7 days", + x="Hour", + y="Average Bad Hair Index", ) elif agg_var == "hour": - plot = ( - plot - + labs( - title="Average BHI by hour on the next 7 days", - x='Day', - y='Average Bad Hair Index') + plot = plot + p9.labs( + title="Average BHI by hour on the next 7 days", + x="Day", + y="Average Bad Hair Index", ) - + return plot -# %% def main(country, city, agg_var="day"): -# def main(agg_var="day"): + # def main(agg_var="day"): # Get lat, long from Nominatim API url_request_nominatim = build_request_nominatim(country, city) lat, long = get_lat_long(query=url_request_nominatim) @@ -100,9 +103,3 @@ def main(country, city, agg_var="day"): # Graphical representation return plot_agg_avg_bhi(df_preds, agg_var) - -# %% -main('France', 'Montrouge', 'day') - -# %% -main('France', 'Montrouge', 'hour') \ No newline at end of file From 78bd438b26556384fb1377f22d850245f6dd6e66 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:08:17 +0000 Subject: [PATCH 89/92] clearer import statement --- source/projects/RP/tutorial.qmd | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/source/projects/RP/tutorial.qmd b/source/projects/RP/tutorial.qmd index 4dddc75f..48f04f33 100644 --- a/source/projects/RP/tutorial.qmd +++ b/source/projects/RP/tutorial.qmd @@ -17,15 +17,19 @@ Le fichier que nous allons utilisé peut être téléchargé directement via cet ```{python} #| eval: false -import copy +import geopandas as gpd + +# Choisissez entre pandas/seaborn/matplotlib et polars/plotnine +# Bloc to uncomment for pandas and seaborn/matplotlib +import solutions import pandas as pd import matplotlib.pyplot as plt -import geopandas as gpd import seaborn as sns -# Choisissez entre pandas/seaborn/matplotlib et polars/plotnine -import solutions # pandas and seaborn/matplotlib -# import solutions_polars as solutions # polars and plotnine +# Bloc to uncomment for polars and plotnine +# import solutions_polars as solutions +# import polars as pl +# import plotnine as p9 ``` ## Partie 1 : Téléchargement et mise en forme des données From 118193246e9abbe03c16b6cc83627ba8096c970e Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:08:27 +0000 Subject: [PATCH 90/92] remove unnecessary dependancies --- pyproject.toml | 4 +- uv.lock | 1365 +----------------------------------------------- 2 files changed, 22 insertions(+), 1347 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0f47637e..9979da92 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,10 +10,7 @@ dependencies = [ "pandas", "pyarrow", "scikit-learn", - "tidypolars>=0.3.2", - "jupyter>=1.1.1", "cartiflette>=0.1.9", - "fastexcel>=0.18.0", "geopandas>=1.1.1", "plotnine>=0.15.2", "polars>=1.36.1", @@ -21,4 +18,5 @@ dependencies = [ "requests>=2.32.5", "seaborn>=0.13.2", "xlrd>=2.0.2", + "fastexcel>=0.19.0", ] diff --git a/uv.lock b/uv.lock index 8b9896f0..5e2d7297 100644 --- a/uv.lock +++ b/uv.lock @@ -6,101 +6,6 @@ resolution-markers = [ "python_full_version < '3.14'", ] -[[package]] -name = "anyio" -version = "4.12.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "idna" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/96/f0/5eb65b2bb0d09ac6776f2eb54adee6abe8228ea05b20a5ad0e4945de8aac/anyio-4.12.1.tar.gz", hash = "sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703", size = 228685, upload-time = "2026-01-06T11:45:21.246Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c", size = 113592, upload-time = "2026-01-06T11:45:19.497Z" }, -] - -[[package]] -name = "appnope" -version = "0.1.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/35/5d/752690df9ef5b76e169e68d6a129fa6d08a7100ca7f754c89495db3c6019/appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee", size = 4170, upload-time = "2024-02-06T09:43:11.258Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c", size = 4321, upload-time = "2024-02-06T09:43:09.663Z" }, -] - -[[package]] -name = "argon2-cffi" -version = "25.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "argon2-cffi-bindings" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/0e/89/ce5af8a7d472a67cc819d5d998aa8c82c5d860608c4db9f46f1162d7dab9/argon2_cffi-25.1.0.tar.gz", hash = "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1", size = 45706, upload-time = "2025-06-03T06:55:32.073Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl", hash = "sha256:fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741", size = 14657, upload-time = "2025-06-03T06:55:30.804Z" }, -] - -[[package]] -name = "argon2-cffi-bindings" -version = "25.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cffi" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/5c/2d/db8af0df73c1cf454f71b2bbe5e356b8c1f8041c979f505b3d3186e520a9/argon2_cffi_bindings-25.1.0.tar.gz", hash = "sha256:b957f3e6ea4d55d820e40ff76f450952807013d361a65d7f28acc0acbf29229d", size = 1783441, upload-time = "2025-07-30T10:02:05.147Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/60/97/3c0a35f46e52108d4707c44b95cfe2afcafc50800b5450c197454569b776/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:3d3f05610594151994ca9ccb3c771115bdb4daef161976a266f0dd8aa9996b8f", size = 54393, upload-time = "2025-07-30T10:01:40.97Z" }, - { url = "https://files.pythonhosted.org/packages/9d/f4/98bbd6ee89febd4f212696f13c03ca302b8552e7dbf9c8efa11ea4a388c3/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8b8efee945193e667a396cbc7b4fb7d357297d6234d30a489905d96caabde56b", size = 29328, upload-time = "2025-07-30T10:01:41.916Z" }, - { url = "https://files.pythonhosted.org/packages/43/24/90a01c0ef12ac91a6be05969f29944643bc1e5e461155ae6559befa8f00b/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3c6702abc36bf3ccba3f802b799505def420a1b7039862014a65db3205967f5a", size = 31269, upload-time = "2025-07-30T10:01:42.716Z" }, - { url = "https://files.pythonhosted.org/packages/d4/d3/942aa10782b2697eee7af5e12eeff5ebb325ccfb86dd8abda54174e377e4/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1c70058c6ab1e352304ac7e3b52554daadacd8d453c1752e547c76e9c99ac44", size = 86558, upload-time = "2025-07-30T10:01:43.943Z" }, - { url = "https://files.pythonhosted.org/packages/0d/82/b484f702fec5536e71836fc2dbc8c5267b3f6e78d2d539b4eaa6f0db8bf8/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e2fd3bfbff3c5d74fef31a722f729bf93500910db650c925c2d6ef879a7e51cb", size = 92364, upload-time = "2025-07-30T10:01:44.887Z" }, - { url = "https://files.pythonhosted.org/packages/c9/c1/a606ff83b3f1735f3759ad0f2cd9e038a0ad11a3de3b6c673aa41c24bb7b/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4f9665de60b1b0e99bcd6be4f17d90339698ce954cfd8d9cf4f91c995165a92", size = 85637, upload-time = "2025-07-30T10:01:46.225Z" }, - { url = "https://files.pythonhosted.org/packages/44/b4/678503f12aceb0262f84fa201f6027ed77d71c5019ae03b399b97caa2f19/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ba92837e4a9aa6a508c8d2d7883ed5a8f6c308c89a4790e1e447a220deb79a85", size = 91934, upload-time = "2025-07-30T10:01:47.203Z" }, - { url = "https://files.pythonhosted.org/packages/f0/c7/f36bd08ef9bd9f0a9cff9428406651f5937ce27b6c5b07b92d41f91ae541/argon2_cffi_bindings-25.1.0-cp314-cp314t-win32.whl", hash = "sha256:84a461d4d84ae1295871329b346a97f68eade8c53b6ed9a7ca2d7467f3c8ff6f", size = 28158, upload-time = "2025-07-30T10:01:48.341Z" }, - { url = "https://files.pythonhosted.org/packages/b3/80/0106a7448abb24a2c467bf7d527fe5413b7fdfa4ad6d6a96a43a62ef3988/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b55aec3565b65f56455eebc9b9f34130440404f27fe21c3b375bf1ea4d8fbae6", size = 32597, upload-time = "2025-07-30T10:01:49.112Z" }, - { url = "https://files.pythonhosted.org/packages/05/b8/d663c9caea07e9180b2cb662772865230715cbd573ba3b5e81793d580316/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:87c33a52407e4c41f3b70a9c2d3f6056d88b10dad7695be708c5021673f55623", size = 28231, upload-time = "2025-07-30T10:01:49.92Z" }, - { url = "https://files.pythonhosted.org/packages/1d/57/96b8b9f93166147826da5f90376e784a10582dd39a393c99bb62cfcf52f0/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:aecba1723ae35330a008418a91ea6cfcedf6d31e5fbaa056a166462ff066d500", size = 54121, upload-time = "2025-07-30T10:01:50.815Z" }, - { url = "https://files.pythonhosted.org/packages/0a/08/a9bebdb2e0e602dde230bdde8021b29f71f7841bd54801bcfd514acb5dcf/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2630b6240b495dfab90aebe159ff784d08ea999aa4b0d17efa734055a07d2f44", size = 29177, upload-time = "2025-07-30T10:01:51.681Z" }, - { url = "https://files.pythonhosted.org/packages/b6/02/d297943bcacf05e4f2a94ab6f462831dc20158614e5d067c35d4e63b9acb/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:7aef0c91e2c0fbca6fc68e7555aa60ef7008a739cbe045541e438373bc54d2b0", size = 31090, upload-time = "2025-07-30T10:01:53.184Z" }, - { url = "https://files.pythonhosted.org/packages/c1/93/44365f3d75053e53893ec6d733e4a5e3147502663554b4d864587c7828a7/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e021e87faa76ae0d413b619fe2b65ab9a037f24c60a1e6cc43457ae20de6dc6", size = 81246, upload-time = "2025-07-30T10:01:54.145Z" }, - { url = "https://files.pythonhosted.org/packages/09/52/94108adfdd6e2ddf58be64f959a0b9c7d4ef2fa71086c38356d22dc501ea/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e924cfc503018a714f94a49a149fdc0b644eaead5d1f089330399134fa028a", size = 87126, upload-time = "2025-07-30T10:01:55.074Z" }, - { url = "https://files.pythonhosted.org/packages/72/70/7a2993a12b0ffa2a9271259b79cc616e2389ed1a4d93842fac5a1f923ffd/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87b72589133f0346a1cb8d5ecca4b933e3c9b64656c9d175270a000e73b288d", size = 80343, upload-time = "2025-07-30T10:01:56.007Z" }, - { url = "https://files.pythonhosted.org/packages/78/9a/4e5157d893ffc712b74dbd868c7f62365618266982b64accab26bab01edc/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1db89609c06afa1a214a69a462ea741cf735b29a57530478c06eb81dd403de99", size = 86777, upload-time = "2025-07-30T10:01:56.943Z" }, - { url = "https://files.pythonhosted.org/packages/74/cd/15777dfde1c29d96de7f18edf4cc94c385646852e7c7b0320aa91ccca583/argon2_cffi_bindings-25.1.0-cp39-abi3-win32.whl", hash = "sha256:473bcb5f82924b1becbb637b63303ec8d10e84c8d241119419897a26116515d2", size = 27180, upload-time = "2025-07-30T10:01:57.759Z" }, - { url = "https://files.pythonhosted.org/packages/e2/c6/a759ece8f1829d1f162261226fbfd2c6832b3ff7657384045286d2afa384/argon2_cffi_bindings-25.1.0-cp39-abi3-win_amd64.whl", hash = "sha256:a98cd7d17e9f7ce244c0803cad3c23a7d379c301ba618a5fa76a67d116618b98", size = 31715, upload-time = "2025-07-30T10:01:58.56Z" }, - { url = "https://files.pythonhosted.org/packages/42/b9/f8d6fa329ab25128b7e98fd83a3cb34d9db5b059a9847eddb840a0af45dd/argon2_cffi_bindings-25.1.0-cp39-abi3-win_arm64.whl", hash = "sha256:b0fdbcf513833809c882823f98dc2f931cf659d9a1429616ac3adebb49f5db94", size = 27149, upload-time = "2025-07-30T10:01:59.329Z" }, -] - -[[package]] -name = "arrow" -version = "1.4.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "python-dateutil" }, - { name = "tzdata" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b9/33/032cdc44182491aa708d06a68b62434140d8c50820a087fac7af37703357/arrow-1.4.0.tar.gz", hash = "sha256:ed0cc050e98001b8779e84d461b0098c4ac597e88704a655582b21d116e526d7", size = 152931, upload-time = "2025-10-18T17:46:46.761Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl", hash = "sha256:749f0769958ebdc79c173ff0b0670d59051a535fa26e8eba02953dc19eb43205", size = 68797, upload-time = "2025-10-18T17:46:45.663Z" }, -] - -[[package]] -name = "asttokens" -version = "3.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/be/a5/8e3f9b6771b0b408517c82d97aed8f2036509bc247d46114925e32fe33f0/asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7", size = 62308, upload-time = "2025-11-15T16:43:48.578Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", size = 27047, upload-time = "2025-11-15T16:43:16.109Z" }, -] - -[[package]] -name = "async-lru" -version = "2.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/05/8a/ca724066c32a53fa75f59e0f21aa822fdaa8a0dffa112d223634e3caabf9/async_lru-2.2.0.tar.gz", hash = "sha256:80abae2a237dbc6c60861d621619af39f0d920aea306de34cb992c879e01370c", size = 14654, upload-time = "2026-02-20T19:11:43.848Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/13/5c/af990f019b8dd11c5492a6371fe74a5b0276357370030b67254a87329944/async_lru-2.2.0-py3-none-any.whl", hash = "sha256:e2c1cf731eba202b59c5feedaef14ffd9d02ad0037fcda64938699f2c380eafe", size = 7890, upload-time = "2026-02-20T19:11:42.273Z" }, -] - [[package]] name = "attrs" version = "25.4.0" @@ -110,45 +15,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, ] -[[package]] -name = "babel" -version = "2.18.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7d/b2/51899539b6ceeeb420d40ed3cd4b7a40519404f9baf3d4ac99dc413a834b/babel-2.18.0.tar.gz", hash = "sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d", size = 9959554, upload-time = "2026-02-01T12:30:56.078Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl", hash = "sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35", size = 10196845, upload-time = "2026-02-01T12:30:53.445Z" }, -] - -[[package]] -name = "beautifulsoup4" -version = "4.14.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "soupsieve" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c3/b0/1c6a16426d389813b48d95e26898aff79abbde42ad353958ad95cc8c9b21/beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86", size = 627737, upload-time = "2025-11-30T15:08:26.084Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" }, -] - -[[package]] -name = "bleach" -version = "6.3.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "webencodings" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/07/18/3c8523962314be6bf4c8989c79ad9531c825210dd13a8669f6b84336e8bd/bleach-6.3.0.tar.gz", hash = "sha256:6f3b91b1c0a02bb9a78b5a454c92506aa0fdf197e1d5e114d2e00c6f64306d22", size = 203533, upload-time = "2025-10-27T17:57:39.211Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl", hash = "sha256:fe10ec77c93ddf3d13a73b035abaac7a9f5e436513864ccdad516693213c65d6", size = 164437, upload-time = "2025-10-27T17:57:37.538Z" }, -] - -[package.optional-dependencies] -css = [ - { name = "tinycss2" }, -] - [[package]] name = "cartiflette" version = "0.1.9" @@ -187,51 +53,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", size = 159438, upload-time = "2025-11-12T02:54:49.735Z" }, ] -[[package]] -name = "cffi" -version = "2.0.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pycparser", marker = "implementation_name != 'PyPy'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, - { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, - { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, - { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, - { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, - { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, - { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, - { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, - { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, - { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, - { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, - { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, - { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" }, - { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" }, - { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, - { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, - { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, - { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, - { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, - { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, - { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" }, - { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" }, - { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" }, - { url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" }, - { url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" }, - { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, - { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, - { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, - { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, - { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, - { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, - { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, - { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, - { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, -] - [[package]] name = "charset-normalizer" version = "3.4.4" @@ -282,15 +103,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] -[[package]] -name = "comm" -version = "0.2.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4c/13/7d740c5849255756bc17888787313b61fd38a0a8304fc4f073dfc46122aa/comm-0.2.3.tar.gz", hash = "sha256:2dc8048c10962d55d7ad693be1e7045d891b7ce8d999c97963a5e3e99c055971", size = 6319, upload-time = "2025-07-25T14:02:04.452Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl", hash = "sha256:c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417", size = 7294, upload-time = "2025-07-25T14:02:02.896Z" }, -] - [[package]] name = "contourpy" version = "1.3.3" @@ -355,75 +167,22 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" }, ] -[[package]] -name = "debugpy" -version = "1.8.20" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e0/b7/cd8080344452e4874aae67c40d8940e2b4d47b01601a8fd9f44786c757c7/debugpy-1.8.20.tar.gz", hash = "sha256:55bc8701714969f1ab89a6d5f2f3d40c36f91b2cbe2f65d98bf8196f6a6a2c33", size = 1645207, upload-time = "2026-01-29T23:03:28.199Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/15/e2/fc500524cc6f104a9d049abc85a0a8b3f0d14c0a39b9c140511c61e5b40b/debugpy-1.8.20-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:5dff4bb27027821fdfcc9e8f87309a28988231165147c31730128b1c983e282a", size = 2539560, upload-time = "2026-01-29T23:03:48.738Z" }, - { url = "https://files.pythonhosted.org/packages/90/83/fb33dcea789ed6018f8da20c5a9bc9d82adc65c0c990faed43f7c955da46/debugpy-1.8.20-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:84562982dd7cf5ebebfdea667ca20a064e096099997b175fe204e86817f64eaf", size = 4293272, upload-time = "2026-01-29T23:03:50.169Z" }, - { url = "https://files.pythonhosted.org/packages/a6/25/b1e4a01bfb824d79a6af24b99ef291e24189080c93576dfd9b1a2815cd0f/debugpy-1.8.20-cp313-cp313-win32.whl", hash = "sha256:da11dea6447b2cadbf8ce2bec59ecea87cc18d2c574980f643f2d2dfe4862393", size = 5331208, upload-time = "2026-01-29T23:03:51.547Z" }, - { url = "https://files.pythonhosted.org/packages/13/f7/a0b368ce54ffff9e9028c098bd2d28cfc5b54f9f6c186929083d4c60ba58/debugpy-1.8.20-cp313-cp313-win_amd64.whl", hash = "sha256:eb506e45943cab2efb7c6eafdd65b842f3ae779f020c82221f55aca9de135ed7", size = 5372930, upload-time = "2026-01-29T23:03:53.585Z" }, - { url = "https://files.pythonhosted.org/packages/33/2e/f6cb9a8a13f5058f0a20fe09711a7b726232cd5a78c6a7c05b2ec726cff9/debugpy-1.8.20-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:9c74df62fc064cd5e5eaca1353a3ef5a5d50da5eb8058fcef63106f7bebe6173", size = 2538066, upload-time = "2026-01-29T23:03:54.999Z" }, - { url = "https://files.pythonhosted.org/packages/c5/56/6ddca50b53624e1ca3ce1d1e49ff22db46c47ea5fb4c0cc5c9b90a616364/debugpy-1.8.20-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:077a7447589ee9bc1ff0cdf443566d0ecf540ac8aa7333b775ebcb8ce9f4ecad", size = 4269425, upload-time = "2026-01-29T23:03:56.518Z" }, - { url = "https://files.pythonhosted.org/packages/c5/d9/d64199c14a0d4c476df46c82470a3ce45c8d183a6796cfb5e66533b3663c/debugpy-1.8.20-cp314-cp314-win32.whl", hash = "sha256:352036a99dd35053b37b7803f748efc456076f929c6a895556932eaf2d23b07f", size = 5331407, upload-time = "2026-01-29T23:03:58.481Z" }, - { url = "https://files.pythonhosted.org/packages/e0/d9/1f07395b54413432624d61524dfd98c1a7c7827d2abfdb8829ac92638205/debugpy-1.8.20-cp314-cp314-win_amd64.whl", hash = "sha256:a98eec61135465b062846112e5ecf2eebb855305acc1dfbae43b72903b8ab5be", size = 5372521, upload-time = "2026-01-29T23:03:59.864Z" }, - { url = "https://files.pythonhosted.org/packages/e0/c3/7f67dea8ccf8fdcb9c99033bbe3e90b9e7395415843accb81428c441be2d/debugpy-1.8.20-py2.py3-none-any.whl", hash = "sha256:5be9bed9ae3be00665a06acaa48f8329d2b9632f15fd09f6a9a8c8d9907e54d7", size = 5337658, upload-time = "2026-01-29T23:04:17.404Z" }, -] - -[[package]] -name = "decorator" -version = "5.2.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", size = 56711, upload-time = "2025-02-24T04:41:34.073Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190, upload-time = "2025-02-24T04:41:32.565Z" }, -] - -[[package]] -name = "defusedxml" -version = "0.7.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520, upload-time = "2021-03-08T10:59:26.269Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" }, -] - -[[package]] -name = "executing" -version = "2.2.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, -] - [[package]] name = "fastexcel" -version = "0.18.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8a/bd/29c2e1689587ca5fa23f2e422e1a845cb6c3b6e19197f56d8ac8360f9889/fastexcel-0.18.0.tar.gz", hash = "sha256:00d82b787ca6dd0fae9c5d75e6c7b0a2c489236ac93e63cba70571e6d3e87568", size = 59027, upload-time = "2025-11-24T11:07:52.799Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c9/af/86df57906c473d0072785360f1951b222ba6d33b2ff1e0bea86ff6070503/fastexcel-0.18.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:6ec6e53de42519b8a080dcaf1ec8e8eca99c5e6a19d30022d168f488b1f0ec12", size = 3065735, upload-time = "2025-11-24T11:07:41.223Z" }, - { url = "https://files.pythonhosted.org/packages/81/74/ce74f5d5a7fd36e3384499fe43bb5db23cf16c98b7f95b0f3a2456361cb3/fastexcel-0.18.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:b7fadce17c6649819709bd06f5acb66bae3ce38112237d80b4816ab791693b73", size = 2857635, upload-time = "2025-11-24T11:07:43.6Z" }, - { url = "https://files.pythonhosted.org/packages/1c/05/68f6145b7230a4e75b8c08a592ce4dcac88567420967aca190b7feee73e3/fastexcel-0.18.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f8edb3e38aa458a110dffd3fb6aabb64ef8e10b8c5cede2d2346e5c04e5e1ef", size = 3185991, upload-time = "2025-11-24T11:07:33.102Z" }, - { url = "https://files.pythonhosted.org/packages/81/c5/d2833ce05892e78979450c0a439a0298bddbb5613244d5d43406341cc217/fastexcel-0.18.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eaebd921d4d89d02293e94739d92965f58873433e77a44a187ed1947769592c", size = 3359228, upload-time = "2025-11-24T11:07:35.07Z" }, - { url = "https://files.pythonhosted.org/packages/d8/71/61572e6c59029a1edfe99ec05722cb1fcdf4825adc49c5c9308fa7e83c24/fastexcel-0.18.0-cp310-abi3-win_amd64.whl", hash = "sha256:259d29c1f40828e4665d64762232dd6680fec2344192ea850ba9fe4f4fddd6de", size = 2890696, upload-time = "2025-11-24T11:07:49.238Z" }, - { url = "https://files.pythonhosted.org/packages/26/f7/30bfe0a608bb26606b76db3ce9493501f2d3d5b0efc29de75175b9b847ca/fastexcel-0.18.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:cb9be21a5b5e28cd77081f37e0a972833c8fb8f1b646986b56f893313672df0a", size = 3057524, upload-time = "2025-11-24T11:07:45.607Z" }, - { url = "https://files.pythonhosted.org/packages/df/1f/e4e91eed5cc9ee7327176483204bf16611884315c11bca273f9e3fecf503/fastexcel-0.18.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:102dfe32348519be7e8055f010f6fad1857201f768d94e418c563c6fde439410", size = 2847009, upload-time = "2025-11-24T11:07:47.352Z" }, - { url = "https://files.pythonhosted.org/packages/c9/c7/8fab170bf0fe48d0179e2bcbbdc797c8f577d7edbb7858fc23483cec2620/fastexcel-0.18.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cf22c4753c9895fe273835e160b52e64edaef89d84585a90f8b82ef1e9adc6a", size = 3185911, upload-time = "2025-11-24T11:07:36.879Z" }, - { url = "https://files.pythonhosted.org/packages/58/a6/0957473ed388e8315d18c7c6e054b37b9f278b27a70afb50f6e3684528df/fastexcel-0.18.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:178cf27b44a8b16be23dc165081c144463322a91b6b4043e60d6cc1b9415233b", size = 3354475, upload-time = "2025-11-24T11:07:39.095Z" }, - { url = "https://files.pythonhosted.org/packages/6f/ff/7c1f5af4b3339910f11a9b621b72e1345b8016c6dff99737e9df1388e911/fastexcel-0.18.0-cp314-cp314t-win_amd64.whl", hash = "sha256:79bb347d1ea573f6ed7de01cec0a3fc850ddaade0096f9500a07692b32541af4", size = 2890781, upload-time = "2025-11-24T11:07:51.133Z" }, -] - -[[package]] -name = "fastjsonschema" -version = "2.21.2" +version = "0.19.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/20/b5/23b216d9d985a956623b6bd12d4086b60f0059b27799f23016af04a74ea1/fastjsonschema-2.21.2.tar.gz", hash = "sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de", size = 374130, upload-time = "2025-08-14T18:49:36.666Z" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/c8/3b09911348e9c64dbf41096d3e8f0e93c141a23990ec9f32514111bd5f55/fastexcel-0.19.0.tar.gz", hash = "sha256:216c3719ee90963bd93a0bf8c10b177233046ac975b67651152fdaedd3c99aa1", size = 60323, upload-time = "2026-01-20T11:17:37.253Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl", hash = "sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463", size = 24024, upload-time = "2025-08-14T18:49:34.776Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e0/3820e93ea606549cfddb8c437141dd69f2b245e74785efc8bd7511ba909d/fastexcel-0.19.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:68601072a0b4b4277c165b68f1055f88ef7ffe7ed6f08c1eeda0f0271e3f7da0", size = 3082362, upload-time = "2026-01-20T11:17:27.157Z" }, + { url = "https://files.pythonhosted.org/packages/66/0f/b42dc09515879192919942157292912393584045fd8bad98bd92961d4c30/fastexcel-0.19.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:c8a87d94445678e7e3f46a6aa39d2afaee5b88a983ec3661143a6488d8955f44", size = 2864365, upload-time = "2026-01-20T11:17:28.786Z" }, + { url = "https://files.pythonhosted.org/packages/8e/4a/bc358b20fcff64b4c14ff7d7a0e1f797792b8b77e30ae755873c02362538/fastexcel-0.19.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e94fc1be6642555f277af792c22a9f80ec9b4d640d9690f00abb822b6d865069", size = 3186426, upload-time = "2026-01-20T11:17:19.087Z" }, + { url = "https://files.pythonhosted.org/packages/58/ae/d2ffdc5ad14190153e2422fc90a1052a4b0c3086d24cb8ae8967575321d8/fastexcel-0.19.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:334f9f40cd68b5924a712b6c104949757a0b8ad8a7e3fa3f3fad1c1ebc00258b", size = 3365628, upload-time = "2026-01-20T11:17:21.116Z" }, + { url = "https://files.pythonhosted.org/packages/6e/67/5f6d4e7760dc3dd8244cd124dabdd5bb7622bf1197edcc2513648847690e/fastexcel-0.19.0-cp310-abi3-win_amd64.whl", hash = "sha256:fbbdf9de79c3ef3572809bb187927c0dc5840968ffe513ea015a383024b7c6b0", size = 2905173, upload-time = "2026-01-20T11:17:33.687Z" }, + { url = "https://files.pythonhosted.org/packages/aa/a4/4290e356cfe028b11db8d96f8d5bca43bde8ed1fd9a491661df4d57551de/fastexcel-0.19.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:26eb85d98087b3c13e083a1fb51a3dfcd57607865fb44d8d6db451948ef65c63", size = 3069723, upload-time = "2026-01-20T11:17:30.521Z" }, + { url = "https://files.pythonhosted.org/packages/fb/1e/1364b08c1d5449236af23366ac3beaabbc63b283f354fc1aa6ad0b95cc37/fastexcel-0.19.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:42d48b077b7ec070de6ea34c99f9a0c97e45cd767fbadd135fc30fa70de24b42", size = 2852643, upload-time = "2026-01-20T11:17:32.079Z" }, + { url = "https://files.pythonhosted.org/packages/85/1b/57a5e2441ab29ecb774f642f66d5e9f9246cdc14ca4ee85ada5b081f4656/fastexcel-0.19.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3c49fac330cc306bb0bd73d96138f438441d8254eed19ca6c1800aaa9d69054", size = 3182805, upload-time = "2026-01-20T11:17:23.068Z" }, + { url = "https://files.pythonhosted.org/packages/76/50/0e5c416b990d153bad1e63b8268ea751fc8a319d134de14e3bbba38000c7/fastexcel-0.19.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75aad96c34836eca90fc6d0e061240c145795f8754424698e2aadfd634abb4cf", size = 3360260, upload-time = "2026-01-20T11:17:24.711Z" }, + { url = "https://files.pythonhosted.org/packages/48/38/b3faa12a74f387e037ff33adae761c22fc3aa44eed15a2c09d653b4eb194/fastexcel-0.19.0-cp314-cp314t-win_amd64.whl", hash = "sha256:7ef8e41cb0118f90d5f9a636fcdc0e9d635938cdaa54a3182328f3d34ce9ee1a", size = 2897686, upload-time = "2026-01-20T11:17:35.453Z" }, ] [[package]] @@ -467,7 +226,6 @@ dependencies = [ { name = "cartiflette" }, { name = "fastexcel" }, { name = "geopandas" }, - { name = "jupyter" }, { name = "matplotlib" }, { name = "numpy" }, { name = "pandas" }, @@ -477,16 +235,14 @@ dependencies = [ { name = "requests" }, { name = "scikit-learn" }, { name = "seaborn" }, - { name = "tidypolars" }, { name = "xlrd" }, ] [package.metadata] requires-dist = [ { name = "cartiflette", specifier = ">=0.1.9" }, - { name = "fastexcel", specifier = ">=0.18.0" }, + { name = "fastexcel", specifier = ">=0.19.0" }, { name = "geopandas", specifier = ">=1.1.1" }, - { name = "jupyter", specifier = ">=1.1.1" }, { name = "matplotlib" }, { name = "numpy" }, { name = "pandas" }, @@ -497,19 +253,9 @@ requires-dist = [ { name = "requests", specifier = ">=2.32.5" }, { name = "scikit-learn" }, { name = "seaborn", specifier = ">=0.13.2" }, - { name = "tidypolars", specifier = ">=0.3.2" }, { name = "xlrd", specifier = ">=2.0.2" }, ] -[[package]] -name = "fqdn" -version = "1.5.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/30/3e/a80a8c077fd798951169626cde3e239adeba7dab75deb3555716415bd9b0/fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f", size = 6015, upload-time = "2021-03-11T07:16:29.08Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014", size = 9121, upload-time = "2021-03-11T07:16:28.351Z" }, -] - [[package]] name = "geopandas" version = "1.1.1" @@ -527,43 +273,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0b/70/d5cd0696eff08e62fdbdebe5b46527facb4e7220eabe0ac6225efab50168/geopandas-1.1.1-py3-none-any.whl", hash = "sha256:589e61aaf39b19828843df16cb90234e72897e2579be236f10eee0d052ad98e8", size = 338365, upload-time = "2025-06-26T21:04:55.139Z" }, ] -[[package]] -name = "h11" -version = "0.16.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, -] - -[[package]] -name = "httpcore" -version = "1.0.9" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "certifi" }, - { name = "h11" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, -] - -[[package]] -name = "httpx" -version = "0.28.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "anyio" }, - { name = "certifi" }, - { name = "httpcore" }, - { name = "idna" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, -] - [[package]] name = "idna" version = "3.11" @@ -573,115 +282,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, ] -[[package]] -name = "ipykernel" -version = "7.2.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "appnope", marker = "sys_platform == 'darwin'" }, - { name = "comm" }, - { name = "debugpy" }, - { name = "ipython" }, - { name = "jupyter-client" }, - { name = "jupyter-core" }, - { name = "matplotlib-inline" }, - { name = "nest-asyncio" }, - { name = "packaging" }, - { name = "psutil" }, - { name = "pyzmq" }, - { name = "tornado" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ca/8d/b68b728e2d06b9e0051019640a40a9eb7a88fcd82c2e1b5ce70bef5ff044/ipykernel-7.2.0.tar.gz", hash = "sha256:18ed160b6dee2cbb16e5f3575858bc19d8f1fe6046a9a680c708494ce31d909e", size = 176046, upload-time = "2026-02-06T16:43:27.403Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl", hash = "sha256:3bbd4420d2b3cc105cbdf3756bfc04500b1e52f090a90716851f3916c62e1661", size = 118788, upload-time = "2026-02-06T16:43:25.149Z" }, -] - -[[package]] -name = "ipython" -version = "9.10.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "decorator" }, - { name = "ipython-pygments-lexers" }, - { name = "jedi" }, - { name = "matplotlib-inline" }, - { name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, - { name = "prompt-toolkit" }, - { name = "pygments" }, - { name = "stack-data" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/a6/60/2111715ea11f39b1535bed6024b7dec7918b71e5e5d30855a5b503056b50/ipython-9.10.0.tar.gz", hash = "sha256:cd9e656be97618a0676d058134cd44e6dc7012c0e5cb36a9ce96a8c904adaf77", size = 4426526, upload-time = "2026-02-02T10:00:33.594Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3d/aa/898dec789a05731cd5a9f50605b7b44a72bd198fd0d4528e11fc610177cc/ipython-9.10.0-py3-none-any.whl", hash = "sha256:c6ab68cc23bba8c7e18e9b932797014cc61ea7fd6f19de180ab9ba73e65ee58d", size = 622774, upload-time = "2026-02-02T10:00:31.503Z" }, -] - -[[package]] -name = "ipython-pygments-lexers" -version = "1.1.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pygments" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393, upload-time = "2025-01-17T11:24:34.505Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" }, -] - -[[package]] -name = "ipywidgets" -version = "8.1.8" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "comm" }, - { name = "ipython" }, - { name = "jupyterlab-widgets" }, - { name = "traitlets" }, - { name = "widgetsnbextension" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/4c/ae/c5ce1edc1afe042eadb445e95b0671b03cee61895264357956e61c0d2ac0/ipywidgets-8.1.8.tar.gz", hash = "sha256:61f969306b95f85fba6b6986b7fe45d73124d1d9e3023a8068710d47a22ea668", size = 116739, upload-time = "2025-11-01T21:18:12.393Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl", hash = "sha256:ecaca67aed704a338f88f67b1181b58f821ab5dc89c1f0f5ef99db43c1c2921e", size = 139808, upload-time = "2025-11-01T21:18:10.956Z" }, -] - -[[package]] -name = "isoduration" -version = "20.11.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "arrow" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/7c/1a/3c8edc664e06e6bd06cce40c6b22da5f1429aa4224d0c590f3be21c91ead/isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9", size = 11649, upload-time = "2020-11-01T11:00:00.312Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042", size = 11321, upload-time = "2020-11-01T10:59:58.02Z" }, -] - -[[package]] -name = "jedi" -version = "0.19.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "parso" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/72/3a/79a912fbd4d8dd6fbb02bf69afd3bb72cf0c729bb3063c6f4498603db17a/jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0", size = 1231287, upload-time = "2024-11-11T01:41:42.873Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9", size = 1572278, upload-time = "2024-11-11T01:41:40.175Z" }, -] - -[[package]] -name = "jinja2" -version = "3.1.6" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "markupsafe" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, -] - [[package]] name = "joblib" version = "1.5.3" @@ -691,262 +291,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713", size = 309071, upload-time = "2025-12-15T08:41:44.973Z" }, ] -[[package]] -name = "json5" -version = "0.13.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/77/e8/a3f261a66e4663f22700bc8a17c08cb83e91fbf086726e7a228398968981/json5-0.13.0.tar.gz", hash = "sha256:b1edf8d487721c0bf64d83c28e91280781f6e21f4a797d3261c7c828d4c165bf", size = 52441, upload-time = "2026-01-01T19:42:14.99Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d7/9e/038522f50ceb7e74f1f991bf1b699f24b0c2bbe7c390dd36ad69f4582258/json5-0.13.0-py3-none-any.whl", hash = "sha256:9a08e1dd65f6a4d4c6fa82d216cf2477349ec2346a38fd70cc11d2557499fbcc", size = 36163, upload-time = "2026-01-01T19:42:13.962Z" }, -] - -[[package]] -name = "jsonpointer" -version = "3.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6a/0a/eebeb1fa92507ea94016a2a790b93c2ae41a7e18778f85471dc54475ed25/jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef", size = 9114, upload-time = "2024-06-10T19:24:42.462Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942", size = 7595, upload-time = "2024-06-10T19:24:40.698Z" }, -] - -[[package]] -name = "jsonschema" -version = "4.26.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "attrs" }, - { name = "jsonschema-specifications" }, - { name = "referencing" }, - { name = "rpds-py" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" }, -] - -[package.optional-dependencies] -format-nongpl = [ - { name = "fqdn" }, - { name = "idna" }, - { name = "isoduration" }, - { name = "jsonpointer" }, - { name = "rfc3339-validator" }, - { name = "rfc3986-validator" }, - { name = "rfc3987-syntax" }, - { name = "uri-template" }, - { name = "webcolors" }, -] - -[[package]] -name = "jsonschema-specifications" -version = "2025.9.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "referencing" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, -] - -[[package]] -name = "jupyter" -version = "1.1.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "ipykernel" }, - { name = "ipywidgets" }, - { name = "jupyter-console" }, - { name = "jupyterlab" }, - { name = "nbconvert" }, - { name = "notebook" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/58/f3/af28ea964ab8bc1e472dba2e82627d36d470c51f5cd38c37502eeffaa25e/jupyter-1.1.1.tar.gz", hash = "sha256:d55467bceabdea49d7e3624af7e33d59c37fff53ed3a350e1ac957bed731de7a", size = 5714959, upload-time = "2024-08-30T07:15:48.299Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/38/64/285f20a31679bf547b75602702f7800e74dbabae36ef324f716c02804753/jupyter-1.1.1-py2.py3-none-any.whl", hash = "sha256:7a59533c22af65439b24bbe60373a4e95af8f16ac65a6c00820ad378e3f7cc83", size = 2657, upload-time = "2024-08-30T07:15:47.045Z" }, -] - -[[package]] -name = "jupyter-client" -version = "8.8.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jupyter-core" }, - { name = "python-dateutil" }, - { name = "pyzmq" }, - { name = "tornado" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/05/e4/ba649102a3bc3fbca54e7239fb924fd434c766f855693d86de0b1f2bec81/jupyter_client-8.8.0.tar.gz", hash = "sha256:d556811419a4f2d96c869af34e854e3f059b7cc2d6d01a9cd9c85c267691be3e", size = 348020, upload-time = "2026-01-08T13:55:47.938Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl", hash = "sha256:f93a5b99c5e23a507b773d3a1136bd6e16c67883ccdbd9a829b0bbdb98cd7d7a", size = 107371, upload-time = "2026-01-08T13:55:45.562Z" }, -] - -[[package]] -name = "jupyter-console" -version = "6.6.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "ipykernel" }, - { name = "ipython" }, - { name = "jupyter-client" }, - { name = "jupyter-core" }, - { name = "prompt-toolkit" }, - { name = "pygments" }, - { name = "pyzmq" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/bd/2d/e2fd31e2fc41c14e2bcb6c976ab732597e907523f6b2420305f9fc7fdbdb/jupyter_console-6.6.3.tar.gz", hash = "sha256:566a4bf31c87adbfadf22cdf846e3069b59a71ed5da71d6ba4d8aaad14a53539", size = 34363, upload-time = "2023-03-06T14:13:31.02Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ca/77/71d78d58f15c22db16328a476426f7ac4a60d3a5a7ba3b9627ee2f7903d4/jupyter_console-6.6.3-py3-none-any.whl", hash = "sha256:309d33409fcc92ffdad25f0bcdf9a4a9daa61b6f341177570fdac03de5352485", size = 24510, upload-time = "2023-03-06T14:13:28.229Z" }, -] - -[[package]] -name = "jupyter-core" -version = "5.9.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "platformdirs" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/02/49/9d1284d0dc65e2c757b74c6687b6d319b02f822ad039e5c512df9194d9dd/jupyter_core-5.9.1.tar.gz", hash = "sha256:4d09aaff303b9566c3ce657f580bd089ff5c91f5f89cf7d8846c3cdf465b5508", size = 89814, upload-time = "2025-10-16T19:19:18.444Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl", hash = "sha256:ebf87fdc6073d142e114c72c9e29a9d7ca03fad818c5d300ce2adc1fb0743407", size = 29032, upload-time = "2025-10-16T19:19:16.783Z" }, -] - -[[package]] -name = "jupyter-events" -version = "0.12.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jsonschema", extra = ["format-nongpl"] }, - { name = "packaging" }, - { name = "python-json-logger" }, - { name = "pyyaml" }, - { name = "referencing" }, - { name = "rfc3339-validator" }, - { name = "rfc3986-validator" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/9d/c3/306d090461e4cf3cd91eceaff84bede12a8e52cd821c2d20c9a4fd728385/jupyter_events-0.12.0.tar.gz", hash = "sha256:fc3fce98865f6784c9cd0a56a20644fc6098f21c8c33834a8d9fe383c17e554b", size = 62196, upload-time = "2025-02-03T17:23:41.485Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e2/48/577993f1f99c552f18a0428731a755e06171f9902fa118c379eb7c04ea22/jupyter_events-0.12.0-py3-none-any.whl", hash = "sha256:6464b2fa5ad10451c3d35fabc75eab39556ae1e2853ad0c0cc31b656731a97fb", size = 19430, upload-time = "2025-02-03T17:23:38.643Z" }, -] - -[[package]] -name = "jupyter-lsp" -version = "2.3.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jupyter-server" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/eb/5a/9066c9f8e94ee517133cd98dba393459a16cd48bba71a82f16a65415206c/jupyter_lsp-2.3.0.tar.gz", hash = "sha256:458aa59339dc868fb784d73364f17dbce8836e906cd75fd471a325cba02e0245", size = 54823, upload-time = "2025-08-27T17:47:34.671Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1a/60/1f6cee0c46263de1173894f0fafcb3475ded276c472c14d25e0280c18d6d/jupyter_lsp-2.3.0-py3-none-any.whl", hash = "sha256:e914a3cb2addf48b1c7710914771aaf1819d46b2e5a79b0f917b5478ec93f34f", size = 76687, upload-time = "2025-08-27T17:47:33.15Z" }, -] - -[[package]] -name = "jupyter-server" -version = "2.17.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "anyio" }, - { name = "argon2-cffi" }, - { name = "jinja2" }, - { name = "jupyter-client" }, - { name = "jupyter-core" }, - { name = "jupyter-events" }, - { name = "jupyter-server-terminals" }, - { name = "nbconvert" }, - { name = "nbformat" }, - { name = "packaging" }, - { name = "prometheus-client" }, - { name = "pywinpty", marker = "os_name == 'nt'" }, - { name = "pyzmq" }, - { name = "send2trash" }, - { name = "terminado" }, - { name = "tornado" }, - { name = "traitlets" }, - { name = "websocket-client" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/5b/ac/e040ec363d7b6b1f11304cc9f209dac4517ece5d5e01821366b924a64a50/jupyter_server-2.17.0.tar.gz", hash = "sha256:c38ea898566964c888b4772ae1ed58eca84592e88251d2cfc4d171f81f7e99d5", size = 731949, upload-time = "2025-08-21T14:42:54.042Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/92/80/a24767e6ca280f5a49525d987bf3e4d7552bf67c8be07e8ccf20271f8568/jupyter_server-2.17.0-py3-none-any.whl", hash = "sha256:e8cb9c7db4251f51ed307e329b81b72ccf2056ff82d50524debde1ee1870e13f", size = 388221, upload-time = "2025-08-21T14:42:52.034Z" }, -] - -[[package]] -name = "jupyter-server-terminals" -version = "0.5.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pywinpty", marker = "os_name == 'nt'" }, - { name = "terminado" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f4/a7/bcd0a9b0cbba88986fe944aaaf91bfda603e5a50bda8ed15123f381a3b2f/jupyter_server_terminals-0.5.4.tar.gz", hash = "sha256:bbda128ed41d0be9020349f9f1f2a4ab9952a73ed5f5ac9f1419794761fb87f5", size = 31770, upload-time = "2026-01-14T16:53:20.213Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl", hash = "sha256:55be353fc74a80bc7f3b20e6be50a55a61cd525626f578dcb66a5708e2007d14", size = 13704, upload-time = "2026-01-14T16:53:18.738Z" }, -] - -[[package]] -name = "jupyterlab" -version = "4.5.5" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "async-lru" }, - { name = "httpx" }, - { name = "ipykernel" }, - { name = "jinja2" }, - { name = "jupyter-core" }, - { name = "jupyter-lsp" }, - { name = "jupyter-server" }, - { name = "jupyterlab-server" }, - { name = "notebook-shim" }, - { name = "packaging" }, - { name = "setuptools" }, - { name = "tornado" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/6e/2d/953a5612a34a3c799a62566a548e711d103f631672fd49650e0f2de80870/jupyterlab-4.5.5.tar.gz", hash = "sha256:eac620698c59eb810e1729909be418d9373d18137cac66637141abba613b3fda", size = 23968441, upload-time = "2026-02-23T18:57:34.339Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b9/52/372d3494766d690dfdd286871bf5f7fb9a6c61f7566ccaa7153a163dd1df/jupyterlab-4.5.5-py3-none-any.whl", hash = "sha256:a35694a40a8e7f2e82f387472af24e61b22adcce87b5a8ab97a5d9c486202a6d", size = 12446824, upload-time = "2026-02-23T18:57:30.398Z" }, -] - -[[package]] -name = "jupyterlab-pygments" -version = "0.3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/90/51/9187be60d989df97f5f0aba133fa54e7300f17616e065d1ada7d7646b6d6/jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d", size = 512900, upload-time = "2023-11-23T09:26:37.44Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780", size = 15884, upload-time = "2023-11-23T09:26:34.325Z" }, -] - -[[package]] -name = "jupyterlab-server" -version = "2.28.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "babel" }, - { name = "jinja2" }, - { name = "json5" }, - { name = "jsonschema" }, - { name = "jupyter-server" }, - { name = "packaging" }, - { name = "requests" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/d6/2c/90153f189e421e93c4bb4f9e3f59802a1f01abd2ac5cf40b152d7f735232/jupyterlab_server-2.28.0.tar.gz", hash = "sha256:35baa81898b15f93573e2deca50d11ac0ae407ebb688299d3a5213265033712c", size = 76996, upload-time = "2025-10-22T13:59:18.37Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl", hash = "sha256:e4355b148fdcf34d312bbbc80f22467d6d20460e8b8736bf235577dd18506968", size = 59830, upload-time = "2025-10-22T13:59:16.767Z" }, -] - -[[package]] -name = "jupyterlab-widgets" -version = "3.0.16" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/26/2d/ef58fed122b268c69c0aa099da20bc67657cdfb2e222688d5731bd5b971d/jupyterlab_widgets-3.0.16.tar.gz", hash = "sha256:423da05071d55cf27a9e602216d35a3a65a3e41cdf9c5d3b643b814ce38c19e0", size = 897423, upload-time = "2025-11-01T21:11:29.724Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl", hash = "sha256:45fa36d9c6422cf2559198e4db481aa243c7a32d9926b500781c830c80f7ecf8", size = 914926, upload-time = "2025-11-01T21:11:28.008Z" }, -] - [[package]] name = "kiwisolver" version = "1.4.9" @@ -996,75 +340,14 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8c/ae/29ffcbd239aea8b93108de1278271ae764dfc0d803a5693914975f200596/kiwisolver-1.4.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e2ea9f7ab7fbf18fffb1b5434ce7c69a07582f7acc7717720f1d69f3e806f90c", size = 66399, upload-time = "2025-08-10T21:27:21.496Z" }, { url = "https://files.pythonhosted.org/packages/a1/ae/d7ba902aa604152c2ceba5d352d7b62106bedbccc8e95c3934d94472bfa3/kiwisolver-1.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b34e51affded8faee0dfdb705416153819d8ea9250bbbf7ea1b249bdeb5f1122", size = 1582197, upload-time = "2025-08-10T21:27:22.604Z" }, { url = "https://files.pythonhosted.org/packages/f2/41/27c70d427eddb8bc7e4f16420a20fefc6f480312122a59a959fdfe0445ad/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8aacd3d4b33b772542b2e01beb50187536967b514b00003bdda7589722d2a64", size = 1390125, upload-time = "2025-08-10T21:27:24.036Z" }, - { url = "https://files.pythonhosted.org/packages/41/42/b3799a12bafc76d962ad69083f8b43b12bf4fe78b097b12e105d75c9b8f1/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7cf974dd4e35fa315563ac99d6287a1024e4dc2077b8a7d7cd3d2fb65d283134", size = 1402612, upload-time = "2025-08-10T21:27:25.773Z" }, - { url = "https://files.pythonhosted.org/packages/d2/b5/a210ea073ea1cfaca1bb5c55a62307d8252f531beb364e18aa1e0888b5a0/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:85bd218b5ecfbee8c8a82e121802dcb519a86044c9c3b2e4aef02fa05c6da370", size = 1453990, upload-time = "2025-08-10T21:27:27.089Z" }, - { url = "https://files.pythonhosted.org/packages/5f/ce/a829eb8c033e977d7ea03ed32fb3c1781b4fa0433fbadfff29e39c676f32/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0856e241c2d3df4efef7c04a1e46b1936b6120c9bcf36dd216e3acd84bc4fb21", size = 2331601, upload-time = "2025-08-10T21:27:29.343Z" }, - { url = "https://files.pythonhosted.org/packages/e0/4b/b5e97eb142eb9cd0072dacfcdcd31b1c66dc7352b0f7c7255d339c0edf00/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9af39d6551f97d31a4deebeac6f45b156f9755ddc59c07b402c148f5dbb6482a", size = 2422041, upload-time = "2025-08-10T21:27:30.754Z" }, - { url = "https://files.pythonhosted.org/packages/40/be/8eb4cd53e1b85ba4edc3a9321666f12b83113a178845593307a3e7891f44/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:bb4ae2b57fc1d8cbd1cf7b1d9913803681ffa903e7488012be5b76dedf49297f", size = 2594897, upload-time = "2025-08-10T21:27:32.803Z" }, - { url = "https://files.pythonhosted.org/packages/99/dd/841e9a66c4715477ea0abc78da039832fbb09dac5c35c58dc4c41a407b8a/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:aedff62918805fb62d43a4aa2ecd4482c380dc76cd31bd7c8878588a61bd0369", size = 2391835, upload-time = "2025-08-10T21:27:34.23Z" }, - { url = "https://files.pythonhosted.org/packages/0c/28/4b2e5c47a0da96896fdfdb006340ade064afa1e63675d01ea5ac222b6d52/kiwisolver-1.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:1fa333e8b2ce4d9660f2cda9c0e1b6bafcfb2457a9d259faa82289e73ec24891", size = 79988, upload-time = "2025-08-10T21:27:35.587Z" }, - { url = "https://files.pythonhosted.org/packages/80/be/3578e8afd18c88cdf9cb4cffde75a96d2be38c5a903f1ed0ceec061bd09e/kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32", size = 70260, upload-time = "2025-08-10T21:27:36.606Z" }, -] - -[[package]] -name = "lark" -version = "1.3.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/da/34/28fff3ab31ccff1fd4f6c7c7b0ceb2b6968d8ea4950663eadcb5720591a0/lark-1.3.1.tar.gz", hash = "sha256:b426a7a6d6d53189d318f2b6236ab5d6429eaf09259f1ca33eb716eed10d2905", size = 382732, upload-time = "2025-10-27T18:25:56.653Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/82/3d/14ce75ef66813643812f3093ab17e46d3a206942ce7376d31ec2d36229e7/lark-1.3.1-py3-none-any.whl", hash = "sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12", size = 113151, upload-time = "2025-10-27T18:25:54.882Z" }, -] - -[[package]] -name = "markupsafe" -version = "3.0.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, - { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, - { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, - { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, - { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, - { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, - { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, - { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, - { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, - { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, - { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, - { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, - { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, - { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, - { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, - { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, - { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, - { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, - { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, - { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, - { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, - { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, - { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, - { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, - { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, - { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, - { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, - { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, - { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, - { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, - { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, - { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, - { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, - { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, - { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, - { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, - { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, - { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, - { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, - { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, - { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, - { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, - { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, - { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, + { url = "https://files.pythonhosted.org/packages/41/42/b3799a12bafc76d962ad69083f8b43b12bf4fe78b097b12e105d75c9b8f1/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7cf974dd4e35fa315563ac99d6287a1024e4dc2077b8a7d7cd3d2fb65d283134", size = 1402612, upload-time = "2025-08-10T21:27:25.773Z" }, + { url = "https://files.pythonhosted.org/packages/d2/b5/a210ea073ea1cfaca1bb5c55a62307d8252f531beb364e18aa1e0888b5a0/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:85bd218b5ecfbee8c8a82e121802dcb519a86044c9c3b2e4aef02fa05c6da370", size = 1453990, upload-time = "2025-08-10T21:27:27.089Z" }, + { url = "https://files.pythonhosted.org/packages/5f/ce/a829eb8c033e977d7ea03ed32fb3c1781b4fa0433fbadfff29e39c676f32/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0856e241c2d3df4efef7c04a1e46b1936b6120c9bcf36dd216e3acd84bc4fb21", size = 2331601, upload-time = "2025-08-10T21:27:29.343Z" }, + { url = "https://files.pythonhosted.org/packages/e0/4b/b5e97eb142eb9cd0072dacfcdcd31b1c66dc7352b0f7c7255d339c0edf00/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9af39d6551f97d31a4deebeac6f45b156f9755ddc59c07b402c148f5dbb6482a", size = 2422041, upload-time = "2025-08-10T21:27:30.754Z" }, + { url = "https://files.pythonhosted.org/packages/40/be/8eb4cd53e1b85ba4edc3a9321666f12b83113a178845593307a3e7891f44/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:bb4ae2b57fc1d8cbd1cf7b1d9913803681ffa903e7488012be5b76dedf49297f", size = 2594897, upload-time = "2025-08-10T21:27:32.803Z" }, + { url = "https://files.pythonhosted.org/packages/99/dd/841e9a66c4715477ea0abc78da039832fbb09dac5c35c58dc4c41a407b8a/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:aedff62918805fb62d43a4aa2ecd4482c380dc76cd31bd7c8878588a61bd0369", size = 2391835, upload-time = "2025-08-10T21:27:34.23Z" }, + { url = "https://files.pythonhosted.org/packages/0c/28/4b2e5c47a0da96896fdfdb006340ade064afa1e63675d01ea5ac222b6d52/kiwisolver-1.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:1fa333e8b2ce4d9660f2cda9c0e1b6bafcfb2457a9d259faa82289e73ec24891", size = 79988, upload-time = "2025-08-10T21:27:35.587Z" }, + { url = "https://files.pythonhosted.org/packages/80/be/3578e8afd18c88cdf9cb4cffde75a96d2be38c5a903f1ed0ceec061bd09e/kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32", size = 70260, upload-time = "2025-08-10T21:27:36.606Z" }, ] [[package]] @@ -1114,27 +397,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5d/49/d651878698a0b67f23aa28e17f45a6d6dd3d3f933fa29087fa4ce5947b5a/matplotlib-3.10.8-cp314-cp314t-win_arm64.whl", hash = "sha256:113bb52413ea508ce954a02c10ffd0d565f9c3bc7f2eddc27dfe1731e71c7b5f", size = 8192560, upload-time = "2025-12-10T22:56:38.008Z" }, ] -[[package]] -name = "matplotlib-inline" -version = "0.2.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c7/74/97e72a36efd4ae2bccb3463284300f8953f199b5ffbc04cbbb0ec78f74b1/matplotlib_inline-0.2.1.tar.gz", hash = "sha256:e1ee949c340d771fc39e241ea75683deb94762c8fa5f2927ec57c83c4dffa9fe", size = 8110, upload-time = "2025-10-23T09:00:22.126Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76", size = 9516, upload-time = "2025-10-23T09:00:20.675Z" }, -] - -[[package]] -name = "mistune" -version = "3.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9d/55/d01f0c4b45ade6536c51170b9043db8b2ec6ddf4a35c7ea3f5f559ac935b/mistune-3.2.0.tar.gz", hash = "sha256:708487c8a8cdd99c9d90eb3ed4c3ed961246ff78ac82f03418f5183ab70e398a", size = 95467, upload-time = "2025-12-23T11:36:34.994Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl", hash = "sha256:febdc629a3c78616b94393c6580551e0e34cc289987ec6c35ed3f4be42d0eee1", size = 53598, upload-time = "2025-12-23T11:36:33.211Z" }, -] - [[package]] name = "mizani" version = "0.14.3" @@ -1150,98 +412,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5c/d2/4ffcaa27c8a4b4f9ad456da4821c76dfbdfada23e8210cd4d80e1eb3236a/mizani-0.14.3-py3-none-any.whl", hash = "sha256:6d2ca9b1b8366ff85668f0cc1b6095f1e702e26e66f132c4f02a949efa32a688", size = 133433, upload-time = "2025-10-30T20:16:51.218Z" }, ] -[[package]] -name = "nbclient" -version = "0.10.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jupyter-client" }, - { name = "jupyter-core" }, - { name = "nbformat" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/56/91/1c1d5a4b9a9ebba2b4e32b8c852c2975c872aec1fe42ab5e516b2cecd193/nbclient-0.10.4.tar.gz", hash = "sha256:1e54091b16e6da39e297b0ece3e10f6f29f4ac4e8ee515d29f8a7099bd6553c9", size = 62554, upload-time = "2025-12-23T07:45:46.369Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl", hash = "sha256:9162df5a7373d70d606527300a95a975a47c137776cd942e52d9c7e29ff83440", size = 25465, upload-time = "2025-12-23T07:45:44.51Z" }, -] - -[[package]] -name = "nbconvert" -version = "7.17.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "beautifulsoup4" }, - { name = "bleach", extra = ["css"] }, - { name = "defusedxml" }, - { name = "jinja2" }, - { name = "jupyter-core" }, - { name = "jupyterlab-pygments" }, - { name = "markupsafe" }, - { name = "mistune" }, - { name = "nbclient" }, - { name = "nbformat" }, - { name = "packaging" }, - { name = "pandocfilters" }, - { name = "pygments" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/38/47/81f886b699450d0569f7bc551df2b1673d18df7ff25cc0c21ca36ed8a5ff/nbconvert-7.17.0.tar.gz", hash = "sha256:1b2696f1b5be12309f6c7d707c24af604b87dfaf6d950794c7b07acab96dda78", size = 862855, upload-time = "2026-01-29T16:37:48.478Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/4b/8d5f796a792f8a25f6925a96032f098789f448571eb92011df1ae59e8ea8/nbconvert-7.17.0-py3-none-any.whl", hash = "sha256:4f99a63b337b9a23504347afdab24a11faa7d86b405e5c8f9881cd313336d518", size = 261510, upload-time = "2026-01-29T16:37:46.322Z" }, -] - -[[package]] -name = "nbformat" -version = "5.10.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "fastjsonschema" }, - { name = "jsonschema" }, - { name = "jupyter-core" }, - { name = "traitlets" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/6d/fd/91545e604bc3dad7dca9ed03284086039b294c6b3d75c0d2fa45f9e9caf3/nbformat-5.10.4.tar.gz", hash = "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a", size = 142749, upload-time = "2024-04-04T11:20:37.371Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b", size = 78454, upload-time = "2024-04-04T11:20:34.895Z" }, -] - -[[package]] -name = "nest-asyncio" -version = "1.6.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/83/f8/51569ac65d696c8ecbee95938f89d4abf00f47d58d48f6fbabfe8f0baefe/nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", size = 7418, upload-time = "2024-01-21T14:25:19.227Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195, upload-time = "2024-01-21T14:25:17.223Z" }, -] - -[[package]] -name = "notebook" -version = "7.5.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jupyter-server" }, - { name = "jupyterlab" }, - { name = "jupyterlab-server" }, - { name = "notebook-shim" }, - { name = "tornado" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/78/08/9d446fbb49f95de316ea6d7f25d0a4bc95117dd574e35f405895ac706f29/notebook-7.5.4.tar.gz", hash = "sha256:b928b2ba22cb63aa83df2e0e76fe3697950a0c1c4a41b84ebccf1972b1bb5771", size = 14167892, upload-time = "2026-02-24T14:13:56.116Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/59/01/05e5387b53e0f549212d5eff58845886f3827617b5c9409c966ddc07cb6d/notebook-7.5.4-py3-none-any.whl", hash = "sha256:860e31782b3d3a25ca0819ff039f5cf77845d1bf30c78ef9528b88b25e0a9850", size = 14578014, upload-time = "2026-02-24T14:13:52.274Z" }, -] - -[[package]] -name = "notebook-shim" -version = "0.2.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jupyter-server" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/54/d2/92fa3243712b9a3e8bafaf60aac366da1cada3639ca767ff4b5b3654ec28/notebook_shim-0.2.4.tar.gz", hash = "sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb", size = 13167, upload-time = "2024-02-14T23:35:18.353Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f9/33/bd5b9137445ea4b680023eb0469b2bb969d61303dedb2aac6560ff3d14a1/notebook_shim-0.2.4-py3-none-any.whl", hash = "sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef", size = 13307, upload-time = "2024-02-14T23:35:16.286Z" }, -] - [[package]] name = "numpy" version = "2.3.5" @@ -1343,24 +513,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/70/44/5191d2e4026f86a2a109053e194d3ba7a31a2d10a9c2348368c63ed4e85a/pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87", size = 13202175, upload-time = "2025-09-29T23:31:59.173Z" }, ] -[[package]] -name = "pandocfilters" -version = "1.5.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/70/6f/3dd4940bbe001c06a65f88e36bad298bc7a0de5036115639926b0c5c0458/pandocfilters-1.5.1.tar.gz", hash = "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e", size = 8454, upload-time = "2024-01-18T20:08:13.726Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ef/af/4fbc8cab944db5d21b7e2a5b8e9211a03a79852b1157e2c102fcc61ac440/pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc", size = 8663, upload-time = "2024-01-18T20:08:11.28Z" }, -] - -[[package]] -name = "parso" -version = "0.8.6" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/81/76/a1e769043c0c0c9fe391b702539d594731a4362334cdf4dc25d0c09761e7/parso-0.8.6.tar.gz", hash = "sha256:2b9a0332696df97d454fa67b81618fd69c35a7b90327cbe6ba5c92d2c68a7bfd", size = 401621, upload-time = "2026-02-09T15:45:24.425Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b6/61/fae042894f4296ec49e3f193aff5d7c18440da9e48102c3315e1bc4519a7/parso-0.8.6-py2.py3-none-any.whl", hash = "sha256:2c549f800b70a5c4952197248825584cb00f033b29c692671d3bf08bf380baff", size = 106894, upload-time = "2026-02-09T15:45:21.391Z" }, -] - [[package]] name = "patsy" version = "1.0.2" @@ -1373,18 +525,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl", hash = "sha256:37bfddbc58fcf0362febb5f54f10743f8b21dd2aa73dec7e7ef59d1b02ae668a", size = 233301, upload-time = "2025-10-20T16:17:36.563Z" }, ] -[[package]] -name = "pexpect" -version = "4.9.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "ptyprocess" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" }, -] - [[package]] name = "pillow" version = "12.0.0" @@ -1495,73 +635,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d8/a12e6aa14f63784cead437083319ec7cece0d5bb9a5bfe7678cc6578b52a/polars_runtime_32-1.36.1-cp39-abi3-win_arm64.whl", hash = "sha256:809e73857be71250141225ddd5d2b30c97e6340aeaa0d445f930e01bef6888dc", size = 39798896, upload-time = "2025-12-10T01:14:11.568Z" }, ] -[[package]] -name = "prometheus-client" -version = "0.24.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f0/58/a794d23feb6b00fc0c72787d7e87d872a6730dd9ed7c7b3e954637d8f280/prometheus_client-0.24.1.tar.gz", hash = "sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9", size = 85616, upload-time = "2026-01-14T15:26:26.965Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl", hash = "sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055", size = 64057, upload-time = "2026-01-14T15:26:24.42Z" }, -] - -[[package]] -name = "prompt-toolkit" -version = "3.0.52" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "wcwidth" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, -] - -[[package]] -name = "psutil" -version = "7.2.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/aa/c6/d1ddf4abb55e93cebc4f2ed8b5d6dbad109ecb8d63748dd2b20ab5e57ebe/psutil-7.2.2.tar.gz", hash = "sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372", size = 493740, upload-time = "2026-01-28T18:14:54.428Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/51/08/510cbdb69c25a96f4ae523f733cdc963ae654904e8db864c07585ef99875/psutil-7.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2edccc433cbfa046b980b0df0171cd25bcaeb3a68fe9022db0979e7aa74a826b", size = 130595, upload-time = "2026-01-28T18:14:57.293Z" }, - { url = "https://files.pythonhosted.org/packages/d6/f5/97baea3fe7a5a9af7436301f85490905379b1c6f2dd51fe3ecf24b4c5fbf/psutil-7.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78c8603dcd9a04c7364f1a3e670cea95d51ee865e4efb3556a3a63adef958ea", size = 131082, upload-time = "2026-01-28T18:14:59.732Z" }, - { url = "https://files.pythonhosted.org/packages/37/d6/246513fbf9fa174af531f28412297dd05241d97a75911ac8febefa1a53c6/psutil-7.2.2-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a571f2330c966c62aeda00dd24620425d4b0cc86881c89861fbc04549e5dc63", size = 181476, upload-time = "2026-01-28T18:15:01.884Z" }, - { url = "https://files.pythonhosted.org/packages/b8/b5/9182c9af3836cca61696dabe4fd1304e17bc56cb62f17439e1154f225dd3/psutil-7.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:917e891983ca3c1887b4ef36447b1e0873e70c933afc831c6b6da078ba474312", size = 184062, upload-time = "2026-01-28T18:15:04.436Z" }, - { url = "https://files.pythonhosted.org/packages/16/ba/0756dca669f5a9300d0cbcbfae9a4c30e446dfc7440ffe43ded5724bfd93/psutil-7.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:ab486563df44c17f5173621c7b198955bd6b613fb87c71c161f827d3fb149a9b", size = 139893, upload-time = "2026-01-28T18:15:06.378Z" }, - { url = "https://files.pythonhosted.org/packages/1c/61/8fa0e26f33623b49949346de05ec1ddaad02ed8ba64af45f40a147dbfa97/psutil-7.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:ae0aefdd8796a7737eccea863f80f81e468a1e4cf14d926bd9b6f5f2d5f90ca9", size = 135589, upload-time = "2026-01-28T18:15:08.03Z" }, - { url = "https://files.pythonhosted.org/packages/81/69/ef179ab5ca24f32acc1dac0c247fd6a13b501fd5534dbae0e05a1c48b66d/psutil-7.2.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00", size = 130664, upload-time = "2026-01-28T18:15:09.469Z" }, - { url = "https://files.pythonhosted.org/packages/7b/64/665248b557a236d3fa9efc378d60d95ef56dd0a490c2cd37dafc7660d4a9/psutil-7.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7b6d09433a10592ce39b13d7be5a54fbac1d1228ed29abc880fb23df7cb694c9", size = 131087, upload-time = "2026-01-28T18:15:11.724Z" }, - { url = "https://files.pythonhosted.org/packages/d5/2e/e6782744700d6759ebce3043dcfa661fb61e2fb752b91cdeae9af12c2178/psutil-7.2.2-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fa4ecf83bcdf6e6c8f4449aff98eefb5d0604bf88cb883d7da3d8d2d909546a", size = 182383, upload-time = "2026-01-28T18:15:13.445Z" }, - { url = "https://files.pythonhosted.org/packages/57/49/0a41cefd10cb7505cdc04dab3eacf24c0c2cb158a998b8c7b1d27ee2c1f5/psutil-7.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e452c464a02e7dc7822a05d25db4cde564444a67e58539a00f929c51eddda0cf", size = 185210, upload-time = "2026-01-28T18:15:16.002Z" }, - { url = "https://files.pythonhosted.org/packages/dd/2c/ff9bfb544f283ba5f83ba725a3c5fec6d6b10b8f27ac1dc641c473dc390d/psutil-7.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c7663d4e37f13e884d13994247449e9f8f574bc4655d509c3b95e9ec9e2b9dc1", size = 141228, upload-time = "2026-01-28T18:15:18.385Z" }, - { url = "https://files.pythonhosted.org/packages/f2/fc/f8d9c31db14fcec13748d373e668bc3bed94d9077dbc17fb0eebc073233c/psutil-7.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:11fe5a4f613759764e79c65cf11ebdf26e33d6dd34336f8a337aa2996d71c841", size = 136284, upload-time = "2026-01-28T18:15:19.912Z" }, - { url = "https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486", size = 129090, upload-time = "2026-01-28T18:15:22.168Z" }, - { url = "https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979", size = 129859, upload-time = "2026-01-28T18:15:23.795Z" }, - { url = "https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9", size = 155560, upload-time = "2026-01-28T18:15:25.976Z" }, - { url = "https://files.pythonhosted.org/packages/63/65/37648c0c158dc222aba51c089eb3bdfa238e621674dc42d48706e639204f/psutil-7.2.2-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b0726cecd84f9474419d67252add4ac0cd9811b04d61123054b9fb6f57df6e9e", size = 156997, upload-time = "2026-01-28T18:15:27.794Z" }, - { url = "https://files.pythonhosted.org/packages/8e/13/125093eadae863ce03c6ffdbae9929430d116a246ef69866dad94da3bfbc/psutil-7.2.2-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8", size = 148972, upload-time = "2026-01-28T18:15:29.342Z" }, - { url = "https://files.pythonhosted.org/packages/04/78/0acd37ca84ce3ddffaa92ef0f571e073faa6d8ff1f0559ab1272188ea2be/psutil-7.2.2-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b58fabe35e80b264a4e3bb23e6b96f9e45a3df7fb7eed419ac0e5947c61e47cc", size = 148266, upload-time = "2026-01-28T18:15:31.597Z" }, - { url = "https://files.pythonhosted.org/packages/b4/90/e2159492b5426be0c1fef7acba807a03511f97c5f86b3caeda6ad92351a7/psutil-7.2.2-cp37-abi3-win_amd64.whl", hash = "sha256:eb7e81434c8d223ec4a219b5fc1c47d0417b12be7ea866e24fb5ad6e84b3d988", size = 137737, upload-time = "2026-01-28T18:15:33.849Z" }, - { url = "https://files.pythonhosted.org/packages/8c/c7/7bb2e321574b10df20cbde462a94e2b71d05f9bbda251ef27d104668306a/psutil-7.2.2-cp37-abi3-win_arm64.whl", hash = "sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee", size = 134617, upload-time = "2026-01-28T18:15:36.514Z" }, -] - -[[package]] -name = "ptyprocess" -version = "0.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762, upload-time = "2020-12-28T15:15:30.155Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993, upload-time = "2020-12-28T15:15:28.35Z" }, -] - -[[package]] -name = "pure-eval" -version = "0.2.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752, upload-time = "2024-07-21T12:58:21.801Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" }, -] - [[package]] name = "pyarrow" version = "23.0.1" @@ -1598,24 +671,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/50/f2/c0e76a0b451ffdf0cf788932e182758eb7558953f4f27f1aff8e2518b653/pyarrow-23.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:527e8d899f14bd15b740cd5a54ad56b7f98044955373a17179d5956ddb93d9ce", size = 28365807, upload-time = "2026-02-16T10:14:03.892Z" }, ] -[[package]] -name = "pycparser" -version = "3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, -] - -[[package]] -name = "pygments" -version = "2.19.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, -] - [[package]] name = "pyogrio" version = "0.12.1" @@ -1721,15 +776,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, ] -[[package]] -name = "python-json-logger" -version = "4.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/29/bf/eca6a3d43db1dae7070f70e160ab20b807627ba953663ba07928cdd3dc58/python_json_logger-4.0.0.tar.gz", hash = "sha256:f58e68eb46e1faed27e0f574a55a0455eecd7b8a5b88b85a784519ba3cff047f", size = 17683, upload-time = "2025-10-06T04:15:18.984Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl", hash = "sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2", size = 15548, upload-time = "2025-10-06T04:15:17.553Z" }, -] - [[package]] name = "pytz" version = "2025.2" @@ -1739,114 +785,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" }, ] -[[package]] -name = "pywinpty" -version = "3.0.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f7/54/37c7370ba91f579235049dc26cd2c5e657d2a943e01820844ffc81f32176/pywinpty-3.0.3.tar.gz", hash = "sha256:523441dc34d231fb361b4b00f8c99d3f16de02f5005fd544a0183112bcc22412", size = 31309, upload-time = "2026-02-04T21:51:09.524Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e5/cb/58d6ed3fd429c96a90ef01ac9a617af10a6d41469219c25e7dc162abbb71/pywinpty-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9c91dbb026050c77bdcef964e63a4f10f01a639113c4d3658332614544c467ab", size = 2112686, upload-time = "2026-02-04T21:52:03.035Z" }, - { url = "https://files.pythonhosted.org/packages/fd/50/724ed5c38c504d4e58a88a072776a1e880d970789deaeb2b9f7bd9a5141a/pywinpty-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:fe1f7911805127c94cf51f89ab14096c6f91ffdcacf993d2da6082b2142a2523", size = 234591, upload-time = "2026-02-04T21:52:29.821Z" }, - { url = "https://files.pythonhosted.org/packages/f7/ad/90a110538696b12b39fd8758a06d70ded899308198ad2305ac68e361126e/pywinpty-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:3f07a6cf1c1d470d284e614733c3d0f726d2c85e78508ea10a403140c3c0c18a", size = 2112360, upload-time = "2026-02-04T21:55:33.397Z" }, - { url = "https://files.pythonhosted.org/packages/44/0f/7ffa221757a220402bc79fda44044c3f2cc57338d878ab7d622add6f4581/pywinpty-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:15c7c0b6f8e9d87aabbaff76468dabf6e6121332c40fc1d83548d02a9d6a3759", size = 233107, upload-time = "2026-02-04T21:51:45.455Z" }, - { url = "https://files.pythonhosted.org/packages/28/88/2ff917caff61e55f38bcdb27de06ee30597881b2cae44fbba7627be015c4/pywinpty-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:d4b6b7b0fe0cdcd02e956bd57cfe9f4e5a06514eecf3b5ae174da4f951b58be9", size = 2113282, upload-time = "2026-02-04T21:52:08.188Z" }, - { url = "https://files.pythonhosted.org/packages/63/32/40a775343ace542cc43ece3f1d1fce454021521ecac41c4c4573081c2336/pywinpty-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:34789d685fc0d547ce0c8a65e5a70e56f77d732fa6e03c8f74fefb8cbb252019", size = 234207, upload-time = "2026-02-04T21:51:58.687Z" }, - { url = "https://files.pythonhosted.org/packages/8d/54/5d5e52f4cb75028104ca6faf36c10f9692389b1986d34471663b4ebebd6d/pywinpty-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:0c37e224a47a971d1a6e08649a1714dac4f63c11920780977829ed5c8cadead1", size = 2112910, upload-time = "2026-02-04T21:52:30.976Z" }, - { url = "https://files.pythonhosted.org/packages/0a/44/dcd184824e21d4620b06c7db9fbb15c3ad0a0f1fa2e6de79969fb82647ec/pywinpty-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:c4e9c3dff7d86ba81937438d5819f19f385a39d8f592d4e8af67148ceb4f6ab5", size = 233425, upload-time = "2026-02-04T21:51:56.754Z" }, -] - -[[package]] -name = "pyyaml" -version = "6.0.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, - { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, - { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, - { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, - { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, - { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, - { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, - { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, - { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, - { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, - { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, - { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, - { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, - { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, - { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, - { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, - { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, - { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, - { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, - { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, - { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, - { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, - { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, - { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, - { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, - { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, - { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, - { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, -] - -[[package]] -name = "pyzmq" -version = "27.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cffi", marker = "implementation_name == 'pypy'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/04/0b/3c9baedbdf613ecaa7aa07027780b8867f57b6293b6ee50de316c9f3222b/pyzmq-27.1.0.tar.gz", hash = "sha256:ac0765e3d44455adb6ddbf4417dcce460fc40a05978c08efdf2948072f6db540", size = 281750, upload-time = "2025-09-08T23:10:18.157Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:452631b640340c928fa343801b0d07eb0c3789a5ffa843f6e1a9cee0ba4eb4fc", size = 1306279, upload-time = "2025-09-08T23:08:03.807Z" }, - { url = "https://files.pythonhosted.org/packages/e8/5e/c3c49fdd0f535ef45eefcc16934648e9e59dace4a37ee88fc53f6cd8e641/pyzmq-27.1.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1c179799b118e554b66da67d88ed66cd37a169f1f23b5d9f0a231b4e8d44a113", size = 895645, upload-time = "2025-09-08T23:08:05.301Z" }, - { url = "https://files.pythonhosted.org/packages/f8/e5/b0b2504cb4e903a74dcf1ebae157f9e20ebb6ea76095f6cfffea28c42ecd/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3837439b7f99e60312f0c926a6ad437b067356dc2bc2ec96eb395fd0fe804233", size = 652574, upload-time = "2025-09-08T23:08:06.828Z" }, - { url = "https://files.pythonhosted.org/packages/f8/9b/c108cdb55560eaf253f0cbdb61b29971e9fb34d9c3499b0e96e4e60ed8a5/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43ad9a73e3da1fab5b0e7e13402f0b2fb934ae1c876c51d0afff0e7c052eca31", size = 840995, upload-time = "2025-09-08T23:08:08.396Z" }, - { url = "https://files.pythonhosted.org/packages/c2/bb/b79798ca177b9eb0825b4c9998c6af8cd2a7f15a6a1a4272c1d1a21d382f/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0de3028d69d4cdc475bfe47a6128eb38d8bc0e8f4d69646adfbcd840facbac28", size = 1642070, upload-time = "2025-09-08T23:08:09.989Z" }, - { url = "https://files.pythonhosted.org/packages/9c/80/2df2e7977c4ede24c79ae39dcef3899bfc5f34d1ca7a5b24f182c9b7a9ca/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:cf44a7763aea9298c0aa7dbf859f87ed7012de8bda0f3977b6fb1d96745df856", size = 2021121, upload-time = "2025-09-08T23:08:11.907Z" }, - { url = "https://files.pythonhosted.org/packages/46/bd/2d45ad24f5f5ae7e8d01525eb76786fa7557136555cac7d929880519e33a/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f30f395a9e6fbca195400ce833c731e7b64c3919aa481af4d88c3759e0cb7496", size = 1878550, upload-time = "2025-09-08T23:08:13.513Z" }, - { url = "https://files.pythonhosted.org/packages/e6/2f/104c0a3c778d7c2ab8190e9db4f62f0b6957b53c9d87db77c284b69f33ea/pyzmq-27.1.0-cp312-abi3-win32.whl", hash = "sha256:250e5436a4ba13885494412b3da5d518cd0d3a278a1ae640e113c073a5f88edd", size = 559184, upload-time = "2025-09-08T23:08:15.163Z" }, - { url = "https://files.pythonhosted.org/packages/fc/7f/a21b20d577e4100c6a41795842028235998a643b1ad406a6d4163ea8f53e/pyzmq-27.1.0-cp312-abi3-win_amd64.whl", hash = "sha256:9ce490cf1d2ca2ad84733aa1d69ce6855372cb5ce9223802450c9b2a7cba0ccf", size = 619480, upload-time = "2025-09-08T23:08:17.192Z" }, - { url = "https://files.pythonhosted.org/packages/78/c2/c012beae5f76b72f007a9e91ee9401cb88c51d0f83c6257a03e785c81cc2/pyzmq-27.1.0-cp312-abi3-win_arm64.whl", hash = "sha256:75a2f36223f0d535a0c919e23615fc85a1e23b71f40c7eb43d7b1dedb4d8f15f", size = 552993, upload-time = "2025-09-08T23:08:18.926Z" }, - { url = "https://files.pythonhosted.org/packages/60/cb/84a13459c51da6cec1b7b1dc1a47e6db6da50b77ad7fd9c145842750a011/pyzmq-27.1.0-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:93ad4b0855a664229559e45c8d23797ceac03183c7b6f5b4428152a6b06684a5", size = 1122436, upload-time = "2025-09-08T23:08:20.801Z" }, - { url = "https://files.pythonhosted.org/packages/dc/b6/94414759a69a26c3dd674570a81813c46a078767d931a6c70ad29fc585cb/pyzmq-27.1.0-cp313-cp313-android_24_x86_64.whl", hash = "sha256:fbb4f2400bfda24f12f009cba62ad5734148569ff4949b1b6ec3b519444342e6", size = 1156301, upload-time = "2025-09-08T23:08:22.47Z" }, - { url = "https://files.pythonhosted.org/packages/a5/ad/15906493fd40c316377fd8a8f6b1f93104f97a752667763c9b9c1b71d42d/pyzmq-27.1.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:e343d067f7b151cfe4eb3bb796a7752c9d369eed007b91231e817071d2c2fec7", size = 1341197, upload-time = "2025-09-08T23:08:24.286Z" }, - { url = "https://files.pythonhosted.org/packages/14/1d/d343f3ce13db53a54cb8946594e567410b2125394dafcc0268d8dda027e0/pyzmq-27.1.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:08363b2011dec81c354d694bdecaef4770e0ae96b9afea70b3f47b973655cc05", size = 897275, upload-time = "2025-09-08T23:08:26.063Z" }, - { url = "https://files.pythonhosted.org/packages/69/2d/d83dd6d7ca929a2fc67d2c3005415cdf322af7751d773524809f9e585129/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d54530c8c8b5b8ddb3318f481297441af102517602b569146185fa10b63f4fa9", size = 660469, upload-time = "2025-09-08T23:08:27.623Z" }, - { url = "https://files.pythonhosted.org/packages/3e/cd/9822a7af117f4bc0f1952dbe9ef8358eb50a24928efd5edf54210b850259/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f3afa12c392f0a44a2414056d730eebc33ec0926aae92b5ad5cf26ebb6cc128", size = 847961, upload-time = "2025-09-08T23:08:29.672Z" }, - { url = "https://files.pythonhosted.org/packages/9a/12/f003e824a19ed73be15542f172fd0ec4ad0b60cf37436652c93b9df7c585/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c65047adafe573ff023b3187bb93faa583151627bc9c51fc4fb2c561ed689d39", size = 1650282, upload-time = "2025-09-08T23:08:31.349Z" }, - { url = "https://files.pythonhosted.org/packages/d5/4a/e82d788ed58e9a23995cee70dbc20c9aded3d13a92d30d57ec2291f1e8a3/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:90e6e9441c946a8b0a667356f7078d96411391a3b8f80980315455574177ec97", size = 2024468, upload-time = "2025-09-08T23:08:33.543Z" }, - { url = "https://files.pythonhosted.org/packages/d9/94/2da0a60841f757481e402b34bf4c8bf57fa54a5466b965de791b1e6f747d/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:add071b2d25f84e8189aaf0882d39a285b42fa3853016ebab234a5e78c7a43db", size = 1885394, upload-time = "2025-09-08T23:08:35.51Z" }, - { url = "https://files.pythonhosted.org/packages/4f/6f/55c10e2e49ad52d080dc24e37adb215e5b0d64990b57598abc2e3f01725b/pyzmq-27.1.0-cp313-cp313t-win32.whl", hash = "sha256:7ccc0700cfdf7bd487bea8d850ec38f204478681ea02a582a8da8171b7f90a1c", size = 574964, upload-time = "2025-09-08T23:08:37.178Z" }, - { url = "https://files.pythonhosted.org/packages/87/4d/2534970ba63dd7c522d8ca80fb92777f362c0f321900667c615e2067cb29/pyzmq-27.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:8085a9fba668216b9b4323be338ee5437a235fe275b9d1610e422ccc279733e2", size = 641029, upload-time = "2025-09-08T23:08:40.595Z" }, - { url = "https://files.pythonhosted.org/packages/f6/fa/f8aea7a28b0641f31d40dea42d7ef003fded31e184ef47db696bc74cd610/pyzmq-27.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:6bb54ca21bcfe361e445256c15eedf083f153811c37be87e0514934d6913061e", size = 561541, upload-time = "2025-09-08T23:08:42.668Z" }, - { url = "https://files.pythonhosted.org/packages/87/45/19efbb3000956e82d0331bafca5d9ac19ea2857722fa2caacefb6042f39d/pyzmq-27.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:ce980af330231615756acd5154f29813d553ea555485ae712c491cd483df6b7a", size = 1341197, upload-time = "2025-09-08T23:08:44.973Z" }, - { url = "https://files.pythonhosted.org/packages/48/43/d72ccdbf0d73d1343936296665826350cb1e825f92f2db9db3e61c2162a2/pyzmq-27.1.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1779be8c549e54a1c38f805e56d2a2e5c009d26de10921d7d51cfd1c8d4632ea", size = 897175, upload-time = "2025-09-08T23:08:46.601Z" }, - { url = "https://files.pythonhosted.org/packages/2f/2e/a483f73a10b65a9ef0161e817321d39a770b2acf8bcf3004a28d90d14a94/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7200bb0f03345515df50d99d3db206a0a6bee1955fbb8c453c76f5bf0e08fb96", size = 660427, upload-time = "2025-09-08T23:08:48.187Z" }, - { url = "https://files.pythonhosted.org/packages/f5/d2/5f36552c2d3e5685abe60dfa56f91169f7a2d99bbaf67c5271022ab40863/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01c0e07d558b06a60773744ea6251f769cd79a41a97d11b8bf4ab8f034b0424d", size = 847929, upload-time = "2025-09-08T23:08:49.76Z" }, - { url = "https://files.pythonhosted.org/packages/c4/2a/404b331f2b7bf3198e9945f75c4c521f0c6a3a23b51f7a4a401b94a13833/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:80d834abee71f65253c91540445d37c4c561e293ba6e741b992f20a105d69146", size = 1650193, upload-time = "2025-09-08T23:08:51.7Z" }, - { url = "https://files.pythonhosted.org/packages/1c/0b/f4107e33f62a5acf60e3ded67ed33d79b4ce18de432625ce2fc5093d6388/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:544b4e3b7198dde4a62b8ff6685e9802a9a1ebf47e77478a5eb88eca2a82f2fd", size = 2024388, upload-time = "2025-09-08T23:08:53.393Z" }, - { url = "https://files.pythonhosted.org/packages/0d/01/add31fe76512642fd6e40e3a3bd21f4b47e242c8ba33efb6809e37076d9b/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cedc4c68178e59a4046f97eca31b148ddcf51e88677de1ef4e78cf06c5376c9a", size = 1885316, upload-time = "2025-09-08T23:08:55.702Z" }, - { url = "https://files.pythonhosted.org/packages/c4/59/a5f38970f9bf07cee96128de79590bb354917914a9be11272cfc7ff26af0/pyzmq-27.1.0-cp314-cp314t-win32.whl", hash = "sha256:1f0b2a577fd770aa6f053211a55d1c47901f4d537389a034c690291485e5fe92", size = 587472, upload-time = "2025-09-08T23:08:58.18Z" }, - { url = "https://files.pythonhosted.org/packages/70/d8/78b1bad170f93fcf5e3536e70e8fadac55030002275c9a29e8f5719185de/pyzmq-27.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:19c9468ae0437f8074af379e986c5d3d7d7bfe033506af442e8c879732bedbe0", size = 661401, upload-time = "2025-09-08T23:08:59.802Z" }, - { url = "https://files.pythonhosted.org/packages/81/d6/4bfbb40c9a0b42fc53c7cf442f6385db70b40f74a783130c5d0a5aa62228/pyzmq-27.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dc5dbf68a7857b59473f7df42650c621d7e8923fb03fa74a526890f4d33cc4d7", size = 575170, upload-time = "2025-09-08T23:09:01.418Z" }, -] - -[[package]] -name = "referencing" -version = "0.37.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "attrs" }, - { name = "rpds-py" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" }, -] - [[package]] name = "requests" version = "2.32.5" @@ -1879,105 +817,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/68/3f/dfa42bb16be96d53351aa151cb1e39fcaafe6cda01389c530a2ec809ef8a/requests_cache-1.3.0-py3-none-any.whl", hash = "sha256:f09f27bbf100c250886acf13a9db35b53cf2852fddd71977b47c71ea7d90dbba", size = 69626, upload-time = "2026-02-02T23:17:31.718Z" }, ] -[[package]] -name = "rfc3339-validator" -version = "0.1.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "six" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/28/ea/a9387748e2d111c3c2b275ba970b735e04e15cdb1eb30693b6b5708c4dbd/rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b", size = 5513, upload-time = "2021-05-12T16:37:54.178Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa", size = 3490, upload-time = "2021-05-12T16:37:52.536Z" }, -] - -[[package]] -name = "rfc3986-validator" -version = "0.1.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/da/88/f270de456dd7d11dcc808abfa291ecdd3f45ff44e3b549ffa01b126464d0/rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055", size = 6760, upload-time = "2019-10-28T16:00:19.144Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9", size = 4242, upload-time = "2019-10-28T16:00:13.976Z" }, -] - -[[package]] -name = "rfc3987-syntax" -version = "1.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "lark" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/2c/06/37c1a5557acf449e8e406a830a05bf885ac47d33270aec454ef78675008d/rfc3987_syntax-1.1.0.tar.gz", hash = "sha256:717a62cbf33cffdd16dfa3a497d81ce48a660ea691b1ddd7be710c22f00b4a0d", size = 14239, upload-time = "2025-07-18T01:05:05.015Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl", hash = "sha256:6c3d97604e4c5ce9f714898e05401a0445a641cfa276432b0a648c80856f6a3f", size = 8046, upload-time = "2025-07-18T01:05:03.843Z" }, -] - -[[package]] -name = "rpds-py" -version = "0.30.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469, upload-time = "2025-11-30T20:24:38.837Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ed/dc/d61221eb88ff410de3c49143407f6f3147acf2538c86f2ab7ce65ae7d5f9/rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2", size = 374887, upload-time = "2025-11-30T20:22:41.812Z" }, - { url = "https://files.pythonhosted.org/packages/fd/32/55fb50ae104061dbc564ef15cc43c013dc4a9f4527a1f4d99baddf56fe5f/rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8", size = 358904, upload-time = "2025-11-30T20:22:43.479Z" }, - { url = "https://files.pythonhosted.org/packages/58/70/faed8186300e3b9bdd138d0273109784eea2396c68458ed580f885dfe7ad/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4", size = 389945, upload-time = "2025-11-30T20:22:44.819Z" }, - { url = "https://files.pythonhosted.org/packages/bd/a8/073cac3ed2c6387df38f71296d002ab43496a96b92c823e76f46b8af0543/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136", size = 407783, upload-time = "2025-11-30T20:22:46.103Z" }, - { url = "https://files.pythonhosted.org/packages/77/57/5999eb8c58671f1c11eba084115e77a8899d6e694d2a18f69f0ba471ec8b/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7", size = 515021, upload-time = "2025-11-30T20:22:47.458Z" }, - { url = "https://files.pythonhosted.org/packages/e0/af/5ab4833eadc36c0a8ed2bc5c0de0493c04f6c06de223170bd0798ff98ced/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2", size = 414589, upload-time = "2025-11-30T20:22:48.872Z" }, - { url = "https://files.pythonhosted.org/packages/b7/de/f7192e12b21b9e9a68a6d0f249b4af3fdcdff8418be0767a627564afa1f1/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6", size = 394025, upload-time = "2025-11-30T20:22:50.196Z" }, - { url = "https://files.pythonhosted.org/packages/91/c4/fc70cd0249496493500e7cc2de87504f5aa6509de1e88623431fec76d4b6/rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e", size = 408895, upload-time = "2025-11-30T20:22:51.87Z" }, - { url = "https://files.pythonhosted.org/packages/58/95/d9275b05ab96556fefff73a385813eb66032e4c99f411d0795372d9abcea/rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d", size = 422799, upload-time = "2025-11-30T20:22:53.341Z" }, - { url = "https://files.pythonhosted.org/packages/06/c1/3088fc04b6624eb12a57eb814f0d4997a44b0d208d6cace713033ff1a6ba/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7", size = 572731, upload-time = "2025-11-30T20:22:54.778Z" }, - { url = "https://files.pythonhosted.org/packages/d8/42/c612a833183b39774e8ac8fecae81263a68b9583ee343db33ab571a7ce55/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31", size = 599027, upload-time = "2025-11-30T20:22:56.212Z" }, - { url = "https://files.pythonhosted.org/packages/5f/60/525a50f45b01d70005403ae0e25f43c0384369ad24ffe46e8d9068b50086/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95", size = 563020, upload-time = "2025-11-30T20:22:58.2Z" }, - { url = "https://files.pythonhosted.org/packages/0b/5d/47c4655e9bcd5ca907148535c10e7d489044243cc9941c16ed7cd53be91d/rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d", size = 223139, upload-time = "2025-11-30T20:23:00.209Z" }, - { url = "https://files.pythonhosted.org/packages/f2/e1/485132437d20aa4d3e1d8b3fb5a5e65aa8139f1e097080c2a8443201742c/rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15", size = 240224, upload-time = "2025-11-30T20:23:02.008Z" }, - { url = "https://files.pythonhosted.org/packages/24/95/ffd128ed1146a153d928617b0ef673960130be0009c77d8fbf0abe306713/rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1", size = 230645, upload-time = "2025-11-30T20:23:03.43Z" }, - { url = "https://files.pythonhosted.org/packages/ff/1b/b10de890a0def2a319a2626334a7f0ae388215eb60914dbac8a3bae54435/rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a", size = 364443, upload-time = "2025-11-30T20:23:04.878Z" }, - { url = "https://files.pythonhosted.org/packages/0d/bf/27e39f5971dc4f305a4fb9c672ca06f290f7c4e261c568f3dea16a410d47/rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e", size = 353375, upload-time = "2025-11-30T20:23:06.342Z" }, - { url = "https://files.pythonhosted.org/packages/40/58/442ada3bba6e8e6615fc00483135c14a7538d2ffac30e2d933ccf6852232/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000", size = 383850, upload-time = "2025-11-30T20:23:07.825Z" }, - { url = "https://files.pythonhosted.org/packages/14/14/f59b0127409a33c6ef6f5c1ebd5ad8e32d7861c9c7adfa9a624fc3889f6c/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db", size = 392812, upload-time = "2025-11-30T20:23:09.228Z" }, - { url = "https://files.pythonhosted.org/packages/b3/66/e0be3e162ac299b3a22527e8913767d869e6cc75c46bd844aa43fb81ab62/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2", size = 517841, upload-time = "2025-11-30T20:23:11.186Z" }, - { url = "https://files.pythonhosted.org/packages/3d/55/fa3b9cf31d0c963ecf1ba777f7cf4b2a2c976795ac430d24a1f43d25a6ba/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa", size = 408149, upload-time = "2025-11-30T20:23:12.864Z" }, - { url = "https://files.pythonhosted.org/packages/60/ca/780cf3b1a32b18c0f05c441958d3758f02544f1d613abf9488cd78876378/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083", size = 383843, upload-time = "2025-11-30T20:23:14.638Z" }, - { url = "https://files.pythonhosted.org/packages/82/86/d5f2e04f2aa6247c613da0c1dd87fcd08fa17107e858193566048a1e2f0a/rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9", size = 396507, upload-time = "2025-11-30T20:23:16.105Z" }, - { url = "https://files.pythonhosted.org/packages/4b/9a/453255d2f769fe44e07ea9785c8347edaf867f7026872e76c1ad9f7bed92/rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0", size = 414949, upload-time = "2025-11-30T20:23:17.539Z" }, - { url = "https://files.pythonhosted.org/packages/a3/31/622a86cdc0c45d6df0e9ccb6becdba5074735e7033c20e401a6d9d0e2ca0/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94", size = 565790, upload-time = "2025-11-30T20:23:19.029Z" }, - { url = "https://files.pythonhosted.org/packages/1c/5d/15bbf0fb4a3f58a3b1c67855ec1efcc4ceaef4e86644665fff03e1b66d8d/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08", size = 590217, upload-time = "2025-11-30T20:23:20.885Z" }, - { url = "https://files.pythonhosted.org/packages/6d/61/21b8c41f68e60c8cc3b2e25644f0e3681926020f11d06ab0b78e3c6bbff1/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27", size = 555806, upload-time = "2025-11-30T20:23:22.488Z" }, - { url = "https://files.pythonhosted.org/packages/f9/39/7e067bb06c31de48de3eb200f9fc7c58982a4d3db44b07e73963e10d3be9/rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6", size = 211341, upload-time = "2025-11-30T20:23:24.449Z" }, - { url = "https://files.pythonhosted.org/packages/0a/4d/222ef0b46443cf4cf46764d9c630f3fe4abaa7245be9417e56e9f52b8f65/rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d", size = 225768, upload-time = "2025-11-30T20:23:25.908Z" }, - { url = "https://files.pythonhosted.org/packages/86/81/dad16382ebbd3d0e0328776d8fd7ca94220e4fa0798d1dc5e7da48cb3201/rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0", size = 362099, upload-time = "2025-11-30T20:23:27.316Z" }, - { url = "https://files.pythonhosted.org/packages/2b/60/19f7884db5d5603edf3c6bce35408f45ad3e97e10007df0e17dd57af18f8/rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be", size = 353192, upload-time = "2025-11-30T20:23:29.151Z" }, - { url = "https://files.pythonhosted.org/packages/bf/c4/76eb0e1e72d1a9c4703c69607cec123c29028bff28ce41588792417098ac/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f", size = 384080, upload-time = "2025-11-30T20:23:30.785Z" }, - { url = "https://files.pythonhosted.org/packages/72/87/87ea665e92f3298d1b26d78814721dc39ed8d2c74b86e83348d6b48a6f31/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f", size = 394841, upload-time = "2025-11-30T20:23:32.209Z" }, - { url = "https://files.pythonhosted.org/packages/77/ad/7783a89ca0587c15dcbf139b4a8364a872a25f861bdb88ed99f9b0dec985/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87", size = 516670, upload-time = "2025-11-30T20:23:33.742Z" }, - { url = "https://files.pythonhosted.org/packages/5b/3c/2882bdac942bd2172f3da574eab16f309ae10a3925644e969536553cb4ee/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18", size = 408005, upload-time = "2025-11-30T20:23:35.253Z" }, - { url = "https://files.pythonhosted.org/packages/ce/81/9a91c0111ce1758c92516a3e44776920b579d9a7c09b2b06b642d4de3f0f/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad", size = 382112, upload-time = "2025-11-30T20:23:36.842Z" }, - { url = "https://files.pythonhosted.org/packages/cf/8e/1da49d4a107027e5fbc64daeab96a0706361a2918da10cb41769244b805d/rpds_py-0.30.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07", size = 399049, upload-time = "2025-11-30T20:23:38.343Z" }, - { url = "https://files.pythonhosted.org/packages/df/5a/7ee239b1aa48a127570ec03becbb29c9d5a9eb092febbd1699d567cae859/rpds_py-0.30.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f", size = 415661, upload-time = "2025-11-30T20:23:40.263Z" }, - { url = "https://files.pythonhosted.org/packages/70/ea/caa143cf6b772f823bc7929a45da1fa83569ee49b11d18d0ada7f5ee6fd6/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65", size = 565606, upload-time = "2025-11-30T20:23:42.186Z" }, - { url = "https://files.pythonhosted.org/packages/64/91/ac20ba2d69303f961ad8cf55bf7dbdb4763f627291ba3d0d7d67333cced9/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f", size = 591126, upload-time = "2025-11-30T20:23:44.086Z" }, - { url = "https://files.pythonhosted.org/packages/21/20/7ff5f3c8b00c8a95f75985128c26ba44503fb35b8e0259d812766ea966c7/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53", size = 553371, upload-time = "2025-11-30T20:23:46.004Z" }, - { url = "https://files.pythonhosted.org/packages/72/c7/81dadd7b27c8ee391c132a6b192111ca58d866577ce2d9b0ca157552cce0/rpds_py-0.30.0-cp314-cp314-win32.whl", hash = "sha256:ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed", size = 215298, upload-time = "2025-11-30T20:23:47.696Z" }, - { url = "https://files.pythonhosted.org/packages/3e/d2/1aaac33287e8cfb07aab2e6b8ac1deca62f6f65411344f1433c55e6f3eb8/rpds_py-0.30.0-cp314-cp314-win_amd64.whl", hash = "sha256:95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950", size = 228604, upload-time = "2025-11-30T20:23:49.501Z" }, - { url = "https://files.pythonhosted.org/packages/e8/95/ab005315818cc519ad074cb7784dae60d939163108bd2b394e60dc7b5461/rpds_py-0.30.0-cp314-cp314-win_arm64.whl", hash = "sha256:613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6", size = 222391, upload-time = "2025-11-30T20:23:50.96Z" }, - { url = "https://files.pythonhosted.org/packages/9e/68/154fe0194d83b973cdedcdcc88947a2752411165930182ae41d983dcefa6/rpds_py-0.30.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb", size = 364868, upload-time = "2025-11-30T20:23:52.494Z" }, - { url = "https://files.pythonhosted.org/packages/83/69/8bbc8b07ec854d92a8b75668c24d2abcb1719ebf890f5604c61c9369a16f/rpds_py-0.30.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8", size = 353747, upload-time = "2025-11-30T20:23:54.036Z" }, - { url = "https://files.pythonhosted.org/packages/ab/00/ba2e50183dbd9abcce9497fa5149c62b4ff3e22d338a30d690f9af970561/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7", size = 383795, upload-time = "2025-11-30T20:23:55.556Z" }, - { url = "https://files.pythonhosted.org/packages/05/6f/86f0272b84926bcb0e4c972262f54223e8ecc556b3224d281e6598fc9268/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898", size = 393330, upload-time = "2025-11-30T20:23:57.033Z" }, - { url = "https://files.pythonhosted.org/packages/cb/e9/0e02bb2e6dc63d212641da45df2b0bf29699d01715913e0d0f017ee29438/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e", size = 518194, upload-time = "2025-11-30T20:23:58.637Z" }, - { url = "https://files.pythonhosted.org/packages/ee/ca/be7bca14cf21513bdf9c0606aba17d1f389ea2b6987035eb4f62bd923f25/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419", size = 408340, upload-time = "2025-11-30T20:24:00.2Z" }, - { url = "https://files.pythonhosted.org/packages/c2/c7/736e00ebf39ed81d75544c0da6ef7b0998f8201b369acf842f9a90dc8fce/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551", size = 383765, upload-time = "2025-11-30T20:24:01.759Z" }, - { url = "https://files.pythonhosted.org/packages/4a/3f/da50dfde9956aaf365c4adc9533b100008ed31aea635f2b8d7b627e25b49/rpds_py-0.30.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8", size = 396834, upload-time = "2025-11-30T20:24:03.687Z" }, - { url = "https://files.pythonhosted.org/packages/4e/00/34bcc2565b6020eab2623349efbdec810676ad571995911f1abdae62a3a0/rpds_py-0.30.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5", size = 415470, upload-time = "2025-11-30T20:24:05.232Z" }, - { url = "https://files.pythonhosted.org/packages/8c/28/882e72b5b3e6f718d5453bd4d0d9cf8df36fddeb4ddbbab17869d5868616/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404", size = 565630, upload-time = "2025-11-30T20:24:06.878Z" }, - { url = "https://files.pythonhosted.org/packages/3b/97/04a65539c17692de5b85c6e293520fd01317fd878ea1995f0367d4532fb1/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856", size = 591148, upload-time = "2025-11-30T20:24:08.445Z" }, - { url = "https://files.pythonhosted.org/packages/85/70/92482ccffb96f5441aab93e26c4d66489eb599efdcf96fad90c14bbfb976/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40", size = 556030, upload-time = "2025-11-30T20:24:10.956Z" }, - { url = "https://files.pythonhosted.org/packages/20/53/7c7e784abfa500a2b6b583b147ee4bb5a2b3747a9166bab52fec4b5b5e7d/rpds_py-0.30.0-cp314-cp314t-win32.whl", hash = "sha256:dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0", size = 211570, upload-time = "2025-11-30T20:24:12.735Z" }, - { url = "https://files.pythonhosted.org/packages/d0/02/fa464cdfbe6b26e0600b62c528b72d8608f5cc49f96b8d6e38c95d60c676/rpds_py-0.30.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3", size = 226532, upload-time = "2025-11-30T20:24:14.634Z" }, -] - [[package]] name = "scikit-learn" version = "1.8.0" @@ -2081,24 +920,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/83/11/00d3c3dfc25ad54e731d91449895a79e4bf2384dc3ac01809010ba88f6d5/seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987", size = 294914, upload-time = "2024-01-25T13:21:49.598Z" }, ] -[[package]] -name = "send2trash" -version = "2.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c5/f0/184b4b5f8d00f2a92cf96eec8967a3d550b52cf94362dad1100df9e48d57/send2trash-2.1.0.tar.gz", hash = "sha256:1c72b39f09457db3c05ce1d19158c2cbef4c32b8bedd02c155e49282b7ea7459", size = 17255, upload-time = "2026-01-14T06:27:36.056Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1c/78/504fdd027da3b84ff1aecd9f6957e65f35134534ccc6da8628eb71e76d3f/send2trash-2.1.0-py3-none-any.whl", hash = "sha256:0da2f112e6d6bb22de6aa6daa7e144831a4febf2a87261451c4ad849fe9a873c", size = 17610, upload-time = "2026-01-14T06:27:35.218Z" }, -] - -[[package]] -name = "setuptools" -version = "82.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/82/f3/748f4d6f65d1756b9ae577f329c951cda23fb900e4de9f70900ced962085/setuptools-82.0.0.tar.gz", hash = "sha256:22e0a2d69474c6ae4feb01951cb69d515ed23728cf96d05513d36e42b62b37cb", size = 1144893, upload-time = "2026-02-08T15:08:40.206Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e1/c6/76dc613121b793286a3f91621d7b75a2b493e0390ddca50f11993eadf192/setuptools-82.0.0-py3-none-any.whl", hash = "sha256:70b18734b607bd1da571d097d236cfcfacaf01de45717d59e6e04b96877532e0", size = 1003468, upload-time = "2026-02-08T15:08:38.723Z" }, -] - [[package]] name = "shapely" version = "2.1.2" @@ -2151,29 +972,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, ] -[[package]] -name = "soupsieve" -version = "2.8.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7b/ae/2d9c981590ed9999a0d91755b47fc74f74de286b0f5cee14c9269041e6c4/soupsieve-2.8.3.tar.gz", hash = "sha256:3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349", size = 118627, upload-time = "2026-01-20T04:27:02.457Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl", hash = "sha256:ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95", size = 37016, upload-time = "2026-01-20T04:27:01.012Z" }, -] - -[[package]] -name = "stack-data" -version = "0.6.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "asttokens" }, - { name = "executing" }, - { name = "pure-eval" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707, upload-time = "2023-09-30T13:58:05.479Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" }, -] - [[package]] name = "statsmodels" version = "0.14.6" @@ -2201,20 +999,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/26/33/f1652d0c59fa51de18492ee2345b65372550501ad061daa38f950be390b6/statsmodels-0.14.6-cp314-cp314-win_amd64.whl", hash = "sha256:151b73e29f01fe619dbce7f66d61a356e9d1fe5e906529b78807df9189c37721", size = 9588010, upload-time = "2025-12-05T23:14:07.28Z" }, ] -[[package]] -name = "terminado" -version = "0.18.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "ptyprocess", marker = "os_name != 'nt'" }, - { name = "pywinpty", marker = "os_name == 'nt'" }, - { name = "tornado" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/8a/11/965c6fd8e5cc254f1fe142d547387da17a8ebfd75a3455f637c663fb38a0/terminado-0.18.1.tar.gz", hash = "sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e", size = 32701, upload-time = "2024-03-12T14:34:39.026Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl", hash = "sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0", size = 14154, upload-time = "2024-03-12T14:34:36.569Z" }, -] - [[package]] name = "threadpoolctl" version = "3.6.0" @@ -2224,50 +1008,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638, upload-time = "2025-03-13T13:49:21.846Z" }, ] -[[package]] -name = "tidypolars" -version = "0.3.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "numpy" }, - { name = "polars" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/06/b4/98c9f4f6c87d0630c4745777140c889d3b1a70db5a292204020839f0deae/tidypolars-0.3.2.tar.gz", hash = "sha256:009cb92d3211fb20a375adbfcf043703b04411aa22c05351addd13addff84f67", size = 17836, upload-time = "2024-11-02T14:49:21.012Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4b/c5/fe58f5ff266d15d22c3eb214c04d035c606febd317ea51cac85e212e74de/tidypolars-0.3.2-py3-none-any.whl", hash = "sha256:73ca614730c38abc63e30db832e599b098e95ea7094d9cff60fe24733b0a5293", size = 18731, upload-time = "2024-11-02T14:49:19.513Z" }, -] - -[[package]] -name = "tinycss2" -version = "1.4.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "webencodings" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/7a/fd/7a5ee21fd08ff70d3d33a5781c255cbe779659bd03278feb98b19ee550f4/tinycss2-1.4.0.tar.gz", hash = "sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7", size = 87085, upload-time = "2024-10-24T14:58:29.895Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289", size = 26610, upload-time = "2024-10-24T14:58:28.029Z" }, -] - -[[package]] -name = "tornado" -version = "6.5.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/37/1d/0a336abf618272d53f62ebe274f712e213f5a03c0b2339575430b8362ef2/tornado-6.5.4.tar.gz", hash = "sha256:a22fa9047405d03260b483980635f0b041989d8bcc9a313f8fe18b411d84b1d7", size = 513632, upload-time = "2025-12-15T19:21:03.836Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ab/a9/e94a9d5224107d7ce3cc1fab8d5dc97f5ea351ccc6322ee4fb661da94e35/tornado-6.5.4-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:d6241c1a16b1c9e4cc28148b1cda97dd1c6cb4fb7068ac1bedc610768dff0ba9", size = 443909, upload-time = "2025-12-15T19:20:48.382Z" }, - { url = "https://files.pythonhosted.org/packages/db/7e/f7b8d8c4453f305a51f80dbb49014257bb7d28ccb4bbb8dd328ea995ecad/tornado-6.5.4-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2d50f63dda1d2cac3ae1fa23d254e16b5e38153758470e9956cbc3d813d40843", size = 442163, upload-time = "2025-12-15T19:20:49.791Z" }, - { url = "https://files.pythonhosted.org/packages/ba/b5/206f82d51e1bfa940ba366a8d2f83904b15942c45a78dd978b599870ab44/tornado-6.5.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1cf66105dc6acb5af613c054955b8137e34a03698aa53272dbda4afe252be17", size = 445746, upload-time = "2025-12-15T19:20:51.491Z" }, - { url = "https://files.pythonhosted.org/packages/8e/9d/1a3338e0bd30ada6ad4356c13a0a6c35fbc859063fa7eddb309183364ac1/tornado-6.5.4-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50ff0a58b0dc97939d29da29cd624da010e7f804746621c78d14b80238669335", size = 445083, upload-time = "2025-12-15T19:20:52.778Z" }, - { url = "https://files.pythonhosted.org/packages/50/d4/e51d52047e7eb9a582da59f32125d17c0482d065afd5d3bc435ff2120dc5/tornado-6.5.4-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5fb5e04efa54cf0baabdd10061eb4148e0be137166146fff835745f59ab9f7f", size = 445315, upload-time = "2025-12-15T19:20:53.996Z" }, - { url = "https://files.pythonhosted.org/packages/27/07/2273972f69ca63dbc139694a3fc4684edec3ea3f9efabf77ed32483b875c/tornado-6.5.4-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9c86b1643b33a4cd415f8d0fe53045f913bf07b4a3ef646b735a6a86047dda84", size = 446003, upload-time = "2025-12-15T19:20:56.101Z" }, - { url = "https://files.pythonhosted.org/packages/d1/83/41c52e47502bf7260044413b6770d1a48dda2f0246f95ee1384a3cd9c44a/tornado-6.5.4-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:6eb82872335a53dd063a4f10917b3efd28270b56a33db69009606a0312660a6f", size = 445412, upload-time = "2025-12-15T19:20:57.398Z" }, - { url = "https://files.pythonhosted.org/packages/10/c7/bc96917f06cbee182d44735d4ecde9c432e25b84f4c2086143013e7b9e52/tornado-6.5.4-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6076d5dda368c9328ff41ab5d9dd3608e695e8225d1cd0fd1e006f05da3635a8", size = 445392, upload-time = "2025-12-15T19:20:58.692Z" }, - { url = "https://files.pythonhosted.org/packages/0c/1a/d7592328d037d36f2d2462f4bc1fbb383eec9278bc786c1b111cbbd44cfa/tornado-6.5.4-cp39-abi3-win32.whl", hash = "sha256:1768110f2411d5cd281bac0a090f707223ce77fd110424361092859e089b38d1", size = 446481, upload-time = "2025-12-15T19:21:00.008Z" }, - { url = "https://files.pythonhosted.org/packages/d6/6d/c69be695a0a64fd37a97db12355a035a6d90f79067a3cf936ec2b1dc38cd/tornado-6.5.4-cp39-abi3-win_amd64.whl", hash = "sha256:fa07d31e0cd85c60713f2b995da613588aa03e1303d75705dca6af8babc18ddc", size = 446886, upload-time = "2025-12-15T19:21:01.287Z" }, - { url = "https://files.pythonhosted.org/packages/50/49/8dc3fd90902f70084bd2cd059d576ddb4f8bb44c2c7c0e33a11422acb17e/tornado-6.5.4-cp39-abi3-win_arm64.whl", hash = "sha256:053e6e16701eb6cbe641f308f4c1a9541f91b6261991160391bfc342e8a551a1", size = 445910, upload-time = "2025-12-15T19:21:02.571Z" }, -] - [[package]] name = "tqdm" version = "4.67.3" @@ -2280,15 +1020,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf", size = 78374, upload-time = "2026-02-03T17:35:50.982Z" }, ] -[[package]] -name = "traitlets" -version = "5.14.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/eb/79/72064e6a701c2183016abbbfedaba506d81e30e232a68c9f0d6f6fcd1574/traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", size = 161621, upload-time = "2024-04-19T11:11:49.746Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f", size = 85359, upload-time = "2024-04-19T11:11:46.763Z" }, -] - [[package]] name = "typing-extensions" version = "4.15.0" @@ -2307,15 +1038,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, ] -[[package]] -name = "uri-template" -version = "1.3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/31/c7/0336f2bd0bcbada6ccef7aaa25e443c118a704f828a0620c6fa0207c1b64/uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7", size = 21678, upload-time = "2023-06-21T01:49:05.374Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363", size = 11140, upload-time = "2023-06-21T01:49:03.467Z" }, -] - [[package]] name = "url-normalize" version = "2.2.1" @@ -2337,51 +1059,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" }, ] -[[package]] -name = "wcwidth" -version = "0.6.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/35/a2/8e3becb46433538a38726c948d3399905a4c7cabd0df578ede5dc51f0ec2/wcwidth-0.6.0.tar.gz", hash = "sha256:cdc4e4262d6ef9a1a57e018384cbeb1208d8abbc64176027e2c2455c81313159", size = 159684, upload-time = "2026-02-06T19:19:40.919Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/68/5a/199c59e0a824a3db2b89c5d2dade7ab5f9624dbf6448dc291b46d5ec94d3/wcwidth-0.6.0-py3-none-any.whl", hash = "sha256:1a3a1e510b553315f8e146c54764f4fb6264ffad731b3d78088cdb1478ffbdad", size = 94189, upload-time = "2026-02-06T19:19:39.646Z" }, -] - -[[package]] -name = "webcolors" -version = "25.10.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1d/7a/eb316761ec35664ea5174709a68bbd3389de60d4a1ebab8808bfc264ed67/webcolors-25.10.0.tar.gz", hash = "sha256:62abae86504f66d0f6364c2a8520de4a0c47b80c03fc3a5f1815fedbef7c19bf", size = 53491, upload-time = "2025-10-31T07:51:03.977Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl", hash = "sha256:032c727334856fc0b968f63daa252a1ac93d33db2f5267756623c210e57a4f1d", size = 14905, upload-time = "2025-10-31T07:51:01.778Z" }, -] - -[[package]] -name = "webencodings" -version = "0.5.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923", size = 9721, upload-time = "2017-04-05T20:21:34.189Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774, upload-time = "2017-04-05T20:21:32.581Z" }, -] - -[[package]] -name = "websocket-client" -version = "1.9.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/2c/41/aa4bf9664e4cda14c3b39865b12251e8e7d239f4cd0e3cc1b6c2ccde25c1/websocket_client-1.9.0.tar.gz", hash = "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", size = 70576, upload-time = "2025-10-07T21:16:36.495Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/34/db/b10e48aa8fff7407e67470363eac595018441cf32d5e1001567a7aeba5d2/websocket_client-1.9.0-py3-none-any.whl", hash = "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef", size = 82616, upload-time = "2025-10-07T21:16:34.951Z" }, -] - -[[package]] -name = "widgetsnbextension" -version = "4.0.15" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/bd/f4/c67440c7fb409a71b7404b7aefcd7569a9c0d6bd071299bf4198ae7a5d95/widgetsnbextension-4.0.15.tar.gz", hash = "sha256:de8610639996f1567952d763a5a41af8af37f2575a41f9852a38f947eb82a3b9", size = 1097402, upload-time = "2025-11-01T21:15:55.178Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl", hash = "sha256:8156704e4346a571d9ce73b84bee86a29906c9abfd7223b7228a28899ccf3366", size = 2196503, upload-time = "2025-11-01T21:15:53.565Z" }, -] - [[package]] name = "xlrd" version = "2.0.2" From 52fc17d3fb7ba1e4d4d619e706d034a3e7648cbe Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:10:44 +0000 Subject: [PATCH 91/92] jupyter was necessaery :o --- pyproject.toml | 1 + uv.lock | 1318 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 1314 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9979da92..db1f069b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,4 +19,5 @@ dependencies = [ "seaborn>=0.13.2", "xlrd>=2.0.2", "fastexcel>=0.19.0", + "jupyter>=1.1.1", ] diff --git a/uv.lock b/uv.lock index 5e2d7297..8c8f71a3 100644 --- a/uv.lock +++ b/uv.lock @@ -6,6 +6,101 @@ resolution-markers = [ "python_full_version < '3.14'", ] +[[package]] +name = "anyio" +version = "4.12.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/96/f0/5eb65b2bb0d09ac6776f2eb54adee6abe8228ea05b20a5ad0e4945de8aac/anyio-4.12.1.tar.gz", hash = "sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703", size = 228685, upload-time = "2026-01-06T11:45:21.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c", size = 113592, upload-time = "2026-01-06T11:45:19.497Z" }, +] + +[[package]] +name = "appnope" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/35/5d/752690df9ef5b76e169e68d6a129fa6d08a7100ca7f754c89495db3c6019/appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee", size = 4170, upload-time = "2024-02-06T09:43:11.258Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c", size = 4321, upload-time = "2024-02-06T09:43:09.663Z" }, +] + +[[package]] +name = "argon2-cffi" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "argon2-cffi-bindings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0e/89/ce5af8a7d472a67cc819d5d998aa8c82c5d860608c4db9f46f1162d7dab9/argon2_cffi-25.1.0.tar.gz", hash = "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1", size = 45706, upload-time = "2025-06-03T06:55:32.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4f/d3/a8b22fa575b297cd6e3e3b0155c7e25db170edf1c74783d6a31a2490b8d9/argon2_cffi-25.1.0-py3-none-any.whl", hash = "sha256:fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741", size = 14657, upload-time = "2025-06-03T06:55:30.804Z" }, +] + +[[package]] +name = "argon2-cffi-bindings" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5c/2d/db8af0df73c1cf454f71b2bbe5e356b8c1f8041c979f505b3d3186e520a9/argon2_cffi_bindings-25.1.0.tar.gz", hash = "sha256:b957f3e6ea4d55d820e40ff76f450952807013d361a65d7f28acc0acbf29229d", size = 1783441, upload-time = "2025-07-30T10:02:05.147Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/97/3c0a35f46e52108d4707c44b95cfe2afcafc50800b5450c197454569b776/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:3d3f05610594151994ca9ccb3c771115bdb4daef161976a266f0dd8aa9996b8f", size = 54393, upload-time = "2025-07-30T10:01:40.97Z" }, + { url = "https://files.pythonhosted.org/packages/9d/f4/98bbd6ee89febd4f212696f13c03ca302b8552e7dbf9c8efa11ea4a388c3/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8b8efee945193e667a396cbc7b4fb7d357297d6234d30a489905d96caabde56b", size = 29328, upload-time = "2025-07-30T10:01:41.916Z" }, + { url = "https://files.pythonhosted.org/packages/43/24/90a01c0ef12ac91a6be05969f29944643bc1e5e461155ae6559befa8f00b/argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3c6702abc36bf3ccba3f802b799505def420a1b7039862014a65db3205967f5a", size = 31269, upload-time = "2025-07-30T10:01:42.716Z" }, + { url = "https://files.pythonhosted.org/packages/d4/d3/942aa10782b2697eee7af5e12eeff5ebb325ccfb86dd8abda54174e377e4/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1c70058c6ab1e352304ac7e3b52554daadacd8d453c1752e547c76e9c99ac44", size = 86558, upload-time = "2025-07-30T10:01:43.943Z" }, + { url = "https://files.pythonhosted.org/packages/0d/82/b484f702fec5536e71836fc2dbc8c5267b3f6e78d2d539b4eaa6f0db8bf8/argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e2fd3bfbff3c5d74fef31a722f729bf93500910db650c925c2d6ef879a7e51cb", size = 92364, upload-time = "2025-07-30T10:01:44.887Z" }, + { url = "https://files.pythonhosted.org/packages/c9/c1/a606ff83b3f1735f3759ad0f2cd9e038a0ad11a3de3b6c673aa41c24bb7b/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4f9665de60b1b0e99bcd6be4f17d90339698ce954cfd8d9cf4f91c995165a92", size = 85637, upload-time = "2025-07-30T10:01:46.225Z" }, + { url = "https://files.pythonhosted.org/packages/44/b4/678503f12aceb0262f84fa201f6027ed77d71c5019ae03b399b97caa2f19/argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ba92837e4a9aa6a508c8d2d7883ed5a8f6c308c89a4790e1e447a220deb79a85", size = 91934, upload-time = "2025-07-30T10:01:47.203Z" }, + { url = "https://files.pythonhosted.org/packages/f0/c7/f36bd08ef9bd9f0a9cff9428406651f5937ce27b6c5b07b92d41f91ae541/argon2_cffi_bindings-25.1.0-cp314-cp314t-win32.whl", hash = "sha256:84a461d4d84ae1295871329b346a97f68eade8c53b6ed9a7ca2d7467f3c8ff6f", size = 28158, upload-time = "2025-07-30T10:01:48.341Z" }, + { url = "https://files.pythonhosted.org/packages/b3/80/0106a7448abb24a2c467bf7d527fe5413b7fdfa4ad6d6a96a43a62ef3988/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b55aec3565b65f56455eebc9b9f34130440404f27fe21c3b375bf1ea4d8fbae6", size = 32597, upload-time = "2025-07-30T10:01:49.112Z" }, + { url = "https://files.pythonhosted.org/packages/05/b8/d663c9caea07e9180b2cb662772865230715cbd573ba3b5e81793d580316/argon2_cffi_bindings-25.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:87c33a52407e4c41f3b70a9c2d3f6056d88b10dad7695be708c5021673f55623", size = 28231, upload-time = "2025-07-30T10:01:49.92Z" }, + { url = "https://files.pythonhosted.org/packages/1d/57/96b8b9f93166147826da5f90376e784a10582dd39a393c99bb62cfcf52f0/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:aecba1723ae35330a008418a91ea6cfcedf6d31e5fbaa056a166462ff066d500", size = 54121, upload-time = "2025-07-30T10:01:50.815Z" }, + { url = "https://files.pythonhosted.org/packages/0a/08/a9bebdb2e0e602dde230bdde8021b29f71f7841bd54801bcfd514acb5dcf/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2630b6240b495dfab90aebe159ff784d08ea999aa4b0d17efa734055a07d2f44", size = 29177, upload-time = "2025-07-30T10:01:51.681Z" }, + { url = "https://files.pythonhosted.org/packages/b6/02/d297943bcacf05e4f2a94ab6f462831dc20158614e5d067c35d4e63b9acb/argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:7aef0c91e2c0fbca6fc68e7555aa60ef7008a739cbe045541e438373bc54d2b0", size = 31090, upload-time = "2025-07-30T10:01:53.184Z" }, + { url = "https://files.pythonhosted.org/packages/c1/93/44365f3d75053e53893ec6d733e4a5e3147502663554b4d864587c7828a7/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e021e87faa76ae0d413b619fe2b65ab9a037f24c60a1e6cc43457ae20de6dc6", size = 81246, upload-time = "2025-07-30T10:01:54.145Z" }, + { url = "https://files.pythonhosted.org/packages/09/52/94108adfdd6e2ddf58be64f959a0b9c7d4ef2fa71086c38356d22dc501ea/argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e924cfc503018a714f94a49a149fdc0b644eaead5d1f089330399134fa028a", size = 87126, upload-time = "2025-07-30T10:01:55.074Z" }, + { url = "https://files.pythonhosted.org/packages/72/70/7a2993a12b0ffa2a9271259b79cc616e2389ed1a4d93842fac5a1f923ffd/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87b72589133f0346a1cb8d5ecca4b933e3c9b64656c9d175270a000e73b288d", size = 80343, upload-time = "2025-07-30T10:01:56.007Z" }, + { url = "https://files.pythonhosted.org/packages/78/9a/4e5157d893ffc712b74dbd868c7f62365618266982b64accab26bab01edc/argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1db89609c06afa1a214a69a462ea741cf735b29a57530478c06eb81dd403de99", size = 86777, upload-time = "2025-07-30T10:01:56.943Z" }, + { url = "https://files.pythonhosted.org/packages/74/cd/15777dfde1c29d96de7f18edf4cc94c385646852e7c7b0320aa91ccca583/argon2_cffi_bindings-25.1.0-cp39-abi3-win32.whl", hash = "sha256:473bcb5f82924b1becbb637b63303ec8d10e84c8d241119419897a26116515d2", size = 27180, upload-time = "2025-07-30T10:01:57.759Z" }, + { url = "https://files.pythonhosted.org/packages/e2/c6/a759ece8f1829d1f162261226fbfd2c6832b3ff7657384045286d2afa384/argon2_cffi_bindings-25.1.0-cp39-abi3-win_amd64.whl", hash = "sha256:a98cd7d17e9f7ce244c0803cad3c23a7d379c301ba618a5fa76a67d116618b98", size = 31715, upload-time = "2025-07-30T10:01:58.56Z" }, + { url = "https://files.pythonhosted.org/packages/42/b9/f8d6fa329ab25128b7e98fd83a3cb34d9db5b059a9847eddb840a0af45dd/argon2_cffi_bindings-25.1.0-cp39-abi3-win_arm64.whl", hash = "sha256:b0fdbcf513833809c882823f98dc2f931cf659d9a1429616ac3adebb49f5db94", size = 27149, upload-time = "2025-07-30T10:01:59.329Z" }, +] + +[[package]] +name = "arrow" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, + { name = "tzdata" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/33/032cdc44182491aa708d06a68b62434140d8c50820a087fac7af37703357/arrow-1.4.0.tar.gz", hash = "sha256:ed0cc050e98001b8779e84d461b0098c4ac597e88704a655582b21d116e526d7", size = 152931, upload-time = "2025-10-18T17:46:46.761Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ed/c9/d7977eaacb9df673210491da99e6a247e93df98c715fc43fd136ce1d3d33/arrow-1.4.0-py3-none-any.whl", hash = "sha256:749f0769958ebdc79c173ff0b0670d59051a535fa26e8eba02953dc19eb43205", size = 68797, upload-time = "2025-10-18T17:46:45.663Z" }, +] + +[[package]] +name = "asttokens" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/be/a5/8e3f9b6771b0b408517c82d97aed8f2036509bc247d46114925e32fe33f0/asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7", size = 62308, upload-time = "2025-11-15T16:43:48.578Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", size = 27047, upload-time = "2025-11-15T16:43:16.109Z" }, +] + +[[package]] +name = "async-lru" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8a/ca724066c32a53fa75f59e0f21aa822fdaa8a0dffa112d223634e3caabf9/async_lru-2.2.0.tar.gz", hash = "sha256:80abae2a237dbc6c60861d621619af39f0d920aea306de34cb992c879e01370c", size = 14654, upload-time = "2026-02-20T19:11:43.848Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/5c/af990f019b8dd11c5492a6371fe74a5b0276357370030b67254a87329944/async_lru-2.2.0-py3-none-any.whl", hash = "sha256:e2c1cf731eba202b59c5feedaef14ffd9d02ad0037fcda64938699f2c380eafe", size = 7890, upload-time = "2026-02-20T19:11:42.273Z" }, +] + [[package]] name = "attrs" version = "25.4.0" @@ -15,6 +110,45 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, ] +[[package]] +name = "babel" +version = "2.18.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/b2/51899539b6ceeeb420d40ed3cd4b7a40519404f9baf3d4ac99dc413a834b/babel-2.18.0.tar.gz", hash = "sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d", size = 9959554, upload-time = "2026-02-01T12:30:56.078Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl", hash = "sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35", size = 10196845, upload-time = "2026-02-01T12:30:53.445Z" }, +] + +[[package]] +name = "beautifulsoup4" +version = "4.14.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "soupsieve" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c3/b0/1c6a16426d389813b48d95e26898aff79abbde42ad353958ad95cc8c9b21/beautifulsoup4-4.14.3.tar.gz", hash = "sha256:6292b1c5186d356bba669ef9f7f051757099565ad9ada5dd630bd9de5fa7fb86", size = 627737, upload-time = "2025-11-30T15:08:26.084Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1a/39/47f9197bdd44df24d67ac8893641e16f386c984a0619ef2ee4c51fbbc019/beautifulsoup4-4.14.3-py3-none-any.whl", hash = "sha256:0918bfe44902e6ad8d57732ba310582e98da931428d231a5ecb9e7c703a735bb", size = 107721, upload-time = "2025-11-30T15:08:24.087Z" }, +] + +[[package]] +name = "bleach" +version = "6.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "webencodings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/07/18/3c8523962314be6bf4c8989c79ad9531c825210dd13a8669f6b84336e8bd/bleach-6.3.0.tar.gz", hash = "sha256:6f3b91b1c0a02bb9a78b5a454c92506aa0fdf197e1d5e114d2e00c6f64306d22", size = 203533, upload-time = "2025-10-27T17:57:39.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cd/3a/577b549de0cc09d95f11087ee63c739bba856cd3952697eec4c4bb91350a/bleach-6.3.0-py3-none-any.whl", hash = "sha256:fe10ec77c93ddf3d13a73b035abaac7a9f5e436513864ccdad516693213c65d6", size = 164437, upload-time = "2025-10-27T17:57:37.538Z" }, +] + +[package.optional-dependencies] +css = [ + { name = "tinycss2" }, +] + [[package]] name = "cartiflette" version = "0.1.9" @@ -53,6 +187,51 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", size = 159438, upload-time = "2025-11-12T02:54:49.735Z" }, ] +[[package]] +name = "cffi" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, + { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, + { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, + { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, + { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, + { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, + { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, + { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, + { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, + { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, + { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, + { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, + { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" }, + { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" }, + { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, + { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, + { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, + { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, + { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, + { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" }, + { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" }, + { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" }, + { url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" }, + { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, + { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, + { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, + { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, + { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, + { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, +] + [[package]] name = "charset-normalizer" version = "3.4.4" @@ -103,6 +282,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] +[[package]] +name = "comm" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/13/7d740c5849255756bc17888787313b61fd38a0a8304fc4f073dfc46122aa/comm-0.2.3.tar.gz", hash = "sha256:2dc8048c10962d55d7ad693be1e7045d891b7ce8d999c97963a5e3e99c055971", size = 6319, upload-time = "2025-07-25T14:02:04.452Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl", hash = "sha256:c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417", size = 7294, upload-time = "2025-07-25T14:02:02.896Z" }, +] + [[package]] name = "contourpy" version = "1.3.3" @@ -167,6 +355,50 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321, upload-time = "2023-10-07T05:32:16.783Z" }, ] +[[package]] +name = "debugpy" +version = "1.8.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/b7/cd8080344452e4874aae67c40d8940e2b4d47b01601a8fd9f44786c757c7/debugpy-1.8.20.tar.gz", hash = "sha256:55bc8701714969f1ab89a6d5f2f3d40c36f91b2cbe2f65d98bf8196f6a6a2c33", size = 1645207, upload-time = "2026-01-29T23:03:28.199Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/e2/fc500524cc6f104a9d049abc85a0a8b3f0d14c0a39b9c140511c61e5b40b/debugpy-1.8.20-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:5dff4bb27027821fdfcc9e8f87309a28988231165147c31730128b1c983e282a", size = 2539560, upload-time = "2026-01-29T23:03:48.738Z" }, + { url = "https://files.pythonhosted.org/packages/90/83/fb33dcea789ed6018f8da20c5a9bc9d82adc65c0c990faed43f7c955da46/debugpy-1.8.20-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:84562982dd7cf5ebebfdea667ca20a064e096099997b175fe204e86817f64eaf", size = 4293272, upload-time = "2026-01-29T23:03:50.169Z" }, + { url = "https://files.pythonhosted.org/packages/a6/25/b1e4a01bfb824d79a6af24b99ef291e24189080c93576dfd9b1a2815cd0f/debugpy-1.8.20-cp313-cp313-win32.whl", hash = "sha256:da11dea6447b2cadbf8ce2bec59ecea87cc18d2c574980f643f2d2dfe4862393", size = 5331208, upload-time = "2026-01-29T23:03:51.547Z" }, + { url = "https://files.pythonhosted.org/packages/13/f7/a0b368ce54ffff9e9028c098bd2d28cfc5b54f9f6c186929083d4c60ba58/debugpy-1.8.20-cp313-cp313-win_amd64.whl", hash = "sha256:eb506e45943cab2efb7c6eafdd65b842f3ae779f020c82221f55aca9de135ed7", size = 5372930, upload-time = "2026-01-29T23:03:53.585Z" }, + { url = "https://files.pythonhosted.org/packages/33/2e/f6cb9a8a13f5058f0a20fe09711a7b726232cd5a78c6a7c05b2ec726cff9/debugpy-1.8.20-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:9c74df62fc064cd5e5eaca1353a3ef5a5d50da5eb8058fcef63106f7bebe6173", size = 2538066, upload-time = "2026-01-29T23:03:54.999Z" }, + { url = "https://files.pythonhosted.org/packages/c5/56/6ddca50b53624e1ca3ce1d1e49ff22db46c47ea5fb4c0cc5c9b90a616364/debugpy-1.8.20-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:077a7447589ee9bc1ff0cdf443566d0ecf540ac8aa7333b775ebcb8ce9f4ecad", size = 4269425, upload-time = "2026-01-29T23:03:56.518Z" }, + { url = "https://files.pythonhosted.org/packages/c5/d9/d64199c14a0d4c476df46c82470a3ce45c8d183a6796cfb5e66533b3663c/debugpy-1.8.20-cp314-cp314-win32.whl", hash = "sha256:352036a99dd35053b37b7803f748efc456076f929c6a895556932eaf2d23b07f", size = 5331407, upload-time = "2026-01-29T23:03:58.481Z" }, + { url = "https://files.pythonhosted.org/packages/e0/d9/1f07395b54413432624d61524dfd98c1a7c7827d2abfdb8829ac92638205/debugpy-1.8.20-cp314-cp314-win_amd64.whl", hash = "sha256:a98eec61135465b062846112e5ecf2eebb855305acc1dfbae43b72903b8ab5be", size = 5372521, upload-time = "2026-01-29T23:03:59.864Z" }, + { url = "https://files.pythonhosted.org/packages/e0/c3/7f67dea8ccf8fdcb9c99033bbe3e90b9e7395415843accb81428c441be2d/debugpy-1.8.20-py2.py3-none-any.whl", hash = "sha256:5be9bed9ae3be00665a06acaa48f8329d2b9632f15fd09f6a9a8c8d9907e54d7", size = 5337658, upload-time = "2026-01-29T23:04:17.404Z" }, +] + +[[package]] +name = "decorator" +version = "5.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/fa/6d96a0978d19e17b68d634497769987b16c8f4cd0a7a05048bec693caa6b/decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", size = 56711, upload-time = "2025-02-24T04:41:34.073Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190, upload-time = "2025-02-24T04:41:32.565Z" }, +] + +[[package]] +name = "defusedxml" +version = "0.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0f/d5/c66da9b79e5bdb124974bfe172b4daf3c984ebd9c2a06e2b8a4dc7331c72/defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", size = 75520, upload-time = "2021-03-08T10:59:26.269Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" }, +] + +[[package]] +name = "executing" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, +] + [[package]] name = "fastexcel" version = "0.19.0" @@ -185,6 +417,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/48/38/b3faa12a74f387e037ff33adae761c22fc3aa44eed15a2c09d653b4eb194/fastexcel-0.19.0-cp314-cp314t-win_amd64.whl", hash = "sha256:7ef8e41cb0118f90d5f9a636fcdc0e9d635938cdaa54a3182328f3d34ce9ee1a", size = 2897686, upload-time = "2026-01-20T11:17:35.453Z" }, ] +[[package]] +name = "fastjsonschema" +version = "2.21.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/b5/23b216d9d985a956623b6bd12d4086b60f0059b27799f23016af04a74ea1/fastjsonschema-2.21.2.tar.gz", hash = "sha256:b1eb43748041c880796cd077f1a07c3d94e93ae84bba5ed36800a33554ae05de", size = 374130, upload-time = "2025-08-14T18:49:36.666Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cb/a8/20d0723294217e47de6d9e2e40fd4a9d2f7c4b6ef974babd482a59743694/fastjsonschema-2.21.2-py3-none-any.whl", hash = "sha256:1c797122d0a86c5cace2e54bf4e819c36223b552017172f32c5c024a6b77e463", size = 24024, upload-time = "2025-08-14T18:49:34.776Z" }, +] + [[package]] name = "fonttools" version = "4.61.1" @@ -226,6 +467,7 @@ dependencies = [ { name = "cartiflette" }, { name = "fastexcel" }, { name = "geopandas" }, + { name = "jupyter" }, { name = "matplotlib" }, { name = "numpy" }, { name = "pandas" }, @@ -243,6 +485,7 @@ requires-dist = [ { name = "cartiflette", specifier = ">=0.1.9" }, { name = "fastexcel", specifier = ">=0.19.0" }, { name = "geopandas", specifier = ">=1.1.1" }, + { name = "jupyter", specifier = ">=1.1.1" }, { name = "matplotlib" }, { name = "numpy" }, { name = "pandas" }, @@ -256,6 +499,15 @@ requires-dist = [ { name = "xlrd", specifier = ">=2.0.2" }, ] +[[package]] +name = "fqdn" +version = "1.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/3e/a80a8c077fd798951169626cde3e239adeba7dab75deb3555716415bd9b0/fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f", size = 6015, upload-time = "2021-03-11T07:16:29.08Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/58/8acf1b3e91c58313ce5cb67df61001fc9dcd21be4fadb76c1a2d540e09ed/fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014", size = 9121, upload-time = "2021-03-11T07:16:28.351Z" }, +] + [[package]] name = "geopandas" version = "1.1.1" @@ -273,22 +525,424 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0b/70/d5cd0696eff08e62fdbdebe5b46527facb4e7220eabe0ac6225efab50168/geopandas-1.1.1-py3-none-any.whl", hash = "sha256:589e61aaf39b19828843df16cb90234e72897e2579be236f10eee0d052ad98e8", size = 338365, upload-time = "2025-06-26T21:04:55.139Z" }, ] +[[package]] +name = "h11" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, +] + +[[package]] +name = "httpx" +version = "0.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "certifi" }, + { name = "httpcore" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, +] + [[package]] name = "idna" version = "3.11" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, + { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, +] + +[[package]] +name = "ipykernel" +version = "7.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "appnope", marker = "sys_platform == 'darwin'" }, + { name = "comm" }, + { name = "debugpy" }, + { name = "ipython" }, + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "matplotlib-inline" }, + { name = "nest-asyncio" }, + { name = "packaging" }, + { name = "psutil" }, + { name = "pyzmq" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ca/8d/b68b728e2d06b9e0051019640a40a9eb7a88fcd82c2e1b5ce70bef5ff044/ipykernel-7.2.0.tar.gz", hash = "sha256:18ed160b6dee2cbb16e5f3575858bc19d8f1fe6046a9a680c708494ce31d909e", size = 176046, upload-time = "2026-02-06T16:43:27.403Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl", hash = "sha256:3bbd4420d2b3cc105cbdf3756bfc04500b1e52f090a90716851f3916c62e1661", size = 118788, upload-time = "2026-02-06T16:43:25.149Z" }, +] + +[[package]] +name = "ipython" +version = "9.10.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "decorator" }, + { name = "ipython-pygments-lexers" }, + { name = "jedi" }, + { name = "matplotlib-inline" }, + { name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "prompt-toolkit" }, + { name = "pygments" }, + { name = "stack-data" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a6/60/2111715ea11f39b1535bed6024b7dec7918b71e5e5d30855a5b503056b50/ipython-9.10.0.tar.gz", hash = "sha256:cd9e656be97618a0676d058134cd44e6dc7012c0e5cb36a9ce96a8c904adaf77", size = 4426526, upload-time = "2026-02-02T10:00:33.594Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/aa/898dec789a05731cd5a9f50605b7b44a72bd198fd0d4528e11fc610177cc/ipython-9.10.0-py3-none-any.whl", hash = "sha256:c6ab68cc23bba8c7e18e9b932797014cc61ea7fd6f19de180ab9ba73e65ee58d", size = 622774, upload-time = "2026-02-02T10:00:31.503Z" }, +] + +[[package]] +name = "ipython-pygments-lexers" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393, upload-time = "2025-01-17T11:24:34.505Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" }, +] + +[[package]] +name = "ipywidgets" +version = "8.1.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "comm" }, + { name = "ipython" }, + { name = "jupyterlab-widgets" }, + { name = "traitlets" }, + { name = "widgetsnbextension" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4c/ae/c5ce1edc1afe042eadb445e95b0671b03cee61895264357956e61c0d2ac0/ipywidgets-8.1.8.tar.gz", hash = "sha256:61f969306b95f85fba6b6986b7fe45d73124d1d9e3023a8068710d47a22ea668", size = 116739, upload-time = "2025-11-01T21:18:12.393Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/56/6d/0d9848617b9f753b87f214f1c682592f7ca42de085f564352f10f0843026/ipywidgets-8.1.8-py3-none-any.whl", hash = "sha256:ecaca67aed704a338f88f67b1181b58f821ab5dc89c1f0f5ef99db43c1c2921e", size = 139808, upload-time = "2025-11-01T21:18:10.956Z" }, +] + +[[package]] +name = "isoduration" +version = "20.11.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "arrow" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7c/1a/3c8edc664e06e6bd06cce40c6b22da5f1429aa4224d0c590f3be21c91ead/isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9", size = 11649, upload-time = "2020-11-01T11:00:00.312Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042", size = 11321, upload-time = "2020-11-01T10:59:58.02Z" }, +] + +[[package]] +name = "jedi" +version = "0.19.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "parso" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/72/3a/79a912fbd4d8dd6fbb02bf69afd3bb72cf0c729bb3063c6f4498603db17a/jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0", size = 1231287, upload-time = "2024-11-11T01:41:42.873Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9", size = 1572278, upload-time = "2024-11-11T01:41:40.175Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "joblib" +version = "1.5.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/41/f2/d34e8b3a08a9cc79a50b2208a93dce981fe615b64d5a4d4abee421d898df/joblib-1.5.3.tar.gz", hash = "sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3", size = 331603, upload-time = "2025-12-15T08:41:46.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713", size = 309071, upload-time = "2025-12-15T08:41:44.973Z" }, +] + +[[package]] +name = "json5" +version = "0.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/77/e8/a3f261a66e4663f22700bc8a17c08cb83e91fbf086726e7a228398968981/json5-0.13.0.tar.gz", hash = "sha256:b1edf8d487721c0bf64d83c28e91280781f6e21f4a797d3261c7c828d4c165bf", size = 52441, upload-time = "2026-01-01T19:42:14.99Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d7/9e/038522f50ceb7e74f1f991bf1b699f24b0c2bbe7c390dd36ad69f4582258/json5-0.13.0-py3-none-any.whl", hash = "sha256:9a08e1dd65f6a4d4c6fa82d216cf2477349ec2346a38fd70cc11d2557499fbcc", size = 36163, upload-time = "2026-01-01T19:42:13.962Z" }, +] + +[[package]] +name = "jsonpointer" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6a/0a/eebeb1fa92507ea94016a2a790b93c2ae41a7e18778f85471dc54475ed25/jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef", size = 9114, upload-time = "2024-06-10T19:24:42.462Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/92/5e77f98553e9e75130c78900d000368476aed74276eb8ae8796f65f00918/jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942", size = 7595, upload-time = "2024-06-10T19:24:40.698Z" }, +] + +[[package]] +name = "jsonschema" +version = "4.26.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/fc/e067678238fa451312d4c62bf6e6cf5ec56375422aee02f9cb5f909b3047/jsonschema-4.26.0.tar.gz", hash = "sha256:0c26707e2efad8aa1bfc5b7ce170f3fccc2e4918ff85989ba9ffa9facb2be326", size = 366583, upload-time = "2026-01-07T13:41:07.246Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" }, +] + +[package.optional-dependencies] +format-nongpl = [ + { name = "fqdn" }, + { name = "idna" }, + { name = "isoduration" }, + { name = "jsonpointer" }, + { name = "rfc3339-validator" }, + { name = "rfc3986-validator" }, + { name = "rfc3987-syntax" }, + { name = "uri-template" }, + { name = "webcolors" }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2025.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/74/a633ee74eb36c44aa6d1095e7cc5569bebf04342ee146178e2d36600708b/jsonschema_specifications-2025.9.1.tar.gz", hash = "sha256:b540987f239e745613c7a9176f3edb72b832a4ac465cf02712288397832b5e8d", size = 32855, upload-time = "2025-09-08T01:34:59.186Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, +] + +[[package]] +name = "jupyter" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ipykernel" }, + { name = "ipywidgets" }, + { name = "jupyter-console" }, + { name = "jupyterlab" }, + { name = "nbconvert" }, + { name = "notebook" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/58/f3/af28ea964ab8bc1e472dba2e82627d36d470c51f5cd38c37502eeffaa25e/jupyter-1.1.1.tar.gz", hash = "sha256:d55467bceabdea49d7e3624af7e33d59c37fff53ed3a350e1ac957bed731de7a", size = 5714959, upload-time = "2024-08-30T07:15:48.299Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/64/285f20a31679bf547b75602702f7800e74dbabae36ef324f716c02804753/jupyter-1.1.1-py2.py3-none-any.whl", hash = "sha256:7a59533c22af65439b24bbe60373a4e95af8f16ac65a6c00820ad378e3f7cc83", size = 2657, upload-time = "2024-08-30T07:15:47.045Z" }, +] + +[[package]] +name = "jupyter-client" +version = "8.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-core" }, + { name = "python-dateutil" }, + { name = "pyzmq" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/05/e4/ba649102a3bc3fbca54e7239fb924fd434c766f855693d86de0b1f2bec81/jupyter_client-8.8.0.tar.gz", hash = "sha256:d556811419a4f2d96c869af34e854e3f059b7cc2d6d01a9cd9c85c267691be3e", size = 348020, upload-time = "2026-01-08T13:55:47.938Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl", hash = "sha256:f93a5b99c5e23a507b773d3a1136bd6e16c67883ccdbd9a829b0bbdb98cd7d7a", size = 107371, upload-time = "2026-01-08T13:55:45.562Z" }, +] + +[[package]] +name = "jupyter-console" +version = "6.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ipykernel" }, + { name = "ipython" }, + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "prompt-toolkit" }, + { name = "pygments" }, + { name = "pyzmq" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bd/2d/e2fd31e2fc41c14e2bcb6c976ab732597e907523f6b2420305f9fc7fdbdb/jupyter_console-6.6.3.tar.gz", hash = "sha256:566a4bf31c87adbfadf22cdf846e3069b59a71ed5da71d6ba4d8aaad14a53539", size = 34363, upload-time = "2023-03-06T14:13:31.02Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ca/77/71d78d58f15c22db16328a476426f7ac4a60d3a5a7ba3b9627ee2f7903d4/jupyter_console-6.6.3-py3-none-any.whl", hash = "sha256:309d33409fcc92ffdad25f0bcdf9a4a9daa61b6f341177570fdac03de5352485", size = 24510, upload-time = "2023-03-06T14:13:28.229Z" }, +] + +[[package]] +name = "jupyter-core" +version = "5.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "platformdirs" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/49/9d1284d0dc65e2c757b74c6687b6d319b02f822ad039e5c512df9194d9dd/jupyter_core-5.9.1.tar.gz", hash = "sha256:4d09aaff303b9566c3ce657f580bd089ff5c91f5f89cf7d8846c3cdf465b5508", size = 89814, upload-time = "2025-10-16T19:19:18.444Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl", hash = "sha256:ebf87fdc6073d142e114c72c9e29a9d7ca03fad818c5d300ce2adc1fb0743407", size = 29032, upload-time = "2025-10-16T19:19:16.783Z" }, +] + +[[package]] +name = "jupyter-events" +version = "0.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jsonschema", extra = ["format-nongpl"] }, + { name = "packaging" }, + { name = "python-json-logger" }, + { name = "pyyaml" }, + { name = "referencing" }, + { name = "rfc3339-validator" }, + { name = "rfc3986-validator" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9d/c3/306d090461e4cf3cd91eceaff84bede12a8e52cd821c2d20c9a4fd728385/jupyter_events-0.12.0.tar.gz", hash = "sha256:fc3fce98865f6784c9cd0a56a20644fc6098f21c8c33834a8d9fe383c17e554b", size = 62196, upload-time = "2025-02-03T17:23:41.485Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/48/577993f1f99c552f18a0428731a755e06171f9902fa118c379eb7c04ea22/jupyter_events-0.12.0-py3-none-any.whl", hash = "sha256:6464b2fa5ad10451c3d35fabc75eab39556ae1e2853ad0c0cc31b656731a97fb", size = 19430, upload-time = "2025-02-03T17:23:38.643Z" }, +] + +[[package]] +name = "jupyter-lsp" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-server" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/5a/9066c9f8e94ee517133cd98dba393459a16cd48bba71a82f16a65415206c/jupyter_lsp-2.3.0.tar.gz", hash = "sha256:458aa59339dc868fb784d73364f17dbce8836e906cd75fd471a325cba02e0245", size = 54823, upload-time = "2025-08-27T17:47:34.671Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1a/60/1f6cee0c46263de1173894f0fafcb3475ded276c472c14d25e0280c18d6d/jupyter_lsp-2.3.0-py3-none-any.whl", hash = "sha256:e914a3cb2addf48b1c7710914771aaf1819d46b2e5a79b0f917b5478ec93f34f", size = 76687, upload-time = "2025-08-27T17:47:33.15Z" }, +] + +[[package]] +name = "jupyter-server" +version = "2.17.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "argon2-cffi" }, + { name = "jinja2" }, + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "jupyter-events" }, + { name = "jupyter-server-terminals" }, + { name = "nbconvert" }, + { name = "nbformat" }, + { name = "packaging" }, + { name = "prometheus-client" }, + { name = "pywinpty", marker = "os_name == 'nt'" }, + { name = "pyzmq" }, + { name = "send2trash" }, + { name = "terminado" }, + { name = "tornado" }, + { name = "traitlets" }, + { name = "websocket-client" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/ac/e040ec363d7b6b1f11304cc9f209dac4517ece5d5e01821366b924a64a50/jupyter_server-2.17.0.tar.gz", hash = "sha256:c38ea898566964c888b4772ae1ed58eca84592e88251d2cfc4d171f81f7e99d5", size = 731949, upload-time = "2025-08-21T14:42:54.042Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/80/a24767e6ca280f5a49525d987bf3e4d7552bf67c8be07e8ccf20271f8568/jupyter_server-2.17.0-py3-none-any.whl", hash = "sha256:e8cb9c7db4251f51ed307e329b81b72ccf2056ff82d50524debde1ee1870e13f", size = 388221, upload-time = "2025-08-21T14:42:52.034Z" }, +] + +[[package]] +name = "jupyter-server-terminals" +version = "0.5.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pywinpty", marker = "os_name == 'nt'" }, + { name = "terminado" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f4/a7/bcd0a9b0cbba88986fe944aaaf91bfda603e5a50bda8ed15123f381a3b2f/jupyter_server_terminals-0.5.4.tar.gz", hash = "sha256:bbda128ed41d0be9020349f9f1f2a4ab9952a73ed5f5ac9f1419794761fb87f5", size = 31770, upload-time = "2026-01-14T16:53:20.213Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/2d/6674563f71c6320841fc300911a55143925112a72a883e2ca71fba4c618d/jupyter_server_terminals-0.5.4-py3-none-any.whl", hash = "sha256:55be353fc74a80bc7f3b20e6be50a55a61cd525626f578dcb66a5708e2007d14", size = 13704, upload-time = "2026-01-14T16:53:18.738Z" }, +] + +[[package]] +name = "jupyterlab" +version = "4.5.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "async-lru" }, + { name = "httpx" }, + { name = "ipykernel" }, + { name = "jinja2" }, + { name = "jupyter-core" }, + { name = "jupyter-lsp" }, + { name = "jupyter-server" }, + { name = "jupyterlab-server" }, + { name = "notebook-shim" }, + { name = "packaging" }, + { name = "setuptools" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6e/2d/953a5612a34a3c799a62566a548e711d103f631672fd49650e0f2de80870/jupyterlab-4.5.5.tar.gz", hash = "sha256:eac620698c59eb810e1729909be418d9373d18137cac66637141abba613b3fda", size = 23968441, upload-time = "2026-02-23T18:57:34.339Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/52/372d3494766d690dfdd286871bf5f7fb9a6c61f7566ccaa7153a163dd1df/jupyterlab-4.5.5-py3-none-any.whl", hash = "sha256:a35694a40a8e7f2e82f387472af24e61b22adcce87b5a8ab97a5d9c486202a6d", size = 12446824, upload-time = "2026-02-23T18:57:30.398Z" }, +] + +[[package]] +name = "jupyterlab-pygments" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/90/51/9187be60d989df97f5f0aba133fa54e7300f17616e065d1ada7d7646b6d6/jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d", size = 512900, upload-time = "2023-11-23T09:26:37.44Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b1/dd/ead9d8ea85bf202d90cc513b533f9c363121c7792674f78e0d8a854b63b4/jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780", size = 15884, upload-time = "2023-11-23T09:26:34.325Z" }, +] + +[[package]] +name = "jupyterlab-server" +version = "2.28.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "babel" }, + { name = "jinja2" }, + { name = "json5" }, + { name = "jsonschema" }, + { name = "jupyter-server" }, + { name = "packaging" }, + { name = "requests" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d6/2c/90153f189e421e93c4bb4f9e3f59802a1f01abd2ac5cf40b152d7f735232/jupyterlab_server-2.28.0.tar.gz", hash = "sha256:35baa81898b15f93573e2deca50d11ac0ae407ebb688299d3a5213265033712c", size = 76996, upload-time = "2025-10-22T13:59:18.37Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/07/a000fe835f76b7e1143242ab1122e6362ef1c03f23f83a045c38859c2ae0/jupyterlab_server-2.28.0-py3-none-any.whl", hash = "sha256:e4355b148fdcf34d312bbbc80f22467d6d20460e8b8736bf235577dd18506968", size = 59830, upload-time = "2025-10-22T13:59:16.767Z" }, ] [[package]] -name = "joblib" -version = "1.5.3" +name = "jupyterlab-widgets" +version = "3.0.16" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/41/f2/d34e8b3a08a9cc79a50b2208a93dce981fe615b64d5a4d4abee421d898df/joblib-1.5.3.tar.gz", hash = "sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3", size = 331603, upload-time = "2025-12-15T08:41:46.427Z" } +sdist = { url = "https://files.pythonhosted.org/packages/26/2d/ef58fed122b268c69c0aa099da20bc67657cdfb2e222688d5731bd5b971d/jupyterlab_widgets-3.0.16.tar.gz", hash = "sha256:423da05071d55cf27a9e602216d35a3a65a3e41cdf9c5d3b643b814ce38c19e0", size = 897423, upload-time = "2025-11-01T21:11:29.724Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713", size = 309071, upload-time = "2025-12-15T08:41:44.973Z" }, + { url = "https://files.pythonhosted.org/packages/ab/b5/36c712098e6191d1b4e349304ef73a8d06aed77e56ceaac8c0a306c7bda1/jupyterlab_widgets-3.0.16-py3-none-any.whl", hash = "sha256:45fa36d9c6422cf2559198e4db481aa243c7a32d9926b500781c830c80f7ecf8", size = 914926, upload-time = "2025-11-01T21:11:28.008Z" }, ] [[package]] @@ -350,6 +1004,67 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/80/be/3578e8afd18c88cdf9cb4cffde75a96d2be38c5a903f1ed0ceec061bd09e/kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32", size = 70260, upload-time = "2025-08-10T21:27:36.606Z" }, ] +[[package]] +name = "lark" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/34/28fff3ab31ccff1fd4f6c7c7b0ceb2b6968d8ea4950663eadcb5720591a0/lark-1.3.1.tar.gz", hash = "sha256:b426a7a6d6d53189d318f2b6236ab5d6429eaf09259f1ca33eb716eed10d2905", size = 382732, upload-time = "2025-10-27T18:25:56.653Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/3d/14ce75ef66813643812f3093ab17e46d3a206942ce7376d31ec2d36229e7/lark-1.3.1-py3-none-any.whl", hash = "sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12", size = 113151, upload-time = "2025-10-27T18:25:54.882Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, + { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, + { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, + { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, + { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, + { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, + { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, + { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, + { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, + { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, + { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, + { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, + { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, + { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, + { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, + { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, + { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, + { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, + { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, + { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, + { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, + { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, + { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, + { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, + { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, + { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, + { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, + { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, + { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, + { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, + { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, + { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, +] + [[package]] name = "matplotlib" version = "3.10.8" @@ -397,6 +1112,27 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5d/49/d651878698a0b67f23aa28e17f45a6d6dd3d3f933fa29087fa4ce5947b5a/matplotlib-3.10.8-cp314-cp314t-win_arm64.whl", hash = "sha256:113bb52413ea508ce954a02c10ffd0d565f9c3bc7f2eddc27dfe1731e71c7b5f", size = 8192560, upload-time = "2025-12-10T22:56:38.008Z" }, ] +[[package]] +name = "matplotlib-inline" +version = "0.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c7/74/97e72a36efd4ae2bccb3463284300f8953f199b5ffbc04cbbb0ec78f74b1/matplotlib_inline-0.2.1.tar.gz", hash = "sha256:e1ee949c340d771fc39e241ea75683deb94762c8fa5f2927ec57c83c4dffa9fe", size = 8110, upload-time = "2025-10-23T09:00:22.126Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/33/ee4519fa02ed11a94aef9559552f3b17bb863f2ecfe1a35dc7f548cde231/matplotlib_inline-0.2.1-py3-none-any.whl", hash = "sha256:d56ce5156ba6085e00a9d54fead6ed29a9c47e215cd1bba2e976ef39f5710a76", size = 9516, upload-time = "2025-10-23T09:00:20.675Z" }, +] + +[[package]] +name = "mistune" +version = "3.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9d/55/d01f0c4b45ade6536c51170b9043db8b2ec6ddf4a35c7ea3f5f559ac935b/mistune-3.2.0.tar.gz", hash = "sha256:708487c8a8cdd99c9d90eb3ed4c3ed961246ff78ac82f03418f5183ab70e398a", size = 95467, upload-time = "2025-12-23T11:36:34.994Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/f7/4a5e785ec9fbd65146a27b6b70b6cdc161a66f2024e4b04ac06a67f5578b/mistune-3.2.0-py3-none-any.whl", hash = "sha256:febdc629a3c78616b94393c6580551e0e34cc289987ec6c35ed3f4be42d0eee1", size = 53598, upload-time = "2025-12-23T11:36:33.211Z" }, +] + [[package]] name = "mizani" version = "0.14.3" @@ -412,6 +1148,98 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5c/d2/4ffcaa27c8a4b4f9ad456da4821c76dfbdfada23e8210cd4d80e1eb3236a/mizani-0.14.3-py3-none-any.whl", hash = "sha256:6d2ca9b1b8366ff85668f0cc1b6095f1e702e26e66f132c4f02a949efa32a688", size = 133433, upload-time = "2025-10-30T20:16:51.218Z" }, ] +[[package]] +name = "nbclient" +version = "0.10.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "nbformat" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/56/91/1c1d5a4b9a9ebba2b4e32b8c852c2975c872aec1fe42ab5e516b2cecd193/nbclient-0.10.4.tar.gz", hash = "sha256:1e54091b16e6da39e297b0ece3e10f6f29f4ac4e8ee515d29f8a7099bd6553c9", size = 62554, upload-time = "2025-12-23T07:45:46.369Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/a0/5b0c2f11142ed1dddec842457d3f65eaf71a0080894eb6f018755b319c3a/nbclient-0.10.4-py3-none-any.whl", hash = "sha256:9162df5a7373d70d606527300a95a975a47c137776cd942e52d9c7e29ff83440", size = 25465, upload-time = "2025-12-23T07:45:44.51Z" }, +] + +[[package]] +name = "nbconvert" +version = "7.17.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beautifulsoup4" }, + { name = "bleach", extra = ["css"] }, + { name = "defusedxml" }, + { name = "jinja2" }, + { name = "jupyter-core" }, + { name = "jupyterlab-pygments" }, + { name = "markupsafe" }, + { name = "mistune" }, + { name = "nbclient" }, + { name = "nbformat" }, + { name = "packaging" }, + { name = "pandocfilters" }, + { name = "pygments" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/38/47/81f886b699450d0569f7bc551df2b1673d18df7ff25cc0c21ca36ed8a5ff/nbconvert-7.17.0.tar.gz", hash = "sha256:1b2696f1b5be12309f6c7d707c24af604b87dfaf6d950794c7b07acab96dda78", size = 862855, upload-time = "2026-01-29T16:37:48.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0d/4b/8d5f796a792f8a25f6925a96032f098789f448571eb92011df1ae59e8ea8/nbconvert-7.17.0-py3-none-any.whl", hash = "sha256:4f99a63b337b9a23504347afdab24a11faa7d86b405e5c8f9881cd313336d518", size = 261510, upload-time = "2026-01-29T16:37:46.322Z" }, +] + +[[package]] +name = "nbformat" +version = "5.10.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fastjsonschema" }, + { name = "jsonschema" }, + { name = "jupyter-core" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6d/fd/91545e604bc3dad7dca9ed03284086039b294c6b3d75c0d2fa45f9e9caf3/nbformat-5.10.4.tar.gz", hash = "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a", size = 142749, upload-time = "2024-04-04T11:20:37.371Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a9/82/0340caa499416c78e5d8f5f05947ae4bc3cba53c9f038ab6e9ed964e22f1/nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b", size = 78454, upload-time = "2024-04-04T11:20:34.895Z" }, +] + +[[package]] +name = "nest-asyncio" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/83/f8/51569ac65d696c8ecbee95938f89d4abf00f47d58d48f6fbabfe8f0baefe/nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", size = 7418, upload-time = "2024-01-21T14:25:19.227Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195, upload-time = "2024-01-21T14:25:17.223Z" }, +] + +[[package]] +name = "notebook" +version = "7.5.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-server" }, + { name = "jupyterlab" }, + { name = "jupyterlab-server" }, + { name = "notebook-shim" }, + { name = "tornado" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/78/08/9d446fbb49f95de316ea6d7f25d0a4bc95117dd574e35f405895ac706f29/notebook-7.5.4.tar.gz", hash = "sha256:b928b2ba22cb63aa83df2e0e76fe3697950a0c1c4a41b84ebccf1972b1bb5771", size = 14167892, upload-time = "2026-02-24T14:13:56.116Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/59/01/05e5387b53e0f549212d5eff58845886f3827617b5c9409c966ddc07cb6d/notebook-7.5.4-py3-none-any.whl", hash = "sha256:860e31782b3d3a25ca0819ff039f5cf77845d1bf30c78ef9528b88b25e0a9850", size = 14578014, upload-time = "2026-02-24T14:13:52.274Z" }, +] + +[[package]] +name = "notebook-shim" +version = "0.2.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-server" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/54/d2/92fa3243712b9a3e8bafaf60aac366da1cada3639ca767ff4b5b3654ec28/notebook_shim-0.2.4.tar.gz", hash = "sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb", size = 13167, upload-time = "2024-02-14T23:35:18.353Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/33/bd5b9137445ea4b680023eb0469b2bb969d61303dedb2aac6560ff3d14a1/notebook_shim-0.2.4-py3-none-any.whl", hash = "sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef", size = 13307, upload-time = "2024-02-14T23:35:16.286Z" }, +] + [[package]] name = "numpy" version = "2.3.5" @@ -513,6 +1341,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/70/44/5191d2e4026f86a2a109053e194d3ba7a31a2d10a9c2348368c63ed4e85a/pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87", size = 13202175, upload-time = "2025-09-29T23:31:59.173Z" }, ] +[[package]] +name = "pandocfilters" +version = "1.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/70/6f/3dd4940bbe001c06a65f88e36bad298bc7a0de5036115639926b0c5c0458/pandocfilters-1.5.1.tar.gz", hash = "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e", size = 8454, upload-time = "2024-01-18T20:08:13.726Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/af/4fbc8cab944db5d21b7e2a5b8e9211a03a79852b1157e2c102fcc61ac440/pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc", size = 8663, upload-time = "2024-01-18T20:08:11.28Z" }, +] + +[[package]] +name = "parso" +version = "0.8.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/81/76/a1e769043c0c0c9fe391b702539d594731a4362334cdf4dc25d0c09761e7/parso-0.8.6.tar.gz", hash = "sha256:2b9a0332696df97d454fa67b81618fd69c35a7b90327cbe6ba5c92d2c68a7bfd", size = 401621, upload-time = "2026-02-09T15:45:24.425Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b6/61/fae042894f4296ec49e3f193aff5d7c18440da9e48102c3315e1bc4519a7/parso-0.8.6-py2.py3-none-any.whl", hash = "sha256:2c549f800b70a5c4952197248825584cb00f033b29c692671d3bf08bf380baff", size = 106894, upload-time = "2026-02-09T15:45:21.391Z" }, +] + [[package]] name = "patsy" version = "1.0.2" @@ -525,6 +1371,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f1/70/ba4b949bdc0490ab78d545459acd7702b211dfccf7eb89bbc1060f52818d/patsy-1.0.2-py2.py3-none-any.whl", hash = "sha256:37bfddbc58fcf0362febb5f54f10743f8b21dd2aa73dec7e7ef59d1b02ae668a", size = 233301, upload-time = "2025-10-20T16:17:36.563Z" }, ] +[[package]] +name = "pexpect" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ptyprocess" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" }, +] + [[package]] name = "pillow" version = "12.0.0" @@ -635,6 +1493,73 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d8/a12e6aa14f63784cead437083319ec7cece0d5bb9a5bfe7678cc6578b52a/polars_runtime_32-1.36.1-cp39-abi3-win_arm64.whl", hash = "sha256:809e73857be71250141225ddd5d2b30c97e6340aeaa0d445f930e01bef6888dc", size = 39798896, upload-time = "2025-12-10T01:14:11.568Z" }, ] +[[package]] +name = "prometheus-client" +version = "0.24.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f0/58/a794d23feb6b00fc0c72787d7e87d872a6730dd9ed7c7b3e954637d8f280/prometheus_client-0.24.1.tar.gz", hash = "sha256:7e0ced7fbbd40f7b84962d5d2ab6f17ef88a72504dcf7c0b40737b43b2a461f9", size = 85616, upload-time = "2026-01-14T15:26:26.965Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/74/c3/24a2f845e3917201628ecaba4f18bab4d18a337834c1df2a159ee9d22a42/prometheus_client-0.24.1-py3-none-any.whl", hash = "sha256:150db128af71a5c2482b36e588fc8a6b95e498750da4b17065947c16070f4055", size = 64057, upload-time = "2026-01-14T15:26:24.42Z" }, +] + +[[package]] +name = "prompt-toolkit" +version = "3.0.52" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, +] + +[[package]] +name = "psutil" +version = "7.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/c6/d1ddf4abb55e93cebc4f2ed8b5d6dbad109ecb8d63748dd2b20ab5e57ebe/psutil-7.2.2.tar.gz", hash = "sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372", size = 493740, upload-time = "2026-01-28T18:14:54.428Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/08/510cbdb69c25a96f4ae523f733cdc963ae654904e8db864c07585ef99875/psutil-7.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2edccc433cbfa046b980b0df0171cd25bcaeb3a68fe9022db0979e7aa74a826b", size = 130595, upload-time = "2026-01-28T18:14:57.293Z" }, + { url = "https://files.pythonhosted.org/packages/d6/f5/97baea3fe7a5a9af7436301f85490905379b1c6f2dd51fe3ecf24b4c5fbf/psutil-7.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78c8603dcd9a04c7364f1a3e670cea95d51ee865e4efb3556a3a63adef958ea", size = 131082, upload-time = "2026-01-28T18:14:59.732Z" }, + { url = "https://files.pythonhosted.org/packages/37/d6/246513fbf9fa174af531f28412297dd05241d97a75911ac8febefa1a53c6/psutil-7.2.2-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a571f2330c966c62aeda00dd24620425d4b0cc86881c89861fbc04549e5dc63", size = 181476, upload-time = "2026-01-28T18:15:01.884Z" }, + { url = "https://files.pythonhosted.org/packages/b8/b5/9182c9af3836cca61696dabe4fd1304e17bc56cb62f17439e1154f225dd3/psutil-7.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:917e891983ca3c1887b4ef36447b1e0873e70c933afc831c6b6da078ba474312", size = 184062, upload-time = "2026-01-28T18:15:04.436Z" }, + { url = "https://files.pythonhosted.org/packages/16/ba/0756dca669f5a9300d0cbcbfae9a4c30e446dfc7440ffe43ded5724bfd93/psutil-7.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:ab486563df44c17f5173621c7b198955bd6b613fb87c71c161f827d3fb149a9b", size = 139893, upload-time = "2026-01-28T18:15:06.378Z" }, + { url = "https://files.pythonhosted.org/packages/1c/61/8fa0e26f33623b49949346de05ec1ddaad02ed8ba64af45f40a147dbfa97/psutil-7.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:ae0aefdd8796a7737eccea863f80f81e468a1e4cf14d926bd9b6f5f2d5f90ca9", size = 135589, upload-time = "2026-01-28T18:15:08.03Z" }, + { url = "https://files.pythonhosted.org/packages/81/69/ef179ab5ca24f32acc1dac0c247fd6a13b501fd5534dbae0e05a1c48b66d/psutil-7.2.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00", size = 130664, upload-time = "2026-01-28T18:15:09.469Z" }, + { url = "https://files.pythonhosted.org/packages/7b/64/665248b557a236d3fa9efc378d60d95ef56dd0a490c2cd37dafc7660d4a9/psutil-7.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7b6d09433a10592ce39b13d7be5a54fbac1d1228ed29abc880fb23df7cb694c9", size = 131087, upload-time = "2026-01-28T18:15:11.724Z" }, + { url = "https://files.pythonhosted.org/packages/d5/2e/e6782744700d6759ebce3043dcfa661fb61e2fb752b91cdeae9af12c2178/psutil-7.2.2-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fa4ecf83bcdf6e6c8f4449aff98eefb5d0604bf88cb883d7da3d8d2d909546a", size = 182383, upload-time = "2026-01-28T18:15:13.445Z" }, + { url = "https://files.pythonhosted.org/packages/57/49/0a41cefd10cb7505cdc04dab3eacf24c0c2cb158a998b8c7b1d27ee2c1f5/psutil-7.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e452c464a02e7dc7822a05d25db4cde564444a67e58539a00f929c51eddda0cf", size = 185210, upload-time = "2026-01-28T18:15:16.002Z" }, + { url = "https://files.pythonhosted.org/packages/dd/2c/ff9bfb544f283ba5f83ba725a3c5fec6d6b10b8f27ac1dc641c473dc390d/psutil-7.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c7663d4e37f13e884d13994247449e9f8f574bc4655d509c3b95e9ec9e2b9dc1", size = 141228, upload-time = "2026-01-28T18:15:18.385Z" }, + { url = "https://files.pythonhosted.org/packages/f2/fc/f8d9c31db14fcec13748d373e668bc3bed94d9077dbc17fb0eebc073233c/psutil-7.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:11fe5a4f613759764e79c65cf11ebdf26e33d6dd34336f8a337aa2996d71c841", size = 136284, upload-time = "2026-01-28T18:15:19.912Z" }, + { url = "https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486", size = 129090, upload-time = "2026-01-28T18:15:22.168Z" }, + { url = "https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979", size = 129859, upload-time = "2026-01-28T18:15:23.795Z" }, + { url = "https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9", size = 155560, upload-time = "2026-01-28T18:15:25.976Z" }, + { url = "https://files.pythonhosted.org/packages/63/65/37648c0c158dc222aba51c089eb3bdfa238e621674dc42d48706e639204f/psutil-7.2.2-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b0726cecd84f9474419d67252add4ac0cd9811b04d61123054b9fb6f57df6e9e", size = 156997, upload-time = "2026-01-28T18:15:27.794Z" }, + { url = "https://files.pythonhosted.org/packages/8e/13/125093eadae863ce03c6ffdbae9929430d116a246ef69866dad94da3bfbc/psutil-7.2.2-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8", size = 148972, upload-time = "2026-01-28T18:15:29.342Z" }, + { url = "https://files.pythonhosted.org/packages/04/78/0acd37ca84ce3ddffaa92ef0f571e073faa6d8ff1f0559ab1272188ea2be/psutil-7.2.2-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b58fabe35e80b264a4e3bb23e6b96f9e45a3df7fb7eed419ac0e5947c61e47cc", size = 148266, upload-time = "2026-01-28T18:15:31.597Z" }, + { url = "https://files.pythonhosted.org/packages/b4/90/e2159492b5426be0c1fef7acba807a03511f97c5f86b3caeda6ad92351a7/psutil-7.2.2-cp37-abi3-win_amd64.whl", hash = "sha256:eb7e81434c8d223ec4a219b5fc1c47d0417b12be7ea866e24fb5ad6e84b3d988", size = 137737, upload-time = "2026-01-28T18:15:33.849Z" }, + { url = "https://files.pythonhosted.org/packages/8c/c7/7bb2e321574b10df20cbde462a94e2b71d05f9bbda251ef27d104668306a/psutil-7.2.2-cp37-abi3-win_arm64.whl", hash = "sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee", size = 134617, upload-time = "2026-01-28T18:15:36.514Z" }, +] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762, upload-time = "2020-12-28T15:15:30.155Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993, upload-time = "2020-12-28T15:15:28.35Z" }, +] + +[[package]] +name = "pure-eval" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752, upload-time = "2024-07-21T12:58:21.801Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" }, +] + [[package]] name = "pyarrow" version = "23.0.1" @@ -671,6 +1596,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/50/f2/c0e76a0b451ffdf0cf788932e182758eb7558953f4f27f1aff8e2518b653/pyarrow-23.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:527e8d899f14bd15b740cd5a54ad56b7f98044955373a17179d5956ddb93d9ce", size = 28365807, upload-time = "2026-02-16T10:14:03.892Z" }, ] +[[package]] +name = "pycparser" +version = "3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + [[package]] name = "pyogrio" version = "0.12.1" @@ -776,6 +1719,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, ] +[[package]] +name = "python-json-logger" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/29/bf/eca6a3d43db1dae7070f70e160ab20b807627ba953663ba07928cdd3dc58/python_json_logger-4.0.0.tar.gz", hash = "sha256:f58e68eb46e1faed27e0f574a55a0455eecd7b8a5b88b85a784519ba3cff047f", size = 17683, upload-time = "2025-10-06T04:15:18.984Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/e5/fecf13f06e5e5f67e8837d777d1bc43fac0ed2b77a676804df5c34744727/python_json_logger-4.0.0-py3-none-any.whl", hash = "sha256:af09c9daf6a813aa4cc7180395f50f2a9e5fa056034c9953aec92e381c5ba1e2", size = 15548, upload-time = "2025-10-06T04:15:17.553Z" }, +] + [[package]] name = "pytz" version = "2025.2" @@ -785,6 +1737,114 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" }, ] +[[package]] +name = "pywinpty" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f7/54/37c7370ba91f579235049dc26cd2c5e657d2a943e01820844ffc81f32176/pywinpty-3.0.3.tar.gz", hash = "sha256:523441dc34d231fb361b4b00f8c99d3f16de02f5005fd544a0183112bcc22412", size = 31309, upload-time = "2026-02-04T21:51:09.524Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/cb/58d6ed3fd429c96a90ef01ac9a617af10a6d41469219c25e7dc162abbb71/pywinpty-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9c91dbb026050c77bdcef964e63a4f10f01a639113c4d3658332614544c467ab", size = 2112686, upload-time = "2026-02-04T21:52:03.035Z" }, + { url = "https://files.pythonhosted.org/packages/fd/50/724ed5c38c504d4e58a88a072776a1e880d970789deaeb2b9f7bd9a5141a/pywinpty-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:fe1f7911805127c94cf51f89ab14096c6f91ffdcacf993d2da6082b2142a2523", size = 234591, upload-time = "2026-02-04T21:52:29.821Z" }, + { url = "https://files.pythonhosted.org/packages/f7/ad/90a110538696b12b39fd8758a06d70ded899308198ad2305ac68e361126e/pywinpty-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:3f07a6cf1c1d470d284e614733c3d0f726d2c85e78508ea10a403140c3c0c18a", size = 2112360, upload-time = "2026-02-04T21:55:33.397Z" }, + { url = "https://files.pythonhosted.org/packages/44/0f/7ffa221757a220402bc79fda44044c3f2cc57338d878ab7d622add6f4581/pywinpty-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:15c7c0b6f8e9d87aabbaff76468dabf6e6121332c40fc1d83548d02a9d6a3759", size = 233107, upload-time = "2026-02-04T21:51:45.455Z" }, + { url = "https://files.pythonhosted.org/packages/28/88/2ff917caff61e55f38bcdb27de06ee30597881b2cae44fbba7627be015c4/pywinpty-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:d4b6b7b0fe0cdcd02e956bd57cfe9f4e5a06514eecf3b5ae174da4f951b58be9", size = 2113282, upload-time = "2026-02-04T21:52:08.188Z" }, + { url = "https://files.pythonhosted.org/packages/63/32/40a775343ace542cc43ece3f1d1fce454021521ecac41c4c4573081c2336/pywinpty-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:34789d685fc0d547ce0c8a65e5a70e56f77d732fa6e03c8f74fefb8cbb252019", size = 234207, upload-time = "2026-02-04T21:51:58.687Z" }, + { url = "https://files.pythonhosted.org/packages/8d/54/5d5e52f4cb75028104ca6faf36c10f9692389b1986d34471663b4ebebd6d/pywinpty-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:0c37e224a47a971d1a6e08649a1714dac4f63c11920780977829ed5c8cadead1", size = 2112910, upload-time = "2026-02-04T21:52:30.976Z" }, + { url = "https://files.pythonhosted.org/packages/0a/44/dcd184824e21d4620b06c7db9fbb15c3ad0a0f1fa2e6de79969fb82647ec/pywinpty-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:c4e9c3dff7d86ba81937438d5819f19f385a39d8f592d4e8af67148ceb4f6ab5", size = 233425, upload-time = "2026-02-04T21:51:56.754Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, + { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, + { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, + { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, + { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, + { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, + { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, + { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, + { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, + { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, + { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, + { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, + { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, + { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, + { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, + { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, + { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, + { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, + { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, + { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, + { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, + { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, + { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, + { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, + { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, + { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, +] + +[[package]] +name = "pyzmq" +version = "27.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "implementation_name == 'pypy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/0b/3c9baedbdf613ecaa7aa07027780b8867f57b6293b6ee50de316c9f3222b/pyzmq-27.1.0.tar.gz", hash = "sha256:ac0765e3d44455adb6ddbf4417dcce460fc40a05978c08efdf2948072f6db540", size = 281750, upload-time = "2025-09-08T23:10:18.157Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:452631b640340c928fa343801b0d07eb0c3789a5ffa843f6e1a9cee0ba4eb4fc", size = 1306279, upload-time = "2025-09-08T23:08:03.807Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5e/c3c49fdd0f535ef45eefcc16934648e9e59dace4a37ee88fc53f6cd8e641/pyzmq-27.1.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1c179799b118e554b66da67d88ed66cd37a169f1f23b5d9f0a231b4e8d44a113", size = 895645, upload-time = "2025-09-08T23:08:05.301Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e5/b0b2504cb4e903a74dcf1ebae157f9e20ebb6ea76095f6cfffea28c42ecd/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3837439b7f99e60312f0c926a6ad437b067356dc2bc2ec96eb395fd0fe804233", size = 652574, upload-time = "2025-09-08T23:08:06.828Z" }, + { url = "https://files.pythonhosted.org/packages/f8/9b/c108cdb55560eaf253f0cbdb61b29971e9fb34d9c3499b0e96e4e60ed8a5/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43ad9a73e3da1fab5b0e7e13402f0b2fb934ae1c876c51d0afff0e7c052eca31", size = 840995, upload-time = "2025-09-08T23:08:08.396Z" }, + { url = "https://files.pythonhosted.org/packages/c2/bb/b79798ca177b9eb0825b4c9998c6af8cd2a7f15a6a1a4272c1d1a21d382f/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0de3028d69d4cdc475bfe47a6128eb38d8bc0e8f4d69646adfbcd840facbac28", size = 1642070, upload-time = "2025-09-08T23:08:09.989Z" }, + { url = "https://files.pythonhosted.org/packages/9c/80/2df2e7977c4ede24c79ae39dcef3899bfc5f34d1ca7a5b24f182c9b7a9ca/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:cf44a7763aea9298c0aa7dbf859f87ed7012de8bda0f3977b6fb1d96745df856", size = 2021121, upload-time = "2025-09-08T23:08:11.907Z" }, + { url = "https://files.pythonhosted.org/packages/46/bd/2d45ad24f5f5ae7e8d01525eb76786fa7557136555cac7d929880519e33a/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f30f395a9e6fbca195400ce833c731e7b64c3919aa481af4d88c3759e0cb7496", size = 1878550, upload-time = "2025-09-08T23:08:13.513Z" }, + { url = "https://files.pythonhosted.org/packages/e6/2f/104c0a3c778d7c2ab8190e9db4f62f0b6957b53c9d87db77c284b69f33ea/pyzmq-27.1.0-cp312-abi3-win32.whl", hash = "sha256:250e5436a4ba13885494412b3da5d518cd0d3a278a1ae640e113c073a5f88edd", size = 559184, upload-time = "2025-09-08T23:08:15.163Z" }, + { url = "https://files.pythonhosted.org/packages/fc/7f/a21b20d577e4100c6a41795842028235998a643b1ad406a6d4163ea8f53e/pyzmq-27.1.0-cp312-abi3-win_amd64.whl", hash = "sha256:9ce490cf1d2ca2ad84733aa1d69ce6855372cb5ce9223802450c9b2a7cba0ccf", size = 619480, upload-time = "2025-09-08T23:08:17.192Z" }, + { url = "https://files.pythonhosted.org/packages/78/c2/c012beae5f76b72f007a9e91ee9401cb88c51d0f83c6257a03e785c81cc2/pyzmq-27.1.0-cp312-abi3-win_arm64.whl", hash = "sha256:75a2f36223f0d535a0c919e23615fc85a1e23b71f40c7eb43d7b1dedb4d8f15f", size = 552993, upload-time = "2025-09-08T23:08:18.926Z" }, + { url = "https://files.pythonhosted.org/packages/60/cb/84a13459c51da6cec1b7b1dc1a47e6db6da50b77ad7fd9c145842750a011/pyzmq-27.1.0-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:93ad4b0855a664229559e45c8d23797ceac03183c7b6f5b4428152a6b06684a5", size = 1122436, upload-time = "2025-09-08T23:08:20.801Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b6/94414759a69a26c3dd674570a81813c46a078767d931a6c70ad29fc585cb/pyzmq-27.1.0-cp313-cp313-android_24_x86_64.whl", hash = "sha256:fbb4f2400bfda24f12f009cba62ad5734148569ff4949b1b6ec3b519444342e6", size = 1156301, upload-time = "2025-09-08T23:08:22.47Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ad/15906493fd40c316377fd8a8f6b1f93104f97a752667763c9b9c1b71d42d/pyzmq-27.1.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:e343d067f7b151cfe4eb3bb796a7752c9d369eed007b91231e817071d2c2fec7", size = 1341197, upload-time = "2025-09-08T23:08:24.286Z" }, + { url = "https://files.pythonhosted.org/packages/14/1d/d343f3ce13db53a54cb8946594e567410b2125394dafcc0268d8dda027e0/pyzmq-27.1.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:08363b2011dec81c354d694bdecaef4770e0ae96b9afea70b3f47b973655cc05", size = 897275, upload-time = "2025-09-08T23:08:26.063Z" }, + { url = "https://files.pythonhosted.org/packages/69/2d/d83dd6d7ca929a2fc67d2c3005415cdf322af7751d773524809f9e585129/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d54530c8c8b5b8ddb3318f481297441af102517602b569146185fa10b63f4fa9", size = 660469, upload-time = "2025-09-08T23:08:27.623Z" }, + { url = "https://files.pythonhosted.org/packages/3e/cd/9822a7af117f4bc0f1952dbe9ef8358eb50a24928efd5edf54210b850259/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f3afa12c392f0a44a2414056d730eebc33ec0926aae92b5ad5cf26ebb6cc128", size = 847961, upload-time = "2025-09-08T23:08:29.672Z" }, + { url = "https://files.pythonhosted.org/packages/9a/12/f003e824a19ed73be15542f172fd0ec4ad0b60cf37436652c93b9df7c585/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c65047adafe573ff023b3187bb93faa583151627bc9c51fc4fb2c561ed689d39", size = 1650282, upload-time = "2025-09-08T23:08:31.349Z" }, + { url = "https://files.pythonhosted.org/packages/d5/4a/e82d788ed58e9a23995cee70dbc20c9aded3d13a92d30d57ec2291f1e8a3/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:90e6e9441c946a8b0a667356f7078d96411391a3b8f80980315455574177ec97", size = 2024468, upload-time = "2025-09-08T23:08:33.543Z" }, + { url = "https://files.pythonhosted.org/packages/d9/94/2da0a60841f757481e402b34bf4c8bf57fa54a5466b965de791b1e6f747d/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:add071b2d25f84e8189aaf0882d39a285b42fa3853016ebab234a5e78c7a43db", size = 1885394, upload-time = "2025-09-08T23:08:35.51Z" }, + { url = "https://files.pythonhosted.org/packages/4f/6f/55c10e2e49ad52d080dc24e37adb215e5b0d64990b57598abc2e3f01725b/pyzmq-27.1.0-cp313-cp313t-win32.whl", hash = "sha256:7ccc0700cfdf7bd487bea8d850ec38f204478681ea02a582a8da8171b7f90a1c", size = 574964, upload-time = "2025-09-08T23:08:37.178Z" }, + { url = "https://files.pythonhosted.org/packages/87/4d/2534970ba63dd7c522d8ca80fb92777f362c0f321900667c615e2067cb29/pyzmq-27.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:8085a9fba668216b9b4323be338ee5437a235fe275b9d1610e422ccc279733e2", size = 641029, upload-time = "2025-09-08T23:08:40.595Z" }, + { url = "https://files.pythonhosted.org/packages/f6/fa/f8aea7a28b0641f31d40dea42d7ef003fded31e184ef47db696bc74cd610/pyzmq-27.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:6bb54ca21bcfe361e445256c15eedf083f153811c37be87e0514934d6913061e", size = 561541, upload-time = "2025-09-08T23:08:42.668Z" }, + { url = "https://files.pythonhosted.org/packages/87/45/19efbb3000956e82d0331bafca5d9ac19ea2857722fa2caacefb6042f39d/pyzmq-27.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:ce980af330231615756acd5154f29813d553ea555485ae712c491cd483df6b7a", size = 1341197, upload-time = "2025-09-08T23:08:44.973Z" }, + { url = "https://files.pythonhosted.org/packages/48/43/d72ccdbf0d73d1343936296665826350cb1e825f92f2db9db3e61c2162a2/pyzmq-27.1.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1779be8c549e54a1c38f805e56d2a2e5c009d26de10921d7d51cfd1c8d4632ea", size = 897175, upload-time = "2025-09-08T23:08:46.601Z" }, + { url = "https://files.pythonhosted.org/packages/2f/2e/a483f73a10b65a9ef0161e817321d39a770b2acf8bcf3004a28d90d14a94/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7200bb0f03345515df50d99d3db206a0a6bee1955fbb8c453c76f5bf0e08fb96", size = 660427, upload-time = "2025-09-08T23:08:48.187Z" }, + { url = "https://files.pythonhosted.org/packages/f5/d2/5f36552c2d3e5685abe60dfa56f91169f7a2d99bbaf67c5271022ab40863/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01c0e07d558b06a60773744ea6251f769cd79a41a97d11b8bf4ab8f034b0424d", size = 847929, upload-time = "2025-09-08T23:08:49.76Z" }, + { url = "https://files.pythonhosted.org/packages/c4/2a/404b331f2b7bf3198e9945f75c4c521f0c6a3a23b51f7a4a401b94a13833/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:80d834abee71f65253c91540445d37c4c561e293ba6e741b992f20a105d69146", size = 1650193, upload-time = "2025-09-08T23:08:51.7Z" }, + { url = "https://files.pythonhosted.org/packages/1c/0b/f4107e33f62a5acf60e3ded67ed33d79b4ce18de432625ce2fc5093d6388/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:544b4e3b7198dde4a62b8ff6685e9802a9a1ebf47e77478a5eb88eca2a82f2fd", size = 2024388, upload-time = "2025-09-08T23:08:53.393Z" }, + { url = "https://files.pythonhosted.org/packages/0d/01/add31fe76512642fd6e40e3a3bd21f4b47e242c8ba33efb6809e37076d9b/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cedc4c68178e59a4046f97eca31b148ddcf51e88677de1ef4e78cf06c5376c9a", size = 1885316, upload-time = "2025-09-08T23:08:55.702Z" }, + { url = "https://files.pythonhosted.org/packages/c4/59/a5f38970f9bf07cee96128de79590bb354917914a9be11272cfc7ff26af0/pyzmq-27.1.0-cp314-cp314t-win32.whl", hash = "sha256:1f0b2a577fd770aa6f053211a55d1c47901f4d537389a034c690291485e5fe92", size = 587472, upload-time = "2025-09-08T23:08:58.18Z" }, + { url = "https://files.pythonhosted.org/packages/70/d8/78b1bad170f93fcf5e3536e70e8fadac55030002275c9a29e8f5719185de/pyzmq-27.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:19c9468ae0437f8074af379e986c5d3d7d7bfe033506af442e8c879732bedbe0", size = 661401, upload-time = "2025-09-08T23:08:59.802Z" }, + { url = "https://files.pythonhosted.org/packages/81/d6/4bfbb40c9a0b42fc53c7cf442f6385db70b40f74a783130c5d0a5aa62228/pyzmq-27.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dc5dbf68a7857b59473f7df42650c621d7e8923fb03fa74a526890f4d33cc4d7", size = 575170, upload-time = "2025-09-08T23:09:01.418Z" }, +] + +[[package]] +name = "referencing" +version = "0.37.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/22/f5/df4e9027acead3ecc63e50fe1e36aca1523e1719559c499951bb4b53188f/referencing-0.37.0.tar.gz", hash = "sha256:44aefc3142c5b842538163acb373e24cce6632bd54bdb01b21ad5863489f50d8", size = 78036, upload-time = "2025-10-13T15:30:48.871Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" }, +] + [[package]] name = "requests" version = "2.32.5" @@ -817,6 +1877,105 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/68/3f/dfa42bb16be96d53351aa151cb1e39fcaafe6cda01389c530a2ec809ef8a/requests_cache-1.3.0-py3-none-any.whl", hash = "sha256:f09f27bbf100c250886acf13a9db35b53cf2852fddd71977b47c71ea7d90dbba", size = 69626, upload-time = "2026-02-02T23:17:31.718Z" }, ] +[[package]] +name = "rfc3339-validator" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/ea/a9387748e2d111c3c2b275ba970b735e04e15cdb1eb30693b6b5708c4dbd/rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b", size = 5513, upload-time = "2021-05-12T16:37:54.178Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/44/4e421b96b67b2daff264473f7465db72fbdf36a07e05494f50300cc7b0c6/rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa", size = 3490, upload-time = "2021-05-12T16:37:52.536Z" }, +] + +[[package]] +name = "rfc3986-validator" +version = "0.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/88/f270de456dd7d11dcc808abfa291ecdd3f45ff44e3b549ffa01b126464d0/rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055", size = 6760, upload-time = "2019-10-28T16:00:19.144Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/51/17023c0f8f1869d8806b979a2bffa3f861f26a3f1a66b094288323fba52f/rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9", size = 4242, upload-time = "2019-10-28T16:00:13.976Z" }, +] + +[[package]] +name = "rfc3987-syntax" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "lark" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/2c/06/37c1a5557acf449e8e406a830a05bf885ac47d33270aec454ef78675008d/rfc3987_syntax-1.1.0.tar.gz", hash = "sha256:717a62cbf33cffdd16dfa3a497d81ce48a660ea691b1ddd7be710c22f00b4a0d", size = 14239, upload-time = "2025-07-18T01:05:05.015Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/71/44ce230e1b7fadd372515a97e32a83011f906ddded8d03e3c6aafbdedbb7/rfc3987_syntax-1.1.0-py3-none-any.whl", hash = "sha256:6c3d97604e4c5ce9f714898e05401a0445a641cfa276432b0a648c80856f6a3f", size = 8046, upload-time = "2025-07-18T01:05:03.843Z" }, +] + +[[package]] +name = "rpds-py" +version = "0.30.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/af/3f2f423103f1113b36230496629986e0ef7e199d2aa8392452b484b38ced/rpds_py-0.30.0.tar.gz", hash = "sha256:dd8ff7cf90014af0c0f787eea34794ebf6415242ee1d6fa91eaba725cc441e84", size = 69469, upload-time = "2025-11-30T20:24:38.837Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ed/dc/d61221eb88ff410de3c49143407f6f3147acf2538c86f2ab7ce65ae7d5f9/rpds_py-0.30.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f83424d738204d9770830d35290ff3273fbb02b41f919870479fab14b9d303b2", size = 374887, upload-time = "2025-11-30T20:22:41.812Z" }, + { url = "https://files.pythonhosted.org/packages/fd/32/55fb50ae104061dbc564ef15cc43c013dc4a9f4527a1f4d99baddf56fe5f/rpds_py-0.30.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7536cd91353c5273434b4e003cbda89034d67e7710eab8761fd918ec6c69cf8", size = 358904, upload-time = "2025-11-30T20:22:43.479Z" }, + { url = "https://files.pythonhosted.org/packages/58/70/faed8186300e3b9bdd138d0273109784eea2396c68458ed580f885dfe7ad/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2771c6c15973347f50fece41fc447c054b7ac2ae0502388ce3b6738cd366e3d4", size = 389945, upload-time = "2025-11-30T20:22:44.819Z" }, + { url = "https://files.pythonhosted.org/packages/bd/a8/073cac3ed2c6387df38f71296d002ab43496a96b92c823e76f46b8af0543/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0a59119fc6e3f460315fe9d08149f8102aa322299deaa5cab5b40092345c2136", size = 407783, upload-time = "2025-11-30T20:22:46.103Z" }, + { url = "https://files.pythonhosted.org/packages/77/57/5999eb8c58671f1c11eba084115e77a8899d6e694d2a18f69f0ba471ec8b/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76fec018282b4ead0364022e3c54b60bf368b9d926877957a8624b58419169b7", size = 515021, upload-time = "2025-11-30T20:22:47.458Z" }, + { url = "https://files.pythonhosted.org/packages/e0/af/5ab4833eadc36c0a8ed2bc5c0de0493c04f6c06de223170bd0798ff98ced/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:692bef75a5525db97318e8cd061542b5a79812d711ea03dbc1f6f8dbb0c5f0d2", size = 414589, upload-time = "2025-11-30T20:22:48.872Z" }, + { url = "https://files.pythonhosted.org/packages/b7/de/f7192e12b21b9e9a68a6d0f249b4af3fdcdff8418be0767a627564afa1f1/rpds_py-0.30.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9027da1ce107104c50c81383cae773ef5c24d296dd11c99e2629dbd7967a20c6", size = 394025, upload-time = "2025-11-30T20:22:50.196Z" }, + { url = "https://files.pythonhosted.org/packages/91/c4/fc70cd0249496493500e7cc2de87504f5aa6509de1e88623431fec76d4b6/rpds_py-0.30.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:9cf69cdda1f5968a30a359aba2f7f9aa648a9ce4b580d6826437f2b291cfc86e", size = 408895, upload-time = "2025-11-30T20:22:51.87Z" }, + { url = "https://files.pythonhosted.org/packages/58/95/d9275b05ab96556fefff73a385813eb66032e4c99f411d0795372d9abcea/rpds_py-0.30.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4796a717bf12b9da9d3ad002519a86063dcac8988b030e405704ef7d74d2d9d", size = 422799, upload-time = "2025-11-30T20:22:53.341Z" }, + { url = "https://files.pythonhosted.org/packages/06/c1/3088fc04b6624eb12a57eb814f0d4997a44b0d208d6cace713033ff1a6ba/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5d4c2aa7c50ad4728a094ebd5eb46c452e9cb7edbfdb18f9e1221f597a73e1e7", size = 572731, upload-time = "2025-11-30T20:22:54.778Z" }, + { url = "https://files.pythonhosted.org/packages/d8/42/c612a833183b39774e8ac8fecae81263a68b9583ee343db33ab571a7ce55/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ba81a9203d07805435eb06f536d95a266c21e5b2dfbf6517748ca40c98d19e31", size = 599027, upload-time = "2025-11-30T20:22:56.212Z" }, + { url = "https://files.pythonhosted.org/packages/5f/60/525a50f45b01d70005403ae0e25f43c0384369ad24ffe46e8d9068b50086/rpds_py-0.30.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:945dccface01af02675628334f7cf49c2af4c1c904748efc5cf7bbdf0b579f95", size = 563020, upload-time = "2025-11-30T20:22:58.2Z" }, + { url = "https://files.pythonhosted.org/packages/0b/5d/47c4655e9bcd5ca907148535c10e7d489044243cc9941c16ed7cd53be91d/rpds_py-0.30.0-cp313-cp313-win32.whl", hash = "sha256:b40fb160a2db369a194cb27943582b38f79fc4887291417685f3ad693c5a1d5d", size = 223139, upload-time = "2025-11-30T20:23:00.209Z" }, + { url = "https://files.pythonhosted.org/packages/f2/e1/485132437d20aa4d3e1d8b3fb5a5e65aa8139f1e097080c2a8443201742c/rpds_py-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:806f36b1b605e2d6a72716f321f20036b9489d29c51c91f4dd29a3e3afb73b15", size = 240224, upload-time = "2025-11-30T20:23:02.008Z" }, + { url = "https://files.pythonhosted.org/packages/24/95/ffd128ed1146a153d928617b0ef673960130be0009c77d8fbf0abe306713/rpds_py-0.30.0-cp313-cp313-win_arm64.whl", hash = "sha256:d96c2086587c7c30d44f31f42eae4eac89b60dabbac18c7669be3700f13c3ce1", size = 230645, upload-time = "2025-11-30T20:23:03.43Z" }, + { url = "https://files.pythonhosted.org/packages/ff/1b/b10de890a0def2a319a2626334a7f0ae388215eb60914dbac8a3bae54435/rpds_py-0.30.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:eb0b93f2e5c2189ee831ee43f156ed34e2a89a78a66b98cadad955972548be5a", size = 364443, upload-time = "2025-11-30T20:23:04.878Z" }, + { url = "https://files.pythonhosted.org/packages/0d/bf/27e39f5971dc4f305a4fb9c672ca06f290f7c4e261c568f3dea16a410d47/rpds_py-0.30.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:922e10f31f303c7c920da8981051ff6d8c1a56207dbdf330d9047f6d30b70e5e", size = 353375, upload-time = "2025-11-30T20:23:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/40/58/442ada3bba6e8e6615fc00483135c14a7538d2ffac30e2d933ccf6852232/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdc62c8286ba9bf7f47befdcea13ea0e26bf294bda99758fd90535cbaf408000", size = 383850, upload-time = "2025-11-30T20:23:07.825Z" }, + { url = "https://files.pythonhosted.org/packages/14/14/f59b0127409a33c6ef6f5c1ebd5ad8e32d7861c9c7adfa9a624fc3889f6c/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47f9a91efc418b54fb8190a6b4aa7813a23fb79c51f4bb84e418f5476c38b8db", size = 392812, upload-time = "2025-11-30T20:23:09.228Z" }, + { url = "https://files.pythonhosted.org/packages/b3/66/e0be3e162ac299b3a22527e8913767d869e6cc75c46bd844aa43fb81ab62/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f3587eb9b17f3789ad50824084fa6f81921bbf9a795826570bda82cb3ed91f2", size = 517841, upload-time = "2025-11-30T20:23:11.186Z" }, + { url = "https://files.pythonhosted.org/packages/3d/55/fa3b9cf31d0c963ecf1ba777f7cf4b2a2c976795ac430d24a1f43d25a6ba/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39c02563fc592411c2c61d26b6c5fe1e51eaa44a75aa2c8735ca88b0d9599daa", size = 408149, upload-time = "2025-11-30T20:23:12.864Z" }, + { url = "https://files.pythonhosted.org/packages/60/ca/780cf3b1a32b18c0f05c441958d3758f02544f1d613abf9488cd78876378/rpds_py-0.30.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51a1234d8febafdfd33a42d97da7a43f5dcb120c1060e352a3fbc0c6d36e2083", size = 383843, upload-time = "2025-11-30T20:23:14.638Z" }, + { url = "https://files.pythonhosted.org/packages/82/86/d5f2e04f2aa6247c613da0c1dd87fcd08fa17107e858193566048a1e2f0a/rpds_py-0.30.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:eb2c4071ab598733724c08221091e8d80e89064cd472819285a9ab0f24bcedb9", size = 396507, upload-time = "2025-11-30T20:23:16.105Z" }, + { url = "https://files.pythonhosted.org/packages/4b/9a/453255d2f769fe44e07ea9785c8347edaf867f7026872e76c1ad9f7bed92/rpds_py-0.30.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bdfdb946967d816e6adf9a3d8201bfad269c67efe6cefd7093ef959683c8de0", size = 414949, upload-time = "2025-11-30T20:23:17.539Z" }, + { url = "https://files.pythonhosted.org/packages/a3/31/622a86cdc0c45d6df0e9ccb6becdba5074735e7033c20e401a6d9d0e2ca0/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c77afbd5f5250bf27bf516c7c4a016813eb2d3e116139aed0096940c5982da94", size = 565790, upload-time = "2025-11-30T20:23:19.029Z" }, + { url = "https://files.pythonhosted.org/packages/1c/5d/15bbf0fb4a3f58a3b1c67855ec1efcc4ceaef4e86644665fff03e1b66d8d/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:61046904275472a76c8c90c9ccee9013d70a6d0f73eecefd38c1ae7c39045a08", size = 590217, upload-time = "2025-11-30T20:23:20.885Z" }, + { url = "https://files.pythonhosted.org/packages/6d/61/21b8c41f68e60c8cc3b2e25644f0e3681926020f11d06ab0b78e3c6bbff1/rpds_py-0.30.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4c5f36a861bc4b7da6516dbdf302c55313afa09b81931e8280361a4f6c9a2d27", size = 555806, upload-time = "2025-11-30T20:23:22.488Z" }, + { url = "https://files.pythonhosted.org/packages/f9/39/7e067bb06c31de48de3eb200f9fc7c58982a4d3db44b07e73963e10d3be9/rpds_py-0.30.0-cp313-cp313t-win32.whl", hash = "sha256:3d4a69de7a3e50ffc214ae16d79d8fbb0922972da0356dcf4d0fdca2878559c6", size = 211341, upload-time = "2025-11-30T20:23:24.449Z" }, + { url = "https://files.pythonhosted.org/packages/0a/4d/222ef0b46443cf4cf46764d9c630f3fe4abaa7245be9417e56e9f52b8f65/rpds_py-0.30.0-cp313-cp313t-win_amd64.whl", hash = "sha256:f14fc5df50a716f7ece6a80b6c78bb35ea2ca47c499e422aa4463455dd96d56d", size = 225768, upload-time = "2025-11-30T20:23:25.908Z" }, + { url = "https://files.pythonhosted.org/packages/86/81/dad16382ebbd3d0e0328776d8fd7ca94220e4fa0798d1dc5e7da48cb3201/rpds_py-0.30.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:68f19c879420aa08f61203801423f6cd5ac5f0ac4ac82a2368a9fcd6a9a075e0", size = 362099, upload-time = "2025-11-30T20:23:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/2b/60/19f7884db5d5603edf3c6bce35408f45ad3e97e10007df0e17dd57af18f8/rpds_py-0.30.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ec7c4490c672c1a0389d319b3a9cfcd098dcdc4783991553c332a15acf7249be", size = 353192, upload-time = "2025-11-30T20:23:29.151Z" }, + { url = "https://files.pythonhosted.org/packages/bf/c4/76eb0e1e72d1a9c4703c69607cec123c29028bff28ce41588792417098ac/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f251c812357a3fed308d684a5079ddfb9d933860fc6de89f2b7ab00da481e65f", size = 384080, upload-time = "2025-11-30T20:23:30.785Z" }, + { url = "https://files.pythonhosted.org/packages/72/87/87ea665e92f3298d1b26d78814721dc39ed8d2c74b86e83348d6b48a6f31/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac98b175585ecf4c0348fd7b29c3864bda53b805c773cbf7bfdaffc8070c976f", size = 394841, upload-time = "2025-11-30T20:23:32.209Z" }, + { url = "https://files.pythonhosted.org/packages/77/ad/7783a89ca0587c15dcbf139b4a8364a872a25f861bdb88ed99f9b0dec985/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e62880792319dbeb7eb866547f2e35973289e7d5696c6e295476448f5b63c87", size = 516670, upload-time = "2025-11-30T20:23:33.742Z" }, + { url = "https://files.pythonhosted.org/packages/5b/3c/2882bdac942bd2172f3da574eab16f309ae10a3925644e969536553cb4ee/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e7fc54e0900ab35d041b0601431b0a0eb495f0851a0639b6ef90f7741b39a18", size = 408005, upload-time = "2025-11-30T20:23:35.253Z" }, + { url = "https://files.pythonhosted.org/packages/ce/81/9a91c0111ce1758c92516a3e44776920b579d9a7c09b2b06b642d4de3f0f/rpds_py-0.30.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47e77dc9822d3ad616c3d5759ea5631a75e5809d5a28707744ef79d7a1bcfcad", size = 382112, upload-time = "2025-11-30T20:23:36.842Z" }, + { url = "https://files.pythonhosted.org/packages/cf/8e/1da49d4a107027e5fbc64daeab96a0706361a2918da10cb41769244b805d/rpds_py-0.30.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:b4dc1a6ff022ff85ecafef7979a2c6eb423430e05f1165d6688234e62ba99a07", size = 399049, upload-time = "2025-11-30T20:23:38.343Z" }, + { url = "https://files.pythonhosted.org/packages/df/5a/7ee239b1aa48a127570ec03becbb29c9d5a9eb092febbd1699d567cae859/rpds_py-0.30.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4559c972db3a360808309e06a74628b95eaccbf961c335c8fe0d590cf587456f", size = 415661, upload-time = "2025-11-30T20:23:40.263Z" }, + { url = "https://files.pythonhosted.org/packages/70/ea/caa143cf6b772f823bc7929a45da1fa83569ee49b11d18d0ada7f5ee6fd6/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:0ed177ed9bded28f8deb6ab40c183cd1192aa0de40c12f38be4d59cd33cb5c65", size = 565606, upload-time = "2025-11-30T20:23:42.186Z" }, + { url = "https://files.pythonhosted.org/packages/64/91/ac20ba2d69303f961ad8cf55bf7dbdb4763f627291ba3d0d7d67333cced9/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:ad1fa8db769b76ea911cb4e10f049d80bf518c104f15b3edb2371cc65375c46f", size = 591126, upload-time = "2025-11-30T20:23:44.086Z" }, + { url = "https://files.pythonhosted.org/packages/21/20/7ff5f3c8b00c8a95f75985128c26ba44503fb35b8e0259d812766ea966c7/rpds_py-0.30.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:46e83c697b1f1c72b50e5ee5adb4353eef7406fb3f2043d64c33f20ad1c2fc53", size = 553371, upload-time = "2025-11-30T20:23:46.004Z" }, + { url = "https://files.pythonhosted.org/packages/72/c7/81dadd7b27c8ee391c132a6b192111ca58d866577ce2d9b0ca157552cce0/rpds_py-0.30.0-cp314-cp314-win32.whl", hash = "sha256:ee454b2a007d57363c2dfd5b6ca4a5d7e2c518938f8ed3b706e37e5d470801ed", size = 215298, upload-time = "2025-11-30T20:23:47.696Z" }, + { url = "https://files.pythonhosted.org/packages/3e/d2/1aaac33287e8cfb07aab2e6b8ac1deca62f6f65411344f1433c55e6f3eb8/rpds_py-0.30.0-cp314-cp314-win_amd64.whl", hash = "sha256:95f0802447ac2d10bcc69f6dc28fe95fdf17940367b21d34e34c737870758950", size = 228604, upload-time = "2025-11-30T20:23:49.501Z" }, + { url = "https://files.pythonhosted.org/packages/e8/95/ab005315818cc519ad074cb7784dae60d939163108bd2b394e60dc7b5461/rpds_py-0.30.0-cp314-cp314-win_arm64.whl", hash = "sha256:613aa4771c99f03346e54c3f038e4cc574ac09a3ddfb0e8878487335e96dead6", size = 222391, upload-time = "2025-11-30T20:23:50.96Z" }, + { url = "https://files.pythonhosted.org/packages/9e/68/154fe0194d83b973cdedcdcc88947a2752411165930182ae41d983dcefa6/rpds_py-0.30.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:7e6ecfcb62edfd632e56983964e6884851786443739dbfe3582947e87274f7cb", size = 364868, upload-time = "2025-11-30T20:23:52.494Z" }, + { url = "https://files.pythonhosted.org/packages/83/69/8bbc8b07ec854d92a8b75668c24d2abcb1719ebf890f5604c61c9369a16f/rpds_py-0.30.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a1d0bc22a7cdc173fedebb73ef81e07faef93692b8c1ad3733b67e31e1b6e1b8", size = 353747, upload-time = "2025-11-30T20:23:54.036Z" }, + { url = "https://files.pythonhosted.org/packages/ab/00/ba2e50183dbd9abcce9497fa5149c62b4ff3e22d338a30d690f9af970561/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d08f00679177226c4cb8c5265012eea897c8ca3b93f429e546600c971bcbae7", size = 383795, upload-time = "2025-11-30T20:23:55.556Z" }, + { url = "https://files.pythonhosted.org/packages/05/6f/86f0272b84926bcb0e4c972262f54223e8ecc556b3224d281e6598fc9268/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5965af57d5848192c13534f90f9dd16464f3c37aaf166cc1da1cae1fd5a34898", size = 393330, upload-time = "2025-11-30T20:23:57.033Z" }, + { url = "https://files.pythonhosted.org/packages/cb/e9/0e02bb2e6dc63d212641da45df2b0bf29699d01715913e0d0f017ee29438/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a4e86e34e9ab6b667c27f3211ca48f73dba7cd3d90f8d5b11be56e5dbc3fb4e", size = 518194, upload-time = "2025-11-30T20:23:58.637Z" }, + { url = "https://files.pythonhosted.org/packages/ee/ca/be7bca14cf21513bdf9c0606aba17d1f389ea2b6987035eb4f62bd923f25/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5d3e6b26f2c785d65cc25ef1e5267ccbe1b069c5c21b8cc724efee290554419", size = 408340, upload-time = "2025-11-30T20:24:00.2Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c7/736e00ebf39ed81d75544c0da6ef7b0998f8201b369acf842f9a90dc8fce/rpds_py-0.30.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:626a7433c34566535b6e56a1b39a7b17ba961e97ce3b80ec62e6f1312c025551", size = 383765, upload-time = "2025-11-30T20:24:01.759Z" }, + { url = "https://files.pythonhosted.org/packages/4a/3f/da50dfde9956aaf365c4adc9533b100008ed31aea635f2b8d7b627e25b49/rpds_py-0.30.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:acd7eb3f4471577b9b5a41baf02a978e8bdeb08b4b355273994f8b87032000a8", size = 396834, upload-time = "2025-11-30T20:24:03.687Z" }, + { url = "https://files.pythonhosted.org/packages/4e/00/34bcc2565b6020eab2623349efbdec810676ad571995911f1abdae62a3a0/rpds_py-0.30.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fe5fa731a1fa8a0a56b0977413f8cacac1768dad38d16b3a296712709476fbd5", size = 415470, upload-time = "2025-11-30T20:24:05.232Z" }, + { url = "https://files.pythonhosted.org/packages/8c/28/882e72b5b3e6f718d5453bd4d0d9cf8df36fddeb4ddbbab17869d5868616/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:74a3243a411126362712ee1524dfc90c650a503502f135d54d1b352bd01f2404", size = 565630, upload-time = "2025-11-30T20:24:06.878Z" }, + { url = "https://files.pythonhosted.org/packages/3b/97/04a65539c17692de5b85c6e293520fd01317fd878ea1995f0367d4532fb1/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3e8eeb0544f2eb0d2581774be4c3410356eba189529a6b3e36bbbf9696175856", size = 591148, upload-time = "2025-11-30T20:24:08.445Z" }, + { url = "https://files.pythonhosted.org/packages/85/70/92482ccffb96f5441aab93e26c4d66489eb599efdcf96fad90c14bbfb976/rpds_py-0.30.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:dbd936cde57abfee19ab3213cf9c26be06d60750e60a8e4dd85d1ab12c8b1f40", size = 556030, upload-time = "2025-11-30T20:24:10.956Z" }, + { url = "https://files.pythonhosted.org/packages/20/53/7c7e784abfa500a2b6b583b147ee4bb5a2b3747a9166bab52fec4b5b5e7d/rpds_py-0.30.0-cp314-cp314t-win32.whl", hash = "sha256:dc824125c72246d924f7f796b4f63c1e9dc810c7d9e2355864b3c3a73d59ade0", size = 211570, upload-time = "2025-11-30T20:24:12.735Z" }, + { url = "https://files.pythonhosted.org/packages/d0/02/fa464cdfbe6b26e0600b62c528b72d8608f5cc49f96b8d6e38c95d60c676/rpds_py-0.30.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3", size = 226532, upload-time = "2025-11-30T20:24:14.634Z" }, +] + [[package]] name = "scikit-learn" version = "1.8.0" @@ -920,6 +2079,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/83/11/00d3c3dfc25ad54e731d91449895a79e4bf2384dc3ac01809010ba88f6d5/seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987", size = 294914, upload-time = "2024-01-25T13:21:49.598Z" }, ] +[[package]] +name = "send2trash" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c5/f0/184b4b5f8d00f2a92cf96eec8967a3d550b52cf94362dad1100df9e48d57/send2trash-2.1.0.tar.gz", hash = "sha256:1c72b39f09457db3c05ce1d19158c2cbef4c32b8bedd02c155e49282b7ea7459", size = 17255, upload-time = "2026-01-14T06:27:36.056Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1c/78/504fdd027da3b84ff1aecd9f6957e65f35134534ccc6da8628eb71e76d3f/send2trash-2.1.0-py3-none-any.whl", hash = "sha256:0da2f112e6d6bb22de6aa6daa7e144831a4febf2a87261451c4ad849fe9a873c", size = 17610, upload-time = "2026-01-14T06:27:35.218Z" }, +] + +[[package]] +name = "setuptools" +version = "82.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/82/f3/748f4d6f65d1756b9ae577f329c951cda23fb900e4de9f70900ced962085/setuptools-82.0.0.tar.gz", hash = "sha256:22e0a2d69474c6ae4feb01951cb69d515ed23728cf96d05513d36e42b62b37cb", size = 1144893, upload-time = "2026-02-08T15:08:40.206Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/c6/76dc613121b793286a3f91621d7b75a2b493e0390ddca50f11993eadf192/setuptools-82.0.0-py3-none-any.whl", hash = "sha256:70b18734b607bd1da571d097d236cfcfacaf01de45717d59e6e04b96877532e0", size = 1003468, upload-time = "2026-02-08T15:08:38.723Z" }, +] + [[package]] name = "shapely" version = "2.1.2" @@ -972,6 +2149,29 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, ] +[[package]] +name = "soupsieve" +version = "2.8.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/ae/2d9c981590ed9999a0d91755b47fc74f74de286b0f5cee14c9269041e6c4/soupsieve-2.8.3.tar.gz", hash = "sha256:3267f1eeea4251fb42728b6dfb746edc9acaffc4a45b27e19450b676586e8349", size = 118627, upload-time = "2026-01-20T04:27:02.457Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/46/2c/1462b1d0a634697ae9e55b3cecdcb64788e8b7d63f54d923fcd0bb140aed/soupsieve-2.8.3-py3-none-any.whl", hash = "sha256:ed64f2ba4eebeab06cc4962affce381647455978ffc1e36bb79a545b91f45a95", size = 37016, upload-time = "2026-01-20T04:27:01.012Z" }, +] + +[[package]] +name = "stack-data" +version = "0.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asttokens" }, + { name = "executing" }, + { name = "pure-eval" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707, upload-time = "2023-09-30T13:58:05.479Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" }, +] + [[package]] name = "statsmodels" version = "0.14.6" @@ -999,6 +2199,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/26/33/f1652d0c59fa51de18492ee2345b65372550501ad061daa38f950be390b6/statsmodels-0.14.6-cp314-cp314-win_amd64.whl", hash = "sha256:151b73e29f01fe619dbce7f66d61a356e9d1fe5e906529b78807df9189c37721", size = 9588010, upload-time = "2025-12-05T23:14:07.28Z" }, ] +[[package]] +name = "terminado" +version = "0.18.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ptyprocess", marker = "os_name != 'nt'" }, + { name = "pywinpty", marker = "os_name == 'nt'" }, + { name = "tornado" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8a/11/965c6fd8e5cc254f1fe142d547387da17a8ebfd75a3455f637c663fb38a0/terminado-0.18.1.tar.gz", hash = "sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e", size = 32701, upload-time = "2024-03-12T14:34:39.026Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/9e/2064975477fdc887e47ad42157e214526dcad8f317a948dee17e1659a62f/terminado-0.18.1-py3-none-any.whl", hash = "sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0", size = 14154, upload-time = "2024-03-12T14:34:36.569Z" }, +] + [[package]] name = "threadpoolctl" version = "3.6.0" @@ -1008,6 +2222,37 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638, upload-time = "2025-03-13T13:49:21.846Z" }, ] +[[package]] +name = "tinycss2" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "webencodings" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7a/fd/7a5ee21fd08ff70d3d33a5781c255cbe779659bd03278feb98b19ee550f4/tinycss2-1.4.0.tar.gz", hash = "sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7", size = 87085, upload-time = "2024-10-24T14:58:29.895Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e6/34/ebdc18bae6aa14fbee1a08b63c015c72b64868ff7dae68808ab500c492e2/tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289", size = 26610, upload-time = "2024-10-24T14:58:28.029Z" }, +] + +[[package]] +name = "tornado" +version = "6.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/37/1d/0a336abf618272d53f62ebe274f712e213f5a03c0b2339575430b8362ef2/tornado-6.5.4.tar.gz", hash = "sha256:a22fa9047405d03260b483980635f0b041989d8bcc9a313f8fe18b411d84b1d7", size = 513632, upload-time = "2025-12-15T19:21:03.836Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/a9/e94a9d5224107d7ce3cc1fab8d5dc97f5ea351ccc6322ee4fb661da94e35/tornado-6.5.4-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:d6241c1a16b1c9e4cc28148b1cda97dd1c6cb4fb7068ac1bedc610768dff0ba9", size = 443909, upload-time = "2025-12-15T19:20:48.382Z" }, + { url = "https://files.pythonhosted.org/packages/db/7e/f7b8d8c4453f305a51f80dbb49014257bb7d28ccb4bbb8dd328ea995ecad/tornado-6.5.4-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2d50f63dda1d2cac3ae1fa23d254e16b5e38153758470e9956cbc3d813d40843", size = 442163, upload-time = "2025-12-15T19:20:49.791Z" }, + { url = "https://files.pythonhosted.org/packages/ba/b5/206f82d51e1bfa940ba366a8d2f83904b15942c45a78dd978b599870ab44/tornado-6.5.4-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1cf66105dc6acb5af613c054955b8137e34a03698aa53272dbda4afe252be17", size = 445746, upload-time = "2025-12-15T19:20:51.491Z" }, + { url = "https://files.pythonhosted.org/packages/8e/9d/1a3338e0bd30ada6ad4356c13a0a6c35fbc859063fa7eddb309183364ac1/tornado-6.5.4-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50ff0a58b0dc97939d29da29cd624da010e7f804746621c78d14b80238669335", size = 445083, upload-time = "2025-12-15T19:20:52.778Z" }, + { url = "https://files.pythonhosted.org/packages/50/d4/e51d52047e7eb9a582da59f32125d17c0482d065afd5d3bc435ff2120dc5/tornado-6.5.4-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5fb5e04efa54cf0baabdd10061eb4148e0be137166146fff835745f59ab9f7f", size = 445315, upload-time = "2025-12-15T19:20:53.996Z" }, + { url = "https://files.pythonhosted.org/packages/27/07/2273972f69ca63dbc139694a3fc4684edec3ea3f9efabf77ed32483b875c/tornado-6.5.4-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9c86b1643b33a4cd415f8d0fe53045f913bf07b4a3ef646b735a6a86047dda84", size = 446003, upload-time = "2025-12-15T19:20:56.101Z" }, + { url = "https://files.pythonhosted.org/packages/d1/83/41c52e47502bf7260044413b6770d1a48dda2f0246f95ee1384a3cd9c44a/tornado-6.5.4-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:6eb82872335a53dd063a4f10917b3efd28270b56a33db69009606a0312660a6f", size = 445412, upload-time = "2025-12-15T19:20:57.398Z" }, + { url = "https://files.pythonhosted.org/packages/10/c7/bc96917f06cbee182d44735d4ecde9c432e25b84f4c2086143013e7b9e52/tornado-6.5.4-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6076d5dda368c9328ff41ab5d9dd3608e695e8225d1cd0fd1e006f05da3635a8", size = 445392, upload-time = "2025-12-15T19:20:58.692Z" }, + { url = "https://files.pythonhosted.org/packages/0c/1a/d7592328d037d36f2d2462f4bc1fbb383eec9278bc786c1b111cbbd44cfa/tornado-6.5.4-cp39-abi3-win32.whl", hash = "sha256:1768110f2411d5cd281bac0a090f707223ce77fd110424361092859e089b38d1", size = 446481, upload-time = "2025-12-15T19:21:00.008Z" }, + { url = "https://files.pythonhosted.org/packages/d6/6d/c69be695a0a64fd37a97db12355a035a6d90f79067a3cf936ec2b1dc38cd/tornado-6.5.4-cp39-abi3-win_amd64.whl", hash = "sha256:fa07d31e0cd85c60713f2b995da613588aa03e1303d75705dca6af8babc18ddc", size = 446886, upload-time = "2025-12-15T19:21:01.287Z" }, + { url = "https://files.pythonhosted.org/packages/50/49/8dc3fd90902f70084bd2cd059d576ddb4f8bb44c2c7c0e33a11422acb17e/tornado-6.5.4-cp39-abi3-win_arm64.whl", hash = "sha256:053e6e16701eb6cbe641f308f4c1a9541f91b6261991160391bfc342e8a551a1", size = 445910, upload-time = "2025-12-15T19:21:02.571Z" }, +] + [[package]] name = "tqdm" version = "4.67.3" @@ -1020,6 +2265,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/16/e1/3079a9ff9b8e11b846c6ac5c8b5bfb7ff225eee721825310c91b3b50304f/tqdm-4.67.3-py3-none-any.whl", hash = "sha256:ee1e4c0e59148062281c49d80b25b67771a127c85fc9676d3be5f243206826bf", size = 78374, upload-time = "2026-02-03T17:35:50.982Z" }, ] +[[package]] +name = "traitlets" +version = "5.14.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/eb/79/72064e6a701c2183016abbbfedaba506d81e30e232a68c9f0d6f6fcd1574/traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", size = 161621, upload-time = "2024-04-19T11:11:49.746Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/c0/8f5d070730d7836adc9c9b6408dec68c6ced86b304a9b26a14df072a6e8c/traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f", size = 85359, upload-time = "2024-04-19T11:11:46.763Z" }, +] + [[package]] name = "typing-extensions" version = "4.15.0" @@ -1038,6 +2292,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, ] +[[package]] +name = "uri-template" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/31/c7/0336f2bd0bcbada6ccef7aaa25e443c118a704f828a0620c6fa0207c1b64/uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7", size = 21678, upload-time = "2023-06-21T01:49:05.374Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/00/3fca040d7cf8a32776d3d81a00c8ee7457e00f80c649f1e4a863c8321ae9/uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363", size = 11140, upload-time = "2023-06-21T01:49:03.467Z" }, +] + [[package]] name = "url-normalize" version = "2.2.1" @@ -1059,6 +2322,51 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" }, ] +[[package]] +name = "wcwidth" +version = "0.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/35/a2/8e3becb46433538a38726c948d3399905a4c7cabd0df578ede5dc51f0ec2/wcwidth-0.6.0.tar.gz", hash = "sha256:cdc4e4262d6ef9a1a57e018384cbeb1208d8abbc64176027e2c2455c81313159", size = 159684, upload-time = "2026-02-06T19:19:40.919Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/68/5a/199c59e0a824a3db2b89c5d2dade7ab5f9624dbf6448dc291b46d5ec94d3/wcwidth-0.6.0-py3-none-any.whl", hash = "sha256:1a3a1e510b553315f8e146c54764f4fb6264ffad731b3d78088cdb1478ffbdad", size = 94189, upload-time = "2026-02-06T19:19:39.646Z" }, +] + +[[package]] +name = "webcolors" +version = "25.10.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/7a/eb316761ec35664ea5174709a68bbd3389de60d4a1ebab8808bfc264ed67/webcolors-25.10.0.tar.gz", hash = "sha256:62abae86504f66d0f6364c2a8520de4a0c47b80c03fc3a5f1815fedbef7c19bf", size = 53491, upload-time = "2025-10-31T07:51:03.977Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e2/cc/e097523dd85c9cf5d354f78310927f1656c422bd7b2613b2db3e3f9a0f2c/webcolors-25.10.0-py3-none-any.whl", hash = "sha256:032c727334856fc0b968f63daa252a1ac93d33db2f5267756623c210e57a4f1d", size = 14905, upload-time = "2025-10-31T07:51:01.778Z" }, +] + +[[package]] +name = "webencodings" +version = "0.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0b/02/ae6ceac1baeda530866a85075641cec12989bd8d31af6d5ab4a3e8c92f47/webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923", size = 9721, upload-time = "2017-04-05T20:21:34.189Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f4/24/2a3e3df732393fed8b3ebf2ec078f05546de641fe1b667ee316ec1dcf3b7/webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", size = 11774, upload-time = "2017-04-05T20:21:32.581Z" }, +] + +[[package]] +name = "websocket-client" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2c/41/aa4bf9664e4cda14c3b39865b12251e8e7d239f4cd0e3cc1b6c2ccde25c1/websocket_client-1.9.0.tar.gz", hash = "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", size = 70576, upload-time = "2025-10-07T21:16:36.495Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/34/db/b10e48aa8fff7407e67470363eac595018441cf32d5e1001567a7aeba5d2/websocket_client-1.9.0-py3-none-any.whl", hash = "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef", size = 82616, upload-time = "2025-10-07T21:16:34.951Z" }, +] + +[[package]] +name = "widgetsnbextension" +version = "4.0.15" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/f4/c67440c7fb409a71b7404b7aefcd7569a9c0d6bd071299bf4198ae7a5d95/widgetsnbextension-4.0.15.tar.gz", hash = "sha256:de8610639996f1567952d763a5a41af8af37f2575a41f9852a38f947eb82a3b9", size = 1097402, upload-time = "2025-11-01T21:15:55.178Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3f/0e/fa3b193432cfc60c93b42f3be03365f5f909d2b3ea410295cf36df739e31/widgetsnbextension-4.0.15-py3-none-any.whl", hash = "sha256:8156704e4346a571d9ce73b84bee86a29906c9abfd7223b7228a28899ccf3366", size = 2196503, upload-time = "2025-11-01T21:15:53.565Z" }, +] + [[package]] name = "xlrd" version = "2.0.2" From aad2416e4f9e2eca748900a765e20c6302584662 Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Thu, 26 Feb 2026 16:45:14 +0000 Subject: [PATCH 92/92] update gha with uv --- .github/workflows/publish.yaml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 9d3a49e9..caf70af6 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -1,6 +1,6 @@ name: Publish slides and notebooks -on: +on: push: branches: - main @@ -11,24 +11,24 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v6 with: - python-version: '3.10' - - run: pip install -r requirements.txt + python-version: "3.13" + + - name: Install the default version of uv + id: setup-uv + uses: astral-sh/setup-uv@v7 - name: Set up quarto uses: quarto-dev/quarto-actions/setup@v2 - - name: Render FR version - uses: quarto-dev/quarto-actions/render@v2 - env: - QUARTO_PROFILE: fr - - name: Render EN version - uses: quarto-dev/quarto-actions/render@v2 - env: - QUARTO_PROFILE: en + - name: Render FR and EN version + run: | + uv run quarto render --profile fr + uv run quarto render --profile en + - name: Publish to GitHub Pages (and render) uses: quarto-dev/quarto-actions/publish@v2 with:

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%0D*ILLPANN>@iit(u#cmU-<*tGWLBWuqR^x1N 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 R05bf`NY6~STH7i7{{a*8ztI2y literal 0 HcmV?d00001 diff --git a/source/manipulation/polars/img/polars-split-parallel-apply-combine.svg b/source/manipulation/polars/img/polars-split-parallel-apply-combine.svg new file mode 100644 index 00000000..434fbeb0 --- /dev/null +++ b/source/manipulation/polars/img/polars-split-parallel-apply-combine.svg @@ -0,0 +1,2526 @@ + + + + + + + + + + + + + x + + + + x + + + + + + + + + y + + + + y + + + + + + + + + 1 + + + + 1 + + + + + + + + + 2 + + + + 2 + + + + + + + + + 3 + + + + 3 + + + + + + + + + 5 + + + + 5 + + + + + + + + + 4 + + + + 4 + + + + + + + + + 6 + + + + 6 + + + + + + + + + a + + + + a + + + + + + + + + a + + + + a + + + + + + + + + b + + + + b + + + + + + + + + c + + + + c + + + + + + + + + b + + + + b + + + + + + + + + c + + + + c + + + + + + + + + + + + + + + x + + + + x + + + + + + + + + y + + + + y + + + + + + + + + 1 + + + + 1 + + + + + + + + + 2 + + + + 2 + + + + + + + + + a + + + + a + + + + + + + + + a + + + + a + + + + + + + + + x + + + + x + + + + + + + + + y + + + + y + + + + + + + + + 3 + + + + 3 + + + + + + + + + 4 + + + + 4 + + + + + + + + + b + + + + b + + + + + + + + + b + + + + b + + + + + + + + + x + + + + x + + + + + + + + + y + + + + y + + + + + + + + + 5 + + + + 5 + + + + + + + + + 6 + + + + 6 + + + + + + + + + c + + + + c + + + + + + + + + c + + + + c + + + + + + + + + split + + + + split + + + + + + + + + + + + + + + apply + + + + apply + + + + + + + + + x + + + + x + + + + + + + + + y + + + + y + + + + + + + + + 3 + + + + 3 + + + + + + + + + a + + + + a + + + + + + + + + 7 + + + + 7 + + + + + + + + + b + + + + b + + + + + + + + + 11 + + + + 11 + + + + + + + + + c + + + + c + + + + + + + + + + + + + + + combine + + + + combine + + + + + + + + + + Embarrassingly parallel + + + + + + Embarrassingly parallel + + + + + + + + + data + + + + data + + + + + + Viewer does not support full SVG 1.1 + + + + + + + + + + x + + + + x + + + + + + + + + y + + + + y + + + + + + + + + 3 + + + + 3 + + + + + + + + + a + + + + a + + + + + + + + + x + + + + x + + + + + + + + + y + + + + y + + + + + + + + + 7 + + + + 7 + + + + + + + + + b + + + + b + + + + + + + + + x + + + + x + + + + + + + + + y + + + + y + + + + + + + + + 11 + + + + 11 + + + + + + + + + c + + + + c + + + + diff --git a/source/manipulation/polars/img/structure_df.png b/source/manipulation/polars/img/structure_df.png deleted file mode 100644 index c77d08cd40924dc848d570e7be9050f116a93051..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 164895 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%0D`*i=n)D=_x`5c_u4L#?^;uEk`^Xs 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�B^?=k$hb+wTeY#;+HZC` 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 diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index a1b18e2b..82fc9583 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -1,15 +1,149 @@ ::: {.content-visible when-profile="fr"} # Traiter des données tabulaires avec Polars -L'analyse statistique a généralement pour base des **données tabulaires**, dans lesquelles chaque ligne représente une observation et chaque colonne une variable. Pour traiter ce type de données et y appliquer facilement les méthodes d'analyse de données standards, des objets dédiés ont été conçus : les `DataFrames`. Les utilisateurs de `R` connaissent bien cette structure de données, qui est native à ce langage orienté statistique. En `Python`, langage généraliste, cet objet n'existe pas nativement. +L'analyse statistique a généralement pour base des **données tabulaires**, dans lesquelles chaque ligne représente une observation et chaque colonne une variable. +Pour traiter ce type de données et y appliquer facilement les méthodes d'analyse de données standards, des objets dédiés ont été conçus : les `DataFrames`. +Les utilisateurs de `R` connaissent bien cette structure de données, qui est native à ce langage orienté statistique. +En `Python`, langage généraliste, cet objet n'existe pas nativement. +Plusieurs packages viennent ainsi combler ce manque, comme `pandas`, XX. + +## Les atouts de Polars + +Les _benchmarks_ disponibles [sont clairs](https://h2oai.github.io/db-benchmark/) : `Polars` est +un ours qui court vite ! + +Le benchmark suivant, [effectué par H2O](https://h2oai.github.io/db-benchmark/), propose +un comparatif de la vitesse des principaux frameworks de manipulation de données +pour effectuer une agrégation par groupe avec un jeu de données de 50GB: + +![Benchmark H2O](img/polars-benchmark-short.png) + +`Polars` devance des solutions connues pour leur efficacité sur ce type d'opérations, +comme le package `R` `data.table`. L'utilisateur habituel de `Pandas` +ne pourrait même pas traiter ces données, qui excèdent les capacités computationnelles +de sa machine. + +### L'évaluation _lazy_ + +Plusieurs éléments expliquent cette rapidité. + +En premier lieu, `Polars` est conçu pour optimiser les requêtes : +grâce au mode _lazy_ (_"paresseux"_), +on laisse la possibilité au moteur d'analyser ce qu'on souhaite faire +pour proposer une exécution optimale (pour la lecture comme pour la transformation des jeux de données). +La _lazy evaluation_ est une méthode assez commune pour améliorer la vitesse +des traitements et est utilisée, entre autres, par `Spark`. + +Du fait de +la _lazy evaluation_ il est ainsi possible, par exemple, +si un filtre sur les lignes arrive +tardivement, de le remonter dans l'ordre des opérations effectuées par `Python` +afin que +les opérations ultérieures ne soient effectuées que sur +l'ensemble optimal de données. +Ces optimisations sont détaillées dans la [documentation officielle](https://pola-rs.github.io/polars-book/user-guide/optimizations/intro.html). + + +### Lecture optimisée des fichiers + +L'utilisateur `Pandas` est habitué à lire du CSV avec `pd.read_csv`. +Avec `Polars`, il existe deux manières, très ressemblantes +de le faire. + +```python +import polars as pl + +# Création d'une requête +q = ( + pl.scan_csv("iris.csv") # Lecture lazy + .filter(pl.col("sepal_length") > 5) + .groupby("species") + .agg(pl.all().sum()) +) + +# Exécution de la requête +df = q.collect() +``` + +Avec cette syntaxe, les connaisseurs de `Pyspark` retrouveront facilement leurs petits (ours 🐻). + +On peut toujours lire de manière plus directe +(en mode _eager_, _"impatient"_) en utilisant la fonction `read_csv`, +et ensuite appliquer des transformations optimisables en glissant habilement `lazy` : + +```python +df = pl.read_csv("iris.csv") + +df_res = df.lazy() # ← ici :) + .filter(pl.col("sepal_length") > 5) + .groupby("species") + .agg(pl.all().sum()) + .collect() +``` + +`Polars` fonctionne également très bien avec le format `Parquet`, comme illustré dans +le _notebook_ qui accompagne ce _post_. -On commence par importer la librairie `Polars`. L'usage est courant est de lui attribuer l'alias `pl` afin de simplifier les futurs appels aux objets et fonctions du package. -Intro, reprendre de +### Parallélisation +`Polars` parallélise les traitements dès que cela est possible, notamment dans le cas d'agrégation. +Chaque coeur se charge d'une partie de l'agrégation et envoie des données plus légères à `Python` +qui va finaliser l'agrégation. -- [Lien réparé vers le notebook Polars](https://datalab.sspcloud.fr/launcher/ide/jupyter-python?name=Tutoriel%20Polars&version=2.3.28&s3=region-79669f20&init.personalInit=«https%3A%2F%2Fraw.githubusercontent.com%2Fntoulemonde%2Ftest%2Frefs%2Fheads%2Fmain%2Finit.sh»&autoLaunch=true) +![Parallélisation](img/polars-split-parallel-apply-combine.svg) +_Illustration du principe de la parallélisation_ + +Sur les systèmes proposant de nombreux coeurs, cela peut faire gagner beaucoup de temps. + +### Des couches basses à la pointe + +Enfin, le choix d'utiliser à la fois le format de représentation en mémoire [Arrow](https://arrow.apache.org/) et le langage [Rust](https://www.rust-lang.org/fr) pour le coeur de la bibliothèque n'est pas étranger à cette performance. + +### Calculs _out of memory_ + +`Polars` travaille vite mais présente aussi l'avantage +de lire naturellement des jeux de données hors des limites de la mémoire de l'ordinateur grâce à [sa capacité de lire en flux](https://www.youtube.com/watch?v=3-C0Afs5TXQ) (méthode qu'on appelle le _streaming_). + + +```python +# La même requête que tout à l'heure va lire le fichier "en flux" +df = q.collect(streaming=True) +``` + +De plus, `Polars` lit nativement les fichiers `Parquet` qui par ses propriétés +permet d'aller beaucoup plus vite que le CSV ! + +# Une API fluide + +C'est un reproche régulièrement fait à `Pandas` : +la syntaxe de manipulations des données est parfois complexe ou peu lisible, et les choix d'écriture ne sont pas transparents du point de vue des performances. + +L'API proposée par Polars est à la fois expressive et transparente. +Voici un exemple d'exploitation de la BPE, issu du _notebook_ accompagnant +ce _post_ : + +```python +df.lazy() + .filter( + pl.col("TYPEQU") == "B316" + ) + .groupby("DEP") + .agg( + pl.count().alias("NB_STATION_SERVICE") + ) + .collect() +``` + +# Un pipe natif +On retrouve une sémantique d'opérations de haut niveau qui s'enchaînent à la manière de [ce que l'on peut faire en `dplyr`](https://www.book.utilitr.org/03_fiches_thematiques/fiche_tidyverse#comment-utiliser-lop%C3%A9rateur-pipe-avec-le-tidyverse). + + + + + +On commence par importer la librairie `Polars`. L'usage est courant est de lui attribuer l'alias `pl` afin de simplifier les futurs appels aux objets et fonctions du package. Polars plus proche de l'univers du tidyverse pour des personnes venant de R. beaucoup plus rapide que pandas @@ -19,23 +153,20 @@ très strict sur les types des colonnes Parler de : -- types : FAIT - colonnes sont associées à des string. - pas d'index. - polars selectors -- pipe - lazy eval - unnest "TO DO" - Polars Séries -"TO DO" les sélecteurs dans Polars pour aller plus loin : - interconnection avec duckDB pour des requêtes en SQL Ressources : -https://ddotta.github.io/awesome-polars/ - +- [Blog Awesome Polars](https://ddotta.github.io/awesome-polars/), par Damien D +- [Notebook Polars](https://datalab.sspcloud.fr/launcher/ide/jupyter-python?name=Tutoriel%20Polars&version=2.3.28&s3=region-79669f20&init.personalInit=«https%3A%2F%2Fraw.githubusercontent.com%2Fntoulemonde%2Ftest%2Frefs%2Fheads%2Fmain%2Finit.sh»&autoLaunch=true) ::: {.panel-tabset group="polars_vs_tidypolars"}} @@ -1311,23 +1442,19 @@ df_a.join(df_b, how="full", on='key', coalesce=True) ### Questions de compréhension -- 1/ Qu'est-ce qu'un DataFrame dans le contexte de Pandas et à quel type de structure de données peut-on le comparer dans le langage Python ? - -- 2/ Quelle est la différence fondamentale entre un array Numpy et une Pandas Series ? +- 1/ Qu'est-ce qu'un DataFrame dans le contexte de Polars et à quel type de structure de données peut-on le comparer dans le langage Python ? -- 3/ Quel est le lien entre Series et DataFrame dans Pandas ? +- 2/ Quels sont les avantages de Polars ? -- 4/ Comment sont structurées les données dans un DataFrame Pandas ? +- 3/ Quel est le lien entre Series et DataFrame dans Polars ? -- 5/ Quel est le rôle de l'index dans un DataFrame Pandas et comment peut-il être utilisé lors de la manipulation des données ? +- 4/ Comment sont structurées les données dans un DataFrame Polars ? - 6/ Quelles méthodes pouvez-vous utiliser pour explorer un DataFrame inconnu et en apprendre davantage sur son contenu et sa structure ? -- 7/ Dans Pandas, quelle est la différence entre assigner le résultat d'une opération à une nouvelle variable et utiliser une méthode avec l'argument `inplace=True` ? - -- 8/ Comment s'applique le principe de la vectorisation dans Pandas et pourquoi est-ce avantageux pour manipuler les données ? +- 8/ Comment s'applique le principe d'évaluation paresseuse dans Polars et pourquoi est-ce avantageux pour manipuler les données ? -- 9/ Comment Pandas représente-t-il les valeurs manquantes et quel impact cela a-t-il sur les calculs et les transformations de données ? +- 9/ Comment Polars représente-t-il les valeurs manquantes et quel impact cela a-t-il sur les calculs et les transformations de données ? - 10/ Quelle est la différence entre concaténer deux DataFrames et les joindre via une jointure, et quand utiliseriez-vous l'une plutôt que l'autre ? From 6348c4c9aa145f641e97e2cf030ce47d665b34ff Mon Sep 17 00:00:00 2001 From: nicolastlm <192305627+ntoulemonde@users.noreply.github.com> Date: Wed, 21 Jan 2026 16:39:21 +0000 Subject: [PATCH 30/92] without english part --- source/manipulation/polars/tutorial.qmd | 2059 ----------------------- 1 file changed, 2059 deletions(-) diff --git a/source/manipulation/polars/tutorial.qmd b/source/manipulation/polars/tutorial.qmd index 82fc9583..3b97de3a 100644 --- a/source/manipulation/polars/tutorial.qmd +++ b/source/manipulation/polars/tutorial.qmd @@ -2549,2062 +2549,3 @@ df_clean.head(20) - - - - - - - - - - -::: {.content-visible when-profile="en"} - -# Working with tabular data using Pandas - -Statistical analysis is generally based on **tabular data**, where each row represents an observation and each column a variable. To handle this type of data and easily apply standard data analysis methods, dedicated objects have been designed: `DataFrames`. Users of `R` are well acquainted with this data structure, which is native to this statistics-oriented language. In `Python`, a general-purpose language, this object does not exist natively. Fortunately, a very comprehensive and convenient library, designed as an overlay to `NumPy`, introduces the `DataFrame` object in `Python` and allows for simple and intuitive data manipulation and analysis: `Pandas`. - -::: {.callout-note} -Pandas is the central element of the data science ecosystem in Python, offering virtually infinite data processing capabilities. Moreover, there are generally multiple ways to perform the same operation in Pandas. Consequently, this chapter is particularly long and dense with new features. The goal is not to memorize all the methods presented throughout this chapter, but rather to have a general overview of what is possible in order to use the right tools in projects. In particular, the end-of-chapter exercises and the mini-projects at the end of the course will provide an opportunity to apply this new knowledge to concrete problems. -::: - -Let's start by importing the `Pandas` library. The common usage is to give it the alias `pd` to simplify future calls to the package's objects and functions. We also import `NumPy` as we will compare the fundamental objects of the two packages. - -```{python} -import pandas as pd -import numpy as np -``` - -## Data structures - -To fully understand how `Pandas` works, it is important to focus on its fundamental objects. We will therefore first study the `Series`, whose concatenation allows us to build a `DataFrame`. - -### The `Series` - -A Series is a one-dimensional data container that can hold any type of data (integers, strings, Python objects...). However, a Series is of a given type: a Series containing only integers will be of type `int`, and a Series containing objects of different natures will be of type `object`. Let's build our first Series from a list to check this behavior. - -```{python} -l = [1, "X", 3] -s = pd.Series(l) -print(s) -``` - -In particular, we can access the data of a Series by position, as for a list or an array. - -```{python} -print(s[1]) -``` - -At first glance, we do not see much difference between a Series and a one-dimensional `NumPy` array. However, there is a significant difference: the presence of an index. The observations have an associated label. When we create a Series without specifying anything, the index is automatically set to the integers from 0 to n-1 (with n being the number of elements in the Series). But it is possible to pass a specific index (e.g., dates, town names, etc.). - -```{python} -s = pd.Series(l, index=["a", "b", "c"]) -print(s) -``` - -This allows us to access the data by label: - -```{python} -s["b"] -``` - -This difference may seem minor at first, but it becomes essential for constructing the DataFrame. For the rest, Series behave very similarly to NumPy arrays: calculations are vectorized, we can directly sum two Series, etc. Moreover, we can easily convert a Series into an array via the `values` attribute. This naturally loses the index... - -```{python} -s = pd.Series(l, index=["a", "b", "c"]) -s.values -``` - -### The `DataFrame` - -Fundamentally, a DataFrame consists of a collection of Series, aligned by their indexes. This concatenation thus constructs a data table, with Series corresponding to columns, and the index identifying the rows. The following figure ([source](https://www.geeksforgeeks.org/creating-a-pandas-dataframe/)) helps to understand this data structure. - -![](img/structure_df.png){fig-align="center" width="800"} - -A DataFrame can be constructed in multiple ways. In practice, we generally build a DataFrame directly from tabular data files (e.g., CSV, Excel), rarely by hand. So, we will only illustrate the most common manual construction method: from a data dictionary. - -```{python} -df = pd.DataFrame( - data = { - "var1": [1.3, 5.6, None, np.nan, 0, np.nan], - "var2": np.random.randint(-10, 10, 6), - "experiment": ["test", "train", "test", "train", "train", "validation"], - "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-01-05", "2022-01-06"], - "sample": "sample1" - } -) - -df -``` - -A Pandas DataFrame has a set of useful attributes that we will discover throughout this tutorial. For now, let's focus on the most basic ones: the index and the column names. By default, the index is initialized, as for Series, to the list of positions of the observations. We could have specified an alternative index when constructing the DataFrame by specifying the `index` argument of the `pd.DataFrame` function. - -```{python} -df.index -``` - -```{python} -df.columns -``` - -Often, rather than specifying an index manually during the construction of the DataFrame, we will want to use a certain column of the DataFrame as an index. We use the `set_index` method associated with DataFrames for this. - -```{python} -df = df.set_index("date") -df -``` - -The index attribute has naturally changed: - -```{python} -df.index -``` - -## Selecting data - -When manipulating tabular data, it is common to want to extract specific columns from a `DataFrame`. This extraction is simple with `Pandas` using square brackets. - -### Selecting columns - -#### Selecting a single column - -To extract a single column, we can use the following syntax: - -```{python} -selected_column = df["var1"] -selected_column -``` - -The `selected_column` object here returns the column named `var1` from the `DataFrame` `df`. But what type is this object? To answer this question, we use the `type()` function: - -```{python} -type(selected_column) -``` - -As we can see, the result is a `Series`, which is a one-dimensional object in `Pandas`. - -Another useful attribute to know is `shape`. It allows us to know the dimension of the object. For a `Series`, `shape` will return a tuple whose first element indicates the number of rows. - -```{python} -selected_column.shape -``` - -#### Selecting multiple columns - -To extract multiple columns, just pass a list of the desired column names: - -```{python} -selected_columns = df[["var1", "var2", "experiment"]] -selected_columns -``` - -This snippet shows the columns `var1`, `var2`, and `experiment` from the `DataFrame` `df`. Let's now check its type: - -```{python} -type(selected_columns) -``` - -The result is a `DataFrame` because it is a two-dimensional object. We can also check its shape with the `shape` attribute. In this case, the tuple returned by `shape` will contain two elements: the number of rows and the number of columns. - -```{python} -selected_columns.shape -``` - -### Selecting rows - -#### Using `loc` and `iloc` - -When we want to select specific rows in a DataFrame, we can use two main methods: `loc` and `iloc`. - -- `iloc` allows selecting rows and columns by their position, i.e., by numeric indices. - -Example, selecting the first 3 rows: - -```{python} -df.iloc[0:3, :] -``` - -- `loc` works with labels. If the DataFrame's indexes are numbers, they resemble positions, but this is not necessarily the case. It is crucial to note that, unlike `iloc`, with `loc`, the end index is included in the selection. - -```{python} -df.loc["2022-01-01":"2022-01-03", :] -``` - -#### Filtering data based on conditions - -In practice, rather than selecting rows based on positions or labels, we often want to filter a DataFrame based on certain conditions. In this case, we primarily use boolean filters. - -- **Inequalities**: We might want to keep only the rows that meet a certain condition. - -Example, filtering rows where the value of the `var2` column is greater than 0: - -```{python} -df[df['var2'] >= 0] -``` - -- **Membership with `isin`**: If we want to filter data based on a list of possible values, the `isin` method is very useful. - -Example, to keep only the rows where the `experiment` column has values 'test' or 'validation': - -```{python} -df[df['experiment'].isin(['train', 'validation'])] -``` - -These methods can be combined to create more complex conditions. It is also possible to use logical operators (`&` for "and", `|` for "or") to combine multiple conditions. Be careful to enclose each condition in parentheses when combining them. - -Example, selecting rows where `var2` is greater than 0 and `experiment` is equal to 'test' or 'validation': - -```{python} -df[(df['var2'] >= 0) & (df['experiment'].isin(['train', 'validation']))] -``` - -## Exploring tabular data - -In public statistics, the starting point is generally not the manual generation of data but rather pre-existing tab - -ular files. These files, whether from surveys, administrative databases, or other sources, constitute the raw material for any subsequent analysis. Pandas offers powerful tools to import these tabular files and explore them for further manipulations. - -### Importing and exporting data - -#### Importing a CSV file - -As we saw in a previous lab, the CSV format is one of the most common formats for storing tabular data. We previously used the `csv` library to handle them as text files, but it was not very convenient. To recall, the syntax for reading a CSV file and displaying the first lines was as follows: - -```{python} -import csv - -rows = [] - -with open("data/departement2021.csv") as file_in: - csv_reader = csv.reader(file_in) - for row in csv_reader: - rows.append(row) - -rows[:5] -``` - -With Pandas, just use the `read_csv()` function to import the file as a DataFrame, then the `head()` function. - -```{python} -df_departements = pd.read_csv('data/departement2021.csv') -df_departements.head() -``` - -It is also possible to import a CSV file directly from a URL. This is particularly convenient when the data is regularly updated on a website, and we want to access the latest version without manually downloading the file each time. Let's take the example of a CSV file available on the INSEE website: the file of given names, from civil status data. We also note another handy feature: the CSV file is compressed (in `zip` format), but Pandas can recognize and decompress it before importing. - -```{python} -# Importing a CSV file from a URL -url = "https://www.insee.fr/fr/statistiques/fichier/2540004/nat2021_csv.zip" -df_prenoms_url = pd.read_csv(url, sep=";") -df_prenoms_url.head() -``` - -When working with CSV files, there are many optional arguments available in the `read_csv()` function that allow us to adjust the import process according to the specifics of the file. These arguments can, for example, define a specific delimiter (as above for the given names file), skip certain lines at the beginning of the file, or define data types for each column, and many others. All these parameters and their usage are detailed in the [official documentation](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html). - -#### Exporting to CSV format - -Once the data has been processed and modified within Pandas, it is common to want to export the result as a CSV file for sharing, archiving, or use in other tools. Pandas offers a simple method for this operation: `to_csv()`. Suppose we want to export the data from the `df_departements` DataFrame specific to the five overseas departments. - -```{python} -df_departements_dom = df_departements[df_departements["DEP"].isin(["971", "972", "973", "974", "975"])] -df_departements_dom.to_csv('output/departements2021_dom.csv') -``` - -One of the key arguments of the `to_csv()` method is `index`. By default, `index=True`, which means that the DataFrame's index will also be written in the CSV file. We can verify this by printing the first lines of our CSV file: Pandas has added an unnamed column, which contains the index of the retained rows. - -```{python} -with open("output/departements2021_dom.csv") as file_in: - for i in range(5): - row = next(file_in).strip() - print(row) -``` - -In some cases, notably when the index does not provide useful information or is simply automatically generated by Pandas, we might want to exclude it from the exported file. To do this, we can set `index=False`. - -```{python} -df_departements_dom.to_csv('output/departements2021_dom_noindex.csv', index=False) -``` - -#### Importing a Parquet file - -The Parquet format is another format for storing tabular data, increasingly used. Without going into technical details, the Parquet format has various characteristics that make it a preferred choice for storing and processing large volumes of data. Due to these advantages, this format is increasingly used for data dissemination at INSEE. It is therefore essential to know how to import and query Parquet files with Pandas. - -Importing a Parquet file into a Pandas DataFrame is as easy as for a CSV file. The function is called `read_parquet()`. - -```{python} -df_departements = pd.read_parquet('data/departement2021.parquet') -df_departements.head() -``` - -#### Exporting to Parquet format - -Again, everything works as in the CSV world: we use the `to_parquet()` method to export a DataFrame to a Parquet file. Similarly, we can choose to export or not the index, using the `index` parameter (which defaults to `True`). - -```{python} -df_departements_dom = df_departements[df_departements["DEP"].isin(["971", "972", "973", "974", "975"])] -df_departements_dom.to_parquet('output/departements2021_dom.parquet', index=False) -``` - -One of the major strengths of the Parquet format, compared to text formats like CSV, is its ability to store metadata, i.e., data that helps better understand the data contained in the file. In particular, a Parquet file includes in its metadata the data schema (variable names, variable types, etc.), making it a very suitable format for data dissemination. Let's verify this behavior by revisiting the DataFrame we defined earlier. - -```{python} -df = pd.DataFrame( - data = { - "var1": [1.3, 5.6, None, None, 0, None], - "var2": np.random.randint(-10, 10, 6), - "experiment": ["test", "train", "test", "train", "train", "validation"], - "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-01-05", "2022-01-06"], - "sample": "sample1" - } -) - -df = df.assign( - experiment=pd.Categorical(df["experiment"]), - date=pd.to_datetime(df["date"]) -) -``` - -This time, we use two specific data types, for categorical data (`category`) and for temporal data (`datetime`). We will see later in the tutorial how to use these types. For now, let's simply note that Pandas stores these types in the data schema. - -```{python} -df.info() -``` - -Let's now verify that exporting and re-importing this data in Parquet preserves the schema. - -```{python} -df.to_parquet("output/df_test_schema.parquet", index=False) -df_test_schema_parquet = pd.read_parquet('output/df_test_schema.parquet') - -df_test_schema_parquet.info() -``` - -Conversely, a CSV file, which by definition only contains text, does not preserve this data. The variables for which we specified the type are imported as strings (type `object` in Pandas). - -```{python} -df.to_csv("output/df_test_schema.csv", index=False) -df_test_schema_csv = pd.read_csv('output/df_test_schema.csv') - -df_test_schema_csv.info() -``` - -### Viewing a sample of data - -When working with large datasets, it is often useful to quickly view a sample of the data to get an idea of its structure, format, or even to detect potential problems. Pandas offers several methods for this. - -The `head()` method displays the first rows of the DataFrame. By default, it returns the first 5 rows, but we can specify another number as an argument if necessary. - -```{python} -df_departements.head() -``` - -```{python} -df_departements.head(10) -``` - -Conversely, the `tail()` method gives a preview of the last rows of the DataFrame. - -```{python} -df_departements.tail() -``` - -Displaying the first or last rows may sometimes not be representative of the entire dataset, especially when the data is sorted. To minimize the risk of obtaining a biased overview of the data, we can use the `sample()` method, which selects a random sample of rows. By default, it returns a single row, but we can request a specific number of rows using the `n` argument. - -```{python} -df_departements.sample(n=5) -``` - -### Getting an overview of the data - -One of the first steps when exploring new data is to understand the general structure of the dataset. The `info()` method in Pandas provides a quick overview of the data, including data types, the presence of missing values, and memory usage. - -```{python} -df.info() -``` - -Several key pieces of information can be extracted from this result: - -- **index**: The DataFrame has a `RangeIndex`, which means the index is a simple numeric sequence. Here, the index ranges from 0 to 5, for a total of 6 entries. - -- **schema**: The list of columns is displayed with very useful information about the data schema: - - - **Non-Null Count**: The number of **non-missing** (non-`nan`) values in the column. If this number is less than the total number of entries (in our case, 6), it means the column contains missing values. Note the possible ambiguity on "null": this indeed means missing values, not values equal to 0. Thus, in our case, the number of "non-null" values for the `var1` variable is 5. - - - **Dtype**: The data type of the column, which helps understand the nature of the information stored in each column. For example, `float64` - - (real numbers), `int32` (integers), `category` (categorical variable), `datetime64[ns]` (temporal information), and `object` (text or mixed data). - -Using `info()` is a quick and effective way to get an overview of a DataFrame, quickly identify columns containing missing values, and understand the data structure. - -### Calculating descriptive statistics - -In addition to the information returned by the `info()` method, we might want to obtain simple descriptive statistics to quickly visualize the distributions of variables. The `describe()` method provides a synthetic view of the distribution of data in each column. - -```{python} -df.describe() -``` - -It should be noted that `describe()` only returns statistics for numeric columns by default. If we want to include columns of other types, we need to specify this via the `include` argument. For example, `df.describe(include='all')` will return statistics for all columns, including metrics such as the unique count, the most frequent value, and the frequency of the most frequent value for non-numeric columns. - -```{python} -df.describe(include='all') -``` - -Note again that the `count` variable returns the number of **non-missing** values in each variable. - -## Main data manipulations - -### Transforming data - -Data transformation operations are essential for shaping, cleaning, and preparing data for analysis. Transformations can apply to the entire DataFrame, specific columns, or specific rows. - -#### Transforming a DataFrame - -To transform an entire DataFrame (or a sub-DataFrame), it is possible to use vectorized functions, which allow quickly applying an operation to all elements of the DataFrame. This includes a number of methods available for `Series`, as well as NumPy mathematical functions, etc. - -For example, raising each numeric value in a DataFrame to the power of 2: - -```{python} -df = pd.DataFrame( - data = { - "var1": [1.3, 5.6, None, None, 0, None], - "var2": np.random.randint(-10, 10, 6), - } -) - -df ** 2 -``` - -or taking the absolute value: - -```{python} -np.abs(df) -``` - -Some methods available for `Series` can also be used to transform an entire DataFrame. For example, the very useful [replace()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.replace.html) method, which allows replacing all occurrences of a given value with another value. For example, suppose the value 0 in the `var1` column actually indicates a measurement error. It would be preferable to replace it with a missing value. - -```{python} -df.replace(0, None) -``` - -::: {.callout-warning title="Assignment or in-place methods?"} -In the previous example, applying the [replace()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.replace.html) method does not directly modify the DataFrame. To make the modification persistent, one possibility is to assign the result to an object: - -```{python} -df = df.replace(0, None) -``` - -A second possibility is, when methods offer it, to use the `inplace` argument. When `inplace=True`, the operation is performed "in place", and the DataFrame is therefore directly modified. - -```{python} -df.replace(0, None, inplace=True) -``` - -In practice, it is better to limit `inplace` operations. They do not favor the reproducibility of analyses, as the re-execution of the same cell will give different results each time. -::: - -#### Transforming columns - -In some cases, we will not want to apply transformations to the entire data but to specific variables. Transformations possible at the DataFrame level (vectorized functions, methods like [replace()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.replace.html), etc.) naturally remain possible at the column level. - -```{python} -df = pd.DataFrame( - data = { - "var1": [1.3, 5.6, None, None, 0, None], - "var2": np.random.randint(-10, 10, 6), - } -) - -np.abs(df["var2"]) -``` - -```{python} -df["var1"].replace(0, None) -``` - -But there are other transformations that are generally applied at the level of one or a few columns. For example, when the schema has not been properly recognized upon import, it may happen that numeric variables are defined as strings (type `object` in Pandas). - -```{python} -df = pd.DataFrame( - data = { - "var1": [1.3, 5.6, None], - "var2": ["1", "5", "18"], - } -) - -df.info() -``` - -In this case, we can use the `astype` method to convert the column to the desired type. - -```{python} -df['var2'] = df['var2'].astype(int) - -df.info() -``` - -Another frequent operation is renaming one or more columns. To do this, we can use the [rename()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.rename.html) method, passing a dictionary containing as many key-value pairs as variables to be renamed, where each key-value pair is of the form `'old_name': 'new_name'`. - -```{python} -df.rename(columns={'var2': 'age'}) -``` - -Finally, we might want to remove columns from the DataFrame that are not or no longer useful for analysis. For this, we use the [drop()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.drop.html) method, to which we pass either a string (name of a column if we want to remove only one) or a list of column names to remove. - -```{python} -df.drop(columns=['var1']) -``` - -#### Transforming rows - -In statistics, we generally apply transformations involving one or more columns. However, in some cases, it is necessary to apply transformations at the row level. For this, we can use the [apply()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.apply.html) method of Pandas, applied to the row axis (`axis=1`). Let's illustrate its operation with a simple case. First, we generate data. - -```{python} -df = pd.DataFrame( - data = { - "var1": [1, 5, 9, 13], - "var2": [3, 7, 11, 15], - "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04"], - } -) - -df.head() -``` - -We now apply the `apply()` function to the DataFrame to calculate a new variable that is the sum of the two existing ones. - -```{python} -df['sum_row'] = df.apply(lambda row: row['var1'] + row['var2'], axis=1) - -df.head() -``` - -::: {.callout-tip title="Lambda functions"} -A `lambda` function is a small anonymous function. It can take any number of arguments but can have only one expression. In the example above, the `lambda` function takes a row as an argument and returns the sum of the `var1` and `var2` columns for that row. - -Lambda functions allow defining simple functions "on the fly" without having to give them a name. In our example, this would have been perfectly equivalent to the following code: - -```{python} -def sum_row(row): - return row['var1'] + row['var2'] - -df['sum_row'] = df.apply(sum_row, axis=1) -``` - -::: - -Although `apply()` offers great flexibility, it is not the most efficient method, especially for large datasets. Vectorized operations are always preferable as they process data in blocks rather than row by row. In our case, it would have been preferable to create our variable using column operations. - -```{python} -df['sum_row_vect'] = df['var1'] + df['var2'] - -df.head() -``` - -However, we might find ourselves in certain (rare) cases where an operation cannot be easily vectorized or where the logic is complex. Suppose, for example, we want to combine the values of several columns based on certain conditions. - -```{python} -def combine_columns(row): - if row['var1'] > 6: - return str(row['var2']) - else: - return str(row['var2']) + "_" + row['date'] - -df['combined_column'] = df.apply(combine_columns, axis=1) - -df -``` - -### Sorting values - -Sorting data is particularly useful for exploring and visualizing data. With Pandas, we use the [sort_values()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.sort_values.html) method to sort the values of a DataFrame based on one or more columns. - -```{python} -df = pd.DataFrame( - data = { - "var1": [1, 5, 9, 13], - "var2": [3, 7, 11, 15], - "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04"], - } -) - -df -``` - -To sort the values based on a single column, just pass the column name as a parameter. - -```{python} -df.sort_values(by='var1') -``` - -By default, the sorting is done in ascending - - order. To sort the values in descending order, just set `ascending=False`. - -```{python} -df.sort_values(by='var1', ascending=False) -``` - -If we want to sort the DataFrame on multiple columns, we can provide a list of column names. We can also choose to sort in ascending order for some columns and descending order for others. - -### Aggregating data - -Aggregating data is a process where the data is broken down into groups based on certain criteria and then aggregated using an aggregation function applied independently to each group. This operation is common in exploratory analysis or when preprocessing data for visualization or statistical modeling. - -```{python} -df = pd.DataFrame( - data = { - "var1": [1.3, 5.6, None, None, 0, None], - "var2": np.random.randint(-10, 10, 6), - "experiment": ["test", "train", "test", "train", "train", "validation"], - "date": ["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-01-05", "2022-01-06"], - "sample": "sample1" - } -) - -df.head() -``` - -#### The `groupBy` operation - -The `groupBy` method in Pandas allows dividing the DataFrame into subsets based on the values of one or more columns, and then applying an aggregation function to each subset. It returns a `DataFrameGroupBy` object that is not very useful by itself but is an essential intermediate step to then apply one or more aggregation function(s) to the different groups. - -```{python} -df.groupby('experiment') -``` - -#### Aggregation functions - -Once the data is grouped, we can apply aggregation functions to obtain a statistical summary. Pandas includes a number of these functions, the complete list of which is detailed in the [documentation](https://pandas.pydata.org/docs/user_guide/groupby.html#built-in-aggregation-methods). Here are some examples of using these methods. - -For example, count the number of occurrences in each group. - -```{python} -df.groupby('experiment').size() -``` - -Calculate the sum of a variable by group. - -```{python} -df.groupby('experiment')['var1'].sum() -``` - -Or count the number of unique values of a variable by group. The possibilities are numerous. - -```{python} -# For the number of unique values of 'var2' in each group -df.groupby('experiment')['var2'].nunique() -``` - -When we want to apply multiple aggregation functions at once or custom functions, we use the `agg` method. This method accepts a list of functions or a dictionary that associates column names with functions to apply. This allows for finer application of aggregation functions. - -```{python} -df.groupby('experiment').agg({'var1': 'mean', 'var2': 'count'}) -``` - -::: {.callout-note title="Method chaining"} -The previous examples illustrate an important concept in Pandas: method chaining. This term refers to the possibility of chaining transformations applied to a DataFrame by applying methods to it in a chain. At each applied method, an intermediate DataFrame is created (but not assigned to a variable), which becomes the input of the next method. - -Method chaining allows combining several operations into a single code expression. This can improve efficiency by avoiding intermediate assignments and making the code more fluid and readable. It also favors a functional programming style where data flows smoothly through a chain of transformations. -::: - -#### Effects on the index - -It is interesting to note the effects of the aggregation process on the DataFrame's index. The last example above illustrates this well: the groups, i.e., the modalities of the variable used for aggregation, become the values of the index. - -We might want to reuse this information in subsequent analyses and therefore want it as a column. For this, just reset the index with the `reset_index()` method. - -```{python} -df_agg = df.groupby('experiment').agg({'var1': 'mean', 'var2': 'count'}) -df_agg.reset_index() -``` - -### Handling missing values - -Missing values are a common reality in real-world data processing and can occur for various reasons, such as non-responses to a questionnaire, data entry errors, data loss during transmission, or simply because the information is not applicable. Pandas offers several tools to handle missing values. - -#### Representation of missing values - -In Pandas, missing values are generally represented by `np.nan`, a special marker provided by the `NumPy` library. While it is preferable to use this object to denote missing values, note that the `None` object in `Python` is also understood as a missing value by `Pandas`. - -Let's verify this property. To identify where the missing values are, we use the `isna()` function, which returns a boolean DataFrame indicating `True` where the values are `NaN`. - -```{python} -df = pd.DataFrame( - data = { - "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], - "var2": np.random.randint(-10, 10, 6), - "experiment": ["test", "train", "test", None, "train", "validation"], - "sample": "sample1" - } -) - -df.isna() -``` - -#### Calculations on columns containing missing values - -During statistical calculations, missing values are generally ignored. For example, the `.mean()` method calculates the mean of non-missing values. - -```{python} -df['var1'].mean() -``` - -However, calculations involving multiple columns do not always ignore missing values and can often result in `NaN`. - -```{python} -df['var3'] = df['var1'] + df['var2'] - -df -``` - -#### Removing missing values - -The `dropna()` method allows us to remove rows (`axis=0`) or columns (`axis=1`) containing missing values. By default, any row containing at least one missing value is removed. - -```{python} -df.dropna() -``` - -By changing the `axis` parameter, we can request that any column containing at least one missing value be removed. - -```{python} -df.dropna(axis=1) -``` - -Finally, the `how` parameter defines the deletion mode. By default, a row or column is removed when at least one value is missing (`how=any`), but it is possible to remove the row/column only when all values are missing (`how=all`). - -#### Replacing missing values - -To handle missing values in a DataFrame, a common approach is imputation, which involves replacing the missing values with other values. The `fillna()` method allows us to perform this operation in various ways. One possibility is replacement by a constant value. - -```{python} -df['var1'].fillna(value=0) -``` - -::: {.callout-warning title="Changing the representation of missing values"} -It can sometimes be tempting to change the manifestation of a missing value for visibility reasons, for example by replacing it with a string: - -```{python} -df['var1'].fillna(value="MISSING") -``` - -In practice, this is not recommended. It is indeed preferable to stick to Pandas' standard convention (using `np.nan`), firstly for standardization purposes that facilitate reading and maintaining the code, but also because the standard convention is optimized for performance and calculations from data containing missing values. -::: - -Another frequent imputation method is to use a statistical value, such as the mean or median of the variable. - -```{python} -df['var1'].fillna(value=df['var1'].mean()) -``` - -::: {.callout-warning title="Imputation bias"} -Replacing missing values with a constant value, such as zero, the mean, or the median, can be problematic. If the data is not missing at random (MNAR), this can introduce bias into the analysis. MNAR variables are variables whose probability of being missing is related to their own value or other variables in the data. In such cases, more sophisticated imputation may be necessary to minimize distortions. We will see an example in the end-of-tutorial exercise. -::: - -### Handling data of specific types - -#### Text data - -Text data often requires cleaning and preparation before analysis. Pandas provides an array of vectorized operations via the `str` library that make preparing text data both simple and very efficient. Again, the possibilities are numerous and detailed in the [documentation](https://pandas.pydata.org/docs/user_guide/text.html). Here we present the most frequently used methods in data analysis. - -```{python} -df = pd.DataFrame( - data = { - "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], - "var2": np.random.randint(-10, 10, 6), - "experiment": ["test", "train", "test", "test", "train", "validation"], - "sample": [" sample1", "sample1", "sample2", " sample2 ", "sample2 ", "sample1"] - } -) - -df -``` - -A first frequent operation is to extract certain characters from a string. We use the `str[n:]` function (with a somewhat peculiar syntax) for this. For example, if we want to extract the last character of the `sample` variable to retain only the sample number. - -```{python} -df["sample_n"] = df["sample"].str[-1:] - -df -``` - -The principle was correct, but the presence of extraneous spaces in our text data (which were not visible when viewing the DataFrame!) made the operation more difficult than expected. This is an opportunity to introduce the `strip` family of methods (`.str.strip()`, `.str.lstrip()`, and `.str.rstrip()`) that respectively remove extr - -aneous spaces from both sides or one side. - -```{python} -df["sample"] = df["sample"].str.strip() -df["sample_n"] = df["sample"].str[-1:] - -df -``` - -We might also want to filter a DataFrame based on the presence or absence of a certain string (or substring) of characters. For this, we use the `.str.contains()` method. - -```{python} -df[df['experiment'].str.contains('test')] -``` - -Finally, we might want to replace a string (or substring) of characters with another, which the `str.replace()` method allows. - -```{python} -df['experiment'] = df['experiment'].str.replace('validation', 'val') - -df -``` - -#### Categorical data - -Categorical data is variables that contain a limited number of categories. Similar to `R` with the notion of `factor`, Pandas has a special data type, `category`, which is useful for representing categorical data more efficiently and informatively. Categorical data is indeed optimized for certain types of data and can speed up operations like grouping and sorting. It is also useful for visualization, ensuring that categories are displayed in a coherent and logical order. - -To convert a variable to the `category` format, we use the `astype()` method. - -```{python} -df = pd.DataFrame( - data = { - "var1": [1.3, 5.6, np.nan, np.nan, 0, np.nan], - "var2": np.random.randint(-10, 10, 6), - "experiment": ["test", "train", "test", None, "train", "validation"], - } -) -print(df.dtypes) -``` - -```{python} -df['experiment'] = df['experiment'].astype('category') - -print(df.dtypes) -``` - -This conversion gives us access to some very useful methods, specific to handling categorical variables. For example, it can be useful to rename categories for clarity or standardization. - -```{python} -df['experiment'] = df['experiment'].cat.rename_categories({'test': 'Test', 'train': 'Train', 'validation': 'Validation'}) -df -``` - -Sometimes, the order of categories is significant, and we might want to modify it. This is particularly important for visualization, as the categories will by default be displayed in the specified order. - -```{python} -df_cat = df['experiment'].cat.reorder_categories(['Test', 'Train', 'Validation'], ordered=True) -df.groupby("experiment").mean().plot(kind='bar') -``` - -#### Temporal data - -Temporal data is often present in tabular data to temporally identify the observations collected. Pandas offers functionalities for handling these types of data, particularly through the `datetime64` type, which allows precise manipulation of dates and times. - -```{python} -df = pd.DataFrame( - data = { - "var1": [1, 5, 9, 13], - "var2": [3, 7, 11, 15], - "date": ["2022-01-01", "2022-01-02", "2023-01-01", "2023-01-02"], - "sample": ["sample1", "sample1", "sample2", "sample2"] - } -) - -df.dtypes -``` - -To handle temporal data, it is necessary to convert the strings into `datetime` objects. Pandas does this via the `to_datetime()` function. - -```{python} -df['date'] = pd.to_datetime(df['date']) - -df.dtypes -``` - -Once converted, dates can be formatted, compared, and used in calculations. In particular, Pandas now understands the "order" of the dates present in the data, allowing for filtering over given periods. - -```{python} -df[(df['date'] >= "2022-01-01") & (df['date'] < "2022-01-03")] -``` - -We might also want to perform less precise filtering, involving the year or month. Pandas allows us to easily extract specific components of the date, such as the year, month, day, hour, etc. - -```{python} -df['year'] = df['date'].dt.year -df['month'] = df['date'].dt.month -df['day'] = df['date'].dt.day - -df[df['year'] == 2023] -``` - -Finally, calculations involving dates become possible. We can add or subtract time periods from dates and compare them with each other. The functions used come from `Pandas` but are very similar in operation to those of the [time](https://docs.python.org/fr/3/library/time.html) module in Python. - -For example, we can add time intervals or calculate differences from a reference date. - -```{python} -df['date_plus_one'] = df['date'] + pd.Timedelta(days=1) -df['date_diff'] = df['date'] - pd.to_datetime('2022-01-01') - -df -``` - -### Joining tables - -In data analysis, it is common to want to combine different data sources. This combination can be done vertically (one DataFrame on top of another), for example, when combining two years of the same survey for joint analysis. The combination can also be done horizontally (side by side) based on one or more join keys, often to enrich one data source with information from another source covering the same statistical units. - -#### Concatenating tables - -The vertical concatenation of tables is done using the `concat()` function in Pandas. - -```{python} -df1 = pd.DataFrame( - data = { - "var1": [1, 5], - "var2": [3, 7], - "date": ["2022-01-01", "2022-01-02"], - "sample": ["sample1", "sample1"] - } -) - -df2 = pd.DataFrame( - data = { - "var1": [9, 13], - "date": ["2023-01-01", "2023-01-02"], - "var2": [11, 15], - "sample": ["sample2", "sample2"] - } -) - -df_concat = pd.concat([df1, df2]) - -df_concat -``` - -Note that the order of variables in the two DataFrames is not important. Pandas does not "dumbly" juxtapose the two DataFrames; it matches the schemas to align the variables by name. If two variables have the same name but not the same type - for example, if a numeric variable has been interpreted as strings - Pandas will resolve the issue by taking the common denominator, usually converting to strings (type `object`). - -However, the previous concatenation reveals an issue of repetition at the index level. This is logical: we did not specify an index for our initial two DataFrames, which therefore have the same position index ([0, 1]). In this case (where the index is not important), we can pass the `ignore_index=True` parameter to rebuild the final index from scratch. - -```{python} -df_concat = pd.concat([df1, df2], ignore_index=True) - -df_concat -``` - -::: {.callout-warning title="Iterative construction of a DataFrame"} -One might have the idea of using `pd.concat()` to iteratively construct a DataFrame by adding a new row to the existing DataFrame in each iteration of a loop. However, this is not a good idea: as we have seen, a DataFrame is represented in memory as a juxtaposition of Series. Thus, adding a column to a DataFrame is not costly, but adding a row involves modifying each element constituting the DataFrame. To construct a DataFrame, it is therefore advisable to store the rows in a list of lists (one per column) or a dictionary, then call `pd.DataFrame()` to build the DataFrame, as we did at the beginning of this tutorial. -::: - -#### Merging tables - -Merging tables is an operation that allows us to associate rows from two different DataFrames based on one or more common keys, similar to joins in SQL databases. Different types of joins are possible depending on the data we want to keep, the main ones being represented in the following diagram. - -![](img/joins.png) - -Source: [link](https://medium.com/swlh/merging-dataframes-with-pandas-pd-merge-7764c7e2d46d) - -In Pandas, joins are done with the [merge()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.merge.html) function. To perform a join, we must specify (at a minimum) two pieces of information: - -- the type of join: by default, Pandas performs an `inner` join. The `how` parameter allows specifying other types of joins; - -- the join key. By default, Pandas tries to join the two DataFrames based on their indexes. In practice, we often specify a variable present in the DataFrames as the join key (the `on` parameter if the variable has the same name in both DataFrames, or `left_on` and `right_on` otherwise). - -Let's analyze the difference between the different types of joins through examples. - -```{python} -df_a = pd.DataFrame({ - 'key': ['K0', 'K1', 'K2', 'K3', 'K4'], - 'A': ['A0', 'A1', 'A2', 'A3', 'A4'], - 'B': ['B0', 'B1', 'B2', 'B3', 'A4'] -}) - -df_b = pd.DataFrame({ - 'key': ['K0', 'K1', 'K2', 'K5', 'K6'], - 'C': ['C0', 'C1', 'C2', 'C5', 'C6'], - 'D': ['D0', 'D1', 'D2', 'D5', 'D6'] -}) - -display(df_a) -display(df_b) -``` - -The `inner` join keeps the observations whose key is present in both DataFrames. - -```{python} -df_merged_inner = pd.merge(df_a, df_b, on='key') -df_merged_inner -``` - -::: {.callout-warning title="Inner joins"} -The `inner` join is the most intuitive: it generally does not create missing values and therefore allows working directly on the merged table. But beware: if many keys are not present in both DataFrames, an `inner` join can result in significant data loss, leading to biased final results. In this case, it is better to choose a left or right join, depending on the source we want to enrich and for which it is most important to minimize data loss. -::: - -A `left` join keeps all observations in the left DataFrame (the first DataFrame specified in `pd.merge()`). As a result, if keys are present in the left DataFrame but not in the right one, the final DataFrame contains missing values at those observations (for the right DataFrame's variables). - -```{python} -df_merged_left = pd.merge(df_a, df_b, how="left", on='key') -df_merged_left -``` - -The `outer` join contains all observations and variables in both DataFrames. Thus, the retained information is maximal, but on the other hand, missing values can be quite numerous. It will therefore be necessary to handle missing values well before proceeding with analyses. - -```{python} -df_merged_outer = pd.merge(df_a, df_b, how="outer", on='key') -df_merged_outer -``` - -## Exercises - -### Comprehension questions - -1. What is a DataFrame in the context of Pandas, and what type of data structure can it be compared to in Python? -2. What is the fundamental difference between a NumPy array and a Pandas Series? -3. What is the relationship between Series and DataFrame in Pandas? -4. How are data structured in a Pandas DataFrame? -5. What is the role of the index in a Pandas DataFrame, and how can it be used when manipulating data? -6. What methods can you use to explore an unknown DataFrame and learn more about its content and structure? -7. In Pandas, what is the difference between assigning the result of an operation to a new variable and using a method with the `inplace=True` argument? -8. How does the principle of vectorization apply in Pandas, and why is it advantageous for manipulating data? -9. How does Pandas represent missing values, and what impact does this have on calculations and data transformations? -10. What is the difference between concatenating two DataFrames and joining them via a merge, and when would you use one over the other? - -::: {.cell .markdown} - -