Radar Python francophone

[ccomb] PyCon Fr 2010 ... 01/09/2010
PyCon Fr 2010

Le week-end dernier avait lieu PyCon FR, la rencontre annuelle sur Python en France, organisée depuis 4 ans par l'afpy et qui consiste en 2 jours de conférences et ateliers à la Cité des Sciences.

Voici un petit résumé de l'événement.

Fréquentation

On partait avec deux gros handicaps : la date, fin août, ne garantissait pas que tout le monde soit rentré de vacances. De plus la communication n'a pas été très bonne. Malgré tout, dès le samedi matin la salle (L'Agora du Carrefour numérique) était quasi pleine, et la fréquentation n'a pas baissé jusqu'au dimanche 18h, où les gens n'avaient manifestement pas envie de partir. Un petit sondage le dimanche matin a montré qu'une majorité de visiteurs s'était déplacé de province.

L'événement a été soutenu par 10 sponsors, qu'on remercie une nouvelle fois :

Tout a été enregistré par Ubicast et sera disponible en ligne. Le site web a été géré par Logilab, grâce à Cubicweb.

Tendances

Python

Le Web : le développement web est comme toujours un sujet majeur en Python. Serveur WSGI haute performance, CMS orienté sémantique, CMS sur mesure, CMS qui stocke en Git, nombreux frameworks web, cloud computing, réseau social distribué, le sujet était vaste.

Calcul scientifique : deux conférences passionnantes sur le Machine Learning, le traitement des langues naturelles, l'analyse statistique, le calcul parallèle ou le multiprocessing, l'interfaçage avec C/C++.

Cloud et NoSQL : Une confirmation de la tendance de l'année dernière, avec des présentations parlant de MongoDB, itools.database (une DB versionnée), Google App Engine, SilverLining, MediaTemple, LibCloud, etc...

ERP : Une présentation de Tryton, un fork d'OpenERP, fait aussi par des belges, qui proposent également une version allégée minimale (Neso). La demande pour OpenERP est, paraît-il, monumentale.

On a regretté l'absence de Tarek Ziadé, obligé de rentrer d'urgence à Dijon, et qui aurait dû présenter son travail chez Mozilla : la réécriture de Mozilla Sync en Python. On a regretté aussi l'annulation de dernière minute d'une présentation sur Plone.

OSDC Fr 2010

En parlant de Plone, je serai à OSDC Fr les 9 et 10 octobre pour parler de Plone 4 qui vient de sortir, ainsi que d'une application permettant de déployer des démos d'applications web (Drupal, Plone, OpenERP, etc...).

[j-mad] Django Simple Captcha et tout devient si simple ... 31/08/2010

Comme d’habitude le mois d’aout fut une vraie folie. Et qui dit mois de folie dit, billet qui prennent du retard. Heureusement que j’ai pu tricher en publiant la première interview. (ben oui c’est beaucoup plus rapide de poser des questions que d’y répondre, enfin beaucoup plus rapide d’écrire les questions dans un mails quoi).

Du coup, je suis presque en retard pour la django app du mois. Et pour ne pas être en retard, j’ai choisi pour ce mois ci, une django app simple, mais très utile, django simple captcha (pour la petite histoire j’ai découverte cette app en testant django-tellafriend, une application dont il faudra que je vous parle également).

1- Où on le trouve, comment on l’installe, tout ça quoi (et la doc) ?

