PROJET AUTOBLOG


Sam & Max: Python, Django, Git et du cul

Site original : Sam & Max: Python, Django, Git et du cul

⇐ retour index

Mise à jour

Mise à jour de la base de données, veuillez patienter...

Mise à jour de l’article sur les middlewares Django

lundi 19 septembre 2016 à 12:04

Ça faisait un bout de temps que je n’avais pas mis à jour un article en Python 3.

Là je fais un Pierre deux couilles puisque les middlewares ont changé avec Django 1.10 et ça me permet de rafraîchir cette notion assez floue du framework.

Allez hop, on va lire l’article.

C’est pas pour tout de suite

vendredi 16 septembre 2016 à 09:44

J’ai envie de vous écrire un article sur les types hints, mais le tooling est encore incomplet. On vient juste d’avoir le support de async / await et le typage structurel n’est pas d’actualité. Ennuyeux pour un langage qui aime autant les canards.

J’ai envie de vous écrire un article sur asyncio, mais je ne veux pas faire un article qui survole le sujet comme tout ce qu’il y a sur la toile. Je veux parler de cas concrets, et amener des solutions pour le debuggage, l’architecture, et du code pour les actions les plus communes. Et ça fait des mois que j’y travaille, mais comme vous pouvez le voir y a encore du taff.

J’ai envie de vous parler de la 3.6, mais tout est toujours en beta et la mailing list de Python est en ébullition, difficile de savoir comme ça va se finir, même avec un feature freeze pas loin. Et c’est pas faute de participer. je préfère attendre que ça se soit calmé.

Bref, y a des trucs sympas à écrire, mais des trucs pas prêts.

Du coup j’ai sous le coude des petits trucs comme un petit middleware django, le test coverage, etc.

Je dis ça parce que je me fais en ce moment tout le temps twitter pour que j’écrive sur ces sujets, mais c’est pas encore le bon moment.

Vérifier qu’un uuid est valide en Python 6

mardi 6 septembre 2016 à 13:23

Si on teste du code qui utilise des uuid, on veut vérifier qu’on récupère bien des uuid valides là où on les attend.

Le plus simple est de déléguer cette vérification au module uuid qui est déjà celui qu’on utilise pour les produire.

from uuid import UUID
 
def is_uuid(uuid_string, version=4):
    try:
        # Si uuid_string est un code hex valide mais pas un uuid valid,
        # UUID() va quand même le convertir en uuid valide. Pour se prévenir
        # de se problème, on check la version original (sans les tirets) avec
        # le code hex généré qui doivent être les mêmes.
        uid = UUID(uuid_string, version=version)
        return uid.hex == uuid_string.replace('-', '')
    except ValueError:
        return False

Et pouf:

>>> import uuid
 
>>> print(uuid.uuid4())
1049d03f-6f45-4637-89ff-f57567f6d022
 
>>> is_uuid('1049d03f-6f45-4637-89ff-f57567f6d022')
True
 
>>> is_uuid('1049d03f6f45463789fff57567f6d022')
True
 
>>> is_uuid('1049d03f6f45')
False

À chaque fois que j’utilise un uuid, j’ai un peu l’impression d’user la fabrique de l’univers, comme si je fabriquais quelque chose d’unique pour le mettre la poubelle, et qui n’existera plus jamais. Le gâchis d’un flocon de neige virtuel :)

C’est le futur ! 3   Recently updated !

jeudi 1 septembre 2016 à 18:26

J’ai twitté il y a quelque temps l’article hilarant It’s the future. Mais j’ai bien conscience que plein de gens ne lisent pas l’anglais et ne peuvent profiter de cette perle. Comme on a ouvert le blog S&M en français, car on voulait justement créer des bonnes ressources dans notre langue, je traduis de temps en temps ces trucs fantastiques, comme par exemple Le bonheur des frameworks.

Donc voici la traduction de celui-ci. Faites-vous plaiz’

Hey, mon boss m’a dit de venir te voir. Il paraît que tu gères niveau web apps ?

