Dedupicating Makefiles.

This commit is contained in:
Julien Palard 2022-09-23 16:12:30 +02:00
parent 675d7b7778
commit d6cabd6284
Signed by: mdk
GPG Key ID: 0EFC1AC1006886F8
45 changed files with 413 additions and 449 deletions

View File

@ -11,7 +11,7 @@ jobs:
matrix:
directory:
- python-initiation
- python-avance
- python-avancé
- drf-initiation
- django-initiation
- python-perfs

View File

@ -21,6 +21,7 @@ jobs:
python-version: '3.10'
cache: pip
- run: sudo apt-get install -y cutycapt
- run: python3 -m pip install -r requirements.txt
- run: make -C ${{ inputs.directory }} test
- name: Publish
env:

34
Makefile Normal file
View File

@ -0,0 +1,34 @@
SRCS := $(sort $(wildcard *.md))
DEST := $(notdir $(PWD))
.PHONY: static
static: output/index.html
%.html: %.md
sed 's/#!//e;' perfs.md | mdtoreveal /dev/stdin --output $@
output/index.md: $(SRCS)
mkdir -p output
cat $(SRCS) > output/index.md
.PHONY: rsync
rsync: static
rsync -vah --delete output/ mdk_fr@mdk.fr:/var/www/mdk.fr/$DEST/
.PHONY: clean
clean:
rm -fr output
.PHONY: entr
entr:
ls -1 *.md | entr $(MAKE) static
.PHONY: serve
serve: static
python3 -m http.server -d output/
.PHONY: test
test:
if [ -f test.py ]; then \
python test.py *.md; \
fi

View File

