Maj controler_projection() + debut script Main

Prends en compte l'intersection des valeurs dans
les projections CC47 et Lambert93
This commit is contained in:
David Castex 2025-05-23 16:42:06 +02:00
parent 8f1a42785c
commit ef876b7a69
5 changed files with 124 additions and 63 deletions

115
banbou.py
View File

@ -1,7 +1,7 @@
## Script Banbou pour le prétraitement des données des dossiers de recollement ## Script Banbou pour le prétraitement des données des dossiers de recollement
## de fibre optique. ## de fibre optique.
import os, shutil import os, shutil, datetime
@ -66,7 +66,7 @@ def creer_liste(dossier):
for dossier_courant, list_sousdossiers, list_fichiers in os.walk(dossier): for dossier_courant, list_sousdossiers, list_fichiers in os.walk(dossier):
for fichier_courant in list_fichiers: for fichier_courant in list_fichiers:
print(f"fichier courant : {fichier_courant}") print(f"\nfichier courant : {fichier_courant}")
ce_Fichier = _Fichier.lire(dossier_courant, fichier_courant) ce_Fichier = _Fichier.lire(dossier_courant, fichier_courant)
liste.append(ce_Fichier) liste.append(ce_Fichier)
@ -79,7 +79,7 @@ def afficher(liste):
Affiche le nom des fichiers de la liste des _Fichiers Affiche le nom des fichiers de la liste des _Fichiers
""" """
for courant in liste: for courant in liste:
print(courant.nom + "." + courant.extension) print("\n" + courant.nom + "." + courant.extension)
@ -87,7 +87,7 @@ def afficher(liste):
def controller_projection(id_point, point_x, point_y): def controller_projection(id_point, point_x, point_y):
""" """
regarde si les coordonnées du point sont bien dans une des projections regarde si les coordonnées d'un point sont bien dans une des projections
autorisées autorisées
Contrainte : Contrainte :
@ -195,6 +195,18 @@ def controller_projection(id_point, point_x, point_y):
# projection à retourner # projection à retourner
projection = "Mauvaise projection" projection = "Mauvaise projection"
# NOTE : Une partie des ensembles de coordonnées de CC47 et de Lambert93 s'intersectionne :
# Lorsqu'un point de coordonnées (X, Y) se situe dans la plage 1100000, 1300000 pour X et
# la plage 3089000, 3311000 pour Y, alors ce point est à la fois valide en CC47 et en Lambert93
# Avant de déterminer la projection, je vais donc vérifier si le point à controler n'est pas dans cette plage
# Et notifier si necessaire
# TODO : exporter la notif
if 6089000 < point_y < 6311000:
if 1100000 < point_x < 1300000:
print("\nAvertissement : ces coordonnées peuvent être interpréter correctement comme du CC47 et du Lambert93")
print("Normalement vous devrez projeter la Table de Point en CC47")
# définie la projection conique Nord en regardant dans quelle intervalle la valeur se situe # définie la projection conique Nord en regardant dans quelle intervalle la valeur se situe
for elem in projections_conformes: for elem in projections_conformes:
borne_basse = elem["N0"] - elem["fenetreN0"] borne_basse = elem["N0"] - elem["fenetreN0"]
@ -202,25 +214,27 @@ def controller_projection(id_point, point_x, point_y):
if borne_basse < point_y < borne_haute : if borne_basse < point_y < borne_haute :
projection = elem["nom"] projection = elem["nom"]
print(f"Proj. trouvé : {projection}") print(f"\nProj. trouvé : {projection}")
# Controle la longitude # Controle la longitude
# Si c'est Lambert93 alors # TODO: refaire cette partie avec des variables et non des entiers literraux
# TODO: refaire cette partie avec des variables et non des entiers literraux
longitude_correcte = False longitude_correcte = False
match projection: match projection:
case "Lambert93": case "Lambert93":
if 100000 < point_x < 1300000 : if 100000 < point_x < 1300000 :
longitude_correcte = True longitude_correcte = True
case "CC42" | "CC43" | "CC44" | "CC45" | "CC46" | "CC47" | "CC48" | "CC49" | "CC50": case "CC42" | "CC43" | "CC44" | "CC45" | "CC46" | "CC47" | "CC48" | "CC49" | "CC50":
if 900000 < point_x < 2300000 : if 1100000 < point_x < 2300000 :
longitude_correcte = True
case "GPS":
if -180 < point_x < 180:
longitude_correcte = True longitude_correcte = True
case _: case _:
pass pass
if not longitude_correcte : if not longitude_correcte :
projection = "Mauvaise projection" projection = "Mauvaise projection"
print(f"Avertissement : Longitude du point id {id_point} pas en métropole.") print(f"\nAvertissement : Longitude du point id {id_point} pas en métropole.")
return projection return projection
@ -230,13 +244,6 @@ def controller_projection(id_point, point_x, point_y):
# REPRÉSENTATION DES DONNÉES # REPRÉSENTATION DES DONNÉES
class _Fichier: class _Fichier:
@ -261,6 +268,7 @@ class _Fichier:
""" """
Affiche dans la sortie standard les éléments du fichier Affiche dans la sortie standard les éléments du fichier
""" """
print("")
print("nom :".ljust(16) + self.nom) print("nom :".ljust(16) + self.nom)
print("nom orig :".ljust(16) + self.nom_original) print("nom orig :".ljust(16) + self.nom_original)
print("ext :".ljust(16) + self.extension) print("ext :".ljust(16) + self.extension)
@ -319,7 +327,7 @@ class _Projet:
nom="Pas de nom", nom="Pas de nom",
date="Pas de date", date="Pas de date",
racine="Pas de chemin", racine="Pas de chemin",
liste=[], fichiers=[],
nb_fichiers=0, nb_fichiers=0,
taille=0, taille=0,
rapport="Pas de fichier", rapport="Pas de fichier",
@ -328,11 +336,11 @@ class _Projet:
nb_csv=0, nb_csv=0,
nb_dwgs=0, nb_dwgs=0,
nb_points = 0, nb_points = 0,
liste_notifs=[]): notifs=[]):
self.nom = nom # nom du projet self.nom = nom # nom du projet
self.date = date # date du traitement self.date = date # date du traitement
self.racine = racine # chemin racine du projet self.racine = racine # chemin racine du projet
self.liste = liste # liste de _Fichier self.fichiers = fichiers # liste de _Fichier
self.nb_fichiers = nb_fichiers # nb de fichiers dans "Travail" self.nb_fichiers = nb_fichiers # nb de fichiers dans "Travail"
self.taille = taille # taille des fichiers dans "Travail" self.taille = taille # taille des fichiers dans "Travail"
self.rapport = rapport # chemin vers le visa self.rapport = rapport # chemin vers le visa
@ -340,8 +348,9 @@ class _Projet:
self.nb_releves = nb_releves # nb de rapports de relevés topo self.nb_releves = nb_releves # nb de rapports de relevés topo
self.nb_csv = nb_csv # nb de fichiers CSV self.nb_csv = nb_csv # nb de fichiers CSV
self.nb_dwgs = nb_dwgs # nb de fichiers DWG self.nb_dwgs = nb_dwgs # nb de fichiers DWG
self.nb_pdfs = nb_pdfs # nb de fichiers PDF
self.nb_points = nb_points # nb de points des CSVs self.nb_points = nb_points # nb de points des CSVs
self.liste_notifs = liste_notifs # liste contenant les notifs du VISA self.notifs = notifs # liste contenant les notifs du VISA
def enraciner(self): def enraciner(self):
@ -350,7 +359,7 @@ class _Projet:
met à jour l'attribut 'racine' met à jour l'attribut 'racine'
""" """
self.racine = os.getcwd() self.racine = os.getcwd()
print("Racine : ".ljust(16), f"{self.racine}\n") print("\nRacine : ".ljust(16), f"{self.racine}\n")
def calculer_taille(self): def calculer_taille(self):
@ -360,7 +369,7 @@ class _Projet:
Met à jour l'attribut 'taille' dans le projet Met à jour l'attribut 'taille' dans le projet
""" """
taille = 0.0 taille = 0.0
for courant in self.liste: for courant in self.fichiers:
if courant.implication in "Necessaire": if courant.implication in "Necessaire":
taille += courant.taille taille += courant.taille
self.taille = taille self.taille = taille
@ -373,9 +382,9 @@ class _Projet:
else : else :
unite = "Mo" unite = "Mo"
taille /= 1024**2 taille /= 1024**2
print(f"Taille totale : {taille:.2f} {unite}.\n") print(f"\nTaille totale : {taille:.2f} {unite}.\n")
def dater_projet(self): def dater(self):
""" """
recupère la date du jour recupère la date du jour
met à jour l'attribut 'date' du projet met à jour l'attribut 'date' du projet
@ -383,7 +392,7 @@ class _Projet:
self.date = datetime.datetime.today().strftime('%Y%m%d') self.date = datetime.datetime.today().strftime('%Y%m%d')
def nommer_projet(self): def nommer(self):
""" """
met à jour l'attribut 'nom' en composant un nom. met à jour l'attribut 'nom' en composant un nom.
Le nom est constitué du nom du dossier racine et de la date Le nom est constitué du nom du dossier racine et de la date
@ -397,28 +406,30 @@ class _Projet:
""" """
Créer un dossier "Travail" dans la racine du working directory et Créer un dossier "Travail" dans la racine du working directory et
le peuple des fichiers nécessaires le peuple des fichiers nécessaires
Met à jour le nombre de fichiers CSVs, DWGs et
""" """
travail = "Travail" travail = "Travail"
# création du dossier "Travail et dossier" # création du dossier "Travail et dossier"
chemin = f"{self.racine}\\{travail}" chemin = f"{self.racine}\\{travail}"
print(f"CHEMIN FABRIQUE : {chemin}") print(f"\nCHEMIN FABRIQUE : {chemin}")
try: try:
os.mkdir(chemin) os.mkdir(chemin)
print (f'Dossier "{travail}" créé.') print (f'\nDossier "{travail}" créé.')
except FileExistsError as erreur: except FileExistsError as erreur:
print(f'Avertissement: Le dossier "{travail}" existe déja.') print(f'\nAvertissement: Le dossier "{travail}" existe déja.')
except OSError as err: except OSError as err:
print(f"Fichier non trouvé. Surement un pb de chemin en amont.") print(f"\nFichier non trouvé. Surement un pb de chemin en amont.")
# peuplement du dossier Travail avec les fichiers necessaires # peuplement du dossier Travail avec les fichiers necessaires
for fichier in self.liste: for fichier in self.fichiers:
source = fichier.chemin source = fichier.chemin
print(f"source : {source}") print(f"\nsource : {source}")
# lors du peuplement préfixer et suffixer les noms des fichiers concernés comme suit : "Plan_nomfichierdwg.dwg" et "Point_nomfichiercsv_IN.csv" # lors du peuplement préfixer et suffixer les noms des fichiers concernés comme suit : "Plan_nomfichierdwg.dwg" et "Point_nomfichiercsv_IN.csv"
# Confirmation par Audrey qu'il n'y a nécessairement qu'un fichier CSV par projet --> Le script s'occupe de le renommer. # Confirmation par Audrey qu'il n'y a nécessairement qu'un fichier CSV par projet --> Le script s'occupe de le renommer.
# Mais parfois il peut y avoir plusieurs DWGs dont un seul est utile --> PASS -- Je laisse l'opérateur choisir lequel utiliser et le renommer manuellement. # Mais parfois il peut y avoir plusieurs DWGs dont un seul est utile --> PASS -- Je laisse l'opérateur choisir lequel utiliser et le renommer manuellement.
match fichier.extention: match fichier.extension:
case "csv": case "csv":
dest = self.racine + "\\" + travail + "\\" + "Point_" + fichier.nom + "_IN" + "." + fichier.extension dest = self.racine + "\\" + travail + "\\" + "Point_" + fichier.nom + "_IN" + "." + fichier.extension
@ -429,13 +440,12 @@ class _Projet:
if fichier.implication in "Necessaire": if fichier.implication in "Necessaire":
try: try:
shutil.copyfile( source , dest) shutil.copyfile( source , dest)
print(fichier.nom.ljust(40,".") + "copié") print("\n" + fichier.nom.ljust(40,".") + "copié")
except shutil.SameFileError as err : except shutil.SameFileError as err :
print(f"Le fichier {fichier.nom + fichier.extension} existe déjà.") print(f"\nLe fichier {fichier.nom + fichier.extension} existe déjà.")
#TODO : #TODO :
# Confirmation par Audrey qu'il n'y a necessairement qu'un fichier CSV par projet --> On peut le renommer. # Confirmation par Audrey qu'il n'y a necessairement qu'un fichier CSV par projet --> On peut le renommer.
# Mais parfois il peut y avoir plusieurs DWGs dont un seul est utile --> PASS -- Je laisse l'opérateur choisir lequel utiliser et le renommer manuellement. # Mais parfois il peut y avoir plusieurs DWGs dont un seul est utile --> PASS -- Je laisse l'opérateur choisir lequel utiliser et le renommer manuellement.
shutil.move()
#TODO : verifier aussi la longueur des noms de fichiers. Notifier si nécessaire #TODO : verifier aussi la longueur des noms de fichiers. Notifier si nécessaire
@ -515,27 +525,44 @@ class _Notification:
# -------------------------------------------------------------------------- #
# -------------------------------------------------------------------------- #
# MAIN # MAIN
racine = os.getcwd() racine = os.getcwd()
print("Répertoire courant : ".center(18), racine) print("\nRépertoire courant : ".center(18), racine)
# --recupérer le chemin du dossier à traiter # --recupérer le chemin du dossier à traiter
pas_de_dossier = True pas_de_dossier = True
for a in os.scandir(): for a in os.scandir():
print("courant scandir() = ", a.name.ljust(25), " ", a.is_dir()) print("\ncourant scandir() = ", a.name.ljust(25), " ", a.is_dir())
if a.is_dir(): if a.is_dir():
#il y a un dossier #il y a un dossier
pas_de_dossier = False pas_de_dossier = False
print(f"Dossier à Traiter trouvé : {a.name}") print(f"\nDossier à Traiter trouvé : {a.name}")
racine = a racine = a
if pas_de_dossier: if pas_de_dossier:
print("Pas de dossier trouvé...\nFin de programme\n") print("\nPas de dossier trouvé...\nFin de programme.\n")
os.system("pause") os.system("pause")
# fin du programme exit()
exit()
# Création entité projet et maj de ses attributs
projet = _Projet()
projet.dater()
projet.nommer()
# controle de la longueur du nom du projet
if len(projet.nom) >=46 :
print(f"\n{projet.nom} est un nom de dossier trop long (+ de 46 caractères). Veuillez raccourcir son nom\nFin de programme.\n")
os.system("pause")
exit()
projet.enraciner()
projet.rapport = f"{racine}\\Visa_lot_2.xlsx"
projet.fichiers = creer_liste(projet.racine)