Alors on le trouve, tout simplement, sur la page google code qui lui est consacré. Pour l’installation,   c’est comme toujours du classique (ha ce que j’aimerais un jour, avoir une surprise à ce niveau là, pouvoir gouter à un peu de nouveauté… mais non, c’est toujours pareil.

Vous avez donc le choix entre :

  • easy_install
  • un tar.gz de la dernière release
  • un checkout de SVN

Dans tout les cas, il vous suffira une fois votre petite application installée, de la rajouter dans les INSTALLED_APP, de lancer un petit syncdb et magie… ça fonctionnera.

Enfin, si vous avez pensé à installer PIL, bien entendu.

La doc elle, est minimaliste mais plutôt claire et bien faite.

2- Mais au fait, à quoi ça sert ?

He ben mon cher ami, c’est indiqué dans le titre. C’est une application de captcha. Elle permet dans sa version de base de proposer trois méthodes de tests de l’utilisateur :
le très classique lettre dans le désordre
l’opération mathématique (toi aussi répond à 4+2)
le choix d’un mot, au hasard, dans un dictionnaire.

Et là, ou c’est vraiment le top avec cette petite app, c’est que si vous avez installé Flite, vous pourrez même avoir votre captcha en Text-so-speech, et vive l’accessibilité !!

3- Comment ça marche ?

En fait rien de plus simple, l’app fourni tout simplement un noueau type de Field a utiliser dans un formulaire.

Et oui, rien de plus simple.

On crée son formulaire, on rajouter un champ Captcha et quand le formulaire a été posté, on fait un joli is_valid() pour savoir si c’est bon.
Et au niveau de la configuration, les possibilités sont très complètes. On peut configurer le taux de bruit appliqué à l’image, les inclinaisons maximums appliqués aux lettres et aux chiffres, la font à utiliser ainsi que sa taille, les différentes couleurs, etc etc,

4- Mais encore

Ce qui est de bien avec cette app, c’est qu’en plus de penser à tout ce qui accessibilité, elle est bien pensé. Elle vous permet en effet de rajouter vos propres générateurs de tests. Il suffit de coder une petite fonction qui renverra un tuple contenant la question et sa réponse dans un tuple. Et le tour est joué.

Et ça c’est plutôt très sympa.

Dernière précision, la page google code contient un bouton flattr, si vous avez un compte flattr (cet excellent nouveau système de rétribution dont il faudra que je parle un jour, mais google est votre ami), n’hésitez pas à cliquer sur le bouton.

[Ohan] lancer gunicorn avec supervisord ... 31/08/2010
Après avoir mis en place une méthode pour lancer gunicorn avec runit, voici un second article pour lancer ce même gunicorn (qui poutre du poney, rappelons-le), mais avec un outil que je trouve à l’utilisation bien plus pratique : supervisord Pourquoi supervisord et pas runit ? Après l’avoir utilisé sans aucun soucis depuis quelques temps sur [...]
[Ohan] PyCon.fr 2010 : retour sur une conférence organisée par l’AFPY ... 30/08/2010
Cette édition de PyCon.fr était la deuxième à laquelle j’ai assisté. Elle s’est déroulée, comme l’année dernière, à la CyberBase de la Cité des Sciences à la Villette, Paris. Et comme l’année dernière, j’ai apporté ma maigre contribution à l’organisation sur place, aux côté des super-motivés de l’Association Francophone PYthon (liste non exhaustive : Christophe [...]
[ccomb] Debian, Ubuntu, dedibox v3 : deuxième round ... 16/08/2010

Influence de l'ext4 sur les performances

Debian

Un peu étonné des résultats d'avant-hier montrant Ubuntu largement à la traine par rapport à Debian, j'ai voulu vérifier les résultats en utilisant cette fois la même dedibox v3. J'ai donc relancé une fois le benchmark en Ubuntu 10.04 64bits, puis je l'ai réinstallée complètement en ext4 (dispo depuis peu à l'install dedibox).

L'apport de l'ext4 est ici nettement visible en écriture. Sinon les résultats sont assez proches.

/static/bench3/read.png/static/bench3/random_read.png/static/bench3/write.png
/static/bench3/random_write.png

Debian vainqueur par K.O.

J'ai ensuite réinstallé avec la Debian 5.0 Lenny proposé aussi par dedibox. Et là on retrouve bien la même différence qu'avant-hier, que je trouve énorme. Je n'ai pas encore eu le temps de creuser, il s'agit sûrement d'un réglage lors du montage, de la journalisation, du scheduler ou je ne sais quoi d'autre. En tout cas pour une installation par défaut c'est regrettable.

/static/bench5/read.png/static/bench5/random_read.png/static/bench5/write.png
/static/bench5/random_write.png

Vous me direz, oui, mais l'Ubuntu peut être installée directement en ext4, qui améliore pas mal. Qu'à cela ne tienne, comparons donc la vieille Debian 5.0 ext3 et la nouvelle Ubuntu 10.04 ext4. Là encore, la Debian est plus rapide, sauf en écriture pour les gros fichiers :

/static/bench6/read.png/static/bench6/random_read.png/static/bench6/write.png
/static/bench6/random_write.png

Et la prochaine Debian 6.0 ?

Pour finir, j'ai effectué la mise à jour en Debian 6.0 Squeeze, qui vient juste d'être gelée. Pour mémoire, l'upgrade en Debian 6.0 se déroule en gros comme ceci :

  • remplacer lenny par squeeze dans /etc/apt.sources.list
  • # aptitude update
  • # aptitude install apt aptitude dpkg
  • # aptitude full-upgrade
  • # upgrade-from-grub-legacy
  • # aptitude install linux-image-2.6-amd64
  • remplacer GRUB_DEFAULT=0 par GRUB_DEFAULT=2 dans /etc/default/grub
  • # upgrade-grub
  • # reboot
  • # aptitude remove --purge linux-image-2.6.32-bpo.4-amd64
  • Remettre GRUB_DEFAULT=0 dans /etc/default/grub
  • # upgrade-grub

Debian 5.0 et Debian 6.0 sont très proches, même si on note un léger avantage à la nouvelle version :

/static/bench7/read.png/static/bench7/random_read.png/static/bench7/write.png
/static/bench7/random_write.png

Et Debian 6.0 en ext4 ??

Ah mais vous voulez vraiment le beurre et l'argent du beurre... Bon ok. On lance le système de secours Dedibox, puis :

  • # sudo tune2fs -O extents,uninit_bg,dir_index /dev/sda1
  • # sudo tune2fs -O extents,uninit_bg,dir_index /dev/sda2
  • # sudo e2fsck -fDC0 /dev/sda1
  • # sudo e2fsck -fDC0 /dev/sda2
  • Puis remplacer ext3 par ext4 dans /etc/fstab.
  • Par précaution j'ai aussi fait un update-grub après avoir chrooté la racine, puis monté /boot, /proc et /sys, mais je pense que c'était inutile.

Ensuite on redémarre, et voici ce que ça donne. Comme pour l'Ubuntu, le système de fichiers ext4 améliore surtout les performances en écriture. Mais l'amélioration est encore plus spectaculaire, car on gagne ici 70% au lieu de 60% (sur la moyenne) dans le cas de l'Ubuntu :

/static/bench8/read.png/static/bench8/random_read.png/static/bench8/write.png
/static/bench8/random_write.png

La conclusion, c'est que Debian fait toujours du bon boulot... Je ne pense pas que le problème vienne spécialement des Dedibox, car je retrouve la même forme sur mon portable en Ubuntu 64bits ext4.

Comparatif entre les disques durs Dedibox v1, v2, v3 :

Lors des tests précédents j'ai lancé simplement iozone -a, qui utilise les buffers du noyau lors des transferts. C'est pour cette raison qu'on obtient des taux énormes, de l'ordre de 1 ou 2 Go/s. C'est un bon test en conditions réelles car il fait intervenir aussi le CPU. Si on recommence la même chose en lançant plutôt iozone -aI, on obtient le taux de transfert réel du disque dur, plus utile pour tester vraiment le matériel. C'est le même genre de différence qu'entre hdparm -t et hdparm -T. Voici donc la comparaison entre les trois dedibox. Pour la dedibox v1 j'ai limité le nombre de tests, faudrait pas la fatiguer, ni qu'elle meure avant la migration... :)

La surprise, c'est que le disque le plus lent est celui de la dedibox v2. Quant à la v3, elle reste encore la plus rapide. J'ai aussi effectué le test en ext4, et là encore on note une belle amélioration des performances grâce à l'ext4.

/static/bench4/read.png/static/bench4/random_read.png/static/bench4/write.png
/static/bench4/random_write.png
[ccomb] Benchmark filesystem dedibox v1, v2, v3, sur Ubuntu et Debian ... 14/08/2010
Debian

J'ai commandé récemment trois dedibox v3 : deux pour l'AFPY, une pour Gorfou, afin de remplacer les anciennes. Cette dedibox v3 est sortie il y a peu, et semble à première vue être intéressante : pour deux fois moins cher, on a plus de mémoire vive, plus d'espace disque, un CPU plus rapide, avec 64bits et virtualisation, et plus de bande passante. J'ai réalisé que j'avais accès aux trois générations de dedibox : les deux serveurs principaux AFPY et Gorfou sont des dedibox v1, et le serveur secondaire de l'AFPY, qui servait pour les buildbots, est une dedibox v2 (mise à disposition par Toonux).

J'en ai profité pour lancer un test de filesystem en utilisant iozone.

Voici les machines utilisées :

nom génération système archi syst. fichiers
py dedibox v1 Debian Lenny 5.0 32 buts ext3
cody dedibox v1 Ubuntu 10.04 Lucid 32 bits ext3
boa dedibox v2 Debian 5.0 Lenny 32 bits ext3
nouvelle cody dedibox v3 Ubuntu 10.04 Lucid 64 bits ext3
nouvelle boa dedibox v3 Ubuntu 10.04 Lucid 64 bits ext3
nouvelle py dedibox v3 Debian 6.0 Squeeze 64 bits ext3

J'ai juste lancé « iozone -a » (mode automatique) deux fois sur chaque serveur (1 seule fois sur cody).

Le résultat de iozone est un grand tableau de nombres illisible. Plutôt que d'ouvrir le résultat dans OpenOffice, j'ai trouvé que c'était une bonne occasion de jouer avec NumPy et Matplotlib pour extraire les données et tracer des résultats comparatifs en 3D.

Je tiens à signaler que les mesures n'ont pas été faites dans des conditions idéales, et que je n'ai pas cherché à modifier les options d'iozone. Si vous voulez comprendre les valeurs, reportez-vous à la doc d'iozone.

Voici les résultats :

Comparatif Dedibox V1 / V2 / V3

Lecture

En lecture, la dedibox v3 est la plus rapide des trois, il n'y a aucun doute.

/static/bench1/read.png/static/bench1/reread.png/static/bench1/random_read.png/static/bench1/bkwd_read.png/static/bench1/stride_read.png/static/bench1/fread.png
/static/bench1/freread.png

Écriture

En écriture, c'est un peu moins clair : la dedibox v3 est plus rapide dans 4 tests sur 6.

/static/bench1/write.png/static/bench1/rewrite.png/static/bench1/random_write.png/static/bench1/record_rewrite.png/static/bench1/fwrite.png
/static/bench1/frewrite.png

Comparatif Ubuntu / Debian

Voyons maintenant la différence entre Debian et Ubuntu. Ici les machines sont censées être les mêmes, sont toutes les deux vides et non utilisées, et sont installées avec les dernières versions de Debian 6.0 et Ubuntu 10.04. Les noyaux sont tous les deux des 2.6.32.

On note une très forte différence entre les deux : la machine sous Debian est beaucoup plus rapide.

Lecture

/static/bench2/read.png/static/bench2/reread.png/static/bench2/random_read.png/static/bench2/bkwd_read.png/static/bench2/stride_read.png/static/bench2/fread.png
/static/bench2/freread.png

Écriture

Bizzare, mais même constat, la dedibox sous Debian est en moyenne une fois et demi plus rapide que celle avec Ubuntu.

/static/bench2/write.png/static/bench2/rewrite.png/static/bench2/random_write.png/static/bench2/record_rewrite.png/static/bench2/fwrite.png
/static/bench2/frewrite.png

Je me garderai de faire des commentaires, vu les conditions dans lesquelles ces tests ont été réalisés, mais ça mériterait de creuser un peu...

Script d'extraction

Si vous voulez reproduire les grahiques, voici comment faire.

Il faut récupérer la sortie de « iozone -a » en ne gardant que le tableau, puis changer l'en-tête du tableau pour qu'il tienne sur une seule ligne, et sauver ça dans un fichier texte. Ensuite il faut installer Matplotlib 1.0. La version 0.99 fournie avec Ubuntu 10.04 ne convient pas, il faut compiler la version 1.0. Je vous laisse le doux plaisir de découvrir les dépendances à installer

$ virtualenv sandbox
$ sandbox/bin/pip install  install http://sourceforge.net/projects/matplotlib/files/matplotlib/matplotlib-1.0/matplotlib-1.0.0.tar.gz/download

Ensuite voici le script qui a permis d'extraire et tracer les données, que j'appelle bench.py :

#!/usr/bin/env python
# coding: utf-8
import sys
import pylab, numpy as np
from numpy import log2
from mpl_toolkits.mplot3d import axes3d

tests = {}

files = sys.argv[1:]
pylab_colors = ('r', 'g', 'b', 'y', 'm', 'y', 'k')
assert len(files) <= len(pylab_colors)
colors = dict([(f, pylab_colors[i]) for i, f in enumerate(files)])

for k, filename in enumerate(files):
    with open(filename) as f:
        tests[filename] = {}
        tests[filename]['titles'] = f.readline().split()[2:]
    tests[filename]['raw'] = np.loadtxt(filename, dtype=int, skiprows=1)
    for i, testname in enumerate(tests[filename]['titles']):
        tests[filename][testname] = {}
        data = tests[filename][testname]['data'] = np.zeros((20, 15))
        data[:] = np.nan
        raw = tests[filename]['raw']
        data[log2(raw[:,0]).astype(int), log2(raw[:,1]).astype(int)] = raw[:, i+2]
        data /= 1024.0
        tests[filename][testname]['mean'] = data[-np.isnan(data)].mean()
        tests[filename][testname]['max'] = data[-np.isnan(data)].max()


axes = {}
X, Y = np.mgrid[0:20,0:15]
for testname in tests.values()[0]['titles']:
    ax = axes3d.Axes3D(pylab.figure())
    ax.w_xaxis.set_ticks(range(3,21,2))
    ax.w_yaxis.set_ticks(range(2,15,2))
    ax.w_xaxis.set_ticklabels(2**np.arange(3,21,2))
    ax.w_yaxis.set_ticklabels(2**np.arange(2,15,2))
    ax.set_xlabel('kB')
    ax.set_ylabel('reclen')
    ax.set_zlabel('MB/s')
    means = dict([(filename, tests[filename][testname]['mean']) for filename in files])
    maxs = max([tests[filename][testname]['max'] for filename in files])
    ax.text(X.min(), 15, maxs, 'test: ' + testname, color='k')
    for i, filename in enumerate(sorted(means, key=lambda x:-means[x])):
        i+=1
        Z = tests[filename][testname]['data']
        c = colors[filename]
        ax.plot_wireframe(X, Y, Z, color=c)
        ax.text(X.min(), 15, maxs*(1-0.07*i),
                str(int(means[filename])) + " MB/s : " + filename, color=c)
    #pylab.gcf().set_size_inches(6,4)
    pylab.savefig(testname + '.png')

pylab.show()

Pour le lancer avec la nouvelle version de matplotlib, il suffit d'utiliser le Python de la sandbox. Le script prend en paramètres les fichiers contenant les résultats iozone

$ ./sandbox/bin/python bench.py resultat1.txt resultat2.txt resultat3.txt

Il est possible d'écrire un script beaucoup plus propre, mais je voulais juste m'obliger à le faire avec Numpy et Matplotlib et sans y passer trop de temps non plus. Notez qu'une des lignes du script utilise une affectation grâce au Fancy Indexing de Numpy:

data[log2(raw[:,0]).astype(int), log2(raw[:,1]).astype(int)] = raw[:, i+2]
[j-mad] Petit tour du coté des itertools, billet sans nucléaire dedans... ... 11/08/2010


Le module itertools est un module bien pratique auquel on ne pense pas assez souvent. En tout cas auquel, moi, je ne pense pas assez souvent. Et pourtant, il peut grandement simplifier pas mal de ligne de code, dans un bon nombre de situation. Il faut juste savoir que les fonctions qu’il propose existe.

Ce billet a donc 2 objectifs, vous faire découvrir les itertools (je ne vais pas lister toutes les fonctions juste celles dont je devrais me servir plus souvent et que j’oublie) et me permettre de ne pas oublier que je pourrais les utiliser.

Point important : Un certain nombre des itertools permettent de gérer les iterateur infinis, ce que ne permettent pas les fonctions ‘normales’ comme map par exemple (qui renvoie une sortie complétement calculée, ce qui est par définition impossible avec un iterateur infini).

Précision : les exemples de code sont ceux fournis par la doc officielle des itertools

itertools.chain (*iterables)

permet d’avoir un iterateur qui retourne tout les éléments du premier iterable passé en paramètre, puis du second, puis du troisième, etc etc… Bien pratique pour aérer son code.

def chain(*iterables):
# chain('ABC', 'DEF') --> A B C D E F
for it in iterables:
for element in it:
yield element

Depuis python 2.6, il existe une classmethod de chain, from_iterable(iterable) qui ne prend qu’un argument, un iterable contenant tout les iterables.

@classmethod
def from_iterable(iterables):
# chain.from_iterable(['ABC', 'DEF']) --> A B C D E F
for it in iterables:
for element in it:
yield element

itertools.compress(data, selectors)

compress n’est disponible qu’en python 2.7. Cette fonction retourne un iterateur contenant que uniquement les valeurs de data auxquelles correspondent un élément évalué à True dans le selectors. Compress s’arrête dès que data ou selectors est vide.

def compress(data, selectors):
# compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F
return (d for d, s in izip(data, selectors) if s)

itertools.count(start=0, step=1)

Cette fonction bien que présente depuis longtemps a droit à quelques modifications dans python 2.7. Count gagne en effet l’argument step et la possibilité d’itérer sur des arguments non integer.

def count(start=0, step=1):
# count(10) --> 10 11 12 13 14 ...
# count(2.5, 0.5) -> 3.5 3.0 4.5 ...
n = start
while True:
yield n
n += step

itertools.dropwhile(predicate, iterable)

Construit un iterateur qui ne renvoie aucun élément de l’iterable tant que le prédicat est vrai, ensuite, tout les éléments de l’iterable sont renvoyés

def dropwhile(predicate, iterable):
# dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1
iterable = iter(iterable)
for x in iterable:
if not predicate(x):
yield x
break
for x in iterable:
yield x

itertools.takewhile(predicate, iterable)

Construit un iterateur qui, tant que le prédicat est vrai, renvoie les éléments de l’iterable.

def takewhile(predicate, iterable):
# takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4
for x in iterable:
if predicate(x):
yield x
else:
break

itertools.ifilter(predicate, iterable) et itertools.ifilterfalse(predicate, iterable)

Construit un iterateur qui ne renvoie que les éléments pour lesquels le prédicat est respectivement True ou False. Si predicate est à None, l’iterateur renvoie les éléments respectivement True ou False.

def ifilter(predicate, iterable):
# ifilter(lambda x: x%2, range(10)) --> 1 3 5 7 9
if predicate is None:
predicate = bool
for x in iterable:
if predicate(x):
yield x

itertools.imap(function, *iterables)

Renvoie un iterateur qui applique function en utilisant les iterables comme argument. Si function est None, les arguments sont retournés sous la forme d’un tuple. Imap s’arrête lorsqu’elle atteint la fin du plus petit des iterables. Imap est utile lorsque l’on utilise des iterateur infinie qui provoque une erreur avec map.

def imap(function, *iterables):
# imap(pow, (2,3,10), (5,2,3)) --> 32 9 1000
iterables = map(iter, iterables)
while True:
args = [next(it) for it in iterables]
if function is None:
yield tuple(args)
else:
yield function(*args)

les autres i-versions des fonctions classiques.

Comme l’on trouve imap, il existe aussi izip, izip_longest et islice,

Parmi les autres fonctions il y a des fonctions de combinaisons, de calcul, de cycle, de grouby, mais celles là, vous les trouverez sur la doc officielle.

[j-mad] Django-websocket parce que sans chaussettes, le web, il pue un... ... 31/07/2010

Et oui, malgré la chaleur, malgré les vacances, la plage et l’appel de starcraft 2, malgré tout cela, je reste fidèle au poste et je publie une django app du mois. Bon ok, c’est le dernier jour du mois, mais je suis encore dans les clous.

Mais par contre, vu que c’est l’été, les vacances, je vais pour une fois parler d’une app qui est pour faire tout sauf de la prod. C’est une app toute jeune et qui en plus s’aventure dans un domaine encore très peu supportés dans les navigateurs (pour l’instant uniquement dans Chrome 4, Firefox 4 et Safari 5) , celui des websockets. C’est quoi une websocket vous allez me dire ? C’est un mécanisme qui apparaît dans HTML 5 et qui permet d’avoir un mécanisme de connexion persistante et bi directionnelle entre le serveur web et le browser de l’utilisateur. Trop cool vous allez me dire. Je ne puis qu’être d’accord avec vous. (pour plus d’infos sur les websockets vous pouvez aller lire la page wikipedia ou la norme W3C qui est plutôt facile à lire).

Django-websocket est donc une toute récente app (version 0,3 à l’heure ou j’écris ce billet) qui permet de commencer à s’amuser avec ces adorables websockets.

1- Où on le trouve, comment on l’installe, la doc.

Vous trouverez django-websocket sur sa page pypi ou sur sa page github. L’installation se fera donc soit :

  • avec easy_install
  • un git clone

Comme le code évolue pas mal et que de toute façon c’est pour l’instant plus une app pour tester et pas pour mettre en prod, moi, je vous conseillerais le git clone qui vous permettra d’avoir plus souvent une app à jour.

La documentation est plutôt bien fournie, claire et suffit pour démarrer. Le repository github permet d’avoir en plus les tests et une petite application example de echo.

2- Comment ça marche ?

En fait c’est vraiment super facile, il suffit d’utiliser deux décorateurs de vues soit :

  • require_websocket pour obliger la vue à fonctionner en websocket
  • accept_websocket si l’on veut permettre à la vue de fonctionner sans les websockets.

Ensuite il n’y a qu’un seul objet à utiliser request.websocket sur lequelle on pourra :

  • faire des attentes et récupérer un message quand il y en a un (wait)
  • vérifier si il y a des messages ( has_messages )
  • lire un message ( read )
  • envoyer un message ( send )
  • les utiliser comme un iterator (ce qui ferrait comme un wait dans une boucle avec la gestion en plus de la fermeture de la socket )

Petite précision, le serveur de développement de django n’est pas multithread, il n’est donc pas possible d’ouvrir deux requêtes concurrentes avec. L’app fourni donc une commande spéciale pour le runserver ( –multithreaded ) qui permet de contourner le problème.

3- Un petit Mad Exemple

Histoire de m’amuser un peu avec l’app, j’ai commis un petit exemple avec, en me basant sur le echo exemple. Mon exemple est tout con, vous entrez une chaine de caractère et je lance (grâce à restkit) une recherche google toute les 30 secondes sur la chaine de caractère. Les dix premiers résultats de la recherche sont ensuite affichés grâce à la websocket.

Vous pourrez trouver le code en question sur le tout nouveau repository bitbucket que j’ai du coup, crée pour l’occasion.

[No] Succès colossal pour le premier AFPYro National ... 29/07/2010

Hier soir, dans plusieurs villes de France, se déroulait le premier AFPYro National. Les amateurs du langage de programmation Python se retrouvaient régulièrement pour un apéro sympa, mais pour d'obscures raisons centralistes, cet apéro se déroulait exclusivement à Paris. En France. Il paraît.

Récemment, j'ai été chaleureusement convié à participer au premier AFPYro Palois.

Afpyro Vrai Sud

Très bonne ambiance, gens apparemment curieux du langage, de ses bonnes pratiques ; on s'était promis de se revoir, tout ça.

Et au détour d'une conversation sur IRC, voilà-t-y pas que l'idée surgit d'organiser un AFPYro - pas seulement à Pau - dans toute la France. La date retenue : le 28 juillet au soir. Bon j'avoue que cette date était loin de m'arranger, aussi je ne pouvais pas faire le déplacement à Pau. Et je n'avais pas le coeur à organiser un truc tout seul de mon côté, aussi je m'abstins. C'est ainsi qu'au quatre coins de l'hexagones (on ne se lasse pas de cette incongruité géométrique), se tint le premier AFPYro National : à Pau, Paris, Toulouse, Nice et Metz. Et peut-être ailleurs...

Et moi qui pensais que Python n'était pas répandu à Bayonne... Je me trompais.

Déjà, dans la ville, depuis quelques temps, je voyais bien que quelque chose était en train de se tramer... des tonnes de palettes de boissons diverses débarquaient chez les cafetiers, un imposant dispositif de sécurité se déployait... Des barrières fleurissaient un peu partout, pour protéger des massifs de fleurs ou des ronds-points.

Bref, du pas net.

Et j'ai eu l'heureuse surprise de voir, dès le milieu de la journée d'hier, une foule impressionnante de gens, portant l'uniforme. Haut blanc. Bas blanc. Ici ou là, un foulard rouge ou une écharpe (rouge aussi) autour de la taille.

Et c'est alors que j'ai compris... Des profondeurs d'on-ne-sait-z'où, ont débarqué une horde d'une centaine de milliers de Pythonistas, parés pour un AFPYro historique !

Vers les 22h, une énorme pétarade a retenti, et la foule en liesse a célébré le sacre du roi Léon, en chantant :

Ah Léon, Léon, Léon, roi de Bayonne, roi de Bayonne
Ah Léon, Léon, Léon, roi de Bayonne, roi du Python !

On m'a même raconté que Frédéric Beigbeder, juché sur le balcon de l'hôtel de ville, aurait lancé vers la foule des clés (en carton). J'ignore la symbolique de ce geste, mais je gage qu'un internaute saura me renseigner.

Concernant l'accoutrement des pythonistes, j'ai eu quelques informations. J'ai pu en questionner quelques uns qui trinquaient en bas de chez moi : le blanc symbolise bien évidemment les espaces, la tabulation : bref, les blancs que les codeurs en Python utilisent pour indenter leur code ; puisque l'indentation fait partie de la syntaxe. Et comme c'est la couleur blanche qui est choisie, on oublie pour un temps les trolls sur le choix "tabulation ou espaces" et on célèbre ensemble la pureté et la beauté du code.

Concernant le foulard rouge, il y a plusieurs versions discordantes :

  • Certains affirment que ce foulard a la couleur du rubis pour rendre hommage à cet autre langage de programmation : Ruby,
  • D'autres évoquent les tests unitaires qu'on se doit d'écrire avant le code, la couleur rouge est un avertissement : un code non testé est un code défectueux !
  • Pour un autre groupe, le rouge étant la couleur du communisme, c'est un hommage à notre bien aimé Dictateur Bénévole à Vie, Guido Van Rossum, qui guide notre communauté d'une main ferme vers la révolution Pythonnienne,
  • D'autres encore évoquent le foulard porté par Karaté Kid. Mais cette version a peu de crédibilité.

Toujours est-il que pendant toute la nuit des milliers - que dis-je - des centaines de milliers de passionnés de Python ont célébré leur langage favori dans les rues de Bayonne. Oh franchement ça faisait plaisir à voir, toute cette joie et cette allégresse !

Allez Alleeeeeez, les petits doigts il va falloir pythonneeeeeeeeeer !

[Afpy] Afpyro National de juillet 2010 ... 23/07/2010
Viendez, viendez nombreux à l'afpyro national de juillet le mercredi 28 juillet 2010 à 19h - Pau: au club d'échecs Henri IV 39 ter rue E. Guichenné 64000 PAU. - Paris: au Café Chéri(e) 44 bd de la Villette, 75019 Paris (FR). M°: Belleville /Colonel Fabien - Toulouse: Au Au Mulligans, 39 grand rue St michel 31000 Toulouse ligne B St michel - Nice: au Green King, et il est "quartier Saint Philippe, 06410 BIOT" (à sophia, face au Golf de Greenside). - Metz : Café Jeanne d'Arc Place Jeanne d'Arc 57000 Metz
[Afpy] Pycon Fr 2010 - Le programme est en ligne ... 22/07/2010
Pycon FR se déroulera les 28 et 29 août 2010 à la Cyberbase de la Villette à Paris
[Afpy] Pycon Fr 2010 - Appel à conférenciers ... 30/06/2010
Pycon FR se déroulera les 28 et 29 août 2010 à la Cyberbase de la Villette à Paris
[carlchenet] Redis, votre nouveau cache applicatif (GLMF) ... 29/06/2010
Suivez-moi sur Identi.ca : http://identi.ca/carlchenet Vos applications manquent de peps, que vous utilisiez ou non une base de données. Vous avez identifié des requêtes ou des résultats ré-utilisables qu’il est intéressant de conserver et pour lesquels regénérer un nouveau résultat n’est pas toujours pertinent selon le temps qui s’écoule entre deux sollicitations ? Redis est [...]
[Afpy] Sortie d'itws, CMS Open Source facile de prise en main ... 28/06/2010
Itaapy vient de sortir la version 1.0 d'itws, un outil de création de site web et extranet facile de prise en main.
[carlchenet] Qu’est-ce qu’un mainteneur Debian ? ... 25/06/2010
Suivez-moi sur identi.ca : http://identi.ca/carlchenet Pour fêter ma nomination au poste de mainteneur Debian, un petit billet explicatif sur ce titre et sa fonction s’impose. La notion de mainteneur Debian a été intégrée à Debian en 2007. Sera éligible un contributeur régulier au projet Debian qui maintient des paquets de l’archive officielle, paquets sponsorisés par un développeur Debian [...]
[j-mad] Django-improved-inlines, enrichissez facilement vos contenus e... ... 20/06/2010

La pluie ayant décidé d’être l’invité surprise du week-end, j’ai donc une bonne excuse pour ne pas aller prendre des coups de soleil à la plage mais rester bien tranquillement sur mon clavier. Autant donc en profiter pour vous parler de l’application django du mois, j’ai nommé django-improved-inlines. Oui, je sais, elle a un nom à rallonge. Django-improved-inlines est en fait une version légèrement dopé de django-inlines (d’où le improved) qui fait elle même parti du package django-basic-apps. Oui je sais, ça commence à faire un arbre généalogique digne d’une série américaine (ou du trône de fer).

1- Où on le trouve, comment on l’installe, tout ça quoi (et la doc) ?

Vous le trouverez sur sa page github. C’est d’ailleurs là que vous pourrez apprendre que cette sympathique petite app est une version modifiée de l’app inlines de django-basic-apps.

Pour l’installation deux méthodes :
directement en clonant le repository git de github
avec un petit easy_install bien de chez nous.

Attention, l’application pour fonctionner à besoin de BeautifulSoup mais l’installation par easy_install ne vous l’installera pas automatiquement. Un petit easy_install beautifulsoup sera donc de rigueur. Et oui.

Quand à la doc, elle tient dans un mouchoir de poche, à savoir le fichier readme mais au vu de la simplicité de l’app, ce n’est pas vraiment dérangeant.

2- Mais au fait, à quoi ça sert ?

En fait c’est tout simple. Cela vous permet, lorsque vous rédigez des contenus, d’insérer à l’intérieur d’autre contenu gérer par votre django. Et en les mettant en forme avec des templates spécifiques.

Imaginons par exemple que vous voulez insérez des images d’une manière simple dans un billet de blog, ou des blocks de texte ou ce que vous voulez en fait. Et cela, sans modifier le template de votre contenu principal. Et oui. Mais non, ce n’est pas de la magie.

3- Comment ça marche ?

En fait, cela marche en deux temps. Tout d’abord dans le template d’affichage de votre contenu principal, il faut déclarer et utiliser le template de django-improved-inlines, comme ceci :

{% load inlines %}
…....
{{ post.body|render_inlines }}

Ensuite, tout va se jouer dans votre contenu, ici le body de votre post. Vous allez parsemer celui si de bouts d’xml qui seront process par BeautifulSoup et Improved-Inlines et qui seront transformés en html (grâce à un template).

L’exemple le plus simple est :

<inline type="media.photo" id="1" />

qui affichera l’objet de pk 1 qui est modélisé par la classe photo contenu dans l’app media.

Mais vous pourrez également utiliser les attributs xml suivant :
ids pour afficher plusieurs id, séparées par des virgules.
filter pour passer un filtre django
template pour choisir le template django qui sera utilisé (par défault l’app utilise inlines/app_model.html)
class qui permet de passer une class au template

ce qui donnerait :

<inline type="calendar.event" filter="date__gte=datetime.date.today()" template="calendar/event_inline.html" />

ou encore :

<inline type="app.model" id="<some pk>"/> <inline type="app.model" ids="<some pk>,<some other pk>" />

4-Conclusion

Je n’ai pas encore eu l’occasion de m’amuser, ‘pour de vrai’ avec cette appli toute simple, ce n’est pas l’envie qui m’en manque parce que je pense lui trouver une foule d’application qui me faciliteront grandement la vie.
J’ai une seule petite appréhension que le process par BeautifulSoup ne ralentisse pas quelque peu le rendering des pages. Ca serait d’ailleurs un ralentissement à évaluer. En tout cas, amusez vous bien avec cette appli aussi simple, qu’utile.

[Afpy] Livre "Apprendre à Programmer avec Python 3" ... 19/06/2010
Gérard Swinnen nous offre un nouvel ouvrage consacré à Python 3.
[carlchenet] Développeurs : pourquoi Debian modifie parfois vos source... ... 18/06/2010
Suivez-moi sur Identi.ca : http://identi.ca/carlchenet Suite à certains commentaires sur LinuxFR qui attaquaient le travail des responsables Debian chargés de la maintenance d’applications qui sont fournies sous forme de paquets, j’ai pensé qu’une petite mise au point (et accessoiremment le point de vue d’un de ces responsables ) pourrait vous intéresser. Les développeurs des applications [...]
[jon] Créer des PDF en Python avec Genshi et RML: pyjon.reports ... 15/06/2010
Attention, cet article est technique… Si vous ne vous intéressez pas au développement en python, passez à l’article suivant Vous voulez faire des rapports en pdf, envoyer des lettres ou une quelquonque autre action nécéssitant de la génération de PDF ? Si vous êtes aguéris du monde python vous avez surement entendu parler de ReportLab. [...]
[Afpy] Pau a son Afpyro ! ... 09/06/2010
Viendez, viendez nombreux au premier afpyro de Pau. Jeudi 10 juin 2010 à 19h au café l'Entropie.
[carlchenet] Sqlobject 0.12.4 dans Debian ... 05/06/2010
Par Carl Chenet: http://identi.ca/carlchenet Sqlobject est un gestionnaire relationnel d’objets. Ce dernier vous permet de créer une couche d’abstraction entre votre base de données et la gestion de vos données au niveau de votre programme, tout cela à travers une bibliothèque de programmation en Python. Si aujourd’hui SQLAchemy semble devenir une référence, SQLObject garde une simplicité [...]
[carlchenet] pykickstart entre dans Debian ... 05/06/2010
Par Carl Chenet: http://identi.ca/carlchenet Peut-être connaissez-vous Kickstart, le système d’installation automatisé pour les systèmes Fedora/Redhat. À partir d’un fichier de configuration kickstart, vous pouvez définir finement les paquets qui constitueront vos futurs systèmes et les ordres à passer lors de ces installations automatisées. Le fichier de configuration kickstart est ainsi assez long et complexe et [...]
[j-mad] Django-samaritan, parce que tout le monde a le droit d’aimer B... ... 23/05/2010

Le mois de mai est toujours un mois compliqué. Normalement c’est à cause de tout ces jours fériés qui sont autant d’obstacle au travail et qui nous oblige à être tout le temps en retard en mai. Pourtant, cette année, malgré que deux des jours fériés de mai tombent un samedi et que le dernier (demain) soit un jour travaillé pour moi, la malédiction du mois de mai a encore frappé et je n’ai de temps pour rien… A croire que c’est le mois de mai lui-même qui a pour conséquence que l’on soit en retard. La malédiction sanglante du mois de mai … (tiens on pourrait faire un bon film de série B avec ça). Enfin, tout ça pour expliquer le fait que l’application du mois que j’ai choisi est une toute petite application, que je n’ai en fait pas eu l’occasion d’essayer ‘en vrai’. (et puis bon, je n’allais pas cracher sur la possibilité de faire un jeu de mot coolos en parlant d’un film que j’adore …)

1- Où on le trouve, comment on l’installe, tout ça quoi (et la doc) ?

On le trouve sur la page github qui va bien et c’est tout. Quand à la doc, elle est, elle aussi uniquement sur le github

La doc se découpe d’ailleurs entre :

  • le Readme
  • le Install
  • les commentaires dans le code.

C’est peu vous aller me dire, mais vu que l’app fait, en tout et pour tout, moins de 200 lignes, c’est suffisant.

2- A quoi ca sert ?

A remplacer le model django.contrib.auth.models.User par un des siens, d’une façon propre. Pour aider encore plus, des models spéciaux de M2M, de OnetoOne et de FK sont fournis pour quand on voudra créer des références vers nos nouveaux users.

3- Comment ça marche ?

Il y a deux façons possibles de le faire marcher.

En l’installant puis en l’utilisant. Tout simplement.. On créé son model, on utilise la fonction get_user_model() qui est fournit avec django-samaritain (ou en utilisant directement notre model d’ailleurs). Et on utilise les spécialisations des FK,OtO et M2M.

En utilisant la méthode de Monkey Patching pour injecter à la volée le comportement de django-samaritan dans un projet existant. Cette deuxième méthode est déconseillée pour une utilisation à long terme,dixit l’auteur de l’app lui même.

3- Retour ?

Et oui, je sais, c’est un comble. Mais bon, c’est mes billets, alors je fais ce que je veux. Donc, si l’un de vous a des retours sur l’utilisation de cette app, je suis bien entendu preneur, ne vous gênez surtout pas.

[logilab] Une mise en place de l’eXtreme Programming - ce que j'en ret... ... 20/05/2010
http://rubyonrails.org/images/rails.png

Je suis allé à la présentation de "Une mise en place de l’eXtreme Programming" présenté par Karine Sabatier dans le cadre d'Agile Nantes. On y a parlé plutôt Ruby on Rails que python, mais surtout de méthodes agiles et XP.

Voici quelques points que j'ai retenu de cette présentation tout à fait pragmatique d'une mise en pratique des principes XP :

  • Le principe de "Convention over configuration" : préférer la convention (notamment pour la programmation) plutôt que la contrainte par la configuration. Dans Ruby On Rails, les conventions sont très fortes, pour faire une application on ne peut pas s'éloigner du modèle MVC : les modèles sont dans "model", les views sont dans "views" etc... À ce sujet, la conférencière a fait référence à deux types de designs que je ne connaissait pas : le DDD Domain-driven Design et Behavior Driven Development.
  • Utilisation de métaphores : trouver un langage commun avec le client mais aussi avec les utilisateurs
  • Application de déploiement ruby on rails : Capistrano, bien qu'à Logilab nous privilégions le déploiement par paquets et dépôts debian, en python on pourra jeter un coup d'œil à Fabric.
http://retrospectiva.org/extensions/overview/images/product_backlog.png?1265550417
  • Leur projet XP utilisait le logiciel de gestion de projet Retrospectiva. Celui-ci ressemble sur bien des points à JPL (Jeux de Planification Logiciel) disponible sur le framework CubicWeb (http://www.cubicweb.org). Coté intégration continue : CruiseControl , en python nous privilégions apycot.
  • Ce projet a essayé l'utilisation de Selenium pour ces tests web. Le constat est le même que chez Logilab : la première fois que ca marche c'est utile et apporte une grande satisfaction, dans un deuxième temps ca reste très difficile à maintenir. Nous regardons à présent plutôt du coté de Windmill qui a été intégré à la version 3.9 de cubicweb.
  • Une mention a été fait d'une société fonctionnement uniquement en mode agile Pyxis.
[Afpy] Python WAW 2010 : Semaine 19 ... 16/05/2010
Python Week After Week : les liens de la semaine 19 de l'année 2010 de l'AFPY. Cette semaine les faits importants sont la sortie de Django 1.2 et le début de l'enregistrement des participants pour EuroSciPy. Les communautés respectives devraient faire des annonces français sous peu.
[Afpy] Python WAW 2010 : Semaine 18 ... 09/05/2010
Python Week After Week : les liens de la semaine 18 de l'année 2010 de l'AFPY
[carlchenet] /me sur identi.ca ... 07/05/2010
Je me rends compte que je passe un nombre important d’informations qui pourraient intéresser un large public à la trappe car il m’est difficile d’écrire un billet complet à chque fois. Pour cette raison j’ai ouvert un compte identi.ca afin de pouvoir rapidement diffuser ces informations que je trouve digne d’intérêt. Vous pourrez donc me [...]
[Afpy] Python WAW 2010 : Semaine 17 ... 02/05/2010
Python Week After Week : les liens de la semaine 17 de l'année 2010 de l'AFPY
[Afpy] Python WAW 2010 : Semaine 16 ... 01/05/2010
Python Week After Week : les liens de la semaine 16 de l'année 2010 de l'AFPY
[nsteinmetz] Créer son atelier de développement logiciel Python ... 30/04/2010

Aide mémoire pour la confection d'un atelier logiciel autour de Python. Il sera complété au fur et à mesure...

Pré-requis :

  • pip ; un sudo easy_install pip doit fonctionner si setuptools est installé.

Installation de Virtualenv & Virtualenvwrapper

Virtualenv permet de créer des environnements virtuels python avec les librairies de votre choix. Vous pouvez avoir un environnement virtuel pour chaque version de DJango (dj-096, dj-100, dj-110, dj-120, etc) et contre lesquels vous allez pouvoir tester l'application que vous développez. L'autre avantage est que l'on peut installer ce que l'on veut comme librairie python, sans avoir de droit système. De mémoire, on doit même pouvoir utiliser plusieurs versions de python si besoin. Bref, l'idéal pour des tests et ne pas pourrir son système global :-)

Virtualenvwrapper est l'outil pour les fainéants qui utilisent virtualenv puisqu'il simplifie l'utilisation de virtualenv. Il y a des options assez sioux ; se reporter à la documentation

sudo pip install virtualenv virtualenvwrapper

Dans votre fichier $HOME/.bashrc :

# Création du répertoire accueillant les environnements virtuels
export WORKON_HOME=$HOME/python/virtualenv
# Instructions spécifiques pour l'usage de PIP
export PIP_VIRTUALENV_BASE=$WORKON_HOME
export PIP_RESPECT_VIRTUALENV=true
# Chargement des commandes fournies par virtualenvwrapper 
. /usr/bin/virtualenvwrapper.sh

Ensuite dans votre console :

# Création du répertoire accueillant les environnements virtuels
mkdir -p $HOME/python/virtualenv
# Prise en compte des modifications réalisées précédemments
source $HOME/.bashrc

avec pour résultat :

virtualenvwrapper.user_scripts Creating /home/nsteinmetz/python/virtualenv/initialize
virtualenvwrapper.user_scripts Creating /home/nsteinmetz/python/virtualenv/premkvirtualenv
virtualenvwrapper.user_scripts Creating /home/nsteinmetz/python/virtualenv/postmkvirtualenv
virtualenvwrapper.user_scripts Creating /home/nsteinmetz/python/virtualenv/prermvirtualenv
virtualenvwrapper.user_scripts Creating /home/nsteinmetz/python/virtualenv/postrmvirtualenv
virtualenvwrapper.user_scripts Creating /home/nsteinmetz/python/virtualenv/predeactivate
virtualenvwrapper.user_scripts Creating /home/nsteinmetz/python/virtualenv/postdeactivate
virtualenvwrapper.user_scripts Creating /home/nsteinmetz/python/virtualenv/preactivate
virtualenvwrapper.user_scripts Creating /home/nsteinmetz/python/virtualenv/postactivate

Création de son premier environnement virtuel

mkvirtualenv demo
New python executable in demo/bin/python
Installing setuptools............done.
virtualenvwrapper.user_scripts Creating /home/nsteinmetz/python/virtualenv/demo/bin/predeactivate
virtualenvwrapper.user_scripts Creating /home/nsteinmetz/python/virtualenv/demo/bin/postdeactivate
virtualenvwrapper.user_scripts Creating /home/nsteinmetz/python/virtualenv/demo/bin/preactivate
virtualenvwrapper.user_scripts Creating /home/nsteinmetz/python/virtualenv/demo/bin/postactivate

Sur votre prompt, vous devez voir un petit (demo) apparaître indiquant que vous utilisez cet environnement :

Avant :

[nsteinmetz@citrouille ~]$

Après :

(demo)[nsteinmetz@citrouille ~]$ 

Comme tout projet doit avoir sa documentation et être versionné, installons sphinx et mercurial.

pip install sphinx mercurial

Il ne vous reste plus qu'à installer les autres librairies dont vous avez besoin.

Pour sortir de votre environnement, il suffit d'utiliser la commande deactivate.

Pour revenir dans votre environnement, il faut utiliser la commande workon :

  • Si vous n'avez qu'un environnement virtuel (comme dans notre cas) alors vous basculez automatiquement dans cet environnement
  • Si vous avez plusieurs environnements virtuels, alors workon liste les environnements disponibles. Pour en activer un en particulier, il faut préciser son nom ; dans notre cas workon demo.

To be continued... et je suis preneur de vos retours / idées / ...

[logilab] Sprint CubicWeb chez Logilab - annonce de dernière minute ... 29/04/2010

Logilab est en ce moment en train d'acceuillir un sprint autour de la plateforme CubicWeb. L'objectif principal de ce sprint de 5 jours est d'améliorer l'usage de javascript et des css dans CubicWeb :

http://www.logilab.org/image/28586?vid=downloadhttp://codesnip.net/wp-content/uploads/javascript.png
  • avoir une API javascript propre, testée et documentée
  • pouvoir facilement changer le style d'une application cubicweb
  • gestion de bundle pour javascript et CSS
  • une documentation sur les standards d'écriture des fichiers JS et CSS pour cubicweb

Ce sprint aura lieu du jeudi 29 avril 2010 au 5 mai 2010 (weekend exlus - les bureaux seront fermés). Vous êtes les bienvenus pour contribuer, filer un coup de main, faire du pair programming... ou simplement rencontrer des développeurs cubicweb. Vous pouvez même venir une après-midi ou une seule journée. Pour ceux avec des portables, il y aura du réseau disponible pour être connecté.

Adresse : 104 Boulevard Auguste-Blanqui, Paris. Sonnez à "Logilab".

Métro : St Jacques or Corvisart (Glacière est la station la plus proche mais sera fermée à partir de lundi)

Contact : http://www.logilab.fr/contact

Dates : du 29/04/2010 au 30/04/2010 et du 03/05/2010 au 05/05/2010

[Afpy] Atelier d’initiation à Python et de développement agile en Pyth... ... 29/04/2010
L'atelier aura lieu à Brignoles dans le 83 (Var) et portera sur le thème du langage Python et du développement Agile en Python. Je vous invite à prendre connaissance de cet atelier sur mon blog :
[j-mad] Djangocong ,bilan perso d’un gentil organisateur. ... 27/04/2010

Poussé par les nombreux bilans que je vois fleurir sur le hastag #djangocong, je ne peux que participer et faire mon bilan perso de ce week-end de folie, (et comme je suis à la bourre, je le fais en dégustant mon jambon-beurre salé du midi).

Je ferrais un bilan plus ‘du coté de l’organisateur’ parce que des bilans ‘coté public’ il y en a déjà eu plein et des super complets, bien plus que ce que je pourrais faire (comme celui de laurent mais aussi de tous les autres présents, une simple recherche sur le hastag donnera tout les liens).

Pour commencer, les remerciements :

  • à David bien entendu, parce que voilà, y aurait pas eu de djangocong sans david.
  • à Samuel pour la vidéo et les bières belges, toujours aussi bonnes (je ne citerais pas de noms, même sous la torture (je dirais juste qu’il sait super bien manier un aspirateur), mais certains présents sont d’ailleurs tombés amoureux de certaines bières …)
  • à Fred, pour avoir transporter son matos depuis la Belgique et nous avoir permis d’avoir des prises sons pour toutes les confs.
  • à Laurent pour les photos, très réussies,
  • à Johann qui oui a milité pour la création d’une asso, a réalisé de super tee-shirt dans un délai plus que court. (d’ailleurs il en reste quelqu’un à vendre, si vous voulez….)
  • à Matthieu qui s’est occupé de tout plein de petits trucs tout le temps, quand on se demandait bien comment on allait faire, comme par exemple des badges (qui a remarqué que le poney django était en filigramme très clair sur la partie blanche des badges?), mais qui aussi passe l’aspirateur comme personne.
  • À Daks pour avoir bossé sur le petit feuillet programme/info importantes et l’avoir imprimé en nombre.
  • à la chérie de David qui a réalisé la mascotte des Congs
  • à ma chérie qui m’a aidé sur les recherches de lieu (si vous avez eu des hotels où dormir, c’est grâce à elle :) ).
  • à Marseille Innovation, le propriétaire des salles qui m’a fait confiance (bon j’ai du un peu jouer au chat de Shrek) et nous a permis d’avoir un événement gratuit en me prêtant les salles pour le week-end avec pour seule condition de ne rien dégrader et de les rendre aussi propre que ce que je les avais reçu.
  • Aux généreux donateurs
  • À tout les conférenciers pour avoir fait des conférences de qualité, vivantes, et carrément cools.
  • À tout les présents, pour avoir été là, avoir donné la chance à cette première fois, avoir fait des centaines de kilomètre en train, voiture,  avions, vélos.
  • à la météo de dimanche qui nous a permis de manger au soleil.

Pour le reste.

J’ai adoré ces deux jours de conférences. Et j’ai vraiment adoré les organiser. Que ce soit avant ou pendant. Plein de moment de stress (‘mais où va-t-on trouver un resto pour ce soir?’) ou de petits moment fun (comme appeler un resto pour lui dire ‘bon je vous réserve l’intégralité de vos couverts’ ).

Effectivement vouloir être intervenant en étant organisateur, ce fut une gageure qui fut difficile à tenir. Faire des slides entre minuit et deux heures du mat, pendant la nuit de samedi à dimanche (vous pouvez les trouver là ou sur slideshare), c’était rigolo mais fatiguant. Mais d’un autre coté, je suis content d’avoir pu parler un peu, d’un sujet qui me tenait à cœur, même si j’aurais voulu faire mieux, pour le coup.

Donc oui, voir que tout ce passait plutôt bien, que tout le monde était content, heureux d’être venu, fut une vraie joie et autant le dire tout de suite, une vraie motivation pour se dire qu’il faut faire un truc l’année prochaine (oui, je sais david, il faut débrieffer et qu’on en discute, tout ça,…. :) )

Bien entendu il y a des choses à améliorer. Pour les repas, on a dérapé à chaque fois au niveau du planning prévu. Faut il passer sur une pause de 2h pour le repas, prévoir un traiteur ou trouver une troisième solution, il faudra étudier le truc.

Pour les conférences, elles furent effectivement super denses, s’enchainant à toute allure sans trop de pause. Est ce qu’il faut réduire le temps des confs, en faire moins, prévoir plus que deux jours de congs.. là aussi il y a plein de pistes à explorer (l’idée de david de partir sur un format un peu plus barcamp me semble une idée très intéressante) .

Laisser plus de place à des sprint code pourrait être intéressant aussi, à voir comment on mixe les eux. Plein de possibilité donc, pour la prochaine édition, si elle a lieu (ben quoi laissons un peu le suspense planer:) )

Au niveau logistique, plein de petit truc à améliorer pour la prochaine, David en a listé par mal, je rajouterais de prévoir plus de cafetière (au moins deux) pour pouvoir étancher plus facilement la soif des intervenants et ne pas faire confiance aux bus marseillais le dimanche matin :) . Je suis sur qu’en se posant et en réfléchissant on trouvera d’autre petit trucs pour améliorer la logistique.

