# articles

feed_id: http://sametmax.com/?p=2725
title: Virer toute la merde d’Ubuntu 12.10
uri: Virer-toute-la-merde-d-Ubuntu-12-10
url: http://sametmax.com/virer-toute-la-merde-dubuntu-12-10/
content:
<p><code">sudo apt-get -y remove unity-lens-shopping account-plugin-aim account-plugin-facebook account-plugin-flickr account-plugin-google account-plugin-icons account-plugin-identica account-plugin-jabber account-plugin-salut account-plugin-twitter account-plugin-windows-live account-plugin-yahoo gnome-online-accounts </code></p>
<p><a href="http://lehollandaisvolant.net/index.php?mode=links&#038;id=20121023124938">Parce que bon, hein, ho&#8230;</a></p>


feed_id: http://sametmax.com/?p=362
title: Décompresser sous linux en ligne de commande
uri: Décompresser-sous-linux-en-ligne-de-commande
url: http://sametmax.com/decompresser-sous-linux-en-ligne-de-commande/
content:
<p>Si comme moi vous ne vous souvenez jamais de l&#8217;incantation magique qui permet de décompresser les fichiers <em>tar.gz</em> et autres linuxeries, voici un pense-bête:</p>
<p><code>tar xvf truc.tar # untar uniquement </code><br />
<code>tar xvzf truc.tar.gz # decompresse sur place</code><br />
<code>tar xvzf truc.tar.gz /chemin/vers/dossier # decompresse dans un dossier</code><br />
<code>tar jxf truc.tar.bz2 # decompresser bz2</code><br />
<code>gunzip truc.bz > truc # ungzip uniquement</code></p>
<p>Et pour les zip/tar, c&#8217;est <code>unzip</code>/<code>untar</code>, sans option. Mais il faut les installer à part.</p>


feed_id: http://sametmax.com/?p=2741
title: Variable d’environnement PATH et crontab
uri: Variable-d-environnement-PATH-et-crontab
url: http://sametmax.com/variable-denvironnement-path-et-crontab/
content:
<p>Si vous utilisez crontab pour vos tâche, faites attention à un détail : le PATH.</p>
<p>il y a un fichier de conf que j&#8217;ai pas réussi à faire fonctionner dans /etc/crontab, si vous y arrivez tant mieux sinon éditez votre cron de la sorte:</p>
<p><strong>1. Version avec PATH défini par tâche:</strong></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff4500;">30</span> <span style="color: #ff4500;">23</span> <span style="color: #66cc66;">*</span> <span style="color: #66cc66;">*</span> <span style="color: #66cc66;">*</span> PATH=$PATH:/usr/local/bin <span style="color: #66cc66;">&amp;&amp;</span> export PATH <span style="color: #66cc66;">&amp;&amp;</span> python /home/penetrator/script.<span style="color: black;">py</span></pre></div></div>

<p><strong>2. Version avec variables définies en haut du fichier cron:</strong></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Env</span>
SHELL=/bin/bash
HOME=/home/prod
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
&nbsp;
<span style="color: #808080; font-style: italic;"># Cmd cron</span>
<span style="color: #ff4500;">30</span> <span style="color: #ff4500;">23</span> <span style="color: #66cc66;">*</span> <span style="color: #66cc66;">*</span> <span style="color: #66cc66;">*</span> python /home/penetrator/script.<span style="color: black;">py</span></pre></div></div>

<p><em>$PATH=PATH:/usr/local/bin &#038;&#038; export PATH</em>  va rajouter /usr/local/bin dans le PATH.<br />
Ayant installé et compilé un programme dans <em>/usr/local/bin</em> et l&#8217;utilisant dans script.py, il faut que son chemin soit dans le PATH.</p>
<p><strong>Pour avoir des infos sur l&#8217;env de votre cron:</strong></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">*</span> <span style="color: #66cc66;">*</span> <span style="color: #66cc66;">*</span> <span style="color: #66cc66;">*</span> <span style="color: #66cc66;">*</span> PATH=$PATH:/usr/local/bin <span style="color: #66cc66;">&amp;&amp;</span> export PATH <span style="color: #66cc66;">&amp;&amp;</span> env <span style="color: #66cc66;">&gt;</span> /tmp/cronenv</pre></div></div>

<p>faites un <em>tail -f /tmp/cronenv </em>pour voir si votre PATH est bien déclaré.</p>
<p>ça peut éviter quelques heures à s&#8217;arracher les cheveux pour le debug d&#8217;un script&#8230;</p>


feed_id: http://sametmax.com/?p=2759
title: Comment recruter un développeur Python
uri: Comment-recruter-un-développeur-Python
url: http://sametmax.com/comment-recruter-un-developpeur-python/
content:
<p>Bonjour M. Gentil. Vous venez pour la position de stagiaire ingénieur senior en periode d&#8217;essai sur 3 ans ?</p>
<p>C&#8217;est bien, c&#8217;est bien.</p>
<p>Nous avons des perspectives de progression fascinantes dans notre SS3I au carré.</p>
<p>J&#8217;ai juste quelques tests à vous faire passer. Trois fois rien. Simple formalité administrative. Vous comprenez, on ne peut pas embaucher pas n&#8217;importe quel Bac + 5 et le payer SMIC, comme ça sur un coup de tête.</p>
<p>Ce n&#8217;est pas contre vous, non.</p>
<p>Pourriez-vous me dire ce qu&#8217;affiche ce snippet ? (mouahahahahaha, rire diabolique intérieur)</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff4500;">1</span> + <span style="color: #483d8b;">&quot;1&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">TypeError</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;exception&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">finally</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;finally&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Et celui-là, il affiche la stack trace ou pas ?</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #ff4500;">1</span> + <span style="color: #483d8b;">&quot;1&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">TypeError</span>:
        <span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">ValueError</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Test'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">finally</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;finally&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Bon ok, mais si on a un générateur alors ?</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #ff4500;">1</span> + <span style="color: #483d8b;">&quot;1&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">TypeError</span>:
        <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #483d8b;">'typerror'</span>
        <span style="color: #ff7700;font-weight:bold;">return</span>
    <span style="color: #ff7700;font-weight:bold;">finally</span>:
        <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #483d8b;">&quot;finally&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #483d8b;">&quot;Out&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> value <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> value</pre></div></div>

<p>Quelle exception sera catchée, dans le bout de code suivant ? (tapoter son style de manière énervante sur la table)</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #ff7700;font-weight:bold;">assert</span> <span style="color: #ff4500;">1</span> + <span style="color: #483d8b;">&quot;1&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">AssertionError</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;assertionerror&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">Exception</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;exception&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">TypeError</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;typerror&quot;</span>
&nbsp;
<span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Je vois. Donc finally est exécuté dans tous les cas ?</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">RuntimeError</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'runtimeerror'</span>
    <span style="color: #ff7700;font-weight:bold;">finally</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'finally'</span>
&nbsp;
<span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Vous êtes sûr ? VRAIMENT dans tous les cas ? (regard appuyé bien stressant, travaillé durant un poste de manager chez Quick)</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        PRINTEUH <span style="color: #66cc66;">!</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">SyntaxError</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'syntaxerror'</span>
    <span style="color: #ff7700;font-weight:bold;">finally</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'finally'</span>
&nbsp;
<span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>VRAIMENT, VRAIMENT, dans tous les cas ? Mais alors, VRAIMENT ? (prendre la voix d&#8217;Alain Chabat, parce qu&#8217;arrivé à ce stade là c&#8217;est juste plus rigolo)</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span>bar<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> bar
        <span style="color: #ff7700;font-weight:bold;">return</span> foo, bar
&nbsp;
    bar = <span style="color: #483d8b;">'bar'</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
            foo, bar = foo<span style="color: black;">&#40;</span>bar<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">RuntimeError</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'runtimeerror'</span>
    <span style="color: #ff7700;font-weight:bold;">finally</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'finally'</span>
&nbsp;
<span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Ne vous inquiétez pas, nous ne vous JUgeons paaaaaaas. Détendez-vous. Allez. Une petite dernière. Je vous aide. <code>sys.exit(1)</code> retourne le code 1.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span>l=<span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span> l
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff4500;">1</span> + <span style="color: #483d8b;">&quot;1&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">TypeError</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> l <span style="color: #ff7700;font-weight:bold;">or</span> l.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">finally</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Je sais plus là, sérieux&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>l<span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;</span> <span style="color: #ff4500;">1</span>:
            <span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Bon, je sens que vous êtes fatigué. On va arrêter là peut être. Vous êtes le genre à vous en tenir là, hein ? Non. Très bien, très bien. Voici un code sur lequel on planche en interne depuis une semaine pour comprendre combien de fois il affiche finally, mais on s&#8217;est dit que vous pourriez le résoudre gratuitement pour nous:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">time</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> multiprocessing
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">Queue</span> <span style="color: #ff7700;font-weight:bold;">import</span> Empty
&nbsp;
in_queue = multiprocessing.<span style="color: #dc143c;">Queue</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
out_queue = multiprocessing.<span style="color: #dc143c;">Queue</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> worker<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            res = in_queue.<span style="color: black;">get</span><span style="color: black;">&#40;</span>timeout=<span style="color: #ff4500;">0.1</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> res == <span style="color: #483d8b;">'stop'</span>:
                <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">print</span> res
        <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: black;">&#40;</span>Empty, multiprocessing.<span style="color: black;">TimeoutError</span><span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">pass</span>
        <span style="color: #ff7700;font-weight:bold;">finally</span>:
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'finally'</span>
&nbsp;
&nbsp;
process = multiprocessing.<span style="color: black;">Process</span><span style="color: black;">&#40;</span>target=worker<span style="color: black;">&#41;</span>
process.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
in_queue.<span style="color: black;">put</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'test'</span><span style="color: black;">&#41;</span>
in_queue.<span style="color: black;">put</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'stop'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'afterstop'</span>
&nbsp;
<span style="color: #dc143c;">time</span>.<span style="color: black;">sleep</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'done'</span></pre></div></div>

<p>Merci, ce sera tout.</p>
<p>Bon WE, monsieur Gentil.</p>
<p>Nous gardons votre CV. On vous recontactera.</p>


feed_id: http://sametmax.com/?p=2753
title: Le Flux RSS de nos tweets à changé
uri: Le-Flux-RSS-de-nos-tweets-à-changé
url: http://sametmax.com/le-flux-rss-de-nos-tweets-a-change/
content:
<p>Si vous y étiez abonné, il faut changer l&#8217;URL, qui est maintenant: <a href="https://api.twitter.com/1/statuses/user_timeline.rss?screen_name=sam_et_max">https://api.twitter.com/1/statuses/user_timeline.rss?screen_name=sam_et_max</a></p>
<p>Je rappelle également que nos tweets sont tous <a href="sametmax.com/nos-tweets/">listés</a> sur le blog. Vous n&#8217;avez pas besoin de trainer sur Twitter pour nous suivre.</p>
<p>Un lecteur a par ailleurs suggérer qu&#8217;on fasse des articles chaque semaine résumant les tweets de la semaine. D&#8217;autres sont intéressés ?</p>


feed_id: http://sametmax.com/?p=2772
title: Retour d’expérience sur l’installation d’Ubuntu 12.10
uri: Retour-d-expérience-sur-l-installation-d-Ubuntu-12-10
url: http://sametmax.com/retour-dexperience-sur-linstallation-dubuntu-12-10/
content:
<p>Les versions d&#8217;Ubuntu sont de plus en plus instables avec le temps.</p>
<p>Premier laptop (update): pas de touchpad (obligé de le faire passer pour une souris USB avec une option dans un fichier de config GRUB) et pas de wifi (obligé de trouver et compiler le drivers à la main). Je vous passe les détails sur mon après-midi pour avoir trouvé les solutions à ces problèmes.</p>
<p>Deuxième laptop (fresh install): plus de gestion du second moniteur. 4 crash de 4 applications différentes en une demie-heure: 2 sous Unity, et 2 sous Gnome-shell.</p>
<p>Le daemon Ubuntu one est toujours aussi gourmand dès qu&#8217;il a plus de 3Go à indexer, et inkillable.</p>
<p>Je joue actuellement avec l&#8217;idée de retourner sur une debian et un bureau GNOME 2. J&#8217;ai quand même installé KDE pour faire mon ouvert d&#8217;esprit. J&#8217;ai refermé mon esprit après l&#8217;impression de viol graphique que j&#8217;ai ressenti à la connection.</p>
<p>Si un dev Ubuntu passe par là: les gars, <strong>arrêtez de rajouter des features de Web social et des fenêtres qui font wizz et prenez les 2 prochaines versions pour faire un produit stable</strong>. Sans nouvelles fonctionnalités. Justes les dernières libs (pas comme debian), mais un ensemble stable.</p>
<p>Pas la peine de de suggérer les autres distribs/bureaux, ceci n&#8217;est pas une appel à une solution à mon problème. </p>
<p>P.S: arrête de rire Max. Je te pisse à la raie.</p>
<p>P.P.S: vous noterez que le passage à Python 3 ne s&#8217;est pas fait. Et oui, <a href="http://sametmax.com/dois-je-apprendre-python-2-ou-python-3/">c&#8217;est pas si simple</a>&#8230;</p>


feed_id: http://sametmax.com/?p=2778
title: Pedobear et SNCF
uri: Bedobear-et-SNCF
url: http://sametmax.com/bedobear-et-sncf/
content:
<p>Ce matin dans le train, j&#8217;essayais de trouver l&#8217;inspiration pour un article de cul. Rien ne vint.</p>
<p>C&#8217;est que c&#8217;est dur pondre une news par jour, vous vous rendez pas compte. Faire un excellent article une fois, c&#8217;est facile. On a tous une étincelle de génie un jour ou l&#8217;autre. Mais être bon tous les jours, je cherche encore comment faire.</p>
<p>C&#8217;est entre autre pour ça qu&#8217;il est vachement plus impressionnant d&#8217;être un bon acteur de théâtre que de ciné.</p>
<p>Mais bon, cette fois le Dieu du porno infantile est venu à mon secours, sous la forme ici incarnée de deux petites voisines de 8 ans, qui me permettront de combler le vide d&#8217;aujourd&#8217;hui en vous reportant leur conversation:</p>
<blockquote>
<ul>
<li>tu as vu sa culotte ?, dit la première, tendant le chef-d’œuvre d&#8217;art néo-naïf en pastel qu&#8217;elle venait juste de terminer. Il représentait une humanoïde femelle à la jupe triangulaire fort drue, rouge et courte. Et avec pas mal de fils qui dépassaient.</li>
<li>nan, j&#8217;vois pas !</li>
<li> j&#8217;l'ai pas dessiné !</li>
</ul>
</blockquote>
<p>Merci les enfants !</p>


feed_id: http://sametmax.com/?p=2787
title: Python, Ruby et PHP sont lents
uri: Python-Ruby-et-PHP-sont-lents
url: http://sametmax.com/python-ruby-et-php-sont-lents/
content:
<p>Ce matin je lançais ma petit recherche <a href="https://twitter.com/search/realtime?q=%28python+OR+django+OR+git+OR+%23python+OR+%23django+OR+%23git%29+lang%3Afr&amp;src=savs">Python/Django/Git</a> habituelle sur Twitter pour voir ce qui s&#8217;y tramait, quand je suis tombé sur plusieurs tweets qui m&#8217;ont fait tiqué.</p>
<p>Il y en a un qui résume très bien l&#8217;idée:</p>
<blockquote><p>Cay de la merde je préfère les langages plus bas niveaux, python c&#8217;est lent.</p></blockquote>
<p>C&#8217;est un argument que je lis souvent, et qui est aussi utilisé contre Ruby ou PHP.</p>
<p>Si j&#8217;ai la personne en face de moi, généralement la question qui suit est:</p>
<blockquote><p>Ouai je comprends. C&#8217;est quoi ta contrainte ? Tu dois exécuter quel calcul sous quelle limite de temps ?</p></blockquote>
<p>Il n&#8217;y a jamais aucune réponse autre qu&#8217;un bafouillement, car une personne qui a une réelle contrainte de temps d&#8217;exécution ne sort pas ce genre d&#8217;ânerie: il utilise le bon outil pour le bon travail selon des metrics précises, pas selon le nom du langage.</p>
<p>Ceux qui trollent, généralement des étudiants en informatique qui n&#8217;ont encore jamais codé d&#8217;utile de leur vie (je l&#8217;ai fais, donc je +1, d&#8217;ailleurs parfois je le fais toujours :-p), ont entendu / lu que Python, Ruby et PHP étaient lents, et donc les rejette car ils ne correspondent pas à l&#8217;idée qu&#8217;il se fait de la programmation, encore naissance dans sa tête.</p>
<p>La vérité est que les personnes qui ont des contraintes de temps d&#8217;éxécution auquel langage X, n&#8217;importe quel langage, ne peut pas répondre, font partie des 0.00000001 de la population des programmeurs: le plus souvent dans l&#8217;embarqué (voiture, satellite, microchips, etc) et les systèmes temps réels (navigation, chaîne de productions, bourse d&#8217;échange&#8230;). Pour les autres, nous, quasiment tous, les problèmes de performances se joueront sur l&#8217;algo, les libs, les serveurs Web et BDD, le caching, etc. On peut programmer en Basic ou en <a href="http://www.gotopp.org/index.html.fr">GOTO++</a>, ça ne change rien.</p>
<blockquote><p>Languages, libraries and frameworks don&#8217;t scale. Architectures do.</p></blockquote>
<p><a href="http://en.wikipedia.org/wiki/Cal_Henderson"><cite>Cal Henderson </cite></a></p>
<p>Dans certains cas, par exemple le calcul scientifique, les interfaces graphiques ou les jeux videos, la rapidité est importante, et on le sait sans même mesurer. Mais ces problèmes là sont résolus depuis longtemps: il existe des bindings en C extrêmement rapides qui permettent de coder dans son langage interprété favoris tout en bénéficiant d&#8217;algos Speedy Gonzalez sous le capot.</p>
<p>Par ailleurs, ça a déjà été dit 1000 fois, mais ça ne fait pas de mal de le répéter:</p>
<p><strong>Le salaire du développeur et l&#8217;impact commercial de la lenteur d&#8217;un développement coûtent immensément plus cher qu&#8217;un ordinateur plus puissant</strong>. Qui d&#8217;ailleurs ne coûtera plus rien dans 6 mois.</p>
<p>Alors OK, ce n&#8217;est pas une invitation à coder avec ses pieds sous prétexte qu&#8217;on la puissance à disposition (ce qui se fait malheureusement de plus en plus).</p>
<p>Mais choisissez une techno parce que vous êtes productif avec, pas pour ses performances. Sauf si vous avez des mesures chiffrées qui s&#8217;imposent à vous. Auquel cas vous n&#8217;avez de toute façon pas besoin de lire cet article, vous êtes plus compétent que moi.</p>


feed_id: http://sametmax.com/?p=2799
title: Réagir aux changements avec le module signals de Django
uri: Réagir-aux-changements-avec-le-module-signals-de-Django
url: http://sametmax.com/reagir-aux-changements-avec-le-module-signals-de-django/
content:
<p>Le module <code>signals</code> contient une implémentation du <a href="http://sametmax.com/le-pattern-observer-en-utilisant-des-decorateurs/">design pattern observer</a>, c&#8217;est à dire un moyen de lier un <a href="http://sametmax.com/quest-ce-quun-callback/">callback</a> à un événement afin de pouvoir y réagir quand il se déclenche.</p>
<p>Les événements peuvent être aussi divers que &#8220;une requête a commencé&#8221; ou &#8220;un modèle a été sauvé en base de données&#8221;.</p>
<p>L&#8217;utilisation d&#8217;un signal se fait en 3 temps:</p>
<ol>
<li>décider à quel événement on veut réagir;</li>
<li>décider ce qu&#8217;on veut faire quand il se déclenche;</li>
<li>associer l&#8217;événement à l&#8217;action.</li>
</ol>
<p>Par exemple, après la suppression d&#8217;un modèle, je veux faire un travail de nettoyage dans ma base de données.</p>
<p>Je choisis l&#8217;événement auquel je veux réagir dans la <a href="https://docs.djangoproject.com/en/dev/ref/signals/">liste des signaux disponibles</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span>.<span style="color: black;">models</span>.<span style="color: black;">signals</span> <span style="color: #ff7700;font-weight:bold;">import</span> post_delete</pre></div></div>

<p>Ici j&#8217;ai choisi <code>post_delete</code>, car c&#8217;est un signal qui est envoyé après la suppression d&#8217;un modèle automatiquement par Django.</p>
<p>Ensuite je décide de ce que je veux faire quand l&#8217;action se déclenche en écrivant une fonction:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> reaction_au_signal<span style="color: black;">&#40;</span>sender, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># faire ici mon opération de nettoyage</span></pre></div></div>

<p>Vous noterez les arguments très spécifiques que j&#8217;accepte. Ils sont propres à l&#8217;implémentation des signaux de Django et cette signature est obligatoire. <code>sender</code> est l&#8217;objet qui envoie le signal. Dans notre cas ce sera la classe du modèle supprimé. <code>kwargs</code> c&#8217;est <a href="http://sametmax.com/operateur-splat-ou-etoile-en-python/">tout le reste</a>, et son contenu dépend du type de signal reçu. Généralement il y a plein d&#8217;informations dedans sur le contexte qui nous permettent de prendre des décisions.</p>
<p>Ainsi, pour le signal <a href="https://docs.djangoproject.com/en/dev/ref/signals/#django.db.models.signals.post_delete">post_delete</a>, <code>kwargs</code> contient l&#8217;instance du modèle supprimé (dont les valeurs ne sont donc plus en base de données, ne faites pas de query avec !) et le nom de la base de données utilisés si vous en utilisez plusieurs.</p>
<p>Enfin il faut associer l&#8217;événement à l&#8217;action, en utilisant la fonction <code>connect()</code>.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">post_delete.<span style="color: black;">connect</span><span style="color: black;">&#40;</span>reaction_au_signal<span style="color: black;">&#41;</span></pre></div></div>

<p>Le code complet donne ceci:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span>.<span style="color: black;">models</span>.<span style="color: black;">signals</span> <span style="color: #ff7700;font-weight:bold;">import</span> post_delete
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> reaction_au_signal<span style="color: black;">&#40;</span>sender, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># faire ici mon opération de nettoyage dans la base de donnée</span>
&nbsp;
post_delete.<span style="color: black;">connect</span><span style="color: black;">&#40;</span>reaction_au_signal<span style="color: black;">&#41;</span></pre></div></div>

<h2>Réponses à quelques questions existentielles</h2>
<h3>Mais pourquoi que à quoi ça sert de quoi donc ?</h3>
<p>Pourquoi ne pas utiliser plutôt l&#8217;héritage, ou mettre des hooks de callback ? Et bien tout simplement parce que les signaux permettent de réagir à une événement sans avoir à toucher le code qui génère l&#8217;événement. C&#8217;est un moyen très flexible et puissant de réagir à ce que fait du code dans une autre application. Ou de permettre à du code d&#8217;autres applications de réagir à vos événements sans avoir à toucher à votre code. Car oui, vous pouvez définir vos propres signaux.</p>
<h3>Je les mets où ces signaux ?</h3>
<p>Généralement dans le module qui contient la même sémantique que le signal: si c&#8217;est pour les requêtes HTTP, dans <em>views.py</em>, si c&#8217;est pour l&#8217;ORM, dans <em>models.py</em>, etc.</p>
<h3>Est-ce que Dieu existe ?</h3>
<p>Cher lecteur, merci de ne pas prononcer mon nom en vain.</p>
<h2>Quelques astuces avec les signaux</h2>
<p>Il est rare que vous vouliez réagir à la suppression de tous les modèles, ou de toutes les requêtes. Généralement on veut uniquement réagir à un signal pour un émetteur précis. Django permet cela en vous laissant choisir le sender:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> TopModel<span style="color: black;">&#40;</span>models.<span style="color: black;">Model</span><span style="color: black;">&#41;</span>:
    bonnet = models.<span style="color: black;">TextField</span><span style="color: black;">&#40;</span>max_char=<span style="color: #ff4500;">1</span>, default=<span style="color: #483d8b;">&quot;A&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
post_delete.<span style="color: black;">connect</span><span style="color: black;">&#40;</span>reaction_au_signal, sender=TopModel<span style="color: black;">&#41;</span></pre></div></div>

<p>Ainsi, <code>reaction_au_signal()</code> ne sera appelée qu&#8217;à la suppression d&#8217;un objet de type <code>TopModel</code>.</p>
<p>Sachez aussi qu&#8217;il existe une syntaxe à base de décorateurs. Ca fait la même chose, mais perso je préfère la style:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">db</span>.<span style="color: black;">models</span>.<span style="color: black;">signals</span> <span style="color: #ff7700;font-weight:bold;">import</span> post_delete
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">dispatch</span> <span style="color: #ff7700;font-weight:bold;">import</span> receiver
&nbsp;
@receiver<span style="color: black;">&#40;</span>pre_save, sender=MyModel<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> reaction_au_signal<span style="color: black;">&#40;</span>sender, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
    ...</pre></div></div>

<p>Il faut aussi savoir que parfois, certains modules sont exécutés plusieurs fois, et si le handler du signal est déclaré dedans, il va être attaché plusieurs fois au signal, et donc lancé plusieurs fois quand le signal se déclenche. Pas glop.</p>
<p>Pour éviter ça, on peut passer un identifiant unique en attachant le signal:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">post_delete.<span style="color: black;">connect</span><span style="color: black;">&#40;</span>reaction_au_signal, dispatch_uid=<span style="color: #483d8b;">&quot;une_chaine_de_caracteres_quelconque&quot;</span><span style="color: black;">&#41;</span></pre></div></div>

<p><code>dispatch_uid</code> peut contenir n&#8217;importe quoi, pourvu qu&#8217;il soit unique à cette association signal/callback.</p>
<p>Il y a aussi un autre paramètre est nommé <code>weak</code>. C&#8217;est un booléen par défaut mis sur <code>True</code> qui décide si la référence vers le handler est une référence faible ou non. Mettez le sur <code>False</code> si votre callback n&#8217;a aucune autre référence que le signal, par exemple si la fonction est générée à la volée, ou si c&#8217;est une <a href="http://sametmax.com/fonctions-anonymes-en-python-ou-lambda/">lambda</a>.</p>
<p>Enfin, les signaux ne sont PAS exécutés dans un thread à part, donc ils bloquent l’exécution du programme comme le reste du code. La bonne nouvelle, c&#8217;est que ça vous permet d&#8217;utiliser <a href="http://sametmax.com/debugger-en-python-les-bases-de-pdb/">pdb</a> dedans. C&#8217;est particulièrement utile pour les signaux complexes comme <code>m2m_changed</code> qui est assez compliqué et pour lequel on s&#8217;y reprend à plusieurs fois.</p>
<p>Ah, juste un dernier détails. <code>Model.objects.update()</code> ne déclenche aucun signal&#8230;</p>
<h2><code>m2m_changed</code>, ce petit bâtard</h2>
<p>La plupart des signaux sont super faciles à manipuler. Sauf un. <code>m2m_changed</code>. C&#8217;est un enculé.</p>
<p>Il faut savoir que quand vous utilisez <code>models.ManyToManyField</code>, une troisième table est automatiquement et silencieusement créé qui contient l&#8217;association entre vos deux modèles, avec le modèle correspondant. Mais ce modèle ne déclenche pas les signaux <code>*_save</code> et <code>*_delete</code>.</p>
<p>Donc si vous voulez réagir à <code>Model.objects.add()</code>, <code>clear()</code> et consorts, il va falloir se mapper sur <code>m2m_changed</code>, un espèce de fourre tout qui gère l&#8217;intégralité des cas de figures.</p>
<p>Il s&#8217;utilise comme les autres:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> handler<span style="color: black;">&#40;</span>sender, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
   <span style="color: #808080; font-style: italic;"># truc</span>
&nbsp;
m2m_changed.<span style="color: black;">connect</span><span style="color: black;">&#40;</span>handler<span style="color: black;">&#41;</span></pre></div></div>

<p>Mais déjà, première différence, si vous voulez filtrer sur le sender, il faut utiliser le modèle autogénéré de la troisième table qui est un attribut de l&#8217;attribut du modèle qui définit la relation many to many. Vous suivez ? Non ? Relisez la phrase. Ça donne ça:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Tic<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
     partenaire = models.<span style="color: black;">ManyToManyField</span><span style="color: black;">&#40;</span>Tac<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> handler<span style="color: black;">&#40;</span>sender, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
   <span style="color: #808080; font-style: italic;"># truc</span>
&nbsp;
m2m_changed.<span style="color: black;">connect</span><span style="color: black;">&#40;</span>handler, sender=Tic.<span style="color: black;">partenaire</span>.<span style="color: black;">through</span><span style="color: black;">&#41;</span></pre></div></div>

<p><code>through</code> contenant toujours le modèle voulu.</p>
<p>Ensuite, et c&#8217;est là la partie bien relou, <code>kwargs</code> va contenir en plus de <code>instance</code> et <code>using</code>:</p>
<p><strong>action</strong></p>
<p>Ce qui arrive pendant le signal. En gros au lieu d&#8217;avoir 6 signaux, on en a un auquel on passe la valeur: &#8220;<code>pre_add</code>, <code>post_add</code>, <code>pre_remove</code>, <code>post_remove</code>, <code>pre_clear</code>, <code>post_clear</code>&#8220;. Du coup votre code doit gérer tous les cas dans une seule fonction à grand coup de <code>if/else</code>. Génial !</p>
<p><strong>reverse</strong></p>
<p>Indique dans quel sens est la relation. Hyper confusionant.</p>
<p>En gros, si j&#8217;ai:</p>

<div class="wp_syntax"><div class="code"><pre class="true" style="font-family:monospace;">class Tic(object):
     partenaire = models.ManyToManyField(Tac)</pre></div></div>

<p><code>reverse</code> est sur <code>False</code>, si on part de <code>Tic</code> pour aller vers <code>Tac</code>, et <code>True</code> si on part de <code>Tac</code> pour aller vers <code>Tic</code>, car le <code>ManyToManyField</code> est déclaré dans <code>Tic</code>. C&#8217;est complètement arbitraire, car il n&#8217;y a bien entendu aucun sens à une relation M2M, c&#8217;est justement ce qui la différencie d&#8217;un M2One.</p>
<p>Et là où ça devient vraiment fendard, c&#8217;est que la valeur des autres paramètres changent selon la valeur de <code>reverse</code>. Il va falloir rajouter des <code>if/else</code> dans vos <code>if/else</code>.</p>
<p><strong>model</strong></p>
<p>La classe qui a été ajoutée, retirée ou wipée de la relation. Dans notre cas, si <code>reverse</code>, c&#8217;est <code>Tic</code>, sinon, c&#8217;est <code>Tac</code>.</p>
<p><strong>pk_set</strong></p>
<p>Donc le cas des actions add et remove (mais pas clear), ceci est la liste des objets concernés. Elles sont des id d&#8217;instances de <code>Tic</code>, si <code>reverse</code>, sinon des id d&#8217;instances de <code>Tac</code>.</p>
<h2>Créer son propre signal</h2>
<p>C&#8217;est tellement facile qu&#8217;au début on est pas sûr d&#8217;avoir tout fait.</p>
<p>Supposons que vous voulez faire une application qui envoie un <em>POUET !</em> et que vous vouliez également permettre à une autre personne de réagir à cet événement indispensable.</p>
<p>Dans un fichier <em>signals.py</em>, vous allez écrire:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> django.<span style="color: black;">dispatch</span>
&nbsp;
pre_pouet = django.<span style="color: black;">dispatch</span>.<span style="color: black;">Signal</span><span style="color: black;">&#40;</span>providing_args=<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;pouet&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
post_pouet = django.<span style="color: black;">dispatch</span>.<span style="color: black;">Signal</span><span style="color: black;">&#40;</span>providing_args=<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;pouet&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Ouai, c&#8217;est tout. Vous avez créé deux signaux importables qui attendent un argument: le pouet.</p>
<p>Et pour déclencher ces signaux, c&#8217;est très simple:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> signals <span style="color: #ff7700;font-weight:bold;">import</span> pre_pouet, post_pouet
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> PouetGenerator<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    ...
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> send_pouet<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, pouet=<span style="color: #483d8b;">&quot;Alors là, je dis pouet !&quot;</span><span style="color: black;">&#41;</span>:
&nbsp;
        pre_pouet.<span style="color: black;">send</span><span style="color: black;">&#40;</span>sender=<span style="color: #008000;">self</span>, pouet=pouet<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> pouet
        post_pouet.<span style="color: black;">send</span><span style="color: black;">&#40;</span>sender=<span style="color: #008000;">self</span>, pouet=pouet<span style="color: black;">&#41;</span></pre></div></div>

<p>C&#8217;était vachement dur !</p>
<p>Et si quelqu&#8217;un veut réagir à vos pouets, il peut faire:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> pouet_handler<span style="color: black;">&#40;</span>sender, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Tiens, un pouet !&quot;</span>
&nbsp;
post_pouet.<span style="color: black;">connect</span><span style="color: black;">&#40;</span>pouet_handler<span style="color: black;">&#41;</span></pre></div></div>

<p>Dans la série des subtilités, vous avez, en plus de <code>send()</code>, la possibilités d&#8217;appeler <code>send_robust()</code>. C&#8217;est la même chose, mais les exceptions sont attrapées ce qui permet à tous handlers de recevoir le signal, même en cas d&#8217;erreur. Le sender reçoit les exceptions dans un tuple à la fin.</p>
<p>A ce stade là, vous aurez compris, handler, receiver et callback désignent la même chose: la fonction qui réagit à l&#8217;événement. Je les ai utilisées un peu partout sans y prendre garde dans l&#8217;article, donc je mets cette note pour le cas où je vous ai perdu.</p>
<h2>Last word</h2>
<p><code>Signal.disconnect()</code> est l&#8217;inverse de <code>connect()</code>. Je ne m&#8217;en suis jamais servis.</p>


feed_id: http://sametmax.com/?p=2810
title: Google ne sait plus référencer correctement les sites, la preuve en images
uri: Google-ne-sait-plus-référencer-correctement-les-sites-la-preuve-en
url: http://sametmax.com/google-ne-sait-plus-referencer-correctement-les-sites-la-preuve-en-images/
content:
<p>Article un peu provocateur certes mais les résultats Google sont de plus en plus médiocres, j&#8217;en veux pour preuve le site de vos dévoués serviteurs, sam &#038; max. En fouinant dans les mots-clefs qui vous font venir ici je m&#8217;aperçois que pour certains on ressort non seulement sur la première page des résultats Google mais qu&#8217;en plus on rafle la place à des sites institutionnels.</p>
<p>Deux exemples au menu, je précise que les tests ont été fait depuis <strong>différents navigateurs</strong>, sur des <strong>IP différentes</strong>, <strong>sans être loggué</strong> avec un quelconque compte Google.</p>
<p><strong>1. Que les diététitiens me lèchent les couilles!</strong><br />
Je rafle la première place car je suis le plus beau, c&#8217;est normal j&#8217;ai pondu un seul article <a href="http://sametmax.com/comment-bien-manger-en-5-etapes/" title="Comment bien manger">sur comment bien manger</a> et paf nous voilà sur la première page devant mangerbouger.fr.</p>
<div id="attachment_2811" class="wp-caption aligncenter" style="width: 608px"><a href="http://sametmax.com/wp-content/uploads/2012/10/bienmanger.png"?9d7bd4"><img src="http://sametmax.com/wp-content/uploads/2012/10/bienmanger.png"?9d7bd4" alt="" title="Résultats google pour &quot;Comment Bien manger&quot;" width="598" height="548" class="size-full wp-image-2811" /></a><p class="wp-caption-text">10 000$ le backlink, qui n&#039;en veut ?</p></div>
<p>En cherchant sur pagerank.fr j&#8217;ai constaté que mangerbouger.fr avait un pagerank de 6 (sametmax.com a un pagerank de 2) et 1080 bakclinks contre une 20aine pour S&#038;M. C&#8217;est quand même un comble, honte sur eux&#8230;</p>
<p><strong>2. Youporn a qu&#8217;à bien se tenir!</strong><br />
On domine les résultats des recherchent sur le sexe au japon. Là encore un article certes avec du contenu mais pas de quoi fouetter une naine obèse unijambiste, arrive en premier pour pas mal de mots clefs qu&#8217;un webmaster de site de boules voudrait bien avoir (sexe japon, sex japon, sexe japonais, etc..)</p>
<div id="attachment_2815" class="wp-caption aligncenter" style="width: 608px"><a href="http://sametmax.com/wp-content/uploads/2012/11/sexejapon.png"?9d7bd4"><img src="http://sametmax.com/wp-content/uploads/2012/11/sexejapon.png"?9d7bd4" alt="" title="résultats pour &quot;sex japon&quot;" width="598" height="548" class="size-full wp-image-2815" /></a><p class="wp-caption-text">on fait moins les malins là !</p></div>
<p>Je pense qu&#8217;un mec qui va taper ce genre de mot-clef (safesearch désactivé) a déjà la nouille à la main prêt à solliciter les actions de la companie Kleenex et ne s&#8217;attend pas à tomber sur un site comme le nôtre.</p>
<p>Bientôt quand on va taper &#8220;unijambiste fisting&#8221; on va tomber sur un site de prothèses vous allez voir&#8230;</p>
<p>Je nous prends comme exemple mais ça commence à me le faire de plus en plus, les recherches sont beaucoup moins sympas qu&#8217;avant je trouve, il y a aussi les sites comme Wikipedia qui tombent quasi systématiquement en premier alors que <a href="http://www.conservapedia.com/Examples_of_Bias_in_Wikipedia">presque n&#8217;importe qui peut modifier un article sournoisement pour induire le lecteur en erreur</a>.</p>
<p><strong>Conclusion:</strong><br />
Alors oui on pourrait croire que c&#8217;est cool d&#8217;avoir un petit site perso comme S&#038;M qui sort pour &#8220;comment bien manger&#8221; plutôt qu&#8217;un site institutionnel, que ça permet à des sites de sortir du néant face à des mastodontes mais faudrait pas que ça tombe dans le n&#8217;importe quoi non plus.<br />
En fait la première page des résultats de Google est de moins en moins utile je trouve, soit on croise des sites qui n&#8217;ont rien à voir avec la choucroute soit on tombe sur des géants comme Wikipedia et dont on s&#8217;en branle, voire même depuis quelques temps Google nous refourgue ses propres services (traduc, email et Cie).<br />
Faudrait sortir un plugin qui renvoit directos sur la 2ème page ^^</p>
<p>HA! On vient de me signaler qu&#8217;un agent de Google vient de passer sur S&#038;M&#8230;<br />
En plongée&#8230;. 2000 mètres&#8230;</p>


feed_id: http://sametmax.com/?p=2806
title: Cookies, sessions et redirections dans un middleware Django
uri: Cookies-sessions-et-redirections-dans-un-middleware-Django
url: http://sametmax.com/cookies-sessions-et-redirections-dans-un-middleware-django/
content:
<p>En Django les sessions utilisent des cookies, et il n&#8217;y a pas de fallback possible sur un SESSION_ID  passé dans l&#8217;URL comme le fait par exemple PHP (il y a des apps pour ça, mais la pratique est considérée peu sécurisée de toute façon).</p>
<p>Or, comme HTTP est stateless, les cookies sont échangés en permanence, on les reçoit par la requête, et on les envoie avec les réponses. Ajoutez à cela qu&#8217;un client peut choisir de désactiver le support de cookie, et vous avez là un merveilleux casse-tête.</p>
<p>Imaginez: vous vérifiez que l&#8217;utilisateur possède une valeur dans les cookies. Si ce n&#8217;est pas le cas, vous mettez la valeur dans le cookie et vous redirigez sur la page en cours. Ainsi, il retourne sur la même page, avec le cookie. Mais si il a les cookies désactivée, il va revenir sans le cookie, et vous allez le rediriger, encore, et encore.</p>
<p>Et oui, on peut faire des boucles infinies avec HTTP !</p>
<h2>Tester si les cookies sont disponibles</h2>
<p>Le seul moyen de s&#8217;en sortir dans un site qui ne peut pas fonctionner sans cookie (ce qui est le cas de toute partie d&#8217;une site qui demande une authentification) est d&#8217;utiliser 3 vues.</p>
<p>La vue normale qui demande une session, et donc un cookie.<br />
La vue qui remplit la session avec les informations utiles (par exemple la vue d&#8217;authentification, ou autre).<br />
La vue vers laquelle on renvoie si il n&#8217;y a pas de cookie (une page expliquant qu&#8217;il faut activer les cookies si on veut accéder à la partie authentifiée du site).</p>
<p>Voilà à quoi ressemble le mécanisme dans sa plus simple expression:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">shortcuts</span> <span style="color: #ff7700;font-weight:bold;">import</span> redirect
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">http</span> <span style="color: #ff7700;font-weight:bold;">import</span> HttpResponse
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># '^nocookies/'</span>
<span style="color: #ff7700;font-weight:bold;">def</span> nocookies<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        Page expliquant avec pédagogie que les cookies sont nécessaires
        à l'accès à la partie authentifiée du site.
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> HttpResponse<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Use cookies, you bastard'</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># '^setinfos/'</span>
<span style="color: #ff7700;font-weight:bold;">def</span> setinfos<span style="color: black;">&#40;</span>request, next<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        Page qui vérifie si les cookies sont disponibles, et si oui, remplit
        la session d'infos importantes, puis redirige vers la page précédente.
&nbsp;
        Si les cookies ne sont pas disponibles, on redirige vers la page
        d'explication.
    &quot;&quot;&quot;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># On vérifie la présence du cookie de test</span>
    <span style="color: #808080; font-style: italic;"># Il atteste que les cookies marchent</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> request.<span style="color: black;">session</span>.<span style="color: black;">test_cookie_worked</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> redirect<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/nocookies/'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># On nettoie le cookie de test, on va pas pourrir le navigateur du user :-)</span>
    request.<span style="color: black;">session</span>.<span style="color: black;">delete_test_cookie</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># On met les infos en sessions</span>
    request.<span style="color: black;">session</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'trucimportant'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'Super Important !'</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># On redirige vers la page qui a redirigé vers cette page</span>
    <span style="color: #808080; font-style: italic;"># Si la page précédente n'a pas précisé ou rediriger en querystring,</span>
    <span style="color: #808080; font-style: italic;"># on redirige vers l’accueil</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> redirect<span style="color: black;">&#40;</span>request.<span style="color: black;">GET</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'next'</span>, <span style="color: #483d8b;">'/'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># /profile</span>
<span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #dc143c;">profile</span><span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        Page qui a besoin d'informations en session, et qui redirige vers
        la page qui écrit ces infos en cas d'absence de celles-ci.
    &quot;&quot;&quot;</span>
&nbsp;
    important = request.<span style="color: black;">session</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'trucimportant'</span>, <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> important:
        <span style="color: #808080; font-style: italic;"># on met le cookie de test ici, car on veut vérifier sa présence</span>
        <span style="color: #808080; font-style: italic;"># dans la prochaine vue</span>
        request.<span style="color: black;">session</span>.<span style="color: black;">set_test_cookie</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># On redirige vers la vue qui met les infos dont on a besoin en session</span>
        <span style="color: #808080; font-style: italic;"># en précisant vers où rediriger une fois les infos mises en place</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> redirect<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/setinfos/?next=%s'</span> <span style="color: #66cc66;">%</span> request.<span style="color: black;">get_full_path</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> HttpResponse<span style="color: black;">&#40;</span>important<span style="color: black;">&#41;</span></pre></div></div>

<p>Pour la page pédagogique, ma technique favorite consiste à mettre une courte explication avec un lien vers <a href="http://support.google.com/accounts/bin/answer.py?hl=en&#038;answer=61416">la page que Google utilise</a> pour expliquer comment activer les cookies: cette page est à jour pour tous les browsers et est disponible dans de nombreuses langues (crédit à 37signals qui font ça pour le javascript). Je met aussi un lien vers la page qui set les infos en session avec l&#8217;URL de redirection en paramètre, car sinon l&#8217;utilisateur ne saura pas retourner à son point de départ. Le texte doit être court, clair, et pas perturbant.</p>
<h2>Et dans un middleware&#8230;</h2>
<p>Mais le plus fun, c&#8217;est quand on fait tout ça dans un middleware. Car on a pas le loisir d&#8217;avoir plusieurs vues avec lesquelles jouer. Que faire alors ? Et bien on va utiliser HTTP jusqu&#8217;au bout en stockant la sémantique dans les URLs, et en la récupérant directement dedans.</p>
<p>C&#8217;est ce que je fais dans le middleware d&#8217;autologging de <a href="http://sametmax.com/django-quicky-labolition-des-preliminaires-par-sam-et-max/">Django quicky</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> AutoLogNewUser<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
&nbsp;
    CALLBACK = setting<span style="color: black;">&#40;</span><span style="color: #483d8b;">'AUTOLOGNEWUSER_CALLBAK'</span>, <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> process_request<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, request<span style="color: black;">&#41;</span>:
&nbsp;
&nbsp;
        <span style="color: #808080; font-style: italic;"># on arrive dans ce if seulement si on a détecté avant pas </span>
        <span style="color: #808080; font-style: italic;"># de données dans la session et redirigé sur cette URL </span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #483d8b;">'django-quicky-test-cookie'</span> <span style="color: #ff7700;font-weight:bold;">in</span> request.<span style="color: black;">path</span>:
&nbsp;
            <span style="color: #808080; font-style: italic;"># on check que le test cookie a marché, et sinon, on redirige</span>
            <span style="color: #808080; font-style: italic;"># sur la page pédagogique</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> request.<span style="color: black;">session</span>.<span style="color: black;">test_cookie_worked</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
                <span style="color: #ff7700;font-weight:bold;">return</span> render<span style="color: black;">&#40;</span>request, <span style="color: #483d8b;">'django_quicky/no_cookies.html'</span>,
                              <span style="color: black;">&#123;</span><span style="color: #483d8b;">'next'</span>: request.<span style="color: black;">GET</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'next'</span>, <span style="color: #483d8b;">'/'</span><span style="color: black;">&#41;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
&nbsp;
            request.<span style="color: black;">session</span>.<span style="color: black;">delete_test_cookie</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
            first_name = <span style="color: #008000;">iter</span><span style="color: black;">&#40;</span>NameGenerator<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">next</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">title</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            username = <span style="color: #483d8b;">&quot;%s%s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>first_name, <span style="color: #dc143c;">random</span>.<span style="color: black;">randint</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span>, <span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            <span style="color: #dc143c;">user</span> = User.<span style="color: black;">objects</span>.<span style="color: black;">create</span><span style="color: black;">&#40;</span>username=username,
                                       first_name=first_name<span style="color: black;">&#41;</span>
            request.<span style="color: black;">session</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'django-quicky:user_id'</span><span style="color: black;">&#93;</span> = <span style="color: #dc143c;">user</span>.<span style="color: black;">pk</span>
&nbsp;
            <span style="color: #808080; font-style: italic;"># tout a bien marché, on redirige vers l'url précédente</span>
            next = request.<span style="color: black;">GET</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'next'</span>, <span style="color: #483d8b;">'/'</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">CALLBACK</span>:
                res = <span style="color: #008000;">self</span>.<span style="color: black;">CALLBACK</span><span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">return</span> redirect<span style="color: black;">&#40;</span>res <span style="color: #ff7700;font-weight:bold;">or</span> next<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
        <span style="color: #808080; font-style: italic;"># ici is_authenticated() ne marche pas si pas de cookie</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> request.<span style="color: #dc143c;">user</span>.<span style="color: black;">is_authenticated</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
            user_id = request.<span style="color: black;">session</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'django-quicky:user_id'</span>, <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #808080; font-style: italic;"># rien en session ? on redirige sur l'url test de cookie</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> user_id:
&nbsp;
                request.<span style="color: black;">session</span>.<span style="color: black;">set_test_cookie</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
                <span style="color: #ff7700;font-weight:bold;">return</span> redirect<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/django-quicky-test-cookie/?next=%s'</span> <span style="color: #66cc66;">%</span> request.<span style="color: black;">path</span><span style="color: black;">&#41;</span>
&nbsp;
            request.<span style="color: #dc143c;">user</span> = User.<span style="color: black;">objects</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span>pk=user_id<span style="color: black;">&#41;</span></pre></div></div>

<h2>Et si on veut stocker tout ça dans des cookies, et pas en session ?</h2>
<p>On est très tenté de faire un truc comme ça:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">request.<span style="color: black;">COOKIES</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'trucimportant'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'Super Important !'</span></pre></div></div>

<p>Mais ça ne peut plus marcher que de faire ça:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">request.<span style="color: black;">POST</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'trucimportant'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'Super Important !'</span></pre></div></div>

<p>En effet, les cookies sont justes des infos qu&#8217;on s&#8217;envoie. Il n&#8217;y a pas de lien entre ceux qu&#8217;on reçoit et ceux qu&#8217;on envoie, et là on écrit dans le dictionnaire de ceux qu&#8217;on reçoit.</p>
<p>Donc pour envoyer un cookie, il faut le faire dans la réponse:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">response = render_to_response<span style="color: black;">&#40;</span>...<span style="color: black;">&#41;</span>
response.<span style="color: black;">set_cookie</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;trucimportant&quot;</span>, <span style="color: #483d8b;">'Super Important !'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">return</span> response</pre></div></div>


feed_id: http://sametmax.com/?p=2785
title: Les vues sur des collections en Python
uri: Les-vues-sur-des-collections-en-Python
url: http://sametmax.com/les-vues-sur-des-collections-en-python/
content:
<p>Python 3 introduit de nombreux changements qui ont été backportés dans Python 2.7. Parmi eux, les vues, qui sont un concept assez mal expliqué dans la documentation standard.</p>
<h2>Dictionary views</h2>
<p>Quand on voulait travailler sur les valeurs d&#8217;un dictionnaire en Python, on avait deux choix:</p>
<ul>
<li>faire <code>dict.values()</code> et récupérer une liste entière. Créant une liste entière en mémoire.</li>
<li>faire <code>dict.itervalues()</code>, et récupérer un générateur. Mais qui ne peut être lu qu&#8217;une fois.</li>
</ul>
<p>Les vues sont une solution intermédiaire: ce sont des objets qui prennent peu de mémoire, mais qui peuvent être lus plusieurs fois.</p>
<p>Exemple:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> scores = <span style="color: black;">&#123;</span><span style="color: #483d8b;">'foo'</span>: <span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">'bar'</span>: <span style="color: #ff4500;">0</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> val = scores.<span style="color: black;">viewvalues</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> val
dict_values<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff4500;">1</span> <span style="color: #ff7700;font-weight:bold;">in</span> val
<span style="color: #008000;">True</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: black;">&#91;</span>x <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">2</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> val<span style="color: black;">&#93;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Contrairement à une liste, les vues issues d&#8217;un dictionnaire ne supportent pas le slicing ou l&#8217;assignation et il n&#8217;y a aucune garantie d&#8217;ordre des éléments. De plus, elles ne peuvent être modifiées.</p>
<p>Bref, <strong>une vue ne contient rien</strong>, c&#8217;est juste un objet qui, quand on accède à son contenu, va le chercher dans le dictionnaire et vous le retourne. C&#8217;est ce qu&#8217;on appelle un objet proxy: il vous donne l&#8217;illusion d&#8217;accéder directement aux données pour vous faciliter la vie, généralement en vous les présentant sous une forme différente: ici un itérable.</p>
<p>On peut récupérer des vues pour les valeurs, mais également pour les clés et les couples clés / valeurs. Ces deux types de vues se comportent en plus comme des <a href="http://sametmax.com/ce-que-vous-ne-saviez-pas-sur-les-collections-en-python/">sets</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> scores.<span style="color: black;">viewitems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
dict_items<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'foo'</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #483d8b;">'bar'</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> scores.<span style="color: black;">viewkeys</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> | <span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span>,<span style="color: black;">&#93;</span>
<span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span>, <span style="color: #483d8b;">'foo'</span>, <span style="color: #483d8b;">'bar'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Puisqu&#8217;il est rare d&#8217;avoir besoin d&#8217;une vraie liste, et comme les vues sont une très bonne alternative aux générateurs, <code>dict.values</code> et consorts retournent des vues en Python 3.</p>
<p>Maintenant vous allez me dire &#8220;Mais si les vues sont une si bonne alternative aux générateurs, pourquoi on ne remplace pas tous les générateurs par des vues ?&#8221;. </p>
<p>Tout simplement parce que ce n&#8217;est pas possible. Un générateur est un mécanisme standard qui permet de produire des valeurs une par une. N&#8217;importe qui peut créer un générateur, car c&#8217;est un concept portable d&#8217;un problème à un autre. On peut l&#8217;appliquer à de nombreuses choses: algorithme, flux de données, fichier, etc. </p>
<p>Une vue n&#8217;est qu&#8217;un proxy qui permet de voir une <a href="http://sametmax.com/quest-ce-quune-structure-de-donnees/">structure de données</a> sous une autre forme. Il faut coder une vue par type de structure de données, car la vue va chercher les données dans cette structure quand on lui demande. Le code est donc différent à chaque fois.</p>
<p>Python ne permet pas de créer soi-même des vues, mais créer un proxy, c&#8217;est à dire un objet qui retourne les valeurs d&#8217;un autre objet quand on l&#8217;interroge, peut se faire à la main dans tout langage de programmation. Ainsi vous pourriez créer un proxy qui ressemble a une vue des clés d&#8217;un dico très simplement:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> keyview<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, d<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">d</span> = d
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__iter__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">d</span>.<span style="color: black;">iterkeys</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> view = keyview<span style="color: black;">&#40;</span>scores<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> view:
...     <span style="color: #ff7700;font-weight:bold;">print</span> x
...     
<span style="color: black;">foo</span>
bar
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>view<span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'foo'</span>, <span style="color: #483d8b;">'bar'</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span></pre></div></div>

<p>L&#8217;implémentation réelle de Python (en C&#8230;) ne fait pas vraiment grand chose de plus, juste un travail d&#8217;optimisation pour être plus rapide.</p>
<h2>memoryview</h2>
<p>Les memory views suivent le même principe, mais appliqué à toute structure de données qui supporte le buffer protocole (un certain nombre de méthodes avec un nom et un comportement défini par ce protocole) comme celles trouvées dans le module <code>struct</code> ou <code>array</code>. La structure de données la plus connue qui suit le buffer protocole est la chaîne de caractères.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> s = <span style="color: #483d8b;">'Sam &amp; Max eat the road with a Github fork'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> ms = memoryview<span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> ms<span style="color: black;">&#91;</span>-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
<span style="color: #483d8b;">'k'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> ms<span style="color: black;">&#91;</span>:<span style="color: #ff4500;">9</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&lt;</span>memory at 0x25ded60<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>ms<span style="color: black;">&#91;</span>:<span style="color: #ff4500;">9</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'Sam &amp; Max'</span></pre></div></div>

<p>Le principal intérêt de la memory view appliquée aux strings, c&#8217;est que tout slicing retourne une nouvelle memory view. On peut donc travailler sur des parties de la chaînes sans créer une nouvelle chaîne en mémoire.</p>
<p>En revanche, les chaînes unicodes ne sont pas supportées. Il vous faudra jouer avec <code>encode()</code> et <code>decode()</code>.</p>


feed_id: http://sametmax.com/?p=2855
title: Qu’est-ce qu’une structure de données ?
uri: Qu-est-ce-qu-une-structure-de-données
url: http://sametmax.com/quest-ce-quune-structure-de-donnees/
content:
<p>Dans certains des articles, on utilise ce terme. Et il est très répandu également sur le Web, sous cette forme ou dans sa version angloclassos: data structure.</p>
<p>Une structure de données est simplement du code dont le but est de contenir des données et de les représenter sous une certaine forme:</p>
<ul>
<li>une liste est une structure de données;</li>
<li>un dictionnaire est une structure de données;</li>
<li>un arbre binaire est une structure de données.</li>
</ul>
<p>Les structures de données sont donc des conteneurs, mais qui sont liés à une certaine logique de manipulation: on peut faire des <code>append()</code> et des <code>pop()</code> sur une liste, des <code>get()</code> et <code>setdefault()</code> sur un dictionnaire, et des <code>parent()</code>, <code>left()</code> et <code>right()</code> sur un arbre binaire. Dans des langages qui ne sont pas complètement orientés objet comme PHP, on a des fonctions pour manipuler ces structures de données, par exemple<br />
<code>array_pop()</code> permet de manipuler <code>Array()</code>.</p>
<p>Or, vous pouvez coder votre propre structure de données, et c&#8217;est d&#8217;ailleurs ce que vous faites quand vous créez un objet.</p>
<p>Vous pouvez apprécier maintenant la question suivante avec une certaine ironie: qu&#8217;est-ce qui n&#8217;est PAS une structure de données ? Dans les langages comme le C, une fonction n&#8217;est pas une structure de données: elle ne contient rien, c&#8217;est une suite d&#8217;instructions. Mais dans le langage Python, une fonction est une structure de données car c&#8217;est un objet: il contient des références vers son code, ses arguments, et tout un tas de metadata.</p>
<p>Pour se simplifier la vie, on parlera de structure de données pour les objets qui ont été créés avec pour but de contenir et de manipuler des données à travers eux (liste, tuple, set, dict, strings, etc), et non pas des objets dont leur nature a pour effet secondaire d&#8217;être une structure de données (fonctions, objets métiers, classes, etc).</p>
<p>Notez bien que les structures de données sont très nombreuses: il n&#8217;y a pas que les tuples et les sets dans la vie. Rien qu&#8217;en Python, on a des arrays, des string buffers, des heap queue, et tout un tas de joyeusetés. </p>


feed_id: http://sametmax.com/?p=2863
title: Quelques innovation de Python 3 backportées en Python 2.7
uri: Quelques-innovation-de-Python-3-backportées-en-Python-2-7
url: http://sametmax.com/quelques-innovation-de-python-3-backportees-en-python-2-7/
content:
<p>Comme nous l&#8217;avons vu avec les <a href="http://sametmax.com/les-vues-sur-des-collections-en-python/">vues</a> ou les <a href="http://sametmax.com/ce-que-vous-ne-saviez-pas-sur-les-collections-en-python/">collections</a>, Python 2.7 vient avec pas mal de bonus issus directement de la branche 3. En voici quelques autres. Tout ceci n&#8217;est bien sûr ni nouveau ni exhaustif, mais je m’aperçois que peu de personnes le savent.</p>
<p>Une notation littérale pour les sets:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: black;">&#123;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#125;</span> == <span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">True</span></pre></div></div>

<p>Une syntaxe pour les dictionnaires en intention:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> d = <span style="color: black;">&#123;</span><span style="color: #008000;">chr</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>: x <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">65</span>, <span style="color: #ff4500;">91</span><span style="color: black;">&#41;</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> d
<span style="color: black;">&#123;</span><span style="color: #483d8b;">'A'</span>: <span style="color: #ff4500;">65</span>, <span style="color: #483d8b;">'C'</span>: <span style="color: #ff4500;">67</span>, <span style="color: #483d8b;">'B'</span>: <span style="color: #ff4500;">66</span>, <span style="color: #483d8b;">'E'</span>: <span style="color: #ff4500;">69</span>, <span style="color: #483d8b;">'D'</span>: <span style="color: #ff4500;">68</span>, <span style="color: #483d8b;">'G'</span>: <span style="color: #ff4500;">71</span>, <span style="color: #483d8b;">'F'</span>: <span style="color: #ff4500;">70</span>, <span style="color: #483d8b;">'I'</span>: <span style="color: #ff4500;">73</span>, <span style="color: #483d8b;">'H'</span>: <span style="color: #ff4500;">72</span>, <span style="color: #483d8b;">'K'</span>: <span style="color: #ff4500;">75</span>, <span style="color: #483d8b;">'J'</span>: <span style="color: #ff4500;">74</span>, <span style="color: #483d8b;">'M'</span>: <span style="color: #ff4500;">77</span>, <span style="color: #483d8b;">'L'</span>: <span style="color: #ff4500;">76</span>, <span style="color: #483d8b;">'O'</span>: <span style="color: #ff4500;">79</span>, <span style="color: #483d8b;">'N'</span>: <span style="color: #ff4500;">78</span>, <span style="color: #483d8b;">'Q'</span>: <span style="color: #ff4500;">81</span>, <span style="color: #483d8b;">'P'</span>: <span style="color: #ff4500;">80</span>, <span style="color: #483d8b;">'S'</span>: <span style="color: #ff4500;">83</span>, <span style="color: #483d8b;">'R'</span>: <span style="color: #ff4500;">82</span>, <span style="color: #483d8b;">'U'</span>: <span style="color: #ff4500;">85</span>, <span style="color: #483d8b;">'T'</span>: <span style="color: #ff4500;">84</span>, <span style="color: #483d8b;">'W'</span>: <span style="color: #ff4500;">87</span>, <span style="color: #483d8b;">'V'</span>: <span style="color: #ff4500;">86</span>, <span style="color: #483d8b;">'Y'</span>: <span style="color: #ff4500;">89</span>, <span style="color: #483d8b;">'X'</span>: <span style="color: #ff4500;">88</span>, <span style="color: #483d8b;">'Z'</span>: <span style="color: #ff4500;">90</span><span style="color: black;">&#125;</span></pre></div></div>

<p>Imbriquer <code>with</code>:</p>
<p>Avant il fallait utiliser <a href="http://docs.python.org/2/library/contextlib.html#contextlib.nested">nested()</a> ou imbriquer à la main</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'fichiera'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> a:
    <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'fichiera'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> b:
        <span style="color: #808080; font-style: italic;"># faire un truc</span></pre></div></div>

<p>Maintenant on peut faire:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'fichiera'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> a, <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'fichiera'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> b:
    <span style="color: #808080; font-style: italic;"># faire un truc</span></pre></div></div>

<p>Rien à voir, mais toujours sympa. <code>timedelta</code> a maintenant une méthode <code>total_seconds()</code> qui retourne la valeur de la durée en seconde. En effet, l&#8217;attribut <code>seconds</code> ne retourne que ce qui reste en seconde une fois qu&#8217;on a retiré les jours:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">datetime</span> <span style="color: #ff7700;font-weight:bold;">import</span> timedelta
<span style="color: #66cc66;">&gt;&gt;&gt;</span> delta = timedelta<span style="color: black;">&#40;</span>days=<span style="color: #ff4500;">1</span>, seconds=<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> delta.<span style="color: black;">seconds</span>
<span style="color: #ff4500;">1</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> delta.<span style="color: black;">total_seconds</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">86401.0</span></pre></div></div>

<p>Notez qu&#8217;il n&#8217;y a toujours ni attribut minutes, ni heures.</p>
<p>Le module <code>unittest</code> gagne une pléthore d&#8217;améliorations, et notamment:</p>
<p>L&#8217;utilisation de <code>assertRaises</code> comme context manager:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">self</span>.<span style="color: black;">assertRaises</span><span style="color: black;">&#40;</span><span style="color: #008000;">KeyError</span><span style="color: black;">&#41;</span>:
    <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'foo'</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Et un bon gros nombres de méthodes:</p>
<p><code>assertIsNone()</code> / <code>assertIsNotNone()</code>, <code>assertIs()</code> / <code>assertIsNot()</code>, <code>assertIsInstance()</code> / <code>assertNotIsInstance()</code>, <code>assertGreater()</code> / <code>assertGreaterEqual()</code> / <code>assertLess()</code> / <code>assertLessEqual()</code>, <code>assertRegexpMatches()</code> / <code>assertNotRegexpMatches()</code>, <code>assertRaisesRegexp()</code>,<br />
<code>assertIn()</code> / <code>assertNotIn()</code>, <code>assertDictContainsSubset()</code>, <code>assertAlmostEqual()</code> / <code>assertNotAlmostEqual()</code>.</p>
<p>Enfin <code>format()</code> commence à devenir une alternative valable à <code>%</code> car il propose maintenant des marqueurs sans noter d’index:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;{}, puis {} et finalement {}&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'0, puis 1 et finalement 2'</span></pre></div></div>

<p>Et il ajoute le séparateur des milliers au mini-langage de formatage, mais pour la virgule uniquement. Par exemple, si avoir un nombre de 15 caractères minimum formater en tant que float, avec deux chiffres après la virgules, et donc les milliers sont groupés à l&#8217;américaine:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">'{:15,.2f}'</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">54321</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'      54,321.00'</span></pre></div></div>


feed_id: http://sametmax.com/?p=2871
title: Devenez un super-héros, ou pas…
uri: Devenez-un-super-héros-ou-pas
url: http://sametmax.com/devenez-un-super-hero-ou-zero/
content:
<p>Comme j&#8217;ai passé le week-end sur une doc de 2.2 gigawatts j&#8217;ai zappé après 3 claquages de synapses et me suis écroulé devant la télé, et là sur TV5 monde je tombe sur le reportage : &#8220;Deviens un super-héros&#8230; pour de vrai !&#8221;</p>
<p>Reportage réalisé par <a href="http://www.aleksandardzerdz.com/">Aleksandar Dzedz</a>.</p>
<p><iframe src="http://player.vimeo.com/video/24728614?title=0&amp;portrait=0&amp;color=F0A29C" width="400" height="300" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe></p>
<p>L&#8217;action se situe principalement aux USA, des gens (généralement des jeunes du genre &#8220;je sais tout je vais à la FAC&#8221;) se déguisent en super-héros et veulent faire régner la loi, la justice, dans leur quartier.<br />
Les premières minutes m&#8217;ont fait me demander si c&#8217;était une blague ou pas, j&#8217;ai même failli zapper tellement je trouvais ça nul, et puis quelque chose m&#8217;a forcé à regarder, la flêmme de changer de chaîne surement.</p>
<p>Mais au fil du reportage (qui ne porte pas de jugement d&#8217;ailleur, ça change des merdes de Rance télévision) le réalisateur nous dépeind les personnages un par un et les filme dans leurs actions.<br />
Ils sont tous déjantés (surtout Master Legend qui distribue des diamants imbibés de ses supers pouvoirs, sisi&#8230;) mais ils ont un tous un point commun qu&#8217;on aura jamais en France, c&#8217;est le : &#8220;Faites-le vous même&#8221;.<br />
Ils savent très bien que les associations c&#8217;est du flanc, que l&#8217;Etat n&#8217;a rien à foutre de ses pauvres et donc ces super-héros font avant tout du social et ne courrent pas (comme je le pensais au début) après les méchants.</p>
<p><strong>Des chaussettes, un café chaud et une couverture:</strong><br />
Même si certains font des rondes de quartier pour ne serait-ce que par leur présence dissuader certains voleurs de passer à l&#8217;acte. La grande majorité distribue non pas des pains mais des..chaussettes.<br />
Ca parrait con les chaussettes mais c&#8217;est le genre de chose qui fait défaut aux gens qui vivent dans la rue avec des couvertures, et un peu de chaleur humaine.<br />
Une poignée de main, quelques mots, un sandwich, un café, c&#8217;est vrai qu&#8217;au final on devrait tous le faire de temps en temps. C&#8217;est rien pour nous mais ça compte pour la personne qui n&#8217;a plus rien.</p>
<p><strong>Pourquoi ils se deguisent ?</strong><br />
Là où je pige pas trop c&#8217;est le fait de se déguiser en super-héros, surement que dans la tête des américains c&#8217;est synonyme de supers pouvoirs et que ça les motives encore plus à faire leurs bonnes actions. Un peu comme quand on met son super <a href="http://www.youtube.com/watch?v=HpSoZlcRFFM" title="ha bougoudoublou fish">slip moulant</a> quand on va à la plage faire le beau, ça permet de se sentir dans la peau d&#8217;un autre, d&#8217;un Superman.</p>
<p>Je ne suis pas sur que ça emmergera un jour chez nous, le Français est trop égoïste par nature, trop fainéant et surtout trop individualiste pour agir de la sorte (j&#8217;en suis une belle preuve) mais je dois avouer qu&#8217;à la fin du reportage je me suis immaginé à aller acheter un sac avec couverture, chaussettes, etc pour le filer à un malheureux mais bien sur je ne l&#8217;ai pas fait.<br />
Quoiqu&#8217;il en soit c&#8217;est un reportage que je recommande, le côté déjanté des ricains leur font faire des trucs étonnants quand même.</p>
<p>PS: mon super-héros préféré est &#8220;Life&#8221; si vous regardez le reportage, plutôt discret avec juste un petit masque à la frelon vert.</p>
<p><strong>Et vous allez vous aimez les uns les autres bordel de merde !</strong><br />
<iframe width="420" height="315" src="http://www.youtube.com/embed/OKu098E-gA0" frameborder="0" allowfullscreen></iframe></p>


feed_id: http://sametmax.com/?p=2879
title: Utiliser AngularJs avec le langage de template de Django
uri: Utiliser-AngularJs-avec-le-langage-de-template-de-Django
url: http://sametmax.com/utiliser-angularjs-avec-le-langage-de-template-de-django/
content:
<p><a href="http://angularjs.org/">AngularJS</a> est vraiment une bibliothèque javascript prometteuse. Je suis en train de jouer avec, avec l&#8217;espoir qu&#8217;un jour elle remplace complètement jQuery + Backbone.js dans tous mes projets.</p>
<p>Une chose qui peut être ennuyeuse cependant, c&#8217;est que par défaut Angular évalue les expressions qui sont marquées par <code>{{}}</code>, exactement comme le langage de template Django. Cela amène à un conflit.</p>
<p>Heureusement on peut changer ces marqueurs à l&#8217;initialisation:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> m <span style="color: #339933;">=</span> angular.<span style="color: #660066;">module</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'monApp'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
m.<span style="color: #660066;">config</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>$interpolateProvider<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
    $interpolateProvider.<span style="color: #660066;">startSymbol</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'[['</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
    $interpolateProvider.<span style="color: #660066;">endSymbol</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">']]'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Ici je choisis <code>[[]]</code>.</p>


feed_id: http://sametmax.com/?p=2884
title: Se simplifier les tests Python avec Pytest
uri: Se-simplifier-les-tests-Python-avec-Pytest
url: http://sametmax.com/se-simplifier-les-tests-python-avec-pytest/
content:
<p>Personne n&#8217;aime faire des tests unitaires. C&#8217;est un peu comme les impôts: on sait que c&#8217;est utile, mais on est jamais content de s&#8217;en occuper.</p>
<p>Réchèr m&#8217;a dernièrement <a href="http://sametmax.com/quelques-innovation-de-python-3-backportees-en-python-2-7/#comment-2870">posé la question</a> de l&#8217;abondance des méthodes <code>assertTruc()</code> et leur utilité, et je lui ai répondu que chaque méthode donnait des infos adaptées au test effectué.</p>
<p>Max m&#8217;a dernièrement fait la remarque que les tests &#8220;c&#8217;est bien mais c&#8217;est compliqué&#8221;. J&#8217;avoue être à court de contre argument.</p>
<p>Et si on pouvait rendre les tests plus simples à écrire et à lire, aussi simple qu&#8217;un <code>assert</code>, mais avec un résultat plus clair que <code>unittest</code> en sortie ?</p>
<p><code><a href="http://sametmax.com/votre-python-aime-les-pip/">pip install</a> pytest </code></p>
<p><a href="http://pytest.org/latest/index.html">Pytest</a> est une lib de test à utiliser à la place de <a href="http://docs.python.org/2/library/unittest.html">unittest</a>. Ses créateurs utilisent l&#8217;introspections et l&#8217;injection de dépendance pour créer des tests magiquement.</p>
<p>D&#8217;ordinnaire, la magie, on aime pas trop ça en Python, et on laisse ça aux rubistes. Mais dans le domaine du test, qui n&#8217;est pas un code de production avec les mêmes contraintes de lecture, de recherche de bugs architecturaux et d&#8217;interactions entre dev, mais qui a par contre une forte contrainte &#8220;j&#8217;ai pas envie d&#8217;écrire un caractère de plus&#8221;, ça a du sens.</p>
<p>Voilà comment ça se passe: on vire toute ce qui est classe et setup verbeux. On laisse juste les imports de vos libs, et les tests. Avec des <code>assert</code>. Pytest va alors analyser tout ça, et faire tout le boulot autour pour vous.</p>
<p>Exemple:</p>
<p>Dans votre lib:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> ma_fonction_a_tester<span style="color: black;">&#40;</span>a, b<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> a + b</pre></div></div>

<p>Dans votre fichier test.py:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> malib <span style="color: #ff7700;font-weight:bold;">import</span> ma_fonction_a_tester
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> test_function<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">assert</span> ma_fonction_a_tester<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span> == <span style="color: #ff4500;">2</span></pre></div></div>

<p>Et on lance :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">py.test test.py</pre></div></div>

<p>Pour obtenir:</p>
<pre>====== test session starts ======
platform linux2 -- Python 2.7.3 -- pytest-2.3.2
collected 1 items

Bureau/test.py .

====== 1 passed in 0.02 seconds ======
</pre>
<p>Et voilà, les tests redeviennent bêtes et simples. Mais ils ne perdent pas en puissance. Car Pytest analyse le <code>assert</code>, et le transforme à la volée. Du coup, pour les <a href="http://sametmax.com/quest-ce-quune-structure-de-donnees/">structures de données</a> complexes, Pytest va vous sortir les infos de debug utile que <code>assertTruc()</code> de unittest vous aurait sorti.</p>
<p>Exemple avec des tuples:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> ma_fonction_a_tester<span style="color: black;">&#40;</span>a, b<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span>a <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">2</span>, b <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> test_function<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">assert</span> ma_fonction_a_tester<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span> == <span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Va donner:</p>
<pre>
====== test session starts ======
platform linux2 -- Python 2.7.3 -- pytest-2.3.2
collected 1 items

Bureau/test.py F

====== FAILURES ======
______ test_function ______

    def test_function():
>       assert ma_fonction_a_tester(1, 1) == (2, 2, 3)
E       assert (2, 2) == (2, 2, 3)
E         Right contains more items, first extra item: 3

Bureau/test.py:7: AssertionError
====== 1 failed in 0.02 seconds ======</pre>
<p>On nous indique clairement qu&#8217;il y a un item de trop dans mon résultat, et lequel.</p>
<p>En prime, Pytest nous affranchie des fonctions <code>setUp()</code> et <code>tearDown()</code> génériques. Le problème de ces méthodes dans unittest, c&#8217;est qu&#8217;elles sont éxécutées à chaque début de test. On en a pas forcément besoin, et on a pas les mêmes besoins pour chaque test.</p>
<p>Pytest ajoute encore un peu de magie pour régler le probleme</p>
<p>Dans votre lib, vous avez ça:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> extraire_title<span style="color: black;">&#40;</span>html<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        Extrait le title d'une page HTML a base de regex. C'est mal.
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">search</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'&lt;title[^&gt;]*&gt;(.*)&lt;/title&gt;'</span>, html<span style="color: black;">&#41;</span>.<span style="color: black;">groups</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">IndexError</span>, <span style="color: #008000;">AttributeError</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">None</span></pre></div></div>

<p>Dans votre fichier de tests, vous aurez:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">urllib2</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> pytest
&nbsp;
@pytest.<span style="color: black;">fixture</span>
<span style="color: #ff7700;font-weight:bold;">def</span> exemple_html<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #dc143c;">urllib2</span>.<span style="color: black;">urlopen</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://www.google.com'</span><span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> test_extraire_title<span style="color: black;">&#40;</span>exemple_html<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">assert</span> extraire_title<span style="color: black;">&#40;</span>exemple_html<span style="color: black;">&#41;</span> == <span style="color: #483d8b;">'Google'</span></pre></div></div>

<p>Qu&#8217;est-ce qui va se passer ?</p>
<p><code>exemple_html()</code> va être déclarée comme une &#8220;fixture&#8221;, c&#8217;est à dire quelque chose qui contient ou génère des données de tests.</p>
<p>Quand Pytest va lancer les tests, il va voir qu&#8217;un argument de <code>test_extraire_title()</code> porte le même nom que la fonction <code>exemple_html</code>. Alors, il va automatiquement appeler <code>exemple_html()</code>, et passer le résultat à <code>test_extraire_title()</code> pour lancer le test.</p>
<p>On peut donc avoir des tas de fonctions de setup, partagées entre plein de fonctons de tests.</p>


feed_id: http://sametmax.com/?p=2913
title: Les ordinateurs et consoles qui ont bercé notre jeunesse. Retour sur toute une époque.
uri: Les-ordinateurs-et-consoles-qui-ont-bercés-notre-jeunesse-Retour-sur
url:
http://sametmax.com/les-ordinnateurs-et-consoles-qui-ont-berces-notre-jeunesse-retour-sur-toute-une-epoque/

content:
<p>Bon c&#8217;est pas le premier article du genre sur le wouebe, c&#8217;est du réchauffé même, mais chaque site d&#8217;info qui se respecte doit avoir son petit côté nostalgie.<br />
Je vais vous parler de ces ordis qui ont bercé ma (et sûrement la vôtre) <a href="http://www.youtube.com/watch?v=Oj-3hk2L7MQ">jeunesse</a> et qui m&#8217;ont donné goût à l&#8217;info. Comme je les ai presque tous eu il va y avoir une bonne liste.</p>
<p><strong>Une des première console de jeux: Atari 2600</strong></p>
<div id="attachment_2915" class="wp-caption aligncenter" style="width: 392px"><a href="http://sametmax.com/wp-content/uploads/2012/11/atari2600.jpeg"?9d7bd4"><img class="size-full wp-image-2915" title="haaaaaa que de souvenirs sur l'Atari 2600..." src="http://sametmax.com/wp-content/uploads/2012/11/atari2600.jpeg"?9d7bd4" alt="" width="382" height="293" /></a><p class="wp-caption-text">ATARI 2600... des milliers d&#39;heures passées dessus...</p></div>
<p style="text-align: left;"><a href="http://sametmax.com/wp-content/uploads/2012/11/jungle-hunt-atari-2600.jpeg"?9d7bd4"><img class="alignright  wp-image-2917" title="jungle hunt, surtout éviter les crocos !" src="http://sametmax.com/wp-content/uploads/2012/11/jungle-hunt-atari-2600.jpeg"?9d7bd4" alt="" width="150" height="200" /></a>Oui bon ça date mais je suis pas tout jeune, j&#8217;en ai eu même avant celà mais comme l&#8217;electricité n&#8217;existait pas encore je n&#8217;ose pas en parler&#8230; A mes yeux l&#8217;Atari 2600 reste la meilleure console, je ne parle pas de graphisme mais de poilade,  j&#8217;étais très jeune aussi, j&#8217;ai essayé de rejouer à certains jeux ça a pris un coup de vieux. Mais ce qui faisait la magie de cette console c&#8217;est qu&#8217;à l&#8217;époque ça parraissait être un ovni, je vous rappelle qu&#8217;on est à la fin des années 70,  pattes d&#8217;eph et disco à la télé, pas encore de montre à quartz, le concept des manettes etc tout ça n&#8217;avait jamais été vu avant (ou presque).</p>
<p style="text-align: left;">En plus j&#8217;étais le seul à savoir la faire marcher, ben oui mes parents savaient pas comment la brancher, ils sont d&#8217;une autre époque. ça faisait de moi le &#8220;<a href="http://www.youtube.com/watch?v=9Fb-Mh68SX4">ptit génie de la maison</a>&#8220;.<br />
Quelques titres dont je me rappelle encore comme &#8220;jungle hunt, moon patrol, dig dug, Qberts, toutankamon&#8230;&#8221;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong>Le MO5, une machine bien de chez nous, Française, blanche&#8230;</strong></p>
<div id="attachment_2919" class="wp-caption aligncenter" style="width: 410px"><a href="http://sametmax.com/wp-content/uploads/2012/11/thomson_mo5_1b.jpeg"?9d7bd4"><img class=" wp-image-2919" title="Thomson mo5" src="http://sametmax.com/wp-content/uploads/2012/11/thomson_mo5_1b.jpeg"?9d7bd4" alt="" width="400" height="283" /></a><p class="wp-caption-text">Cocorico !</p></div>
<p><a href="http://sametmax.com/wp-content/uploads/2012/11/aigle2.png"?9d7bd4"><img class="alignright  wp-image-2920" title="L'aigle d'or" src="http://sametmax.com/wp-content/uploads/2012/11/aigle2.png"?9d7bd4" alt="" width="202" height="130" /></a>Je m&#8217;en rappelle encore, c&#8217;était un soir de 1984, mon père m&#8217;emmene à RALLY ( une sorte de Carrefour) et il m&#8217;achète cet ordi au design sobre et beau (d&#8217;ailleur je trouve que le MacBook Air lui ressemble beaucoup au niveau des touches) . C&#8217;est là dessus que j&#8217;ai fais mes premiers programme en BASIC, j&#8217;aimais bien, c&#8217;était simple, je faisais des trucs de merde, c&#8217;était des images avec une musique en fond, mais je trouvais ça fantastique.<br />
Là encore des jeux m&#8217;on scotché comme Airbus, l&#8217;Aigle d&#8217;Or , le 5ème Axe. Des graphismes d&#8217;une horreur époustouflante mais des heures passés dessus, surtout l&#8217;aigle d&#8217;Or que je n&#8217;ai jamais fini je crois.</p>
<p>&nbsp;</p>
<p><strong>L&#8217;Amstrad CPC 6128<br />
</strong></p>
<div id="attachment_2922" class="wp-caption aligncenter" style="width: 410px"><a href="http://sametmax.com/wp-content/uploads/2012/11/amstrad.jpeg"?9d7bd4"><img class=" wp-image-2922 " title="Amstrad cpc 6128" src="http://sametmax.com/wp-content/uploads/2012/11/amstrad.jpeg"?9d7bd4" alt="" width="400" height="286" /></a><p class="wp-caption-text">Le croisement entre concole et ordi</p></div>
<p><a href="http://sametmax.com/wp-content/uploads/2012/11/Barbarian_demo1.png"?9d7bd4"><img class="alignright  wp-image-2923" title="Barbarian, c'est pas un jeu de PD ça !" src="http://sametmax.com/wp-content/uploads/2012/11/Barbarian_demo1.png"?9d7bd4" alt="" width="227" height="160" /></a>Très vite le MO5 (et TO7) a laissé la place à l&#8217;Amstrad, des graphismes plus mieux, une bonne bibliothèque de jeux et surtout un coup marketing à l&#8217;époque fantastique, le grille-pain était vendu AVEC un écran. Ca peut avoir l&#8217;air con mais de cette sorte les parents ne voyaient plus leur télé monopolisée par le boutonneux de service, je suis persuadé que ça a énormément joué à l&#8217;époque.<br />
Il a aussi à mon avis participé à l&#8217;introduction de la micro dans les foyers, en mélangeant console de jeux et ordinateur. Je n&#8217;ai pas beaucoup &#8220;développer&#8221; là dessus car les jeux étaient tellement bons que je faisais plus que ça&#8230; On se rappellera de Stram II, Barbarian (j&#8217;adorais trancher la tête&#8230;), green Beret, Commando, Zaxon, Turok, etc&#8230;</p>
<p>&nbsp;</p>
<p><strong>La Nes<br />
</strong></p>
<div id="attachment_2926" class="wp-caption aligncenter" style="width: 411px"><a href="http://sametmax.com/wp-content/uploads/2012/11/nintendo-entertainment-system.jpeg"?9d7bd4"><img class=" wp-image-2926 " title="NES - la console ultime" src="http://sametmax.com/wp-content/uploads/2012/11/nintendo-entertainment-system.jpeg"?9d7bd4" alt="" width="401" height="291" /></a><p class="wp-caption-text">Mario Bros - y a pas mieux</p></div>
<p><a href="http://sametmax.com/wp-content/uploads/2012/11/mike-tyson-punch-out.jpeg"?9d7bd4"><img class="alignright  wp-image-2927" title="Mike tyson , fallait éviter ses upercuts" src="http://sametmax.com/wp-content/uploads/2012/11/mike-tyson-punch-out.jpeg"?9d7bd4" alt="" width="240" height="209" /></a>Alors là il fallait le voir pour le croire,  une petite boite toute carrée mais des super graphismes (pour l&#8217;époque), je me rappelle encore de la démo de Mario Bros, on avait économisé avec mon frère pour se la payer, elle coutait 990 Francs , c&#8217;était pas cher comparé aux ordis de l&#8217;époque mais là où Nintendo a bien joué c&#8217;est qu&#8217;il vendait les jeux dans les 300 / 400 Francs, ça faisait mal au cul&#8230;<br />
Cette console est pour moi le symbole de la jouabilité, je n&#8217;ai depuis jamais retrouvé cette jouabilité sur des jeux, sa conccurente de l&#8217;époque, la Master system de Sega était une vrai daube en terme de maniabilité, il y avait bien sur les pros et les contres comme Xbox et Sony de nos jours :).<br />
La Nes a également introduit le concept de sauvegarde, je me rappelle qu&#8217;il y avait une <a href="http://www.youtube.com/watch?v=XkIiteODsW8">pile dans les cartouches</a> de Zelda. On pouvait sauvegarder notre partie, aller se coucher et le lendemain, ho miracle on peut reprendre là où on avait fini&#8230;<br />
Quelques jeux mémorables mais la liste est longue Les goonies, Metroid, Zelda, Mario Bros, Gradius, Punch Out, etc.</p>
<p>&nbsp;</p>
<p><strong>ATARI ST 520 STE<br />
</strong></p>
<div id="attachment_2924" class="wp-caption aligncenter" style="width: 394px"><a href="http://sametmax.com/wp-content/uploads/2012/11/ATARI520STE.jpeg"?9d7bd4"><img class=" wp-image-2924 " title="Atari 520 ste" src="http://sametmax.com/wp-content/uploads/2012/11/ATARI520STE.jpeg"?9d7bd4" alt="" width="384" height="280" /></a><p class="wp-caption-text">C&#39;est parti pour un Dungeon Master!</p></div>
<p><a href="http://sametmax.com/wp-content/uploads/2012/11/dugeon-master.png"?9d7bd4"><img class="alignright  wp-image-2925" title="Dungeon master" src="http://sametmax.com/wp-content/uploads/2012/11/dugeon-master.png"?9d7bd4" alt="" width="224" height="140" /></a>Il y a eu le 520 Stf, Ste, Le 1040, etc&#8230; L&#8217;atari ST a vraiment marqué un tournant je trouve, grace au&#8230;piratage :) En effet on arrivait à l&#8217;école avec nos paquets de disquettes ultra fines (maintenant ça ferait rire) qu&#8217;on s&#8217;echangeait, c&#8217;était on ne peu plus simple de copier les jeux à l&#8217;époque grace à un logiciel (en allemand d&#8217;ailleurs) qui demandait d&#8217;insérer la disquette source puis la disquette destination et c&#8217;est tout !<br />
C&#8217;était une bête de course dans tous les domaines, graphismes et audio, il sera d&#8217;ailleurs beaucoup utilisé en <a href="http://www.olivier-g.com/musique/initiation-mao/equipement-home-studio.php">MAO</a> , Cubase lui doit beaucoup car c&#8217;était un des logiciels de musique les plus piraté sur Atari St, certaines légendes racontes que Cubase lui-même avait fait en sorte que le logiciel soit facilement piraté pour pouvoir diffuser sont utilisation en masse&#8230; Il avait cependant un ennemi féroce l&#8217;Amiga qui était beaucoup plus puissant (et plus chèr aussi) où d&#8217;ailleurs j&#8217;ai vu de très belles <a href="http://www.youtube.com/watch?v=fPSst20JEcE">démos</a> .<br />
On se rappellera des jeux comme Rick dangerous, Stunt car Racer, Maupiti Island, Opération Steal, Dungeon Master, etc..</p>
<p><strong>La super Nes<br />
</strong></p>
<div id="attachment_2929" class="wp-caption aligncenter" style="width: 394px"><a href="http://sametmax.com/wp-content/uploads/2012/11/Super_Famicom_JPN.jpeg"?9d7bd4"><img class=" wp-image-2929 " title="Super Nintendo" src="http://sametmax.com/wp-content/uploads/2012/11/Super_Famicom_JPN.jpeg"?9d7bd4" alt="" width="384" height="307" /></a><p class="wp-caption-text">Are you ken ?</p></div>
<p><a href="http://sametmax.com/wp-content/uploads/2012/11/street_fighter_ii_snes_hadoken.jpeg"?9d7bd4"><img class="alignright  wp-image-2930" title="Street Fighter II" src="http://sametmax.com/wp-content/uploads/2012/11/street_fighter_ii_snes_hadoken.jpeg"?9d7bd4" alt="" width="253" height="190" /></a>Très attendue a l&#8217;époque, c&#8217;était la première fois où l&#8217;on voyait le phénomène d&#8217;attente pour la sortie d&#8217;un produit, au JT passait des images de Japonnais attendant devant le magasin pour être servis les premiers, maintenant ce genre de folie s&#8217;est étendu à la terre entière et pour n&#8217;importe qu&#8217;elle saloperie un peu high tek. La super Nes a rajouté un peu de jeune dans les consoles avec l&#8217;arrivé de la 3D (donkey kong )  et les effets sonores (reverb, etc). J&#8217;ai passé pas mal de temps sur cette console mais la magie des jeux commencait déjà à me quitter, c&#8217;est une des dernières consoles auquelle j&#8217;ai passé beaucoup de temps.<br />
La liste des jeux est là encore impressionante, j&#8217;ai surtout aimé la série des Marios ainsi que Street fighter.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong>La MegaDrive de Sega:</strong></p>
<div id="attachment_3000" class="wp-caption aligncenter" style="width: 370px"><a href="http://sametmax.com/wp-content/uploads/2012/11/megadrive.jpeg"?9d7bd4"><img class=" wp-image-3000 " title="SEGA Megadrive" src="http://sametmax.com/wp-content/uploads/2012/11/megadrive.jpeg"?9d7bd4" alt="" width="360" height="301" /></a><p class="wp-caption-text">Des graphismes superbes et une maniabilité de me...</p></div>
<p><a href="http://sametmax.com/wp-content/uploads/2012/11/ecco_the_dolphin_182378.jpeg"?9d7bd4"><img class="alignright  wp-image-3001" title="Ecco the dolphin 1992" src="http://sametmax.com/wp-content/uploads/2012/11/ecco_the_dolphin_182378.jpeg"?9d7bd4" alt="" width="244" height="183" /></a>Annoncée comme le messie avec ses 16 Bits la Megadrive était la conccurente de la SNES, la jouabilité était vraiment minable je trouve mais les graphismes bien mieux que la SNES, je trouve que ça a toujours été le problème de SEGA de faire des jeux beaux mais dont la maniabilité était médiocre, les personnages avaient un baton dans le cul&#8230;<br />
Il y a eu de très très bons jeux dessus comme Altered Beast, Sonic the EdgeHog, E-Swat, Shinobi, Golden Axe, Afterburner, etc. Cette console avait un peu de magie car on y retrouvait les jeux d&#8217;arcade qui étant de SEGA se trouvaient portés sur cette console, du coup on se croyait comme dans les salles de jeux, j&#8217;avais même pensé à me construire une borne d&#8217;arcade à lépoque pour l&#8217;occasion.<br />
J&#8217;ai une pensée particulière pou Ecco the dolphin qui bien qu&#8217;étant pas vraiment interressant était d&#8217;un graphisme époustouflant et avait une musique appaisante, On pouvait y jouer des heures juste à déplacer son dauphin&#8230;<br />
Dans un aéroport il y a un an ou deux j&#8217;ai trouvé une <a href="Sega Mega Drive Portable Video Game Player ">console portable reprennant les plus grands titres de la Mégadrive</a>, j&#8217;ai passé des heures aux chiottes avec !</p>
<p>&nbsp;</p>
<p><strong>Le Personal Computer<br />
</strong></p>
<div id="attachment_2931" class="wp-caption aligncenter" style="width: 397px"><a href="http://sametmax.com/wp-content/uploads/2012/11/ibm.jpeg"?9d7bd4"><img class=" wp-image-2931  " title="Personal Computer" src="http://sametmax.com/wp-content/uploads/2012/11/ibm.jpeg"?9d7bd4" alt="" width="387" height="257" /></a><p class="wp-caption-text">Un IBM des années 90 8 Mhz !</p></div>
<p><strong></strong><a href="http://sametmax.com/wp-content/uploads/2012/11/sammax2.jpeg"?9d7bd4"><img class="alignright  wp-image-2932" title="Sam &amp; Max 2" src="http://sametmax.com/wp-content/uploads/2012/11/sammax2.jpeg"?9d7bd4" alt="" width="233" height="146" /></a>Les années 90 ont marquées un tournant pour l&#8217;informatique, les PC se sont imposés en masse, je n&#8217;en voit pas trop la raison en fait, ils étaient gros, lourds, moches, pas puissants, chers (4000 Francs la barette de 1 mo de mémoire, 1200 francs le lecteur CD, etc.) . Et essayez de déconnecter votre ordi d&#8217;internet et vous allez voir si vous faites encore quelque chose avec votre grille-pain&#8230;<br />
Possible que ce soit le côté bidouille mais chez moi personne à part moi voulait y toucher. Mon premier PC était un 386 Sx 16 Mhz avec un disque dur de 20 Mo et un lecteur de disquette de 5&#8243;, même la plus petite des calculettes de nos jours lui met la misère.<br />
Et puis petit à petit la puissance a commencée à arrivée nottement avec les célèbres 486 DX 2 66 et on a commencé à voir arriver des jeux comme Duke nukem, Day of tentacules, Sam et Max ;) mais aussi des superbes démos comme <a href="http://www.youtube.com/watch?v=8G_aUxbbqWU">Second Reality</a>, regardez moi tous <a href="http://www.youtube.com/watch?v=LIIBRr31DIU&amp;feature=related">ces geeks</a> :)</p>
<p>&nbsp;</p>
<p><strong>La Playstation<br />
</strong></p>
<div id="attachment_2933" class="wp-caption aligncenter" style="width: 399px"><a href="http://sametmax.com/wp-content/uploads/2012/11/psone.jpeg"?9d7bd4"><img class=" wp-image-2933 " title="Playstation" src="http://sametmax.com/wp-content/uploads/2012/11/psone.jpeg"?9d7bd4" alt="" width="389" height="259" /></a><p class="wp-caption-text">Le début de la fin, chargements inter Minables...</p></div>
<p><a href="http://sametmax.com/wp-content/uploads/2012/11/jaquette-crash-bandicoot-playstation-3-ps3-cover-avant-g.jpeg"?9d7bd4"><img class="alignright  wp-image-2934" title="Crash bandicoot" src="http://sametmax.com/wp-content/uploads/2012/11/jaquette-crash-bandicoot-playstation-3-ps3-cover-avant-g.jpeg"?9d7bd4" alt="" width="240" height="207" /></a>La playstation a été pour moi le début de la fin. Quelle erreur avait fait Sony là, un lecteur CD !!!! Alors certes on avait des supers intro animés mais bordel une heure de chargement entre chaque étapes, malgrès le fait qu&#8217;il y avait de très bon jeux dessus cette console m&#8217;a dégoûté des&#8230;consoles , je me suis donc tourné vers les PC pour laisser petit à petit les jeux de côté. D&#8217;autant qu&#8217;internet venait d&#8217;arriver timidement en France avec Compuserve et ses notes de téléphones à 2000 Francs :)<br />
Petite anecdote à l&#8217;époque je faisais des puces pour pouvoir jouer aux jeux copiés sur la console, ça a du faire sa rennomée ça aussi, quand les graveurs de CD sont arrivés il était facile de copier les jeux lorsqu&#8217;on avait une puce d&#8217;installé, je m&#8217;étais alors improvisé monteur de puces sur console, un bon business à l&#8217;époque, je vendais les puces et mon pote les jeux copiés qu&#8217;il louait au vidéo-club, je programmais des PIC 1504 et les soudaient à même la console, ça payait les sorties&#8230;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>Voilà, j&#8217;espère que ça aura reveillé quelques souvenirs à certains d&#8217;entre vous. Je ne parle pas de l&#8217;excellente Nintendo 64 qui pour certains est la meilleure console de tous les temps avec son golden eye car je ne l&#8217;ai pas eu, j&#8217;avais déjà lâché les consoles à cette époque. Il y a également la Megadrive, la Dreamcast, etc.. J&#8217;ai zappé également les consoles portables comme la Gameboy ou la GBA.</p>
<p>Les derniers consoles depuis la PS2 (déjà 10 ans) ne valent pas grand chose à mes yeux, ce ne sont que des monstres de puissance avec des jeux fades, j&#8217;ai acheté une xbox 360 et une PS3 que j&#8217;ai gardé respectivement 1 semaine et 2 mois,  les jeux bien que superbes n&#8217;ont pas d&#8217;âmes, sont pas maniables (sérieusement un COD c&#8217;est nul à jouer à la manette !). Depuis un seul jeu m&#8217;a amusé et c&#8217;est sur PC , c&#8217;était Battlefield  2142, possible qu&#8217;un jour je m&#8217;y remette mais je pense que la flamme du joueur qui est en moi s&#8217;est étteinte&#8230;</p>
<p>A vous Cognac Jay.</p>
<p>Edit: je n&#8217;ai pu m&#8217;empêché de rajouter la MegaDrive car je pense qu&#8217;elle a droit à sa place dans la postérité :)</p>


feed_id: http://sametmax.com/?p=2904
title: Bien expliquer quelque chose: les règles de base
uri: Bien-expliquer-quelque-chose-les-règles-de-base
url: http://sametmax.com/bien-expliquer-quelque-chose-les-regles-de-base/
content:
<p>Il n&#8217;y a pas beaucoup de choses dans lesquelles je me considère vraiment très bon. Je ne suis pas un génie. Je ne suis même pas un excellent programmeur. Mais enseigner, expliquer quelque chose à quelqu&#8217;un est définitivement un de mes points forts. La bonne nouvelle, c&#8217;est qu&#8217;il existe quelques règles simples, qui, si vous les suivez, vous permettront vous aussi de développer vos capacités à faire passer des connaissances.</p>
<p>(par contre je vous préviens, c&#8217;est un méchant bloc, prévoyez la lecture à la pause de midi :-p)</p>
<h2>1 &#8211; Il n&#8217;y a rien d&#8217;évident</h2>
<p>Quand on est bon dans quelque chose, on a tendance à considérer certaines connaissances comme la base. Tout le monde doit savoir ça. Il n&#8217;est pas rare dans notre profession, très intellectuelle, de voir même certains afficher du mépris envers ceux qui montrent leur ignorance dans ces domaines (salut cortex :-)).</p>
<p>La règle numéro 1, la seule à retenir si vous ne voulez pas lire le reste: <strong>il n&#8217;existe AUCUNE connaissance que tout le monde possède</strong>.</p>
<p>Anecdote amusante: même si il existait une chose que tout le monde savait une fois atteint l&#8217;âge adulte (ce qui n&#8217;est pas le cas), par le simple truchement des statistiques, il y aurait <a href="http://xkcd.com/1053/">10000 personnes par jour aux USA qui découvriraient</a> ce fait. Donc qui l&#8217;ignoraient hier.</p>
<p>Le corollaire, c&#8217;est que donc<strong> la valeur d&#8217;une personne ne peut pas être jugée en fonction de ce qu&#8217;elle sait, ou ce qu&#8217;elle ne sait pas</strong>. Max a appris ce qu&#8217;était la signature d&#8217;une fonction le mois dernier. Il a 15 ans de métier.</p>
<p>Par respect donc, et par souci d&#8217;efficacité, il va falloir faire une liste des prérequis nécessaires à la compréhension de ce que vous essayez d&#8217;expliquer. Et il va falloir se demander: puis-je glisser une explication simple pour ces prérequis ? Puis-je glisser un rappel ? Au moins faire un lien vers une autre ressource qui fait ce rappel ? Quel en sera le prix (taille de l&#8217;article, temps de la conférence, complexité, énergie dépensée, etc) ? Si le prix est raisonnable, précisez cette notion, et votre article / cours / présentation touchera soudainement plus de monde.</p>
<p>L&#8217;exemple de la réussite de cette pratique est <a href="http://sametmax.com/comprendre-les-decorateurs-python-pas-a-pas-partie-1/">l&#8217;article sur les décorateurs Python</a>. Il n&#8217;existe aucun autre bon article français sur Internet expliquant les décorateurs, parce que la plupart partent du principe que vous savez ce qu&#8217;implique qu&#8217;une fonction est un objet en Python. Ici, la moitié de l&#8217;article s&#8217;acharne à expliquer cette notion. L&#8217;autre moitié à expliquer ce qu&#8217;on peut faire avec les décorateurs. Seule une toute petite partie de l&#8217;article est vraiment une explication sur les décorateurs. La notion clé n&#8217;est pas forcément ce qui prend le plus de temps à expliquer: les choses sont simples quand on connaît le contexte.</p>
<p>L&#8217;exemple de l&#8217;échec de cette pratique, c&#8217;est l&#8217;article sur <a href="http://sametmax.com/les-vues-sur-des-collections-en-python/">les vues en Python</a>. Je suis parti du principe que les lecteurs savaient ce qu&#8217;était une structure de données et un proxy, des notions qui à mes yeux étaient des notions de base. J&#8217;ai été heureusement rapidement rappelé à l&#8217;ordre par deux lecteurs sympathiques. Si ils ne l&#8217;avaient pas fait, je serais resté dans l&#8217;illusion que mon article était bon. Car c&#8217;est tout le problème avec une mauvaise explication: personne n&#8217;a envie d&#8217;admettre que l&#8217;on n&#8217;a pas compris quelque chose. Et on crée un sentiment de rejet envers le sujet et l&#8217;auteur.</p>
<p>Il y a un fort attachement émotionnel qui se créé pour le lecteur si on fait bien son travail: il reçoit votre message, et dedans il se rend compte qu&#8217;il comprend, et voit l&#8217;effort que vous avez fait pour qu&#8217;il comprenne, alors que d&#8217;autres sources ne l&#8217;ont pas fait. Il se créé un sentiment de satisfaction pour lui d&#8217;avoir compris, et de reconnaissance pour vous de lui avoir expliqué.</p>
<p>C&#8217;est exactement ce qui s&#8217;est passé avec le <a href="http://www.siteduzero.com/">site du zéro</a>. Le mec était tellement bon que quand il a eu besoin d&#8217;un nouveau serveur (au tout début du site), il a lancé une collecte et reçu 2000 euros des lecteurs heureux. Sa boîte, Simple IT, est construite sur le lien émotionnel qu&#8217;il a créé avec ses lecteurs en ne les prenant pas pour des cons. Inutile de préciser que j&#8217;adore ce mec.</p>
<h2>2 &#8211; Limitez le bruit</h2>
<p>Quand vous parlez d&#8217;un sujet, <a href="http://sametmax.com/se-simplifier-les-tests-python-avec-pytest/#comment-2918">limitez au maximum toute notion dont vous n&#8217;avez pas besoin dans le sujet</a>. Si vous faites un article sur comment débuter dans le domaine x, ne mettez JAMAIS les bonnes pratiques du domaine x.</p>
<p>Trop de profs expliquent (ce qu&#8217;ils croient être)  les bonnes pratiques à des gens qui ne connaissent pas la base. On dépense déjà beaucoup d&#8217;énergie à comprendre la base. Il y a zéro chance qu&#8217;on comprenne en plus les bonnes pratiques, et leurs implications. Et même si on y arrive, le jour où on à vraiment besoin d&#8217;appliquer ces bonnes pratiques est très loin, et on aura oublié tout cela (l&#8217;exception à cet exemple étant la formation / présentation professionnelle sur quelques jours).</p>
<p>Si les bonnes pratiques sont essentielles à votre cours, comme par exemple un cours sur le xHTML qui doit être valide, donnez uniquement des exemples valides. Introduisez les règles de validité <strong>sans emphase par rapport au reste</strong>. Mais ne martelez pas la philosophie de la raison de rendre le code valide. C&#8217;est un autre sujet. Traitez le ailleurs. Les gens sont ici pour apprendre à faire du code valide, pas pour entendre un sermon. Laissez les produire du code non valide. C&#8217;est une erreur comme les autres. Ça se corrige avec la pratique, comme toutes les autres erreurs.</p>
<p>Un autre exemple: évitez d&#8217;introduire une notion connexe. Si vous parlez d&#8217;une algo de parcours, éviter de parler en détail de complexité algorithmique. Juste savoir qu&#8217;il est efficace pour tel usage ou non suffit. A moins d&#8217;être dans un cours d&#8217;algo, bien sûr. Si vous parlez d&#8217;<a href="http://sametmax.com/creer-un-site-avec-bottle-en-5-minutes-parceque-7-cest-impossible-voyons/">une nouvelle lib Python</a>, ce n&#8217;est pas le moment de parler de <a href="http://sametmax.com/votre-python-aime-les-pip/">comment installer une lib avec pip</a>. Tous les gens qui savent déjà ça vont être gavés. Les autres vont être perdus. Installer une lib avec pip, c&#8217;est un exercice à part. Je hais de tout mon être les livres sur Django qui commencent par expliquer des notions de Python: le résultat, c&#8217;est qu&#8217;aucun des deux sujets n&#8217;est bien traité.</p>
<p>Montrez une seule manière de faire les choses, et de préférence la plus simple à moins qu&#8217;elle soit vraiment nulle ou que le titre de votre article soit &#8220;x façons de faire z&#8221;.</p>
<p>En Python, on peut par exemple faire:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span>truc, key=<span style="color: #dc143c;">operator</span>.<span style="color: black;">itemgetter</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>ou</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span>truc, key=<span style="color: #ff7700;font-weight:bold;">lambda</span> x: x<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Lequel des deux utiliser n&#8217;est pas important pour votre sujet en cours. Choisissez-en un, ne mentionnez même pas l&#8217;existence de l&#8217;autre. On s&#8217;en branle.</p>
<p>Si un petit malin vient faire une réflexion en comment, mettez lui un tampon dans la tronche.</p>
<p>J&#8217;ai toujours fait ça par instinct, sachant que c&#8217;était plus efficace, mais sans vraiment savoir pourquoi. Jusqu&#8217;à ce que je sorte avec une neuropsy qui m&#8217;a un jour expliqué le principe des tests dans son métier: toute la difficulté est de créer un exercice qui teste une aptitude mentale, et n&#8217;implique aucune autre. Par exemple si on veut tester la mémoire, le jeu du <a href="http://fr.wikipedia.org/wiki/Memory_%28jeu%29">memory</a> est un mauvais test car il demande aussi une capacité d&#8217;observation. Vous pourriez diagnostiquer une personne comme ayant Alzheimer alors qu&#8217;elle est juste pas observatrice.</p>
<p>C&#8217;est pareil en pédagogie: une personne risque de ne pas comprendre un sujet car vous avez introduit une notion supplémentaire, donc un risque supplémentaire d&#8217;incompréhension. Le problème avec l&#8217;incompréhension, c&#8217;est que ça s&#8217;accumule: si on ne pige pas le premier paragraphe, le cerveau est confus, et aura plus de mal à comprendre le second paragraphe qu&#8217;il aurait compris tout de suite si il n&#8217;avait pas lu le premier. Et je vous passe bien sûr les conséquences de la frustration de l&#8217;échec dans un monde où Youtube est à un clic de votre article tout pourri.</p>
<p>Cette règle est très difficile à appliquer car elle contredit deux autres règles:</p>
<ul>
<li>La règle numéro 1. Quand vous avez besoin d&#8217;expliquer un prérequis, il faut rajouter du bruit. Néanmoins, il faudra toujours choisir de sacrifier une part du public pour respecter la règle 2. Par exemple, si vous faites un article sur une notion de Python avancée, vous pouvez sacrifier les grands débutants.</li>
<li>La règle numéro 3. Quand vous voulez intéresser le lecteur, il faut dériver un peu.</li>
</ul>
<p>C&#8217;est une question de dosage, et ça vient avec l&#8217;expérience. Mais il faut toujours travailler à améliorer ce dosage.</p>
<h2>3 &#8211; Rendez ça fun</h2>
<p>Notre capacité de concentration est limitée. Pour maintenir l’intérêt, introduisez des détails qui font marcher une autre partie du cerveau: un truc qui choque, qui fait réfléchir, ou rire.</p>
<p>Il faut faire ça de la manière la moins intrusive possible pour ne pas dégommer instantanément la règle 2. Si vous faites un trait d&#8217;humour, faites le court. Mieux encore, gardez tout l&#8217;article sérieux, mais mettez la blague dans le nom d&#8217;une variable du code d&#8217;exemple, dans un lien sortant de l&#8217;article, dans une référence cinématographique sans vous attarder, dans une photo d&#8217;illustration, dans un title qu&#8217;on lit au survol, dans le ton général de l&#8217;article.</p>
<p>Ce n&#8217;est pas grave si tout le monde ne comprend pas. Nous n&#8217;avons pas tous le même humour. L&#8217;idée est de ne pas déconcentrer l&#8217;audience, mais que ceux qui tiltent aient un sourire au coin de la bouche.</p>
<p>Si vous commencez vraiment à vous toucher, vous pouvez utiliser des citations, des blagues complètes, des petites histoires et autres moyens plus imposants. Mais c&#8217;est advanced. Garder un rythme avec ça, c&#8217;est plus difficile.</p>
<p>Dans tous les cas n&#8217;en abusez pas. Voir règle 2.</p>
<h2>4 &#8211; D&#8217;où on vient, où on va</h2>
<p>L&#8217;être humain est biologiquement câblé pour détester l&#8217;inconnu. Et quand il n&#8217;aime pas, il fuit. Sur Internet ça se traduit par la fermeture de l&#8217;onglet, dans une conf par la consultation de Facebook sur son mobile, etc.</p>
<p>En gros, quand vous commencez un article, votre accroche doit toujours indiquer de quoi on va parler et pourquoi. Avec si possible une forme qui donne envie de lire la suite.</p>
<p>Rapidement, il va falloir aussi respecter la règle 1, sinon les gens vont se demander ce qu&#8217;ils foutent là. Si vous ne respectez pas la règle 1 dans le but de respecter la règle 2 ou parce que vous n&#8217;avez pas les ressources pour le faire (vous écrivez un article de blog, pas un livre&#8230;), alors glissez une explication de ce que l&#8217;on a besoin de savoir pour comprendre la notion. Comme ça les gens savent pourquoi ils ne comprennent pas, et peuvent choisir de se documenter au lieu de juste se barrer. Ils peuvent aussi se dire &#8220;ok, je comprends pas ça, mais ça ne m&#8217;empêche pas de retenir, comme ça quand je saurai l&#8217;autre truc plus tard, tout ça deviendra utile&#8221;.</p>
<p>Et annoncez la couleur: si c&#8217;est un article que vous avez fait long et pompeux, ben dites le. Au moins ils sont prévenus. Si vous allez taper un coup de gueule, introduisez avec le bon ton. Les personnes qui ne sont pas d&#8217;humeur sauront que l&#8217;article n&#8217;est pas pour elles, du moins pas aujourd&#8217;hui.</p>
<p>Enfin, de manière générale, respectez l&#8217;adage de notre bon Pikachu. Heu, Picasso, pardon:</p>
<blockquote><p>Pour apprendre quelque chose aux gens il faut mélanger ce qu’ils connaissent avec ce qu’ils ignorent</p></blockquote>
<p>Ne communiquez pas en zorglang, partez d&#8217;une base commune. On se sent en sécurité, et on peut commencer à chercher à comprendre le reste.</p>
<h2>5 &#8211; Une bon dessin vaut mieux&#8230;</h2>
<p>Des <a href="http://sametmax.com/schema-de-fonctionnement-general-de-django/">schémas</a> et des <a href="http://sametmax.com/python-love-les-listes-en-intention-partie/">exemples</a>. C&#8217;est votre priorité.</p>
<p>Les schémas servent à avoir une vision globale: utilisez les partout où vous avez des relations complexes à expliquer telles que des imbrications, des flux non linéaires (car pour les flux linéaires une liste suffit), des dépendances sous forme de graphe, etc.</p>
<p>Mettez des exemples de mises en œuvre et d&#8217;usages. La mise en œuvre permet de savoir comment ça marche. L&#8217;usage permet de savoir à quoi ça sert. Les deux sont importants à la compréhension. Dans notre métier, les exemples sont généralement du code. La mise en œuvre, c&#8217;est le code qui montre &#8220;comment écrire un décorateur&#8221;, l&#8217;usage c&#8217;est le code qui montre &#8220;pour quoi utiliser un décorateur&#8221;.</p>
<p>Et si vous écrivez beaucoup de texte: une liste vaut mieux qu&#8217;un paragraphe. Deux parties titrées valent mieux qu&#8217;une grosse partie. Deux petits paragraphes valent mieux qu&#8217;un gros. Divisez. Mettez du gras sur les notions clés. Faites des phrases courtes. Rendez la lecture en diagonale facile.</p>
<p><strong>Les gens ne vont JAMAIS lire votre article de bas en haut</strong>. Il vont cherchez les images et schémas et sauter sur eux. Si il n&#8217;y en a pas, ou si ils s’aperçoivent qu&#8217;ils ne comprennent pas uniquement avec le schéma (et en supposant qu&#8217;ils aient encore la patience pour lire la suite), ils vont scanner rapidement la page pour cherche des exemples. Pour nous des bouts de code. Si il n&#8217;y en a pas, ou si les exemples ne suffisent pas pour comprendre la notion (vous avez déjà perdu la moitié de votre auditoire ici, dans une conf, tout le monde check ses mails à ce stade), ils iront lire le texte.</p>
<p>Même ceux qui croient lire de haut en bas ne le font pas. Inconsciemment, nos yeux scannent les pages, et notre cerveau évalue le coût de la lecture, avec un ratio &#8220;intérêt pour le sujet&#8221; / &#8220;effort demandé&#8221;. On a de la chance, en info, généralement le dividende est plus conséquent que dans d&#8217;autres domaines comme la finance ou les jeux vidéos. C&#8217;est aussi pour cette raison qu&#8217;il faut utiliser des phrases simples, pas alambiquées, dans une mise en page claire, car sinon on augmente ce qu&#8217;on appelle en ergonomie la &#8220;charge cérébrale&#8221;. En gros la consommation CPU de la tête du lecteur. C&#8217;est très sérieux, il y a même des outils pour calculer la <a href="https://en.wikipedia.org/wiki/Gunning_fog_index">lisibilité d&#8217;un texte</a>.</p>
<p>Exemple ironique: <a href="http://www.uvp5.univ-paris5.fr/TFL/Ac/AffFicheT.asp?CleFiche=5011&amp;Org=QUTH">cette page qui parle de complexité de texte</a>, et qui est une corvée à lire.</p>
<p>Cette règle est applicable à tout système qui doit être compris: blague, machine outil et surtout&#8230; UI. Google et Apple respectent ces règles sur leurs sites et téléphones.</p>
<p>La seule exception à la règle 5 est l&#8217;article dit &#8220;d&#8217;essai&#8221;, comme celui que vous êtes en train de lire. Mais sachez que ce genre de texte demande beaucoup de travail, et sera lu par une minorité.</p>
<h2>6 &#8211; Laissez les gens se planter</h2>
<p>C&#8217;est dur. C&#8217;est très dur.</p>
<p>Mais le mécanisme de base de l&#8217;apprentissage c&#8217;est de se vautrer comme une grosse loutre bourrée à la bière. De s&#8217;en apercevoir. Et de recommencer en essayant de ne pas se planter cette fois.</p>
<p>Et de se planter à nouveau. for&#8230; in et try/catch.</p>
<p>Donc, si vous êtes dans un cours, ou avec un collègue en train d&#8217;expliquer un truc, résistez à l&#8217;envie de lui donner la réponse. Résistez à l&#8217;envie de corriger son code tout merdique qu&#8217;il va mettre en prod (l&#8217;enculé !).</p>
<p>Si vous émettez une critique, ce sera une seule. Même si il y a 20 choses à redire. On est limité dans le nombre de critiques qu&#8217;on peut assimiler. Après on se braque.</p>
<p>Et évidement, ça va sans dire, ne soyez pas méprisant dans votre critique. Vous faites de la merde vous aussi. Et elle sent pas la rose.</p>
<p>Mais inutile d&#8217;envelopper ça dans un sandwich de compliments comme on vous l&#8217;apprend en cours de com&#8217;, et surtout, surtout, évitez ces tournures à la con de la soi-disant &#8220;communication non violente&#8221; du genre &#8220;tu penses pas que ce serait mieux si&#8230;&#8221;. Dites clairement et simplement ce que vous pensez. Il y a rien qui crie plus &#8220;je te regarde de haut&#8221; qu&#8217;un mec qui essaye maladroitement de ne pas te blesser. Laissez ça aux gonzesses, elles elles savent le faire correctement, nous on sonne encore plus désagréable et faux-cul.</p>


feed_id: http://sametmax.com/?p=2947
title: id(), None et bidouilleries mémoire en python.
uri: id()-None-et-bidouilleries-mémoire-en-python
url: http://sametmax.com/id-none-et-bidouilleries-memoire-en-python/
content:
<blockquote><p><em>Ceci est un post invité de <a href="http://recher.wordpress.com" target="_blank">Réchèr</a> posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.</em></p></blockquote>
<p>Mon maître-ninja python, entre deux riffs sur sa contrebasse électrique, m&#8217;avait un jour dit : &#8220;il ne faut pas écrire <code>if a == None:</code>, mais <code>if a is None:</code>&#8220;. Il m&#8217;avait ensuite donné une justification pertinente, que je n&#8217;ai pas retenue, car j&#8217;étais en train de penser à des nichons. Puis il avait conclu par &#8220;on n&#8217;est pas égal au vide. On <em>EST</em> le vide.&#8221;</p>
<p>Rien que pour vous, ainsi que pour m&#8217;auto-déculpabiliser de penser souvent à des nichons, j&#8217;ai parcouru l&#8217;internet entier à dos de souris et j&#8217;ai retrouvé la justification. Mais avant de vous la livrer, quelques explications préliminaires.</p>
<h3>On n&#8217;a pas de pétrole, mais on a des id()</h3>
<p><a title="Et quand on n'a pas d'id, on a des fix !" href="http://sametmax.com/wp-content/uploads/2012/11/idfix2.jpg"?9d7bd4"><img class="size-full wp-image-2968" src="http://sametmax.com/wp-content/uploads/2012/11/idfix2.jpg"?9d7bd4" alt="Et quand on n'a pas d'id, on a des fix !" width="124" height="150" /></a></p>
<p>La fonction <code>id()</code>, présente dans <code>__builtins__</code>, renvoie un entier, représentant l&#8217;identifiant interne de n&#8217;importe quel objet, quel que soit son type. Concrètement, il s&#8217;agit de l&#8217;adresse mémoire dans laquelle il est stocké. Jouons un peu avec.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">»» a = <span style="color: #ff4500;">1</span>
»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>a<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">19846928</span>
»» b = <span style="color: #483d8b;">&quot;plop&quot;</span>
»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>b<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">33984800</span>
»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">19846916</span></pre></div></div>

<p>Si vous faites cela chez vous, vous n&#8217;obtiendrez certainement pas les mêmes nombres. Ce qui est important à repérer, c&#8217;est que dans ce premier exemple, tous les id sont différents. Au passage, vous remarquerez que même les constantes ont un id. Je ne sais pas exactement comment cela fonctionne en interne, mais je suppose que lorsqu&#8217;on écrit le chiffre 2, on oblige le python à stocker cette valeur dans une sorte de monde magique contenant tout ce qui a été utilisé depuis le début de l&#8217;exécution, même si certaines de ces valeurs ne sont plus référencées nul part.</p>
<p>Il est parfois intéressant de vérifier que deux id sont égaux ou différents. Mais vous ne pouvez pas faire grand chose de plus. Les caractères de la chaîne &#8220;plop&#8221; sont, à priori, stockés les uns à la suite des autres, dans une seule zone mémoire (tous les langages de programmation gèrent les strings de cette manière), mais vous ne pouvez pas mettre ce fait en évidence.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>b<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">19483368</span>
»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>b<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">19989736</span>
»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>b<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">19989760</span>
»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>b<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span>:<span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">31983736</span>
»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>b<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">31983424</span></pre></div></div>

<p>Les adresses ne se suivent pas, et ne sont même pas rangées dans l&#8217;ordre croissant. Ce n&#8217;est pas vraiment exploitable. En revanche, il y a quelque chose de rigolo à constater :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">»» c = <span style="color: #483d8b;">&quot;pouet&quot;</span>
»» d = <span style="color: #483d8b;">&quot;pouet&quot;</span>
»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>c<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">33984768</span>
»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>d<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">33984768</span>
»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;pouet&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">33984768</span></pre></div></div>

<p>On a deux variables différentes, contenant la même chose, et elles pointent sur la même adresse mémoire. Mais alors, si je modifie c, ça va aussi modifier d ! Ohlala, Comment le python va faire ? Rassurez-vous, il s&#8217;en sort.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">»» c += <span style="color: #483d8b;">&quot;a&quot;</span>
»» c
<span style="color: #483d8b;">'poueta'</span>
»» d
<span style="color: #483d8b;">'pouet'</span>
»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>c<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">33855904</span>
»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>d<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">33984768</span></pre></div></div>

<p>Le type string est immutable (ndm aussi: &#8220;immuable&#8221;). Cela signifie que vous ne pouvez rien changer dedans. Tout ce que vous pouvez faire, c&#8217;est réaffecter des variables (à une autre string, à n&#8217;importe quoi, &#8230;). Dans cet exemple, la réaffectation de c l&#8217;a fait pointer sur une autre zone de la mémoire. Mais sinon, la variable d n&#8217;a pas changé, ni son pointage, ni le contenu de ce qui est pointé. Ouf !!</p>
<p><a title="Je te fais &quot;pouet-pouet&quot;, tu me fais &quot;pouet-pouet&quot; ..." href="http://sametmax.com/wp-content/uploads/2012/11/schema1.png"?9d7bd4"><img class="alignnone  wp-image-2995" src="http://sametmax.com/wp-content/uploads/2012/11/schema1.png"?9d7bd4" alt="Je te fais &quot;pouet-pouet&quot;, tu me fais &quot;pouet-pouet&quot; ..." width="160" height="296" /></a></p>
<p>Au passage, je rappelle que toutes les fonctions de traitement de chaîne de caractères (replace(), upper(), strip(), &#8230;) ne font jamais la modification &#8220;sur place&#8221;. Elles renvoient la valeur sous forme d&#8217;une nouvelle string. Si vous voulez modifier sur place, vous êtes obligés de faire une réaffectation explicite. Quelque chose comme : <code>c = c.upper()</code></p>
<h3>Bidouilleries optimisatoires internes</h3>
<p><a title="Je sens que vous redemandez encore du jeu de mots pourri. So, here comze da None !" href="http://sametmax.com/wp-content/uploads/2012/11/danone1742762776.jpg"?9d7bd4"><img class="alignnone  wp-image-2974" src="http://sametmax.com/wp-content/uploads/2012/11/danone1742762776.jpg"?9d7bd4" alt="Je sens que vous redemandez encore du jeu de mots pourri. So, here comze da None !" width="281" height="180" /></a></p>
<p>Le fait qu&#8217;un objet soit immutable n&#8217;oblige pas le python à créer une seule zone mémoire par valeur. Dans l&#8217;exemple précédent, lorsque j&#8217;ai affecté les variables c et d à &#8220;pouet&#8221;, leurs id auraient pu être différentes dès le départ, et les zones mémoires pointées auraient toutes les deux contenues &#8220;pouet&#8221;. Il se trouve que le python les a mises en commun, par souci d&#8217;optimisation. Cependant, je ne suis pas sûr que cette technique soit appliquée par tous les interpréteurs, toutes les versions, et dans tous les contextes. Mais &#8220;chez moi, ça marche&#8221;.</p>
<p>Cette optimisation est également effectuée pour les valeurs booléennes et les valeurs numériques entières. Mais pas pour les floats, alors qu&#8217;à ma connaissance, ils sont eux aussi immutables.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span><span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">505281316</span>
»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span><span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">505281316</span>
»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span><span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">505280988</span>
»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span><span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">505280988</span>
»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">19846820</span>
»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">19846820</span>
»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10.0</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">19879104</span>
»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10.0</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">31338664</span>
<span style="color: #808080; font-style: italic;"># Refaites des id(10.0), et vous aurez encore d'autres valeurs différentes.</span>
<span style="color: #808080; font-style: italic;"># Mais peut-être pas à chaque fois. On ne peut pas le prévoir.</span></pre></div></div>

<p>En revanche, l&#8217;optimisation de la valeur None est garantie, quel que soit votre python et son contexte. <strong>Il n&#8217;y a toujours qu&#8217;une et une seule instance de None dans une exécution de python.</strong> Je n&#8217;ai pas trouvé d&#8217;annonce officielle concernant cette garantie, mais ça se dit un peu partout sur les forums. (Et si c&#8217;est sur internet, c&#8217;est forcément vrai).</p>
<p>Jouons un peu avec la singletonitude du None.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span><span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">505255972</span>
»» z = <span style="color: #008000;">None</span>
»» <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>z<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">505255972</span>
»» zzzz = <span style="color: black;">&#91;</span><span style="color: #008000;">None</span>, <span style="color: black;">&#93;</span> <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">30</span>
»» zzzz
<span style="color: black;">&#91;</span><span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>,
<span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>,
<span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span><span style="color: black;">&#93;</span>
»» <span style="color: black;">&#91;</span> <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>elem<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> elem <span style="color: #ff7700;font-weight:bold;">in</span> zzzz <span style="color: black;">&#93;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>,
<span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>,
<span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>,
<span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span>,
<span style="color: #ff4500;">505255972</span>, <span style="color: #ff4500;">505255972</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Disgression : les mot-clés True et False peuvent être réaffectés. Mais pas le mot-clé None. Mais je m&#8217;égare. Revenons à nos agneaux, comme dirait Hannibal Lecter.</p>
<h3>noir is noir. (Il n&#8217;y a plus d&#8217;ayspouuaaaarr).</h3>
<p><a title="&quot;Mmmmppff... psshhhh...&quot; (#000000 Vador)" href="http://sametmax.com/wp-content/uploads/2012/11/joy-toy-2248596-star-wars.jpg"?9d7bd4"><img class="alignnone size-full wp-image-2975" src="http://sametmax.com/wp-content/uploads/2012/11/joy-toy-2248596-star-wars.jpg"?9d7bd4" alt="&quot;Mmmmppff... psshhhh...&quot; (#000000 Vador)" width="110" height="110" /></a></p>
<p>Laissez-moi maintenant vous introduire (schlorrp) l&#8217;opérateur <code>is</code>. Il est présent nativement dans le python, et permet de comparer les id de deux objets. <code>A is B</code> renvoie un booléen, le même que celui que renverrait <code>id(A) == id(B)</code>.</p>
<p>A quoi cela pourrait-il donc servir ? Eh bien &#8230; De même que la fonction <code>id</code> ne sert pas à grand chose, <code>is</code> est, lui aussi, d&#8217;une utilité discutable. Mais attendez, ne partez pas tout de suite.</p>
<p>L&#8217;opérateur <code>is</code> est vraiment tout simple. Il ne peut pas être surchargé, et fait toujours la même chose quel que soit les opérandes : une comparaison d&#8217;id.</p>
<p>L&#8217;opérateur <code>==</code> a l&#8217;air tout bête, vu comme ça, mais il peut être surchargé, et il effectue une suite d&#8217;actions pas forcément triviales. Il appelle la fonction <code>__eq__</code> si elle existe, sinon il essaie avec la fonction <code>__cmp__</code>, et peut-être encore d&#8217;autres choses que je ne détaillerai pas ici, parce que je ne me suis pas renseigné en détail sur le sujet. (Faut que je conserve une partie de mon temps pour le pensage à des nichons, vous comprenez bien).</p>
<p>En règle générale, dès que c&#8217;est possible, il vaut mieux utiliser un truc simple plutôt qu&#8217;un truc compliqué. Malheureusement, comme on ne maîtrise pas vraiment la façon dont les id sont gérés et optimisés, l&#8217;utilisation du <code>is</code> serait trop risquée. Sauf dans un cas bien identifié. Devinez lequel ?</p>
<p>Le None, qui n&#8217;a toujours qu&#8217;une et une seule id ! Joie ! Noël !</p>
<p>Au fait, pendant qu&#8217;on y est, ne pourrait-on pas utiliser <code>is</code> avec les valeurs True et False ? A priori, ces deux valeurs sont gérées de la même manière que le None ?</p>
<p>Certes, mais pour les booléens, on a encore plus simple. Au lieu de tester <code>if A is True:</code> ou <code>if A == True:</code>, on peut directement tester <code>if A:</code>. Pour False, on teste <code>if not A:</code>. Voili voilà.</p>
<h3>Le béni oui-oui</h3>
<p><a title="Un béni oui-oui !" href="http://sametmax.com/wp-content/uploads/2012/11/beni-oui-oui.jpg"?9d7bd4"><img class="alignnone  wp-image-2976" src="http://sametmax.com/wp-content/uploads/2012/11/beni-oui-oui.jpg"?9d7bd4" alt="Un béni oui-oui !" width="222" height="202" /></a></p>
<p>Pour finir, une petite justification supplémentaire, que je n&#8217;ai jamais rencontré dans la vraie vie, mais on va faire comme si.</p>
<p>Alors voilà, vous êtes quelqu&#8217;un de bizarre, et vous avez besoin d&#8217;une classe qui est égale à tout. Donc vous surchargez la fonction <code>__eq__</code>.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">»» <span style="color: #ff7700;font-weight:bold;">class</span> BeniOuiOui:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__eq__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># Je suis une classe magique, qui est égale à tout ce qui existe !</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span>
»» beniOuiOui = BeniOuiOui<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Un peu plus loin dans le code, vous avez une variable, récupérée d&#8217;on ne sait trop où, et vous voulez savoir si c&#8217;est None, ou si c&#8217;est une instance de béni-oui-oui. Pour faire cela, vous êtes obligés d&#8217;utiliser <code>is</code>, car <code>==</code> vous répondrait systématiquement True.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">»» beniOuiOui == <span style="color: #ff4500;">2</span>
<span style="color: #008000;">True</span>
»» beniOuiOui == <span style="color: #483d8b;">&quot;n'importe quoi&quot;</span>
<span style="color: #008000;">True</span>
»» beniOuiOui == <span style="color: #008000;">None</span>
<span style="color: #008000;">True</span>
»» beniOuiOui <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span>
<span style="color: #008000;">False</span></pre></div></div>

<h3>this (is not) une pipe</h3>
<p><a title="Ce serait même plutôt le contraire." href="http://sametmax.com/wp-content/uploads/2012/11/cuni0024405_004b.jpg"?9d7bd4"><img class="alignnone  wp-image-2977" src="http://sametmax.com/wp-content/uploads/2012/11/cuni0024405_004b.jpg"?9d7bd4" alt="Ce serait même plutôt le contraire." width="259" height="194" /></a></p>
<p>Comment fait-on pour vérifier que quelque chose n&#8217;est pas None ? La première réponse qui vient à l&#8217;esprit, c&#8217;est <code>not A is None</code>. Mais on peut aussi utiliser <code>A is not None</code>. C&#8217;est chouette, ça ressemble à du langage naturel.</p>
<p>Oh, mais, attendez &#8230; Est-ce que cette écriture n&#8217;est pas un peu dangereuse ?</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">»» <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">None</span>
<span style="color: #008000;">True</span></pre></div></div>

<p><code>not None</code> renvoie True. Pourquoi pas. C&#8217;est ce qui semble le plus logique.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">»» <span style="color: #ff4500;">1</span> <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">True</span>
<span style="color: #008000;">False</span></pre></div></div>

<p><code>1 is True</code> est faux. Ca semble correct aussi. La valeur numérique 1 et la valeur booléenne True sont égales, mais ce ne <em>SONT</em> pas les mêmes objets.</p>
<p>Mais alors, si j&#8217;écris <code>1 is not None</code>, le python va transformer le <code>not None</code> en <code>True</code>, ça va faire <code>1 is True</code>, et ça va renvoyer faux. Ce n&#8217;est pas ce que je veux ! La valeur numérique 1, ce n&#8217;est pas None. Moi je veux que <code>1 is not None</code> me renvoie vrai.</p>
<p>Arrggh ! Pleurons mes amis ! Et regardons avec horreur le python se désintégrer tout seul dans une bouffée de logique !</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">»» <span style="color: #ff4500;">1</span> <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">None</span>
<span style="color: #008000;">True</span></pre></div></div>

<p>Ah tiens non. Hmmm&#8230; Attendez voir&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">»» <span style="color: #ff4500;">1</span> <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">False</span></pre></div></div>

<p>Qu&#8217;est-ce donc que cela ? Figurez-vous que <code>is not</code> est un opérateur. Il compare les id, et renvoie True s&#8217;ils sont différents. Je vous laisse confirmer cela en consultant la doc du python, ou en faisant un petit <code>help("is")</code> dans la console.</p>
<p>Voilà, j&#8217;espère que ça vous a plu. La prochaine fois, nous essaierons de déceler dans le langage Brainfuck des éléments de la thèse existentialiste selon Jean-Paul Sartre.</p>


feed_id: http://sametmax.com/?p=3016
title: Les abréviations dans le domaine adulte, vous connaissez ?
uri: Les-abréviations-dans-le-domaine-adulte-vous-connaissez
url: http://sametmax.com/les-abreviations-dans-le-domaine-adulte-vous-connaissez/
content:
<p>Avec tous ces nouveaux riches &#8211; et oui il n&#8217;y en a jamais eu <a href="http://www.lexpress.fr/actualite/economie/de-plus-en-plus-de-millionnaires-dans-le-monde_1005272.html">autant</a> &#8211; les sites d&#8217;escorts ont poussé comme des champignons, de même que les forums spécialisés dans le recenssement des lieux à filles de joies.<br />
Et ça tombe bien c&#8217;est la saison des champignons ! Alors voici un petit guide des abréviations que vous risquez de trouver sur ces champig&#8230;sites quand vous serez riches et que vous comprendrez que les boudins de Meetic ne servent à rien (pour un riche) et que vous chercherez de la bombe atomique comme <a href="http://sextvx.com/fr/video/124851/aria-giovanni-superbe-brune-stars-du-x-gros-seins">Aria Giovani</a>.</p>

<table id="wp-table-reloaded-id-1-no-1" class="wp-table-reloaded wp-table-reloaded-id-1">
<thead>
	<tr class="row-1 odd">
		<th colspan="3" class="column-1 colspan-3"><b>A</b></th>
	</tr>
</thead>
<tbody>
	<tr class="row-2 even">
		<td class="column-1">ATM</td><td class="column-2">Ass To Mouth</td><td class="column-3">Dans le cul puis dans la bouche</td>
	</tr>
	<tr class="row-3 odd">
		<td colspan="3" class="column-1 colspan-3"><b>B</b></td>
	</tr>
	<tr class="row-4 even">
		<td class="column-1">Bareback</td><td class="column-2">Without condom.<br />
</td><td class="column-3">Sans capote !</td>
	</tr>
	<tr class="row-5 odd">
		<td class="column-1">BBBJ</td><td class="column-2">Bare Back Blow Job</td><td class="column-3">Turlute sans capote</td>
	</tr>
	<tr class="row-6 even">
		<td class="column-1">BBW</td><td class="column-2">Big Beautiful Woman<br />
</td><td class="column-3">Sauvez Willy</td>
	</tr>
	<tr class="row-7 odd">
		<td class="column-1">BDSM</td><td class="column-2">Bondage, Discipline, Sado-Masochism.<br />
</td><td class="column-3">je te fouette, tu me fouettes..</td>
	</tr>
	<tr class="row-8 even">
		<td class="column-1">BFE</td><td class="column-2">Boy Friend Experience<br />
</td><td class="column-3">Toi t'es un pote...</td>
	</tr>
	<tr class="row-9 odd">
		<td class="column-1">BJ</td><td class="column-2">Blow Job</td><td class="column-3">Turlutte</td>
	</tr>
	<tr class="row-10 even">
		<td class="column-1">BLS</td><td class="column-2">Ball Licking and Sucking<br />
</td><td class="column-3"><a href=http://www.youtube.com/watch?v=HtNWiv6PGOg>Voir ici</a></td>
	</tr>
	<tr class="row-11 odd">
		<td class="column-1">Brown Shower	</td><td class="column-2">Defecation on your partner.<br />
</td><td class="column-3">se faire chier dessus</td>
	</tr>
	<tr class="row-12 even">
		<td class="column-1">BS</td><td class="column-2">Body slide</td><td class="column-3"><a href=http://sametmax.com/la-levrette-au-baby-oil-merci-johnson/>massage à l'huile</a></td>
	</tr>
	<tr class="row-13 odd">
		<td colspan="3" class="column-1 colspan-3"><b>C</b></td>
	</tr>
	<tr class="row-14 even">
		<td class="column-1">CBJ</td><td class="column-2">Covered Blow Job</td><td class="column-3">Pipe avec capote</td>
	</tr>
	<tr class="row-15 odd">
		<td class="column-1">CFM</td><td class="column-2">Come Fuck Me</td><td class="column-3">Se dit d'une fille qui sent le cul</td>
	</tr>
	<tr class="row-16 even">
		<td class="column-1">CIM</td><td class="column-2">Cum in Mouth<br />
</td><td class="column-3">Une bonne giclée de sperme dans la bouche</td>
	</tr>
	<tr class="row-17 odd">
		<td class="column-1">COB</td><td class="column-2">Cum on Breast<br />
</td><td class="column-3">Ejac sur les nibards</td>
	</tr>
	<tr class="row-18 even">
		<td class="column-1">COF</td><td class="column-2">Cum on Face</td><td class="column-3"><a href="http://sextvx.com/fr/video/168883/shes-covered-in-cum">Ejaculation faciale</a></td>
	</tr>
	<tr class="row-19 odd">
		<td colspan="3" class="column-1 colspan-3"><b>D</b></td>
	</tr>
	<tr class="row-20 even">
		<td class="column-1">DFK</td><td class="column-2">Deep French Kissing<br />
</td><td class="column-3">Avec la langue régis ! Et bien profond</td>
	</tr>
	<tr class="row-21 odd">
		<td class="column-1">DS</td><td class="column-2">DoggyStyle. Man behind girl, girl on hands and knees</td><td class="column-3">Mon petit poney...</td>
	</tr>
	<tr class="row-22 even">
		<td class="column-1">DPA</td><td class="column-2">Double Penetration Anal<br />
</td><td class="column-3">2 bites dans le cul</td>
	</tr>
	<tr class="row-23 odd">
		<td class="column-1">DT</td><td class="column-2">Deep Throat<br />
</td><td class="column-3">Gorge profonde</td>
	</tr>
	<tr class="row-24 even">
		<td colspan="3" class="column-1 colspan-3"><b>F</b></td>
	</tr>
	<tr class="row-25 odd">
		<td class="column-1">FJ</td><td class="column-2">Foot job</td><td class="column-3"><a href="http://xhamster.com/movies/1378903/japanese_dildo_footjob.html">branlette avec les pieds</a></td>
	</tr>
	<tr class="row-26 even">
		<td class="column-1">FK</td><td class="column-2">French Kissing</td><td class="column-3">Avec la langue</td>
	</tr>
	<tr class="row-27 odd">
		<td class="column-1">FKK</td><td class="column-2">Frei Körper Kultur </td><td class="column-3">Maisons closes fleurissants aux abords des routes allemandes...</td>
	</tr>
	<tr class="row-28 even">
		<td class="column-1">FS</td><td class="column-2">Full Service </td><td class="column-3">Je vous fait le parebrise avec ça ?</td>
	</tr>
	<tr class="row-29 odd">
		<td colspan="3" class="column-1 colspan-3"><b>G</b></td>
	</tr>
	<tr class="row-30 even">
		<td class="column-1">GFE</td><td class="column-2">Girl Friend Experience<br />
</td><td class="column-3">C'est comme si t'étais ma meuf, tu me coûte autant mais au moins je te baise.</td>
	</tr>
	<tr class="row-31 odd">
		<td class="column-1">GS</td><td class="column-2">Golden Shower</td><td class="column-3">se faire pisser dessus</td>
	</tr>
	<tr class="row-32 even">
		<td colspan="3" class="column-1 colspan-3"><b>H</b></td>
	</tr>
	<tr class="row-33 odd">
		<td class="column-1">HE</td><td class="column-2">Happy Ending</td><td class="column-3"><a href="http://sextvx.com/fr/video/194697/japanese-massage-with-happy-ending-for-teen-girl">Massage avec finition</a></td>
	</tr>
	<tr class="row-34 even">
		<td class="column-1">HJ</td><td class="column-2">Hand Job<br />
</td><td class="column-3">Branlette à la main</td>
	</tr>
	<tr class="row-35 odd">
		<td colspan="3" class="column-1 colspan-3"><b>L</b></td>
	</tr>
	<tr class="row-36 even">
		<td class="column-1">LT</td><td class="column-2">Long Time</td><td class="column-3">Relation d'au moins 24 heures avec une Biatch. Ex: Kany West est en LT avec kim Kardashian</td>
	</tr>
	<tr class="row-37 odd">
		<td colspan="3" class="column-1 colspan-3"><b>O</b></td>
	</tr>
	<tr class="row-38 even">
		<td class="column-1">OWO</td><td class="column-2">Oral WithOut a condom</td><td class="column-3">Turlutte sans capote, voir BBBJ</td>
	</tr>
	<tr class="row-39 odd">
		<td class="column-1">OWOTC</td><td class="column-2">Oral Without Condom To Completion<br />
</td><td class="column-3">Turlutte sans capote avec éjac</td>
	</tr>
	<tr class="row-40 even">
		<td colspan="3" class="column-1 colspan-3"><b>S</b></td>
	</tr>
	<tr class="row-41 odd">
		<td class="column-1">SOMF</td><td class="column-2">Sat On My Face<br />
</td><td class="column-3">voir la dernière image de <a href="http://sametmax.com/id-none-et-bidouilleries-memoire-en-python/">ça</a></td>
	</tr>
	<tr class="row-42 even">
		<td class="column-1">ST</td><td class="column-2">Short Time</td><td class="column-3">Prendre une Biatch pour 1 heure et la remercier.</td>
	</tr>
	<tr class="row-43 odd">
		<td colspan="3" class="column-1 colspan-3"><b>T</b></td>
	</tr>
	<tr class="row-44 even">
		<td class="column-1">Tossing Salad</td><td class="column-2">Analingus</td><td class="column-3">se faire bouffer le cul</td>
	</tr>
	<tr class="row-45 odd">
		<td class="column-1">TS</td><td class="column-2">Transexual</td><td class="column-3">Mon frère depuis que je l'appelle ma soeur</td>
	</tr>
	<tr class="row-46 even">
		<td class="column-1">TUMA</td><td class="column-2">Tongue Up My Ass<br />
</td><td class="column-3">Se faire mettre la langue dans le trou de balle, en général quand on ose pas embrasser.</td>
	</tr>
	<tr class="row-47 odd">
		<td colspan="3" class="column-1 colspan-3"><b>W</b></td>
	</tr>
	<tr class="row-48 even">
		<td class="column-1">WF</td><td class="column-2">Wild Fuck</td><td class="column-3">Baise déjantée</td>
	</tr>
</tbody>
</table>

<p>J&#8217;ai du en oublier quelques unes mais en gros avec ça on s&#8217;en sort déjà pas mal au moment de choisir le dessert.</p>
<p>Et N&#8217;oubliez pas la célèbre citation de George Simenon :<br />
     <em>&#8220;Les filles que l&#8217;on paie ne sont pas celles qui nous coûtent le plus cher&#8230;&#8221;</em></p>


feed_id: http://sametmax.com/?p=2869
title: Valeurs et références en Python
uri: Valeurs-et-références-en-Python
url: http://sametmax.com/valeurs-et-references-en-python/
content:
<p>Petit article en complément de <a href="http://sametmax.com/id-none-et-bidouilleries-memoire-en-python/">l&#8217;article de Réchèr</a>.</p>
<p>Il y a plusieurs manières de passer une variable en informatique: par valeur ou par référence. Et dans les langages bas niveau comme le C, on se pose la question: &#8220;passe-t-on la valeur ? un pointer ? un pointer vers un pointer ?&#8221;</p>
<p>En Python ce n&#8217;est pas la question puisque tout se passe par référence. Tous les objets. Dans tous les cas.</p>
<p>La question est donc plutôt: &#8220;ça veut dire quoi passer par référence ?&#8221;</p>
<h2>Assignation et référence</h2>
<p>Une référence est comme une adresse qui dit où la donnée se trouve en mémoire.</p>
<p>Quand vous faites ceci:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">a = <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Vous n&#8217;assignez pas la liste à la variable &#8220;a&#8221;, vous assignez une référence vers la liste, donc une sorte d&#8217;adresse qui indique où elle se trouve en mémoire. (en vérité vous n&#8217;assignez rien, les variables sont des étiquettes en Python, mais on va ignorer ce détail ici).</p>
<p>Et quand vous faites:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">print</span> a</pre></div></div>

<p>Python va chercher dans <code>a</code> la référence, et retrouver la liste en suivant &#8220;l&#8217;adresse&#8221;.</p>
<p>C&#8217;est important car ça veut dire deux choses.</p>
<p>1. Quand vous faites ça:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">a = b</pre></div></div>

<p>Vous ne copiez pas la liste. Vous copiez la référence. Du coup, on ne prend pas deux fois la place en mémoire, et la copie est très rapide</p>
<p>2. Quand vous faites ça:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">a = b</pre></div></div>

<p>Vous ne copiez pas la liste. Vous copiez la référence. Bis.</p>
<p>Et si vous faites:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">b.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Alors:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">print</span> a</pre></div></div>

<p>Va donner&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span>, <span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Car en faisant <code>append()</code> sur <code>b</code>, Python va trouver une référence, retrouver la liste derrière la référence, et faire un <code>append()</code> sur la liste. Comme c&#8217;est la même réference dans <code>a</code> et <code>b</code> (puisqu&#8217;on l&#8217;a copié), c&#8217;est la même liste derrière. Tout ce qu&#8217;on applique à <code>a</code>, s&#8217;applique donc à <code>b</code>, et vice-versa.</p>
<p>Si vous voulez faire une vraie copie, alors il faut recréer une toute nouvelle liste. Par exemple:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">b = <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>a<span style="color: black;">&#41;</span></pre></div></div>

<h2>Mutable et non mutable</h2>
<p>L&#8217;assignation par référence n&#8217;a vraiment d&#8217;importance que dans le cas où un objet est mutable. En Python, il existe en effet deux types d&#8217;objets: les mutables (listes, dictionnaires, sets, objets custo, etc) et les nons mutables (strings, int, floats, tuples, etc).</p>
<p>Les mutables sont ceux qu&#8217;on peut modifier après leur création. Les non mutables sont ceux qu&#8217;on ne peut pas modifier après création.</p>
<p>On ne peut pas modifier <code>152</code> un fois que l&#8217;objet int est créé. Mais on peut rajouter des éléments à une liste après qu&#8217;elle soit créé. Les ints sont non mutables. Les lists sont mutables.</p>
<p>Cela peut surprendre, mais les strings sont non mutables. Même quand vous faites:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> pa = <span style="color: #483d8b;">&quot;papa&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> pi = pa.<span style="color: black;">replace</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;a&quot;</span>, <span style="color: #483d8b;">&quot;i&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> pa
papa
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> pi
pipi</pre></div></div>

<p>Vous ne modifiez pas la chaîne originale: vous créé une copie de la chaîne, et la chaîne de départ n&#8217;a pas bougé.</p>
<p>C&#8217;est important car si on fait une référence vers un type non mutable, on s&#8217;en oint le pourtour anale avec pelle à tarte: il ne peut pas être modifié. Peu importe que la référence soit copiée à droite et à gauche. Mais si l&#8217;objet est mutable, chaque copie de la référence ajoute un endroit dans le programme duquel on peut modifier l&#8217;objet.</p>
<p>Cela a des implications parfois assez coquines.</p>
<p>Ainsi:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> l = <span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">3</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> l <span style="color: #808080; font-style: italic;"># une liste de 3 zéros</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> l<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span> += <span style="color: #ff4500;">1</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> l
<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Ici tout se comporte comme prévu. Les ints sont non mutables, donc on ne s’aperçoit pas d&#8217;un détail important: <code>[0] * 3</code> copie la référence à <code>0</code> trois fois. Quand on fait <code>+=</code>, ça remplace l&#8217;ancien int par un nouveau, donc un seul item de la liste est changé.</p>
<p>Mais si on fait vicieusement:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> l = <span style="color: black;">&#91;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span> <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">3</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> l <span style="color: #808080; font-style: italic;"># une liste de listes d'un seul zéro chacune</span>
<span style="color: black;">&#91;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>, <span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>, <span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> l<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> += <span style="color: #ff4500;">1</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> l
<span style="color: black;">&#91;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>, <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>, <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Ici on a copié 3 fois la référence vers la même liste. Du coup une modification affecte les 3 items. Doh.</p>
<p>Rappels: les tuples ne sont pas mutables. Et on peut passer d&#8217;un tuple à une liste avec <code>tuple(l)</code> et <code>list(t)</code>. Pensez-y si vous rencontrez ce genre de problème.</p>
<h2>Passage des arguments de fonction par référence</h2>
<p>Quand vous faites cela:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> encore_une_fonction_d_exemple_inutile<span style="color: black;">&#40;</span>l<span style="color: black;">&#41;</span>:
    l.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> l
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> l1 = <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> encore_une_fonction_d_exemple_inutile<span style="color: black;">&#40;</span>l1<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> l1
<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span>, <span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Vous noterez que la liste a été modifiée. C&#8217;est parce que l&#8217;on passe une référence à la liste quand on la passe en argument. Toute modification de la liste dans la fonction est donc visible en dehors de la fonction. Si le paramètre était immutable, encore une fois on s&#8217;en ficherait. Mais là, comme liste est mutable, notre fonction possède ce qu&#8217;on nomme un effet de bord: quand on l&#8217;appelle, elle a des conséquences sur des objets qui existe en dehors d&#8217;elle même.</p>
<p>Il est généralement de bon ton d&#8217;éviter les effets de bord, aussi, essayez toujours de travailler sur des copies: utilisez le slicing, les listes en intention, les générateurs, etc., pour retourner les nouvelles valeurs plutôt que de modifier l&#8217;objet original.</p>
<p>Ici:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> encore_une_fonction_d_exemple_inutile<span style="color: black;">&#40;</span>l<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> l1 + <span style="color: black;">&#91;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Nous permet de retourner une nouvelle liste. Si la liste prend beaucoup de place en mémoire, on peut faire ça:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> encore_une_fonction_d_exemple_inutile<span style="color: black;">&#40;</span>l<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> l:
        <span style="color: #ff7700;font-weight:bold;">yield</span> x
    <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #ff4500;">4</span></pre></div></div>

<p>Ce qui aurait pour effet de retourner un itérable similaire, sans prendre plus de mémoire.</p>
<h2>Valeurs par défaut et référence</h2>
<p>Quand on utilise une valeur par défaut, par exemple dans la déclaration des paramètres d&#8217;une fonction, on initialise une référence qui va rester la même pour toute la durée du programme.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> encore_une_fonction_d_exemple_inutile<span style="color: black;">&#40;</span>l=<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>:
    l.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> l
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> encore_une_fonction_d_exemple_inutile<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> encore_une_fonction_d_exemple_inutile<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> l1
<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span>, <span style="color: #ff4500;">4</span>, <span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span></pre></div></div>

<p>On constate ici que <code>4</code> a été ajouté deux fois dans la liste. En effet, l est l&#8217;argument par défaut, et ici, il est initialisé à la référence pointant sur une liste <code>[1, 2, 3]</code>. Pas sur la valeur <code>[1, 2, 3]</code>. <code>[1, 2, 3]</code> est stocké quelque part dans un monde invisible que seul Guido Van Rossum connait, et <code>l</code> contient juste la référence à cette liste.</p>
<p>Cette référence est gardée, et à chaque appel, c&#8217;est la même liste qui est utilisée. Si on appelle deux fois la fonction, la première fois c&#8217;est la liste <code>[1, 2, 3, 4]</code> à laquelle on ajoute <code>4</code>. Puis comme c&#8217;est la même référence, on ajoute ensuite <code>4</code> à la même liste, à laquelle on avait déjà ajouté <code>4</code>.</p>
<p>Bref, évitez les mutables dans les paramètres par défaut à moins de savoir ce que vous faites (cache ou memoization).</p>
<h2>Variables de classe et références</h2>
<p>La même problématique existe pour le classes. Si vous faites:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> AuChocolat<span style="color: black;">&#40;</span>objet<span style="color: black;">&#41;</span>:
&nbsp;
    suppéments = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'chantilly'</span>, <span style="color: #483d8b;">'praline'</span><span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> g1 = AuChocolat<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> g2 = AuChocolat<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> g1.<span style="color: black;">supplements</span>.<span style="color: black;">pop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'praline'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> g2.<span style="color: black;">supplements</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'chantilly'</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Même principe: toute variable de classe pointe pour toute la durée du programme sur la même réference. La référence va être partagée entre toutes les instances de la classe. C&#8217;est donc la même liste !</p>
<h2>Maintient d&#8217;une référence</h2>
<p>Python garde un objet en mémoire tant qu&#8217;il existe une référence vers cet objet.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> a = <span style="color: #ff4500;">1</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> b = a
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">del</span> a
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> b
<span style="color: #ff4500;">1</span></pre></div></div>

<p>Si je supprime <code>a</code>, il reste <code>b</code>, donc l&#8217;objet est toujours en mémoire. Si je supprime <code>b</code> également, Python va lancer le processus de nettoyage pour effacer l&#8217;objet de la mémoire.</p>
<p>Une référence existe toujours dans le cadre d&#8217;un scope. Par exemple, si une référence est copiée dans une fonction, quand la fonction se termine, la copie de la référence est supprimée, et ne compte plus comme une voix pour le maintient de l&#8217;objet en mémoire.</p>
<p>En Python, il n&#8217;existe donc aucun moyen de supprimer un objet. On peut juste supprimer toutes ses références, et attendre que Python s&#8217;apperçoive que tout le monde s&#8217;en branle à présent de l&#8217;objet, et le supprime.</p>
<p>Dans certains cas particuliers, on veut qu&#8217;une référence à un objet ne compte pas comme une voix. On peut le faire en utilisant le module <code>weakref</code>, mais cela ne marche qu&#8217;avec les classes que l&#8217;on code soit-même.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> ALaVanille<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">weakref</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> g1 = ALaVanille<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> g2 = <span style="color: #dc143c;">weakref</span>.<span style="color: black;">proxy</span><span style="color: black;">&#40;</span>g1<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> g2
<span style="color: #66cc66;">&lt;</span>weakproxy at 0x7f5f26994730 to ALaVanille at 0x7f5f26992d90<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> g1.<span style="color: black;">foo</span> = <span style="color: #483d8b;">&quot;bar&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> g2.<span style="color: black;">foo</span>
<span style="color: #483d8b;">'bar'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">del</span> g1
<span style="color: #66cc66;">&gt;&gt;&gt;</span> g2
<span style="color: #66cc66;">&lt;</span>weakproxy at 0x7f5f26994730 to NoneType at 0x859380<span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>Dès qu&#8217;on supprime <code>g1</code>, <code>g2</code> proxy vers <code>None</code>, car la référence vers l&#8217;instance de <code>ALaVanille</code> ne compte pas pour garder en vie l&#8217;objet.</p>


feed_id: http://sametmax.com/?p=1588
title: Shut ! J’ai un secret en Python…
uri: Shut-J-ai-un-secret-en-Python
url: http://sametmax.com/shut-jai-un-secret-en-python/
content:
<p>J&#8217;adore les chasses au trésor. Préparer les énigmes, suivre les participants, c&#8217;est bien plus marrant que de faire partie d&#8217;une des équipes. Je me suis toujours dit que si je devenais obscènement riche, j&#8217;achèterais 10 millions d&#8217;euros en pièces d&#8217;or et je les planquerais quelque part, puis je lancerais une chasse au trésor mondiale pour le fun. Des années de préparation, des années d&#8217;amusement !</p>
<p>Une des problématiques de la chasse au trésor, c&#8217;est de s&#8217;assurer que tout le monde a une chance. Il faut varier les épreuves: musique, littérature, observation, orientation, histoire, puzzle, exercice physique, etc. Et bien sûr il faut créer un système tolérant à l&#8217;échec, car le but c&#8217;est quand même que quelqu&#8217;un trouve le butin. La meilleure partie est après tout ce très court moment d’exultation où on ouvre le coffre, ou son équivalent.</p>
<p>Quand c&#8217;est une chasse au trésor pour mioches, c&#8217;est facile, il suffit de donner un temps d&#8217;avance à l&#8217;équipe qui réussi une épreuve en premier, de balancer un indice, de retirer une contrainte, etc. Au pire on saute juste une épreuve.</p>
<p>Dans une grosse chasse au trésor, il faut faire quelque chose de plus sérieux: on doit limiter son interaction au maximum avec les équipes pour leur donner une sensation d&#8217;aventure, et de challenge.</p>
<p>La solution à ce problème, c&#8217;est d&#8217;utiliser des indices divisibles:</p>
<ul>
<li>prendre l&#8217;indice suivant;</li>
<li>le diviser en morceaux;</li>
<li>permettre de recoller les morceaux, et obtenir l&#8217;indice même quand on ne les a pas tous.</li>
</ul>
<p>Ainsi, si on a 5 épreuves, on prend l&#8217;indice suivant, on le divise en 5, et on s&#8217;assure que réussir 3 épreuves suffisse à donner assez d&#8217;informations pour reconstituer l&#8217;indice suivant. Ca marche avec les cartes incomplètes, les textes à trou, les dessins superposables, etc.</p>
<p>En informatique il existe un moyen de faire cela avec le <a href="https://fr.wikipedia.org/wiki/Partage_de_cl%C3%A9_secr%C3%A8te_de_Shamir">partage de clé secrète de Shamir</a>. Et bien sûr, comme toujours, il y a <a href="http://code.google.com/p/python-secret-sharing/">une lib Python</a> qui permet de s&#8217;en servir.</p>
<p>Malheureusement, comme beaucoup de libs scientifiques, elle est bien chiante à installer et elle ne respecte pas le PEP8:</p>
<p>D&#8217;abord il vous faut installer pycrypto, une dépendance:</p>
<p><code><a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a> install pycryto</code></p>
<p>Assurez-vous d&#8217;avoir les headers de Python (paquet python-dev sous Ubuntu), car c&#8217;est une extension en C que pip va compiler.</p>
<p>Ensuite, on doit cloner le repo à la main (si, si):</p>
<p><code>git clone https://code.google.com/p/python-secret-sharing/</code></p>
<p>Et copier le dossier nommé &#8216;ss&#8217; (un truc aussi strict, c&#8217;est forcément les nazis j&#8217;vous dis) dans le dossier de votre application ou dans votre dossier de site-package. Si j&#8217;ai le temps je leur proposerais un petit <code>setup.py</code>.</p>
<p>Ensuite ça s&#8217;utilise très facilement:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> ss.<span style="color: black;">secret_sharing</span> <span style="color: #ff7700;font-weight:bold;">import</span> secret_sharing
<span style="color: #66cc66;">&gt;&gt;&gt;</span> secret = secret_sharing<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;1 - voler des caleçons. 2 - .... 3 - profit !&quot;</span>, <span style="color: #ff4500;">20</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Ceci va produire un secret divisible en 20 parts, donc il ne faut que 3 parts pour relire le secret de conquête du monde que j&#8217;ai planqué dans cette citation pleine de sagesse.</p>
<p>Je peux obtenir une part au hasard:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> secret.<span style="color: black;">share_random</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> 
<span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">16</span>, 721654044499788854347597992565674L<span style="color: black;">&#41;</span>,
 <span style="color: black;">&#40;</span><span style="color: #ff4500;">18</span>,
  102214856329848326909206303519239813304695812929767500268700035275955811306374521388L<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Notez que c&#8217;est un simple tuple. On peut en faire des choses avec un simple tuple, comme le serialiser, le compresser, l&#8217;obfusquer, l&#8217;encoder, le sténographier&#8230;</p>
<p>Et si je veux retrouver le secret:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> ss.<span style="color: black;">secret_sharing_c</span> <span style="color: #ff7700;font-weight:bold;">import</span> secret_sharing_c
<span style="color: #66cc66;">&gt;&gt;&gt;</span> assembleur = secret_sharing_c<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> assembleur.<span style="color: black;">add_share</span><span style="color: black;">&#40;</span>secret.<span style="color: black;">share_random</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> assembleur.<span style="color: black;">add_share</span><span style="color: black;">&#40;</span>secret.<span style="color: black;">share_random</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> assembleur.<span style="color: black;">add_share</span><span style="color: black;">&#40;</span>secret.<span style="color: black;">share_random</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> assembleur.<span style="color: black;">reconstruct</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">1</span> - voler des caleçons. <span style="color: #ff4500;">2</span> - .... <span style="color: #ff4500;">3</span> - profit <span style="color: #66cc66;">!</span></pre></div></div>

<p>Attention: si on met moins ou plus de parts dans l&#8217;assembleur que prévu, il s&#8217;auto-poutre avec un salami en bêton bardé de <code>ZeroDivisionError</code> ou <code>OverflowError</code>.</p>
<p>Bref, comme d&#8217;habitude l&#8217;informatique peut être fun, fun, fun. Je me demande pourquoi on enseigne jamais ça en cours. C&#8217;est quand même plus marrant que de créer des fonctions de manipulation de graphes en Java comme on avait eu la bonne idée de nous faire faire.</p>


feed_id: http://sametmax.com/?p=2694
title: git revert pour annuler proprement le dernier commit
uri: git-revert-pour-annuler-proprement-le-dernier-commit
url: http://sametmax.com/git-revert-pour-annuler-proprement-le-dernier-commit/
content:
<p>On ne peut pas à proprement parler supprimer un commit de Git. Mais on peut l&#8217;inverser proprement.</p>
<p>Assurez-vous d&#8217;avoir une copie de travail propre (sans files to be commited ou conflits, quitte à <a href="http://sametmax.com/soyez-relax-faites-vous-un-petit-git-stash/">stasher</a>). Puis:</p>
<p><code>git revert HEAD~1</code></p>
<p>Cette commande va immédiatement prendre le précédent commit, créer une commit exactement inverse, et l&#8217;appliquer.</p>
<p>Si vous aviez:  C1 &#8212; C2 &#8212; C3</p>
<p>Et que vous vouliez annuler C3.</p>
<p>Vous allez vous retrouver avec:  C1 &#8212; C2 &#8212; C3 &#8212; C4.</p>
<p>Avec C4 comme exacte inverse de C3.</p>
<p>Si vous voulez annuler plus d&#8217;un commit: <code>git revert HEAD~nombre-de-commits</code></p>
<p>Y a plus qu&#8217;à pusher !</p>
<p>Ceci est complètement différent de <code>git commit --amend</code> qui lui remplace le commit précédent par le commit actuel <strong>à condition de ne pas avoir pushé le commit précédent</strong>.</p>
<p>Avec amend, si vous aviez:</p>
<p>Si vous aviez:  C1 &#8212; C2 &#8212; C3</p>
<p>Et que vous vouliez annuler C3.</p>
<p>Vous allez vous retrouver avec:  C1 &#8212; C2 &#8212; C4 </p>
<p>Mais il faut créer C4 de toute pièce. </p>
<p><code>revert</code>, c&#8217;est comme Cabrel: c&#8217;était mieux avant.<br />
<code>amend</code>, c&#8217;est comme Britney: ooups, I did it again.</p>


feed_id: http://sametmax.com/?p=3081
title: Utiliser Cherrypy (serveur web léger) avec Bottle (Framework léger)
uri: Utiliser-Cherrypy-(serveur-web-léger)-avec-Bottle-(Framework-léger)
url: http://sametmax.com/utiliser-cherrypy-serveur-web-leger-avec-bottle-framework-leger/
content:
<p>Pour les sites/app qu&#8217;on developpe en une journée, <a href="http://bottlepy.org/docs/dev/">Bottle</a> et <a href="http://www.cherrypy.org/">Cherrypy</a> sont deux larons en foire qui s&#8217;accouplent parfaitement&#8230;</p>
<p><strong>Rappel:</strong></p>
<p style="padding-left: 30px;"><strong></strong><strong>Bottle:</strong> Framework python light, allez voir <a title="Créer un site avec bottle en 5 minutes" href="http://sametmax.com/creer-un-site-avec-bottle-en-5-minutes-parceque-7-cest-impossible-voyons/">&#8220;Créer un site avec bottle en 5 minutes&#8221;</a><br />
<strong>Cherrypy:</strong> Framework python light + serveur web</p>
<p><strong><br />
Une bonne <a href="http://sametmax.com/votre-python-aime-les-pip/">Pip</a> pour commencer:</strong></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">monsieur@fion:~<span style="color: #808080; font-style: italic;"># pip install cherrypy</span></pre></div></div>

<p><strong>Dans votre fichier start.py:</strong></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">run<span style="color: black;">&#40;</span>host=<span style="color: #483d8b;">'0.0.0.0'</span>, port=<span style="color: #ff4500;">80</span>, server=<span style="color: #483d8b;">'cherrypy'</span><span style="color: black;">&#41;</span></pre></div></div>

<p><strong>Note:</strong> le 0.0.0.0 permet d&#8217;acceder à votre site depuis l&#8217;extérieur.</p>
<p>Pour lancer en daemon vous pouvez utiliser <a href="http://supervisord.org/">supervisord</a> <strong>ou</strong> faire un script dans le répertoire où se trouve <em>start.py</em> de votre projet et y coller:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#! /bin/sh</span>
&nbsp;
<span style="color: #808080; font-style: italic;">### Run server in daemon mode</span>
nohup python start.<span style="color: black;">py</span> <span style="color: #66cc66;">&amp;</span></pre></div></div>

<p><strong>Plusieurs serveurs web sur la même machine:</strong><br />
Si vous avez un autre serveur web qui tourne sur votre machine et qui vous empêche de lancer cherrypy sur le port 80 vous pouvez utiliser <a href="http://nginx.org/">nginx</a> en <a href="http://wiki.nginx.org/HttpProxyModule">proxy</a>. Pour ce faire modifiez le port de cherrypy dans votre fichier <em>start.py</em> (voir plus haut) et réglez-le sur 7777 par exemple avec un host 127.0.0.1.<br />
Ouvrez un fichier de conf nginx et copiez ceci:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">upstream monsite_cherrypy <span style="color: black;">&#123;</span>
    server 127.0.0.1:<span style="color: #ff4500;">7777</span><span style="color: #66cc66;">;</span>
<span style="color: black;">&#125;</span>
&nbsp;
server <span style="color: black;">&#123;</span>
        listen       <span style="color: #ff4500;">80</span><span style="color: #66cc66;">;</span>
        server_name monsite.<span style="color: black;">com</span> www.<span style="color: black;">monsite</span>.<span style="color: black;">com</span> <span style="color: #66cc66;">;</span>
&nbsp;
        location /favicon.<span style="color: black;">ico</span> <span style="color: black;">&#123;</span>
            root  /home/monsite/static/img<span style="color: #66cc66;">;</span>
        <span style="color: black;">&#125;</span>
&nbsp;
        location / <span style="color: black;">&#123;</span>
            proxy_pass http://monsite_cherrypy<span style="color: #66cc66;">;</span> 
        <span style="color: black;">&#125;</span>
&nbsp;
<span style="color: black;">&#125;</span></pre></div></div>

<p>Relancez Nginx (service nginx restart). Et votre site est en place. C&#8217;est ce qu&#8217;on utilise pour <a href="http://multiboards.net/">multiboards</a> par exemple.</p>
<p>C&#8217;est rapide et simple et ça peut tenir pas mal de visiteurs. ça évite d&#8217;installer des trucs lourds avec 3 tonnes de config.</p>


feed_id: http://sametmax.com/?p=3077
title: Comment savoir qu’il est temps de faire une pause ?
uri: Comment-savoir-qu-il-est-temps-de-faire-une-pause
url: http://sametmax.com/comment-savoir-quil-est-temps-de-faire-une-pause/
content:
<p>Parfois on a la tête dans le guidon, et on ne sait pas trop quand il faut s&#8217;arrêter.</p>
<p>Voici un signe qui ne trompe pas:</p>
<ol>
<li>Vous retirez une pastille de poudre vaisselle de son emballage.</li>
<li>Vous jetez la pastille, et vous mettez l&#8217;emballage dans la machine.</li>
<li>Vous lancez la machine.</li>
</ol>
<p>Je crois que je ne ferai donc pas d&#8217;article aujourd&#8217;hui. </p>
<p>Ah, trop tard.</p>
<p>En plus, j&#8217;ai appuyé sur le mauvais bouton, la machine n&#8217;est jamais parti.</p>


feed_id: http://sametmax.com/?p=3102
title: Créer un setup.py et mettre sa bibliothèque Python en ligne sur Pypi
uri: Créer-un-setup-py-et-mettre-sa-bibliothèque-Python-en-ligne-sur-Pypi
url: http://sametmax.com/creer-un-setup-py-et-mettre-sa-bibliotheque-python-en-ligne-sur-pypi/
content:
<p>Je crois que ce sujet est dans le top 10 des trucs qui paraissent mystiques même après avoir passé des heures sur les docs sur le net. Et si ça prend effectivement un peu de temps CPU neuronale pour s&#8217;en sortir, on est loin de la montagne qu&#8217;on s&#8217;en est fait.</p>
<p>Scénario: vous avez écrit une lib. Elle est belle, elle sent bon le sable chaud. Vous voulez la partager.</p>
<p>La première étape, c&#8217;est de créer une fichier setup.py qui permettra aux gens de l&#8217;installer. La seconde, c&#8217;est de la mettre en ligne sur le site Pypi pour que les gens puissent l&#8217;installer avec <a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a>.</p>
<p>Nous allons donc créer un <em>setup.py</em> pour une lib incroyable: la &#8220;sm_lib&#8221;.</p>
<h2>Arborescence</h2>
<p>Généralement, quand on développe une petite lib au fil de l&#8217;eau, on une forte tendance à tout mettre en vrac dans un dossier. Cependant pour créer un paquet installable, il est beaucoup plus simple et propre d&#8217;avoir une organisation de fichiers standards. On peut faire sans, mais c&#8217;est prise de tête.</p>
<p>Prenons notre lib exceptionnelle&#8230;</p>
<p><a href="http://sametmax.com/wp-content/uploads/2012/11/Capture-du-2012-11-16-1058501.png"?9d7bd4"><img src="http://sametmax.com/wp-content/uploads/2012/11/Capture-du-2012-11-16-1058501.png"?9d7bd4" alt="" title="" width="313" height="386" class="aligncenter size-full wp-image-3108" /></a></p>
<p>Pour le moment, elle est composée d&#8217;un dossier &#8220;sm_lib&#8221; avec 3 fichiers:</p>
<ul>
<li>une photo des auteurs (suite aux plaintes reçues, nous avons une nouvelle ligne de conduite concernant les photographies. Demain, les bébés !);</li>
<li>l&#8217;indispensable <em>__init__.py</em>, qui est vide;</li>
<li>un fichier <em>core.py</em> (qui peut avoir n&#8217;importe quel nom) qui contient le code de notre lib dont le but est de diffuser un message hautement subversif:</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">datetime</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">datetime</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> proclamer<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;[%s] Sam et Max, c'est bien&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #dc143c;">datetime</span>.<span style="color: black;">now</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    proclamer<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Maintenant que nous avons changé de mentalité, nous voulons absolument propager notre nouveau message et ton du blog partout, donc on va distribuer cette bibliothèque.</p>
<p>Premièrement, on va réorganiser les fichiers et en rajouter quelques uns:</p>
<p><a href="http://sametmax.com/wp-content/uploads/2012/11/Capture-du-2012-11-16-111239.png"?9d7bd4"><img src="http://sametmax.com/wp-content/uploads/2012/11/Capture-du-2012-11-16-111239.png"?9d7bd4" alt="On met sm_lib dans un dossier sm_lib" title="" width="376" height="779" class="aligncenter size-full wp-image-3109" /></a></p>
<p>Vous noterez qu&#8217;on a mis notre dossier de lib, dans un autre dossier, et que les deux dossiers portent le même nom &#8220;sm_lib&#8221;. C&#8217;est redondant, mais c&#8217;est normal. Le dossier qui contient tout est le dossier de distribution, c&#8217;est l&#8217;emballage de notre lib. Le dossier qui contient notre code, c&#8217;est le dossier d&#8217;installation, c&#8217;est celui qui sera copié sur le système, et qui doit avoir un nom de package importable (pas de uniquement des lettres et des _ dans le nom, ou un chiffre mais pas en premier caractère).</p>
<p>Les noms peuvent être différents, mais généralement on donne le même nom aux deux, car c&#8217;est plus simple.</p>
<p>On rajoute 3 fichiers:</p>
<ul>
<li>setup.py: un fichier de code Python qui est notre installeur.</li>
<li>MANIFEST.in: un fichier texte qui liste les fichiers non Python qu&#8217;on inclura dans l&#8217;installation.</li>
<li>README.md: un fichier markdown (c&#8217;est du texte, juste un peu formaté) contiendra une présentation du package.</li>
</ul>
<p>Pour le moment nos trois fichiers sont vides.</p>
<h2>Choix des outils</h2>
<p>Une des difficultés principales dans la distribution d&#8217;un code Python, c&#8217;est l&#8217;abondance de solutions. Pour l&#8217;installeur, on peut choisir entre <code>distribute</code>, <code>setuptools</code>, <code>distutils</code> ou <code>Distutils2</code>.</p>
<p>Je vous passe les détails, mais j&#8217;ai essayé les 4. <code>distutils</code> est trop vieux. <code>distribute</code> va être remplacé par <code>distutils2</code> qui lui est encore très jeune. La seule solution qui passe partout pour le moment c&#8217;est <code>setuptools</code>. Tarek Ziade va faire la gueule, mais c&#8217;est ce que je recommande d&#8217;utiliser pour le moment. Je metterai à jour cet article pour utiliser un <em>setup.cfg</em> et des moyens plus modernes quand tout ça sera devenu la solution de facto, mais je ne vais pas pousser à la migration.</p>
<p>Donc vous allez utiliser <code>setuptools</code>.</p>
<p>Ensuite on utilise un fichier <em>MANIFEST.in</em> pour lister les fichiers non Python. On pourrait tout passer en paramètres à la main, mais le manifeste est la solution la plus productive.</p>
<p>Enfin on utilise un fichier markdown. ReST est le standard en Python, mais il est compliqué (je me suis tapé suffisament de doc sphynx pour témoigner), et pas géré par Github par défaut. Markdown ressort bien sur Pypi même sans conversion en HTML, donc on va garder ce format.</p>
<p>Oh, et ça va sans dire, mais ça va mieux en le disant, on va distribuer les fichiers sous forme de source pure, pas sous forme d&#8217;exe ou d&#8217;egg. C&#8217;est installable avec pip sur toutes les plateformes, et ça évite bien des prises de tête.</p>
<h2>Rendez votre paquets user friendly</h2>
<p>La première chose à faire, avant de mettre en ligne, c&#8217;est de rendre votre paquets facile à utiliser. Assurez-vous d&#8217;avoir les docstrings qui vont bien, et faciliter les imports.</p>
<p>Par exemple, dans notre <em>__init__.py</em>, on va rajouter:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> core <span style="color: #ff7700;font-weight:bold;">import</span> proclamer</pre></div></div>

<p>Ainsi, l&#8217;utilisateur pourra faire:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> sm_lib <span style="color: #ff7700;font-weight:bold;">import</span> proclamer</pre></div></div>

<p>au lieu de :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> sm_lib.<span style="color: black;">core</span> <span style="color: #ff7700;font-weight:bold;">import</span> proclamer</pre></div></div>

<p>Faites cela uniquement pour les fonctions et classes les plus utiles. C&#8217;est un détail, mais ça rend l&#8217;expérience plus agréable.</p>
<p>Ensuite, si l&#8217;utilisateur est dans son shell, il va utiliser l&#8217;autocompletion pour découvrir votre lib. Il va se balader, et spammer &#8220;tab&#8221; pour voir &#8220;ce qu&#8217;il y a dedans&#8221;.</p>
<p>Pour faciliter ce process, limitez ce qui est importable avec <code>__all__</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">datetime</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">datetime</span>
&nbsp;
__all__ = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'proclamer'</span><span style="color: black;">&#93;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> proclamer<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;[%s] Sam et Max, c'est bien&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #dc143c;">datetime</span>.<span style="color: black;">now</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    proclamer<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Ainsi, seul<code> proclamer()</code> sera importable depuis le module <code>core</code>. En effet, en important <code>datetime</code>, vous l&#8217;insérer dans le namespace de <code>core</code>, et donc il sera importable en faisant <code>from sm_lib.core import datetime</code>, et il apparaîtra dans l&#8217;autocompletion. Ici ça parait dérisoire, mais sur les grosses libs, ça fait beaucoup de bruit.</p>
<p><code>__all__</code> est une liste strings qui contient les noms de tout ce qu&#8217;on autorise à importer depuis ce module. Utilisez le pour rendre votre API d&#8217;import propre comme la chatte de&#8230; comme un sous neuf pardon. Désolé, par encore habitué à parler la novlang. On s&#8217;y met. On s&#8217;y met.</p>
<p>Pour finir on met les docstrings qui vont bien:</p>
<ul>
<li>une dans <em>__init__.py</em> pour décrire le package;</li>
<li>une au sommet de <em>core.py</em> pour décrire module;</li>
<li>une dans <code>proclamer()</code> pour décrire la fonction.</li>
</ul>
<p>Ainsi l&#8217;utilisateur qui va installer votre lib s&#8217;y retrouvera très facilement en utilisant la fonction <code>help()</code>. Même sans doc et hors ligne.</p>
<p><em>__init__.py</em> (on rajoute aussi l&#8217;en-tête d&#8217;encoding vu que la docstring contient des caractères non-ASCII):</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;
    Ce module proclame la bonne parole de sieurs Sam et Max. Puissent-t-ils
    retrouver une totale liberté de pensée cosmique vers un nouvel age
    reminiscent.
&quot;&quot;&quot;</span>
&nbsp;
__version__ = <span style="color: #483d8b;">&quot;0.0.1&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> core <span style="color: #ff7700;font-weight:bold;">import</span> proclamer</pre></div></div>

<p>On a aussi rajouté la version, car il n&#8217;y a rien de plus chiant que d&#8217;avoir un bug sur une lib et de ne pas savoir de quelle version il s&#8217;agit. Il va falloir maintenir cette variable à jour.</p>
<p>Et <em>core.py</em>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;
    Implémentation de la proclamation de la bonne parole.
&nbsp;
    Usage:
&nbsp;
    &gt;&gt;&gt; from sm_lib import proclamer
    &gt;&gt;&gt; proclamer()
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">datetime</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">datetime</span>
&nbsp;
__all__ = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'proclamer'</span><span style="color: black;">&#93;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> proclamer<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        Fonction de proclamation de la bonne parole. Aucun paramètre, et
        retourne None, car tout le monde say que &quot;Ex nihilo nihil&quot;
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;[%s] Sam et Max, c'est bien&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #dc143c;">datetime</span>.<span style="color: black;">now</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    proclamer<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Je vous passe le pamphlet sur les tests, c&#8217;est plusieurs articles rien que pour expliquer le pourquoi du comment. C&#8217;est mieux si vous en avez, mais si vous n&#8217;en avez pas, ne vous empêchez pas de publier, ça peut se rajouter au fur et à mesure.</p>
<p>Petite remarque en passant: je met toute la doc en français pour que vous compreniez le principe, mais si vous publiez un truc, je vous recommande chaudement de tout écrire en anglais de A à Z (variables, fonctions, modules, docstrings, comments, readme, doc, tests, etc). Sans quoi votre audience sera limitée au nombre de francophones qui programment, et en Python, et qui ont le niveau pour intéresser aux libs externes. Autant dire l&#8217;équivalent de l&#8217;audience ridicule de ce blog.</p>
<h2>README</h2>
<p>Dans le fichier README.md, qui est un fichier texte ordinnaire, assurez-vous de mettez les choses suivante:</p>
<ul>
<li>A quoi sert la lib.</li>
<li>Comment l&#8217;installer.</li>
<li>Un exempe concret d&#8217;utilisation.</li>
<li>La licence d&#8217;utilisation.</li>
<li>Un lien vers la doc si elle existe.</li>
</ul>
<p>Nous allons mettre le texte au format markdown. C&#8217;est <a href="http://daringfireball.net/projects/markdown/basics">un format très simple</a> qui a le double avantage d&#8217;être automatiquement transformé en HTML par Github, et qui est bien lisible même quand il reste brut, tel qu&#8217;il sera affiché sur Pypi.</p>
<p>Dans notre cas, README.md va ressembler à un mélange des docstrings, un peu amélioré:</p>
<pre>SM Lib - Proclame la bonne parole de sieurs Sam et Max
========================================================

Ce module proclame la bonne parole de sieurs Sam et Max. Puissent-t-ils
retrouver une totale liberté de pensée cosmique vers un nouvel age
reminiscent.

Vous pouvez l'installer avec pip:

    pip install sm_lib

Exemple d'usage:

    >>> from sm_lib import proclamer
    >>> proclamer()

Ce code est sous licence <a href="https://en.wikipedia.org/wiki/WTFPL">WTFPL</a>.</pre>
<h2>MANIFEST.in</h2>
<p>Le fichier va contenir une liste de tous les fichiers non Python qu&#8217;on veut inclure dans le package. Dans notre cas, la photo et le README.</p>
<pre>include *.md
recursive-include sm_lib *.jpg</pre>
<p>La syntaxe est elle aussi très simple, et utilise la notation des globs &#8220;*&#8221;.</p>
<p>La première ligne dit d&#8217;inclure tout fichier dans le nom est &#8220;n&#8217;importe quoi&#8221;.md. Il va inclure le README.<br />
La seconde ligne dit d&#8217;inclure récursivement tout fichier dans le dossier sm_lib et ses sous-dossiers qui est nommé &#8220;n&#8217;importe quoi&#8221;.jpg. Il va inclure notre photo.</p>
<p>On peut mettre plusieurs lignes, et plusieurs motifs sur chaque ligne. Il n&#8217;est donc pas rare de voir des fichiers qui ressemblent à ça:</p>
<pre>include *.txt *.rst
recursive-include dir1 *.txt *.rst
recursive-include dir2 *.png *.jpg *.gif
recursive-include dir2 *.css *.js *.coffee</pre>
<h2>Setup.py</h2>
<p>C&#8217;est la partie difficile. Le fichier <em>setup.py</em> contient une fonction qui va magiquement installer votre lib, et il faut lui passer des paramètres et l&#8217;appeler. Le problème c&#8217;est que cette fonction compte 34 (à ma connaissance) arguments.</p>
<p>Vous pouvez mettre n&#8217;importe quel code Python dans le <em>setup.py</em>, mais généralement la fonction <code>setup()</code> suffit.</p>
<p>Je vais mettre dans ce <em>setup.py</em> les paramètres que vous utiliserez les plus souvent:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> setuptools <span style="color: #ff7700;font-weight:bold;">import</span> setup, find_packages
&nbsp;
<span style="color: #808080; font-style: italic;"># notez qu'on import la lib</span>
<span style="color: #808080; font-style: italic;"># donc assurez-vous que l'importe n'a pas d'effet de bord</span>
<span style="color: #ff7700;font-weight:bold;">import</span> sm_lib
&nbsp;
<span style="color: #808080; font-style: italic;"># Ceci n'est qu'un appel de fonction. Mais il est trèèèèèèèèèèès long</span>
<span style="color: #808080; font-style: italic;"># et il comporte beaucoup de paramètres</span>
setup<span style="color: black;">&#40;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># le nom de votre bibliothèque, tel qu'il apparaitre sur pypi</span>
    name=<span style="color: #483d8b;">'sm_lib'</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># la version du code</span>
    version=sm_lib.__version__,
&nbsp;
    <span style="color: #808080; font-style: italic;"># Liste les packages à insérer dans la distribution</span>
    <span style="color: #808080; font-style: italic;"># plutôt que de le faire à la main, on utilise la foncton</span>
    <span style="color: #808080; font-style: italic;"># find_packages() de setuptools qui va cherche tous les packages</span>
    <span style="color: #808080; font-style: italic;"># python recursivement dans le dossier courant.</span>
    <span style="color: #808080; font-style: italic;"># C'est pour cette raison que l'on a tout mis dans un seul dossier:</span>
    <span style="color: #808080; font-style: italic;"># on peut ainsi utiliser cette fonction facilement</span>
    packages=find_packages<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># votre pti nom</span>
    author=<span style="color: #483d8b;">&quot;Sam et Max&quot;</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># Votre email, sachant qu'il sera publique visible, avec tous les risques</span>
    <span style="color: #808080; font-style: italic;"># que ça implique.</span>
    author_email=<span style="color: #483d8b;">&quot;lesametlemax@gmail.com&quot;</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># Une description courte</span>
    description=<span style="color: #483d8b;">&quot;Proclame la bonne parole de sieurs Sam et Max&quot;</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># Une description longue, sera affichée pour présenter la lib</span>
    <span style="color: #808080; font-style: italic;"># Généralement on dump le README ici</span>
    long_description=<span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'README.md'</span><span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># Vous pouvez rajouter une liste de dépendances pour votre lib</span>
    <span style="color: #808080; font-style: italic;"># et même préciser une version. A l'installation, Python essayera de</span>
    <span style="color: #808080; font-style: italic;"># les télécharger et les installer.</span>
    <span style="color: #808080; font-style: italic;">#</span>
    <span style="color: #808080; font-style: italic;"># Ex: [&quot;gunicorn&quot;, &quot;docutils &gt;= 0.3&quot;, &quot;lxml==0.5a7&quot;]</span>
    <span style="color: #808080; font-style: italic;">#</span>
    <span style="color: #808080; font-style: italic;"># Dans notre cas on en a pas besoin, donc je le commente, mais je le</span>
    <span style="color: #808080; font-style: italic;"># laisse pour que vous sachiez que ça existe car c'est très utile.</span>
    <span style="color: #808080; font-style: italic;"># install_requires= ,</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Active la prise en compte du fichier MANIFEST.in</span>
    include_package_data=<span style="color: #008000;">True</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># Une url qui pointe vers la page officielle de votre lib</span>
    url=<span style="color: #483d8b;">'http://github.com/sametmax/sm_lib'</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># Il est d'usage de mettre quelques metadata à propos de sa lib</span>
    <span style="color: #808080; font-style: italic;"># Pour que les robots puissent facilement la classer.</span>
    <span style="color: #808080; font-style: italic;"># La liste des marqueurs autorisées est longue, alors je vous</span>
    <span style="color: #808080; font-style: italic;"># l'ai mise sur 0bin: http://is.gd/AajTjj</span>
    <span style="color: #808080; font-style: italic;">#</span>
    <span style="color: #808080; font-style: italic;"># Il n'y a pas vraiment de règle pour le contenu. Chacun fait un peu</span>
    <span style="color: #808080; font-style: italic;"># comme il le sent. Il y en a qui ne mettent rien.</span>
    classifiers=<span style="color: black;">&#91;</span>
        <span style="color: #483d8b;">&quot;Programming Language :: Python&quot;</span>,
        <span style="color: #483d8b;">&quot;Development Status :: 1 - Planning&quot;</span>,
        <span style="color: #483d8b;">&quot;License :: OSI Approved&quot;</span>,
        <span style="color: #483d8b;">&quot;Natural Language :: French&quot;</span>,
        <span style="color: #483d8b;">&quot;Operating System :: OS Independent&quot;</span>,
        <span style="color: #483d8b;">&quot;Programming Language :: Python :: 2.7&quot;</span>,
        <span style="color: #483d8b;">&quot;Topic :: Communications&quot;</span>,
    <span style="color: black;">&#93;</span>,
&nbsp;
&nbsp;
    <span style="color: #808080; font-style: italic;"># C'est un système de plugin, mais on s'en sert presque exclusivement</span>
    <span style="color: #808080; font-style: italic;"># Pour créer des commandes, comme &quot;django-admin&quot;.</span>
    <span style="color: #808080; font-style: italic;"># Par exemple, si on veut créer la fabuleuse commande &quot;proclame-sm&quot;, on</span>
    <span style="color: #808080; font-style: italic;"># va faire pointer ce nom vers la fonction proclamer(). La commande sera</span>
    <span style="color: #808080; font-style: italic;"># créé automatiquement. </span>
    <span style="color: #808080; font-style: italic;"># La syntaxe est &quot;nom-de-commande-a-creer = package.module:fonction&quot;.</span>
    entry_points = <span style="color: black;">&#123;</span>
        <span style="color: #483d8b;">'console_scripts'</span>: <span style="color: black;">&#91;</span>
            <span style="color: #483d8b;">'proclame-sm = sm_lib.core:proclamer'</span>,
        <span style="color: black;">&#93;</span>,
    <span style="color: black;">&#125;</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># A fournir uniquement si votre licence n'est pas listée dans &quot;classifiers&quot;</span>
    <span style="color: #808080; font-style: italic;"># ce qui est notre cas</span>
    license=<span style="color: #483d8b;">&quot;WTFPL&quot;</span>,
&nbsp;
    <span style="color: #808080; font-style: italic;"># Il y a encore une chiée de paramètres possibles, mais avec ça vous</span>
    <span style="color: #808080; font-style: italic;"># couvrez 90% des besoins</span>
&nbsp;
<span style="color: black;">&#41;</span></pre></div></div>

<h2>Tester si tout marche bien</h2>
<p>Si vous publiez du code, je vais partir du principe que vous utilisez au moins un <a href="http://sametmax.com/les-environnement-virtuels-python-virtualenv-et-virtualenvwrapper/">virtualenv</a> :-)</p>
<p>Donc, activez un environnement de test, et dans le dossier contenant <em>setup.py</em>, faites:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">python setup.py <span style="color: #c20cb9; font-weight: bold;">install</span></pre></div></div>

<p>Normalement votre lib devrait s&#8217;insaller dans votre env proprement. Vous devriez pouvoir faire dans un shell Python:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> sm_lib <span style="color: #ff7700;font-weight:bold;">import</span> proclamer
<span style="color: #66cc66;">&gt;&gt;&gt;</span> proclamer<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">2012</span>-<span style="color: #ff4500;">11</span>-<span style="color: #ff4500;">16</span> <span style="color: #ff4500;">13</span>:06:<span style="color: #ff4500;">58.128545</span><span style="color: black;">&#93;</span> Sam et Max, c<span style="color: #483d8b;">'est bien</span></pre></div></div>

<p>Et comme on a créé une commande, on doit aussi pouvoir faire depuis un terminal:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ proclame-sm
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">2012</span>-<span style="color: #000000;">11</span>-<span style="color: #000000;">16</span> <span style="color: #000000;">13</span>:08:<span style="color: #000000;">18.763732</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> Sam et Max, c<span style="color: #ff0000;">'est bien</span></pre></div></div>

<p>Si vous regardez dans votre virtualenv, vous verrez que votre package a été ajouté. Sur ma machine il se trouve par exemple à <em>~/.virtualenvs/test/lib/python2.7/site-packages/sm_lib-0.0.1-py2.7.egg/sm_lib</em>.</p>
<p>La photo doit-être dedans, ainsi que le code Python. La photo est un exemple important à comprendre et à faire marcher car c&#8217;est le manifeste que vous utiliserez pour tous les fichiers non Python: CSS, Javascript, Documentation, Images, Xml, Json, etc. </p>
<h2>Publier sur Pypi</h2>
<p>Cela va vous paraitre étonnant, mais tout le monde peut publier sur Pypi. Pourvu que le nom soit disponible, vous pouvez en fait uploader n&#8217;importe quoi. Même une lib de test comme celle-ci.</p>
<p>Entrez la commande (il faut avoir accès à internet):</p>
<p><code>$ python setup.py register</code></p>
<p>Ceci va inscrire votre lib dans leur listing. Et donnera une sortie qui ressemble à ça:</p>
<pre>running register
running egg_info
writing sm_lib.egg-info/PKG-INFO
writing top-level names to sm_lib.egg-info/top_level.txt
writing dependency_links to sm_lib.egg-info/dependency_links.txt
writing entry points to sm_lib.egg-info/entry_points.txt
reading manifest file 'sm_lib.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'sm_lib.egg-info/SOURCES.txt'
running check
We need to know who you are, so please choose either:
 1. use your existing login,
 2. register as a new user,
 3. have the server generate a new password for you (and email it to you), or
 4. quit
Your selection [default 1]: </pre>
<p>Choissisez 2. Il va vous permettre de créer un compte. Quand il vous demandera de sauvegarder vos identifiants pour un usage future, répondre oui vous permettra de ne pas rentrer votre mot de passe à chaque upload.</p>
<p>La prochaine fois vous pourrez choisir 1, puisque vous aurez un compte.</p>
<p>Si ça se coupe, relancez juste la commande. Le but étant d&#8217;obtenir ça:</p>
<pre>Registering sm_lib to http://pypi.python.org/pypi
Server response (200): OK</pre>
<p>Ce qui signifie que votre lib est inscrite sur Pypi (et que donc le nom était disponible, sinon il vous enverra chier et vous avez plus qu&#8217;à renommer votre lib).</p>
<p>Puis, il faut créer une distribution source (sdist) et le mettre en ligne (upload):</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">python setup.py sdist upload</pre></div></div>

<p>Et voilà, votre lib est en ligne et installable avec pip !</p>
<p>Voici la <a href="http://pypi.python.org/pypi/sm_lib/">page pypi</a>, et <a href="https://github.com/sametmax/sm_lib">la page gitub</a> (ce qui n&#8217;a rien à voir, mais si vous voulez le code source&#8230;).</p>
<p>C&#8217;est finit. Si vous voulez uploader une nouvelle version de votre lib, il faut changer <code>__version__</code> car Pypi n&#8217;accepte pas deux fois la même version.</p>


feed_id: http://sametmax.com/?p=3122
title: “ERROR: VIRTUALENVWRAPPER_LOG_DIR is not set” et “ImportError: cannot import name urandom”
uri: ERROR-VIRTUALENVWRAPPER_LOG_DIR-is-not-set-et-ImportError-c
url:
http://sametmax.com/error-virtualenvwrapper_log_dir-is-not-set-et-importerror-cannot-import-name-urandom/

content:
<p>Petits bugs pour <a href="http://sametmax.com/les-environnement-virtuels-python-virtualenv-et-virtualenvwrapper/">virtualenwrapper</a> sous Ubuntu. Ca se corrige facilement. </p>
<p>Ajoutez dans <em>.bashrc</em> pour corriger le premier:</p>
<p><code>export VIRTUALENVWRAPPER_LOG_DIR="$WORKON_HOME"<br />
export VIRTUALENVWRAPPER_HOOK_DIR="$WORKON_HOME"</code></p>
<p>Pour le second, il faut relancer la création de l&#8217;env, sur l&#8217;env lui-même. Si votre env s&#8217;appelle &#8220;mon_env&#8221;, faites:</p>
<p><code>mkvirtualenv mon_env</code></p>
<p>Il faut les mêmes paramètres qu&#8217;à la création de l&#8217;env.</p>


feed_id: http://sametmax.com/?p=3150
title: Arnaque sur le bon coin – numéro surtaxé à rappeler
uri: Arnaque-sur-le-bon-coin-numéro-surtaxé-à-rappeler
url: http://sametmax.com/arnaque-sur-le-bon-coin-numero-surtaxe-a-rappeler/
content:
<p>L&#8217;autre jour un proche a décidé de vendre son véhicule, comme la plupart des gens il se rend sur leboncoin.fr pensant avoir une réponse rapide. Pour aller plus vite il a laissé son numéro de téléphone.</p>
<p>24 heures après pas une touche mais il reçoit un sms:</p>
<blockquote><p>Nous somme interressés par l&#8217;annonce de votre voiture sur leboncoin, veuillez nous contacter au 08&#8230;&#8230; </p></blockquote>
<p>Coup de bol il a flairé l&#8217;arnaque mais imaginez le pauvre type qui doit vendre à tout prix un truc et qui reçoit ça, l&#8217;envie de vendre, le côté pressé, etc&#8230;<br />
Le taux de transformation doit être super.<br />
Si en plus au bout on a un répondeur qui vous demande de patienter ou d&#8217;appuyer sur la touche 5 pour être mis en relation avec un interlocuteur&#8230;<br />
En plus le sms était bien personalisé (nom du site, type de bien vendu).</p>
<p><strong>Pour rappel:</strong><br />
Les numéros surtaxés commencent en général par 08 et vous prélèvent 1 eur ou plus à l&#8217;appel + 30/40 cents par minutes sur votre facture téléphonique, les tarifs peuvent varier.</p>
<p>L&#8217;envoi de sms par gros volumes est de l&#8217;ordre de quelques centimes (0.06 voire moins) alors que l&#8217;arnaque peut rapporter jusquà 80, 90 % de l&#8217;appel (1 euros ou plus) et autant pour chaque minutes passées. Y a de la maille à se faire&#8230;</p>
<p>Qu&#8217;est-ce que je suis bien depuis que j&#8217;ai plus de mobile&#8230;</p>


feed_id: http://sametmax.com/?p=3155
title: Internet Explorer 6, 7, 8, 9 Sous Mac/Linux Facilement avec VMWare Fusion
uri: Internet-Explorer-6-7-8-9-Sous-Mac-Linux-Facilement-avec-VMWare-Fus
url: http://sametmax.com/internet-explorer-6-7-8-9-sous-maclinux-facilement/
content:
<p>Quand on developpe des applications web on doit s&#8217;assurer de la compatibilité de ces dernières avec les différents navigateurs du marché. Jusqu&#8217;à présent sous MAC/Linux c&#8217;était pas évident de tester son application sur Internet Explorer.</p>
<p>J&#8217;ai essayé <a href="http://www.codeweavers.com/products/">cross-over</a> sous MAC qui ne vaut pas le coup à mes yeux (trop lent, plantage, pas compatible pour certaines versions d&#8217;IE, etc.), <a href="http://www.winehq.org/">Wine</a> sous Linux dont cross-over est un dérivé il me semble, mêmes galères.<br />
Il y a aussi <a href="http://www.my-debugbar.com/wiki/IETester/HomePage">IETester</a> qui a l&#8217;air pas mal pour avoir toutes les versions d&#8217;IE sur un seul navigateur mais il ne marche que sous Windows.</p>
<p>Les choses ont changées et Microsoft propose désormais gratuitement des Images de son Os Windows avec la version IE qui va bien.<br />
La seule contrainte est qu&#8217;il faut posséder VMWare (<a href="https://www.virtualbox.org/">ou VirtualBox</a> GRATUIT), je conseille la <a href="http://www.vmware.com/products/fusion/overview.html">version 5 pour 50 euros</a> qui a un mode magique, le mode &#8220;Unity&#8221; qui fusionne votre Os émulé avec votre Os hôte, j&#8217;ai dans mon dock Mac une icône IE8, c&#8217;est trop mignon, fluide et pratique.<br />
Une chose non négligeable c&#8217;est le copier/coller qui marche entre les deux OS.</p>
<div id="attachment_3156" class="wp-caption aligncenter" style="width: 474px"><a href="http://sametmax.com/wp-content/uploads/2012/11/vmware.jpeg"?9d7bd4"><img class=" wp-image-3156 " title="Vmware et le mode Unity" src="http://sametmax.com/wp-content/uploads/2012/11/vmware.jpeg"?9d7bd4" alt="" width="464" height="290" /></a><p class="wp-caption-text">Pratique pour voir si son site fonctionne sous IE depuis son Mac</p></div>
<p><strong><br />
Installation:</strong></p>
<p>Rendez-vous chez Microsoft et <a href="http://www.microsoft.com/en-us/download/details.aspx?displaylang=fr&#038;id=11575">téléchargez la version qui vous convient</a></p>
<p>Une fois les archives téléchargées vous les décompressées (avec <a href="http://wakaba.c3.cx/s/apps/unarchiver.html">The unarchiver</a> sous Mac)</p>
<p>Dans VMWare vous sélectionnez &#8220;Ajouter > Importer&#8221; et vous importer l&#8217;image téléchargée, c&#8217;est celle qui comporte l&#8217;extension VHD (ex: Win7_IE8.vhd). Il va vous demander de convertir l&#8217;image etc, faites mouliner.</p>
<p><strong>Attention:</strong></p>
<p>Le mot de passe des OS est Password1 à taper en clavier QWERTY, si vous n&#8217;y arrivez pas, cliquez à gauche à l&#8217;écran d&#8217;accueil Windows sur l&#8217;espèce de <a href="http://imgur.com/96Ta0">petite roue </a>et sélectionnez &#8220;Show keyboard&#8221;, un clavier virtuel va s&#8217;afficher et vous pourrez cliquer sur les touches.</p>
<p>Passez l&#8217;activation de windows il n&#8217;y en a pas besoin.</p>
<p>Pour éviter que sa copie arrive à expiration le mieux est de faire un <a href="http://www.vmware.com/support/ws55/doc/ws_preserve_sshot_taking.html">Snapshot</a> (sauvegarde de l&#8217;état de la Machine virtuelle à un instant T) dès la première installation de votre machine virtuelle.</p>
<p>Je dois dire que c&#8217;est plutôt sympa, car je peux coder sur mon Mac tout en testant le résultat sous IE comme si c&#8217;était une appli Mac.</p>
<p>NB: Si vous lancez un serveur web sous votre Mac et n&#8217;arrivez pas à y acceder depuis le navigateur IE, lancez le serveur sur le port 80 et l&#8217;ip de votre machine (192.168&#8230;..) </p>


feed_id: http://sametmax.com/?p=2703
title: Mail bien réel d’un client
uri: Mail-bien-réel-d-un-client
url: http://sametmax.com/mail-bien-reel-dun-client/
content:
<blockquote><p>J&#8217;ai demandé a ma sœur et mes parents et ils trouvent le rouge agressif, ils ont l&#8217;impression qu&#8217;on les force a faire qq chose. Peux tu faire une version comme suit qui nous permettra de tester ce que nous trouvons le mieux:<br />
Le nom du vendeur: bleu<br />
Son objet: vert<br />
Nom de la personne connecté: orange<br />
Nom du bénéficiaire: violet<br />
Date fin de la vente: jaune<br />
En blanc: Le texte autour des liens</p></blockquote>
<p>Pour vous remettre dans le contexte, ce site de vente d&#8217;objets possède un design avec la moitié du fond de body en noir, l&#8217;autre moitié en blanc. Et il n&#8217;y a aucun lien rouge nul part (il y a des liens marrons, je supposes qu&#8217;il parle de ça&#8230;).</p>
<p>Bref, je me suis retenu répondre &#8220;Et les objets rares, je les met en doré, comme ça on a la parité avec Diablo ?&#8221;.</p>


feed_id: http://sametmax.com/?p=3179
title: Installer Adobe Air et Balsamiq Mockup sur Ubuntu 12.10 64 bits
uri: Installer-Adobe-Air-et-Balsamiq-Mockup-sur-Ubuntu-12-10-64-bits
url: http://sametmax.com/installer-adobe-air-et-balsamiq-mockup-sur-ubuntu-12-10-64-bits/
content:
<p>Pour installer <a href="http://www.balsamiq.com/">Balsamiq</a>, il faut Adobe Air, qui bien entendu ne fonctionne pas out of the box et nous pond la magnifique erreur:</p>
<p><code>error while loading shared libraries: libgtk-x11-2.0.so.0: cannot open shared object file: No such file or directory</code></p>
<p>Etape 1: on installe les libs de compatibilité 32 vers 64 bits:</p>
<p><code>sudo apt-get install ia32-libs-gtk</code></p>
<p>Je vous préviens, ça va faire mal, avec vingt-douze paquets à installer pour presque 100 Mo de téléchargement.</p>
<p>Etape 2: <a href="http://airdownload.adobe.com/air/lin/download/2.6/AdobeAIRInstaller.bin">télécharger Adobe Air</a> et le rendre éxécutable</p>
<p>On peut le récupérer ici, et ensuite on chmode tout ça:</p>
<p><code>chmod +x AdobeAIRInstaller.bin</code></p>
<p>A ce stade, si vous lancez l&#8217;installeur, il va vous sortir:</p>
<blockquote><p>Adobe AIR n&#8217;a pas pu être installé. Installez Gnome Keyring ou KDE KWallet avant d&#8217;installer Adobe AIR.</p></blockquote>
<p>Etape 3: ruser un peu en faisant quelques symlink:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">ln</span> <span style="color: #660033;">-s</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>i386-linux-gnu<span style="color: #000000; font-weight: bold;">/</span>libgnome-keyring.so.0 <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libgnome-keyring.so.0
$ <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">ln</span> <span style="color: #660033;">-s</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>i386-linux-gnu<span style="color: #000000; font-weight: bold;">/</span>libgnome-keyring.so.0.2.0 <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>libgnome-keyring.so.0.2.0
$ .<span style="color: #000000; font-weight: bold;">/</span>AdobeAIRInstaller.bin</pre></div></div>

<p>Si tout se passe bien Adore Air a été installé avec succès, et vous pouvez maintenant télécharger l&#8217;installeur de Balsamiq, mais la version <a href="http://builds.balsamiq.com/b/mockups-desktop/MockupsForDesktop.air">air</a>, pas la version deb. Tout devrait s&#8217;installer dans la joie et l&#8217;allégresse.</p>


feed_id: http://sametmax.com/?p=3165
title: Authoriser GoogleBot à crawler certains contenus de votre site sous Django avec Reverse DNS Lookup
uri: Authoriser-GoogleBot-à-crawler-certains-contenus-de-votre-site-sous-D
url:
http://sametmax.com/authoriser-googleboot-a-crawler-certains-contenus-de-votre-site-sous-django-avec-reverse-dns-lookup/

content:
<p>Si vous avez du contenu <a href="https://support.google.com/webmasters/bin/answer.py?hl=en&#038;answer=183668&#038;ctx=cb&#038;src=cb&#038;cbid=1bw4t9jciznos&#038;cbrank=3#2">rich media</a> que vous voulez le faire indexer par Google vous allez devoir proposer dans votre <a href="https://support.google.com/webmasters/bin/answer.py?hl=en&#038;answer=156184&#038;topic=8476&#038;ctx=topic">Sitemap</a> un lien vers votre contenu video ou image. Et vous n&#8217;avez certainement pas envie que tout le monde puisse puiser dedans.</p>
<p>D&#8217;après La doc Google, le rich media c&#8217;est l&#8217;avenir, micro-datas, sitemap video, etc&#8230; faut être à la page.<br />
Du coup vous avez envie que votre contenu se retrouve indexé par Google et rien que lui, ou pas lui et rien que Yahoo, ou pas Yahoo et rien que Bing, ou pas que Bing mais rien que Yahoo et Google et aussi un peu Bing finalement mais surtout pas Da silva&#8230;<a href="http://www.youtube.com/watch?v=wlPhNy8nHHU">Je l&#8217;aime pas Da silva</a>&#8230;</p>
<p>Google <a href="https://support.google.com/webmasters/bin/answer.py?hl=en&#038;answer=80553">conseille d&#8217;utiliser le Reverse DNS lookup</a>. En gros de récupérer le nom de domaine du robot en fonction de l&#8217;IP qui vous crawle.</p>
<p><strong>On fait une fonction qui check l&#8217;ip et on gère le retour dans la vue Django:</strong></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> allowed_bot<span style="color: black;">&#40;</span>ip<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        Do a reverse dns lookup on IP to get domain 
        and check if it is a bot from know search engines
    &quot;&quot;&quot;</span>
    allowed_bots = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'.msn.com'</span>, <span style="color: #483d8b;">'.yahoo.com'</span>, <span style="color: #483d8b;">'.googlebot.com'</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #dc143c;">socket</span>.<span style="color: black;">setdefaulttimeout</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
        host = <span style="color: #dc143c;">socket</span>.<span style="color: black;">gethostbyaddr</span><span style="color: black;">&#40;</span>ip<span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #dc143c;">socket</span>.<span style="color: black;">herror</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">False</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">for</span> bot <span style="color: #ff7700;font-weight:bold;">in</span> allowed_bots:
        <span style="color: #ff7700;font-weight:bold;">if</span> host.<span style="color: black;">find</span><span style="color: black;">&#40;</span>bot<span style="color: black;">&#41;</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">0</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> ma_vue<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
       redirect to video to index
    &quot;&quot;&quot;</span>
    ip = request.<span style="color: black;">META</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'REMOTE_ADDR'</span>, <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> allowed_bot<span style="color: black;">&#40;</span>ip<span style="color: black;">&#41;</span>: 
        <span style="color: #ff7700;font-weight:bold;">return</span> http.<span style="color: black;">HttpResponseRedirect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;http://monsite.com/video/meme.flv&quot;</span><span style="color: black;">&#41;</span> 
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> http.<span style="color: black;">http404</span></pre></div></div>

<p>Cette méthode n&#8217;est pas à utiliser pour une vue qui retourne une page entière car ça ferait une requête à chaque fois, mais pour du contenu qu&#8217;on a mis à dispo dans un Sitemap comme un player flv .</p>
<p>Exemple de sitemap avec la balise video :</p>

<div class="wp_syntax"><div class="code"><pre class="" style="font-family:monospace;">&nbsp;
    &lt;video:video&gt;      
      &lt;video:player_loc allow_embed=&quot;yes&quot;&gt;http://www.monsite.com/player.swf?file=/play/<span style="">76293</span>.xml&lt;/video:player_loc&gt;
      &lt;video:thumbnail_loc&gt;http://www.monsite.com/video/<span style="">76293</span>/thumbnail.jpg&lt;/video:thumbnail_loc&gt;
      &lt;video:title&gt;mémé à l'île de la raie&lt;/video:title&gt;
      &lt;video:description&gt;Aller mémé te laisse pas ratrapper par la raie !&lt;/video:description&gt;
    &lt;/video:video&gt;</pre></div></div>

<p>Il y a d&#8217;autres solutions comme récupérer la liste de toutes les IPs des crawlers et les passer à Nginx en adaptant un peu <a href="http://sametmax.com/nginx-et-limitation-de-connexion-par-ip-avec-limit_conn_zone/" title="nginx et limitation de connexion par IP avec limit_conn_zone">cet article</a></p>
<p>NB: Si vous utilisez nginx en tant que proxy n&#8217;oubliez pas d&#8217;inclure proxy_set_header pour renvoyer la bonne IP du client:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">location <span style="color: #000000; font-weight: bold;">/</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
  proxy_pass        http:<span style="color: #000000; font-weight: bold;">//</span>monsite_cherrypy;
  proxy_set_header  X-Real-IP  <span style="color: #007800;">$remote_addr</span>;
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></div></div>


feed_id: http://sametmax.com/?p=3197
title: Ces bébés animaux qui nous font craquer
uri: Ces-bébés-animaux-qui-nous-font-craquer
url: http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/
content:
<p><strong>On passe en mode Bisounours ! </strong><br />
Allez chercher un bon verre de cacao chaud ou un thé à la banane.<br />
On va passer en revue ces petites bestioles qui nous font craquer.</p>

<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/ecureuil/' title='ecureuil'><img width="600" height="399" src="http://sametmax.com/wp-content/uploads/2012/11/ecureuil.jpg"?9d7bd4" class="attachment-large" alt="J&#039;ai un rancard" title="ecureuil" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/lezard/' title='lezard'><img width="450" height="600" src="http://sametmax.com/wp-content/uploads/2012/11/lezard.jpg"?9d7bd4" class="attachment-large" alt="V" title="lezard" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/geco/' title='geco'><img width="500" height="378" src="http://sametmax.com/wp-content/uploads/2012/11/geco.jpg"?9d7bd4" class="attachment-large" alt="Richard Géco" title="geco" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/pandas/' title='pandas'><img width="600" height="378" src="http://sametmax.com/wp-content/uploads/2012/11/pandas.jpg"?9d7bd4" class="attachment-large" alt="Vous m&#039;en mettrez 2 de côté" title="pandas" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/adorable-animal-baby-animals-blue-cat-favim-com-303515/' title='adorable-animal-baby-animals-blue-cat-Favim.com-303515'><img width="500" height="332" src="http://sametmax.com/wp-content/uploads/2012/11/adorable-animal-baby-animals-blue-cat-Favim.com-303515.jpg"?9d7bd4" class="attachment-large" alt="des ptits chatons...miam" title="adorable-animal-baby-animals-blue-cat-Favim.com-303515" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/adorable-animals-cute-love-penguins-favim-com-42160/' title='adorable-animals-cute-love-penguins-Favim.com-42160'><img width="400" height="265" src="http://sametmax.com/wp-content/uploads/2012/11/adorable-animals-cute-love-penguins-Favim.com-42160.jpg"?9d7bd4" class="attachment-large" alt="penguins in love" title="adorable-animals-cute-love-penguins-Favim.com-42160" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/bunny2/' title='bunny2'><img width="300" height="285" src="http://sametmax.com/wp-content/uploads/2012/11/bunny2.jpg"?9d7bd4" class="attachment-large" alt="mmmmmm..." title="bunny2" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/louttre/' title='louttre'><img width="600" height="405" src="http://sametmax.com/wp-content/uploads/2012/11/louttre.jpg"?9d7bd4" class="attachment-large" alt="Une louttre" title="louttre" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/cannards/' title='cannards'><img width="600" height="508" src="http://sametmax.com/wp-content/uploads/2012/11/cannards.jpg"?9d7bd4" class="attachment-large" alt="des ptits cannards" title="cannards" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/babyseahorse/' title='babyseahorse'><img width="321" height="333" src="http://sametmax.com/wp-content/uploads/2012/11/babyseahorse.jpg"?9d7bd4" class="attachment-large" alt="hippopocampe de mer..." title="babyseahorse" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/tiny-adorable-animals-15/' title='Tiny-Adorable-Animals-15'><img width="600" height="450" src="http://sametmax.com/wp-content/uploads/2012/11/Tiny-Adorable-Animals-15.jpg"?9d7bd4" class="attachment-large" alt="chais pas..." title="Tiny-Adorable-Animals-15" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/poissoncoffre/' title='poissoncoffre'><img width="500" height="375" src="http://sametmax.com/wp-content/uploads/2012/11/poissoncoffre.jpg"?9d7bd4" class="attachment-large" alt="J&#039;en sais rien" title="poissoncoffre" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/turtle/' title='turtle'><img width="400" height="267" src="http://sametmax.com/wp-content/uploads/2012/11/turtle.jpg"?9d7bd4" class="attachment-large" alt="Tortue génial" title="turtle" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/poulpe/' title='poulpe'><img width="600" height="450" src="http://sametmax.com/wp-content/uploads/2012/11/poulpe.jpg"?9d7bd4" class="attachment-large" alt="Un poulpinet" title="poulpe" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/hedgehog41/' title='hedgehog41'><img width="500" height="373" src="http://sametmax.com/wp-content/uploads/2012/11/hedgehog41.jpg"?9d7bd4" class="attachment-large" alt="Si c&#039;est pas mimi ce hérisson" title="hedgehog41" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/chauvesouris/' title='chauvesouris'><img width="600" height="400" src="http://sametmax.com/wp-content/uploads/2012/11/chauvesouris.jpg"?9d7bd4" class="attachment-large" alt="Batman à la maternité" title="chauvesouris" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/cuteowl/' title='cuteowl'><img width="400" height="488" src="http://sametmax.com/wp-content/uploads/2012/11/cuteowl.jpg"?9d7bd4" class="attachment-large" alt="cte chouette..." title="cuteowl" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/baby-hamster/' title='baby hamster'><img width="468" height="351" src="http://sametmax.com/wp-content/uploads/2012/11/baby-hamster.jpg"?9d7bd4" class="attachment-large" alt="un hamster" title="baby hamster" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/bebehippo/' title='bebehippo'><img width="600" height="400" src="http://sametmax.com/wp-content/uploads/2012/11/bebehippo.jpg"?9d7bd4" class="attachment-large" alt="Un bébé hippo (en noir)" title="bebehippo" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/babydog/' title='babydog'><img width="417" height="600" src="http://sametmax.com/wp-content/uploads/2012/11/babydog.jpg"?9d7bd4" class="attachment-large" alt="Un...chien" title="babydog" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/tiny_adorable_animals_25_thumb/' title='tiny_adorable_animals_25_thumb'><img width="240" height="200" src="http://sametmax.com/wp-content/uploads/2012/11/tiny_adorable_animals_25_thumb.jpg"?9d7bd4" class="attachment-large" alt="encore un poulpinet" title="tiny_adorable_animals_25_thumb" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/orni/' title='orni'><img width="600" height="400" src="http://sametmax.com/wp-content/uploads/2012/11/orni.jpg"?9d7bd4" class="attachment-large" alt="Ornithorynque" title="orni" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/cute-sea-animals-2/' title='cute-sea-animals-2'><img width="512" height="441" src="http://sametmax.com/wp-content/uploads/2012/11/cute-sea-animals-2.jpg"?9d7bd4" class="attachment-large" alt="Une raie" title="cute-sea-animals-2" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/putois/' title='putois'><img width="500" height="400" src="http://sametmax.com/wp-content/uploads/2012/11/putois.jpg"?9d7bd4" class="attachment-large" alt="Pépé le putois" title="putois" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/33934-bigthumbnail/' title='33934-bigthumbnail'><img width="450" height="301" src="http://sametmax.com/wp-content/uploads/2012/11/33934-bigthumbnail.jpg"?9d7bd4" class="attachment-large" alt="tiger wood ?" title="33934-bigthumbnail" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/cameleon3/' title='cameleon3'><img width="500" height="375" src="http://sametmax.com/wp-content/uploads/2012/11/cameleon3.jpg"?9d7bd4" class="attachment-large" alt="Reviens Léon, j&#039;ai du Camay" title="cameleon3" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/animal-baby-cute-koala-koala-bear-favim-com-345696/' title='animal-baby-cute-koala-koala-bear-Favim.com-345696'><img width="500" height="383" src="http://sametmax.com/wp-content/uploads/2012/11/animal-baby-cute-koala-koala-bear-Favim.com-345696.jpg"?9d7bd4" class="attachment-large" alt="un koala albinos :)" title="animal-baby-cute-koala-koala-bear-Favim.com-345696" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/frog/' title='frog'><img width="241" height="210" src="http://sametmax.com/wp-content/uploads/2012/11/frog.jpeg"?9d7bd4" class="attachment-large" alt="Tranquillou" title="frog" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/adorable-animals-mad-ya/' title='adorable-animals-mad-ya'><img width="600" height="489" src="http://sametmax.com/wp-content/uploads/2012/11/adorable-animals-mad-ya.jpg"?9d7bd4" class="attachment-large" alt="mmm :)" title="adorable-animals-mad-ya" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/adorable-animal-baby-cute-sea-favim-com-182890/' title='adorable-animal-baby-cute-sea-Favim.com-182890'><img width="400" height="317" src="http://sametmax.com/wp-content/uploads/2012/11/adorable-animal-baby-cute-sea-Favim.com-182890.jpg"?9d7bd4" class="attachment-large" alt="el nino squido" title="adorable-animal-baby-cute-sea-Favim.com-182890" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/snake/' title='snake'><img width="400" height="284" src="http://sametmax.com/wp-content/uploads/2012/11/snake.jpg"?9d7bd4" class="attachment-large" alt="Snake eyes" title="snake" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/cameleon/' title='cameleon'><img width="500" height="376" src="http://sametmax.com/wp-content/uploads/2012/11/cameleon.jpg"?9d7bd4" class="attachment-large" alt="Un chaméléon..encore" title="cameleon" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/adorable-animal-animals-baby-cute-favim-com-401586/' title='adorable-animal-animals-baby-cute-Favim.com-401586'><img width="500" height="375" src="http://sametmax.com/wp-content/uploads/2012/11/adorable-animal-animals-baby-cute-Favim.com-401586.jpg"?9d7bd4" class="attachment-large" alt="tranquillou bilou" title="adorable-animal-animals-baby-cute-Favim.com-401586" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/hamster/' title='hamster'><img width="500" height="375" src="http://sametmax.com/wp-content/uploads/2012/11/hamster.jpg"?9d7bd4" class="attachment-large" alt="Un baby hamster, so cuuute" title="hamster" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/araignee/' title='araignée'><img width="600" height="400" src="http://sametmax.com/wp-content/uploads/2012/11/araignée.jpg"?9d7bd4" class="attachment-large" alt="Mieux qu&#039;un cartoon" title="araignée" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/adorable-animals-cute-giraffe-favim-com-424983/' title='adorable-animals-cute-giraffe-Favim.com-424983'><img width="463" height="600" src="http://sametmax.com/wp-content/uploads/2012/11/adorable-animals-cute-giraffe-Favim.com-424983.jpg"?9d7bd4" class="attachment-large" alt="sophie..." title="adorable-animals-cute-giraffe-Favim.com-424983" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/seche/' title='seche'><img width="278" height="181" src="http://sametmax.com/wp-content/uploads/2012/11/seche.jpeg"?9d7bd4" class="attachment-large" alt="une sèche" title="seche" /></a>
<a href='http://sametmax.com/ces-bebes-animaux-qui-nous-font-craquer/souris/' title='souris'><img width="600" height="400" src="http://sametmax.com/wp-content/uploads/2012/11/souris.jpg"?9d7bd4" class="attachment-large" alt="Ratatouille" title="souris" /></a>

<p>Je vous passe les bactéries et mycoses car c&#8217;est une passion qui n&#8217;est pas forcément partagées (pas tjrs) par tout le monde&#8230;</p>
<p>Et je vous invite à voir comment défoncer l&#8217;audience !<br />
<iframe width="420" height="315" src="http://www.youtube.com/embed/pbTN7UX-_Ho" frameborder="0" allowfullscreen></iframe></p>


feed_id: http://sametmax.com/?p=3163
title: Crate.io, une alternative à Pypi
uri: Create-io-une-alternative-à-Pypi
url: http://sametmax.com/create-io-une-alternative-a-pypi/
content:
<p>Si vous avez lu l&#8217;article sur <a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a>, vous savez que le listing officiel des libs Python est <a href="http://pypi.python.org/pypi">Pypi</a>, un site fort pratique, mais qui commence à dater.</p>
<p>Apparemment certains ont eu envie de changer ça, en créant <a href="https://crate.io/">crate.io</a>, une alternative moderne à Pypi: interface plus léchée et présentant des stats sympathiques, il est un mirroir complet de Pypi et contient donc les <a href="https://crate.io/packages/zerobin/">mêmes packages</a>.</p>
<p>On peut demander à pip d&#8217;utiliser <a href="https://create.io/">create.io</a> comme source. Par exemple pour installer Django:</p>
<p><code> pip install --index-url=https://simple.crate.io django </code></p>
<p>Pratique si Pypi n&#8217;est pas disponible, ou juste pour ne pas mettre tous ses oeufs dans le même panier.</p>
<p>Il est important de noter que c&#8217;est une initiative privée, alors que Pypi est gérée par la Python fondation, les buts ne sont pas les mêmes. Cela dit, les sources sont disponibles sur <a href="https://github.com/crateio">github</a>, donc ça met en confiance. On peut d&#8217;ailleurs voir que le bouzin tourne avec Django/Postgesql/Redis/Celery.</p>


feed_id: http://sametmax.com/?p=3257
title: Effacer le cache DNS sous Mac Os
uri: Effacer-le-cache-DNS-sous-Mac-Os
url: http://sametmax.com/effacer-le-cache-dns-sous-mac-os/
content:
<p>Si vous avez encore l&#8217;ancienne IP lorsque vous faites un ping sur un site c&#8217;est que votre cache DNS l&#8217;a mémorisée. Il faut parfois le réinitialiser (si vous changez votre site de serveur ou que vous ne pouvez plus accéder à un site en particulier).</p>
<p><strong>Ouvrez un Terminal:</strong><br />
<em>Dans <strong>Applications > Utilitaires > Terminal </strong></em></p>
<p>et tapez:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">lookupd -flushcache</pre></div></div>

<p>Si ça ne marche pas  essayez (pour les Mac plus récents):</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">dscacheutil -flushcache</pre></div></div>

<p><strong>Rappel:</strong><br />
la commande ping est toujours utile, c&#8217;est un outil qui sert à tester la conneciton entre 2 IPs.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">ping yahoo.<span style="color: black;">com</span>
PING yahoo.<span style="color: black;">com</span> <span style="color: black;">&#40;</span>72.30.38.140<span style="color: black;">&#41;</span>: <span style="color: #ff4500;">56</span> data <span style="color: #dc143c;">bytes</span>
<span style="color: #ff4500;">64</span> <span style="color: #dc143c;">bytes</span> <span style="color: #ff7700;font-weight:bold;">from</span> 72.30.38.140: icmp_seq=<span style="color: #ff4500;">0</span> ttl=<span style="color: #ff4500;">42</span> <span style="color: #dc143c;">time</span>=<span style="color: #ff4500;">275.592</span> ms
<span style="color: #ff4500;">64</span> <span style="color: #dc143c;">bytes</span> <span style="color: #ff7700;font-weight:bold;">from</span> 72.30.38.140: icmp_seq=<span style="color: #ff4500;">1</span> ttl=<span style="color: #ff4500;">42</span> <span style="color: #dc143c;">time</span>=<span style="color: #ff4500;">212.991</span> ms
<span style="color: #ff4500;">64</span> <span style="color: #dc143c;">bytes</span> <span style="color: #ff7700;font-weight:bold;">from</span> 72.30.38.140: icmp_seq=<span style="color: #ff4500;">2</span> ttl=<span style="color: #ff4500;">42</span> <span style="color: #dc143c;">time</span>=<span style="color: #ff4500;">255.605</span> ms</pre></div></div>


feed_id: http://sametmax.com/?p=2578
title: Les causes perdues de la linguistique
uri: Les-causes-perdues-de-la-linguistique
url: http://sametmax.com/les-causes-perdues-de-la-linguistiques/
content:
<p>La langue c&#8217;est un truc très marrant. On l&#8217;utilise pour se faire comprendre, et on se démerde toujours pour la rendre la moins efficace possible.</p>
<p>On la déforme, on utilise l&#8217;argo, le verlan, puis selon l&#8217;époque des mots qui changent de sens. C&#8217;est &#8220;mortel&#8221; veut dire létal. Sauf dans les années 70 où ça veut dire &#8220;ennuyeux&#8221;. Sauf dans les années 90 où ça veut dire &#8220;génial&#8221;. Sauf dans les années 2000 où ça veut dire &#8220;figurant dans Twilight&#8221; Et puis on s&#8217;exprime mal, et on interprète. Le bordel !</p>
<p>Je ne sais pas si vous connaissez la citation (que j&#8217;ai lu pour la première fois dans un bouquin de Werber):</p>
<blockquote><p>Entre ce que je pense,</p>
<p>Ce que je veux dire,</p>
<p>Ce que je crois dire,</p>
<p>Ce que je dis réellement,</p>
<p>Ce que tu veux entendre,</p>
<p>Ce que tu entends,</p>
<p>Ce que tu crois comprendre,</p>
<p>Ce que tu veux comprendre,</p>
<p>Et ce que tu comprends réellement,</p>
<p>Cela fait 9 bonnes raisons de ne pas se comprendre. Mais essayons quand même.</p></blockquote>
<p>Mais l&#8217;être humain est un animal de contradiction. Quand il essaye, il s&#8217;enfonce.</p>
<h2>La langue des signes</h2>
<p>On pourrait croire que la langue des signes est quelque chose d&#8217;international. Pas du tout: elle est issue d&#8217;un phénomène d’émergence sociale, avec ses composantes d’influences externes et d&#8217;isolation. Du coup, en plus d&#8217;avoir une fracture linguistique, on a une fracture gestuelle dans notre communication.</p>
<p>Ca ne devrait pas être une surprise, car contrairement à ce que la série &#8220;lie to me&#8221; aime faire croire, la gestuelle n&#8217;est pas du tout universelle. C&#8217;est une acquis culturel et contextuel qui s&#8217;est affiné par des générations d&#8217;éducation. Le simple signalement oui/non par la tête peut différer d&#8217;un pays à l&#8217;autre:</p>
<ul>
<li>En Polynésie, le &#8216;oui&#8217; est matérialisé par un levé de sourcils et le &#8216;non&#8217; par un hochement diagonal.</li>
<li>En Albanie ou en Bulgarie le hochement tête de haut en bas signifie &#8216;Non&#8217; et de gauche à droite signifie &#8216;Oui&#8217;.</li>
<li>En Grèce, c&#8217;est un levé de menton qui signifie &#8216;non&#8217;</li>
</ul>
<h2>Les langage artificiels</h2>
<p>L&#8217;<a href="https://fr.wikipedia.org/wiki/Esp%C3%A9ranto">esperanto</a> est un peu le <a href="http://sametmax.com/quest-ce-que-bitcoin/">bitcoin</a> de la linguistique. Un mec s&#8217;est réveillé un matin avec une très belle idée: créer une langage facile à apprendre pour le monde entier, avec une grammaire régulière et aucune exception. La bonne nouvelle, c&#8217;est qu&#8217;il a assez bien réussi son coup car c&#8217;est la seule langue artificielle qui soit devenue une langue vivante.</p>
<div id="attachment_3063" class="wp-caption aligncenter" style="width: 210px"><a href="http://sametmax.com/wp-content/uploads/2012/11/200px-Unua_Libro_fr_001.png"?9d7bd4"><img class="size-full wp-image-3063" title="Le vrai nom de l'Esperanto est &quot;langue international&quot;. Mais bon, le vrai nom de scotch est &quot;ruban adhésif&quot;..." src="http://sametmax.com/wp-content/uploads/2012/11/200px-Unua_Libro_fr_001.png"?9d7bd4" alt="Couverture du précis de langue international d'Esperanto" width="200" height="308" /></a><p class="wp-caption-text">Le vrai nom de l&#39;Esperanto est &quot;langue internationale&quot;. Mais bon, le vrai nom de scotch est &quot;ruban adhésif&quot;...</p></div>
<p>La mauvaise, c&#8217;est qu&#8217;elle ne tient absolument pas compte du fait qu&#8217;un tiers de la population mondiale vit en Asie, où les règles de langue n&#8217;ont absolument rien à voir avec les nôtres. Donc quitte à apprendre une langue très difficile pour eux, les quelques 1 milliards de chinois, autant d&#8217;indiens et à moitié autant de japs vont préférer l&#8217;anglais, déjà utilisé pour le business et par une autre partie significative de la population. En plus, l&#8217;esperanto est un cas typique d&#8217;<a href="http://xkcd.com/927/">introduction d&#8217;un énième standard</a>, qui ajoute au problème plus qu&#8217;il n&#8217;en résout.</p>
<p>Personnellement j&#8217;adore l&#8217;idée. L&#8217;esperanto est d&#8217;ailleurs sur ma liste des langues à apprendre. Mais derrière l&#8217;espagnol, le chinois, la langue des signes française et l&#8217;arabe. Dans cet ordre. Donc je doute sérieusement la parler un jour.</p>
<p>C&#8217;est que je deviens prudent avec les langues. Déjà parce que je parle anglais et 20 langages de programmation. Ma tête est bien chargée. Ensuite parce que durant mes sessions en humanitaire j&#8217;avais voulu apprendre le bambara, dialecte local. Après quelque cours, j&#8217;ai appris qu&#8217;à 200 bornes au nord de la ville, on parlait dogon, mais pas bambara. A l&#8217;est on parlait peul. A l&#8217;ouest wolof. Ca m&#8217;a foutu un coup.</p>
<p>Bref, on a déjà plus de 5000 langues et dialectes, pourquoi en inventer une en plus ?</p>
<p>Comme d&#8217;habitude, l&#8217;art a la réponse. Tolkien a inventé l&#8217;<a href="http://www.tolkienfrance.net/elfique/">elfique</a> pour les besoins de LOTR. Ouais, la langue complète, ouais. Ah, il a pas fait sa chochotte, il s&#8217;est dit &#8220;j&#8217;ai déjà écrit un pavé de 1200 pages, je peux bien me lancer dans un dico&#8221;. Et puis il a fait le Simarilion derrière, preuve que l&#8217;opération lui avait grillé quelques neurones.</p>
<p>Mais il n&#8217;est pas le seul, puisque les mecs de Star Trek ont eux aussi pensé que créer une saga de pas moins de 6 séries télévisées, c&#8217;était pas vraiment un challenge, alors on allait faire parler à certains personnages le <a href="http://fr.wikipedia.org/wiki/Klingon_%28langue%29">Klingon</a>. Et dans la foulée codifier toute la grammaire, c&#8217;est tellement fun. Ce qui fait peur avec le Klingon, ce n&#8217;est pas que certains le parlent dans la vie réelle, c&#8217;est que certains l&#8217;enseignent.</p>
<div id="attachment_3064" class="wp-caption aligncenter" style="width: 410px"><a href="http://sametmax.com/wp-content/uploads/2012/11/Klingon_Beauty_Contest_by_Aranluc.jpg"?9d7bd4"><img class="size-full wp-image-3064" title="Contrairement à la langue, il est bien connu que les standards de beauté intergalactique sont universels" src="http://sametmax.com/wp-content/uploads/2012/11/Klingon_Beauty_Contest_by_Aranluc.jpg"?9d7bd4" alt="Concours de baeuté klingon" width="400" height="412" /></a><p class="wp-caption-text">Contrairement à la langue, il est bien connu que les standards de beauté intergalactiques sont universels</p></div>
<p>Cela dit, dans la liste des curiosités, la palme revient au langage <a href="http://fr.wikipedia.org/wiki/Solresol">solresol</a>, qui est un langage qui se chante. Il n&#8217;y a pas de mots. Seulement des notes. Une symphonie devient un discours, et on peut meumeuter ses mots de passe. C&#8217;est trop chouxe non ?</p>
<h2>Et dans l&#8217;informatique ?</h2>
<p>Notre domaine de prédilection a quelque chose de merveilleux: il possède une concentration de nerds et donc un potentiel de partir en couille fabulissime.</p>
<p>Par exemple, savez-vous d&#8217;où vient notre disposition de clavier ? AZERTY pour les francophones, QWERTY pour les anglophones, et des centaines de config différentes à travers le monde pour être sûr que personne n&#8217;envoie un message de 140 caractères sans au moins une faute de frappe ?</p>
<p>Et bien à l&#8217;époque des machines à écrire, le clavier a été disposé de la manière la plus anti-ergonomique qui soit: deux touches étaient mises proches l&#8217;une de l&#8217;autre si elles étaient rarement utilisées côte à côte dans un même mot. Ainsi pour nous A est à côté de Z. La raison à cela, c&#8217;est que les dactylos tapent très vite, et deux tampons de machine à écrire proches tapés vite s’entremêlent. Donc en éloignant les touches les unes des autres, on évite de bourrer la machine.</p>
<p>Quand les ordinateurs sont arrivés, les premiers opérateurs à se servir du clavier étaient les dactylos. Formés au clavier précédent, on leur a fournit le même clavier, pour ne pas les frustrer, et pour économiser du temps et des sous. Et tant pis si les ordis n&#8217;ont plus de tampons.</p>
<p>Donc on a un clavier de merde, qui rend la frappe lente, imprécise, et mauvaise pour les membres.</p>
<p>Que fait l&#8217;humanité quand elle a un problème avec un standard ? Elle en invente un autre dans son coin !</p>
<p>Arrive alors le <a href="http://fr.wikipedia.org/wiki/August_Dvorak">Auguste Dvorak</a> qui fait des études mathématiques et ergonomiques qui nous pond son clavier aujourd&#8217;hui éponyme. La disposition française s&#8217;appelle le BEPO:</p>
<div id="attachment_3061" class="wp-caption aligncenter" style="width: 510px"><a href="http://sametmax.com/wp-content/uploads/2012/11/typematrix-2030-bepo.jpg"?9d7bd4"><img class="size-full wp-image-3061" title="Le typematrix 2030 est généralement la référence pour les claviers ergonomiques" src="http://sametmax.com/wp-content/uploads/2012/11/typematrix-2030-bepo.jpg"?9d7bd4" alt="Photo du clavier typematrix 2030 " width="500" height="375" /></a><p class="wp-caption-text">Le typematrix 2030 est généralement la référence pour les claviers ergonomiques</p></div>
<p>&nbsp;</p>
<p>Je connais seulement deux personnes qui l&#8217;utilisent, mais ils me jurent que ça leur change la vie. D&#8217;ailleurs ils en possèdent plusieurs.</p>
<p>Comptez quand même un bon mois de galère pour être productif avec. Cela dit, leur vitesse de frappe est le double de la mienne si ils utilisent ce clavier.</p>
<p>Enfin, je ferais une petite conclusion sur un projet absolument inutile, donc parfaitement indispensable, à savoir le jeu de caractère <a href="http://dotsies.org/">dotsies</a>. Le but est de rendre le plus compact possible l&#8217;alphabet ASCII en utilisant 5 pixels alignés sur une colonne verticale pour représenter les lettres. Leur page d&#8217;apprentissage est fabuleuse.</p>
<p>Voici ce que donne notre title en dotsies:</p>
<link href='http://dotsies.org/dotsies.css' rel='stylesheet' type='text/css'>
<p style="font-family: Dotsies; font-size:2.5em; padding:1em;">Sam et Max &#8211; Python, Django, Git et du cul !</p>
<p>Vous avez juste à copier / coller le texte ailleurs pour le voir dans une autre police.</p>


feed_id: http://sametmax.com/?p=3276
title: Les descripteurs en Python
uri: Les-descripteurs-en-Python
url: http://sametmax.com/les-descripteurs-en-python/
content:
<p>Un descripteur est une classe qu&#8217;on instancie comme attribut d&#8217;une autre classe pour faire office de setter et de getter sur cet attribut. Le descripteur doit implémenter les méthodes <code>__get__</code> et <code>__set__</code> qui seront exécutées quand on essaye d&#8217;assigner ou lire l&#8217;attribut. Respecter cette signature, c&#8217;est adopter ce qu&#8217;on appelle pompeusement le &#8220;descriptor protocol&#8221;.</p>
<p>Si le principe vous rappelle les <a href="http://docs.python.org/2/library/functions.html#property">propriétés</a>, c&#8217;est normal, les propriétés sont implémentées en utilisant des descripteurs.</p>
<p>Exemple balot et complètement arbitraire :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> JeSuisUnDescripteurEtJeVousEmmerde<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># les noms des attributs sont des conventions</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__get__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, obj, objtype<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> obj, objtype
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__set__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, obj, value<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> obj, value
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> JeSuisUneClasseNormaleEtJeVousAime<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    ze_attribute = JeSuisUnDescripteurEtJeVousEmmerde<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> objet_affecteux = JeSuisUneClasseNormaleEtJeVousAime<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> objet_affecteux.<span style="color: black;">ze_attribute</span>
<span style="color: #66cc66;">&lt;</span>__main__.<span style="color: black;">JeSuisUneClasseNormaleEtJeVousAime</span> <span style="color: #008000;">object</span> at 0x1cb20d0<span style="color: #66cc66;">&gt;</span> <span style="color: #66cc66;">&lt;</span>class <span style="color: #483d8b;">'__main__.JeSuisUneClasseNormaleEtJeVousAime'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> objet_affecteux.<span style="color: black;">ze_attribute</span> = <span style="color: #483d8b;">'dtc '</span>
<span style="color: #66cc66;">&lt;</span>__main__.<span style="color: black;">JeSuisUneClasseNormaleEtJeVousAime</span> <span style="color: #008000;">object</span> at 0x1cedf10<span style="color: #66cc66;">&gt;</span> dtc</pre></div></div>

<p>Vous noterez que <code>obj</code> est donc toujours l&#8217;instance de l&#8217;objet qui possède l&#8217;attribut sur lequel on agit. Dans <code>__get__</code>, <code>objtype</code> est la classe de cet objet. Dans <code>__set__</code>, <code>value</code> est la nouvelle valeur qu&#8217;on assigne à l&#8217;objet.</p>
<p>Vous allez me dire: pourquoi utiliser les descriptors plutôt que les properties ?</p>
<p>D&#8217;abord, les descripteurs sont des unités de code indépendantes. Vous pouvez faire un module avec vos descripteurs, et les distribuer en tant que lib. Donc c&#8217;est réutilisable. Ensuite, vous n&#8217;êtes pas limités à votre méthode en cours, vous avez accès à tout l&#8217;arsenal de la programmation OO.</p>
<p>Par exemple, si vous pouvez faire un descriptor d&#8217;alerte, qui envoie un signal à tous les abonnés pour cette valeur:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> SignalDescriptor<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    abonnements = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
&nbsp;
    @<span style="color: #008000;">classmethod</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> previens_moi<span style="color: black;">&#40;</span>cls, obj, attr, callback<span style="color: black;">&#41;</span>:
        cls.<span style="color: black;">abonnements</span>.<span style="color: black;">setdefault</span><span style="color: black;">&#40;</span>obj, <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>.<span style="color: black;">setdefault</span><span style="color: black;">&#40;</span>attr, <span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">add</span><span style="color: black;">&#40;</span>callback<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, nom, valeur_initiale=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">nom</span> = nom
        <span style="color: #008000;">self</span>.<span style="color: black;">valeur</span> = valeur_initiale
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__get__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, obj, objtype<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">for</span> callback <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">self</span>.<span style="color: black;">abonnements</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span>obj, <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">nom</span>, <span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
            callback<span style="color: black;">&#40;</span><span style="color: #483d8b;">'get'</span>, obj, <span style="color: #008000;">self</span>.<span style="color: black;">nom</span>, <span style="color: #008000;">self</span>.<span style="color: black;">valeur</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">valeur</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__set__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, obj, valeur<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">for</span> callback <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">self</span>.<span style="color: black;">abonnements</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span>obj, <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">nom</span>, <span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
            callback<span style="color: black;">&#40;</span><span style="color: #483d8b;">'set'</span>, obj, <span style="color: #008000;">self</span>.<span style="color: black;">nom</span>, <span style="color: #008000;">self</span>.<span style="color: black;">valeur</span>, valeur<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">valeur</span> = valeur</pre></div></div>

<p>Et voilà, vous pouvez distribuer ça sur Github, c&#8217;est plug and play.</p>
<p>Par exemple, pour créer un objet <code>Joueur</code> sur lequel on veut monitorer le nombre de crédits :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Joueur<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    credits = SignalDescriptor<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;credits&quot;</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span></pre></div></div>

<p>On l&#8217;utilise normalement:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> j = Joueur<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> j.<span style="color: black;">credits</span>
<span style="color: #ff4500;">0</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> j.<span style="color: black;">credits</span> = <span style="color: #ff4500;">15</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> j.<span style="color: black;">credits</span>
<span style="color: #ff4500;">15</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> j.<span style="color: black;">credits</span> += <span style="color: #ff4500;">5</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> j.<span style="color: black;">credits</span>
<span style="color: #ff4500;">20</span></pre></div></div>

<p>Mais si on rajoute un abonné :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> monitorer_credits<span style="color: black;">&#40;</span>action, obj, attribut, valeur_actuelle, nouvelle_valeur=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
&nbsp;
   <span style="color: #ff7700;font-weight:bold;">if</span> action == <span style="color: #483d8b;">'set'</span>:
       <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Les crédits ont changé:&quot;</span>
   <span style="color: #ff7700;font-weight:bold;">else</span>:
       <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Les crédits ont été consultés:&quot;</span>
   <span style="color: #ff7700;font-weight:bold;">print</span> action, obj, attribut, valeur_actuelle, nouvelle_valeur
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> SignalDescriptor.<span style="color: black;">previens_moi</span><span style="color: black;">&#40;</span>j, <span style="color: #483d8b;">'credits'</span>, monitorer_credits<span style="color: black;">&#41;</span></pre></div></div>

<p>Alors à chaque action sur les crédits, tous les abonnés sont appelés :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> j.<span style="color: black;">credits</span>
Les crédits ont été consultés:
get <span style="color: #66cc66;">&lt;</span>__main__.<span style="color: black;">Joueur</span> <span style="color: #008000;">object</span> at 0x1f6b190<span style="color: #66cc66;">&gt;</span> credits <span style="color: #ff4500;">20</span> <span style="color: #008000;">None</span>
<span style="color: #ff4500;">20</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> j.<span style="color: black;">credits</span> = -<span style="color: #ff4500;">20</span>
Les crédits ont changé:
<span style="color: #008000;">set</span> <span style="color: #66cc66;">&lt;</span>__main__.<span style="color: black;">Joueur</span> <span style="color: #008000;">object</span> at 0x1f6b190<span style="color: #66cc66;">&gt;</span> credits <span style="color: #ff4500;">20</span> -<span style="color: #ff4500;">20</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> j.<span style="color: black;">credits</span> -= <span style="color: #ff4500;">10</span> <span style="color: #808080; font-style: italic;"># get ET set</span>
Les crédits ont été consultés:
get <span style="color: #66cc66;">&lt;</span>__main__.<span style="color: black;">Joueur</span> <span style="color: #008000;">object</span> at 0x1f6b190<span style="color: #66cc66;">&gt;</span> credits -<span style="color: #ff4500;">20</span> <span style="color: #008000;">None</span>
Les crédits ont changé:
<span style="color: #008000;">set</span> <span style="color: #66cc66;">&lt;</span>__main__.<span style="color: black;">Joueur</span> <span style="color: #008000;">object</span> at 0x1f6b190<span style="color: #66cc66;">&gt;</span> credits -<span style="color: #ff4500;">20</span> -<span style="color: #ff4500;">30</span></pre></div></div>

<p>On vient d&#8217;implémenter une version encapsulée du <a href="http://sametmax.com/le-pattern-observer-en-utilisant-des-decorateurs">pattern observer</a> dédié à un attribut. On peut faire de nombreuses choses avec les descripteurs: grouper des attributs, les transformer à la volée, les sauvegarder ailleurs (imaginez un objet de config qui sauvegarde automatiquement chaque modification de ses attributs dans un fichier…).</p>


feed_id: http://sametmax.com/?p=3290
title: (Très) Grand listing des libs tierce partie les plus utiles en Python
uri: (Très)-Grand-listing-des-libs-tierce-partie-les-plus-utiles-en-Python
url: http://sametmax.com/tres-grand-listing-des-libs-tierce-partie-les-plus-utiles-en-python/
content:
<p>Je n&#8217;ai pas tout mis, et quand j&#8217;ai omis c&#8217;est soit par ignorance, soit par choix. Je suis partial et limité :-) Ça m&#8217;a quand même pris une bonne partie de mon dimanche de compiler tout ça. Enjoy.</p>
<table width="642" cellspacing="0" cellpadding="2">
<colgroup>
<col width="126" />
<col width="103" />
<col width="401" /> </colgroup>
<tbody>
<tr>
<td width="126" height="16">
<p align="CENTER"><strong>Sujet</strong></p>
</td>
<td width="103">
<p align="CENTER"><strong>Nom de la bibliothèque</strong></p>
</td>
<td width="401">
<p align="CENTER"><strong>Description</strong></p>
</td>
</tr>
<tr>
<td colspan="3" bgcolor="#eeeeee" width="638" height="17">
<p align="CENTER">Administration système</p>
</td>
</tr>
<tr>
<td rowspan="5" width="126">
<p align="CENTER">Outils autour de la ligne de commande</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://www.noah.org/python/pexpect/">Pexpect</a></p>
</td>
<td width="401">
<p align="LEFT">Capture de sortie avancée, mais surtout des facilités pour discuter avec le programme comme si on était un humain devant sa console en train de taper.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://github.com/kennethreitz/clint">Clint</a></p>
</td>
<td width="401">
<p align="LEFT">Quelques helpers pour afficher dans un terminal proprement (couleur, indentation, quoting) sans se compliquer la vie.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://amoffat.github.com/sh/">Sh</a></p>
</td>
<td width="401">
<p align="LEFT">Appeler les programmes en lignes de commande comme si c’était des fonctions Python. Fonctionne automaGiquement.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://github.com/kennethreitz/envoy">Envoy</a></p>
</td>
<td width="401">
<p align="LEFT">Une alternative élégante au module subprocessing qui permet d’appeler d’autres programmes depuis Python.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://github.com/ksamuel/Pyped">Pyped</a></p>
</td>
<td width="401">
<p align="LEFT">Un petit outil pour pouvoir piper des sorties de commande et les traiter avec des one-liners en Python, comme on fait avec Perl.</p>
</td>
</tr>
<tr>
<td rowspan="3" width="126">
<p align="CENTER">Manipuler des fichiers</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://pypi.python.org/pypi/grin">Grin</a></p>
</td>
<td width="401">
<p align="LEFT">Grep sous stéroïde. Utilisable en ligne de commande, ou programmatiquement.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://pypi.python.org/pypi/path.py/2.2.2">Path.py</a></p>
</td>
<td width="401">
<p align="LEFT">Améliore sensiblement l’API de manipulation des fichiers de Python en lui donnant un goût de POO et une certaine élégance.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://packages.python.org/watchdog/">Watchdog</a></p>
</td>
<td width="401">
<p align="LEFT">API multiplateforme pour surveiller les changements dans le système de fichiers (création de dossier, édition, etc) et y réagir.</p>
</td>
</tr>
<tr>
<td rowspan="3" width="126">
<p align="CENTER">Manipuler le réseau</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://www.secdev.org/projects/scapy/">Scapy</a></p>
</td>
<td width="401">
<p align="LEFT">Un couteau suisse pour le réseau qui clame pouvoir remplacer programmatiquement hping, 85% de nmap, arpspoof, arp-sk, arping, tcpdump, tethereal et p0f. Non testé par l’auteur, mais il a une bonne réputation.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://code.google.com/p/dpkt/">DPKT</a></p>
</td>
<td width="401">
<p align="LEFT">Création basique de paquets et gestion primitive de TCP/IP. Vise clairement le hacker qui veut rester proche de l’implémentation.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://www.lag.net/paramiko/">Paramiko</a></p>
</td>
<td width="401">
<p align="LEFT">API de haut niveau pour travailler à travers le protocole SSH.</p>
</td>
</tr>
<tr>
<td rowspan="3" width="126">
<p align="CENTER">Interaction avec l’OS</p>
</td>
<td width="103">
<p align="CENTER"><a href="https://code.google.com/p/psutil/">Psutil</a></p>
</td>
<td width="401">
<p align="LEFT">Outil multiplateforme qui permet d’obtenir les informations que fournissent ps, top, df, kill, free, lsof, netstat, ifconfig, nice, ionice, iostat, iotop, uptime, pidof, tty, who, taskset et pmap.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://starship.python.net/%7Eskippy/win32/Downloads.html">Win32</a></p>
</td>
<td width="401">
<p align="LEFT">Travailler directement avec l’API COM de Windows. Utile pour contrôler des programmes avec des macros en VB, donner des ordres à MS Office et avoir accès à certains appels que seul le Dieu des DLL connaît. Installable via un .exe.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://github.com/kennethreitz/env">Env</a></p>
</td>
<td width="401">
<p align="LEFT">Une API simple et élégante pour interagir avec les variables d’environnement.</p>
</td>
</tr>
<tr>
<td rowspan="3" width="126">
<p align="CENTER">Déploiement</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://saltstack.org/">Salt</a></p>
</td>
<td width="401">
<p align="LEFT">Salt peut gérer entièrement et rapidement votre infrastructure même si elle compte des milliers de serveurs, à travers des fichiers de conf. Lancement de services, installation de paquets, gestion des dépendances…</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://docs.fabfile.org/en/1.5/">Fabric</a></p>
</td>
<td width="401">
<p align="LEFT">Fabric a les mêmes objectifs que salt mais l’approche est différente : d’accès plus facile, il vise les déploiements de moyenne taille et utilise des fichiers de code en Python, et non de configuration. Exécuter une installation à distance via SSH automatiquement est sa spécialité.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://github.com/ronnix/fabtools">Fabtools</a></p>
</td>
<td width="401">
<p align="LEFT">Collection d’outils pour fabric pour étendre ses fonctionnalités et rajouter, par exemple, la gestion de dépendances des paquets. Encore jeune.</p>
</td>
</tr>
<tr>
<td rowspan="2" width="126">
<p align="CENTER">Services</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://pypi.python.org/pypi/supervisor">Supervisor</a></p>
</td>
<td width="401">
<p align="LEFT">Démarre, arrête et relance gracieusement des services. N’importe quel programme peut être défini comme un service dans un fichier de configuration adapté, et sera daemonisé, monitoré et relancé si besoin en cas de crash. Très utilisé pour gérer les daemons de celery, gunicorn, etc. Un très bon remplacement à tous ces scripts dans /etc/init.d.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://pypi.python.org/pypi/circus">Circus</a></p>
</td>
<td width="401">
<p align="LEFT">Vise le même but que supervisor, mais gère en plus les sockets. Il peut être réparti sur plusieurs nœuds qui communiquent avec ZeroMQ (qui est donc une dépendance). Le projet est soutenu par Mozilla. Si vous cherchez la simplicité, restez sur supervisor, si vous cherchez la puissance, circus est fait pour vous.</p>
</td>
</tr>
<tr>
<td rowspan="3" width="126">
<p align="CENTER">Matériel</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://bleyer.org/pyusb/">PyUSB</a></p>
</td>
<td width="401">
<p align="LEFT">Manipuler des périphériques USB depuis Python sous Windows.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://pyserial.sourceforge.net/">PySerial</a></p>
</td>
<td width="401">
<p align="LEFT">Manipuler des ports séries depuis Python. Nécessite l’extension JavaComm et ctypes sous Windows.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://pyserial.sourceforge.net/pyparallel.html">PyParallel</a></p>
</td>
<td width="401">
<p align="LEFT">Manipuler des ports parallèles depuis Python. Nécessite l’extension JavaComm.</p>
</td>
</tr>
<tr>
<td colspan="3" bgcolor="#eeeeee" width="638" height="17">
<p align="CENTER">Bases de données</p>
</td>
</tr>
<tr>
<td rowspan="3" width="126">
<p align="CENTER">SGBD</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://sourceforge.net/projects/mysql-python/">mysql-python</a></p>
</td>
<td width="401">
<p align="LEFT">Malgré le nom inversé, c’est bien ce paquet qu’il faudra installer pour obtenir les drivers MySQL. Nécessite distribute (pip install distribute) et une compilation pour pip avec dépendances.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://www.initd.org/psycopg/">Psycopg</a></p>
</td>
<td width="401">
<p align="LEFT">Adaptateur pour se connecter à une base de données PostgreSQL. Demande une compilation si installé avec pip.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://code.google.com/p/pyodbc/">PyODBC</a></p>
</td>
<td width="401">
<p align="LEFT">Permet de se connecter aux base de données qui possèdent une interface ODBC, telles que MS Access. Requiert une compilation pour pip.</p>
</td>
</tr>
<tr>
<td rowspan="5" width="126">
<p align="CENTER">NoSQL</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://labs.codernity.com/codernitydb/index.html">Codernitydb</a></p>
</td>
<td width="401">
<p align="LEFT">Une sorte de SQLite en NoSQL, écrit en pur Python, et fourni avec son propre serveur HTTP optionnel.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://github.com/mongodb/mongo-python-driver">PyMongo</a></p>
</td>
<td width="401">
<p align="LEFT">Tout ce qu’il faut pour jouer avec MongoDB. Mais nécessite distribute…</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://github.com/andymccurdy/redis-py">Redis</a></p>
</td>
<td width="401">
<p align="LEFT">Client pour Redis. Pur Python. Installer Hiredis pour le rendre plus rapide, mais cela demande compilation pour pip.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://pypi.python.org/pypi/CouchDB">Couchdb</a></p>
</td>
<td width="401">
<p align="LEFT">Client officiel pour CouchDB.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://pypi.python.org/pypi/Whoosh">Woosh</a></p>
</td>
<td width="401">
<p align="LEFT">Un moteur d’indexation et de recherche de texte écrit en pur Python. Une sorte de SQLite pour moteur de recherche.</p>
</td>
</tr>
<tr>
<td rowspan="2" width="126">
<p align="CENTER">ORM</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://peewee.readthedocs.org/en/latest/">Peewee</a></p>
</td>
<td width="401">
<p align="LEFT">Un micro-ORM qui tient dans un fichier, il est néanmoins très capable. Parfait pour un petit script ou un projet desktop.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://www.sqlalchemy.org/">SQLAlchemy</a></p>
</td>
<td width="401">
<p align="LEFT">Probablement l’ORM le plus complet au monde.</p>
</td>
</tr>
<tr>
<td width="126" height="47">
<p align="CENTER">Sécurité</p>
</td>
<td width="103">
<p align="CENTER"><a href="https://www.dlitz.net/software/pycrypto/">PyCryto</a></p>
</td>
<td width="401">
<p align="LEFT">La référence du chiffrement en Python pour tous vos besoins autour de AES, Blowfish, SHA, etc. Nécessite une compilation par pip.</p>
</td>
</tr>
<tr>
<td colspan="3" bgcolor="#eeeeee" width="638" height="17">
<p align="CENTER">Desktop</p>
</td>
</tr>
<tr>
<td colspan="3" bgcolor="#ffffff" width="638" height="32">
<p align="CENTER"><em>Ces bibliothèques sont difficiles à installer dans un environnement virtuel. Exceptionnellement, installez-les au niveau de l’OS en utilisant un installer fourni sur le site officiel ou dans les dépôts de votre système, et non avec pip.</em></p>
</td>
</tr>
<tr>
<td rowspan="4" width="126">
<p align="CENTER">Développer une interface graphique</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://kivy.org/#home">Kivy</a></p>
</td>
<td width="401">
<p align="LEFT">Pour le moment très jeune. Permet de développer des UI sur les principaux systèmes d’exploitations et sur Android ainsi que iOS. Gère le multi-touche.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://www.pygtk.org/">PyGTK</a></p>
</td>
<td width="401">
<p align="LEFT">Binding Python des bibliothèques GTK, assez simple à utiliser et très bien intégré au bureau GNOME bien qu’il existe des moyens de porter une application sur d’autres OS. La documentation est globalement moins bonne que celle de PySide/PyQT.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://qt-project.org/wiki/PySide">PySide</a></p>
</td>
<td width="401">
<p align="LEFT">Portable et très complet, PySide est aussi complètement compatible avec PyQt mais offre une licence plus permissive (LGPL). Le projet est soutenu par Nokia.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://wxpython.org/">wxPython</a></p>
</td>
<td width="401">
<p align="LEFT">Très portable, et moins dur à packager que les autres, mais avec une API très proche du C et un manque de widgets modernes.</p>
</td>
</tr>
<tr>
<td width="126" height="77">
<p align="CENTER">Développer une interface console</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://excess.org/urwid/">Urwid</a></p>
</td>
<td width="401">
<p align="LEFT">Création d’interfaces textuelles avancées dans la lignée de curses, mais avec des widgets supplémentaires, une bonne gestion des couleurs et de l’UTF-8 et une courbe d’apprentissage assez raide.</p>
</td>
</tr>
<tr>
<td colspan="3" bgcolor="#eeeeee" width="638" height="17">
<p align="CENTER">Localisation</p>
</td>
</tr>
<tr>
<td width="126" height="47">
<p align="CENTER">Calcul avancé avec des dates et des périodes</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://labix.org/python-dateutil#head-cf004ee9a75592797e076752b2a889c10f445418">Dateutil</a></p>
</td>
<td width="401">
<p align="LEFT">Un complément puissant compatible avec datetime et qui propose en plus un parseur avancé, une gestion des récurrences et des durées relatives.</p>
</td>
</tr>
<tr>
<td width="126" height="17">
<p align="CENTER">I18n</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://babel.edgewall.org/">Babel</a></p>
</td>
<td width="401">
<p align="LEFT">Traduction, localisation, dates naturelles…</p>
</td>
</tr>
<tr>
<td width="126" height="32">
<p align="CENTER">Manipuler des devises</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://pypi.python.org/pypi/python-money/0.5">Python-money</a></p>
</td>
<td width="401">
<p align="LEFT">Des primitives pour effectuer le délicat travail de manipulation des devises.</p>
</td>
</tr>
<tr>
<td colspan="3" bgcolor="#eeeeee" width="638" height="17">
<p align="CENTER">Multimédia</p>
</td>
</tr>
<tr>
<td width="126" height="47">
<p align="CENTER">Manipuler des images</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://www.pythonware.com/products/pil/">PIL</a></p>
</td>
<td width="401">
<p align="LEFT">Le standard de la manipulation d’images en Python. Toutes les opérations de base y sont, mais elle est assez difficile à installer.</p>
</td>
</tr>
<tr>
<td rowspan="2" width="126">
<p align="CENTER">Création de jeu vidéo et d’animations</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://www.pygame.org/news.html">PyGame</a></p>
</td>
<td width="401">
<p align="LEFT">Jeux vidéos en 2D, du moteur graphique à la logique du jeu en passant par la musique.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://pyopengl.sourceforge.net/">PyOpenGl</a></p>
</td>
<td width="401">
<p align="LEFT">Un binding OpenGL en Python qui donne accès à OpenGL (v1.1 à 4.3), GLU, GLUT v3.7, FreeGLUT, GLE 3 et des centaines d’extensions OpenGL. En prime, PyOpenGl est interopérable avec wxPython, PyGame, PyQt / PySide et PyGTK.</p>
</td>
</tr>
<tr>
<td rowspan="4" width="126">
<p align="CENTER">Générer des documents</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://jinja.pocoo.org/docs/">Jinja2</a></p>
</td>
<td width="401">Un langage de template proche de celui de Django qui limite le code Python utilisable et est facile d&#8217;accès.</td>
</tr>
<tr>
<td width="103">
<p align="CENTER">Mako</p>
</td>
<td width="401">Un langage de template au rendu très rapide qui autorise n&#8217;importe quelle expression Python dans le document.</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://secure.simplistix.co.uk/svn/xlwt/trunk/xlwt/doc/xlwt.html">xlwt</a></p>
</td>
<td width="401">
<p align="LEFT">Produire des documents au format XLS.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://weasyprint.org/">Weasyprint</a></p>
</td>
<td width="401">
<p align="LEFT">Une solution plus simple pour générer du PDF que Reportlab : générer du HTML et le convertir en PDF. Excellent si vous n’avez pas de besoin en lecture et si vous pouvez assumer la dépendance à PyGTK.</p>
</td>
</tr>
<tr>
<td colspan="3" bgcolor="#eeeeee" width="638" height="17">
<p align="CENTER">Outils</p>
</td>
</tr>
<tr>
<td rowspan="3" width="126">
<p align="CENTER">Tests unitaires</p>
</td>
<td width="103">
<p align="CENTER"><a href="https://nose.readthedocs.org/en/latest/">Nose</a></p>
</td>
<td width="401">
<p align="LEFT">Lanceur de tests avec auto détection des tests et des adaptateurs d’entrées et sorties pour beaucoup d’autres outils.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://packages.python.org/lettuce/index.html">Lettuce</a></p>
</td>
<td width="401">
<p align="LEFT">La bibliothèque la plus connue pour faire du BDD (développement orienté comportement).</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://pytest.org/latest/">PyTest</a></p>
</td>
<td width="401">
<p align="LEFT">Rend les tests plus simples à écrire et faciles à debugger. Très belle API, surtout comparée à xUnit.</p>
</td>
</tr>
<tr>
<td width="126" height="62">
<p align="CENTER">Documentation</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://pypi.python.org/pypi/Sphinx">Sphinx</a></p>
</td>
<td width="401">
<p align="LEFT">Permet d’écrire sa documentation au format RST et génère du HTML statique avec un moteur de recherche hors ligne très propre. Standard dans le monde de Python.</p>
</td>
</tr>
<tr>
<td rowspan="3" width="126">
<p align="CENTER">Packaging</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://www.py2exe.org/">p2exe</a></p>
</td>
<td width="401">
<p align="LEFT">Transforme un programme Python en exécutable Windows. Il n’y a pas de magie cependant, et cela demande un certain travail. Par ailleurs, cela ne crée pas un installateur pour autant.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://starship.python.net/crew/atuining/cx_Freeze/">cx_Freeze</a></p>
</td>
<td width="401">
<p align="LEFT">Similaire à p2exe, mais peut être lancé sous un autre OS que Windows.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://packages.python.org/versiontools/">Versiontools</a></p>
</td>
<td width="401">
<p align="LEFT">Des helpers pour incrémenter la version de son programme proprement.</p>
</td>
</tr>
<tr>
<td rowspan="6" width="126">
<p align="CENTER">Développement</p>
</td>
<td width="103">
<p align="CENTER"><a href="https://github.com/rbarrois/xworkflows">Xworkflows</a></p>
</td>
<td width="401">
<p align="LEFT">Facilite la création de machines à états finis.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://www.gevent.org/">Gevent</a></p>
</td>
<td width="401">
<p align="LEFT">Monkey patch les fonctions de réseau de la bibliothèque standard pour les rendre asynchrones et ainsi gagner en performance sur la lecture et l’écriture.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://txzone.net/2012/08/pyjnius-accessing-java-classes-from-python/">Pyjnius</a></p>
</td>
<td width="401">
<p align="LEFT">Accéder à des classes Java sans sortir l’artillerie lourde (comme Jython).</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://github.com/kennethreitz/showme">Showme</a></p>
</td>
<td width="401">
<p align="LEFT">Une collection de décorateurs pour facilement et rapidement regarder le temps, le nombre de cycles CPU et l’entrée/sortie d’une fonction.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://starship.python.net/crew/theller/ctypes/">Ctypes</a></p>
</td>
<td width="401">
<p align="LEFT">Appeler du C depuis Python. Si vous avez un .dll ou un .so qui vous tient à cœur, c’est par ici.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://github.com/sametmax/Bat-belt/tree/master/batbelt">Batbelt</a></p>
</td>
<td width="401">
<p align="LEFT">Une bibliothèque fourre-tout qui contient des fonctions-outils fort sympathiques pour la vie de tous les jours en Python : slugification, parcours d’itérables avec fenêtre, capture de stdout dans une variable, imports dynamiques simplifiés, sets ordonnés, etc. Absence totale de documentation, mais très bien commentée.</p>
</td>
</tr>
<tr>
<td colspan="3" bgcolor="#eeeeee" width="638" height="17">
<p align="CENTER">Parsing</p>
</td>
</tr>
<tr>
<td width="126" height="62">
<p align="CENTER">Parser les arguments de la ligne de commande</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://pypi.python.org/pypi/clize">Clize</a></p>
</td>
<td width="401">
<p align="LEFT">Permet de transformer l’appel d’une fonction automatiquement en une liste d’argument pour le script en cours. Très simple et tient dans un fichier mais utilise en interne un parsing manuel.</p>
</td>
</tr>
<tr>
<td rowspan="7" width="126">
<p align="CENTER">Catégoriser du contenu</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://pypi.python.org/pypi/Reverend">Reverend</a></p>
</td>
<td width="401">
<p align="LEFT">Implémentation en Python de filtrage bayésien. Utile pour lutter contre le spam ou trouver des contenus qui se ressemblent dans leurs formes.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://github.com/clips/pattern">Pattern</a></p>
</td>
<td width="401">
<p align="LEFT">Analyse linguistique en langage naturel, intelligence artificielle et même quelques Web spiders.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://github.com/seatgeek/fuzzywuzzy">FuzzyFuzzy</a></p>
</td>
<td width="401">
<p align="LEFT">La documentation dit « Fuzzy string matching like a boss ». C’est bien résumé. API très simple pour des comparaisons floues sur les chaînes de caractères.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://bitbucket.org/spirit/guess_language">guess_language</a></p>
</td>
<td width="401">
<p align="LEFT">Essaye de deviner la langue dans laquelle est écrit un texte.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://pypi.python.org/pypi/chardet">Chardet</a></p>
</td>
<td width="401">
<p align="LEFT">Essaye de deviner l’encodage dans lequel est écrit un texte. Utilisé par Mozilla.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://pyparsing.wikispaces.com/">PyParsing</a></p>
</td>
<td width="401">
<p align="LEFT">Créer des parseurs pour des langages dont la grammaire est régulière en utilisant Python plutôt que des choses compliquées comme Lex.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://nltk.org/">NLTK</a></p>
</td>
<td width="401">
<p align="LEFT">« Natural Language Toolkit » Une référence dans le domaine de l&#8217;analyse du langage naturel.</p>
</td>
</tr>
<tr>
<td width="126" height="32">
<p align="CENTER">Coloration syntaxique</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://pygments.org/">Pygments</a></p>
</td>
<td width="401">
<p align="LEFT">Rapide et puisant, mais ne détecte pas automatiquement le langage utilisé.</p>
</td>
</tr>
<tr>
<td rowspan="3" width="126">
<p align="CENTER">Parser du XML</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://lxml.de/">LXML</a></p>
</td>
<td width="401">
<p align="LEFT">Facile, puissant, rapide, mais pip devra compiler cette bibliothèque. Dans ses dernières versions, gère aussi le HTML, mais n’a pas la même tolérance que BeautifulSoup.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://pypi.python.org/pypi/feedparser">Feedparser</a></p>
</td>
<td width="401">
<p align="LEFT">Extrait les données de flux RSS et Atom.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://github.com/stchris/untangle">Untangle</a></p>
</td>
<td width="401">
<p align="LEFT">Transforme un arbre XML en un objet Python. Lent mais une belle API très agréable et facile à manipuler.</p>
</td>
</tr>
<tr>
<td rowspan="2" width="126">
<p align="CENTER">Parser du HTML</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://www.crummy.com/software/BeautifulSoup/">Beautiful Soup</a></p>
</td>
<td width="401">
<p align="LEFT">Pas très rapide mais très puissant, mais capable d’analyser du HTML très mal formé, et est écrit en pur Python. N’utilisez pas la version 3. En concurrence avec HTML5Lib que je n’ai pas testé.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://packages.python.org/pyquery/">PyQuery</a></p>
</td>
<td width="401">
<p align="LEFT">L’API de jQuery, portée en Python.</p>
</td>
</tr>
<tr>
<td rowspan="7" width="126">
<p align="CENTER">Parser un fichier binaire</p>
</td>
<td width="103">
<p align="CENTER"><a href="https://bitbucket.org/haypo/hachoir/wiki/Home">Hachoir</a></p>
</td>
<td width="401">
<p align="LEFT">Transforme un fichier binaire en un arbre de champs manipulables. La bibliothèque est par ailleurs très modulaire.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://github.com/mikemaccana/python-docx">python-docx</a></p>
</td>
<td width="401">
<p align="LEFT">Lire et écrire dans le fameux format « standard » de MS Office. Dépendances lourdes : LXML et PIL.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://pyrtf.sourceforge.net/">PyRTF</a></p>
</td>
<td width="401">
<p align="LEFT">Lire et écrire en RTF, seul format 100 % compatible avec MS Office et LibreOffice.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://www.reportlab.com/">Reportlab</a></p>
</td>
<td width="401">
<p align="LEFT">Lire et écrire des PDF, au pixel prêt.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://pypi.python.org/pypi/odfpy">OdfPy</a></p>
</td>
<td width="401">
<p align="LEFT">Manipuler les fichiers ODF en pur Python.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://appyframework.org/pod.html">Pod</a></p>
</td>
<td width="401">
<p align="LEFT">Une solution hybride qui part d’un template au format ODF (et pouvant contenir du code Python) qui ensuite génère du PDF, DOC, RTF ou TXT derrière. Requiert LibreOffice en mode serveur.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://secure.simplistix.co.uk/svn/xlrd/trunk/xlrd/doc/xlrd.html">xlrd</a></p>
</td>
<td width="401">
<p align="LEFT">Lire les documents produits par Excel.</p>
</td>
</tr>
<tr>
<td colspan="3" bgcolor="#eeeeee" width="638" height="17">
<p align="CENTER">Science</p>
</td>
</tr>
<tr>
<td rowspan="2" width="126">
<p align="CENTER">Calculs</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://numpy.scipy.org/">NumPy</a></p>
</td>
<td width="401">
<p align="LEFT">Bibliothèque de calculs scientifiques haute performance avec gestion des grands jeux de nombres, matrices avec n dimensions et même de quoi réutiliser son vieux code C/C++ ou Fortran. Requiert une compilation pour pip.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://www.scipy.org/">SciPy</a></p>
</td>
<td width="401">
<p align="LEFT">Utilise la puissance de NumPy pour fournir des opérations avancées rapides sur les grands jeux de nombres et les matrices.</p>
</td>
</tr>
<tr>
<td rowspan="2" width="126">
<p align="CENTER">Création de graphiques</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://matplotlib.org/">Matplotlib</a></p>
</td>
<td width="401">
<p align="LEFT">Produit des graphiques en 2D de bonne qualité, du plus simple au plus complexe. Très bien intégré au shell iPython avec lequel il permet de recréer un environnement similaire à MatLab.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://networkx.lanl.gov/">Networkx</a></p>
</td>
<td width="401">
<p align="LEFT">Création et manipulation de graphes nœud par nœud. Export en SVG.</p>
</td>
</tr>
<tr>
<td rowspan="5" width="126">
<p align="CENTER">Analyse de données et modélisation</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://pandas.pydata.org/">Pandas</a></p>
</td>
<td width="401">
<p align="LEFT">Traitement en masse de gros échantillons de données pour en extraire les parties significatives et les traiter.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://www.pytables.org/moin">PyTables</a></p>
</td>
<td width="401">
<p align="LEFT">Manipulation de gros jeux de données hiérarchiques avec optimisation automatique des ressources disque et mémoire utilisées (notamment en utilisant la compression à la volée).</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://docs.python-tablib.org/en/latest/">Tablib</a></p>
</td>
<td width="401">
<p align="LEFT">API élégante pour importer, manipuler et exporter des jeux de données tabulaires. Supporte la ségrégation, les colonnes dynamiques, les tags et le filtrage ainsi que l’export JSON, YML, CSV et XLS.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://rpy.sourceforge.net/rpy2.html">SimPy</a></p>
</td>
<td width="401">
<p align="LEFT">Bibliothèque de simulation en Python similaire à REPAST ou NetLogo en moins puissant.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://rpy.sourceforge.net/rpy2.html">RPy2</a></p>
</td>
<td width="401">
<p align="LEFT">Utiliser R, depuis Python.</p>
</td>
</tr>
<tr>
<td colspan="3" bgcolor="#eeeeee" width="638" height="17">
<p align="CENTER">Web et Internet</p>
</td>
</tr>
<tr>
<td width="126" height="47">
<p align="CENTER">Crawling</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://scrapy.org/">Scrappy</a></p>
</td>
<td width="401">
<p align="LEFT">Un framework entier pour créer des bots qui vont parcourir et extraire des données de sites entiers. Vraiment très complet.</p>
</td>
</tr>
<tr>
<td rowspan="6" width="126">
<p align="CENTER">Framework</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://www.bottlepy.org/docs/dev/">Bottle</a></p>
</td>
<td width="401">
<p align="LEFT">Un micro-framework qui tient dans un fichier. Excellent pour débuter la programmation Web avec Python ou pour un petit projet vite fait. Pas d’ORM, mais un langage de template.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://www.cherrypy.org/">CherryPy</a></p>
</td>
<td width="401">
<p align="LEFT">Framework POO assez complet mais sans ORM ni langage de template. Embarque un serveur HTTP en pur Python assez performant (et intégrable à Bottle).</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://www.djangoproject.com/">Django</a></p>
</td>
<td width="401">
<p align="LEFT">Le plus utilisé dans la communauté Python. Très intégré, extrêmement complet (ORM, template, formulaire, admin, middlewares, etc), grande quantité de ressources et de bibliothèques autour du projet. Malgré cela, assez facile à prendre en main.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://www.pylonsproject.org/">Pyramid</a></p>
</td>
<td width="401">
<p align="LEFT">Une fusion de la plupart des anciens concurrents de Django. Beaucoup plus découplé. À surveiller.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://www.tornadoweb.org/">Tornado</a></p>
</td>
<td width="401">
<p align="LEFT">Un framework asynchrone plus accessible que Twisted, mais un peu moins performant et surtout spécialisé dans le Web. Utilisé notamment par Facebook.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://twistedmatrix.com/trac/">Twisted</a></p>
</td>
<td width="401">
<p align="LEFT">Spécialisé dans la programmation asynchrone. Peut faire bien plus que du Web, en fait tout ce qui est réseau, et en haute performance. Le prix a payer est sa complexité. Nécessite d’être compilé par pip.</p>
</td>
</tr>
<tr>
<td rowspan="4" width="126">
<p align="CENTER">Messaging</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://pypi.python.org/pypi/celery/2.5.5">Celery</a></p>
</td>
<td width="401">
<p align="LEFT">Surcouche à Kombu pour implémenter des files de tâches et des tâches récurrentes. On l’utilise généralement en lieu et place de Kombu.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://pypi.python.org/pypi/kombu">Kombu</a></p>
</td>
<td width="401">
<p align="LEFT">Le <i>statu quo</i> dans la gestion de messages et de queues, proposant une interface unifiée quel que soit le broker. Supporte RabbitMQ, Redis, Beanstalk, Amazon SQS, CouchDB, MongoDB et ZooKeeper.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://github.com/zeromq/pyzmq">PyZMQ</a></p>
</td>
<td width="401">
<p align="LEFT">Support Python pour le protocole ZeroMQ. Nécessite une compilation de la part de pip.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://www.snakemq.net/">SnakeMQ</a></p>
</td>
<td width="401">
<p align="LEFT">Implémentation prometteuse en pur Python d’un protocole de messagerie similaire à ZeroMQ. Jeune, immature, incompatible avec ZeroMQ.</p>
</td>
</tr>
<tr>
<td rowspan="2" width="126">
<p align="CENTER">Proxys et serveurs</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://packages.python.org/Deliverance/">Deliverance</a></p>
</td>
<td width="401">
<p align="LEFT">Prend le design de n’importe quel site en ligne et l’adapte sur un autre site que vous possédez. Pratique pour changer l’aspect d’un site dont le thème est très difficile à modifier (exemple : un site Zope ou Plone).</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://pypi.python.org/pypi/gunicorn">Gunicorn</a></p>
</td>
<td width="401">
<p align="LEFT">Un serveur compatible WSGI assez rapide. Très utilisé en couple avec Nginx et Django. Nécessite une compilation pour pip.</p>
</td>
</tr>
<tr>
<td rowspan="5" width="126">
<p align="CENTER">HTTP</p>
</td>
<td width="103">
<p align="CENTER"><a href="http://jeanphix.me/Ghost.py/">Ghost.py</a></p>
</td>
<td width="401">
<p align="LEFT">Simuler un navigateur Web incluant un moteur de rendu complet (Webkit) et donc JavaScript. Nécessite PySide et donc un gros boulot d’installation.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://pypi.python.org/pypi/mechanize">Mechanize</a></p>
</td>
<td width="401">
<p align="LEFT">Simule un navigateur Web (sans le JavaScript).</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://rg3.github.com/youtube-dl/">Youtube-dl</a></p>
</td>
<td width="401">
<p align="LEFT">Téléchargement des vidéos et metadata sur des dizaines de sites de streaming, de manière uniforme.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://docs.python-requests.org/en/latest/index.html">Requests</a></p>
</td>
<td width="401">
<p align="LEFT">Une surcouche à urllib2 qui rend l’utilisation de requête HTTP belle et agréable.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://github.com/kennethreitz/grequests">Grequest</a></p>
</td>
<td width="401">
<p align="LEFT">Un wrapper de requests utilisant Gevent pour rendre la bibliothèque asynchrone.</p>
</td>
</tr>
<tr>
<td rowspan="5" width="126">
<p align="CENTER">Webservices</p>
</td>
<td width="103">
<p align="CENTER"><a href="https://github.com/simplegeo/python-oauth2">Python-oauth2</a></p>
</td>
<td width="401">
<p align="LEFT">Actuellement le meilleur client pour gérer OAuth en Python.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://fedorahosted.org/suds/">Suds</a></p>
</td>
<td width="401">
<p align="LEFT">La seule bibliothèque efficace et stable pour créer un client SOAP.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://github.com/arskom/spyne">Spyne</a></p>
</td>
<td width="401">
<p align="LEFT">SOAPLib marche très bien pour créer des serveurs SOAP, mais elle est dépréciée. Elle est néanmoins intégrée dans Spyne, qui se veut une solution généraliste pour créer des Webservices.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="https://github.com/jgorset/facepy">Facepy</a></p>
</td>
<td width="401">
<p align="LEFT">Un client pour interagir avec la Graph API de Facebook. Seule alternative à jour depuis l’abandon de FB de sa propre lib et l’absence de mise à jour de facebook-sdk.</p>
</td>
</tr>
<tr>
<td width="103">
<p align="CENTER"><a href="http://pypi.python.org/pypi/twitter/">Twitter</a></p>
</td>
<td width="401">
<p align="LEFT">Un client basique pour interagir avec Twitter.</p>
</td>
</tr>
</tbody>
</table>
<p>Vous pouvez rajouter en com&#8217; toute lib qui vous semble utile. Si je l&#8217;aime, je l&#8217;insérerais dans le poste. Par avance, je vous indique que j&#8217;ai volontairement mis de côté: paste, zope, plone et buildout car à mes yeux leurs valeurs ajoutées ne compensent pas la complexité qu&#8217;elles apportent.</p>


feed_id: http://sametmax.com/?p=3316
title: Je suis à la bourre !!!
uri: Je-suis-à-la-bourre
url: http://sametmax.com/je-suis-a-la-bourre/
content:
<p>Sur ce petit blog cette dernière semaine alors que je me tapais de la Doc de <a href="https://www.varnish-cache.org/">Varnish</a>, <a href="http://www.nginx.com/">Nginx</a> (encore) et encore du <a href="https://docs.djangoproject.com/en/1.4/">Django</a>, je voyais courir les commentaires sur le post de la <a href="http://sametmax.com/les-causes-perdues-de-la-linguistiques/">linguistique</a> de l&#8217;oncle Sam&#8230;<br />
Je ne connais que l&#8217;Esperanto (de nom hein), tout le reste est le trou noir, pire que ma sœur. Je vois défiler des noms barbares de langages ou de types de clavier, etc&#8230;</p>
<div id="attachment_3319" class="wp-caption aligncenter" style="width: 410px"><img class=" wp-image-3319" title="Je vous emmerde...Et je rentre à ma maison..." src="http://sametmax.com/wp-content/uploads/2012/11/the-man-from-earth-2.jpg"?9d7bd4" alt="" width="400" height="225" /><p class="wp-caption-text">Je vous emmerde...Et je rentre à ma maison...</p></div>
<p>Ça me fait penser à un film que j&#8217;ai vu récemment (<a href="http://www.youtube.com/watch?v=ytJBqeI4rRg">the man from earth</a>) qui est un huis-clos sur un homme immortel ayant traversé les âges et qui raconte sa petite histoire à ses amis professeurs d&#8217;Université.<br />
De longue date je n&#8217;ai pas vu de film aussi intéressant, il n&#8217;y a pas d&#8217;effets spéciaux, pas de monstres, mais le film pose des questions intéressantes sur l&#8217;immortalité. Ce n&#8217;est pas un chef d&#8217;œuvre mais je le conseille car il capte vraiment notre attention. Et la fin vous laisse un goût de trop-peu.</p>
<p>En gros l&#8217;immortel du film affirmait que même du haut de ses 14000 ans il n&#8217;était pas plus avancé que le plus avancé des hommes &#8220;mortels&#8221; de la planète, qu&#8217;il n&#8217;était pas surdoué et surtout qu&#8217;il y avait tellement d&#8217;informations qu&#8217;il n&#8217;arrivait tout simplement plus à être au courant de tout comme auparavant et qu&#8217;il a dû donc faire des choix.</p>
<p>Pour en revenir au titre, je trouve que je suis à la bourre ! Je suis pourtant friand d&#8217;infos mais là avec le <a title="Le meilleur de l’actu IT fr, le temps d’un café: le multiboards" href="http://sametmax.com/le-meilleur-de-lactu-it-le-temps-dun-cafe-le-multiboards/">multiboards</a> que je consulte tous les matins je m&#8217;aperçois que je ne peux tout simplement pas suivre toute l&#8217;actu, j&#8217;ai déjà du mal quand je vois vos commentaires sur S&amp;M qui abondent de liens, d&#8217;idées, de concepts, d&#8217;informations pertinentes.<br />
Vivement que la transplantation de puces mémorielles à mise à jour automatique arrive&#8230;</p>
<p>Bref! je suis à la bourre.</p>


feed_id: http://sametmax.com/?p=3272
title: Un seul comment vous tank, et tout est dépeuplé
uri: Un-seul-comment-vous-tank-et-tout-est-dépeuplé
url: http://sametmax.com/un-seul-comment-vous-tank-et-tout-est-depeuple/
content:
<p>Même quand on ne troll pas ou que l&#8217;on s&#8217;exprime de manière policée (ce qui n&#8217;est pas notre cas), on s&#8217;expose toujours à une tarte dans la gueule quand on écrit pour plus de 2 personnes. Je ne parle pas de critiques mais bien de remarques blessantes.</p>
<p>On découvre alors un phénomène amusant : vous pouvez avoir tout le soutient du monde, un seul comment merdique suffit à pourrir la journée. On ne connaît pas le mec. Il a posté 2 lignes. Ça pourrait même être un bot. Ça ne change rien.</p>
<p>Ça marche dans tous les domaines où les gens sont passionnés par leur production car ça leur tient à cœur. Comme les <a href="http://www.altdevblogaday.com/2012/11/21/what-they-dont-tell-you-about-being-a-game-developer/">jeux vidéos</a> ou le <a href="http://theoatmeal.com/comics/making_things">dessin</a>.</p>
<p>Je ne dis pas ça pour me plaindre car ma situation est très confortable.</p>
<p>Mais des fois j&#8217;envie Max : lui il s&#8217;en branle complètement.  Pas comme ces gens qui disent qu&#8217;ils s&#8217;en branlent… Lui il ne dit rien, ou pas grand chose. Et il s&#8217;en branle, mais alors d&#8217;une force !</p>
<p>Je continue de me demander si ce n&#8217;est pas la meilleure stratégie.</p>


feed_id: http://sametmax.com/?p=3352
title: Publication de nos tutos sous une forme groupée
uri: Publication-de-nos-tutos-sous-une-forme-groupée
url: http://sametmax.com/publication-de-nos-tutos-sous-une-forme-groupee/
content:
<p>On écrit un peu à l&#8217;arrache, comme on en a envie.</p>
<p>Avantage, c&#8217;est cooooooooool.</p>
<p>Inconvénient, c&#8217;est chaud de suivre tout ce qu&#8217;on raconte.</p>
<p>Comme tout ce qu&#8217;on dit n&#8217;est pas intéressant, c&#8217;est pas grave. Mais pour la partie tuto, c&#8217;est un peu plus relou.</p>
<p>Alors on vous a mis un petit lien &#8220;cours et tutos&#8221; <strong>dans le menu en haut à droite</strong>. J&#8217;y tiendrais (à jour si possible, mouarf), un listing ordonné et groupé des tutos du blog.</p>
<p>Je vais essayer quoi. Pour voir.</p>


feed_id: http://sametmax.com/?p=3369
title: ASCIINOSCOPE – Viendez-y , on va s’en payer une tra(o)nche !
uri: ASCIINOSCOPE-Viendez-y-on-va-s-en-payer-une-tra(o)nche
url: http://sametmax.com/asciinoscope-viendez-y-on-va-sen-payer-une-traonche/
content:
<h2 style="text-align: center;">AUJOURD&#8217;HUI: ATELIER ARTS PLASTIQUE</h2>
<p>Au détours d&#8217;un concours <a href="http://nodeknockout.com/">nodeknockout</a> j&#8217;ai trouvé une <a href="http://comorichweb.nko3.jitsu.com/">app sympa qui vous asciise le blair</a> via la webcam ou un fichier.</p>
<p>J&#8217;ouvre le pas en y mettant la mienne, si vous avez 2 minutes à perdre immortalisez votre groin et postez nous ça.</p>
<p>Mettez les dans des balises :<br />
<code lang="bash">&lt; pre style="font-size: 7px;line-height:4px"&gt;&lt; /pre&gt;</code></p>
<p><a href="http://comorichweb.nko3.jitsu.com/">Go! Go! Go</a></p>
<pre style="font-size: 7px;line-height: 4px;font-weight: bold;text-shadow: 2px 14px 29px 2px;">

$$=$@@@@@@@@@@@@@@@@=$$$$=======$==$$=$=$$$$=$$=$$$=@$#@@#@$$$$$@$#$$$$$=$$$$$$$$$$=$$$$$$$$$$$$
=$@@@@@@@@@@@@@@@@@@$$======$$$$=$=====$$$$$$$$=$$$$@$@@#@@##$$$@#$$$$$$$$$$$$$$$$$$$$#$$$$$$$$$
=$@@@@@@@@@@@@#@@@@#=$==$===$==$=========$=$=$$#####@@@@@#@###$##@$$$$=$$$$$$$$$$$$$$$$$$$=$$$$$
=$@@@@@@@@@@@@@@@@#$===============$======$$$#@@@$@@@@@@@@@@@@#@@@#$$#$$#$$$$==$$$$$$$$$#$$$$$$$
==@@@@@@@@@@@@@@@@@$==$====$===$==$===$====$$#@@@@@#@@@@@@@@@@@@#@@##@#@#$$$$$$$$=$$$$$==$$$$$$$
=#@@@@@@@@@@@@@@@@@$==$$======$===========$$$###@@#@@@#@@@@@@@##@@@@@@#$$$$$$$$$$$$$=$$$$=$$$$$$
=$@@@@@@@@@@@@@@@@#$======$$===$====$====#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@$$$$$$$$$$$$#$$$$$$$$$
=@@@@@@@@@@@@@@@@@@==================$=$#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#$$=$$$$$$=$=$$#$=$$$$$
$@@@@@@@@#@@@@@@@@@=======$===========$@@@@@@@@@@@@@@@@#@#@@@@@@@@@@@#@$$#$$$=$=$$$$$=$$$$$$$$$$
$@@@@#@@@@@@@@@@@@@==================$@@@@@@@@@@@@@@@@$@@@@@@@@@@@@@@#@@#$$$$$=$$$$$$$$$$$$$$$=$
$@@@@@@@#@@@@@@@@@#==================$@@@@@@@@@@@@@$@@@@@@@@@@@@@@@@##@@$@#@$$$$$$=$$$$$$$$$$$$$
$@@@@@@@#@@@@@#@@@#==================$@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#@@@@###=$$=$$$=$$$$$$$$$$$$
#@@@@@@@@@@@@@#@@@$==================@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#@#$$$$==$=$$$$$#==$$$$$$
@@@@@@@@@@@@@@@@@@#================$#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@$$$=$$$$$$$$$$$$$$$$
@@@@@@@@@@@@@@@@@@$=================@@@@@@@@@$@@@@@@@@@@@@@@@@@@@@@@@@@@@@##$$$$=$$$$$$=$$$$$=$$
@@@@@@@@@@@#@@@@@@$================$@@@@@@@@@$@@@@@@@@@@@@@@@@@@@@@@@@@@@##$=$$=$$$$$$$=$$$$$$$$
@@@@#@@@@@@@@@#@@@=================@@@@@@@@@@#$@@@@@@@@@@@@@@@@@@@@@@@@@@@#$$$==$$$$==$$$$$$$$$$
@@@#@@@@@@@@@@@@@@=================@@@@@@@@@@@#@@@@@@@@@@@@@@@@@@@@@@@@@@@$=$$$$$$$$$$$=$$$==$$$
@@@#@@@@@@@@#@@@@@=================@@@@@@@#####@@@@@@@@@@@@@@@@@@@@@@@@@@@$==$==$==$=$$$$$$$=$$$
@@@@@@@@@@@@@@#@@@=================#@@@@@@$==$#@@@@@@@@@@@@@@@@@@@@@@@@@@#$=$$$$=$$$$=$$$$$$$$$$
@@@@@@@@@@@@@@@@@#=================@@@@@@$*!!!=*$@#@@@@@@@@@@@@@@@#$#@@@@#==$======$==$$=$$$$$$$
@@@@@@@@@@@@@@@@@#=================##@@@@$!;;;!**=#@@@@@@@@@@@#=@$$=$#@@@$=$=$$=$=$=$==$=$$$$$==
@@@@@@@@@@@@@@@@@#================$@#@@@@*;;;;;;;;*=$@@@@@@@#$$=*=**=$@@@===$==$$=$$$==$$=$$$$$$
@@@@@@@@@@@@@@@@@$=================@@@@##!;;:;::::;;!*$@@@@@#$*!!;!*=$@@@$$====$=========$=$==$$
@@@@@@@@@@@@@@@@##=====*===========@@@@#$!;:;:::~~~~::;!=$#$$*;;;;!!*$@@$====$=====$=$=$$$===$$$
@@@@@@@#@@@@@@@##$=*===============#@@@##*;::::~~~-~~--~:!!;:::;;;;!*=#@$=$=======$==$=$$$=$==$$
#@@@@@#@@@@#@@@@#==*=*==============@@@@#=!::::~~~---~,---~~~:::;;;!*=@@$===========$$===$$=$$$$
@@@@@@#@@@@@##@##==*================@@@@#=!:::~~~----,,,---~~:::::;!*=@@==========$==$==$=$=$$=$
@@#@@@#@@@@@#@@@#=============*=====@@@@@$!;::~~~---,-,----~~:::::;!!=@@======$==$=========$$=$$
@@$###@@@@@@@@@@#===================@@@@##*:::~~----,,------~~~:::;!**@@================$=$=$$$=
#@#@@##@@@@@@@@@#=========*=========#@@@@@*:::~~~~--,,,----~~~::::;;*=@$============$=$===$$$==$
@###@#@@@@@@@@@##==============**!:~~~:#@#*:::~~~---,-----~~~~~~~:;!!$#==============$=====$$$$$
@##@@#@@@@@@@@@##========**;:;:~~~--~,,~@@;:::~~--~,-------~~~~~~::;!$===============$=$$$==$$==
@@##@#@@@##@@@@@#==*=*!;;::~~-,,,,,,-,,;::;:::~~---,,,--~--~~~~~~::;!*$=================$===$$$=
@@@#@#@@@@@##@#!:::~~~--,,,,,,,,,,,,-~~~-,;:;:~~--,-,,,---~~---~~:;!!$#=====================$$$$
@@@@@@@@@@#@#$;~~~-~--,,,,,,,,-~;:~~----,,;;::~~-----,,----~--~~::!*$@@================$$===$$=$
@#@@#@@@@@@#*!:~::!;:~--~~;;;::~~-,,,-,,--;;!;:;:::~---------~~:;$#@@@$===================$=$==$
@##@@@@@@@#!!;;;;;;!!!;;::~~~~~--,,,,,-;*;;!*==*=$$$==;~~~~~~~:*#@;*#$==============$======$$==$
##@@#@#@@#*!;;::::~~~-----,,,,,,,,,-~:*#*;;:::=*;$#~;**;:~~~:;*:=*;*=$==$$$=$===========$$$=$$$$
@#@@@@@@$!!:::::~--~~---,,,,,,-,-~!==:!#!;:~~~;;~$*,~::;;~~~:*::;!===$$$$=$==============$==$$$$
##@@#@@$!;:::::~-,,-~-----~--~~;=====::#*!:~~~::~~~:;~~~~~--:*!!!**;*$$$==$=========$=$=$=$$=$$$
#@@@#@*!;:::::-,,,-,-~~~;:~~;========*~!$!;~~-~~::::~~~~~~--~*;:;;;;!$$=$$$$$$===$$====$$$$==$$$
#@@@$*!;;:::~--,,,,-~:;!;=============*=$*;:~----,,,----~~--~!!:;:;;*$$$$=====$$$==$=$$$$$$$=$$$
@@#*!;;:::~~-,,,,,---~!========$======$$#*!:~---,------~~~~-~!!:;;;!=$$$$$$$$$$$$$=$$$$$$$$$$$$$
#=!;;;:::~~,,-------,,~========$===$=$$#@**::~------,---~~~~~;!~:;!*$$$$$$$$$$$$$$==$$$==$$$$$$$
=!;:::::~---~~-~-,,,,,:*===$==$==$=$$$$@@=!;:~-,,,,,,-~~~:~~~;;::!*$$$$$$$$$$$$$$$$$=$$$$$=$$$$$
!;::::~~-~~:~--,,,,,,-:==$$=$====$$=$$$#@=*!::~---,,,-~~::~~-:!:;*=$$$$$$$$$$$$$$$$$$$$$$$=$$$$$
;::::~~~~~~--,--------:**$=$$$=$$$$$$$@@@$!!;:~~---,--::::~~-~!;;*$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
::::~~~~---,,-------,,~**$$==$$$=$$#@@@@@@*;!;:~-----~;:::~--~;!!*$##$$#$$#$$$$$$#$$$$$$$$$$$$$$
:::::~---,----------,,-*=$$$$$$$#@@@@@@@@@!;!;;:~-----;~::~-,~;*!*@@####$#$##$$#$$$$$#$$$$$$$$$$
:::~~---,,,-------,,,,~$$$$$#@@@@@@@@@@@@@$;!!;:~~~---:~~:~,-~!;!=@@@@@@#####$$$###$##$$$$$$$$$$
:~~~----,--------,,,,-!$$#@@@@@@@@@@@@@@@@@!;*!:~~~~~~~~:~::::!!*=@@@@@@@@@@######$$$$$$$$$$$$$$
~~~---,,--,--,,,-----:$@@@@@@@@@@@@@@@@@@@@@!!!!:::~~::~:~::;;!**$@@@@@@@@@@@@####$$#####$$$$$$$
~~-------,-,-------~;*@@@@@@@@@@@@@@@@@@@@@@=!**;:::::::~~:~:;!*=@@@@@@@@@@@@@@@######$#$$#$##$$
~------,,,,,,-----~*@@@@@@@@@@@@@@@@@@@@@@@@@*!*!;;;::::~~:~::!==@@@@@@@@@@@@@@@@@@#######$#$$#$
~----,-,,,,,----~:*@@@@@@@@@@@@@@@@@@@@@@@#@@#***;;:;!!!;;:;!**=#@@@@@@@@@@@@@@@@@@@@@######$$$$
~-,,-----------:=@@@@@@@@@@@@@@@@@@@@@@@@@#@##=!*!;;:;;;:!:::*==@@@@@@@@@@@@@@@@@@@@@@@####$$###
,,,--~~~~~~~~:!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*!*;;;;!;;:;;!*==@@@@@@@@@@@@@@@@@@@@@@@@@@$####$
---~~~:~~::!#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@**!;;;;!!**!*!=@@@@@@@@@@@@@@@@@@@@@@@@@@@@##$#$
~:~~:;!=$@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@**!;::::;;;;*$@@@@@@@@@@@@@@@@@@@@@@@@@@@@#####
!!*=$###@#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#*=!;;::;;;!=@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####
##@#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@**@#*!!;!!!=@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@####
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*=@@@#$$#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@###
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@$*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@~;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@$#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#@@@@@@@#@@=$@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@=#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*=@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#$@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@:;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@##@@@@@@@@@$:@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@</pre>


feed_id: http://sametmax.com/?p=2630
title: Le travail d’écriture dans le domaine du cul
uri: Le-travail-d-écriture-dans-le-domaine-du-cul
url: http://sametmax.com/le-travail-decriture-dans-le-domaine-du-cul/
content:
<p>On associe rarement cul et travail d&#8217;écriture.</p>
<p>C&#8217;est un tort.</p>
<p>C&#8217;est comme d&#8217;autres choses, c&#8217;est bon quand c&#8217;est bien fait !</p>
<p>Par exemple, le très vieux mais excellent film de boule <a href="http://fr.wikipedia.org/wiki/Ma%C3%AEtresses_tr%C3%A8s_particuli%C3%A8res">Maitresses très particulières</a> fait partie de ces œuvres old school qui ont &#8230; un scénario ! Et les acteurs ne sont pas incroyablement mauvais. On y sent presque une une caricature d&#8217;Audiard dans la manière dont ils déclament leur texte. Quand aux répliques, arf, les répliques. Je vous laisse écouter:</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe frameborder="0" width="480" height="360" src="http://www.dailymotion.com/embed/video/x5f7bp" scrolling="no" class="iframe-class"></iframe>
<p>L&#8217;image apporte une vraie valeur ajoutée, mais elle est censurée sur les tubes. Vous pouvez néanmoins facilement trouver le film complet <a href="http://thepiratebay.se/torrent/4624473">ailleurs</a>. Certaines phrases sont tellement mythiques que la masse créatrice du net s&#8217;est amusée à faire des samples pour pouvoir les ressortir à loisir au bureau:</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="560" src="http://htz.usualpro.free.fr/soundboard03.swf" height="480" scrolling="no" class="iframe-class" frameborder="0"></iframe>
<p>J&#8217;attends l&#8217;application smartphone avec impatience.</p>
<p>On sait que le porno est globalement assez pauvre artistiquement, mais quand il s&#8217;agit de parodie, et quand l’œuvre originale est déjà moyenne, on se retrouve avec des choses amusantes. Par exemple, je pense que vous reconnaîtrez ce package complet:</p>
<div id="attachment_3406" class="wp-caption aligncenter" style="width: 560px"><a href="http://sametmax.com/wp-content/uploads/2012/11/Pornav.jpg"?9d7bd4"><img class="size-full wp-image-3406" title="Notez les lunettes 3D et la flashlight bleue... Je vous laisse imaginer les bonus !" src="http://sametmax.com/wp-content/uploads/2012/11/Pornav.jpg"?9d7bd4" alt="Pack DVD collector d'une parodie pornographique d'avatar" width="550" height="303" /></a><p class="wp-caption-text">Notez les lunettes 3D et la flashlight bleue... Je vous laisse imaginer les bonus !</p></div>
<p>Et ce qui est marrant avec ce truc, c&#8217;est que les scènes sont classiques pour du pron, et donc semblent presque plus à propos que la version réelle. Par exemple, la bonasse qui joue le rôle de la meuf qui était jouée par Sigourney Weaver chope le soldat lors de son examen médicale pour la turlutte protocolaire après décryogénisation:</p>
<blockquote><p>It&#8217;s biolab protocol, Marine, gotta do it.</p></blockquote>
<p>\o/</p>
<p>Mais pour avoir du texte bien fendard, on est pas obligé de se pencher sur un boular.  Les canadiens sont très bons pour ce genre de choses. J&#8217;ai particulièrement aimé <a href="http://www.dpstream.net/film-le-declin-de-l-empire-americain-en-streaming-501091.html">Le déclin de l&#8217;empire américain</a>, qui est finalement un film X où les acteurs sont intelligents et habillés:</p>
<blockquote><p><strong>Rémy</strong> : Et puis c&#8217;est pas tout, il faut la faire JOUIR. C&#8217;est pas de la tarte, ça. D&#8217;abord, trouver le clitoris.<br />
<strong>Claude</strong> : Oh mon Dieu !<br />
<strong>Rémy</strong> : Déjà, ça, c&#8217;est une entreprise assez délicate, merci. Y&#8217;a même des cas où c&#8217;est pire que de chercher une chenille sur un damier. Ensuite, t&#8217;as dans la tête toutes les notes, appendices et chapitres de Masters &amp; Johnson, le rapport Hite, la controverse du G spot, Germaine Greer, Nancy Friday&#8230; Tu sais plus si tu dois employer tes doigts, ta langue, ta queue. Là, tu la guettes du coin de l&#8217;oeil. Tu te dis &#8220;Elle a l&#8217;air de&#8230; j&#8217;espère que&#8230; Mais même si&#8230;&#8221; L&#8217;ENFER, L&#8217;ENFER !!</p></blockquote>
<p>Mais souvenez-vous que pour parler cochon, on est pas obligé de faire dans le film. La littérature française abonde (ne serait-ce que les centaines de succulentes phrases du genre &#8221; Vous avez dû en voir de dures, ma pauvre amie! &#8211; - J&#8217;en ai vu davantage de molles!&#8221; de <a href="https://fr.wikipedia.org/wiki/San-Antonio_%28s%C3%A9rie%29">San Antonio</a>), mais surtout, le Web sait se lâcher. Bien sûr, il y a des blogs (je parle pas forcément du nôtre, mais aussi des trucs super marrants comme l&#8217;ancien blog de l&#8217;escorte <a href="http://fr.wikipedia.org/wiki/Belle_de_Jour_%28%C3%A9crivain%29">Belle de jour</a>), mais parfois les pros savent aussi se lâcher. Libé par exemple (ils utilisent Django, c&#8217;est forcément des gens bien), sait parfois <a href="http://www.liberation.fr/cahier-special/010150708-l-italie-branlante">rapprocher les balles des boules</a>:</p>
<blockquote><p>&#8230; Sylvain Wiltord, qui égalise juste avant le clap de fin. Coït interrompu et prolongations-débandade : Trezeguet claque de volée. 2-1 ! But (et couilles) en or pour les Bleus. La Squadra Azzurra va encore faire ceinture. Dix-huit ans que ça dure !</p></blockquote>
<p>Et puis merde, on est des gros pervers dans notre pays. Tous les auteurs classiques ont écrit des trucs polissons. Vous avez étudié Guillaume Apollinaire au collège ? Je suis certain qu&#8217;on vous a pas fait apprendre ce verset par coeur, extrait des <a href="http://fr.wikipedia.org/wiki/Les_Onze_Mille_Verges">Onze Mille Verges</a> :</p>
<blockquote><p>Tes mains introduiront mon beau membre asinin<br />
Dans le sacré bordel ouvert entre tes cuisses<br />
Et je veux t’avouer, en dépit d’Avinain,<br />
Que me fait ton amour pourvu que tu jouisses!</p></blockquote>
<p>Et votre papa, qui écoutait Brassens, validait complètement cet état de fait. Y a pas que les chanteurs de Hard Rock qui mettent du &#8220;Fuck&#8221; partout:</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe frameborder="0" width="480" height="371" src="http://www.dailymotion.com/embed/video/x4gy9w" scrolling="no" class="iframe-class"></iframe>
<p>Sur ce, un whisky ?</p>


feed_id: http://sametmax.com/?p=3395
title: Echaper du HTML en Python ou avec jQuery
uri: Echaper-du-HTML-en-Python-ou-avec-jQuery
url: http://sametmax.com/echaper-le-html/
content:
<p>La question bateau du jour: mais comment transforme-t-on des tags HTML en entités HTML pour sécuriser les inputs utilisateurs qui seront affichées sur le site ?</p>
<h2>En Python</h2>
<p>On peut utiliser le module <code>sax</code>, qui a la base sert à échaper les caractères pour du XML. On va juste étendre sa table de caractères pour rajouter le simple et le double quote.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">xml</span>.<span style="color: black;">sax</span>.<span style="color: black;">saxutils</span> <span style="color: #ff7700;font-weight:bold;">import</span> escape, unescape
&nbsp;
a_echapper = <span style="color: black;">&#123;</span><span style="color: #483d8b;">'&quot;'</span>: <span style="color: #483d8b;">&quot;&amp;quot;&quot;</span>, <span style="color: #483d8b;">&quot;'&quot;</span>: <span style="color: #483d8b;">&quot;&amp;apos;&quot;</span><span style="color: black;">&#125;</span>
a_reconstituer = <span style="color: #008000;">dict</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>value, key<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> key, value <span style="color: #ff7700;font-weight:bold;">in</span> a_echapper.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> echape_html<span style="color: black;">&#40;</span>text, a_echapper=a_echapper<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> escape<span style="color: black;">&#40;</span>text, a_echapper<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> reconstitue_html<span style="color: black;">&#40;</span>text, a_reconstituer=a_reconstituer<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> unescape<span style="color: black;">&#40;</span>text, a_reconstituer<span style="color: black;">&#41;</span></pre></div></div>

<h2>Avec jQuery</h2>
<p>En pur JS, ce sera galère. Mais avec jQuery, c&#8217;est :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'&lt;div&gt;&lt;/div&gt;'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">text</span><span style="color: #009900;">&#40;</span>text_a_echaper<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">html</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Je ne sais pas comment on peut faire facilement l&#8217;opération inverse par contre.</p>


feed_id: http://sametmax.com/?p=3419
title: Transformer des caractères spéciaux en ASCII
uri: Transformer-des-caractères-spéciaux-en-ASCII
url: http://sametmax.com/transformer-des-caracteres-speciaux-en-ascii/
content:
<p>Dans beaucoup de cas, plutôt que de se taper la gestion de l&#8217;encodage, on préfère tout ramener au plus petit dénominateur commun: l&#8217;ASCII. Pas d&#8217;accent, pas de problème, comme disait mon grand-père juif. Ça devait être un autre contexte. Mais quand même.</p>
<h2>Remplacer les accents par leurs équivalents ASCII les plus proches</h2>
<p>Une astuce que j&#8217;ai lue pour la toute première fois dans les excellents <a href="http://www.sebsauvage.net/python/snyppets/">snippets Python</a> de Sauvage (encore et toujours&#8230;).</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">unicodedata</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> chaine_unicode = u<span style="color: #483d8b;">&quot;Vous êtes le Père Noël ? s'étonna le petit garçon.&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">unicodedata</span>.<span style="color: black;">normalize</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'NFKD'</span>, chaine_unicode<span style="color: black;">&#41;</span>.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ascii'</span>, <span style="color: #483d8b;">'ignore'</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">&quot;Vous etes le Pere Noel ? s'etonna le petit garcon.&quot;</span></pre></div></div>

<p>Si un caractère n&#8217;est pas vraiment remplaçable, on peut choisir plusieurs stratégies. Ignorer le caractère:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">unicodedata</span>.<span style="color: black;">normalize</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'NFKD'</span>, u<span style="color: #483d8b;">&quot;Bei Jing en chinois s'écrit 北亰&quot;</span><span style="color: black;">&#41;</span>.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ascii'</span>, <span style="color: #483d8b;">'ignore'</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">&quot;Bei Jing en chinois s'ecrit &quot;</span></pre></div></div>

<p>Remplacer le caractère par un point d&#8217;interrogation:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">unicodedata</span>.<span style="color: black;">normalize</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'NFKD'</span>, u<span style="color: #483d8b;">&quot;Bei Jing en chinois s'écrit 北亰&quot;</span><span style="color: black;">&#41;</span>.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ascii'</span>, <span style="color: #483d8b;">'replace'</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">&quot;Bei Jing en chinois s'e?crit ??&quot;</span></pre></div></div>

<p>Notez l&#8217;effet sur le caractère accentué&#8230;</p>
<p>Ou se vautrer comme une grosse loutre bourrée à la bière:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">unicodedata</span>.<span style="color: black;">normalize</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'NFKD'</span>, u<span style="color: #483d8b;">&quot;Bei Jing en chinois s'écrit 北亰&quot;</span><span style="color: black;">&#41;</span>.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ascii'</span><span style="color: black;">&#41;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;ipython-input-21-24181c80fc7f&gt;&quot;</span>, line <span style="color: #ff4500;">1</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
    <span style="color: #dc143c;">unicodedata</span>.<span style="color: black;">normalize</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'NFKD'</span>, u<span style="color: #483d8b;">&quot;Bei Jing en chinois s'écrit 北亰&quot;</span><span style="color: black;">&#41;</span>.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ascii'</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">UnicodeEncodeError</span>: <span style="color: #483d8b;">'ascii'</span> codec can<span style="color: #483d8b;">'t encode character u'</span>\u0301<span style="color: #483d8b;">' in position 23: ordinal not in range(128)</span></pre></div></div>

<p>Ce qui pour nous a un intérêt limité.</p>
<p>Certains alphabets, comme le hongrois, ont des caractères qui pourraient être extrapolés vers l&#8217;ASCII, mais la normalisation NFKD ne le permet pas. On peut alors faire appel à une bibliothèque externe.</p>
<h2>Unidecode, la cafetière de l&#8217;encoding</h2>
<p><a href="https://github.com/iki/unidecode">Unidecode</a> est une lib <a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a> installable qui permet la translittération de caractères. Ce n&#8217;est pas toujours très rigoureux, mais c&#8217;est toujours très pratique.</p>
<p>Par exemple, vous voulez créer un site Web de mode à destination du marché Hongrois. Si, si. C&#8217;est un marché en pleine expansion, j&#8217;vous dis. </p>
<p>Et bien entendu vous avez une rubrique manteau, qui se dit en hongrois, comme nous le savons tous: &#8220;kožušček&#8221;.</p>
<p>Bon, si vous essayé de mettre ça en slug dans vos URL, ça va être un peu chiant à taper, et malheureusement l&#8217;astuce précédente ne va pas vous aider:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">In <span style="color: black;">&#91;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#93;</span>: <span style="color: #dc143c;">unicodedata</span>.<span style="color: black;">normalize</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'NFKD'</span>, u<span style="color: #483d8b;">&quot;kožušček&quot;</span><span style="color: black;">&#41;</span>.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ascii'</span>, <span style="color: #483d8b;">'replace'</span><span style="color: black;">&#41;</span>
Out<span style="color: black;">&#91;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#93;</span>: <span style="color: #483d8b;">'koz?us?c?ek'</span></pre></div></div>

<p>Partant de là, vous pouvez soit:</p>
<ul>
<li>choisir d&#8217;inviter tous vos utilisateurs à lire <a href="http://fr.wikipedia.org/wiki/%C3%89loge_des_femmes_m%C3%BBres">l&#8217;éloge des femmes mûres</a> dans la langue de l&#8217;auteur et arrêter d&#8217;acheter des manteaux de merde qui sont de toute façon faits en Chine.</li>
<li>soit utiliser <code>unidecode</code>.</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">In <span style="color: black;">&#91;</span><span style="color: #ff4500;">7</span><span style="color: black;">&#93;</span>: <span style="color: #ff7700;font-weight:bold;">from</span> unidecode <span style="color: #ff7700;font-weight:bold;">import</span> unidecode
In <span style="color: black;">&#91;</span><span style="color: #ff4500;">8</span><span style="color: black;">&#93;</span>: unidecode<span style="color: black;">&#40;</span>u<span style="color: #483d8b;">&quot;kožušček&quot;</span><span style="color: black;">&#41;</span>
Out<span style="color: black;">&#91;</span><span style="color: #ff4500;">8</span><span style="color: black;">&#93;</span>: <span style="color: #483d8b;">'kozuscek'</span></pre></div></div>

<h2>
Encore plus fastoche, dans le XML et HTML</h2>
<p>Dans ces formats à balise, on peut s&#8217;affranchir des problème d&#8217;encodage en transformant chaque caractère en une entité XML / HTML. On récupère alors du texte ASCII et le client se tapera le boulot d&#8217;afficher tous les caractères tordus auxquels l&#8217;humanité a pu penser:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">In <span style="color: black;">&#91;</span><span style="color: #ff4500;">11</span><span style="color: black;">&#93;</span>: <span style="color: #ff7700;font-weight:bold;">print</span> u<span style="color: #483d8b;">&quot;Le Père Noël m'a offert un kožušček à 北亰&quot;</span>.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ascii'</span>, <span style="color: #483d8b;">'xmlcharrefreplace'</span><span style="color: black;">&#41;</span>
Le P<span style="color: #66cc66;">&amp;</span><span style="color: #808080; font-style: italic;">#232;re No&amp;#235;l m'a offert un ko&amp;#382;u&amp;#353;&amp;#269;ek &amp;#224; &amp;#21271;&amp;#20144;</span></pre></div></div>

<h2>Et dans tous les autres cas ?</h2>
<p>Ben c&#8217;est comme d&#8217;hab: <code>str.decode()</code> pour tout ce qui rentre pour récupérer une chaîne unicode, et <code>unicode.encode()</code> pour tout ce qui sort pour rebalancer une chaîne de caractères au monde extérieur.</p>
<p>Ça mérite peut être un article d&#8217;ailleurs&#8230;</p>
<p>P.S: <a href="http://sametmax.com/les-10-meilleures-extensions-firefox-chrome/">Lazarus</a> vient de me sauver la mise en restaurant cet article suite à un clic malheureux. Vive lazarus.</p>


feed_id: http://sametmax.com/?p=3446
title: Des idées cadeaux pour Noël
uri: Des-idées-cadeaux-pour-Noël
url: http://sametmax.com/des-idees-cadeaux-pour-noel/
content:
<p>Tous les ans c&#8217;est pareil. On repousse au maximum, on traine et puis arrivent les derniers jours.<br />
Alors on se presse pour aller acheter les cadeaux de Noël.<br />
Et souvent ça se fait le dernier jour dans la grande surface du coin bien sûr bondée d&#8217;autres personnes ayant aussi attendu le dernier moment.</p>
<p>J&#8217;espère que ce post sera complété par vos coms car je fais partie de ces gens là :)</p>
<p><strong>Ma méthode (imparfaite):</strong><br />
Elle consiste en une chose simple préférée des feignasses. Je fuis le centre ville, la périphérie pour rester&#8230;. devant mon ordi.<br />
En fait 90% de mes achats se concentrent sur Amazon, ils ont une option de wishlist que je remplis au fur et à mesure dans l&#8217;année et arrivé à la date fatidique je la complète avec souvent des suggestions et je commande.<br />
Les 10% restant sont en général Champagne, foie gras, hommard.<br />
De cette façon même si mes cadeaux sont pourris on a toujours un bon repas.</p>
<p><strong>N&#8217;achetez jamais un seul gros cadeau !</strong><br />
Un seul cadeau a plus de chance de décevoir et coutera plus cher que plusieurs petits cadeaux. Par exemple je ne vais pas acheter un service à Thé mais plutôt quelques tasses design + un échantillons de Thé + un livre sur l&#8217;histoire du Thé. ça fait plus de cadeaux donc plus de chance d&#8217;en avoir un qui plait.</p>
<p><strong>Procéder par association thématique:</strong><br />
Pour aller encore plus vite je procède par association pour les cadeaux. Comme dit ci-dessus je groupe les cadeaux par famille, la bouffe avec la bouffe, les vêtements avec les vêtements, etc.<br />
De la sorte je lance une thématique par personne et ça accélère encore les choix.<br />
Les suggestions Amazon servent bien en général pour ça.</p>
<div id="attachment_3449" class="wp-caption aligncenter" style="width: 603px"><img class=" wp-image-3449  " title="Amazon smart Suggestion" src="http://sametmax.com/wp-content/uploads/2012/12/amazon.jpg"?9d7bd4" alt="" width="593" height="419" /><p class="wp-caption-text">Un conseiller qui répond à vos attentes...</p></div>
<p><strong>Des cadeaux ciblés:</strong><br />
Avant de commencer à chercher les cadeaux je &#8220;profile&#8221; mes cibles pour connaitre leurs envies du moment et en général. Ça m&#8217;aide à mettre une étiquette sur chacune d&#8217;entre elles et commencer à choisir ses futurs cadeaux.</p>
<p><strong>Quelques idées d&#8217;associations:</strong></p>
<p><em>personne 1: cycliste amateur </em>:-&gt; casque, gants, gourde, lumières, chaussettes, etc<br />
<em>personne 2: aime la cuisine</em> :-&gt; livre de recettes pratiques, kit à fabriquer des sushis, couteau céramique, planche à pizza pour four, etc<br />
<em>personne 3: ado attardé </em> :-&gt; un jeu pour sa gameboy, écouteurs Dr DREE megabass, trousse de rangement pour sa GB, etc<br />
<em>personne 4: la soeur Hilton </em> :-&gt; un rdv chez Sephora pour nettoyage de peau, 1 seance d&#8217;UV, quelques rouges à lèvres copiés sur ceux qu&#8217;elle utilise souvent. Pas de parfum c&#8217;est perso.</p>
<p style="text-align: center;"><strong>Lancer la commande sur Amazon.fr en prenant aussi les rouleaux de papier d&#8217;emballages et y a plus qu&#8217;à attendre.</strong></p>
<p>Et à tout ça en général je propose mes services de cuisinier.</p>
<div id="attachment_3453" class="wp-caption alignright" style="width: 250px"><img class="size-full wp-image-3453" title="Père ducrasse" src="http://sametmax.com/wp-content/uploads/2012/12/ducrasse.jpeg"?9d7bd4" alt="" width="240" height="192" /><p class="wp-caption-text">Et la terrine de chaton ?..</p></div>
<p>Le matin de Noël je vais faire les courses avec 2, 3 personnes, on fait le marché et on choisit les produits frais que l&#8217;on va manger le soir.<br />
C&#8217;est un moment de partage que j&#8217;apprécie, on parle, on est en famille, on déconne, on goûte les produits.</p>
<p>Les cadeaux deviennent moins importants que la bouffe du coup et c&#8217;est pas plus mal car c&#8217;est là que ça se passe, autour d&#8217;une bonne table, en famille ou entre amis.</p>
<p>&nbsp;</p>
<p>Je sais que Sam n&#8217;aime pas Amazon, que certains disent qu&#8217;on fait mourir le commerce de proximité, etc, j&#8217;ai déjà fait quelques aller/retour en ville et je n&#8217;ai jamais trouvé ce que je voulais, obligé donc de rentrer commander sur le Net.<br />
Je garde cependant le côté shopping pour la bouffe et là je ne regarde pas à la dépense, que de la qualité (on a qu&#8217;une vie).</p>
<p>&nbsp;</p>
<p>Bon, à vous de partager vos astuces (celle de voler un caddy plein à la sortie du Mamouth je la connais déjà)&#8230;</p>
<p>&nbsp;</p>
<h2 style="text-align: center;"><strong>Passez de bonnes Vacances et un joyeux Noël</strong></h2>
<p>&nbsp;</p>


feed_id: http://sametmax.com/?p=3431
title: Nginx en reverse proxy + Gunicorn pour vos apps Django
uri: Nginx-en-reverse-proxy-Gunicorn-pour-vos-apps-Django
url: http://sametmax.com/nginx-en-reverse-proxy-gunicorn-pour-vos-apps-django/
content:
<p>Nginx est bien connu depuis quelques années. Puissant serveur HTTP, il peut être utilisé en tant que reverse proxy (mandataire inverse en Français) afin d&#8217;améliorer les performances.<br />
Je vous copie/colle les avantages depuis <a href="http://fr.wikipedia.org/wiki/Mandataire_inverse">Wikipédia</a> parce que je suis une feignasse:</p>
<p><strong>cache :</strong> le mandataire inverse ou (reverse proxy) peut décharger les serveurs Web de la charge de pages/objets statiques (pages HTML, images) par la gestion d&#8217;un cache local. La charge des serveurs Web est ainsi généralement diminuée, on parle alors d&#8217;« accélérateur web » ou d&#8217;« accélérateur HTTP ».<br />
<strong>Intermédiaire de sécurité :</strong> le mandataire inverse protège un serveur Web des attaques provenant de l&#8217;extérieur. En effet, la couche supplémentaire apportée par les mandataires inverses peut apporter une sécurité supplémentaire. La ré-écriture programmable des URL permet de masquer et de contrôler, par exemple, l&#8217;architecture d&#8217;un site web interne. Mais cette architecture permet surtout le filtrage en un point unique des accès aux ressources Web.<br />
<strong>Chiffrement SSL :</strong> le mandataire inverse peut être utilisé en tant que « terminateur SSL », par exemple par le biais de matériel dédié,<br />
<strong>Répartition de charge :</strong> le mandataire inverse peut distribuer la charge d&#8217;un site unique sur plusieurs serveurs Web applicatifs. Selon sa configuration, un travail de ré-écriture d&#8217;URL sera donc nécessaire,<br />
<strong>Compression :</strong> le mandataire inverse peut optimiser la compression du contenu des sites.</p>
<p><strong>Pour résumé:</strong></p>
<p><strong>Visiteur &gt; Web &gt; Votre Serveur &gt; Nginx &gt; Gunicorn &gt; Django<br />
</strong></p>
<p>Dans la configuration suivante Nginx va servir les fichiers statiques (images, js, etc) et envoyer le reste des requêtes sur <a href="http://gunicorn.org/#quickstart">Gunicorn</a>. Gunicorn est une interface WSGI entre le serveur HTTP (nginx) et Python, je n&#8217;ai pas trouvé de bonne explication sur WSGI à part le <a href="http://wsgi.readthedocs.org/en/latest/index.html">site officiel </a>fait par des autistes.</p>
<p><strong>Soit la configuration de Gunicorn suivante (on peut le lancer avec <a href="https://0bin.readthedocs.org/en/latest/fr/using_supervisor.html">supervisor</a>):</strong></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">gunicorn_django  myapp.<span style="color: black;">py</span> --bind 127.0.0.1:<span style="color: #ff4500;">8080</span> --log-<span style="color: #008000;">file</span> /var/log/myapp.<span style="color: black;">gunicorn</span>.<span style="color: black;">log</span> --log-level info --workers <span style="color: #ff4500;">2</span> --pid /tmp/myapp.<span style="color: black;">pid</span>  --worker-<span style="color: #ff7700;font-weight:bold;">class</span> gevent</pre></div></div>

<p>Gunicorn va &#8220;écouter&#8221; en local sur le port 8080, il va logger des infos dans le fichier /var/log/myapp.gunicorn.log (pratique pour le debug si besoin).<br />
Pour les workers et worker-class regardez <a href="http://docs.gunicorn.org/en/latest/configure.html">la doc</a>.</p>
<p><strong>Configurer Nginx: </strong><br />
Dans la conf Nginx on va avoir.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">server <span style="color: black;">&#123;</span>
        listen       <span style="color: #ff4500;">80</span><span style="color: #66cc66;">;</span>
        server_name mysite.<span style="color: black;">com</span> www.<span style="color: black;">mysite</span>.<span style="color: black;">com</span><span style="color: #66cc66;">;</span>
&nbsp;
        location /static/ <span style="color: black;">&#123;</span>
            root  /home/myapp/prod<span style="color: #66cc66;">;</span>
            <span style="color: #dc143c;">gzip</span>  on<span style="color: #66cc66;">;</span>
        <span style="color: black;">&#125;</span>
&nbsp;
        location / <span style="color: black;">&#123;</span>
            proxy_pass http://127.0.0.1:<span style="color: #ff4500;">8080</span><span style="color: #66cc66;">;</span> <span style="color: #808080; font-style: italic;"># Pass to Gunicorn</span>
            proxy_set_header X-Real-IP $remote_addr<span style="color: #66cc66;">;</span> <span style="color: #808080; font-style: italic;"># get real Client IP</span>
        <span style="color: black;">&#125;</span>
<span style="color: black;">&#125;</span></pre></div></div>

<p><a href="http://wiki.nginx.org/HttpCoreModule#location">location</a> va indiquer à Nginx ce qu&#8217;il faut faire lorsqu&#8217;il rencontre certaines URL.</p>
<p>Dans notre cas le <strong>location /static/</strong> va dire à Nginx de servir directement tous les fichiers du répertoire /home/myapp/prod/static pour les URL http://mysite.com/static/&#8230; En général les images, javascript, etc.</p>
<p>Pour le reste <strong>location /</strong> va renvoyer les requêtes sur votre serveur Gunicorn qui va les traiter.</p>
<p>proxy_set_header sert à passer à Gunicorn certaines infos comme l&#8217;<a title="Récupérer l’IP client avec Nginx en proxy sous CherryPy/Django/Bottle – proxy_set_header" href="http://sametmax.com/recuperer-lip-client-avec-nginx-en-proxy-sous-cherrypy-proxy_set_header/">IP réelle du client </a>(sinon Gunicorn verrait celle de NGinx 127.0.0.1).</p>
<p>De cette manière on ne surcharge pas Gunicorn pour servir nos fichiers statiques, on ajoute une protection (Nginx).<br />
On peut éventuellement <a href="http://wiki.nginx.org/HttpProxyModule#proxy_cache">mettre en cache</a> certaines pages mais je n&#8217;ai jamais utilisé cette option.<br />
Nginx peut également distribuer la charge sur plusieurs serveurs et se charger de la <a href="https://developers.google.com/speed/articles/gzip">compression des pages</a> (gzip).</p>


feed_id: http://sametmax.com/?p=3149
title: Usages et dangers du null object pattern en Python
uri: Usages-et-dangers-du-null-object-pattern-en-Python
url: http://sametmax.com/usages-et-dangers-du-null-object-pattern-en-python/
content:
<p>Le motif de conception de l&#8217;objet nul ou &#8220;Null object pattern&#8221; dans la langue de Justin Bieber, est une technique qui consiste à créer un objet qui ne fait rien. Et quand on lui demande de faire quelque chose, il se renvoie lui-même.</p>
<p>Voici à quoi ça ressemble en Python:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Null<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    _instances = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__new__</span><span style="color: black;">&#40;</span>cls, <span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            On s'assure que Null est un singleton, c'est à dire qu'on ne peut
            pas créer deux fois Null. Ainsi, id(Null()) == id(Null()).
&nbsp;
            Je devrais peut être faire un article sur le Singleton.
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> cls <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> cls._instances:
            cls._instances<span style="color: black;">&#91;</span>cls<span style="color: black;">&#93;</span> = <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>Null, cls<span style="color: black;">&#41;</span>.<span style="color: #0000cd;">__new__</span><span style="color: black;">&#40;</span>cls, <span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> cls._instances<span style="color: black;">&#91;</span>cls<span style="color: black;">&#93;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Null accepte n'importe quel argument
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__repr__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            On lui met quand même quelque représentation pour le debug
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;&lt;Null&gt;&quot;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__str__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Null se cast sous forme de chaîne vide. Comme ça vous pouvez
            faire open('fichier').write(Null()) et ça ne fait rien.
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;&quot;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__eq__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Null est égal à lui même, ou à None car on peut les utiliser dans
            des endroits similaires. On peut toujours les distinguer avec &quot;is&quot;.
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">id</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span> == <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>other<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> other <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Comme None, Null() est faux dans un contexte booléen</span>
    <span style="color: #0000cd;">__nonzero__</span> = __bool__ = <span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #008000;">self</span>: <span style="color: #008000;">False</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Et là, on fait le gros travail d'annihilation: toutes les méthodes</span>
    <span style="color: #808080; font-style: italic;"># et opérations du Null() renvoient Null(). Et comme Null() accepte tout</span>
    <span style="color: #808080; font-style: italic;"># et ne fait rien, toute opération marche toujours, ne fait rien, et</span>
    <span style="color: #808080; font-style: italic;"># renvoie une valeur qui assure que les suivantes feront pareil.</span>
    nullify = <span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #008000;">self</span>, <span style="color: #66cc66;">*</span>x, <span style="color: #66cc66;">**</span>kwargs: <span style="color: #008000;">self</span>
&nbsp;
    <span style="color: #0000cd;">__call__</span> = nullify
    <span style="color: #0000cd;">__getattr__</span> = <span style="color: #0000cd;">__setattr__</span> = <span style="color: #0000cd;">__delattr__</span> = nullify
    <span style="color: #0000cd;">__cmp__</span> = <span style="color: #0000cd;">__ne__</span> = <span style="color: #0000cd;">__lt__</span> = <span style="color: #0000cd;">__gt__</span> = <span style="color: #0000cd;">__le__</span> = <span style="color: #0000cd;">__ge__</span> = nullify
    <span style="color: #0000cd;">__pos__</span> = <span style="color: #0000cd;">__neg__</span> = <span style="color: #0000cd;">__abs__</span> = <span style="color: #0000cd;">__invert__</span> = nullify
    <span style="color: #0000cd;">__add__</span> = <span style="color: #0000cd;">__sub__</span> = <span style="color: #0000cd;">__mul__</span> = <span style="color: #0000cd;">__mod__</span> = <span style="color: #0000cd;">__pow__</span> = nullify
    __floordiv__ = <span style="color: #0000cd;">__div__</span> = __truediv__ = <span style="color: #0000cd;">__divmod__</span> = nullify
    <span style="color: #0000cd;">__lshift__</span> = <span style="color: #0000cd;">__rshift__</span> = <span style="color: #0000cd;">__and__</span> = <span style="color: #0000cd;">__or__</span> = <span style="color: #0000cd;">__xor__</span> = nullify
    <span style="color: #0000cd;">__radd__</span> = <span style="color: #0000cd;">__rsub__</span> = <span style="color: #0000cd;">__rmul__</span> = <span style="color: #0000cd;">__rmod__</span> = <span style="color: #0000cd;">__rpow__</span> = nullify
    __rfloordiv__ = <span style="color: #0000cd;">__rdiv__</span> = __rtruediv__ = <span style="color: #0000cd;">__rdivmod__</span> = nullify
    <span style="color: #0000cd;">__rlshift__</span> = <span style="color: #0000cd;">__rrshift__</span> = <span style="color: #0000cd;">__rand__</span> = <span style="color: #0000cd;">__ror__</span> = <span style="color: #0000cd;">__rxor__</span> = nullify
    <span style="color: #0000cd;">__iadd__</span> = <span style="color: #0000cd;">__isub__</span> = __imul__ = <span style="color: #0000cd;">__imod__</span> = <span style="color: #0000cd;">__ipow__</span> = nullify
    __ifloordiv__ = <span style="color: #0000cd;">__idiv__</span> = __itruediv__ = __idivmod__ = nullify
    <span style="color: #0000cd;">__ilshift__</span> = <span style="color: #0000cd;">__irshift__</span> = <span style="color: #0000cd;">__iand__</span> = <span style="color: #0000cd;">__ior__</span> = <span style="color: #0000cd;">__ixor__</span> = nullify
    <span style="color: #0000cd;">__getitem__</span> = <span style="color: #0000cd;">__setitem__</span> = <span style="color: #0000cd;">__delitem__</span> = nullify
    <span style="color: #0000cd;">__getslice__</span> = <span style="color: #0000cd;">__setslice__</span> = <span style="color: #0000cd;">__delslice__</span> = nullify
    __reversed__ = nullify
    <span style="color: #0000cd;">__contains__</span> = __missing__ = nullify
    __enter__ = __exit__ = nullify</pre></div></div>

<p>Certaines méthodes ne peuvent pas retourner <code>Null()</code> car elle sont tenues<br />
par l&#8217;implémentation en C de retourner un certain type. C&#8217;est le cas<br />
des méthode de conversion, d&#8217;itération, d&#8217;approximation ou certaines<br />
renvoyant des metadata comme: <code>__int__</code> , <code>__iter__</code>, <code>__round__</code> ou <code>__len__</code>.</p>
<p>Donc il y aura toujours des cas extrêmes où Null ne marchera pas, mais croyez moi, avec le code ci-dessus, on a déjà couvert un paquet de trucs.</p>
<h2>Comment on s&#8217;en sert</h2>
<p>C&#8217;est la beauté de l&#8217;objet Null, il n&#8217;y a rien à faire d&#8217;autre que l&#8217;instancier. Après il se débrouille tout seul&#8230; pour ne rien faire !</p>
<p><code>Null()</code> accepte tout à la création, et renvoie toujours le même objet :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> n = Null<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> n
<span style="color: #66cc66;">&lt;</span>Null<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>n<span style="color: black;">&#41;</span> == <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>Null<span style="color: black;">&#40;</span><span style="color: #483d8b;">'value'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> == <span style="color: #008000;">id</span><span style="color: black;">&#40;</span>Null<span style="color: black;">&#40;</span><span style="color: #483d8b;">'value'</span>, param=<span style="color: #483d8b;">'value'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">True</span></pre></div></div>

<p>On peut lui demander tout ce qu&#8217;on veut, il retourne <code>Null()</code> :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> n<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> == n<span style="color: black;">&#40;</span><span style="color: #483d8b;">'value'</span><span style="color: black;">&#41;</span> == n<span style="color: black;">&#40;</span><span style="color: #483d8b;">'value'</span>, param=<span style="color: #483d8b;">'value'</span><span style="color: black;">&#41;</span> == n
<span style="color: #008000;">True</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> n.<span style="color: black;">attr1</span>
<span style="color: #66cc66;">&lt;</span>Null<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> n.<span style="color: black;">attr1</span>.<span style="color: black;">attr2</span>
<span style="color: #66cc66;">&lt;</span>Null<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> n.<span style="color: black;">method1</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>Null<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> n.<span style="color: black;">method1</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">method2</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>Null<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> n.<span style="color: black;">method</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'value'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>Null<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> n.<span style="color: black;">method</span><span style="color: black;">&#40;</span>param=<span style="color: #483d8b;">'value'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>Null<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> n.<span style="color: black;">method</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'value'</span>, param=<span style="color: #483d8b;">'value'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>Null<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> n.<span style="color: black;">attr1</span>.<span style="color: black;">method1</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>Null<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> n.<span style="color: black;">method1</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">attr1</span>
<span style="color: #66cc66;">&lt;</span>Null<span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>On peut le modifier, ça ne change rien :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> n.<span style="color: black;">attr1</span> = <span style="color: #483d8b;">'value'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> n.<span style="color: black;">attr1</span>.<span style="color: black;">attr2</span> = <span style="color: #483d8b;">'value'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">del</span> n.<span style="color: black;">attr1</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">del</span> n.<span style="color: black;">attr1</span>.<span style="color: black;">attr2</span>.<span style="color: black;">attr3</span></pre></div></div>

<p>Les opérations sur lui le laissent de glace:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>n<span style="color: black;">&#41;</span> == <span style="color: #483d8b;">''</span>
<span style="color: #008000;">True</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> n + <span style="color: #ff4500;">1</span> / <span style="color: #ff4500;">7</span> <span style="color: #66cc66;">%</span> <span style="color: #ff4500;">3</span>
<span style="color: #66cc66;">&lt;</span>Null<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> n<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span> == n<span style="color: black;">&#91;</span>:<span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span> == n
<span style="color: #008000;">True</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">'test'</span> <span style="color: #ff7700;font-weight:bold;">in</span> n
<span style="color: #008000;">False</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> n<span style="color: black;">&#91;</span><span style="color: #483d8b;">'test'</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&lt;</span>Null<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> Null<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&gt;&gt;</span> <span style="color: #ff4500;">1</span>
<span style="color: #66cc66;">&lt;</span>Null<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> Null<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> == <span style="color: #008000;">None</span>
<span style="color: #008000;">True</span></pre></div></div>

<h2>Chouetttteeeeeee ! Mais ça sert à quoi ?</h2>
<p>Et bien à simplifier les vérifications, et supprimer pas mal de <code>if</code>. Quand vous avez un état inconnu dans votre programme, au lieu de renvoyer <code>None</code>, ou faire des tests dans tous les sens pour éviter de planter, vous pouvez juste renvoyer <code>Null()</code>. Il va continuer sa petite vie dans votre programme, et accepter tout ce qu&#8217;on lui demande, sans rien faire crasher.</p>
<p>Attention cependant, <code>Null()</code> accepte tout silencieusement, et donc votre programme ne plantera jamais là où <code>Null()</code> est utilisé. En clair, si vous merdez et que <code>Null()</code> se retrouve là où il ne doit pas, il va se multiplier et remplir tout votre programme et le transformer en une soupe d&#8217;appels à<code> Null()</code> qui ne foutent rien, mais le font bien, et en silence.</p>
<p>Un design pattern puissant, mais dangereux.</p>
<h2>L&#8217;édit obligatoire</h2>
<p>Suite aux objections tout à fait valides de Moumoutte, je rajoute un exemple d&#8217;usage.</p>
<p>Il faut bien comprendre en effet que <code>Null()</code> n&#8217;est pas un passe droit pour faire n&#8217;importe quoi avec la gestion des erreurs, et n&#8217;est en aucun cas quelque chose à utiliser massivement.</p>
<p>Il est particulièrement utile quand les tests à faire sont juste trop nombreux. Par exemple, dans des secteurs comme la banque ou la biologie, on traite des données en masse, et hétérogènes, mais on fait des opérations entre les différents types.</p>
<p>Certains types sont compatibles, d&#8217;autres pas. Si on a des milliers de types, et des milliers d&#8217;opérations différentes, cela fait des milliers de milliers de combinaisons possibles à évaluer. Dans ce cas, <code>Null()</code> permet de s&#8217;affranchir de tous ces tests et simplifier énormément l&#8217;algo.</p>
<p>Voici un exemple simple de ce que ça donne à petit échelle (multipliez ça par mille types <strong>et opérations</strong> pour avoir un ordre de grandeur d&#8217;un cas réel):</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Chaque type peut faire des opérations uniquement sur d'autres types</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> TypeA<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> operation<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>other, TypeB<span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> other
        <span style="color: #ff7700;font-weight:bold;">return</span> Null<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> TypeB<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> operation<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>other, TypeC<span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> other
        <span style="color: #ff7700;font-weight:bold;">return</span> Null<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> TypeC<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> operation<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>other, TypeD<span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> other
        <span style="color: #ff7700;font-weight:bold;">return</span> Null<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> TypeD<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> operation<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>other, TypeE<span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> other
        <span style="color: #ff7700;font-weight:bold;">return</span> Null<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> TypeE<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> operation<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>other, TypeA<span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> other
        <span style="color: #ff7700;font-weight:bold;">return</span> Null<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># Votre pool de données vous arrive en masse et complètement mélangé.</span>
<span style="color: #808080; font-style: italic;"># Vous n'avez AUCUN contrôle là dessus.</span>
pool = <span style="color: black;">&#40;</span>TypeA, TypeB, TypeC, TypeD, TypeE<span style="color: black;">&#41;</span>
&nbsp;
data1 = <span style="color: black;">&#40;</span><span style="color: #dc143c;">random</span>.<span style="color: black;">choice</span><span style="color: black;">&#40;</span>pool<span style="color: black;">&#41;</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1000</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
data2 = <span style="color: black;">&#40;</span><span style="color: #dc143c;">random</span>.<span style="color: black;">choice</span><span style="color: black;">&#40;</span>pool<span style="color: black;">&#41;</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1000</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
data3 = <span style="color: black;">&#40;</span><span style="color: #dc143c;">random</span>.<span style="color: black;">choice</span><span style="color: black;">&#40;</span>pool<span style="color: black;">&#41;</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1000</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
data4 = <span style="color: black;">&#40;</span><span style="color: #dc143c;">random</span>.<span style="color: black;">choice</span><span style="color: black;">&#40;</span>pool<span style="color: black;">&#41;</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1000</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Avec le Null() object pattern, vous ne vous posez pas la question de quel type</span>
<span style="color: #808080; font-style: italic;"># va avec quoi. Vous faites l'opération comme si tout était homogène. Tout</span>
<span style="color: #808080; font-style: italic;"># va se trier automatiquement.</span>
&nbsp;
res1 = <span style="color: black;">&#40;</span>z.<span style="color: black;">operation</span><span style="color: black;">&#40;</span>y<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> z, y <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">zip</span><span style="color: black;">&#40;</span>data1, data2<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
res2 = <span style="color: black;">&#40;</span>z.<span style="color: black;">operation</span><span style="color: black;">&#40;</span>y<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> z, y <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">zip</span><span style="color: black;">&#40;</span>res1, data3<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
res3 = <span style="color: black;">&#40;</span>z.<span style="color: black;">operation</span><span style="color: black;">&#40;</span>y<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> z, y <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">zip</span><span style="color: black;">&#40;</span>res2, data4<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Et à la fin, il est très facile de récupérer uniquement les données</span>
<span style="color: #808080; font-style: italic;"># significatives.</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>x.__class__.__name__ <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> res3 <span style="color: #ff7700;font-weight:bold;">if</span> x<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Ceci va printer quelque chose comme:</span>
<span style="color: #808080; font-style: italic;"># ['TypeD', 'TypeA', 'TypeE', 'TypeE', 'TypeC', 'TypeE', 'TypeE', 'TypeA']</span></pre></div></div>

<p>On a ainsi réduit un énorme jeu de données hétérogènes en un petit jeu de données significatif, avec très très peu d&#8217;effort et un algo simple et lisible.</p>