View File

@ -1,12 +1,26 @@
from banbou import controller_projection from banbou import controller_projection
def test_projection_correcte_metropole() : def test_projection_CC_correcte_metropole() :
sut = ("1004", 1585702, 2185080) sut = ("1004", 1585702, 2185080)
proj = controller_projection(*sut) proj = controller_projection(*sut)
assert proj == "CC43" assert proj == "CC43"
def test_projection_Lambert93_correcte_metropole() :
sut = ("1004", 752466.254, 6600112.012)
proj = controller_projection(*sut)
assert proj == "Lambert93"
def test_projection_GPS_correcte() :
sut = ("1004", 0, 0)
proj = controller_projection(*sut)
assert proj == "GPS"
def test_projection_correcte_avec_des_flottants() : def test_projection_correcte_avec_des_flottants() :
sut = ("1004", 1585702.06, 2185080.612) sut = ("1004", 1585702.06, 2185080.612)
@ -22,12 +36,25 @@ def test_lattitude_incorrecte() :
assert proj == "Mauvaise projection" assert proj == "Mauvaise projection"
def test_longitude_incorrecte(capsys) : def test_longitude_incorrecte(capsys) :
sut = ("1004", 1000000, 0) sut = ("1004", 1000000, 500000000)
proj = controller_projection(*sut) proj = controller_projection(*sut)
out, err = capsys.readouterr() out, err = capsys.readouterr()
expected_out = "Proj. trouvé : Mauvaise projection\n" + "Avertissement : Longitude du point id 1004 pas en métropole.\n" expected_out = "\nProj. trouvé : Mauvaise projection\n" + "\nAvertissement : Longitude du point id 1004 pas en métropole.\n"
assert proj == "Mauvaise projection" assert proj == "Mauvaise projection"
assert out == expected_out assert out == expected_out
def test_coordonnees_intersection_entre_CC47_et_Lambert93(capsys):
sut = ("1004", 1125804.292, 6291079.947)
proj = controller_projection(*sut)
out, err = capsys.readouterr()
expected_out = "\nAvertissement : ces coordonnées peuvent être interpréter correctement comme du CC47 et du Lambert93\n" + \
"Normalement vous devrez projeter la Table de Point en CC47\n" + \
"\nProj. trouvé : CC47\n"
assert proj == "CC47"
assert out == expected_out

