Posts Tagged ‘Libre’

Django 1.4 passe à HTML5 ! et autres nouveautés

Tuesday, January 3rd, 2012

Le 22 décembre dernier est sorti Django 1.4 alpha 1. Comme on peu l’imaginer pour un projet d’une telle ampleur, cette nouvelle version apporte beaucoup de nouveautés. Je me contenterai d’en détailler rapidement cinq qui me semblent particulièrement intéressantes :

    1. Le passage au Doctype HTML5, tous les templates fournis avec Django, en particulier ceux de l’interface d’administration, utilisant donc désormais <!DOCTYPE html>. C’est un choix logique, qui permet d’utiliser toutes les nouvelles fonctionnalités de HTML5 sans plus se soucier de devoir corriger le Doctype.
    2. L’abandon du support de Python 2.4, datant de 2004, mais pas le passage à Python 3. Django supporte et est testé sur Python 2.5, 2.6 et 2.7.
    3. Le nouveau framework de test LiveServerTestCase, compatible avec Selenium et Windmill, pour tester l’interface de votre application web côté client (dans le navigateur web).
    4. La nouvelle option --template pour les commandes startapp et startproject, permettant de leur spécifier aisément un template personnalisé.
    5. La nouvelle clause elif pour la balise if. Elle permettra de ne plus avoir à imbriquer plusieurs if then else et autant d’indentations ou à se définir une balise personnalisée. Alors oui j’ose le dire : c’est pas trop tôt !

On voit donc qu’encore une fois Django continue d’avancer dans la bonne direction, bonifiant sans cesse une base déjà excellente. La seule chose que je regrette encore et toujours, c’est la défiance manifeste de la core team envers l’intégration de django-nonrel… peut-être pour Django 1.5 ?

La compréhension de liste en Python, une syntaxe moderne pour map() et filter()

Monday, December 5th, 2011

La compréhension de liste est un syntactic sugar pour les fonctions classiques de la programmation fonctionnelle que sont map() et filter(). Disponible depuis Python 2.0, la compréhension de liste devrait à terme amener à la disparition des fonctions map() et filter() du langage Python, ce que Guido van Rossum avait déjà envisagé pour Python 3.

Ainsi, si vous avez du “vieux code” utilisant ces fonctions, je vous encourage à le porter vers cette nouvelle syntaxe beaucoup plus lisible et plus pythonique. J’espère que cet article pourra aider certains à éviter les pièges qui pourraient apparaître devant eux lors de cette démarche.

map()
Commençons d’abord par la fonction map(), dont la syntaxe est map(fonction, liste). Prenons un exemple très simple, avec une fonction anonyme lambda qui à tout x élément de la liste des chiffres de 0 à 9 associe 2 fois x.

>>> map(lambda x: 2*x, range(10))
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

On obtient l’équivalent de la fonction map() avec une compréhension de liste de la forme [fonction(x) for x in liste], ce qui donne pour notre exemple :

>>> [2*x for x in range(10)]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

filter()
La syntaxe de la fonction filter() est filter(fonction, liste). Prenons ici aussi un exemple très simple, avec une fonction anonyme lambda qui n’est Vrai pour chaque x élément de la liste des chiffres de 0 à 9 que s’il est strictement supérieur à 5.

>>> filter(lambda x: x>5, range(10))
[6, 7, 8, 9]

On obtient l’équivalent de la fonction filter() avec une compréhension de liste de la forme [x for x in liste if fonction(x)], et donc notre exemple devient :

>>> [x for x in range(10) if x>5]
[6, 7, 8, 9]

Un des grands intérêts des fonctions est de pouvoir être composées. Cependant, cette opération de composition n’est pas anodine, et il faut bien envisager les différents cas pour ne pas commettre d’erreur.

map o filter()
La composition notée map o filter() revient à map(filter()), c’est-à-dire à appliquer d’abord la fonction filter(), puis la fonction map(). Si nous combinons nos deux premiers exemples, nous obtenons :

>>> map(lambda x: 2*x, filter(lambda x: x>5, range(10)))
[12, 14, 16, 18]


On obtient l’équivalent de la composition de fonction map o filter() avec une compréhension de liste de la forme [fonction_map(x) for x in liste if fonction_filter(x)], ce qui donne ici :

>>> [2*x for x in range(10) if x>5]
[12, 14, 16, 18]

La composition de fonction map o filter() ne pose pas de problème.

On remarque que plus l’on compose des fonctions map() et filter(), plus l’avantage syntaxique de lisibilité et de compréhensibilité des compréhensions de liste augmente.

filter o map()
Mais qu’en est-il de la composition notée filter o map(), qui revient à filter(map()), c’est-à-dire à appliquer d’abord la fonction map(), puis la fonction filter(). Si nous combinons ici aussi nos deux premiers exemples, nous obtenons :

>>> filter(lambda x: x>5, map(lambda x: 2*x, range(10)))
[6, 8, 10, 12, 14, 16, 18]

Le résultat retourné est différent de celui obtenu à l’exemple précédent avec une compréhension de liste de la forme [fonction_map(x) for x in liste if fonction_filter(x)]. En fait, la bonne compréhension de liste est :

