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...

Travailler via des start up éphémères

lundi 10 mars 2014 à 21:30

Petite correspondance à la gare d’Austerlitz. Il fait beau, des ados massacrent joyeusement “No woman, no cry” sur le piano en libre service de la station, et ça me met de très bonne humeur. J’ai rendez-vous avez Cortex, dont vous n’avez pas entendu parler depuis longtemps, pour un verre en compagnie du Stégosaure en bois du parc du musée d’histoire naturelle afin de passer le temps.

On se raconte qui et quoi. Comment va machin, est-ce que tu as vu le nouveau joujou truc ?

Et puis ça parle boulot, parce qu’on fait ce qu’on fait car on aime le faire, et la passion, c’est plus ou moins ce qui nous réunit.

Il m’explique que depuis quelques temps, il a un nouveau concept de travail : les start up éphémères.

On lui confie des missions, généralement des trucs assez coton, car cortex est un spécialiste. Il ne fait que les trucs qui sont trop durs pour les autres. Si vous pouvez le faire, ça ne l’intéresse pas. Une fois qu’il a accepté, il met sur place sa A-team en cherchant des profils de dev qui correspondent exactement au besoin, et il lance la prog en mode commando.

Il loue quelques milliers d’euros une grande maison, un truc sexy dans lequel on a envie de mettre des filles en bikini ou faire un bbq avec 50 membres de sa famille. Bonne connexion internet required. Il rassemble tout le monde, et ça devient le dortoir de l’équipe pour 2 jours ou 2 mois, le temps de finir la mission impossible.

Ensuite il livre, il se fait payer l’équivalent de votre salaire annuel, il le dépense, et il recommence.

Il crée sa start up pour quelques semaines, dans un joli cadre, sur un projet sympa. C’est cool. C’est fun. Et c’est en France. Comme quoi, Hollywood n’a pas le monopole des hackers branchés.

flattr this!

Faire manger du datetime à JSON en Python

dimanche 9 mars 2014 à 21:32

La guerre de la sérialisation a plus ou moins été gagnée par JSON. Le XML est relégué aux documents très riches et aux systèmes legacy. Le YML est cantonné a des niches (et en plus souvent des niches en Ruby, c’est dire !). Et les formats binaires, sont gardés pour les besoins de perf. Le reste, c’est du JSON, du JSON et du JSON.

Seulement le JSON ne permet pas de sauvegarder des dates, seulement des chaînes, des entiers, des booléens et null. Heureusement on peut créer son propre dialecte au dessus de JSON pour y remédier, mais il faut avoir un un parseur qui le gère.

En Python on peut créer sa propre classe d’encodeur et décodeur de JSON et donc techniquement ajouter n’importe quel type.

Voici une recette pour en créer un qui gère le type datetime de manière transparente :

import re
import json
 
from datetime import datetime
 
# On hérite simplement de l'encodeur de base pour faire son propre encodeur
class JSONEncoder(json.JSONEncoder):
 
    # Cette méthode est appelée pour serialiser les objets en JSON
    def default(self, obj):
        # Si l'objet est de type datetime, on retourne une chaîne formatée
        # représentant l'instant de manière classique
        # ex: "2014-03-09 19:51:32.7689"
        if isinstance(obj, datetime):
            return obj.strftime('%Y-%m-%d %H:%M:%S.%f')
        return json.JSONEncoder.default(self, obj)
 
 
# On fait l'opération exactement inverse pour le décodeur
class JSONDecoder(json.JSONDecoder):
 
 
    # On écrase la méthode qui permet de décoder les paires clé / valeur
    # du format JSON afin que chaque valeur passe par notre moulinette
    def object_pairs_hook(self, obj):
        return dict((k, self.decode_on_match(v)) for k, v in obj)
 
 
    # notre moulinette
    def decode_on_match(self, obj):
 
        # une petite regex permet de savoir si la chaine est une date
        # sérialisée selon notre format précédent
        match = re.search(r'\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{6}', unicode(obj))
        # si oui, on parse et on retourne le datetime
        if match:
            return datetime.strptime(match.string, self.datetime_format)
 
        # sinon on retourne l'objet tel quel
        return obj
 
# On se fait des raccourcis pour loader et dumper le json
 
def json_dumps(data):
    return JSONEncoder().encode(data)
 
 