– Ouais, je suis plus un spécialiste des systèmes distribués maintenant. Je reviens du ContainerCamp et de la Gluecon et je vais à la Dockercon la semaine prochaine. Je suis emballé par la direction que prend l’industrie – tout est plus simple et fiable. C’est le futur !

Cool. Je veux juste faire une simple Web app pour le moment – un CRUD normal avec Rails, que je vais déployer sur Heroku. C’est toujours d’actu ?

– Oh non. C’est old school. Heroku, c’est mort – plus personne ne l’utilise. Il te faut Docker maintenant. C’est le futur.

Oh, OK. Qu’est-ce que c’est ?

– Docker est la nouvelle façon de faire de la conteneurisation. Comme LXC, mais c’est aussi un format de package, une plateforme de distribution et des outils pour rendre la création de systèmes distribués très facile.

Conteneuri.. – Hein ? C’est quoi LXE ?

– LCX. C’est comme un chroot aux stéroïdes.

C’est quoi cheroot ?

– Ok, regarde. Docker. Conteneurisation. C’est le futur. C’est comme la virtualisation, mais plus rapide et moins coûteux.

Oh, comme Vagrant.

– No, Vagrant c’est mort. Tout va être conteneurisé maintenant, c’est le futur.

Ok, donc je n’ai pas besoin de savoir quoi que ce soit sur la virtualisation ?

– Non, tu as quand même besoin de la virtualisation, parce que les conteneurs ne fournissent pas toutes les couches de sécurité pour le moment. Donc ce que tu veux, c’est faire tout tourner dans un environnement multitiers de telle sorte qu’on ne puisse s’échapper de la sandbox.

Ok, je suis un peu perdu là. On rembobine. Donc il y a un truc comme la virtualisation qu’on appelle les conteneurs. Et je peux l’utiliser sur Heroku ?

– Et bien, Heroku a un support pour docker, mais je viens de le dire : Heroku c’est mort. Ce que tu veux c’est faire tourner tes conteneurs sur CoreOS.

Ok, c’est quoi ?

– C’est un OS hôte très cool qu’on peut utiliser avec Docker. Tu n’as même pas besoin de Docker, tu peux utiliser rkt.

Rocket ?

– No, rkt.

Ouais, Rocket.

– Non, ça s’appelle rkt maintenant. Rien à voir. C’est un format de conteneurisation alternatif qui n’est pas aussi intégré que Docker par défaut, et donc plus composable.

C’est une bonne chose.

– Bien entendu. La composabilité c’est le futur.

Ok, ça s’utilise comment ?

– Je ne sais pas. Je ne pense pas que qui que ce soit l’utilise.

Arf. Tu disais quoi à propos de CoreOS ?

– Ah oui, c’est un OS hôte pour Docker.

C’est quoi un OS hôte ?

– Un OS hôte fait tourner tous tes conteneurs.

Tourner mes conteneurs ?

– Ouais, tu dois avoir quelque chose pour faire tourner tes conteneurs. Donc tu te crées genre une instance EC2, tu mets CoreOS dessus, tu lances le daemon Docker, puis tu déploies tes images Docker dessus.

Quelle partie est le conteneur ?

– Tout. Écoute, tu prends ton app, écris un Dockerfile, tu en fais une image locale, puis tu la push sur n’importe quel hôte Docker.

Ah, comme Heroku ?

– Non, pas Heroku. Je te l’ai dit. Heroku c’est mort. Tu gères ton propre cloud en utilisant Docker.

Hein ?

– Ouais, c’est tout simple. Check #gifee.

Gify?

Google’s infrastructure for everyone else. Tu prends les outils que tu veux, avec des conteneurs, et tu as la même infra que Google.

Pourquoi pas juste utiliser celles de Google ?

Tu crois que ça sera encore là dans 6 mois ?

OK, mais est-ce que quelqu’un fait du hosting pour ça ? J’ai pas la foi d’héberger mon bordel moi-même.

