leave pdoc for classic latex documentation
This commit is contained in:
parent
cf833625e3
commit
e6e87732f2
7 changed files with 184 additions and 1138 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,4 +1,8 @@
|
|||
__pycache__/
|
||||
documentation/*
|
||||
|
||||
*.pdf
|
||||
*.sqlite3
|
||||
|
||||
!documentation/documentation.pdf
|
||||
!documentation/documentation.tex
|
||||
|
|
|
@ -52,9 +52,3 @@ A savoir :
|
|||
- [ ] Exporter le ticket de caisse en format image
|
||||
- [x] Lisibilité du code
|
||||
- [x] Toutes les fonctions sont nommés et typés (j'utilises `Python 3.9.7`)
|
||||
|
||||
### 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 --html -fc "html_lang='fr'" -o ./documentation .
|
||||
```
|
||||
|
|
|
@ -1,275 +0,0 @@
|
|||
<!doctype html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
|
||||
<meta name="generator" content="pdoc 0.10.0" />
|
||||
<title>GesMag.db API documentation</title>
|
||||
<meta name="description" content="" />
|
||||
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
|
||||
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
|
||||
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
|
||||
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
|
||||
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
|
||||
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
|
||||
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
|
||||
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<article id="content">
|
||||
<header>
|
||||
<h1 class="title">Module <code>GesMag.db</code></h1>
|
||||
</header>
|
||||
<section id="section-intro">
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">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</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="GesMag.db.BaseDeDonnees"><code class="flex name class">
|
||||
<span>class <span class="ident">BaseDeDonnees</span></span>
|
||||
<span>(</span><span>urlBaseDeDonnee: str)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Gère la base de donnée.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">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</code></pre>
|
||||
</details>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="GesMag.db.BaseDeDonnees.affichageResultat"><code class="name flex">
|
||||
<span>def <span class="ident">affichageResultat</span></span>(<span>self, curseur: sqlite3.Cursor) ‑> list</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Affiche le résultat d'une requête.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">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</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="GesMag.db.BaseDeDonnees.creerConnexion"><code class="name flex">
|
||||
<span>def <span class="ident">creerConnexion</span></span>(<span>self, path: str)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Connexion à une base de donnée SQLite.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">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</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="GesMag.db.BaseDeDonnees.fichierExiste"><code class="name flex">
|
||||
<span>def <span class="ident">fichierExiste</span></span>(<span>self, path: str) ‑> bool</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Vérifie qu'un fichier existe.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">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</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="GesMag.db.BaseDeDonnees.requete"><code class="name flex">
|
||||
<span>def <span class="ident">requete</span></span>(<span>self, requete: str, valeurs=None)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Envois une requête vers la base de données.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">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)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</article>
|
||||
<nav id="sidebar">
|
||||
<h1>Index</h1>
|
||||
<div class="toc">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<ul id="index">
|
||||
<li><h3>Super-module</h3>
|
||||
<ul>
|
||||
<li><code><a title="GesMag" href="index.html">GesMag</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="GesMag.db.BaseDeDonnees" href="#GesMag.db.BaseDeDonnees">BaseDeDonnees</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="GesMag.db.BaseDeDonnees.affichageResultat" href="#GesMag.db.BaseDeDonnees.affichageResultat">affichageResultat</a></code></li>
|
||||
<li><code><a title="GesMag.db.BaseDeDonnees.creerConnexion" href="#GesMag.db.BaseDeDonnees.creerConnexion">creerConnexion</a></code></li>
|
||||
<li><code><a title="GesMag.db.BaseDeDonnees.fichierExiste" href="#GesMag.db.BaseDeDonnees.fichierExiste">fichierExiste</a></code></li>
|
||||
<li><code><a title="GesMag.db.BaseDeDonnees.requete" href="#GesMag.db.BaseDeDonnees.requete">requete</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
|
@ -1,70 +0,0 @@
|
|||
<!doctype html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
|
||||
<meta name="generator" content="pdoc 0.10.0" />
|
||||
<title>GesMag API documentation</title>
|
||||
<meta name="description" content="" />
|
||||
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
|
||||
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
|
||||
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
|
||||
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
|
||||
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
|
||||
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
|
||||
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
|
||||
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<article id="content">
|
||||
<header>
|
||||
<h1 class="title">Namespace <code>GesMag</code></h1>
|
||||
</header>
|
||||
<section id="section-intro">
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-submodules">Sub-modules</h2>
|
||||
<dl>
|
||||
<dt><code class="name"><a title="GesMag.db" href="db.html">GesMag.db</a></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="GesMag.main" href="main.html">GesMag.main</a></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
<dt><code class="name"><a title="GesMag.users" href="users.html">GesMag.users</a></code></dt>
|
||||
<dd>
|
||||
<div class="desc"></div>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
</article>
|
||||
<nav id="sidebar">
|
||||
<h1>Index</h1>
|
||||
<div class="toc">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<ul id="index">
|
||||
<li><h3><a href="#header-submodules">Sub-modules</a></h3>
|
||||
<ul>
|
||||
<li><code><a title="GesMag.db" href="db.html">GesMag.db</a></code></li>
|
||||
<li><code><a title="GesMag.main" href="main.html">GesMag.main</a></code></li>
|
||||
<li><code><a title="GesMag.users" href="users.html">GesMag.users</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
|
@ -1,430 +0,0 @@
|
|||
<!doctype html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
|
||||
<meta name="generator" content="pdoc 0.10.0" />
|
||||
<title>GesMag.main API documentation</title>
|
||||
<meta name="description" content="" />
|
||||
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
|
||||
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
|
||||
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
|
||||
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
|
||||
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
|
||||
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
|
||||
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
|
||||
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<article id="content">
|
||||
<header>
|
||||
<h1 class="title">Module <code>GesMag.main</code></h1>
|
||||
</header>
|
||||
<section id="section-intro">
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">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()</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-functions">Functions</h2>
|
||||
<dl>
|
||||
<dt id="GesMag.main.dimensionsFenetre"><code class="name flex">
|
||||
<span>def <span class="ident">dimensionsFenetre</span></span>(<span>fenetre, taille: tuple)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Permet de définir une fenetre centrer sur l'écran</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">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}")</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="GesMag.main.GesMag"><code class="flex name class">
|
||||
<span>class <span class="ident">GesMag</span></span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Programme de Gestion d'une caise de magasin.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">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)</code></pre>
|
||||
</details>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="GesMag.main.GesMag.connexion"><code class="name flex">
|
||||
<span>def <span class="ident">connexion</span></span>(<span>self, utilisateur: str, motDePasse: str)</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Gère la connexion aux différentes interfaces de l'application.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">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()}")</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="GesMag.main.GesMag.demarrer"><code class="name flex">
|
||||
<span>def <span class="ident">demarrer</span></span>(<span>self) ‑> None</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Lance le programme GesMag.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">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</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="GesMag.main.GesMag.motDePasseCorrect"><code class="name flex">
|
||||
<span>def <span class="ident">motDePasseCorrect</span></span>(<span>self, motDPasse: str) ‑> tuple</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Détermine si un mot de passe suit la politique du programme ou non.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">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</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</article>
|
||||
<nav id="sidebar">
|
||||
<h1>Index</h1>
|
||||
<div class="toc">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<ul id="index">
|
||||
<li><h3>Super-module</h3>
|
||||
<ul>
|
||||
<li><code><a title="GesMag" href="index.html">GesMag</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-functions">Functions</a></h3>
|
||||
<ul class="">
|
||||
<li><code><a title="GesMag.main.dimensionsFenetre" href="#GesMag.main.dimensionsFenetre">dimensionsFenetre</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="GesMag.main.GesMag" href="#GesMag.main.GesMag">GesMag</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="GesMag.main.GesMag.connexion" href="#GesMag.main.GesMag.connexion">connexion</a></code></li>
|
||||
<li><code><a title="GesMag.main.GesMag.demarrer" href="#GesMag.main.GesMag.demarrer">demarrer</a></code></li>
|
||||
<li><code><a title="GesMag.main.GesMag.motDePasseCorrect" href="#GesMag.main.GesMag.motDePasseCorrect">motDePasseCorrect</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
|
@ -1,357 +0,0 @@
|
|||
<!doctype html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
|
||||
<meta name="generator" content="pdoc 0.10.0" />
|
||||
<title>GesMag.users API documentation</title>
|
||||
<meta name="description" content="" />
|
||||
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
|
||||
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
|
||||
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
|
||||
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
|
||||
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
|
||||
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
|
||||
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
|
||||
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<article id="content">
|
||||
<header>
|
||||
<h1 class="title">Module <code>GesMag.users</code></h1>
|
||||
</header>
|
||||
<section id="section-intro">
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">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))]</code></pre>
|
||||
</details>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
</section>
|
||||
<section>
|
||||
<h2 class="section-title" id="header-classes">Classes</h2>
|
||||
<dl>
|
||||
<dt id="GesMag.users.Utilisateurs"><code class="flex name class">
|
||||
<span>class <span class="ident">Utilisateurs</span></span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Gère une table "utilisateurs" pour une base de donnée donné.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">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))]</code></pre>
|
||||
</details>
|
||||
<h3>Ancestors</h3>
|
||||
<ul class="hlist">
|
||||
<li>db.BaseDeDonnees</li>
|
||||
</ul>
|
||||
<h3>Methods</h3>
|
||||
<dl>
|
||||
<dt id="GesMag.users.Utilisateurs.ajoutUtilisateurs"><code class="name flex">
|
||||
<span>def <span class="ident">ajoutUtilisateurs</span></span>(<span>self, pseudo: str, passe: str, metier: int, nom: str, prenom: str, naissance: str, adresse: str, postal: str) ‑> list</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Ajoute un utilisateur et retourne l'ID de ce dernier.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">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();"))</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="GesMag.users.Utilisateurs.creationTable"><code class="name flex">
|
||||
<span>def <span class="ident">creationTable</span></span>(<span>self) ‑> None</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Créer la table qui stocker les utilisateurs.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">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
|
||||
)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="GesMag.users.Utilisateurs.listUtilisateurs"><code class="name flex">
|
||||
<span>def <span class="ident">listUtilisateurs</span></span>(<span>self) ‑> list</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Retourne la liste des nom d'utilisateurs.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">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))]</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="GesMag.users.Utilisateurs.suppressionUtilisateurs"><code class="name flex">
|
||||
<span>def <span class="ident">suppressionUtilisateurs</span></span>(<span>self, pseudo: str) ‑> None</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Supprime un utilisateur.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">def suppressionUtilisateurs(self, pseudo: str) -> None:
|
||||
"""Supprime un utilisateur."""
|
||||
requete = """
|
||||
DELETE FROM utilisateurs
|
||||
WHERE pseudo = ?
|
||||
"""
|
||||
self.requete(requete, pseudo)</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
<dt id="GesMag.users.Utilisateurs.verificationIdentifiants"><code class="name flex">
|
||||
<span>def <span class="ident">verificationIdentifiants</span></span>(<span>self, pseudo: str, motDePasse: str) ‑> bool</span>
|
||||
</code></dt>
|
||||
<dd>
|
||||
<div class="desc"><p>Renvoie vrai ou faux si les identifiants données sont bons.</p></div>
|
||||
<details class="source">
|
||||
<summary>
|
||||
<span>Expand source code</span>
|
||||
</summary>
|
||||
<pre><code class="python">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</code></pre>
|
||||
</details>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</article>
|
||||
<nav id="sidebar">
|
||||
<h1>Index</h1>
|
||||
<div class="toc">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<ul id="index">
|
||||
<li><h3>Super-module</h3>
|
||||
<ul>
|
||||
<li><code><a title="GesMag" href="index.html">GesMag</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><h3><a href="#header-classes">Classes</a></h3>
|
||||
<ul>
|
||||
<li>
|
||||
<h4><code><a title="GesMag.users.Utilisateurs" href="#GesMag.users.Utilisateurs">Utilisateurs</a></code></h4>
|
||||
<ul class="">
|
||||
<li><code><a title="GesMag.users.Utilisateurs.ajoutUtilisateurs" href="#GesMag.users.Utilisateurs.ajoutUtilisateurs">ajoutUtilisateurs</a></code></li>
|
||||
<li><code><a title="GesMag.users.Utilisateurs.creationTable" href="#GesMag.users.Utilisateurs.creationTable">creationTable</a></code></li>
|
||||
<li><code><a title="GesMag.users.Utilisateurs.listUtilisateurs" href="#GesMag.users.Utilisateurs.listUtilisateurs">listUtilisateurs</a></code></li>
|
||||
<li><code><a title="GesMag.users.Utilisateurs.suppressionUtilisateurs" href="#GesMag.users.Utilisateurs.suppressionUtilisateurs">suppressionUtilisateurs</a></code></li>
|
||||
<li><code><a title="GesMag.users.Utilisateurs.verificationIdentifiants" href="#GesMag.users.Utilisateurs.verificationIdentifiants">verificationIdentifiants</a></code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</main>
|
||||
<footer id="footer">
|
||||
<p>Generated by <a href="https://pdoc3.github.io/pdoc" title="pdoc: Python API documentation generator"><cite>pdoc</cite> 0.10.0</a>.</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
180
documentation/documentation.tex
Normal file
180
documentation/documentation.tex
Normal file
|
@ -0,0 +1,180 @@
|
|||
\documentclass{article}
|
||||
|
||||
\usepackage[french]{babel} % français
|
||||
\usepackage[T1]{fontenc} % encodage
|
||||
\usepackage[hidelinks]{hyperref} % liens cliquable dans la table des matières
|
||||
\usepackage{graphicx} % images
|
||||
\usepackage{listingsutf8} % intégration code
|
||||
\usepackage{xcolor} % couleurs personnalisés
|
||||
\usepackage{geometry} % change les dimensions de la page
|
||||
\usepackage{enumitem} % liste personnalisée
|
||||
\usepackage{amssymb, pifont} % police (todolist)
|
||||
|
||||
\geometry{ % définition taille pages
|
||||
a4paper,
|
||||
left=20mm,
|
||||
top=20mm
|
||||
}
|
||||
|
||||
% définition de la liste de choses à faire/faites (https://tex.stackexchange.com/q/247681/)
|
||||
\newlist{todolist}{itemize}{3}
|
||||
\setlist[todolist]{label=$\square$}
|
||||
\newcommand{\fait}{\rlap{\raisebox{0.3ex}{\hspace{0.4ex}\scriptsize \ding{56}}}$\square$}
|
||||
|
||||
% définition blocs de codes
|
||||
\lstset{
|
||||
breaklines=true,
|
||||
extendedchars=true,
|
||||
inputencoding=utf8/latin1
|
||||
}
|
||||
|
||||
% Python definition (c) 1998 Michael Weber
|
||||
% Additional definitions (2013) Alexis Dimitriadis
|
||||
% modified by https://tex.stackexchange.com/questions/235783/listings-recognize-numbers-and-1e-3
|
||||
\definecolor{maroon}{cmyk}{0, 0.87, 0.68, 0.32}
|
||||
\definecolor{halfgray}{gray}{0.55}
|
||||
\definecolor{ipython_frame}{RGB}{207, 207, 207}
|
||||
\definecolor{ipython_bg}{RGB}{247, 247, 247}
|
||||
\definecolor{ipython_red}{RGB}{186, 33, 33}
|
||||
\definecolor{ipython_green}{RGB}{0, 128, 0}
|
||||
\definecolor{ipython_cyan}{RGB}{64, 128, 128}
|
||||
\definecolor{ipython_purple}{RGB}{170, 34, 255}
|
||||
\lstdefinelanguage{iPython}{
|
||||
morekeywords={access,and,break,class,continue,def,del,elif,else,except,exec,finally,for,from,global,if,import,in,is,lambda,not,or,pass,print,raise,return,try,while},
|
||||
morekeywords=[2]{abs,all,any,basestring,bin,bool,bytearray,callable,chr,classmethod,cmp,compile,complex,delattr,dict,dir,divmod,enumerate,eval,execfile,file,filter,float,format,frozenset,getattr,globals,hasattr,hash,help,hex,id,input,int,isinstance,issubclass,iter,len,list,locals,long,map,max,memoryview,min,next,object,oct,open,ord,pow,property,range,raw_input,reduce,reload,repr,reversed,round,set,setattr,slice,sorted,staticmethod,str,sum,super,tuple,type,unichr,unicode,vars,xrange,zip,apply,buffer,coerce,intern},
|
||||
sensitive=true,
|
||||
morecomment=[l]\#,
|
||||
morestring=[b]',
|
||||
morestring=[b]",
|
||||
morecomment=[s]{"""}{"""},
|
||||
morestring=[s]{'''}{'''},
|
||||
morestring=[s]{r'}{'},
|
||||
morestring=[s]{r"}{"},
|
||||
morestring=[s]{r'''}{'''},
|
||||
morestring=[s]{r"""}{"""},
|
||||
morestring=[s]{u'}{'},
|
||||
morestring=[s]{u"}{"},
|
||||
morestring=[s]{u'''}{'''},
|
||||
morestring=[s]{u"""}{"""},
|
||||
literate=
|
||||
*{+}{{{\color{ipython_purple}+}}}1
|
||||
{-}{{{\color{ipython_purple}-}}}1
|
||||
{*}{{{\color{ipython_purple}$^\ast$}}}1
|
||||
{/}{{{\color{ipython_purple}/}}}1
|
||||
{^}{{{\color{ipython_purple}\^{}}}}1
|
||||
{?}{{{\color{ipython_purple}?}}}1
|
||||
{!}{{{\color{ipython_purple}!}}}1
|
||||
{\%}{{{\color{ipython_purple}\%}}}1
|
||||
{<}{{{\color{ipython_purple}<}}}1
|
||||
{>}{{{\color{ipython_purple}>}}}1
|
||||
{|}{{{\color{ipython_purple}|}}}1
|
||||
{\&}{{{\color{ipython_purple}\&}}}1
|
||||
{~}{{{\color{ipython_purple}~}}}1
|
||||
{==}{{{\color{ipython_purple}==}}}2
|
||||
{<=}{{{\color{ipython_purple}<=}}}2
|
||||
{>=}{{{\color{ipython_purple}>=}}}2
|
||||
{+=}{{{+=}}}2
|
||||
{-=}{{{-=}}}2
|
||||
{*=}{{{$^\ast$=}}}2
|
||||
{/=}{{{/=}}}2,
|
||||
commentstyle=\color{ipython_cyan}\ttfamily,
|
||||
stringstyle=\color{ipython_red}\ttfamily,
|
||||
keepspaces=true,
|
||||
showspaces=false,
|
||||
showstringspaces=false,
|
||||
rulecolor=\color{ipython_frame},
|
||||
frame=single,
|
||||
frameround={t}{t}{t}{t},
|
||||
framexleftmargin=6mm,
|
||||
numbers=left,
|
||||
numberstyle=\tiny\color{halfgray},
|
||||
backgroundcolor=\color{ipython_bg},
|
||||
basicstyle=\scriptsize\ttfamily,
|
||||
keywordstyle=\color{ipython_green}\ttfamily,
|
||||
escapechar=\¢,
|
||||
escapebegin=\color{ipython_green},
|
||||
}
|
||||
|
||||
\author{Anri Kennel}
|
||||
\title{Programmation d'interfaces $\cdot$ Projet final}
|
||||
\date{}
|
||||
|
||||
\begin{document}
|
||||
\maketitle
|
||||
\tableofcontents
|
||||
|
||||
\begin{center}
|
||||
\emph{Les explications sont en commentaire du code.}
|
||||
\end{center}
|
||||
\clearpage
|
||||
|
||||
\section{Consigne}
|
||||
|
||||
\begin{todolist}
|
||||
\item[\fait] Page de login \texttt{/1.5}
|
||||
\begin{todolist}
|
||||
\item[\fait] Nom d'utilisateur ne contient que des lettres et des chiffres
|
||||
\item[\fait] Mot de passe de minimum 8 caractères dont 1 caractère spécial, une majuscule et une minuscule (possibilité d'afficher ou non en clair le mot de passe)
|
||||
\item[\fait] Un bouton de connexion (possibilité aussi d'utiliser la touche Entrer pour aller plus vite) qui permet de se rendre sur l'interface Caissier ou Manager
|
||||
\item[\fait] Un bouton pour quitter l'application
|
||||
\end{todolist}
|
||||
\item Page de manager (définit par un nom d'utilisateur et un mot de passe) \texttt{/7.5}
|
||||
\begin{todolist}
|
||||
\item Peut ajouter et supprimer un caissier
|
||||
\item Peut voir la liste des caissiers
|
||||
\item Un suivi des ventes
|
||||
\item Un bouton pour vider tous les champs de saisie
|
||||
\item Un bouton pour quitter l'application
|
||||
\item Un bouton pour se mettre en "mode caissier"
|
||||
\end{todolist}
|
||||
\item Page de caissier (définit par un identifiant, un nom d'utilisateur, un mot de passe, un nom, un prenom, une date de naissance, une adresse et une code postal) \texttt{/6}
|
||||
\begin{todolist}
|
||||
\item Afficher le stock disponible
|
||||
\begin{todolist}
|
||||
\item 4 rayons de chacun au moins 10 articles de votre choix (fruits/légumes, boulangerie, boucherie/poissonnerie ou produits d'entretien)
|
||||
\item Au clic sur le produit, l'identifiant, le nom, la quantité en stock et le prix s'affichent
|
||||
\item Possibilité de rajouter des produits en stock
|
||||
\end{todolist}
|
||||
\item Affichage d'un ticket de caisse
|
||||
\begin{todolist}
|
||||
\item Date de vente
|
||||
\item ID, nom, quantité, prix des produits achetés
|
||||
\item Prix total
|
||||
\item Un bouton pour valider
|
||||
\end{todolist}
|
||||
\item Interface d'export des statistiques (stock le montant total de vente par jour)
|
||||
\end{todolist}
|
||||
\end{todolist}
|
||||
|
||||
Avec à savoir :
|
||||
\begin{todolist}
|
||||
\item Ergonomie \texttt{/2}
|
||||
\item[\fait] Utilisateurs stockés dans la base de donnée \texttt{/2}
|
||||
\begin{todolist}
|
||||
\item[\fait] Possibilité de recréer la base de donnée automatiquement si elle n'existe plus
|
||||
\end{todolist}
|
||||
\item Ajout d'autres fonctionnalités \texttt{/1}
|
||||
\begin{todolist}
|
||||
\item Heure de connexion stricte pour les caissiers
|
||||
\item Meilleur caissier (avec le plus de ventes sur la journée/semaine précédente par exemple)
|
||||
\item Exporter le ticket de caisse en format image
|
||||
\end{todolist}
|
||||
\item[\fait] Lisibilité du code
|
||||
\begin{todolist}
|
||||
\item[\fait] Toutes les fonctions sont nommés et typés \texttt{(j'utilises Python 3.9.7)}
|
||||
\end{todolist}
|
||||
\end{todolist}
|
||||
|
||||
|
||||
\clearpage
|
||||
\section{Code}
|
||||
\subsection[\texttt{main.py}]{\texttt{main.py}, fichier principale}
|
||||
\begin{lstinputlisting}[language=iPython]{../main.py}\end{lstinputlisting}
|
||||
|
||||
\subsection[\texttt{db.py}]{\texttt{db.py}, gère la communication avec la base de donnée en sa globalité}
|
||||
\begin{lstinputlisting}[language=iPython]{../db.py}\end{lstinputlisting}
|
||||
|
||||
\subsection[\texttt{users.py}]{\texttt{users.py}, implante la partie pour les utilisateurs}
|
||||
\begin{lstinputlisting}[language=iPython]{../users.py}\end{lstinputlisting}
|
||||
|
||||
\end{document}
|
Reference in a new issue