View File

@ -20,7 +20,7 @@ def test_doit_afficher_un_fichier(mocker, capsys):
#capture l'affichage de stdout #capture l'affichage de stdout
out, err = capsys.readouterr() out, err = capsys.readouterr()
expected_out = __nom + "mon_fichier\n" + __nom_orig + "mon fichier\n" + __ext + "csv\n" + __chemin + "/home/david/projet01\n" + __implication + "Necessaire\n" + __taille + "300\n" expected_out = "\n" + __nom + "mon_fichier\n" + __nom_orig + "mon fichier\n" + __ext + "csv\n" + __chemin + "/home/david/projet01\n" + __implication + "Necessaire\n" + __taille + "300\n"
assert out == expected_out assert out == expected_out
@ -30,7 +30,7 @@ def test_doit_afficher_un_fichier_avec_des_champs_vides(mocker, capsys):
sut.afficher() sut.afficher()
out, err = capsys.readouterr() out, err = capsys.readouterr()
expected_out = __nom + "Pas de nom\n" + __nom_orig + "Pas de nom original\n" + __ext + "Pas d'extension\n" + __chemin + "Pas de chemin\n" + __implication + "Non-conforme\n" + __taille + "0\n" expected_out = "\n" +__nom + "Pas de nom\n" + __nom_orig + "Pas de nom original\n" + __ext + "Pas d'extension\n" + __chemin + "Pas de chemin\n" + __implication + "Non-conforme\n" + __taille + "0\n"
assert out == expected_out assert out == expected_out

