PROJET AUTOBLOG


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

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

⇐ retour index

Mon prompt bash est tout cassé ! 23

jeudi 14 janvier 2016 à 10:43

Ça m’était déjà arrivé plusieurs fois après avoir ajouté mon env virtuel et ma branch git dans mon prompt : soudainement il se met à faire n’importe quoi. Des mixes de caractères, des sauts de ligne qui se font pas, la fusion de la ligne de commande sur elle-même.

Inutilisable.

Aujourd’hui plutôt que de subir le problème, j’ai cherché une solution, et pouf : quand on utilise des couleurs dans son prompt, il faut entourer tout le balisage de [].

Mais le balisage qui colore le prompt est composé de séquences d’échappements, qui contiennent aussi [], donc il faut mettre des anti-slash.

Du coup on passe de ça :

export PS1="\[\033[01;34m\]\$(basename '$VIRTUAL_ENV')\e[0m $PS1"

à :

export PS1="\[\033[01;34m\]\$(basename '$VIRTUAL_ENV')[\e[0m] $PS1"

à la solution qui marche :

export PS1="\[\033[01;34m\]\$(basename '$VIRTUAL_ENV')\[\e[0m\] $PS1"

Évidemment à appliquer à tous les codes d’échappement chelou qu’on a réparti un peu partout.

J’ai un tampon prêt à tirer pour le premier qui me parle de zsh.

En Python, les threads et l’asyncio s’utilisent ensemble 8

mercredi 13 janvier 2016 à 13:11

En Python, les threads et l’asyncio s’utilisent ensemble

Je vois beaucoup dans les tutos ici et là des gens qui opposent asyncio avec l’ancienne manière de faire de l’IO non bloquante : les threads.

C’est une erreur : les deux méthodes ne sont pas opposées, elles sont complémentaires.

Faire des requêtes pendant que ça bloque

En effet, asyncio ne peut être non bloquant que sur le réseau : ça ne gère pas l’IO sur les fichiers. Par ailleurs, toute opération CPU bloque également la boucle d’évènement.

C’est très bien de ne pas bloquer sur le réseau, mais encore faut-il pouvoir faire la requête réseau.

Si votre programme est bloqué à attendre une compression zip qui dure 3 secondes, pendant ce temps, les opérations réseaux déjà lancées tournent bien.

MAIS IL N’EN LANCERA PAS DE NOUVELLES.

Pendant 3 secondes, aucune nouvelle requête ne sera faite puisque le programme ne fait qu’une chose : ziper. Ca marche pour d’autres choses hein : copie de fichier, gros calcul matheux, traverser une grande liste, etc.

Donc si vous avez fini toutes vos requêtes à la seconde 1, pendant 2 secondes, votre programme n’est pas utilisé à son plein potentiel.

Les threads ne permettent pas d’avancer plus vite, mais ils permettent de faire 2 travaux en parallèle. Par exemple, de lancer pendant ces 2 secondes des requêtes supplémentaires sur le réseau.

Asyncio a de l’overhead

On a vendu asyncio comme plus léger que les threads. Ce n’est pas tout à fait exact. asyncio a les avantages suivants :

Mais si on a quelques threads, le changement de contexte entre les threads est moins important que ce que coûte asyncio à faire tourner.

Pour certains travaux où le coût d’une opération réseau est faible, mais que cumulativement toutes les opérations ralentissent votre programme, un thread sera plus performant.

Par exemple, beaucoup d’opérations sur les bases de données tombent dans cette catégorie, à moins d’avoir des très longues requêtes.

Dans ce cas, avoir un thread dédié aux opérations de la base de données peut être une bonne décision.

Quoi faire ?

Si vous avez des opérations sur des fichiers ou de grosses opérations CPU, les faire travailler dans un thread peut booster votre programme. Ca tombe bien il y a une lib pour ça.

Si vous avez beaucoup de petites opérations réseau, les grouper, dans un thread à part, peut booster votre programme.

Et asyncio pour le reste, par exemple des requêtes HTTPs, DNS, SMTP, FTP, SSH, etc.

On peut donc copieusement utiliser les deux en parallèle. La bonne nouvelle, c’est que Guido a designé asyncio pour ça:

import asyncio
import aiohttp
 
async def main(loop):
 
    # ça c’est fait avec asyncio
    await aiohttp.get('http://bidule.com')
 
    # ça c’est fait dans un thread
    await loop.run_in_executor(None, gros_calcul, params)
 
loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))

Notez bien :

Bien entendu, chaque fois que vous ajoutez un mécanisme de concurrence, vous ajoutez de la complexité, donc ne le faites que si c’est nécessaire.

Commencez avec un programme synchrone simple. Si c’est trop lent, ajouter les threads ou l’asyncio, si ça ne suffit pas, utilisez les deux.

La communauté JS est actuellement une machine à créer de la dette technique 82   Recently updated !

mardi 12 janvier 2016 à 13:45

Vous savez, quand on ne brule pas un Troll, ses blessures se soignent rapidement, et il attaque à nouveau.

Et vous savez également comme j’aime troller JS.

