├── .gitignore
├── README.md
├── app-001_convertisseur-devises
├── Session 192
│ └── app.py
├── Session 193
│ └── app.py
├── Session 194
│ └── app.py
├── Session 195
│ └── app.py
├── Session 196
│ └── app.py
├── Session 197
│ └── app.py
└── Session 198
│ └── app.py
├── app-002_cineclub-api
├── Session 202
│ ├── app.py
│ ├── data
│ │ └── movies.json
│ └── movie.py
├── Session 206
│ ├── app.py
│ ├── data
│ │ └── movies.json
│ └── movie.py
├── Session 208
│ ├── app.py
│ ├── data
│ │ └── movies.json
│ └── movie.py
├── Session 210
│ ├── app.py
│ ├── data
│ │ └── movies.json
│ └── movie.py
├── Session 212
│ ├── app.py
│ ├── data
│ │ └── movies.json
│ └── movie.py
└── Session 214
│ ├── app.py
│ ├── data
│ └── movies.json
│ └── movie.py
├── app-002_cineclub-gui
├── Session 216
│ ├── app.py
│ ├── data
│ │ └── movies.json
│ └── movie.py
├── Session 218
│ ├── app.py
│ ├── data
│ │ └── movies.json
│ └── movie.py
├── Session 220
│ ├── app.py
│ ├── data
│ │ └── movies.json
│ └── movie.py
├── Session 222
│ ├── app.py
│ ├── data
│ │ └── movies.json
│ └── movie.py
└── Session 223
│ ├── app.py
│ ├── data
│ └── movies.json
│ └── movie.py
├── app-003_site-web-django
├── requirements.txt
└── src
│ ├── DocBlog
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── static
│ │ └── css
│ │ │ ├── background.jpg
│ │ │ └── style.css
│ ├── templates
│ │ └── DocBlog
│ │ │ └── index.html
│ ├── urls.py
│ ├── views.py
│ └── wsgi.py
│ ├── blog
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── templates
│ │ └── blog
│ │ │ ├── article_01.html
│ │ │ ├── article_02.html
│ │ │ ├── article_03.html
│ │ │ ├── article_not_found.html
│ │ │ └── index.html
│ ├── tests.py
│ ├── urls.py
│ └── views.py
│ └── manage.py
├── app-004_bot-discord
├── config
├── main.py
└── requirements.txt
├── chp-001_les-bases
├── afficher-le-type-dune-variable
│ └── script.py
├── la-concatenation
│ └── script.py
├── les-fonctions-de-conversion
│ └── script.py
└── recuperer-linput-de-lutilisateur
│ └── script.py
├── chp-002_les-structures-conditionnelles
├── les-blocs-dinstructions
│ └── script.py
├── structure-conditionnelle-avancee-avec-else
│ └── script.py
├── tester-plusieurs-conditions
│ └── script.py
└── tester-une-condition-avec-if
│ └── script.py
├── chp-003_quelques-modules-et-fonctions
├── aller-chercher-de-laide-avec-les-fonctions-dir-et-help
│ └── script.py
├── le-module-os
│ └── script.py
└── le-module-random
│ └── script.py
├── chp-004_les-listes
├── ajouter-et-enlever-des-elements-a-une-liste
│ └── script.py
├── dautres-methodes-pour-enlever-des-elements
│ └── script.py
├── dautres-methodes-sur-les-listes
│ └── script.py
├── joindre-les-elements-dune-liste
│ └── script.py
├── les-listes-imbriques
│ └── script.py
├── les-listes
│ └── script.py
├── les-operateurs-dappartenance
│ └── script.py
├── les-slices
│ └── script.py
└── recuperer-un-element-dans-une-liste
│ └── script.py
├── chp-005_les-modules
├── actualiser-un-module
│ ├── script.py
│ └── utils.py
├── creer-notre-propre-module
│ ├── random.py
│ └── script.py
├── la-variable-name
│ ├── script.py
│ └── utils.py
└── le-pythonpath
│ └── script.py
├── chp-006_le-logging
├── configurer-le-logger
│ └── script.py
├── ecrire-dans-un-fichier-de-log
│ └── script.py
└── le-module-logging
│ └── script.py
├── chp-007_oriente-objet-premiere-partie
├── attributs-de-classe-et-attributs-dinstance
│ └── attributs.py
├── creer-des-instances
│ └── instances.py
├── creer-notre-premiere-classe
│ └── classe.py
├── initialiser-une-instance
│ └── initialisation.py
├── la-signification-de-self
│ └── self.py
└── la-verite-sur-les-fonctions-de-conversion
│ └── script.py
├── chp-008_reecriture-la-liste-de-courses-avec-la-poo
├── afficher-les-elements-dans-la-liste
│ ├── constants.py
│ └── lib.py
├── creation-de-la-classe-liste
│ ├── constants.py
│ └── lib.py
├── creation-des-constantes
│ └── constants.py
├── creation-des-methodes-ajouter-et-enlever
│ ├── constants.py
│ └── lib.py
└── sauvegarder-la-liste
│ ├── constants.py
│ ├── data
│ └── courses.json
│ └── lib.py
├── chp-009_oriente-objet-deuxieme-partie
├── la-fonction-super
│ └── super.py
├── la-methode-str
│ └── method_magic.py
├── la-surcharge
│ └── surcharge.py
├── le-polymorphisme
│ └── polymorphisme.py
├── les-methodes-de-classe
│ └── class_method.py
├── les-methodes-statiques
│ └── static_method.py
└── lheritage
│ └── heritage.py
├── chp-010_bases-de-donnees
├── ajouter-des-donnees
│ ├── app.py
│ └── database.db
├── creer-un-tableau
│ ├── app.py
│ └── database.db
├── introduction-a-sqlite
│ ├── app.py
│ └── database.db
├── mettre-a-jour-des-donnees
│ ├── app.py
│ └── database.db
├── recuperer-des-donnees
│ ├── app.py
│ └── database.db
├── stocker-des-donnees-dans-un-fichier-json
│ ├── app.py
│ └── settings.json
└── supprimer-des-donnees
│ ├── app.py
│ └── database.db
├── chp-011_bases-de-donnees-tinydb
├── data.json
└── main.py
├── chp-012_applications-command-line-typer
├── data
│ ├── _generate.py
│ ├── actually.js
│ ├── already.avi
│ ├── although.mov
│ ├── available.flac
│ ├── beautiful.css
│ ├── bed.jpg
│ ├── behavior.css
│ ├── big.css
│ ├── catch.pdf
│ ├── center.tiff
│ ├── chair.mov
│ ├── claim.ods
│ ├── claim.png
│ ├── contain.pptx
│ ├── defense.pptx
│ ├── describe.flac
│ ├── development.webm
│ ├── each.mp3
│ ├── enough.flac
│ ├── environment.pdf
│ ├── everyone.pdf
│ ├── evidence.js
│ ├── far.mp3
│ ├── force.avi
│ ├── friend.tiff
│ ├── general.bmp
│ ├── great.mp3
│ ├── group.pptx
│ ├── industry.ods
│ ├── information.xlsx
│ ├── inside.jpeg
│ ├── inside.webm
│ ├── interest.flac
│ ├── job.css
│ ├── learn.webm
│ ├── leave.avi
│ ├── line.jpeg
│ ├── live.flac
│ ├── marriage.webm
│ ├── material.webm
│ ├── movement.bmp
│ ├── movie.mp3
│ ├── opportunity.key
│ ├── page.avi
│ ├── physical.ods
│ ├── point.webm
│ ├── position.doc
│ ├── pressure.bmp
│ ├── pressure.mp3
│ ├── produce.css
│ ├── production.pptx
│ ├── program.mp3
│ ├── pull.avi
│ ├── quality.css
│ ├── recent.ppt
│ ├── resource.mov
│ ├── rock.js
│ ├── scene.xlsx
│ ├── senior.avi
│ ├── share.numbers
│ ├── simply.html
│ ├── site.odp
│ ├── somebody.html
│ ├── station.png
│ ├── step.webm
│ ├── still.webm
│ ├── student.avi
│ ├── team.flac
│ ├── than.webm
│ ├── trouble.css
│ ├── voice.jpg
│ ├── while.mp3
│ ├── wish.bmp
│ ├── work.pdf
│ ├── worker.docx
│ ├── yard.html
│ ├── yeah.mp3
│ └── your.pptx
└── main.py
├── chp-013_les-tests-unitaires
├── assets
│ └── style.css
├── bank.py
├── index.html
├── main.py
├── test_bank.py
└── test_main.py
├── chp-014_bases-de-la-data-science
├── 01_lecture_fichier.ipynb
├── 02_analyser_dataframe.ipynb
├── 03_selectionner_des_donnees.ipynb
├── 04_supprimer_des_colonnes.ipynb
├── 05_traiter_valeurs_manquantes.ipynb
├── 06_ajouter_des_donnees.ipynb
├── 07_analyser_des_donnees.ipynb
├── 08_graphiques.ipynb
├── 09_graphiques_avances.ipynb
├── analyse_netflix.ipynb
├── data.csv
└── netflix_titles.csv
├── exr-001_input-utilisateur
├── 01-sources
│ └── recuperer_input.py
└── 02-solution
│ └── recuperer_input.py
├── exr-002_changer-type-variable
├── 01-sources
│ └── changer_type_variable.py
└── 02-solution
│ └── changer_type_variable.py
├── exr-004_la-concatenation
├── 01-sources
│ └── la_concatenation.py
└── 02-solution
│ └── la_concatenation.py
├── exr-009_verifier-mot-de-passe
├── solution
│ └── script.py
└── sources
│ └── script.py
├── exr-010_nombre-mystere-erreurs
├── 01-sources
│ └── devine_un_nombre_04.py
└── 02-solution
│ └── devine_un_nombre_04.py
├── exr-011_comprehensions-de-liste
├── 01-sources
│ └── comprehension_de_liste.py
└── 02-solutions
│ └── comprehension_de_liste.py.py
├── exr-012_afficher-dix-utilisateurs
├── 01-sources
│ └── afficher_utilisateurs.py
└── 02-solution
│ └── afficher_utilisateurs.py
├── exr-013_mot-a-lenvers
├── 01-sources
│ └── afficher_un_mot_a_lenvers.py
└── 02-solution
│ └── afficher_un_mot_a_lenvers.py
├── exr-014_boucle-while-input
├── 01-sources
│ └── sortir_boucle_while.py
└── 02-solution
│ └── sortir_boucle_while.py
├── exr-025_gerer-erreurs-fichier
├── 01-sources
│ ├── fichier_invalide.abc
│ └── readme.txt
└── 02-solution
│ ├── fichier_invalide.abc
│ ├── gerer_erreurs.py
│ └── readme.txt
├── prj-001_la-calculatrice
├── 01-sources
│ └── main.py
└── 02-solution
│ └── main.py
├── prj-002_la-calculatrice-gestion-des-erreurs
├── 01-sources
│ └── main.py
└── 02-solution
│ └── main.py
├── prj-003_la-liste-de-courses
├── 01-sources
│ └── main.py
└── 02-solution
│ └── main.py
├── prj-004_le-nombre-mystere
├── 01-sources
│ └── main.py
└── 02-solution
│ └── main.py
├── prj-005_le-jeu-de-role
├── 01-sources
│ └── main.py
└── 02-solution
│ └── main.py
├── prj-006_la-liste-de-courses-avec-sauvegarde
├── 01-sources
│ └── main.py
└── 02-solution
│ └── main.py
├── prj-007_le-trieur-de-fichiers
├── 01-sources
│ └── main.py
└── 02-solution
│ └── main.py
├── prj-008_le-createur-de-dossiers
├── 01-sources
│ └── main.py
└── 02-solution
│ └── main.py
├── prj-009_organiser-des-donnees
├── 01-sources
│ ├── main.py
│ └── prenoms.txt
└── 02-solution
│ ├── main.py
│ ├── prenoms.txt
│ └── prenoms_final.txt
├── prj-010_le-gestionnaire-dutilisateurs-crm
└── user.py
├── prj-011_creer-une-classe-voiture
└── voiture.py
├── prj-012_le-gestionnaire-dutilisateurs-poo
└── crm.py
├── prj-013_le-gestionnaire-dutilisateurs-tests
├── crm.py
└── test_crm.py
└── prj-014_le-gestionnaire-dutilisateurs-django
├── requirements.txt
└── webapp
├── api
├── crm.py
├── db.json
└── test_crm.py
├── contacts
├── __init__.py
├── apps.py
├── static
│ └── css
│ │ └── style.css
├── templates
│ └── contacts
│ │ └── index.html
└── views.py
├── manage.py
└── webapp
├── __init__.py
├── asgi.py
├── settings.py
├── urls.py
└── wsgi.py
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | .idea/
12 | .DS_Store
13 | build/
14 | develop-eggs/
15 | dist/
16 | downloads/
17 | eggs/
18 | .eggs/
19 | lib/
20 | lib64/
21 | parts/
22 | sdist/
23 | var/
24 | wheels/
25 | pip-wheel-metadata/
26 | share/python-wheels/
27 | *.egg-info/
28 | .installed.cfg
29 | *.egg
30 | MANIFEST
31 |
32 | # PyInstaller
33 | # Usually these files are written by a python script from a template
34 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
35 | *.manifest
36 | *.spec
37 |
38 | # Installer logs
39 | pip-log.txt
40 | pip-delete-this-directory.txt
41 |
42 | # Unit test / coverage reports
43 | htmlcov/
44 | .tox/
45 | .nox/
46 | .coverage
47 | .coverage.*
48 | .cache
49 | nosetests.xml
50 | coverage.xml
51 | *.cover
52 | *.py,cover
53 | .hypothesis/
54 | .pytest_cache/
55 |
56 | # Translations
57 | *.mo
58 | *.pot
59 |
60 | # Django stuff:
61 | *.log
62 | local_settings.py
63 | db.sqlite3
64 | db.sqlite3-journal
65 |
66 | # Flask stuff:
67 | instance/
68 | .webassets-cache
69 |
70 | # Scrapy stuff:
71 | .scrapy
72 |
73 | # Sphinx documentation
74 | docs/_build/
75 |
76 | # PyBuilder
77 | target/
78 |
79 | # Jupyter Notebook
80 | .ipynb_checkpoints
81 |
82 | # pyenv
83 | .python-version
84 |
85 | # celery beat schedule file
86 | celerybeat-schedule
87 |
88 | # IPython
89 | profile_default/
90 | ipython_config.py
91 |
92 | # pyenv
93 | .python-version
94 |
95 | # pipenv
96 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
97 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
98 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
99 | # install all needed dependencies.
100 | #Pipfile.lock
101 |
102 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
103 | __pypackages__/
104 |
105 | # Celery stuff
106 | celerybeat-schedule
107 | celerybeat.pid
108 |
109 | # SageMath parsed files
110 | *.sage.py
111 |
112 | # Environments
113 | .env
114 | .venv
115 | env/
116 | venv/
117 | ENV/
118 | env.bak/
119 | venv.bak/
120 |
121 | # Spyder project settings
122 | .spyderproject
123 | .spyproject
124 |
125 | # Rope project settings
126 | .ropeproject
127 |
128 | # mkdocs documentation
129 | /site
130 |
131 | # mypy
132 | .mypy_cache/
133 | .dmypy.json
134 | dmypy.json
135 |
136 | # Pyre type checker
137 | .pyre/
138 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # La Formation Complète Python
2 | Ce repo Github contient toutes les sources du cours [**La Formation Complète Python**](https://www.docstring.fr/formations/la-formation-complete-python/).
3 |
--------------------------------------------------------------------------------
/app-001_convertisseur-devises/Session 192/app.py:
--------------------------------------------------------------------------------
1 | from PySide2 import QtWidgets, QtGui, QtCore
2 |
3 | class App(QtWidgets.QWidget):
4 | def __init__(self):
5 | super().__init__()
6 | self.setWindowTitle("Convertisseur de devises")
7 |
8 | app = QtWidgets.QApplication([])
9 | win = App()
10 | win.show()
11 | app.exec_()
--------------------------------------------------------------------------------
/app-001_convertisseur-devises/Session 193/app.py:
--------------------------------------------------------------------------------
1 | from PySide2 import QtWidgets, QtGui, QtCore
2 |
3 | class App(QtWidgets.QWidget):
4 | def __init__(self):
5 | super().__init__()
6 | self.setWindowTitle("Convertisseur de devises")
7 | self.setup_ui()
8 |
9 | def setup_ui(self):
10 | self.layout = QtWidgets.QHBoxLayout(self)
11 | self.cbb_devisesFrom = QtWidgets.QComboBox()
12 | self.le_montant = QtWidgets.QSpinBox()
13 | self.cbb_devisesTo = QtWidgets.QComboBox()
14 | self.le_montantConverti = QtWidgets.QSpinBox()
15 | self.btn_inverser = QtWidgets.QPushButton("Inverser devises")
16 |
17 | self.layout.addWidget(self.cbb_devisesFrom)
18 | self.layout.addWidget(self.le_montant)
19 | self.layout.addWidget(self.cbb_devisesTo)
20 | self.layout.addWidget(self.le_montantConverti)
21 | self.layout.addWidget(self.btn_inverser)
22 |
23 | app = QtWidgets.QApplication([])
24 | win = App()
25 | win.show()
26 | app.exec_()
--------------------------------------------------------------------------------
/app-001_convertisseur-devises/Session 194/app.py:
--------------------------------------------------------------------------------
1 | from PySide2 import QtWidgets, QtGui, QtCore
2 | import currency_converter
3 |
4 | class App(QtWidgets.QWidget):
5 | def __init__(self):
6 | super().__init__()
7 | self.c = currency_converter.CurrencyConverter()
8 | self.setWindowTitle("Convertisseur de devises")
9 | self.setup_ui()
10 | self.set_default_values()
11 |
12 | def setup_ui(self):
13 | self.layout = QtWidgets.QHBoxLayout(self)
14 | self.cbb_devisesFrom = QtWidgets.QComboBox()
15 | self.le_montant = QtWidgets.QSpinBox()
16 | self.cbb_devisesTo = QtWidgets.QComboBox()
17 | self.le_montantConverti = QtWidgets.QSpinBox()
18 | self.btn_inverser = QtWidgets.QPushButton("Inverser devises")
19 |
20 | self.layout.addWidget(self.cbb_devisesFrom)
21 | self.layout.addWidget(self.le_montant)
22 | self.layout.addWidget(self.cbb_devisesTo)
23 | self.layout.addWidget(self.le_montantConverti)
24 | self.layout.addWidget(self.btn_inverser)
25 |
26 | def set_default_values(self):
27 | self.cbb_devisesFrom.addItems(sorted(list(self.c.currencies)))
28 | self.cbb_devisesTo.addItems(sorted(list(self.c.currencies)))
29 | self.cbb_devisesFrom.setCurrentText("EUR")
30 | self.cbb_devisesTo.setCurrentText("EUR")
31 | self.le_montant.setValue(100)
32 | self.le_montantConverti.setValue(100)
33 | self.le_montant.setRange(1, 1000000)
34 | self.le_montantConverti.setRange(1, 1000000)
35 |
36 |
37 | app = QtWidgets.QApplication([])
38 | win = App()
39 | win.show()
40 | app.exec_()
--------------------------------------------------------------------------------
/app-001_convertisseur-devises/Session 195/app.py:
--------------------------------------------------------------------------------
1 | from PySide2 import QtWidgets, QtGui, QtCore
2 | import currency_converter
3 |
4 | class App(QtWidgets.QWidget):
5 | def __init__(self):
6 | super().__init__()
7 | self.c = currency_converter.CurrencyConverter()
8 | self.setWindowTitle("Convertisseur de devises")
9 | self.setup_ui()
10 | self.setup_connections()
11 | self.set_default_values()
12 |
13 | def setup_ui(self):
14 | self.layout = QtWidgets.QHBoxLayout(self)
15 | self.cbb_devisesFrom = QtWidgets.QComboBox()
16 | self.le_montant = QtWidgets.QSpinBox()
17 | self.cbb_devisesTo = QtWidgets.QComboBox()
18 | self.le_montantConverti = QtWidgets.QSpinBox()
19 | self.btn_inverser = QtWidgets.QPushButton("Inverser devises")
20 |
21 | self.layout.addWidget(self.cbb_devisesFrom)
22 | self.layout.addWidget(self.le_montant)
23 | self.layout.addWidget(self.cbb_devisesTo)
24 | self.layout.addWidget(self.le_montantConverti)
25 | self.layout.addWidget(self.btn_inverser)
26 |
27 | def setup_connections(self):
28 | self.cbb_devisesFrom.activated.connect(self.compute)
29 | self.cbb_devisesTo.activated.connect(self.compute)
30 | self.le_montant.valueChanged.connect(self.compute)
31 | self.btn_inverser.clicked.connect(self.inverser_devises)
32 |
33 | def set_default_values(self):
34 | self.cbb_devisesFrom.addItems(sorted(list(self.c.currencies)))
35 | self.cbb_devisesTo.addItems(sorted(list(self.c.currencies)))
36 | self.cbb_devisesFrom.setCurrentText("EUR")
37 | self.cbb_devisesTo.setCurrentText("EUR")
38 | self.le_montant.setValue(100)
39 | self.le_montantConverti.setValue(100)
40 | self.le_montant.setRange(1, 1000000)
41 | self.le_montantConverti.setRange(1, 1000000)
42 |
43 | def compute(self):
44 | print("Compute")
45 |
46 | def inverser_devises(self):
47 | print("Inverser devise")
48 |
49 | app = QtWidgets.QApplication([])
50 | win = App()
51 | win.show()
52 | app.exec_()
--------------------------------------------------------------------------------
/app-001_convertisseur-devises/Session 196/app.py:
--------------------------------------------------------------------------------
1 | from PySide2 import QtWidgets, QtGui, QtCore
2 | import currency_converter
3 |
4 | class App(QtWidgets.QWidget):
5 | def __init__(self):
6 | super().__init__()
7 | self.c = currency_converter.CurrencyConverter()
8 | self.setWindowTitle("Convertisseur de devises")
9 | self.setup_ui()
10 | self.setup_connections()
11 | self.set_default_values()
12 |
13 | def setup_ui(self):
14 | self.layout = QtWidgets.QHBoxLayout(self)
15 | self.cbb_devisesFrom = QtWidgets.QComboBox()
16 | self.le_montant = QtWidgets.QSpinBox()
17 | self.cbb_devisesTo = QtWidgets.QComboBox()
18 | self.le_montantConverti = QtWidgets.QSpinBox()
19 | self.btn_inverser = QtWidgets.QPushButton("Inverser devises")
20 |
21 | self.layout.addWidget(self.cbb_devisesFrom)
22 | self.layout.addWidget(self.le_montant)
23 | self.layout.addWidget(self.cbb_devisesTo)
24 | self.layout.addWidget(self.le_montantConverti)
25 | self.layout.addWidget(self.btn_inverser)
26 |
27 | def setup_connections(self):
28 | self.cbb_devisesFrom.activated.connect(self.compute)
29 | self.cbb_devisesTo.activated.connect(self.compute)
30 | self.le_montant.valueChanged.connect(self.compute)
31 | self.btn_inverser.clicked.connect(self.inverser_devises)
32 |
33 | def set_default_values(self):
34 | self.cbb_devisesFrom.addItems(sorted(list(self.c.currencies)))
35 | self.cbb_devisesTo.addItems(sorted(list(self.c.currencies)))
36 | self.cbb_devisesFrom.setCurrentText("EUR")
37 | self.cbb_devisesTo.setCurrentText("EUR")
38 | self.le_montant.setValue(100)
39 | self.le_montantConverti.setValue(100)
40 | self.le_montant.setRange(1, 1000000)
41 | self.le_montantConverti.setRange(1, 1000000)
42 |
43 | def compute(self):
44 | montant = self.le_montant.value()
45 | deviseFrom = self.cbb_devisesFrom.currentText()
46 | deviseTo = self.cbb_devisesTo.currentText()
47 | resultat = self.c.convert(montant, deviseFrom, deviseTo)
48 | self.le_montantConverti.setValue(resultat)
49 |
50 | def inverser_devises(self):
51 | devise_from = self.cbb_devisesFrom.currentText()
52 | devise_to = self.cbb_devisesTo.currentText()
53 |
54 | self.cbb_devisesFrom.setCurrentText(devise_to)
55 | self.cbb_devisesTo.setCurrentText(devise_from)
56 | self.compute()
57 |
58 | app = QtWidgets.QApplication([])
59 | win = App()
60 | win.show()
61 | app.exec_()
--------------------------------------------------------------------------------
/app-001_convertisseur-devises/Session 197/app.py:
--------------------------------------------------------------------------------
1 | from PySide2 import QtWidgets, QtGui, QtCore
2 | import currency_converter
3 |
4 | class App(QtWidgets.QWidget):
5 | def __init__(self):
6 | super().__init__()
7 | self.c = currency_converter.CurrencyConverter()
8 | self.setWindowTitle("Convertisseur de devises")
9 | self.setup_ui()
10 | self.setup_connections()
11 | self.set_default_values()
12 |
13 | def setup_ui(self):
14 | self.layout = QtWidgets.QHBoxLayout(self)
15 | self.cbb_devisesFrom = QtWidgets.QComboBox()
16 | self.le_montant = QtWidgets.QSpinBox()
17 | self.cbb_devisesTo = QtWidgets.QComboBox()
18 | self.le_montantConverti = QtWidgets.QSpinBox()
19 | self.btn_inverser = QtWidgets.QPushButton("Inverser devises")
20 |
21 | self.layout.addWidget(self.cbb_devisesFrom)
22 | self.layout.addWidget(self.le_montant)
23 | self.layout.addWidget(self.cbb_devisesTo)
24 | self.layout.addWidget(self.le_montantConverti)
25 | self.layout.addWidget(self.btn_inverser)
26 |
27 | def setup_connections(self):
28 | self.cbb_devisesFrom.activated.connect(self.compute)
29 | self.cbb_devisesTo.activated.connect(self.compute)
30 | self.le_montant.valueChanged.connect(self.compute)
31 | self.btn_inverser.clicked.connect(self.inverser_devises)
32 |
33 | def set_default_values(self):
34 | self.cbb_devisesFrom.addItems(sorted(list(self.c.currencies)))
35 | self.cbb_devisesTo.addItems(sorted(list(self.c.currencies)))
36 | self.cbb_devisesFrom.setCurrentText("EUR")
37 | self.cbb_devisesTo.setCurrentText("EUR")
38 | self.le_montant.setValue(100)
39 | self.le_montantConverti.setValue(100)
40 | self.le_montant.setRange(1, 1000000)
41 | self.le_montantConverti.setRange(1, 1000000)
42 |
43 | def compute(self):
44 | montant = self.le_montant.value()
45 | deviseFrom = self.cbb_devisesFrom.currentText()
46 | deviseTo = self.cbb_devisesTo.currentText()
47 |
48 | try:
49 | resultat = self.c.convert(montant, deviseFrom, deviseTo)
50 | except currency_converter.currency_converter.RateNotFoundError:
51 | print("Rate not found")
52 | else:
53 | self.le_montantConverti.setValue(resultat)
54 |
55 | def inverser_devises(self):
56 | devise_from = self.cbb_devisesFrom.currentText()
57 | devise_to = self.cbb_devisesTo.currentText()
58 |
59 | self.cbb_devisesFrom.setCurrentText(devise_to)
60 | self.cbb_devisesTo.setCurrentText(devise_from)
61 | self.compute()
62 |
63 | app = QtWidgets.QApplication([])
64 | win = App()
65 | win.show()
66 | app.exec_()
--------------------------------------------------------------------------------
/app-001_convertisseur-devises/Session 198/app.py:
--------------------------------------------------------------------------------
1 | from PySide2 import QtWidgets, QtGui, QtCore
2 | import currency_converter
3 |
4 | class App(QtWidgets.QWidget):
5 | def __init__(self):
6 | super().__init__()
7 | self.c = currency_converter.CurrencyConverter()
8 | self.setWindowTitle("Convertisseur de devises")
9 | self.setup_ui()
10 | self.setup_connections()
11 | self.set_default_values()
12 | self.setup_css()
13 | self.resize(500, 50)
14 |
15 | def setup_ui(self):
16 | self.layout = QtWidgets.QHBoxLayout(self)
17 | self.cbb_devisesFrom = QtWidgets.QComboBox()
18 | self.le_montant = QtWidgets.QSpinBox()
19 | self.cbb_devisesTo = QtWidgets.QComboBox()
20 | self.le_montantConverti = QtWidgets.QSpinBox()
21 | self.btn_inverser = QtWidgets.QPushButton("Inverser devises")
22 |
23 | self.layout.addWidget(self.cbb_devisesFrom)
24 | self.layout.addWidget(self.le_montant)
25 | self.layout.addWidget(self.cbb_devisesTo)
26 | self.layout.addWidget(self.le_montantConverti)
27 | self.layout.addWidget(self.btn_inverser)
28 |
29 | def setup_connections(self):
30 | self.cbb_devisesFrom.activated.connect(self.compute)
31 | self.cbb_devisesTo.activated.connect(self.compute)
32 | self.le_montant.valueChanged.connect(self.compute)
33 | self.btn_inverser.clicked.connect(self.inverser_devises)
34 |
35 | def setup_css(self):
36 | self.setStyleSheet("""
37 | background-color: rgb(30, 30, 30);
38 | color: rgb(240, 240, 240);
39 | border: none;
40 | """)
41 | style = """
42 | QComboBox::down-arrow {
43 | image: none;
44 | border-width: 0px;
45 | }
46 | QComboBox::drop-down {
47 | border-width: 0px;
48 | }
49 | """
50 | self.cbb_devisesFrom.setStyleSheet(style)
51 | self.cbb_devisesTo.setStyleSheet(style)
52 |
53 | def set_default_values(self):
54 | self.cbb_devisesFrom.addItems(sorted(list(self.c.currencies)))
55 | self.cbb_devisesTo.addItems(sorted(list(self.c.currencies)))
56 | self.cbb_devisesFrom.setCurrentText("EUR")
57 | self.cbb_devisesTo.setCurrentText("EUR")
58 | self.le_montant.setValue(100)
59 | self.le_montantConverti.setValue(100)
60 | self.le_montant.setRange(1, 1000000)
61 | self.le_montantConverti.setRange(1, 1000000)
62 |
63 | def compute(self):
64 | montant = self.le_montant.value()
65 | deviseFrom = self.cbb_devisesFrom.currentText()
66 | deviseTo = self.cbb_devisesTo.currentText()
67 |
68 | try:
69 | resultat = self.c.convert(montant, deviseFrom, deviseTo)
70 | except currency_converter.currency_converter.RateNotFoundError:
71 | print("Rate not found")
72 | else:
73 | self.le_montantConverti.setValue(resultat)
74 |
75 | def inverser_devises(self):
76 | devise_from = self.cbb_devisesFrom.currentText()
77 | devise_to = self.cbb_devisesTo.currentText()
78 |
79 | self.cbb_devisesFrom.setCurrentText(devise_to)
80 | self.cbb_devisesTo.setCurrentText(devise_from)
81 | self.compute()
82 |
83 | app = QtWidgets.QApplication([])
84 | win = App()
85 | win.show()
86 | app.exec_()
--------------------------------------------------------------------------------
/app-002_cineclub-api/Session 202/app.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/app-002_cineclub-api/Session 202/app.py
--------------------------------------------------------------------------------
/app-002_cineclub-api/Session 202/data/movies.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/app-002_cineclub-api/Session 202/data/movies.json
--------------------------------------------------------------------------------
/app-002_cineclub-api/Session 202/movie.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/app-002_cineclub-api/Session 202/movie.py
--------------------------------------------------------------------------------
/app-002_cineclub-api/Session 206/app.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/app-002_cineclub-api/Session 206/app.py
--------------------------------------------------------------------------------
/app-002_cineclub-api/Session 206/data/movies.json:
--------------------------------------------------------------------------------
1 | [
2 | "Harry Potter",
3 | "Spider Man"
4 | ]
--------------------------------------------------------------------------------
/app-002_cineclub-api/Session 206/movie.py:
--------------------------------------------------------------------------------
1 | class Movie:
2 | def __init__(self, title):
3 | self.title = title.title()
4 |
5 | def __str__(self):
6 | return self.title
7 |
8 | if __name__ == "__main__":
9 | m = Movie("harry potter")
10 | print(m)
--------------------------------------------------------------------------------
/app-002_cineclub-api/Session 208/app.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/app-002_cineclub-api/Session 208/app.py
--------------------------------------------------------------------------------
/app-002_cineclub-api/Session 208/data/movies.json:
--------------------------------------------------------------------------------
1 | [
2 | "Harry Potter",
3 | "Spider Man"
4 | ]
--------------------------------------------------------------------------------
/app-002_cineclub-api/Session 208/movie.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 |
4 | CUR_DIR = os.path.dirname(__file__)
5 | DATA_FILE = os.path.join(CUR_DIR, "data", "movies.json")
6 |
7 | class Movie:
8 | def __init__(self, title):
9 | self.title = title.title()
10 |
11 | def __str__(self):
12 | return self.title
13 |
14 | def _get_movies(self):
15 | with open(DATA_FILE, "r") as f:
16 | return json.load(f)
17 |
18 | def _write_movies(self, movies):
19 | with open(DATA_FILE, "w") as f:
20 | json.dump(movies, f, indent=4)
21 |
22 | if __name__ == "__main__":
23 | m = Movie("harry potter")
24 | m._get_movies()
25 | m._write_movies()
26 |
27 | # m.add_to_movies()
28 | # m.remove_from_movies()
--------------------------------------------------------------------------------
/app-002_cineclub-api/Session 210/app.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/app-002_cineclub-api/Session 210/app.py
--------------------------------------------------------------------------------
/app-002_cineclub-api/Session 210/data/movies.json:
--------------------------------------------------------------------------------
1 | [
2 | "Harry Potter",
3 | "Spider Man"
4 | ]
--------------------------------------------------------------------------------
/app-002_cineclub-api/Session 210/movie.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 |
4 | CUR_DIR = os.path.dirname(__file__)
5 | DATA_FILE = os.path.join(CUR_DIR, "data", "movies.json")
6 |
7 | class Movie:
8 | def __init__(self, title):
9 | self.title = title.title()
10 |
11 | def __str__(self):
12 | return self.title
13 |
14 | def _get_movies(self):
15 | with open(DATA_FILE, "r") as f:
16 | return json.load(f)
17 |
18 | def _write_movies(self, movies):
19 | with open(DATA_FILE, "w") as f:
20 | json.dump(movies, f, indent=4)
21 |
22 | def add_to_movies(self):
23 | movies = self._get_movies()
24 |
25 | if self.title not in movies:
26 | movies.append(self.title)
27 | self._write_movies(movies)
28 | return True
29 | else:
30 | print(f"Le film {self.title} est déjà enregistré.")
31 | return False
32 |
33 | if __name__ == "__main__":
34 | m = Movie("harry potter")
--------------------------------------------------------------------------------
/app-002_cineclub-api/Session 212/app.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/app-002_cineclub-api/Session 212/app.py
--------------------------------------------------------------------------------
/app-002_cineclub-api/Session 212/data/movies.json:
--------------------------------------------------------------------------------
1 | [
2 | "Harry Potter",
3 | "Spider Man"
4 | ]
--------------------------------------------------------------------------------
/app-002_cineclub-api/Session 212/movie.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 |
4 | CUR_DIR = os.path.dirname(__file__)
5 | DATA_FILE = os.path.join(CUR_DIR, "data", "movies.json")
6 |
7 | class Movie:
8 | def __init__(self, title):
9 | self.title = title.title()
10 |
11 | def __str__(self):
12 | return self.title
13 |
14 | def _get_movies(self):
15 | with open(DATA_FILE, "r") as f:
16 | return json.load(f)
17 |
18 | def _write_movies(self, movies):
19 | with open(DATA_FILE, "w") as f:
20 | json.dump(movies, f, indent=4)
21 |
22 | def add_to_movies(self):
23 | movies = self._get_movies()
24 |
25 | if self.title not in movies:
26 | movies.append(self.title)
27 | self._write_movies(movies)
28 | return True
29 | else:
30 | print(f"Le film {self.title} est déjà enregistré.")
31 | return False
32 |
33 | def remove_from_movies(self):
34 | movies = self._get_movies()
35 |
36 | if self.title in movies:
37 | movies.remove(self.title)
38 | self._write_movies(movies)
39 |
40 | if __name__ == "__main__":
41 | m = Movie("harry potter")
42 | m.remove_from_movies()
--------------------------------------------------------------------------------
/app-002_cineclub-api/Session 214/app.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/app-002_cineclub-api/Session 214/app.py
--------------------------------------------------------------------------------
/app-002_cineclub-api/Session 214/data/movies.json:
--------------------------------------------------------------------------------
1 | [
2 | "Harry Potter",
3 | "Spider Man"
4 | ]
--------------------------------------------------------------------------------
/app-002_cineclub-api/Session 214/movie.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 |
4 | CUR_DIR = os.path.dirname(__file__)
5 | DATA_FILE = os.path.join(CUR_DIR, "data", "movies.json")
6 |
7 | def get_movies():
8 | movies_instances = []
9 | with open(DATA_FILE, "r") as f:
10 | movies = json.load(f)
11 | for movie_title in movies:
12 | movies_instances.append(Movie(movie_title))
13 |
14 | return movies_instances
15 |
16 | class Movie:
17 | def __init__(self, title):
18 | self.title = title.title()
19 |
20 | def __str__(self):
21 | return self.title
22 |
23 | def _get_movies(self):
24 | with open(DATA_FILE, "r") as f:
25 | return json.load(f)
26 |
27 | def _write_movies(self, movies):
28 | with open(DATA_FILE, "w") as f:
29 | json.dump(movies, f, indent=4)
30 |
31 | def add_to_movies(self):
32 | movies = self._get_movies()
33 |
34 | if self.title not in movies:
35 | movies.append(self.title)
36 | self._write_movies(movies)
37 | return True
38 | else:
39 | print(f"Le film {self.title} est déjà enregistré.")
40 | return False
41 |
42 | def remove_from_movies(self):
43 | movies = self._get_movies()
44 |
45 | if self.title in movies:
46 | movies.remove(self.title)
47 | self._write_movies(movies)
48 |
49 | if __name__ == "__main__":
50 | get_movies()
--------------------------------------------------------------------------------
/app-002_cineclub-gui/Session 216/app.py:
--------------------------------------------------------------------------------
1 | from PySide2 import QtWidgets, QtCore
2 |
3 | class App(QtWidgets.QWidget):
4 | def __init__(self):
5 | super().__init__()
6 | self.setWindowTitle("Ciné Club")
7 | self.setup_ui()
8 |
9 | def setup_ui(self):
10 | self.main_layout = QtWidgets.QVBoxLayout(self)
11 |
12 | self.le_movieTitle = QtWidgets.QLineEdit()
13 | self.btn_addMovie = QtWidgets.QPushButton("Ajouter un film")
14 | self.lw_movies = QtWidgets.QListWidget()
15 | self.lw_movies.setSelectionMode(QtWidgets.QListWidget.ExtendedSelection)
16 | self.btn_removeMovie = QtWidgets.QPushButton("Supprimer le(s) film(s)")
17 |
18 | self.main_layout.addWidget(self.le_movieTitle)
19 | self.main_layout.addWidget(self.btn_addMovie)
20 | self.main_layout.addWidget(self.lw_movies)
21 | self.main_layout.addWidget(self.btn_removeMovie)
22 |
23 |
24 | app = QtWidgets.QApplication([])
25 | win = App()
26 | win.show()
27 | app.exec_()
--------------------------------------------------------------------------------
/app-002_cineclub-gui/Session 216/data/movies.json:
--------------------------------------------------------------------------------
1 | [
2 | "Harry Potter",
3 | "Spider Man"
4 | ]
--------------------------------------------------------------------------------
/app-002_cineclub-gui/Session 216/movie.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 |
4 | CUR_DIR = os.path.dirname(__file__)
5 | DATA_FILE = os.path.join(CUR_DIR, "data", "movies.json")
6 |
7 | def get_movies():
8 | movies_instances = []
9 | with open(DATA_FILE, "r") as f:
10 | movies = json.load(f)
11 | for movie_title in movies:
12 | movies_instances.append(Movie(movie_title))
13 |
14 | return movies_instances
15 |
16 | class Movie:
17 | def __init__(self, title):
18 | self.title = title.title()
19 |
20 | def __str__(self):
21 | return self.title
22 |
23 | def _get_movies(self):
24 | with open(DATA_FILE, "r") as f:
25 | return json.load(f)
26 |
27 | def _write_movies(self, movies):
28 | with open(DATA_FILE, "w") as f:
29 | json.dump(movies, f, indent=4)
30 |
31 | def add_to_movies(self):
32 | movies = self._get_movies()
33 |
34 | if self.title not in movies:
35 | movies.append(self.title)
36 | self._write_movies(movies)
37 | return True
38 | else:
39 | print(f"Le film {self.title} est déjà enregistré.")
40 | return False
41 |
42 | def remove_from_movies(self):
43 | movies = self._get_movies()
44 |
45 | if self.title in movies:
46 | movies.remove(self.title)
47 | self._write_movies(movies)
48 |
49 | if __name__ == "__main__":
50 | m = Movie("harry potter")
51 | m.remove_from_movies()
--------------------------------------------------------------------------------
/app-002_cineclub-gui/Session 218/app.py:
--------------------------------------------------------------------------------
1 | from PySide2 import QtWidgets, QtCore
2 | from movie import Movie, get_movies
3 |
4 | class App(QtWidgets.QWidget):
5 | def __init__(self):
6 | super().__init__()
7 | self.setWindowTitle("Ciné Club")
8 | self.setup_ui()
9 | self.populate_movies()
10 |
11 | def setup_ui(self):
12 | self.main_layout = QtWidgets.QVBoxLayout(self)
13 |
14 | self.le_movieTitle = QtWidgets.QLineEdit()
15 | self.btn_addMovie = QtWidgets.QPushButton("Ajouter un film")
16 | self.lw_movies = QtWidgets.QListWidget()
17 | self.lw_movies.setSelectionMode(QtWidgets.QListWidget.ExtendedSelection)
18 | self.btn_removeMovie = QtWidgets.QPushButton("Supprimer le(s) film(s)")
19 |
20 | self.main_layout.addWidget(self.le_movieTitle)
21 | self.main_layout.addWidget(self.btn_addMovie)
22 | self.main_layout.addWidget(self.lw_movies)
23 | self.main_layout.addWidget(self.btn_removeMovie)
24 |
25 | def populate_movies(self):
26 | self.lw_movies.clear()
27 | movies = get_movies()
28 | for movie in movies:
29 | lw_item = QtWidgets.QListWidgetItem(movie.title)
30 | lw_item.setData(QtCore.Qt.UserRole, movie)
31 | self.lw_movies.addItem(lw_item)
32 |
33 | app = QtWidgets.QApplication([])
34 | win = App()
35 | win.show()
36 | app.exec_()
--------------------------------------------------------------------------------
/app-002_cineclub-gui/Session 218/data/movies.json:
--------------------------------------------------------------------------------
1 | [
2 | "Harry Potter",
3 | "Spider Man"
4 | ]
--------------------------------------------------------------------------------
/app-002_cineclub-gui/Session 218/movie.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 |
4 | CUR_DIR = os.path.dirname(__file__)
5 | DATA_FILE = os.path.join(CUR_DIR, "data", "movies.json")
6 |
7 | def get_movies():
8 | movies_instances = []
9 | with open(DATA_FILE, "r") as f:
10 | movies = json.load(f)
11 | for movie_title in movies:
12 | movies_instances.append(Movie(movie_title))
13 |
14 | return movies_instances
15 |
16 | class Movie:
17 | def __init__(self, title):
18 | self.title = title.title()
19 |
20 | def __str__(self):
21 | return self.title
22 |
23 | def _get_movies(self):
24 | with open(DATA_FILE, "r") as f:
25 | return json.load(f)
26 |
27 | def _write_movies(self, movies):
28 | with open(DATA_FILE, "w") as f:
29 | json.dump(movies, f, indent=4)
30 |
31 | def add_to_movies(self):
32 | movies = self._get_movies()
33 |
34 | if self.title not in movies:
35 | movies.append(self.title)
36 | self._write_movies(movies)
37 | return True
38 | else:
39 | print(f"Le film {self.title} est déjà enregistré.")
40 | return False
41 |
42 | def remove_from_movies(self):
43 | movies = self._get_movies()
44 |
45 | if self.title in movies:
46 | movies.remove(self.title)
47 | self._write_movies(movies)
48 |
49 | if __name__ == "__main__":
50 | m = Movie("harry potter")
51 | m.remove_from_movies()
--------------------------------------------------------------------------------
/app-002_cineclub-gui/Session 220/app.py:
--------------------------------------------------------------------------------
1 | from PySide2 import QtWidgets, QtCore
2 | from movie import Movie, get_movies
3 |
4 | class App(QtWidgets.QWidget):
5 | def __init__(self):
6 | super().__init__()
7 | self.setWindowTitle("Ciné Club")
8 | self.setup_ui()
9 | self.setup_connections()
10 | self.populate_movies()
11 |
12 | def setup_ui(self):
13 | self.main_layout = QtWidgets.QVBoxLayout(self)
14 |
15 | self.le_movieTitle = QtWidgets.QLineEdit()
16 | self.btn_addMovie = QtWidgets.QPushButton("Ajouter un film")
17 | self.lw_movies = QtWidgets.QListWidget()
18 | self.lw_movies.setSelectionMode(QtWidgets.QListWidget.ExtendedSelection)
19 | self.btn_removeMovie = QtWidgets.QPushButton("Supprimer le(s) film(s)")
20 |
21 | self.main_layout.addWidget(self.le_movieTitle)
22 | self.main_layout.addWidget(self.btn_addMovie)
23 | self.main_layout.addWidget(self.lw_movies)
24 | self.main_layout.addWidget(self.btn_removeMovie)
25 |
26 | def setup_connections(self):
27 | self.btn_addMovie.clicked.connect(self.add_movie)
28 | self.le_movieTitle.returnPressed.connect(self.add_movie)
29 | self.btn_removeMovie.clicked.connect(self.remove_movie)
30 |
31 | def populate_movies(self):
32 | self.lw_movies.clear()
33 | movies = get_movies()
34 | for movie in movies:
35 | lw_item = QtWidgets.QListWidgetItem(movie.title)
36 | lw_item.setData(QtCore.Qt.UserRole, movie)
37 | self.lw_movies.addItem(lw_item)
38 |
39 | def add_movie(self):
40 | print("On ajoute un film")
41 |
42 | def remove_movie(self):
43 | print("On supprime un film")
44 |
45 | app = QtWidgets.QApplication([])
46 | win = App()
47 | win.show()
48 | app.exec_()
--------------------------------------------------------------------------------
/app-002_cineclub-gui/Session 220/data/movies.json:
--------------------------------------------------------------------------------
1 | [
2 | "Harry Potter",
3 | "Spider Man"
4 | ]
--------------------------------------------------------------------------------
/app-002_cineclub-gui/Session 220/movie.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 |
4 | CUR_DIR = os.path.dirname(__file__)
5 | DATA_FILE = os.path.join(CUR_DIR, "data", "movies.json")
6 |
7 | def get_movies():
8 | movies_instances = []
9 | with open(DATA_FILE, "r") as f:
10 | movies = json.load(f)
11 | for movie_title in movies:
12 | movies_instances.append(Movie(movie_title))
13 |
14 | return movies_instances
15 |
16 | class Movie:
17 | def __init__(self, title):
18 | self.title = title.title()
19 |
20 | def __str__(self):
21 | return self.title
22 |
23 | def _get_movies(self):
24 | with open(DATA_FILE, "r") as f:
25 | return json.load(f)
26 |
27 | def _write_movies(self, movies):
28 | with open(DATA_FILE, "w") as f:
29 | json.dump(movies, f, indent=4)
30 |
31 | def add_to_movies(self):
32 | movies = self._get_movies()
33 |
34 | if self.title not in movies:
35 | movies.append(self.title)
36 | self._write_movies(movies)
37 | return True
38 | else:
39 | print(f"Le film {self.title} est déjà enregistré.")
40 | return False
41 |
42 | def remove_from_movies(self):
43 | movies = self._get_movies()
44 |
45 | if self.title in movies:
46 | movies.remove(self.title)
47 | self._write_movies(movies)
48 |
49 | if __name__ == "__main__":
50 | m = Movie("harry potter")
51 | m.remove_from_movies()
--------------------------------------------------------------------------------
/app-002_cineclub-gui/Session 222/app.py:
--------------------------------------------------------------------------------
1 | from PySide2 import QtWidgets, QtCore
2 | from movie import Movie, get_movies
3 |
4 | class App(QtWidgets.QWidget):
5 | def __init__(self):
6 | super().__init__()
7 | self.setWindowTitle("Ciné Club")
8 | self.setup_ui()
9 | self.setup_connections()
10 | self.populate_movies()
11 |
12 | def setup_ui(self):
13 | self.main_layout = QtWidgets.QVBoxLayout(self)
14 |
15 | self.le_movieTitle = QtWidgets.QLineEdit()
16 | self.btn_addMovie = QtWidgets.QPushButton("Ajouter un film")
17 | self.lw_movies = QtWidgets.QListWidget()
18 | self.lw_movies.setSelectionMode(QtWidgets.QListWidget.ExtendedSelection)
19 | self.btn_removeMovie = QtWidgets.QPushButton("Supprimer le(s) film(s)")
20 |
21 | self.main_layout.addWidget(self.le_movieTitle)
22 | self.main_layout.addWidget(self.btn_addMovie)
23 | self.main_layout.addWidget(self.lw_movies)
24 | self.main_layout.addWidget(self.btn_removeMovie)
25 |
26 | def setup_connections(self):
27 | self.btn_addMovie.clicked.connect(self.add_movie)
28 | self.le_movieTitle.returnPressed.connect(self.add_movie)
29 | self.btn_removeMovie.clicked.connect(self.remove_movie)
30 |
31 | def populate_movies(self):
32 | self.lw_movies.clear()
33 | movies = get_movies()
34 | for movie in movies:
35 | lw_item = QtWidgets.QListWidgetItem(movie.title)
36 | lw_item.setData(QtCore.Qt.UserRole, movie)
37 | self.lw_movies.addItem(lw_item)
38 |
39 | def add_movie(self):
40 | movie_title = self.le_movieTitle.text()
41 | if not movie_title:
42 | return False
43 |
44 | movie = Movie(title=movie_title)
45 | result = movie.add_to_movies()
46 | if result:
47 | lw_item = QtWidgets.QListWidgetItem(movie.title)
48 | lw_item.setData(QtCore.Qt.UserRole, movie)
49 | self.lw_movies.addItem(lw_item)
50 | self.le_movieTitle.setText("")
51 |
52 | def remove_movie(self):
53 | print("On supprime un film")
54 |
55 | app = QtWidgets.QApplication([])
56 | win = App()
57 | win.show()
58 | app.exec_()
--------------------------------------------------------------------------------
/app-002_cineclub-gui/Session 222/data/movies.json:
--------------------------------------------------------------------------------
1 | [
2 | "Harry Potter",
3 | "Spider Man"
4 | ]
--------------------------------------------------------------------------------
/app-002_cineclub-gui/Session 222/movie.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 |
4 | CUR_DIR = os.path.dirname(__file__)
5 | DATA_FILE = os.path.join(CUR_DIR, "data", "movies.json")
6 |
7 | def get_movies():
8 | movies_instances = []
9 | with open(DATA_FILE, "r") as f:
10 | movies = json.load(f)
11 | for movie_title in movies:
12 | movies_instances.append(Movie(movie_title))
13 |
14 | return movies_instances
15 |
16 | class Movie:
17 | def __init__(self, title):
18 | self.title = title.title()
19 |
20 | def __str__(self):
21 | return self.title
22 |
23 | def _get_movies(self):
24 | with open(DATA_FILE, "r") as f:
25 | return json.load(f)
26 |
27 | def _write_movies(self, movies):
28 | with open(DATA_FILE, "w") as f:
29 | json.dump(movies, f, indent=4)
30 |
31 | def add_to_movies(self):
32 | movies = self._get_movies()
33 |
34 | if self.title not in movies:
35 | movies.append(self.title)
36 | self._write_movies(movies)
37 | return True
38 | else:
39 | print(f"Le film {self.title} est déjà enregistré.")
40 | return False
41 |
42 | def remove_from_movies(self):
43 | movies = self._get_movies()
44 |
45 | if self.title in movies:
46 | movies.remove(self.title)
47 | self._write_movies(movies)
48 |
49 | if __name__ == "__main__":
50 | m = Movie("harry potter")
51 | m.remove_from_movies()
--------------------------------------------------------------------------------
/app-002_cineclub-gui/Session 223/app.py:
--------------------------------------------------------------------------------
1 | from PySide2 import QtWidgets, QtCore
2 | from movie import Movie, get_movies
3 |
4 | class App(QtWidgets.QWidget):
5 | def __init__(self):
6 | super().__init__()
7 | self.setWindowTitle("Ciné Club")
8 | self.setup_ui()
9 | self.setup_connections()
10 | self.populate_movies()
11 |
12 | def setup_ui(self):
13 | self.main_layout = QtWidgets.QVBoxLayout(self)
14 |
15 | self.le_movieTitle = QtWidgets.QLineEdit()
16 | self.btn_addMovie = QtWidgets.QPushButton("Ajouter un film")
17 | self.lw_movies = QtWidgets.QListWidget()
18 | self.lw_movies.setSelectionMode(QtWidgets.QListWidget.ExtendedSelection)
19 | self.btn_removeMovie = QtWidgets.QPushButton("Supprimer le(s) film(s)")
20 |
21 | self.main_layout.addWidget(self.le_movieTitle)
22 | self.main_layout.addWidget(self.btn_addMovie)
23 | self.main_layout.addWidget(self.lw_movies)
24 | self.main_layout.addWidget(self.btn_removeMovie)
25 |
26 | def setup_connections(self):
27 | self.btn_addMovie.clicked.connect(self.add_movie)
28 | self.le_movieTitle.returnPressed.connect(self.add_movie)
29 | self.btn_removeMovie.clicked.connect(self.remove_movie)
30 |
31 | def populate_movies(self):
32 | self.lw_movies.clear()
33 | movies = get_movies()
34 | for movie in movies:
35 | lw_item = QtWidgets.QListWidgetItem(movie.title)
36 | lw_item.setData(QtCore.Qt.UserRole, movie)
37 | self.lw_movies.addItem(lw_item)
38 |
39 | def add_movie(self):
40 | movie_title = self.le_movieTitle.text()
41 | if not movie_title:
42 | return False
43 |
44 | movie = Movie(title=movie_title)
45 | result = movie.add_to_movies()
46 | if result:
47 | lw_item = QtWidgets.QListWidgetItem(movie.title)
48 | lw_item.setData(QtCore.Qt.UserRole, movie)
49 | self.lw_movies.addItem(lw_item)
50 | self.le_movieTitle.setText("")
51 |
52 | def remove_movie(self):
53 | for selected_item in self.lw_movies.selectedItems():
54 | movie = selected_item.data(QtCore.Qt.UserRole)
55 | movie.remove_from_movies()
56 | self.lw_movies.takeItem(self.lw_movies.row(selected_item))
57 |
58 | app = QtWidgets.QApplication([])
59 | win = App()
60 | win.show()
61 | app.exec_()
--------------------------------------------------------------------------------
/app-002_cineclub-gui/Session 223/data/movies.json:
--------------------------------------------------------------------------------
1 | [
2 | "Harry Potter",
3 | "Spider Man"
4 | ]
--------------------------------------------------------------------------------
/app-002_cineclub-gui/Session 223/movie.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 |
4 | CUR_DIR = os.path.dirname(__file__)
5 | DATA_FILE = os.path.join(CUR_DIR, "data", "movies.json")
6 |
7 | def get_movies():
8 | movies_instances = []
9 | with open(DATA_FILE, "r") as f:
10 | movies = json.load(f)
11 | for movie_title in movies:
12 | movies_instances.append(Movie(movie_title))
13 |
14 | return movies_instances
15 |
16 | class Movie:
17 | def __init__(self, title):
18 | self.title = title.title()
19 |
20 | def __str__(self):
21 | return self.title
22 |
23 | def _get_movies(self):
24 | with open(DATA_FILE, "r") as f:
25 | return json.load(f)
26 |
27 | def _write_movies(self, movies):
28 | with open(DATA_FILE, "w") as f:
29 | json.dump(movies, f, indent=4)
30 |
31 | def add_to_movies(self):
32 | movies = self._get_movies()
33 |
34 | if self.title not in movies:
35 | movies.append(self.title)
36 | self._write_movies(movies)
37 | return True
38 | else:
39 | print(f"Le film {self.title} est déjà enregistré.")
40 | return False
41 |
42 | def remove_from_movies(self):
43 | movies = self._get_movies()
44 |
45 | if self.title in movies:
46 | movies.remove(self.title)
47 | self._write_movies(movies)
48 |
49 | if __name__ == "__main__":
50 | m = Movie("harry potter")
51 | m.remove_from_movies()
--------------------------------------------------------------------------------
/app-003_site-web-django/requirements.txt:
--------------------------------------------------------------------------------
1 | asgiref==3.3.1
2 | Django==3.1.6
3 | pytz==2021.1
4 | sqlparse==0.4.1
5 |
--------------------------------------------------------------------------------
/app-003_site-web-django/src/DocBlog/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/app-003_site-web-django/src/DocBlog/__init__.py
--------------------------------------------------------------------------------
/app-003_site-web-django/src/DocBlog/asgi.py:
--------------------------------------------------------------------------------
1 | """
2 | ASGI config for DocBlog project.
3 |
4 | It exposes the ASGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.asgi import get_asgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'DocBlog.settings')
15 |
16 | application = get_asgi_application()
17 |
--------------------------------------------------------------------------------
/app-003_site-web-django/src/DocBlog/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for DocBlog project.
3 |
4 | Generated by 'django-admin startproject' using Django 3.1.6.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.1/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/3.1/ref/settings/
11 | """
12 | import os
13 | from pathlib import Path
14 |
15 | # Build paths inside the project like this: BASE_DIR / 'subdir'.
16 | BASE_DIR = Path(__file__).resolve().parent.parent
17 |
18 | # Quick-start development settings - unsuitable for production
19 | # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
20 |
21 | # SECURITY WARNING: keep the secret key used in production secret!
22 | SECRET_KEY = '6ft^t^q*-o194fx^8$d$4dsqz1gu(@b-8wv=*$7y-tc8^l*_$q'
23 |
24 | # SECURITY WARNING: don't run with debug turned on in production!
25 | DEBUG = True
26 | ALLOWED_HOSTS = []
27 |
28 | # Application definition
29 |
30 | INSTALLED_APPS = [
31 | 'django.contrib.admin',
32 | 'django.contrib.auth',
33 | 'django.contrib.contenttypes',
34 | 'django.contrib.sessions',
35 | 'django.contrib.messages',
36 | 'django.contrib.staticfiles',
37 | 'blog'
38 | ]
39 |
40 | MIDDLEWARE = [
41 | 'django.middleware.security.SecurityMiddleware',
42 | 'django.contrib.sessions.middleware.SessionMiddleware',
43 | 'django.middleware.common.CommonMiddleware',
44 | 'django.middleware.csrf.CsrfViewMiddleware',
45 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
46 | 'django.contrib.messages.middleware.MessageMiddleware',
47 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
48 | ]
49 |
50 | ROOT_URLCONF = 'DocBlog.urls'
51 |
52 | TEMPLATES = [
53 | {
54 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
55 | 'DIRS': [os.path.join(BASE_DIR, "DocBlog/templates")],
56 | 'APP_DIRS': True,
57 | 'OPTIONS': {
58 | 'context_processors': [
59 | 'django.template.context_processors.debug',
60 | 'django.template.context_processors.request',
61 | 'django.contrib.auth.context_processors.auth',
62 | 'django.contrib.messages.context_processors.messages',
63 | ],
64 | },
65 | },
66 | ]
67 |
68 | WSGI_APPLICATION = 'DocBlog.wsgi.application'
69 |
70 | # Database
71 | # https://docs.djangoproject.com/en/3.1/ref/settings/#databases
72 |
73 | DATABASES = {
74 | 'default': {
75 | 'ENGINE': 'django.db.backends.sqlite3',
76 | 'NAME': BASE_DIR / 'db.sqlite3',
77 | }
78 | }
79 |
80 | # Password validation
81 | # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
82 |
83 | AUTH_PASSWORD_VALIDATORS = [
84 | {
85 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
86 | },
87 | {
88 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
89 | },
90 | {
91 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
92 | },
93 | {
94 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
95 | },
96 | ]
97 |
98 | # Internationalization
99 | # https://docs.djangoproject.com/en/3.1/topics/i18n/
100 |
101 | LANGUAGE_CODE = 'fr-FR'
102 |
103 | TIME_ZONE = 'UTC'
104 |
105 | USE_I18N = True
106 |
107 | USE_L10N = True
108 |
109 | USE_TZ = True
110 |
111 | # Static files (CSS, JavaScript, Images)
112 | # https://docs.djangoproject.com/en/3.1/howto/static-files/
113 |
114 | STATIC_URL = '/static/'
115 | STATICFILES_DIRS = [
116 | os.path.join(BASE_DIR, "DocBlog/static")
117 | ]
--------------------------------------------------------------------------------
/app-003_site-web-django/src/DocBlog/static/css/background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/app-003_site-web-django/src/DocBlog/static/css/background.jpg
--------------------------------------------------------------------------------
/app-003_site-web-django/src/DocBlog/static/css/style.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Lato&display=swap');
2 |
3 | html, body {
4 | height: 100%;
5 | margin: 0;
6 | border: 0;
7 | font-family: 'Lato', sans-serif;
8 | }
9 |
10 | body {
11 | background-image: url("background.jpg");
12 | background-position: center;
13 | background-repeat: no-repeat;
14 | background-size: cover;
15 | }
16 |
17 | .container {
18 | height: 100%;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: 2rem;
24 | color: white;
25 | background-color: rgba(0, 0, 0, .5);
26 | }
--------------------------------------------------------------------------------
/app-003_site-web-django/src/DocBlog/templates/DocBlog/index.html:
--------------------------------------------------------------------------------
1 | {% load static %}
2 |
3 |
4 |
5 |
6 | Mon site web
7 |
8 |
9 |
10 |
11 |
Bienvenue sur mon site
12 | Aujourd'hui nous sommes le {{ date|date:"d F Y" }}
13 | Il est actuellement {{ date|date:"H\hi" }}
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app-003_site-web-django/src/DocBlog/urls.py:
--------------------------------------------------------------------------------
1 | """DocBlog URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/3.1/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: path('', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.urls import include, path
14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
15 | """
16 | from django.contrib import admin
17 | from django.urls import path, include
18 |
19 | from .views import index
20 |
21 | urlpatterns = [
22 | path('', index, name="index"),
23 | path('blog/', include("blog.urls")),
24 | path('admin/', admin.site.urls),
25 | ]
26 |
--------------------------------------------------------------------------------
/app-003_site-web-django/src/DocBlog/views.py:
--------------------------------------------------------------------------------
1 | from datetime import datetime
2 |
3 | from django.shortcuts import render
4 |
5 |
6 | def index(request):
7 | return render(request, "DocBlog/index.html", context={"date": datetime.today()})
8 |
--------------------------------------------------------------------------------
/app-003_site-web-django/src/DocBlog/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for DocBlog project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'DocBlog.settings')
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/app-003_site-web-django/src/blog/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/app-003_site-web-django/src/blog/__init__.py
--------------------------------------------------------------------------------
/app-003_site-web-django/src/blog/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/app-003_site-web-django/src/blog/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class BlogConfig(AppConfig):
5 | name = 'blog'
6 |
--------------------------------------------------------------------------------
/app-003_site-web-django/src/blog/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/app-003_site-web-django/src/blog/migrations/__init__.py
--------------------------------------------------------------------------------
/app-003_site-web-django/src/blog/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 | # Create your models here.
4 |
--------------------------------------------------------------------------------
/app-003_site-web-django/src/blog/templates/blog/article_01.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Article 01
6 |
7 |
8 | Article 01
9 |
10 |
--------------------------------------------------------------------------------
/app-003_site-web-django/src/blog/templates/blog/article_02.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Article 02
6 |
7 |
8 | Article 02
9 |
10 |
--------------------------------------------------------------------------------
/app-003_site-web-django/src/blog/templates/blog/article_03.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Article 03
6 |
7 |
8 | Article 03
9 |
10 |
--------------------------------------------------------------------------------
/app-003_site-web-django/src/blog/templates/blog/article_not_found.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Article non trouvé
6 |
7 |
8 | L'article n'existe pas
9 |
10 |
--------------------------------------------------------------------------------
/app-003_site-web-django/src/blog/templates/blog/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Le Blog
6 |
7 |
8 | Le Blog
9 |
10 |
--------------------------------------------------------------------------------
/app-003_site-web-django/src/blog/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/app-003_site-web-django/src/blog/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path
2 | from .views import index, article
3 |
4 | urlpatterns = [
5 | path('', index, name="blog-index"),
6 | path('article-/', article, name="blog-article"),
7 | ]
8 |
--------------------------------------------------------------------------------
/app-003_site-web-django/src/blog/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render
2 |
3 |
4 | def index(request):
5 | return render(request, "blog/index.html")
6 |
7 |
8 | def article(request, numero_article):
9 | if numero_article in ["01", "02", "03"]:
10 | return render(request, f"blog/article_{numero_article}.html", context={})
11 | return render(request, "blog/article_not_found.html")
12 |
--------------------------------------------------------------------------------
/app-003_site-web-django/src/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """Django's command-line utility for administrative tasks."""
3 | import os
4 | import sys
5 |
6 |
7 | def main():
8 | """Run administrative tasks."""
9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'DocBlog.settings')
10 | try:
11 | from django.core.management import execute_from_command_line
12 | except ImportError as exc:
13 | raise ImportError(
14 | "Couldn't import Django. Are you sure it's installed and "
15 | "available on your PYTHONPATH environment variable? Did you "
16 | "forget to activate a virtual environment?"
17 | ) from exc
18 | execute_from_command_line(sys.argv)
19 |
20 |
21 | if __name__ == '__main__':
22 | main()
23 |
--------------------------------------------------------------------------------
/app-004_bot-discord/config:
--------------------------------------------------------------------------------
1 | TOKEN=VOTRE TOKEN ICI
--------------------------------------------------------------------------------
/app-004_bot-discord/main.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | import discord
4 | from discord.ext import commands
5 | from dotenv import load_dotenv
6 |
7 | load_dotenv(dotenv_path="config")
8 |
9 | default_intents = discord.Intents.default()
10 | default_intents.members = True # Vous devez activer les intents dans les paramètres du Bot
11 | bot = commands.Bot(command_prefix="!", intents=default_intents)
12 |
13 |
14 | @bot.event
15 | async def on_ready():
16 | print("Le bot est connecté.")
17 |
18 |
19 | @bot.event
20 | async def on_member_join(member):
21 | print(f"Un nouveau membre est arrivé : {member.display_name}")
22 |
23 |
24 | @bot.command(name="del")
25 | async def delete(ctx, number: int):
26 | messages = await ctx.channel.history(limit=number + 1).flatten()
27 |
28 | for each_message in messages:
29 | await each_message.delete()
30 |
31 |
32 | bot.run(os.getenv("TOKEN"))
33 |
--------------------------------------------------------------------------------
/app-004_bot-discord/requirements.txt:
--------------------------------------------------------------------------------
1 | aiohttp==3.6.3
2 | async-timeout==3.0.1
3 | attrs==20.3.0
4 | chardet==3.0.4
5 | discord.py==1.5.1
6 | idna==2.10
7 | idna-ssl==1.1.0
8 | multidict==4.7.6
9 | python-dotenv==0.15.0
10 | typing-extensions==3.7.4.3
11 | yarl==1.5.1
12 |
--------------------------------------------------------------------------------
/chp-001_les-bases/afficher-le-type-dune-variable/script.py:
--------------------------------------------------------------------------------
1 | nombre = input("Entrez un nombre: ")
2 | print(type(nombre)) # retourne . La fonction input retourne toujours une chaîne de caractères.
3 |
4 | # Vous pouvez par la suite convertir la variable nombre en nombre entier grâce à la fonction int
5 | nombre = int(nombre)
6 | print(type(nombre)) # retourne . La variable a bien été convertie.
--------------------------------------------------------------------------------
/chp-001_les-bases/la-concatenation/script.py:
--------------------------------------------------------------------------------
1 | a = 5
2 | b = 10
3 | resultat = f"La multiplication de {a} par {b} est égale à {a * b}."
4 | print(resultat)
5 |
--------------------------------------------------------------------------------
/chp-001_les-bases/les-fonctions-de-conversion/script.py:
--------------------------------------------------------------------------------
1 | b = "10"
2 | b = int(b)
--------------------------------------------------------------------------------
/chp-001_les-bases/recuperer-linput-de-lutilisateur/script.py:
--------------------------------------------------------------------------------
1 | nombre = input("Entrez un nombre: ")
2 | print(nombre)
--------------------------------------------------------------------------------
/chp-002_les-structures-conditionnelles/les-blocs-dinstructions/script.py:
--------------------------------------------------------------------------------
1 | age = 20
2 | langage == "Python"
3 |
4 | if age >= 18:
5 | print("Vous êtes majeur !")
6 | if langage == "Python":
7 | print("Vous pouvez rentrer")
8 |
9 | print("Le script est terminé")
--------------------------------------------------------------------------------
/chp-002_les-structures-conditionnelles/structure-conditionnelle-avancee-avec-else/script.py:
--------------------------------------------------------------------------------
1 | utilisateur = "root"
2 | if utilisateur == "admin":
3 | print("Accès autorisé !")
4 | elif utilisateur == "root":
5 | print("Accès autorisé !")
6 | else:
7 | print("Accès refusé...")
--------------------------------------------------------------------------------
/chp-002_les-structures-conditionnelles/tester-plusieurs-conditions/script.py:
--------------------------------------------------------------------------------
1 | age = 15
2 | if age >= 18:
3 | print("Vous êtes majeur")
4 | elif age < 18:
5 | print("Vous êtes mineur")
--------------------------------------------------------------------------------
/chp-002_les-structures-conditionnelles/tester-une-condition-avec-if/script.py:
--------------------------------------------------------------------------------
1 | age = 20
2 | if age >= 18:
3 | print("Vous êtes majeur !")
--------------------------------------------------------------------------------
/chp-003_quelques-modules-et-fonctions/aller-chercher-de-laide-avec-les-fonctions-dir-et-help/script.py:
--------------------------------------------------------------------------------
1 | import random
2 | from pprint import pprint
3 | print(dir(random))
--------------------------------------------------------------------------------
/chp-003_quelques-modules-et-fonctions/le-module-os/script.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | chemin = "/Users/thibh/formation-developpeur-python"
4 | dossier = os.path.join(chemin, "dossier", "test")
5 | if os.path.exists(dossier):
6 | os.removedirs(dossier)
--------------------------------------------------------------------------------
/chp-003_quelques-modules-et-fonctions/le-module-random/script.py:
--------------------------------------------------------------------------------
1 | import random
2 |
3 | r = random.randint(0, 1)
4 | r = random.uniform(0, 1)
5 | r = random.randrange(2)
6 | r = random.randrange(0, 101, 10)
--------------------------------------------------------------------------------
/chp-004_les-listes/ajouter-et-enlever-des-elements-a-une-liste/script.py:
--------------------------------------------------------------------------------
1 | liste = [5]
2 | liste.append(3) # [5, 3]
3 | liste.extend([20, "Python"]) # [5, 3, 20, "Python"]
4 | liste.remove("Python") # [5, 3, 20]
--------------------------------------------------------------------------------
/chp-004_les-listes/dautres-methodes-pour-enlever-des-elements/script.py:
--------------------------------------------------------------------------------
1 | employes = ["Carlos", "Max", "Martine", "Patrick", "Alex"]
2 | element = employes.pop(-1) # retire le dernier élément de la liste (ici, "Alex") et le retourne dans la variable 'element'
3 | print(element) # affiche 'Alex'
4 | employes.clear() # supprime tous les éléments de la liste
--------------------------------------------------------------------------------
/chp-004_les-listes/dautres-methodes-sur-les-listes/script.py:
--------------------------------------------------------------------------------
1 | employes = ["Carlos", "Max", "Martine", "Patrick", "Alex", "Max"]
2 | employes.index("Alex") # 4
3 | employes.count("Max") # 2
4 | employes.sort() # Trie la liste en la modifiant directement : ["Alex", "Carlos", "Martine", "Max", "Max", "Patrick"]
5 | sorted(employes) # Trie la liste mais ne modifie pas la liste d'origine !
6 | liste_trie = sorted(employes) # On retourne la liste triée dans une nouvelle liste.
7 |
8 | nombres = [10, 1, 5, 15]
9 | nombres.reverse() # Inverse l'ordre de la liste : [15, 5, 1, 10]
10 | print(nombres)
--------------------------------------------------------------------------------
/chp-004_les-listes/joindre-les-elements-dune-liste/script.py:
--------------------------------------------------------------------------------
1 | liste = ["Python", "est", "un", "langage", "incroyable"]
2 | " ".join(liste) # 'Python est un langage incroyable'
3 | " - ".join(liste) # Python - est - un - langage - incroyable
4 | "".join(liste) # Pythonestunlangageincroyable
5 |
6 | resultat = "\n".join(liste)
7 | print(resultat)
8 | # Python
9 | # est
10 | # un
11 | # langage
12 | # incroyable
--------------------------------------------------------------------------------
/chp-004_les-listes/les-listes-imbriques/script.py:
--------------------------------------------------------------------------------
1 | liste = ["Python", ["Java", "C++", ["C"]], ["Ruby"]]
2 |
3 | liste[0] # 'Python'
4 | liste[-1][0] # 'Ruby'
5 | liste[0][0:2] # 'Py'
6 | liste[1][1] # 'C++'
7 | liste[1][:2] # ['Java', 'C++']
--------------------------------------------------------------------------------
/chp-004_les-listes/les-listes/script.py:
--------------------------------------------------------------------------------
1 | liste = [250, "Python", True]
--------------------------------------------------------------------------------
/chp-004_les-listes/les-operateurs-dappartenance/script.py:
--------------------------------------------------------------------------------
1 | utilisateurs = ["Paul", "Pierre", "Marie"]
2 | "Paul" in utilisateurs # retourne le booléen True
3 |
4 | if "Paul" in utilisateurs:
5 | print("Bonjour Paul, bon retour parmi nous!")
6 |
7 | if "Paul" in utilisateurs:
8 | utilisateurs.remove("Paul")
9 |
10 | # Fonction aussi avec des chaînes de caractères
11 | "Java" in "Javascript" # retourne le booléen True
--------------------------------------------------------------------------------
/chp-004_les-listes/les-slices/script.py:
--------------------------------------------------------------------------------
1 | liste = ["Utilisateur_01",
2 | "Utilisateur_02",
3 | "Utilisateur_03",
4 | "Utilisateur_04",
5 | "Utilisateur_05",
6 | "Utilisateur_06"]
7 |
8 | liste[:] # ['Utilisateur_01', 'Utilisateur_02', 'Utilisateur_03', 'Utilisateur_04', 'Utilisateur_05', 'Utilisateur_06']
9 | liste[1:] # ['Utilisateur_02', 'Utilisateur_03', 'Utilisateur_04', 'Utilisateur_05', 'Utilisateur_06']
10 | liste[:1] # ['Utilisateur_01']
11 | liste[1:3] # ['Utilisateur_02', 'Utilisateur_03']
12 | liste[1:-1] # ['Utilisateur_02', 'Utilisateur_03', 'Utilisateur_04', 'Utilisateur_05']
--------------------------------------------------------------------------------
/chp-004_les-listes/recuperer-un-element-dans-une-liste/script.py:
--------------------------------------------------------------------------------
1 | liste = ["Python", "C++", "Java"]
2 | liste[0] # "Python"
3 | liste[1] # "C++"
4 | liste[2] # "Java"
5 | liste[-1] # "Java"
6 | liste[-2] # "C++"
7 | liste[-3] # "Python"
8 | liste[-4] # Erreur ! Indice hors des limites de la liste
9 | liste[3] # Erreur ! Indice hors des limites de la liste
--------------------------------------------------------------------------------
/chp-005_les-modules/actualiser-un-module/script.py:
--------------------------------------------------------------------------------
1 | import utils
2 | import importlib
3 | importlib.reload(utils)
4 |
5 | print(utils.a)
--------------------------------------------------------------------------------
/chp-005_les-modules/actualiser-un-module/utils.py:
--------------------------------------------------------------------------------
1 | a = 4
--------------------------------------------------------------------------------
/chp-005_les-modules/creer-notre-propre-module/random.py:
--------------------------------------------------------------------------------
1 | a = 5
--------------------------------------------------------------------------------
/chp-005_les-modules/creer-notre-propre-module/script.py:
--------------------------------------------------------------------------------
1 | import random
2 |
3 | print(random.a)
--------------------------------------------------------------------------------
/chp-005_les-modules/la-variable-name/script.py:
--------------------------------------------------------------------------------
1 | import utils
2 |
3 |
--------------------------------------------------------------------------------
/chp-005_les-modules/la-variable-name/utils.py:
--------------------------------------------------------------------------------
1 | def addition(a, b):
2 | return a + b
3 |
4 | if __name__ == "__main__":
5 | print(addition(4, 5))
--------------------------------------------------------------------------------
/chp-005_les-modules/le-pythonpath/script.py:
--------------------------------------------------------------------------------
1 | import sys
2 | sys.path.append("/Users/thibh/Documents/mes_modules")
3 |
4 | import module_test
--------------------------------------------------------------------------------
/chp-006_le-logging/configurer-le-logger/script.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | logging.basicConfig(level=logging.ERROR,
4 | format='%(asctime)s : %(levelname)s : %(message)s')
5 |
6 | logging.debug("La fonction a bien été exécutée")
7 | logging.info("Message d'information général")
8 | logging.warning("Attention !")
9 | logging.error("Une erreur est arrivée")
10 | logging.critical("Erreur critique")
--------------------------------------------------------------------------------
/chp-006_le-logging/ecrire-dans-un-fichier-de-log/script.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | logging.basicConfig(level=logging.DEBUG,
4 | filename="app.log",
5 | filemode="w",
6 | format='%(asctime)s - %(levelname)s - %(message)s')
7 |
8 | logging.debug("La fonction a bien été exécutée")
9 | logging.info("Message d'information général")
10 | logging.warning("Attention !")
11 | logging.error("Une erreur est arrivée")
12 | logging.critical("Erreur critique")
--------------------------------------------------------------------------------
/chp-006_le-logging/le-module-logging/script.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | logging.debug("La fonction a bien été exécutée")
4 | logging.info("Message d'information général")
5 | logging.warning("Attention !")
6 | logging.error("Une erreur est arrivée")
7 | logging.critical("Erreur critique")
--------------------------------------------------------------------------------
/chp-007_oriente-objet-premiere-partie/attributs-de-classe-et-attributs-dinstance/attributs.py:
--------------------------------------------------------------------------------
1 | class Voiture:
2 | marque = "Lamborghini"
3 |
4 | voiture_01 = Voiture()
5 | voiture_02 = Voiture()
6 |
7 | # print(voiture_01.marque)
8 | # print(voiture_02.marque)
9 |
10 | Voiture.marque = "Porsche"
11 |
12 | # print(voiture_01.marque)
13 | # print(voiture_02.marque)
14 |
15 | voiture_01.marque = "Peugeolt"
16 | voiture_02.marque = "Volkswagen"
17 |
18 | print(Voiture.marque)
19 | print(voiture_01.marque)
20 | print(voiture_02.marque)
--------------------------------------------------------------------------------
/chp-007_oriente-objet-premiere-partie/creer-des-instances/instances.py:
--------------------------------------------------------------------------------
1 | class Voiture:
2 | marque = "Lamborghini"
3 |
4 | voiture_01 = Voiture()
5 | voiture_02 = Voiture()
6 | print(voiture_01.marque)
7 | print(voiture_02.marque)
8 |
--------------------------------------------------------------------------------
/chp-007_oriente-objet-premiere-partie/creer-notre-premiere-classe/classe.py:
--------------------------------------------------------------------------------
1 | class Voiture:
2 | marque = "Lamborghini"
3 | couleur = "rouge"
4 |
5 | print(Voiture.marque)
6 | print(Voiture.couleur)
--------------------------------------------------------------------------------
/chp-007_oriente-objet-premiere-partie/initialiser-une-instance/initialisation.py:
--------------------------------------------------------------------------------
1 | class Voiture:
2 | voitures_crees = 0
3 | def __init__(self, marque):
4 | Voiture.voitures_crees += 1
5 | self.marque = marque
6 |
7 | voiture_01 = Voiture("Lamborghini")
8 | voiture_02 = Voiture("Porsche")
9 | print(Voiture.voitures_crees)
10 |
--------------------------------------------------------------------------------
/chp-007_oriente-objet-premiere-partie/la-signification-de-self/self.py:
--------------------------------------------------------------------------------
1 | class Voiture:
2 | def __init__(self, marque):
3 | self.marque = marque
4 |
5 | def afficher_marque(self):
6 | print(f"La voiture est une {self.marque}")
7 |
8 | voiture_01 = Voiture("Lamborghini")
9 | voiture_01.afficher_marque()
10 | Voiture.afficher_marque(voiture_01)
11 |
--------------------------------------------------------------------------------
/chp-007_oriente-objet-premiere-partie/la-verite-sur-les-fonctions-de-conversion/script.py:
--------------------------------------------------------------------------------
1 | # class str:
2 | # pass
3 |
4 | # a = 5
5 | # a = str(a)
6 | ma_liste = list("python")
7 | print(ma_liste)
8 |
--------------------------------------------------------------------------------
/chp-008_reecriture-la-liste-de-courses-avec-la-poo/afficher-les-elements-dans-la-liste/constants.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | CUR_DIR = os.path.dirname(os.path.abspath(__file__))
4 | DATA_DIR = os.path.join(CUR_DIR, "data")
--------------------------------------------------------------------------------
/chp-008_reecriture-la-liste-de-courses-avec-la-poo/afficher-les-elements-dans-la-liste/lib.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | LOGGER = logging.getLogger()
4 |
5 |
6 | class Liste(list):
7 | def __init__(self, nom):
8 | self.nom = nom
9 |
10 | def ajouter(self, element):
11 | if not isinstance(element, str):
12 | raise ValueError("Vous ne pouvez ajouter que des chaînes de caractères!")
13 |
14 | if element in self:
15 | LOGGER.error(f"{element} est déjà dans la liste.")
16 | return False
17 |
18 | self.append(element)
19 | return True
20 |
21 | def enlever(self, element):
22 | if element in self:
23 | self.remove(element)
24 | return True
25 | return False
26 |
27 | def afficher(self):
28 | print(f"Ma liste de {self.nom} :")
29 | for element in self:
30 | print(f" - {element}")
31 |
32 | if __name__ == "__main__":
33 | liste = Liste("taches")
34 | liste.ajouter("Pommes")
35 | liste.ajouter("Poires")
36 | liste.afficher()
--------------------------------------------------------------------------------
/chp-008_reecriture-la-liste-de-courses-avec-la-poo/creation-de-la-classe-liste/constants.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | CUR_DIR = os.path.dirname(os.path.abspath(__file__))
4 | DATA_DIR = os.path.join(CUR_DIR, "data")
--------------------------------------------------------------------------------
/chp-008_reecriture-la-liste-de-courses-avec-la-poo/creation-de-la-classe-liste/lib.py:
--------------------------------------------------------------------------------
1 | class Liste(list):
2 | def __init__(self, nom):
3 | self.nom = nom
4 |
5 | if __name__ == "__main__":
6 | print("Hello")
--------------------------------------------------------------------------------
/chp-008_reecriture-la-liste-de-courses-avec-la-poo/creation-des-constantes/constants.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | CUR_DIR = os.path.dirname(os.path.abspath(__file__))
4 | DATA_DIR = os.path.join(CUR_DIR, "data")
--------------------------------------------------------------------------------
/chp-008_reecriture-la-liste-de-courses-avec-la-poo/creation-des-methodes-ajouter-et-enlever/constants.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | CUR_DIR = os.path.dirname(os.path.abspath(__file__))
4 | DATA_DIR = os.path.join(CUR_DIR, "data")
--------------------------------------------------------------------------------
/chp-008_reecriture-la-liste-de-courses-avec-la-poo/creation-des-methodes-ajouter-et-enlever/lib.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | LOGGER = logging.getLogger()
4 |
5 |
6 | class Liste(list):
7 | def __init__(self, nom):
8 | self.nom = nom
9 |
10 | def ajouter(self, element):
11 | if not isinstance(element, str):
12 | raise ValueError("Vous ne pouvez ajouter que des chaînes de caractères!")
13 |
14 | if element in self:
15 | LOGGER.error(f"{element} est déjà dans la liste.")
16 | return False
17 |
18 | self.append(element)
19 | return True
20 |
21 | def enlever(self, element):
22 | if element in self:
23 | self.remove(element)
24 | return True
25 | return False
26 |
27 | if __name__ == "__main__":
28 | liste = Liste("courses")
29 | liste.ajouter("Pommes")
30 | liste.ajouter("Poires")
31 | print(liste)
32 |
--------------------------------------------------------------------------------
/chp-008_reecriture-la-liste-de-courses-avec-la-poo/sauvegarder-la-liste/constants.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | CUR_DIR = os.path.dirname(os.path.abspath(__file__))
4 | DATA_DIR = os.path.join(CUR_DIR, "data")
--------------------------------------------------------------------------------
/chp-008_reecriture-la-liste-de-courses-avec-la-poo/sauvegarder-la-liste/data/courses.json:
--------------------------------------------------------------------------------
1 | [
2 | "Pommes",
3 | "Poires"
4 | ]
--------------------------------------------------------------------------------
/chp-008_reecriture-la-liste-de-courses-avec-la-poo/sauvegarder-la-liste/lib.py:
--------------------------------------------------------------------------------
1 | import json
2 | import logging
3 | import os
4 |
5 | from constants import DATA_DIR
6 |
7 | LOGGER = logging.getLogger()
8 |
9 |
10 | class Liste(list):
11 | def __init__(self, nom):
12 | self.nom = nom
13 |
14 | def ajouter(self, element):
15 | if not isinstance(element, str):
16 | raise ValueError("Vous ne pouvez ajouter que des chaînes de caractères!")
17 |
18 | if element in self:
19 | LOGGER.error(f"{element} est déjà dans la liste.")
20 | return False
21 |
22 | self.append(element)
23 | return True
24 |
25 | def afficher(self):
26 | print(f"Ma liste de {self.nom} :")
27 | for element in self:
28 | print(f" - {element}")
29 |
30 | def enlever(self, element):
31 | if element in self:
32 | self.remove(element)
33 | return True
34 | return False
35 |
36 | def sauvegarder(self):
37 | chemin = os.path.join(DATA_DIR, f"{self.nom}.json")
38 | if not os.path.exists(DATA_DIR):
39 | os.makedirs(DATA_DIR)
40 |
41 | with open(chemin, "w") as f:
42 | json.dump(self, f, indent=4)
43 |
44 | return True
45 |
46 | if __name__ == "__main__":
47 | liste = Liste("courses")
48 | liste.ajouter("Pommes")
49 | liste.ajouter("Poires")
50 | liste.sauvegarder()
51 |
--------------------------------------------------------------------------------
/chp-009_oriente-objet-deuxieme-partie/la-fonction-super/super.py:
--------------------------------------------------------------------------------
1 | projets = ["pr_GameOfThrones", "HarryPotter", "pr_Avengers"]
2 | class Utilisateur:
3 | def __init__(self, nom, prenom):
4 | self.nom = nom
5 | self.prenom = prenom
6 |
7 | def __str__(self):
8 | return f"Utilisateur {self.nom} {self.prenom}"
9 |
10 | def afficher_projets(self):
11 | for projet in projets:
12 | print(projet)
13 |
14 | class Junior(Utilisateur):
15 | def __init__(self, nom, prenom):
16 | super().__init__(nom, prenom)
17 |
18 | paul = Junior("Paul", "Durand")
19 | paul.afficher_projets()
20 |
21 |
--------------------------------------------------------------------------------
/chp-009_oriente-objet-deuxieme-partie/la-methode-str/method_magic.py:
--------------------------------------------------------------------------------
1 | class Voiture:
2 | def __init__(self, marque, vitesse):
3 | self.marque = marque
4 | self.vitesse = vitesse
5 |
6 | def __str__(self):
7 | return f"Voiture de marque {self.marque} avec vitesse maximale de {self.vitesse}."
8 |
9 | porsche = Voiture("Porsche", 200)
10 | affichage = str(porsche)
11 | print(affichage)
--------------------------------------------------------------------------------
/chp-009_oriente-objet-deuxieme-partie/la-surcharge/surcharge.py:
--------------------------------------------------------------------------------
1 | projets = ["pr_GameOfThrones", "HarryPotter", "pr_Avengers"]
2 | class Utilisateur:
3 | def __init__(self, nom, prenom):
4 | self.nom = nom
5 | self.prenom = prenom
6 |
7 | def __str__(self):
8 | return f"Utilisateur {self.nom} {self.prenom}"
9 |
10 | def afficher_projets(self):
11 | for projet in projets:
12 | print(projet)
13 |
14 | class Junior(Utilisateur):
15 | def __init__(self, nom, prenom):
16 | super().__init__(nom, prenom)
17 |
18 | def afficher_projets(self):
19 | for projet in projets:
20 | if not projet.startswith("pr_"):
21 | print(projet)
22 |
23 | paul = Junior("Paul", "Durand")
24 | paul.afficher_projets()
25 |
26 |
--------------------------------------------------------------------------------
/chp-009_oriente-objet-deuxieme-partie/le-polymorphisme/polymorphisme.py:
--------------------------------------------------------------------------------
1 | class Vehicule:
2 | def avance(self):
3 | print("Le véhicule démarre")
4 |
5 | class Voiture(Vehicule):
6 | def avance(self):
7 | super().avance()
8 | print("La voiture roule")
9 |
10 | class Avion(Vehicule):
11 | def avance(self):
12 | super().avance()
13 | print("L'avion vol")
14 |
15 | v = Voiture()
16 | a = Avion()
17 | v.avance()
18 | a.avance()
19 |
--------------------------------------------------------------------------------
/chp-009_oriente-objet-deuxieme-partie/les-methodes-de-classe/class_method.py:
--------------------------------------------------------------------------------
1 | class Voiture:
2 | def __init__(self, marque, vitesse, prix):
3 | self.marque = marque
4 | self.vitesse = vitesse
5 | self.prix = prix
6 |
7 | @classmethod
8 | def lamborghini(cls):
9 | return cls(marque="Lamborghini", vitesse=250, prix=200000)
10 |
11 | @classmethod
12 | def porsche(cls):
13 | return cls(marque="Porsche", vitesse=200, prix=180000)
14 |
15 | lambo = Voiture.lamborghini()
16 | porsche = Voiture.porsche()
17 |
--------------------------------------------------------------------------------
/chp-009_oriente-objet-deuxieme-partie/les-methodes-statiques/static_method.py:
--------------------------------------------------------------------------------
1 | class Voiture:
2 | voiture_crees = 0
3 | def __init__(self, marque, vitesse, prix):
4 | Voiture.voiture_crees += 1
5 | self.marque = marque
6 | self.vitesse = vitesse
7 | self.prix = prix
8 |
9 | @classmethod
10 | def lamborghini(cls):
11 | return cls(marque="Lamborghini", vitesse=250, prix=200000)
12 |
13 | @classmethod
14 | def porsche(cls):
15 | return cls(marque="Porsche", vitesse=200, prix=180000)
16 |
17 | @staticmethod
18 | def afficher_nombre_voitures():
19 | print(f"Vous avez {Voiture.voiture_crees} voitures dans votre garage.")
20 |
21 | lambo = Voiture.lamborghini()
22 | porsche = Voiture.porsche()
23 | Voiture.afficher_nombre_voitures()
--------------------------------------------------------------------------------
/chp-009_oriente-objet-deuxieme-partie/lheritage/heritage.py:
--------------------------------------------------------------------------------
1 | projets = ["pr_GameOfThrones", "HarryPotter", "pr_Avengers"]
2 |
3 | class Utilisateur:
4 | def __init__(self, nom, prenom):
5 | self.nom = nom
6 | self.prenom = prenom
7 |
8 | def __str__(self):
9 | return f"Utilisateur {self.nom} {self.prenom}"
10 |
11 | def afficher_projets(self):
12 | for projet in projets:
13 | print(projet)
14 |
15 | class Junior(Utilisateur):
16 | def __init__(self, nom, prenom):
17 | Utilisateur.__init__(self, nom, prenom)
18 |
19 | paul = Junior("Paul", "Durand")
20 | paul.afficher_projets()
21 |
22 |
--------------------------------------------------------------------------------
/chp-010_bases-de-donnees/ajouter-des-donnees/app.py:
--------------------------------------------------------------------------------
1 | import sqlite3
2 |
3 | conn = sqlite3.connect("database.db")
4 | c = conn.cursor()
5 | c.execute("""
6 | CREATE TABLE IF NOT EXISTS employees
7 | (
8 | prenom text,
9 | nom text
10 | )
11 | """)
12 |
13 | d = {"prenom": "Paul", "nom": "Dupond"}
14 | c.execute("INSERT INTO employees VALUES (:prenom, :nom)", d)
15 |
16 | conn.commit()
17 | conn.close()
--------------------------------------------------------------------------------
/chp-010_bases-de-donnees/ajouter-des-donnees/database.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-010_bases-de-donnees/ajouter-des-donnees/database.db
--------------------------------------------------------------------------------
/chp-010_bases-de-donnees/creer-un-tableau/app.py:
--------------------------------------------------------------------------------
1 | import sqlite3
2 |
3 | conn = sqlite3.connect("database.db")
4 | c = conn.cursor()
5 |
6 | c.execute("""
7 | CREATE TABLE IF NOT EXISTS employees(
8 | prenom text,
9 | nom text
10 | )
11 | """)
12 | conn.commit()
13 | conn.close()
--------------------------------------------------------------------------------
/chp-010_bases-de-donnees/creer-un-tableau/database.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-010_bases-de-donnees/creer-un-tableau/database.db
--------------------------------------------------------------------------------
/chp-010_bases-de-donnees/introduction-a-sqlite/app.py:
--------------------------------------------------------------------------------
1 | import sqlite3
2 |
3 | conn = sqlite3.connect("database.db")
4 | conn.close()
--------------------------------------------------------------------------------
/chp-010_bases-de-donnees/introduction-a-sqlite/database.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-010_bases-de-donnees/introduction-a-sqlite/database.db
--------------------------------------------------------------------------------
/chp-010_bases-de-donnees/mettre-a-jour-des-donnees/app.py:
--------------------------------------------------------------------------------
1 | import sqlite3
2 |
3 | conn = sqlite3.connect("database.db")
4 | c = conn.cursor()
5 | c.execute("""
6 | CREATE TABLE IF NOT EXISTS employees
7 | (
8 | prenom text,
9 | nom text,
10 | salaire int
11 | )
12 | """)
13 |
14 | d = {"salaire": 20000, "prenom": "Patrick", "nom": "Dupont"}
15 |
16 | c.execute("""UPDATE employees SET salaire=:salaire
17 | WHERE prenom=:prenom AND nom=:nom""", d)
18 |
19 | conn.commit()
20 | conn.close()
--------------------------------------------------------------------------------
/chp-010_bases-de-donnees/mettre-a-jour-des-donnees/database.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-010_bases-de-donnees/mettre-a-jour-des-donnees/database.db
--------------------------------------------------------------------------------
/chp-010_bases-de-donnees/recuperer-des-donnees/app.py:
--------------------------------------------------------------------------------
1 | import sqlite3
2 |
3 | conn = sqlite3.connect("database.db")
4 | c = conn.cursor()
5 | c.execute("""
6 | CREATE TABLE IF NOT EXISTS employees
7 | (
8 | prenom text,
9 | nom text
10 | )
11 | """)
12 |
13 |
14 | c.execute("SELECT * FROM employees WHERE")
15 | donnees = c.fetchall()
16 | print(donnees)
17 | premier = c.fetchone()
18 | print(premier)
19 |
20 |
21 | conn.commit()
22 | conn.close()
--------------------------------------------------------------------------------
/chp-010_bases-de-donnees/recuperer-des-donnees/database.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-010_bases-de-donnees/recuperer-des-donnees/database.db
--------------------------------------------------------------------------------
/chp-010_bases-de-donnees/stocker-des-donnees-dans-un-fichier-json/app.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | fichier = "settings.json"
4 |
5 | with open(fichier, "r") as f:
6 | settings = json.load(f)
7 |
8 | settings["fontSize"] = 15
9 |
10 | with open(fichier, "w") as f:
11 | json.dump(settings, f, indent=4)
12 |
--------------------------------------------------------------------------------
/chp-010_bases-de-donnees/stocker-des-donnees-dans-un-fichier-json/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "fontSize": 15
3 | }
--------------------------------------------------------------------------------
/chp-010_bases-de-donnees/supprimer-des-donnees/app.py:
--------------------------------------------------------------------------------
1 | import sqlite3
2 |
3 | conn = sqlite3.connect("database.db")
4 | c = conn.cursor()
5 | c.execute("""
6 | CREATE TABLE IF NOT EXISTS employees
7 | (
8 | prenom text,
9 | nom text
10 | )
11 | """)
12 |
13 | c.execute("DELETE FROM employees")
14 |
15 | conn.commit()
16 | conn.close()
--------------------------------------------------------------------------------
/chp-010_bases-de-donnees/supprimer-des-donnees/database.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-010_bases-de-donnees/supprimer-des-donnees/database.db
--------------------------------------------------------------------------------
/chp-011_bases-de-donnees-tinydb/data.json:
--------------------------------------------------------------------------------
1 | {
2 | "_default": {},
3 | "Users": {
4 | "1": {
5 | "name": "Patrick",
6 | "salary": 25000
7 | },
8 | "2": {
9 | "name": "Paul",
10 | "salary": 35000
11 | },
12 | "3": {
13 | "name": "Julie",
14 | "salary": 45000
15 | }
16 | },
17 | "Roles": {
18 | "1": {
19 | "name": "Pythonista"
20 | },
21 | "2": {
22 | "name": "Javaista"
23 | },
24 | "3": {
25 | "name": "JavaScripta"
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/chp-011_bases-de-donnees-tinydb/main.py:
--------------------------------------------------------------------------------
1 | from tinydb import TinyDB, Query, where
2 |
3 | db = TinyDB('data.json', indent=4)
4 |
5 |
6 | users = db.table("Users")
7 | roles = db.table("Roles")
8 |
9 | users.insert({"name": "Patrick", "salary": 25000})
10 | users.insert({"name": "Paul", "salary": 35000})
11 | users.insert({"name": "Julie", "salary": 45000})
12 |
13 | roles.insert_multiple([
14 | {"name": "Pythonista"},
15 | {"name": "Javaista"},
16 | {"name": "JavaScripta"},
17 | ])
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/_generate.py:
--------------------------------------------------------------------------------
1 | from faker import Faker
2 | from pathlib import Path
3 |
4 | BASE_DIR = Path(__file__).resolve().parent
5 | fake = Faker()
6 |
7 | for _ in range(100):
8 | Path(BASE_DIR / fake.file_name()).touch()
9 |
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/actually.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/actually.js
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/already.avi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/already.avi
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/although.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/although.mov
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/available.flac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/available.flac
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/beautiful.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/beautiful.css
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/bed.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/bed.jpg
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/behavior.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/behavior.css
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/big.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/big.css
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/catch.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/catch.pdf
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/center.tiff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/center.tiff
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/chair.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/chair.mov
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/claim.ods:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/claim.ods
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/claim.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/claim.png
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/contain.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/contain.pptx
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/defense.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/defense.pptx
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/describe.flac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/describe.flac
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/development.webm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/development.webm
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/each.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/each.mp3
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/enough.flac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/enough.flac
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/environment.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/environment.pdf
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/everyone.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/everyone.pdf
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/evidence.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/evidence.js
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/far.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/far.mp3
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/force.avi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/force.avi
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/friend.tiff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/friend.tiff
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/general.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/general.bmp
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/great.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/great.mp3
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/group.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/group.pptx
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/industry.ods:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/industry.ods
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/information.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/information.xlsx
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/inside.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/inside.jpeg
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/inside.webm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/inside.webm
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/interest.flac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/interest.flac
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/job.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/job.css
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/learn.webm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/learn.webm
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/leave.avi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/leave.avi
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/line.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/line.jpeg
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/live.flac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/live.flac
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/marriage.webm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/marriage.webm
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/material.webm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/material.webm
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/movement.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/movement.bmp
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/movie.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/movie.mp3
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/opportunity.key:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/opportunity.key
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/page.avi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/page.avi
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/physical.ods:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/physical.ods
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/point.webm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/point.webm
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/position.doc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/position.doc
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/pressure.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/pressure.bmp
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/pressure.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/pressure.mp3
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/produce.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/produce.css
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/production.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/production.pptx
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/program.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/program.mp3
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/pull.avi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/pull.avi
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/quality.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/quality.css
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/recent.ppt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/recent.ppt
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/resource.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/resource.mov
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/rock.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/rock.js
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/scene.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/scene.xlsx
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/senior.avi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/senior.avi
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/share.numbers:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/share.numbers
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/simply.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/simply.html
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/site.odp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/site.odp
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/somebody.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/somebody.html
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/station.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/station.png
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/step.webm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/step.webm
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/still.webm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/still.webm
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/student.avi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/student.avi
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/team.flac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/team.flac
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/than.webm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/than.webm
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/trouble.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/trouble.css
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/voice.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/voice.jpg
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/while.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/while.mp3
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/wish.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/wish.bmp
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/work.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/work.pdf
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/worker.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/worker.docx
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/yard.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/yard.html
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/yeah.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/yeah.mp3
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/data/your.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/chp-012_applications-command-line-typer/data/your.pptx
--------------------------------------------------------------------------------
/chp-012_applications-command-line-typer/main.py:
--------------------------------------------------------------------------------
1 | import typer
2 | from typing import Optional
3 | from pathlib import Path
4 |
5 | app = typer.Typer()
6 |
7 |
8 | @app.command('run')
9 | def main(extension: str,
10 | directory: Optional[str] = typer.Argument(None, help="Dossier dans lequel chercher."),
11 | delete: bool = typer.Option(False, help="Supprime les fichiers trouvés.")):
12 | """
13 | Affiche les fichiers trouvés avec l'extension donnée.
14 | """
15 |
16 | if directory:
17 | directory = Path(directory)
18 | else:
19 | directory = Path.cwd()
20 |
21 | if not directory.exists():
22 | typer.secho(f"Le dossier '{directory}' n'existe pas.", fg=typer.colors.RED)
23 | raise typer.Exit()
24 |
25 | files = directory.rglob(f"*.{extension}")
26 | if delete:
27 | typer.confirm("Voulez-vous vraiment supprimer tous les fichiers trouvés ?", abort=True)
28 | for file in files:
29 | file.unlink()
30 | typer.secho(f"Suppression du fichier {file}.", fg=typer.colors.RED)
31 | else:
32 | typer.secho(f"Fichier trouvés l'extension {extension} :", bg=typer.colors.BLUE, fg=typer.colors.BRIGHT_WHITE)
33 | for file in files:
34 | typer.echo(file)
35 |
36 |
37 | @app.command()
38 | def search(extension: str):
39 | """Chercher les fichiers avec l'extension donnée."""
40 | main(extension=extension, directory=None, delete=False)
41 |
42 |
43 | @app.command()
44 | def delete(extension: str):
45 | """Supprimer les fichiers avec l'extension donnée."""
46 | main(extension=extension, directory=None, delete=True)
47 |
48 | if __name__ == "__main__":
49 | app()
--------------------------------------------------------------------------------
/chp-013_les-tests-unitaires/assets/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: Helvetica, Arial, sans-serif;
3 | font-size: 12px;
4 | /* do not increase min-width as some may use split screens */
5 | min-width: 800px;
6 | color: #999;
7 | }
8 |
9 | h1 {
10 | font-size: 24px;
11 | color: black;
12 | }
13 |
14 | h2 {
15 | font-size: 16px;
16 | color: black;
17 | }
18 |
19 | p {
20 | color: black;
21 | }
22 |
23 | a {
24 | color: #999;
25 | }
26 |
27 | table {
28 | border-collapse: collapse;
29 | }
30 |
31 | /******************************
32 | * SUMMARY INFORMATION
33 | ******************************/
34 | #environment td {
35 | padding: 5px;
36 | border: 1px solid #E6E6E6;
37 | }
38 | #environment tr:nth-child(odd) {
39 | background-color: #f6f6f6;
40 | }
41 |
42 | /******************************
43 | * TEST RESULT COLORS
44 | ******************************/
45 | span.passed,
46 | .passed .col-result {
47 | color: green;
48 | }
49 |
50 | span.skipped,
51 | span.xfailed,
52 | span.rerun,
53 | .skipped .col-result,
54 | .xfailed .col-result,
55 | .rerun .col-result {
56 | color: orange;
57 | }
58 |
59 | span.error,
60 | span.failed,
61 | span.xpassed,
62 | .error .col-result,
63 | .failed .col-result,
64 | .xpassed .col-result {
65 | color: red;
66 | }
67 |
68 | /******************************
69 | * RESULTS TABLE
70 | *
71 | * 1. Table Layout
72 | * 2. Extra
73 | * 3. Sorting items
74 | *
75 | ******************************/
76 | /*------------------
77 | * 1. Table Layout
78 | *------------------*/
79 | #results-table {
80 | border: 1px solid #e6e6e6;
81 | color: #999;
82 | font-size: 12px;
83 | width: 100%;
84 | }
85 | #results-table th,
86 | #results-table td {
87 | padding: 5px;
88 | border: 1px solid #E6E6E6;
89 | text-align: left;
90 | }
91 | #results-table th {
92 | font-weight: bold;
93 | }
94 |
95 | /*------------------
96 | * 2. Extra
97 | *------------------*/
98 | .log {
99 | background-color: #e6e6e6;
100 | border: 1px solid #e6e6e6;
101 | color: black;
102 | display: block;
103 | font-family: "Courier New", Courier, monospace;
104 | height: 230px;
105 | overflow-y: scroll;
106 | padding: 5px;
107 | white-space: pre-wrap;
108 | }
109 | .log:only-child {
110 | height: inherit;
111 | }
112 |
113 | div.image {
114 | border: 1px solid #e6e6e6;
115 | float: right;
116 | height: 240px;
117 | margin-left: 5px;
118 | overflow: hidden;
119 | width: 320px;
120 | }
121 | div.image img {
122 | width: 320px;
123 | }
124 |
125 | div.video {
126 | border: 1px solid #e6e6e6;
127 | float: right;
128 | height: 240px;
129 | margin-left: 5px;
130 | overflow: hidden;
131 | width: 320px;
132 | }
133 | div.video video {
134 | overflow: hidden;
135 | width: 320px;
136 | height: 240px;
137 | }
138 |
139 | .collapsed {
140 | display: none;
141 | }
142 |
143 | .expander::after {
144 | content: " (show details)";
145 | color: #BBB;
146 | font-style: italic;
147 | cursor: pointer;
148 | }
149 |
150 | .collapser::after {
151 | content: " (hide details)";
152 | color: #BBB;
153 | font-style: italic;
154 | cursor: pointer;
155 | }
156 |
157 | /*------------------
158 | * 3. Sorting items
159 | *------------------*/
160 | .sortable {
161 | cursor: pointer;
162 | }
163 |
164 | .sort-icon {
165 | font-size: 0px;
166 | float: left;
167 | margin-right: 5px;
168 | margin-top: 5px;
169 | /*triangle*/
170 | width: 0;
171 | height: 0;
172 | border-left: 8px solid transparent;
173 | border-right: 8px solid transparent;
174 | }
175 | .inactive .sort-icon {
176 | /*finish triangle*/
177 | border-top: 8px solid #E6E6E6;
178 | }
179 | .asc.active .sort-icon {
180 | /*finish triangle*/
181 | border-bottom: 8px solid #999;
182 | }
183 | .desc.active .sort-icon {
184 | /*finish triangle*/
185 | border-top: 8px solid #999;
186 | }
187 |
--------------------------------------------------------------------------------
/chp-013_les-tests-unitaires/bank.py:
--------------------------------------------------------------------------------
1 | from random import choice
2 | import string
3 |
4 |
5 | class Account:
6 | def __init__(self, initial_balance=0):
7 | self.identifier = self._create_identifier()
8 | self.balance = initial_balance
9 |
10 | def deposit(self, amount):
11 | self.balance += amount
12 |
13 | def withdraw(self, amount):
14 | if self.balance - amount < 0:
15 | raise ValueError(f"Not enough money in account {self.identifier}")
16 | self.balance -= amount
17 |
18 | @staticmethod
19 | def _create_identifier():
20 | letters_and_digits = string.ascii_letters + string.digits
21 | return "".join([choice(letters_and_digits) for _ in range(25)])
22 |
--------------------------------------------------------------------------------
/chp-013_les-tests-unitaires/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Test Report
6 |
7 |
8 |
245 | index.html
246 | Report generated on 21-Feb-2021 at 12:26:28 by pytest-html v3.1.1
247 | Environment
248 |
249 |
250 | Packages |
251 | {"pluggy": "0.13.1", "py": "1.10.0", "pytest": "6.2.2"} |
252 |
253 | Platform |
254 | macOS-10.16-x86_64-i386-64bit |
255 |
256 | Plugins |
257 | {"html": "3.1.1", "metadata": "1.11.0"} |
258 |
259 | Python |
260 | 3.9.1 |
261 | Summary
262 | 4 tests ran in 0.04 seconds.
263 | (Un)check the boxes to filter the results.
3 passed, 0 skipped, 1 failed, 0 errors, 0 expected failures, 0 unexpected passes
264 | Results
265 |
266 |
267 |
268 | Result |
269 | Test |
270 | Duration |
271 | Links |
272 |
273 | No results found. Try to check the filters |
274 |
275 |
276 | Failed |
277 | test.py::test_add_with_two_booleans |
278 | 0.00 |
279 | |
280 |
281 |
283 |
284 |
285 | Passed |
286 | test.py::test_add_with_two_numbers |
287 | 0.00 |
288 | |
289 |
290 |
292 |
293 |
294 | Passed |
295 | test.py::test_add_with_two_letters |
296 | 0.00 |
297 | |
298 |
299 |
301 |
302 |
303 | Passed |
304 | test.py::test_add_with_two_none |
305 | 0.00 |
306 | |
307 |
308 |
--------------------------------------------------------------------------------
/chp-013_les-tests-unitaires/main.py:
--------------------------------------------------------------------------------
1 | def add(a, b):
2 | return a + b
3 |
--------------------------------------------------------------------------------
/chp-013_les-tests-unitaires/test_bank.py:
--------------------------------------------------------------------------------
1 | from bank import Account
2 | import pytest
3 |
4 |
5 | @pytest.fixture
6 | def account():
7 | return Account(initial_balance=1000)
8 |
9 |
10 | def test_deposit(account):
11 | account.deposit(amount=1000)
12 | assert account.balance == 2000
13 |
14 |
15 | def test_withdraw(account):
16 | account.withdraw(amount=500)
17 | assert account.balance == 500
18 |
19 |
20 | def test_withdraw_not_enough_money():
21 | account = Account(initial_balance=200)
22 | with pytest.raises(ValueError):
23 | account.withdraw(amount=500)
24 |
25 |
26 | def test__create_identifier_length_of_identifier(account):
27 | assert len(account.identifier) == 25
28 |
29 |
30 | def test__create_identifier_is_alnum(account):
31 | assert account.identifier.isalnum() is True
32 |
--------------------------------------------------------------------------------
/chp-013_les-tests-unitaires/test_main.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | from main import add
4 |
5 |
6 | def test_add_with_two_numbers():
7 | assert add(5, 10) == 15
8 |
9 |
10 | def test_add_with_two_letters():
11 | assert add("a", "b") == "ab"
12 |
13 |
14 | def test_add_with_two_booleans():
15 | assert add(True, False) == 0
16 | assert add(True, True) == 2
17 | assert add(False, False) == 0
18 |
19 |
20 | def test_add_with_two_none():
21 | with pytest.raises(TypeError):
22 | add(None, None)
23 |
--------------------------------------------------------------------------------
/chp-014_bases-de-la-data-science/01_lecture_fichier.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "ceffd540-5795-4d5b-a289-745e3c1588cf",
6 | "metadata": {
7 | "tags": []
8 | },
9 | "source": [
10 | "# Lecture d'un fichier CSV"
11 | ]
12 | },
13 | {
14 | "cell_type": "markdown",
15 | "id": "7583c91e-b842-47d7-812b-69a1257739df",
16 | "metadata": {},
17 | "source": [
18 | "On importe la bibliothèque pandas"
19 | ]
20 | },
21 | {
22 | "cell_type": "code",
23 | "execution_count": 3,
24 | "id": "ecbe9ce9-dc8f-497c-ab2d-9f17b57df92a",
25 | "metadata": {},
26 | "outputs": [],
27 | "source": [
28 | "import pandas as pd"
29 | ]
30 | },
31 | {
32 | "cell_type": "markdown",
33 | "id": "9682d9c6-890f-4b9d-a66c-5799477de60b",
34 | "metadata": {},
35 | "source": [
36 | "Pour lire un fichier, on utilise les fonctions `read_`, comme `read_csv`, `read_excel` ou encore `read_json`. \n",
37 | "Vous trouverez la liste de toutes les foncions `read` dans la documentation : https://pandas.pydata.org/pandas-docs/stable/user_guide/io.html"
38 | ]
39 | },
40 | {
41 | "cell_type": "code",
42 | "execution_count": 9,
43 | "id": "d3d4b11f-5d0c-4a7a-9103-869a3d80b242",
44 | "metadata": {},
45 | "outputs": [
46 | {
47 | "name": "stdout",
48 | "output_type": "stream",
49 | "text": [
50 | " id date first_name last_name email \\\n",
51 | "0 1 03/28/2021 Marylin Alders malders0@shop-pro.jp \n",
52 | "1 2 03/19/2021 Hinda Harridge hharridge1@gnu.org \n",
53 | "2 3 03/17/2021 Erl Kilminster ekilminster2@etsy.com \n",
54 | "3 4 03/19/2021 Grata Brantl gbrantl3@umn.edu \n",
55 | "4 5 03/24/2021 Kanya Beasant kbeasant4@jigsy.com \n",
56 | ".. ... ... ... ... ... \n",
57 | "995 996 03/24/2021 Duff Errigo derrigorn@elpais.com \n",
58 | "996 997 03/17/2021 Ame Rastall arastallro@toplist.cz \n",
59 | "997 998 03/13/2021 Betty Stickels bstickelsrp@cloudflare.com \n",
60 | "998 999 03/17/2021 Paquito Tesoe ptesoerq@rakuten.co.jp \n",
61 | "999 1000 03/23/2021 Rochelle Pringuer rpringuerrr@house.gov \n",
62 | "\n",
63 | " gender ip_address country price_paid tax \n",
64 | "0 Male 160.119.8.119 Canada $5.36 NaN \n",
65 | "1 Female 210.51.172.132 Canada $8.32 NaN \n",
66 | "2 Male 213.8.101.145 United States $3.73 20.0 \n",
67 | "3 Female 5.140.237.101 United States $3.70 20.0 \n",
68 | "4 Male 106.252.162.233 Morocco $9.24 20.0 \n",
69 | ".. ... ... ... ... ... \n",
70 | "995 Female 193.84.247.144 France $3.63 NaN \n",
71 | "996 Female 188.219.12.109 NaN $4.59 20.0 \n",
72 | "997 Male 199.80.60.87 United States $7.54 20.0 \n",
73 | "998 Male 0.183.63.11 United States $5.81 NaN \n",
74 | "999 NaN 170.193.249.83 Canada $8.01 20.0 \n",
75 | "\n",
76 | "[1000 rows x 10 columns]\n"
77 | ]
78 | }
79 | ],
80 | "source": [
81 | "df = pd.read_csv(\"data.csv\")\n",
82 | "print(df)"
83 | ]
84 | },
85 | {
86 | "cell_type": "code",
87 | "execution_count": null,
88 | "id": "ac346a8e-777c-4b92-9a14-0ab424dcff51",
89 | "metadata": {},
90 | "outputs": [],
91 | "source": []
92 | }
93 | ],
94 | "metadata": {
95 | "kernelspec": {
96 | "display_name": "Python 3",
97 | "language": "python",
98 | "name": "python3"
99 | },
100 | "language_info": {
101 | "codemirror_mode": {
102 | "name": "ipython",
103 | "version": 3
104 | },
105 | "file_extension": ".py",
106 | "mimetype": "text/x-python",
107 | "name": "python",
108 | "nbconvert_exporter": "python",
109 | "pygments_lexer": "ipython3",
110 | "version": "3.9.1"
111 | }
112 | },
113 | "nbformat": 4,
114 | "nbformat_minor": 5
115 | }
116 |
--------------------------------------------------------------------------------
/chp-014_bases-de-la-data-science/analyse_netflix.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 4,
6 | "id": "d6ddf6e1-e4cb-4c14-80e4-4274bacc12fe",
7 | "metadata": {},
8 | "outputs": [],
9 | "source": [
10 | "import pandas as pd\n",
11 | "df = pd.read_csv(\"netflix_titles.csv\")"
12 | ]
13 | },
14 | {
15 | "cell_type": "markdown",
16 | "id": "99e85fd6-8e9f-4188-8391-17f2380f29bd",
17 | "metadata": {},
18 | "source": [
19 | "# Durée moyenne des films"
20 | ]
21 | },
22 | {
23 | "cell_type": "code",
24 | "execution_count": 3,
25 | "id": "3eaeb66c-4176-4393-930d-f544cdb771ad",
26 | "metadata": {},
27 | "outputs": [
28 | {
29 | "data": {
30 | "text/plain": [
31 | "99.30797842663195"
32 | ]
33 | },
34 | "execution_count": 3,
35 | "metadata": {},
36 | "output_type": "execute_result"
37 | }
38 | ],
39 | "source": [
40 | "df_duration = df[df[\"duration\"].str.contains(\"min\")][\"duration\"]\n",
41 | "df_duration.str.replace(\"min\", \"\").map(int).mean()"
42 | ]
43 | },
44 | {
45 | "cell_type": "markdown",
46 | "id": "edc55a7d-18d8-4bd5-b8ea-27437c8d78bf",
47 | "metadata": {},
48 | "source": [
49 | "# Récupérer pays plus importants"
50 | ]
51 | },
52 | {
53 | "cell_type": "code",
54 | "execution_count": 5,
55 | "id": "244de501-547b-402b-a29c-03d7b2d65525",
56 | "metadata": {},
57 | "outputs": [
58 | {
59 | "data": {
60 | "text/plain": [
61 | "{'United States': 2555, 'India': 923, 'United Kingdom': 397}"
62 | ]
63 | },
64 | "execution_count": 5,
65 | "metadata": {},
66 | "output_type": "execute_result"
67 | }
68 | ],
69 | "source": [
70 | "df[\"country\"].value_counts()[:3].to_dict()"
71 | ]
72 | },
73 | {
74 | "cell_type": "markdown",
75 | "id": "44b924a9-6d67-4b06-ae39-d6567702c500",
76 | "metadata": {},
77 | "source": [
78 | "# Nombre de films par année"
79 | ]
80 | },
81 | {
82 | "cell_type": "code",
83 | "execution_count": 11,
84 | "id": "3f755853-b8bb-4cbf-88f4-3837cdb759c4",
85 | "metadata": {},
86 | "outputs": [
87 | {
88 | "data": {
89 | "text/plain": [
90 | "2021 31\n",
91 | "2020 868\n",
92 | "2019 996\n",
93 | "2018 1121\n",
94 | "2017 1012\n",
95 | "2016 882\n",
96 | "2015 541\n",
97 | "2014 334\n",
98 | "2013 267\n",
99 | "2012 219\n",
100 | "Name: release_year, dtype: int64"
101 | ]
102 | },
103 | "execution_count": 11,
104 | "metadata": {},
105 | "output_type": "execute_result"
106 | }
107 | ],
108 | "source": [
109 | "df[\"release_year\"].value_counts().sort_index(ascending=False)[:10]"
110 | ]
111 | },
112 | {
113 | "cell_type": "markdown",
114 | "id": "3040ed4d-b0ac-4768-bb06-3d5f2edc7fde",
115 | "metadata": {},
116 | "source": [
117 | "# Récupérer la liste des réalisateurs"
118 | ]
119 | },
120 | {
121 | "cell_type": "code",
122 | "execution_count": 8,
123 | "id": "712028c7-2d2f-4f88-b6fd-4e359d8c9eb6",
124 | "metadata": {},
125 | "outputs": [
126 | {
127 | "data": {
128 | "text/plain": [
129 | "['Jorge Michel Grau',\n",
130 | " 'Gilbert Chan',\n",
131 | " 'Shane Acker',\n",
132 | " 'Robert Luketic',\n",
133 | " 'Serdar Akar',\n",
134 | " 'Yasir Al Yasiri',\n",
135 | " 'Kevin Reynolds',\n",
136 | " 'Shravan Kumar',\n",
137 | " 'Vikram Bhatt',\n",
138 | " 'Zak Hilditch']"
139 | ]
140 | },
141 | "execution_count": 8,
142 | "metadata": {},
143 | "output_type": "execute_result"
144 | }
145 | ],
146 | "source": [
147 | "df.director.dropna().unique().tolist()[:10]"
148 | ]
149 | },
150 | {
151 | "cell_type": "code",
152 | "execution_count": null,
153 | "id": "510757e0-6ef3-4709-828e-6d4636121109",
154 | "metadata": {},
155 | "outputs": [],
156 | "source": []
157 | }
158 | ],
159 | "metadata": {
160 | "kernelspec": {
161 | "display_name": "Python 3",
162 | "language": "python",
163 | "name": "python3"
164 | },
165 | "language_info": {
166 | "codemirror_mode": {
167 | "name": "ipython",
168 | "version": 3
169 | },
170 | "file_extension": ".py",
171 | "mimetype": "text/x-python",
172 | "name": "python",
173 | "nbconvert_exporter": "python",
174 | "pygments_lexer": "ipython3",
175 | "version": "3.9.1"
176 | }
177 | },
178 | "nbformat": 4,
179 | "nbformat_minor": 5
180 | }
181 |
--------------------------------------------------------------------------------
/exr-001_input-utilisateur/01-sources/recuperer_input.py:
--------------------------------------------------------------------------------
1 | # Demander le prénom, la ville de naissance et l'âge de la personne qui utilise le script
2 | # Afficher ces trois informations
--------------------------------------------------------------------------------
/exr-001_input-utilisateur/02-solution/recuperer_input.py:
--------------------------------------------------------------------------------
1 | prenom = input("Comment vous appelez-vous ? ")
2 | ville_de_naissance = input("Quelle est votre ville de naissance ? ")
3 | age = input("Quel est votre âge ? ")
4 |
5 | print(prenom)
6 | print(ville_de_naissance)
7 | print(age)
--------------------------------------------------------------------------------
/exr-002_changer-type-variable/01-sources/changer_type_variable.py:
--------------------------------------------------------------------------------
1 | # Demander à l'utilisateur d'entrer un nombre
2 | # Afficher le résultat de l'addition de ce nombre avec le nombre a.
3 | # Par exemple : "Le résultat de l'opération est 15" (dans le cas où l'utilisateur entre le nombre 5)
4 |
5 | a = 10
--------------------------------------------------------------------------------
/exr-002_changer-type-variable/02-solution/changer_type_variable.py:
--------------------------------------------------------------------------------
1 | a = 10
2 | b = input("Entrez un nombre : ")
3 | resultat = a + int(b)
4 | print("Le résultat de l'opération est " + str(resultat))
5 |
--------------------------------------------------------------------------------
/exr-004_la-concatenation/01-sources/la_concatenation.py:
--------------------------------------------------------------------------------
1 | """
2 | Dans cet exercice, vous devez utiliser les fonctions de conversions
3 | pour convertir les objets dans le bon type afin d'afficher les phrases
4 | suivantes et éviter les erreurs.
5 |
6 | Phrases à afficher :
7 | J'ai une classe de 30 élèves
8 | 10 + 5 est égal à 15
9 | 15
10 | L'addition de 10 + 5 est égal à 15
11 | """
12 |
13 | a = "J'ai une classe de " + 30 + " élèves"
14 | b = 10 + " + " + "5" + " est égal à " + 15
15 | c = 10 + "5"
16 | d = "L'addition de 10 + 5 est égal à " + 10 + 5
--------------------------------------------------------------------------------
/exr-004_la-concatenation/02-solution/la_concatenation.py:
--------------------------------------------------------------------------------
1 | a = "J'ai une classe de " + str(30) + " élèves"
2 | b = str(10) + " + " + "5" + " est égal à " + str(15)
3 | c = 10 + int("5")
4 | d = "L'addition de 10 + 5 est égal à " + str(10 + 5)
--------------------------------------------------------------------------------
/exr-009_verifier-mot-de-passe/solution/script.py:
--------------------------------------------------------------------------------
1 | mdp = input("Entrez un mot de passe (min 8 caractères) : ")
2 | mdp_trop_court = "votre mot de passe est trop court."
3 |
4 | if len(mdp) == 0:
5 | print(mdp_trop_court.upper())
6 | exit()
7 | elif len(mdp) < 8:
8 | print(mdp_trop_court.capitalize())
9 | exit()
10 |
11 | if mdp.isdigit():
12 | print("Votre mot de passe ne contient que des nombres.")
13 | exit()
14 |
15 | print("Inscription terminée.")
16 |
--------------------------------------------------------------------------------
/exr-009_verifier-mot-de-passe/sources/script.py:
--------------------------------------------------------------------------------
1 | mdp = input("Entrez un mot de passe (min 8 caractères) : ")
2 | mdp_trop_court = "votre mot de passe est trop court."
--------------------------------------------------------------------------------
/exr-010_nombre-mystere-erreurs/01-sources/devine_un_nombre_04.py:
--------------------------------------------------------------------------------
1 | import random
2 |
3 | nombre_mystere = random.randint(0, 10)
4 | nombre = input("Quel est le nombre mystère ? ")
5 | nombre = int(nombre)
6 |
7 | if nombre > nombre_mystere:
8 | print(f"Le nombre mystère est plus petit que {nombre}")
9 | elif nombre < nombre_mystere:
10 | print(f"Le nombre mystère est plus grand que {nombre}")
11 | else:
12 | print("Bravo, vous avez trouvé le nombre mystère !")
13 |
--------------------------------------------------------------------------------
/exr-010_nombre-mystere-erreurs/02-solution/devine_un_nombre_04.py:
--------------------------------------------------------------------------------
1 | import random
2 |
3 | nombre_mystere = random.randint(0, 10)
4 | nombre = input("Quel est le nombre mystère ? ")
5 | if not nombre.isdigit():
6 | print("SVP, entrez un nombre valide.")
7 | exit()
8 |
9 | nombre = int(nombre)
10 | if nombre > nombre_mystere:
11 | print(f"Le nombre mystère est plus petit que {nombre}")
12 | elif nombre < nombre_mystere:
13 | print(f"Le nombre mystère est plus grand que {nombre}")
14 | else:
15 | print("Bravo, vous avez trouvé le nombre mystère !")
16 |
--------------------------------------------------------------------------------
/exr-011_comprehensions-de-liste/01-sources/comprehension_de_liste.py:
--------------------------------------------------------------------------------
1 | nombres = [1, 21, 5, 44, 4, 9, 5, 83, 29, 31, 25, 38]
2 | nombres_pairs = []
3 | for i in nombres:
4 | if i % 2 == 0:
5 | nombres_pairs.append(i)
6 |
7 | print(nombres_pairs)
8 |
9 | # ---------------------------------------------------- #
10 |
11 | nombres = range(-10, 10)
12 | nombres_positifs = []
13 | for i in nombres:
14 | if i >= 0:
15 | nombres_positifs.append(i)
16 |
17 | print(nombres_positifs)
18 |
19 | # ---------------------------------------------------- #
20 |
21 | nombres = range(5)
22 | nombres_doubles = []
23 | for i in nombres:
24 | nombres_doubles.append(i * 2)
25 |
26 | print(nombres_doubles)
27 |
28 | # ---------------------------------------------------- #
29 |
30 | nombres = range(10)
31 | nombres_inverses = []
32 | for i in nombres:
33 | if i % 2 == 0:
34 | nombres_inverses.append(i)
35 | else:
36 | nombres_inverses.append(-i)
37 |
38 | print(nombres_inverses)
--------------------------------------------------------------------------------
/exr-011_comprehensions-de-liste/02-solutions/comprehension_de_liste.py.py:
--------------------------------------------------------------------------------
1 | nombres = [1, 21, 5, 44, 4, 9, 5, 83, 29, 31, 25, 38]
2 | nombres_pairs = [i for i in nombres if i % 2 == 0]
3 | print(nombres_pairs)
4 |
5 | # ---------------------------------------------------- #
6 |
7 | nombres = range(-10, 10)
8 | nombres_positifs = [i for i in nombres if i >= 0]
9 | print(nombres_positifs)
10 |
11 | # ---------------------------------------------------- #
12 |
13 | nombres = range(5)
14 | nombres_doubles = [i * 2 for i in nombres]
15 | print(nombres_doubles)
16 |
17 | # ---------------------------------------------------- #
18 |
19 | nombres = range(10)
20 | nombres_inverses = [i if i % 2 == 0 else -i for i in nombres]
21 | print(nombres_inverses)
--------------------------------------------------------------------------------
/exr-012_afficher-dix-utilisateurs/01-sources/afficher_utilisateurs.py:
--------------------------------------------------------------------------------
1 | """
2 | Votre script doit afficher les chaînes de caractères suivantes :
3 |
4 | Utilisateur 1
5 | Utilisateur 2
6 | Utilisateur 3
7 | Utilisateur 4
8 | Utilisateur 5
9 | Utilisateur 6
10 | Utilisateur 7
11 | Utilisateur 8
12 | Utilisateur 9
13 | Utilisateur 10
14 | """
15 |
--------------------------------------------------------------------------------
/exr-012_afficher-dix-utilisateurs/02-solution/afficher_utilisateurs.py:
--------------------------------------------------------------------------------
1 | # Solution #1
2 | for i in range(10):
3 | print(f"Utilisateur {i + 1}")
4 |
5 | # Solution #2
6 | for i in range(1, 11):
7 | print(f"Utilisateur {i}")
--------------------------------------------------------------------------------
/exr-013_mot-a-lenvers/01-sources/afficher_un_mot_a_lenvers.py:
--------------------------------------------------------------------------------
1 | """
2 | Dans cet exercice vous devez afficher les lettres du mot 'Python' dans le sens inverse.
3 | Votre script devra donc afficher :
4 | n
5 | o
6 | h
7 | t
8 | y
9 | P
10 | """
--------------------------------------------------------------------------------
/exr-013_mot-a-lenvers/02-solution/afficher_un_mot_a_lenvers.py:
--------------------------------------------------------------------------------
1 | # Solution 1
2 | mot = "Python"
3 | for lettre in reversed(mot):
4 | print(lettre)
5 |
6 | # Solution 2
7 | mot = "Python"
8 | for lettre in mot[::-1]:
9 | print(lettre)
--------------------------------------------------------------------------------
/exr-014_boucle-while-input/01-sources/sortir_boucle_while.py:
--------------------------------------------------------------------------------
1 | # Comment peut-on permettre à l'utilisateur de sortir de la boucle
2 | # en modifiant les lignes de code dans la boucle while ?
3 |
4 | continuer = "o"
5 | while continuer == "o":
6 | print("On continue !")
7 | input("Voulez-vous continuer ? o/n ")
--------------------------------------------------------------------------------
/exr-014_boucle-while-input/02-solution/sortir_boucle_while.py:
--------------------------------------------------------------------------------
1 | # Solution 1
2 | continuer = "o"
3 | while continuer == "o":
4 | print("On continue !")
5 | continuer = input("Voulez-vous continuer ? o/n ")
6 |
7 | # Solution 2
8 | continuer = "o"
9 | while continuer == "o":
10 | print("On continue !")
11 | resultat = input("Voulez-vous continuer ? o/n ")
12 | if resultat != "o":
13 | break
14 |
15 | # Solution 3 avec Python 3.8 uniquement
16 | while (continuer := "o") == "o":
17 | print("On continue !")
18 | if (resultat := input("Voulez-vous continuer ? o/n ")) != "o":
19 | break
--------------------------------------------------------------------------------
/exr-025_gerer-erreurs-fichier/01-sources/fichier_invalide.abc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/exr-025_gerer-erreurs-fichier/01-sources/fichier_invalide.abc
--------------------------------------------------------------------------------
/exr-025_gerer-erreurs-fichier/01-sources/readme.txt:
--------------------------------------------------------------------------------
1 | J'adore Python !
--------------------------------------------------------------------------------
/exr-025_gerer-erreurs-fichier/02-solution/fichier_invalide.abc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/exr-025_gerer-erreurs-fichier/02-solution/fichier_invalide.abc
--------------------------------------------------------------------------------
/exr-025_gerer-erreurs-fichier/02-solution/gerer_erreurs.py:
--------------------------------------------------------------------------------
1 | fichier = input("Entrez un fichier à ouvrir : ")
2 |
3 | try:
4 | f = open(fichier, "r")
5 | print(f.read())
6 | except FileNotFoundError:
7 | print("Le fichier est introuvable.")
8 | except UnicodeDecodeError:
9 | print("Impossible d'ouvrir le fichier.")
10 | else:
11 | f.close()
--------------------------------------------------------------------------------
/exr-025_gerer-erreurs-fichier/02-solution/readme.txt:
--------------------------------------------------------------------------------
1 | J'adore Python !
--------------------------------------------------------------------------------
/prj-001_la-calculatrice/01-sources/main.py:
--------------------------------------------------------------------------------
1 | # Demander à l'utilisateur d'entrer un premier nombre
2 | # Demander à l'utilisateur d'entrer un deuxième nombre
3 | # Afficher à l'écran le résultat de l'addition (exemple : 'Le résultat de l'addition de 5 + 10 est égal à 15')
--------------------------------------------------------------------------------
/prj-001_la-calculatrice/02-solution/main.py:
--------------------------------------------------------------------------------
1 | a = int(input("Entrez un premier nombre : "))
2 | b = int(input("Entrez un deuxième nombre : "))
3 | resultat = f"Le résultat de l'addition de {a} avec {b} est égal à {a + b}"
4 | print(resultat)
--------------------------------------------------------------------------------
/prj-002_la-calculatrice-gestion-des-erreurs/01-sources/main.py:
--------------------------------------------------------------------------------
1 | """
2 | Dans ce projet, vous devez réaliser une calculatrice en ligne de commande qui vous permettra d'additionner deux nombres ensemble.
3 |
4 | 👉 Déroulé du script
5 | Le script doit demander à l'utilisateur de saisir deux nombres :
6 |
7 | >>> Entrez un premier nombre : 5
8 | >>> Entrez un deuxième nombre : 10
9 | Le script doit ensuite afficher la phrase suivante :
10 |
11 | "Le résultat de l'addition de 5 avec 10 est égal à 15"
12 |
13 | Vous devrez donc utiliser une fonction de Python qui permet de récupérer la saisie de l'utilisateur (deux fois), pour ensuite additionner ces variables et afficher le résultat.
14 |
15 | Vous devez vous assurer que le programme ne retournera pas d'erreur si l'utilisateur rentre autre chose que deux nombres.
16 |
17 | Il va donc falloir gérer ces cas de figure. Si l'utilisateur rentre une lettre, un symbole ou quoi que ce soit d'autre qu'un nombre, vous devrez lui demander de nouveau de saisir deux valeurs valides :
18 |
19 | >>> Entrez un premier nombre : a
20 | >>> Entrez un deuxième nombre : sgoind
21 | Veuillez entrer deux nombres valides
22 | >>> Entrez un premier nombre
23 | """
--------------------------------------------------------------------------------
/prj-002_la-calculatrice-gestion-des-erreurs/02-solution/main.py:
--------------------------------------------------------------------------------
1 | # On déclare deux variables
2 | a = b = ""
3 |
4 | # Tant que a et b ne sont pas des nombres, on boucle
5 | while not (a.isdigit() and b.isdigit()):
6 |
7 | # On demande deux nombres à l'utilisateur
8 | a = input("Entrez un premier nombre : ")
9 | b = input("Entrez un deuxième nombre : ")
10 |
11 | # On affiche une phrase si les nombres entrés ne sont pas valides.
12 | if not (a.isdigit() and b.isdigit()):
13 | print("Veuillez entrer deux nombres valides")
14 |
15 | # On affiche le résultat de l'addition
16 | print(f"Le résultat de l'addition de {a} avec {b} est égal à {int(a) + int(b)}")
--------------------------------------------------------------------------------
/prj-003_la-liste-de-courses/01-sources/main.py:
--------------------------------------------------------------------------------
1 | """
2 | Dans ce projet, tu vas devoir créer un programme en ligne de commande qui permet de manipuler une liste de courses.
3 |
4 | 👉 Déroulé du script
5 | Le programme doit permettre de réaliser 5 actions :
6 | - Ajouter un élément à la liste de courses
7 | - Retirer un élément de la liste de courses
8 | - Afficher les éléments de la liste de courses
9 | - Vider la liste de courses
10 | - Quitter le programme
11 |
12 | Tu dois donc demander à l'utilisateur de choisir parmi une de ces action en entrant un nombre de 1 à 5.
13 |
14 | Tu dois gérer le cas de figure où l'utilisateur ne rentre pas un nombre compris entre 1 et 5 ou s'il rentre par exemple des lettres ou un autre symbole invalide. Dans ce cas, tu dois afficher de nouveau le menu avec les options disponibles, jusqu'à ce que l'utilisateur choisisse une option valide.
15 |
16 | Dans ce projet, tu ne dois pas sauvegarder la liste dans un fichier ou une base de donnée.
17 |
18 | Le but ici est juste d'interagir avec l'utilisateur et de manipuler une liste en fonction de son choix.
19 |
20 | Bonne chance pour cet exercice ?
21 |
22 | Prends le temps de bien décrire toutes les étapes en français avant de te lancer dans le code !
23 |
24 |
25 | Quelques éléments pour t'aider :
26 |
27 | Pour boucler sur un itérable et récupérer en même temps l'indice de l'itération, tu peux utiliser la fonction enumerate :
28 |
29 | >>> for i, element in enumerate("Python"):
30 | >>> print(i, element)
31 | 0 "P"
32 | 1 "y"
33 | 2 "t"
34 | 3 "h"
35 | 4 "o"
36 | 5 "n"
37 | Pour sortir d'un script en ligne de commande, tu peux utiliser le module sys et la fonction exit :
38 |
39 | import sys
40 | sys.exit()
41 | Cela aura pour effet de mettre fin au script en cours d'exécution.
42 | """
--------------------------------------------------------------------------------
/prj-003_la-liste-de-courses/02-solution/main.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | LISTE = []
4 |
5 | MENU = """Choisissez parmi les 5 options suivantes :
6 | 1: Ajouter un élément à la liste
7 | 2: Retirer un élément de la liste
8 | 3: Afficher la liste
9 | 4: Vider la liste
10 | 5: Quitter
11 | ? Votre choix : """
12 |
13 | MENU_CHOICES = ["1", "2", "3", "4", "5"]
14 |
15 |
16 |
17 | while True:
18 | user_choice = input(MENU)
19 | if user_choice not in MENU_CHOICES:
20 | print("Veuillez choisir une option valide...")
21 | continue
22 |
23 | if user_choice == "1": # Ajouter un élément
24 | item = input("Entrez le nom d'un élément à ajouter à la liste de courses : ")
25 | LISTE.append(item)
26 | print(f"L'élément {item} a bien été ajouté à la liste.")
27 | elif user_choice == "2": # Retirer un élément
28 | item = input("Entrez le nom d'un élément à retirer de la liste de courses : ")
29 | if item in LISTE:
30 | LISTE.remove(item)
31 | print(f"L'élément {item} a bien été supprimé de la liste.")
32 | else:
33 | print(f"L'élément {item} n'est pas dans la liste.")
34 | elif user_choice == "3": # Afficher la liste
35 | if LISTE:
36 | print("Voici le contenu de votre liste :")
37 | for i, item in enumerate(LISTE, 1):
38 | print(f"{i}. {item}")
39 | else:
40 | print("Votre liste ne contient aucun élément.")
41 | elif user_choice == "4": # Vider la liste
42 | LISTE.clear()
43 | print("La liste a été vidée de son contenu.")
44 | elif user_choice == "5": # Quitter
45 | print("À bientôt !")
46 | sys.exit()
47 |
48 | print("-" * 50)
--------------------------------------------------------------------------------
/prj-004_le-nombre-mystere/01-sources/main.py:
--------------------------------------------------------------------------------
1 | """
2 | Le but de ce projet est de permettre à un joueur d'essayer de deviner un nombre mystère généré aléatoirement par l'ordinateur, en 5 essais ou moins.
3 |
4 | 👉 Déroulé du script
5 | Au début du script, vous devez générer un nombre aléatoire compris entre 0 et 100 (vous pouvez agrandir ou réduire cet intervalle pour simplifier ou complexifier le jeu).
6 |
7 | Le joueur dispose alors de 5 essais (là encore, libre à vous de changer cette valeur) pour trouver le nombre mystère.
8 |
9 | À chaque essai, vous devez indiquer au joueur si le nombre qu'il a entré est plus petit ou plus grand que le nombre mystère.
10 |
11 | Si le nombre entré par l'utilisateur est égal au nombre mystère, alors le joueur gagne la partie.
12 |
13 | Dans le cas d'une victoire, vous devez indiquer au joueur combien d'essais lui ont été nécessaire pour gagner.
14 |
15 | Si le joueur ne trouve pas le nombre mystère avec les 5 essais disponibles, il perd la partie.
16 | """
--------------------------------------------------------------------------------
/prj-004_le-nombre-mystere/02-solution/main.py:
--------------------------------------------------------------------------------
1 | from random import randint
2 |
3 | number_to_find = randint(0, 100)
4 | remaining_attempts = 5
5 |
6 | print("*** Le jeu du nombre mystère ***")
7 |
8 | # Boucle principale
9 | while remaining_attempts > 0:
10 | print(f"Il te reste {remaining_attempts} essai{'s' if remaining_attempts > 1 else ''}")
11 |
12 | # Saisie de l'utilisateur
13 | user_choice = input("Devine le nombre : ")
14 | if not user_choice.isdigit():
15 | print("Veuillez entrer un nombre valide.")
16 | continue
17 |
18 | user_choice = int(user_choice)
19 |
20 | if number_to_find > user_choice: # Plus grand
21 | print(f"Le nombre mystère est plus grand que {user_choice}")
22 | elif number_to_find < user_choice: # Plus petit
23 | print(f"Le nombre mystère est plus petit que {user_choice}")
24 | else: # Égal (succès)
25 | break
26 |
27 | remaining_attempts -= 1
28 |
29 | # Gagné ou perdu
30 | if remaining_attempts == 0:
31 | print(f"Dommage ! Le nombre mystère était {number_to_find}")
32 | else:
33 | print(f"Bravo ! Le nombre mystère était bien {number_to_find} !")
34 | print(f"Tu as trouvé le nombre en {6 - remaining_attempts} essai")
35 |
36 | print("Fin du jeu.")
37 |
--------------------------------------------------------------------------------
/prj-005_le-jeu-de-role/01-sources/main.py:
--------------------------------------------------------------------------------
1 | """
2 | Règles du jeu
3 | Le but de ce projet est de créer un jeu de rôle textuel dans le terminal.
4 |
5 | Le jeu comporte deux joueurs : vous et un ennemi.
6 |
7 | Vous commencez tous les deux avec 50 points de vie.
8 |
9 | Votre personnage dispose de 3 potions qui vous permettent de récupérer des points de vie.
10 |
11 | L'ennemi ne dispose d'aucune potion.
12 |
13 | Chaque potion vous permet de récupérer un nombre aléatoire de points de vie, compris entre 15 et 50.
14 |
15 | Votre attaque inflige à l'ennemi des dégâts aléatoires compris entre 5 et 10 points de vie.
16 |
17 | L'attaque de l'ennemi vous inflige des dégâts aléatoires compris entre 5 et 15 points de vie.
18 |
19 | Lorsque vous utilisez une potion, vous passez le prochain tour.
20 |
21 | 👉 Déroulé de la partie
22 | Lorsque vous lancez le script, vous devez demander à l'utilisateur s'il souhaite attaquer ou utiliser une potion :
23 |
24 | "Souhaitez-vous attaquer (1) ou utiliser une potion (2) ? "
25 |
26 | Cette phrase sera demandée à l'utilisateur au début de chaque tour.
27 |
28 | ? Si l'utilisateur choisi la première option (1), vous infligez des points de dégât à l'ennemi.
29 |
30 | Ces points seront compris entre 5 et 10 et déterminés aléatoirement par le programme.
31 |
32 | ? Si l'utilisateur choisi la deuxième option (2), vous prenez une potion.
33 |
34 | Les points de vie que la potion vous donne doivent être compris entre 15 et 50 et générés aléatoirement par le programme Python.
35 |
36 | Vous devez vérifier que l'utilisateur dispose de suffisamment de potion et décrémenter le nombre de potions qu'il a dans son inventaire lorsqu'il en boit une. Si l'utilisateur n'a plus de potions, vous devez lui indiquer et lui proposer de nouveau de faire un choix (attaquer ou prendre une potion).
37 |
38 | Quand le joueur prend une potion, il passe le prochain tour.
39 |
40 | Une fois l'action du joueur exécutée, et si l'ennemi est encore vivant, il vous attaque. Si l'ennemi est mort, vous pouvez terminer le jeu et indiqué à l'utilisateur qu'il a gagné ?
41 |
42 | L'attaque de l'ennemi inflige des dégâts au joueur compris entre 5 et 15, là encore déterminés aléatoirement par le script.
43 |
44 | Si vous n'avez plus de points de vie, le jeu se termine et vous avez perdu la partie.
45 |
46 | À la fin du tour, vous devez afficher le nombre de points de vie restants du joueur et de l'ennemi.
47 |
48 | Toutes ces opérations se répètent tant que le joueur et l'ennemi sont en vie.
49 |
50 | À chaque tour, vous attaquez en premier. Il ne peut donc pas y avoir de match nul. Si lorsque vous attaquez, votre attaque fait descendre les points de vie de l'ennemi en dessous (ou égal à) 0, vous gagnez la partie sans que l'ennemi n'ait le temps de vous attaquer en retour.
51 | """
--------------------------------------------------------------------------------
/prj-005_le-jeu-de-role/02-solution/main.py:
--------------------------------------------------------------------------------
1 | import random
2 |
3 | ENEMY_HEALTH = 50
4 | PLAYER_HEALTH = 50
5 | NUMBER_OF_POTIONS = 3
6 | SKIP_TURN = False
7 |
8 | while True:
9 | # Jeu du joueur
10 | if SKIP_TURN:
11 | print("Vous passez votre tour...")
12 | SKIP_TURN = False
13 | else:
14 | user_choice = ""
15 | while user_choice not in ["1", "2"]:
16 | user_choice = input("Souhaitez-vous attaquer (1) ou utiliser une potion (2) ? ")
17 |
18 | if user_choice == "1": # Attaque
19 | your_attack = random.randint(5, 10)
20 | ENEMY_HEALTH -= your_attack
21 | print(f"Vous avez infligé {your_attack} points de dégats à l'ennemi ⚔️")
22 | elif user_choice == "2" and NUMBER_OF_POTIONS > 0: # Potion
23 | potion_health = random.randint(15, 50)
24 | PLAYER_HEALTH += potion_health
25 | NUMBER_OF_POTIONS -= 1
26 | SKIP_TURN = True
27 | print(f"Vous récupérez {potion_health} points de vie ❤️ ({NUMBER_OF_POTIONS} ? restantes)")
28 | else:
29 | print("Vous n'avez plus de potions...")
30 | continue
31 |
32 |
33 | if ENEMY_HEALTH <= 0:
34 | print("Tu as gagné ?")
35 | break
36 |
37 | # Attaque de l'ennemi
38 | enemy_attack = random.randint(5, 15)
39 | PLAYER_HEALTH -= enemy_attack
40 | print(f"L'ennemi vous a infligé {enemy_attack} points de dégats ⚔️")
41 |
42 | if PLAYER_HEALTH <= 0:
43 | print("Tu as perdu ?")
44 | break
45 |
46 | # Stats
47 | print(f"Il vous reste {PLAYER_HEALTH} points de vie.")
48 | print(f"Il reste {ENEMY_HEALTH} points de vie à l'ennemi.")
49 | print("-" * 50)
50 |
51 | print("Fin du jeu.")
--------------------------------------------------------------------------------
/prj-006_la-liste-de-courses-avec-sauvegarde/01-sources/main.py:
--------------------------------------------------------------------------------
1 | """
2 | Le but de cet exercice est de repartir de notre script de la liste de course et d'ajouter un système de sauvegarde sur le disque.
3 |
4 |
5 | 👉 Quelques astuces pour mener à bien ce projet (ne pas lire si tu souhaites essayer tout seul !)
6 | Pour cet exercice tu vas devoir utiliser le module os et le module json.
7 |
8 | Pour récupérer le chemin complet vers le script Python, tu peux utiliser la variable __file__ qui est définie par Python et qui contient le chemin complet vers le script exécuté.
9 |
10 | Avec le module os, tu peux ensuite récupérer le dossier parent et concaténer le nom du fichier json (liste.json) à ce dossier, avec la fonction os.path.join.
11 |
12 | Pour lire et écrire dans un fichier json, on utilise respectivement les fonctions load et dump du module json.
13 |
14 | Il faudra également t'assurer que le fichier existe avant de lire son contenu. Pour ça tu peux utiliser la fonction os.path.exists du module os.
15 | """
16 |
17 |
18 | import sys
19 |
20 | LISTE = []
21 |
22 | MENU = """Choisissez parmi les 5 options suivantes :
23 | 1: Ajouter un élément à la liste
24 | 2: Retirer un élément de la liste
25 | 3: Afficher la liste
26 | 4: Vider la liste
27 | 5: Quitter
28 | 👉 Votre choix : """
29 |
30 | MENU_CHOICES = ["1", "2", "3", "4", "5"]
31 |
32 |
33 |
34 | while True:
35 | user_choice = ""
36 | while user_choice not in MENU_CHOICES:
37 | user_choice = input(MENU)
38 | if user_choice not in MENU_CHOICES:
39 | print("Veuillez choisir une option valide...")
40 |
41 | if user_choice == "1": # Ajouter un élément
42 | item = input("Entrez le nom d'un élément à ajouter à la liste de courses : ")
43 | LISTE.append(item)
44 | print(f"L'élément {item} a bien été ajouté à la liste.")
45 | elif user_choice == "2": # Retirer un élément
46 | item = input("Entrez le nom d'un élément à retirer de la liste de courses : ")
47 | if item in LISTE:
48 | LISTE.remove(item)
49 | print(f"L'élément {item} a bien été supprimé de la liste.")
50 | else:
51 | print(f"L'élément {item} n'est pas dans la liste.")
52 | elif user_choice == "3": # Afficher la liste
53 | if LISTE:
54 | print("Voici le contenu de votre liste :")
55 | for i, item in enumerate(LISTE, 1):
56 | print(f"{i}. {item}")
57 | else:
58 | print("Votre liste ne contient aucun élément.")
59 | elif user_choice == "4": # Vider la liste
60 | LISTE.clear()
61 | print("La liste a été vidée de son contenu.")
62 | elif user_choice == "5": # Quitter
63 | print("À bientôt !")
64 | sys.exit()
65 |
66 | print("-" * 50)
67 |
--------------------------------------------------------------------------------
/prj-006_la-liste-de-courses-avec-sauvegarde/02-solution/main.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | import json
4 |
5 | CUR_DIR = os.path.dirname(__file__)
6 | LISTE_PATH = os.path.join(CUR_DIR, "liste.json")
7 |
8 | MENU = """Choisissez parmi les 5 options suivantes :
9 | 1: Ajouter un élément à la liste
10 | 2: Retirer un élément de la liste
11 | 3: Afficher la liste
12 | 4: Vider la liste
13 | 5: Quitter
14 | ? Votre choix : """
15 |
16 | MENU_CHOICES = ["1", "2", "3", "4", "5"]
17 |
18 | if os.path.exists(LISTE_PATH):
19 | with open(LISTE_PATH, "r") as f:
20 | LISTE = json.load(f)
21 | else:
22 | LISTE = []
23 |
24 |
25 | while True:
26 | user_choice = ""
27 | while user_choice not in MENU_CHOICES:
28 | user_choice = input(MENU)
29 | if user_choice not in MENU_CHOICES:
30 | print("Veuillez choisir une option valide...")
31 |
32 | if user_choice == "1": # Ajouter un élément
33 | item = input("Entrez le nom d'un élément à ajouter à la liste de courses : ")
34 | LISTE.append(item)
35 | print(f"L'élément {item} a bien été ajouté à la liste.")
36 | elif user_choice == "2": # Retirer un élément
37 | item = input("Entrez le nom d'un élément à retirer de la liste de courses : ")
38 | if item in LISTE:
39 | LISTE.remove(item)
40 | print(f"L'élément {item} a bien été supprimé de la liste.")
41 | else:
42 | print(f"L'élément {item} n'est pas dans la liste.")
43 | elif user_choice == "3": # Afficher la liste
44 | if LISTE:
45 | print("Voici le contenu de votre liste :")
46 | for i, item in enumerate(LISTE, 1):
47 | print(f"{i}. {item}")
48 | else:
49 | print("Votre liste ne contient aucun élément.")
50 | elif user_choice == "4": # Vider la liste
51 | LISTE.clear()
52 | print("La liste a été vidée de son contenu.")
53 | elif user_choice == "5": # Sauvegarder et quitter
54 | with open(LISTE_PATH, "w") as f:
55 | json.dump(LISTE, f, indent=4)
56 | print("À bientôt !")
57 | sys.exit()
58 |
59 | print("-" * 50)
--------------------------------------------------------------------------------
/prj-007_le-trieur-de-fichiers/01-sources/main.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | LISTE = []
4 |
5 | MENU = """Choisissez parmi les 5 options suivantes :
6 | 1: Ajouter un élément à la liste
7 | 2: Retirer un élément de la liste
8 | 3: Afficher la liste
9 | 4: Vider la liste
10 | 5: Quitter
11 | 👉 Votre choix : """
12 |
13 | MENU_CHOICES = ["1", "2", "3", "4", "5"]
14 |
15 |
16 |
17 | while True:
18 | user_choice = ""
19 | while user_choice not in MENU_CHOICES:
20 | user_choice = input(MENU)
21 | if user_choice not in MENU_CHOICES:
22 | print("Veuillez choisir une option valide...")
23 |
24 | if user_choice == "1": # Ajouter un élément
25 | item = input("Entrez le nom d'un élément à ajouter à la liste de courses : ")
26 | LISTE.append(item)
27 | print(f"L'élément {item} a bien été ajouté à la liste.")
28 | elif user_choice == "2": # Retirer un élément
29 | item = input("Entrez le nom d'un élément à retirer de la liste de courses : ")
30 | if item in LISTE:
31 | LISTE.remove(item)
32 | print(f"L'élément {item} a bien été supprimé de la liste.")
33 | else:
34 | print(f"L'élément {item} n'est pas dans la liste.")
35 | elif user_choice == "3": # Afficher la liste
36 | if LISTE:
37 | print("Voici le contenu de votre liste :")
38 | for i, item in enumerate(LISTE, 1):
39 | print(f"{i}. {item}")
40 | else:
41 | print("Votre liste ne contient aucun élément.")
42 | elif user_choice == "4": # Vider la liste
43 | LISTE.clear()
44 | print("La liste a été vidée de son contenu.")
45 | elif user_choice == "5": # Quitter
46 | print("À bientôt !")
47 | sys.exit()
48 |
49 | print("-" * 50)
--------------------------------------------------------------------------------
/prj-007_le-trieur-de-fichiers/02-solution/main.py:
--------------------------------------------------------------------------------
1 | """
2 | Trier les fichiers contenus dans le dossier data selon les associations suivantes :
3 | mp3, wav, flac : Musique
4 | avi, mp4, gif : Videos
5 | bmp, png, jpg : Images
6 | txt, pptx, csv, xls, odp, pages : Documents
7 | autres : Divers
8 | """
9 | from pathlib import Path
10 |
11 |
12 | EXTENSIONS_MAPPING = {".mp3": "Musique",
13 | ".wav": "Musique",
14 | ".mp4": "Videos",
15 | ".avi": "Videos",
16 | ".gif": "Videos",
17 | ".bmp": "Images",
18 | ".png": "Images",
19 | ".jpg": "Images",
20 | ".txt": "Documents",
21 | ".pptx": "Documents",
22 | ".csv": "Documents",
23 | ".xls": "Documents",
24 | ".odp": "Documents",
25 | ".pages": "Documents"}
26 |
27 | BASE_DIR = Path('/Users/thibh/trieur_fichiers/data')
28 |
29 | # On récupère tous les fichiers dans le dossier de base
30 | files = [f for f in BASE_DIR.iterdir() if f.is_file()]
31 | for file in files: # On boucle sur chaque fichier
32 | # On récupère le dossier cible à partir du dictionnaire
33 | dossier_cible = EXTENSIONS_MAPPING.get(file.suffix, "Divers")
34 | # On concatène le dossier de base avec le dossier cible
35 | dossier_cible_absolu = BASE_DIR / dossier_cible
36 | # On crée le dossier cible s'il n'existe pas déjà
37 | dossier_cible_absolu.mkdir(exist_ok=True)
38 | # On concatène le dossier cible avec le nom du fichier
39 | fichier_cible = dossier_cible_absolu / file.name
40 | # On déplace le fichier
41 | file.rename(fichier_cible)
--------------------------------------------------------------------------------
/prj-008_le-createur-de-dossiers/01-sources/main.py:
--------------------------------------------------------------------------------
1 | chemin = "ENTREZ UN CHEMIN DE DOSSIER DANS LEQUEL CRÉER LA STRUCTURE"
2 |
3 | d = {"Films": ["Le seigneur des anneaux",
4 | "Harry Potter",
5 | "Moon",
6 | "Forrest Gump"],
7 | "Employes": ["Paul",
8 | "Pierre",
9 | "Marie"],
10 | "Exercices": ["les_variables",
11 | "les_fichiers",
12 | "les_boucles"]}
--------------------------------------------------------------------------------
/prj-008_le-createur-de-dossiers/02-solution/main.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 |
3 | chemin = "/Users/thibh/dossier_test"
4 |
5 | d = {"Films": ["Le seigneur des anneaux",
6 | "Harry Potter",
7 | "Moon",
8 | "Forrest Gump"],
9 | "Employes": ["Paul",
10 | "Pierre",
11 | "Marie"],
12 | "Exercices": ["les_variables",
13 | "les_fichiers",
14 | "les_boucles"]}
15 |
16 |
17 | for dossier_principal, sous_dossiers in d.items():
18 | for dossier in sous_dossiers:
19 | chemin_dossier = Path(chemin) / dossier_principal / dossier
20 | chemin_dossier.mkdir(exist_ok=True, parents=True)
--------------------------------------------------------------------------------
/prj-009_organiser-des-donnees/01-sources/main.py:
--------------------------------------------------------------------------------
1 | """
2 | Dans cet exercice vous devez :
3 | - Ouvrir le fichier prenoms.txt et lire son contenu.
4 | - Récupérer chaque prénom séparément dans une liste.
5 | - Nettoyer les prénoms pour enlever les virgules, points ou espace.
6 | - Écrire la liste ordonnée et nettoyée dans un nouveau fichier texte.
7 | """
--------------------------------------------------------------------------------
/prj-009_organiser-des-donnees/01-sources/prenoms.txt:
--------------------------------------------------------------------------------
1 | Charlotte, Raphaël, Jade, Justin, Zoe Jeanne, Elsa
2 | Mathis, Sara, David. Chloe, Ludovic, Nicolas, Léo, Mathieu, Charles, Apolline, Noemie, Heloïse, Anaïs, Philippe, Antoine, Lina, Laura
3 | Pauline, Simon
4 | Maxime, Victoire, Noah,
5 | Emilie, Gabrielle, Louise, Nathan, Logan, Margaux, Clemence, Inès, Tommy, Isaac, Malik, Yasmine, Lena, Juliette, Eva, Elisa, Lisa, Salome, Ambre, Emma, Marie, Maya, Dylan, Mathilde, Noa, Christopher, Anna, Alexis, Elise, Guillaume, Adam, Alexandre, Victor, Sarah, Lou, Lucas, Lola, Victoria, Capucine, Jonathan, Clara, Camille, Lea, Félix, Gabriel, Cédric, Josephine, Alex, Sofia, Benjamin, Loïc, Thomas, Elliot, Romane, Agathe, Alix, Manon, Vincent, Alice, Samuel, Hugo, Diane, Julien, Jacob, Margot, Nina, Valentine, Rose, Jérémy, Julie, Anthony, Julia, Tristan
6 | Olivier, Louis, Adèle, Michaël, Lucie,
--------------------------------------------------------------------------------
/prj-009_organiser-des-donnees/02-solution/main.py:
--------------------------------------------------------------------------------
1 | with open("/Users/thibh/Documents/prenoms.txt", "r") as f:
2 | lines = f.read().splitlines()
3 |
4 | prenoms = []
5 | for line in lines:
6 | prenoms.extend(line.split())
7 |
8 | prenoms_final = [prenom.strip(",. ") for prenom in prenoms]
9 |
10 | with open("/Users/thibh/Documents/prenoms_final.txt", "w") as f:
11 | f.write("\n".join(sorted(prenoms_final)))
--------------------------------------------------------------------------------
/prj-009_organiser-des-donnees/02-solution/prenoms.txt:
--------------------------------------------------------------------------------
1 | Charlotte, Raphaël, Jade, Justin, Zoe Jeanne, Elsa
2 | Mathis, Sara, David. Chloe, Ludovic, Nicolas, Léo, Mathieu, Charles, Apolline, Noemie, Heloïse, Anaïs, Philippe, Antoine, Lina, Laura
3 | Pauline, Simon
4 | Maxime, Victoire, Noah,
5 | Emilie, Gabrielle, Louise, Nathan, Logan, Margaux, Clemence, Inès, Tommy, Isaac, Malik, Yasmine, Lena, Juliette, Eva, Elisa, Lisa, Salome, Ambre, Emma, Marie, Maya, Dylan, Mathilde, Noa, Christopher, Anna, Alexis, Elise, Guillaume, Adam, Alexandre, Victor, Sarah, Lou, Lucas, Lola, Victoria, Capucine, Jonathan, Clara, Camille, Lea, Félix, Gabriel, Cédric, Josephine, Alex, Sofia, Benjamin, Loïc, Thomas, Elliot, Romane, Agathe, Alix, Manon, Vincent, Alice, Samuel, Hugo, Diane, Julien, Jacob, Margot, Nina, Valentine, Rose, Jérémy, Julie, Anthony, Julia, Tristan
6 | Olivier, Louis, Adèle, Michaël, Lucie,
--------------------------------------------------------------------------------
/prj-009_organiser-des-donnees/02-solution/prenoms_final.txt:
--------------------------------------------------------------------------------
1 | Adam
2 | Adèle
3 | Agathe
4 | Alex
5 | Alexandre
6 | Alexis
7 | Alice
8 | Alix
9 | Ambre
10 | Anaïs
11 | Anna
12 | Anthony
13 | Antoine
14 | Apolline
15 | Benjamin
16 | Camille
17 | Capucine
18 | Charles
19 | Charlotte
20 | Chloe
21 | Christopher
22 | Clara
23 | Clemence
24 | Cédric
25 | David
26 | Diane
27 | Dylan
28 | Elisa
29 | Elise
30 | Elliot
31 | Elsa
32 | Emilie
33 | Emma
34 | Eva
35 | Félix
36 | Gabriel
37 | Gabrielle
38 | Guillaume
39 | Heloïse
40 | Hugo
41 | Inès
42 | Isaac
43 | Jacob
44 | Jade
45 | Jeanne
46 | Jonathan
47 | Josephine
48 | Julia
49 | Julie
50 | Julien
51 | Juliette
52 | Justin
53 | Jérémy
54 | Laura
55 | Lea
56 | Lena
57 | Lina
58 | Lisa
59 | Logan
60 | Lola
61 | Lou
62 | Louis
63 | Louise
64 | Loïc
65 | Lucas
66 | Lucie
67 | Ludovic
68 | Léo
69 | Malik
70 | Manon
71 | Margaux
72 | Margot
73 | Marie
74 | Mathieu
75 | Mathilde
76 | Mathis
77 | Maxime
78 | Maya
79 | Michaël
80 | Nathan
81 | Nicolas
82 | Nina
83 | Noa
84 | Noah
85 | Noemie
86 | Olivier
87 | Pauline
88 | Philippe
89 | Raphaël
90 | Romane
91 | Rose
92 | Salome
93 | Samuel
94 | Sara
95 | Sarah
96 | Simon
97 | Sofia
98 | Thomas
99 | Tommy
100 | Tristan
101 | Valentine
102 | Victoire
103 | Victor
104 | Victoria
105 | Vincent
106 | Yasmine
107 | Zoe
--------------------------------------------------------------------------------
/prj-010_le-gestionnaire-dutilisateurs-crm/user.py:
--------------------------------------------------------------------------------
1 | """Module to generate random users"""
2 | import faker
3 | import logging
4 | from pathlib import Path
5 |
6 | BASE_DIR = Path(__file__).resolve().parent
7 | logging.basicConfig(filename=BASE_DIR / 'user.log', level=logging.WARNING)
8 |
9 | fake = faker.Faker()
10 |
11 |
12 | def get_user():
13 | """Generate a single user
14 |
15 | Returns:
16 | str: user
17 | """
18 | logging.info("Generating user.")
19 | return f"{fake.first_name()} {fake.last_name()}"
20 |
21 |
22 | def get_users(n):
23 | """Generate a list of users
24 |
25 | Args:
26 | n (int): Number of user to generate
27 |
28 | Returns:
29 | list[str]: users
30 | """
31 | logging.info(f"Generating a list of {n} user.")
32 | return [get_user() for _ in range(n)]
33 |
34 |
35 | if __name__ == "__main__":
36 | user = get_users(n=5)
37 | print(user)
--------------------------------------------------------------------------------
/prj-011_creer-une-classe-voiture/voiture.py:
--------------------------------------------------------------------------------
1 | class Voiture:
2 | def __init__(self):
3 | self.essence = 100
4 |
5 | def afficher_reservoir(self):
6 | print(f"La voiture contient {self.essence}L d'essence.")
7 |
8 | def roule(self, km):
9 | if self.essence <= 0:
10 | print("Vous n'avez plus d'essence, faites le plein !")
11 | return
12 |
13 | self.essence -= (km * 5) / 100
14 |
15 | if self.essence < 10:
16 | print("Vous n'avez bientôt plus d'essence !")
17 |
18 | self.afficher_reservoir()
19 |
20 | def faire_le_plein(self):
21 | self.essence = 100
22 | print("Vous pouvez repartir !")
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/prj-012_le-gestionnaire-dutilisateurs-poo/crm.py:
--------------------------------------------------------------------------------
1 | import re
2 | import string
3 | from tinydb import TinyDB, where, table
4 | from pathlib import Path
5 | from typing import List
6 |
7 |
8 | class User:
9 | DB = TinyDB(Path(__file__).resolve().parent / 'db.json', indent=4)
10 |
11 | def __init__(self, first_name: str, last_name: str, phone_number: str = "", address: str = ""):
12 | self.first_name = first_name
13 | self.last_name = last_name
14 | self.phone_number = phone_number
15 | self.address = address
16 |
17 | def __repr__(self):
18 | return f"User({self.first_name}, {self.last_name})"
19 |
20 | def __str__(self):
21 | return f"{self.full_name}\n{self.phone_number}\n{self.address}"
22 |
23 | @property
24 | def full_name(self):
25 | return f"{self.first_name} {self.last_name}"
26 |
27 | @property
28 | def db_instance(self) -> table.Document:
29 | return User.DB.get((where('first_name') == self.first_name) & (where('last_name') == self.last_name))
30 |
31 | def _checks(self):
32 | self._check_phone_number()
33 | self._check_names()
34 |
35 | def _check_phone_number(self):
36 | phone_number = re.sub(r"[+()\s]*", "", self.phone_number)
37 | if len(phone_number) < 10 or not phone_number.isdigit():
38 | raise ValueError(f"Numéro de téléphone {self.phone_number} invalide.")
39 |
40 | def _check_names(self):
41 | if not (self.first_name and self.last_name):
42 | raise ValueError("Le prénom et le nom de famille ne peuvent pas être vides.")
43 |
44 | special_characters = string.punctuation + string.digits
45 |
46 | for character in self.first_name + self.last_name:
47 | if character in special_characters:
48 | raise ValueError(f"Nom invalide {self.full_name}.")
49 |
50 | def exists(self):
51 | return bool(self.db_instance)
52 |
53 | def delete(self) -> List[int]:
54 | if self.exists():
55 | return User.DB.remove(doc_ids=[self.db_instance.doc_id])
56 | return []
57 |
58 | def save(self, validate_data: bool = False) -> int:
59 | if validate_data:
60 | self._checks()
61 |
62 | if self.exists():
63 | return -1
64 | else:
65 | return User.DB.insert(self.__dict__)
66 |
67 |
68 | def get_all_users():
69 | return [User(**user) for user in User.DB.all()]
70 |
71 |
72 | if __name__ == "__main__":
73 | martin = User("Martin", "Voisin")
--------------------------------------------------------------------------------
/prj-013_le-gestionnaire-dutilisateurs-tests/crm.py:
--------------------------------------------------------------------------------
1 | import re
2 | import string
3 | from tinydb import TinyDB, where, table
4 | from pathlib import Path
5 | from typing import List
6 |
7 |
8 | class User:
9 | DB = TinyDB(Path(__file__).resolve().parent / 'db.json', indent=4)
10 |
11 | def __init__(self, first_name: str, last_name: str, phone_number: str = "", address: str = ""):
12 | self.first_name = first_name
13 | self.last_name = last_name
14 | self.phone_number = phone_number
15 | self.address = address
16 |
17 | def __repr__(self):
18 | return f"User({self.first_name}, {self.last_name})"
19 |
20 | def __str__(self):
21 | return f"{self.full_name}\n{self.phone_number}\n{self.address}"
22 |
23 | @property
24 | def full_name(self):
25 | return f"{self.first_name} {self.last_name}"
26 |
27 | @property
28 | def db_instance(self) -> table.Document:
29 | return User.DB.get((where('first_name') == self.first_name) & (where('last_name') == self.last_name))
30 |
31 | def _checks(self):
32 | self._check_phone_number()
33 | self._check_names()
34 |
35 | def _check_phone_number(self):
36 | phone_number = re.sub(r"[+()\s]*", "", self.phone_number)
37 | if len(phone_number) < 10 or not phone_number.isdigit():
38 | raise ValueError(f"Numéro de téléphone {self.phone_number} invalide.")
39 |
40 | def _check_names(self):
41 | if not (self.first_name and self.last_name):
42 | raise ValueError("Le prénom et le nom de famille ne peuvent pas être vides.")
43 |
44 | special_characters = string.punctuation + string.digits
45 |
46 | for character in self.first_name + self.last_name:
47 | if character in special_characters:
48 | raise ValueError(f"Nom invalide {self.full_name}.")
49 |
50 | def exists(self):
51 | return bool(self.db_instance)
52 |
53 | def delete(self) -> List[int]:
54 | if self.exists():
55 | return User.DB.remove(doc_ids=[self.db_instance.doc_id])
56 | return []
57 |
58 | def save(self, validate_data: bool = False) -> int:
59 | if validate_data:
60 | self._checks()
61 |
62 | if self.exists():
63 | return -1
64 | else:
65 | return User.DB.insert(self.__dict__)
66 |
67 |
68 | def get_all_users():
69 | return [User(**user) for user in User.DB.all()]
70 |
71 |
72 | if __name__ == "__main__":
73 | martin = User("Martin", "Voisin")
--------------------------------------------------------------------------------
/prj-013_le-gestionnaire-dutilisateurs-tests/test_crm.py:
--------------------------------------------------------------------------------
1 | from crm import User
2 | import pytest
3 | from tinydb import TinyDB, table
4 | from tinydb.storages import MemoryStorage
5 |
6 |
7 | @pytest.fixture
8 | def setup_db():
9 | User.DB = TinyDB(storage=MemoryStorage)
10 |
11 |
12 | @pytest.fixture
13 | def user(setup_db):
14 | u = User(first_name="Patrick",
15 | last_name="Martin",
16 | address="1 rue du chemin, 75000 Paris",
17 | phone_number="0123456789")
18 | u.save()
19 | return u
20 |
21 |
22 | def test_first_name(user):
23 | assert user.first_name == "Patrick"
24 |
25 |
26 | def test_full_name(user):
27 | assert user.full_name == "Patrick Martin"
28 |
29 |
30 | def test_exists(user):
31 | assert user.exists() is True
32 |
33 |
34 | def test_not_exists(setup_db):
35 | u = User(first_name="Patrick",
36 | last_name="Martin",
37 | address="1 rue du chemin, 75000 Paris",
38 | phone_number="0123456789")
39 | assert u.exists() is False
40 |
41 |
42 | def test_db_instance(user):
43 | assert isinstance(user.db_instance, table.Document)
44 | assert user.db_instance["first_name"] == "Patrick"
45 | assert user.db_instance["last_name"] == "Martin"
46 | assert user.db_instance["address"] == "1 rue du chemin, 75000 Paris"
47 | assert user.db_instance["phone_number"] == "0123456789"
48 |
49 |
50 | def test_not_db_instance(setup_db):
51 | u = User(first_name="Patrick",
52 | last_name="Martin",
53 | address="1 rue du chemin, 75000 Paris",
54 | phone_number="0123456789")
55 | assert u.db_instance is None
56 |
57 |
58 | def test__check_phone_number(setup_db):
59 | user_good = User(first_name="Jean",
60 | last_name="Smith",
61 | address="1 rue du chemin, 75015, Paris",
62 | phone_number="0123456789")
63 | user_bad = User(first_name="Jean",
64 | last_name="Smith",
65 | address="1 rue du chemin, 75015, Paris",
66 | phone_number="abcd")
67 |
68 | with pytest.raises(ValueError) as err:
69 | user_bad._check_phone_number()
70 |
71 | assert "invalide" in str(err.value)
72 |
73 | user_good.save(validate_data=True)
74 | assert user_good.exists() is True
75 |
76 |
77 | def test__check_names_empty(setup_db):
78 | user_bad = User(first_name="",
79 | last_name="",
80 | address="1 rue du chemin, 75000 Paris",
81 | phone_number="0123456789")
82 |
83 | with pytest.raises(ValueError) as err:
84 | user_bad._check_names()
85 |
86 | assert "Le prénom et le nom de famille ne peuvent pas être vides." in str(err.value)
87 |
88 |
89 | def test__check_names_invalid_characters(setup_db):
90 | user_bad = User(first_name="Patrick%&*$?%&",
91 | last_name="#(*%$(*",
92 | address="1 rue du chemin, 75000 Paris",
93 | phone_number="0123456789")
94 |
95 | with pytest.raises(ValueError) as err:
96 | user_bad._check_names()
97 |
98 | assert "Nom invalide" in str(err.value)
99 |
100 |
101 | def test_delete(setup_db):
102 | user_test = User(first_name="John",
103 | last_name="Smith",
104 | address="1 rue du chemin, 75015, Paris",
105 | phone_number="0123456789")
106 | user_test.save()
107 | first = user_test.delete()
108 | second = user_test.delete()
109 | assert len(first) > 0
110 | assert isinstance(first, list)
111 | assert len(second) == 0
112 | assert isinstance(second, list)
113 |
114 |
115 | def test_save(setup_db):
116 | user_test = User(first_name="John",
117 | last_name="Smith",
118 | address="1 rue du chemin, 75015, Paris",
119 | phone_number="0123456789")
120 | user_test_dup = User(first_name="John",
121 | last_name="Smith",
122 | address="1 rue du chemin, 75015, Paris",
123 | phone_number="0123456789")
124 | first = user_test.save()
125 | second = user_test_dup.save()
126 | assert isinstance(first, int)
127 | assert isinstance(second, int)
128 | assert first > 0
129 | assert second == -1
130 |
--------------------------------------------------------------------------------
/prj-014_le-gestionnaire-dutilisateurs-django/requirements.txt:
--------------------------------------------------------------------------------
1 | attrs==21.2.0
2 | click==7.1.2
3 | Faker==8.4.0
4 | importlib-metadata==4.3.1
5 | iniconfig==1.1.1
6 | packaging==20.9
7 | pluggy==0.13.1
8 | py==1.10.0
9 | pyparsing==2.4.7
10 | pytest==6.2.4
11 | python-dateutil==2.8.1
12 | six==1.16.0
13 | text-unidecode==1.3
14 | tinydb==4.4.0
15 | toml==0.10.2
16 | typing-extensions==3.10.0.0
17 | zipp==3.4.1
18 |
--------------------------------------------------------------------------------
/prj-014_le-gestionnaire-dutilisateurs-django/webapp/api/crm.py:
--------------------------------------------------------------------------------
1 | import re
2 | import string
3 | from tinydb import TinyDB, where, table
4 | from pathlib import Path
5 | from typing import List
6 |
7 |
8 | class User:
9 | DB = TinyDB(Path(__file__).resolve().parent / 'db.json', indent=4)
10 |
11 | def __init__(self, first_name: str, last_name: str, phone_number: str = "", address: str = ""):
12 | self.first_name = first_name
13 | self.last_name = last_name
14 | self.phone_number = phone_number
15 | self.address = address
16 |
17 | def __repr__(self):
18 | return f"User({self.first_name}, {self.last_name})"
19 |
20 | def __str__(self):
21 | return f"{self.full_name}\n{self.phone_number}\n{self.address}"
22 |
23 | @property
24 | def full_name(self):
25 | return f"{self.first_name} {self.last_name}"
26 |
27 | @property
28 | def db_instance(self) -> table.Document:
29 | return User.DB.get((where('first_name') == self.first_name) & (where('last_name') == self.last_name))
30 |
31 | def _checks(self):
32 | self._check_phone_number()
33 | self._check_names()
34 |
35 | def _check_phone_number(self):
36 | phone_number = re.sub(r"[+()\s]*", "", self.phone_number)
37 | if len(phone_number) < 10 or not phone_number.isdigit():
38 | raise ValueError(f"Numéro de téléphone {self.phone_number} invalide.")
39 |
40 | def _check_names(self):
41 | if not (self.first_name and self.last_name):
42 | raise ValueError("Le prénom et le nom de famille ne peuvent pas être vides.")
43 |
44 | special_characters = string.punctuation + string.digits
45 |
46 | for character in self.first_name + self.last_name:
47 | if character in special_characters:
48 | raise ValueError(f"Nom invalide {self.full_name}.")
49 |
50 | def exists(self):
51 | return bool(self.db_instance)
52 |
53 | def delete(self) -> List[int]:
54 | if self.exists():
55 | return User.DB.remove(doc_ids=[self.db_instance.doc_id])
56 | return []
57 |
58 | def save(self, validate_data: bool = False) -> int:
59 | if validate_data:
60 | self._checks()
61 |
62 | if self.exists():
63 | return -1
64 | else:
65 | return User.DB.insert(self.__dict__)
66 |
67 |
68 | def get_all_users():
69 | return [User(**user) for user in User.DB.all()]
70 |
71 |
72 | if __name__ == "__main__":
73 | martin = User("Martin", "Voisin")
74 | for i in martin.delete():
75 | print(i)
76 |
--------------------------------------------------------------------------------
/prj-014_le-gestionnaire-dutilisateurs-django/webapp/api/db.json:
--------------------------------------------------------------------------------
1 | {
2 | "_default": {
3 | "1": {
4 | "first_name": "Patrick",
5 | "last_name": "Smith",
6 | "phone_number": "0123456789",
7 | "address": "10 rue des champs \u00e9lys\u00e9e, Paris"
8 | },
9 | "2": {
10 | "first_name": "John",
11 | "last_name": "Smith",
12 | "phone_number": "0123456789",
13 | "address": "10 rue du chemin vert, Toulouse"
14 | },
15 | "6": {
16 | "first_name": "Patrick",
17 | "last_name": "Martin",
18 | "phone_number": "9876543210",
19 | "address": "1 rue du chemin vert,\r\n75000 Paris"
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/prj-014_le-gestionnaire-dutilisateurs-django/webapp/api/test_crm.py:
--------------------------------------------------------------------------------
1 | from crm import User
2 | import pytest
3 | from tinydb import TinyDB, table
4 | from tinydb.storages import MemoryStorage
5 |
6 |
7 | @pytest.fixture
8 | def setup_db():
9 | User.DB = TinyDB(storage=MemoryStorage)
10 |
11 |
12 | @pytest.fixture
13 | def user(setup_db):
14 | u = User(first_name="Patrick",
15 | last_name="Martin",
16 | address="1 rue du chemin, 75000 Paris",
17 | phone_number="0123456789")
18 | u.save()
19 | return u
20 |
21 |
22 | def test_first_name(user):
23 | assert user.first_name == "Patrick"
24 |
25 |
26 | def test_full_name(user):
27 | assert user.full_name == "Patrick Martin"
28 |
29 |
30 | def test_exists(user):
31 | assert user.exists() is True
32 |
33 |
34 | def test_not_exists(setup_db):
35 | u = User(first_name="Patrick",
36 | last_name="Martin",
37 | address="1 rue du chemin, 75000 Paris",
38 | phone_number="0123456789")
39 | assert u.exists() is False
40 |
41 |
42 | def test_db_instance(user):
43 | assert isinstance(user.db_instance, table.Document)
44 | assert user.db_instance["first_name"] == "Patrick"
45 | assert user.db_instance["last_name"] == "Martin"
46 | assert user.db_instance["address"] == "1 rue du chemin, 75000 Paris"
47 | assert user.db_instance["phone_number"] == "0123456789"
48 |
49 |
50 | def test_not_db_instance(setup_db):
51 | u = User(first_name="Patrick",
52 | last_name="Martin",
53 | address="1 rue du chemin, 75000 Paris",
54 | phone_number="0123456789")
55 | assert u.db_instance is None
56 |
57 |
58 | def test__check_phone_number(setup_db):
59 | user_good = User(first_name="Jean",
60 | last_name="Smith",
61 | address="1 rue du chemin, 75015, Paris",
62 | phone_number="0123456789")
63 | user_bad = User(first_name="Jean",
64 | last_name="Smith",
65 | address="1 rue du chemin, 75015, Paris",
66 | phone_number="abcd")
67 |
68 | with pytest.raises(ValueError) as err:
69 | user_bad._check_phone_number()
70 |
71 | assert "invalide" in str(err.value)
72 |
73 | user_good.save(validate_data=True)
74 | assert user_good.exists() is True
75 |
76 |
77 | def test__check_names_empty(setup_db):
78 | user_bad = User(first_name="",
79 | last_name="",
80 | address="1 rue du chemin, 75000 Paris",
81 | phone_number="0123456789")
82 |
83 | with pytest.raises(ValueError) as err:
84 | user_bad._check_names()
85 |
86 | assert "Le prénom et le nom de famille ne peuvent pas être vides." in str(err.value)
87 |
88 |
89 | def test__check_names_invalid_characters(setup_db):
90 | user_bad = User(first_name="Patrick%&*$?%&",
91 | last_name="#(*%$(*",
92 | address="1 rue du chemin, 75000 Paris",
93 | phone_number="0123456789")
94 |
95 | with pytest.raises(ValueError) as err:
96 | user_bad._check_names()
97 |
98 | assert "Nom invalide" in str(err.value)
99 |
100 |
101 | def test_delete(setup_db):
102 | user_test = User(first_name="John",
103 | last_name="Smith",
104 | address="1 rue du chemin, 75015, Paris",
105 | phone_number="0123456789")
106 | user_test.save()
107 | first = user_test.delete()
108 | second = user_test.delete()
109 | assert len(first) > 0
110 | assert isinstance(first, list)
111 | assert len(second) == 0
112 | assert isinstance(second, list)
113 |
114 |
115 | def test_save(setup_db):
116 | user_test = User(first_name="John",
117 | last_name="Smith",
118 | address="1 rue du chemin, 75015, Paris",
119 | phone_number="0123456789")
120 | user_test_dup = User(first_name="John",
121 | last_name="Smith",
122 | address="1 rue du chemin, 75015, Paris",
123 | phone_number="0123456789")
124 | first = user_test.save()
125 | second = user_test_dup.save()
126 | assert isinstance(first, int)
127 | assert isinstance(second, int)
128 | assert first > 0
129 | assert second == -1
130 |
--------------------------------------------------------------------------------
/prj-014_le-gestionnaire-dutilisateurs-django/webapp/contacts/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/prj-014_le-gestionnaire-dutilisateurs-django/webapp/contacts/__init__.py
--------------------------------------------------------------------------------
/prj-014_le-gestionnaire-dutilisateurs-django/webapp/contacts/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class ContactsConfig(AppConfig):
5 | default_auto_field = 'django.db.models.BigAutoField'
6 | name = 'contacts'
7 |
--------------------------------------------------------------------------------
/prj-014_le-gestionnaire-dutilisateurs-django/webapp/contacts/static/css/style.css:
--------------------------------------------------------------------------------
1 | .navbar {
2 | background-color: #0d6efd;
3 | padding: 24px;
4 | margin-bottom: 32px;
5 | }
--------------------------------------------------------------------------------
/prj-014_le-gestionnaire-dutilisateurs-django/webapp/contacts/templates/contacts/index.html:
--------------------------------------------------------------------------------
1 | {% load static %}
2 |
3 |
4 |
5 |
6 | Mon carnet d'adresse
7 |
8 |
9 |
10 |
11 |
12 |
13 |
Mon carnet d'adresse
14 |
15 |
16 |
17 |
18 | {% for user in users %}
19 |
20 |
21 |
22 |
{{ user.full_name }}
23 |
24 | {% if user.phone_number %}
{{ user.phone_number }}
{% endif %}
25 | {% if user.address %}
{{ user.address }}
{% endif %}
26 |
27 |
33 |
34 |
35 |
36 | {% endfor %}
37 |
38 |
39 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/prj-014_le-gestionnaire-dutilisateurs-django/webapp/contacts/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render, redirect
2 | from api.crm import get_all_users, User
3 |
4 |
5 | def index(request):
6 | return render(request, 'contacts/index.html', {'users': get_all_users()})
7 |
8 |
9 | def add_contact(request):
10 | first_name = request.POST.get("first_name")
11 | last_name = request.POST.get("last_name")
12 | address = request.POST.get("address")
13 | phone_number = request.POST.get("phone_number")
14 |
15 | user = User(first_name=first_name,
16 | last_name=last_name,
17 | phone_number=phone_number,
18 | address=address)
19 | user.save()
20 |
21 | return redirect('index')
22 |
23 |
24 | def delete_contact(request):
25 | first_name = request.POST.get("first_name")
26 | last_name = request.POST.get("last_name")
27 | user = User(first_name, last_name)
28 | user.delete()
29 |
30 | return redirect('index')
--------------------------------------------------------------------------------
/prj-014_le-gestionnaire-dutilisateurs-django/webapp/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """Django's command-line utility for administrative tasks."""
3 | import os
4 | import sys
5 |
6 |
7 | def main():
8 | """Run administrative tasks."""
9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'webapp.settings')
10 | try:
11 | from django.core.management import execute_from_command_line
12 | except ImportError as exc:
13 | raise ImportError(
14 | "Couldn't import Django. Are you sure it's installed and "
15 | "available on your PYTHONPATH environment variable? Did you "
16 | "forget to activate a virtual environment?"
17 | ) from exc
18 | execute_from_command_line(sys.argv)
19 |
20 |
21 | if __name__ == '__main__':
22 | main()
23 |
--------------------------------------------------------------------------------
/prj-014_le-gestionnaire-dutilisateurs-django/webapp/webapp/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DocstringFr/la-formation-complete-python/58f7f8fbd4dbd9fbe21026bb07281688fb00bc2e/prj-014_le-gestionnaire-dutilisateurs-django/webapp/webapp/__init__.py
--------------------------------------------------------------------------------
/prj-014_le-gestionnaire-dutilisateurs-django/webapp/webapp/asgi.py:
--------------------------------------------------------------------------------
1 | """
2 | ASGI config for webapp project.
3 |
4 | It exposes the ASGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.asgi import get_asgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'webapp.settings')
15 |
16 | application = get_asgi_application()
17 |
--------------------------------------------------------------------------------
/prj-014_le-gestionnaire-dutilisateurs-django/webapp/webapp/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for webapp project.
3 |
4 | Generated by 'django-admin startproject' using Django 3.2.3.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.2/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/3.2/ref/settings/
11 | """
12 |
13 | from pathlib import Path
14 |
15 | # Build paths inside the project like this: BASE_DIR / 'subdir'.
16 | BASE_DIR = Path(__file__).resolve().parent.parent
17 |
18 |
19 | # Quick-start development settings - unsuitable for production
20 | # See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
21 |
22 | # SECURITY WARNING: keep the secret key used in production secret!
23 | SECRET_KEY = 'django-insecure-zqw(ks39=&cmoonh^1=12j(kvto4=lp9yznl%q$j04an25^pe#'
24 |
25 | # SECURITY WARNING: don't run with debug turned on in production!
26 | DEBUG = True
27 |
28 | ALLOWED_HOSTS = []
29 |
30 |
31 | # Application definition
32 |
33 | INSTALLED_APPS = [
34 | 'django.contrib.admin',
35 | 'django.contrib.auth',
36 | 'django.contrib.contenttypes',
37 | 'django.contrib.sessions',
38 | 'django.contrib.messages',
39 | 'django.contrib.staticfiles',
40 | 'contacts'
41 | ]
42 |
43 | MIDDLEWARE = [
44 | 'django.middleware.security.SecurityMiddleware',
45 | 'django.contrib.sessions.middleware.SessionMiddleware',
46 | 'django.middleware.common.CommonMiddleware',
47 | 'django.middleware.csrf.CsrfViewMiddleware',
48 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
49 | 'django.contrib.messages.middleware.MessageMiddleware',
50 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
51 | ]
52 |
53 | ROOT_URLCONF = 'webapp.urls'
54 |
55 | TEMPLATES = [
56 | {
57 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
58 | 'DIRS': [],
59 | 'APP_DIRS': True,
60 | 'OPTIONS': {
61 | 'context_processors': [
62 | 'django.template.context_processors.debug',
63 | 'django.template.context_processors.request',
64 | 'django.contrib.auth.context_processors.auth',
65 | 'django.contrib.messages.context_processors.messages',
66 | ],
67 | },
68 | },
69 | ]
70 |
71 | WSGI_APPLICATION = 'webapp.wsgi.application'
72 |
73 |
74 | # Database
75 | # https://docs.djangoproject.com/en/3.2/ref/settings/#databases
76 |
77 | DATABASES = {
78 | 'default': {
79 | 'ENGINE': 'django.db.backends.sqlite3',
80 | 'NAME': BASE_DIR / 'db.sqlite3',
81 | }
82 | }
83 |
84 |
85 | # Password validation
86 | # https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
87 |
88 | AUTH_PASSWORD_VALIDATORS = [
89 | {
90 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
91 | },
92 | {
93 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
94 | },
95 | {
96 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
97 | },
98 | {
99 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
100 | },
101 | ]
102 |
103 |
104 | # Internationalization
105 | # https://docs.djangoproject.com/en/3.2/topics/i18n/
106 |
107 | LANGUAGE_CODE = 'en-us'
108 |
109 | TIME_ZONE = 'UTC'
110 |
111 | USE_I18N = True
112 |
113 | USE_L10N = True
114 |
115 | USE_TZ = True
116 |
117 |
118 | # Static files (CSS, JavaScript, Images)
119 | # https://docs.djangoproject.com/en/3.2/howto/static-files/
120 |
121 | STATIC_URL = '/static/'
122 |
123 | # Default primary key field type
124 | # https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
125 |
126 | DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
127 |
--------------------------------------------------------------------------------
/prj-014_le-gestionnaire-dutilisateurs-django/webapp/webapp/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path
2 |
3 | from contacts.views import index, add_contact, delete_contact
4 |
5 | urlpatterns = [
6 | path('', index, name="index"),
7 | path('add/', add_contact, name="add-contact"),
8 | path('delete/', delete_contact, name="delete-contact"),
9 | ]
10 |
--------------------------------------------------------------------------------
/prj-014_le-gestionnaire-dutilisateurs-django/webapp/webapp/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for webapp project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'webapp.settings')
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------