# articles

feed_id: http://sametmax.com/?p=22404
title: Le don du mois : nuitka, bis Recently updated !
uri: Le-don-du-mois-nuitka-bis-Recently-updated
url: http://sametmax.com/le-don-du-mois-nuitka-bis/
content:
<p>Ça faisait un bail que j&#8217;avais pas parlé d&#8217;un don du mois. Le don du mois n&#8217;est pas un don mensuel, mais un don que je fais pour le mois. Des fois j’oublie. Des fois je n&#8217;ai pas de thune. Des fois je ne me sens pas généreux, que l&#8217;humanité aille crever dans sa crasse !</p>
<p>Mais quand les astres du pognon et de la bonne humeur sont alignés je m&#8217;y remets.</p>
<p>J&#8217;ai pris des nouvelles de <a href="http://nuitka.net/">nuitka</a>, un outil qui permet de compiler du code Python en un exe indépendant. Malgré le fait que l&#8217;auteur soit visiblement le seul à vraiment travailler dessus, le projet continue d&#8217;avancer avec régularité et détermination. Corrections de bugs, optimisation (amélioration de la comptabilité (la 3.5 est supportée, la 3.6 en cours !)).</p>
<p>J&#8217;ai été agréablement surpris de voir que l&#8217;outil s&#8217;était encore amélioré. <a href="http://nuitka.net/doc/user-manual.html#use-case-1-program-compilation-with-all-modules-embedded">Le hello world stand alone</a> m&#8217;a pris quelques minutes à mettre en œuvre, d&#8217;autant que nuitka est dans les dépôts Ubuntu donc l&#8217;installation ne demande aucun effort.</p>
<p>Comme pouvoir shipper du code Python sans demander à l&#8217;utilisateur final d&#8217;installer Python est quelque chose qui est en forte demande en ce moment, j&#8217;ai voulu soutenir le projet, et j&#8217;ai fait <a href="http://nuitka.net/pages/donations.html">un don</a> de 50 euros.</p>
<p>Puis je me suis souvenu qu&#8217;en fait, <a href="http://sametmax.com/le-don-du-mois-nuitka/">j&#8217;en avais déjà fait un</a> l&#8217;année dernière :) Bah, l&#8217;auteur mérite qu&#8217;on le soutienne. Des mecs comme ça y en a pas des masses.</p>


feed_id: http://sametmax.com/?p=22463
title: Proposition d’un mot clé pour l’évaluation paresseuse en Python 3.7 Recently updated !
uri: Proposition-d-un-mot-clé-pour-l-évaluation-paresseuse-en-Python
url: http://sametmax.com/proposition-dun-mot-cle-pour-levaluation-paresseuse-en-python-3-7/
content:
<p>Si il y a bien une mailing-list à suivre, c&#8217;est <a href="https://mail.python.org/mailman/listinfo/python-dev">Python-dev</a>. Elle regorge de tout, on est y apprend sans cesse à propos de Python, la programmation en général, la gestion de communautés, etc. Mais c&#8217;est accessible pour peu qu&#8217;on soit à l&#8217;aise en anglais.</p>
<p>Parmi les sujets chauds du moment, il y a l&#8217;introduction, pour potentiellement Python 3.7, d&#8217;un mot clé pour évaluer paresseusement les expressions.</p>
<p>Je m&#8217;explique&#8230;</p>
<p>On a déjà plusieurs moyens de faire du lazy loading en python :</p>
<ul>
<li>Le <a href="http://sametmax.com/quelques-astuces-a-propos-de-and-et-or/">shortcut</a> des opérateurs <code>and</code> et <code>or</code>. La partie droite ne s&#8217;exécute que si la gauche ne répond pas déjà à la question.</li>
<li>Les <a href="http://sametmax.com/comment-utiliser-yield-et-les-generateurs-en-python/">générateurs</a>. Il ne sont évalués qu&#8217;au premier appel de <code>next()</code>.</li>
<li><code>await</code> : évalué seulement quand la boucle d&#8217;événement décide de passer par là.</li>
</ul>
<p>La nouvelle proposition est quelque chose de différent : permettre de déclarer une expression arbitraire, mais qui n&#8217;est évaluée que la première fois qu&#8217;on la lit.</p>
<p>Ca 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> somme<span style="color: black;">&#40;</span>a<span style="color: #66cc66;">,</span> b<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;">'coucou'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> a + b
&nbsp;
truc <span style="color: #66cc66;">=</span> lazy somme<span style="color: black;">&#40;</span>a<span style="color: #66cc66;">,</span> b<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;Hello&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>truc<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Ce qui afficherait:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">Hello
coucou
<span style="color: #ff4500;">3</span></pre></td></tr></table></div>

<p>On peut mettre ce qu&#8217;on veut après le mot clé <code>lazy</code>. Le code n&#8217;est exécuté qu&#8217;une fois qu&#8217;on essaye d&#8217;utiliser la variable <code>truc</code>.</p>
<p>L&#8217;usage essentiel, c&#8217;est de pouvoir déclarer du code sans chichi, comme si on allait l&#8217;utiliser maintenant. Le passer à du code qui va l&#8217;utiliser sans même avoir besoin de savoir que c&#8217;est un truc spécial. Et que tout marche à la dernière minute naturellement.</p>
<p>Par exemple, la traduction d&#8217;un texte dans un code Python ressemble souvent à ç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;">from</span> <span style="color: #dc143c;">gettext</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">gettext</span> <span style="color: #ff7700;font-weight:bold;">as</span> _
...
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>_<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Thing to translate'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Mais dans Django on déclare un champ de modèle dont on veut pouvoir traduire le nom comme ceci :</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> django.<span style="color: black;">utils</span>.<span style="color: black;">translation</span> <span style="color: #ff7700;font-weight:bold;">import</span> ugettext_lazy
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Produit<span style="color: black;">&#40;</span>models.<span style="color: black;">Model</span><span style="color: black;">&#41;</span>:
    ...
    <span style="color: black;">price</span> <span style="color: #66cc66;">=</span> models.<span style="color: black;">IntegerField</span><span style="color: black;">&#40;</span>verbose_name<span style="color: #66cc66;">=</span>ugettext_lazy<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;price&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>La raison est qu&#8217;on déclare ce texte au démarrage du serveur, et on ne sait pas encore la langue dans laquelle on va le traduire. Cette information n&#8217;arrive que bien plus tard, quand un utilisateur arrive sur le site. Mais pour détecter toutes les chaînes à traduire, créer le fichier de traduction, construire le cache, etc., il faut pouvoir marquer la chaîne comme traductible à l&#8217;avance.</p>
<p>Django a donc codé <code>ugettext_lazy</code> et tout un procédé pour évaluer cette traduction uniquement quand une requête Web arrive et qu&#8217;on sait la langue de l&#8217;utilisateur.</p>
<p>Avec la nouvelle fonctionnalité, on pourrait juste faire:</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;">gettext</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">gettext</span> <span style="color: #ff7700;font-weight:bold;">as</span> _
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Produit<span style="color: black;">&#40;</span>models.<span style="color: black;">Model</span><span style="color: black;">&#41;</span>:
    ...
    <span style="color: black;">price</span> <span style="color: #66cc66;">=</span> models.<span style="color: black;">IntegerField</span><span style="color: black;">&#40;</span>verbose_name<span style="color: #66cc66;">=</span>lazy _<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;price&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Rien à coder nul part du côté de Django, rien à savoir de plus pour un utilisateur. Ça marche dans tous les cas pareil, pour tout le monde, dans tous les programmes Python.</p>
<p>Bref, j&#8217;aime beaucoup cette idée qui permet de s&#8217;affranchir de pas mal de wrappers pour plein de trucs, mais aussi beaucoup aider les débutants. En effet les nouveaux en programmations font généralement des architectures basiques : pas d&#8217;injection de dépendances, pas de factories, etc. Avec <code>lazy</code>, même si une fonction n&#8217;accepte pas une factory, on peut quand même passer quelque chose qui sera exécuté plus tard.</p>
<p>Évidement ça ne dispense pas les gens de faire ça intelligemment et d&#8217;attendre des <a href="http://sametmax.com/les-trucmuchables-en-python/">callables</a> en paramètre. Dans le cas de Django, une meilleure architecture accepterait un callable pour <code>verbose_name</code> par exemple.</p>
<p>Mais c&#8217;est un bon palliatif dans plein de situations. Et l&#8217;avantage indiscutable, c&#8217;est que le code qui utilise la valeur paresseuse n&#8217;a pas besoin de savoir qu&#8217;elle le fait.</p>
<p>Les participants sont assez enthousiastes, et moi aussi, bien que tout le monde a conscience que ça pose plein de questions sur la gestion des générateurs, de <code>locals()</code>, et du debugging en général.</p>
<p>Plusieurs mots clés sont actuellement en compétition: <code>delayed</code>, <code>defer</code>, <code>lazy</code>. <code>delayed</code> est le plus utilisé, mais j&#8217;ai un penchant pour <code>lazy</code>.</p>
<p>Viendez sur la mailing list !</p>


feed_id: http://sametmax.com/?p=22504
title: Quelques outils pour gérer les clés secrètes en Django 3 Recently updated !
uri: Quelques-outils-pour-gérer-les-clés-secrètes-en-Django-3-Recentl
url: http://sametmax.com/quelques-outils-pour-gerer-les-cles-secretes-en-django/
content:
<p>On ne veut pas mettre sa SECRET_KEY en prod, et utiliser un service pour <a href="http://www.miniwebtool.com/django-secret-key-generator/">générer la clé</a>, ça va deux minutes.</p>
<p>Générer une clé secrète:</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;">random</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">string</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> secret_key<span style="color: black;">&#40;</span>size<span style="color: #66cc66;">=</span><span style="color: #ff4500;">50</span><span style="color: black;">&#41;</span>:
    pool <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">string</span>.<span style="color: black;">ascii_letters</span> + <span style="color: #dc143c;">string</span>.<span style="color: black;">digits</span> + <span style="color: #dc143c;">string</span>.<span style="color: black;">punctuation</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;&quot;</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">random</span>.<span style="color: black;">SystemRandom</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">choice</span><span style="color: black;">&#40;</span>pool<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>size<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Générer une clé secrete avec une commande <code>manage.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> django.<span style="color: black;">core</span>.<span style="color: black;">management</span>.<span style="color: black;">base</span> <span style="color: #ff7700;font-weight:bold;">import</span> BaseCommand<span style="color: #66cc66;">,</span> CommandError
<span style="color: #ff7700;font-weight:bold;">from</span> polls.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> Question <span style="color: #ff7700;font-weight:bold;">as</span> Poll
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Command<span style="color: black;">&#40;</span>BaseCommand<span style="color: black;">&#41;</span>:
    <span style="color: #008000;">help</span> <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'Generate a secret key'</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> add_arguments<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">parser</span><span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">parser</span>.<span style="color: black;">add_argument</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'size'</span><span style="color: #66cc66;">,</span> default<span style="color: #66cc66;">=</span><span style="color: #ff4500;">50</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">type</span><span style="color: #66cc66;">=</span><span style="color: #008000;">int</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> handle<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> *args<span style="color: #66cc66;">,</span> **options<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">stdout</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span>secret_key<span style="color: black;">&#40;</span>options<span style="color: black;">&#91;</span><span style="color: #483d8b;">'size'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>A mettre dans <code>./votreapp/management/command/generate_secret_key.py</code> :)</p>
<p>Une fonction pour lire la clé depuis un fichier texte ou générer la clé si elle n&#8217;existe pas:</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> io
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">try</span>:
    <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">pwd</span>
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">ImportError</span>:
    <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">try</span>:
    <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">grp</span>
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">ImportError</span>:
    <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> secret_key_from_file<span style="color: black;">&#40;</span>
        file_path<span style="color: #66cc66;">,</span> 
        create<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: #66cc66;">,</span> 
        size<span style="color: #66cc66;">=</span><span style="color: #ff4500;">50</span><span style="color: #66cc66;">,</span> 
        file_perms<span style="color: #66cc66;">=</span><span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #808080; font-style: italic;"># unix uniquement</span>
        file_user<span style="color: #66cc66;">=</span><span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #808080; font-style: italic;"># unix uniquement</span>
        file_group<span style="color: #66cc66;">=</span><span style="color: #008000;">None</span> <span style="color: #808080; font-style: italic;"># unix uniquement</span>
    <span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #ff7700;font-weight:bold;">with</span> io.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span>file_path<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> f:
            <span style="color: #ff7700;font-weight:bold;">return</span> f.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">IOError</span> <span style="color: #ff7700;font-weight:bold;">as</span> e:
        <span style="color: #ff7700;font-weight:bold;">if</span> e.<span style="color: #dc143c;">errno</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">2</span> <span style="color: #ff7700;font-weight:bold;">and</span> create:
            <span style="color: #ff7700;font-weight:bold;">with</span> io.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span>file_path<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:
                key <span style="color: #66cc66;">=</span> secret_key<span style="color: black;">&#40;</span>size<span style="color: black;">&#41;</span>
                f.<span style="color: black;">write</span><span style="color: black;">&#40;</span>key<span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">any</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>file_perms<span style="color: #66cc66;">,</span> file_user<span style="color: #66cc66;">,</span> file_group<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">pwd</span>:
                <span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">ValueError</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'File chmod and chown are for Unix only'</span><span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #ff7700;font-weight:bold;">if</span> file_user:
                <span style="color: #dc143c;">os</span>.<span style="color: black;">chown</span><span style="color: black;">&#40;</span>file_path<span style="color: #66cc66;">,</span> uid<span style="color: #66cc66;">=</span><span style="color: #dc143c;">pwd</span>.<span style="color: black;">getpwnam</span><span style="color: black;">&#40;</span>file_user<span style="color: black;">&#41;</span>.<span style="color: black;">pw_uid</span><span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #ff7700;font-weight:bold;">if</span> file_group:
                <span style="color: #dc143c;">os</span>.<span style="color: black;">chown</span><span style="color: black;">&#40;</span>file_path<span style="color: #66cc66;">,</span> gid<span style="color: #66cc66;">=</span><span style="color: #dc143c;">grp</span>.<span style="color: black;">getgrnam</span><span style="color: black;">&#40;</span>file_group<span style="color: black;">&#41;</span>.<span style="color: black;">gr_gid</span><span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #ff7700;font-weight:bold;">if</span> file_perms:
                <span style="color: #dc143c;">os</span>.<span style="color: black;">chmod</span><span style="color: black;">&#40;</span>file_path<span style="color: #66cc66;">,</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span>file_perms<span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">8</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #ff7700;font-weight:bold;">return</span> key
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">raise</span></pre></td></tr></table></div>

<p>Et une fonction pour récupére la clé depuis une variable d&#8217;environnement ou un fichier:</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_secret_key<span style="color: black;">&#40;</span>
        file_path<span style="color: #66cc66;">=</span><span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> 
        create<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: #66cc66;">,</span> 
        size<span style="color: #66cc66;">=</span><span style="color: #ff4500;">50</span><span style="color: #66cc66;">,</span> 
        file_perms<span style="color: #66cc66;">=</span><span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> 
        file_user<span style="color: #66cc66;">=</span><span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> 
        file_group<span style="color: #66cc66;">=</span><span style="color: #008000;">None</span><span style="color: #66cc66;">,</span>
        env_var<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;DJANGO_SECRET_KEY&quot;</span>
    <span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span><span style="color: black;">&#91;</span>env_var<span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">KeyError</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> file_path:
            <span style="color: #ff7700;font-weight:bold;">return</span> secret_key_from_file<span style="color: black;">&#40;</span>file_path<span style="color: #66cc66;">,</span> create<span style="color: #66cc66;">=</span>create<span style="color: #66cc66;">,</span> size<span style="color: #66cc66;">=</span>size<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">raise</span></pre></td></tr></table></div>

<p>Le but de cette dernière est d&#8217;avoir ça dans son fichier de settings:</p>
<p><code>SECRET_KEY = get_secret_key('secret_key')</code></p>
<p>Et de foutre &#8216;secret_key&#8217; dans son .gitignore.</p>
<p>Comme ça:</p>
<ul>
<li>Si on a pas de clé secrète, on en génère une.</li>
<li>Si on a une, elle est dans un fichier qui n&#8217;est PAS dans settings.py.</li>
<li>On peut commiter settings.py. Chaque env de dev et prod a sa clé secrète automatiquement.</li>
<li>On peut overrider la clé avec une variable d&#8217;environnement si on le souhaite.</li>
</ul>
<p>En attendant, <a href="https://github.com/django-extensions/django-extensions/issues/1017">j&#8217;ai proposé qu&#8217;on ajoute ça a django extensions</a>. Et qui sait, dans le core peut être un jour ?</p>


feed_id: http://sametmax.com/?p=22573
uri: BlockingIOError-Errno-11-Resource-temporarily-unavailable-pou
url: http://sametmax.com/blockingioerror-errno-11-resource-temporarily-unavailable-pour-python-3-6/
title:
“BlockingIOError: [Errno 11] Resource temporarily unavailable” pour Python 3.6 4   Recently updated !

content:
<p>La toute première version de Python 3.6 avait <a href="https://bugs.python.org/issue29208">un bug</a> assez vicieux qui ne se manifestait que sous certaines conditions, généralement dans un daemon sur un serveur, et en important certains modules qui finissent pas déclencher par réaction en chaîne l&#8217;usage de <code>random</code>.</p>
<p><code>django</code> est concerné.</p>
<p>On tombait dessus généralement assez tard, à la mise en prod, avec un message cryptique:</p>
<pre> 
BlockingIOError: [Errno 11] Resource temporarily unavailable 
  
 The above exception was the direct cause of the following exception: 

Traceback (most recent call last): 
   .... <- des imports de votre code qui ne font rien de mal
   File "/usr/local/lib/python3.6/site-packages/pkg_resources/__init__.py", line 36, in <module> 
     import email.parser 
   File "/usr/local/lib/python3.6/email/parser.py", line 12, in <module> 
     from email.feedparser import FeedParser, BytesFeedParser 
   File "/usr/local/lib/python3.6/email/feedparser.py", line 27, in <module> 
     from email._policybase import compat32 
   File "/usr/local/lib/python3.6/email/_policybase.py", line 9, in <module> 
     from email.utils import _has_surrogates 
   File "/usr/local/lib/python3.6/email/utils.py", line 28, in <module> 
     import random 
   File "/usr/local/lib/python3.6/random.py", line 742, in <module> 
     _inst = Random() 
 SystemError: <class 'random.Random'> returned a result with an error set 
</pre>
<p>Cela a été corrigé rapidement, et le binaire patché ajoute juste un &#8220;+&#8221; à sa version:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">$ python <span style="color: #660033;">--version</span>
Python 3.6.0+</pre></td></tr></table></div>

<p>En théorie vous ne pouvez pas tomber dessus, tous les liens de téléchargement ont été mis à jour, les distributions ont changé leurs dépôts, etc.</p>
<p>Mais hier je me suis fait bien niqué, et j&#8217;ai perdu 1h à debugguer cette surprise qui n&#8217;avait aucun sens (puisque mon code allait bien) : les bugs dans les binaires officiels sont rares et c&#8217;est le dernier endroit où je cherche.</p>
<p>En effet, certaines sources non-officielles pour installer Python n&#8217;ont pas été mise à jour, et c&#8217;est le cas du très populaire PPA deadsnake.</p>
<p>Si vous avez installé Python 3.6 en faisant :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> add-apt-repository ppa:fkrull<span style="color: #000000; font-weight: bold;">/</span>deadsnakes
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get update</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get install</span> python3.6</pre></td></tr></table></div>

<p>Vous l&#8217;avez dans le cul.</p>
<p>Il existe un PPA plus à jour si vous avez besoin de corriger le tir :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> add-apt-repository ppa:jonathonf<span style="color: #000000; font-weight: bold;">/</span>python-<span style="color: #000000;">3.6</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get update</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get install</span> python3.6</pre></td></tr></table></div>

<p>Donc si vous avez compilé Python à la main ou utilisé un PPA, assurez-vous bien d&#8217;avoir la bonne version, et sinon upgradez. En attendant j&#8217;ai un bug report à faire à deadsnakes&#8230;</p>


feed_id: http://sametmax.com/?p=22621
title: devpy, outils de dev à l’arrache Recently updated !
uri: devpy-outils-de-dev-à-l-arrache-Recently-updated
url: http://sametmax.com/devpy-outils-de-dev-a-larrache/
content:
<p>Je le publie en coup de vent car je me dis que ça peut servir à des gens, mais j&#8217;ai pas l&#8217;intention d&#8217;y passer des heures&#8230; vu que je fais ça pour me faire gagner du temps en mission.</p>
<p>J&#8217;ai créé <a href="https://github.com/sametmax/devpy">devpy</a>, un outil pour me faciliter le développement. </p>
<p>Dans sa forme la plus simple:</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> devpy</pre></td></tr></table></div>

<p>Ca donne automatiquement:</p>
<ul>
<li>Un logger qui log dans un fichier temporaire et dans la console.</li>
<li>Un traceback qui montre les lignes de SON code avec coloration syntaxique.</li>
<li>Si le programme crash, la stack trace est logguée dans le log automatiquement.</li>
</ul>
<p>En gros quand on commence à bosser on fait:</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> devpy.<span style="color: black;">develop</span> <span style="color: #ff7700;font-weight:bold;">as</span> log</pre></td></tr></table></div>

<p>Et on peut logger comme avec les logs python habituels (log.info, log.debug, etc).</p>
<p>On peut facilement retirer devpy une fois qu&#8217;on a fini et le remplacer par un log Python traditionnel type:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">log <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">logging</span>.<span style="color: black;">getLogger</span><span style="color: black;">&#40;</span>__name__<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Donc utiliser devpy ne coûte rien car on peut le retirer facilement une fois qu&#8217;on a fini: c&#8217;est 100% compat avec le log de la stdlib.</p>
<p>Ça tombe bien, car c&#8217;est pas un truc qu&#8217;on met en prod en théorie (même si ça peut pas abîmer le serveur).</p>
<p>C&#8217;est juste un outil que j&#8217;ai fais car j&#8217;en avais marre:</p>
<ul>
<li>De galérer à setuper un logging de base à chaque fois. C&#8217;est long, verbeux, pleins de coups fourrés. Mais 9 fois sur 10 je veux la même chose: la console et un fichier temp. Du coup par flemme je fais un print et je le regrette plus tard.</li>
<li>Devoir faire les choses proprement pour le dev. Oui un bon log c&#8217;est important, mais quand je commence à bosser je ne veux pas passer mon après midi à setuper les logs proprement. Je ferais ça plus tard, un truc à l&#8217;arrache pour le debug me suffit.</li>
<li>Devoir chercher dans la stack trace les lignes qui m&#8217;intéresse. Je debug rarement la stdlib. Montre moi MON code</li>
<li>Avoir des logs avec la stack trace en cas d&#8217;erreur est super relou à mettre en place. Mais c&#8217;est tellement pratique.</li>
</ul>
<p>Je vais sûrement rajouter des trucs dedans au fur et à mesure mais pour le moment ça fait ce que je veux.</p>
<p>Je l&#8217;ai mis compatible uniquement 3.6 car j&#8217;ai pas envie de me faire chier à tester ailleurs. D&#8217;ailleurs j&#8217;ai même pas de tests.</p>
<p>Et si vous êtes pas contents, vous pouvez vous mettre ma deadline là où je pense.</p>


feed_id: http://sametmax.com/?p=22896
title: Dites non aux DSL 7 Recently updated !
uri: Dites-non-aux-DSL-7-Recently-updated
url: http://sametmax.com/dites-non-aux-dsl/
content:
<p>Un Domain Specific Language est un langage créé pour une tache très particulière. CSS, HTML et SQL sont des bons exemples de DSL populaires. Moins connus: ReactQL, QML, Less, Latex, XPath, Graphviz&#8230; Les plus connus sont encore là car ils sont utiles, alors créer le votre pourrait être tentant.</p>
<p>Suite a <a href="http://blog.erezsh.com/how-to-write-a-dsl-in-python-with-lark/">ce tuto</a> sur la fabrications d&#8217;un DSL en Python, je réalise que quelques personnes recommandent encore de créer des DSL.</p>
<p>Il faut absolument que je vous empêche de commettre cette erreur irréparable !</p>
<h2>Une API n&#8217;est pas un DSL</h2>
<p>Ruby, qui a des parenthèses optionnelles et la capacité d&#8217;intercepter les accès d&#8217;attributs à la volée, a lancé la mode du mot DSL à tout va. Sauf que la plupart des DSL en Ruby n&#8217;en sont pas. Ce sont juste des <a href="http://sametmax.com/quest-ce-quune-api/">API</a> écrites en Ruby.</p>
<div id="attachment_22900" style="width: 694px" class="wp-caption aligncenter"><a href="media/323c966c.you-keep-using-that-word.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/03/you-keep-using-that-word.jpg" class="grouped_elements" rel="tc-fancybox-group22896"><img src="media/323c966c.you-keep-using-that-word.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/03/you-keep-using-that-word.jpg" alt="You keep using that world, I don&#039;t think it means what you think it means" width="684" height="384" class="size-full wp-image-22900" /></a><p class="wp-caption-text">You killed my project, prepare to die</p></div>
<p><a href="https://robots.thoughtbot.com/writing-a-domain-specific-language-in-ruby">Enchaîner les méthodes et opérateurs overloadé</a>s dans un langage populaire n&#8217;est pas utiliser un DSL. foo.bar().baz() n&#8217;est PAS un DSL si ça tourne dans la VM du langage. Quel que soit l&#8217;enrobage syntaxique qu&#8217;on a rajouté.</p>
<p>Un format de sérialisation générique n&#8217;est pas un DSL: XLM et YML n&#8217;en sont pas, contrairement à ce qu&#8217;on peut lire. Car ils sont généralistes, et donc pas &#8220;domain spécific&#8221; par nature.</p>
<p>Par contre on peut écrire un DSL en JSON, XML ou YAML, et il en existe d&#8217;ailleurs pas mal. MathML et SVG sont des exemples de DSL écrits en XML.</p>
<h2>Ne créez jamais un DSL</h2>
<p>Pourquoi avez vous besoin d&#8217;un nouveau langages ? Il existe <a href="http://99-bottles-of-beer.net/">des centaines de langages</a> et encore plus de formats de sérialisation. Aucun d&#8217;entre eux ne peut répondre à votre besoin ? Vraiment ? Vous avez tout testé pendant un mois ?</p>
<div id="attachment_22899" style="width: 790px" class="wp-caption aligncenter"><a href="media/6ebe88ff.CUJuINi.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/03/CUJuINi.jpg" class="grouped_elements" rel="tc-fancybox-group22896"><img src="media/6ebe88ff.CUJuINi.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/03/CUJuINi.jpg" alt="The world is the problem, the atomic bomis the answer" width="780" height="533" class="size-full wp-image-22899" /></a><p class="wp-caption-text">Choisir le bon outil, Civ style</p></div>
<p>Créer un DSL , donc un nouveau langage implique vous avez besoin:</p>
<ul>
<li>d&#8217;informations dessus: docs, standards et de tutos&#8230;</li>
<li>d&#8217;outils : UI, générateurs, wrapper pour le scripting, coloration syntaxique, snippets, linters, checkers, debuggers&#8230;</li>
<li>un support du DSL : garantir qu&#8217;on pourra le lire, écrire et manipuler dans 5 ans. Pouvoir fournir de nouveaux outils si le besoin évolues. Pouvoir faire évoluer le standard si (pardon &#8220;quand&#8221;) il se révélera limité. Répondre aux questions des utilisateurs. Fournir des messages d&#8217;erreurs et procédures pour résoudre les problèmes. Avoir un bug tracker.</li>
</ul>
<p>Et il faut tenir tout ça à jour.</p>
<p>Ah. Ah. Ah.</p>
<p>Personne ne le fait jamais, ce qui font l&#8217;usage de la plupart des DSL un enfer, sans parler de la maintenance des projets qui l&#8217;utilisent sur le long terme. Mais les créateurs de DSL s&#8217;en effeuillent amoureusement les génitoires car ils seront dans une nouvelle boite quand ça arrivera. Eux il se sont bien amusé a créer un parseur pour le fun. D&#8217;ailleurs ça fait classe sur le CV.</p>
<div id="attachment_22901" style="width: 3034px" class="wp-caption aligncenter"><a href="media/b9802428.D2TdcBx.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/03/D2TdcBx.jpg" class="grouped_elements" rel="tc-fancybox-group22896"><img src="media/b9802428.D2TdcBx.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/03/D2TdcBx.jpg" alt="Fuck everything" width="3024" height="4032" class="size-full wp-image-22901" /></a><p class="wp-caption-text">Réponse standardisée aux propositions de DSL. Aussi valable pour l&#8217;introduction d&#8217;une nouvelle stack Javascript</p></div>
<h2>Créez une API</h2>
<p>Votre langage de prédilection est turing complet. Il est donc capable de gérer ce que fait le DSL. Libérez l&#8217;anus de cette mouche et traitez votre problème avec un langage supporté, éprouvé, avec un large écosystème et qui résout déjà tout un tas de problèmes.</p>
<p>Ce qu&#8217;il vous faut, c&#8217;est faire une belle API, pour rendre la tache agréable:</p>
<ul>
<li>Créer des méthodes biens découplées, de l&#8217;injection de dépendance et un système d&#8217;events.</li>
<li>Faites des wrappers plus haut niveau, et des factories pour les cas courants.</li>
<li>Utilisez le sucre syntaxique de votre langage pour rendre tout ça tout beau (ex: __getiem__, __enter__, @decorateur, etc. pour python).</li>
</ul>
<div id="attachment_22905" style="width: 2058px" class="wp-caption aligncenter"><a href="media/32739aef.maxresdefault.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/03/maxresdefault.jpg" class="grouped_elements" rel="tc-fancybox-group22896"><img src="media/32739aef.maxresdefault.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/03/maxresdefault.jpg" alt="Rayon bien ran" width="2048" height="1152" class="size-full wp-image-22905" /></a><p class="wp-caption-text">Avec une belle présentation, un truc standard ennuyeux devient soudainement très attractif</p></div>
<p>Si créer une API n&#8217;aide pas assez, par exemple vous faites outil avec un langage haut niveau et avez besoin d&#8217;un langage haut niveau pour le scripting ou la configuration, embarquez un langage haut niveau connu. Par exemple Lua ou Python. Ne faites pas comme varnish ou nginx qui ont des fichiers de configuration dans un langage imbitable, indébuggable et mal documenté.</p>
<h2>Quelques bonnes raisons de créer un DSL</h2>
<p>Aller, il ne faut jamais dire jamais, et comme toujours en informatique, il y a parfois une bonne raison de faire quelque chose. Voici donc la liste des RARES cas où écrire un DSL a du sens:</p>
<ul>
<li>Vous avez un jeu de règles métier très complexes et des non informaticiens doivent pouvoir les composer. Et une UI ne ferait pas l&#8217;affaire pour une raison qui m&#8217;échappe. Et vous ne pouvez pas formez les non informaticiens parce que fuck you. Les langages de templates types jinja sont dans cette catégorie.</li>
<li>Vous avez un jeu de règles métier très complexes,  vous voulez pouvoir les serialiser (pour les sauver dans un fichier ou une base de données ou les transmettre à travers le réseau par exemple) et la sérialisation doit pouvoir être accessible depuis plusieurs langages incompatibles (donc pas de dump mémoire, de pickle, etc). Les langages de requêtes comme GraphQL en font partie.</li>
<li>Vous créez un langage pour remplacer un autre DSL. Par exemple Sass pour le CSS.</li>
<li>Vous voulez des instructions logiques mais sécurisées pour autoriser une source en laquelle vous n&#8217;avez pas confiance à manipuler vos données. Et vous ne pouvez pas mettre une couche d&#8217;abstraction (ou c&#8217;est la couche d&#8217;abstraction) type Web API, RPC ou autre et ça va, maintenant, TG, c&#8217;est mon projet. Tous les formats des sérialisations pour le RPC justement répondent à ce problème.</li>
</ul>
<p>Mais dans tous ces cas, ne faites un DSL que si:</p>
<ul>
<li>Une bonne UI n&#8217;est pas possible pas pour créer les règles et il faut les sérialiser.</li>
<li>Il n&#8217;existe pas déjà un standard existant.</li>
<li>Vous etes certains de fournir des outils pour manipuler le DSL.</li>
<li>Vous etes certains de documenter, tester et maintenir le DSL</li>
<li>J&#8217;ai dis certains de documenter, tester et maintenir votre DSL. Arrêtez de mentir vous ne le ferez pas.</li>
<li>Lachez ce DSL tout de suite ! Vous êtes dans une start up. Vous n&#8217;allez jamais faire tout ça. Oust !</li>
</ul>
<div id="attachment_22903" style="width: 310px" class="wp-caption aligncenter"><a href="media/7521c7ae.eBn1kcQ.png" data-original-source="http://sametmax.com/wp-content/uploads/2017/03/eBn1kcQ.png" class="grouped_elements" rel="tc-fancybox-group22896"><img src="media/7521c7ae.eBn1kcQ.png" data-original-source="http://sametmax.com/wp-content/uploads/2017/03/eBn1kcQ.png" alt="Special snowflake award" width="300" height="259" class="size-full wp-image-22903" /></a><p class="wp-caption-text">&#8220;Mais moi c&#8217;est pas pareil&#8221;, le hello word du DSL pour prendre des mauvaises décisions dans la vie</p></div>


feed_id: http://sametmax.com/?p=22936
title: Django, une app à la fois, mis à jour Recently updated !
uri: Django-une-app-à-la-fois-mis-à-jour-Recently-updated
url: http://sametmax.com/django-une-app-a-la-fois-mise-a-jour/
content:
<p><a href="https://github.com/sametmax/Django--an-app-at-a-time/">Django, une app à la fois</a> fonctionnait avec une vielle version de Django, donc je l&#8217;ai mis à jour pour marcher avec la 1.10.</p>
<p>J&#8217;ai trop attendu et la travail a été plus long que prévu car plein de choses avait du coup changé dans le framework. Des petits détails, mais déjà tout le routing ne marchait plus.</p>
<p>N&#8217;oubliez pas que la branche master est en anglais, mais il a y a une branche traduite en français. Les deux sont téléchargeables sous forme de zip sur la page d&#8217;accueil du projet github si vous ne souhaitez pas utiliser git. Il n&#8217;y a rien à installer : unzip, lire, lancer.</p>
<p>D&#8217;une manière générale, le projet est toujours très pratique pour enseigner ou apprendre les bases de django en complément des supports traditionnels. Il faudra que je rajoute la partie ORM un de ces 4.</p>


feed_id: http://sametmax.com/?p=23149
uri: 2017-04-18-
url: http://sametmax.com/sheepit-le-rendering-pour-tous-accessible-sans-trop-de-difficultes-et-gratos/
title:
Sheepit – Le rendering pour tous, accessible sans trop de difficultés et gratos 1   Recently updated !

content:
<p>Entre deux bars à putes et les restaux faut bien prendre un peu de temps pour se relaxer, il y a les salons de massage branlette vous me direz, mais pas que.</p>
<p>Dans une galaxie lointaine il y a fort fort longtemps je m&#8217;amusais à faire de la 3D, je vous parle d&#8217;un temps que les jeunes ne peuvent pas connaîtres&#8230;<br />
A l&#8217;époque reignaient en maîtres absolus 3DS MAX, MAYA, CINEMA 4D, etc et les outils maisons des studios Pixar. Pour les simples mortels comme moi on avait droit à Truespace, Vue D&#8217;esprit, Poser et sûrement d&#8217;autres dont j&#8217;ai oublié le nom. Truespace était mon favoris, plutôt sympa, pas compliqué à prendre en main et pas cher (voir gratos quand on se démerdait).</p>
<p>Pour faire mumuse c&#8217;était super mais voilà, c&#8217;était long, long, longggggg&#8230;&#8230;&#8230;..</p>
<p>De nos jour on a droit à de supers cartes graphiques comme les <a href="https://www.nvidia.com/en-us/geforce/products/10series/titan-x-pascal/">Titans X</a>  et pas mal de logiciels de 3D gratuits aussi, certe on peut faire dans le warez et se procurer Maya, 3D Studio, Cinema4D et plein de nouveaux que je ne connais pas mais restons dans le légal pour une fois car ce qui se passe est intéressant.</p>
<p>Donc le monde du gratos a super bien évolué, il y a plein de tutos sur youtube, des logiciels gratuits concurrencent les plus gros soft de 3D sur le marché et si ses derniers ont du succès c&#8217;est surtout parceque les studios en ont fait leur standard.</p>
<p>Je vais vous parler de <a href="https://www.blender.org/">Blender ,</a> c&#8217;est un projet open source que je suis de très loin mais qui a attiré mon attention depuis peu avec quelques superbes vidéos sur youtube sur lesquelles je suis tombé:<br />
&#8211; <a href="https://www.youtube.com/watch?v=-TksegJETqI">https://www.youtube.com/watch?v=-TksegJETqI</a><br />
&#8211; <a href="https://www.youtube.com/watch?v=kSp3pHA_tRM">https://www.youtube.com/watch?v=kSp3pHA_tRM</a><br />
&#8211; <a href="https://www.youtube.com/watch?v=7lY9SlQ8gjY">https://www.youtube.com/watch?v=7lY9SlQ8gjY</a><br />
&#8211; <a href="https://www.youtube.com/watch?v=Q1VCLFJY250">https://www.youtube.com/watch?v=Q1VCLFJY250</a><br />
&#8211; <a href="https://www.youtube.com/watch?v=143k1fqPukk">https://www.youtube.com/watch?v=143k1fqPukk</a><br />
&#8211; <a href="https://www.youtube.com/watch?v=LcCQKuWPhXk">https://www.youtube.com/watch?v=LcCQKuWPhXk</a></p>
<p>Il y a vraiment une bonne <a href="https://www.blender.org/support/user-community/">communauté </a></p>
<p>Des <a href="https://www.youtube.com/results?search_query=blender%20tutorials">milliers de tutos sur youtube</a> pour s&#8217;en sortir avec les millions d&#8217;options que possède le logiciel.</p>
<p>Bref tout ça c&#8217;est merveilleux, pour perdre son temps y a pas mieux. Mais il y a un hic, le temps de rendu justement. Je me souviens de cette époque où j&#8217;attendais 1 heure, voire 2 pour rendre une seule image et m&#8217;apperçevoir que le résultat était moyen.<br />
Et de ce côté ça n&#8217;a pas changé ! C&#8217;est même plus long avec toutes les nouvelles options de raytracing possibles même avec des cartes graphiques surpuissantes comme cité plus haut. Alors une animation&#8230;.</p>
<p>Blender possède un <a href="https://wiki.blender.org/index.php/Doc%3A2.6/Manual/Render/Performance/Netrender">plugin de network rendering</a>, à savoir partager le temps de calcul sur plusieurs serveurs du réseau, c&#8217;est sympa mais c&#8217;est pas tout le monde qui a 10 ordis à la maison&#8230;</p>
<p>Une solution a vu le jour il y a quelques années et quelques milliers de membres font vivre une véritable ferme de rendu.</p>
<p><strong>Le principe de la ferme de rendu:</strong><br />
Via un réseau d&#8217;ordinateurs on partage le temps cpu entre plusieurs machines, accélérant ainsi le temps de rendu.</p>
<p>Cette solution c&#8217;est <a href="https://www.sheepit-renderfarm.com/index.php">Sheepit</a>.</p>
<p>Ok <a href="https://www.youtube.com/watch?v=NfDUkR3DOFw">on décolle</a> ! Vous installez leur app java sur un serveur qui traîne au garage ou sur votre ordi et vous avez droit à des points en fonction du temps machine que vous consacré à l&#8217;application. Ces points vont vous permettre &#8220;d&#8217;acheter&#8221; du temps de calcul parmi tous les participants.<br />
Ainsi un projet d&#8217;animation qui d&#8217;ordinaire me prend 5 jours est rendu en quelques heures, gratos en plus !</p>
<p>Je trouve le concept très sympa, tout est gratuit, il y a une admin avec le nombres de personnes qui partagent vos calculs, on peu former des équipes pour se tirer la bourre ou privilégier les cpu à ses coéquipiers, bref c&#8217;est bien pensé et je voulais en parler pour, qui sait, leur ramener un peu de monde.</p>
<p>Aux dernières nouvelles il y a environ 350 machines connectées en permanence, vous imaginez le temps de calcul offert !</p>
<p>Une petite ligne de code pour mettre un serveur dans la pool:</p>
<p>inscrivez-vous sur sheepit : <a href="https://www.sheepit-renderfarm.com/getstarted.php">https://www.sheepit-renderfarm.com/getstarted.php</a><br />
Il y a une version applet java pour le navigateur mais je n&#8217;ai pas testé, je préfère laisser tourner leur app sur un serveur h24:<br />
téléchargez l&#8217;app java: <a href="https://www.sheepit-renderfarm.com/media/applet/sheepit-client-5.366.2818.jar">https://www.sheepit-renderfarm.com/media/applet/sheepit-client-5.366.2818.jar</a></p>
<p>Sur Centos j&#8217;ai créé un user sheepit pour pas lancer leur app en root:</p>
<p><code>useradd sheepit</code></p>
<p>ensuite dans un screen je lance l&#8217;app avec les paramètres suivants:</p>
<p><code>sudo -u sheepit java -jar /sheepit/sheepit-client-5.366.2818.jar -ui text -login mon_login_sheepit -password mon_pass_sheepit -cores 3 -compute-method CPU<br />
</code></p>
<p><strong>-ui text :</strong> Pour lancer l&#8217;app java en headless (pour les serveur sans GUI)<br />
<strong>-login mon_login_sheepit :</strong> Le login que vous avez choisit lors de l&#8217;inscription à sheepit<br />
<strong>-password mon_pass_sheepit :</strong> Le mot de passe que vous avez choisit lors de l&#8217;inscription à sheepit<br />
<strong>-cores 3 :</strong> Le nombres de processeurs que vous voulez dédier à Sheepit, plus vous en dédiez plus vous gagnerez des points et plus vos projet passerons en priorité dans la pool de rendu.<br />
<strong>-compute-method CPU:</strong> N&#8217;utilise que le cpu de votre serveur, vous pouvez mettre GPU si vous en avez.</p>
<p>Ce système a beaucoup d&#8217;avantages, il vous permet enfin de faire de supers rendus en peu de temps, sans dépenser d&#8217;argent, c&#8217;est vraiment magique. (je ne vous partagerais pas les merdes que j&#8217;ai fait car je suis une quiche en 3D). L&#8217;inconvénient c&#8217;est qu&#8217;il faut ensuite télécharger toutes les frames du projet, là j&#8217;ai 24 Go de frames à télécharger, ça fait lourd si on a pas la fibre.</p>
<p>Ils ont un <a href="https://www.sheepit-renderfarm.com/forum/">forum qui ne demande qu&#8217;à grandir</a></p>
<p>Il y a des artistes en herbe qui n&#8217;ont pas les moyens de s&#8217;offrir des cartes graphiques à 2000€ et je trouve ce système juste fantastique pour eux et même pour les gros projets. J&#8217;espère que vous ferez passer le mot et si vous avez un serveur ou deux soyez cool, ça prend 5 minutes.</p>
<p>Allez le meilleur pour la fin:</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/b6_wwKiyFvI?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>A poil les putes!</p>


feed_id: http://sametmax.com/?p=23196
title: Comment garder des lignes courtes ? 6 Recently updated !
uri: Comment-garder-des-lignes-courtes-6-Recently-updated
url: http://sametmax.com/comment-garder-des-lignes-courtes/
content:
<p>Arg, j&#8217;ai plein de commentaires sans réponse sur le blog, indexerror aussi. Des tickets millénaires sur 0bin et les impôts qui arrivent. Dois fois ce qu&#8217;il faut c&#8217;est une petit victoire pour relativiser.</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/MLLseEQRnzA?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>Du coup, un petit post pour me donner l&#8217;impression de ne pas être inutile à l&#8217;humanité.</p>
<p>De toutes les recommandations du PEP8, garder des lignes courtes, souvent moins de 80 caractères, est celle qui fait le plus râler.</p>
<p>On rétorque parfois que c&#8217;est une règle qui n&#8217;a pas de sens de nos jours avec nos grands écrans HD.</p>
<p>Sauf que:</p>
<ul>
<li>L’œil humain fonctionne par micro sauts, et peut donc bien plus efficacement scanner de longues colonnes que de longues lignes.</li>
<li>Il est très courant de pouvoir mettre du code côte à côte sur un même écran pour comparer, merger ou avoir plusieurs vues sur un fichier.</li>
<li>Vous ne savez pas sur quoi sera lu votre code. Au bureau vous avez peut être un setup à triple écran 4K, mais les autres n&#8217;ont peut être pas cette chance. Les chats, les pastebins, les blogs posts, un slide show, un remote ssh, des comments, des tickets, ou un retro projecteur basse résolution sont autant de supports sur lesquels votre code finira probablement. Et ils ne sont pas larges.</li>
<li>Un diff sur de longues lignes c&#8217;est dégueulasse.</li>
<li>Le debug pas à pas qui s&#8217;arrête sur une ligne de 3km ça donne des envies de meurtre.</li>
</ul>
<p>D&#8217;une manière générale, garder des lignes courtes est une bonne habitude et incitera à écrire un code sain. Le processus de réduire la taille des lignes passe par l&#8217;expressivité, la clarté, le refactoring, etc. Au final, c&#8217;est excellent pour la santé du projet.</p>
<p>N&#8217;oubliez pas non plus que le PEP8 indique clairement qu&#8217;il ne faut jamais suivre une règle de manière rigide. Si votre ligne est absolument plus adéquate sur une ligne, alors mettez là sur une ligne.</p>
<p>Maintenant qu&#8217;on a expliqué le pourquoi, parlons du comment. En effet beaucoup de bonnes pratiques ne sont pas appliquées parce qu&#8217;on ne sait pas faire. Faire des lignes courtes demande une certaine connaissance, et un peu de pratique. </p>
<p>Voici quelques pistes pour vous aider dans vos prochaines sessions.</p>
<h2>Python est fait pour ça</h2>
<p>Python force à indenter, et c&#8217;est une de ses meilleures caractéristiques. Jamais vous ne vous retrouverez comme dans d&#8217;autres langages face au code de votre collègue, ce gros porc, aligne ses accolades avec le groin.</p>
<p>Mais pour garder des lignes courtes, l&#8217;indentation joue contre vous. </p>
<p>Python vient heureusement avec tout un tas d&#8217;outils pour qui rendre votre code court, rapide et peu gourmand on mémoire. C&#8217;est tout bénef.</p>
<p><code>itertools</code>, <code>all()</code>, <code>any()</code>, <code>filter()</code>, <code>map()</code>, <code>collections</code>, les listes en intension, <code>functools</code> et les générateurs sont tous d&#8217;excellents moyens de créer un code plus beau, plus court, et plus efficace. Apprenez à les utilisez ! Vous serez un meilleur programmeur, plus productif, et les lignes seront naturellement plus courtes.</p>
<p>Exemples&#8230;</p>
<p>Le module <code>itertools</code> permet de faire un tas de choses, comme remplacer les boucles imbriquées.</p>
<p>Remplaçons :</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> lettre <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #483d8b;">&quot;abc&quot;</span>:
...     <span style="color: #ff7700;font-weight:bold;">for</span> chiffre <span style="color: #ff7700;font-weight:bold;">in</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: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>lettre<span style="color: #66cc66;">,</span> chiffre<span style="color: black;">&#41;</span>
...
<span style="color: black;">a</span> <span style="color: #ff4500;">1</span>
a <span style="color: #ff4500;">2</span>
a <span style="color: #ff4500;">3</span>
b <span style="color: #ff4500;">1</span>
b <span style="color: #ff4500;">2</span>
b <span style="color: #ff4500;">3</span>
c <span style="color: #ff4500;">1</span>
c <span style="color: #ff4500;">2</span>
c <span style="color: #ff4500;">3</span></pre></td></tr></table></div>

<p>Par :</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> <span style="color: #dc143c;">itertools</span> <span style="color: #ff7700;font-weight:bold;">import</span> product
<span style="color: #66cc66;">&gt;&gt;&gt;</span> products <span style="color: #66cc66;">=</span> product<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;abc&quot;</span><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: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">for</span> lettre<span style="color: #66cc66;">,</span> chiffre <span style="color: #ff7700;font-weight:bold;">in</span> products:
...     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>lettre<span style="color: #66cc66;">,</span> chiffre<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Les built-ins ont un tas d&#8217;outils pour pour manipuler les données.</p>
<p>Si vous avez des collections dont vous voulez vérifier tout le contenu:</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> <span style="color: #dc143c;">random</span> <span style="color: #ff7700;font-weight:bold;">import</span> randint
<span style="color: #66cc66;">&gt;&gt;&gt;</span> data <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span>randint<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">10</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;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> randint<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">max</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span>  <span style="color: #808080; font-style: italic;"># pas besoin de boucler pour trouver le max</span>
<span style="color: #ff4500;">9</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">any</span><span style="color: black;">&#40;</span>x <span style="color: #66cc66;">&gt;</span> <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> data<span style="color: black;">&#41;</span>: <span style="color: #808080; font-style: italic;"># any est un super &quot;or&quot;</span>
...    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Un élément est supérieur à 3'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Le module <code>collections</code> possède d&#8217;ailleurs tout un tas d&#8217;outils pour faire le travail à votre place :</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> <span style="color: #dc143c;">collections</span> <span style="color: #ff7700;font-weight:bold;">import</span> Counter
<span style="color: #66cc66;">&gt;&gt;&gt;</span> Counter<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;aaaaaaaaabbbbbbccccc&quot;</span><span style="color: black;">&#41;</span>
Counter<span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'a'</span>: <span style="color: #ff4500;">9</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'b'</span>: <span style="color: #ff4500;">6</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span>: <span style="color: #ff4500;">5</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>On peut éviter un tas de <code>try</code>/<code>except</code> avec les helpers qui retournent une valeur par défaut:</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: black;">&#123;</span><span style="color: #483d8b;">&quot;foo&quot;</span>: <span style="color: #ff4500;">1</span><span style="color: black;">&#125;</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'bar'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>  <span style="color: #808080; font-style: italic;"># et next, iter, setdefault... </span>
<span style="color: #ff4500;">3</span></pre></td></tr></table></div>

<p>Sans parler de l&#8217;unpacking, le slicing, le paramétrage dynamique, etc.</p>
<p>Bref, si votre ligne est trop longue, c&#8217;est peut être parce que vous être en train de sous utiliser Python.</p>
<p>De même, apprenez les libs les plus célèbres en Python.</p>
<p>pytest, pendulum, request, pandas&#8230;</p>
<p>Dès qu&#8217;un usage particulier intervient, elles seront généralement plus efficaces que la stdlib. Moins de code !</p>
<h2>Refactorisez</h2>
<p>Un bloc de code qui commence à être long sera aventageusement déplacé dans une méthode ou une fonction. Avec un joli nom bien explicite qui va naturellement rendre votre code mieux documenté, et testable.</p>
<p>Tant qu&#8217;on y est, faites usages des variables intermédiaires.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">res <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span>foo <span style="color: #ff7700;font-weight:bold;">for</span> foo <span style="color: #ff7700;font-weight:bold;">in</span> objet.<span style="color: black;">attribut</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'cle'</span><span style="color: black;">&#93;</span> <span style="color: #ff7700;font-weight:bold;">if</span> foo <span style="color: #66cc66;">&gt;</span> wololo<span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Gagnera à devenir:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">nom_explicite <span style="color: #66cc66;">=</span> objet.<span style="color: black;">attribut</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'cle'</span><span style="color: black;">&#93;</span>
res <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span>foo <span style="color: #ff7700;font-weight:bold;">for</span> foo <span style="color: #ff7700;font-weight:bold;">in</span> nom_explicite <span style="color: #ff7700;font-weight:bold;">if</span> foo <span style="color: #66cc66;">&gt;</span> wololo<span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Les parenthèses pour les sauts de ligne</p>
<p>Les parenthèses en Python, c&#8217;est magique.</p>
<p>Avant :</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> module_de_la_mort_qui_tue <span style="color: #ff7700;font-weight:bold;">import</span> foo<span style="color: #66cc66;">,</span> bar<span style="color: #66cc66;">,</span> et<span style="color: #66cc66;">,</span> toute<span style="color: #66cc66;">,</span> la<span style="color: #66cc66;">,</span> clique</pre></td></tr></table></div>

<p>Après</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> module_de_la_mort_qui_tue <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: black;">&#40;</span>
	foo<span style="color: #66cc66;">,</span> 
	bar<span style="color: #66cc66;">,</span> 
	et<span style="color: #66cc66;">,</span> 
	toute<span style="color: #66cc66;">,</span> 
	la<span style="color: #66cc66;">,</span> 
	clique
<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Ca marche partout, dans les appels de fonctions, l&#8217;accès des attributs, les chaînes de caractères&#8230;</p>
<p>On part de :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">queryset <span style="color: #66cc66;">=</span> ModelDeDjango.<span style="color: black;">objects</span>.<span style="color: #008000;">filter</span><span style="color: black;">&#40;</span>attribut<span style="color: #66cc66;">=</span>val<span style="color: black;">&#41;</span>.<span style="color: black;">first</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Et bim :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">queryset <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span>ModelDeDjango.<span style="color: black;">objects</span>
                         .<span style="color: #008000;">filter</span><span style="color: black;">&#40;</span>attribut<span style="color: #66cc66;">=</span>val<span style="color: black;">&#41;</span>
                         .<span style="color: black;">first</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Si des parenthèses sont déjà là, inutile d&#8217;en rajouter:</p>
<p>Aller :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">raise</span> OverkillError<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Arrrrrrrrrrrrrrrrrrrrrrrrrrrrggggggg&quot;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Hop :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">raise</span> OverkillError<span style="color: black;">&#40;</span>
	<span style="color: #483d8b;">&quot;Arrrrrrrrrrrrrrrrr&quot;</span>
	<span style="color: #483d8b;">&quot;rrrrrrrrrrrggggggg&quot;</span>
<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<h2>Aidez-vous de l&#8217;environnement</h2>
<p>Vous outils sont là pour vous faciliter la vie. Votre éditeur par exemple, a certainement un moyen d&#8217;afficher un indicateur vertical pour symboliser la limite de 80 caractères.</p>
<p>Les bons IDES et les linters vous signalerons le dépassement. Ca vaut le coup d&#8217;investir dedans. Si votre éditeur ne le supporte pas par défaut, il a peut être un plugin pour utiliser un linter. </p>
<p>VSCode et Sublime Text ont tout deux des plugins pour Python qui permettent cela. Notamment ils peut exploiter l&#8217;excellent linter flake8, qui sinon peut s&#8217;utiliser à la main.</p>
<p>Pour certains lignes, vous allez dépasser. Ce n&#8217;est pas la mer à boire tant que c&#8217;est un choix conscient et pas de la flemme.</p>
<p>Par exemple, les commentaires avec des URLS dedans dépassent souvent. Beaucoup de linters ont un réglage pour les autoriser (ou un pattern au choix), activez le.</p>
<p>Si vous avez une ligne qui dépasse et que le signalement de votre IDE/linter vous casse les couilles, il est souvent possible de le désactiver en ajoutant en fin de ligne le commentaire:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># noqa</span></pre></td></tr></table></div>

<p>Qui signifie tanto &#8220;no question asked&#8221; ou &#8220;no quality assessment&#8221;. </p>


feed_id: http://sametmax.com/?p=23211
title: Le don du mois : vue.js
uri: Le-don-du-mois-vue-js
url: http://sametmax.com/le-don-du-mois-vue-js/
content:
<p>Le pognon rentre à nouveau et c&#8217;est donc le retour du don du mois.</p>
<p>Ça ne fait que quelques temps que j&#8217;utilise cette lib, mais globalement c&#8217;est déjà mon outil par défaut pour toute UI en JS.</p>
<p>J&#8217;ai encore des demandes de formations et projets pour Angular 1 et React, mais si j&#8217;ai le choix il n&#8217;y a aucune hésitation.</p>
<p>J&#8217;ai essayé quelques alternatives, comme Riot, mais on arrive jamais à cette combinaison parfaite de simplicité, légèreté, puissance et performance. Ce projet est un petit bijoux du monde de l&#8217;open source. Un truc rare en Javascript.</p>
<p>Bref, c&#8217;est bien beau de cracher toujours sur JS, mais ça résout pas le problème. Il faut aussi aider, et c&#8217;est donc pour ça que je fais un don de 50 €, <a href="https://vuejs.org/support-vuejs/">par ici</a>.</p>
<p>Et si vous regrettiez l&#8217;époque de la simplicité de jQuery mais que vous avez envie de quelque chose qui automatise bien plus comme un framework moderne, vous savez ce qu&#8217;il vous reste à essayer :)</p>


feed_id: http://sametmax.com/?p=23244
title: Réaction à ReactJS 14 Recently updated !
uri: Réaction-à-ReactJS-14-Recently-updated
url: http://sametmax.com/reaction-a-reactjs/
content:
<p>Grand utilisateur de jQuery, formateur Angular et maintenant adorateur de VueJS, vous vous demandez sûrement ce que je pense de React. Si, je le sais, mon avis est pour vous comme un phare dans la nuit sombre du frontend engluée dans le brouillard de Javascript.</p>
<p>Après tout, facebook est codé avec cette techno pixel par pixel, et ils servent des milliards de pages chaque jour. Ça ne peut pas être mauvais. Ce ne sont pas de cons quand même.</p>
<p>Et puis tout le monde en parle, les asticots gigotent autour des restes du gigot d&#8217;ordre que les devs des GAFAS tentent de mettre au menu dans leur régime sans sel et sans typage.</p>
<p>Alors merde, quoi, react, keskeçavo ?</p>
<p>Je vais passer peut être pour un réact (hashtag lol), mais franchement le gigot au brouillard, c&#8217;est pas mon plat préféré.</p>
<p>Taillons un peu JS, ça m&#8217;avait manqué.</p>
<h2>Mon royaume pour un hello world</h2>
<p>React est tellement chiant à setuper que la doc officielle <a href="https://facebook.github.io/react/docs/hello-world.html">vous propose le hello world dans un code pen</a> histoire de pas vous faire fuir tout de suite.</p>
<p>En fait, si pour vous installer un module avec npm/yarn/bower (plutôt que de copier le truc directement ou d&#8217;utiliser un CDN) est déjà un truc qui vous fait grogner, vous êtes loin derrière.</p>
<p>Il va vous falloir un outil de build (gulp, grunt ou l&#8217;usine à Vespene Webpack) et la série de recettes obsolètes customisées trouvées sur un coin de github pour connecter tous les bouts de votre pipeline. React bien sûr, mais aussi babel pour transformer le JSX en JS.</p>
<p>Babel suit la left-pad philosophie, à savoir que tout est configurable et éclaté en centaines de petites dépendances et settings. C&#8217;est tellement chiant que des packages existent, appelés &#8220;presets&#8221;, dont l&#8217;unique but est de configurer babel pour une tâche particulière.</p>
<p>Une fois que vous avez tout ça up, vous vous allez à la pêche au tuto, seulement pour remarquer que tout le monde code en ES6, voir ES7, et vous rajoutez donc un peu plus de plugins à tout ce bordel. Allah vous garde si vous tentez d&#8217;utiliser typescript.</p>
<p>Et vient alors le moment tant attendu pour faire coucou de la main programmatiquement. Ça foire, bien entendu. Le debugger vous pointe sur un bundle.js de plusieurs Mo, et vous apprenez que le support des sources maps est inégale d&#8217;un navigateur à l&#8217;autre.</p>
<p>Bienvenue.</p>
<h2>Le X c&#8217;est pas toujours excitant.</h2>
<p>Une fois passée la douloureuse expérience de mettre en place votre environnement de travail, vous trouvez un certains confort. L&#8217;autoreload de la page est franchement pratique, et pouvoir utiliser l&#8217;unpacking (pardon le spread), les valeurs de paramètres par défaut et les arrow functions sans vous soucier de la compat du navigateur c&#8217;est quand même cool. Avec un webpack tout bien huilé avec amour (et douleur), vous pouvez faire des imports en JS et on a presque l&#8217;impression d&#8217;utiliser un langage de programmation.</p>
<p>Et puis le JSX, de loin ça à l&#8217;air pas mal ! Du HTML directement dans le JS ça parait un peu bizarre mais on vous le vend comme un avantage : finit les langages de templates limités, vous pouvez utiliser la pleine puissance (hum&#8230;) du langage Javascript pour créer vos balises.</p>
<p>Sauf que non, le JSX, ça pue du cul.</p>
<p>D&#8217;abord, il y a le fait que toutes les structures sont à faire en JS. Les conditions, les concaténations et bien entendu, les boucles. Donc vous avez une liste de noms et numéros de téléphone, en VueJS, vous faites:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="html" style="font-family:monospace;">&lt;ul&gt;
    &lt;li v-for=&quot;pers in persons&quot; v-if=&quot;pers&quot;&gt;
        &lt;strong&gt;{{ pers.nom }} &lt;/strong&gt;: {{ pers.tel }} 
    &lt;/li&gt;
    &lt;li v-else&gt;
        &lt;em&gt;Nobody's here!&lt;/em&gt;
    &lt;/li&gt;
&lt;/ul&gt;</pre></td></tr></table></div>

<p>Mais en React, vous allez faire péter une expression ternaire et une fonction anonyme en plein milieu rien que pour l&#8217;occasion:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="jsx" style="font-family:monospace;">&lt;ul&gt;
    {
      (this.state.persons)
        ? this.state.persons.map((pers) =&gt; (
            &lt;li&gt;&lt;strong&gt;{ pers.nom } &lt;/strong&gt;: { pers.tel } &lt;/li&gt;
        ))
        : (
            &lt;li&gt;
                &lt;em&gt;Nobody's here!&lt;/em&gt;
            &lt;/li&gt;
        )
    }
&lt;/ul&gt;</pre></td></tr></table></div>

<p>Vous la sentez bien la puissance de Javascript là ?</p>
<p>Et attention à ces boucles, car dedans vous guette cette erreur qui va vous poursuivre jusque dans vos cauchemars:</p>
<pre>
SyntaxError: Adjacent JSX elements must be wrapped in an enclosing tag</pre>
<p>Babel vous signale gentiment que ne pouvez pas produire un snippet de JSX qui contienne plus d&#8217;un élément à la racine. Donc il faut TOUT wrapper dans un container. TOUT. Vous allez avoir vite des DIVs et des SPANs inutiles partout, juste pour faire plaisir à React. C&#8217;est absurde. C&#8217;est à vomir. Ca nique votre CSS et rempli vos sessions &#8220;examinez un élément&#8221; de tendinites dues aux clics pour déplier tout l&#8217;arbre des emballages cadeaux de vos balises. Et aussi, nique la sémantique.</p>
<p>Pour éviter ça vous allez tenter d&#8217;inliner un maximum de truc dans une seule expression JSX ou tout foutre dans des arrays. Car je ne l&#8217;ai pas précisé ? Les arrays de JSX sont automatiquement et magiquement convertis en sous-elements. Et du coup vous pourrez profitez au maximum des qualités de lisibilités de JS.</p>
<p>JSX est bourré de petits trucs comme ça, pour faire plaisir.  Par exemple, j&#8217;ai un button, quand je le clique il delete la personne de la ligne de mon agenda. Je mets aussi une classe pour tous et une selon que la personne est importante ou non. Un prevent default pour éviter que le browser recharge la page si je suis dans un form.</p>
<p>En Vue, je passe un objet qui dit quelle classe afficher ou non. Le click handler contient une instruction <code>prevent </code>qui me permet d&#8217;appeler <code>preventDefault</code> automatiquement. Et j&#8217;appelle <code>deletePerson</code> tout naturellement :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="html" style="font-family:monospace;">&lt;button class=&quot;{'delete-person': true, 'important-person': pers.isImportant}&quot; 
        v-on:click.prevent=&quot;deletePerson(pers)&quot;&gt;
    Delete
&lt;/button&gt;</pre></td></tr></table></div>

<p>En react, on ne peut pas passer de paramètre à son handler. Il faut le passer dans une closure. Mais alors la closure va recevoir l&#8217;objet event, qu&#8217;on doit donc faire suivre à notre handler, afin qu&#8217;il puisse appeler <code>preventDefault</code> à la main. A noter aussi que <code>class</code> s&#8217;appelle <code>className</code>. Et n&#8217;accepte que des strings donc la concaténation se fait à la mano.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="html" style="font-family:monospace;">// plus haut on appelle preventDefault dans handleDelete
&nbsp;
&lt;button className={'delete-person ' + (pers.isImportant ? 'important-person': '')}
        onClick={(e) =&gt; this.deletePerson(pers, e)}&gt;
    Delete
&lt;/button&gt;</pre></td></tr></table></div>

<p>Ce n&#8217;est pas juste chiant à lire, c&#8217;est surtout hyper chiant à trouver, à taper et à debugger. </p>
<h2>Un peu de nutella sur votre confiture ?</h2>
<p>React, c&#8217;est verbeux, il va falloir vous y faire. Il suffit de comparer <a href="https://github.com/tastejs/todomvc/tree/gh-pages/examples">le code nécessaire</a> pour faire une TODO en react avec les autres frameworks.</p>
<p>Mais ce n&#8217;est pas juste ça qui est lourd.</p>
<p>Non, le vrai truc qui est super pesant, c&#8217;est que react est un cancer. Quand il est utilisé, il contamine tout.</p>
<p>Par principe, une fois que vous utilisez react, il faut mettre TOUTE VOTRE PAGE en react. Pas juste un petit bout. Par là j&#8217;entends que 90% de votre HTML va devoir migrer dans le code JSX. Votre beau code HTML bien propre, converti en cette monstruosité de mélange entre le langage le plus dégueulasse du monde et un monstre mimic qui essaye de se faire passer pour du HTML pour vous bouffer.</p>
<p>Or, toute l&#8217;idée c&#8217;est de faire des composants, de diviser votre pages en plus petits bouts. Mais voilà, React n&#8217;a rien prévu de simple pour la communication. Pour passer des données des composants enfants, il faut les passer via les attributs de balise HTML (appelés les props, pour faciliter la rechercher Google). Si vous avez 5 niveaux d&#8217;imbrications, vous vous tapez ça 5 fois.</p>
<p>Plus amusant, il n&#8217;y a aucun mécanisme pour passer des infos de l&#8217;enfant aux parents. La méthode standard est d&#8217;écrire puis passer manuellement un callback du parent à l&#8217;enfant, via props, et appeler ce callback dans l&#8217;enfant avec la valeur que le parent utilise ensuite. POUR. CHAQUE. PUTAIN. DE. VALEUR.</p>
<p>Passer des callbacks, ça va 5 minutes. Et ca ne résout pas un problème de communication entre composants parallèles, c&#8217;est à dire ni parent, ni enfant. Du coup tout le monde finit par utiliser une lib supplémentaire type <code>EventEmitter</code> pour servir de bus de communication.</p>
<p>Quand vous entendez les gens se plaindre de la difficulté d&#8217;utiliser l&#8217;écosystème de react, les fans répondent souvent que l&#8217;écosystème n&#8217;est pas obligatoire. On peut très bien s&#8217;en passer sur un petit projet. </p>
<p>Sauf que react est absolument inutilisable sans. Sans un bus d&#8217;event, un transpiler ES6 + JSX, un builder et un hot reloader au mininum, le projet ne dépasse jamais le stade du prototype.</p>
<p>Mais bon soyons franc, beaucoup de projets react tout court ne dépassent jamais le stade du prototype. On parle de codeurs JS là.</p>
<h2>Etat</h2>
<p>Les props ne doivent jamais changer. Seul l&#8217;état d&#8217;un composant react peut changer, ce qui trigger un nouveau rendu du composant.</p>
<p>Mais l&#8217;état lui-même est en read-only. On est supposé uniquement créer un nouvel état à chaque fois et remplacer l&#8217;ancien.</p>
<p>Au début on le fait à la main, mais JS n&#8217;est pas vraiment fait pour faire de l&#8217;immutabilité, et ça devient uber chiant très vite. Changer la propriété d&#8217;un objet qui est lui même dans un array demande de recréer tout l&#8217;array et l&#8217;objet. A chaque fois.</p>
<p>On se tourne alors vers des libs (encore une) type immutable.js qui fournit des listes et maps qui sont immutables et permettent de faire ces opérations sans y laisser ses jours de congé.</p>
<p>Une fois de plus, les connards qui vous disent qu&#8217;on peut faire du react sans la tonne de boiler plate qu&#8217;on voit dans les tutos ne le font jamais eux-mêmes. Parce que oui, on peut faire Paris-Amien à pied en théorie, mais bon&#8230;</p>
<h2>Des décisions à la con</h2>
<p>Clairement, react a été fait pour créer des UI. Mais au bout d&#8217;un moment, les utilisateurs se sont réveillés et ont voulu une encapsulation pour des composants non UI. Mais react ne sait pas faire. Quand vous avez donc un composant non UI, par exemple la déclaration de votre routing, vous le déclarez&#8230; en JSX:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="jsx" style="font-family:monospace;">  render((
      &lt;Router history={browserHistory}&gt;
        &lt;Route path=&quot;/foo&quot; component={FooView}/&gt;
        &lt;Route path=&quot;/bar&quot; component={BarViw}/&gt;
      &lt;/Router&gt;
  ), document.getElementById('app'))</pre></td></tr></table></div>

<p>Votre app va devenir très vite une pyramide de composants, certains qui s&#8217;affichent, d&#8217;autres non, tous se passant en cascade des données les un aux autres.</p>
<p>Et au passage, quel est l&#8217;abruti qui a décidé des noms des méthodes des cycles de vie comme
<pre>getInitialState</pre>
<p>,
<pre>componentWillMount</pre>
<p> et
<pre>componentDidMount</pre>
<p> ? </p>
<p>Surtout que vos méthodes et les méthodes héritées de la classe du component sont dans le même espace de nom.</p>
<h2>Le bonheur des stores</h2>
<p>Un truc dont on peut vraiment se passer par contre, ce sont les stores. Flux, redux, vuex, etc. On peut utiliser n&#8217;importe quelles solutions pour stocker l&#8217;état de son projet côté client.</p>
<p>Mais si vous voulez profiter des promesses de react, comme le time travel et la concurrence parfaite, il vous faudra un store. </p>
<p>&#8220;store&#8221; c&#8217;est le nom huppé que react donne à ses modèles. Je ne vais pas rentrer dans les détails, et vous laissez décider par vous même du truc. Voici, comment la doc vous recommande d&#8217;ajouter une personne dans une liste d&#8217;un agenda avec redux, la store la plus populaire:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="jsx" style="font-family:monospace;">// Les imports
import React from 'react';
import { render } from 'react-dom';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
&nbsp;
// creation du store
const initialState = {'agenda': []};
&nbsp;
function reducer(state=initialState, action){
  switch (action.type) {
    case 'ADD_PERSON':
      return {
        'agenda': [..., action.object]
      }
    default:
      return state
  }
}
&nbsp;
const store = createStore(reducer);
&nbsp;
&nbsp;
// creatin de l'action d'ajouter un objet dans le store
&nbsp;
function addPersonAction(obj){
    return {
        'type': 'ADD_Person',
        'object': obj
    };
}
&nbsp;
&nbsp;
export function addPerson(Person){
    store.dispatch(addPersonAction(Person));
}
&nbsp;
&nbsp;
// composant qui affiche le form de l'agenda et la liste des personnes
var Agenda = React.createClass({
&nbsp;
  handleAdd: function(){
      addPerson({
        &quot;name&quot;: this.refs.name.value,
        &quot;tel&quot;: this.refs.tel.value
      })
  },
&nbsp;
  render: function(){
&nbsp;
    return &lt;form onClick={this.handleAdd}&gt;
        &lt;p&gt;&lt;input ref=&quot;name&quot; /&gt;&lt;input ref=&quot;tel&quot; /&gt;&lt;button&gt;Add&lt;/button&gt;&lt;/p&gt;
    &lt;/form&gt;
&nbsp;
    &lt;ul&gt;
        {
            this.store.agenda.map((pers) =&gt; (
                &lt;li&gt;&lt;strong&gt;{ pers.nom } &lt;/strong&gt;: { pers.tel } &lt;/li&gt;
            ))
        }
    &lt;/ul&gt;
  }
&nbsp;
&nbsp;
});
&nbsp;
&nbsp;
// adapter qui permet de passer le store à l'agenda
const AgendaContainer = connect(function(state){
    return {'agenda': state.get(&quot;agenda&quot;)};
})(Agenda);
&nbsp;
&nbsp;
// affichage du bouzin
render((
&lt;Provider store={store}&gt;
  &lt;AgendaContainer&gt;
&lt;/Provider&gt;
), document.getElementById('app'))</pre></td></tr></table></div>

<p>Vous imaginez bien que trouver ça tout seul a été un bonheur. Parce que oui, la doc est absolument à chier, dans la longue tradition des stacks JS moderns.</p>


feed_id: http://sametmax.com/?p=23281
title: Vue, j’l’avais pas vu Recently updated !
uri: Vue-j-l-avais-pas-vu-Recently-updated
url: http://sametmax.com/vue-jlavais-pas-vu/
content:
<p><em>(Pour max: je t&#8217;ai mis un exemple de code tout fait en bas de page car je sais que ça va te saouler de tout lire)<br />
</em><br />
Elle était facile, mais ça fait des années que le blog est up, je peux pas avoir de l&#8217;inspiration tout le temps.</p>
<p><a href="http://sametmax.com/reaction-a-reactjs/">Dans le dernier article</a>, je vous offrais votre dose maintenant obligatoire de bashing de l&#8217;écosystème JS. En l’occurrence en suggérant que React était un bouquet de roses avec plus d&#8217;épines que de pétales.</p>
<p>Mais bon, si les gens utilisent React, ça n&#8217;est pas QUE parce que c&#8217;est la mode. C&#8217;est parce que cette techno répond à un besoin de plus en plus impérieux en dev front end : avoir un outil valable pour créer des GUI avancées en JS.</p>
<p>Parce que le combo jQuery + moteur de template, ça nous a mené loin, mais on arrive au stade où ça scale plus.</p>
<p>Pas mal de tentatives ont été faites pour répondre au problème : knockout, angular 1, polymer, etc.</p>
<p>La nouvelle génération (react, riot, vue, angular 2+, etc) est beaucoup plus mature et performante, et offre des fonctionalités très sympas:</p>
<ul>
<li>DOM virtuel qui permet de faire des mises à jour fréquentes sur de tres nombreux objets à l&#8217;écran sans freezer le browser.</li>
<li>Découplage très élégant des données et de leur représentation.</li>
<li>Facilité de manipulation des éléments HTML, des events et du cycle de vie de tout le bordel.</li>
<li>Création de composants graphiques isolés et réutilisables.</li>
</ul>
<p>En gros, partout ou on faisait avant <code>$(selecteur).trucmuche(element)</code>, on peut maintenant faire ça plus facilement, plus rapidement et plus proprement. (Par contre Vue/React/etc font pas l&#8217;AJAX, tournez-vous vers <a href="https://github.com/mzabriskie/axios">axios</a> ou gardez jquery sous le coude).</p>
<p>Bon, si ils offrent TOUS ces éléments là, pourquoi diable est-ce que j&#8217;ai une préférence pour Vue.JS plutôt que Riot, Angular ou React ?</p>
<p>Souvenez-vous, je reprochais essentiellement ceci à React:</p>
<ul>
<li>Grosse courbe d&#8217;apprentissage. Ce qui impact la productivité de tout nouveau dans l&#8217;équipe.</li>
<li>Mauvaise ergonomie du JSX qui du coup s&#8217;écrit, se lit et se debug lentement.</li>
<li>Mauvaise foi totale de la communauté qui prétend qu&#8217;on peut utiliser React sans la tonne de nutella autour ce qui est comme argumenter qu&#8217;on peut faire du Java sans IDE.</li>
<li>Nutella sus-nommé qui est blindé d&#8217;huile de palme et de vidange.</li>
<li>Globalement une API inélégante et peu intuitive.</li>
</ul>
<p>Mais alors, qu&#8217;est-ce que <a href="https://vuejs.org/">Vue.js</a> fait de mieux ?</p>
<p>Ben tout, mes amis. Tout.</p>
<h2>Légèreté</h2>
<p>A l&#8217;heure où les codeurs hypes de la vibes du flexs ont tous un fichier de conf webpack de 3 km, mais déjà obsolète et qui pétera à la prochaine upgade, Vue offre un point de vue rafraichissant sur la question.</p>
<p>TOUTE, j&#8217;ai bien dis TOUTE, la puissance de vue.js est accessible avec une simple inclusion de balise script. </p>
<p>Vous en avez marre des pages de 3Mo ? Minifié et gzippé, Vue.js pèse moins de 30ko.</p>
<p>Dans un monde où il faut soit faire un site Web, soit faire une SPA (aux chiottes l&#8217;amélioration progressive !), Vue permet de ne remplacer que quelques bouts de vos pages si vous n&#8217;avez pas envie de tout transformer en un monstre de JS.</p>
<p>La doc, très bien faites, vous permettra de prendre l&#8217;outil en main en une après-midi. En buvant du thé.</p>
<p>Le tout, sans besoin d&#8217;aucun écosystème particulier. Aucun. Rien. Ca marche out of the box.</p>
<p>En gros, là où tout le monde vous vend du scale up, Vue vous permet de scale down.</p>
<h2>Puissance</h2>
<p>Malgré cela, Vue reste parfaitement adaptée aux gros projets. En fait, elle a été créé pour et par l&#8217;équipe du site du géant chinois, alibaba.com. Alors oui, c&#8217;est sur, c&#8217;est pas facebook et son milliard d&#8217;utilisateurs, mais comme mes projet ne servent pas 10 millions de pages par jour, contrairement à Alibaba, je pense que je suis ok.</p>
<p>Dans la pratique, qu&#8217;est-ce que ça veut dire ?</p>
<p>Et bien d&#8217;abord, <a href="http://www.stefankrause.net/wp/?p=316">Vue est plus rapide que React</a>. Ouai ça fait mal au cul de lire ça quand on vient de finir d&#8217;optimiser son pipeline de rendu JSX, surtout que la techno a été créé pour la vitesse. Mais voilà, c&#8217;est le cas.</p>
<p>Vue supporte aussi parfaitement l&#8217;inclusion dans un écosystème plus gros si le besoin s&#8217;en fait sentir :</p>
<ul>
<li>Vous pouvez utiliser Vue avec <a href="https://github.com/vuejs-templates/webpack">Webpack</a>.</li>
<li>Vous avez <a href="https://vuex.vuejs.org">une store</a> et <a href="https://vuex.vuejs.org">un routeur</a> pour vue.</li>
<li>Vous pouvez <a href="https://github.com/vuejs/babel-plugin-transform-vue-jsx">utilisez du JSX</a> si vous êtes maso.</li>
<li>Vous pouvez créer des SPA avec une hiérarchie de <a href="https://vuejs.org/v2/guide/components.html">composants</a>.</li>
<li>Vous pouvez faire le <a href="https://vuejs.org/v2/guide/ssr.html">rendu des templates côté serveur</a>.</li>
</ul>
<p>En gros, Vue peut faire absolument tout ce que les autres font. Mais ne vous oblige pas à commencer en sortant le bazooka. Vue est ce que React aurait du être depuis le début.</p>
<p>Notez qu&#8217;on peut remercier les devs de React pour avoir popularisé de nombreux concepts que Vue utilise. Standing on the giants&#8217; shoulders et tout, et tout. Vue n&#8217;aurait jamais existé sans React. Mais maintenant que Vue est là, on peut laisser React en paix.</p>
<h2>Elegance</h2>
<p>De part son design, Vue vous permet donc de commencer doucement, en ajoutant 30ko à votre projet et en l&#8217;utilisant un peu ici et là. Puis quand vous en avez besoin, vous pouvez commencer à utiliser des fonctionnalités avancées.</p>
<p>Par exemple, vous pouvez comme avec Angular 1 balancer toutes vos variables et binding dans le HTML de votre page en vrac. Et plus tard tout refactoriser en composant comme avec React. Tranquille.</p>
<p>L&#8217;API de Vue est petite, et surtout, facile à comprendre car tout est bien nommé, et bien rangé. Voyez plutôt:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;">Vue<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
  el<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;#app&quot;</span><span style="color: #339933;">,</span> <span style="color: #006600; font-style: italic;">// l'élément sur lequel attacher la vue</span>
  created<span style="color: #339933;">:</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>
    <span style="color: #006600; font-style: italic;">// code lancé au démarrage</span>
  <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
  mounted<span style="color: #339933;">:</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>
    <span style="color: #006600; font-style: italic;">// code lancé quand la vue est attachée à la page</span>
  <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
  updated<span style="color: #339933;">:</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>
    <span style="color: #006600; font-style: italic;">// code lancé quand la vue est mise à jour</span>
  <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
  destroyed<span style="color: #339933;">:</span> functon<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">// code lancé quand la vue est détruite</span>
  <span style="color: #009900;">&#125;</span>
  data<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">// ben ici y a vous données statiques</span>
  <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
  methods<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">// ici les fonctions à rendre disponibles dans le HTML</span>
  <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
  computed<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">// ici on met les données à recalculer à la volée</span>
    <span style="color: #006600; font-style: italic;">// a chaque refresh</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span></pre></td></tr></table></div>

<p>Voilà vous avez là 50% de l&#8217;API de Vue. Very hard indeed.</p>
<p>On sent partout que les devs ont apporté des soins à des petits détails comme:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="html" style="font-family:monospace;">&lt;!-- Lance truc() juste au premier click.
Appelle preventDefault automatiquement. --&gt;
&lt;a v-on:click.once.prevent=&quot;truc()&quot;&gt;Foo&lt;/a&gt;</pre></td></tr></table></div>

<p>D&#8217;une manière générale, tout template Vue est du HTML valide, ce qui fait qu&#8217;il est très facile d&#8217;insérer du Vue sur un site existant.</p>
<h2>Un petit bout de vue</h2>
<p>Mais alors, pour tous ceux qui en sont resté à jQuery et handlebar.js, à quoi ça ressemble tout ça ?</p>
<p>Ben un todo ressemble à ça en Vue:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="html" style="font-family:monospace;">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;title&gt;Todo&lt;/title&gt;
  &lt;script src=&quot;https://unpkg.com/vue&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;!-- Cette partie va être contrôlée par la vue --&gt;
&lt;div id=&quot;app&quot;&gt;
&nbsp;
&lt;!-- Quand on soumet le formulaire, on ajoute la tache --&gt;
&lt;form v-on:submit.prevent=&quot;addTask(newTask)&quot;&gt;
  &lt;!-- L'input est maintenant liée à la variable newTask --&gt;
  &lt;p&gt;&lt;input v-model=&quot;newTask&quot;&gt; &lt;button&gt;Ajouter&lt;/button&gt;&lt;/p&gt;
&lt;/form&gt;
&nbsp;
&lt;ul&gt;
  &lt;!-- Créer un li pour chaque tache dans mon array 'tasks' --&gt;
  &lt;li v-for=&quot;task in tasks&quot;&gt;{{task}}&lt;/li&gt;
&lt;/ul&gt;
&nbsp;
&lt;/div&gt;
&nbsp;
&lt;script type=&quot;text/javascript&quot;&gt;
app = new Vue({
  el: &quot;#app&quot;, // j'attache cette vue à l'élément avec l'id App
  data: {
    tasks: [], // mes taches seront stockées dans l'array 'tasks'
    newTask: &quot;&quot;, // ce que contient l'input du formulaire
  },
  methods: {
    addTask: function(task){
      this.tasks.push(task); // on ajoute la tache dans l'array
      this.newTask = &quot;&quot;; // on vide l'input
    }
  }
})
&lt;/script&gt;
&nbsp;
&lt;/body&gt;
&lt;/html&gt;</pre></td></tr></table></div>

<p>(Vous pouvez littéralement copiez-coller ce code dans un fichier todo.html et ça marche. Essayez de faire ça avec React&#8230;)</p>
<p>Comme avec Angular/React/Riot on a sépare complètement la logique de manipulation des données de celle de l&#8217;affichage qui est mis à jour automatiquement quand les données changent.</p>
<p>Contrairement à React, on est pas obligé de créer un arbre complexe de composants qui transforme toute sa page en soupe de JS(X). Mais contrairement à Angular, on est pas obligé de rester sur cet exemple simple, et on peut créer une hiérarchie de composants. </p>
<p>Un composant peut complètement isoler le JS, le HTML et le CSS (qui n&#8217;affecte alors que le composant):</p>
<p><img src="media/1fb760a1.vue-component.png" data-original-source="https://vuejs.org/images/vue-component.png"></img></p>
<p>Et pour que ça marche, pas besoin de préprocesseur, pas besoin de ES6, ES7, typescript, babel, webpack, npm&#8230; Vous pouvez les utiliser. Sur un gros projet je me fais chier à setup ce qui vaut le coup. Mais vous n&#8217;êtes pas obligé. </p>
<h2>La communauté</h2>
<p>La communauté est importante pour un projet, et celle de vue est très agréable. Ce sont des gens polis, humbles, et compétents. Ils pensent aux petits détails. Regardez par exemple <a href="https://vuex.vuejs.org/en/intro.html">cette page</a> pleine de jolis schémas.</p>
<p>En comparaison, la communauté React est crillarde. Les conf des devs de facebooks sont faites par <a href="https://www.youtube.com/watch?v=XxVg_s8xAms">des présentateurs tout droit sorti de south park</a>. Quand on critique react, on se fait insulter personnellement sur twitter par les fan boys plutôt que de tenter de discuter, preuve systématique de l&#8217;absence d&#8217;arguments.</p>
<p>Enfin les seuls éléments donnés pour combattre les critiques sont les raisons des problèmes, un rappel de la taille des utilisateurs et des &#8220;moi j&#8217;aime&#8221; laconiques.</p>
<p>Mais faites un test. Prenez 3 dev, un react, un jquery, un vue. Faites leur faire un agenda CRUD avec recherche et autocompletion qui tape en Ajax dans un backend Django/Rails/Whatever. Donnez leurs des machines vierges. Et sortez le pop corn.</p>
<p>Pour le moment, React possède encore deux avantages: react native, et la masse (fb, les utilisateurs, le nombre de plugins, etc). </p>
<p>Mais honnêtement ? Il y a très peu de bénéfices à utiliser React plutôt que Vue sur la plupart des projets pur Web. Et un coût garanti d&#8217;être élevé.</p>
<p>Angular 1 est en train de mourir de l&#8217;abandon de Google. Après la sucette de l&#8217;incompatibilité de d&#8217;Angular 2, je n&#8217;ai aucune confiance en la techno et ne compte donc pas réinvestir de billes dedans. De plus Angular 2+ souffre du même problème d&#8217;obligation d&#8217;installer la terre entière avant de commencer à coder.</p>
<p>Riot est une meilleure alternative, mais l&#8217;obligation de passer par des composants est un no-go IMO. Créer des composants pour moi est l&#8217;exception, pas la règle. Je le fais en dernier, à la phase de refactoring.</p>
<p>Donc ne vous emmerdez pas, prenez quelques heures pour jouer avec Vue, ça coute pas cher, et c&#8217;est chouette.</p>


feed_id: http://sametmax.com/?p=23369
title: Dell XPS 15 : une succession d’échecs 6
uri: Dell-XPS-15-une-succession-d-échecs-6
url: http://sametmax.com/dell-xps-15-une-succession-dechecs/
content:
<p>J&#8217;aimais beaucoup mon Samsung 9 series, mais quand on utilise à outrance sa machine il faut la remplacer régulièrement. J&#8217;ai opté pour un Dell XPS 15, une version 15 pouces du modèle phare de la marque, puisque le XPS 13 a tant d&#8217;excellents retours. Ça faisait des années que je trainais sur un 13 pouces, et je voulais voir si coder sur un 15 allait vraiment rajouter au confort.</p>
<p>Le XPS 15 a plusieurs atouts. D&#8217;abord un écran superbe, quasiment sans bord, donc plus large que les 15 pouces traditionnels. Ensuite une carte nvidia intégrée. Et surtout, un port USB C thunderbolt avec lequel on peut théoriquement charger le PC, brancher ses écrans, faire passer de l’Ethernet, bref la promesse du monocable sur mon bureau malgré mon setup encombrant de 3 écrans et la fibre.</p>
<p>Marchant très bien avec un dual boot W10/Ubuntu, j&#8217;en ai profité pour lui plugger 32Go de Ram et 1To de SSD. La bestiole est donc supposé être un monstre de guerre qui devrait pouvoir avaler du travail de dev dans des conditions féériques.</p>
<p>Après quelques mois d&#8217;utilisation, je peux vous affirmer que le produit n&#8217;est pas du tout à la hauteur du prix, à savoir plus de 2000 boules.</p>
<p>Bien que l&#8217;écran soit effectivement très confortable, et que les applications de tous les jours tournent sans soucis, l’intérêt du XPS 15 s&#8217;arrête là.</p>
<p>D&#8217;abord, il est lourd, le chargeur est énorme, et la batterie tient en moyenne 3H, pitoyable de nos jours. Ce n&#8217;est donc pas le meilleur amis du voyageur.</p>
<p>Mais surtout, il ne marche pas correctement. Et c&#8217;est bien ça le problème.</p>
<p>Pendant un mois les baffles ont tout simplement arrêter de produire un son cohérent, vomissant tel un metalleux bourré sans son micro la moindre note. Puis c&#8217;est revenu, sans explication, à la normale.</p>
<p>Un autre mois des écrans bleus incessant m&#8217;empêchaient tout simplement d&#8217;utiliser Windows jusqu&#8217;à ce que je tombe sur <a href="http://en.community.dell.com/support-forums/laptop/f/3519/t/20009401">un thread de forum de support Dell</a> que la marque a ignoré pendant longtemps. Un des utilisateurs recommande de downgrader le firmware du BIOS pour remédier au problème. Effectivement, ça marche.</p>
<p>Mais la réaction de Dell ? Désolé d&#8217;avoir niqué votre machine a un SMIC et demi ? Naaaa. Un mec poste laconiquement une video youtube d&#8217;un utilisateur sur internet d&#8217;une solution qui n&#8217;a pas marché pour moi. Et c&#8217;est tout. Le logiciel d&#8217;update DELL continue de suggérer des mises à jours qui refond planter tout le système. </p>
<p>Le port USB-C ne tient aucune de ses promesses. Parfoit la charge s&#8217;arrête en cours de route sans prévenir. L’Ethernet n&#8217;a pas marché pendant plusieurs mois pour soudainement s&#8217;activer, mais uniquement sous Windows. Le triple écran qui marchait parfaitement sous Ubuntu et Windows a cessé de fonctionner sans prévenir. Maintenant au mieux je fais du dual screen sous Windows uniquement.</p>
<p>Si vous lancez un jeu, le laptop décide de temps en temps de faire tourner soudainement le CPU en mode éco, tuant les FPS et vous faisant perdre. Il se trouve que la machine chauffe trop, ce que vos doigts auraient pu vous signaler de toute façon. A croire que les ingés qui l&#8217;ont conçu n&#8217;ont jamais testé l&#8217;engin. </p>
<p>La solution ? Beaucoup de recherches (parce que j&#8217;ai que ça à faire, pallier aux erreurs de Dell sur une machine que j&#8217;ai payé cher pour gagner du temps dans mon travail) pour atterrir sur un autre thread du support Dell. Quelqu&#8217;un suggère de désactiver dans le BIOS Intel step. Ça marche, mais bouffe plus encore la maigre autonomie de la batterie.</p>
<p>Ce n&#8217;est pas la qualité de produit qu&#8217;on peut attendre d&#8217;une marque comme Dell, ni d&#8217;un modèle à ce prix. Mais surtout, l&#8217;absence totale de communication de Dell sur la question, le manque de réaction de leur part laisse à pensez qu&#8217;ils ont fait une grosse erreur sur ce produit et espèrent que ça passe en faisant le mort.</p>
<p>Sinon j&#8217;ai aussi acheté un téléphone One Plus à la même époque, qui lui est toujours formidable pour un prix avantageux. Histoire de finir sur une note positive&#8230;</p>


feed_id: http://sametmax.com/?p=23385
uri: Accepter-un-ID-mais-retourner-un-objet-pour-les-liens-de-Django-Rest-F
url: http://sametmax.com/accepter-un-id-mais-retourner-un-objet-pour-les-liens-de-django-rest-framework/
title:
Accepter un ID mais retourner un objet pour les liens de Django Rest Framework 2   Recently updated !

content:
<p>DRF est une des perles de Django. De Python même. Comme marshmallow, requests, jupyter, pandas, SQLAlchemy ou l&#8217;admin Django. Python a tellement de libs extraordinaires.</p>
<p>Mais aucune n&#8217;est parfaite, et une chose qui m&#8217;a toujours emmerdé avec celle-ci, c&#8217;est que si j&#8217;ai un modèle du genre:</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> Foo<span style="color: black;">&#40;</span>models.<span style="color: black;">Model</span><span style="color: black;">&#41;</span>:
    name <span style="color: #66cc66;">=</span> models.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>max_lengt<span style="color: #66cc66;">=</span><span style="color: #ff4500;">64</span><span style="color: black;">&#41;</span>
    bar <span style="color: #66cc66;">=</span> models.<span style="color: black;">ForeignKey</span><span style="color: black;">&#40;</span>Bar<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Et le serializer:</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> FooSerialize<span style="color: black;">&#40;</span>serilizers.<span style="color: black;">ModelSerializer</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">class</span> Meta:
        model <span style="color: #66cc66;">=</span> Foo</pre></td></tr></table></div>

<p>J&#8217;ai le choix entre soit avoir que des ID&#8230;</p>
<p>En lecture (chiant) :</p>
<pre>GET /api/foos/1/

{
    name: "toto",
    bar: 2
}</pre>
<p>Et en écriture (pratique) :</p>
<pre>POST /api/foos/
{
    name: "tata",
    bar: 2
}</pre>
<p>Soit avoir que des objets.</p>
<p>En lecture (pratique):</p>
<pre>GET /api/foos/1/

{
    name: "toto",
    bar: {
       // tout l'objet bar disponible en lecture
    }
}
</pre>
<pre>
Et en écriture (chiant) :

POST /api/foos/
{
    name: "tata",
    bar: {
       // tout l'objet bar à se taper à écrire
    }
}</pre>
<p>Il y a aussi la version hypermedia où l&#8217;id est remplacé par une URL. Mais vous voyez le genre : mon API REST est soit pratique en lecture mais relou à écrire, soit pratique en écriture (je fournis juste une référence), mais relou en lecture, puisque je dois ensuite fetcher chaque référence.</p>
<p>GraphQL répond particulièrement bien à ce problème, mais bon, la techno est encore jeune, et il y a encore plein d&#8217;API REST à coder pour les années à venir.</p>
<p>Comment donc résoudre ce casse-tête, Oh Sam! &#8211; sauveur de la pythonitude ?</p>
<h2>Solution 1, utiliser un serializer à la place du field</h2>

<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> FooSerializer<span style="color: black;">&#40;</span>serilizers.<span style="color: black;">ModelSerializer</span><span style="color: black;">&#41;</span>:
&nbsp;
    bar <span style="color: #66cc66;">=</span> BarSerializer<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">class</span> Meta:
        model <span style="color: #66cc66;">=</span> Foo</pre></td></tr></table></div>

<p>Et là j&#8217;ai bien l&#8217;objet complet qui m&#8217;est retourné. Mais je suis en lecture seul, et il faut que je fasse l&#8217;écriture à la main. Youpi.</p>
<p>Pas la bonne solution donc.</p>
<h2>Solution 2, écrire deux serializers</h2>
<p>Ben ça marche mais il faut 2 routings, ça duplique l&#8217;API, la doc, les tests. Moche. Next.</p>
<h2>Solution 3, un petit hack</h2>
<p>En lisant le code source de DRF (ouai j&#8217;ai conscience que tout le monde à pas la foi de faire ça), j&#8217;ai noté que <code>ModelSerializer</code> génère automatiquement pour les relations un <code>PrimaryKeyRelatedField</code>, qui lui même fait le lien via l&#8217;ID. On a des classes similaires pour la version full de l&#8217;objet et celle avec l&#8217;hyperlien.</p>
<p>En héritant de cette classe, on peut créer une variante qui fait ce qu&#8217;on veut:</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;">collections</span> <span style="color: #ff7700;font-weight:bold;">import</span> OrderedDict
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> rest_framework <span style="color: #ff7700;font-weight:bold;">import</span> serializers
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> AsymetricRelatedField<span style="color: black;">&#40;</span>serializers.<span style="color: black;">PrimaryKeyRelatedField</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># en lecture, je veux l'objet complet, pas juste l'id</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> to_representation<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> value<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">serializer_class</span><span style="color: black;">&#40;</span>value<span style="color: black;">&#41;</span>.<span style="color: black;">data</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># petite astuce perso et pas obligatoire pour permettre de taper moins </span>
    <span style="color: #808080; font-style: italic;"># de code: lui faire prendre le queryset du model du serializer </span>
    <span style="color: #808080; font-style: italic;"># automatiquement. Je suis lazy</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> get_queryset<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;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">queryset</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">queryset</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">serializer_class</span>.<span style="color: black;">Meta</span>.<span style="color: black;">model</span>.<span style="color: black;">objects</span>.<span style="color: #008000;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Get choices est utilisé par l'autodoc DRF et s'attend à ce que </span>
    <span style="color: #808080; font-style: italic;"># to_representation() retourne un ID ce qui fait tout planter. On </span>
    <span style="color: #808080; font-style: italic;"># réécrit le truc pour utiliser item.pk au lieu de to_representation()</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> get_choices<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> cutoff<span style="color: #66cc66;">=</span><span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
        queryset <span style="color: #66cc66;">=</span> <span style="color: #008000;">self</span>.<span style="color: black;">get_queryset</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> queryset <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> cutoff <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">None</span>:
            queryset <span style="color: #66cc66;">=</span> queryset<span style="color: black;">&#91;</span>:cutoff<span style="color: black;">&#93;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">return</span> OrderedDict<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>
            <span style="color: black;">&#40;</span>
                item.<span style="color: black;">pk</span><span style="color: #66cc66;">,</span>
                <span style="color: #008000;">self</span>.<span style="color: black;">display_value</span><span style="color: black;">&#40;</span>item<span style="color: black;">&#41;</span>
            <span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">for</span> item <span style="color: #ff7700;font-weight:bold;">in</span> queryset
        <span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># DRF saute certaines validations quand il n'y a que l'id, et comme ce </span>
    <span style="color: #808080; font-style: italic;"># n'est pas le cas ici, tout plante. On desactive ça.</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> use_pk_only_optimization<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;">False</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Un petit constructeur pour générer le field depuis un serializer. lazy,</span>
    <span style="color: #808080; font-style: italic;"># lazy, lazy...</span>
    <span style="color: #66cc66;">@</span><span style="color: #008000;">classmethod</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> from_serializer<span style="color: black;">&#40;</span>cls<span style="color: #66cc66;">,</span> serializer<span style="color: #66cc66;">,</span> name<span style="color: #66cc66;">=</span><span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> args<span style="color: #66cc66;">=</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> kwargs<span style="color: #66cc66;">=</span><span style="color: black;">&#123;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> name <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span>:
            name <span style="color: #66cc66;">=</span> f<span style="color: #483d8b;">&quot;{serializer.__class__.name}AsymetricAutoField&quot;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>name<span style="color: #66cc66;">,</span> <span style="color: black;">&#91;</span>cls<span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;serializer_class&quot;</span>: serializer<span style="color: black;">&#125;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Et du coup:</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> FooSerializer<span style="color: black;">&#40;</span>serializers.<span style="color: black;">ModelSerializer</span><span style="color: black;">&#41;</span>:
&nbsp;
    bar <span style="color: #66cc66;">=</span> AsymetricRelatedField<span style="color: black;">&#40;</span>BarSerializer<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">class</span> Meta:
        model <span style="color: #66cc66;">=</span> Foo</pre></td></tr></table></div>

<p>Et voilà, on peut maintenant faire:</p>
<pre>
GET /api/foos/1/

{
    name: "toto",
    bar: {
       // tout l'objet bar disponible en lecture
    }
}

POST /api/foos/
{
    name: "tata",
    bar: 2
}</pre>
<p>Elle est pas belle la vie ?</p>
<p>Ca serait bien cool que ce soit rajouté officiellement dans DRF tout ça. Je crois que je vais <a href="https://github.com/encode/django-rest-framework/issues/5206">ouvrir un ticket</a>&#8230;</p>


feed_id: http://sametmax.com/?p=23443
title: Les plus grosses roues du monde 6 Recently updated !
uri: Les-plus-grosses-roues-du-monde-6-Recently-updated
url: http://sametmax.com/les-plus-grosses-roues-du-monde/
content:
<p>L&#8217;avantage d&#8217;avoir quelques années de programmations dans les pattes et un certain nombres de projets à son actif, c&#8217;est qu&#8217;on arrive à identifier des motifs communs qui se dégagent encore et encore.</p>
<p>Par exemple, quand j&#8217;étais en tout début de carrière, j&#8217;ai ouvert l&#8217;excellent bouquin &#8220;Head first design patterns&#8221; et je n&#8217;en ai pas  retiré grand chose car je n&#8217;avais pas la matière pour pouvoir identifier l&#8217;utilité des solutions proposées. Bien plus tard, en le relisant, je me suis aperçu que j&#8217;avais en fait rencontré moult fois chaque chapitre IRL, base de code après base de code.</p>
<p>La vie apprend les design patterns bien plus efficacement que les écrits. Mais ces derniers ont l&#8217;avantage de mettre de l&#8217;ordre dans ses idées. Ils mettent des mots sur des pensées floues, et tracent des contours qui délimitent pragmatiquement les concepts.</p>
<p>Aujourd&#8217;hui néanmoins, nous n&#8217;allons pas parler de design pattern, bien que faire un dossier dessus serait une bonne idée. Mais ça fait des mois que je dois finir le dossier tests unitaires, alors je vais pas commencer un nouveau dossier.</p>
<p>Non, aujourd&#8217;hui, nous allons parler d&#8217;outils dont on a besoin dans quasiment tous les projets important et qu&#8217;on réinvente, ou rapièce, presque à chaque fois.</p>
<h2>Dispatching</h2>
<p>Que ce soit parce que vous avez un observer, du pub/sub, un système de routing ou des events internes, votre projet finira par avoir besoin d&#8217;un système de dispatching. Le dispatching c&#8217;est la propagation/distribution de l&#8217;information et de son traitement.</p>
<p>Ils ont toujours la même chose en commun:</p>
<ul>
<li>Des points centraux qui prennent les entrées et les dirigent vers les bonnes sorties.</li>
<li>Un système d&#8217;enregistrement des points d&#8217;entrées (hooks) et des points de sorties (endpoints).</li>
<li>Une logique de résolution qui permet de faire transiter les données depuis une entrée, vers une ou plusieurs sorties, parfois aller-retour.</li>
</ul>
<p>Par exemple:</p>
<ul>
<li>Le pub/sub de redis ou crossbar.io.</li>
<li>Le routing URL d&#8217;un framework Web comme Django ou Rails.</li>
<li>Les events d&#8217;un UI comme le addEventListener en JS ou connect() en QT.</li>
<li>La remontée hiérarchique des messages de logs dans le module Python logging.</li>
</ul>
<p>Ce sont tous des implémentations spécialisées d&#8217;un système de dispatching. Le hello world du dispatching est le design pattern observer, qui minimalement ressemble à ç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> <span style="color: #ff7700;font-weight:bold;">class</span> Dispatcher:
...     <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: #008000;">self</span>.<span style="color: black;">registry</span> <span style="color: #66cc66;">=</span> <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
...     <span style="color: #ff7700;font-weight:bold;">def</span> on<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> event<span style="color: #66cc66;">,</span> callback<span style="color: black;">&#41;</span>:
...         <span style="color: #008000;">self</span>.<span style="color: black;">registry</span>.<span style="color: black;">setdefault</span><span style="color: black;">&#40;</span>event<span style="color: #66cc66;">,</span> <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span>callback<span style="color: black;">&#41;</span>
...     <span style="color: #ff7700;font-weight:bold;">def</span> trigger<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> event<span style="color: black;">&#41;</span>:
...         <span style="color: #ff7700;font-weight:bold;">for</span> callback <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">self</span>.<span style="color: black;">registry</span><span style="color: black;">&#91;</span>event<span style="color: black;">&#93;</span>:
...                 <span style="color: black;">callback</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
... 
... <span style="color: black;">hub</span> <span style="color: #66cc66;">=</span> Dispatcher<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
... 
... <span style="color: black;">hub</span>.<span style="color: black;">on</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;j'arrive&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">lambda</span>: <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'coucou'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
... <span style="color: black;">hub</span>.<span style="color: black;">on</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;j'arrive&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">lambda</span>: <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'salut'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
... 
... <span style="color: black;">hub</span>.<span style="color: black;">trigger</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;j'arrive&quot;</span><span style="color: black;">&#41;</span>
... 
<span style="color: black;">coucou</span>
salut</pre></td></tr></table></div>

<p>En fait, à moins de faire uniquement des scripts, vous avez utilisé plein de systèmes de dispatching sans le savoir.</p>
<p>Bien que pour qu&#8217;ils soient utiles il faut des versions spécialisées pour chaque usage, c&#8217;est un problème générique et il est ridicule que nous devions réimplementer à chaque fois ce truc. Un bon système de dispatching est utile dans tout gros projet. Vous voulez permettre à quelqu&#8217;un de lancer du code quand votre système s&#8217;initialise ? Créer une logique de plugin ? Bam, il faut du dispatching.</p>
<p>Il faudrait donc un framework en Python qui permette de fabriquer son propre système de dispatching. Il devra bien entendu inclure des implémentations spécialisées au moins pour les cas les plus courants sinon ça fera comme une lib zope et ça prendra la poussière.</p>
<p>Le but étant qu&#8217;au bout de quelques années, tout le monde base son implémentation sur cette brique, robuste et documentée, plutôt que de créer son propre système.</p>
<p>En effet, un bon système de dispatching doit pouvoir gérer les cas suivants :</p>
<ul>
<li>Mono directionel ou bi-directionel.</li>
<li>Un ou plusieurs endpoints.</li>
<li>Middlewares.</li>
<li>Algo de routing custo.</li>
<li>Passage de paramètres à l&#8217;ajout d&#8217;un enpoint.</li>
<li>Passage de contexte à l&#8217;appel de l&#8217;endpoint.</li>
<li>Appel synchrone ou asynchrone des endpoints</li>
<li>Enpoint locaux ou remotes.</li>
<li>Gestions de plusieurs dispatchers en parallèle.</li>
<li>Interconnection de plusieurs dispatchers.</li>
<li>Adapters pour les dispatchers courants déjà existants.</li>
</ul>
<p>Le tout bien entendu avec des backends pour chaque partie qu&#8217;on puisse swapper.</p>
<h2>Configuration</h2>
<p>La conf, c&#8217;est l&#8217;exemple exacte de la fragmentation dans notre métier. C&#8217;est l&#8217;usine a roues (carrées) réinventées.</p>
<p>Sérieusement, entre le parsing des arguments de la ligne de commande, les fichiers de config, les services de config (etcd anyone ?), les configs sauvegardées en BDD, les API de conf, les variables d&#8217;environnement, etc. c&#8217;est un bordel sans nom.</p>
<p>Tout le monde a fait son petit fichier params.(ini|yml|xml|json) et ou sa table SQL settings dans un coin. Et la validation. Et la génération. Et les valeurs par défaut. Et l&#8217;overriding des envs. Ca change à chaque projet, à chaque framework, à chaque foutu lib.</p>
<p>C&#8217;est que le but est simple, mais le problème est complexe. Mais on en a tous besoin, et il n&#8217;y a rien, mais alors rien qui existe de générique.</p>
<p>Une bonne lib de conf doit:</p>
<ul>
<li>Offrir une API standardisée pour définir les paramètres qu&#8217;attend son programme sous la forme d&#8217;un schéma de données.</li>
<li>Permettre de générer depuis ce schéma les outils de parsing de la ligne de commande et des variables d&#8217;env.</li>
<li>Permettre de générer depuis ce schéma des validateurs pour ces schémas.</li>
<li>Permettre de générer des API pour modifier la conf</li>
<li>Permettre de générer des UIs pour modifier la conf</li>
<li>Séparer la notion de configuration du programme des paramètres utilisateurs.</li>
<li>Pouvoir marquer des settings en lecture seule, ou des permissions sur les settings.</li>
<li>Notifier le reste du code (ou des services) qu&#8217;une valeur à été modifiée. Dispatching, quand tu nous tiens&#8230;</li>
<li>Charger les setting depuis une source compatible (bdd, fichier, api, service, etc).</li>
<li>Permettre une hierarchie de conf, avec une conf principales, des enfants, des enfants d&#8217;enfants, etc. et la récupération de la valeur qui cascade le long de cette hierarchie. Un code doit pouvoir plugger sa conf dans une branche de l&#8217;arbre à la volée.</li>
<li>Fournir un service de settings pour les architectures distribuées.</li>
<li>Etre quand même utile et facile pour les tous petits scripts.</li>
<li>Auto documentation des settings.</li>
</ul>
<p>Pas évident non ? Ça change de &#8220;ah bah je vais dumper tout ça dans un settings.py et on verra bien&#8221; :)</p>
<p>Les bénéfices d&#8217;avoir un bon système de settings sont énormes. D&#8217;abord, si il est largement adopté, plus besoin de fouiller dans la doc de chaque projet pour savoir comment l&#8217;utiliser. Les problèmes difficiles comme les &#8220;live settings&#8221; sont réglés une fois pour toute. Plus besoin d&#8217;écrire pour la millième fois le code de glue entre son schéma marshmallow + ses params clicks + son parser yml qui sera forcément bricolé. Et une expérience utilisateur bien meilleure avec de la doc, des messages standardisés, des checks de sources de données que d&#8217;habitude personne ne fait, etc. </p>
<h2>Logging</h2>
<p>Oui, je sais, je sais, Python a un excellent module de logging, très riche et polyvalent. Et puis ce ne sont pas les projets de logging qui manquent. Il y a celui de twisted, il y a logbook, logpy&#8230; En fait ĵ&#8217;ai même pondu <a href="https://github.com/sametmax/devpy">devpy</a>.</p>
<p>Malgré ça, force est de constater que tous ces projets sont loin d&#8217;être une bonne solution pour convenir à tous.</p>
<p>Le module logging Python manque de configuration par défaut, n&#8217;a pas de gestion multiprocessing, aucune facilité pour générer des logs structurés ou binaires, etc. logbook et logpy sont des surcouches qui améliorent, mais sans aller assez loin, l&#8217;expérience. Twisted comme d&#8217;hab fait le café mais est indigeste. Logpy n&#8217;est bien que pour les cas simples.</p>
<p>Un bon module de logging devrait:</p>
<ul>
<li>Etre compatible avec la stdlib, et avoir des adaptateurs pour les systèmes les plus courants (comme twisted).</li>
<li>Gérer le multiproccessing, particulièrement le locking des fichiers ou avoir un process central dédié au log.</li>
<li>Proposer une UI user friendly de consommation des logs.</li>
<li>Avoir des pré-configuration prête à l&#8217;usage hyper simple et rapide à utiliser pour les cas les plus simples, comme le scripting. </li>
<li>Gérer des formats avancées: json, binaires, nesting, log structurés, etc. Avec des recettes toutes faites pour les cas courants.</li>
<li>Avoir une bonne intégration avec les systèmes de logs natifs de l&#8217;OS sans besoin de trifouiller.</li>
<li>Proposer des outils d&#8217;analyse de logs.</li>
<li>Offre des solutions pour les cas simples (console, fichier, coloration, post-mortem, etc) ou complexe mais courants (mail, logstash, sentry, log sur serveur distant, etc).</li>
</ul>
<p>Au fait, aviez-vous notez que le cœur d&#8217;un système de log est un dispatcheur ? :)</p>
<h2>Lifecyle</h2>
<p>Dès que vous créez un projet, il a un cycle de vie. Il s&#8217;initialise, charge les paramètres, load les plugins si il y en a, lance son processus principal, puis finit par s&#8217;arrêter, ou foirer, ou les deux.</p>
<p>Si c&#8217;est un petit script, ce n&#8217;est pas très important, on ne s&#8217;en rend même pas compte. </p>
<p>Si c&#8217;est un gros projet, vous allez vouloir que le code du reste du monde puisse interagir avec ça. D&#8217;ailleurs, tous les gros frameworks vous permettent de réagir au cycle de vie. Django a le fichier appconfig.py par exemple pour lancer du code au démarrage du framework, et des middlewares pour intercepter les requêtes et les réponses. Twisted permet de dire &#8220;lance ce code à dès que le reactor est en route&#8221;. Pour comprendre Angular ou une app Android, la moitiée du boulot c&#8217;est de piger les différentes phases du cycle de chaque composant.</p>
<p>Le cycle de vie est en fait un système de dispatching (surprise !) couplé à une machine à état fini, et concrétisé dans un processus metier. La bonne nouvelle, c&#8217;est que des libs de state machines en Python on en a un max, et des bien fournies. La mauvaise, c&#8217;est qu&#8217;avec la popularité grandissante d&#8217;asyncio, on a de plus en plus besoin de gérer explicitement le cycle de vie de ses projets et qu&#8217;on a rien de générique pour ça alors la cyclogénèse envahie la communauté. </p>
<p>En effet, dès qu&#8217;on a une boucle d&#8217;événement comme avec asyncio/twisted/tornado, on a un cycle de vie complexe mais implicite qui se met en place puisque la loop démarre, s&#8217;arrête, est supprimée, est remplacée, est en train d&#8217;exécuter une tâche, une tâche qui peut générer des erreurs&#8230; Et très vite le cycle dégouline de partout, et on commence à coder ici et là pour gérer tout ça sans se rendre compte qu&#8217;on créer petit à petit un énième framework de lifecycle. Pas vrai Gordon ?</p>
<p>C&#8217;est l&#8217;histoire de la viiiiiiiiiiiiiiiie. C&#8217;est le cycle éterneleuuuuuuuuuh. De la roue infinieeeeeeee. Codée à la truelleuuuuuuh.</p>
<h2>Structure de projet</h2>
<p>Bon, imaginons que vous ayez une lib de life cycle, qui charge vos settings avec votre super lib de conf, log tout grâce à votre géniale lib de logging, le tout powered par une lib de dispatching que le monde vous envie. Le perfide.</p>
<p>Je dis &#8220;imaginez&#8221; parce que dans votre projet vous avez plutôt un tas de crottes retenues par un cornet de glace que vous avez codé pour la enième fois à la va vite en utilisant 30% de libs terce partie, 30% d&#8217;outils votre framework du jour et 40% de roux (du NIH sans ame quoi&#8230;).</p>
<p>Donc imaginez ça. Et maintenant vous voulez mettre en place un moyen de diviser votre projet en sous parties. Peut être des apps, ou pourquoi pas des plugins. Mais vous voudriez que tout ça soit gérable par un point d&#8217;entrée principal, ou individuellement. Que ça se plug dynamiquement. Que ça joue bien avec votre système de conf et de lifecyle. Diantres vous voulez qu&#8217;un code externe puisse être découvert et pluggé au système. Choisir si ça tourne dans des threads ou des processus séparés. Mais communiquer entre les partie. Et que tout ça soit découplé bien entendu ! Sauf qu&#8217;il y a une gestion de dépendance des plugins&#8230;</p>
<p>Pas de problème, vous prenez un bus de communication, un système de plugin, un graph de résolution de dépendances, vos super libs ci-dessus et vous gluez tout ça avec de la logique de chez mémé et de la sueur. Une mémé si ronde qu&#8217;elle a un pneu autour de la taille. Et un essieu.</p>
<p>Django a ses apps. jQuery a ses plugins. L&#8217;app d&#8217;un de mes clients avec un hack a base d&#8217;importlib et ctype qui loadait une dll pour charger les drivers de leur matos. Ca roule Maurice, ça roule à mort.</p>
<p>Il nous faut une lib de référence qui permette:</p>
<ul>
<li>De diviser son projets en plus petites unités tout en gardant un point central pour faire le lien</li>
<li>De découvrir, charger et décharger ces unités.</li>
<li>Permettre de répartir ces unités dans des threads, multiprocess, machines.</li>
<li>Les faire communiquer.</li>
</ul>
<h2>Et dans les ténèbres les lier</h2>
<p>Une fois qu&#8217;on a tout ça, il faut bien entendu un gros framework qui permette de faire le lien entre tout ça et coder un projet automatiquement intégré.</p>
<p>Imaginez&#8230; Imaginez pouvoir faire un truc comme ç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;">from</span> super_framework <span style="color: #ff7700;font-weight:bold;">import</span> projets<span style="color: #66cc66;">,</span> config
&nbsp;
<span style="color: #808080; font-style: italic;"># Tout est configurable et réassemblable, mais le framework offre des réglages </span>
<span style="color: #808080; font-style: italic;"># auto pour les usages simples</span>
project<span style="color: #66cc66;">,</span> app<span style="color: #66cc66;">,</span> conf <span style="color: #66cc66;">=</span> projets.<span style="color: black;">SimpleProject</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'name'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Fichier de conf automatiquement créé, parsé et vérifié. Valeurs exposées en </span>
<span style="color: #808080; font-style: italic;"># CLI et overridables.</span>
<span style="color: #66cc66;">@</span>config.<span style="color: black;">source</span><span style="color: black;">&#40;</span><span style="color: #008000;">file</span><span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;foo.tml&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Schema<span style="color: black;">&#40;</span>config.<span style="color: black;">Schema</span><span style="color: black;">&#41;</span>:
    foo <span style="color: #66cc66;">=</span> config.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span>max_len<span style="color: #66cc66;">=</span><span style="color: #ff4500;">30</span><span style="color: #66cc66;">,</span> live<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
    bar <span style="color: #66cc66;">=</span> config.<span style="color: black;">DateField</span><span style="color: black;">&#40;</span>optional<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: #66cc66;">,</span> local<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
    baz <span style="color: #66cc66;">=</span> config.<span style="color: black;">TextField</span><span style="color: black;">&#40;</span>
        verbose_name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;Basile&quot;</span><span style="color: #66cc66;">,</span> 
        default<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;Je sers la science et c'est ma joie&quot;</span>
    <span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Lancé automatiquement à la phase d'init du projet</span>
<span style="color: #808080; font-style: italic;"># Des events comme ça sont lancés pour chaque app, et chaque phase de vie de </span>
<span style="color: #808080; font-style: italic;"># chacune d'elles.</span>
project.<span style="color: black;">on</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'init'</span><span style="color: black;">&#41;</span>
async <span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span>context<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># un log sain automatiquement fourni</span>
    app.<span style="color: black;">log</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Debut du projet. Verbosité:'</span><span style="color: #66cc66;">,</span> conf.<span style="color: black;">log</span>.<span style="color: black;">level</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Démarre l'event loop. Parse la ligne ligne de commande et les </span>
<span style="color: #808080; font-style: italic;"># variables d'env, puis le fichier de conf. Mais seulement si le module n'est </span>
<span style="color: #808080; font-style: italic;"># pas importé (comme __name__ == &quot;__main__&quot;)</span>
<span style="color: #808080; font-style: italic;"># Print le fichier de log automatique dès le démarrage du programme</span>
project.<span style="color: #dc143c;">cmd</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Et imaginez que de ce petit script, ça scale sur 20 plugins qui peuvent communiquer, un système de settings live, de gestion d&#8217;erreurs et de logs aux petits oignons. </p>
<p>Imaginez que l&#8217;api bas niveau soit suffisamment flexible pour que les plus grand framework puisse réécrire exactement la même API qu&#8217;ils ont déjà en utilisant cette fondation. Imaginez que tous vos projets futures soient du coup compatibles entre eux.</p>
<p>Vous pouvez imaginez longtemps, car ça n&#8217;arrivera jamais. Mais j&#8217;avais du temps à l&#8217;aéroport alors j&#8217;ai écris cet article.</p>


feed_id: http://sametmax.com/?p=23459
title: Alternative au do…while en Python 5 Recently updated !
uri: Alternative-au-do-while-en-Python-5-Recently-updated
url: http://sametmax.com/alternative-au-do-while-en-python/
content:
<p>De nombreuses instructions ont été volontairement écartées de Python. Le <code>goto</code> bien entendu, mais aussi le <code>switch</code>, <code>unless</code> et le <code>do...while</code>.</p>
<p>Le but est de limiter le nombre de mots clés à connaitre afin de comprendre le langage. Les créateurs ont choisi donc de mettre de côté des mots clés trop souvent mal utilisés, pas assez utilisés, ou qui possèdent des alternatives suffisantes.</p>
<p>La boucle <code>while</code> est rarement utilisée en Python, en tout cas beaucoup, beaucoup moins que sa petit soeur la boucle <code>for</code>. Avoir besoin d&#8217;un <code>do...while</code> est encore plus rare, et donc ne peut faire partie du club très fermé des mots clés réservés.</p>
<p>Si l&#8217;on souhaite obtenir l&#8217;effet du <code>do..while</code> en python, on fait donc généralement une boucle infinie suivie d&#8217;un break sur une condition. 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;">import</span> <span style="color: #dc143c;">random</span>
&nbsp;
choix <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">random</span>.<span style="color: black;">randint</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
    reponse <span style="color: #66cc66;">=</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #008000;">input</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Devinez le nombre: '</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> reponse <span style="color: #66cc66;">&lt;</span> choix:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Plus grand'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">elif</span> reponse <span style="color: #66cc66;">&gt;</span> choix:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Plus petit'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">break</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Bravo'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Le défaut de cette technique et qu&#8217;elle ne rend pas claire dès le début la condition de sortie de la boucle. Aujourd&#8217;hui en parcourant la mailling list python-idea, je suis tombé sur un idée pas conne:</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;">random</span>
&nbsp;
choix <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">random</span>.<span style="color: black;">randint</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #483d8b;">&quot;L'utilisateur n'a pas encore deviné le nombre&quot;</span>:
    reponse <span style="color: #66cc66;">=</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #008000;">input</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Devinez le nombre: '</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> reponse <span style="color: #66cc66;">&lt;</span> choix:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Plus grand'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">elif</span> reponse <span style="color: #66cc66;">&gt;</span> choix:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Plus petit'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">break</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Bravo'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Ca marche car les chaînes non vides sont toujours vraie en Python, et ça documente le code :)</p>


feed_id: http://sametmax.com/?p=23488
title: Caldigit et USB-C 5
uri: Caldigit-et-USB-C-5
url: http://sametmax.com/caldigit-et-usb-c/
content:
<p>Mon rêve d&#8217;avoir un setup tri-écran, ethernet, casque-micro et chargement avec un seul cable est enfin devenu une réalité. </p>
<p>Et ça a pas été de la tarte.</p>
<p>J&#8217;ai un <a href="http://sametmax.com/dell-xps-15-une-succession-dechecs/">Dell XPS 15</a> qui a un port USB-C avec thunderbolt. J&#8217;ai acheté un dock <a href="http://www.caldigit.com/usb-3-1-usb-c-dock/">USB-C caldigit</a> qui propose une entrée micro, une sortie casque, un port HDMI, un display port et un port ethernet, le tout avec un seul branchement via USB-C.</p>
<p>Inutile de dire que ça n&#8217;a pas marché. L&#8217;USB-C est une vraie jungle, vous connaissez aussi mon avis sur les finitions du XPS 15 et puis la vidéo, ça fait partie de ces trucs qui sont toujours galère en 2017.</p>
<p>Mais&#8230;</p>
<p>Après avoir:</p>
<ul>
<li>Mis à jour tous les drivers du XPS et flashé le bios et le controller USBC (sic).</li>
<li>Télécharger le driver ethernet linux de caldigit (sympas !)</li>
<li>Avoir acheté les bons cables (USB-C respectant le standard, convertisseurs HDMI actifs, etc).</li>
<li>Flashé le dock avec l&#8217;outil caldigit en ayant les bons cables branchés.</li>
<li>Et bidouillé avec la config d&#8217;affichage d&#8217;Ubuntu pendant pas mal de temps.</li>
</ul>
<p>Ca marche. </p>
<p>Pas plug and play pour deux ronds. Mais j&#8217;ai enfin un seul cable qui charge l&#8217;ordi, m&#8217;envoit un débit fibré et étend mon affichage, automatiquement au boot, sous Linux et Windows.</p>
<p>Joie.</p>
<p>Si j&#8217;écris l&#8217;article, c&#8217;est pour dire que:</p>
<ul>
<li>C&#8217;est possible.</li>
<li>C&#8217;est chiant.</li>
<li>Le dock caldigit est le seul que j&#8217;ai trouvé qui marche avec le XPS (qui suce un max de Watts). Et j&#8217;en ai essayé des bidules.</li>
<li>Les cables et adaptateurs sont le nerf de la guerre. Et ils sont dans le camp ennemie.</li>
</ul>
<p>Mais surtout pour signaler que le support de caldigit a été fantastique, ce qui est assez rare pour le souligner. Ma premiere interlocutrice via chat a répondu vite et posé les bonnes questions. Identifiant qu&#8217;elle ne pouvait pas résoudre le problème, elle m&#8217;a redirigé vers le niveau supérieur du support en faisant suivre correctement tout le dossier. Niveau supérieur très technique qui a permi, mail après mail, détail après détail, à faire marche le bouzin. Pas une question à la noix. Pas besoin de me répéter 15 fois. Pas de remise en cause de ma bonne fois ou de prise pour un gogole. Quand les gens font leur boulot ça étonne toujours.</p>


feed_id: http://sametmax.com/?p=23501
title: Le don du mois: Framasoft (bis) 3
uri: Le-don-du-mois-Framasoft-(bis)-3
url: http://sametmax.com/le-don-du-mois-framasoft-bis/
content:
<p>J&#8217;ai <a href="http://sametmax.com/le-don-du-mois-framasoft/">déjà donné</a> à <a href="https://framasoft.org/">Framasoft</a> il y a 2 ans alors que je n&#8217;utilisais plus vraiment le site. Plutôt en remerciement de tout ce qu&#8217;ils ont fait pendant que j&#8217;étais encore sous Windows XP à bricoler avec Phoenix, CloneCD et WinAmp.</p>
<p>Depuis 2001 cet excellent portail a fleuri pour devenir un hébergeur de nombreux services, particulièrement:</p>
<ul>
<li>Un <a href="https://framapad.org/">traitement de texte</a> et <a href="https://framacalc.org/">un tableur</a> collaboratifs.</li>
<li><a href="https://framadate.org/">Un doodle</a>.</li>
<li>Et surtout un <a href="http://framagenda.org/">calendrier</a> auquel je viens de m&#8217;inscrire.</li>
</ul>
<p>Pour l&#8217;instant je suis très content de l&#8217;agenda qui une instance <a href="https://owncloud.org/">owncloud</a> avec une jolie UI, offrant plusieurs calendriers en parallèle, des partages et exports et tout le tintouin. Donc j&#8217;ai <a href="https://addons.mozilla.org/en-US/thunderbird/addon/lightning/">thunderbird</a> linké dessus sous Ubuntu, et <a href="https://play.google.com/store/apps/details?id=net.daum.android.solcalendar&#038;hl=en">Solcalendar</a> sous Android (avec <a href="https://messenger.klinkerapps.com/">pulse sms</a> pour pouvoir taper les sms confortablement sur l&#8217;ordi, rien à avoir mais j&#8217;en suis content alors je plug).</p>
<p>Bref, cet outil arrive à point pour être bien productif. Reste plus qu&#8217;à trouver une alternative à GTG qui est lent comme une grand-mère asthmatique. Si vous avez des suggestions&#8230;</p>
<p>Néanmoins, héberger des services comme ça, ça coûte cher. Et framasoft les propose gratuitement.</p>
<p>Donc, don de 30 euros à l&#8217;asso. Merci messieurs-dames, vous déchirez.</p>
<p>Pour vous aussi faire un don, <a href="https://soutenir.framasoft.org/">c&#8217;est par ici.</a></p>


feed_id: http://sametmax.com/?p=23520
title: Le pattern strategy version gastronomique 5 Recently updated !
uri: Le-pattern-strategy-version-gastronomique-5-Recently-updated
url: http://sametmax.com/le-pattern-strategy-version-gastronomique/
content:
<p>Aller, un petit article de POO un peu avancée pour faire marcher ses neurones ce WE.</p>
<p>Le design pattern strategy, qui consiste à déléguer une partie du comportement d&#8217;un objet à un autre objet est probablement l&#8217;un des motifs de conception les plus utiles en programmation. Trop souvent les gens utilisent l&#8217;héritage là où la composition serait plus adaptée, et une injection de dépendance bien faite permet de gagner beaucoup en qualité de code.</p>
<p>Si vous ne vous souvenez plus ce qu&#8217;est le pattern strategy, vous pouvez faire un saut sur <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-5/">le chapitre qui en parle</a> dans le guide de la POO :)</p>
<p>Mais comme un petit rappel ne fait pas de mal, en très court, strategy 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;">class</span> MonObjet:
    <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: #008000;">self</span>.<span style="color: black;">strategie</span> <span style="color: #66cc66;">=</span> MaStrategie<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">strategy</span>.<span style="color: black;">foo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Ce qui permet à une souclasse de changer la strategy ou non :</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> MonSousObjet<span style="color: black;">&#40;</span>MonObjet<span style="color: black;">&#41;</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: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">strategie</span> <span style="color: #66cc66;">=</span> MonAutreStrategie<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Ou de changer la strat dynamiquement :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">hop <span style="color: #66cc66;">=</span> MonObjet<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
hop.<span style="color: black;">stategie</span> <span style="color: #66cc66;">=</span> SuperNewStrat<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Mais si vous vous en tenez à ce design, les utilisateurs de la classe vont très vite rencontrer des limitations.</p>
<p>D&#8217;abord, une bonne stratégie peut avoir besoin de contexte. Dans ce cas, donnez lui le choix d&#8217;avoir une référence à l&#8217;objet parent:</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> MonObjet:
    <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: #808080; font-style: italic;"># Passer self permet à la stratégie de connaître son contexte. </span>
        <span style="color: #808080; font-style: italic;"># Le désavantage est l'introduction potentiel d'un couplage entre </span>
        <span style="color: #808080; font-style: italic;"># les deux objets, et potentiellement des effets de bords supplémentaire. Cela reste </span>
        <span style="color: #808080; font-style: italic;"># néanmoins souvent une bonne idée.</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">strategie</span> <span style="color: #66cc66;">=</span> MaStrategie<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>   
    ...</pre></td></tr></table></div>

<p>Ensuite, une stratégie devrait pouvoir être passée à la création de l&#8217;objet :</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> MonObjet:
    <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> strategie<span style="color: #66cc66;">=</span>MaStrategie<span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># On donne la priorité à l'objet passé en paramètre. Si il n'y en a </span>
        <span style="color: #808080; font-style: italic;"># pas on créé la stratégie par défaut.</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">strategie</span> <span style="color: #66cc66;">=</span> strategie<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>  
    ...</pre></td></tr></table></div>

<p>Cela permet d&#8217;overrider la stratégie pour les usages plus avancés, tout en permettant aux débutants de ne pas se soucier de cela car il existe quand même une valeur par défaut.</p>

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

<p>Comme le travail dans un init est souvent assez redondant, il avoir un endroit pour permettre aux sous-classes de facilement overrider la stratégie est une bonne pratique. En Python il est courant d&#8217;utiliser les variables de classes pour cela :</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> MonObjet:
&nbsp;
    <span style="color: #808080; font-style: italic;"># On appelle souvent cet attribut &quot;strategy_class&quot; ou &quot;strategy_factory&quot;</span>
    strategie_par_default <span style="color: #66cc66;">=</span> MaStrategie
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> strategie<span style="color: #66cc66;">=</span><span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">strategie</span> <span style="color: #66cc66;">=</span> strategie<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;">if</span> strategie <span style="color: #ff7700;font-weight:bold;">else</span> <span style="color: #008000;">self</span>.<span style="color: black;">strategie_par_default</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span> 
    ...
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> MonSousObjet<span style="color: black;">&#40;</span>MonObjet<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># Et boom, overriding de la stratégie par la classe enfant en une ligne.</span>
    <span style="color: #808080; font-style: italic;"># Django fait ça par exemple avec les classes based views et l'attribut </span>
    <span style="color: #808080; font-style: italic;"># model</span>
    strategie_par_default <span style="color: #66cc66;">=</span> MonAutreStrategie</pre></td></tr></table></div>

<p>Une fois que vous avez fait tout ça, vous avez déjà fait mieux que 90% des programmeurs. Néanmoins si vous voulez vraiment mettre la petit touche pro à votre API, vous pouvez aussi permettre la création dynamique de la stratégie:</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> MonObjet:
&nbsp;
    strategie_par_default <span style="color: #66cc66;">=</span> MaStrategie
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> strategie<span style="color: #66cc66;">=</span><span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">strategie</span> <span style="color: #66cc66;">=</span> strategie<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;">if</span> strategie <span style="color: #ff7700;font-weight:bold;">else</span> <span style="color: #008000;">self</span>.<span style="color: black;">build_strategy</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> 
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> build_strategy<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">strategie_par_default</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
&nbsp;
    ...</pre></td></tr></table></div>

<p>Wow, ça en fait des self et des factories :) En fait, ça fait la même chose qu&#8217;avant, c&#8217;est à dire que le tout premier exemple de code tout simple qu&#8217;on a vu en début d&#8217;article marche toujours ! C&#8217;est la beauté de la chose.</p>
<p>La différence, c&#8217;est que maintenant un classe enfant peut overrider build_strategy() et créer des stratégies à la volée, en fonction du contexte d’exécution. Par exemple créer une stratégie différente en fonction d&#8217;une valeur de base de données. C&#8217;est rare que ça arrive, et c&#8217;est vraiment de l&#8217;usage avancé. Mais quand vous avez ça, vous êtes certains que votre code est prêt à être utilisé par autrui. Car si cet autrui n&#8217;est pas content, il peut faire une profonde coloscopie à votre code et y insérer ce qu&#8217;il veut, quand il veut.</p>
<p>Être dev après tout, c&#8217;est être un peu poète. </p>


feed_id: http://sametmax.com/?p=18765
title: La course du bus de l’innovation sur le chemin de la croissance 1
uri: La-course-du-bus-de-l-innovation-sur-le-chemin-de-la-croissance-1
url: http://sametmax.com/la-course-du-bus-de-linnovation-sur-le-chemin-de-la-croissance/
content:
<p style="text-align: center;"><em><small>Ceci est un post invité de <a href="yamatierea.org">01ivier</a> posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.</small></em></p>
<p>Bonsjours à toutes et à tous,</p>
<p>Dans un sursaut de patriotisme, je me suis dit qu&#8217;il me fallait, moi aussi, participer à l&#8217;effort national et <strong>promouvoir le savoir-faire technologique français</strong>. Partant du constat que, de nos jours, proposer quelque chose de <strong>nouveau</strong> semble suffisant pour être <strong>innovant</strong>, j&#8217;ai fait comme tout bon <strong>startupeur</strong>, je ne me suis pas embarrassé à concevoir quelque chose d&#8217;utile. À vrai dire, ce n&#8217;est même pas nouveau. Mais je suis français et j&#8217;ai un compte Twitter, je crois que c&#8217;est amplement suffisant pour prétendre au label <strong>#CitizenOfTheFrenchTechNation</strong>. </p>
<p>&nbsp;<br />
<a href="media/be13776a.frenchtech.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2016/04/frenchtech.jpg" class="grouped_elements" rel="tc-fancybox-group18765"><img src="media/be13776a.frenchtech.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2016/04/frenchtech.jpg" alt="frenchtech" width="363" height="373" class="aligncenter size-full wp-image-19213" /></a></p>
<p>&nbsp;</p>
<h2>Où le bus l&#8217;innovation va tout droit.</h2>
<p>Parce que je suis bien conscient de l&#8217;influence que cet article va avoir dans le monde du jeu vidéo, je vais détailler les différentes étapes de la réalisation de ce projet bouleversant.</p>
<p>Tout d&#8217;abord, j&#8217;ai fait en sorte que le <strong>bus de l&#8217;innovation</strong> aille tout droit sur un <strong>chemin de la croissance</strong> qui est tout droit.</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: #808080; font-style: italic;"># On importe de quoi dormir</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">time</span> <span style="color: #ff7700;font-weight:bold;">import</span> sleep
&nbsp;
<span style="color: #808080; font-style: italic;"># On définit le graphisme en accord avec l'équipe de designers</span>
chemin <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot; &quot;</span> 
arbre <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;A&quot;</span>
bus <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;B&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On définit la qualité de l'image après avoir consulté les experts en GPU du Digital-Agile-Open-Tech-Lab-Responsive.IO</span>
largeur_ecran <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">70</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On définit l'état initial conjointement avec la team level design.</span>
<span style="color: #808080; font-style: italic;"># (elle-même ayant sollicité au préalable le narrative designer, bien entendu)</span>
largeur_chemin <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">15</span>
position_chemin <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">28</span>
position_bus <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">35</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># On place la première portion d'arbres dans le paysage</span>
    paysage <span style="color: #66cc66;">=</span> arbre * position_chemin
    <span style="color: #808080; font-style: italic;"># On place le chemin</span>
    paysage +<span style="color: #66cc66;">=</span> chemin * largeur_chemin
    <span style="color: #808080; font-style: italic;"># On remplit le reste du paysage par la deuxième portion d'arbres</span>
    paysage +<span style="color: #66cc66;">=</span> arbre * <span style="color: black;">&#40;</span>largeur_ecran - <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>paysage<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># On place le bus sur notre paysage</span>
    paysage <span style="color: #66cc66;">=</span> paysage<span style="color: black;">&#91;</span>:position_bus<span style="color: black;">&#93;</span> + bus + paysage<span style="color: black;">&#91;</span>position_bus:<span style="color: black;">&#93;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># On affiche le tout</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>paysage<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># On dort un peu</span>
    sleep<span style="color: black;">&#40;</span><span style="color: #ff4500;">0.2</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p><a href="media/8fea524c.bus_innovation_droit.gif" data-original-source="http://sametmax.com/wp-content/uploads/2016/03/bus_innovation_droit.gif" class="grouped_elements" rel="tc-fancybox-group18765"><img src="media/8fea524c.bus_innovation_droit.gif" data-original-source="http://sametmax.com/wp-content/uploads/2016/03/bus_innovation_droit.gif" alt="bus_innovation_droit" width="644" height="348" class="aligncenter size-full wp-image-18768" /></a></p>
<p>Oui. Il est effectivement possible d&#8217;arriver plus simplement au même résultat, mais, mes qualifications ne m&#8217;offrent pas le loisir d&#8217;être incompétent. J&#8217;anticipe donc les futurs mouvements du <strong>bus de l&#8217;innovation</strong> ainsi que les inéluctables virages du <strong>chemin de la croissance</strong>.</p>
<p>Ce doit être un peu déroutant pour vous, j&#8217;en conviens, mais c&#8217;est l’expérience qui parle.</p>
<p>Faites-moi confiance.</p>
<p>&nbsp;</p>
<h2>Où le bus l&#8217;innovation va tout droit mais en bien plus beau.</h2>
<p>Parce que l&#8217;on n&#8217;est jamais assez exigent sur l&#8217;apparence d&#8217;un produit de luxe, j&#8217;ai voulu changer le rendu des arbres en remplaçant le &#8220;A&#8221; par un &#8220;█&#8221; bien plus raffiné. Voici le résultat que j&#8217;ai obtenu :</p>
<p><a href="media/4eea85d9.bus_innovation_droit_arbre.png" data-original-source="http://sametmax.com/wp-content/uploads/2016/03/bus_innovation_droit_arbre.png" class="grouped_elements" rel="tc-fancybox-group18765"><img src="media/4eea85d9.bus_innovation_droit_arbre.png" data-original-source="http://sametmax.com/wp-content/uploads/2016/03/bus_innovation_droit_arbre.png" alt="bus_innovation_droit_arbre" width="644" height="348" class="aligncenter size-full wp-image-18774" /></a></p>
<p>Diable comme le succès est semé d’embûches !</p>
<p>En effet, un petit&#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> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;█&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">3</span></pre></td></tr></table></div>

<p>&#8230; m&#8217;a appris que le &#8220;█&#8221; comptait pour trois caractères, faussant mon ingénieuse gestion des positions.</p>
<p>Mon talent m&#8217;avait permis d&#8217;anticiper les mouvements et autres virages mais pas ça. Damned. Qu&#8217;allais-je faire ?</p>
<p>Un petit <code>replace()</code> bien placé et le tour était joué. Sans compter que je pouvais désormais me permettre de mettre de la couleur.</p>
<p>La classe internationale.</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;">from</span> <span style="color: #dc143c;">time</span> <span style="color: #ff7700;font-weight:bold;">import</span> sleep
&nbsp;
chemin <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot; &quot;</span> 
arbre <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;A&quot;</span>
<span style="color: #808080; font-style: italic;">#On définit un arbre classe et vert en utilisant les codes ANSI</span>
arbre_classe_et_vert <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\3</span>3[32m█<span style="color: #000099; font-weight: bold;">\0</span>33[0m&quot;</span>
bus <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;B&quot;</span>
&nbsp;
largeur_ecran <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">70</span>
largeur_chemin <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">15</span>
position_chemin <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">28</span>
position_bus <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">35</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
&nbsp;
    paysage <span style="color: #66cc66;">=</span> arbre * position_chemin
    paysage +<span style="color: #66cc66;">=</span> chemin* largeur_chemin
    paysage +<span style="color: #66cc66;">=</span> arbre * <span style="color: black;">&#40;</span>largeur_ecran - <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>paysage<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    paysage <span style="color: #66cc66;">=</span> paysage<span style="color: black;">&#91;</span>:position_bus<span style="color: black;">&#93;</span> + bus + paysage<span style="color: black;">&#91;</span>position_bus:<span style="color: black;">&#93;</span>
    <span style="color: #808080; font-style: italic;"># PAF ! On remplace l'arbre ridicule par un arbre classe et vert après avoir géré la position des différents éléments.</span>
    paysage <span style="color: #66cc66;">=</span> paysage.<span style="color: black;">replace</span><span style="color: black;">&#40;</span>arbre<span style="color: #66cc66;">,</span> arbre_classe_et_vert<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>paysage<span style="color: black;">&#41;</span>
&nbsp;
    sleep<span style="color: black;">&#40;</span><span style="color: #ff4500;">0.5</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>BIM !</p>
<p><a href="media/d2276abf.bus_innovation_droit_arbre_vert.gif" data-original-source="http://sametmax.com/wp-content/uploads/2016/03/bus_innovation_droit_arbre_vert.gif" class="grouped_elements" rel="tc-fancybox-group18765"><img src="media/d2276abf.bus_innovation_droit_arbre_vert.gif" data-original-source="http://sametmax.com/wp-content/uploads/2016/03/bus_innovation_droit_arbre_vert.gif" alt="bus_innovation_droit_arbre_vert" width="644" height="348" class="aligncenter size-full wp-image-18781" /></a></p>
<p>&nbsp;</p>
<h2>Où le bus de l&#8217;innovation va tout droit mais sur un chemin de la croissance qui tourne.</h2>
<p>Pour faire tourner <strong>le chemin de la croissance</strong> je fais un petit +2/-2 sur sa position avec un <code>randint()</code>, et zou.</p>
<p>Par contre, pour forcer <strong>le chemin de la croissance</strong> à rester dans l&#8217;écran, j&#8217;ai été surpris de ne pas trouver de fonction prête à l&#8217;emploi pour contraindre un nombre dans un intervalle donné. Je suis donc passé par une &#8220;astuce&#8221; pécho sur <strong>Stack Overflow</strong> que j&#8217;ai trouvée élégante. On classe par ordre croissant le nombre donné avec les bornes de l&#8217;interval et on récupère le deuxième élément.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">position <span style="color: #66cc66;">=</span> <span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span>position_min<span style="color: #66cc66;">,</span> position<span style="color: #66cc66;">,</span> position_max<span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Si vous avez mieux, ça m&#8217;intéresse.</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: #808080; font-style: italic;"># On importe de quoi choisir des nombres au hasard</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">random</span> <span style="color: #ff7700;font-weight:bold;">import</span> randint
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">time</span> <span style="color: #ff7700;font-weight:bold;">import</span> sleep
&nbsp;
chemin <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot; &quot;</span> 
arbre <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;A&quot;</span>
arbre_classe_et_vert <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\3</span>3[32m█<span style="color: #000099; font-weight: bold;">\0</span>33[0m&quot;</span>
bus <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;B&quot;</span>
&nbsp;
largeur_ecran <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">70</span>
largeur_chemin <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">15</span>
position_chemin <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">28</span>
position_bus <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">35</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On définit une position maximale pour le chemin de la croissance</span>
position_max_chemin <span style="color: #66cc66;">=</span> largeur_ecran - largeur_chemin
&nbsp;
<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># On calcule la nouvelle position du chemin de la croissance</span>
    <span style="color: #808080; font-style: italic;"># Un peu plus à droite, un peu plus à gauche ou un peu plus tout droit...</span>
    position_chemin +<span style="color: #66cc66;">=</span> randint<span style="color: black;">&#40;</span>-<span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># En s'assurant qu'il ne déborde pas de la largeur de l'écran</span>
    position_chemin <span style="color: #66cc66;">=</span> <span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> position_chemin<span style="color: #66cc66;">,</span> position_max_chemin<span style="color: black;">&#93;</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>
&nbsp;
    paysage <span style="color: #66cc66;">=</span> arbre * position_chemin
    paysage +<span style="color: #66cc66;">=</span> chemin * largeur_chemin
    paysage +<span style="color: #66cc66;">=</span> arbre * <span style="color: black;">&#40;</span>largeur_ecran - <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>paysage<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    paysage <span style="color: #66cc66;">=</span> paysage<span style="color: black;">&#91;</span>:position_bus<span style="color: black;">&#93;</span> + bus + paysage<span style="color: black;">&#91;</span>position_bus:<span style="color: black;">&#93;</span>
    paysage <span style="color: #66cc66;">=</span> paysage.<span style="color: black;">replace</span><span style="color: black;">&#40;</span>arbre<span style="color: #66cc66;">,</span> arbre_classe_et_vert<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>paysage<span style="color: black;">&#41;</span>
&nbsp;
    sleep<span style="color: black;">&#40;</span><span style="color: #ff4500;">0.5</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p><a href="media/c0566799.bus_innovation_chemin_virage.gif" data-original-source="http://sametmax.com/wp-content/uploads/2016/03/bus_innovation_chemin_virage.gif" class="grouped_elements" rel="tc-fancybox-group18765"><img src="media/c0566799.bus_innovation_chemin_virage.gif" data-original-source="http://sametmax.com/wp-content/uploads/2016/03/bus_innovation_chemin_virage.gif" alt="bus_innovation_chemin_virage" width="642" height="341" class="aligncenter size-full wp-image-18797" /></a></p>
<p>&nbsp;</p>
<h2>Où le bus de l&#8217;innovation crache des flammes.</h2>
<p>Avant de me pencher sur les mouvements du <strong>bus de l&#8217;innovation</strong>, j&#8217;ai pris le temps de le tuner un peu.</p>
<p>Déjà, direct, je l&#8217;ai peint en rouge, rapport au fait que le <strong>bus de l&#8217;innovation</strong>, c&#8217;est un peu la <strong>Ferrari de l&#8217;entrepreneuriat</strong>.</p>
<p>Et puis, je me suis dit qu&#8217;il fallait qu&#8217;il n&#8217;y ai vraiment absolument aucun doute sur le fait que c&#8217;était bel et bien <strong>le bus de l&#8217;innovation</strong>. Je lui ai donc fait écrire &#8220;<strong>LE BUS DE L&#8217;INNOVATION</strong>&#8221; sur la route. Je m&#8217;en remets à vous pour me dire s&#8217;il reste une ambiguïté.</p>
<p>Accessoirement, le &#8220;<strong>A</strong>&#8221; utilisé pour placer les arbres est devenu un &#8220;<strong>a</strong>&#8220;, pour ne pas être confondus avec le &#8220;<strong>A</strong>&#8221; présent dans &#8220;INNOV<strong>A</strong>TION&#8221;. C&#8217;est un détail, mais les générations d&#8217;ingénieurs qui liront ça dans deux cent ans seront bien contents de trouver cette explication.</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;">from</span> <span style="color: #dc143c;">random</span> <span style="color: #ff7700;font-weight:bold;">import</span> randint
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">time</span> <span style="color: #ff7700;font-weight:bold;">import</span> sleep
&nbsp;
chemin <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot; &quot;</span> 
arbre <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;a&quot;</span>
arbre_classe_et_vert <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\3</span>3[32m█<span style="color: #000099; font-weight: bold;">\0</span>33[0m&quot;</span>
&nbsp;
largeur_ecran <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">70</span>
largeur_chemin <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">15</span>
position_chemin <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">28</span>
position_bus <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">35</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On définit le texte écrit par le bus de l'innovation</span>
texte_du_bus <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;LE BUS DE L'INNOVATION &quot;</span>
<span style="color: #808080; font-style: italic;"># On récupère le nombre de caractères dans le texte écrit par le bus de l'innovation</span>
nb_caractere <span style="color: #66cc66;">=</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>texte_du_bus<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># On initialise un compteur pour gérer la succession des caractères</span>
compteur <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">0</span>
&nbsp;
position_max_chemin <span style="color: #66cc66;">=</span> largeur_ecran - largeur_chemin
&nbsp;
<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
&nbsp;
    position_chemin +<span style="color: #66cc66;">=</span> randint<span style="color: black;">&#40;</span>-<span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
    position_chemin <span style="color: #66cc66;">=</span> <span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> position_chemin<span style="color: #66cc66;">,</span> position_max_chemin<span style="color: black;">&#93;</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>
&nbsp;
    paysage <span style="color: #66cc66;">=</span> arbre * position_chemin
    paysage +<span style="color: #66cc66;">=</span> chemin * largeur_chemin
    paysage +<span style="color: #66cc66;">=</span> arbre * <span style="color: black;">&#40;</span>largeur_ecran - <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>paysage<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Dans le texte écrit par le bus de l'innovation, on prend le caractère </span>
    <span style="color: #808080; font-style: italic;"># indiqué par le compteur modulo le nombre de caractères possibles</span>
    caractere <span style="color: #66cc66;">=</span> texte_du_bus<span style="color: black;">&#91;</span>compteur%nb_caractere<span style="color: black;">&#93;</span>
    <span style="color: #808080; font-style: italic;"># On peint le caractère en rouge Ferrari</span>
    bus <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\3</span>3[31m{0}<span style="color: #000099; font-weight: bold;">\0</span>33[0m&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>caractere<span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># On incrémente le compteur pour avoir le caractère suivant au prochain tour</span>
    compteur +<span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span>
&nbsp;
    paysage <span style="color: #66cc66;">=</span> paysage<span style="color: black;">&#91;</span>:position_bus<span style="color: black;">&#93;</span> + bus + paysage<span style="color: black;">&#91;</span>position_bus:<span style="color: black;">&#93;</span>
    paysage <span style="color: #66cc66;">=</span> paysage.<span style="color: black;">replace</span><span style="color: black;">&#40;</span>arbre<span style="color: #66cc66;">,</span> arbre_classe_et_vert<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>paysage<span style="color: black;">&#41;</span>
&nbsp;
    sleep<span style="color: black;">&#40;</span><span style="color: #ff4500;">0.5</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Magnifique.</p>
<p><a href="media/30793caf.bus_innovation_flamme.gif" data-original-source="http://sametmax.com/wp-content/uploads/2016/03/bus_innovation_flamme.gif" class="grouped_elements" rel="tc-fancybox-group18765"><img src="media/30793caf.bus_innovation_flamme.gif" data-original-source="http://sametmax.com/wp-content/uploads/2016/03/bus_innovation_flamme.gif" alt="bus_innovation_flamme" width="642" height="450" class="aligncenter size-full wp-image-18805" /></a></p>
<p>&nbsp;</p>
<h2>Où l&#8217;on cherche à faire tourner le bus de l&#8217;innovation.</h2>
<p>Je ne vais pas vous mentir, <strong>la course du bus de l&#8217;innovation sur le chemin de la croissance</strong> n&#8217;est pas vraiment une nouveauté vidéoludique. Nous, c&#8217;est à dire <strong>La Labomedia</strong>, l&#8217;avons <a href="http://labomedia.org/du-29-mai-au-1er-juin-2014-participation-au-toulouse-hacker-space-factory-thsf/#CourseInnovation">déjà présentée</a> à Toulouse lors du <a href="http://thsf.tetalab.org/2014/">THSF 2014</a> ainsi qu&#8217;au <a href="https://www.pseshsf.org/fr/accueil">PSESHSF 2016</a> de Choisy-le-Roi dont il existe même une <a href="https://www.youtube.com/watch?v=I_T0FFTJN3A">vidéo de la Master Class</a>. </p>
<p>Sur cette photo spectaculaire, vous pouvez découvrir la pertinence de notre ingénieuse interface biologique imputrescible nourrie aux anti-biotiques NF.</p>
<p><a href="media/8684178d.busdelinnovationsurlechemindelacroissance.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2016/03/busdelinnovationsurlechemindelacroissance.jpg" class="grouped_elements" rel="tc-fancybox-group18765"><img src="media/8684178d.busdelinnovationsurlechemindelacroissance.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2016/03/busdelinnovationsurlechemindelacroissance.jpg" alt="busdelinnovationsurlechemindelacroissance" width="291" height="388" class="aligncenter size-full wp-image-18816" /></a></p>
<p>Mais, non seulement j&#8217;avais perdu totalement le code initial mais en plus l&#8217;installation s’appuyait sur l’excessivement chère <a href="http://www.makeymakey.com/">MakeyMakey</a> qui, par ailleurs, telle qu&#8217;elle est vendue, impose à l&#8217;utilisateur d&#8217;être relié à une masse.</p>
<p>Pour sa résurrection, je lui ai donc préférée la <a href="https://www.adafruit.com/products/2340">Capacitive Touch HAT</a> pour <strong>RaspberryPi</strong> conçue par <strong>Adafruit</strong> et qui fonctionne direct au simple touché.</p>
<p>(Il va de soit que les <em>natural chicken flavor interfaces</em> n&#8217;ont, elles, pas été remises en question.)</p>
<p>Voici le code minimal pour utiliser le <em>Capacitive Touch HAT</em> une fois la librairie d&#8217;Adafruit installée :</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> Adafruit_MPR121.<span style="color: black;">MPR121</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">time</span> <span style="color: #ff7700;font-weight:bold;">import</span> sleep
&nbsp;
interface <span style="color: #66cc66;">=</span> Adafruit_MPR121.<span style="color: black;">MPR121</span>.<span style="color: black;">MPR121</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
interface.<span style="color: black;">begin</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
&nbsp;
  <span style="color: #808080; font-style: italic;"># Si la patine numéro 0 est touchée</span>
  <span style="color: #ff7700;font-weight:bold;">if</span> interface.<span style="color: black;">is_touched</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</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;GAUCHE !&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># Si la patine numéro 10 est touchée</span>
  <span style="color: #ff7700;font-weight:bold;">if</span> interface.<span style="color: black;">is_touched</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</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;DROITE !&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
  sleep<span style="color: black;">&#40;</span><span style="color: #ff4500;">0.1</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Qui devient ceci quand on instaure un seuil de détection pour tenir compte de la conductivité des pattes de poulet.</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> Adafruit_MPR121.<span style="color: black;">MPR121</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">time</span> <span style="color: #ff7700;font-weight:bold;">import</span> sleep
&nbsp;
interface <span style="color: #66cc66;">=</span> Adafruit_MPR121.<span style="color: black;">MPR121</span>.<span style="color: black;">MPR121</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
interface.<span style="color: black;">begin</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
seuil <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">100</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
&nbsp;
  <span style="color: #808080; font-style: italic;"># Si la patte de poulet reliée à la patine numéro 0 est touchée</span>
  <span style="color: #ff7700;font-weight:bold;">if</span> interface.<span style="color: black;">filtered_data</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;</span> seuil:
      <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;GAUCHE !&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># Si la patte de poulet reliée à la patine numéro 0 est touchée</span>
  <span style="color: #ff7700;font-weight:bold;">if</span> interface.<span style="color: black;">filtered_data</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;</span> seuil:
      <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;DROITE !&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
  sleep<span style="color: black;">&#40;</span><span style="color: #ff4500;">0.1</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>On ne peut pas dire que ce soit très compliqué. À noter tout de même la nécessité d&#8217;activer l&#8217;<strong>I2C</strong> et de lancer le script en <strong>root</strong>. Une formalité pour celles et ceux qui ont de l&#8217;ambition dans la Vie.</p>
<p>Une fois intégré dans notre formidable simulation de sport mécanique extrême, le script ressemble alors à ç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: #808080; font-style: italic;"># On importe la librairie d'Adafruit</span>
<span style="color: #ff7700;font-weight:bold;">import</span> Adafruit_MPR121.<span style="color: black;">MPR121</span> <span style="color: #ff7700;font-weight:bold;">as</span> MPR121
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">random</span> <span style="color: #ff7700;font-weight:bold;">import</span> randint
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">time</span> <span style="color: #ff7700;font-weight:bold;">import</span> sleep
&nbsp;
<span style="color: #808080; font-style: italic;"># On instancie l'interface...</span>
interface <span style="color: #66cc66;">=</span> MPR121.<span style="color: black;">MPR121</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># ... et on la démarre.</span>
interface.<span style="color: black;">begin</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
chemin <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot; &quot;</span> 
arbre <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;a&quot;</span>
arbre_classe_et_vert <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\3</span>3[32m█<span style="color: #000099; font-weight: bold;">\0</span>33[0m&quot;</span>
&nbsp;
largeur_ecran <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">70</span>
largeur_chemin <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">15</span>
position_chemin <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">28</span>
position_bus <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">35</span>
&nbsp;
texte_du_bus <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;LE BUS DE L'INNOVATION &quot;</span>
nb_caractere <span style="color: #66cc66;">=</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>texte_du_bus<span style="color: black;">&#41;</span>
compteur <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">0</span>
&nbsp;
position_max_chemin <span style="color: #66cc66;">=</span> largeur_ecran - largeur_chemin
&nbsp;
seuil <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">100</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># En fonction des patines touchées,</span>
    <span style="color: #808080; font-style: italic;"># on déplace le bus de l'innovation vers la droite...</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> interface.<span style="color: black;">filtered_data</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;</span> seuil:
        position_bus +<span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># ... ou vers la gauche.</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> interface.<span style="color: black;">filtered_data</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;</span> seuil:
        position_bus -<span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span>
&nbsp;
    position_chemin +<span style="color: #66cc66;">=</span> randint<span style="color: black;">&#40;</span>-<span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
    position_chemin <span style="color: #66cc66;">=</span> <span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> position_chemin<span style="color: #66cc66;">,</span> position_max_chemin<span style="color: black;">&#93;</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>
&nbsp;
    paysage <span style="color: #66cc66;">=</span> arbre * position_chemin
    paysage +<span style="color: #66cc66;">=</span> chemin * largeur_chemin
    paysage +<span style="color: #66cc66;">=</span> arbre * <span style="color: black;">&#40;</span>largeur_ecran - <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>paysage<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    caractere <span style="color: #66cc66;">=</span> texte_du_bus<span style="color: black;">&#91;</span>compteur%nb_caractere<span style="color: black;">&#93;</span>
    bus <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\3</span>3[31m{0}<span style="color: #000099; font-weight: bold;">\0</span>33[0m&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>caractere<span style="color: black;">&#41;</span>
    compteur +<span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span>
&nbsp;
    paysage <span style="color: #66cc66;">=</span> paysage<span style="color: black;">&#91;</span>:position_bus<span style="color: black;">&#93;</span> + bus + paysage<span style="color: black;">&#91;</span>position_bus:<span style="color: black;">&#93;</span>
    paysage <span style="color: #66cc66;">=</span> paysage.<span style="color: black;">replace</span><span style="color: black;">&#40;</span>arbre<span style="color: #66cc66;">,</span> arbre_classe_et_vert<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>paysage<span style="color: black;">&#41;</span>
&nbsp;
    sleep<span style="color: black;">&#40;</span><span style="color: #ff4500;">0.5</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p><a href="media/e70c8250.bus_innovation_tourne.gif" data-original-source="http://sametmax.com/wp-content/uploads/2016/03/bus_innovation_tourne.gif" class="grouped_elements" rel="tc-fancybox-group18765"><img src="media/e70c8250.bus_innovation_tourne.gif" data-original-source="http://sametmax.com/wp-content/uploads/2016/03/bus_innovation_tourne.gif" alt="bus_innovation_tourne" width="641" height="432" class="aligncenter size-full wp-image-18849" /></a></p>
<p>&nbsp;</p>
<h2>Où le bus de l&#8217;innovation est tenu de rester sur le chemin de la croissance.</h2>
<p>Écoutez, que les choses soient bien claires, moi aussi je trouve cet article beaucoup trop long, mais c&#8217;est du rayonnement de la <strong>France</strong> dont il est question. Dois-je vous le rappeler ? </p>
<p>Voici donc comment j&#8217;ai tenu compte des sorties du <strong>chemin de la croissance</strong> par notre <strong>bus de l&#8217;innovation</strong> :</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> Adafruit_MPR121.<span style="color: black;">MPR121</span> <span style="color: #ff7700;font-weight:bold;">as</span> MPR121
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">random</span> <span style="color: #ff7700;font-weight:bold;">import</span> randint
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">time</span> <span style="color: #ff7700;font-weight:bold;">import</span> sleep
&nbsp;
interface <span style="color: #66cc66;">=</span> MPR121.<span style="color: black;">MPR121</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
interface.<span style="color: black;">begin</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
chemin <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot; &quot;</span> 
arbre <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;a&quot;</span>
arbre_classe_et_vert <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\3</span>3[32m█<span style="color: #000099; font-weight: bold;">\0</span>33[0m&quot;</span>
&nbsp;
largeur_ecran <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">70</span>
largeur_chemin <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">15</span>
position_chemin <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">28</span>
position_bus <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">35</span>
&nbsp;
texte_du_bus <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;LE BUS DE L'INNOVATION &quot;</span>
nb_caractere <span style="color: #66cc66;">=</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>texte_du_bus<span style="color: black;">&#41;</span>
compteur <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">0</span>
&nbsp;
position_max_chemin <span style="color: #66cc66;">=</span> largeur_ecran - largeur_chemin
&nbsp;
<span style="color: #808080; font-style: italic;"># On définit un booléen qui rendra compte de l'état du bus de l'innovation</span>
le_bus_roule <span style="color: #66cc66;">=</span> <span style="color: #008000;">True</span>
&nbsp;
seuil <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">100</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> interface.<span style="color: black;">filtered_data</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;</span> seuil:
        position_bus +<span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> interface.<span style="color: black;">filtered_data</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;</span> seuil:
        position_bus -<span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Si le bus roule...</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> le_bus_roule:
&nbsp;
        position_chemin +<span style="color: #66cc66;">=</span> randint<span style="color: black;">&#40;</span>-<span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
        position_chemin <span style="color: #66cc66;">=</span> <span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> position_chemin<span style="color: #66cc66;">,</span> position_max_chemin<span style="color: black;">&#93;</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>
&nbsp;
        paysage <span style="color: #66cc66;">=</span> arbre * position_chemin
        paysage +<span style="color: #66cc66;">=</span> chemin * largeur_chemin
        paysage +<span style="color: #66cc66;">=</span> arbre * <span style="color: black;">&#40;</span>largeur_ecran - <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>paysage<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>     
&nbsp;
        <span style="color: #808080; font-style: italic;"># Si le bus sort de la route, à gauche ou à droite...</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> position_bus <span style="color: #66cc66;">&lt;=</span> position_chemin <span style="color: #ff7700;font-weight:bold;">or</span> position_bus <span style="color: #66cc66;">&gt;=</span> position_chemin + largeur_chemin:
&nbsp;
            <span style="color: #808080; font-style: italic;"># On change l'apparence du bus (qui devient une croix verte)</span>
            bus <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\3</span>3[32mX<span style="color: #000099; font-weight: bold;">\0</span>33[0m&quot;</span>
            <span style="color: #808080; font-style: italic;"># On change l'état du bus de l'innovation</span>
            le_bus_roule <span style="color: #66cc66;">=</span> <span style="color: #008000;">False</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Sinon, on affiche le bus comme précédement défini</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            caractere <span style="color: #66cc66;">=</span> texte_du_bus<span style="color: black;">&#91;</span>compteur%nb_caractere<span style="color: black;">&#93;</span>
            bus <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\3</span>3[31m{0}<span style="color: #000099; font-weight: bold;">\0</span>33[0m&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>caractere<span style="color: black;">&#41;</span>
            compteur +<span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span>
&nbsp;
        paysage <span style="color: #66cc66;">=</span> paysage<span style="color: black;">&#91;</span>:position_bus<span style="color: black;">&#93;</span> + bus + paysage<span style="color: black;">&#91;</span>position_bus:<span style="color: black;">&#93;</span>
        paysage <span style="color: #66cc66;">=</span> paysage.<span style="color: black;">replace</span><span style="color: black;">&#40;</span>arbre<span style="color: #66cc66;">,</span> arbre_classe_et_vert<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>paysage<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Si, entre temps, le bus de l'innovation s'est arrêté de rouler</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> le_bus_roule:
&nbsp;
            <span style="color: #808080; font-style: italic;"># On affiche un message sympathique après avoir sauté une ligne</span>
            <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>Il n'est pas exclu que le bus de l'innovation se soit pris un arbre...&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
        sleep<span style="color: black;">&#40;</span><span style="color: #ff4500;">0.5</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p><a href="media/c32a1c28.bus_innovation_crash.gif" data-original-source="http://sametmax.com/wp-content/uploads/2016/03/bus_innovation_crash.gif" class="grouped_elements" rel="tc-fancybox-group18765"><img src="media/c32a1c28.bus_innovation_crash.gif" data-original-source="http://sametmax.com/wp-content/uploads/2016/03/bus_innovation_crash.gif" alt="bus_innovation_crash" width="641" height="307" class="aligncenter size-full wp-image-18850" /></a></p>
<p>&nbsp;</p>
<h2>Où la course du bus de l&#8217;innovation sur le chemin de la croissance va pouvoir enfin commencer.</h2>
<p>Afin que le public intègre bien le défi collectif que représente la relance de l&#8217;économie par le financement et le développement d&#8217;innovants nouveaux projets novateurs avec de la technologie à la pointe de la technologie, j&#8217;ai fait en sorte d&#8217;afficher la croissance totale que l&#8217;ensemble des joueurs auront fait parcourir au <strong>bus de l&#8217;innovation</strong>.</p>
<p>Ainsi, n&#8217;y a-t-il jamais un individu qui perd, mais toujours un <strong>collectif qui gagne</strong>.</p>
<p>Quelque chose entre la <strong>victoire éternelle</strong> et le <strong>succès permanent</strong>.</p>
<p>Une véritable leçon de Vie.</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> Adafruit_MPR121.<span style="color: black;">MPR121</span> <span style="color: #ff7700;font-weight:bold;">as</span> MPR121
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">random</span> <span style="color: #ff7700;font-weight:bold;">import</span> randint
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">time</span> <span style="color: #ff7700;font-weight:bold;">import</span> sleep
&nbsp;
interface <span style="color: #66cc66;">=</span> MPR121.<span style="color: black;">MPR121</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
interface.<span style="color: black;">begin</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
chemin <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot; &quot;</span> 
arbre <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;a&quot;</span>
arbre_classe_et_vert <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\3</span>3[32m█<span style="color: #000099; font-weight: bold;">\0</span>33[0m&quot;</span>
&nbsp;
largeur_ecran <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">70</span>
largeur_chemin <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">15</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On met en place un système d'initialisation des positions</span>
<span style="color: #808080; font-style: italic;"># du chemin de l'innovation et du bus de la croissance</span>
init_position_chemin <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">28</span>
init_position_bus <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">35</span>
position_chemin <span style="color: #66cc66;">=</span> init_position_chemin
position_bus <span style="color: #66cc66;">=</span> init_position_bus
&nbsp;
texte_du_bus <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;LE BUS DE L'INNOVATION &quot;</span>
nb_caractere <span style="color: #66cc66;">=</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>texte_du_bus<span style="color: black;">&#41;</span>
compteur <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">0</span>
&nbsp;
position_max_chemin <span style="color: #66cc66;">=</span> largeur_ecran - largeur_chemin
&nbsp;
seuil <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">100</span>
&nbsp;
le_bus_roule <span style="color: #66cc66;">=</span> <span style="color: #008000;">True</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On déclare des variables qui vont nous permettre de rendre compte</span>
<span style="color: #808080; font-style: italic;"># des quantités de croissance parcourue par le bus de l'innovation</span>
croissance_parcourue_totale <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">0</span>
croissance_parcourue <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">0</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On définit un petit texte à formater pour présenter les quantités en question</span>
texte_crash <span style="color: #66cc66;">=</span><span style="color: #483d8b;">'''
Bravo !
Tu t'es pris un arbre mais tu as parcouru {0} mètres de croissance !
&nbsp;
Pour ton information, le Bus de l'Innovation a parcouru {1} mètres
de croissance depuis son départ.
&nbsp;
Pour le faire redémarrer, appuie sur la cuisse de poulet du milieu.
La France compte sur toi !
'''</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> interface.<span style="color: black;">filtered_data</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;</span> seuil:
        position_bus +<span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> interface.<span style="color: black;">filtered_data</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;</span> seuil:
        position_bus -<span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># On met en place un moyen de reprendre le chemin de la croissance</span>
    <span style="color: #808080; font-style: italic;"># si le bus de l'innovation s'est pris un arbre</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">if</span> interface.<span style="color: black;">filtered_data</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;</span> seuil <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #ff7700;font-weight:bold;">not</span> le_bus_roule:
        le_bus_roule <span style="color: #66cc66;">=</span> <span style="color: #008000;">True</span>
        croissance_parcourue <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">0</span>
        position_chemin <span style="color: #66cc66;">=</span> init_position_chemin
        position_bus <span style="color: #66cc66;">=</span> init_position_bus
        compteur <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">0</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> le_bus_roule:
&nbsp;
        position_chemin +<span style="color: #66cc66;">=</span> randint<span style="color: black;">&#40;</span>-<span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
        position_chemin <span style="color: #66cc66;">=</span> <span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> position_chemin<span style="color: #66cc66;">,</span> position_max_chemin<span style="color: black;">&#93;</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>
&nbsp;
        paysage <span style="color: #66cc66;">=</span> arbre * position_chemin
        paysage +<span style="color: #66cc66;">=</span> chemin * largeur_chemin
        paysage +<span style="color: #66cc66;">=</span> arbre * <span style="color: black;">&#40;</span>largeur_ecran - <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>paysage<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>     
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> position_bus <span style="color: #66cc66;">&lt;=</span> position_chemin <span style="color: #ff7700;font-weight:bold;">or</span> position_bus <span style="color: #66cc66;">&gt;=</span> position_chemin + largeur_chemin:
&nbsp;
            bus <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\3</span>3[32mX<span style="color: #000099; font-weight: bold;">\0</span>33[0m&quot;</span>
            le_bus_roule <span style="color: #66cc66;">=</span> <span style="color: #008000;">False</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            caractere <span style="color: #66cc66;">=</span> texte_du_bus<span style="color: black;">&#91;</span>compteur%nb_caractere<span style="color: black;">&#93;</span>
            bus <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\3</span>3[31m{0}<span style="color: #000099; font-weight: bold;">\0</span>33[0m&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>caractere<span style="color: black;">&#41;</span>
            compteur +<span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span>
            <span style="color: #808080; font-style: italic;"># On incrémente la croissance parcourue à chaque tour</span>
            croissance_parcourue +<span style="color: #66cc66;">=</span> <span style="color: #ff4500;">5</span>
&nbsp;
        paysage <span style="color: #66cc66;">=</span> paysage<span style="color: black;">&#91;</span>:position_bus<span style="color: black;">&#93;</span> + bus + paysage<span style="color: black;">&#91;</span>position_bus:<span style="color: black;">&#93;</span>
        paysage <span style="color: #66cc66;">=</span> paysage.<span style="color: black;">replace</span><span style="color: black;">&#40;</span>arbre<span style="color: #66cc66;">,</span> arbre_classe_et_vert<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>paysage<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> le_bus_roule:
&nbsp;
            <span style="color: #808080; font-style: italic;"># On calcule la croissance totale parcourue</span>
            croissance_parcourue_totale +<span style="color: #66cc66;">=</span> croissance_parcourue
            <span style="color: #808080; font-style: italic;"># On formate notre petit texte pour informer le joueur de sa </span>
            <span style="color: #808080; font-style: italic;"># performance individuelle et collective.</span>
            <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>texte_crash.<span style="color: black;">format</span><span style="color: black;">&#40;</span>croissance_parcourue<span style="color: #66cc66;">,</span> croissance_parcourue_totale<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
        sleep<span style="color: black;">&#40;</span><span style="color: #ff4500;">0.5</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p><a href="media/d076860b.bus_innovation_arcade.gif" data-original-source="http://sametmax.com/wp-content/uploads/2016/03/bus_innovation_arcade.gif" class="grouped_elements" rel="tc-fancybox-group18765"><img src="media/d076860b.bus_innovation_arcade.gif" data-original-source="http://sametmax.com/wp-content/uploads/2016/03/bus_innovation_arcade.gif" alt="bus_innovation_arcade" width="641" height="433" class="aligncenter size-full wp-image-18921" /></a></p>


feed_id: http://sametmax.com/?p=23629
title: Jouer l’asticot sous les talons-aiguille, nouvel eldorado érotique Recently updated !
uri: Jouer-l-asticot-sous-les-talons-aiguille-nouvel-eldorado-érotique
url: http://sametmax.com/jouer-lasticot-sous-les-talons-aiguille-nouvel-eldorado-erotique/
content:
<p style="text-align: center;"><em><small>Ceci est un post invité de <a href="http://sametmax.com/author/Emma/">Emma</a> posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.</small></em></p>
<p><strong>Préambule</strong></p>
<p><strong>Allongé de tout votre long par terre, encordé, saucissonné, enveloppé dans un drap ou du papier film alimentaire, vous allez découvrir que jouer le vers de terre ou l’asticot, ça fait autant de bien que de se l’astiquer. &#8220;ErotiQ LombriQ&#8221;, un jeu à pratiquer bien sûr sous les ordres de sa chère et tendre. Entre documentaire animalier et art ménagé. </strong></p>
<p>Avant toute chose : nous sommes tous d’accord pour admettre que le plaisir de l’humiliation fait désormais parti du lifestyle de l’époque. A l’heure des déclarations vexatoires de Trump et des nouilles dans le slip de Hanouna, le sm est devenu un truc de Bisounours dans la mesure où là, tout est consenti.</p>
<p><strong>Quel équipement ?</strong></p>
<p>Pas de panoplie très élaborée. 2 ou 3 cordes achetées chez Bricorama suffiront amplement pour se faire saucissonner dans un premier temps. Vous pouvez aussi utiliser un drap dans lequel il faudra s’enrouler, façon rouleau de printemps. Il y aussi le wrapping, technique sm très en vogue en ce moment chez les dominas pro. Il s’agit de se faire immobiliser, envelopper intégralement de papier film, le même que celui qu’on utilise pour recouvrir un reste de spaghetti bolognaise à mettre au frigo. Seule la tête reste libre. Petit détail qui a son importance, lors de l’enroulement, le sboub doit-il être comprimé vers le haut ou vers le bas ? C’est à votre copine de trancher.</p>
<p>Pour toutes ces techniques, inutile que votre nana maitrise le bondage sur le bout des doigts même s’il faudra qu’elle ait envie d’être un zest directive ce soir là, nous y reviendrons.</p>
<p><strong>Jouer le lombric, quel intérêt pour le mec ?</strong></p>
<p>De prime abord, on s’imagine une pratique pénible, ramper façon entrainement militaire ou Koh Lanta, un mauvais bizutage ou une reconstitution flippante d’un <em>Faite entrer l’accusé</em> avec cadavre retrouvé enroulé dans le tapis persan de la grand-mère… Élargissez votre horizon, la « vers de terre attitude », c’est bien plus profond que ça.</p>
<p><a href="media/6a75b675.e-de-collection-pixi-spirou-enroule-dans-un-tapis-6569-20151.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/09/figurine-de-collection-pixi-spirou-enroule-dans-un-tapis-6569-20151.jpg" class="grouped_elements" rel="tc-fancybox-group23629"><img class="  wp-image-23633 aligncenter" src="media/6a75b675.e-de-collection-pixi-spirou-enroule-dans-un-tapis-6569-20151.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/09/figurine-de-collection-pixi-spirou-enroule-dans-un-tapis-6569-20151.jpg" alt="figurine-de-collection-pixi-spirou-enroule-dans-un-tapis-6569-2015" width="351" height="206" /></a>L’époque nous a transformé en robots multitâches, pressurisés comme jamais, chaque minute doit être rentable, chaque objectif rempli en temps et en heure, et plus vite que ça ! Il faut réussir sa life dans tous les domaines : être un king dans le taf, avoir pleins d’amis réels et virtuels, s’afficher en papa modèle et enfin assurer comme une bête au pieu, la bite à la main, toujours prêt (le mec n’a pas le droit de dire « non »). Au regard de ces constats, admettez que devenir une larve, une limace dénuée d’énergie, de cerveau, de bras, de jambes, de membres, peut s’avérer séduisant. Si les filles ont le droit de faire l’étoile de mer, les gars eux, ce sera donc le vers de terre.</p>
<p>Immobiliser ou presque, inutile de réfléchir, impossible de décider, d’agir, de contrôler, de faire des choix, c’est le grand soulagement, les vacances forcées, l’immense plaisir de la contrainte qui libère. Alors, vous pouvez philosopher : « je ne suis plus rien, je suis le lombric du monde ». Le lâcher-prise engendre le fameux subspace, cet état de conscience modifié procuré par les endorphines, bref, de quoi économiser quelques joints.</p>
<p><a href="media/d832d154.01.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/09/01.jpg" class="grouped_elements" rel="tc-fancybox-group23629"><img class="  wp-image-23635 aligncenter" src="media/d832d154.01.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/09/01.jpg" alt="01" width="284" height="217" /></a>Au raz du sol, vous ondulez avec vue imprenable sur les Bouboutin de votre meuf, ses jambes, ses bas-couture. Même le grand Bashung l’avait fantasmé dans sa chanson <em>J’ai longtemps contemplé</em> (album <em>Chatterton</em>)</p>
<p><em>&#8220;J&#8217;ai longtemps contemplé </em><br />
<em> Tibias, péronés </em><br />
<em> Au ras des rez-de-chaussée </em><br />
<em> Ces cités immenses </em><br />
<em> Où je ne rutilais pas </em><br />
<em> J&#8217;arpentais des tapis de braise…&#8221;</em></p>
<p>Mais attention, ce n’est pas le Club Med pour autant. Il va falloir essayer de bouger un peu, de se tortiller, avancer centimètre par centimètre, bref ramper tel un nuisible, pour atteindre le ridicule absolu ! Votre douce complice peut vous motiver en semant par terre des lombrics gélifiés trouvés au rayon Haribo, ou disséminer dans toute la pièce ses culottes sales ou encore des lignes de coke. Mais être saucissonné sous cocaïne, c’est un peu comme boire un Pétrus juste après s’être lavé les dents avec un dentifrice mentholé, c’est gâché !</p>
<p>Après vous avoir fait mordre la poussière, la meuf va vous obliger à jouer l’aspirateur à cunni. D’un coup de talon, la miss vous fera rouler sur le dos. Elle ne résistera pas à l’envie sadique de retirer son string histoire de vous faire admirer sa moquette, juste au dessus de votre tête. Toujours impossible de bouger un doigt, vous êtes à sa merci, et on dit merci qui ? « Merci Maîtresse ! » Dans sa grande mansuétude, elle se servira de vous comme d’un vulgaire sextoy en s’asseyant sur votre tronche, pour un facesitting d’anthologie. Attention tout de même à l’asphyxie, car enfoui sous ses fesses, difficile de bafouiller un safe word audible ou de faire un signe de secours, vu que vous n’avez plus de bras. À moins de se tordre comme un appât à deux doigts d’être accroché à l’hameçon de la pécheresse.</p>
<p><a href="media/4a25d130.ver-une-caricature-stupide-fou-tee-shirts-t-shirt-homme.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/09/ver-une-caricature-stupide-fou-tee-shirts-t-shirt-homme.jpg" class="grouped_elements" rel="tc-fancybox-group23629"><img class="  wp-image-23631 aligncenter" src="media/4a25d130.ver-une-caricature-stupide-fou-tee-shirts-t-shirt-homme.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/09/ver-une-caricature-stupide-fou-tee-shirts-t-shirt-homme.jpg" alt="ver-une-caricature-stupide-fou-tee-shirts-t-shirt-homme" width="270" height="270" /></a><strong>Faire mordre la poussière à son partenaire, quel intérêt pour la nana ?</strong></p>
<p>Si les mecs ne peuvent pas échapper aux bimbos à plat ventre au détour d’un spam, d’un kiosque à journaux ou d’une pub dans le métro, pour les femmes, profiter de mecs dans le même état d’abandon, c’est beaucoup plus rare. Mais il y a quand même deux professions masculines où les filles ont la chance d’admirer quasi systématiquement un gars à quatre pattes voir à plat ventre, raie du cul apparente : plombier et dépanneur informatique. Ces derniers passent sous le bureau et se retrouvent nez à nez ou plutôt nez à pieds avec les escarpins aux talons parfois vertigineux.</p>
<p>Avoir un homme à ses pieds, lui demander n’importe quoi sans avoir à lui dire merci, ça peut être très excitant. C’est aussi une bonne façon de se foutre de sa gueule, de régler des vieux comptes, lui faire manger les acariens à ce vaurien, depuis le temps qu’il repousse le moment de passer l’aspi. « Les plates excuses, c’est fini ! Tu n’es qu’un insecte rampant. Ce soir, ce ne sera pas « baisons » mais baygon vert ! » (contre insectes rampants, cafards, fourmis, action immédiate et longue durée, comme dit la pub.)</p>
<p>Il peut être très plaisant de faire rouler le vermisseau sous ses pieds, un peu comme pousser un gros boudin, ça rappelle l’émission culte Interville. Et puis, comme expliqué plus haut, la demoiselle ou la dame pourra utiliser l’asticot tel un objet sexuel, en bonne entomologiste zoophile. Elle peut faire un trou dans le drap ou le papier film, juste au niveau du zboub.</p>
<p><a href="media/7e4c5d1d.353-0.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/09/353-0.jpg" class="grouped_elements" rel="tc-fancybox-group23629"><img class=" size-full wp-image-23634 aligncenter" src="media/7e4c5d1d.353-0.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/09/353-0.jpg" alt="353-0" width="240" height="180" /></a>Mais votre amour propre est sauf, elle ne pourra pas vous traiter de « bite sur patte », puisque vous n’en avez plus, des papattes. Reste pour elle à s’empaler gaiement sur votre appendice. Concentrez-vous uniquement sur votre érection. Le reste n’a plus aucune importance vu le ridicule dans lequel vous êtes vautré, plus rien à réussir, plus d’objectif à atteindre, le nirvana post productiviste en somme.</p>
<p style="text-align: center;"> <strong>De notre contributrice Emma du blog <a href="http://www.parisderriere.fr/" target="_blank">Paris Derrière</a>, blog sur les frasques du Paris érotique. </strong></p>
<p><a href="http://www.parisderriere.fr/"><img class="  wp-image-23630 aligncenter" src="media/fc05e09b.logo6.png" data-original-source="http://sametmax.com/wp-content/uploads/2017/09/logo6.png" class="grouped_elements" rel="tc-fancybox-group23629" alt="logo6" width="551" height="173" /></a></p>
<p>&nbsp;</p>


feed_id: http://sametmax.com/?p=23681
title: Regrouper ses fichiers de settings avec stow 2 Recently updated !
uri: Regrouper-ses-fichiers-de-settings-avec-stow-2-Recently-updated
url: http://sametmax.com/regrouper-ses-fichiers-de-settings-avec-stow/
content:
<p>Sous Linux, le dossier utilisateur est blindé de fichiers de configuration. Les fameux <code>.machins</code>. Par exemple le <code>.bashrc</code> pour la config du bash, le <code>.mozilla</code> qui contient toutes vos données Firefox, le <code>.ssh</code> avec toutes vos clés privées, le <code>.local/share/virtualenvs</code> avec les envs virtuels Python créés par pew ou <code>.config/sublime-text-3</code> pour la configuration de Sublime text, etc.</p>
<p>Au final, voici tous les fichiers de conf qui sont importants pour moi de près ou de loin:</p>
<pre>
├── .autoenv
├── .bashrc
├── .config
│   ├── autostart
│   ├── Code
│   ├── copyq
│   ├── fish
│   ├── gtg
│   ├── liferea
│   ├── pulse
│   ├── stremio
│   ├── sublime-text-3
│   ├── transmission
│   ├── user-dirs.dirs
│   ├── user-dirs.locale
│   ├── variety
│   ├── VeraCrypt
│   ├── Zeal
│   └── zim
├── .django-completion.bash
├── .editorconfig
├── .git-aware-prompt
├── .git-completion.bash
├── .gitconfig
├── .gitignore
├── .git-prompt.sh
├── .git.scmbrc
├── .jupyter
├── .lastpass
├── .liferea_1.8
├── .local
│   └── share
        ├── gtg
        ├── keyrings
        ├── liferea
        ├── omf
        ├── TowerFall
        ├── virtualenvs
        └── Zeal
├── .mozilla
├── .netrc
├── .oh-my-zsh
├── .openambit
├── .pypirc
├── .scmbrc
├── .scm_breeze
├── .sshplus
├── .vscode
│   └── extensions
└── .zshrc
</pre>
<p>Quand on bidouille, on les change souvent. On les backup aussi, pour pouvoir les porter d&#8217;un laptop à un autre, les synchroniser, les uploader sur un serveur ou les récup lors d&#8217;une réinstallation. Parce que quand on a tuné ses terminaux et éditeurs aux petits oignons, on a pas envie de recommencer à poil.</p>
<p>Pour bien faciliter les choses, ils sont éparpillés un peu partout, dans des sous-dossiers différents. </p>
<p>Et je sais pas quel vil individu a suggéré une fois que faire une partition séparée pour <code>/home</code> était la solution de Skippy à tous les soucis, mais perso, ça me cause plus de bugs qu&#8217;autre chose quand on change de versions d&#8217;OS.</p>
<p>Bref, laissez tomber vos vieilles croyances issues de charlatans de sectes. Moi, j&#8217;ai vu la lumière (lien de don bitcoin en bas à droite de la page), et elle s&#8217;appelle <code>GNU stow</code>.</p>
<p>Stow est un vieil utilitaire (donc sagesse millénaire des anciens, vous pouvez avoir confiance, prenez ce cristal aussi il est en promo), qui est grosso merdo un <code>ln -s</code> récursive. C&#8217;est-à-dire que ça fait des symlinks des fichiers et des dossiers que vous lui passez.</p>
<p>On peut l&#8217;utiliser pour plein de choses, mais l&#8217;usage sacré implique le sacrifice d&#8217;une vierge à Max, puis de déplacer tous les fichiers de settings qu&#8217;on souhaite gérer dans un seul dossier.</p>
<p>Par exemple, moi j&#8217;ai:</p>
<pre>
/home/user/church/settings/

    ├── .autoenv
    ├── .bashrc
    ├── .config
    │   ├── autostart
    │   ├── Code
    │   ├── copyq
    │   ├── fish
    │   ├── gtg
    ...
</pre>
<p>Au lieu de les avoir éparpillées partout, toutes les brebis sont maintenant regroupées dans une seule église. </p>
<p>Il est très important de garder l&#8217;organisation des dossiers et des sous-dossiers d&#8217;origine. Ici vous voyez que j&#8217;ai le dossier <code>Code</code>, qui est le dossier de settings de VSCode. Mais il est DANS un dossier <code>.config</code>, car avant mon regroupement il était dans <code>/home/user/.config/</code>.</p>
<p>En revanche, il n&#8217;est pas du tout nécessaire que <code>.config</code> contienne tous les dossiers qu&#8217;il avait précédemment. Seuls ceux qui vous intéressent. Le reste peut rester à sa place initiale, dans le <code>/home/user/.config/</code>.</p>
<p>Donc je résume:</p>
<ul>
<li>Listez les fichiers et dossiers de settings qui vous intéressent.</li>
<li>Déplacez les tous dans un dossier commun en gardant une arborescence similaire.</li>
<li>Laissez les fichiers qui ne vous intéressent pas là où ils sont.</li>
<li>Priez (une bonne pratique avant toute opération informatique).</li>
</ul>
<p>Arrive le messie, Stow.</p>
<p>D&#8217;abord, il faut l&#8217;installer, mais comme c&#8217;est un outil vénérable, il est dans les dépôts. Sous Ubuntu, le psaume &#8220;apt install stow&#8221; fera l&#8217;affaire.</p>
<p>Ensuite, on prêche. Je me perds dans mes propres paraboles, mais les voies du seigneur sont impénétrables, contrairement à celles d&#8217;Abella Anderson. Bref on demande à <code>stow</code> de traiter récursivement tout le contenu du dossier <code>settings</code> qui est dans <code>/home/user/church</code> afin de le linker vers <code>/home/user/</code>:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">stow <span style="color: #660033;">-d</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>user<span style="color: #000000; font-weight: bold;">/</span>church <span style="color: #660033;">-t</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>user<span style="color: #000000; font-weight: bold;">/</span> settings</pre></td></tr></table></div>

<p>Stow va prendre récursivement tous les dossiers qui sont dans <code>/home/user/church/settings</code>, et les comparer à ceux dans <code>/home/user</code>. Si ils existent, il va ne rien faire, mais si ils n&#8217;existent pas, il va créer un lien vers chacun de ceux manquants. Pour les fichiers, si ils n&#8217;existent pas, il va créer un lien, sinon il va vous afficher une erreur, afin de ne pas écraser quelque chose d&#8217;important et vous signalez qu&#8217;il y un souci.</p>
<p>Le but de tout ça ?</p>
<p>Pour votre système et tous vos logiciels, ça ne change rien. Ils vont tomber sur les liens et avoir l&#8217;impression que tous les fichiers de configs sont à leur place et vont continuer à fonctionner dans la joie et le gospel.</p>
<p>Et pour vous, ben vous avez un seul endroit où tous les fichiers importants sont regroupés. Plus besoin de les chercher. Facile à backuper et à restaurer. On peut même tout foutre sous Git.</p>
<p>Loué soit le sauveur.</p>
<p>Vive moi.</p>


feed_id: http://sametmax.com/?p=23691
title: pipenv, solution moderne pour remplacer pip et virtualenv 1 Recently updated !
uri: pipenv-solution-moderne-pour-remplacer-pip-et-virtualenv-1-Recentl
url: http://sametmax.com/pipenv-solution-moderne-pour-remplacer-pip-et-virtualenv/
content:
<p>Kenneth Reitz, l&#8217;auteur de <a href="http://docs.python-requests.org/en/master/">requests</a>, tente régulièrement de nous refaire le coup du projet star. Ca n&#8217;a malheureusement pas très bien marché, et beaucoup de ses projets comme maya, records, crayon, tablib ou awesome n&#8217;ont pas vraiment connu de succès.</p>
<p>Entre alors <a href="https://github.com/kennethreitz/pipenv">pipenv</a>, que j&#8217;ai testé il y a presque qu&#8217;un an, et qui au départ montrait un beau potentiel, mais n&#8217;était pas encore très utilisable. J&#8217;ai fais quelques suggestions d&#8217;amélioration, comme permettre de choisir précisément la version de Python, et je me suis fais envoyé bouler. J&#8217;ai donc laissé l&#8217;auteur s&#8217;enterrer dans sa recherche de gloire passée.</p>
<p>Le hasard de reddit m&#8217;a remis <code>pipenv</code> sous le nez, et j&#8217;ai donc redonné sa chance au produit. Surprise, l&#8217;outil est maintenant très stable (plus de 2000 commits !) et mes propositions avaient même été intégrées. </p>
<p>Après ces 3 paragraphes vous vous demandez sans doute quand est-ce que je vais rentrer dans le vif du sujet, donc:</p>
<p><code>pipenv</code> reprend les idées de <a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a>, <a href="http://sametmax.com/les-environnement-virtuels-python-virtualenv-et-virtualenvwrapper/">virtualenv</a>, <a href="http://sametmax.com/mieux-que-python-virtualenvwrapper-pew/">pew</a> et même quelques trucs de npm, yarn, cargo, et essaye d&#8217;appliquer tout ça à Python. L&#8217;article suppose que vous savez ce que sont ces mots barbares, donc suivez les liens si ce n&#8217;est pas le cas.</p>
<p><code>pipenv</code> permet donc d&#8217;installer des packages Python, d&#8217;isoler cette installation et de la rendre reproductible. Mais sans effort.</p>
<p>En effet, contrairement à la concurrence:</p>
<ul>
<li>La gestion du virtualenv est automatique et transparente</li>
<li>Les paquets installés sont sauvegadés dans des fichiers de config, encore une fois de manière automatique et transparente.</li>
<li>Les fichiers de config distinguent les dépendances de prod et de dev, et incluent les versions des sous-dépendances.</li>
</ul>
<h2>Installer pipenv</h2>
<p>Contrairement à pip et virtualenv, <code>pipenv</code> n&#8217;est pas fourni avec une installation standard de Python, bien que l&#8217;outil soit maitenant <a href="https://packaging.python.org/new-tutorials/installing-and-using-packages/">recommandé par la doc officielle</a>. Il va donc falloir l&#8217;installer. Or <code>pipenv</code> se base sur une version récente de <code>pip</code>, donc il faut d&#8217;abord être sur d&#8217;avoir pip à jour.</p>
<p>Du coup:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># mise à jour de pip, mais juste au niveau utilisateur pour </span>
<span style="color: #666666; font-style: italic;"># pas casser le  system</span>
python <span style="color: #660033;">-m</span> pip <span style="color: #c20cb9; font-weight: bold;">install</span> pip <span style="color: #660033;">--upgrade</span> <span style="color: #660033;">--user</span></pre></td></tr></table></div>

<p>Puis:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># installation de pipenv</span>
python <span style="color: #660033;">-m</span> pip <span style="color: #c20cb9; font-weight: bold;">install</span> pipenv <span style="color: #660033;">--user</span></pre></td></tr></table></div>

<p>A moins d&#8217;être sous une Debian like type Ubuntu (qui demande un apt install de python-pip avant), tout le monde a pip installé avec une version moderne de Python. </p>
<p>Voilà, vous devriez avoir la commande <code>pipenv</code> disponible, ou pour ceux qui ont un système mal configuré, <code>python -m pipenv</code>.</p>
<h2>Usage</h2>
<p>Dans le dossier de votre projet:</p>

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

<p>C&#8217;est tout.</p>
<p>Si un virtualenv n&#8217;existe pas il sera créé. Sinon il sera utilisé. Les fichiers de configs sont gérés automatiquement, il n&#8217;y a rien à faire.</p>
<p>Si vous voulez lancer une commande dans le virtualenv:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">pipenv run commande</pre></td></tr></table></div>

<p>Exemple:</p>

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

<p>Va lancer le Python de votre virtualenv.</p>
<p>Si vous voulez que toutes les commandes soient dans le virtualenv:</p>

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

<p>Et vous êtes dans un nouveau shell, dans le virtualenv. Ainsi:</p>

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

<p>Lancera celui de votre virtualenv.</p>
<p>On sort du shell avec <code>Ctrl + D.</code></p>
<p>Vous pouvez arrêtez de lire l&#8217;article ici, c&#8217;est l&#8217;essentiel de ce qu&#8217;il y a à savoir.</p>
<h2>Astuces</h2>
<p>Si vous lancez pour la première fois dans un dossier <code>pipenv</code> avec:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">pipenv <span style="color: #660033;">--python</span> x.x</pre></td></tr></table></div>

<p>Le virtualenv sera créé avec la version de Python x.x, pourvu qu&#8217;elle existe sur votre système. Setter la variable d&#8217;env  <code>PIPENV_DEFAULT_PYTHON_VERSION</code> a le même effet.</p>
<p>Installer un package avec <code>pipenv install --dev</code> le marque comme dépendance de développement uniquement, et permet une installation séparée.</p>
<p>Vous pouvez aussi obtenir quelques infos utiles comme:</p>
<ul>
<li><code>pipenv --venv</code>: ou est le dossier du virtualenv</li>
<li><code>pipenv graph</code>: un graph de toutes vos dépendances</li>
<li><code>pipenv --py</code>: chemin vers le Python en cours.</li>
</ul>
<p>Enfin <code>pipenv</code> utilise <code>pew</code>, donc la magie de <code>pew</code> reste dispo, y compris la gestion de projets :)</p>
<h2>Usage avancé</h2>
<p>Si vous créez un fichier <code>.env</code> dans le dossier de votre projet tels que:</p>
<pre>FOO=1
BAR=wololo</pre>
<p><code>pipenv</code> éxécutera toutes ses commandes (y compris <code>shell</code>), avec <code>FOO</code> et <code>BAR</code> comme variables d&#8217;environnement.</p>
<p>La commande:</p>

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

<p>Va créer un lock file. Ce fichier contient toutes les dépendances, et recursivement, les dépendances des dépendances, installées, avec leurs versions. On peut réutiliser ce fichier en prod pour installer une exacte copie de son setup local avec <code>pipenv install</code>. Sans ce fichier, <code>pipenv install</code> se comportera comme <code>pip install</code>.</p>
<p>Il y a plein d&#8217;autres trucs mais on va en rester là.</p>


feed_id: http://sametmax.com/?p=23755
title: Protégé jusqu’à la mort 3 Recently updated !
uri: Protégé-jusqu-à-la-mort-3-Recently-updated
url: http://sametmax.com/protege-jusqua-la-mort/
content:
<p>Ce matin là, comme dans toutes les démos importantes avec un client, rien ne marchait. D&#8217;abord la multiprise, puis la prise Ethernet physique, puis la connexion elle-même. Pour faire bonne mesure, j&#8217;avais moi aussi un bug dans le code que je n&#8217;ai pu résoudre qu&#8217;en changeant de bâtiment (ne cherchez pas&#8230;).</p>
<p>Un moment merveilleux de communion avec tous les dev du monde qui ont connu cette expérience spirituelle de destruction de moral et de crédibilité.</p>
<p>Après quelques blagues et une utilisation de la partie du service qui marchait qui m&#8217;ont permis de garder la face, un nouveau problème fit son apparition.</p>
<p>Un fichier .odt que je générais était corrompu au téléchargement.</p>
<div id="attachment_23763" style="width: 410px" class="wp-caption aligncenter"><a href="media/66f76468.8lrOhH0.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/11/8lrOhH0.jpg" class="grouped_elements" rel="tc-fancybox-group23755"><img src="media/66f76468.8lrOhH0.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/11/8lrOhH0.jpg" alt="God left" width="400" height="289" class="size-full wp-image-23763" /></a><p class="wp-caption-text">And he&#8217;s right</p></div>
<p>Pourtant, ça marchait, j&#8217;en étais certain.</p>
<p>Aucune erreur. Rien. Tout était nickel de bout en bout. Sur ma machine, tout va bien. Sur les leurs, plantage direct de Libre Office.</p>
<p>Je change de navigateur sur mon laptop ou leurs tours. Queud.</p>
<p>Je change d&#8217;OS. La même.</p>
<p>Avec CURL ? Zob.</p>
<p>Et puis je note un truc étrange : la taille du fichier n&#8217;est pas la même sur leur machine. Elle change à chaque putain de téléchargement.</p>
<p>Je reste un instant interloqué. Et par &#8220;un instant interloqué&#8221; j&#8217;entends 2h surcaféine à trafiquer sur 3 machines différentes toutes les hypothèses tordues possibles, frénétiquement, et la bave aux lèvres.</p>
<p>Quand soudain l&#8217;idée me vint. La grâce divine.</p>
<div id="attachment_23759" style="width: 323px" class="wp-caption aligncenter"><a href="media/519982dc.nrEWONk.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/11/nrEWONk.jpg" class="grouped_elements" rel="tc-fancybox-group23755"><img src="media/519982dc.nrEWONk.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/11/nrEWONk.jpg" alt="Jesus saves" width="313" height="700" class="size-full wp-image-23759" /></a><p class="wp-caption-text">Jesus saves. For later.</p></div>
<p>Je désactive leur antivirus.</p>
<p>Miracle, ça marche.</p>
<p>Karspersky protégeait leurs machines jusqu&#8217;à la mort.</p>
<p>Je ne sais pas ce qui se passait dans sa petite tête, mais il lobotomisait de quelques Ko tous les documents, en mode frappe préventive américaine.  Peu importe, leur admin n&#8217;aurait de toute façon pas été capable de corriger le problème.</p>
<p>La solution est de se passer des forces de l&#8217;ordre et faire justice soit même : tout foutre en SSL pour que le petit salopiot arrête de mettre son nez dans mes paquets. Ils sont sur un intranet. Avec un VPN. Mais fuck, ils seront bien protégés.</p>
<div id="attachment_23761" style="width: 185px" class="wp-caption aligncenter"><a href="media/0d63f2d5.z2F2qZx.png" data-original-source="http://sametmax.com/wp-content/uploads/2017/11/z2F2qZx.png" class="grouped_elements" rel="tc-fancybox-group23755"><img src="media/0d63f2d5.z2F2qZx.png" data-original-source="http://sametmax.com/wp-content/uploads/2017/11/z2F2qZx.png" alt="Something queer this way come" width="175" height="291" class="size-full wp-image-23761" /></a><p class="wp-caption-text">Also, openssl -days 10000000</p></div>


feed_id: http://sametmax.com/?p=23805
title: De la thune avec un « Mining Pool » de BTG
uri: De-la-thune-avec-un-Mining-Pool-de-BTG
url: http://sametmax.com/de-la-thune-avec-un-mining-pool-de-btg/
content:
<p><em>C&#8217;est pas parce que vous entendez plus trop parler de Max qu&#8217;il est mort. En ce moment, il est à fond sur les cryptomonnaies. Mais si, rappelez-vous,  <a href="http://sametmax.com/tag/bitcoin/">ça fait quand même 5 ans qu&#8217;on vous parle du Bitcoin sur le blog</a>&#8230; Aujourd&#8217;hui le Bitcoin est à quelques milliers d&#8217;euros, et des centaines de monnaies concurrentes sont arrivées sur le marché. </p>
<p>Les opportunités pour faire de l&#8217;argent (et en perdre of course) sont décuplées, et Max, ainsi que deux potes à nous, se sont lancés dans un petit montage sympa. Potentiellement, si vous avez une bonne carte graphique, y a moyen de se faire du pognon sans trop d&#8217;effort. Plus on a de lecteurs qui participent, plus la thune arrive.</p>
<p> Je leur laisse la parole dans un article invité de Tic, où ils vous expliqueront ça mieux que moi </em></p>
<hr />
<p>Avec une bande de zozos, on est en train de monter un mining pool sur le Bitcoin Gold. Rien que cette phrase je me demande comment j’ai pu l’écrire.</p>
<p>Je ne suis pas du genre à me baigner dans du charbon, donc je vais préciser les choses :</p>
<p>Certaines cryptomonnaies (Bitcoin, Ether, Monero, mon préféré Electroneum …) reposent sur une blockchain dont la sécurisation (ie gravure des transactions et informations dans le marbre de la blockchain, vérification qu’il n’y a pas de fraude) est réalisée par une armée de machines capable de réaliser des tonnes d’opérations mathématiques : les mineurs.</p>
<p>Pour valider un block de la chaine chaque mineur essaye des foultitudes de combinaisons mathématiques liées à ce block, jusqu’à ce qu’un trouve la bonne combinaison et Bingo il touche la cagnotte, le salaire (versé dans la cryptomonnaie associée) lié à la validation de ce block et ainsi de suite, jusqu’à presque l’infini.</p>
<p>Du coup, soit les mineurs travaillent tout seuls dans leur coin pour choper le gros lot, soit ils s’associent dans un « pool » et mettent leur puissance (et leur chance, car il s’agit bien de chance) en commun pour gagner plus souvent une plus petite partie de la mise.</p>
<p>Un peu comme jouer au loto, soit on fait sa grille tout seul dans son coin pour gagner en moyenne 2 millions avec une probabilité de 1/19 Millions, soit on a 1 000 « amis » avec qui on s’associe pour gagner en moyenne 2000 euros avec une probabilité de 1/19000. On gagne beaucoup moins, mais on a beaucoup plus de chance (au sens probabiliste) que ça arrive au moins dans une vie.</p>
<p>Sauf que pour miner, pas besoin d&#8217;acheter un ticket. Il suffit d&#8217;avoir une carte graphique sur son ordi.</p>
<p>Et avec un pool, on a un serveur sur lequel chaque mineur se connecte pour lui demander du travail, sa feuille de route au niveau calcul pour les secondes à venir. Chacun fait ses calculs aussi vite qu’il peut et renvoie ses résultats, et si un des mineurs du pool trouve la combinaison gagnante, le pool redistribue les gains selon la quantité de travail (pour la plupart dans le vent, mais c’est le jeu qui veut ça) fournie par chacun. Par chacun, on parle d’un PC (presque) de base à une ferme de minage comprenant plusieurs dizaines (ou centaines) de cartes graphiques.</p>
<p>Sinon j’ai parlé de BTG en titre, c’est le Bitcoin Gold (il y a le silver et surement un jour le copper à venir, mais on va rester sur le Gold). Le BTG c’est une nouvelle cryptomonnaie qui sort officiellement le 12 Novembre à 19h UTC. <strong>Donc ce soir.</strong> Pour faire court et simple (et pas trop m’embrouiller), le BTG est basé sur la blockchain du BTC (The Bitcoin), c’est un « fork » qui veut redonner le pouvoir au peuple dans la mesure où la sécurisation de la chaine Bitcoin originale est devenue tellement difficile que seule une poignée de gros acteurs basés dans l’Empire du milieu (bref des chinois) détient la quasi-totalité de la puissance. Pour la sécurisation décentralisée de la chose, on repassera. Le bitcoin gold tend à redonner la voix au peuple en proposant une chaine sécurisable par des cartes graphiques et seulement des cartes graphiques, du coup la démocratisation est plus plausible, car il suffit de 1000 PC de gamers disséminés n’importe où pour égaler (et contrebalancer) la puissance d’une ferme entière cachée au fin fond de l’Oural ou de la Mongolie.</p>
<p>Du coup voilà, on est en train de monter un mining pool de BTG.</p>
<hr />
<p><em>Maintenant la partie fun. </p>
<p>Quand une nouvelle cryptomonnaie arrive, le début du minage est plus facile. Ce soir, Max et Tic &#038; Tac vont donc ouvrir leur mining pool, et on va poster un tuto sur le blog pour que vous puissiez vous connecter dessus.</p>
<p>Afin qu&#8217;on fasse de la thune tous ensemble, dans la joie et la bonne humeur.</em></p>


feed_id: http://sametmax.com/?p=23817
title: Le miner pool BTG est ready: voici comment faire 1 Recently updated !
uri: Le-miner-pool-BTG-est-ready-voici-comment-faire-1-Recently-updated
url: http://sametmax.com/le-miner-pool-btg-est-ready-voici-comment-faire/
content:
<p><span style="color: #ff0000;"><strong>ATTENTION !!! Article posté par erreur, BTCGOLD ayant pris un low kick frontal par une DDoS de gniaks, ils ont tout niqué. C&#8217;est en train de sync le mainnet, on en est à 50%, je pense que ce sera fini demain matin. Je vous posterai un article/tuto quand ils seront up.</strong></span></p>
<p>Max s&#8217;est bien marré et pour miner du bitcoin gold, nous a pondu le site <a href="http://goldenshower.io/">http://goldenshower.io/</a>.</p>
<p>Qui s&#8217;est fait insta banné des listing et donc on a du mettre un alias http://goldenshow.io. On garde l&#8217;autre pour la postérité :)</p>
<p>Toutes les instructions sont dessus.</p>
<p>Mais en résumé, vous créez un wallet sur un site <a href="https://btgwallet.online/">type https://btgwallet.online/</a>.</p>
<p>Ca donne un truc comme ça:</p>
<div id="attachment_23818" style="width: 1259px" class="wp-caption aligncenter"><a href="media/1a492cbc.Capture-du-2017-11-13-00-33-27.png" data-original-source="http://sametmax.com/wp-content/uploads/2017/11/Capture-du-2017-11-13-00-33-27.png" class="grouped_elements" rel="tc-fancybox-group23817"><img class="size-full wp-image-23818" src="media/1a492cbc.Capture-du-2017-11-13-00-33-27.png" data-original-source="http://sametmax.com/wp-content/uploads/2017/11/Capture-du-2017-11-13-00-33-27.png" alt="Non c'est pas le mien bandes de bananes" width="1249" height="604" /></a><p class="wp-caption-text">Non c&#8217;est pas le mien bandes de bananes</p></div>
<p>Sauvegardez tout ça.</p>
<p>Installez le miner pour votre os et carte graphique tel que listé sur http://goldenshower.io/.</p>
<p>Les windowsiens peuvent avoir un probleme de dll. Dans ce cas y a un truc de plus à installer:</p>
<p>https://superuser.com/questions/1163409/msvcp120-dll-and-msvcr120-dll-are-missing</p>
<p>Si vous avez un doute, essayez en premier https://www.microsoft.com/en-us/download/confirmation.aspx?id=40784</p>
<p>Ensuite, vous votre miner depuis le terminal et on attend :)</p>


feed_id: http://sametmax.com/?p=23823
title: Tutorial pour Miner du Bitcoin GOLD – BTG 11 Recently updated !
uri: Tutorial-pour-Miner-du-Bitcoin-GOLD-BTG-11-Recently-updated
url: http://sametmax.com/tutorial-pour-miner-du-bitcoin-gold-btg/
content:
<p>ça y est le pool est open, tout devrait marcher !</p>
<p><strong>Comment on utilise un mining pool :</strong></p>
<p>Dans peu de temps (ou depuis peu de temps c’est selon), le mainnet (blockchain de prod) de BTG est en ligne, du coup, yahoo on peut commencer à miner. Avec des potes on s&#8217;est marrer à monter un pool de minage sur lequel vous pourrez vous connecter. <a href="http://goldenshower.io">http://goldenshower.io</a>, avec un nom pareil on s&#8217;es fait ban du listing du site officiel :) du coup on a pris goldenshow.io mais les 2 ndds marchent pareil.</p>
<p>&nbsp;</p>
<div id="attachment_23826" style="width: 810px" class="wp-caption aligncenter"><a href="http://goldenshower.io"><img class="wp-image-23826 size-full" src="media/219f5c54.thumbnail.png" data-original-source="http://sametmax.com/wp-content/uploads/2017/11/thumbnail.png" class="grouped_elements" rel="tc-fancybox-group23823" alt="Une bonne douche dorée de BTC ^^ " width="800" height="456" /></a><p class="wp-caption-text">Une bonne douche dorée de BTC ^^</p></div>
<p><a href="http://sametmax.com/de-la-thune-avec-un-mining-pool-de-btg/">Pour ceux qui ont loupé la 1ère partie c&#8217;est ici.</a></p>
<p>&nbsp;</p>
<p>Petit tuto rapide, mais j’espère clair :</p>
<p><strong>1) Créer un wallet BTG</strong></p>
<p><a href="https://btgwallet.online/">https://btgwallet.online/</a> ou là <a href="https://mybtgwallet.com/">https://mybtgwallet.com/</a><br />
Notez bien dans un endroit sécurisé tout ce qu’ils disent de noter (si si c’est important, sinon tous ces beaux Bitcoin Golds seront perdus à jamais). Vous obtiendrez votre adresse que nous nommerons <strong>bitcoin-gold-address</strong> dans la suite.</p>
<p><strong>2) Installer un logiciel de minage, selon votre système d’exploitation et la marque de votre carte graphique :</strong></p>
<p>Sur ces deux repos se trouvent les versions Linux et Windos (pas encore de miner pour OSX)</p>
<p>Si vous avez une carte graphique NVIDIA:<br />
EWBF v0.3.4b (NVIDIA) &#8211;  <a href="https://github.com/poolgold/ewbf-miner-btg-edition/releases">https://github.com/poolgold/ewbf-miner-btg-edition/releases</a></p>
<p>Si vous avez une carte graphique AMD:<br />
ClaymoreZcash v12.6 (AMD) &#8211; <a href="https://github.com/poolgold/ClaymoreBTGMiner/releases">https://github.com/poolgold/ClaymoreBTGMiner/releases</a></p>
<p>Il est possible que votre antivirus se plaigne, mais ces liens sont légitimes et utilisés par plein plein de gens sans problème.<br />
Ces logiciels contiennent des fonctions cryptographiques (ce qui fait hurler les antivirus) parce que justement c’est leur boulot en tant que mineurs.</p>
<p><strong>3) Configurer le mineur avant de le lancer :</strong></p>
<p>Sous Windows:<br />
* EWBF (les carte nvidia) : miner &#8211;server btg.goldenshow.io &#8211;user <strong>bitcoin-gold-address</strong>.worker &#8211;pass x &#8211;port 3857</p>
<p>* Claymore (les cartes AMD):<br />
Editez le fichier start.bat et mettez ça :</p>
<pre class="bash">set GPU_FORCE_64BIT_PTR=1
set GPU_MAX_HEAP_SIZE=100
set GPU_USE_SYNC_OBJECTS=1
set GPU_MAX_ALLOC_PERCENT=100
set GPU_SINGLE_ALLOC_PERCENT=100
</pre>
<p>Editer le fichier config.txt</p>
<pre class="bash">-zpool stratum+tcp://btg.goldenshow.io:3857
-zwal <strong>bitcoin-gold-address.worker</strong>
-zpsw x
-allpools 1
</pre>
<p>et lancer ZecMiner64.exe</p>
<p><strong>4) Pour les plus pointus d’entre vous, il y a quelques variantes :</strong></p>
<p>ports :</p>
<pre class="bash">3857 = PC standard à quelques GPU
3860 = petite ferme (10-15 GPU ou plus)
3870 = nicehash ou mega fermes ( + 150 gpus)
</pre>
<p>Pour linux c&#8217;est la même chose mais en créant un fichier bash à la place du .bat.</p>
<p>Si vous rencontrez des problèmes (et vous allez en avoir) on a un <a href="https://t.me/goldenshowio">chan Telegram</a>.</p>
<p>Happy mining !</p>


feed_id: http://sametmax.com/?p=23832
title: NiceHash – Pump up your power, à quoi ça sert et comment ça marche ?
uri: NiceHash-Pump-up-your-power-à-quoi-ça-sert-et-comment-ça-march
url: http://sametmax.com/nicehash-pump-up-your-power-a-quoi-ca-sert-et-comment-ca-marche/
content:
<p>Alors c’est quoi ce « gentil hachis » dont vous parlez sur Telegram, c’est un truc de cuisine ?</p>
<p>« Nicehash » c’est un service de location de puissance de « hash », en gros avoir le plaisir de posséder l’équivalent de 25000 cartes graphiques pendant un moment pour miner de la cryptomonnaie.<br />
C’est un peu la Smartbox (vous savez celle où on peut faire 200 bornes pour conduire un R8 pendant ¼ d’heure) de la crypto, mais sans sortir de chez soi, moins de plaisir, mais plus de rendement.</p>
<p>D’un côté Nicehash propose aux mineurs (ceux qui ont des machines qui chauffent leur maison toute la journée) de mettre ces machines en location, et d’un autre on peut participier à des enchères pour louer la puissance (additionnée) de plein de mineurs d’un coup pour devenir un moment un gros mineur bien velu.<br />
On voit bien sur ce graphe ce que ça donne là quand un gars s’est un peu énervé pendant ½ heure</p>
<p><img class="aligncenter size-full wp-image-23834" src="media/08d1421c.photo_2017-11-14_10-47-47.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/11/photo_2017-11-14_10-47-47.jpg" alt="un ptit coup de nicehash ?" width="1128" height="422" /><br />
Sur le <a href="https://t.me/goldenshowio">chan de Goldenshow</a>er.io on a l’histoire d’un gars qui a réussi à lancer ¼ d’heure de nNicehash au tout départ du BitcoinGold et en a ramassé une bonne grosse poignée à ce moment là, mais sinon de notre expérience avec le service, il est possible de faire un 10-25% de bénéfice (on achète du hashpower en BTC, on mine une monnaie, qu’on revend ensuite, et ça fait 10-25% de BTC en plus pour recommencer ).</p>
<h4>
Allons-y &#8220;gayment&#8221;! Rendez-vous sur <a href="https://www.nicehash.com/register">https://www.nicehash.com/ </a></h4>
<p>&nbsp;</p>
<p>On créer un compte, on valide tout ça et on passe aux choses sérieuses. Le tuto suivant décrit la méthode pour lancer un NiceHash sur la crypto Bitcoin Gold, qui est basé sur l&#8217;algo Equihash, pour d&#8217;autres cryptos il faudra choisir l&#8217;algo approprié mais pour le reste il n&#8217;y a rien à changer.</p>
<p>&nbsp;</p>
<ol>
<li>On va dans le marketplace (place de marché)<br />
<img class="aligncenter size-full wp-image-23835" src="media/ad288adb.1_Goto_marketplace.png" data-original-source="http://sametmax.com/wp-content/uploads/2017/11/1_Goto_marketplace.png" alt="On sélectionne  market place" width="1052" height="532" /></li>
<li>On sélectionne l&#8217;algo approprié à la crypto que l&#8217;on va miner, ici pour BTG (Bitcoin Gold) on sélectionne Equihash.<br />
<img class="aligncenter size-full wp-image-23836" src="media/0ceed16c.2_SelectAlgo.png" data-original-source="http://sametmax.com/wp-content/uploads/2017/11/2_SelectAlgo.png" alt="Equihash est l'algo que l'on va utiliser pour miner du BTG (Bitcoin Gold)" width="1376" height="879" /></li>
<li>La partie la plus importante, Il va falloir envoyer notre puissance de calcul louée sur un pool, ici sur goldenshower.io. Pourquoi celui-là et pas un autre ?<br />
Parce que c&#8217;est celui de Sam&amp;Max (et des potes) , qu&#8217;on est les plus beaux et qu&#8217;on a besoin de tunes pour aller aux putes régulièrement et vous mijoter de jolis articles tous mignons.<br />
<img class="aligncenter size-full wp-image-23837" src="media/ff990f1e.3_SetupPool.png" data-original-source="http://sametmax.com/wp-content/uploads/2017/11/3_SetupPool.png" alt="PArtie la plus important, setup du pool " width="589" height="622" /><strong>Pool Name:</strong> Golden Show (le nom de votre pool, mettez ce que vous voulez, c&#8217;est pour le reconnaître par la suite dans la liste.)<br />
<strong>Stratum hostname ou IP:</strong> btg.goldenshow.io<br />
<strong>port:</strong> 3870<br />
<strong>User:</strong> là il faut mettre votre addresse de Wallet BTG que vous <a href="http://sametmax.com/tutorial-pour-miner-du-bitcoin-gold-btg/">aurez créé en suivant notre tuto précédent ici</p>
<p></a></li>
<li>On place son Order (et oui comme à la bourse) qui va consister à acheter de la puissance de Hash à un prix fixé par vous.<br />
<span style="color: #ff0000;">ATTENTION!</span> Avant de placer un order il faut créditer son compte Nicehash avec des BTC (Bitcoins), car tout se paie en BTC.<br />
Sur la figure suivante j&#8217;ai placé un order à 0.01258 BTC.</p>
<p><strong>PRICE: </strong>par défaut un prix est suggéré , il faut regarder dans la liste des ordres à côté que vous êtes dans les bonnes valeurs, un prix trop bas et votre ordre ne passera jamais.<br />
<strong>LIMIT: </strong>sert à limiter la puissance de calcul envoyée dans le temps, pour les premiers essais il vaut mieux mettre une faible valeur (attention si vous mettez 0 nicehash va envoyer toute la puissance d&#8217;un coup) en cas de mauvaise configuration du pool, ça serait con d&#8217;envoyer toute la puissance sur un truc qui mine pas :)<br />
<strong>AMOUNT: </strong>le budget que vous voulez allouer, là aussi au départ une petite somme pour tester l&#8217;artillerie, une fois que vous êtes sûr que ça marche, vous pouvez placez un ordre plus important.</p>
<p><img class="aligncenter size-full wp-image-23838" src="media/e44b0b74.4_SetupOrder.png" data-original-source="http://sametmax.com/wp-content/uploads/2017/11/4_SetupOrder.png" alt="on achète des gigoWatts Doc !!" width="603" height="401" /></li>
<li>Et C&#8217;est tout ! La puissance de calcul louée sur Nicehash va être transmise au pool goldenshow.io et c&#8217;est comme si vous aviez une ferme de GPU qui mine. Elle est pas belle la vie ?<br />
<img class="aligncenter size-full wp-image-23840" src="media/57d85569.6_MiningStart.png" data-original-source="http://sametmax.com/wp-content/uploads/2017/11/6_MiningStart.png" alt="6_MiningStart" width="1257" height="809" /></li>
</ol>
<p style="text-align: left;">Si vous voulez racheter de la puissance de calcul vous éditez votre order dans la liste et vous changez les valeurs appropriées.<br />
<img class="aligncenter size-full wp-image-23842" src="media/c58ef3dd.8_If_Need_Change_Price_or_refill.png" data-original-source="http://sametmax.com/wp-content/uploads/2017/11/8_If_Need_Change_Price_or_refill.png" alt="8_If_Need_Change_Price_or_refill" width="708" height="464" /><br />
Vous l&#8217;aurez compris, Nicehash permet d&#8217;avoir l&#8217;équivalent d&#8217;une immense ferme de GPUs sans les inconvenients. Pratique pour miner à la sortie d&#8217;une crypto sans avoir à setup grand chose et pour se rendre compte immédiatement de la rentabilité de minage de la monnaie concernée.<br />
A savoir qu&#8217;en général quand une monnaie sort la difficulté est faible donc ça vaut le coup de se lancer dessus et le Nicehash est la solution la plus rapide.</p>
<p>Rendez-vous sur <a title="Mining Pool" href="http://goldenshow.io">goldenshow.io</a>, votre pool préféré pour miner (pas exclu qu&#8217;on rajoute d&#8217;autres cryptos soon ^^ )</p>
<p><strong>Les précédents Tutos:</strong></p>
<p><a href="http://sametmax.com/de-la-thune-avec-un-mining-pool-de-btg/"><strong>http://sametmax.com/de-la-thune-avec-un-mining-pool-de-btg/</strong></a></p>
<p><a title="miner du BTG" href="http://sametmax.com/tutorial-pour-miner-du-bitcoin-gold-btg/"><strong>http://sametmax.com/tutorial-pour-miner-du-bitcoin-gold-btg/</strong></a></p>


feed_id: http://sametmax.com/?p=23894
title: GoldenShower sera coupé, faute de miners
uri: GoldenShower-sera-coupé-faute-de-miners
url: http://sametmax.com/goldenshower-sera-coupe-faute-de-miners/
content:
<p>Slt les gens,</p>
<p>&nbsp;</p>
<p>On va couper le pool <a title="Tutorial pour Miner du Bitcoin GOLD – BTG" href="http://sametmax.com/tutorial-pour-miner-du-bitcoin-gold-btg/">Goldenshower</a>, car ça coûte en hébergement et qu&#8217;il n&#8217;y a plus de miners pour espérer choper un block. C&#8217;est la loi du &#8220;transvasationnagement&#8221; des liquides. Si vous voulez continuer l&#8217;aventure essayez les pool btgpool ou suprnova. Je vous encourage d&#8217;ailleurs à vous intéresser aux crypto-monnaies dans l&#8217;ensemble, ça fait pas de mal ^^</p>
<p>&nbsp;</p>
<p>On remercie tous ceux qui ont participé à l&#8217;aventure en espérant que vous aurez appris au moins autant que nous. Pour info on a rien gagné, les coms de la pool ayant payé l&#8217;hébergement du serveur et quelques NiceHash (qui s&#8217;est fait hacker au passage&#8230;)</p>
<p>Possible qu&#8217;on monte un autre pool mais l&#8217;expérience nous a appris que c&#8217;est pas facile sans une forte concentration de miners.</p>
<p>Je pense vous faire un tuto sur les Masternodes bientôt pour voir les cryptos sous un autre angle.</p>
<p>Passez de bonnes fêtes!</p>
<p>Max,</p>
<p>&nbsp;</p>


feed_id: http://sametmax.com/?p=23913
title: Le point sur les crypto-monnaies 10 Recently updated !
uri: Le-point-sur-les-crypto-monnaies-10-Recently-updated
url: http://sametmax.com/le-point-sur-les-cryptos/
content:
<p>Max est arrivé, il a posté, puis il est reparti.</p>
<p>Miner du Bitcoin Gold n&#8217;a pas été rentable du tout, ni pour vous, ni pour la team de GoldenShower. Et NiceHash s&#8217;est fait hacké. Mais au moins c&#8217;était fun.</p>
<p>Cela dit ce n&#8217;était que la partie émergée de l&#8217;iceberg, et  avec tout le bordel actuel, vous avez peut-être envie d&#8217;un petit topo pour remettre tout en contexte.</p>
<p>Il y a 5 ans, je vous parlais du Bitcoin, un projet qui expérimentait avec l&#8217;idée de créer une monnaie <strong>décentralisée</strong>, non dirigée par les banques ou les états.</p>
<p>Le système Bitcoin a introduit les bases d&#8217;un système novateur:</p>
<ul>
<li>Tout le monde est égal, et peut créer un compte Bitcoin sans aucun prérequis. C&#8217;est ce qu&#8217;on appelle le wallet. Les techniques modernes de chiffrement permettent à chaque wallet de s&#8217;identifier, et de déclarer des transactions. </li>
<li>Personne ne possède ses propres bitcoins, mais chaque personne dans le réseau peut télécharger tout l&#8217;historique des transactions depuis la création du Bitcoin. Cette base de données est ce qu&#8217;on appelle la blockchain. Ainsi le système sait exactement qui peut dépenser quoi.
<li>Chaque personne peut participer à la création de la monnaie. C&#8217;est ce qu&#8217;on appelle le minage, et en gros on demande à son ordinateur de résoudre un problème mathématique complexe. On obtient la monnaie quand on peut donner la preuve qu&#8217;on a résolu le problème. C&#8217;est ce qu&#8217;on appelle le &#8220;proof of work&#8221;.</li>
</ul>
<p>Bitcoin est un peu le prototype de la roue, taillé dans la pierre: révolutionnaire, mais vraiment super lourd.</p>
<ul>
<li>Tout est public. Les wallets sont anonymes, mais toutes les transactions sont en clair. Les premiers marchés noirs (remember the silk road ?) se sont fait tej assez vite.</li>
<li>Les transactions irréversibles et la complexité technique pour sécuriser son portefeuille ont amené de nombreuses attaques.</li>
<li>La nature de la production du BTC a amené des gens à se regrouper en grosse communauté afin de miner plus facilement, empêchant les individus seuls de participer de manière significative. C&#8217;est ce qu&#8217;on appelle les pools. De plus, les gros capitaux ont investi dans de grosses fermes d&#8217;ordinateurs pour miner en masse. Une grosse partie est en Chine, et ils ont une énorme influence sur le Bitcoin qui n&#8217;est donc plus autant décentralisé.</li>
<li>La blochain est devenue énorme. <a href="https://bitinfocharts.com/">Plus de 150Go</a> et ça va continuer à grossir. Héberger un noeud complet sur son téléphone n&#8217;est plus faisable. Du coup les gens utilisent des wallets légers, qui font confiance à un service externe. Bitcoin perd encore plus son bénéfice de décentralisation.</li>
<li>Les transactions sont lentes. On plafonne à quelques échanges par seconde. Pour le monde entier !</li>
<li>Bitcoin a déjà vu deux forks, le Bitcoin Cash et le Bitcoin Gold, à cause de toutes ses limitations.</li>
</ul>
<p>Malgré ça, de par le nom célèbre et la robustesse technique du système, Bitcoin reste la référence de la cryptomonnaie. En quelque sort &#8220;l&#8217;or&#8221;, la valeur refuge. Amusant quand on connait sa volatilité. Le cours a explosé (plus de 15000 euros), <a href="https://www.letemps.ch/economie/2017/12/11/bourse-chicago-bitcoin-demarre-trombe">la bourse de Chicago ouvre les vannes de la spéculation officielle</a> et on peut même en acheter avec sa CB de nos jours (ce qui n&#8217;était pas le cas au début).</p>
<p>En gros, Bitcoin est légitimé.</p>
<p><a href="media/6cf5b54f.LEPQ6E0.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/12/LEPQ6E0.jpg" class="grouped_elements" rel="tc-fancybox-group23913"><img src="media/6cf5b54f.LEPQ6E0.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/12/LEPQ6E0.jpg" alt=" " width="750" height="647" class="aligncenter size-full wp-image-23916" /></a></p>
<p>Et c&#8217;est ironique, car cette légitimation passe par la négation du projet original. Bitcoin n&#8217;est plus du tout une monnaie alternative aux mains du peuple, mais un instrument spéculatif de plus.</p>
<p>Les cryptomonnaies actuelles ont une valeur aberrante, sans rien derrière. C&#8217;est du vent total.</p>
<h2>Alors qu&#8217;est-ce qui se passe maintenant ?</h2>
<p>Et bien d&#8217;abord les cryptomonnaies alternatives ont fleuri. Il y en a des centaines. La plupart sans aucun projet, avec des teams branlantes et l&#8217;espoir de &#8220;mooner&#8221; (que le cours monte jusqu&#8217;à la lune).</p>
<p>Certaines cryptos sont très intéressantes néanmoins:</p>
<ul>
<li>Ethereum a montré la voie des smart contrats, et permet de glisser des programmes dans la blockchain que chacun peut exécuter en dépensant des ETH. </li>
<li>Dash a popularisé le concept du master node: certains wallets immobilisent du capital (par exemple 1000 dash), et en échange obtiennent la confiance du réseau pour effectuer des tâches (accélérer les transactions, anonymiser les échanges, etc) contre des prélèvements (fee) qui s&#8217;ajoutent à leur pécule.</li>
<li>Monero est devenu célèbre parmi les créateurs de virus (et de mineurs JavaScript) car il permet de miner sur le CPU et est anonyme.</li>
<li>VTC a promu l&#8217;idée d&#8217;être ASIC resistant, c&#8217;est-à-dire de rendre difficile d&#8217;acheter du matériel spécialisé pour le minage pour créer une grosse ferme.</li>
<li>Ripple est préminé (toutes les pieces existent déjà) et soutenu par les banques et les GAFAS.</li>
<li>Electroneum (Max l&#8217;appelle &#8220;electroscam&#8221;) veut créer du &#8216;fake mining&#8217; et permettent aux gosses de la cour de récré de générer du cash depuis leur téléphone.</li>
<li>duniter mise sur l&#8217;aspect social: mineur est un status qu&#8217;il faut obtenir et maintenir en convainquant 5 humains de voter pour soi, tous les 2 ans.</li>
</ul>
<p>Du coup il y a une vraie exploration technique, et ça va donner des choses intéressantes. M<a href="https://medium.com/e-residency-blog/were-planning-to-launch-estcoin-and-that-s-only-the-start-310aba7f3790">ême les états s&#8217;y mettent</a>.</p>
<p>Néanmoins soyons honnête, l&#8217;utilisateur moyen s&#8217;en bat les couilles (oui les couilles, l&#8217;utilisateur moyen n&#8217;est clairement pas une utilisatrice pour le moment) et veut juste avoir de l&#8217;argent qui rentre en espérant que plus d&#8217;argent sort.</p>
<p><a href="media/7b9d8fcd.szEys0O.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/12/szEys0O.jpg" class="grouped_elements" rel="tc-fancybox-group23913"><img src="media/7b9d8fcd.szEys0O.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/12/szEys0O.jpg" alt="" width="460" height="612" class="aligncenter size-full wp-image-23915" /></a></p>
<p>Pour répondre à cette demande, de <a href="http://cryptopia.co.nz/">nombreuses</a> <a href="http://coinsmarkets.com/">places de marché</a> <a href="http://yobit.net/">ont vu le jour</a>. On peut échanger des trucs obscurs tels que le Wyvern, l&#8217;ObamaCare, le Satancoin, le CheeseCoin, le Marijuanacoin, le GirlsToken ou le CharlieChaplinCoin.</p>
<p>J&#8217;aimerais vraiment vous dire que je plaisante. Mais non.</p>
<p>Et puis tout ça va finir en bulle. Et ça va péter. Et des tas de gens vont tout perdre. Dans 6 mois ? Dans 2 ans ? Dans 10 ans. Aucune idée. Personne ne sait. On sait juste que ça va arriver. On est pas dupe, ces monnaies de singe ne valent rien: pas d&#8217;atout technique, pas de projet social, pas de team de ouf, pas de gros backers&#8230; Rien pour compenser l&#8217;absence de garantie par l&#8217;Etat qu&#8217;une vraie monnaie a. </p>
<p>Le petit secret, c&#8217;est que la plupart des ces cryptos sont des forks des projets principaux (Btc, eth, dash, etc) avec juste un logo différent. Ou pire, juste un smart contract sur ETH et même pas de blockchain, quand on est vraiment paresseux et doué en com, pourquoi se faire chier.</p>
<p>Une minorité, mais bien réelle, deviendront ancrées dans la société après la crise. Après tout la possibilité de stocker une valeur et de l&#8217;échanger sans contrôle et rapidement est trop intéressante. Le jeu du chat et de la souris avec les institutions va continuer. Il va y avoir législation. Et au bout d&#8217;un temps, acceptation sous certaines conditions.</p>
<p>De plus, les innovations techniques autour de la blockchain vont produire des choses vraiment utiles, et on les utilisera.</p>
<p>Mais la plupart des monnaies actuelles vont disparaitre au son des pleurs. Tout le monde le sait, mais tout le monde s&#8217;en fout. On espère tous que ce sera le voisin, et que nous nous on sera riche. Les gens s&#8217;identifient beaucoup plus souvent au début du &#8220;loup de wall street&#8221; qu&#8217;à la fin de &#8220;the big short&#8221;.</p>
<p>Déjà que je regrette la centaine de BTC que j&#8217;ai vendu avant que ça monte, alors j&#8217;imagine le sentiment quand tout s&#8217;écroule après l&#8217;achat&#8230;</p>
<h2>Et comment je fais du pognon moi alors ?</h2>
<p>Ben si je savais comment faire de la thune a coup sûr, je le ferais et je ne le vous le dirais pas, bande de guignols.</p>
<p>Mais avec Max, on essaye de profiter de la situation.</p>
<p>Déjà, pour le moment, acheter les cryptos les plus célèbres (Bitcoin, Ethereum, Monero, Dash, Litecoin&#8230;), a été une stratégie gagnante puisque ça monte énormément. </p>
<p>Ensuite il y les investissements alternatifs. Par exemple notre bande de potes investis dans <a href="https://masternodes.pro/">des master nodes</a> (particulièrement le Vivo, le CRC, l&#8217;interzone, etc). Comme le dit Max &#8220;20k en assurance vie m&#8217;a rapporté 200 euros en 5 ans. Sur un masternode, 7k me rapporte 40euros par jour&#8221;. Évidement&#8230;</p>
<p>Enfin il y a la stratégie &#8220;pendant la ruée vers l&#8217;or, vends des pelles&#8221;. </p>
<p>Max essaye de mettre en place un système de bot facile à scripter pour spéculer sur toutes les plateformes de manière uniformisée, et les louer. </p>
<p>Moi je monte un système pour gérer les master nodes des gens en échange d&#8217;une part des gains. C&#8217;est que c&#8217;est chiant à monter et maintenir ces petites bestioles.</p>
<p><a href="media/23d80ef0.i0uRTzf.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/12/i0uRTzf.jpg" class="grouped_elements" rel="tc-fancybox-group23913"><img src="media/23d80ef0.i0uRTzf.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/12/i0uRTzf.jpg" alt=" " width="540" height="396" class="aligncenter size-full wp-image-23917" /></a></p>
<p>Si vous comptez mettre du pognon là dedans, n&#8217;oubliez pas de ne jouer dans ce grand casino bordélique et immoral que ce que vous pouvez perdre. </p>
<p>Mais la vérité ?</p>
<p>En tant que dev, on s&#8217;était pas autant marré depuis les débuts du Web, quand on bricolait des services pourris en PHP pour se faire une place.</p>


feed_id: http://sametmax.com/?p=23944
title: Monter son master node Interzone (ITZ) 3 Recently updated !
uri: Monter-son-master-node-Interzone-(ITZ)-3-Recently-updated
url: http://sametmax.com/monter-son-master-node-interzone-itz/
content:
<p>Acheter et vendre <a href="http://sametmax.com/le-point-sur-les-cryptos/">des cryptomonnaies</a>, tout le monde comprend le principe. J&#8217;achète un truc, j&#8217;attends, je le revends. Si le prix a monté, je gagne du pognon, s’il est descendu, j&#8217;en perds.</p>
<p>Mais il existe d&#8217;autres formes d&#8217;investissement. L&#8217;une d&#8217;elles est le master node, et on va apprendre à en monter un.</p>
<p>Attention, ça demande de savoir administrer un serveur linux. Le tutoriel n&#8217;explique pas <code>bash</code>, <code>apt</code>, <code>ssh</code> ou <code>make</code> et suppose que vous êtes à l&#8217;aise avec ces outils. Si ce n&#8217;est pas la cas&#8230; pas de bol.</p>
<h2>C&#8217;est quoi déjà ?</h2>
<p>Bitcoin n&#8217;est plus la seule crypto, il y en a maintenant des centaines, et certaines essayent de se distinguer technologiquement.</p>
<p>Quelques-unes ont le concept de master node, des machines dont les propriétaires ont acheté un certains nombre de coins, et les bloquent. En échange de quoi, le réseau donne à la machine le droit de faire certaines opérations en plus, opérations qui rendent service au réseau (rendre les exchanges anonymes, accélérer les transactions, etc).</p>
<p>Le but des master nodes est double:</p>
<ul>
<li>Avoir toujours plein de wallets répartis dans le monde et avec plein de propriétaires différents. Ça renforce le réseau.</li>
<li>Forcer les gens a acheter plein de coins et donc faire monter le cours, faisant gagner du pognon aux créateurs de la monnaie qui en ont généralement préminé une partie.</li>
</ul>
<p>Mais pour le propriétaire du master node, qu&#8217;est-ce qu&#8217;on y gagne ? </p>
<p>Et bien tous les jours, une cagnotte est répartie équitablement entre tous les masternodes en récompense de leur service. </p>
<p>Par exemple, j&#8217;ai monté la semaine dernière un master node <a href="https://www.cryptopia.co.nz/Exchange/?market=VIVO_BTC">Vivo</a>. Il a couté a l&#8217;achat 3200 euros. Tous les jours, il génère 5 vivos, soit actuellement 20 euros. En plus de cela, le vivo a augmenté de prix depuis l&#8217;achat, et le master node vaut maintenant 5000 euros si je décide de revendre les coins qui sont bloquées. Mais ça voudrait dire fermer mon master node.</p>
<h2>Choisir un master node</h2>
<p>Tous les master nodes ont des coûts et une rentabilité différents. Il existe <a href="https://masternodes.online/">des listing</a> qui permettent de se faire une idée de la question.</p>
<p>Aujourd&#8217;hui je vais vous faire un tuto sur le master node <a href="https://masternodes.online/currencies/ITZ/">Interzone</a>, car il est très peu cher à l&#8217;achat: moins de 300 euros. Évidemment, il ne rapporte que 2 euros par jour.</p>
<p>Mais si vous voulez apprendre à faire des master nodes, c&#8217;est plus simple que de débloquer 5000 balles pour du vivo.  Ou pire, un million pour un node dash :)</p>
<p>Interzone est aussi un wallet très basique, et donc simple à monter.</p>
<h2>Acheter les coins</h2>
<p>D&#8217;abord, il faut acheter les coins. Le nombre de coins à acheter est différent pour chaque type de node. Pour Interzone, c&#8217;est 5000 à bloquer, et donc on va en acheter 5001 pour les frais de transaction.</p>
<p>Pour se faire, il faut d&#8217;abord acheter une monnaie plus populaire sur une plateforme d&#8217;achat. Par exemple, vous pouvez acheter du Bitcoin sur <a href="http://bitstamp.net/">Bitstamp</a>. </p>
<p>Ensuite, faite un virement (withdrawal) vers une plateforme d&#8217;échange.</p>
<p>Tout ça se fait en plusieurs étapes.</p>
<p>D&#8217;abord, ouvrir des comptes sur ces sites, et faire les putains de vérifications de sécurité. Ouai, si vous vouliez trader anonymement c&#8217;est raté. Et parfois c&#8217;est long. Très long. Par exemple pour les achats par carte bancaire, Bitstamp m&#8217;avait demandé une photo de moi tenant mon passeport. Je sais pas si ils le font toujours, mais c&#8217;est over chiant.</p>
<p>&#8230;</p>
<p>Je vous laisse vous occupez de tous ça, on se revoit dans quelques jours.</p>
<p>&#8230;</p>
<p>Ça y est, de retour ?</p>
<p>Ok.</p>
<p>D&#8217;une part on va aller sur un exchange voir <a href="https://coinsmarkets.com/trade-BTC-ITZ.htm">le cours de l&#8217;Interzone</a> pour savoir combien de BTC acheter.</p>
<p>Par exemple à cet instant je vois que je peux acheter un ITZ pour entre 0.000002699 et 0.000007300 BTC. En regardant les cours, je vois que j&#8217;ai suffisamment de vendeurs pour avoir 5001 ITZ à 0.000002990 BTC, donc 0.0149529900 BTC. On rajoute les fees de l&#8217;exchange (0.0000373824750 BTC) et on prend en compte les <a href="https://estimatefee.com/">fees de transactions</a> de la block chain bitcoin (0.00265914 BTC).</p>
<p>Total: 0.017649512 BTC, soit 281.57 euros sur Bitstamp. </p>
<p>Parfois c&#8217;est plus, parfois c&#8217;est moins. Ça fluctue beaucoup.</p>
<p>On achète ça. Ça prend encore du temps&#8230;</p>
<p>Quand on a tout, on fait le virement sur son autre wallet, celui sur l&#8217;exchange.</p>
<p>Depuis l&#8217;exchange, on achète enfin son Interzone.</p>
<h2>Monter son master node</h2>
<p>En théorie on peut faire ça avec <a href="https://interzone.space/#service">un client</a>, mais en pratique ils ne marchent jamais. En plus il faut que ça reste allumé tout le temps et il faut avoir une IP statique. </p>
<p>Donc on va le faire sur son propre serveur linux.</p>
<p>Le plus pratique est d&#8217;avoir un serveur à soi qui tourne quelque part, ou de louer un <a href="http://online.net/">VPS</a> au prix minimal. En effet un master node, ça consomme que dalle en ressource et vous pouvez le mettre sur un raspberry pi si ça vous chante.</p>
<p>Parce que je suis pas maso, je vais expliquer que pour une distro, car il va falloir compiler. On va donc faire ça pour une Ubuntu 16.04.</p>
<p>D&#8217;abord on s&#8217;assure d&#8217;être toujours à l&#8217;heure:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get install</span> ntp ntpdate
<span style="color: #c20cb9; font-weight: bold;">sudo</span> update-rc.d ntp <span style="color: #7a0874; font-weight: bold;">enable</span></pre></td></tr></table></div>

<p>On installe la tetrachiée de dépendances:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get install</span> build-essential software-properties-common <span style="color: #c20cb9; font-weight: bold;">nano</span> libboost-all-dev libzmq3-dev libminiupnpc-dev libssl-dev libevent-dev   libtool autotools-dev <span style="color: #c20cb9; font-weight: bold;">automake</span> pkg-config libssl-dev libevent-dev bsdmainutils libboost-all-dev</pre></td></tr></table></div>

<p>Ensuite, on a besoin de downgrader une lib, donc, ppa:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> add-apt-repository ppa:bitcoin<span style="color: #000000; font-weight: bold;">/</span>bitcoin
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get update</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get install</span> libdb4.8-dev libdb4.8++-dev</pre></td></tr></table></div>

<p>On download les sources:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">wget</span> https:<span style="color: #000000; font-weight: bold;">//</span>github.com<span style="color: #000000; font-weight: bold;">/</span>projectinterzone<span style="color: #000000; font-weight: bold;">/</span>ITZ<span style="color: #000000; font-weight: bold;">/</span>archive<span style="color: #000000; font-weight: bold;">/</span>master.zip
<span style="color: #c20cb9; font-weight: bold;">unzip</span> master.zip</pre></td></tr></table></div>

<p>Et on compile:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">cd</span> ITZ-master 
.<span style="color: #000000; font-weight: bold;">/</span>autogen.sh
.<span style="color: #000000; font-weight: bold;">/</span>configure
<span style="color: #c20cb9; font-weight: bold;">make</span></pre></td></tr></table></div>

<p>Vous pouvez aller boire un coup, pisser, faire la sieste. Ça prend pas mal de RAM, donc si vous serveur en a pas assez, faites les sur un ordi local avec la même version de linux.</p>
<p>Une fois tout ça terminé, le résultat est que dans le dossier ITZ-master/src vous avez deux executable:</p>
<ul>
<li>interzoned (le daemon qui va servir de master node)</li>
<li>interzone-cli (le client qui va vous permettre d&#8217;envoyer des ordres au master node)</li>
</ul>
<p>C&#8217;est ce qu&#8217;on va utiliser. Si vous avez compilé en local, uploadez les n&#8217;importe où sur votre serveur.</p>
<p>Maintenant, on se place sur le serveur, dans le dossier qui contient interzoned et interzone-cli, et on va créer un fichier de config.</p>
<p>Pour le fichier de config, il vous faut l&#8217;adresse IP du serveur. On peut la choper avec:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">dig</span> TXT +short o-o.myaddr.l.google.com <span style="color: #000000; font-weight: bold;">@</span>ns1.google.com <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">awk</span> <span style="color: #660033;">-F</span><span style="color: #ff0000;">'&quot;'</span> <span style="color: #ff0000;">'{ print $2}'</span>
xxx.xxx.xxx.xxx</pre></td></tr></table></div>

<p>Le port, lui, est toujours 55675 (soyez sur de pas le bloquer).</p>
<p>Puis on choisit un mot de passe pour le client:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">tr</span> <span style="color: #660033;">-cd</span> <span style="color: #ff0000;">'[:alnum:]'</span> <span style="color: #000000; font-weight: bold;">&lt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>urandom <span style="color: #000000; font-weight: bold;">|</span> fold <span style="color: #660033;">-w30</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">head</span> <span style="color: #660033;">-n1</span>
BjHQ2T95Og2VNxsVDQ5qcFBU1eVNHP</pre></td></tr></table></div>

<p>On ouvre le fichier:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">mkdir</span> .interzone
<span style="color: #c20cb9; font-weight: bold;">vi</span> .<span style="color: #000000; font-weight: bold;">/</span>interzone<span style="color: #000000; font-weight: bold;">/</span>interzone.conf</pre></td></tr></table></div>

<p>Et on écrit dedans:</p>
<pre>
bind=<L'ip du serveur>:55675
rpcuser=interzone
rpcpassword=BjHQ2T95Og2VNxsVDQ5qcFBU1eVNHP</pre>
<p>Puis on lance le daemon:</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>interzoned <span style="color: #660033;">-daemon</span> <span style="color: #660033;">-reindex</span></pre></td></tr></table></div>

<p>Si vous êtes consciencieux, ajoutez un service qui le démarre quand votre machine boot.</p>
<p>Au premier lancement, il va télécharger toute la block chain, mais ici c&#8217;est seulement 140Mo car interzone est tout jeune encore. Donnez-lui 30 minutes pour être tranquille.</p>
<p>Au bout de quelques minutes, votre client pourra déjà se connecter au master node et voir le progrès avec:</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>interzone-cli getinfo 
<span style="color: #7a0874; font-weight: bold;">&#123;</span>
...
    <span style="color: #ff0000;">&quot;blocks&quot;</span> : <span style="color: #000000;">92477</span>,
...
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></td></tr></table></div>

<p>Il est temps de loader votre master node avec du pognon ! On se fait une adresse:</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>interzoned getnewaddress MN1
1MKDs1yNze7VEr4zWHTKbiV3T3fBTwtxZ4</pre></td></tr></table></div>

<p>Et là vous allez sur votre exchange où vous avez acheté vos coins, et vous faite un transfert d&#8217;EXACTEMENT 5000 coins sur cette adresse (la votre, pas 1MKDs1yNze7VEr4zWHTKbiV3T3fBTwtxZ4, bande de moules). Pas un sou de moins. Pas un sou de plus.</p>
<p>Vous attendez que les coins arrivent. Ça peut prendre quelques minutes. Vérifiez avec:</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>interzone-cli getbalance
<span style="color: #000000;">5000.00</span></pre></td></tr></table></div>

<p>Si ça dit 5000, c&#8217;est bon.</p>
<p>Il est temps de démarrer notre master node.</p>
<p>D&#8217;abord, on arrête le daemon:</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>interzone-cli stop</pre></td></tr></table></div>

<p>Ensuite, on se génère une clé privée pour notre master node:</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>interzone-cli masternode genkey
EHLKJHoYfNaeziVMAtLs5678G9Em861r3456xtYh1TEotpY1</pre></td></tr></table></div>

<p>Ensuite on rouvre notre fichier de config, et on le met à jour pour contenir ça:</p>
<pre>bind=<L'ip du serveur>:55675
rpcuser=interzone
rpcpassword=BjHQ2T95Og2VNxsVDQ5qcFBU1eVNHP
masternode=1
masternodeprivkey=EHLKJHoYfNaeziVMAtLs5678G9Em861r3456xtYh1TEotpY1</pre>
<p>Ne soyez pas con, n&#8217;utilisez pas la clé que je poste dans ce tuto.</p>
<p>On va aussi chiffrer son waller, maintenant qu&#8217;on a des sous dessus, pour éviter de se le faire tirer. On génère un nouveau mot de passe, et on encrypt:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">tr</span> <span style="color: #660033;">-cd</span> <span style="color: #ff0000;">'[:alnum:]'</span> <span style="color: #000000; font-weight: bold;">&lt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>urandom <span style="color: #000000; font-weight: bold;">|</span> fold <span style="color: #660033;">-w30</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">head</span> <span style="color: #660033;">-n1</span>
efFMgBGFpVhlQ0j8o8N4TaC5XdASyG
$ .<span style="color: #000000; font-weight: bold;">/</span>interzone-cli encryptwallet <span style="color: #ff0000;">&quot;efFMgBGFpVhlQ0j8o8N4TaC5XdASyG&quot;</span></pre></td></tr></table></div>

<p><strong>Faites un backup de votre wallet avant et du mot de passe. Si vous perdez ça, vous êtes niqué de chez niqué.</strong></p>
<p>Vous pouvez déverrouiller le wallet avec:</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>interzone-cli walletpassphrase efFMgBGFpVhlQ0j8o8N4TaC5XdASyG <span style="color: #000000;">120</span></pre></td></tr></table></div>

<p>efFMgBGFpVhlQ0j8o8N4TaC5XdASyG étant à remplacer avec votre mot de passe fraichement généré et 120 est le nombre de secondes pour le garder débloqué.</p>
<p>Il est temps de relancer le daemon:</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>interzoned <span style="color: #660033;">-daemon</span></pre></td></tr></table></div>

<p>Et finalement, le passer en master node:</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>interzone-cli masternode start</pre></td></tr></table></div>

<p>C&#8217;est good.</p>
<p>Vous pouvez vérifier que ça a été accepté par le réseau avec:</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>interzone-cli masternodelist <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> PUBLIC_IP</pre></td></tr></table></div>

<p>Toutes les 24h, vous pourrez joyeusement contempler le chiffre fourni par <code>./interzone-cli getbalance</code> qui augmente. Et vous pouvez envoyer vos coins où vous le souhaitez (par exemple pour les revendre) avec un joli:</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>interzone-cli walletpassphrase <span style="color: #000000; font-weight: bold;">&lt;</span>votre password<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000;">120</span>
.<span style="color: #000000; font-weight: bold;">/</span>interzone-cli sendtoaddress</pre></td></tr></table></div>

<h2>Sécurité</h2>
<p>Votre master node est ici configuré en mode &#8220;hot wallet&#8221;, c&#8217;est-à-dire que vos coins sont sur le serveur. Il existe une méthode, plus complexe, plus longue, mais plus sure, qui permet de le configurer en &#8220;cold wallet&#8221;. Vos coins sont alors sur votre machine, et un lien est fait enter votre machine et votre master node.</p>
<p>Si la sécurité vous importe, je vous invite donc à étudier la question.</p>
<p>Renforcer la configuration du firewall aussi est une bonne idée, puisque maintenant vous êtes une cible d&#8217;attaque potentielle.</p>
<p>Enfin, n&#8217;oubliez pas de vider tout l&#8217;historique bash en partant, histoire de pas avoir tous les trucs en clair dedans:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null <span style="color: #000000; font-weight: bold;">&gt;</span> ~<span style="color: #000000; font-weight: bold;">/</span>.bash_history <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #7a0874; font-weight: bold;">history</span> <span style="color: #660033;">-c</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #7a0874; font-weight: bold;">exit</span></pre></td></tr></table></div>

<p>Et backupez comme des porcs aussi.</p>
<h2>Profit ?</h2>
<p>J&#8217;espère pour vous que tout ça va fructifier (et pour moi aussi). Si c&#8217;est le cas, vous savez ce qu&#8217;il vous reste à faire: envoyez-nous une carte postale de votre ile deserte. Ou des ITZ à 1AChuSLWAHQgmkGa84AHqBRCs1Z1cxHjnU. Ça marche aussi.</p>
<p>Si vous avez tout perdu, sachez que c&#8217;est la faute de Max. Je peux vous donner son adresse. </p>
<p>Et pour tous ceux qui n&#8217;ont pas la foi de faire tout ça, je pense que je vais monter un service qui permet de cliquer et acheter des masternodes automatiquement. </p>


feed_id: http://sametmax.com/?p=23967
title: Les critiques des ORM sont à côté de la plaque
uri: Les-critiques-des-ORM-sont-à-côté-de-la-plaque
url: http://sametmax.com/les-critiques-des-orm-sont-a-cote-de-la-plaque/
content:
<p>En ce moment, y a deux modes. Dire que les cryptomonnaies c&#8217;est génial, et dire que les ORM c&#8217;est de la merde.</p>
<p>Durant les derniers articles, je pense qu&#8217;on vous a assez parlé de crypto, donc on va parler des ORM.</p>
<p>Ou ORMs. Je sais jamais si les acronymes s&#8217;accordent.</p>
<h2>Rappel: qu&#8217;est-ce qu&#8217;un ORM ?</h2>
<p>Si vous avez lu le titre de l&#8217;article et que votre sang n&#8217;a fait qu&#8217;un tour, vous pouvez passer tout de suite à la partie suivante, puisqu&#8217;on va commencer par les révisions.</p>
<p>Un ORM, pour <a href="https://en.wikipedia.org/wiki/Object-relational_mapping">Object-relational Mapping</a>, est une bibliothèque qui permet de décrire son modèle de données, et d&#8217;utiliser cette description pour faire le lien entre votre application et une base de données relationnelle. Dans sa forme la plus courante, l&#8217;ORM fournit les outils pour générer des requêtes SQL &#8211; sans écrire du SQL &#8211; et les exécuter, mais présente également les résultats sous forme d&#8217;objets du langage dans lequel il est écrit.</p>
<p>Par exemple, en Python, je peux faire de la base de données à la mano (sans ORM):</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> sqlite3
&nbsp;
<span style="color: #808080; font-style: italic;"># Création de la base</span>
<span style="color: #ff7700;font-weight:bold;">with</span> sqlite3.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'db.sqlite'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> conn:
&nbsp;
    <span style="color: #808080; font-style: italic;"># On se positionne sur la base</span>
    c <span style="color: #66cc66;">=</span> conn.<span style="color: black;">cursor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Créer la table</span>
    c.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'''
        CREATE TABLE product (
            name text,
            price real
        )
    '''</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Insertion de données en base</span>
    c.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;INSERT INTO product VALUES ('Pizza', 5000)&quot;</span><span style="color: black;">&#41;</span>
    c.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;INSERT INTO product VALUES ('Love', 150)&quot;</span><span style="color: black;">&#41;</span>
    c.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;INSERT INTO product VALUES ('Nessie', 3.5)&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Sauvegarde des changements</span>
    conn.<span style="color: black;">commit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Lecture de toute la base:</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> row <span style="color: #ff7700;font-weight:bold;">in</span> c.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'SELECT * FROM product'</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;">type</span><span style="color: black;">&#40;</span>row<span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">':'</span><span style="color: #66cc66;">,</span> *row<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Ce qui va me sortir:</p>
<pre>python3 db.py
<class 'tuple'> : Pizza 5000.0
<class 'tuple'> : Love 150.0
<class 'tuple'> : Nessie 3.5</pre>
<p>Et voici la même chose avec l&#8217;ORM <a href="http://docs.peewee-orm.com/en/latest/">peewee</a> (apres <code>pip install peewee</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;">import</span> peewee <span style="color: #ff7700;font-weight:bold;">as</span> pw
&nbsp;
<span style="color: #808080; font-style: italic;"># On créé la base</span>
db <span style="color: #66cc66;">=</span> pw.<span style="color: black;">SqliteDatabase</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'product2.db'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Description de la table.</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Product<span style="color: black;">&#40;</span>pw.<span style="color: black;">Model</span><span style="color: black;">&#41;</span>:
&nbsp;
    name <span style="color: #66cc66;">=</span> pw.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    price <span style="color: #66cc66;">=</span> pw.<span style="color: black;">FloatField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">class</span> Meta:
        database <span style="color: #66cc66;">=</span> db
&nbsp;
<span style="color: #808080; font-style: italic;"># Connection et création de la table</span>
db.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
db.<span style="color: black;">create_tables</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>Product<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Insertion de données en base</span>
Product.<span style="color: black;">create</span><span style="color: black;">&#40;</span>name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'Pizza'</span><span style="color: #66cc66;">,</span> price<span style="color: #66cc66;">=</span><span style="color: #ff4500;">5000</span><span style="color: black;">&#41;</span>
Product.<span style="color: black;">create</span><span style="color: black;">&#40;</span>name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'Love'</span><span style="color: #66cc66;">,</span> price<span style="color: #66cc66;">=</span><span style="color: #ff4500;">150</span><span style="color: black;">&#41;</span>
Product.<span style="color: black;">create</span><span style="color: black;">&#40;</span>name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'Nessie'</span><span style="color: #66cc66;">,</span> price<span style="color: #66cc66;">=</span><span style="color: #ff4500;">3.5</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> p <span style="color: #ff7700;font-weight:bold;">in</span> Product.<span style="color: #dc143c;">select</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: #008000;">type</span><span style="color: black;">&#40;</span>p<span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">':'</span><span style="color: #66cc66;">,</span> p.<span style="color: black;">name</span><span style="color: #66cc66;">,</span> p.<span style="color: black;">price</span><span style="color: black;">&#41;</span>
&nbsp;
db.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Ce qui sort:</p>
<pre>python3 db.py
<class '__main__.Product'> : Pizza 5000.0
<class '__main__.Product'> : Love 150.0
<class '__main__.Product'> : Nessie 3.5
</pre>
<p>A priori, c&#8217;est la même chose, mais avec un style différent. Le premier exemple favorise l&#8217;écriture du SQL à la main, fait les requêtes explicitement et récupère les résultats sous forme de tuples. Le second a une surcouche, l&#8217;ORM, qui implique que tout est décrit en Python. Le SQL est généré sous le capot, et on récupère les résultats sous forme d&#8217;objets <code>Product</code>.</p>
<p>Il existe de nombreux ORM en Python, les plus populaires étant Peewee (pour les petits besoins), <a href="http://docs.sqlalchemy.org/en/latest/orm/tutorial.html">SQLAlchemy</a> (pour les gros projets) et l&#8217;<a href="https://docs.djangoproject.com/en/2.0/topics/db/models/">ORM de Django</a> (ben, si vous utilisez Django ^^). Évidemment le concept des ORM n&#8217;est pas particulièrement lié à Python, et on en retrouve dans tous les langages, avec des variations de styles et de fonctionnalités.</p>
<h2>Que reproche-t-on aux ORM ?</h2>
<p>Avant de répondre aux détracteurs, listons d&#8217;abord leurs arguments.</p>
<ul>
<li>C&#8217;est un niveau d&#8217;indirection de plus, avec de l&#8217;implicite et de la magie.</li>
<li>L&#8217;ORM va générer des requêtes non optimisées, voire lentes.</li>
<li>SQL est un excellent DSL spécialisé dans les requêtes. Au lieu d&#8217;apprendre une API de plus, autant aller à la source.</li>
<li>SQL marche pareil d&#8217;un client à l&#8217;autre, donc la connaissance est réutilisable, contrairement à celle de son ORM.</li>
<li>C&#8217;est une béquille pour ne pas apprendre le SQL, et par ailleurs va amener tot ou tard les ignorants à se tirer une balle dans le pied.</li>
<li>Les ORMs ne peuvent pas permettre l&#8217;usage de toutes les fonctionnalités de sa base de données, et donc limitent la puissance qu&#8217;on en tire.</li>
<li>Ça ne scale pas. Les gros sites, comme Instagram qui est écrit en Django, on tous finit par virer leurs ORM.</li>
</ul>
<p>Et vous savez quoi ?</p>
<p>Ils ont raison.</p>
<h2>Heu ?</h2>
<p>Toutes ces critiques sont parfaitement justifiées.</p>
<p>Sauf qu&#8217;elles passent complètement à côté de la problématique.</p>
<p><em>Les ORM ne servent pas à éviter d&#8217;écrire du SQL.</em></p>
<p>Ça, c&#8217;est vaguement un effet de bord.</p>
<p>Ils servent à créer une API unifiée inspectable, une expérience homogène, un point d&#8217;entrée unique, un socle de référence explicite et central, pour le modèle de données.</p>
<p>Une fois qu&#8217;on a passé pas mal de temps à faire des projets, on note toujours la même chose: <a href="http://sametmax.com/les-plus-grosses-roues-du-monde/">certaines parties du logiciel sont réécrites encore et encore</a>. Si un projet commence à parler à une source de données à la main (API, base de données, crawling, fichiers, etc), tôt ou tard, quelqu&#8217;un dans l&#8217;équipe va commencer à écrire une abstraction. Celle-ci va grossir, et finir au bout de nombreux mois, pour l&#8217;accès à la base de données, à un semi ORM dégueulasse, mal testé / documenté.</p>
<p>Mais, si les requêtes SQL à la main c&#8217;est si bien, alors pourquoi ça arrive ?</p>
<p>Simplement parce que tout projet qui grandit a besoin d&#8217;une forme de gestion de la complexité. Ca passe pas avoir un point, et un seul où sont décrites à quoi ressemblent les données, leur accès, leurs garanties, leurs contraintes, et leurs validations. Ca passe aussi par permettre aux autres parties du projet d&#8217;utiliser automatiquement ces informations pour leur code métier, ainsi que la logique associée.</p>
<h2>L&#8217;exemple de Django</h2>
<p>L&#8217;ORM Django n&#8217;est pas vraiment le projet Python le plus propre. Il a plein de limitations et bizarreries, et son principal concurrent, SQLAlchemy est probablement une des meilleures libs au monde dans cette spécialité.</p>
<p>Mais !</p>
<p>Il est au coeur de ce qui a fait autant le succès colossal de Django.</p>
<p>Parce que Django est organisé autour de son ORM, il peut proposer:</p>
<ul>
<li>Des <a href="https://docs.djangoproject.com/en/2.0/topics/forms/">validateurs</a> générés automatiquement qui permettent de valider toute saisie de données, et sauvegarder les changements en base de données. Si besoin, il peuvent générer des formulaires HTML afin de proposer une saisie utilisateur automatiquement contrôlée et nettoyée, avec messages d&#8217;erreurs pre-traduits.</li>
<li><a href="https://docs.djangoproject.com/en/2.0/ref/class-based-views/generic-display/">Des vues</a> pour lire, lister, mettre à jour et supprimer les données, générées automatiquement. Y a plus qu&#8217;à mettre du HTML autour.</li>
<li><a href="https://docs.djangoproject.com/en/2.0/ref/contrib/admin/">Une admin</a> de base de données autogénérée. Un backend gratos et customisable pour votre projet.</li>
<li>Une <a href="https://docs.djangoproject.com/en/2.0/topics/http/shortcuts/">pléthore d&#8217;outils</a> pour gérer les données: <a href="https://docs.djangoproject.com/en/2.0/topics/signals/">signals</a>, getters, auto-castage en objet natifs, validation avancées, etc.</li>
<li>Des points d&#8217;entrées pour étendre la manipulation de ces données de manière générique (<a href="https://docs.djangoproject.com/en/2.0/ref/models/fields/">fields</a>, <a href="https://docs.djangoproject.com/en/2.0/topics/db/managers/">managers</a>, etc).</li>
<li>De l&#8217;<a href="https://docs.djangoproject.com/en/2.0/topics/migrations/">outillage pour les migrations</a>.</li>
<li>Un worflow d&#8217;<a href="https://docs.djangoproject.com/en/2.0/topics/auth/">authentification</a>, d&#8217;identification, de session, de cache et de permissions.</li>
<li>La normalisation automatique des valeurs: <a href="https://docs.djangoproject.com/en/2.0/ref/unicode/">encoding</a>, <a href="https://docs.djangoproject.com/en/2.0/topics/i18n/">fuseaux horaires</a>, devises, format de textes et nombres. Et les points d&#8217;entrées pour écrire les siens pour plugger ceux de quelqu&#8217;un d&#8217;autre.</li>
</ul>
<p>A cela se rajoute le fait que tous les projets Django se ressemblent. Il est très facile de passer d&#8217;une équipe à une autre, d&#8217;un projet à une autre. La formalisation du schéma devient une documentation, et la seule source de la vérité à propos des données, et pas juste celle de la base. Et qui est commité dans Git. Pour savoir ce que fait un projet Django, il suffit de regarder urls.py, settings.py et models.py, et c&#8217;est parti.</p>
<p>Mais ce n&#8217;est pas tout. L&#8217;ORM ne fait pas que définir un point central inspectable et des outils réutilisables. Il donne aussi une base commune sur laquelle tout le monde peut compter.</p>
<p>Et pour cette raison, l&#8217;écosystème Django est très, très riche en modules tierces partis qui se pluggent en 3 coups de cuillère à pot:</p>
<ul>
<li>De quoi <a href="http://www.django-rest-framework.org/">générer une API REST complète</a> à partir du modèle.</li>
<li><a href="https://djangopackages.org/grids/g/authentication/">Des dizaines de backend d&#8217;authentification.</a></li>
<li>Moult outils de manipulations de données (<a href=http://viewflow.io/>workflow</a>, <a href="https://github.com/carltongibson/django-filter">filtrage</a>, <a href="https://github.com/talpor/django-dashing">dashboard</a>, <a href="https://github.com/jcassee/django-analytical">analytics</a>, etc) qui marchent out of the box.</li>
<li>Et ces fameux bidules dont ont à tous besoin: <a href="https://github.com/alex/django-taggit/">tags</a>, <a href="https://django-haystack.readthedocs.io/en/master/">recherche</a>, <a href="https://github.com/HonzaKral/django-threadedcomments">commentaires</a>, <a href="http://django-allauth.readthedocs.io/en/latest/">registrations</a>, <a href="https://github.com/ASKBOT/askbot-devel">posts de forum</a>, <a href="https://wagtail.io/">pages de cms</a>, <a href="https://github.com/montylounge/django-mingus">articles de blog</a>, <a href='http://django-oscar.readthedocs.io/en/latest/'>fiches produits d&#8217;e-commerce</a>, <a href="https://github.com/applecat/django-simple-poll">résultats de sondages</a>&#8230;</li>
</ul>
<p>La cerise sur le gâteau ? Parce que tout ça utilise l&#8217;ORM, tout ça est compatible ensemble. Votre authentification social auth va produire un objet user qui pourra se logger, consulter un dashboard qui contiendra le résultat d&#8217;un sondage sur un produit de la boutique.</p>
<p>Et ça marche avec MySQL, Oracle, SQLite ou PosgreSQL, comme l&#8217;intégralité du framework, gratos.</p>
<p>Ce n&#8217;est pas l&#8217;apanage de Django hein, RoR fait pareil.</p>
<p>Maitenant prenez un projet NodeJS. Pour le coup, par parce que &#8220;JS ça pue&#8221; mais parce que la culture de l&#8217;ORM n&#8217;est pas très présente dans cette communauté. Non pas que ça n&#8217;existe pas, mais il n&#8217;y a pas de Django du monde du Javascript. Même les gros framework types Meteor n&#8217;ont rien d&#8217;aussi intégré.</p>
<p>Vous allez devoir réapprendre toute la mécanique de gestion de données si vous changez de projet, car ça sera fait différemment à chaque fois. Vous allez devoir former des gens.</p>
<p>Et surtout vous allez devoir réécrire tout ça.</p>
<p>Oh bien sûr, vous aurez une bibliothèque pour chaque chose, mais elle sera écrite différemment. Vous n&#8217;aurez pas d&#8217;objet User sur qui compter. Votre moyen de traduire le texte ? Pas le même. Vous utilisez Oracle mais l&#8217;auteur PostgreSQL ? Pas de bol. Vous voulez générer quelque chose à partir de votre modèle de données ? Ah, pourquoi vous croyez que facebook a créé GraphQL ! Une petite migration ? Vous avez le choix de l&#8217;embarras. Bon, maintenant vous allez gérer les dates, et 4 de vos bibliothèques les sérialisent différemment et une utilise l&#8217;heure locale au lieu d&#8217;UTC. P</p>
<p>Évidemment, on sait que votre équipe ne testera pas tout ça, et ne documentera pas tout ça. La suivante non plus.</p>
<p>Donc non, l&#8217;ORM, ce n&#8217;est pas parce que &#8220;mais heu SQL c&#8217;est dur&#8221;.</p>
<p>C&#8217;est parce que ça permet de créer un monde autour.</p>
<h2>Objection !</h2>
<p><strong>On a des abstractions qui ne sont pas des ORM&#8230;</strong></p>
<p>L&#8217;important est d&#8217;avoir un modèle central, pas un ORM. Mais les ORM font ça particulièrement bien.</p>
<p>Il existe des abstractions (ex: <a href="https://msdn.microsoft.com/en-us/library/bb308959.aspx">LINQ</a>) qui font un excellent travail pour masquer la source de données. Mais elles ne sont pas un remplacement pour un modèle introspectable central listant nature et contraintes.</p>
<p>Une bonne lib propose les deux.</p>
<p>Par exemple SQLALchemy propose un ORM, mais en vérité <a href="http://docs.sqlalchemy.org/en/latest/core/tutorial.html">l&#8217;API de base est fonctionnelle</a> et composable. Pour cette raison, on peut utiliser toutes fonctionnalités avancées de sa base de données avec SQLAlchemy car on a cette alternative à l&#8217;ORM à tout moment, et qui est compatible avec l&#8217;ORM.</p>
<p><strong>Mais les perfs !</strong></p>
<p>D&#8217;abord, on optimise pour les humains. En chemin, on optimise pour la machine. Quand ton ORM arrête de scaler, c&#8217;est un BON problème à avoir. Ca veut dire que le projet a atteint un certain succès, et qu&#8217;on peut investir dans la séparation avec l&#8217;ORM.</p>
<p>De plus, aucune technologie n&#8217;est faite pour être utilisée partout, tout le temps, pour tout le projet.</p>
<p>Google a connu ses débuts de succès en Python, et avec sa taille, a réécrit une partie en Java, C puis Go. C&#8217;est logique, on ne commence pas avec un langage bas niveau directement, c&#8217;est trop lent à écrire. Mais on ne garde pas un langage haut niveau pour tout quand ça monte dans les tours. Enfin les tours&#8230; Là on parle de centrifugeuse cosmique hein.</p>
<p>Car gardez en tête que vous n&#8217;êtes PAS Google. L&#8217;immense majorité des projets deviennent viables, rentables, puis pleins de succès, sans jamais atteindre l&#8217;échelle qui amène aux limites de l&#8217;ORM.</p>
<p>Quant à l&#8217;idée que votre stagiaire peut écrire une boucle avec une requête à chaque step&#8230; Il peut tout aussi bien écrire une requête SQL sans se protéger correctement l&#8217;injection de code. C&#8217;est con un stagiaire, faut le surveiller. C&#8217;est le principe, sinon il aurait un CDI.</p>
<p><strong>Mais les fonctionnalités !</strong></p>
<p>Les ORM bien faits n&#8217;empêchent pas d&#8217;utiliser toutes les fonctionnalités de son système. Et tous permettent d&#8217;écrire du SQL à la main si besoin. C&#8217;est comme les blocks <code>unsafe</code> de rust: on empêche pas, on isole.</p>
<p>L&#8217;idée c&#8217;est de garder ça pour le moment où on en a vraiment besoin. SQL est à la base de données ce que l&#8217;assembleur est à la machine. On n’écrit pas tout en assembleur de nos jours, ça n&#8217;est pas utile.</p>
<p>Root of all evil, tout ça.</p>
<p><strong>Mais on ne change pas de base de données souvent !</strong></p>
<p>L&#8217;argument &#8220;l&#8217;orm supporte plusieurs bases&#8221; n&#8217;est pas destiné à la migration de données d&#8217;un projet existant d&#8217;une base de données à une autre.</p>
<p>Pas. Du. Tout.</p>
<p>C&#8217;est pas que ça arrive jamais. Ça m&#8217;est déjà arrivé 2, 3 de fois.</p>
<p>Mais ce n&#8217;est pas le cas courant. Le cas courant c&#8217;est la réutilisation <em>du code</em> d&#8217;un projet précédent dans un nouveau projet utilisant une base de données différente. C&#8217;est la création d&#8217;un écosystème de modules qui ne sont pas dépendants de la base de données.</p>
<p>Si vous faites une &#8220;app&#8221; Django, vous pouvez la publier et elle sera utile pour toutes les bases de données supportées. Et c&#8217;est pour ça qu&#8217;il y autant d&#8217;outils.</p>
<p><strong>Mais on pourrait avoir un modèle central sans ORM !</strong></p>
<p>Oui, mais toutes les formes ne se valent pas.</p>
<p>Par exemple, <a href="http://www.doctrine-project.org/projects/orm.html">Doctrine</a> permet d&#8217;écrire son modèle dans un fichier YAML, et <a href="http://hibernate.org/">Hibernate</a> dans un fichier XML.</p>
<p>Au final on écrit son modèle dans un langage moins complet, moins expressif, moins facile à débugger et avec moins de tooling. On perd encore plus en faisant ça qu&#8217;en passant de SQL à un ORM, sans autant de gains.</p>
<p>En prime, on peut vouloir de la logique de validation très complexe ou des choses à faire hors validation (signals, génération dynamique de modèle, etc), et là, pouet.</p>
<p>Une alternative, ça serait de se servir d&#8217;une lib de pur modèle (ex: l&#8217;excellent <a href="https://marshmallow.readthedocs.io/en/latest/">marshmallow</a>) et de tout dériver de là. Une approche intéressante qui pourrait satisfaire tous les camps, mais que je n&#8217;ai jamais vu poussée jusqu&#8217;au bout dans aucun framework. Si vous cherchez un projet pour vos week-end :)</p>
<h2>Lib VS framework</h2>
<p>C&#8217;est un peu le vieux débat du découplage VS intégration qu&#8217;on retrouve dans la critique des ORM (ou dans vi VS vscode, POO vs fonctionnel, ta femme vs ta mère&#8230;).</p>
<p>Et comme d&#8217;habitude on retrouve toujours les meilleurs programmeurs du côté de ceux qui veulent le plus de liberté (vive SQL!) parce qu&#8217;ils ignorent complètement les problématiques qui vont plus loin que leur fichier de code. Faire fleurir un écosystème, gérer une communauté, favoriser la productivité, facilité l&#8217;intégration des membres de ses équipes&#8230; Tout ça sont des problématiques moins funs que de faire la requête parfaite avec le tout nouveau champ hyperloglog de PostGres.</p>
<p>Diffile de convaincre des gens qui sont non seulement excellents, mais qui sauront, seuls, être très productifs sans ORM. Surtout quand les gros projets qui atteignent des centaines de millions d&#8217;utilisateurs par jour finissent toujours par se séparer de leurs abstractions initiales.</p>
<p>Mais voilà, il ne faut pas perdre de vue que 2 projets sur 3 en informatiques échouent. Quasiment jamais pour des raisons techniques. Généralement la cause est humaine. Et l&#8217;ORM est là pour soutenir l&#8217;humain en créant un pivot sur lequel il peut compter, quitte à investir plus tard pour s&#8217;en passer.</p>
<p>C&#8217;est un excellent outil et une très belle réussite de l&#8217;informatique moderne. Si on sait l&#8217;aborder sans dogmatisme.</p>


feed_id: http://sametmax.com/?p=24059
title: Introduction aux extensions Python avec CFFI Recently updated !
uri: Introduction-aux-extensions-Python-avec-CFFI-Recently-updated
url: http://sametmax.com/introduction-aux-extensions-python-avec-cffi/
content:
<p style="text-align: center;"><em><small>Ceci est un post invité de Realitix posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.</small></em></p>
<p><strong>Préambule</strong></p>
<p>Vous avez réalisé une analyse de votre code et vous avez un bottleneck ?<br />
Vous souhaitez utiliser une bibliothèque bas niveau (C/C++/Rust) ?</p>
<p>Pas de problème, dans cet article, je vais vous expliquer les différentes solutions et pénétrer en profondeur dans la plus charmante d&#8217;entre elles, son petit nom: CFFI.</p>
<p>Sam&#038;Max me faisant l&#8217;honneur d&#8217;accepter mon article, je vais suivre la guideline du site avec un langage détendu et beaucoup d&#8217;exemples.</p>
<h2>Qu&#8217;est-ce qu&#8217;une extension Python ?</h2>
<p>Guido, pendant l&#8217;acte créateur, n&#8217;a pas oublié une chose importante: les extensions Python !<br />
Une extension Python est un module compilé pouvant être importé dans votre code Python.<br />
Cette fonctionnalité est très puissante: cela vous permet d&#8217;utiliser un langage bas niveau (et toutes ses capacités) pour créer un module Python.<br />
Vous utilisez très probablement des extensions Python dans vos projets sans le savoir.<br />
Par exemple, si vous souhaitez embarquer la bibliothèque de calcul physique [Bullet](https://github.com/bulletphysics/bullet3), vous pouvez le faire au sein d&#8217;une extension Python.</p>
<p>Il y a deux points à différencier:</p>
<ul>
<li>Importer une bibliothèque tierce</li>
<li>Améliorer les performances de son code</li>
</ul>
<p>En y réfléchissant bien, créer un code performant revient à créer une bibliothèque tierce et l&#8217;importer au sein de l&#8217;interpréteur.</p>
<h3>Ça laisse rêveur, alors comment fait-on ?</h3>
<p>Plusieurs solutions:</p>
<ol>
<li>L&#8217;API C de CPython. Y&#8217;en a qu&#8217;ont essayé, ils ont eu des problèmes&#8230;<br />
   En utilisant cette méthode, vous aurez accès à tout l&#8217;interpréteur Python et vous pourrez tout faire&#8230; mais à quel prix ?<br />
   Je ne vous recommande pas cette approche, je me suis cassé les dents pendant 4 mois dessus avec un succès mitigé.</li>
<li>Cython est une bonne solution mais plus orienté sur l&#8217;optimisation de code.</li>
<li>CFFI: le saint Graal, alléluia!</li>
</ol>
<h2>CFFI: Première mise en bouche</h2>
<p>CFFI va vous permettre de créer des extensions Python mais pas que&#8230;<br />
Tout comme le module <code>ctypes</code>, il va permettre d&#8217;importer une bibliothèque dynamique au runtime.<br />
Si vous ne savez pas ce qu&#8217;est une bibliothèque, c&#8217;est par <a href="https://fr.wikipedia.org/wiki/Biblioth%C3%A8que_logicielle">ici</a>.</p>
<p>CFFI va donc vous permettre:</p>
<ul>
<li>D&#8217;importer une bibliothèque dynamique au runtime comme <code>ctypes</code> mais avec une meilleure API -> Mode ABI -> Pas de compilation</li>
<li>De réaliser une extension Python compilée comme `cython` ou comme avec l&#8217;API C de CPYTHON  -> Mode API -> Phase de compilation</li>
</ul>
<p>Par rapport à <code>ctypes</code>, CFFI apporte une API pythonic et légère, l&#8217;API de <code>ctypes</code> étant lourde.<br />
Par rapport à l&#8217;API C de CPython&#8230; Ha non! Je n&#8217;en parle même pas de celle-là!</p>
<h3>J&#8217;ai dit qu&#8217;il y aurait beaucoup d&#8217;exemples, alors c&#8217;est parti !</h3>
<p>D&#8217;abord, on installe le bouzin, il y a une dépendance système avec <code>libffi</code>, sur Ubuntu:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get install</span> libffi-dev python3-dev</pre></td></tr></table></div>

<p>Sur Windows, <code>libffi</code> est embarquée dans CPython donc pas de soucis.<br />
Ensuite, on conserve les bonnes habitudes avec le classique:</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> cffi</pre></td></tr></table></div>

<p>Je vous conseille d&#8217;utiliser un <code>virtualenv</code> mais ce n&#8217;est pas le sujet!</p>
<h3>Les trois modes</h3>
<p>Il y a trois moyens d&#8217;utiliser CFFI, comprenez bien cela car c&#8217;est la partie tricky:</p>
<ol>
<li>Le mode ABI/Inline</li>
<li>Le mode API/Out-of-line</li>
<li>Le mode ABI/Out-of-line</li>
</ol>
<p>On a déjà évoqué les modes ABI et API, mais je n&#8217;ai pas encore parlé de Inline et Out-of-line.<br />
CFFI utilise une phase de &#8220;compilation&#8221; pour parser les header C. Ce n&#8217;est pas une vraie compilation mais une phase de traitement qui peut être lourde.<br />
Le mode Inline signifie que ce traitement va être effectué à l&#8217;import du module alors que Out-of-line met en cache ce traitement à l&#8217;installation du module.</p>
<p>Evidemment, le mode API/Inline ne peut pas exister puisque le mode API impose une phase de &#8220;vraie&#8221; compilation.</p>
<h4>Le mode ABI/Inline</h4>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># On commence par import le module cffi qui contient la classe de base FFI</span>
<span style="color: #ff7700;font-weight:bold;">from</span> cffi <span style="color: #ff7700;font-weight:bold;">import</span> FFI
&nbsp;
<span style="color: #808080; font-style: italic;"># 1 - On instancie l'object FFI, cet objet est la base de cffi</span>
ffi <span style="color: #66cc66;">=</span> FFI<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># 2 - On appelle la méthode cdef.</span>
<span style="color: #808080; font-style: italic;"># Cette méthode attend en paramètre un header C, c'est à dire</span>
<span style="color: #808080; font-style: italic;"># les déclarations des fonctions C qui seront utilisées par la suite.</span>
<span style="color: #808080; font-style: italic;"># CFFI ne connaîtra que ce qui a été déclaré dans le cdef.</span>
<span style="color: #808080; font-style: italic;"># La puissance de CFFI réside dans cette fonction, à partir d'un header C,</span>
<span style="color: #808080; font-style: italic;"># il va automatiquement créer un wrapper léger.</span>
<span style="color: #808080; font-style: italic;"># A noter: le code dans cdef ne doit pas contenir de directive pré-processeur.</span>
<span style="color: #808080; font-style: italic;"># Ici, on déclare la fonction printf appartenant au namespace C</span>
ffi.<span style="color: black;">cdef</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;&quot;&quot;
    int printf(const char *format, ...);
&quot;&quot;&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># 3 - On charge la bibliothèque dynamique</span>
<span style="color: #808080; font-style: italic;"># dlopen va charger la biliothèque dynamique et la stocker dans la variable nommée cvar.</span>
<span style="color: #808080; font-style: italic;"># L'argument passé est None, cela demande à cffi de charger le namespace C.</span>
<span style="color: #808080; font-style: italic;"># On peut ici spécifier un fichier .so (Linux) ou .dll (Windows).</span>
<span style="color: #808080; font-style: italic;"># Seul ce qui a été déclaré dans cdef sera accessible dans cvar.</span>
cvar <span style="color: #66cc66;">=</span> ffi.<span style="color: black;">dlopen</span><span style="color: black;">&#40;</span><span style="color: #008000;">None</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p><em>Comme vous pouvez le voir dans ce bout de code, CFFI est très simple d&#8217;utilisation, il suffit de copier le header C pour avoir accès aux fonctions de la bibliothèque.<br />
A noter: si les déclarations dans le cdef ne correspondent pas aux déclarations présentes dans la bibliothèque (au niveau ABI), vous obtiendrez une erreur de segmentation.</em></p>
<h4>Le mode API/Out-of-line</h4>
<p>Pour bien comprendre ce mode, nous allons implémenter la fonction factorielle.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Comme pour le mode ABI, FFI est la classe principale</span>
<span style="color: #ff7700;font-weight:bold;">from</span> cffi <span style="color: #ff7700;font-weight:bold;">import</span> FFI
&nbsp;
<span style="color: #808080; font-style: italic;"># Par convention, en mode API, on appelle l'instance ffibuilder car le compilateur va être appelé</span>
ffibuilder <span style="color: #66cc66;">=</span> FFI<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># En mode API, on utilise pas dlopen, mais la fonction set_source.</span>
<span style="color: #808080; font-style: italic;"># Le premier argument est le nom du fichier C à générer, le 2e est le code source.</span>
<span style="color: #808080; font-style: italic;"># Ce code source va être passé au compilateur, il peut donc contenir des directives pré-processeur.</span>
<span style="color: #808080; font-style: italic;"># Dans l'exemple, je passe directement le code source mais en général, on va plutôt ouvrir le fichier avec open().</span>
ffibuilder.<span style="color: black;">set_source</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;_exemple&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;&quot;&quot;
    long factorielle(int n) {
        long r = n;
        while(n &gt; 1) {
            n -= 1;
            r *= n;
        }
        return r;
    }
&quot;&quot;&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Comme pour le mode ABI, on déclare notre fonction avec la méthode cdef.</span>
ffibuilder.<span style="color: black;">cdef</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;&quot;&quot;
    long factorielle(int);
&quot;&quot;&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># Enfin, on va appeler la méthode compile() qui génère l'extension en 2 étapes:</span>
<span style="color: #808080; font-style: italic;"># 1 - Génération d'un fichier C contenant la magie CFFI et notre code C</span>
<span style="color: #808080; font-style: italic;"># 2 - Compilation de ce fichier C en extension Python</span>
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    ffibuilder.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>verbose<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Après éxécution du script, voici ce que l&#8217;on voit dans le terminal:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">generating ./_exemple.<span style="color: black;">c</span>  -<span style="color: #66cc66;">&gt;</span> Étape <span style="color: #ff4500;">1</span>: Génération du fichier C
the current directory <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #483d8b;">'/home/realitix/test'</span>
running build_ext
building <span style="color: #483d8b;">'_exemple'</span> extension  -<span style="color: #66cc66;">&gt;</span> Étape <span style="color: #ff4500;">2</span>: Génération de l<span style="color: #483d8b;">'extension
x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -g -fdebug-prefix-map=/build/python3.6-sXpGnM/python3.6-3.6.3=. -specs=/usr/share/dpkg/no-pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/home/realitix/venv/py36/include -I/usr/include/python3.6m -c _exemple.c -o ./_exemple.o
x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -specs=/usr/share/dpkg/no-pie-link.specs -Wl,-z,relro -Wl,-Bsymbolic-functions -specs=/usr/share/dpkg/no-pie-link.specs -Wl,-z,relro -g -fdebug-prefix-map=/build/python3.6-sXpGnM/python3.6-3.6.3=. -specs=/usr/share/dpkg/no-pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 ./_exemple.o -o ./_exemple.cpython-36m-x86_64-linux-gnu.so</span></pre></td></tr></table></div>

<p>Et vous pouvez trouver l&#8217;extension Python `_exemple.cpython-36m-x86_64-linux-gnu.so`.<br />
Étudions le module généré, dans un interpréteur 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: #ff7700;font-weight:bold;">from</span> _exemple <span style="color: #ff7700;font-weight:bold;">import</span> ffi<span style="color: #66cc66;">,</span> lib
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">dir</span><span style="color: black;">&#40;</span>ffi<span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'CData'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'CType'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'NULL'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'RTLD_DEEPBIND'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'RTLD_GLOBAL'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'RTLD_LAZY'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'RTLD_LOCAL'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'RTLD_NODELETE'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'RTLD_NOLOAD'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'RTLD_NOW'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__class__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__delattr__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__dir__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__doc__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__eq__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__format__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__ge__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__getattribute__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__gt__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__hash__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__init__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__init_subclass__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__le__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__lt__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__ne__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__new__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__reduce__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__reduce_ex__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__repr__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__setattr__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__sizeof__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__str__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__subclasshook__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'addressof'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'alignof'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'buffer'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'callback'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'cast'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'def_extern'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'dlclose'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'dlopen'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'errno'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'error'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'from_buffer'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'from_handle'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'gc'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'getctype'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'init_once'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'integer_const'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'list_types'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'memmove'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'new'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'new_allocator'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'new_handle'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'offsetof'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'sizeof'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'string'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'typeof'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'unpack'</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">dir</span><span style="color: black;">&#40;</span>lib<span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'factorielle'</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Les modules générés par CFFI contiennent 2 objets ffi et lib.</p>
<ul>
<li> ffi: Les fonctions de l&#8217;API CFFI ainsi que les typedef et structs</li>
<li> lib: Toutes nos fonctions C, ici, il n&#8217;y a que factorielle</li>
</ul>
<p><strong>Ça vous dit d&#8217;utiliser notre extension avec un petit test de performance ? Allons y !</strong></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;">time</span>
<span style="color: #ff7700;font-weight:bold;">from</span> contextlib <span style="color: #ff7700;font-weight:bold;">import</span> contextmanager
&nbsp;
<span style="color: #808080; font-style: italic;"># On import lib qui contient notre fonction factorielle</span>
<span style="color: #ff7700;font-weight:bold;">from</span> _exemple <span style="color: #ff7700;font-weight:bold;">import</span> lib
&nbsp;
<span style="color: #808080; font-style: italic;"># On créé l'équivalent de notre fonction C en Python</span>
<span style="color: #ff7700;font-weight:bold;">def</span> py_factorielle<span style="color: black;">&#40;</span>n<span style="color: black;">&#41;</span>:
    r <span style="color: #66cc66;">=</span> n
    <span style="color: #ff7700;font-weight:bold;">while</span> n <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">1</span>:
        n -<span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span>
        r *<span style="color: #66cc66;">=</span> n
    <span style="color: #ff7700;font-weight:bold;">return</span> r
&nbsp;
<span style="color: #808080; font-style: italic;"># Un petit contextmanager pour mesurer le temps</span>
<span style="color: #66cc66;">@</span>contextmanager
<span style="color: #ff7700;font-weight:bold;">def</span> mesure<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        debut <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">yield</span>
    <span style="color: #ff7700;font-weight:bold;">finally</span>:
        fin <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> - debut
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>f<span style="color: #483d8b;">'Temps écoulé: {fin}'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># On va réaliser un factorielle 25 un million de fois</span>
    loop <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1000000</span>
    rec <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">25</span>
    <span style="color: #808080; font-style: italic;"># Version Python</span>
    <span style="color: #ff7700;font-weight:bold;">with</span> mesure<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">for</span> _ <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>loop<span style="color: black;">&#41;</span>:
            r <span style="color: #66cc66;">=</span> py_factorielle<span style="color: black;">&#40;</span>rec<span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># Version CFFI</span>
    <span style="color: #ff7700;font-weight:bold;">with</span> mesure<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">for</span> _ <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>loop<span style="color: black;">&#41;</span>:
            r <span style="color: #66cc66;">=</span> lib.<span style="color: black;">factorielle</span><span style="color: black;">&#40;</span>rec<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>:
    <span style="color: #dc143c;">test</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Le résultat sur ma machine:</p>
<pre>
Temps écoulé: 1.9101519584655762
Temps écoulé: 0.13172173500061035
</pre>
<p>La version CFFI est 14 fois plus rapide, pas mal !<br />
CFFI permet de faire vraiment beaucoup de choses simplement, je ne vous ai montré que la surface afin de vous donner envie d&#8217;aller plus loin.</p>
<h2>Ou trouver des ressources</h2>
<ul>
<li>La doc de CFFI est vraiment bien, un bon readthedocs classique: <a href="https://cffi.readthedocs.io">cffi.readthedocs.io</a></li>
<li>Une de mes présentations à PyConAU, la version EuroPython est moins bonne: <a href="https://www.youtube.com/watch?v=P6qvhoQGaSk">ICI</a></li>
<li>Mes projets CFFI:
<ol>
<li>vulkan: Mode ABI <a href="https://github.com/realitix/vulkan">ICI</a></li>
<li>Pour les curieux, la version en utilisant l&#8217;API C de CPython <a href="https://github.com/realitix/cvulkan">ICI</a></li>
<li>vulk-bare: Mode API, un module très simple <a href="https://github.com/realitix/vulk-bare">ICI</a></li>
<li>PyVma: Celui-là est très intéressant, mode API qui étend le module vulkan qui en mode ABI, c&#8217;est un très bon exemple</li>
</ol>
</li>
</ul>
<p>A savoir que CFFI a été créé par Armin Rigo et Maciej Fijalkowski, les deux créateurs de Pypy.<br />
Toutes les extensions créées avec CFFI sont compatibles avec Pypy !</p>
<h2>Conclusion</h2>
<p>J&#8217;espère que cette introduction vous a plu. Si les retours sont bons, je pourrai m&#8217;atteler à un tuto plus conséquent.<br />
Vive Python !</p>
<p>Si vous avez des remarques, n&#8217;hésitez pas à me le faire savoir: @realitix sur Twitter</p>


feed_id: http://sametmax.com/?p=24161
title: Do you rotate ? Recently updated !
uri: Do-you-rotate-Recently-updated
url: http://sametmax.com/do-you-rotate/
content:
<p>L&#8217;explosion de la taille des logs a tué plus d&#8217;un serveur. Il est amusant de se dire que c&#8217;est du texte qui peut mettre à genoux un serveur de streaming vidéo avec 32 coeurs, 2To de SSD et 64 Go de RAM. Mais un bon access log non contrôlé sous nginx ou même <a href="https://forum.smartcash.cc/t/smartnode-new-start-required-and-other-issues/3105">le log de debug</a> du wallet de la coin smartcash, ça peut prendre par surprise.</p>
<p>Le module <a href="http://sametmax.com/ecrire-des-logs-en-python/">logging</a> de Python a d&#8217;excellentes options pour gérer la taille des logs, notamment le <code>RotatingFileHandler</code>.</p>
<p>Sous Linux, c&#8217;est logrotate qui fait le boulot pour le système. C&#8217;est performant, ça marche super bien, c&#8217;est hyper simple à utiliser, et c&#8217;est dispo partout.</p>
<p>Bref, en prod, un petit vi sur <code>/etc/logrotate.d/ton_projet</code> et pouf, on peut demander une rotation en 10 lignes:</p>
<pre>/var/www/ton_projet/*.log
{
    size 100K
    daily
    rotate 5
    missingok
    notifempty
}</pre>
<p>Y a rien a activer, un cron lance déjà logrotate tous les jours.</p>
<p>Par contre, si votre process utilise systemd pour démarrer, inutile de logger manuellement. Tout ce qui est sur la sortie standard est automatiquement loggué avec rotation et accessible avec un petit <code>journalctl -u ton_process.service --since today</code>.</p>
<p>Bref, attendez encore un peu avant de rajouter logstash a votre stack.</p>


feed_id: http://sametmax.com/?p=24187
title: 13558 Go de rames 7 Recently updated !
uri: 13558-Go-de-rames-7-Recently-updated
url: http://sametmax.com/13558-go-de-rames/
content:
<p>J&#8217;ai une tache celery qui me génère des données de test. Elle est lancée toutes les 5 minutes pour simuler le crawling d&#8217;un site qui popule une base de données, le tout piloté par l&#8217;ORM django, puis dumpé dans redis.</p>
<p>Jusqu&#8217;ici tout va bien.</p>
<p>Mais après un certain temps, ma machine rame, puis se frise.</p>
<p>Et j&#8217;ai du mal à y croire. J&#8217;ai 8 coeurs, un 32 Go de mémoire vive, un SSD d&#8217;un putain de To. On va pas me la faire à l&#8217;envers, c&#8217;est pas un def tout moisi qui va me faire trembler les genoux. C&#8217;est forcément un de ces cons de wallets que j&#8217;ai laissé ouvert, encore codé par un nantais ça !</p>
<p>Mais après une enquête minutieuse, qui a consisté en subtilement killer tout mes processus un par un avec <code>echo "douceur" | sed s/c/l</code>, le constat est là. </p>
<div id="attachment_24189" style="width: 562px" class="wp-caption aligncenter"><a href="media/e357a381.O88afud.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2018/03/O88afud.jpg" class="grouped_elements" rel="tc-fancybox-group24187"><img src="media/e357a381.O88afud.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2018/03/O88afud.jpg" alt="Eukekaca" width="552" height="459" class="size-full wp-image-24189" /></a><p class="wp-caption-text">Eukekaca.</p></div>
<p>Cette fonction est responsable:</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> generate_fake_stats<span style="color: black;">&#40;</span>x<span style="color: #66cc66;">=</span><span style="color: #ff4500;">1000</span><span style="color: black;">&#41;</span>:
&nbsp;
    cur_stats <span style="color: #66cc66;">=</span> <span style="color: black;">&#123;</span>
        s.<span style="color: black;">currency</span>.<span style="color: black;">short_code</span>: s
        <span style="color: #ff7700;font-weight:bold;">for</span> s <span style="color: #ff7700;font-weight:bold;">in</span> CurrencyMarketStatsFactory.<span style="color: black;">build_batch</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
    <span style="color: black;">&#125;</span>
&nbsp;
    mn_stats: Dict<span style="color: black;">&#91;</span><span style="color: #008000;">str</span><span style="color: #66cc66;">,</span> MNMarketStats<span style="color: black;">&#93;</span> <span style="color: #66cc66;">=</span> <span style="color: black;">&#123;</span>
        s.<span style="color: black;">masternode</span>.<span style="color: black;">coin</span>.<span style="color: black;">short_code</span>: s
        <span style="color: #ff7700;font-weight:bold;">for</span> s <span style="color: #ff7700;font-weight:bold;">in</span> MNMarketStatsFactory.<span style="color: black;">build_batch</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
    <span style="color: black;">&#125;</span>
&nbsp;
    stats <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">for</span> <span style="color: #dc143c;">code</span><span style="color: #66cc66;">,</span> mns <span style="color: #ff7700;font-weight:bold;">in</span> mn_stats.<span style="color: black;">items</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
        cstats: CurrencyMarketStats <span style="color: #66cc66;">=</span> cur_stats.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">code</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> cstats:
            <span style="color: #ff7700;font-weight:bold;">continue</span>
&nbsp;
        dollar_value <span style="color: #66cc66;">=</span> <span style="color: #008000;">float</span><span style="color: black;">&#40;</span>cstats.<span style="color: black;">dollar_value</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span>
        collateral <span style="color: #66cc66;">=</span> mns.<span style="color: black;">masternode</span>.<span style="color: black;">collateral</span>
&nbsp;
        stats <span style="color: #66cc66;">=</span> <span style="color: black;">&#123;</span>
            <span style="color: #483d8b;">'created'</span>: <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>mns.<span style="color: black;">created</span>.<span style="color: black;">timestamp</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span>
            <span style="color: #483d8b;">'name'</span>: cstats.<span style="color: black;">currency</span>.<span style="color: black;">name</span><span style="color: #66cc66;">,</span>
            <span style="color: #483d8b;">'code'</span>: <span style="color: #dc143c;">code</span><span style="color: #66cc66;">,</span>
            <span style="color: #483d8b;">'title'</span>: f<span style="color: #483d8b;">'{cstats.currency.name} ({code})'</span><span style="color: #66cc66;">,</span>
            <span style="color: #483d8b;">'marketcap'</span>: dollar_value * cstats.<span style="color: black;">supply</span><span style="color: #66cc66;">,</span>
            <span style="color: #483d8b;">'dollar_value'</span>: dollar_value<span style="color: #66cc66;">,</span>
            <span style="color: #483d8b;">'change_rate'</span>: cstats.<span style="color: black;">change_rate</span><span style="color: #66cc66;">,</span>
            <span style="color: #483d8b;">'volume'</span>: <span style="color: #008000;">float</span><span style="color: black;">&#40;</span>cstats.<span style="color: black;">volume</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span>
            <span style="color: #483d8b;">'supply'</span>: cstats.<span style="color: black;">supply</span><span style="color: #66cc66;">,</span>
            <span style="color: #483d8b;">'roi'</span>: mns.<span style="color: black;">roi</span><span style="color: #66cc66;">,</span>
            <span style="color: #483d8b;">'mn_worth'</span>: collateral * dollar_value<span style="color: #66cc66;">,</span>
            <span style="color: #483d8b;">'node_count'</span>: mns.<span style="color: black;">node_count</span><span style="color: #66cc66;">,</span>
            <span style="color: #483d8b;">'required_coins'</span>: collateral<span style="color: #66cc66;">,</span>
        <span style="color: black;">&#125;</span>
&nbsp;
    RedisClient.<span style="color: black;">get_instance</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">jset</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'marketstats'</span><span style="color: #66cc66;">,</span> stats<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> stats</pre></td></tr></table></div>

<p>Il m&#8217;a fallu une bonne heure pour trouver ma connerie. J&#8217;ai changé plein d&#8217;options, mis DEBUG sur False, limité la mémoire de Redis, etc.</p>
<p>Mais non, c&#8217;était mon code. Qui générait au bas mot 847390982*1000*16 octets de données, soit 1,355825571×10¹³ pour mes objets Python. </p>
<div id="attachment_24191" style="width: 560px" class="wp-caption aligncenter"><a href="media/e38508bb.iDr73ez.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2018/03/iDr73ez.jpg" class="grouped_elements" rel="tc-fancybox-group24187"><img src="media/e38508bb.iDr73ez.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2018/03/iDr73ez.jpg" alt="J&#039;ai un nouveau mapping clavier qui permet de n&#039;utiliser qu&#039;un doigt" width="550" height="970" class="size-full wp-image-24191" /></a><p class="wp-caption-text">J&#8217;ai un nouveau mapping clavier qui permet de n&#8217;utiliser qu&#8217;un doigt</p></div>
<p>Il y en a un peu plus madame, je vous le mets quand même ?</p>
<p>Nan parce que 13 To pour une pov liste de dicos, c&#8217;est la boucherie.</p>
<p>Alors, sachant que je vous ai éliminé la recherche des causes parallèles et que vous savez que le bug est de ma (grande et stupide) faute, saurez-vous trouver dans ces lignes le d20 qui tombe sur un 1 à tous les jets ?</p>
<p>Si vous ne trouvez pas, la réponse dans quelques jours.</p>
<div id="attachment_24190" style="width: 510px" class="wp-caption aligncenter"><a href="media/80181193.AOPXWnu.gif" data-original-source="http://sametmax.com/wp-content/uploads/2018/03/AOPXWnu.gif" class="grouped_elements" rel="tc-fancybox-group24187"><img src="media/80181193.AOPXWnu.gif" data-original-source="http://sametmax.com/wp-content/uploads/2018/03/AOPXWnu.gif" alt="Explain all the humans !" width="500" height="288" class="size-full wp-image-24190" /></a><p class="wp-caption-text">Explain all the humans !</p></div>


feed_id: http://sametmax.com/?p=24323
title: Trier un CSV de 5 Go
uri: Trier-un-CSV-de-5-Go
url: http://sametmax.com/trier-un-csv-de-5-go/
content:
<p>Marrant, j&#8217;ai jamais eu autant de RAM, et j&#8217;ai jamais eu autant de problèmes de RAM. On est en train de faire un bon dans inefficacité des programmes, et ça va pas aller en s&#8217;arrangeant entre docker, electron et nos chers navigateurs. Une grosse app Python peut devenir assez velue aussi niveau mémoire, même quand on est pas <a href="http://sametmax.com/13558-go-de-rames/">un boulet</a> comme moi.</p>
<p>Et justement, en relisant <a href="http://neopythonic.blogspot.fr/2008/10/sorting-million-32-bit-integers-in-2mb.html">un célèbre post de Guido</a> sur la réponse à la blague &#8220;comment trier un million d&#8217;entiers avec 2M de Ram&#8221;, j&#8217;ai réalisé 2 choses:</p>
<ul>
<li>Le contenu de l&#8217;article est génial.</li>
<li>Le contenu de l&#8217;article est incompréhensible.</li>
</ul>
<p>Or c&#8217;est un peu ma raison d&#8217;être, si vous voulez, de prendre les trucs cools mais imbitables et les rendre utilisables.</p>
<p>Aujourd&#8217;hui, donc, on va trier un CSV de 5Go en Python. Ça parle plus qu&#8217;un fichier de nombres, et puis ça évite d&#8217;expliquer le module <code>array</code> qui est juste une optimisation.</p>
<p>J&#8217;ai pris mes petites mimines, et j&#8217;ai pondu un CSV qui contient 63Mo de:</p>
<pre>A,01/02/2016,2
A,13/07/2011,1
B,24/01/1996,3
C,30/12/1999,1
D,13/07/2011,3
D,01/02/2016,5
E,24/01/1996,4
F,30/12/1999,1
G,13/07/2011,4
H,01/02/2016,4
I,01/02/2016,5
I,13/07/2011,2
A,01/02/2016,2
A,13/07/2011,1</pre>
<p>En copier/coller.</p>
<p>Puis j&#8217;ai lancé un script pour dupliquer le bébé et jusqu&#8217;à atteindre 5,9 Go de taille:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'data.csv'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> infile:
    <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;">'data2.csv'</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> outfile:
        <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;">100</span><span style="color: black;">&#41;</span>:
            outfile.<span style="color: black;">write</span><span style="color: black;">&#40;</span>i.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            infile.<span style="color: black;">seek</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<div id="attachment_24327" style="width: 490px" class="wp-caption aligncenter"><a href="media/83cdb381.V3btCPt.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2018/05/V3btCPt.jpg" class="grouped_elements" rel="tc-fancybox-group24323"><img src="media/83cdb381.V3btCPt.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2018/05/V3btCPt.jpg" alt="Si jamais vous doutiez que je vous aime..." width="480" height="360" class="size-full wp-image-24327" /></a><p class="wp-caption-text">Si jamais vous doutiez que je vous aime&#8230;</p></div>
<p>395366400 lignes. Jusqu&#8217;ici tout va bien.</p>
<p>Maintenant, supposons qu&#8217;on veuille trier sur la date. Si vos souvenirs en Python sont exacts (ou si vous avez lu notre super article sur <a href="http://sametmax.com/ordonner-en-python/">Ordonner en Python</a>), vous savez que la solution naïve est de loader le fichier cash pistache, puis d&#8217;appeler dessus <code>sorted()</code> avec le paramètre <code>key</code>.</p>
<p>D&#8217;abord, il faut choisir le callback à passer à <code>key</code>, c&#8217;est à dire la fonction qui va être exécutée pour chaque ligne pour extraire la date de la ligne et permettre ainsi à <code>sorted()</code> de comparer avec les autres dates.</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> str_date <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;A,01/02/2016,2&quot;</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">','</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: #808080; font-style: italic;"># récupère la date uniquement</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> str_date
<span style="color: #483d8b;">'01/02/2016'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>str_date.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/'</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;">&#41;</span> <span style="color: #808080; font-style: italic;"># on inverse la date avoir une valeur ordonnable</span>
<span style="color: #483d8b;">'20160201'</span>
&nbsp;
On en fait une fonction:
&nbsp;
<span style="color: #66cc66;">&lt;</span>pre lang<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;python&quot;</span><span style="color: #66cc66;">&gt;</span> 
<span style="color: #ff7700;font-weight:bold;">def</span> extract_date<span style="color: black;">&#40;</span>ligne<span style="color: black;">&#41;</span>:
    str_date <span style="color: #66cc66;">=</span> ligne.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">','</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: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>str_date.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/'</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;">&#41;</span></pre></td></tr></table></div>

<p>Ensuite on a juste à ouvrir le fichier, trier les lignes, et sauvegarder tout ça dans l&#8217;autre fichier:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'data2.csv'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> infile:
    <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;">'sorted_data.csv'</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> outfile:
        <span style="color: #808080; font-style: italic;"># on fait le tri</span>
        sorted_lines <span style="color: #66cc66;">=</span> <span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span>infile<span style="color: #66cc66;">,</span> key<span style="color: #66cc66;">=</span>extract_date<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># on ecrit les lignes triées dans le nouveau fichier</span>
        outfile.<span style="color: black;">writelines</span><span style="color: black;">&#40;</span>sorted_lines<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Easy money, double poney.</p>
<p>Enfin avec un fichier de quelques Mo. Parce que si vous faites ça dans un fichier de 5,9 Go, votre RAM va vomir comme une pom pom girl anorexique.</p>
<div id="attachment_24325" style="width: 824px" class="wp-caption aligncenter"><a href="media/3abb5bad.cfCXCHK.png" data-original-source="http://sametmax.com/wp-content/uploads/2018/05/cfCXCHK.png" class="grouped_elements" rel="tc-fancybox-group24323"><img src="media/3abb5bad.cfCXCHK.png" data-original-source="http://sametmax.com/wp-content/uploads/2018/05/cfCXCHK.png" alt="sorted() sur un disque complet, illustré" width="814" height="390" class="size-full wp-image-24325" /></a><p class="wp-caption-text">sorted() sur un disque complet, illustré</p></div>
<p>Comment résoudre ce problème ?</p>
<p>Et bien en faisant tout pareil, mais avec des petits morceaux !</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;">heapq</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">tempfile</span> <span style="color: #ff7700;font-weight:bold;">import</span> TemporaryFile
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">itertools</span> <span style="color: #ff7700;font-weight:bold;">import</span> islice
&nbsp;
<span style="color: #808080; font-style: italic;"># On garde notre fonction key</span>
<span style="color: #ff7700;font-weight:bold;">def</span> extract_date<span style="color: black;">&#40;</span>ligne<span style="color: black;">&#41;</span>:
    str_date <span style="color: #66cc66;">=</span> ligne.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">','</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: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>str_date.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/'</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;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Liste de tous les fichiers temporaires avec les lignes triées</span>
sorted_temp_files <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: black;">&#93;</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;">'data2.csv'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> infile:
    progress <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">0</span>
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
        <span style="color: #808080; font-style: italic;"># On lit seulement 3000000 lignes sur 395366400 à chaque tour de boucle</span>
        lines <span style="color: #66cc66;">=</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>islice<span style="color: black;">&#40;</span>infile<span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3000000</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> lines:  <span style="color: #808080; font-style: italic;"># plus de ligne ? On sort</span>
            <span style="color: #ff7700;font-weight:bold;">break</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># On affiche où on en est</span>
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;{:.2f}%&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>progress<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        progress +<span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #ff4500;">3000000</span> / <span style="color: #ff4500;">395366400</span> * <span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># On tri les lignes, comme avec sorted() mais sur place. </span>
        <span style="color: #808080; font-style: italic;"># Ça évite de dupliquer les données en mémoire.</span>
        lines.<span style="color: black;">sort</span><span style="color: black;">&#40;</span>key<span style="color: #66cc66;">=</span>extract_date<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># On crée un fichier temporaire qui va contenir les 3000000 lignes</span>
        <span style="color: #808080; font-style: italic;"># triées</span>
        f <span style="color: #66cc66;">=</span> TemporaryFile<span style="color: black;">&#40;</span>mode<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;r+&quot;</span><span style="color: black;">&#41;</span>
        f.<span style="color: black;">writelines</span><span style="color: black;">&#40;</span>lines<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># On rembobine le fichier pour pouvoir relire le contenu plus tard</span>
        f.<span style="color: black;">seek</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># On balance le fichier dans la liste des fichiers triés</span>
        <span style="color: #808080; font-style: italic;"># L'objet fichier hein. Pas le chemin du fichier. C'est pour ça qu'on</span>
        <span style="color: #808080; font-style: italic;"># a fait .seek(0) avant. On va en avoir besoin plus bas.</span>
        sorted_temp_files.<span style="color: black;">append</span><span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Toute la magie se fait là.</span>
    <span style="color: #808080; font-style: italic;"># On utilise heapq.merge(), qui prend en paramètre plein de trucs qu'on </span>
    <span style="color: #808080; font-style: italic;"># vient de trier, et permet de se balader dedans comme si c'était un seul</span>
    <span style="color: #808080; font-style: italic;"># gros truc trié, mais sans tout charger en mémoire.</span>
    <span style="color: #808080; font-style: italic;"># En gros il regarde les premières valeurs de tous les itérables, les compares,</span>
    <span style="color: #808080; font-style: italic;"># puis fait retourne un générateur qui yield tout dans l'ordre </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;">'sorted_data.csv'</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> outfile:
        <span style="color: #ff7700;font-weight:bold;">for</span> ligne <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">heapq</span>.<span style="color: black;">merge</span><span style="color: black;">&#40;</span>*sorted_temp_files<span style="color: #66cc66;">,</span> key<span style="color: #66cc66;">=</span>extract_date<span style="color: black;">&#41;</span>:
            outfile.<span style="color: black;">write</span><span style="color: black;">&#40;</span>ligne<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Au lieu de charger les 5 Go en mémoire, on plafonne à 400 Mo. Une raison de plus d&#8217;<a href="http://sametmax.com/comment-utiliser-yield-et-les-generateurs-en-python/">apprendre à utiliser les générateurs.</a></p>
<div id="attachment_24326" style="width: 590px" class="wp-caption aligncenter"><a href="media/a25140fd.kPXVXqx.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2018/05/kPXVXqx.jpg" class="grouped_elements" rel="tc-fancybox-group24323"><img src="media/a25140fd.kPXVXqx.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2018/05/kPXVXqx.jpg" alt="Sametmax, c&#039;est de la bombe" width="580" height="326" class="size-full wp-image-24326" /></a><p class="wp-caption-text">Sametmax, c&#8217;est de la bombe</p></div>
<p>Alors évidemment, c&#8217;est long. Y a genre 40 minutes de traitement. Moins si on utilise pypy et qu&#8217;on accepte de up la conso RAM. On code pas en Rust :)</p>
<p>Si vous avez besoin de perfs et que Python reste votre outil de prédilections, 3 solutions restent à votre disposition:</p>
<p>&#8211; Prétraiter le fichier en lui rajoutant une première colonne qui contient un timestamp. Ca c&#8217;est super rapide à trier.<br />
&#8211; Utiliser un truc de numpy ou pandas comme np.memmap().sort(kind=&#8217;merge&#8217;). C&#8217;est du C, donc ça speed.<br />
&#8211; <a href="https://www.chrisstucchio.com/blog/2013/hadoop_hatred.html">Acheter de la ram et tout trier en mémoire</a> avec la solution 1.</p>


feed_id: http://sametmax.com/?p=24447
title: Je fais mon coming out 5 Recently updated !
uri: Je-fais-mon-coming-out-5-Recently-updated
url: http://sametmax.com/je-fais-mon-coming-out/
content:
<p>J&#8217;utilise <a href="https://code.visualstudio.com/download">VSCode</a></p>
<p>J&#8217;ai vraiment du mal à m&#8217;en remettre, et j&#8217;ai des proches qui utilisent Vim et ne sont pas toujours encore à l&#8217;aise avec l&#8217;idée. J&#8217;ai refusé d&#8217;utiliser Visual Studio à de nombreuses reprises, alors tester son petit frère était déjà un pas osé. Un truc Microsoft. Un truc écrit en Javascript.</p>
<p>Mais bon, j&#8217;aime ça, et il faut pas avoir honte de qui on est.</p>
<p>Le fait que ce soit libre et multiplateform pour un produit Microsoft est surprenant, néanmoins c&#8217;est le maintien continu de l&#8217;excellent comportement de la team derrière qui est le plus bluffant: respectueux, proche des utilisateurs, sans bullshit&#8230;</p>
<p>Le fait que ce soit facile à installer et utiliser pour un projet javascript est surprenant, néanmoins c&#8217;est l&#8217;excellente performance du produit qui est le plus bluffant: temps démarrage, réactivité du scroll, gestion de gros projets&#8230;</p>
<p>Alors j&#8217;ai continué à le garder sous le coude, en parallèle à Sublime Text.</p>
<p>Et quelque chose de subtil a changé, chaque jour, sublime dont j&#8217;ai pourtant payé la licence, me faisait de moins en moins bander. Je sollicitais de plus en plus VSCode. Jusqu&#8217;à ce que ça devienne mon éditeur par défaut.</p>
<p>Oh, ST et moi on se voit toujours. Pour ouvrir un petit fichier vite fait, taper un article, tester un truc.</p>
<p>En revanche dès que c&#8217;est un projet, j&#8217;ai un éditeur Electron made in Redmond pour ça, et il me rend heureux.</p>
<h2>L&#8217;ergonomie de la bestiole</h2>
<p>Les auteurs de VSCode ont pompé tous les éditeurs les plus populaires, goulûment. Ils ont optimisé le temps de démarrage à mort, et même si on n&#8217;a pas la vitesse d&#8217;un ST ou d&#8217;un Vim, ça reste moult fois plus rapide que la vaste majorité de la concurrence. Pas de splash screen à rallonge et ce moment de doute où on n&#8217;est pas sur d&#8217;avoir vraiment cliqué sur le bouton. J&#8217;aime bien Jetbrain mais le startup de PyCharm me fout les boules à chaque fois.</p>
<p>Côté apparence, on retrouve des lignes épurées avec peu de boutons, des tabs, la fameuse <a href="https://www.youtube.com/watch?v=BteWRBLDbfo">bird view du code</a> de ST, un <a href="https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette">Head Up Display</a>, une statut-bar très riche et le &#8220;<a href="https://www.youtube.com/watch?v=BpSbKmZkKFQ">go to anywhere</a>&#8221; que tout le monde adore depuis Mate.</p>
<p>La force de VSCode c&#8217;est l&#8217;expérience de son équipe : ils ont bien compris ce que les utilisateurs faisaient le plus souvent, et l&#8217;ont mis à porter de main. Un clic pour faire un split view ou afficher le terminal intégré. Mais pas de fonction &#8220;Imprimer&#8221;. Une barre latérale donne l&#8217;accès à 4 autres modes, un pour la recherche dans tout le projet, un pour git (et rien d&#8217;autre), un pour le debuggeur intégré, et un pour installer des extensions.</p>
<p>Une foule de choses sont configurables, avec une interface qui mélange fichiers de config et aide à la saisie. C&#8217;est étrange la première fois qu&#8217;on met le nez dans &#8220;paramètres de l&#8217;utilisateur&#8221; ou &#8220;ouvrir les raccourcis clavier&#8221;. Ni vraiment une fenêtre avec des formulaires. Ni vraiment un JSON à éditer à la main. Un peu des deux. Et c&#8217;est super bien fait.</p>
<p>Ceci dit, comme les réglages par défaut sont assez sains, un junior n&#8217;aura pas à s&#8217;en soucier et pourra tout de suite commencer à introduire des bugs dans votre projet.</p>
<h2>L&#8217;éditeur</h2>
<p>Aucune innovation. Aucune tentative de faire différent de la concurrence. C&#8217;est du classique, c&#8217;est propre, et ça marche. On peut bien entendu choisir entre plusieurs mode de saisie (mode VI, Emarcs, Sublime, etc), mais perso je reste avec le mode original et quelques raccourcis custo.</p>
<p>Derrière, toutes les fonctionnalités modernes sont là: <a href="https://code.visualstudio.com/docs/getstarted/tips-and-tricks#_multi-cursor-selection">multi-curseur</a>, <a href="https://stackoverflow.com/questions/29953479/multiple-cursors-in-visual-studio-code">sélection</a>/recherche incrémentale, <a href="https://code.visualstudio.com/docs/languages/python#_snippets">snippets</a> (<a href="https://code.visualstudio.com/docs/editor/emmet">emmet</a> inclus !), complétion des mots les plus utilisés, navigation par symbole, <a ref="https://www.infoq.com/news/2016/12/visualstudiocode-18-released">hot exit</a>. L&#8217;avantage, c&#8217;est que comme VSCode joue la carte de l&#8217;interface minimaliste, on n&#8217;a pas besoin de connaitre tout ça, et on peut juste commencer à taper, tout en apprenant chaque feature au fur et à mesure de ses progrès. C&#8217;est un excellent éditeur pour débutant en ce sens. Mais les powers users qui aiment malgré tout la souris et les onglets y trouveront leur compte.</p>
<p>La coloration syntaxique est irréprochable (heureusement), mais on voit qu&#8217;ils ont du faire des concessions. Par exemple au démarrage, seule la partie de votre viewport est colorée. Il faut attendre une à deux secondes sur les gros projets pour que le reste du fichier le soit, histoire de pas freezer tout le bouzin.</p>
<p>Le bon côté de ça c&#8217;est que c&#8217;est très fluide. Bon évidemment j&#8217;ai 8 coeurs et 32Go de RAM. J&#8217;ai tenté l&#8217;aventure sur une VM avec 2 de rames et un tout petit coeur, et c&#8217;est pénible. Au repos avec quelques tabs ouverts, le truc s&#8217;engouffre quand même ses 700Mo de mémoire vive. N&#8217;oubliez pas que c&#8217;est du V8 derrière.</p>
<p>En comparaison ST en bouffe 300, et Vim, heu, LOL.</p>
<h2>Intégration Git</h2>
<p>L&#8217;intelligence de cette feature, c&#8217;est qu&#8217;ils se sont limités aux opérations simples et courantes. Permettre de naviguer dans l&#8217;espace temps ou de lancer son <code>merge --rebase</code>, c&#8217;est dur à faire correctement. Donc VSCode n&#8217;essaye pas.</p>
<p>Il affiche juste la liste des fichiers qui sont modifiés et/ou en staging, permet de les bouger de l&#8217;un à l&#8217;autre ou annuler les modifications, et de faire un commit rapidement. Un clic sur un fichier l&#8217;ouvre en mode diff avec HEAD. C&#8217;est tout.</p>
<p>C&#8217;est pas 1% de ce que permet de faire Git.</p>
<p>Mais c&#8217;est facilement 69% de mon usage de Git. Du coup c&#8217;est super pratique. Combiné avec le terminal intégré, et vous pouvez gérer presque tout le repo sans sortir de l&#8217;éditeur.</p>
<h2>Le debuggeur</h2>
<p>Je ne l&#8217;utilise jamais et je préfère <a href="http://sametmax.com/debugger-en-python-les-bases-de-pdb/">ipdb</a>. Pour le moment, en Python, il est trop lent. Les devs JS en disent du bien, vu qu&#8217;apparemment il est capable de se connecter directement au navigateur et comprend TypeScript de manière transparente.</p>
<h2>La recherche</h2>
<p>Rien à dire. C&#8217;est rapide. Ça marche. Ça supporte les trucs les plus importants: case insensitive (activé par défaut), regex, in sélection, dans tous les fichiers, filtrés par extension, et tout le bordel. Cliquer sur le résultat ouvre le fichier à la bonne ligne. Pas de modale qui bloque l&#8217;UI.</p>
<p>Pas de surprise, donc. Mais pas de mauvaises surprises.</p>
<p>L&#8217;indexage est configurable par projet, ce qui est indispensable dès que vous avez quelque chose d&#8217;un peu complexe.</p>
<p>La recherche de fichiers par nom est absente puisque ferait doublons avec &#8220;Go To Anywhere&#8221;.</p>
<h2>Intégration des langages</h2>
<p>Là, on attaque la partie intéressante. VSCode est neutre dans son traitement des langages, et toutes les features avancées se font donc via des extensions. L&#8217;astuce, c&#8217;est que l&#8217;équipe supporte officiellement certaines extensions, et elles sont donc d&#8217;excellente qualité.</p>
<p>Le support de Python est phénoménal. C&#8217;est simplement le meilleur après celui de PyCharm (et de pas beaucoup), ce qui n&#8217;est pas peu dire, vu que Jetbrain fait probablement des messes noires et des sacrifices à Quetzalcoatl pour obtenir ce résultat.</p>
<p>Python est notoirement difficile à outiller de par son très grand dynamisme.</p>
<p>Mais là, c&#8217;est beau.</p>
<p>Pylint est activé par défaut, et flake8 ainsi que mypy sont optionnellement activables. Leurs préréglages sont de bonne qualité, particulièrement celui de mypy qui est normalement inutilisable out of the box. L&#8217;éditeur vous prompte pour l&#8217;installation quand il détecte qu&#8217;ils sont absents, et lance tout ça pour vous.</p>
<p>Tout est configurable par projet, et donc si vous spécifiez un virtualenv pour votre projet (ce qui vous devriez toujours faire), VSCode va détecter que les outils ne sont pas dedans, vous proposer de les installer, et le faire pour vous.</p>
<p>Du coup, bénéficier des types hints, de la détection des erreurs de syntaxes, des variables non déclarées et des imports manquants ou inutiles est beaucoup plus facile que sur n&#8217;importe quel compétiteur. Ok, sauf PyCharm. Mais personnellement je l&#8217;appelle PyChiderme.</p>
<p>Si VSCode ne supporte pas nativement un outil, il existe probablement une extension pour ça. Par exemple, il y a une extension pour <a href="https://github.com/ambv/black">black</a>, qui est a Python ce que <a href="https://golang.org/cmd/gofmt/">Gofmt</a> est à Go, et que j&#8217;installe donc maintenant à chaque nouveau projet.</p>
<p>L&#8217;intégration de ces outils est excellente :</p>
<ul>
<li>Les linters de Python sont naturellement lents, mais VSCode les lance en asynchrone et ça ne ralentit pas son UI.</li>
<li>L&#8217;affichage des erreurs est claire, mais discret. Ça limite l&#8217;effet sapin de noel.</li>
<li>à côté du terminal intégré existe une fenêtre qui liste toutes les erreurs par fichier. On peut ainsi parcourir son projet erreur par erreur.</li>
</ul>
<p>VScode m&#8217;a même surpris à détecter mes tests unitaires, m&#8217;a proposé d&#8217;installer <a href="http://sametmax.com/un-gros-guide-bien-gras-sur-les-tests-unitaires-en-python-partie-3/">pytest</a> puis de lancer tout ça.</p>
<p>Cependant, pour vraiment parler de l&#8217;intégration de Python dans VSCode, il me faut mentionner IntelliSense. C&#8217;est un terme marketing inventé par MS pour caractériser toutes les fonctionnalités autour de la compréhension que l&#8217;éditeur à du code, et des opérations qu&#8217;il propose dessus.</p>
<p>Ok, ok, c&#8217;est un mot 100% bullshit.</p>
<p>Mais bordel, ça marche.</p>
<p>La complétion du code est excellente, et marche sans aucun réglage. Avec la lib standard bien entendu, mais aussi avec votre code, et toutes les libs installées dans votre virtualenv (si vous avez précisé le chemin vers ledit env dans les settings du projet, of course, il est pas devin).</p>
<p>VSCode affiche les docstrings, les params et propose d&#8217;aller à la définition de n&#8217;importe quoi en un clic.</p>
<p>Et si comme moi vous avez passé un temps fou à essayer d&#8217;obtenir le même résultat sous ST/Vim/Whatever en chargeant what mille plugins et en changeant 600 valeurs de configs, vous comprendrez que c&#8217;est juste, topissime.</p>
<h2>Quelques infos</h2>
<p>Les réglages de VSCode de base sont bons. C&#8217;est vraiment une partie de ce qui fait la force du projet: moins de bordel à faire soi-même. Mais comme il est bien configurable, il ne faut pas s&#8217;en priver. Quelques trucs que je fais toujours:</p>
<h3>Installer une police avec des ligatures</h3>
<p>Genre <a href="https://github.com/tonsky/FiraCode">Fira-Code</a>.</p>
<p>Et activer les settings:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;">    <span style="color: #3366CC;">&quot;editor.fontFamily&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;'Fira Code', 'Droid Sans Mono', 'Courier New', monospace, 'Droid Sans Fallback'&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;editor.fontLigatures&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span></pre></td></tr></table></div>

<h3>Exclure plein de fichiers</h3>
<p>J&#8217;ai pas du tout envie que &#8220;Go to anywhere&#8221;, la recherche des fichiers ou l&#8217;indexage git charge des trucs inutiles. Donc j&#8217;ai des settings de base de nazi:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;">    <span style="color: #3366CC;">&quot;files.exclude&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #3366CC;">&quot;**/.git&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/.svn&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/.hg&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/.DS_Store&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/dist&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/build&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/env/**&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/venv/**&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/virtualenv/**&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/node_modules&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/bower_components&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/vendors&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/__pycache__&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/**/*.pyc&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;files.watcherExclude&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #3366CC;">&quot;**/.git/objects/**&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/node_modules/**&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/build/**&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/dist/**&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/env/**&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/venv/**&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/virtualenv/**&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/bower_components/**&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/vendors/**&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/__pycache__&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;**/**/*.pyc&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span></pre></td></tr></table></div>

<p>Mes settings par projet sont généralement encore plus restrictifs.</p>
<h3>Je change les params de zoom</h3>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;"> <span style="color: #3366CC;">&quot;window.zoomLevel&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">2</span><span style="color: #339933;">,</span>
 <span style="color: #3366CC;">&quot;editor.mouseWheelZoom&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
 <span style="color: #3366CC;">&quot;editor.fontSize&quot;</span><span style="color: #339933;">:</span> <span style="color: #CC0000;">10</span><span style="color: #339933;">,</span></pre></td></tr></table></div>

<h3>Je vire la télémétrie</h3>
<p>Je suis pas sous Windows 10, merde.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;">    <span style="color: #3366CC;">&quot;telemetry.enableCrashReporter&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;telemetry.enableTelemetry&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">,</span></pre></td></tr></table></div>

<h3>Je mets des barres verticales</h3>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;">    <span style="color: #3366CC;">&quot;editor.rulers&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span>
        <span style="color: #CC0000;">79</span><span style="color: #339933;">,</span> # PEP8
        <span style="color: #CC0000;">88</span><span style="color: #339933;">,</span> # Black
        <span style="color: #CC0000;">120</span> # Javascript
    <span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span></pre></td></tr></table></div>

<h3>Ergonomie perso</h3>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;">    <span style="color: #3366CC;">&quot;editor.renderWhitespace&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;none&quot;</span><span style="color: #339933;">,</span> # overridé par projet
    <span style="color: #3366CC;">&quot;editor.renderIndentGuides&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;editor.minimap.enabled&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;editor.minimap.renderCharacters&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;editor.autoIndent&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;window.restoreWindows&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;all&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;window.openFoldersInNewWindow&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;on&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;editor.acceptSuggestionOnEnter&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;off&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;editor.tabCompletion&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;emmet.triggerExpansionOnTab&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span></pre></td></tr></table></div>

<h3>Pour un Python heureux</h3>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;">    <span style="color: #3366CC;">&quot;python.venvPath&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;~/.local/share/virtualenvs/&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;python.linting.mypyEnabled&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;python.linting.enabled&quot;</span><span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;python.pythonPath&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;/usr/bin/python3.6&quot;</span><span style="color: #339933;">,</span> # je l<span style="color: #3366CC;">'override dans les settings de projet
    &quot;black.path&quot;: &quot;/home/user/.local/bin/black&quot;, # black a besoin de Python 3.6
    &quot;python.formatting.provider&quot;: &quot;none&quot;, # pour black
    &quot;editor.formatOnPaste&quot;: true,
    &quot;files.associations&quot;: {
        &quot;.pylintrc&quot;: &quot;ini&quot;
    },
    &quot;python.linting.flake8Enabled&quot;: true,
    &quot;python.unitTest.pyTestEnabled&quot;: true,
    &quot;python.linting.pylintEnabled&quot;: true,</span></pre></td></tr></table></div>

<h3>J&#8217;installe généralement ces extensions</h3>
<ul>
<li><strong>Python</strong>. Logique.</li>
<li><strong>Color highlight</strong> pour que les code hexa soient surlignés avec la couleur qu&#8217;ils représentent.</li>
<li><strong>Black</strong>, parce que je ne veux plus jamais reformater du code manuellement de ma vie.</li>
<li><strong>Django template</strong> et <strong>jinja</strong>, pour un meilleur support des templates django et jinja en coloration syntaxique.</li>
<li><strong>Editor config</strong> parce que j&#8217;ai toujours un .editorconfig à la racine de mes projets.</li>
<li><strong>gitignore</strong>, <strong>systemd-init-file</strong>, <strong>restructured text</strong> afin d&#8217;avoir la coloration syntaxique pour eux aussi</li>
<li><strong>path intellisense</strong>, comme ça j&#8217;ai la complétion sur les chemins de fichier.</li>
<li><strong>Rainbow CSV</strong>, qui affiche chaque colonne d&#8217;un CSV dans une couleur différente.</li>
<li><strong>git history</strong> pour afficher l&#8217;histoque d&#8217;un fichier ou d&#8217;une ligne.</li>
</ul>
<h3>Astuces utiles</h3>
<p>VSCode vient avec les raccourcis traditionnels des éditeurs graphiques: <kdb>ctrl</kdb> + <kdb>F</kdb> pour rechercher, <kdb>ctrl</kdb> + <kdb>shift</kdb> + <kdb>f</kdb> pour rechercher dans le projet, <kdb>ctrl</kdb> + <kdb>d</kdb> pour la sélection incrémentale, <kdb>ctrl</kdb> + <kdb>p</kdb> pour le &#8220;go to anywhere&#8221;, <kdb>ctrl</kdb> + <kdb>shift</kdb> + <kdb>p</kdb> pour le head up display, <kdb>ctrl</kdb> + <kdb>s</kdb> pour sauvegarder, <kdb>ctrl</kdb> (+<kdb>shift</kdb>) pour se balader (selectioner) de mot en mot, etc.</p>
<p>Il possède aussi quelques trucs sympas dont on parle moins dans les tutos:</p>
<ul>
<li>click milieu active la sélection verticale</li>
<li>Dans un shell, <code>code -r</code> ouvre un fichier dans la fenêtre en court, et <code>code -n</code> dans une nouvelle fenêtre. <code>code --diff foo bar</code> ouvre les deux fichiers en mode comparaison.</li>
<li>Dans un projet, le fichier <code>.vscode/tasks.json</code> contient la configuration des taches à lancer. Compilation, tests unitaires, debuggage, serveur&#8230; On peut lui faire faire n&#8217;importe quoi.</li>
<li>&#8220;Join line&#8221; n&#8217;a aucun shortcut par défaut. C&#8217;est une opération courante, donc je vous conseille de la mapper. Perso je la mets sur <kdb>ctrl</kdb> + <kdb>j</kdb>.</li>
<li><kdb>Ctrl</kdb>+<kdb>Shift</kdb>+ <kdb>O</kdb> permet de se déplacer vers n&#8217;importe quel symbole. C&#8217;est pratique, mais personne ne s&#8217;en souvient jamais. Plus facile à retenir: faire un &#8220;go to anywhere&#8221; (<kdb>ctrl</kdb> + <kdb>P</kdb>) et commencer la recherche par <code>@</code>. Ou <code>@:</code> pour regrouper les symboles par nature (classes, fonctions, etc). Le &#8220;go to symbole&#8221; marche sur tout le projet avec <kdb>Ctrl</kdb> + <kdb>T</kdb>, mais c&#8217;est lennnnnnnnnnnnt.</li>
<li>De la même manière, on peut aller à un numéro de ligne avec <code><kdb>Ctrl</kdb>+ <kdb>G</kdb></code>. Mais c&#8217;est plus facile de faire un &#8220;go to anywhere&#8221; puis de taper <code>:</code>. Ou depuis un terminal <code>code file.ext:numligne</code></li>
<li><code><kdb>Ctrl</kdb>+ <kdb>U</kdb></code>, aka &#8220;putain nooooooooooooooon, j&#8217;ai fais un <kdb>ctrl</kdb> + <kdb>d</kdb> de trop&#8221;.</li>
<li><kdb>Ctrl</kdb> + <kdb>k</kdb> + <kdb>ctrl</kdb> + <kdb>f</kdb> appliquer le formateur à la sélection. Pour les gens qui ont des TOC.</li>
<li>VSCode a une preview pour le markdown. Facile à lancer depuis le HUD</li>
<li>Une fois que vous avez pris l&#8217;habitude d&#8217;utiliser &#8220;go to definition&#8221; dans le menu contextuel, sachez que <kdb>ctrl</kdb> + <kdb>c</kdb>hlick fait pareil :)</li>
</ul>
<p>Un snippet perso que je rajoute également (dans <code>$HOME/.config/Code/User/snippets/python.json</code>):</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;">   <span style="color: #3366CC;">&quot;wrap_in_try_except&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #3366CC;">&quot;prefix&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;try&quot;</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;body&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span>
          <span style="color: #3366CC;">&quot;try:&quot;</span><span style="color: #339933;">,</span>
          <span style="color: #3366CC;">&quot;<span style="color: #000099; font-weight: bold;">\t</span>${0}${TM_SELECTED_TEXT}&quot;</span><span style="color: #339933;">,</span>
          <span style="color: #3366CC;">&quot;except ${1:Exception}:&quot;</span><span style="color: #339933;">,</span>
          <span style="color: #3366CC;">&quot;<span style="color: #000099; font-weight: bold;">\t</span>${2:import pdb; pdb.set_trace()}&quot;</span>
        <span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;description&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Wrap in try/except&quot;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span></pre></td></tr></table></div>

<p>Ça permet de sélectionner un truc, de taper <code>try</code> puis tab et avoir le tout wrappé dans un <code>try/except</code>.</p>
<h2>Le futur</h2>
<p>Depuis sa sortie, l&#8217;éditeur est en constante amélioration. Les mises à jour sont toujours une excellente surprise, avec des tas de goodies, y compris dans les extensions.</p>
<p>Mais là, dans la dernière <a href="https://code.visualstudio.com/insiders/">version instable</a> (qui a la bonne idée de ne pas overrider la stable à l&#8217;installation), VSCode vient avec <a href="https://code.visualstudio.com/blogs/2017/11/15/live-share">une preview</a> de l&#8217;édition collaborative. Genre Google doc, mais pour le code, et dans tout l&#8217;éditeur.</p>
<p>La partie chiante, c&#8217;est qu&#8217;il faut un compte (Microsoft évidemment), et donc que ça passe par leurs serveurs.</p>
<p>La partie amazing par contre, c&#8217;est que ça envoie du poney nucléaire. L&#8217;ouverture des onglets, l&#8217;écriture, le scroll&#8230; Tout se synchronise proprement. Si on décide de faire sa vie, VSCode désynchronise la navigation, et permet à tout le monde de travailler en parallèle sur le projet (et même optionnellement donner accès à son terminal). Si on veut de nouveau voir la navigation de l&#8217;autre, on peut demander de le suivre à nouveau, et pouf, on suit ce qu&#8217;il fait en live.</p>
<p>Testé avec des clients à des milliers de borne. C&#8217;est bluffant.</p>
<h2>Vous l&#8217;avez compris</h2>
<p><iframe frameborder="0" width="480" height="270" src="//www.dailymotion.com/embed/video/x2tjxy0?queue-enable=false" allowfullscreen allow="autoplay"></iframe></p>