Créer l’asso, on s’y est un peu engagé au tout début des deux jours, et ça sera un pré-requis obligatoire, pour la deuxième édition, je pense.

Donc voilà, pour moi, c’est deux jours furent vraiment un plaisir de chaque instant.

Le dimanche soir, lorsque je me suis retrouvé seul dans le bâtiment, à vérifier une dernière fois que tout était niquel, en ordre, bien rangé, juste avant de charger le carton de cadavre de bière pour aller le jeter au recyclage, il faut bien avouer que j’ai eu un petit pincement au coeur en me disant ‘c’est déjà fini’.

Et puis je me suis dit ‘vivement l’année prochaine pour la deuxième édition’.

Alors voilà.

A l’année prochaine, pour de nouvelles aventures, qu’elles qu’en soient leur formes.

[Biologeek] Bilan personnel sur djangocong ... 26/04/2010

Les rencontres Django se sont achevées hier et il m'a fallu une bonne journée de récupération. Les premiers bilans de Laurent, Bruno, Nicolas, William, Boris et Olivier sont clairement positifs et ça me fait vraiment plaisir. Tout n'a pourtant pas été tout rose, enfin à part le poney ;-)

Django pony marseillais

Bilan à chaud

Ce qui a fonctionné

  • Le contenu des conférences : c'est pas évident de sélectionner des interventions qui plaisent à tout le monde mais c'était à mon avis un bon compromis sujets basiques/avancés.
  • Les lightning talks : j'aurais préféré des sujets plus variés (moins Django-centrés) mais ça restait extrêmement intéressant et tout le monde a joué le jeu.
  • La vidéo : bon j'attends de voir le résultat mais je n'ai aucun doute sur le perfectionnisme de Samuel !
  • Les bières : je vais vous faire un aveu public, je n'aime pas la bière, mais la bière belge... c'est juste différent et pas pareil :-)
  • La connexion : je doutais que ça tienne et finalement on a eu du net sur les deux jours de façon plutôt correcte.
  • Plutôt satisfait de mon expérience avec EventBrite pour gérer les inscrits.

