Semaine 7
This commit is contained in:
BIN
Semaine_07/Jour_01/Company_MySQL_001.mwb
Normal file
BIN
Semaine_07/Jour_01/Company_MySQL_001.mwb
Normal file
Binary file not shown.
BIN
Semaine_07/Jour_01/Company_MySQL_001.mwb.bak
Normal file
BIN
Semaine_07/Jour_01/Company_MySQL_001.mwb.bak
Normal file
Binary file not shown.
22
Semaine_07/Jour_01/docker-compose.yml
Normal file
22
Semaine_07/Jour_01/docker-compose.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:8.0
|
||||
container_name: mysql
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: rootpassword
|
||||
MYSQL_DATABASE: company
|
||||
MYSQL_USER: mysql_user
|
||||
MYSQL_PASSWORD: Azerty123
|
||||
command: --log_bin_trust_function_creators=1
|
||||
ports:
|
||||
- "3306:3306"
|
||||
volumes:
|
||||
- mysql_data:/var/lib/mysql
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
mysql_data:
|
||||
208
Semaine_07/Jour_02/SQL_scripts.sql
Normal file
208
Semaine_07/Jour_02/SQL_scripts.sql
Normal file
@@ -0,0 +1,208 @@
|
||||
USE company;
|
||||
|
||||
SELECT * FROM country;
|
||||
|
||||
SELECT first_name "Firstname", last_name "Lastname" from employee;
|
||||
|
||||
select distinct department_ID from employee;
|
||||
|
||||
select count(job_id) from employee;
|
||||
|
||||
select count(distinct job_id) from employee;
|
||||
|
||||
-- liste des employés embauchés avant le 01.01.1991
|
||||
select * from employee where hire_date < '1991-01-01';
|
||||
|
||||
-- FOnctions
|
||||
-- -- mettre en majuscule
|
||||
select upper(first_name) "Firstname" from employee;
|
||||
-- -- mettre les 3 premières lettres des nom et prénom des employés
|
||||
select substring(upper(first_name), 1, 3), substring(upper(last_name), 1, 3)
|
||||
from employee;
|
||||
-- -- prénom + nom + longueur totale du prénom+nom
|
||||
select first_name, last_name,
|
||||
char_length(first_name) + char_length(last_name) "Longueur totale"
|
||||
from employee;
|
||||
-- -- Qui gagne le plus dans l'entreprise
|
||||
select first_name, last_name, salary
|
||||
from employee order by salary desc limit 1;
|
||||
select first_name, last_name,
|
||||
salary >= (select max(salary) from employee)
|
||||
from employee order by salary desc;
|
||||
-- -- salaire min et max
|
||||
select min(salary), max(salary), avg(salary), sum(salary) from employee;
|
||||
-- -- les gens de l'IT qui gagnent moins de 5000
|
||||
select first_name, last_name, department_id, salary
|
||||
from employee where department_id = 60 and salary > 5000;
|
||||
-- -- les gens dans la vente (80) et le mercatique (20)
|
||||
select first_name, last_name, salary
|
||||
from employee where department_id in (20, 80);
|
||||
-- -- salaire entre 5000 et 10000
|
||||
select first_name, last_name, salary
|
||||
from employee where salary between 5000 and 10000;
|
||||
-- -- avec une commission
|
||||
select first_name, last_name, commission_pct
|
||||
from employee where commission_pct != 0;
|
||||
-- -- employés dont le nom de famille commance par "K"
|
||||
select first_name, last_name
|
||||
from employee where last_name like "K%";
|
||||
-- -- employés dont le prénom contient "an"
|
||||
select first_name, last_name
|
||||
from employee where first_name like "%an%";
|
||||
-- -- employés dont le prénom fait 4 lettres
|
||||
select first_name, last_name
|
||||
from employee where first_name like "____";
|
||||
-- -- REGEX : nom de famille commence par "S" ou "T"
|
||||
select first_name, last_name
|
||||
from employee where last_name regexp "^[ST]";
|
||||
-- -- le nombre de jour depuis l'embauche
|
||||
select first_name, last_name, hire_date,
|
||||
datediff(curdate(), hire_date) as nb_jours
|
||||
from employee order by nb_jours;
|
||||
|
||||
-- Exercice
|
||||
-- -- les commerciaux gagnant plus de 9000 triés par commission décroissante
|
||||
select first_name, last_name, salary, commission_pct
|
||||
from employee
|
||||
where department_id = 80 and salary > 9000 order by commission_pct desc;
|
||||
-- -- les postes dont le salaire est au moins le double du salaire minimum
|
||||
select first_name, last_name, salary
|
||||
from employee where salary > (select min(salary) from employee) * 2
|
||||
order by salary asc;
|
||||
-- -- les employés dont le prénom commence et fini par la même lettre
|
||||
select first_name, last_name
|
||||
from employee
|
||||
where left(first_name, 1) = right(first_name, 1);
|
||||
-- -- le top 5 des employés les mieux payés n'étant pas chefs
|
||||
select first_name, last_name, salary, job_id
|
||||
from employee
|
||||
where employee_id not in (select manager_id from employee)
|
||||
order by salary desc limit 10;
|
||||
|
||||
-- COURS
|
||||
-- -- Jointures
|
||||
-- -- -- https://cartman34.fr/informatique/sgbd/differences-entre-inner-left-right-et-outer-join-en-sql.html
|
||||
select first_name, last_name, department_name
|
||||
from employee e
|
||||
inner join department d
|
||||
on e.department_id = d.department_id;
|
||||
-- -- -- LEFT avec condition : les employés qui ne sont affectés à aucun départment
|
||||
select e.first_name, e.last_name, d.department_name
|
||||
from employee e
|
||||
left join department d
|
||||
on e.department_id = d.department_id
|
||||
where d.department_id is null;
|
||||
-- -- -- RIGHT avec condition : la liste des départments ne contenant aucun employé
|
||||
select e.first_name, e.last_name, d.department_name
|
||||
from employee e
|
||||
right join department d
|
||||
on e.department_id = d.department_id
|
||||
where e.department_id is null;
|
||||
-- -- -- FULL OUTER JOIN
|
||||
select e.first_name, e.last_name, d.department_name
|
||||
from employee e
|
||||
left join department d
|
||||
on e.department_id = d.department_id
|
||||
union
|
||||
select e.first_name, e.last_name, d.department_name
|
||||
from employee e
|
||||
right join department d
|
||||
on e.department_id = d.department_id;
|
||||
-- -- -- NATURAL JOIN -> INNER JOIN
|
||||
select location_id, street_address, city, country_name
|
||||
from location
|
||||
natural join country;
|
||||
-- -- -- EXEMPLE : nous voulons la liste des employés travaillant à Seattle
|
||||
-- -- -- On doit faire EMPLOYEE -> DEPARTMENT -> LOCATION
|
||||
select e.first_name, e.last_name, l.city
|
||||
from employee e
|
||||
join department d
|
||||
on e.department_id = d.department_id
|
||||
join location l
|
||||
on d.location_id = l.location_id
|
||||
where lower(l.city) = "seattle";
|
||||
|
||||
-- -- -- EXEMPLE : nous voulons la liste des employés travaillant aux USA
|
||||
-- -- -- On doit faire EMPLOYEE -> DEPARTMENT -> LOCATION -> COUNTRY
|
||||
select e.first_name, e.last_name, l.city
|
||||
from employee e
|
||||
join department d
|
||||
on e.department_id = d.department_id
|
||||
join location l
|
||||
on d.location_id = l.location_id
|
||||
join country c
|
||||
on l.country_id = c.country_id
|
||||
where lower(c.country_name) like "%united%states%";
|
||||
-- -- -- Prénom et nom de l'employé suivi du prénom de son chef
|
||||
select e.first_name, e.last_name, m.first_name "Prénom chef", m.last_name "Nom chef"
|
||||
from employee e
|
||||
left join employee m
|
||||
on m.employee_id = e.manager_id;
|
||||
-- -- -- Nombre de gens dans chaque poste
|
||||
select j.job_title, count(*)
|
||||
from employee e
|
||||
join job j
|
||||
on e.job_id = j.job_id
|
||||
group by j.job_id;
|
||||
-- -- -- la liste des chefs et le nombre d'employés sous leurs ordres
|
||||
-- -- -- et dont le nombre d'employés est d'au moins 5
|
||||
select m.first_name "Prénom chef",
|
||||
m.last_name "Nom chef",
|
||||
count(e.employee_id) as count
|
||||
from employee e
|
||||
join employee m
|
||||
on m.employee_id = e.manager_id
|
||||
group by e.manager_id
|
||||
having count >= 5
|
||||
order by count desc;
|
||||
|
||||
-- -- Sous-requêtes
|
||||
-- -- -- Tous les employés gagnant plus que l'employé nommé "Bull"
|
||||
select first_name, last_name, salary
|
||||
from employee
|
||||
where salary >
|
||||
(select salary from employee where lower(last_name) = "Bull");
|
||||
-- -- -- Tous les employés ayant pour chef un prénommé "Payam"
|
||||
-- -- -- JOINTURE
|
||||
select e.first_name, e.last_name, m.first_name "Prénom chef", m.last_name "Nom chef"
|
||||
from employee e
|
||||
left join employee m
|
||||
on m.employee_id = e.manager_id
|
||||
where lower(m.first_name) = "payam";
|
||||
-- -- -- Tous les employés ayant pour chef un prénommé "Payam"
|
||||
-- -- -- SOUS-REQUETE
|
||||
select first_name, last_name
|
||||
from employee
|
||||
where manager_id =
|
||||
(select employee_id from employee where lower(first_name) = "payam");
|
||||
-- -- -- Les employés dont le salaire est compris entre le plus petit et 3000
|
||||
select first_name, last_name, salary
|
||||
from employee
|
||||
where salary
|
||||
between (select min(salary) from employee) and 3000
|
||||
order by salary asc;
|
||||
-- -- -- les employés dont le chef bosse aux USA
|
||||
select first_name, last_name
|
||||
from employee
|
||||
where manager_id in
|
||||
(
|
||||
select employee_id from employee where department_id in
|
||||
(
|
||||
select department_id from department where location_id in
|
||||
(
|
||||
select location_id from location where lower(country_id) = "us"
|
||||
)
|
||||
)
|
||||
);
|
||||
-- -- Création de "Vues"
|
||||
-- -- Grosso modo, c'est une requête pré-enregistrée
|
||||
create view `seattle_employees` as
|
||||
select e.first_name, e.last_name, e.salary, d.department_name, l.city
|
||||
from employee e
|
||||
join department d
|
||||
on e.department_id = d.department_id
|
||||
join location l
|
||||
on d.location_id = l.location_id
|
||||
where lower(l.city) = "seattle";
|
||||
|
||||
select * from seattle_employees;
|
||||
38
Semaine_07/Jour_02/SQL_transactions.sql
Normal file
38
Semaine_07/Jour_02/SQL_transactions.sql
Normal file
@@ -0,0 +1,38 @@
|
||||
-- Création de "Transactions"
|
||||
-- -- ACID : Atomique, Cohérence, Isolation, Durabilité
|
||||
-- -- minimum deux requêtes, et si l'une échoue,
|
||||
-- -- la BDD revient à l'état initial. Toutes passent sinon aucune
|
||||
|
||||
-- -- -- On veut transférer un employé vers un autre département
|
||||
-- -- -- avec un nouveau job, et archiver son poste dans job_history
|
||||
|
||||
START transaction;
|
||||
|
||||
-- -- -- 1. Archivage
|
||||
|
||||
insert into job_history (
|
||||
employee_id,
|
||||
start_date,
|
||||
end_date,
|
||||
job_id,
|
||||
department_id
|
||||
)
|
||||
select
|
||||
employee_id,
|
||||
e.hire_date,
|
||||
current_date,
|
||||
e.job_id,
|
||||
e.department_id
|
||||
from employee e
|
||||
where e.employee_id = 101;
|
||||
|
||||
-- -- -- 2. Mettre à jour le job et département
|
||||
|
||||
update employee
|
||||
set
|
||||
job_id = "SA_REP",
|
||||
department_id = 80,
|
||||
hire_date = current_date
|
||||
where employee_id = 101;
|
||||
|
||||
COMMIT;
|
||||
241
Semaine_07/Jour_02/hr_data.sql
Normal file
241
Semaine_07/Jour_02/hr_data.sql
Normal file
@@ -0,0 +1,241 @@
|
||||
use company;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- vide les tables et remet les compteurs a zero
|
||||
truncate table job_history;
|
||||
truncate table employee;
|
||||
truncate table job;
|
||||
truncate table department;
|
||||
truncate table location;
|
||||
truncate table country;
|
||||
truncate table region;
|
||||
|
||||
-- drop et truncate
|
||||
|
||||
INSERT INTO region (REGION_ID, REGION_NAME) VALUES
|
||||
('1', 'Europe'),
|
||||
('2', 'America'),
|
||||
('3', 'Asia'),
|
||||
('4', 'Middle East and Africa');
|
||||
|
||||
INSERT INTO country (COUNTRY_ID, COUNTRY_NAME, REGION_ID) VALUES
|
||||
('AR', 'Argentina', '2'),
|
||||
('AU', 'Australia', '3'),
|
||||
('BE', 'Belgium', '1'),
|
||||
('BR', 'Brazil', '2'),
|
||||
('CA', 'Canada', '2'),
|
||||
('CH', 'Switzerland', '1'),
|
||||
('CN', 'China', '3'),
|
||||
('DE', 'Germany', '1'),
|
||||
('DK', 'Denmark', '1'),
|
||||
('EG', 'Egypt', '4'),
|
||||
('FR', 'France', '1'),
|
||||
('HK', 'HongKong', '3'),
|
||||
('IL', 'Israel', '4'),
|
||||
('IN', 'India', '3'),
|
||||
('IT', 'Italy', '1'),
|
||||
('JP', 'Japan', '3'),
|
||||
('KW', 'Kuwait', '4'),
|
||||
('MX', 'Mexico', '2'),
|
||||
('NG', 'Nigeria', '4'),
|
||||
('NL', 'Netherlands', '1'),
|
||||
('SG', 'Singapore', '3'),
|
||||
('UK', 'United Kingdom', '1'),
|
||||
('US', 'United States of America', '2'),
|
||||
('ZM', 'Zambia', '4'),
|
||||
('ZW', 'Zimbabwe', '4');
|
||||
|
||||
INSERT INTO location (LOCATION_ID, STREET_ADDRESS, POSTAL_CODE, CITY, STATE_PROVINCE, COUNTRY_ID) VALUES
|
||||
('1000', '1297 Via Cola di Rie', '989', 'Roma', '', 'IT'),
|
||||
('1100', '93091 Calle della Testa', '10934', 'Venice', '', 'IT'),
|
||||
('1200', '2017 Shinjuku-ku', '1689', 'Tokyo', 'Tokyo Prefecture', 'JP'),
|
||||
('1300', '9450 Kamiya-cho', '6823', 'Hiroshima', '', 'JP'),
|
||||
('1400', '2014 Jabberwocky Rd', '26192', 'Southlake', 'Texas', 'US'),
|
||||
('1500', '2011 Interiors Blvd', '99236', 'South San Francisco', 'California', 'US'),
|
||||
('1600', '2007 Zagora St', '50090', 'South Brunswick', 'New Jersey', 'US'),
|
||||
('1700', '2004 Charade Rd', '98199', 'Seattle', 'Washington', 'US'),
|
||||
('1800', '147 Spadina Ave', 'M5V 2L7', 'Toronto', 'Ontario', 'CA'),
|
||||
('1900', '6092 Boxwood St', 'YSW 9T2', 'Whitehorse', 'Yukon', 'CA'),
|
||||
('2000', '40-5-12 Laogianggen', '190518', 'Beijing', '', 'CN'),
|
||||
('2100', '1298 Vileparle (E)', '490231', 'Bombay', 'Maharashtra', 'IN'),
|
||||
('2200', '12-98 Victoria Street', '2901', 'Sydney', 'New South Wales', 'AU'),
|
||||
('2300', '198 Clementi North', '540198', 'Singapore', '', 'SG'),
|
||||
('2400', '8204 Arthur St', '', 'London', '', 'UK'),
|
||||
('2500', '"Magdalen Centre', ' The Oxford ', 'OX9 9ZB', 'Oxford', 'UK'),
|
||||
('2600', '9702 Chester Road', '9629850293', 'Stretford', 'Manchester', 'UK'),
|
||||
('2700', 'Schwanthalerstr. 7031', '80925', 'Munich', 'Bavaria', 'DE'),
|
||||
('2800', 'Rua Frei Caneca 1360', '01307-002', 'Sao Paulo', 'Sao Paulo', 'BR'),
|
||||
('2900', '20 Rue des Corps-Saints', '1730', 'Geneva', 'Geneve', 'CH'),
|
||||
('3000', 'Murtenstrasse 921', '3095', 'Bern', 'BE', 'CH'),
|
||||
('3100', 'Pieter Breughelstraat 837', '3029SK', 'Utrecht', 'Utrecht', 'NL'),
|
||||
('3200', 'Mariano Escobedo 9991', '11932', 'Mexico City', '"Distrito Federal', 'MX');
|
||||
|
||||
INSERT INTO department (DEPARTMENT_ID , DEPARTMENT_NAME , MANAGER_ID, LOCATION_ID) VALUES
|
||||
('10', 'Administration', '200', '1700'),
|
||||
('20', 'Marketing', '201', '1800'),
|
||||
('30', 'Purchasing', '114', '1700'),
|
||||
('40', 'Human Resources', '203', '2400'),
|
||||
('50', 'Shipping', '121', '1500'),
|
||||
('60', 'IT', '103', '1400'),
|
||||
('70', 'Public Relations', '204', '2700'),
|
||||
('80', 'Sales', '145', '2500'),
|
||||
('90', 'Executive', '100', '1700'),
|
||||
('100', 'Finance', '108', '1700'),
|
||||
('110', 'Accounting', '205', '1700'),
|
||||
('120', 'Treasury', '0', '1700'),
|
||||
('130', 'Corporate Tax', '0', '1700'),
|
||||
('140', 'Control And Credit', '0', '1700'),
|
||||
('150', 'Shareholder Services', '0', '1700'),
|
||||
('160', 'Benefits', '0', '1700'),
|
||||
('170', 'Manufacturing', '0', '1700'),
|
||||
('180', 'Construction', '0', '1700'),
|
||||
('190', 'Contracting', '0', '1700'),
|
||||
('200', 'Operations', '0', '1700'),
|
||||
('210', 'IT Support', '0', '1700'),
|
||||
('220', 'NOC', '0', '1700'),
|
||||
('230', 'IT Helpdesk', '0', '1700'),
|
||||
('240', 'Government Sales', '0', '1700'),
|
||||
('250', 'Retail Sales', '0', '1700'),
|
||||
('260', 'Recruiting', '0', '1700'),
|
||||
('270', 'Payroll', '0', '1700');
|
||||
|
||||
INSERT INTO job (JOB_ID, JOB_TITLE, MIN_SALARY, MAX_SALARY) VALUES
|
||||
('AD_PRES', 'President', '20000', '40000'),
|
||||
('AD_VP', 'Administration Vice President', '15000', '30000'),
|
||||
('AD_ASST', 'Administration Assistant', '3000', '6000'),
|
||||
('FI_MGR', 'Finance Manager', '8200', '16000'),
|
||||
('FI_ACCOUNT', 'Accountant', '4200', '9000'),
|
||||
('AC_MGR', 'Accounting Manager', '8200', '16000'),
|
||||
('AC_ACCOUNT', 'Public Accountant', '4200', '9000'),
|
||||
('SA_MAN', 'Sales Manager', '10000', '20000'),
|
||||
('SA_REP', 'Sales Representative', '6000', '12000'),
|
||||
('PU_MAN', 'Purchasing Manager', '8000', '15000'),
|
||||
('PU_CLERK', 'Purchasing Clerk', '2500', '5500'),
|
||||
('ST_MAN', 'Stock Manager', '5500', '8500'),
|
||||
('ST_CLERK', 'Stock Clerk', '2000', '5000'),
|
||||
('SH_CLERK', 'Shipping Clerk', '2500', '5500'),
|
||||
('IT_PROG', 'Programmer', '4000', '10000'),
|
||||
('MK_MAN', 'Marketing Manager', '9000', '15000'),
|
||||
('MK_REP', 'Marketing Representative', '4000', '9000'),
|
||||
('HR_REP', 'Human Resources Representative', '4000', '9000'),
|
||||
('PR_REP', 'Public Relations Representative', '4500', '10500');
|
||||
|
||||
INSERT INTO employee (EMPLOYEE_ID, FIRST_NAME, LAST_NAME, EMAIL, PHONE_NUMBER, HIRE_DATE, JOB_ID, SALARY, COMMISSION_PCT, MANAGER_ID, DEPARTMENT_ID) VALUES
|
||||
('100', 'Steven', 'King', 'SKING', '515.123.4567', '1987-06-20', 'AD_PRES', '24000.00', '0.00', '0', '90'),
|
||||
('101', 'Neena', 'Kochhar', 'NKOCHHAR', '515.123.4568','1987-06-20' , 'AD_VP', '17000.00', '0.00', '100', '90'),
|
||||
('102', 'Lex', 'De Haan', 'LDEHAAN', '515.123.4569', '1987-06-20', 'AD_VP', '17000.00', '0.00', '100', '90'),
|
||||
('103', 'Alexander', 'Hunold', 'AHUNOLD', '590.423.4567', '1987-06-20', 'IT_PROG', '9000.00', '0.00', '102', '60'),
|
||||
('104', 'Bruce', 'Ernst', 'BERNST', '590.423.4568', '1987-06-21', 'IT_PROG', '6000.00', '0.00', '103', '60'),
|
||||
('105', 'David', 'Austin', 'DAUSTIN', '590.423.4569', '1987-06-22', 'IT_PROG', '4800.00', '0.00', '103', '60'),
|
||||
('106', 'Valli', 'Pataballa', 'VPATABAL', '590.423.4560', '1987-06-23', 'IT_PROG', '4800.00', '0.00', '103', '60'),
|
||||
('107', 'Diana', 'Lorentz', 'DLORENTZ', '590.423.5567', '1987-06-24', 'IT_PROG', '4200.00', '0.00', '103', '60'),
|
||||
('108', 'Nancy', 'Greenberg', 'NGREENBE', '515.124.4569', '1987-06-25', 'FI_MGR', '12000.00', '0.00', '101', '100'),
|
||||
('109', 'Daniel', 'Faviet', 'DFAVIET', '515.124.4169', '1987-06-26', 'FI_ACCOUNT', '9000.00', '0.00', '108', '100'),
|
||||
('110', 'John', 'Chen', 'JCHEN', '515.124.4269', '1987-06-27', 'FI_ACCOUNT', '8200.00', '0.00', '108', '100'),
|
||||
('111', 'Ismael', 'Sciarra', 'ISCIARRA', '515.124.4369', '1987-06-28', 'FI_ACCOUNT', '7700.00', '0.00', '108', '100'),
|
||||
('112', 'Jose Manuel', 'Urman', 'JMURMAN', '515.124.4469', '1987-06-29', 'FI_ACCOUNT', '7800.00', '0.00', '108', '100'),
|
||||
('113', 'Luis', 'Popp', 'LPOPP', '515.124.4567', '1987-06-30', 'FI_ACCOUNT', '6900.00', '0.00', '108', '100'),
|
||||
('114', 'Den', 'Raphaely', 'DRAPHEAL', '515.127.4561', '1987-07-01', 'PU_MAN', '11000.00', '0.00', '100', '30'),
|
||||
('115', 'Alexander', 'Khoo', 'AKHOO', '515.127.4562', '1987-07-02', 'PU_CLERK', '3100.00', '0.00', '114', '30'),
|
||||
('116', 'Shelli', 'Baida', 'SBAIDA', '515.127.4563', '1987-07-03', 'PU_CLERK', '2900.00', '0.00', '114', '30'),
|
||||
('117', 'Sigal', 'Tobias', 'STOBIAS', '515.127.4564', '1987-07-04', 'PU_CLERK', '2800.00', '0.00', '114', '30'),
|
||||
('118', 'Guy', 'Himuro', 'GHIMURO', '515.127.4565', '1987-07-05', 'PU_CLERK', '2600.00', '0.00', '114', '30'),
|
||||
('119', 'Karen', 'Colmenares', 'KCOLMENA', '515.127.4566', '1987-07-06', 'PU_CLERK', '2500.00', '0.00', '114', '30'),
|
||||
('120', 'Matthew', 'Weiss', 'MWEISS', '650.123.1234', '1987-07-07', 'ST_MAN', '8000.00', '0.00', '100', '50'),
|
||||
('121', 'Adam', 'Fripp', 'AFRIPP', '650.123.2234', '1987-07-08', 'ST_MAN', '8200.00', '0.00', '100', '50'),
|
||||
('122', 'Payam', 'Kaufling', 'PKAUFLIN', '650.123.3234', '1987-07-09', 'ST_MAN', '7900.00', '0.00', '100', '50'),
|
||||
('123', 'Shanta', 'Vollman', 'SVOLLMAN', '650.123.4234', '1987-07-10', 'ST_MAN', '6500.00', '0.00', '100', '50'),
|
||||
('124', 'Kevin', 'Mourgos', 'KMOURGOS', '650.123.5234', '1987-07-11', 'ST_MAN', '5800.00', '0.00', '100', '50'),
|
||||
('125', 'Julia', 'Nayer', 'JNAYER', '650.124.1214', '1987-07-12', 'ST_CLERK', '3200.00', '0.00', '120', '50'),
|
||||
('126', 'Irene', 'Mikkilineni', 'IMIKKILI', '650.124.1224', '1987-07-13', 'ST_CLERK', '2700.00', '0.00', '120', '50'),
|
||||
('127', 'James', 'Landry', 'JLANDRY', '650.124.1334', '1987-07-14', 'ST_CLERK', '2400.00', '0.00', '120', '50'),
|
||||
('128', 'Steven', 'Markle', 'SMARKLE', '650.124.1434', '1987-07-15', 'ST_CLERK', '2200.00', '0.00', '120', '50'),
|
||||
('129', 'Laura', 'Bissot', 'LBISSOT', '650.124.5234', '1987-07-16', 'ST_CLERK', '3300.00', '0.00', '121', '50'),
|
||||
('130', 'Mozhe', 'Atkinson', 'MATKINSO', '650.124.6234', '1987-07-17', 'ST_CLERK', '2800.00', '0.00', '121', '50'),
|
||||
('131', 'James', 'Marlow', 'JAMRLOW', '650.124.7234', '1987-07-18', 'ST_CLERK', '2500.00', '0.00', '121', '50'),
|
||||
('132', 'TJ', 'Olson', 'TJOLSON', '650.124.8234', '1987-07-19', 'ST_CLERK', '2100.00', '0.00', '121', '50'),
|
||||
('133', 'Jason', 'Mallin', 'JMALLIN', '650.127.1934', '1987-07-20', 'ST_CLERK', '3300.00', '0.00', '122', '50'),
|
||||
('134', 'Michael', 'Rogers', 'MROGERS', '650.127.1834', '1987-07-21', 'ST_CLERK', '2900.00', '0.00', '122', '50'),
|
||||
('135', 'Ki', 'Gee', 'KGEE', '650.127.1734', '1987-07-22', 'ST_CLERK', '2400.00', '0.00', '122', '50'),
|
||||
('136', 'Hazel', 'Philtanker', 'HPHILTAN', '650.127.1634', '1987-07-23', 'ST_CLERK', '2200.00', '0.00', '122', '50'),
|
||||
('137', 'Renske', 'Ladwig', 'RLADWIG', '650.121.1234', '1987-07-24', 'ST_CLERK', '3600.00', '0.00', '123', '50'),
|
||||
('138', 'Stephen', 'Stiles', 'SSTILES', '650.121.2034', '1987-07-25', 'ST_CLERK', '3200.00', '0.00', '123', '50'),
|
||||
('139', 'John', 'Seo', 'JSEO', '650.121.2019', '1987-07-26', 'ST_CLERK', '2700.00', '0.00', '123', '50'),
|
||||
('140', 'Joshua', 'Patel', 'JPATEL', '650.121.1834', '1987-07-27', 'ST_CLERK', '2500.00', '0.00', '123', '50'),
|
||||
('141', 'Trenna', 'Rajs', 'TRAJS', '650.121.8009', '1987-07-28', 'ST_CLERK', '3500.00', '0.00', '124', '50'),
|
||||
('142', 'Curtis', 'Davies', 'CDAVIES', '650.121.2994', '1987-07-29', 'ST_CLERK', '3100.00', '0.00', '124', '50'),
|
||||
('143', 'Randall', 'Matos', 'RMATOS', '650.121.2874', '1987-07-30', 'ST_CLERK', '2600.00', '0.00', '124', '50'),
|
||||
('144', 'Peter', 'Vargas', 'PVARGAS', '650.121.2004', '1987-07-31', 'ST_CLERK', '2500.00', '0.00', '124', '50'),
|
||||
('145', 'John', 'Russell', 'JRUSSEL', '011.44.1344.429268', '1987-08-01', 'SA_MAN', '14000.00', '0.40', '100', '80'),
|
||||
('146', 'Karen', 'Partners', 'KPARTNER', '011.44.1344.467268', '1987-08-02', 'SA_MAN', '13500.00', '0.30', '100', '80'),
|
||||
('147', 'Alberto', 'Errazuriz', 'AERRAZUR', '011.44.1344.429278', '1987-08-03', 'SA_MAN', '12000.00', '0.30', '100', '80'),
|
||||
('148', 'Gerald', 'Cambrault', 'GCAMBRAU', '011.44.1344.619268', '1987-08-04', 'SA_MAN', '11000.00', '0.30', '100', '80'),
|
||||
('149', 'Eleni', 'Zlotkey', 'EZLOTKEY', '011.44.1344.429018', '1987-08-05', 'SA_MAN', '10500.00', '0.20', '100', '80'),
|
||||
('150', 'Peter', 'Tucker', 'PTUCKER', '011.44.1344.129268', '1987-08-06', 'SA_REP', '10000.00', '0.30', '145', '80'),
|
||||
('151', 'David', 'Bernstein', 'DBERNSTE', '011.44.1344.345268', '1987-08-07', 'SA_REP', '9500.00', '0.25', '145', '80'),
|
||||
('152', 'Peter', 'Hall', 'PHALL', '011.44.1344.478968', '1987-08-08', 'SA_REP', '9000.00', '0.25', '145', '80'),
|
||||
('153', 'Christopher', 'Olsen', 'COLSEN', '011.44.1344.498718', '1987-08-09', 'SA_REP', '8000.00', '0.20', '145', '80'),
|
||||
('154', 'Nanette', 'Cambrault', 'NCAMBRAU', '011.44.1344.987668', '1987-08-10', 'SA_REP', '7500.00', '0.20', '145', '80'),
|
||||
('155', 'Oliver', 'Tuvault', 'OTUVAULT', '011.44.1344.486508', '1987-08-11', 'SA_REP', '7000.00', '0.15', '145', '80'),
|
||||
('156', 'Janette', 'King', 'JKING', '011.44.1345.429268', '1987-08-12', 'SA_REP', '10000.00', '0.35', '146', '80'),
|
||||
('157', 'Patrick', 'Sully', 'PSULLY', '011.44.1345.929268', '1987-08-13', 'SA_REP', '9500.00', '0.35', '146', '80'),
|
||||
('158', 'Allan', 'McEwen', 'AMCEWEN', '011.44.1345.829268', '1987-08-14', 'SA_REP', '9000.00', '0.35', '146', '80'),
|
||||
('159', 'Lindsey', 'Smith', 'LSMITH', '011.44.1345.729268', '1987-08-15', 'SA_REP', '8000.00', '0.30', '146', '80'),
|
||||
('160', 'Louise', 'Doran', 'LDORAN', '011.44.1345.629268', '1987-08-16', 'SA_REP', '7500.00', '0.30', '146', '80'),
|
||||
('161', 'Sarath', 'Sewall', 'SSEWALL', '011.44.1345.529268', '1987-08-17', 'SA_REP', '7000.00', '0.25', '146', '80'),
|
||||
('162', 'Clara', 'Vishney', 'CVISHNEY', '011.44.1346.129268', '1987-08-18', 'SA_REP', '10500.00', '0.25', '147', '80'),
|
||||
('163', 'Danielle', 'Greene', 'DGREENE', '011.44.1346.229268', '1987-08-19', 'SA_REP', '9500.00', '0.15', '147', '80'),
|
||||
('164', 'Mattea', 'Marvins', 'MMARVINS', '011.44.1346.329268', '1987-08-20', 'SA_REP', '7200.00', '0.10', '147', '80'),
|
||||
('165', 'David', 'Lee', 'DLEE', '011.44.1346.529268', '1987-08-21', 'SA_REP', '6800.00', '0.10', '147', '80'),
|
||||
('166', 'Sundar', 'Ande', 'SANDE', '011.44.1346.629268', '1987-08-22', 'SA_REP', '6400.00', '0.10', '147', '80'),
|
||||
('167', 'Amit', 'Banda', 'ABANDA', '011.44.1346.729268', '1987-08-23', 'SA_REP', '6200.00', '0.10', '147', '80'),
|
||||
('168', 'Lisa', 'Ozer', 'LOZER', '011.44.1343.929268', '1987-08-24', 'SA_REP', '11500.00', '0.25', '148', '80'),
|
||||
('169', 'Harrison', 'Bloom', 'HBLOOM', '011.44.1343.829268', '1987-08-25', 'SA_REP', '10000.00', '0.20', '148', '80'),
|
||||
('170', 'Tayler', 'Fox', 'TFOX', '011.44.1343.729268', '1987-08-26', 'SA_REP', '9600.00', '0.20', '148', '80'),
|
||||
('171', 'William', 'Smith', 'WSMITH', '011.44.1343.629268', '1987-08-27', 'SA_REP', '7400.00', '0.15', '148', '80'),
|
||||
('172', 'Elizabeth', 'Bates', 'EBATES', '011.44.1343.529268', '1987-08-28', 'SA_REP', '7300.00', '0.15', '148', '80'),
|
||||
('173', 'Sundita', 'Kumar', 'SKUMAR', '011.44.1343.329268', '1987-08-29', 'SA_REP', '6100.00', '0.10', '148', '80'),
|
||||
('174', 'Ellen', 'Abel', 'EABEL', '011.44.1644.429267', '1987-08-30', 'SA_REP', '11000.00', '0.30', '149', '80'),
|
||||
('175', 'Alyssa', 'Hutton', 'AHUTTON', '011.44.1644.429266', '1987-08-31', 'SA_REP', '8800.00', '0.25', '149', '80'),
|
||||
('176', 'Jonathon', 'Taylor', 'JTAYLOR', '011.44.1644.429265', '1987-09-01', 'SA_REP', '8600.00', '0.20', '149', '80'),
|
||||
('177', 'Jack', 'Livingston', 'JLIVINGS', '011.44.1644.429264', '1987-09-02', 'SA_REP', '8400.00', '0.20', '149', '80'),
|
||||
('178', 'Kimberely', 'Grant', 'KGRANT', '011.44.1644.429263', '1987-09-03', 'SA_REP', '7000.00', '0.15', '149', '0'),
|
||||
('179', 'Charles', 'Johnson', 'CJOHNSON', '011.44.1644.429262', '1987-09-04', 'SA_REP', '6200.00', '0.10', '149', '80'),
|
||||
('180', 'Winston', 'Taylor', 'WTAYLOR', '650.507.9876', '1987-09-05', 'SH_CLERK', '3200.00', '0.00', '120', '50'),
|
||||
('181', 'Jean', 'Fleaur', 'JFLEAUR', '650.507.9877', '1987-09-06', 'SH_CLERK', '3100.00', '0.00', '120', '50'),
|
||||
('182', 'Martha', 'Sullivan', 'MSULLIVA', '650.507.9878', '1987-09-07', 'SH_CLERK', '2500.00', '0.00', '120', '50'),
|
||||
('183', 'Girard', 'Geoni', 'GGEONI', '650.507.9879', '1987-09-08', 'SH_CLERK', '2800.00', '0.00', '120', '50'),
|
||||
('184', 'Nandita', 'Sarchand', 'NSARCHAN', '650.509.1876', '1987-09-09', 'SH_CLERK', '4200.00', '0.00', '121', '50'),
|
||||
('185', 'Alexis', 'Bull', 'ABULL', '650.509.2876', '1987-09-10', 'SH_CLERK', '4100.00', '0.00', '121', '50'),
|
||||
('186', 'Julia', 'Dellinger', 'JDELLING', '650.509.3876', '1987-09-11', 'SH_CLERK', '3400.00', '0.00', '121', '50'),
|
||||
('187', 'Anthony', 'Cabrio', 'ACABRIO', '650.509.4876', '1987-09-12', 'SH_CLERK', '3000.00', '0.00', '121', '50'),
|
||||
('188', 'Kelly', 'Chung', 'KCHUNG', '650.505.1876', '1987-09-13', 'SH_CLERK', '3800.00', '0.00', '122', '50'),
|
||||
('189', 'Jennifer', 'Dilly', 'JDILLY', '650.505.2876', '1987-09-14', 'SH_CLERK', '3600.00', '0.00', '122', '50'),
|
||||
('190', 'Timothy', 'Gates', 'TGATES', '650.505.3876', '1987-09-15', 'SH_CLERK', '2900.00', '0.00', '122', '50'),
|
||||
('191', 'Randall', 'Perkins', 'RPERKINS', '650.505.4876', '1987-09-16', 'SH_CLERK', '2500.00', '0.00', '122', '50'),
|
||||
('192', 'Sarah', 'Bell', 'SBELL', '650.501.1876', '1987-09-17', 'SH_CLERK', '4000.00', '0.00', '123', '50'),
|
||||
('193', 'Britney', 'Everett', 'BEVERETT', '650.501.2876', '1987-09-18', 'SH_CLERK', '3900.00', '0.00', '123', '50'),
|
||||
('194', 'Samuel', 'McCain', 'SMCCAIN', '650.501.3876', '1987-09-19', 'SH_CLERK', '3200.00', '0.00', '123', '50'),
|
||||
('195', 'Vance', 'Jones', 'VJONES', '650.501.4876', '1987-09-20', 'SH_CLERK', '2800.00', '0.00', '123', '50'),
|
||||
('196', 'Alana', 'Walsh', 'AWALSH', '650.507.9811', '1987-09-21', 'SH_CLERK', '3100.00', '0.00', '124', '50'),
|
||||
('197', 'Kevin', 'Feeney', 'KFEENEY', '650.507.9822', '1987-09-22', 'SH_CLERK', '3000.00', '0.00', '124', '50'),
|
||||
('198', 'Donald', 'OConnell', 'DOCONNEL', '650.507.9833', '1987-09-23', 'SH_CLERK', '2600.00', '0.00', '124', '50'),
|
||||
('199', 'Douglas', 'Grant', 'DGRANT', '650.507.9844', '1987-09-24', 'SH_CLERK', '2600.00', '0.00', '124', '50'),
|
||||
('200', 'Jennifer', 'Whalen', 'JWHALEN', '515.123.4444', '1987-09-25', 'AD_ASST', '4400.00', '0.00', '101', '10'),
|
||||
('201', 'Michael', 'Hartstein', 'MHARTSTE', '515.123.5555', '1987-09-26', 'MK_MAN', '13000.00', '0.00', '100', '20'),
|
||||
('202', 'Pat', 'Fay', 'PFAY', '603.123.6666', '1987-09-27', 'MK_REP', '6000.00', '0.00', '201', '20'),
|
||||
('203', 'Susan', 'Mavris', 'SMAVRIS', '515.123.7777', '1987-09-28', 'HR_REP', '6500.00', '0.00', '101', '40'),
|
||||
('204', 'Hermann', 'Baer', 'HBAER', '515.123.8888', '1987-09-29', 'PR_REP', '10000.00', '0.00', '101', '70'),
|
||||
('205', 'Shelley', 'Higgins', 'SHIGGINS', '515.123.8080', '1987-09-30', 'AC_MGR', '12000.00', '0.00', '101', '110'),
|
||||
('206', 'William', 'Gietz', 'WGIETZ', '515.123.8181', '1987-10-01', 'AC_ACCOUNT', '8300.00', '0.00', '205', '110');
|
||||
|
||||
INSERT INTO job_history (EMPLOYEE_ID, START_DATE, END_DATE, JOB_ID, DEPARTMENT_ID) VALUES
|
||||
('102', '1993-01-13', '1998-07-24', 'IT_PROG', '60'),
|
||||
('101', '1989-09-21', '1993-10-27', 'AC_ACCOUNT', '110'),
|
||||
('201', '1996-02-17', '1999-12-19', 'MK_REP', '20'),
|
||||
('114', '1998-03-24', '1999-12-31', 'ST_CLERK', '50'),
|
||||
('122', '1999-01-01', '1999-12-31', 'ST_CLERK', '50'),
|
||||
('200', '1987-09-17', '1993-06-17', 'AD_ASST', '90'),
|
||||
('176', '1998-03-24', '1998-12-31', 'SA_REP', '80');
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
BIN
Semaine_07/Jour_02/sql_joins.jpg
Normal file
BIN
Semaine_07/Jour_02/sql_joins.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 144 KiB |
BIN
Semaine_07/Jour_03/BDD_Sujet_B.pdf
Normal file
BIN
Semaine_07/Jour_03/BDD_Sujet_B.pdf
Normal file
Binary file not shown.
BIN
Semaine_07/Jour_03/B_Boiché_Gauvain.mwb
Normal file
BIN
Semaine_07/Jour_03/B_Boiché_Gauvain.mwb
Normal file
Binary file not shown.
BIN
Semaine_07/Jour_03/B_Boiché_Gauvain.mwb.bak
Normal file
BIN
Semaine_07/Jour_03/B_Boiché_Gauvain.mwb.bak
Normal file
Binary file not shown.
4
Semaine_07/Jour_03/python/connector/.env
Normal file
4
Semaine_07/Jour_03/python/connector/.env
Normal file
@@ -0,0 +1,4 @@
|
||||
DB_HOST=localhost
|
||||
DB_USER=mysql_user
|
||||
DB_PASSWORD=Azerty123
|
||||
DB_NAME=company
|
||||
1
Semaine_07/Jour_03/python/connector/.python-version
Normal file
1
Semaine_07/Jour_03/python/connector/.python-version
Normal file
@@ -0,0 +1 @@
|
||||
3.12
|
||||
0
Semaine_07/Jour_03/python/connector/README.md
Normal file
0
Semaine_07/Jour_03/python/connector/README.md
Normal file
115
Semaine_07/Jour_03/python/connector/main.py
Normal file
115
Semaine_07/Jour_03/python/connector/main.py
Normal file
@@ -0,0 +1,115 @@
|
||||
import os
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from mysql.connector import Error, connect, errorcode
|
||||
|
||||
load_dotenv()
|
||||
|
||||
db_host = os.environ.get("DB_HOST")
|
||||
db_user = os.environ.get("DB_USER")
|
||||
db_password = os.environ.get("DB_PASSWORD")
|
||||
db_name = os.environ.get("DB_NAME")
|
||||
|
||||
try:
|
||||
connection = connect(
|
||||
host= db_host,
|
||||
user= db_user,
|
||||
password= db_password,
|
||||
database= db_name
|
||||
)
|
||||
|
||||
cursor = connection.cursor()
|
||||
### Exemple 1 : commande
|
||||
# cursor.execute("SELECT * FROM employee LIMIT 5")
|
||||
# results = cursor.fetchone()
|
||||
# print(results)
|
||||
|
||||
# ### Exemple 2 : requête complète comme variable
|
||||
# query = """
|
||||
# CREATE TABLE IF NOT EXISTS movies (
|
||||
# id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
# title VARCHAR(100),
|
||||
# release_year YEAR(4),
|
||||
# genre VARCHAR(100),
|
||||
# collection_in_mil DECIMAL(4,1)
|
||||
# )
|
||||
# """
|
||||
# cursor.execute(query)
|
||||
# # CIUD : Create, Insert, Update, Delete => Commit
|
||||
# connection.commit()
|
||||
|
||||
### Exemple 3 : multiple requête
|
||||
insert_query = """
|
||||
INSERT INTO movies (title, release_year, genre, collection_in_mil)
|
||||
VALUES
|
||||
("Forrest Gump", 1994, "Drama", 330.2),
|
||||
("INception", 2010, "Aventure", 293.7),
|
||||
("Titanic", 1995, "Drama", 530.4)
|
||||
"""
|
||||
|
||||
create_query = """
|
||||
CREATE TABLE IF NOT EXISTS reviewers (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
firstname VARCHAR(100),
|
||||
lastname VARCHAR(100)
|
||||
)
|
||||
"""
|
||||
|
||||
insert_query_2 = """
|
||||
INSERT INTO reviewers (firstname, lastname)
|
||||
VALUES (%s, %s)
|
||||
"""
|
||||
|
||||
reviewers = [
|
||||
("Jean", "FAIBLE"),
|
||||
("Alain", "TERIEUR"),
|
||||
("Tabatha", "CLOISON"),
|
||||
("Ahmed", "BIEN")
|
||||
]
|
||||
|
||||
cursor.execute(insert_query)
|
||||
cursor.execute(create_query)
|
||||
cursor.executemany(insert_query_2, reviewers)
|
||||
connection.commit()
|
||||
|
||||
cursor.execute("SELECT * FROM movies")
|
||||
# lire un par un
|
||||
resultat = cursor.fetchone()
|
||||
print(resultat)
|
||||
while resultat is not None:
|
||||
print(resultat)
|
||||
resultat = cursor.fetchone()
|
||||
|
||||
# utilisation de lot
|
||||
cursor.execute("SELECT * FROM movies")
|
||||
batch = cursor.fetchmany(size= 4)
|
||||
while batch:
|
||||
print("----")
|
||||
for row in batch:
|
||||
print(row)
|
||||
batch = cursor.fetchmany(4)
|
||||
|
||||
# Out of Memory
|
||||
|
||||
insert_movies_query = """
|
||||
INSERT INTO movies (title, release_year, genre, collection_in_mil)
|
||||
VALUES (%s, %s, %s, %s)
|
||||
"""
|
||||
|
||||
with open("movies.csv", "r") as fichier:
|
||||
reader = csv.reader(fichier)
|
||||
next(reader)
|
||||
|
||||
except Error as error:
|
||||
match error.errno:
|
||||
case errorcode.ER_ACCESS_DENIED_ERROR:
|
||||
print("Accès refusé. Vérifier USER et PASSWORD")
|
||||
case errorcode.ER_BAD_DB_ERROR:
|
||||
print("BDD n'existe pas")
|
||||
case _:
|
||||
print(f"Erreur {error}")
|
||||
finally:
|
||||
if cursor is not None:
|
||||
cursor.close()
|
||||
if connection is not None and connection.is_connected():
|
||||
connection.close()
|
||||
10
Semaine_07/Jour_03/python/connector/pyproject.toml
Normal file
10
Semaine_07/Jour_03/python/connector/pyproject.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
[project]
|
||||
name = "connector"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
"mysql-connector-python>=9.6.0",
|
||||
"python-dotenv>=1.2.2",
|
||||
]
|
||||
51
Semaine_07/Jour_03/python/connector/uv.lock
generated
Normal file
51
Semaine_07/Jour_03/python/connector/uv.lock
generated
Normal file
@@ -0,0 +1,51 @@
|
||||
version = 1
|
||||
revision = 3
|
||||
requires-python = ">=3.12"
|
||||
|
||||
[[package]]
|
||||
name = "connector"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "mysql-connector-python" },
|
||||
{ name = "python-dotenv" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "mysql-connector-python", specifier = ">=9.6.0" },
|
||||
{ name = "python-dotenv", specifier = ">=1.2.2" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mysql-connector-python"
|
||||
version = "9.6.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/6f/6e/c89babc7de3df01467d159854414659c885152579903a8220c8db02a3835/mysql_connector_python-9.6.0.tar.gz", hash = "sha256:c453bb55347174d87504b534246fb10c589daf5d057515bf615627198a3c7ef1", size = 12254999, upload-time = "2026-02-10T12:04:52.63Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/d9/2a4b4d90b52f4241f0f71618cd4bd8779dd6d18db8058b0a4dd83ec0541c/mysql_connector_python-9.6.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:9664e217c72dd6fb700f4c8512af90261f72d2f5d7c00c4e13e4c1e09bfa3d5e", size = 17585672, upload-time = "2026-02-10T12:03:52.955Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/33/91/2495835733a054e716a17dc28404748b33f2dc1da1ae4396fb45574adf40/mysql_connector_python-9.6.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:1ed4b5c4761e5333035293e746683890e4ef2e818e515d14023fd80293bc31fa", size = 18452624, upload-time = "2026-02-10T12:03:56.153Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7a/69/e83abbbbf7f8eed855b5a5ff7285bc0afb1199418ac036c7691edf41e154/mysql_connector_python-9.6.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:5095758dcb89a6bce2379f349da336c268c407129002b595c5dba82ce387e2a5", size = 34169154, upload-time = "2026-02-10T12:03:58.831Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/82/44/67bb61c71f398fbc739d07e8dcadad94e2f655874cb32ae851454066bea0/mysql_connector_python-9.6.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:4ae4e7780fad950a4f267dea5851048d160f5b71314a342cdbf30b154f1c74f7", size = 34542947, upload-time = "2026-02-10T12:04:02.408Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/39/994c4f7e9c59d3ca534a831d18442ac4c529865db20aeaa4fd94e2af5efd/mysql_connector_python-9.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:c180e0b4100d7402e03993bfac5c97d18e01d7ca9d198d742fffc245077f8ffe", size = 16515709, upload-time = "2026-02-10T12:04:04.924Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2f/58/9521aa678708ec6cebfd40524c14c3d151e4f29e3774e6086aa0a30d203b/mysql_connector_python-9.6.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e86e45a7b540ca09af8a18ecfa761e0cdeccfdb62818331614ec030ae44bfd26", size = 17585837, upload-time = "2026-02-10T12:04:07.004Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/39/8d/b108f9bcce9780f6a1f91decb2af54defdaf845e237ddc42f2b4578f1cd7/mysql_connector_python-9.6.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:8d3e9252384e1b7f95b07020664f2673d9c29c5e95eeda2e048b3331e190b9d4", size = 18452844, upload-time = "2026-02-10T12:04:09.418Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/28/735cd93d16e76dc2feb4abb3f1229a1d9475af34d80c26712fec6abe1d70/mysql_connector_python-9.6.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:0fa18ead33cb699ea92005695077cef09aa494eebf51164ee30c891c3eaea90c", size = 34169374, upload-time = "2026-02-10T12:04:12.13Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/42/07/069983799cf4050c68f61a494f94b06f095fee6026ab0dd863a14de30867/mysql_connector_python-9.6.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:a26490cb029bf7b18a1d2093101105b3526a1036b51ad01553d30138f5beb8d2", size = 34543019, upload-time = "2026-02-10T12:04:15.065Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/00/fbeb7d666ab8153f719e620bac5abfbc74640e8ec511612493110a75fe66/mysql_connector_python-9.6.0-cp313-cp313-win_amd64.whl", hash = "sha256:3460ed976e1b88b7284335d9397a3c519dff56d71580ca1f76ff1c0c7714c813", size = 16515701, upload-time = "2026-02-10T12:04:19.26Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/51/13cc90b2a703784cd9a0aa0a6fce07946cf6a2abe7c8fd0b585562e250fc/mysql_connector_python-9.6.0-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:e2cc13cd3dcdb845d636e52c4e7a9509b63da09bec6ce1b3696be53a79847e2d", size = 17585800, upload-time = "2026-02-10T12:04:21.6Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/6b/ce7ab998fbdd17f35a1b54624365d039045cbb2d42bbc7b03f50d7597c7b/mysql_connector_python-9.6.0-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:a08c2149d4b52a010c4353f18c84716d18114a4ecd00b466ea34138de2c640f2", size = 18452823, upload-time = "2026-02-10T12:04:23.995Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/bf/8157ed61d17878c33511dcb97c68ecaaaf6220bea5a2944ea4eba73cc63a/mysql_connector_python-9.6.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:b00228b985edd208b20f45c5e684c54e08e31e01bc1d8c3c18a36641c3be5bf7", size = 34171594, upload-time = "2026-02-10T12:04:27.401Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/06/5efdd28819afdb9f1487a62842fda4277febe128a3cd6e9090dbe0a6524e/mysql_connector_python-9.6.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:4617ef5216da7ca32dd46afda61a1552807762434127413bba46fbe4379f59d4", size = 34542851, upload-time = "2026-02-10T12:04:31.021Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/40/6a/26e08a4a79f159cd8e5b64eb10bd056e7735b65d4464d98641f59eb9ca3a/mysql_connector_python-9.6.0-cp314-cp314-win_amd64.whl", hash = "sha256:bc782f64ca00b6b933d4c6a35568f1349d115cc4434c849b5b9edc015bee3e62", size = 17002947, upload-time = "2026-02-10T12:04:34.386Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/dd/b3250826c29cee7816de4409a2fe5e469a68b9a89f6bfaa5eed74f05532c/mysql_connector_python-9.6.0-py2.py3-none-any.whl", hash = "sha256:44b0fb57207ebc6ae05b5b21b7968a9ed33b29187fe87b38951bad2a334d75d5", size = 480527, upload-time = "2026-02-10T12:04:36.176Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-dotenv"
|
||||
version = "1.2.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" },
|
||||
]
|
||||
1
Semaine_07/Jour_04/bank/.python-version
Normal file
1
Semaine_07/Jour_04/bank/.python-version
Normal file
@@ -0,0 +1 @@
|
||||
3.12
|
||||
3
Semaine_07/Jour_04/bank/README.md
Normal file
3
Semaine_07/Jour_04/bank/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
```py
|
||||
uv add sqlalchemy
|
||||
```
|
||||
12
Semaine_07/Jour_04/bank/database/__init__.py
Normal file
12
Semaine_07/Jour_04/bank/database/__init__.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from sqlalchemy.orm import DeclarativeMeta, declarative_base
|
||||
from database.connection import get_engine
|
||||
|
||||
Base: DeclarativeMeta = declarative_base() # permet à SQLAlchemy de faire la liaison Python <-> SQL
|
||||
engine = get_engine()
|
||||
|
||||
from entities.accounts import Account
|
||||
from entities.banks import Bank
|
||||
from entities.clients import Client, ClientNotFound
|
||||
from entities.credit_cards import CreditCard
|
||||
|
||||
Base.metadata.create_all(engine)
|
||||
0
Semaine_07/Jour_04/bank/database/bank.db
Normal file
0
Semaine_07/Jour_04/bank/database/bank.db
Normal file
16
Semaine_07/Jour_04/bank/database/connection.py
Normal file
16
Semaine_07/Jour_04/bank/database/connection.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import declarative_base, sessionmaker # constructeur de classe
|
||||
|
||||
db_url = "sqlite:///database/bank.db"
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
# moteur_dialect
|
||||
def get_engine():
|
||||
return create_engine(url= db_url)
|
||||
|
||||
# session => cursor
|
||||
def get_session():
|
||||
engine = get_engine()
|
||||
Session = sessionmaker(bind= engine)
|
||||
return Session()
|
||||
51
Semaine_07/Jour_04/bank/entities/accounts.py
Normal file
51
Semaine_07/Jour_04/bank/entities/accounts.py
Normal file
@@ -0,0 +1,51 @@
|
||||
from random import randint
|
||||
|
||||
from sqlalchemy import ForeignKey, Column, Integer, Float
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from database import Base, engine
|
||||
|
||||
class Account(Base):
|
||||
__tablename__ = "accounts"
|
||||
|
||||
id = Column(Integer, primary_key= True, autoincrement= True)
|
||||
number = Column(Integer, nullable= False)
|
||||
balance = Column(Float, default= 0, nullable= False)
|
||||
|
||||
client_id = Column(Integer, ForeignKey("clients.id"), nullable= False)
|
||||
credit_card_id = Column(Integer, ForeignKey("credit_cards.id"))
|
||||
|
||||
client = relationship('Client', back_populates= "accounts")
|
||||
|
||||
def __init__(self, initial_deposit: int | float) -> None:
|
||||
self.number = self.account_number()
|
||||
self.amount = initial_deposit
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"\
|
||||
[Numéro de compte] : {self.number}\n\
|
||||
[Montant disponible] : {self.amount}"
|
||||
|
||||
def __eq__(self, other: 'Account'):
|
||||
return self.number == other.number
|
||||
|
||||
def account_number(self):
|
||||
number = "".join(str(randint(0,9)) for _ in range(7))
|
||||
return " ".join(number[_: _ + 4] for _ in range(0,7,4))
|
||||
|
||||
def add_money(self, add_amount: int | float):
|
||||
if add_amount < 0:
|
||||
return f"{add_amount} n'est pas un entier positif. Recommencez."
|
||||
self.amount += add_amount
|
||||
return f"{add_amount} ont été ajoutés. Le nouveau solde est de {self.amount}."
|
||||
|
||||
def take_money(self, take_amount: int | float):
|
||||
if take_amount < 0:
|
||||
return f"{take_amount} n'est pas un entier positif. Recommencez."
|
||||
self.amount -= take_amount
|
||||
if self.amount < 0:
|
||||
return f"{take_amount} ont été retirés. Le nouveau solde est de {self.amount}.\n\
|
||||
Vous êtes débiteur et devrez payer des agios si vous ne régularisez pas votre situation."
|
||||
return f"{take_amount} ont été retirés. Le nouveau solde est de {self.amount}."
|
||||
|
||||
Base.metadata.create_all(engine)
|
||||
37
Semaine_07/Jour_04/bank/entities/banks.py
Normal file
37
Semaine_07/Jour_04/bank/entities/banks.py
Normal file
@@ -0,0 +1,37 @@
|
||||
from clients import Client, ClientNotFound
|
||||
from credit_cards import CreditCard
|
||||
|
||||
from sqlalchemy import Column, Integer, String
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from database import Base, engine
|
||||
|
||||
class Bank(Base):
|
||||
__tablename__ = "banks"
|
||||
|
||||
id = Column(Integer, primary_key= True, autoincrement= True)
|
||||
name = Column(String(200), nullable= False)
|
||||
|
||||
clients = relationship("Client", back_populate= "bank", uselist= True) # type: ignore
|
||||
# Le uselist définit le One ou le Many d'une relation inter-tables
|
||||
# Cela permet aussi de définir la dépendance d'une table à l'autre
|
||||
|
||||
def __init__(self, name: str) -> None:
|
||||
self.name = name
|
||||
self.clients: list["Client"] = []
|
||||
# Tout attribut faisant référence à une autre classe
|
||||
# est une RELATION, pas une COLONNE
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"\
|
||||
[Banque] : {self.name}"
|
||||
|
||||
def add_client(self, client: "Client"):
|
||||
self.clients.append(client)
|
||||
|
||||
def request_credit_card(self, client: "Client"):
|
||||
if client not in self.clients:
|
||||
raise ClientNotFound()
|
||||
return CreditCard(account = client.account)
|
||||
|
||||
Base.metadata.create_all(engine)
|
||||
43
Semaine_07/Jour_04/bank/entities/clients.py
Normal file
43
Semaine_07/Jour_04/bank/entities/clients.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from accounts import Account
|
||||
from services import client_service
|
||||
|
||||
from sqlalchemy import ForeignKey, Column, Integer, String, Float
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from database import Base, engine
|
||||
|
||||
class Client(Base):
|
||||
__tablename__ = "clients"
|
||||
|
||||
id = Column(Integer, primary_key= True, autoincrement= True)
|
||||
first_name = Column(String(200), nullable= False)
|
||||
last_name = Column(String(200), nullable= False)
|
||||
city = Column(String(200))
|
||||
salary = Column(Float)
|
||||
|
||||
bank_id = Column(Integer, ForeignKey("banks.id"), nullable= False)
|
||||
|
||||
bank = relationship("Bank", back_populates= "clients")
|
||||
account = relationship("Account", back_populates= "clients", uselist= False) # type: ignore
|
||||
services = relationship("Services", back_populates= "clients", secondary= client_service)
|
||||
|
||||
def __init__(self, first_name: str, last_name: str, salary: float, city: str, initial_deposit: int | float = 0) -> None:
|
||||
self.first_name = first_name
|
||||
self.last_name = last_name
|
||||
self.salary = salary
|
||||
self.city = city
|
||||
self.account: Account = Account(initial_deposit = initial_deposit)
|
||||
|
||||
def __eq__(self, other: "Client") -> bool:
|
||||
return self.first_name == other.first_name and\
|
||||
self.last_name == other.last_name and\
|
||||
self.account == other.account # type: ignore
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Client({self.first_name} {self.last_name})"
|
||||
|
||||
class ClientNotFound(Exception):
|
||||
def __init__(self, *args: object) -> None:
|
||||
super().__init__("Client not found")
|
||||
|
||||
Base.metadata.create_all(engine)
|
||||
45
Semaine_07/Jour_04/bank/entities/credit_cards.py
Normal file
45
Semaine_07/Jour_04/bank/entities/credit_cards.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from datetime import datetime
|
||||
from random import randint
|
||||
|
||||
from accounts import Account
|
||||
|
||||
from sqlalchemy import Column, Integer, CHAR
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from database import Base, engine
|
||||
|
||||
class CreditCard(Base):
|
||||
__tablename__ = "credit_cards"
|
||||
|
||||
id = Column(Integer, primary_key= True, autoincrement= True)
|
||||
number = Column(CHAR(19), nullable= False)
|
||||
secure_code = Column(CHAR(3), nullable= False)
|
||||
expire_date = Column(CHAR(5), nullable= False)
|
||||
|
||||
account = relationship("Account", back_populates= "credit_cards", uselist= False) # type: ignore
|
||||
|
||||
def __init__(self, account: "Account") -> None:
|
||||
self.number = self.credit_card_number()
|
||||
self.expire_date = self.expiration_date()
|
||||
self.secure_code = self.security_code()
|
||||
self.account = account
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"\
|
||||
[Numéro de carte] : {self.number}\n\
|
||||
[Date d'expiration] : {self.expire_date}\n\
|
||||
[Code de sécurité] : {self.secure_code}"
|
||||
|
||||
def credit_card_number(self):
|
||||
number = "".join(str(randint(0,9)) for _ in range(16))
|
||||
return " ".join(number[_: _ + 4] for _ in range(0,16,4))
|
||||
|
||||
def security_code(self):
|
||||
return "".join(str(randint(0,9)) for _ in range(3))
|
||||
|
||||
def expiration_date(self):
|
||||
current_date = datetime.now()
|
||||
future_date = current_date.replace(year=current_date.year + 5)
|
||||
return str(future_date.strftime("%m/%y"))
|
||||
|
||||
Base.metadata.create_all(engine)
|
||||
30
Semaine_07/Jour_04/bank/entities/services.py
Normal file
30
Semaine_07/Jour_04/bank/entities/services.py
Normal file
@@ -0,0 +1,30 @@
|
||||
from sqlalchemy import ForeignKey, Column, Integer, String, Float, Table
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from database.connection import Base
|
||||
|
||||
# Table d'association
|
||||
client_service = Table(
|
||||
'client_service',
|
||||
Base.metadata,
|
||||
Column('client_id', Integer, ForeignKey('clients.id'), primary_key= True),
|
||||
Column('service_id', Integer, ForeignKey('clients.id'), primary_key= True)
|
||||
)
|
||||
|
||||
class Service(Base):
|
||||
__tablename__ = "Services"
|
||||
|
||||
id = Column(Integer, primary_key= True, autoincrement= True)
|
||||
name = Column(String(200), nullable= False)
|
||||
description = Column(String(500))
|
||||
monthly_price = Column(Float)
|
||||
|
||||
clients = relationship("Client", back_populates= "services", secondary= client_service)
|
||||
|
||||
def __init__(self, name, description= "", price= 0):
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.monthly_price = price
|
||||
|
||||
def __repr__(self):
|
||||
return f"Service({self.name})"
|
||||
@@ -0,0 +1,51 @@
|
||||
from entities.accounts import Account
|
||||
from entities.banks import Bank
|
||||
from entities.clients import Client, ClientNotFound
|
||||
from entities.credit_cards import CreditCard
|
||||
# from database import create_table
|
||||
|
||||
"""
|
||||
On veut gérer des banques
|
||||
Une banque a comme attributs :
|
||||
- un nom
|
||||
- une liste de clients
|
||||
|
||||
Un client a comme attributs :
|
||||
- un prénom
|
||||
- un nom
|
||||
- un salaire
|
||||
- une ville
|
||||
|
||||
Une banque peut ajouter un client à sa liste, ce qui va créer un compte
|
||||
|
||||
Un compte a :
|
||||
- un numéro à 7 chiffres
|
||||
- un solde initial de 0
|
||||
|
||||
On peut :
|
||||
- déposer de l'argent
|
||||
- retirer de l'argent
|
||||
|
||||
Une banque peut demander unne CB pour un client
|
||||
Une CB a un numéro à 16 chiffres, un code de sécurité de 3 chiffres et une date d'expiration de 5 ans
|
||||
"""
|
||||
|
||||
def create_tables():
|
||||
Base.metadata.create_all(get_engine())
|
||||
|
||||
create_tables()
|
||||
session = get_session()
|
||||
|
||||
# Banques
|
||||
bank_001 = Bank("Crédit Agricool")
|
||||
bank_002 = Bank("Société Géniale")
|
||||
# Clients
|
||||
client_001 = Client("Alex", "TERIEUR", 3000, "Lorient")
|
||||
client_002 = Client("Emma", "TITEGOUTTE", 1750, "Brest")
|
||||
|
||||
session.add(bank_001)
|
||||
session.add(bank_002)
|
||||
session.add(client_001)
|
||||
session.add(client_002)
|
||||
|
||||
session.commit()
|
||||
51
Semaine_07/Jour_04/bank/main.py
Normal file
51
Semaine_07/Jour_04/bank/main.py
Normal file
@@ -0,0 +1,51 @@
|
||||
from entities.accounts import Account
|
||||
from entities.banks import Bank
|
||||
from entities.clients import Client, ClientNotFound
|
||||
from entities.credit_cards import CreditCard
|
||||
from database import create_table
|
||||
|
||||
"""
|
||||
On veut gérer des banques
|
||||
Une banque a comme attributs :
|
||||
- un nom
|
||||
- une liste de clients
|
||||
|
||||
Un client a comme attributs :
|
||||
- un prénom
|
||||
- un nom
|
||||
- un salaire
|
||||
- une ville
|
||||
|
||||
Une banque peut ajouter un client à sa liste, ce qui va créer un compte
|
||||
|
||||
Un compte a :
|
||||
- un numéro à 7 chiffres
|
||||
- un solde initial de 0
|
||||
|
||||
On peut :
|
||||
- déposer de l'argent
|
||||
- retirer de l'argent
|
||||
|
||||
Une banque peut demander unne CB pour un client
|
||||
Une CB a un numéro à 16 chiffres, un code de sécurité de 3 chiffres et une date d'expiration de 5 ans
|
||||
"""
|
||||
|
||||
def create_tables():
|
||||
Base.metadata.create_all(get_engine())
|
||||
|
||||
create_tables()
|
||||
session = get_session()
|
||||
|
||||
# Banques
|
||||
bank_001 = Bank("Crédit Agricool")
|
||||
bank_002 = Bank("Société Géniale")
|
||||
# Clients
|
||||
client_001 = Client("Alex", "TERIEUR", 3000, "Lorient")
|
||||
client_002 = Client("Emma", "TITEGOUTTE", 1750, "Brest")
|
||||
|
||||
session.add(bank_001)
|
||||
session.add(bank_002)
|
||||
session.add(client_001)
|
||||
session.add(client_002)
|
||||
|
||||
session.commit()
|
||||
9
Semaine_07/Jour_04/bank/pyproject.toml
Normal file
9
Semaine_07/Jour_04/bank/pyproject.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
[project]
|
||||
name = "bank"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
"sqlalchemy>=2.0.48",
|
||||
]
|
||||
108
Semaine_07/Jour_04/bank/uv.lock
generated
Normal file
108
Semaine_07/Jour_04/bank/uv.lock
generated
Normal file
@@ -0,0 +1,108 @@
|
||||
version = 1
|
||||
revision = 3
|
||||
requires-python = ">=3.12"
|
||||
|
||||
[[package]]
|
||||
name = "bank"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "sqlalchemy" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [{ name = "sqlalchemy", specifier = ">=2.0.48" }]
|
||||
|
||||
[[package]]
|
||||
name = "greenlet"
|
||||
version = "3.3.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a3/51/1664f6b78fc6ebbd98019a1fd730e83fa78f2db7058f72b1463d3612b8db/greenlet-3.3.2.tar.gz", hash = "sha256:2eaf067fc6d886931c7962e8c6bede15d2f01965560f3359b27c80bde2d151f2", size = 188267, upload-time = "2026-02-20T20:54:15.531Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/ab/1608e5a7578e62113506740b88066bf09888322a311cff602105e619bd87/greenlet-3.3.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:ac8d61d4343b799d1e526db579833d72f23759c71e07181c2d2944e429eb09cd", size = 280358, upload-time = "2026-02-20T20:17:43.971Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a5/23/0eae412a4ade4e6623ff7626e38998cb9b11e9ff1ebacaa021e4e108ec15/greenlet-3.3.2-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ceec72030dae6ac0c8ed7591b96b70410a8be370b6a477b1dbc072856ad02bd", size = 601217, upload-time = "2026-02-20T20:47:31.462Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/16/5b1678a9c07098ecb9ab2dd159fafaf12e963293e61ee8d10ecb55273e5e/greenlet-3.3.2-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a2a5be83a45ce6188c045bcc44b0ee037d6a518978de9a5d97438548b953a1ac", size = 611792, upload-time = "2026-02-20T20:55:58.423Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/1f/5155f55bd71cabd03765a4aac9ac446be129895271f73872c36ebd4b04b6/greenlet-3.3.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43e99d1749147ac21dde49b99c9abffcbc1e2d55c67501465ef0930d6e78e070", size = 613875, upload-time = "2026-02-20T20:21:01.102Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/dd/845f249c3fcd69e32df80cdab059b4be8b766ef5830a3d0aa9d6cad55beb/greenlet-3.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4c956a19350e2c37f2c48b336a3afb4bff120b36076d9d7fb68cb44e05d95b79", size = 1571467, upload-time = "2026-02-20T20:49:33.495Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/50/2649fe21fcc2b56659a452868e695634722a6655ba245d9f77f5656010bf/greenlet-3.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c6f8ba97d17a1e7d664151284cb3315fc5f8353e75221ed4324f84eb162b395", size = 1640001, upload-time = "2026-02-20T20:21:09.154Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/40/cc802e067d02af8b60b6771cea7d57e21ef5e6659912814babb42b864713/greenlet-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:34308836d8370bddadb41f5a7ce96879b72e2fdfb4e87729330c6ab52376409f", size = 231081, upload-time = "2026-02-20T20:17:28.121Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/2e/fe7f36ff1982d6b10a60d5e0740c759259a7d6d2e1dc41da6d96de32fff6/greenlet-3.3.2-cp312-cp312-win_arm64.whl", hash = "sha256:d3a62fa76a32b462a97198e4c9e99afb9ab375115e74e9a83ce180e7a496f643", size = 230331, upload-time = "2026-02-20T20:17:23.34Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ac/48/f8b875fa7dea7dd9b33245e37f065af59df6a25af2f9561efa8d822fde51/greenlet-3.3.2-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:aa6ac98bdfd716a749b84d4034486863fd81c3abde9aa3cf8eff9127981a4ae4", size = 279120, upload-time = "2026-02-20T20:19:01.9Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/49/8d/9771d03e7a8b1ee456511961e1b97a6d77ae1dea4a34a5b98eee706689d3/greenlet-3.3.2-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab0c7e7901a00bc0a7284907273dc165b32e0d109a6713babd04471327ff7986", size = 603238, upload-time = "2026-02-20T20:47:32.873Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/0e/4223c2bbb63cd5c97f28ffb2a8aee71bdfb30b323c35d409450f51b91e3e/greenlet-3.3.2-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d248d8c23c67d2291ffd47af766e2a3aa9fa1c6703155c099feb11f526c63a92", size = 614219, upload-time = "2026-02-20T20:55:59.817Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7a/34/259b28ea7a2a0c904b11cd36c79b8cef8019b26ee5dbe24e73b469dea347/greenlet-3.3.2-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6997d360a4e6a4e936c0f9625b1c20416b8a0ea18a8e19cabbefc712e7397ab", size = 616774, upload-time = "2026-02-20T20:21:02.454Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0a/03/996c2d1689d486a6e199cb0f1cf9e4aa940c500e01bdf201299d7d61fa69/greenlet-3.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:64970c33a50551c7c50491671265d8954046cb6e8e2999aacdd60e439b70418a", size = 1571277, upload-time = "2026-02-20T20:49:34.795Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/c4/2570fc07f34a39f2caf0bf9f24b0a1a0a47bc2e8e465b2c2424821389dfc/greenlet-3.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1a9172f5bf6bd88e6ba5a84e0a68afeac9dc7b6b412b245dd64f52d83c81e55b", size = 1640455, upload-time = "2026-02-20T20:21:10.261Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/91/39/5ef5aa23bc545aa0d31e1b9b55822b32c8da93ba657295840b6b34124009/greenlet-3.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:a7945dd0eab63ded0a48e4dcade82939783c172290a7903ebde9e184333ca124", size = 230961, upload-time = "2026-02-20T20:16:58.461Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/6b/a89f8456dcb06becff288f563618e9f20deed8dd29beea14f9a168aef64b/greenlet-3.3.2-cp313-cp313-win_arm64.whl", hash = "sha256:394ead29063ee3515b4e775216cb756b2e3b4a7e55ae8fd884f17fa579e6b327", size = 230221, upload-time = "2026-02-20T20:17:37.152Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/ae/8bffcbd373b57a5992cd077cbe8858fff39110480a9d50697091faea6f39/greenlet-3.3.2-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:8d1658d7291f9859beed69a776c10822a0a799bc4bfe1bd4272bb60e62507dab", size = 279650, upload-time = "2026-02-20T20:18:00.783Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/c0/45f93f348fa49abf32ac8439938726c480bd96b2a3c6f4d949ec0124b69f/greenlet-3.3.2-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:18cb1b7337bca281915b3c5d5ae19f4e76d35e1df80f4ad3c1a7be91fadf1082", size = 650295, upload-time = "2026-02-20T20:47:34.036Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/de/dd7589b3f2b8372069ab3e4763ea5329940fc7ad9dcd3e272a37516d7c9b/greenlet-3.3.2-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2e47408e8ce1c6f1ceea0dffcdf6ebb85cc09e55c7af407c99f1112016e45e9", size = 662163, upload-time = "2026-02-20T20:56:01.295Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/d8/09bfa816572a4d83bccd6750df1926f79158b1c36c5f73786e26dbe4ee38/greenlet-3.3.2-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63d10328839d1973e5ba35e98cccbca71b232b14051fd957b6f8b6e8e80d0506", size = 664160, upload-time = "2026-02-20T20:21:04.015Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/48/cf/56832f0c8255d27f6c35d41b5ec91168d74ec721d85f01a12131eec6b93c/greenlet-3.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e4ab3cfb02993c8cc248ea73d7dae6cec0253e9afa311c9b37e603ca9fad2ce", size = 1619181, upload-time = "2026-02-20T20:49:36.052Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0a/23/b90b60a4aabb4cec0796e55f25ffbfb579a907c3898cd2905c8918acaa16/greenlet-3.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:94ad81f0fd3c0c0681a018a976e5c2bd2ca2d9d94895f23e7bb1af4e8af4e2d5", size = 1687713, upload-time = "2026-02-20T20:21:11.684Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/ca/2101ca3d9223a1dc125140dbc063644dca76df6ff356531eb27bc267b446/greenlet-3.3.2-cp314-cp314-win_amd64.whl", hash = "sha256:8c4dd0f3997cf2512f7601563cc90dfb8957c0cff1e3a1b23991d4ea1776c492", size = 232034, upload-time = "2026-02-20T20:20:08.186Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f6/4a/ecf894e962a59dea60f04877eea0fd5724618da89f1867b28ee8b91e811f/greenlet-3.3.2-cp314-cp314-win_arm64.whl", hash = "sha256:cd6f9e2bbd46321ba3bbb4c8a15794d32960e3b0ae2cc4d49a1a53d314805d71", size = 231437, upload-time = "2026-02-20T20:18:59.722Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/98/6d/8f2ef704e614bcf58ed43cfb8d87afa1c285e98194ab2cfad351bf04f81e/greenlet-3.3.2-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:e26e72bec7ab387ac80caa7496e0f908ff954f31065b0ffc1f8ecb1338b11b54", size = 286617, upload-time = "2026-02-20T20:19:29.856Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/0d/93894161d307c6ea237a43988f27eba0947b360b99ac5239ad3fe09f0b47/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b466dff7a4ffda6ca975979bab80bdadde979e29fc947ac3be4451428d8b0e4", size = 655189, upload-time = "2026-02-20T20:47:35.742Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/2c/d2d506ebd8abcb57386ec4f7ba20f4030cbe56eae541bc6fd6ef399c0b41/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b8bddc5b73c9720bea487b3bffdb1840fe4e3656fba3bd40aa1489e9f37877ff", size = 658225, upload-time = "2026-02-20T20:56:02.527Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8e/30/3a09155fbf728673a1dea713572d2d31159f824a37c22da82127056c44e4/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b26b0f4428b871a751968285a1ac9648944cea09807177ac639b030bddebcea4", size = 657907, upload-time = "2026-02-20T20:21:05.259Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/fd/d05a4b7acd0154ed758797f0a43b4c0962a843bedfe980115e842c5b2d08/greenlet-3.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1fb39a11ee2e4d94be9a76671482be9398560955c9e568550de0224e41104727", size = 1618857, upload-time = "2026-02-20T20:49:37.309Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/e1/50ee92a5db521de8f35075b5eff060dd43d39ebd46c2181a2042f7070385/greenlet-3.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:20154044d9085151bc309e7689d6f7ba10027f8f5a8c0676ad398b951913d89e", size = 1680010, upload-time = "2026-02-20T20:21:13.427Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/29/4b/45d90626aef8e65336bed690106d1382f7a43665e2249017e9527df8823b/greenlet-3.3.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c04c5e06ec3e022cbfe2cd4a846e1d4e50087444f875ff6d2c2ad8445495cf1a", size = 237086, upload-time = "2026-02-20T20:20:45.786Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlalchemy"
|
||||
version = "2.0.48"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "greenlet", marker = "platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/1f/73/b4a9737255583b5fa858e0bb8e116eb94b88c910164ed2ed719147bde3de/sqlalchemy-2.0.48.tar.gz", hash = "sha256:5ca74f37f3369b45e1f6b7b06afb182af1fd5dde009e4ffd831830d98cbe5fe7", size = 9886075, upload-time = "2026-03-02T15:28:51.474Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/91/a42ae716f8925e9659df2da21ba941f158686856107a61cc97a95e7647a3/sqlalchemy-2.0.48-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:348174f228b99f33ca1f773e85510e08927620caa59ffe7803b37170df30332b", size = 2155737, upload-time = "2026-03-02T15:49:13.207Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/52/f75f516a1f3888f027c1cfb5d22d4376f4b46236f2e8669dcb0cddc60275/sqlalchemy-2.0.48-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53667b5f668991e279d21f94ccfa6e45b4e3f4500e7591ae59a8012d0f010dcb", size = 3337020, upload-time = "2026-03-02T15:50:34.547Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/37/9a/0c28b6371e0cdcb14f8f1930778cb3123acfcbd2c95bb9cf6b4a2ba0cce3/sqlalchemy-2.0.48-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34634e196f620c7a61d18d5cf7dc841ca6daa7961aed75d532b7e58b309ac894", size = 3349983, upload-time = "2026-03-02T15:53:25.542Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1c/46/0aee8f3ff20b1dcbceb46ca2d87fcc3d48b407925a383ff668218509d132/sqlalchemy-2.0.48-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:546572a1793cc35857a2ffa1fe0e58571af1779bcc1ffa7c9fb0839885ed69a9", size = 3279690, upload-time = "2026-03-02T15:50:36.277Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/8c/a957bc91293b49181350bfd55e6dfc6e30b7f7d83dc6792d72043274a390/sqlalchemy-2.0.48-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:07edba08061bc277bfdc772dd2a1a43978f5a45994dd3ede26391b405c15221e", size = 3314738, upload-time = "2026-03-02T15:53:27.519Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/44/1d257d9f9556661e7bdc83667cc414ba210acfc110c82938cb3611eea58f/sqlalchemy-2.0.48-cp312-cp312-win32.whl", hash = "sha256:908a3fa6908716f803b86896a09a2c4dde5f5ce2bb07aacc71ffebb57986ce99", size = 2115546, upload-time = "2026-03-02T15:54:31.591Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/af/c3c7e1f3a2b383155a16454df62ae8c62a30dd238e42e68c24cebebbfae6/sqlalchemy-2.0.48-cp312-cp312-win_amd64.whl", hash = "sha256:68549c403f79a8e25984376480959975212a670405e3913830614432b5daa07a", size = 2142484, upload-time = "2026-03-02T15:54:34.072Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/c6/569dc8bf3cd375abc5907e82235923e986799f301cd79a903f784b996fca/sqlalchemy-2.0.48-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e3070c03701037aa418b55d36532ecb8f8446ed0135acb71c678dbdf12f5b6e4", size = 2152599, upload-time = "2026-03-02T15:49:14.41Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/ff/f4e04a4bd5a24304f38cb0d4aa2ad4c0fb34999f8b884c656535e1b2b74c/sqlalchemy-2.0.48-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2645b7d8a738763b664a12a1542c89c940daa55196e8d73e55b169cc5c99f65f", size = 3278825, upload-time = "2026-03-02T15:50:38.269Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/88/cb59509e4668d8001818d7355d9995be90c321313078c912420603a7cb95/sqlalchemy-2.0.48-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b19151e76620a412c2ac1c6f977ab1b9fa7ad43140178345136456d5265b32ed", size = 3295200, upload-time = "2026-03-02T15:53:29.366Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/dc/1609a4442aefd750ea2f32629559394ec92e89ac1d621a7f462b70f736ff/sqlalchemy-2.0.48-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5b193a7e29fd9fa56e502920dca47dffe60f97c863494946bd698c6058a55658", size = 3226876, upload-time = "2026-03-02T15:50:39.802Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/37/c3/6ae2ab5ea2fa989fbac4e674de01224b7a9d744becaf59bb967d62e99bed/sqlalchemy-2.0.48-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:36ac4ddc3d33e852da9cb00ffb08cea62ca05c39711dc67062ca2bb1fae35fd8", size = 3265045, upload-time = "2026-03-02T15:53:31.421Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/82/ea4665d1bb98c50c19666e672f21b81356bd6077c4574e3d2bbb84541f53/sqlalchemy-2.0.48-cp313-cp313-win32.whl", hash = "sha256:389b984139278f97757ea9b08993e7b9d1142912e046ab7d82b3fbaeb0209131", size = 2113700, upload-time = "2026-03-02T15:54:35.825Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/2b/b9040bec58c58225f073f5b0c1870defe1940835549dafec680cbd58c3c3/sqlalchemy-2.0.48-cp313-cp313-win_amd64.whl", hash = "sha256:d612c976cbc2d17edfcc4c006874b764e85e990c29ce9bd411f926bbfb02b9a2", size = 2139487, upload-time = "2026-03-02T15:54:37.079Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/f4/7b17bd50244b78a49d22cc63c969d71dc4de54567dc152a9b46f6fae40ce/sqlalchemy-2.0.48-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:69f5bc24904d3bc3640961cddd2523e361257ef68585d6e364166dfbe8c78fae", size = 3558851, upload-time = "2026-03-02T15:57:48.607Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/0d/213668e9aca61d370f7d2a6449ea4ec699747fac67d4bda1bb3d129025be/sqlalchemy-2.0.48-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fd08b90d211c086181caed76931ecfa2bdfc83eea3cfccdb0f82abc6c4b876cb", size = 3525525, upload-time = "2026-03-02T16:04:38.058Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/d7/a84edf412979e7d59c69b89a5871f90a49228360594680e667cb2c46a828/sqlalchemy-2.0.48-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:1ccd42229aaac2df431562117ac7e667d702e8e44afdb6cf0e50fa3f18160f0b", size = 3466611, upload-time = "2026-03-02T15:57:50.759Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/86/55/42404ce5770f6be26a2b0607e7866c31b9a4176c819e9a7a5e0a055770be/sqlalchemy-2.0.48-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f0dcbc588cd5b725162c076eb9119342f6579c7f7f55057bb7e3c6ff27e13121", size = 3475812, upload-time = "2026-03-02T16:04:40.092Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/ae/29b87775fadc43e627cf582fe3bda4d02e300f6b8f2747c764950d13784c/sqlalchemy-2.0.48-cp313-cp313t-win32.whl", hash = "sha256:9764014ef5e58aab76220c5664abb5d47d5bc858d9debf821e55cfdd0f128485", size = 2141335, upload-time = "2026-03-02T15:52:51.518Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/91/44/f39d063c90f2443e5b46ec4819abd3d8de653893aae92df42a5c4f5843de/sqlalchemy-2.0.48-cp313-cp313t-win_amd64.whl", hash = "sha256:e2f35b4cccd9ed286ad62e0a3c3ac21e06c02abc60e20aa51a3e305a30f5fa79", size = 2173095, upload-time = "2026-03-02T15:52:52.79Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/b3/f437eaa1cf028bb3c927172c7272366393e73ccd104dcf5b6963f4ab5318/sqlalchemy-2.0.48-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:e2d0d88686e3d35a76f3e15a34e8c12d73fc94c1dea1cd55782e695cc14086dd", size = 2154401, upload-time = "2026-03-02T15:49:17.24Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/1c/b3abdf0f402aa3f60f0df6ea53d92a162b458fca2321d8f1f00278506402/sqlalchemy-2.0.48-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49b7bddc1eebf011ea5ab722fdbe67a401caa34a350d278cc7733c0e88fecb1f", size = 3274528, upload-time = "2026-03-02T15:50:41.489Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/5e/327428a034407651a048f5e624361adf3f9fbac9d0fa98e981e9c6ff2f5e/sqlalchemy-2.0.48-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:426c5ca86415d9b8945c7073597e10de9644802e2ff502b8e1f11a7a2642856b", size = 3279523, upload-time = "2026-03-02T15:53:32.962Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/ca/ece73c81a918add0965b76b868b7b5359e068380b90ef1656ee995940c02/sqlalchemy-2.0.48-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:288937433bd44e3990e7da2402fabc44a3c6c25d3704da066b85b89a85474ae0", size = 3224312, upload-time = "2026-03-02T15:50:42.996Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/11/fbaf1ae91fa4ee43f4fe79661cead6358644824419c26adb004941bdce7c/sqlalchemy-2.0.48-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:8183dc57ae7d9edc1346e007e840a9f3d6aa7b7f165203a99e16f447150140d2", size = 3246304, upload-time = "2026-03-02T15:53:34.937Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/a8/5fb0deb13930b4f2f698c5541ae076c18981173e27dd00376dbaea7a9c82/sqlalchemy-2.0.48-cp314-cp314-win32.whl", hash = "sha256:1182437cb2d97988cfea04cf6cdc0b0bb9c74f4d56ec3d08b81e23d621a28cc6", size = 2116565, upload-time = "2026-03-02T15:54:38.321Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/95/7e/e83615cb63f80047f18e61e31e8e32257d39458426c23006deeaf48f463b/sqlalchemy-2.0.48-cp314-cp314-win_amd64.whl", hash = "sha256:144921da96c08feb9e2b052c5c5c1d0d151a292c6135623c6b2c041f2a45f9e0", size = 2142205, upload-time = "2026-03-02T15:54:39.831Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/e3/69d8711b3f2c5135e9cde5f063bc1605860f0b2c53086d40c04017eb1f77/sqlalchemy-2.0.48-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5aee45fd2c6c0f2b9cdddf48c48535e7471e42d6fb81adfde801da0bd5b93241", size = 3563519, upload-time = "2026-03-02T15:57:52.387Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/4f/a7cce98facca73c149ea4578981594aaa5fd841e956834931de503359336/sqlalchemy-2.0.48-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7cddca31edf8b0653090cbb54562ca027c421c58ddde2c0685f49ff56a1690e0", size = 3528611, upload-time = "2026-03-02T16:04:42.097Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cd/7d/5936c7a03a0b0cb0fa0cc425998821c6029756b0855a8f7ee70fba1de955/sqlalchemy-2.0.48-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7a936f1bb23d370b7c8cc079d5fce4c7d18da87a33c6744e51a93b0f9e97e9b3", size = 3472326, upload-time = "2026-03-02T15:57:54.423Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/33/cea7dfc31b52904efe3dcdc169eb4514078887dff1f5ae28a7f4c5d54b3c/sqlalchemy-2.0.48-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e004aa9248e8cb0a5f9b96d003ca7c1c0a5da8decd1066e7b53f59eb8ce7c62b", size = 3478453, upload-time = "2026-03-02T16:04:44.584Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/95/32107c4d13be077a9cae61e9ae49966a35dc4bf442a8852dd871db31f62e/sqlalchemy-2.0.48-cp314-cp314t-win32.whl", hash = "sha256:b8438ec5594980d405251451c5b7ea9aa58dda38eb7ac35fb7e4c696712ee24f", size = 2147209, upload-time = "2026-03-02T15:52:54.274Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/d7/1e073da7a4bc645eb83c76067284a0374e643bc4be57f14cc6414656f92c/sqlalchemy-2.0.48-cp314-cp314t-win_amd64.whl", hash = "sha256:d854b3970067297f3a7fbd7a4683587134aa9b3877ee15aa29eea478dc68f933", size = 2182198, upload-time = "2026-03-02T15:52:55.606Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/2c/9664130905f03db57961b8980b05cab624afd114bf2be2576628a9f22da4/sqlalchemy-2.0.48-py3-none-any.whl", hash = "sha256:a66fe406437dd65cacd96a72689a3aaaecaebbcd62d81c5ac1c0fdbeac835096", size = 1940202, upload-time = "2026-03-02T15:52:43.285Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.15.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
|
||||
]
|
||||
1
Semaine_07/Jour_05/Boiche_Gauvain_eval_20_03_2026/.env
Normal file
1
Semaine_07/Jour_05/Boiche_Gauvain_eval_20_03_2026/.env
Normal file
@@ -0,0 +1 @@
|
||||
DB_PASSWORD=MementoMarsouin96
|
||||
@@ -0,0 +1 @@
|
||||
3.12
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,4 @@
|
||||
DB_HOST=localhost
|
||||
DB_USER=root
|
||||
DB_PASSWORD=MementoMarsouin96
|
||||
DB_NAME=petcare
|
||||
@@ -0,0 +1,23 @@
|
||||
from peewee import *
|
||||
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
db_name = os.environ.get("DB_NAME")
|
||||
db_user = os.environ.get("DB_USER")
|
||||
db_password = os.environ.get("DB_PASSWORD")
|
||||
db_host = os.environ.get("DB_HOST")
|
||||
|
||||
db = MySQLDatabase(
|
||||
database= db_name,
|
||||
user= db_user,
|
||||
password= db_password,
|
||||
host= db_host,
|
||||
port= 3306
|
||||
)
|
||||
|
||||
class BaseModel(Model):
|
||||
class Meta:
|
||||
database = db
|
||||
@@ -0,0 +1,10 @@
|
||||
from __init__ import *
|
||||
|
||||
class Care(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
nom = CharField(max_length= 150, null= False)
|
||||
description = TextField()
|
||||
prix = DecimalField(max_digits= 6, decimal_places= 2)
|
||||
|
||||
class Meta:
|
||||
table_name = "traitement"
|
||||
@@ -0,0 +1,27 @@
|
||||
from __init__ import *
|
||||
from classes.pet import Pet
|
||||
from classes.veterinarian import Veterinarian
|
||||
from classes.care import Care
|
||||
|
||||
class Consultation(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
date_consultation = DateField(formats= '%Y-%m-%d') # formats= '%Y-%m-%d %H:%M:%S
|
||||
motif = CharField(max_length= 255, null= False)
|
||||
diagnostic = TextField()
|
||||
prix_consultation = DecimalField(max_digits= 6, decimal_places= 2)
|
||||
|
||||
animal = ForeignKeyField(Pet, backref= "animal", null= False)
|
||||
veterinaire = ForeignKeyField(Veterinarian, backref= "veterinaire", null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "consultation"
|
||||
|
||||
class ConsultationCare(BaseModel):
|
||||
consultation = ForeignKeyField(Consultation)
|
||||
traitement = ForeignKeyField(Care)
|
||||
|
||||
class Meta:
|
||||
table_name = "consultation_traitement"
|
||||
indexes= (
|
||||
(("consultation", "traitement"), True),
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
from __init__ import *
|
||||
|
||||
class Owner(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
prenom = CharField(max_length= 100, null= False)
|
||||
nom = CharField(max_length= 100, null= False)
|
||||
telephone = CharField(max_length= 15, null= False)
|
||||
email = CharField(max_length= 150, null= False, unique= True)
|
||||
ville = CharField(max_length= 100, null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "proprietaire"
|
||||
@@ -0,0 +1,15 @@
|
||||
from __init__ import *
|
||||
from classes.owner import Owner
|
||||
|
||||
class Pet(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
nom = CharField(max_length= 100, null= False)
|
||||
espece = CharField(max_length= 50, null= False)
|
||||
race = CharField(max_length= 100, null= False)
|
||||
date_naissance = DateField(formats= '%Y-%m-%d')
|
||||
poids = DecimalField(max_digits= 5, decimal_places= 2)
|
||||
|
||||
proprietaire = ForeignKeyField(Owner, backref= "proprietaire", null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "animal"
|
||||
@@ -0,0 +1,11 @@
|
||||
from __init__ import *
|
||||
|
||||
class Veterinarian(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
prenom = CharField(max_length= 100, null= False)
|
||||
nom = CharField(max_length= 100, null= False)
|
||||
specialite = CharField(max_length= 100, null= False, unique= True)
|
||||
telephone = CharField(max_length= 15, null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "veterinaire"
|
||||
@@ -0,0 +1,127 @@
|
||||
from __init__ import *
|
||||
|
||||
# 1. Modèles
|
||||
|
||||
from classes.care import *
|
||||
from classes.consultation import *
|
||||
from classes.owner import *
|
||||
from classes.pet import *
|
||||
from classes.veterinarian import *
|
||||
|
||||
# 2. CRUD
|
||||
|
||||
## 1. CREATE
|
||||
|
||||
try:
|
||||
with db.atomic():
|
||||
owner_01 = Owner.create(
|
||||
prenom= "Camille",
|
||||
nom= "LEMOINE",
|
||||
telephone= "0656781234",
|
||||
email= "camille.lemoine@mail.com",
|
||||
ville= "Bordeaux"
|
||||
)
|
||||
pet_01 = Pet.create(
|
||||
nom= "Pixel",
|
||||
espece= "Chat",
|
||||
race= "Bengal",
|
||||
date_naissance= "2023-06-15",
|
||||
poids= 4.5,
|
||||
proprietaire= owner_01
|
||||
)
|
||||
veterinarian_01_girard = Veterinarian.get(3)
|
||||
consultation_01 = Consultation.create(
|
||||
date_consultation= "2025-05-15",
|
||||
motif= "Première visite",
|
||||
diagnostic= "RAS",
|
||||
prix_consultation= 35.00,
|
||||
animal= pet_01,
|
||||
veterinaire= veterinarian_01_girard
|
||||
)
|
||||
|
||||
care_01_vermifuge = Care.get(Care.nom == "Vermifuge")
|
||||
care_01_puce_elec = Care.get(10)
|
||||
|
||||
ConsultationCare.create(consultation= consultation_01, traitement= care_01_vermifuge)
|
||||
ConsultationCare.create(consultation= consultation_01, traitement= care_01_puce_elec)
|
||||
except IntegrityError as error:
|
||||
print(error)
|
||||
|
||||
## 2. READ
|
||||
|
||||
print("\n----- Animaux de Claire MARTIN -----")
|
||||
claire_martin_pets = Pet.select().join(Owner).where(
|
||||
(Owner.prenom == "Claire") &
|
||||
(Owner.nom == "Martin")
|
||||
)
|
||||
for pet in claire_martin_pets:
|
||||
print(f"{pet.nom} - {pet.espece} - {pet.poids}")
|
||||
|
||||
print("\n----- Consultations de REX -----")
|
||||
claire_martin_rex_consultations = Consultation\
|
||||
.select(Consultation, Veterinarian)\
|
||||
.join(Veterinarian)\
|
||||
.where(Consultation.animal == 1)
|
||||
for consultation in claire_martin_rex_consultations:
|
||||
print(f"{consultation.date_consultation} - {consultation.motif} - Dr {consultation.veterinaire.nom}")
|
||||
|
||||
print("\n----- Statistiques par espèce -----")
|
||||
# Partie faite à l'aide de l'IA, notamment pour le "group_by" avant quoi je n'avais que "Chien" sans explication
|
||||
# et qui m'a soufflé l'idée de l'alias qui est quand même bien pratique
|
||||
stats_species = Pet.select(
|
||||
Pet.espece,
|
||||
fn.COUNT(Pet.id).alias("nb_pets"),
|
||||
fn.AVG(Pet.poids).alias("avg_weight")
|
||||
).group_by(Pet.espece)
|
||||
for stat in stats_species:
|
||||
print(f"{stat.nb_pets} {stat.espece}(s) au total - {round(stat.avg_weight, 2)}kg en moyenne")
|
||||
|
||||
## 3. UPDATE
|
||||
|
||||
print("\n----- Le Gros Buddy qui mange trop -----")
|
||||
try:
|
||||
pet_buddy = Pet.get(Pet.nom == "Buddy")
|
||||
print(f"Le poids de {pet_buddy.nom} est enregistré comme étant de {pet_buddy.poids}kg.")
|
||||
pet_buddy.poids = 29.50
|
||||
pet_buddy.save()
|
||||
print(f"Le poids de Buddy a été changé.")
|
||||
print(f"Le poids de {pet_buddy.nom} est enregistré comme étant de {pet_buddy.poids}kg.")
|
||||
except DoesNotExist:
|
||||
print("L'animal \"Buddy\" n'existe pas.")
|
||||
|
||||
## 4. DELETE
|
||||
|
||||
print("\n----- Vous z'avez pas vu mon fils ? -----")
|
||||
try:
|
||||
pet_nemo = Pet.get(Pet.nom == "Nemo")
|
||||
had_nemo_consultations = Consultation.select().where(Consultation.animal == pet_nemo).count()
|
||||
|
||||
if had_nemo_consultations > 0:
|
||||
print(f"Impossible de supprimer {pet_nemo.nom}, il possède des consultations associées.")
|
||||
else:
|
||||
pet_nemo.delete_instance()
|
||||
print(f"L'animal {pet_nemo.nom} a été supprimé de la base de données.")
|
||||
except DoesNotExist:
|
||||
print(f"L'animal \"Nemo\" n'a pas été trouvé dans la base de données.")
|
||||
|
||||
# 3. Requêtes avancées
|
||||
|
||||
print("\n----- Top 3 soigneurs de zanimaux -----")
|
||||
top_veterinarians = Veterinarian\
|
||||
.select(
|
||||
Veterinarian.nom,
|
||||
Veterinarian.specialite,
|
||||
fn.COUNT(Consultation.id).alias("nb_cons")
|
||||
)\
|
||||
.join(Consultation)\
|
||||
.group_by(Veterinarian.id)\
|
||||
.order_by(fn.COUNT(Consultation.id)\
|
||||
.desc()).limit(3)
|
||||
for idx, veterinarian in enumerate(top_veterinarians):
|
||||
print(f"{idx+1} - Dr {veterinarian.nom} avec {veterinarian.nb_cons} consultations.")
|
||||
|
||||
print("\n----- Facture n°1 détaillée -----")
|
||||
|
||||
|
||||
print("\n----- Historique-Animal -----")
|
||||
def historique_animal():
|
||||
@@ -0,0 +1,142 @@
|
||||
CREATE DATABASE IF NOT EXISTS petcare;
|
||||
USE petcare;
|
||||
|
||||
CREATE TABLE proprietaire (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
nom VARCHAR(100) NOT NULL,
|
||||
prenom VARCHAR(100) NOT NULL,
|
||||
telephone VARCHAR(15) NOT NULL,
|
||||
email VARCHAR(150) UNIQUE,
|
||||
ville VARCHAR(100) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE veterinaire (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
nom VARCHAR(100) NOT NULL,
|
||||
prenom VARCHAR(100) NOT NULL,
|
||||
specialite VARCHAR(100) NOT NULL,
|
||||
telephone VARCHAR(15) NOT NULL UNIQUE
|
||||
);
|
||||
|
||||
CREATE TABLE animal (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
nom VARCHAR(100) NOT NULL,
|
||||
espece VARCHAR(50) NOT NULL,
|
||||
race VARCHAR(100),
|
||||
date_naissance DATE,
|
||||
poids DECIMAL(5,2) CHECK (poids > 0),
|
||||
proprietaire_id INT NOT NULL,
|
||||
FOREIGN KEY (proprietaire_id) REFERENCES proprietaire(id)
|
||||
);
|
||||
|
||||
CREATE TABLE consultation (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
date_consultation DATE NOT NULL,
|
||||
motif VARCHAR(255) NOT NULL,
|
||||
diagnostic TEXT,
|
||||
prix_consultation DECIMAL(6,2) NOT NULL DEFAULT 35.00 CHECK (prix_consultation > 0),
|
||||
animal_id INT NOT NULL,
|
||||
veterinaire_id INT NOT NULL,
|
||||
FOREIGN KEY (animal_id) REFERENCES animal(id),
|
||||
FOREIGN KEY (veterinaire_id) REFERENCES veterinaire(id)
|
||||
);
|
||||
|
||||
CREATE TABLE traitement (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
nom VARCHAR(150) NOT NULL,
|
||||
description TEXT,
|
||||
prix DECIMAL(6,2) NOT NULL CHECK (prix > 0)
|
||||
);
|
||||
|
||||
CREATE TABLE consultation_traitement (
|
||||
consultation_id INT,
|
||||
traitement_id INT,
|
||||
dosage VARCHAR(100),
|
||||
PRIMARY KEY (consultation_id, traitement_id),
|
||||
FOREIGN KEY (consultation_id) REFERENCES consultation(id),
|
||||
FOREIGN KEY (traitement_id) REFERENCES traitement(id)
|
||||
);
|
||||
|
||||
-- Propriétaires
|
||||
INSERT INTO proprietaire (nom, prenom, telephone, email, ville) VALUES
|
||||
('Martin', 'Claire', '0612345678', 'claire.martin@mail.com', 'Paris'),
|
||||
('Dupont', 'Jean', '0698765432', 'jean.dupont@mail.com', 'Lyon'),
|
||||
('Bernard', 'Sophie', '0654321987', 'sophie.bernard@mail.com', 'Paris'),
|
||||
('Petit', 'Thomas', '0687654321', 'thomas.petit@mail.com', 'Marseille'),
|
||||
('Moreau', 'Julie', '0676543210', 'julie.moreau@mail.com', 'Lyon'),
|
||||
('Garcia', 'Pierre', '0665432109', NULL, 'Toulouse'),
|
||||
('Roux', 'Isabelle', '0643219876', 'isabelle.roux@mail.com', 'Paris');
|
||||
|
||||
-- Vétérinaires
|
||||
INSERT INTO veterinaire (nom, prenom, specialite, telephone) VALUES
|
||||
('Leroy', 'Marc', 'Chirurgie', '0611111111'),
|
||||
('Fabre', 'Anne', 'Dermatologie', '0622222222'),
|
||||
('Girard', 'Paul', 'Médecine générale', '0633333333'),
|
||||
('Duval', 'Marie', 'Comportement', '0644444444');
|
||||
|
||||
-- Animaux
|
||||
INSERT INTO animal (nom, espece, race, date_naissance, poids, proprietaire_id) VALUES
|
||||
('Rex', 'Chien', 'Berger Allemand', '2020-03-15', 32.50, 1),
|
||||
('Mimi', 'Chat', 'Siamois', '2019-07-22', 4.20, 1),
|
||||
('Buddy', 'Chien', 'Labrador', '2021-01-10', 28.00, 2),
|
||||
('Luna', 'Chat', 'Persan', '2022-05-18', 3.80, 3),
|
||||
('Rocky', 'Chien', 'Bulldog', '2020-11-03', 22.50, 4),
|
||||
('Nemo', 'Poisson', 'Poisson clown', '2023-01-01', 0.02, 4),
|
||||
('Bella', 'Chien', 'Golden Retriever', '2019-09-14', 30.00, 5),
|
||||
('Caramel', 'Chat', 'Européen', '2021-08-25', 5.10, 5),
|
||||
('Max', 'Chien', 'Husky', '2022-02-28', 25.00, 6),
|
||||
('Coco', 'Perroquet', 'Ara', '2018-04-12', 1.20, 7),
|
||||
('Filou', 'Chat', 'Maine Coon', '2020-06-30', 7.50, 7),
|
||||
('Oscar', 'Chien', 'Caniche', '2023-03-20', 8.00, 2);
|
||||
|
||||
-- Traitements
|
||||
INSERT INTO traitement (nom, description, prix) VALUES
|
||||
('Vaccination rage', 'Vaccin antirabique annuel', 45.00),
|
||||
('Vaccination typhus', 'Vaccin contre le typhus félin', 40.00),
|
||||
('Vermifuge', 'Traitement antiparasitaire interne', 25.00),
|
||||
('Anti-puces', 'Traitement antiparasitaire externe', 30.00),
|
||||
('Détartrage', 'Nettoyage dentaire sous anesthésie', 80.00),
|
||||
('Radiographie', 'Examen radiologique', 60.00),
|
||||
('Analyse sanguine', 'Bilan sanguin complet', 55.00),
|
||||
('Antibiotiques', 'Traitement antibactérien 10 jours', 35.00),
|
||||
('Castration', 'Stérilisation chirurgicale', 120.00),
|
||||
('Puce électronique', 'Identification par puce', 50.00);
|
||||
|
||||
-- Consultations
|
||||
INSERT INTO consultation (date_consultation, motif, diagnostic, prix_consultation, animal_id, veterinaire_id) VALUES
|
||||
('2025-01-15', 'Visite annuelle', 'Bon état général', 35.00, 1, 1),
|
||||
('2025-01-20', 'Boiterie', 'Entorse légère patte avant droite', 35.00, 3, 1),
|
||||
('2025-02-10', 'Mauvaise haleine', 'Tartre important', 35.00, 2, 2),
|
||||
('2025-02-14', 'Perte de poils', 'Allergie alimentaire', 45.00, 4, 2),
|
||||
('2025-03-01', 'Vaccination', 'RAS', 35.00, 5, 3),
|
||||
('2025-03-05', 'Griffures', 'Infection cutanée légère', 35.00, 8, 2),
|
||||
('2025-03-10', 'Visite annuelle', 'Surpoids léger', 35.00, 7, 3),
|
||||
('2025-03-15', 'Apathie', 'Anémie légère', 45.00, 11, 3),
|
||||
('2025-04-01', 'Comportement agressif', 'Stress environnemental', 50.00, 9, 4),
|
||||
('2025-04-10', 'Visite annuelle', 'Bon état général', 35.00, 10, 3),
|
||||
('2025-04-15', 'Vomissements', 'Gastrite', 35.00, 12, 1),
|
||||
('2025-04-20', 'Visite de contrôle', 'Guérison confirmée', 35.00, 3, 1),
|
||||
('2025-05-01', 'Vaccination rappel', 'RAS', 35.00, 1, 3);
|
||||
|
||||
-- Consultations-Traitements
|
||||
INSERT INTO consultation_traitement (consultation_id, traitement_id, dosage) VALUES
|
||||
(1, 1, '1 injection'),
|
||||
(1, 3, '1 comprimé'),
|
||||
(2, 6, '2 clichés'),
|
||||
(2, 8, '1 comprimé/jour pendant 5 jours'),
|
||||
(3, 5, 'Séance complète'),
|
||||
(4, 7, 'Prélèvement standard'),
|
||||
(4, 4, 'Application locale'),
|
||||
(5, 1, '1 injection'),
|
||||
(5, 10, 'Implantation épaule gauche'),
|
||||
(6, 8, '1 comprimé/jour pendant 7 jours'),
|
||||
(6, 4, 'Application locale'),
|
||||
(7, 3, '1 comprimé'),
|
||||
(7, 7, 'Prélèvement standard'),
|
||||
(8, 7, 'Prélèvement standard'),
|
||||
(9, 7, 'Prélèvement standard'),
|
||||
(10, 3, '1 comprimé'),
|
||||
(11, 8, '1 comprimé/jour pendant 5 jours'),
|
||||
(12, 6, '1 cliché'),
|
||||
(13, 1, '1 injection'),
|
||||
(13, 3, '1 comprimé');
|
||||
@@ -0,0 +1,4 @@
|
||||
DB_HOST=localhost
|
||||
DB_USER=root
|
||||
DB_PASSWORD=MementoMarsouin96
|
||||
DB_NAME=datacenters
|
||||
@@ -0,0 +1,23 @@
|
||||
from peewee import *
|
||||
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
db_name = os.environ.get("DB_NAME")
|
||||
db_user = os.environ.get("DB_USER")
|
||||
db_password = os.environ.get("DB_PASSWORD")
|
||||
db_host = os.environ.get("DB_HOST")
|
||||
|
||||
db = MySQLDatabase(
|
||||
database= db_name,
|
||||
user= db_user,
|
||||
password= db_password,
|
||||
host= db_host,
|
||||
port= 3306
|
||||
)
|
||||
|
||||
class BaseModel(Model):
|
||||
class Meta:
|
||||
database = db
|
||||
@@ -0,0 +1,11 @@
|
||||
from __init__ import *
|
||||
|
||||
class Client(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
nom = CharField(max_length= 150, null= False)
|
||||
email = CharField(max_length= 200, null= False)
|
||||
telephone = CharField(max_length= 20, null= False)
|
||||
type_contrat = CharField(max_length= 50, null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "client"
|
||||
@@ -0,0 +1,12 @@
|
||||
from __init__ import *
|
||||
|
||||
class Datacenter(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
nom = CharField(max_length= 100, null= False)
|
||||
ville = CharField(max_length= 100, null= False)
|
||||
pays = CharField(max_length= 100, null= False)
|
||||
capacite_racks = IntegerField(null= False)
|
||||
annee_ouverture = IntegerField(null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "datacenter"
|
||||
@@ -0,0 +1,15 @@
|
||||
from __init__ import *
|
||||
from classes.client import Client
|
||||
from classes.servers import Serveur
|
||||
|
||||
class Hebergement(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
date_debut = DateField(formats= "%Y-%m-%d", null= False)
|
||||
date_fin = DateField(formats= "%Y-%m-%d", null= True)
|
||||
prix_mensuel = DecimalField(max_digits= 8, decimal_places= 2, null= False)
|
||||
|
||||
serveur = ForeignKeyField(Serveur, backref= "serveur", null= False)
|
||||
client = ForeignKeyField(Client, backref= "client", null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "hebergement"
|
||||
@@ -0,0 +1,15 @@
|
||||
from __init__ import *
|
||||
from classes.servers import Serveur
|
||||
|
||||
class Intervention(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
date_intervention = DateField(formats= "%Y-%m-%d")
|
||||
type_intervention = CharField(max_length= 100, null= False)
|
||||
description = TextField()
|
||||
duree_heures = DecimalField(max_digits= 4, decimal_places= 2, null= False)
|
||||
cout = DecimalField(max_digits= 8, decimal_places= 2, null= False)
|
||||
|
||||
serveur = ForeignKeyField(Serveur, backref= "serveur", null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "intervention"
|
||||
@@ -0,0 +1,14 @@
|
||||
from __init__ import *
|
||||
from classes.datacenter import Datacenter
|
||||
|
||||
class Salle(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
nom = CharField(max_length= 100, null= False)
|
||||
etage = IntegerField(null= False)
|
||||
superficie_m2 = DecimalField(max_digits= 7, decimal_places= 2, null= False)
|
||||
nb_racks = IntegerField(null= False)
|
||||
|
||||
datacenter = ForeignKeyField(Datacenter, backref= "datacenter", null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "salle"
|
||||
@@ -0,0 +1,17 @@
|
||||
from __init__ import *
|
||||
from classes.salle import Salle
|
||||
|
||||
class Serveur(BaseModel):
|
||||
id = AutoField(primary_key= True)
|
||||
hostname = CharField(max_length= 100, null= False)
|
||||
marque = CharField(max_length= 100, null= False)
|
||||
modele = CharField(max_length= 100, null= False)
|
||||
cpu_cores = IntegerField(null= False)
|
||||
ram_go = IntegerField(null= False)
|
||||
stockage_to = DecimalField(max_digits= 5, decimal_places= 2, null= False)
|
||||
date_installation = DateField(formats= "%Y-%m-%d")
|
||||
|
||||
salle = ForeignKeyField(Salle, backref= "salle", null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "serveur"
|
||||
@@ -0,0 +1,115 @@
|
||||
from __init__ import *
|
||||
|
||||
from classes.client import *
|
||||
from classes.datacenter import *
|
||||
from classes.hosting import *
|
||||
from classes.intervention import *
|
||||
from classes.salle import *
|
||||
from classes.servers import *
|
||||
|
||||
# 1. Requêtes de base
|
||||
|
||||
print("\n----- Datacenters en France par année d'ouverture -----")
|
||||
datacenters_france = (Datacenter
|
||||
.select(Datacenter.nom, Datacenter.ville)
|
||||
.where(Datacenter.pays == "France")
|
||||
.order_by(Datacenter.annee_ouverture))
|
||||
for datacenter in datacenters_france:
|
||||
print(f"{datacenter.nom} - {datacenter.ville}")
|
||||
|
||||
print("\n----- Serveurs Dell par nom d'hôte -----")
|
||||
dell_servers = (Serveur
|
||||
.select(Serveur.hostname, Serveur.modele, Serveur.cpu_cores)
|
||||
.where(Serveur.marque == 'Dell')
|
||||
.order_by(Serveur.hostname))
|
||||
for serveur in dell_servers:
|
||||
print(f"{serveur.hostname} - Modèle {serveur.modele} - {serveur.cpu_cores} coeurs")
|
||||
|
||||
print("\n----- Interventions de mars 2025 -----")
|
||||
march_2025_interventions = (Intervention
|
||||
.select(Intervention.type_intervention, Intervention.cout, Intervention.date_intervention)
|
||||
.where(Intervention.date_intervention.between('2025-03-01', '2025-03-31')))
|
||||
for intervention in march_2025_interventions:
|
||||
print(f"{intervention.date_intervention} : {intervention.type_intervention} pour {intervention.cout}€.")
|
||||
|
||||
# 2. Jointures
|
||||
|
||||
print("\n----- Liste des serveurs -----")
|
||||
server_listing = (Serveur
|
||||
.select(Serveur, Salle, Datacenter)
|
||||
.join(Salle)
|
||||
.join(Datacenter)
|
||||
.order_by(Datacenter.nom, Serveur.hostname))
|
||||
for server in server_listing:
|
||||
print(f"{server.hostname} - Salle {server.salle.nom}, DC {server.salle.datacenter.nom}")
|
||||
|
||||
print("\n----- Hébergements actifs -----")
|
||||
active_hostings = (Hebergement
|
||||
.select(Hebergement, Client, Serveur)
|
||||
.join(Client)
|
||||
.switch(Hebergement)
|
||||
.join(Serveur)
|
||||
.where(Hebergement.date_fin.is_null())
|
||||
.order_by(Hebergement.prix_mensuel.desc()))
|
||||
for active_hosting in active_hostings:
|
||||
print(f"{active_hosting.client.nom} - sur {active_hosting.serveur.hostname} pour {active_hosting.prix_mensuel}€ / mois.")
|
||||
|
||||
print("\n----- Serveurs qui n'ont jamais panné (ni poisson ni rien) -----")
|
||||
servers_without_problem = (Serveur
|
||||
.select(Serveur.hostname, Serveur.date_installation)
|
||||
.join(Intervention, JOIN.LEFT_OUTER)
|
||||
.where(Intervention.id.is_null()))
|
||||
for server in servers_without_problem:
|
||||
print(f"{server.hostname} - Installation {server.date_installation}.)")
|
||||
|
||||
print("\n----- Hébergements par client -----")
|
||||
client_hostings = (Client
|
||||
.select(Client.nom,
|
||||
fn.COUNT(Hebergement.id).alias("nb_servers"),
|
||||
fn.SUM(Hebergement.prix_mensuel).alias("monthly_price"))
|
||||
.join(Hebergement)
|
||||
.group_by(Client.id, Client.nom)
|
||||
.order_by(fn.SUM(Hebergement.prix_mensuel).desc()))
|
||||
for client_hosting in client_hostings:
|
||||
total = client_hosting.monthly_price if client_hosting.monthly_price else 0
|
||||
print(f"{client_hosting.nom} - {client_hosting.nb_servers} serveur(s) pour un total de {total}€ / mois.")
|
||||
|
||||
# 3. Agrégations
|
||||
|
||||
print("\n----- Liste des serveurs par marque -----")
|
||||
servers_brand = (Serveur
|
||||
.select(Serveur.marque, fn.COUNT(Serveur.id).alias("nb_servers"))
|
||||
.group_by(Serveur.marque))
|
||||
for server_brand in servers_brand:
|
||||
print(f"{server_brand.marque} - {server_brand.nb_servers} serveur(s).")
|
||||
|
||||
print("\n----- Coût total par intervention -----")
|
||||
intervention_cost = (Intervention
|
||||
.select(Intervention.type_intervention,
|
||||
fn.SUM(Intervention.cout).alias("cost"),
|
||||
fn.AVG(Intervention.cout).alias("avg"))
|
||||
.group_by(Intervention.type_intervention))
|
||||
for cost in intervention_cost:
|
||||
print(f"{cost.type_intervention} - {cost.cost}€ - moyenne à {round(cost.avg, 2)}€.") # Bonus pour le fun
|
||||
|
||||
print("\n----- Datacenters qui tournent pas trop à vide -----")
|
||||
empty_datacenters = (Datacenter
|
||||
.select(Datacenter.nom, fn.COUNT(Serveur.id).alias("nb_serveurs"))
|
||||
.join(Salle)
|
||||
.join(Serveur)
|
||||
.group_by(Datacenter.id, Datacenter.nom)
|
||||
.having(fn.COUNT(Serveur.id) > 3))
|
||||
for datacenter in empty_datacenters:
|
||||
print(f"{datacenter.nom} - {datacenter.nb_serveurs} serveurs.")
|
||||
|
||||
print("\n----- Mois le plus chargé de l'année -----")
|
||||
heaviest_month = (Intervention
|
||||
.select(fn.DATE_FORMAT(Intervention.date_intervention, '%Y-%m').alias('mois'),
|
||||
fn.COUNT(Intervention.id).alias('nb_interventions'),
|
||||
fn.SUM(Intervention.cout).alias('cout_total'))
|
||||
.group_by(fn.DATE_FORMAT(Intervention.date_intervention, '%Y-%m'))
|
||||
.order_by(fn.COUNT(Intervention.id).desc())
|
||||
.limit(1))
|
||||
for record in heaviest_month:
|
||||
print(f"En {record.mois}, il y a eu {record.nb_interventions} interventions totalisant {record.cout_total}€.\n\
|
||||
Pensez aux actionnaires !")
|
||||
@@ -0,0 +1,152 @@
|
||||
CREATE DATABASE IF NOT EXISTS datacenters;
|
||||
USE datacenters;
|
||||
|
||||
CREATE TABLE datacenter (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
nom VARCHAR(100) NOT NULL UNIQUE,
|
||||
ville VARCHAR(100) NOT NULL,
|
||||
pays VARCHAR(100) NOT NULL,
|
||||
capacite_racks INT NOT NULL CHECK (capacite_racks > 0),
|
||||
annee_ouverture INT NOT NULL CHECK (annee_ouverture >= 2000)
|
||||
);
|
||||
|
||||
CREATE TABLE salle (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
nom VARCHAR(100) NOT NULL,
|
||||
etage INT NOT NULL,
|
||||
superficie_m2 DECIMAL(7,2) NOT NULL CHECK (superficie_m2 > 0),
|
||||
nb_racks INT NOT NULL CHECK (nb_racks > 0),
|
||||
datacenter_id INT NOT NULL,
|
||||
FOREIGN KEY (datacenter_id) REFERENCES datacenter(id)
|
||||
);
|
||||
|
||||
CREATE TABLE client (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
nom VARCHAR(150) NOT NULL,
|
||||
email VARCHAR(200) NOT NULL UNIQUE,
|
||||
telephone VARCHAR(20),
|
||||
type_contrat VARCHAR(50) NOT NULL CHECK (type_contrat IN ('Essentiel', 'Standard', 'Premium'))
|
||||
);
|
||||
|
||||
CREATE TABLE serveur (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
hostname VARCHAR(100) NOT NULL UNIQUE,
|
||||
marque VARCHAR(100) NOT NULL,
|
||||
modele VARCHAR(100) NOT NULL,
|
||||
cpu_cores INT NOT NULL CHECK (cpu_cores > 0),
|
||||
ram_go INT NOT NULL CHECK (ram_go > 0),
|
||||
stockage_to DECIMAL(5,2) NOT NULL CHECK (stockage_to > 0),
|
||||
date_installation DATE NOT NULL,
|
||||
salle_id INT NOT NULL,
|
||||
FOREIGN KEY (salle_id) REFERENCES salle(id)
|
||||
);
|
||||
|
||||
CREATE TABLE intervention (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
date_intervention DATE NOT NULL,
|
||||
type_intervention VARCHAR(100) NOT NULL,
|
||||
description TEXT,
|
||||
duree_heures DECIMAL(4,2) NOT NULL CHECK (duree_heures > 0),
|
||||
cout DECIMAL(8,2) NOT NULL CHECK (cout >= 0),
|
||||
serveur_id INT NOT NULL,
|
||||
FOREIGN KEY (serveur_id) REFERENCES serveur(id)
|
||||
);
|
||||
|
||||
CREATE TABLE hebergement (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
date_debut DATE NOT NULL,
|
||||
date_fin DATE,
|
||||
prix_mensuel DECIMAL(8,2) NOT NULL CHECK (prix_mensuel > 0),
|
||||
serveur_id INT NOT NULL,
|
||||
client_id INT NOT NULL,
|
||||
FOREIGN KEY (serveur_id) REFERENCES serveur(id),
|
||||
FOREIGN KEY (client_id) REFERENCES client(id)
|
||||
);
|
||||
|
||||
-- Datacenters
|
||||
INSERT INTO datacenter (nom, ville, pays, capacite_racks, annee_ouverture) VALUES
|
||||
('DC-Paris-Nord', 'Paris', 'France', 500, 2015),
|
||||
('DC-Lyon-Est', 'Lyon', 'France', 300, 2018),
|
||||
('DC-Marseille-Sud', 'Marseille', 'France', 200, 2020),
|
||||
('DC-Bruxelles-Centre', 'Bruxelles', 'Belgique', 400, 2016),
|
||||
('DC-Geneve-Lac', 'Genève', 'Suisse', 250, 2019);
|
||||
|
||||
-- Salles
|
||||
INSERT INTO salle (nom, etage, superficie_m2, nb_racks, datacenter_id) VALUES
|
||||
('Salle Alpha', 0, 450.00, 120, 1),
|
||||
('Salle Beta', 0, 380.00, 100, 1),
|
||||
('Salle Gamma', 1, 500.00, 140, 1),
|
||||
('Salle Delta', 0, 300.00, 80, 2),
|
||||
('Salle Epsilon', 1, 280.00, 70, 2),
|
||||
('Salle Zeta', 0, 200.00, 50, 3),
|
||||
('Salle Eta', 0, 350.00, 100, 4),
|
||||
('Salle Theta', 1, 320.00, 90, 4),
|
||||
('Salle Iota', 0, 250.00, 65, 5),
|
||||
('Salle Kappa', 1, 230.00, 60, 5);
|
||||
|
||||
-- Clients
|
||||
INSERT INTO client (nom, email, telephone, type_contrat) VALUES
|
||||
('TechnoWeb SAS', 'contact@technoweb.fr', '0145678901', 'Premium'),
|
||||
('StartupFlow', 'admin@startupflow.io', '0234567890', 'Standard'),
|
||||
('MegaStore Europe', 'infra@megastore.eu', '0156789012', 'Premium'),
|
||||
('DataLab Research', 'tech@datalab.org', '0145671234', 'Standard'),
|
||||
('CloudFirst Agency', 'ops@cloudfirst.fr', '0198765432', 'Premium'),
|
||||
('GreenEnergy Corp', 'it@greenenergy.com', '0187654321', 'Essentiel'),
|
||||
('MediaPlus', 'support@mediaplus.fr', '0176543210', 'Standard'),
|
||||
('FinanceSecure SA', 'infra@financesecure.ch', '0223456789', 'Premium'),
|
||||
('EduConnect', 'admin@educonnect.fr', '0156784321', 'Essentiel'),
|
||||
('LogiTrans SARL', 'it@logitrans.fr', '0167890123', 'Standard');
|
||||
|
||||
-- Serveurs
|
||||
INSERT INTO serveur (hostname, marque, modele, cpu_cores, ram_go, stockage_to, date_installation, salle_id) VALUES
|
||||
('srv-web-01', 'Dell', 'PowerEdge R750', 32, 128, 2.00, '2023-03-15', 1),
|
||||
('srv-web-02', 'Dell', 'PowerEdge R750', 32, 128, 2.00, '2023-03-15', 1),
|
||||
('srv-db-01', 'HP', 'ProLiant DL380', 64, 512, 8.00, '2022-06-10', 1),
|
||||
('srv-app-01', 'Lenovo', 'ThinkSystem SR650', 48, 256, 4.00, '2023-09-01', 2),
|
||||
('srv-storage-01', 'Dell', 'PowerEdge R760', 16, 64, 24.00, '2024-01-20', 3),
|
||||
('srv-lyon-01', 'HP', 'ProLiant DL360', 32, 128, 2.00, '2023-05-12', 4),
|
||||
('srv-lyon-02', 'HP', 'ProLiant DL380', 48, 256, 4.00, '2022-11-08', 4),
|
||||
('srv-lyon-db-01', 'Dell', 'PowerEdge R750', 64, 512, 8.00, '2023-01-25', 5),
|
||||
('srv-mars-01', 'Lenovo', 'ThinkSystem SR630', 16, 64, 1.00, '2024-03-10', 6),
|
||||
('srv-mars-02', 'Lenovo', 'ThinkSystem SR650', 32, 128, 2.00, '2024-03-10', 6),
|
||||
('srv-brux-01', 'Dell', 'PowerEdge R750', 48, 256, 4.00, '2021-07-15', 7),
|
||||
('srv-brux-02', 'HP', 'ProLiant DL380', 64, 512, 8.00, '2021-07-15', 7),
|
||||
('srv-brux-03', 'Dell', 'PowerEdge R760', 32, 128, 2.00, '2023-04-20', 8),
|
||||
('srv-gen-01', 'HP', 'ProLiant DL380', 48, 256, 4.00, '2022-09-05', 9),
|
||||
('srv-gen-02', 'Lenovo', 'ThinkSystem SR650', 32, 128, 2.00, '2023-08-18', 10);
|
||||
|
||||
-- Interventions
|
||||
INSERT INTO intervention (date_intervention, type_intervention, description, duree_heures, cout, serveur_id) VALUES
|
||||
('2025-01-10', 'Maintenance préventive', 'Remplacement disques préventif', 2.00, 350.00, 3),
|
||||
('2025-01-15', 'Panne matérielle', 'Remplacement alimentation défectueuse', 1.50, 280.00, 1),
|
||||
('2025-02-01', 'Mise à jour firmware', 'Update BIOS et firmware RAID', 1.00, 150.00, 6),
|
||||
('2025-02-12', 'Panne matérielle', 'Remplacement barrette RAM défectueuse', 0.50, 420.00, 12),
|
||||
('2025-02-20', 'Extension capacité', 'Ajout 256 Go RAM', 1.00, 1200.00, 7),
|
||||
('2025-03-01', 'Maintenance préventive', 'Nettoyage et vérification câblage', 3.00, 200.00, 11),
|
||||
('2025-03-05', 'Mise à jour firmware', 'Update BIOS', 0.50, 100.00, 4),
|
||||
('2025-03-10', 'Panne matérielle', 'Remplacement ventilateur', 0.50, 180.00, 9),
|
||||
('2025-03-15', 'Extension capacité', 'Ajout disque SSD 2 To', 1.00, 450.00, 14),
|
||||
('2025-04-01', 'Maintenance préventive', 'Vérification générale', 2.00, 200.00, 1),
|
||||
('2025-04-05', 'Panne matérielle', 'Remplacement contrôleur RAID', 2.50, 750.00, 8),
|
||||
('2025-04-10', 'Mise à jour firmware', 'Update firmware stockage', 1.00, 150.00, 5),
|
||||
('2025-04-15', 'Maintenance préventive', 'Remplacement pâte thermique CPU', 1.50, 120.00, 13),
|
||||
('2025-05-01', 'Panne matérielle', 'Remplacement carte réseau', 1.00, 320.00, 2),
|
||||
('2025-05-10', 'Extension capacité', 'Ajout 128 Go RAM', 0.50, 600.00, 10);
|
||||
|
||||
-- Hébergements
|
||||
INSERT INTO hebergement (date_debut, date_fin, prix_mensuel, serveur_id, client_id) VALUES
|
||||
('2023-04-01', NULL, 850.00, 1, 1),
|
||||
('2023-04-01', NULL, 850.00, 2, 1),
|
||||
('2022-07-01', NULL, 1500.00, 3, 3),
|
||||
('2023-10-01', NULL, 1100.00, 4, 5),
|
||||
('2024-02-01', NULL, 600.00, 5, 3),
|
||||
('2023-06-01', '2025-01-31', 750.00, 6, 2),
|
||||
('2023-02-01', NULL, 1100.00, 7, 4),
|
||||
('2023-02-01', NULL, 1500.00, 8, 8),
|
||||
('2024-04-01', NULL, 400.00, 9, 9),
|
||||
('2024-04-01', NULL, 750.00, 10, 6),
|
||||
('2021-08-01', NULL, 1100.00, 11, 3),
|
||||
('2021-08-01', NULL, 1500.00, 12, 8),
|
||||
('2023-05-01', NULL, 750.00, 13, 7),
|
||||
('2022-10-01', NULL, 1100.00, 14, 5),
|
||||
('2023-09-01', NULL, 750.00, 15, 10);
|
||||
47
Semaine_07/Jour_05/Boiche_Gauvain_eval_20_03_2026/README.md
Normal file
47
Semaine_07/Jour_05/Boiche_Gauvain_eval_20_03_2026/README.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Evaluation 20/03/2026 - BOICHÉ Gauvain
|
||||
|
||||
## Démarrage
|
||||
|
||||
### Initialisation
|
||||
|
||||
```bash
|
||||
uv init --python 3.12
|
||||
uv run main.py
|
||||
.venv/Scripts/activate
|
||||
|
||||
uv add dotenv
|
||||
uv add peewee pymysql
|
||||
```
|
||||
|
||||
### Fichier .env
|
||||
|
||||
Les "secrets" sont gérés pour l'occasion dans un fichier .env
|
||||
|
||||
Normalement, on met aussi un fichier
|
||||
|
||||
`.gitignore`
|
||||
|
||||
Dont le contenu mentionne :
|
||||
|
||||
`*.env`
|
||||
|
||||
Pour l'exercice évidemment, je garde le fichier en clair.
|
||||
|
||||
## Partie 1
|
||||
|
||||
|
||||
|
||||
## Partie 2
|
||||
|
||||
### Requêtes normales
|
||||
|
||||
Avoir une requête SQL normale fonctionne :
|
||||
|
||||
```sql
|
||||
select nom, ville
|
||||
from datacenters.datacenter
|
||||
where pays = "France"
|
||||
order by annee_ouverture;
|
||||
```
|
||||
|
||||
Maintenant faut les traduire.
|
||||
@@ -0,0 +1,19 @@
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:8.0
|
||||
container_name: mysql_evaluation
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
|
||||
command: --log_bin_trust_function_creators=1
|
||||
ports:
|
||||
- "3306:3306"
|
||||
volumes:
|
||||
- mysql_data:/var/lib/mysql
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
mysql_data:
|
||||
Binary file not shown.
@@ -0,0 +1,11 @@
|
||||
[project]
|
||||
name = "boiche-gauvain-eval-20-03-2026"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
"dotenv>=0.9.9",
|
||||
"peewee>=4.0.2",
|
||||
"pymysql>=1.1.2",
|
||||
]
|
||||
58
Semaine_07/Jour_05/Boiche_Gauvain_eval_20_03_2026/uv.lock
generated
Normal file
58
Semaine_07/Jour_05/Boiche_Gauvain_eval_20_03_2026/uv.lock
generated
Normal file
@@ -0,0 +1,58 @@
|
||||
version = 1
|
||||
revision = 3
|
||||
requires-python = ">=3.12"
|
||||
|
||||
[[package]]
|
||||
name = "boiche-gauvain-eval-20-03-2026"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "dotenv" },
|
||||
{ name = "peewee" },
|
||||
{ name = "pymysql" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "dotenv", specifier = ">=0.9.9" },
|
||||
{ name = "peewee", specifier = ">=4.0.2" },
|
||||
{ name = "pymysql", specifier = ">=1.1.2" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dotenv"
|
||||
version = "0.9.9"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "python-dotenv" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/b7/545d2c10c1fc15e48653c91efde329a790f2eecfbbf2bd16003b5db2bab0/dotenv-0.9.9-py2.py3-none-any.whl", hash = "sha256:29cf74a087b31dafdb5a446b6d7e11cbce8ed2741540e2339c69fbef92c94ce9", size = 1892, upload-time = "2025-02-19T22:15:01.647Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peewee"
|
||||
version = "4.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/54/9b/3439dcc3ed5138eb26f28fc208f958ca97b831f5f898b26d5354302e5df4/peewee-4.0.2.tar.gz", hash = "sha256:fd5d026ce7787c6cd3a84316e665a76b72c9c4e87322598c413f44604fa6c38d", size = 714081, upload-time = "2026-03-15T15:46:30.049Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/8e/943f57ce32eb005c7037110a759e2ebfb22e467a9a0efcb6d516c5bf00c6/peewee-4.0.2-py3-none-any.whl", hash = "sha256:86d5d16bcda5bbe017a108f6efc57abaac8d89277915541904542df9d2a7f25d", size = 143344, upload-time = "2026-03-15T15:46:28.778Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pymysql"
|
||||
version = "1.1.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f5/ae/1fe3fcd9f959efa0ebe200b8de88b5a5ce3e767e38c7ac32fb179f16a388/pymysql-1.1.2.tar.gz", hash = "sha256:4961d3e165614ae65014e361811a724e2044ad3ea3739de9903ae7c21f539f03", size = 48258, upload-time = "2025-08-24T12:55:55.146Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/4c/ad33b92b9864cbde84f259d5df035a6447f91891f5be77788e2a3892bce3/pymysql-1.1.2-py3-none-any.whl", hash = "sha256:e6b1d89711dd51f8f74b1631fe08f039e7d76cf67a42a323d3178f0f25762ed9", size = 45300, upload-time = "2025-08-24T12:55:53.394Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-dotenv"
|
||||
version = "1.2.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" },
|
||||
]
|
||||
5
Semaine_07/Jour_05/orm_peewee/.env
Normal file
5
Semaine_07/Jour_05/orm_peewee/.env
Normal file
@@ -0,0 +1,5 @@
|
||||
DB_HOST=localhost
|
||||
DB_USER=root
|
||||
DB_PASSWORD=MementoMarsouin96
|
||||
DB_NAME=company
|
||||
DB_PORT=3306
|
||||
1
Semaine_07/Jour_05/orm_peewee/.python-version
Normal file
1
Semaine_07/Jour_05/orm_peewee/.python-version
Normal file
@@ -0,0 +1 @@
|
||||
3.12
|
||||
11
Semaine_07/Jour_05/orm_peewee/README.md
Normal file
11
Semaine_07/Jour_05/orm_peewee/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
Normalement, on met aussi un fichier
|
||||
|
||||
`.gitignore`
|
||||
|
||||
Dont le contenu mentionne :
|
||||
|
||||
```
|
||||
*.env
|
||||
```
|
||||
|
||||
Pour l'exercice évidemment, je garde le fichier en clair.
|
||||
19
Semaine_07/Jour_05/orm_peewee/docker-compose.yml
Normal file
19
Semaine_07/Jour_05/orm_peewee/docker-compose.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:8.0
|
||||
container_name: mysql_peewee
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
|
||||
command: --log_bin_trust_function_creators=1
|
||||
ports:
|
||||
- "3306:3306"
|
||||
volumes:
|
||||
- mysql_data:/var/lib/mysql
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
mysql_data:
|
||||
123
Semaine_07/Jour_05/orm_peewee/main.py
Normal file
123
Semaine_07/Jour_05/orm_peewee/main.py
Normal file
@@ -0,0 +1,123 @@
|
||||
from peewee import *
|
||||
|
||||
# import os
|
||||
# from dotenv import load_dotenv
|
||||
|
||||
# load_dotenv()
|
||||
|
||||
# db_name = os.environ.get("DB_NAME")
|
||||
# db_user = os.environ.get("DB_USER")
|
||||
# db_password = os.environ.get("DB_PASSWORD")
|
||||
# db_host = os.environ.get("DB_HOST")
|
||||
# db_port = os.environ.get("DB_PORT")
|
||||
|
||||
db_name = "company"
|
||||
db_user = "root"
|
||||
db_password = "MementoMarsouin96"
|
||||
db_host = "localhost"
|
||||
db_port = 3306
|
||||
|
||||
db = MySQLDatabase(
|
||||
database= db_name,
|
||||
user= db_user,
|
||||
password= db_password,
|
||||
host= db_host,
|
||||
port= db_port
|
||||
)
|
||||
|
||||
# équivalent de "Base = declarative_base()"
|
||||
class BaseModel(Model):
|
||||
class Meta:
|
||||
database = db
|
||||
|
||||
class Department(BaseModel):
|
||||
department_id = AutoField(primary_key= True)
|
||||
department_name = CharField(max_length= 50, null= False, unique= True)
|
||||
location_id = DecimalField(max_digits= 4, decimal_places= 0, null= False)
|
||||
|
||||
# équivalent de "__tablename__ = "truc""
|
||||
class Meta:
|
||||
table_name = "departments"
|
||||
|
||||
class Employee(BaseModel):
|
||||
employee_id = AutoField(primary_key= True)
|
||||
first_name = CharField(max_length= 50, null= False)
|
||||
last_name = CharField(max_length= 50, null= False)
|
||||
email = CharField(max_length= 50, null= False, unique= True)
|
||||
salary = IntegerField(null= False)
|
||||
|
||||
department = ForeignKeyField(Department, backref= "employees", null= False)
|
||||
|
||||
class Meta:
|
||||
table_name = "employees"
|
||||
|
||||
db.connect()
|
||||
db.create_tables([Department, Employee])
|
||||
|
||||
try:
|
||||
it_dept = Department.create(department_name= "IT", location_id= 1400)
|
||||
except IntegrityError:
|
||||
print("Département déjà existant.")
|
||||
|
||||
it_dept = Department.get(Department.department_name == "IT")
|
||||
|
||||
try:
|
||||
Employee.create(
|
||||
first_name= "Alice",
|
||||
last_name= "Smith",
|
||||
email= "a.smith@company.au",
|
||||
salary= 4000,
|
||||
department= it_dept # utiliser l'OBJET, pas le nom de l'objet
|
||||
)
|
||||
except IntegrityError:
|
||||
print("Employé(e) déjà existant(e).")
|
||||
|
||||
new_employees = [
|
||||
{'first_name': 'Marie', 'last_name': 'Dupont', 'email': 'mdupont', 'salary': 4500},
|
||||
{'first_name': 'Jean', 'last_name': 'Martin', 'email': 'jmartin', 'salary': 5200},
|
||||
{'first_name': 'Sophie', 'last_name': 'Bernard', 'email': 'sbernard', 'salary': 4800},
|
||||
]
|
||||
|
||||
# with db.atomic():
|
||||
# Employee.insert_many(new_employees).execute()
|
||||
|
||||
employee_01 = Employee.get(1)
|
||||
print(employee_01.first_name, employee_01.last_name)
|
||||
|
||||
employee_02 = Employee.get(Employee.email == "a.smith@company.au")
|
||||
print(employee_02.first_name, employee_02.salary)
|
||||
|
||||
try:
|
||||
employee_76 = Employee.get(76)
|
||||
except DoesNotExist:
|
||||
print("L'employé(e) 76 n'existe pas.")
|
||||
|
||||
employee_select_01 = Employee.select() # SELECT * FROM employees
|
||||
print(employee_select_01)
|
||||
for employee in employee_select_01:
|
||||
print(employee.first_name, employee.last_name, employee.email)
|
||||
|
||||
employee_select_02 = Employee.select().where(
|
||||
(Employee.salary > 8000) & (Employee.department == it_dept)
|
||||
)
|
||||
print(employee_select_02)
|
||||
|
||||
# pagination
|
||||
page_01 = Employee.select().order_by(Employee.employee_id).paginate(1, 10)
|
||||
|
||||
# compter une valeur
|
||||
salary_01 = Employee.select().where(Employee.salary > 10000).count()
|
||||
|
||||
# Jointures (LEFT JOIN, RIGHT JOIN etc)
|
||||
### FULL JOIN
|
||||
query = (Employee
|
||||
.select(Employee, Department)
|
||||
.join(Department)
|
||||
.where(Department.department_name == "IT"))
|
||||
|
||||
### Employés affectés à un département
|
||||
### et ceux non affectés à un département
|
||||
query = (Employee
|
||||
.select(Employee, Department)
|
||||
.join(Department, JOIN.LEFT_OUTER)
|
||||
.where(Department.department_name == "IT"))
|
||||
10
Semaine_07/Jour_05/orm_peewee/pyproject.toml
Normal file
10
Semaine_07/Jour_05/orm_peewee/pyproject.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
[project]
|
||||
name = "orm-peewee"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
"peewee>=4.0.2",
|
||||
"pymysql>=1.1.2",
|
||||
]
|
||||
105
Semaine_07/Jour_05/orm_peewee/relations.py
Normal file
105
Semaine_07/Jour_05/orm_peewee/relations.py
Normal file
@@ -0,0 +1,105 @@
|
||||
from peewee import *
|
||||
|
||||
# import os
|
||||
# from dotenv import load_dotenv
|
||||
|
||||
# load_dotenv()
|
||||
|
||||
# db_name = os.environ.get("DB_NAME")
|
||||
# db_user = os.environ.get("DB_USER")
|
||||
# db_password = os.environ.get("DB_PASSWORD")
|
||||
# db_host = os.environ.get("DB_HOST")
|
||||
# db_port = os.environ.get("DB_PORT")
|
||||
|
||||
db_name = "company"
|
||||
db_user = "root"
|
||||
db_password = "MementoMarsouin96"
|
||||
db_host = "localhost"
|
||||
db_port = 3306
|
||||
|
||||
db = MySQLDatabase(
|
||||
database= db_name,
|
||||
user= db_user,
|
||||
password= db_password,
|
||||
host= db_host,
|
||||
port= db_port
|
||||
)
|
||||
|
||||
# équivalent de "Base = declarative_base()"
|
||||
class BaseModel(Model):
|
||||
class Meta:
|
||||
database = db
|
||||
|
||||
# Relations One-To-Many
|
||||
class User(BaseModel):
|
||||
username = CharField(unique= True)
|
||||
email = CharField()
|
||||
|
||||
class Meta:
|
||||
table_name = "user"
|
||||
|
||||
class Todo(BaseModel):
|
||||
title = CharField()
|
||||
is_done = BooleanField(default= False)
|
||||
user= ForeignKeyField(User, backref= "todos") # l'accès inverse est géré automatiquement
|
||||
|
||||
class Meta:
|
||||
table_name = "todos"
|
||||
|
||||
class Tag(BaseModel):
|
||||
name = CharField(unique= True)
|
||||
|
||||
class Meta:
|
||||
table_name = "tag"
|
||||
|
||||
class TodoTag(BaseModel):
|
||||
todo = ForeignKeyField(Todo)
|
||||
tag = ForeignKeyField(Tag)
|
||||
|
||||
class Meta:
|
||||
table_name = 'todo_tag'
|
||||
indexes= (
|
||||
(('todo', 'tag'), True),
|
||||
)
|
||||
|
||||
class Profile(BaseModel):
|
||||
user = ForeignKeyField(User, unique= True, backref= "profile") # One-To-One
|
||||
bio = TextField(null= True)
|
||||
avatar = CharField(null= True)
|
||||
|
||||
class Meta:
|
||||
table_name = "profile"
|
||||
|
||||
db.connect()
|
||||
db.create_tables([User, Todo, Profile, Tag, TodoTag])
|
||||
|
||||
try:
|
||||
alice = User.create(username= "Alice", email= "a.smith@company.au")
|
||||
Todo.create(title= "Apprendre Python", user= alice)
|
||||
Todo.create(title= "Apprendre JS", user= alice)
|
||||
Todo.create(title= "Apprendre COBOL", user= alice)
|
||||
|
||||
for todo in alice.todos:
|
||||
print(todo.title, todo.is_done)
|
||||
except IntegrityError as error:
|
||||
print(error)
|
||||
|
||||
try:
|
||||
Profile.create(
|
||||
user= User.get(1),
|
||||
bio = 'Developpeur',
|
||||
avatar= 'http://example.com'
|
||||
)
|
||||
except IntegrityError as error:
|
||||
print(error)
|
||||
|
||||
try:
|
||||
tag_urgent = Tag.create(name= "Urgent")
|
||||
tag_perso = Tag.create(name= "Perso")
|
||||
tag_pro = Tag.create(name= "Pro")
|
||||
|
||||
todo_cobol = Todo.get(Todo.title == "Apprendre COBOL")
|
||||
|
||||
TodoTag.create(todo= todo_cobol, tag= tag_urgent)
|
||||
except IntegrityError as error:
|
||||
print(error)
|
||||
36
Semaine_07/Jour_05/orm_peewee/uv.lock
generated
Normal file
36
Semaine_07/Jour_05/orm_peewee/uv.lock
generated
Normal file
@@ -0,0 +1,36 @@
|
||||
version = 1
|
||||
revision = 3
|
||||
requires-python = ">=3.12"
|
||||
|
||||
[[package]]
|
||||
name = "orm-peewee"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "peewee" },
|
||||
{ name = "pymysql" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "peewee", specifier = ">=4.0.2" },
|
||||
{ name = "pymysql", specifier = ">=1.1.2" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "peewee"
|
||||
version = "4.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/54/9b/3439dcc3ed5138eb26f28fc208f958ca97b831f5f898b26d5354302e5df4/peewee-4.0.2.tar.gz", hash = "sha256:fd5d026ce7787c6cd3a84316e665a76b72c9c4e87322598c413f44604fa6c38d", size = 714081, upload-time = "2026-03-15T15:46:30.049Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/8e/943f57ce32eb005c7037110a759e2ebfb22e467a9a0efcb6d516c5bf00c6/peewee-4.0.2-py3-none-any.whl", hash = "sha256:86d5d16bcda5bbe017a108f6efc57abaac8d89277915541904542df9d2a7f25d", size = 143344, upload-time = "2026-03-15T15:46:28.778Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pymysql"
|
||||
version = "1.1.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f5/ae/1fe3fcd9f959efa0ebe200b8de88b5a5ce3e767e38c7ac32fb179f16a388/pymysql-1.1.2.tar.gz", hash = "sha256:4961d3e165614ae65014e361811a724e2044ad3ea3739de9903ae7c21f539f03", size = 48258, upload-time = "2025-08-24T12:55:55.146Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/4c/ad33b92b9864cbde84f259d5df035a6447f91891f5be77788e2a3892bce3/pymysql-1.1.2-py3-none-any.whl", hash = "sha256:e6b1d89711dd51f8f74b1631fe08f039e7d76cf67a42a323d3178f0f25762ed9", size = 45300, upload-time = "2025-08-24T12:55:53.394Z" },
|
||||
]
|
||||
Reference in New Issue
Block a user