View File

@ -11,9 +11,9 @@ def test_doit_calculer_la_taille_du_projet(mocker):
mocker.patch("banbou._Fichier", return_value = MockResponse()) mocker.patch("banbou._Fichier", return_value = MockResponse())
liste = [banbou._Fichier()] fichiers = [banbou._Fichier()]
sut = _Projet() sut = _Projet()
sut.liste = liste sut.fichiers = fichiers
expected_value = 40 expected_value = 40
@ -23,9 +23,9 @@ def test_doit_calculer_la_taille_du_projet(mocker):
def test_doit_calculer_une_liste_vide(mocker): def test_doit_calculer_une_liste_vide(mocker):
liste = [] fichiers = []
sut = _Projet() sut = _Projet()
sut.liste = liste sut.fichiers = fichiers
expected_value = 0 expected_value = 0
@ -42,9 +42,9 @@ def test_ne_doit_pas_calculer_fichier_non_necessaire(mocker):
mocker.patch("banbou._Fichier", return_value = MockResponse()) mocker.patch("banbou._Fichier", return_value = MockResponse())
liste = [banbou._Fichier()] fichiers = [banbou._Fichier()]
sut = _Projet() sut = _Projet()
sut.liste = liste sut.fichiers = fichiers
expected_value = 0 expected_value = 0
@ -61,11 +61,11 @@ def test_doit_afficher_un_arrondi_deux_decimale(mocker, capsys):
mocker.patch("banbou._Fichier", return_value = MockResponse()) mocker.patch("banbou._Fichier", return_value = MockResponse())
liste = [banbou._Fichier()] fichiers = [banbou._Fichier()]
sut = _Projet() sut = _Projet()
sut.liste = liste sut.fichiers = fichiers
expected_value = "Taille totale : 1.99 Mo.\n\n" expected_value = "\nTaille totale : 1.99 Mo.\n\n"
sut.calculer_taille() sut.calculer_taille()
out, err = capsys.readouterr() out, err = capsys.readouterr()