Ce qui n'a pas fonctionné

  • Vouloir participer tout en organisant : c'était une erreur de vouloir cumuler les deux dans mon cas, à retenir.
  • Les soirées : c'était pas non plus la cata mais tout le monde était bien crevé à chaque fois, il va falloir réfléchir à une autre organisation sur ce point.

Ce qui aurait pu être mieux

  • Une meilleure gestion du temps : les confs étaient un poil trop longues à mon avis, je pense qu'un format 15 minutes + 5 minutes de questions aurait été plus dynamique et aurait permis de faire plus de pauses qui sont tout aussi intéressantes sur ce type de rendez-vous. La limite entre barcamp et conf traditionnelle reste encore à explorer...
  • La préparation des repas : que ce soit samedi ou dimanche (en ayant réservé ou pas), on a pris une heure de retard et c'est pas normal. La solution budget plus conséquent et traiteur/livraison s'annonce incontournable.
  • L'acoustique de la salle était un peu limite parfois et si on avait été plus nombreux un ampli aurait à mon avis été nécessaire.
  • Quelques détails qui viendront avec l'expérience : réserver les viennoiseries, prévoir des jus, prévoir beaucoup de multi-prises, mieux baliser l'itinéraire, etc etc.

Bilan comptable

J'avais l'impression que l'on serait très « déficitaires » suite à l'achat des T-shirts mais finalement la balance est positive grâce notamment à un généreux don de dernière minute. Voici le bilan comptable final de l'événement, sachant que les salles étaient prêtées gracieusement :

