<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://flux.ducastel.name/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Jérémie Ducastel</title>
	
	<link>http://jeremie.ducastel.name</link>
	<description>développement web</description>
	<lastBuildDate>Thu, 26 Nov 2009 11:45:22 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://flux.ducastel.name/billets-sw" /><feedburner:info uri="billets-sw" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><feedburner:emailServiceId>billets-sw</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Garder le contrôle de ses flux déportés</title>
		<link>http://flux.ducastel.name/~r/billets-sw/~3/7K_yJ6LfEIQ/</link>
		<comments>http://jeremie.ducastel.name/2009/11/garder-le-controle-de-ses-flux-deportes/#comments</comments>
		<pubDate>Thu, 26 Nov 2009 11:27:30 +0000</pubDate>
		<dc:creator>Jérémie Ducastel</dc:creator>
				<category><![CDATA[Tutoriels]]></category>
		<category><![CDATA[flux]]></category>
		<category><![CDATA[stats]]></category>

		<guid isPermaLink="false">http://jeremie.ducastel.name/?p=78</guid>
		<description><![CDATA[Amis auteurs de blog, bonjour. Il y a de grande chance pour que vous ne lisiez pas ce billet sur le site où il est publié, parce que comme moi vous ne passez pas votre journée à faire le tour des centaines de blogs et sites d&#8217;information que vous suivez mais laissez la tâche à [...]]]></description>
			<content:encoded><![CDATA[<p>Amis auteurs de blog, bonjour. Il y a de grande chance pour que vous ne lisiez pas ce billet sur <a href="http://jeremie.ducastel.name">le site</a> où il est publié, parce que comme moi vous ne passez pas votre journée à faire le tour des centaines de blogs et sites d&#8217;information que vous suivez mais laissez la tâche à votre agrégateur favori. Vous n&#8217;apparaissez donc pas dans les statistiques d&#8217;accès du site, mais dans celles du flux de syndication qui est pour cela déporté vers un service externe (feedburner).</p>
<p><img src="http://jeremie.ducastel.name/wp-content/uploads/2009/11/feedburner.png" alt="feedburner" title="feedburner" width="506" height="160" class="aligncenter size-full wp-image-148" /></p>
<p>Comme vous peut être, je n&#8217;aime pas trop me rendre dépendant d&#8217;un service et risquer de perdre tous mes abonnés si l&#8217;envie me prenait de le quitter. J&#8217;ai donc configuré ces flux de telle manière que leur url reste sous le domaine du site concerné. Voici un très bref tutorial.</p>
<p><span id="more-78"></span></p>
<p>Il vous faut :</p>
<ul>
<li>Un nom de domaine dont vous pouvez éditer les DNS (Ici enregistré chez <a href="http://gandi.net">Gandi</a>).</li>
<li>Un compte google/<a href="http://feedburner.com">feedburner</a>.</li>
<li>Un outil de publication permettant de modifier l&#8217;url du flux public (ici <a href="http://wordpress.org">Wordpress</a>).</li>
</ul>
<ol>
<li>
<p>Choisir le sous-domaine qui sera affecté aux flux. <q>feeds</q> par défaut pour feedburner, mais j&#8217;ai choisi <q>flux</q> pour mes sites, essentiellement francophones.</p>
</li>
<li>
<p>Générer le flux déporté par feedburner en lui fournissant l&#8217;url source du flux, c&#8217;est à dire celle produite par votre site (ici Wordpress donc votreblog.com/feed ).</p>
<p><img src="http://jeremie.ducastel.name/wp-content/uploads/2009/11/burn-a-feed.jpg" alt="burn a feed" title="burn a feed" width="458" height="52" class="aligncenter size-full wp-image-138" /></p>
</li>
<li>
<p>Aller sur son <a href="http://feedburner.google.com/fb/a/mybrand">compte feedburner</a>. Copier la valeur du champ DNS CNAME (qui se termine par <q>feedproxy.ghs.google.com.</q>)</p>
</li>
<li>
<p>Ouvrir un onglet avec la configuration du domaine. Ajouter un enregistrement CNAME avec la valeur copiée précédemment. Attention, cette modification pourra prendre plusieurs heures pour être prise en compte.</p>
<p><img src="http://jeremie.ducastel.name/wp-content/uploads/2009/11/gandi-feedburner.png" alt="gandi-feedburner" title="gandi-feedburner" width="378" height="126" class="alignnone size-full wp-image-144" /></p>
</li>
<li>
<p>Revenir sur feedburner. Lui spécifier les domaines complets des flux. Activer le service.</p>
<p><img src="http://jeremie.ducastel.name/wp-content/uploads/2009/11/feedburner-domains.png" alt="feedburner-domains" title="feedburner-domains" width="363" height="61" class="alignnone size-full wp-image-143" /></p>
</li>
<li>
<p>Modifier l&#8217;adresse publique des flux sur votre site. Pour Wordpress, il y a sans doute un plugin qui fait ça très bien mais pas celui que j&#8217;ai testé. Je suis donc allé dans l&#8217;editeur du thème utilisé pour modifier les <code class=\'prettyprint\' >&lt;?php bloginfo('rss2_url'); ?&gt;</code> par http://flux.votredomaine.com/slug-feedburner-du-flux. Les fichiers concernés sont généralement <q>header.php</q> (à plusieurs emplacements, dans la partie &lt;head&gt; et dans &lt;body&gt;) et <q>footer.php</q>.</p>
</li>
</ol>
<div class="feedflare">
<a href="http://flux.ducastel.name/~ff/billets-sw?a=7K_yJ6LfEIQ:x4C4NoOLT4M:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=7K_yJ6LfEIQ:x4C4NoOLT4M:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/billets-sw?i=7K_yJ6LfEIQ:x4C4NoOLT4M:D7DqB2pKExk" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=7K_yJ6LfEIQ:x4C4NoOLT4M:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=7K_yJ6LfEIQ:x4C4NoOLT4M:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/billets-sw/~4/7K_yJ6LfEIQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://jeremie.ducastel.name/2009/11/garder-le-controle-de-ses-flux-deportes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://jeremie.ducastel.name/2009/11/garder-le-controle-de-ses-flux-deportes/</feedburner:origLink></item>
		<item>
		<title>Twig, les templates Django sous PHP (le retour)</title>
		<link>http://flux.ducastel.name/~r/billets-sw/~3/CTdAqW-TyhA/</link>
		<comments>http://jeremie.ducastel.name/2009/10/twig-les-templates-django-sous-php-le-retour/#comments</comments>
		<pubDate>Thu, 08 Oct 2009 15:41:31 +0000</pubDate>
		<dc:creator>Jérémie Ducastel</dc:creator>
				<category><![CDATA[Développement]]></category>
		<category><![CDATA[Opinion]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://jeremie.ducastel.name/?p=100</guid>
		<description><![CDATA[Je dis le retour parce que j&#8217;avais moi-même implémenté la syntaxe de templates de Django en PHP il y a plus de deux ans (ça fait partie des librairies disponibles de webappkit). D&#8217;ailleurs, il m&#8217;avait déjà semblé voir d&#8217;autres implémentations ça et là depuis.

Je ne me prononcerai pas sur twig que je ne testerai sans [...]]]></description>
			<content:encoded><![CDATA[<p>Je dis le retour parce que j&#8217;avais moi-même implémenté la syntaxe de templates de <a href="http://djangoproject.com/">Django</a> en PHP il y a plus de deux ans (ça fait partie des librairies disponibles de <a href="http://webappkit.net">webappkit</a>). D&#8217;ailleurs, il m&#8217;avait déjà semblé voir d&#8217;autres implémentations ça et là depuis.</p>
<p><span id="more-100"></span></p>
<p>Je ne me prononcerai pas sur <a href="http://www.twig-project.org/">twig</a> que je ne testerai sans doute pas de sitôt (vous aurez compris que le besoin est déjà couvert). Je trouve juste dommage que Django ne soit presque pas cité sur son site. D&#8217;abord c&#8217;est inélégant, mais surtout cela passe à coté de l&#8217;un des intérêts selon moi de la librairie en question : l&#8217;interopérabilité avec un framework python majeur. J&#8217;en fais actuellement l&#8217;expérience, puisque je réécris une application web PHP avec Django, et que je réutilise quasiment tel quels les templates puisque la syntaxe est la même.</p>
<p>Concernant la syntaxe en question, et l&#8217;avantage par rapport à du PHP &#8220;pur&#8221;, qui semble être le débat en cours sur twig, il y a bien sûr la possibilité d&#8217;en permettre l&#8217;édition par l&#8217;équipe éditoriale sans qu&#8217;une erreur dans le template ne mène à une erreur 500 ou une faille de sécurité. Mais aussi le système d&#8217;héritage qui permet de définir facilement un <em>layout</em> global ou par section; le marquage des contenus à traduire pour l&#8217;internationalisation, etc.</p>
<div class="feedflare">
<a href="http://flux.ducastel.name/~ff/billets-sw?a=CTdAqW-TyhA:cw_u7YbJgHM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=CTdAqW-TyhA:cw_u7YbJgHM:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/billets-sw?i=CTdAqW-TyhA:cw_u7YbJgHM:D7DqB2pKExk" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=CTdAqW-TyhA:cw_u7YbJgHM:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=CTdAqW-TyhA:cw_u7YbJgHM:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/billets-sw/~4/CTdAqW-TyhA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://jeremie.ducastel.name/2009/10/twig-les-templates-django-sous-php-le-retour/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://jeremie.ducastel.name/2009/10/twig-les-templates-django-sous-php-le-retour/</feedburner:origLink></item>
		<item>
		<title>Définir l’ip client dans les tests unitaires Django</title>
		<link>http://flux.ducastel.name/~r/billets-sw/~3/bxdSVX15KRI/</link>
		<comments>http://jeremie.ducastel.name/2009/09/definir-lip-client-dans-les-tests-unitaires-django/#comments</comments>
		<pubDate>Wed, 30 Sep 2009 15:40:06 +0000</pubDate>
		<dc:creator>Jérémie Ducastel</dc:creator>
				<category><![CDATA[Développement]]></category>
		<category><![CDATA[django]]></category>

		<guid isPermaLink="false">http://jeremie.ducastel.name/?p=98</guid>
		<description><![CDATA[Note brève, mais ça peut servir :
Pour pouvoir accéder à l&#8217;ip client via request.META['REMOTE_ADDR'] lors de l&#8217;éxécution des tests unitaires, il faut la définir lors de l&#8217;instanciation du client de test. Par exemple :
from django.test import TestCase
from django.test.client import Client
class MyTestCase(TestCase):
    def setUp(self):
        self.client = [...]]]></description>
			<content:encoded><![CDATA[<p>Note brève, mais ça peut servir :</p>
<p>Pour pouvoir accéder à l&#8217;ip client via request.META['REMOTE_ADDR'] lors de l&#8217;éxécution des tests unitaires, il faut la définir lors de l&#8217;instanciation du client de test. Par exemple :</p>
<p><code class=\'prettyprint\' >from django.test import TestCase<br />
from django.test.client import Client</p>
<p>class MyTestCase(TestCase):</p>
<p>    def setUp(self):<br />
        self.client = Client(REMOTE_ADDR='127.0.0.1')</code></p>
<p>Sans cela vous obtiendrez une exception de type KeyError parce que REMOTE_ADDR ne sera pas définie dans request.META. Ceci concerne Django 1.0.2 et j&#8217;ai trouvé la solution <a href="http://code.djangoproject.com/ticket/8551">ici</a></p>
<div class="feedflare">
<a href="http://flux.ducastel.name/~ff/billets-sw?a=bxdSVX15KRI:ahzo2iLqywI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=bxdSVX15KRI:ahzo2iLqywI:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/billets-sw?i=bxdSVX15KRI:ahzo2iLqywI:D7DqB2pKExk" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=bxdSVX15KRI:ahzo2iLqywI:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=bxdSVX15KRI:ahzo2iLqywI:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/billets-sw/~4/bxdSVX15KRI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://jeremie.ducastel.name/2009/09/definir-lip-client-dans-les-tests-unitaires-django/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://jeremie.ducastel.name/2009/09/definir-lip-client-dans-les-tests-unitaires-django/</feedburner:origLink></item>
		<item>
		<title>python : les erreurs du débutant</title>
		<link>http://flux.ducastel.name/~r/billets-sw/~3/RjmlzjRP8co/</link>
		<comments>http://jeremie.ducastel.name/2009/05/python-les-erreurs-du-debutant/#comments</comments>
		<pubDate>Fri, 29 May 2009 15:38:50 +0000</pubDate>
		<dc:creator>Jérémie Ducastel</dc:creator>
				<category><![CDATA[Développement]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://jeremie.ducastel.name/?p=96</guid>
		<description><![CDATA[Ou plus exactement, les erreurs du développeur habitué à un autre langage et qui doit se défaire de ses habitudes et présupposés. Trois cas concrets.

Ci dessous, je veux créer une variable str, et ensuite convertir un entier en chaine. Ce qui me lève une exception.
&#62;&#62;&#62; str = "un chaine"
&#62;&#62;&#62; douze = str(12)
TypeError: 'str' object is [...]]]></description>
			<content:encoded><![CDATA[<p>Ou plus exactement, les erreurs du développeur habitué à un autre langage et qui doit se défaire de ses habitudes et présupposés. Trois cas concrets.</p>
<p><span id="more-96"></span></p>
<p>Ci dessous, je veux créer une <em>variable</em> <var>str</var>, et ensuite convertir un entier en chaine. Ce qui me lève une exception.</p>
<pre><code class=\'prettyprint\' >&gt;&gt;&gt; str = "un chaine"
&gt;&gt;&gt; douze = str(12)
TypeError: 'str' object is not callable</code></pre>
<p>Pourquoi ? Parce qu&#8217;en python tout est objet &#8211; y compris les fonctions, et que le concept de variable est remplacé par celui de  <q>nom</q>, qui référence les objets. En l&#8217;absence du $ qui en PHP distingue les variables des fonctions, j&#8217;avais tout simplement <q>remplacé</q> la fonction str() par une chaine.</p>
<p>Ensuite, je me suis arraché les cheveux sur une erreur de calcul incompréhensible jusqu&#8217;à ce que j&#8217;ouvre une console python pour obtenir le résultat suivant :</p>
<pre><code class=\'prettyprint\' >&gt;&gt;&gt; 9/12
0
&gt;&gt;&gt; 9.0/12.0
0.75</code></pre>
<p>Eh oui, pas de conversion automatique d&#8217;entier en float lors d&#8217;une opération. Il faut donc explicitement déclarer les opérateurs en float avec le <q>.0</q>.</p>
<p>La meilleure pour la fin. En PHP, j&#8217;avais pris pour habitude de déclarer toutes les propriétés d&#8217;instance dans le corps de la classe plutôt que dans le constructeur, afin d&#8217;y associer des <em>doc blocks </em> et d&#8217;y définir les éventuelles valeurs par défaut. Comme ceci :</p>
<pre><code class=\'prettyprint\' >&lt;?php
class MyClass {
    /**
     * @var int un entier entre un et douze
     */
    protected $qt = 3;

    public function __construct($qt=null) {
        if (is_int($qt))
          $this-&gt;qt = $qt;
    }
}</code></pre>
<p>Ce qui en python donne quelque chose comme ça :</p>
<pre><code class=\'prettyprint\' >class MyClass():
    # @var int un entier entre un et douze
    qt = 3

    def __init__(qt = None):
        if qt is not None:
            self.qt = qt</code></pre>
<p>Mais ne fonctionne pas du tout pareil. J&#8217;étais d&#8217;autant plus perdu que la classe en question était instanciée via une méthode statique et que mes instances se comportaient en <em>singleton</em> sans que ce soit le résultat souhaité. J&#8217;ai bien du perdre deux heures là dessus, à multiplier les tests unitaires et refactoriser le code pour trouver la source du problème.</p>
<pre><code class=\'prettyprint\' >&gt;&gt;&gt; first = MyClass(12)
&gt;&gt;&gt; first.qt
12
&gt;&gt;&gt; second = MyClass()
&gt;&gt;&gt; second.qt
12</code></pre>
<p>Jusqu&#8217;à ce que je réalise que tout attribut déclaré dans la classe est un attribut de celle-ci et non de l&#8217;instance, bien qu&#8217;elle soit accessible et modifiable par l&#8217;instance avec la même syntaxe (<kbd>self.qt</kbd>). Les attributs de classe sont à peu près équivalents aux propriétés statiques en php, et sont partagés entre toutes les instances de la classe.</p>
<p>Pour qu&#8217;un attribut soit propre à l&#8217;instance (local), il faut impérativement qu&#8217;il soit déclaré dans le constructeur :</p>
<pre><code class=\'prettyprint\' >class MyClass:
    def __init__(qt=None):
        if qt is not None:
            self.qt = qt
        else:
            self.qt = 3</code></pre>
<div class="feedflare">
<a href="http://flux.ducastel.name/~ff/billets-sw?a=RjmlzjRP8co:CBFEohn54Oc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=RjmlzjRP8co:CBFEohn54Oc:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/billets-sw?i=RjmlzjRP8co:CBFEohn54Oc:D7DqB2pKExk" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=RjmlzjRP8co:CBFEohn54Oc:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=RjmlzjRP8co:CBFEohn54Oc:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/billets-sw/~4/RjmlzjRP8co" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://jeremie.ducastel.name/2009/05/python-les-erreurs-du-debutant/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://jeremie.ducastel.name/2009/05/python-les-erreurs-du-debutant/</feedburner:origLink></item>
		<item>
		<title>Tests de portage PHP &gt; Python</title>
		<link>http://flux.ducastel.name/~r/billets-sw/~3/aIZi37P_bGA/</link>
		<comments>http://jeremie.ducastel.name/2009/05/tests-de-portage-php-python/#comments</comments>
		<pubDate>Thu, 14 May 2009 15:35:31 +0000</pubDate>
		<dc:creator>Jérémie Ducastel</dc:creator>
				<category><![CDATA[Développement]]></category>
		<category><![CDATA[django]]></category>

		<guid isPermaLink="false">http://jeremie.ducastel.name/?p=94</guid>
		<description><![CDATA[Sur un coup de tête (un peu déçu par le PHPCamp, où l&#8217;on a beaucoup parlé de technologies connexes et très peu de PHP), j&#8217;ai décidé lundi matin de tester l&#8217;implémentation en Django/Python d&#8217;une application web PHP4 que je dois réécrire pour l&#8217;internationaliser (anglais / français / chinois). Je précise que si je développe en [...]]]></description>
			<content:encoded><![CDATA[<p>Sur un coup de tête (un peu déçu par le <a href="http://barcamp.org/PhpCampParis2">PHPCamp</a>, où l&#8217;on a beaucoup parlé de technologies connexes et très peu de PHP), j&#8217;ai décidé lundi matin de tester l&#8217;implémentation en <a href="http://www.django-fr.org/">Django</a>/Python d&#8217;une application web PHP4 que je dois réécrire pour l&#8217;internationaliser (anglais / français / chinois). Je précise que si je développe en PHP depuis 2001, je parcours les manuels python depuis plusieurs années et je me suis déjà bien plongé dans la documentation de Django puisque j&#8217;ai implémenté en PHP son moteur de templates. Bien qu&#8217;ayant très peu pratiqué, je ne suis pas tout à fait novice sur ces deux technologies.</p>
<p>Voici le bilan de trois jours d&#8217;évaluation.</p>
<p><span id="more-94"></span></p>
<p><strong>Premier jour :</strong> (ré)installation de Django, la version 1.0.2, et création du projet. L&#8217;application se compose de trois interfaces : une interface web classique (qui doit donc etre multilingue), une interface <a href="http://www.xmlrpc.com/">XML-RPC</a> et  une interface client-serveur proprietaire. J&#8217;ai choisi de créer une <em>app</em> par interface. Je commence par l&#8217;interface client-serveur, qui est le point le plus critique et qui va subir prochainement une forte montée en charge. C&#8217;est elle qui va contenir la couche modèle.</p>
<p>La structure de la base de données étant déjà définie, je crée les classes modèles afin qu&#8217;elles s&#8217;adaptent aux tables existantes. Il s&#8217;agit pour l&#8217;instant de code essentiellement déclaratif. Parmi les spécificités, je créé un modèle superflu pour prendre en charge une table de liaison qui ne suit pas les conventions de nommage de Django; et un champ CSVField pour des listes de valeurs stockées en CSV dans la base. Le code ci-dessous, incluant <a href="http://www.python.org/dev/peps/pep-0257/">docstrings</a> et <a href="http://www.python.org/doc/2.5.2/lib/module-doctest.html">doctests</a> (Qui sont pour moi une forme de documentation) :</p>
<pre><code class=\'prettyprint\' >from django.db import models

class CSVField(models.Field):
    """Python list stored as a single CSV-encoded varchar field"""
    separator = ';'
    max_length = 255

    def db_type(self):
        """Define SQL column type"""
        return 'VARCHAR(%s)' % self.max_length

    def to_python(self, value):
        """Converts CSV to Python list

        &gt;&gt;&gt; CSVField.to_python('1;2;3;4;5')
        [1,2,3,4,5]"""
        return value.split(self.separator)

    def get_db_prep_value(self, value):
        """Converts Python list to CSV

        &gt;&gt;&gt; CSVField.get_db_prep_value([1,2,3,4,5])
        '1;2;3;4;5'"""
        return self.separator.join(value)</code></pre>
<p>Je crée également les premières vues, qui se contentent de réafficher les paramètres passées dans l&#8217;url.</p>
<p><strong>Deuxième jour :</strong> Je mets en place les premiers tests unitaires. Je découvre le <a href="http://docs.djangoproject.com/en/dev/topics/testing/#module-django.test.client">client de test</a> de Django, qui me permet de tester les premières vues, avec des données générées dans une base de tests en partie par un fichier yaml (<a href="http://docs.djangoproject.com/en/dev/topics/testing/#fixture-loading">fixtures</a>) et en partie via l&#8217;API de la couche  modèle dans le setUp() de la classe de tests.</p>
<p>Ensuite, je m&#8217;attaque à l&#8217;interface web classique qui doit être internationalisée. J&#8217;installe pour cela <a href="http://fr.wikipedia.org/wiki/Gettext">gettext</a> sur mon poste de travail (windows). Je crée la première vue (la page d&#8217;accueil) et les templates correspondant. Je marque les parties à traduire dans le code et les templates, et crée les fichiers de traduction anglais et chinois. Je les édite avec <a href="http://www.poedit.net/">poedit</a>, un logiciel spécialisé (de l&#8217;avantage d&#8217;utiliser un standard existant). Je copie-colle ce que me donne Google Translate pour le chinois parce que, euh, je ne parle pas cette langue. Mais je peux voir avec satisfaction les premiers idéogrammes apparaitre sur le site.</p>
<p>Ici les contenus textuels n&#8217;auront pas à être édités fréquemment. Dans le cas contraire je vois mal comment interfacer simplement gettext avec un CMS. Ici, le choix de gettext et poedit permet de faire saisir les traductions par quelqu&#8217;un qui n&#8217;est pas webmestre. De plus, gettext est également disponible en PHP via une extension spécifique.</p>
<p><strong>Troisième jour :</strong> Il est temps de passer à l&#8217;interface xml-rpc. Après une brève recherche, je tombe sur <a href="http://code.google.com/p/django-xmlrpc/">django_xmlrpc</a> qui permet d&#8217;associer les vues aux methodes fournies par le serveur (Django sert les vues selon des expressions régulières sur l&#8217;url de la requete, or avec xml-rpc toutes les méthodes sont servies sur la même url).</p>
<p>Après avoir listé les méthodes et les vues, je crée quelques tests unitaires pour la première. pour cela, je surcharge la classe TestCase de Django avec quelques méthodes utilisant les utilitaires xml-rpc de python (Voir le code ci-dessous). Après quelques tatonnements, mes premiers tests passent !</p>
<pre><code class=\'prettyprint\' >from django.test import TestCase

class XmlRpcTestCase(TestCase):
    """Specialisation de TestCase pour xml-rpc"""

    # @param string method
    # @param tuple params
    # @param string uri
    # @return Response
    def methodCall(self, method, params=(), uri='/rpc/'):
        """Issue a methodCall and sends a django's test client Response"""
        from xmlrpclib import dumps
        call = dumps(params, method)
        return self.client.post(uri, call, content_type='text/xml')

    # @param Response response
    # @param bool use_datetime if True return datetimes as object
    # @return tuple
    def parseResponse(self, response, use_datetime=True):
        """Parse django's client http Response to python tuple"""
        from xmlrpclib import loads, Fault
        try:
            result = loads(response.content, use_datetime)
            # result is a tuple params, method
            return result[0]
        except Fault, f:
            self.fail("Response was a Fault")
            return ()

    # @param string method
    # @param tuple params
    # @param string uri
    # @return tuple
    def parseCall(self, method, params=(), uri='/rpc/'):
        """method's result &lt;params&gt; as a python tuple

        assert False on method Fault"""
        response = self.methodCall(method, params, uri)
        return self.parseResponse(response)

    def assertNotFault(self, response):
        return self.assertNotContains(response, '&lt;fault&gt;')</code></pre>
<p>Comme il me reste un peu de temps, je reviens sur l&#8217;interface client-serveur qui sert un XML maison. Je découvre donc l&#8217;implémentation DOM de python pour le générer. Je rajoute quelques tests, et quitte la boite (tôt) sur un premier test positif <img src='http://jeremie.ducastel.name/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><strong>Bilan :</strong> Compte tenu de la vitesse à laquelle je me retrouve avec un prototype, et du fait que je n&#8217;ai rencontré aucun obstacle, je vais très probablement continuer l&#8217;implémentation en python et django. Il s&#8217;agit d&#8217;un choix tout à fait subjectif. J&#8217;apprécie beaucoup la syntaxe Python, son modèle tout-objet, et la philosophie <em>batteries included</em> (il y a en standard une bonne librairie pour la plupart des besoins). Et surtout, la qualité et l&#8217;exhaustivité de la documentation du langage et du framework, qui permettent de trouver très rapidement ce que l&#8217;on cherche, et même plus !</p>
<div class="feedflare">
<a href="http://flux.ducastel.name/~ff/billets-sw?a=aIZi37P_bGA:D3pkY_zO3cw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=aIZi37P_bGA:D3pkY_zO3cw:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/billets-sw?i=aIZi37P_bGA:D3pkY_zO3cw:D7DqB2pKExk" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=aIZi37P_bGA:D3pkY_zO3cw:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=aIZi37P_bGA:D3pkY_zO3cw:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/billets-sw/~4/aIZi37P_bGA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://jeremie.ducastel.name/2009/05/tests-de-portage-php-python/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://jeremie.ducastel.name/2009/05/tests-de-portage-php-python/</feedburner:origLink></item>
		<item>
		<title>Webappkit 0.13</title>
		<link>http://flux.ducastel.name/~r/billets-sw/~3/9ucenEhdKN4/</link>
		<comments>http://jeremie.ducastel.name/2009/05/webappkit-0-13/#comments</comments>
		<pubDate>Wed, 06 May 2009 15:32:14 +0000</pubDate>
		<dc:creator>Jérémie Ducastel</dc:creator>
				<category><![CDATA[Projets]]></category>
		<category><![CDATA[webappkit]]></category>

		<guid isPermaLink="false">http://jeremie.ducastel.name/?p=90</guid>
		<description><![CDATA[&#8230; est disponible au téléchargement. Pas mal de changements depuis la dernière version, puisqu&#8217;il s&#8217;est écoulé plus d&#8217;un an ! Parmi les changements, un nouveau look pour l&#8217;interface d&#8217;administration mais c&#8217;est la partie émergée de l&#8217;iceberg.


Formulaire d&#8217;installation de l&#8217;administration (création d&#8217;utilisateur pour l&#8217;authentification HTTP).
Génération de la structure de base des paquets depuis l&#8217;admin, ainsi que [...]]]></description>
			<content:encoded><![CDATA[<p>&#8230; est <a href="http://code.google.com/p/webappkit/downloads/detail?name=webappkit.0.13.zip">disponible au téléchargement</a>. Pas mal de changements depuis la dernière version, puisqu&#8217;il s&#8217;est écoulé plus d&#8217;un an ! Parmi les changements, un nouveau look pour l&#8217;interface d&#8217;administration mais c&#8217;est la partie émergée de l&#8217;iceberg.</p>
<p><span id="more-90"></span></p>
<ul>
<li>Formulaire d&#8217;installation de l&#8217;administration (création d&#8217;utilisateur pour l&#8217;authentification HTTP).</li>
<li>Génération de la structure de base des paquets depuis l&#8217;admin, ainsi que l&#8217;import de fichier de librairie.</li>
<li>Simplification de l&#8217;usage des tests unitaires : il suffit de déposer les classes de tests et scripts SQL de mise en place dans le dossier <q>tests/</q> du kit.</li>
<li>De nouvelles librairies intégrées (bases de données, système de fichiers, et un début d&#8217;implémentation de <a href="http://docs.djangoproject.com/en/dev/topics/forms/">Django Forms</a>.</li>
<li>Et bien sûr pas mal de polissage et de corrections de bugs.</li>
</ul>
<p><a href="http://webappkit.net"><img src="http://blog.sorcellerieweb.net/wp-content/uploads/2009/05/webappkitnet2009-05-06-180x120.png" alt="webappkit.net" title="webappkit.net" width="180" height="120" class="alignleft size-thumbnail wp-image-177" /></a></p>
<p>Le <a href="http://webappkit.net">site web</a> a également été mis à jour pour l&#8217;occasion, avec un nouveau tutorial qui se place dans le cadre de la refactorisation d&#8217;un site. La première partie est publiée, le reste suivra prochainement.</p>
<blockquote>
<p>Prenons le cas d&#8217;une application web vieillissante que nous souhaitons étendre et refactoriser. Comme par exemple, un intranet en code spaghetti, consistant en un ensemble de scripts mixant HTML, PHP et SQL. Bien sûr, il s&#8217;agit d&#8217;un exemple purement théorique. Toute coïncidence avec une application existante ne serait que pur incident statistique <img src='http://jeremie.ducastel.name/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
<p><a href="http://webappkit.net/tutorial">lire la suite</a></p>
</blockquote>
<p>Pour rester informés, vous pouvez suivre le <a href="http://twitter.com/webappkit">twitter du proje</a>t. Ses messages sont repris sur le site web et sur l&#8217;interface d&#8217;administration. Pour participer, vous pouvez également passer par le <a href="http://groups.google.com/group/webappkit">forum / newsgroup</a> ou <a href="mailto:contact[enlevez-ceci]@webappkit.net">envoyer un email</a>.</p>
<div class="feedflare">
<a href="http://flux.ducastel.name/~ff/billets-sw?a=9ucenEhdKN4:qbMu6_EeDiw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=9ucenEhdKN4:qbMu6_EeDiw:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/billets-sw?i=9ucenEhdKN4:qbMu6_EeDiw:D7DqB2pKExk" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=9ucenEhdKN4:qbMu6_EeDiw:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=9ucenEhdKN4:qbMu6_EeDiw:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/billets-sw/~4/9ucenEhdKN4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://jeremie.ducastel.name/2009/05/webappkit-0-13/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://jeremie.ducastel.name/2009/05/webappkit-0-13/</feedburner:origLink></item>
		<item>
		<title>Google est tout algorithme…</title>
		<link>http://flux.ducastel.name/~r/billets-sw/~3/oZ5cyMbgDV0/</link>
		<comments>http://jeremie.ducastel.name/2009/04/google-est-tout-algorithme/#comments</comments>
		<pubDate>Wed, 22 Apr 2009 15:30:17 +0000</pubDate>
		<dc:creator>Jérémie Ducastel</dc:creator>
				<category><![CDATA[Opinion]]></category>
		<category><![CDATA[google]]></category>

		<guid isPermaLink="false">http://jeremie.ducastel.name/?p=88</guid>
		<description><![CDATA[L&#8217;informatique au service des humains, le retour du balancier : Google est tout algorythme, mon projet est plutôt centré sur le comportement des humains, leurs goûts et les manières « invisibles » dont ils entrent en relation les uns avec les autres.
&#8211; le blog de alexis

Google est tout algorithme&#8230; peut être, mais pas inhumain pour [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>L&#8217;informatique au service des humains, le retour du balancier : Google est tout algorythme, mon projet est plutôt centré sur le comportement des humains, leurs goûts et les manières « invisibles » dont ils entrent en relation les uns avec les autres.</p>
<p>&#8211; <a href="http://www.encoreungeek.com/osera-pas-osera-pas-lancer-une-startup-web-part-ii">le blog de alexis</a></p>
</blockquote>
<p>Google est tout algorithme&#8230; peut être, mais pas <em>inhumain</em> pour autant.</p>
<p>Au contraire, l&#8217;algorithme de Google prend en compte les évaluations humaines puisqu&#8217;il se base sur les liens entre les sites web pour jauger de la pertinence d&#8217;un site. C&#8217;est cette approche révolutionnaire (A l&#8217;époque) qui lui a permis de surclasser, écraser totalement ses adversaires. Plus un site possède de liens <q>entrants</q> (d&#8217;autres sites qui y font référence), plus il est supposé faire <em>autorité</em>.</p>
<p>C&#8217;est d&#8217;ailleurs sans doute la raison qui fait que Wikipedia s&#8217;est très vite retrouvé en haut des résultats pour beaucoup de recherches, car il est courant de mettre un lien vers wikipedia dès qu&#8217;on cite un concept qui pourrait ne pas être familier pour ses lecteurs (En tout cas c&#8217;est ce que je fais souvent).</p>
<div class="feedflare">
<a href="http://flux.ducastel.name/~ff/billets-sw?a=oZ5cyMbgDV0:Zh7KN8FuXv4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=oZ5cyMbgDV0:Zh7KN8FuXv4:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/billets-sw?i=oZ5cyMbgDV0:Zh7KN8FuXv4:D7DqB2pKExk" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=oZ5cyMbgDV0:Zh7KN8FuXv4:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=oZ5cyMbgDV0:Zh7KN8FuXv4:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/billets-sw/~4/oZ5cyMbgDV0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://jeremie.ducastel.name/2009/04/google-est-tout-algorithme/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://jeremie.ducastel.name/2009/04/google-est-tout-algorithme/</feedburner:origLink></item>
		<item>
		<title>Scripts SQL de migration SPIP &gt;&gt; WordPress</title>
		<link>http://flux.ducastel.name/~r/billets-sw/~3/Ml59h25j6Tg/</link>
		<comments>http://jeremie.ducastel.name/2009/04/scripts-sql-de-migration-spip-wordpress/#comments</comments>
		<pubDate>Wed, 15 Apr 2009 15:27:49 +0000</pubDate>
		<dc:creator>Jérémie Ducastel</dc:creator>
				<category><![CDATA[Développement]]></category>
		<category><![CDATA[spip]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://jeremie.ducastel.name/?p=86</guid>
		<description><![CDATA[Il y a quelques années, quelques autres anciens de Gobelins et moi avions monté un site sous SPIP, où nous parlions web et culture : exgobz.com
Ayant découvert Wordpress et la qualité de son interface de rédaction qui me pousse à migrer tous mes blogs sur cette plate-forme, j&#8217;ai décidé de faire de même pour exgobz. [...]]]></description>
			<content:encoded><![CDATA[<p>Il y a quelques années, quelques autres anciens de <a href="http://www.gobelins.fr/">Gobelins</a> et moi avions monté un site sous <a href="http://www.spip.net/">SPIP</a>, où nous parlions web et culture : <a href="http://exgobz.com">exgobz.com</a></p>
<p>Ayant découvert <a href="http://wordpress.org/">Wordpress</a> et la qualité de son interface de rédaction qui me pousse à migrer tous mes blogs sur cette plate-forme, j&#8217;ai décidé de faire de même pour exgobz. Voilà les quelques requêtes que j&#8217;ai utilisé pour importer les contenus. On part du principe que les tables wordpress sont préfixées avec wp_, adaptez selon vos besoins.</p>
<p><span id="more-86"></span></p>
<p><code class=\'prettyprint\' ># migration SPIP vers Wordpress</p>
<p># utilisateurs<br />
# ici INSERT IGNORE pour ne pas écraser l'utilisateur #1 (c'est moi sur les 2 sites)<br />
INSERT IGNORE INTO wp_users(<br />
    ID<br />
    , user_login<br />
    , user_email<br />
    , user_url<br />
    , display_name)<br />
SELECT<br />
    id_auteur<br />
    , login<br />
    , email<br />
    , url_site<br />
    , nom<br />
FROM<br />
    spip_auteurs;</p>
<p># rubriques &gt;&gt; categories<br />
# 2 requetes, wordpress utilise deux tables qui contiennent categories et mots clefs<br />
REPLACE INTO wp_terms(<br />
    term_id<br />
    , name<br />
    , slug)<br />
SELECT<br />
    id_rubrique<br />
    , titre<br />
    , url_propre<br />
FROM spip_rubriques;</p>
<p>REPLACE INTO wp_term_taxonomy(<br />
    term_taxonomy_id<br />
    , term_id<br />
    , taxonomy<br />
    , description<br />
    , parent)<br />
SELECT<br />
    id_rubrique<br />
    , id_rubrique<br />
    , 'category'<br />
    , descriptif<br />
    , id_parent<br />
FROM<br />
    spip_rubriques;</p>
<p># articles<br />
# attention, tous les articles sont publies d'office !<br />
REPLACE INTO exgobz_posts(<br />
    ID<br />
    , post_author<br />
    , post_date, post_date_gmt<br />
    , post_content<br />
    , post_title<br />
    , post_category<br />
    # , post_status<br />
    , to_ping , pinged<br />
    , post_modified, post_modified_gmt<br />
)<br />
SELECT<br />
    p.id_article<br />
    , u.id_auteur<br />
    , p.date, p.date<br />
    , concat(p.chapo, ' <!--more--> ', p.texte)<br />
    , titre<br />
    , p.id_rubrique<br />
    , '', ''<br />
    , p.date_modif, p.date_modif<br />
FROM<br />
    spip_articles AS p<br />
    LEFT JOIN spip_auteurs_articles AS u ON u.id_article = p.id_article;</p>
<p># association billets / categories<br />
REPLACE INTO<br />
    wp_term_relationships(<br />
    object_id<br />
    , term_taxonomy_id)<br />
SELECT<br />
    p.id_article<br />
    , p.id_rubrique<br />
FROM<br />
    spip_articles AS p;</code></p>
<p>C&#8217;est loin d&#8217;être parfait ni même complet, mais ça peut servir de base de travail. La hiérarchie des catégories semble déficiente sur certains thèmes, je n&#8217;ai pas vraiment le temps de fouiller ça pour l&#8217;instant.</p>
<div class="feedflare">
<a href="http://flux.ducastel.name/~ff/billets-sw?a=Ml59h25j6Tg:O6adwd7NIY8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=Ml59h25j6Tg:O6adwd7NIY8:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/billets-sw?i=Ml59h25j6Tg:O6adwd7NIY8:D7DqB2pKExk" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=Ml59h25j6Tg:O6adwd7NIY8:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=Ml59h25j6Tg:O6adwd7NIY8:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/billets-sw/~4/Ml59h25j6Tg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://jeremie.ducastel.name/2009/04/scripts-sql-de-migration-spip-wordpress/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://jeremie.ducastel.name/2009/04/scripts-sql-de-migration-spip-wordpress/</feedburner:origLink></item>
		<item>
		<title>quizzgeek.net fermé</title>
		<link>http://flux.ducastel.name/~r/billets-sw/~3/6E0dJUD3PZY/</link>
		<comments>http://jeremie.ducastel.name/2009/04/quizzgeek-net-ferme/#comments</comments>
		<pubDate>Sat, 11 Apr 2009 15:25:54 +0000</pubDate>
		<dc:creator>Jérémie Ducastel</dc:creator>
				<category><![CDATA[Bazaar]]></category>

		<guid isPermaLink="false">http://jeremie.ducastel.name/?p=84</guid>
		<description><![CDATA[
Je viens de fermer Quizzgeek.net, le quizz en ligne pour geeks que j&#8217;avais développé. Mais je travaille déjà sur son remplaçant, un site de quizzes plus généraliste. Les questions sont conservées et je tâcherai  d&#8217;en réintégrer un maximum dans le nouveau site.
A suivre donc&#8230;
]]></description>
			<content:encoded><![CDATA[<p><a href="http://quizzgeek.net"><img src="http://blog.sorcellerieweb.net/wp-content/uploads/2009/04/quizzgeek-closed-180x120.png" alt="quizzgeek.net fermé" title="quizzgeek.net fermé" width="180" height="120" class="alignleft size-thumbnail wp-image-155" /></a></p>
<p>Je viens de fermer <a href="http://quizzgeek.net">Quizzgeek.net</a>, le quizz en ligne pour geeks que j&#8217;avais développé. Mais je travaille déjà sur son remplaçant, un site de quizzes plus généraliste. Les questions sont conservées et je tâcherai  d&#8217;en réintégrer un maximum dans le nouveau site.</p>
<p>A suivre donc&#8230;</p>
<div class="feedflare">
<a href="http://flux.ducastel.name/~ff/billets-sw?a=6E0dJUD3PZY:v7GpKGjgK9Q:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=6E0dJUD3PZY:v7GpKGjgK9Q:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/billets-sw?i=6E0dJUD3PZY:v7GpKGjgK9Q:D7DqB2pKExk" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=6E0dJUD3PZY:v7GpKGjgK9Q:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=6E0dJUD3PZY:v7GpKGjgK9Q:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/billets-sw/~4/6E0dJUD3PZY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://jeremie.ducastel.name/2009/04/quizzgeek-net-ferme/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://jeremie.ducastel.name/2009/04/quizzgeek-net-ferme/</feedburner:origLink></item>
		<item>
		<title>Safari 4, Google et signets</title>
		<link>http://flux.ducastel.name/~r/billets-sw/~3/hq0CH2_JTuc/</link>
		<comments>http://jeremie.ducastel.name/2009/04/safari-4-google-et-signets/#comments</comments>
		<pubDate>Thu, 09 Apr 2009 15:23:38 +0000</pubDate>
		<dc:creator>Jérémie Ducastel</dc:creator>
				<category><![CDATA[Opinion]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[safari]]></category>
		<category><![CDATA[signets]]></category>

		<guid isPermaLink="false">http://jeremie.ducastel.name/?p=82</guid>
		<description><![CDATA[Après quelques semaines de test de Safari 4 (beta), je suis retourné à Chrome pour ce qui est de surfer sur PC. La faute à quelques détails gênants :

Des bogues dans la gestion des cookies et de l&#8217;authentification qui m&#8217;empêche d&#8217;avoir accès à certains sites, dont l&#8217;intranet du boulot (que je maintiens).
Impossibilité de définir les [...]]]></description>
			<content:encoded><![CDATA[<p>Après quelques semaines de test de Safari 4 (beta), je suis retourné à Chrome pour ce qui est de surfer sur PC. La faute à quelques détails gênants :</p>
<ul>
<li>Des bogues dans la gestion des cookies et de l&#8217;authentification qui m&#8217;empêche d&#8217;avoir accès à certains sites, dont l&#8217;intranet du boulot (que je maintiens).</li>
<li>Impossibilité de définir les préférences de langue (<a href="/2007/12/03/detecter-les-preferences-du-navigateur/">préférences qui pourront être ensuite détectées par le site visité pour adapter le contenu</a>).</li>
<li>Un peu plus lent et gourmand en ressources.</li>
</ul>
<p><a href="/wp-content/uploads/2009/04/safari-cover-flow.png"><img src="/wp-content/uploads/2009/04/safari-cover-flow-320x165.png" alt="Cover Flow dans Safari 4" title="Cover Flow dans Safari 4" width="320" height="165" class="alignleft size-medium wp-image-134" /></a></p>
<p>C&#8217;est dommage (mais je retenterai dès qu&#8217;il sortira en version finale), parce qu&#8217;il est pas mal, sinon, Safari 4. Une interface totalement pompée sur Chrome, mais en plus sexy (Apple  quoi). Une sorte de Chrome + Cover Flow pour naviguer dans les signets et l&#8217;historique.</p>
<p>Autre gros point positif, c&#8217;est la synchronisation des signets via <a href="http://me.com">Mobile Me</a> qui me permet(tait) d&#8217;avoir les même favoris sur Mac, PC et iPhone.</p>
<p><span id="more-82"></span></p>
<p>Etant un gros surfeur (j&#8217;ai pris du poids mais c&#8217;est une coïncidence), j&#8217;ai des favoris à la fois dans mon navigateur courant, sur netvibes et sur <a href="http://delicious.com/fredbird">Delicious</a> (environ 2000), pour les pages qui semblent intéressantes &#8211; que je veux garder sous le coude mais que je ne visite pas tous les jours (J&#8217;ai également utilisé <a href="http://blogmarks.net/user/fredbird">blogmarks</a>). Sauf qu&#8217;au final, je ne me sers (presque) jamais de ces derniers, et mon compte delicious ressemble à un <em>cimetière des éléphants</em> de mes centres d&#8217;intérêt.</p>
<p>Au final, comme la plupart des internautes lambda, je passe bien souvent par une recherche google pour <strong>retrouver des sites que j&#8217;ai déjà visités</strong>. Chrome, Firefox et Safari ont intégré ce comportement en suggérant les éléments de l&#8217;historique et des favoris lorsqu&#8217;on commence à saisir une adresse. La recherche est plus efficace que le classement, même par mot clef.</p>
<p><img src="/wp-content/uploads/2009/04/google-star.png" alt="google star" title="google star" width="120" height="120" class="alignleft size-full wp-image-132" /> Google pourrait pousser facilement son avantage avec une simple intégration plus poussée de ses services existants. Il est déjà possible de stocker des favoris en ligne avec <a href="http://www.google.com/bookmarks">Google Bookmarks</a>, avec la possibilité de chercher dans ses favoris, c&#8217;est à dire non pas dans les mots clefs ou notes saisies mais bien dans le contenu de la page indexée. Plus besoin de classer soi même les favoris avec une ribambelle de mots-clefs. Aux mots clefs censés indexer le contenu devrait se substituer le contexte d&#8217;utilisation (travail, loisirs, etc).</p>
<p>Chrome devrait permettre de synchroniser les signets locaux avec les signets en ligne. De manière générale, tout ce qui est <em>marquable comme suivi</em> (le fameux <q>star this</q>) devrait être accessible via une recherche personnalisée : les items de Google Reader (facile, puisque chaque item fait déjà référence à une url !), mais aussi les courriels (Gmail), les documents (Google Docs), les livres (Google Books), etc.</p>
<p>Et cerise sur le gâteau, tout contenu marqué comme suivi devrait être archivé/mis en cache pour être certain de pouvoir le retrouver si il venait à disparaitre.</p>
<p><img src="/wp-content/uploads/2009/04/google-recherche-favoris.png" alt="rechercher dans les favoris" title="rechercher dans les favoris" width="532" height="32" class="alignnone size-full wp-image-130" /></p>
<p>L&#8217;utilisateur aurait alors à sa disposition un panier de ressources unifié, une présélection pour affiner ses recherches. Un Spotlight (le moteur de recherche unifié de Mac OS X) pour tous ses contenus en ligne. Je me souviens de mon enthousiasme pour <a href="http://beagle-project.org/Main_Page">Beagle</a> (le moteur de recherche de Gnome), mais je n&#8217;utilise que rarement ce genre d&#8217;outil car l&#8217;essentiel de mes contenus sont désormais en ligne.</p>
<div class="feedflare">
<a href="http://flux.ducastel.name/~ff/billets-sw?a=hq0CH2_JTuc:tCDZC1jpf9o:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=hq0CH2_JTuc:tCDZC1jpf9o:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/billets-sw?i=hq0CH2_JTuc:tCDZC1jpf9o:D7DqB2pKExk" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=hq0CH2_JTuc:tCDZC1jpf9o:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://flux.ducastel.name/~ff/billets-sw?a=hq0CH2_JTuc:tCDZC1jpf9o:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/billets-sw?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/billets-sw/~4/hq0CH2_JTuc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://jeremie.ducastel.name/2009/04/safari-4-google-et-signets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://jeremie.ducastel.name/2009/04/safari-4-google-et-signets/</feedburner:origLink></item>
	</channel>
</rss>