def json_loads(string):
    return JSONDecoder().decode(string)

Usage :

>>> res = json_dumps({'test': datetime(2000, 1, 1, 1, 1, 1), 'autre': [True, 1]})
>>> print(type(res), res)
(<type 'str'>, '{"test": "2000-01-01 01:01:01.000000", "autre": [true, 1]}')
>>> res = json_loads(res)
>>> print(type(res), res)
(<type 'dict'>, {u'test': u'2000-01-01 01:01:01.000000', u'autre': [True, 1]})

Minibelt contient une version un peu plus élaborée de ce code qui prend en compte les types date, time et timedelta ainsi que pas mal d’options de configuration.

flattr this!

Configurer un outil de merge pour git sous Windows

dimanche 9 mars 2014 à 00:04

Si vous utilisez msysgit, il n’y a pas d’outil pratique préinstallé pour gérer ce qui suit un git mergetool. Le plus simple à configurer est kdiff3. Il suffit de le télécharger et installer, puis de rajouter ceci dans votre fichier .gitconfig :

[diff]
    tool = kdiff3
	keepBackup = false
	prompt = false
[merge]
    tool = kdiff3
	keepBackup = false
	prompt = false
[mergetool "kdiff3"]
    path = C:/Program Files (x86)/KDiff3/kdiff3.exe
    trustExitCode = false

Remplacez “C:/Program Files (x86)/KDiff3/kdiff3.exe” par le bon chemin selon votre système, bien entendu.

kdiff3 a tendance à laisser trainer des fichiers *.orig après le merge, et ça peut se régler dans Configure/Options > Directory Merge > Backup Files (*.orig).

Ainsi votre prochain merge ouvrira tranquilement kdiff3 pour chaque conflit.

flattr this!

One myth down, pass it around

vendredi 7 mars 2014 à 15:34

Elle existe. Je l’ai rencontrée.

On avait demandé un coup de main à des amis pour des travaux, et elle avait proposé de venir. L’ambiance était plutôt poussière et transpiration en mode vêtement de clodo, alors quand elle s’est pointé avec des talons hauts et une bouteille de rosé, on a un peu tiqué.

Mais bon, mon coloc me la présente comme une copine, et c’était le moment de faire une pause de toute façon, alors pourquoi se prendre la tête ? Et puis il n’y a jamais assez de jolies rouquines sur les chantiers.

Assez rapidement on se rend compte qu’elle est complètement déchirée et n’a pas vraiment compris le principe du mot “travaux”. Elle demande un tire-bouchon, mais y en pas dans la boîte à outil. Elle a l’air vraiment déçue, alors j’entreprends de l’ouvrir à la savate.

Pour ceux qui ne connaissent pas cette technique de vieux sioux alcoolique, ça consiste à mettre la bouteille dans une chaussure de manière à ce que son cul touche la semelle côté talon, et ensuite taper l’extérieur du dit talon contre un mur jusqu’à ce que le bouchon sorte, ce qui peut prendre quelques minutes.

C’est fatiguant, et ça secoue méchamment le vin, donc je ne recommande pas ça à la soirée de monsieur Duran.

Bref, j’arrive avec le bouchon à moitié sorti, ses yeux se mettent à briller. J’explique que je vais l’ouvrir dans les chiottes parce que j’ai peur d’en mettre partout. J’entre, elle entre avec moi et et ferme la porte.

Je précise que je ne la connais toujours pas. En fait, je ne sais même pas comment elle s’appelle.

Elle se penche vers moi pour me rouler une pelle, puis recule et me demande :

“Attend, t’es venu avec qui déjà ?”

Prise de conscience.

“La bouteille.”

Je l’ouvre, on sort. Elle est déjà en train d’enlacer un autre pote. Dans la seconde. La seconde, je vous dis.

Qui est un peu gêné parce que sa copine à lui est à approximativement 3 mètres en train d’halluciner.

Notre personnage principal va donc faire du body-body avec tous les mecs présents en environ 15 minutes, puis, réalisant que personne n’étaient vraiment chauds, s’allonge sur le canapé, et s’endort pour le reste de la soirée.

Mon coloc m’expliquera plus tard :

“Elle est gentille mais elle peut rapidement te flinguer une soirée. Elle va pas faire gaffe aux couples et ça peut vite partir en fight. Par contre si tu t’ennuies ce soir…”

