Semaine 4, jour 5

This commit is contained in:
gauvainboiche
2026-01-16 17:13:01 +01:00
parent 54bb4d7628
commit 3f609ad139
38 changed files with 556 additions and 10 deletions

View File

@@ -1,5 +1,9 @@
from typing import TYPE_CHECKING
from PyQt6.QtCore import QObject, pyqtSignal from PyQt6.QtCore import QObject, pyqtSignal
if TYPE_CHECKING:
from gui.ui_library import Ui_Library
class SignalManagement(QObject): class SignalManagement(QObject):
change_list_signal = pyqtSignal() change_list_signal = pyqtSignal()

View File

@@ -1,8 +1,11 @@
from typing import TYPE_CHECKING
from logic import actions from logic import actions
from gui.ui_library import
if TYPE_CHECKING:
from gui.ui_library import Ui_Library
class Ui_Initialization: class Ui_Initialization:
def __init__(self, ui): def __init__(self, ui: Ui_Library):
self.ui = ui self.ui = ui
def connect_button(self): def connect_button(self):

View File

@@ -1,7 +1,9 @@
from Semaine_04.Bibliotheque.gui.signal_mgt import SignalManagement
from logic import actions from logic import actions
from gui.signal_mgt import SignalManagement
from gui.ui_init import Ui_Initialization from gui.ui_init import Ui_Initialization
from gui.ui_base import Ui_MainWindow from gui.ui_base import Ui_MainWindow
from PyQt6.QtWidgets import QMessageBox from PyQt6.QtWidgets import QMessageBox
from PyQt6.QtGui import QStandardItemModel, QStandardItem from PyQt6.QtGui import QStandardItemModel, QStandardItem

View File

@@ -0,0 +1 @@
3.12

View File

View File

@@ -0,0 +1,33 @@
class Fraction:
def __init__(self, numerateur, denominateur):
if denominateur == 0:
raise ValueError("Le denominateur ne peut etre nul")
if not isinstance(denominateur, int) or not isinstance(numerateur, int):
raise TypeError("Le numerateur/denominateur doit etre un entier")
self.numerateur = numerateur
self.denominateur = denominateur
@property
def quotient(self):
return self.numerateur / self.denominateur
print("Debut programme")
try:
tiers = Fraction(1, '0')
print(tiers.quotient)
except (ValueError, TypeError) as msg :
print(msg)
liste = [1,2,3,4]
dico = {'nom': "John"}
try:
print(dico['prenom'])
print(liste[7])
except LookupError as msg:
if isinstance(msg, KeyError):
print("La cle n'existe pas")
else:
print(msg)
print("Fin du programme")

31
Semaine_04/Divers/main.py Normal file
View File

@@ -0,0 +1,31 @@
from typing import TypedDict
def addition(*args): # args => tuple (2,3,4,5,6,6,6,7,7,8,9)
return sum(args)
print(addition(2,3,4,5))
livres = [
{"titre": "1984", "auteur": "Orwell"},
{"titre": "1983", "auteur": "Orwella"},
{"titre": "1985", "auteur": "Orwell"}
]
def display_infos(**kwargs): # kwargs => dict {"Titre": "Scandale", "Auteur": "Marlène Schiappa"}
resultats = []
for livre in livres:
if "auteur" in kwargs and kwargs["auteur"].lower() in livre["auteur"]:
resultats.append(livre)
if "titre" in kwargs and kwargs["titre"].lower() in livre["titre"]:
resultats.append(livre)
return resultats
infos: dict[str | int, str | int] = {"age": 23, "nom": "Albatar", "is_admin" : False}
class Criteres(TypedDict):
auteur: NotRequired[str]
titre: NotRequired[str]
print(CONSTANTES["db_name"])

View File