Bilan comptable djangocong

Un événement gratuit de cette ampleur basé sur les dons reste donc réalisable. Je suis quand même légèrement déçu qu'il n'y ait eu « que » 46 personnes présentes alors que l'on était monté à 70 inscrits la quinzaine précédent l'événement, pour 57 inscrits le jour J suite aux désistements annoncés. Je ne sais pas si un prix, même symbolique, aurait limité ce phénomène. C'est une piste à réfléchir pour l'année prochaine.

Bilan motivation

Parlons justement de « la prochaine fois ». Il faut encore que l'on débriefe avec Jean-Michel mais a priori les nombreux messages sur Twitter et sur les blogs sont très encourageants et motivants. Je ne vous cache pas que c'est une grande source de satisfaction personnelle.

Quelques pistes :

  • Rester aussi « artisanal » et se faire plaisir entre geeks, modulo les améliorations proposées.
  • Passer à la vitesse supérieure et accueillir EuroDjangoCon.
  • Davantage profiter du lieu en organisant une session sur une semaine, dans le style de /dev/fort en effectifs réduits avec bronzette et code au programme.
  • Faire un DjangoSea, pendant à DjangoSki.

L'avantage de ces propositions étant qu'elles sont non exclusives ;-).

Bilan remerciements

Déjà merci à tous d'être venu(e)s, parfois de loin : Toulouse, Bayonne, Rennes, Angleterre, Belgique, Suisse, Grenoble, Nice, ça fait quand même une belle boucle !