De plus, il y a quelque temps, je vous affirmais que NodeJS n’était pas mature.

Est-ce que l’écosystème JS a muri depuis ?

Et bien maintenant je crois qu’on a passé l’enfance, et qu’on est dans la phase de l’adolescence. Ca crie, ça bouge, ça a plein d’énergie, et ça mérite des baffes.

Je sais, je sais, je vais encore avoir une horde de fans boys qui aiment le typage mou et les champs de moustaches venir me dire que je devrais arrêter d’écrire, de coder et m’enfoncer la version imprimée de Wikipédia dans l’anus.

According to this, you're a hérétic

Comment on appelle l’adulation de quelque chose par une communauté en dépit de toute rationalité déjà ?

Mais dans l’histoire de JS, y a pas eu un moment qui ne méritait pas un bon article de ce genre. A croire que c’est volontaire.

En l’occurrence, j’ai eu envie d’écrire cet article à la suite de plusieurs évènements successifs:

Homme se servant du whisky

Laissez-moi reprendre un peu de force pour la suite

Donc, reprenons.

NodeJS est toujours splitté entre 3 versions : Node, Io.JS et convergence.

Il y a plus de frameworks front end que jamais : Angular, React, Amber, Backbone, Polymer, ExtJS, Aurelia, Durandal, Knockout, Mithril, MarionetteJS, Vue.js, Meteor, etc. Et je ne liste que les plus connus, car la liste est interminable.

Ils ont tous des versions différentes, des addons (qui ont des versions et des dépendances), des docs et tutos répartis un peu partout..

Par dessus ça, on rajoute les langages qui compilent vers du JS qui eux aussi se multiplient comme les gremlins mouillés: Coffeescript, Dart, GWT, Closure, Haxe, Elm, TypeScript, Brython, Skulpt, PyJS, etc. Vous voulez, un listing complet ? Attention ça pique les yeux.

En clair, la seule chose que les gens aiment autant que de pallier l’absence de library standard de JS est de pallier la syntaxe de JS.

The 5 steps of software development

A cela s’ajoute le problème que visiblement les devs JS et le reste du monde n’en sont pas à la même phase. Ils en sont toujours au déni.

Mais on ne peut pas blâmer uniquement le langage. La communauté JS a pris la modularité tellement à l’extrême qu’aucune solution standard ne s’est démarquée pour rien : outils de build, libs de tests, solutions de routing, toolings fonctionnels, et même packages managers…

Même à l’intérieur d’un écosystème, c’est les poupées russes. Par exemple React peut être accompagné d’un pattern que Facebook appelle Flux. C’est du MVC monodirectionnel. Les modèles sont immutables. Le contrôleur est à base d’évènements. Les vues sont gérées par des widgets React. Rien de fou, mais ça faisait pas assez innovant alors ils ont inventé un nouveau nom.

Bref, ils ont leur propre implémentation, mais même la référence n’a pas gagné la guerre. Non, en JS, ça a déclenché immédiatement un concours de celui qui pisse le plus loin et vous pouvez (devez ?) choisir entre : Flux, redux, alt, reflux, flummox, fluxible, fluxxor, marty.js, fynx, MacFly, DeLorean.js, fluxify, fluxury, exim, fluxtore, Redx, fluxx. Les noms ne sont pas une tentative d’humour de ma part.

Ce qui donne les comments du genre :

What a wonderful example of the paradox of choice!

No wonder that it’s easier to get started with Meteor + React, than with Flux + React.

Pour rappel, Meteor est le truc le plus expérimental qui existe en termes de stack techno à l’heure actuelle.

Évidemment tous ces projets ont une documentation succincte, une durée de vie aléatoire, et on peut déjà lire des trucs comme :

Flummox 4.0 will likely be the last major release. Use Redux instead.

The future starts now

Ton projet

Et ils ne sont pas compatibles entre eux. Et en fait ils ne font pas exactement la même chose :

how does redux “replace” flummox, exactly? Seems like they have two very different approaches

Je vous mets les comments car je sais que vous n’avez pas le temps d’aller lire, et encore moins d’étudier chacun de ses projets pour décider duquel utiliser, déjà qu’il faut apprendre React… A vous ne saviez pas ce qu’était React ? Mais vous êtes à la bourre dites donc !

Rassurez-vous, choisir ce genre de techno a seulement un impact sur tout le code front de votre projet. C’est tout.

Mais les outils s’améliorent, et JS est de plus en plus facile à coder. Pas vrai ? Pas vrai ?

On a créé un robot qui adore jour du piano, et on lui a mis des moufles

L’avancée technique ne veut pas forcément dire que la vie est plus belle

Nope.

React fait ramer misérablement la console de debug de Firefox.

Les préprocesseurs ont tout envahi, et si vous choisissez 4 libs, l’un sera en ES6, l’autre en typescript et la troisième en Dart. Et il faut un setup de connard pour debug du code de préprocesseur confortablement : détecteur de changement, builder, injecteur de code, source mapper…

Les frameworks comme Angular ou React ont une gestion d’erreur bien à eux, qui affichent des messages chelous.