>>> [2*x for x in range(10) if 2*x>5]
[6, 8, 10, 12, 14, 16, 18]

Nous voyons que la composition de fonction filter o map() pose des problèmes, et qu’il faudra y porter une attention particulière en cas de conversion de vieux code fonctionnel en compréhensions de liste.

filter o filter()
La composition notée filter o filter() revient à filter(filter()), c’est-à-dire à appliquer deux fois de suite la fonction filter(). Nous allons donc rajouter une deuxième condition à notre premier exemple de filter(), qui sera que chaque élément x devra en plus être strictement inférieur à 8.

>>> filter(lambda x: x<8, filter(lambda x: x>5, range(10)))
[6, 7]

Le même résultat est obtenu en inversant l’ordre des deux conditions :

>>> filter(lambda x: x>5, filter(lambda x: x<8, range(10)))
[6, 7]

La composition filter o filter() est commutative, et peut en fait facilement se factoriser sous la forme :

>>> filter(lambda x: x>5 and x<8, range(10))
[6, 7]

On obtient l’équivalent de la composition de fonction filter o filter() avec une compréhension de liste de la forme [x for x in liste if fonction_filter_1(x) and fonction_filter_2(x)], ce qui donne ici :

>>> [x for x in range(10) if x>5 and x<8]
[6, 7]

La composition de fonction filter o filter() ne pose pas de problème.

map o map()
Mais qu’en est-il de la composition notée map o map(), qui revient à map(map()), c’est-à-dire à appliquer deux fois de suite la fonction map() ? Rajoutons une deuxième fonction à notre premier exemple de map(), qui à chaque x associera x plus 1.

>>> map(lambda x: x+1, map(lambda x: 2*x, range(10)))
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

et

>>> map(lambda x: 2*x, map(lambda x: x+1, range(10)))
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

ne donnent pas les mêmes résultats. La composition map o map() n’est pas commutative. On obtient l’équivalent de la composition de fonction map o map() avec une compréhension de liste de la forme [fonction_map_2(x) for x in [fonction_map_1(x) for x in liste]], ce qui donne ici :

>>> [x+1 for x in [2*x for x in range(10)]]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

et

>>> [2*x for x in [x+1 for x in range(10)]]
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

Il est possible de factoriser les deux fonctions map() comme nous l’avons fait pour les fonctions filter(), mais il faut faire très attention à l’ordre de composition des fonctions. Dans le premier cas on a (2*x)+1 = 2*x+1 qui donne :

>>> [2*x+1 for x in range(10)]
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]

et dans le deuxième cas on obtient 2*(x+1) = 2*x+2 qui produit :

>>> [2*x+2 for x in range(10)]
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

Nous voyons que la composition de fonction map o map() pose des problèmes.

Pour ne pas tomber dans des pièges, il suffit de retenir que toutes les compositions de fonctions qui commencent par une fonction map() sont dangereuses, alors que celles commençant par une fonction filter() sont sans danger.

Pour mon plus grand bonheur, la syntaxe de compréhension de liste rend particulièrement pythonique et centrale au langage Python une partie de la sémantique de la programmation fonctionnelle qui y était jusqu’à présent mal intégrée et mal aimée. Encore une fois, et même si certains de mes professeurs d’informatique ne l’ont jamais accepté, sans une bonne syntaxe, une sémantique géniale n’est rien.

Steve Jobs est mort, un pionnier de l’informatique disparaît

Thursday, October 6th, 2011

Steve Jobs est mort hier, seulement un mois et demi après s’être retiré de son poste de CEO d’Apple. Il aura donc mené sa passionnante vie jusqu’à la toute dernière limite de ses possibilités physiques.

En tant qu’informaticien, et en tant que simple utilisateur d’ordinateur, je le remercie d’être allé voler les idées géniales et inexploitées d’interfaces graphiques et de souris au PARC, le Palo Alto Research Center de Xerox, dont la photo orne toujours la porte de ma chambre.

Et d’en avoir conçu en 1983 le premier ordinateur personnel utilisable par une personne normale, nommé Lisa (le prénom de sa fille).

Quand il fut viré d’Apple par John Sculley en 1985, il fonda une entreprise nommée NeXT. Le nom de domaine que j’utilise, FLeXT, y fait directement référence.

Avec NeXTSTEP, il créa le premier Unix doté d’une interface graphique innovante tant d’un point de vue technique qu’ergonomique, que l’on connaît encore aujourd’hui sous le nom de Mac OS X (avec un look un peu plus eye candy), et dont le projet GNUstep est une réimplémentation libre des APIs.

J’ai très longtemps utilisé exclusivement Window Maker, un gestionnaire de fenêtre libre pour X11 réimplémentant l’ergonomie de NeXTSTEP.

Merci à toi Steve d’avoir été à l’origine de certains des plus beaux designs de l’histoire de l’informatique, comme la première version de la NeXTstation, avec son écran noir et blanc NeXT MegaPixel de 17″ dont un exemplaire est encore stocké dans ma cave, alors qu’une NeXTstation TurboColor est toujours présente sur mon bureau pour rehausser mon écran ;