@@ -0,0 +1,42 @@
from datetime import date, time, datetime, timedelta
import pytz
date_2026 = date(2026, 1, 10)
print(date_2026)
today = date.today()
print(today)
hour = time()
print(hour)
hour = time(12, 34, 23)
print(hour)
hour_now = datetime.now().time()
print(hour_now)
day_now = datetime.now().date()
print(day_now)
timezone_paris = pytz.timezone("Europe/Paris")
timezone_moscou = pytz.timezone("Europe/Moscow")
timezone_pyongyang = pytz.timezone("Asia/Pyongyang")
heure_actuelle_paris = datetime.now(tz= timezone_paris)
heure_actuelle_moscou = datetime.now(tz= timezone_moscou)
heure_actuelle_pyongyang = datetime.now(tz= timezone_pyongyang)
print(heure_actuelle_paris)
print(heure_actuelle_moscou)
print(heure_actuelle_pyongyang)
date_15_jours = date.today() + timedelta(days= 15)
print(date_15_jours)
debut_voyage = datetime(2026, 1, 16, 12, 7, 18, tzinfo= timezone_paris)
fin_voyage = datetime(2026, 12, 25, 13, 56, 23, tzinfo= timezone_pyongyang)
print(debut_voyage - fin_voyage)
detail_voyage = debut_voyage - fin_voyage
print(detail_voyage.days)
print(detail_voyage.seconds)

View File

@@ -0,0 +1,9 @@
[project]
name = "divers"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"pytz>=2025.2",
]

23
Semaine_04/Divers/uv.lock generated Normal file
View File

@@ -0,0 +1,23 @@
version = 1
revision = 3
requires-python = ">=3.12"
[[package]]
name = "divers"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "pytz" },
]
[package.metadata]
requires-dist = [{ name = "pytz", specifier = ">=2025.2" }]
[[package]]
name = "pytz"
version = "2025.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f8/bf/abbd3cdfb8fbc7fb3d4d38d320f2441b1e7cbe29be4f23797b4a2b5d8aac/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", size = 320884, upload-time = "2025-03-25T02:25:00.538Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" },
]

View File

@@ -0,0 +1,6 @@
from math import pi
class Point:
def __init__(self, x: float, y: float):
self.x = x
self.y = y

View File

@@ -1,10 +1,6 @@
# Composition: traduit une relation "A UN" "POSSED UN" "DEPEND DE" # Composition: traduit une relation "A UN" "POSSED UN" "DEPEND DE"
from math import pi from math import pi
from composition import Point
class Point:
def __init__(self, x: float, y: float):
self.x = x
self.y = y
class Forme: # Abstraction class Forme: # Abstraction
def __init__(self, centre: Point): def __init__(self, centre: Point):
@@ -16,14 +12,16 @@ class Forme: # Abstraction
def perimetre(self): def perimetre(self):
raise NotImplementedError("Attention perimetre doit etre redefini") raise NotImplementedError("Attention perimetre doit etre redefini")
class Cercle(Forme): class Cercle:
def __init__(self, centre: Point, rayon: float): def __init__(self, centre: Point, rayon: float):
super().__init__(centre) self.centre = centre
self.rayon = rayon self.rayon = rayon
@property
def aire(self): def aire(self):
return pi * self.rayon ** 2 return pi * self.rayon ** 2
@property
def perimetre(self): def perimetre(self):
return 2 * pi * self.rayon return 2 * pi * self.rayon

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,28 @@
def persistance(num: int):
"""
A partir d'un entier positif, renvoie la persistance multiplicative,
à savoir le nombre de fois qu'on peut multiplier les chiffres de l'entier
entre eux jusqu'à un résultat d'un seul chiffre.
Exemples :
4 -> 0
39 -> 3 (3*9=27, 2*7=14, 1*4=4)
"""
if num < 0:
return "Merci d'utiliser un entier positif."
steps = 0
start = num
while len(str(num)) > 1:
base = 1
for n in str(num):
base *= int(n)
steps += 1
num = base
if steps == 0:
return f"Partant de {start}, pas besoin de multiplication."
return f"Partant de {start}, la persistance multiplicative est de {steps} étapes."

View File

