# articles

feed_id: http://sametmax.com/?p=12510
title: Le cercle de ses amis
uri: Le-cercle-de-ses-amis
url: http://sametmax.com/le-cercle-de-ses-amis/
content:
<p>Aujourd&#8217;hui une jolie blonde m&#8217;a trollé en recrachant mon sperme dans mon nombril.</p>
<p>J&#8217;ai trouvé ça hilarant, et j&#8217;ai éclaté de rire.</p>
<p>Elle a pris son sex toy et m&#8217;a dit : &#8220;je jouis encore une fois et on joue à Dota&#8221;. </p>
<p>Et je me suis occupé de ses seins pendant qu&#8217;elle s&#8217;occupait d&#8217;elle.</p>
<p>Je préfère ces moments là aux couchés de soleil, aux fleurs, aux restos avec bougies et aux boîtes de chocolat de la saint valentin.</p>
<p>L&#8217;humanité adore les clichés mais je pense qu&#8217;il appartient à tout à chacun de déterminer ce qu&#8217;on trouve charmant ou non. La partie coton, c&#8217;est de trainer avec des gens qui sont d&#8217;accord sur la question.</p>
<p>Je ne m&#8217;en fais pas trop sur le sujet.</p>
<p>J&#8217;ai Max pour me parler de la dernière thaï atomique qu&#8217;il a trouvé en VOIP.</p>
<p>J&#8217;ai un ami chinois qui m&#8217;a recommandé un super club échangiste alors qu&#8217;on surfait sur des sites de libertins.</p>
<p>J&#8217;ai une copine libanaise qui m&#8217;a signalé une bonne plage nudiste tandis qu&#8217;on mettait à jour son ordinateur sous Ubuntu.</p>
<p>J&#8217;ai un pote espagnol qui m&#8217;a raconté les envies de partouse de sa coloc avec son ex en jouant à LOL.</p>
<p>Geeks et cul, finalement, la formule du blog était pas si bête.</p>


feed_id: http://sametmax.com/?p=12584
title: Automatiser un peu plus SQLAlchemy declarative
uri: Automatiser-un-peu-plus-SQLAlchemy-declarative
url: http://sametmax.com/automatiser-un-peu-plus-sqlalchemy-declarative/
content:
<p>Avec l&#8217;intégration de l&#8217;interface déclarative d&#8217;SQLAlchemy, le projet Elexir est mort, et bien mort. Mais avec lui, la syntaxe la plus simple de déclaration pour cet ORM. En effet, par défaut, SQLA vous oblige à spécifier le nom de la table et l&#8217;attribut ID pour chaque classe :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> sqlalchemy <span style="color: #ff7700;font-weight:bold;">import</span> Column<span style="color: #66cc66;">,</span> Integer<span style="color: #66cc66;">,</span> String
<span style="color: #ff7700;font-weight:bold;">from</span> sqlalchemy.<span style="color: black;">ext</span>.<span style="color: black;">declarative</span> <span style="color: #ff7700;font-weight:bold;">import</span> declarative_base
<span style="color: #ff7700;font-weight:bold;">from</span> sqlalchemy <span style="color: #ff7700;font-weight:bold;">import</span> create_engine
&nbsp;
Base <span style="color: #66cc66;">=</span> declarative_base<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Person<span style="color: black;">&#40;</span>Base<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># explicit is better than... fuck it !</span>
    __tablename__ <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'person'</span> 
    <span style="color: #008000;">id</span> <span style="color: #66cc66;">=</span> Column<span style="color: black;">&#40;</span>Integer<span style="color: #66cc66;">,</span> primary_key<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
    name <span style="color: #66cc66;">=</span> Column<span style="color: black;">&#40;</span>String<span style="color: black;">&#40;</span><span style="color: #ff4500;">250</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> nullable<span style="color: #66cc66;">=</span><span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Animal<span style="color: black;">&#40;</span>Base<span style="color: black;">&#41;</span>:
    __tablename__ <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'animal'</span>
    <span style="color: #008000;">id</span> <span style="color: #66cc66;">=</span> Column<span style="color: black;">&#40;</span>Integer<span style="color: #66cc66;">,</span> primary_key<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># Paie ton DRY</span>
    name <span style="color: #66cc66;">=</span> Column<span style="color: black;">&#40;</span>String<span style="color: black;">&#40;</span><span style="color: #ff4500;">250</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> nullable<span style="color: #66cc66;">=</span><span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
&nbsp;
engine <span style="color: #66cc66;">=</span> create_engine<span style="color: black;">&#40;</span><span style="color: #483d8b;">'sqlite:///db.db.db...db'</span><span style="color: black;">&#41;</span>
Base.<span style="color: black;">metadata</span>.<span style="color: black;">create_all</span><span style="color: black;">&#40;</span>engine<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>SQLA est très flexible, et il existe des tas de raisons pour vouloir un PK ou un nom de table custo. Mais dans beaucoup de projets, le nom de la table peut être le nom de la classe, et la PK peut être un ID auto incrémenté.</p>
<p>Heureusement, la lib vous permet de customiser absolument tout, même la manière dont on doit la customiser. Si c&#8217;est pas méta, tout ça&#8230;</p>
<p>Bref, on peut créer sa propre base déclarative qui va faire tout ça pour nous :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> sqlalchemy.<span style="color: black;">ext</span>.<span style="color: black;">declarative</span> <span style="color: #ff7700;font-weight:bold;">import</span> as_declarative<span style="color: #66cc66;">,</span> declared_attr
&nbsp;
<span style="color: #808080; font-style: italic;"># Ceci sera le parent de tout nos objets</span>
<span style="color: #66cc66;">@</span>as_declarative<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Base<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;"># Vu qu'on a pas vraiment envie de se réécrire la</span>
    <span style="color: #808080; font-style: italic;"># métaclasse, SQLA nous file ce gentil décorateur </span>
    <span style="color: #808080; font-style: italic;"># pour déclarer des attributs qui ne sont pas des </span>
    <span style="color: #808080; font-style: italic;"># champs</span>
    <span style="color: #66cc66;">@</span>declared_attr
    <span style="color: #ff7700;font-weight:bold;">def</span> __tablename__<span style="color: black;">&#40;</span>cls<span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># le nom de la table est le nom de la classe</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> cls.__name__.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># L'id c'est la vie</span>
    <span style="color: #008000;">id</span> <span style="color: #66cc66;">=</span> Column<span style="color: black;">&#40;</span>Integer<span style="color: #66cc66;">,</span> primary_key<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Person<span style="color: black;">&#40;</span>Base<span style="color: black;">&#41;</span>:
    name <span style="color: #66cc66;">=</span> Column<span style="color: black;">&#40;</span>String<span style="color: black;">&#40;</span><span style="color: #ff4500;">250</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> nullable<span style="color: #66cc66;">=</span><span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Animal<span style="color: black;">&#40;</span>Base<span style="color: black;">&#41;</span>:
    name <span style="color: #66cc66;">=</span> Column<span style="color: black;">&#40;</span>String<span style="color: black;">&#40;</span><span style="color: #ff4500;">250</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> nullable<span style="color: #66cc66;">=</span><span style="color: #008000;">False</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Evidemment il faut que vous soyez certains d&#8217;éviter les conflits liés à cette décision, mais c&#8217;est quand même vachement pratique.</p>


feed_id: http://sametmax.com/?p=12561
title: AngularJS pour les utilisateurs de jQuery : partie 2
uri: AngularJS-pour-les-utilisateurs-de-jQuery-partie-2
url: http://sametmax.com/angularjs-pour-les-utilisateurs-de-jquery-partie-2/
content:
<p>Après une intro sans trop de code, on va passer à du concret.</p>
<p><span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='1170' height='689' src='http://www.youtube.com/embed/6Kbv1OpIpaA?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0' allowfullscreen='true'></iframe></span></p>
<p>Pour apprivoiser la bête, on va comme d&#8217;habitude lui faire donner la patte et dire bonjour :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="html" style="font-family:monospace;">&lt;!doctype html&gt;
&lt;!-- Lien entre l'app et la page --&gt;
&lt;html ng-app=&quot;tuto&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot; /&gt;
    &lt;title&gt;Hello Angular&lt;/title&gt;
    &lt;script src=&quot;https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
&nbsp;
    // Déclaration de l'app
    var app = angular.module('tuto', [])
&nbsp;
    // Lancement du code quand angular est prêt
    app.run(function(){
        alert('Hello !')
    })
&nbsp;
    &lt;/script&gt;
  &lt;/head&gt;
  &lt;body&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre></td></tr></table></div>