@ -1,6 +1,16 @@
# Python Introduction Slides
# The slides I use while teaching
https://mdk.fr/python-initiation/
Each directory contains a Makefile that builds the slides using
[mdtoreveal](https://pypi.org/project/mdtoreveal/).
Each directory is also uploaded to mdk.fr:
- https://mdk.fr/python-initiation
- https://mdk.fr/python-avancé
- https://mdk.fr/drf-initiation
- https://mdk.fr/django-initiation
- https://mdk.fr/python-perfs
- https://mdk.fr/git-initiation
## TODO
@ -74,3 +84,76 @@ Souci : Jour 1 pytest nécessite Jour 2 pip...
- jupyter
<a rel="license" href="http://creativecommons.org/licenses/by/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by/4.0/88x31.png" /></a><br />Ce(tte) œuvre est mise à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by/4.0/">Licence Creative Commons Attribution 4.0 International</a>.
# DRF
Side project : https://github.com/JulienPalard/drf-demos
- Revue des bases et consolidation Python et Django
- Présentation des types d'API, approfondissement de REST/HATEOAS
- Rappels autour de la sémantique HTTP
- django-rest-framework: La sérialisation
- django-rest-framework: Les différents types de vues
- django-rest-framework: Les permissions
- django-rest-framework: Les relations
- Les tests et la maintenabilité
# Objectifs pédagogiques
- Pouvoir démarrer rapidement un projet DRF.
- Savoir designer une API.
- Implémenter un service headless en utilisant DRF.
# TP
- Projet 1 : API « Horloge parlante ».
- Projet 2 : API « memcached ».
- Projet 3 : API « file system ».
- Projet 4 : API « uptime manager ».
# Formation Initiation Linux (2 jours)
Cette formation est destinée à toute personne souhaitant utiliser
Linux, pour du développement, de l'administration système, ou pour un
usage quotidien.
## Stagiaires
Maximum 5 par sessions, pour commencer, peut monter à 7.
## Pré-requis
Aucun.
## Objectifs pédagogiques
- Pouvoir utiliser une machine sous Linux au quotidien.
- Être à l'aise avec les interfaces en ligne de commande.
- Savoir installer et utiliser des logiciels.
- Manipuler des fichiers, des données.
## Plan
### Jour 1
- Présentation de l'environnement Linux.
- Maniement de l'émulateur de terminal.
- Approche des commandes classiques :
- `man`, `cd`, `ls`, `pwd`, `mv`, `cp`, `rm`, `less`, …
- Installer, désinstaller des applications depuis le gestionnaire de paquets.
### Jour 2
- L'accès à l'extérieur avec `ssh`, `rsync`, `curl`, et gestion des sauvegardes.
- Introduction à la gestion de sources en utilisant `git`.
- Manipulation de données en utilisant `awk`, `sed`, `grep`, `find`.
- L'édition de texte depuis un terminal en utilisant `emacs`.
- Approche du système de fichier : les droits, la sécurité, `mount`.

View File

@ -1,43 +0,0 @@
# Formation Initiation Linux (2 jours)
Cette formation est destinée à toute personne souhaitant utiliser
Linux, pour du développement, de l'administration système, ou pour un
usage quotidien.
## Stagiaires
Maximum 5 par sessions, pour commencer, peut monter à 7.
## Pré-requis
Aucun.
## Objectifs pédagogiques
- Pouvoir utiliser une machine sous Linux au quotidien.
- Être à l'aise avec les interfaces en ligne de commande.
- Savoir installer et utiliser des logiciels.
- Manipuler des fichiers, des données.
## Plan
### Jour 1
- Présentation de l'environnement Linux.
- Maniement de l'émulateur de terminal.
- Approche des commandes classiques :
- `man`, `cd`, `ls`, `pwd`, `mv`, `cp`, `rm`, `less`, …
- Installer, désinstaller des applications depuis le gestionnaire de paquets.
### Jour 2
- L'accès à l'extérieur avec `ssh`, `rsync`, `curl`, et gestion des sauvegardes.
- Introduction à la gestion de sources en utilisant `git`.
- Manipulation de données en utilisant `awk`, `sed`, `grep`, `find`.
- L'édition de texte depuis un terminal en utilisant `emacs`.
- Approche du système de fichier : les droits, la sécurité, `mount`.

1
culture-unix/Makefile Symbolic link
View File

@ -0,0 +1 @@
../Makefile

View File

@ -1,33 +0,0 @@
.PHONY: help
help:
@echo "Usage:"
@echo " make static # to build static version."
@echo " make test # to run tests."
@echo " make rsync # rsync to prod"
@echo " make clean"
.PHONY: static
static: output/index.html
.PHONY: check
test:
python test.py *.md
%.html: %.md
mdtoreveal $< --output $@
output/index.md: django.md
mkdir -p output
cat $< > $@
.PHONY: rsync
rsync: static
rsync -vah --delete output/ mdk_fr@mdk.fr:/var/www/mdk.fr/django-initiation/
.PHONY: clean
clean:
rm -fr output/
.PHONY: serve
serve:
python -m http.server -d output/

1
django-initiation/Makefile Symbolic link
View File

@ -0,0 +1 @@
../Makefile

View File

@ -1,27 +0,0 @@
# Contenu
Side project : https://github.com/JulienPalard/drf-demos
- Revue des bases et consolidation Python et Django
- Présentation des types d'API, approfondissement de REST/HATEOAS
- Rappels autour de la sémantique HTTP
- django-rest-framework: La sérialisation
- django-rest-framework: Les différents types de vues
- django-rest-framework: Les permissions
- django-rest-framework: Les relations
- Les tests et la maintenabilité
# Objectifs pédagogiques
- Pouvoir démarrer rapidement un projet DRF.
- Savoir designer une API.
- Implémenter un service headless en utilisant DRF.
# TP
- Projet 1 : API « Horloge parlante ».
- Projet 2 : API « memcached ».
- Projet 3 : API « file system ».
- Projet 4 : API « uptime manager ».

View File

@ -35,7 +35,7 @@ Dans Django on va avoir principalement des `models`, des `vues`, des
On travaillera toujours dans un `venv` :
```python
```bash
python -m pip install django
```
@ -43,7 +43,7 @@ python -m pip install django
Pour démarrer un projet, une commande :
```python
```bash
django-admin startproject project
```
@ -51,7 +51,7 @@ django-admin startproject project
Une fois dans le projet, pour créer une application, une commande :
```python
```bash
python manage.py startapp watch
```
@ -307,8 +307,8 @@ Dans `project/urls.py` on va se rajouter une URL pour la page d'accueil :
from watch import views
urlpatterns = [
...
...
...,
...,
path("", views.index, name="index"),
]
```
@ -721,7 +721,7 @@ fichier doit commencer par `test` pour être trouvé.
Les tests s'exécutent via :
```python
```bash
python manage.py test
```

View File

@ -1,40 +0,0 @@
#!/usr/bin/env python3
import argparse
from string import ascii_letters, digits
import re
import doctest
from tempfile import NamedTemporaryFile
import importlib.util
parser = argparse.ArgumentParser()
parser.add_argument("file", nargs="+")
parser.add_argument("-v", "--verbose", action="store_true")
parser.add_argument("-d", "--debug", action="store_true")
args = parser.parse_args()
for file_to_test in args.file:
with open(file_to_test) as f:
source = f.read()
with NamedTemporaryFile(mode="w", suffix=".py") as f:
for example_match in re.finditer("```python.*?```", source, re.S):
example = example_match.group()
example = "\n".join(example.split("\n")[1:-1])
lineno = source[:example_match.start()].count("\n") + 1
function_name = ''.join(letter if letter in ascii_letters + digits else '_' for letter in file_to_test[:-3]) + "_line_" + str(lineno)
if example.startswith(">>> "):
if '"""' in example:
f.write(f"""def _{function_name}():\n r'''""" + example + """\n'''\n\n""")
else:
f.write(f'''def _{function_name}():\n r"""''' + example + '''\n"""\n\n''')
else:
f.write(example + "\n\n")
f.flush()
if args.debug:
with open(f.name) as py_source:
print(py_source.read())
spec = importlib.util.spec_from_file_location("to_test", f.name)
to_test = importlib.util.module_from_spec(spec)
spec.loader.exec_module(to_test)
doctest.testmod(to_test, verbose=args.verbose)

152
doddling/find_sum.py Normal file
View File

@ -0,0 +1,152 @@
def find_sum1(n, l):
"""Gros nombre non trouvé : pour 10**4 elements : 10s
Petit nombre non trouvé : pour 10**4 elements : 10s
"""
for i in range(len(l)):
for j in range(len(l)):
if i == j:
continue
if l[i] + l[j] == n:
return True
return False
def find_sum2(n, l):
"""Gros nombre non trouvé : pour 10**4 elements : 12s
Petit nombre non trouvé : 0s
"""
for i in range(len(l)):
if l[i] > n:
continue
for j in range(len(l)):
if i == j:
continue
if l[j] > n:
continue
if l[i] + l[j] == n:
return True
return False
def find_sum3(n, l):
"""Gros nombre non trouvé : pour 10**4 elements : 8s
Petit nombre non trouvé : pour 10**4 elements : 0s
"""
for i in range(len(l)):
if l[i] > n:
return False
for j in range(i + 1, len(l)):
if l[i] + l[j] == n:
return True
if l[i] + l[j] > n:
break
return False
def find_sum3(n, l):
"""Gros nombre non trouvé : pour 10**4 elements : 8s
Petit nombre non trouvé : pour 10**4 elements : 0s
"""
for i in range(len(l)):
if l[i] > n:
return False
for j in range(i + 1, len(l)):
if l[i] + l[j] == n:
return True
if l[i] + l[j] > n:
break
return False
def find_sum4(n, l):
"""Gros nombre non trouvé : pour 10**4 elements : 8s
Petit nombre non trouvé : pour 10**4 elements : 5s
"""
if len(l) <= 1:
return False
i = 0
j = len(l) - 1
while True:
if l[i] + l[j] == n:
return True
i += 1
if i == j or l[i] + l[j] > n:
if l[i] + l[j] < n:
return False
i = 0
j -= 1
if j == 0:
return False
def find_sum5(n, l):
if len(l) <= 1:
return False
i = 0
j = len(l) - 1
while True:
print(f"Searching at {i}+{j} ({l[i]+l[j]})")
if l[i] + l[j] == n:
return True
if l[i] + l[j] > n:
j -= 1
if l[i] + l[j] < n:
i += 1
find_sum5(12, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
exit(0)
find_sum4(2, [10, 10, 10])
from time import perf_counter
import matplotlib.pyplot as plt
k = 4
seed = list(range(10, 10 ** 5))
print(f"Testing small int a list of length {10 ** k}...")
to_find = seed[: 10 ** k]
begin = perf_counter()
find_sum4(2, to_find)
end = perf_counter()
print(f"Done in {end - begin}s")
print(f"Testing big int a list of length {10 ** k}...")
to_find = seed[: 10 ** k]
begin = perf_counter()
find_sum4(2 ** 32, to_find)
end = perf_counter()
print(f"Done in {end - begin}s")
assert find_sum1(2, [1, 1])
assert find_sum1(5, [1, 2, 3, 4, 5])
assert not find_sum1(5, [1, 3, 6])
assert not find_sum1(4, [2, 3, 4, 5, 6])
assert find_sum1(10, [2, 3, 5, 6, 7, 9])
assert find_sum2(2, [1, 1])
assert find_sum2(5, [1, 2, 3, 4, 5])
assert not find_sum2(5, [1, 3, 6])
assert not find_sum2(4, [2, 3, 4, 5, 6])
assert find_sum2(10, [2, 3, 5, 6, 7, 9])
assert find_sum3(2, [1, 1])
assert find_sum3(5, [1, 2, 3, 4, 5])
assert not find_sum3(5, [1, 3, 6])
assert not find_sum3(4, [2, 3, 4, 5, 6])
assert find_sum3(10, [2, 3, 5, 6, 7, 9])
assert find_sum4(2, [1, 1])
assert find_sum4(5, [1, 2, 3, 4, 5])
assert not find_sum4(5, [1, 3, 6])
assert not find_sum4(4, [2, 3, 4, 5, 6])
assert find_sum4(10, [2, 3, 5, 6, 7, 9])
assert find_sum5(2, [1, 1])
assert find_sum5(5, [1, 2, 3, 4, 5])
assert not find_sum5(5, [1, 3, 6])
assert not find_sum5(4, [2, 3, 4, 5, 6])
assert find_sum5(10, [2, 3, 5, 6, 7, 9])

127
doddling/sudoku.py Normal file
View File

@ -0,0 +1,127 @@
import numpy as np
from collections import Counter
def is_done(grid):
for square in (
grid[0:3, 0:3],
grid[0:3, 3:6],
grid[0:3, 6:9],
grid[3:6, 0:3],
grid[3:6, 3:6],
grid[3:6, 6:9],
grid[6:9, 0:3],
grid[6:9, 3:6],
grid[6:9, 6:9],
):
if set(square.ravel()) != {1, 2, 3, 4, 5, 6, 7, 8, 9}:
return False
for line in grid:
if set(line) != {1, 2, 3, 4, 5, 6, 7, 8, 9}:
return False
for line in grid.T:
if set(line) != {1, 2, 3, 4, 5, 6, 7, 8, 9}:
return False
return True
def is_valid(grid):
for square in (
grid[0:3, 0:3],
grid[0:3, 3:6],
grid[0:3, 6:9],
grid[3:6, 0:3],
grid[3:6, 3:6],
grid[3:6, 6:9],
grid[6:9, 0:3],
grid[6:9, 3:6],
grid[6:9, 6:9],
):
c = Counter(square.ravel())
if 0 in c:
del c[0]
try:
value, occurences = c.most_common(1)[0]
if occurences > 1:
return False
except IndexError:
pass
for line in grid:
c = Counter(line)
if 0 in c:
del c[0]
try:
value, occurences = c.most_common(1)[0]
if occurences > 1:
return False
except IndexError:
pass
for line in grid.T:
c = Counter(line)
if 0 in c:
del c[0]
try:
value, occurences = c.most_common(1)[0]
if occurences > 1:
return False
except IndexError:
pass
return True
grid = np.zeros((9, 9), dtype=int)
grid = np.array(
[
[0, 0, 0, 1, 1, 1, 2, 2, 2],
[0, 0, 0, 1, 1, 1, 2, 2, 2],
[0, 0, 0, 1, 1, 1, 2, 2, 2],
[3, 3, 3, 4, 4, 4, 5, 5, 5],
[3, 3, 3, 4, 4, 4, 5, 5, 5],
[3, 3, 3, 4, 4, 4, 5, 5, 5],
[6, 6, 6, 7, 7, 7, 8, 8, 8],
[6, 6, 6, 7, 7, 7, 8, 8, 8],
[6, 6, 6, 7, 7, 7, 8, 8, 8],
]
)
is_valid(grid)
def find_first_blank(grid):
i, j = 0, 0
for i in range(9):
for j in range(9):
if grid[i, j] == 0:
return i, j
def solve(grid):
print(grid)
if is_done(grid):
print(grid)
exit(0)
try:
my_i, my_j = find_first_blank(grid)
except TypeError:
return
for i in range(1, 10):
grid[my_i, my_j] = i
if is_valid(grid):
solve(grid.copy())
grid = np.array(
[
[0, 0, 0, 7, 3, 0, 6, 0, 0],
[0, 7, 0, 0, 8, 0, 1, 5, 0],
[2, 3, 0, 5, 0, 0, 0, 0, 0],
[0, 0, 0, 6, 0, 2, 4, 0, 5],
[6, 4, 0, 0, 0, 0, 0, 8, 2],
[5, 0, 9, 3, 0, 8, 0, 0, 0],
[0, 0, 0, 0, 0, 5, 0, 4, 8],
[0, 9, 4, 0, 2, 0, 0, 7, 0],
[0, 0, 5, 0, 7, 6, 0, 0, 0],
]
)
solve(grid)

View File

@ -1,33 +0,0 @@
.PHONY: help
help:
@echo "Usage:"
@echo " make static # to build static version."
@echo " make test # to run tests."
@echo " make rsync # rsync to prod"
@echo " make clean"
.PHONY: static
static: output/index.html
.PHONY: check
test:
python test.py *.md
%.html: %.md
mdtoreveal $< --output $@
output/index.md: drf.md
mkdir -p output
cat $< > $@
.PHONY: rsync
rsync: static
rsync -vah --delete output/ mdk_fr@mdk.fr:/var/www/mdk.fr/drf-initiation/
.PHONY: clean
clean:
rm -fr output/
.PHONY: serve
serve:
python -m http.server -d output/

1
drf-initiation/Makefile Symbolic link
View File

@ -0,0 +1 @@
../Makefile

View File

@ -1,27 +0,0 @@
# Contenu
Side project : https://github.com/JulienPalard/drf-demos
- Revue des bases et consolidation Python et Django
- Présentation des types d'API, approfondissement de REST/HATEOAS
- Rappels autour de la sémantique HTTP
- django-rest-framework: La sérialisation
- django-rest-framework: Les différents types de vues
- django-rest-framework: Les permissions
- django-rest-framework: Les relations
- Les tests et la maintenabilité
# Objectifs pédagogiques
- Pouvoir démarrer rapidement un projet DRF.
- Savoir designer une API.
- Implémenter un service headless en utilisant DRF.
# TP
- Projet 1 : API « Horloge parlante ».
- Projet 2 : API « memcached ».
- Projet 3 : API « file system ».
- Projet 4 : API « uptime manager ».

View File

@ -1,40 +0,0 @@
#!/usr/bin/env python3
import argparse
from string import ascii_letters, digits
import re
import doctest
from tempfile import NamedTemporaryFile
import importlib.util
parser = argparse.ArgumentParser()
parser.add_argument("file", nargs="+")
parser.add_argument("-v", "--verbose", action="store_true")
parser.add_argument("-d", "--debug", action="store_true")
args = parser.parse_args()
for file_to_test in args.file:
with open(file_to_test) as f:
source = f.read()
with NamedTemporaryFile(mode="w", suffix=".py") as f:
for example_match in re.finditer("```python.*?```", source, re.S):
example = example_match.group()
example = "\n".join(example.split("\n")[1:-1])
lineno = source[:example_match.start()].count("\n") + 1
function_name = ''.join(letter if letter in ascii_letters + digits else '_' for letter in file_to_test[:-3]) + "_line_" + str(lineno)
if example.startswith(">>> "):
if '"""' in example:
f.write(f"""def _{function_name}():\n r'''""" + example + """\n'''\n\n""")
else:
f.write(f'''def _{function_name}():\n r"""''' + example + '''\n"""\n\n''')
else:
f.write(example + "\n\n")
f.flush()
if args.debug:
with open(f.name) as py_source:
print(py_source.read())
spec = importlib.util.spec_from_file_location("to_test", f.name)
to_test = importlib.util.module_from_spec(spec)
spec.loader.exec_module(to_test)
doctest.testmod(to_test, verbose=args.verbose)

View File

@ -1,34 +0,0 @@
.PHONY: help
help:
@echo "Usage:"
@echo " make static # to build static version."
@echo " make test # to run tests."
@echo " make rsync # rsync to prod"
@echo " make clean"
.PHONY: static
static: output/index.html
cp -a static/ output/
.PHONY: check
test:
python test.py *.md
%.html: %.md
mdtoreveal $< --output $@
output/index.md: git.md
mkdir -p output
cat $< > $@
.PHONY: rsync
rsync: static
rsync -vah --delete output/ mdk_fr@mdk.fr:/var/www/mdk.fr/git-initiation/
.PHONY: clean
clean:
rm -fr output/
.PHONY: serve
serve:
python -m http.server -d output/

1
git-initiation/Makefile Symbolic link
View File

@ -0,0 +1 @@
../Makefile

View File

@ -1 +0,0 @@
# GIT

View File

@ -1,40 +0,0 @@
#!/usr/bin/env python3
import argparse
from string import ascii_letters, digits
import re
import doctest
from tempfile import NamedTemporaryFile
import importlib.util
parser = argparse.ArgumentParser()
parser.add_argument("file", nargs="+")
parser.add_argument("-v", "--verbose", action="store_true")
parser.add_argument("-d", "--debug", action="store_true")
args = parser.parse_args()
for file_to_test in args.file:
with open(file_to_test) as f:
source = f.read()
with NamedTemporaryFile(mode="w", suffix=".py") as f:
for example_match in re.finditer("```python.*?```", source, re.S):
example = example_match.group()
example = "\n".join(example.split("\n")[1:-1])
lineno = source[:example_match.start()].count("\n") + 1
function_name = ''.join(letter if letter in ascii_letters + digits else '_' for letter in file_to_test[:-3]) + "_line_" + str(lineno)
if example.startswith(">>> "):
if '"""' in example:
f.write(f"""def _{function_name}():\n r'''""" + example + """\n'''\n\n""")
else:
f.write(f'''def _{function_name}():\n r"""''' + example + '''\n"""\n\n''')
else:
f.write(example + "\n\n")
f.flush()
if args.debug:
with open(f.name) as py_source:
print(py_source.read())
spec = importlib.util.spec_from_file_location("to_test", f.name)
to_test = importlib.util.module_from_spec(spec)
spec.loader.exec_module(to_test)
doctest.testmod(to_test, verbose=args.verbose)

View File

@ -1,31 +0,0 @@
SRCS := $(sort $(wildcard *-*.md))
.PHONY: help
help:
@echo "Usage:"
@echo " make static # to build static version."
@echo " make test # to run tests."
@echo " make rsync # rsync to prod"
@echo " make clean"
.PHONY: check
test:
python test.py *.md
.PHONY: static
static: output/index.html
%.html: %.md
mdtoreveal $< --output $@
output/index.md: $(SRCS)
mkdir -p output
cat $(SRCS) > output/index.md
.PHONY: rsync
rsync: static
rsync -vah --delete output/ mdk_fr@mdk.fr:/var/www/mdk.fr/python-avancé/
.PHONY: clean
clean:
rm -fr output

View File

@ -1,3 +0,0 @@
# TODO
- [ ] Ajouter les nombres imaginaires.

1
python-avancé/Makefile Symbolic link
View File

@ -0,0 +1 @@
../Makefile

View File

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 108 KiB

View File

@ -1,30 +0,0 @@
.PHONY: static
static: output/index.html
.PHONY: help
help:
@echo "Usage:"
@echo " make static"
@echo " make test"
@echo " make rsync"
@echo " make clean"
.PHONY: check
test:
python test.py *.md
output/index.html: initiation.md
mdtoreveal $< --output $@
cp -a static output
.PHONY: rsync
rsync: static
rsync -vah --delete output/ mdk_fr@mdk.fr:/var/www/mdk.fr/python-initiation/
.PHONY: clean
clean:
rm -f $(HTML)
.PHONY: serve
serve:
python3 -m http.server -d output/

1
python-initiation/Makefile Symbolic link
View File

@ -0,0 +1 @@
../Makefile

View File

@ -1,20 +0,0 @@
# TODO
Lors de la présentation des fonctions natives dans un REPL, il y a une
ambiguité (`print` vs `return`):
>>> int("42")
42
>>> print("42")
42
On pourrait passer par une variable peut-être :
>>> quarante_deux = int("42")
>>> quarante_deux
42
>>> result = print("42")
42
>>> print(result)
None

View File

@ -1,38 +0,0 @@
export PATH := $(PATH):bin
# Only run watch with -j2 so entr and serve are run in parallel.
.PHONY: watch
watch: entr serve
.PHONY: static
static: output/index.html
cp -a .cache/*.png output/
.PHONY: help
help:
@echo "Usage:"
@echo " make static"
@echo " make test"
@echo " make rsync"
@echo " make clean"
.PHONY: entr
entr:
ls -1 *.md include/*.py | entr $(MAKE) static
output/index.html: perfs.md
mkdir -p .cache
sed 's/#!//e;' perfs.md | mdtoreveal /dev/stdin --output $@
if [ -d static ]; then cp -a static output; fi
.PHONY: rsync
rsync: static
rsync -vah --delete output/ mdk_fr@mdk.fr:/var/www/mdk.fr/python-perfs/
.PHONY: clean
clean:
rm -f $(HTML)
.PHONY: serve
serve:
python3 -m http.server -d output/

1
python-perfs/Makefile Symbolic link
View File

@ -0,0 +1 @@
../Makefile