@@ -0,0 +1,22 @@
def numeral_square(num: int):
"""
A partir d'un entier positif, renvoie la racine numérique,
à savoir la somme récursive de tous les chiffres d'un nombre.
Exemples :
16 -> 1+6=7
1567 -> 1+5+6+7=19, 1+9=10, 1+0=1
"""
if num < 0:
return "Merci d'utiliser un entier positif."
start = num
while len(str(num)) > 1:
base = 0
for n in str(num):
base += int(n)
num = base
return f"La racine numérique de {start} donne {base}."

View File

@@ -0,0 +1,18 @@
def gen_pyramid(num: int) -> list[str]:
"""
A partir d'un entier, renvoie sous forme de tableau une
pyramide composée d'autant d'étages avec le caractère *
"""
if num == 0:
return ["Merci d'utiliser un entier non nul."]
if num < 0:
num = +abs(num)
pyramid = []
for n in range(num):
white_spaces = ' ' * (num - n - 1)
bloc_spaces = '*' * (2 * n + 1)
pyramid.append(f"{white_spaces}{bloc_spaces}{white_spaces}")
return pyramid

View File

@@ -0,0 +1,45 @@
from datetime import date, time, datetime, timedelta
from pprint import pprint
from exo_01 import persistance
from exo_02 import numeral_square
from exo_03 import gen_pyramid
from prog_or_obj import Service,\
ServeurPhysique,\
ServeurVirtuel,\
Technicien,\
Maintenance,\
Datacenter
# Exercice 1
print("\n----- Exercice [1] -----\n")
exo_1_test_list = [-7, 4, 39, 999]
for test in exo_1_test_list:
print(persistance(test))
# Exercice 2
print("\n----- Exercice [2] -----\n")
exo_2_test_list = [-7, 16, 942, 132189, 493193]
for test in exo_2_test_list:
print(numeral_square(test))
# Exercice 3
print("\n----- Exercice [3] -----\n")
exo_3_test_list = [-7, 0, 6, 12]
for test in exo_3_test_list:
pprint(gen_pyramid(test), width= 30)
# Exercice de Programmation Orientée Objet - Centre de données
today = date.today()
two_days_ago = date.today() - timedelta(days= 2)
five_days_ago = date.today() - timedelta(days= 5)
service_01 = Service("HTTP", 80, "TCP", True)
service_02 = Service("HTTPS", "443", "TCP", True)
service_03 = Service("PostGresql", 5432, "TCP", False)
service_04 = Service("Counter-Strike LAN", 36729, "UDP", False)
server_physical_01 = ServeurPhysique("Thorium", "10.10.19.94", "Debian 13", today, "HP version 4.2", 45, True)
server_physical_02 = ServeurPhysique("Iridium", "10.10.18.94", "Arch Linux 4", two_days_ago, "HP version 4.2", 37, True)
server_physical_03 = ServeurPhysique("Polonium", "10.10.17.94", "Apple Server mdr", five_days_ago, "HP version 3.3", 445, False)

View File

