├── .gitignore ├── .pre-commit-config.yaml ├── .vscode ├── extensions.json ├── launch.json ├── settings.json └── workspace.code-snippets ├── LICENSE ├── README.md ├── docs ├── Makefile ├── conf.py ├── index.rst ├── lab1 │ └── index.rst ├── lab2 │ └── index.rst └── make.bat ├── environment.yml ├── notebooks ├── lab1.ipynb ├── lab2.ipynb ├── lab3.ipynb ├── lab4.ipynb ├── lab5.ipynb └── lab6.ipynb ├── notes ├── anaconda-vscode.md ├── command-line.md ├── new-project-setup.md ├── packaging.md ├── project-workflow.md ├── self-evaluation.md ├── tests-documentation.md ├── to-go-further.md └── version-control.md ├── pyproject.toml ├── setup.cfg ├── setup.py ├── src └── sdia_python │ ├── __init__.py │ ├── lab1 │ ├── __init__.py │ └── functions.py │ ├── lab2 │ ├── README.md │ ├── __init__.py │ ├── box_window.py │ └── utils.py │ ├── lab3 │ ├── README.md │ └── __init__.py │ ├── lab4 │ └── __init__.py │ ├── lab5 │ └── __init__.py │ └── lab6 │ └── __init__.py └── tests ├── __init__.py ├── lab1 ├── __init__.py ├── test_is_unique.py └── test_triangle_shape.py ├── lab2 ├── __init__.py ├── test_box_window.py └── test_example.py ├── lab3 └── __init__.py ├── lab4 └── __init__.py ├── lab5 └── __init__.py └── lab6 └── __init__.py /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/macos,windows,linux,vscode,python,c++ 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=macos,windows,linux,vscode,python,c++ 4 | 5 | ### C++ ### 6 | # Prerequisites 7 | *.d 8 | 9 | # Compiled Object files 10 | *.slo 11 | *.lo 12 | *.o 13 | *.obj 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Linker files 20 | *.ilk 21 | 22 | # Debugger Files 23 | *.pdb 24 | 25 | # Compiled Dynamic libraries 26 | *.so 27 | *.dylib 28 | *.dll 29 | 30 | # Fortran module files 31 | *.mod 32 | *.smod 33 | 34 | # Compiled Static libraries 35 | *.lai 36 | *.la 37 | *.a 38 | *.lib 39 | 40 | # Executables 41 | *.exe 42 | *.out 43 | *.app 44 | 45 | ### Linux ### 46 | *~ 47 | 48 | # temporary files which can be created if a process still has a handle open of a deleted file 49 | .fuse_hidden* 50 | 51 | # KDE directory preferences 52 | .directory 53 | 54 | # Linux trash folder which might appear on any partition or disk 55 | .Trash-* 56 | 57 | # .nfs files are created when an open file is removed but is still being accessed 58 | .nfs* 59 | 60 | ### macOS ### 61 | # General 62 | .DS_Store 63 | .AppleDouble 64 | .LSOverride 65 | 66 | # Icon must end with two \r 67 | Icon 68 | 69 | 70 | # Thumbnails 71 | ._* 72 | 73 | # Files that might appear in the root of a volume 74 | .DocumentRevisions-V100 75 | .fseventsd 76 | .Spotlight-V100 77 | .TemporaryItems 78 | .Trashes 79 | .VolumeIcon.icns 80 | .com.apple.timemachine.donotpresent 81 | 82 | # Directories potentially created on remote AFP share 83 | .AppleDB 84 | .AppleDesktop 85 | Network Trash Folder 86 | Temporary Items 87 | .apdisk 88 | 89 | ### Python ### 90 | # Byte-compiled / optimized / DLL files 91 | __pycache__/ 92 | *.py[cod] 93 | *$py.class 94 | 95 | # C extensions 96 | 97 | # Distribution / packaging 98 | .Python 99 | build/ 100 | develop-eggs/ 101 | dist/ 102 | downloads/ 103 | eggs/ 104 | .eggs/ 105 | lib/ 106 | lib64/ 107 | parts/ 108 | sdist/ 109 | var/ 110 | wheels/ 111 | pip-wheel-metadata/ 112 | share/python-wheels/ 113 | *.egg-info/ 114 | .installed.cfg 115 | *.egg 116 | MANIFEST 117 | 118 | # PyInstaller 119 | # Usually these files are written by a python script from a template 120 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 121 | *.manifest 122 | *.spec 123 | 124 | # Installer logs 125 | pip-log.txt 126 | pip-delete-this-directory.txt 127 | 128 | # Unit test / coverage reports 129 | htmlcov/ 130 | .tox/ 131 | .nox/ 132 | .coverage 133 | .coverage.* 134 | .cache 135 | nosetests.xml 136 | coverage.xml 137 | *.cover 138 | *.py,cover 139 | .hypothesis/ 140 | .pytest_cache/ 141 | pytestdebug.log 142 | 143 | # Translations 144 | *.mo 145 | *.pot 146 | 147 | # Django stuff: 148 | *.log 149 | local_settings.py 150 | db.sqlite3 151 | db.sqlite3-journal 152 | 153 | # Flask stuff: 154 | instance/ 155 | .webassets-cache 156 | 157 | # Scrapy stuff: 158 | .scrapy 159 | 160 | # Sphinx documentation 161 | docs/_build/ 162 | doc/_build/ 163 | 164 | # PyBuilder 165 | target/ 166 | 167 | # Jupyter Notebook 168 | .ipynb_checkpoints 169 | 170 | # IPython 171 | profile_default/ 172 | ipython_config.py 173 | 174 | # pyenv 175 | .python-version 176 | 177 | # pipenv 178 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 179 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 180 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 181 | # install all needed dependencies. 182 | #Pipfile.lock 183 | 184 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 185 | __pypackages__/ 186 | 187 | # Celery stuff 188 | celerybeat-schedule 189 | celerybeat.pid 190 | 191 | # SageMath parsed files 192 | *.sage.py 193 | 194 | # Environments 195 | .env 196 | .venv 197 | env/ 198 | venv/ 199 | ENV/ 200 | env.bak/ 201 | venv.bak/ 202 | pythonenv* 203 | 204 | # Spyder project settings 205 | .spyderproject 206 | .spyproject 207 | 208 | # Rope project settings 209 | .ropeproject 210 | 211 | # mkdocs documentation 212 | /site 213 | 214 | # mypy 215 | .mypy_cache/ 216 | .dmypy.json 217 | dmypy.json 218 | 219 | # Pyre type checker 220 | .pyre/ 221 | 222 | # pytype static type analyzer 223 | .pytype/ 224 | 225 | # profiling data 226 | .prof 227 | 228 | ### vscode ### 229 | # .vscode/* 230 | # !.vscode/settings.json 231 | # !.vscode/tasks.json 232 | # !.vscode/launch.json 233 | # !.vscode/extensions.json 234 | # *.code-workspace 235 | 236 | ### Windows ### 237 | # Windows thumbnail cache files 238 | Thumbs.db 239 | Thumbs.db:encryptable 240 | ehthumbs.db 241 | ehthumbs_vista.db 242 | 243 | # Dump file 244 | *.stackdump 245 | 246 | # Folder config file 247 | [Dd]esktop.ini 248 | 249 | # Recycle Bin used on file shares 250 | $RECYCLE.BIN/ 251 | 252 | # Windows Installer files 253 | *.cab 254 | *.msi 255 | *.msix 256 | *.msm 257 | *.msp 258 | 259 | # Windows shortcuts 260 | *.lnk 261 | 262 | # End of https://www.toptal.com/developers/gitignore/api/macos,windows,linux,vscode,python,c++ 263 | 264 | 265 | *.ipynb_checkpoints 266 | *.pytest_cache 267 | *.zip 268 | *.DS_Store 269 | *.h5 270 | *.npy 271 | *build 272 | *.c 273 | *.html 274 | __pycache__* 275 | tp2/img* 276 | *.zip 277 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # https://pre-commit.com/ 2 | repos: 3 | # making isort compatible with black 4 | # see https://github.com/PyCQA/isort/issues/1518 5 | - repo: https://github.com/pre-commit/pre-commit-hooks 6 | rev: v3.2.0 7 | hooks: 8 | - id: check-case-conflict 9 | - id: check-docstring-first 10 | - id: check-json 11 | exclude: ^(.vscode/|other/folder/) # weird errors with .vscode/*.json 12 | - id: check-toml 13 | - id: check-yaml 14 | - id: end-of-file-fixer 15 | exclude: ^((.*)\.(ipynb|otherext)) # avoid reformat notebooks everytime 16 | - id: mixed-line-ending 17 | - id: trailing-whitespace 18 | - repo: https://github.com/psf/black 19 | rev: 20.8b1 20 | hooks: 21 | - id: black 22 | - repo: https://github.com/pycqa/isort 23 | rev: 5.5.4 24 | hooks: 25 | - id: isort 26 | args: ["--profile", "black"] 27 | - repo: https://github.com/asottile/blacken-docs 28 | rev: v1.8.0 29 | hooks: 30 | - id: blacken-docs 31 | additional_dependencies: [black==20.8b1] 32 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | // An opinionated list of VS Code snippets used by Guillaume Gautier guilgautier https://guilgautier.github.io/ 2 | { 3 | "recommendations": [ 4 | // General extensions 5 | "VisualStudioExptTeam.vscodeintellicode", 6 | "christian-kohler.path-intellisense", 7 | "CoenraadS.bracket-pair-colorizer-2", 8 | "aaron-bond.better-comments", 9 | "streetsidesoftware.code-spell-checker", 10 | "streetsidesoftware.code-spell-checker-french", 11 | // Github 12 | "eamodio.gitlens", 13 | "donjayamanne.githistory", 14 | "GitHub.vscode-pull-request-github", 15 | // Markdown 16 | "yzhang.markdown-all-in-one", 17 | "DavidAnson.vscode-markdownlint", 18 | // Jupyter Notebook 19 | "ms-toolsai.jupyter", 20 | // Python 21 | "ms-python.python", 22 | "ms-python.vscode-pylance", 23 | "njpwerner.autodocstring", 24 | "KevinRose.vsc-python-indent", 25 | // Restructuredtext 26 | "lextudio.restructuredtext-pack", 27 | // TOML 28 | "tamasfe.even-better-toml", 29 | //Table formatter 30 | "shuworks.vscode-table-formatter", 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Python: Current File", 9 | "type": "python", 10 | "request": "launch", 11 | "program": "${file}", 12 | "console": "integratedTerminal" 13 | }, 14 | { 15 | // https://code.visualstudio.com/docs/python/debugging 16 | "name": "Debug tests", 17 | "type": "python", 18 | "request": "launch", 19 | // avoid purpose when tests/subfolders 20 | // "purpose": [ 21 | // "debug-test" 22 | // ], 23 | "program": "${file}", 24 | "console": "integratedTerminal", 25 | "justMyCode": true, 26 | "env": { 27 | // "PYTEST_ADDOPTS": "--no-cov" // https://stackoverflow.com/a/67185092 28 | } 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // CMD+Maj+P or View->Command palette->Preferences: Open Settings (JSON) 2 | // An opinionated list of VS Code settings used by Guillaume Gautier guilgautier https://guilgautier.github.io/ 3 | { 4 | // Explorer 5 | "explorer.sortOrder": "type", 6 | // Workbench 7 | "workbench.activityBar.visible": true, 8 | "workbench.editorAssociations": { 9 | "*.ipynb": "jupyter-notebook" 10 | }, 11 | "workbench.sideBar.location": "right", 12 | "workbench.statusBar.visible": true, 13 | // Files 14 | "files.insertFinalNewline": true, 15 | "files.trimFinalNewlines": true, 16 | "files.trimTrailingWhitespace": true, 17 | // Editor 18 | "editor.codeActionsOnSave": { 19 | "source.fixAll.markdownlint": true 20 | }, 21 | "editor.detectIndentation": true, 22 | "editor.fontSize": 13, 23 | "editor.formatOnPaste": true, 24 | "editor.formatOnSave": true, 25 | "editor.formatOnType": true, 26 | "editor.insertSpaces": true, 27 | // "editor.minimap.enabled": false, 28 | // "editor.multiCursorModifier": "ctrlCmd", 29 | "editor.renderControlCharacters": true, 30 | "editor.renderWhitespace": "none", 31 | "editor.snippetSuggestions": "top", 32 | "editor.suggestOnTriggerCharacters": true, 33 | "editor.suggestSelection": "first", 34 | "editor.tabSize": 4, 35 | "editor.tokenColorCustomizations": null, 36 | "editor.wordWrap": "bounded", 37 | "editor.quickSuggestions": true, 38 | // Terminal 39 | // "terminal.integrated.inheritEnv": false, 40 | "terminal.integrated.defaultProfile.osx": "zsh", 41 | // "terminal.integrated.fontFamily": "Meslo LG L DZ for Powerline", 42 | // Intellicode 43 | "vsintellicode.modify.editor.suggestSelection": "automaticallyOverrodeDefaultValue", 44 | // Python 45 | "[python]": { 46 | "editor.insertSpaces": true, 47 | "editor.rulers": [ 48 | { 49 | "column": 80, 50 | "color": "#ff00FF" 51 | }, 52 | 100, // <- a ruler in the default color or as customized at column 0 53 | { 54 | "column": 120, 55 | "color": "#ff0000" 56 | }, 57 | ], 58 | "editor.tabSize": 4, 59 | "editor.wordWrapColumn": 80, 60 | }, 61 | "python.languageServer": "Pylance", 62 | // "python.condaPath": "~/opt/anaconda3/bin/anaconda", 63 | // "python.defaultInterpreterPath": "${workspaceFolder}/.venv", 64 | "python.formatting.provider": "black", 65 | "python.linting.enabled": true, 66 | "python.linting.lintOnSave": true, 67 | "python.terminal.activateEnvironment": false, 68 | "autoDocstring.docstringFormat": "google", 69 | "pythonIndent.trimLinesWithOnlyWhitespace": true, 70 | // Markdown 71 | "[markdown]": { 72 | "editor.tabSize": 2, 73 | "editor.quickSuggestions": true, 74 | }, 75 | // RestructuredText 76 | "restructuredtext.confPath": "${workspaceFolder}/docs", 77 | "restructuredtext.languageServer.disabled": true, 78 | // TOML 79 | "[toml]": { 80 | "editor.defaultFormatter": "tamasfe.even-better-toml" 81 | }, 82 | // Spell checker 83 | "cSpell.enabled": true, 84 | "cSpell.language": "en,fr", 85 | "python.testing.pytestArgs": [ 86 | "tests" 87 | ], 88 | "python.testing.unittestEnabled": false, 89 | // "python.testing.nosetestsEnabled": false, 90 | "python.testing.pytestEnabled": true, 91 | } 92 | -------------------------------------------------------------------------------- /.vscode/workspace.code-snippets: -------------------------------------------------------------------------------- 1 | { 2 | "my email": { 3 | "scope": "markdown,python", 4 | "prefix": "myemail", 5 | "body": [ 6 | "bonjour@gmail.com" 7 | ], 8 | "description": "" 9 | }, 10 | } 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Guillaume Gautier 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SDIA - Python 2 | 3 | - [SDIA - Python](#sdia---python) 4 | - [Get the project](#get-the-project) 5 | - [Set up your working environment](#set-up-your-working-environment) 6 | - [Virtual environment](#virtual-environment) 7 | - [Create a virtual environment](#create-a-virtual-environment) 8 | - [Activate a virtual environment](#activate-a-virtual-environment) 9 | - [Deactivate a virtual environment](#deactivate-a-virtual-environment) 10 | - [Install the project in editable mode](#install-the-project-in-editable-mode) 11 | - [Integrated Development Environment - Visual Studio Code](#integrated-development-environment---visual-studio-code) 12 | - [Jupyter Notebooks](#jupyter-notebooks) 13 | - [Launch a Jupyter notebook](#launch-a-jupyter-notebook) 14 | 15 | Python course given to students enrolled in [Parcours DATA - Science des Données et Intelligence Artificielle (SDIA)](http://pierrechainais.ec-lille.fr/Centrale/Option_DAD/Accueil.html) managed by [Pierre Chainais](http://pierrechainais.ec-lille.fr/) at [Ecole Centrale de Lille](https://centralelille.fr/). 16 | 17 | Some material is inspired and/or borrowed from courses previously given by: 18 | 19 | - [Pierre-Antoine Thouvenin](https://pthouvenin.github.io/) at [Ecole Centrale de Lille - Data Science and Artificial Intelligence (SDIA)](http://pierrechainais.ec-lille.fr/Centrale/Option_DAD/Accueil.html), and 20 | - [Guillermo Polito](https://guillep.github.io/) at [Université de Lille - M2 Data Science](https://www.univ-lille.fr/formations/fr-00020709.html). 21 | 22 | ## Get the project 23 | 24 | It is suggested you [Fork](https://github.com/guilgautier/sdia-python/fork) the original repository. 25 | 26 | > A [fork](https://docs.github.com/en/github/collaborating-with-pull-requests/working-with-forks/about-forks) is a copy of a repository that you manage. 27 | > Forks let you make changes to a project without affecting the original repository. 28 | > You can fetch updates from or submit changes to the original repository with [Pull Requests (PRs)](https://github.com/guilgautier/sdia-python/pulls). 29 | 30 | 1. [Fork](https://github.com/guilgautier/sdia-python/fork) 31 | 2. Clone: `git clone https://github.com//sdia-python.git` 32 | 3. [Create a remote](https://docs.github.com/en/github/collaborating-with-pull-requests/working-with-forks/configuring-a-remote-for-a-fork). 33 | 34 | ```bash 35 | cd sdia-python 36 | git remote -v # list the remotes ; an origin remote should be present 37 | git remote add upstream https://github.com/guilgautier/sdia-python.git 38 | git remote -v # remotes origin and upstream should be listed 39 | ``` 40 | 41 | This process allows you to link your local copy of `/sdia-python` with the original repository `guilgautier/sdia-python`, so that you can fetch updates from it, e.g., corrections, new course material, etc. 42 | 43 | [![git remotes](https://www.tomasbeuzen.com/post/git-fork-branch-pull/featured_hud478d74d48d19bfd1c1c03fc398c8033_312322_720x0_resize_lanczos_2.png)](https://www.tomasbeuzen.com/post/git-fork-branch-pull/) 44 | 45 | For example, at the beginning of a practical session, to get the latest course material 46 | 47 | ```bash 48 | git checkout main # select your main branch 49 | git pull upstream main # fetch and merge commits from guilgautier/sdia-python 50 | ``` 51 | 52 | Note: Merge conflicts may occur 😏. We'll see how to handle this **very** common situation. 53 | 54 | ## Set up your working environment 55 | 56 | We will use [`conda`](https://conda.io/projects/conda/en/latest/index.html) to manage Python packages and virtual environments 57 | 58 | ### Virtual environment 59 | 60 | See also [notes/anaconda-vscode.md](./notes/anaconda-vscode.md) 61 | 62 | #### Create a virtual environment 63 | 64 | > A [virtual environment](https://docs.python.org/3/tutorial/venv.html) is a self-contained directory tree that contains a Python installation for a particular version of Python, plus a number of additional packages. 65 | 66 | It is always good practice to work in a virtual environment, isolated from your other Python projects. 67 | 68 | The [environment.yml](./environment.yml) file contains the list of the main packages that will be installed when creating the environment 69 | 70 | ```bash 71 | cd sdia-python 72 | # conda env list 73 | conda env create -f environment.yml 74 | ``` 75 | 76 | #### Activate a virtual environment 77 | 78 | ```bash 79 | # cd sdia-python 80 | conda env list 81 | conda activate sdia-python 82 | # prefix (sdia-python) should appear 83 | ``` 84 | 85 | #### Deactivate a virtual environment 86 | 87 | ```bash 88 | # cd sdia-python 89 | # conda activate sdia-python 90 | conda deactivate 91 | # prefix (sdia-python) should disappear 92 | ``` 93 | 94 | ### Install the project in editable mode 95 | 96 | In order to be able to import your code in various places of your project (source files, test files, noteboooks), like 97 | 98 | ```python 99 | import sdia_python.lab1 100 | from sdia_python.lab1.xxx import yyy 101 | ``` 102 | 103 | > You can [install a project in "editable" or "develop" mode](https://packaging.python.org/guides/distributing-packages-using-setuptools/#working-in-development-mode) while you’re working on it. 104 | > When installed as editable, a project can be edited in-place without reinstallation: 105 | > changes to Python source files in projects installed as editable will be reflected the next time an interpreter process is started. 106 | 107 | Before installing the project in "editable" mode, [make sure to first activate your environment](#activate-a-virtual-environment), 108 | 109 | ```bash 110 | # cd sdia-python 111 | conda activate sdia-python # a (sdia-python) prefix should appear 112 | pip install -e . 113 | ``` 114 | 115 | See also 116 | 117 | - 118 | - 119 | 120 | ## Integrated Development Environment - Visual Studio Code 121 | 122 | [Visual Studio Code (VSCode)](https://code.visualstudio.com/) is recommended to ease your coding experience. 123 | 124 | See the [notes/anaconda-vscode.md](./notes/anaconda-vscode.md) file. 125 | 126 | ## Jupyter Notebooks 127 | 128 | [Jupyter](https://jupyter.org/) notebooks allow you to easily prototype code and showcase your project, see [`notebooks/`](./notebooks/) folder. 129 | 130 | In order to automatically reflect modifications of the source files (located in [`src/`](./src/)) into your notebook, make sure your notebook has the following cell (make it the top cell of your notebook) **and run it!** 131 | 132 | ```bash 133 | %load_ext autoreload 134 | %autoreload 2 135 | ``` 136 | 137 | ### Launch a Jupyter notebook 138 | 139 | - Within VSCode, the [Jupyter extension](https://marketplace.visualstudio.com/items?itemName=ms-toolsai.jupyter) provides a full [Jupyter notebook experience within VSCode](https://code.visualstudio.com/docs/datascience/jupyter-notebooks). 140 | - Simply open a `.ipynb` file located in [`notebooks/`](./notebooks/) 141 | 142 | - From the command line 143 | 144 | ```bash 145 | # cd sdia-python/notebooks 146 | # activate sdia-python 147 | jupyter notebook 148 | ``` 149 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | import os 14 | import sys 15 | 16 | sys.path.insert(0, os.path.abspath(os.path.join("..", "src"))) 17 | 18 | 19 | # -- Project information ----------------------------------------------------- 20 | 21 | project = "sdia-python" 22 | copyright = "2021, Guillaume Gautier" 23 | author = "Guillaume Gautier" 24 | 25 | 26 | # -- General configuration --------------------------------------------------- 27 | 28 | # Add any Sphinx extension module names here, as strings. They can be 29 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 30 | # ones. 31 | extensions = [ 32 | "sphinx.ext.doctest", 33 | "sphinx.ext.autodoc", 34 | "sphinx.ext.viewcode", 35 | "sphinx.ext.mathjax", # LaTeX math rendering 36 | "sphinx.ext.napoleon", 37 | # "sphinxcontrib.bibtex", # Bibliography management, installation required 38 | ] 39 | # "matplotlib.sphinxext.plot_directive" to generate matplotlib plots in the documentation 40 | # see https://matplotlib.org/stable/api/sphinxext_plot_directive_api.html 41 | 42 | 43 | # Add any paths that contain templates here, relative to this directory. 44 | templates_path = ["_templates"] 45 | 46 | # List of patterns, relative to source directory, that match files and 47 | # directories to ignore when looking for source files. 48 | # This pattern also affects html_static_path and html_extra_path. 49 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] 50 | 51 | 52 | # -- Options for HTML output ------------------------------------------------- 53 | 54 | # The theme to use for HTML and HTML Help pages. See the documentation for 55 | # a list of builtin themes. 56 | # 57 | html_theme = "alabaster" 58 | 59 | # Add any paths that contain custom static files (such as style sheets) here, 60 | # relative to this directory. They are copied after the builtin static files, 61 | # so a file named "default.css" will overwrite the builtin "default.css". 62 | html_static_path = ["_static"] 63 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. sdi-python documentation master file, created by 2 | sphinx-quickstart on Wed Sep 1 17:27:45 2021. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to sdi-python's documentation! 7 | ====================================== 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | lab1/index 14 | lab2/index 15 | 16 | Indices and tables 17 | ================== 18 | 19 | * :ref:`genindex` 20 | * :ref:`modindex` 21 | * :ref:`search` 22 | -------------------------------------------------------------------------------- /docs/lab1/index.rst: -------------------------------------------------------------------------------- 1 | ***** 2 | Lab 1 3 | ***** 4 | 5 | .. automodule:: sdia_python.lab1.functions 6 | :members: 7 | :inherited-members: 8 | :show-inheritance: 9 | -------------------------------------------------------------------------------- /docs/lab2/index.rst: -------------------------------------------------------------------------------- 1 | ***** 2 | Lab 2 3 | ***** 4 | 5 | BoxWindow 6 | ========= 7 | 8 | .. automodule:: sdia_python.lab2.box_window 9 | :members: 10 | :inherited-members: 11 | :show-inheritance: 12 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /environment.yml: -------------------------------------------------------------------------------- 1 | name: sdia-python 2 | channels: 3 | - defaults 4 | - conda-forge 5 | - spyder-ide 6 | - plotly 7 | dependencies: 8 | - python=3.8 9 | - numpy 10 | - scipy 11 | - pandas 12 | - matplotlib 13 | - plotly 14 | - networkx 15 | - numba 16 | # Documentation 17 | - sphinx 18 | # Dev 19 | - pre-commit 20 | - pytest 21 | - black 22 | - isort 23 | # Jupyter notebook 24 | - jupyter 25 | - ipykernel 26 | - notebook>=5.3 # support for plotly in notebook 27 | # - ipywidget>=7.5 # support for plotly in notebook 28 | # Package installer 29 | # First try "conda install ", 30 | # Last resort "pip install " 31 | - pip 32 | - pip: 33 | - "" 34 | # Spyder IDE 35 | # - spyder 36 | # - spyder-unittest 37 | # - spyder-notebook 38 | # # Fix lag in spyder MacOS https://github.com/spyder-ide/spyder/issues/14218#issuecomment-729257620 39 | # - pyqt 40 | # - pyqtwebengine 41 | -------------------------------------------------------------------------------- /notebooks/lab1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "source": [ 6 | "# Practical session 1 - Some Python basics\n", 7 | "\n", 8 | "Course: [SDIA-Python](https://github.com/guilgautier/sdia-python)\n", 9 | "\n", 10 | "Dates: 09/21/2021-09/22/2021\n", 11 | "\n", 12 | "Instructor: [Guillaume Gautier](https://guilgautier.github.io/)\n", 13 | "\n", 14 | "Students (pair):\n", 15 | "- [Student 1]([link](https://github.com/username1))\n", 16 | "- [Student 2]([link](https://github.com/username2))" 17 | ], 18 | "metadata": {} 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": null, 23 | "source": [ 24 | "%load_ext autoreload\n", 25 | "%autoreload 2" 26 | ], 27 | "outputs": [], 28 | "metadata": {} 29 | }, 30 | { 31 | "cell_type": "markdown", 32 | "source": [ 33 | "## Documentation\n", 34 | "\n", 35 | "To display the documentation associated to a Python function in your notebook (launched in VSCode), you can either\n", 36 | "- run `?functionname` or `help(my_adder)`\n", 37 | "- place your mouse pointer on the function name\n", 38 | "- write the name of the function and start opening the brackets" 39 | ], 40 | "metadata": {} 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "source": [ 45 | "## Zen of Python\n" 46 | ], 47 | "metadata": {} 48 | }, 49 | { 50 | "cell_type": "code", 51 | "execution_count": null, 52 | "source": [ 53 | "import this" 54 | ], 55 | "outputs": [], 56 | "metadata": {} 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "source": [ 61 | "## Reserved keywords\n" 62 | ], 63 | "metadata": {} 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": null, 68 | "source": [ 69 | "import keyword\n", 70 | "print(keyword.kwlist)" 71 | ], 72 | "outputs": [], 73 | "metadata": {} 74 | }, 75 | { 76 | "cell_type": "markdown", 77 | "source": [ 78 | "## Arithmetic" 79 | ], 80 | "metadata": {} 81 | }, 82 | { 83 | "cell_type": "markdown", 84 | "source": [ 85 | "Compute 4 raised to the power 8" 86 | ], 87 | "metadata": {} 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "source": [ 92 | "Compute the quotient and the remainder of the euclidean division of 17 by 3. " 93 | ], 94 | "metadata": {} 95 | }, 96 | { 97 | "cell_type": "markdown", 98 | "source": [ 99 | "Create two integer variables `a, b` of your choice and swap their content." 100 | ], 101 | "metadata": {} 102 | }, 103 | { 104 | "cell_type": "markdown", 105 | "source": [ 106 | "Modify `a` inplace, so that the new value of `a` is twice its previous value." 107 | ], 108 | "metadata": {} 109 | }, 110 | { 111 | "cell_type": "markdown", 112 | "source": [ 113 | "Define a complex number `z` and print it as\n", 114 | "\n", 115 | "`real=real-part, imag=imaginary-part`" 116 | ], 117 | "metadata": {} 118 | }, 119 | { 120 | "cell_type": "markdown", 121 | "source": [ 122 | "## Strings\n" 123 | ], 124 | "metadata": {} 125 | }, 126 | { 127 | "cell_type": "markdown", 128 | "source": [ 129 | "Propose two ways to define an empty string" 130 | ], 131 | "metadata": {} 132 | }, 133 | { 134 | "cell_type": "markdown", 135 | "source": [ 136 | "Define a string made of the 26 letters of the alphabet (lower case), then\n", 137 | "- What is the 12th letter of the alphabet\n", 138 | "- What are the 10 last letters of the alphabet\n", 139 | "- What are the 5th to the 10th letters of the alphabet\n", 140 | "- Create a new string where the 26 letters are converted to upper case." 141 | ], 142 | "metadata": {} 143 | }, 144 | { 145 | "cell_type": "markdown", 146 | "source": [ 147 | "Extract the first 4 digits of the number `x = 2341324530045968` (answer is `2341`)." 148 | ], 149 | "metadata": {} 150 | }, 151 | { 152 | "cell_type": "markdown", 153 | "source": [ 154 | "## Lists" 155 | ], 156 | "metadata": {} 157 | }, 158 | { 159 | "cell_type": "markdown", 160 | "source": [ 161 | "Propose two ways to define an empty list." 162 | ], 163 | "metadata": {} 164 | }, 165 | { 166 | "cell_type": "markdown", 167 | "source": [ 168 | "Create the list of consecutive integers from 5 to 11." 169 | ], 170 | "metadata": {} 171 | }, 172 | { 173 | "cell_type": "markdown", 174 | "source": [ 175 | "Add `100` to this list." 176 | ], 177 | "metadata": {} 178 | }, 179 | { 180 | "cell_type": "markdown", 181 | "source": [ 182 | "Given the following list, \n", 183 | "Change the `\"sdia\"` to its reverse (`\"aids\"`)." 184 | ], 185 | "metadata": {} 186 | }, 187 | { 188 | "cell_type": "code", 189 | "execution_count": null, 190 | "source": [ 191 | "x = [10, [3, 4], [5, [100, 200, [\"sdia\"]], 23, 11], 1, 7]" 192 | ], 193 | "outputs": [], 194 | "metadata": {} 195 | }, 196 | { 197 | "cell_type": "markdown", 198 | "source": [ 199 | "Given the following list, \n", 200 | "\n", 201 | " 1. extract the first two items\n", 202 | " 2. extract the last two items\n", 203 | " 3. find the index of the first occurence of `9`\n", 204 | " 4. extract the items located at odd indices\n", 205 | " 5. create a new list which corresponds to the reversed version of the originial list\n", 206 | " 6. create a new list where each item of the original list is raised to the power 3" 207 | ], 208 | "metadata": {} 209 | }, 210 | { 211 | "cell_type": "code", 212 | "execution_count": null, 213 | "source": [ 214 | "x = [3, 7, 5, 3, 8, 6, 8, 8, 0, 7, 3, 9, 3, 4, 2, 7, 0, 9, 5, 0, 0, 9, 0, 9, 3, 1, 4, 0, 5, 5, 5, 8, 9, 9, 5, 5, 4, 9, 5, 6, 2, 8, 5, 2, 4, 9, 2, 2, 3, 1]\n" 215 | ], 216 | "outputs": [], 217 | "metadata": {} 218 | }, 219 | { 220 | "cell_type": "markdown", 221 | "source": [ 222 | "## Tuples" 223 | ], 224 | "metadata": {} 225 | }, 226 | { 227 | "cell_type": "markdown", 228 | "source": [ 229 | "\n", 230 | "Propose two ways to define an empty tuple." 231 | ], 232 | "metadata": {} 233 | }, 234 | { 235 | "cell_type": "markdown", 236 | "source": [ 237 | "Given the following tuple\n", 238 | "- try to replace the second item (`4`) to `8`.\n", 239 | "- modify the list so that the second element of the first item is raised to the power 5 " 240 | ], 241 | "metadata": {} 242 | }, 243 | { 244 | "cell_type": "markdown", 245 | "source": [ 246 | "x = ([1, 2, 3], 4)" 247 | ], 248 | "metadata": {} 249 | }, 250 | { 251 | "cell_type": "markdown", 252 | "source": [ 253 | "What is the main difference between a list and a tuple?" 254 | ], 255 | "metadata": {} 256 | }, 257 | { 258 | "cell_type": "markdown", 259 | "source": [ 260 | "## Sets" 261 | ], 262 | "metadata": {} 263 | }, 264 | { 265 | "cell_type": "markdown", 266 | "source": [ 267 | "Create an empty set" 268 | ], 269 | "metadata": {} 270 | }, 271 | { 272 | "cell_type": "markdown", 273 | "source": [ 274 | "Compute the intersection between $A = \\{1, 2, 3\\}$ and $B = \\{2, 4, 5, 6\\}$." 275 | ], 276 | "metadata": {} 277 | }, 278 | { 279 | "cell_type": "markdown", 280 | "source": [ 281 | "From the following set\n", 282 | "- add the numbers 4, 5, 6\n", 283 | "- remove the numbers 1, 2, 3\n", 284 | "- check if the resulting set is contained in `{1, 2, 4, 5, 6, 10}` " 285 | ], 286 | "metadata": {} 287 | }, 288 | { 289 | "cell_type": "code", 290 | "execution_count": null, 291 | "source": [ 292 | "x = {0, 1, 2, 3, 6, 7, 8, 9, 10}" 293 | ], 294 | "outputs": [], 295 | "metadata": {} 296 | }, 297 | { 298 | "cell_type": "markdown", 299 | "source": [ 300 | "## Dictionnaries" 301 | ], 302 | "metadata": {} 303 | }, 304 | { 305 | "cell_type": "markdown", 306 | "source": [ 307 | "Propose two ways to define an empty dictionary" 308 | ], 309 | "metadata": {} 310 | }, 311 | { 312 | "cell_type": "markdown", 313 | "source": [ 314 | "Propose at least 3 ways to define a dictionary with \n", 315 | "- keys `(\"a\", \"b\", \"c\", \"d\")`\n", 316 | "- values `(1, 3, 5 , 7)`" 317 | ], 318 | "metadata": {} 319 | }, 320 | { 321 | "cell_type": "markdown", 322 | "source": [ 323 | "Given the following dictionary, use indexing to get to the word `\"sdia\"`" 324 | ], 325 | "metadata": {} 326 | }, 327 | { 328 | "cell_type": "code", 329 | "execution_count": null, 330 | "source": [ 331 | "d = {\n", 332 | " \"outer\": [\n", 333 | " 1,\n", 334 | " 2,\n", 335 | " 3,\n", 336 | " {\"inner\": [\"this\", \"is\", \"inception\", {\"inner_inner\": [1, 2, 3, \"sdia\"]}]},\n", 337 | " ]\n", 338 | "}" 339 | ], 340 | "outputs": [], 341 | "metadata": {} 342 | }, 343 | { 344 | "cell_type": "markdown", 345 | "source": [ 346 | "From the following dictionary,\n", 347 | "- Create the list of keys\n", 348 | "- Create the list of values\n", 349 | "- Check if the key `\"abc\"` is present, if not, return `123`.\n", 350 | "- Merge the initial dictionary with `{\"e\": -1, 4: True}`" 351 | ], 352 | "metadata": {} 353 | }, 354 | { 355 | "cell_type": "code", 356 | "execution_count": null, 357 | "source": [ 358 | "d1 = dict(zip([(0, 1), \"e\", 1, None], [\"abc\", 4, None, 1 + 2j]))" 359 | ], 360 | "outputs": [], 361 | "metadata": {} 362 | }, 363 | { 364 | "cell_type": "markdown", 365 | "source": [ 366 | "## Conditions" 367 | ], 368 | "metadata": {} 369 | }, 370 | { 371 | "cell_type": "markdown", 372 | "source": [ 373 | "Propose two ways to construct the list of odd values ranging from 0 to 30" 374 | ], 375 | "metadata": {} 376 | }, 377 | { 378 | "cell_type": "markdown", 379 | "source": [ 380 | "From the following list, create another list which contains\n", 381 | "- `\"fiz\"` if the item is a multiple of 5,\n", 382 | "- `\"buz\"` if the item is a multiple of 7,\n", 383 | "- `\"fizbuz\"` if the item is a both a multiple of 5 and 7,\n", 384 | "- the index of the item otherwise." 385 | ], 386 | "metadata": {} 387 | }, 388 | { 389 | "cell_type": "code", 390 | "execution_count": null, 391 | "source": [ 392 | "x = [2, 1, 3, 31, 35, 20, 70, 132, 144, 49]" 393 | ], 394 | "outputs": [], 395 | "metadata": {} 396 | }, 397 | { 398 | "cell_type": "markdown", 399 | "source": [ 400 | "Given a string variable `course`, construct a `if/elif/else` statement that prints:\n", 401 | "- `\"That is very useful!\"` if `course` is `\"maths\"` (any kind of capitalization)\n", 402 | "- `\"That is very useful!\"` if `course` is `\"python\"` (any kind of capitalization)\n", 403 | "- `\"How nice!\"` if `course` is `\"meditation\"` (any kind of capitalization)\n", 404 | "- `\"You're not at Hogwarts\"` if `course` is `\"magic\"` (any kind of capitalization)\n", 405 | "- otherwise `\"What is this COURSE?\"` if `course` is anything else." 406 | ], 407 | "metadata": {} 408 | }, 409 | { 410 | "cell_type": "markdown", 411 | "source": [ 412 | "Given the following variables, create and print the string\n", 413 | "\n", 414 | "``quantity`` ``fruit``(s) cost(s) $``price``\n", 415 | "\n", 416 | "such that\n", 417 | "- there is an `\"s\"` at `\"cost\"` when there is more only one fruit,\n", 418 | "- there is an `\"s\"` at `\"fruit\"` when there is more that one fruit,\n", 419 | "- the price is displayed as ...,xxx,xxx.yy where yy corresponds rounded cents value" 420 | ], 421 | "metadata": {} 422 | }, 423 | { 424 | "cell_type": "code", 425 | "execution_count": null, 426 | "source": [ 427 | "quantity = 1\n", 428 | "fruit = \"avocado\"\n", 429 | "price = 1.8912392e4" 430 | ], 431 | "outputs": [], 432 | "metadata": {} 433 | }, 434 | { 435 | "cell_type": "markdown", 436 | "source": [ 437 | "## Functions\n", 438 | "\n", 439 | "- Create your function in `src/sdia_python/lab1/functions.py` files\n", 440 | "- Import them using `from sdia_python.lab1.functions import MYFUNCTION`" 441 | ], 442 | "metadata": {} 443 | }, 444 | { 445 | "cell_type": "markdown", 446 | "source": [ 447 | "Define the function `is_unique(x)` which takes a list of integers `x` as input and returns `True` if the there is no duplicate items otherwise return `False`." 448 | ], 449 | "metadata": {} 450 | }, 451 | { 452 | "cell_type": "markdown", 453 | "source": [ 454 | "Define a function `triangle_shape(height)`, that returns \n", 455 | "- `\"\"` if `height=0`, \n", 456 | "- otherwise it returns a string that forms a triangle with height prescribed by `height`.\n", 457 | "\n", 458 | "**Examples**\n", 459 | "\n", 460 | "height=1\n", 461 | "```\n", 462 | "x\n", 463 | "```\n", 464 | "\n", 465 | "height=2\n", 466 | "```\n", 467 | " x \n", 468 | "xxx\n", 469 | "```\n", 470 | "\n", 471 | "height=3\n", 472 | "```\n", 473 | " x \n", 474 | " xxx \n", 475 | "xxxxx\n", 476 | "```\n", 477 | "\n", 478 | "height=4\n", 479 | "```\n", 480 | " x \n", 481 | " xxx \n", 482 | " xxxxx \n", 483 | "xxxxxxx\n", 484 | "```\n", 485 | "\n", 486 | "height=5\n", 487 | "```\n", 488 | " x \n", 489 | " xxx \n", 490 | " xxxxx \n", 491 | " xxxxxxx \n", 492 | "xxxxxxxxx\n", 493 | "```\n", 494 | "\n", 495 | "height=6\n", 496 | "```\n", 497 | " x \n", 498 | " xxx \n", 499 | " xxxxx \n", 500 | " xxxxxxx \n", 501 | " xxxxxxxxx \n", 502 | "xxxxxxxxxxx\n", 503 | "```" 504 | ], 505 | "metadata": {} 506 | } 507 | ], 508 | "metadata": { 509 | "orig_nbformat": 4, 510 | "language_info": { 511 | "name": "python", 512 | "version": "3.8.11", 513 | "mimetype": "text/x-python", 514 | "codemirror_mode": { 515 | "name": "ipython", 516 | "version": 3 517 | }, 518 | "pygments_lexer": "ipython3", 519 | "nbconvert_exporter": "python", 520 | "file_extension": ".py" 521 | }, 522 | "kernelspec": { 523 | "name": "python3", 524 | "display_name": "Python 3.8.11 64-bit ('sdia-python': conda)" 525 | }, 526 | "interpreter": { 527 | "hash": "ba6ca9fc42f42968b7c4e3e70d1a500cae409fe585200fde26f7b418fee309bd" 528 | } 529 | }, 530 | "nbformat": 4, 531 | "nbformat_minor": 2 532 | } 533 | -------------------------------------------------------------------------------- /notebooks/lab2.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "source": [ 7 | "%load_ext autoreload\n", 8 | "%autoreload 2" 9 | ], 10 | "outputs": [], 11 | "metadata": {} 12 | } 13 | ], 14 | "metadata": { 15 | "orig_nbformat": 4, 16 | "language_info": { 17 | "name": "python", 18 | "version": "3.9.6", 19 | "mimetype": "text/x-python", 20 | "codemirror_mode": { 21 | "name": "ipython", 22 | "version": 3 23 | }, 24 | "pygments_lexer": "ipython3", 25 | "nbconvert_exporter": "python", 26 | "file_extension": ".py" 27 | }, 28 | "kernelspec": { 29 | "name": "python3", 30 | "display_name": "Python 3.9.6 64-bit ('sdia-python': conda)" 31 | }, 32 | "interpreter": { 33 | "hash": "ba6ca9fc42f42968b7c4e3e70d1a500cae409fe585200fde26f7b418fee309bd" 34 | } 35 | }, 36 | "nbformat": 4, 37 | "nbformat_minor": 2 38 | } -------------------------------------------------------------------------------- /notebooks/lab3.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "source": [ 6 | "# Practical session 3 - Practice with numpy\n", 7 | "\n", 8 | "Course: [SDIA-Python](https://github.com/guilgautier/sdia-python)\n", 9 | "\n", 10 | "Date: 10/06/2021\n", 11 | "\n", 12 | "Instructor: [Guillaume Gautier](https://guilgautier.github.io/)\n", 13 | "\n", 14 | "Students (pair):\n", 15 | "- [Student 1]([link](https://github.com/username1))\n", 16 | "- [Student 2]([link](https://github.com/username2))" 17 | ], 18 | "metadata": {} 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": null, 23 | "source": [ 24 | "%load_ext autoreload\n", 25 | "%autoreload 2\n", 26 | "\n", 27 | "import numpy as np\n", 28 | "from sdia_python.lab2.utils import get_random_number_generator" 29 | ], 30 | "outputs": [], 31 | "metadata": {} 32 | }, 33 | { 34 | "cell_type": "code", 35 | "execution_count": null, 36 | "source": [ 37 | "my_array = np.array([0])\n", 38 | "print(type(my_array))\n", 39 | "dir(np.ndarray)" 40 | ], 41 | "outputs": [], 42 | "metadata": {} 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "source": [ 47 | "Propose at leat 2 ways to create an integer vector of size 100 made of 1s" 48 | ], 49 | "metadata": {} 50 | }, 51 | { 52 | "cell_type": "markdown", 53 | "source": [ 54 | "Create a vector with values ranging from 10 to 49" 55 | ], 56 | "metadata": {} 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "source": [ 61 | "Propose a way to construct the vector $(0.0, 0.2, 0.4, 0.6, 0.8)$" 62 | ], 63 | "metadata": {} 64 | }, 65 | { 66 | "cell_type": "markdown", 67 | "source": [ 68 | "Convert a float array into an integer array in place" 69 | ], 70 | "metadata": {} 71 | }, 72 | { 73 | "cell_type": "markdown", 74 | "source": [ 75 | "Given a boolean array\n", 76 | "\n", 77 | "- return the indices where \n", 78 | "- negate the array inplace? " 79 | ], 80 | "metadata": {} 81 | }, 82 | { 83 | "cell_type": "markdown", 84 | "source": [ 85 | "Given 2 vectors $u, v$, propose at least\n", 86 | "\n", 87 | "- 2 ways to compute the inner product $v^{\\top} u$ (here they must have the same size)\n", 88 | "- 2 ways to compute the outer product matrix $u v^{\\top}$\n", 89 | "- 2 ways to compute the outer sum matrix \"$M = u + v^{\\top}$\", where $M_{ij} = u_i + v_j$" 90 | ], 91 | "metadata": {} 92 | }, 93 | { 94 | "cell_type": "markdown", 95 | "source": [ 96 | "Given the following matrix\n", 97 | "\n", 98 | "$$\n", 99 | "M = \n", 100 | "\\begin{pmatrix}\n", 101 | " 0 & 1 & 2 \\\\\n", 102 | " 3 & 4 & 5 \\\\\n", 103 | " 6 & 7 & 8 \\\\\n", 104 | "\\end{pmatrix}\n", 105 | "$$\n", 106 | "\n", 107 | "- Create $M$ using as a list of lists and access the element in the middle\n", 108 | "- Propose at least 2 ways to create $M$ using numpy and access the element in the middle\n", 109 | "- Swap its first and second row\n", 110 | "- Propose at least 3 ways to extract the submatrix $\\begin{pmatrix}4 & 5 \\\\7 & 8 \\\\\\end{pmatrix}$\n", 111 | "- Propose at least 2 ways to extract the diagonal of $M$\n", 112 | "- Propose at least 2 ways to compute $M^3$\n", 113 | "- Compute $v^{\\top} M$, resp. $M N$ for a vector, resp. a matrix of your choice. \n", 114 | "- Propose 2 ways to \"vectorize\" the matrix, i.e., transform it into\n", 115 | " - $(0, 1, 2, 3, 4, 5, 6, 7, 8)$\n", 116 | " - $(0, 3, 6, 1, 4, 7, 2, 5, 8)$\n", 117 | "- Consider $v = (1, 2 , 3)$, compute the\n", 118 | " - row-wise multiplication of $M$ by $v$ ($M_{i\\cdot}$ is multiplied by $v_i$)\n", 119 | " - column-wise multiplication of $M$ by $v$ ($M_{\\cdot j}$ is multiplied by $v_i$)" 120 | ], 121 | "metadata": {} 122 | }, 123 | { 124 | "cell_type": "markdown", 125 | "source": [ 126 | "Write a function `is_symmetric` that checks whether a given n x n matrix is symmetric, and provide an example" 127 | ], 128 | "metadata": {} 129 | }, 130 | { 131 | "cell_type": "markdown", 132 | "source": [ 133 | "## Random\n", 134 | "\n", 135 | "REQUIREMENT: USE THE FUNCTION `get_random_number_generator` as previously used in Lab 2." 136 | ], 137 | "metadata": {} 138 | }, 139 | { 140 | "cell_type": "markdown", 141 | "source": [ 142 | "Consider the Bernoulli(0.4) distribution\n", 143 | "\n", 144 | "- Propose at least 2 ways to generate n=1000 samples from it\n", 145 | "- Compute the empirical mean and variance" 146 | ], 147 | "metadata": {} 148 | }, 149 | { 150 | "cell_type": "markdown", 151 | "source": [ 152 | "Consider a random matrix of size $50 \\times 100$, filled with i.i.d. standard Gaussian variables, compute\n", 153 | "\n", 154 | "- the absolute value of each entry\n", 155 | "- the sum of each row\n", 156 | "- the sum of each colomn \n", 157 | "- the (euclidean) norm of each row\n", 158 | "- the (euclidean) norm of each column" 159 | ], 160 | "metadata": {} 161 | }, 162 | { 163 | "cell_type": "markdown", 164 | "source": [], 165 | "metadata": {} 166 | } 167 | ], 168 | "metadata": { 169 | "kernelspec": { 170 | "name": "python3", 171 | "display_name": "Python 3.8.11 64-bit ('sdia-python': conda)" 172 | }, 173 | "language_info": { 174 | "codemirror_mode": { 175 | "name": "ipython", 176 | "version": 3 177 | }, 178 | "file_extension": ".py", 179 | "mimetype": "text/x-python", 180 | "name": "python", 181 | "nbconvert_exporter": "python", 182 | "pygments_lexer": "ipython3", 183 | "version": "3.8.11" 184 | }, 185 | "toc": { 186 | "base_numbering": 1, 187 | "nav_menu": {}, 188 | "number_sections": false, 189 | "sideBar": true, 190 | "skip_h1_title": true, 191 | "title_cell": "Lecture Outline", 192 | "title_sidebar": "Contents", 193 | "toc_cell": true, 194 | "toc_position": {}, 195 | "toc_section_display": true, 196 | "toc_window_display": true 197 | }, 198 | "interpreter": { 199 | "hash": "ba6ca9fc42f42968b7c4e3e70d1a500cae409fe585200fde26f7b418fee309bd" 200 | } 201 | }, 202 | "nbformat": 4, 203 | "nbformat_minor": 4 204 | } 205 | -------------------------------------------------------------------------------- /notebooks/lab4.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "source": [ 7 | "%load_ext autoreload\n", 8 | "%autoreload 2" 9 | ], 10 | "outputs": [], 11 | "metadata": {} 12 | } 13 | ], 14 | "metadata": { 15 | "orig_nbformat": 4, 16 | "language_info": { 17 | "name": "python", 18 | "version": "3.9.6", 19 | "mimetype": "text/x-python", 20 | "codemirror_mode": { 21 | "name": "ipython", 22 | "version": 3 23 | }, 24 | "pygments_lexer": "ipython3", 25 | "nbconvert_exporter": "python", 26 | "file_extension": ".py" 27 | }, 28 | "kernelspec": { 29 | "name": "python3", 30 | "display_name": "Python 3.9.6 64-bit ('sdia-python': conda)" 31 | }, 32 | "interpreter": { 33 | "hash": "ba6ca9fc42f42968b7c4e3e70d1a500cae409fe585200fde26f7b418fee309bd" 34 | } 35 | }, 36 | "nbformat": 4, 37 | "nbformat_minor": 2 38 | } -------------------------------------------------------------------------------- /notebooks/lab5.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "source": [ 7 | "%load_ext autoreload\n", 8 | "%autoreload 2" 9 | ], 10 | "outputs": [], 11 | "metadata": {} 12 | } 13 | ], 14 | "metadata": { 15 | "orig_nbformat": 4, 16 | "language_info": { 17 | "name": "python", 18 | "version": "3.9.6", 19 | "mimetype": "text/x-python", 20 | "codemirror_mode": { 21 | "name": "ipython", 22 | "version": 3 23 | }, 24 | "pygments_lexer": "ipython3", 25 | "nbconvert_exporter": "python", 26 | "file_extension": ".py" 27 | }, 28 | "kernelspec": { 29 | "name": "python3", 30 | "display_name": "Python 3.9.6 64-bit ('sdia-python': conda)" 31 | }, 32 | "interpreter": { 33 | "hash": "ba6ca9fc42f42968b7c4e3e70d1a500cae409fe585200fde26f7b418fee309bd" 34 | } 35 | }, 36 | "nbformat": 4, 37 | "nbformat_minor": 2 38 | } -------------------------------------------------------------------------------- /notebooks/lab6.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "source": [ 7 | "%load_ext autoreload\n", 8 | "%autoreload 2" 9 | ], 10 | "outputs": [], 11 | "metadata": {} 12 | } 13 | ], 14 | "metadata": { 15 | "orig_nbformat": 4, 16 | "language_info": { 17 | "name": "python", 18 | "version": "3.9.6", 19 | "mimetype": "text/x-python", 20 | "codemirror_mode": { 21 | "name": "ipython", 22 | "version": 3 23 | }, 24 | "pygments_lexer": "ipython3", 25 | "nbconvert_exporter": "python", 26 | "file_extension": ".py" 27 | }, 28 | "kernelspec": { 29 | "name": "python3", 30 | "display_name": "Python 3.9.6 64-bit ('sdia-python': conda)" 31 | }, 32 | "interpreter": { 33 | "hash": "ba6ca9fc42f42968b7c4e3e70d1a500cae409fe585200fde26f7b418fee309bd" 34 | } 35 | }, 36 | "nbformat": 4, 37 | "nbformat_minor": 2 38 | } -------------------------------------------------------------------------------- /notes/anaconda-vscode.md: -------------------------------------------------------------------------------- 1 | # Define your project environments 2 | 3 | - [Define your project environments](#define-your-project-environments) 4 | - [Requirements](#requirements) 5 | - [Python Virtual environment with conda](#python-virtual-environment-with-conda) 6 | - [Exercise 1](#exercise-1) 7 | - [Integrated Development Environment - VSCode](#integrated-development-environment---vscode) 8 | - [Launch VSCode](#launch-vscode) 9 | - [From Anaconda Navigator](#from-anaconda-navigator) 10 | - [From the command line](#from-the-command-line) 11 | - [Per project configuration](#per-project-configuration) 12 | - [Extensions](#extensions) 13 | - [Exercise 2](#exercise-2) 14 | - [Settings](#settings) 15 | - [Exercise 3](#exercise-3) 16 | - [Snippets](#snippets) 17 | - [Exercise 4](#exercise-4) 18 | - [Version control within VSCode](#version-control-within-vscode) 19 | 20 | ## Requirements 21 | 22 | Install 23 | 24 | - [Anaconda](https://www.anaconda.com/) 25 | - [VSCode](https://code.visualstudio.com/) 26 | 27 | ## Python Virtual environment with conda 28 | 29 | > A [virtual environment](https://docs.python.org/3/tutorial/venv.html) is a self-contained directory tree that contains a Python installation for a particular version of Python, plus a number of additional packages. 30 | 31 | It is always good practice to work in a virtual environment, isolated from your other Python projects. 32 | 33 | In this course, we will use [`conda`](https://docs.conda.io/projects/conda/en/latest/index.html), both as 34 | 35 | - an [environment manager](https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html#) 36 | - a [package manager](https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-pkgs.html). 37 | 38 | See also the [conda cheat sheet](https://docs.conda.io/projects/conda/en/latest/user-guide/cheatsheet.html). 39 | 40 | ### Exercise 1 41 | 42 | - Read the [Getting Started section of the conda documentation](https://docs.conda.io/projects/conda/en/latest/user-guide/getting-started.html) 43 | 44 | In your terminal 45 | 46 | - list the `conda` environments currently available on your machine 47 | 48 | - For the `base` environment 49 | - list the installed packages 50 | - what were the channels used to install the different packages? 51 | 52 | - Create a conda environment called `myenv` with Python 3.8.2 53 | - install `numpy` 54 | - install `matplotlib` using `pip` 55 | - list the installed packages 56 | - export the environment to a cross-platform `myenv.yml` file 57 | - delete the environment `myenv` 58 | 59 | - Recreate the conda environment `myenv` from the previous `myenv.yml` file 60 | - update the Python version to its latest version. 61 | - install `scipy` using the `conda-forge` channel 62 | - export the environment to a cross-platform `myenv2.yml` file 63 | 64 | ## Integrated Development Environment - VSCode 65 | 66 | [Visual Studio Code (VSCode)](https://code.visualstudio.com/) is recommended to ease your coding experience. 67 | 68 | **Important:** Use the [command palette](https://code.visualstudio.com/docs/getstarted/tips-and-tricks#_command-palette) ( `CMD/CRTL + Maj + P` ). 69 | 70 | See also 71 | 72 | - [VSCode setup documentation](https://code.visualstudio.com/docs/setup/setup-overview) 73 | - [guilgautier/vscode-workflow](https://github.com/guilgautier/vscode-workflow) repository 74 | 75 | **Tip:** You may also consider [synchronizing your settings](https://code.visualstudio.com/docs/editor/settings-sync), in order to keep the same setup each time you use VSCode (even from a different machine). 76 | 77 | ### Launch VSCode 78 | 79 | #### From Anaconda Navigator 80 | 81 | Launch [Anaconda Navigator](https://docs.anaconda.com/anaconda/navigator/index.html#:~:text=Anaconda%20Navigator%20is%20a%20desktop,in%20a%20local%20Anaconda%20Repository.) 82 | 83 | - (Windows) Open [Start Menu](https://support.microsoft.com/en-us/windows/open-the-start-menu-4ed57ad7-ed1f-3cc9-c9e4-f329822f5aeb) (Windows key) 84 | - (MacOS) Open [Spotlight](https://support.apple.com/fr-fr/guide/mac-help/mchlp1008/mac) (CMD + Space) 85 | 86 | - Search for and open `Anaconda-Navigator` 87 | 88 | - Click on VSCode->Launch 89 | 90 | #### From the command line 91 | 92 | ```bash 93 | # cd path-to-your-projet 94 | code . # open VSCode and define a workspace from current directory 95 | code README.md # open README.md in VSCode 96 | ``` 97 | 98 | See also 99 | 100 | - [VSCode command line](https://code.visualstudio.com/docs/getstarted/tips-and-tricks#_command-line) 101 | - [code is not recognized as an internal or external command](https://code.visualstudio.com/docs/editor/command-line#_code-is-not-recognized-as-an-internal-or-external-command) 102 | 103 | ### Per project configuration 104 | 105 | The [.vscode](../.vscode) directory, placed at the root of your project workspace, contains a list of suggested extensions together with the corresponding settings, code snippets, etc. 106 | You can share the [.vscode](../.vscode) directory with your collaborator, e.g., using git/GitHub, to make sure you have some common setup. 107 | 108 | Note: This configuration only applies in the current workspace and has precedence over global user settings, see also [Settings](#settings) and [Snippets](#snippets). 109 | 110 | ### Extensions 111 | 112 | All registered extensions are available on [VSCode's Marketplace](https://marketplace.visualstudio.com/vscode). 113 | Extensions can also be installed locally from your VSCode window, see the [documentation](https://code.visualstudio.com/docs/editor/extension-marketplace). 114 | 115 | The [.vscode/extensions.json](../.vscode/extensions.json) file contains a list of suggested extensions that will *greatly* simplify your coding workflow. 116 | 117 | #### Exercise 2 118 | 119 | - Install the extensions listed in [.vscode/extensions.json](../.vscode/extensions.json) 120 | - Activate/Deactivate the `Multiline Comments` setting of the `Better Comments` extension 121 | 122 | ### Settings 123 | 124 | > [VSCode settings](https://code.visualstudio.com/docs/getstarted/settings) You can configure Visual Studio Code to your liking through its various settings. Nearly every part of VSCode's editor, user interface, and functional behavior has options you can modify. 125 | 126 | To do so, you can either define settings 127 | 128 | - Globally: Open the Command Palette ( `CMD/CRTL + Maj + P` ) and type either 129 | - `Open User Settings`, or 130 | - `Open Settings (JSON)`, 131 | - Per project: see [settings.json](../.vscode/settings.json). 132 | 133 | See also [guilgautier/vscode-workflow](https://github.com/guilgautier/vscode-workflow) repository. 134 | 135 | #### Exercise 3 136 | 137 | - Change the location of the VSCode sidebar left <-> right. 138 | 139 | ### Snippets 140 | 141 | > [Code snippets](https://code.visualstudio.com/docs/editor/userdefinedsnippets) are templates that make it easier to enter repeating code patterns, such as loops or conditional-statements. 142 | 143 | Many language-specific [extensions](#extensions) already provide some useful snippets. 144 | While some of them exactly match your needs, some others might be missing or you may not remember how to trigger them. 145 | 146 | For these reasons you may create your own snippets to increase your productivity. 147 | To do so, you can either define snippets 148 | 149 | - Globally: Open the Command Palette ( `CMD/CRTL + Maj + P` ) and type `Configure User Snippets` and choose to create 150 | - language-specific snippets, 151 | - generic snippets that can be triggered in different scopes. 152 | - Per project: see [workspace.code-snippets](../.vscode/workspace.code-snippets) 153 | 154 | See also [guilgautier/vscode-workflow](https://github.com/guilgautier/vscode-workflow) repository. 155 | 156 | #### Exercise 4 157 | 158 | - Create your own `mygithub` snippet and make it available only in Markdown (`.md`) files. 159 | - Create an `forenum` Python snippet, that displays when triggered in Python (`.py`) files 160 | 161 | ```python 162 | for idx, val in enumerate(values): 163 | print(idx, val) 164 | ``` 165 | 166 | ### Version control within VSCode 167 | 168 | All, and more, of what we experimented with `git` from the command line (cf. [`notes/command_line.md`](./command_line.md)) can be achieved within VSCode, using 169 | 170 | - the [VSCode integrated terminal](https://code.visualstudio.com/docs/editor/integrated-terminal) 171 | - the [VSCode version control tool](https://code.visualstudio.com/docs/editor/versioncontrol) 😅 172 | -------------------------------------------------------------------------------- /notes/command-line.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | - [Introduction](#introduction) 4 | - [Command line basics](#command-line-basics) 5 | - [Exercise 1](#exercise-1) 6 | - [Exercise 2](#exercise-2) 7 | 8 | ## Command line basics 9 | 10 | | Unix | Windows | 11 | | :------------------------- | :--------------------------------- | 12 | | `pwd` | `cd` | 13 | | `ls` | `dir` | 14 | | `mkdir folder_name` | - | 15 | | `cd path` | - | 16 | | `cd or cd ~` | `cd \` | 17 | | `touch empty.txt` | `echo $null > empty.txt` | 18 | | `echo hello > file.txt` | - | 19 | | `cp current_path new_path` | - or `xcopy current_path new_path` | 20 | | `mv current_path new_path` | - or `move current_path new_path` | 21 | | `rm path_to_file` | - or `del path_to_file` | 22 | | `rm -r path_to_folder` | `rmdir /s path_to_folder` | 23 | 24 | See also 25 | 26 | ### Exercise 1 27 | 28 | - When you open a terminal: what is your current directory? 29 | - Check if your current directory is empty 30 | - Navigate to the root using relative paths 31 | - Navigate to your home from the root using relative paths 32 | 33 | ### Exercise 2 34 | 35 | - Create a new folder called `sdia-cli` 36 | - Create a file `hello.txt` in the `sdia-cli` folder containing only the `hello` string 37 | - Duplicate the file with some other name, like `hi.txt` 38 | - Move the `hi.txt` file into a new directory called `tmp` 39 | - Duplicate the directory with some other name 40 | -------------------------------------------------------------------------------- /notes/new-project-setup.md: -------------------------------------------------------------------------------- 1 | # Setting up a new Python project 2 | 3 | There is no canonical way: if your search the web, you will find many blogs and tutorials that explain one way of doing, each way has its pros and cons. 4 | Here is another opinionated suggestion, using `conda` as a Python package manager and a virtual environment manager. 5 | 6 | 1. Create a [new GitHub repository](https://github.com/new), 7 | - name it wisely, say `my_python_package`: 8 | - use lowercase and underscores, 9 | - see also the latest [trending Python GitHub repos](https://github.com/trending/python?). 10 | - write a short but meaningful description, 11 | - choose to make it public or private (this can be modified a posteriori) 12 | - initialize it with the following files: 13 | - `README.md`, 14 | - `.gitignore` and select the Python template, 15 | - `License`, for non sensitive projects consider a permissive license like the [MIT License](https://en.wikipedia.org/wiki/MIT_License). 16 | - invite collaborators: Settings/Manage access. 17 | 18 | 2. Clone the repository and navigate into the corresponding folder 19 | 20 | ```bash 21 | cd parent-directory-of-the-project 22 | git clone https://github.com/my_python_package.git 23 | cd my_python_package 24 | ``` 25 | 26 | 3. Define a `conda` virtual environment for your project 27 | - consider naming the environment with the same name as the overall project 28 | - consider using an `environment.yml` file to be shared with your collaborators 29 | 30 | 4. Activate your `conda` virtual environment 31 | 32 | ```bash 33 | # cd my_python_package 34 | conda deactivate 35 | conda activate my_python_package # a (my_python_package) prefix should appear 36 | ``` 37 | 38 | 5. Structure your project files 39 | 40 | ```bash 41 | my_python_package # project name 42 | ├── .gitignore # list of files/folders not to track using git 43 | ├── LICENSE 44 | ├── README.md # front/main page of the project 45 | ├── environment.yml # conda virtual environment file 46 | ├── pyproject.toml # project build and tools configuration 47 | ├── setup.cfg # project meta-data, dependencies and tools configuration 48 | ├── setup.py # useful for editable install with pip < 21.1 49 | ├── src # source files of the project 50 | │ └── my_python_package # package name 51 | │ ├── __init__.py # make the directory a Python package 52 | │ ├── lab1 # sub-package name 53 | │ │ └── __init__.py 54 | │ └── lab2 # sub-package name 55 | │ └── __init__.py 56 | ├── tests # unit-testing 57 | │ ├── __init__.py 58 | │ ├── lab1 59 | │ │ ├── __init__.py 60 | │ │ └── test_example.py 61 | │ └── lab2 62 | │ ├── __init__.py 63 | │ └── test_example.py 64 | ├── docs # documentation generated by sphinx 65 | │ ├── Makefile 66 | │ ├── make.bat 67 | │ ├── conf.py # documentation configuration file 68 | │ ├── index.rst # documentation front page and structure 69 | │ ├── lab1 70 | │ │ └── index.rst 71 | │ └── lab2 72 | │ └── index.rst 73 | ├── notebooks # sugar used at best to showcase your project 74 | │ ├── lab1.ipynb 75 | │ └── lab2.ipynb 76 | ├── .vscode # Visual Studio Code local configuration 77 | │ ├── workspace.code-snippets # custom snippets 78 | │ ├── extensions.json # recommended extensions 79 | │ ├── launch.json # debugging configurations 80 | │ └── settings.json # generic settings 81 | └── notes # general or personal notes 82 | ├── note1.md 83 | └── note2.md 84 | ``` 85 | 86 | 6. Define the project meta-data and dependencies in the [`setup.cfg`](../setup.cfg) file 87 | 88 | 7. Install the project in editable mode 89 | 90 | ```bash 91 | # cd my_python_package 92 | conda activate my_python_package # a (my_python_package) prefix should appear 93 | pip install -e . 94 | ``` 95 | 96 | 8. Start working, see also [`project-workflow.md`](./project-workflow.md). 97 | 98 | ## To go further 99 | 100 | If you're happy with the resulting package templating process, you can think of converting the repository into a 101 | 102 | - [GitHub template repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-template-repository), or a 103 | - [cookiecutter](https://cookiecutter-pypackage.readthedocs.io/en/latest/) package 104 | -------------------------------------------------------------------------------- /notes/packaging.md: -------------------------------------------------------------------------------- 1 | # Packaging 2 | 3 | - [Packaging](#packaging) 4 | - [Restructure the package](#restructure-the-package) 5 | - [Build the package](#build-the-package) 6 | - [Publish the package](#publish-the-package) 7 | - [IMPORTANT NOTE](#important-note) 8 | - [Check your package install with pip](#check-your-package-install-with-pip) 9 | 10 | As mentioned on the [official documentation of `setuptools`](https://setuptools.pypa.io/en/latest/userguide/quickstart.html#resources-on-python-packaging) 11 | > Packaging in Python is hard. Here we provide a list of links for those that want to learn more. 12 | 13 | Nevertheless, the way was already paved for you 14 | 15 | - [`src/`](../src/) structure 16 | - [`setup.cfg`](../setup.cfg), [`pyproject.toml`](../pyproject.toml), [`setup.py`](../setup.py) files 17 | - [`README.md`](../README.md) and [`License`](../LICENSE) files 18 | 19 | However, the project is currently made of the packages `lab1`, `lab2`, ... which can be imported using `from/import labX ...` (when the sdia-python virtual environment is activated). 20 | This may conflict with another course where you may also want to import the corresponding `lab*` files. 21 | 22 | - Wouldn't it be clearer to import them using `from/import sdia_python.labX ...` instead? 23 | - How about we turn the project into a real Python package, so that you can share your project using a command like `pip install your-package-name`? 24 | 25 | See also 26 | 27 | - 28 | - 29 | 30 | ## Restructure the package 31 | 32 | **Your instructor could have done it for you from the beginning, but instead left it as a Python+git+VSCode exercise!** 33 | 34 | 1. **FIRST COMMIT YOUR LAST CHANGES** 35 | 36 | ```bash 37 | git status 38 | git add file1 file2 ... 39 | git commit -m "Write an explicit message" 40 | ``` 41 | 42 | 2. Create a new branch `packaging` 43 | 44 | ```bash 45 | git branch --list 46 | # "*" symbol indicates current working branch 47 | git branch packaging 48 | git switch packaging 49 | # git switch --create packaging 50 | git branch 51 | # same as git branch --list 52 | git log --oneline 53 | ``` 54 | 55 | 3. Move `lab*` folders to a new folder `src/sdia_python` which only contains a blank `__init__.py` file. To do this, 56 | 57 | - use the command line and let `git` follow what you're doing 58 | 59 | ```bash 60 | # cd path-to-your-project 61 | # conda activate sdia-python 62 | ################################# 63 | # MacOS 64 | mkdir src/sdia_python 65 | touch src/sdia_python/__init__.py 66 | git mv src/lab* src/sdia_python 67 | git status 68 | git add src/sdia_python 69 | git status 70 | # Windows 71 | mkdir src\sdia_python 72 | type NUL > src\sdia_python\__init__.py 73 | # create an empty file src\sdia_python\__init__.py 74 | git mv src\lab1 src\sdia_python 75 | git mv src\lab2 src\sdia_python 76 | git mv src\lab3 src\sdia_python 77 | git mv src\lab4 src\sdia_python 78 | git mv src\lab5 src\sdia_python 79 | git mv src\lab6 src\sdia_python 80 | git status 81 | git add src\sdia_python 82 | git status 83 | ################################# 84 | ``` 85 | 86 | 4. Update the package imports: the source files have been moved, so that imports must be updated accordingly (`from/import lab...` -> `from sdia_python.lab...`). From VSCode, you can use `CMD/CTRL + Maj + H` or `CMD/CTRL + Maj + P + Search: Replace in files`, enter the successive "search - replace" pairs in the corresponding cells, remove the current `packaging.md` file from the list and click the "Replace All" button (you might need save the files just modified) 87 | 88 | - from lab - from sdia_python.lab 89 | - import lab - import sdia_python.lab 90 | - .. automodule:: lab - .. automodule:: sdia_python.lab 91 | - src/lab - src/sdia_python/lab 92 | 93 | - Finally, run 94 | 95 | ```bash 96 | git status 97 | git add --update 98 | git status 99 | ``` 100 | 101 | 5. Reinstall the package in **EDITABLE** mode, to update the new paths to the package 102 | 103 | ```bash 104 | # cd path-to-your-project 105 | # conda activate sdia-python 106 | # safer but not mandatory a priori 107 | pip uninstall sdia-python 108 | pip install -e . 109 | ``` 110 | 111 | 6. Check your tests still run and pass against the restructured package 112 | 113 | ```bash 114 | # cd path-to-your-project 115 | # conda activate sdia-python 116 | pytest 117 | ``` 118 | 119 | 7. Check your documentation builds correctly against the restructured package 120 | 121 | ```bash 122 | # cd path-to-your-project 123 | # conda activate sdia-python 124 | sphinx-build -b html docs docs/_build/html 125 | ``` 126 | 127 | 8. Commit your changes, once tests pass and documentation builds 128 | 129 | ```bash 130 | # cd path-to-your-project 131 | # conda activate sdia-python 132 | git status 133 | git add -u 134 | # Moved files should appear in green in the staging area "Changes to be committed:" 135 | # Modified files should appear in red in the "Changes not staged for commit:" 136 | git commit -m "Restructure the package into src/sdia_python, update imports accordingly" 137 | ``` 138 | 139 | 9. If everything works and you're satisfied with this new structure, you can merge your `packaging` branch into your `main` branch 140 | 141 | ```bash 142 | git log --oneline 143 | git switch main 144 | git log --oneline 145 | git merge packaging 146 | git log --oneline 147 | ``` 148 | 149 | ## Build the package 150 | 151 | 0. Install the [PyPA `build` tool](https://pypa-build.readthedocs.io/en/latest/index.html) 152 | 153 | ```bash 154 | # cd path-to-your-project 155 | # conda activate sdia-python 156 | pip install build 157 | ``` 158 | 159 | 1. Build the package 160 | 161 | ```bash 162 | # cd path-to-your-project 163 | # conda activate sdia-python 164 | # MacOS 165 | rm dist/* 166 | python -m build 167 | # Windows 168 | rmdir dist 169 | python -m build 170 | ``` 171 | 172 | ## Publish the package 173 | 174 | 0. `conda install twine` 175 | 1. Create a [TestPyPI account](https://test.pypi.org/account/register/) (consider using the same username as your GitHub username) 176 | 2. Before uploading/publishing your package, make sure that 177 | - the [`your-package-name` isn't already used on TestPyPI](https://test.pypi.org/search/?q=package-name), otherwise you need to consider changing `[metedata] name = sdia-python` in [`setup.cfg`](../setup.cfg), like `sdia-python-username`. 178 | - your `[metedata] version =` in [`setup.cfg`](../setup.cfg) differs from what is already present on TestPyPI 179 | - you may consider setting `version = 0.1.0-alpha.1` 180 | - see also [semantic versioning](https://semver.org/)! 181 | - otherwise 182 | - apply the necessary modifications 183 | - **SAVE YOUR FILE** 184 | - re-[build the package](#build-the-package) 185 | 3. [Upload/publish your package to TestPI](https://packaging.python.org/tutorials/packaging-projects/#uploading-the-distribution-archives) 186 | 187 | ```bash 188 | twine check dist/* 189 | twine upload --repository testpypi dist/* 190 | ``` 191 | 192 | 4. Check the result on 193 | 194 | ### IMPORTANT NOTE 195 | 196 | Recall that your package was previously installed in editable mode (see 4. in [Restructure the package](#restructure-the-package)) under the name `sdia-python` with version `0.1.0` (check the info using `conda list`). 197 | 198 | Hence, the modifications made in [`setup.cfg`](../setup.cfg), namely `name = sdia-python-username` and `version = your-version` introduce semantic conflicts with the current installation. 199 | 200 | Besides, this may in turn lead to conflicts with your partner's version of the [`setup.cfg`](../setup.cfg) file. 201 | 202 | You can consider restoring the file to its previous version 203 | 204 | ```bash 205 | git status 206 | git diff setup.cfg 207 | git restore setup.cfg 208 | ``` 209 | 210 | ## Check your package install with pip 211 | 212 | 0. Create a new environment. 213 | 214 | ```bash 215 | conda deactivate 216 | conda create -n sdia-python-testpypi python=3.8 pip 217 | ``` 218 | 219 | 1. Activate your new environment 220 | - `conda activate sdia-python-testpypi` 221 | 222 | 2. [Install your package from TestPyPI](https://packaging.python.org/guides/using-testpypi/#using-testpypi-with-pip) 223 | - `pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ sdia-python-username` 224 | 225 | 3. `conda list` find the line corresponding to `sdia-python-username` 226 | -------------------------------------------------------------------------------- /notes/project-workflow.md: -------------------------------------------------------------------------------- 1 | # Important steps to follow when working on your project 2 | 3 | 1. Open your favorite shell 4 | - **Windows:** Open Anaconda Prompt (Windows key + Anaconda prompt) 5 | - **MacOS:** Open Terminal (CMD + Space + Terminal) 6 | 7 | 2. Navigate to your project folder 8 | - `cd path-to-your-project`, see also the "Command line basics" section in [command-line.md](./command-line.md#command-line-basics) 9 | 10 | 3. Activate your virtual environment 11 | - Conda, see also "Python Virtual environment with conda" section in [`anaconda-vscode.md`](./anaconda-vscode.md#python-virtual-environment-with-conda) 12 | - `conda deactivate # deactivate current environment, most probably (base)` 13 | - `conda env list # list available environment` 14 | - If your target environment is already available, activate it, e.g., for `sdia-python` 15 | - `conda activate sdia-python # a (sdia-python) should appear` 16 | - Otherwise create a new environment and then activate it 17 | 18 | 4. Make sure your package is installed in editable mode 19 | - run `conda list` then find `your-package-name`, you should see something similar to 20 | 21 | ```bash 22 | your-package-name version-number dev_0 23 | ``` 24 | 25 | - otherwise see the section "Install the project in editable mode" in the main [README.md](../README.md#install-the-project-in-editable-mode) file. 26 | 27 | 5. Open your IDE 28 | - Visual Studio Code 29 | - See "Launch VSCode" section in [`anaconda-vscode.md`](./anaconda-vscode.md#launch-vscode) 30 | - Make sure your ["Python Interpreter"](https://code.visualstudio.com/docs/python/environments#_select-and-activate-an-environment) (CMD/CTRL + Maj + P -> Select interpreter) reflects your virtual environment 31 | - Make sure the ["Integrated Terminal"](https://code.visualstudio.com/docs/editor/integrated-terminal) (View -> Terminal) reflects your virtual environment, otherwise activate it as proposed mentioned above 32 | - **Windows:** make sure you use "Command prompt" and not "PowerShell" 33 | - **MacOS:** use preferably "zsh" 34 | 35 | 6. Run your tests, see the "Run tests" section in the [`tests-documentation.md`](./tests-documentation.md#run-tests) 36 | 37 | ```bash 38 | pytest 39 | ``` 40 | 41 | - ideally all the tests should pass 42 | - otherwise fix them 🔩 43 | 44 | 7. Synchronize your project using git and GitHub 45 | - **Read `git` indications after running a command** 46 | - `git status` 47 | - ideally you would get messages like 48 | - "Your branch is up to date with 'origin/main'." 49 | - "nothing to commit, working tree clean", or 50 | - "nothing added to commit but untracked files present (use "git add" to track)" 51 | - otherwise 52 | - `git add/commit` your local changes 53 | - Get the latest modifs from the GitHub repositories of your choice (yours or your partner's) 54 | - `git pull remote-name main` and solve the potential merge conflicts ☺️ 55 | - Get the latest material from the instructor 56 | - `git pull upstream main` and solve the potential merge conflicts ☺️ 57 | 58 | 8. During your working session 59 | - write/update and run tests each time you create/modify a feature of your code 60 | - commit **OFTEN** 61 | - **when working with notebooks** first **CLEAR OUTPUTS** 62 | - save your files (CMD/CTRL + S), this should format them at the same time 63 | - `git status` 64 | - `git add path-to-file1 path-to-file2` 65 | - `git commit -m "Explicit commit message"` 66 | - synchronize the important changes with your partner when needed 67 | - first `git add/commit` (see above) 68 | - then `git push remote-name main` and **read `git` indications after running a command** 69 | 70 | 9. At the end of your working session 71 | - run your tests, ideally they should all pass, see the "Run tests" section in the [tests-documentation.md](./tests-documentation.md#run-tests) file 72 | - build your documentation, see the "Generate the documentation" section in the [tests-documentation.md](./tests-documentation.md#generate-the-documentation) file 73 | - finally `git add/commit/push` (see above) 74 | 75 | 10. Close your computer, you're good to go, take a break! 76 | -------------------------------------------------------------------------------- /notes/self-evaluation.md: -------------------------------------------------------------------------------- 1 | # Self-evaluation 2 | 3 | Let's review your own work and the work of another duo. 4 | 5 | Be fair, honest, factual and (try to) be objective. 6 | 7 | At the end of this double reviewing process, 8 | 9 | - discuss your reviews with the other duo 10 | - **DO NOT COMMIT THIS FILE** except you really want to 11 | - send this file to me by e-mail 12 | 13 | Happy reviewing. 14 | 15 | ## Your duo 16 | 17 | - name1-name2 18 | - link to repository 19 | 20 | ### Code 0/5 21 | 22 | - Are the `BoxWindow`, `UnitBoxWindow`, `BallWindow`, `UnitBallWindow` defined? 23 | - Are the methods originally listed, now defined? 24 | - Are there new methods defined? How are they used? 25 | - How readable is the code? 26 | - Are most of the operations "vectorized" using numpy? To which extent? 27 | - How original is the code? 28 | 29 | ### Testing - 0/5 30 | 31 | - Do the tests (all) pass? 32 | - Are all functions/methods tested? 33 | - Are the test readable? 34 | - Are the tests meaningful? 35 | 36 | ### Documentation - 0/5 37 | 38 | - Does the documentation build? 39 | - Clarity/quality of the docstrings 40 | - Syntax 41 | - Consistency 42 | - Potential examples or doctests are provided 43 | - ... 44 | - Does the documentation look nice? (this is more subjective) 45 | 46 | ### Packaging 47 | 48 | See [packaging.md](.packaging.md) 49 | 50 | [BONUS] 51 | 52 | - Can the package be found on TestPyPI? 53 | - write the link here 54 | - Does it install in a new environment? 55 | 56 | ## Review another duo 57 | 58 | - name1-name2 59 | - link to repository 60 | 61 | 0. Commit your last changes 62 | 1. Select an other duo (see the list below) 63 | 2. Copy paste the corresponding snippet of code (assuming you've followed the steps mentioned in [README.md](../README.md#get-the-project). 64 | - This will successively 65 | - create a new branch `name1-name2` from the initial commit with id `2240f62...` of the project 66 | - add a new remote `name1-name2` targeting the other duo's repository 67 | - pull their latest changes babe-fremerye will then be pulled from the associated remote 68 | 3. Start reviewing their work based on the same criteria you used to self-evaluate your duo 69 | 70 | ```language 71 | # Aloïs Louis 72 | git checkout -b babe-fremerye 2240f62 73 | git branch 74 | git log --oneline 75 | git remote add babe-fremerye https://github.com/AloisBABE/sdia-python.git 76 | git remote -v 77 | git pull babe-fremerye main 78 | git log --oneline 79 | 80 | # Thomas Leo 81 | git checkout -b besnier-beuque 2240f62 82 | git branch 83 | git log --oneline 84 | git remote add besnier-beuque https://github.com/tbesnier/sdia-python.git 85 | git remote -v 86 | git pull besnier-beuque main 87 | git log --oneline 88 | 89 | # Hamza Oussama 90 | git checkout -b jelloul-jourairi 2240f62 91 | git branch 92 | git log --oneline 93 | git remote add jelloul-jourairi https://github.com/jouraOuss/sdia-python.git 94 | git remote -v 95 | git pull jelloul-jourairi main 96 | git log --oneline 97 | 98 | # Ayoub Zakaria 99 | git checkout -b magga-oussalem 2240f62 100 | git branch 101 | git log --oneline 102 | git remote add magga-oussalem https://github.com/02ayoub02/sdia-python.git 103 | git remote -v 104 | git pull magga-oussalem main 105 | git log --oneline 106 | 107 | # Benjamin Aurélien 108 | git checkout -b cohen-orgiazzi 2240f62 109 | git branch 110 | git log --oneline 111 | git remote add cohen-orgiazzi https://github.com/aurelienO/sdia-python.git>e 112 | git remote -v 113 | git pull cohen-orgiazzi main 114 | git log --oneline 115 | 116 | # Salim Amine 117 | git checkout -b kabiri-ait_lemqeddem 2240f62 118 | git branch 119 | git log --oneline 120 | git remote add kabiri-ait_lemqeddem https://github.com/KsalimK/sdia-python.git 121 | git remote -v 122 | git pull kabiri-ait_lemqeddem main 123 | git log --oneline 124 | 125 | # Aurian Georges 126 | git checkout -b le_bellier-quelennec 2240f62 127 | git branch 128 | git log --oneline 129 | git remote add le_bellier-quelennec https://github.com/gle-bellier/sdia-python.git 130 | git remote -v 131 | git pull le_bellier-quelennec main 132 | git log --oneline 133 | 134 | # Emilie Hadrien 135 | git checkout -b salem-salem 2240f62 136 | git branch 137 | git log --oneline 138 | git remote add salem-salem https://github.com/SnowHawkeye/sdia-python.git 139 | git remote -v 140 | git pull salem-salem main 141 | git log --oneline 142 | 143 | # Rémy Virgile 144 | git checkout -b descarpentries-valiau 2240f62 145 | git branch 146 | git log --oneline 147 | git remote add descarpentries-valiau https://github.com/VirgileValiau/sdia-python.git 148 | git remote -v 149 | git pull descarpentries-valiau main 150 | git log --oneline 151 | 152 | # Capucine Thomas 153 | git checkout -b garcon-waldura 2240f62 154 | git branch 155 | git log --oneline 156 | git remote add garcon-waldura https://github.com/CapucineGARCON/sdia-python.git 157 | git remote -v 158 | git pull garcon-waldura main 159 | git log --oneline 160 | 161 | # Anna Loan 162 | git checkout -b marizy-sarazin 2240f62 163 | git branch 164 | git log --oneline 165 | git remote add marizy-sarazin https://github.com/AnnaMarizy/sdia-python.git 166 | git remote -v 167 | git pull marizy-sarazin main 168 | git log --oneline 169 | 170 | # Justine Emilie 171 | git checkout -b bourgain-yip 2240f62 172 | git branch 173 | git log --oneline 174 | git remote add bourgain-yip https://github.com/JustineBrgn/sdia-python.git 175 | git remote -v 176 | git pull bourgain-yip main 177 | git log --oneline 178 | ``` 179 | -------------------------------------------------------------------------------- /notes/tests-documentation.md: -------------------------------------------------------------------------------- 1 | # Tests and documentation 2 | 3 | ## Tests 4 | 5 | > The [`pytest`](https://docs.pytest.org/en/6.2.x/) framework makes it easy to write small tests, yet scales to support complex functional testing. 6 | 7 | It is **very important** to write and run unit tests, to make sure your code works (at least) as expected both for you as you develop but also for other users. 8 | 9 | ### Install testing dependencies 10 | 11 | In this project, 12 | 13 | - `pytest` is listed as a development dependency, see [`[options.extras_require]` section of the `setup.cfg`](../setup.cfg) file, 14 | 15 | ```bash 16 | # cd path-to-your-project 17 | # conda activate sdia-python 18 | pip install -e ".[dev]" 19 | ``` 20 | 21 | The configuration of `pytest` is defined in the [`[tool.pytest.ini_options]` section of the `pyproject.toml` file](https://docs.pytest.org/en/latest/reference/customize.html#pyproject-toml). 22 | 23 | ### Run tests 24 | 25 | Unit tests of the package are declared in [`tests/labX/test_*.py`](../tests/) files as `test_*` functions with a simple `assert` statement, 26 | 27 | Run the package test suite with 28 | 29 | ```bash 30 | # cd path-to-your-project 31 | # conda activate sdia-python 32 | pytest # run all tests discovered by pytest 33 | # run all tests from tests/ folder 34 | pytest tests/ 35 | # run all tests from all files contained in folder tests/lab1/ 36 | pytest tests/lab1/ 37 | # run all tests from file tests/lab1/tests_is_unique.py 38 | pytest tests/lab1/test_is_unique.py 39 | # run specific test called "test_is_unique" from file tests/lab1/tests_is_unique.py 40 | pytest tests/lab1/test_is_unique.py::test_is_unique 41 | ``` 42 | 43 | ### Exercise 1 44 | 45 | Test your code from `lab1` and make sure they all pass. 46 | 47 | ### Write tests in the documentation 48 | 49 | See the [Doctests](#doctests) 50 | 51 | ## Documentation 52 | 53 | > [Sphinx](https://www.sphinx-doc.org/en/master/index.html) is a tool that makes it easy to create intelligent and beautiful documentation. 54 | 55 | Sphinx is in charge of building the documentation and generating HTML output, but also PDF, epub, ... 56 | 57 | Documentation is an **essential** part of your project; you must take some time to document you project properly. 58 | 59 | See also: 60 | 61 | - [sphinx documentation](https://www.sphinx-doc.org/en/master/usage/configuration.html) 62 | 63 | ### Docstrings 64 | 65 | [Documenting Python code](https://realpython.com/documenting-python-code/) is **key** to your project. 66 | 67 | **You must take some time to document your functions, classes, etc.** 68 | 69 | In this project, we suggest to use 70 | 71 | - the ["Python Docstring Generator" extension](https://marketplace.visualstudio.com/items?itemName=njpwerner.autodocstring), see the [`.vscode/extensions.json`](../.vscode/extensions.json) file, 72 | - the Google docstring format as defined at `"autoDocstring.docstringFormat": "google"` in the [`.vscode/settings.json`](../.vscode/settings.json) file. 73 | - note that the `"sphinx.ext.napoleon"` is required to support google and numpy docstring style as defined in the [`docs/conf.py`](../docs/conf.py) file. 74 | 75 | See also: 76 | 77 | - [docstrings conventions](https://www.python.org/dev/peps/pep-0257/) 78 | 79 | ### Install documentation dependencies 80 | 81 | Documentation dependencies are listed as in [`[options.extras_require]` section of the `setup.cfg`](../setup.cfg) file, 82 | 83 | ```bash 84 | # cd path-to-your-project 85 | # conda activate sdia-python 86 | pip install ".[docs]" 87 | ``` 88 | 89 | ### Generate the documentation 90 | 91 | The source files of the documentation are simply `.rst` ([reStructuredText](https://docutils.sourceforge.io/rst.html)) or `.md` (Markdown) files. 92 | However we suggest using reST markup to keep the same syntax and format as used for writing [Python docstings](https://devguide.python.org/documenting/). 93 | 94 | The documentation is configured in the [`docs/conf.py`](../docs/conf.py) file. 95 | 96 | To generate the documentation locally, i.e., on your machine, you can either use 97 | 98 | ```bash 99 | # cd path-to-your-project 100 | # conda activate sdia-python 101 | sphinx-build -b html docs docs/_build/html 102 | ``` 103 | 104 | Then, open the file [docs/_build/html/index.html](../docs/_build/html/index.html) in your favorite browser. 105 | 106 | **Note:** 107 | 108 | - Any change made in the source `.py` files or the [`docs/conf.py`](../docs/conf.py) file require rebuilding the documentation. 109 | 110 | #### Doctests 111 | 112 | **Provided you use the `sphinx.ext.doctest` extension in your [`docs/conf.py`](../docs/conf.py) file**. 113 | 114 | Doctests, i.e., tests written in the docstrings, can be used to test and showcase your Python object/function etc. 115 | For an example, see the `triangle_shape` function docstring in the [lab1/functions.py](../src/sdia_python/lab1/functions.py) file. 116 | 117 | To run the doctests use 118 | 119 | ```bash 120 | make --directory=docs/ doctest 121 | ``` 122 | 123 | ### Exercise 2 124 | 125 | - Edit the metadata of the package defined in [`docs/conf.py`](../docs/conf.py) 126 | - Write good docstrings your code from `lab1`, 127 | - Generate the corresponding documentation 128 | - [BONUS] customize the documentation with some new sections, LaTeX, etc. 129 | -------------------------------------------------------------------------------- /notes/to-go-further.md: -------------------------------------------------------------------------------- 1 | # To go further 2 | 3 | A list of topics and links to resources that may help you learn and improve. 4 | 5 | In particular, I find [Real Python](https://realpython.com/) a great (mostly free) and high quality place to learn new Python stuff. 6 | 7 | ## Run Python scripts 8 | 9 | - [Real Python tutorial](https://realpython.com/run-python-scripts/) 10 | 11 | Simply run `python file.py` 12 | 13 | ```python 14 | # file.py 15 | 16 | 17 | def addition(x, y): 18 | return x 19 | 20 | 21 | def main(): 22 | x, y = 1, 2 23 | result = addition(x, y) 24 | print(result) 25 | 26 | 27 | if __name__ == "__main__": 28 | main() 29 | ``` 30 | 31 | ## Run tests using VSCode 32 | 33 | See the [Testing](https://code.visualstudio.com/docs/python/testing) section of the VSCode documentation. 34 | 35 | ## Debug Python code using VSCode 36 | 37 | The configuration file [.vscode/launch.json](.vscode/launch.json) contains two configurations for debugging 38 | 39 | 1. Python generic 40 | 2. Python test files 41 | 42 | For more details, check out the documentation 43 | 44 | - [Debugging](https://code.visualstudio.com/docs/python/debugging), 45 | - [Debug Tests](https://code.visualstudio.com/docs/python/testing#_debug-tests). 46 | 47 | ## Play with paths 48 | 49 | Use [`pathlib`](https://docs.python.org/3/library/pathlib.html) 50 | 51 | - [Real Python tutorial](https://realpython.com/python-pathlib/) 52 | 53 | ## Data structures 54 | 55 | - [Real Python tutorial](https://realpython.com/python-data-structures/) 56 | 57 | ### Numpy arrays 58 | 59 | - [`numpy` official documentation](https://numpy.org/learn/) 60 | - [Real Python tutorial](https://realpython.com/numpy-array-programming/) 61 | 62 | ### Pandas DataFrames 63 | 64 | - [`pandas` official documentation](https://pandas.pydata.org/pandas-docs/stable/getting_started/index.html#) 65 | - [Real Python tutorial](https://realpython.com/pandas-dataframe/) 66 | 67 | ## Plotting 68 | 69 | [`matplotlib`](https://matplotlib.org/stable/tutorials/index.html) is the main tool on which many other tools are built on, like 70 | 71 | - [`pandas` visualization](https://pandas.pydata.org/pandas-docs/stable/user_guide/visualization.html) 72 | - [`seaborn`](https://seaborn.pydata.org/) 73 | 74 | ### Tip for matplotlib users 75 | 76 | To make consistent plots (size/font of labels/ticks, width of lines/points) consider using a [`my_style.mplstyle`](https://matplotlib.org/stable/tutorials/introductory/customizing.html) file and import it in your `.py` file or your notebook ; see also [this concise tutorial](https://towardsdatascience.com/how-to-create-and-use-custom-matplotlib-style-sheet-9393f498063). 77 | 78 | ### See also 79 | 80 | - [`plotnine`](https://plotnine.readthedocs.io/en/stable/) 81 | - [`plotly`](https://plotly.com/python/) 82 | - [`bokeh`](https://bokeh.org/) 83 | 84 | ## Performance 85 | 86 | ### Timing 87 | 88 | - [`timeit`](https://docs.python.org/3/library/timeit.html) 89 | - [Real Python tutorial](https://realpython.com/python-timer/#python-timers) 90 | 91 | #### Anywhere 92 | 93 | [`timeit`](https://docs.python.org/3/library/timeit.html) 94 | 95 | ```python 96 | import timeit 97 | 98 | setup_code = """ 99 | from sdia_python.lab1.functions import is_unique 100 | x = [1, 2, 3] 101 | """ 102 | 103 | main_code = """ 104 | is_unique(x) 105 | """ 106 | 107 | print(timeit.timeit(stmt=main_code, setup=setup_code, number=10)) 108 | print(timeit.repeat(stmt=main_code, setup=setup_code, number=10, repeat=5)) 109 | ``` 110 | 111 | #### In your notebook 112 | 113 | See the [IPython documentation](https://ipython.readthedocs.io/en/stable/interactive/magics.html?highlight=timeit#cell-magics) 114 | 115 | - inline `%timeit code-to-time` 116 | - in cell 117 | 118 | ```bash 119 | %%timeit 120 | code-to-time 121 | ``` 122 | 123 | ### Profiling 124 | 125 | > A [profile](https://docs.python.org/3/library/profile.html#module-cProfile) is a set of statistics that describes how often and for how long various parts of the program executed 126 | 127 | It will help you identify the bottlenecks in your code, so that you can focus on them to improve the performance of your code. 128 | 129 | ### Multiprocessing 130 | 131 | - [`multiprocessing`](https://docs.python.org/3/library/multiprocessing.html) 132 | - [Machine Learning Plus tutorial](tps://www.machinelearningplus.com/python/parallel-processing-python/) 133 | -------------------------------------------------------------------------------- /notes/version-control.md: -------------------------------------------------------------------------------- 1 | # Version Control System - GIT and GitHub 2 | 3 | ## Install git 4 | 5 | Check if git is already installed 6 | 7 | ```bash 8 | git --version 9 | ``` 10 | 11 | If not, install it 12 | 13 | - OSX 14 | - [install homebrew](https://brew.sh/), then 15 | - `brew install git` 16 | - Linux 17 | - `sudo apt-get install git` 18 | - Windows 19 | - [Download and install Git for Windows](https://git-scm.com/download/win) 20 | 21 | Check if git installed properly 22 | 23 | ```bash 24 | git --version 25 | ``` 26 | 27 | ## Create a GitHub account 28 | 29 | [GitHub](https://github.com/signup?source=login) 30 | 31 | ## Exercise 3 32 | 33 | First few steps with [git](https://git-scm.com/) and [GitHub](https://github.com), using the command line interface. 34 | 35 | ### Online 36 | 37 | - Create a new **blank** (no README, License, .gitignore files, etc.) GitHub repository called `sdia-git`. 38 | 39 | ### On your machine 40 | 41 | - Create a new folder called `sdia-git` 42 | - Create a file `README.md` in the `sdia-git` folder containing at least the `# sdia-git` string at the top 43 | - Run `git init` in the `sdia-git` folder 44 | - Run successively and observe the output of the following commands 45 | - `git status` 46 | - `git add README.md` 47 | - `git status` 48 | - `git commit -m "first commit"` 49 | - `git status` 50 | - `git log` 51 | - `git branch -M main` 52 | - `git remote add origin https://github.com//sdia-git.git>` 53 | - `git push -u origin main` 54 | 55 | ### Back online 56 | 57 | - Delete your `sdia-git` repository 58 | - Settings 59 | - Danger Zone 60 | - Delete this repository 61 | - Create a new `sdia-git` repository, but this time, 62 | - add README, License and .gitignore files. 63 | 64 | ### Back to your machine 65 | 66 | - Clone your new your `sdia-git` repository 67 | 68 | ```bash 69 | cd parent_directory_of_your_project 70 | git clone https://github.com//sdia-git.git 71 | ``` 72 | 73 | ## BONUSES 74 | 75 | - Customize the `README.md` file of your `sdia-git` repository with some [Mardown markup](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) 76 | - Register for a [Student Developer Pack](https://education.github.com/pack) 77 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools >= 40.9.0", "wheel"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [tool.pytest.ini_options] 6 | # poetry run pytest 7 | minversion = "6.0" 8 | addopts = "-ra -q -vv" 9 | testpaths = ["tests"] 10 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | # https://setuptools.readthedocs.io/en/latest/userguide/declarative_config.html#declarative-config 2 | 3 | [metadata] 4 | name = sdia-python 5 | version = 0.1.0 6 | url = https://github.com/guilgautier/sdia-python 7 | download_url = https://github.com/guilgautier/sdia-python 8 | project_urls = 9 | Documentation = https://github.com/guilgautier/sdia-python 10 | Source = https://github.com/guilgautier/sdia-python 11 | author = Guillaume Gautier 12 | author_email = guillaume.gautier@univ-lille.fr 13 | maintainer = Guillaume Gautier 14 | maintainer_email = guillaume.gautier@univ-lille.fr 15 | # https://pypi.org/classifiers/ 16 | classifiers = 17 | Intended Audience :: Education 18 | Intended Audience :: Science/Research 19 | License :: OSI Approved :: MIT License 20 | Natural Language :: English 21 | Natural Language :: French 22 | Programming Language :: Python :: 3.8 23 | Programming Language :: Python :: 3.9 24 | Topic :: Scientific/Engineering :: Mathematics 25 | Topic :: Scientific/Engineering :: Artificial Intelligence 26 | # license = 27 | license_files = file: LICENSE 28 | description = Python practical sessions G3 - SDIA at Centrale Lille 29 | long_description = file: README.md 30 | long_description_content_type = text/markdown 31 | keywords = Python, SDIA, Centrale Lille 32 | # platforms = 33 | # provides = 34 | # requires = 35 | # obsoletes = 36 | 37 | 38 | [options] 39 | # zip_safe = 40 | # setup_requires = 41 | install_requires = 42 | numpy 43 | scipy 44 | pandas 45 | matplotlib 46 | networkx 47 | numba 48 | 49 | # extras_require see [options.extras_require] 50 | python_requires = >=3.8 51 | # entry_points = 52 | # scripts = 53 | # eager_resources = 54 | # dependency_links = 55 | # tests_require = 56 | # include_package_data = 57 | packages = find: 58 | package_dir = 59 | =src 60 | # namespace_packages = 61 | # py_modules = 62 | # data_files = 63 | 64 | [options.packages.find] 65 | where = src 66 | # include = 67 | exclude = tests 68 | 69 | [options.extras_require] 70 | # MacOS pip install -e ".[notebook,docs,dev]" 71 | # Windows pip install -e .[notebook,docs,dev] 72 | # Linux idk, one of the two options above 73 | notebook = 74 | jupyter 75 | ipykernel 76 | docs = 77 | sphinx 78 | dev = 79 | pre-commit 80 | pytest 81 | black 82 | isort 83 | 84 | # [options.package_data] 85 | 86 | # [options.exclude_package_data 87 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # From pip >= 21.1, setup.cfg suffices: setup.py is not mandatory https://pip.pypa.io/en/stable/news/#v21-1 2 | # For pip < 21.1, here is a shim that makes an editable install possible: 3 | # pip install -e . 4 | 5 | import setuptools 6 | 7 | if __name__ == "__main__": 8 | setuptools.setup() 9 | -------------------------------------------------------------------------------- /src/sdia_python/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guilgautier/sdia-python/b48e410a50c25305efe7c8bc6a7236e5f3803c94/src/sdia_python/__init__.py -------------------------------------------------------------------------------- /src/sdia_python/lab1/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guilgautier/sdia-python/b48e410a50c25305efe7c8bc6a7236e5f3803c94/src/sdia_python/lab1/__init__.py -------------------------------------------------------------------------------- /src/sdia_python/lab1/functions.py: -------------------------------------------------------------------------------- 1 | def is_unique(x): 2 | """Check that ``x`` has no duplicate elements. 3 | 4 | Args: 5 | x (list): elements to be compared. 6 | 7 | Returns: 8 | bool: True if ``x`` has duplicate elements, otherwise False 9 | """ 10 | return len(set(x)) == len(x) 11 | 12 | 13 | def triangle_shape(n, fillchar="x", spacechar=" "): 14 | """Return a string made of ``fillchar`` and ``spacechar``representing a triangle shape of height ``n``. 15 | 16 | For n=0, return ``""``. 17 | 18 | .. testcode:: 19 | 20 | from sdia_python.lab1.functions import triangle_shape 21 | print(triangle_shape(6, fillchar="x", spacechar="_")) 22 | 23 | .. testoutput:: 24 | 25 | _____x_____ 26 | ____xxx____ 27 | ___xxxxx___ 28 | __xxxxxxx__ 29 | _xxxxxxxxx_ 30 | xxxxxxxxxxx 31 | 32 | Args: 33 | n (int): height of the triangle. 34 | fillchar (str, optional): Defaults to "x". 35 | spacechar (str, optional): Defaults to " ". 36 | 37 | Returns: 38 | str: string representation of the triangle. 39 | """ 40 | width = 2 * n - 1 41 | return "\n".join( 42 | (fillchar * (2 * i + 1)).center(width, spacechar) for i in range(n) 43 | ) 44 | -------------------------------------------------------------------------------- /src/sdia_python/lab2/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Python classes 3 | 4 | See also 5 | 6 | - [Real Python - Class tutorial](https://realpython.com/python3-object-oriented-programming/) 7 | - [Official Python - Class tutorial](https://docs.python.org/fr/3/tutorial/classes.html) 8 | 9 | ## BoxWindow class 10 | 11 | - Edit the class `BoxWindow` in [src/sdia_python/lab2/box_window.py](./box_window.py) to make it work in any dimension (you may start with a low dimensional implementation). 12 | - Run the tests from [`tests/lab2/`](../../tests/lab2) 13 | - Complete the class body 14 | - write the docstrings 15 | - make sure the current tests pass 16 | - Add new methods of your choice like `center`, etc. 17 | - Write new tests that test various use cases of the different methods 18 | - Create the counterpart `BallWindow` class that works at least in 1D and 2D 19 | 20 | - [Bonus] Estimate the value of `pi` using [rejection sampling](https://en.wikipedia.org/wiki/Rejection_sampling) 21 | -------------------------------------------------------------------------------- /src/sdia_python/lab2/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guilgautier/sdia-python/b48e410a50c25305efe7c8bc6a7236e5f3803c94/src/sdia_python/lab2/__init__.py -------------------------------------------------------------------------------- /src/sdia_python/lab2/box_window.py: -------------------------------------------------------------------------------- 1 | from sdia_python.lab2.utils import get_random_number_generator 2 | 3 | 4 | class BoxWindow: 5 | """[summary]""" 6 | 7 | def __init__(self, args): 8 | """[summary] 9 | 10 | Args: 11 | args ([type]): [description] 12 | """ 13 | self.bounds = None 14 | 15 | def __str__(self): 16 | r"""BoxWindow: :math:`[a_1, b_1] \times [a_2, b_2] \times \cdots` 17 | 18 | Returns: 19 | [type]: [description] 20 | """ 21 | return "" 22 | 23 | def __len__(self): 24 | return 25 | 26 | def __contains__(self, args): 27 | return True or False 28 | 29 | def dimension(self): 30 | """[summary]""" 31 | return 32 | 33 | def volume(self): 34 | """[summary]""" 35 | return 36 | 37 | def indicator_function(self, args): 38 | """[summary] 39 | 40 | Args: 41 | args ([type]): [description] 42 | """ 43 | return 44 | 45 | def rand(self, n=1, rng=None): 46 | """Generate ``n`` points uniformly at random inside the :py:class:`BoxWindow`. 47 | 48 | Args: 49 | n (int, optional): [description]. Defaults to 1. 50 | rng ([type], optional): [description]. Defaults to None. 51 | """ 52 | rng = get_random_number_generator(rng) 53 | return 54 | 55 | 56 | class UnitBoxWindow(BoxWindow): 57 | def __init__(self, center, dimension): 58 | """[summary] 59 | 60 | Args: 61 | dimension ([type]): [description] 62 | center ([type], optional): [description]. Defaults to None. 63 | """ 64 | super(UnitBoxWindow, self).__init__(bounds) 65 | -------------------------------------------------------------------------------- /src/sdia_python/lab2/utils.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def get_random_number_generator(seed): 5 | """Turn seed into a np.random.Generator instance.""" 6 | return np.random.default_rng(seed) 7 | -------------------------------------------------------------------------------- /src/sdia_python/lab3/README.md: -------------------------------------------------------------------------------- 1 | # Lab3 2 | 3 | ## Numpy 4 | 5 | Practice your numpy skills in [notebooks/lab3.ipynb](../../notebooks/lab3.ipynb). 6 | 7 | ## Back to lab2 8 | 9 | - Use numpy vectorization power to refactor your code from sdia_python.lab2 10 | - Make sure each method is 11 | - tested 12 | - well documented (docstrings + additional comments if needed) 13 | - Generate the documentation 14 | 15 | If we have time today or during the next session we'll package + build + publish the project to make it installable using `pip install sdia-python-username` 16 | -------------------------------------------------------------------------------- /src/sdia_python/lab3/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guilgautier/sdia-python/b48e410a50c25305efe7c8bc6a7236e5f3803c94/src/sdia_python/lab3/__init__.py -------------------------------------------------------------------------------- /src/sdia_python/lab4/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guilgautier/sdia-python/b48e410a50c25305efe7c8bc6a7236e5f3803c94/src/sdia_python/lab4/__init__.py -------------------------------------------------------------------------------- /src/sdia_python/lab5/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guilgautier/sdia-python/b48e410a50c25305efe7c8bc6a7236e5f3803c94/src/sdia_python/lab5/__init__.py -------------------------------------------------------------------------------- /src/sdia_python/lab6/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guilgautier/sdia-python/b48e410a50c25305efe7c8bc6a7236e5f3803c94/src/sdia_python/lab6/__init__.py -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guilgautier/sdia-python/b48e410a50c25305efe7c8bc6a7236e5f3803c94/tests/__init__.py -------------------------------------------------------------------------------- /tests/lab1/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guilgautier/sdia-python/b48e410a50c25305efe7c8bc6a7236e5f3803c94/tests/lab1/__init__.py -------------------------------------------------------------------------------- /tests/lab1/test_is_unique.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from sdia_python.lab1.functions import is_unique 4 | 5 | 6 | @pytest.mark.parametrize( 7 | "items, expected", 8 | (([], True), ([1], True), ([1, 2], True), ([100, 100], False), ([1, 2, 1], False)), 9 | ) 10 | def test_is_unique(items, expected): 11 | assert is_unique(items) == expected 12 | -------------------------------------------------------------------------------- /tests/lab1/test_triangle_shape.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from sdia_python.lab1.functions import triangle_shape 4 | 5 | triangle_strings = [ 6 | "", 7 | "x", 8 | "\n".join( 9 | [ 10 | " x ", 11 | "xxx", 12 | ] 13 | ), 14 | "\n".join( 15 | [ 16 | " x ", 17 | " xxx ", 18 | "xxxxx", 19 | ] 20 | ), 21 | "\n".join( 22 | [ 23 | " x ", 24 | " xxx ", 25 | " xxxxx ", 26 | "xxxxxxx", 27 | ] 28 | ), 29 | "\n".join( 30 | [ 31 | " x ", 32 | " xxx ", 33 | " xxxxx ", 34 | " xxxxxxx ", 35 | "xxxxxxxxx", 36 | ] 37 | ), 38 | "\n".join( 39 | [ 40 | " x ", 41 | " xxx ", 42 | " xxxxx ", 43 | " xxxxxxx ", 44 | " xxxxxxxxx ", 45 | "xxxxxxxxxxx", 46 | ] 47 | ), 48 | ] 49 | 50 | 51 | @pytest.mark.parametrize("height, expected", enumerate(triangle_strings)) 52 | def test_triangle_shape(height, expected): 53 | shape = triangle_shape(height) 54 | assert shape == expected 55 | -------------------------------------------------------------------------------- /tests/lab2/__init__.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | 4 | from sdia_python.lab2.box_window import BoxWindow, UnitBoxWindow 5 | 6 | 7 | @pytest.fixture 8 | def example_box_window(): 9 | bounds = np.array([[-5, -5], [5, 5]]) 10 | return BoxWindow(bounds) 11 | 12 | 13 | @pytest.mark.parametrize( 14 | "point, expected", 15 | [ 16 | (np.array([0, 0]), True), 17 | (np.array([-1, 5]), True), 18 | (np.array([5, 6]), False), 19 | ], 20 | ) 21 | def test_indicator_function_box_2d(example_box_window, point, expected): 22 | box = example_box_window 23 | assert box.indicator_function(point) == expected 24 | -------------------------------------------------------------------------------- /tests/lab2/test_box_window.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | 4 | from sdia_python.lab2.box_window import BoxWindow 5 | 6 | 7 | def test_raise_type_error_when_something_is_called(): 8 | with pytest.raises(TypeError): 9 | # call_something_that_raises_TypeError() 10 | raise TypeError() 11 | 12 | 13 | @pytest.mark.parametrize( 14 | "bounds, expected", 15 | [ 16 | (np.array([[2.5, 2.5]]), "BoxWindow: [2.5, 2.5]"), 17 | (np.array([[0, 5], [0, 5]]), "BoxWindow: [0, 5] x [0, 5]"), 18 | ( 19 | np.array([[0, 5], [-1.45, 3.14], [-10, 10]]), 20 | "BoxWindow: [0, 5] x [-1.45, 3.14] x [-10, 10]", 21 | ), 22 | ], 23 | ) 24 | def test_box_string_representation(bounds, expected): 25 | assert str(BoxWindow(bounds)) == expected 26 | 27 | 28 | @pytest.fixture 29 | def box_2d_05(): 30 | return BoxWindow(np.array([[0, 5], [0, 5]])) 31 | 32 | 33 | @pytest.mark.parametrize( 34 | "point, expected", 35 | [ 36 | (np.array([0, 0]), True), 37 | (np.array([2.5, 2.5]), True), 38 | (np.array([-1, 5]), False), 39 | (np.array([10, 3]), False), 40 | ], 41 | ) 42 | def test_indicator_function_box_2d(box_2d_05, point, expected): 43 | is_in = box_2d_05.indicator_function(point) 44 | assert is_in == expected 45 | 46 | 47 | # ================================ 48 | # ==== WRITE YOUR TESTS BELOW ==== 49 | # ================================ 50 | -------------------------------------------------------------------------------- /tests/lab2/test_example.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | def addition(x, y): 5 | return x + y 6 | 7 | 8 | def test_simple_addition(): 9 | result = addition(1, 1) 10 | expected_result = 2 11 | assert result == expected_result 12 | 13 | 14 | @pytest.mark.parametrize( 15 | "x, y, expected", 16 | [ 17 | (0, 0, 0), 18 | (1, 1, 2), 19 | (2, 1, 3), 20 | (3, 2, 5), 21 | (4, 3, 7), 22 | (5, 5, 10), 23 | (6, 8, 14), 24 | ], 25 | ) 26 | def test_multiple_addition(x, y, expected): 27 | assert addition(x, y) == expected 28 | 29 | 30 | def test_raise_type_error_when_something_is_called(): 31 | with pytest.raises(TypeError): 32 | # call_something_that_raises_TypeError() 33 | raise TypeError() 34 | -------------------------------------------------------------------------------- /tests/lab3/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guilgautier/sdia-python/b48e410a50c25305efe7c8bc6a7236e5f3803c94/tests/lab3/__init__.py -------------------------------------------------------------------------------- /tests/lab4/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guilgautier/sdia-python/b48e410a50c25305efe7c8bc6a7236e5f3803c94/tests/lab4/__init__.py -------------------------------------------------------------------------------- /tests/lab5/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guilgautier/sdia-python/b48e410a50c25305efe7c8bc6a7236e5f3803c94/tests/lab5/__init__.py -------------------------------------------------------------------------------- /tests/lab6/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guilgautier/sdia-python/b48e410a50c25305efe7c8bc6a7236e5f3803c94/tests/lab6/__init__.py --------------------------------------------------------------------------------