– Et bien, Amazon a ECS, mais il faut écrire du XML et 2, 3 merdes.

Et OpenStack ?

– Beurk.

Beurk ?

– Beurk.

Écoute, j’ai vraiment pas envie d’héberger tout ça.

– Na, c’est super simple. Tu te setup juste un cluster Kubernetes.

J’ai besoin d’un cluster ?

– Un cluster Kubernetes. Ça gère le déploiement de tous tes services.

J’ai seulement un service.

– Qu’est-ce que tu racontes. Tu as une app non? donc tu as bien au moins 8-12 services ?

Quoi ? Non. Juste une app. Service, on s’en branle. Juste un truc.

– Non, jette un coup d’oeil à la notion de microservices. C’est le futur. C’est comme ça qu’on fait tout de nos jours. Tu prends ton app monolithique et tu la divises en quelque chose comme 12 services, un pour chaque tâche.

Ça semble excessif.

– C’est le seul moyen de s’assurer que c’est fiable. Ainsi si ton service authentification tombe…

Service authentification ? J’allais juste utiliser une gem que j’avais déjà mis en place plusieurs fois avant.

– Super. Utilise la gem. Mets la dans son propre projet. Fous une API RESTful par dessus. Et fait en sorte que les autres services utilisent cette API et gèrent gracieusement les échecs. Mets ça dans un conteneur et push le bordel en déploiement continu.

Ok, donc là j’ai une douzaine de services ingérables, et maintenant ?

– Ouais, d’où Kubernetes. Il orchestre tes services.

Orchestre ?

– Ouais, donc tu as ces services, ils doivent être fiables donc il t’en faut plusieurs copies. Donc Kubernetes s’assure que tu en as assez, et qu’ils sont distribués à travers de multiples hôtes dans ta flotte de serveurs, afin qu’ils soient toujours disponibles.

Ah parce qu’il me faut une flotte maintenant ?

– Ouais, pour la fiabilité. Mais Kubernetes la gère pour toi. Et tu sais que Kubernetes ça marche vu que Google l’a fabriqué et que ça tourne sur etcd.

C’est quoi etcd ?

– Une implémentation de Raft.

OK, c’est quoi Raft.

– C’est comme Paxos.

Putain, jusqu’où ça va le terrier du lapin blanc là ? Je veux juste lancer une app. Arf. Bordel, Ok, on respire. Fiou. Ok, donc Paxos c’est quoi ?

– Paxos c’est ce très vieux protocole de consensus distribué des années 70 que personne ne comprend ou n’utilise.

Super, merci de m’en avoir parlé. Et donc Raft ?

– Comme personne ne pige Paxos, y a ce mec, Diego

Oh, tu le connais ?

– Non, il travaille a CoreOS. Bref, Diego a créé Raft pour sa thèse de doctorat, car Paxos était trop compliqué. Futé le gars. Et il a écrit etcd comme implémentation, et Aphyr a dit que c’était pas de la merde.

C’est quoi Aphyr ?

– Aphyr est le mec qui a écrit Call Me Maybe. Tu vois, le mec spécialiste des systèmes distribués et du BDSM ?

WUT ? BDSM ?

– Ouais, BDSM. C’est San Francisco hein, tout le monde est à fond dans les systèmes distribués et le BDSM

Hum, OK. Donc il a écrit cette chanson de Katy Perry ?

– Nan, il a écrit des posts sur son blog comme quoi toutes les databases n’atteignaient jamais le CAP.

C’est quoi le CAP ?

– Le théorème CAP. Ça dit que tu peux avoir des données consistantes, disponibles et tolérantes au partitionnement, mais qu’il faut choisir 2 de ces caractéristiques sur les 3.

Ok, et donc toutes les bases de données foirent CAP. C’est à dire ?

– Ça veut dire qu’elles sont à chier. Comme Mongo.

Je pensais que Mongo scalait ?

– Ben personne d’autre ne le pensait.

Ok, et etcd.

– Ouais, etcd c’est un système de stockage de clé/valeur distribué.