@@ -0,0 +1,255 @@
from datetime import date
import json
class Service:
"""
Application déployée sur un serveur.
"""
def __init__(self, name: str, port: str | int, protocol: str, is_critical: bool):
self.name = name
self.port = int(port)
self.protocol = protocol
self.is_critical = is_critical
def __eq__(self, other: "Service"):
return self.name == other.name and self.port == other.port
def serialized_services(self):
"""Converti la classe \"Services\" en dictionnaire JSONable"""
return {
"Name": self.name,
"Port": self.port,
"Protocol": self.protocol,
"Is_Critical": self.is_critical,
}
@classmethod
def deserialized_services(cls, dictionnary):
"""Lis un JSON pour le retranscrire en classe \"Services\""""
return cls(
name= dictionnary["Name"],
port= dictionnary["Port"],
protocol= dictionnary["Protocol"],
is_critical= dictionnary["Is_Critical"],
)
class Serveur:
"""
Serveur, classe maîtresse. NE PAS UTILISER DIRECTEMENT.
Préférez les classes héritées :
- ServeurPhysique
- ServeurVirtuel
"""
def __init__(self, name: str, ip_address: str, os_name: str, commission_date: date):
self.name = name
self.ip_address = ip_address
self.os_name = os_name
self.commission_date = commission_date
self.services = self.load_services()
def __str__(self) -> str:
return f"\
[Serveur] > {self.name}\n\
[Addresse IP] > {self.ip_address}\n\
[Système d'Exploitation] > {self.os_name}\n\
[Date de mise en prod] > {self.commission_date}"
def __len__(self) -> int:
return len(self.services)
def list_services(self):
return self.services
def add_service(self, service: Service):
"""Ajout d'un service à la liste des services disponibles"""
if service in self.services:
return f"Le service [{service.name.capitalize()}] est déjà présent."
self.services.append(service)
self.save_services()
return f"{service.name.capitalize()} a été ajouté."
def remove_service(self, service_str: str):
"""Retire un service de la liste des services disponibles"""
for service in self.services:
if service.name.lower() == service_str.lower()\
or str(service.port) == service_str.lower()\
or service.protocol.lower() == service_str.lower():
self.services.remove(service)
self.save_services()
return f"{service.name.capitalize} a été retiré."
return f"{service.name.capitalize()} n'est pas dans la liste."
def serialized_servers(self):
"""Converti la classe \"Services\" en dictionnaire JSONable"""
return {
"Name": self.name,
"IP_Address": self.ip_address,
"OS_Name": self.os_name,
"Commission_Date": self.commission_date,
}
@classmethod
def deserialized_servers(cls, dictionnary):
"""Lis un JSON pour le retranscrire en classe \"Services\""""
return cls(
name= dictionnary["Name"],
ip_address= dictionnary["IP_Address"],
os_name= dictionnary["OS_Name"],
commission_date= dictionnary["Commission_Date"],
)
def save_services(self):
"""
Inscris dans un fichier JSON le contenu des services disponibles
"""
services_dict = [services.serialized_services() for services in self.services]
with open("services.json", "w", encoding= "utf-8") as json_file:
json.dump(services_dict, json_file, indent= 4)
def load_services(self) -> list[Service]:
"""
Récupère le contenu d'un fichier JSON contenant les services
"""
with open("services.json", encoding= "utf-8") as json_file:
return json.load(json_file, object_hook= Service.deserialized_services)
class ServeurPhysique(Serveur):
def __init__(self, name: str, ip_address: str, os_name: str, commission_date: date, rack: str, electric_cons: int, warranty: bool):
super().__init__(name, ip_address, os_name, commission_date)
self.rack = rack
self.electric_cons = electric_cons
warranty_bools = ("Non", "Oui")
self.warranty = warranty_bools[warranty]
def __str__(self) -> str:
return f"\
{super().__str__()}\n\
[Châssis] > {self.rack}\n\
[Consommation en kWh] > {self.electric_cons}\n\
[Sous garantie] > {self.warranty}"
def __len__(self) -> int:
return super().__len__()
class ServeurVirtuel(Serveur):
def __init__(self, name: str, ip_address: str, os_name: str, commission_date: date, hypervisor: str, vcpus: int, giga_ram: float):
super().__init__(name, ip_address, os_name, commission_date)
self.hypervisor = hypervisor
self.vcpus = vcpus
self.giga_ram = giga_ram
def __str__(self) -> str:
return f"\
{super().__str__()}\n\
[Hyperviseur] > {self.hypervisor}\n\
[Coeurs virtuels] > {self.vcpus}\n\
[Mémoire vive (Go)] > {self.giga_ram}"
def __len__(self) -> int:
return super().__len__()
class Maintenance:
def __init__(self, id: int, commission_date: date, type: str, affected_technician: "Technicien", associated_server: "ServeurPhysique | ServeurVirtuel"):
self.id = id
self.commission_date = commission_date
self.type = type
self.affected_technician = affected_technician
self.associated_server = associated_server
def __str__(self) -> str:
return f"\
[ID] > {self.id}\n\
[Serveur associé] > {self.associated_server}\n\
[Date de mise en prod] > {self.commission_date}\n\
[Type de maintenance] > {self.type}\n\
[Technicien affecté] > {self.affected_technician}"
# J'ai le sentiment que ce n'est PAS ce qui est demandé. Mais il est 16h25 et je n'ai plus d'idée sur comment le faire
def link_to_server(self, server: ServeurPhysique | ServeurVirtuel):
return f"La maintenance est liée au serveur {server.name.upper()}, addresse IP {server.ip_address}."
def serialized_maintenances(self):
"""Converti la classe \"Maintenance\" en dictionnaire JSONable"""
return {
"ID": self.id,
"Associated_Server": self.associated_server,
"Commission_Date": self.commission_date,
"Type": self.type,
"Affected_Technician": self.affected_technician,
}
@classmethod
def deserialized_maintenances(cls, dictionnary):
"""Lis un JSON pour le retranscrire en classe \"Maintenance\""""
return cls(
id= dictionnary["ID"],
associated_server= dictionnary["Associated_Server"],
commission_date= dictionnary["Commission_Date"],
type= dictionnary["Type"],
affected_technician= dictionnary["Affected_Technician"],
)
class Technicien:
def __init__(self, fullname: str, speciality: str, id: int):
self.name = fullname
self.speciality = speciality
self.id = id
self.maintenances = self.load_maintenances()
def list_affected_jobs(self):
return self.maintenances
def affect_maintenance(self):
pass
def save_maintenances(self):
"""
Inscris dans un fichier JSON le contenu des maintenances disponibles
"""
maintenances_dict = [maintenances.serialized_maintenances() for maintenances in self.maintenances]
with open("maintenances.json", "w", encoding= "utf-8") as json_file:
json.dump(maintenances_dict, json_file, indent= 4)
def load_maintenances(self) -> list[Maintenance]:
"""
Récupère le contenu d'un fichier JSON contenant les maintenances
"""
with open("maintenances.json", encoding= "utf-8") as json_file:
return json.load(json_file, object_hook= Maintenance.deserialized_maintenances)
class Datacenter:
def __init__(self, name: str, location: str, id: int):
self.name = name
self.location = location
self.id = id
self.servers = self.load_servers()
def list_servers(self):
return self.servers
def list_critical_services(self):
for server in self.servers:
server.list_services()
# Là j'ai cherché à récupérer un genre de 'if server.list_services().is_critical'
# pour avoir le "True/False" et renvoyer le résultat en cas de "True" mais j'ai craqué
def list_services_number(self):
services = 0
for server in self.servers:
services += len(server)
return services
def save_servers(self):
"""
Inscris dans un fichier JSON le contenu des serveurs disponibles
"""
servers_dict = [servers.serialized_servers() for servers in self.servers]
with open("servers.json", "w", encoding= "utf-8") as json_file:
json.dump(servers_dict, json_file, indent= 4)
def load_servers(self) -> list[Serveur]:
"""
Récupère le contenu d'un fichier JSON contenant les serveurs
"""
with open("servers.json", encoding= "utf-8") as json_file:
return json.load(json_file, object_hook= Serveur.deserialized_servers)

26
Semaine_04/Jour_05.md Normal file
View File

@@ -0,0 +1,26 @@
## TYPE_CHECKING
En cas d'import circulaire de dépendance, un conflit peut apparaitre :
```py
# dans main.py :
from classes.py import dependance_01
```
```py
# dans classes.py :
from main.py import dependance_02
```
La lecture des fichiers par Python peut conduire à une boucle où chacun fichier lit l'autre et bloque sur un import. On utilise alors dans la dépendance secondaire :
```py
# dans classes.py :
if TYPE_CHECKING:
from main.py import dependance_02
```
Pour sortir de la boucle.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.