<p>Pour comprendre ce snippet, il faut réaliser qu&#8217;Angular est d&#8217;abord et avant tout un moyen d&#8217;organiser son code, et qu&#8217;il vous incite à le séparer en conteneurs :</p>
<ul>
<li>Des modules, qu&#8217;on appelle aussi apps. Ce sont les boîtes qui contiennent les autres boîtes. L&#8217;équivalent des apps Django, en fait : on peut mettre tout le programme dedans, mais on peut aussi en faire une lib réutilisable.</li>
<li>Les providers : des fournisseurs de services. Tout le code métier est dedans.</li>
<li>Les directives : tout le code de manipulation du DOM est dedans.</li>
<li>Les contrôleurs : fait le lien entre le HTML et les données.</li>
</ul>
<p>Dans ce code, nous déclarons un module (ou app, c&#8217;est kif-kif) nommé &#8220;tuto&#8221; et n&#8217;ayant aucune dépendance (le second paramètre est un array vide) :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">var</span> app <span style="color: #339933;">=</span> angular.<span style="color: #660066;">module</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'tuto'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span></pre></td></tr></table></div>

<p>Les apps ne font pas grand chose. <strong>Ce sont de gros namespaces avec des dépendances</strong>, c&#8217;est à dire qui déclarent les autres apps nécessaires à leur fonctionnement. Par défaut, aucune autre app n&#8217;est obligatoire pour lancer notre code, donc on ne déclare aucune dépendance.</p>
<p>Il y a juste un piège qu&#8217;il faut connaître. Si je fais :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">var</span> app <span style="color: #339933;">=</span> angular.<span style="color: #660066;">module</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'tuto'</span><span style="color: #009900;">&#41;</span></pre></td></tr></table></div>

<p>(notez l&#8217;absence de second paramètre)</p>
<p>Angular va tenter de me chercher la référence d&#8217;app du nom de &#8220;tuto&#8221; qui existe déjà. L&#8217;absence de dépendance se note donc avec un array vide, et non l&#8217;absence d&#8217;array. Subtilité piégeuse s&#8217;il en est. Vu qu&#8217;on n&#8217;aura pas besoin de déclarer de dépendances avant longtemps, inutile de vous crisper dessus, je vous l&#8217;indique juste pour le débuggage qui va immanquablement arriver le jour où vous oublierez l&#8217;array vide.</p>
<p>Ensuite, on fait le lien entre notre code HTML et l&#8217;app via :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="html" style="font-family:monospace;">&lt;html ng-app=&quot;tuto&quot;&gt;</pre></td></tr></table></div>

<p><code>ng-app</code> est ce qu&#8217;on appelle une directive. Toutes les directives préfixées <code>ng-</code> sont fournies avec le framework et déjà chargées, prêtes à être utilisées. Une directive est un bout de code Javascript appliqué à du HTML, dans ce cas précis via un attribut.</p>
<p>Vous vous souvenez dans les années 2000 comme on vous faisait chier avec le fait de ne pas mettre de Javascript inline dans du HTML ? Les directives, c&#8217;est du Javascript inline qui ne dit pas son nom.</p>
<p><strong>Chaque page doit être liée à une app, et une seule.</strong> Si on ne met pas <code>ng-app</code>, notre code ne se chargera pas, si on en met 2, ça foire. C&#8217;est le point d&#8217;entrée de notre code. Nous déclarons donc que cette page sera gérée par notre app &#8220;tuto&#8221;.</p>
<p>Puis lance notre hello tonitruant :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;">    app.<span style="color: #660066;">run</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        alert<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Hello !'</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span></pre></td></tr></table></div>

<p><code>app</code> est la variable contenant la référence à notre app, et en utilisant la méthode <code>.run</code>, on lui passe un <a href="http://sametmax.com/quest-ce-quun-callback/">callback</a> à appeler quand l&#8217;app sera prête.</p>
<p>Il y a plusieurs choses à réaliser ici :</p>
<ul>
<li>C&#8217;est un callback, donc le code de la fonction ne s&#8217;exécute pas tout de suite. Il sera lancé après l&#8217;initialisation de l&#8217;app.</li>
<li>C&#8217;est ce qu&#8217;il y a de plus proche du <code>$.ready</code> de jQuery.</li>
<li>On n&#8217;utilise presque jamais ce code avec Angular.</li>
</ul>
<p>Vous allez me dire, mais espèce de pignouf, pourquoi tu nous montres un code que personne n&#8217;utilise ?</p>
<p>Et bien parce que le titre du dossier est <em>AngularJS pour les utilisateurs de jQuery</em>, du coup je vous mets en terrain connu.</p>
<p>Mais la vérité, c&#8217;est qu&#8217;un vrai hello d&#8217;Angular ressemble à ça :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="html" style="font-family:monospace;">&lt;!doctype html&gt;
&lt;html ng-app=&quot;tuto&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot; /&gt;
    &lt;title&gt;Hello Angular&lt;/title&gt;
    &lt;script src=&quot;https://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
&nbsp;
    /* La je recréé l'app à chaque fois pour des raisons de praticité, mais
        dans un vrai code vous auriez ça dans un fichier à part, une seule
        fois */
    var app = angular.module('tuto', [])
&nbsp;
    // Création d'un controller, et attachement d'une variable au scope.
    app.controller('HelloCtrl', function($scope){
        // Attachement d'une donnée au scope
        $scope.hello = &quot;Hello&quot;
    })
&nbsp;
    &lt;/script&gt;
  &lt;/head&gt;
  &lt;body ng-controller=&quot;HelloCtrl&quot;&gt;
    &lt;!-- Affichage du message attaché au scope --&gt;
    &lt;h1&gt;{{ hello }}&lt;/h1&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre></td></tr></table></div>

<p>Et là il y a beaucoup à dire.</p>
<p>Premièrement, contrairement à jQuery, il n&#8217;y a pas de notion de préparation du DOM. En vérité, on peut mettre son code Angular en vrac, et Angular va initialiser tout son monde dans le bon ordre, et exécuter ce qu&#8217;il faut au bon moment. Et ce bon moment est parfois avant que le DOM soit prêt.</p>
<p>Mais vous n&#8217;avez pas à vous en soucier.</p>
<p>Car avec Angular, on manipule très rarement le DOM. Très peu de <code>$('selecteur')</code>, <code>$node.bind()</code> et autre <code>$node.append()</code>, à part dans les directives.</p>
<p>La majorité de votre taf va être de définir des données en pur Javascript, de dire où elles vont dans la page, et de les manipuler en Javascript pendant qu&#8217;Angular s&#8217;occupe de mettre la page à jour automatiquement.</p>
<p>Nous avons pas mal de nouvelles notions ici. D&#8217;abord, le contrôleur&#8230;</p>
<p><strong>C&#8217;est un bout de code qu&#8217;on va lier à un bout de HTML</strong> via la directive <code>ng-controller</code> :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="html" style="font-family:monospace;">  &lt;body ng-controller=&quot;HelloCtrl&quot;&gt;
    ...
  &lt;/body&gt;</pre></td></tr></table></div>

<p>Le contrôleur va être responsable de mettre à disposition des données pour ce bout de HTML. On peut lier  autant de contrôleurs qu&#8217;on veut dans une page, et même les imbriquer. Ici, on dit que notre contrôleur <code>HelloCtrl</code> est responsable de mettre des données à disposition pour le tag <code>body</code> et tout ce qu&#8217;il contient.</p>
<p>On fait rarement des contrôleurs qui ratissent aussi large dans de vraies apps, mais pour notre exercice, c&#8217;est très bien.</p>
<p>Comment met-on à disposition des données ? Qu&#8217;est-ce que veut dire &#8220;mettre à disposition&#8221; ? Quelles données ?</p>
<p>Notre contrôleur ressemble à ceci :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="html" style="font-family:monospace;">    app.controller('HelloCtrl', function($scope){
        $scope.hello = &quot;Hello&quot;
    })</pre></td></tr></table></div>

<p>La fonction de callback sera exécutée quand <code>ng-controller="HelloCtrl"</code> sera activé automatiquement par Angular. Vous n&#8217;avez pas à vous souciez de quand, il le fera au moment le plus optimisé.</p>
<p>La seule chose dont vous avez à vous soucier, c&#8217;est ce que vous allez mettre dedans.</p>
<p>Et il y a ici deux nouvelles notions :</p>
<ul>
<li>L&#8217;injection de dépendances.</li>
<li>Le service (je vous explique ce qu&#8217;est un service plus loin) <code>$scope</code>.</li>
</ul>
<p>L&#8217;injection de dépendance fait partie de ces trucs qu&#8217;Angular fait automatiquement pour vous. Quand vous déclarez une variable dans le callback d&#8217;un contrôleur, Angular va chercher ce nom en mémoire, et récupérer le service qui porte ce nom. S&#8217;il ne le trouve pas, il plante.</p>
<p>Une fois qu&#8217;il a trouvé le service, il va attendre tranquillement le bon moment pour appeler le callback. Ce moment opportun arrivant, il va lui passer le service en paramètre. On dit qu&#8217;il lui &#8220;injecte&#8221; le service.</p>
<p>En relisant ces paragraphes, je réalise qu&#8217;il y a un mélange de plein de termes : contrôleurs, services, injection, bla, bla, bla.</p>
<p>Voilà le deal :</p>
<ol>
<li>Vous déclarez un contrôleur et vous le liez à du HTML via <code>ng-controlleur</code>.</li>
<li>Dans ce contrôleur vous dites &#8220;j&#8217;ai besoin du service Machin&#8221;</li>
<li>Angular cherche s&#8217;il connait Machin. Si non, il plante.</li>
<li>Angular prépare le HTML, décide qu&#8217;il est prêt, appelle votre contrôleur et lui passe Machin en paramètre automatiquement.</li>
</ol>
<p>Les services sont justes des d&#8217;objets javascript ordinaires, qu&#8217;on a nommés d&#8217;une certaine manière pour qu&#8217;Angular puisse les injecter. C&#8217;est tout.</p>
<p>En effet, pour résoudre le problèmes d&#8217;espace de nom en Javascript et d&#8217;organisation d&#8217;une grosse application, les créateurs d&#8217;Angular on créé un grand registre. On enregistre notre code dedans sous un nom (<code>Angular.module('nom_de_l_app')</code>, <code>app.controlleur('nom_du_controller')</code>, etc.), et Angular récupère le bon code au bon moment. C&#8217;est essentiellement un moyen de pallier au fait que Javascript est dégueulasse.</p>
<p>Donc, plutôt que de faire des imports comme en Python, on va déclarer une variable en paramètre, et Angular injecte le bon objet pour vous. C&#8217;est bizarre, mais on s&#8217;habitue.</p>
<p>Du coup, là :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;">app.<span style="color: #660066;">controller</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'HelloCtrl'</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>$scope<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span></pre></td></tr></table></div>

<p>Je dis &#8220;crée moi le contrôleur nommé &#8216;HelloCtrl&#8217;, et quand tu vas appeler le callback, passe lui l&#8217;objet nommé &#8216;$scope&#8217; en paramètre. Fais ça au bon moment, je m&#8217;en branle, je veux pas le savoir. Démmerde toi, on a tous des problèmes.&#8221;</p>
<p>Le résultat, c&#8217;est que votre fonction sera exécutée automatiquement au bon moment, et qu&#8217;elle aura <code>$scope</code> qui lui sera passé.</p>
<p>Alors à quoi sert ce <code>$scope</code> ?</p>
<p>C&#8217;est simple : tout ce qui est attaché en attribut de <code>$scope</code> est accessible dans le HTML géré par ce contrôleur. Quand je fais :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;">    app.<span style="color: #660066;">controller</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'HelloCtrl'</span><span style="color: #339933;">,</span> <span style="color: #000066; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>$scope<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        $scope.<span style="color: #660066;">hello</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;Hello&quot;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span></pre></td></tr></table></div>

<p>Et que après je lie mon contrôleur au HTML :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="html" style="font-family:monospace;">  &lt;body ng-controller=&quot;HelloCtrl&quot;&gt;
    &lt;!-- Affichage du message attaché au scope --&gt;
    &lt;h1&gt;{{ hello }}&lt;/h1&gt;
  &lt;/body&gt;</pre></td></tr></table></div>

<p>Ma variable <code>hello</code> est disponible ici (via les petites moustaches qu&#8217;on verra au prochain chapitre), parce que je suis dans <code>body</code> qui est géré par le contrôleur <code>HelloCtrl</code> qui contient un <code>$scope</code> avec l&#8217;attribut <code>hello</code>. Fiou ! Ca en fait des couches. Mais Angular, c&#8217;est comme <del>un orgre</del> un onion.</p>
<p>Vous touchez ici du doigt l&#8217;essence même du boulot des contrôleurs, et à peu près leur unique but : mettre des données à disposition du HTML. C&#8217;est le C de <a href="http://sametmax.com/quest-de-que-mvc-et-a-quoi-ca-sert/">MVC</a>.</p>
<p>C&#8217;est pour cette raison que je vous ai répété &#8220;Angular va tout faire au bon moment, vous n&#8217;avez pas à vous soucier de quand&#8221;. Ceci est en effet très frustrant à entendre quand on vient du monde de jQuery puisque qu&#8217;on doit savoir exactement quand on fait les choses : il faut que le DOM soit prêt, il faut que les éléments sur lesquels on travaille existent, il faut qu&#8217;on puisse récupérer des nodes et en ajouter.</p>
<p>Avec Angular, on ne fait rien de tout ça. On va déclarer ses données dans le contrôleur, et dire où elles doivent être mises dans la page. Angular se charge de faire le lien pour vous quand le HTML est prêt, quand le Javascript est chargé, quand les Dieux sont avec vous&#8230;</p>
<hr />
<a href="https://github.com/sametmax/codes-des-articles/tree/master/2014/octobre"><br />
Télécharger le code de l&#8217;article.</a></p>


feed_id: http://sametmax.com/?p=12601
title: Des idées que j’aurai jamais le temps de faire.
uri: Des-idées-que-j-aurais-jamais-le-temps-de-faire
url: http://sametmax.com/des-idees-que-jaurais-jamais-le-temps-de-faire/
content:
<blockquote><p>Ceci est un post invité de <a href="http://recher.wordpress.com" target="_blank">Réchèr</a> sous licence <a href="http://creativecommons.org/licenses/by/3.0/" target="_blank">creative common 3.0 unported.</a></p></blockquote>
<p>Mon cerveau est absolument génial. Il trouve tout le temps un tas de projets super. Le problème c&#8217;est que mon corps est une grosse feignasse, et ne prend jamais le temps ni le courage de les réaliser. Du coup, je me retrouve avec un tas de bazar dans la tête dont je ne ferais jamais rien. Le mieux, c&#8217;est de l&#8217;offrir au monde.</p>
<p>Il y a un peu de tout : du potentiellement intéressant, du bien débile, et du carrément glauque. C&#8217;est en vrac, faites en ce que vous voulez.</p>
<p>Et puisque ça semble être une tradition pour les articles longs : un peu de musique.</p>
<p><span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='1170' height='689' src='http://www.youtube.com/embed/TboNW5AiHA8?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0' allowfullscreen='true'></iframe></span></p>
<h2>Chocolate DB</h2>
<p><em>&#8220;Maintenant, vous savez sur quoi vous allez tomber&#8221;</em></p>
<p><a href="media/9e6c5611.ipad_chocolate_ichocolates.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/ipad_chocolate_ichocolates.jpg" class="grouped_elements" rel="tc-fancybox-group12601"><img src="media/d45fad4b.ipad_chocolate_ichocolates-300x256.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/ipad_chocolate_ichocolates-300x256.jpg" alt="ipad_chocolate_ichocolates" width="300" height="256" class="alignnone size-medium wp-image-12603" /></a></p>
<p>Repas de Noël en famille. Au moment du café, votre grand-mère pose la traditionnelle boîte de chocolat sur la table. Votre tante est allergique aux noix, votre cousin converti à l&#8217;islam ne boit plus d&#8217;alcool, y compris sous forme de liqueur, et vous, vous voudriez éviter le caramel car ça colle aux dents. Comme chaque année, votre grand-mère a jeté le papier de description de la boîte, parce que &#8220;c&#8217;est écrit trop petit dessus&#8221;.</p>
<p>Le site de recensement Chocolate DB est là pour vous sortir de ce genre de situation délicate, avec des informations détaillées et individuelles de chaque chocolat, dans chaque boîte. Bien évidemment, le site comporte le bataclan habituel : tags, fonctions de recherche, avis des consommateurs, &#8230;</p>
<p>Si ça marche bien, on peut ensuite mettre en place un service d&#8217;échange entre personnes habitants à proximité. Deux machins dégeux à la noix de coco contre un succulent praliné au gianduja ? Ça marche !</p>
<p>Le concept est généralisable à tous ce qui se vend sous forme d&#8217;assortiment : yaourts aux fruits, sachets de thé, bonbons, bières, &#8230;</p>
<h2>Pub&#8217;homme</h2>
<p><a href="media/3141666f.toilet-paper-ad.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/toilet-paper-ad.jpg" class="grouped_elements" rel="tc-fancybox-group12601"><img src="media/3ab954c7.toilet-paper-ad-300x225.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/toilet-paper-ad-300x225.jpg" alt="toilet-paper-ad" width="300" height="225" class="alignnone size-medium wp-image-12605" /></a></p>
<p>Site web de contre-pouvoir à la publicité.</p>
<p>Au début, il y aurait juste des analyses et des recensements, pour mettre en lumière les techniques de fourbe régulièrement utilisées par la publicité :</p>
<ul>
<li>hyperréalité</li>
<li>misandrie</li>
<li>sexualisation injustifiée</li>
<li>flatterie</li>
<li>association arbitraire avec une célébrité</li>
<li>&#8230;</li>
</ul>
<p>Sérieusement, quelqu&#8217;un pourrait me dire ce qu&#8217;il y a de sexuel dans un <a href="http://www.youtube.com/watch?v=9DIH-WYf9MY">putain de clacos</a> ?</p>
<p>Ensuite, il serait envisageable de créer des structures de soutien aux victimes de la publicité. Par exemple :</p>
<ul>
<li>Les techniciens Carglass. Il y a certainement beaucoup de clients qui se foutent de leur gueule, et les plus extrêmes ont peut-être même envie de leur cogner dessus.</li>
<li>Les gens qui s&#8217;appellent Mégane Renault ou Zoé Renault.</li>
<li>Les parents dont les enfants font des caprices à cause des jouets qu&#8217;ils voient dans les publicités.</li>
</ul>
<p>(Parce que tout le monde n&#8217;est pas capable de se défendre aussi bien que <a href="http://www.liberation.fr/societe/2000/05/16/les-leneuf-entendus-par-la-justice-la-campagne-de-pub-de-9telecom-va-etre-temperee_326539">les Leneuf</a>).</p>
<p>Pour finir, on pourrait s&#8217;offrir quelques flash mobs. 500 personnes se retrouvant à une finale de Rolland-Garros pour balancer des Kinder Buenos à la gueule de Jo-Wilfried Tsonga, ça vous tente ?</p>
<h2>Un jeu web avec une économie déflationniste</h2>
<p><a href="media/202f84ac.WoW_stats.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/WoW_stats.jpg" class="grouped_elements" rel="tc-fancybox-group12601"><img src="media/ffeec5ce.WoW_stats-300x146.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/WoW_stats-300x146.jpg" alt="WoW_stats" width="300" height="146" class="alignnone size-medium wp-image-12608" /></a></p>
<p>Si vous lisez ce blog, vous connaissez déjà les bitcoins et les crypto-monnaies. L&#8217;une des raisons pour laquelle ce type de monnaie ne se démocratise pas, c&#8217;est qu&#8217;elles sont déflationnistes, un fonctionnement assez inhabituel. Un jeu web permettrait de le faire découvrir, d&#8217;expérimenter des situations, de détecter des comportements émergents, etc.</p>
<p>Pour le jeu en lui-même, pas la peine de se prendre la tête, il suffirait de reprendre un thème classique : gestion d&#8217;une ferme / d&#8217;un héros / d&#8217;un bar à gigolos &#8230; L&#8217;économie du jeu aurait les particularités suivantes :</p>
<ul>
<li>La quantité totale d&#8217;argent ne change jamais. Au départ, tout est dans la caisse commune du jeu. Pour l&#8217;exemple, mettons qu&#8217;il y ait un million de pièce d&#8217;or.</li>
<li>Les premiers joueurs inscrits reçoivent 100 pièces d&#8217;or, les suivants 50, les suivants-suivants 5, etc. (Au passage, ça incite à s&#8217;inscrire le plus tôt possible). Au bout d&#8217;un moment, les nouveaux arrivés ne reçoivent rien. Ce n&#8217;est pas grave, ça ne les empêche pas de jouer, et de se constituer un capital de départ en produisant et vendant des objets de base aux autres joueurs.</li>
<li>Une pièce d&#8217;or est divisible à l&#8217;infini. Vous pouvez acheter une caisse de patates à 0.0000001 pièce d&#8217;or.</li>
<li>Pour que l&#8217;expérience soit complète, il faut que les joueurs puissent également faire du troc.</li>
</ul>
<p>Ce dernier point comporte un risque, car les joueurs pourront décider d&#8217;utiliser une ressource de base pour leurs échanges, à la place de la monnaie déflationniste. Par exemple, ils définiront leurs prix en caisse de patates, plutôt qu&#8217;en pièces d&#8217;or. Ce risque est toutefois limité. Si la caisse de patate devient de fait la monnaie universelle, tous les joueurs chercheront à en fabriquer. Comme c&#8217;est une ressource de base, elle est très facile à produire, et elle deviendra donc une monnaie hautement inflationniste, en laquelle il sera difficile de faire confiance. Il y aura peut-être cohabitation de plusieurs monnaies. On ne sait pas, mais je pense que ça vaudrait le coup de tester.</p>
<h2>YourCryptoCoins</h2>
<p><a href="media/f202fd01.crypto-coins.jpeg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/crypto-coins.jpeg" class="grouped_elements" rel="tc-fancybox-group12601"><img src="media/f202fd01.crypto-coins.jpeg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/crypto-coins.jpeg" alt="crypto-coins" width="300" height="180" class="alignnone size-full wp-image-12606" /></a></p>
<p>Un logiciel simple pour créer sa propre crypto-monnaie, avec pleins de paramètres à ajuster, histoire de tester s&#8217;il y a plus efficace que le bitcoin :</p>
<ul>
<li>masse monétaire totale.</li>
<li>coût de transaction.</li>
<li>récompense par preuve de travail et/ou preuve de participation. Montant des récompenses.</li>
<li>difficulté de minage.</li>
<li>diminution automatique. (Tous les X jours, le solde de tous les comptes existants baissent de Y%, afin d&#8217;inciter les gens à dépenser leur argent)</li>
</ul>
<p>Ça permettrait aux gens de se créer leur petite crypto-monnaie locale, ce qui est peut-être un peu plus fiable que des bouts de papier imprimés à l&#8217;arrache avec écrit &#8220;Soleil&#8221; dessus.</p>
<h2>Un réseau de communication vraiment décentralisé.</h2>
<p><a href="media/089f5990.semaphore.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/semaphore.jpg" class="grouped_elements" rel="tc-fancybox-group12601"><img src="media/77869bdf.semaphore-300x195.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/semaphore-300x195.jpg" alt="semaphore" width="300" height="195" class="alignnone size-medium wp-image-12610" /></a></p>
<p>Le problème d&#8217;internet, c&#8217;est que les adresses IP sont attribuées par des autorités centrales. Et le support de communication (les fils téléphoniques et le spectre radio) est également sous contrôle central. Je ne sais pas trop comment y remédier, mais ça mérite réflexion.</p>
<p>On pourrait mettre des capteurs et des petites lumières clignotantes sur les toits des maisons, qui se transmettraient les informations entre eux. Concrètement, vous ne pouriez communiquer qu&#8217;avec vos voisins, mais des messages pourraient transiter de maison en maison. Et on utiliserait des uuid pour identifier chaque point du réseau. Avec un système de clé publique-machin-truc pour garantir l&#8217;identifiant de chaque point et éviter les usurpations d&#8217;identité.</p>
<p>Et pour les zones peu densément peuplée, on utiliserait des successions de petites lumières, ou des fils mais gérés de manière décentralisée.</p>
<p>Ce serait sûrement très lent et pas fiable (si vos voisins n&#8217;ont pas allumé leurs transmetteurs, vous ne pouvez plus communiquer). Mais ce serait &#8220;libre&#8221;. Et du coup, pas d&#8217;abonnement à payer, juste de l&#8217;électricité.</p>
<p>C&#8217;est vraiment brumeux comme idée, parce que j&#8217;y connais rien en bidouilleries réseau. Si d&#8217;autres gens ont des améliorations à proposer, qu&#8217;ils n&#8217;hésitent pas.</p>
<h2>Poilatout</h2>
<p><a href="media/1877fc0a.cousin_machin.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/cousin_machin.jpg" class="grouped_elements" rel="tc-fancybox-group12601"><img src="media/bcf39cb8.cousin_machin-214x300.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/cousin_machin-214x300.jpg" alt="cousin_machin" width="214" height="300" class="alignnone size-medium wp-image-12611" /></a></p>
<p>Algorithme, qui, à partir d&#8217;une phrase donnée, renvoie le &#8220;poil au&#8221; correspondant.<br />
Exemple :<br />
<em>&#8220;Quand l&#8217;imbécile montre la Lune&#8221;</em><br />
 -> <em>&#8220;poil aux burnes&#8221;</em><br />
<em>&#8220;Le sage lui met un doigt&#8221;</em><br />
 -> <em>&#8220;poil au foie&#8221;</em></p>
<p>Y&#8217;a plus qu&#8217;à plugger ça avec Siri, et votre smartphone vous permettra de spammer toutes vos conversations de &#8220;poil au&#8221;.</p>
<p>Si ça sert à rien, c&#8217;est que c&#8217;est indispensable.</p>
<h2>Mi-tik</h2>
<p><em>&#8220;Trouvez votre moitié&#8221;.</em></p>
<p><a href="media/6c264e15.half_man_Andy_Gross.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/half_man_Andy_Gross.jpg" class="grouped_elements" rel="tc-fancybox-group12601"><img src="media/6c264e15.half_man_Andy_Gross.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/half_man_Andy_Gross.jpg" alt="half_man_Andy_Gross" width="186" height="159" class="alignnone size-full wp-image-12613" /></a></p>
<p>Vous êtes unijambiste de la jambe gauche. Vous vous inscrivez sur le site Mi-tik. Vous avez alors la possibilité d&#8217;être mis en relation avec des unijambistes de la jambe droite. Si vous trouvez quelqu&#8217;un qui vous correspond, vous obtenez 50% de réduction sur tous vos achats de chaussures.</p>
<p>Le site permet également de faire se rencontrer les manchots d&#8217;un bras, les borgnes, les &#8220;Van Gogh&#8221;, les hémiplégiques, &#8230;</p>
<h2>HarDis (Harcèlement Distribué).</h2>
<p><em>&#8220;Pensez dystopie globale, agissez dystopie locale&#8221;.</em></p>
<p><a href="media/ecd7bcad.dented-car-chuck-norris.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/dented-car-chuck-norris.jpg" class="grouped_elements" rel="tc-fancybox-group12601"><img src="media/ecd7bcad.dented-car-chuck-norris.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/dented-car-chuck-norris.jpg" alt="dented-car-chuck-norris" width="250" height="165" class="alignnone size-full wp-image-12614" /></a></p>
<p>La loi française ne vous interdit pas de chier sur le palier de votre voisin, de rayer sa voiture ou de l&#8217;appeler à 2 heures du matin. Mais elle vous interdit de le faire de manière répétée. Ça s&#8217;appelle du harcèlement.</p>
<p>Le &#8220;réseau d&#8217;entraide HarDis&#8221; permet de s&#8217;affranchir de ce détail. Vous vous y inscrivez en déclarant un périmètre géographique d&#8217;action. Vous recevez ensuite des missions, vous demandant d&#8217;agir chez une personne-cible. Vous ne recevez jamais deux missions sur une même personne. À chaque fois que vous en effectuez une, vous envoyez une preuve de réalisation (photo, vidéo, &#8230;) et vous gagnez des points. Vous pouvez dépenser ces points pour créer des missions sur des gens que vous n&#8217;aimez pas.</p>
<p>L&#8217;identité et l&#8217;adresse des personnes-cibles est révélée le plus tard possible. Chaque compte a un indice de confiance, visible par tous, qui augmente lorsqu&#8217;on effectue une mission et diminue lorsqu&#8217;on en prend une et qu&#8217;on ne l&#8217;effectue pas. Le but étant de limiter les &#8220;espions&#8221; (des personnes qui ne veulent pas réaliser de missions, mais qui veulent juste surveiller si elles ne sont pas la cible de missions existantes).</p>
<p>Bien entendu, vous pouvez acheter des points, et bien entendu tous les outils d&#8217;anonymat sont disponibles : réseau Tor, crypto-monnaie, &#8230;</p>
<h2>ADN-Fuck</h2>
<p><em>&#8220;Là où y&#8217;a des gènes, y&#8217;a du plaisir&#8221;.</em></p>
<p><a href="media/0ef1e032.ensalada-de-pasta.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/ensalada-de-pasta.jpg" class="grouped_elements" rel="tc-fancybox-group12601"><img src="media/34961064.ensalada-de-pasta-300x212.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/ensalada-de-pasta-300x212.jpg" alt="ensalada-de-pasta" width="300" height="212" class="alignnone size-medium wp-image-12615" /></a></p>
<p>La société ADN-Fuck rachète vos petits déchets corporels : salive, poils, sang, peaux mortes, urine, sperme&#8230; Elle les mélange avec ceux de centaines de personnes, et revend le tout sous forme de petit sachet.</p>
<p>Quelqu&#8217;un souhaitant commettre un acte illégal peut acheter l&#8217;un de ces sachet d&#8217;anonymisation, et le répandre sur les lieux de son acte. Bonne chance à la police scientifique pour retrouver l&#8217;ADN du coupable !</p>
<p>La société ADN-Fuck en elle-même ne commet rien d&#8217;illégal. Le commerce de poils de cul est, à priori, toujours autorisé dans la plupart des régions du globe.</p>
<h2>RoboCraft</h2>
<p><a href="media/3a4a53ce.minecraft_robot.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/minecraft_robot.jpg" class="grouped_elements" rel="tc-fancybox-group12601"><img src="media/ab9c6220.minecraft_robot-300x168.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/minecraft_robot-300x168.jpg" alt="minecraft_robot" width="300" height="168" class="alignnone size-medium wp-image-12616" /></a></p>
<p>Un jeu vidéo comme Minecraft, mais avec des robots programmables (en python, évidemment !). On peut les faire miner, construire, explorer, transformer des ressources, etc.</p>
<p>Il y a déjà un add-on de Minecraft pour ça (ComputerCraft), mais c&#8217;est pas quelque chose de très officiel. Du coup, tout l&#8217;équilibrage du jeu est fait sans tenir compte de ComputerCraft. Un jeu conçu spécialement avec des robots, ce serait super chouette.</p>
<p>Ça rejoint le concept d&#8217;automatic-play, dont on parle ici ou là : <a href="http://gamestudies.org/1301/articles/depaoli_automatic_play">http://gamestudies.org/1301/articles/depaoli_automatic_play</a></p>
<p>Et il faudrait une économie déflationniste dans le jeu. Et des robots à reconnaissance vocale qui disent &#8220;poil au cul&#8221;.</p>
<h2>Multi-versus</h2>
<p><a href="media/b096ece0.multi_versus.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/multi_versus.jpg" class="grouped_elements" rel="tc-fancybox-group12601"><img src="media/ad83ef79.multi_versus-300x102.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/multi_versus-300x102.jpg" alt="multi_versus" width="300" height="102" class="alignnone size-medium wp-image-12617" /></a></p>
<p>Un jeu vidéo composé de mini-jeux, dans lequel deux joueurs ou plus s&#8217;affrontent, chacun avec un mini-jeux différent.</p>
<p>Par exemple, le joueur 1 (Tetris) affronte le joueur 2 (Puzzle Bobble). Lorsque le joueur 1 effectue des actions valorisantes, (détruire plusieurs lignes à la fois), il envoie de la difficulté au Puzzle Bobble du joueur 2 (des bulles noires impossible à détruire). Et vice-versa : si le joueur 2 détruit plus de 3 bulles d&#8217;un coup, il envoie des lignes de cochonnerie sur l&#8217;aire de Tetris du joueur 1.</p>
<p>Ce n&#8217;est faisable qu&#8217;avec des mini-jeux ou chacun joue sur son terrain (pas de Bomberman ni de Pong, par exemple), et ce serait une galère monumentale pour les équilibrer entre eux, mais ça serait vraiment fun.</p>
<h2>Un format de fichier pour décrire des dessins animés.</h2>
<p>Ce serait un format human-readable. C&#8217;est très important, car ça augmente la potentialité de bidouillage par n&#8217;importe qui, y compris des gamins de 8 ans.<br />
Ça pourrait ressembler à ceci par exemple :</p>
<pre>
img_balle = http://s2.postimg.org/w709hznpx/balle.png
img_balle_ecrase = http://s18.postimg.org/hy41jochx/balle_ecrase.png
area = 147, 275
default_time = 5 ms

ball = Sprite(img_balle, 20, 0)
ball.move(0, 10)
ball.move(0, 10)
ball.move(0, 10)
ball.change_img(img_balle_ecrase)
ball.move(0, -10)
ball.move(0, -10)
ball.move(0, -10)
</pre>
<p>Et ça donnerait quelque chose de ce genre :</p>
<p><a href="media/f1075302.bounce_147.gif" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/bounce_147.gif" class="grouped_elements" rel="tc-fancybox-group12601"><img src="media/f1075302.bounce_147.gif" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/bounce_147.gif" alt="bounce_147" width="147" height="275" class="alignnone size-full wp-image-12619" /></a></p>
<p>Et ensuite, on pourrait faire plein de trucs avec ce format de fichier :</p>
<ul>
<li>des players web, des players desktop, des éditeurs, des extracteurs d&#8217;images,</li>
<li>des vidéos online (les images et les sons sont indiqués par des urls de téléchargement) et des vidéos stand-alone (tout est embarqué dans un .zip),</li>
<li>des options de sous-titres, de commentaires, d&#8217;audio-description, d&#8217;adaptation aux daltoniens et aux épileptiques,</li>
<li>des convertisseurs vers des fichiers vidéos classiques et vers du gif animé,</li>
<li>des méta-données pour les credits, la licence, le rating ESRB,</li>
<li>et bien d&#8217;autres choses encore !</li>
</ul>
<p>Vous allez me dire : &#8220;mais il y a déjà plein de trucs qui font ça : le flash, les gifs animés, Blender&#8230;&#8221;</p>
<p>Oui, sauf que le flash c&#8217;est pas libre, les gifs c&#8217;est pas optimisé et c&#8217;est super compliqué à reprendre et à bidouiller, et Blender, il faut des mois de pratique avant de savoir faire quelque chose de correct.</p>
<p>Ce format de fichier permettrait de créer rapidement des petits trucs à l&#8217;arrache, des cartes de vœux, des memes animés, etc. Et comme c&#8217;est du texte, c&#8217;est versionable et éditable collaborativement.</p>
<h2>Githubiser pleins de trucs.</h2>
<p><a href="media/8c265b3c.github-octocat.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/github-octocat.jpg" class="grouped_elements" rel="tc-fancybox-group12601"><img src="media/03682427.github-octocat-300x244.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/github-octocat-300x244.jpg" alt="github-octocat" width="300" height="244" class="alignnone size-medium wp-image-12620" /></a></p>
<p>Alors voilà, vous êtes un musicien et vous faites un solo de flûte à bec comme ça pour déconner. Vous le mettez sur gitsound. Quelqu&#8217;un d&#8217;autre arrive et ajoute une ligne de basse. Un autre y met quelques paroles. Un autre refait votre air initial avec une guitare électrique. Un autre reprend le tout en accéléré. Un autre y ajoute un &#8220;Cher effect&#8221; et colle un flow de rap par dessus. Et ainsi de suite.</p>
<p>Ou alors, vous êtes un modéliseur 3D et vous commencez à créer un arbre géant. Quelqu&#8217;un arrive et ajoute des mini-branches pour lui donner un air plus détaillé. Un autre met des textures plus belles pour les feuilles. Un autre creuse un trou à l&#8217;intérieur. Un autre le recopie en 1000 exemplaires sur un quadrillage pour en faire un décor de clip de Mark Gormley. Et ainsi de suite.</p>
<p>Il y a plein d&#8217;autres trucs qu&#8217;on pourrait githubiser afin de faciliter la création collaborative : les images (vectorielles ou pas), les recettes de cuisine, les règles de jeux de société, les dessins animés, les positions du kama-sutra, &#8230; Et pour certains médias, le github de base, qui ne permet de traiter que du texte, ne suffit pas.</p>
<h2>Un Tolkien de la culture africaine</h2>
<p><a href="media/e4076de7.blackfoot-medicine-man-right.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/blackfoot-medicine-man-right.jpg" class="grouped_elements" rel="tc-fancybox-group12601"><img src="media/c7b73841.blackfoot-medicine-man-right-250x300.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/11/blackfoot-medicine-man-right-250x300.jpg" alt="blackfoot-medicine-man-right" width="250" height="300" class="alignnone size-medium wp-image-12621" /></a></p>
<p>Tolkien connaissait toutes les légendes de son pays et d&#8217;ailleurs. Il a défini la plupart des éléments de l&#8217;heroic fantasy. Sans lui, pas de Donjons et Dragons, de World of Warcraft, ou de Harry Potter. Maintenant, l&#8217;heroic fantasy vole de ses propres ailes et emprunte des éléments à d&#8217;autres cultures : momies égyptiennes, ninjas asiatiques, doppelgängers teutons, mind flayer lovecraftien, &#8230;</p>
<p>Mais à part les zombis, on trouve très peu de choses empruntés à la mythologie africaine. C&#8217;est vraiment dommage, car avec le foisonnement culturel de ce continent, on pourrait créer des mondes imaginaires de dingue, peuplés de créatures étranges et de magie aux règles complexes, très différent de l&#8217;heroic fantasy.</p>
<p>Il faudrait une personne qui connaisse tous ces trucs (l&#8217;animisme, le vaudou, les totems, les esprits, &#8230;) et qui s&#8217;en inspire pour écrire une chiée de bouquins. Ensuite, les rôlistes, les gamers et J.K. Rowling feront le reste.</p>
<p><br/></p>
<p>Voilà, ce sera tout pour le moment. Phosphorez mes braves, phosphorez !! Et si l&#8217;une de ces idées existe déjà réellement, prévenez-moi, ça m&#8217;intéresse.</p>


feed_id: http://sametmax.com/?p=12632
title: Pas de bras et pas de chocolat
uri: Pas-de-bras-et-pas-de-chocolat
url: http://sametmax.com/pas-de-bras-et-pas-de-chocolat/
content:
<p>On avait pas d&#8217;articles, on a pas de forum, et on aura de nouveau pas d&#8217;articles.</p>
<p>C&#8217;est à peu près le résumé de ces derniers jours.</p>
<p>Je m&#8217;étais lancé dans l&#8217;installation de Discourse pour avoir un petit forum pour accompagner le blog, et du coup je n&#8217;ai pas écrit. </p>
<p>Mais c&#8217;est un FAIL. Et du coup on a pas de forum.</p>
<p>Foxmask et Gordon ont proposé d&#8217;installer ça sur leurs machines, du coup on aura peut être quelque chose quand ils auront fait leur bidouille.</p>
<p>Mais je me casse dans un endroit où je n&#8217;auras pas accès au téléphone ou internet pendant 10 jours, du coup y aura pas d&#8217;articles ces deux semaines non plus.</p>
<p>Du coup je fais un post bien long pour dire qu&#8217;il ne se passera rien, si c&#8217;est pas du vrai journalisme ça !</p>


feed_id: http://sametmax.com/?p=12677
title: Est-ce que tu peux rendre ça configurable ?
uri: Est-ce-que-tu-peux-rendre-ça-configurable
url: http://sametmax.com/est-ce-que-tu-peux-rendre-ca-configurable/
content:
<p>Il y a cette manie qui traîne, cette idée que si quelque chose n&#8217;est pas dans un fichier de configuration, un outil manque de souplesse. Que si il n&#8217;y a pas un <code>settings['truc']</code>, ça va être compliqué si on veut le changer plus tard.</p>
<p>Et dans de nombreux langages bas niveaux, ça se vérifie.</p>
<p>Mais quand on code en Python, Ruby, PHP ou Javascript, et d&#8217;autant plus avec des gros frameworks d&#8217;abstraction, <strong>le code est déjà une forme de configuration.</strong></p>
<p>Souvent les clients me demandent de découpler mon code pour le rendre plus souple, plus flexible. Avec des options pour le rendre configurable. Et c&#8217;est une bonne chose.</p>
<p>Cependant il faut comprendre qu&#8217;il y a déjà tellement de design patterns embarqués dans nos outils modernes (iterator, generator, indexable, sliceable&#8230;), tellement de facilités offertes par les paradigmes actuels (typage dynamique, late binding, duck typing, bytecode, etc.) qu&#8217;un programme qui n&#8217;a pas été écrit comme un porc propose déjà une large marge de manœuvre.</p>
<p>Il est vrai qu&#8217;avec l&#8217;expérience, on écrit plus vite un code de meilleur qualité, et que, naturellement, on a tendance à laisser des hooks par ci, des opportunités d&#8217;injecter des dépendances par là. Surtout si on fait des tests unitaires.</p>
<p>Néanmoins, trop souvent, il sera demandé de pouvoir &#8220;rendre cette partie adaptable&#8221;, &#8220;faire en sorte qu&#8217;ici on puisse switcher d&#8217;implémentation&#8221; ou &#8220;je veux pouvoir changer d&#8217;avis plus tard&#8221;.</p>
<p>On peut déjà le faire.</p>
<p>Je suis programmeur, Python me parle. Un bon dev de la même techno trouvant mon code pourra modifier une bonne partie de mon travail pour obtenir un résultat différent.</p>
<p>Il n&#8217;y a pas forcément besoin d&#8217;une entrée en plus dans le <code>.ini|json|conf|bak|old|~|/dev/null</code>, d&#8217;un paramètre <code>backend</code>, de 2 jours de taf de plus pour rendre adaptable quelque chose qui peut être édité facilement.</p>
<p>De nombreuse fois, il est plus aisé de modifier, casser, remplacer, et même copier / coller.</p>
<p>Ce n&#8217;est pas écrit dans les bouquins sur les bonnes pratiques, mais c&#8217;est notre métier de coder. On est bons pour ça. On est rapides. Efficaces.</p>
<p>Si la fonctionnalité est un besoin avéré qu&#8217;il faudra pouvoir activer et désactiver en prod, bien entendu, il faut une option.</p>
<p>Mais si il faut couvrir un besoin futur hypothétiquement potentiel, laissez le dev décider si c&#8217;est YAGNI, on peut gagner beaucoup en productivité en pariant que modifier le code quand le besoin se présentera est la démarche la plus simple.</p>
<p>L&#8217;équilibre entre la dette technique et la sur-ingénierie permet de garder un projet sur les rails.</p>


feed_id: http://sametmax.com/?p=12665
title: To shave or not to shave ?
uri: To-shave-or-not-to-shave
url: http://sametmax.com/to-shave-or-not-to-shave/
content:
<p>Le sexe fait parti de ces choses qui ne font pas l&#8217;unanimité. Pour rien.</p>
<p>Il n&#8217;y a qu&#8217;à lire les commentaires de nos articles d&#8217;opinion (<a href="http://sametmax.com/comment-tailler-une-pipe/">comment tailler une pipe</a>, <a href="http://sametmax.com/sol-do-mi-sol-do-mi-sol-do-mi/">la sodomie</a>, etc) pour illustrer les avis divergents sur la question.</p>
<p>Mais rien ne m&#8217;a semblé plus sujet à désaccord que la question de la pilosité.</p>
<p>Chez la femme, bien entendu, il y a l&#8217;épilation aisselles, jambes et maillot. Alors que les touffes sous les bras sont rarement un débat velu, le reste est déjà plus flou.</p>
<p>D&#8217;un côté, la majorité des hommes, selon un sondage officiel de l&#8217;INDMS, vous répondront qu&#8217;ils aiment la sensation de douceur d&#8217;un mollet imberbe. D&#8217;un autre, combien de gars se sont dit &#8220;nan, je vais trop pas coucher avec elle, elle est pas épilée&#8221;. J&#8217;en ai rencontré deux dans ma vie.</p>
<p>Détail amusant, quand on sait à quel point certaines meufs sont paniquées à l&#8217;idée de s&#8217;envoyer en l&#8217;air le premier soir si elles n&#8217;ont pas fait place nette. Surtout qu&#8217;un bas nylon coquinement gardé sera souvent fort apprécié, c&#8217;est dire si le mâle n&#8217;est pas difficile à satisfaire.</p>
<p>Mais le plus houleux, c&#8217;est la teuch.</p>
<p>Parce que si le film adulte main stream s&#8217;est mis à montrer des abricots chauves partout, ce n&#8217;est pas un hasard, c&#8217;est le résultat d&#8217;un ajustement au marché. Mais dans la VVV, on rencontre de tout. Ceux qui aiment avec, sans, en ticket de métro ou avec juste un pompon pour le clito. Une chance sur cinq de déplaire, selon notre échantillon représentatif de 5 personnes au dîner d&#8217;hier.</p>
<p>Et là c&#8217;est compliqué. Parce qu&#8217;un type qui n&#8217;aime pas la forêt tropicale va sans doute sauter la case broutage de pelouse, une étape de jardinage qui a son importance. Quel dommage.</p>
<p>En prime, pour rendre les choses bien plus amusantes, c&#8217;est aussi une question de culture. Au japon, les nanas ont l&#8217;entre-jambes fleuri, c&#8217;est pas de la paresse, c&#8217;est la loi de l&#8217;offre et la demande. En revanche, certaines femmes musulmanes très voilées ont l&#8217;entre-cuisses lisse qui glisse. Délice ou vice ?</p>
<p>Chez l&#8217;homme, c&#8217;est comme d&#8217;hab, moins clair encore.</p>
<p>Déjà vous avez le problème de la calvitie, des poils de tronc et celui de porter la barbe qui se rajoutent. Il y toujours moyen de déplaire à 30% du public, quoi qu&#8217;on fasse.</p>
<p>Et comme le modèle marketing du mec torride est sans poil, jusque sur les coucougnettes, on pourrait penser que c&#8217;est aussi une représentation empiriquement choisie. Fi, on m&#8217;a demandé bien souvent de laisser se garnir mon service 3 pièces car &#8220;ça fait acteur porno sinon&#8221;. Comprenons donc bien, qu&#8217;il n&#8217;y aucune garantie d&#8217;aller dans le sens du poil.</p>
<p>Mais ne coupons pas les cheveux en quatre, que faire ?</p>
<p>Du pareto, bien sûr !</p>
<p>Je connaissais un gars qui disait, les poils, ça n&#8217;a sa place que sur la tête. Sans rentrer dans les extrêmes tirés par les cheveux, les hommes peuvent, plutôt que de se raser ou s&#8217;épiler, se tondre. Ça fait propre, mais pas trop. Ça demande de la maintenance, c&#8217;est sûr, et aussi de se promener avec une tondeuse, ce qui est bien relou. Il ne faut pas avoir un poil dans la main pour ce genre de chose.</p>
<p>Max a tenté l&#8217;épilation définitive des burnes avec une machine à utiliser chez soi. Aux dernières nouvelles il a abandonné en cours de route à son départ pour l&#8217;Asie. Je ne puis donc vous en dire plus.</p>
<p>On pourra se consoler en disant que c&#8217;est plus chiant encore pour les nanas. Tout arracher est en effet encore le pari le plus sûr. Au pire quelqu&#8217;un qui aime jouer sur gazon sera plus tolérant qu&#8217;un obsédé du terrain synthétique. Mais ça fait mal. Et ça coûte cher. Enfin les filles, attendez l&#8217;accouchement, c&#8217;est encore plus douloureux, et ça douille encore plus, sur environ 20 ans. La vie est injuste.</p>
<p>Je ne peux pas terminer cet article sans vous remercier de m&#8217;avoir lu.</p>
<p>Poil au cul.</p>
<p>Je ne suis pas désolé.</p>


feed_id: http://sametmax.com/?p=12659
title: 0bin s’est fait tej
uri: 0bin-s-est-fait-tej
url: http://sametmax.com/0bin-sest-fait-tej/
content:
<p>On a eu une take down notice pour une page 0bin, et comme on a pas réagit assez vite, on nous a juste coupé le site.</p>
<p>J&#8217;adore cette justice qui se passe de l&#8217;avis du système judiciaire, qui renverse la charge de la preuve et donne le pouvoir à des sociétés privées qui sont juges et parties. Je n&#8217;ai pas encore regardé la page en question, mais que ce soit légitime ou non, la démarche est aberrante.</p>
<p>Je vois bien Mac Do qui arrive chez un boucher :</p>
<blockquote><p>
Monsieur, nous pensons que votre steak imite le notre, nous fermons votre boutique jusqu&#8217;à ce que vous ne le vendiez plus. Non on a pas l&#8217;autorisation d&#8217;un juge, on est pas une société française de toute façon, on a juste fait pression sur le propriétaire de votre immeuble. Non, c&#8217;est pas mafieux si c&#8217;est légal, monsieur.
</p></blockquote>
<p>En plus, c&#8217;est pas comme si le système était pas déjà abusé par <a href="http://www.itworld.com/article/2734365/it-management/warner-brothers-abusing-dmca-takedown-rules.html">les ayant droits</a> ET <a href="http://korben.info/comment-google-livre-tete-d-une-activiste-aux-islamistes.html">les criminels</a>.</p>
<p>Bref, 0bin est down le temps qu&#8217;on répare tout ça.</p>


feed_id: http://sametmax.com/?p=12648
title: Un peu de fun avec les décorateurs
uri: Un-peu-de-fun-avec-les-décorateurs
url: http://sametmax.com/un-peu-de-fun-avec-les-decorateurs/
content:
<p>Puisque la programmation asynchrone est au goût du jour, on se mange des callbacks un peu partout. Et ça alourdit toujours le code. Chaque langage, lib ou framework a essayé de trouver des astuces pour rendre tout ça plus digeste, et on a vu la naissance des Futures, Deferred, Promises, coroutines, yield from et autres joyeusetés.</p>
<p>Prenons par exemple un script Twisted. Déjà, Twisted, c&#8217;est pas vraiment l&#8217;exemple de la syntaxe Weight Watcher, ou alors si, mais avant le début du régime.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot; Télécharge des pages et affiche leur, de manière asynchrone &quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Ceci doit être pip installé</span>
<span style="color: #ff7700;font-weight:bold;">import</span> treq
<span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">internet</span>.<span style="color: black;">task</span> <span style="color: #ff7700;font-weight:bold;">import</span> react
<span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">internet</span>.<span style="color: black;">defer</span> <span style="color: #ff7700;font-weight:bold;">import</span> inlineCallbacks<span style="color: #66cc66;">,</span> returnValue
&nbsp;
<span style="color: #808080; font-style: italic;"># Soit on utilise la syntaxe 'inlineCallbacks', c'est à dire avec des yields</span>
<span style="color: #808080; font-style: italic;"># qui marquent les appels asynchrones.</span>
<span style="color: #66cc66;">@</span>inlineCallbacks
<span style="color: #ff7700;font-weight:bold;">def</span> get_title<span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>:
    res <span style="color: #66cc66;">=</span> <span style="color: #ff7700;font-weight:bold;">yield</span> treq.<span style="color: black;">get</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># Ceci est asynchrone et non bloquant</span>
    html <span style="color: #66cc66;">=</span> <span style="color: #ff7700;font-weight:bold;">yield</span> res.<span style="color: black;">content</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># Ça aussi</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        val <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">search</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">''</span><span style="color: #66cc66;">,</span> html.<span style="color: black;">decode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span><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>:
        val <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">''</span>
&nbsp;
    returnValue<span style="color: black;">&#40;</span>val<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Soit on récupère un objet defer et on ajoute un callback manuellement</span>
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span>reactor<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># Ceci est asynchrone et non bloquant</span>
    defer <span style="color: #66cc66;">=</span> get_title<span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://sametmax.com/quest-ce-quun-callback/'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Ceci arrive une fois que get_title est terminé</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> cb<span style="color: black;">&#40;</span>title<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>title.<span style="color: black;">upper</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">'!'</span><span style="color: black;">&#41;</span>
&nbsp;
    defer.<span style="color: black;">addCallback</span><span style="color: black;">&#40;</span>cb<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Pareil</span>
    autre_defer <span style="color: #66cc66;">=</span> get_title<span style="color: black;">&#40;</span><span style="color: #483d8b;">'https://github.com/sametmax/django-quicky'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> cb<span style="color: black;">&#40;</span>title<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>title.<span style="color: black;">upper</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">'!!!'</span><span style="color: black;">&#41;</span>
&nbsp;
    autre_defer.<span style="color: black;">addCallback</span><span style="color: black;">&#40;</span>cb<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> defer
&nbsp;
react<span style="color: black;">&#40;</span>main<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>D&#8217;une manière générale, je préfère la syntaxe à base de yields, même si elle oblige à se trimbaler le décorateur <code>inlineCallbacks</code> partout, à parsemer sa fonction de yields et à utiliser <code>returnValue</code> à la place de <code>return</code> puisque le mot clé est interdit dans les générateurs en Python 2.7.</p>
<p>Mais bon, ça reste facile à lire. On sait que les lignes avec <code>yield</code>, sont les appels bloquant qu&#8217;on demande à la boucle d’événements de traiter de manière asynchrone.</p>
<p>La syntaxe à base de callbacks est plus lourde, en revanche elle donne le contrôle sur la concurrence des callbacks puisqu&#8217;ils sont explicites au lieu d&#8217;être automatiquement ajoutés par magie. Elle parlera aussi plus aux dev Javascript qui ont l&#8217;habitude d&#8217;ajouter des callbacks manuellement.</p>
<p>Néanmoins, en JS, on a des fonctions anonymes plus flexibles, et on ferait donc plutôt une truc du genre :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">get_title<span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>.<span style="color: black;">then</span><span style="color: black;">&#40;</span>function<span style="color: black;">&#40;</span>title<span style="color: black;">&#41;</span><span style="color: black;">&#123;</span>
    <span style="color: #808080; font-style: italic;"># faire un truc avec le résultat</span>
<span style="color: black;">&#125;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Et bien il se trouve qu&#8217;avec Python, bien qu&#8217;on ne le voit pas souvent, on peut avoir cette idée de la déclaration de son appel asynchrone juste au dessus de son callback, en utilisant des <a href="http://sametmax.com/comprendre-les-decorateurs-python-pas-a-pas-partie-1/">décorateurs</a>.</p>
<p>En effet, les décorateurs ne sont que du sucre syntaxique :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">@</span>truc
<span style="color: #ff7700;font-weight:bold;">def</span> bidule<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    chose</pre></td></tr></table></div>

<p>N&#8217;est en fait qu&#8217;un raccourci pour écrire :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> bidule<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    chose
&nbsp;
bidule <span style="color: #66cc66;">=</span> truc<span style="color: black;">&#40;</span>bidule<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Du coup, on peut prendre n&#8217;importe quelle fonction, ou méthode, et l&#8217;utiliser comme décorateur :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">@</span>react
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span>reactor<span style="color: black;">&#41;</span>:
&nbsp;
    then <span style="color: #66cc66;">=</span> get_title<span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://sametmax.com/quest-ce-quun-callback/'</span><span style="color: black;">&#41;</span>.<span style="color: black;">addCallback</span>
    <span style="color: #66cc66;">@</span>then
    <span style="color: #ff7700;font-weight:bold;">def</span> cb<span style="color: black;">&#40;</span>title<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>title.<span style="color: black;">upper</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">'!'</span><span style="color: black;">&#41;</span>
&nbsp;
    then <span style="color: #66cc66;">=</span> get_title<span style="color: black;">&#40;</span><span style="color: #483d8b;">'https://github.com/sametmax/django-quicky'</span><span style="color: black;">&#41;</span>.<span style="color: black;">addCallback</span>
    <span style="color: #66cc66;">@</span>then
    <span style="color: #ff7700;font-weight:bold;">def</span> cb<span style="color: black;">&#40;</span>title<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>title.<span style="color: black;">upper</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">'!!!'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> cb</pre></td></tr></table></div>

<p>Et en jouant avec <code>functools.partial</code>, on peut faire aussi des trucs rigolos.</p>
<p>Non pas que cette syntaxe soit le truc indispensable à connaître et à utiliser. Mais les gens n&#8217;y pensent jamais. On utilise pas assez les décorateurs.</p>
<p>Par exemple, combien de fois vous avez vu :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Doh'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">'__main__'</span>:
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Certaines libs, comme begin, font des décorateurs pour ça :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span>func<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">'__main__'</span>:
        func<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Et du coup, dans son prog:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">@</span>main
<span style="color: #ff7700;font-weight:bold;">def</span> _<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Doh'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Comme souvent, c&#8217;est le genre de feature qui peut être abusée, mais c&#8217;est parfois sympa de rapprocher une action juste au dessus de la fonction qui va être dans ce contexte.</p>
<p>J&#8217;espère ainsi vous avoir inspiré pour mettre un hack ou deux en production détournant complètement l&#8217;usage des décorateurs et ajoutant quelques gouttes de plus dans le vase de la sécurité de votre emploi, ou votre licenciement.</p>


feed_id: http://sametmax.com/?p=12709
title: Dans quels secteurs retrouve-t-on Python ces temps-ci ? Recently updated !
uri: Dans-quels-secteurs-retrouve-t-on-Python-ces-temps-ci
url: http://sametmax.com/dans-quels-secteurs-retrouve-t-on-python-ces-temps-ci/
content:
<p>J&#8217;utilise le <a href="https://twitter.com/sam_et_max">compte Tweeter du blog</a> (n&#8217;oubliez pas qu&#8217;il y a un <a href="http://bridge.suumitsu.eu/?action=display&amp;bridge=TwitterBridge&amp;u=sam_et_max&amp;format=AtomFormat">flux RSS des tweets</a>) pour RT des offres d&#8217;emploi en rapport avec Python régulièrement. Des stages, des demandes de freelance, des embauches, etc. J&#8217;essaye de rester dans des offres francophones ou dans des pays limitrophes à la France, histoire que ce soit des infos utiles.</p>
<p>Ce faisant, j&#8217;ai pu noter au fil de l&#8217;année les secteurs qui sont le plus présents parmi ces recrutements, en tout cas via micro-blogging.</p>
<p>En premier, on a le Web, évidemment. Essentiellement du Django. Rien d&#8217;étonnant, ce n&#8217;est pas lié à Python en particulier, c&#8217;est juste le secteur informatique qui est le plus actif, et tout langage qui peut faire du HTTP correctement amène forcément du taf. Les outils pour cela en Python sont de bonne qualité, et on le retrouve donc un peu partout.</p>
<p>Ensuite vient la finance.</p>
<p>Ceci me gène un peu. Je ne les retweete pas en général, car éthiquement parlant, je ne suis pas à l&#8217;aise avec les institutions financières actuelles, mais ce n&#8217;est pas le sujet de l&#8217;article. Néanmoins ce sont d&#8217;excellentes opportunités techniques : analyse de données, temps réel, traitements logiques, UI, grosses infras, des moyens et un travail avec un impact fort IRL. Que Python s&#8217;impose dans ces milieux n&#8217;est pas une surprise : ils privilégient pragmatisme et efficacité. Or Python est un langage clair, qui permet une itération rapide en dev, des traitements complexes tout en restant facile à maintenir.</p>
<p>En 3ème position (selon les stats de l&#8217;INDMS, bien sûr), on retrouve la science : les chercheurs, biologistes, physiciens, géographes, astronomes et tous corps de métiers qui ont besoin de pouvoir adapter facilement des algos, transcrire des maths en code, traiter des gros jeux de données&#8230; Python est un langage fantastique pour cela, et sont apparues tout un tas de libs, soit pour gagner en perf, soit pour coller aux règles du métier. On retrouve du coup le langage comme solution de scripting dans des logiciels pros comme les SIG, des bases de données moléculaires et autres gros morceaux. C&#8217;est un usage tellement important que la prochaine version va embarquer un nouvel opérateur mathématique pour multiplier les matrices : le <code>@</code>.</p>
<p>Et puis il y a l&#8217;admin système et l&#8217;automatisation. Python remplace Perl un peu partout, dès qu&#8217;un script bash ne suffit plus. Car Python est simplement plus lisible et maintenable que ces deux langages, et il est aussi maintenant plus versatile, grâce au travail de la communauté. Des initiatives comme <a href="http://www.openstack.org/">OpenStack</a> ont fait de Python un acteur majeur dans les solutions de déploiement, de cloud, d&#8217;archi distribuées. C&#8217;est néanmoins très spécialisé, et concurrentiel, et donc trouver un bon dev là dedans ne doit pas être facile.</p>
<p>Notre pénultième, c&#8217;est la gestion d&#8217;entreprise. Principalement à travers le produit <a href="https://www.odoo.com/">Odoo</a> (aka OpenERP) qui s&#8217;occupe de tout, du personnel aux clients en passant par la facturation. C&#8217;est un peu usine à gaz, mais ça vaut toujours mieux que SAP. Ceci dit, en dehors de cela, Python est un fantastique langage glu, du fait qu&#8217;il est capable de lire et générer de nombreux formats (MS Office, LibreOffice, PDF, images) et base de données (MySQL, PostGres, Oracle, Access, et d&#8217;autres plus obscures). On peut même parler certains protocoles de machines outils. Dans des usines qui ont 15 ans d&#8217;empilement technologique et de migrations avec des morceaux legacy qui traînent partout, ça change la vie. Surtout qu&#8217;on peut maintenant remplacer VB avec Python presque partout, y compris dans Excel.</p>
<p>En dernier, il y a le Big Data. Derrière ce mot pompeux se cache les analyses de données massives, l&#8217;intelligence artificielle et en fait, tout ce qui concerne extraire du sens à partir d&#8217;un gros blob qui n&#8217;appartient pas aux métiers cités précédemment. Interprétation du langage humain, études d&#8217;images ou de son, réseaux sémantiques, généralement sous forme de grandes collections d&#8217;échantillons. Là c&#8217;est du haut niveau, mais ça fait justement des postes intéressants.</p>
<p>Malgré <a href="http://kivy.org/">Kivy</a>, le <a href="http://www.raspberrypi.org/">Rasberry Py</a> et <a href="http://micropython.org/">Micro Python</a>, je ne vois pas encore le langage décoller dans l&#8217;embarqué, sur téléphone, sur l&#8217;internet des objets&#8230; <a href="http://sametmax.com/le-potentiel-de-wamp-autobahn-et-crossbar-io/">WAMP</a> va peut être changer la donne, mais pas tant que qu&#8217;on aura pas créé une API plus sexy.</p>
<p>Les jeux vidéos sont aussi un secteur qui manque de Python, et c&#8217;est dommage. On lui préfère souvent le Lua, à part dans quelques cas comme Civilisation ou Eve Online.</p>
<p>Apparemment Python paie bien, mais honnêtement j&#8217;en ferai pas un critère de choix : ces choses là changent. Si on veut de la thune, on fait du Cobol, emploi bien payé garanti.</p>


feed_id: http://sametmax.com/?p=12704
title: Créer un réseau ad hoc sous Windows 8
uri: Créer-un-réseau-ad-hoc-sous-Windows-8
url: http://sametmax.com/creer-un-reseau-ad-hoc-sous-windows-8/
content:
<p>On a pas toujours un switch sous la main, et pourtant, mettre deux ordinateurs en réseau peut se faire sentir. Ok, c&#8217;est pour faire une LAN, qui j&#8217;essaye de tromper là ?</p>
<p>La solution, c&#8217;est le réseau ad hoc, c&#8217;est à dire demander à son ordi d&#8217;être point d&#8217;accès WIFI et réseau local.</p>
<p>Sous Windows 7, c&#8217;est facile, panneau de config, réseaux et partages, 3 clics et ça roule.</p>
<p>Mais mon Windows 8 ne voyait pas le réseau, et j&#8217;ai steam installé dessus.</p>
<p>Du coup, on a cherché un moyen de faire le réseau depuis W8, et l&#8217;option a été retirée des GUI.</p>
<p>Heureusement, il reste la ligne de commande.</p>
<p>D&#8217;abord, vérifier que son matos supporte le mode ad hoc :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">netsh wlan show drivers</pre></td></tr></table></div>

<p>Dans la liste, il doit y avoir une ligne à propos d&#8217;un réseau hébergé avec marqué &#8220;oui&#8221;.</p>
<p>Si ce n&#8217;est pas le cas, fin du voyage. Sinon, on configure le réseau (les droits admins sont nécessaires) :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">netsh wlan <span style="color: #000000; font-weight: bold;">set</span> un_nom_de_reseau <span style="color: #007800;">mode</span>=allow <span style="color: #007800;">ssid</span>=un_ssid <span style="color: #007800;">key</span>=un_mot_de_passe</pre></td></tr></table></div>

<p>Quand on veut lancer le réseau :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">netsh wlan start un_nom_de_reseau</pre></td></tr></table></div>

<p>Quand on veut l&#8217;arrêter :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">netsh wlan stop un_nom_de_reseau</pre></td></tr></table></div>

<p>Et les autres systèmes peuvent le voir dans la liste des réseaux WIFI sous le nom de &#8220;un_ssid&#8221; avec le mot de passe &#8220;un_mot_de_passe&#8221;.</p>


feed_id: http://sametmax.com/?p=12766
title: Quelle est la différence entre “bloquer” et “en cours d’exécution” ? Recently updated !
uri: Quelle-est-la-différence-entre-bloquer-et-en-cours-d-exéc
url: http://sametmax.com/quelle-est-la-difference-entre-bloquer-et-en-cours-dexecution/
content:
<p>On vous dit qu&#8217;il faut faire attention en utilisant des technologies non bloquantes, car si on bloque dans la boucle d&#8217;événement, on bloque tout le programme, et on perd l’intérêt de l&#8217;outil.</p>
<p>C&#8217;est vrai, mais que veut dire &#8220;bloquer&#8221; ?</p>
<p>Car si je fais :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><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;">1000000</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Mon programme va tourner longtemps, et la boucle d’événement va bloquer, n&#8217;est-ce pas ?</p>
<p>En fait, &#8220;bloquer&#8221; et un abus de langage car il y a plusieurs raisons pour bloquer. Dans notre contexte, il faudrait dire &#8220;bloquer en attente d&#8217;une entrée ou d&#8217;une sortie&#8221;. D&#8217;où l&#8217;appellation &#8220;Aynschronous non blocking I/O&#8221; des technos types NodeJS, Twisted, Tornado, Gevent, etc.</p>
<p>En effet, il faut distinguer deux causes d&#8217;attente à votre programme :</p>
<ul>
<li>Attendre que vos instructions se terminent. C&#8217;est être &#8220;en cours d&#8217;exécution&#8221;.</li>
<li>Attendre qu&#8217;un événement extérieur (écrire sur le disque, lire une socket, un clic de souris) arrive à sa conclusion. C&#8217;est bloquer sur de l&#8217;I/O.</li>
</ul>
<p>Le premier cas est impossible à éviter. Tout au mieux pouvons-nous répartir la charge du programme sur plusieurs cœurs, processeurs voire machines. Le code devra toujours attendre qu&#8217;il se termine, mais ça ira plus vite.</p>
<p>Dans le contexte de la programmation non bloquante telle qu&#8217;on vous en a parlé, on est donc dans le deuxième cas.</p>
<p>Il ne s&#8217;agit alors pas de s&#8217;interdire de faire des boucles ou autre opération longue (ou plutôt, c&#8217;est un problème d&#8217;optimisation ordinaire qui n&#8217;a rien à voir avec le fait de bloquer), il s&#8217;agit de ne pas &#8220;attendre à ne rien faire&#8221; quand une opération extérieure est en cours.</p>
<p>C&#8217;est ce que font naturellement NodeJS, Twisted, Tornado, Gevent &#038; Co. Quand on fait un échange HTTP, le bout de données part, puis le reste du code continue de tourner, passant à la tâche suivante, en attendant que le paquet traverse le réseau, atteigne l&#8217;autre machine, qui vous répond finalement. C&#8217;est ce temps, incompressible, sans contrôle de votre côté, durant lequel il ne faut pas bloquer. Le gain de perf est que votre programme ne se la touche pas pendant les temps d&#8217;attente, mais bien entendu que VOTRE, lui, code va prendre du temps et &#8220;bloquer&#8221; le processeur. Il faut bien qu&#8217;il s&#8217;exécute.</p>
<p>Ce qu&#8217;on entend donc par &#8220;il ne faut pas faire d&#8217;opération bloquante dans un code qui est déjà non bloquant&#8221; c&#8217;est &#8220;il ne faut pas utiliser un outil à l&#8217;API bloquante au milieu d&#8217;autres outils non bloquants&#8221;.</p>
<p>Par exemple, n&#8217;utilisez pas <a href="http://docs.python-requests.org/en/latest/">requests</a> avec Twisted, car requests est codé pour attendre sans rien faire jusqu’à obtenir une réponse à chaque requête, bloquant Twisted. Utilisez plutôt <a href="http://treq.readthedocs.org/en/latest/">treq</a>. C&#8217;est pareil pour la lecture d&#8217;un fichier, une requête de base de données, etc. Et il existe des boucles d&#8217;événements ailleurs que sur le serveur : une page Web possède sa propre boucle (c&#8217;est pour cela que tout JS est asynchrone), un toolkit GUI comme QT ou GTK aussi (c&#8217;est pour ça qu&#8217;ils utilisent la programmation événementielle), etc.</p>
<p>Maintenant vous allez me dire : mais pourquoi bloquer alors ? Pourquoi ne pas toujours éviter de bloquer ?</p>
<p>Et bien parce que si on ne bloque pas, on ne peut pas écrire un programme ligne à ligne. On est obligé d&#8217;adopter un style de programmation asynchrone puisqu&#8217;on ne sait pas quand le résultat de certaines lignes va arriver. Ça veut dire des callbacks, ou des futures, ou des coroutines, ou du message passing&#8230; Bref, un truc plus compliqué. Or, on n&#8217;a pas forcément besoin de ce niveau de performance. En fait, la grande majorité des programmes n&#8217;ont pas besoin de ce niveau de performance. Donc, on bloque en attendant, non pas Godot, mais l&#8217;I/O, parce que c&#8217;est plus simple à écrire. Pour pas se faire chier.</p>
<p>Il y a bien des moyens de contourner ce problème : les threads, le multiprocessing, les coroutines, etc. Parfois même, on ignore le problème : bloquer quelques ms au milieu d&#8217;une boucle d’événements une fois par seconde n&#8217;est pas un drame. Une fois que j&#8217;ai fini le dossier sur les tests unitaires, je vous ferai un dossier sur la programmation non bloquante, avec aussi une esquisse de la parallélisation.</p>
<p>En attendant, ne stressez pas parce que votre code &#8220;bloque&#8221; parce qu&#8217;il travaille longtemps, assurez-vous juste que les APIs que vous utilisez ne bloquent pas pendant l&#8217;I/O, et vous êtes ok. </p>
<p>Et comment savoir ? Et bien si une donnée rentre ou sort de votre programme (ça ne fait pas parti du code source), c&#8217;est de l&#8217;I/O. Si votre code ressemble à ça :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">res <span style="color: #66cc66;">=</span> faire_operation_sur_IO<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
faire_un_truc_avec_le_res<span style="color: black;">&#40;</span>res<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Alors votre outil est bloquant, puisque qu&#8217;il compte sur le fait que la deuxième ligne sera exécutée à coup sûr quand la première sera terminée. Un outil non bloquant exigera quelque chose pour gérer le retour du résultat plus tard: un callback, une promesse, un <code>yield</code>&#8230;</p>


feed_id: http://sametmax.com/?p=12742
title: 0bin.net est de nouveau en ligne Recently updated !
uri: 0bin-net-est-de-nouveau-en-ligne
url: http://sametmax.com/0bin-net-est-de-nouveau-en-ligne/
content:
<p><a href="http://sametmax.com/0bin-sest-fait-tej/">0bin était down</a>, on a supprimé la page en cause, et on l&#8217;a remis up.</p>
<p>On ne sait pas trop comment lutter contre ça. Même TPB a dû avoir 40 noms de domaine pour s&#8217;en sortir, et franchement on n&#8217;a pas envie de se taper autant de boulot pour un projet qui ne nous rapporte rien.</p>
<p>Que faire donc ?</p>
<p>D&#8217;abord, créer une admin pour 0bin pour supprimer une page plus facilement. Ça nous évitera de dépasser les délais la prochaine fois, car je n&#8217;étais pas dispo et Max ne savait pas comment faire. C&#8217;est pas que c&#8217;est compliqué, mais ça prend du temps, faut lire la doc, se connecter au serveur, etc. Et forcément, c&#8217;est du temps qu&#8217;on préfère passer sur Dota ou des projets qui rapportent des sous.</p>
<p>Ensuite, prendre le temps de vous rappeler que <a href="http://0bin.net/">0bin.net</a> n&#8217;est qu&#8217;une instance de 0bin. Un exemple. Multiplier les instances est encore le meilleur moyen d&#8217;avoir l&#8217;outil à disposition. Et le process est <a href="https://0bin.readthedocs.org/en/latest/">plutôt bien documenté</a>.</p>
<p>Mais une fois qu&#8217;on a posté son truc sur une instance, si elle tombe, que fait-on ?</p>
<p>Pour le moment on est baisé. </p>
<p>On pourrait donc imaginer de rajouter une fonction de distribution à 0bin. L&#8217;idée serait de se lier via une API simple à d&#8217;autres 0bin en qui on a confiance. Si quelqu&#8217;un poste sur l&#8217;un, tous les autres reçoivent une copie. Ainsi dans le lot, il y en aura bien un qui résistera. </p>
<p>Je me tâte à faire ça dans la semaine. Déjà 0bin a besoin d&#8217;un portage qui supporte Python 3. Ensuite quelques tests unitaires ne feraient pas de mal. Une fois que c&#8217;est fait, je freeze cette version, et je lance 1bin.net, la version suivante. Avec du crossbar.io, du angularjs et du mode distribué. Le truc sera plus lourd, uniquement compatible 2.7 et plus compliqué, donc je préfère en faire une version à part. </p>
<p>Ça se tente, voir si j&#8217;arrive à débloquer un peu de temps pour le faire, mais c&#8217;est pas impossible. Stay tuned.</p>


feed_id: http://sametmax.com/?p=12717
title: Un gros guide bien gras sur les tests unitaires en Python, partie 4 Recently updated !
uri: Un-gros-guide-bien-gras-sur-les-tests-unitaires-en-Python-partie-4
url: http://sametmax.com/un-gros-guide-bien-gras-sur-les-tests-unitaires-en-python-partie-4/
content:
<p>Python est un langage très pro, et il y a beaucoup, beaucoup d&#8217;outils pour faire des tests.</p>
<p><a href="http://sametmax.com/un-gros-guide-bien-gras-sur-les-tests-unitaires-en-python-partie-3/">Après avoir vu pytest</a>, un outil typiquement pythonique sont les doctests, des tests unitaires intégrés dans les <a href="http://sametmax.com/les-docstrings/">docstrings</a>.</p>
<p>Pour rappel, les docstrings, ce sont ces chaînes de caractères qu&#8217;on retrouve au début des modules, sous la signature des fonctions ou dans la définition des classes. Elles servent à la documentation de ceux-ci, ainsi on peut la lire dans le code, et dans les vraies docs car les outils standards savent les extraire.</p>
<p>Ça ressemble à ça :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> une_fonction<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Ceci est une docstring.
&nbsp;
        On peut la lire dans le code source, avec help() dans le shell ou
        dans les docs générés par pydoc et sphinx.
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">pass</span></pre></td></tr></table></div>

<p>Et bien ces docstrings, on peut mettre des tests unitaires dedans formatés comme des sessions de shell Python. Cela permet de donner des exemples d&#8217;usage, tout en testant son code. C&#8217;est chouette.</p>
<p>Musique ?</p>
<p>Musique.</p>
<p><span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='1170' height='689' src='http://www.youtube.com/embed/hUSm87nvG3k?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0' allowfullscreen='true'></iframe></span></p>
<h2>Hello doctests</h2>
<p>Faire des doctests n&#8217;est pas bien compliqué car c&#8217;est du copier coller. On fait une session shell avec ce qu&#8217;on veut tester, et on copie-colle le tout dans la docstring. Fastoche.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># on copie juste la session de shell tel quel</span>
<span style="color: #ff7700;font-weight:bold;">def</span> ajouter<span style="color: black;">&#40;</span>a<span style="color: #66cc66;">,</span> b<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        &gt;&gt;&gt; ajouter(1, 2)
        3
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> a + b
&nbsp;
<span style="color: #808080; font-style: italic;"># et on demande à Python de parser les doctests. Directement dans votre fichier</span>
<span style="color: #808080; font-style: italic;"># de code. Si, si. Pas de fichier de tests à part.</span>
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">doctest</span>
    <span style="color: #dc143c;">doctest</span>.<span style="color: black;">testmod</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>On lance ensuite directement notre fichier de code :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">python mon_module.py</pre></td></tr></table></div>

<p>Et ça n&#8217;affiche absolument rien. C&#8217;est parce qu&#8217;il n&#8217;y a pas d&#8217;erreur. On peut avoir le topo en demandant un peu de verbosité avec <code>-v</code> :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">python mon_module.py <span style="color: #660033;">-v</span>
Trying:
    ajouter<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">1</span>, <span style="color: #000000;">2</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
Expecting:
    <span style="color: #000000;">3</span>
ok
<span style="color: #000000;">1</span> items had no tests:
    __main__
<span style="color: #000000;">1</span> items passed all tests:
   <span style="color: #000000;">1</span> tests <span style="color: #000000; font-weight: bold;">in</span> __main__.ajouter
<span style="color: #000000;">1</span> tests <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000;">2</span> items.
<span style="color: #000000;">1</span> passed and <span style="color: #000000;">0</span> failed.
Test passed.</pre></td></tr></table></div>

<p>Les doctests marchent purement en se basant sur le formatage texte. Python prendre la ligne avec <code>&gt;&gt;&gt;</code>, l&#8217;exécuter, si la ligne suivante ne contient pas de <code>&gt;&gt;&gt;</code>, il va comparer le résultat de l&#8217;exécution de la ligne précédente avec le contenu de la ligne qui la suit.</p>
<p>Ceci passe :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;
    &gt;&gt;&gt; ajouter(1, 2)
    3
&quot;&quot;&quot;</span></pre></td></tr></table></div>

<p>Mais ceci échoue :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;
    &gt;&gt;&gt; ajouter(1, 2)
    4
&quot;&quot;&quot;</span></pre></td></tr></table></div>

<p>Car le résultat AFFICHÉ dans le shell est 3, et non 4.</p>
<p>En cas d&#8217;échec, Python vous en dit un peu plus :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">python mon_module.py
<span style="color: #000000; font-weight: bold;">**********************************************************************</span>
File <span style="color: #ff0000;">&quot;mon_module.py&quot;</span>, line <span style="color: #000000;">6</span>, <span style="color: #000000; font-weight: bold;">in</span> __main__.ajouter
Failed example:
    ajouter<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">1</span>, <span style="color: #000000;">2</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
Expected:
    <span style="color: #000000;">4</span>
Got:
    <span style="color: #000000;">3</span>
<span style="color: #000000; font-weight: bold;">**********************************************************************</span>
<span style="color: #000000;">1</span> items had failures:
   <span style="color: #000000;">1</span> of   <span style="color: #000000;">1</span> <span style="color: #000000; font-weight: bold;">in</span> __main__.ajouter</pre></td></tr></table></div>

<h2>Formater ses doctests</h2>
<p>Les doctests sont faits pour s&#8217;intégrer de manière transparente aux docstrings. On peut donc en mettre autant qu&#8217;on veut, au milieu du texte ordinaire de la docstring. Python se base sur les chevrons (<code>&gt;&gt;&gt;</code>) pour savoir quand commence un test, et le saut de ligne pour savoir quand ça se termine. Au delà de ça, le style est libre.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> ajouter<span style="color: black;">&#40;</span>a<span style="color: #66cc66;">,</span> b<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Je peux mettre n'importe quoi ici.
&nbsp;
        Et ici aussi.
&nbsp;
        Puis intégrer des tests:
&nbsp;
        &gt;&gt;&gt; ajouter(1, 2)
        3
        &gt;&gt;&gt; ajouter(2, 2)
        4
&nbsp;
        Et un saut de ligne indique que les tests sont terminés. Mais je peux
        encore en ajouter après si je veux.
&nbsp;
        &gt;&gt;&gt; ajouter(0, 0)
        0
&nbsp;
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> a + b</pre></td></tr></table></div>

<p>Néanmoins, l’intérêt des doctests est de documenter son code à travers les tests, et donc on adoptera généralement un format tel que ace;:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> ajouter<span style="color: black;">&#40;</span>a<span style="color: #66cc66;">,</span> b<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Additionne deux elements.
&nbsp;
        Exemple :
&nbsp;
            &gt;&gt;&gt; # on peut mettre des commentaires ici
            &gt;&gt;&gt; ajouter(1, 2) # ou là
            3
            &gt;&gt;&gt; ajouter(2., 2) # fonctionne sur tous les types de nombre
            4.0
&nbsp;
        La fonction fonctionne en duck typing, et accepte donc tout objet
        qui possède la méthode magique __add__ :
&nbsp;
            &gt;&gt;&gt; ajouter('a', 'b')
            'ab'
            &gt;&gt;&gt; ajouter([1], [2])
            [1, 2]
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> a + b</pre></td></tr></table></div>

<p>Notez comme il est agréable de lire cette docstring : on comprend tout de suite comment utiliser la fonction. En prime, ce sont des tests unitaires qui garantissent que notre fonction va continuer de fonctionner correctement et nous oblige à garder cette doc à jour.</p>
<p>On peut faire des imports dedans ou utiliser temporairement <a href="http://sametmax.com/debugger-en-python-les-bases-de-pdb/">pdb</a> pour debugger. N&#8217;importe quel code de shell est valide mais faites attention à ne pas démarrer des boucles infinies comme les event loops des GUI ou lib async.</p>
<p>Voici ce que donnerait l&#8217;exemple des articles précédents avec des docstests :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> get<span style="color: black;">&#40;</span>data<span style="color: #66cc66;">,</span> index<span style="color: #66cc66;">,</span> default<span style="color: #66cc66;">=</span><span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Implémente l'équivalent de dict.get() pour les indexables.
&nbsp;
        Example :
&nbsp;
            &gt;&gt;&gt; simple_comme_bonjour = ('pomme', 'banane')
            &gt;&gt;&gt; get(simple_comme_bonjour, 0)
            'pomme'
            &gt;&gt;&gt; get(simple_comme_bonjour, 1000, 'Je laisse la main')
            'Je laisse la main'
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> data<span style="color: black;">&#91;</span>index<span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">IndexError</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> default</pre></td></tr></table></div>

<h2>Problèmes et solutions</h2>
<p>Les doctests ne sont pas la Panacée, particulièrement parce que le test se fera sur le résultat AFFICHÉ dans le shell. Cela peut facilement amener à des erreurs.</p>
<p>Déjà, il faut faire attention à la représentation des objets dans le shell Python. <strong>La représentation n&#8217;est pas forcément la valeur de saisie</strong> :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff4500;">1</span>.
<span style="color: #ff4500;">1.0</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;1&quot;</span>
<span style="color: #483d8b;">'1'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;foo&quot;</span>: <span style="color: #483d8b;">&quot;bar&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;une apostrophe : '&quot;</span>: <span style="color: #483d8b;">&quot;est échapée ainsi qu'un accent&quot;</span><span style="color: black;">&#125;</span>
<span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;une apostrophe : '&quot;</span>: <span style="color: #483d8b;">&quot;est <span style="color: #000099; font-weight: bold;">\x</span>c3<span style="color: #000099; font-weight: bold;">\x</span>a9chap<span style="color: #000099; font-weight: bold;">\x</span>c3<span style="color: #000099; font-weight: bold;">\x</span>a9e ainsi qu'un accent&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'foo'</span>: <span style="color: #483d8b;">'bar'</span><span style="color: black;">&#125;</span></pre></td></tr></table></div>

<p>La solution à ce problème est de tester dans le shell les valeurs de retour, et non de le faire de tête. Faites bien gaffe aux espaces qui sont donc significatifs, surtout ceux en fin de ligne. Mon éditeur est configuré pour les virer par défaut, et ça m&#8217;a niqué en écrivant l&#8217;article :)</p>
<p>Ensuite, il y a des cas où la représentation ne sera pas la même d&#8217;un appel à l&#8217;autre.</p>
<p>C&#8217;est le cas avec les dictionnaires, puisque l&#8217;ordre des éléments n&#8217;est pas garanti par nature. Ne faites donc pas :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> retourne_un_dico<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#123;</span><span style="color: #483d8b;">'ordre'</span>: <span style="color: #483d8b;">'non garanti'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'le'</span>: <span style="color: #483d8b;">'resultat'</span><span style="color: black;">&#125;</span></pre></td></tr></table></div>

<p>Mais plutôt quelque chose qui vous garantit l&#8217;affichage :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;
&gt;&gt;&gt; res = list(retourne_un_dico().items())
&gt;&gt;&gt; res.sort()
[('le', 'resultat'), ('ordre', 'non garanti')]
&gt;&gt;&gt; # ou
&gt;&gt;&gt; retourne_un_dico() == {'ordre': 'non garanti', 'le': 'resultat'}
True
&quot;&quot;&quot;</span></pre></td></tr></table></div>

<p>Parfois, on ne peut juste pas garantir l&#8217;affichage. Par exemple avec des nombres non prévisibles comme les hash ou les id des objets :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;
&gt;&gt;&gt; class Test(): pass
&gt;&gt;&gt; repr(Test())
''
&quot;&quot;&quot;</span></pre></td></tr></table></div>

<p><code>7f4687d30fc8</code> n&#8217;est ici pas prévisible. Python met certains cas spéciaux comme celui-ci des flags activables via le commentaire <code># doctest: +NOM_DU_FLAG</code>.</p>
<p>Par exemple, le flag <code>ELLIPSIS</code> permet de placer <code>...</code> dans le résultat en guise de joker :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;
&gt;&gt;&gt; repr(Test()) # doctest: +ELLIPSIS
''
&quot;&quot;&quot;</span></pre></td></tr></table></div>

<p>D&#8217;autres problèmes similaires peuvent être résolus ainsi. Le flag <code>SKIP</code> permet de sauter un test que vous voulez mettre là, en exemple, mais qui ne doit pas être testé :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;
&gt;&gt;&gt; # ce test va être ignoré
&gt;&gt;&gt; repr(Test()) # doctest: +SKIP
''
&quot;&quot;&quot;</span></pre></td></tr></table></div>

<p><code>NORMALIZE_WHITESPACE</code> permet de considérer toute séquence de caractères non imprimables comme un espace. 8 tabs ou 4 espaces dans le résultat seront tous considérés comme un espace.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;
&gt;&gt;&gt; 'ceci est une assez longue ligne divisible' # doctest: +NORMALIZE_WHITESPACE
'ceci    est     une assez longue    ligne divisible'
&quot;&quot;&quot;</span></pre></td></tr></table></div>

<p>Les flags sont cumulables, si on les sépare par des virgules dans le commentaire.</p>
<p>Autre astuce, si votre sortie doit contenir un saut de ligne, Python va l’interpréter comme la fin des tests. On peut pallier cela en utilisant <code>&lt;BLANKLINE&gt;</code> :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;
&gt;&gt;&gt; print('Un saut de ligne<span style="color: #000099; font-weight: bold;">\\</span>n')
Un saut de ligne
&nbsp;
&quot;&quot;&quot;</span></pre></td></tr></table></div>

<p>Faites attention aux antislash et autres caractères spéciaux dans vos docstests puisque toute string est parsée deux fois : une fois à l&#8217;écriture de la docstring, puis une fois à son exécution. Ici vous voyez que je suis tenu d&#8217;échapper mon <code>\n</code> On peut d&#8217;ailleurs utiliser les préfixes <code>r</code> (cf: les <a href="http://sametmax.com/comment-marchent-les-raw-strings-en-python/">raw strings</a>) et <code>u</code> sur les docstrings, si un jour vous êtes bloqué par trop d&#8217;échappements ou des caractères non ASCII en pagaille, pensez-y.</p>
<p>Un cas particulier est celui des exceptions. LOL, n&#8217;est-il pas ?</p>
<p>Pour y répondre, Python décide qu&#8217;une expression est levée si il voit <code>Traceback (most recent call last):</code>. Il ignore ensuite tout le texte &#8211; qui est donc optionnel et que vous pouvez omettre &#8211; jusqu&#8217;à ce qu&#8217;il rencontre le nom de l&#8217;exception levée. À partir de là, il vérifie que le test passe.</p>
<p>Par exemple, si votre exception génère ce traceback :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> 
  File <span style="color: #483d8b;">&quot;test.py&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">41</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> ajouter
    <span style="color: #ff4500;">1</span> / <span style="color: #ff4500;">0</span>
<span style="color: #008000;">ZeroDivisionError</span>: integer division <span style="color: #ff7700;font-weight:bold;">or</span> modulo by zero</pre></td></tr></table></div>

<p>Vous pouvez faire dans votre doctest :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;
&gt;&gt;&gt; je_leve_une_exception()
Traceback (most recent call last):
ZeroDivisionError: integer division or modulo by zero
&quot;&quot;&quot;</span></pre></td></tr></table></div>

<p>Seule la dernière ligne est comparée.</p>
<p>Il est également possible de mettre les doctests dans un fichier texte à part, mais je ne vous le recommande pas. Cela retire l’intérêt principal des doctests : avoir du code exécutable dans la doc. Si on doit avoir un fichier séparé, autant utiliser des tests normaux, bien plus pratiques et complets.</p>
<p>Car il n&#8217;y a pas de tear down, setup ou fixtures avec les docstests. Ca reste un outil basique.</p>
<p>Sachez néanmoins que les doctests sont parfaitement compris par <code>pytest</code>, il suffit juste de lui demander de les exécuter avec l&#8217;option suivante :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">py.test <span style="color: #660033;">--doctest-modules</span></pre></td></tr></table></div>

<p>Dans ce cas, il n&#8217;est pas nécessaire de faire à la fin de chaque fichier contenant des doctests :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">doctest</span>
    <span style="color: #dc143c;">doctest</span>.<span style="color: black;">testmod</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<h2>Quand utiliser les doctests ?</h2>
<p>Généralement, on utilise un mélange des tests ordinaires (dans notre cas des tests <code>pytest</code> plutôt que <code>unittest</code>) et des doctests.</p>
<p>On utilisera des doctests pour les objets ou les fonctions simples et indépendantes. J&#8217;entends par là, des fonctions et des objets qui prennent uniquement des types basiques en paramètres, et qui retournent uniquement ces types basiques en paramètres. Pour les objets, ils doivent avoir peu de méthodes.</p>
<p>Pour tout le reste, on utilisera des tests ordinaires.</p>
<p>Par exemple, si vous avez une fonction comme notre exemple <code>get()</code>, les doctests sont un bon choix. En revanche, si vous avez un objet <code>Server</code> qui est un serveur HTTP, ou une fonction qui prend un objet <code>Server</code> en paramètre, il vaut mieux utiliser les tests ordinaires.</p>
<p>Il est tout à fait possible, et même agréable, de mettre quelques tests simples en doctests qui aident à la documentation, et de faire les tests les plus compliqués via <code>pytest</code>.</p>
<p>Prochaine étape, les mocks. Parti de là, je pourrais vous dire quelles parties de votre programme tester en priorité, et comment. Au début je voulais faire l&#8217;inverse, mais finalement, c&#8217;est plus pratique.</p>
<hr />
<p><a href="https://github.com/sametmax/codes-des-articles/blob/master/2014/decembre/docstests.py">Télécharger le code de l&#8217;article</a></p>


feed_id: http://sametmax.com/?p=12693
title: Introduction au currying Recently updated !
uri: Introduction-au-currying-Recently-updated
url: http://sametmax.com/introduction-au-currying/
content:
<p>Le currying (ou Curryfication pour les frencofans) est le nom donné à une technique de programmation qui consiste à créer une fonction à partir d&#8217;une autre fonction et d&#8217;une liste partielle de paramètres destinés à celle-ci. On retrouve massivement cette technique en programmation fonctionnelle puisqu&#8217;elle permet de créer une fonction pure à partir d&#8217;une autre fonction pure. C&#8217;est une forme de réutilisabilité de code.</p>
<p>La forme la plus simple de currying est de réécrire une fonction appelant l&#8217;autre. Par exemple, soit une fonction pour multiplier tous les éléments d&#8217;un itérable :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> multiply<span style="color: black;">&#40;</span>iterable<span style="color: #66cc66;">,</span> number<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Multiplie tous les éléments d'un itérable par un nombre.
&nbsp;
        Exemple :
&nbsp;
            &gt;&gt;&gt; list(multiply([1, 2, 3], 2))
            [2, 4, 6]
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span>x * number <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> iterable<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>On peut ensuite créer une fonction qui multipliera par 2 tous les éléments d&#8217;un itérable :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> doubled<span style="color: black;">&#40;</span>iterable<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Multiplie tous les éléments d'un itérable par un 2.
&nbsp;
        Exemple :
&nbsp;
            &gt;&gt;&gt; list(doubled([1, 2, 3]))
            [2, 4, 6]
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> multiply<span style="color: black;">&#40;</span>iterable<span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>C&#8217;est une forme de currying. On créé une fonction qui fait ce que fait une autre fonction, mais avec des arguments par défaut.</p>
<p>Python possède une fonction pour faire ça automatiquement avec n&#8217;importe quelle fonction :</p>

<div class="wp_syntax"><table><tr><td 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> functools <span style="color: #ff7700;font-weight:bold;">import</span> partial 
<span style="color: #66cc66;">&gt;&gt;&gt;</span> tripled <span style="color: #66cc66;">=</span> partial<span style="color: black;">&#40;</span>multiply<span style="color: #66cc66;">,</span> number<span style="color: #66cc66;">=</span><span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># on curryfie ici</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>tripled<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># nouvelle fonction avec un seul argument</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">6</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">9</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Cela marche car, je vous le rappelle, les fonctions sont des objets en Python. On peut mettre une fonction (je ne parle pas de son résultat) dans une variable, passer une fonction en paramètre ou retourner une fonction dans une autre fonction. <strong>Les fonctions sont manipulables</strong>.</p>
<p>Il n&#8217;est pas rare d&#8217;utiliser les fonctions anonymes comme outils curryfication. En Python, on ferait ça avec une <a href="http://sametmax.com/fonctions-anonymes-en-python-ou-lambda/">lambda</a> :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> tripled <span style="color: #66cc66;">=</span> <span style="color: #ff7700;font-weight:bold;">lambda</span> x: multiple<span style="color: black;">&#40;</span>x<span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span> 
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>tripled<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">6</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">9</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Certains outils, comme <a href="http://buzzdecafe.github.io/code/2014/05/16/introducing-ramda/">Ramda</a> en Javascript, vont plus loin, et exposent des fonctions qui se curryfient automatiquement.</p>
<p>Pour ce faire, il faut inverser l&#8217;ordre qu&#8217;on mettrait intuitivement aux arguments dans la déclaration d&#8217;une fonction :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># au lieu de multiply(iterable, number), on a :</span>
<span style="color: #ff7700;font-weight:bold;">def</span> multiply<span style="color: black;">&#40;</span>number<span style="color: #66cc66;">,</span> iterable<span style="color: #66cc66;">=</span><span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># Si on a pas d'itérable passé, on curryfie</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> iterable <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> partial<span style="color: black;">&#40;</span>multiply<span style="color: #66cc66;">,</span> number<span style="color: #66cc66;">=</span>number<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span>x * number <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> iterable<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Ainsi :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>multiply<span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># pas de currying</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">4</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">6</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> quintuple <span style="color: #66cc66;">=</span> multiply<span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># currying automatique</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>quintuple<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">5</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">10</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">15</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>L’intérêt de ce style, c&#8217;est qu&#8217;on peut composer des traitements à partir de plusieurs sous traitements, presque déclarativement :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> remove<span style="color: black;">&#40;</span><span style="color: #008000;">filter</span><span style="color: #66cc66;">,</span> iterable<span style="color: #66cc66;">=</span><span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Retire tous les éléments d'un itérable correspondant au filtre.
&nbsp;
        Exemple :
&nbsp;
            &gt;&gt;&gt; list(remove(lambda x: x &gt;= 4, [1, 2, 3, 4, 5]))
            [1, 2, 3]
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> iterable <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> partial<span style="color: black;">&#40;</span>remove<span style="color: #66cc66;">,</span> <span style="color: #008000;">filter</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span>x <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> iterable <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">filter</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> smalls <span style="color: #66cc66;">=</span> remove<span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> x: x <span style="color: #66cc66;">&gt;=</span> <span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>smalls<span style="color: black;">&#40;</span>tripled<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># le traitement est auto descriptif</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Néanmoins, il faut savoir que ce style n&#8217;est pas pythonique. En effet, en Python on préférera généralement utiliser des suites suite de générateurs. Soit par <a href="http://sametmax.com/python-love-les-listes-en-intention-partie-2/">intention</a>, soit via <a href="http://sametmax.com/comment-utiliser-yield-et-les-generateurs-en-python/">yield</a>.</p>
<p>Notre exemple serait alors :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> tripled <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span>x * <span style="color: #ff4500;">3</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> smalls <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span>x <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> tripled <span style="color: #ff7700;font-weight:bold;">if</span> x <span style="color: #66cc66;">&lt;=</span> <span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>smalls<span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>De plus, cette technique suppose qu&#8217;on ne profitera pas de certaines fonctionnalités, comme les paramètres par défaut des fonctions Python.</p>
<p>C&#8217;est toutefois une bonne chose à connaître. C&#8217;est occasionnellement utile en Python et peut produire des solutions très élégantes. C&#8217;est également une bonne chose à comprendre pour aborder d&#8217;autres langages plus fonctionnels qui les utilisent bien plus comme le Javascript, le Lisp, ou carrément le Haskell.</p>


feed_id: http://sametmax.com/?p=12815
title: Des bouts de Python cachés Recently updated !
uri: Des-bouts-de-Python-cachés-Recently-updated
url: http://sametmax.com/des-bouts-de-python-caches/
content:
<p>J&#8217;aime bien fouiner pour trouver des petits trucs insolites dans mes techos. Cet <a href="http://stackoverflow.com/questions/101268/hidden-features-of-python?page=3&#038;tab=oldest#tab-top">excellent post</a> sur SO est un bon début, mais on découvre toujours de nouvelles choses.</p>
<h2>ChainMap</h2>
<p>Vous vous souvenez de <a href="http://sametmax.com/chercher-dans-plusieurs-dicts-a-la-fois-avec-chainmap/">ChainMap</a> ? C&#8217;est top, mais uniquement en Python 3. </p>
<p>Et bien il existe une version cachée en Python 2 :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">ConfigParser</span> <span style="color: #ff7700;font-weight:bold;">import</span> _Chainmap <span style="color: #ff7700;font-weight:bold;">as</span> ChainMap</pre></td></tr></table></div>

<p>C&#8217;est pas aussi complet (il n&#8217;y pas les méthodes <code>new_child</code> et <code>parents</code>), mais ça peut servir.</p>
<p>Si néanmoins, vous avez besoin de l&#8217;implémentation complète, il existe <a href="https://github.com/justanr/Py2ChainMap">un backport</a> installable avec <a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a> :</p>
<p><code lang="bash">pip install Py2ChainMap</code></p>
<h2>str.startswith, str.endswith et un tuple</h2>
<p>Pour beaucoup de situations, une regex en Python, c&#8217;est overkill. On a <code>in</code> pour vérifier qu&#8217;une chaîne en contient une autre. Et on a <code>str.startswith()</code> et <code>str.endswith()</code> pour vérifier qu&#8217;on chaîne commence ou finit par une autre. Avec des <code>strip()</code>/<code>split()</code>/<code>lower()</code>, on finit souvent par s&#8217;en sortir, et l&#8217;usage de toutes ces méthodes sont en général plus performantes que d&#8217;utiliser <code>re</code>.</p>
<p>Mais si vous avez plusieurs chaînes à vérifier ? Pas de problème, <code>str.startswith()</code> et <code>str.endswith()</code> acceptent aussi des tuples :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;Je suis une chaîne qui a du caractère&quot;</span>.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Tu'</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">False</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;Je suis une chaîne qui a du caractère&quot;</span>.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Je'</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">True</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;Je suis une chaîne qui a du caractère&quot;</span>.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Tu'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Je'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">True</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span></pre></td></tr></table></div>

<h2>Les espaces entre une instance et son attribut sont ignorés</h2>
<p>Bien que la deuxième ligne soit très moche, elle est parfaitement valide :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;Yolo&quot;</span>.<span style="color: black;">upper</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'YOLO'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;Yolo&quot;</span>           .<span style="color: black;">upper</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'YOLO'</span></pre></td></tr></table></div>

<p>Or on peut intercepter l&#8217;accès aux attributs à la volée en Python grâce aux <a href="http://sametmax.com/le-guide-ultime-et-definitif-sur-la-programmation-orientee-objet-en-python-a-lusage-des-debutants-qui-sont-rassures-par-les-textes-detailles-qui-prennent-le-temps-de-tout-expliquer-partie-6/">méthodes magiques</a>.</p>
<p>Ca veut dire qu&#8217;on peut implémenter des &#8220;symboles&#8221; en Python.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> SymbolMaker<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
    symbols <span style="color: #66cc66;">=</span> <span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__getattr__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> value<span style="color: black;">&#41;</span>:
        symbols.<span style="color: black;">add</span><span style="color: black;">&#40;</span>value<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> make_symbol <span style="color: #66cc66;">=</span> SymbolMaker<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> make_symbol   .<span style="color: black;">start</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> make_symbol   .<span style="color: black;">end</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> SymbolMaker.<span style="color: black;">symbols</span>
<span style="color: black;">&#123;</span><span style="color: #483d8b;">'end'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'start'</span><span style="color: black;">&#125;</span></pre></td></tr></table></div>

<p>Je n&#8217;ai pas dit qu&#8217;on devrait le faire, j&#8217;ai dit qu&#8217;on pouvait :) D&#8217;ailleurs, y en a qui <a href="http://entrian.com/goto/">l&#8217;utilisent pour implémenter <code>GOTO</code> en Python</a>. The troll is strong with this &#8220;feature&#8221;.</p>


feed_id: http://sametmax.com/?p=12854
title: Qu’est-ce qu’une coroutine en Python, et à quoi ça sert ? Recently updated !
uri: Qu-est-ce-qu-une-coroutine-en-Python-et-à-quoi-ça-sert-Rec
url: http://sametmax.com/quest-ce-quune-coroutine-en-python-et-a-quoi-ca-sert/
content:
<p>Si vous avez aimé les générateurs, vous avez du creuser un peu <code>yield</code> et vous apercevoir qu&#8217;on pouvait créer des coroutines avec. Mais sans vraiment comprendre ce que ça faisait.</p>
<p>On va se faire une petit intro. C&#8217;est un sujet vraiment avancé, donc si vous avez autre chose de moins compliqué à comprendre en Python (n&#8217;importe quoi à part les métaclasses :)), ne vous prenez pas la tête sur cet article. Ecoutez juste la musique :</p>
<p><span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='1170' height='689' src='http://www.youtube.com/embed/zqKZ_WIK5ms?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0' allowfullscreen='true'></iframe></span></p>
<p>D&#8217;abord, rappel sur le fonctionnement des générateurs (qui sont un prérequis de l&#8217;article, donc si besoin, relisez le <a href="http://sametmax.com/comment-utiliser-yield-et-les-generateurs-en-python/">tuto dédié</a>) :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> soleil<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Premier next()'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Yield 1'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #ff4500;">1</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Deuxième next()'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Yield 2'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #ff4500;">2</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Troisième next()'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Yield 3'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #ff4500;">3</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># pas de quatrième next(),</span>
    <span style="color: #808080; font-style: italic;"># donc on ne passe jamais ici</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Pas vu'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># rappel, ceci ne déclenche pas le code </span>
<span style="color: #808080; font-style: italic;"># de soleil() puisqu'il y a yield dedans</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Creation du generateur&quot;</span><span style="color: black;">&#41;</span>
undeuxtrois <span style="color: #66cc66;">=</span> soleil<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On execute le code jusqu'au yield 1</span>
res <span style="color: #66cc66;">=</span> next<span style="color: black;">&#40;</span>undeuxtrois<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'res = %s'</span> % res<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On execute le code jusqu'au yield 2</span>
res <span style="color: #66cc66;">=</span> next<span style="color: black;">&#40;</span>undeuxtrois<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'res = %s'</span> % res<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On execute le code jusqu'au yield 3</span>
res <span style="color: #66cc66;">=</span> next<span style="color: black;">&#40;</span>undeuxtrois<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'res = %s'</span> % res<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Good bye'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">## Premier next()</span>
<span style="color: #808080; font-style: italic;">## Yield 1</span>
<span style="color: #808080; font-style: italic;">## res = 1</span>
<span style="color: #808080; font-style: italic;">## Deuxième next()</span>
<span style="color: #808080; font-style: italic;">## Yield 2</span>
<span style="color: #808080; font-style: italic;">## res = 2</span>
<span style="color: #808080; font-style: italic;">## Troisième next()</span>
<span style="color: #808080; font-style: italic;">## Yield 3</span>
<span style="color: #808080; font-style: italic;">## res = 3</span>
<span style="color: #808080; font-style: italic;">## Good bye</span></pre></td></tr></table></div>

<p>Chaque fois qu&#8217;on appelle <code>next()</code> sur le générateur, il va exécuter le code jusqu&#8217;au prochain <code>yield</code>, et retourner la valeur de celui-ci, puis mettre le générateur en pause.</p>
<p>On peut assigner le résultat d&#8217;un <code>yield</code>, mais si on fait des <code>next()</code>, on obtient toujours <code>None</code> :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> lune<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Premier next()'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Yield 1'</span><span style="color: black;">&#41;</span>
    x <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">yield</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: black;">&#40;</span><span style="color: #483d8b;">'Deuxième next()'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Avant le yield 2, x = %s'</span> % x<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Yield 2'</span><span style="color: black;">&#41;</span>
    x <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Troisième next()'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Avant le yield 3, x = %s'</span> % x<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Yield 3'</span><span style="color: black;">&#41;</span>
    x <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Pas vu'</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Creation du generateur&quot;</span><span style="color: black;">&#41;</span>
generateur <span style="color: #66cc66;">=</span> lune<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
res <span style="color: #66cc66;">=</span> next<span style="color: black;">&#40;</span>generateur<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'res = %s'</span> % res<span style="color: black;">&#41;</span>
&nbsp;
res <span style="color: #66cc66;">=</span> next<span style="color: black;">&#40;</span>generateur<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'res = %s'</span> % res<span style="color: black;">&#41;</span>
&nbsp;
res <span style="color: #66cc66;">=</span> next<span style="color: black;">&#40;</span>generateur<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'res = %s'</span> % res<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Good bye'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">## Creation du generateur</span>
<span style="color: #808080; font-style: italic;">## Premier next()</span>
<span style="color: #808080; font-style: italic;">## Yield 1</span>
<span style="color: #808080; font-style: italic;">## res = 1</span>
<span style="color: #808080; font-style: italic;">## Deuxième next()</span>
<span style="color: #808080; font-style: italic;">## Avant le yield 2, x = None</span>
<span style="color: #808080; font-style: italic;">## Yield 2</span>
<span style="color: #808080; font-style: italic;">## res = 2</span>
<span style="color: #808080; font-style: italic;">## Troisième next()</span>
<span style="color: #808080; font-style: italic;">## Avant le yield 3, x = None</span>
<span style="color: #808080; font-style: italic;">## Yield 3</span>
<span style="color: #808080; font-style: italic;">## res = 3</span>
<span style="color: #808080; font-style: italic;">## Good bye</span></pre></td></tr></table></div>

<p>La raison est que cette valeur doit venir de l&#8217;extérieur. Pour la fournir, il faut utiliser la méthode <code>send()</code> et non la fonction <code>next()</code>.</p>
<p>Mais elle ne fonctionne pas du tout pareil. En fait, si on l&#8217;appelle cash pistache, ça plante :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Creation du generateur&quot;</span><span style="color: black;">&#41;</span>
generateur <span style="color: #66cc66;">=</span> lune<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
res <span style="color: #66cc66;">=</span> generateur.<span style="color: black;">send</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;A&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'res = %s'</span> % res<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">## Creation du generateur</span>
<span style="color: #808080; font-style: italic;">## Traceback (most recent call last):</span>
<span style="color: #808080; font-style: italic;">## File &quot;test.py&quot;, line 24, in </span>
<span style="color: #808080; font-style: italic;">##   res = generateur.send(&quot;A&quot;)</span>
<span style="color: #808080; font-style: italic;">##     TypeError: can't send non-None value to a just-started generator</span></pre></td></tr></table></div>

<p>C&#8217;est parce que, contrairement à <code>next()</code> qui va jusqu&#8217;au prochain <code>yield</code>, <code>send()</code> PART du dernier <code>yield</code> atteint pour aller au suivant.</p>
<p>Il faut donc d&#8217;abord arriver à un premier <code>yield</code> avant de faire un <code>send()</code>. On peut le faire en utilisant au moins un <code>next()</code>.</p>
<p>Voici donc notre nouveau code :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> lune<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'On fait au moins un next()'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Yield 1'</span><span style="color: black;">&#41;</span>
&nbsp;
    x <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">yield</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: black;">&#40;</span><span style="color: #483d8b;">'Premier send(), x = %s'</span> % x<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Yield 2'</span><span style="color: black;">&#41;</span>
&nbsp;
    x <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Deuxième send(), x = %s'</span> % x<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Yield 3'</span><span style="color: black;">&#41;</span>
&nbsp;
    x <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Comme on fait un next() et 3 send()</span>
    <span style="color: #808080; font-style: italic;"># on arrive là</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Troisième send(), x = %s'</span> % x<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'YOLOOOOO'</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Creation du generateur&quot;</span><span style="color: black;">&#41;</span>
generateur <span style="color: #66cc66;">=</span> lune<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
next<span style="color: black;">&#40;</span>generateur<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># Ou generateur.send(None)</span>
&nbsp;
res <span style="color: #66cc66;">=</span> generateur.<span style="color: black;">send</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;A&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'res = %s'</span> % res<span style="color: black;">&#41;</span>
&nbsp;
res <span style="color: #66cc66;">=</span> generateur.<span style="color: black;">send</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;B&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'res = %s'</span> % res<span style="color: black;">&#41;</span>
&nbsp;
res <span style="color: #66cc66;">=</span> generateur.<span style="color: black;">send</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;C&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'res = %s'</span> % res<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Good bye'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">## Creation du generateur</span>
<span style="color: #808080; font-style: italic;">## On fait au moins un next()</span>
<span style="color: #808080; font-style: italic;">## Yield 1</span>
<span style="color: #808080; font-style: italic;">## Premier send(), x = A</span>
<span style="color: #808080; font-style: italic;">## Yield 2</span>
<span style="color: #808080; font-style: italic;">## res = 2</span>
<span style="color: #808080; font-style: italic;">## Deuxième send(), x = B</span>
<span style="color: #808080; font-style: italic;">## Yield 3</span>
<span style="color: #808080; font-style: italic;">## res = 3</span>
<span style="color: #808080; font-style: italic;">## Troisième send(), x = C</span>
<span style="color: #808080; font-style: italic;">## YOLOOOOO</span>
<span style="color: #808080; font-style: italic;">## Traceback (most recent call last):</span>
<span style="color: #808080; font-style: italic;">##   File &quot;test.py&quot;, line 33, in </span>
<span style="color: #808080; font-style: italic;">##     res = generateur.send(&quot;C&quot;)</span>
<span style="color: #808080; font-style: italic;">## StopIteration</span></pre></td></tr></table></div>

<p><code>send()</code> agit donc comme <code>next()</code>. Il va aller jusqu&#8217;au prochain <code>yield</code> et lui faire retourner sa valeur. Mais il y a des différences :</p>
<ul>
<li>Elle doit partir d&#8217;un précédent <code>yield</code>.</li>
<li>Donc il faut au moins avoir atteint un <code>yield</code> via <code>next()</code>.</li>
<li>Ce précédent <code>yield</code> peut retourner une valeur : celle passée via <code>send(val).</code></li>
</ul>
<p>La valeur peut être n&#8217;importe quel objet : string, int, classe, list, etc.</p>
<p>Bref, <code>send()</code> permet de créer un générateur donc le comportement n&#8217;est pas figé dans le marbre.</p>
<p>Par exemple :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> creer_fontaine<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    contenu <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;soda&quot;</span> 
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
        x <span style="color: #66cc66;">=</span> <span style="color: #ff7700;font-weight:bold;">yield</span> contenu
        <span style="color: #ff7700;font-weight:bold;">if</span> x:
            contenu <span style="color: #66cc66;">=</span> x
&nbsp;
&nbsp;
fontaine <span style="color: #66cc66;">=</span> creer_fontaine<span style="color: black;">&#40;</span><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> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>next<span style="color: black;">&#40;</span>fontaine<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># on change le contenu de la fontaine</span>
fontaine.<span style="color: black;">send</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;lait&quot;</span><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> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>next<span style="color: black;">&#40;</span>fontaine<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
soda
soda
soda
soda
soda
lait
lait
lait
lait
lait</pre></td></tr></table></div>

<p>On peut même s&#8217;en servir pour faire des trucs chelou comme injecter une dépendance à la volée ou contrôler le flux de son générateur :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> fuckitjaiplusdenomcool<span style="color: black;">&#40;</span>start<span style="color: #66cc66;">,</span> inc<span style="color: #66cc66;">=</span><span style="color: #ff7700;font-weight:bold;">lambda</span> x: x + <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>:
    x <span style="color: #66cc66;">=</span> start
    <span style="color: #808080; font-style: italic;"># on controle le flux du générateur en changeant</span>
    <span style="color: #808080; font-style: italic;"># la valeur de x qui peut tout stopper</span>
    <span style="color: #ff7700;font-weight:bold;">while</span> x:
        sent <span style="color: #66cc66;">=</span> <span style="color: #ff7700;font-weight:bold;">yield</span> x
        <span style="color: #ff7700;font-weight:bold;">if</span> sent:
            inc <span style="color: #66cc66;">=</span> sent
        <span style="color: #808080; font-style: italic;"># la valeur de x dépend de ce bout de code</span>
        <span style="color: #808080; font-style: italic;"># qui est injectable</span>
        x <span style="color: #66cc66;">=</span> inc<span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
generateur <span style="color: #66cc66;">=</span> fuckitjaiplusdenomcool<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;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> generateur:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> x &amp;gt<span style="color: #66cc66;">;</span> <span style="color: #ff4500;">10</span>:
        <span style="color: #808080; font-style: italic;"># si on dépasse 10, on décrémente</span>
        generateur.<span style="color: black;">send</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> x: x - <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">## 1</span>
<span style="color: #808080; font-style: italic;">## 2</span>
<span style="color: #808080; font-style: italic;">## 3</span>
<span style="color: #808080; font-style: italic;">## 4</span>
<span style="color: #808080; font-style: italic;">## 5</span>
<span style="color: #808080; font-style: italic;">## 6</span>
<span style="color: #808080; font-style: italic;">## 7</span>
<span style="color: #808080; font-style: italic;">## 8</span>
<span style="color: #808080; font-style: italic;">## 9</span>
<span style="color: #808080; font-style: italic;">## 10</span>
<span style="color: #808080; font-style: italic;">## 11</span>
<span style="color: #808080; font-style: italic;">## 9</span>
<span style="color: #808080; font-style: italic;">## 8</span>
<span style="color: #808080; font-style: italic;">## 7</span>
<span style="color: #808080; font-style: italic;">## 6</span>
<span style="color: #808080; font-style: italic;">## 5</span>
<span style="color: #808080; font-style: italic;">## 4</span>
<span style="color: #808080; font-style: italic;">## 3</span>
<span style="color: #808080; font-style: italic;">## 2</span>
<span style="color: #808080; font-style: italic;">## 1</span></pre></td></tr></table></div>

<p>Mais bon, pas la peine de rentrer dans des cas si compliqués.</p>
<p>Néanmoins, un cas d&#8217;usage de <code>send()</code> est de créer une coroutine. Une coroutine est simplement une tâche.</p>
<p>C&#8217;est un bout de code qui fait une tache, avec un bout d&#8217;initialisation, et un bout de finalisation, et un bout d&#8217;exécution.</p>
<p>Par exemple, j&#8217;ai un filtre qui prend un fichier rempli d&#8217;adresses IP. Il va recevoir du texte, et si le texte contient une adresse IP, il le signale, et remplit un compteur sur le disque.</p>
<p>Si on devait coder ça en objet on dirait :</p>

<div class="wp_syntax"><table><tr><td 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;">class</span> Filtre:
&nbsp;
    <span style="color: #808080; font-style: italic;"># initialisation</span>
    <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> ipfile<span style="color: #66cc66;">,</span> counterfile<span style="color: black;">&#41;</span>:
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>ipfile<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'r'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> f:
            <span style="color: #008000;">self</span>.<span style="color: black;">banned_ips</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">set</span><span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>counterfile<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> f:
            <span style="color: #008000;">self</span>.<span style="color: black;">count</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>f.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">counterfile</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>counterfile<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'w'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> check<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> line<span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># récupère les ip et check celles qui sont </span>
        <span style="color: #808080; font-style: italic;"># à filtrer</span>
        ips <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">findall</span><span style="color: black;">&#40;</span> r<span style="color: #483d8b;">'[0-9]+(?:<span style="color: #000099; font-weight: bold;">\.</span>[0-9]+){3}'</span><span style="color: #66cc66;">,</span> line<span style="color: black;">&#41;</span>
        bad_ips <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span>ip <span style="color: #ff7700;font-weight:bold;">for</span> ip <span style="color: #ff7700;font-weight:bold;">in</span> ips <span style="color: #ff7700;font-weight:bold;">if</span> ip <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">self</span>.<span style="color: black;">banned_ips</span><span style="color: black;">&#93;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># si il y a des ip à filtrer, on incrémente le compteur</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> bad_ips:
            <span style="color: #008000;">self</span>.<span style="color: black;">count</span> +<span style="color: #66cc66;">=</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>bad_ips<span style="color: black;">&#41;</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">counterfile</span>.<span style="color: black;">seek</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">counterfile</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">count</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># on retourn les valeurs trouvées</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> bad_ips
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> close<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">counterfile</span>.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>On l&#8217;utiliserait comme ça :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">f <span style="color: #66cc66;">=</span> Filtre<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;/chemin/vers/liste&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;/chemin/vers/counteur&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> line <span style="color: #ff7700;font-weight:bold;">in</span> text:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>f.<span style="color: black;">check</span><span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
f.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Notez que pour une tâche, l&#8217;API est toujours la même : initialiser, exécuter la tâche autant de fois que nécessaire, puis finaliser.</p>
<p>Les coroutines sont un mot qu&#8217;on met sur ce principe (initialiser, exec, finaliser), mais avec une API sous forme de générateur. Le même code en coroutine :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> filtre<span style="color: black;">&#40;</span>ipfile<span style="color: #66cc66;">,</span> counterfile<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># Initialisation</span>
    <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>ipfile<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'r'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> f:
        banned_ips <span style="color: #66cc66;">=</span> <span style="color: #008000;">set</span><span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>counterfile<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> f:
        count <span style="color: #66cc66;">=</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>f.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    counterfile <span style="color: #66cc66;">=</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>counterfile<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'w'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Exécution</span>
    bad_ips <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
    <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>:
            <span style="color: #808080; font-style: italic;"># entree et sortie de notre send(), qui équivaut</span>
            <span style="color: #808080; font-style: italic;"># aux params de &quot;check()&quot;</span>
            line <span style="color: #66cc66;">=</span> <span style="color: #ff7700;font-weight:bold;">yield</span> bad_ips
&nbsp;
        <span style="color: #808080; font-style: italic;"># GeneratorExit est levé is on fait generator.close()</span>
        <span style="color: #808080; font-style: italic;"># On ne peut pas ignorer cette erreur, mais</span>
        <span style="color: #808080; font-style: italic;"># on peut mettre du code de finalisation ici.</span>
        <span style="color: #808080; font-style: italic;"># Bon en vrai faudrait faire un finally quelque part</span>
        <span style="color: #808080; font-style: italic;"># mais c'est pour l'exemple bande de peer reviewers</span>
        <span style="color: #ff7700;font-weight:bold;">except</span> GeneratorExit:
                <span style="color: #008000;">self</span>.<span style="color: black;">counterfile</span>.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
        ips <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">findall</span><span style="color: black;">&#40;</span> r<span style="color: #483d8b;">'[0-9]+(?:<span style="color: #000099; font-weight: bold;">\.</span>[0-9]+){3}'</span><span style="color: #66cc66;">,</span> line<span style="color: black;">&#41;</span>
        bad_ips <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span>ip <span style="color: #ff7700;font-weight:bold;">for</span> ip <span style="color: #ff7700;font-weight:bold;">in</span> ips <span style="color: #ff7700;font-weight:bold;">if</span> ip <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">self</span>.<span style="color: black;">banned_ips</span><span style="color: black;">&#93;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># si il y a des ip à filtrer, on incrémente le compteur</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> bad_ips:
            <span style="color: #008000;">self</span>.<span style="color: black;">count</span> +<span style="color: #66cc66;">=</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>bad_ips<span style="color: black;">&#41;</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">counterfile</span>.<span style="color: black;">seek</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">counterfile</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">count</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>On l&#8217;utiliserait comme ça :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">f <span style="color: #66cc66;">=</span> filtre<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;/chemin/vers/liste&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;/chemin/vers/counteur&quot;</span><span style="color: black;">&#41;</span>
next<span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> line <span style="color: #ff7700;font-weight:bold;">in</span> text:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>f.<span style="color: black;">send</span><span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># ceci raise GeneratorExit</span>
f.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Généralement on veut pas se faire chier à appeler <code>next()</code> à chaque fois, donc toutes les libs à base de coroutine ont ce genre de décorateur :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> coroutine<span style="color: black;">&#40;</span>func<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> wrapper<span style="color: black;">&#40;</span>*arg<span style="color: #66cc66;">,</span> **kwargs<span style="color: black;">&#41;</span>:
        generator <span style="color: #66cc66;">=</span> func<span style="color: black;">&#40;</span>*arg<span style="color: #66cc66;">,</span> **kwargs<span style="color: black;">&#41;</span>
        next<span style="color: black;">&#40;</span>generator<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> generator
    <span style="color: #ff7700;font-weight:bold;">return</span> wrapper</pre></td></tr></table></div>

<p>Afin de pouvoir faire ça :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">@</span>coroutine
<span style="color: #ff7700;font-weight:bold;">def</span> filtre<span style="color: black;">&#40;</span>ipfile<span style="color: #66cc66;">,</span> counterfile<span style="color: black;">&#41;</span>:
    ...</pre></td></tr></table></div>

<p>Ca a un double usage : ça appelle <code>next()</code> automatiquement, et ça signale que la fonction est destinée à être utilisée comme coroutine.</p>
<p>Mais voilà, c&#8217;est tout, une coroutine c&#8217;est juste ça : utiliser un générateur pour faire une tâche qui consiste à s&#8217;initialiser, faire un traitement plusieurs fois, et optionellement, se finaliser. On utilisera une coroutine pour ne pas reinventer la roue car c&#8217;est un problème bien défini, qui a une solution. D&#8217;autant qu&#8217;une coroutine bouffe moins de ressources qu&#8217;une classe.</p>
<p>Les usages avancés des coroutines impliquent de chaîner plusieurs coroutines, comme des tuyaux.</p>
<p>Souvenez-vous, en Python il est courant de chaîner des générateurs :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> mettre_au_carre<span style="color: black;">&#40;</span>iterable<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> iterable:
        <span style="color: #ff7700;font-weight:bold;">yield</span> x * x
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> filtrer_les_pairs<span style="color: black;">&#40;</span>iterable<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> iterable:
        <span style="color: #ff7700;font-weight:bold;">if</span> x % <span style="color: #ff4500;">2</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">0</span>:
            <span style="color: #ff7700;font-weight:bold;">yield</span> x
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> strigifier<span style="color: black;">&#40;</span>iterable<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> iterable:
        <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># on pipe les données d'un générateur à l'autre</span>
nombres <span style="color: #66cc66;">=</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span>
carres <span style="color: #66cc66;">=</span> mettre_au_carre<span style="color: black;">&#40;</span>nombres<span style="color: black;">&#41;</span>
carres_pairs <span style="color: #66cc66;">=</span> filtrer_les_pairs<span style="color: black;">&#40;</span>carres<span style="color: black;">&#41;</span>
fete_du_string <span style="color: #66cc66;">=</span> strigifier<span style="color: black;">&#40;</span>carres_pairs<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> fete_du_string:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">repr</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">## '0'</span>
<span style="color: #808080; font-style: italic;">## '4'</span>
<span style="color: #808080; font-style: italic;">## '16'</span>
<span style="color: #808080; font-style: italic;">## '36'</span>
<span style="color: #808080; font-style: italic;">## '64'</span></pre></td></tr></table></div>

<p>On peut faire pareil avec les coroutines. Cependant, la logique est inversée : au lieu de lire les données, on les envoie :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">@</span>coroutine
<span style="color: #ff7700;font-weight:bold;">def</span> mettre_au_carre<span style="color: black;">&#40;</span>ouput<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
        x <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">yield</span><span style="color: black;">&#41;</span>
        ouput.<span style="color: black;">send</span><span style="color: black;">&#40;</span>x * x<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">@</span>coroutine
<span style="color: #ff7700;font-weight:bold;">def</span> filtrer_les_paires<span style="color: black;">&#40;</span>ouput<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
        x <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">yield</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> x % <span style="color: #ff4500;">2</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">0</span>:
            ouput.<span style="color: black;">send</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">@</span>coroutine
<span style="color: #ff7700;font-weight:bold;">def</span> strigifier<span style="color: black;">&#40;</span>ouput<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
        x <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">yield</span><span style="color: black;">&#41;</span>
        ouput.<span style="color: black;">send</span><span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">@</span>coroutine
<span style="color: #ff7700;font-weight:bold;">def</span> afficher<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
        x <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">yield</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
&nbsp;
nombres <span style="color: #66cc66;">=</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># chaque coroutine est la sortie d'une autre</span>
afficheur <span style="color: #66cc66;">=</span> afficher<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
fete_du_string <span style="color: #66cc66;">=</span> strigifier<span style="color: black;">&#40;</span>afficheur<span style="color: black;">&#41;</span>
paires <span style="color: #66cc66;">=</span> filtrer_les_paires<span style="color: black;">&#40;</span>fete_du_string<span style="color: black;">&#41;</span>
carre <span style="color: #66cc66;">=</span> mettre_au_carre<span style="color: black;">&#40;</span>paires<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># on envoit les données vers la première coroutine</span>
<span style="color: #808080; font-style: italic;"># et elle fait suivre aux autres</span>
<span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> nombres:
    carre.<span style="color: black;">send</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">## '0'</span>
<span style="color: #808080; font-style: italic;">## '4'</span>
<span style="color: #808080; font-style: italic;">## '16'</span>
<span style="color: #808080; font-style: italic;">## '36'</span>
<span style="color: #808080; font-style: italic;">## '64'</span></pre></td></tr></table></div>

<p>Vous allez me dire : &#8220;ça fait la même chose, et c&#8217;est plus compliqué, quel interêt ?&#8221;.</p>
<p>En fait, ça ne fait pas exactement la même chose.</p>
<p>Dans le cas des générateurs ordinaires, on déclenche le traitement par la fin. On fait une boucle qui demande quelle est la prochaine donnée, et si il y en a une, on l&#8217;affiche. C&#8217;est pratique si on sait qu&#8217;on a des données sous la main car on demande (<code>next()</code> est appelée par la boucle <code>for</code>) la donnée suivante à chaque fois : c&#8217;est du PULL.</p>
<p>Mais que se passe-t-il si on n&#8217;a pas encore les données ? Si on traite des données qui arrivent par évenement ?</p>
<p>Par exemple, si on écrit un serveur HTTP qui doit réagir aux requêtes ?</p>
<p>Dans ce cas, on ne peut envoyer (<code>send()</code>) la donnée suivante dans notre pipeline de générateurs uniquement quand elle arrive, et les coroutines font exactement cela : c&#8217;est du PUSH.</p>
<p>En résumé :</p>
<ul>
<li><code>yield</code> permet de faire des générateurs</li>
<li>On peut demander la prochaine valeur du générateur avec <code>next()</code>. Dans ce cas, le code s&#8217;exécute jusqu&#8217;au prochain <code>yield</code>.</li>
<li>On peut envoyer une valeur au générateur avec <code>send()</code>. Dans ce cas, on DOIT partir d&#8217;un <code>yield</code> existant duquel on récupère la valeur envoyée via une assignation. Donc il faut au moins un <code>next()</code> avant d&#8217;utiliser un <code>send()</code> et un signe égal sur le <code>yield</code>.</li>
<li><code>send()</code> va aussi aller au prochain <code>yield</code> et retourner sa valeur.</li>
<li>Une coroutine n&#8217;est qu&#8217;une formalisation de la manière d&#8217;éffectuer une tâche avec un init, une exécution et une finalisation optionelle en utilisant un générateur. C&#8217;est une solution générique à un problème courant, mais plus léger qu&#8217;une classe.</li>
<li>Généralement on décore les générateurs coroutines avec un décorateur <code>@coroutine</code> pour s&#8217;éviter d&#8217;appeler <code>next()</code> à la main et notifier l&#8217;usage qu&#8217;il est fait de ce générateur.</li>
<li>On peut chaîner des coroutines comme on chaîne des générateurs, mais au lieu de lire les données une à une (PULL), on les envoie une par une (PUSH). Cela est pratique quand on ne sait pas à l&#8217;avance quand une nouvelle donnée va arriver.</li>
</ul>
<p>Si vous êtes arrivé jusqu&#8217;ici, vous méritez un cookie.</p>
<p>Ca tombe bien, ce blog utilise des cookies, et la loi m&#8217;oblige à vous le notifier.</p>


feed_id: http://sametmax.com/?p=12867
title: Quand ne pas utiliser Python ?
uri: Quand-ne-pas-utiliser-Python-Recently-updated
url: http://sametmax.com/quand-ne-pas-utiliser-python/
content:
<p>J&#8217;ai lu récemment sur un forum la question &#8220;quand utiliser Python ?&#8221;. Mais la vérité c&#8217;est que Python est un langage globalement bon partout. En fait, <a href="http://sametmax.com/quest-ce-quon-peut-faire-avec-python/">on peut presque tout faire en Python</a> car c&#8217;est un langage <a href="http://sametmax.com/10-raisons-pour-lesquelles-je-suis-toujours-marie-a-python/">bourré de qualités</a> avec <a href="http://pyvideo.org/">une belle communauté</a> et <a href="http://sametmax.com/tres-grand-listing-des-libs-tierce-partie-les-plus-utiles-en-python/">des libs pour presque tout</a>.</p>
<p>Du coup, je pense qu&#8217;il est plus judicieux de se poser la question inverse : quand ne pas utiliser Python ?</p>
<p>Pour le moment, j&#8217;évite d&#8217;utiliser Python dans les cas suivants :</p>
<ul>
<li>L&#8217;équipe avec laquelle je travaille est bien meilleure dans un autre langage. Il faut profiter des compétences de chacun au maximum plutôt que privilégier une technologie, c&#8217;est plus productif.</li>
<li>Je reprends du code d&#8217;un projet solide, dans un autre langage. Inutile de réécrire quelque chose qui est propre et qui fonctionne.</li>
<li>Je travaille dans un environnement où d&#8217;autres technologies sont mieux intégrées. Par exemple, dans une entreprise avec une forte culture Java, faire les choses dans son coin ne va pas permettre un bon travail d&#8217;équipe. Travailler avec une boîte qui a des serveurs qu&#8217;ils ne peuvent pas changer et d&#8217;autres technos ? Inutile de forcer la main.</li>
<li>Des technologies plus productives existent pour ce domaine : c&#8217;est le cas de l&#8217;embarqué, ou des jeux vidéos. Ça ne veut pas dire qu&#8217;on ne peut pas en faire en Python. En fait, il y a un fort travail de la communauté pour améliorer cela en ce moment même. Mais difficile de combattre les outils en C/C++ dans ces domaines.</li>
<li>Je suis pressé, et la solution de facto n&#8217;est pas en Python. Par exemple, je veux faire du Web temps réel. Si j&#8217;ai le temps, je ferai du Python, car ce n&#8217;est pas grave si il me faut aiguiser moi-même quelques outils pour obtenir le résultat désiré. Si par contre j&#8217;ai 2 semaines devant moi, je prendrais NodeJS, malgré <a href="http://sametmax.com/un-gros-troll-de-plus-sur-javacscript/">mon dégoût pour le Javascript</a>, car je suis pragmatique. </li>
<li>J&#8217;ai <strong>mesuré</strong> mes besoins objectivement, et est évalué que Python ne serait pas assez performant malgré toute les mesures d&#8217;optimisation que je sais mettre en œuvre. Dans ce cas, on se tourne vers des solutions plus lourdes mais nativement plus rapides : C, GO, Erlang etc.</li>
<li>Je vise une plateforme en particulier (Windows, iOS&#8230;), je n&#8217;ai pas besoin de porter mon code, et je sais qu&#8217;utiliser les outils de la boîte qui fait l&#8217;OS me donnera de meilleurs résultats. Par exemple si je vise Android uniquement, utiliser leur SDK donnera une app plus fluide et une UI mieux intégrée.</li>
</ul>
<p>Dans tous les autres cas, Python est un choix excellent.</p>


feed_id: http://sametmax.com/?p=12995
title: Embarquement en porte 19 3
uri: Embarquement-en-porte-19
url: http://sametmax.com/embarquement-en-porte-19/
content:
<p>Bon, je vais rejoindre Max et j&#8217;ai 12 heures de vol et 13 heures d&#8217;escale, donc je ferai les fixes sur les slides durant le vol. Ca me donne plus de temps pour le reste. Pas d&#8217;amélioration aujourd&#8217;hui donc. Mais merci beaucoup à tous les retours, ils sont vraiment très utiles. </p>
<p>Un de ces 4 faudra que je fasse un article sur les tests ergonomiques, ça marche un peu pareil :)</p>


feed_id: http://sametmax.com/?p=12969
title: Présentation de WAMP.ws, round 2 39
uri: Présentation-de-WAMP-ws-round-2-Recently-updated
url: http://sametmax.com/presentation-de-wamp-round-2/
content:
<p>Dans le cadre de <a href="http://sametmax.com/full-disclosure/">mon travail sur WAMP</a>, j&#8217;ai proposé à Tobias de commencer par une présentation générale de la stack techno sous forme de slide show.</p>
<p>L&#8217;idée est de mettre ça dans le header des sites de WAMP, crossbar.io et autobahn, afin que quand les gens arrivent dessus ils puissent rapidement voir de quoi on parle. Ou alors, si on est sur un forum, on peut linker vers les diapos pour donner un contexte.</p>
<p><iframe src="https://www.slideshare.net/slideshow/embed_code/42901476" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe>
<div style="margin-bottom:5px"> <strong> <a href="https://www.slideshare.net/sametmax/introduction-wampws-le-protocole-websocket-pour-faire-du-pubsub-et-rpc-over-websocket-en-tempr" title="Présentation de WAMP.ws, le protocole pour faire du PUB/SUB et RPC over Websocket" target="_blank">Présentation de WAMP.ws, le protocole pour faire du PUB/SUB et RPC over Websocket</a> </strong> from <strong><a href="http://www.slideshare.net/sametmax" target="_blank">sametmax</a></strong> </div>
<p>Comme prévu, je fais une première version en français que je poste ici. Puis je vais récolter vos commentaires : qu&#8217;est-ce qu&#8217;on comprend pas, quelles informations manquent, qu&#8217;est-ce qui est flou, ambigüe, etc.</p>
<p>Ensuite je l&#8217;améliorerai lors de la traduction en anglais qui sera ensuite proposée à Tavendo.</p>


feed_id: http://sametmax.com/?p=12948
title: Message de service aux débutants en Python 24 Recently updated !
uri: Message-de-service-aux-débutants-en-Python-Recently-updated
url: http://sametmax.com/message-de-service-aux-debutants-en-python/
content:
<p>Ces informations sont éparpillées sur le net, et même sur le blog. Mais c&#8217;est un peu le package que tout dev Python qui se lance doit apprendre petit à petit. Alors je vais vous épargner les recherches.</p>
<p>Ne prenez pas ça comme une checklist qu&#8217;il faut impérativement faire avant de programmer. Coder est le plus important pour apprendre. Tout le reste est facultatif. Mais cet article liste des raccourcis qui vous seront utiles au fur et à mesure de votre progression.</p>
<h2>Réponse aux grandes questions de la vie</h2>
<h3>J&#8217;installe Python avec quoi ?</h3>
<p>Sous Linux, avec votre gestionnaire de paquet. Mais souvenez-vous que la 2.7 est installée par défaut.</p>
<p>Sous Mac, avec <a href="http://brew.sh/">homebrew</a>. Mais souvenez-vous que la 2.7 est installée par défaut. Vous aurez besoin de GCC. Mais pas besoin de télécharger xcode pour ça, il y a des <a href="https://github.com/kennethreitz/osx-gcc-installer">solutions légères</a>.</p>
<p>Sous Windows, utilisez <a href="http://conda.pydata.org/miniconda.html">miniconda</a>. L&#8217;installeur officiel est pas mal, mais miniconda vous aidera beaucoup pour plein de choses, comme installer facilement les extensions compilées type scipy ou QT. Et cochez toujours l&#8217;option pour ajouter Python au SYSTEM PATH, sinon il faudra <a href="http://sametmax.com/ajouter-un-chemin-a-la-variable-denvironnement-path-sous-windows/">le faire à la main</a> et c&#8217;est relou.</p>
<h3>Python 2 or Python 3 ?</h3>
<p>Python 3 sauf si :</p>
<ul>
<li>Vous êtes certain de devoir utiliser une lib en rouge dans <a href="https://python3wos.appspot.com/">cette liste</a>.</li>
<li>Vous êtes sur Mac ou Linux, et vous avez pas envie de vous faire chier à installer Python 3 alors que Python 2.7 est déjà là par défaut.</li>
<li>Vous n&#8217;avez pas accès à Python 3.3 ou 3.4. Les premières versions de Python 3 sont horribles.</li>
</ul>
<p>Dans tous les cas, souvenez-vous :</p>
<ul>
<li>Qu&#8217;on peut installer plusieurs versions en même temps.</li>
<li>Que passer de l&#8217;un à l&#8217;autre n&#8217;est pas difficile. On peut même écrire du code compatible avec les deux si besoin même si c&#8217;est un peu chiant.</li>
<li>La commande <code>py</code> permet de choisir quel Python lancer sous Windows (<code>py -2 </code>ou <code>py -3</code>). Sous linux, on peut carrément faire <code>python2</code> ou <code>python3</code>, ou <code>python3.4</code>.</li>
<li>Les environnement virtuels peuvent utiliser une version de Python en particulier avec <code>-p.</code></li>
</ul>
<h3>Mais c&#8217;est quoi cette histoire de CPython, Pypy, IronPython, Jython, Julia, Cython, Nuitka, Hope&#8230;</h3>
<p>Y a combien de Python bordel ?</p>
<p>Pour vous, un seul : CPython. C&#8217;est-à-dire ce que les gens appellent &#8220;Python&#8221;.</p>
<p>Vous pouvez ignorer le reste. Vous n&#8217;avez pas à vous inquiéter de devoir utiliser un autre un jour, devoir passer à un autre, etc. Ce sont juste des bonus qui peuvent aider des gens dans des cas particuliers, rien d&#8217;indispensable.</p>
<h3>Pip ou easy_install</h3>
<p>pip. <a href="http://sametmax.com/votre-python-aime-les-pip/">Installez toujours pip</a>. Utilisez toujours pip. Apprenez à bien utiliser pip avec toutes ses options.</p>
<p>Et souvenez-vous qu&#8217;on peut installer un module pour une version de python en particulier en faisant <code>pythonX -m pip</code> ou sous windows, <code>py -x -m pip</code>.</p>
<p>Une exception pour les extensions :</p>
<p>Si vous êtes sous Windows, installer <strong>en plus</strong> miniconda va vous simplifier énormément la vie pour installer les extensions compilées comme scipy.</p>
<p>Et si vous êtes sous Linux utilisez votre gestionnaire de paquet sans quoi vous allez devoir installer gcc et les headers de Python (package python-dev sous Ubuntu par exemple).</p>
<h3>distutils, setuptools ou distribute ?</h3>
<p>Setuptools. Le reste a été fusionné ou déprécié.</p>
<h3>Python 32 bits ou python 64 bits ?</h3>
<p>64 bits. Si vous avez un jour une erreur indébuggable sous windows, testez avec une version 32 bits au cas où. Mais 64 bits reste le choix par défaut.</p>
<h3>Quel IDE ?</h3>
<p>Aucun IDE n&#8217;est nécessaire en Python. On peut coder avec un simple éditeur de texte et la console. Je fais toutes mes formations avec Notepad++ sous Windows, ou Gedit sous Ubuntu.</p>
<p>Vous pouvez donc juste utiliser ce que vous aimez le plus.</p>
<h3>Pour UI, PyQt, PySide, wxPython, Kivy, PyGTK, Tkinter ?</h3>
<p><a href="https://docs.python.org/2/library/tkinter.html">Tkinter</a> si c&#8217;est une UI simple (quelques fenêtres, quelques formulaires). <a href="http://wxpython.org/">WxPython</a> si c&#8217;est un programme complexe en Python 2.7. C&#8217;est le meilleur équilibre poids/puissance. <a href="http://kivy.org/">Kivy</a> si ça doit tourner sur mobile.</p>
<p><a href="http://www.riverbankcomputing.co.uk/software/pyqt/intro">PyQt</a>/<a href="http://qt-project.org/wiki/PySide">PySide</a> sont les plus puissants, mais beaucoup plus dur à utiliser. Ca vaut rarement le coup, sauf que pour le moment, c&#8217;est la seule solution solide en Python 3.</p>
<h2>Les outils qui changent la vie</h2>
<p>On peut coder avec Python sans tout ça, mais la vie est plus belle avec.</p>
<ul>
<li>pip permet d&#8217;installer facilement plein de libs.</li>
<li><a href="http://ipython.org/">ipython</a>, un shell Python qui facilite l&#8217;expérimentation de code.</li>
<li><a href="http://sametmax.com/debugger-en-python-les-bases-de-pdb/">pdb</a> permet de débugger votre programme. <a href="https://pypi.python.org/pypi/pdbpp/">pdb++</a> en bonus.</li>
<li><a href="http://sametmax.com/les-environnement-virtuels-python-virtualenv-et-virtualenvwrapper/">virtualenv</a> vous permet d&#8217;avoir des installations de Python différentes pour chaque projet avec des libs isolées. Avec <a href="http://sametmax.com/mieux-que-python-virtualenvwrapper-pew/">pew</a> en bonus.</li>
<li><a href="http://sametmax.com/grin-le-grep-python-sous-steroid/">grin</a>, pour rechercher un mot dans votre code. Mieux que grep et marche sous Windows.</li>
<li><a href="http://sametmax.com/remplacer-sed-awk-cut-et-perl-par-python-orgasme-pour-sysadmin/">pyped</a>, pour remplacer sed, cut, awk et bien plus par du python simple, y compris sous Windows</li>
</ul>
<p>Si vous êtes sous windows, souvenez-vous que <kbd>Shift</kbd> avant un clic droit ajoute des options supplémentaires au menu contextuel de votre explorateur de fichiers. Avec notamment &#8220;Ouvrir une invite de commande dans ce dossier&#8221;. Sous Mac il y a un <a href="http://hdrapin.com/2013/02/17/mac-comment-ouvrir-le-dossier-selectionne-dans-le-terminal/">réglage</a> pour ça. <a href="http://www.distrogeeks.com/open-terminal-here-ubuntu/">Sous Ubuntu il y a un plugin</a>.</p>
<p>Ah oui, et sous windows, utilisez <a href="https://github.com/cbucher/console/wiki/Downloads">une console décente</a>.</p>
<h2>Bonnes habitudes</h2>
<p>Réglez votre éditeur de texte pour utiliser 4 espaces pour indenter. Si vous préférez les tabs, réglez aussi votre éditeur de texte pour utiliser 4 espaces pour indenter.</p>
<p>Tant qu&#8217;on y est, <a href="http://sametmax.com/lencoding-en-python-une-bonne-fois-pour-toute/">apprenez à gérer votre encoding</a>. Particulièrement, assurez-vous de savoir où changer l&#8217;encoding des caractères de vos fichiers dans les options de votre éditeur de texte. Et mettez le par défaut sur UTF8. Utilisez toujours des chaînes de caractères unicode et le header <code># -*- coding: utf-8 -*-</code>.</p>
<p>Utilisez <code>print</code> avec la syntaxe sous forme de fonction. Et faites des imports absolus, jamais relatifs.</p>
<p>En fait, si vous êtes en Python 2.7, activez le plus de comportement de Python 3 possible en faisant les imports de <code>__future__</code>.</p>
<p>Pour un débutant, voici donc un bon template de fichier Python 2.7 par défaut :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;
    Documenter le module ici.
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">__future__</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: black;">&#40;</span>unicode_literals<span style="color: #66cc66;">,</span> absolute_import<span style="color: #66cc66;">,</span>
                        print_function<span style="color: #66cc66;">,</span> division<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Run the whole program &quot;&quot;&quot;</span>
    <span style="color: #808080; font-style: italic;"># votre code ici</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Hello !'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">'__main__'</span>:
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<ul>
<li><strong>unicode_literals</strong> : active les chaînes unicode par défaut.</li>
<li><strong>absolute_import</strong> : active les imports absolus par défaut.</li>
<li><strong>print_function</strong> : remplace le mot clé <strong>print</strong> par la fonction <strong>print()</strong>.</li>
<li><strong>division</strong> : <code>/</code> devient la division classique, <code>//</code> la division entière.</li>
</ul>
<p>Pour Python 3, c&#8217;est plus simple :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;
    Documenter le module ici.
&quot;&quot;&quot;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Run the whole program &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Hello !'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">'__main__'</span>:
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Utilisez toujours des dates en UTC. Ne convertissez qu&#8217;à l&#8217;affichage. Donc ça veut dire utiliser <code>datetime.utcnow()</code> et non <code>datetime.now()</code></p>
<h2>Des libs qu&#8217;on les aime</h2>
<p>Les modules disponibles avec Python sont ce qu&#8217;on appelle la bibliothèque standard, ou stdlib. Il y a beaucoup de modules <a href="http://sametmax.com/tres-grand-listing-des-libs-standard-partie-les-plus-utiles-en-python/">très utiles</a>.</p>
<p>Néanmoins certains doivent avoir la priorité dans votre apprentissage. Les plus importants sont :</p>
<ul>
<li><a href="https://docs.python.org/2/library/os.html?highlight=os#module-os">os</a>, <a href="https://docs.python.org/2/library/shutil.html?highlight=shutils">shutil</a>, <a href="https://docs.python.org/2/library/subprocess.html?highlight=subprocess">subprocess</a> et <a href="https://docs.python.org/2/library/sys.html?highlight=sys#module-sys">sys</a> : manipuler votre OS, des fichiers aux processus.</li>
<li><a href="https://docs.python.org/2/library/datetime.html?highlight=datetime#module-datetime">datetime</a> : manipuler les dates.</li>
<li><a href="https://docs.python.org/2/library/math.html?highlight=math#module-math">math</a> et <a href="https://docs.python.org/2/library/decimal.html?highlight=decimal#module-decimal">decimal</a> : ben, les maths.</li>
<li><a href="https://docs.python.org/2/library/collections.html?highlight=collection#module-collections">collections</a> : des structures de données avancées.</li>
<li><a href="https://docs.python.org/2/library/decimal.html?highlight=decimal#module-decimal">argparse</a> : faire un script avec des paramètres.</li>
<li><a href="https://docs.python.org/2/library/urllib2.html?highlight=urllib#module-urllib2">urllib2</a> : faire des requêtes HTTP.</li>
<li><a href="https://docs.python.org/2/library/itertools.html?highlight=itertools#module-itertools">itertools</a> : l&#8217;itération est tout en Python.</li>
</ul>
<p>Quelques modules sont vieux, et ça se sent dans leur facilité d&#8217;usage. Pour cette raison, si vous utilisez beaucoup certains d&#8217;entre eux, des alternatives installables avec pip peuvent vous simplifier <strong>énormément</strong> la vie :</p>
<table class="tableizer-table">
<tbody>
<tr>
<td>Stdlib</td>
<td>Lib tierce partie plus pratique&gt;</td>
</tr>
<tr class="tableizer-firstrow">
<td>datetime</td>
<td><a href="http://sametmax.com/les-time-zones-en-python/">arrow</a></td>
</tr>
<tr>
<td>os, sys, shutil</td>
<td><a href="http://sametmax.com/path-py-plus-en-detail/">path.py</a></td>
</tr>
<tr>
<td>argparse</td>
<td><a href="http://sametmax.com/la-plus-belle-maniere-de-parser-les-arguments-de-script-en-python/">docopt</a></td>
</tr>
<tr>
<td>unittest</td>
<td><a href="http://sametmax.com/se-simplifier-les-tests-python-avec-pytest/">pytest</a>. En fait ne faites jamais de <a href="http://sametmax.com/un-gros-guide-bien-gras-sur-les-tests-unitaires-en-python-partie-1/">tests unitaires</a> sans pytest. La vie est trop courte.</td>
</tr>
<tr>
<td>urllib2</td>
<td><a href="http://docs.python-requests.org/en/latest/">requests</a></td>
</tr>
</tbody>
</table>
<h2>Y a des priorités dans la vie</h2>
<p>Les trucs importants à apprendre en Python (qui sont typiques de ce langage, j&#8217;entends) avant de se lancer dans la sophistication :</p>
<ul>
<li>Toutes les choses ont une valeur booléenne. Savoir en tirer parti.</li>
<li>Connaitre toutes les méthodes des strings.</li>
<li>Les exceptions : try, except, else, finally, raise.</li>
<li>Maitriser le slicing et l&#8217;unpacking.</li>
<li><a href="http://sametmax.com/operateur-splat-ou-etoile-en-python/">L&#8217;opérateur splat</a>.</li>
<li>Manipuler des fichiers.</li>
<li>Les dictionnaires et les sets. Vous les sous-utilisez. Étudiez-les.</li>
<li>Bien maitriser l&#8217;itération : for, else, continue, break.</li>
<li>Bien maitriser l&#8217;itération (bis) : zip, enumerate, sorted, reversed, any, all&#8230;</li>
<li>Bien maitriser l&#8217;itération (ter) : <a href="http://sametmax.com/python-love-les-listes-en-intention-partie/">les listes en intension</a>.</li>
<li>Bien maitriser l&#8217;itération (vous-ai je dit que c&#8217;était tout en Python ?) : <a href="http://sametmax.com/comment-utiliser-yield-et-les-generateurs-en-python/">les générateurs</a>.</li>
<li>Les regex. C&#8217;est chiant. Je sais. Mais c&#8217;est trop puissant pour être ignoré.</li>
</ul>
<p>Avec ça vous pouvez aborder sereinement tout problème. Le reste, c&#8217;est du bonus.</p>
<p>Typiquement, on peut repousser à bien plus tard l&#8217;apprentissage de :</p>
<ul>
<li><a href="http://sametmax.com/fonctions-anonymes-en-python-ou-lambda/">Les lambdas</a>.</li>
<li><a href="http://sametmax.com/comprendre-les-decorateurs-python-pas-a-pas-partie-1/">Decorateurs</a>.</li>
<li>Les <a href="http://sametmax.com/les-context-managers-et-le-mot-cle-with-en-python/">context managers</a>.</li>
<li>L&#8217;introspection.</li>
<li><a href="http://sametmax.com/le-guide-ultime-et-definitif-sur-la-programmation-orientee-objet-en-python-a-lusage-des-debutants-qui-sont-rassures-par-les-textes-detailles-qui-prennent-le-temps-de-tout-expliquer-partie-1/">La programmation orientée objet</a>.</li>
<li>Metaclasses.</li>
</ul>


feed_id: http://sametmax.com/?p=12939
title: Mieux que Python virtualenvwrapper : pew 8 Recently updated !
uri: Mieux-que-Python-virtualenvwrapper-pew-Recently-updated
url: http://sametmax.com/mieux-que-python-virtualenvwrapper-pew/
content:
<p>Vous avez compris que Python sans <a href="http://sametmax.com/les-environnement-virtuels-python-virtualenv-et-virtualenvwrapper/">virtualenv</a> c&#8217;est comme la mer sans les vagues, c&#8217;est comme les vagues sans l&#8217;écume, c&#8217;est comme l&#8217;écume sans le sel, c&#8217;est comme le sel sans le poivre&#8230;</p>
<p>Mais c&#8217;est aussi appétissant que les méduses échouées.</p>
<p>Donc pour se faciliter la vie, vous utilisez virtualenvwrapper.</p>
<p>Et bien il y a plus meilleur : <a href="https://github.com/berdario/pew#usage">pew</a>.</p>
<p>Non content d&#8217;avoir un nom cool et court, c&#8217;est un progrès non négligeable dans l&#8217;ergonomie de notre vie de dresseur de reptiles.</p>
<p>D&#8217;abord : <code><a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a> install pew</code>.</p>
<p>Ensuite, tableau d&#8217;équivalence avec virtualenvwrapper :</p>
<table class="tableizer-table">
<tbody>
<tr class="tableizer-firstrow">
<th></th>
<th>virtualenvwrapper</th>
<th>pew</th>
</tr>
<tr>
<td>Lister les env existant</td>
<td>workon</td>
<td>pew ls</td>
</tr>
<tr>
<td>Créer un env</td>
<td>mkvirtualenv name</td>
<td>pew new name</td>
</tr>
<tr>
<td>Supprimer un env</td>
<td>rmvirtualenv name</td>
<td>pew rm name</td>
</tr>
<tr>
<td>Activer un env</td>
<td>workon name</td>
<td>pew workon name</td>
</tr>
<tr>
<td>Aller dans le dossier site-packages</td>
<td>cdsitepackages</td>
<td>cd $(pew sitepackages_dir)</td>
</tr>
<tr>
<td>Valeur par défaut pour $WORKON_HOME (dossier qui contient tous les envs)</td>
<td>~/.virtualenvs</td>
<td>~/local/share/virtualenvs</td>
</tr>
</tbody>
</table>
<p>Vous noterez que les commandes de pew sont plus faciles à retenir, plus cohérentes, et toutes des sous-commandes histoire d&#8217;éviter de pourrir son espace de nom.</p>
<p>Autres avantages : pew n&#8217;a pas besoin qu&#8217;on ajoute un fichier à votre <code>.bashrc</code> pour marcher. Car pew ne source pas un env dans votre shell courant, il ouvre un nouveau shell. Pour sortir de l&#8217;env, c&#8217;est donc un simple <kbd>Ctrl</kbd> + <kbd>D</kbd>.</p>
<p>Seulement ça ne s&#8217;arrête pas là. Pew possède quelques commandes bonus qui changent bien la vie :</p>
<table class="tableizer-table">
<tbody>
<tr class="tableizer-firstrow">
<th></th>
<th>virtualenvwrapper</th>
<th>pew</th>
</tr>
<tr>
<td>Éxecuter la commande dans un env sans l&#8217;activer</td>
<td>Nope</td>
<td>pew in name commande</td>
</tr>
<tr>
<td>Éxecuter la commande dans tous les env</td>
<td>Non</td>
<td>pew inall commande</td>
</tr>
<tr>
<td>Dupliquer un virtualenv ailleurs</td>
<td>Nada</td>
<td>pew cp name destination</td>
</tr>
<tr>
<td>Ajouter un chemin au PYTHONPATH de l&#8217;env</td>
<td>Fuck it</td>
<td>pew add path</td>
</tr>
<tr>
<td>Changer la prise en compte des libs du site-packages du système quand on veut</td>
<td>I&#8217;m out</td>
<td>pew toggleglobalsitepackages</td>
</tr>
<tr>
<td>Créer un env temporaire supprimé dès qu&#8217;on en sort</td>
<td>Now you are just pushing it</td>
<td>pew mktmpenv</td>
</tr>
<tr>
<td>Choisir un dossier vers lequel aller à l&#8217;activation de l&#8217;env</td>
<td>BANG !</td>
<td>pew setproject path</td>
</tr>
</tbody>
</table>
<p>Bon, le seul truc qui manque pour le moment, ce sont les hooks.</p>


feed_id: http://sametmax.com/?p=12923
title: Petit à petit, on reconstruit Recently updated !
uri: Petit-à-petit-on-reconstruit-Recently-updated
url: http://sametmax.com/petit-a-petit-on-reconstruit/
content:
<p>Certains l&#8217;auront noté, les tampons sont de retour.</p>
<p>J&#8217;ai aussi, à la demande d&#8217;un lecteur, ajouté un plugin pour permettre aux commentaires d&#8217;être écrits en markdown (avec les extensions de github).</p>
<p>Pour obtenir la parité avec le précédent blog, il nous faudra donc restaurer encore quelques easter eggs et améliorer les images sur la page d&#8217;accueil, mais c&#8217;est presque fini. Comme quoi, une migration, c&#8217;est long. Et chiant. Et ingrat.</p>


feed_id: http://sametmax.com/?p=12902
title: Travailler à deux sur iPython à distance
uri: Travailler-à-deux-sur-iPython-à-distance
url: http://sametmax.com/travailler-a-deux-sur-ipython-a-distance/
content:
<p>Bon, j&#8217;ai pas fini mon slideshow sur WAMP, donc je vais faire un article sur ça.</p>
<p><a href="http://sametmax.com/profiter-du-notebook-de-ipython/">iPython notebook</a>, c&#8217;est pratique, mais une seule personne peut coder à la fois. Si quelqu&#8217;un veut voir les changements, il faut recharger avec F5. A l&#8217;heure des Google Doc temps réel, c&#8217;est con. Surtout que c&#8217;est du ZMQ derrière.</p>
<p>Du coup je me suis lancé dans une expérimentation avec <a href="https://togetherjs.com/docs/">TogetherJS</a>, la lib de Momo pour le travail collaboratif.</p>
<p>Pour lancer le truc, il suffit d&#8217;aller dans son dossier de profile iPython et éditer le fichier Javascript vierge fait pour étendre l&#8217;outil. Par exemple, sous Ubuntu, mon profile par défaut est dans <code>~/ipython/profile_default</code> et le fichier à éditer est <code>./profile_default/static/custom/custom.js</code>.</p>
<p>Dedans on met :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">TogetherJSConfig_autoStart <span style="color: #66cc66;">=</span> true<span style="color: #66cc66;">;</span>
TogetherJSConfig_cloneClicks <span style="color: #66cc66;">=</span> false<span style="color: #66cc66;">;</span>
TogetherJSConfig_dontShowClicks <span style="color: #66cc66;">=</span> true<span style="color: #66cc66;">;</span>
$.<span style="color: black;">getScript</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'https://togetherjs.com/togetherjs-min.js'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">;</span></pre></td></tr></table></div>

<p>Et on est bon. Il faut ouvrir deux browsers différents pour bien tester le truc, par exemple un chrominou et un firefoune. Moi j&#8217;ai ouvert deux FF parce que j&#8217;ai pleins de profiles dessus.</p>
<p>La frappe est bien synchro, mais malheureusement pas l&#8217;affichage du résultat. Y a donc bien un truc intéressant à creuser, mais pour le moment, c&#8217;est pas utilisable.</p>
<p>Ensuite, il y a des services Web. <a href="https://cloud.sagemath.com/">SageMathCloud</a> annonce faire cela, mais impossible de s&#8217;inscrire, le formulaire ne marche pas. <ahref="https://www.codebox.io">Codebox</ahref=> propose un env complet de dev en ligne, mais l&#8217;inscription est temporairement suspendue. <a href="http://codebunk.com">Codebunk</a> marche pas mal, est plutôt bien foutu et clair, mais Python 2.7 uniquement, et aucun moyen d&#8217;installer une lib, donc adieu scipy ou matplotlib.</p>
<p>Celui qui s&#8217;en rapproche le plus est <a href="https://www.pythonanywhere.com">Pythonanywhere</a> : des consoles synchronisées pour toutes les versions de Python, beaucoup de libs préinstallées (dont scipy et matplotlib), un vrai système de fichier sur lequel travailler, du pip a dispo. Et en prime un éditeur de texte pour des fichiers complets, mais qui lui, n&#8217;est pas collaboratif. Damn it. Et impossible d&#8217;afficher en ligne une image pondue via matplotlib. En plus, on a pas le concept des cellules d&#8217;iPython, qui est super pratique.</p>
<p>Bref, il manque vraiment un outil pour faire ce genre de choses.</p>


feed_id: http://sametmax.com/?p=12883
title: Full disclosure Recently updated !
uri: Full-disclosure-Recently-updated
url: http://sametmax.com/full-disclosure/
content:
<p>Depuis quelques jours je suis en discussion avec Tobias de Tavendo. Comme vous avez pu le remarquer avec mes précédents articles sur <a href="http://sametmax.com/crossbar-le-futur-des-applications-web-python/">WAMP</a> et <a href="http://sametmax.com/le-potentiel-de-wamp-autobahn-et-crossbar-io/">Crossbar</a> :</p>
<ul>
<li>Ils sont bons techniquement, et nuls pour expliquer ce qu&#8217;ils ont techniqué.</li>
<li>Cette techno est une techno de rêve pour moi. J&#8217;y crois à mort.</li>
<li>Je suis le seul à avoir pondu des explications décentes sur WAMP et Crossbar. Et ça n&#8217;a pas suffit à faire battre un cil.</li>
</ul>
<p>Bref, ils ont embauché des mecs de haute voltige pour la technique (du genre un contributeur PyPy). Et ils m&#8217;ont contacté pour me demander si je n&#8217;étais pas chaud pour faire de l&#8217;évangélisme, rémunéré, autour de WAMP, Autobahn et Crossbar.</p>
<p>L&#8217;idée : écrire des tutos, des articles, améliorer la doc, répondre sur le chan IRC, etc.</p>
<p>J&#8217;adore le concept, vu que j&#8217;aime leur projet et que je le faisais gratos avant, surtout qu&#8217;ils sont pas trop contraignants sur le temps que je vais passer dessus.</p>
<p>Donc voilà le deal : quand je vais pondre des tutos et des articles sur WAMP et Co, je vais d&#8217;abord les faire en français ici. Comme ça j&#8217;aurai les retours des lecteurs du blog qui pourront, comme d&#8217;habitude, me faire part de leurs douces remarques sur à quel point on ne pige rien.</p>
<p>Une fois la prose aiguisée, je traduis et je publie chez Tavendo.</p>
<p>Je disclose donc ici que vous verrez peut-être des prochaines rédactions qui seront attachées à une activité pro. Pas impartial donc. Mais bon, depuis quand je suis impartial ? Javascript c&#8217;est de la merde, et je préfère les rousses.</p>
<p>Par saucisse d&#8217;honnêteté, je signalerai chaque choucroute concernée avec un lien vers ce post.</p>
<p>Enfin, le contrat est pas signé encore, mais vu que je vais commencer à taffer dessus aujourd&#8217;hui, je pense à une première publication demain sous la forme d&#8217;un slide show expliquant avec de jolies diapos ce que sont WAMP, Autobahn et Crossbar. À quoi ça sert et ce qu&#8217;on peut faire avec.</p>


feed_id: http://sametmax.com/?p=13004
title: Les trucmuchables en Python 9 Recently updated !
uri: Les-trucmuchables-en-Python-Recently-updated
url: http://sametmax.com/les-trucmuchables-en-python/
content:
<p>Parcourez votre itérable, passez un callable, retournez un indexable&#8230;</p>
<p>En Python on aime le duck typing. On ne va donc pas s&#8217;intéresser à un type, mais à un comportement.</p>
<p>Quand vous voyez un suffixe &#8220;-able&#8221; en anglais, ça veut dire &#8220;accepte qu&#8217;on lui fasse quelque chose&#8221;. Par exemple, &#8220;fuckable&#8221; = &#8220;baisable&#8221;.</p>
<p>Sur ce morceau de poésie, je vous offre un peu de Vivaldi pour faire glisser profondément ce gros article qui va lister les chosables les plus connus.</p>
<p><span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='1170' height='689' src='http://www.youtube.com/embed/watQ28Fx2Mg?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0' allowfullscreen='true'></iframe></span></p>
<h2>Iterable</h2>
<p>Le plus important en Python.</p>
<p>Un itérable est ce qui accepte l&#8217;itération, ce sur quoi on peut itérer, c&#8217;est à dire une collection dont on peut prendre les éléments un à un.</p>
<p>Pour faire simple, <strong>tout ce sur quoi on peut appliquer une boucle <code>for</code></strong>.</p>
<p>L&#8217;exemple le plus connu sont les listes :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'une'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'liste'</span><span style="color: black;">&#93;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
une
liste</pre></td></tr></table></div>

<p>Mais cela s&#8217;applique à bien d&#8217;autres types :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #483d8b;">'unechaine'</span>:
...     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
...
<span style="color: black;">u</span>
n
e
c
h
a
i
n
e
<span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'un'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'tuple'</span><span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
...
<span style="color: black;">un</span>
<span style="color: #008000;">tuple</span>
<span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#123;</span><span style="color: #483d8b;">'un'</span>: <span style="color: #483d8b;">'dico'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'par'</span>: <span style="color: #483d8b;">'cle'</span><span style="color: black;">&#125;</span>:
...     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
...
<span style="color: black;">un</span>
par
<span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'un'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'set'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
...
<span style="color: black;">un</span>
<span style="color: #008000;">set</span>
<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;">'/tmp/test'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'w'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> f:
    f.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'un<span style="color: #000099; font-weight: bold;">\n</span>fichier'</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;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/test'</span><span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>x<span style="color: #66cc66;">,</span> end<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: black;">&#41;</span>
...
<span style="color: black;">un</span>
fichier</pre></td></tr></table></div>

<p>Les tuples, dicos, sets, fichiers, et strings sont itérables. Beaucoup de structures de données du module <a href="http://sametmax.com/ce-que-vous-ne-saviez-pas-sur-les-collections-en-python/">collections</a> (<code>deque</code>, <code>namedtupple</code>, <code>defaultdict</code>) sont itérables.</p>
<p>Mais surtout, les générateurs sont itérables :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> generator<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #ff4500;">1</span>
    <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #ff4500;">2</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> generator<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">1</span>
<span style="color: #ff4500;">2</span></pre></td></tr></table></div>

<p>Pour vérifier si quelque chose est itérable, on peut utiliser la fonction <code>iter()</code>. Cette fonction prend un iteérable, et retourne un générateur (appelé &#8220;iterator&#8221;) qui permet d&#8217;énumérer chaque élément de l&#8217;iterable :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">lst <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'ceci'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'est'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'aussi'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'une'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'liste'</span><span style="color: black;">&#93;</span>
generateur <span style="color: #66cc66;">=</span> <span style="color: #008000;">iter</span><span style="color: black;">&#40;</span>lst<span style="color: black;">&#41;</span>
next<span style="color: black;">&#40;</span>generateur<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'ceci'</span>
next<span style="color: black;">&#40;</span>generateur<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'est'</span>
next<span style="color: black;">&#40;</span>generateur<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'aussi'</span>
next<span style="color: black;">&#40;</span>generateur<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'une'</span></pre></td></tr></table></div>

<p><code>iter()</code> lève <code>TypeError</code> sur un non iterable :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #008000;">iter</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</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;&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> 
    <span style="color: #008000;">iter</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">TypeError</span>: <span style="color: #483d8b;">'int'</span> <span style="color: #008000;">object</span> <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #ff7700;font-weight:bold;">not</span> iterable</pre></td></tr></table></div>

<p>Pour la culture, c&#8217;est ainsi que la boucle <code>for</code> fonctionne : à coup de <code>next()</code> sur un itérateur.</p>
<p>On peut rendre n&#8217;importe quelle objet itérable en définissant la méthode <code>__iter__</code>, qui doit retourner un générateur :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> NouvelIterable:
    <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: #808080; font-style: italic;"># mettre des yield marche aussi</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">iter</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><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> NouvelIterable<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">1</span>
<span style="color: #ff4500;">2</span>
<span style="color: #ff4500;">3</span></pre></td></tr></table></div>

<p>Les itérables sont les bidulables les plus important en Python car de très nombreuses fonctions les acceptent :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #008000;">list</span><span style="color: black;">&#40;</span><span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'AZERTY'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># tri</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'A'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'E'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'R'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'T'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Y'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Z'</span><span style="color: black;">&#93;</span>
<span style="color: #008000;">list</span><span style="color: black;">&#40;</span><span style="color: #008000;">reversed</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'AZERTY'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># inversion</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'Y'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'T'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'R'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'E'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Z'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'A'</span><span style="color: black;">&#93;</span>
<span style="color: #008000;">list</span><span style="color: black;">&#40;</span><span style="color: #008000;">zip</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'AZERTY'</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #ff4500;">100</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">300</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">600</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># lier deux itérables</span>
<span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'A'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Z'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">300</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'E'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">600</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
<span style="color: #008000;">any</span><span style="color: black;">&#40;</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: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># un élément au moins est vrai ?</span>
<span style="color: #008000;">True</span>
<span style="color: #008000;">all</span><span style="color: black;">&#40;</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: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># tous les éléments sont vrais ?</span>
<span style="color: black;">&#41;</span>
<span style="color: #008000;">False</span></pre></td></tr></table></div>

<p>Et elles retournent souvent des itérables également :)</p>
<p>La plupart des itérables sont compatibles entre eux. Y compris les générateurs. Qui souvent traitent eux même des itérables et retournent des itérables. Cela permet de faire d&#8217;énormes pipelines de traitements connectés les uns aux autres :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">s <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'123456789'</span>
res <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #008000;">int</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> s<span style="color: black;">&#41;</span>
<span style="color: #008000;">tuple</span><span style="color: black;">&#40;</span><span style="color: #008000;">reversed</span><span style="color: black;">&#40;</span><span style="color: #008000;">list</span><span style="color: black;">&#40;</span>res<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span>:<span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span>
<span style="color: black;">&#40;</span><span style="color: #483d8b;">'999999999'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'88888888'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'7777777'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'666666'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<h2>Mutable</h2>
<p>Dont on peut changer la valeur.</p>
<p>Quand on assigne une variable en Python, on ne change pas la valeur de l&#8217;objet, on change la valeur de la variable :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">a <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span>
a <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">2</span></pre></td></tr></table></div>

<p>Ici <code>1</code> n&#8217;a pas changé, la valeur stockée dans <code>a</code> a changé.</p>
<p>C&#8217;est différent de ceci :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">a <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
a<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;">2</span>
a
<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Ici, c&#8217;est la même liste qui est dans <code>a</code>, mais la valeur stockée dans la liste a changé.</p>
<p>Cette notion est importante car en Python, les variables ne contiennent en fait pas vraiment des valeurs, mais des références à ces valeurs.</p>
<p>Si je change le contenu de la variable, il n&#8217;y a pas d&#8217;effet de bords :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">a <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span>
b <span style="color: #66cc66;">=</span> a <span style="color: #808080; font-style: italic;"># b et a contienne une référence à la même liste</span>
b
<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span>
a <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: #ff4500;">4</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">5</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">6</span><span style="color: black;">&#93;</span> <span style="color: #808080; font-style: italic;"># le contenu de a change</span>
b
<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span> <span style="color: #808080; font-style: italic;"># b et a ont une contenu différents</span></pre></td></tr></table></div>

<p>Si je change la valeur de ma structure de données, ici ma liste, alors il y a un effet de bord :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">a <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span>
b <span style="color: #66cc66;">=</span> a
a<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;">1000</span>
b <span style="color: #808080; font-style: italic;"># a et b référencent la même liste</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">1000</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>En effet, <code>a</code> ne contient pas la liste, mais une référence à la liste. Quand on copie le contenu de <code>a</code> vers <code>b</code>, on ne copie pas la liste, mais cette référence. Donc <code>a</code> et <code>b</code> sont des variables qui pointent vers <strong>la même liste</strong>.</p>
<p>Il est alors important de savoir quelles opérations modifient quelque chose, et lesquelles ne les modifient pas.</p>
<p>Les listes, les dictionnaires et les sets sont modifiables, on dit qu&#8217;il sont &#8220;mutables&#8221;.</p>
<p>On peut le voir avec la fonction <code>id()</code> qui renvoie le numéro unique de l&#8217;objet :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">une_liste <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
<span style="color: #008000;">id</span><span style="color: black;">&#40;</span>une_liste<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">140693805855368</span>
une_liste.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
une_liste
<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
<span style="color: #008000;">id</span><span style="color: black;">&#40;</span>une_liste<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">140693805855368</span></pre></td></tr></table></div>

<p>La liste a changé, mais l&#8217;id est le même, c&#8217;est le même objet.</p>
<p>Les opérations qui &#8220;changent la valeur&#8221; sur les types mutables sont performantes en Python car il n&#8217;y a pas besoin de recréer un objet à chaque fois.</p>
<p>Les tuples, les nombres, les chaînes de caractères ne sont pas modifiables. Il ne sont pas &#8220;mutables&#8221; :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #008000;">id</span><span style="color: black;">&#40;</span>une_liste<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">140693805855368</span>
un_tuple <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">id</span><span style="color: black;">&#40;</span>un_tuple<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">140693772746040</span>
un_tuple +<span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">5</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">6</span><span style="color: black;">&#41;</span>
un_tuple
<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">4</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">5</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">6</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">id</span><span style="color: black;">&#40;</span>un_tuple<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">140693772879144</span></pre></td></tr></table></div>

<p>Le tuple n&#8217;a pas changé : l&#8217;id n&#8217;est pas le même car la variable <code>un_tuple</code> contient un nouvel objet.</p>
<p>Les opérations qui &#8220;changent la valeur&#8221; sur les types non mutables sont moins performantes en Python car il faut recréer un objet à chaque fois.</p>
<p>Par défaut, toute classe que vous écrivez crée un objet mutable.</p>
<h2>Callable</h2>
<p>Tout ce qui peut être appelé, c&#8217;est à dire qu&#8217;on peut mettre <code>()</code> après le nom de la variable qui le contient pour obtenir un effet.</p>
<p>Ce qui vient en premier en tête ce sont les fonctions (ou les méthodes):</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Je suis appelée&quot;</span><span style="color: black;">&#41;</span>
...
<span style="color: black;">foo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># j'appelle ma fonction</span>
Je suis appelée</pre></td></tr></table></div>

<p>Mais, en Python, le concept d&#8217;appeler va plus loin.</p>
<p>Une classe est un callable :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Bar:
    <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: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Je suis appelée&quot;</span><span style="color: black;">&#41;</span>
Bar<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># j'instancie en utilisant ()</span>
&nbsp;
Je suis appelée</pre></td></tr></table></div>

<p>Un type est un callable :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Et on peut rendre n&#8217;importe quel objet callable en définissant la méthode <code>__call__</code> :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> UnCallableQuiCreerUnCallable:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__call__</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;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Je suis appelé'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #008000;">callable</span> <span style="color: #66cc66;">=</span> UnCallableQuiCreerUnCallable<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">callable</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
Je suis appelé</pre></td></tr></table></div>

<p>Donc quand on vous dit : &#8220;ceci attend un callable en paramètre&#8221;, vous pouvez passer n&#8217;importe quel type de callable. Pas juste une fonction. On peut créer des décorateurs avec et pour n&#8217;importe quel callable.</p>
<p>Si on essaye d&#8217;appeler un objet qui n&#8217;est pas un callabe, on obtient un <code>TypeError</code> :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">lst
<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
lst<span style="color: black;">&#40;</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;&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> 
    lst<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">TypeError</span>: <span style="color: #483d8b;">'list'</span> <span style="color: #008000;">object</span> <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">callable</span></pre></td></tr></table></div>

<h2>Hashable</h2>
<p>Les clés des dictionnaires n&#8217;ont pas besoin d&#8217;être des chaînes de caractères. Elles peuvent être n&#8217;importe quel objet hashable. Pour les types de base, ce sont les non mutables, soit les strings, mais aussi ints, floats ou tuples :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">dico <span style="color: #66cc66;">=</span> <span style="color: black;">&#123;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'une'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'cle'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'qui'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'est'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'un'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'tuple'</span><span style="color: black;">&#41;</span>: <span style="color: #ff4500;">1</span><span style="color: black;">&#125;</span>
<span style="color: #008000;">len</span><span style="color: black;">&#40;</span>dico<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">1</span>
dico<span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'une'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'cle'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'qui'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'est'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'un'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'tuple'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
<span style="color: #ff4500;">1</span></pre></td></tr></table></div>

<p>Pour obtenir cet effet, le dictionnaire prend l&#8217;objet passé en clé, et calcule un hash, une empreinte unique de l&#8217;objet. Pour que cela marche, il faut que le hash d&#8217;un objet donne toujours le même résultat si il est appliqué deux fois au même objet, ou à deux objets parfaitement égaux.</p>
<p>Un objet hashable est donc un objet qu&#8217;on peut utiliser comme clé de dictionnaire. C&#8217;est un objet qu&#8217;on peut passer à la fonction <code>hash()</code>. Dans la stdlib, les types non mutables sont hashable, et les types mutables ne le sont pas :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #008000;">hash</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;fdkslmf&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">4874978338908949266</span>
<span style="color: #008000;">hash</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#93;</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;&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> 
    <span style="color: #008000;">hash</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">TypeError</span>: unhashable <span style="color: #008000;">type</span>: <span style="color: #483d8b;">'list'</span></pre></td></tr></table></div>

<p>Mais on peut créer sa propre définition de ce qu&#8217;est un objet hashable avec la méthode <code>__hash__</code>, qui doit retourner un entier :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Personne:
    <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> nom<span style="color: #66cc66;">,</span> prenom<span style="color: #66cc66;">,</span> age<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">nom</span> <span style="color: #66cc66;">=</span> nom
        <span style="color: #008000;">self</span>.<span style="color: black;">prenom</span> <span style="color: #66cc66;">=</span> prenom
        <span style="color: #008000;">self</span>.<span style="color: black;">age</span> <span style="color: #66cc66;">=</span> age
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__hash__</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;">sum</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #008000;">ord</span><span style="color: black;">&#40;</span>x<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: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">nom</span> + <span style="color: #008000;">self</span>.<span style="color: black;">prenom</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> + <span style="color: #008000;">self</span>.<span style="color: black;">age</span>
...
<span style="color: #008000;">hash</span><span style="color: black;">&#40;</span>Personne<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;bob&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;sinclaire&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">78</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">1339</span></pre></td></tr></table></div>

<p>Vous avez néanmoins intérêt à savoir ce que vous faites en faisant ça, c&#8217;est un nid de frelons.</p>
<h2>Subscriptables</h2>
<p>Ce dont on peut récupérer une partie avec <code>[]</code>. Essayer sur un objet qui ne l&#8217;est pas peut lever <code>TypeError: 'x' object is not subscriptable</code> ou une sous erreur.</p>
<p>Car on peut utiliser <code>[]</code> de deux façons.</p>
<h3>Indexable</h3>
<p>Dont on peut récupérer un élément à une position particulière, avec la syntaxe <code>[]</code>. Dans la stdlib, les listes, les chaînes de caractères, les tuples et les dictionnaires sont indexables mais pas les sets :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;fdjskl&quot;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
<span style="color: #483d8b;">'f'</span>
<span style="color: black;">&#40;</span><span style="color: #483d8b;">'1'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'2'</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: #483d8b;">'1'</span>
<span style="color: black;">&#123;</span><span style="color: #483d8b;">'yo'</span>: <span style="color: #483d8b;">'man'</span><span style="color: black;">&#125;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'yo'</span><span style="color: black;">&#93;</span>
<span style="color: #483d8b;">'man'</span>
s <span style="color: #66cc66;">=</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: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
s<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> 
    s<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
<span style="color: #008000;">TypeError</span>: <span style="color: #483d8b;">'set'</span> <span style="color: #008000;">object</span> does <span style="color: #ff7700;font-weight:bold;">not</span> support indexing</pre></td></tr></table></div>

<p>On peut définir son propre comportement d&#8217;indexation avec <code>__getitem__</code> :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> MainGauche:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__getitem__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> index<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;Index de la main gauche&quot;</span>
&nbsp;
main <span style="color: #66cc66;">=</span> MainGauche<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>main<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
Index de la main gauche</pre></td></tr></table></div>

<h3>Sliceable</h3>
<p>Dont on peut récupérer un sous ensemble des éléments avec la syntaxe <code>[start:stop:step]</code>. Un sliceable est souvent indexable, mais l&#8217;inverse n&#8217;est pas forcément vrai. Dans la stdlib, les listes, les strings et les tuples sont sliceables, mais pas les dictionnaires ni les sets :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;fdjskl&quot;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>::<span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
<span style="color: #483d8b;">'dsl'</span>
<span style="color: black;">&#40;</span><span style="color: #483d8b;">'1'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'2'</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">True</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">False</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span>:-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
<span style="color: black;">&#40;</span><span style="color: #483d8b;">'1'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'2'</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#123;</span><span style="color: #483d8b;">'yo'</span>: <span style="color: #483d8b;">'man'</span><span style="color: black;">&#125;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> 
    <span style="color: black;">&#123;</span><span style="color: #483d8b;">'yo'</span>: <span style="color: #483d8b;">'man'</span><span style="color: black;">&#125;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
<span style="color: #008000;">TypeError</span>: unhashable <span style="color: #008000;">type</span>: <span style="color: #483d8b;">'slice'</span></pre></td></tr></table></div>

<p>Le slice s&#8217;implémente comme l&#8217;index, avec <code>__getitem__</code>. La différence est qu&#8217;au lieu de recevoir une valeur ordinaire, vous allez recevoir un objet slice :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> MainDroite:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__getitem__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">slice</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">slice</span>.<span style="color: black;">start</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">slice</span>.<span style="color: black;">stop</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;Slice de la main droite. Heu...&quot;</span>
&nbsp;
main <span style="color: #66cc66;">=</span> MainDroite<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>main<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span>:<span style="color: #ff4500;">6</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">2</span> <span style="color: #ff4500;">6</span>
Slice de la main droite. <span style="color: black;">Heu</span>...</pre></td></tr></table></div>


feed_id: http://sametmax.com/?p=13011
title: Corrections des slides WAMP 8
uri: Corrections-des-slides-WAMP-Recently-updated
url: http://sametmax.com/corrections-des-slides-wamp/
content:
<p>Suite aux commentaires, j&#8217;ai fais une refonte des dispos :</p>
<ul>
<li>Plus d&#8217;insistance sur la différence entre RPC et PUB/SUB.</li>
<li>Les exemples sont amenés plus tôt, et les schémas sont en premier.</li>
<li>Des lourdeurs et des redondances sont supprimées.</li>
<li>J&#8217;ai ajouté des réponses à quelques questions posées : perf, sécu, etc.</li>
</ul>
<p>Histoire d&#8217;éviter d&#8217;éparpiller des versions partout, je l&#8217;ai juste réup <a href="http://sametmax.com/presentation-de-wamp-round-2/">au même endroit</a>.</p>
<p>Merci, donc, pour toutes les remarques qui ont significativement permises d&#8217;améliorer la prez.</p>


feed_id: http://sametmax.com/?p=13019
title: Qu’est-ce que l’unpacking en Python et à quoi ça sert ? 6
uri: Qu-est-ce-que-l-unpacking-en-Python-et-à-quoi-ça-sert-Recen
url: http://sametmax.com/quest-ce-que-lunpacking-en-python-et-a-quoi-ca-sert/
content:
<p>Ce terme apparaît dans de nombreux articles du blog, et je prends parfois le temps de l&#8217;expliquer superficiellement. Évidemment, à de nombreux moments j&#8217;ai fait des tutos en ayant la connaissance de l&#8217;unpacking comme prérequis, et rien vers quoi faire un lien. Corrigeons ça, en attendant que je traduise les slides sur WAMP.</p>
<h2>Le principe de base</h2>
<p>Normalement, si vous voulez mettre le contenu d&#8217;un tuple dans des variables, vous devez procéder ainsi :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> ducks <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'riri'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'fifi'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'loulou'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> duck1 <span style="color: #66cc66;">=</span> ducks<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> duck2 <span style="color: #66cc66;">=</span> ducks<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> duck3 <span style="color: #66cc66;">=</span> ducks<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>duck1<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'riri'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>duck2<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'fifi'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>duck3<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'loulou'</span></pre></td></tr></table></div>

<p>L’unpacking, qu&#8217;on pourrait traduire par le terme fort moche de &#8220;déballage&#8221;, dans le sens &#8220;ouvrir un colis&#8221;, permet de faire la même chose, bien plus facilement :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> duck1<span style="color: #66cc66;">,</span> duck2<span style="color: #66cc66;">,</span> duck3 <span style="color: #66cc66;">=</span>  ducks
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>duck1<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'riri'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>duck2<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'fifi'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>duck3<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'loulou'</span></pre></td></tr></table></div>

<p>Il n&#8217;y a rien à faire, c&#8217;est automatique. La seule condition est que le nombre de variables à gauche du signe égal soit le même que le nombre d&#8217;éléments dans la collection de droite.</p>
<p>D&#8217;ailleurs, ça marche même avec un seul élément :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> ducks <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'riri'</span><span style="color: #66cc66;">,</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> duck1<span style="color: #66cc66;">,</span> <span style="color: #66cc66;">=</span> ducks <span style="color: #808080; font-style: italic;"># notez la virgule</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> duck1
<span style="color: #483d8b;">'riri'</span></pre></td></tr></table></div>

<p>Et ça marche avec n&#8217;importe quel <a href="http://sametmax.com/les-trucmuchables-en-python/">itérable</a>, pas uniquement les tuples. Avec une liste, une string, un générateur&#8230;</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> a<span style="color: #66cc66;">,</span> b<span style="color: #66cc66;">,</span> c<span style="color: #66cc66;">,</span> d <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> c
<span style="color: #ff4500;">3</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a<span style="color: #66cc66;">,</span> b <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;12&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> b
<span style="color: #483d8b;">'2'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">def</span> yolo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #483d8b;">&quot;leroy&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #483d8b;">&quot;jenkins&quot;</span>
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> nom<span style="color: #66cc66;">,</span> prenom <span style="color: #66cc66;">=</span> yolo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> nom
<span style="color: #483d8b;">'leroy'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> prenom
<span style="color: #483d8b;">'jenkins'</span></pre></td></tr></table></div>

<p>Ça marche bien entendu avec un dico ou un set, mais comme ils ne sont pas ordonnés, c&#8217;est pas très utile.</p>
<h2>Astuces autour de l&#8217;unpacking</h2>
<p>On peut utiliser l&#8217;unpacking dans des endroits inattendus. Par exemple, pour échanger la valeur de deux variables :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> a <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> b <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">2</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a<span style="color: #66cc66;">,</span> b <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span>b<span style="color: #66cc66;">,</span> a<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a
<span style="color: #ff4500;">2</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a<span style="color: #66cc66;">,</span> b <span style="color: #66cc66;">=</span> b<span style="color: #66cc66;">,</span> a <span style="color: #808080; font-style: italic;"># les parenthèses sont facultatives dans les tuples</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> b
<span style="color: #ff4500;">2</span></pre></td></tr></table></div>

<p>Puisqu&#8217;on est dans les tuples sans parenthèses, on peut retourner un tuple et donner l&#8217;illusion de retourner plusieurs variables :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">def</span> duckmebaby<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;rifi&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'filou'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'louri'</span>
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> et<span style="color: #66cc66;">,</span> hop<span style="color: #66cc66;">,</span> la <span style="color: #66cc66;">=</span> duckmebaby<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> et
<span style="color: #483d8b;">'rifi'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> hop
<span style="color: #483d8b;">'filou'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> la
<span style="color: #483d8b;">'louri'</span></pre></td></tr></table></div>

<p>Allons plus loin.</p>
<p>On peut utiliser l&#8217;unpacking à l&#8217;intérieur d&#8217;une boucle <code>for</code>. Souvenez vous que les itérables peuvent contenir d&#8217;autres itérables. Par exemple, j&#8217;ai une liste qui contient 3 tuples, chaque tuple contient deux éléments :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> scores <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Monique'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'3'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'David'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Dick'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">for</span> score <span style="color: #ff7700;font-weight:bold;">in</span> scores:
...     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>score<span style="color: black;">&#41;</span>
...
<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Monique'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'3'</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#40;</span><span style="color: #483d8b;">'David'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Dick'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Si je veux afficher le nom et le score l&#8217;un en dessous de l&#8217;autre :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">for</span> nom_et_score <span style="color: #ff7700;font-weight:bold;">in</span> scores:
...     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>nom_et_score<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: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>nom_et_score<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: black;">Monique</span>
<span style="color: #ff4500;">3</span>
David
<span style="color: #ff4500;">10</span>
Dick
<span style="color: #ff4500;">1</span></pre></td></tr></table></div>

<p>Je peux appliquer l&#8217;unpacking dans la boucle pour rendre cette opération plus élégante :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">for</span> nom<span style="color: #66cc66;">,</span> score <span style="color: #ff7700;font-weight:bold;">in</span> scores:
...     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>nom<span style="color: black;">&#41;</span>
...     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>score<span style="color: black;">&#41;</span>
...
<span style="color: black;">Monique</span>
<span style="color: #ff4500;">3</span>
David
<span style="color: #ff4500;">10</span>
Dick
<span style="color: #ff4500;">1</span></pre></td></tr></table></div>

<p>Cela marche avec des itérables plus gros, bien entendu. C&#8217;est aussi particulièrement utile avec des dictionnaires car on peut les transformer en itérable de tuples :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> scores <span style="color: #66cc66;">=</span> <span style="color: black;">&#123;</span><span style="color: #483d8b;">'Monique'</span>: <span style="color: #483d8b;">'3'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'David'</span>: <span style="color: #ff4500;">10</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Dick'</span>: <span style="color: #ff4500;">1</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> scores<span style="color: black;">&#91;</span><span style="color: #483d8b;">'Monique'</span><span style="color: black;">&#93;</span>
<span style="color: #483d8b;">'3'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> scores.<span style="color: black;">items</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># transformation !</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;">'Monique'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'3'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'David'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Dick'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</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> <span style="color: #ff7700;font-weight:bold;">for</span> nom<span style="color: #66cc66;">,</span> score <span style="color: #ff7700;font-weight:bold;">in</span> scores.<span style="color: black;">items</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>nom<span style="color: black;">&#41;</span>
...     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>score<span style="color: black;">&#41;</span>
...
<span style="color: black;">Monique</span>
<span style="color: #ff4500;">3</span>
David
<span style="color: #ff4500;">10</span>
Dick
<span style="color: #ff4500;">1</span></pre></td></tr></table></div>

<p>Tout aussi utile, mais plus compliqué, est l&#8217;usage de l&#8217;unpacking dans l&#8217;appel de fonction. Pour cela, on utilise <a href="http://sametmax.com/operateur-splat-ou-etoile-en-python/">l&#8217;opérateur splat</a>, l&#8217;étoile en Python.</p>
<p>Soit une fonction qui additionne des nombres :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">def</span> add<span style="color: black;">&#40;</span>a<span style="color: #66cc66;">,</span> b<span style="color: #66cc66;">,</span> c<span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">return</span> a + b + c
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> add<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">6</span></pre></td></tr></table></div>

<p>Oui, imaginons que je suis complètement débile, et que j&#8217;ai cette fonction pérave dans mon code. Vous noterez dans les articles que je l&#8217;utilise souvent sur le blog. C&#8217;est la fonction fourre tout pour expliquer un truc quand j&#8217;ai pas d&#8217;idée.</p>
<p>Maintenant, imaginez que je veuille additionner des canards. Si, ça marche en Python :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">'riri'</span> + <span style="color: #483d8b;">'fifi'</span> + <span style="color: #483d8b;">'loulou'</span> <span style="color: #808080; font-style: italic;"># what the duck ?</span>
<span style="color: #483d8b;">'rirififiloulou'</span></pre></td></tr></table></div>

<p>Maintenant je me refais mon tuples de canards :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #808080; font-style: italic;"># nous entrerons dans la bande à picsou, youhou</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> duckyou <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'riri'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'fifi'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'loulou'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Si je veux utiliser ma fonction pourrie pour mon use case stupide, je ferai ceci :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> add<span style="color: black;">&#40;</span>duckyou<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> duckyou<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> duckyou<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: #483d8b;">'rirififiloulou'</span></pre></td></tr></table></div>

<p>Voilà une perte de productivité intolérable, c&#8217;est pas comme ça qu&#8217;on va faire fructifier son sou fétiche.</p>
<p>On peut forcer l&#8217;unpacking avec l&#8217;étoile :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> add<span style="color: black;">&#40;</span>*duckyou<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'rirififiloulou'</span></pre></td></tr></table></div>

<p>Si on oublie l&#8217;étoile, le premier paramètre reçoit tout le tuple, et les autres paramètres rien :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> add<span style="color: black;">&#40;</span>duckyou<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;&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> 
    add<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">TypeError</span>: add<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> missing <span style="color: #ff4500;">2</span> required positional arguments: <span style="color: #483d8b;">'b'</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #483d8b;">'c'</span></pre></td></tr></table></div>

<p>Les fonctions ont même le droit à un bonus car on peut unpacker des dictionnaires en utilisant la <strong>double</strong> étoile. Ca ne marche qu&#8217;avec les fonctions, et ça va déballer le dico pour que chaque paire clé/valeur soit passée comme nom et valeur de l&#8217;argument :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">def</span> pas_add<span style="color: black;">&#40;</span>arg1<span style="color: #66cc66;">,</span> arg2<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>arg1<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>arg2<span style="color: black;">&#41;</span>
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> pas_add<span style="color: black;">&#40;</span>arg1<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;Je suis la valeur 1&quot;</span><span style="color: #66cc66;">,</span> arg2<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;Je m'en branle de qui tu es&quot;</span><span style="color: black;">&#41;</span>
Je suis la valeur <span style="color: #ff4500;">1</span>
Je m<span style="color: #483d8b;">'en branle de qui tu es
&gt;&gt;&gt; dicocorico = {'</span>arg1<span style="color: #483d8b;">': '</span>cotcot<span style="color: #483d8b;">', '</span>arg2<span style="color: #483d8b;">': '</span>ouai je pête un cable<span style="color: #66cc66;">,</span> l\<span style="color: #483d8b;">'avion me soule'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> pas_add<span style="color: black;">&#40;</span>**dicocorico<span style="color: black;">&#41;</span>
cotcot
ouai je pête un cable<span style="color: #66cc66;">,</span> l<span style="color: #483d8b;">'avion me soule</span></pre></td></tr></table></div>

<p>Quand on unpacke des paramètres, il faut s&#8217;assurer que le nombre d&#8217;arguments passé n&#8217;est pas supérieur à ceux existant, sinon ça plante :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> dicocorico <span style="color: #66cc66;">=</span> <span style="color: black;">&#123;</span><span style="color: #483d8b;">'arg1'</span>: <span style="color: #483d8b;">'cocot'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'arg2'</span>: <span style="color: #483d8b;">'ouai je pête un cable, l<span style="color: #000099; font-weight: bold;">\'</span>avion me soule'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'dang'</span>: <span style="color: #483d8b;">'je suis en trop et ça fait chier tout le monde'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> pas_add<span style="color: black;">&#40;</span>**dicocorico<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;&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> 
    pas_add<span style="color: black;">&#40;</span>**dicocorico<span style="color: black;">&#41;</span>
<span style="color: #008000;">TypeError</span>: pas_add<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> got an unexpected <span style="color: #dc143c;">keyword</span> argument <span style="color: #483d8b;">'dang'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> stuplet <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> pas_add<span style="color: black;">&#40;</span>*stuplet<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;&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> 
    pas_add<span style="color: black;">&#40;</span>*stuplet<span style="color: black;">&#41;</span>
<span style="color: #008000;">TypeError</span>: pas_add<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> takes <span style="color: #ff4500;">2</span> positional arguments but <span style="color: #ff4500;">3</span> were given</pre></td></tr></table></div>

<p>Par contre, rien ne vous empêche de fournir moins d&#8217;arguments et de remplir les autres à la main :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">def</span> encore_add<span style="color: black;">&#40;</span>a<span style="color: #66cc66;">,</span> b<span style="color: #66cc66;">,</span> c<span style="color: #66cc66;">,</span> d<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> a + b + <span style="color: #ff4500;">0</span> + c + d <span style="color: #808080; font-style: italic;"># je feinte</span>
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> encore_add<span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: #66cc66;">,</span> *stuplet<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">16</span></pre></td></tr></table></div>

<p>Et on peut bien entendu faire le mega mix. Par exemple, prenons la fonction <code>print</code>, dont la signature accepte une infinité d&#8217;arguments positionnels et quelques arguments nommés :</p>
<p><code>print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)</code></p>
<p>Aller, on va lui unpacker sa mère :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> ducks <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'riri'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'fifi'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'loulou'</span><span style="color: black;">&#93;</span> <span style="color: #808080; font-style: italic;"># is this duck typing ?</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> keywords <span style="color: #66cc66;">=</span> <span style="color: black;">&#123;</span><span style="color: #483d8b;">'sep'</span>: <span style="color: #483d8b;">' / '</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;end&quot;</span>: <span style="color: #483d8b;">&quot; : vous êtes du coin ? <span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'picsou'</span><span style="color: #66cc66;">,</span> *ducks<span style="color: #66cc66;">,</span> **keywords<span style="color: black;">&#41;</span>
picsou / riri / fifi / loulou : vous êtes du coin ?</pre></td></tr></table></div>

<p>Ça c&#8217;est fait.</p>
<h2>Python 3, c&#8217;est du chocolat</h2>
<p>En Python 3, l&#8217;unpacking a été amélioré, et on peut maintenant faire de l&#8217;unpacking partiel :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #808080; font-style: italic;"># exemple 100% repompé d'un autre article du blog. Duck it.</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> l <span style="color: #66cc66;">=</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span><span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</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: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a<span style="color: #66cc66;">,</span> *b <span style="color: #66cc66;">=</span> l
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a
<span style="color: #ff4500;">0</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> b
<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a<span style="color: #66cc66;">,</span> *b<span style="color: #66cc66;">,</span> c <span style="color: #66cc66;">=</span> l
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a
<span style="color: #ff4500;">0</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> b
<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> c
<span style="color: #ff4500;">4</span></pre></td></tr></table></div>

<p>Ce qui peut être très pratique sur les longs itérables. Comment obtenir la dernière ligne d&#8217;un fichier ?</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> *contenu<span style="color: #66cc66;">,</span> dernire_ligne <span style="color: #66cc66;">=</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/etc/fstab'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> dernire_ligne
<span style="color: #483d8b;">'UUID=0e8c3132-8fa2-46d5-a541-2890db9b371f none            swap    sw              0       0<span style="color: #000099; font-weight: bold;">\n</span>'</span></pre></td></tr></table></div>

<p>Ou alors, dans une boucle :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">for</span> initiale<span style="color: #66cc66;">,</span> *reste <span style="color: #ff7700;font-weight:bold;">in</span> ducks:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>initiale<span style="color: black;">&#41;</span>
...
<span style="color: black;">r</span>
f
l</pre></td></tr></table></div>


feed_id: http://sametmax.com/?p=13072
title: Bridge HTTP/WAMP 5
uri: Bridge-HTTP-WAMP-3-Recently-updated
url: http://sametmax.com/bridge-httpwamp/
content:
<p>Il y a 4 gros freins à l&#8217;adoption de <a href="http://sametmax.com/presentation-de-wamp-round-2/">WAMP</a> :</p>
<ol>
<li>L&#8217;incompréhension de la techno. Les gens ne voient pas à quoi ça sert, ce qu&#8217;ils peuvent faire avec, et ont peur. Logique. Je vais pas les blâmer, c&#8217;est pareil avec toute nouvelle techo. S&#8217;investir dans un nouveau truc a un coût, surtout un truc jeune.</li>
<li>La doc. je vais travailler sur la question, mais c&#8217;est un travail de fond.</li>
<li>L&#8217;API : ça va avec les deux points plus haut. Il faut quelque chose de plus haut niveau. L&#8217;API <a href="http://sametmax.com/introduction-a-wamp-en-python/">flaskesque</a> est un bon début, il faut maintenant continuer dans ce sens.</li>
<li>L&#8217;intégration avec les anciennes technos. Par exemple, un site Django. Personne n&#8217;a envie de mettre toute son ancienne stack à la poubelle.</li>
</ol>
<p>Toute les libs qui introduisent une nouvelle façon de travailler rencontrent ce problème. Quand les ORM sont sortis, c&#8217;était pareil. Quand les Django et Rails, et Symfony sont sortis, c&#8217;était pareil.</p>
<p>Mais puisqu&#8217;on le sait, on peut agir.</p>
<p>Les 3 premiers points ont déjà un début de solution, ce qui nous intéresse c&#8217;est donc le 4ème point.</p>
<p>Il y a de nombreuses choses à faire pour l’intégration : authentification, actions bloquantes, communications&#8230;</p>
<p>On ne peut pas tout résoudre d&#8217;un coup, mais une solution qui ratisse large serait de créer un bridge HTTP/WAMP.</p>
<p>Le principe : faire un client WAMP qui soit aussi client HTTP avec une API REST.</p>
<h2>Fonctionnement</h2>
<p>En envoyant des requêtes HTTP avec un <a href="https://github.com/progrium/pyjwt">webtoken</a> pour s&#8217;authentifier, on peut faire un register/subscribe/call/publish sur le bridge en spécifiant une URL de callback. Le bridge transmet tout ça à routeur WAMP. Quand un événement arrive sur le bridge qui concerne une des URLs de callback, il fait une requête sur l&#8217;URL avec les infos arrivées via WAMP.</p>
<p>API :</p>
<p><code>POST /register/</code></p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">// token d'authentification</span>
    token<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;fdjsklfqsdjm&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #006600; font-style: italic;">// On enregistre des urls de callbacks pour chaque &quot;function&quot; exposées en RPC</span>
    <span style="color: #006600; font-style: italic;">// Quand le bridge reçoit un appel RPC via WAMP, il fera une requête POST</span>
    <span style="color: #006600; font-style: italic;">// sur la bonne URL. Votre app récupère les données via POST, et retourne</span>
    <span style="color: #006600; font-style: italic;">// du JSON que le bridge va transmettre via WAMP.</span>
    endpoints<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #3366CC;">&quot;nom_fonction_1&quot;</span><span style="color: #339933;">:</span>  <span style="color: #3366CC;">&quot;http://localhost:8080/wamp/rpc/nom_fonction_1/&quot;</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;nom_fonction_2&quot;</span><span style="color: #339933;">:</span>  <span style="color: #3366CC;">&quot;http://localhost:8080/wamp/rpc/nom_fonction_2/&quot;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p><code>POST /subscribe/</code></p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#123;</span>
    token<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;fdjsklfqsdjm&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #006600; font-style: italic;">// On enregistre des urls de callbacks chaque abonnement à un topic.</span>
    <span style="color: #006600; font-style: italic;">// Quand le bridge reçoit un message PUB via WAMP, il fera une requête POST</span>
    <span style="color: #006600; font-style: italic;">// sur la bonne URL. Votre app récupère les données via POST.</span>
    endpoints<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #3366CC;">&quot;nom_fonction_1&quot;</span><span style="color: #339933;">:</span>  <span style="color: #3366CC;">&quot;http://localhost:8080/wamp/pub/nom_fonction_1/&quot;</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;nom_fonction_2&quot;</span><span style="color: #339933;">:</span>  <span style="color: #3366CC;">&quot;http://localhost:8080/wamp/pub/nom_fonction_2/&quot;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p><code>POST /call/nom_fonction/</code></p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#123;</span>
    token<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;fdjsklfqsdjm&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #006600; font-style: italic;">// Le bridge fera l'appel RPC, récupère la valeur de retour, et la renvoie</span>
    <span style="color: #006600; font-style: italic;">// à cette URL via POST ou une erreur 500 en cas d'exception.</span>
    callback<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;http://localhost:8080/wamp/callback/nom_fonction&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #006600; font-style: italic;">// Les params à passer à l'appel RPC</span>
    params<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'param1'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'param2'</span><span style="color: #009900;">&#93;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p><code>POST /publish/nom_sujet/</code></p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#123;</span>
    token<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;fdjsklfqsdjm&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #006600; font-style: italic;">// Le bridge fera la publication WAMP</span>
    <span style="color: #006600; font-style: italic;">// Les params à passer lors de la publication</span>
    params<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'param1'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'param2'</span><span style="color: #009900;">&#93;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>On peut rajouter des fioritures : recharger le fichier de config qui contient les API keys, se désabonner, désinscrire un callback RPC, etc. </p>
<p>Bien entendu, du fait d&#8217;avoir un intermédiaire, c&#8217;est peu performant, mais suffisant pour permettre une communication entre des apps existantes et vos apps WAMP et mettre un pied dedans.</p>
<h2>Intégration poussée</h2>
<p>Ceci permet une intégration générique, de telle sorte que tout le monde puisse intégrer son app facilement avec quelques requêtes HTTP. Néanmoins, avoir un plugin pour son framework plug and play faciliterait la vie de beaucoup de gens.</p>
<p>Donc la partie 2, c&#8217;est de faire des apps pour les frameworks les plus courants qui wrappent tout ça.</p>
<p>Par exemple, pour Django, ça permettrait de faire :</p>
<p><code>settings.py</code></p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">WAMP_BRIDGE_URL <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;http://localhost:8181/&quot;</span></pre></td></tr></table></div>

<p><code>urls.py</code></p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> wamp_bridge.<span style="color: black;">adapters</span>.<span style="color: black;">django</span> <span style="color: #ff7700;font-weight:bold;">import</span> dispatcher
&nbsp;
urlpatterns +<span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span><span style="color: #66cc66;">,</span>
    url<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/wamp/, dispatcher),
    ...
)</span></pre></td></tr></table></div>

<p><code>views.py</code></p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> wamp_bridge.<span style="color: black;">adapters</span>.<span style="color: black;">django</span> <span style="color: #ff7700;font-weight:bold;">import</span> publish<span style="color: #66cc66;">,</span> call<span style="color: #66cc66;">,</span> rpc<span style="color: #66cc66;">,</span> sub
&nbsp;
<span style="color: #66cc66;">@</span>rpc<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> nom_fonction_1<span style="color: black;">&#40;</span>val1<span style="color: #66cc66;">,</span> val2<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># faire un truc</span>
&nbsp;
<span style="color: #66cc66;">@</span>sub<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> nom_topic_1<span style="color: black;">&#40;</span>val1<span style="color: #66cc66;">,</span> val2<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># faire un truc</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> vue_normale<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
    publish<span style="color: black;">&#40;</span><span style="color: #483d8b;">'sujet'</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'arg1'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    resultat <span style="color: #66cc66;">=</span> call<span style="color: black;">&#40;</span><span style="color: #483d8b;">'function'</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'arg1'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Ca répond pas à des questions du genre : &#8220;comment je fais pour garder mon authentification Django&#8221; mais c&#8217;est déjà super glucose.</p>
<h2>Implémentation</h2>
<p>On peut créer un bridge dans plein de langages, mais je pense que Python est le plus adapté.</p>
<p>Les clients JS utiliseraientt de toute façon nodeJS, qui n&#8217;a pas besoin de bridge, puisque déjà asynchrone. Un routeur en C demanderait de la compilation. PHP est trop moche. Java, c&#8217;est tout un bordel à setuper à chaque fois. C#, si il faut se taper Mono sous Linux&#8230;</p>
<p>En prime, le routeur crossbar est déjà en Python, donc a déjà tout sous la main pour le faire. On peut même penser à l&#8217;intégrer à crossbar plus tard histoire que ce soit batteries included.</p>
<p>Il faut une implémentation Python 2 et Python 3, donc une avec Twisted, et une avec asyncio.</p>
<p>Pour le client twisted, on peut fusionner le client WAMP ordinaire avec <a href="http://twistedmatrix.com/documents/14.0.0/web/howto/web-in-60/index.html</a> et <a href="https://github.com/dreid/treq">treq</a>.</p>
<p>Pour asyncio, il y a <a href="https://github.com/KeepSafe/aiohttp">aiohttp</a> qui fait client et serveur.</p>
<p>On met les clés API dans un fichier de conf ou une variable d&#8217;env, une auth via token, et yala.</p>
<p>C&#8217;est le genre de projet intéressant car pas trop gros, mais suffisamment complexe pour être un challenge surtout qu&#8217;il faudra des tests unitaires partout, de la doc, bref un truc propre.</p>
<p>Je laisse les specs là, des fois qu&#8217;il y ait quelqu&#8217;un qui ait des envies de code cet hiver et cherche un projet open source dans lequel se lancer.</p>
<p>Si on se sent un peut foufou, on peut même transformer ça en bridget HTTP <=> anything, avec des backends pour ce qu&#8217;on veut : IRC, XMPP, Redis, Trigger Happy&#8230;</p>


feed_id: http://sametmax.com/?p=12972
title: Prendre le contrôle d’internet ? C’est possible ! Dégainez & Tirez avec Trigger Happy 4
uri: Prendre-le-contrôle-d-internet-C-est-possible-Dégainez-Tir
url: http://sametmax.com/prendre-le-controle-dinternet-cest-possible-degainez-tirez-avec-trigger-happy/
content:
<p style="text-align: center;"><em><small>Ceci est un post invité de <a href="http://sametmax.com/author/foxmask/">foxmask</a> posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.</small></em></p>
<p>&#8220;C&#8217;est l&#8217;histoire d&#8217;un mec qu&#8217;est su&#8217;l&#8217;pont de l&#8217;Alma et regarde dans&#8221; &#8230; le python, et comme il débute, se demande mais putain de bordel, des projets à la con à pondre pour se lancer à l&#8217;assaut d&#8217;un langage, c&#8217;est toujours les mêmes trucs chiants que plus personne n&#8217;a envie de voir tels : forum, blog, wiki, cms. Alors comment être novateur un poil plus que ces projets sans (plus aucun) défit technique ?</p>
<p>A cette question je me suis dit, pourquoi ne pas produire &#8220;simplement&#8221; (toute proportion gardée) un équivalent libre au célébrissime <a href="https://www.ifttt.com">IFTTT</a> ?</p>
<h2>Mais qu&#8217;est-ce ? </h2>
<p>IFTTT est un service qui vous permet de brancher entre eux, les services internet où vous possédez un compte, comme Twitter, Facebook pour ne citer qu&#8217;eux (parce que la liste est longue comme un python au moins;) Et donc quand un évènement défini se produit sur votre compte twitter, genre un tweet de votre poto tombe, le service réagit au quart de tour pour rebalancer les données ailleurs, sur Facebook, un blog et n&#8217;importe quoi qui vous chante.</p>
<p>Hé bien cet équivalent libre est <a href="https://github.com/foxmask/django-th">Trigger Happy</a>, et ce &#8220;principe&#8221; décrit ci-dessus défini un ESB (Entreprise Service Bus, très connu du monde Java), un BUS qui récupère des données de droite et vous les expédie à gauche.</p>
<p>Wikipedia le défini ainsi :</p>
<blockquote="wikipedia"><p>
L&#8217;enterprise service bus (ESB) est une technique informatique intergicielle. Son but est avant tout de permettre la communication des applications qui n&#8217;ont pas été conçues pour fonctionner ensemble</p></blockquote>
<h2>Pourquoi un tel projet ?</h2>
<p>3 aspects :</p>
<ul>
<li>Avec ce projet je me suis lancé le défit d&#8217;arriver à cerner au mieux Django et abordé au mieux Python.</li>
<li>Comme tout ce que j&#8217;entreprends, se produit par pur réaction allergique à un truc qui m&#8217;a gonflé, explications les zamis :<br />
Au début on fait (plus ou moins) comme tout le monde, sa veille techno à partir de flux RSS de sites web choisis, avec un lecteur de flux RSS moins bien choisi comme iGoogle à une certaine époque ou encore &#8230; Google Reader.<br />
Là le truc qui m&#8217;a pris le chou, ce fut d&#8217;avoir dans Evernote, le résultats des flux RSS de mes sites favoris complètement atrophiés.<br />
Du genre &#8220;il a été à l&#8217;école&#8221; devenait &#8220;il a t l&#8217;cole&#8221;. Or le problème ne vient pas d&#8217;Evernote qui affiche parfaitement nos chers caractères latins, mais de IFTTT qui les bouffait au passage. Outre IFTTT il existe des versions payantes de services mais qui sont vite très vite limitées dans le nombre de triggers déclenchés que sont Zapier et CloudWork.
</li>
<li>
Le dernier aspect concerne sa chère vie privé.<br />
Oui en effet, pour que IFTTT puisse récupérer des donnés d&#8217;un service à l&#8217;autre, il faut que vous ayez un compte sur chaque service comme Twitter et Facebook. Pourquoi IFTTT en a besoin ? Pour que, &#8220;en votre nom&#8221;, avec les accréditations que vous leur octroyez, puisse lire/écrire les informations de part et d&#8217;autre.<br />
Mais pourquoi faire confiance à IFTTT / Cloudwork / Zapier ? Pourquoi leur offrir NOS accréditations les yeux fermés ?<br />
Trigger Happy repond à la question puisque l&#8217;application vous appartient, les accréditations obtenues de Twitter, Facebook etc, sont stockées dans VOTRE application Trigger Happy. Et personne n&#8217;ira les exploiter pour voir ce que vous faites sur vos comptes.
</li>
</ul>
<h2>Comment fonctionne le projet ?</h2>
<p>Dans la version simplifiée ceci donne :<br />
<div id="attachment_5019" style="width: 420px" class="wp-caption aligncenter"><a href="media/ed04294d.trigger-happy-working.png" data-original-source="http://www.foxmask.bzh/wp-content/uploads/2014/12/trigger-happy-working.png" class="grouped_elements" rel="tc-fancybox-group12972"><img src="media/ed04294d.trigger-happy-working.png" data-original-source="http://www.foxmask.bzh/wp-content/uploads/2014/12/trigger-happy-working.png" alt="Trigger Happy wokring process" width="410" height="351" class="size-full wp-image-5019" /></a><p class="wp-caption-text">Image tirée de ma main &#8220;gauche&#8221; gauche, enfin la gauche pas adroite</p></div><br />
De part et d&#8217;autres (dans les nuages) on a les services qui nous intéressent<br />
Les éclairs oranges sont les connecteurs qui permettent de dialoguer avec les services<br />
Au milieu .. (non ne coule pas une rivière) le moteur Trigger Happy qui gère, via les connecteurs, l&#8217;échange des données.</p>
<p>Dans la version complète ceci donne :<br />
<div id="attachment_5018" style="width: 567px" class="wp-caption aligncenter"><a href="media/1ad209e2.th_esb.png" data-original-source="http://www.foxmask.bzh/wp-content/uploads/2014/12/th_esb.png" class="grouped_elements" rel="tc-fancybox-group12972"><img src="media/1ad209e2.th_esb.png" data-original-source="http://www.foxmask.bzh/wp-content/uploads/2014/12/th_esb.png" alt="Trigger Happy Micro ESB" width="557" height="347" class="size-full wp-image-5018" /></a><p class="wp-caption-text">Trigger Happy Micro ESB</p></div></p>
<p>On a au milieu un &#8220;tube&#8221; (pipeline) qui va permettre, via des &#8220;command&#8221; &#038; settings &#038; url &#038; service provider, d&#8217;identifier les services &#8220;django th 1, 2, 3, 4&#8243;.<br />
A un moment donné, à l&#8217;entrée du tube, arrive un &#8220;flux&#8221; de donnés identifié pour admettons &#8220;django th 1&#8243; aka un flux RSS (au pif) puis on identifie une destination, admettons &#8220;django th 2&#8243; aka &#8220;twitter&#8221;, et les données collectées repartent donc du tube vers twitter, comme le service s&#8217;attend à les recevoir.</p>
<h2>Dans la vraie vie comment ça se passe  ?</h2>
<p>Ça se passe bien mon zami : je m&#8217;en va (la fote est volontaire tout comme l&#8217;reste;) vous montrer la création d&#8217;un trigger, permettant d&#8217;extraire les billets du flux de mon blog et de les renvoyer sur Twitter en 5 étapes :</p>
<p>Ici en premier lieu vous pouvez voir la liste des services que Trigger Happy gere pour l&#8217;utilisateur courant (mézigues)</p>
<div id="attachment_5023" style="width: 614px" class="wp-caption aligncenter"><a href="media/4c2d2385.trigger_happy_services.png" data-original-source="http://www.foxmask.bzh/wp-content/uploads/2014/12/trigger_happy_services.png" class="grouped_elements" rel="tc-fancybox-group12972"><img src="media/8bce876d.trigger_happy_services-1024x539.png" data-original-source="http://www.foxmask.bzh/wp-content/uploads/2014/12/trigger_happy_services-1024x539.png" alt="Trigger Happy : services activés" width="604" height="318" class="size-large wp-image-5023" /></a><p class="wp-caption-text">Trigger Happy : services activés</p></div>
<p>Puis l&#8217;accueil de l&#8217;appli où on remarquera que je suis radin en nombre de trigger affichés par page parce que &#8230; je me sers de l&#8217;appli via un browser sur mon smartphone m&#8217;sieur &#8216;dames :<br />
<div id="attachment_5022" style="width: 614px" class="wp-caption aligncenter"><a href="media/79f7ec87.trigger_happy_home.png" data-original-source="http://www.foxmask.bzh/wp-content/uploads/2014/12/trigger_happy_home.png" class="grouped_elements" rel="tc-fancybox-group12972"><img src="media/481b4d11.trigger_happy_home-1024x595.png" data-original-source="http://www.foxmask.bzh/wp-content/uploads/2014/12/trigger_happy_home-1024x595.png" alt="Trigger Happy : Accueil" width="604" height="351" class="size-large wp-image-5022" /></a><p class="wp-caption-text">Trigger Happy : Accueil</p></div></p>
<p>Etape 1:<br />
<div id="attachment_5024" style="width: 621px" class="wp-caption aligncenter"><a href="media/658ab035.trigger_happy_step1.png" data-original-source="http://www.foxmask.bzh/wp-content/uploads/2014/12/trigger_happy_step1.png" class="grouped_elements" rel="tc-fancybox-group12972"><img src="media/658ab035.trigger_happy_step1.png" data-original-source="http://www.foxmask.bzh/wp-content/uploads/2014/12/trigger_happy_step1.png" alt="Trigger Happy : Etape 1 de la création d&#039;un trigger" width="611" height="315" class="size-full wp-image-5024" /></a><p class="wp-caption-text">Choix du service fournissant les données</p></div></p>
<p>Etape 2:<br />
<div id="attachment_5025" style="width: 709px" class="wp-caption aligncenter"><a href="media/caf951ed.trigger_happy_step2.png" data-original-source="http://www.foxmask.bzh/wp-content/uploads/2014/12/trigger_happy_step2.png" class="grouped_elements" rel="tc-fancybox-group12972"><img src="media/caf951ed.trigger_happy_step2.png" data-original-source="http://www.foxmask.bzh/wp-content/uploads/2014/12/trigger_happy_step2.png" alt="Trigger Happy : Etape 2 de la création d&#039;un trigger" width="699" height="329" class="size-full wp-image-5025" /></a><p class="wp-caption-text">nommage du service et fourniture de l&#8217;origine des données</p></div></p>
<p>Etape 3:<br />
<div id="attachment_5026" style="width: 602px" class="wp-caption aligncenter"><a href="media/899b6c46.trigger_happy_step3.png" data-original-source="http://www.foxmask.bzh/wp-content/uploads/2014/12/trigger_happy_step3.png" class="grouped_elements" rel="tc-fancybox-group12972"><img src="media/899b6c46.trigger_happy_step3.png" data-original-source="http://www.foxmask.bzh/wp-content/uploads/2014/12/trigger_happy_step3.png" alt="Trigger Happy : Etape 3 de la création d&#039;un trigger" width="592" height="310" class="size-full wp-image-5026" /></a><p class="wp-caption-text">Choix du service accueillant les données</p></div></p>
<p>Etape 4:<br />
<div id="attachment_5027" style="width: 670px" class="wp-caption aligncenter"><a href="media/93f38121.trigger_happy_step4.png" data-original-source="http://www.foxmask.bzh/wp-content/uploads/2014/12/trigger_happy_step4.png" class="grouped_elements" rel="tc-fancybox-group12972"><img src="media/93f38121.trigger_happy_step4.png" data-original-source="http://www.foxmask.bzh/wp-content/uploads/2014/12/trigger_happy_step4.png" alt="Trigger Happy : Etape 4 de la création d&#039;un trigger" width="660" height="351" class="size-full wp-image-5027" /></a><p class="wp-caption-text">Trigger Happy : Etape 4 de la création d&#8217;un trigger</p></div></p>
<p>Ensuite le moment venu, se déclenche ce trigger, et pour en voir le résultat, on peut consulter <a href="http://www.foxmask.bzh/post/2014/11/27/django-paris-numa-novembre-2014-demo-live/">le billet</a> que j&#8217;avais préparé le mois dernier pour une présentation Django Paris. Et qui au moment de la publication du billet, à 19h15 pétantes, est tombé sur <a href="https://twitter.com/foxmask/status/538033340155432960">twitter</a> directement et <a href="https://www.evernote.com/pub/foxmask1/Django#st=p&#038;n=e47e8324-ad7e-4b4a-bf4e-0823642b9d3a">Evernote</a> dans la foulée.</p>
<p>Voilà ! </p>
<p>Le défit est parti et n&#8217;attend plus qu&#8217;à ce que le nombre de services croissent. Pour cela rien de plus simple, j&#8217;ai fait une doc expliquant comment pondre un module django qui exploite le service de votre choix tel Buffer, Trello, Dropbox et j&#8217;en passe et des meilleurs. Tout ce dont on a besoin : l&#8217;API du service visé en python, créer un compte pour avoir accès au service et suivre le howto sur <a href="http://trigger-happy.readthedocs.org/en/latest/new_module.html">readthedoc</a>  </p>
<p>Last but not least aux dev : ca tourne avec django 1.7 / Python 2.7 et 3.4</p>
<p>Dernier détail: comme je suis sûr que vous vous demandez pourquoi ce nom de projet ? <a href="media/11eb85e9.trigger-happy.png" data-original-source="http://trigger-happy.eu/static/django-paris-novembre-2014/trigger-happy.png" class="grouped_elements" rel="tc-fancybox-group12972">C&#8217;est un perso de la franchise Skylander</a> auquel joue mon fils et comme le projet &#8220;trigger&#8221; à tirelarigot sur l&#8217;net, ca collait pile poil :)</p>


feed_id: http://sametmax.com/?p=13047
title: Comment arrivent les plans à 3 ? 5 Recently updated !
uri: Comment-arrivent-les-plans-à-3-3-Recently-updated
url: http://sametmax.com/comment-arrivent-les-plans-a-3/
content:
<p>Au début, on se demande comment parler à l&#8217;autre. Et comment on fait pour toucher ? Embrasser ? Baiser ? Obtenir une fellation ? Une sodomie ? Amener un scénario, un jeu SM ?</p>
<p>Et puis on grandit et on passe de l&#8217;autre côté de la barrière, et à chaque fois on se dit que c&#8217;était pas si mystérieux que ça au final.</p>
<p>Mais il reste toujours des situations inconnues, qui apparaissent obscures : par exemple, comment on arrive à un threesome, bordel ?</p>
<p>Comme d&#8217;habitude, je n&#8217;ai pas de recette magique, mais je peux vous donner quelques exemples de situations.</p>
<h2>Promotion sur canapé</h2>
<p>Marc, Marie et Mathilde ont orienté le rétroprojecteur vers le plafond pour regarder un film comme des loques, allongés sur deux canapés poussés l&#8217;un contre l&#8217;autre. Marc et Marie sortent ensemble, Marc et Mathilde ont fleurté. Tous les 3 sont sexuellement décontractés et ont déjà parlé de cul à table. Ils se connaissent, ils ont plusieurs soirées derrière eux.</p>
<p>En plein film, Marc caresse le bras de Marie, puis descend lentement vers sa chatte, sans y penser. Il finit par la caresser discrètement, et emporté, lui cale un doigt. Marie reste calme, mais Mathilde s&#8217;en aperçoit. Elle soulève le shirt de Marie, et commence à lui toucher un sein, puis à le prendre dans sa bouche. Tout en regardant le film, Marc et Mathilde s&#8217;occupent de Marie. Puis l&#8217;excitation monte, et Marc retire le pantalon de Marie pour lui faire un cuni&#8230;</p>
<p>Que s&#8217;est-t-il passé ?</p>
<p>Les 3 personnes se connaissaient. Elles sont à l&#8217;aise sexuellement. Elles ont déjà parlé de sexe.</p>
<p>En effet, on ne peut pas faire ça avec tout le monde : seul un certain type de personnes se retrouvent dans ces threesomes, les gens à l&#8217;aise avec le cul. Si vous avez du mal à assumer votre sexualité, si pour vous la fellation est un événement rare, ne tentez pas le plan à 3 tout de suite. Courir avant de marcher, tout ça&#8230;</p>
<p>Ensuite, ils savent qui ils sont : ils se sont vu plusieurs fois, ont parlé de sexe, se sont évalués. La prise de risque est allégée. </p>
<p>Ils sont seuls, dans une situation confortable, intime, et tout escalade doucement, naturellement. Personne n&#8217;a essayé de lancer un plan à 3. Ça s&#8217;est fait, non pas parce que chaque pas à amené vers, mais parce qu&#8217;aucun pas n&#8217;a été bloqué.</p>
<p>Car quand il s&#8217;agit de sexe, si une envie n&#8217;est pas satisfaite, c&#8217;est toujours imposé par une forme ou une autre de blocage. Il ne s&#8217;agit donc pas de pousser, mais d&#8217;être dans un contexte fluide, sans blocage.</p>
<h2>Comment on fait, putain ?</h2>
<p>La putain, est aussi la porte d&#8217;entrée aux plan à 3. Julien et Jérémy vont dans un bordel, embauchent une professionnelle en lui demandant si ils peuvent être deux pendant la séance. Ils se rejoignent dans la chambre, surmontent leurs inhibitions et se déshabillent. Au début ils hésitent, mais la prostituée connaît son métier et commence par en sucer un, exposant sa croupe à l&#8217;autre. Invité, le second la pénètre après avoir mis un préservatif. Les deux amis ne se toucheront pas, nullement intéressés l&#8217;un par l&#8217;autre, mais trouveront agréable l&#8217;expérience de partager une même femme.</p>
<p>Encore une fois, on note que tout le monde ne peut pas se retrouver dans cette situation : il faut des gens à l&#8217;aise avec l&#8217;idée de prostitution, et qui acceptent de se dévoiler, plus nus que jamais, l&#8217;un à l&#8217;autre dans une activité sexuelle.</p>
<p>Ce sont des amis, ils se connaissent. On en revient donc à la notion de confort et de confiance.</p>
<p>De son côté, la femme, accepte de prendre deux hommes en même temps, ce qui n&#8217;est pas forcément toujours le cas. Croire que les putes acceptent tout et que la permission est optionnelle est l&#8217;erreur des gens qui confondent sexe payé et esclavage. Une prostituée est une femme ordinaire, qui mérite le même respect.</p>
<h2>Je ne fais pas ça d&#8217;habitude</h2>
<p>Ingrid, Isabelle et Ignace ont tous beaucoup bu. Ignace a été gogo danseur par le passé et a fait sérieusement monté la température sur scène, mais maintenant ils se détendent, assis sur le même canapé. Ils ne parlent pas, ils sont dans la torpeur que le mélange de musique forte, d&#8217;éthanol et d&#8217;activité physique finit toujours par produire.</p>
<p>Ignace a lancé cette soirée chez lui, comme de nombreuses autres. Tout le monde le connaît comme quelqu&#8217;un de sociable, connaissant beaucoup de gens. Car il aime ça, il aime parler à autrui. Il aime aider. Il aime recevoir. Et toutes les personnes ce soir le savent.</p>
<p>Pour ne rien gâcher, Ignace est beau gosse, officiellement bi, et parle de sexe ouvertement. Il sera donc le pivot.</p>
<p>Dans le flou flottant de cet instant, les deux filles se reposent sur Ignace qui en embrasse une sur la tête. Il met ses bras autour d&#8217;elles. Ils restent ainsi un moment qui peut paraître long (mais difficile à évaluer car on perd la notion du temps dans ces conditions), affectueusement. Les mains d&#8217;Ignace caressent légèrement Ingrid et Isabelle. L&#8217;une l&#8217;embrasse sur la joue. L&#8217;autre l&#8217;embrasse sur la main. Il peut se passer un temps important entre deux baisers. Mais il décroit, jusqu&#8217;à ce que leurs corps remuent un peu, légèrement, l&#8217;un contre l&#8217;autre. Alors ils s&#8217;en vont dans la chambre.</p>
<p>Une fois de plus : les personnes sont connues, le milieu est sûr, il y a du confort et de la confiance, et bien entendu une aisance avec le sexe. L&#8217;alcool et le bruit catalysent cela, donnant une impression de proximité, voir d&#8217;intimité. </p>
<h2>Ou autres</h2>
<p>Ce ne sont pas les seules possibilités. Je pourrais parler de la drogue, des clubs échangistes, des plans à 3 planifiés avec son/sa partenaire&#8230;</p>
<p>Mais l&#8217;idée reste là :</p>
<ul>
<li>Ça ne se fait pas avec n&#8217;importe qui : des gens qu&#8217;on connait, envers lesquels on a confiance, qui sont à l&#8217;aise avec le cul.
</li>
<li>La prise de risque doit être faible. Il ne doit pas y avoir de blocage. Le reste suit juste son cours.</li>
<li>Le contexte joue : alcool, confort, joie, côté naturel de la chose.</li>
</ul>
<p>Ceci s&#8217;applique même pour l&#8217;exemple avec la prostituée. Si vous ne le voyez pas, c&#8217;est que vous avez encore un blocage quelque part. Le premier blocage à faire sauter, c&#8217;est le vôtre.</p>
<p>Une autre chose importante là-dedans, c&#8217;est qu&#8217;aucun des acteurs n&#8217;a la peur d&#8217;être rejeté. Non pas qu&#8217;ils ont la certitude que ça va marcher, mais plutôt :</p>
<ul>
<li>Qu&#8217;ils n&#8217;ont pas l&#8217;objectif &#8220;threesome&#8221; en tête. Juste de passer un bon moment.</li>
<li>Ils sont ok à l&#8217;idée qu&#8217;on dise non. C&#8217;est absolument normal.</li>
<li>Ils se sont déjà fait dire non bien des fois.</li>
</ul>
<p>Autre chose : personne n&#8217;a rien demandé. Ils font. Pour ce genre de choses, il est plus facile de demander pardon que la permission.</p>


feed_id: http://sametmax.com/?p=15615
title: Qu’est-ce que les websockets et à quoi ça sert ? 8 Recently updated !
uri: Qu-est-ce-que-les-websockets-et-à-quoi-ça-sert-6-Recently-upd
url: http://sametmax.com/quest-ce-que-les-websockets-et-a-quoi-ca-sert/
content:
<blockquote><p>Le protocole WebSocket vise à développer un canal de communication full-duplex sur un socket TCP.</p></blockquote>
<p>LOL. C&#8217;est clair non ?</p>
<p>Vous inquiétez pas, tonton Sam est là.</p>
<p>Le Web a évolué. On est passé de Gopher a HTTP 1 puis 1.1. Et on a eu AJAX pour rafraîchir la page sans tout recharger.</p>
<p>Et maintenant on a des apps complètes qui font des centaines de requêtes au serveur alors même que l&#8217;utilisateur ne change pas de page. D&#8217;ailleurs, je parie que plein de gens ne savent même plus ce qu&#8217;est une page&#8230;</p>
<p>Le problème c&#8217;est qu&#8217;AJAX, c&#8217;est toujours HTTP, et HTTP est sans état (stateless) : il ne garde aucune information en mémoire d&#8217;une requête à l&#8217;autre. Ça a des avantages, mais cela implique qu&#8217;à chaque requête, il faut ouvrir une connexion et la refermer. Ce qui bouffe quelques ms à chaque fois, et d&#8217;autant plus si on utilise SSL.</p>
<p>Une autre limite, c&#8217;est que le serveur ne peut pas envoyer de données au client (ici le navigateur) si le client ne fait pas une requête au préalable. Du coup, pour savoir si il y a quelque chose de nouveau, le navigateur doit régulièrement faire des requêtes au serveur ou utiliser des gros hacks comme le long polling.</p>
<p>Les websockets (c&#8217;est un abus de langage, on devrait parler du protocole Websocket) ont été créés pour répondre à ces besoins : elles permettent d&#8217;ouvrir une connexion permanente entre le navigateur et le serveur. Ainsi, chaque requête est plus rapide, et plus légère. En prime, le serveur peut envoyer des requêtes au navigateur pour le prévenir qu&#8217;il y a du nouveau.</p>
<p>Ceci permet de faire tout ce que permettait de faire AJAX mais en plus rapide, et en plus léger. Et également d&#8217;envoyer des notifications (ce contenu a changé, un message est arrivé, l&#8217;autre joueur a fait cette action&#8230;) au navigateur au moment où l&#8217;événement se produit.</p>
<p>En gros, de faire des apps Web quasi temps réel.</p>
<p>Il existe d&#8217;autre technos pour faire cela : applets Java, flash, comet, server sent events&#8230;</p>
<p>Mais aucune n&#8217;ont décollé. Websocket est donc aujourd&#8217;hui la solution de facto.</p>
<h2>Caractéristiques</h2>
<p>Le protocole Websocket utilise l&#8217;abréviation <code>ws</code> et <code>wss</code> si SSL, les URLs vers des endpoints websocket ressemblent donc à : <code>ws://domaine.tld/chemin/vers/truc/</code>.</p>
<p>Intelligemment, il utilise un handshake compatible avec celui de HTTP, permettant à un serveur de gérer les deux sur les mêmes ports. Donc on peut faire du Websocket sur le port 80 et 443. Néanmoins, certains proxy se gourent quand ils voient du websocket non chiffré et gauffrent votre connexion en la traitant comme du HTTP. Donc si vous voulez une app solide, investissez dans un certif SSL.</p>
<p>Tout ça fonctionne à partir de IE10. Notez comme IE est devenu le standard de ce qui ce fait de moins bien à tel point que je n&#8217;ai même pas besoin de vous parler des autres, vous savez que ça marche. Il existe en plus des <a href="https://github.com/gimite/web-socket-js">plugins flash</a> pour simuler des websockets sur les navigateurs anciens, c&#8217;est à dire les encore plus vieux IE.</p>
<p>Par défaut, les websockets permettent de faire de requêtes crossdomain, contrairement à AJAX. Avec les nouvelles apps qui utilisent NodeJS en local (comme <a href="http://getpopcornti.me/">popcorntime</a>) on peut imaginer une nouvelle type d&#8217;attaque : une page web qui se connecte à un serveur websocket local de votre machine. Comme les websockets sont souvent utilisées pour du RPC, il y a du potentiel.</p>
<h2>Bon, ta gueule, et montre le code</h2>

<!-- iframe plugin v.2.9 wordpress.org/plugins/iframe/ -->
<iframe width="100%" height="300" src="http://jsfiddle.net/rpecs5f1/embedded/result,js" allowfullscreen="allowfullscreen" frameborder="0" scrolling="no" class="iframe-class"></iframe>

<p>Vous noterez que ce qui prend du temps dans l&#8217;exemple c&#8217;est la connexion, qu&#8217;on ne fait qu&#8217;une fois. Ensuite l&#8217;échange de données est super rapide.</p>
<p>Ceci est un exemple Javascript, mais un client websocket n&#8217;est pas forcément un navigateur. En fait, c&#8217;est très précisément le cas avec <a href="http://sametmax.com/presentation-de-wamp-round-2/">WAMP</a>, dont les clients peuvent être des programmes Python, Objective C, Java, C++, etc. L&#8217;avantage de WAMP, c&#8217;est qu&#8217;il automatise toute la machinerie pour découper la logique de son programme en divers fonctions et services, plutôt que d&#8217;avoir à tout faire à la main avec <code>send()</code> et <code>onmessage()</code>.</p>
<p>Dans tous les cas, il vous faudra un serveur qui supporte les Websockets pour l&#8217;utiliser. En Python, c&#8217;est Tornado ou Twisted (sur lequel est basé le serveur WAMP crossbar). En Javascript, c&#8217;est NodeJS. Quoi qu&#8217;il en soit, il vous faut un logiciel qui gère l&#8217;IO de manière <a href="http://sametmax.com/quelle-est-la-difference-entre-bloquer-et-en-cours-dexecution/">non bloquante</a>, car il y a de nombreuses connexions ouvertes en simultanées, si on veut que ça soit performant.</p>


feed_id: http://sametmax.com/?p=15623
title: IndexError : plateforme de Questions/Réponses pour Python en français 23
uri: IndexError-plateforme-de-Questions-Réponses-pour-Python-en-françai
url: http://sametmax.com/indexerror-plateforme-de-questionsreponses-pour-python-en-francais/
content:
<p>Quand des gens demandent de l&#8217;aide en comments, on les invite à aller plutôt sur des forums. Les commentaires sont pas pratiques pour ça.</p>
<h2>La nouvelle qu&#8217;elle est cool</h2>
<p>Aujourd&#8217;hui Max a installé un petit outil (PHP, mais bon, on va pas faire la fine bouche) genre mini-stackoverflow en beaucoup plus simple :</p>
<p><a href="http://indexerror.net/">IndexError</a></p>
<p>Vous pouvez maintenant poser vos questions techniques dessus, ou répondre à celles des autres. Le contenu est placé sous la même licence que le blog, en creative 3.0 unported.</p>
<p>Je vais traîner un peu dessus, et faire ce que je ne pouvais pas faire auparavant, donner un coup de main. Mais ne prenez pas ça pour une ligne directe en SAV gratuit avec Sam. On a plutôt envie qu&#8217;une petite communauté s&#8217;entraide, SamOS n&#8217;est pas scalable pour ce genre de charge. </p>
<h2>La clause en tout petit en bas du contrat</h2>
<p><strong>L&#8217;espace de discussions est uniquement fait pour parler de l&#8217;écosystème Python en français</strong>. Pas de cul, de Javascript ou autres trucs déviants ;)</p>
<p>Ça laisse quand même de la marge : Blender, Raspberry, Django, Pygame, Twisted, OpenCV, Scipy, Virtualenv, OpenStack, WAMP, ArcGIS&#8230; Y a du Python partout !</p>
<p>Le site est lent &#8211; et la raison est simple &#8211; on est hébergé sur la même petite instance que le blog pour des raisons de budget. Si il commence à y avoir un peu de monde, on migrera le truc sur quelque chose de plus gros. En attendant, <strong>on va croiser les doigts et serrer les fesses, espérant que ça nous explose pas à la tronche dès qu&#8217;il y a 3 clampins dessus</strong>.</p>
<p>Néanmoins, si ça arrive, ça va coûter des thunes. Contrairement au blog qui ne verra jamais un morceau d&#8217;AdSense par principe, il faudra bien trouver un moyen de payer ces frais. Donc en gros, si on commence à avoir du traf, y aura sûrement de la pub quelque part. J&#8217;annonce avant qu&#8217;on se fasse tomater la gueule sur scène&#8230; Ce truc n&#8217;est pas comme 0bin, ça fait des requêtes en masse, ça envoie de mails, ça consomme quoi.</p>
<p>On sépare donc bien la partie blog, qui reste un espace de liberté où on peut parler de sodomie sans se taper une pop under, et IndexError, quelque chose de plus classique. </p>


feed_id: http://sametmax.com/?p=13068
title: La notation de version SemVer 7 Recently updated !
uri: La-notation-de-version-SemVer-2
url: http://sametmax.com/la-notation-de-version-semver/
content:
<p>Il y a des tas de manières d&#8217;indiquer la version d&#8217;un logiciel.</p>
<p>Ubuntu utilise l&#8217;année et le mois, à l&#8217;envers : la 14.04 indique une version sortie en avril 2014.</p>
<p>Avant la 1.2, angular utilisait les versions paires pour signifier la stabilité, et impaire pour l&#8217;instabilité.</p>
<p>Quelques projets utilisent des numéros de branche Git ou Svn.</p>
<p>Certains utilisent des noms du genre &#8220;kangourou-cosmique&#8221; pour marquer le coup.</p>
<p>Et d&#8217;autres mélangent plusieurs techniques.</p>
<p>En Python, la méthode recommandée est nommée <a href="http://semver.org/">SemVer</a>, pour Semantic Versioning.</p>
<h2>Explications</h2>
<p>Tout est basé sur la notion d&#8217;API publique. Si vous ne vous souvenez pas de ce qu&#8217;est une API publique, <a href="http://sametmax.com/quest-ce-quune-api/">c&#8217;est par ici</a>.</p>
<p>Une bibliothèque versionnée avec SemVer doit clairement documenter toute son API publique pour dire : voici les bouts de codes que vous pouvez utiliser sans risque.</p>
<p>Beaucoup de devs ne font pas, tout comme on fait souvent du REST non pur, on fait souvent du SemVer non pur, mais je vous le dis sinon des puristes viendront jouer de la moustache en commentaires.</p>
<p>Le principe est simple : votre versioning est noté <code>x.y.z</code>, <code>x</code>, <code>y</code> et <code>z</code> étant des entiers positifs. A moins que le nombre soit <code>0</code>, aucun nombre ne doit commencer par <code>0</code>.</p>
<p>Le <code>x</code> représente une version majeure, qui introduit au moins un changement incompatible dans l&#8217;API publique.</p>
<p>Le <code>y</code> représente une version mineure, qui introduit au moins une nouvelle fonctionnalité dans l&#8217;API publique.</p>
<p>Le <code>z</code> représente une correction de bug ou un changement dans l&#8217;API privée.</p>
<p>Et c&#8217;est tout.</p>
<h2>En pratique</h2>
<p>Si vous réparez un bug, <code>z</code> augmente de <code>1</code>.</p>
<p>Ex : <code>1.3.4</code> devient <code>1.3.5</code></p>
<p>Si vous introduisez un nouveau paramètre optionnel, une fonction outil indépendante, un nouvel attribut public, <code>y</code> augmente de <code>1</code>, et <code>z</code> est remis à 0 :</p>
<p>Ex : <code>1.3.4</code> devient <code>1.4.0</code></p>
<p>Si une fonction retourne maintenant ne serait-ce qu&#8217;un tuple au lieu de précédemment une liste, <code>x</code> augmente de <code>1</code>, <code>y</code> et <code>z</code> sont remis à 0 :</p>
<p>Ex : <code>1.3.4</code> devient <code>2.0.0</code></p>
<h2>FAQ</h2>
<h3>Le numéro de version va monter très vite non ?</h3>
<p>On ne change le numéro de version que pour une version publiée. Si vous faites plein de petits changements mais que vous ne déclarez pas ce nouveau code comme la dernière version officielle, pas besoin de changer de version : vous êtes encore en développement.</p>
<p>N&#8217;oubliez pas aussi que c&#8217;est VOTRE job de vous assurez que votre programme reste compatible. Faites des adapters, des alias, introduisez les fonctionnalités de manière optionnelle, depréciation à l&#8217;avance&#8230; Il y a des moyens de faire ça proprement.</p>
<h3>C&#8217;est quand même over chiant pour une lib qui vient de sortir et que personne n&#8217;utilise, non ?</h3>
<p>Jusqu&#8217;à la version <code>1.0.0</code>, le SemVer ne s&#8217;applique pas. En <code>0.y.z</code>, on peut faire du freestyle.</p>
<h3>Mais si je suis en beta ?</h3>
<p>On peut signaler des informations supplémentaires en mettant un tiret après son versioning. Le style est libre mais la convention est généralement <code>x.y.z-status</code>. Ex : <code>1.3.3-alpha</code>, <code>1.3.3-beta</code>, <code>1.3.3-rc1</code>, etc.</p>
<h3>Attend, je fais une release parfaitement compatible, mais avec une fonction publique qui ne retourne plus <code>1</code> mais <code>True</code>, je vais pas bumper pour ça quand même ?</h3>
<p>Si. Si vous ne voulez pas le faire, mettez le dans une branche à part, et attendez une release plus grosse pour introduire ce changement.</p>
<h3>J&#8217;ai une correction de bug qui introduit une changement incompatible dans l&#8217;API publique, je fais quoi ?</h3>
<p>On bump. Ça n&#8217;arrive pas si souvent que ça qu&#8217;un bug change l&#8217;API publique, faut pas charrier.</p>
<h3>Ouais, genre tu le fais&#8230;</h3>
<p>Non, je ne fais pas du SemVer pur. Mais sur une lib qui est très utilisée, c&#8217;est un système indispensable. Si j&#8217;avais la responsabilité de pondre Django, ouais, je ferais du SemVer pur.</p>
<h3>Ok, je l&#8217;ai fais mais j&#8217;ai pas l&#8217;impression d&#8217;y gagner quoi que ce soit.</h3>
<p>Le bénéfice n&#8217;est pas pour l&#8217;auteur, mais pour les utilisateurs. Si un autre utilisateur à votre lib comme dépendance, il peut déclarer dans son fichier setup.py:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">requires<span style="color: #66cc66;">=</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'votrelib&gt;=1.3.1&lt;2.0.0'</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Ainsi il est certain que ça ne pétera pas si vous faites votre boulot correctement car la lib installée par pip sera toujours dans une version entre la 1.3.1 qu&#8217;il sait compatible, jusqu&#8217;à la 2.0.0 qui sera incompatible.</p>


feed_id: http://sametmax.com/?p=15653
title: Les articles les plus importants sur Python 6
uri: Les-articles-les-plus-importants-sur-Python-Recently-updated
url: http://sametmax.com/les-articles-les-plus-importants-sur-python/
content:
<p>J&#8217;ai beau régulièrement pointer vers la section <a href="http://sametmax.com/cours-et-tutos/">Cours et tutos</a>, je sens bien que les gens n&#8217;en bénéficient pas autant qu&#8217;ils le devraient.</p>
<p>Une des raisons est la quantité d&#8217;info à lire. </p>
<p>Ok, voici donc une sélection d&#8217;articles, qui ne sont pas forcément orientés débutants. Ce sont les trucs à maîtriser. Pas tout de suite. Pas tout d&#8217;un coup. Mais au final, un programmeur Python doit savoir ça.</p>
<ul>
<li><a href="http://sametmax.com/message-de-service-aux-debutants-en-python/">Message de service aux débutant</a></li>
<li><a href="http://sametmax.com/votre-python-aime-les-pip/">Installer une lib avec pip</a></li>
<li><a href="http://sametmax.com/les-environnement-virtuels-python-virtualenv-et-virtualenvwrapper/">Virtualenv</a></li>
<li><a href="http://sametmax.com/python-love-les-listes-en-intention-partie/">Les listes en intensions</a></li>
<li><a href="http://sametmax.com/les-trucmuchables-en-python/">Les trucmuchables</a></li>
<li><a href="http://sametmax.com/ordonner-en-python/">Ordonner en Python</a></li>
<li><a href="http://sametmax.com/debugger-en-python-les-bases-de-pdb/">Les bases de pdb</a></li>
<li><a href="http://sametmax.com/si-vous-ne-savez-pas-ce-que-contient-une-variable-vous-ne-comprenez-pas-le-programme/">Si vous ne savez pas ce que contient une variable, vous ne comprenez pas le programme.</a></li>
<li><a href="http://sametmax.com/lencoding-en-python-une-bonne-fois-pour-toute/">L&#8217;encoding en python</a></li>
<li><a href="http://sametmax.com/comment-utiliser-yield-et-les-generateurs-en-python/">Les générateurs et le mot clé yield</a></li>
<li><a href="http://sametmax.com/operateur-splat-ou-etoile-en-python/">L’opérateur splat (l’étoile: *)</a></li>
<li><a href="http://sametmax.com/comprendre-les-decorateurs-python-pas-a-pas-partie-1/">Les décorateurs</a></li>
<li><a href="http://sametmax.com/les-context-managers-et-le-mot-cle-with-en-python/">Les context managers et le mot clé with</a></li>
<li><a href="http://sametmax.com/le-guide-ultime-et-definitif-sur-la-programmation-orientee-objet-en-python-a-lusage-des-debutants-qui-sont-rassures-par-les-textes-detailles-qui-prennent-le-temps-de-tout-expliquer-partie-1/">La programmation orientée objet</a></li>
<li><a href="http://sametmax.com/tres-grand-listing-des-libs-standard-partie-les-plus-utiles-en-python/">(Très) Grand listing des libs standards les plus utiles</a></li>
</ul>


feed_id: http://sametmax.com/?p=15659
title: S’assurer que SELinux ne bloque pas un programme 7
uri: S-assurer-que-SELinux-ne-bloque-pas-un-programme-7
url: http://sametmax.com/sassurer-que-selinux-ne-bloque-pas-un-programme/
content:
<p>Les distros Linux récentes viennent souvent avec des surcouches de protections type policykit, apparmor, SELinux, etc.</p>
<p>Tout ça est bien loin de la simplicité de la notion user/group et leurs permissions, et peut mener à un arrachage de cheveux en règle. </p>
<p>Cette après midi par exemple, on avait notre backend qui ne répondait pas sur le serveur tout neuf. On a changé toutes les permissions, passé de <code>sock://</code> à <code>http://</code>, tweaké les fichiers de settings de iptables, varnish, nginx, gunicorn, supervisor, django&#8230; Puis en dernier recours, on a viré toutes les couches une par une, desinstaller les programmes, réinstaller à neuf, reset les fichiers de config en valeur par défaut, créé des fichiers de config minimaux pour toute la stack, nada. La journée frustrante et foutue en l&#8217;air.</p>
<p>On a quand même isolé le point de blocage sur varnish, et après avoir fait tous les tests possibles et des sacrifices humains, Max a eu l&#8217;intuition SELinux.</p>
<p>Voici maintenant ce qui se passe généralement dans cette situation.</p>
<p>Dans un élan de colère, l&#8217;utilisateur impatient fera un rapide test pour savoir si SELinux le protège comme les USA ont protégé les irakiens :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #000000;">0</span> <span style="color: #000000; font-weight: bold;">&gt;/</span>selinux<span style="color: #000000; font-weight: bold;">/</span>enforce</pre></td></tr></table></div>

<p>Ça désactive tout le bouzin jusqu&#8217;au prochain reboot, mettre <code>1</code> inversant la tendance.</p>
<p>Lançant son programme et voyant que ça marche, notre dev échaudé se fend de l&#8217;équivalent du <code>chmod 777 -R</code> pour SELinux, à savoir éditer le fichier de config (<code>/etc/sysconfig/selinux</code> sur Centos) et changer rageusement <code>SELINUX=enforcing</code> pour <code>SELINUX=disabled</code>. Reboot and forget.</p>
<p>Une solution radicale et efficace, certes, mais qui laisse quand même un petit poids sur le conscience : diantre, il y a sûrement un moyen propre d&#8217;essuyer toute cette merde. Où sont les 3 coquillages ?</p>
<p>La solution est dans un petit programme appelé <code>audit2allow</code>, qui fait parti d&#8217;un package plus gros qu&#8217;il vous faudra trouver pour votre OS. Sous CentOs, puisque c&#8217;était notre config ce jour là, on a du faire un petit :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">yum install</span> policycoreutils-python</pre></td></tr></table></div>

<p>Ensuite, on lance notre audit :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">audit2allow <span style="color: #660033;">-a</span> <span style="color: #660033;">-w</span></pre></td></tr></table></div>

<p>Et après un peu de moulinage, il va vous sortir tout un listing de blocage, et quoi faire pour s&#8217;en sortir. Un petit <code>grep votre_prog</code> sur la sortie et vous obtenez ceci :</p>
<pre>type=AVC msg=audit(1331500393.450:25): avc:  denied  { name_connect } for  pid=1276 comm="varnishd" dest=81 scontext=unconfined_u:system_r:varnishd_t:s0 tcontext=system_u:object_r:reserved_port_t:s0 tclass=tcp_socket
        Was caused by:
        One of the following booleans was set incorrectly.
        Description:
        Allow varnishd to connect to all ports, not just HTTP.

        Allow access by executing:
        # setsebool -P varnishd_connect_any 1
        Description:
        Allow system to run with NIS

        Allow access by executing:
        # setsebool -P allow_ypbind 1</pre>
<p>Nous, c&#8217;était varnish qui était bloqué, comme le confirme le discret <strong>denied</strong> dans ce gros blog d&#8217;informations illisibles. A croire que les gars de SELinux ont tout fait pour créer la techno la moins user friendly possible. Je pense que la ligne ne commence pas par &#8220;AVC&#8221; pour rien, chaque fois que SELinux bloque un truc, un devops stagiaire meurt quelque part.</p>
<p>Il suffit ensuite de suivre docilement les instructions. Pour ce cas, on rentre avec les droits admin la commande :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">setsebool <span style="color: #660033;">-P</span> varnishd_connect_any <span style="color: #000000;">1</span></pre></td></tr></table></div>

<p>Et on est bon. </p>
<p>Enfin, jusqu&#8217;à la prochaine après midi de debug incompréhensible qui vous fera revenir à SELinux. Max est beaucoup tenté par la solution 1 pour éviter une nouvelle galère. </p>


feed_id: http://sametmax.com/?p=15665
title: Les managers le détestent : faites tourner WAMP dans Django avec cette astuce insolite 9
uri: Les-managers-le-détestent-faites-tourner-WAMP-dans-Django-avec-cett
url:
http://sametmax.com/les-managers-le-detestent-faites-tourner-wamp-dans-django-avec-cette-astuce-insolite/

content:
<p>Il existe une lib appelée <a href="https://pypi.python.org/pypi/crochet">crochet</a> qui permet de faire marcher des API de twisted entre deux bouts de code bloquants. Certes, ça ne marche qu&#8217;en 2.7 et c&#8217;est pas hyper performant, mais on peut faire des trucs mignons du genre cette démo qui <a href="https://github.com/tavendo/AutobahnPython/tree/master/examples/twisted/wamp/app/crochet/example1">mélange flask et WAMP</a>.</p>
<p>C&#8217;est du pur Python, pas de process externe à gérer, c&#8217;est presque simple.</p>
<p>Bref, si on veut utiliser WAMP avec une app synchrone comme flask, c&#8217;est un bon moyen de s&#8217;y mettre. On aura jamais des perfs fantastiques, mais on peut pusher vers le browser.</p>
<p>Du coup je me suis demandé si on pouvait faire ça avec Django.</p>
<p>Évidement, ça a été un peu plus compliqué car par défaut <code>runserver</code> lance plusieurs workers et fait un peu de magie avec les threads. Mais après un peu de bidouillage, ça marche !</p>
<p>On peut utiliser WAMP, <code>directement</code> dans Django.</p>
<h2>Suivez le guide</h2>
<p>D&#8217;abord, on installe tout le bouzin (python 2.7, souvenez-vous) :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">pip <span style="color: #c20cb9; font-weight: bold;">install</span> crossbar crochet django</pre></td></tr></table></div>

<p>Il vous faudra un Django 1.7, le tout dernier, car il possède <a href="https://docs.djangoproject.com/en/dev/ref/applications/#django.apps.AppConfig.ready">une fonctionnalité</a> qui nous permet de lancer du code quand tout le framework est chargé.</p>
<p>Vous vous faites votre projet comme d&#8217;hab, et vous ouvrez le fichier de settings et au lieu de mettre votre app dans <code>INSTALLED_APPS</code>, vous rajoutez ça :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">INSTALLED_APPS <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span>
    <span style="color: #483d8b;">'...'</span><span style="color: #66cc66;">,</span>
    <span style="color: #483d8b;">'votreapp.app.VotreAppConfig'</span>
<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Puis dans le module de votre app, vous créez un fichier app.py, qui va contenir ça:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> crochet
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">apps</span> <span style="color: #ff7700;font-weight:bold;">import</span> AppConfig
&nbsp;
<span style="color: #808080; font-style: italic;"># On charge l'objet contenant la session WAMP définie dans la vue</span>
<span style="color: #ff7700;font-weight:bold;">from</span> votreapp.<span style="color: black;">views</span> <span style="color: #ff7700;font-weight:bold;">import</span> wapp
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> VotreAppConfig<span style="color: black;">&#40;</span>AppConfig<span style="color: black;">&#41;</span>:
    name <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'votreapp'</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> ready<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># On dit a crochet de faire tourner notre app wamp dans sa popote qui</span>
        <span style="color: #808080; font-style: italic;"># isole le reactor de Twisted</span>
        <span style="color: #66cc66;">@</span>crochet.<span style="color: black;">run_in_reactor</span>
        <span style="color: #ff7700;font-weight:bold;">def</span> start_wamp<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
           <span style="color: #808080; font-style: italic;"># On démarre la session WAMP en se connectant au serveur</span>
           <span style="color: #808080; font-style: italic;"># publique de test</span>
           wapp.<span style="color: black;">run</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;wws://demo.crossbar.io/ws&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;realm1&quot;</span><span style="color: #66cc66;">,</span> start_reactor<span style="color: #66cc66;">=</span><span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
        start_wamp<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>On passe à urls.py dans lequel on se rajoute des vues de démo :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">    url<span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^ping/'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'votreapp.views.ping'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span>
    url<span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^$'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'votreapp.views.index'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Puis dans notre fichier views.py, on met :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> uuid
&nbsp;
<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> render
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> crochet
&nbsp;
<span style="color: #808080; font-style: italic;"># Crochet se démerde pour faire tourner le reactor twisted de</span>
<span style="color: #808080; font-style: italic;"># manière invisible. A lancer avant d'importer autobahn</span>
crochet.<span style="color: black;">setup</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> autobahn.<span style="color: black;">twisted</span>.<span style="color: black;">wamp</span> <span style="color: #ff7700;font-weight:bold;">import</span> Application
&nbsp;
<span style="color: #808080; font-style: italic;"># un objet qui contient une session WAMP</span>
wapp <span style="color: #66cc66;">=</span> Application<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On enrobe les primitives de WAMP pour les rendre synchrones</span>
<span style="color: #66cc66;">@</span>crochet.<span style="color: black;">wait_for</span><span style="color: black;">&#40;</span>timeout<span style="color: #66cc66;">=</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> publish<span style="color: black;">&#40;</span>topic<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> wapp.<span style="color: black;">session</span>.<span style="color: black;">publish</span><span style="color: black;">&#40;</span>topic<span style="color: #66cc66;">,</span> *args<span style="color: #66cc66;">,</span> **kwargs<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">@</span>crochet.<span style="color: black;">wait_for</span><span style="color: black;">&#40;</span>timeout<span style="color: #66cc66;">=</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> call<span style="color: black;">&#40;</span>name<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> wapp.<span style="color: black;">session</span>.<span style="color: black;">call</span><span style="color: black;">&#40;</span>name<span style="color: #66cc66;">,</span> *args<span style="color: #66cc66;">,</span> **kwargs<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> register<span style="color: black;">&#40;</span>name<span style="color: #66cc66;">,</span> *args<span style="color: #66cc66;">,</span> **kwargs<span style="color: black;">&#41;</span>:
    <span style="color: #66cc66;">@</span>crochet.<span style="color: black;">run_in_reactor</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> decorator<span style="color: black;">&#40;</span>func<span style="color: black;">&#41;</span>:
        wapp.<span style="color: black;">register</span><span style="color: black;">&#40;</span>name<span style="color: #66cc66;">,</span> *args<span style="color: #66cc66;">,</span> **kwargs<span style="color: black;">&#41;</span><span style="color: black;">&#40;</span>func<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> decorator
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> subscribe<span style="color: black;">&#40;</span>name<span style="color: #66cc66;">,</span> *args<span style="color: #66cc66;">,</span> **kwargs<span style="color: black;">&#41;</span>:
    <span style="color: #66cc66;">@</span>crochet.<span style="color: black;">run_in_reactor</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> decorator<span style="color: black;">&#40;</span>func<span style="color: black;">&#41;</span>:
        wapp.<span style="color: black;">subscribe</span><span style="color: black;">&#40;</span>name<span style="color: #66cc66;">,</span> *args<span style="color: #66cc66;">,</span> **kwargs<span style="color: black;">&#41;</span><span style="color: black;">&#40;</span>func<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> decorator
&nbsp;
<span style="color: #808080; font-style: italic;"># Et hop, on peut utiliser nos outils WAMP !</span>
&nbsp;
<span style="color: #66cc66;">@</span>register<span style="color: black;">&#40;</span><span style="color: #483d8b;">'uuid'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> get_uuid<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> uuid.<span style="color: black;">uuid4</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: #008000;">hex</span>
&nbsp;
<span style="color: #66cc66;">@</span>subscribe<span style="color: black;">&#40;</span><span style="color: #483d8b;">'ping'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> onping<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <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;">'test'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'w'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> f:
        f.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ping'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Et à côté, quelques vues django normales</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> index<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># pub et RPC en action côté Python</span>
    publish<span style="color: black;">&#40;</span><span style="color: #483d8b;">'ping'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> call<span style="color: black;">&#40;</span><span style="color: #483d8b;">'uuid'</span><span style="color: black;">&#41;</span>
&nbsp;
    <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;">'test'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> f:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>f.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</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: #66cc66;">,</span> <span style="color: #483d8b;">'index.html'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> ping<span style="color: black;">&#40;</span>request<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: #66cc66;">,</span> <span style="color: #483d8b;">'ping.html'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Après, un peu de templating pour que ça marche&#8230;</p>
<p>Index.html :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="html" style="font-family:monospace;">{% load staticfiles %}
&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot; /&gt;
    &lt;title&gt;
       UUID
    &lt;/title&gt;
&nbsp;
    &lt;script src=&quot;{% static 'autobahn.min.js' %}&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
      var connection = new autobahn.Connection({
         url: &quot;ws://localhost:8080/ws&quot;,
         realm: &quot;realm1&quot;
      });
&nbsp;
     connection.onopen = function (session) {
&nbsp;
        session.call(&quot;uuid&quot;).then(function (uuid) {
          var p = document.getElementById('uuid');
          p.innerHTML = uuid;
        });
     };
&nbsp;
     connection.open();
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h2&gt;UUID&lt;/h2&gt;
&lt;p id=&quot;uuid&quot;&gt;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</pre></td></tr></table></div>

<p>ping.html :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: black;">&#123;</span>% load staticfiles %<span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&lt;!</span>DOCTYPE html<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>html<span style="color: #66cc66;">&gt;</span>
  <span style="color: #66cc66;">&lt;</span>head<span style="color: #66cc66;">&gt;</span>
    <span style="color: #66cc66;">&lt;</span>meta charset<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;utf-8&quot;</span> /<span style="color: #66cc66;">&gt;</span>
    <span style="color: #66cc66;">&lt;</span>title<span style="color: #66cc66;">&gt;</span>
       Ping
    <span style="color: #66cc66;">&lt;</span>/title<span style="color: #66cc66;">&gt;</span>
&nbsp;
    <span style="color: #66cc66;">&lt;</span>script src<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;{% static 'autobahn.min.js' %}&quot;</span><span style="color: #66cc66;">&gt;&lt;</span>/script<span style="color: #66cc66;">&gt;</span>
    <span style="color: #66cc66;">&lt;</span>script <span style="color: #008000;">type</span><span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;text/javascript&quot;</span><span style="color: #66cc66;">&gt;</span>
      var connection <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">new</span> autobahn.<span style="color: black;">Connection</span><span style="color: black;">&#40;</span><span style="color: black;">&#123;</span>
         url: <span style="color: #483d8b;">&quot;ws://localhost:8080/ws&quot;</span><span style="color: #66cc66;">,</span>
         realm: <span style="color: #483d8b;">&quot;realm1&quot;</span>
      <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">;</span>
&nbsp;
     connection.<span style="color: black;">onopen</span> <span style="color: #66cc66;">=</span> function <span style="color: black;">&#40;</span>session<span style="color: black;">&#41;</span> <span style="color: black;">&#123;</span>
&nbsp;
        session.<span style="color: black;">subscribe</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;ping&quot;</span><span style="color: #66cc66;">,</span> function <span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: black;">&#123;</span>
          var ul <span style="color: #66cc66;">=</span> document.<span style="color: black;">getElementById</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ping'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">;</span>
          var li <span style="color: #66cc66;">=</span> document.<span style="color: black;">createElement</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'li'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">;</span>
          li.<span style="color: black;">innerHTML</span> <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'Ping !'</span>
          ul.<span style="color: black;">appendChild</span><span style="color: black;">&#40;</span>li<span style="color: black;">&#41;</span><span style="color: #66cc66;">;</span>
        <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">;</span>
     <span style="color: black;">&#125;</span><span style="color: #66cc66;">;</span>
&nbsp;
     connection.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">;</span>
    <span style="color: #66cc66;">&lt;</span>/script<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>/head<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>body<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>h2<span style="color: #66cc66;">&gt;</span>Ping me <span style="color: #66cc66;">!&lt;</span>/h2<span style="color: #66cc66;">&gt;</span>
&nbsp;
<span style="color: #66cc66;">&lt;</span>ul <span style="color: #008000;">id</span><span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;ping&quot;</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>/ul<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>/body<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>/html<span style="color: #66cc66;">&gt;</span></pre></td></tr></table></div>

<p>On ouvre la console, on lance son routeur :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">    crossbar init
    crossbar start</pre></td></tr></table></div>

<p>On lance dans une autre console son serveur Django :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">.<span style="color: #000000; font-weight: bold;">/</span>manage.py runserver</pre></td></tr></table></div>

<p>Et si on navigue sur <code>http://127.0.0.1:8000</code>, on récupère un UUID tout frais via RCP.</p>
<p>On peut aussi voir dans le shell que ça marche côté Python :</p>
<pre>94cfccf0899d4c42950788fa655b65ed
ping</pre>
<p>D’ailleurs un fichier nommé &#8220;test&#8221; est créé à la racine du projet.</p>
<p>Et si on navigue sur <code>http://127.0.0.1:8000/ping/</code> et qu&#8217;on refresh <code>http://127.0.0.1:8000</code> plusieurs fois, on voit la page se mettre à jour.</p>
<p>Achievement unlock : use WAMP and Django code in the same file.</p>
<h2>A partir de là</h2>
<p>Il y a plein de choses à faire.</p>
<p>On pourrait faire une lib qui wrap tout ça pour pas à avoir à le mettre dans son fichier de vue et qui utilise settings.py pour la configuration.</p>
<p>Il faut tester ça avec des setups plus gros pour voir comment ça se comporte avec gunicorn, plusieurs workers, le logging de Django, etc. Je suis à peu près sûr que les callbacks vont être registrés plusieurs fois et ça devrait faire des erreurs dans les logs (rien de grave ceci dit).</p>
<p>On pourrait aussi adapter le RPC pour qu&#8217;il utilise les cookies d&#8217;authentification Django, et pouvoir les protéger avec @login_required.</p>
<p>Mais un monde d&#8217;opportunités s&#8217;offrent à vous à partir de là.</p>
<p>Moi, ça fait 6 h que je taffe dessus, je vais me pieuter.</p>
<hr />
<p><a href="https://github.com/sametmax/codes-des-articles/tree/master/2015/janvier/wamp_et_django">Télécharger le code de l&#8217;article</a></p>


feed_id: http://sametmax.com/?p=10493
title: Black awk down 8
uri: Black-awk-down-5-Recently-updated
url: http://sametmax.com/black-awk-down/
content:
<blockquote><p>Ceci est un post invité de <a href="http://sametmax.com/author/foX" target="_blank">foX </a>posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/" target="_blank">creative common 3.0 unported</a>.</p></blockquote>
<h2>Introduction (sans douleur)</h2>
<p>Qui n&#8217;a jamais rêvé d&#8217;avoir un shell Unix un peu plus pythonic ? Les oneliners en <a href="http://fr.wikipedia.org/wiki/Stream_Editor" title="sed">sed</a> et <a href="http://fr.wikipedia.org/wiki/Awk" title="Awk">Awk</a> bien chiadés, c&#8217;est l&#8217;apanage des grands barbus en sandales et ça déchire, mais ça reste cryptique et la manipulation de liste et de chaînes de caractères est tout de même limitée. On peut dégainer perl en one line, comme ça c&#8217;est encore plus puissant mais moins lisible&#8230;</p>
<p>Et python dans tout ça ? En oneliner, ça craint, car le principe d&#8217;indentation ne facilite pas les choses et on finit avec une imbrication de bazar de parenthèses illisible.</p>
<p>La solution ? Pour se faire plaisir : une bonne pyp. Le bidule s&#8217;installe avec&#8230; pip (c&#8217;est une méta pipe).</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">pip <span style="color: #c20cb9; font-weight: bold;">install</span> pyp</pre></td></tr></table></div>

<p>pyp (<a href="http://code.google.com/p/pyp/" title="pyp">Python Power at the Prompt</a>) va enchanter votre shell unix et vous envoyer au 7ème ciel. Petit tour d&#8217;horizon de la merveille.</p>
<h2>Pyp et les strings</h2>
<p>C&#8217;est la base quand on bricole des oneliners en shell, tripoter des strings.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #000000; font-weight: bold;">*</span>JPG <span style="color: #000000; font-weight: bold;">|</span> pyp <span style="color: #ff0000;">&quot;'mv', p, p.replace('JPG', 'jpg')&quot;</span></pre></td></tr></table></div>

<p>Revoyons l&#8217;action au ralenti : </p>
<ul>
<li>ls *JPG va nous lister tous les fichiers qui finissent par JPG dans le dossier courant.</li>
<li>Ensuite on envoie cela dans pyp avec un pipe Unix. Celui-ci va composer une ligne de commande qui est la concaténation d&#8217;une commande unix (mv pour renommer un fichier), ce qu&#8217;on aura reçu en entrée (qui s&#8217;appelle par convention &#8220;p&#8221;) et une version modifiée de p où l&#8217;on remplace JPG par jpg.</li>
</ul>
<p>On voit ici que l&#8217;on utilise la méthode replace de la classe str python. On peut utiliser n&#8217;importe quelle méthode de str : lower, upper, title, strip(tease), count etc. Avec des petits bonus comme refindall(re) :-)</p>
<p>Ça donne quoi ma brave dame ? Et bien si on avait des fichiers appelés porn1.JPG et ass.JPG notre jolie commande renverrait :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">mv</span> porn1.JPG porn1.jpg
<span style="color: #c20cb9; font-weight: bold;">mv</span> ass.JPG ass.jpg</pre></td></tr></table></div>

<p>Ok, bien gentil me direz-vous, mais qu&#8217;en fait-on ? Et bien ou l&#8217;on pipe ça dans le shell ( | sh) ou alors on passe l&#8217;argument -x (ou &#8211;execute) à pyp ou directement exécuter le résultat.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #000000; font-weight: bold;">*</span>JPG <span style="color: #000000; font-weight: bold;">|</span> pyp <span style="color: #ff0000;">&quot;'mv', p, p.replace('JPG', 'jpg')&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sh</span>
<span style="color: #666666; font-style: italic;"># ou bien</span>
<span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #000000; font-weight: bold;">*</span>JPG <span style="color: #000000; font-weight: bold;">|</span> pyp <span style="color: #660033;">-x</span> <span style="color: #ff0000;">&quot;'mv', p, p.replace('JPG', 'jpg')&quot;</span></pre></td></tr></table></div>

<p>Pourquoi on aime bien python ? Car il slice le bread comme un chef. Pyp aussi, oeuf corse, quelques exemples :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;sam-et-max&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> pyp <span style="color: #ff0000;">&quot;p.split('-')[2]&quot;</span>
<span style="color: #666666; font-style: italic;"># max</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># La même chose en plus court. Le m, comme minus, sous-entend qu'on split sur &quot;-&quot;</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;sam-et-max&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> pyp <span style="color: #ff0000;">&quot;m[2]&quot;</span>
<span style="color: #666666; font-style: italic;"># max</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;sam-et-max&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> pyp <span style="color: #ff0000;">&quot;m[0], m[2]&quot;</span>
<span style="color: #666666; font-style: italic;"># sam max</span></pre></td></tr></table></div>

<p>Comme vous avez vu, il y a un petit raccourci sympa avec m (comme minus) au lieu de p. C&#8217;est pas fini, vous en avez d&#8217;autres : d (dot) pour un point, w (whitespace) pour une espace, u pour underscore, s pour slash&#8230; Ils ont pensé à tout.</p>
<h2>Des pyp à la chaîne</h2>
<p>On tout de suite envie de remettre le couvert avec une autre pyp. C&#8217;est possible et même encouragé. Le symbole utilisé est le pipe unix | dans une commande pyp. Ce n&#8217;est donc pas un pipe du shell mais un pipe interne de pyp. Vous suivez ? Un petit exemple :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;sam et max&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> pyp <span style="color: #ff0000;">&quot;w[0] | 'avant : ', o, 'après :', p&quot;</span>
<span style="color: #666666; font-style: italic;"># avant :  sam et max après : sam</span></pre></td></tr></table></div>

<p>Le p représente toujours le paramètre courant. Donc dans la seconde partie du pipe, c&#8217;est le premier élément de la liste issu du split de la chaîne &#8220;sam et max&#8221; sur l&#8217;espace (w comme whitespace). Vous suivez toujours ? Oui, bon. Et donc le o ? Et bien c&#8217;est le paramètre d&#8217;origine non modifié. Et il y a h (comme history ou comme hâlibi !) pour avoir le paramètre p à toutes les étapes de la chaîne de pipe&#8230; Beaucoup de puissance on vous dit !</p>
<p>On peut aussi rouler^w faire des join facilement avec les mêmes raccourcis. Par exemple on split sur les espaces puis join sur slash :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;sam et max aiment le lourd en fin de soirée&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> pyp <span style="color: #ff0000;">&quot;w[:6]|s&quot;</span>
<span style="color: #666666; font-style: italic;"># sam/et/max/aiment/le/lourd</span></pre></td></tr></table></div>

<h2>Une liste de pyp avec une belle pp</h2>
<p>S&#8217;il y a un bien un truc qui envoie du bois avec python, c&#8217;est la gestion des listes. Pyp n&#8217;est pas en reste. C&#8217;est pp qui contient les listes. En avant :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #000000; font-weight: bold;">|</span> pyp <span style="color: #ff0000;">&quot;pp[3]&quot;</span>
<span style="color: #666666; font-style: italic;"># Affiche le troisième fichier</span></pre></td></tr></table></div>

<p>On peut utiliser toutes les méthodes standards de la classe list (sort, count etc.) plus quelques bonus :</p>
<p># Équivalent de | sort | uniq</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #000000; font-weight: bold;">|</span> pyp <span style="color: #ff0000;">&quot;pp.uniq()&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Additionne tous les PID des process de machine.</span>
<span style="color: #666666; font-style: italic;"># Ça ne sert à rien, mais c'est un exemple hein ?</span>
<span style="color: #c20cb9; font-weight: bold;">ps</span> <span style="color: #660033;">-ef</span> <span style="color: #000000; font-weight: bold;">|</span> pyp <span style="color: #ff0000;">&quot;w[1] | int(p) | sum(pp)&quot;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Voilà qui est plus utile. </span>
<span style="color: #666666; font-style: italic;"># Au passage, on note que la ligne d'en-tête est ignoré et ne fait pas planter pyp.</span>
<span style="color: #666666; font-style: italic;"># Malin le lapin.</span>
<span style="color: #c20cb9; font-weight: bold;">df</span> <span style="color: #660033;">-m</span> <span style="color: #000000; font-weight: bold;">|</span> pyp <span style="color: #ff0000;">&quot;w[1] | int(p) | sum(pp)&quot;</span></pre></td></tr></table></div>

<h2>pyp au naturel</h2>
<p>Pour compléter les fonctions python, pyp propose quelques fonctions maisons tout à fait sympathiques. Florilège :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Sam Bill Max&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> pyp <span style="color: #ff0000;">&quot;p.kill('Bill')&quot;</span>  <span style="color: #666666; font-style: italic;"># quand c'est pas bill, c'est kenny...</span>
<span style="color: #666666; font-style: italic;"># Sam  Max</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #000000;">124</span> <span style="color: #000000; font-weight: bold;">|</span> pyp <span style="color: #ff0000;">&quot;(int(p)/2+30)&quot;</span>
<span style="color: #666666; font-style: italic;"># 91</span>
&nbsp;
<span style="color: #c20cb9; font-weight: bold;">ls</span>  <span style="color: #000000; font-weight: bold;">|</span> pyp <span style="color: #ff0000;">&quot;n, p&quot;</span>
<span style="color: #666666; font-style: italic;"># Liste des fichiers avec un numéro croissant devant</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>fox<span style="color: #000000; font-weight: bold;">/</span>video<span style="color: #000000; font-weight: bold;">/</span>gangbang.avi  <span style="color: #000000; font-weight: bold;">|</span> pyp <span style="color: #ff0000;">&quot;'Dir='+p.dir, '<span style="color: #000099; font-weight: bold;">\n</span>File='+p.file, '<span style="color: #000099; font-weight: bold;">\n</span>Ext='+p.ext&quot;</span> <span style="color: #666666; font-style: italic;"># basename, dirname et ses amis</span>
<span style="color: #666666; font-style: italic;"># Dir=/home/fox/video </span>
<span style="color: #666666; font-style: italic;"># File=gangbang.avi </span>
<span style="color: #666666; font-style: italic;"># Ext=avi</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># On définit le séparateur de liste comme l'espace, </span>
<span style="color: #666666; font-style: italic;"># puis on regroupe la liste par deux élément</span>
<span style="color: #666666; font-style: italic;"># et enfin on fait un join sur le caractère tiret (minus)</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;1 2 3 4 5 6&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> pyp <span style="color: #ff0000;">&quot;pp.delimit(' ') | pp.divide(2) | m&quot;</span>
<span style="color: #666666; font-style: italic;"># 1-2</span>
<span style="color: #666666; font-style: italic;"># 3-4</span>
<span style="color: #666666; font-style: italic;"># 5-6</span>
&nbsp;
<span style="color: #c20cb9; font-weight: bold;">ps</span> <span style="color: #660033;">-ef</span> <span style="color: #000000; font-weight: bold;">|</span> pyp <span style="color: #ff0000;">&quot;w[1] | int(p) | max(pp)&quot;</span> 
<span style="color: #666666; font-style: italic;"># (le PID le plus grand)</span></pre></td></tr></table></div>

<h2>pyp en intention ou intention de pyp ?</h2>
<p>Il ne faut pas se gêner, on peut utiliser les excellentes <a href="http://sametmax.com/python-love-les-listes-en-intention-partie/" title="Listes en intention">listes en intention</a> de Python.  Voici tous les PID impaires :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">ps</span> <span style="color: #660033;">-ef</span> <span style="color: #000000; font-weight: bold;">|</span> pyp <span style="color: #ff0000;">&quot;w[1] | int(p) | [i for i in pp if i%2] | p &quot;</span></pre></td></tr></table></div>

<h2>L&#8217;industrie de la pyp c&#8217;est un truc de macro</h2>
<p>Les bonnes choses, ça se garde, alors voilà :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">ps</span> <span style="color: #660033;">-ef</span> <span style="color: #000000; font-weight: bold;">|</span> pyp <span style="color: #ff0000;">&quot;w[1] | int(p) | [i for i in pp if i%2] | p &quot;</span> <span style="color: #660033;">-s</span> odd  <span style="color: #666666; font-style: italic;"># on enregistre la macro 'odd'</span>
&nbsp;
<span style="color: #c20cb9; font-weight: bold;">ps</span> ef <span style="color: #000000; font-weight: bold;">|</span> pyp odd <span style="color: #666666; font-style: italic;"># c'est aussi simple que cela ;-)</span></pre></td></tr></table></div>

<h2>pyp sur grand écran</h2>
<p>Cette petite pépite est développée par Sony Pictures Imageworks pour ses besoins internes. Le développement n&#8217;est pas très collaboratif (un commit par release&#8230;) mais reste ouvert aux contributions externes. C&#8217;est sous une licence de type BSD.<br />
Les loulous ont fait une jolie vidéo de tutorial très bling bling. C&#8217;est l&#8217;avantage de bosser dans le milieu : </p>
<p><span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='1170' height='689' src='http://www.youtube.com/embed/eWtVWF0JSJA?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0' allowfullscreen='true'></iframe></span></p>
<h2>Et bien plus encore&#8230;</h2>
<p>Cet outil merveilleux possède encore des fonctionnalités qui vont vous le faire adorer comme son mode interactif avec une coloration syntaxique sympathique, la gestion de l&#8217;historique dans le pipe et beaucoup d&#8217;autres. Adieu sed, awk, uniq, sort et con sort, vous étiez mes premiers amours, mais pyp vous chasse dehors.</p>
<p>Ce n&#8217;est pas la seule ni la première tentative de faire la peau d&#8217;awk avec python. Sam avait déjà écrit <a href="http://sametmax.com/remplacer-sed-awk-cut-et-perl-par-python-orgasme-pour-sysadmin/" title="une pyped pour Sam">un article </a>sur une autre solution aussi appelée pyped.</p>
<h2> C&#8217;est donc parfait ? </h2>
<p>Oui, bien entendu. Aucun défaut, aucun bug. Ok&#8230; voici les limites : </p>
<ul>
<ol>Perf de daube. Sur des petits volumes (quelques milliers de lignes) ça le fait. Au delà, ça rame. Quelques patch sont proposés pour diviser par trois le temps de traitement :-)</ol>
<ol>Conso mémoire obcène. Idem, pour des petits volumes on s&#8217;en fout, mais sinon ça peut rapidement chiffrer. Pourquoi ? Le machin ne fonctionne pas en stream, tout est gardé en mémoire et à chaque étape de transformation (pour permettre d&#8217;accéder à l&#8217;historique).</ol>
<ol>C&#8217;est installé sur votre pc, mais pas partout, contrairement à ce bon vieux awk. </ol>
</ul>
<p>Amusez vous bien, celui qui fait la plus jolie commande pyp dans les commentaires aura le droit à un bisous.</p>


feed_id: http://sametmax.com/?p=15682
title: Conclusions de la migration 10 Recently updated !
uri: Conclusions-de-la-migration-5-Recently-updated
url: http://sametmax.com/conclusions-de-la-migration/
content:
<p>La migration de serveur est terminée. Le blog, le <a href="http://multiboards.net">multiboards</a>, <a href="http://indexerror.net">IndexError</a> et <a href="http://0bin.net">0bin</a> on été rétablis. On en a profité pour remettre sur pied <a href="http://allthatcounts.net">AllThatCounts</a> qui avait été délaissé durant le dernier crash.</p>
<p>On quitte donc <a href="https://www.leaseweb.com/">LeaseWeb</a>, qui nous a forcé à migré 3 fois avec ses machines qui ont planté. En plus deux fois la partition <code>/tmp</code> était corrompue, ce qui rend le backup particulièrement compliqué. On notera que leur SAV nous posait des questions du genre &#8220;si vous installez ça, et lancez cette commande, ça donne quoi ?&#8221;, alors qu&#8217;on leur a bien notifié qu&#8217;on avait un disque monté en lecture seul du fait du FS en vrac&#8230;</p>
<p>On est passé chez <a href="http://www.cinfu.com/vps/">Cinfu</a>, car on peut les payer en Bitcoin. Livraison du serveur rapide, installation sans histoire, et finalement une migration beaucoup moins chiante que la dernière fois car on a fait les gros bourrins : <code>rsync</code> + <code>mysqldump</code> bien large. Ce qui a pris le plus de temps c&#8217;était de résoudre les centaines de problèmes de permissions que ça a créé, les trucs que ça aurait pas du écraser, etc.</p>
<p>On avait + de 100000 spams dans la poubelle des commentaires, qui prenaient 300 Mo des 400 mo de la taille totale de la BDD du blog. Un petit :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">DELETE</span> <span style="color: #993333; font-weight: bold;">FROM</span> wp_comments <span style="color: #993333; font-weight: bold;">WHERE</span> comment_approved <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'trash'</span>;</pre></td></tr></table></div>

<p>A accéléré la migration vu qu&#8217;on a du transférer la base 3 fois et la réimporter autant à cause d&#8217;erreurs diverses. Note à nous-même : arrêter de mettre des <code>.bak</code> dans <code>/tmp</code> parce que c&#8217;est &#8220;juste pour 5 minutes&#8221;. Après on se fait avoir comme des débutants au reboot. </p>
<p>C&#8217;est là qu&#8217;on voit qu&#8217;on est dev, et pas admin.</p>
<p>Rajouter dans wp-config.php :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'EMPTY_TRASH_DAYS'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">30</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Nous évitera d&#8217;avoir à repenser à tout ça. C&#8217;est con mais faut le savoir.</p>
<p>J&#8217;en profite pour témoigner mon amour immodéré pour <a href="https://mosh.mit.edu/">mosh</a>. Parce que faire tout ça sur une connexion thai avec 300ms de ping minimum et une coupure toutes les 10 minutes, avec SSH, c&#8217;est juste un enfer.</p>
<p>Sous Centos, faut installer les repos <code>EPEL</code> et <code>yum install mosh</code> derrière.</p>
<p>Sous Ubuntu, fait installer le ppa <code>ppa:keithw/mosh</code> et <code>apt-get install mosh</code> derrière.</p>
<p>Certains serveurs ont un pare feu tatillon, et il faut rajouter dans la section <code>:RH-Firewall-1-INPUT - [0:0]</code> de iptable :</p>
<p><code>-A RH-Firewall-1-INPUT -p udp --dport 60000:61000 -j ACCEPT</code></p>
<p>D&#8217;autres ont des problèmes de locales:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">apt-get install --reinstall language-pack-fr
dpkg-reconfigure locales</pre></td></tr></table></div>

<p>Parfois y a aucun problème. C&#8217;est juste qu&#8217;on a pas un parc homogène, avec des bécanes vieilles de 1000 ans, alors forcément&#8230;</p>
<p>Mais Max a fait des devis, et si on passe au cloud avec les 2G/s de BP et les To de disque dur qu&#8217;on consomme, on multiplie les prix par 10 d&#8217;hébergement. Faire les trucs à la main, c&#8217;est chiant, mais c&#8217;est économe.</p>
<p>Pour mosh, pas de serveur à lancer, juste remplacer <code>ssh</code> par <code>mosh</code> dans la commande quand on se connecte. Des fois je lance avec <code>--predict=experimental</code> car je suis impatient et le retour de frappe est plus rapide, mais le cursor fait des mouvements bizarres, faut s&#8217;habituer.</p>
<p>Bon, on retourne faire des trucs plus productifs.</p>