“Mais pourquoi tu l’as invité aujourd’hui ?”

“Je sais pas, elle a proposé, je me suis dis, plus on a de bras…”

flattr this!

Un petit goût de meteor.js en Python

jeudi 6 mars 2014 à 11:37

Je n’ai jamais caché ma jalousie envers les codeurs Javascript sous meteor.js. C’est à mon sens la techno la plus révolutionnaire en matière de dev Web depuis l’invention des frameworks HTTP.

Ca permet notamment de faire du PUB/SUB entre le navigateur et le serveur. C’est à dire qu’un navigateur déclenche un événement, le serveur le reçoit, et tous les browsers abonnés le reçoivent aussi. Du coup, on modifie une page, toutes les autres pages sont modifiées en temps réel.

Dommage que ce soit codé dans un langage pourri.

Heureusement depuis quelques temps, un standard est en train d’émerger autour du RPC et PUB/SUB entre navigateurs et serveurs : WAMP. Il existe du coup des implémentations du protocole en plusieurs langages, donc une en Python avec autobahn.

Ca s’utilise ainsi : pip install autobahn.

Puis, un petit coup de Python :

import sys
 
from twisted.python import log
from twisted.internet import reactor
 
from autobahn.twisted.websocket import listenWS
 
from autobahn.wamp1.protocol import WampServerFactory, WampServerProtocol
 
 
class MyPubSubServerProtocol(WampServerProtocol):
    def onSessionOpen(self):
        # On choisit un namespace pour enregistrer ses events PUB/SUB
        self.registerForPubSub("http://example.com/events/bam")
 
if __name__ == '__main__':
   # on lance notre serveur avec moult verbosité
   log.startLogging(sys.stdout)
   wampFactory = WampServerFactory("ws://127.0.0.1:9000", debugWamp=True)
   wampFactory.protocol = MyPubSubServerProtocol
   listenWS(wampFactory)
   reactor.run()

On lance le serveur directement :

python votre_script.py

Côté client (pas besoin de serveur, on peut l’ouvrir dans le browser cash pistache) :

<!DOCTYPE html>
<html>
  <head>
    <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
    <script src="https://raw.github.com/tavendo/AutobahnPython/master/examples/twisted/wamp1/pubsub/simple/example1/autobahn.min.js"></script>
    <script type="text/javascript">
 
    $(function(){
        ab.connect("ws://localhost:9000", function(session) {
 
            $('#foo').click(function(){
                // au clic sur le bouton, on envoit un evenement BAM
                session.publish('http://example.com/events/bam', ['bam']);
 
                // On ajoute bam à la liste en local car le publisher ne
                // reçoit pas ses propres events
                $('#doh').append('<li>bam</li>');
            });
 
            session.subscribe('http://example.com/events/bam', function(topic, evt){
                // on s'inscrit pour recevoir l'event quand il est
                // déclenché. Ceci marchera dans tout autre tab que celui
                // qui a déclenché l'event
                $('#doh').append('<li>bam</li>');
            });
        })
 
    });
 
    </script>
 
</head>
 
<body>
 
<!-- Notre liste qui va se remplir de bam ! -->
<ul id="doh"></ul>
<button id="foo" value="Bam">Bam</button>
 
</body>
</html>

Ce qui ce passe, c’est que quand j’appuie sur le bouton “Bam”, ça envoit un événement Bam au serveur via Websocket, qui propage l’événement à tous les clients. Donc tous les tabs ouverts sur cette page récupèrent l’événement et peuvent y réagir. Ici, les deux pages sont mises à jour en simultané.

Mise à jour de deux pages web en simultané avec autobahn

Chez moi ça marche

Bien entendu, ceci est un exemple très basique fait pour vous donner un avant goût de la techno. D’ailleurs, meteor.js, c’est bien plus que du PUB/SUB. Il y a de la gestion de la deco, la synchro de la base côté client, le hot push de code, etc. Ils ont fait un vrai travail de fond sur les problématiques concrètes.

Donc on en est encore loin, surtout que même leur techno est toujours expérimentale. Mais on a enfin de quoi rattraper le temps perdu. Et avec asyncio, îl n’y aura même pas besoin de dépendre de twisted pour ce faire. 2014 va être trop fun !

flattr this!

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/?108 #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}