commit 5f296f8447c0f839a3669a06d9ed3412aeee76d1 Author: raj_mathe Date: Mon Oct 10 11:17:09 2022 +0200 main > main: init diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..2068dde --- /dev/null +++ b/.coveragerc @@ -0,0 +1,22 @@ +[run] +source="." + +[report] +show_missing = true +omit = + # ignore tests folder + tests/* + # ignore thirdparty imports + src/thirdparty/* + # ignore models folder (auto generated) + models/** + # ignore __init__ files (only used for exports) + **/__init__.py + # ignore main.py, app.py (-> too macroscopic and covered by integration tests) + main.py + src/app.py +# TODO: increase code-coverage: +fail_under = 100 +precision = 1 +exclude_lines = + pragma: no cover diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fd2b917 --- /dev/null +++ b/.gitignore @@ -0,0 +1,86 @@ +* +!/.gitignore + +################################################################ +# DOCKER +################################################################ + +!/.dockerignore +!/Dockerfile +!/docker-compose.yaml + +################################################################ +# MAIN FOLDER +################################################################ + +!/justfile +!/Makefile +!/README.md +!/LICENSE +!/.coveragerc +!/pyproject.toml +!/requirements* + +################################################################ +# PROJECT FILES +################################################################ + +!/templates +!/templates/template* + +!/src +!/src/**/ +!/src/**/*.py +!/src/**/*.yaml +!/main.py + +!/notebooks +!/notebooks/*.ipynb +!/notebooks/*.md + +# NOTE: models are created as part of the build process: +!/models +!/models/*.yaml +!/models/README.md + +!/docs +!/docs/*/ +!/docs/*/Models/ +!/docs/**/*.md + +!/tests +!/tests/**/ +!/tests/**/*.py +!/tests/resources/*.yaml +!/tests/README.md + +!/dist +!/dist/VERSION + +################################################################ +# AUXLIARY +################################################################ + +/logs +/**/.env + +################################################################ +# TEMPLATES +################################################################ + +!/templates/.env + +################################################################ +# ARTEFACTS +################################################################ + +/**/__pycache__ +/**/.pytest_cache +/**/.DS_Store +/**/__archive__* + +################################################################ +# Git Keep +################################################################ + +!/**/.gitkeep diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md new file mode 100644 index 0000000..41c9444 --- /dev/null +++ b/README.md @@ -0,0 +1,77 @@ +# Mathematik für Physiker I, WiSe 2022-23 # + +Der Inhalt dieses Repository ist keineswegs verpflichtend, sondern dient dem Zweck, „Handnotizen“ anzubieten. +Es besteht hier kein Anspruch auf Vollständigkeit. +Es werden hier keine offiziellen Lösungen für die Übungsblätter gespeichert. + +Die offiziellen Notizen zum Kurs sowie alle Übungsblätter, (Abgabe)termine, _etc._ +findet man ausschließlich auf der **Moodle**-Seite. + +## (Wesentliche) Struktur des Repositorys ## + +```text +. +├── ./notebooks # Python/Jupyter Notebooks +│ ├── ... +│ └── ... *.ipynb Dateien +├── ./src # Quellcode +│ ├── ... +│ └── ... *.py Dateien +├── ./templates # Templates für Konfiguration +│ ├── ... +│ └── ... *.yaml Dateien +├── ./setup # User Konfiguration +│ ├── ... +│ └── ... *.yaml Dateien +├── ./tests # enthält ggf. automatisiertes Testing +├── ./dist # enthält VERSION infos +├── ./models # erzeugte Modelle +├── ./docs # Dokumentation für erzeugte Modelle +│ +├── justfile +├── README.md +├── LICENSE +├── requirements.txt +└── main.py +``` + +## Gebrauchshinweise ## + +### Systemvoraussetzungen ### + +- [**python 3.10.x**](https://www.python.org/downloads) +- optional: **bash** (für Windowsuser siehe [git for windows](https://gitforwindows.org), was bash mit installiert) +- optional: das [**justfile** Tool](https://github.com/casey/just#installation) (für Windowsuser wird die das [Chocolatey](https://chocolatey.org/install) Tool empfohlen, um dieses Tool installieren zu können) + +### Setup ### + +Für den Gebrauch der Python-Skripte + Notebooks braucht man einige Packages. +Um diese zu installiere führe man +```bash +just build +# oder +just build-requirements +``` +aus. Alternativ kann man +```bash +python3 -m pip install -r --disable-pip-version-check -r requirements.txt +# für Windowsuser: +py -3 -m pip install -r --disable-pip-version-check -r requirements.txt +``` +verwenden. + +### Ausführung ### + +Die Notebooks kann man direkt in dem [**jupyter**](https://jupyter.org) GUI öffnen, +oder in einem bash Terminal führe man +```bash +just notebook xyz +``` +aus, um den Notebook **notebooks/xyz.ipynb** zu starten. +Alternativ, kann man +``` bash +python3 -m jupyter notebook notebooks/xyz.ipynb +# für Windowsuser: +py -3 -m jupyter notebook notebooks/xyz.ipynb +``` +verwenden. diff --git a/justfile b/justfile new file mode 100644 index 0000000..ba44a40 --- /dev/null +++ b/justfile @@ -0,0 +1,259 @@ +# set shell := [ "bash", "-uc" ] +_default: + @- just --unsorted --list +menu: + @- just --unsorted --choose +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Justfile +# NOTE: Do not change the contents of this file! +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# VARIABLES +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +OS := if os_family() == "windows" { "windows" } else { "linux" } +PYTHON := if os_family() == "windows" { "py -3" } else { "python3" } +GEN_MODELS := "datamodel-codegen" +GEN_MODELS_DOCUMENTATION := "openapi-generator" +PORT := "8000" +URL_API := "http://127.0.0.1:8000/docs" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Macros +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +_create-file-if-not-exists fname: + @touch "{{fname}}"; + +_create-folder-if-not-exists path: + @if ! [[ -d "{{path}}" ]]; then mkdir -p "{{path}}"; fi + +_delete-if-file-exists fname: + @if [[ -f "{{fname}}" ]]; then rm "{{fname}}"; fi + +_delete-if-folder-exists path: + @if [[ -d "{{path}}" ]]; then rm -rf "{{path}}"; fi + +_clean-all-files path pattern: + @find {{path}} -type f -name "{{pattern}}" -exec basename {} \; 2> /dev/null + @- find {{path}} -type f -name "{{pattern}}" -exec rm {} \; 2> /dev/null + +_clean-all-folders path pattern: + @find {{path}} -type d -name "{{pattern}}" -exec basename {} \; 2> /dev/null + @- find {{path}} -type d -name "{{pattern}}" -exec rm -rf {} \; 2> /dev/null + +_copy-file-if-not-exists path_from path_to: + @- cp -n "{{path_from}}" "{{path_to}}" + +_check-python-tool tool name: + #!/usr/bin/env bash + success=false + {{tool}} --help >> /dev/null 2> /dev/null && success=true; + # NOTE: if exitcode is 251 (= help or print version), then render success. + [[ "$?" == "251" ]] && success=true; + # FAIL tool not installed + if ( $success ); then + echo -e "Tool \x1b[2;3m{{tool}}\x1b[0m installed correctly."; + exit 0; + else + echo -e "Tool \x1b[2;3m{{tool}}\x1b[0m did not work." >> /dev/stderr; + echo -e "Ensure that \x1b[2;3m{{name}}\x1b[0m (-> \x1b[1mjust build\x1b[0m) installed correctly and system paths are set." >> /dev/stderr; + exit 1; + fi + +_generate-models path name: + @{{GEN_MODELS}} \ + --input-file-type openapi \ + --encoding "UTF-8" \ + --disable-timestamp \ + --use-schema-description \ + --allow-population-by-field-name \ + --snake-case-field \ + --strict-nullable \ + --target-python-version 3.10 \ + --input {{path}}/{{name}}-schema.yaml \ + --output {{path}}/generated/{{name}}.py + +_generate-models-documentation path_schema path_docs name: + @{{GEN_MODELS_DOCUMENTATION}} generate \ + --input-spec {{path_schema}}/{{name}}-schema.yaml \ + --generator-name markdown \ + --output "{{path_docs}}/{{name}}" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# TARGETS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# TARGETS: build +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +build: + @just build-misc + @just build-requirements + @just _check-system-requirements + @just build-models +build-misc: + @# create database if not exists: + @just _create-folder-if-not-exists "data" + @# copy template of configs to setup if not exists: + @just _create-folder-if-not-exists "setup" + @just _copy-file-if-not-exists "templates/template-config.yaml" "setup/config.yaml" + @just _copy-file-if-not-exists "templates/template.env" ".env" +build-requirements: + @{{PYTHON}} -m pip install --disable-pip-version-check -r requirements.txt +build-models: + @echo "Generate data models from schemata." + @just _delete-if-folder-exists "models/generated" + @just _create-folder-if-not-exists "models/generated" + @- #just _generate-models "models" "config" +build-documentation: + @echo "Generate documentations data models from schemata." + @just _delete-if-folder-exists "docs" + @just _create-folder-if-not-exists "docs" + @- #just _generate-models-documentation "models" "docs" "config" + @- just _clean-all-files "." .openapi-generator* + @- just _clean-all-folders "." .openapi-generator* +dist: + @just build + @just build-documentation + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# TARGETS: run +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# runs using commandline interface +run: + @# create config/data folders if missing: + @just build-misc + @# run source code als cli + @{{PYTHON}} main.py + +# runs python notebook (in browser) +notebook name="main": + @# create config/data folders if missing: + @just build-misc + @# run notebook + @{{PYTHON}} -m jupyter notebook notebooks/{{name}}.ipynb + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# TARGETS: tests +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +tests: tests-unit tests-integration +tests-logs: + @just _create-logs + @- just tests + @just _display-logs +tests-unit-logs: + @just _create-logs + @- just tests-unit + @just _display-logs +tests-integration-logs: + @just _create-logs + @- just tests-integration + @just _display-logs +tests-unit: + @{{PYTHON}} -m pytest tests \ + --ignore=tests/integration \ + --cov-reset \ + --cov=. \ + 2> /dev/null +tests-integration: + @{{PYTHON}} -m pytest tests/integration 2> /dev/null + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# TARGETS: qa +# NOTE: use for development only. +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +qa: + @{{PYTHON}} -m coverage report -m +coverage source_path tests_path: + @just _create-logs + @-just _coverage-no-logs "{{source_path}}" "{{tests_path}}" + @just _display-logs +_coverage-no-logs source_path tests_path: + @{{PYTHON}} -m pytest {{tests_path}} \ + --ignore=tests/integration \ + --cov-reset \ + --cov={{source_path}} \ + --capture=tee-sys \ + 2> /dev/null + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# TARGETS: clean +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +clean: + @just clean-basic + @just pre-commit +pre-commit: + @echo "Clean python notebooks." + @{{PYTHON}} -m jupyter nbconvert --clear-output --inplace **/*.ipynb + @- {{PYTHON}} -m jupytext --update-metadata '{"vscode":""}' **/*.ipynb 2> /dev/null + @- {{PYTHON}} -m jupytext --update-metadata '{"vscode":null}' **/*.ipynb 2> /dev/null +clean-basic: + @echo "All system artefacts will be force removed." + @- just _clean-all-files "." ".DS_Store" 2> /dev/null + @echo "All build artefacts will be force removed." + @- just _clean-all-folders "." "__pycache__" 2> /dev/null + @- just _delete-if-folder-exists "models/generated" 2> /dev/null + @echo "All test artefacts will be force removed." + @- just _clean-all-folders "." ".pytest_cache" 2> /dev/null + @- just _delete-if-file-exists ".coverage" 2> /dev/null + @- just _delete-if-folder-exists "logs" 2> /dev/null + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# TARGETS: logging +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +_create-logs: + @# For logging purposes (since stdout is rechanneled): + @just _delete-if-file-exists "logs/debug.log" + @just _create-folder-if-not-exists "logs" + @just _create-file-if-not-exists "logs/debug.log" +_display-logs: + @echo "" + @echo "Content of logs/debug.log:" + @echo "----------------" + @echo "" + @- cat logs/debug.log + @echo "" + @echo "----------------" + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# TARGETS: processes +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +api-process: + #!/usr/bin/env bash + if [[ "{{OS}}" == "linux" ]]; then + ps aux | grep "uvicorn src.api:app" + else + netstat -ano | findstr "uvicorn src.api:app" + fi +kill-api-process: + #!/usr/bin/env bash + # NOTE: only need to do this for linux. + if [[ "{{OS}}" == "linux" ]]; then + echo "Terminating all processes associated to app and port {{PORT}}." + while read pid; do + if [[ "$pid" == "" ]]; then continue; fi + echo "- killing process $pid:" + kill -9 ${pid}; + done <<< $( pgrep -f "uvicorn src.api:app --port {{PORT}}" ) + fi + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# TARGETS: requirements +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +_check-system: + @echo "Operating System detected: {{os_family()}}." + @echo "Python command used: {{PYTHON}}." + +_check-system-requirements: + @just _check-python-tool "{{GEN_MODELS}}" "datamodel-code-generator" + @just _check-python-tool "{{GEN_MODELS_DOCUMENTATION}}" "openapi-code-generator" diff --git a/main.py b/main.py new file mode 100644 index 0000000..c106cd8 --- /dev/null +++ b/main.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +import os; +import sys; + +os.chdir(os.path.dirname(__file__)); +sys.path.insert(0, os.getcwd()); + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# MAIN +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def enter(): + print('Not yet implemented.'); + return; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXECUTION +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +if __name__ == '__main__': + # sys.tracebacklimit = 0; + enter(); diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..81cc22a --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,57 @@ +[project] +name = "course-mathe-fuer-physiker-1" +version = "X.Y.Z" +description = "" +authors = [ "gitea.math.uni-leipzig.de/raj_mathe" ] +maintainers = [ "gitea.math.uni-leipzig.de/raj_mathe" ] +license = "MIT" +readme = "README.md" +python = "^3.10" +homepage = "https://gitea.math.uni-leipzig.de/raj_mathe/mfp1-2022" +repository = "https://gitea.math.uni-leipzig.de/raj_mathe/mfp1-2022" +documentation = "https://gitea.math.uni-leipzig.de/raj_mathe/mfp1-2022/src/README.md" +keywords = [ + "python", +] +# cf. https://pypi.org/classifiers +classifiers = [ + "Development Status :: 3 - Alpha", + "Environment :: Console", + "Intended Audience :: Developers", + "Operating System :: Unix", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.10", +] + +[tool.pytest.ini_options] +minversion = "7.1.1" +testpaths = [ + "tests", +] +python_files = [ + "**/tests_*.py", +] +asyncio_mode = "auto" +filterwarnings = [ + "error", + "ignore::UserWarning", + "ignore::DeprecationWarning", +] +# NOTE: appends (not prepends) flags: +addopts = [ + "--order-dependencies", + "--order-group-scope=module", + "--cache-clear", + "--verbose", + "--maxfail=1", + "-k test_", + # NOTE: will be ignored, if --cov not used (e.g. integration tests): + "--no-cov-on-fail", + "--cov-report=term", + "--cov-config=.coveragerc", + # NOTE: for development purposes only: + # "-s", # verbose print/err capturing disabled + # "--capture=tee-sys", # verbose print/err capturing enabled +] diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..1f448d0 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,49 @@ +pip>=22.2.2 +wheel>=0.37.1 + +# jupyter +ipython>=8.3.0 +jupyter>=1.0.0 + +# running +codetiming>=1.3.0 + +# testing + dev +coverage[toml]>=6.4 +pytest>=7.1.1 +pytest-asyncio>=0.18.3 +pytest-cov>=3.0.0 +pytest-lazy-fixture>=0.6.3 +pytest-order>=1.0.1 +testfixtures>=6.18.5 + +# misc +importlib>=1.0.4 +authlib>=1.0.1 +passlib>=1.7.4 +psutil>=5.9.0 +pathlib>=1.0.1 +lorem>=0.1.1 +safetywrap>=1.5.0 +typing>=3.7.4.3 +nptyping>=2.1.1 +typing-extensions>=3.10.0.2 + +# config +python-dotenv>=0.20.0 +jsonschema>=4.4.0 +lazy-load>=0.8.2 +pyyaml>=5.4.1 +pydantic>=1.9.1 +datamodel-code-generator>=0.12.0 + +# maths +fraction>=2.2.0 +numpy>=1.22.4 +matplotlib>=3.5.1 + +# tables, data frames +pandas>=1.4.2 +tabulate>=0.8.10 +# array-to-latex>=0.82 # <- has issues +qiskit[visualization]>=0.38.0 diff --git a/templates/template-config.yaml b/templates/template-config.yaml new file mode 100644 index 0000000..e69de29 diff --git a/templates/template.env b/templates/template.env new file mode 100644 index 0000000..e69de29