Merci aux conférenciers d'avoir été consciencieux dans la préparation de leur intervention.

Merci à Laurent pour les photos des intervenants.

Merci à Samuel pour la vidéo pendant les deux jours et l'importation de bières ;-). Je sais combien la tâche de synchro/correction/encodage/etc des vidéos va être fastidieuse, courage !

Merci à Frédéric pour le son pendant les deux jours aussi, je suis impatient de voir le résultat.

Merci à Johan pour nous avoir motivés à créer une association et pour avoir imprimé les T-shirts en un temps record !

Merci à Mathieu pour toutes ses petites attentions qui font gagner un temps fou.

Merci à Jean-Michel sans qui rien n'aurait été possible.

Merci à la miss d'avoir dessiné un Django pony marseillais et d'avoir donné les droits de paternité à l'événement.

Merci aux généreux donateurs et aux rédacteurs du compte-rendu collaboratif. J'intégrerai ces notes sur le site la semaine prochaine.

Samuel à Djangocong

Logo biologeek Bilan personnel sur djangocong a été rédigé par David Larlet pour biologeek.com et a été originellement posté le 27 avril 2010. À part exceptions, c'est ©2004-2009 David Larlet et sous licence (presque) libre autorisant la reproduction, la distribution et la modification sous certaines conditions. Veuillez les respecter.

[Afpy] Vitefait 5.5 est sorti ... 25/04/2010
beaucoup de nouveautés pour cette version
[No] Beeroverip à Djangocong ... 25/04/2010

Ai fait hier une conférence sur Beeroverip lors des premières rencontres Django francophones, dans la belle ville de Marseille.

Je publie ici les slides de la conférence, qui devrait être disponible en vidéo bientôt.

L'événement se passe ma foi à merveille : super orga, très très bonnes confs (et je ne dis pas ça pour flatter, je suis vraiment bluffé par la grande diversité et qualité des orateurs). Et une excellente ambiance, entre une bande de copains de l'IRC qui arrivent à mettre un visage et une voix sur des pseudos.

Python is love, my friends.

[Afpy] Python WAW 2010 : Semaine 15 ... 21/04/2010
Python Week After Week : les liens de la semaine 15 de l'année 2010 de l'AFPY
[carlchenet] Nagstamon : le client lourd pour Nagios ... 15/04/2010
Vous en avez marre de passer par votre navigateur pour contrôler l’état de vos serveurs avec Nagios ? Une alternative existe : Nagstamon. Ce programme, écrit en Python, contacte régulièrement votre serveur Nagios et vous tient informé des différents événements qui surviennent sur votre parc. Vous pouvez à chaque instant contrôler ce qui se passe [...]
[No] L'article de JHLP dont tu es le héros ... 12/04/2010

0. Tu te trouves sur ce blog. Un nouvel article est apparu depuis ta dernière visite. Si tu veux le lire, vas en 1.. Si tu ne veux pas le lire, tu vas en 8.

1. L'article en question relate un site qui parle de jeux de rôles. Si tu sais ce qu'est un jeu de rôle, vas en 3. Si tu ne sais pas, vas en 6.

2. Sache donc qu'il existe un nouveau site de jeux de rôles. Ce site s'appelle "Histoires de Rôlistes". Il offre aux rôlistes (ceux qui pratiquent ce genre de jeu) de raconter leurs histoires, leurs éclats de rire, leurs bon ou mauvais souvenirs concernant une partie ou un personnage. Si tu as des histoires à raconter, tu peux aller en 4. Sinon, tu peux aller en 5.

3. Si tu as déjà joué à jeu de rôle et que ça t'a plu, vas en 2. Si tu n'a jamais joué à un jeu de rôle d'aventure fantastique ou que tu y as joué et que tu n'as pas aimé, vas en 8.

4. Il est très facile de s'inscrire sur le site et de proposer une histoire.

5. Rien ne t'empêche d'aller lire les histoires sur le site. Certaines sont assez cryptiques, d'autres peuvent être comprises, même par quelqu'un qui n'a jamais joué à un de ces jeux en particulier. Et même un utilisateur "passif" peut participer à sa façon, en mettant un commentaire, on signalant qu'il aime l'histoire en question, etc. Il y a même un système de badges qui récompense certaines pratiques sur le site. À présent, si cet article t'a plu, tu peux aller en 7. Sinon, tu peux aller en 8.

6. Un jeu de rôle est une sorte de jeu dans lequel des joueurs incarnent des personnages imaginaires qui doivent survivre aux situations présentées par le Maître de jeu. Personnellement, je définis ce jeu par : "c'est une pièce de théâtre pour laquelle les comédiens ne connaissent pas le scénario à l'avance". Wikipedia possède un article pas trop mal détaillé. Maintenant que tu sais à peu près ce qu'est un jeu de rôle, tu peux aller en 3.

7. Oui, bon, certes, c'est pas l'article le plus remarquable de la blogophonie, non plus, faut pas exagérer. Bon, allez, fiche le camp. Hop ! Je te libère, tu peux y allez, maintenant.

8. Un énorme troll qui respire bruyamment abat une énorme massue dans ta tête. Ton crâne s'enfonce entre tes épaules. Tu es mort. S'il fallait une consolation à ta mort soudaine, ce serait que le site est propulsé par Django.

[Afpy] Python WAW 2010 : Semaine 14 ... 12/04/2010
Python Week After Week : les liens de la semaine 14 de l'année 2010 de l'AFPY
[j-mad] Titanium par l’exemple, un client twitter en dix minutes. ... 10/04/2010


Bon, bien entendu mon titre est volontairement accrocheur. Et complètement mensonger. Mais il faut bien appâter le chaland un peu. Sinon, je ne serais jamais un blogueur influent.. Alors vive les titres accrocheur :)

Mais avant de commencer, il faut peut-être que j’explique ce que c’est que Titanium. Titanium c’est un framework assez génial (et libre) qui permet de faire du dev iphone/android en html/javascript. Histoire que ceux qui n’aiment ni l’objective-C, ni le Java puisse tout de même coder sur ces plateformes là. Histoire aussi de coder qu’une fois son appli et de la voir tourner sur les deux.

Là, vous devez être en train de vous demander : ‘Il va nous parler de dev iphone/android en js ? ‘

Et ben en fait, pas du tout.

Parce que là où Titanium est encore plus génial, c’est que l’on peut coder pour le Desktop aussi, en multiplateforme à savoir Linux, OSX et Windows. Sympa, vous aller me dire, mais bon faire toute une appli desktop en js, voilà quoi …

Oui, mais non, parce que pour le desktop, on peut coder en python (attention en python 2.5 uniquement), en ruby ou.. misère, en php. Et là, ça devient carrément miam.

Ca faisait donc plusieurs mois que j’avais envie de tester le bouzin, mais bon, j’avais déjà pas le temps de bosser sur histoiresderolistes.com alors tester un truc en plus… Et puis les tests c’est bien joli mais pour faire des Hello World! Merci.

Mais comme les vacances, ce n’est pas fait que pour travailler sur le boulot en retard, j’ai pu m’y mettre, un peu. (et puis faut avouer que le billet de @popofr13 sur le dev titanium iphone m’a boosté à écrire le mien). Restait alors le problème du Hello World. Après 30 secondes de réflexion je me suis dit que bidouiller des trucs avec twitter, ça serait rigolo. Et en plus comme c’est bien buzz word twitter, ça plaira, c’est sur.

Et c’est ainsi qu’un froid jour d’avril, une nouvelle catégorie d’article naquit sur le j-mad blog. Une catégorie dédiée aux bidouillages avec Titanium et ayant pour fil rouge le dev d’un client twitter basique (type Pino quoi). Et comme pour chaque projet, il faut un nom, j’en ai trouvé un TwittPouick. Oui je sais. Non, pas de commentaires sur le nom.

1- La genèse, installation et création du projet.

Alors c’est tout simple, pour télécharger Titanium, on va sur le site et on clique sur téléchargement.

Ensuite il n’y a qu’à décompresser l’archive et lancer l’installateur. Petite précision, il y a assez régulièrement de nouvelle version, qui sont indiqués directement dans l’interface de Titanium. Il suffit alors de relancer le cycle dl/décompression/installation.

Une fois Titanium installé et lancé, il suffit de cliquer sur New Project pour voir la fenêtre ci dessous apparaître. Rien de bien difficile à comprendre, il suffit de remplir les champs et de cliquer sur create project (N’oubliez pas de cocher en vert la petite case python tout de même).

Vous arrivez ensuite sur la fenêtre principale composé d’à gauche la liste de vos projets (sur mon screen on voit d’ailleurs mon projet twittpouick) et à droite ben la zone de droite avec un menu horizontal en haut Dashboard / Edit / Test & Package.

  • Le premier ne sert à rien, c’est simplement la liste des options en fonction de si on a un abonnement payant ou pas.
  • L’onglet Edit sert un peu plus, il permet de modifier les infos que l’on a saisit à la création du projet
  • Enfin Test & Package sera celui sur lequel vous allez passer le plus de temps, vu que c’est à partir de là que vous lancerez votre projet. (et qu’un jour quand il sera fini vous le packagerait et tout et tout)

2- Et ensuite ?

Ben ensuite, on prend son navigateur de fichier favori et on va voir ce qu’il nous à générer le tonton Titanium.
Et l’on voit ça :

Bon le fichier jquery n’est pas là de base, c’est moi qui l’est rajouté. Vous comprendrez pourquoi par la suite.

Donc il ne devrait y avoir quasiment que le fichier index.html. Qui correspond à notre fenêtre principale. Avant de partir pour de vrai dans des vrais choses rigolotes (comprendre le client twitter), on va tout de même faire un hello word. Et oui.

Ouvrez le fichier index.html et remplacez son contenu par celui-ci

<html>
    <head>
        <script type="text/python">
      def hello_python():
          return "Hello World"
        </script>
    </head>

    <body >
        <div >
            <div >Le Hello World</div>
            <button onclick="alert(hello_python())">Bouton Hello</button>
        </div>
    </body>
</html>

Allez dans Test & Package, cliquez sur Launch App, une fenêtre blanche se lance avec un bouton, cliquez sur le bouton et mirage, une fenêtre Alert javascript s’affiche avec un Hello World dedans.

Ce qui est logique, si on regarde le code au dessus. On crée une section de code python, on définit une fonction que l’on appelle sur le onclick du bouton, dans un code js donc, et on passe le retour de la fonction python (je le rappelle) en paramètre à la fonction alert js.