Oh, comme Redis.

– Non, rien à voir. etcd est distribué. Redis perd la moitié de ce que tu écris en cas d’échec réseau.

Ok, donc c’est un système de stockage de clé/valeur distribué. Pourquoi c’est utile ?

– Kubernetes setup par défaut un cluster de 5 nodes et utilise etcd comme bus de transport de messages. En combinaison avec quelques services de Kubernetes lui-même, ça fournit un système d’orchestration assez résilient.

5 nodes ? J’ai une app. Combien de machines je vais devoir prendre pour tout ça ?

– Et bien tu vas avoir environ 12 services, et bien sûr il te faut des copies de chaque pour la redondance, quelques load balancers, le cluster etcd, ta base de données, et le cluster kubernetes. Je dirais peut-être 50 conteneurs.

WTF ?!

– Aucun problème ! Les conteneurs sont vraiment efficaces, donc tu peux les distribuer sur genre, 8 machines. C’est pas incroyable ?

C’est une manière de voir les choses. Et avec tout ça, je vais être capable de simplement déployer mon app ?

– Yep. Je veux dire, la question du stockage est toujours en suspend avec Docker et Kubernetes, et la partie réseau va demander un peu de travail, mais techniquement, tu es à 2m du bol de sangria.

Je vois. Ok, je pense que j’ai pigé.

– Super !

Merci pour l’explication.

– No problem.

Laisse-moi faire un résumé pour voir si j’ai bien tout compris.

– Bien sûr !

Donc j’ai besoin de diviser mon app CRUD toute simple, en 12 microservices, chacun avec leur propre API qui s’appellent les uns et les autres, mais qui gèrent les erreurs de manière résiliente, les mettre dans des conteneurs Docker, lancer une flotte de 8 machines qui sont des hôtes Docker tournant sous CoreOS, les orchestrer avec un petit cluster Kubernetes qui tourne avec etcd, me démerder avec la question du réseau et du stockage, et je fais tout ça en déploiement continu pour de multiples copies redondantes des microservices de ma flotte. J’ai bon ?

– Yep ! C’est pas fabuleux ?

Je retourne sous Heroku.

En relisant l’article, je réalise deux choses :

 

Des astuces avec pytest   Recently updated !

mardi 30 août 2016 à 11:36

Pytest est fantastique. En fait si la lib n’est pas dispo je n’ai même plus la volonté d’écrire des tests unitaires tellement je suis habitué aux facilités qu’elle offre.

Au fur et à mesure de son usage, j’ai noté quelques astuces qui, je le sais, vous serviront bien sur le long terme.

Choper une exception avec un message particulier

On peut vérifier qu’une fonction lève bien une exception avec la fonction raises():

import pytest
 
def test_truc():
    with pytest.raises(MachinError):
        foo()

Ce test réussira si foo() lève bien de manière consistante MachinError. Mais parfois on a plein d’erreurs similaires, et on en veut une avec un message particulier. Dans ce cas, on peut matcher le message sur une regex:

def test_truc():
    with pytest.raises(MachinError) as excinfo:
        foo()
     excinfo.match(r"votre regex du message d'erreur")

Configurez, il en restera toujours quelque chose

On peut mettre la config de votre projet dans un fichier pytest.ini (mais le fichier tox.ini ou setup.cfg marche aussi \o/). Parmi les options les plus pratiques:

addopts, qui permet de forcer des options à la ligne de commande pytest pour ne pas les passer à chaque fois à la main.

Celles que j’active toujours:

--exitfirst : le premier échec arrête les tests. Pas la peine de me mettre 22 mille erreurs.
--capture=no : affiche les print() de mon code.
--ignore="virtualenv" : permet de ne pas cherche les tests dans un dossier. Par exemple le virtualenv.
-vv : bien verbeux. Je veux de l’info sur mes tests.
--showlocals : montre les variables locales sur les tests qui foirent.

Par exemple:

[pytest]
addopts = --exitfirst --capture=no -ignore="virtualenv" -vv --showlocals