View File

@ -1,5 +1,5 @@
from banbou import _Projet from banbou import _Projet
import banbou, os import banbou, os, shutil
# Je n'ai pas mocker l'environnement donc prévoir d'effacer # Je n'ai pas mocker l'environnement donc prévoir d'effacer
# les anciens fichiers et dossier créés par les tests précédents # les anciens fichiers et dossier créés par les tests précédents
@ -13,18 +13,25 @@ def test_doit_copier_les_fichiers_necessaires(mocker):
sut = _Projet() sut = _Projet()
sut.racine = dossier sut.racine = dossier
sut.liste = banbou.creer_liste(dossier) sut.fichiers = banbou.creer_liste(dossier)
sut.preparer_dossier_travail() sut.preparer_dossier_travail()
# ici je parcours "Travail" pour voir ce qui à été créé
out = os.walk(dossier + "\\Travail") out = os.walk(dossier + "\\Travail")
liste = [i for i in out] liste = [i for i in out] # transfo de l'itérable en liste
# valeurs attendues # valeurs attendues
sous_dossier_attendue = [] # pas de sous dossier sous_dossier_attendue = [] # pas de sous dossier
fichiers_attendues = ['DIS.pdf', 'DIS_AXR08_PT802161.csv', 'DIS_AXR08_PT802161.dwg', 'DIS_AXR08_PT802161.pdf'] fichiers_attendues = ['DIS.pdf', 'DIS_AXR08_PT802161.dwg', 'DIS_AXR08_PT802161.pdf', 'Point_DIS_AXR08_PT802161_IN.csv']
# Ici j'efface le dossier de "Travail" pour pas interférer avec les autres tests,
# d'ailleurs j'ai voulu ecrire ces lignes après les asserts et ça ne s'éxecutait pas,
# j'en conclu que tout ce qui est écrit après un assert NE S'EXÉCUTE PAS
print("\n" + dossier + "\\Travail")
shutil.rmtree(dossier + "\\Travail")
assert liste[0][1] == sous_dossier_attendue assert liste[0][1] == sous_dossier_attendue
assert liste[0][2] == fichiers_attendues assert liste[0][2] == fichiers_attendues
# TODO: effacer le dossier de "Travail" pour pas interférer avec les autres tests