En fait cet exemple, bien que très simple, montre la plupart des trucs génials de Titanium.

On peut déclarer des sections de code python, directement dans les fichiers html (mais on peut le faire proprement en dehors aussi, ça sera l’objet d’un prochain billet) et on peut accéder au python du js.

Et c’est aussi valable dans l’autre sens. On peut accéder du python, à du code JS. Que ce soit accéder à des fonctions ou à des variables, que l’on peut modifier, bien entendu (à ce propos, cette page de la doc officielle explique la conversion entre les types python / javascript.

3- Et TwittPouick naquit.

Pour clore ce premier billet, déjà bien long, et justifier un peu, le titre du billet, on va faire une premier truc, c’est récupérer, après clic sur un bouton, sa timeline, dans un mode code grouirk, parce que c’est juste pour finir en beauté ce billet.

3.1 Récupération de sa timeline.

Je ne connais pas les librairies twitter en python. Et je n’ai pas vraiment le temps de me plonger dedans pour voir laquelle est la mieux. Par contre je connais bien restkit, une librairie bien bien sympa de @benoitc et qui marche plutôt bien.

On va donc l’utiliser pour récupérer sa timeline.

3.2 Affichage de sa timeline.

On à une interface HTML. On veut modifier le dom. Moi j’aime bien jquery. Donc on va utiliser Jquery. Directement dans du code python. Et oui. Comme si on était en Js. Sauf que l’on ne pourra pas utiliser le raccourci $ , vu qu’on est en python. On va donc simplement utiliser le vrai objet JQuery.

3.3 Utilisation des API Titanium

On peut bien entendu, encore heureux, utiliser directement les API titanium qui sont en Js. Pour l’exemple, j’utilise Titanium.API.info qui permet d’afficher une chaîne de caractère dans la console.

Bon et maintenant le code, complet, du fichier index.html

<html>
    <head>
   
    <link rel="stylesheet" type="text/css" href="style.css" />
    <link rel="stylesheet" type="text/css" href="color.css" />    
   
    <script type ="text/javascript" src="jquery-1.3.2.js"></script>


    <script type="text/python">
        def getTimelineJquery():
            from restkit import Resource, BasicAuth
            from pyquery import PyQuery as pq
           
            try:
                import simplejson as json
            except ImportError:
                import json # py2.6 only
   
            class TwitterTimeline(Resource):
   
                def __init__(self, pool_instance=None, **kwargs):
                    search_url = "https://api.twitter.com/1/statuses/"
       
                    auth = BasicAuth("TwitterUserName", "TwitterPassword")
       
                    super(TwitterTimeline, self).__init__(search_url, follow_redirect=True,
                                    max_follow_redirect=10,
                                    pool_instance=pool_instance,
                                   filters=[auth],
                                    **kwargs)
       
                def get_timeline(self):
                    return self.get('home_timeline.json')
       
                def request(self, *args, **kwargs):
                    resp = super(TwitterTimeline, self).request(*args, **kwargs)
                    return json.loads(resp.body)
   
            s = TwitterTimeline()
            tl = s.get_timeline()

            for item in tl :
                element = u"""<p class="p_tweet color_p_tweet"> %s :  %s</p>""" % (item['user']['screen_name'], item['text'] )
                Titanium.API.info (element)
                jQuery("#timeline").append(element)

    </script>

    </head>
    <body class="body color_body">
         <div>
           
            <h1>Votre timeline avec TwittPouick</h1>
            <button onclick="getTimelineJquery()"> Get Timeline Jquery </button>
           
            <div id="timeline">

            </div>
        </div>
    </body>
</html>

Vous n’avez plus qu’à installer restkit (avec easy_install), pour python 2.5 N’OUBLIEZ PAS !!!, mettre jquery à coté de votre fichier index.html, mettre votre login / mot de passe twitter et puis lancer l’appli twitter.

Cliquer sur le bouton, quelque seconde après .. miracle les tweets apparaissent. Recliquez sur le bouton, les nouveaux twitts s’ajoutent en bas de liste….

Et voilà, même pas 10 minutes et déjà vous avez un début de client. Comme quoi, je ne vous avais pas tant mené en bateau que ça, dans mon titre, finalement.

4- Conclusion.

Ce premier billet, n’est qu’un premier billet. Il ne va pas très loin dans la présentation de Titanium, parce que je n’ai pas vraiment eu le temps de moi même faire plus. Vivement les prochains billets donc. Enfin, j’espère que c’est ce que vous vous dites en ce moment :) .
Pour la suite, je mettrais en place un repository mercurial sur bitbucket où je déposerais les différentes étapes de la création de TwittPouick.

En attendant mon prochain billet, amusez vous bien avec Titanium.

[j-mad] Django-request , ne partez plus en quest de vos stats ... 10/04/2010


Et non, vous ne rêvez pas, on est même pas le 15 avril et déjà, déjà, le billet de l’app django du mois est là. Mais bon, les rencontres django ayant lieu dans maintenant 14 jours et n’ayant pas encore commencer à préparer ma conf, même pas le premier mot (enfin si, bonjour), ce qui fait que je suis ‘dans la banade’, comme l’a fait si justement remarquer il y a peu @daks_

Donc, je préfère me ‘débarrasser’ tout de suite de l’app du mois, comme ça, ça sera au moins une chose de faite.

Ce mois-ci, je vais donc vous présenter django-request, une app pour faire des stats sur la fréquentation de votre django. Oui je sais il y a google analytics pour ça. Mais bon, on sait jamais, ça peut être utile quand même.

1- Où on le trouve, comment on l’installe, tout ça quoi (et la doc) ?

On le trouve à deux endroits :

A noter que quasiment toute la doc se trouve être sur la partie dédiée à django-request sur le site de son auteur.

Pour l’installation, facile, un git clone, un téléchargement de source ou alors pip et easy_install.

Quand à la doc, elle est vraiment très fournie et complète, permettant d’installer, de configurer, d’utiliser, la totale quoi.

2- A quoi ca sert ?

Ben à faire des stats, je l’ai déjà dit. Qui ne seront visibles que dans la partie admin.

On peut avoir de jolis graphiques concernant :

  • les visiteurs uniques
  • les visites basées sur des referrer différents
  • les requêtes reçues par le serveur
  • les requêtes venant des moteur de recherches
  • les requêtes provenant du javascript
  • les requêtes en SSL
  • les requêtes faites par un utilisateur
  • le nombre d’erreur 404
  • le nombre d’erreur, toutes erreurs comprises
  • le nombre d’utilisateur enregistré sur le site qui ont fait des requêtes

Par défaut les calculs seront fait pour les visiteurs uniques, les visites en fonctions des referrers et le nombre global de requêtes.

On obtient ensuite un joli petit graphique qui nous donne tout plein d’infos. Et plein de petits tableaux pour en avoir encore plus.

Et on peut même avoir, des petits templates tags pour voir les users actifs sur le site

3- Comment ça marche ?

Il suffit d’ajouter ‘request’ dans ses installed_apps et d’ajouter le middleware qui va bien. (Attention suivant les middlewares déjà installés, la position du middleware de django-request, dans le tuple des middleware est importantt, mais c’est bien expliqué dans la doc).

Ensuite, tout ce passe dans l’interface d’admin

4- Tips de chez Jmad.

Quand j’ai installé le tout avec easy_install, j’ai oublié de rajouter les chemins pour avoir les templates admins de l’app. Résultat je n’avais rien dans l’admin. Faites y attention ou alors installez request directement dans votre projet django, comme une de vos apps.

Le model Request présente un champ language qui est modélisé en bd par un varchar de 25. Avec mes tests, cette longueur était bien trop petite pour mon firefox. Du coup boum une erreur BD a base de ‘machin qui a été truncated’. J’ai passé la taille du champ à 200 pour être tranquille.

Les différents fichiers js qui sont utilisés sont bien entendu fournis. Pourtant par défaut, les templates vont utilisés ceux hostés ailleurs (sur le site web de l’auteur par exemple). N’oubliez pas de changer cette option si cela vous dérange.

C’est expliqué dans la doc, mais je le redis ici. Une fois que tout est bien configuré, pour aller voir ces stats, vous allez dans l’admin, vous cliquez sur la ligne Request de l’app Request. Là vous avez la liste de toutes les requêtes. (pas très utile là comme ça, vous me direz). Levez les yeux, en haut à droie, à coté du bouton Add Request, vous avez un bouton Overview. Et voilà, cliquez, vous avez vos stats.

[Afpy] Python WAW 2010 : Semaine 13 ... 06/04/2010
Python Week After Week : les liens de la semaine 13 de l'année 2010 de l'AFPY
[j-mad] Lancement d’un side project : Histoiresderolistes.com ... 05/04/2010


‘C’est l’histoire d’un mec …’ qui était rôliste.

Bon ok, c’était facile, mais je trouve que c’est une bonne façon de démarrer ce billet. Billet tout entier consacré à de l’autopromo ou plutôt à l’annonce du lancement d’un de mes side-project comme on dit.

Histoiresderolistes.com. Né d’une idée toute simple à savoir que les rôlistes, dont je suis, adorent se raconter leur vieilles histoires de joueurs, leurs souvenirs de catastrophe évitées ou de justesse, ou pas du tout, leur grand moment de rigolade. Et parfois on a envie de partager ces histoires, pas seulement avec son groupe de joueur actuel, mais avec ses anciens compagnons de parties, ou même avec d’autres rôlistes tout court.

Comme je n’ai pas trouvé un tel endroit, je me suis dit que j’allais la bâtir moi même, la petite taverne virtuelle où nous pourrions tous être barde, le temps d’une histoire.

Alors ce ne fut pas facile de venir à bout de ce projet, dont la taille est pourtant plus que petite. Pour donner une idée de la chronologie :

  • j’ai eu l’idée du site en juillet 2009, j’ai aussitôt acheté le nom de domaine
  • j’ai commencé à aligner quelques lignes de code en aout (merci les vacances), mais ayant du boulot du boulot, en retard, j’ai que très peu avancé.
  • Je m’y suis vraiment mis fin janvier/début février en essayant de trouver du temps la nuit et les week-ends.
  • le week-end de Pâques m’a permis de finaliser le tout et de faire tester à quelques chanceux (merci les gens de #djangocong et du plug).

Mais maintenant, il est en ligne, et vous pouvez aller y lire/raconter des histoires de rôlistes. Et si il est en ligne, c’est aussi grâce à ma chére et tendre qui a été la première des béta testeuses, bien qu’elle ne soit pas du tout rôliste… Le fait qu’il n’y est pas de fautes d’ortographes sur le site (ou presque pas) est par exemple complètement grâce à elle, mais ce n’est pas son seul apport, loin de là.

Et ce n’est pas qu’un ’simple’ site où les gens soumettent des histoires. Quitte à lancer un truc, autant s’en servir comme bac à sable, pour tester des choses dont je parle dans mes billets.

Comme par exemple, l’introduction de mécanismes tirés des jeux vidéos, comme les titres et succès (qui sont ici appelés badges).

Vous pourrez donc gagner des titres (top posteur par exemple) ou des badges comme le badge du djinn narcissique ou du gobelin fanatique (liste des badges). Exactement comme dans les jeux, vous ne connaitrez pas la manière de débloquer certains badges. Parfois même, vous ne saurez même pas que les badges existent avant de les débloquer.

Ce n’est bien entendu qu’un début, j’ai plein d’autres idées (dont certaines déjà listées dans les billet du ce blog), que je mettrais en place petit à petit. En essayant, ensuite, d’analyser le retour des utilisateurs à mes ‘expériences’.

Mais déjà, la question est de savoir si h2rolistes (et il y a même un twitter et un identi.ca pour suivre les nouveautés) va trouver son public ou non…

Et bien entendu, h2rolistes c’est du 100% django.

[No] Installer MongoDb sur Ubuntu Karmic ... 03/04/2010

Voilà quelques temps que je fais mumuse avec les bases de données orientées document (du style Couchdb et/ou MongoDb). Pour CouchDb, son intégration est déjà incluse dans Karmic Koala pour la bonne raison qu'Ubuntu One s'appuie sur Couch.

En attendant que Mongodb débarque dans les dépôts officiels de Lucid, on peut toujours utiliser les dépôts tiers. Et quand bien même on serait arrivés dans l'ère du Lynx, utiliser ces dépôts permet d'utiliser une version plus récente que celle proposée dans les dépôts d'Ubuntu.

En terme de dépôt tiers, c'est un peu le top, puisque ce sont des dépôts fournis par 10gen (les développeurs à l'origine du projet). Pour ce faire, tutorial très simple.

