├── .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 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 |
Packages{"pluggy": "0.13.1", "py": "1.10.0", "pytest": "6.2.2"}
PlatformmacOS-10.16-x86_64-i386-64bit
Plugins{"html": "3.1.1", "metadata": "1.11.0"}
Python3.9.1
261 |

Summary

262 |

4 tests ran in 0.04 seconds.

263 | 3 passed, 0 skipped, 1 failed, 0 errors, 0 expected failures, 0 unexpected passes 264 |

Results

265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 |
ResultTestDurationLinks
Failedtest.py::test_add_with_two_booleans0.00
282 |
def test_add_with_two_booleans():
> assert add(True, False) == 0
E assert 1 == 0
E +1
E -0

test.py:15: AssertionError
Passedtest.py::test_add_with_two_numbers0.00
291 |
No log output captured.
Passedtest.py::test_add_with_two_letters0.00
300 |
No log output captured.
Passedtest.py::test_add_with_two_none0.00
309 |
No log output captured.
-------------------------------------------------------------------------------- /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 | 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 |
28 | {% csrf_token %} 29 | 30 | 31 | 32 |
33 |
34 |
35 |
36 | {% endfor %} 37 |
38 | 39 |
40 | 41 |
42 | {% csrf_token %} 43 |
44 | 45 | 46 |
47 |
48 | 49 | 50 |
51 |
52 | 53 | 54 |
55 |
56 | 57 | 58 |
59 | 60 |
61 | 62 |
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 | --------------------------------------------------------------------------------