comme l’Apple Cube dans l’esprit duquel, avec l’aide de Philou, j’ai essayé de réaliser un boîtier en plexiglas pour une carte mère mini-ITX ;

et bien sûr comme le sublime iMac Tournesol, dont je serais très heureux de récupérer un modèle 20″ !

 

Merci aussi d’avoir longtemps été l’un des seuls à tenir tête à Bill Gates et à son empire de médiocrité informatique nommé Microsoft. Bravo pour avoir eu l’intelligence technique d’utiliser massivement les logiciels libres, qui sont la composante principale des systèmes Mac OS X et iOS diffusés par Apple, même si tu n’en as pas compris la puissance politique.

Alors bien sûr, l’Apple d’aujourd’hui, première valorisation boursière mondiale, l’Apple des bobos, des DRM et des iBidules, très peu pour moi comme pour tous les libristes. Mais Steve Jobs a fait bien d’autres choses que cela, c’est un exceptionnel pionnier de l’informatique qui nous a quitté hier.

 

 

Freebox, enfin le code source !

Wednesday, September 14th, 2011

 

Après de trop longues tergiversations, et en accord avec l’article 11.5.2 de ses nouvelles conditions générales de vente du 1er août 2011, Free se met enfin en conformité avec les termes de la licence GNU GPL et de son Copyleft, en donnant accès aux codes sources modifiés utilisés dans les Freebox !

C’est le dernier des trois grands FAI français à effectuer cette démarche, SFR ayant ouvert un premier site en 2007, puis un second en 2010 pour les sources de sa NeufBox, et Orange un site en 2009 pour les sources de sa LiveBox. Il semblerait d’ailleurs qu’il y ait une belle dynamique de création de firmwares alternatifs pour la NeufBox, puisque c’est la seule des trois box à ne pas être victime de tivoisation, c’est-à-dire d’un système électronique empêchant l’utilisation d’un firmware modifié.

Si la liste des logiciels libres utilisés dans ces box est très longue, les composants de base sont le noyau Linux et la mini boîte à outils Unix BusyBox, qui sont tous les deux sous licence GNU GPLv2. L’action en justice entreprise en 2008 contre Free par Harald Welte, pour son code de Netfilter dans le noyau Linux, et les développeurs de BusyBox Erik Andersen et Rob Landley, trouve ici son dénouement logique. On appréciera au passage  le travail de Maître Olivier Hugot dans ce dossier.

Pour les personnes qui auraient encore eu un doute, la licence GNU GPL et le Copyleft ont une validité juridique incontestable, et si vous voulez utiliser des codes sources qui y sont soumis, vous devez en respecter les règles, toutes les règles.

L’impact de Django

Thursday, September 1st, 2011

Armin Ronacher, membre de la Pocco Team, est le principal développeur de nombreux projets libres comme le langage de template Jinja et le microframework Flask, qui sont des programmes Python très populaires et d’excellente qualité.

Le 8 juin, lors du DjangoCon Europe 2011, il a fait une présentation intitulée The Impact of Django ayant un contenu similaire en bien des points à mon article du 6 juin intitulé Et le meilleur framework web Python est… Django !. Vous pouvez voir la conférence en ligne et en consulter ou télécharger les slides.

Bien sûr, il est assez plaisant de constater qu’un développeur, qui n’est pas loin d’être le meilleur au monde sur le sujet, fait une analyse très proche de la mienne en particulier en prenant le contre-exemple de TurboGears et en montrant l’influence du langage de template de Django. Cependant, il ajoute deux éléments  d’analyse, l’un social et l’autre juridique.

Premièrement, Armin pense que, d’une manière assez similaire à Ruby on Rails pour Ruby, Django est actuellement la locomotive du langage Python :

Django is the reason Python is getting that much attention lately.

Ainsi, environ 1 200 des 15 000 paquets disponibles sur PyPi contiendraient “Django” dans leur nom, de même que 10 000 des 77 000 dépôts sur GitHub et 3 000 dépôts sur Bitbucket. Si Python est beaucoup plus utilisé que Ruby en dehors du web, l’importance de ce dernier est telle qu’il est logique que le logiciel qui y est leader soit aussi le leader du langage.

Deuxièmement, Armin lie le succès de la licence BSD dans la communauté Python avec celui de Django et de son écosystème. Ansi 700 des 2 500 paquets sous licence BSD sur PyPI sont classés Django. Et surtout la licence BSD semble être utilisée par des projets assez récents, quand les plus anciens privilégiaient la licence GNU GPL.

Le choix de la licence est quelque chose de fondamental pour un logiciel libre, et il faut réfléchir aux implications réelles qui en découlent. En pratique, dans le contexte du serveur web qui est celui de Django, la licence GNU GPL n’est pas spécialement plus contraignante qu’une licence BSD, n’obligeant pas à redistribuer le code source modifié, et choisir l’une plutôt que l’autre n’a donc pas vraiment de signification pertinente.