ATTENTION !!! Installer des logiciels en-dehors des dépôts officiels peut mettre en péril la stabilité de ton système. Il est indispensable que tu saches parfaitement ce que tu fais avant de poursuivre.

[j-mad] Petit mémo concernant la syndication Django ... 03/04/2010


Ce billet n’est qu’un petit mémo rapide, pour éviter que d’autre perdent comme moi du temps à chercher un problème qui n’en est pas un. Si jamais je me trompe dans mon interprétation du problème et dans la solution que j’en donne, je suis preneur d’une explication / correctif dans les commentaires.

Django embarque, dans les contrib, un petit framework pour géré la syndication. Plutôt bien foutu d’ailleurs.

Il fonctionne suivant un principe assez simple, pour chaque flux on définit une classe, ensuite on range les classes dans un dict où la clé sera le nom du flux dans l’url et la valeur, la classe, que l’on passe en paramètre à la vue qui gère l’ensemble des flux. (tout est parfaitement expliqué dans la doc, ici).

Par exemple :

from django.conf.urls.defaults import *
from myproject.feeds import LatestEntries, LatestEntriesByCategory

feeds = {
'latest': LatestEntries,
'categories': LatestEntriesByCategory,
}

urlpatterns = patterns('',
# ...
(r'^feeds/(?P<url>.*)/$', 'django.contrib.syndication.views.feed',
{'feed_dict': feeds}),
# ...
)

ici on aura donc deux urls :

  • /feeds/latest
  • /feeds/categories

On peut définir deux templates celui pour justes les titres et celui pour l’item RSS complet. Les deux templates doivent avoir pour nom :

  • KeyDict_title.html
  • KeyDict_description.html

Soit dans notre exemple :

  • latest_title.html
  • latest_description.html
  • categories_title.html
  • categories_description.html

Et tout fonctionne parfaitement dans le meilleur des mondes.

Maintenant prenant un exemple un peu plus compliqué. Imaginons deux apps django, une pour gérer un blog, une pour gérer des reviews de films.
Les deux apps vont donc mettre en place des flux RSS, logique.
Et les deux vont vouloir mettre en place le flux latest. Donc dans chaque répertoire templates des apps, il y aura un sous-répertoire feeds avec les fichiers latest_title.html et latest_description.html

Et là, patatra. Le deuxième flux (dans l’ordre des INSTALLED_APPS) va utiliser les fichiers templates du premier. Parce qu’apparement la recherche des templates pour les feeds et transversale.
Donc faut nommer de manière différentes ses flux. latestblogs et latestreviews par exemple.

Et là, miracle, ça fonctionne.

Voilà, c’est tout.

[j-mad] Petits tours des méthodes des querysets. ... 02/04/2010


Les queryset sont une des composantes importantes de Django. Comment en effet interagir avec la BD sans eux ?

Mais est ce que cet outil si important et si souvent utilisé est si bien connu que ça ?

Parce que tout le monde connait count(), filter(), all() et exclude(). Mais qu’n est-il des autres méthodes ? Perso, je suis le premier à aller dans la doc, pour revérifier si ce que je voudrais n’existe pas déjà…

C’est le pourquoi de ce billet, lister quelques méthodes ‘à connaître’ des querysets (et puis comme ça la prochaine fois que j’aurais besoin de vérifier un truc, je pourrais le faire en lisant du français et pas de l’anglais). (Ce n’est au final qu’une redite de la page de doc qui va bien, mais ça peut servir).

1- Les méthodes qui renvoient un queryset (ou assimilés)

annotate(*args, **kwargs)

une petite méthode bien pratique, qui permet de rajouter des colonnes calculées (en utilisant les classes d’agrégat Sum,Count, etc défini par django) pour chaque objets récupérés dans le queryset.

Et ça, c’est plutôt fort. Surtout que l’on peut, bien entendu, ‘traverser’ les foreign key
L’un des exemples de la doc, montre cela en calculant pour un magasin le prix minimum et maximum des livres en vente :

Store.objects.annotate(min_price=Min('books__price'), max_price=Max('books__price'))

values(*fields) et Values_list (*fields)

Deux méthodes plus que miam.
Values retourne un ValuesQuerySet qui est en fait un queryset composé d’une liste de dictionnaires au lieu d’une liste d’instance d’objet modèle. Chaque dictionnaire représente un objet, les paire clés / valeur représentant le nom de l’attribut (la key) et la valeur de l’attribut (sa valeur).
On peut passer à values un paramètre optionnel *fields, qui permet de spécifier la liste des noms d’attribut (des strings donc) que l’on veut récupérer.
Exemple :

>>>Blog.objects.values()
[{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}],
>>> Blog.objects.values('id', 'name')
[{'id': 1, 'name': 'Beatles Blog'}]

Deux choses importantes à se rappeler, values ne récupère rien pour les manytomany et dans le cas des FK, la clé du dico est le nom ‘vrai’ de l’attribut dans la table (souvent avec _id donc) et la valeur, la valeur de la PK de la FK. Et comme le voit dans l’exemple, si on veut passer le nom explicite de l’attribut de la fk, on peut au choix mettre ou pas le _id, le résultat est le même.

Exemple :

>>> Entry.objects.values()
[{'blog_id: 1, 'headline': u'First Entry', ...}, ...]

>>> Entry.objects.values('
blog')
[{'
blog': 1}, ...]

>>> Entry.objects.values('
blog_id')
[{'
blog_id': 1}, ...]

values_list c’est à peu près la même chose que values, sauf que c’est une liste de tuple et pas une liste de dico. On peut en plus lui passer un paramêtre flat que l’on peut mettre à true , pour ‘aplatir’ les tuples quand l’on demande qu’un seul champ (juste coolos quand on veut une liste de pk)

>>> Entry.objects.values_list('id').order_by('id')
[(1,), (2,), (3,), ...]

>>> Entry.objects.values_list('id', flat=True).order_by('id')
[1, 2, 3, ...]

A quoi sert values et values_list ?

L’intérêt c’est qu’un ValuesQuerySet, c’est comme un queryset. Et que donc on peut utiliser toutes les méthodes des queryset dessus. Y compris refiltrer, order_by, etc etc ..

Et que dans le même temps, on peut alléger la charge, surtout si on a des gros models dont l’on ne veut utiliser que quelques champs.

defer (*fields)

Permet d’indiquer au queryset de ne pas récupérer automatiquement le contenu des champs qui sont passés en paramêtre du defer. Ca peut être utile dans le cas de gros champ texte par exemple (imaginons une vue en liste de billet de blog où l’on ne veut que les titres des billets et pas leur contenu, utiliser un defer(‘body’) pourrait être une possibilité , utiliser un values en serait une autre)

les champs deferred seront récupérés quand on les appelera explicitement. Pour annuler les defer d’un queryset, il suffit d’appeler la fonction avec None en paramêtre.

only (*fields)

C’est l’inverse du defer, on ne récupère que certains champs.

2- Les fonctions qui ne renvoient pas un queryset.

in_bulk(id_list)

Cette petite fonction bien sympa prend une liste de pk et renvoie un dico des objets qui correspondent (les clés étant les pk)

latest(field_name=None)

Renvoie le dernier objet, inséré dans la base, en se basant sur les dates et en utilisant le champ passé en paramètre (qui doit donc être un champ  date).
Si le model en question définit la Meta get_latest_by, on peut appeler latest sans argument.

Ok, cette fonction ‘ne sert à rien’ à part pour rendre plus lisible le code. Mais bon, ça ne mange pas de pain. Et l’utilisation de la Meta get_latest_by permet de ‘centraliser’ la façon de rechercher le dernier, ce qui rendra une modification plus facile.

aggregate(*args, **kwargs)

Retourne un dico des valeurs d’aggrégat calculés non pas objet par objet comme avec annotate, mais sur tout le queryset.

A vous les sommes de champ, les moyennes ou autre. Vive les rapports :) .

>>> q = Blog.objects.aggregate(Count('entry'))
{'entry__count': 16}
>>> q = Blog.objects.aggregate(number_of_entries=Count('entry'))
{'number_of_entries': 16}

et comme pour annotate, on peut contrôler le nom, ici de la clé, que notre valeur calculée.

exists()

cette fonction n’existe pas encore dans django, elle sera présente dans la 1.2. Elle permet tout simplement de savoir si le queryset est vide ou pas. (oui je sais, devoir attendre la 1.2 pour avoir cette fonction.. mais bon :) ).

[Afpy] Whyton Si vous n'aimez pas les espaces de la syntaxe Python...... 01/04/2010
Si vous n'aimez pas les espaces de la syntaxe Python...
[Afpy] Python WAW 2010 : Semaine 12 ... 29/03/2010
Python Week After Week : les liens de la semaine 12 de l'année 2010 de l'AFPY
[j-mad] Django-rosetta, parce que pierre qui roule n’amasse pas mousse ... 28/03/2010

Vous aimez mon titre ? Parce que moi, j’en suis super fier en fait. Et oui, il m’en faut peu. Bon donc pour la django-app du mois de février, j’avais choisi django-transmeta qui permettait de traduire facilement son contenu. Mais un site n’est pas fait que de contenu, il est aussi fait de label, de menu, de tout plein de truc qu’il faut internationaliser à coup de .po et de .mo. Ce qui est, il faut bien le dire, un poil chiant. Limite je pourrais dire, qu’à vouloir traduire tout ces mots, on pourrait bien finir par y laisser notre peau.

C’est là que django-rosetta intervient.

1- Où on le trouve, comment on l’installe, tout ça quoi (et la doc) ?

Comme bien souvent, sur la page qui lui est destiné, qui est, un google code. Pour l’installation, rosetta fait dans le rustique : tar.gz ou svn checkout. Brut mais efficace.

Ensuite il suffira de rajouter django-rosetta dans les INSTALLED_APPS  et de rajouter ses urls dans l’urlpattern qui va bien. Et c’est tout, après roule ma poule (ou ma pierre, de rosette HA HA).

Pour la doc, la encore, il n’y a que la page home du google code. Mais l’app est suffisament bien faite, pour que la doc présente soit amplement suffisante.

2- Comment ça marche ?

Django-rosetta vous permet de rendre la rédaction des .po moins chiante que dans un simple gedit. Mais du coup, cela veut dire que l’application a besoin d’avoir les permissions d’écritures sur certains des fichiers de votre arborescence.

Du coup, elle n’est utilisable que de l’admin django. C’est un choix qui me semble, en fait, très logique. Et puis est ce que cela existe des gens qui n’utilisent pas du tout la partie admin de django ?

Ensuite, c’est tout simple, on a une liste des fichiers po, avec les pourcentages de traduction effectuées. On en choisit un et on se met au boulot. On peut même choisir si l’on veut afficher toute s les chaines ou que celle que l’on n’a pas encore traduite.

Allez op, deux petites images pour vous montrer le truc, parce que je suis gentil. (Et puis que je ne me suis pas trop fatigué, je reprend honteusement celles du google code officiel).

Voilà, avec cette deuxième app, j’en ai fini de parler, en tout cas pour un temps, d’internationalisation. A bientôt (dans un mois) pour de nouvelles découvertes dans le merveilleux pays des app django.

Python.org : Le site officiel du langage Python.
Zope.org : Le site web officiel de Zope.
Daily Python-URL : Actus de l'univers Python.
Tribute to Zyons : Zyons notre ami et membre fondateur de l'Afpy, nous quittait en 2005.