Homme transpercé au torax par un tuyau

Pourquoi ça marche pas ? Ben…

L’installation est devenue un enfer. Entre les dépendances dépréciées, les libs incompatibles, les différents outils de build, et les options de config et les plugins, c’est une merde incommensurable. Plusieurs standards d’installeurs (et outils joints) se tirent la bourre : AMD, CommonJS et Harmony. Vous vous souvenez du temps ou on copiait juste jQuery dans le répertoire static ?

Attendez, avec Webassembly on pourra même plus faire “read source”.

Donc JS…

On peut faire plus de choses qu’avant. De manière plus propre (enfin propre, on parle de JS là…).

Mais l’écosystème, c’est le bordel général, l’anarchie totale, et ça continue d’avancer, en laissant tout le reste derrière.

Les projets JS s’accumulent, de freelances en SS2I qui se pointent, codent ou (surtout) recodent, et repartent en laissant un projet qu’il sera imbuvable à reprendre, déprécié avant même d’être terminé, non documenté, non testé.

Un projet jetable.

Judge dread regarde bruler

Ca vallait le coup de quitter PHP

Le bulletin sécu : https pour 0bin et leak de mots de passe 18

dimanche 10 janvier 2016 à 13:42

Quand letsencrypt est passé live, on m’a gentiment signalé qu’on avait plus d’excuses pour faire tourner 0bin en clair.

Bon, soit.

J’ai mis en place ça hier à titre de test : https://0bin.net/.

Pour le moment je vais pas faire de redirection car j’attends de voir si le truc tient.

La bonne nouvelle, c’est que comme l’installation est juste nginx + zerobin, il n’y a pas eut grand chose à faire : lancer un script, le laisser nous identifier et installer les dependances pour qu’il génère le certificat et faire pointer le dit certificat par nginx.

La moins bonne nouvelle c’est que notre archi pour sametmax.com et indexerror.net est basé sur client => varnish => nginx => worker => site.

Il faut donc mettre le certif au niveau de varnish.

Mais comme vous vous en doutez bien, il fallait que ça couille : support de https est un truc récent sur varnish et notre version ne le supporte pas. Donc il reste à :

Oh, du boulot en plus, je ne m’y attendais tellement pas…

Merci à tous ceux qui ont proposé et fourni de l’aide néanmoins. C’est cool d’avoir du soutien parmi ses lecteurs.

Pendant ce temps, et ça n’a rien à voir, un lecteur s’est amusé à brute forcer des hashs de mots de passe qu’on avait leakés connement et a trouvé celui de max au bout de quelques jours. Il nous a gentiment envoyé le résultat de ses recherches par mail. Ce n’est pas ironique, hein. J’apprécie que quand quelqu’un trouve que tu es à poil il te le fasse savoir avec précision et honnêteté.

Du coup va falloir aussi changer tous les mots de passe du blog et de indexerror.

Comme ce n’est pas une question de sécurité nationale, je ne suis pas en mode bersek à vouloir faire ça dans la minute, mais sachez-le : changez vos mots de passe à l’occasion. Personne ne va violer votre sœur demain si vous ne le faites pas, mais mieux vaut prévenir que guérir.

Oh, du boulot en plus, je ne m’y attendais tellement pas…

Desactiver la validation des mots de passe en mode DEBUG sous Django 3

vendredi 8 janvier 2016 à 11:29

Django 1.9 rajoute la validation de “sécurité” des mots de passe comme corde à son arc.

Personnellement je trouve ça naze.

Je suis pour permettre aux utilisateurs de mettre le password qu’ils veulent, même tout pourri. De toute façon les gens qui ne font pas attention à leur sécurité ne vont jamais se souvenir du mot de passe compliqué et faire un « j’ai oublié mon mot de passe » à chaque fois.

Pire, la complexité ajoutée va faire fuir les nouveaux utilisateurs qui ne vont pas vouloir se faire chier à remplir le formulaire. Ou alors ils vont faire « login with facebook ».

Mais le plus naze dans tout ça c’est que la validation est tout ou rien : on peut pas mettre de la validation juste pour les comptes admin par exemple. Ce qui aurait du sens.

Alors, oui à la mise en oeuvre d’un indicateur de force de mot de passe, mais pas un refus catégorique de s’inscrire comme le système actuel le fait.

Dans tous les cas, vous voudrez au moins le désactiver en mode DEBUG car devoir taper un mot de passe compliqué en dev sur votre machine en local pour accéder à une base de données sqlite de test, c’est relou.

Car oui, ./manage.py createsuperuser refuse votre password si il n’est pas “sécurisé” par défaut. En prod, ça a du sens, mais quand je veux tester une merde sur mon laptop, “admin/admin” est généralement ce je veux.

Donc:

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
        'OPTIONS': {
            'min_length': 9,
        }
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]
 
if DEBUG:
    AUTH_PASSWORD_VALIDATORS = []

Enfin, franchement, un validateur de mot de passe basé sur la présence de chiffres. Sérieux ? On a des validateurs basés sur une entropie générale depuis longtemps.