Pour ce type de logiciel, si l’on veut voir s’appliquer la puissance du copyleft, il faut utiliser la licence GNU Affero GPL. À titre personnel, c’est la licence que je conseille, mais si l’on veut une licence libérale, alors je trouve effectivement plus clair de choisir une licence BSD qu’une licence GNU GPL vidée de sa substance par le contexte du logiciel serveur.

Comparaison des langages de balisage (markup) léger (lightweight) : Txt2tags, Pandoc, Docutils, AsciiDoc, Deplate, Stx2any, AFT, Markdown et Textile

Sunday, August 14th, 2011

La bureautique est la principale utilisation de l’informatique depuis sa création. Pourtant, les outils majoritairement utilisés dans ce domaine, les logiciels de traitement de texte WYSIWYG comme LibreOffice et OpenOffice, laissent la majorité des informaticiens et des ergonomes très dubitatifs, voire totalement désespérés.

Ces logiciels ont en effet un nombre de défauts très important : ils font se concentrer sur la forme et non sur le fond, leur résultat final ne correspond souvent pas à ce qui est affiché, ils sont incompatibles entre eux, ce sont d’énormes usines à gaz inutilisables sur de vieilles machines, ils ne fonctionnent qu’en mode graphique, etc. La seule manière rationnelle, efficace et interopérable de travailler sur un ordinateur est d’utiliser de simples fichiers textes, tous les documents étant donc modifiable dans n’importe quel éditeur de texte.

Il a donc fallu penser à une manière de donner ces instructions de mise en forme au sein du fichier texte lui-même, et c’est ainsi que sont apparus les langages de balisage (markup), dont les plus connus sont HTML (inventé en 1991 par Tim Berners-Lee) et LaTeX (créé en 1985, et basé sur TeX, inventé par le grand Donald Knuth en 1977), et dont la première grande figure fut Roff, un programme Unix historique développé à partir de 1961, et dont la version GNU, Groff, est installée par défaut sur toutes les distributions Linux, puisqu’on l’utilise encore pour les pages de man des logiciels.

Pour mieux visualiser, prenons comme exemple la création d’une nouvelle section d’un document en man :

.SH Nouvelle section en man

en HTML :

<h1>Nouvelle section en HTML</h1>

et en LaTeX :

\section{Nouvelle section en LaTeX}

Ces langages représentent une nette amélioration, mais ont tous un gros problème : ils sont gênants ! On ne retrouve plus aussi facilement son contenu au milieu de toutes ces balises supplémentaires, sans parler du fait que les syntaxes complexes ouvrent la voie à de nombreuses erreurs de compilation.

C’est en 1995 que l’on trouva la solution de ce problème, avec la création du premier langage Wiki, dont le but principal était de permettre l’édition facile de pages web par tout un chacun, et dont l’utilisateur actuel le plus célèbre est l’encyclopédie libre Wikipédia. S’il y a presque autant de syntaxes différentes que de logiciels Wiki, elles ont toutes la caractéristique d’utiliser des caractères textuels simples et intuitifs pour donner les indications de formatage du texte.

Toujours le même exemple, une nouvelle section en MediaWiki :

= Nouvelle section Wiki =

et une en Setext :

Nouvelle section Setext
=======================

Mais pourquoi limiter ces langages de balisage léger à la seule génération de HTML ? Pourquoi ne pas utiliser la même syntaxe pour différentes cibles (appelées backends, targets ou writers selon les logiciels), de manière à obtenir aussi bien une page web en HTML, qu’un document en LaTeX pour l’impression, ou qu’une page de man pour un logiciel ? Ce sont les logiciels qui poursuivent ce but qui m’intéressent, ils constituent pour moi l’avenir de la bureautique informatique, et j’ai été amené à les comparer pour en choisir un dans lequel m’investir comme développeur.

Voici un tableau comparatif des meilleurs logiciels libres existants, avec comme information supplémentaire l’existence d’une cible texte brut, puisque je souhaitais me baser sur ce code pour programmer certaines de mes idées ASCII art.

Les logiciels complets

NomLangage de programmationPopularité du projeti18nCible texte brutLicence
Txt2tagsPythonmoyenne + RedNotebookOui + docOuiGNU GPLv2
DocutilsPythonforte + SphinxNonNonDomaine public
AsciiDocPythonforteNonDump de w3m ou de LynxGNU GPLv2 ou suivante
DeplateRubyfaibleNonOuiGNU GPLv2 ou suivante
PandocHaskellmoyenneNonOuiGNU GPLv2 ou suivante
Stx2anySed et m4faibleNonDump de w3mLicence copyleftée personnalisée
AFTPerlfaibleNonNonClarified Artistic License

Exceptés Docutils et AFT (Almost Free Text), tous les logiciels semblaient au premier abord proposer une cible texte. Mais en fait c’est un peu un trompe l’œil, car deux d’entre eux, AsciiDoc et Stx2any, se contentent de dumper un navigateur web en mode texte (w3m ou Lynx) du résultat généré par leur cible HTML. Il n’y avait donc pas dans ces cas de base de code que je pouvais espérer améliorer.

