diff --git a/.gitignore b/.gitignore index fe392f0..59c84bf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -*.pdf __pycache__/ + +*.pdf *.sqlite3 -!doc/* diff --git a/README.md b/README.md index 0792557..d268425 100644 --- a/README.md +++ b/README.md @@ -53,9 +53,8 @@ A savoir : - [x] Lisibilité du code - [x] Toutes les fonctions sont nommés et typés (j'utilises `Python 3.9.7`) -### Crédit -Pour générer la documentation présente [ici](doc/README.md) vous aurez besoin de [pdoc](https://pdoc3.github.io/pdoc/). +### Crédit pour la documentation +Pour générer la documentation présente [ici](doc/) vous aurez besoin de [pdoc](https://pdoc3.github.io/pdoc/), ainsi pour la générer, vous devez lancez cette commande : ``` -python3 -m pdoc --pdf . 1> doc/README.md +python3 -m pdoc --html --output-dir doc . ``` -J'utilises Chromium pour convertir le fichier Markdown vers un [fichier pdf disponible ici](doc/README.pdf). diff --git a/doc/GesMag/db.html b/doc/GesMag/db.html new file mode 100644 index 0000000..be599be --- /dev/null +++ b/doc/GesMag/db.html @@ -0,0 +1,275 @@ + + + + + + +GesMag.db API documentation + + + + + + + + + + + +
+
+
+

Module GesMag.db

+
+
+
+ +Expand source code + +
import sqlite3
+from sqlite3.dbapi2 import Cursor
+
+class BaseDeDonnees:
+    """Gère la base de donnée."""
+    def __init__(self, urlBaseDeDonnee: str):
+        self.connexion = self.creerConnexion(urlBaseDeDonnee)
+
+    def creerConnexion(self, path: str):
+        """Connexion à une base de donnée SQLite."""
+        if not self.fichierExiste(path): # si l base de donnée n'existe pas
+            open(path, "x") # on la créer
+        try:
+            connnexion = sqlite3.connect(path)
+        except sqlite3.Error as e:
+            print(e) # on affiche l'erreur
+            connnexion = None # et renvoie None
+        return connnexion
+
+    def fichierExiste(self, path: str) -> bool:
+        """Vérifie qu'un fichier existe."""
+        try: # on essaie d'ouvrir le fichier
+            open(path, "r")
+        except FileNotFoundError: # si le fichier n'existe pas
+            return False
+        else: # si le fichier existe
+            return True
+
+    def requete(self, requete: str, valeurs = None):
+        """Envois une requête vers la base de données."""
+        try:
+            curseur = self.connexion.cursor()
+            if valeurs: # s'il y a des valeurs alors on lance la commande `execute` avec ses dernières
+                if type(valeurs) not in [list, tuple]: # si la valeur c'est juste une chaîne de charactère (par exemple), alors la converti en liste
+                    valeurs = [valeurs]
+                curseur.execute(requete, valeurs)
+            else: # sinon on lance juste la requête
+                curseur.execute(requete)
+            self.connexion.commit() # applique les changements à la base de donnée
+            return (curseur, curseur.lastrowid) # renvoie le curseur et l'ID de l'élément modifié
+        except sqlite3.Error as e: # s'il y a eu une erreur SQLite
+            print(e)
+
+    def affichageResultat(self, curseur: Cursor) -> list:
+        """Affiche le résultat d'une requête."""
+        tableau = []
+        if curseur == None: # si le curseur est vide il n'y a rien a affiché (tableau vide)
+            return tableau
+        lignes = curseur[0].fetchall() # sinon on récupère les éléments
+        for ligne in lignes:
+            tableau.append(ligne) # on les ajoute au tableau
+        return tableau # on le renvoie
+
+
+
+
+
+
+
+
+
+

Classes

+
+
+class BaseDeDonnees +(urlBaseDeDonnee: str) +
+
+

Gère la base de donnée.

+
+ +Expand source code + +
class BaseDeDonnees:
+    """Gère la base de donnée."""
+    def __init__(self, urlBaseDeDonnee: str):
+        self.connexion = self.creerConnexion(urlBaseDeDonnee)
+
+    def creerConnexion(self, path: str):
+        """Connexion à une base de donnée SQLite."""
+        if not self.fichierExiste(path): # si l base de donnée n'existe pas
+            open(path, "x") # on la créer
+        try:
+            connnexion = sqlite3.connect(path)
+        except sqlite3.Error as e:
+            print(e) # on affiche l'erreur
+            connnexion = None # et renvoie None
+        return connnexion
+
+    def fichierExiste(self, path: str) -> bool:
+        """Vérifie qu'un fichier existe."""
+        try: # on essaie d'ouvrir le fichier
+            open(path, "r")
+        except FileNotFoundError: # si le fichier n'existe pas
+            return False
+        else: # si le fichier existe
+            return True
+
+    def requete(self, requete: str, valeurs = None):
+        """Envois une requête vers la base de données."""
+        try:
+            curseur = self.connexion.cursor()
+            if valeurs: # s'il y a des valeurs alors on lance la commande `execute` avec ses dernières
+                if type(valeurs) not in [list, tuple]: # si la valeur c'est juste une chaîne de charactère (par exemple), alors la converti en liste
+                    valeurs = [valeurs]
+                curseur.execute(requete, valeurs)
+            else: # sinon on lance juste la requête
+                curseur.execute(requete)
+            self.connexion.commit() # applique les changements à la base de donnée
+            return (curseur, curseur.lastrowid) # renvoie le curseur et l'ID de l'élément modifié
+        except sqlite3.Error as e: # s'il y a eu une erreur SQLite
+            print(e)
+
+    def affichageResultat(self, curseur: Cursor) -> list:
+        """Affiche le résultat d'une requête."""
+        tableau = []
+        if curseur == None: # si le curseur est vide il n'y a rien a affiché (tableau vide)
+            return tableau
+        lignes = curseur[0].fetchall() # sinon on récupère les éléments
+        for ligne in lignes:
+            tableau.append(ligne) # on les ajoute au tableau
+        return tableau # on le renvoie
+
+

Methods

+
+
+def affichageResultat(self, curseur: sqlite3.Cursor) ‑> list +
+
+

Affiche le résultat d'une requête.

+
+ +Expand source code + +
def affichageResultat(self, curseur: Cursor) -> list:
+    """Affiche le résultat d'une requête."""
+    tableau = []
+    if curseur == None: # si le curseur est vide il n'y a rien a affiché (tableau vide)
+        return tableau
+    lignes = curseur[0].fetchall() # sinon on récupère les éléments
+    for ligne in lignes:
+        tableau.append(ligne) # on les ajoute au tableau
+    return tableau # on le renvoie
+
+
+
+def creerConnexion(self, path: str) +
+
+

Connexion à une base de donnée SQLite.

+
+ +Expand source code + +
def creerConnexion(self, path: str):
+    """Connexion à une base de donnée SQLite."""
+    if not self.fichierExiste(path): # si l base de donnée n'existe pas
+        open(path, "x") # on la créer
+    try:
+        connnexion = sqlite3.connect(path)
+    except sqlite3.Error as e:
+        print(e) # on affiche l'erreur
+        connnexion = None # et renvoie None
+    return connnexion
+
+
+
+def fichierExiste(self, path: str) ‑> bool +
+
+

Vérifie qu'un fichier existe.

+
+ +Expand source code + +
def fichierExiste(self, path: str) -> bool:
+    """Vérifie qu'un fichier existe."""
+    try: # on essaie d'ouvrir le fichier
+        open(path, "r")
+    except FileNotFoundError: # si le fichier n'existe pas
+        return False
+    else: # si le fichier existe
+        return True
+
+
+
+def requete(self, requete: str, valeurs=None) +
+
+

Envois une requête vers la base de données.

+
+ +Expand source code + +
def requete(self, requete: str, valeurs = None):
+    """Envois une requête vers la base de données."""
+    try:
+        curseur = self.connexion.cursor()
+        if valeurs: # s'il y a des valeurs alors on lance la commande `execute` avec ses dernières
+            if type(valeurs) not in [list, tuple]: # si la valeur c'est juste une chaîne de charactère (par exemple), alors la converti en liste
+                valeurs = [valeurs]
+            curseur.execute(requete, valeurs)
+        else: # sinon on lance juste la requête
+            curseur.execute(requete)
+        self.connexion.commit() # applique les changements à la base de donnée
+        return (curseur, curseur.lastrowid) # renvoie le curseur et l'ID de l'élément modifié
+    except sqlite3.Error as e: # s'il y a eu une erreur SQLite
+        print(e)
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/doc/GesMag/index.html b/doc/GesMag/index.html new file mode 100644 index 0000000..f9207c0 --- /dev/null +++ b/doc/GesMag/index.html @@ -0,0 +1,70 @@ + + + + + + +GesMag API documentation + + + + + + + + + + + +
+
+
+

Namespace GesMag

+
+
+
+
+

Sub-modules

+
+
GesMag.db
+
+
+
+
GesMag.main
+
+
+
+
GesMag.users
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/doc/GesMag/main.html b/doc/GesMag/main.html new file mode 100644 index 0000000..c17eb3d --- /dev/null +++ b/doc/GesMag/main.html @@ -0,0 +1,430 @@ + + + + + + +GesMag.main API documentation + + + + + + + + + + + +
+
+
+

Module GesMag.main

+
+
+
+ +Expand source code + +
import tkinter.messagebox as messagebox
+
+from tkinter import *
+from re import sub
+
+from users import Utilisateurs # import de mon fichier pour gérer la base de donnée
+
+def dimensionsFenetre(fenetre, taille: tuple):
+    """Permet de définir une fenetre centrer sur l'écran"""
+    largeur = fenetre.winfo_screenwidth()
+    hauteur = fenetre.winfo_screenheight()
+
+    x = (largeur // 2) - (taille[0] // 2)
+    y = (hauteur // 2) - (taille[1] // 2)
+
+    fenetre.geometry(f"{taille[0]}x{taille[1]}+{x}+{y}")
+
+class GesMag:
+    """Programme de Gestion d'une caise de magasin."""
+    def demarrer(self) -> None:
+        """Lance le programme GesMag."""
+        print("Lancement de l'interface de gestion d'une caisse d'un magasin...")
+        self.font = ("Comfortaa", 14) # police par défaut
+        Utilisateurs().creationTable() # on créer la base de donnée si elle n'existe pas déjà
+        self.parent = Tk() # on créer notre fenêtre principale
+
+        self._interfaceConnexion() # on créer la variable `self.f` qui est la frame a affiché
+        self.f.grid() # on affiche la frame
+
+        self.parent.mainloop() # on affiche la fenêtre
+
+    def motDePasseCorrect(self, motDPasse: str) -> tuple:
+        """Détermine si un mot de passe suit la politique du programme ou non."""
+        if len(motDPasse) == 0: # si le champs est vide
+            return (False, "Mot de passe incorrect.")
+        if len(motDPasse) < 8: # si le mot de passe est plus petit que 8 caractères
+            return (False, "Un mot de passe doit faire 8 caractères minimum.")
+        """
+        Pour le regex, je réfléchie comme dans la fonction `self.connexion`.
+        J'utilises pas `match` parce que je suis plus à l'aise avec `sub`.
+        """
+        if not sub(r"[A-Z]", '', motDPasse) != motDPasse:
+            return (False, "Un mot de passe doit au moins contenir une lettre majuscule.")
+        if not sub(r"[a-z]", '', motDPasse) != motDPasse:
+            return (False, "Un mot de passe doit au moins contenir une lettre minuscule.")
+        if not sub(r" *?[^\w\s]+", '', motDPasse) != motDPasse:
+            return (False, "Un mot de passe doit au moins contenir un caractère spécial.")
+
+        return (True,) # si aucun des tests précédents n'est valide, alors le mot de passe est valide
+
+    def connexion(self, utilisateur: str, motDePasse: str):
+        """Gère la connexion aux différentes interfaces de l'application."""
+        """
+        Vérification nom d'utilisateur / mot de passe correctement entré
+        -> Pour le nom d'utilisateur on vérifie si le champs n'est pas vide
+           et si il y a bien que des lettres et des chiffres (le regex élimine tout
+           ce qui n'est pas ça, alors si la fonction `sub` renvoie pas exactement
+           la même chaîne de charactère alors c'est qu'il y avait un charactère
+           interdit dans le nom d'utilisateur).
+        -> Pour le mot de passe on demande à la fonction `motDePasseCorrect` pour
+           éviter de faire tout les tests ici.
+        """
+        if len(utilisateur) == 0 or sub(r" *?[^\w\s]+", '', utilisateur) != utilisateur:
+            messagebox.showerror("Erreur", "Utilisateur incorrect.")
+            return
+        mdpOk = self.motDePasseCorrect(motDePasse)
+        if not mdpOk[0]:
+            messagebox.showerror("Erreur", mdpOk[1])
+            return
+
+        # Redirection vers la bonne interface
+        if Utilisateurs().verificationIdentifiants(utilisateur, motDePasse):
+            print("Bienvenue mon pote")
+        else:
+            print(f"Bah nan frérot c'est pas bon, ça c'est la liste des utilisateurs : {Utilisateurs().listUtilisateurs()}")
+
+    def _interfaceConnexion(self):
+        """Affiche la fenêtre de connexion."""
+        # Paramètres de la fenêtre
+        dimensionsFenetre(self.parent, (400, 600))
+        self.parent.title("Fenêtre de connexion")
+
+        # Instanciation de la Frame, on va donc ajouter tout nos widgets à cet Frame
+        self.f = Frame(self.parent)
+
+        # Affichage des labels et boutons
+        tentativeDeConnexion = lambda _ = None: self.connexion(utilisateur.get(), motDpasse.get()) # lambda pour envoyer les informations entrés dans le formulaire
+        ecart = 80 # écart pour avoir un affichage centré
+        Label(self.f).grid(row=0, pady=50) # utilisé pour du padding (meilleur affichage)
+
+        Label(self.f, text="Utilisateur", font=self.font).grid(column=0, row=1, columnspan=2, padx=ecart - 20, pady=20, sticky=W)
+        utilisateur = Entry(self.f, font=self.font, width=18)
+        utilisateur.grid(column=1, row=2, columnspan=2, padx=ecart)
+
+        Label(self.f, text="Mot de passe", font=self.font).grid(column=0, row=3, columnspan=2, padx=ecart - 20, pady=20, sticky=W)
+        motDpasse = Entry(self.f, font=self.font, show='⁎', width=18)
+        motDpasse.grid(column=1, row=4, columnspan=2, padx=ecart)
+        motDpasse.bind("<Return>", tentativeDeConnexion)
+
+        def __afficherMDP(self):
+            """Permet de gérer l'affichage du mot de passe dans le champs sur la page de connexion."""
+            if self.mdpVisible == False: # si mot de passe caché, alors on l'affiche
+                self.mdpVisible = True
+                motDpasse.config(show='')
+                bouttonAffichageMDP.config(font=("Arial", 10, "overstrike"))
+
+            else: # inversement
+                self.mdpVisible = False
+                motDpasse.config(show='⁎')
+                bouttonAffichageMDP.config(font=("Arial", 10))
+
+        bouttonAffichageMDP = Button(self.f, text='👁', command=lambda: __afficherMDP(self))
+        bouttonAffichageMDP.grid(column=2, row=4, columnspan=2)
+        self.mdpVisible = False
+
+        bouton = Button(self.f, text="Se connecter", font=self.font, command=tentativeDeConnexion)
+        bouton.grid(column=0, row=5, columnspan=3, padx=ecart, pady=20)
+        bouton.bind("<Return>", tentativeDeConnexion)
+
+        Button(self.f, text="Quitter", font=self.font, command=quit).grid(column=0, row=6, columnspan=4, pady=20)
+
+if __name__ == "__main__":
+    """"Application "GesMag" pour le module de Programmation d'interfaces (2021-2022)"""
+    print("--  Compte par défaut --\nNom d'utilisateur: admin\nMot de passe: P@ssword\n")
+    GesMag().demarrer()
+
+
+
+
+
+
+
+

Functions

+
+
+def dimensionsFenetre(fenetre, taille: tuple) +
+
+

Permet de définir une fenetre centrer sur l'écran

+
+ +Expand source code + +
def dimensionsFenetre(fenetre, taille: tuple):
+    """Permet de définir une fenetre centrer sur l'écran"""
+    largeur = fenetre.winfo_screenwidth()
+    hauteur = fenetre.winfo_screenheight()
+
+    x = (largeur // 2) - (taille[0] // 2)
+    y = (hauteur // 2) - (taille[1] // 2)
+
+    fenetre.geometry(f"{taille[0]}x{taille[1]}+{x}+{y}")
+
+
+
+
+
+

Classes

+
+
+class GesMag +
+
+

Programme de Gestion d'une caise de magasin.

+
+ +Expand source code + +
class GesMag:
+    """Programme de Gestion d'une caise de magasin."""
+    def demarrer(self) -> None:
+        """Lance le programme GesMag."""
+        print("Lancement de l'interface de gestion d'une caisse d'un magasin...")
+        self.font = ("Comfortaa", 14) # police par défaut
+        Utilisateurs().creationTable() # on créer la base de donnée si elle n'existe pas déjà
+        self.parent = Tk() # on créer notre fenêtre principale
+
+        self._interfaceConnexion() # on créer la variable `self.f` qui est la frame a affiché
+        self.f.grid() # on affiche la frame
+
+        self.parent.mainloop() # on affiche la fenêtre
+
+    def motDePasseCorrect(self, motDPasse: str) -> tuple:
+        """Détermine si un mot de passe suit la politique du programme ou non."""
+        if len(motDPasse) == 0: # si le champs est vide
+            return (False, "Mot de passe incorrect.")
+        if len(motDPasse) < 8: # si le mot de passe est plus petit que 8 caractères
+            return (False, "Un mot de passe doit faire 8 caractères minimum.")
+        """
+        Pour le regex, je réfléchie comme dans la fonction `self.connexion`.
+        J'utilises pas `match` parce que je suis plus à l'aise avec `sub`.
+        """
+        if not sub(r"[A-Z]", '', motDPasse) != motDPasse:
+            return (False, "Un mot de passe doit au moins contenir une lettre majuscule.")
+        if not sub(r"[a-z]", '', motDPasse) != motDPasse:
+            return (False, "Un mot de passe doit au moins contenir une lettre minuscule.")
+        if not sub(r" *?[^\w\s]+", '', motDPasse) != motDPasse:
+            return (False, "Un mot de passe doit au moins contenir un caractère spécial.")
+
+        return (True,) # si aucun des tests précédents n'est valide, alors le mot de passe est valide
+
+    def connexion(self, utilisateur: str, motDePasse: str):
+        """Gère la connexion aux différentes interfaces de l'application."""
+        """
+        Vérification nom d'utilisateur / mot de passe correctement entré
+        -> Pour le nom d'utilisateur on vérifie si le champs n'est pas vide
+           et si il y a bien que des lettres et des chiffres (le regex élimine tout
+           ce qui n'est pas ça, alors si la fonction `sub` renvoie pas exactement
+           la même chaîne de charactère alors c'est qu'il y avait un charactère
+           interdit dans le nom d'utilisateur).
+        -> Pour le mot de passe on demande à la fonction `motDePasseCorrect` pour
+           éviter de faire tout les tests ici.
+        """
+        if len(utilisateur) == 0 or sub(r" *?[^\w\s]+", '', utilisateur) != utilisateur:
+            messagebox.showerror("Erreur", "Utilisateur incorrect.")
+            return
+        mdpOk = self.motDePasseCorrect(motDePasse)
+        if not mdpOk[0]:
+            messagebox.showerror("Erreur", mdpOk[1])
+            return
+
+        # Redirection vers la bonne interface
+        if Utilisateurs().verificationIdentifiants(utilisateur, motDePasse):
+            print("Bienvenue mon pote")
+        else:
+            print(f"Bah nan frérot c'est pas bon, ça c'est la liste des utilisateurs : {Utilisateurs().listUtilisateurs()}")
+
+    def _interfaceConnexion(self):
+        """Affiche la fenêtre de connexion."""
+        # Paramètres de la fenêtre
+        dimensionsFenetre(self.parent, (400, 600))
+        self.parent.title("Fenêtre de connexion")
+
+        # Instanciation de la Frame, on va donc ajouter tout nos widgets à cet Frame
+        self.f = Frame(self.parent)
+
+        # Affichage des labels et boutons
+        tentativeDeConnexion = lambda _ = None: self.connexion(utilisateur.get(), motDpasse.get()) # lambda pour envoyer les informations entrés dans le formulaire
+        ecart = 80 # écart pour avoir un affichage centré
+        Label(self.f).grid(row=0, pady=50) # utilisé pour du padding (meilleur affichage)
+
+        Label(self.f, text="Utilisateur", font=self.font).grid(column=0, row=1, columnspan=2, padx=ecart - 20, pady=20, sticky=W)
+        utilisateur = Entry(self.f, font=self.font, width=18)
+        utilisateur.grid(column=1, row=2, columnspan=2, padx=ecart)
+
+        Label(self.f, text="Mot de passe", font=self.font).grid(column=0, row=3, columnspan=2, padx=ecart - 20, pady=20, sticky=W)
+        motDpasse = Entry(self.f, font=self.font, show='⁎', width=18)
+        motDpasse.grid(column=1, row=4, columnspan=2, padx=ecart)
+        motDpasse.bind("<Return>", tentativeDeConnexion)
+
+        def __afficherMDP(self):
+            """Permet de gérer l'affichage du mot de passe dans le champs sur la page de connexion."""
+            if self.mdpVisible == False: # si mot de passe caché, alors on l'affiche
+                self.mdpVisible = True
+                motDpasse.config(show='')
+                bouttonAffichageMDP.config(font=("Arial", 10, "overstrike"))
+
+            else: # inversement
+                self.mdpVisible = False
+                motDpasse.config(show='⁎')
+                bouttonAffichageMDP.config(font=("Arial", 10))
+
+        bouttonAffichageMDP = Button(self.f, text='👁', command=lambda: __afficherMDP(self))
+        bouttonAffichageMDP.grid(column=2, row=4, columnspan=2)
+        self.mdpVisible = False
+
+        bouton = Button(self.f, text="Se connecter", font=self.font, command=tentativeDeConnexion)
+        bouton.grid(column=0, row=5, columnspan=3, padx=ecart, pady=20)
+        bouton.bind("<Return>", tentativeDeConnexion)
+
+        Button(self.f, text="Quitter", font=self.font, command=quit).grid(column=0, row=6, columnspan=4, pady=20)
+
+

Methods

+
+
+def connexion(self, utilisateur: str, motDePasse: str) +
+
+

Gère la connexion aux différentes interfaces de l'application.

+
+ +Expand source code + +
def connexion(self, utilisateur: str, motDePasse: str):
+    """Gère la connexion aux différentes interfaces de l'application."""
+    """
+    Vérification nom d'utilisateur / mot de passe correctement entré
+    -> Pour le nom d'utilisateur on vérifie si le champs n'est pas vide
+       et si il y a bien que des lettres et des chiffres (le regex élimine tout
+       ce qui n'est pas ça, alors si la fonction `sub` renvoie pas exactement
+       la même chaîne de charactère alors c'est qu'il y avait un charactère
+       interdit dans le nom d'utilisateur).
+    -> Pour le mot de passe on demande à la fonction `motDePasseCorrect` pour
+       éviter de faire tout les tests ici.
+    """
+    if len(utilisateur) == 0 or sub(r" *?[^\w\s]+", '', utilisateur) != utilisateur:
+        messagebox.showerror("Erreur", "Utilisateur incorrect.")
+        return
+    mdpOk = self.motDePasseCorrect(motDePasse)
+    if not mdpOk[0]:
+        messagebox.showerror("Erreur", mdpOk[1])
+        return
+
+    # Redirection vers la bonne interface
+    if Utilisateurs().verificationIdentifiants(utilisateur, motDePasse):
+        print("Bienvenue mon pote")
+    else:
+        print(f"Bah nan frérot c'est pas bon, ça c'est la liste des utilisateurs : {Utilisateurs().listUtilisateurs()}")
+
+
+
+def demarrer(self) ‑> None +
+
+

Lance le programme GesMag.

+
+ +Expand source code + +
def demarrer(self) -> None:
+    """Lance le programme GesMag."""
+    print("Lancement de l'interface de gestion d'une caisse d'un magasin...")
+    self.font = ("Comfortaa", 14) # police par défaut
+    Utilisateurs().creationTable() # on créer la base de donnée si elle n'existe pas déjà
+    self.parent = Tk() # on créer notre fenêtre principale
+
+    self._interfaceConnexion() # on créer la variable `self.f` qui est la frame a affiché
+    self.f.grid() # on affiche la frame
+
+    self.parent.mainloop() # on affiche la fenêtre
+
+
+
+def motDePasseCorrect(self, motDPasse: str) ‑> tuple +
+
+

Détermine si un mot de passe suit la politique du programme ou non.

+
+ +Expand source code + +
def motDePasseCorrect(self, motDPasse: str) -> tuple:
+    """Détermine si un mot de passe suit la politique du programme ou non."""
+    if len(motDPasse) == 0: # si le champs est vide
+        return (False, "Mot de passe incorrect.")
+    if len(motDPasse) < 8: # si le mot de passe est plus petit que 8 caractères
+        return (False, "Un mot de passe doit faire 8 caractères minimum.")
+    """
+    Pour le regex, je réfléchie comme dans la fonction `self.connexion`.
+    J'utilises pas `match` parce que je suis plus à l'aise avec `sub`.
+    """
+    if not sub(r"[A-Z]", '', motDPasse) != motDPasse:
+        return (False, "Un mot de passe doit au moins contenir une lettre majuscule.")
+    if not sub(r"[a-z]", '', motDPasse) != motDPasse:
+        return (False, "Un mot de passe doit au moins contenir une lettre minuscule.")
+    if not sub(r" *?[^\w\s]+", '', motDPasse) != motDPasse:
+        return (False, "Un mot de passe doit au moins contenir un caractère spécial.")
+
+    return (True,) # si aucun des tests précédents n'est valide, alors le mot de passe est valide
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/doc/GesMag/users.html b/doc/GesMag/users.html new file mode 100644 index 0000000..bd6cb66 --- /dev/null +++ b/doc/GesMag/users.html @@ -0,0 +1,357 @@ + + + + + + +GesMag.users API documentation + + + + + + + + + + + +
+
+
+

Module GesMag.users

+
+
+
+ +Expand source code + +
from db import BaseDeDonnees
+
+class Utilisateurs(BaseDeDonnees):
+    """Gère une table "utilisateurs" pour une base de donnée donné."""
+    def __init__(self):
+        super().__init__(r"utilisateurs.sqlite3")
+
+    def creationTable(self) -> None:
+        """Créer la table qui stocker les utilisateurs."""
+        requete = """
+                  CREATE TABLE IF NOT EXISTS utilisateurs (
+                      id INTEGER PRIMARY KEY,
+                      pseudo TEXT,
+                      passe TEXT,
+                      metier INTEGER,
+                      nom TEXT,
+                      prenom TEXT,
+                      naissance TEXT,
+                      adresse TEXT,
+                      postal INTEGER
+                  );
+                  """
+        self.requete(requete)
+        # Ajout d'un utilisateur par défaut si aucun utilisateur n'existe dans la base de donnée
+        if len(self.listUtilisateurs()) == 0:
+            self.ajoutUtilisateurs(
+                pseudo="admin",
+                passe="P@ssword",
+                metier=0,
+                nom="Admin",
+                prenom="Admin",
+                naissance="2000/10/09",
+                adresse="12 Rue de Montmartre",
+                postal=46800
+            )
+
+    def ajoutUtilisateurs(self, pseudo: str, passe: str, metier: int, nom: str, prenom: str, naissance: str, adresse: str, postal: str) -> list:
+        """Ajoute un utilisateur et retourne l'ID de ce dernier."""
+        requete = """
+                  INSERT INTO utilisateurs (
+                      pseudo, passe, metier, nom, prenom, naissance, adresse, postal
+                  ) VALUES (
+                      ?, ?, ?, ?, ?, ?, ?, ?
+                  );
+                  """
+        self.requete(requete, [pseudo, passe, metier, nom, prenom, naissance, adresse, postal])
+        return self.affichageResultat(self.requete("SELECT last_insert_rowid();"))
+
+    def suppressionUtilisateurs(self, pseudo: str) -> None:
+        """Supprime un utilisateur."""
+        requete = """
+                  DELETE FROM utilisateurs
+                  WHERE pseudo = ?
+                  """
+        self.requete(requete, pseudo)
+
+    def verificationIdentifiants(self, pseudo: str, motDePasse: str) -> bool:
+        """Renvoie vrai ou faux si les identifiants données sont bons."""
+        requete = """
+                  SELECT EXISTS (
+                      SELECT 1 FROM utilisateurs
+                      WHERE pseudo = ? AND passe = ?
+                  )
+                  """
+        # Vrai si le premier élément que renvoie la requête au dessus est 1
+        return True if self.affichageResultat(self.requete(requete, [pseudo, motDePasse]))[0][0] == 1 else False
+
+    def listUtilisateurs(self) -> list:
+        """Retourne la liste des nom d'utilisateurs."""
+        requete = """
+                  SELECT pseudo FROM utilisateurs
+                  """
+        # i[0] parce que sinon ça renvoie des Tuple qui ressemble à ça : `(Utilisateur,)`
+        return [i[0] for i in self.affichageResultat(self.requete(requete))]
+
+
+
+
+
+
+
+
+
+

Classes

+
+
+class Utilisateurs +
+
+

Gère une table "utilisateurs" pour une base de donnée donné.

+
+ +Expand source code + +
class Utilisateurs(BaseDeDonnees):
+    """Gère une table "utilisateurs" pour une base de donnée donné."""
+    def __init__(self):
+        super().__init__(r"utilisateurs.sqlite3")
+
+    def creationTable(self) -> None:
+        """Créer la table qui stocker les utilisateurs."""
+        requete = """
+                  CREATE TABLE IF NOT EXISTS utilisateurs (
+                      id INTEGER PRIMARY KEY,
+                      pseudo TEXT,
+                      passe TEXT,
+                      metier INTEGER,
+                      nom TEXT,
+                      prenom TEXT,
+                      naissance TEXT,
+                      adresse TEXT,
+                      postal INTEGER
+                  );
+                  """
+        self.requete(requete)
+        # Ajout d'un utilisateur par défaut si aucun utilisateur n'existe dans la base de donnée
+        if len(self.listUtilisateurs()) == 0:
+            self.ajoutUtilisateurs(
+                pseudo="admin",
+                passe="P@ssword",
+                metier=0,
+                nom="Admin",
+                prenom="Admin",
+                naissance="2000/10/09",
+                adresse="12 Rue de Montmartre",
+                postal=46800
+            )
+
+    def ajoutUtilisateurs(self, pseudo: str, passe: str, metier: int, nom: str, prenom: str, naissance: str, adresse: str, postal: str) -> list:
+        """Ajoute un utilisateur et retourne l'ID de ce dernier."""
+        requete = """
+                  INSERT INTO utilisateurs (
+                      pseudo, passe, metier, nom, prenom, naissance, adresse, postal
+                  ) VALUES (
+                      ?, ?, ?, ?, ?, ?, ?, ?
+                  );
+                  """
+        self.requete(requete, [pseudo, passe, metier, nom, prenom, naissance, adresse, postal])
+        return self.affichageResultat(self.requete("SELECT last_insert_rowid();"))
+
+    def suppressionUtilisateurs(self, pseudo: str) -> None:
+        """Supprime un utilisateur."""
+        requete = """
+                  DELETE FROM utilisateurs
+                  WHERE pseudo = ?
+                  """
+        self.requete(requete, pseudo)
+
+    def verificationIdentifiants(self, pseudo: str, motDePasse: str) -> bool:
+        """Renvoie vrai ou faux si les identifiants données sont bons."""
+        requete = """
+                  SELECT EXISTS (
+                      SELECT 1 FROM utilisateurs
+                      WHERE pseudo = ? AND passe = ?
+                  )
+                  """
+        # Vrai si le premier élément que renvoie la requête au dessus est 1
+        return True if self.affichageResultat(self.requete(requete, [pseudo, motDePasse]))[0][0] == 1 else False
+
+    def listUtilisateurs(self) -> list:
+        """Retourne la liste des nom d'utilisateurs."""
+        requete = """
+                  SELECT pseudo FROM utilisateurs
+                  """
+        # i[0] parce que sinon ça renvoie des Tuple qui ressemble à ça : `(Utilisateur,)`
+        return [i[0] for i in self.affichageResultat(self.requete(requete))]
+
+

Ancestors

+
    +
  • db.BaseDeDonnees
  • +
+

Methods

+
+
+def ajoutUtilisateurs(self, pseudo: str, passe: str, metier: int, nom: str, prenom: str, naissance: str, adresse: str, postal: str) ‑> list +
+
+

Ajoute un utilisateur et retourne l'ID de ce dernier.

+
+ +Expand source code + +
def ajoutUtilisateurs(self, pseudo: str, passe: str, metier: int, nom: str, prenom: str, naissance: str, adresse: str, postal: str) -> list:
+    """Ajoute un utilisateur et retourne l'ID de ce dernier."""
+    requete = """
+              INSERT INTO utilisateurs (
+                  pseudo, passe, metier, nom, prenom, naissance, adresse, postal
+              ) VALUES (
+                  ?, ?, ?, ?, ?, ?, ?, ?
+              );
+              """
+    self.requete(requete, [pseudo, passe, metier, nom, prenom, naissance, adresse, postal])
+    return self.affichageResultat(self.requete("SELECT last_insert_rowid();"))
+
+
+
+def creationTable(self) ‑> None +
+
+

Créer la table qui stocker les utilisateurs.

+
+ +Expand source code + +
def creationTable(self) -> None:
+    """Créer la table qui stocker les utilisateurs."""
+    requete = """
+              CREATE TABLE IF NOT EXISTS utilisateurs (
+                  id INTEGER PRIMARY KEY,
+                  pseudo TEXT,
+                  passe TEXT,
+                  metier INTEGER,
+                  nom TEXT,
+                  prenom TEXT,
+                  naissance TEXT,
+                  adresse TEXT,
+                  postal INTEGER
+              );
+              """
+    self.requete(requete)
+    # Ajout d'un utilisateur par défaut si aucun utilisateur n'existe dans la base de donnée
+    if len(self.listUtilisateurs()) == 0:
+        self.ajoutUtilisateurs(
+            pseudo="admin",
+            passe="P@ssword",
+            metier=0,
+            nom="Admin",
+            prenom="Admin",
+            naissance="2000/10/09",
+            adresse="12 Rue de Montmartre",
+            postal=46800
+        )
+
+
+
+def listUtilisateurs(self) ‑> list +
+
+

Retourne la liste des nom d'utilisateurs.

+
+ +Expand source code + +
def listUtilisateurs(self) -> list:
+    """Retourne la liste des nom d'utilisateurs."""
+    requete = """
+              SELECT pseudo FROM utilisateurs
+              """
+    # i[0] parce que sinon ça renvoie des Tuple qui ressemble à ça : `(Utilisateur,)`
+    return [i[0] for i in self.affichageResultat(self.requete(requete))]
+
+
+
+def suppressionUtilisateurs(self, pseudo: str) ‑> None +
+
+

Supprime un utilisateur.

+
+ +Expand source code + +
def suppressionUtilisateurs(self, pseudo: str) -> None:
+    """Supprime un utilisateur."""
+    requete = """
+              DELETE FROM utilisateurs
+              WHERE pseudo = ?
+              """
+    self.requete(requete, pseudo)
+
+
+
+def verificationIdentifiants(self, pseudo: str, motDePasse: str) ‑> bool +
+
+

Renvoie vrai ou faux si les identifiants données sont bons.

+
+ +Expand source code + +
def verificationIdentifiants(self, pseudo: str, motDePasse: str) -> bool:
+    """Renvoie vrai ou faux si les identifiants données sont bons."""
+    requete = """
+              SELECT EXISTS (
+                  SELECT 1 FROM utilisateurs
+                  WHERE pseudo = ? AND passe = ?
+              )
+              """
+    # Vrai si le premier élément que renvoie la requête au dessus est 1
+    return True if self.affichageResultat(self.requete(requete, [pseudo, motDePasse]))[0][0] == 1 else False
+
+
+
+
+
+
+
+ +
+ + + \ No newline at end of file diff --git a/doc/README.md b/doc/README.md deleted file mode 100644 index e6a2f4b..0000000 --- a/doc/README.md +++ /dev/null @@ -1,342 +0,0 @@ ---- -description: | - API documentation for modules: GesMag, GesMag.db, GesMag.main, GesMag.users. - -lang: en - -classoption: oneside -geometry: margin=1in -papersize: a4 - -linkcolor: blue -links-as-notes: true -... - - - -# Namespace `GesMag` {#id} - - - - - -## Sub-modules - -* [GesMag.db](#GesMag.db) -* [GesMag.main](#GesMag.main) -* [GesMag.users](#GesMag.users) - - - - - - - -# Module `GesMag.db` {#id} - - - - - - - - -## Classes - - - -### Class `BaseDeDonnees` {#id} - - - - -> class BaseDeDonnees( -> urlBaseDeDonnee: str -> ) - - -Gère la base de donnée. - - - - - - - - -#### Methods - - - -##### Method `affichageResultat` {#id} - - - - -> def affichageResultat( -> self, -> curseur: sqlite3.Cursor -> ) ‑> list - - -Affiche le résultat d'une requête. - - -##### Method `creerConnexion` {#id} - - - - -> def creerConnexion( -> self, -> path: str -> ) - - -Connexion à une base de donnée SQLite. - - -##### Method `fichierExiste` {#id} - - - - -> def fichierExiste( -> self, -> path: str -> ) ‑> bool - - -Vérifie qu'un fichier existe. - - -##### Method `requete` {#id} - - - - -> def requete( -> self, -> requete: str, -> valeurs=None -> ) - - -Envois une requête vers la base de données. - - - - -# Module `GesMag.main` {#id} - - - - - - - -## Functions - - - -### Function `dimensionsFenetre` {#id} - - - - -> def dimensionsFenetre( -> fenetre, -> taille: tuple -> ) - - -Permet de définir une fenetre centrer sur l'écran - - - -## Classes - - - -### Class `GesMag` {#id} - - - - -> class GesMag - - -Programme de Gestion d'une caise de magasin. - - - - - - - - -#### Methods - - - -##### Method `connexion` {#id} - - - - -> def connexion( -> self, -> utilisateur: str, -> motDePasse: str -> ) - - -Gère la connexion aux différentes interfaces de l'application. - - -##### Method `demarrer` {#id} - - - - -> def demarrer( -> self -> ) ‑> None - - -Lance le programme GesMag. - - -##### Method `motDePasseCorrect` {#id} - - - - -> def motDePasseCorrect( -> self, -> motDPasse: str -> ) ‑> tuple - - -Détermine si un mot de passe suit la politique du programme ou non. - - - - -# Module `GesMag.users` {#id} - - - - - - - - -## Classes - - - -### Class `Utilisateurs` {#id} - - - - -> class Utilisateurs - - -Gère une table "utilisateurs" pour une base de donnée donné. - - - -#### Ancestors (in MRO) - -* [db.BaseDeDonnees](#db.BaseDeDonnees) - - - - - - - -#### Methods - - - -##### Method `ajoutUtilisateurs` {#id} - - - - -> def ajoutUtilisateurs( -> self, -> pseudo: str, -> passe: str, -> metier: int, -> nom: str, -> prenom: str, -> naissance: str, -> adresse: str, -> postal: str -> ) ‑> list - - -Ajoute un utilisateur et retourne l'ID de ce dernier. - - -##### Method `creationTable` {#id} - - - - -> def creationTable( -> self -> ) ‑> None - - -Créer la table qui stocker les utilisateurs. - - -##### Method `listUtilisateurs` {#id} - - - - -> def listUtilisateurs( -> self -> ) ‑> list - - -Retourne la liste des nom d'utilisateurs. - - -##### Method `suppressionUtilisateurs` {#id} - - - - -> def suppressionUtilisateurs( -> self, -> pseudo: str -> ) ‑> None - - -Supprime un utilisateur. - - -##### Method `verificationIdentifiants` {#id} - - - - -> def verificationIdentifiants( -> self, -> pseudo: str, -> motDePasse: str -> ) ‑> bool - - -Renvoie vrai ou faux si les identifiants données sont bons. - - ------ -Generated by *pdoc* 0.10.0 (). diff --git a/doc/README.pdf b/doc/README.pdf deleted file mode 100644 index 709758a..0000000 Binary files a/doc/README.pdf and /dev/null differ