feat: Semaine 9

This commit is contained in:
gauvainboiche
2026-05-15 16:24:56 +02:00
parent 3315cb2336
commit ce1f0e513a
108 changed files with 3150 additions and 0 deletions
View File
+24
View File
@@ -0,0 +1,24 @@
from dataclasses import dataclass
from typing import Callable
@dataclass
class User:
username: str
is_authenticated: bool = False
def authentication_required(fonction: Callable):
def internal_wrapper(user: User):
if not user.is_authenticated:
return PermissionError(f"L'utilisateur {user.username} n'est pas authentifié.")
return fonction(user)
return internal_wrapper
@authentication_required
def operation_sensible(user: User):
return f"Opération sensible faite par {user.username}."
alice = User("alice@courriel.fr", True)
bob = User("bob@courriel.fr")
print(operation_sensible(alice))
print(operation_sensible(bob))
+13
View File
@@ -0,0 +1,13 @@
from typing import Callable
class Decorateur:
def __init__(self, fonction: Callable):
self.fonction = fonction
def __call__(self, *args, **kwargs):
print(f"Appel de la fonction {self.fonction.__name__}")
return self.fonction(*args, **kwargs)
@Decorateur
def addition(a, b):
return a + b
@@ -0,0 +1,37 @@
from typing import Callable
import time
def decorateur(fonction: Callable):
def internal_wrapper(*args, **kwargs):
print(f"Appel de la fonction {fonction.__name__}")
resultat = fonction(*args, **kwargs)
print(f"Fin du décorateur")
return resultat
return internal_wrapper
def addition(a, b):
return a + b
def salutations(name):
return f"Bonjour {name}."
def multiplication(a, b, c):
return a * b * c
# Décorateur qui calcule le temps d'exécution de n'importe quelle fonction
def decorateur_temps(fonction: Callable):
def internal_wrapper(*args, **kwargs):
nonlocal time_total
time_start = time.time()
result = fonction(*args, **kwargs)
time_duration = time.time() - time_start
time_total += time_duration
print(f"Temps d'exécution : {time_duration} - Total : {time_total}")
return result
time_total = 0
return internal_wrapper
@@ -0,0 +1,62 @@
"""
Classe décoratrice qui calcule le temps d'exécution
de n'importe quelle fonction et qui l'enregistre
dans une DB SQLite
=> (fonction_name, execution_time, execution_date)
=> Date : YYYY-MM-DD HH:MM:SS
1. La DB existe ? Oui, Non
2. save()
"""
import sqlite3
from typing import Callable
from time import time, strftime, gmtime, perf_counter
class Decorateur:
def __init__(self, fonction: Callable):
self.fonction = fonction
self.connection = sqlite3.connect("functions.db")
def create_table(self):
cursor = self.connection.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS exec_stats(
function_name TEXT,
execution_time REAL,
execution_date TEXT
)
""")
self.connection.commit()
def __call__(self, *args, **kwargs):
print(f"Appel de la fonction {self.fonction.__name__}")
start_time = time.perf_counter()
resultat = self.fonction(*args, **kwargs)
end_time = time.perf_counter()
execution_time = end_time - start_time
execution_date = time.strftime("%Y-%m-%d %H:%M:%S")
self.save_to_db(
function_name= self.fonction.__name__,
execution_time= execution_time,
execution_date= execution_date
)
return resultat
def save_to_db(self, function_name, execution_time, execution_date):
cursor = self.connection.cursor()
cursor.execute("""
INSERT INTO exec_stats(function_name, execution_time, execution_date)
VALUES (?, ?, ?)
""", (function_name, execution_time, execution_date))
self.connection.commit()
@Decorateur
def test():
return f"Bah ouais quoi."
Binary file not shown.
@@ -0,0 +1,11 @@
from typing import Callable
def decorateur(fonction: Callable):
print(f"Appel de la fonction {fonction.__name__}")
return fonction # où il retourne le résultat de la fonction
def simple_fonction():
print("Hello tout le monde !")
fonction_decoree = decorateur(simple_fonction)
fonction_decoree()
+13
View File
@@ -0,0 +1,13 @@
import argparse
parser = argparse.ArgumentParser(description= "Outil de salutation")
parser.add_argument("nom", help= "Le nom de la personne à saluer")
parser.add_argument("--majuscule", action= "store_true", help= "Afficher le message de salutation en majuscules")
args = parser.parse_args()
message = f"Bonjour {args.nom}"
if args.majuscule:
message = message.upper()
print(message)
+63
View File
@@ -0,0 +1,63 @@
import argparse
import time
### Générer adresse IP
import random
import socket
import struct
def ip_address():
return socket.inet_ntoa(struct.pack('>I', random.randint(1, 0xffffffff)))
### Fin du bloc de l'addresse IP
parser = argparse.ArgumentParser(prog="NetInfo", description= "Outil réseau")
parser.add_argument("-v", "--verbose", action="store_true", help="Mode verbeux")
subparsers = parser.add_subparsers(dest="commande", help="Commande à exécuter")
# parent_parser = argparse.ArgumentParser(add_help=False)
# parent_parser.add_argument("-v", "--verbose", action="store_true", help="Mode verbeux")
scan_parser = subparsers.add_parser("scan", help="Scan d'un hôte")
scan_parser.add_argument("host", default="192.168.1.1", help="Adresse IP de l'hôte cible")
scan_parser.add_argument("-p", "--ports", default=[80], nargs= "+", type= int)
whois_parser = subparsers.add_parser("whois", help="Ping sur un hôte")
whois_parser.add_argument("domain", help="Domaine désiré pour les informations")
args = parser.parse_args()
def net_info(fonction):
def internal_wrapper(args):
if args.verbose:
print(f"[DEBUG] Lancement de la commande...")
start_time = time.perf_counter()
result = fonction(args)
print(f"[DEBUG] Commande terminée.")
print(f"[DEBUG] Commande exécutée en {time.perf_counter() - start_time} secondes.")
return result
return fonction(args)
return internal_wrapper
@net_info
def scan(args):
print(f"Scan de l'hôte: {args.host}")
results = []
for port in args.ports:
status = "ouvert" if port % 2 == 0 else "fermé"
results.append(f"Port {port}: {status}")
print(f"Port {port}: {status}")
return results
@net_info
def whois(args):
print(f"WHOIS pour {args.domain}")
print(f"\
IP : {ip_address()}\n\
Registrar : Exemple\n\
Expirattion : Bientôt\n\
")
if args.commande == "scan":
scan(args)
elif args.commande == "whois":
whois(args)
+11
View File
@@ -0,0 +1,11 @@
import argparse
parser = argparse.ArgumentParser(description= "Outil réseau")
subparsers = parser.add_subparsers(dest="commande", help="Commande à exécuter")
scan_parser = subparsers.add_parser("scan", help="Scan d'un hôte")
scan_parser.add_argument("--host")
scan_parser.add_argument("--port", nargs= "+", type= int)
ping_parser = subparsers.add_parser("ping", help="Ping sur un hôte")
ping_parser.add_argument()
+9
View File
@@ -0,0 +1,9 @@
[project]
name = "jour-01"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"typing>=3.10.0.0",
]
+27
View File
@@ -0,0 +1,27 @@
from dataclasses import dataclass, field
from typing import Callable
@dataclass
class User:
username: str
is_authenticated: bool = False
roles: list[str] = field(default_factory=lambda: ["user"])
def required_roles(roles: list[str]):
def wrapper(fonction: Callable):
def internal_wrapper(user: User):
if not any(role in user.roles for role in roles): # True => [False, False, True]
raise PermissionError(f"L'utilisateur {user.username} n'a pas le rôle requis.")
return fonction(user)
return internal_wrapper
return wrapper
@required_roles(["admin", "modo"])
def operation_sensible(user: User):
return f"Opération sensible faite par {user.username}"
alice = User("alice@courriel.fr", True, ["modo"])
bob = User("bob@courriel.fr", True)
print(operation_sensible(alice))
+19
View File
@@ -0,0 +1,19 @@
"""
uv run scanner.py --host 192.0.0.1 --port 80 -t 2.5
-h / --host : hôte en texte
-p / --port : port en int
-t / --timeout : timeout en secondes (float)
"""
import argparse
parser = argparse.ArgumentParser(prog="Bistro", description= "Connexion à un serveur distant")
parser.add_argument("--host", type= str, help= "Défini l'emplacement du serveur")
parser.add_argument("-p", "--ports", type= int, choices= [80, 443, 3000, 8000], nargs= "+", default= 80, help= "Défini le port visé sur le serveur")
parser.add_argument("-t", "--timeout", type= float, help= "Défini (optionnellement) une durée d'exécution maximum sans retour du serveur avant échec")
args = parser.parse_args()
for port in args.ports:
print(f"Scan de {args.host} sur le port {port} (timeout= {args.timeout})")
+23
View File
@@ -0,0 +1,23 @@
version = 1
revision = 3
requires-python = ">=3.12"
[[package]]
name = "jour-01"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "typing" },
]
[package.metadata]
requires-dist = [{ name = "typing", specifier = ">=3.10.0.0" }]
[[package]]
name = "typing"
version = "3.10.0.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/b0/1b/835d4431805939d2996f8772aca1d2313a57e8860fec0e48e8e7dfe3a477/typing-3.10.0.0.tar.gz", hash = "sha256:13b4ad211f54ddbf93e5901a9967b1e07720c1d1b78d596ac6a439641aa1b130", size = 78962, upload-time = "2021-05-01T18:03:58.186Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f2/5d/865e17349564eb1772688d8afc5e3081a5964c640d64d1d2880ebaed002d/typing-3.10.0.0-py3-none-any.whl", hash = "sha256:12fbdfbe7d6cca1a42e485229afcb0b0c8259258cfb919b8a5e2a5c953742f89", size = 26320, upload-time = "2021-05-01T18:03:56.398Z" },
]
+25
View File
@@ -0,0 +1,25 @@
import argparse
import time
def timer_command(fonction):
def internal_wrapper(args):
if args.verbose:
print("[DEBUG] Lancement de la commande...")
start_time = time.perf_counter()
result = fonction(args)
print(f"[DEBUG] Terminé en {time.perf_counter() - start_time}")
return result
return fonction(args)
return internal_wrapper
parser = argparse.ArgumentParser(description="Un scanneur")
parser.add_argument("-n", "--numbers", nargs= "+", type= int, help="Nombres à additioner")
parser.add_argument("-v", "--verbose", action="store_true", help="Mode verbeux")
@timer_command
def addition(args):
return sum(args.numbers)
args = parser.parse_args()
print(addition(args))