J’ai mis dans le comparatif stx2any et AFT codés respectivement en m4 et en Perl, de manière à proposer un large éventail de langages de programmation, mais ces logiciels sont à la fois moins utilisés et dotés de moins de fonctionnalités que les autres. En étudiant les différents logiciels disponibles, je me suis rendu compte que, par chance pour moi, beaucoup étaient codés en Python (3 sur 7 au total, mais surtout 3 sur les 5 vraiment intéressants). Ce n’est d’ailleurs pas la première fois que je constate, en cherchant à sélectionner des logiciels libres, que ceux codés en python sont à la fois les plus nombreux et les meilleurs.

Les cinq logiciels restants sont vraiment excellents, et constituent tous un bon choix. Trois d’entre eux, Docutils, Deplate et Pandoc, ont un design évolué, avec une machine à états finis pour laquelle on peut écrire de nouveaux readers et writers de manière parfaitement propre. Cependant, malgré leurs grandes qualités, Deplate est un projet trop confidentiel (ainsi il n’est incompréhensiblement pas présent parmi les pourtant si nombreux paquets Debian), et je ne me sentais pas à la hauteur pour m’investir dans un projet comme Pandoc, totalement écrit en Haskell, qui est un langage de programmation complexe que j’aimerais beaucoup utiliser, mais où ma compétence est encore trop limitée.

Il fallait donc que j’approfondisse ma réflexion sur les logiciels en Python :

Choix en Python

NomCibles principalesCible texte brut
Txt2tagsHTML, Latex et syntaxes WikiOui
DocutilsHTML et LatexNon
AsciiDocHTML et DocBookDump
MarkdownHTMLNon
TextileHTMLNon

J’ai rajouté dans ce comparatif Markdown et Textile, puisqu’ils ont chacun une implémentation en Python, mais ne générant que du HTML, ils ne m’intéressaient pas vraiment. AsciiDoc et Txt2tags ont un peu la même architecture, avec un gros fichier principal faisant tout le travail, que l’on peut configurer, respectivement avec un fichier .conf et deux dictionnaires Python (un pour les Tags et l’autre pour les Rules), pour créer de nouvelles cibles. AsciiDoc et Txt2tags sont donc plus aisés à prendre en main et à modifier rapidement que Docutils, qui est une très belle et très bien architecturée machine à états objet, mais aussi plus difficile à appréhender.

De plus, comme je désapprouvais totalement la politique de licence domaine publique de Docutils, il ne me restait plus qu’à faire mon choix entre Txt2tags et AsciiDoc. C’est principalement l’orientation très DocBook (un format ne m’intéressant personnellement pas du tout) d’AsciiDoc, et d’autres détails, comme la localisation en de nombreuses langues de Txt2tags et sa plus grande simplicité, qui m’ont finalement fait choisir Txt2tags.

Ce choix est confirmé par une étude plus avancée des différentes syntaxes. Ainsi alors que la syntaxe reST de Docutils ne dispose que de :

*italique* et **gras**

Txt2tags est beaucoup plus riche :

//italique// **gras** __souligné__ et --barré--

Le codage visuel est bien meilleur, et le compréhension instantanée avec la syntaxe de Txt2tags, puisque les slashs donnent l’impression penchée de l’italique, les étoiles imitent la surcharge du gras, les underscores donnent l’impression de soulignement, et les moins apparaissent comme une barre. De plus, l’utilisation généralisée des caractères de balisage en doubles, permet de lever à peu de frais un maximum d’ambiguïtés syntaxiques.

Par exemple une phrase aussi simple que celle contenue dans le fichier d’exemple de Txt2tags :

We use double *, /, - and _ to represent **bold**, //italic//, --strike-- and __underline__.

et qui ne pose aucun problème :

est en fait déjà trop ambigüe en reST, puisque :

We use double *, /, - and _ to represent **bold**, *italic*, strike and underline.

donnera :

De manière générale, la syntaxe reST est souvent trop lourde. Par exemple dans le cas de l’insertion d’une image servant de lien :

.. image:: picture.png
:target: http://fgallaire.flext.net

que l’on peut comparer avec le beaucoup plus simple Txt2tags :