Mais bon comme j’ai toujours ces trucs-là activés, je force ces options dans mon .bashrc via la variable d’env:

export PYTEST_ADDOPTS="--exitfirst --capture=no -ignore="virtualenv" -vv --showlocals"

Autres options sympas:

testpaths qui permet de choisir les chemins dans lesquels chercher les tests:

Ex:

[pytest]
testpaths =
    tests
    foo
    bar

Si à l’intérieur de ces dossiers il a un truc à ne pas choper, norecursedirs est là pour ça :

[pytest]
norecursedirs =
    tests/media
    tests/scripts

Les options pratiques de tous les jours

Il y a des options qu’on ne veut pas tout le temps, mais qui sont super utiles ponctuellement:

--failed-first : relance tous les tests, mais ceux qui ont foiré en premier.
--pdb : lance pdb juste après le premier échec.
-k : lance uniquement les tests dont le nom matche cette regex.

Et souvenez-vous que vous pouvez lancer un seul test en spécifiant son chemin avec la syntaxe relative/file/path.py::test_func. Par exemple:

pytest test/test_foo.py::test_bar

Vive les plugins

Pytest a une grosse communauté de plugins, il suffit de chercher sur google “pytest + techno” pour avoir tout de suite des helpers qui popent.

Ceux que j’utilise très souvent:

pytest-pythonpath :

Permet d’avoir dans son conf file python_paths = chemins qui seront ajoutés au PYTHON PATH:

Ex:

[pytest]
python_paths =
    .
    libs

pytest-flake8 permet de lancer le linter flake8 pendant les tests et de considérer son échec comme un test qui foire. En plus flake8 peut mettre sa config dans les mêmes fichiers que pytest donc j’ai souvent ça:

[flake8]
exclude = doc,build,.tox,.git,__pycache__,build # ignorer les dossiers inutiles
max-complexity = 10 # verifier que le code n'est pas trop complexe
max-line-length = 80 # pep8 for ever, mais noqa peut servir parfois

Après j’utilise souvent tox, donc ce plugin n’est plus aussi utile qu’avant.

pytest-django qui ajoute des setup et tear down avec la base de données Django, fourni des fixtures pour le client de test django et permet de configurer DJANGO_SETTINGS_MODULE dans son fichier ini.

pytest-asyncio qui permet de gérer la loop, utiliser await dans les tests, etc.

Gérer ses fixtures

Le système de fixtures est une des choses qui rend pytest si cool, particulièrement parce qu’on peut être très précis dans ce qu’on charge. Mais des fois on veut les fixtures pour tout le monde, ou tout un module. autouse fait exactement ça:

@pytest.fixture(autouse=True, scope="module")
def ma_fixture():
    return foo()

Et cette fixture sera instanciée une seule fois pour tout le module. On peut aussi avoir un score de session (une seule fois par lancement de pytest) ou de class (une fois par classe).

Si vous avez besoin de lancer un code avant toute session de tests, par exemple pour vous définir des fixtures qui sont dispo dans tous les tests, il suffit de le mettre dans un fichier conftest.py à la racine de vos tests. Ce fichier est automatiquement détecté par pytest, et lancé avant toute chose. Il permet également de faire des hooks complexes, créer ses propres plugins, etc. Mais je l’utilise surtout pour faire des fixtures globales et m’éviter de les importer.

Error happened! 0 - count(): Argument #1 ($value) must be of type Countable|array, null given In: /var/www/ecirtam.net/autoblogs/autoblogs/autoblog.php:428 http://ecirtam.net/autoblogs/autoblogs/sametmaxcom_a844ada43a979e3b1395ab9acb6afafb84340999/?49 #0 /var/www/ecirtam.net/autoblogs/autoblogs/autoblog.php(999): VroumVroum_Blog->update() #1 /var/www/ecirtam.net/autoblogs/autoblogs/sametmaxcom_a844ada43a979e3b1395ab9acb6afafb84340999/index.php(1): require_once('...') #2 {main}