[[picture.png] http://fgallaire.flext.net]

On remarque bien sûr ici que la syntaxe reST offre sûrement plein d’autres options que la simple :target:, et qu’elle est donc plus puissante que celle de Txt2tags. Cependant, mon avis est que la pénalité de lourdeur est toujours présente, alors qu’elle n’est utile que dans peut-être 1% des cas.

Voici maintenant un comparatif des logiciels disponibles par syntaxe :

Classement par syntaxe

UsageTxt2tagsAsciiDocreStructuredTextMarkdown
BureautiqueTxt2tagsAsciiDocDocutils
Pandoc
Pandoc
Web serveurTxt2tags (Python)AsciiDoc (Python)Docutils (Python)Perl
Python
Ruby
PHP
Web clientJavaScript

Leur implémentation en Python permet à Txt2tags, reST (par Docutils) et AsciiDoc d’être utilisables à la fois comme logiciels de bureautique multiplateforme (Linux, Mac OS X, Windows et *BSD) et pour le web côté serveur. En face, Markdown est représenté par une armada d’implémentations dans tous les langages utilisés sur le web côté serveur, et aussi en JavaScript côté client pour des prévisualisation efficace sans Ajax, mais seul Pandoc, qui n’est pas si facile à compiler sur toutes les plateformes, propose autre chose qu’un rendu en HTML.

Je vais bien sûr continuer à travailler sur le logiciel Txt2tags, mais une implémentation de la syntaxe Txt2tags en JavaScript pour un rendu live sur le net, ainsi que des readers Pandoc, car j’ai vraiment envie de programmer en Haskell, et Docutils, pour pouvoir bénéficier ensuite du sublime Sphinx, sont des projets qui me motivent de plus en plus.

Enfin, je suis toujours un peu nostalgique devant ce screenshot, parce que c’est en le voyant, avec en haut à gauche le fichier avec les balises, et en bas à droite celui avec le résultat texte brut, que j’ai pris conscience que Txt2tags faisait bien ce que j’espérais, et que comme en plus il était en Python, ce serait probablement le logiciel auquel j’allais contribuer !

Compter récursivement le nombre de lignes avec wc (Word Count)

Monday, August 1st, 2011

Comme j’ai passé beaucoup de temps à programmer sur Txt2tags en juin et en juillet, j’ai été amené à comparer avec mon ami Carl le nombre de lignes de code de nos projets libres respectifs. Or, contrairement à grep, wc ne fournit pas d’option -r pour activer la récursivité.

Pour pallier cela, l’utilisation des classiques commandes Unix find et xargs est de rigueur. Ainsi, pour avoir le nombre total de lignes de tous les fichiers du répertoire faites :

$ find . -type f | xargs wc -l

Si, comme moi, seuls les fichiers python vous intéressent, vous pouvez ajouter un grep au milieu qui filtrera tous les noms de fichier se finissant par .py :

$ find . -type f | grep .py$ | xargs wc -l

Ou, encore plus simple, vous pouvez utiliser l’option -name de find :

$ find . -name "*.py" | xargs wc -l

Et le meilleur framework web Python est… Django !

Monday, June 6th, 2011

On  observe depuis quelques temps un phénomène de “consolidation” au niveau de beaucoup de logiciels libres. En effet, le modèle du libre est par essence de permettre à chacun de faire se qu’il veut, et donc d’expérimenter et d’innover. Cette dynamique est encore plus sensible quand il s’agit de technologies nouvelles. Mais une fois cette phase d’expérimentation passée, il faut aussi en tirer des conclusions, et se rassembler pour atteindre une masse critique d’utilisateurs et de développeurs, une communauté, qui viabilise le projet sur la durée.

Ainsi Ruby on Rails a été dès 2004 le grand précurseur des frameworks web de nouvelle génération. Mais même dans le monde Ruby des projets concurrents sont apparus, dont le plus important fut Merb, un framework plus léger et plus modulaire. En décembre 2008, Merb et RoR ont fusionné pour donner Ruby on Rails 3, et ainsi rassembler les énergies et les talents.

La situation dans le monde Python, bien que beaucoup plus complexe, a pris le même chemin. En effet, il existait depuis longtemps un grand nombre de technologies web en Python, aussi bien des serveurs d’application comme CherryPy ou Paste, que des langages de templates comme Myghty, Python Server Pages ou Cheetah. On ne peut que constater cette incroyable diversité sur le site officiel de Python. Une blague classique était de dire que Python était un langage tellement simple que chaque développeur pouvait écrire son propre framework. Mais aucun ne proposait un ensemble cohérent et tout intégré… aucun sauf Zope 2, mais qui lui avait comme défaut principal d’être trop intégré !

Ainsi, si sa ZODB, une vraie base de données orientée objet, était en avance techniquement sur un ORM (Object-Relationnal Mapping), c’est-à-dire une simple surcouche pour donner une apparence objet à une base de données relationnelle (SQL), elle a néanmoins fait fuire la majorité des développeurs, qui avaient comme contrainte non négociable de s’interfacer avec des bases de données MySQL, PostgreSQL ou Oracle préexistantes. De plus Zope 2 est connu pour sa courbe d’apprentissage en “Z” (Z-shaped learning curve), qui vous donne d’abord l’impression de régresser et nécessite beaucoup de temps et d’efforts avant d’obtenir un premier résultat intéressant, ainsi que pour mériter le fameux qualificatif “d’usine à gaz logicielle”.

En janvier 2006, Stéphane Fermigier, président fondateur de Nuxeo, essayait d’y voir plus clair grâce à ce schéma :

On peut identifier cinq concurrents directs, de type framework web complet : CPS, Django, TurboGears, Subway et Pylons, ainsi qu’un serveur d’application moderne orienté composant, n’attendant que de servir de base pour de nouveaux frameworks : Zope 3.

Que sont-ils tous devenus ? Il y a d’abord ceux qui sont morts, Subway, de manière classique dans le monde du libre, par désintérêt (des développeurs et/ou des utilisateurs), et CPS, de manière plus originale, en se faisant “seppuku” (d’un point de vue pythonique), en décidant de changer de base technologique, passant de Zope 2 et Python à J2EE et Java.

Restaient donc trois frameworks, Django, un ensemble complet et monolithique d’un côté, et TurboGears et Pylons de l’autre, qui essayaient quant à eux de réutiliser au maximum les nombreux projets python existants. Ainsi, Django a souvent été accusé de souffrir du syndrome NIH (Not Invented Here), voir l’intéressante conférence de Mark Ramm (principal développeur de TurboGears) sur le sujet lors du DjangoCon 2008. Il y eu donc naturellement un rapprochement entre TurboGears et Pylons, et en juin 2007 Mark Ramm annonça que le futur TurboGears 2 serait basé sur Pylons. au grand désarroi de CherryPy.

D’un autre côté apparurent plusieurs frameworks, dont Grok et repoze.bfg, prenant comme base technologique Zope 3, mais en essayant de le rendre plus facile à utiliser et à configurer, par exemple en vous préservant de trop nombreux fichiers ZCML. Et voilà qu’en novembre 2010, Pylons et repoze.bfg fusionnent pour donner naissance à un nouveau framework soutenu par le Projet Pylons et appelé Pyramid, qui se base sur le code source de repoze.bfg et son architecture à composant, Pylons ne pouvant plus évoluer à cause d’un problème de design. Enfin, en décembre, c’est TurboGears qui fusionne avec Pyramid.

Trois frameworks qui ne font donc plus qu’un, espérant qu’en additionnant toutes leurs forces ils pourront constituer un adversaire crédible à Django. Mais un survol du tutoriel rapide m’a fait froid dans le dos : du SQL à la main (c’est bien la dernière chose que je souhaitait revivre) et des décorateurs pour spécifier le langage de template pour chaque view !? Comme en plus je ne suis pas convaincu que l’architecture à composant enthousiasme grand monde, j’ai de gros doutes sur l’avenir de Pyramid.

On en est donc arrivé à un point où les concurrents de Django ont soit disparu, soit fusionné. Alors qu’il a lui continué son chemin sans trop d’embûches, en étant en particulier extrêmement stable technologiquement. Imaginez le cauchemard du développeur TurboGears, qui a d’abord appris Kid, CherryPy et SQLObject dans la version 1, puis Genshi, Paste et SQLAlchemy dans la version 2, et qui doit maintenant ouvrir son esprit à l’architecture composant de Pyramid ! Les développeurs Django n’ont eux jamais eu à vivre ce genre de choses, et ce à mon avis grâce aux excellents choix de design logiciel faits dès le départ :

  1. Le langage de template de Django est devenu un standard, utilisé par le Google App Engine et repris dans de nombreuses autres implémentations comme Jinja et le langage de template de Tornado en Python, ErlyDTL en Erlang, Twig (le langage de template de Symfony2) et H2O en PHP, Liquid en Ruby, Dotiac en Perl, Jangod en Java, NDjango en F#, ou encore djangode de node.js et le langage de template de Dojo en JavaScript. Cette réussite est principalement due à la simplicité de ce langage de template qui est “stupide”, ce qui force à mettre la logique de traitement hors des templates, et n‘a pas une  syntaxe XML, ce qui le rend utilisable facilement par des humains. Enfin, en janvier 2006 c’est le créateur de Python, Guido Van Rossum en personne, qui le consacre comme son choix personnel.
  2. Beaucoup décriaient l’ORM de Django, qu’aucun autre projet n’utilisait, et conseillaient l’utilisation de SQLobject -un changement-… puis de SQLAlchemy -un deuxième changement-, juste pour faire comme les autres frameworks Python… Puis les bases de données NoSQL sont arrivées, que ni SQLobject, ni SQLAlchemy n’ont vocation de supporter (ce n’est plus du SQL !), alors que l’ORM de Django s’adapte elle à la situation grâce au projet Django-nonrel, qui sera je l’espère bientôt intégré dans la branche principale.
  3. Le choix standard du langage de template et de l’ORM a permis et encouragé l’émergence d’un écosystème de nombreuses applications, toutes compatibles entre elles, et de snippets permettant aux développeurs de ne pas sans cesse réinventer la roue logicielle. De plus ils peuvent se baser sur l’un des nombreux sites libres disponibles pour créer les leurs. À l’opposé d’un Pylons qui laissait la liberté de ces choix, et qui n’a donc jamais pu bénéficier d’une dynamique comparable, Django est devenu une plateforme de développement autonome et incroyablement riche.

Ce développement cohérent et linéaire depuis 2005 a permis la constitution d’un large communauté et rendu Django suffisamment crédible et répandu en entreprise pour que l’on puisse trouver assez facilement un travail, un job, un emploi, ou encore un autre travail ou un autre job, de développeur rémunéré à plein temps pour travailler sur une technologie libre qu’il aime (je n’ai pas dit faire du libre), ce qui est encore trop rare.

Alors bien sûr vous pouvez aussi utiliser web2py, Tornado pour faire de l’asynchrone, un des nombreux microframeworks, ou encore créer le vôtre avec WebOb, si vous êtes bons, vous ferez d’excellentes choses. Mais LE meilleur framework web Python, c’est Django !

Mise à jour du 28 juillet 2011 : J’ai rajouté trois liens dans l’article. De plus, Georges Racinet m’a gentiment contacté pour me faire part du fait qu’il est mainteneur de CPS depuis trois ans, et que si le projet a “une communauté restreinte et peu de visibilité, il n’est pas mort et il y a du dév actif dessus”.

Head et tail de liste en Python 3

Saturday, April 23rd, 2011

Bien que Python ne soit pas un langage de programmation fonctionnelle, il incorpore un certain nombre de fonctionnalités typiques de ces langages. Ainsi les fonctions anonymes lambda, la compréhension de liste, ou encore les fonctions built-in map(), filter() et reduce() (cette dernière ayant été supprimée dans Python 3).

La programmation fonctionnelle est caractérisée par une utilisation intensive des listes, et en particulier par de nombreuses opérations récursives sur ces dernières. On est donc souvent amené à vouloir récupérer le premier élément d’une liste, sa tête ou head, et l’ensemble des éléments restants, sa queue ou tail. Ce qui s’écrit donc trivialement avec la fonction f() retournant une liste :

head, tail = f()[0], f()[1:]

Le premier problème ici est le double appel de la fonction f(), que l’on peut facilement corriger grâce à l’utilisation d’une variable intermédiaire result :

result = f()
head, tail = result[0], result[1:]

Le second problème est la lourdeur syntaxique de l’ensemble, avec la variable intermédiaire et le double usage du [] (le __getitem__ des listes en Python). On aimerait bien à la place avoir une syntaxe plus adaptée, c’est-à-dire plus proche de celles utilisées par les langages de programmation fonctionnelle, comme par exemple Erlang :

[Head|Tail] = Result

Et comme toujours avec Python, le langage se bonifie grâce à une PEP (Python Enhancement Proposal), en l’occurence la PEP 3132 intitulée Extended Iterable Unpacking. Ainsi, depuis Python 3.0, on peut utiliser une nouvelle syntaxe qui reprend celle des star-args (*args) des fonctions Python :

head, *tail = result

Ceci se teste facilement dans un shell Python 3 :

>>> result = [1, 2, 3, 4]
>>> head, *tail = result
>>> head
>>> 1
>>> tail
>>> [2, 3, 4]

On a donc maintenant une syntaxe tout à fait satisfaisante, très lisible et facilitant un style de programmation fonctionnel. Ce qui est encore plus intéressant avec cette notation, c’est qu’elle ne se limite pas au couple head et tail, et peut ainsi être déclinée de bien des manières tout à fait intéressantes comme par exemple :

>>> result = [1, 2, 3, 4]
>>> head, *body, tail = result
>>> head
>>> 1
>>> body
>>> [2, 3]
>>> tail
>>> 4

Python 3 est sorti depuis plus de deux ans et, sans être révolutionnaire, il apporte de nombreuses améliorations à Python 2 qui valent le coup d’être découvertes et utilisées !

Zack 2.0

Wednesday, April 20th, 2011

Zack

C’est officiel depuis le 16 avril, Stefano Zacchiroli (Zack) vient d’être réélu Debian Project Leader. Sans surprise, car comme vous pourrez le constater à la vue des résultats, l’option 1 “Stefano Zacchiroli” était seulement concurrencée par l’option 2 “None Of The Above”, et ces deux options ne constituaient donc pas une réelle alternative.

null

Le fait que Zack soit le seul candidat a provoqué un petit débat sur le caractère démocratique du vote, lui-même regrettant de ne pas avoir “d’adversaire”. Mais cela aurait-il été mieux  avec un “adversaire” fantoche, ayant le rôle pré-attribué du perdant de l’élection, comme caution démocratique ? En fait, nous sommes ici confrontés à un faux problème, lié à l’erreur très répandue d’établir l’unité entre démocratie et élections, quelque chose que l’on pourrait écrire :

démocratie = élections

alors que même sans chercher trop loin, et en utilisant le ou informatique, c’est-à-dire non exclusif, on peut proposer facilement le beaucoup plus riche :

démocratie = consensus ou élections ou manifestations ou insurrections

Zack, dont l’action comme DPL cette année a de toute évidence été grandement appréciée, a fait consensus sur son nom. Tout le monde le sait depuis la clôture de la période de candidature le 12 mars.

Sauf a faire du fétichisme du vote, on aurait pu apprécier la chance qu’une communauté aussi grande et diverse arrive à un consensus, et se baser sur cette dynamique pour commencer des actions utiles, plutôt que d’organiser un vote inutile et absurde.

Zack, dont les qualités aussi bien techniques qu’humaines sont reconnues de tous, a un an de plus pour mettre en œuvre son programme, et il est certain qu’avec l’expérience qu’il a maintenant, il sera encore meilleur que l’année dernière !